1 /*
2  *  Single source autogenerated distributable for Duktape 1.8.0.
3  *
4  *  Git commit 0a70d7e4c5227c84e3fed5209828973117d02849 (v1.8.0).
5  *  Git branch v1.8-maintenance.
6  *
7  *  See Duktape AUTHORS.rst and LICENSE.txt for copyright and
8  *  licensing information.
9  */
10 
11 /* LICENSE.txt */
12 /*
13 *  ===============
14 *  Duktape license
15 *  ===============
16 *
17 *  (http://opensource.org/licenses/MIT)
18 *
19 *  Copyright (c) 2013-2017 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 /* AUTHORS.rst */
40 /*
41 *  ===============
42 *  Duktape authors
43 *  ===============
44 *
45 *  Copyright
46 *  =========
47 *
48 *  Duktape copyrights are held by its authors.  Each author has a copyright
49 *  to their contribution, and agrees to irrevocably license the contribution
50 *  under the Duktape ``LICENSE.txt``.
51 *
52 *  Authors
53 *  =======
54 *
55 *  Please include an e-mail address, a link to your GitHub profile, or something
56 *  similar to allow your contribution to be identified accurately.
57 *
58 *  The following people have contributed code, website contents, or Wiki contents,
59 *  and agreed to irrevocably license their contributions under the Duktape
60 *  ``LICENSE.txt`` (in order of appearance):
61 *
62 *  * Sami Vaarala <sami.vaarala@iki.fi>
63 *  * Niki Dobrev
64 *  * Andreas \u00d6man <andreas@lonelycoder.com>
65 *  * L\u00e1szl\u00f3 Lang\u00f3 <llango.u-szeged@partner.samsung.com>
66 *  * Legimet <legimet.calc@gmail.com>
67 *  * Karl Skomski <karl@skomski.com>
68 *  * Bruce Pascoe <fatcerberus1@gmail.com>
69 *  * Ren\u00e9 Hollander <rene@rene8888.at>
70 *  * Julien Hamaide (https://github.com/crazyjul)
71 *  * Sebastian G\u00f6tte (https://github.com/jaseg)
72 *
73 *  Other contributions
74 *  ===================
75 *
76 *  The following people have contributed something other than code (e.g. reported
77 *  bugs, provided ideas, etc; roughly in order of appearance):
78 *
79 *  * Greg Burns
80 *  * Anthony Rabine
81 *  * Carlos Costa
82 *  * Aur\u00e9lien Bouilland
83 *  * Preet Desai (Pris Matic)
84 *  * judofyr (http://www.reddit.com/user/judofyr)
85 *  * Jason Woofenden
86 *  * Micha\u0142 Przyby\u015b
87 *  * Anthony Howe
88 *  * Conrad Pankoff
89 *  * Jim Schimpf
90 *  * Rajaran Gaunker (https://github.com/zimbabao)
91 *  * Andreas \u00d6man
92 *  * Doug Sanden
93 *  * Josh Engebretson (https://github.com/JoshEngebretson)
94 *  * Remo Eichenberger (https://github.com/remoe)
95 *  * Mamod Mehyar (https://github.com/mamod)
96 *  * David Demelier (https://github.com/markand)
97 *  * Tim Caswell (https://github.com/creationix)
98 *  * Mitchell Blank Jr (https://github.com/mitchblank)
99 *  * https://github.com/yushli
100 *  * Seo Sanghyeon (https://github.com/sanxiyn)
101 *  * Han ChoongWoo (https://github.com/tunz)
102 *  * Joshua Peek (https://github.com/josh)
103 *  * Bruce E. Pascoe (https://github.com/fatcerberus)
104 *  * https://github.com/Kelledin
105 *  * https://github.com/sstruchtrup
106 *  * Michael Drake (https://github.com/tlsa)
107 *  * https://github.com/chris-y
108 *  * Laurent Zubiaur (https://github.com/lzubiaur)
109 *  * Ole Andr\u00e9 Vadla Ravn\u00e5s (https://github.com/oleavr)
110 *
111 *  If you are accidentally missing from this list, send me an e-mail
112 *  (``sami.vaarala@iki.fi``) and I'll fix the omission.
113 */
114 /*
115  *  Top-level include file to be used for all (internal) source files.
116  *
117  *  Source files should not include individual header files, as they
118  *  have not been designed to be individually included.
119  */
120 
121 #ifndef DUK_INTERNAL_H_INCLUDED
122 #define DUK_INTERNAL_H_INCLUDED
123 
124 /*
125  *  The 'duktape.h' header provides the public API, but also handles all
126  *  compiler and platform specific feature detection, Duktape feature
127  *  resolution, inclusion of system headers, etc.  These have been merged
128  *  because the public API is also dependent on e.g. detecting appropriate
129  *  C types which is quite platform/compiler specific especially for a non-C99
130  *  build.  The public API is also dependent on the resolved feature set.
131  *
132  *  Some actions taken by the merged header (such as including system headers)
133  *  are not appropriate for building a user application.  The define
134  *  DUK_COMPILING_DUKTAPE allows the merged header to skip/include some
135  *  sections depending on what is being built.
136  */
137 
138 #define DUK_COMPILING_DUKTAPE
139 #include "duktape.h"
140 
141 /*
142  *  User declarations, e.g. prototypes for user functions used by Duktape
143  *  macros.  Concretely, if DUK_USE_PANIC_HANDLER is used and the macro
144  *  value calls a user function, it needs to be declared for Duktape
145  *  compilation to avoid warnings.
146  */
147 
148 DUK_USE_USER_DECLARE()
149 
150 /*
151  *  Duktape includes (other than duk_features.h)
152  *
153  *  The header files expect to be included in an order which satisfies header
154  *  dependencies correctly (the headers themselves don't include any other
155  *  includes).  Forward declarations are used to break circular struct/typedef
156  *  dependencies.
157  */
158 
159 #ifndef DUK_REPLACEMENTS_H_INCLUDED
160 #define DUK_REPLACEMENTS_H_INCLUDED
161 
162 #if !defined(DUK_SINGLE_FILE)
163 #if defined(DUK_USE_COMPUTED_INFINITY)
164 DUK_INTERNAL_DECL double duk_computed_infinity;
165 #endif
166 #if defined(DUK_USE_COMPUTED_NAN)
167 DUK_INTERNAL_DECL double duk_computed_nan;
168 #endif
169 #if defined(DUK_USE_REPL_FPCLASSIFY)
170 DUK_INTERNAL_DECL int duk_repl_fpclassify(double x);
171 #endif
172 #if defined(DUK_USE_REPL_SIGNBIT)
173 DUK_INTERNAL_DECL int duk_repl_signbit(double x);
174 #endif
175 #if defined(DUK_USE_REPL_ISFINITE)
176 DUK_INTERNAL_DECL int duk_repl_isfinite(double x);
177 #endif
178 #if defined(DUK_USE_REPL_ISNAN)
179 DUK_INTERNAL_DECL int duk_repl_isnan(double x);
180 #endif
181 #if defined(DUK_USE_REPL_ISINF)
182 DUK_INTERNAL_DECL int duk_repl_isinf(double x);
183 #endif
184 #endif  /* !DUK_SINGLE_FILE */
185 
186 #endif  /* DUK_REPLACEMENTS_H_INCLUDED */
187 /*
188  *  Wrapper for jmp_buf.
189  *
190  *  This is used because jmp_buf is an array type for backward compatibility.
191  *  Wrapping jmp_buf in a struct makes pointer references, sizeof, etc,
192  *  behave more intuitively.
193  *
194  *  http://en.wikipedia.org/wiki/Setjmp.h#Member_types
195  */
196 
197 #ifndef DUK_JMPBUF_H_INCLUDED
198 #define DUK_JMPBUF_H_INCLUDED
199 
200 #if defined(DUK_USE_CPP_EXCEPTIONS)
201 struct duk_jmpbuf {
202 	duk_small_int_t dummy;  /* unused */
203 };
204 #else
205 struct duk_jmpbuf {
206 	DUK_JMPBUF_TYPE jb;
207 };
208 #endif
209 
210 #endif  /* DUK_JMPBUF_H_INCLUDED */
211 /*
212  *  Exception for Duktape internal throws when C++ exceptions are used
213  *  for long control transfers.
214  *
215  *  Doesn't inherit from any exception base class to minimize the chance
216  *  that user code would accidentally catch this exception.
217  */
218 
219 #ifndef DUK_EXCEPTION_H_INCLUDED
220 #define DUK_EXCEPTION_H_INCLUDED
221 
222 #if defined(DUK_USE_CPP_EXCEPTIONS)
223 class duk_internal_exception {
224 	/* intentionally empty */
225 };
226 #endif
227 
228 #endif  /* DUK_EXCEPTION_H_INCLUDED */
229 /*
230  *  Forward declarations for all Duktape structures.
231  */
232 
233 #ifndef DUK_FORWDECL_H_INCLUDED
234 #define DUK_FORWDECL_H_INCLUDED
235 
236 /*
237  *  Forward declarations
238  */
239 
240 #if defined(DUK_USE_CPP_EXCEPTIONS)
241 class duk_internal_exception;
242 #else
243 struct duk_jmpbuf;
244 #endif
245 
246 /* duk_tval intentionally skipped */
247 struct duk_heaphdr;
248 struct duk_heaphdr_string;
249 struct duk_hstring;
250 struct duk_hstring_external;
251 struct duk_hobject;
252 struct duk_hcompiledfunction;
253 struct duk_hnativefunction;
254 struct duk_hthread;
255 struct duk_hbufferobject;
256 struct duk_hbuffer;
257 struct duk_hbuffer_fixed;
258 struct duk_hbuffer_dynamic;
259 struct duk_hbuffer_external;
260 
261 struct duk_propaccessor;
262 union duk_propvalue;
263 struct duk_propdesc;
264 
265 struct duk_heap;
266 struct duk_breakpoint;
267 
268 struct duk_activation;
269 struct duk_catcher;
270 struct duk_strcache;
271 struct duk_ljstate;
272 struct duk_strtab_entry;
273 
274 #ifdef DUK_USE_DEBUG
275 struct duk_fixedbuffer;
276 #endif
277 
278 struct duk_bitdecoder_ctx;
279 struct duk_bitencoder_ctx;
280 struct duk_bufwriter_ctx;
281 
282 struct duk_token;
283 struct duk_re_token;
284 struct duk_lexer_point;
285 struct duk_lexer_ctx;
286 struct duk_lexer_codepoint;
287 
288 struct duk_compiler_instr;
289 struct duk_compiler_func;
290 struct duk_compiler_ctx;
291 
292 struct duk_re_matcher_ctx;
293 struct duk_re_compiler_ctx;
294 
295 #if defined(DUK_USE_CPP_EXCEPTIONS)
296 /* no typedef */
297 #else
298 typedef struct duk_jmpbuf duk_jmpbuf;
299 #endif
300 
301 /* duk_tval intentionally skipped */
302 typedef struct duk_heaphdr duk_heaphdr;
303 typedef struct duk_heaphdr_string duk_heaphdr_string;
304 typedef struct duk_hstring duk_hstring;
305 typedef struct duk_hstring_external duk_hstring_external;
306 typedef struct duk_hobject duk_hobject;
307 typedef struct duk_hcompiledfunction duk_hcompiledfunction;
308 typedef struct duk_hnativefunction duk_hnativefunction;
309 typedef struct duk_hbufferobject duk_hbufferobject;
310 typedef struct duk_hthread duk_hthread;
311 typedef struct duk_hbuffer duk_hbuffer;
312 typedef struct duk_hbuffer_fixed duk_hbuffer_fixed;
313 typedef struct duk_hbuffer_dynamic duk_hbuffer_dynamic;
314 typedef struct duk_hbuffer_external duk_hbuffer_external;
315 
316 typedef struct duk_propaccessor duk_propaccessor;
317 typedef union duk_propvalue duk_propvalue;
318 typedef struct duk_propdesc duk_propdesc;
319 
320 typedef struct duk_heap duk_heap;
321 typedef struct duk_breakpoint duk_breakpoint;
322 
323 typedef struct duk_activation duk_activation;
324 typedef struct duk_catcher duk_catcher;
325 typedef struct duk_strcache duk_strcache;
326 typedef struct duk_ljstate duk_ljstate;
327 typedef struct duk_strtab_entry duk_strtab_entry;
328 
329 #ifdef DUK_USE_DEBUG
330 typedef struct duk_fixedbuffer duk_fixedbuffer;
331 #endif
332 
333 typedef struct duk_bitdecoder_ctx duk_bitdecoder_ctx;
334 typedef struct duk_bitencoder_ctx duk_bitencoder_ctx;
335 typedef struct duk_bufwriter_ctx duk_bufwriter_ctx;
336 
337 typedef struct duk_token duk_token;
338 typedef struct duk_re_token duk_re_token;
339 typedef struct duk_lexer_point duk_lexer_point;
340 typedef struct duk_lexer_ctx duk_lexer_ctx;
341 typedef struct duk_lexer_codepoint duk_lexer_codepoint;
342 
343 typedef struct duk_compiler_instr duk_compiler_instr;
344 typedef struct duk_compiler_func duk_compiler_func;
345 typedef struct duk_compiler_ctx duk_compiler_ctx;
346 
347 typedef struct duk_re_matcher_ctx duk_re_matcher_ctx;
348 typedef struct duk_re_compiler_ctx duk_re_compiler_ctx;
349 
350 #endif  /* DUK_FORWDECL_H_INCLUDED */
351 /*
352  *  Tagged type definition (duk_tval) and accessor macros.
353  *
354  *  Access all fields through the accessor macros, as the representation
355  *  is quite tricky.
356  *
357  *  There are two packed type alternatives: an 8-byte representation
358  *  based on an IEEE double (preferred for compactness), and a 12-byte
359  *  representation (portability).  The latter is needed also in e.g.
360  *  64-bit environments (it usually pads to 16 bytes per value).
361  *
362  *  Selecting the tagged type format involves many trade-offs (memory
363  *  use, size and performance of generated code, portability, etc),
364  *  see doc/types.rst for a detailed discussion (especially of how the
365  *  IEEE double format is used to pack tagged values).
366  *
367  *  NB: because macro arguments are often expressions, macros should
368  *  avoid evaluating their argument more than once.
369  */
370 
371 #ifndef DUK_TVAL_H_INCLUDED
372 #define DUK_TVAL_H_INCLUDED
373 
374 /* sanity */
375 #if !defined(DUK_USE_DOUBLE_LE) && !defined(DUK_USE_DOUBLE_ME) && !defined(DUK_USE_DOUBLE_BE)
376 #error unsupported: cannot determine byte order variant
377 #endif
378 
379 #if defined(DUK_USE_PACKED_TVAL)
380 /* ======================================================================== */
381 
382 /*
383  *  Packed 8-byte representation
384  */
385 
386 /* use duk_double_union as duk_tval directly */
387 typedef union duk_double_union duk_tval;
388 
389 /* tags */
390 #define DUK_TAG_NORMALIZED_NAN    0x7ff8UL   /* the NaN variant we use */
391 /* avoid tag 0xfff0, no risk of confusion with negative infinity */
392 #if defined(DUK_USE_FASTINT)
393 #define DUK_TAG_FASTINT           0xfff1UL   /* embed: integer value */
394 #endif
395 #define DUK_TAG_UNUSED            0xfff2UL   /* marker; not actual tagged value */
396 #define DUK_TAG_UNDEFINED         0xfff3UL   /* embed: nothing */
397 #define DUK_TAG_NULL              0xfff4UL   /* embed: nothing */
398 #define DUK_TAG_BOOLEAN           0xfff5UL   /* embed: 0 or 1 (false or true) */
399 /* DUK_TAG_NUMBER would logically go here, but it has multiple 'tags' */
400 #define DUK_TAG_POINTER           0xfff6UL   /* embed: void ptr */
401 #define DUK_TAG_LIGHTFUNC         0xfff7UL   /* embed: func ptr */
402 #define DUK_TAG_STRING            0xfff8UL   /* embed: duk_hstring ptr */
403 #define DUK_TAG_OBJECT            0xfff9UL   /* embed: duk_hobject ptr */
404 #define DUK_TAG_BUFFER            0xfffaUL   /* embed: duk_hbuffer ptr */
405 
406 /* for convenience */
407 #define DUK_XTAG_BOOLEAN_FALSE    0xfff50000UL
408 #define DUK_XTAG_BOOLEAN_TRUE     0xfff50001UL
409 
410 /* two casts to avoid gcc warning: "warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]" */
411 #if defined(DUK_USE_64BIT_OPS)
412 #if defined(DUK_USE_DOUBLE_ME)
413 #define DUK__TVAL_SET_TAGGEDPOINTER(v,h,tag)  do { \
414 		(v)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) (tag)) << 16) | (((duk_uint64_t) (duk_uint32_t) (h)) << 32); \
415 	} while (0)
416 #else
417 #define DUK__TVAL_SET_TAGGEDPOINTER(v,h,tag)  do { \
418 		(v)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) (tag)) << 48) | ((duk_uint64_t) (duk_uint32_t) (h)); \
419 	} while (0)
420 #endif
421 #else  /* DUK_USE_64BIT_OPS */
422 #define DUK__TVAL_SET_TAGGEDPOINTER(v,h,tag)  do { \
423 		(v)->ui[DUK_DBL_IDX_UI0] = ((duk_uint32_t) (tag)) << 16; \
424 		(v)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (h); \
425 	} while (0)
426 #endif  /* DUK_USE_64BIT_OPS */
427 
428 #if defined(DUK_USE_64BIT_OPS)
429 /* Double casting for pointer to avoid gcc warning (cast from pointer to integer of different size) */
430 #if defined(DUK_USE_DOUBLE_ME)
431 #define DUK__TVAL_SET_LIGHTFUNC(v,fp,flags)  do { \
432 		(v)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_LIGHTFUNC) << 16) | \
433 		                             ((duk_uint64_t) (flags)) | \
434 		                             (((duk_uint64_t) (duk_uint32_t) (fp)) << 32); \
435 	} while (0)
436 #else
437 #define DUK__TVAL_SET_LIGHTFUNC(v,fp,flags)  do { \
438 		(v)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_LIGHTFUNC) << 48) | \
439 		                             (((duk_uint64_t) (flags)) << 32) | \
440 		                             ((duk_uint64_t) (duk_uint32_t) (fp)); \
441 	} while (0)
442 #endif
443 #else  /* DUK_USE_64BIT_OPS */
444 #define DUK__TVAL_SET_LIGHTFUNC(v,fp,flags)  do { \
445 		(v)->ui[DUK_DBL_IDX_UI0] = (((duk_uint32_t) DUK_TAG_LIGHTFUNC) << 16) | ((duk_uint32_t) (flags)); \
446 		(v)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (fp); \
447 	} while (0)
448 #endif  /* DUK_USE_64BIT_OPS */
449 
450 #if defined(DUK_USE_FASTINT)
451 /* Note: masking is done for 'i' to deal with negative numbers correctly */
452 #if defined(DUK_USE_DOUBLE_ME)
453 #define DUK__TVAL_SET_FASTINT(v,i)  do { \
454 		(v)->ui[DUK_DBL_IDX_UI0] = ((duk_uint32_t) DUK_TAG_FASTINT) << 16 | (((duk_uint32_t) ((i) >> 32)) & 0x0000ffffUL); \
455 		(v)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (i); \
456 	} while (0)
457 #define DUK__TVAL_SET_FASTINT_U32(v,i)  do { \
458 		(v)->ui[DUK_DBL_IDX_UI0] = ((duk_uint32_t) DUK_TAG_FASTINT) << 16; \
459 		(v)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (i); \
460 	} while (0)
461 #else
462 #define DUK__TVAL_SET_FASTINT(v,i)  do { \
463 		(v)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_FASTINT) << 48) | (((duk_uint64_t) (i)) & 0x0000ffffffffffffULL); \
464 	} while (0)
465 #define DUK__TVAL_SET_FASTINT_U32(v,i)  do { \
466 		(v)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_FASTINT) << 48) | (duk_uint64_t) (i); \
467 	} while (0)
468 #endif
469 
470 #define DUK__TVAL_SET_FASTINT_I32(v,i)  do { \
471 		duk_int64_t duk__tmp = (duk_int64_t) (i); \
472 		DUK_TVAL_SET_FASTINT((v), duk__tmp); \
473 	} while (0)
474 
475 /* XXX: clumsy sign extend and masking of 16 topmost bits */
476 #if defined(DUK_USE_DOUBLE_ME)
477 #define DUK__TVAL_GET_FASTINT(v)      (((duk_int64_t) ((((duk_uint64_t) (v)->ui[DUK_DBL_IDX_UI0]) << 32) | ((duk_uint64_t) (v)->ui[DUK_DBL_IDX_UI1]))) << 16 >> 16)
478 #else
479 #define DUK__TVAL_GET_FASTINT(v)      ((((duk_int64_t) (v)->ull[DUK_DBL_IDX_ULL0]) << 16) >> 16)
480 #endif
481 #define DUK__TVAL_GET_FASTINT_U32(v)  ((v)->ui[DUK_DBL_IDX_UI1])
482 #define DUK__TVAL_GET_FASTINT_I32(v)  ((duk_int32_t) (v)->ui[DUK_DBL_IDX_UI1])
483 #endif  /* DUK_USE_FASTINT */
484 
485 #define DUK_TVAL_SET_UNDEFINED(v)  do { \
486 		(v)->us[DUK_DBL_IDX_US0] = (duk_uint16_t) DUK_TAG_UNDEFINED; \
487 	} while (0)
488 #define DUK_TVAL_SET_UNUSED(v)  do { \
489 		(v)->us[DUK_DBL_IDX_US0] = (duk_uint16_t) DUK_TAG_UNUSED; \
490 	} while (0)
491 #define DUK_TVAL_SET_NULL(v)  do { \
492 		(v)->us[DUK_DBL_IDX_US0] = (duk_uint16_t) DUK_TAG_NULL; \
493 	} while (0)
494 
495 #define DUK_TVAL_SET_BOOLEAN(v,val)         DUK_DBLUNION_SET_HIGH32((v), (((duk_uint32_t) DUK_TAG_BOOLEAN) << 16) | ((duk_uint32_t) (val)))
496 
497 #define DUK_TVAL_SET_NAN(v)                 DUK_DBLUNION_SET_NAN_FULL((v))
498 
499 /* Assumes that caller has normalized NaNs, otherwise trouble ahead. */
500 #if defined(DUK_USE_FASTINT)
501 #define DUK_TVAL_SET_DOUBLE(v,d)  do { \
502 		duk_double_t duk__dblval; \
503 		duk__dblval = (d); \
504 		DUK_ASSERT_DOUBLE_IS_NORMALIZED(duk__dblval); \
505 		DUK_DBLUNION_SET_DOUBLE((v), duk__dblval); \
506 	} while (0)
507 #define DUK_TVAL_SET_FASTINT(v,i)           DUK__TVAL_SET_FASTINT((v), (i))
508 #define DUK_TVAL_SET_FASTINT_I32(v,i)       DUK__TVAL_SET_FASTINT_I32((v), (i))
509 #define DUK_TVAL_SET_FASTINT_U32(v,i)       DUK__TVAL_SET_FASTINT_U32((v), (i))
510 #define DUK_TVAL_SET_NUMBER_CHKFAST(v,d)    duk_tval_set_number_chkfast((v), (d))
511 #define DUK_TVAL_SET_NUMBER(v,d)            DUK_TVAL_SET_DOUBLE((v), (d))
512 #define DUK_TVAL_CHKFAST_INPLACE(v)  do { \
513 		duk_tval *duk__tv; \
514 		duk_double_t duk__d; \
515 		duk__tv = (v); \
516 		if (DUK_TVAL_IS_DOUBLE(duk__tv)) { \
517 			duk__d = DUK_TVAL_GET_DOUBLE(duk__tv); \
518 			DUK_TVAL_SET_NUMBER_CHKFAST(duk__tv, duk__d); \
519 		} \
520 	} while (0)
521 #else
522 #define DUK_TVAL_SET_DOUBLE(v,d)  do { \
523 		duk_double_t duk__dblval; \
524 		duk__dblval = (d); \
525 		DUK_ASSERT_DOUBLE_IS_NORMALIZED(duk__dblval); \
526 		DUK_DBLUNION_SET_DOUBLE((v), duk__dblval); \
527 	} while (0)
528 #define DUK_TVAL_SET_FASTINT(v,i)           DUK_TVAL_SET_DOUBLE((v), (duk_double_t) (i))  /* XXX: fast int-to-double */
529 #define DUK_TVAL_SET_FASTINT_I32(v,i)       DUK_TVAL_SET_DOUBLE((v), (duk_double_t) (i))
530 #define DUK_TVAL_SET_FASTINT_U32(v,i)       DUK_TVAL_SET_DOUBLE((v), (duk_double_t) (i))
531 #define DUK_TVAL_SET_NUMBER_CHKFAST(v,d)    DUK_TVAL_SET_DOUBLE((v), (d))
532 #define DUK_TVAL_SET_NUMBER(v,d)            DUK_TVAL_SET_DOUBLE((v), (d))
533 #define DUK_TVAL_CHKFAST_INPLACE(v)  do { } while (0)
534 #endif
535 
536 #define DUK_TVAL_SET_LIGHTFUNC(v,fp,flags)  DUK__TVAL_SET_LIGHTFUNC((v), (fp), (flags))
537 #define DUK_TVAL_SET_STRING(v,h)            DUK__TVAL_SET_TAGGEDPOINTER((v), (h), DUK_TAG_STRING)
538 #define DUK_TVAL_SET_OBJECT(v,h)            DUK__TVAL_SET_TAGGEDPOINTER((v), (h), DUK_TAG_OBJECT)
539 #define DUK_TVAL_SET_BUFFER(v,h)            DUK__TVAL_SET_TAGGEDPOINTER((v), (h), DUK_TAG_BUFFER)
540 #define DUK_TVAL_SET_POINTER(v,p)           DUK__TVAL_SET_TAGGEDPOINTER((v), (p), DUK_TAG_POINTER)
541 
542 #define DUK_TVAL_SET_TVAL(v,x)              do { *(v) = *(x); } while (0)
543 
544 /* getters */
545 #define DUK_TVAL_GET_BOOLEAN(v)             ((int) (v)->us[DUK_DBL_IDX_US1])
546 #if defined(DUK_USE_FASTINT)
547 #define DUK_TVAL_GET_DOUBLE(v)              ((v)->d)
548 #define DUK_TVAL_GET_FASTINT(v)             DUK__TVAL_GET_FASTINT((v))
549 #define DUK_TVAL_GET_FASTINT_U32(v)         DUK__TVAL_GET_FASTINT_U32((v))
550 #define DUK_TVAL_GET_FASTINT_I32(v)         DUK__TVAL_GET_FASTINT_I32((v))
551 #define DUK_TVAL_GET_NUMBER(v)              duk_tval_get_number_packed((v))
552 #else
553 #define DUK_TVAL_GET_NUMBER(v)              ((v)->d)
554 #define DUK_TVAL_GET_DOUBLE(v)              ((v)->d)
555 #endif
556 #define DUK_TVAL_GET_LIGHTFUNC(v,out_fp,out_flags)  do { \
557 		(out_flags) = (v)->ui[DUK_DBL_IDX_UI0] & 0xffffUL; \
558 		(out_fp) = (duk_c_function) (v)->ui[DUK_DBL_IDX_UI1]; \
559 	} while (0)
560 #define DUK_TVAL_GET_LIGHTFUNC_FUNCPTR(v)   ((duk_c_function) ((v)->ui[DUK_DBL_IDX_UI1]))
561 #define DUK_TVAL_GET_LIGHTFUNC_FLAGS(v)     (((int) (v)->ui[DUK_DBL_IDX_UI0]) & 0xffffUL)
562 #define DUK_TVAL_GET_STRING(v)              ((duk_hstring *) (v)->vp[DUK_DBL_IDX_VP1])
563 #define DUK_TVAL_GET_OBJECT(v)              ((duk_hobject *) (v)->vp[DUK_DBL_IDX_VP1])
564 #define DUK_TVAL_GET_BUFFER(v)              ((duk_hbuffer *) (v)->vp[DUK_DBL_IDX_VP1])
565 #define DUK_TVAL_GET_POINTER(v)             ((void *) (v)->vp[DUK_DBL_IDX_VP1])
566 #define DUK_TVAL_GET_HEAPHDR(v)             ((duk_heaphdr *) (v)->vp[DUK_DBL_IDX_VP1])
567 
568 /* decoding */
569 #define DUK_TVAL_GET_TAG(v)                 ((duk_small_uint_t) (v)->us[DUK_DBL_IDX_US0])
570 
571 #define DUK_TVAL_IS_UNDEFINED(v)            (DUK_TVAL_GET_TAG((v)) == DUK_TAG_UNDEFINED)
572 #define DUK_TVAL_IS_UNUSED(v)               (DUK_TVAL_GET_TAG((v)) == DUK_TAG_UNUSED)
573 #define DUK_TVAL_IS_NULL(v)                 (DUK_TVAL_GET_TAG((v)) == DUK_TAG_NULL)
574 #define DUK_TVAL_IS_BOOLEAN(v)              (DUK_TVAL_GET_TAG((v)) == DUK_TAG_BOOLEAN)
575 #define DUK_TVAL_IS_BOOLEAN_TRUE(v)         ((v)->ui[DUK_DBL_IDX_UI0] == DUK_XTAG_BOOLEAN_TRUE)
576 #define DUK_TVAL_IS_BOOLEAN_FALSE(v)        ((v)->ui[DUK_DBL_IDX_UI0] == DUK_XTAG_BOOLEAN_FALSE)
577 #define DUK_TVAL_IS_LIGHTFUNC(v)            (DUK_TVAL_GET_TAG((v)) == DUK_TAG_LIGHTFUNC)
578 #define DUK_TVAL_IS_STRING(v)               (DUK_TVAL_GET_TAG((v)) == DUK_TAG_STRING)
579 #define DUK_TVAL_IS_OBJECT(v)               (DUK_TVAL_GET_TAG((v)) == DUK_TAG_OBJECT)
580 #define DUK_TVAL_IS_BUFFER(v)               (DUK_TVAL_GET_TAG((v)) == DUK_TAG_BUFFER)
581 #define DUK_TVAL_IS_POINTER(v)              (DUK_TVAL_GET_TAG((v)) == DUK_TAG_POINTER)
582 #if defined(DUK_USE_FASTINT)
583 /* 0xfff0 is -Infinity */
584 #define DUK_TVAL_IS_DOUBLE(v)               (DUK_TVAL_GET_TAG((v)) <= 0xfff0UL)
585 #define DUK_TVAL_IS_FASTINT(v)              (DUK_TVAL_GET_TAG((v)) == DUK_TAG_FASTINT)
586 #define DUK_TVAL_IS_NUMBER(v)               (DUK_TVAL_GET_TAG((v)) <= 0xfff1UL)
587 #else
588 #define DUK_TVAL_IS_NUMBER(v)               (DUK_TVAL_GET_TAG((v)) <= 0xfff0UL)
589 #define DUK_TVAL_IS_DOUBLE(v)               DUK_TVAL_IS_NUMBER((v))
590 #endif
591 
592 /* This is performance critical because it appears in every DECREF. */
593 #define DUK_TVAL_IS_HEAP_ALLOCATED(v)       (DUK_TVAL_GET_TAG((v)) >= DUK_TAG_STRING)
594 
595 #if defined(DUK_USE_FASTINT)
596 DUK_INTERNAL_DECL duk_double_t duk_tval_get_number_packed(duk_tval *tv);
597 #endif
598 
599 #else  /* DUK_USE_PACKED_TVAL */
600 /* ======================================================================== */
601 
602 /*
603  *  Portable 12-byte representation
604  */
605 
606 /* Note: not initializing all bytes is normally not an issue: Duktape won't
607  * read or use the uninitialized bytes so valgrind won't issue warnings.
608  * In some special cases a harmless valgrind warning may be issued though.
609  * For example, the DumpHeap debugger command writes out a compiled function's
610  * 'data' area as is, including any uninitialized bytes, which causes a
611  * valgrind warning.
612  */
613 
614 typedef struct duk_tval_struct duk_tval;
615 
616 struct duk_tval_struct {
617 	duk_small_uint_t t;
618 	duk_small_uint_t v_extra;
619 	union {
620 		duk_double_t d;
621 		duk_small_int_t i;
622 #if defined(DUK_USE_FASTINT)
623 		duk_int64_t fi;  /* if present, forces 16-byte duk_tval */
624 #endif
625 		void *voidptr;
626 		duk_hstring *hstring;
627 		duk_hobject *hobject;
628 		duk_hcompiledfunction *hcompiledfunction;
629 		duk_hnativefunction *hnativefunction;
630 		duk_hthread *hthread;
631 		duk_hbuffer *hbuffer;
632 		duk_heaphdr *heaphdr;
633 		duk_c_function lightfunc;
634 	} v;
635 };
636 
637 #define DUK__TAG_NUMBER               0  /* not exposed */
638 #if defined(DUK_USE_FASTINT)
639 #define DUK_TAG_FASTINT               1
640 #endif
641 #define DUK_TAG_UNDEFINED             2
642 #define DUK_TAG_NULL                  3
643 #define DUK_TAG_BOOLEAN               4
644 #define DUK_TAG_POINTER               5
645 #define DUK_TAG_LIGHTFUNC             6
646 #define DUK_TAG_UNUSED                7  /* marker; not actual tagged type */
647 #define DUK_TAG_STRING                8  /* first heap allocated, match bit boundary */
648 #define DUK_TAG_OBJECT                9
649 #define DUK_TAG_BUFFER                10
650 
651 /* DUK__TAG_NUMBER is intentionally first, as it is the default clause in code
652  * to support the 8-byte representation.  Further, it is a non-heap-allocated
653  * type so it should come before DUK_TAG_STRING.  Finally, it should not break
654  * the tag value ranges covered by case-clauses in a switch-case.
655  */
656 
657 /* setters */
658 #define DUK_TVAL_SET_UNDEFINED(tv)  do { \
659 		(tv)->t = DUK_TAG_UNDEFINED; \
660 	} while (0)
661 
662 #define DUK_TVAL_SET_UNUSED(tv)  do { \
663 		(tv)->t = DUK_TAG_UNUSED; \
664 	} while (0)
665 
666 #define DUK_TVAL_SET_NULL(tv)  do { \
667 		(tv)->t = DUK_TAG_NULL; \
668 	} while (0)
669 
670 #define DUK_TVAL_SET_BOOLEAN(tv,val)  do { \
671 		(tv)->t = DUK_TAG_BOOLEAN; \
672 		(tv)->v.i = (val); \
673 	} while (0)
674 
675 #if defined(DUK_USE_FASTINT)
676 #define DUK_TVAL_SET_DOUBLE(tv,val)  do { \
677 		(tv)->t = DUK__TAG_NUMBER; \
678 		(tv)->v.d = (val); \
679 	} while (0)
680 #define DUK_TVAL_SET_FASTINT(tv,val)  do { \
681 		(tv)->t = DUK_TAG_FASTINT; \
682 		(tv)->v.fi = (val); \
683 	} while (0)
684 #define DUK_TVAL_SET_FASTINT_U32(tv,val)  do { \
685 		(tv)->t = DUK_TAG_FASTINT; \
686 		(tv)->v.fi = (duk_int64_t) (val); \
687 	} while (0)
688 #define DUK_TVAL_SET_FASTINT_I32(tv,val)  do { \
689 		(tv)->t = DUK_TAG_FASTINT; \
690 		(tv)->v.fi = (duk_int64_t) (val); \
691 	} while (0)
692 #define DUK_TVAL_SET_NUMBER_CHKFAST(tv,d) \
693 	duk_tval_set_number_chkfast((tv), (d))
694 #define DUK_TVAL_SET_NUMBER(tv,val) \
695 	DUK_TVAL_SET_DOUBLE((tv), (val))
696 #define DUK_TVAL_CHKFAST_INPLACE(v)  do { \
697 		duk_tval *duk__tv; \
698 		duk_double_t duk__d; \
699 		duk__tv = (v); \
700 		if (DUK_TVAL_IS_DOUBLE(duk__tv)) { \
701 			duk__d = DUK_TVAL_GET_DOUBLE(duk__tv); \
702 			DUK_TVAL_SET_NUMBER_CHKFAST(duk__tv, duk__d); \
703 		} \
704 	} while (0)
705 #else
706 #define DUK_TVAL_SET_DOUBLE(tv,d) \
707 	DUK_TVAL_SET_NUMBER((tv), (d))
708 #define DUK_TVAL_SET_FASTINT(tv,val) \
709 	DUK_TVAL_SET_NUMBER((tv), (duk_double_t) (val))  /* XXX: fast int-to-double */
710 #define DUK_TVAL_SET_FASTINT_U32(tv,val) \
711 	DUK_TVAL_SET_NUMBER((tv), (duk_double_t) (val))
712 #define DUK_TVAL_SET_FASTINT_I32(tv,val) \
713 	DUK_TVAL_SET_NUMBER((tv), (duk_double_t) (val))
714 #define DUK_TVAL_SET_NUMBER(tv,val)  do { \
715 		(tv)->t = DUK__TAG_NUMBER; \
716 		(tv)->v.d = (val); \
717 	} while (0)
718 #define DUK_TVAL_SET_NUMBER_CHKFAST(tv,d) \
719 	DUK_TVAL_SET_NUMBER((tv), (d))
720 #define DUK_TVAL_CHKFAST_INPLACE(v)  do { } while (0)
721 #endif  /* DUK_USE_FASTINT */
722 
723 #define DUK_TVAL_SET_POINTER(tv,hptr)  do { \
724 		(tv)->t = DUK_TAG_POINTER; \
725 		(tv)->v.voidptr = (hptr); \
726 	} while (0)
727 
728 #define DUK_TVAL_SET_LIGHTFUNC(tv,fp,flags)  do { \
729 		(tv)->t = DUK_TAG_LIGHTFUNC; \
730 		(tv)->v_extra = (flags); \
731 		(tv)->v.lightfunc = (duk_c_function) (fp); \
732 	} while (0)
733 
734 #define DUK_TVAL_SET_STRING(tv,hptr)  do { \
735 		(tv)->t = DUK_TAG_STRING; \
736 		(tv)->v.hstring = (hptr); \
737 	} while (0)
738 
739 #define DUK_TVAL_SET_OBJECT(tv,hptr)  do { \
740 		(tv)->t = DUK_TAG_OBJECT; \
741 		(tv)->v.hobject = (hptr); \
742 	} while (0)
743 
744 #define DUK_TVAL_SET_BUFFER(tv,hptr)  do { \
745 		(tv)->t = DUK_TAG_BUFFER; \
746 		(tv)->v.hbuffer = (hptr); \
747 	} while (0)
748 
749 #define DUK_TVAL_SET_NAN(tv)  do { \
750 		/* in non-packed representation we don't care about which NaN is used */ \
751 		(tv)->t = DUK__TAG_NUMBER; \
752 		(tv)->v.d = DUK_DOUBLE_NAN; \
753 	} while (0)
754 
755 #define DUK_TVAL_SET_TVAL(v,x)             do { *(v) = *(x); } while (0)
756 
757 /* getters */
758 #define DUK_TVAL_GET_BOOLEAN(tv)           ((tv)->v.i)
759 #if defined(DUK_USE_FASTINT)
760 #define DUK_TVAL_GET_DOUBLE(tv)            ((tv)->v.d)
761 #define DUK_TVAL_GET_FASTINT(tv)           ((tv)->v.fi)
762 #define DUK_TVAL_GET_FASTINT_U32(tv)       ((duk_uint32_t) ((tv)->v.fi))
763 #define DUK_TVAL_GET_FASTINT_I32(tv)       ((duk_int32_t) ((tv)->v.fi))
764 #if 0
765 #define DUK_TVAL_GET_NUMBER(tv)            (DUK_TVAL_IS_FASTINT((tv)) ? \
766                                                (duk_double_t) DUK_TVAL_GET_FASTINT((tv)) : \
767                                                DUK_TVAL_GET_DOUBLE((tv)))
768 #define DUK_TVAL_GET_NUMBER(tv)            duk_tval_get_number_unpacked((tv))
769 #else
770 /* This seems reasonable overall. */
771 #define DUK_TVAL_GET_NUMBER(tv)            (DUK_TVAL_IS_FASTINT((tv)) ? \
772                                                duk_tval_get_number_unpacked_fastint((tv)) : \
773                                                DUK_TVAL_GET_DOUBLE((tv)))
774 #endif
775 #else
776 #define DUK_TVAL_GET_NUMBER(tv)            ((tv)->v.d)
777 #define DUK_TVAL_GET_DOUBLE(tv)            ((tv)->v.d)
778 #endif  /* DUK_USE_FASTINT */
779 #define DUK_TVAL_GET_POINTER(tv)           ((tv)->v.voidptr)
780 #define DUK_TVAL_GET_LIGHTFUNC(tv,out_fp,out_flags)  do { \
781 		(out_flags) = (duk_uint32_t) (tv)->v_extra; \
782 		(out_fp) = (tv)->v.lightfunc; \
783 	} while (0)
784 #define DUK_TVAL_GET_LIGHTFUNC_FUNCPTR(tv) ((tv)->v.lightfunc)
785 #define DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv)   ((duk_uint32_t) ((tv)->v_extra))
786 #define DUK_TVAL_GET_STRING(tv)            ((tv)->v.hstring)
787 #define DUK_TVAL_GET_OBJECT(tv)            ((tv)->v.hobject)
788 #define DUK_TVAL_GET_BUFFER(tv)            ((tv)->v.hbuffer)
789 #define DUK_TVAL_GET_HEAPHDR(tv)           ((tv)->v.heaphdr)
790 
791 /* decoding */
792 #define DUK_TVAL_GET_TAG(tv)               ((tv)->t)
793 #define DUK_TVAL_IS_UNDEFINED(tv)          ((tv)->t == DUK_TAG_UNDEFINED)
794 #define DUK_TVAL_IS_UNUSED(tv)             ((tv)->t == DUK_TAG_UNUSED)
795 #define DUK_TVAL_IS_NULL(tv)               ((tv)->t == DUK_TAG_NULL)
796 #define DUK_TVAL_IS_BOOLEAN(tv)            ((tv)->t == DUK_TAG_BOOLEAN)
797 #define DUK_TVAL_IS_BOOLEAN_TRUE(tv)       (((tv)->t == DUK_TAG_BOOLEAN) && ((tv)->v.i != 0))
798 #define DUK_TVAL_IS_BOOLEAN_FALSE(tv)      (((tv)->t == DUK_TAG_BOOLEAN) && ((tv)->v.i == 0))
799 #if defined(DUK_USE_FASTINT)
800 #define DUK_TVAL_IS_DOUBLE(tv)             ((tv)->t == DUK__TAG_NUMBER)
801 #define DUK_TVAL_IS_FASTINT(tv)            ((tv)->t == DUK_TAG_FASTINT)
802 #define DUK_TVAL_IS_NUMBER(tv)             ((tv)->t == DUK__TAG_NUMBER || \
803                                             (tv)->t == DUK_TAG_FASTINT)
804 #else
805 #define DUK_TVAL_IS_NUMBER(tv)             ((tv)->t == DUK__TAG_NUMBER)
806 #define DUK_TVAL_IS_DOUBLE(v)              DUK_TVAL_IS_NUMBER((v))
807 #endif  /* DUK_USE_FASTINT */
808 #define DUK_TVAL_IS_POINTER(tv)            ((tv)->t == DUK_TAG_POINTER)
809 #define DUK_TVAL_IS_LIGHTFUNC(tv)          ((tv)->t == DUK_TAG_LIGHTFUNC)
810 #define DUK_TVAL_IS_STRING(tv)             ((tv)->t == DUK_TAG_STRING)
811 #define DUK_TVAL_IS_OBJECT(tv)             ((tv)->t == DUK_TAG_OBJECT)
812 #define DUK_TVAL_IS_BUFFER(tv)             ((tv)->t == DUK_TAG_BUFFER)
813 
814 /* This is performance critical because it's needed for every DECREF.
815  * Take advantage of the fact that the first heap allocated tag is 8,
816  * so that bit 3 is set for all heap allocated tags (and never set for
817  * non-heap-allocated tags).
818  */
819 #if 0
820 #define DUK_TVAL_IS_HEAP_ALLOCATED(tv)     ((tv)->t >= DUK_TAG_STRING)
821 #endif
822 #define DUK_TVAL_IS_HEAP_ALLOCATED(tv)     ((tv)->t & 0x08)
823 
824 #if defined(DUK_USE_FASTINT)
825 #if 0
826 DUK_INTERNAL_DECL duk_double_t duk_tval_get_number_unpacked(duk_tval *tv);
827 #endif
828 DUK_INTERNAL_DECL duk_double_t duk_tval_get_number_unpacked_fastint(duk_tval *tv);
829 #endif
830 
831 #endif  /* DUK_USE_PACKED_TVAL */
832 
833 /*
834  *  Convenience (independent of representation)
835  */
836 
837 #define DUK_TVAL_SET_BOOLEAN_TRUE(v)        DUK_TVAL_SET_BOOLEAN(v, 1)
838 #define DUK_TVAL_SET_BOOLEAN_FALSE(v)       DUK_TVAL_SET_BOOLEAN(v, 0)
839 
840 /* Lightfunc flags packing and unpacking. */
841 /* Sign extend: 0x0000##00 -> 0x##000000 -> sign extend to 0xssssss## */
842 #define DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags) \
843 	((((duk_int32_t) (lf_flags)) << 16) >> 24)
844 #define DUK_LFUNC_FLAGS_GET_LENGTH(lf_flags) \
845 	(((lf_flags) >> 4) & 0x0f)
846 #define DUK_LFUNC_FLAGS_GET_NARGS(lf_flags) \
847 	((lf_flags) & 0x0f)
848 #define DUK_LFUNC_FLAGS_PACK(magic,length,nargs) \
849 	(((magic) & 0xff) << 8) | ((length) << 4) | (nargs)
850 
851 #define DUK_LFUNC_NARGS_VARARGS             0x0f   /* varargs marker */
852 #define DUK_LFUNC_NARGS_MIN                 0x00
853 #define DUK_LFUNC_NARGS_MAX                 0x0e   /* max, excl. varargs marker */
854 #define DUK_LFUNC_LENGTH_MIN                0x00
855 #define DUK_LFUNC_LENGTH_MAX                0x0f
856 #define DUK_LFUNC_MAGIC_MIN                 (-0x80)
857 #define DUK_LFUNC_MAGIC_MAX                 0x7f
858 
859 /* fastint constants etc */
860 #if defined(DUK_USE_FASTINT)
861 #define DUK_FASTINT_MIN           (-0x800000000000LL)
862 #define DUK_FASTINT_MAX           0x7fffffffffffLL
863 #define DUK_FASTINT_BITS          48
864 
865 DUK_INTERNAL_DECL void duk_tval_set_number_chkfast(duk_tval *tv, duk_double_t x);
866 #endif
867 
868 #endif  /* DUK_TVAL_H_INCLUDED */
869 /*
870  *  Automatically generated by genbuiltins.py, do not edit!
871  */
872 
873 #ifndef DUK_BUILTINS_H_INCLUDED
874 #define DUK_BUILTINS_H_INCLUDED
875 
876 #if defined(DUK_USE_ROM_STRINGS)
877 #error ROM support not enabled, rerun make_dist.py with --rom-support
878 #else  /* DUK_USE_ROM_STRINGS */
879 #define DUK_STRIDX_UC_UNDEFINED                                       0                              /* 'Undefined' */
880 #define DUK_HEAP_STRING_UC_UNDEFINED(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_UNDEFINED)
881 #define DUK_HTHREAD_STRING_UC_UNDEFINED(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_UNDEFINED)
882 #define DUK_STRIDX_UC_NULL                                            1                              /* 'Null' */
883 #define DUK_HEAP_STRING_UC_NULL(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_NULL)
884 #define DUK_HTHREAD_STRING_UC_NULL(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_NULL)
885 #define DUK_STRIDX_UC_ARGUMENTS                                       2                              /* 'Arguments' */
886 #define DUK_HEAP_STRING_UC_ARGUMENTS(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_ARGUMENTS)
887 #define DUK_HTHREAD_STRING_UC_ARGUMENTS(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_ARGUMENTS)
888 #define DUK_STRIDX_UC_OBJECT                                          3                              /* 'Object' */
889 #define DUK_HEAP_STRING_UC_OBJECT(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_OBJECT)
890 #define DUK_HTHREAD_STRING_UC_OBJECT(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_OBJECT)
891 #define DUK_STRIDX_UC_FUNCTION                                        4                              /* 'Function' */
892 #define DUK_HEAP_STRING_UC_FUNCTION(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_FUNCTION)
893 #define DUK_HTHREAD_STRING_UC_FUNCTION(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_FUNCTION)
894 #define DUK_STRIDX_ARRAY                                              5                              /* 'Array' */
895 #define DUK_HEAP_STRING_ARRAY(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ARRAY)
896 #define DUK_HTHREAD_STRING_ARRAY(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ARRAY)
897 #define DUK_STRIDX_UC_STRING                                          6                              /* 'String' */
898 #define DUK_HEAP_STRING_UC_STRING(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_STRING)
899 #define DUK_HTHREAD_STRING_UC_STRING(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_STRING)
900 #define DUK_STRIDX_UC_BOOLEAN                                         7                              /* 'Boolean' */
901 #define DUK_HEAP_STRING_UC_BOOLEAN(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_BOOLEAN)
902 #define DUK_HTHREAD_STRING_UC_BOOLEAN(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_BOOLEAN)
903 #define DUK_STRIDX_UC_NUMBER                                          8                              /* 'Number' */
904 #define DUK_HEAP_STRING_UC_NUMBER(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_NUMBER)
905 #define DUK_HTHREAD_STRING_UC_NUMBER(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_NUMBER)
906 #define DUK_STRIDX_DATE                                               9                              /* 'Date' */
907 #define DUK_HEAP_STRING_DATE(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DATE)
908 #define DUK_HTHREAD_STRING_DATE(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DATE)
909 #define DUK_STRIDX_REG_EXP                                            10                             /* 'RegExp' */
910 #define DUK_HEAP_STRING_REG_EXP(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_REG_EXP)
911 #define DUK_HTHREAD_STRING_REG_EXP(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_REG_EXP)
912 #define DUK_STRIDX_UC_ERROR                                           11                             /* 'Error' */
913 #define DUK_HEAP_STRING_UC_ERROR(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_ERROR)
914 #define DUK_HTHREAD_STRING_UC_ERROR(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_ERROR)
915 #define DUK_STRIDX_MATH                                               12                             /* 'Math' */
916 #define DUK_HEAP_STRING_MATH(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MATH)
917 #define DUK_HTHREAD_STRING_MATH(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MATH)
918 #define DUK_STRIDX_JSON                                               13                             /* 'JSON' */
919 #define DUK_HEAP_STRING_JSON(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON)
920 #define DUK_HTHREAD_STRING_JSON(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON)
921 #define DUK_STRIDX_EMPTY_STRING                                       14                             /* '' */
922 #define DUK_HEAP_STRING_EMPTY_STRING(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EMPTY_STRING)
923 #define DUK_HTHREAD_STRING_EMPTY_STRING(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EMPTY_STRING)
924 #define DUK_STRIDX_ARRAY_BUFFER                                       15                             /* 'ArrayBuffer' */
925 #define DUK_HEAP_STRING_ARRAY_BUFFER(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ARRAY_BUFFER)
926 #define DUK_HTHREAD_STRING_ARRAY_BUFFER(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ARRAY_BUFFER)
927 #define DUK_STRIDX_DATA_VIEW                                          16                             /* 'DataView' */
928 #define DUK_HEAP_STRING_DATA_VIEW(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DATA_VIEW)
929 #define DUK_HTHREAD_STRING_DATA_VIEW(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DATA_VIEW)
930 #define DUK_STRIDX_INT8_ARRAY                                         17                             /* 'Int8Array' */
931 #define DUK_HEAP_STRING_INT8_ARRAY(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT8_ARRAY)
932 #define DUK_HTHREAD_STRING_INT8_ARRAY(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT8_ARRAY)
933 #define DUK_STRIDX_UINT8_ARRAY                                        18                             /* 'Uint8Array' */
934 #define DUK_HEAP_STRING_UINT8_ARRAY(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT8_ARRAY)
935 #define DUK_HTHREAD_STRING_UINT8_ARRAY(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT8_ARRAY)
936 #define DUK_STRIDX_UINT8_CLAMPED_ARRAY                                19                             /* 'Uint8ClampedArray' */
937 #define DUK_HEAP_STRING_UINT8_CLAMPED_ARRAY(heap)                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT8_CLAMPED_ARRAY)
938 #define DUK_HTHREAD_STRING_UINT8_CLAMPED_ARRAY(thr)                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT8_CLAMPED_ARRAY)
939 #define DUK_STRIDX_INT16_ARRAY                                        20                             /* 'Int16Array' */
940 #define DUK_HEAP_STRING_INT16_ARRAY(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT16_ARRAY)
941 #define DUK_HTHREAD_STRING_INT16_ARRAY(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT16_ARRAY)
942 #define DUK_STRIDX_UINT16_ARRAY                                       21                             /* 'Uint16Array' */
943 #define DUK_HEAP_STRING_UINT16_ARRAY(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT16_ARRAY)
944 #define DUK_HTHREAD_STRING_UINT16_ARRAY(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT16_ARRAY)
945 #define DUK_STRIDX_INT32_ARRAY                                        22                             /* 'Int32Array' */
946 #define DUK_HEAP_STRING_INT32_ARRAY(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT32_ARRAY)
947 #define DUK_HTHREAD_STRING_INT32_ARRAY(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT32_ARRAY)
948 #define DUK_STRIDX_UINT32_ARRAY                                       23                             /* 'Uint32Array' */
949 #define DUK_HEAP_STRING_UINT32_ARRAY(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT32_ARRAY)
950 #define DUK_HTHREAD_STRING_UINT32_ARRAY(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT32_ARRAY)
951 #define DUK_STRIDX_FLOAT32_ARRAY                                      24                             /* 'Float32Array' */
952 #define DUK_HEAP_STRING_FLOAT32_ARRAY(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FLOAT32_ARRAY)
953 #define DUK_HTHREAD_STRING_FLOAT32_ARRAY(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FLOAT32_ARRAY)
954 #define DUK_STRIDX_FLOAT64_ARRAY                                      25                             /* 'Float64Array' */
955 #define DUK_HEAP_STRING_FLOAT64_ARRAY(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FLOAT64_ARRAY)
956 #define DUK_HTHREAD_STRING_FLOAT64_ARRAY(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FLOAT64_ARRAY)
957 #define DUK_STRIDX_GLOBAL                                             26                             /* 'global' */
958 #define DUK_HEAP_STRING_GLOBAL(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GLOBAL)
959 #define DUK_HTHREAD_STRING_GLOBAL(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GLOBAL)
960 #define DUK_STRIDX_OBJ_ENV                                            27                             /* 'ObjEnv' */
961 #define DUK_HEAP_STRING_OBJ_ENV(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_OBJ_ENV)
962 #define DUK_HTHREAD_STRING_OBJ_ENV(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_OBJ_ENV)
963 #define DUK_STRIDX_DEC_ENV                                            28                             /* 'DecEnv' */
964 #define DUK_HEAP_STRING_DEC_ENV(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DEC_ENV)
965 #define DUK_HTHREAD_STRING_DEC_ENV(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DEC_ENV)
966 #define DUK_STRIDX_UC_BUFFER                                          29                             /* 'Buffer' */
967 #define DUK_HEAP_STRING_UC_BUFFER(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_BUFFER)
968 #define DUK_HTHREAD_STRING_UC_BUFFER(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_BUFFER)
969 #define DUK_STRIDX_UC_POINTER                                         30                             /* 'Pointer' */
970 #define DUK_HEAP_STRING_UC_POINTER(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_POINTER)
971 #define DUK_HTHREAD_STRING_UC_POINTER(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_POINTER)
972 #define DUK_STRIDX_UC_THREAD                                          31                             /* 'Thread' */
973 #define DUK_HEAP_STRING_UC_THREAD(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_THREAD)
974 #define DUK_HTHREAD_STRING_UC_THREAD(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_THREAD)
975 #define DUK_STRIDX_EVAL                                               32                             /* 'eval' */
976 #define DUK_HEAP_STRING_EVAL(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EVAL)
977 #define DUK_HTHREAD_STRING_EVAL(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EVAL)
978 #define DUK_STRIDX_DEFINE_PROPERTY                                    33                             /* 'defineProperty' */
979 #define DUK_HEAP_STRING_DEFINE_PROPERTY(heap)                         DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DEFINE_PROPERTY)
980 #define DUK_HTHREAD_STRING_DEFINE_PROPERTY(thr)                       DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DEFINE_PROPERTY)
981 #define DUK_STRIDX_VALUE                                              34                             /* 'value' */
982 #define DUK_HEAP_STRING_VALUE(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VALUE)
983 #define DUK_HTHREAD_STRING_VALUE(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VALUE)
984 #define DUK_STRIDX_WRITABLE                                           35                             /* 'writable' */
985 #define DUK_HEAP_STRING_WRITABLE(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITABLE)
986 #define DUK_HTHREAD_STRING_WRITABLE(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITABLE)
987 #define DUK_STRIDX_CONFIGURABLE                                       36                             /* 'configurable' */
988 #define DUK_HEAP_STRING_CONFIGURABLE(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONFIGURABLE)
989 #define DUK_HTHREAD_STRING_CONFIGURABLE(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONFIGURABLE)
990 #define DUK_STRIDX_ENUMERABLE                                         37                             /* 'enumerable' */
991 #define DUK_HEAP_STRING_ENUMERABLE(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ENUMERABLE)
992 #define DUK_HTHREAD_STRING_ENUMERABLE(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ENUMERABLE)
993 #define DUK_STRIDX_JOIN                                               38                             /* 'join' */
994 #define DUK_HEAP_STRING_JOIN(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JOIN)
995 #define DUK_HTHREAD_STRING_JOIN(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JOIN)
996 #define DUK_STRIDX_TO_LOCALE_STRING                                   39                             /* 'toLocaleString' */
997 #define DUK_HEAP_STRING_TO_LOCALE_STRING(heap)                        DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_LOCALE_STRING)
998 #define DUK_HTHREAD_STRING_TO_LOCALE_STRING(thr)                      DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_LOCALE_STRING)
999 #define DUK_STRIDX_VALUE_OF                                           40                             /* 'valueOf' */
1000 #define DUK_HEAP_STRING_VALUE_OF(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VALUE_OF)
1001 #define DUK_HTHREAD_STRING_VALUE_OF(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VALUE_OF)
1002 #define DUK_STRIDX_TO_UTC_STRING                                      41                             /* 'toUTCString' */
1003 #define DUK_HEAP_STRING_TO_UTC_STRING(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_UTC_STRING)
1004 #define DUK_HTHREAD_STRING_TO_UTC_STRING(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_UTC_STRING)
1005 #define DUK_STRIDX_TO_ISO_STRING                                      42                             /* 'toISOString' */
1006 #define DUK_HEAP_STRING_TO_ISO_STRING(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_ISO_STRING)
1007 #define DUK_HTHREAD_STRING_TO_ISO_STRING(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_ISO_STRING)
1008 #define DUK_STRIDX_TO_GMT_STRING                                      43                             /* 'toGMTString' */
1009 #define DUK_HEAP_STRING_TO_GMT_STRING(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_GMT_STRING)
1010 #define DUK_HTHREAD_STRING_TO_GMT_STRING(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_GMT_STRING)
1011 #define DUK_STRIDX_SOURCE                                             44                             /* 'source' */
1012 #define DUK_HEAP_STRING_SOURCE(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SOURCE)
1013 #define DUK_HTHREAD_STRING_SOURCE(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SOURCE)
1014 #define DUK_STRIDX_IGNORE_CASE                                        45                             /* 'ignoreCase' */
1015 #define DUK_HEAP_STRING_IGNORE_CASE(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IGNORE_CASE)
1016 #define DUK_HTHREAD_STRING_IGNORE_CASE(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IGNORE_CASE)
1017 #define DUK_STRIDX_MULTILINE                                          46                             /* 'multiline' */
1018 #define DUK_HEAP_STRING_MULTILINE(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MULTILINE)
1019 #define DUK_HTHREAD_STRING_MULTILINE(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MULTILINE)
1020 #define DUK_STRIDX_LAST_INDEX                                         47                             /* 'lastIndex' */
1021 #define DUK_HEAP_STRING_LAST_INDEX(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LAST_INDEX)
1022 #define DUK_HTHREAD_STRING_LAST_INDEX(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LAST_INDEX)
1023 #define DUK_STRIDX_ESCAPED_EMPTY_REGEXP                               48                             /* '(?:)' */
1024 #define DUK_HEAP_STRING_ESCAPED_EMPTY_REGEXP(heap)                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ESCAPED_EMPTY_REGEXP)
1025 #define DUK_HTHREAD_STRING_ESCAPED_EMPTY_REGEXP(thr)                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ESCAPED_EMPTY_REGEXP)
1026 #define DUK_STRIDX_INDEX                                              49                             /* 'index' */
1027 #define DUK_HEAP_STRING_INDEX(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INDEX)
1028 #define DUK_HTHREAD_STRING_INDEX(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INDEX)
1029 #define DUK_STRIDX_PROTOTYPE                                          50                             /* 'prototype' */
1030 #define DUK_HEAP_STRING_PROTOTYPE(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PROTOTYPE)
1031 #define DUK_HTHREAD_STRING_PROTOTYPE(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PROTOTYPE)
1032 #define DUK_STRIDX_CONSTRUCTOR                                        51                             /* 'constructor' */
1033 #define DUK_HEAP_STRING_CONSTRUCTOR(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONSTRUCTOR)
1034 #define DUK_HTHREAD_STRING_CONSTRUCTOR(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONSTRUCTOR)
1035 #define DUK_STRIDX_MESSAGE                                            52                             /* 'message' */
1036 #define DUK_HEAP_STRING_MESSAGE(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MESSAGE)
1037 #define DUK_HTHREAD_STRING_MESSAGE(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MESSAGE)
1038 #define DUK_STRIDX_LC_BOOLEAN                                         53                             /* 'boolean' */
1039 #define DUK_HEAP_STRING_LC_BOOLEAN(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_BOOLEAN)
1040 #define DUK_HTHREAD_STRING_LC_BOOLEAN(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_BOOLEAN)
1041 #define DUK_STRIDX_LC_NUMBER                                          54                             /* 'number' */
1042 #define DUK_HEAP_STRING_LC_NUMBER(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_NUMBER)
1043 #define DUK_HTHREAD_STRING_LC_NUMBER(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_NUMBER)
1044 #define DUK_STRIDX_LC_STRING                                          55                             /* 'string' */
1045 #define DUK_HEAP_STRING_LC_STRING(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_STRING)
1046 #define DUK_HTHREAD_STRING_LC_STRING(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_STRING)
1047 #define DUK_STRIDX_LC_OBJECT                                          56                             /* 'object' */
1048 #define DUK_HEAP_STRING_LC_OBJECT(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_OBJECT)
1049 #define DUK_HTHREAD_STRING_LC_OBJECT(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_OBJECT)
1050 #define DUK_STRIDX_LC_UNDEFINED                                       57                             /* 'undefined' */
1051 #define DUK_HEAP_STRING_LC_UNDEFINED(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_UNDEFINED)
1052 #define DUK_HTHREAD_STRING_LC_UNDEFINED(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_UNDEFINED)
1053 #define DUK_STRIDX_NAN                                                58                             /* 'NaN' */
1054 #define DUK_HEAP_STRING_NAN(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NAN)
1055 #define DUK_HTHREAD_STRING_NAN(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NAN)
1056 #define DUK_STRIDX_INFINITY                                           59                             /* 'Infinity' */
1057 #define DUK_HEAP_STRING_INFINITY(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INFINITY)
1058 #define DUK_HTHREAD_STRING_INFINITY(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INFINITY)
1059 #define DUK_STRIDX_MINUS_INFINITY                                     60                             /* '-Infinity' */
1060 #define DUK_HEAP_STRING_MINUS_INFINITY(heap)                          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MINUS_INFINITY)
1061 #define DUK_HTHREAD_STRING_MINUS_INFINITY(thr)                        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MINUS_INFINITY)
1062 #define DUK_STRIDX_MINUS_ZERO                                         61                             /* '-0' */
1063 #define DUK_HEAP_STRING_MINUS_ZERO(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MINUS_ZERO)
1064 #define DUK_HTHREAD_STRING_MINUS_ZERO(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MINUS_ZERO)
1065 #define DUK_STRIDX_COMMA                                              62                             /* ',' */
1066 #define DUK_HEAP_STRING_COMMA(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_COMMA)
1067 #define DUK_HTHREAD_STRING_COMMA(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_COMMA)
1068 #define DUK_STRIDX_SPACE                                              63                             /* ' ' */
1069 #define DUK_HEAP_STRING_SPACE(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SPACE)
1070 #define DUK_HTHREAD_STRING_SPACE(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SPACE)
1071 #define DUK_STRIDX_NEWLINE_4SPACE                                     64                             /* '\n    ' */
1072 #define DUK_HEAP_STRING_NEWLINE_4SPACE(heap)                          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NEWLINE_4SPACE)
1073 #define DUK_HTHREAD_STRING_NEWLINE_4SPACE(thr)                        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NEWLINE_4SPACE)
1074 #define DUK_STRIDX_BRACKETED_ELLIPSIS                                 65                             /* '[...]' */
1075 #define DUK_HEAP_STRING_BRACKETED_ELLIPSIS(heap)                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BRACKETED_ELLIPSIS)
1076 #define DUK_HTHREAD_STRING_BRACKETED_ELLIPSIS(thr)                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BRACKETED_ELLIPSIS)
1077 #define DUK_STRIDX_INVALID_DATE                                       66                             /* 'Invalid Date' */
1078 #define DUK_HEAP_STRING_INVALID_DATE(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INVALID_DATE)
1079 #define DUK_HTHREAD_STRING_INVALID_DATE(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INVALID_DATE)
1080 #define DUK_STRIDX_LC_ARGUMENTS                                       67                             /* 'arguments' */
1081 #define DUK_HEAP_STRING_LC_ARGUMENTS(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_ARGUMENTS)
1082 #define DUK_HTHREAD_STRING_LC_ARGUMENTS(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_ARGUMENTS)
1083 #define DUK_STRIDX_CALLEE                                             68                             /* 'callee' */
1084 #define DUK_HEAP_STRING_CALLEE(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CALLEE)
1085 #define DUK_HTHREAD_STRING_CALLEE(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CALLEE)
1086 #define DUK_STRIDX_CALLER                                             69                             /* 'caller' */
1087 #define DUK_HEAP_STRING_CALLER(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CALLER)
1088 #define DUK_HTHREAD_STRING_CALLER(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CALLER)
1089 #define DUK_STRIDX_HAS                                                70                             /* 'has' */
1090 #define DUK_HEAP_STRING_HAS(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_HAS)
1091 #define DUK_HTHREAD_STRING_HAS(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_HAS)
1092 #define DUK_STRIDX_GET                                                71                             /* 'get' */
1093 #define DUK_HEAP_STRING_GET(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET)
1094 #define DUK_HTHREAD_STRING_GET(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET)
1095 #define DUK_STRIDX_DELETE_PROPERTY                                    72                             /* 'deleteProperty' */
1096 #define DUK_HEAP_STRING_DELETE_PROPERTY(heap)                         DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DELETE_PROPERTY)
1097 #define DUK_HTHREAD_STRING_DELETE_PROPERTY(thr)                       DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DELETE_PROPERTY)
1098 #define DUK_STRIDX_ENUMERATE                                          73                             /* 'enumerate' */
1099 #define DUK_HEAP_STRING_ENUMERATE(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ENUMERATE)
1100 #define DUK_HTHREAD_STRING_ENUMERATE(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ENUMERATE)
1101 #define DUK_STRIDX_OWN_KEYS                                           74                             /* 'ownKeys' */
1102 #define DUK_HEAP_STRING_OWN_KEYS(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_OWN_KEYS)
1103 #define DUK_HTHREAD_STRING_OWN_KEYS(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_OWN_KEYS)
1104 #define DUK_STRIDX_SET_PROTOTYPE_OF                                   75                             /* 'setPrototypeOf' */
1105 #define DUK_HEAP_STRING_SET_PROTOTYPE_OF(heap)                        DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_PROTOTYPE_OF)
1106 #define DUK_HTHREAD_STRING_SET_PROTOTYPE_OF(thr)                      DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_PROTOTYPE_OF)
1107 #define DUK_STRIDX___PROTO__                                          76                             /* '__proto__' */
1108 #define DUK_HEAP_STRING___PROTO__(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX___PROTO__)
1109 #define DUK_HTHREAD_STRING___PROTO__(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX___PROTO__)
1110 #define DUK_STRIDX_REQUIRE                                            77                             /* 'require' */
1111 #define DUK_HEAP_STRING_REQUIRE(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_REQUIRE)
1112 #define DUK_HTHREAD_STRING_REQUIRE(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_REQUIRE)
1113 #define DUK_STRIDX_ID                                                 78                             /* 'id' */
1114 #define DUK_HEAP_STRING_ID(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ID)
1115 #define DUK_HTHREAD_STRING_ID(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ID)
1116 #define DUK_STRIDX_EXPORTS                                            79                             /* 'exports' */
1117 #define DUK_HEAP_STRING_EXPORTS(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EXPORTS)
1118 #define DUK_HTHREAD_STRING_EXPORTS(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EXPORTS)
1119 #define DUK_STRIDX_FILENAME                                           80                             /* 'filename' */
1120 #define DUK_HEAP_STRING_FILENAME(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FILENAME)
1121 #define DUK_HTHREAD_STRING_FILENAME(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FILENAME)
1122 #define DUK_STRIDX_TO_STRING                                          81                             /* 'toString' */
1123 #define DUK_HEAP_STRING_TO_STRING(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_STRING)
1124 #define DUK_HTHREAD_STRING_TO_STRING(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_STRING)
1125 #define DUK_STRIDX_TO_JSON                                            82                             /* 'toJSON' */
1126 #define DUK_HEAP_STRING_TO_JSON(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_JSON)
1127 #define DUK_HTHREAD_STRING_TO_JSON(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_JSON)
1128 #define DUK_STRIDX_TYPE                                               83                             /* 'type' */
1129 #define DUK_HEAP_STRING_TYPE(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TYPE)
1130 #define DUK_HTHREAD_STRING_TYPE(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TYPE)
1131 #define DUK_STRIDX_DATA                                               84                             /* 'data' */
1132 #define DUK_HEAP_STRING_DATA(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DATA)
1133 #define DUK_HTHREAD_STRING_DATA(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DATA)
1134 #define DUK_STRIDX_LENGTH                                             85                             /* 'length' */
1135 #define DUK_HEAP_STRING_LENGTH(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LENGTH)
1136 #define DUK_HTHREAD_STRING_LENGTH(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LENGTH)
1137 #define DUK_STRIDX_BYTE_LENGTH                                        86                             /* 'byteLength' */
1138 #define DUK_HEAP_STRING_BYTE_LENGTH(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BYTE_LENGTH)
1139 #define DUK_HTHREAD_STRING_BYTE_LENGTH(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BYTE_LENGTH)
1140 #define DUK_STRIDX_BYTE_OFFSET                                        87                             /* 'byteOffset' */
1141 #define DUK_HEAP_STRING_BYTE_OFFSET(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BYTE_OFFSET)
1142 #define DUK_HTHREAD_STRING_BYTE_OFFSET(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BYTE_OFFSET)
1143 #define DUK_STRIDX_BYTES_PER_ELEMENT                                  88                             /* 'BYTES_PER_ELEMENT' */
1144 #define DUK_HEAP_STRING_BYTES_PER_ELEMENT(heap)                       DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BYTES_PER_ELEMENT)
1145 #define DUK_HTHREAD_STRING_BYTES_PER_ELEMENT(thr)                     DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BYTES_PER_ELEMENT)
1146 #define DUK_STRIDX_SET                                                89                             /* 'set' */
1147 #define DUK_HEAP_STRING_SET(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET)
1148 #define DUK_HTHREAD_STRING_SET(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET)
1149 #define DUK_STRIDX_STACK                                              90                             /* 'stack' */
1150 #define DUK_HEAP_STRING_STACK(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_STACK)
1151 #define DUK_HTHREAD_STRING_STACK(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_STACK)
1152 #define DUK_STRIDX_PC                                                 91                             /* 'pc' */
1153 #define DUK_HEAP_STRING_PC(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PC)
1154 #define DUK_HTHREAD_STRING_PC(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PC)
1155 #define DUK_STRIDX_LINE_NUMBER                                        92                             /* 'lineNumber' */
1156 #define DUK_HEAP_STRING_LINE_NUMBER(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LINE_NUMBER)
1157 #define DUK_HTHREAD_STRING_LINE_NUMBER(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LINE_NUMBER)
1158 #define DUK_STRIDX_INT_TRACEDATA                                      93                             /* '\xffTracedata' */
1159 #define DUK_HEAP_STRING_INT_TRACEDATA(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_TRACEDATA)
1160 #define DUK_HTHREAD_STRING_INT_TRACEDATA(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_TRACEDATA)
1161 #define DUK_STRIDX_NAME                                               94                             /* 'name' */
1162 #define DUK_HEAP_STRING_NAME(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NAME)
1163 #define DUK_HTHREAD_STRING_NAME(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NAME)
1164 #define DUK_STRIDX_FILE_NAME                                          95                             /* 'fileName' */
1165 #define DUK_HEAP_STRING_FILE_NAME(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FILE_NAME)
1166 #define DUK_HTHREAD_STRING_FILE_NAME(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FILE_NAME)
1167 #define DUK_STRIDX_LC_BUFFER                                          96                             /* 'buffer' */
1168 #define DUK_HEAP_STRING_LC_BUFFER(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_BUFFER)
1169 #define DUK_HTHREAD_STRING_LC_BUFFER(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_BUFFER)
1170 #define DUK_STRIDX_LC_POINTER                                         97                             /* 'pointer' */
1171 #define DUK_HEAP_STRING_LC_POINTER(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_POINTER)
1172 #define DUK_HTHREAD_STRING_LC_POINTER(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_POINTER)
1173 #define DUK_STRIDX_INT_VALUE                                          98                             /* '\xffValue' */
1174 #define DUK_HEAP_STRING_INT_VALUE(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_VALUE)
1175 #define DUK_HTHREAD_STRING_INT_VALUE(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_VALUE)
1176 #define DUK_STRIDX_INT_NEXT                                           99                             /* '\xffNext' */
1177 #define DUK_HEAP_STRING_INT_NEXT(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_NEXT)
1178 #define DUK_HTHREAD_STRING_INT_NEXT(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_NEXT)
1179 #define DUK_STRIDX_INT_BYTECODE                                       100                            /* '\xffBytecode' */
1180 #define DUK_HEAP_STRING_INT_BYTECODE(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_BYTECODE)
1181 #define DUK_HTHREAD_STRING_INT_BYTECODE(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_BYTECODE)
1182 #define DUK_STRIDX_INT_FORMALS                                        101                            /* '\xffFormals' */
1183 #define DUK_HEAP_STRING_INT_FORMALS(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_FORMALS)
1184 #define DUK_HTHREAD_STRING_INT_FORMALS(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_FORMALS)
1185 #define DUK_STRIDX_INT_VARMAP                                         102                            /* '\xffVarmap' */
1186 #define DUK_HEAP_STRING_INT_VARMAP(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_VARMAP)
1187 #define DUK_HTHREAD_STRING_INT_VARMAP(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_VARMAP)
1188 #define DUK_STRIDX_INT_LEXENV                                         103                            /* '\xffLexenv' */
1189 #define DUK_HEAP_STRING_INT_LEXENV(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_LEXENV)
1190 #define DUK_HTHREAD_STRING_INT_LEXENV(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_LEXENV)
1191 #define DUK_STRIDX_INT_VARENV                                         104                            /* '\xffVarenv' */
1192 #define DUK_HEAP_STRING_INT_VARENV(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_VARENV)
1193 #define DUK_HTHREAD_STRING_INT_VARENV(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_VARENV)
1194 #define DUK_STRIDX_INT_SOURCE                                         105                            /* '\xffSource' */
1195 #define DUK_HEAP_STRING_INT_SOURCE(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_SOURCE)
1196 #define DUK_HTHREAD_STRING_INT_SOURCE(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_SOURCE)
1197 #define DUK_STRIDX_INT_PC2LINE                                        106                            /* '\xffPc2line' */
1198 #define DUK_HEAP_STRING_INT_PC2LINE(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_PC2LINE)
1199 #define DUK_HTHREAD_STRING_INT_PC2LINE(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_PC2LINE)
1200 #define DUK_STRIDX_INT_ARGS                                           107                            /* '\xffArgs' */
1201 #define DUK_HEAP_STRING_INT_ARGS(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_ARGS)
1202 #define DUK_HTHREAD_STRING_INT_ARGS(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_ARGS)
1203 #define DUK_STRIDX_INT_MAP                                            108                            /* '\xffMap' */
1204 #define DUK_HEAP_STRING_INT_MAP(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_MAP)
1205 #define DUK_HTHREAD_STRING_INT_MAP(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_MAP)
1206 #define DUK_STRIDX_INT_FINALIZER                                      109                            /* '\xffFinalizer' */
1207 #define DUK_HEAP_STRING_INT_FINALIZER(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_FINALIZER)
1208 #define DUK_HTHREAD_STRING_INT_FINALIZER(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_FINALIZER)
1209 #define DUK_STRIDX_INT_HANDLER                                        110                            /* '\xffHandler' */
1210 #define DUK_HEAP_STRING_INT_HANDLER(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_HANDLER)
1211 #define DUK_HTHREAD_STRING_INT_HANDLER(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_HANDLER)
1212 #define DUK_STRIDX_INT_CALLEE                                         111                            /* '\xffCallee' */
1213 #define DUK_HEAP_STRING_INT_CALLEE(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_CALLEE)
1214 #define DUK_HTHREAD_STRING_INT_CALLEE(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_CALLEE)
1215 #define DUK_STRIDX_INT_THREAD                                         112                            /* '\xffThread' */
1216 #define DUK_HEAP_STRING_INT_THREAD(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_THREAD)
1217 #define DUK_HTHREAD_STRING_INT_THREAD(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_THREAD)
1218 #define DUK_STRIDX_INT_REGBASE                                        113                            /* '\xffRegbase' */
1219 #define DUK_HEAP_STRING_INT_REGBASE(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_REGBASE)
1220 #define DUK_HTHREAD_STRING_INT_REGBASE(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_REGBASE)
1221 #define DUK_STRIDX_INT_TARGET                                         114                            /* '\xffTarget' */
1222 #define DUK_HEAP_STRING_INT_TARGET(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_TARGET)
1223 #define DUK_HTHREAD_STRING_INT_TARGET(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_TARGET)
1224 #define DUK_STRIDX_INT_THIS                                           115                            /* '\xffThis' */
1225 #define DUK_HEAP_STRING_INT_THIS(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_THIS)
1226 #define DUK_HTHREAD_STRING_INT_THIS(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_THIS)
1227 #define DUK_STRIDX_COMPILE                                            116                            /* 'compile' */
1228 #define DUK_HEAP_STRING_COMPILE(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_COMPILE)
1229 #define DUK_HTHREAD_STRING_COMPILE(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_COMPILE)
1230 #define DUK_STRIDX_INPUT                                              117                            /* 'input' */
1231 #define DUK_HEAP_STRING_INPUT(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INPUT)
1232 #define DUK_HTHREAD_STRING_INPUT(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INPUT)
1233 #define DUK_STRIDX_ERR_CREATE                                         118                            /* 'errCreate' */
1234 #define DUK_HEAP_STRING_ERR_CREATE(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ERR_CREATE)
1235 #define DUK_HTHREAD_STRING_ERR_CREATE(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ERR_CREATE)
1236 #define DUK_STRIDX_ERR_THROW                                          119                            /* 'errThrow' */
1237 #define DUK_HEAP_STRING_ERR_THROW(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ERR_THROW)
1238 #define DUK_HTHREAD_STRING_ERR_THROW(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ERR_THROW)
1239 #define DUK_STRIDX_MOD_SEARCH                                         120                            /* 'modSearch' */
1240 #define DUK_HEAP_STRING_MOD_SEARCH(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MOD_SEARCH)
1241 #define DUK_HTHREAD_STRING_MOD_SEARCH(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MOD_SEARCH)
1242 #define DUK_STRIDX_MOD_LOADED                                         121                            /* 'modLoaded' */
1243 #define DUK_HEAP_STRING_MOD_LOADED(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MOD_LOADED)
1244 #define DUK_HTHREAD_STRING_MOD_LOADED(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MOD_LOADED)
1245 #define DUK_STRIDX_ENV                                                122                            /* 'env' */
1246 #define DUK_HEAP_STRING_ENV(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ENV)
1247 #define DUK_HTHREAD_STRING_ENV(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ENV)
1248 #define DUK_STRIDX_HEX                                                123                            /* 'hex' */
1249 #define DUK_HEAP_STRING_HEX(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_HEX)
1250 #define DUK_HTHREAD_STRING_HEX(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_HEX)
1251 #define DUK_STRIDX_BASE64                                             124                            /* 'base64' */
1252 #define DUK_HEAP_STRING_BASE64(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BASE64)
1253 #define DUK_HTHREAD_STRING_BASE64(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BASE64)
1254 #define DUK_STRIDX_JX                                                 125                            /* 'jx' */
1255 #define DUK_HEAP_STRING_JX(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JX)
1256 #define DUK_HTHREAD_STRING_JX(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JX)
1257 #define DUK_STRIDX_JC                                                 126                            /* 'jc' */
1258 #define DUK_HEAP_STRING_JC(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JC)
1259 #define DUK_HTHREAD_STRING_JC(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JC)
1260 #define DUK_STRIDX_RESUME                                             127                            /* 'resume' */
1261 #define DUK_HEAP_STRING_RESUME(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_RESUME)
1262 #define DUK_HTHREAD_STRING_RESUME(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_RESUME)
1263 #define DUK_STRIDX_FMT                                                128                            /* 'fmt' */
1264 #define DUK_HEAP_STRING_FMT(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FMT)
1265 #define DUK_HTHREAD_STRING_FMT(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FMT)
1266 #define DUK_STRIDX_RAW                                                129                            /* 'raw' */
1267 #define DUK_HEAP_STRING_RAW(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_RAW)
1268 #define DUK_HTHREAD_STRING_RAW(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_RAW)
1269 #define DUK_STRIDX_LC_TRACE                                           130                            /* 'trace' */
1270 #define DUK_HEAP_STRING_LC_TRACE(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_TRACE)
1271 #define DUK_HTHREAD_STRING_LC_TRACE(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_TRACE)
1272 #define DUK_STRIDX_LC_DEBUG                                           131                            /* 'debug' */
1273 #define DUK_HEAP_STRING_LC_DEBUG(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_DEBUG)
1274 #define DUK_HTHREAD_STRING_LC_DEBUG(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_DEBUG)
1275 #define DUK_STRIDX_LC_INFO                                            132                            /* 'info' */
1276 #define DUK_HEAP_STRING_LC_INFO(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_INFO)
1277 #define DUK_HTHREAD_STRING_LC_INFO(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_INFO)
1278 #define DUK_STRIDX_LC_WARN                                            133                            /* 'warn' */
1279 #define DUK_HEAP_STRING_LC_WARN(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_WARN)
1280 #define DUK_HTHREAD_STRING_LC_WARN(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_WARN)
1281 #define DUK_STRIDX_LC_ERROR                                           134                            /* 'error' */
1282 #define DUK_HEAP_STRING_LC_ERROR(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_ERROR)
1283 #define DUK_HTHREAD_STRING_LC_ERROR(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_ERROR)
1284 #define DUK_STRIDX_LC_FATAL                                           135                            /* 'fatal' */
1285 #define DUK_HEAP_STRING_LC_FATAL(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_FATAL)
1286 #define DUK_HTHREAD_STRING_LC_FATAL(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_FATAL)
1287 #define DUK_STRIDX_LC_N                                               136                            /* 'n' */
1288 #define DUK_HEAP_STRING_LC_N(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_N)
1289 #define DUK_HTHREAD_STRING_LC_N(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_N)
1290 #define DUK_STRIDX_LC_L                                               137                            /* 'l' */
1291 #define DUK_HEAP_STRING_LC_L(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_L)
1292 #define DUK_HTHREAD_STRING_LC_L(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_L)
1293 #define DUK_STRIDX_CLOG                                               138                            /* 'clog' */
1294 #define DUK_HEAP_STRING_CLOG(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CLOG)
1295 #define DUK_HTHREAD_STRING_CLOG(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CLOG)
1296 #define DUK_STRIDX_TO_LOG_STRING                                      139                            /* 'toLogString' */
1297 #define DUK_HEAP_STRING_TO_LOG_STRING(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_LOG_STRING)
1298 #define DUK_HTHREAD_STRING_TO_LOG_STRING(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_LOG_STRING)
1299 #define DUK_STRIDX_JSON_EXT_UNDEFINED                                 140                            /* '{"_undef":true}' */
1300 #define DUK_HEAP_STRING_JSON_EXT_UNDEFINED(heap)                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_UNDEFINED)
1301 #define DUK_HTHREAD_STRING_JSON_EXT_UNDEFINED(thr)                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_UNDEFINED)
1302 #define DUK_STRIDX_JSON_EXT_NAN                                       141                            /* '{"_nan":true}' */
1303 #define DUK_HEAP_STRING_JSON_EXT_NAN(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_NAN)
1304 #define DUK_HTHREAD_STRING_JSON_EXT_NAN(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_NAN)
1305 #define DUK_STRIDX_JSON_EXT_POSINF                                    142                            /* '{"_inf":true}' */
1306 #define DUK_HEAP_STRING_JSON_EXT_POSINF(heap)                         DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_POSINF)
1307 #define DUK_HTHREAD_STRING_JSON_EXT_POSINF(thr)                       DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_POSINF)
1308 #define DUK_STRIDX_JSON_EXT_NEGINF                                    143                            /* '{"_ninf":true}' */
1309 #define DUK_HEAP_STRING_JSON_EXT_NEGINF(heap)                         DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_NEGINF)
1310 #define DUK_HTHREAD_STRING_JSON_EXT_NEGINF(thr)                       DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_NEGINF)
1311 #define DUK_STRIDX_JSON_EXT_FUNCTION1                                 144                            /* '{"_func":true}' */
1312 #define DUK_HEAP_STRING_JSON_EXT_FUNCTION1(heap)                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_FUNCTION1)
1313 #define DUK_HTHREAD_STRING_JSON_EXT_FUNCTION1(thr)                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_FUNCTION1)
1314 #define DUK_STRIDX_JSON_EXT_FUNCTION2                                 145                            /* '{_func:true}' */
1315 #define DUK_HEAP_STRING_JSON_EXT_FUNCTION2(heap)                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_FUNCTION2)
1316 #define DUK_HTHREAD_STRING_JSON_EXT_FUNCTION2(thr)                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_FUNCTION2)
1317 #define DUK_STRIDX_BREAK                                              146                            /* 'break' */
1318 #define DUK_HEAP_STRING_BREAK(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BREAK)
1319 #define DUK_HTHREAD_STRING_BREAK(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BREAK)
1320 #define DUK_STRIDX_CASE                                               147                            /* 'case' */
1321 #define DUK_HEAP_STRING_CASE(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CASE)
1322 #define DUK_HTHREAD_STRING_CASE(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CASE)
1323 #define DUK_STRIDX_CATCH                                              148                            /* 'catch' */
1324 #define DUK_HEAP_STRING_CATCH(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CATCH)
1325 #define DUK_HTHREAD_STRING_CATCH(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CATCH)
1326 #define DUK_STRIDX_CONTINUE                                           149                            /* 'continue' */
1327 #define DUK_HEAP_STRING_CONTINUE(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONTINUE)
1328 #define DUK_HTHREAD_STRING_CONTINUE(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONTINUE)
1329 #define DUK_STRIDX_DEBUGGER                                           150                            /* 'debugger' */
1330 #define DUK_HEAP_STRING_DEBUGGER(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DEBUGGER)
1331 #define DUK_HTHREAD_STRING_DEBUGGER(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DEBUGGER)
1332 #define DUK_STRIDX_DEFAULT                                            151                            /* 'default' */
1333 #define DUK_HEAP_STRING_DEFAULT(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DEFAULT)
1334 #define DUK_HTHREAD_STRING_DEFAULT(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DEFAULT)
1335 #define DUK_STRIDX_DELETE                                             152                            /* 'delete' */
1336 #define DUK_HEAP_STRING_DELETE(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DELETE)
1337 #define DUK_HTHREAD_STRING_DELETE(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DELETE)
1338 #define DUK_STRIDX_DO                                                 153                            /* 'do' */
1339 #define DUK_HEAP_STRING_DO(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DO)
1340 #define DUK_HTHREAD_STRING_DO(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DO)
1341 #define DUK_STRIDX_ELSE                                               154                            /* 'else' */
1342 #define DUK_HEAP_STRING_ELSE(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ELSE)
1343 #define DUK_HTHREAD_STRING_ELSE(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ELSE)
1344 #define DUK_STRIDX_FINALLY                                            155                            /* 'finally' */
1345 #define DUK_HEAP_STRING_FINALLY(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FINALLY)
1346 #define DUK_HTHREAD_STRING_FINALLY(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FINALLY)
1347 #define DUK_STRIDX_FOR                                                156                            /* 'for' */
1348 #define DUK_HEAP_STRING_FOR(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FOR)
1349 #define DUK_HTHREAD_STRING_FOR(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FOR)
1350 #define DUK_STRIDX_LC_FUNCTION                                        157                            /* 'function' */
1351 #define DUK_HEAP_STRING_LC_FUNCTION(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_FUNCTION)
1352 #define DUK_HTHREAD_STRING_LC_FUNCTION(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_FUNCTION)
1353 #define DUK_STRIDX_IF                                                 158                            /* 'if' */
1354 #define DUK_HEAP_STRING_IF(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IF)
1355 #define DUK_HTHREAD_STRING_IF(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IF)
1356 #define DUK_STRIDX_IN                                                 159                            /* 'in' */
1357 #define DUK_HEAP_STRING_IN(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IN)
1358 #define DUK_HTHREAD_STRING_IN(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IN)
1359 #define DUK_STRIDX_INSTANCEOF                                         160                            /* 'instanceof' */
1360 #define DUK_HEAP_STRING_INSTANCEOF(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INSTANCEOF)
1361 #define DUK_HTHREAD_STRING_INSTANCEOF(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INSTANCEOF)
1362 #define DUK_STRIDX_NEW                                                161                            /* 'new' */
1363 #define DUK_HEAP_STRING_NEW(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NEW)
1364 #define DUK_HTHREAD_STRING_NEW(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NEW)
1365 #define DUK_STRIDX_RETURN                                             162                            /* 'return' */
1366 #define DUK_HEAP_STRING_RETURN(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_RETURN)
1367 #define DUK_HTHREAD_STRING_RETURN(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_RETURN)
1368 #define DUK_STRIDX_SWITCH                                             163                            /* 'switch' */
1369 #define DUK_HEAP_STRING_SWITCH(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SWITCH)
1370 #define DUK_HTHREAD_STRING_SWITCH(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SWITCH)
1371 #define DUK_STRIDX_THIS                                               164                            /* 'this' */
1372 #define DUK_HEAP_STRING_THIS(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_THIS)
1373 #define DUK_HTHREAD_STRING_THIS(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_THIS)
1374 #define DUK_STRIDX_THROW                                              165                            /* 'throw' */
1375 #define DUK_HEAP_STRING_THROW(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_THROW)
1376 #define DUK_HTHREAD_STRING_THROW(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_THROW)
1377 #define DUK_STRIDX_TRY                                                166                            /* 'try' */
1378 #define DUK_HEAP_STRING_TRY(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TRY)
1379 #define DUK_HTHREAD_STRING_TRY(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TRY)
1380 #define DUK_STRIDX_TYPEOF                                             167                            /* 'typeof' */
1381 #define DUK_HEAP_STRING_TYPEOF(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TYPEOF)
1382 #define DUK_HTHREAD_STRING_TYPEOF(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TYPEOF)
1383 #define DUK_STRIDX_VAR                                                168                            /* 'var' */
1384 #define DUK_HEAP_STRING_VAR(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VAR)
1385 #define DUK_HTHREAD_STRING_VAR(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VAR)
1386 #define DUK_STRIDX_CONST                                              169                            /* 'const' */
1387 #define DUK_HEAP_STRING_CONST(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONST)
1388 #define DUK_HTHREAD_STRING_CONST(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONST)
1389 #define DUK_STRIDX_VOID                                               170                            /* 'void' */
1390 #define DUK_HEAP_STRING_VOID(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VOID)
1391 #define DUK_HTHREAD_STRING_VOID(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VOID)
1392 #define DUK_STRIDX_WHILE                                              171                            /* 'while' */
1393 #define DUK_HEAP_STRING_WHILE(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WHILE)
1394 #define DUK_HTHREAD_STRING_WHILE(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WHILE)
1395 #define DUK_STRIDX_WITH                                               172                            /* 'with' */
1396 #define DUK_HEAP_STRING_WITH(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WITH)
1397 #define DUK_HTHREAD_STRING_WITH(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WITH)
1398 #define DUK_STRIDX_CLASS                                              173                            /* 'class' */
1399 #define DUK_HEAP_STRING_CLASS(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CLASS)
1400 #define DUK_HTHREAD_STRING_CLASS(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CLASS)
1401 #define DUK_STRIDX_ENUM                                               174                            /* 'enum' */
1402 #define DUK_HEAP_STRING_ENUM(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ENUM)
1403 #define DUK_HTHREAD_STRING_ENUM(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ENUM)
1404 #define DUK_STRIDX_EXPORT                                             175                            /* 'export' */
1405 #define DUK_HEAP_STRING_EXPORT(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EXPORT)
1406 #define DUK_HTHREAD_STRING_EXPORT(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EXPORT)
1407 #define DUK_STRIDX_EXTENDS                                            176                            /* 'extends' */
1408 #define DUK_HEAP_STRING_EXTENDS(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EXTENDS)
1409 #define DUK_HTHREAD_STRING_EXTENDS(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EXTENDS)
1410 #define DUK_STRIDX_IMPORT                                             177                            /* 'import' */
1411 #define DUK_HEAP_STRING_IMPORT(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IMPORT)
1412 #define DUK_HTHREAD_STRING_IMPORT(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IMPORT)
1413 #define DUK_STRIDX_SUPER                                              178                            /* 'super' */
1414 #define DUK_HEAP_STRING_SUPER(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SUPER)
1415 #define DUK_HTHREAD_STRING_SUPER(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SUPER)
1416 #define DUK_STRIDX_LC_NULL                                            179                            /* 'null' */
1417 #define DUK_HEAP_STRING_LC_NULL(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_NULL)
1418 #define DUK_HTHREAD_STRING_LC_NULL(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_NULL)
1419 #define DUK_STRIDX_TRUE                                               180                            /* 'true' */
1420 #define DUK_HEAP_STRING_TRUE(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TRUE)
1421 #define DUK_HTHREAD_STRING_TRUE(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TRUE)
1422 #define DUK_STRIDX_FALSE                                              181                            /* 'false' */
1423 #define DUK_HEAP_STRING_FALSE(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FALSE)
1424 #define DUK_HTHREAD_STRING_FALSE(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FALSE)
1425 #define DUK_STRIDX_IMPLEMENTS                                         182                            /* 'implements' */
1426 #define DUK_HEAP_STRING_IMPLEMENTS(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IMPLEMENTS)
1427 #define DUK_HTHREAD_STRING_IMPLEMENTS(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IMPLEMENTS)
1428 #define DUK_STRIDX_INTERFACE                                          183                            /* 'interface' */
1429 #define DUK_HEAP_STRING_INTERFACE(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INTERFACE)
1430 #define DUK_HTHREAD_STRING_INTERFACE(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INTERFACE)
1431 #define DUK_STRIDX_LET                                                184                            /* 'let' */
1432 #define DUK_HEAP_STRING_LET(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LET)
1433 #define DUK_HTHREAD_STRING_LET(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LET)
1434 #define DUK_STRIDX_PACKAGE                                            185                            /* 'package' */
1435 #define DUK_HEAP_STRING_PACKAGE(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PACKAGE)
1436 #define DUK_HTHREAD_STRING_PACKAGE(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PACKAGE)
1437 #define DUK_STRIDX_PRIVATE                                            186                            /* 'private' */
1438 #define DUK_HEAP_STRING_PRIVATE(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PRIVATE)
1439 #define DUK_HTHREAD_STRING_PRIVATE(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PRIVATE)
1440 #define DUK_STRIDX_PROTECTED                                          187                            /* 'protected' */
1441 #define DUK_HEAP_STRING_PROTECTED(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PROTECTED)
1442 #define DUK_HTHREAD_STRING_PROTECTED(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PROTECTED)
1443 #define DUK_STRIDX_PUBLIC                                             188                            /* 'public' */
1444 #define DUK_HEAP_STRING_PUBLIC(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PUBLIC)
1445 #define DUK_HTHREAD_STRING_PUBLIC(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PUBLIC)
1446 #define DUK_STRIDX_STATIC                                             189                            /* 'static' */
1447 #define DUK_HEAP_STRING_STATIC(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_STATIC)
1448 #define DUK_HTHREAD_STRING_STATIC(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_STATIC)
1449 #define DUK_STRIDX_YIELD                                              190                            /* 'yield' */
1450 #define DUK_HEAP_STRING_YIELD(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_YIELD)
1451 #define DUK_HTHREAD_STRING_YIELD(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_YIELD)
1452 
1453 #define DUK_HEAP_NUM_STRINGS                                          191
1454 #define DUK_STRIDX_START_RESERVED                                     146
1455 #define DUK_STRIDX_START_STRICT_RESERVED                              182
1456 #define DUK_STRIDX_END_RESERVED                                       191                            /* exclusive endpoint */
1457 
1458 /* To convert a heap stridx to a token number, subtract
1459  * DUK_STRIDX_START_RESERVED and add DUK_TOK_START_RESERVED.
1460  */
1461 #if !defined(DUK_SINGLE_FILE)
1462 DUK_INTERNAL_DECL const duk_uint8_t duk_strings_data[1049];
1463 #endif  /* !DUK_SINGLE_FILE */
1464 #define DUK_STRDATA_MAX_STRLEN                                        17
1465 #define DUK_STRDATA_DATA_LENGTH                                       1049
1466 #endif  /* DUK_USE_ROM_STRINGS */
1467 
1468 #if defined(DUK_USE_ROM_OBJECTS)
1469 #error ROM support not enabled, rerun make_dist.py with --rom-support
1470 #else
1471 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor(duk_context *ctx);
1472 DUK_INTERNAL_DECL duk_ret_t duk_bi_function_constructor(duk_context *ctx);
1473 DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype(duk_context *ctx);
1474 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_constructor(duk_context *ctx);
1475 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_constructor(duk_context *ctx);
1476 DUK_INTERNAL_DECL duk_ret_t duk_bi_boolean_constructor(duk_context *ctx);
1477 DUK_INTERNAL_DECL duk_ret_t duk_bi_number_constructor(duk_context *ctx);
1478 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor(duk_context *ctx);
1479 DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_constructor(duk_context *ctx);
1480 DUK_INTERNAL_DECL duk_ret_t duk_bi_error_constructor_shared(duk_context *ctx);
1481 DUK_INTERNAL_DECL duk_ret_t duk_bi_type_error_thrower(duk_context *ctx);
1482 DUK_INTERNAL_DECL duk_ret_t duk_bi_proxy_constructor(duk_context *ctx);
1483 DUK_INTERNAL_DECL duk_ret_t duk_bi_thread_constructor(duk_context *ctx);
1484 DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_constructor(duk_context *ctx);
1485 DUK_INTERNAL_DECL duk_ret_t duk_bi_pointer_constructor(duk_context *ctx);
1486 DUK_INTERNAL_DECL duk_ret_t duk_bi_logger_constructor(duk_context *ctx);
1487 DUK_INTERNAL_DECL duk_ret_t duk_bi_arraybuffer_constructor(duk_context *ctx);
1488 DUK_INTERNAL_DECL duk_ret_t duk_bi_dataview_constructor(duk_context *ctx);
1489 DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_constructor(duk_context *ctx);
1490 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_constructor(duk_context *ctx);
1491 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_eval(duk_context *ctx);
1492 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_parse_int(duk_context *ctx);
1493 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_parse_float(duk_context *ctx);
1494 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_is_nan(duk_context *ctx);
1495 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_is_finite(duk_context *ctx);
1496 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_decode_uri(duk_context *ctx);
1497 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_decode_uri_component(duk_context *ctx);
1498 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_encode_uri(duk_context *ctx);
1499 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_encode_uri_component(duk_context *ctx);
1500 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_escape(duk_context *ctx);
1501 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_unescape(duk_context *ctx);
1502 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_print_helper(duk_context *ctx);
1503 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_require(duk_context *ctx);
1504 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_getprototype_shared(duk_context *ctx);
1505 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_setprototype_shared(duk_context *ctx);
1506 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_get_own_property_descriptor(duk_context *ctx);
1507 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_keys_shared(duk_context *ctx);
1508 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_create(duk_context *ctx);
1509 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_define_property(duk_context *ctx);
1510 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_define_properties(duk_context *ctx);
1511 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_seal_freeze_shared(duk_context *ctx);
1512 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_prevent_extensions(duk_context *ctx);
1513 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_is_sealed_frozen_shared(duk_context *ctx);
1514 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_is_extensible(duk_context *ctx);
1515 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_to_string(duk_context *ctx);
1516 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_to_locale_string(duk_context *ctx);
1517 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_value_of(duk_context *ctx);
1518 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_has_own_property(duk_context *ctx);
1519 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_is_prototype_of(duk_context *ctx);
1520 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_property_is_enumerable(duk_context *ctx);
1521 DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_to_string(duk_context *ctx);
1522 DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_apply(duk_context *ctx);
1523 DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_call(duk_context *ctx);
1524 DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_bind(duk_context *ctx);
1525 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_constructor_is_array(duk_context *ctx);
1526 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_to_string(duk_context *ctx);
1527 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_join_shared(duk_context *ctx);
1528 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_concat(duk_context *ctx);
1529 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_pop(duk_context *ctx);
1530 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_push(duk_context *ctx);
1531 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_reverse(duk_context *ctx);
1532 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_shift(duk_context *ctx);
1533 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_slice(duk_context *ctx);
1534 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_sort(duk_context *ctx);
1535 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_splice(duk_context *ctx);
1536 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_unshift(duk_context *ctx);
1537 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_indexof_shared(duk_context *ctx);
1538 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_iter_shared(duk_context *ctx);
1539 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_reduce_shared(duk_context *ctx);
1540 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_constructor_from_char_code(duk_context *ctx);
1541 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_to_string(duk_context *ctx);
1542 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_char_at(duk_context *ctx);
1543 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_char_code_at(duk_context *ctx);
1544 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_concat(duk_context *ctx);
1545 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_indexof_shared(duk_context *ctx);
1546 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_locale_compare(duk_context *ctx);
1547 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_match(duk_context *ctx);
1548 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_replace(duk_context *ctx);
1549 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_search(duk_context *ctx);
1550 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_slice(duk_context *ctx);
1551 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_split(duk_context *ctx);
1552 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_substring(duk_context *ctx);
1553 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_caseconv_shared(duk_context *ctx);
1554 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_trim(duk_context *ctx);
1555 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_substr(duk_context *ctx);
1556 DUK_INTERNAL_DECL duk_ret_t duk_bi_boolean_prototype_tostring_shared(duk_context *ctx);
1557 DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_string(duk_context *ctx);
1558 DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_locale_string(duk_context *ctx);
1559 DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_value_of(duk_context *ctx);
1560 DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_fixed(duk_context *ctx);
1561 DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_exponential(duk_context *ctx);
1562 DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_precision(duk_context *ctx);
1563 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor_parse(duk_context *ctx);
1564 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor_utc(duk_context *ctx);
1565 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor_now(duk_context *ctx);
1566 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_tostring_shared(duk_context *ctx);
1567 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_to_json(duk_context *ctx);
1568 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_value_of(duk_context *ctx);
1569 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_get_shared(duk_context *ctx);
1570 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_get_timezone_offset(duk_context *ctx);
1571 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_set_time(duk_context *ctx);
1572 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_set_shared(duk_context *ctx);
1573 DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_exec(duk_context *ctx);
1574 DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_test(duk_context *ctx);
1575 DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_to_string(duk_context *ctx);
1576 DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_stack_getter(duk_context *ctx);
1577 DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_stack_setter(duk_context *ctx);
1578 DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_filename_getter(duk_context *ctx);
1579 DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_filename_setter(duk_context *ctx);
1580 DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_linenumber_getter(duk_context *ctx);
1581 DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_linenumber_setter(duk_context *ctx);
1582 DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_to_string(duk_context *ctx);
1583 DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_onearg_shared(duk_context *ctx);
1584 DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_twoarg_shared(duk_context *ctx);
1585 DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_max(duk_context *ctx);
1586 DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_min(duk_context *ctx);
1587 DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_random(duk_context *ctx);
1588 DUK_INTERNAL_DECL duk_ret_t duk_bi_json_object_parse(duk_context *ctx);
1589 DUK_INTERNAL_DECL duk_ret_t duk_bi_json_object_stringify(duk_context *ctx);
1590 DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_info(duk_context *ctx);
1591 DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_act(duk_context *ctx);
1592 DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_gc(duk_context *ctx);
1593 DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_fin(duk_context *ctx);
1594 DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_enc(duk_context *ctx);
1595 DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_dec(duk_context *ctx);
1596 DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_compact(duk_context *ctx);
1597 DUK_INTERNAL_DECL duk_ret_t duk_bi_thread_yield(duk_context *ctx);
1598 DUK_INTERNAL_DECL duk_ret_t duk_bi_thread_resume(duk_context *ctx);
1599 DUK_INTERNAL_DECL duk_ret_t duk_bi_thread_current(duk_context *ctx);
1600 DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_prototype_tostring_shared(duk_context *ctx);
1601 DUK_INTERNAL_DECL duk_ret_t duk_bi_pointer_prototype_tostring_shared(duk_context *ctx);
1602 DUK_INTERNAL_DECL duk_ret_t duk_bi_logger_prototype_fmt(duk_context *ctx);
1603 DUK_INTERNAL_DECL duk_ret_t duk_bi_logger_prototype_raw(duk_context *ctx);
1604 DUK_INTERNAL_DECL duk_ret_t duk_bi_logger_prototype_log_shared(duk_context *ctx);
1605 DUK_INTERNAL_DECL duk_ret_t duk_bi_arraybuffer_isview(duk_context *ctx);
1606 DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_slice_shared(duk_context *ctx);
1607 DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_readfield(duk_context *ctx);
1608 DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_writefield(duk_context *ctx);
1609 DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_set(duk_context *ctx);
1610 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_concat(duk_context *ctx);
1611 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_is_encoding(duk_context *ctx);
1612 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_is_buffer(duk_context *ctx);
1613 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_byte_length(duk_context *ctx);
1614 DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_compare_shared(duk_context *ctx);
1615 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_tostring(duk_context *ctx);
1616 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_tojson(duk_context *ctx);
1617 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_fill(duk_context *ctx);
1618 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_copy(duk_context *ctx);
1619 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_write(duk_context *ctx);
1620 #if !defined(DUK_SINGLE_FILE)
1621 DUK_INTERNAL_DECL const duk_c_function duk_bi_native_functions[149];
1622 #endif  /* !DUK_SINGLE_FILE */
1623 #if defined(DUK_USE_BUILTIN_INITJS)
1624 #if !defined(DUK_SINGLE_FILE)
1625 DUK_INTERNAL_DECL const duk_uint8_t duk_initjs_data[204];
1626 #endif  /* !DUK_SINGLE_FILE */
1627 #define DUK_BUILTIN_INITJS_DATA_LENGTH                                204
1628 #endif  /* DUK_USE_BUILTIN_INITJS */
1629 #define DUK_BIDX_GLOBAL                                               0
1630 #define DUK_BIDX_GLOBAL_ENV                                           1
1631 #define DUK_BIDX_OBJECT_CONSTRUCTOR                                   2
1632 #define DUK_BIDX_OBJECT_PROTOTYPE                                     3
1633 #define DUK_BIDX_FUNCTION_CONSTRUCTOR                                 4
1634 #define DUK_BIDX_FUNCTION_PROTOTYPE                                   5
1635 #define DUK_BIDX_ARRAY_CONSTRUCTOR                                    6
1636 #define DUK_BIDX_ARRAY_PROTOTYPE                                      7
1637 #define DUK_BIDX_STRING_CONSTRUCTOR                                   8
1638 #define DUK_BIDX_STRING_PROTOTYPE                                     9
1639 #define DUK_BIDX_BOOLEAN_CONSTRUCTOR                                  10
1640 #define DUK_BIDX_BOOLEAN_PROTOTYPE                                    11
1641 #define DUK_BIDX_NUMBER_CONSTRUCTOR                                   12
1642 #define DUK_BIDX_NUMBER_PROTOTYPE                                     13
1643 #define DUK_BIDX_DATE_CONSTRUCTOR                                     14
1644 #define DUK_BIDX_DATE_PROTOTYPE                                       15
1645 #define DUK_BIDX_REGEXP_CONSTRUCTOR                                   16
1646 #define DUK_BIDX_REGEXP_PROTOTYPE                                     17
1647 #define DUK_BIDX_ERROR_CONSTRUCTOR                                    18
1648 #define DUK_BIDX_ERROR_PROTOTYPE                                      19
1649 #define DUK_BIDX_EVAL_ERROR_CONSTRUCTOR                               20
1650 #define DUK_BIDX_EVAL_ERROR_PROTOTYPE                                 21
1651 #define DUK_BIDX_RANGE_ERROR_CONSTRUCTOR                              22
1652 #define DUK_BIDX_RANGE_ERROR_PROTOTYPE                                23
1653 #define DUK_BIDX_REFERENCE_ERROR_CONSTRUCTOR                          24
1654 #define DUK_BIDX_REFERENCE_ERROR_PROTOTYPE                            25
1655 #define DUK_BIDX_SYNTAX_ERROR_CONSTRUCTOR                             26
1656 #define DUK_BIDX_SYNTAX_ERROR_PROTOTYPE                               27
1657 #define DUK_BIDX_TYPE_ERROR_CONSTRUCTOR                               28
1658 #define DUK_BIDX_TYPE_ERROR_PROTOTYPE                                 29
1659 #define DUK_BIDX_URI_ERROR_CONSTRUCTOR                                30
1660 #define DUK_BIDX_URI_ERROR_PROTOTYPE                                  31
1661 #define DUK_BIDX_MATH                                                 32
1662 #define DUK_BIDX_JSON                                                 33
1663 #define DUK_BIDX_TYPE_ERROR_THROWER                                   34
1664 #define DUK_BIDX_PROXY_CONSTRUCTOR                                    35
1665 #define DUK_BIDX_DUKTAPE                                              36
1666 #define DUK_BIDX_THREAD_CONSTRUCTOR                                   37
1667 #define DUK_BIDX_THREAD_PROTOTYPE                                     38
1668 #define DUK_BIDX_BUFFER_CONSTRUCTOR                                   39
1669 #define DUK_BIDX_BUFFER_PROTOTYPE                                     40
1670 #define DUK_BIDX_POINTER_CONSTRUCTOR                                  41
1671 #define DUK_BIDX_POINTER_PROTOTYPE                                    42
1672 #define DUK_BIDX_LOGGER_CONSTRUCTOR                                   43
1673 #define DUK_BIDX_LOGGER_PROTOTYPE                                     44
1674 #define DUK_BIDX_DOUBLE_ERROR                                         45
1675 #define DUK_BIDX_ARRAYBUFFER_CONSTRUCTOR                              46
1676 #define DUK_BIDX_ARRAYBUFFER_PROTOTYPE                                47
1677 #define DUK_BIDX_DATAVIEW_CONSTRUCTOR                                 48
1678 #define DUK_BIDX_DATAVIEW_PROTOTYPE                                   49
1679 #define DUK_BIDX_TYPEDARRAY_PROTOTYPE                                 50
1680 #define DUK_BIDX_INT8ARRAY_CONSTRUCTOR                                51
1681 #define DUK_BIDX_INT8ARRAY_PROTOTYPE                                  52
1682 #define DUK_BIDX_UINT8ARRAY_CONSTRUCTOR                               53
1683 #define DUK_BIDX_UINT8ARRAY_PROTOTYPE                                 54
1684 #define DUK_BIDX_UINT8CLAMPEDARRAY_CONSTRUCTOR                        55
1685 #define DUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE                          56
1686 #define DUK_BIDX_INT16ARRAY_CONSTRUCTOR                               57
1687 #define DUK_BIDX_INT16ARRAY_PROTOTYPE                                 58
1688 #define DUK_BIDX_UINT16ARRAY_CONSTRUCTOR                              59
1689 #define DUK_BIDX_UINT16ARRAY_PROTOTYPE                                60
1690 #define DUK_BIDX_INT32ARRAY_CONSTRUCTOR                               61
1691 #define DUK_BIDX_INT32ARRAY_PROTOTYPE                                 62
1692 #define DUK_BIDX_UINT32ARRAY_CONSTRUCTOR                              63
1693 #define DUK_BIDX_UINT32ARRAY_PROTOTYPE                                64
1694 #define DUK_BIDX_FLOAT32ARRAY_CONSTRUCTOR                             65
1695 #define DUK_BIDX_FLOAT32ARRAY_PROTOTYPE                               66
1696 #define DUK_BIDX_FLOAT64ARRAY_CONSTRUCTOR                             67
1697 #define DUK_BIDX_FLOAT64ARRAY_PROTOTYPE                               68
1698 #define DUK_BIDX_NODEJS_BUFFER_CONSTRUCTOR                            69
1699 #define DUK_BIDX_NODEJS_BUFFER_PROTOTYPE                              70
1700 #define DUK_NUM_BUILTINS                                              71
1701 #define DUK_NUM_BIDX_BUILTINS                                         71
1702 #define DUK_NUM_ALL_BUILTINS                                          71
1703 #if defined(DUK_USE_DOUBLE_LE)
1704 #if !defined(DUK_SINGLE_FILE)
1705 DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[3833];
1706 #endif  /* !DUK_SINGLE_FILE */
1707 #define DUK_BUILTINS_DATA_LENGTH                                      3833
1708 #elif defined(DUK_USE_DOUBLE_BE)
1709 #if !defined(DUK_SINGLE_FILE)
1710 DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[3833];
1711 #endif  /* !DUK_SINGLE_FILE */
1712 #define DUK_BUILTINS_DATA_LENGTH                                      3833
1713 #elif defined(DUK_USE_DOUBLE_ME)
1714 #if !defined(DUK_SINGLE_FILE)
1715 DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[3833];
1716 #endif  /* !DUK_SINGLE_FILE */
1717 #define DUK_BUILTINS_DATA_LENGTH                                      3833
1718 #else
1719 #error invalid endianness defines
1720 #endif
1721 #endif  /* DUK_USE_ROM_OBJECTS */
1722 #endif  /* DUK_BUILTINS_H_INCLUDED */
1723 
1724 /*
1725  *  Utilities
1726  */
1727 
1728 #ifndef DUK_UTIL_H_INCLUDED
1729 #define DUK_UTIL_H_INCLUDED
1730 
1731 #define DUK_UTIL_MIN_HASH_PRIME  17  /* must match genhashsizes.py */
1732 
1733 #define DUK_UTIL_GET_HASH_PROBE_STEP(hash)  (duk_util_probe_steps[(hash) & 0x1f])
1734 
1735 /*
1736  *  Endian conversion
1737  */
1738 
1739 #if defined(DUK_USE_INTEGER_LE)
1740 #define DUK_HTON32(x) DUK_BSWAP32((x))
1741 #define DUK_NTOH32(x) DUK_BSWAP32((x))
1742 #define DUK_HTON16(x) DUK_BSWAP16((x))
1743 #define DUK_NTOH16(x) DUK_BSWAP16((x))
1744 #elif defined(DUK_USE_INTEGER_BE)
1745 #define DUK_HTON32(x) (x)
1746 #define DUK_NTOH32(x) (x)
1747 #define DUK_HTON16(x) (x)
1748 #define DUK_NTOH16(x) (x)
1749 #else
1750 #error internal error, endianness defines broken
1751 #endif
1752 
1753 /*
1754  *  Bitstream decoder
1755  */
1756 
1757 struct duk_bitdecoder_ctx {
1758 	const duk_uint8_t *data;
1759 	duk_size_t offset;
1760 	duk_size_t length;
1761 	duk_uint32_t currval;
1762 	duk_small_int_t currbits;
1763 };
1764 
1765 /*
1766  *  Bitstream encoder
1767  */
1768 
1769 struct duk_bitencoder_ctx {
1770 	duk_uint8_t *data;
1771 	duk_size_t offset;
1772 	duk_size_t length;
1773 	duk_uint32_t currval;
1774 	duk_small_int_t currbits;
1775 	duk_small_int_t truncated;
1776 };
1777 
1778 /*
1779  *  Raw write/read macros for big endian, unaligned basic values.
1780  *  Caller ensures there's enough space.  The macros update the pointer
1781  *  argument automatically on resizes.  The idiom seems a bit odd, but
1782  *  leads to compact code.
1783  */
1784 
1785 #define DUK_RAW_WRITE_U8(ptr,val)  do { \
1786 		*(ptr)++ = (duk_uint8_t) (val); \
1787 	} while (0)
1788 #define DUK_RAW_WRITE_U16_BE(ptr,val) duk_raw_write_u16_be(&(ptr), (duk_uint16_t) (val))
1789 #define DUK_RAW_WRITE_U32_BE(ptr,val) duk_raw_write_u32_be(&(ptr), (duk_uint32_t) (val))
1790 #define DUK_RAW_WRITE_DOUBLE_BE(ptr,val) duk_raw_write_double_be(&(ptr), (duk_double_t) (val))
1791 #define DUK_RAW_WRITE_XUTF8(ptr,val)  do { \
1792 		/* 'ptr' is evaluated both as LHS and RHS. */ \
1793 		duk_uint8_t *duk__ptr; \
1794 		duk_small_int_t duk__len; \
1795 		duk__ptr = (duk_uint8_t *) (ptr); \
1796 		duk__len = duk_unicode_encode_xutf8((duk_ucodepoint_t) (val), duk__ptr); \
1797 		duk__ptr += duk__len; \
1798 		(ptr) = duk__ptr; \
1799 	} while (0)
1800 #define DUK_RAW_WRITE_CESU8(ptr,val)  do { \
1801 		/* 'ptr' is evaluated both as LHS and RHS. */ \
1802 		duk_uint8_t *duk__ptr; \
1803 		duk_small_int_t duk__len; \
1804 		duk__ptr = (duk_uint8_t *) (ptr); \
1805 		duk__len = duk_unicode_encode_cesu8((duk_ucodepoint_t) (val), duk__ptr); \
1806 		duk__ptr += duk__len; \
1807 		(ptr) = duk__ptr; \
1808 	} while (0)
1809 
1810 #define DUK_RAW_READ_U8(ptr) ((duk_uint8_t) (*(ptr)++))
1811 #define DUK_RAW_READ_U16_BE(ptr) duk_raw_read_u16_be(&(ptr));
1812 #define DUK_RAW_READ_U32_BE(ptr) duk_raw_read_u32_be(&(ptr));
1813 #define DUK_RAW_READ_DOUBLE_BE(ptr) duk_raw_read_double_be(&(ptr));
1814 
1815 /*
1816  *  Buffer writer (dynamic buffer only)
1817  *
1818  *  Helper for writing to a dynamic buffer with a concept of a "spare" area
1819  *  to reduce resizes.  You can ensure there is enough space beforehand and
1820  *  then write for a while without further checks, relying on a stable data
1821  *  pointer.  Spare handling is automatic so call sites only indicate how
1822  *  much data they need right now.
1823  *
1824  *  There are several ways to write using bufwriter.  The best approach
1825  *  depends mainly on how much performance matters over code footprint.
1826  *  The key issues are (1) ensuring there is space and (2) keeping the
1827  *  pointers consistent.  Fast code should ensure space for multiple writes
1828  *  with one ensure call.  Fastest inner loop code can temporarily borrow
1829  *  the 'p' pointer but must write it back eventually.
1830  *
1831  *  Be careful to ensure all macro arguments (other than static pointers like
1832  *  'thr' and 'bw_ctx') are evaluated exactly once, using temporaries if
1833  *  necessary (if that's not possible, there should be a note near the macro).
1834  *  Buffer write arguments often contain arithmetic etc so this is
1835  *  particularly important here.
1836  */
1837 
1838 /* XXX: Migrate bufwriter and other read/write helpers to its own header? */
1839 
1840 struct duk_bufwriter_ctx {
1841 	duk_uint8_t *p;
1842 	duk_uint8_t *p_base;
1843 	duk_uint8_t *p_limit;
1844 	duk_hbuffer_dynamic *buf;
1845 };
1846 
1847 #define DUK_BW_SPARE_ADD           64
1848 #define DUK_BW_SPARE_SHIFT         4    /* 2^4 -> 1/16 = 6.25% spare */
1849 
1850 /* Initialization and finalization (compaction), converting to other types. */
1851 
1852 #define DUK_BW_INIT_PUSHBUF(thr,bw_ctx,sz) do { \
1853 		duk_bw_init_pushbuf((thr), (bw_ctx), (sz)); \
1854 	} while (0)
1855 #define DUK_BW_INIT_WITHBUF(thr,bw_ctx,buf) do { \
1856 		duk_bw_init((thr), (bw_ctx), (buf)); \
1857 	} while (0)
1858 #define DUK_BW_COMPACT(thr,bw_ctx) do { \
1859 		/* Make underlying buffer compact to match DUK_BW_GET_SIZE(). */ \
1860 		duk_bw_compact((thr), (bw_ctx)); \
1861 	} while (0)
1862 #define DUK_BW_PUSH_AS_STRING(thr,bw_ctx) do { \
1863 		duk_push_lstring((duk_context *) (thr), \
1864 		                 (const char *) (bw_ctx)->p_base, \
1865 		                 (duk_size_t) ((bw_ctx)->p - (bw_ctx)->p_base)); \
1866 	} while (0)
1867 /* Pointers may be NULL for a while when 'buf' size is zero and before any
1868  * ENSURE calls have been made.  Once an ENSURE has been made, the pointers
1869  * are required to be non-NULL so that it's always valid to use memcpy() and
1870  * memmove(), even for zero size.
1871  */
1872 #define DUK_BW_ASSERT_VALID_EXPR(thr,bw_ctx) \
1873 	DUK_ASSERT_EXPR((bw_ctx) != NULL && \
1874 	                (bw_ctx)->buf != NULL && \
1875 			((DUK_HBUFFER_DYNAMIC_GET_SIZE((bw_ctx)->buf) == 0) || \
1876 				((bw_ctx)->p != NULL && \
1877 		                 (bw_ctx)->p_base != NULL && \
1878 		                 (bw_ctx)->p_limit != NULL && \
1879 		                 (bw_ctx)->p_limit >= (bw_ctx)->p_base && \
1880 		                 (bw_ctx)->p >= (bw_ctx)->p_base && \
1881 		                 (bw_ctx)->p <= (bw_ctx)->p_limit)))
1882 #define DUK_BW_ASSERT_VALID(thr,bw_ctx) do { \
1883 		DUK_BW_ASSERT_VALID_EXPR((thr), (bw_ctx)); \
1884 	} while (0)
1885 
1886 /* Working with the pointer and current size. */
1887 
1888 #define DUK_BW_GET_PTR(thr,bw_ctx) \
1889 	((bw_ctx)->p)
1890 #define DUK_BW_SET_PTR(thr,bw_ctx,ptr) do { \
1891 		(bw_ctx)->p = (ptr); \
1892 	} while (0)
1893 #define DUK_BW_ADD_PTR(thr,bw_ctx,delta) do { \
1894 		(bw_ctx)->p += (delta); \
1895 	} while (0)
1896 #define DUK_BW_GET_BASEPTR(thr,bw_ctx) \
1897 	((bw_ctx)->p_base)
1898 #define DUK_BW_GET_LIMITPTR(thr,bw_ctx) \
1899 	((bw_ctx)->p_limit)
1900 #define DUK_BW_GET_SIZE(thr,bw_ctx) \
1901 	((duk_size_t) ((bw_ctx)->p - (bw_ctx)->p_base))
1902 #define DUK_BW_SET_SIZE(thr,bw_ctx,sz) do { \
1903 		DUK_ASSERT((duk_size_t) (sz) <= (duk_size_t) ((bw_ctx)->p - (bw_ctx)->p_base)); \
1904 		(bw_ctx)->p = (bw_ctx)->p_base + (sz); \
1905 	} while (0)
1906 #define DUK_BW_RESET_SIZE(thr,bw_ctx) do { \
1907 		/* Reset to zero size, keep current limit. */ \
1908 		(bw_ctx)->p = (bw_ctx)->p_base; \
1909 	} while (0)
1910 #define DUK_BW_GET_BUFFER(thr,bw_ctx) \
1911 	((bw_ctx)->buf)
1912 
1913 /* Ensuring (reserving) space. */
1914 
1915 #define DUK_BW_ENSURE(thr,bw_ctx,sz) do { \
1916 		duk_size_t duk__sz, duk__space; \
1917 		DUK_BW_ASSERT_VALID((thr), (bw_ctx)); \
1918 		duk__sz = (sz); \
1919 		duk__space = (duk_size_t) ((bw_ctx)->p_limit - (bw_ctx)->p); \
1920 		if (duk__space < duk__sz) { \
1921 			(void) duk_bw_resize((thr), (bw_ctx), duk__sz); \
1922 		} \
1923 	} while (0)
1924 /* NOTE: Multiple evaluation of 'ptr' in this macro. */
1925 /* XXX: Rework to use an always-inline function? */
1926 #define DUK_BW_ENSURE_RAW(thr,bw_ctx,sz,ptr) \
1927 	(((duk_size_t) ((bw_ctx)->p_limit - (ptr)) >= (sz)) ? \
1928 	 (ptr) : \
1929 	 ((bw_ctx)->p = (ptr), duk_bw_resize((thr),(bw_ctx),(sz))))
1930 #define DUK_BW_ENSURE_GETPTR(thr,bw_ctx,sz) \
1931 	DUK_BW_ENSURE_RAW((thr), (bw_ctx), (sz), (bw_ctx)->p)
1932 #define DUK_BW_ASSERT_SPACE_EXPR(thr,bw_ctx,sz) \
1933 	(DUK_BW_ASSERT_VALID_EXPR((thr), (bw_ctx)), \
1934 	 DUK_ASSERT_EXPR((duk_size_t) ((bw_ctx)->p_limit - (bw_ctx)->p) >= (duk_size_t) (sz)))
1935 #define DUK_BW_ASSERT_SPACE(thr,bw_ctx,sz) do { \
1936 		DUK_BW_ASSERT_SPACE_EXPR((thr), (bw_ctx), (sz)); \
1937 	} while (0)
1938 
1939 /* Miscellaneous. */
1940 
1941 #define DUK_BW_SETPTR_AND_COMPACT(thr,bw_ctx,ptr) do { \
1942 		(bw_ctx)->p = (ptr); \
1943 		duk_bw_compact((thr), (bw_ctx)); \
1944 	} while (0)
1945 
1946 /* Fast write calls which assume you control the spare beforehand.
1947  * Multibyte write variants exist and use a temporary write pointer
1948  * because byte writes alias with anything: with a stored pointer
1949  * explicit pointer load/stores get generated (e.g. gcc -Os).
1950  */
1951 
1952 #define DUK_BW_WRITE_RAW_U8(thr,bw_ctx,val) do { \
1953 		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 1); \
1954 		*(bw_ctx)->p++ = (duk_uint8_t) (val); \
1955 	} while (0)
1956 #define DUK_BW_WRITE_RAW_U8_2(thr,bw_ctx,val1,val2) do { \
1957 		duk_uint8_t *duk__p; \
1958 		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 2); \
1959 		duk__p = (bw_ctx)->p; \
1960 		*duk__p++ = (duk_uint8_t) (val1); \
1961 		*duk__p++ = (duk_uint8_t) (val2); \
1962 		(bw_ctx)->p = duk__p; \
1963 	} while (0)
1964 #define DUK_BW_WRITE_RAW_U8_3(thr,bw_ctx,val1,val2,val3) do { \
1965 		duk_uint8_t *duk__p; \
1966 		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 3); \
1967 		duk__p = (bw_ctx)->p; \
1968 		*duk__p++ = (duk_uint8_t) (val1); \
1969 		*duk__p++ = (duk_uint8_t) (val2); \
1970 		*duk__p++ = (duk_uint8_t) (val3); \
1971 		(bw_ctx)->p = duk__p; \
1972 	} while (0)
1973 #define DUK_BW_WRITE_RAW_U8_4(thr,bw_ctx,val1,val2,val3,val4) do { \
1974 		duk_uint8_t *duk__p; \
1975 		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 4); \
1976 		duk__p = (bw_ctx)->p; \
1977 		*duk__p++ = (duk_uint8_t) (val1); \
1978 		*duk__p++ = (duk_uint8_t) (val2); \
1979 		*duk__p++ = (duk_uint8_t) (val3); \
1980 		*duk__p++ = (duk_uint8_t) (val4); \
1981 		(bw_ctx)->p = duk__p; \
1982 	} while (0)
1983 #define DUK_BW_WRITE_RAW_U8_5(thr,bw_ctx,val1,val2,val3,val4,val5) do { \
1984 		duk_uint8_t *duk__p; \
1985 		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 5); \
1986 		duk__p = (bw_ctx)->p; \
1987 		*duk__p++ = (duk_uint8_t) (val1); \
1988 		*duk__p++ = (duk_uint8_t) (val2); \
1989 		*duk__p++ = (duk_uint8_t) (val3); \
1990 		*duk__p++ = (duk_uint8_t) (val4); \
1991 		*duk__p++ = (duk_uint8_t) (val5); \
1992 		(bw_ctx)->p = duk__p; \
1993 	} while (0)
1994 #define DUK_BW_WRITE_RAW_U8_6(thr,bw_ctx,val1,val2,val3,val4,val5,val6) do { \
1995 		duk_uint8_t *duk__p; \
1996 		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 6); \
1997 		duk__p = (bw_ctx)->p; \
1998 		*duk__p++ = (duk_uint8_t) (val1); \
1999 		*duk__p++ = (duk_uint8_t) (val2); \
2000 		*duk__p++ = (duk_uint8_t) (val3); \
2001 		*duk__p++ = (duk_uint8_t) (val4); \
2002 		*duk__p++ = (duk_uint8_t) (val5); \
2003 		*duk__p++ = (duk_uint8_t) (val6); \
2004 		(bw_ctx)->p = duk__p; \
2005 	} while (0)
2006 #define DUK_BW_WRITE_RAW_XUTF8(thr,bw_ctx,cp) do { \
2007 		duk_ucodepoint_t duk__cp; \
2008 		duk_small_int_t duk__enc_len; \
2009 		duk__cp = (cp); \
2010 		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), duk_unicode_get_xutf8_length(duk__cp)); \
2011 		duk__enc_len = duk_unicode_encode_xutf8(duk__cp, (bw_ctx)->p); \
2012 		(bw_ctx)->p += duk__enc_len; \
2013 	} while (0)
2014 #define DUK_BW_WRITE_RAW_CESU8(thr,bw_ctx,cp) do { \
2015 		duk_ucodepoint_t duk__cp; \
2016 		duk_small_int_t duk__enc_len; \
2017 		duk__cp = (duk_ucodepoint_t) (cp); \
2018 		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), duk_unicode_get_cesu8_length(duk__cp)); \
2019 		duk__enc_len = duk_unicode_encode_cesu8(duk__cp, (bw_ctx)->p); \
2020 		(bw_ctx)->p += duk__enc_len; \
2021 	} while (0)
2022 /* XXX: add temporary duk__p pointer here too; sharing */
2023 #define DUK_BW_WRITE_RAW_BYTES(thr,bw_ctx,valptr,valsz) do { \
2024 		const void *duk__valptr; \
2025 		duk_size_t duk__valsz; \
2026 		duk__valptr = (const void *) (valptr); \
2027 		duk__valsz = (duk_size_t) (valsz); \
2028 		DUK_MEMCPY((void *) ((bw_ctx)->p), duk__valptr, duk__valsz); \
2029 		(bw_ctx)->p += duk__valsz; \
2030 	} while (0)
2031 #define DUK_BW_WRITE_RAW_CSTRING(thr,bw_ctx,val) do { \
2032 		const duk_uint8_t *duk__val; \
2033 		duk_size_t duk__val_len; \
2034 		duk__val = (const duk_uint8_t *) (val); \
2035 		duk__val_len = DUK_STRLEN((const char *) duk__val); \
2036 		DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) duk__val, duk__val_len); \
2037 		(bw_ctx)->p += duk__val_len; \
2038 	} while (0)
2039 #define DUK_BW_WRITE_RAW_HSTRING(thr,bw_ctx,val) do { \
2040 		duk_size_t duk__val_len; \
2041 		duk__val_len = DUK_HSTRING_GET_BYTELEN((val)); \
2042 		DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HSTRING_GET_DATA((val)), duk__val_len); \
2043 		(bw_ctx)->p += duk__val_len; \
2044 	} while (0)
2045 #define DUK_BW_WRITE_RAW_HBUFFER(thr,bw_ctx,val) do { \
2046 		duk_size_t duk__val_len; \
2047 		duk__val_len = DUK_HBUFFER_GET_SIZE((val)); \
2048 		DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
2049 		(bw_ctx)->p += duk__val_len; \
2050 	} while (0)
2051 #define DUK_BW_WRITE_RAW_HBUFFER_FIXED(thr,bw_ctx,val) do { \
2052 		duk_size_t duk__val_len; \
2053 		duk__val_len = DUK_HBUFFER_FIXED_GET_SIZE((val)); \
2054 		DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_FIXED_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
2055 		(bw_ctx)->p += duk__val_len; \
2056 	} while (0)
2057 #define DUK_BW_WRITE_RAW_HBUFFER_DYNAMIC(thr,bw_ctx,val) do { \
2058 		duk_size_t duk__val_len; \
2059 		duk__val_len = DUK_HBUFFER_DYNAMIC_GET_SIZE((val)); \
2060 		DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
2061 		(bw_ctx)->p += duk__val_len; \
2062 	} while (0)
2063 
2064 /* Append bytes from a slice already in the buffer. */
2065 #define DUK_BW_WRITE_RAW_SLICE(thr,bw,dst_off,dst_len) \
2066 	duk_bw_write_raw_slice((thr), (bw), (dst_off), (dst_len))
2067 
2068 /* Insert bytes in the middle of the buffer from an external buffer. */
2069 #define DUK_BW_INSERT_RAW_BYTES(thr,bw,dst_off,buf,len) \
2070 	duk_bw_insert_raw_bytes((thr), (bw), (dst_off), (buf), (len))
2071 
2072 /* Insert bytes in the middle of the buffer from a slice already
2073  * in the buffer.  Source offset is interpreted "before" the operation.
2074  */
2075 #define DUK_BW_INSERT_RAW_SLICE(thr,bw,dst_off,src_off,len) \
2076 	duk_bw_insert_raw_slice((thr), (bw), (dst_off), (src_off), (len))
2077 
2078 /* Insert a reserved area somewhere in the buffer; caller fills it.
2079  * Evaluates to a (duk_uint_t *) pointing to the start of the reserved
2080  * area for convenience.
2081  */
2082 #define DUK_BW_INSERT_RAW_AREA(thr,bw,off,len) \
2083 	duk_bw_insert_raw_area((thr), (bw), (off), (len))
2084 
2085 /* Remove a slice from inside buffer. */
2086 #define DUK_BW_REMOVE_RAW_SLICE(thr,bw,off,len) \
2087 	duk_bw_remove_raw_slice((thr), (bw), (off), (len))
2088 
2089 /* Safe write calls which will ensure space first. */
2090 
2091 #define DUK_BW_WRITE_ENSURE_U8(thr,bw_ctx,val) do { \
2092 		DUK_BW_ENSURE((thr), (bw_ctx), 1); \
2093 		DUK_BW_WRITE_RAW_U8((thr), (bw_ctx), (val)); \
2094 	} while (0)
2095 #define DUK_BW_WRITE_ENSURE_U8_2(thr,bw_ctx,val1,val2) do { \
2096 		DUK_BW_ENSURE((thr), (bw_ctx), 2); \
2097 		DUK_BW_WRITE_RAW_U8_2((thr), (bw_ctx), (val1), (val2)); \
2098 	} while (0)
2099 #define DUK_BW_WRITE_ENSURE_U8_3(thr,bw_ctx,val1,val2,val3) do { \
2100 		DUK_BW_ENSURE((thr), (bw_ctx), 3); \
2101 		DUK_BW_WRITE_RAW_U8_3((thr), (bw_ctx), (val1), (val2), (val3)); \
2102 	} while (0)
2103 #define DUK_BW_WRITE_ENSURE_U8_4(thr,bw_ctx,val1,val2,val3,val4) do { \
2104 		DUK_BW_ENSURE((thr), (bw_ctx), 4); \
2105 		DUK_BW_WRITE_RAW_U8_4((thr), (bw_ctx), (val1), (val2), (val3), (val4)); \
2106 	} while (0)
2107 #define DUK_BW_WRITE_ENSURE_U8_5(thr,bw_ctx,val1,val2,val3,val4,val5) do { \
2108 		DUK_BW_ENSURE((thr), (bw_ctx), 5); \
2109 		DUK_BW_WRITE_RAW_U8_5((thr), (bw_ctx), (val1), (val2), (val3), (val4), (val5)); \
2110 	} while (0)
2111 #define DUK_BW_WRITE_ENSURE_U8_6(thr,bw_ctx,val1,val2,val3,val4,val5,val6) do { \
2112 		DUK_BW_ENSURE((thr), (bw_ctx), 6); \
2113 		DUK_BW_WRITE_RAW_U8_6((thr), (bw_ctx), (val1), (val2), (val3), (val4), (val5), (val6)); \
2114 	} while (0)
2115 #define DUK_BW_WRITE_ENSURE_XUTF8(thr,bw_ctx,cp) do { \
2116 		DUK_BW_ENSURE((thr), (bw_ctx), DUK_UNICODE_MAX_XUTF8_LENGTH); \
2117 		DUK_BW_WRITE_RAW_XUTF8((thr), (bw_ctx), (cp)); \
2118 	} while (0)
2119 #define DUK_BW_WRITE_ENSURE_CESU8(thr,bw_ctx,cp) do { \
2120 		DUK_BW_ENSURE((thr), (bw_ctx), DUK_UNICODE_MAX_CESU8_LENGTH); \
2121 		DUK_BW_WRITE_RAW_CESU8((thr), (bw_ctx), (cp)); \
2122 	} while (0)
2123 /* XXX: add temporary duk__p pointer here too; sharing */
2124 #define DUK_BW_WRITE_ENSURE_BYTES(thr,bw_ctx,valptr,valsz) do { \
2125 		const void *duk__valptr; \
2126 		duk_size_t duk__valsz; \
2127 		duk__valptr = (const void *) (valptr); \
2128 		duk__valsz = (duk_size_t) (valsz); \
2129 		DUK_BW_ENSURE((thr), (bw_ctx), duk__valsz); \
2130 		DUK_MEMCPY((void *) ((bw_ctx)->p), duk__valptr, duk__valsz); \
2131 		(bw_ctx)->p += duk__valsz; \
2132 	} while (0)
2133 #define DUK_BW_WRITE_ENSURE_CSTRING(thr,bw_ctx,val) do { \
2134 		const duk_uint8_t *duk__val; \
2135 		duk_size_t duk__val_len; \
2136 		duk__val = (const duk_uint8_t *) (val); \
2137 		duk__val_len = DUK_STRLEN((const char *) duk__val); \
2138 		DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
2139 		DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) duk__val, duk__val_len); \
2140 		(bw_ctx)->p += duk__val_len; \
2141 	} while (0)
2142 #define DUK_BW_WRITE_ENSURE_HSTRING(thr,bw_ctx,val) do { \
2143 		duk_size_t duk__val_len; \
2144 		duk__val_len = DUK_HSTRING_GET_BYTELEN((val)); \
2145 		DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
2146 		DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HSTRING_GET_DATA((val)), duk__val_len); \
2147 		(bw_ctx)->p += duk__val_len; \
2148 	} while (0)
2149 #define DUK_BW_WRITE_ENSURE_HBUFFER(thr,bw_ctx,val) do { \
2150 		duk_size_t duk__val_len; \
2151 		duk__val_len = DUK_HBUFFER_GET_SIZE((val)); \
2152 		DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
2153 		DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
2154 		(bw_ctx)->p += duk__val_len; \
2155 	} while (0)
2156 #define DUK_BW_WRITE_ENSURE_HBUFFER_FIXED(thr,bw_ctx,val) do { \
2157 		duk_size_t duk__val_len; \
2158 		duk__val_len = DUK_HBUFFER_FIXED_GET_SIZE((val)); \
2159 		DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
2160 		DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_FIXED_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
2161 		(bw_ctx)->p += duk__val_len; \
2162 	} while (0)
2163 #define DUK_BW_WRITE_ENSURE_HBUFFER_DYNAMIC(thr,bw_ctx,val) do { \
2164 		duk_size_t duk__val_len; \
2165 		duk__val_len = DUK_HBUFFER_DYNAMIC_GET_SIZE((val)); \
2166 		DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
2167 		DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
2168 		(bw_ctx)->p += duk__val_len; \
2169 	} while (0)
2170 
2171 #define DUK_BW_WRITE_ENSURE_SLICE(thr,bw,dst_off,dst_len) \
2172 	duk_bw_write_ensure_slice((thr), (bw), (dst_off), (dst_len))
2173 #define DUK_BW_INSERT_ENSURE_BYTES(thr,bw,dst_off,buf,len) \
2174 	duk_bw_insert_ensure_bytes((thr), (bw), (dst_off), (buf), (len))
2175 #define DUK_BW_INSERT_ENSURE_SLICE(thr,bw,dst_off,src_off,len) \
2176 	duk_bw_insert_ensure_slice((thr), (bw), (dst_off), (src_off), (len))
2177 #define DUK_BW_INSERT_ENSURE_AREA(thr,bw,off,len) \
2178 	/* Evaluates to (duk_uint8_t *) pointing to start of area. */ \
2179 	duk_bw_insert_ensure_area((thr), (bw), (off), (len))
2180 #define DUK_BW_REMOVE_ENSURE_SLICE(thr,bw,off,len) \
2181 	/* No difference between raw/ensure because the buffer shrinks. */ \
2182 	DUK_BW_REMOVE_RAW_SLICE((thr), (bw), (off), (len))
2183 
2184 /*
2185  *  Externs and prototypes
2186  */
2187 
2188 #if !defined(DUK_SINGLE_FILE)
2189 DUK_INTERNAL_DECL const duk_uint8_t duk_lc_digits[36];
2190 DUK_INTERNAL_DECL const duk_uint8_t duk_uc_nybbles[16];
2191 DUK_INTERNAL_DECL const duk_int8_t duk_hex_dectab[256];
2192 #if defined(DUK_USE_HEX_FASTPATH)
2193 DUK_INTERNAL_DECL const duk_int16_t duk_hex_dectab_shift4[256];
2194 DUK_INTERNAL_DECL const duk_uint16_t duk_hex_enctab[256];
2195 #endif
2196 #if defined(DUK_USE_BASE64_FASTPATH)
2197 DUK_INTERNAL_DECL const duk_uint8_t duk_base64_enctab[64];
2198 DUK_INTERNAL_DECL const duk_int8_t duk_base64_dectab[256];
2199 #endif
2200 #endif  /* !DUK_SINGLE_FILE */
2201 
2202 /* Note: assumes that duk_util_probe_steps size is 32 */
2203 #if defined(DUK_USE_HOBJECT_HASH_PART) || defined(DUK_USE_STRTAB_PROBE)
2204 #if !defined(DUK_SINGLE_FILE)
2205 DUK_INTERNAL_DECL duk_uint8_t duk_util_probe_steps[32];
2206 #endif  /* !DUK_SINGLE_FILE */
2207 #endif
2208 
2209 #if defined(DUK_USE_STRHASH_DENSE)
2210 DUK_INTERNAL_DECL duk_uint32_t duk_util_hashbytes(const duk_uint8_t *data, duk_size_t len, duk_uint32_t seed);
2211 #endif
2212 
2213 #if defined(DUK_USE_HOBJECT_HASH_PART) || defined(DUK_USE_STRTAB_PROBE)
2214 DUK_INTERNAL_DECL duk_uint32_t duk_util_get_hash_prime(duk_uint32_t size);
2215 #endif
2216 
2217 DUK_INTERNAL_DECL duk_int32_t duk_bd_decode(duk_bitdecoder_ctx *ctx, duk_small_int_t bits);
2218 DUK_INTERNAL_DECL duk_small_int_t duk_bd_decode_flag(duk_bitdecoder_ctx *ctx);
2219 DUK_INTERNAL_DECL duk_int32_t duk_bd_decode_flagged(duk_bitdecoder_ctx *ctx, duk_small_int_t bits, duk_int32_t def_value);
2220 
2221 DUK_INTERNAL_DECL void duk_be_encode(duk_bitencoder_ctx *ctx, duk_uint32_t data, duk_small_int_t bits);
2222 DUK_INTERNAL_DECL void duk_be_finish(duk_bitencoder_ctx *ctx);
2223 
2224 DUK_INTERNAL_DECL duk_uint32_t duk_util_tinyrandom_get_bits(duk_hthread *thr, duk_small_int_t n);
2225 DUK_INTERNAL_DECL duk_double_t duk_util_tinyrandom_get_double(duk_hthread *thr);
2226 
2227 DUK_INTERNAL_DECL void duk_bw_init(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_hbuffer_dynamic *h_buf);
2228 DUK_INTERNAL_DECL void duk_bw_init_pushbuf(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t buf_size);
2229 DUK_INTERNAL_DECL duk_uint8_t *duk_bw_resize(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t sz);
2230 DUK_INTERNAL_DECL void duk_bw_compact(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx);
2231 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);
2232 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);
2233 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);
2234 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);
2235 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);
2236 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);
2237 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);
2238 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);
2239 DUK_INTERNAL_DECL void duk_bw_remove_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len);
2240 /* No duk_bw_remove_ensure_slice(), functionality would be identical. */
2241 
2242 DUK_INTERNAL_DECL duk_uint16_t duk_raw_read_u16_be(duk_uint8_t **p);
2243 DUK_INTERNAL_DECL duk_uint32_t duk_raw_read_u32_be(duk_uint8_t **p);
2244 DUK_INTERNAL_DECL duk_double_t duk_raw_read_double_be(duk_uint8_t **p);
2245 DUK_INTERNAL_DECL void duk_raw_write_u16_be(duk_uint8_t **p, duk_uint16_t val);
2246 DUK_INTERNAL_DECL void duk_raw_write_u32_be(duk_uint8_t **p, duk_uint32_t val);
2247 DUK_INTERNAL_DECL void duk_raw_write_double_be(duk_uint8_t **p, duk_double_t val);
2248 
2249 #if defined(DUK_USE_DEBUGGER_SUPPORT)  /* For now only needed by the debugger. */
2250 DUK_INTERNAL void duk_byteswap_bytes(duk_uint8_t *p, duk_small_uint_t len);
2251 #endif
2252 
2253 #endif  /* DUK_UTIL_H_INCLUDED */
2254 /*
2255  *  Shared error messages: declarations and macros
2256  *
2257  *  Error messages are accessed through macros with fine-grained, explicit
2258  *  error message distinctions.  Concrete error messages are selected by the
2259  *  macros and multiple macros can map to the same concrete string to save
2260  *  on code footprint.  This allows flexible footprint/verbosity tuning with
2261  *  minimal code impact.  There are a few limitations to this approach:
2262  *  (1) switching between plain messages and format strings doesn't work
2263  *  conveniently, and (2) conditional strings are a bit awkward to handle.
2264  *
2265  *  Because format strings behave differently in the call site (they need to
2266  *  be followed by format arguments), they have a special prefix (DUK_STR_FMT_
2267  *  and duk_str_fmt_).
2268  *
2269  *  On some compilers using explicit shared strings is preferable; on others
2270  *  it may be better to use straight literals because the compiler will combine
2271  *  them anyway, and such strings won't end up unnecessarily in a symbol table.
2272  */
2273 
2274 #ifndef DUK_ERRMSG_H_INCLUDED
2275 #define DUK_ERRMSG_H_INCLUDED
2276 
2277 #define DUK_STR_INTERNAL_ERROR duk_str_internal_error
2278 #define DUK_STR_INVALID_COUNT duk_str_invalid_count
2279 #define DUK_STR_INVALID_CALL_ARGS duk_str_invalid_call_args
2280 #define DUK_STR_NOT_CONSTRUCTABLE duk_str_not_constructable
2281 #define DUK_STR_NOT_CALLABLE duk_str_not_callable
2282 #define DUK_STR_NOT_EXTENSIBLE duk_str_not_extensible
2283 #define DUK_STR_NOT_WRITABLE duk_str_not_writable
2284 #define DUK_STR_NOT_CONFIGURABLE duk_str_not_configurable
2285 
2286 #if !defined(DUK_SINGLE_FILE)
2287 DUK_INTERNAL_DECL const char *duk_str_internal_error;
2288 DUK_INTERNAL_DECL const char *duk_str_invalid_count;
2289 DUK_INTERNAL_DECL const char *duk_str_invalid_call_args;
2290 DUK_INTERNAL_DECL const char *duk_str_not_constructable;
2291 DUK_INTERNAL_DECL const char *duk_str_not_callable;
2292 DUK_INTERNAL_DECL const char *duk_str_not_extensible;
2293 DUK_INTERNAL_DECL const char *duk_str_not_writable;
2294 DUK_INTERNAL_DECL const char *duk_str_not_configurable;
2295 #endif  /* !DUK_SINGLE_FILE */
2296 
2297 #define DUK_STR_INVALID_CONTEXT duk_str_invalid_context
2298 #define DUK_STR_INVALID_INDEX duk_str_invalid_call_args
2299 #define DUK_STR_PUSH_BEYOND_ALLOC_STACK duk_str_push_beyond_alloc_stack
2300 #define DUK_STR_NOT_UNDEFINED duk_str_unexpected_type
2301 #define DUK_STR_NOT_NULL duk_str_unexpected_type
2302 #define DUK_STR_NOT_BOOLEAN duk_str_unexpected_type
2303 #define DUK_STR_NOT_NUMBER duk_str_unexpected_type
2304 #define DUK_STR_NOT_STRING duk_str_unexpected_type
2305 #define DUK_STR_NOT_OBJECT duk_str_unexpected_type
2306 #define DUK_STR_NOT_POINTER duk_str_unexpected_type
2307 #define DUK_STR_NOT_BUFFER duk_str_not_buffer  /* still in use with verbose messages */
2308 #define DUK_STR_UNEXPECTED_TYPE duk_str_unexpected_type
2309 #define DUK_STR_NOT_THREAD duk_str_unexpected_type
2310 #define DUK_STR_NOT_COMPILEDFUNCTION duk_str_unexpected_type
2311 #define DUK_STR_NOT_NATIVEFUNCTION duk_str_unexpected_type
2312 #define DUK_STR_NOT_C_FUNCTION duk_str_unexpected_type
2313 #define DUK_STR_NOT_FUNCTION duk_str_unexpected_type
2314 #define DUK_STR_NOT_REGEXP duk_str_unexpected_type
2315 #define DUK_STR_DEFAULTVALUE_COERCE_FAILED duk_str_defaultvalue_coerce_failed
2316 #define DUK_STR_NUMBER_OUTSIDE_RANGE duk_str_number_outside_range
2317 #define DUK_STR_NOT_OBJECT_COERCIBLE duk_str_not_object_coercible
2318 #define DUK_STR_STRING_TOO_LONG duk_str_string_too_long
2319 #define DUK_STR_BUFFER_TOO_LONG duk_str_buffer_too_long
2320 #define DUK_STR_SPRINTF_TOO_LONG duk_str_sprintf_too_long
2321 #define DUK_STR_ALLOC_FAILED duk_str_alloc_failed
2322 #define DUK_STR_POP_TOO_MANY duk_str_pop_too_many
2323 #define DUK_STR_WRONG_BUFFER_TYPE duk_str_wrong_buffer_type
2324 #define DUK_STR_ENCODE_FAILED duk_str_encode_failed
2325 #define DUK_STR_DECODE_FAILED duk_str_decode_failed
2326 #define DUK_STR_NO_SOURCECODE duk_str_no_sourcecode
2327 #define DUK_STR_CONCAT_RESULT_TOO_LONG duk_str_concat_result_too_long
2328 #define DUK_STR_UNIMPLEMENTED duk_str_unimplemented
2329 #define DUK_STR_UNSUPPORTED duk_str_unsupported
2330 #define DUK_STR_ARRAY_LENGTH_OVER_2G duk_str_array_length_over_2g
2331 
2332 #if !defined(DUK_SINGLE_FILE)
2333 DUK_INTERNAL_DECL const char *duk_str_invalid_context;
2334 DUK_INTERNAL_DECL const char *duk_str_push_beyond_alloc_stack;
2335 DUK_INTERNAL_DECL const char *duk_str_not_buffer;
2336 DUK_INTERNAL_DECL const char *duk_str_unexpected_type;
2337 DUK_INTERNAL_DECL const char *duk_str_defaultvalue_coerce_failed;
2338 DUK_INTERNAL_DECL const char *duk_str_number_outside_range;
2339 DUK_INTERNAL_DECL const char *duk_str_not_object_coercible;
2340 DUK_INTERNAL_DECL const char *duk_str_string_too_long;
2341 DUK_INTERNAL_DECL const char *duk_str_buffer_too_long;
2342 DUK_INTERNAL_DECL const char *duk_str_sprintf_too_long;
2343 DUK_INTERNAL_DECL const char *duk_str_alloc_failed;
2344 DUK_INTERNAL_DECL const char *duk_str_pop_too_many;
2345 DUK_INTERNAL_DECL const char *duk_str_wrong_buffer_type;
2346 DUK_INTERNAL_DECL const char *duk_str_encode_failed;
2347 DUK_INTERNAL_DECL const char *duk_str_decode_failed;
2348 DUK_INTERNAL_DECL const char *duk_str_no_sourcecode;
2349 DUK_INTERNAL_DECL const char *duk_str_concat_result_too_long;
2350 DUK_INTERNAL_DECL const char *duk_str_unimplemented;
2351 DUK_INTERNAL_DECL const char *duk_str_unsupported;
2352 DUK_INTERNAL_DECL const char *duk_str_array_length_over_2g;
2353 #endif  /* !DUK_SINGLE_FILE */
2354 
2355 #define DUK_STR_FMT_PTR duk_str_fmt_ptr
2356 #define DUK_STR_FMT_INVALID_JSON duk_str_fmt_invalid_json
2357 #define DUK_STR_JSONDEC_RECLIMIT duk_str_jsondec_reclimit
2358 #define DUK_STR_JSONENC_RECLIMIT duk_str_jsonenc_reclimit
2359 #define DUK_STR_CYCLIC_INPUT duk_str_cyclic_input
2360 
2361 #if !defined(DUK_SINGLE_FILE)
2362 DUK_INTERNAL_DECL const char *duk_str_fmt_ptr;
2363 DUK_INTERNAL_DECL const char *duk_str_fmt_invalid_json;
2364 DUK_INTERNAL_DECL const char *duk_str_jsondec_reclimit;
2365 DUK_INTERNAL_DECL const char *duk_str_jsonenc_reclimit;
2366 DUK_INTERNAL_DECL const char *duk_str_cyclic_input;
2367 #endif  /* !DUK_SINGLE_FILE */
2368 
2369 #define DUK_STR_PROXY_REVOKED duk_str_proxy_revoked
2370 #define DUK_STR_INVALID_BASE duk_str_invalid_base
2371 #define DUK_STR_STRICT_CALLER_READ duk_str_strict_caller_read
2372 #define DUK_STR_PROXY_REJECTED duk_str_proxy_rejected
2373 #define DUK_STR_INVALID_ARRAY_LENGTH duk_str_invalid_array_length
2374 #define DUK_STR_ARRAY_LENGTH_WRITE_FAILED duk_str_array_length_write_failed
2375 #define DUK_STR_ARRAY_LENGTH_NOT_WRITABLE duk_str_array_length_not_writable
2376 #define DUK_STR_SETTER_UNDEFINED duk_str_setter_undefined
2377 #define DUK_STR_REDEFINE_VIRT_PROP duk_str_redefine_virt_prop
2378 #define DUK_STR_INVALID_DESCRIPTOR duk_str_invalid_descriptor
2379 #define DUK_STR_PROPERTY_IS_VIRTUAL duk_str_property_is_virtual
2380 
2381 #if !defined(DUK_SINGLE_FILE)
2382 DUK_INTERNAL_DECL const char *duk_str_proxy_revoked;
2383 DUK_INTERNAL_DECL const char *duk_str_invalid_base;
2384 DUK_INTERNAL_DECL const char *duk_str_strict_caller_read;
2385 DUK_INTERNAL_DECL const char *duk_str_proxy_rejected;
2386 DUK_INTERNAL_DECL const char *duk_str_invalid_array_length;
2387 DUK_INTERNAL_DECL const char *duk_str_array_length_write_failed;
2388 DUK_INTERNAL_DECL const char *duk_str_array_length_not_writable;
2389 DUK_INTERNAL_DECL const char *duk_str_setter_undefined;
2390 DUK_INTERNAL_DECL const char *duk_str_redefine_virt_prop;
2391 DUK_INTERNAL_DECL const char *duk_str_invalid_descriptor;
2392 DUK_INTERNAL_DECL const char *duk_str_property_is_virtual;
2393 #endif  /* !DUK_SINGLE_FILE */
2394 
2395 #define DUK_STR_PARSE_ERROR duk_str_parse_error
2396 #define DUK_STR_DUPLICATE_LABEL duk_str_duplicate_label
2397 #define DUK_STR_INVALID_LABEL duk_str_invalid_label
2398 #define DUK_STR_INVALID_ARRAY_LITERAL duk_str_invalid_array_literal
2399 #define DUK_STR_INVALID_OBJECT_LITERAL duk_str_invalid_object_literal
2400 #define DUK_STR_INVALID_VAR_DECLARATION duk_str_invalid_var_declaration
2401 #define DUK_STR_CANNOT_DELETE_IDENTIFIER duk_str_cannot_delete_identifier
2402 #define DUK_STR_INVALID_EXPRESSION duk_str_invalid_expression
2403 #define DUK_STR_INVALID_LVALUE duk_str_invalid_lvalue
2404 #define DUK_STR_EXPECTED_IDENTIFIER duk_str_expected_identifier
2405 #define DUK_STR_EMPTY_EXPR_NOT_ALLOWED duk_str_empty_expr_not_allowed
2406 #define DUK_STR_INVALID_FOR duk_str_invalid_for
2407 #define DUK_STR_INVALID_SWITCH duk_str_invalid_switch
2408 #define DUK_STR_INVALID_BREAK_CONT_LABEL duk_str_invalid_break_cont_label
2409 #define DUK_STR_INVALID_RETURN duk_str_invalid_return
2410 #define DUK_STR_INVALID_TRY duk_str_invalid_try
2411 #define DUK_STR_INVALID_THROW duk_str_invalid_throw
2412 #define DUK_STR_WITH_IN_STRICT_MODE duk_str_with_in_strict_mode
2413 #define DUK_STR_FUNC_STMT_NOT_ALLOWED duk_str_func_stmt_not_allowed
2414 #define DUK_STR_UNTERMINATED_STMT duk_str_unterminated_stmt
2415 #define DUK_STR_INVALID_ARG_NAME duk_str_invalid_arg_name
2416 #define DUK_STR_INVALID_FUNC_NAME duk_str_invalid_func_name
2417 #define DUK_STR_INVALID_GETSET_NAME duk_str_invalid_getset_name
2418 #define DUK_STR_FUNC_NAME_REQUIRED duk_str_func_name_required
2419 
2420 #if !defined(DUK_SINGLE_FILE)
2421 DUK_INTERNAL_DECL const char *duk_str_parse_error;
2422 DUK_INTERNAL_DECL const char *duk_str_duplicate_label;
2423 DUK_INTERNAL_DECL const char *duk_str_invalid_label;
2424 DUK_INTERNAL_DECL const char *duk_str_invalid_array_literal;
2425 DUK_INTERNAL_DECL const char *duk_str_invalid_object_literal;
2426 DUK_INTERNAL_DECL const char *duk_str_invalid_var_declaration;
2427 DUK_INTERNAL_DECL const char *duk_str_cannot_delete_identifier;
2428 DUK_INTERNAL_DECL const char *duk_str_invalid_expression;
2429 DUK_INTERNAL_DECL const char *duk_str_invalid_lvalue;
2430 DUK_INTERNAL_DECL const char *duk_str_expected_identifier;
2431 DUK_INTERNAL_DECL const char *duk_str_empty_expr_not_allowed;
2432 DUK_INTERNAL_DECL const char *duk_str_invalid_for;
2433 DUK_INTERNAL_DECL const char *duk_str_invalid_switch;
2434 DUK_INTERNAL_DECL const char *duk_str_invalid_break_cont_label;
2435 DUK_INTERNAL_DECL const char *duk_str_invalid_return;
2436 DUK_INTERNAL_DECL const char *duk_str_invalid_try;
2437 DUK_INTERNAL_DECL const char *duk_str_invalid_throw;
2438 DUK_INTERNAL_DECL const char *duk_str_with_in_strict_mode;
2439 DUK_INTERNAL_DECL const char *duk_str_func_stmt_not_allowed;
2440 DUK_INTERNAL_DECL const char *duk_str_unterminated_stmt;
2441 DUK_INTERNAL_DECL const char *duk_str_invalid_arg_name;
2442 DUK_INTERNAL_DECL const char *duk_str_invalid_func_name;
2443 DUK_INTERNAL_DECL const char *duk_str_invalid_getset_name;
2444 DUK_INTERNAL_DECL const char *duk_str_func_name_required;
2445 #endif  /* !DUK_SINGLE_FILE */
2446 
2447 #define DUK_STR_INVALID_QUANTIFIER_NO_ATOM duk_str_invalid_quantifier_no_atom
2448 #define DUK_STR_INVALID_QUANTIFIER_VALUES duk_str_invalid_quantifier_values
2449 #define DUK_STR_QUANTIFIER_TOO_MANY_COPIES duk_str_quantifier_too_many_copies
2450 #define DUK_STR_UNEXPECTED_CLOSING_PAREN duk_str_unexpected_closing_paren
2451 #define DUK_STR_UNEXPECTED_END_OF_PATTERN duk_str_unexpected_end_of_pattern
2452 #define DUK_STR_UNEXPECTED_REGEXP_TOKEN duk_str_unexpected_regexp_token
2453 #define DUK_STR_INVALID_REGEXP_FLAGS duk_str_invalid_regexp_flags
2454 #define DUK_STR_INVALID_BACKREFS duk_str_invalid_backrefs
2455 
2456 #if !defined(DUK_SINGLE_FILE)
2457 DUK_INTERNAL_DECL const char *duk_str_invalid_quantifier_no_atom;
2458 DUK_INTERNAL_DECL const char *duk_str_invalid_quantifier_values;
2459 DUK_INTERNAL_DECL const char *duk_str_quantifier_too_many_copies;
2460 DUK_INTERNAL_DECL const char *duk_str_unexpected_closing_paren;
2461 DUK_INTERNAL_DECL const char *duk_str_unexpected_end_of_pattern;
2462 DUK_INTERNAL_DECL const char *duk_str_unexpected_regexp_token;
2463 DUK_INTERNAL_DECL const char *duk_str_invalid_regexp_flags;
2464 DUK_INTERNAL_DECL const char *duk_str_invalid_backrefs;
2465 #endif  /* !DUK_SINGLE_FILE */
2466 
2467 #define DUK_STR_VALSTACK_LIMIT duk_str_valstack_limit
2468 #define DUK_STR_CALLSTACK_LIMIT duk_str_callstack_limit
2469 #define DUK_STR_CATCHSTACK_LIMIT duk_str_catchstack_limit
2470 #define DUK_STR_PROTOTYPE_CHAIN_LIMIT duk_str_prototype_chain_limit
2471 #define DUK_STR_BOUND_CHAIN_LIMIT duk_str_bound_chain_limit
2472 #define DUK_STR_C_CALLSTACK_LIMIT duk_str_c_callstack_limit
2473 #define DUK_STR_COMPILER_RECURSION_LIMIT duk_str_compiler_recursion_limit
2474 #define DUK_STR_BYTECODE_LIMIT duk_str_bytecode_limit
2475 #define DUK_STR_REG_LIMIT duk_str_reg_limit
2476 #define DUK_STR_TEMP_LIMIT duk_str_temp_limit
2477 #define DUK_STR_CONST_LIMIT duk_str_const_limit
2478 #define DUK_STR_FUNC_LIMIT duk_str_func_limit
2479 #define DUK_STR_REGEXP_COMPILER_RECURSION_LIMIT duk_str_regexp_compiler_recursion_limit
2480 #define DUK_STR_REGEXP_EXECUTOR_RECURSION_LIMIT duk_str_regexp_executor_recursion_limit
2481 #define DUK_STR_REGEXP_EXECUTOR_STEP_LIMIT duk_str_regexp_executor_step_limit
2482 
2483 #if !defined(DUK_SINGLE_FILE)
2484 DUK_INTERNAL_DECL const char *duk_str_valstack_limit;
2485 DUK_INTERNAL_DECL const char *duk_str_callstack_limit;
2486 DUK_INTERNAL_DECL const char *duk_str_catchstack_limit;
2487 DUK_INTERNAL_DECL const char *duk_str_prototype_chain_limit;
2488 DUK_INTERNAL_DECL const char *duk_str_bound_chain_limit;
2489 DUK_INTERNAL_DECL const char *duk_str_c_callstack_limit;
2490 DUK_INTERNAL_DECL const char *duk_str_compiler_recursion_limit;
2491 DUK_INTERNAL_DECL const char *duk_str_bytecode_limit;
2492 DUK_INTERNAL_DECL const char *duk_str_reg_limit;
2493 DUK_INTERNAL_DECL const char *duk_str_temp_limit;
2494 DUK_INTERNAL_DECL const char *duk_str_const_limit;
2495 DUK_INTERNAL_DECL const char *duk_str_func_limit;
2496 DUK_INTERNAL_DECL const char *duk_str_regexp_compiler_recursion_limit;
2497 DUK_INTERNAL_DECL const char *duk_str_regexp_executor_recursion_limit;
2498 DUK_INTERNAL_DECL const char *duk_str_regexp_executor_step_limit;
2499 #endif  /* !DUK_SINGLE_FILE */
2500 
2501 #if !defined(DUK_SINGLE_FILE)
2502 DUK_INTERNAL_DECL const char *duk_str_anon;
2503 #endif  /* !DUK_SINGLE_FILE */
2504 
2505 #endif  /* DUK_ERRMSG_H_INCLUDED */
2506 /*
2507  *  Ecmascript bytecode
2508  */
2509 
2510 #ifndef DUK_JS_BYTECODE_H_INCLUDED
2511 #define DUK_JS_BYTECODE_H_INCLUDED
2512 
2513 /*
2514  *  Logical instruction layout
2515  *  ==========================
2516  *
2517  *  !3!3!2!2!2!2!2!2!2!2!2!2!1!1!1!1!1!1!1!1!1!1! ! ! ! ! ! ! ! ! ! !
2518  *  !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!
2519  *  +---------------------------------------------------+-----------+
2520  *  !       C         !       B         !      A        !    OP     !
2521  *  +---------------------------------------------------+-----------+
2522  *
2523  *  OP (6 bits):  opcode (DUK_OP_*), access should be fastest
2524  *  A (8 bits):   typically a target register number
2525  *  B (9 bits):   typically first source register/constant number
2526  *  C (9 bits):   typically second source register/constant number
2527  *
2528  *  Some instructions combine BC or ABC together for larger parameter values.
2529  *  Signed integers (e.g. jump offsets) are encoded as unsigned, with an opcode
2530  *  specific bias.  B and C may denote a register or a constant, see
2531  *  DUK_BC_ISREG() and DUK_BC_ISCONST().
2532  *
2533  *  Note: macro naming is a bit misleading, e.g. "ABC" in macro name but
2534  *  the field layout is logically "CBA".
2535  */
2536 
2537 typedef duk_uint32_t duk_instr_t;
2538 
2539 #define DUK_DEC_OP(x)               ((x) & 0x3fUL)
2540 #define DUK_DEC_A(x)                (((x) >> 6) & 0xffUL)
2541 #define DUK_DEC_B(x)                (((x) >> 14) & 0x1ffUL)
2542 #define DUK_DEC_C(x)                (((x) >> 23) & 0x1ffUL)
2543 #define DUK_DEC_BC(x)               (((x) >> 14) & 0x3ffffUL)
2544 #define DUK_DEC_ABC(x)              (((x) >> 6) & 0x3ffffffUL)
2545 
2546 #define DUK_ENC_OP(op)              ((duk_instr_t) (op))
2547 #define DUK_ENC_OP_ABC(op,abc)      ((duk_instr_t) ( \
2548                                         (((duk_instr_t) (abc)) << 6) | \
2549                                         ((duk_instr_t) (op)) \
2550                                     ))
2551 #define DUK_ENC_OP_A_BC(op,a,bc)    ((duk_instr_t) ( \
2552                                         (((duk_instr_t) (bc)) << 14) | \
2553                                         (((duk_instr_t) (a)) << 6) | \
2554                                         ((duk_instr_t) (op)) \
2555                                     ))
2556 #define DUK_ENC_OP_A_B_C(op,a,b,c)  ((duk_instr_t) ( \
2557                                         (((duk_instr_t) (c)) << 23) | \
2558                                         (((duk_instr_t) (b)) << 14) | \
2559                                         (((duk_instr_t) (a)) << 6) | \
2560                                         ((duk_instr_t) (op)) \
2561                                     ))
2562 #define DUK_ENC_OP_A_B(op,a,b)      DUK_ENC_OP_A_B_C(op,a,b,0)
2563 #define DUK_ENC_OP_A(op,a)          DUK_ENC_OP_A_B_C(op,a,0,0)
2564 
2565 /* Constants should be signed so that signed arithmetic involving them
2566  * won't cause values to be coerced accidentally to unsigned.
2567  */
2568 #define DUK_BC_OP_MIN               0
2569 #define DUK_BC_OP_MAX               0x3fL
2570 #define DUK_BC_A_MIN                0
2571 #define DUK_BC_A_MAX                0xffL
2572 #define DUK_BC_B_MIN                0
2573 #define DUK_BC_B_MAX                0x1ffL
2574 #define DUK_BC_C_MIN                0
2575 #define DUK_BC_C_MAX                0x1ffL
2576 #define DUK_BC_BC_MIN               0
2577 #define DUK_BC_BC_MAX               0x3ffffL
2578 #define DUK_BC_ABC_MIN              0
2579 #define DUK_BC_ABC_MAX              0x3ffffffL
2580 #define DUK_BC_EXTRAOP_MIN          DUK_BC_A_MIN
2581 #define DUK_BC_EXTRAOP_MAX          DUK_BC_A_MAX
2582 
2583 #define DUK_OP_LDREG                0
2584 #define DUK_OP_STREG                1
2585 #define DUK_OP_LDCONST              2
2586 #define DUK_OP_LDINT                3
2587 #define DUK_OP_LDINTX               4
2588 #define DUK_OP_MPUTOBJ              5
2589 #define DUK_OP_MPUTOBJI             6
2590 #define DUK_OP_MPUTARR              7
2591 #define DUK_OP_MPUTARRI             8
2592 #define DUK_OP_NEW                  9
2593 #define DUK_OP_NEWI                 10
2594 #define DUK_OP_REGEXP               11
2595 #define DUK_OP_CSREG                12
2596 #define DUK_OP_CSREGI               13
2597 #define DUK_OP_GETVAR               14
2598 #define DUK_OP_PUTVAR               15
2599 #define DUK_OP_DECLVAR              16
2600 #define DUK_OP_DELVAR               17
2601 #define DUK_OP_CSVAR                18
2602 #define DUK_OP_CSVARI               19
2603 #define DUK_OP_CLOSURE              20
2604 #define DUK_OP_GETPROP              21
2605 #define DUK_OP_PUTPROP              22
2606 #define DUK_OP_DELPROP              23
2607 #define DUK_OP_CSPROP               24
2608 #define DUK_OP_CSPROPI              25
2609 #define DUK_OP_ADD                  26
2610 #define DUK_OP_SUB                  27
2611 #define DUK_OP_MUL                  28
2612 #define DUK_OP_DIV                  29
2613 #define DUK_OP_MOD                  30
2614 #define DUK_OP_BAND                 31
2615 #define DUK_OP_BOR                  32
2616 #define DUK_OP_BXOR                 33
2617 #define DUK_OP_BASL                 34
2618 #define DUK_OP_BLSR                 35
2619 #define DUK_OP_BASR                 36
2620 #define DUK_OP_EQ                   37
2621 #define DUK_OP_NEQ                  38
2622 #define DUK_OP_SEQ                  39
2623 #define DUK_OP_SNEQ                 40
2624 #define DUK_OP_GT                   41
2625 #define DUK_OP_GE                   42
2626 #define DUK_OP_LT                   43
2627 #define DUK_OP_LE                   44
2628 #define DUK_OP_IF                   45
2629 #define DUK_OP_JUMP                 46
2630 #define DUK_OP_RETURN               47
2631 #define DUK_OP_CALL                 48
2632 #define DUK_OP_CALLI                49
2633 #define DUK_OP_TRYCATCH             50
2634 #define DUK_OP_EXTRA                51
2635 #define DUK_OP_PREINCR              52  /* pre/post opcode values have constraints, */
2636 #define DUK_OP_PREDECR              53  /* see duk_js_executor.c */
2637 #define DUK_OP_POSTINCR             54
2638 #define DUK_OP_POSTDECR             55
2639 #define DUK_OP_PREINCV              56
2640 #define DUK_OP_PREDECV              57
2641 #define DUK_OP_POSTINCV             58
2642 #define DUK_OP_POSTDECV             59
2643 #define DUK_OP_PREINCP              60
2644 #define DUK_OP_PREDECP              61
2645 #define DUK_OP_POSTINCP             62
2646 #define DUK_OP_POSTDECP             63
2647 #define DUK_OP_NONE                 64  /* dummy value used as marker */
2648 
2649 /* DUK_OP_EXTRA, sub-operation in A */
2650 #define DUK_EXTRAOP_NOP             0
2651 #define DUK_EXTRAOP_INVALID         1
2652 #define DUK_EXTRAOP_LDTHIS          2
2653 #define DUK_EXTRAOP_LDUNDEF         3
2654 #define DUK_EXTRAOP_LDNULL          4
2655 #define DUK_EXTRAOP_LDTRUE          5
2656 #define DUK_EXTRAOP_LDFALSE         6
2657 #define DUK_EXTRAOP_NEWOBJ          7
2658 #define DUK_EXTRAOP_NEWARR          8
2659 #define DUK_EXTRAOP_SETALEN         9
2660 #define DUK_EXTRAOP_TYPEOF          10
2661 #define DUK_EXTRAOP_TYPEOFID        11
2662 #define DUK_EXTRAOP_INITENUM        12
2663 #define DUK_EXTRAOP_NEXTENUM        13
2664 #define DUK_EXTRAOP_INITSET         14
2665 #define DUK_EXTRAOP_INITSETI        15
2666 #define DUK_EXTRAOP_INITGET         16
2667 #define DUK_EXTRAOP_INITGETI        17
2668 #define DUK_EXTRAOP_ENDTRY          18
2669 #define DUK_EXTRAOP_ENDCATCH        19
2670 #define DUK_EXTRAOP_ENDFIN          20
2671 #define DUK_EXTRAOP_THROW           21
2672 #define DUK_EXTRAOP_INVLHS          22
2673 #define DUK_EXTRAOP_UNM             23
2674 #define DUK_EXTRAOP_UNP             24
2675 #define DUK_EXTRAOP_DEBUGGER        25
2676 #define DUK_EXTRAOP_BREAK           26
2677 #define DUK_EXTRAOP_CONTINUE        27
2678 #define DUK_EXTRAOP_BNOT            28
2679 #define DUK_EXTRAOP_LNOT            29
2680 #define DUK_EXTRAOP_INSTOF          30
2681 #define DUK_EXTRAOP_IN              31
2682 #define DUK_EXTRAOP_LABEL           32
2683 #define DUK_EXTRAOP_ENDLABEL        33
2684 
2685 /* DUK_OP_CALL flags in A */
2686 #define DUK_BC_CALL_FLAG_TAILCALL           (1 << 0)
2687 #define DUK_BC_CALL_FLAG_EVALCALL           (1 << 1)
2688 
2689 /* DUK_OP_TRYCATCH flags in A */
2690 #define DUK_BC_TRYCATCH_FLAG_HAVE_CATCH     (1 << 0)
2691 #define DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY   (1 << 1)
2692 #define DUK_BC_TRYCATCH_FLAG_CATCH_BINDING  (1 << 2)
2693 #define DUK_BC_TRYCATCH_FLAG_WITH_BINDING   (1 << 3)
2694 
2695 /* DUK_OP_RETURN flags in A */
2696 #define DUK_BC_RETURN_FLAG_HAVE_RETVAL      (1 << 0)
2697 
2698 /* DUK_OP_DECLVAR flags in A; bottom bits are reserved for propdesc flags (DUK_PROPDESC_FLAG_XXX) */
2699 #define DUK_BC_DECLVAR_FLAG_UNDEF_VALUE     (1 << 4)  /* use 'undefined' for value automatically */
2700 #define DUK_BC_DECLVAR_FLAG_FUNC_DECL       (1 << 5)  /* function declaration */
2701 
2702 /* misc constants and helper macros */
2703 #define DUK_BC_REGLIMIT             256  /* if B/C is >= this value, refers to a const */
2704 #define DUK_BC_ISREG(x)             ((x) < DUK_BC_REGLIMIT)
2705 #define DUK_BC_ISCONST(x)           ((x) >= DUK_BC_REGLIMIT)
2706 #define DUK_BC_LDINT_BIAS           (1L << 17)
2707 #define DUK_BC_LDINTX_SHIFT         18
2708 #define DUK_BC_JUMP_BIAS            (1L << 25)
2709 
2710 #endif  /* DUK_JS_BYTECODE_H_INCLUDED */
2711 /*
2712  *  Lexer defines.
2713  */
2714 
2715 #ifndef DUK_LEXER_H_INCLUDED
2716 #define DUK_LEXER_H_INCLUDED
2717 
2718 typedef void (*duk_re_range_callback)(void *user, duk_codepoint_t r1, duk_codepoint_t r2, duk_bool_t direct);
2719 
2720 /*
2721  *  A token is interpreted as any possible production of InputElementDiv
2722  *  and InputElementRegExp, see E5 Section 7 in its entirety.  Note that
2723  *  the E5 "Token" production does not cover all actual tokens of the
2724  *  language (which is explicitly stated in the specification, Section 7.5).
2725  *  Null and boolean literals are defined as part of both ReservedWord
2726  *  (E5 Section 7.6.1) and Literal (E5 Section 7.8) productions.  Here,
2727  *  null and boolean values have literal tokens, and are not reserved
2728  *  words.
2729  *
2730  *  Decimal literal negative/positive sign is -not- part of DUK_TOK_NUMBER.
2731  *  The number tokens always have a non-negative value.  The unary minus
2732  *  operator in "-1.0" is optimized during compilation to yield a single
2733  *  negative constant.
2734  *
2735  *  Token numbering is free except that reserved words are required to be
2736  *  in a continuous range and in a particular order.  See genstrings.py.
2737  */
2738 
2739 #define DUK_LEXER_INITCTX(ctx)        duk_lexer_initctx((ctx))
2740 
2741 #define DUK_LEXER_SETPOINT(ctx,pt)    duk_lexer_setpoint((ctx), (pt))
2742 
2743 #define DUK_LEXER_GETPOINT(ctx,pt)    do { (pt)->offset = (ctx)->window[0].offset; \
2744                                            (pt)->line = (ctx)->window[0].line; } while (0)
2745 
2746 /* currently 6 characters of lookup are actually needed (duk_lexer.c) */
2747 #define DUK_LEXER_WINDOW_SIZE                     6
2748 #if defined(DUK_USE_LEXER_SLIDING_WINDOW)
2749 #define DUK_LEXER_BUFFER_SIZE                     64
2750 #endif
2751 
2752 #define DUK_TOK_MINVAL                            0
2753 
2754 /* returned after EOF (infinite amount) */
2755 #define DUK_TOK_EOF                               0
2756 
2757 /* identifier names (E5 Section 7.6) */
2758 #define DUK_TOK_IDENTIFIER                        1
2759 
2760 /* reserved words: keywords */
2761 #define DUK_TOK_START_RESERVED                    2
2762 #define DUK_TOK_BREAK                             2
2763 #define DUK_TOK_CASE                              3
2764 #define DUK_TOK_CATCH                             4
2765 #define DUK_TOK_CONTINUE                          5
2766 #define DUK_TOK_DEBUGGER                          6
2767 #define DUK_TOK_DEFAULT                           7
2768 #define DUK_TOK_DELETE                            8
2769 #define DUK_TOK_DO                                9
2770 #define DUK_TOK_ELSE                              10
2771 #define DUK_TOK_FINALLY                           11
2772 #define DUK_TOK_FOR                               12
2773 #define DUK_TOK_FUNCTION                          13
2774 #define DUK_TOK_IF                                14
2775 #define DUK_TOK_IN                                15
2776 #define DUK_TOK_INSTANCEOF                        16
2777 #define DUK_TOK_NEW                               17
2778 #define DUK_TOK_RETURN                            18
2779 #define DUK_TOK_SWITCH                            19
2780 #define DUK_TOK_THIS                              20
2781 #define DUK_TOK_THROW                             21
2782 #define DUK_TOK_TRY                               22
2783 #define DUK_TOK_TYPEOF                            23
2784 #define DUK_TOK_VAR                               24
2785 #define DUK_TOK_CONST                             25
2786 #define DUK_TOK_VOID                              26
2787 #define DUK_TOK_WHILE                             27
2788 #define DUK_TOK_WITH                              28
2789 
2790 /* reserved words: future reserved words */
2791 #define DUK_TOK_CLASS                             29
2792 #define DUK_TOK_ENUM                              30
2793 #define DUK_TOK_EXPORT                            31
2794 #define DUK_TOK_EXTENDS                           32
2795 #define DUK_TOK_IMPORT                            33
2796 #define DUK_TOK_SUPER                             34
2797 
2798 /* "null", "true", and "false" are always reserved words.
2799  * Note that "get" and "set" are not!
2800  */
2801 #define DUK_TOK_NULL                              35
2802 #define DUK_TOK_TRUE                              36
2803 #define DUK_TOK_FALSE                             37
2804 
2805 /* reserved words: additional future reserved words in strict mode */
2806 #define DUK_TOK_START_STRICT_RESERVED             38  /* inclusive */
2807 #define DUK_TOK_IMPLEMENTS                        38
2808 #define DUK_TOK_INTERFACE                         39
2809 #define DUK_TOK_LET                               40
2810 #define DUK_TOK_PACKAGE                           41
2811 #define DUK_TOK_PRIVATE                           42
2812 #define DUK_TOK_PROTECTED                         43
2813 #define DUK_TOK_PUBLIC                            44
2814 #define DUK_TOK_STATIC                            45
2815 #define DUK_TOK_YIELD                             46
2816 
2817 #define DUK_TOK_END_RESERVED                      47  /* exclusive */
2818 
2819 /* "get" and "set" are tokens but NOT ReservedWords.  They are currently
2820  * parsed and identifiers and these defines are actually now unused.
2821  */
2822 #define DUK_TOK_GET                               47
2823 #define DUK_TOK_SET                               48
2824 
2825 /* punctuators (unlike the spec, also includes "/" and "/=") */
2826 #define DUK_TOK_LCURLY                            49
2827 #define DUK_TOK_RCURLY                            50
2828 #define DUK_TOK_LBRACKET                          51
2829 #define DUK_TOK_RBRACKET                          52
2830 #define DUK_TOK_LPAREN                            53
2831 #define DUK_TOK_RPAREN                            54
2832 #define DUK_TOK_PERIOD                            55
2833 #define DUK_TOK_SEMICOLON                         56
2834 #define DUK_TOK_COMMA                             57
2835 #define DUK_TOK_LT                                58
2836 #define DUK_TOK_GT                                59
2837 #define DUK_TOK_LE                                60
2838 #define DUK_TOK_GE                                61
2839 #define DUK_TOK_EQ                                62
2840 #define DUK_TOK_NEQ                               63
2841 #define DUK_TOK_SEQ                               64
2842 #define DUK_TOK_SNEQ                              65
2843 #define DUK_TOK_ADD                               66
2844 #define DUK_TOK_SUB                               67
2845 #define DUK_TOK_MUL                               68
2846 #define DUK_TOK_DIV                               69
2847 #define DUK_TOK_MOD                               70
2848 #define DUK_TOK_INCREMENT                         71
2849 #define DUK_TOK_DECREMENT                         72
2850 #define DUK_TOK_ALSHIFT                           73  /* named "arithmetic" because result is signed */
2851 #define DUK_TOK_ARSHIFT                           74
2852 #define DUK_TOK_RSHIFT                            75
2853 #define DUK_TOK_BAND                              76
2854 #define DUK_TOK_BOR                               77
2855 #define DUK_TOK_BXOR                              78
2856 #define DUK_TOK_LNOT                              79
2857 #define DUK_TOK_BNOT                              80
2858 #define DUK_TOK_LAND                              81
2859 #define DUK_TOK_LOR                               82
2860 #define DUK_TOK_QUESTION                          83
2861 #define DUK_TOK_COLON                             84
2862 #define DUK_TOK_EQUALSIGN                         85
2863 #define DUK_TOK_ADD_EQ                            86
2864 #define DUK_TOK_SUB_EQ                            87
2865 #define DUK_TOK_MUL_EQ                            88
2866 #define DUK_TOK_DIV_EQ                            89
2867 #define DUK_TOK_MOD_EQ                            90
2868 #define DUK_TOK_ALSHIFT_EQ                        91
2869 #define DUK_TOK_ARSHIFT_EQ                        92
2870 #define DUK_TOK_RSHIFT_EQ                         93
2871 #define DUK_TOK_BAND_EQ                           94
2872 #define DUK_TOK_BOR_EQ                            95
2873 #define DUK_TOK_BXOR_EQ                           96
2874 
2875 /* literals (E5 Section 7.8), except null, true, false, which are treated
2876  * like reserved words (above).
2877  */
2878 #define DUK_TOK_NUMBER                            97
2879 #define DUK_TOK_STRING                            98
2880 #define DUK_TOK_REGEXP                            99
2881 
2882 #define DUK_TOK_MAXVAL                            99  /* inclusive */
2883 
2884 /* Convert heap string index to a token (reserved words) */
2885 #define DUK_STRIDX_TO_TOK(x)                        ((x) - DUK_STRIDX_START_RESERVED + DUK_TOK_START_RESERVED)
2886 
2887 /* Sanity check */
2888 #if (DUK_TOK_MAXVAL > 255)
2889 #error DUK_TOK_MAXVAL too large, code assumes it fits into 8 bits
2890 #endif
2891 
2892 /* Sanity checks for string and token defines */
2893 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_BREAK) != DUK_TOK_BREAK)
2894 #error mismatch in token defines
2895 #endif
2896 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CASE) != DUK_TOK_CASE)
2897 #error mismatch in token defines
2898 #endif
2899 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CATCH) != DUK_TOK_CATCH)
2900 #error mismatch in token defines
2901 #endif
2902 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CONTINUE) != DUK_TOK_CONTINUE)
2903 #error mismatch in token defines
2904 #endif
2905 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_DEBUGGER) != DUK_TOK_DEBUGGER)
2906 #error mismatch in token defines
2907 #endif
2908 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_DEFAULT) != DUK_TOK_DEFAULT)
2909 #error mismatch in token defines
2910 #endif
2911 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_DELETE) != DUK_TOK_DELETE)
2912 #error mismatch in token defines
2913 #endif
2914 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_DO) != DUK_TOK_DO)
2915 #error mismatch in token defines
2916 #endif
2917 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_ELSE) != DUK_TOK_ELSE)
2918 #error mismatch in token defines
2919 #endif
2920 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_FINALLY) != DUK_TOK_FINALLY)
2921 #error mismatch in token defines
2922 #endif
2923 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_FOR) != DUK_TOK_FOR)
2924 #error mismatch in token defines
2925 #endif
2926 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_LC_FUNCTION) != DUK_TOK_FUNCTION)
2927 #error mismatch in token defines
2928 #endif
2929 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_IF) != DUK_TOK_IF)
2930 #error mismatch in token defines
2931 #endif
2932 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_IN) != DUK_TOK_IN)
2933 #error mismatch in token defines
2934 #endif
2935 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_INSTANCEOF) != DUK_TOK_INSTANCEOF)
2936 #error mismatch in token defines
2937 #endif
2938 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_NEW) != DUK_TOK_NEW)
2939 #error mismatch in token defines
2940 #endif
2941 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_RETURN) != DUK_TOK_RETURN)
2942 #error mismatch in token defines
2943 #endif
2944 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_SWITCH) != DUK_TOK_SWITCH)
2945 #error mismatch in token defines
2946 #endif
2947 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_THIS) != DUK_TOK_THIS)
2948 #error mismatch in token defines
2949 #endif
2950 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_THROW) != DUK_TOK_THROW)
2951 #error mismatch in token defines
2952 #endif
2953 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_TRY) != DUK_TOK_TRY)
2954 #error mismatch in token defines
2955 #endif
2956 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_TYPEOF) != DUK_TOK_TYPEOF)
2957 #error mismatch in token defines
2958 #endif
2959 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_VAR) != DUK_TOK_VAR)
2960 #error mismatch in token defines
2961 #endif
2962 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_VOID) != DUK_TOK_VOID)
2963 #error mismatch in token defines
2964 #endif
2965 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_WHILE) != DUK_TOK_WHILE)
2966 #error mismatch in token defines
2967 #endif
2968 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_WITH) != DUK_TOK_WITH)
2969 #error mismatch in token defines
2970 #endif
2971 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CLASS) != DUK_TOK_CLASS)
2972 #error mismatch in token defines
2973 #endif
2974 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CONST) != DUK_TOK_CONST)
2975 #error mismatch in token defines
2976 #endif
2977 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_ENUM) != DUK_TOK_ENUM)
2978 #error mismatch in token defines
2979 #endif
2980 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_EXPORT) != DUK_TOK_EXPORT)
2981 #error mismatch in token defines
2982 #endif
2983 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_EXTENDS) != DUK_TOK_EXTENDS)
2984 #error mismatch in token defines
2985 #endif
2986 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_IMPORT) != DUK_TOK_IMPORT)
2987 #error mismatch in token defines
2988 #endif
2989 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_SUPER) != DUK_TOK_SUPER)
2990 #error mismatch in token defines
2991 #endif
2992 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_LC_NULL) != DUK_TOK_NULL)
2993 #error mismatch in token defines
2994 #endif
2995 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_TRUE) != DUK_TOK_TRUE)
2996 #error mismatch in token defines
2997 #endif
2998 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_FALSE) != DUK_TOK_FALSE)
2999 #error mismatch in token defines
3000 #endif
3001 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_IMPLEMENTS) != DUK_TOK_IMPLEMENTS)
3002 #error mismatch in token defines
3003 #endif
3004 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_INTERFACE) != DUK_TOK_INTERFACE)
3005 #error mismatch in token defines
3006 #endif
3007 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_LET) != DUK_TOK_LET)
3008 #error mismatch in token defines
3009 #endif
3010 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_PACKAGE) != DUK_TOK_PACKAGE)
3011 #error mismatch in token defines
3012 #endif
3013 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_PRIVATE) != DUK_TOK_PRIVATE)
3014 #error mismatch in token defines
3015 #endif
3016 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_PROTECTED) != DUK_TOK_PROTECTED)
3017 #error mismatch in token defines
3018 #endif
3019 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_PUBLIC) != DUK_TOK_PUBLIC)
3020 #error mismatch in token defines
3021 #endif
3022 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_STATIC) != DUK_TOK_STATIC)
3023 #error mismatch in token defines
3024 #endif
3025 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_YIELD) != DUK_TOK_YIELD)
3026 #error mismatch in token defines
3027 #endif
3028 
3029 /* Regexp tokens */
3030 #define DUK_RETOK_EOF                              0
3031 #define DUK_RETOK_DISJUNCTION                      1
3032 #define DUK_RETOK_QUANTIFIER                       2
3033 #define DUK_RETOK_ASSERT_START                     3
3034 #define DUK_RETOK_ASSERT_END                       4
3035 #define DUK_RETOK_ASSERT_WORD_BOUNDARY             5
3036 #define DUK_RETOK_ASSERT_NOT_WORD_BOUNDARY         6
3037 #define DUK_RETOK_ASSERT_START_POS_LOOKAHEAD       7
3038 #define DUK_RETOK_ASSERT_START_NEG_LOOKAHEAD       8
3039 #define DUK_RETOK_ATOM_PERIOD                      9
3040 #define DUK_RETOK_ATOM_CHAR                        10
3041 #define DUK_RETOK_ATOM_DIGIT                       11
3042 #define DUK_RETOK_ATOM_NOT_DIGIT                   12
3043 #define DUK_RETOK_ATOM_WHITE                       13
3044 #define DUK_RETOK_ATOM_NOT_WHITE                   14
3045 #define DUK_RETOK_ATOM_WORD_CHAR                   15
3046 #define DUK_RETOK_ATOM_NOT_WORD_CHAR               16
3047 #define DUK_RETOK_ATOM_BACKREFERENCE               17
3048 #define DUK_RETOK_ATOM_START_CAPTURE_GROUP         18
3049 #define DUK_RETOK_ATOM_START_NONCAPTURE_GROUP      19
3050 #define DUK_RETOK_ATOM_START_CHARCLASS             20
3051 #define DUK_RETOK_ATOM_START_CHARCLASS_INVERTED    21
3052 #define DUK_RETOK_ATOM_END_GROUP                   22
3053 
3054 /* Constants for duk_lexer_ctx.buf. */
3055 #define DUK_LEXER_TEMP_BUF_LIMIT                   256
3056 
3057 /* A token value.  Can be memcpy()'d, but note that slot1/slot2 values are on the valstack.
3058  * Some fields (like num, str1, str2) are only valid for specific token types and may have
3059  * stale values otherwise.
3060  */
3061 struct duk_token {
3062 	duk_small_int_t t;            /* token type (with reserved word identification) */
3063 	duk_small_int_t t_nores;      /* token type (with reserved words as DUK_TOK_IDENTIFER) */
3064 	duk_double_t num;             /* numeric value of token */
3065 	duk_hstring *str1;            /* string 1 of token (borrowed, stored to ctx->slot1_idx) */
3066 	duk_hstring *str2;            /* string 2 of token (borrowed, stored to ctx->slot2_idx) */
3067 	duk_size_t start_offset;      /* start byte offset of token in lexer input */
3068 	duk_int_t start_line;         /* start line of token (first char) */
3069 	duk_int_t num_escapes;        /* number of escapes and line continuations (for directive prologue) */
3070 	duk_bool_t lineterm;          /* token was preceded by a lineterm */
3071 	duk_bool_t allow_auto_semi;   /* token allows automatic semicolon insertion (eof or preceded by newline) */
3072 };
3073 
3074 #define DUK_RE_QUANTIFIER_INFINITE         ((duk_uint32_t) 0xffffffffUL)
3075 
3076 /* A regexp token value. */
3077 struct duk_re_token {
3078 	duk_small_int_t t;           /* token type */
3079 	duk_small_int_t greedy;
3080 	duk_uint_fast32_t num;       /* numeric value (character, count) */
3081 	duk_uint_fast32_t qmin;
3082 	duk_uint_fast32_t qmax;
3083 };
3084 
3085 /* A structure for 'snapshotting' a point for rewinding */
3086 struct duk_lexer_point {
3087 	duk_size_t offset;
3088 	duk_int_t line;
3089 };
3090 
3091 /* Lexer codepoint with additional info like offset/line number */
3092 struct duk_lexer_codepoint {
3093 	duk_codepoint_t codepoint;
3094 	duk_size_t offset;
3095 	duk_int_t line;
3096 };
3097 
3098 /* Lexer context.  Same context is used for Ecmascript and Regexp parsing. */
3099 struct duk_lexer_ctx {
3100 #if defined(DUK_USE_LEXER_SLIDING_WINDOW)
3101 	duk_lexer_codepoint *window; /* unicode code points, window[0] is always next, points to 'buffer' */
3102 	duk_lexer_codepoint buffer[DUK_LEXER_BUFFER_SIZE];
3103 #else
3104 	duk_lexer_codepoint window[DUK_LEXER_WINDOW_SIZE]; /* unicode code points, window[0] is always next */
3105 #endif
3106 
3107 	duk_hthread *thr;                              /* thread; minimizes argument passing */
3108 
3109 	const duk_uint8_t *input;                      /* input string (may be a user pointer) */
3110 	duk_size_t input_length;                       /* input byte length */
3111 	duk_size_t input_offset;                       /* input offset for window leading edge (not window[0]) */
3112 	duk_int_t input_line;                          /* input linenumber at input_offset (not window[0]), init to 1 */
3113 
3114 	duk_idx_t slot1_idx;                           /* valstack slot for 1st token value */
3115 	duk_idx_t slot2_idx;                           /* valstack slot for 2nd token value */
3116 	duk_idx_t buf_idx;                             /* valstack slot for temp buffer */
3117 	duk_hbuffer_dynamic *buf;                      /* temp accumulation buffer */
3118 	duk_bufwriter_ctx bw;                          /* bufwriter for temp accumulation */
3119 
3120 	duk_int_t token_count;                         /* number of tokens parsed */
3121 	duk_int_t token_limit;                         /* maximum token count before error (sanity backstop) */
3122 };
3123 
3124 /*
3125  *  Prototypes
3126  */
3127 
3128 DUK_INTERNAL_DECL void duk_lexer_initctx(duk_lexer_ctx *lex_ctx);
3129 
3130 DUK_INTERNAL_DECL void duk_lexer_setpoint(duk_lexer_ctx *lex_ctx, duk_lexer_point *pt);
3131 
3132 DUK_INTERNAL_DECL
3133 void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx,
3134                                       duk_token *out_token,
3135                                       duk_bool_t strict_mode,
3136                                       duk_bool_t regexp_mode);
3137 #ifdef DUK_USE_REGEXP_SUPPORT
3138 DUK_INTERNAL_DECL void duk_lexer_parse_re_token(duk_lexer_ctx *lex_ctx, duk_re_token *out_token);
3139 DUK_INTERNAL_DECL void duk_lexer_parse_re_ranges(duk_lexer_ctx *lex_ctx, duk_re_range_callback gen_range, void *userdata);
3140 #endif  /* DUK_USE_REGEXP_SUPPORT */
3141 
3142 #endif  /* DUK_LEXER_H_INCLUDED */
3143 /*
3144  *  Ecmascript compiler.
3145  */
3146 
3147 #ifndef DUK_JS_COMPILER_H_INCLUDED
3148 #define DUK_JS_COMPILER_H_INCLUDED
3149 
3150 /* ecmascript compiler limits */
3151 #define DUK_COMPILER_TOKEN_LIMIT           100000000L  /* 1e8: protects against deeply nested inner functions */
3152 
3153 /* maximum loopcount for peephole optimization */
3154 #define DUK_COMPILER_PEEPHOLE_MAXITER      3
3155 
3156 /* maximum bytecode length in instructions */
3157 #define DUK_COMPILER_MAX_BYTECODE_LENGTH   (256L * 1024L * 1024L)  /* 1 GB */
3158 
3159 /*
3160  *  Compiler intermediate values
3161  *
3162  *  Intermediate values describe either plain values (e.g. strings or
3163  *  numbers) or binary operations which have not yet been coerced into
3164  *  either a left-hand-side or right-hand-side role (e.g. object property).
3165  */
3166 
3167 #define DUK_IVAL_NONE          0   /* no value */
3168 #define DUK_IVAL_PLAIN         1   /* register, constant, or value */
3169 #define DUK_IVAL_ARITH         2   /* binary arithmetic; DUK_OP_ADD, DUK_OP_EQ, other binary ops */
3170 #define DUK_IVAL_ARITH_EXTRAOP 3   /* binary arithmetic using extraops; DUK_EXTRAOP_INSTOF etc */
3171 #define DUK_IVAL_PROP          4   /* property access */
3172 #define DUK_IVAL_VAR           5   /* variable access */
3173 
3174 #define DUK_ISPEC_NONE         0   /* no value */
3175 #define DUK_ISPEC_VALUE        1   /* value resides in 'valstack_idx' */
3176 #define DUK_ISPEC_REGCONST     2   /* value resides in a register or constant */
3177 
3178 /* bit mask which indicates that a regconst is a constant instead of a register */
3179 #define DUK_JS_CONST_MARKER    0x80000000UL
3180 
3181 /* type to represent a reg/const reference during compilation */
3182 typedef duk_uint32_t duk_regconst_t;
3183 
3184 /* type to represent a straight register reference, with <0 indicating none */
3185 typedef duk_int32_t duk_reg_t;
3186 
3187 typedef struct {
3188 	duk_small_uint_t t;          /* DUK_ISPEC_XXX */
3189 	duk_regconst_t regconst;
3190 	duk_idx_t valstack_idx;      /* always set; points to a reserved valstack slot */
3191 } duk_ispec;
3192 
3193 typedef struct {
3194 	/*
3195 	 *  PLAIN: x1
3196 	 *  ARITH: x1 <op> x2
3197 	 *  PROP: x1.x2
3198 	 *  VAR: x1 (name)
3199 	 */
3200 
3201 	/* XXX: can be optimized for smaller footprint esp. on 32-bit environments */
3202 	duk_small_uint_t t;          /* DUK_IVAL_XXX */
3203 	duk_small_uint_t op;         /* bytecode opcode (or extraop) for binary ops */
3204 	duk_ispec x1;
3205 	duk_ispec x2;
3206 } duk_ivalue;
3207 
3208 /*
3209  *  Bytecode instruction representation during compilation
3210  *
3211  *  Contains the actual instruction and (optionally) debug info.
3212  */
3213 
3214 struct duk_compiler_instr {
3215 	duk_instr_t ins;
3216 #if defined(DUK_USE_PC2LINE)
3217 	duk_uint32_t line;
3218 #endif
3219 };
3220 
3221 /*
3222  *  Compiler state
3223  */
3224 
3225 #define DUK_LABEL_FLAG_ALLOW_BREAK       (1 << 0)
3226 #define DUK_LABEL_FLAG_ALLOW_CONTINUE    (1 << 1)
3227 
3228 #define DUK_DECL_TYPE_VAR                0
3229 #define DUK_DECL_TYPE_FUNC               1
3230 
3231 /* XXX: optimize to 16 bytes */
3232 typedef struct {
3233 	duk_small_uint_t flags;
3234 	duk_int_t label_id;          /* numeric label_id (-1 reserved as marker) */
3235 	duk_hstring *h_label;        /* borrowed label name */
3236 	duk_int_t catch_depth;       /* catch depth at point of definition */
3237 	duk_int_t pc_label;          /* pc of label statement:
3238 	                              * pc+1: break jump site
3239 	                              * pc+2: continue jump site
3240 	                              */
3241 
3242 	/* Fast jumps (which avoid longjmp) jump directly to the jump sites
3243 	 * which are always known even while the iteration/switch statement
3244 	 * is still being parsed.  A final peephole pass "straightens out"
3245 	 * the jumps.
3246 	 */
3247 } duk_labelinfo;
3248 
3249 /* Compiling state of one function, eventually converted to duk_hcompiledfunction */
3250 struct duk_compiler_func {
3251 	/* These pointers are at the start of the struct so that they pack
3252 	 * nicely.  Mixing pointers and integer values is bad on some
3253 	 * platforms (e.g. if int is 32 bits and pointers are 64 bits).
3254 	 */
3255 
3256 	duk_bufwriter_ctx bw_code;          /* bufwriter for code */
3257 
3258 	duk_hstring *h_name;                /* function name (borrowed reference), ends up in _name */
3259 	/* h_code: held in bw_code */
3260 	duk_hobject *h_consts;              /* array */
3261 	duk_hobject *h_funcs;               /* array of function templates: [func1, offset1, line1, func2, offset2, line2]
3262 	                                     * offset/line points to closing brace to allow skipping on pass 2
3263 	                                     */
3264 	duk_hobject *h_decls;               /* array of declarations: [ name1, val1, name2, val2, ... ]
3265 	                                     * valN = (typeN) | (fnum << 8), where fnum is inner func number (0 for vars)
3266 	                                     * record function and variable declarations in pass 1
3267 	                                     */
3268 	duk_hobject *h_labelnames;          /* array of active label names */
3269 	duk_hbuffer_dynamic *h_labelinfos;  /* C array of duk_labelinfo */
3270 	duk_hobject *h_argnames;            /* array of formal argument names (-> _Formals) */
3271 	duk_hobject *h_varmap;              /* variable map for pass 2 (identifier -> register number or null (unmapped)) */
3272 
3273 	/* value stack indices for tracking objects */
3274 	/* code_idx: not needed */
3275 	duk_idx_t consts_idx;
3276 	duk_idx_t funcs_idx;
3277 	duk_idx_t decls_idx;
3278 	duk_idx_t labelnames_idx;
3279 	duk_idx_t labelinfos_idx;
3280 	duk_idx_t argnames_idx;
3281 	duk_idx_t varmap_idx;
3282 
3283 	/* temp reg handling */
3284 	duk_reg_t temp_first;               /* first register that is a temporary (below: variables) */
3285 	duk_reg_t temp_next;                /* next temporary register to allocate */
3286 	duk_reg_t temp_max;                 /* highest value of temp_reg (temp_max - 1 is highest used reg) */
3287 
3288 	/* shuffle registers if large number of regs/consts */
3289 	duk_reg_t shuffle1;
3290 	duk_reg_t shuffle2;
3291 	duk_reg_t shuffle3;
3292 
3293 	/* stats for current expression being parsed */
3294 	duk_int_t nud_count;
3295 	duk_int_t led_count;
3296 	duk_int_t paren_level;              /* parenthesis count, 0 = top level */
3297 	duk_bool_t expr_lhs;                /* expression is left-hand-side compatible */
3298 	duk_bool_t allow_in;                /* current paren level allows 'in' token */
3299 
3300 	/* misc */
3301 	duk_int_t stmt_next;                /* statement id allocation (running counter) */
3302 	duk_int_t label_next;               /* label id allocation (running counter) */
3303 	duk_int_t catch_depth;              /* catch stack depth */
3304 	duk_int_t with_depth;               /* with stack depth (affects identifier lookups) */
3305 	duk_int_t fnum_next;                /* inner function numbering */
3306 	duk_int_t num_formals;              /* number of formal arguments */
3307 	duk_reg_t reg_stmt_value;           /* register for writing value of 'non-empty' statements (global or eval code), -1 is marker */
3308 #if defined(DUK_USE_DEBUGGER_SUPPORT)
3309 	duk_int_t min_line;                 /* XXX: typing (duk_hcompiledfunction has duk_uint32_t) */
3310 	duk_int_t max_line;
3311 #endif
3312 
3313 	/* status booleans */
3314 	duk_bool_t is_function;             /* is an actual function (not global/eval code) */
3315 	duk_bool_t is_eval;                 /* is eval code */
3316 	duk_bool_t is_global;               /* is global code */
3317 	duk_bool_t is_setget;               /* is a setter/getter */
3318 	duk_bool_t is_decl;                 /* is a function declaration (as opposed to function expression) */
3319 	duk_bool_t is_strict;               /* function is strict */
3320 	duk_bool_t is_notail;               /* function must not be tail called */
3321 	duk_bool_t in_directive_prologue;   /* parsing in "directive prologue", recognize directives */
3322 	duk_bool_t in_scanning;             /* parsing in "scanning" phase (first pass) */
3323 	duk_bool_t may_direct_eval;         /* function may call direct eval */
3324 	duk_bool_t id_access_arguments;     /* function refers to 'arguments' identifier */
3325 	duk_bool_t id_access_slow;          /* function makes one or more slow path accesses */
3326 	duk_bool_t is_arguments_shadowed;   /* argument/function declaration shadows 'arguments' */
3327 	duk_bool_t needs_shuffle;           /* function needs shuffle registers */
3328 	duk_bool_t reject_regexp_in_adv;    /* reject RegExp literal on next advance() call; needed for handling IdentifierName productions */
3329 };
3330 
3331 struct duk_compiler_ctx {
3332 	duk_hthread *thr;
3333 
3334 	/* filename being compiled (ends up in functions' '_filename' property) */
3335 	duk_hstring *h_filename;            /* borrowed reference */
3336 
3337 	/* lexing (tokenization) state (contains two valstack slot indices) */
3338 	duk_lexer_ctx lex;
3339 
3340 	/* current and previous token for parsing */
3341 	duk_token prev_token;
3342 	duk_token curr_token;
3343 	duk_idx_t tok11_idx;                /* curr_token slot1 (matches 'lex' slot1_idx) */
3344 	duk_idx_t tok12_idx;                /* curr_token slot2 (matches 'lex' slot2_idx) */
3345 	duk_idx_t tok21_idx;                /* prev_token slot1 */
3346 	duk_idx_t tok22_idx;                /* prev_token slot2 */
3347 
3348 	/* recursion limit */
3349 	duk_int_t recursion_depth;
3350 	duk_int_t recursion_limit;
3351 
3352 	/* code emission temporary */
3353 	duk_int_t emit_jumpslot_pc;
3354 
3355 	/* current function being compiled (embedded instead of pointer for more compact access) */
3356 	duk_compiler_func curr_func;
3357 };
3358 
3359 /*
3360  *  Prototypes
3361  */
3362 
3363 #define DUK_JS_COMPILE_FLAG_EVAL      (1 << 0)  /* source is eval code (not global) */
3364 #define DUK_JS_COMPILE_FLAG_STRICT    (1 << 1)  /* strict outer context */
3365 #define DUK_JS_COMPILE_FLAG_FUNCEXPR  (1 << 2)  /* source is a function expression (used for Function constructor) */
3366 
3367 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);
3368 
3369 #endif  /* DUK_JS_COMPILER_H_INCLUDED */
3370 /*
3371  *  Regular expression structs, constants, and bytecode defines.
3372  */
3373 
3374 #ifndef DUK_REGEXP_H_INCLUDED
3375 #define DUK_REGEXP_H_INCLUDED
3376 
3377 /* maximum bytecode copies for {n,m} quantifiers */
3378 #define DUK_RE_MAX_ATOM_COPIES             1000
3379 
3380 /* regexp compilation limits */
3381 #define DUK_RE_COMPILE_TOKEN_LIMIT         100000000L   /* 1e8 */
3382 
3383 /* regexp execution limits */
3384 #define DUK_RE_EXECUTE_STEPS_LIMIT         1000000000L  /* 1e9 */
3385 
3386 /* regexp opcodes */
3387 #define DUK_REOP_MATCH                     1
3388 #define DUK_REOP_CHAR                      2
3389 #define DUK_REOP_PERIOD                    3
3390 #define DUK_REOP_RANGES                    4
3391 #define DUK_REOP_INVRANGES                 5
3392 #define DUK_REOP_JUMP                      6
3393 #define DUK_REOP_SPLIT1                    7
3394 #define DUK_REOP_SPLIT2                    8
3395 #define DUK_REOP_SQMINIMAL                 9
3396 #define DUK_REOP_SQGREEDY                  10
3397 #define DUK_REOP_SAVE                      11
3398 #define DUK_REOP_WIPERANGE                 12
3399 #define DUK_REOP_LOOKPOS                   13
3400 #define DUK_REOP_LOOKNEG                   14
3401 #define DUK_REOP_BACKREFERENCE             15
3402 #define DUK_REOP_ASSERT_START              16
3403 #define DUK_REOP_ASSERT_END                17
3404 #define DUK_REOP_ASSERT_WORD_BOUNDARY      18
3405 #define DUK_REOP_ASSERT_NOT_WORD_BOUNDARY  19
3406 
3407 /* flags */
3408 #define DUK_RE_FLAG_GLOBAL                 (1 << 0)
3409 #define DUK_RE_FLAG_IGNORE_CASE            (1 << 1)
3410 #define DUK_RE_FLAG_MULTILINE              (1 << 2)
3411 
3412 struct duk_re_matcher_ctx {
3413 	duk_hthread *thr;
3414 
3415 	duk_uint32_t re_flags;
3416 	const duk_uint8_t *input;
3417 	const duk_uint8_t *input_end;
3418 	const duk_uint8_t *bytecode;
3419 	const duk_uint8_t *bytecode_end;
3420 	const duk_uint8_t **saved;  /* allocated from valstack (fixed buffer) */
3421 	duk_uint32_t nsaved;
3422 	duk_uint32_t recursion_depth;
3423 	duk_uint32_t recursion_limit;
3424 	duk_uint32_t steps_count;
3425 	duk_uint32_t steps_limit;
3426 };
3427 
3428 struct duk_re_compiler_ctx {
3429 	duk_hthread *thr;
3430 
3431 	duk_uint32_t re_flags;
3432 	duk_lexer_ctx lex;
3433 	duk_re_token curr_token;
3434 	duk_bufwriter_ctx bw;
3435 	duk_uint32_t captures;  /* highest capture number emitted so far (used as: ++captures) */
3436 	duk_uint32_t highest_backref;
3437 	duk_uint32_t recursion_depth;
3438 	duk_uint32_t recursion_limit;
3439 	duk_uint32_t nranges;  /* internal temporary value, used for char classes */
3440 };
3441 
3442 /*
3443  *  Prototypes
3444  */
3445 
3446 DUK_INTERNAL_DECL void duk_regexp_compile(duk_hthread *thr);
3447 DUK_INTERNAL_DECL void duk_regexp_create_instance(duk_hthread *thr);
3448 DUK_INTERNAL_DECL void duk_regexp_match(duk_hthread *thr);
3449 DUK_INTERNAL_DECL void duk_regexp_match_force_global(duk_hthread *thr);  /* hacky helper for String.prototype.split() */
3450 
3451 #endif  /* DUK_REGEXP_H_INCLUDED */
3452 /*
3453  *  Heap header definition and assorted macros, including ref counting.
3454  *  Access all fields through the accessor macros.
3455  */
3456 
3457 #ifndef DUK_HEAPHDR_H_INCLUDED
3458 #define DUK_HEAPHDR_H_INCLUDED
3459 
3460 /*
3461  *  Common heap header
3462  *
3463  *  All heap objects share the same flags and refcount fields.  Objects other
3464  *  than strings also need to have a single or double linked list pointers
3465  *  for insertion into the "heap allocated" list.  Strings are held in the
3466  *  heap-wide string table so they don't need link pointers.
3467  *
3468  *  Technically, 'h_refcount' must be wide enough to guarantee that it cannot
3469  *  wrap (otherwise objects might be freed incorrectly after wrapping).  This
3470  *  means essentially that the refcount field must be as wide as data pointers.
3471  *  On 64-bit platforms this means that the refcount needs to be 64 bits even
3472  *  if an 'int' is 32 bits.  This is a bit unfortunate, and compromising on
3473  *  this might be reasonable in the future.
3474  *
3475  *  Heap header size on 32-bit platforms: 8 bytes without reference counting,
3476  *  16 bytes with reference counting.
3477  */
3478 
3479 struct duk_heaphdr {
3480 	duk_uint32_t h_flags;
3481 
3482 #if defined(DUK_USE_REFERENCE_COUNTING)
3483 #if defined(DUK_USE_REFCOUNT16)
3484 	duk_uint16_t h_refcount16;
3485 #else
3486 	duk_size_t h_refcount;
3487 #endif
3488 #endif
3489 
3490 #if defined(DUK_USE_HEAPPTR16)
3491 	duk_uint16_t h_next16;
3492 #else
3493 	duk_heaphdr *h_next;
3494 #endif
3495 
3496 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
3497 	/* refcounting requires direct heap frees, which in turn requires a dual linked heap */
3498 #if defined(DUK_USE_HEAPPTR16)
3499 	duk_uint16_t h_prev16;
3500 #else
3501 	duk_heaphdr *h_prev;
3502 #endif
3503 #endif
3504 
3505 	/* When DUK_USE_HEAPPTR16 (and DUK_USE_REFCOUNT16) is in use, the
3506 	 * struct won't align nicely to 4 bytes.  This 16-bit extra field
3507 	 * is added to make the alignment clean; the field can be used by
3508 	 * heap objects when 16-bit packing is used.  This field is now
3509 	 * conditional to DUK_USE_HEAPPTR16 only, but it is intended to be
3510 	 * used with DUK_USE_REFCOUNT16 and DUK_USE_DOUBLE_LINKED_HEAP;
3511 	 * this only matter to low memory environments anyway.
3512 	 */
3513 #if defined(DUK_USE_HEAPPTR16)
3514 	duk_uint16_t h_extra16;
3515 #endif
3516 };
3517 
3518 struct duk_heaphdr_string {
3519 	/* 16 bits would be enough for shared heaphdr flags and duk_hstring
3520 	 * flags.  The initial parts of duk_heaphdr_string and duk_heaphdr
3521 	 * must match so changing the flags field size here would be quite
3522 	 * awkward.  However, to minimize struct size, we can pack at least
3523 	 * 16 bits of duk_hstring data into the flags field.
3524 	 */
3525 	duk_uint32_t h_flags;
3526 
3527 #if defined(DUK_USE_REFERENCE_COUNTING)
3528 #if defined(DUK_USE_REFCOUNT16)
3529 	duk_uint16_t h_refcount16;
3530 	duk_uint16_t h_strextra16;  /* round out to 8 bytes */
3531 #else
3532 	duk_size_t h_refcount;
3533 #endif
3534 #else
3535 	duk_uint16_t h_strextra16;
3536 #endif
3537 };
3538 
3539 #define DUK_HEAPHDR_FLAGS_TYPE_MASK      0x00000003UL
3540 #define DUK_HEAPHDR_FLAGS_FLAG_MASK      (~DUK_HEAPHDR_FLAGS_TYPE_MASK)
3541 
3542                                              /* 2 bits for heap type */
3543 #define DUK_HEAPHDR_FLAGS_HEAP_START     2   /* 5 heap flags */
3544 #define DUK_HEAPHDR_FLAGS_USER_START     7   /* 25 user flags */
3545 
3546 #define DUK_HEAPHDR_HEAP_FLAG_NUMBER(n)  (DUK_HEAPHDR_FLAGS_HEAP_START + (n))
3547 #define DUK_HEAPHDR_USER_FLAG_NUMBER(n)  (DUK_HEAPHDR_FLAGS_USER_START + (n))
3548 #define DUK_HEAPHDR_HEAP_FLAG(n)         (1UL << (DUK_HEAPHDR_FLAGS_HEAP_START + (n)))
3549 #define DUK_HEAPHDR_USER_FLAG(n)         (1UL << (DUK_HEAPHDR_FLAGS_USER_START + (n)))
3550 
3551 #define DUK_HEAPHDR_FLAG_REACHABLE       DUK_HEAPHDR_HEAP_FLAG(0)  /* mark-and-sweep: reachable */
3552 #define DUK_HEAPHDR_FLAG_TEMPROOT        DUK_HEAPHDR_HEAP_FLAG(1)  /* mark-and-sweep: children not processed */
3553 #define DUK_HEAPHDR_FLAG_FINALIZABLE     DUK_HEAPHDR_HEAP_FLAG(2)  /* mark-and-sweep: finalizable (on current pass) */
3554 #define DUK_HEAPHDR_FLAG_FINALIZED       DUK_HEAPHDR_HEAP_FLAG(3)  /* mark-and-sweep: finalized (on previous pass) */
3555 #define DUK_HEAPHDR_FLAG_READONLY        DUK_HEAPHDR_HEAP_FLAG(4)  /* read-only object, in code section */
3556 
3557 #define DUK_HTYPE_MIN                    1
3558 #define DUK_HTYPE_STRING                 1
3559 #define DUK_HTYPE_OBJECT                 2
3560 #define DUK_HTYPE_BUFFER                 3
3561 #define DUK_HTYPE_MAX                    3
3562 
3563 #if defined(DUK_USE_HEAPPTR16)
3564 #define DUK_HEAPHDR_GET_NEXT(heap,h) \
3565 	((duk_heaphdr *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->h_next16))
3566 #define DUK_HEAPHDR_SET_NEXT(heap,h,val)   do { \
3567 		(h)->h_next16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) val); \
3568 	} while (0)
3569 #else
3570 #define DUK_HEAPHDR_GET_NEXT(heap,h)  ((h)->h_next)
3571 #define DUK_HEAPHDR_SET_NEXT(heap,h,val)   do { \
3572 		(h)->h_next = (val); \
3573 	} while (0)
3574 #endif
3575 
3576 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
3577 #if defined(DUK_USE_HEAPPTR16)
3578 #define DUK_HEAPHDR_GET_PREV(heap,h) \
3579 	((duk_heaphdr *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->h_prev16))
3580 #define DUK_HEAPHDR_SET_PREV(heap,h,val)   do { \
3581 		(h)->h_prev16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (val)); \
3582 	} while (0)
3583 #else
3584 #define DUK_HEAPHDR_GET_PREV(heap,h)       ((h)->h_prev)
3585 #define DUK_HEAPHDR_SET_PREV(heap,h,val)   do { \
3586 		(h)->h_prev = (val); \
3587 	} while (0)
3588 #endif
3589 #endif
3590 
3591 #if defined(DUK_USE_REFERENCE_COUNTING)
3592 #if defined(DUK_USE_REFCOUNT16)
3593 #define DUK_HEAPHDR_GET_REFCOUNT(h)   ((h)->h_refcount16)
3594 #define DUK_HEAPHDR_SET_REFCOUNT(h,val)  do { \
3595 		(h)->h_refcount16 = (val); \
3596 	} while (0)
3597 #define DUK_HEAPHDR_PREINC_REFCOUNT(h)  (++(h)->h_refcount16)  /* result: updated refcount */
3598 #define DUK_HEAPHDR_PREDEC_REFCOUNT(h)  (--(h)->h_refcount16)  /* result: updated refcount */
3599 #else
3600 #define DUK_HEAPHDR_GET_REFCOUNT(h)   ((h)->h_refcount)
3601 #define DUK_HEAPHDR_SET_REFCOUNT(h,val)  do { \
3602 		(h)->h_refcount = (val); \
3603 	} while (0)
3604 #define DUK_HEAPHDR_PREINC_REFCOUNT(h)  (++(h)->h_refcount)  /* result: updated refcount */
3605 #define DUK_HEAPHDR_PREDEC_REFCOUNT(h)  (--(h)->h_refcount)  /* result: updated refcount */
3606 #endif
3607 #else
3608 /* refcount macros not defined without refcounting, caller must #ifdef now */
3609 #endif  /* DUK_USE_REFERENCE_COUNTING */
3610 
3611 /*
3612  *  Note: type is treated as a field separate from flags, so some masking is
3613  *  involved in the macros below.
3614  */
3615 
3616 #define DUK_HEAPHDR_GET_FLAGS_RAW(h)  ((h)->h_flags)
3617 
3618 #define DUK_HEAPHDR_GET_FLAGS(h)      ((h)->h_flags & DUK_HEAPHDR_FLAGS_FLAG_MASK)
3619 #define DUK_HEAPHDR_SET_FLAGS(h,val)  do { \
3620 		(h)->h_flags = ((h)->h_flags & ~(DUK_HEAPHDR_FLAGS_FLAG_MASK)) | (val); \
3621 	} while (0)
3622 
3623 #define DUK_HEAPHDR_GET_TYPE(h)       ((h)->h_flags & DUK_HEAPHDR_FLAGS_TYPE_MASK)
3624 #define DUK_HEAPHDR_SET_TYPE(h,val)   do { \
3625 		(h)->h_flags = ((h)->h_flags & ~(DUK_HEAPHDR_FLAGS_TYPE_MASK)) | (val); \
3626 	} while (0)
3627 
3628 #define DUK_HEAPHDR_HTYPE_VALID(h)    ( \
3629 	DUK_HEAPHDR_GET_TYPE((h)) >= DUK_HTYPE_MIN && \
3630 	DUK_HEAPHDR_GET_TYPE((h)) <= DUK_HTYPE_MAX \
3631 	)
3632 
3633 #define DUK_HEAPHDR_SET_TYPE_AND_FLAGS(h,tval,fval)  do { \
3634 		(h)->h_flags = ((tval) & DUK_HEAPHDR_FLAGS_TYPE_MASK) | \
3635 		               ((fval) & DUK_HEAPHDR_FLAGS_FLAG_MASK); \
3636 	} while (0)
3637 
3638 #define DUK_HEAPHDR_SET_FLAG_BITS(h,bits)  do { \
3639 		DUK_ASSERT(((bits) & ~(DUK_HEAPHDR_FLAGS_FLAG_MASK)) == 0); \
3640 		(h)->h_flags |= (bits); \
3641 	} while (0)
3642 
3643 #define DUK_HEAPHDR_CLEAR_FLAG_BITS(h,bits)  do { \
3644 		DUK_ASSERT(((bits) & ~(DUK_HEAPHDR_FLAGS_FLAG_MASK)) == 0); \
3645 		(h)->h_flags &= ~((bits)); \
3646 	} while (0)
3647 
3648 #define DUK_HEAPHDR_CHECK_FLAG_BITS(h,bits)  (((h)->h_flags & (bits)) != 0)
3649 
3650 #define DUK_HEAPHDR_SET_REACHABLE(h)      DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_REACHABLE)
3651 #define DUK_HEAPHDR_CLEAR_REACHABLE(h)    DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_REACHABLE)
3652 #define DUK_HEAPHDR_HAS_REACHABLE(h)      DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_REACHABLE)
3653 
3654 #define DUK_HEAPHDR_SET_TEMPROOT(h)       DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_TEMPROOT)
3655 #define DUK_HEAPHDR_CLEAR_TEMPROOT(h)     DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_TEMPROOT)
3656 #define DUK_HEAPHDR_HAS_TEMPROOT(h)       DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_TEMPROOT)
3657 
3658 #define DUK_HEAPHDR_SET_FINALIZABLE(h)    DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZABLE)
3659 #define DUK_HEAPHDR_CLEAR_FINALIZABLE(h)  DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZABLE)
3660 #define DUK_HEAPHDR_HAS_FINALIZABLE(h)    DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZABLE)
3661 
3662 #define DUK_HEAPHDR_SET_FINALIZED(h)      DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZED)
3663 #define DUK_HEAPHDR_CLEAR_FINALIZED(h)    DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZED)
3664 #define DUK_HEAPHDR_HAS_FINALIZED(h)      DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZED)
3665 
3666 #define DUK_HEAPHDR_SET_READONLY(h)       DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_READONLY)
3667 #define DUK_HEAPHDR_CLEAR_READONLY(h)     DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_READONLY)
3668 #define DUK_HEAPHDR_HAS_READONLY(h)       DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_READONLY)
3669 
3670 /* get or set a range of flags; m=first bit number, n=number of bits */
3671 #define DUK_HEAPHDR_GET_FLAG_RANGE(h,m,n)  (((h)->h_flags >> (m)) & ((1UL << (n)) - 1UL))
3672 
3673 #define DUK_HEAPHDR_SET_FLAG_RANGE(h,m,n,v)  do { \
3674 		(h)->h_flags = \
3675 			((h)->h_flags & (~(((1UL << (n)) - 1UL) << (m)))) \
3676 			| ((v) << (m)); \
3677 	} while (0)
3678 
3679 /* init pointer fields to null */
3680 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
3681 #define DUK_HEAPHDR_INIT_NULLS(h)       do { \
3682 		DUK_HEAPHDR_SET_NEXT((h), (void *) NULL); \
3683 		DUK_HEAPHDR_SET_PREV((h), (void *) NULL); \
3684 	} while (0)
3685 #else
3686 #define DUK_HEAPHDR_INIT_NULLS(h)       do { \
3687 		DUK_HEAPHDR_SET_NEXT((h), (void *) NULL); \
3688 	} while (0)
3689 #endif
3690 
3691 #define DUK_HEAPHDR_STRING_INIT_NULLS(h)  /* currently nop */
3692 
3693 /*
3694  *  Assert helpers
3695  */
3696 
3697 /* Check that prev/next links are consistent: if e.g. h->prev is != NULL,
3698  * h->prev->next should point back to h.
3699  */
3700 #if defined(DUK_USE_DOUBLE_LINKED_HEAP) && defined(DUK_USE_ASSERTIONS)
3701 #define DUK_ASSERT_HEAPHDR_LINKS(heap,h) do { \
3702 		if ((h) != NULL) { \
3703 			duk_heaphdr *h__prev, *h__next; \
3704 			h__prev = DUK_HEAPHDR_GET_PREV((heap), (h)); \
3705 			h__next = DUK_HEAPHDR_GET_NEXT((heap), (h)); \
3706 			DUK_ASSERT(h__prev == NULL || (DUK_HEAPHDR_GET_NEXT((heap), h__prev) == (h))); \
3707 			DUK_ASSERT(h__next == NULL || (DUK_HEAPHDR_GET_PREV((heap), h__next) == (h))); \
3708 		} \
3709 	} while (0)
3710 #else
3711 #define DUK_ASSERT_HEAPHDR_LINKS(heap,h) do {} while (0)
3712 #endif
3713 
3714 /*
3715  *  Reference counting helper macros.  The macros take a thread argument
3716  *  and must thus always be executed in a specific thread context.  The
3717  *  thread argument is needed for features like finalization.  Currently
3718  *  it is not required for INCREF, but it is included just in case.
3719  *
3720  *  Note that 'raw' macros such as DUK_HEAPHDR_GET_REFCOUNT() are not
3721  *  defined without DUK_USE_REFERENCE_COUNTING, so caller must #ifdef
3722  *  around them.
3723  */
3724 
3725 #if defined(DUK_USE_REFERENCE_COUNTING)
3726 
3727 #if defined(DUK_USE_ROM_OBJECTS)
3728 /* With ROM objects "needs refcount update" is true when the value is
3729  * heap allocated and is not a ROM object.
3730  */
3731 /* XXX: double evaluation for 'tv' argument. */
3732 #define DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv) \
3733 	(DUK_TVAL_IS_HEAP_ALLOCATED((tv)) && !DUK_HEAPHDR_HAS_READONLY(DUK_TVAL_GET_HEAPHDR((tv))))
3734 #define DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(h)  (!DUK_HEAPHDR_HAS_READONLY((h)))
3735 #else  /* DUK_USE_ROM_OBJECTS */
3736 /* Without ROM objects "needs refcount update" == is heap allocated. */
3737 #define DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv)    DUK_TVAL_IS_HEAP_ALLOCATED((tv))
3738 #define DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(h)  1
3739 #endif  /* DUK_USE_ROM_OBJECTS */
3740 
3741 /* Fast variants, inline refcount operations except for refzero handling.
3742  * Can be used explicitly when speed is always more important than size.
3743  * For a good compiler and a single file build, these are basically the
3744  * same as a forced inline.
3745  */
3746 #define DUK_TVAL_INCREF_FAST(thr,tv) do { \
3747 		duk_tval *duk__tv = (tv); \
3748 		DUK_ASSERT(duk__tv != NULL); \
3749 		if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(duk__tv)) { \
3750 			duk_heaphdr *duk__h = DUK_TVAL_GET_HEAPHDR(duk__tv); \
3751 			DUK_ASSERT(duk__h != NULL); \
3752 			DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
3753 			DUK_HEAPHDR_PREINC_REFCOUNT(duk__h); \
3754 		} \
3755 	} while (0)
3756 #define DUK_TVAL_DECREF_FAST(thr,tv) do { \
3757 		duk_tval *duk__tv = (tv); \
3758 		DUK_ASSERT(duk__tv != NULL); \
3759 		if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(duk__tv)) { \
3760 			duk_heaphdr *duk__h = DUK_TVAL_GET_HEAPHDR(duk__tv); \
3761 			DUK_ASSERT(duk__h != NULL); \
3762 			DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
3763 			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) > 0); \
3764 			if (DUK_HEAPHDR_PREDEC_REFCOUNT(duk__h) == 0) { \
3765 				duk_heaphdr_refzero((thr), duk__h); \
3766 			} \
3767 		} \
3768 	} while (0)
3769 #define DUK_HEAPHDR_INCREF_FAST(thr,h) do { \
3770 		duk_heaphdr *duk__h = (duk_heaphdr *) (h); \
3771 		DUK_ASSERT(duk__h != NULL); \
3772 		DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
3773 		if (DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(duk__h)) { \
3774 			DUK_HEAPHDR_PREINC_REFCOUNT(duk__h); \
3775 		} \
3776 	} while (0)
3777 #define DUK_HEAPHDR_DECREF_FAST(thr,h) do { \
3778 		duk_heaphdr *duk__h = (duk_heaphdr *) (h); \
3779 		DUK_ASSERT(duk__h != NULL); \
3780 		DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
3781 		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) > 0); \
3782 		if (DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(duk__h)) { \
3783 			if (DUK_HEAPHDR_PREDEC_REFCOUNT(duk__h) == 0) { \
3784 				duk_heaphdr_refzero((thr), duk__h); \
3785 			} \
3786 		} \
3787 	} while (0)
3788 
3789 /* Slow variants, call to a helper to reduce code size.
3790  * Can be used explicitly when size is always more important than speed.
3791  */
3792 #define DUK_TVAL_INCREF_SLOW(thr,tv) do { \
3793 		duk_tval_incref((tv)); \
3794 	} while (0)
3795 #define DUK_TVAL_DECREF_SLOW(thr,tv) do { \
3796 		duk_tval_decref((thr), (tv)); \
3797 	} while (0)
3798 #define DUK_HEAPHDR_INCREF_SLOW(thr,h) do { \
3799 		duk_heaphdr_incref((duk_heaphdr *) (h)); \
3800 	} while (0)
3801 #define DUK_HEAPHDR_DECREF_SLOW(thr,h) do { \
3802 		duk_heaphdr_decref((thr), (duk_heaphdr *) (h)); \
3803 	} while (0)
3804 
3805 /* Default variants.  Selection depends on speed/size preference.
3806  * Concretely: with gcc 4.8.1 -Os x64 the difference in final binary
3807  * is about +1kB for _FAST variants.
3808  */
3809 #if defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
3810 #define DUK_TVAL_INCREF(thr,tv)                DUK_TVAL_INCREF_FAST((thr),(tv))
3811 #define DUK_TVAL_DECREF(thr,tv)                DUK_TVAL_DECREF_FAST((thr),(tv))
3812 #define DUK_HEAPHDR_INCREF(thr,h)              DUK_HEAPHDR_INCREF_FAST((thr),(h))
3813 #define DUK_HEAPHDR_DECREF(thr,h)              DUK_HEAPHDR_DECREF_FAST((thr),(h))
3814 #else
3815 #define DUK_TVAL_INCREF(thr,tv)                DUK_TVAL_INCREF_SLOW((thr),(tv))
3816 #define DUK_TVAL_DECREF(thr,tv)                DUK_TVAL_DECREF_SLOW((thr),(tv))
3817 #define DUK_HEAPHDR_INCREF(thr,h)              DUK_HEAPHDR_INCREF_SLOW((thr),(h))
3818 #define DUK_HEAPHDR_DECREF(thr,h)              DUK_HEAPHDR_DECREF_SLOW((thr),(h))
3819 #endif
3820 
3821 /* Casting convenience. */
3822 #define DUK_HSTRING_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
3823 #define DUK_HSTRING_DECREF(thr,h)              DUK_HEAPHDR_DECREF((thr),(duk_heaphdr *) (h))
3824 #define DUK_HOBJECT_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
3825 #define DUK_HOBJECT_DECREF(thr,h)              DUK_HEAPHDR_DECREF((thr),(duk_heaphdr *) (h))
3826 #define DUK_HBUFFER_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
3827 #define DUK_HBUFFER_DECREF(thr,h)              DUK_HEAPHDR_DECREF((thr),(duk_heaphdr *) (h))
3828 #define DUK_HCOMPILEDFUNCTION_INCREF(thr,h)    DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
3829 #define DUK_HCOMPILEDFUNCTION_DECREF(thr,h)    DUK_HEAPHDR_DECREF((thr),(duk_heaphdr *) &(h)->obj)
3830 #define DUK_HNATIVEFUNCTION_INCREF(thr,h)      DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
3831 #define DUK_HNATIVEFUNCTION_DECREF(thr,h)      DUK_HEAPHDR_DECREF((thr),(duk_heaphdr *) &(h)->obj)
3832 #define DUK_HBUFFEROBJECT_INCREF(thr,h)        DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
3833 #define DUK_HBUFFEROBJECT_DECREF(thr,h)        DUK_HEAPHDR_DECREF((thr),(duk_heaphdr *) &(h)->obj)
3834 #define DUK_HTHREAD_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
3835 #define DUK_HTHREAD_DECREF(thr,h)              DUK_HEAPHDR_DECREF((thr),(duk_heaphdr *) &(h)->obj)
3836 
3837 /* Convenience for some situations; the above macros don't allow NULLs
3838  * for performance reasons.
3839  */
3840 #define DUK_HOBJECT_INCREF_ALLOWNULL(thr,h) do { \
3841 		if ((h) != NULL) { \
3842 			DUK_HEAPHDR_INCREF((thr), (duk_heaphdr *) (h)); \
3843 		} \
3844 	} while (0)
3845 #define DUK_HOBJECT_DECREF_ALLOWNULL(thr,h) do { \
3846 		if ((h) != NULL) { \
3847 			DUK_HEAPHDR_DECREF((thr), (duk_heaphdr *) (h)); \
3848 		} \
3849 	} while (0)
3850 
3851 /*
3852  *  Macros to set a duk_tval and update refcount of the target (decref the
3853  *  old value and incref the new value if necessary).  This is both performance
3854  *  and footprint critical; any changes made should be measured for size/speed.
3855  */
3856 
3857 #define DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0(thr,tvptr_dst) do { \
3858 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
3859 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
3860 		DUK_TVAL_SET_UNDEFINED(tv__dst); \
3861 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
3862 	} while (0)
3863 
3864 #define DUK_TVAL_SET_UNUSED_UPDREF_ALT0(thr,tvptr_dst) do { \
3865 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
3866 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
3867 		DUK_TVAL_SET_UNUSED(tv__dst); \
3868 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
3869 	} while (0)
3870 
3871 #define DUK_TVAL_SET_NULL_UPDREF_ALT0(thr,tvptr_dst) do { \
3872 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
3873 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
3874 		DUK_TVAL_SET_NULL(tv__dst); \
3875 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
3876 	} while (0)
3877 
3878 #define DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
3879 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
3880 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
3881 		DUK_TVAL_SET_BOOLEAN(tv__dst, (newval)); \
3882 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
3883 	} while (0)
3884 
3885 #define DUK_TVAL_SET_NUMBER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
3886 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
3887 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
3888 		DUK_TVAL_SET_NUMBER(tv__dst, (newval)); \
3889 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
3890 	} while (0)
3891 #define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
3892 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
3893 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
3894 		DUK_TVAL_SET_NUMBER_CHKFAST(tv__dst, (newval)); \
3895 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
3896 	} while (0)
3897 #define DUK_TVAL_SET_DOUBLE_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
3898 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
3899 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
3900 		DUK_TVAL_SET_DOUBLE(tv__dst, (newval)); \
3901 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
3902 	} while (0)
3903 #define DUK_TVAL_SET_NAN_UPDREF_ALT0(thr,tvptr_dst) do { \
3904 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
3905 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
3906 		DUK_TVAL_SET_NAN(tv__dst); \
3907 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
3908 	} while (0)
3909 #if defined(DUK_USE_FASTINT)
3910 #define DUK_TVAL_SET_FASTINT_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
3911 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
3912 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
3913 		DUK_TVAL_SET_FASTINT(tv__dst, (newval)); \
3914 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
3915 	} while (0)
3916 #define DUK_TVAL_SET_FASTINT_I32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
3917 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
3918 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
3919 		DUK_TVAL_SET_FASTINT_I32(tv__dst, (newval)); \
3920 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
3921 	} while (0)
3922 #define DUK_TVAL_SET_FASTINT_U32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
3923 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
3924 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
3925 		DUK_TVAL_SET_FASTINT_U32(tv__dst, (newval)); \
3926 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
3927 	} while (0)
3928 #else
3929 #define DUK_TVAL_SET_DOUBLE_CAST_UPDREF(thr,tvptr_dst,newval) \
3930 	DUK_TVAL_SET_DOUBLE_UPDREF((thr), (tvptr_dst), (duk_double_t) (newval))
3931 #endif  /* DUK_USE_FASTINT */
3932 
3933 #define DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0(thr,tvptr_dst,lf_v,lf_fp,lf_flags) do { \
3934 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
3935 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
3936 		DUK_TVAL_SET_LIGHTFUNC(tv__dst, (lf_v), (lf_fp), (lf_flags)); \
3937 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
3938 	} while (0)
3939 
3940 #define DUK_TVAL_SET_STRING_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
3941 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
3942 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
3943 		DUK_TVAL_SET_STRING(tv__dst, (newval)); \
3944 		DUK_HSTRING_INCREF((thr), (newval)); \
3945 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
3946 	} while (0)
3947 
3948 #define DUK_TVAL_SET_OBJECT_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
3949 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
3950 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
3951 		DUK_TVAL_SET_OBJECT(tv__dst, (newval)); \
3952 		DUK_HOBJECT_INCREF((thr), (newval)); \
3953 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
3954 	} while (0)
3955 
3956 #define DUK_TVAL_SET_BUFFER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
3957 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
3958 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
3959 		DUK_TVAL_SET_BUFFER(tv__dst, (newval)); \
3960 		DUK_HBUFFER_INCREF((thr), (newval)); \
3961 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
3962 	} while (0)
3963 
3964 #define DUK_TVAL_SET_POINTER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
3965 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
3966 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
3967 		DUK_TVAL_SET_POINTER(tv__dst, (newval)); \
3968 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
3969 	} while (0)
3970 
3971 /* DUK_TVAL_SET_TVAL_UPDREF() is used a lot in executor, property lookups,
3972  * etc, so it's very important for performance.  Measure when changing.
3973  *
3974  * NOTE: the source and destination duk_tval pointers may be the same, and
3975  * the macros MUST deal with that correctly.
3976  */
3977 
3978 /* Original idiom used, minimal code size. */
3979 #define DUK_TVAL_SET_TVAL_UPDREF_ALT0(thr,tvptr_dst,tvptr_src) do { \
3980 		duk_tval *tv__dst, *tv__src; duk_tval tv__tmp; \
3981 		tv__dst = (tvptr_dst); tv__src = (tvptr_src); \
3982 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
3983 		DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
3984 		DUK_TVAL_INCREF((thr), tv__src); \
3985 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
3986 	} while (0)
3987 
3988 /* Faster alternative: avoid making a temporary copy of tvptr_dst and use
3989  * fast incref/decref macros.
3990  */
3991 #define DUK_TVAL_SET_TVAL_UPDREF_ALT1(thr,tvptr_dst,tvptr_src) do { \
3992 		duk_tval *tv__dst, *tv__src; duk_heaphdr *h__obj; \
3993 		tv__dst = (tvptr_dst); tv__src = (tvptr_src); \
3994 		DUK_TVAL_INCREF_FAST((thr), tv__src); \
3995 		if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv__dst)) { \
3996 			h__obj = DUK_TVAL_GET_HEAPHDR(tv__dst); \
3997 			DUK_ASSERT(h__obj != NULL); \
3998 			DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
3999 			DUK_HEAPHDR_DECREF_FAST((thr), h__obj);  /* side effects */ \
4000 		} else { \
4001 			DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
4002 		} \
4003 	} while (0)
4004 
4005 /* XXX: no optimized variants yet */
4006 #define DUK_TVAL_SET_UNDEFINED_UPDREF         DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0
4007 #define DUK_TVAL_SET_UNUSED_UPDREF            DUK_TVAL_SET_UNUSED_UPDREF_ALT0
4008 #define DUK_TVAL_SET_NULL_UPDREF              DUK_TVAL_SET_NULL_UPDREF_ALT0
4009 #define DUK_TVAL_SET_BOOLEAN_UPDREF           DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0
4010 #define DUK_TVAL_SET_NUMBER_UPDREF            DUK_TVAL_SET_NUMBER_UPDREF_ALT0
4011 #define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF    DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0
4012 #define DUK_TVAL_SET_DOUBLE_UPDREF            DUK_TVAL_SET_DOUBLE_UPDREF_ALT0
4013 #define DUK_TVAL_SET_NAN_UPDREF               DUK_TVAL_SET_NAN_UPDREF_ALT0
4014 #if defined(DUK_USE_FASTINT)
4015 #define DUK_TVAL_SET_FASTINT_UPDREF           DUK_TVAL_SET_FASTINT_UPDREF_ALT0
4016 #define DUK_TVAL_SET_FASTINT_I32_UPDREF       DUK_TVAL_SET_FASTINT_I32_UPDREF_ALT0
4017 #define DUK_TVAL_SET_FASTINT_U32_UPDREF       DUK_TVAL_SET_FASTINT_U32_UPDREF_ALT0
4018 #else
4019 #define DUK_TVAL_SET_FASTINT_UPDREF           DUK_TVAL_SET_DOUBLE_CAST_UPDREF  /* XXX: fast int-to-double */
4020 #define DUK_TVAL_SET_FASTINT_I32_UPDREF       DUK_TVAL_SET_DOUBLE_CAST_UPDREF
4021 #define DUK_TVAL_SET_FASTINT_U32_UPDREF       DUK_TVAL_SET_DOUBLE_CAST_UPDREF
4022 #endif  /* DUK_USE_FASTINT */
4023 #define DUK_TVAL_SET_LIGHTFUNC_UPDREF         DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0
4024 #define DUK_TVAL_SET_STRING_UPDREF            DUK_TVAL_SET_STRING_UPDREF_ALT0
4025 #define DUK_TVAL_SET_OBJECT_UPDREF            DUK_TVAL_SET_OBJECT_UPDREF_ALT0
4026 #define DUK_TVAL_SET_BUFFER_UPDREF            DUK_TVAL_SET_BUFFER_UPDREF_ALT0
4027 #define DUK_TVAL_SET_POINTER_UPDREF           DUK_TVAL_SET_POINTER_UPDREF_ALT0
4028 
4029 #if defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
4030 /* Optimized for speed. */
4031 #define DUK_TVAL_SET_TVAL_UPDREF              DUK_TVAL_SET_TVAL_UPDREF_ALT1
4032 #define DUK_TVAL_SET_TVAL_UPDREF_FAST         DUK_TVAL_SET_TVAL_UPDREF_ALT1
4033 #define DUK_TVAL_SET_TVAL_UPDREF_SLOW         DUK_TVAL_SET_TVAL_UPDREF_ALT0
4034 #else
4035 /* Optimized for size. */
4036 #define DUK_TVAL_SET_TVAL_UPDREF              DUK_TVAL_SET_TVAL_UPDREF_ALT0
4037 #define DUK_TVAL_SET_TVAL_UPDREF_FAST         DUK_TVAL_SET_TVAL_UPDREF_ALT0
4038 #define DUK_TVAL_SET_TVAL_UPDREF_SLOW         DUK_TVAL_SET_TVAL_UPDREF_ALT0
4039 #endif
4040 
4041 #else  /* DUK_USE_REFERENCE_COUNTING */
4042 
4043 #define DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv)     0
4044 #define DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(h)   0
4045 
4046 #define DUK_TVAL_INCREF_FAST(thr,v)            do {} while (0) /* nop */
4047 #define DUK_TVAL_DECREF_FAST(thr,v)            do {} while (0) /* nop */
4048 #define DUK_TVAL_INCREF_SLOW(thr,v)            do {} while (0) /* nop */
4049 #define DUK_TVAL_DECREF_SLOW(thr,v)            do {} while (0) /* nop */
4050 #define DUK_TVAL_INCREF(thr,v)                 do {} while (0) /* nop */
4051 #define DUK_TVAL_DECREF(thr,v)                 do {} while (0) /* nop */
4052 #define DUK_HEAPHDR_INCREF_FAST(thr,h)         do {} while (0) /* nop */
4053 #define DUK_HEAPHDR_DECREF_FAST(thr,h)         do {} while (0) /* nop */
4054 #define DUK_HEAPHDR_INCREF_SLOW(thr,h)         do {} while (0) /* nop */
4055 #define DUK_HEAPHDR_DECREF_SLOW(thr,h)         do {} while (0) /* nop */
4056 #define DUK_HEAPHDR_INCREF(thr,h)              do {} while (0) /* nop */
4057 #define DUK_HEAPHDR_DECREF(thr,h)              do {} while (0) /* nop */
4058 #define DUK_HSTRING_INCREF(thr,h)              do {} while (0) /* nop */
4059 #define DUK_HSTRING_DECREF(thr,h)              do {} while (0) /* nop */
4060 #define DUK_HOBJECT_INCREF(thr,h)              do {} while (0) /* nop */
4061 #define DUK_HOBJECT_DECREF(thr,h)              do {} while (0) /* nop */
4062 #define DUK_HBUFFER_INCREF(thr,h)              do {} while (0) /* nop */
4063 #define DUK_HBUFFER_DECREF(thr,h)              do {} while (0) /* nop */
4064 #define DUK_HCOMPILEDFUNCTION_INCREF(thr,h)    do {} while (0) /* nop */
4065 #define DUK_HCOMPILEDFUNCTION_DECREF(thr,h)    do {} while (0) /* nop */
4066 #define DUK_HNATIVEFUNCTION_INCREF(thr,h)      do {} while (0) /* nop */
4067 #define DUK_HNATIVEFUNCTION_DECREF(thr,h)      do {} while (0) /* nop */
4068 #define DUK_HBUFFEROBJECT_INCREF(thr,h)        do {} while (0) /* nop */
4069 #define DUK_HBUFFEROBJECT_DECREF(thr,h)        do {} while (0) /* nop */
4070 #define DUK_HTHREAD_INCREF(thr,h)              do {} while (0) /* nop */
4071 #define DUK_HTHREAD_DECREF(thr,h)              do {} while (0) /* nop */
4072 #define DUK_HOBJECT_INCREF_ALLOWNULL(thr,h)    do {} while (0) /* nop */
4073 #define DUK_HOBJECT_DECREF_ALLOWNULL(thr,h)    do {} while (0) /* nop */
4074 
4075 #define DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0(thr,tvptr_dst) do { \
4076 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4077 		DUK_TVAL_SET_UNDEFINED(tv__dst); \
4078 		DUK_UNREF((thr)); \
4079 	} while (0)
4080 
4081 #define DUK_TVAL_SET_UNUSED_UPDREF_ALT0(thr,tvptr_dst) do { \
4082 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4083 		DUK_TVAL_SET_UNUSED(tv__dst); \
4084 		DUK_UNREF((thr)); \
4085 	} while (0)
4086 
4087 #define DUK_TVAL_SET_NULL_UPDREF_ALT0(thr,tvptr_dst) do { \
4088 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4089 		DUK_TVAL_SET_NULL(tv__dst); \
4090 		DUK_UNREF((thr)); \
4091 	} while (0)
4092 
4093 #define DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4094 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4095 		DUK_TVAL_SET_BOOLEAN(tv__dst, (newval)); \
4096 		DUK_UNREF((thr)); \
4097 	} while (0)
4098 
4099 #define DUK_TVAL_SET_NUMBER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4100 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4101 		DUK_TVAL_SET_NUMBER(tv__dst, (newval)); \
4102 		DUK_UNREF((thr)); \
4103 	} while (0)
4104 #define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4105 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4106 		DUK_TVAL_SET_NUMBER_CHKFAST(tv__dst, (newval)); \
4107 		DUK_UNREF((thr)); \
4108 	} while (0)
4109 #define DUK_TVAL_SET_DOUBLE_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4110 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4111 		DUK_TVAL_SET_DOUBLE(tv__dst, (newval)); \
4112 		DUK_UNREF((thr)); \
4113 	} while (0)
4114 #define DUK_TVAL_SET_NAN_UPDREF_ALT0(thr,tvptr_dst) do { \
4115 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4116 		DUK_TVAL_SET_NAN(tv__dst); \
4117 		DUK_UNREF((thr)); \
4118 	} while (0)
4119 #if defined(DUK_USE_FASTINT)
4120 #define DUK_TVAL_SET_FASTINT_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4121 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4122 		DUK_TVAL_SET_FASTINT(tv__dst, (newval)); \
4123 		DUK_UNREF((thr)); \
4124 	} while (0)
4125 #define DUK_TVAL_SET_FASTINT_I32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4126 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4127 		DUK_TVAL_SET_FASTINT_I32(tv__dst, (newval)); \
4128 		DUK_UNREF((thr)); \
4129 	} while (0)
4130 #define DUK_TVAL_SET_FASTINT_U32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4131 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4132 		DUK_TVAL_SET_FASTINT_U32(tv__dst, (newval)); \
4133 		DUK_UNREF((thr)); \
4134 	} while (0)
4135 #else
4136 #define DUK_TVAL_SET_DOUBLE_CAST_UPDREF(thr,tvptr_dst,newval) \
4137 	DUK_TVAL_SET_DOUBLE_UPDREF((thr), (tvptr_dst), (duk_double_t) (newval))
4138 #endif  /* DUK_USE_FASTINT */
4139 
4140 #define DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0(thr,tvptr_dst,lf_v,lf_fp,lf_flags) do { \
4141 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4142 		DUK_TVAL_SET_LIGHTFUNC(tv__dst, (lf_v), (lf_fp), (lf_flags)); \
4143 		DUK_UNREF((thr)); \
4144 	} while (0)
4145 
4146 #define DUK_TVAL_SET_STRING_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4147 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4148 		DUK_TVAL_SET_STRING(tv__dst, (newval)); \
4149 		DUK_UNREF((thr)); \
4150 	} while (0)
4151 
4152 #define DUK_TVAL_SET_OBJECT_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4153 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4154 		DUK_TVAL_SET_OBJECT(tv__dst, (newval)); \
4155 		DUK_UNREF((thr)); \
4156 	} while (0)
4157 
4158 #define DUK_TVAL_SET_BUFFER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4159 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4160 		DUK_TVAL_SET_BUFFER(tv__dst, (newval)); \
4161 		DUK_UNREF((thr)); \
4162 	} while (0)
4163 
4164 #define DUK_TVAL_SET_POINTER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4165 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4166 		DUK_TVAL_SET_POINTER(tv__dst, (newval)); \
4167 		DUK_UNREF((thr)); \
4168 	} while (0)
4169 
4170 #define DUK_TVAL_SET_TVAL_UPDREF_ALT0(thr,tvptr_dst,tvptr_src) do { \
4171 		duk_tval *tv__dst, *tv__src; \
4172 		tv__dst = (tvptr_dst); tv__src = (tvptr_src); \
4173 		DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
4174 		DUK_UNREF((thr)); \
4175 	} while (0)
4176 
4177 #define DUK_TVAL_SET_UNDEFINED_UPDREF         DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0
4178 #define DUK_TVAL_SET_UNUSED_UPDREF            DUK_TVAL_SET_UNUSED_UPDREF_ALT0
4179 #define DUK_TVAL_SET_NULL_UPDREF              DUK_TVAL_SET_NULL_UPDREF_ALT0
4180 #define DUK_TVAL_SET_BOOLEAN_UPDREF           DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0
4181 #define DUK_TVAL_SET_NUMBER_UPDREF            DUK_TVAL_SET_NUMBER_UPDREF_ALT0
4182 #define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF    DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0
4183 #define DUK_TVAL_SET_DOUBLE_UPDREF            DUK_TVAL_SET_DOUBLE_UPDREF_ALT0
4184 #define DUK_TVAL_SET_NAN_UPDREF               DUK_TVAL_SET_NAN_UPDREF_ALT0
4185 #if defined(DUK_USE_FASTINT)
4186 #define DUK_TVAL_SET_FASTINT_UPDREF           DUK_TVAL_SET_FASTINT_UPDREF_ALT0
4187 #define DUK_TVAL_SET_FASTINT_I32_UPDREF       DUK_TVAL_SET_FASTINT_I32_UPDREF_ALT0
4188 #define DUK_TVAL_SET_FASTINT_U32_UPDREF       DUK_TVAL_SET_FASTINT_U32_UPDREF_ALT0
4189 #else
4190 #define DUK_TVAL_SET_FASTINT_UPDREF           DUK_TVAL_SET_DOUBLE_CAST_UPDREF  /* XXX: fast-int-to-double */
4191 #define DUK_TVAL_SET_FASTINT_I32_UPDREF       DUK_TVAL_SET_DOUBLE_CAST_UPDREF
4192 #define DUK_TVAL_SET_FASTINT_U32_UPDREF       DUK_TVAL_SET_DOUBLE_CAST_UPDREF
4193 #endif  /* DUK_USE_FASTINT */
4194 #define DUK_TVAL_SET_LIGHTFUNC_UPDREF         DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0
4195 #define DUK_TVAL_SET_STRING_UPDREF            DUK_TVAL_SET_STRING_UPDREF_ALT0
4196 #define DUK_TVAL_SET_OBJECT_UPDREF            DUK_TVAL_SET_OBJECT_UPDREF_ALT0
4197 #define DUK_TVAL_SET_BUFFER_UPDREF            DUK_TVAL_SET_BUFFER_UPDREF_ALT0
4198 #define DUK_TVAL_SET_POINTER_UPDREF           DUK_TVAL_SET_POINTER_UPDREF_ALT0
4199 
4200 #define DUK_TVAL_SET_TVAL_UPDREF              DUK_TVAL_SET_TVAL_UPDREF_ALT0
4201 #define DUK_TVAL_SET_TVAL_UPDREF_FAST         DUK_TVAL_SET_TVAL_UPDREF_ALT0
4202 #define DUK_TVAL_SET_TVAL_UPDREF_SLOW         DUK_TVAL_SET_TVAL_UPDREF_ALT0
4203 
4204 #endif  /* DUK_USE_REFERENCE_COUNTING */
4205 
4206 #endif  /* DUK_HEAPHDR_H_INCLUDED */
4207 /*
4208  *  Internal API calls which have (stack and other) semantics similar
4209  *  to the public API.
4210  */
4211 
4212 #ifndef DUK_API_INTERNAL_H_INCLUDED
4213 #define DUK_API_INTERNAL_H_INCLUDED
4214 
4215 /* duk_push_sprintf constants */
4216 #define DUK_PUSH_SPRINTF_INITIAL_SIZE  256L
4217 #define DUK_PUSH_SPRINTF_SANITY_LIMIT  (1L * 1024L * 1024L * 1024L)
4218 
4219 /* Flag ORed to err_code to indicate __FILE__ / __LINE__ is not
4220  * blamed as source of error for error fileName / lineNumber.
4221  */
4222 #define DUK_ERRCODE_FLAG_NOBLAME_FILELINE  (1L << 24)
4223 
4224 /* Valstack resize flags */
4225 #define DUK_VSRESIZE_FLAG_SHRINK           (1 << 0)
4226 #define DUK_VSRESIZE_FLAG_COMPACT          (1 << 1)
4227 #define DUK_VSRESIZE_FLAG_THROW            (1 << 2)
4228 
4229 /* Current convention is to use duk_size_t for value stack sizes and global indices,
4230  * and duk_idx_t for local frame indices.
4231  */
4232 DUK_INTERNAL_DECL
4233 duk_bool_t duk_valstack_resize_raw(duk_context *ctx,
4234                                    duk_size_t min_new_size,
4235                                    duk_small_uint_t flags);
4236 
4237 #if defined(DUK_USE_VERBOSE_ERRORS) && defined(DUK_USE_PARANOID_ERRORS)
4238 DUK_INTERNAL_DECL const char *duk_get_type_name(duk_context *ctx, duk_idx_t index);
4239 #endif
4240 
4241 DUK_INTERNAL_DECL duk_tval *duk_get_tval(duk_context *ctx, duk_idx_t index);
4242 DUK_INTERNAL_DECL duk_tval *duk_require_tval(duk_context *ctx, duk_idx_t index);
4243 DUK_INTERNAL_DECL void duk_push_tval(duk_context *ctx, duk_tval *tv);
4244 
4245 /* Push the current 'this' binding; throw TypeError if binding is not object
4246  * coercible (CheckObjectCoercible).
4247  */
4248 DUK_INTERNAL_DECL void duk_push_this_check_object_coercible(duk_context *ctx);
4249 
4250 /* duk_push_this() + CheckObjectCoercible() + duk_to_object() */
4251 DUK_INTERNAL_DECL duk_hobject *duk_push_this_coercible_to_object(duk_context *ctx);
4252 
4253 /* duk_push_this() + CheckObjectCoercible() + duk_to_string() */
4254 DUK_INTERNAL_DECL duk_hstring *duk_push_this_coercible_to_string(duk_context *ctx);
4255 
4256 /* Get a borrowed duk_tval pointer to the current 'this' binding.  Caller must
4257  * make sure there's an active callstack entry.  Note that the returned pointer
4258  * is unstable with regards to side effects.
4259  */
4260 DUK_INTERNAL_DECL duk_tval *duk_get_borrowed_this_tval(duk_context *ctx);
4261 
4262 /* XXX: add fastint support? */
4263 #define duk_push_u64(ctx,val) \
4264 	duk_push_number((ctx), (duk_double_t) (val))
4265 #define duk_push_i64(ctx,val) \
4266 	duk_push_number((ctx), (duk_double_t) (val))
4267 
4268 /* duk_push_(u)int() is guaranteed to support at least (un)signed 32-bit range */
4269 #define duk_push_u32(ctx,val) \
4270 	duk_push_uint((ctx), (duk_uint_t) (val))
4271 #define duk_push_i32(ctx,val) \
4272 	duk_push_int((ctx), (duk_int_t) (val))
4273 
4274 /* sometimes stack and array indices need to go on the stack */
4275 #define duk_push_idx(ctx,val) \
4276 	duk_push_int((ctx), (duk_int_t) (val))
4277 #define duk_push_uarridx(ctx,val) \
4278 	duk_push_uint((ctx), (duk_uint_t) (val))
4279 #define duk_push_size_t(ctx,val) \
4280 	duk_push_uint((ctx), (duk_uint_t) (val))  /* XXX: assumed to fit for now */
4281 
4282 DUK_INTERNAL_DECL duk_hstring *duk_get_hstring(duk_context *ctx, duk_idx_t index);
4283 DUK_INTERNAL_DECL duk_hobject *duk_get_hobject(duk_context *ctx, duk_idx_t index);
4284 DUK_INTERNAL_DECL duk_hbuffer *duk_get_hbuffer(duk_context *ctx, duk_idx_t index);
4285 DUK_INTERNAL_DECL duk_hthread *duk_get_hthread(duk_context *ctx, duk_idx_t index);
4286 DUK_INTERNAL_DECL duk_hcompiledfunction *duk_get_hcompiledfunction(duk_context *ctx, duk_idx_t index);
4287 DUK_INTERNAL_DECL duk_hnativefunction *duk_get_hnativefunction(duk_context *ctx, duk_idx_t index);
4288 
4289 DUK_INTERNAL_DECL duk_hobject *duk_get_hobject_with_class(duk_context *ctx, duk_idx_t index, duk_small_uint_t classnum);
4290 
4291 #if 0  /* This would be pointless: unexpected type and lightfunc would both return NULL */
4292 DUK_INTERNAL_DECL duk_hobject *duk_get_hobject_or_lfunc(duk_context *ctx, duk_idx_t index);
4293 #endif
4294 DUK_INTERNAL_DECL duk_hobject *duk_get_hobject_or_lfunc_coerce(duk_context *ctx, duk_idx_t index);
4295 
4296 #if 0  /*unused*/
4297 DUK_INTERNAL_DECL void *duk_get_voidptr(duk_context *ctx, duk_idx_t index);
4298 #endif
4299 
4300 DUK_INTERNAL_DECL duk_hstring *duk_to_hstring(duk_context *ctx, duk_idx_t index);
4301 #if defined(DUK_USE_DEBUGGER_SUPPORT)  /* only needed by debugger for now */
4302 DUK_INTERNAL_DECL duk_hstring *duk_safe_to_hstring(duk_context *ctx, duk_idx_t index);
4303 #endif
4304 DUK_INTERNAL_DECL void duk_to_object_class_string_top(duk_context *ctx);
4305 #if !defined(DUK_USE_PARANOID_ERRORS)
4306 DUK_INTERNAL_DECL void duk_push_hobject_class_string(duk_context *ctx, duk_hobject *h);
4307 #endif
4308 
4309 DUK_INTERNAL_DECL duk_int_t duk_to_int_clamped_raw(duk_context *ctx, duk_idx_t index, duk_int_t minval, duk_int_t maxval, duk_bool_t *out_clamped);  /* out_clamped=NULL, RangeError if outside range */
4310 DUK_INTERNAL_DECL duk_int_t duk_to_int_clamped(duk_context *ctx, duk_idx_t index, duk_int_t minval, duk_int_t maxval);
4311 DUK_INTERNAL_DECL duk_int_t duk_to_int_check_range(duk_context *ctx, duk_idx_t index, duk_int_t minval, duk_int_t maxval);
4312 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
4313 DUK_INTERNAL_DECL duk_uint8_t duk_to_uint8clamped(duk_context *ctx, duk_idx_t index);
4314 #endif
4315 
4316 DUK_INTERNAL_DECL duk_hstring *duk_require_hstring(duk_context *ctx, duk_idx_t index);
4317 DUK_INTERNAL_DECL duk_hobject *duk_require_hobject(duk_context *ctx, duk_idx_t index);
4318 DUK_INTERNAL_DECL duk_hbuffer *duk_require_hbuffer(duk_context *ctx, duk_idx_t index);
4319 DUK_INTERNAL_DECL duk_hthread *duk_require_hthread(duk_context *ctx, duk_idx_t index);
4320 DUK_INTERNAL_DECL duk_hcompiledfunction *duk_require_hcompiledfunction(duk_context *ctx, duk_idx_t index);
4321 DUK_INTERNAL_DECL duk_hnativefunction *duk_require_hnativefunction(duk_context *ctx, duk_idx_t index);
4322 
4323 DUK_INTERNAL_DECL duk_hobject *duk_require_hobject_with_class(duk_context *ctx, duk_idx_t index, duk_small_uint_t classnum);
4324 
4325 DUK_INTERNAL_DECL duk_hobject *duk_require_hobject_or_lfunc(duk_context *ctx, duk_idx_t index);
4326 DUK_INTERNAL_DECL duk_hobject *duk_require_hobject_or_lfunc_coerce(duk_context *ctx, duk_idx_t index);
4327 
4328 DUK_INTERNAL_DECL void duk_push_hstring(duk_context *ctx, duk_hstring *h);
4329 DUK_INTERNAL_DECL void duk_push_hstring_stridx(duk_context *ctx, duk_small_int_t stridx);
4330 DUK_INTERNAL_DECL void duk_push_hobject(duk_context *ctx, duk_hobject *h);
4331 DUK_INTERNAL_DECL void duk_push_hbuffer(duk_context *ctx, duk_hbuffer *h);
4332 #define duk_push_hthread(ctx,h) \
4333 	duk_push_hobject((ctx), (duk_hobject *) (h))
4334 #define duk_push_hcompiledfunction(ctx,h) \
4335 	duk_push_hobject((ctx), (duk_hobject *) (h))
4336 #define duk_push_hnativefunction(ctx,h) \
4337 	duk_push_hobject((ctx), (duk_hobject *) (h))
4338 DUK_INTERNAL_DECL void duk_push_hobject_bidx(duk_context *ctx, duk_small_int_t builtin_idx);
4339 DUK_INTERNAL_DECL duk_idx_t duk_push_object_helper(duk_context *ctx, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx);
4340 DUK_INTERNAL_DECL duk_idx_t duk_push_object_helper_proto(duk_context *ctx, duk_uint_t hobject_flags_and_class, duk_hobject *proto);
4341 DUK_INTERNAL_DECL duk_idx_t duk_push_object_internal(duk_context *ctx);
4342 DUK_INTERNAL_DECL duk_idx_t duk_push_compiledfunction(duk_context *ctx);
4343 DUK_INTERNAL_DECL void duk_push_c_function_noexotic(duk_context *ctx, duk_c_function func, duk_int_t nargs);
4344 DUK_INTERNAL_DECL void duk_push_c_function_noconstruct_noexotic(duk_context *ctx, duk_c_function func, duk_int_t nargs);
4345 
4346 DUK_INTERNAL_DECL void duk_push_string_funcptr(duk_context *ctx, duk_uint8_t *ptr, duk_size_t sz);
4347 DUK_INTERNAL_DECL void duk_push_lightfunc_name(duk_context *ctx, duk_tval *tv);
4348 DUK_INTERNAL_DECL void duk_push_lightfunc_tostring(duk_context *ctx, duk_tval *tv);
4349 DUK_INTERNAL_DECL duk_hbufferobject *duk_push_bufferobject_raw(duk_context *ctx, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx);
4350 
4351 #if !defined(DUK_USE_PARANOID_ERRORS)
4352 DUK_INTERNAL_DECL const char *duk_push_string_readable(duk_context *ctx, duk_idx_t index);
4353 DUK_INTERNAL_DECL const char *duk_push_string_tval_readable(duk_context *ctx, duk_tval *tv);
4354 #endif
4355 
4356 DUK_INTERNAL_DECL duk_bool_t duk_get_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx);     /* [] -> [val] */
4357 DUK_INTERNAL_DECL duk_bool_t duk_put_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx);     /* [val] -> [] */
4358 DUK_INTERNAL_DECL duk_bool_t duk_del_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx);     /* [] -> [] */
4359 DUK_INTERNAL_DECL duk_bool_t duk_has_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx);     /* [] -> [] */
4360 
4361 DUK_INTERNAL_DECL duk_bool_t duk_get_prop_stridx_boolean(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx, duk_bool_t *out_has_prop);  /* [] -> [] */
4362 
4363 DUK_INTERNAL_DECL void duk_xdef_prop(duk_context *ctx, duk_idx_t obj_index, duk_small_uint_t desc_flags);  /* [key val] -> [] */
4364 DUK_INTERNAL_DECL void duk_xdef_prop_index(duk_context *ctx, duk_idx_t obj_index, duk_uarridx_t arr_index, duk_small_uint_t desc_flags);  /* [val] -> [] */
4365 DUK_INTERNAL_DECL void duk_xdef_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx, duk_small_uint_t desc_flags);  /* [val] -> [] */
4366 DUK_INTERNAL_DECL void duk_xdef_prop_stridx_builtin(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx, duk_small_int_t builtin_idx, duk_small_uint_t desc_flags);  /* [] -> [] */
4367 DUK_INTERNAL_DECL void duk_xdef_prop_stridx_thrower(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx, duk_small_uint_t desc_flags);  /* [] -> [] */
4368 
4369 /* These are macros for now, but could be separate functions to reduce code
4370  * footprint (check call site count before refactoring).
4371  */
4372 #define duk_xdef_prop_wec(ctx,obj_index) \
4373 	duk_xdef_prop((ctx), (obj_index), DUK_PROPDESC_FLAGS_WEC)
4374 #define duk_xdef_prop_index_wec(ctx,obj_index,arr_index) \
4375 	duk_xdef_prop_index((ctx), (obj_index), (arr_index), DUK_PROPDESC_FLAGS_WEC)
4376 #define duk_xdef_prop_stridx_wec(ctx,obj_index,stridx) \
4377 	duk_xdef_prop_stridx((ctx), (obj_index), (stridx), DUK_PROPDESC_FLAGS_WEC)
4378 
4379 /* Set object 'length'. */
4380 DUK_INTERNAL_DECL void duk_set_length(duk_context *ctx, duk_idx_t index, duk_size_t length);
4381 
4382 /* Raw internal valstack access macros: access is unsafe so call site
4383  * must have a guarantee that the index is valid.  When that is the case,
4384  * using these macro results in faster and smaller code than duk_get_tval().
4385  * Both 'ctx' and 'idx' are evaluted multiple times, but only for asserts.
4386  */
4387 #define DUK_ASSERT_VALID_NEGIDX(ctx,idx) \
4388 	(DUK_ASSERT_EXPR((idx) < 0), DUK_ASSERT_EXPR(duk_is_valid_index((ctx), (idx))))
4389 #define DUK_ASSERT_VALID_POSIDX(ctx,idx) \
4390 	(DUK_ASSERT_EXPR((idx) >= 0), DUK_ASSERT_EXPR(duk_is_valid_index((ctx), (idx))))
4391 #define DUK_GET_TVAL_NEGIDX(ctx,idx) \
4392 	(DUK_ASSERT_VALID_NEGIDX((ctx),(idx)), ((duk_hthread *) (ctx))->valstack_top + (idx))
4393 #define DUK_GET_TVAL_POSIDX(ctx,idx) \
4394 	(DUK_ASSERT_VALID_POSIDX((ctx),(idx)), ((duk_hthread *) (ctx))->valstack_bottom + (idx))
4395 #define DUK_GET_HOBJECT_NEGIDX(ctx,idx) \
4396 	(DUK_ASSERT_VALID_NEGIDX((ctx),(idx)), DUK_TVAL_GET_OBJECT(((duk_hthread *) (ctx))->valstack_top + (idx)))
4397 #define DUK_GET_HOBJECT_POSIDX(ctx,idx) \
4398 	(DUK_ASSERT_VALID_POSIDX((ctx),(idx)), DUK_TVAL_GET_OBJECT(((duk_hthread *) (ctx))->valstack_bottom + (idx)))
4399 
4400 #endif  /* DUK_API_INTERNAL_H_INCLUDED */
4401 /*
4402  *  Heap string representation.
4403  *
4404  *  Strings are byte sequences ordinarily stored in extended UTF-8 format,
4405  *  allowing values larger than the official UTF-8 range (used internally)
4406  *  and also allowing UTF-8 encoding of surrogate pairs (CESU-8 format).
4407  *  Strings may also be invalid UTF-8 altogether which is the case e.g. with
4408  *  strings used as internal property names and raw buffers converted to
4409  *  strings.  In such cases the 'clen' field contains an inaccurate value.
4410  *
4411  *  Ecmascript requires support for 32-bit long strings.  However, since each
4412  *  16-bit codepoint can take 3 bytes in CESU-8, this representation can only
4413  *  support about 1.4G codepoint long strings in extreme cases.  This is not
4414  *  really a practical issue.
4415  */
4416 
4417 #ifndef DUK_HSTRING_H_INCLUDED
4418 #define DUK_HSTRING_H_INCLUDED
4419 
4420 /* Impose a maximum string length for now.  Restricted artificially to
4421  * ensure adding a heap header length won't overflow size_t.  The limit
4422  * should be synchronized with DUK_HBUFFER_MAX_BYTELEN.
4423  *
4424  * E5.1 makes provisions to support strings longer than 4G characters.
4425  * This limit should be eliminated on 64-bit platforms (and increased
4426  * closer to maximum support on 32-bit platforms).
4427  */
4428 
4429 #if defined(DUK_USE_STRLEN16)
4430 #define DUK_HSTRING_MAX_BYTELEN                     (0x0000ffffUL)
4431 #else
4432 #define DUK_HSTRING_MAX_BYTELEN                     (0x7fffffffUL)
4433 #endif
4434 
4435 /* XXX: could add flags for "is valid CESU-8" (Ecmascript compatible strings),
4436  * "is valid UTF-8", "is valid extended UTF-8" (internal strings are not,
4437  * regexp bytecode is), and "contains non-BMP characters".  These are not
4438  * needed right now.
4439  */
4440 
4441 #define DUK_HSTRING_FLAG_ASCII                      DUK_HEAPHDR_USER_FLAG(0)  /* string is ASCII, clen == blen */
4442 #define DUK_HSTRING_FLAG_ARRIDX                     DUK_HEAPHDR_USER_FLAG(1)  /* string is a valid array index */
4443 #define DUK_HSTRING_FLAG_INTERNAL                   DUK_HEAPHDR_USER_FLAG(2)  /* string is internal */
4444 #define DUK_HSTRING_FLAG_RESERVED_WORD              DUK_HEAPHDR_USER_FLAG(3)  /* string is a reserved word (non-strict) */
4445 #define DUK_HSTRING_FLAG_STRICT_RESERVED_WORD       DUK_HEAPHDR_USER_FLAG(4)  /* string is a reserved word (strict) */
4446 #define DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS          DUK_HEAPHDR_USER_FLAG(5)  /* string is 'eval' or 'arguments' */
4447 #define DUK_HSTRING_FLAG_EXTDATA                    DUK_HEAPHDR_USER_FLAG(6)  /* string data is external (duk_hstring_external) */
4448 
4449 #define DUK_HSTRING_HAS_ASCII(x)                    DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ASCII)
4450 #define DUK_HSTRING_HAS_ARRIDX(x)                   DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ARRIDX)
4451 #define DUK_HSTRING_HAS_INTERNAL(x)                 DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_INTERNAL)
4452 #define DUK_HSTRING_HAS_RESERVED_WORD(x)            DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_RESERVED_WORD)
4453 #define DUK_HSTRING_HAS_STRICT_RESERVED_WORD(x)     DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_STRICT_RESERVED_WORD)
4454 #define DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(x)        DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS)
4455 #define DUK_HSTRING_HAS_EXTDATA(x)                  DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EXTDATA)
4456 
4457 #define DUK_HSTRING_SET_ASCII(x)                    DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ASCII)
4458 #define DUK_HSTRING_SET_ARRIDX(x)                   DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ARRIDX)
4459 #define DUK_HSTRING_SET_INTERNAL(x)                 DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_INTERNAL)
4460 #define DUK_HSTRING_SET_RESERVED_WORD(x)            DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_RESERVED_WORD)
4461 #define DUK_HSTRING_SET_STRICT_RESERVED_WORD(x)     DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_STRICT_RESERVED_WORD)
4462 #define DUK_HSTRING_SET_EVAL_OR_ARGUMENTS(x)        DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS)
4463 #define DUK_HSTRING_SET_EXTDATA(x)                  DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EXTDATA)
4464 
4465 #define DUK_HSTRING_CLEAR_ASCII(x)                  DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ASCII)
4466 #define DUK_HSTRING_CLEAR_ARRIDX(x)                 DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ARRIDX)
4467 #define DUK_HSTRING_CLEAR_INTERNAL(x)               DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_INTERNAL)
4468 #define DUK_HSTRING_CLEAR_RESERVED_WORD(x)          DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_RESERVED_WORD)
4469 #define DUK_HSTRING_CLEAR_STRICT_RESERVED_WORD(x)   DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_STRICT_RESERVED_WORD)
4470 #define DUK_HSTRING_CLEAR_EVAL_OR_ARGUMENTS(x)      DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS)
4471 #define DUK_HSTRING_CLEAR_EXTDATA(x)                DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EXTDATA)
4472 
4473 #if 0  /* Slightly smaller code without explicit flag, but explicit flag
4474         * is very useful when 'clen' is dropped.
4475         */
4476 #define DUK_HSTRING_IS_ASCII(x)                     (DUK_HSTRING_GET_BYTELEN((x)) == DUK_HSTRING_GET_CHARLEN((x)))
4477 #endif
4478 #define DUK_HSTRING_IS_ASCII(x)                     DUK_HSTRING_HAS_ASCII((x))
4479 #define DUK_HSTRING_IS_EMPTY(x)                     (DUK_HSTRING_GET_BYTELEN((x)) == 0)
4480 
4481 #if defined(DUK_USE_STRHASH16)
4482 #define DUK_HSTRING_GET_HASH(x)                     ((x)->hdr.h_flags >> 16)
4483 #define DUK_HSTRING_SET_HASH(x,v) do { \
4484 		(x)->hdr.h_flags = ((x)->hdr.h_flags & 0x0000ffffUL) | ((v) << 16); \
4485 	} while (0)
4486 #else
4487 #define DUK_HSTRING_GET_HASH(x)                     ((x)->hash)
4488 #define DUK_HSTRING_SET_HASH(x,v) do { \
4489 		(x)->hash = (v); \
4490 	} while (0)
4491 #endif
4492 
4493 #if defined(DUK_USE_STRLEN16)
4494 #define DUK_HSTRING_GET_BYTELEN(x)                  ((x)->hdr.h_strextra16)
4495 #define DUK_HSTRING_SET_BYTELEN(x,v) do { \
4496 		(x)->hdr.h_strextra16 = (v); \
4497 	} while (0)
4498 #if defined(DUK_USE_HSTRING_CLEN)
4499 #define DUK_HSTRING_GET_CHARLEN(x)                  ((x)->clen16)
4500 #define DUK_HSTRING_SET_CHARLEN(x,v) do { \
4501 		(x)->clen16 = (v); \
4502 	} while (0)
4503 #else
4504 #define DUK_HSTRING_GET_CHARLEN(x)                  duk_hstring_get_charlen((x))
4505 #define DUK_HSTRING_SET_CHARLEN(x,v) do { \
4506 		DUK_ASSERT(0);  /* should never be called */ \
4507 	} while (0)
4508 #endif
4509 #else
4510 #define DUK_HSTRING_GET_BYTELEN(x)                  ((x)->blen)
4511 #define DUK_HSTRING_SET_BYTELEN(x,v) do { \
4512 		(x)->blen = (v); \
4513 	} while (0)
4514 #define DUK_HSTRING_GET_CHARLEN(x)                  ((x)->clen)
4515 #define DUK_HSTRING_SET_CHARLEN(x,v) do { \
4516 		(x)->clen = (v); \
4517 	} while (0)
4518 #endif
4519 
4520 #if defined(DUK_USE_HSTRING_EXTDATA)
4521 #define DUK_HSTRING_GET_EXTDATA(x) \
4522 	((x)->extdata)
4523 #define DUK_HSTRING_GET_DATA(x) \
4524 	(DUK_HSTRING_HAS_EXTDATA((x)) ? \
4525 		DUK_HSTRING_GET_EXTDATA((const duk_hstring_external *) (x)) : ((const duk_uint8_t *) ((x) + 1)))
4526 #else
4527 #define DUK_HSTRING_GET_DATA(x) \
4528 	((const duk_uint8_t *) ((x) + 1))
4529 #endif
4530 
4531 #define DUK_HSTRING_GET_DATA_END(x) \
4532 	(DUK_HSTRING_GET_DATA((x)) + (x)->blen)
4533 
4534 /* marker value; in E5 2^32-1 is not a valid array index (2^32-2 is highest valid) */
4535 #define DUK_HSTRING_NO_ARRAY_INDEX  (0xffffffffUL)
4536 
4537 /* get array index related to string (or return DUK_HSTRING_NO_ARRAY_INDEX);
4538  * avoids helper call if string has no array index value.
4539  */
4540 #define DUK_HSTRING_GET_ARRIDX_FAST(h)  \
4541 	(DUK_HSTRING_HAS_ARRIDX((h)) ? duk_js_to_arrayindex_string_helper((h)) : DUK_HSTRING_NO_ARRAY_INDEX)
4542 
4543 /* slower but more compact variant */
4544 #define DUK_HSTRING_GET_ARRIDX_SLOW(h)  \
4545 	(duk_js_to_arrayindex_string_helper((h)))
4546 
4547 /*
4548  *  Misc
4549  */
4550 
4551 struct duk_hstring {
4552 	/* Smaller heaphdr than for other objects, because strings are held
4553 	 * in string intern table which requires no link pointers.  Much of
4554 	 * the 32-bit flags field is unused by flags, so we can stuff a 16-bit
4555 	 * field in there.
4556 	 */
4557 	duk_heaphdr_string hdr;
4558 
4559 	/* Note: we could try to stuff a partial hash (e.g. 16 bits) into the
4560 	 * shared heap header.  Good hashing needs more hash bits though.
4561 	 */
4562 
4563 	/* string hash */
4564 #if defined(DUK_USE_STRHASH16)
4565 	/* If 16-bit hash is in use, stuff it into duk_heaphdr_string flags. */
4566 #else
4567 	duk_uint32_t hash;
4568 #endif
4569 
4570 	/* length in bytes (not counting NUL term) */
4571 #if defined(DUK_USE_STRLEN16)
4572 	/* placed in duk_heaphdr_string */
4573 #else
4574 	duk_uint32_t blen;
4575 #endif
4576 
4577 	/* length in codepoints (must be E5 compatible) */
4578 #if defined(DUK_USE_STRLEN16)
4579 #if defined(DUK_USE_HSTRING_CLEN)
4580 	duk_uint16_t clen16;
4581 #else
4582 	/* computed live */
4583 #endif
4584 #else
4585 	duk_uint32_t clen;
4586 #endif
4587 
4588 	/*
4589 	 *  String value of 'blen+1' bytes follows (+1 for NUL termination
4590 	 *  convenience for C API).  No alignment needs to be guaranteed
4591 	 *  for strings, but fields above should guarantee alignment-by-4
4592 	 *  (but not alignment-by-8).
4593 	 */
4594 };
4595 
4596 /* The external string struct is defined even when the feature is inactive. */
4597 struct duk_hstring_external {
4598 	duk_hstring str;
4599 
4600 	/*
4601 	 *  For an external string, the NUL-terminated string data is stored
4602 	 *  externally.  The user must guarantee that data behind this pointer
4603 	 *  doesn't change while it's used.
4604 	 */
4605 
4606 	const duk_uint8_t *extdata;
4607 };
4608 
4609 /*
4610  *  Prototypes
4611  */
4612 
4613 DUK_INTERNAL_DECL duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr, duk_hstring *h, duk_uint_t pos);
4614 
4615 #if !defined(DUK_USE_HSTRING_CLEN)
4616 DUK_INTERNAL_DECL duk_size_t duk_hstring_get_charlen(duk_hstring *h);
4617 #endif
4618 
4619 #endif  /* DUK_HSTRING_H_INCLUDED */
4620 /*
4621  *  Heap object representation.
4622  *
4623  *  Heap objects are used for Ecmascript objects, arrays, and functions,
4624  *  but also for internal control like declarative and object environment
4625  *  records.  Compiled functions, native functions, and threads are also
4626  *  objects but with an extended C struct.
4627  *
4628  *  Objects provide the required Ecmascript semantics and exotic behaviors
4629  *  especially for property access.
4630  *
4631  *  Properties are stored in three conceptual parts:
4632  *
4633  *    1. A linear 'entry part' contains ordered key-value-attributes triples
4634  *       and is the main method of string properties.
4635  *
4636  *    2. An optional linear 'array part' is used for array objects to store a
4637  *       (dense) range of [0,N[ array indexed entries with default attributes
4638  *       (writable, enumerable, configurable).  If the array part would become
4639  *       sparse or non-default attributes are required, the array part is
4640  *       abandoned and moved to the 'entry part'.
4641  *
4642  *    3. An optional 'hash part' is used to optimize lookups of the entry
4643  *       part; it is used only for objects with sufficiently many properties
4644  *       and can be abandoned without loss of information.
4645  *
4646  *  These three conceptual parts are stored in a single memory allocated area.
4647  *  This minimizes memory allocation overhead but also means that all three
4648  *  parts are resized together, and makes property access a bit complicated.
4649  */
4650 
4651 #ifndef DUK_HOBJECT_H_INCLUDED
4652 #define DUK_HOBJECT_H_INCLUDED
4653 
4654 /* Object flag.  There are currently 26 flag bits available.  Make sure
4655  * this stays in sync with debugger object inspection code.
4656  */
4657 #define DUK_HOBJECT_FLAG_EXTENSIBLE            DUK_HEAPHDR_USER_FLAG(0)   /* object is extensible */
4658 #define DUK_HOBJECT_FLAG_CONSTRUCTABLE         DUK_HEAPHDR_USER_FLAG(1)   /* object is constructable */
4659 #define DUK_HOBJECT_FLAG_BOUND                 DUK_HEAPHDR_USER_FLAG(2)   /* object established using Function.prototype.bind() */
4660 #define DUK_HOBJECT_FLAG_COMPILEDFUNCTION      DUK_HEAPHDR_USER_FLAG(4)   /* object is a compiled function (duk_hcompiledfunction) */
4661 #define DUK_HOBJECT_FLAG_NATIVEFUNCTION        DUK_HEAPHDR_USER_FLAG(5)   /* object is a native function (duk_hnativefunction) */
4662 #define DUK_HOBJECT_FLAG_BUFFEROBJECT          DUK_HEAPHDR_USER_FLAG(6)   /* object is a buffer object (duk_hbufferobject) (always exotic) */
4663 #define DUK_HOBJECT_FLAG_THREAD                DUK_HEAPHDR_USER_FLAG(7)   /* object is a thread (duk_hthread) */
4664 #define DUK_HOBJECT_FLAG_ARRAY_PART            DUK_HEAPHDR_USER_FLAG(8)   /* object has an array part (a_size may still be 0) */
4665 #define DUK_HOBJECT_FLAG_STRICT                DUK_HEAPHDR_USER_FLAG(9)   /* function: function object is strict */
4666 #define DUK_HOBJECT_FLAG_NOTAIL                DUK_HEAPHDR_USER_FLAG(10)  /* function: function must not be tail called */
4667 #define DUK_HOBJECT_FLAG_NEWENV                DUK_HEAPHDR_USER_FLAG(11)  /* function: create new environment when called (see duk_hcompiledfunction) */
4668 #define DUK_HOBJECT_FLAG_NAMEBINDING           DUK_HEAPHDR_USER_FLAG(12)  /* function: create binding for func name (function templates only, used for named function expressions) */
4669 #define DUK_HOBJECT_FLAG_CREATEARGS            DUK_HEAPHDR_USER_FLAG(13)  /* function: create an arguments object on function call */
4670 #define DUK_HOBJECT_FLAG_ENVRECCLOSED          DUK_HEAPHDR_USER_FLAG(14)  /* envrec: (declarative) record is closed */
4671 #define DUK_HOBJECT_FLAG_EXOTIC_ARRAY          DUK_HEAPHDR_USER_FLAG(15)  /* 'Array' object, array length and index exotic behavior */
4672 #define DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ      DUK_HEAPHDR_USER_FLAG(16)  /* 'String' object, array index exotic behavior */
4673 #define DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS      DUK_HEAPHDR_USER_FLAG(17)  /* 'Arguments' object and has arguments exotic behavior (non-strict callee) */
4674 #define DUK_HOBJECT_FLAG_EXOTIC_DUKFUNC        DUK_HEAPHDR_USER_FLAG(18)  /* Duktape/C (nativefunction) object, exotic 'length' */
4675 #define DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ       DUK_HEAPHDR_USER_FLAG(19)  /* 'Proxy' object */
4676 
4677 #define DUK_HOBJECT_FLAG_CLASS_BASE            DUK_HEAPHDR_USER_FLAG_NUMBER(20)
4678 #define DUK_HOBJECT_FLAG_CLASS_BITS            5
4679 
4680 #define DUK_HOBJECT_GET_CLASS_NUMBER(h)        \
4681 	DUK_HEAPHDR_GET_FLAG_RANGE(&(h)->hdr, DUK_HOBJECT_FLAG_CLASS_BASE, DUK_HOBJECT_FLAG_CLASS_BITS)
4682 #define DUK_HOBJECT_SET_CLASS_NUMBER(h,v)      \
4683 	DUK_HEAPHDR_SET_FLAG_RANGE(&(h)->hdr, DUK_HOBJECT_FLAG_CLASS_BASE, DUK_HOBJECT_FLAG_CLASS_BITS, (v))
4684 
4685 #define DUK_HOBJECT_GET_CLASS_MASK(h)          \
4686 	(1UL << DUK_HEAPHDR_GET_FLAG_RANGE(&(h)->hdr, DUK_HOBJECT_FLAG_CLASS_BASE, DUK_HOBJECT_FLAG_CLASS_BITS))
4687 
4688 /* Macro for creating flag initializer from a class number.
4689  * Unsigned type cast is needed to avoid warnings about coercing
4690  * a signed integer to an unsigned one; the largest class values
4691  * have the highest bit (bit 31) set which causes this.
4692  */
4693 #define DUK_HOBJECT_CLASS_AS_FLAGS(v)          (((duk_uint_t) (v)) << DUK_HOBJECT_FLAG_CLASS_BASE)
4694 
4695 /* E5 Section 8.6.2 + custom classes */
4696 #define DUK_HOBJECT_CLASS_UNUSED               0
4697 #define DUK_HOBJECT_CLASS_ARGUMENTS            1
4698 #define DUK_HOBJECT_CLASS_ARRAY                2
4699 #define DUK_HOBJECT_CLASS_BOOLEAN              3
4700 #define DUK_HOBJECT_CLASS_DATE                 4
4701 #define DUK_HOBJECT_CLASS_ERROR                5
4702 #define DUK_HOBJECT_CLASS_FUNCTION             6
4703 #define DUK_HOBJECT_CLASS_JSON                 7
4704 #define DUK_HOBJECT_CLASS_MATH                 8
4705 #define DUK_HOBJECT_CLASS_NUMBER               9
4706 #define DUK_HOBJECT_CLASS_OBJECT               10
4707 #define DUK_HOBJECT_CLASS_REGEXP               11
4708 #define DUK_HOBJECT_CLASS_STRING               12
4709 #define DUK_HOBJECT_CLASS_GLOBAL               13
4710 #define DUK_HOBJECT_CLASS_OBJENV               14  /* custom */
4711 #define DUK_HOBJECT_CLASS_DECENV               15  /* custom */
4712 #define DUK_HOBJECT_CLASS_BUFFER               16  /* custom; implies DUK_HOBJECT_IS_BUFFEROBJECT */
4713 #define DUK_HOBJECT_CLASS_POINTER              17  /* custom */
4714 #define DUK_HOBJECT_CLASS_THREAD               18  /* custom; implies DUK_HOBJECT_IS_THREAD */
4715 #define DUK_HOBJECT_CLASS_ARRAYBUFFER          19  /* implies DUK_HOBJECT_IS_BUFFEROBJECT */
4716 #define DUK_HOBJECT_CLASS_DATAVIEW             20
4717 #define DUK_HOBJECT_CLASS_INT8ARRAY            21
4718 #define DUK_HOBJECT_CLASS_UINT8ARRAY           22
4719 #define DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY    23
4720 #define DUK_HOBJECT_CLASS_INT16ARRAY           24
4721 #define DUK_HOBJECT_CLASS_UINT16ARRAY          25
4722 #define DUK_HOBJECT_CLASS_INT32ARRAY           26
4723 #define DUK_HOBJECT_CLASS_UINT32ARRAY          27
4724 #define DUK_HOBJECT_CLASS_FLOAT32ARRAY         28
4725 #define DUK_HOBJECT_CLASS_FLOAT64ARRAY         29
4726 #define DUK_HOBJECT_CLASS_MAX                  29
4727 
4728 /* class masks */
4729 #define DUK_HOBJECT_CMASK_ALL                  ((1UL << (DUK_HOBJECT_CLASS_MAX + 1)) - 1UL)
4730 #define DUK_HOBJECT_CMASK_UNUSED               (1UL << DUK_HOBJECT_CLASS_UNUSED)
4731 #define DUK_HOBJECT_CMASK_ARGUMENTS            (1UL << DUK_HOBJECT_CLASS_ARGUMENTS)
4732 #define DUK_HOBJECT_CMASK_ARRAY                (1UL << DUK_HOBJECT_CLASS_ARRAY)
4733 #define DUK_HOBJECT_CMASK_BOOLEAN              (1UL << DUK_HOBJECT_CLASS_BOOLEAN)
4734 #define DUK_HOBJECT_CMASK_DATE                 (1UL << DUK_HOBJECT_CLASS_DATE)
4735 #define DUK_HOBJECT_CMASK_ERROR                (1UL << DUK_HOBJECT_CLASS_ERROR)
4736 #define DUK_HOBJECT_CMASK_FUNCTION             (1UL << DUK_HOBJECT_CLASS_FUNCTION)
4737 #define DUK_HOBJECT_CMASK_JSON                 (1UL << DUK_HOBJECT_CLASS_JSON)
4738 #define DUK_HOBJECT_CMASK_MATH                 (1UL << DUK_HOBJECT_CLASS_MATH)
4739 #define DUK_HOBJECT_CMASK_NUMBER               (1UL << DUK_HOBJECT_CLASS_NUMBER)
4740 #define DUK_HOBJECT_CMASK_OBJECT               (1UL << DUK_HOBJECT_CLASS_OBJECT)
4741 #define DUK_HOBJECT_CMASK_REGEXP               (1UL << DUK_HOBJECT_CLASS_REGEXP)
4742 #define DUK_HOBJECT_CMASK_STRING               (1UL << DUK_HOBJECT_CLASS_STRING)
4743 #define DUK_HOBJECT_CMASK_GLOBAL               (1UL << DUK_HOBJECT_CLASS_GLOBAL)
4744 #define DUK_HOBJECT_CMASK_OBJENV               (1UL << DUK_HOBJECT_CLASS_OBJENV)
4745 #define DUK_HOBJECT_CMASK_DECENV               (1UL << DUK_HOBJECT_CLASS_DECENV)
4746 #define DUK_HOBJECT_CMASK_BUFFER               (1UL << DUK_HOBJECT_CLASS_BUFFER)
4747 #define DUK_HOBJECT_CMASK_POINTER              (1UL << DUK_HOBJECT_CLASS_POINTER)
4748 #define DUK_HOBJECT_CMASK_THREAD               (1UL << DUK_HOBJECT_CLASS_THREAD)
4749 #define DUK_HOBJECT_CMASK_ARRAYBUFFER          (1UL << DUK_HOBJECT_CLASS_ARRAYBUFFER)
4750 #define DUK_HOBJECT_CMASK_DATAVIEW             (1UL << DUK_HOBJECT_CLASS_DATAVIEW)
4751 #define DUK_HOBJECT_CMASK_INT8ARRAY            (1UL << DUK_HOBJECT_CLASS_INT8ARRAY)
4752 #define DUK_HOBJECT_CMASK_UINT8ARRAY           (1UL << DUK_HOBJECT_CLASS_UINT8ARRAY)
4753 #define DUK_HOBJECT_CMASK_UINT8CLAMPEDARRAY    (1UL << DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY)
4754 #define DUK_HOBJECT_CMASK_INT16ARRAY           (1UL << DUK_HOBJECT_CLASS_INT16ARRAY)
4755 #define DUK_HOBJECT_CMASK_UINT16ARRAY          (1UL << DUK_HOBJECT_CLASS_UINT16ARRAY)
4756 #define DUK_HOBJECT_CMASK_INT32ARRAY           (1UL << DUK_HOBJECT_CLASS_INT32ARRAY)
4757 #define DUK_HOBJECT_CMASK_UINT32ARRAY          (1UL << DUK_HOBJECT_CLASS_UINT32ARRAY)
4758 #define DUK_HOBJECT_CMASK_FLOAT32ARRAY         (1UL << DUK_HOBJECT_CLASS_FLOAT32ARRAY)
4759 #define DUK_HOBJECT_CMASK_FLOAT64ARRAY         (1UL << DUK_HOBJECT_CLASS_FLOAT64ARRAY)
4760 
4761 #define DUK_HOBJECT_CMASK_ALL_BUFFEROBJECTS \
4762 	(DUK_HOBJECT_CMASK_BUFFER | \
4763 	 DUK_HOBJECT_CMASK_ARRAYBUFFER | \
4764 	 DUK_HOBJECT_CMASK_DATAVIEW | \
4765 	 DUK_HOBJECT_CMASK_INT8ARRAY | \
4766 	 DUK_HOBJECT_CMASK_UINT8ARRAY | \
4767 	 DUK_HOBJECT_CMASK_UINT8CLAMPEDARRAY | \
4768 	 DUK_HOBJECT_CMASK_INT16ARRAY | \
4769 	 DUK_HOBJECT_CMASK_UINT16ARRAY | \
4770 	 DUK_HOBJECT_CMASK_INT32ARRAY | \
4771 	 DUK_HOBJECT_CMASK_UINT32ARRAY | \
4772 	 DUK_HOBJECT_CMASK_FLOAT32ARRAY | \
4773 	 DUK_HOBJECT_CMASK_FLOAT64ARRAY)
4774 
4775 #define DUK_HOBJECT_IS_OBJENV(h)               (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_OBJENV)
4776 #define DUK_HOBJECT_IS_DECENV(h)               (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_DECENV)
4777 #define DUK_HOBJECT_IS_ENV(h)                  (DUK_HOBJECT_IS_OBJENV((h)) || DUK_HOBJECT_IS_DECENV((h)))
4778 #define DUK_HOBJECT_IS_ARRAY(h)                (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_ARRAY)
4779 #define DUK_HOBJECT_IS_COMPILEDFUNCTION(h)     DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPILEDFUNCTION)
4780 #define DUK_HOBJECT_IS_NATIVEFUNCTION(h)       DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATIVEFUNCTION)
4781 #define DUK_HOBJECT_IS_BUFFEROBJECT(h)         DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFFEROBJECT)
4782 #define DUK_HOBJECT_IS_THREAD(h)               DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_THREAD)
4783 
4784 #define DUK_HOBJECT_IS_NONBOUND_FUNCTION(h)    DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, \
4785                                                         DUK_HOBJECT_FLAG_COMPILEDFUNCTION | \
4786                                                         DUK_HOBJECT_FLAG_NATIVEFUNCTION)
4787 
4788 #define DUK_HOBJECT_IS_FUNCTION(h)             DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, \
4789                                                         DUK_HOBJECT_FLAG_BOUND | \
4790                                                         DUK_HOBJECT_FLAG_COMPILEDFUNCTION | \
4791                                                         DUK_HOBJECT_FLAG_NATIVEFUNCTION)
4792 
4793 #define DUK_HOBJECT_IS_CALLABLE(h)             DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, \
4794                                                         DUK_HOBJECT_FLAG_BOUND | \
4795                                                         DUK_HOBJECT_FLAG_COMPILEDFUNCTION | \
4796                                                         DUK_HOBJECT_FLAG_NATIVEFUNCTION)
4797 
4798 /* object has any exotic behavior(s) */
4799 #define DUK_HOBJECT_EXOTIC_BEHAVIOR_FLAGS      (DUK_HOBJECT_FLAG_EXOTIC_ARRAY | \
4800                                                 DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS | \
4801                                                 DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ | \
4802                                                 DUK_HOBJECT_FLAG_EXOTIC_DUKFUNC | \
4803                                                 DUK_HOBJECT_FLAG_BUFFEROBJECT | \
4804                                                 DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
4805 
4806 #define DUK_HOBJECT_HAS_EXOTIC_BEHAVIOR(h)     DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_EXOTIC_BEHAVIOR_FLAGS)
4807 
4808 #define DUK_HOBJECT_HAS_EXTENSIBLE(h)          DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXTENSIBLE)
4809 #define DUK_HOBJECT_HAS_CONSTRUCTABLE(h)       DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CONSTRUCTABLE)
4810 #define DUK_HOBJECT_HAS_BOUND(h)               DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUND)
4811 #define DUK_HOBJECT_HAS_COMPILEDFUNCTION(h)    DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPILEDFUNCTION)
4812 #define DUK_HOBJECT_HAS_NATIVEFUNCTION(h)      DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATIVEFUNCTION)
4813 #define DUK_HOBJECT_HAS_BUFFEROBJECT(h)        DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFFEROBJECT)
4814 #define DUK_HOBJECT_HAS_THREAD(h)              DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_THREAD)
4815 #define DUK_HOBJECT_HAS_ARRAY_PART(h)          DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ARRAY_PART)
4816 #define DUK_HOBJECT_HAS_STRICT(h)              DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_STRICT)
4817 #define DUK_HOBJECT_HAS_NOTAIL(h)              DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NOTAIL)
4818 #define DUK_HOBJECT_HAS_NEWENV(h)              DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NEWENV)
4819 #define DUK_HOBJECT_HAS_NAMEBINDING(h)         DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NAMEBINDING)
4820 #define DUK_HOBJECT_HAS_CREATEARGS(h)          DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CREATEARGS)
4821 #define DUK_HOBJECT_HAS_ENVRECCLOSED(h)        DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ENVRECCLOSED)
4822 #define DUK_HOBJECT_HAS_EXOTIC_ARRAY(h)        DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARRAY)
4823 #define DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(h)    DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ)
4824 #define DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(h)    DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS)
4825 #define DUK_HOBJECT_HAS_EXOTIC_DUKFUNC(h)      DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_DUKFUNC)
4826 #define DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h)     DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
4827 
4828 #define DUK_HOBJECT_SET_EXTENSIBLE(h)          DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXTENSIBLE)
4829 #define DUK_HOBJECT_SET_CONSTRUCTABLE(h)       DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CONSTRUCTABLE)
4830 #define DUK_HOBJECT_SET_BOUND(h)               DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUND)
4831 #define DUK_HOBJECT_SET_COMPILEDFUNCTION(h)    DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPILEDFUNCTION)
4832 #define DUK_HOBJECT_SET_NATIVEFUNCTION(h)      DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATIVEFUNCTION)
4833 #define DUK_HOBJECT_SET_BUFFEROBJECT(h)        DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFFEROBJECT)
4834 #define DUK_HOBJECT_SET_THREAD(h)              DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_THREAD)
4835 #define DUK_HOBJECT_SET_ARRAY_PART(h)          DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ARRAY_PART)
4836 #define DUK_HOBJECT_SET_STRICT(h)              DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_STRICT)
4837 #define DUK_HOBJECT_SET_NOTAIL(h)              DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NOTAIL)
4838 #define DUK_HOBJECT_SET_NEWENV(h)              DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NEWENV)
4839 #define DUK_HOBJECT_SET_NAMEBINDING(h)         DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NAMEBINDING)
4840 #define DUK_HOBJECT_SET_CREATEARGS(h)          DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CREATEARGS)
4841 #define DUK_HOBJECT_SET_ENVRECCLOSED(h)        DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ENVRECCLOSED)
4842 #define DUK_HOBJECT_SET_EXOTIC_ARRAY(h)        DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARRAY)
4843 #define DUK_HOBJECT_SET_EXOTIC_STRINGOBJ(h)    DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ)
4844 #define DUK_HOBJECT_SET_EXOTIC_ARGUMENTS(h)    DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS)
4845 #define DUK_HOBJECT_SET_EXOTIC_DUKFUNC(h)      DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_DUKFUNC)
4846 #define DUK_HOBJECT_SET_EXOTIC_PROXYOBJ(h)     DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
4847 
4848 #define DUK_HOBJECT_CLEAR_EXTENSIBLE(h)        DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXTENSIBLE)
4849 #define DUK_HOBJECT_CLEAR_CONSTRUCTABLE(h)     DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CONSTRUCTABLE)
4850 #define DUK_HOBJECT_CLEAR_BOUND(h)             DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUND)
4851 #define DUK_HOBJECT_CLEAR_COMPILEDFUNCTION(h)  DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPILEDFUNCTION)
4852 #define DUK_HOBJECT_CLEAR_NATIVEFUNCTION(h)    DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATIVEFUNCTION)
4853 #define DUK_HOBJECT_CLEAR_BUFFEROBJECT(h)      DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFFEROBJECT)
4854 #define DUK_HOBJECT_CLEAR_THREAD(h)            DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_THREAD)
4855 #define DUK_HOBJECT_CLEAR_ARRAY_PART(h)        DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ARRAY_PART)
4856 #define DUK_HOBJECT_CLEAR_STRICT(h)            DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_STRICT)
4857 #define DUK_HOBJECT_CLEAR_NOTAIL(h)            DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NOTAIL)
4858 #define DUK_HOBJECT_CLEAR_NEWENV(h)            DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NEWENV)
4859 #define DUK_HOBJECT_CLEAR_NAMEBINDING(h)       DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NAMEBINDING)
4860 #define DUK_HOBJECT_CLEAR_CREATEARGS(h)        DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CREATEARGS)
4861 #define DUK_HOBJECT_CLEAR_ENVRECCLOSED(h)      DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ENVRECCLOSED)
4862 #define DUK_HOBJECT_CLEAR_EXOTIC_ARRAY(h)      DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARRAY)
4863 #define DUK_HOBJECT_CLEAR_EXOTIC_STRINGOBJ(h)  DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ)
4864 #define DUK_HOBJECT_CLEAR_EXOTIC_ARGUMENTS(h)  DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS)
4865 #define DUK_HOBJECT_CLEAR_EXOTIC_DUKFUNC(h)    DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_DUKFUNC)
4866 #define DUK_HOBJECT_CLEAR_EXOTIC_PROXYOBJ(h)   DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
4867 
4868 /* flags used for property attributes in duk_propdesc and packed flags */
4869 #define DUK_PROPDESC_FLAG_WRITABLE              (1 << 0)    /* E5 Section 8.6.1 */
4870 #define DUK_PROPDESC_FLAG_ENUMERABLE            (1 << 1)    /* E5 Section 8.6.1 */
4871 #define DUK_PROPDESC_FLAG_CONFIGURABLE          (1 << 2)    /* E5 Section 8.6.1 */
4872 #define DUK_PROPDESC_FLAG_ACCESSOR              (1 << 3)    /* accessor */
4873 #define DUK_PROPDESC_FLAG_VIRTUAL               (1 << 4)    /* property is virtual: used in duk_propdesc, never stored
4874                                                              * (used by e.g. buffer virtual properties)
4875                                                              */
4876 #define DUK_PROPDESC_FLAGS_MASK                 (DUK_PROPDESC_FLAG_WRITABLE | \
4877                                                  DUK_PROPDESC_FLAG_ENUMERABLE | \
4878                                                  DUK_PROPDESC_FLAG_CONFIGURABLE | \
4879                                                  DUK_PROPDESC_FLAG_ACCESSOR)
4880 
4881 /* additional flags which are passed in the same flags argument as property
4882  * flags but are not stored in object properties.
4883  */
4884 #define DUK_PROPDESC_FLAG_NO_OVERWRITE          (1 << 4)    /* internal define property: skip write silently if exists */
4885 
4886 /* convenience */
4887 #define DUK_PROPDESC_FLAGS_NONE                 0
4888 #define DUK_PROPDESC_FLAGS_W                    (DUK_PROPDESC_FLAG_WRITABLE)
4889 #define DUK_PROPDESC_FLAGS_E                    (DUK_PROPDESC_FLAG_ENUMERABLE)
4890 #define DUK_PROPDESC_FLAGS_C                    (DUK_PROPDESC_FLAG_CONFIGURABLE)
4891 #define DUK_PROPDESC_FLAGS_WE                   (DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_ENUMERABLE)
4892 #define DUK_PROPDESC_FLAGS_WC                   (DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_CONFIGURABLE)
4893 #define DUK_PROPDESC_FLAGS_EC                   (DUK_PROPDESC_FLAG_ENUMERABLE | DUK_PROPDESC_FLAG_CONFIGURABLE)
4894 #define DUK_PROPDESC_FLAGS_WEC                  (DUK_PROPDESC_FLAG_WRITABLE | \
4895                                                  DUK_PROPDESC_FLAG_ENUMERABLE | \
4896                                                  DUK_PROPDESC_FLAG_CONFIGURABLE)
4897 
4898 /* flags for duk_hobject_get_own_propdesc() and variants */
4899 #define DUK_GETDESC_FLAG_PUSH_VALUE          (1 << 0)  /* push value to stack */
4900 #define DUK_GETDESC_FLAG_IGNORE_PROTOLOOP    (1 << 1)  /* don't throw for prototype loop */
4901 
4902 /*
4903  *  Macro for object validity check
4904  *
4905  *  Assert for currently guaranteed relations between flags, for instance.
4906  */
4907 
4908 #define DUK_ASSERT_HOBJECT_VALID(h) do { \
4909 		DUK_ASSERT((h) != NULL); \
4910 		DUK_ASSERT(!DUK_HOBJECT_IS_CALLABLE((h)) || \
4911 		           DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_FUNCTION); \
4912 		DUK_ASSERT(!DUK_HOBJECT_IS_BUFFEROBJECT((h)) || \
4913 		           (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_BUFFER || \
4914 		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_ARRAYBUFFER || \
4915 		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_DATAVIEW || \
4916 		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_INT8ARRAY || \
4917 		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_UINT8ARRAY || \
4918 		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY || \
4919 		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_INT16ARRAY || \
4920 		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_UINT16ARRAY || \
4921 		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_INT32ARRAY || \
4922 		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_UINT32ARRAY || \
4923 		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_FLOAT32ARRAY || \
4924 		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_FLOAT64ARRAY)); \
4925 	} while (0)
4926 
4927 /*
4928  *  Macros to access the 'props' allocation.
4929  */
4930 
4931 #if defined(DUK_USE_HEAPPTR16)
4932 #define DUK_HOBJECT_GET_PROPS(heap,h) \
4933 	((duk_uint8_t *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, ((duk_heaphdr *) (h))->h_extra16))
4934 #define DUK_HOBJECT_SET_PROPS(heap,h,x) do { \
4935 		((duk_heaphdr *) (h))->h_extra16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (x)); \
4936 	} while (0)
4937 #else
4938 #define DUK_HOBJECT_GET_PROPS(heap,h) \
4939 	((h)->props)
4940 #define DUK_HOBJECT_SET_PROPS(heap,h,x) do { \
4941 		(h)->props = (duk_uint8_t *) (x); \
4942 	} while (0)
4943 #endif
4944 
4945 #if defined(DUK_USE_HOBJECT_LAYOUT_1)
4946 /* LAYOUT 1 */
4947 #define DUK_HOBJECT_E_GET_KEY_BASE(heap,h) \
4948 	((duk_hstring **) (void *) ( \
4949 		DUK_HOBJECT_GET_PROPS((heap), (h)) \
4950 	))
4951 #define DUK_HOBJECT_E_GET_VALUE_BASE(heap,h) \
4952 	((duk_propvalue *) (void *) ( \
4953 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
4954 			DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_hstring *) \
4955 	))
4956 #define DUK_HOBJECT_E_GET_FLAGS_BASE(heap,h) \
4957 	((duk_uint8_t *) (void *) ( \
4958 		DUK_HOBJECT_GET_PROPS((heap), (h)) + DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue)) \
4959 	))
4960 #define DUK_HOBJECT_A_GET_BASE(heap,h) \
4961 	((duk_tval *) (void *) ( \
4962 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
4963 			DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) \
4964 	))
4965 #define DUK_HOBJECT_H_GET_BASE(heap,h) \
4966 	((duk_uint32_t *) (void *) ( \
4967 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
4968 			DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
4969 			DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \
4970 	))
4971 #define DUK_HOBJECT_P_COMPUTE_SIZE(n_ent,n_arr,n_hash) \
4972 	( \
4973 		(n_ent) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
4974 		(n_arr) * sizeof(duk_tval) + \
4975 		(n_hash) * sizeof(duk_uint32_t) \
4976 	)
4977 #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 { \
4978 		(set_e_k) = (duk_hstring **) (void *) (p_base); \
4979 		(set_e_pv) = (duk_propvalue *) (void *) ((set_e_k) + (n_ent)); \
4980 		(set_e_f) = (duk_uint8_t *) (void *) ((set_e_pv) + (n_ent)); \
4981 		(set_a) = (duk_tval *) (void *) ((set_e_f) + (n_ent)); \
4982 		(set_h) = (duk_uint32_t *) (void *) ((set_a) + (n_arr)); \
4983 	} while (0)
4984 #elif defined(DUK_USE_HOBJECT_LAYOUT_2)
4985 /* LAYOUT 2 */
4986 #if (DUK_USE_ALIGN_BY == 4)
4987 #define DUK_HOBJECT_E_FLAG_PADDING(e_sz) ((4 - (e_sz)) & 0x03)
4988 #elif (DUK_USE_ALIGN_BY == 8)
4989 #define DUK_HOBJECT_E_FLAG_PADDING(e_sz) ((8 - (e_sz)) & 0x07)
4990 #elif (DUK_USE_ALIGN_BY == 1)
4991 #define DUK_HOBJECT_E_FLAG_PADDING(e_sz) 0
4992 #else
4993 #error invalid DUK_USE_ALIGN_BY
4994 #endif
4995 #define DUK_HOBJECT_E_GET_KEY_BASE(heap,h) \
4996 	((duk_hstring **) (void *) ( \
4997 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
4998 			DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_propvalue) \
4999 	))
5000 #define DUK_HOBJECT_E_GET_VALUE_BASE(heap,h) \
5001 	((duk_propvalue *) (void *) ( \
5002 		DUK_HOBJECT_GET_PROPS((heap), (h)) \
5003 	))
5004 #define DUK_HOBJECT_E_GET_FLAGS_BASE(heap,h) \
5005 	((duk_uint8_t *) (void *) ( \
5006 		DUK_HOBJECT_GET_PROPS((heap), (h)) + DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue)) \
5007 	))
5008 #define DUK_HOBJECT_A_GET_BASE(heap,h) \
5009 	((duk_tval *) (void *) ( \
5010 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
5011 			DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
5012 			DUK_HOBJECT_E_FLAG_PADDING(DUK_HOBJECT_GET_ESIZE((h))) \
5013 	))
5014 #define DUK_HOBJECT_H_GET_BASE(heap,h) \
5015 	((duk_uint32_t *) (void *) ( \
5016 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
5017 			DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
5018 			DUK_HOBJECT_E_FLAG_PADDING(DUK_HOBJECT_GET_ESIZE((h))) + \
5019 			DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \
5020 	))
5021 #define DUK_HOBJECT_P_COMPUTE_SIZE(n_ent,n_arr,n_hash) \
5022 	( \
5023 		(n_ent) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
5024 		DUK_HOBJECT_E_FLAG_PADDING((n_ent)) + \
5025 		(n_arr) * sizeof(duk_tval) + \
5026 		(n_hash) * sizeof(duk_uint32_t) \
5027 	)
5028 #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 { \
5029 		(set_e_pv) = (duk_propvalue *) (void *) (p_base); \
5030 		(set_e_k) = (duk_hstring **) (void *) ((set_e_pv) + (n_ent)); \
5031 		(set_e_f) = (duk_uint8_t *) (void *) ((set_e_k) + (n_ent)); \
5032 		(set_a) = (duk_tval *) (void *) (((duk_uint8_t *) (set_e_f)) + \
5033 		                                 sizeof(duk_uint8_t) * (n_ent) + \
5034 		                                 DUK_HOBJECT_E_FLAG_PADDING((n_ent))); \
5035 		(set_h) = (duk_uint32_t *) (void *) ((set_a) + (n_arr)); \
5036 	} while (0)
5037 #elif defined(DUK_USE_HOBJECT_LAYOUT_3)
5038 /* LAYOUT 3 */
5039 #define DUK_HOBJECT_E_GET_KEY_BASE(heap,h) \
5040 	((duk_hstring **) (void *) ( \
5041 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
5042 			DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_propvalue) + \
5043 			DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \
5044 	))
5045 #define DUK_HOBJECT_E_GET_VALUE_BASE(heap,h) \
5046 	((duk_propvalue *) (void *) ( \
5047 		DUK_HOBJECT_GET_PROPS((heap), (h)) \
5048 	))
5049 #define DUK_HOBJECT_E_GET_FLAGS_BASE(heap,h) \
5050 	((duk_uint8_t *) (void *) ( \
5051 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
5052 			DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_propvalue) + sizeof(duk_hstring *)) + \
5053 			DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) + \
5054 			DUK_HOBJECT_GET_HSIZE((h)) * sizeof(duk_uint32_t) \
5055 	))
5056 #define DUK_HOBJECT_A_GET_BASE(heap,h) \
5057 	((duk_tval *) (void *) ( \
5058 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
5059 			DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_propvalue) \
5060 	))
5061 #define DUK_HOBJECT_H_GET_BASE(heap,h) \
5062 	((duk_uint32_t *) (void *) ( \
5063 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
5064 			DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_propvalue) + sizeof(duk_hstring *)) + \
5065 			DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \
5066 	))
5067 #define DUK_HOBJECT_P_COMPUTE_SIZE(n_ent,n_arr,n_hash) \
5068 	( \
5069 		(n_ent) * (sizeof(duk_propvalue) + sizeof(duk_hstring *) + sizeof(duk_uint8_t)) + \
5070 		(n_arr) * sizeof(duk_tval) + \
5071 		(n_hash) * sizeof(duk_uint32_t) \
5072 	)
5073 #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 { \
5074 		(set_e_pv) = (duk_propvalue *) (void *) (p_base); \
5075 		(set_a) = (duk_tval *) (void *) ((set_e_pv) + (n_ent)); \
5076 		(set_e_k) = (duk_hstring **) (void *) ((set_a) + (n_arr)); \
5077 		(set_h) = (duk_uint32_t *) (void *) ((set_e_k) + (n_ent)); \
5078 		(set_e_f) = (duk_uint8_t *) (void *) ((set_h) + (n_hash)); \
5079 	} while (0)
5080 #else
5081 #error invalid hobject layout defines
5082 #endif  /* hobject property layout */
5083 
5084 #define DUK_HOBJECT_P_ALLOC_SIZE(h) \
5085 	DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE((h)), DUK_HOBJECT_GET_ASIZE((h)), DUK_HOBJECT_GET_HSIZE((h)))
5086 
5087 #define DUK_HOBJECT_E_GET_KEY(heap,h,i)              (DUK_HOBJECT_E_GET_KEY_BASE((heap), (h))[(i)])
5088 #define DUK_HOBJECT_E_GET_KEY_PTR(heap,h,i)          (&DUK_HOBJECT_E_GET_KEY_BASE((heap), (h))[(i)])
5089 #define DUK_HOBJECT_E_GET_VALUE(heap,h,i)            (DUK_HOBJECT_E_GET_VALUE_BASE((heap), (h))[(i)])
5090 #define DUK_HOBJECT_E_GET_VALUE_PTR(heap,h,i)        (&DUK_HOBJECT_E_GET_VALUE_BASE((heap), (h))[(i)])
5091 #define DUK_HOBJECT_E_GET_VALUE_TVAL(heap,h,i)       (DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).v)
5092 #define DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap,h,i)   (&DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).v)
5093 #define DUK_HOBJECT_E_GET_VALUE_GETTER(heap,h,i)     (DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.get)
5094 #define DUK_HOBJECT_E_GET_VALUE_GETTER_PTR(heap,h,i) (&DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.get)
5095 #define DUK_HOBJECT_E_GET_VALUE_SETTER(heap,h,i)     (DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.set)
5096 #define DUK_HOBJECT_E_GET_VALUE_SETTER_PTR(heap,h,i) (&DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.set)
5097 #define DUK_HOBJECT_E_GET_FLAGS(heap,h,i)            (DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)])
5098 #define DUK_HOBJECT_E_GET_FLAGS_PTR(heap,h,i)        (&DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)])
5099 #define DUK_HOBJECT_A_GET_VALUE(heap,h,i)            (DUK_HOBJECT_A_GET_BASE((heap), (h))[(i)])
5100 #define DUK_HOBJECT_A_GET_VALUE_PTR(heap,h,i)        (&DUK_HOBJECT_A_GET_BASE((heap), (h))[(i)])
5101 #define DUK_HOBJECT_H_GET_INDEX(heap,h,i)            (DUK_HOBJECT_H_GET_BASE((heap), (h))[(i)])
5102 #define DUK_HOBJECT_H_GET_INDEX_PTR(heap,h,i)        (&DUK_HOBJECT_H_GET_BASE((heap), (h))[(i)])
5103 
5104 #define DUK_HOBJECT_E_SET_KEY(heap,h,i,k)  do { \
5105 		DUK_HOBJECT_E_GET_KEY((heap), (h), (i)) = (k); \
5106 	} while (0)
5107 #define DUK_HOBJECT_E_SET_VALUE(heap,h,i,v)  do { \
5108 		DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)) = (v); \
5109 	} while (0)
5110 #define DUK_HOBJECT_E_SET_VALUE_TVAL(heap,h,i,v)  do { \
5111 		DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).v = (v); \
5112 	} while (0)
5113 #define DUK_HOBJECT_E_SET_VALUE_GETTER(heap,h,i,v)  do { \
5114 		DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.get = (v); \
5115 	} while (0)
5116 #define DUK_HOBJECT_E_SET_VALUE_SETTER(heap,h,i,v)  do { \
5117 		DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.set = (v); \
5118 	} while (0)
5119 #define DUK_HOBJECT_E_SET_FLAGS(heap,h,i,f)  do { \
5120 		DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) = (duk_uint8_t) (f); \
5121 	} while (0)
5122 #define DUK_HOBJECT_A_SET_VALUE(heap,h,i,v)  do { \
5123 		DUK_HOBJECT_A_GET_VALUE((heap), (h), (i)) = (v); \
5124 	} while (0)
5125 #define DUK_HOBJECT_A_SET_VALUE_TVAL(heap,h,i,v) \
5126 	DUK_HOBJECT_A_SET_VALUE((heap), (h), (i), (v))  /* alias for above */
5127 #define DUK_HOBJECT_H_SET_INDEX(heap,h,i,v)  do { \
5128 		DUK_HOBJECT_H_GET_INDEX((heap), (h), (i)) = (v); \
5129 	} while (0)
5130 
5131 #define DUK_HOBJECT_E_SET_FLAG_BITS(heap,h,i,mask)  do { \
5132 		DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)] |= (mask); \
5133 	} while (0)
5134 
5135 #define DUK_HOBJECT_E_CLEAR_FLAG_BITS(heap,h,i,mask)  do { \
5136 		DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)] &= ~(mask); \
5137 	} while (0)
5138 
5139 #define DUK_HOBJECT_E_SLOT_IS_WRITABLE(heap,h,i)     ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_WRITABLE) != 0)
5140 #define DUK_HOBJECT_E_SLOT_IS_ENUMERABLE(heap,h,i)   ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_ENUMERABLE) != 0)
5141 #define DUK_HOBJECT_E_SLOT_IS_CONFIGURABLE(heap,h,i) ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_CONFIGURABLE) != 0)
5142 #define DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap,h,i)     ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_ACCESSOR) != 0)
5143 
5144 #define DUK_HOBJECT_E_SLOT_SET_WRITABLE(heap,h,i)        DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_WRITABLE)
5145 #define DUK_HOBJECT_E_SLOT_SET_ENUMERABLE(heap,h,i)      DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ENUMERABLE)
5146 #define DUK_HOBJECT_E_SLOT_SET_CONFIGURABLE(heap,h,i)    DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_CONFIGURABLE)
5147 #define DUK_HOBJECT_E_SLOT_SET_ACCESSOR(heap,h,i)        DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ACCESSOR)
5148 
5149 #define DUK_HOBJECT_E_SLOT_CLEAR_WRITABLE(heap,h,i)      DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_WRITABLE)
5150 #define DUK_HOBJECT_E_SLOT_CLEAR_ENUMERABLE(heap,h,i)    DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ENUMERABLE)
5151 #define DUK_HOBJECT_E_SLOT_CLEAR_CONFIGURABLE(heap,h,i)  DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_CONFIGURABLE)
5152 #define DUK_HOBJECT_E_SLOT_CLEAR_ACCESSOR(heap,h,i)      DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ACCESSOR)
5153 
5154 #define DUK_PROPDESC_IS_WRITABLE(p)             (((p)->flags & DUK_PROPDESC_FLAG_WRITABLE) != 0)
5155 #define DUK_PROPDESC_IS_ENUMERABLE(p)           (((p)->flags & DUK_PROPDESC_FLAG_ENUMERABLE) != 0)
5156 #define DUK_PROPDESC_IS_CONFIGURABLE(p)         (((p)->flags & DUK_PROPDESC_FLAG_CONFIGURABLE) != 0)
5157 #define DUK_PROPDESC_IS_ACCESSOR(p)             (((p)->flags & DUK_PROPDESC_FLAG_ACCESSOR) != 0)
5158 
5159 #define DUK_HOBJECT_HASHIDX_UNUSED              0xffffffffUL
5160 #define DUK_HOBJECT_HASHIDX_DELETED             0xfffffffeUL
5161 
5162 /*
5163  *  Macros for accessing size fields
5164  */
5165 
5166 #if defined(DUK_USE_OBJSIZES16)
5167 #define DUK_HOBJECT_GET_ESIZE(h) ((h)->e_size16)
5168 #define DUK_HOBJECT_SET_ESIZE(h,v) do { (h)->e_size16 = (v); } while (0)
5169 #define DUK_HOBJECT_GET_ENEXT(h) ((h)->e_next16)
5170 #define DUK_HOBJECT_SET_ENEXT(h,v) do { (h)->e_next16 = (v); } while (0)
5171 #define DUK_HOBJECT_POSTINC_ENEXT(h) ((h)->e_next16++)
5172 #define DUK_HOBJECT_GET_ASIZE(h) ((h)->a_size16)
5173 #define DUK_HOBJECT_SET_ASIZE(h,v) do { (h)->a_size16 = (v); } while (0)
5174 #if defined(DUK_USE_HOBJECT_HASH_PART)
5175 #define DUK_HOBJECT_GET_HSIZE(h) ((h)->h_size16)
5176 #define DUK_HOBJECT_SET_HSIZE(h,v) do { (h)->h_size16 = (v); } while (0)
5177 #else
5178 #define DUK_HOBJECT_GET_HSIZE(h) 0
5179 #define DUK_HOBJECT_SET_HSIZE(h,v) do { DUK_ASSERT((v) == 0); } while (0)
5180 #endif
5181 #else
5182 #define DUK_HOBJECT_GET_ESIZE(h) ((h)->e_size)
5183 #define DUK_HOBJECT_SET_ESIZE(h,v) do { (h)->e_size = (v); } while (0)
5184 #define DUK_HOBJECT_GET_ENEXT(h) ((h)->e_next)
5185 #define DUK_HOBJECT_SET_ENEXT(h,v) do { (h)->e_next = (v); } while (0)
5186 #define DUK_HOBJECT_POSTINC_ENEXT(h) ((h)->e_next++)
5187 #define DUK_HOBJECT_GET_ASIZE(h) ((h)->a_size)
5188 #define DUK_HOBJECT_SET_ASIZE(h,v) do { (h)->a_size = (v); } while (0)
5189 #if defined(DUK_USE_HOBJECT_HASH_PART)
5190 #define DUK_HOBJECT_GET_HSIZE(h) ((h)->h_size)
5191 #define DUK_HOBJECT_SET_HSIZE(h,v) do { (h)->h_size = (v); } while (0)
5192 #else
5193 #define DUK_HOBJECT_GET_HSIZE(h) 0
5194 #define DUK_HOBJECT_SET_HSIZE(h,v) do { DUK_ASSERT((v) == 0); } while (0)
5195 #endif
5196 #endif
5197 
5198 /*
5199  *  Misc
5200  */
5201 
5202 /* Maximum prototype traversal depth.  Sanity limit which handles e.g.
5203  * prototype loops (even complex ones like 1->2->3->4->2->3->4->2->3->4).
5204  */
5205 #define DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY      10000L
5206 
5207 /* Maximum traversal depth for "bound function" chains. */
5208 #define DUK_HOBJECT_BOUND_CHAIN_SANITY          10000L
5209 
5210 /*
5211  *  Ecmascript [[Class]]
5212  */
5213 
5214 /* range check not necessary because all 4-bit values are mapped */
5215 #define DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(n)  duk_class_number_to_stridx[(n)]
5216 
5217 #define DUK_HOBJECT_GET_CLASS_STRING(heap,h)          \
5218 	DUK_HEAP_GET_STRING( \
5219 		(heap), \
5220 		DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(DUK_HOBJECT_GET_CLASS_NUMBER((h))) \
5221 	)
5222 
5223 /*
5224  *  Macros for property handling
5225  */
5226 
5227 #if defined(DUK_USE_HEAPPTR16)
5228 #define DUK_HOBJECT_GET_PROTOTYPE(heap,h) \
5229 	((duk_hobject *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->prototype16))
5230 #define DUK_HOBJECT_SET_PROTOTYPE(heap,h,x) do { \
5231 		(h)->prototype16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (x)); \
5232 	} while (0)
5233 #else
5234 #define DUK_HOBJECT_GET_PROTOTYPE(heap,h) \
5235 	((h)->prototype)
5236 #define DUK_HOBJECT_SET_PROTOTYPE(heap,h,x) do { \
5237 		(h)->prototype = (x); \
5238 	} while (0)
5239 #endif
5240 
5241 /* note: this updates refcounts */
5242 #define DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr,h,p)       duk_hobject_set_prototype_updref((thr), (h), (p))
5243 
5244 /*
5245  *  Resizing and hash behavior
5246  */
5247 
5248 /* Sanity limit on max number of properties (allocated, not necessarily used).
5249  * This is somewhat arbitrary, but if we're close to 2**32 properties some
5250  * algorithms will fail (e.g. hash size selection, next prime selection).
5251  * Also, we use negative array/entry table indices to indicate 'not found',
5252  * so anything above 0x80000000 will cause trouble now.
5253  */
5254 #if defined(DUK_USE_OBJSIZES16)
5255 #define DUK_HOBJECT_MAX_PROPERTIES       0x0000ffffUL
5256 #else
5257 #define DUK_HOBJECT_MAX_PROPERTIES       0x7fffffffUL   /* 2**31-1 ~= 2G properties */
5258 #endif
5259 
5260 /* higher value conserves memory; also note that linear scan is cache friendly */
5261 #define DUK_HOBJECT_E_USE_HASH_LIMIT     32
5262 
5263 /* hash size relative to entries size: for value X, approx. hash_prime(e_size + e_size / X) */
5264 #define DUK_HOBJECT_H_SIZE_DIVISOR       4  /* hash size approx. 1.25 times entries size */
5265 
5266 /* if new_size < L * old_size, resize without abandon check; L = 3-bit fixed point, e.g. 9 -> 9/8 = 112.5% */
5267 #define DUK_HOBJECT_A_FAST_RESIZE_LIMIT  9  /* 112.5%, i.e. new size less than 12.5% higher -> fast resize */
5268 
5269 /* if density < L, abandon array part, L = 3-bit fixed point, e.g. 2 -> 2/8 = 25% */
5270 /* limit is quite low: one array entry is 8 bytes, one normal entry is 4+1+8+4 = 17 bytes (with hash entry) */
5271 #define DUK_HOBJECT_A_ABANDON_LIMIT      2  /* 25%, i.e. less than 25% used -> abandon */
5272 
5273 /* internal align target for props allocation, must be 2*n for some n */
5274 #if (DUK_USE_ALIGN_BY == 4)
5275 #define DUK_HOBJECT_ALIGN_TARGET         4
5276 #elif (DUK_USE_ALIGN_BY == 8)
5277 #define DUK_HOBJECT_ALIGN_TARGET         8
5278 #elif (DUK_USE_ALIGN_BY == 1)
5279 #define DUK_HOBJECT_ALIGN_TARGET         1
5280 #else
5281 #error invalid DUK_USE_ALIGN_BY
5282 #endif
5283 
5284 /* controls for minimum entry part growth */
5285 #define DUK_HOBJECT_E_MIN_GROW_ADD       16
5286 #define DUK_HOBJECT_E_MIN_GROW_DIVISOR   8  /* 2^3 -> 1/8 = 12.5% min growth */
5287 
5288 /* controls for minimum array part growth */
5289 #define DUK_HOBJECT_A_MIN_GROW_ADD       16
5290 #define DUK_HOBJECT_A_MIN_GROW_DIVISOR   8  /* 2^3 -> 1/8 = 12.5% min growth */
5291 
5292 /* probe sequence */
5293 #define DUK_HOBJECT_HASH_INITIAL(hash,h_size)  ((hash) % (h_size))
5294 #define DUK_HOBJECT_HASH_PROBE_STEP(hash)      DUK_UTIL_GET_HASH_PROBE_STEP((hash))
5295 
5296 /*
5297  *  PC-to-line constants
5298  */
5299 
5300 #define DUK_PC2LINE_SKIP    64
5301 
5302 /* maximum length for a SKIP-1 diffstream: 35 bits per entry, rounded up to bytes */
5303 #define DUK_PC2LINE_MAX_DIFF_LENGTH    (((DUK_PC2LINE_SKIP - 1) * 35 + 7) / 8)
5304 
5305 /*
5306  *  Struct defs
5307  */
5308 
5309 struct duk_propaccessor {
5310 	duk_hobject *get;
5311 	duk_hobject *set;
5312 };
5313 
5314 union duk_propvalue {
5315 	/* The get/set pointers could be 16-bit pointer compressed but it
5316 	 * would make no difference on 32-bit platforms because duk_tval is
5317 	 * 8 bytes or more anyway.
5318 	 */
5319 	duk_tval v;
5320 	duk_propaccessor a;
5321 };
5322 
5323 struct duk_propdesc {
5324 	/* read-only values 'lifted' for ease of use */
5325 	duk_small_int_t flags;
5326 	duk_hobject *get;
5327 	duk_hobject *set;
5328 
5329 	/* for updating (all are set to < 0 for virtual properties) */
5330 	duk_int_t e_idx;  /* prop index in 'entry part', < 0 if not there */
5331 	duk_int_t h_idx;  /* prop index in 'hash part', < 0 if not there */
5332 	duk_int_t a_idx;  /* prop index in 'array part', < 0 if not there */
5333 };
5334 
5335 struct duk_hobject {
5336 	duk_heaphdr hdr;
5337 
5338 	/*
5339 	 *  'props' contains {key,value,flags} entries, optional array entries, and
5340 	 *  an optional hash lookup table for non-array entries in a single 'sliced'
5341 	 *  allocation.  There are several layout options, which differ slightly in
5342 	 *  generated code size/speed and alignment/padding; duk_features.h selects
5343 	 *  the layout used.
5344 	 *
5345 	 *  Layout 1 (DUK_USE_HOBJECT_LAYOUT_1):
5346 	 *
5347 	 *    e_size * sizeof(duk_hstring *)         bytes of   entry keys (e_next gc reachable)
5348 	 *    e_size * sizeof(duk_propvalue)         bytes of   entry values (e_next gc reachable)
5349 	 *    e_size * sizeof(duk_uint8_t)           bytes of   entry flags (e_next gc reachable)
5350 	 *    a_size * sizeof(duk_tval)              bytes of   (opt) array values (plain only) (all gc reachable)
5351 	 *    h_size * sizeof(duk_uint32_t)          bytes of   (opt) hash indexes to entries (e_size),
5352 	 *                                                      0xffffffffUL = unused, 0xfffffffeUL = deleted
5353 	 *
5354 	 *  Layout 2 (DUK_USE_HOBJECT_LAYOUT_2):
5355 	 *
5356 	 *    e_size * sizeof(duk_propvalue)         bytes of   entry values (e_next gc reachable)
5357 	 *    e_size * sizeof(duk_hstring *)         bytes of   entry keys (e_next gc reachable)
5358 	 *    e_size * sizeof(duk_uint8_t) + pad     bytes of   entry flags (e_next gc reachable)
5359 	 *    a_size * sizeof(duk_tval)              bytes of   (opt) array values (plain only) (all gc reachable)
5360 	 *    h_size * sizeof(duk_uint32_t)          bytes of   (opt) hash indexes to entries (e_size),
5361 	 *                                                      0xffffffffUL = unused, 0xfffffffeUL = deleted
5362 	 *
5363 	 *  Layout 3 (DUK_USE_HOBJECT_LAYOUT_3):
5364 	 *
5365 	 *    e_size * sizeof(duk_propvalue)         bytes of   entry values (e_next gc reachable)
5366 	 *    a_size * sizeof(duk_tval)              bytes of   (opt) array values (plain only) (all gc reachable)
5367 	 *    e_size * sizeof(duk_hstring *)         bytes of   entry keys (e_next gc reachable)
5368 	 *    h_size * sizeof(duk_uint32_t)          bytes of   (opt) hash indexes to entries (e_size),
5369 	 *                                                      0xffffffffUL = unused, 0xfffffffeUL = deleted
5370 	 *    e_size * sizeof(duk_uint8_t)           bytes of   entry flags (e_next gc reachable)
5371 	 *
5372 	 *  In layout 1, the 'e_next' count is rounded to 4 or 8 on platforms
5373 	 *  requiring 4 or 8 byte alignment.  This ensures proper alignment
5374 	 *  for the entries, at the cost of memory footprint.  However, it's
5375 	 *  probably preferable to use another layout on such platforms instead.
5376 	 *
5377 	 *  In layout 2, the key and value parts are swapped to avoid padding
5378 	 *  the key array on platforms requiring alignment by 8.  The flags part
5379 	 *  is padded to get alignment for array entries.  The 'e_next' count does
5380 	 *  not need to be rounded as in layout 1.
5381 	 *
5382 	 *  In layout 3, entry values and array values are always aligned properly,
5383 	 *  and assuming pointers are at most 8 bytes, so are the entry keys.  Hash
5384 	 *  indices will be properly aligned (assuming pointers are at least 4 bytes).
5385 	 *  Finally, flags don't need additional alignment.  This layout provides
5386 	 *  compact allocations without padding (even on platforms with alignment
5387 	 *  requirements) at the cost of a bit slower lookups.
5388 	 *
5389 	 *  Objects with few keys don't have a hash index; keys are looked up linearly,
5390 	 *  which is cache efficient because the keys are consecutive.  Larger objects
5391 	 *  have a hash index part which contains integer indexes to the entries part.
5392 	 *
5393 	 *  A single allocation reduces memory allocation overhead but requires more
5394 	 *  work when any part needs to be resized.  A sliced allocation for entries
5395 	 *  makes linear key matching faster on most platforms (more locality) and
5396 	 *  skimps on flags size (which would be followed by 3 bytes of padding in
5397 	 *  most architectures if entries were placed in a struct).
5398 	 *
5399 	 *  'props' also contains internal properties distinguished with a non-BMP
5400 	 *  prefix.  Often used properties should be placed early in 'props' whenever
5401 	 *  possible to make accessing them as fast a possible.
5402 	 */
5403 
5404 #if defined(DUK_USE_HEAPPTR16)
5405 	/* Located in duk_heaphdr h_extra16.  Subclasses of duk_hobject (like
5406 	 * duk_hcompiledfunction) are not free to use h_extra16 for this reason.
5407 	 */
5408 #else
5409 	duk_uint8_t *props;
5410 #endif
5411 
5412 	/* prototype: the only internal property lifted outside 'e' as it is so central */
5413 #if defined(DUK_USE_HEAPPTR16)
5414 	duk_uint16_t prototype16;
5415 #else
5416 	duk_hobject *prototype;
5417 #endif
5418 
5419 #if defined(DUK_USE_OBJSIZES16)
5420 	duk_uint16_t e_size16;
5421 	duk_uint16_t e_next16;
5422 	duk_uint16_t a_size16;
5423 #if defined(DUK_USE_HOBJECT_HASH_PART)
5424 	duk_uint16_t h_size16;
5425 #endif
5426 #else
5427 	duk_uint32_t e_size;  /* entry part size */
5428 	duk_uint32_t e_next;  /* index for next new key ([0,e_next[ are gc reachable) */
5429 	duk_uint32_t a_size;  /* array part size (entirely gc reachable) */
5430 #if defined(DUK_USE_HOBJECT_HASH_PART)
5431 	duk_uint32_t h_size;  /* hash part size or 0 if unused */
5432 #endif
5433 #endif
5434 };
5435 
5436 /*
5437  *  Exposed data
5438  */
5439 
5440 #if !defined(DUK_SINGLE_FILE)
5441 DUK_INTERNAL_DECL duk_uint8_t duk_class_number_to_stridx[32];
5442 #endif  /* !DUK_SINGLE_FILE */
5443 
5444 /*
5445  *  Prototypes
5446  */
5447 
5448 /* alloc and init */
5449 DUK_INTERNAL_DECL duk_hobject *duk_hobject_alloc(duk_heap *heap, duk_uint_t hobject_flags);
5450 #if 0  /* unused */
5451 DUK_INTERNAL_DECL duk_hobject *duk_hobject_alloc_checked(duk_hthread *thr, duk_uint_t hobject_flags);
5452 #endif
5453 DUK_INTERNAL_DECL duk_hcompiledfunction *duk_hcompiledfunction_alloc(duk_heap *heap, duk_uint_t hobject_flags);
5454 DUK_INTERNAL_DECL duk_hnativefunction *duk_hnativefunction_alloc(duk_heap *heap, duk_uint_t hobject_flags);
5455 DUK_INTERNAL duk_hbufferobject *duk_hbufferobject_alloc(duk_heap *heap, duk_uint_t hobject_flags);
5456 DUK_INTERNAL_DECL duk_hthread *duk_hthread_alloc(duk_heap *heap, duk_uint_t hobject_flags);
5457 
5458 /* low-level property functions */
5459 DUK_INTERNAL_DECL void duk_hobject_find_existing_entry(duk_heap *heap, duk_hobject *obj, duk_hstring *key, duk_int_t *e_idx, duk_int_t *h_idx);
5460 DUK_INTERNAL_DECL duk_tval *duk_hobject_find_existing_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_hstring *key);
5461 DUK_INTERNAL_DECL duk_tval *duk_hobject_find_existing_entry_tval_ptr_and_attrs(duk_heap *heap, duk_hobject *obj, duk_hstring *key, duk_int_t *out_attrs);
5462 DUK_INTERNAL_DECL duk_tval *duk_hobject_find_existing_array_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_uarridx_t i);
5463 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);
5464 
5465 /* XXX: when optimizing for guaranteed property slots, use a guaranteed
5466  * slot for internal value; this call can then access it directly.
5467  */
5468 #define duk_hobject_get_internal_value_tval_ptr(heap,obj) \
5469 	duk_hobject_find_existing_entry_tval_ptr((heap), (obj), DUK_HEAP_STRING_INT_VALUE((heap)))
5470 
5471 /* core property functions */
5472 DUK_INTERNAL_DECL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key);
5473 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);
5474 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);
5475 DUK_INTERNAL_DECL duk_bool_t duk_hobject_hasprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key);
5476 
5477 /* internal property functions */
5478 #define DUK_DELPROP_FLAG_THROW  (1 << 0)
5479 #define DUK_DELPROP_FLAG_FORCE  (1 << 1)
5480 DUK_INTERNAL_DECL duk_bool_t duk_hobject_delprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags);
5481 DUK_INTERNAL_DECL duk_bool_t duk_hobject_hasprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key);
5482 DUK_INTERNAL_DECL void duk_hobject_define_property_internal(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags);
5483 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);
5484 DUK_INTERNAL_DECL void duk_hobject_define_accessor_internal(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_hobject *getter, duk_hobject *setter, duk_small_uint_t propflags);
5485 DUK_INTERNAL_DECL void duk_hobject_set_length(duk_hthread *thr, duk_hobject *obj, duk_uint32_t length);  /* XXX: duk_uarridx_t? */
5486 DUK_INTERNAL_DECL void duk_hobject_set_length_zero(duk_hthread *thr, duk_hobject *obj);
5487 DUK_INTERNAL_DECL duk_uint32_t duk_hobject_get_length(duk_hthread *thr, duk_hobject *obj);  /* XXX: duk_uarridx_t? */
5488 
5489 /* helpers for defineProperty() and defineProperties() */
5490 DUK_INTERNAL_DECL
5491 void duk_hobject_prepare_property_descriptor(duk_context *ctx,
5492                                              duk_idx_t idx_in,
5493                                              duk_uint_t *out_defprop_flags,
5494                                              duk_idx_t *out_idx_value,
5495                                              duk_hobject **out_getter,
5496                                              duk_hobject **out_setter);
5497 DUK_INTERNAL_DECL
5498 void duk_hobject_define_property_helper(duk_context *ctx,
5499                                         duk_uint_t defprop_flags,
5500                                         duk_hobject *obj,
5501                                         duk_hstring *key,
5502                                         duk_idx_t idx_value,
5503                                         duk_hobject *get,
5504                                         duk_hobject *set);
5505 
5506 /* Object built-in methods */
5507 DUK_INTERNAL_DECL duk_ret_t duk_hobject_object_get_own_property_descriptor(duk_context *ctx);
5508 DUK_INTERNAL_DECL void duk_hobject_object_seal_freeze_helper(duk_hthread *thr, duk_hobject *obj, duk_bool_t is_freeze);
5509 DUK_INTERNAL_DECL duk_bool_t duk_hobject_object_is_sealed_frozen_helper(duk_hthread *thr, duk_hobject *obj, duk_bool_t is_frozen);
5510 DUK_INTERNAL_DECL duk_bool_t duk_hobject_object_ownprop_helper(duk_context *ctx, duk_small_uint_t required_desc_flags);
5511 
5512 /* internal properties */
5513 DUK_INTERNAL_DECL duk_bool_t duk_hobject_get_internal_value(duk_heap *heap, duk_hobject *obj, duk_tval *tv);
5514 DUK_INTERNAL_DECL duk_hstring *duk_hobject_get_internal_value_string(duk_heap *heap, duk_hobject *obj);
5515 
5516 /* hobject management functions */
5517 DUK_INTERNAL_DECL void duk_hobject_compact_props(duk_hthread *thr, duk_hobject *obj);
5518 
5519 /* ES6 proxy */
5520 #if defined(DUK_USE_ES6_PROXY)
5521 DUK_INTERNAL_DECL duk_bool_t duk_hobject_proxy_check(duk_hthread *thr, duk_hobject *obj, duk_hobject **out_target, duk_hobject **out_handler);
5522 DUK_INTERNAL_DECL duk_hobject *duk_hobject_resolve_proxy_target(duk_hthread *thr, duk_hobject *obj);
5523 #endif
5524 
5525 /* enumeration */
5526 DUK_INTERNAL_DECL void duk_hobject_enumerator_create(duk_context *ctx, duk_small_uint_t enum_flags);
5527 DUK_INTERNAL_DECL duk_ret_t duk_hobject_get_enumerated_keys(duk_context *ctx, duk_small_uint_t enum_flags);
5528 DUK_INTERNAL_DECL duk_bool_t duk_hobject_enumerator_next(duk_context *ctx, duk_bool_t get_value);
5529 
5530 /* macros */
5531 DUK_INTERNAL_DECL void duk_hobject_set_prototype_updref(duk_hthread *thr, duk_hobject *h, duk_hobject *p);
5532 
5533 /* finalization */
5534 DUK_INTERNAL_DECL void duk_hobject_run_finalizer(duk_hthread *thr, duk_hobject *obj);
5535 
5536 /* pc2line */
5537 #if defined(DUK_USE_PC2LINE)
5538 DUK_INTERNAL_DECL void duk_hobject_pc2line_pack(duk_hthread *thr, duk_compiler_instr *instrs, duk_uint_fast32_t length);
5539 DUK_INTERNAL_DECL duk_uint_fast32_t duk_hobject_pc2line_query(duk_context *ctx, duk_idx_t idx_func, duk_uint_fast32_t pc);
5540 #endif
5541 
5542 /* misc */
5543 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);
5544 
5545 #endif  /* DUK_HOBJECT_H_INCLUDED */
5546 /*
5547  *  Heap compiled function (Ecmascript function) representation.
5548  *
5549  *  There is a single data buffer containing the Ecmascript function's
5550  *  bytecode, constants, and inner functions.
5551  */
5552 
5553 #ifndef DUK_HCOMPILEDFUNCTION_H_INCLUDED
5554 #define DUK_HCOMPILEDFUNCTION_H_INCLUDED
5555 
5556 /*
5557  *  Field accessor macros
5558  */
5559 
5560 /* XXX: casts could be improved, especially for GET/SET DATA */
5561 
5562 #if defined(DUK_USE_HEAPPTR16)
5563 #define DUK_HCOMPILEDFUNCTION_GET_DATA(heap,h) \
5564 	((duk_hbuffer_fixed *) (void *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->data16))
5565 #define DUK_HCOMPILEDFUNCTION_SET_DATA(heap,h,v) do { \
5566 		(h)->data16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
5567 	} while (0)
5568 #define DUK_HCOMPILEDFUNCTION_GET_FUNCS(heap,h)  \
5569 	((duk_hobject **) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->funcs16)))
5570 #define DUK_HCOMPILEDFUNCTION_SET_FUNCS(heap,h,v)  do { \
5571 		(h)->funcs16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
5572 	} while (0)
5573 #define DUK_HCOMPILEDFUNCTION_GET_BYTECODE(heap,h)  \
5574 	((duk_instr_t *) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->bytecode16)))
5575 #define DUK_HCOMPILEDFUNCTION_SET_BYTECODE(heap,h,v)  do { \
5576 		(h)->bytecode16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
5577 	} while (0)
5578 #else
5579 #define DUK_HCOMPILEDFUNCTION_GET_DATA(heap,h) \
5580 	((duk_hbuffer_fixed *) (void *) (h)->data)
5581 #define DUK_HCOMPILEDFUNCTION_SET_DATA(heap,h,v) do { \
5582 		(h)->data = (duk_hbuffer *) (v); \
5583 	} while (0)
5584 #define DUK_HCOMPILEDFUNCTION_GET_FUNCS(heap,h)  \
5585 	((h)->funcs)
5586 #define DUK_HCOMPILEDFUNCTION_SET_FUNCS(heap,h,v)  do { \
5587 		(h)->funcs = (v); \
5588 	} while (0)
5589 #define DUK_HCOMPILEDFUNCTION_GET_BYTECODE(heap,h)  \
5590 	((h)->bytecode)
5591 #define DUK_HCOMPILEDFUNCTION_SET_BYTECODE(heap,h,v)  do { \
5592 		(h)->bytecode = (v); \
5593 	} while (0)
5594 #endif
5595 
5596 /*
5597  *  Accessor macros for function specific data areas
5598  */
5599 
5600 /* Note: assumes 'data' is always a fixed buffer */
5601 #define DUK_HCOMPILEDFUNCTION_GET_BUFFER_BASE(heap,h)  \
5602 	DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), DUK_HCOMPILEDFUNCTION_GET_DATA((heap), (h)))
5603 
5604 #define DUK_HCOMPILEDFUNCTION_GET_CONSTS_BASE(heap,h)  \
5605 	((duk_tval *) (void *) DUK_HCOMPILEDFUNCTION_GET_BUFFER_BASE((heap), (h)))
5606 
5607 #define DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE(heap,h)  \
5608 	DUK_HCOMPILEDFUNCTION_GET_FUNCS((heap), (h))
5609 
5610 #define DUK_HCOMPILEDFUNCTION_GET_CODE_BASE(heap,h)  \
5611 	DUK_HCOMPILEDFUNCTION_GET_BYTECODE((heap), (h))
5612 
5613 #define DUK_HCOMPILEDFUNCTION_GET_CONSTS_END(heap,h)  \
5614 	((duk_tval *) (void *) DUK_HCOMPILEDFUNCTION_GET_FUNCS((heap), (h)))
5615 
5616 #define DUK_HCOMPILEDFUNCTION_GET_FUNCS_END(heap,h)  \
5617 	((duk_hobject **) (void *) DUK_HCOMPILEDFUNCTION_GET_BYTECODE((heap), (h)))
5618 
5619 /* XXX: double evaluation of DUK_HCOMPILEDFUNCTION_GET_DATA() */
5620 #define DUK_HCOMPILEDFUNCTION_GET_CODE_END(heap,h)  \
5621 	((duk_instr_t *) (void *) (DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), DUK_HCOMPILEDFUNCTION_GET_DATA((heap), (h))) + \
5622 	                DUK_HBUFFER_GET_SIZE((duk_hbuffer *) DUK_HCOMPILEDFUNCTION_GET_DATA((heap), h))))
5623 
5624 #define DUK_HCOMPILEDFUNCTION_GET_CONSTS_SIZE(heap,h)  \
5625 	( \
5626 	 (duk_size_t) \
5627 	 ( \
5628 	   ((const duk_uint8_t *) DUK_HCOMPILEDFUNCTION_GET_CONSTS_END((heap), (h))) - \
5629 	   ((const duk_uint8_t *) DUK_HCOMPILEDFUNCTION_GET_CONSTS_BASE((heap), (h))) \
5630 	 ) \
5631 	)
5632 
5633 #define DUK_HCOMPILEDFUNCTION_GET_FUNCS_SIZE(heap,h)  \
5634 	( \
5635 	 (duk_size_t) \
5636 	 ( \
5637 	   ((const duk_uint8_t *) DUK_HCOMPILEDFUNCTION_GET_FUNCS_END((heap), (h))) - \
5638 	   ((const duk_uint8_t *) DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE((heap), (h))) \
5639 	 ) \
5640 	)
5641 
5642 #define DUK_HCOMPILEDFUNCTION_GET_CODE_SIZE(heap,h)  \
5643 	( \
5644 	 (duk_size_t) \
5645 	 ( \
5646 	   ((const duk_uint8_t *) DUK_HCOMPILEDFUNCTION_GET_CODE_END((heap),(h))) - \
5647 	   ((const duk_uint8_t *) DUK_HCOMPILEDFUNCTION_GET_CODE_BASE((heap),(h))) \
5648 	 ) \
5649 	)
5650 
5651 #define DUK_HCOMPILEDFUNCTION_GET_CONSTS_COUNT(heap,h)  \
5652 	((duk_size_t) (DUK_HCOMPILEDFUNCTION_GET_CONSTS_SIZE((heap), (h)) / sizeof(duk_tval)))
5653 
5654 #define DUK_HCOMPILEDFUNCTION_GET_FUNCS_COUNT(heap,h)  \
5655 	((duk_size_t) (DUK_HCOMPILEDFUNCTION_GET_FUNCS_SIZE((heap), (h)) / sizeof(duk_hobject *)))
5656 
5657 #define DUK_HCOMPILEDFUNCTION_GET_CODE_COUNT(heap,h)  \
5658 	((duk_size_t) (DUK_HCOMPILEDFUNCTION_GET_CODE_SIZE((heap), (h)) / sizeof(duk_instr_t)))
5659 
5660 
5661 /*
5662  *  Main struct
5663  */
5664 
5665 struct duk_hcompiledfunction {
5666 	/* shared object part */
5667 	duk_hobject obj;
5668 
5669 	/*
5670 	 *  Pointers to function data area for faster access.  Function
5671 	 *  data is a buffer shared between all closures of the same
5672 	 *  "template" function.  The data buffer is always fixed (non-
5673 	 *  dynamic, hence stable), with a layout as follows:
5674 	 *
5675 	 *    constants (duk_tval)
5676 	 *    inner functions (duk_hobject *)
5677 	 *    bytecode (duk_instr_t)
5678 	 *
5679 	 *  Note: bytecode end address can be computed from 'data' buffer
5680 	 *  size.  It is not strictly necessary functionally, assuming
5681 	 *  bytecode never jumps outside its allocated area.  However,
5682 	 *  it's a safety/robustness feature for avoiding the chance of
5683 	 *  executing random data as bytecode due to a compiler error.
5684 	 *
5685 	 *  Note: values in the data buffer must be incref'd (they will
5686 	 *  be decref'd on release) for every compiledfunction referring
5687 	 *  to the 'data' element.
5688 	 */
5689 
5690 	/* Data area, fixed allocation, stable data ptrs. */
5691 #if defined(DUK_USE_HEAPPTR16)
5692 	duk_uint16_t data16;
5693 #else
5694 	duk_hbuffer *data;
5695 #endif
5696 
5697 	/* No need for constants pointer (= same as data).
5698 	 *
5699 	 * When using 16-bit packing alignment to 4 is nice.  'funcs' will be
5700 	 * 4-byte aligned because 'constants' are duk_tvals.  For now the
5701 	 * inner function pointers are not compressed, so that 'bytecode' will
5702 	 * also be 4-byte aligned.
5703 	 */
5704 #if defined(DUK_USE_HEAPPTR16)
5705 	duk_uint16_t funcs16;
5706 	duk_uint16_t bytecode16;
5707 #else
5708 	duk_hobject **funcs;
5709 	duk_instr_t *bytecode;
5710 #endif
5711 
5712 	/*
5713 	 *  'nregs' registers are allocated on function entry, at most 'nargs'
5714 	 *  are initialized to arguments, and the rest to undefined.  Arguments
5715 	 *  above 'nregs' are not mapped to registers.  All registers in the
5716 	 *  active stack range must be initialized because they are GC reachable.
5717 	 *  'nargs' is needed so that if the function is given more than 'nargs'
5718 	 *  arguments, the additional arguments do not 'clobber' registers
5719 	 *  beyond 'nregs' which must be consistently initialized to undefined.
5720 	 *
5721 	 *  Usually there is no need to know which registers are mapped to
5722 	 *  local variables.  Registers may be allocated to variable in any
5723 	 *  way (even including gaps).  However, a register-variable mapping
5724 	 *  must be the same for the duration of the function execution and
5725 	 *  the register cannot be used for anything else.
5726 	 *
5727 	 *  When looking up variables by name, the '_Varmap' map is used.
5728 	 *  When an activation closes, registers mapped to arguments are
5729 	 *  copied into the environment record based on the same map.  The
5730 	 *  reverse map (from register to variable) is not currently needed
5731 	 *  at run time, except for debugging, so it is not maintained.
5732 	 */
5733 
5734 	duk_uint16_t nregs;                /* regs to allocate */
5735 	duk_uint16_t nargs;                /* number of arguments allocated to regs */
5736 
5737 	/*
5738 	 *  Additional control information is placed into the object itself
5739 	 *  as internal properties to avoid unnecessary fields for the
5740 	 *  majority of functions.  The compiler tries to omit internal
5741 	 *  control fields when possible.
5742 	 *
5743 	 *  Function templates:
5744 	 *
5745 	 *    {
5746 	 *      name: "func",    // declaration, named function expressions
5747 	 *      fileName: <debug info for creating nice errors>
5748 	 *      _Varmap: { "arg1": 0, "arg2": 1, "varname": 2 },
5749 	 *      _Formals: [ "arg1", "arg2" ],
5750 	 *      _Source: "function func(arg1, arg2) { ... }",
5751 	 *      _Pc2line: <debug info for pc-to-line mapping>,
5752 	 *    }
5753 	 *
5754 	 *  Function instances:
5755 	 *
5756 	 *    {
5757 	 *      length: 2,
5758 	 *      prototype: { constructor: <func> },
5759 	 *      caller: <thrower>,
5760 	 *      arguments: <thrower>,
5761 	 *      name: "func",    // declaration, named function expressions
5762 	 *      fileName: <debug info for creating nice errors>
5763 	 *      _Varmap: { "arg1": 0, "arg2": 1, "varname": 2 },
5764 	 *      _Formals: [ "arg1", "arg2" ],
5765 	 *      _Source: "function func(arg1, arg2) { ... }",
5766 	 *      _Pc2line: <debug info for pc-to-line mapping>,
5767 	 *      _Varenv: <variable environment of closure>,
5768 	 *      _Lexenv: <lexical environment of closure (if differs from _Varenv)>
5769 	 *    }
5770 	 *
5771 	 *  More detailed description of these properties can be found
5772 	 *  in the documentation.
5773 	 */
5774 
5775 #if defined(DUK_USE_DEBUGGER_SUPPORT)
5776 	/* Line number range for function.  Needed during debugging to
5777 	 * determine active breakpoints.
5778 	 */
5779 	duk_uint32_t start_line;
5780 	duk_uint32_t end_line;
5781 #endif
5782 };
5783 
5784 #endif  /* DUK_HCOMPILEDFUNCTION_H_INCLUDED */
5785 /*
5786  *  Heap native function representation.
5787  */
5788 
5789 #ifndef DUK_HNATIVEFUNCTION_H_INCLUDED
5790 #define DUK_HNATIVEFUNCTION_H_INCLUDED
5791 
5792 #define DUK_HNATIVEFUNCTION_NARGS_VARARGS  ((duk_int16_t) -1)
5793 #define DUK_HNATIVEFUNCTION_NARGS_MAX      ((duk_int16_t) 0x7fff)
5794 
5795 struct duk_hnativefunction {
5796 	/* shared object part */
5797 	duk_hobject obj;
5798 
5799 	duk_c_function func;
5800 	duk_int16_t nargs;
5801 	duk_int16_t magic;
5802 
5803 	/* The 'magic' field allows an opaque 16-bit field to be accessed by the
5804 	 * Duktape/C function.  This allows, for instance, the same native function
5805 	 * to be used for a set of very similar functions, with the 'magic' field
5806 	 * providing the necessary non-argument flags / values to guide the behavior
5807 	 * of the native function.  The value is signed on purpose: it is easier to
5808 	 * convert a signed value to unsigned (simply AND with 0xffff) than vice
5809 	 * versa.
5810 	 *
5811 	 * Note: cannot place nargs/magic into the heaphdr flags, because
5812 	 * duk_hobject takes almost all flags already (and needs the spare).
5813 	 */
5814 };
5815 
5816 #endif  /* DUK_HNATIVEFUNCTION_H_INCLUDED */
5817 /*
5818  *  Heap Buffer object representation.  Used for all Buffer variants.
5819  */
5820 
5821 #ifndef DUK_HBUFFEROBJECT_H_INCLUDED
5822 #define DUK_HBUFFEROBJECT_H_INCLUDED
5823 
5824 /* All element accessors are host endian now (driven by TypedArray spec). */
5825 #define DUK_HBUFFEROBJECT_ELEM_UINT8           0
5826 #define DUK_HBUFFEROBJECT_ELEM_UINT8CLAMPED    1
5827 #define DUK_HBUFFEROBJECT_ELEM_INT8            2
5828 #define DUK_HBUFFEROBJECT_ELEM_UINT16          3
5829 #define DUK_HBUFFEROBJECT_ELEM_INT16           4
5830 #define DUK_HBUFFEROBJECT_ELEM_UINT32          5
5831 #define DUK_HBUFFEROBJECT_ELEM_INT32           6
5832 #define DUK_HBUFFEROBJECT_ELEM_FLOAT32         7
5833 #define DUK_HBUFFEROBJECT_ELEM_FLOAT64         8
5834 #define DUK_HBUFFEROBJECT_ELEM_MAX             8
5835 
5836 #define DUK_ASSERT_HBUFFEROBJECT_VALID(h) do { \
5837 		DUK_ASSERT((h) != NULL); \
5838 		DUK_ASSERT((h)->shift <= 3); \
5839 		DUK_ASSERT((h)->elem_type <= DUK_HBUFFEROBJECT_ELEM_MAX); \
5840 		DUK_ASSERT(((h)->shift == 0 && (h)->elem_type == DUK_HBUFFEROBJECT_ELEM_UINT8) || \
5841 		           ((h)->shift == 0 && (h)->elem_type == DUK_HBUFFEROBJECT_ELEM_UINT8CLAMPED) || \
5842 		           ((h)->shift == 0 && (h)->elem_type == DUK_HBUFFEROBJECT_ELEM_INT8) || \
5843 		           ((h)->shift == 1 && (h)->elem_type == DUK_HBUFFEROBJECT_ELEM_UINT16) || \
5844 		           ((h)->shift == 1 && (h)->elem_type == DUK_HBUFFEROBJECT_ELEM_INT16) || \
5845 		           ((h)->shift == 2 && (h)->elem_type == DUK_HBUFFEROBJECT_ELEM_UINT32) || \
5846 		           ((h)->shift == 2 && (h)->elem_type == DUK_HBUFFEROBJECT_ELEM_INT32) || \
5847 		           ((h)->shift == 2 && (h)->elem_type == DUK_HBUFFEROBJECT_ELEM_FLOAT32) || \
5848 		           ((h)->shift == 3 && (h)->elem_type == DUK_HBUFFEROBJECT_ELEM_FLOAT64)); \
5849 		DUK_ASSERT((h)->is_view == 0 || (h)->is_view == 1); \
5850 		DUK_ASSERT(DUK_HOBJECT_IS_BUFFEROBJECT((duk_hobject *) (h))); \
5851 		if ((h)->buf == NULL) { \
5852 			DUK_ASSERT((h)->offset == 0); \
5853 			DUK_ASSERT((h)->length == 0); \
5854 		} else { \
5855 			/* No assertions for offset or length; in particular, \
5856 			 * it's OK for length to be longer than underlying \
5857 			 * buffer.  Just ensure they don't wrap when added. \
5858 			 */ \
5859 			DUK_ASSERT((h)->offset + (h)->length >= (h)->offset); \
5860 		} \
5861 	} while (0)
5862 
5863 /* Get the current data pointer (caller must ensure buf != NULL) as a
5864  * duk_uint8_t ptr.
5865  */
5866 #define DUK_HBUFFEROBJECT_GET_SLICE_BASE(heap,h) \
5867 	(DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
5868 	(((duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR((heap), (h)->buf)) + (h)->offset))
5869 
5870 /* True if slice is full, i.e. offset is zero and length covers the entire
5871  * buffer.  This status may change independently of the duk_hbufferobject if
5872  * the underlying buffer is dynamic and changes without the hbufferobject
5873  * being changed.
5874  */
5875 #define DUK_HBUFFEROBJECT_FULL_SLICE(h) \
5876 	(DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
5877 	((h)->offset == 0 && (h)->length == DUK_HBUFFER_GET_SIZE((h)->buf)))
5878 
5879 /* Validate that the whole slice [0,length[ is contained in the underlying
5880  * buffer.  Caller must ensure 'buf' != NULL.
5881  */
5882 #define DUK_HBUFFEROBJECT_VALID_SLICE(h) \
5883 	(DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
5884 	((h)->offset + (h)->length <= DUK_HBUFFER_GET_SIZE((h)->buf)))
5885 
5886 /* Validate byte read/write for virtual 'offset', i.e. check that the
5887  * offset, taking into account h->offset, is within the underlying
5888  * buffer size.  This is a safety check which is needed to ensure
5889  * that even a misconfigured duk_hbufferobject never causes memory
5890  * unsafe behavior (e.g. if an underlying dynamic buffer changes
5891  * after being setup).  Caller must ensure 'buf' != NULL.
5892  */
5893 #define DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_INCL(h,off) \
5894 	(DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
5895 	((h)->offset + (off) < DUK_HBUFFER_GET_SIZE((h)->buf)))
5896 
5897 #define DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_EXCL(h,off) \
5898 	(DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
5899 	((h)->offset + (off) <= DUK_HBUFFER_GET_SIZE((h)->buf)))
5900 
5901 /* Clamp an input byte length (already assumed to be within the nominal
5902  * duk_hbufferobject 'length') to the current dynamic buffer limits to
5903  * yield a byte length limit that's safe for memory accesses.  This value
5904  * can be invalidated by any side effect because it may trigger a user
5905  * callback that resizes the underlying buffer.
5906  */
5907 #define DUK_HBUFFEROBJECT_CLAMP_BYTELENGTH(h,len) \
5908 	(DUK_ASSERT_EXPR((h) != NULL), \
5909 	duk_hbufferobject_clamp_bytelength((h), (len)))
5910 
5911 struct duk_hbufferobject {
5912 	/* Shared object part. */
5913 	duk_hobject obj;
5914 
5915 	/* Underlying buffer (refcounted), may be NULL. */
5916 	duk_hbuffer *buf;
5917 
5918 	/* Slice and accessor information.
5919 	 *
5920 	 * Because the underlying buffer may be dynamic, these may be
5921 	 * invalidated by the buffer being modified so that both offset
5922 	 * and length should be validated before every access.  Behavior
5923 	 * when the underlying buffer has changed doesn't need to be clean:
5924 	 * virtual 'length' doesn't need to be affected, reads can return
5925 	 * zero/NaN, and writes can be ignored.
5926 	 *
5927 	 * Note that a data pointer cannot be precomputed because 'buf' may
5928 	 * be dynamic and its pointer unstable.
5929 	 */
5930 
5931 	duk_uint_t offset;       /* byte offset to buf */
5932 	duk_uint_t length;       /* byte index limit for element access, exclusive */
5933 	duk_uint8_t shift;       /* element size shift:
5934 	                          *   0 = u8/i8
5935 	                          *   1 = u16/i16
5936 	                          *   2 = u32/i32/float
5937 	                          *   3 = double
5938 	                          */
5939 	duk_uint8_t elem_type;   /* element type */
5940 	duk_uint8_t is_view;
5941 };
5942 
5943 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
5944 DUK_INTERNAL_DECL duk_uint_t duk_hbufferobject_clamp_bytelength(duk_hbufferobject *h_bufobj, duk_uint_t len);
5945 #endif
5946 DUK_INTERNAL_DECL void duk_hbufferobject_push_validated_read(duk_context *ctx, duk_hbufferobject *h_bufobj, duk_uint8_t *p, duk_small_uint_t elem_size);
5947 DUK_INTERNAL_DECL void duk_hbufferobject_validated_write(duk_context *ctx, duk_hbufferobject *h_bufobj, duk_uint8_t *p, duk_small_uint_t elem_size);
5948 
5949 #endif  /* DUK_HBUFFEROBJECT_H_INCLUDED */
5950 /*
5951  *  Heap thread object representation.
5952  *
5953  *  duk_hthread is also the 'context' (duk_context) for exposed APIs
5954  *  which mostly operate on the topmost frame of the value stack.
5955  */
5956 
5957 #ifndef DUK_HTHREAD_H_INCLUDED
5958 #define DUK_HTHREAD_H_INCLUDED
5959 
5960 /*
5961  *  Stack constants
5962  */
5963 
5964 #define DUK_VALSTACK_GROW_STEP          128     /* roughly 1 kiB */
5965 #define DUK_VALSTACK_SHRINK_THRESHOLD   256     /* roughly 2 kiB */
5966 #define DUK_VALSTACK_SHRINK_SPARE       64      /* roughly 0.5 kiB */
5967 #define DUK_VALSTACK_INITIAL_SIZE       128     /* roughly 1.0 kiB -> but rounds up to DUK_VALSTACK_GROW_STEP in practice */
5968 #define DUK_VALSTACK_INTERNAL_EXTRA     64      /* internal extra elements assumed on function entry,
5969                                                  * always added to user-defined 'extra' for e.g. the
5970                                                  * duk_check_stack() call.
5971                                                  */
5972 #define DUK_VALSTACK_API_ENTRY_MINIMUM  DUK_API_ENTRY_STACK
5973                                                 /* number of elements guaranteed to be user accessible
5974                                                  * (in addition to call arguments) on Duktape/C function entry.
5975                                                  */
5976 
5977 /* Note: DUK_VALSTACK_INITIAL_SIZE must be >= DUK_VALSTACK_API_ENTRY_MINIMUM
5978  * + DUK_VALSTACK_INTERNAL_EXTRA so that the initial stack conforms to spare
5979  * requirements.
5980  */
5981 
5982 #define DUK_VALSTACK_DEFAULT_MAX        1000000L
5983 
5984 #define DUK_CALLSTACK_GROW_STEP         8       /* roughly 256 bytes */
5985 #define DUK_CALLSTACK_SHRINK_THRESHOLD  16      /* roughly 512 bytes */
5986 #define DUK_CALLSTACK_SHRINK_SPARE      8       /* roughly 256 bytes */
5987 #define DUK_CALLSTACK_INITIAL_SIZE      8
5988 #define DUK_CALLSTACK_DEFAULT_MAX       10000L
5989 
5990 #define DUK_CATCHSTACK_GROW_STEP         4      /* roughly 64 bytes */
5991 #define DUK_CATCHSTACK_SHRINK_THRESHOLD  8      /* roughly 128 bytes */
5992 #define DUK_CATCHSTACK_SHRINK_SPARE      4      /* roughly 64 bytes */
5993 #define DUK_CATCHSTACK_INITIAL_SIZE      4
5994 #define DUK_CATCHSTACK_DEFAULT_MAX       10000L
5995 
5996 /*
5997  *  Activation defines
5998  */
5999 
6000 #define DUK_ACT_FLAG_STRICT             (1 << 0)  /* function executes in strict mode */
6001 #define DUK_ACT_FLAG_TAILCALLED         (1 << 1)  /* activation has tail called one or more times */
6002 #define DUK_ACT_FLAG_CONSTRUCT          (1 << 2)  /* function executes as a constructor (called via "new") */
6003 #define DUK_ACT_FLAG_PREVENT_YIELD      (1 << 3)  /* activation prevents yield (native call or "new") */
6004 #define DUK_ACT_FLAG_DIRECT_EVAL        (1 << 4)  /* activation is a direct eval call */
6005 #define DUK_ACT_FLAG_BREAKPOINT_ACTIVE  (1 << 5)  /* activation has active breakpoint(s) */
6006 
6007 #define DUK_ACT_GET_FUNC(act)        ((act)->func)
6008 
6009 /*
6010  *  Flags for __FILE__ / __LINE__ registered into tracedata
6011  */
6012 
6013 #define DUK_TB_FLAG_NOBLAME_FILELINE   (1 << 0)  /* don't report __FILE__ / __LINE__ as fileName/lineNumber */
6014 
6015 /*
6016  *  Catcher defines
6017  */
6018 
6019 /* flags field: LLLLLLFT, L = label (24 bits), F = flags (4 bits), T = type (4 bits) */
6020 #define DUK_CAT_TYPE_MASK            0x0000000fUL
6021 #define DUK_CAT_TYPE_BITS            4
6022 #define DUK_CAT_LABEL_MASK           0xffffff00UL
6023 #define DUK_CAT_LABEL_BITS           24
6024 #define DUK_CAT_LABEL_SHIFT          8
6025 
6026 #define DUK_CAT_FLAG_CATCH_ENABLED          (1 << 4)   /* catch part will catch */
6027 #define DUK_CAT_FLAG_FINALLY_ENABLED        (1 << 5)   /* finally part will catch */
6028 #define DUK_CAT_FLAG_CATCH_BINDING_ENABLED  (1 << 6)   /* request to create catch binding */
6029 #define DUK_CAT_FLAG_LEXENV_ACTIVE          (1 << 7)   /* catch or with binding is currently active */
6030 
6031 #define DUK_CAT_TYPE_UNKNOWN         0
6032 #define DUK_CAT_TYPE_TCF             1
6033 #define DUK_CAT_TYPE_LABEL           2
6034 
6035 #define DUK_CAT_GET_TYPE(c)          ((c)->flags & DUK_CAT_TYPE_MASK)
6036 #define DUK_CAT_GET_LABEL(c)         (((c)->flags & DUK_CAT_LABEL_MASK) >> DUK_CAT_LABEL_SHIFT)
6037 
6038 #define DUK_CAT_HAS_CATCH_ENABLED(c)           ((c)->flags & DUK_CAT_FLAG_CATCH_ENABLED)
6039 #define DUK_CAT_HAS_FINALLY_ENABLED(c)         ((c)->flags & DUK_CAT_FLAG_FINALLY_ENABLED)
6040 #define DUK_CAT_HAS_CATCH_BINDING_ENABLED(c)   ((c)->flags & DUK_CAT_FLAG_CATCH_BINDING_ENABLED)
6041 #define DUK_CAT_HAS_LEXENV_ACTIVE(c)           ((c)->flags & DUK_CAT_FLAG_LEXENV_ACTIVE)
6042 
6043 #define DUK_CAT_SET_CATCH_ENABLED(c)    do { \
6044 		(c)->flags |= DUK_CAT_FLAG_CATCH_ENABLED; \
6045 	} while (0)
6046 #define DUK_CAT_SET_FINALLY_ENABLED(c)  do { \
6047 		(c)->flags |= DUK_CAT_FLAG_FINALLY_ENABLED; \
6048 	} while (0)
6049 #define DUK_CAT_SET_CATCH_BINDING_ENABLED(c)    do { \
6050 		(c)->flags |= DUK_CAT_FLAG_CATCH_BINDING_ENABLED; \
6051 	} while (0)
6052 #define DUK_CAT_SET_LEXENV_ACTIVE(c)    do { \
6053 		(c)->flags |= DUK_CAT_FLAG_LEXENV_ACTIVE; \
6054 	} while (0)
6055 
6056 #define DUK_CAT_CLEAR_CATCH_ENABLED(c)    do { \
6057 		(c)->flags &= ~DUK_CAT_FLAG_CATCH_ENABLED; \
6058 	} while (0)
6059 #define DUK_CAT_CLEAR_FINALLY_ENABLED(c)  do { \
6060 		(c)->flags &= ~DUK_CAT_FLAG_FINALLY_ENABLED; \
6061 	} while (0)
6062 #define DUK_CAT_CLEAR_CATCH_BINDING_ENABLED(c)    do { \
6063 		(c)->flags &= ~DUK_CAT_FLAG_CATCH_BINDING_ENABLED; \
6064 	} while (0)
6065 #define DUK_CAT_CLEAR_LEXENV_ACTIVE(c)    do { \
6066 		(c)->flags &= ~DUK_CAT_FLAG_LEXENV_ACTIVE; \
6067 	} while (0)
6068 
6069 /*
6070  *  Thread defines
6071  */
6072 
6073 #if defined(DUK_USE_ROM_STRINGS)
6074 #define DUK_HTHREAD_GET_STRING(thr,idx) \
6075 	((duk_hstring *) DUK_LOSE_CONST(duk_rom_strings_stridx[(idx)]))
6076 #else  /* DUK_USE_ROM_STRINGS */
6077 #if defined(DUK_USE_HEAPPTR16)
6078 #define DUK_HTHREAD_GET_STRING(thr,idx) \
6079 	((duk_hstring *) DUK_USE_HEAPPTR_DEC16((thr)->heap->heap_udata, (thr)->strs16[(idx)]))
6080 #else
6081 #define DUK_HTHREAD_GET_STRING(thr,idx) \
6082 	((thr)->strs[(idx)])
6083 #endif
6084 #endif  /* DUK_USE_ROM_STRINGS */
6085 
6086 #define DUK_HTHREAD_GET_CURRENT_ACTIVATION(thr)  (&(thr)->callstack[(thr)->callstack_top - 1])
6087 
6088 /* values for the state field */
6089 #define DUK_HTHREAD_STATE_INACTIVE     1   /* thread not currently running */
6090 #define DUK_HTHREAD_STATE_RUNNING      2   /* thread currently running (only one at a time) */
6091 #define DUK_HTHREAD_STATE_RESUMED      3   /* thread resumed another thread (active but not running) */
6092 #define DUK_HTHREAD_STATE_YIELDED      4   /* thread has yielded */
6093 #define DUK_HTHREAD_STATE_TERMINATED   5   /* thread has terminated */
6094 
6095 /* Executor interrupt default interval when nothing else requires a
6096  * smaller value.  The default interval must be small enough to allow
6097  * for reasonable execution timeout checking but large enough to keep
6098  * impact on execution performance low.
6099  */
6100 #if defined(DUK_USE_INTERRUPT_COUNTER)
6101 #define DUK_HTHREAD_INTCTR_DEFAULT     (256L * 1024L)
6102 #endif
6103 
6104 /*
6105  *  Assert context is valid: non-NULL pointer, fields look sane.
6106  *
6107  *  This is used by public API call entrypoints to catch invalid 'ctx' pointers
6108  *  as early as possible; invalid 'ctx' pointers cause very odd and difficult to
6109  *  diagnose behavior so it's worth checking even when the check is not 100%.
6110  */
6111 
6112 #if defined(DUK_USE_PREFER_SIZE)
6113 #define DUK_ASSERT_CTX_VSSIZE(ctx)  /*nop*/
6114 #else
6115 #define DUK_ASSERT_CTX_VSSIZE(ctx) \
6116 	DUK_ASSERT((duk_size_t) (((duk_hthread *) (ctx))->valstack_end - ((duk_hthread *) (ctx))->valstack) == \
6117 		((duk_hthread *) (ctx))->valstack_size)
6118 #endif
6119 #define DUK_ASSERT_CTX_VALID(ctx) do { \
6120 		DUK_ASSERT((ctx) != NULL); \
6121 		DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) (ctx)) == DUK_HTYPE_OBJECT); \
6122 		DUK_ASSERT(DUK_HOBJECT_IS_THREAD((duk_hobject *) (ctx))); \
6123 		DUK_ASSERT(((duk_hthread *) (ctx))->unused1 == 0); \
6124 		DUK_ASSERT(((duk_hthread *) (ctx))->unused2 == 0); \
6125 		DUK_ASSERT(((duk_hthread *) (ctx))->valstack != NULL); \
6126 		DUK_ASSERT(((duk_hthread *) (ctx))->valstack_end >= ((duk_hthread *) (ctx))->valstack); \
6127 		DUK_ASSERT(((duk_hthread *) (ctx))->valstack_top >= ((duk_hthread *) (ctx))->valstack); \
6128 		DUK_ASSERT(((duk_hthread *) (ctx))->valstack_top >= ((duk_hthread *) (ctx))->valstack_bottom); \
6129 		DUK_ASSERT(((duk_hthread *) (ctx))->valstack_end >= ((duk_hthread *) (ctx))->valstack_top); \
6130 		DUK_ASSERT_CTX_VSSIZE((ctx)); \
6131 	} while (0)
6132 
6133 /*
6134  *  Struct defines
6135  */
6136 
6137 /* XXX: for a memory-code tradeoff, remove 'func' and make it's access either a function
6138  * or a macro.  This would make the activation 32 bytes long on 32-bit platforms again.
6139  */
6140 
6141 /* Note: it's nice if size is 2^N (at least for 32-bit platforms). */
6142 struct duk_activation {
6143 	duk_tval tv_func;       /* borrowed: full duk_tval for function being executed; for lightfuncs */
6144 	duk_hobject *func;      /* borrowed: function being executed; for bound function calls, this is the final, real function, NULL for lightfuncs */
6145 	duk_hobject *var_env;   /* current variable environment (may be NULL if delayed) */
6146 	duk_hobject *lex_env;   /* current lexical environment (may be NULL if delayed) */
6147 #ifdef DUK_USE_NONSTD_FUNC_CALLER_PROPERTY
6148 	/* Previous value of 'func' caller, restored when unwound.  Only in use
6149 	 * when 'func' is non-strict.
6150 	 */
6151 	duk_hobject *prev_caller;
6152 #endif
6153 
6154 	duk_instr_t *curr_pc;   /* next instruction to execute (points to 'func' bytecode, stable pointer), NULL for native calls */
6155 #if defined(DUK_USE_DEBUGGER_SUPPORT)
6156 	duk_uint32_t prev_line; /* needed for stepping */
6157 #endif
6158 	duk_small_uint_t flags;
6159 
6160 	/* idx_bottom and idx_retval are only used for book-keeping of
6161 	 * Ecmascript-initiated calls, to allow returning to an Ecmascript
6162 	 * function properly.  They are duk_size_t to match the convention
6163 	 * that value stack sizes are duk_size_t and local frame indices
6164 	 * are duk_idx_t.
6165 	 */
6166 
6167 	/* Bottom of valstack for this activation, used to reset
6168 	 * valstack_bottom on return; index is absolute.  Note:
6169 	 * idx_top not needed because top is set to 'nregs' always
6170 	 * when returning to an Ecmascript activation.
6171 	 */
6172 	duk_size_t idx_bottom;
6173 
6174 	/* Return value when returning to this activation (points to caller
6175 	 * reg, not callee reg); index is absolute (only set if activation is
6176 	 * not topmost).
6177 	 *
6178 	 * Note: idx_bottom is always set, while idx_retval is only applicable
6179 	 * for activations below the topmost one.  Currently idx_retval for
6180 	 * the topmost activation is considered garbage (and it not initialized
6181 	 * on entry or cleared on return; may contain previous or garbage
6182 	 * values).
6183 	 */
6184 	duk_size_t idx_retval;
6185 
6186 	/* Current 'this' binding is the value just below idx_bottom.
6187 	 * Previously, 'this' binding was handled with an index to the
6188 	 * (calling) valstack.  This works for everything except tail
6189 	 * calls, which must not "cumulate" valstack temps.
6190 	 */
6191 };
6192 
6193 /* Note: it's nice if size is 2^N (not 4x4 = 16 bytes on 32 bit) */
6194 struct duk_catcher {
6195 	duk_hstring *h_varname;         /* borrowed reference to catch variable name (or NULL if none) */
6196 	                                /* (reference is valid as long activation exists) */
6197 	duk_instr_t *pc_base;           /* resume execution from pc_base or pc_base+1 (points to 'func' bytecode, stable pointer) */
6198 	duk_size_t callstack_index;     /* callstack index of related activation */
6199 	duk_size_t idx_base;            /* idx_base and idx_base+1 get completion value and type */
6200 	duk_uint32_t flags;             /* type and control flags, label number */
6201 };
6202 
6203 struct duk_hthread {
6204 	/* Shared object part */
6205 	duk_hobject obj;
6206 
6207 	/* Pointer to bytecode executor's 'curr_pc' variable.  Used to copy
6208 	 * the current PC back into the topmost activation when activation
6209 	 * state is about to change (or "syncing" is otherwise needed).  This
6210 	 * is rather awkward but important for performance, see execution.rst.
6211 	 */
6212 	duk_instr_t **ptr_curr_pc;
6213 
6214 	/* Backpointers. */
6215 	duk_heap *heap;
6216 
6217 	/* Current strictness flag: affects API calls. */
6218 	duk_uint8_t strict;
6219 
6220 	/* Thread state. */
6221 	duk_uint8_t state;
6222 	duk_uint8_t unused1;
6223 	duk_uint8_t unused2;
6224 
6225 	/* Sanity limits for stack sizes. */
6226 	duk_size_t valstack_max;
6227 	duk_size_t callstack_max;
6228 	duk_size_t catchstack_max;
6229 
6230 	/* XXX: Valstack, callstack, and catchstack are currently assumed
6231 	 * to have non-NULL pointers.  Relaxing this would not lead to big
6232 	 * benefits (except perhaps for terminated threads).
6233 	 */
6234 
6235 	/* Value stack: these are expressed as pointers for faster stack manipulation.
6236 	 * [valstack,valstack_top[ is GC-reachable, [valstack_top,valstack_end[ is
6237 	 * not GC-reachable but kept initialized as 'undefined'.
6238 	 */
6239 	duk_tval *valstack;                     /* start of valstack allocation */
6240 	duk_tval *valstack_end;                 /* end of valstack allocation (exclusive) */
6241 	duk_tval *valstack_bottom;              /* bottom of current frame */
6242 	duk_tval *valstack_top;                 /* top of current frame (exclusive) */
6243 #if !defined(DUK_USE_PREFER_SIZE)
6244 	duk_size_t valstack_size;               /* cached: valstack_end - valstack (in entries, not bytes) */
6245 #endif
6246 
6247 	/* Call stack.  [0,callstack_top[ is GC reachable. */
6248 	duk_activation *callstack;
6249 	duk_size_t callstack_size;              /* allocation size */
6250 	duk_size_t callstack_top;               /* next to use, highest used is top - 1 */
6251 	duk_size_t callstack_preventcount;      /* number of activation records in callstack preventing a yield */
6252 
6253 	/* Catch stack.  [0,catchstack_top[ is GC reachable. */
6254 	duk_catcher *catchstack;
6255 	duk_size_t catchstack_size;             /* allocation size */
6256 	duk_size_t catchstack_top;              /* next to use, highest used is top - 1 */
6257 
6258 	/* Yield/resume book-keeping. */
6259 	duk_hthread *resumer;                   /* who resumed us (if any) */
6260 
6261 	/* Current compiler state (if any), used for augmenting SyntaxErrors. */
6262 	duk_compiler_ctx *compile_ctx;
6263 
6264 #if defined(DUK_USE_INTERRUPT_COUNTER)
6265 	/* Interrupt counter for triggering a slow path check for execution
6266 	 * timeout, debugger interaction such as breakpoints, etc.  The value
6267 	 * is valid for the current running thread, and both the init and
6268 	 * counter values are copied whenever a thread switch occurs.  It's
6269 	 * important for the counter to be conveniently accessible for the
6270 	 * bytecode executor inner loop for performance reasons.
6271 	 */
6272 	duk_int_t interrupt_counter;    /* countdown state */
6273 	duk_int_t interrupt_init;       /* start value for current countdown */
6274 #endif
6275 
6276 	/* Builtin-objects; may or may not be shared with other threads,
6277 	 * threads existing in different "compartments" will have different
6278 	 * built-ins.  Must be stored on a per-thread basis because there
6279 	 * is no intermediate structure for a thread group / compartment.
6280 	 * This takes quite a lot of space, currently 43x4 = 172 bytes on
6281 	 * 32-bit platforms.
6282 	 *
6283 	 * In some cases the builtins array could be ROM based, but it's
6284 	 * sometimes edited (e.g. for sandboxing) so it's better to keep
6285 	 * this array in RAM.
6286 	 */
6287 	duk_hobject *builtins[DUK_NUM_BUILTINS];
6288 
6289 	/* Convenience copies from heap/vm for faster access. */
6290 #if defined(DUK_USE_ROM_STRINGS)
6291 	/* No field needed when strings are in ROM. */
6292 #else
6293 #if defined(DUK_USE_HEAPPTR16)
6294 	duk_uint16_t *strs16;
6295 #else
6296 	duk_hstring **strs;
6297 #endif
6298 #endif
6299 };
6300 
6301 /*
6302  *  Prototypes
6303  */
6304 
6305 DUK_INTERNAL_DECL void duk_hthread_copy_builtin_objects(duk_hthread *thr_from, duk_hthread *thr_to);
6306 DUK_INTERNAL_DECL void duk_hthread_create_builtin_objects(duk_hthread *thr);
6307 DUK_INTERNAL_DECL duk_bool_t duk_hthread_init_stacks(duk_heap *heap, duk_hthread *thr);
6308 DUK_INTERNAL_DECL void duk_hthread_terminate(duk_hthread *thr);
6309 
6310 DUK_INTERNAL_DECL void duk_hthread_callstack_grow(duk_hthread *thr);
6311 DUK_INTERNAL_DECL void duk_hthread_callstack_shrink_check(duk_hthread *thr);
6312 DUK_INTERNAL_DECL void duk_hthread_callstack_unwind(duk_hthread *thr, duk_size_t new_top);
6313 DUK_INTERNAL_DECL void duk_hthread_catchstack_grow(duk_hthread *thr);
6314 DUK_INTERNAL_DECL void duk_hthread_catchstack_shrink_check(duk_hthread *thr);
6315 DUK_INTERNAL_DECL void duk_hthread_catchstack_unwind(duk_hthread *thr, duk_size_t new_top);
6316 
6317 DUK_INTERNAL_DECL duk_activation *duk_hthread_get_current_activation(duk_hthread *thr);
6318 DUK_INTERNAL_DECL void *duk_hthread_get_valstack_ptr(duk_heap *heap, void *ud);  /* indirect allocs */
6319 DUK_INTERNAL_DECL void *duk_hthread_get_callstack_ptr(duk_heap *heap, void *ud);  /* indirect allocs */
6320 DUK_INTERNAL_DECL void *duk_hthread_get_catchstack_ptr(duk_heap *heap, void *ud);  /* indirect allocs */
6321 
6322 #if defined(DUK_USE_DEBUGGER_SUPPORT)
6323 DUK_INTERNAL_DECL duk_uint_fast32_t duk_hthread_get_act_curr_pc(duk_hthread *thr, duk_activation *act);
6324 #endif
6325 DUK_INTERNAL_DECL duk_uint_fast32_t duk_hthread_get_act_prev_pc(duk_hthread *thr, duk_activation *act);
6326 DUK_INTERNAL_DECL void duk_hthread_sync_currpc(duk_hthread *thr);
6327 DUK_INTERNAL_DECL void duk_hthread_sync_and_null_currpc(duk_hthread *thr);
6328 
6329 #endif  /* DUK_HTHREAD_H_INCLUDED */
6330 /*
6331  *  Heap buffer representation.
6332  *
6333  *  Heap allocated user data buffer which is either:
6334  *
6335  *    1. A fixed size buffer (data follows header statically)
6336  *    2. A dynamic size buffer (data pointer follows header)
6337  *
6338  *  The data pointer for a variable size buffer of zero size may be NULL.
6339  */
6340 
6341 #ifndef DUK_HBUFFER_H_INCLUDED
6342 #define DUK_HBUFFER_H_INCLUDED
6343 
6344 /*
6345  *  Flags
6346  *
6347  *  Fixed buffer:     0
6348  *  Dynamic buffer:   DUK_HBUFFER_FLAG_DYNAMIC
6349  *  External buffer:  DUK_HBUFFER_FLAG_DYNAMIC | DUK_HBUFFER_FLAG_EXTERNAL
6350  */
6351 
6352 #define DUK_HBUFFER_FLAG_DYNAMIC                  DUK_HEAPHDR_USER_FLAG(0)    /* buffer is behind a pointer, dynamic or external */
6353 #define DUK_HBUFFER_FLAG_EXTERNAL                 DUK_HEAPHDR_USER_FLAG(1)    /* buffer pointer is to an externally allocated buffer */
6354 
6355 #define DUK_HBUFFER_HAS_DYNAMIC(x)                DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_DYNAMIC)
6356 #define DUK_HBUFFER_HAS_EXTERNAL(x)               DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_EXTERNAL)
6357 
6358 #define DUK_HBUFFER_SET_DYNAMIC(x)                DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_DYNAMIC)
6359 #define DUK_HBUFFER_SET_EXTERNAL(x)               DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_EXTERNAL)
6360 
6361 #define DUK_HBUFFER_CLEAR_DYNAMIC(x)              DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_DYNAMIC)
6362 #define DUK_HBUFFER_CLEAR_EXTERNAL(x)             DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_EXTERNAL)
6363 
6364 /*
6365  *  Misc defines
6366  */
6367 
6368 /* Impose a maximum buffer length for now.  Restricted artificially to
6369  * ensure resize computations or adding a heap header length won't
6370  * overflow size_t and that a signed duk_int_t can hold a buffer
6371  * length.  The limit should be synchronized with DUK_HSTRING_MAX_BYTELEN.
6372  */
6373 
6374 #if defined(DUK_USE_BUFLEN16)
6375 #define DUK_HBUFFER_MAX_BYTELEN                   (0x0000ffffUL)
6376 #else
6377 /* Intentionally not 0x7fffffffUL; at least JSON code expects that
6378  * 2*len + 2 fits in 32 bits.
6379  */
6380 #define DUK_HBUFFER_MAX_BYTELEN                   (0x7ffffffeUL)
6381 #endif
6382 
6383 /*
6384  *  Field access
6385  */
6386 
6387 /* Get/set the current user visible size, without accounting for a dynamic
6388  * buffer's "spare" (= usable size).
6389  */
6390 #if defined(DUK_USE_BUFLEN16)
6391 /* size stored in duk_heaphdr unused flag bits */
6392 #define DUK_HBUFFER_GET_SIZE(x)     ((x)->hdr.h_flags >> 16)
6393 #define DUK_HBUFFER_SET_SIZE(x,v)   do { \
6394 		duk_size_t duk__v; \
6395 		duk__v = (v); \
6396 		DUK_ASSERT(duk__v <= 0xffffUL); \
6397 		(x)->hdr.h_flags = ((x)->hdr.h_flags & 0x0000ffffUL) | (((duk_uint32_t) duk__v) << 16); \
6398 	} while (0)
6399 #define DUK_HBUFFER_ADD_SIZE(x,dv)  do { \
6400 		(x)->hdr.h_flags += ((dv) << 16); \
6401 	} while (0)
6402 #define DUK_HBUFFER_SUB_SIZE(x,dv)  do { \
6403 		(x)->hdr.h_flags -= ((dv) << 16); \
6404 	} while (0)
6405 #else
6406 #define DUK_HBUFFER_GET_SIZE(x)     (((duk_hbuffer *) (x))->size)
6407 #define DUK_HBUFFER_SET_SIZE(x,v)   do { \
6408 		((duk_hbuffer *) (x))->size = (v); \
6409 	} while (0)
6410 #define DUK_HBUFFER_ADD_SIZE(x,dv)  do { \
6411 		(x)->size += (dv); \
6412 	} while (0)
6413 #define DUK_HBUFFER_SUB_SIZE(x,dv)  do { \
6414 		(x)->size -= (dv); \
6415 	} while (0)
6416 #endif
6417 
6418 #define DUK_HBUFFER_FIXED_GET_SIZE(x)       DUK_HBUFFER_GET_SIZE((duk_hbuffer *) (x))
6419 #define DUK_HBUFFER_FIXED_SET_SIZE(x,v)     DUK_HBUFFER_SET_SIZE((duk_hbuffer *) (x))
6420 
6421 #define DUK_HBUFFER_DYNAMIC_GET_SIZE(x)     DUK_HBUFFER_GET_SIZE((duk_hbuffer *) (x))
6422 #define DUK_HBUFFER_DYNAMIC_SET_SIZE(x,v)   DUK_HBUFFER_SET_SIZE((duk_hbuffer *) (x), (v))
6423 #define DUK_HBUFFER_DYNAMIC_ADD_SIZE(x,dv)  DUK_HBUFFER_ADD_SIZE((duk_hbuffer *) (x), (dv))
6424 #define DUK_HBUFFER_DYNAMIC_SUB_SIZE(x,dv)  DUK_HBUFFER_SUB_SIZE((duk_hbuffer *) (x), (dv))
6425 
6426 #define DUK_HBUFFER_EXTERNAL_GET_SIZE(x)    DUK_HBUFFER_GET_SIZE((duk_hbuffer *) (x))
6427 #define DUK_HBUFFER_EXTERNAL_SET_SIZE(x,v)  DUK_HBUFFER_SET_SIZE((duk_hbuffer *) (x), (v))
6428 
6429 #define DUK_HBUFFER_FIXED_GET_DATA_PTR(heap,x)    ((duk_uint8_t *) (((duk_hbuffer_fixed *) (x)) + 1))
6430 
6431 #if defined(DUK_USE_HEAPPTR16)
6432 #define DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap,x) \
6433 	((void *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, ((duk_heaphdr *) (x))->h_extra16))
6434 #define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap,x,v)     do { \
6435 		((duk_heaphdr *) (x))->h_extra16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
6436 	} while (0)
6437 #define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR_NULL(heap,x)  do { \
6438 		((duk_heaphdr *) (x))->h_extra16 = 0;  /* assume 0 <=> NULL */ \
6439 	} while (0)
6440 #else
6441 #define DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap,x)       ((x)->curr_alloc)
6442 #define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap,x,v)     do { \
6443 		(x)->curr_alloc = (void *) (v); \
6444 	} while (0)
6445 #define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR_NULL(heap,x)  do { \
6446 		(x)->curr_alloc = (void *) NULL; \
6447 	} while (0)
6448 #endif
6449 
6450 /* No pointer compression because pointer is potentially outside of
6451  * Duktape heap.
6452  */
6453 #if defined(DUK_USE_HEAPPTR16)
6454 #define DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(heap,x) \
6455 	((void *) (x)->curr_alloc)
6456 #define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(heap,x,v)     do { \
6457 		(x)->curr_alloc = (void *) (v); \
6458 	} while (0)
6459 #define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR_NULL(heap,x)  do { \
6460 		(x)->curr_alloc = (void *) NULL; \
6461 	} while (0)
6462 #else
6463 #define DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(heap,x) \
6464 	((void *) (x)->curr_alloc)
6465 #define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(heap,x,v)     do { \
6466 		(x)->curr_alloc = (void *) (v); \
6467 	} while (0)
6468 #define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR_NULL(heap,x)  do { \
6469 		(x)->curr_alloc = (void *) NULL; \
6470 	} while (0)
6471 #endif
6472 
6473 /* Get a pointer to the current buffer contents (matching current allocation
6474  * size).  May be NULL for zero size dynamic/external buffer.
6475  */
6476 #if defined(DUK_USE_HEAPPTR16)
6477 #define DUK_HBUFFER_GET_DATA_PTR(heap,x)  ( \
6478 	DUK_HBUFFER_HAS_DYNAMIC((x)) ? \
6479 		( \
6480 			DUK_HBUFFER_HAS_EXTERNAL((x)) ? \
6481 				DUK_HBUFFER_EXTERNAL_GET_DATA_PTR((heap), (duk_hbuffer_external *) (x)) : \
6482 				DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((heap), (duk_hbuffer_dynamic *) (x)) \
6483 		) : \
6484 		DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), (duk_hbuffer_fixed *) (x)) \
6485 	)
6486 #else
6487 /* Without heap pointer compression duk_hbuffer_dynamic and duk_hbuffer_external
6488  * have the same layout so checking for fixed vs. dynamic (or external) is enough.
6489  */
6490 #define DUK_HBUFFER_GET_DATA_PTR(heap,x)  ( \
6491 	DUK_HBUFFER_HAS_DYNAMIC((x)) ? \
6492 		DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((heap), (duk_hbuffer_dynamic *) (x)) : \
6493 		DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), (duk_hbuffer_fixed *) (x)) \
6494 	)
6495 #endif
6496 
6497 /*
6498  *  Structs
6499  */
6500 
6501 /* Shared prefix for all buffer types. */
6502 struct duk_hbuffer {
6503 	duk_heaphdr hdr;
6504 
6505 	/* It's not strictly necessary to track the current size, but
6506 	 * it is useful for writing robust native code.
6507 	 */
6508 
6509 	/* Current size (not counting a dynamic buffer's "spare"). */
6510 #if defined(DUK_USE_BUFLEN16)
6511 	/* Stored in duk_heaphdr unused flags. */
6512 #else
6513 	duk_size_t size;
6514 #endif
6515 
6516 	/*
6517 	 *  Data following the header depends on the DUK_HBUFFER_FLAG_DYNAMIC
6518 	 *  flag.
6519 	 *
6520 	 *  If the flag is clear (the buffer is a fixed size one), the buffer
6521 	 *  data follows the header directly, consisting of 'size' bytes.
6522 	 *
6523 	 *  If the flag is set, the actual buffer is allocated separately, and
6524 	 *  a few control fields follow the header.  Specifically:
6525 	 *
6526 	 *    - a "void *" pointing to the current allocation
6527 	 *    - a duk_size_t indicating the full allocated size (always >= 'size')
6528 	 *
6529 	 *  If DUK_HBUFFER_FLAG_EXTERNAL is set, the buffer has been allocated
6530 	 *  by user code, so that Duktape won't be able to resize it and won't
6531 	 *  free it.  This allows buffers to point to e.g. an externally
6532 	 *  allocated structure such as a frame buffer.
6533 	 *
6534 	 *  Unlike strings, no terminator byte (NUL) is guaranteed after the
6535 	 *  data.  This would be convenient, but would pad aligned user buffers
6536 	 *  unnecessarily upwards in size.  For instance, if user code requested
6537 	 *  a 64-byte dynamic buffer, 65 bytes would actually be allocated which
6538 	 *  would then potentially round upwards to perhaps 68 or 72 bytes.
6539 	 */
6540 };
6541 
6542 /* Fixed buffer; data follows struct, with proper alignment guaranteed by
6543  * struct size.
6544  */
6545 #if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_MSVC_PRAGMA)
6546 #pragma pack(push, 8)
6547 #endif
6548 struct duk_hbuffer_fixed {
6549 	/* A union is used here as a portable struct size / alignment trick:
6550 	 * by adding a 32-bit or a 64-bit (unused) union member, the size of
6551 	 * the struct is effectively forced to be a multiple of 4 or 8 bytes
6552 	 * (respectively) without increasing the size of the struct unless
6553 	 * necessary.
6554 	 */
6555 	union {
6556 		struct {
6557 			duk_heaphdr hdr;
6558 #if defined(DUK_USE_BUFLEN16)
6559 			/* Stored in duk_heaphdr unused flags. */
6560 #else
6561 			duk_size_t size;
6562 #endif
6563 		} s;
6564 #if (DUK_USE_ALIGN_BY == 4)
6565 		duk_uint32_t dummy_for_align4;
6566 #elif (DUK_USE_ALIGN_BY == 8)
6567 		duk_double_t dummy_for_align8;
6568 #elif (DUK_USE_ALIGN_BY == 1)
6569 		/* no extra padding */
6570 #else
6571 #error invalid DUK_USE_ALIGN_BY
6572 #endif
6573 	} u;
6574 
6575 	/*
6576 	 *  Data follows the struct header.  The struct size is padded by the
6577 	 *  compiler based on the struct members.  This guarantees that the
6578 	 *  buffer data will be aligned-by-4 but not necessarily aligned-by-8.
6579 	 *
6580 	 *  On platforms where alignment does not matter, the struct padding
6581 	 *  could be removed (if there is any).  On platforms where alignment
6582 	 *  by 8 is required, the struct size must be forced to be a multiple
6583 	 *  of 8 by some means.  Without it, some user code may break, and also
6584 	 *  Duktape itself breaks (e.g. the compiler stores duk_tvals in a
6585 	 *  dynamic buffer).
6586 	 */
6587 }
6588 #if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_GCC_ATTR)
6589 __attribute__ ((aligned (8)))
6590 #elif (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_CLANG_ATTR)
6591 __attribute__ ((aligned (8)))
6592 #endif
6593 ;
6594 #if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_MSVC_PRAGMA)
6595 #pragma pack(pop)
6596 #endif
6597 
6598 /* Dynamic buffer with 'curr_alloc' pointing to a dynamic area allocated using
6599  * heap allocation primitives.  Also used for external buffers when low memory
6600  * options are not used.
6601  */
6602 struct duk_hbuffer_dynamic {
6603 	duk_heaphdr hdr;
6604 
6605 #if defined(DUK_USE_BUFLEN16)
6606 	/* Stored in duk_heaphdr unused flags. */
6607 #else
6608 	duk_size_t size;
6609 #endif
6610 
6611 #if defined(DUK_USE_HEAPPTR16)
6612 	/* Stored in duk_heaphdr h_extra16. */
6613 #else
6614 	void *curr_alloc;  /* may be NULL if alloc_size == 0 */
6615 #endif
6616 
6617 	/*
6618 	 *  Allocation size for 'curr_alloc' is alloc_size.  There is no
6619 	 *  automatic NUL terminator for buffers (see above for rationale).
6620 	 *
6621 	 *  'curr_alloc' is explicitly allocated with heap allocation
6622 	 *  primitives and will thus always have alignment suitable for
6623 	 *  e.g. duk_tval and an IEEE double.
6624 	 */
6625 };
6626 
6627 /* External buffer with 'curr_alloc' managed by user code and pointing to an
6628  * arbitrary address.  When heap pointer compression is not used, this struct
6629  * has the same layout as duk_hbuffer_dynamic.
6630  */
6631 struct duk_hbuffer_external {
6632 	duk_heaphdr hdr;
6633 
6634 #if defined(DUK_USE_BUFLEN16)
6635 	/* Stored in duk_heaphdr unused flags. */
6636 #else
6637 	duk_size_t size;
6638 #endif
6639 
6640 	/* Cannot be compressed as a heap pointer because may point to
6641 	 * an arbitrary address.
6642 	 */
6643 	void *curr_alloc;  /* may be NULL if alloc_size == 0 */
6644 };
6645 
6646 /*
6647  *  Prototypes
6648  */
6649 
6650 DUK_INTERNAL_DECL duk_hbuffer *duk_hbuffer_alloc(duk_heap *heap, duk_size_t size, duk_small_uint_t flags, void **out_bufdata);
6651 DUK_INTERNAL_DECL void *duk_hbuffer_get_dynalloc_ptr(duk_heap *heap, void *ud);  /* indirect allocs */
6652 
6653 /* dynamic buffer ops */
6654 DUK_INTERNAL_DECL void duk_hbuffer_resize(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t new_size);
6655 DUK_INTERNAL_DECL void duk_hbuffer_reset(duk_hthread *thr, duk_hbuffer_dynamic *buf);
6656 
6657 #endif  /* DUK_HBUFFER_H_INCLUDED */
6658 /*
6659  *  Heap structure.
6660  *
6661  *  Heap contains allocated heap objects, interned strings, and built-in
6662  *  strings for one or more threads.
6663  */
6664 
6665 #ifndef DUK_HEAP_H_INCLUDED
6666 #define DUK_HEAP_H_INCLUDED
6667 
6668 /* alloc function typedefs in duktape.h */
6669 
6670 /*
6671  *  Heap flags
6672  */
6673 
6674 #define DUK_HEAP_FLAG_MARKANDSWEEP_RUNNING                     (1 << 0)  /* mark-and-sweep is currently running */
6675 #define DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED            (1 << 1)  /* mark-and-sweep marking reached a recursion limit and must use multi-pass marking */
6676 #define DUK_HEAP_FLAG_REFZERO_FREE_RUNNING                     (1 << 2)  /* refcount code is processing refzero list */
6677 #define DUK_HEAP_FLAG_ERRHANDLER_RUNNING                       (1 << 3)  /* an error handler (user callback to augment/replace error) is running */
6678 #define DUK_HEAP_FLAG_INTERRUPT_RUNNING                        (1 << 4)  /* executor interrupt running (used to avoid nested interrupts) */
6679 #define DUK_HEAP_FLAG_FINALIZER_NORESCUE                       (1 << 5)  /* heap destruction ongoing, finalizer rescue no longer possible */
6680 
6681 #define DUK__HEAP_HAS_FLAGS(heap,bits)               ((heap)->flags & (bits))
6682 #define DUK__HEAP_SET_FLAGS(heap,bits)  do { \
6683 		(heap)->flags |= (bits); \
6684 	} while (0)
6685 #define DUK__HEAP_CLEAR_FLAGS(heap,bits)  do { \
6686 		(heap)->flags &= ~(bits); \
6687 	} while (0)
6688 
6689 #define DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap)            DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RUNNING)
6690 #define DUK_HEAP_HAS_MARKANDSWEEP_RECLIMIT_REACHED(heap)   DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED)
6691 #define DUK_HEAP_HAS_REFZERO_FREE_RUNNING(heap)            DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_REFZERO_FREE_RUNNING)
6692 #define DUK_HEAP_HAS_ERRHANDLER_RUNNING(heap)              DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_ERRHANDLER_RUNNING)
6693 #define DUK_HEAP_HAS_INTERRUPT_RUNNING(heap)               DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING)
6694 #define DUK_HEAP_HAS_FINALIZER_NORESCUE(heap)              DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE)
6695 
6696 #define DUK_HEAP_SET_MARKANDSWEEP_RUNNING(heap)            DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RUNNING)
6697 #define DUK_HEAP_SET_MARKANDSWEEP_RECLIMIT_REACHED(heap)   DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED)
6698 #define DUK_HEAP_SET_REFZERO_FREE_RUNNING(heap)            DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_REFZERO_FREE_RUNNING)
6699 #define DUK_HEAP_SET_ERRHANDLER_RUNNING(heap)              DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_ERRHANDLER_RUNNING)
6700 #define DUK_HEAP_SET_INTERRUPT_RUNNING(heap)               DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING)
6701 #define DUK_HEAP_SET_FINALIZER_NORESCUE(heap)              DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE)
6702 
6703 #define DUK_HEAP_CLEAR_MARKANDSWEEP_RUNNING(heap)          DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RUNNING)
6704 #define DUK_HEAP_CLEAR_MARKANDSWEEP_RECLIMIT_REACHED(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED)
6705 #define DUK_HEAP_CLEAR_REFZERO_FREE_RUNNING(heap)          DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_REFZERO_FREE_RUNNING)
6706 #define DUK_HEAP_CLEAR_ERRHANDLER_RUNNING(heap)            DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_ERRHANDLER_RUNNING)
6707 #define DUK_HEAP_CLEAR_INTERRUPT_RUNNING(heap)             DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING)
6708 #define DUK_HEAP_CLEAR_FINALIZER_NORESCUE(heap)            DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE)
6709 
6710 /*
6711  *  Longjmp types, also double as identifying continuation type for a rethrow (in 'finally')
6712  */
6713 
6714 #define DUK_LJ_TYPE_UNKNOWN      0    /* unused */
6715 #define DUK_LJ_TYPE_THROW        1    /* value1 -> error object */
6716 #define DUK_LJ_TYPE_YIELD        2    /* value1 -> yield value, iserror -> error / normal */
6717 #define DUK_LJ_TYPE_RESUME       3    /* value1 -> resume value, value2 -> resumee thread, iserror -> error/normal */
6718 #define DUK_LJ_TYPE_BREAK        4    /* value1 -> label number, pseudo-type to indicate a break continuation (for ENDFIN) */
6719 #define DUK_LJ_TYPE_CONTINUE     5    /* value1 -> label number, pseudo-type to indicate a continue continuation (for ENDFIN) */
6720 #define DUK_LJ_TYPE_RETURN       6    /* value1 -> return value, pseudo-type to indicate a return continuation (for ENDFIN) */
6721 #define DUK_LJ_TYPE_NORMAL       7    /* no value, pseudo-type to indicate a normal continuation (for ENDFIN) */
6722 
6723 /*
6724  *  Mark-and-sweep flags
6725  *
6726  *  These are separate from heap level flags now but could be merged.
6727  *  The heap structure only contains a 'base mark-and-sweep flags'
6728  *  field and the GC caller can impose further flags.
6729  */
6730 
6731 #define DUK_MS_FLAG_EMERGENCY                (1 << 0)   /* emergency mode: try extra hard */
6732 #define DUK_MS_FLAG_NO_STRINGTABLE_RESIZE    (1 << 1)   /* don't resize stringtable (but may sweep it); needed during stringtable resize */
6733 #define DUK_MS_FLAG_NO_OBJECT_COMPACTION     (1 << 2)   /* don't compact objects; needed during object property allocation resize */
6734 #define DUK_MS_FLAG_NO_FINALIZERS            (1 << 3)   /* don't run finalizers; leave finalizable objects in finalize_list for next round */
6735 #define DUK_MS_FLAG_SKIP_FINALIZERS          (1 << 4)   /* don't run finalizers; queue finalizable objects back to heap_allocated */
6736 
6737 /*
6738  *  Thread switching
6739  *
6740  *  To switch heap->curr_thread, use the macro below so that interrupt counters
6741  *  get updated correctly.  The macro allows a NULL target thread because that
6742  *  happens e.g. in call handling.
6743  */
6744 
6745 #if defined(DUK_USE_INTERRUPT_COUNTER)
6746 #define DUK_HEAP_SWITCH_THREAD(heap,newthr)  duk_heap_switch_thread((heap), (newthr))
6747 #else
6748 #define DUK_HEAP_SWITCH_THREAD(heap,newthr)  do { \
6749 		(heap)->curr_thread = (newthr); \
6750 	} while (0)
6751 #endif
6752 
6753 /*
6754  *  Other heap related defines
6755  */
6756 
6757 /* Mark-and-sweep interval is relative to combined count of objects and
6758  * strings kept in the heap during the latest mark-and-sweep pass.
6759  * Fixed point .8 multiplier and .0 adder.  Trigger count (interval) is
6760  * decreased by each (re)allocation attempt (regardless of size), and each
6761  * refzero processed object.
6762  *
6763  * 'SKIP' indicates how many (re)allocations to wait until a retry if
6764  * GC is skipped because there is no thread do it with yet (happens
6765  * only during init phases).
6766  */
6767 #if defined(DUK_USE_MARK_AND_SWEEP)
6768 #if defined(DUK_USE_REFERENCE_COUNTING)
6769 #define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_MULT              12800L  /* 50x heap size */
6770 #define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_ADD               1024L
6771 #define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_SKIP              256L
6772 #else
6773 #define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_MULT              256L    /* 1x heap size */
6774 #define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_ADD               1024L
6775 #define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_SKIP              256L
6776 #endif
6777 #endif
6778 
6779 /* Stringcache is used for speeding up char-offset-to-byte-offset
6780  * translations for non-ASCII strings.
6781  */
6782 #define DUK_HEAP_STRCACHE_SIZE                            4
6783 #define DUK_HEAP_STRINGCACHE_NOCACHE_LIMIT                16  /* strings up to the this length are not cached */
6784 
6785 /* helper to insert a (non-string) heap object into heap allocated list */
6786 #define DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap,hdr)     duk_heap_insert_into_heap_allocated((heap),(hdr))
6787 
6788 /*
6789  *  Stringtable
6790  */
6791 
6792 /* initial stringtable size, must be prime and higher than DUK_UTIL_MIN_HASH_PRIME */
6793 #define DUK_STRTAB_INITIAL_SIZE            17
6794 
6795 /* indicates a deleted string; any fixed non-NULL, non-hstring pointer works */
6796 #define DUK_STRTAB_DELETED_MARKER(heap)    ((duk_hstring *) heap)
6797 
6798 /* resizing parameters */
6799 #define DUK_STRTAB_MIN_FREE_DIVISOR        4                /* load factor max 75% */
6800 #define DUK_STRTAB_MIN_USED_DIVISOR        4                /* load factor min 25% */
6801 #define DUK_STRTAB_GROW_ST_SIZE(n)         ((n) + (n))      /* used entries + approx 100% -> reset load to 50% */
6802 
6803 #define DUK_STRTAB_U32_MAX_STRLEN          10               /* 4'294'967'295 */
6804 #define DUK_STRTAB_HIGHEST_32BIT_PRIME     0xfffffffbUL
6805 
6806 /* probe sequence (open addressing) */
6807 #define DUK_STRTAB_HASH_INITIAL(hash,h_size)    ((hash) % (h_size))
6808 #define DUK_STRTAB_HASH_PROBE_STEP(hash)        DUK_UTIL_GET_HASH_PROBE_STEP((hash))
6809 
6810 /* fixed top level hashtable size (separate chaining) */
6811 #define DUK_STRTAB_CHAIN_SIZE              DUK_USE_STRTAB_CHAIN_SIZE
6812 
6813 /*
6814  *  Built-in strings
6815  */
6816 
6817 /* heap string indices are autogenerated in duk_strings.h */
6818 #if defined(DUK_USE_ROM_STRINGS)
6819 #define DUK_HEAP_GET_STRING(heap,idx) \
6820 	((duk_hstring *) DUK_LOSE_CONST(duk_rom_strings_stridx[(idx)]))
6821 #else  /* DUK_USE_ROM_STRINGS */
6822 #if defined(DUK_USE_HEAPPTR16)
6823 #define DUK_HEAP_GET_STRING(heap,idx) \
6824 	((duk_hstring *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (heap)->strs16[(idx)]))
6825 #else
6826 #define DUK_HEAP_GET_STRING(heap,idx) \
6827 	((heap)->strs[(idx)])
6828 #endif
6829 #endif  /* DUK_USE_ROM_STRINGS */
6830 
6831 /*
6832  *  Raw memory calls: relative to heap, but no GC interaction
6833  */
6834 
6835 #define DUK_ALLOC_RAW(heap,size) \
6836 	((heap)->alloc_func((heap)->heap_udata, (size)))
6837 
6838 #define DUK_REALLOC_RAW(heap,ptr,newsize) \
6839 	((heap)->realloc_func((heap)->heap_udata, (void *) (ptr), (newsize)))
6840 
6841 #define DUK_FREE_RAW(heap,ptr) \
6842 	((heap)->free_func((heap)->heap_udata, (void *) (ptr)))
6843 
6844 /*
6845  *  Memory calls: relative to heap, GC interaction, but no error throwing.
6846  *
6847  *  XXX: Currently a mark-and-sweep triggered by memory allocation will run
6848  *  using the heap->heap_thread.  This thread is also used for running
6849  *  mark-and-sweep finalization; this is not ideal because it breaks the
6850  *  isolation between multiple global environments.
6851  *
6852  *  Notes:
6853  *
6854  *    - DUK_FREE() is required to ignore NULL and any other possible return
6855  *      value of a zero-sized alloc/realloc (same as ANSI C free()).
6856  *
6857  *    - There is no DUK_REALLOC_ZEROED because we don't assume to know the
6858  *      old size.  Caller must zero the reallocated memory.
6859  *
6860  *    - DUK_REALLOC_INDIRECT() must be used when a mark-and-sweep triggered
6861  *      by an allocation failure might invalidate the original 'ptr', thus
6862  *      causing a realloc retry to use an invalid pointer.  Example: we're
6863  *      reallocating the value stack and a finalizer resizes the same value
6864  *      stack during mark-and-sweep.  The indirect variant requests for the
6865  *      current location of the pointer being reallocated using a callback
6866  *      right before every realloc attempt; this circuitous approach is used
6867  *      to avoid strict aliasing issues in a more straightforward indirect
6868  *      pointer (void **) approach.  Note: the pointer in the storage
6869  *      location is read but is NOT updated; the caller must do that.
6870  */
6871 
6872 /* callback for indirect reallocs, request for current pointer */
6873 typedef void *(*duk_mem_getptr)(duk_heap *heap, void *ud);
6874 
6875 #define DUK_ALLOC(heap,size)                            duk_heap_mem_alloc((heap), (size))
6876 #define DUK_ALLOC_ZEROED(heap,size)                     duk_heap_mem_alloc_zeroed((heap), (size))
6877 #define DUK_REALLOC(heap,ptr,newsize)                   duk_heap_mem_realloc((heap), (ptr), (newsize))
6878 #define DUK_REALLOC_INDIRECT(heap,cb,ud,newsize)        duk_heap_mem_realloc_indirect((heap), (cb), (ud), (newsize))
6879 #define DUK_FREE(heap,ptr)                              duk_heap_mem_free((heap), (ptr))
6880 
6881 /*
6882  *  Memory constants
6883  */
6884 
6885 #define DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT           5   /* Retry allocation after mark-and-sweep for this
6886                                                               * many times.  A single mark-and-sweep round is
6887                                                               * not guaranteed to free all unreferenced memory
6888                                                               * because of finalization (in fact, ANY number of
6889                                                               * rounds is strictly not enough).
6890                                                               */
6891 
6892 #define DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_EMERGENCY_LIMIT  3  /* Starting from this round, use emergency mode
6893                                                               * for mark-and-sweep.
6894                                                               */
6895 
6896 /*
6897  *  Debugger support
6898  */
6899 
6900 /* Maximum number of breakpoints.  Only breakpoints that are set are
6901  * consulted so increasing this has no performance impact.
6902  */
6903 #define DUK_HEAP_MAX_BREAKPOINTS          16
6904 
6905 /* Opcode interval for a Date-based status/peek rate limit check.  Only
6906  * relevant when debugger is attached.  Requesting a timestamp may be a
6907  * slow operation on some platforms so this shouldn't be too low.  On the
6908  * other hand a high value makes Duktape react to a pause request slowly.
6909  */
6910 #define DUK_HEAP_DBG_RATELIMIT_OPCODES    4000
6911 
6912 /* Milliseconds between status notify and transport peeks. */
6913 #define DUK_HEAP_DBG_RATELIMIT_MILLISECS  200
6914 
6915 /* Step types */
6916 #define DUK_STEP_TYPE_NONE  0
6917 #define DUK_STEP_TYPE_INTO  1
6918 #define DUK_STEP_TYPE_OVER  2
6919 #define DUK_STEP_TYPE_OUT   3
6920 
6921 struct duk_breakpoint {
6922 	duk_hstring *filename;
6923 	duk_uint32_t line;
6924 };
6925 
6926 #if defined(DUK_USE_DEBUGGER_SUPPORT)
6927 #define DUK_HEAP_IS_DEBUGGER_ATTACHED(heap) ((heap)->dbg_read_cb != NULL)
6928 #define DUK_HEAP_CLEAR_STEP_STATE(heap) do { \
6929 		(heap)->dbg_step_type = DUK_STEP_TYPE_NONE; \
6930 		(heap)->dbg_step_thread = NULL; \
6931 		(heap)->dbg_step_csindex = 0; \
6932 		(heap)->dbg_step_startline = 0; \
6933 	} while (0)
6934 #define DUK_HEAP_SET_PAUSED(heap) do { \
6935 		(heap)->dbg_paused = 1; \
6936 		(heap)->dbg_state_dirty = 1; \
6937 		DUK_HEAP_CLEAR_STEP_STATE((heap)); \
6938 	} while (0)
6939 #define DUK_HEAP_CLEAR_PAUSED(heap) do { \
6940 		(heap)->dbg_paused = 0; \
6941 		(heap)->dbg_state_dirty = 1; \
6942 		DUK_HEAP_CLEAR_STEP_STATE((heap)); \
6943 	} while (0)
6944 #define DUK_HEAP_IS_PAUSED(heap) ((heap)->dbg_paused)
6945 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
6946 
6947 /*
6948  *  String cache should ideally be at duk_hthread level, but that would
6949  *  cause string finalization to slow down relative to the number of
6950  *  threads; string finalization must check the string cache for "weak"
6951  *  references to the string being finalized to avoid dead pointers.
6952  *
6953  *  Thus, string caches are now at the heap level now.
6954  */
6955 
6956 struct duk_strcache {
6957 	duk_hstring *h;
6958 	duk_uint32_t bidx;
6959 	duk_uint32_t cidx;
6960 };
6961 
6962 /*
6963  *  Longjmp state, contains the information needed to perform a longjmp.
6964  *  Longjmp related values are written to value1, value2, and iserror.
6965  */
6966 
6967 struct duk_ljstate {
6968 	duk_jmpbuf *jmpbuf_ptr;   /* current setjmp() catchpoint */
6969 	duk_small_uint_t type;    /* longjmp type */
6970 	duk_bool_t iserror;       /* isError flag for yield */
6971 	duk_tval value1;          /* 1st related value (type specific) */
6972 	duk_tval value2;          /* 2nd related value (type specific) */
6973 };
6974 
6975 /*
6976  *  Stringtable entry for fixed size stringtable
6977  */
6978 
6979 struct duk_strtab_entry {
6980 #if defined(DUK_USE_HEAPPTR16)
6981 	/* A 16-bit listlen makes sense with 16-bit heap pointers: there
6982 	 * won't be space for 64k strings anyway.
6983 	 */
6984 	duk_uint16_t listlen;  /* if 0, 'str16' used, if > 0, 'strlist16' used */
6985 	union {
6986 		duk_uint16_t strlist16;
6987 		duk_uint16_t str16;
6988 	} u;
6989 #else
6990 	duk_size_t listlen;  /* if 0, 'str' used, if > 0, 'strlist' used */
6991 	union {
6992 		duk_hstring **strlist;
6993 		duk_hstring *str;
6994 	} u;
6995 #endif
6996 };
6997 
6998 /*
6999  *  Main heap structure
7000  */
7001 
7002 struct duk_heap {
7003 	duk_small_uint_t flags;
7004 
7005 	/* Allocator functions. */
7006 	duk_alloc_function alloc_func;
7007 	duk_realloc_function realloc_func;
7008 	duk_free_function free_func;
7009 
7010 	/* Heap udata, used for allocator functions but also for other heap
7011 	 * level callbacks like pointer compression, etc.
7012 	 */
7013 	void *heap_udata;
7014 
7015 	/* Precomputed pointers when using 16-bit heap pointer packing. */
7016 #if defined(DUK_USE_HEAPPTR16)
7017 	duk_uint16_t heapptr_null16;
7018 	duk_uint16_t heapptr_deleted16;
7019 #endif
7020 
7021 	/* Fatal error handling, called e.g. when a longjmp() is needed but
7022 	 * lj.jmpbuf_ptr is NULL.  fatal_func must never return; it's not
7023 	 * declared as "noreturn" because doing that for typedefs is a bit
7024 	 * challenging portability-wise.
7025 	 */
7026 	duk_fatal_function fatal_func;
7027 
7028 	/* allocated heap objects */
7029 	duk_heaphdr *heap_allocated;
7030 
7031 	/* work list for objects whose refcounts are zero but which have not been
7032 	 * "finalized"; avoids recursive C calls when refcounts go to zero in a
7033 	 * chain of objects.
7034 	 */
7035 #if defined(DUK_USE_REFERENCE_COUNTING)
7036 	duk_heaphdr *refzero_list;
7037 	duk_heaphdr *refzero_list_tail;
7038 #endif
7039 
7040 #if defined(DUK_USE_MARK_AND_SWEEP)
7041 	/* mark-and-sweep control */
7042 #if defined(DUK_USE_VOLUNTARY_GC)
7043 	duk_int_t mark_and_sweep_trigger_counter;
7044 #endif
7045 	duk_int_t mark_and_sweep_recursion_depth;
7046 
7047 	/* mark-and-sweep flags automatically active (used for critical sections) */
7048 	duk_small_uint_t mark_and_sweep_base_flags;
7049 
7050 	/* work list for objects to be finalized (by mark-and-sweep) */
7051 	duk_heaphdr *finalize_list;
7052 #endif
7053 
7054 	/* longjmp state */
7055 	duk_ljstate lj;
7056 
7057 	/* marker for detecting internal "double faults", see duk_error_throw.c */
7058 	duk_bool_t handling_error;
7059 
7060 	/* heap thread, used internally and for finalization */
7061 	duk_hthread *heap_thread;
7062 
7063 	/* current thread */
7064 	duk_hthread *curr_thread;  /* currently running thread */
7065 
7066 	/* heap level "stash" object (e.g., various reachability roots) */
7067 	duk_hobject *heap_object;
7068 
7069 	/* duk_handle_call / duk_handle_safe_call recursion depth limiting */
7070 	duk_int_t call_recursion_depth;
7071 	duk_int_t call_recursion_limit;
7072 
7073 	/* mix-in value for computing string hashes; should be reasonably unpredictable */
7074 	duk_uint32_t hash_seed;
7075 
7076 	/* rnd_state for duk_util_tinyrandom.c */
7077 	duk_uint32_t rnd_state;
7078 
7079 	/* For manual debugging: instruction count based on executor and
7080 	 * interrupt counter book-keeping.  Inspect debug logs to see how
7081 	 * they match up.
7082 	 */
7083 #if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
7084 	duk_int_t inst_count_exec;
7085 	duk_int_t inst_count_interrupt;
7086 #endif
7087 
7088 	/* debugger */
7089 
7090 #if defined(DUK_USE_DEBUGGER_SUPPORT)
7091 	/* callbacks and udata; dbg_read_cb != NULL is used to indicate attached state */
7092 	duk_debug_read_function dbg_read_cb;                /* required, NULL implies detached */
7093 	duk_debug_write_function dbg_write_cb;              /* required */
7094 	duk_debug_peek_function dbg_peek_cb;
7095 	duk_debug_read_flush_function dbg_read_flush_cb;
7096 	duk_debug_write_flush_function dbg_write_flush_cb;
7097 	duk_debug_request_function dbg_request_cb;
7098 	duk_debug_detached_function dbg_detached_cb;
7099 	void *dbg_udata;
7100 
7101 	/* debugger state, only relevant when attached */
7102 	duk_bool_t dbg_processing;              /* currently processing messages or breakpoints: don't enter message processing recursively (e.g. no breakpoints when processing debugger eval) */
7103 	duk_bool_t dbg_paused;                  /* currently paused: talk with debug client until step/resume */
7104 	duk_bool_t dbg_state_dirty;             /* resend state next time executor is about to run */
7105 	duk_bool_t dbg_force_restart;           /* force executor restart to recheck breakpoints; used to handle function returns (see GH-303) */
7106 	duk_bool_t dbg_detaching;               /* debugger detaching; used to avoid calling detach handler recursively */
7107 	duk_small_uint_t dbg_step_type;         /* step type: none, step into, step over, step out */
7108 	duk_hthread *dbg_step_thread;           /* borrowed; NULL if no step state (NULLed in unwind) */
7109 	duk_size_t dbg_step_csindex;            /* callstack index */
7110 	duk_uint32_t dbg_step_startline;        /* starting line number */
7111 	duk_breakpoint dbg_breakpoints[DUK_HEAP_MAX_BREAKPOINTS];  /* breakpoints: [0,breakpoint_count[ gc reachable */
7112 	duk_small_uint_t dbg_breakpoint_count;
7113 	duk_breakpoint *dbg_breakpoints_active[DUK_HEAP_MAX_BREAKPOINTS + 1];  /* currently active breakpoints: NULL term, borrowed pointers */
7114 	/* XXX: make active breakpoints actual copies instead of pointers? */
7115 
7116 	/* These are for rate limiting Status notifications and transport peeking. */
7117 	duk_uint32_t dbg_exec_counter;          /* cumulative opcode execution count (overflows are OK) */
7118 	duk_uint32_t dbg_last_counter;          /* value of dbg_exec_counter when we last did a Date-based check */
7119 	duk_double_t dbg_last_time;             /* time when status/peek was last done (Date-based rate limit) */
7120 
7121 	/* Used to support single-byte stream lookahead. */
7122 	duk_bool_t dbg_have_next_byte;
7123 	duk_uint8_t dbg_next_byte;
7124 #endif
7125 
7126 	/* string intern table (weak refs) */
7127 #if defined(DUK_USE_STRTAB_PROBE)
7128 #if defined(DUK_USE_HEAPPTR16)
7129 	duk_uint16_t *strtable16;
7130 #else
7131 	duk_hstring **strtable;
7132 #endif
7133 	duk_uint32_t st_size;     /* alloc size in elements */
7134 	duk_uint32_t st_used;     /* used elements (includes DELETED) */
7135 #endif
7136 
7137 	/* XXX: static alloc is OK until separate chaining stringtable
7138 	 * resizing is implemented.
7139 	 */
7140 #if defined(DUK_USE_STRTAB_CHAIN)
7141 	duk_strtab_entry strtable[DUK_STRTAB_CHAIN_SIZE];
7142 #endif
7143 
7144 	/* string access cache (codepoint offset -> byte offset) for fast string
7145 	 * character looping; 'weak' reference which needs special handling in GC.
7146 	 */
7147 	duk_strcache strcache[DUK_HEAP_STRCACHE_SIZE];
7148 
7149 	/* built-in strings */
7150 #if defined(DUK_USE_ROM_STRINGS)
7151 	/* No field needed when strings are in ROM. */
7152 #else
7153 #if defined(DUK_USE_HEAPPTR16)
7154 	duk_uint16_t strs16[DUK_HEAP_NUM_STRINGS];
7155 #else
7156 	duk_hstring *strs[DUK_HEAP_NUM_STRINGS];
7157 #endif
7158 #endif
7159 };
7160 
7161 /*
7162  *  Prototypes
7163  */
7164 
7165 DUK_INTERNAL_DECL
7166 duk_heap *duk_heap_alloc(duk_alloc_function alloc_func,
7167                          duk_realloc_function realloc_func,
7168                          duk_free_function free_func,
7169                          void *heap_udata,
7170                          duk_fatal_function fatal_func);
7171 DUK_INTERNAL_DECL void duk_heap_free(duk_heap *heap);
7172 DUK_INTERNAL_DECL void duk_free_hobject_inner(duk_heap *heap, duk_hobject *h);
7173 DUK_INTERNAL_DECL void duk_free_hbuffer_inner(duk_heap *heap, duk_hbuffer *h);
7174 DUK_INTERNAL_DECL void duk_free_hstring_inner(duk_heap *heap, duk_hstring *h);
7175 DUK_INTERNAL_DECL void duk_heap_free_heaphdr_raw(duk_heap *heap, duk_heaphdr *hdr);
7176 
7177 DUK_INTERNAL_DECL void duk_heap_insert_into_heap_allocated(duk_heap *heap, duk_heaphdr *hdr);
7178 #if defined(DUK_USE_DOUBLE_LINKED_HEAP) && defined(DUK_USE_REFERENCE_COUNTING)
7179 DUK_INTERNAL_DECL void duk_heap_remove_any_from_heap_allocated(duk_heap *heap, duk_heaphdr *hdr);
7180 #endif
7181 #if defined(DUK_USE_INTERRUPT_COUNTER)
7182 DUK_INTERNAL_DECL void duk_heap_switch_thread(duk_heap *heap, duk_hthread *new_thr);
7183 #endif
7184 
7185 #if 0  /*unused*/
7186 DUK_INTERNAL_DECL duk_hstring *duk_heap_string_lookup(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen);
7187 #endif
7188 DUK_INTERNAL_DECL duk_hstring *duk_heap_string_intern(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen);
7189 DUK_INTERNAL_DECL duk_hstring *duk_heap_string_intern_checked(duk_hthread *thr, const duk_uint8_t *str, duk_uint32_t len);
7190 #if 0  /*unused*/
7191 DUK_INTERNAL_DECL duk_hstring *duk_heap_string_lookup_u32(duk_heap *heap, duk_uint32_t val);
7192 #endif
7193 DUK_INTERNAL_DECL duk_hstring *duk_heap_string_intern_u32(duk_heap *heap, duk_uint32_t val);
7194 DUK_INTERNAL_DECL duk_hstring *duk_heap_string_intern_u32_checked(duk_hthread *thr, duk_uint32_t val);
7195 #if defined(DUK_USE_REFERENCE_COUNTING)
7196 DUK_INTERNAL_DECL void duk_heap_string_remove(duk_heap *heap, duk_hstring *h);
7197 #endif
7198 #if defined(DUK_USE_MARK_AND_SWEEP) && defined(DUK_USE_MS_STRINGTABLE_RESIZE)
7199 DUK_INTERNAL_DECL void duk_heap_force_strtab_resize(duk_heap *heap);
7200 #endif
7201 DUK_INTERNAL void duk_heap_free_strtab(duk_heap *heap);
7202 #if defined(DUK_USE_DEBUG)
7203 DUK_INTERNAL void duk_heap_dump_strtab(duk_heap *heap);
7204 #endif
7205 
7206 
7207 DUK_INTERNAL_DECL void duk_heap_strcache_string_remove(duk_heap *heap, duk_hstring *h);
7208 DUK_INTERNAL_DECL duk_uint_fast32_t duk_heap_strcache_offset_char2byte(duk_hthread *thr, duk_hstring *h, duk_uint_fast32_t char_offset);
7209 
7210 #if defined(DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS)
7211 DUK_INTERNAL_DECL void *duk_default_alloc_function(void *udata, duk_size_t size);
7212 DUK_INTERNAL_DECL void *duk_default_realloc_function(void *udata, void *ptr, duk_size_t newsize);
7213 DUK_INTERNAL_DECL void duk_default_free_function(void *udata, void *ptr);
7214 #endif
7215 
7216 DUK_INTERNAL_DECL void *duk_heap_mem_alloc(duk_heap *heap, duk_size_t size);
7217 DUK_INTERNAL_DECL void *duk_heap_mem_alloc_zeroed(duk_heap *heap, duk_size_t size);
7218 DUK_INTERNAL_DECL void *duk_heap_mem_realloc(duk_heap *heap, void *ptr, duk_size_t newsize);
7219 DUK_INTERNAL_DECL void *duk_heap_mem_realloc_indirect(duk_heap *heap, duk_mem_getptr cb, void *ud, duk_size_t newsize);
7220 DUK_INTERNAL_DECL void duk_heap_mem_free(duk_heap *heap, void *ptr);
7221 
7222 #ifdef DUK_USE_REFERENCE_COUNTING
7223 #if !defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
7224 DUK_INTERNAL_DECL void duk_tval_incref(duk_tval *tv);
7225 #endif
7226 #if 0  /* unused */
7227 DUK_INTERNAL_DECL void duk_tval_incref_allownull(duk_tval *tv);
7228 #endif
7229 DUK_INTERNAL_DECL void duk_tval_decref(duk_hthread *thr, duk_tval *tv);
7230 #if 0  /* unused */
7231 DUK_INTERNAL_DECL void duk_tval_decref_allownull(duk_hthread *thr, duk_tval *tv);
7232 #endif
7233 #if !defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
7234 DUK_INTERNAL_DECL void duk_heaphdr_incref(duk_heaphdr *h);
7235 #endif
7236 #if 0  /* unused */
7237 DUK_INTERNAL_DECL void duk_heaphdr_incref_allownull(duk_heaphdr *h);
7238 #endif
7239 DUK_INTERNAL_DECL void duk_heaphdr_decref(duk_hthread *thr, duk_heaphdr *h);
7240 DUK_INTERNAL_DECL void duk_heaphdr_decref_allownull(duk_hthread *thr, duk_heaphdr *h);
7241 DUK_INTERNAL_DECL void duk_heaphdr_refzero(duk_hthread *thr, duk_heaphdr *h);
7242 DUK_INTERNAL_DECL void duk_heaphdr_refcount_finalize(duk_hthread *thr, duk_heaphdr *hdr);
7243 #else
7244 /* no refcounting */
7245 #endif
7246 
7247 #if defined(DUK_USE_MARK_AND_SWEEP)
7248 DUK_INTERNAL_DECL duk_bool_t duk_heap_mark_and_sweep(duk_heap *heap, duk_small_uint_t flags);
7249 #endif
7250 
7251 DUK_INTERNAL_DECL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const duk_uint8_t *str, duk_size_t len);
7252 
7253 #endif  /* DUK_HEAP_H_INCLUDED */
7254 #ifndef DUK_DEBUGGER_H_INCLUDED
7255 #define DUK_DEBUGGER_H_INCLUDED
7256 
7257 /* Debugger protocol version is defined in the public API header. */
7258 
7259 /* Initial bytes for markers. */
7260 #define DUK_DBG_IB_EOM                   0x00
7261 #define DUK_DBG_IB_REQUEST               0x01
7262 #define DUK_DBG_IB_REPLY                 0x02
7263 #define DUK_DBG_IB_ERROR                 0x03
7264 #define DUK_DBG_IB_NOTIFY                0x04
7265 
7266 /* Other initial bytes. */
7267 #define DUK_DBG_IB_INT4                  0x10
7268 #define DUK_DBG_IB_STR4                  0x11
7269 #define DUK_DBG_IB_STR2                  0x12
7270 #define DUK_DBG_IB_BUF4                  0x13
7271 #define DUK_DBG_IB_BUF2                  0x14
7272 #define DUK_DBG_IB_UNUSED                0x15
7273 #define DUK_DBG_IB_UNDEFINED             0x16
7274 #define DUK_DBG_IB_NULL                  0x17
7275 #define DUK_DBG_IB_TRUE                  0x18
7276 #define DUK_DBG_IB_FALSE                 0x19
7277 #define DUK_DBG_IB_NUMBER                0x1a
7278 #define DUK_DBG_IB_OBJECT                0x1b
7279 #define DUK_DBG_IB_POINTER               0x1c
7280 #define DUK_DBG_IB_LIGHTFUNC             0x1d
7281 #define DUK_DBG_IB_HEAPPTR               0x1e
7282 /* The short string/integer initial bytes starting from 0x60 don't have
7283  * defines now.
7284  */
7285 
7286 /* Error codes. */
7287 #define DUK_DBG_ERR_UNKNOWN              0x00
7288 #define DUK_DBG_ERR_UNSUPPORTED          0x01
7289 #define DUK_DBG_ERR_TOOMANY              0x02
7290 #define DUK_DBG_ERR_NOTFOUND             0x03
7291 #define DUK_DBG_ERR_APPLICATION          0x04
7292 
7293 /* Commands and notifys initiated by Duktape. */
7294 #define DUK_DBG_CMD_STATUS               0x01
7295 #define DUK_DBG_CMD_PRINT                0x02
7296 #define DUK_DBG_CMD_ALERT                0x03
7297 #define DUK_DBG_CMD_LOG                  0x04
7298 #define DUK_DBG_CMD_THROW                0x05
7299 #define DUK_DBG_CMD_DETACHING            0x06
7300 #define DUK_DBG_CMD_APPNOTIFY            0x07
7301 
7302 /* Commands initiated by debug client. */
7303 #define DUK_DBG_CMD_BASICINFO            0x10
7304 #define DUK_DBG_CMD_TRIGGERSTATUS        0x11
7305 #define DUK_DBG_CMD_PAUSE                0x12
7306 #define DUK_DBG_CMD_RESUME               0x13
7307 #define DUK_DBG_CMD_STEPINTO             0x14
7308 #define DUK_DBG_CMD_STEPOVER             0x15
7309 #define DUK_DBG_CMD_STEPOUT              0x16
7310 #define DUK_DBG_CMD_LISTBREAK            0x17
7311 #define DUK_DBG_CMD_ADDBREAK             0x18
7312 #define DUK_DBG_CMD_DELBREAK             0x19
7313 #define DUK_DBG_CMD_GETVAR               0x1a
7314 #define DUK_DBG_CMD_PUTVAR               0x1b
7315 #define DUK_DBG_CMD_GETCALLSTACK         0x1c
7316 #define DUK_DBG_CMD_GETLOCALS            0x1d
7317 #define DUK_DBG_CMD_EVAL                 0x1e
7318 #define DUK_DBG_CMD_DETACH               0x1f
7319 #define DUK_DBG_CMD_DUMPHEAP             0x20
7320 #define DUK_DBG_CMD_GETBYTECODE          0x21
7321 #define DUK_DBG_CMD_APPREQUEST           0x22
7322 #define DUK_DBG_CMD_GETHEAPOBJINFO       0x23
7323 #define DUK_DBG_CMD_GETOBJPROPDESC       0x24
7324 #define DUK_DBG_CMD_GETOBJPROPDESCRANGE  0x25
7325 
7326 /* The low 8 bits map directly to duk_hobject.h DUK_PROPDESC_FLAG_xxx.
7327  * The remaining flags are specific to the debugger.
7328  */
7329 #define DUK_DBG_PROPFLAG_INTERNAL        (1 << 8)
7330 
7331 #if defined(DUK_USE_DEBUGGER_SUPPORT)
7332 DUK_INTERNAL_DECL void duk_debug_do_detach(duk_heap *heap);
7333 
7334 DUK_INTERNAL_DECL duk_bool_t duk_debug_read_peek(duk_hthread *thr);
7335 DUK_INTERNAL_DECL void duk_debug_write_flush(duk_hthread *thr);
7336 
7337 DUK_INTERNAL_DECL void duk_debug_skip_bytes(duk_hthread *thr, duk_size_t length);
7338 DUK_INTERNAL_DECL void duk_debug_skip_byte(duk_hthread *thr);
7339 
7340 DUK_INTERNAL_DECL void duk_debug_read_bytes(duk_hthread *thr, duk_uint8_t *data, duk_size_t length);
7341 DUK_INTERNAL_DECL duk_uint8_t duk_debug_read_byte(duk_hthread *thr);
7342 DUK_INTERNAL_DECL duk_int32_t duk_debug_read_int(duk_hthread *thr);
7343 DUK_INTERNAL_DECL duk_hstring *duk_debug_read_hstring(duk_hthread *thr);
7344 /* XXX: exposed duk_debug_read_pointer */
7345 /* XXX: exposed duk_debug_read_buffer */
7346 /* XXX: exposed duk_debug_read_hbuffer */
7347 #if 0
7348 DUK_INTERNAL_DECL duk_heaphdr *duk_debug_read_heapptr(duk_hthread *thr);
7349 #endif
7350 #if defined(DUK_USE_DEBUGGER_INSPECT)
7351 DUK_INTERNAL_DECL duk_heaphdr *duk_debug_read_any_ptr(duk_hthread *thr);
7352 #endif
7353 DUK_INTERNAL_DECL duk_tval *duk_debug_read_tval(duk_hthread *thr);
7354 
7355 DUK_INTERNAL_DECL void duk_debug_write_bytes(duk_hthread *thr, const duk_uint8_t *data, duk_size_t length);
7356 DUK_INTERNAL_DECL void duk_debug_write_byte(duk_hthread *thr, duk_uint8_t x);
7357 DUK_INTERNAL_DECL void duk_debug_write_unused(duk_hthread *thr);
7358 DUK_INTERNAL_DECL void duk_debug_write_undefined(duk_hthread *thr);
7359 #if defined(DUK_USE_DEBUGGER_INSPECT)
7360 DUK_INTERNAL_DECL void duk_debug_write_null(duk_hthread *thr);
7361 #endif
7362 DUK_INTERNAL_DECL void duk_debug_write_boolean(duk_hthread *thr, duk_uint_t val);
7363 DUK_INTERNAL_DECL void duk_debug_write_int(duk_hthread *thr, duk_int32_t x);
7364 DUK_INTERNAL_DECL void duk_debug_write_uint(duk_hthread *thr, duk_uint32_t x);
7365 DUK_INTERNAL_DECL void duk_debug_write_string(duk_hthread *thr, const char *data, duk_size_t length);
7366 DUK_INTERNAL_DECL void duk_debug_write_cstring(duk_hthread *thr, const char *data);
7367 DUK_INTERNAL_DECL void duk_debug_write_hstring(duk_hthread *thr, duk_hstring *h);
7368 DUK_INTERNAL_DECL void duk_debug_write_buffer(duk_hthread *thr, const char *data, duk_size_t length);
7369 DUK_INTERNAL_DECL void duk_debug_write_hbuffer(duk_hthread *thr, duk_hbuffer *h);
7370 DUK_INTERNAL_DECL void duk_debug_write_pointer(duk_hthread *thr, void *ptr);
7371 #if defined(DUK_USE_DEBUGGER_DUMPHEAP) || defined(DUK_USE_DEBUGGER_INSPECT)
7372 DUK_INTERNAL_DECL void duk_debug_write_heapptr(duk_hthread *thr, duk_heaphdr *h);
7373 #endif
7374 DUK_INTERNAL_DECL void duk_debug_write_hobject(duk_hthread *thr, duk_hobject *obj);
7375 DUK_INTERNAL_DECL void duk_debug_write_tval(duk_hthread *thr, duk_tval *tv);
7376 #if 0  /* unused */
7377 DUK_INTERNAL_DECL void duk_debug_write_request(duk_hthread *thr, duk_small_uint_t command);
7378 #endif
7379 DUK_INTERNAL_DECL void duk_debug_write_reply(duk_hthread *thr);
7380 DUK_INTERNAL_DECL void duk_debug_write_error_eom(duk_hthread *thr, duk_small_uint_t err_code, const char *msg);
7381 DUK_INTERNAL_DECL void duk_debug_write_notify(duk_hthread *thr, duk_small_uint_t command);
7382 DUK_INTERNAL_DECL void duk_debug_write_eom(duk_hthread *thr);
7383 
7384 DUK_INTERNAL_DECL duk_uint_fast32_t duk_debug_curr_line(duk_hthread *thr);
7385 DUK_INTERNAL_DECL void duk_debug_send_status(duk_hthread *thr);
7386 #if defined(DUK_USE_DEBUGGER_THROW_NOTIFY)
7387 DUK_INTERNAL_DECL void duk_debug_send_throw(duk_hthread *thr, duk_bool_t fatal);
7388 #endif
7389 
7390 DUK_INTERNAL_DECL void duk_debug_halt_execution(duk_hthread *thr, duk_bool_t use_prev_pc);
7391 DUK_INTERNAL_DECL duk_bool_t duk_debug_process_messages(duk_hthread *thr, duk_bool_t no_block);
7392 
7393 DUK_INTERNAL_DECL duk_small_int_t duk_debug_add_breakpoint(duk_hthread *thr, duk_hstring *filename, duk_uint32_t line);
7394 DUK_INTERNAL_DECL duk_bool_t duk_debug_remove_breakpoint(duk_hthread *thr, duk_small_uint_t breakpoint_index);
7395 #endif
7396 
7397 #endif  /* DUK_DEBUGGER_H_INCLUDED */
7398 /*
7399  *  Debugging macros, DUK_DPRINT() and its variants in particular.
7400  *
7401  *  DUK_DPRINT() allows formatted debug prints, and supports standard
7402  *  and Duktape specific formatters.  See duk_debug_vsnprintf.c for details.
7403  *
7404  *  DUK_D(x), DUK_DD(x), and DUK_DDD(x) are used together with log macros
7405  *  for technical reasons.  They are concretely used to hide 'x' from the
7406  *  compiler when the corresponding log level is disabled.  This allows
7407  *  clean builds on non-C99 compilers, at the cost of more verbose code.
7408  *  Examples:
7409  *
7410  *    DUK_D(DUK_DPRINT("foo"));
7411  *    DUK_DD(DUK_DDPRINT("foo"));
7412  *    DUK_DDD(DUK_DDDPRINT("foo"));
7413  *
7414  *  This approach is preferable to the old "double parentheses" hack because
7415  *  double parentheses make the C99 solution worse: __FILE__ and __LINE__ can
7416  *  no longer be added transparently without going through globals, which
7417  *  works poorly with threading.
7418  */
7419 
7420 #ifndef DUK_DEBUG_H_INCLUDED
7421 #define DUK_DEBUG_H_INCLUDED
7422 
7423 #ifdef DUK_USE_DEBUG
7424 
7425 #if defined(DUK_USE_DPRINT)
7426 #define DUK_D(x) x
7427 #else
7428 #define DUK_D(x) do { } while (0) /* omit */
7429 #endif
7430 
7431 #if defined(DUK_USE_DDPRINT)
7432 #define DUK_DD(x) x
7433 #else
7434 #define DUK_DD(x) do { } while (0) /* omit */
7435 #endif
7436 
7437 #if defined(DUK_USE_DDDPRINT)
7438 #define DUK_DDD(x) x
7439 #else
7440 #define DUK_DDD(x) do { } while (0) /* omit */
7441 #endif
7442 
7443 /*
7444  *  Exposed debug macros: debugging enabled
7445  */
7446 
7447 #define DUK_LEVEL_DEBUG    1
7448 #define DUK_LEVEL_DDEBUG   2
7449 #define DUK_LEVEL_DDDEBUG  3
7450 
7451 #ifdef DUK_USE_VARIADIC_MACROS
7452 
7453 /* Note: combining __FILE__, __LINE__, and __func__ into fmt would be
7454  * possible compile time, but waste some space with shared function names.
7455  */
7456 #define DUK__DEBUG_LOG(lev,...)  duk_debug_log((duk_small_int_t) (lev), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, DUK_FUNC_MACRO, __VA_ARGS__);
7457 
7458 #define DUK_DPRINT(...)          DUK__DEBUG_LOG(DUK_LEVEL_DEBUG, __VA_ARGS__)
7459 
7460 #ifdef DUK_USE_DDPRINT
7461 #define DUK_DDPRINT(...)         DUK__DEBUG_LOG(DUK_LEVEL_DDEBUG, __VA_ARGS__)
7462 #else
7463 #define DUK_DDPRINT(...)
7464 #endif
7465 
7466 #ifdef DUK_USE_DDDPRINT
7467 #define DUK_DDDPRINT(...)        DUK__DEBUG_LOG(DUK_LEVEL_DDDEBUG, __VA_ARGS__)
7468 #else
7469 #define DUK_DDDPRINT(...)
7470 #endif
7471 
7472 #else  /* DUK_USE_VARIADIC_MACROS */
7473 
7474 #define DUK__DEBUG_STASH(lev)    \
7475 	(void) DUK_SNPRINTF(duk_debug_file_stash, DUK_DEBUG_STASH_SIZE, "%s", (const char *) DUK_FILE_MACRO), \
7476 	duk_debug_file_stash[DUK_DEBUG_STASH_SIZE - 1] = (char) 0; \
7477 	(void) DUK_SNPRINTF(duk_debug_line_stash, DUK_DEBUG_STASH_SIZE, "%ld", (long) DUK_LINE_MACRO), \
7478 	duk_debug_line_stash[DUK_DEBUG_STASH_SIZE - 1] = (char) 0; \
7479 	(void) DUK_SNPRINTF(duk_debug_func_stash, DUK_DEBUG_STASH_SIZE, "%s", (const char *) DUK_FUNC_MACRO), \
7480 	duk_debug_func_stash[DUK_DEBUG_STASH_SIZE - 1] = (char) 0; \
7481 	(void) (duk_debug_level_stash = (lev))
7482 
7483 /* Without variadic macros resort to comma expression trickery to handle debug
7484  * prints.  This generates a lot of harmless warnings.  These hacks are not
7485  * needed normally because DUK_D() and friends will hide the entire debug log
7486  * statement from the compiler.
7487  */
7488 
7489 #ifdef DUK_USE_DPRINT
7490 #define DUK_DPRINT  DUK__DEBUG_STASH(DUK_LEVEL_DEBUG), (void) duk_debug_log  /* args go here in parens */
7491 #else
7492 #define DUK_DPRINT  0 && /* args go here as a comma expression in parens */
7493 #endif
7494 
7495 #ifdef DUK_USE_DDPRINT
7496 #define DUK_DDPRINT  DUK__DEBUG_STASH(DUK_LEVEL_DDEBUG), (void) duk_debug_log  /* args go here in parens */
7497 #else
7498 #define DUK_DDPRINT  0 && /* args */
7499 #endif
7500 
7501 #ifdef DUK_USE_DDDPRINT
7502 #define DUK_DDDPRINT  DUK__DEBUG_STASH(DUK_LEVEL_DDDEBUG), (void) duk_debug_log  /* args go here in parens */
7503 #else
7504 #define DUK_DDDPRINT  0 && /* args */
7505 #endif
7506 
7507 #endif  /* DUK_USE_VARIADIC_MACROS */
7508 
7509 #else  /* DUK_USE_DEBUG */
7510 
7511 /*
7512  *  Exposed debug macros: debugging disabled
7513  */
7514 
7515 #define DUK_D(x) do { } while (0) /* omit */
7516 #define DUK_DD(x) do { } while (0) /* omit */
7517 #define DUK_DDD(x) do { } while (0) /* omit */
7518 
7519 #ifdef DUK_USE_VARIADIC_MACROS
7520 
7521 #define DUK_DPRINT(...)
7522 #define DUK_DDPRINT(...)
7523 #define DUK_DDDPRINT(...)
7524 
7525 #else  /* DUK_USE_VARIADIC_MACROS */
7526 
7527 #define DUK_DPRINT    0 && /* args go here as a comma expression in parens */
7528 #define DUK_DDPRINT   0 && /* args */
7529 #define DUK_DDDPRINT  0 && /* args */
7530 
7531 #endif  /* DUK_USE_VARIADIC_MACROS */
7532 
7533 #endif  /* DUK_USE_DEBUG */
7534 
7535 /*
7536  *  Structs
7537  */
7538 
7539 #ifdef DUK_USE_DEBUG
7540 struct duk_fixedbuffer {
7541 	duk_uint8_t *buffer;
7542 	duk_size_t length;
7543 	duk_size_t offset;
7544 	duk_bool_t truncated;
7545 };
7546 #endif
7547 
7548 /*
7549  *  Prototypes
7550  */
7551 
7552 #ifdef DUK_USE_DEBUG
7553 DUK_INTERNAL_DECL duk_int_t duk_debug_vsnprintf(char *str, duk_size_t size, const char *format, va_list ap);
7554 #if 0  /*unused*/
7555 DUK_INTERNAL_DECL duk_int_t duk_debug_snprintf(char *str, duk_size_t size, const char *format, ...);
7556 #endif
7557 DUK_INTERNAL_DECL void duk_debug_format_funcptr(char *buf, duk_size_t buf_size, duk_uint8_t *fptr, duk_size_t fptr_size);
7558 
7559 #ifdef DUK_USE_VARIADIC_MACROS
7560 DUK_INTERNAL_DECL void duk_debug_log(duk_small_int_t level, const char *file, duk_int_t line, const char *func, const char *fmt, ...);
7561 #else  /* DUK_USE_VARIADIC_MACROS */
7562 /* parameter passing, not thread safe */
7563 #define DUK_DEBUG_STASH_SIZE  128
7564 #if !defined(DUK_SINGLE_FILE)
7565 DUK_INTERNAL_DECL char duk_debug_file_stash[DUK_DEBUG_STASH_SIZE];
7566 DUK_INTERNAL_DECL char duk_debug_line_stash[DUK_DEBUG_STASH_SIZE];
7567 DUK_INTERNAL_DECL char duk_debug_func_stash[DUK_DEBUG_STASH_SIZE];
7568 DUK_INTERNAL_DECL duk_small_int_t duk_debug_level_stash;
7569 #endif
7570 DUK_INTERNAL_DECL void duk_debug_log(const char *fmt, ...);
7571 #endif  /* DUK_USE_VARIADIC_MACROS */
7572 
7573 DUK_INTERNAL_DECL void duk_fb_put_bytes(duk_fixedbuffer *fb, const duk_uint8_t *buffer, duk_size_t length);
7574 DUK_INTERNAL_DECL void duk_fb_put_byte(duk_fixedbuffer *fb, duk_uint8_t x);
7575 DUK_INTERNAL_DECL void duk_fb_put_cstring(duk_fixedbuffer *fb, const char *x);
7576 DUK_INTERNAL_DECL void duk_fb_sprintf(duk_fixedbuffer *fb, const char *fmt, ...);
7577 DUK_INTERNAL_DECL void duk_fb_put_funcptr(duk_fixedbuffer *fb, duk_uint8_t *fptr, duk_size_t fptr_size);
7578 DUK_INTERNAL_DECL duk_bool_t duk_fb_is_full(duk_fixedbuffer *fb);
7579 
7580 #endif  /* DUK_USE_DEBUG */
7581 
7582 #endif  /* DUK_DEBUG_H_INCLUDED */
7583 /*
7584  *  Error handling macros, assertion macro, error codes.
7585  *
7586  *  There are three level of 'errors':
7587  *
7588  *    1. Ordinary errors, relative to a thread, cause a longjmp, catchable.
7589  *    2. Fatal errors, relative to a heap, cause fatal handler to be called.
7590  *    3. Panic errors, unrelated to a heap and cause a process exit.
7591  *
7592  *  Panics are used by the default fatal error handler and by debug code
7593  *  such as assertions.  By providing a proper fatal error handler, user
7594  *  code can avoid panics in non-debug builds.
7595  */
7596 
7597 #ifndef DUK_ERROR_H_INCLUDED
7598 #define DUK_ERROR_H_INCLUDED
7599 
7600 /*
7601  *  Error codes: defined in duktape.h
7602  *
7603  *  Error codes are used as a shorthand to throw exceptions from inside
7604  *  the implementation.  The appropriate Ecmascript object is constructed
7605  *  based on the code.  Ecmascript code throws objects directly.  The error
7606  *  codes are defined in the public API header because they are also used
7607  *  by calling code.
7608  */
7609 
7610 /*
7611  *  Normal error
7612  *
7613  *  Normal error is thrown with a longjmp() through the current setjmp()
7614  *  catchpoint record in the duk_heap.  The 'curr_thread' of the duk_heap
7615  *  identifies the throwing thread.
7616  *
7617  *  Error formatting is usually unnecessary.  The error macros provide a
7618  *  zero argument version (no formatting) and separate macros for small
7619  *  argument counts.  Variadic macros are not used to avoid portability
7620  *  issues and avoid the need for stash-based workarounds when they're not
7621  *  available.  Vararg calls are avoided for non-formatted error calls
7622  *  because vararg call sites are larger than normal, and there are a lot
7623  *  of call sites with no formatting.
7624  *
7625  *  Note that special formatting provided by debug macros is NOT available.
7626  *
7627  *  The _RAW variants allow the caller to specify file and line.  This makes
7628  *  it easier to write checked calls which want to use the call site of the
7629  *  checked function, not the error macro call inside the checked function.
7630  */
7631 
7632 #if defined(DUK_USE_VERBOSE_ERRORS)
7633 
7634 /* Because there are quite many call sites, pack error code (require at most
7635  * 8-bit) into a single argument.
7636  */
7637 #define DUK_ERROR(thr,err,msg) do { \
7638 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
7639 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
7640 		duk_err_handle_error((thr), DUK_FILE_MACRO, (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (msg)); \
7641 	} while (0)
7642 #define DUK_ERROR_RAW(thr,file,line,err,msg) do { \
7643 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \
7644 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
7645 		duk_err_handle_error((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (msg)); \
7646 	} while (0)
7647 
7648 #define DUK_ERROR_FMT1(thr,err,fmt,arg1) do { \
7649 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
7650 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
7651 		duk_err_handle_error_fmt((thr), DUK_FILE_MACRO, (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1)); \
7652 	} while (0)
7653 #define DUK_ERROR_RAW_FMT1(thr,file,line,err,fmt,arg1) do { \
7654 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \
7655 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
7656 		duk_err_handle_error_fmt((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1)); \
7657 	} while (0)
7658 
7659 #define DUK_ERROR_FMT2(thr,err,fmt,arg1,arg2) do { \
7660 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
7661 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
7662 		duk_err_handle_error_fmt((thr), DUK_FILE_MACRO, (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2)); \
7663 	} while (0)
7664 #define DUK_ERROR_RAW_FMT2(thr,file,line,err,fmt,arg1,arg2) do { \
7665 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \
7666 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
7667 		duk_err_handle_error_fmt((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2)); \
7668 	} while (0)
7669 
7670 #define DUK_ERROR_FMT3(thr,err,fmt,arg1,arg2,arg3) do { \
7671 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
7672 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
7673 		duk_err_handle_error_fmt((thr), DUK_FILE_MACRO, (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2), (arg3)); \
7674 	} while (0)
7675 #define DUK_ERROR_RAW_FMT3(thr,file,line,err,fmt,arg1,arg2,arg3) do { \
7676 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \
7677 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
7678 		duk_err_handle_error_fmt((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2), (arg3)); \
7679 	} while (0)
7680 
7681 #define DUK_ERROR_FMT4(thr,err,fmt,arg1,arg2,arg3,arg4) do { \
7682 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
7683 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
7684 		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)); \
7685 	} while (0)
7686 #define DUK_ERROR_RAW_FMT4(thr,file,line,err,fmt,arg1,arg2,arg3,arg4) do { \
7687 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \
7688 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
7689 		duk_err_handle_error_fmt((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2), (arg3), (arg4)); \
7690 	} while (0)
7691 
7692 #else  /* DUK_USE_VERBOSE_ERRORS */
7693 
7694 #define DUK_ERROR(thr,err,msg)                    duk_err_handle_error((thr), (err))
7695 #define DUK_ERROR_RAW(thr,file,line,err,msg)      duk_err_handle_error((thr), (err))
7696 
7697 #define DUK_ERROR_FMT1(thr,err,fmt,arg1) DUK_ERROR((thr),(err),(fmt))
7698 #define DUK_ERROR_RAW_FMT1(thr,file,line,err,fmt,arg1) DUK_ERROR_RAW((thr),(file),(line),(err),(fmt))
7699 
7700 #define DUK_ERROR_FMT2(thr,err,fmt,arg1,arg2) DUK_ERROR((thr),(err),(fmt))
7701 #define DUK_ERROR_RAW_FMT2(thr,file,line,err,fmt,arg1,arg2) DUK_ERROR_RAW((thr),(file),(line),(err),(fmt))
7702 
7703 #define DUK_ERROR_FMT3(thr,err,fmt,arg1,arg2,arg3) DUK_ERROR((thr),(err),(fmt))
7704 #define DUK_ERROR_RAW_FMT3(thr,file,line,err,fmt,arg1,arg2,arg3) DUK_ERROR_RAW((thr),(file),(line),(err),(fmt))
7705 
7706 #define DUK_ERROR_FMT4(thr,err,fmt,arg1,arg2,arg3,arg4) DUK_ERROR((thr),(err),(fmt))
7707 #define DUK_ERROR_RAW_FMT4(thr,file,line,err,fmt,arg1,arg2,arg3,arg4) DUK_ERROR_RAW((thr),(file),(line),(err),(fmt))
7708 
7709 #endif  /* DUK_USE_VERBOSE_ERRORS */
7710 
7711 /*
7712  *  Fatal error
7713  *
7714  *  There are no fatal error macros at the moment.  There are so few call
7715  *  sites that the fatal error handler is called directly.
7716  */
7717 
7718 /*
7719  *  Panic error
7720  *
7721  *  Panic errors are not relative to either a heap or a thread, and cause
7722  *  DUK_PANIC() macro to be invoked.  Unless a user provides DUK_USE_PANIC_HANDLER,
7723  *  DUK_PANIC() calls a helper which prints out the error and causes a process
7724  *  exit.
7725  *
7726  *  The user can override the macro to provide custom handling.  A macro is
7727  *  used to allow the user to have inline panic handling if desired (without
7728  *  causing a potentially risky function call).
7729  *
7730  *  Panics are only used in debug code such as assertions, and by the default
7731  *  fatal error handler.
7732  */
7733 
7734 #if defined(DUK_USE_PANIC_HANDLER)
7735 /* already defined, good */
7736 #define DUK_PANIC(code,msg)  DUK_USE_PANIC_HANDLER((code),(msg))
7737 #else
7738 #define DUK_PANIC(code,msg)  duk_default_panic_handler((code),(msg))
7739 #endif  /* DUK_USE_PANIC_HANDLER */
7740 
7741 /*
7742  *  Assert macro: failure causes panic.
7743  */
7744 
7745 #if defined(DUK_USE_ASSERTIONS)
7746 
7747 /* the message should be a compile time constant without formatting (less risk);
7748  * we don't care about assertion text size because they're not used in production
7749  * builds.
7750  */
7751 #define DUK_ASSERT(x)  do { \
7752 	if (!(x)) { \
7753 		DUK_PANIC(DUK_ERR_ASSERTION_ERROR, \
7754 			"assertion failed: " #x \
7755 			" (" DUK_FILE_MACRO ":" DUK_MACRO_STRINGIFY(DUK_LINE_MACRO) ")"); \
7756 	} \
7757 	} while (0)
7758 
7759 /* Assertion compatible inside a comma expression, evaluates to void.
7760  * Currently not compatible with DUK_USE_PANIC_HANDLER() which may have
7761  * a statement block.
7762  */
7763 #if defined(DUK_USE_PANIC_HANDLER)
7764 /* XXX: resolve macro definition issue or call through a helper function? */
7765 #define DUK_ASSERT_EXPR(x)  ((void) 0)
7766 #else
7767 #define DUK_ASSERT_EXPR(x) \
7768 	((void) ((x) ? 0 : (DUK_PANIC(DUK_ERR_ASSERTION_ERROR, \
7769 				"assertion failed: " #x \
7770 				" (" DUK_FILE_MACRO ":" DUK_MACRO_STRINGIFY(DUK_LINE_MACRO) ")"), 0)))
7771 #endif
7772 
7773 #else  /* DUK_USE_ASSERTIONS */
7774 
7775 #define DUK_ASSERT(x)  do { /* assertion omitted */ } while (0)
7776 
7777 #define DUK_ASSERT_EXPR(x)  ((void) 0)
7778 
7779 #endif  /* DUK_USE_ASSERTIONS */
7780 
7781 /* this variant is used when an assert would generate a compile warning by
7782  * being always true (e.g. >= 0 comparison for an unsigned value
7783  */
7784 #define DUK_ASSERT_DISABLE(x)  do { /* assertion disabled */ } while (0)
7785 
7786 /*
7787  *  Assertion helpers
7788  */
7789 
7790 #if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_REFERENCE_COUNTING)
7791 #define DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(h)  do { \
7792 		DUK_ASSERT((h) == NULL || DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) (h)) > 0); \
7793 	} while (0)
7794 #define DUK_ASSERT_REFCOUNT_NONZERO_TVAL(tv)  do { \
7795 		if ((tv) != NULL && DUK_TVAL_IS_HEAP_ALLOCATED((tv))) { \
7796 			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(DUK_TVAL_GET_HEAPHDR((tv))) > 0); \
7797 		} \
7798 	} while (0)
7799 #else
7800 #define DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(h)  /* no refcount check */
7801 #define DUK_ASSERT_REFCOUNT_NONZERO_TVAL(tv)    /* no refcount check */
7802 #endif
7803 
7804 #define DUK_ASSERT_TOP(ctx,n)  DUK_ASSERT((duk_idx_t) duk_get_top((ctx)) == (duk_idx_t) (n))
7805 
7806 #if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_PACKED_TVAL)
7807 #define DUK_ASSERT_DOUBLE_IS_NORMALIZED(dval)  do { \
7808 		duk_double_union duk__assert_tmp_du; \
7809 		duk__assert_tmp_du.d = (dval); \
7810 		DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&duk__assert_tmp_du)); \
7811 	} while (0)
7812 #else
7813 #define DUK_ASSERT_DOUBLE_IS_NORMALIZED(dval)  /* nop */
7814 #endif
7815 
7816 /*
7817  *  Helper for valstack space
7818  *
7819  *  Caller of DUK_ASSERT_VALSTACK_SPACE() estimates the number of free stack entries
7820  *  required for its own use, and any child calls which are not (a) Duktape API calls
7821  *  or (b) Duktape calls which involve extending the valstack (e.g. getter call).
7822  */
7823 
7824 #define DUK_VALSTACK_ASSERT_EXTRA  5  /* this is added to checks to allow for Duktape
7825                                        * API calls in addition to function's own use
7826                                        */
7827 #if defined(DUK_USE_ASSERTIONS)
7828 #define DUK_ASSERT_VALSTACK_SPACE(thr,n)   do { \
7829 		DUK_ASSERT((thr) != NULL); \
7830 		DUK_ASSERT((thr)->valstack_end - (thr)->valstack_top >= (n) + DUK_VALSTACK_ASSERT_EXTRA); \
7831 	} while (0)
7832 #else
7833 #define DUK_ASSERT_VALSTACK_SPACE(thr,n)   /* no valstack space check */
7834 #endif
7835 
7836 /*
7837  *  Error throwing helpers
7838  *
7839  *  The goal is to provide verbose and configurable error messages.  Call
7840  *  sites should be clean in source code and compile to a small footprint.
7841  *  Small footprint is also useful for performance because small cold paths
7842  *  reduce code cache pressure.  Adding macros here only makes sense if there
7843  *  are enough call sites to get concrete benefits.
7844  */
7845 
7846 #if defined(DUK_USE_VERBOSE_ERRORS)
7847 /* Verbose errors with key/value summaries (non-paranoid) or without key/value
7848  * summaries (paranoid, for some security sensitive environments), the paranoid
7849  * vs. non-paranoid distinction affects only a few specific errors.
7850  */
7851 #if defined(DUK_USE_PARANOID_ERRORS)
7852 #define DUK_ERROR_REQUIRE_TYPE_INDEX(thr,index,expectname,lowmemstr) do { \
7853 		duk_err_require_type_index((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (index), (expectname)); \
7854 	} while (0)
7855 #else  /* DUK_USE_PARANOID_ERRORS */
7856 #define DUK_ERROR_REQUIRE_TYPE_INDEX(thr,index,expectname,lowmemstr) do { \
7857 		duk_err_require_type_index((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (index), (expectname)); \
7858 	} while (0)
7859 #endif  /* DUK_USE_PARANOID_ERRORS */
7860 
7861 #define DUK_ERROR_UNIMPLEMENTED(thr,msg) do { \
7862 		DUK_ERROR((thr), DUK_ERR_UNIMPLEMENTED_ERROR, (msg)); \
7863 	} while (0)
7864 #define DUK_ERROR_UNIMPLEMENTED_DEFMSG(thr) do { \
7865 		duk_err_unimplemented_defmsg((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
7866 	} while (0)
7867 #define DUK_ERROR_UNSUPPORTED(thr,msg) do { \
7868 		DUK_ERROR((thr), DUK_ERR_UNSUPPORTED_ERROR, (msg)); \
7869 	} while (0)
7870 #if !defined(DUK_USE_BYTECODE_DUMP_SUPPORT)
7871 #define DUK_ERROR_UNSUPPORTED_DEFMSG(thr) do { \
7872 		duk_err_unsupported_defmsg((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
7873 	} while (0)
7874 #endif
7875 #define DUK_ERROR_INTERNAL(thr,msg) do { \
7876 		duk_err_internal((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (msg)); \
7877 	} while (0)
7878 #define DUK_ERROR_INTERNAL_DEFMSG(thr) do { \
7879 		duk_err_internal_defmsg((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
7880 	} while (0)
7881 #define DUK_ERROR_ALLOC(thr,msg) do { \
7882 		duk_err_alloc((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (msg)); \
7883 	} while (0)
7884 #define DUK_ERROR_ALLOC_DEFMSG(thr) do { \
7885 		DUK_ERROR_ALLOC((thr), DUK_STR_ALLOC_FAILED); \
7886 	} while (0)
7887 /* DUK_ERR_ASSERTION_ERROR: no macros needed */
7888 #define DUK_ERROR_API_INDEX(thr,index) do { \
7889 		duk_err_api_index((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (index)); \
7890 	} while (0)
7891 #define DUK_ERROR_API(thr,msg) do { \
7892 		duk_err_api((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (msg)); \
7893 	} while (0)
7894 /* DUK_ERR_UNCAUGHT_ERROR: no macros needed */
7895 /* DUK_ERR_ERROR: no macros needed */
7896 /* DUK_ERR_EVAL: no macros needed */
7897 #define DUK_ERROR_RANGE(thr,msg) do { \
7898 		duk_err_range((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (msg)); \
7899 	} while (0)
7900 /* DUK_ERR_REFERENCE_ERROR: no macros needed */
7901 #define DUK_ERROR_SYNTAX(thr,msg) do { \
7902 		DUK_ERROR((thr), DUK_ERR_SYNTAX_ERROR, (msg)); \
7903 	} while (0)
7904 #define DUK_ERROR_TYPE(thr,msg) do { \
7905 		DUK_ERROR((thr), DUK_ERR_TYPE_ERROR, (msg)); \
7906 	} while (0)
7907 /* DUK_ERR_URI_ERROR: no macros needed */
7908 #else  /* DUK_USE_VERBOSE_ERRORS */
7909 /* Non-verbose errors for low memory targets: no file, line, or message. */
7910 
7911 #define DUK_ERROR_REQUIRE_TYPE_INDEX(thr,index,expectname,lowmemstr) do { \
7912 		duk_err_type((thr)); \
7913 	} while (0)
7914 
7915 #define DUK_ERROR_UNIMPLEMENTED(thr,msg) do { \
7916 		duk_err_unimplemented((thr)); \
7917 	} while (0)
7918 #define DUK_ERROR_UNIMPLEMENTED_DEFMSG(thr) do { \
7919 		duk_err_unimplemented((thr)); \
7920 	} while (0)
7921 #define DUK_ERROR_UNSUPPORTED(thr,msg) do { \
7922 		duk_err_unsupported((thr)); \
7923 	} while (0)
7924 #define DUK_ERROR_UNSUPPORTED_DEFMSG(thr) do { \
7925 		duk_err_unsupported((thr)); \
7926 	} while (0)
7927 #define DUK_ERROR_INTERNAL(thr,msg) do { \
7928 		duk_err_internal((thr)); \
7929 	} while (0)
7930 #define DUK_ERROR_INTERNAL_DEFMSG(thr) do { \
7931 		duk_err_internal((thr)); \
7932 	} while (0)
7933 #define DUK_ERROR_ALLOC(thr,msg) do { \
7934 		duk_err_alloc((thr)); \
7935 	} while (0)
7936 #define DUK_ERROR_ALLOC_DEFMSG(thr) do { \
7937 		duk_err_alloc((thr)); \
7938 	} while (0)
7939 #define DUK_ERROR_API_INDEX(thr,index) do { \
7940 		duk_err_api((thr)); \
7941 	} while (0)
7942 #define DUK_ERROR_API(thr,msg) do { \
7943 		duk_err_api((thr)); \
7944 	} while (0)
7945 #define DUK_ERROR_RANGE(thr,msg) do { \
7946 		duk_err_range((thr)); \
7947 	} while (0)
7948 #define DUK_ERROR_SYNTAX(thr,msg) do { \
7949 		duk_err_syntax((thr)); \
7950 	} while (0)
7951 #define DUK_ERROR_TYPE(thr,msg) do { \
7952 		duk_err_type((thr)); \
7953 	} while (0)
7954 #endif  /* DUK_USE_VERBOSE_ERRORS */
7955 
7956 /*
7957  *  Prototypes
7958  */
7959 
7960 #if defined(DUK_USE_VERBOSE_ERRORS)
7961 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));
7962 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, ...));
7963 #else  /* DUK_USE_VERBOSE_ERRORS */
7964 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_handle_error(duk_hthread *thr, duk_errcode_t code));
7965 #endif  /* DUK_USE_VERBOSE_ERRORS */
7966 
7967 #if defined(DUK_USE_VERBOSE_ERRORS)
7968 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));
7969 #else
7970 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_create_and_throw(duk_hthread *thr, duk_errcode_t code));
7971 #endif
7972 
7973 DUK_NORETURN(DUK_INTERNAL_DECL void duk_error_throw_from_negative_rc(duk_hthread *thr, duk_ret_t rc));
7974 
7975 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
7976 DUK_INTERNAL_DECL void duk_err_augment_error_create(duk_hthread *thr, duk_hthread *thr_callstack, const char *filename, duk_int_t line, duk_bool_t noblame_fileline);
7977 #endif
7978 #if defined(DUK_USE_AUGMENT_ERROR_THROW)
7979 DUK_INTERNAL_DECL void duk_err_augment_error_throw(duk_hthread *thr);
7980 #endif
7981 
7982 #if defined(DUK_USE_VERBOSE_ERRORS)
7983 #if defined(DUK_USE_PARANOID_ERRORS)
7984 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_require_type_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t index, const char *expect_name));
7985 #else
7986 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_require_type_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t index, const char *expect_name));
7987 #endif
7988 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_api_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t index));
7989 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_api(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message));
7990 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_range(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message));
7991 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_unimplemented_defmsg(duk_hthread *thr, const char *filename, duk_int_t linenumber));
7992 #if !defined(DUK_USE_BYTECODE_DUMP_SUPPORT)
7993 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_unsupported_defmsg(duk_hthread *thr, const char *filename, duk_int_t linenumber));
7994 #endif
7995 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_internal_defmsg(duk_hthread *thr, const char *filename, duk_int_t linenumber));
7996 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_internal(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message));
7997 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_alloc(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message));
7998 #else  /* DUK_VERBOSE_ERRORS */
7999 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_range(duk_hthread *thr));
8000 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_syntax(duk_hthread *thr));
8001 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_type(duk_hthread *thr));
8002 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_api(duk_hthread *thr));
8003 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_unimplemented(duk_hthread *thr));
8004 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_unsupported(duk_hthread *thr));
8005 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_internal(duk_hthread *thr));
8006 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_alloc(duk_hthread *thr));
8007 #endif /* DUK_VERBOSE_ERRORS */
8008 
8009 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_longjmp(duk_hthread *thr));
8010 
8011 DUK_NORETURN(DUK_INTERNAL_DECL void duk_default_fatal_handler(duk_context *ctx, duk_errcode_t code, const char *msg));
8012 
8013 #if !defined(DUK_USE_PANIC_HANDLER)
8014 DUK_NORETURN(DUK_INTERNAL_DECL void duk_default_panic_handler(duk_errcode_t code, const char *msg));
8015 #endif
8016 
8017 DUK_INTERNAL_DECL void duk_err_setup_heap_ljstate(duk_hthread *thr, duk_small_int_t lj_type);
8018 
8019 DUK_INTERNAL_DECL duk_hobject *duk_error_prototype_from_code(duk_hthread *thr, duk_errcode_t err_code);
8020 
8021 #endif  /* DUK_ERROR_H_INCLUDED */
8022 /*
8023  *  Unicode helpers
8024  */
8025 
8026 #ifndef DUK_UNICODE_H_INCLUDED
8027 #define DUK_UNICODE_H_INCLUDED
8028 
8029 /*
8030  *  UTF-8 / XUTF-8 / CESU-8 constants
8031  */
8032 
8033 #define DUK_UNICODE_MAX_XUTF8_LENGTH      7   /* up to 36 bit codepoints */
8034 #define DUK_UNICODE_MAX_XUTF8_BMP_LENGTH  3   /* all codepoints up to U+FFFF */
8035 #define DUK_UNICODE_MAX_CESU8_LENGTH      6   /* all codepoints up to U+10FFFF */
8036 #define DUK_UNICODE_MAX_CESU8_BMP_LENGTH  3   /* all codepoints up to U+FFFF */
8037 
8038 /*
8039  *  Useful Unicode codepoints
8040  *
8041  *  Integer constants must be signed to avoid unexpected coercions
8042  *  in comparisons.
8043  */
8044 
8045 #define DUK_UNICODE_CP_ZWNJ                   0x200cL  /* zero-width non-joiner */
8046 #define DUK_UNICODE_CP_ZWJ                    0x200dL  /* zero-width joiner */
8047 #define DUK_UNICODE_CP_REPLACEMENT_CHARACTER  0xfffdL  /* http://en.wikipedia.org/wiki/Replacement_character#Replacement_character */
8048 
8049 /*
8050  *  ASCII character constants
8051  *
8052  *  C character literals like 'x' have a platform specific value and do
8053  *  not match ASCII (UTF-8) values on e.g. EBCDIC platforms.  So, use
8054  *  these (admittedly awkward) constants instead.  These constants must
8055  *  also have signed values to avoid unexpected coercions in comparisons.
8056  *
8057  *  http://en.wikipedia.org/wiki/ASCII
8058  */
8059 
8060 #define DUK_ASC_NUL              0x00
8061 #define DUK_ASC_SOH              0x01
8062 #define DUK_ASC_STX              0x02
8063 #define DUK_ASC_ETX              0x03
8064 #define DUK_ASC_EOT              0x04
8065 #define DUK_ASC_ENQ              0x05
8066 #define DUK_ASC_ACK              0x06
8067 #define DUK_ASC_BEL              0x07
8068 #define DUK_ASC_BS               0x08
8069 #define DUK_ASC_HT               0x09
8070 #define DUK_ASC_LF               0x0a
8071 #define DUK_ASC_VT               0x0b
8072 #define DUK_ASC_FF               0x0c
8073 #define DUK_ASC_CR               0x0d
8074 #define DUK_ASC_SO               0x0e
8075 #define DUK_ASC_SI               0x0f
8076 #define DUK_ASC_DLE              0x10
8077 #define DUK_ASC_DC1              0x11
8078 #define DUK_ASC_DC2              0x12
8079 #define DUK_ASC_DC3              0x13
8080 #define DUK_ASC_DC4              0x14
8081 #define DUK_ASC_NAK              0x15
8082 #define DUK_ASC_SYN              0x16
8083 #define DUK_ASC_ETB              0x17
8084 #define DUK_ASC_CAN              0x18
8085 #define DUK_ASC_EM               0x19
8086 #define DUK_ASC_SUB              0x1a
8087 #define DUK_ASC_ESC              0x1b
8088 #define DUK_ASC_FS               0x1c
8089 #define DUK_ASC_GS               0x1d
8090 #define DUK_ASC_RS               0x1e
8091 #define DUK_ASC_US               0x1f
8092 #define DUK_ASC_SPACE            0x20
8093 #define DUK_ASC_EXCLAMATION      0x21
8094 #define DUK_ASC_DOUBLEQUOTE      0x22
8095 #define DUK_ASC_HASH             0x23
8096 #define DUK_ASC_DOLLAR           0x24
8097 #define DUK_ASC_PERCENT          0x25
8098 #define DUK_ASC_AMP              0x26
8099 #define DUK_ASC_SINGLEQUOTE      0x27
8100 #define DUK_ASC_LPAREN           0x28
8101 #define DUK_ASC_RPAREN           0x29
8102 #define DUK_ASC_STAR             0x2a
8103 #define DUK_ASC_PLUS             0x2b
8104 #define DUK_ASC_COMMA            0x2c
8105 #define DUK_ASC_MINUS            0x2d
8106 #define DUK_ASC_PERIOD           0x2e
8107 #define DUK_ASC_SLASH            0x2f
8108 #define DUK_ASC_0                0x30
8109 #define DUK_ASC_1                0x31
8110 #define DUK_ASC_2                0x32
8111 #define DUK_ASC_3                0x33
8112 #define DUK_ASC_4                0x34
8113 #define DUK_ASC_5                0x35
8114 #define DUK_ASC_6                0x36
8115 #define DUK_ASC_7                0x37
8116 #define DUK_ASC_8                0x38
8117 #define DUK_ASC_9                0x39
8118 #define DUK_ASC_COLON            0x3a
8119 #define DUK_ASC_SEMICOLON        0x3b
8120 #define DUK_ASC_LANGLE           0x3c
8121 #define DUK_ASC_EQUALS           0x3d
8122 #define DUK_ASC_RANGLE           0x3e
8123 #define DUK_ASC_QUESTION         0x3f
8124 #define DUK_ASC_ATSIGN           0x40
8125 #define DUK_ASC_UC_A             0x41
8126 #define DUK_ASC_UC_B             0x42
8127 #define DUK_ASC_UC_C             0x43
8128 #define DUK_ASC_UC_D             0x44
8129 #define DUK_ASC_UC_E             0x45
8130 #define DUK_ASC_UC_F             0x46
8131 #define DUK_ASC_UC_G             0x47
8132 #define DUK_ASC_UC_H             0x48
8133 #define DUK_ASC_UC_I             0x49
8134 #define DUK_ASC_UC_J             0x4a
8135 #define DUK_ASC_UC_K             0x4b
8136 #define DUK_ASC_UC_L             0x4c
8137 #define DUK_ASC_UC_M             0x4d
8138 #define DUK_ASC_UC_N             0x4e
8139 #define DUK_ASC_UC_O             0x4f
8140 #define DUK_ASC_UC_P             0x50
8141 #define DUK_ASC_UC_Q             0x51
8142 #define DUK_ASC_UC_R             0x52
8143 #define DUK_ASC_UC_S             0x53
8144 #define DUK_ASC_UC_T             0x54
8145 #define DUK_ASC_UC_U             0x55
8146 #define DUK_ASC_UC_V             0x56
8147 #define DUK_ASC_UC_W             0x57
8148 #define DUK_ASC_UC_X             0x58
8149 #define DUK_ASC_UC_Y             0x59
8150 #define DUK_ASC_UC_Z             0x5a
8151 #define DUK_ASC_LBRACKET         0x5b
8152 #define DUK_ASC_BACKSLASH        0x5c
8153 #define DUK_ASC_RBRACKET         0x5d
8154 #define DUK_ASC_CARET            0x5e
8155 #define DUK_ASC_UNDERSCORE       0x5f
8156 #define DUK_ASC_GRAVE            0x60
8157 #define DUK_ASC_LC_A             0x61
8158 #define DUK_ASC_LC_B             0x62
8159 #define DUK_ASC_LC_C             0x63
8160 #define DUK_ASC_LC_D             0x64
8161 #define DUK_ASC_LC_E             0x65
8162 #define DUK_ASC_LC_F             0x66
8163 #define DUK_ASC_LC_G             0x67
8164 #define DUK_ASC_LC_H             0x68
8165 #define DUK_ASC_LC_I             0x69
8166 #define DUK_ASC_LC_J             0x6a
8167 #define DUK_ASC_LC_K             0x6b
8168 #define DUK_ASC_LC_L             0x6c
8169 #define DUK_ASC_LC_M             0x6d
8170 #define DUK_ASC_LC_N             0x6e
8171 #define DUK_ASC_LC_O             0x6f
8172 #define DUK_ASC_LC_P             0x70
8173 #define DUK_ASC_LC_Q             0x71
8174 #define DUK_ASC_LC_R             0x72
8175 #define DUK_ASC_LC_S             0x73
8176 #define DUK_ASC_LC_T             0x74
8177 #define DUK_ASC_LC_U             0x75
8178 #define DUK_ASC_LC_V             0x76
8179 #define DUK_ASC_LC_W             0x77
8180 #define DUK_ASC_LC_X             0x78
8181 #define DUK_ASC_LC_Y             0x79
8182 #define DUK_ASC_LC_Z             0x7a
8183 #define DUK_ASC_LCURLY           0x7b
8184 #define DUK_ASC_PIPE             0x7c
8185 #define DUK_ASC_RCURLY           0x7d
8186 #define DUK_ASC_TILDE            0x7e
8187 #define DUK_ASC_DEL              0x7f
8188 
8189 /*
8190  *  Unicode tables
8191  */
8192 
8193 #ifdef DUK_USE_SOURCE_NONBMP
8194 /*
8195  *  Automatically generated by extract_chars.py, do not edit!
8196  */
8197 
8198 extern const duk_uint8_t duk_unicode_ids_noa[791];
8199 #else
8200 /*
8201  *  Automatically generated by extract_chars.py, do not edit!
8202  */
8203 
8204 extern const duk_uint8_t duk_unicode_ids_noabmp[611];
8205 #endif
8206 
8207 #ifdef DUK_USE_SOURCE_NONBMP
8208 /*
8209  *  Automatically generated by extract_chars.py, do not edit!
8210  */
8211 
8212 extern const duk_uint8_t duk_unicode_ids_m_let_noa[42];
8213 #else
8214 /*
8215  *  Automatically generated by extract_chars.py, do not edit!
8216  */
8217 
8218 extern const duk_uint8_t duk_unicode_ids_m_let_noabmp[24];
8219 #endif
8220 
8221 #ifdef DUK_USE_SOURCE_NONBMP
8222 /*
8223  *  Automatically generated by extract_chars.py, do not edit!
8224  */
8225 
8226 extern const duk_uint8_t duk_unicode_idp_m_ids_noa[397];
8227 #else
8228 /*
8229  *  Automatically generated by extract_chars.py, do not edit!
8230  */
8231 
8232 extern const duk_uint8_t duk_unicode_idp_m_ids_noabmp[348];
8233 #endif
8234 
8235 /*
8236  *  Automatically generated by extract_caseconv.py, do not edit!
8237  */
8238 
8239 extern const duk_uint8_t duk_unicode_caseconv_uc[1288];
8240 extern const duk_uint8_t duk_unicode_caseconv_lc[616];
8241 
8242 #if defined(DUK_USE_REGEXP_CANON_WORKAROUND)
8243 /*
8244  *  Automatically generated by extract_caseconv.py, do not edit!
8245  */
8246 
8247 extern const duk_uint16_t duk_unicode_re_canon_lookup[65536];
8248 #endif
8249 
8250 /*
8251  *  Extern
8252  */
8253 
8254 /* duk_unicode_support.c */
8255 #if !defined(DUK_SINGLE_FILE)
8256 DUK_INTERNAL_DECL const duk_uint8_t duk_unicode_xutf8_markers[7];
8257 DUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_digit[2];
8258 DUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_white[22];
8259 DUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_wordchar[8];
8260 DUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_not_digit[4];
8261 DUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_not_white[24];
8262 DUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_not_wordchar[10];
8263 DUK_INTERNAL_DECL const duk_int8_t duk_is_idchar_tab[128];
8264 #endif  /* !DUK_SINGLE_FILE */
8265 
8266 /*
8267  *  Prototypes
8268  */
8269 
8270 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_get_xutf8_length(duk_ucodepoint_t cp);
8271 #if defined(DUK_USE_ASSERTIONS)
8272 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_get_cesu8_length(duk_ucodepoint_t cp);
8273 #endif
8274 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_encode_xutf8(duk_ucodepoint_t cp, duk_uint8_t *out);
8275 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_encode_cesu8(duk_ucodepoint_t cp, duk_uint8_t *out);
8276 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);
8277 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);
8278 DUK_INTERNAL_DECL duk_size_t duk_unicode_unvalidated_utf8_length(const duk_uint8_t *data, duk_size_t blen);
8279 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_whitespace(duk_codepoint_t cp);
8280 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_line_terminator(duk_codepoint_t cp);
8281 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_identifier_start(duk_codepoint_t cp);
8282 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_identifier_part(duk_codepoint_t cp);
8283 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_letter(duk_codepoint_t cp);
8284 DUK_INTERNAL_DECL void duk_unicode_case_convert_string(duk_hthread *thr, duk_bool_t uppercase);
8285 DUK_INTERNAL_DECL duk_codepoint_t duk_unicode_re_canonicalize_char(duk_hthread *thr, duk_codepoint_t cp);
8286 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_re_is_wordchar(duk_codepoint_t cp);
8287 
8288 #endif  /* DUK_UNICODE_H_INCLUDED */
8289 /*
8290  *  Defines for JSON, especially duk_bi_json.c.
8291  */
8292 
8293 #ifndef DUK_JSON_H_INCLUDED
8294 #define DUK_JSON_H_INCLUDED
8295 
8296 /* Encoding/decoding flags */
8297 #define DUK_JSON_FLAG_ASCII_ONLY              (1 << 0)  /* escape any non-ASCII characters */
8298 #define DUK_JSON_FLAG_AVOID_KEY_QUOTES        (1 << 1)  /* avoid key quotes when key is an ASCII Identifier */
8299 #define DUK_JSON_FLAG_EXT_CUSTOM              (1 << 2)  /* extended types: custom encoding */
8300 #define DUK_JSON_FLAG_EXT_COMPATIBLE          (1 << 3)  /* extended types: compatible encoding */
8301 
8302 /* How much stack to require on entry to object/array encode */
8303 #define DUK_JSON_ENC_REQSTACK                 32
8304 
8305 /* How much stack to require on entry to object/array decode */
8306 #define DUK_JSON_DEC_REQSTACK                 32
8307 
8308 /* How large a loop detection stack to use */
8309 #define DUK_JSON_ENC_LOOPARRAY                64
8310 
8311 /* Encoding state.  Heap object references are all borrowed. */
8312 typedef struct {
8313 	duk_hthread *thr;
8314 	duk_bufwriter_ctx bw;        /* output bufwriter */
8315 	duk_hobject *h_replacer;     /* replacer function */
8316 	duk_hstring *h_gap;          /* gap (if empty string, NULL) */
8317 	duk_idx_t idx_proplist;      /* explicit PropertyList */
8318 	duk_idx_t idx_loop;          /* valstack index of loop detection object */
8319 	duk_small_uint_t flags;
8320 	duk_small_uint_t flag_ascii_only;
8321 	duk_small_uint_t flag_avoid_key_quotes;
8322 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
8323 	duk_small_uint_t flag_ext_custom;
8324 	duk_small_uint_t flag_ext_compatible;
8325 	duk_small_uint_t flag_ext_custom_or_compatible;
8326 #endif
8327 	duk_int_t recursion_depth;
8328 	duk_int_t recursion_limit;
8329 	duk_uint_t mask_for_undefined;      /* type bit mask: types which certainly produce 'undefined' */
8330 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
8331 	duk_small_uint_t stridx_custom_undefined;
8332 	duk_small_uint_t stridx_custom_nan;
8333 	duk_small_uint_t stridx_custom_neginf;
8334 	duk_small_uint_t stridx_custom_posinf;
8335 	duk_small_uint_t stridx_custom_function;
8336 #endif
8337 	duk_hobject *visiting[DUK_JSON_ENC_LOOPARRAY];  /* indexed by recursion_depth */
8338 } duk_json_enc_ctx;
8339 
8340 typedef struct {
8341 	duk_hthread *thr;
8342 	const duk_uint8_t *p;
8343 	const duk_uint8_t *p_start;
8344 	const duk_uint8_t *p_end;
8345 	duk_idx_t idx_reviver;
8346 	duk_small_uint_t flags;
8347 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
8348 	duk_small_uint_t flag_ext_custom;
8349 	duk_small_uint_t flag_ext_compatible;
8350 	duk_small_uint_t flag_ext_custom_or_compatible;
8351 #endif
8352 	duk_int_t recursion_depth;
8353 	duk_int_t recursion_limit;
8354 } duk_json_dec_ctx;
8355 
8356 #endif  /* DUK_JSON_H_INCLUDED */
8357 /*
8358  *  Ecmascript execution, support primitives.
8359  */
8360 
8361 #ifndef DUK_JS_H_INCLUDED
8362 #define DUK_JS_H_INCLUDED
8363 
8364 /* Flags for call handling. */
8365 #define DUK_CALL_FLAG_IGNORE_RECLIMIT        (1 << 0)  /* duk_handle_call_xxx: call ignores C recursion limit (for errhandler calls) */
8366 #define DUK_CALL_FLAG_CONSTRUCTOR_CALL       (1 << 1)  /* duk_handle_call_xxx: constructor call (i.e. called as 'new Foo()') */
8367 #define DUK_CALL_FLAG_IS_RESUME              (1 << 2)  /* duk_handle_ecma_call_setup: setup for a resume() */
8368 #define DUK_CALL_FLAG_IS_TAILCALL            (1 << 3)  /* duk_handle_ecma_call_setup: setup for a tail call */
8369 #define DUK_CALL_FLAG_DIRECT_EVAL            (1 << 4)  /* call is a direct eval call */
8370 
8371 /* Flags for duk_js_equals_helper(). */
8372 #define DUK_EQUALS_FLAG_SAMEVALUE            (1 << 0)  /* use SameValue instead of non-strict equality */
8373 #define DUK_EQUALS_FLAG_STRICT               (1 << 1)  /* use strict equality instead of non-strict equality */
8374 
8375 /* Flags for duk_js_compare_helper(). */
8376 #define DUK_COMPARE_FLAG_EVAL_LEFT_FIRST     (1 << 0)  /* eval left argument first */
8377 #define DUK_COMPARE_FLAG_NEGATE              (1 << 1)  /* negate result */
8378 
8379 /* conversions, coercions, comparison, etc */
8380 DUK_INTERNAL_DECL duk_bool_t duk_js_toboolean(duk_tval *tv);
8381 DUK_INTERNAL_DECL duk_double_t duk_js_tonumber(duk_hthread *thr, duk_tval *tv);
8382 DUK_INTERNAL_DECL duk_double_t duk_js_tointeger_number(duk_double_t x);
8383 DUK_INTERNAL_DECL duk_double_t duk_js_tointeger(duk_hthread *thr, duk_tval *tv);
8384 DUK_INTERNAL_DECL duk_uint32_t duk_js_touint32(duk_hthread *thr, duk_tval *tv);
8385 DUK_INTERNAL_DECL duk_int32_t duk_js_toint32(duk_hthread *thr, duk_tval *tv);
8386 DUK_INTERNAL_DECL duk_uint16_t duk_js_touint16(duk_hthread *thr, duk_tval *tv);
8387 DUK_INTERNAL_DECL duk_small_int_t duk_js_to_arrayindex_raw_string(const duk_uint8_t *str, duk_uint32_t blen, duk_uarridx_t *out_idx);
8388 DUK_INTERNAL_DECL duk_uarridx_t duk_js_to_arrayindex_string_helper(duk_hstring *h);
8389 DUK_INTERNAL_DECL duk_bool_t duk_js_equals_helper(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_int_t flags);
8390 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);
8391 DUK_INTERNAL_DECL duk_small_int_t duk_js_string_compare(duk_hstring *h1, duk_hstring *h2);
8392 #if 0  /* unused */
8393 DUK_INTERNAL_DECL duk_small_int_t duk_js_buffer_compare(duk_heap *heap, duk_hbuffer *h1, duk_hbuffer *h2);
8394 #endif
8395 DUK_INTERNAL_DECL duk_bool_t duk_js_compare_helper(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_int_t flags);
8396 DUK_INTERNAL_DECL duk_bool_t duk_js_instanceof(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y);
8397 DUK_INTERNAL_DECL duk_bool_t duk_js_in(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y);
8398 DUK_INTERNAL_DECL duk_hstring *duk_js_typeof(duk_hthread *thr, duk_tval *tv_x);
8399 
8400 #define duk_js_equals(thr,tv_x,tv_y) \
8401 	duk_js_equals_helper((thr), (tv_x), (tv_y), 0)
8402 #define duk_js_strict_equals(tv_x,tv_y) \
8403 	duk_js_equals_helper(NULL, (tv_x), (tv_y), DUK_EQUALS_FLAG_STRICT)
8404 #define duk_js_samevalue(tv_x,tv_y) \
8405 	duk_js_equals_helper(NULL, (tv_x), (tv_y), DUK_EQUALS_FLAG_SAMEVALUE)
8406 
8407 /* E5 Sections 11.8.1, 11.8.5; x < y */
8408 #define duk_js_lessthan(thr,tv_x,tv_y) \
8409 	duk_js_compare_helper((thr), (tv_x), (tv_Y), DUK_COMPARE_FLAG_EVAL_LEFT_FIRST)
8410 
8411 /* E5 Sections 11.8.2, 11.8.5; x > y  -->  y < x */
8412 #define duk_js_greaterthan(thr,tv_x,tv_y) \
8413 	duk_js_compare_helper((thr), (tv_y), (tv_x), 0)
8414 
8415 /* E5 Sections 11.8.3, 11.8.5; x <= y  -->  not (x > y)  -->  not (y < x) */
8416 #define duk_js_lessthanorequal(thr,tv_x,tv_y) \
8417 	duk_js_compare_helper((thr), (tv_y), (tv_x), DUK_COMPARE_FLAG_NEGATE)
8418 
8419 /* E5 Sections 11.8.4, 11.8.5; x >= y  -->  not (x < y) */
8420 #define duk_js_greaterthanorequal(thr,tv_x,tv_y) \
8421 	duk_js_compare_helper((thr), (tv_x), (tv_y), DUK_COMPARE_FLAG_EVAL_LEFT_FIRST | DUK_COMPARE_FLAG_NEGATE)
8422 
8423 /* identifiers and environment handling */
8424 #if 0  /*unused*/
8425 DUK_INTERNAL duk_bool_t duk_js_hasvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name);
8426 #endif
8427 DUK_INTERNAL_DECL duk_bool_t duk_js_getvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name, duk_bool_t throw_flag);
8428 DUK_INTERNAL_DECL duk_bool_t duk_js_getvar_activation(duk_hthread *thr, duk_activation *act, duk_hstring *name, duk_bool_t throw_flag);
8429 DUK_INTERNAL_DECL void duk_js_putvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name, duk_tval *val, duk_bool_t strict);
8430 DUK_INTERNAL_DECL void duk_js_putvar_activation(duk_hthread *thr, duk_activation *act, duk_hstring *name, duk_tval *val, duk_bool_t strict);
8431 #if 0  /*unused*/
8432 DUK_INTERNAL_DECL duk_bool_t duk_js_delvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name);
8433 #endif
8434 DUK_INTERNAL_DECL duk_bool_t duk_js_delvar_activation(duk_hthread *thr, duk_activation *act, duk_hstring *name);
8435 DUK_INTERNAL_DECL duk_bool_t duk_js_declvar_activation(duk_hthread *thr, duk_activation *act, duk_hstring *name, duk_tval *val, duk_small_int_t prop_flags, duk_bool_t is_func_decl);
8436 DUK_INTERNAL_DECL void duk_js_init_activation_environment_records_delayed(duk_hthread *thr, duk_activation *act);
8437 DUK_INTERNAL_DECL void duk_js_close_environment_record(duk_hthread *thr, duk_hobject *env, duk_hobject *func, duk_size_t regbase);
8438 DUK_INTERNAL_DECL duk_hobject *duk_create_activation_environment_record(duk_hthread *thr, duk_hobject *func, duk_size_t idx_bottom);
8439 DUK_INTERNAL_DECL
8440 void duk_js_push_closure(duk_hthread *thr,
8441                          duk_hcompiledfunction *fun_temp,
8442                          duk_hobject *outer_var_env,
8443                          duk_hobject *outer_lex_env,
8444                          duk_bool_t add_auto_proto);
8445 
8446 /* call handling */
8447 DUK_INTERNAL_DECL duk_int_t duk_handle_call_protected(duk_hthread *thr, duk_idx_t num_stack_args, duk_small_uint_t call_flags);
8448 DUK_INTERNAL_DECL void duk_handle_call_unprotected(duk_hthread *thr, duk_idx_t num_stack_args, duk_small_uint_t call_flags);
8449 DUK_INTERNAL_DECL duk_int_t duk_handle_safe_call(duk_hthread *thr, duk_safe_call_function func, duk_idx_t num_stack_args, duk_idx_t num_stack_res);
8450 DUK_INTERNAL_DECL duk_bool_t duk_handle_ecma_call_setup(duk_hthread *thr, duk_idx_t num_stack_args, duk_small_uint_t call_flags);
8451 
8452 /* bytecode execution */
8453 DUK_INTERNAL_DECL void duk_js_execute_bytecode(duk_hthread *exec_thr);
8454 
8455 #endif  /* DUK_JS_H_INCLUDED */
8456 #ifndef DUK_NUMCONV_H_INCLUDED
8457 #define DUK_NUMCONV_H_INCLUDED
8458 
8459 /*
8460  *  Number-to-string conversion.  The semantics of these is very tightly
8461  *  bound with the Ecmascript semantics required for call sites.
8462  */
8463 
8464 /* Output a specified number of digits instead of using the shortest
8465  * form.  Used for toPrecision() and toFixed().
8466  */
8467 #define DUK_N2S_FLAG_FIXED_FORMAT         (1 << 0)
8468 
8469 /* Force exponential format.  Used for toExponential(). */
8470 #define DUK_N2S_FLAG_FORCE_EXP            (1 << 1)
8471 
8472 /* If number would need zero padding (for whole number part), use
8473  * exponential format instead.  E.g. if input number is 12300, 3
8474  * digits are generated ("123"), output "1.23e+4" instead of "12300".
8475  * Used for toPrecision().
8476  */
8477 #define DUK_N2S_FLAG_NO_ZERO_PAD          (1 << 2)
8478 
8479 /* Digit count indicates number of fractions (i.e. an absolute
8480  * digit index instead of a relative one).  Used together with
8481  * DUK_N2S_FLAG_FIXED_FORMAT for toFixed().
8482  */
8483 #define DUK_N2S_FLAG_FRACTION_DIGITS      (1 << 3)
8484 
8485 /*
8486  *  String-to-number conversion
8487  */
8488 
8489 /* Maximum exponent value when parsing numbers.  This is not strictly
8490  * compliant as there should be no upper limit, but as we parse the
8491  * exponent without a bigint, impose some limit.
8492  */
8493 #define DUK_S2N_MAX_EXPONENT              1000000000
8494 
8495 /* Trim white space (= allow leading and trailing whitespace) */
8496 #define DUK_S2N_FLAG_TRIM_WHITE           (1 << 0)
8497 
8498 /* Allow exponent */
8499 #define DUK_S2N_FLAG_ALLOW_EXP            (1 << 1)
8500 
8501 /* Allow trailing garbage (e.g. treat "123foo" as "123) */
8502 #define DUK_S2N_FLAG_ALLOW_GARBAGE        (1 << 2)
8503 
8504 /* Allow leading plus sign */
8505 #define DUK_S2N_FLAG_ALLOW_PLUS           (1 << 3)
8506 
8507 /* Allow leading minus sign */
8508 #define DUK_S2N_FLAG_ALLOW_MINUS          (1 << 4)
8509 
8510 /* Allow 'Infinity' */
8511 #define DUK_S2N_FLAG_ALLOW_INF            (1 << 5)
8512 
8513 /* Allow fraction part */
8514 #define DUK_S2N_FLAG_ALLOW_FRAC           (1 << 6)
8515 
8516 /* Allow naked fraction (e.g. ".123") */
8517 #define DUK_S2N_FLAG_ALLOW_NAKED_FRAC     (1 << 7)
8518 
8519 /* Allow empty fraction (e.g. "123.") */
8520 #define DUK_S2N_FLAG_ALLOW_EMPTY_FRAC     (1 << 8)
8521 
8522 /* Allow empty string to be interpreted as 0 */
8523 #define DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO  (1 << 9)
8524 
8525 /* Allow leading zeroes (e.g. "0123" -> "123") */
8526 #define DUK_S2N_FLAG_ALLOW_LEADING_ZERO   (1 << 10)
8527 
8528 /* Allow automatic detection of hex base ("0x" or "0X" prefix),
8529  * overrides radix argument and forces integer mode.
8530  */
8531 #define DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT   (1 << 11)
8532 
8533 /* Allow automatic detection of octal base, overrides radix
8534  * argument and forces integer mode.
8535  */
8536 #define DUK_S2N_FLAG_ALLOW_AUTO_OCT_INT   (1 << 12)
8537 
8538 /*
8539  *  Prototypes
8540  */
8541 
8542 DUK_INTERNAL_DECL void duk_numconv_stringify(duk_context *ctx, duk_small_int_t radix, duk_small_int_t digits, duk_small_uint_t flags);
8543 DUK_INTERNAL_DECL void duk_numconv_parse(duk_context *ctx, duk_small_int_t radix, duk_small_uint_t flags);
8544 
8545 #endif  /* DUK_NUMCONV_H_INCLUDED */
8546 /*
8547  *  Prototypes for built-in functions not automatically covered by the
8548  *  header declarations emitted by genbuiltins.py.
8549  */
8550 
8551 #ifndef DUK_BUILTIN_PROTOS_H_INCLUDED
8552 #define DUK_BUILTIN_PROTOS_H_INCLUDED
8553 
8554 /* Buffer size needed for duk_bi_date_format_timeval().
8555  * Accurate value is 32 + 1 for NUL termination:
8556  *   >>> len('+123456-01-23T12:34:56.123+12:34')
8557  *   32
8558  * Include additional space to be safe.
8559  */
8560 #define  DUK_BI_DATE_ISO8601_BUFSIZE  48
8561 
8562 /* Maximum length of CommonJS module identifier to resolve.  Length includes
8563  * both current module ID, requested (possibly relative) module ID, and a
8564  * slash in between.
8565  */
8566 #define  DUK_BI_COMMONJS_MODULE_ID_LIMIT  256
8567 
8568 /* Helpers exposed for internal use */
8569 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);
8570 DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_timeval_from_dparts(duk_double_t *dparts, duk_small_uint_t flags);
8571 DUK_INTERNAL_DECL void duk_bi_date_format_timeval(duk_double_t timeval, duk_uint8_t *out_buf);
8572 DUK_INTERNAL_DECL duk_bool_t duk_bi_date_is_leap_year(duk_int_t year);
8573 DUK_INTERNAL_DECL duk_bool_t duk_bi_date_timeval_in_valid_range(duk_double_t x);
8574 DUK_INTERNAL_DECL duk_bool_t duk_bi_date_year_in_valid_range(duk_double_t year);
8575 DUK_INTERNAL_DECL duk_bool_t duk_bi_date_timeval_in_leeway_range(duk_double_t x);
8576 /* Built-in providers */
8577 #if defined(DUK_USE_DATE_NOW_GETTIMEOFDAY)
8578 DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_now_gettimeofday(duk_context *ctx);
8579 #endif
8580 #if defined(DUK_USE_DATE_NOW_TIME)
8581 DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_now_time(duk_context *ctx);
8582 #endif
8583 #if defined(DUK_USE_DATE_NOW_WINDOWS)
8584 DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_now_windows(duk_context *ctx);
8585 #endif
8586 #if defined(DUK_USE_DATE_TZO_GMTIME_R) || defined(DUK_USE_DATE_TZO_GMTIME)
8587 DUK_INTERNAL_DECL duk_int_t duk_bi_date_get_local_tzoffset_gmtime(duk_double_t d);
8588 #endif
8589 #if defined(DUK_USE_DATE_TZO_WINDOWS)
8590 DUK_INTERNAL_DECL duk_int_t duk_bi_date_get_local_tzoffset_windows(duk_double_t d);
8591 #endif
8592 #if defined(DUK_USE_DATE_PRS_STRPTIME)
8593 DUK_INTERNAL_DECL duk_bool_t duk_bi_date_parse_string_strptime(duk_context *ctx, const char *str);
8594 #endif
8595 #if defined(DUK_USE_DATE_PRS_GETDATE)
8596 DUK_INTERNAL_DECL duk_bool_t duk_bi_date_parse_string_getdate(duk_context *ctx, const char *str);
8597 #endif
8598 #if defined(DUK_USE_DATE_FMT_STRFTIME)
8599 DUK_INTERNAL_DECL duk_bool_t duk_bi_date_format_parts_strftime(duk_context *ctx, duk_int_t *parts, duk_int_t tzoffset, duk_small_uint_t flags);
8600 #endif
8601 
8602 DUK_INTERNAL_DECL
8603 void duk_bi_json_parse_helper(duk_context *ctx,
8604                               duk_idx_t idx_value,
8605                               duk_idx_t idx_reviver,
8606                               duk_small_uint_t flags);
8607 DUK_INTERNAL_DECL
8608 void duk_bi_json_stringify_helper(duk_context *ctx,
8609                                   duk_idx_t idx_value,
8610                                   duk_idx_t idx_replacer,
8611                                   duk_idx_t idx_space,
8612                                   duk_small_uint_t flags);
8613 
8614 #endif  /* DUK_BUILTIN_PROTOS_H_INCLUDED */
8615 /*
8616  *  Selftest code
8617  */
8618 
8619 #ifndef DUK_SELFTEST_H_INCLUDED
8620 #define DUK_SELFTEST_H_INCLUDED
8621 
8622 #if defined(DUK_USE_SELF_TESTS)
8623 DUK_INTERNAL_DECL void duk_selftest_run_tests(void);
8624 #endif
8625 
8626 #endif  /* DUK_SELFTEST_H_INCLUDED */
8627 
8628 #endif  /* DUK_INTERNAL_H_INCLUDED */
8629 /*
8630  *  Replacements for missing platform functions.
8631  *
8632  *  Unlike the originals, fpclassify() and signbit() replacements don't
8633  *  work on any floating point types, only doubles.  The C typing here
8634  *  mimics the standard prototypes.
8635  */
8636 
8637 /* include removed: duk_internal.h */
8638 
8639 #if defined(DUK_USE_COMPUTED_NAN)
8640 DUK_INTERNAL double duk_computed_nan;
8641 #endif
8642 
8643 #if defined(DUK_USE_COMPUTED_INFINITY)
8644 DUK_INTERNAL double duk_computed_infinity;
8645 #endif
8646 
8647 #if defined(DUK_USE_REPL_FPCLASSIFY)
duk_repl_fpclassify(double x)8648 DUK_INTERNAL int duk_repl_fpclassify(double x) {
8649 	duk_double_union u;
8650 	duk_uint_fast16_t expt;
8651 	duk_small_int_t mzero;
8652 
8653 	u.d = x;
8654 	expt = (duk_uint_fast16_t) (u.us[DUK_DBL_IDX_US0] & 0x7ff0UL);
8655 	if (expt > 0x0000UL && expt < 0x7ff0UL) {
8656 		/* expt values [0x001,0x7fe] = normal */
8657 		return DUK_FP_NORMAL;
8658 	}
8659 
8660 	mzero = (u.ui[DUK_DBL_IDX_UI1] == 0 && (u.ui[DUK_DBL_IDX_UI0] & 0x000fffffUL) == 0);
8661 	if (expt == 0x0000UL) {
8662 		/* expt 0x000 is zero/subnormal */
8663 		if (mzero) {
8664 			return DUK_FP_ZERO;
8665 		} else {
8666 			return DUK_FP_SUBNORMAL;
8667 		}
8668 	} else {
8669 		/* expt 0xfff is infinite/nan */
8670 		if (mzero) {
8671 			return DUK_FP_INFINITE;
8672 		} else {
8673 			return DUK_FP_NAN;
8674 		}
8675 	}
8676 }
8677 #endif
8678 
8679 #if defined(DUK_USE_REPL_SIGNBIT)
duk_repl_signbit(double x)8680 DUK_INTERNAL int duk_repl_signbit(double x) {
8681 	duk_double_union u;
8682 	u.d = x;
8683 	return (int) (u.uc[DUK_DBL_IDX_UC0] & 0x80UL);
8684 }
8685 #endif
8686 
8687 #if defined(DUK_USE_REPL_ISFINITE)
duk_repl_isfinite(double x)8688 DUK_INTERNAL int duk_repl_isfinite(double x) {
8689 	int c = DUK_FPCLASSIFY(x);
8690 	if (c == DUK_FP_NAN || c == DUK_FP_INFINITE) {
8691 		return 0;
8692 	} else {
8693 		return 1;
8694 	}
8695 }
8696 #endif
8697 
8698 #if defined(DUK_USE_REPL_ISNAN)
duk_repl_isnan(double x)8699 DUK_INTERNAL int duk_repl_isnan(double x) {
8700 	int c = DUK_FPCLASSIFY(x);
8701 	return (c == DUK_FP_NAN);
8702 }
8703 #endif
8704 
8705 #if defined(DUK_USE_REPL_ISINF)
duk_repl_isinf(double x)8706 DUK_INTERNAL int duk_repl_isinf(double x) {
8707 	int c = DUK_FPCLASSIFY(x);
8708 	return (c == DUK_FP_INFINITE);
8709 }
8710 #endif
8711 /*
8712  *  Shared error message strings
8713  *
8714  *  To minimize code footprint, try to share error messages inside Duktape
8715  *  code.  Modern compilers will do this automatically anyway, this is mostly
8716  *  for older compilers.
8717  */
8718 
8719 /* include removed: duk_internal.h */
8720 
8721 /* Mostly API and built-in method related */
8722 DUK_INTERNAL const char *duk_str_internal_error = "internal error";
8723 DUK_INTERNAL const char *duk_str_invalid_count = "invalid count";
8724 DUK_INTERNAL const char *duk_str_invalid_call_args = "invalid call args";
8725 DUK_INTERNAL const char *duk_str_not_constructable = "not constructable";
8726 DUK_INTERNAL const char *duk_str_not_callable = "not callable";
8727 DUK_INTERNAL const char *duk_str_not_extensible = "not extensible";
8728 DUK_INTERNAL const char *duk_str_not_writable = "not writable";
8729 DUK_INTERNAL const char *duk_str_not_configurable = "not configurable";
8730 
8731 DUK_INTERNAL const char *duk_str_invalid_context = "invalid context";
8732 DUK_INTERNAL const char *duk_str_push_beyond_alloc_stack = "attempt to push beyond currently allocated stack";
8733 DUK_INTERNAL const char *duk_str_not_buffer = "not buffer";  /* still in use with verbose messages */
8734 DUK_INTERNAL const char *duk_str_unexpected_type = "unexpected type";
8735 DUK_INTERNAL const char *duk_str_defaultvalue_coerce_failed = "[[DefaultValue]] coerce failed";
8736 DUK_INTERNAL const char *duk_str_number_outside_range = "number outside range";
8737 DUK_INTERNAL const char *duk_str_not_object_coercible = "not object coercible";
8738 DUK_INTERNAL const char *duk_str_string_too_long = "string too long";
8739 DUK_INTERNAL const char *duk_str_buffer_too_long = "buffer too long";
8740 DUK_INTERNAL const char *duk_str_sprintf_too_long = "sprintf message too long";
8741 DUK_INTERNAL const char *duk_str_alloc_failed = "alloc failed";
8742 DUK_INTERNAL const char *duk_str_pop_too_many = "attempt to pop too many entries";
8743 DUK_INTERNAL const char *duk_str_wrong_buffer_type = "wrong buffer type";
8744 DUK_INTERNAL const char *duk_str_encode_failed = "encode failed";
8745 DUK_INTERNAL const char *duk_str_decode_failed = "decode failed";
8746 DUK_INTERNAL const char *duk_str_no_sourcecode = "no sourcecode";
8747 DUK_INTERNAL const char *duk_str_concat_result_too_long = "concat result too long";
8748 DUK_INTERNAL const char *duk_str_unimplemented = "unimplemented";
8749 DUK_INTERNAL const char *duk_str_unsupported = "unsupported";
8750 DUK_INTERNAL const char *duk_str_array_length_over_2g = "array length over 2G";
8751 
8752 /* JSON */
8753 DUK_INTERNAL const char *duk_str_fmt_ptr = "%p";
8754 DUK_INTERNAL const char *duk_str_fmt_invalid_json = "invalid json (at offset %ld)";
8755 DUK_INTERNAL const char *duk_str_jsondec_reclimit = "json decode recursion limit";
8756 DUK_INTERNAL const char *duk_str_jsonenc_reclimit = "json encode recursion limit";
8757 DUK_INTERNAL const char *duk_str_cyclic_input = "cyclic input";
8758 
8759 /* Object property access */
8760 DUK_INTERNAL const char *duk_str_proxy_revoked = "proxy revoked";
8761 DUK_INTERNAL const char *duk_str_invalid_base = "invalid base value";
8762 DUK_INTERNAL const char *duk_str_strict_caller_read = "attempt to read strict 'caller'";
8763 DUK_INTERNAL const char *duk_str_proxy_rejected = "proxy rejected";
8764 DUK_INTERNAL const char *duk_str_invalid_array_length = "invalid array length";
8765 DUK_INTERNAL const char *duk_str_array_length_write_failed = "array length write failed";
8766 DUK_INTERNAL const char *duk_str_array_length_not_writable = "array length non-writable";
8767 DUK_INTERNAL const char *duk_str_setter_undefined = "setter undefined";
8768 DUK_INTERNAL const char *duk_str_redefine_virt_prop = "attempt to redefine virtual property";
8769 DUK_INTERNAL const char *duk_str_invalid_descriptor = "invalid descriptor";
8770 DUK_INTERNAL const char *duk_str_property_is_virtual = "property is virtual";
8771 
8772 /* Compiler */
8773 DUK_INTERNAL const char *duk_str_parse_error = "parse error";
8774 DUK_INTERNAL const char *duk_str_duplicate_label = "duplicate label";
8775 DUK_INTERNAL const char *duk_str_invalid_label = "invalid label";
8776 DUK_INTERNAL const char *duk_str_invalid_array_literal = "invalid array literal";
8777 DUK_INTERNAL const char *duk_str_invalid_object_literal = "invalid object literal";
8778 DUK_INTERNAL const char *duk_str_invalid_var_declaration = "invalid variable declaration";
8779 DUK_INTERNAL const char *duk_str_cannot_delete_identifier = "cannot delete identifier";
8780 DUK_INTERNAL const char *duk_str_invalid_expression = "invalid expression";
8781 DUK_INTERNAL const char *duk_str_invalid_lvalue = "invalid lvalue";
8782 DUK_INTERNAL const char *duk_str_expected_identifier = "expected identifier";
8783 DUK_INTERNAL const char *duk_str_empty_expr_not_allowed = "empty expression not allowed";
8784 DUK_INTERNAL const char *duk_str_invalid_for = "invalid for statement";
8785 DUK_INTERNAL const char *duk_str_invalid_switch = "invalid switch statement";
8786 DUK_INTERNAL const char *duk_str_invalid_break_cont_label = "invalid break/continue label";
8787 DUK_INTERNAL const char *duk_str_invalid_return = "invalid return";
8788 DUK_INTERNAL const char *duk_str_invalid_try = "invalid try";
8789 DUK_INTERNAL const char *duk_str_invalid_throw = "invalid throw";
8790 DUK_INTERNAL const char *duk_str_with_in_strict_mode = "with in strict mode";
8791 DUK_INTERNAL const char *duk_str_func_stmt_not_allowed = "function statement not allowed";
8792 DUK_INTERNAL const char *duk_str_unterminated_stmt = "unterminated statement";
8793 DUK_INTERNAL const char *duk_str_invalid_arg_name = "invalid argument name";
8794 DUK_INTERNAL const char *duk_str_invalid_func_name = "invalid function name";
8795 DUK_INTERNAL const char *duk_str_invalid_getset_name = "invalid getter/setter name";
8796 DUK_INTERNAL const char *duk_str_func_name_required = "function name required";
8797 
8798 /* Regexp */
8799 DUK_INTERNAL const char *duk_str_invalid_quantifier_no_atom = "quantifier without preceding atom";
8800 DUK_INTERNAL const char *duk_str_invalid_quantifier_values = "quantifier values invalid (qmin > qmax)";
8801 DUK_INTERNAL const char *duk_str_quantifier_too_many_copies = "quantifier expansion requires too many atom copies";
8802 DUK_INTERNAL const char *duk_str_unexpected_closing_paren = "unexpected closing parenthesis";
8803 DUK_INTERNAL const char *duk_str_unexpected_end_of_pattern = "unexpected end of pattern";
8804 DUK_INTERNAL const char *duk_str_unexpected_regexp_token = "unexpected token in regexp";
8805 DUK_INTERNAL const char *duk_str_invalid_regexp_flags = "invalid regexp flags";
8806 DUK_INTERNAL const char *duk_str_invalid_backrefs = "invalid backreference(s)";
8807 
8808 /* Limits */
8809 DUK_INTERNAL const char *duk_str_valstack_limit = "valstack limit";
8810 DUK_INTERNAL const char *duk_str_callstack_limit = "callstack limit";
8811 DUK_INTERNAL const char *duk_str_catchstack_limit = "catchstack limit";
8812 DUK_INTERNAL const char *duk_str_prototype_chain_limit = "prototype chain limit";
8813 DUK_INTERNAL const char *duk_str_bound_chain_limit = "function call bound chain limit";
8814 DUK_INTERNAL const char *duk_str_c_callstack_limit = "C call stack depth limit";
8815 DUK_INTERNAL const char *duk_str_compiler_recursion_limit = "compiler recursion limit";
8816 DUK_INTERNAL const char *duk_str_bytecode_limit = "bytecode limit";
8817 DUK_INTERNAL const char *duk_str_reg_limit = "register limit";
8818 DUK_INTERNAL const char *duk_str_temp_limit = "temp limit";
8819 DUK_INTERNAL const char *duk_str_const_limit = "const limit";
8820 DUK_INTERNAL const char *duk_str_func_limit = "function limit";
8821 DUK_INTERNAL const char *duk_str_regexp_compiler_recursion_limit = "regexp compiler recursion limit";
8822 DUK_INTERNAL const char *duk_str_regexp_executor_recursion_limit = "regexp executor recursion limit";
8823 DUK_INTERNAL const char *duk_str_regexp_executor_step_limit = "regexp step limit";
8824 
8825 /* Misc */
8826 /*
8827  *  Debugging macro calls.
8828  */
8829 
8830 /* include removed: duk_internal.h */
8831 
8832 #ifdef DUK_USE_DEBUG
8833 
8834 /*
8835  *  Debugging enabled
8836  */
8837 
8838 #include <stdio.h>
8839 #include <stdlib.h>
8840 #include <stdarg.h>
8841 
8842 #define DUK__DEBUG_BUFSIZE  DUK_USE_DEBUG_BUFSIZE
8843 DUK_LOCAL char duk__debug_buf[DUK__DEBUG_BUFSIZE];
8844 
duk__get_level_string(duk_small_int_t level)8845 DUK_LOCAL const char *duk__get_level_string(duk_small_int_t level) {
8846 	switch ((int) level) {
8847 	case DUK_LEVEL_DEBUG:
8848 		return "D";
8849 	case DUK_LEVEL_DDEBUG:
8850 		return "DD";
8851 	case DUK_LEVEL_DDDEBUG:
8852 		return "DDD";
8853 	}
8854 	return "???";
8855 }
8856 
8857 #ifdef DUK_USE_DPRINT_COLORS
8858 
8859 /* http://en.wikipedia.org/wiki/ANSI_escape_code */
8860 #define DUK__TERM_REVERSE  "\x1b[7m"
8861 #define DUK__TERM_BRIGHT   "\x1b[1m"
8862 #define DUK__TERM_RESET    "\x1b[0m"
8863 #define DUK__TERM_BLUE     "\x1b[34m"
8864 #define DUK__TERM_RED      "\x1b[31m"
8865 
duk__get_term_1(duk_small_int_t level)8866 DUK_LOCAL const char *duk__get_term_1(duk_small_int_t level) {
8867 	DUK_UNREF(level);
8868 	return (const char *) DUK__TERM_RED;
8869 }
8870 
duk__get_term_2(duk_small_int_t level)8871 DUK_LOCAL const char *duk__get_term_2(duk_small_int_t level) {
8872 	switch ((int) level) {
8873 	case DUK_LEVEL_DEBUG:
8874 		return (const char *) (DUK__TERM_RESET DUK__TERM_BRIGHT);
8875 	case DUK_LEVEL_DDEBUG:
8876 		return (const char *) (DUK__TERM_RESET);
8877 	case DUK_LEVEL_DDDEBUG:
8878 		return (const char *) (DUK__TERM_RESET DUK__TERM_BLUE);
8879 	}
8880 	return (const char *) DUK__TERM_RESET;
8881 }
8882 
duk__get_term_3(duk_small_int_t level)8883 DUK_LOCAL const char *duk__get_term_3(duk_small_int_t level) {
8884 	DUK_UNREF(level);
8885 	return (const char *) DUK__TERM_RESET;
8886 }
8887 
8888 #else
8889 
duk__get_term_1(duk_small_int_t level)8890 DUK_LOCAL const char *duk__get_term_1(duk_small_int_t level) {
8891 	DUK_UNREF(level);
8892 	return (const char *) "";
8893 }
8894 
duk__get_term_2(duk_small_int_t level)8895 DUK_LOCAL const char *duk__get_term_2(duk_small_int_t level) {
8896 	DUK_UNREF(level);
8897 	return (const char *) "";
8898 }
8899 
duk__get_term_3(duk_small_int_t level)8900 DUK_LOCAL const char *duk__get_term_3(duk_small_int_t level) {
8901 	DUK_UNREF(level);
8902 	return (const char *) "";
8903 }
8904 
8905 #endif  /* DUK_USE_DPRINT_COLORS */
8906 
8907 #ifdef DUK_USE_VARIADIC_MACROS
8908 
duk_debug_log(duk_small_int_t level,const char * file,duk_int_t line,const char * func,const char * fmt,...)8909 DUK_INTERNAL void duk_debug_log(duk_small_int_t level, const char *file, duk_int_t line, const char *func, const char *fmt, ...) {
8910 	va_list ap;
8911 
8912 	va_start(ap, fmt);
8913 
8914 	DUK_MEMZERO((void *) duk__debug_buf, (size_t) DUK__DEBUG_BUFSIZE);
8915 	duk_debug_vsnprintf(duk__debug_buf, DUK__DEBUG_BUFSIZE - 1, fmt, ap);
8916 
8917 	DUK_FPRINTF(DUK_STDERR, "%s[%s] %s:%ld (%s):%s %s%s\n",
8918 	            (const char *) duk__get_term_1(level),
8919 	            (const char *) duk__get_level_string(level),
8920 	            (const char *) file,
8921 	            (long) line,
8922 	            (const char *) func,
8923 	            (const char *) duk__get_term_2(level),
8924 	            (const char *) duk__debug_buf,
8925 	            (const char *) duk__get_term_3(level));
8926 	DUK_FFLUSH(DUK_STDERR);
8927 
8928 	va_end(ap);
8929 }
8930 
8931 #else  /* DUK_USE_VARIADIC_MACROS */
8932 
8933 DUK_INTERNAL char duk_debug_file_stash[DUK_DEBUG_STASH_SIZE];
8934 DUK_INTERNAL char duk_debug_line_stash[DUK_DEBUG_STASH_SIZE];
8935 DUK_INTERNAL char duk_debug_func_stash[DUK_DEBUG_STASH_SIZE];
8936 DUK_INTERNAL duk_small_int_t duk_debug_level_stash;
8937 
duk_debug_log(const char * fmt,...)8938 DUK_INTERNAL void duk_debug_log(const char *fmt, ...) {
8939 	va_list ap;
8940 	duk_small_int_t level = duk_debug_level_stash;
8941 
8942 	va_start(ap, fmt);
8943 
8944 	DUK_MEMZERO((void *) duk__debug_buf, (size_t) DUK__DEBUG_BUFSIZE);
8945 	duk_debug_vsnprintf(duk__debug_buf, DUK__DEBUG_BUFSIZE - 1, fmt, ap);
8946 
8947 	DUK_FPRINTF(DUK_STDERR, "%s[%s] %s:%s (%s):%s %s%s\n",
8948 	            (const char *) duk__get_term_1(level),
8949 	            (const char *) duk__get_level_string(duk_debug_level_stash),
8950 	            (const char *) duk_debug_file_stash,
8951 	            (const char *) duk_debug_line_stash,
8952 	            (const char *) duk_debug_func_stash,
8953 	            (const char *) duk__get_term_2(level),
8954 	            (const char *) duk__debug_buf,
8955 	            (const char *) duk__get_term_3(level));
8956 	DUK_FFLUSH(DUK_STDERR);
8957 
8958 	va_end(ap);
8959 }
8960 
8961 #endif  /* DUK_USE_VARIADIC_MACROS */
8962 
8963 #else  /* DUK_USE_DEBUG */
8964 
8965 /*
8966  *  Debugging disabled
8967  */
8968 
8969 #endif  /* DUK_USE_DEBUG */
8970 /*
8971  *  Automatically generated by genbuiltins.py, do not edit!
8972  */
8973 
8974 /* include removed: duk_internal.h */
8975 
8976 #if defined(DUK_USE_ROM_STRINGS)
8977 #error ROM support not enabled, rerun make_dist.py with --rom-support
8978 #else  /* DUK_USE_ROM_STRINGS */
8979 DUK_INTERNAL const duk_uint8_t duk_strings_data[1049] = {
8980 79,104,209,144,168,105,6,78,182,139,90,122,8,154,140,35,103,35,117,193,73,
8981 5,52,116,180,104,166,135,52,189,4,98,12,27,178,156,80,211,31,161,115,150,
8982 64,52,221,109,24,18,68,157,24,38,67,118,36,55,73,119,151,164,140,93,18,117,
8983 128,153,201,228,201,205,2,250,8,196,24,232,104,82,146,40,232,193,48,118,
8984 168,37,147,212,54,127,113,208,70,32,194,187,68,54,127,113,208,70,32,196,
8985 123,68,54,127,113,209,44,12,121,7,208,70,32,194,186,134,207,236,126,219,
8986 160,140,65,133,246,136,108,254,199,237,186,8,196,24,87,80,217,253,159,217,
8987 116,17,136,48,190,209,13,159,217,253,151,65,24,131,12,233,86,224,79,236,
8988 254,203,160,140,65,134,116,171,112,39,246,223,105,208,70,32,193,140,183,4,
8989 11,55,92,20,244,141,169,186,50,11,164,109,77,208,208,165,36,79,215,185,13,
8990 153,34,110,204,241,32,6,66,84,11,112,200,84,52,157,124,92,242,70,120,45,64,
8991 186,17,22,138,38,0,172,140,19,154,84,26,145,0,86,69,17,180,97,34,0,172,132,
8992 75,144,215,77,221,91,132,5,147,178,156,80,211,30,160,93,9,215,21,115,119,
8993 169,49,75,211,138,26,101,205,222,68,157,47,78,40,105,151,55,120,204,156,
8994 189,56,161,166,52,157,72,136,138,65,154,232,147,162,4,136,150,81,115,66,
8995 208,210,37,96,148,250,134,140,151,39,212,125,255,221,125,73,80,209,146,233,
8996 124,93,55,79,15,34,196,230,202,113,160,166,232,157,132,148,128,98,28,46,
8997 114,200,6,153,180,96,73,19,74,113,67,76,103,5,36,20,211,70,140,133,67,72,
8998 49,245,160,235,81,212,52,168,106,39,132,253,111,80,210,161,168,158,5,245,
8999 191,96,31,172,15,208,23,226,190,131,232,62,131,232,11,251,127,93,245,223,
9000 93,251,172,234,27,80,45,3,250,14,140,19,34,65,19,81,132,108,228,97,1,107,
9001 33,12,32,45,100,136,206,9,12,196,155,134,69,146,100,235,226,231,146,51,194,
9002 72,218,48,145,4,200,119,89,189,81,49,39,72,147,235,226,233,186,120,121,58,
9003 226,167,90,124,93,55,107,71,137,33,68,68,130,64,206,75,189,209,156,144,84,
9004 44,141,3,8,137,187,178,156,80,211,26,110,242,100,230,146,120,121,8,48,76,6,
9005 89,26,105,157,65,196,201,213,145,166,153,212,28,76,157,113,75,34,78,62,14,
9006 38,73,105,228,142,136,178,48,141,152,228,73,150,83,0,148,39,137,75,67,73,
9007 214,209,129,36,85,190,206,32,17,6,9,128,141,3,8,130,161,100,235,64,194,24,
9008 52,41,73,19,189,200,108,201,19,111,181,2,232,66,239,173,37,230,157,244,56,
9009 153,4,225,145,27,233,93,22,1,114,62,251,80,69,128,121,247,213,146,228,109,
9010 79,190,212,17,35,106,125,246,78,164,68,68,111,175,23,217,45,13,33,119,208,
9011 68,210,38,250,192,61,91,233,80,208,45,25,36,81,190,156,13,26,201,19,239,
9012 162,2,214,66,31,125,153,226,64,13,27,236,72,96,130,68,62,251,48,68,196,153,
9013 119,217,157,18,56,156,199,161,100,42,26,250,77,36,140,122,40,144,19,34,9,
9014 24,246,103,139,172,150,56,125,145,1,17,29,44,112,250,183,0,100,24,200,218,
9015 140,228,185,130,9,19,237,190,208,73,184,146,35,68,146,163,8,50,178,99,136,
9016 44,89,196,2,33,70,64,208,196,67,74,226,88,17,105,73,24,186,37,40,38,5,133,
9017 161,89,4,183,25,115,119,86,227,118,83,138,26,103,255,223,209,106,141,25,11,
9018 244,95,117,56,208,159,250,223,251,250,45,52,13,250,47,186,156,104,79,253,
9019 111,253,253,22,144,210,253,23,221,78,52,39,254,187,254,254,139,77,67,75,
9020 244,95,117,56,208,159,250,239,251,250,45,22,141,23,209,125,212,227,66,127,
9021 235,63,239,69,163,69,247,83,141,9,255,165,12,72,5,16,64,145,10,32,76,71,64,
9022 156,217,161,180,34,6,64,208,198,36,78,50,20,20,92,204,50,44,147,32,134,226,
9023 17,114,33,202,134,129,107,192,202,232,160,180,104,166,135,52,72,40,144,213,
9024 33,178,152,26,34,56,163,105,44,104,146,116,139,77,43,34,98,57,38,116,72,
9025 179,60,93,97,206,56,52,240,242,56,163,168,34,81,57,178,153,42,228,12,182,
9026 58,22,66,89,19,57,68,176,74,68,35,104,195,18,239,116,102,114,94,100,104,
9027 228,100,49,238,140,203,42,60,145,35,104,181,146,113,161,10,80,46,68,82,24,
9028 245,145,132,108,228,148,54,100,137,64,34,13,100,153,222,1,40,6,33,223,20,
9029 84,19,34,95,23,76,130,153,6,103,208,43,64,141,41,130,104,17,112,130,44,96,
9030 };
9031 #endif  /* DUK_USE_ROM_STRINGS */
9032 
9033 #if defined(DUK_USE_ROM_OBJECTS)
9034 #error ROM support not enabled, rerun make_dist.py with --rom-support
9035 #else  /* DUK_USE_ROM_OBJECTS */
9036 /* native functions: 149 */
9037 DUK_INTERNAL const duk_c_function duk_bi_native_functions[149] = {
9038 	duk_bi_array_constructor,
9039 	duk_bi_array_constructor_is_array,
9040 	duk_bi_array_prototype_concat,
9041 	duk_bi_array_prototype_indexof_shared,
9042 	duk_bi_array_prototype_iter_shared,
9043 	duk_bi_array_prototype_join_shared,
9044 	duk_bi_array_prototype_pop,
9045 	duk_bi_array_prototype_push,
9046 	duk_bi_array_prototype_reduce_shared,
9047 	duk_bi_array_prototype_reverse,
9048 	duk_bi_array_prototype_shift,
9049 	duk_bi_array_prototype_slice,
9050 	duk_bi_array_prototype_sort,
9051 	duk_bi_array_prototype_splice,
9052 	duk_bi_array_prototype_to_string,
9053 	duk_bi_array_prototype_unshift,
9054 	duk_bi_arraybuffer_constructor,
9055 	duk_bi_arraybuffer_isview,
9056 	duk_bi_boolean_constructor,
9057 	duk_bi_boolean_prototype_tostring_shared,
9058 	duk_bi_buffer_compare_shared,
9059 	duk_bi_buffer_constructor,
9060 	duk_bi_buffer_prototype_tostring_shared,
9061 	duk_bi_buffer_readfield,
9062 	duk_bi_buffer_slice_shared,
9063 	duk_bi_buffer_writefield,
9064 	duk_bi_dataview_constructor,
9065 	duk_bi_date_constructor,
9066 	duk_bi_date_constructor_now,
9067 	duk_bi_date_constructor_parse,
9068 	duk_bi_date_constructor_utc,
9069 	duk_bi_date_prototype_get_shared,
9070 	duk_bi_date_prototype_get_timezone_offset,
9071 	duk_bi_date_prototype_set_shared,
9072 	duk_bi_date_prototype_set_time,
9073 	duk_bi_date_prototype_to_json,
9074 	duk_bi_date_prototype_tostring_shared,
9075 	duk_bi_date_prototype_value_of,
9076 	duk_bi_duktape_object_act,
9077 	duk_bi_duktape_object_compact,
9078 	duk_bi_duktape_object_dec,
9079 	duk_bi_duktape_object_enc,
9080 	duk_bi_duktape_object_fin,
9081 	duk_bi_duktape_object_gc,
9082 	duk_bi_duktape_object_info,
9083 	duk_bi_error_constructor_shared,
9084 	duk_bi_error_prototype_filename_getter,
9085 	duk_bi_error_prototype_filename_setter,
9086 	duk_bi_error_prototype_linenumber_getter,
9087 	duk_bi_error_prototype_linenumber_setter,
9088 	duk_bi_error_prototype_stack_getter,
9089 	duk_bi_error_prototype_stack_setter,
9090 	duk_bi_error_prototype_to_string,
9091 	duk_bi_function_constructor,
9092 	duk_bi_function_prototype,
9093 	duk_bi_function_prototype_apply,
9094 	duk_bi_function_prototype_bind,
9095 	duk_bi_function_prototype_call,
9096 	duk_bi_function_prototype_to_string,
9097 	duk_bi_global_object_decode_uri,
9098 	duk_bi_global_object_decode_uri_component,
9099 	duk_bi_global_object_encode_uri,
9100 	duk_bi_global_object_encode_uri_component,
9101 	duk_bi_global_object_escape,
9102 	duk_bi_global_object_eval,
9103 	duk_bi_global_object_is_finite,
9104 	duk_bi_global_object_is_nan,
9105 	duk_bi_global_object_parse_float,
9106 	duk_bi_global_object_parse_int,
9107 	duk_bi_global_object_print_helper,
9108 	duk_bi_global_object_require,
9109 	duk_bi_global_object_unescape,
9110 	duk_bi_json_object_parse,
9111 	duk_bi_json_object_stringify,
9112 	duk_bi_logger_constructor,
9113 	duk_bi_logger_prototype_fmt,
9114 	duk_bi_logger_prototype_log_shared,
9115 	duk_bi_logger_prototype_raw,
9116 	duk_bi_math_object_max,
9117 	duk_bi_math_object_min,
9118 	duk_bi_math_object_onearg_shared,
9119 	duk_bi_math_object_random,
9120 	duk_bi_math_object_twoarg_shared,
9121 	duk_bi_nodejs_buffer_byte_length,
9122 	duk_bi_nodejs_buffer_concat,
9123 	duk_bi_nodejs_buffer_constructor,
9124 	duk_bi_nodejs_buffer_copy,
9125 	duk_bi_nodejs_buffer_fill,
9126 	duk_bi_nodejs_buffer_is_buffer,
9127 	duk_bi_nodejs_buffer_is_encoding,
9128 	duk_bi_nodejs_buffer_tojson,
9129 	duk_bi_nodejs_buffer_tostring,
9130 	duk_bi_nodejs_buffer_write,
9131 	duk_bi_number_constructor,
9132 	duk_bi_number_prototype_to_exponential,
9133 	duk_bi_number_prototype_to_fixed,
9134 	duk_bi_number_prototype_to_locale_string,
9135 	duk_bi_number_prototype_to_precision,
9136 	duk_bi_number_prototype_to_string,
9137 	duk_bi_number_prototype_value_of,
9138 	duk_bi_object_constructor,
9139 	duk_bi_object_constructor_create,
9140 	duk_bi_object_constructor_define_properties,
9141 	duk_bi_object_constructor_define_property,
9142 	duk_bi_object_constructor_get_own_property_descriptor,
9143 	duk_bi_object_constructor_is_extensible,
9144 	duk_bi_object_constructor_is_sealed_frozen_shared,
9145 	duk_bi_object_constructor_keys_shared,
9146 	duk_bi_object_constructor_prevent_extensions,
9147 	duk_bi_object_constructor_seal_freeze_shared,
9148 	duk_bi_object_getprototype_shared,
9149 	duk_bi_object_prototype_has_own_property,
9150 	duk_bi_object_prototype_is_prototype_of,
9151 	duk_bi_object_prototype_property_is_enumerable,
9152 	duk_bi_object_prototype_to_locale_string,
9153 	duk_bi_object_prototype_to_string,
9154 	duk_bi_object_prototype_value_of,
9155 	duk_bi_object_setprototype_shared,
9156 	duk_bi_pointer_constructor,
9157 	duk_bi_pointer_prototype_tostring_shared,
9158 	duk_bi_proxy_constructor,
9159 	duk_bi_regexp_constructor,
9160 	duk_bi_regexp_prototype_exec,
9161 	duk_bi_regexp_prototype_test,
9162 	duk_bi_regexp_prototype_to_string,
9163 	duk_bi_string_constructor,
9164 	duk_bi_string_constructor_from_char_code,
9165 	duk_bi_string_prototype_caseconv_shared,
9166 	duk_bi_string_prototype_char_at,
9167 	duk_bi_string_prototype_char_code_at,
9168 	duk_bi_string_prototype_concat,
9169 	duk_bi_string_prototype_indexof_shared,
9170 	duk_bi_string_prototype_locale_compare,
9171 	duk_bi_string_prototype_match,
9172 	duk_bi_string_prototype_replace,
9173 	duk_bi_string_prototype_search,
9174 	duk_bi_string_prototype_slice,
9175 	duk_bi_string_prototype_split,
9176 	duk_bi_string_prototype_substr,
9177 	duk_bi_string_prototype_substring,
9178 	duk_bi_string_prototype_to_string,
9179 	duk_bi_string_prototype_trim,
9180 	duk_bi_thread_constructor,
9181 	duk_bi_thread_current,
9182 	duk_bi_thread_resume,
9183 	duk_bi_thread_yield,
9184 	duk_bi_type_error_thrower,
9185 	duk_bi_typedarray_constructor,
9186 	duk_bi_typedarray_set,
9187 };
9188 #if defined(DUK_USE_BUILTIN_INITJS)
9189 DUK_INTERNAL const duk_uint8_t duk_initjs_data[204] = {
9190 40,102,117,110,99,116,105,111,110,40,100,44,97,41,123,102,117,110,99,116,
9191 105,111,110,32,98,40,97,44,98,44,99,41,123,79,98,106,101,99,116,46,100,101,
9192 102,105,110,101,80,114,111,112,101,114,116,121,40,97,44,98,44,123,118,97,
9193 108,117,101,58,99,44,119,114,105,116,97,98,108,101,58,33,48,44,101,110,117,
9194 109,101,114,97,98,108,101,58,33,49,44,99,111,110,102,105,103,117,114,97,98,
9195 108,101,58,33,48,125,41,125,98,40,97,46,76,111,103,103,101,114,44,34,99,
9196 108,111,103,34,44,110,101,119,32,97,46,76,111,103,103,101,114,40,34,67,34,
9197 41,41,59,98,40,97,44,34,109,111,100,76,111,97,100,101,100,34,44,79,98,106,
9198 101,99,116,46,99,114,101,97,116,101,40,110,117,108,108,41,41,125,41,40,116,
9199 104,105,115,44,68,117,107,116,97,112,101,41,59,10,0,
9200 };
9201 #endif  /* DUK_USE_BUILTIN_INITJS */
9202 #if defined(DUK_USE_DOUBLE_LE)
9203 DUK_INTERNAL const duk_uint8_t duk_builtins_data[3833] = {
9204 105,195,75,32,3,148,52,154,248,9,26,13,128,112,105,0,240,22,20,26,95,124,6,
9205 152,52,137,0,120,99,74,239,129,18,70,241,191,2,98,13,79,32,42,88,210,90,2,
9206 240,1,50,141,37,168,76,94,216,118,69,229,203,127,44,0,84,163,73,106,21,75,
9207 14,236,249,98,242,229,191,150,0,46,81,164,181,14,165,151,54,94,89,119,99,
9208 203,23,151,45,252,176,1,146,141,37,168,93,63,59,186,97,241,23,151,45,252,
9209 176,1,178,141,37,168,77,79,60,50,197,229,203,127,44,0,116,163,73,106,17,86,
9210 148,152,188,185,111,229,128,15,148,129,198,137,36,58,166,142,91,251,212,
9211 243,195,44,94,92,183,242,13,79,8,45,14,91,252,121,148,52,199,120,63,72,105,
9212 21,240,118,128,210,237,224,245,17,165,43,224,211,55,231,207,151,148,161,70,
9213 145,0,31,40,107,26,2,18,138,26,228,192,142,0,16,161,174,76,9,74,26,228,192,
9214 158,0,8,161,174,76,10,96,2,42,26,228,192,174,0,26,161,174,76,11,96,3,74,26,
9215 228,192,190,0,44,161,174,76,12,96,3,202,26,228,192,206,0,70,161,169,84,14,
9216 202,3,255,254,32,234,0,0,0,0,0,0,7,195,248,119,0,0,0,0,0,0,3,193,252,57,
9217 136,1,152,32,16,194,0,166,24,6,49,0,57,138,2,12,96,18,99,128,163,32,5,153,
9218 40,76,94,216,118,69,229,203,127,35,41,10,165,135,118,124,177,121,114,223,
9219 200,203,67,169,101,205,151,150,93,216,242,197,229,203,127,35,49,11,167,231,
9220 119,76,62,34,242,229,191,145,154,132,212,243,195,44,94,92,183,242,51,144,
9221 138,180,164,197,229,203,127,35,60,6,26,0,52,208,193,226,117,215,211,15,12,
9222 166,146,11,67,150,255,30,77,24,58,113,64,243,92,8,27,0,68,217,130,70,212,
9223 19,54,224,161,185,5,77,216,44,111,65,115,126,12,28,16,100,225,156,16,32,18,
9224 17,195,15,46,121,100,238,232,136,136,87,12,60,185,229,141,179,126,30,136,
9225 100,130,233,231,59,12,228,34,66,52,243,141,167,118,158,153,80,73,9,201,151,
9226 30,252,153,106,210,146,118,72,150,76,184,247,228,203,86,148,152,123,246,
9227 240,223,187,46,238,135,132,132,229,221,143,126,76,181,105,73,61,36,75,46,
9228 236,123,242,101,171,74,76,61,251,120,111,221,151,119,67,226,65,178,243,199,
9229 135,134,83,242,66,58,238,203,207,30,30,25,81,201,5,225,203,78,238,136,163,
9230 208,92,59,50,242,232,138,62,0,2,38,163,19,255,255,224,142,80,192,0,20,31,
9231 240,14,135,103,203,210,135,45,253,55,244,243,195,44,252,205,197,0,1,18,221,
9232 82,0,3,24,207,151,164,254,251,168,114,223,195,47,46,158,98,101,231,143,150,
9233 158,29,55,242,104,68,79,62,94,147,251,238,161,203,127,12,188,186,121,157,
9234 135,110,94,109,100,131,99,229,151,15,76,172,168,8,89,217,16,201,151,54,157,
9235 217,104,114,223,195,47,46,154,114,243,102,68,19,158,92,59,27,73,6,205,203,
9236 46,95,89,91,74,0,3,17,225,203,47,108,187,186,69,241,211,46,238,122,119,238,
9237 230,216,72,70,158,116,242,225,217,151,35,81,33,26,121,198,229,191,214,93,
9238 205,69,0,1,134,105,231,23,199,76,187,185,233,197,179,43,73,32,154,242,249,
9239 230,214,80,0,31,255,193,2,38,103,110,117,24,81,115,0,78,228,0,161,208,16,
9240 237,24,121,207,239,186,135,45,252,50,242,233,229,188,144,221,60,232,114,
9241 223,211,127,79,60,50,207,204,224,72,167,14,91,248,101,229,211,204,158,113,
9242 119,117,219,151,150,28,91,50,184,144,40,95,224,0,15,248,64,4,20,78,129,5,
9243 195,195,134,207,38,232,130,99,195,179,97,201,244,19,22,157,217,14,15,130,
9244 135,254,0,48,125,60,224,242,229,135,200,9,1,255,12,2,162,136,112,2,112,80,
9245 128,0,193,177,239,221,143,15,64,35,224,152,20,144,62,27,248,3,2,9,195,175,
9246 61,0,231,208,126,89,123,101,229,207,40,72,32,188,244,105,205,208,40,16,94,
9247 123,52,227,202,22,136,39,61,252,186,6,18,13,207,134,205,56,242,134,175,65,
9248 250,238,231,163,78,110,129,231,208,125,59,178,101,241,63,48,25,248,0,12,47,
9249 102,30,125,36,238,201,151,196,252,192,103,255,255,240,92,189,178,242,242,8,
9250 105,4,231,191,110,80,67,80,0,24,62,109,252,162,225,199,160,16,212,0,10,7,
9251 183,15,0,67,80,0,56,54,109,59,58,101,228,8,106,0,9,6,229,151,39,92,121,66,
9252 15,192,0,97,124,178,228,235,143,45,45,57,244,116,8,63,255,255,10,39,248,0,
9253 195,51,114,223,182,30,140,60,161,239,201,149,248,248,31,241,0,140,80,129,
9254 202,10,49,128,10,35,1,6,199,163,15,40,61,32,9,10,199,163,15,40,123,242,101,
9255 131,210,4,144,108,123,247,99,195,210,8,250,15,167,118,76,190,39,230,131,52,
9256 133,236,195,207,164,157,217,50,248,159,154,12,212,0,6,27,179,126,60,59,50,
9257 195,223,183,134,30,89,97,9,5,219,135,166,61,16,164,131,242,203,195,102,28,
9258 121,97,145,6,231,151,15,44,122,33,201,5,231,179,78,60,177,8,130,243,225,
9259 179,79,72,148,66,121,245,197,207,167,45,59,179,197,162,23,211,124,205,253,
9260 242,242,135,135,158,87,240,68,122,111,153,191,30,29,153,102,111,239,151,
9261 148,60,60,242,191,130,23,211,125,94,28,50,242,135,135,158,87,240,128,0,196,
9262 122,111,153,191,30,29,153,106,240,225,151,148,60,60,242,191,132,0,6,9,211,
9263 150,157,177,160,131,115,235,139,159,78,81,72,10,47,248,0,3,254,40,17,138,
9264 48,66,136,152,64,0,66,129,48,5,27,252,88,76,216,54,47,214,131,50,172,88,31,
9265 255,255,255,255,255,253,239,240,153,178,103,95,173,6,101,88,176,0,64,0,0,0,
9266 0,0,0,3,168,0,0,0,0,0,0,31,15,241,26,19,233,201,169,38,180,91,242,103,70,
9267 147,58,77,75,48,0,0,0,0,0,0,60,31,226,51,162,199,131,82,77,104,183,228,206,
9268 141,38,116,154,150,96,0,0,0,0,0,0,120,127,128,15,248,192,70,40,0,0,0,0,0,0,
9269 0,0,3,10,44,68,9,216,8,20,49,130,15,211,124,109,62,50,228,95,36,55,166,248,
9270 190,56,111,221,151,119,77,56,118,47,18,23,211,125,14,89,113,233,231,167,
9271 126,230,18,5,31,252,0,224,188,48,242,231,148,116,144,58,181,33,143,127,64,
9272 247,111,238,56,0,127,199,2,49,72,0,0,0,0,0,0,248,127,180,81,36,4,51,166,
9273 248,152,122,101,167,211,150,157,217,201,2,0,3,12,233,190,166,157,185,105,
9274 244,229,167,118,114,64,128,1,4,228,129,0,3,137,116,223,51,126,60,59,50,196,
9275 195,211,45,62,156,180,238,206,72,16,0,72,151,77,243,55,227,195,179,45,77,
9276 59,114,211,233,203,78,236,228,129,0,5,10,73,2,0,12,21,18,4,0,28,82,35,32,
9277 80,74,8,62,124,189,42,105,219,148,148,16,188,249,122,70,235,179,101,156,
9278 184,121,15,132,0,34,29,159,47,74,181,33,198,235,179,101,156,184,121,15,132,
9279 0,38,17,159,47,73,187,247,116,208,62,16,0,168,94,124,189,42,212,135,55,126,
9280 238,154,7,194,0,23,7,207,151,164,76,61,50,143,132,0,50,21,159,47,74,181,33,
9281 196,195,211,40,248,64,3,96,217,242,244,137,135,200,248,64,3,161,57,242,244,
9282 171,82,28,76,62,71,194,0,31,8,207,151,164,141,253,121,115,31,8,0,132,47,62,
9283 94,149,106,67,145,191,175,46,99,225,0,17,133,103,203,210,110,157,221,122,
9284 101,230,62,16,1,40,110,124,189,42,212,135,55,78,238,189,50,243,31,8,0,156,
9285 43,62,94,148,242,227,223,187,39,49,240,128,10,67,115,229,233,86,164,58,121,
9286 113,239,221,147,152,248,64,5,97,249,242,244,155,167,102,205,60,242,227,223,
9287 187,39,49,240,128,11,68,179,229,233,86,164,57,186,118,108,211,207,46,61,
9288 251,178,115,31,8,0,188,71,62,94,149,52,237,203,235,126,236,179,243,102,231,
9289 151,161,0,32,252,242,244,169,167,110,82,34,67,249,229,233,55,78,205,154,
9290 121,229,199,191,118,78,100,37,0,24,137,115,203,210,173,72,115,116,236,217,
9291 167,158,92,123,247,100,230,66,80,1,152,87,60,189,41,229,199,191,118,78,100,
9292 43,224,3,80,222,121,122,85,169,14,158,92,123,247,100,230,66,190,0,55,10,
9293 231,151,164,221,59,186,244,203,204,133,252,0,114,27,207,47,74,181,33,205,
9294 211,187,175,76,188,200,95,192,7,97,28,242,244,145,191,175,46,100,51,224,3,
9295 208,190,121,122,85,169,14,70,254,188,185,144,207,128,15,193,249,229,233,19,
9296 15,76,164,37,0,32,133,115,203,210,173,72,113,48,244,202,66,80,2,24,71,60,
9297 189,38,239,221,211,65,10,248,1,20,47,158,94,149,106,67,155,191,119,77,4,43,
9298 224,4,112,190,121,122,70,235,179,101,156,184,121,16,191,128,18,67,185,229,
9299 233,86,164,56,221,118,108,179,151,15,34,23,240,2,88,62,124,189,44,229,195,
9300 200,124,32,4,208,126,121,122,89,203,135,145,9,64,9,194,145,254,0,0,255,144,
9301 24,100,130,14,0,16,176,2,192,129,11,33,12,1,168,193,108,96,186,48,95,32,0,
9302 0,0,0,0,0,0,0,56,38,95,25,113,189,18,9,211,47,62,143,100,20,95,0,20,159,
9303 240,0,7,252,144,162,241,2,195,66,7,11,89,204,140,197,252,229,197,226,230,
9304 115,3,16,69,19,64,5,43,252,0,9,255,40,16,188,33,49,123,97,217,23,151,45,
9305 252,131,66,7,0,20,191,240,0,39,252,176,66,240,133,82,195,187,62,88,188,185,
9306 111,228,26,16,56,0,166,127,128,1,63,230,2,23,132,58,150,92,217,121,101,221,
9307 143,44,94,92,183,242,13,8,28,0,83,127,192,0,159,243,65,11,194,23,79,206,
9308 238,152,124,69,229,203,127,32,208,129,192,5,59,252,0,9,255,56,16,188,33,53,
9309 60,240,203,23,151,45,252,131,66,7,0,20,255,240,0,39,252,240,66,240,132,85,
9310 165,38,47,46,91,249,6,132,14,0,31,255,228,64,98,192,105,87,20,139,10,191,5,
9311 64,130,76,156,197,132,1,101,91,91,187,22,176,36,8,28,201,204,160,119,156,
9312 253,127,33,23,115,31,193,102,79,142,202,44,15,232,34,182,84,113,95,115,248,
9313 52,201,241,216,176,139,0,59,148,152,85,239,47,108,254,5,66,76,1,130,212,69,
9314 79,178,16,148,8,61,58,52,170,49,190,202,6,105,219,251,52,245,7,49,252,22,
9315 157,26,85,25,64,205,59,127,102,158,160,246,63,74,7,135,23,53,2,65,48,227,
9316 223,205,64,160,0,48,76,60,244,238,80,40,0,20,19,15,76,59,148,10,0,7,5,195,
9317 211,14,230,74,72,130,99,203,167,98,129,64,1,32,120,247,243,80,40,0,44,15,
9318 47,142,10,5,0,6,130,230,217,191,127,37,2,128,3,192,246,111,206,160,80,0,
9319 136,30,220,62,19,151,160,123,116,238,79,94,129,240,223,221,73,32,0,48,110,
9320 88,119,100,223,181,68,16,94,91,250,238,200,160,80,0,152,31,61,59,148,10,0,
9321 21,4,231,199,151,69,2,128,5,192,250,97,220,160,80,0,192,127,255,128,20,23,
9322 134,30,92,242,164,34,19,207,167,45,59,179,233,205,229,37,129,127,255,0,0,
9323 191,255,128,0,63,255,197,131,246,203,203,158,157,251,160,0,0,0,0,0,12,98,
9324 160,3,166,156,30,53,32,249,165,131,76,223,159,62,94,70,172,114,16,176,144,
9325 60,56,250,19,18,5,159,25,89,32,121,180,238,42,30,129,229,221,140,164,122,7,
9326 147,46,50,129,232,62,61,251,120,97,199,208,156,129,83,127,0,50,250,69,3,
9327 252,131,32,248,250,242,229,151,119,72,240,3,254,148,0,2,168,254,0,0,255,
9328 167,0,33,68,88,32,0,33,64,176,2,170,254,0,0,255,169,0,33,69,220,32,0,33,67,
9329 184,2,172,254,0,0,255,171,8,137,144,0,0,0,0,0,0,0,128,68,73,4,195,187,126,
9330 226,8,4,178,16,41,164,32,147,7,136,52,193,240,0,18,17,48,124,0,8,133,76,31,
9331 0,3,33,147,7,192,1,8,116,193,240,0,82,127,255,132,47,65,11,137,191,174,45,
9332 153,98,242,229,191,144,105,4,95,47,46,91,249,32,211,185,6,94,92,183,242,65,
9333 163,14,236,155,52,238,206,0,85,255,192,6,13,167,157,109,57,123,136,144,31,
9334 245,192,3,5,231,179,78,60,163,9,0,2,10,199,248,0,3,254,192,4,32,249,242,
9335 244,147,187,163,129,116,128,24,66,51,229,233,87,78,238,142,5,210,0,65,8,
9336 207,151,164,157,221,24,182,23,72,1,140,39,62,94,149,116,238,232,197,176,
9337 186,64,8,97,25,242,244,147,187,163,54,66,233,0,50,132,231,203,210,174,157,
9338 221,25,178,23,72,1,20,43,62,94,145,182,111,195,209,155,33,116,128,17,194,
9339 179,229,233,27,102,252,61,27,52,23,72,1,36,31,158,94,146,119,116,112,50,
9340 208,3,8,71,60,189,42,233,221,209,192,203,64,8,33,28,242,244,147,187,163,22,
9341 195,45,0,49,132,243,203,210,174,157,221,24,182,25,104,1,12,35,158,94,146,
9342 119,116,102,200,101,160,6,80,158,121,122,85,211,187,163,54,67,45,0,34,133,
9343 115,203,210,54,205,248,122,51,100,50,208,2,56,87,60,189,35,108,223,135,163,
9344 102,131,45,0,36,7,255,248,1,11,50,136,132,115,235,139,15,46,88,124,140,36,
9345 0,4,43,79,224,139,16,0,0,0,0,0,0,60,15,192,101,253,152,0,5,109,252,17,98,0,
9346 0,0,0,0,0,7,129,248,12,191,181,0,0,174,63,130,44,64,0,0,0,0,0,0,240,63,1,
9347 151,246,224,0,21,215,240,69,136,0,0,0,0,0,0,0,8,0,50,254,228,0,2,188,254,8,
9348 177,0,0,0,0,0,0,0,1,0,6,95,221,128,0,87,223,193,22,32,0,0,0,0,0,0,8,32,0,
9349 203,251,208,0,11,3,248,34,196,0,0,0,0,0,0,1,4,0,25,127,126,0,1,97,127,4,88,
9350 128,0,0,0,0,0,0,32,128,3,47,240,64,0,44,79,224,139,16,0,0,0,0,0,0,8,16,0,
9351 101,254,24,0,5,141,252,1,96,216,247,238,199,135,162,162,33,90,121,197,221,
9352 143,126,77,59,179,172,146,17,167,156,46,185,179,101,228,176,65,89,77,16,
9353 124,123,246,240,195,203,40,162,64,0,193,255,138,5,144,158,89,112,228,171,
9354 39,119,71,2,232,132,114,203,135,36,157,221,28,11,164,0,66,25,203,46,28,149,
9355 100,238,232,197,180,200,162,233,0,1,134,114,203,135,37,89,59,186,49,109,10,
9356 40,186,64,2,97,124,178,225,201,39,119,70,45,166,69,23,72,0,140,47,150,92,
9357 57,36,238,232,197,180,40,162,233,0,25,134,114,203,135,37,89,59,186,51,101,
9358 50,40,186,64,0,161,156,178,225,201,86,78,238,140,217,66,138,46,144,0,168,
9359 95,44,184,114,73,221,209,155,41,145,69,210,0,37,11,229,151,14,73,59,186,51,
9360 101,10,40,186,64,6,161,124,178,225,201,27,102,252,61,38,69,23,72,0,28,47,
9361 150,92,57,35,108,223,135,164,40,162,233,0,11,134,114,203,135,36,77,253,113,
9362 108,203,50,40,186,64,1,33,156,178,225,201,19,127,92,91,50,194,138,46,144,0,
9363 200,87,44,184,114,85,147,187,164,200,162,237,0,5,133,114,203,135,37,89,59,
9364 186,66,138,46,208,0,216,79,44,184,114,73,221,210,100,81,118,128,10,194,121,
9365 101,195,146,78,238,144,162,139,180,0,118,21,223,150,158,153,106,201,221,
9366 209,192,203,33,61,249,105,233,150,78,238,142,6,90,0,33,13,239,203,79,76,
9367 181,100,238,232,197,180,200,163,45,0,1,134,247,229,167,166,90,178,119,116,
9368 98,218,20,81,150,128,4,195,59,242,211,211,44,157,221,24,182,153,20,101,160,
9369 2,48,206,252,180,244,203,39,119,70,45,161,69,25,104,0,204,55,191,45,61,50,
9370 213,147,187,163,54,83,34,140,180,0,10,27,223,150,158,153,106,201,221,209,
9371 155,40,81,70,90,0,21,12,239,203,79,76,178,119,116,102,202,100,81,150,128,9,
9372 67,59,242,211,211,44,157,221,25,178,133,20,101,160,3,80,206,252,180,244,
9373 203,27,102,252,61,38,69,25,104,0,28,51,191,45,61,50,198,217,191,15,72,81,
9374 70,90,0,23,13,239,203,79,76,177,55,245,197,179,44,200,163,45,0,4,134,247,
9375 229,167,166,88,155,250,226,217,150,20,81,150,128,6,66,251,242,211,211,45,
9376 89,59,186,76,138,51,16,0,88,95,126,90,122,101,171,39,119,72,81,70,98,0,27,
9377 10,239,203,79,76,178,119,116,153,20,102,32,2,176,174,252,180,244,203,39,
9378 119,72,81,70,98,0,58,40,173,176,82,90,4,19,54,157,155,21,217,6,203,199,174,
9379 29,156,197,9,7,199,191,111,12,60,178,138,20,0,6,9,143,127,15,42,208,130,
9380 243,217,167,30,81,132,65,123,242,211,211,42,228,0,
9381 };
9382 #elif defined(DUK_USE_DOUBLE_BE)
9383 DUK_INTERNAL const duk_uint8_t duk_builtins_data[3833] = {
9384 105,195,75,32,3,148,52,154,248,9,26,13,128,112,105,0,240,22,20,26,95,124,6,
9385 152,52,137,0,120,99,74,239,129,18,70,241,191,2,98,13,79,32,42,88,210,90,2,
9386 240,1,50,141,37,168,76,94,216,118,69,229,203,127,44,0,84,163,73,106,21,75,
9387 14,236,249,98,242,229,191,150,0,46,81,164,181,14,165,151,54,94,89,119,99,
9388 203,23,151,45,252,176,1,146,141,37,168,93,63,59,186,97,241,23,151,45,252,
9389 176,1,178,141,37,168,77,79,60,50,197,229,203,127,44,0,116,163,73,106,17,86,
9390 148,152,188,185,111,229,128,15,148,129,198,137,36,58,166,142,91,251,212,
9391 243,195,44,94,92,183,242,13,79,8,45,14,91,252,121,148,52,199,120,63,72,105,
9392 21,240,118,128,210,237,224,245,17,165,43,224,211,55,231,207,151,148,161,70,
9393 145,0,31,40,107,26,2,18,138,26,228,192,142,0,16,161,174,76,9,74,26,228,192,
9394 158,0,8,161,174,76,10,96,2,42,26,228,192,174,0,26,161,174,76,11,96,3,74,26,
9395 228,192,190,0,44,161,174,76,12,96,3,202,26,228,192,206,0,70,161,169,84,14,
9396 202,3,255,254,32,234,3,255,192,0,0,0,0,0,0,119,1,255,192,0,0,0,0,0,0,57,
9397 136,1,152,32,16,194,0,166,24,6,49,0,57,138,2,12,96,18,99,128,163,32,5,153,
9398 40,76,94,216,118,69,229,203,127,35,41,10,165,135,118,124,177,121,114,223,
9399 200,203,67,169,101,205,151,150,93,216,242,197,229,203,127,35,49,11,167,231,
9400 119,76,62,34,242,229,191,145,154,132,212,243,195,44,94,92,183,242,51,144,
9401 138,180,164,197,229,203,127,35,60,6,26,0,52,208,193,226,117,215,211,15,12,
9402 166,146,11,67,150,255,30,77,24,58,113,64,243,92,8,27,0,68,217,130,70,212,
9403 19,54,224,161,185,5,77,216,44,111,65,115,126,12,28,16,100,225,156,16,32,18,
9404 17,195,15,46,121,100,238,232,136,136,87,12,60,185,229,141,179,126,30,136,
9405 100,130,233,231,59,12,228,34,66,52,243,141,167,118,158,153,80,73,9,201,151,
9406 30,252,153,106,210,146,118,72,150,76,184,247,228,203,86,148,152,123,246,
9407 240,223,187,46,238,135,132,132,229,221,143,126,76,181,105,73,61,36,75,46,
9408 236,123,242,101,171,74,76,61,251,120,111,221,151,119,67,226,65,178,243,199,
9409 135,134,83,242,66,58,238,203,207,30,30,25,81,201,5,225,203,78,238,136,163,
9410 208,92,59,50,242,232,138,62,0,2,38,163,19,255,255,224,142,80,192,0,20,31,
9411 240,14,135,103,203,210,135,45,253,55,244,243,195,44,252,205,197,0,1,18,221,
9412 82,0,3,24,207,151,164,254,251,168,114,223,195,47,46,158,98,101,231,143,150,
9413 158,29,55,242,104,68,79,62,94,147,251,238,161,203,127,12,188,186,121,157,
9414 135,110,94,109,100,131,99,229,151,15,76,172,168,8,89,217,16,201,151,54,157,
9415 217,104,114,223,195,47,46,154,114,243,102,68,19,158,92,59,27,73,6,205,203,
9416 46,95,89,91,74,0,3,17,225,203,47,108,187,186,69,241,211,46,238,122,119,238,
9417 230,216,72,70,158,116,242,225,217,151,35,81,33,26,121,198,229,191,214,93,
9418 205,69,0,1,134,105,231,23,199,76,187,185,233,197,179,43,73,32,154,242,249,
9419 230,214,80,0,31,255,193,2,38,103,110,117,24,81,115,0,78,228,0,161,208,16,
9420 237,24,121,207,239,186,135,45,252,50,242,233,229,188,144,221,60,232,114,
9421 223,211,127,79,60,50,207,204,224,72,167,14,91,248,101,229,211,204,158,113,
9422 119,117,219,151,150,28,91,50,184,144,40,95,224,0,15,248,64,4,20,78,129,5,
9423 195,195,134,207,38,232,130,99,195,179,97,201,244,19,22,157,217,14,15,130,
9424 135,254,0,48,125,60,224,242,229,135,200,9,1,255,12,2,162,136,112,2,112,80,
9425 128,0,193,177,239,221,143,15,64,35,224,152,20,144,62,27,248,3,2,9,195,175,
9426 61,0,231,208,126,89,123,101,229,207,40,72,32,188,244,105,205,208,40,16,94,
9427 123,52,227,202,22,136,39,61,252,186,6,18,13,207,134,205,56,242,134,175,65,
9428 250,238,231,163,78,110,129,231,208,125,59,178,101,241,63,48,25,248,0,12,47,
9429 102,30,125,36,238,201,151,196,252,192,103,255,255,240,92,189,178,242,242,8,
9430 105,4,231,191,110,80,67,80,0,24,62,109,252,162,225,199,160,16,212,0,10,7,
9431 183,15,0,67,80,0,56,54,109,59,58,101,228,8,106,0,9,6,229,151,39,92,121,66,
9432 15,192,0,97,124,178,228,235,143,45,45,57,244,116,8,63,255,255,10,39,248,0,
9433 195,51,114,223,182,30,140,60,161,239,201,149,248,248,31,241,0,140,80,129,
9434 202,10,49,128,10,35,1,6,199,163,15,40,61,32,9,10,199,163,15,40,123,242,101,
9435 131,210,4,144,108,123,247,99,195,210,8,250,15,167,118,76,190,39,230,131,52,
9436 133,236,195,207,164,157,217,50,248,159,154,12,212,0,6,27,179,126,60,59,50,
9437 195,223,183,134,30,89,97,9,5,219,135,166,61,16,164,131,242,203,195,102,28,
9438 121,97,145,6,231,151,15,44,122,33,201,5,231,179,78,60,177,8,130,243,225,
9439 179,79,72,148,66,121,245,197,207,167,45,59,179,197,162,23,211,124,205,253,
9440 242,242,135,135,158,87,240,68,122,111,153,191,30,29,153,102,111,239,151,
9441 148,60,60,242,191,130,23,211,125,94,28,50,242,135,135,158,87,240,128,0,196,
9442 122,111,153,191,30,29,153,106,240,225,151,148,60,60,242,191,132,0,6,9,211,
9443 150,157,177,160,131,115,235,139,159,78,81,72,10,47,248,0,3,254,40,17,138,
9444 48,66,136,152,64,0,66,129,48,5,27,252,88,76,216,54,47,214,131,50,172,88,15,
9445 253,255,255,255,255,255,255,240,153,178,103,95,173,6,101,88,176,0,0,0,0,0,
9446 0,0,0,67,168,15,255,0,0,0,0,0,0,17,26,19,233,201,169,38,180,91,242,103,70,
9447 147,58,77,75,48,31,252,0,0,0,0,0,0,34,51,162,199,131,82,77,104,183,228,206,
9448 141,38,116,154,150,96,127,248,0,0,0,0,0,0,0,15,248,192,70,40,0,0,0,0,0,0,0,
9449 0,3,10,44,68,9,216,8,20,49,130,15,211,124,109,62,50,228,95,36,55,166,248,
9450 190,56,111,221,151,119,77,56,118,47,18,23,211,125,14,89,113,233,231,167,
9451 126,230,18,5,31,252,0,224,188,48,242,231,148,116,144,58,181,33,143,127,64,
9452 247,111,238,56,0,127,199,2,49,72,127,248,0,0,0,0,0,0,180,81,36,4,51,166,
9453 248,152,122,101,167,211,150,157,217,201,2,0,3,12,233,190,166,157,185,105,
9454 244,229,167,118,114,64,128,1,4,228,129,0,3,137,116,223,51,126,60,59,50,196,
9455 195,211,45,62,156,180,238,206,72,16,0,72,151,77,243,55,227,195,179,45,77,
9456 59,114,211,233,203,78,236,228,129,0,5,10,73,2,0,12,21,18,4,0,28,82,35,32,
9457 80,74,8,62,124,189,42,105,219,148,148,16,188,249,122,70,235,179,101,156,
9458 184,121,15,132,0,34,29,159,47,74,181,33,198,235,179,101,156,184,121,15,132,
9459 0,38,17,159,47,73,187,247,116,208,62,16,0,168,94,124,189,42,212,135,55,126,
9460 238,154,7,194,0,23,7,207,151,164,76,61,50,143,132,0,50,21,159,47,74,181,33,
9461 196,195,211,40,248,64,3,96,217,242,244,137,135,200,248,64,3,161,57,242,244,
9462 171,82,28,76,62,71,194,0,31,8,207,151,164,141,253,121,115,31,8,0,132,47,62,
9463 94,149,106,67,145,191,175,46,99,225,0,17,133,103,203,210,110,157,221,122,
9464 101,230,62,16,1,40,110,124,189,42,212,135,55,78,238,189,50,243,31,8,0,156,
9465 43,62,94,148,242,227,223,187,39,49,240,128,10,67,115,229,233,86,164,58,121,
9466 113,239,221,147,152,248,64,5,97,249,242,244,155,167,102,205,60,242,227,223,
9467 187,39,49,240,128,11,68,179,229,233,86,164,57,186,118,108,211,207,46,61,
9468 251,178,115,31,8,0,188,71,62,94,149,52,237,203,235,126,236,179,243,102,231,
9469 151,161,0,32,252,242,244,169,167,110,82,34,67,249,229,233,55,78,205,154,
9470 121,229,199,191,118,78,100,37,0,24,137,115,203,210,173,72,115,116,236,217,
9471 167,158,92,123,247,100,230,66,80,1,152,87,60,189,41,229,199,191,118,78,100,
9472 43,224,3,80,222,121,122,85,169,14,158,92,123,247,100,230,66,190,0,55,10,
9473 231,151,164,221,59,186,244,203,204,133,252,0,114,27,207,47,74,181,33,205,
9474 211,187,175,76,188,200,95,192,7,97,28,242,244,145,191,175,46,100,51,224,3,
9475 208,190,121,122,85,169,14,70,254,188,185,144,207,128,15,193,249,229,233,19,
9476 15,76,164,37,0,32,133,115,203,210,173,72,113,48,244,202,66,80,2,24,71,60,
9477 189,38,239,221,211,65,10,248,1,20,47,158,94,149,106,67,155,191,119,77,4,43,
9478 224,4,112,190,121,122,70,235,179,101,156,184,121,16,191,128,18,67,185,229,
9479 233,86,164,56,221,118,108,179,151,15,34,23,240,2,88,62,124,189,44,229,195,
9480 200,124,32,4,208,126,121,122,89,203,135,145,9,64,9,194,145,254,0,0,255,144,
9481 24,100,130,14,0,16,176,2,192,129,11,33,12,1,168,193,108,96,186,48,95,32,0,
9482 0,0,0,0,0,0,0,56,38,95,25,113,189,18,9,211,47,62,143,100,20,95,0,20,159,
9483 240,0,7,252,144,162,241,2,195,66,7,11,89,204,140,197,252,229,197,226,230,
9484 115,3,16,69,19,64,5,43,252,0,9,255,40,16,188,33,49,123,97,217,23,151,45,
9485 252,131,66,7,0,20,191,240,0,39,252,176,66,240,133,82,195,187,62,88,188,185,
9486 111,228,26,16,56,0,166,127,128,1,63,230,2,23,132,58,150,92,217,121,101,221,
9487 143,44,94,92,183,242,13,8,28,0,83,127,192,0,159,243,65,11,194,23,79,206,
9488 238,152,124,69,229,203,127,32,208,129,192,5,59,252,0,9,255,56,16,188,33,53,
9489 60,240,203,23,151,45,252,131,66,7,0,20,255,240,0,39,252,240,66,240,132,85,
9490 165,38,47,46,91,249,6,132,14,0,31,255,228,64,98,192,64,5,191,10,139,20,87,
9491 105,130,76,156,197,132,4,0,38,187,27,187,85,81,104,28,201,204,160,31,243,
9492 23,33,127,125,28,247,193,102,79,142,202,44,3,255,113,84,118,82,184,47,232,
9493 52,201,241,216,176,139,0,255,111,45,236,84,155,148,58,5,66,76,4,0,146,31,
9494 181,68,66,209,136,61,58,52,170,49,190,202,1,255,53,4,243,51,249,222,108,22,
9495 157,26,85,25,64,63,246,160,158,102,127,59,205,74,7,135,23,53,2,65,48,227,
9496 223,205,64,160,0,48,76,60,244,238,80,40,0,20,19,15,76,59,148,10,0,7,5,195,
9497 211,14,230,74,72,130,99,203,167,98,129,64,1,32,120,247,243,80,40,0,44,15,
9498 47,142,10,5,0,6,130,230,217,191,127,37,2,128,3,192,246,111,206,160,80,0,
9499 136,30,220,62,19,151,160,123,116,238,79,94,129,240,223,221,73,32,0,48,110,
9500 88,119,100,223,181,68,16,94,91,250,238,200,160,80,0,152,31,61,59,148,10,0,
9501 21,4,231,199,151,69,2,128,5,192,250,97,220,160,80,0,192,127,255,128,20,23,
9502 134,30,92,242,164,34,19,207,167,45,59,179,233,205,229,37,129,127,255,0,0,
9503 191,255,128,0,63,255,197,131,246,203,203,158,157,251,160,32,98,140,0,0,0,0,
9504 0,3,166,156,30,53,32,249,165,131,76,223,159,62,94,70,172,114,16,176,144,60,
9505 56,250,19,18,5,159,25,89,32,121,180,238,42,30,129,229,221,140,164,122,7,
9506 147,46,50,129,232,62,61,251,120,97,199,208,156,129,83,127,0,50,250,69,3,
9507 252,131,32,248,250,242,229,151,119,72,240,3,254,148,0,2,168,254,0,0,255,
9508 167,0,33,68,88,32,0,33,64,176,2,170,254,0,0,255,169,0,33,69,220,32,0,33,67,
9509 184,2,172,254,0,0,255,171,8,137,144,128,0,0,0,0,0,0,0,68,73,4,195,187,126,
9510 226,8,4,178,16,41,164,32,147,7,136,52,193,240,0,18,17,48,124,0,8,133,76,31,
9511 0,3,33,147,7,192,1,8,116,193,240,0,82,127,255,132,47,65,11,137,191,174,45,
9512 153,98,242,229,191,144,105,4,95,47,46,91,249,32,211,185,6,94,92,183,242,65,
9513 163,14,236,155,52,238,206,0,85,255,192,6,13,167,157,109,57,123,136,144,31,
9514 245,192,3,5,231,179,78,60,163,9,0,2,10,199,248,0,3,254,192,4,32,249,242,
9515 244,147,187,163,129,116,128,24,66,51,229,233,87,78,238,142,5,210,0,65,8,
9516 207,151,164,157,221,24,182,23,72,1,140,39,62,94,149,116,238,232,197,176,
9517 186,64,8,97,25,242,244,147,187,163,54,66,233,0,50,132,231,203,210,174,157,
9518 221,25,178,23,72,1,20,43,62,94,145,182,111,195,209,155,33,116,128,17,194,
9519 179,229,233,27,102,252,61,27,52,23,72,1,36,31,158,94,146,119,116,112,50,
9520 208,3,8,71,60,189,42,233,221,209,192,203,64,8,33,28,242,244,147,187,163,22,
9521 195,45,0,49,132,243,203,210,174,157,221,24,182,25,104,1,12,35,158,94,146,
9522 119,116,102,200,101,160,6,80,158,121,122,85,211,187,163,54,67,45,0,34,133,
9523 115,203,210,54,205,248,122,51,100,50,208,2,56,87,60,189,35,108,223,135,163,
9524 102,131,45,0,36,7,255,248,1,11,50,136,132,115,235,139,15,46,88,124,140,36,
9525 0,4,43,79,224,139,16,15,252,0,0,0,0,0,0,0,101,253,152,0,5,109,252,17,98,1,
9526 255,128,0,0,0,0,0,0,12,191,181,0,0,174,63,130,44,64,63,240,0,0,0,0,0,0,1,
9527 151,246,224,0,21,215,240,69,136,8,0,0,0,0,0,0,0,0,50,254,228,0,2,188,254,8,
9528 177,1,0,0,0,0,0,0,0,0,6,95,221,128,0,87,223,193,22,32,32,8,0,0,0,0,0,0,0,
9529 203,251,208,0,11,3,248,34,196,4,1,0,0,0,0,0,0,0,25,127,126,0,1,97,127,4,88,
9530 128,128,32,0,0,0,0,0,0,3,47,240,64,0,44,79,224,139,16,16,8,0,0,0,0,0,0,0,
9531 101,254,24,0,5,141,252,1,96,216,247,238,199,135,162,162,33,90,121,197,221,
9532 143,126,77,59,179,172,146,17,167,156,46,185,179,101,228,176,65,89,77,16,
9533 124,123,246,240,195,203,40,162,64,0,193,255,138,5,144,158,89,112,228,171,
9534 39,119,71,2,232,132,114,203,135,36,157,221,28,11,164,0,66,25,203,46,28,149,
9535 100,238,232,197,180,200,162,233,0,1,134,114,203,135,37,89,59,186,49,109,10,
9536 40,186,64,2,97,124,178,225,201,39,119,70,45,166,69,23,72,0,140,47,150,92,
9537 57,36,238,232,197,180,40,162,233,0,25,134,114,203,135,37,89,59,186,51,101,
9538 50,40,186,64,0,161,156,178,225,201,86,78,238,140,217,66,138,46,144,0,168,
9539 95,44,184,114,73,221,209,155,41,145,69,210,0,37,11,229,151,14,73,59,186,51,
9540 101,10,40,186,64,6,161,124,178,225,201,27,102,252,61,38,69,23,72,0,28,47,
9541 150,92,57,35,108,223,135,164,40,162,233,0,11,134,114,203,135,36,77,253,113,
9542 108,203,50,40,186,64,1,33,156,178,225,201,19,127,92,91,50,194,138,46,144,0,
9543 200,87,44,184,114,85,147,187,164,200,162,237,0,5,133,114,203,135,37,89,59,
9544 186,66,138,46,208,0,216,79,44,184,114,73,221,210,100,81,118,128,10,194,121,
9545 101,195,146,78,238,144,162,139,180,0,118,21,223,150,158,153,106,201,221,
9546 209,192,203,33,61,249,105,233,150,78,238,142,6,90,0,33,13,239,203,79,76,
9547 181,100,238,232,197,180,200,163,45,0,1,134,247,229,167,166,90,178,119,116,
9548 98,218,20,81,150,128,4,195,59,242,211,211,44,157,221,24,182,153,20,101,160,
9549 2,48,206,252,180,244,203,39,119,70,45,161,69,25,104,0,204,55,191,45,61,50,
9550 213,147,187,163,54,83,34,140,180,0,10,27,223,150,158,153,106,201,221,209,
9551 155,40,81,70,90,0,21,12,239,203,79,76,178,119,116,102,202,100,81,150,128,9,
9552 67,59,242,211,211,44,157,221,25,178,133,20,101,160,3,80,206,252,180,244,
9553 203,27,102,252,61,38,69,25,104,0,28,51,191,45,61,50,198,217,191,15,72,81,
9554 70,90,0,23,13,239,203,79,76,177,55,245,197,179,44,200,163,45,0,4,134,247,
9555 229,167,166,88,155,250,226,217,150,20,81,150,128,6,66,251,242,211,211,45,
9556 89,59,186,76,138,51,16,0,88,95,126,90,122,101,171,39,119,72,81,70,98,0,27,
9557 10,239,203,79,76,178,119,116,153,20,102,32,2,176,174,252,180,244,203,39,
9558 119,72,81,70,98,0,58,40,173,176,82,90,4,19,54,157,155,21,217,6,203,199,174,
9559 29,156,197,9,7,199,191,111,12,60,178,138,20,0,6,9,143,127,15,42,208,130,
9560 243,217,167,30,81,132,65,123,242,211,211,42,228,0,
9561 };
9562 #elif defined(DUK_USE_DOUBLE_ME)
9563 DUK_INTERNAL const duk_uint8_t duk_builtins_data[3833] = {
9564 105,195,75,32,3,148,52,154,248,9,26,13,128,112,105,0,240,22,20,26,95,124,6,
9565 152,52,137,0,120,99,74,239,129,18,70,241,191,2,98,13,79,32,42,88,210,90,2,
9566 240,1,50,141,37,168,76,94,216,118,69,229,203,127,44,0,84,163,73,106,21,75,
9567 14,236,249,98,242,229,191,150,0,46,81,164,181,14,165,151,54,94,89,119,99,
9568 203,23,151,45,252,176,1,146,141,37,168,93,63,59,186,97,241,23,151,45,252,
9569 176,1,178,141,37,168,77,79,60,50,197,229,203,127,44,0,116,163,73,106,17,86,
9570 148,152,188,185,111,229,128,15,148,129,198,137,36,58,166,142,91,251,212,
9571 243,195,44,94,92,183,242,13,79,8,45,14,91,252,121,148,52,199,120,63,72,105,
9572 21,240,118,128,210,237,224,245,17,165,43,224,211,55,231,207,151,148,161,70,
9573 145,0,31,40,107,26,2,18,138,26,228,192,142,0,16,161,174,76,9,74,26,228,192,
9574 158,0,8,161,174,76,10,96,2,42,26,228,192,174,0,26,161,174,76,11,96,3,74,26,
9575 228,192,190,0,44,161,174,76,12,96,3,202,26,228,192,206,0,70,161,169,84,14,
9576 202,3,255,254,32,234,0,0,7,195,248,0,0,0,0,119,0,0,3,193,252,0,0,0,0,57,
9577 136,1,152,32,16,194,0,166,24,6,49,0,57,138,2,12,96,18,99,128,163,32,5,153,
9578 40,76,94,216,118,69,229,203,127,35,41,10,165,135,118,124,177,121,114,223,
9579 200,203,67,169,101,205,151,150,93,216,242,197,229,203,127,35,49,11,167,231,
9580 119,76,62,34,242,229,191,145,154,132,212,243,195,44,94,92,183,242,51,144,
9581 138,180,164,197,229,203,127,35,60,6,26,0,52,208,193,226,117,215,211,15,12,
9582 166,146,11,67,150,255,30,77,24,58,113,64,243,92,8,27,0,68,217,130,70,212,
9583 19,54,224,161,185,5,77,216,44,111,65,115,126,12,28,16,100,225,156,16,32,18,
9584 17,195,15,46,121,100,238,232,136,136,87,12,60,185,229,141,179,126,30,136,
9585 100,130,233,231,59,12,228,34,66,52,243,141,167,118,158,153,80,73,9,201,151,
9586 30,252,153,106,210,146,118,72,150,76,184,247,228,203,86,148,152,123,246,
9587 240,223,187,46,238,135,132,132,229,221,143,126,76,181,105,73,61,36,75,46,
9588 236,123,242,101,171,74,76,61,251,120,111,221,151,119,67,226,65,178,243,199,
9589 135,134,83,242,66,58,238,203,207,30,30,25,81,201,5,225,203,78,238,136,163,
9590 208,92,59,50,242,232,138,62,0,2,38,163,19,255,255,224,142,80,192,0,20,31,
9591 240,14,135,103,203,210,135,45,253,55,244,243,195,44,252,205,197,0,1,18,221,
9592 82,0,3,24,207,151,164,254,251,168,114,223,195,47,46,158,98,101,231,143,150,
9593 158,29,55,242,104,68,79,62,94,147,251,238,161,203,127,12,188,186,121,157,
9594 135,110,94,109,100,131,99,229,151,15,76,172,168,8,89,217,16,201,151,54,157,
9595 217,104,114,223,195,47,46,154,114,243,102,68,19,158,92,59,27,73,6,205,203,
9596 46,95,89,91,74,0,3,17,225,203,47,108,187,186,69,241,211,46,238,122,119,238,
9597 230,216,72,70,158,116,242,225,217,151,35,81,33,26,121,198,229,191,214,93,
9598 205,69,0,1,134,105,231,23,199,76,187,185,233,197,179,43,73,32,154,242,249,
9599 230,214,80,0,31,255,193,2,38,103,110,117,24,81,115,0,78,228,0,161,208,16,
9600 237,24,121,207,239,186,135,45,252,50,242,233,229,188,144,221,60,232,114,
9601 223,211,127,79,60,50,207,204,224,72,167,14,91,248,101,229,211,204,158,113,
9602 119,117,219,151,150,28,91,50,184,144,40,95,224,0,15,248,64,4,20,78,129,5,
9603 195,195,134,207,38,232,130,99,195,179,97,201,244,19,22,157,217,14,15,130,
9604 135,254,0,48,125,60,224,242,229,135,200,9,1,255,12,2,162,136,112,2,112,80,
9605 128,0,193,177,239,221,143,15,64,35,224,152,20,144,62,27,248,3,2,9,195,175,
9606 61,0,231,208,126,89,123,101,229,207,40,72,32,188,244,105,205,208,40,16,94,
9607 123,52,227,202,22,136,39,61,252,186,6,18,13,207,134,205,56,242,134,175,65,
9608 250,238,231,163,78,110,129,231,208,125,59,178,101,241,63,48,25,248,0,12,47,
9609 102,30,125,36,238,201,151,196,252,192,103,255,255,240,92,189,178,242,242,8,
9610 105,4,231,191,110,80,67,80,0,24,62,109,252,162,225,199,160,16,212,0,10,7,
9611 183,15,0,67,80,0,56,54,109,59,58,101,228,8,106,0,9,6,229,151,39,92,121,66,
9612 15,192,0,97,124,178,228,235,143,45,45,57,244,116,8,63,255,255,10,39,248,0,
9613 195,51,114,223,182,30,140,60,161,239,201,149,248,248,31,241,0,140,80,129,
9614 202,10,49,128,10,35,1,6,199,163,15,40,61,32,9,10,199,163,15,40,123,242,101,
9615 131,210,4,144,108,123,247,99,195,210,8,250,15,167,118,76,190,39,230,131,52,
9616 133,236,195,207,164,157,217,50,248,159,154,12,212,0,6,27,179,126,60,59,50,
9617 195,223,183,134,30,89,97,9,5,219,135,166,61,16,164,131,242,203,195,102,28,
9618 121,97,145,6,231,151,15,44,122,33,201,5,231,179,78,60,177,8,130,243,225,
9619 179,79,72,148,66,121,245,197,207,167,45,59,179,197,162,23,211,124,205,253,
9620 242,242,135,135,158,87,240,68,122,111,153,191,30,29,153,102,111,239,151,
9621 148,60,60,242,191,130,23,211,125,94,28,50,242,135,135,158,87,240,128,0,196,
9622 122,111,153,191,30,29,153,106,240,225,151,148,60,60,242,191,132,0,6,9,211,
9623 150,157,177,160,131,115,235,139,159,78,81,72,10,47,248,0,3,254,40,17,138,
9624 48,66,136,152,64,0,66,129,48,5,27,252,88,76,216,54,47,214,131,50,172,88,31,
9625 255,253,239,255,255,255,255,240,153,178,103,95,173,6,101,88,176,0,0,0,0,0,
9626 64,0,0,3,168,0,0,31,15,224,0,0,0,17,26,19,233,201,169,38,180,91,242,103,70,
9627 147,58,77,75,48,0,0,60,31,192,0,0,0,34,51,162,199,131,82,77,104,183,228,
9628 206,141,38,116,154,150,96,0,0,120,127,128,0,0,0,0,15,248,192,70,40,0,0,0,0,
9629 0,0,0,0,3,10,44,68,9,216,8,20,49,130,15,211,124,109,62,50,228,95,36,55,166,
9630 248,190,56,111,221,151,119,77,56,118,47,18,23,211,125,14,89,113,233,231,
9631 167,126,230,18,5,31,252,0,224,188,48,242,231,148,116,144,58,181,33,143,127,
9632 64,247,111,238,56,0,127,199,2,49,72,0,0,248,127,0,0,0,0,180,81,36,4,51,166,
9633 248,152,122,101,167,211,150,157,217,201,2,0,3,12,233,190,166,157,185,105,
9634 244,229,167,118,114,64,128,1,4,228,129,0,3,137,116,223,51,126,60,59,50,196,
9635 195,211,45,62,156,180,238,206,72,16,0,72,151,77,243,55,227,195,179,45,77,
9636 59,114,211,233,203,78,236,228,129,0,5,10,73,2,0,12,21,18,4,0,28,82,35,32,
9637 80,74,8,62,124,189,42,105,219,148,148,16,188,249,122,70,235,179,101,156,
9638 184,121,15,132,0,34,29,159,47,74,181,33,198,235,179,101,156,184,121,15,132,
9639 0,38,17,159,47,73,187,247,116,208,62,16,0,168,94,124,189,42,212,135,55,126,
9640 238,154,7,194,0,23,7,207,151,164,76,61,50,143,132,0,50,21,159,47,74,181,33,
9641 196,195,211,40,248,64,3,96,217,242,244,137,135,200,248,64,3,161,57,242,244,
9642 171,82,28,76,62,71,194,0,31,8,207,151,164,141,253,121,115,31,8,0,132,47,62,
9643 94,149,106,67,145,191,175,46,99,225,0,17,133,103,203,210,110,157,221,122,
9644 101,230,62,16,1,40,110,124,189,42,212,135,55,78,238,189,50,243,31,8,0,156,
9645 43,62,94,148,242,227,223,187,39,49,240,128,10,67,115,229,233,86,164,58,121,
9646 113,239,221,147,152,248,64,5,97,249,242,244,155,167,102,205,60,242,227,223,
9647 187,39,49,240,128,11,68,179,229,233,86,164,57,186,118,108,211,207,46,61,
9648 251,178,115,31,8,0,188,71,62,94,149,52,237,203,235,126,236,179,243,102,231,
9649 151,161,0,32,252,242,244,169,167,110,82,34,67,249,229,233,55,78,205,154,
9650 121,229,199,191,118,78,100,37,0,24,137,115,203,210,173,72,115,116,236,217,
9651 167,158,92,123,247,100,230,66,80,1,152,87,60,189,41,229,199,191,118,78,100,
9652 43,224,3,80,222,121,122,85,169,14,158,92,123,247,100,230,66,190,0,55,10,
9653 231,151,164,221,59,186,244,203,204,133,252,0,114,27,207,47,74,181,33,205,
9654 211,187,175,76,188,200,95,192,7,97,28,242,244,145,191,175,46,100,51,224,3,
9655 208,190,121,122,85,169,14,70,254,188,185,144,207,128,15,193,249,229,233,19,
9656 15,76,164,37,0,32,133,115,203,210,173,72,113,48,244,202,66,80,2,24,71,60,
9657 189,38,239,221,211,65,10,248,1,20,47,158,94,149,106,67,155,191,119,77,4,43,
9658 224,4,112,190,121,122,70,235,179,101,156,184,121,16,191,128,18,67,185,229,
9659 233,86,164,56,221,118,108,179,151,15,34,23,240,2,88,62,124,189,44,229,195,
9660 200,124,32,4,208,126,121,122,89,203,135,145,9,64,9,194,145,254,0,0,255,144,
9661 24,100,130,14,0,16,176,2,192,129,11,33,12,1,168,193,108,96,186,48,95,32,0,
9662 0,0,0,0,0,0,0,56,38,95,25,113,189,18,9,211,47,62,143,100,20,95,0,20,159,
9663 240,0,7,252,144,162,241,2,195,66,7,11,89,204,140,197,252,229,197,226,230,
9664 115,3,16,69,19,64,5,43,252,0,9,255,40,16,188,33,49,123,97,217,23,151,45,
9665 252,131,66,7,0,20,191,240,0,39,252,176,66,240,133,82,195,187,62,88,188,185,
9666 111,228,26,16,56,0,166,127,128,1,63,230,2,23,132,58,150,92,217,121,101,221,
9667 143,44,94,92,183,242,13,8,28,0,83,127,192,0,159,243,65,11,194,23,79,206,
9668 238,152,124,69,229,203,127,32,208,129,192,5,59,252,0,9,255,56,16,188,33,53,
9669 60,240,203,23,151,45,252,131,66,7,0,20,255,240,0,39,252,240,66,240,132,85,
9670 165,38,47,46,91,249,6,132,14,0,31,255,228,64,98,192,10,191,5,64,105,87,20,
9671 139,130,76,156,197,132,11,22,176,36,1,101,91,91,184,28,201,204,160,33,23,
9672 115,31,247,156,253,127,65,102,79,142,202,44,4,113,95,115,255,232,34,182,88,
9673 52,201,241,216,176,139,1,239,47,108,252,59,148,152,86,5,66,76,15,178,16,
9674 148,1,130,212,69,72,61,58,52,170,49,190,202,4,245,7,49,254,105,219,251,52,
9675 22,157,26,85,25,64,158,160,246,63,205,59,127,102,74,7,135,23,53,2,65,48,
9676 227,223,205,64,160,0,48,76,60,244,238,80,40,0,20,19,15,76,59,148,10,0,7,5,
9677 195,211,14,230,74,72,130,99,203,167,98,129,64,1,32,120,247,243,80,40,0,44,
9678 15,47,142,10,5,0,6,130,230,217,191,127,37,2,128,3,192,246,111,206,160,80,0,
9679 136,30,220,62,19,151,160,123,116,238,79,94,129,240,223,221,73,32,0,48,110,
9680 88,119,100,223,181,68,16,94,91,250,238,200,160,80,0,152,31,61,59,148,10,0,
9681 21,4,231,199,151,69,2,128,5,192,250,97,220,160,80,0,192,127,255,128,20,23,
9682 134,30,92,242,164,34,19,207,167,45,59,179,233,205,229,37,129,127,255,0,0,
9683 191,255,128,0,63,255,197,131,246,203,203,158,157,251,160,0,12,98,160,0,0,0,
9684 0,3,166,156,30,53,32,249,165,131,76,223,159,62,94,70,172,114,16,176,144,60,
9685 56,250,19,18,5,159,25,89,32,121,180,238,42,30,129,229,221,140,164,122,7,
9686 147,46,50,129,232,62,61,251,120,97,199,208,156,129,83,127,0,50,250,69,3,
9687 252,131,32,248,250,242,229,151,119,72,240,3,254,148,0,2,168,254,0,0,255,
9688 167,0,33,68,88,32,0,33,64,176,2,170,254,0,0,255,169,0,33,69,220,32,0,33,67,
9689 184,2,172,254,0,0,255,171,8,137,144,0,0,0,128,0,0,0,0,68,73,4,195,187,126,
9690 226,8,4,178,16,41,164,32,147,7,136,52,193,240,0,18,17,48,124,0,8,133,76,31,
9691 0,3,33,147,7,192,1,8,116,193,240,0,82,127,255,132,47,65,11,137,191,174,45,
9692 153,98,242,229,191,144,105,4,95,47,46,91,249,32,211,185,6,94,92,183,242,65,
9693 163,14,236,155,52,238,206,0,85,255,192,6,13,167,157,109,57,123,136,144,31,
9694 245,192,3,5,231,179,78,60,163,9,0,2,10,199,248,0,3,254,192,4,32,249,242,
9695 244,147,187,163,129,116,128,24,66,51,229,233,87,78,238,142,5,210,0,65,8,
9696 207,151,164,157,221,24,182,23,72,1,140,39,62,94,149,116,238,232,197,176,
9697 186,64,8,97,25,242,244,147,187,163,54,66,233,0,50,132,231,203,210,174,157,
9698 221,25,178,23,72,1,20,43,62,94,145,182,111,195,209,155,33,116,128,17,194,
9699 179,229,233,27,102,252,61,27,52,23,72,1,36,31,158,94,146,119,116,112,50,
9700 208,3,8,71,60,189,42,233,221,209,192,203,64,8,33,28,242,244,147,187,163,22,
9701 195,45,0,49,132,243,203,210,174,157,221,24,182,25,104,1,12,35,158,94,146,
9702 119,116,102,200,101,160,6,80,158,121,122,85,211,187,163,54,67,45,0,34,133,
9703 115,203,210,54,205,248,122,51,100,50,208,2,56,87,60,189,35,108,223,135,163,
9704 102,131,45,0,36,7,255,248,1,11,50,136,132,115,235,139,15,46,88,124,140,36,
9705 0,4,43,79,224,139,16,0,0,60,15,192,0,0,0,0,101,253,152,0,5,109,252,17,98,0,
9706 0,7,129,248,0,0,0,0,12,191,181,0,0,174,63,130,44,64,0,0,240,63,0,0,0,0,1,
9707 151,246,224,0,21,215,240,69,136,0,0,0,8,0,0,0,0,0,50,254,228,0,2,188,254,8,
9708 177,0,0,0,1,0,0,0,0,0,6,95,221,128,0,87,223,193,22,32,0,0,8,32,0,0,0,0,0,
9709 203,251,208,0,11,3,248,34,196,0,0,1,4,0,0,0,0,0,25,127,126,0,1,97,127,4,88,
9710 128,0,0,32,128,0,0,0,0,3,47,240,64,0,44,79,224,139,16,0,0,8,16,0,0,0,0,0,
9711 101,254,24,0,5,141,252,1,96,216,247,238,199,135,162,162,33,90,121,197,221,
9712 143,126,77,59,179,172,146,17,167,156,46,185,179,101,228,176,65,89,77,16,
9713 124,123,246,240,195,203,40,162,64,0,193,255,138,5,144,158,89,112,228,171,
9714 39,119,71,2,232,132,114,203,135,36,157,221,28,11,164,0,66,25,203,46,28,149,
9715 100,238,232,197,180,200,162,233,0,1,134,114,203,135,37,89,59,186,49,109,10,
9716 40,186,64,2,97,124,178,225,201,39,119,70,45,166,69,23,72,0,140,47,150,92,
9717 57,36,238,232,197,180,40,162,233,0,25,134,114,203,135,37,89,59,186,51,101,
9718 50,40,186,64,0,161,156,178,225,201,86,78,238,140,217,66,138,46,144,0,168,
9719 95,44,184,114,73,221,209,155,41,145,69,210,0,37,11,229,151,14,73,59,186,51,
9720 101,10,40,186,64,6,161,124,178,225,201,27,102,252,61,38,69,23,72,0,28,47,
9721 150,92,57,35,108,223,135,164,40,162,233,0,11,134,114,203,135,36,77,253,113,
9722 108,203,50,40,186,64,1,33,156,178,225,201,19,127,92,91,50,194,138,46,144,0,
9723 200,87,44,184,114,85,147,187,164,200,162,237,0,5,133,114,203,135,37,89,59,
9724 186,66,138,46,208,0,216,79,44,184,114,73,221,210,100,81,118,128,10,194,121,
9725 101,195,146,78,238,144,162,139,180,0,118,21,223,150,158,153,106,201,221,
9726 209,192,203,33,61,249,105,233,150,78,238,142,6,90,0,33,13,239,203,79,76,
9727 181,100,238,232,197,180,200,163,45,0,1,134,247,229,167,166,90,178,119,116,
9728 98,218,20,81,150,128,4,195,59,242,211,211,44,157,221,24,182,153,20,101,160,
9729 2,48,206,252,180,244,203,39,119,70,45,161,69,25,104,0,204,55,191,45,61,50,
9730 213,147,187,163,54,83,34,140,180,0,10,27,223,150,158,153,106,201,221,209,
9731 155,40,81,70,90,0,21,12,239,203,79,76,178,119,116,102,202,100,81,150,128,9,
9732 67,59,242,211,211,44,157,221,25,178,133,20,101,160,3,80,206,252,180,244,
9733 203,27,102,252,61,38,69,25,104,0,28,51,191,45,61,50,198,217,191,15,72,81,
9734 70,90,0,23,13,239,203,79,76,177,55,245,197,179,44,200,163,45,0,4,134,247,
9735 229,167,166,88,155,250,226,217,150,20,81,150,128,6,66,251,242,211,211,45,
9736 89,59,186,76,138,51,16,0,88,95,126,90,122,101,171,39,119,72,81,70,98,0,27,
9737 10,239,203,79,76,178,119,116,153,20,102,32,2,176,174,252,180,244,203,39,
9738 119,72,81,70,98,0,58,40,173,176,82,90,4,19,54,157,155,21,217,6,203,199,174,
9739 29,156,197,9,7,199,191,111,12,60,178,138,20,0,6,9,143,127,15,42,208,130,
9740 243,217,167,30,81,132,65,123,242,211,211,42,228,0,
9741 };
9742 #else
9743 #error invalid endianness defines
9744 #endif
9745 #endif  /* DUK_USE_ROM_OBJECTS */
9746 /*
9747  *  Error, fatal, and panic handling.
9748  */
9749 
9750 /* include removed: duk_internal.h */
9751 
9752 #define DUK__ERRFMT_BUFSIZE  256  /* size for formatting buffers */
9753 
9754 #if defined(DUK_USE_VERBOSE_ERRORS)
9755 
duk_err_handle_error_fmt(duk_hthread * thr,const char * filename,duk_uint_t line_and_code,const char * fmt,...)9756 DUK_INTERNAL void duk_err_handle_error_fmt(duk_hthread *thr, const char *filename, duk_uint_t line_and_code, const char *fmt, ...) {
9757 	va_list ap;
9758 	char msg[DUK__ERRFMT_BUFSIZE];
9759 	va_start(ap, fmt);
9760 	(void) DUK_VSNPRINTF(msg, sizeof(msg), fmt, ap);
9761 	msg[sizeof(msg) - 1] = (char) 0;
9762 	duk_err_create_and_throw(thr, (duk_errcode_t) (line_and_code >> 24), msg, filename, (duk_int_t) (line_and_code & 0x00ffffffL));
9763 	va_end(ap);  /* dead code, but ensures portability (see Linux man page notes) */
9764 }
9765 
duk_err_handle_error(duk_hthread * thr,const char * filename,duk_uint_t line_and_code,const char * msg)9766 DUK_INTERNAL void duk_err_handle_error(duk_hthread *thr, const char *filename, duk_uint_t line_and_code, const char *msg) {
9767 	duk_err_create_and_throw(thr, (duk_errcode_t) (line_and_code >> 24), msg, filename, (duk_int_t) (line_and_code & 0x00ffffffL));
9768 }
9769 
9770 #else  /* DUK_USE_VERBOSE_ERRORS */
9771 
duk_err_handle_error(duk_hthread * thr,duk_errcode_t code)9772 DUK_INTERNAL void duk_err_handle_error(duk_hthread *thr, duk_errcode_t code) {
9773 	duk_err_create_and_throw(thr, code);
9774 }
9775 
9776 #endif  /* DUK_USE_VERBOSE_ERRORS */
9777 
9778 /*
9779  *  Error throwing helpers
9780  */
9781 
9782 #if defined(DUK_USE_VERBOSE_ERRORS)
9783 #if defined(DUK_USE_PARANOID_ERRORS)
duk_err_require_type_index(duk_hthread * thr,const char * filename,duk_int_t linenumber,duk_idx_t index,const char * expect_name)9784 DUK_INTERNAL void duk_err_require_type_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t index, const char *expect_name) {
9785 	DUK_ERROR_RAW_FMT3(thr, filename, linenumber, DUK_ERR_TYPE_ERROR, "%s required, found %s (stack index %ld)",
9786 	                   expect_name, duk_get_type_name((duk_context *) thr, index), (long) index);
9787 }
9788 #else
duk_err_require_type_index(duk_hthread * thr,const char * filename,duk_int_t linenumber,duk_idx_t index,const char * expect_name)9789 DUK_INTERNAL void duk_err_require_type_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t index, const char *expect_name) {
9790 	DUK_ERROR_RAW_FMT3(thr, filename, linenumber, DUK_ERR_TYPE_ERROR, "%s required, found %s (stack index %ld)",
9791 	                   expect_name, duk_push_string_readable((duk_context *) thr, index), (long) index);
9792 }
9793 #endif
duk_err_range(duk_hthread * thr,const char * filename,duk_int_t linenumber,const char * message)9794 DUK_INTERNAL void duk_err_range(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message) {
9795 	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_RANGE_ERROR, message);
9796 }
duk_err_api_index(duk_hthread * thr,const char * filename,duk_int_t linenumber,duk_idx_t index)9797 DUK_INTERNAL void duk_err_api_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t index) {
9798 	DUK_ERROR_RAW_FMT1(thr, filename, linenumber, DUK_ERR_API_ERROR, "invalid stack index %ld", (long) (index));
9799 }
duk_err_api(duk_hthread * thr,const char * filename,duk_int_t linenumber,const char * message)9800 DUK_INTERNAL void duk_err_api(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message) {
9801 	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_API_ERROR, message);
9802 }
duk_err_unimplemented_defmsg(duk_hthread * thr,const char * filename,duk_int_t linenumber)9803 DUK_INTERNAL void duk_err_unimplemented_defmsg(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
9804 	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_UNIMPLEMENTED_ERROR, DUK_STR_UNIMPLEMENTED);
9805 }
9806 #if !defined(DUK_USE_BYTECODE_DUMP_SUPPORT)
duk_err_unsupported_defmsg(duk_hthread * thr,const char * filename,duk_int_t linenumber)9807 DUK_INTERNAL void duk_err_unsupported_defmsg(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
9808 	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_UNSUPPORTED_ERROR, DUK_STR_UNSUPPORTED);
9809 }
9810 #endif
duk_err_internal_defmsg(duk_hthread * thr,const char * filename,duk_int_t linenumber)9811 DUK_INTERNAL void duk_err_internal_defmsg(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
9812 	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_INTERNAL_ERROR, DUK_STR_INTERNAL_ERROR);
9813 }
duk_err_internal(duk_hthread * thr,const char * filename,duk_int_t linenumber,const char * message)9814 DUK_INTERNAL void duk_err_internal(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message) {
9815 	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_INTERNAL_ERROR, message);
9816 }
duk_err_alloc(duk_hthread * thr,const char * filename,duk_int_t linenumber,const char * message)9817 DUK_INTERNAL void duk_err_alloc(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message) {
9818 	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_ALLOC_ERROR, message);
9819 }
9820 #else
9821 /* The file/line arguments are NULL and 0, they're ignored by DUK_ERROR_RAW()
9822  * when non-verbose errors are used.
9823  */
duk_err_type(duk_hthread * thr)9824 DUK_INTERNAL void duk_err_type(duk_hthread *thr) {
9825 	DUK_ERROR_RAW(thr, NULL, 0, DUK_ERR_TYPE_ERROR, NULL);
9826 }
duk_err_api(duk_hthread * thr)9827 DUK_INTERNAL void duk_err_api(duk_hthread *thr) {
9828 	DUK_ERROR_RAW(thr, NULL, 0, DUK_ERR_API_ERROR, NULL);
9829 }
duk_err_range(duk_hthread * thr)9830 DUK_INTERNAL void duk_err_range(duk_hthread *thr) {
9831 	DUK_ERROR_RAW(thr, NULL, 0, DUK_ERR_RANGE_ERROR, NULL);
9832 }
duk_err_syntax(duk_hthread * thr)9833 DUK_INTERNAL void duk_err_syntax(duk_hthread *thr) {
9834 	DUK_ERROR_RAW(thr, NULL, 0, DUK_ERR_SYNTAX_ERROR, NULL);
9835 }
duk_err_unimplemented(duk_hthread * thr)9836 DUK_INTERNAL void duk_err_unimplemented(duk_hthread *thr) {
9837 	DUK_ERROR_RAW(thr, NULL, 0, DUK_ERR_UNIMPLEMENTED_ERROR, NULL);
9838 }
duk_err_unsupported(duk_hthread * thr)9839 DUK_INTERNAL void duk_err_unsupported(duk_hthread *thr) {
9840 	DUK_ERROR_RAW(thr, NULL, 0, DUK_ERR_UNSUPPORTED_ERROR, NULL);
9841 }
duk_err_internal(duk_hthread * thr)9842 DUK_INTERNAL void duk_err_internal(duk_hthread *thr) {
9843 	DUK_ERROR_RAW(thr, NULL, 0, DUK_ERR_INTERNAL_ERROR, NULL);
9844 }
duk_err_alloc(duk_hthread * thr)9845 DUK_INTERNAL void duk_err_alloc(duk_hthread *thr) {
9846 	DUK_ERROR_RAW(thr, NULL, thr, DUK_ERR_ALLOC_ERROR, NULL);
9847 }
9848 #endif
9849 
9850 /*
9851  *  Default fatal error handler
9852  */
9853 
duk_default_fatal_handler(duk_context * ctx,duk_errcode_t code,const char * msg)9854 DUK_INTERNAL void duk_default_fatal_handler(duk_context *ctx, duk_errcode_t code, const char *msg) {
9855 	DUK_UNREF(ctx);
9856 #if defined(DUK_USE_FILE_IO)
9857 	DUK_FPRINTF(DUK_STDERR, "FATAL %ld: %s\n", (long) code, (const char *) (msg ? msg : "null"));
9858 	DUK_FFLUSH(DUK_STDERR);
9859 #else
9860 	/* omit print */
9861 #endif
9862 	DUK_D(DUK_DPRINT("default fatal handler called, code %ld -> calling DUK_PANIC()", (long) code));
9863 	DUK_PANIC(code, msg);
9864 	DUK_UNREACHABLE();
9865 }
9866 
9867 /*
9868  *  Default panic handler
9869  */
9870 
9871 #if !defined(DUK_USE_PANIC_HANDLER)
duk_default_panic_handler(duk_errcode_t code,const char * msg)9872 DUK_INTERNAL void duk_default_panic_handler(duk_errcode_t code, const char *msg) {
9873 #if defined(DUK_USE_FILE_IO)
9874 	DUK_FPRINTF(DUK_STDERR, "PANIC %ld: %s ("
9875 #if defined(DUK_USE_PANIC_ABORT)
9876 	            "calling abort"
9877 #elif defined(DUK_USE_PANIC_EXIT)
9878 	            "calling exit"
9879 #elif defined(DUK_USE_PANIC_SEGFAULT)
9880 	            "segfaulting on purpose"
9881 #else
9882 #error no DUK_USE_PANIC_xxx macro defined
9883 #endif
9884 	            ")\n", (long) code, (const char *) (msg ? msg : "null"));
9885 	DUK_FFLUSH(DUK_STDERR);
9886 #else
9887 	/* omit print */
9888 	DUK_UNREF(code);
9889 	DUK_UNREF(msg);
9890 #endif
9891 
9892 #if defined(DUK_USE_PANIC_ABORT)
9893 	DUK_ABORT();
9894 #elif defined(DUK_USE_PANIC_EXIT)
9895 	DUK_EXIT(-1);
9896 #elif defined(DUK_USE_PANIC_SEGFAULT)
9897 	/* exit() afterwards to satisfy "noreturn" */
9898 	DUK_CAUSE_SEGFAULT();  /* SCANBUILD: "Dereference of null pointer", normal */
9899 	DUK_EXIT(-1);
9900 #else
9901 #error no DUK_USE_PANIC_xxx macro defined
9902 #endif
9903 
9904 	DUK_UNREACHABLE();
9905 }
9906 #endif  /* !DUK_USE_PANIC_HANDLER */
9907 
9908 #undef DUK__ERRFMT_BUFSIZE
9909 /*
9910  *  Various Unicode help functions for character classification predicates,
9911  *  case conversion, decoding, etc.
9912  */
9913 
9914 /* include removed: duk_internal.h */
9915 
9916 /*
9917  *  Fast path tables
9918  */
9919 
9920 #if defined(DUK_USE_IDCHAR_FASTPATH)
9921 DUK_INTERNAL const duk_int8_t duk_is_idchar_tab[128] = {
9922 	/* 0: not IdentifierStart or IdentifierPart
9923 	 * 1: IdentifierStart and IdentifierPart
9924 	 * -1: IdentifierPart only
9925 	 */
9926 	0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   /* 0x00...0x0f */
9927 	0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   /* 0x10...0x1f */
9928 	0,  0,  0,  0,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   /* 0x20...0x2f */
9929 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0,  0,  0,  0,  0,  0,   /* 0x30...0x3f */
9930 	0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,   /* 0x40...0x4f */
9931 	1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  1,   /* 0x50...0x5f */
9932 	0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,   /* 0x60...0x6f */
9933 	1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0    /* 0x70...0x7f */
9934 };
9935 #endif
9936 
9937 /*
9938  *  XUTF-8 and CESU-8 encoding/decoding
9939  */
9940 
duk_unicode_get_xutf8_length(duk_ucodepoint_t cp)9941 DUK_INTERNAL duk_small_int_t duk_unicode_get_xutf8_length(duk_ucodepoint_t cp) {
9942 	duk_uint_fast32_t x = (duk_uint_fast32_t) cp;
9943 	if (x < 0x80UL) {
9944 		/* 7 bits */
9945 		return 1;
9946 	} else if (x < 0x800UL) {
9947 		/* 11 bits */
9948 		return 2;
9949 	} else if (x < 0x10000UL) {
9950 		/* 16 bits */
9951 		return 3;
9952 	} else if (x < 0x200000UL) {
9953 		/* 21 bits */
9954 		return 4;
9955 	} else if (x < 0x4000000UL) {
9956 		/* 26 bits */
9957 		return 5;
9958 	} else if (x < (duk_ucodepoint_t) 0x80000000UL) {
9959 		/* 31 bits */
9960 		return 6;
9961 	} else {
9962 		/* 36 bits */
9963 		return 7;
9964 	}
9965 }
9966 
9967 #if defined(DUK_USE_ASSERTIONS)
duk_unicode_get_cesu8_length(duk_ucodepoint_t cp)9968 DUK_INTERNAL duk_small_int_t duk_unicode_get_cesu8_length(duk_ucodepoint_t cp) {
9969 	duk_uint_fast32_t x = (duk_uint_fast32_t) cp;
9970 	if (x < 0x80UL) {
9971 		/* 7 bits */
9972 		return 1;
9973 	} else if (x < 0x800UL) {
9974 		/* 11 bits */
9975 		return 2;
9976 	} else if (x < 0x10000UL) {
9977 		/* 16 bits */
9978 		return 3;
9979 	} else {
9980 		/* Encoded as surrogate pair, each encoding to 3 bytes for
9981 		 * 6 bytes total.  Codepoints above U+10FFFF encode as 6 bytes
9982 		 * too, see duk_unicode_encode_cesu8().
9983 		  */
9984 		return 3 + 3;
9985 	}
9986 }
9987 #endif  /* DUK_USE_ASSERTIONS */
9988 
9989 DUK_INTERNAL const duk_uint8_t duk_unicode_xutf8_markers[7] = {
9990 	0x00, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe
9991 };
9992 
9993 /* Encode to extended UTF-8; 'out' must have space for at least
9994  * DUK_UNICODE_MAX_XUTF8_LENGTH bytes.  Allows encoding of any
9995  * 32-bit (unsigned) codepoint.
9996  */
duk_unicode_encode_xutf8(duk_ucodepoint_t cp,duk_uint8_t * out)9997 DUK_INTERNAL duk_small_int_t duk_unicode_encode_xutf8(duk_ucodepoint_t cp, duk_uint8_t *out) {
9998 	duk_uint_fast32_t x = (duk_uint_fast32_t) cp;
9999 	duk_small_int_t len;
10000 	duk_uint8_t marker;
10001 	duk_small_int_t i;
10002 
10003 	len = duk_unicode_get_xutf8_length(cp);
10004 	DUK_ASSERT(len > 0);
10005 
10006 	marker = duk_unicode_xutf8_markers[len - 1];  /* 64-bit OK because always >= 0 */
10007 
10008 	i = len;
10009 	DUK_ASSERT(i > 0);
10010 	do {
10011 		i--;
10012 		if (i > 0) {
10013 			out[i] = (duk_uint8_t) (0x80 + (x & 0x3f));
10014 			x >>= 6;
10015 		} else {
10016 			/* Note: masking of 'x' is not necessary because of
10017 			 * range check and shifting -> no bits overlapping
10018 			 * the marker should be set.
10019 			 */
10020 			out[0] = (duk_uint8_t) (marker + x);
10021 		}
10022 	} while (i > 0);
10023 
10024 	return len;
10025 }
10026 
10027 /* Encode to CESU-8; 'out' must have space for at least
10028  * DUK_UNICODE_MAX_CESU8_LENGTH bytes; codepoints above U+10FFFF
10029  * will encode to garbage but won't overwrite the output buffer.
10030  */
duk_unicode_encode_cesu8(duk_ucodepoint_t cp,duk_uint8_t * out)10031 DUK_INTERNAL duk_small_int_t duk_unicode_encode_cesu8(duk_ucodepoint_t cp, duk_uint8_t *out) {
10032 	duk_uint_fast32_t x = (duk_uint_fast32_t) cp;
10033 	duk_small_int_t len;
10034 
10035 	if (x < 0x80UL) {
10036 		out[0] = (duk_uint8_t) x;
10037 		len = 1;
10038 	} else if (x < 0x800UL) {
10039 		out[0] = (duk_uint8_t) (0xc0 + ((x >> 6) & 0x1f));
10040 		out[1] = (duk_uint8_t) (0x80 + (x & 0x3f));
10041 		len = 2;
10042 	} else if (x < 0x10000UL) {
10043 		/* surrogate pairs get encoded here */
10044 		out[0] = (duk_uint8_t) (0xe0 + ((x >> 12) & 0x0f));
10045 		out[1] = (duk_uint8_t) (0x80 + ((x >> 6) & 0x3f));
10046 		out[2] = (duk_uint8_t) (0x80 + (x & 0x3f));
10047 		len = 3;
10048 	} else {
10049 		/*
10050 		 *  Unicode codepoints above U+FFFF are encoded as surrogate
10051 		 *  pairs here.  This ensures that all CESU-8 codepoints are
10052 		 *  16-bit values as expected in Ecmascript.  The surrogate
10053 		 *  pairs always get a 3-byte encoding (each) in CESU-8.
10054 		 *  See: http://en.wikipedia.org/wiki/Surrogate_pair
10055 		 *
10056 		 *  20-bit codepoint, 10 bits (A and B) per surrogate pair:
10057 		 *
10058 		 *    x = 0b00000000 0000AAAA AAAAAABB BBBBBBBB
10059 		 *  sp1 = 0b110110AA AAAAAAAA  (0xd800 + ((x >> 10) & 0x3ff))
10060 		 *  sp2 = 0b110111BB BBBBBBBB  (0xdc00 + (x & 0x3ff))
10061 		 *
10062 		 *  Encoded into CESU-8:
10063 		 *
10064 		 *  sp1 -> 0b11101101  (0xe0 + ((sp1 >> 12) & 0x0f))
10065 		 *      -> 0b1010AAAA  (0x80 + ((sp1 >> 6) & 0x3f))
10066 		 *      -> 0b10AAAAAA  (0x80 + (sp1 & 0x3f))
10067 		 *  sp2 -> 0b11101101  (0xe0 + ((sp2 >> 12) & 0x0f))
10068 		 *      -> 0b1011BBBB  (0x80 + ((sp2 >> 6) & 0x3f))
10069 		 *      -> 0b10BBBBBB  (0x80 + (sp2 & 0x3f))
10070 		 *
10071 		 *  Note that 0x10000 must be subtracted first.  The code below
10072 		 *  avoids the sp1, sp2 temporaries which saves around 20 bytes
10073 		 *  of code.
10074 		 */
10075 
10076 		x -= 0x10000UL;
10077 
10078 		out[0] = (duk_uint8_t) (0xed);
10079 		out[1] = (duk_uint8_t) (0xa0 + ((x >> 16) & 0x0f));
10080 		out[2] = (duk_uint8_t) (0x80 + ((x >> 10) & 0x3f));
10081 		out[3] = (duk_uint8_t) (0xed);
10082 		out[4] = (duk_uint8_t) (0xb0 + ((x >> 6) & 0x0f));
10083 		out[5] = (duk_uint8_t) (0x80 + (x & 0x3f));
10084 		len = 6;
10085 	}
10086 
10087 	return len;
10088 }
10089 
10090 /* 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)10091 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) {
10092 	const duk_uint8_t *p;
10093 	duk_uint32_t res;
10094 	duk_uint_fast8_t ch;
10095 	duk_small_int_t n;
10096 
10097 	DUK_UNREF(thr);
10098 
10099 	p = *ptr;
10100 	if (p < ptr_start || p >= ptr_end) {
10101 		goto fail;
10102 	}
10103 
10104 	/*
10105 	 *  UTF-8 decoder which accepts longer than standard byte sequences.
10106 	 *  This allows full 32-bit code points to be used.
10107 	 */
10108 
10109 	ch = (duk_uint_fast8_t) (*p++);
10110 	if (ch < 0x80) {
10111 		/* 0xxx xxxx   [7 bits] */
10112 		res = (duk_uint32_t) (ch & 0x7f);
10113 		n = 0;
10114 	} else if (ch < 0xc0) {
10115 		/* 10xx xxxx -> invalid */
10116 		goto fail;
10117 	} else if (ch < 0xe0) {
10118 		/* 110x xxxx   10xx xxxx   [11 bits] */
10119 		res = (duk_uint32_t) (ch & 0x1f);
10120 		n = 1;
10121 	} else if (ch < 0xf0) {
10122 		/* 1110 xxxx   10xx xxxx   10xx xxxx   [16 bits] */
10123 		res = (duk_uint32_t) (ch & 0x0f);
10124 		n = 2;
10125 	} else if (ch < 0xf8) {
10126 		/* 1111 0xxx   10xx xxxx   10xx xxxx   10xx xxxx   [21 bits] */
10127 		res = (duk_uint32_t) (ch & 0x07);
10128 		n = 3;
10129 	} else if (ch < 0xfc) {
10130 		/* 1111 10xx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   [26 bits] */
10131 		res = (duk_uint32_t) (ch & 0x03);
10132 		n = 4;
10133 	} else if (ch < 0xfe) {
10134 		/* 1111 110x   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   [31 bits] */
10135 		res = (duk_uint32_t) (ch & 0x01);
10136 		n = 5;
10137 	} else if (ch < 0xff) {
10138 		/* 1111 1110   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   [36 bits] */
10139 		res = (duk_uint32_t) (0);
10140 		n = 6;
10141 	} else {
10142 		/* 8-byte format could be:
10143 		 * 1111 1111   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   [41 bits]
10144 		 *
10145 		 * However, this format would not have a zero bit following the
10146 		 * leading one bits and would not allow 0xFF to be used as an
10147 		 * "invalid xutf-8" marker for internal keys.  Further, 8-byte
10148 		 * encodings (up to 41 bit code points) are not currently needed.
10149 		 */
10150 		goto fail;
10151 	}
10152 
10153 	DUK_ASSERT(p >= ptr_start);  /* verified at beginning */
10154 	if (p + n > ptr_end) {
10155 		/* check pointer at end */
10156 		goto fail;
10157 	}
10158 
10159 	while (n > 0) {
10160 		DUK_ASSERT(p >= ptr_start && p < ptr_end);
10161 		res = res << 6;
10162 		res += (duk_uint32_t) ((*p++) & 0x3f);
10163 		n--;
10164 	}
10165 
10166 	*ptr = p;
10167 	*out_cp = res;
10168 	return 1;
10169 
10170  fail:
10171 	return 0;
10172 }
10173 
10174 /* 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)10175 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) {
10176 	duk_ucodepoint_t cp;
10177 
10178 	if (duk_unicode_decode_xutf8(thr, ptr, ptr_start, ptr_end, &cp)) {
10179 		return cp;
10180 	}
10181 	DUK_ERROR_INTERNAL(thr, "utf-8 decode failed");  /* XXX: 'internal error' is a bit of a misnomer */
10182 	DUK_UNREACHABLE();
10183 	return 0;
10184 }
10185 
10186 /* Compute (extended) utf-8 length without codepoint encoding validation,
10187  * used for string interning.
10188  *
10189  * NOTE: This algorithm is performance critical, more so than string hashing
10190  * in some cases.  It is needed when interning a string and needs to scan
10191  * every byte of the string with no skipping.  Having an ASCII fast path
10192  * is useful if possible in the algorithm.  The current algorithms were
10193  * chosen from several variants, based on x64 gcc -O2 testing.  See:
10194  * https://github.com/svaarala/duktape/pull/422
10195  *
10196  * NOTE: must match src/dukutil.py:duk_unicode_unvalidated_utf8_length().
10197  */
10198 
10199 #if defined(DUK_USE_PREFER_SIZE)
10200 /* Small variant; roughly 150 bytes smaller than the fast variant. */
duk_unicode_unvalidated_utf8_length(const duk_uint8_t * data,duk_size_t blen)10201 DUK_INTERNAL duk_size_t duk_unicode_unvalidated_utf8_length(const duk_uint8_t *data, duk_size_t blen) {
10202 	const duk_uint8_t *p;
10203 	const duk_uint8_t *p_end;
10204 	duk_size_t ncont;
10205 	duk_size_t clen;
10206 
10207 	p = data;
10208 	p_end = data + blen;
10209 	ncont = 0;
10210 	while (p != p_end) {
10211 		duk_uint8_t x;
10212 		x = *p++;
10213 		if (DUK_UNLIKELY(x >= 0x80 && x <= 0xbf)) {
10214 			ncont++;
10215 		}
10216 	}
10217 
10218 	DUK_ASSERT(ncont <= blen);
10219 	clen = blen - ncont;
10220 	DUK_ASSERT(clen <= blen);
10221 	return clen;
10222 }
10223 #else  /* DUK_USE_PREFER_SIZE */
10224 /* This seems like a good overall approach.  Fast path for ASCII in 4 byte
10225  * blocks.
10226  */
duk_unicode_unvalidated_utf8_length(const duk_uint8_t * data,duk_size_t blen)10227 DUK_INTERNAL duk_size_t duk_unicode_unvalidated_utf8_length(const duk_uint8_t *data, duk_size_t blen) {
10228 	const duk_uint8_t *p;
10229 	const duk_uint8_t *p_end;
10230 	const duk_uint32_t *p32_end;
10231 	const duk_uint32_t *p32;
10232 	duk_size_t ncont;
10233 	duk_size_t clen;
10234 
10235 	ncont = 0;  /* number of continuation (non-initial) bytes in [0x80,0xbf] */
10236 	p = data;
10237 	p_end = data + blen;
10238 	if (blen < 16) {
10239 		goto skip_fastpath;
10240 	}
10241 
10242 	/* Align 'p' to 4; the input data may have arbitrary alignment.
10243 	 * End of string check not needed because blen >= 16.
10244 	 */
10245 	while (((duk_size_t) (const void *) p) & 0x03U) {
10246 		duk_uint8_t x;
10247 		x = *p++;
10248 		if (DUK_UNLIKELY(x >= 0x80 && x <= 0xbf)) {
10249 			ncont++;
10250 		}
10251 	}
10252 
10253 	/* Full, aligned 4-byte reads. */
10254 	p32_end = (const duk_uint32_t *) (const void *) (p + ((duk_size_t) (p_end - p) & (duk_size_t) (~0x03)));
10255 	p32 = (const duk_uint32_t *) (const void *) p;
10256 	while (p32 != (const duk_uint32_t *) p32_end) {
10257 		duk_uint32_t x;
10258 		x = *p32++;
10259 		if (DUK_LIKELY((x & 0x80808080UL) == 0)) {
10260 			;  /* ASCII fast path */
10261 		} else {
10262 			/* Flip highest bit of each byte which changes
10263 			 * the bit pattern 10xxxxxx into 00xxxxxx which
10264 			 * allows an easy bit mask test.
10265 			 */
10266 			x ^= 0x80808080UL;
10267 			if (DUK_UNLIKELY(!(x & 0xc0000000UL))) {
10268 				ncont++;
10269 			}
10270 			if (DUK_UNLIKELY(!(x & 0x00c00000UL))) {
10271 				ncont++;
10272 			}
10273 			if (DUK_UNLIKELY(!(x & 0x0000c000UL))) {
10274 				ncont++;
10275 			}
10276 			if (DUK_UNLIKELY(!(x & 0x000000c0UL))) {
10277 				ncont++;
10278 			}
10279 		}
10280 	}
10281 	p = (const duk_uint8_t *) p32;
10282 	/* Fall through to handle the rest. */
10283 
10284  skip_fastpath:
10285 	while (p != p_end) {
10286 		duk_uint8_t x;
10287 		x = *p++;
10288 		if (DUK_UNLIKELY(x >= 0x80 && x <= 0xbf)) {
10289 			ncont++;
10290 		}
10291 	}
10292 
10293 	DUK_ASSERT(ncont <= blen);
10294 	clen = blen - ncont;
10295 	DUK_ASSERT(clen <= blen);
10296 	return clen;
10297 }
10298 #endif  /* DUK_USE_PREFER_SIZE */
10299 
10300 /*
10301  *  Unicode range matcher
10302  *
10303  *  Matches a codepoint against a packed bitstream of character ranges.
10304  *  Used for slow path Unicode matching.
10305  */
10306 
10307 /* Must match src/extract_chars.py, generate_match_table3(). */
duk__uni_decode_value(duk_bitdecoder_ctx * bd_ctx)10308 DUK_LOCAL duk_uint32_t duk__uni_decode_value(duk_bitdecoder_ctx *bd_ctx) {
10309 	duk_uint32_t t;
10310 
10311 	t = (duk_uint32_t) duk_bd_decode(bd_ctx, 4);
10312 	if (t <= 0x0eU) {
10313 		return t;
10314 	}
10315 	t = (duk_uint32_t) duk_bd_decode(bd_ctx, 8);
10316 	if (t <= 0xfdU) {
10317 		return t + 0x0f;
10318 	}
10319 	if (t == 0xfeU) {
10320 		t = (duk_uint32_t) duk_bd_decode(bd_ctx, 12);
10321 		return t + 0x0fU + 0xfeU;
10322 	} else {
10323 		t = (duk_uint32_t) duk_bd_decode(bd_ctx, 24);
10324 		return t + 0x0fU + 0xfeU + 0x1000UL;
10325 	}
10326 }
10327 
duk__uni_range_match(const duk_uint8_t * unitab,duk_size_t unilen,duk_codepoint_t cp)10328 DUK_LOCAL duk_small_int_t duk__uni_range_match(const duk_uint8_t *unitab, duk_size_t unilen, duk_codepoint_t cp) {
10329 	duk_bitdecoder_ctx bd_ctx;
10330 	duk_codepoint_t prev_re;
10331 
10332 	DUK_MEMZERO(&bd_ctx, sizeof(bd_ctx));
10333 	bd_ctx.data = (const duk_uint8_t *) unitab;
10334 	bd_ctx.length = (duk_size_t) unilen;
10335 
10336 	prev_re = 0;
10337 	for (;;) {
10338 		duk_codepoint_t r1, r2;
10339 		r1 = (duk_codepoint_t) duk__uni_decode_value(&bd_ctx);
10340 		if (r1 == 0) {
10341 			break;
10342 		}
10343 		r2 = (duk_codepoint_t) duk__uni_decode_value(&bd_ctx);
10344 
10345 		r1 = prev_re + r1;
10346 		r2 = r1 + r2;
10347 		prev_re = r2;
10348 
10349 		/* [r1,r2] is the range */
10350 
10351 		DUK_DDD(DUK_DDDPRINT("duk__uni_range_match: cp=%06lx range=[0x%06lx,0x%06lx]",
10352 		                     (unsigned long) cp, (unsigned long) r1, (unsigned long) r2));
10353 		if (cp >= r1 && cp <= r2) {
10354 			return 1;
10355 		}
10356 	}
10357 
10358 	return 0;
10359 }
10360 
10361 /*
10362  *  "WhiteSpace" production check.
10363  */
10364 
duk_unicode_is_whitespace(duk_codepoint_t cp)10365 DUK_INTERNAL duk_small_int_t duk_unicode_is_whitespace(duk_codepoint_t cp) {
10366 	/*
10367 	 *  E5 Section 7.2 specifies six characters specifically as
10368 	 *  white space:
10369 	 *
10370 	 *    0009;<control>;Cc;0;S;;;;;N;CHARACTER TABULATION;;;;
10371 	 *    000B;<control>;Cc;0;S;;;;;N;LINE TABULATION;;;;
10372 	 *    000C;<control>;Cc;0;WS;;;;;N;FORM FEED (FF);;;;
10373 	 *    0020;SPACE;Zs;0;WS;;;;;N;;;;;
10374 	 *    00A0;NO-BREAK SPACE;Zs;0;CS;<noBreak> 0020;;;;N;NON-BREAKING SPACE;;;;
10375 	 *    FEFF;ZERO WIDTH NO-BREAK SPACE;Cf;0;BN;;;;;N;BYTE ORDER MARK;;;;
10376 	 *
10377 	 *  It also specifies any Unicode category 'Zs' characters as white
10378 	 *  space.  These can be extracted with the "src/extract_chars.py" script.
10379 	 *  Current result:
10380 	 *
10381 	 *    RAW OUTPUT:
10382 	 *    ===========
10383 	 *    0020;SPACE;Zs;0;WS;;;;;N;;;;;
10384 	 *    00A0;NO-BREAK SPACE;Zs;0;CS;<noBreak> 0020;;;;N;NON-BREAKING SPACE;;;;
10385 	 *    1680;OGHAM SPACE MARK;Zs;0;WS;;;;;N;;;;;
10386 	 *    180E;MONGOLIAN VOWEL SEPARATOR;Zs;0;WS;;;;;N;;;;;
10387 	 *    2000;EN QUAD;Zs;0;WS;2002;;;;N;;;;;
10388 	 *    2001;EM QUAD;Zs;0;WS;2003;;;;N;;;;;
10389 	 *    2002;EN SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
10390 	 *    2003;EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
10391 	 *    2004;THREE-PER-EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
10392 	 *    2005;FOUR-PER-EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
10393 	 *    2006;SIX-PER-EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
10394 	 *    2007;FIGURE SPACE;Zs;0;WS;<noBreak> 0020;;;;N;;;;;
10395 	 *    2008;PUNCTUATION SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
10396 	 *    2009;THIN SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
10397 	 *    200A;HAIR SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
10398 	 *    202F;NARROW NO-BREAK SPACE;Zs;0;CS;<noBreak> 0020;;;;N;;;;;
10399 	 *    205F;MEDIUM MATHEMATICAL SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
10400 	 *    3000;IDEOGRAPHIC SPACE;Zs;0;WS;<wide> 0020;;;;N;;;;;
10401 	 *
10402 	 *    RANGES:
10403 	 *    =======
10404 	 *    0x0020
10405 	 *    0x00a0
10406 	 *    0x1680
10407 	 *    0x180e
10408 	 *    0x2000 ... 0x200a
10409 	 *    0x202f
10410 	 *    0x205f
10411 	 *    0x3000
10412 	 *
10413 	 *  A manual decoder (below) is probably most compact for this.
10414 	 */
10415 
10416 	duk_uint_fast8_t lo;
10417 	duk_uint_fast32_t hi;
10418 
10419 	/* cp == -1 (EOF) never matches and causes return value 0 */
10420 
10421 	lo = (duk_uint_fast8_t) (cp & 0xff);
10422 	hi = (duk_uint_fast32_t) (cp >> 8);  /* does not fit into an uchar */
10423 
10424 	if (hi == 0x0000UL) {
10425 		if (lo == 0x09U || lo == 0x0bU || lo == 0x0cU ||
10426 		    lo == 0x20U || lo == 0xa0U) {
10427 			return 1;
10428 		}
10429 	} else if (hi == 0x0020UL) {
10430 		if (lo <= 0x0aU || lo == 0x2fU || lo == 0x5fU) {
10431 			return 1;
10432 		}
10433 	} else if (cp == 0x1680L || cp == 0x180eL || cp == 0x3000L ||
10434 	           cp == 0xfeffL) {
10435 		return 1;
10436 	}
10437 
10438 	return 0;
10439 }
10440 
10441 /*
10442  *  "LineTerminator" production check.
10443  */
10444 
duk_unicode_is_line_terminator(duk_codepoint_t cp)10445 DUK_INTERNAL duk_small_int_t duk_unicode_is_line_terminator(duk_codepoint_t cp) {
10446 	/*
10447 	 *  E5 Section 7.3
10448 	 *
10449 	 *  A LineTerminatorSequence essentially merges <CR> <LF> sequences
10450 	 *  into a single line terminator.  This must be handled by the caller.
10451 	 */
10452 
10453 	if (cp == 0x000aL || cp == 0x000dL || cp == 0x2028L ||
10454 	    cp == 0x2029L) {
10455 		return 1;
10456 	}
10457 
10458 	return 0;
10459 }
10460 
10461 /*
10462  *  "IdentifierStart" production check.
10463  */
10464 
duk_unicode_is_identifier_start(duk_codepoint_t cp)10465 DUK_INTERNAL duk_small_int_t duk_unicode_is_identifier_start(duk_codepoint_t cp) {
10466 	/*
10467 	 *  E5 Section 7.6:
10468 	 *
10469 	 *    IdentifierStart:
10470 	 *      UnicodeLetter
10471 	 *      $
10472 	 *      _
10473 	 *      \ UnicodeEscapeSequence
10474 	 *
10475 	 *  IdentifierStart production has one multi-character production:
10476 	 *
10477 	 *    \ UnicodeEscapeSequence
10478 	 *
10479 	 *  The '\' character is -not- matched by this function.  Rather, the caller
10480 	 *  should decode the escape and then call this function to check whether the
10481 	 *  decoded character is acceptable (see discussion in E5 Section 7.6).
10482 	 *
10483 	 *  The "UnicodeLetter" alternative of the production allows letters
10484 	 *  from various Unicode categories.  These can be extracted with the
10485 	 *  "src/extract_chars.py" script.
10486 	 *
10487 	 *  Because the result has hundreds of Unicode codepoint ranges, matching
10488 	 *  for any values >= 0x80 are done using a very slow range-by-range scan
10489 	 *  and a packed range format.
10490 	 *
10491 	 *  The ASCII portion (codepoints 0x00 ... 0x7f) is fast-pathed below because
10492 	 *  it matters the most.  The ASCII related ranges of IdentifierStart are:
10493 	 *
10494 	 *    0x0041 ... 0x005a     ['A' ... 'Z']
10495 	 *    0x0061 ... 0x007a     ['a' ... 'z']
10496 	 *    0x0024                ['$']
10497 	 *    0x005f                ['_']
10498 	 */
10499 
10500 	/* ASCII (and EOF) fast path -- quick accept and reject */
10501 	if (cp <= 0x7fL) {
10502 #if defined(DUK_USE_IDCHAR_FASTPATH)
10503 		return (cp >= 0) && (duk_is_idchar_tab[cp] > 0);
10504 #else
10505 		if ((cp >= 'a' && cp <= 'z') ||
10506 		    (cp >= 'A' && cp <= 'Z') ||
10507 		    cp == '_' || cp == '$') {
10508 			return 1;
10509 		}
10510 		return 0;
10511 #endif
10512 	}
10513 
10514 	/* Non-ASCII slow path (range-by-range linear comparison), very slow */
10515 
10516 #ifdef DUK_USE_SOURCE_NONBMP
10517 	if (duk__uni_range_match(duk_unicode_ids_noa,
10518 	                         (duk_size_t) sizeof(duk_unicode_ids_noa),
10519 	                         (duk_codepoint_t) cp)) {
10520 		return 1;
10521 	}
10522 	return 0;
10523 #else
10524 	if (cp < 0x10000L) {
10525 		if (duk__uni_range_match(duk_unicode_ids_noabmp,
10526 		                         sizeof(duk_unicode_ids_noabmp),
10527 		                         (duk_codepoint_t) cp)) {
10528 			return 1;
10529 		}
10530 		return 0;
10531 	} else {
10532 		/* without explicit non-BMP support, assume non-BMP characters
10533 		 * are always accepted as identifier characters.
10534 		 */
10535 		return 1;
10536 	}
10537 #endif
10538 }
10539 
10540 /*
10541  *  "IdentifierPart" production check.
10542  */
10543 
duk_unicode_is_identifier_part(duk_codepoint_t cp)10544 DUK_INTERNAL duk_small_int_t duk_unicode_is_identifier_part(duk_codepoint_t cp) {
10545 	/*
10546 	 *  E5 Section 7.6:
10547 	 *
10548 	 *    IdentifierPart:
10549 	 *      IdentifierStart
10550 	 *      UnicodeCombiningMark
10551 	 *      UnicodeDigit
10552 	 *      UnicodeConnectorPunctuation
10553 	 *      <ZWNJ>  [U+200C]
10554 	 *      <ZWJ>   [U+200D]
10555 	 *
10556 	 *  IdentifierPart production has one multi-character production
10557 	 *  as part of its IdentifierStart alternative.  The '\' character
10558 	 *  of an escape sequence is not matched here, see discussion in
10559 	 *  duk_unicode_is_identifier_start().
10560 	 *
10561 	 *  To match non-ASCII characters (codepoints >= 0x80), a very slow
10562 	 *  linear range-by-range scan is used.  The codepoint is first compared
10563 	 *  to the IdentifierStart ranges, and if it doesn't match, then to a
10564 	 *  set consisting of code points in IdentifierPart but not in
10565 	 *  IdentifierStart.  This is done to keep the unicode range data small,
10566 	 *  at the expense of speed.
10567 	 *
10568 	 *  The ASCII fast path consists of:
10569 	 *
10570 	 *    0x0030 ... 0x0039     ['0' ... '9', UnicodeDigit]
10571 	 *    0x0041 ... 0x005a     ['A' ... 'Z', IdentifierStart]
10572 	 *    0x0061 ... 0x007a     ['a' ... 'z', IdentifierStart]
10573 	 *    0x0024                ['$', IdentifierStart]
10574 	 *    0x005f                ['_', IdentifierStart and
10575 	 *                                UnicodeConnectorPunctuation]
10576 	 *
10577 	 *  UnicodeCombiningMark has no code points <= 0x7f.
10578 	 *
10579 	 *  The matching code reuses the "identifier start" tables, and then
10580 	 *  consults a separate range set for characters in "identifier part"
10581 	 *  but not in "identifier start".  These can be extracted with the
10582 	 *  "src/extract_chars.py" script.
10583 	 *
10584 	 *  UnicodeCombiningMark -> categories Mn, Mc
10585 	 *  UnicodeDigit -> categories Nd
10586 	 *  UnicodeConnectorPunctuation -> categories Pc
10587 	 */
10588 
10589 	/* ASCII (and EOF) fast path -- quick accept and reject */
10590 	if (cp <= 0x7fL) {
10591 #if defined(DUK_USE_IDCHAR_FASTPATH)
10592 		return (cp >= 0) && (duk_is_idchar_tab[cp] != 0);
10593 #else
10594 		if ((cp >= 'a' && cp <= 'z') ||
10595 		    (cp >= 'A' && cp <= 'Z') ||
10596 		    (cp >= '0' && cp <= '9') ||
10597 		    cp == '_' || cp == '$') {
10598 			return 1;
10599 		}
10600 		return 0;
10601 #endif
10602 	}
10603 
10604 	/* Non-ASCII slow path (range-by-range linear comparison), very slow */
10605 
10606 #ifdef DUK_USE_SOURCE_NONBMP
10607 	if (duk__uni_range_match(duk_unicode_ids_noa,
10608 	                         sizeof(duk_unicode_ids_noa),
10609 	                         (duk_codepoint_t) cp) ||
10610 	    duk__uni_range_match(duk_unicode_idp_m_ids_noa,
10611 	                         sizeof(duk_unicode_idp_m_ids_noa),
10612 	                         (duk_codepoint_t) cp)) {
10613 		return 1;
10614 	}
10615 	return 0;
10616 #else
10617 	if (cp < 0x10000L) {
10618 		if (duk__uni_range_match(duk_unicode_ids_noabmp,
10619 		                         sizeof(duk_unicode_ids_noabmp),
10620 		                         (duk_codepoint_t) cp) ||
10621 		    duk__uni_range_match(duk_unicode_idp_m_ids_noabmp,
10622 		                         sizeof(duk_unicode_idp_m_ids_noabmp),
10623 		                         (duk_codepoint_t) cp)) {
10624 			return 1;
10625 		}
10626 		return 0;
10627 	} else {
10628 		/* without explicit non-BMP support, assume non-BMP characters
10629 		 * are always accepted as identifier characters.
10630 		 */
10631 		return 1;
10632 	}
10633 #endif
10634 }
10635 
10636 /*
10637  *  Unicode letter check.
10638  */
10639 
duk_unicode_is_letter(duk_codepoint_t cp)10640 DUK_INTERNAL duk_small_int_t duk_unicode_is_letter(duk_codepoint_t cp) {
10641 	/*
10642 	 *  Unicode letter is now taken to be the categories:
10643 	 *
10644 	 *    Lu, Ll, Lt, Lm, Lo
10645 	 *
10646 	 *  (Not sure if this is exactly correct.)
10647 	 *
10648 	 *  The ASCII fast path consists of:
10649 	 *
10650 	 *    0x0041 ... 0x005a     ['A' ... 'Z']
10651 	 *    0x0061 ... 0x007a     ['a' ... 'z']
10652 	 */
10653 
10654 	/* ASCII (and EOF) fast path -- quick accept and reject */
10655 	if (cp <= 0x7fL) {
10656 		if ((cp >= 'a' && cp <= 'z') ||
10657 		    (cp >= 'A' && cp <= 'Z')) {
10658 			return 1;
10659 		}
10660 		return 0;
10661 	}
10662 
10663 	/* Non-ASCII slow path (range-by-range linear comparison), very slow */
10664 
10665 #ifdef DUK_USE_SOURCE_NONBMP
10666 	if (duk__uni_range_match(duk_unicode_ids_noa,
10667 	                         sizeof(duk_unicode_ids_noa),
10668 	                         (duk_codepoint_t) cp) &&
10669 	    !duk__uni_range_match(duk_unicode_ids_m_let_noa,
10670 	                          sizeof(duk_unicode_ids_m_let_noa),
10671 	                          (duk_codepoint_t) cp)) {
10672 		return 1;
10673 	}
10674 	return 0;
10675 #else
10676 	if (cp < 0x10000L) {
10677 		if (duk__uni_range_match(duk_unicode_ids_noabmp,
10678 		                         sizeof(duk_unicode_ids_noabmp),
10679 		                         (duk_codepoint_t) cp) &&
10680 		    !duk__uni_range_match(duk_unicode_ids_m_let_noabmp,
10681 		                          sizeof(duk_unicode_ids_m_let_noabmp),
10682 		                          (duk_codepoint_t) cp)) {
10683 			return 1;
10684 		}
10685 		return 0;
10686 	} else {
10687 		/* without explicit non-BMP support, assume non-BMP characters
10688 		 * are always accepted as letters.
10689 		 */
10690 		return 1;
10691 	}
10692 #endif
10693 }
10694 
10695 /*
10696  *  Complex case conversion helper which decodes a bit-packed conversion
10697  *  control stream generated by unicode/extract_caseconv.py.  The conversion
10698  *  is very slow because it runs through the conversion data in a linear
10699  *  fashion to save space (which is why ASCII characters have a special
10700  *  fast path before arriving here).
10701  *
10702  *  The particular bit counts etc have been determined experimentally to
10703  *  be small but still sufficient, and must match the Python script
10704  *  (src/extract_caseconv.py).
10705  *
10706  *  The return value is the case converted codepoint or -1 if the conversion
10707  *  results in multiple characters (this is useful for regexp Canonicalization
10708  *  operation).  If 'buf' is not NULL, the result codepoint(s) are also
10709  *  appended to the hbuffer.
10710  *
10711  *  Context and locale specific rules must be checked before consulting
10712  *  this function.
10713  */
10714 
10715 DUK_LOCAL
duk__slow_case_conversion(duk_hthread * thr,duk_bufwriter_ctx * bw,duk_codepoint_t cp,duk_bitdecoder_ctx * bd_ctx)10716 duk_codepoint_t duk__slow_case_conversion(duk_hthread *thr,
10717                                           duk_bufwriter_ctx *bw,
10718                                           duk_codepoint_t cp,
10719                                           duk_bitdecoder_ctx *bd_ctx) {
10720 	duk_small_int_t skip = 0;
10721 	duk_small_int_t n;
10722 	duk_small_int_t t;
10723 	duk_small_int_t count;
10724 	duk_codepoint_t tmp_cp;
10725 	duk_codepoint_t start_i;
10726 	duk_codepoint_t start_o;
10727 
10728 	DUK_UNREF(thr);
10729 	DUK_ASSERT(bd_ctx != NULL);
10730 
10731 	DUK_DDD(DUK_DDDPRINT("slow case conversion for codepoint: %ld", (long) cp));
10732 
10733 	/* range conversion with a "skip" */
10734 	DUK_DDD(DUK_DDDPRINT("checking ranges"));
10735 	for (;;) {
10736 		skip++;
10737 		n = (duk_small_int_t) duk_bd_decode(bd_ctx, 6);
10738 		if (n == 0x3f) {
10739 			/* end marker */
10740 			break;
10741 		}
10742 		DUK_DDD(DUK_DDDPRINT("skip=%ld, n=%ld", (long) skip, (long) n));
10743 
10744 		while (n--) {
10745 			start_i = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
10746 			start_o = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
10747 			count = (duk_small_int_t) duk_bd_decode(bd_ctx, 7);
10748 			DUK_DDD(DUK_DDDPRINT("range: start_i=%ld, start_o=%ld, count=%ld, skip=%ld",
10749 			                     (long) start_i, (long) start_o, (long) count, (long) skip));
10750 
10751 			if (cp >= start_i) {
10752 				tmp_cp = cp - start_i;  /* always >= 0 */
10753 				if (tmp_cp < (duk_codepoint_t) count * (duk_codepoint_t) skip &&
10754 				    (tmp_cp % (duk_codepoint_t) skip) == 0) {
10755 					DUK_DDD(DUK_DDDPRINT("range matches input codepoint"));
10756 					cp = start_o + tmp_cp;
10757 					goto single;
10758 				}
10759 			}
10760 		}
10761 	}
10762 
10763 	/* 1:1 conversion */
10764 	n = (duk_small_int_t) duk_bd_decode(bd_ctx, 6);
10765 	DUK_DDD(DUK_DDDPRINT("checking 1:1 conversions (count %ld)", (long) n));
10766 	while (n--) {
10767 		start_i = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
10768 		start_o = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
10769 		DUK_DDD(DUK_DDDPRINT("1:1 conversion %ld -> %ld", (long) start_i, (long) start_o));
10770 		if (cp == start_i) {
10771 			DUK_DDD(DUK_DDDPRINT("1:1 matches input codepoint"));
10772 			cp = start_o;
10773 			goto single;
10774 		}
10775 	}
10776 
10777 	/* complex, multicharacter conversion */
10778 	n = (duk_small_int_t) duk_bd_decode(bd_ctx, 7);
10779 	DUK_DDD(DUK_DDDPRINT("checking 1:n conversions (count %ld)", (long) n));
10780 	while (n--) {
10781 		start_i = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
10782 		t = (duk_small_int_t) duk_bd_decode(bd_ctx, 2);
10783 		DUK_DDD(DUK_DDDPRINT("1:n conversion %ld -> %ld chars", (long) start_i, (long) t));
10784 		if (cp == start_i) {
10785 			DUK_DDD(DUK_DDDPRINT("1:n matches input codepoint"));
10786 			if (bw != NULL) {
10787 				while (t--) {
10788 					tmp_cp = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
10789 					DUK_BW_WRITE_RAW_XUTF8(thr, bw, (duk_ucodepoint_t) tmp_cp);
10790 				}
10791 			}
10792 			return -1;
10793 		} else {
10794 			while (t--) {
10795 				(void) duk_bd_decode(bd_ctx, 16);
10796 			}
10797 		}
10798 	}
10799 
10800 	/* default: no change */
10801 	DUK_DDD(DUK_DDDPRINT("no rule matches, output is same as input"));
10802 	/* fall through */
10803 
10804  single:
10805 	if (bw != NULL) {
10806 		DUK_BW_WRITE_RAW_XUTF8(thr, bw, (duk_ucodepoint_t) cp);
10807 	}
10808 	return cp;
10809 }
10810 
10811 /*
10812  *  Case conversion helper, with context/local sensitivity.
10813  *  For proper case conversion, one needs to know the character
10814  *  and the preceding and following characters, as well as
10815  *  locale/language.
10816  */
10817 
10818 /* XXX: add 'language' argument when locale/language sensitive rule
10819  * support added.
10820  */
10821 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)10822 duk_codepoint_t duk__case_transform_helper(duk_hthread *thr,
10823                                            duk_bufwriter_ctx *bw,
10824                                            duk_codepoint_t cp,
10825                                            duk_codepoint_t prev,
10826                                            duk_codepoint_t next,
10827                                            duk_bool_t uppercase) {
10828 	duk_bitdecoder_ctx bd_ctx;
10829 
10830 	/* fast path for ASCII */
10831 	if (cp < 0x80L) {
10832 		/* XXX: there are language sensitive rules for the ASCII range.
10833 		 * If/when language/locale support is implemented, they need to
10834 		 * be implemented here for the fast path.  There are no context
10835 		 * sensitive rules for ASCII range.
10836 		 */
10837 
10838 		if (uppercase) {
10839 			if (cp >= 'a' && cp <= 'z') {
10840 				cp = cp - 'a' + 'A';
10841 			}
10842 		} else {
10843 			if (cp >= 'A' && cp <= 'Z') {
10844 				cp = cp - 'A' + 'a';
10845 			}
10846 		}
10847 
10848 		if (bw != NULL) {
10849 			DUK_BW_WRITE_RAW_U8(thr, bw, (duk_uint8_t) cp);
10850 		}
10851 		return cp;
10852 	}
10853 
10854 	/* context and locale specific rules which cannot currently be represented
10855 	 * in the caseconv bitstream: hardcoded rules in C
10856 	 */
10857 	if (uppercase) {
10858 		/* XXX: turkish / azeri */
10859 	} else {
10860 		/*
10861 		 *  Final sigma context specific rule.  This is a rather tricky
10862 		 *  rule and this handling is probably not 100% correct now.
10863 		 *  The rule is not locale/language specific so it is supported.
10864 		 */
10865 
10866 		if (cp == 0x03a3L &&    /* U+03A3 = GREEK CAPITAL LETTER SIGMA */
10867 		    duk_unicode_is_letter(prev) &&        /* prev exists and is not a letter */
10868 		    !duk_unicode_is_letter(next)) {       /* next does not exist or next is not a letter */
10869 			/* Capital sigma occurred at "end of word", lowercase to
10870 			 * U+03C2 = GREEK SMALL LETTER FINAL SIGMA.  Otherwise
10871 			 * fall through and let the normal rules lowercase it to
10872 			 * U+03C3 = GREEK SMALL LETTER SIGMA.
10873 			 */
10874 			cp = 0x03c2L;
10875 			goto singlechar;
10876 		}
10877 
10878 		/* XXX: lithuanian not implemented */
10879 		/* XXX: lithuanian, explicit dot rules */
10880 		/* XXX: turkish / azeri, lowercase rules */
10881 	}
10882 
10883 	/* 1:1 or special conversions, but not locale/context specific: script generated rules */
10884 	DUK_MEMZERO(&bd_ctx, sizeof(bd_ctx));
10885 	if (uppercase) {
10886 		bd_ctx.data = (const duk_uint8_t *) duk_unicode_caseconv_uc;
10887 		bd_ctx.length = (duk_size_t) sizeof(duk_unicode_caseconv_uc);
10888 	} else {
10889 		bd_ctx.data = (const duk_uint8_t *) duk_unicode_caseconv_lc;
10890 		bd_ctx.length = (duk_size_t) sizeof(duk_unicode_caseconv_lc);
10891 	}
10892 	return duk__slow_case_conversion(thr, bw, cp, &bd_ctx);
10893 
10894  singlechar:
10895 	if (bw != NULL) {
10896 		DUK_BW_WRITE_RAW_XUTF8(thr, bw, (duk_ucodepoint_t) cp);
10897 	}
10898 	return cp;
10899 
10900  /* unused now, not needed until Turkish/Azeri */
10901 #if 0
10902  nochar:
10903 	return -1;
10904 #endif
10905 }
10906 
10907 /*
10908  *  Replace valstack top with case converted version.
10909  */
10910 
duk_unicode_case_convert_string(duk_hthread * thr,duk_small_int_t uppercase)10911 DUK_INTERNAL void duk_unicode_case_convert_string(duk_hthread *thr, duk_small_int_t uppercase) {
10912 	duk_context *ctx = (duk_context *) thr;
10913 	duk_hstring *h_input;
10914 	duk_bufwriter_ctx bw_alloc;
10915 	duk_bufwriter_ctx *bw;
10916 	const duk_uint8_t *p, *p_start, *p_end;
10917 	duk_codepoint_t prev, curr, next;
10918 
10919 	h_input = duk_require_hstring(ctx, -1);
10920 	DUK_ASSERT(h_input != NULL);
10921 
10922 	bw = &bw_alloc;
10923 	DUK_BW_INIT_PUSHBUF(thr, bw, DUK_HSTRING_GET_BYTELEN(h_input));
10924 
10925 	/* [ ... input buffer ] */
10926 
10927 	p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
10928 	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
10929 	p = p_start;
10930 
10931 	prev = -1; DUK_UNREF(prev);
10932 	curr = -1;
10933 	next = -1;
10934 	for (;;) {
10935 		prev = curr;
10936 		curr = next;
10937 		next = -1;
10938 		if (p < p_end) {
10939 			next = (int) duk_unicode_decode_xutf8_checked(thr, &p, p_start, p_end);
10940 		} else {
10941 			/* end of input and last char has been processed */
10942 			if (curr < 0) {
10943 				break;
10944 			}
10945 		}
10946 
10947 		/* on first round, skip */
10948 		if (curr >= 0) {
10949 			/* XXX: could add a fast path to process chunks of input codepoints,
10950 			 * but relative benefit would be quite small.
10951 			 */
10952 
10953 			/* Ensure space for maximum multi-character result; estimate is overkill. */
10954 			DUK_BW_ENSURE(thr, bw, 8 * DUK_UNICODE_MAX_XUTF8_LENGTH);
10955 
10956 			duk__case_transform_helper(thr,
10957 			                           bw,
10958 			                           (duk_codepoint_t) curr,
10959 			                           prev,
10960 			                           next,
10961 			                           uppercase);
10962 		}
10963 	}
10964 
10965 	DUK_BW_COMPACT(thr, bw);
10966 	duk_to_string(ctx, -1);  /* invalidates h_buf pointer */
10967 	duk_remove(ctx, -2);
10968 }
10969 
10970 #ifdef DUK_USE_REGEXP_SUPPORT
10971 
10972 /*
10973  *  Canonicalize() abstract operation needed for canonicalization of individual
10974  *  codepoints during regexp compilation and execution, see E5 Section 15.10.2.8.
10975  *  Note that codepoints are canonicalized one character at a time, so no context
10976  *  specific rules can apply.  Locale specific rules can apply, though.
10977  */
10978 
duk_unicode_re_canonicalize_char(duk_hthread * thr,duk_codepoint_t cp)10979 DUK_INTERNAL duk_codepoint_t duk_unicode_re_canonicalize_char(duk_hthread *thr, duk_codepoint_t cp) {
10980 #if defined(DUK_USE_REGEXP_CANON_WORKAROUND)
10981 	/* Fast canonicalization lookup at the cost of 128kB footprint. */
10982 	DUK_ASSERT(cp >= 0);
10983 	DUK_UNREF(thr);
10984 	if (DUK_LIKELY(cp < 0x10000L)) {
10985 		return (duk_codepoint_t) duk_unicode_re_canon_lookup[cp];
10986 	}
10987 	return cp;
10988 #else  /* DUK_USE_REGEXP_CANON_WORKAROUND */
10989 	duk_codepoint_t y;
10990 
10991 	y = duk__case_transform_helper(thr,
10992 	                               NULL,    /* NULL is allowed, no output */
10993 	                               cp,      /* curr char */
10994 	                               -1,      /* prev char */
10995 	                               -1,      /* next char */
10996 	                               1);      /* uppercase */
10997 
10998 	if ((y < 0) || (cp >= 0x80 && y < 0x80)) {
10999 		/* multiple codepoint conversion or non-ASCII mapped to ASCII
11000 		 * --> leave as is.
11001 		 */
11002 		return cp;
11003 	}
11004 
11005 	return y;
11006 #endif  /* DUK_USE_REGEXP_CANON_WORKAROUND */
11007 }
11008 
11009 /*
11010  *  E5 Section 15.10.2.6 "IsWordChar" abstract operation.  Assume
11011  *  x < 0 for characters read outside the string.
11012  */
11013 
duk_unicode_re_is_wordchar(duk_codepoint_t x)11014 DUK_INTERNAL duk_small_int_t duk_unicode_re_is_wordchar(duk_codepoint_t x) {
11015 	/*
11016 	 *  Note: the description in E5 Section 15.10.2.6 has a typo, it
11017 	 *  contains 'A' twice and lacks 'a'; the intent is [0-9a-zA-Z_].
11018 	 */
11019 	if ((x >= '0' && x <= '9') ||
11020 	    (x >= 'a' && x <= 'z') ||
11021 	    (x >= 'A' && x <= 'Z') ||
11022 	    (x == '_')) {
11023 		return 1;
11024 	}
11025 	return 0;
11026 }
11027 
11028 /*
11029  *  Regexp range tables
11030  */
11031 
11032 /* exposed because lexer needs these too */
11033 DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_digit[2] = {
11034 	(duk_uint16_t) 0x0030UL, (duk_uint16_t) 0x0039UL,
11035 };
11036 DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_white[22] = {
11037 	(duk_uint16_t) 0x0009UL, (duk_uint16_t) 0x000DUL,
11038 	(duk_uint16_t) 0x0020UL, (duk_uint16_t) 0x0020UL,
11039 	(duk_uint16_t) 0x00A0UL, (duk_uint16_t) 0x00A0UL,
11040 	(duk_uint16_t) 0x1680UL, (duk_uint16_t) 0x1680UL,
11041 	(duk_uint16_t) 0x180EUL, (duk_uint16_t) 0x180EUL,
11042 	(duk_uint16_t) 0x2000UL, (duk_uint16_t) 0x200AUL,
11043 	(duk_uint16_t) 0x2028UL, (duk_uint16_t) 0x2029UL,
11044 	(duk_uint16_t) 0x202FUL, (duk_uint16_t) 0x202FUL,
11045 	(duk_uint16_t) 0x205FUL, (duk_uint16_t) 0x205FUL,
11046 	(duk_uint16_t) 0x3000UL, (duk_uint16_t) 0x3000UL,
11047 	(duk_uint16_t) 0xFEFFUL, (duk_uint16_t) 0xFEFFUL,
11048 };
11049 DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_wordchar[8] = {
11050 	(duk_uint16_t) 0x0030UL, (duk_uint16_t) 0x0039UL,
11051 	(duk_uint16_t) 0x0041UL, (duk_uint16_t) 0x005AUL,
11052 	(duk_uint16_t) 0x005FUL, (duk_uint16_t) 0x005FUL,
11053 	(duk_uint16_t) 0x0061UL, (duk_uint16_t) 0x007AUL,
11054 };
11055 DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_not_digit[4] = {
11056 	(duk_uint16_t) 0x0000UL, (duk_uint16_t) 0x002FUL,
11057 	(duk_uint16_t) 0x003AUL, (duk_uint16_t) 0xFFFFUL,
11058 };
11059 DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_not_white[24] = {
11060 	(duk_uint16_t) 0x0000UL, (duk_uint16_t) 0x0008UL,
11061 	(duk_uint16_t) 0x000EUL, (duk_uint16_t) 0x001FUL,
11062 	(duk_uint16_t) 0x0021UL, (duk_uint16_t) 0x009FUL,
11063 	(duk_uint16_t) 0x00A1UL, (duk_uint16_t) 0x167FUL,
11064 	(duk_uint16_t) 0x1681UL, (duk_uint16_t) 0x180DUL,
11065 	(duk_uint16_t) 0x180FUL, (duk_uint16_t) 0x1FFFUL,
11066 	(duk_uint16_t) 0x200BUL, (duk_uint16_t) 0x2027UL,
11067 	(duk_uint16_t) 0x202AUL, (duk_uint16_t) 0x202EUL,
11068 	(duk_uint16_t) 0x2030UL, (duk_uint16_t) 0x205EUL,
11069 	(duk_uint16_t) 0x2060UL, (duk_uint16_t) 0x2FFFUL,
11070 	(duk_uint16_t) 0x3001UL, (duk_uint16_t) 0xFEFEUL,
11071 	(duk_uint16_t) 0xFF00UL, (duk_uint16_t) 0xFFFFUL,
11072 };
11073 DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_not_wordchar[10] = {
11074 	(duk_uint16_t) 0x0000UL, (duk_uint16_t) 0x002FUL,
11075 	(duk_uint16_t) 0x003AUL, (duk_uint16_t) 0x0040UL,
11076 	(duk_uint16_t) 0x005BUL, (duk_uint16_t) 0x005EUL,
11077 	(duk_uint16_t) 0x0060UL, (duk_uint16_t) 0x0060UL,
11078 	(duk_uint16_t) 0x007BUL, (duk_uint16_t) 0xFFFFUL,
11079 };
11080 
11081 #endif  /* DUK_USE_REGEXP_SUPPORT */
11082 /*
11083  *  Misc util stuff
11084  */
11085 
11086 /* include removed: duk_internal.h */
11087 
11088 /*
11089  *  Lowercase digits for radix values 2 to 36.  Also doubles as lowercase
11090  *  hex nybble table.
11091  */
11092 
11093 DUK_INTERNAL const duk_uint8_t duk_lc_digits[36] = {
11094 	DUK_ASC_0, DUK_ASC_1, DUK_ASC_2, DUK_ASC_3,
11095 	DUK_ASC_4, DUK_ASC_5, DUK_ASC_6, DUK_ASC_7,
11096 	DUK_ASC_8, DUK_ASC_9, DUK_ASC_LC_A, DUK_ASC_LC_B,
11097 	DUK_ASC_LC_C, DUK_ASC_LC_D, DUK_ASC_LC_E, DUK_ASC_LC_F,
11098 	DUK_ASC_LC_G, DUK_ASC_LC_H, DUK_ASC_LC_I, DUK_ASC_LC_J,
11099 	DUK_ASC_LC_K, DUK_ASC_LC_L, DUK_ASC_LC_M, DUK_ASC_LC_N,
11100 	DUK_ASC_LC_O, DUK_ASC_LC_P, DUK_ASC_LC_Q, DUK_ASC_LC_R,
11101 	DUK_ASC_LC_S, DUK_ASC_LC_T, DUK_ASC_LC_U, DUK_ASC_LC_V,
11102 	DUK_ASC_LC_W, DUK_ASC_LC_X, DUK_ASC_LC_Y, DUK_ASC_LC_Z
11103 };
11104 
11105 DUK_INTERNAL const duk_uint8_t duk_uc_nybbles[16] = {
11106 	DUK_ASC_0, DUK_ASC_1, DUK_ASC_2, DUK_ASC_3,
11107 	DUK_ASC_4, DUK_ASC_5, DUK_ASC_6, DUK_ASC_7,
11108 	DUK_ASC_8, DUK_ASC_9, DUK_ASC_UC_A, DUK_ASC_UC_B,
11109 	DUK_ASC_UC_C, DUK_ASC_UC_D, DUK_ASC_UC_E, DUK_ASC_UC_F
11110 };
11111 
11112 /*
11113  *  Table for hex decoding ASCII hex digits
11114  */
11115 
11116 DUK_INTERNAL const duk_int8_t duk_hex_dectab[256] = {
11117 	/* -1 if invalid */
11118 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x00-0x0f */
11119 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x10-0x1f */
11120 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x20-0x2f */
11121 	 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1,  /* 0x30-0x3f */
11122 	-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x40-0x4f */
11123 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x50-0x5f */
11124 	-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x60-0x6f */
11125 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x70-0x7f */
11126 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x80-0x8f */
11127 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x90-0x9f */
11128 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xa0-0xaf */
11129 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xb0-0xbf */
11130 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xc0-0xcf */
11131 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xd0-0xdf */
11132 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xe0-0xef */
11133 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1   /* 0xf0-0xff */
11134 };
11135 
11136 #if defined(DUK_USE_HEX_FASTPATH)
11137 /* Preshifted << 4.  Must use 16-bit entry to allow negative value signaling. */
11138 DUK_INTERNAL const duk_int16_t duk_hex_dectab_shift4[256] = {
11139 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x00-0x0f */
11140 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x10-0x1f */
11141 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x20-0x2f */
11142 	0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x30-0x3f */
11143 	  -1, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x40-0x4f */
11144 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x50-0x5f */
11145 	  -1, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x60-0x6f */
11146 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x70-0x7f */
11147 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x80-0x8f */
11148 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x90-0x9f */
11149 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0xa0-0xaf */
11150 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0xb0-0xbf */
11151 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0xc0-0xcf */
11152 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0xd0-0xdf */
11153 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0xe0-0xef */
11154 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1   /* 0xf0-0xff */
11155 };
11156 #endif
11157 
11158 /*
11159  *  Table for hex encoding bytes
11160  */
11161 
11162 #if defined(DUK_USE_HEX_FASTPATH)
11163 /* Lookup to encode one byte directly into 2 characters:
11164  *
11165  *   def genhextab(bswap):
11166  *       for i in xrange(256):
11167  *           t = chr(i).encode('hex')
11168  *           if bswap:
11169  *               t = t[1] + t[0]
11170  *           print('0x' + t.encode('hex') + 'U')
11171  *   print('big endian'); genhextab(False)
11172  *   print('little endian'); genhextab(True)
11173 */
11174 DUK_INTERNAL const duk_uint16_t duk_hex_enctab[256] = {
11175 #if defined(DUK_USE_INTEGER_BE)
11176 	0x3030U, 0x3031U, 0x3032U, 0x3033U, 0x3034U, 0x3035U, 0x3036U, 0x3037U,
11177 	0x3038U, 0x3039U, 0x3061U, 0x3062U, 0x3063U, 0x3064U, 0x3065U, 0x3066U,
11178 	0x3130U, 0x3131U, 0x3132U, 0x3133U, 0x3134U, 0x3135U, 0x3136U, 0x3137U,
11179 	0x3138U, 0x3139U, 0x3161U, 0x3162U, 0x3163U, 0x3164U, 0x3165U, 0x3166U,
11180 	0x3230U, 0x3231U, 0x3232U, 0x3233U, 0x3234U, 0x3235U, 0x3236U, 0x3237U,
11181 	0x3238U, 0x3239U, 0x3261U, 0x3262U, 0x3263U, 0x3264U, 0x3265U, 0x3266U,
11182 	0x3330U, 0x3331U, 0x3332U, 0x3333U, 0x3334U, 0x3335U, 0x3336U, 0x3337U,
11183 	0x3338U, 0x3339U, 0x3361U, 0x3362U, 0x3363U, 0x3364U, 0x3365U, 0x3366U,
11184 	0x3430U, 0x3431U, 0x3432U, 0x3433U, 0x3434U, 0x3435U, 0x3436U, 0x3437U,
11185 	0x3438U, 0x3439U, 0x3461U, 0x3462U, 0x3463U, 0x3464U, 0x3465U, 0x3466U,
11186 	0x3530U, 0x3531U, 0x3532U, 0x3533U, 0x3534U, 0x3535U, 0x3536U, 0x3537U,
11187 	0x3538U, 0x3539U, 0x3561U, 0x3562U, 0x3563U, 0x3564U, 0x3565U, 0x3566U,
11188 	0x3630U, 0x3631U, 0x3632U, 0x3633U, 0x3634U, 0x3635U, 0x3636U, 0x3637U,
11189 	0x3638U, 0x3639U, 0x3661U, 0x3662U, 0x3663U, 0x3664U, 0x3665U, 0x3666U,
11190 	0x3730U, 0x3731U, 0x3732U, 0x3733U, 0x3734U, 0x3735U, 0x3736U, 0x3737U,
11191 	0x3738U, 0x3739U, 0x3761U, 0x3762U, 0x3763U, 0x3764U, 0x3765U, 0x3766U,
11192 	0x3830U, 0x3831U, 0x3832U, 0x3833U, 0x3834U, 0x3835U, 0x3836U, 0x3837U,
11193 	0x3838U, 0x3839U, 0x3861U, 0x3862U, 0x3863U, 0x3864U, 0x3865U, 0x3866U,
11194 	0x3930U, 0x3931U, 0x3932U, 0x3933U, 0x3934U, 0x3935U, 0x3936U, 0x3937U,
11195 	0x3938U, 0x3939U, 0x3961U, 0x3962U, 0x3963U, 0x3964U, 0x3965U, 0x3966U,
11196 	0x6130U, 0x6131U, 0x6132U, 0x6133U, 0x6134U, 0x6135U, 0x6136U, 0x6137U,
11197 	0x6138U, 0x6139U, 0x6161U, 0x6162U, 0x6163U, 0x6164U, 0x6165U, 0x6166U,
11198 	0x6230U, 0x6231U, 0x6232U, 0x6233U, 0x6234U, 0x6235U, 0x6236U, 0x6237U,
11199 	0x6238U, 0x6239U, 0x6261U, 0x6262U, 0x6263U, 0x6264U, 0x6265U, 0x6266U,
11200 	0x6330U, 0x6331U, 0x6332U, 0x6333U, 0x6334U, 0x6335U, 0x6336U, 0x6337U,
11201 	0x6338U, 0x6339U, 0x6361U, 0x6362U, 0x6363U, 0x6364U, 0x6365U, 0x6366U,
11202 	0x6430U, 0x6431U, 0x6432U, 0x6433U, 0x6434U, 0x6435U, 0x6436U, 0x6437U,
11203 	0x6438U, 0x6439U, 0x6461U, 0x6462U, 0x6463U, 0x6464U, 0x6465U, 0x6466U,
11204 	0x6530U, 0x6531U, 0x6532U, 0x6533U, 0x6534U, 0x6535U, 0x6536U, 0x6537U,
11205 	0x6538U, 0x6539U, 0x6561U, 0x6562U, 0x6563U, 0x6564U, 0x6565U, 0x6566U,
11206 	0x6630U, 0x6631U, 0x6632U, 0x6633U, 0x6634U, 0x6635U, 0x6636U, 0x6637U,
11207 	0x6638U, 0x6639U, 0x6661U, 0x6662U, 0x6663U, 0x6664U, 0x6665U, 0x6666U
11208 #else  /* DUK_USE_INTEGER_BE */
11209 	0x3030U, 0x3130U, 0x3230U, 0x3330U, 0x3430U, 0x3530U, 0x3630U, 0x3730U,
11210 	0x3830U, 0x3930U, 0x6130U, 0x6230U, 0x6330U, 0x6430U, 0x6530U, 0x6630U,
11211 	0x3031U, 0x3131U, 0x3231U, 0x3331U, 0x3431U, 0x3531U, 0x3631U, 0x3731U,
11212 	0x3831U, 0x3931U, 0x6131U, 0x6231U, 0x6331U, 0x6431U, 0x6531U, 0x6631U,
11213 	0x3032U, 0x3132U, 0x3232U, 0x3332U, 0x3432U, 0x3532U, 0x3632U, 0x3732U,
11214 	0x3832U, 0x3932U, 0x6132U, 0x6232U, 0x6332U, 0x6432U, 0x6532U, 0x6632U,
11215 	0x3033U, 0x3133U, 0x3233U, 0x3333U, 0x3433U, 0x3533U, 0x3633U, 0x3733U,
11216 	0x3833U, 0x3933U, 0x6133U, 0x6233U, 0x6333U, 0x6433U, 0x6533U, 0x6633U,
11217 	0x3034U, 0x3134U, 0x3234U, 0x3334U, 0x3434U, 0x3534U, 0x3634U, 0x3734U,
11218 	0x3834U, 0x3934U, 0x6134U, 0x6234U, 0x6334U, 0x6434U, 0x6534U, 0x6634U,
11219 	0x3035U, 0x3135U, 0x3235U, 0x3335U, 0x3435U, 0x3535U, 0x3635U, 0x3735U,
11220 	0x3835U, 0x3935U, 0x6135U, 0x6235U, 0x6335U, 0x6435U, 0x6535U, 0x6635U,
11221 	0x3036U, 0x3136U, 0x3236U, 0x3336U, 0x3436U, 0x3536U, 0x3636U, 0x3736U,
11222 	0x3836U, 0x3936U, 0x6136U, 0x6236U, 0x6336U, 0x6436U, 0x6536U, 0x6636U,
11223 	0x3037U, 0x3137U, 0x3237U, 0x3337U, 0x3437U, 0x3537U, 0x3637U, 0x3737U,
11224 	0x3837U, 0x3937U, 0x6137U, 0x6237U, 0x6337U, 0x6437U, 0x6537U, 0x6637U,
11225 	0x3038U, 0x3138U, 0x3238U, 0x3338U, 0x3438U, 0x3538U, 0x3638U, 0x3738U,
11226 	0x3838U, 0x3938U, 0x6138U, 0x6238U, 0x6338U, 0x6438U, 0x6538U, 0x6638U,
11227 	0x3039U, 0x3139U, 0x3239U, 0x3339U, 0x3439U, 0x3539U, 0x3639U, 0x3739U,
11228 	0x3839U, 0x3939U, 0x6139U, 0x6239U, 0x6339U, 0x6439U, 0x6539U, 0x6639U,
11229 	0x3061U, 0x3161U, 0x3261U, 0x3361U, 0x3461U, 0x3561U, 0x3661U, 0x3761U,
11230 	0x3861U, 0x3961U, 0x6161U, 0x6261U, 0x6361U, 0x6461U, 0x6561U, 0x6661U,
11231 	0x3062U, 0x3162U, 0x3262U, 0x3362U, 0x3462U, 0x3562U, 0x3662U, 0x3762U,
11232 	0x3862U, 0x3962U, 0x6162U, 0x6262U, 0x6362U, 0x6462U, 0x6562U, 0x6662U,
11233 	0x3063U, 0x3163U, 0x3263U, 0x3363U, 0x3463U, 0x3563U, 0x3663U, 0x3763U,
11234 	0x3863U, 0x3963U, 0x6163U, 0x6263U, 0x6363U, 0x6463U, 0x6563U, 0x6663U,
11235 	0x3064U, 0x3164U, 0x3264U, 0x3364U, 0x3464U, 0x3564U, 0x3664U, 0x3764U,
11236 	0x3864U, 0x3964U, 0x6164U, 0x6264U, 0x6364U, 0x6464U, 0x6564U, 0x6664U,
11237 	0x3065U, 0x3165U, 0x3265U, 0x3365U, 0x3465U, 0x3565U, 0x3665U, 0x3765U,
11238 	0x3865U, 0x3965U, 0x6165U, 0x6265U, 0x6365U, 0x6465U, 0x6565U, 0x6665U,
11239 	0x3066U, 0x3166U, 0x3266U, 0x3366U, 0x3466U, 0x3566U, 0x3666U, 0x3766U,
11240 	0x3866U, 0x3966U, 0x6166U, 0x6266U, 0x6366U, 0x6466U, 0x6566U, 0x6666U
11241 #endif  /* DUK_USE_INTEGER_BE */
11242 };
11243 #endif  /* DUK_USE_HEX_FASTPATH */
11244 
11245 /*
11246  *  Table for base-64 encoding
11247  */
11248 
11249 #if defined(DUK_USE_BASE64_FASTPATH)
11250 DUK_INTERNAL const duk_uint8_t duk_base64_enctab[64] = {
11251 	0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,  /* A...P */
11252 	0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66,  /* Q...f */
11253 	0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76,  /* g...v */
11254 	0x77, 0x78, 0x79, 0x7a, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2b, 0x2f   /* w.../ */
11255 };
11256 #endif  /* DUK_USE_BASE64_FASTPATH */
11257 
11258 /*
11259  *  Table for base-64 decoding
11260  */
11261 
11262 #if defined(DUK_USE_BASE64_FASTPATH)
11263 DUK_INTERNAL const duk_int8_t duk_base64_dectab[256] = {
11264 	/* -1 = error, -2 = allowed whitespace, -3 = padding ('='), 0...63 decoded bytes */
11265 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -2, -1, -1, -2, -1, -1,  /* 0x00...0x0f */
11266 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x10...0x1f */
11267 	-2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,  /* 0x20...0x2f */
11268 	52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -3, -1, -1,  /* 0x30...0x3f */
11269 	-1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,  /* 0x40...0x4f */
11270 	15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,  /* 0x50...0x5f */
11271 	-1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,  /* 0x60...0x6f */
11272 	41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,  /* 0x70...0x7f */
11273 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x80...0x8f */
11274 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x90...0x9f */
11275 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xa0...0xaf */
11276 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xb0...0xbf */
11277 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xc0...0xcf */
11278 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xd0...0xdf */
11279 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xe0...0xef */
11280 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1   /* 0xf0...0xff */
11281 };
11282 #endif  /* DUK_USE_BASE64_FASTPATH */
11283 
11284 /*
11285  *  Arbitrary byteswap for potentially unaligned values
11286  *
11287  *  Used to byteswap pointers e.g. in debugger code.
11288  */
11289 
11290 #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)11291 DUK_INTERNAL void duk_byteswap_bytes(duk_uint8_t *p, duk_small_uint_t len) {
11292 	duk_uint8_t tmp;
11293 	duk_uint8_t *q = p + len - 1;
11294 
11295 	while (p - q < 0) {
11296 		tmp = *p;
11297 		*p = *q;
11298 		*q = tmp;
11299 		p++;
11300 		q--;
11301 	}
11302 }
11303 #endif
11304 /*
11305  *  Round a number upwards to a prime (not usually the nearest one).
11306  *
11307  *  Uses a table of successive 32-bit primes whose ratio is roughly
11308  *  constant.  This keeps the relative upwards 'rounding error' bounded
11309  *  and the data size small.  A simple 'predict-correct' compression is
11310  *  used to compress primes to one byte per prime.  See genhashsizes.py
11311  *  for details.
11312  *
11313  *  The minimum prime returned here must be coordinated with the possible
11314  *  probe sequence steps in duk_hobject and duk_heap stringtable.
11315  */
11316 
11317 /* include removed: duk_internal.h */
11318 
11319 /* Awkward inclusion condition: drop out of compilation if not needed by any
11320  * call site: object hash part or probing stringtable.
11321  */
11322 #if defined(DUK_USE_HOBJECT_HASH_PART) || defined(DUK_USE_STRTAB_PROBE)
11323 
11324 /* hash size ratio goal, must match genhashsizes.py */
11325 #define DUK__HASH_SIZE_RATIO   1177  /* floor(1.15 * (1 << 10)) */
11326 
11327 /* prediction corrections for prime list (see genhashsizes.py) */
11328 DUK_LOCAL const duk_int8_t duk__hash_size_corrections[] = {
11329 	17,  /* minimum prime */
11330 	4, 3, 4, 1, 4, 1, 1, 2, 2, 2, 2, 1, 6, 6, 9, 5, 1, 2, 2, 5, 1, 3, 3, 3,
11331 	5, 4, 4, 2, 4, 8, 3, 4, 23, 2, 4, 7, 8, 11, 2, 12, 15, 10, 1, 1, 5, 1, 5,
11332 	8, 9, 17, 14, 10, 7, 5, 2, 46, 21, 1, 9, 9, 4, 4, 10, 23, 36, 6, 20, 29,
11333 	18, 6, 19, 21, 16, 11, 5, 5, 48, 9, 1, 39, 14, 8, 4, 29, 9, 1, 15, 48, 12,
11334 	22, 6, 15, 27, 4, 2, 17, 28, 8, 9, 4, 5, 8, 3, 3, 8, 37, 11, 15, 8, 30,
11335 	43, 6, 33, 41, 5, 20, 32, 41, 38, 24, 77, 14, 19, 11, 4, 35, 18, 19, 41,
11336 	10, 23, 16, 9, 2,
11337 	-1
11338 };
11339 
11340 /* probe steps (see genhashsizes.py), currently assumed to be 32 entries long
11341  * (DUK_UTIL_GET_HASH_PROBE_STEP macro).
11342  */
11343 DUK_INTERNAL duk_uint8_t duk_util_probe_steps[32] = {
11344 	2, 3, 5, 7, 11, 13, 19, 31, 41, 47, 59, 67, 73, 79, 89, 101, 103, 107,
11345 	109, 127, 137, 139, 149, 157, 163, 167, 173, 181, 191, 193, 197, 199
11346 };
11347 
duk_util_get_hash_prime(duk_uint32_t size)11348 DUK_INTERNAL duk_uint32_t duk_util_get_hash_prime(duk_uint32_t size) {
11349 	const duk_int8_t *p = duk__hash_size_corrections;
11350 	duk_uint32_t curr;
11351 
11352 	curr = (duk_uint32_t) *p++;
11353 	for (;;) {
11354 		duk_small_int_t t = (duk_small_int_t) *p++;
11355 		if (t < 0) {
11356 			/* may happen if size is very close to 2^32-1 */
11357 			break;
11358 		}
11359 
11360 		/* prediction: portable variant using doubles if 64-bit values not available */
11361 #ifdef DUK_USE_64BIT_OPS
11362 		curr = (duk_uint32_t) ((((duk_uint64_t) curr) * ((duk_uint64_t) DUK__HASH_SIZE_RATIO)) >> 10);
11363 #else
11364 		/* 32-bit x 11-bit = 43-bit, fits accurately into a double */
11365 		curr = (duk_uint32_t) DUK_FLOOR(((double) curr) * ((double) DUK__HASH_SIZE_RATIO) / 1024.0);
11366 #endif
11367 
11368 		/* correction */
11369 		curr += t;
11370 
11371 		DUK_DDD(DUK_DDDPRINT("size=%ld, curr=%ld", (long) size, (long) curr));
11372 
11373 		if (curr >= size) {
11374 			return curr;
11375 		}
11376 	}
11377 	return 0;
11378 }
11379 
11380 #endif  /* DUK_USE_HOBJECT_HASH_PART || DUK_USE_STRTAB_PROBE */
11381 /*
11382  *  Hobject Ecmascript [[Class]].
11383  */
11384 
11385 /* include removed: duk_internal.h */
11386 
11387 #if (DUK_STRIDX_UC_ARGUMENTS > 255)
11388 #error constant too large
11389 #endif
11390 #if (DUK_STRIDX_ARRAY > 255)
11391 #error constant too large
11392 #endif
11393 #if (DUK_STRIDX_UC_BOOLEAN > 255)
11394 #error constant too large
11395 #endif
11396 #if (DUK_STRIDX_DATE > 255)
11397 #error constant too large
11398 #endif
11399 #if (DUK_STRIDX_UC_ERROR > 255)
11400 #error constant too large
11401 #endif
11402 #if (DUK_STRIDX_UC_FUNCTION > 255)
11403 #error constant too large
11404 #endif
11405 #if (DUK_STRIDX_JSON > 255)
11406 #error constant too large
11407 #endif
11408 #if (DUK_STRIDX_MATH > 255)
11409 #error constant too large
11410 #endif
11411 #if (DUK_STRIDX_UC_NUMBER > 255)
11412 #error constant too large
11413 #endif
11414 #if (DUK_STRIDX_UC_OBJECT > 255)
11415 #error constant too large
11416 #endif
11417 #if (DUK_STRIDX_REG_EXP > 255)
11418 #error constant too large
11419 #endif
11420 #if (DUK_STRIDX_UC_STRING > 255)
11421 #error constant too large
11422 #endif
11423 #if (DUK_STRIDX_GLOBAL > 255)
11424 #error constant too large
11425 #endif
11426 #if (DUK_STRIDX_OBJ_ENV > 255)
11427 #error constant too large
11428 #endif
11429 #if (DUK_STRIDX_DEC_ENV > 255)
11430 #error constant too large
11431 #endif
11432 #if (DUK_STRIDX_UC_BUFFER > 255)
11433 #error constant too large
11434 #endif
11435 #if (DUK_STRIDX_UC_POINTER > 255)
11436 #error constant too large
11437 #endif
11438 #if (DUK_STRIDX_UC_THREAD > 255)
11439 #error constant too large
11440 #endif
11441 #if (DUK_STRIDX_ARRAY_BUFFER > 255)
11442 #error constant too large
11443 #endif
11444 #if (DUK_STRIDX_DATA_VIEW > 255)
11445 #error constant too large
11446 #endif
11447 #if (DUK_STRIDX_INT8_ARRAY > 255)
11448 #error constant too large
11449 #endif
11450 #if (DUK_STRIDX_UINT8_ARRAY > 255)
11451 #error constant too large
11452 #endif
11453 #if (DUK_STRIDX_UINT8_CLAMPED_ARRAY > 255)
11454 #error constant too large
11455 #endif
11456 #if (DUK_STRIDX_INT16_ARRAY > 255)
11457 #error constant too large
11458 #endif
11459 #if (DUK_STRIDX_UINT16_ARRAY > 255)
11460 #error constant too large
11461 #endif
11462 #if (DUK_STRIDX_INT32_ARRAY > 255)
11463 #error constant too large
11464 #endif
11465 #if (DUK_STRIDX_UINT32_ARRAY > 255)
11466 #error constant too large
11467 #endif
11468 #if (DUK_STRIDX_FLOAT32_ARRAY > 255)
11469 #error constant too large
11470 #endif
11471 #if (DUK_STRIDX_FLOAT64_ARRAY > 255)
11472 #error constant too large
11473 #endif
11474 #if (DUK_STRIDX_EMPTY_STRING > 255)
11475 #error constant too large
11476 #endif
11477 
11478 /* Note: assumes that these string indexes are 8-bit, genstrings.py must ensure that */
11479 DUK_INTERNAL duk_uint8_t duk_class_number_to_stridx[32] = {
11480 	DUK_STRIDX_EMPTY_STRING,  /* UNUSED, intentionally empty */
11481 	DUK_STRIDX_UC_ARGUMENTS,
11482 	DUK_STRIDX_ARRAY,
11483 	DUK_STRIDX_UC_BOOLEAN,
11484 	DUK_STRIDX_DATE,
11485 	DUK_STRIDX_UC_ERROR,
11486 	DUK_STRIDX_UC_FUNCTION,
11487 	DUK_STRIDX_JSON,
11488 	DUK_STRIDX_MATH,
11489 	DUK_STRIDX_UC_NUMBER,
11490 	DUK_STRIDX_UC_OBJECT,
11491 	DUK_STRIDX_REG_EXP,
11492 	DUK_STRIDX_UC_STRING,
11493 	DUK_STRIDX_GLOBAL,
11494 	DUK_STRIDX_OBJ_ENV,
11495 	DUK_STRIDX_DEC_ENV,
11496 	DUK_STRIDX_UC_BUFFER,
11497 	DUK_STRIDX_UC_POINTER,
11498 	DUK_STRIDX_UC_THREAD,
11499 	DUK_STRIDX_ARRAY_BUFFER,
11500 	DUK_STRIDX_DATA_VIEW,
11501 	DUK_STRIDX_INT8_ARRAY,
11502 	DUK_STRIDX_UINT8_ARRAY,
11503 	DUK_STRIDX_UINT8_CLAMPED_ARRAY,
11504 	DUK_STRIDX_INT16_ARRAY,
11505 	DUK_STRIDX_UINT16_ARRAY,
11506 	DUK_STRIDX_INT32_ARRAY,
11507 	DUK_STRIDX_UINT32_ARRAY,
11508 	DUK_STRIDX_FLOAT32_ARRAY,
11509 	DUK_STRIDX_FLOAT64_ARRAY,
11510 	DUK_STRIDX_EMPTY_STRING,  /* UNUSED, intentionally empty */
11511 	DUK_STRIDX_EMPTY_STRING,  /* UNUSED, intentionally empty */
11512 };
11513 /*
11514  *  Default allocation functions.
11515  *
11516  *  Assumes behavior such as malloc allowing zero size, yielding
11517  *  a NULL or a unique pointer which is a no-op for free.
11518  */
11519 
11520 /* include removed: duk_internal.h */
11521 
11522 #if defined(DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS)
duk_default_alloc_function(void * udata,duk_size_t size)11523 DUK_INTERNAL void *duk_default_alloc_function(void *udata, duk_size_t size) {
11524 	void *res;
11525 	DUK_UNREF(udata);
11526 	res = DUK_ANSI_MALLOC(size);
11527 	DUK_DDD(DUK_DDDPRINT("default alloc function: %lu -> %p",
11528 	                     (unsigned long) size, (void *) res));
11529 	return res;
11530 }
11531 
duk_default_realloc_function(void * udata,void * ptr,duk_size_t newsize)11532 DUK_INTERNAL void *duk_default_realloc_function(void *udata, void *ptr, duk_size_t newsize) {
11533 	void *res;
11534 	DUK_UNREF(udata);
11535 	res = DUK_ANSI_REALLOC(ptr, newsize);
11536 	DUK_DDD(DUK_DDDPRINT("default realloc function: %p %lu -> %p",
11537 	                     (void *) ptr, (unsigned long) newsize, (void *) res));
11538 	return res;
11539 }
11540 
duk_default_free_function(void * udata,void * ptr)11541 DUK_INTERNAL void duk_default_free_function(void *udata, void *ptr) {
11542 	DUK_DDD(DUK_DDDPRINT("default free function: %p", (void *) ptr));
11543 	DUK_UNREF(udata);
11544 	DUK_ANSI_FREE(ptr);
11545 }
11546 #endif  /* DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS */
11547 /*
11548  *  Buffer
11549  */
11550 
11551 /* include removed: duk_internal.h */
11552 
duk_resize_buffer(duk_context * ctx,duk_idx_t index,duk_size_t new_size)11553 DUK_EXTERNAL void *duk_resize_buffer(duk_context *ctx, duk_idx_t index, duk_size_t new_size) {
11554 	duk_hthread *thr = (duk_hthread *) ctx;
11555 	duk_hbuffer_dynamic *h;
11556 
11557 	DUK_ASSERT_CTX_VALID(ctx);
11558 
11559 	h = (duk_hbuffer_dynamic *) duk_require_hbuffer(ctx, index);
11560 	DUK_ASSERT(h != NULL);
11561 
11562 	if (!(DUK_HBUFFER_HAS_DYNAMIC(h) && !DUK_HBUFFER_HAS_EXTERNAL(h))) {
11563 		DUK_ERROR_TYPE(thr, DUK_STR_WRONG_BUFFER_TYPE);
11564 	}
11565 
11566 	/* maximum size check is handled by callee */
11567 	duk_hbuffer_resize(thr, h, new_size);
11568 
11569 	return DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h);
11570 }
11571 
duk_steal_buffer(duk_context * ctx,duk_idx_t index,duk_size_t * out_size)11572 DUK_EXTERNAL void *duk_steal_buffer(duk_context *ctx, duk_idx_t index, duk_size_t *out_size) {
11573 	duk_hthread *thr = (duk_hthread *) ctx;
11574 	duk_hbuffer_dynamic *h;
11575 	void *ptr;
11576 	duk_size_t sz;
11577 
11578 	DUK_ASSERT(ctx != NULL);
11579 
11580 	h = (duk_hbuffer_dynamic *) duk_require_hbuffer(ctx, index);
11581 	DUK_ASSERT(h != NULL);
11582 
11583 	if (!(DUK_HBUFFER_HAS_DYNAMIC(h) && !DUK_HBUFFER_HAS_EXTERNAL(h))) {
11584 		DUK_ERROR_TYPE(thr, DUK_STR_WRONG_BUFFER_TYPE);
11585 	}
11586 
11587 	/* Forget the previous allocation, setting size to 0 and alloc to
11588 	 * NULL.  Caller is responsible for freeing the previous allocation.
11589 	 * Getting the allocation and clearing it is done in the same API
11590 	 * call to avoid any chance of a realloc.
11591 	 */
11592 	ptr = DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h);
11593 	sz = DUK_HBUFFER_DYNAMIC_GET_SIZE(h);
11594 	if (out_size) {
11595 		*out_size = sz;
11596 	}
11597 	DUK_HBUFFER_DYNAMIC_SET_DATA_PTR_NULL(thr->heap, h);
11598 	DUK_HBUFFER_DYNAMIC_SET_SIZE(h, 0);
11599 
11600 	return ptr;
11601 }
11602 
duk_config_buffer(duk_context * ctx,duk_idx_t index,void * ptr,duk_size_t len)11603 DUK_EXTERNAL void duk_config_buffer(duk_context *ctx, duk_idx_t index, void *ptr, duk_size_t len) {
11604 	duk_hthread *thr = (duk_hthread *) ctx;
11605 	duk_hbuffer_external *h;
11606 
11607 	DUK_ASSERT(ctx != NULL);
11608 
11609 	h = (duk_hbuffer_external *) duk_require_hbuffer(ctx, index);
11610 	DUK_ASSERT(h != NULL);
11611 
11612 	if (!DUK_HBUFFER_HAS_EXTERNAL(h)) {
11613 		DUK_ERROR_TYPE(thr, DUK_STR_WRONG_BUFFER_TYPE);
11614 	}
11615 	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(h));
11616 
11617 	DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(thr->heap, h, ptr);
11618 	DUK_HBUFFER_EXTERNAL_SET_SIZE(h, len);
11619 }
11620 /*
11621  *  Bytecode dump/load
11622  *
11623  *  The bytecode load primitive is more important performance-wise than the
11624  *  dump primitive.
11625  *
11626  *  Unlike most Duktape API calls, bytecode dump/load is not guaranteed to be
11627  *  memory safe for invalid arguments - caller beware!  There's little point
11628  *  in trying to achieve memory safety unless bytecode instructions are also
11629  *  validated which is not easy to do with indirect register references etc.
11630  */
11631 
11632 /* include removed: duk_internal.h */
11633 
11634 #if defined(DUK_USE_BYTECODE_DUMP_SUPPORT)
11635 
11636 #define DUK__SER_MARKER  0xff
11637 #define DUK__SER_VERSION 0x00
11638 #define DUK__SER_STRING  0x00
11639 #define DUK__SER_NUMBER  0x01
11640 #define DUK__BYTECODE_INITIAL_ALLOC 256
11641 
11642 /*
11643  *  Dump/load helpers, xxx_raw() helpers do no buffer checks
11644  */
11645 
duk__load_string_raw(duk_context * ctx,duk_uint8_t * p)11646 DUK_LOCAL duk_uint8_t *duk__load_string_raw(duk_context *ctx, duk_uint8_t *p) {
11647 	duk_uint32_t len;
11648 
11649 	len = DUK_RAW_READ_U32_BE(p);
11650 	duk_push_lstring(ctx, (const char *) p, len);
11651 	p += len;
11652 	return p;
11653 }
11654 
duk__load_buffer_raw(duk_context * ctx,duk_uint8_t * p)11655 DUK_LOCAL duk_uint8_t *duk__load_buffer_raw(duk_context *ctx, duk_uint8_t *p) {
11656 	duk_uint32_t len;
11657 	duk_uint8_t *buf;
11658 
11659 	len = DUK_RAW_READ_U32_BE(p);
11660 	buf = (duk_uint8_t *) duk_push_fixed_buffer(ctx, (duk_size_t) len);
11661 	DUK_ASSERT(buf != NULL);
11662 	DUK_MEMCPY((void *) buf, (const void *) p, (size_t) len);
11663 	p += len;
11664 	return p;
11665 }
11666 
duk__dump_hstring_raw(duk_uint8_t * p,duk_hstring * h)11667 DUK_LOCAL duk_uint8_t *duk__dump_hstring_raw(duk_uint8_t *p, duk_hstring *h) {
11668 	duk_size_t len;
11669 	duk_uint32_t tmp32;
11670 
11671 	DUK_ASSERT(h != NULL);
11672 
11673 	len = DUK_HSTRING_GET_BYTELEN(h);
11674 	DUK_ASSERT(len <= 0xffffffffUL);  /* string limits */
11675 	tmp32 = (duk_uint32_t) len;
11676 	DUK_RAW_WRITE_U32_BE(p, tmp32);
11677 	DUK_MEMCPY((void *) p,
11678 	           (const void *) DUK_HSTRING_GET_DATA(h),
11679 	           len);
11680 	p += len;
11681 	return p;
11682 }
11683 
duk__dump_hbuffer_raw(duk_hthread * thr,duk_uint8_t * p,duk_hbuffer * h)11684 DUK_LOCAL duk_uint8_t *duk__dump_hbuffer_raw(duk_hthread *thr, duk_uint8_t *p, duk_hbuffer *h) {
11685 	duk_size_t len;
11686 	duk_uint32_t tmp32;
11687 
11688 	DUK_ASSERT(thr != NULL);
11689 	DUK_ASSERT(h != NULL);
11690 	DUK_UNREF(thr);
11691 
11692 	len = DUK_HBUFFER_GET_SIZE(h);
11693 	DUK_ASSERT(len <= 0xffffffffUL);  /* buffer limits */
11694 	tmp32 = (duk_uint32_t) len;
11695 	DUK_RAW_WRITE_U32_BE(p, tmp32);
11696 	DUK_MEMCPY((void *) p,
11697 	           (const void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h),
11698 	           len);
11699 	p += len;
11700 	return p;
11701 }
11702 
duk__dump_string_prop(duk_hthread * thr,duk_uint8_t * p,duk_bufwriter_ctx * bw_ctx,duk_hobject * func,duk_small_uint_t stridx)11703 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) {
11704 	duk_hstring *h_str;
11705 	duk_tval *tv;
11706 
11707 	tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) func, DUK_HTHREAD_GET_STRING(thr, stridx));
11708 	if (tv != NULL && DUK_TVAL_IS_STRING(tv)) {
11709 		h_str = DUK_TVAL_GET_STRING(tv);
11710 		DUK_ASSERT(h_str != NULL);
11711 	} else {
11712 		h_str = DUK_HTHREAD_STRING_EMPTY_STRING(thr);
11713 		DUK_ASSERT(h_str != NULL);
11714 	}
11715 	DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL);  /* ensures no overflow */
11716 	p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4 + DUK_HSTRING_GET_BYTELEN(h_str), p);
11717 	p = duk__dump_hstring_raw(p, h_str);
11718 	return p;
11719 }
11720 
duk__dump_buffer_prop(duk_hthread * thr,duk_uint8_t * p,duk_bufwriter_ctx * bw_ctx,duk_hobject * func,duk_small_uint_t stridx)11721 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) {
11722 	duk_tval *tv;
11723 
11724 	tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) func, DUK_HTHREAD_GET_STRING(thr, stridx));
11725 	if (tv != NULL && DUK_TVAL_IS_BUFFER(tv)) {
11726 		duk_hbuffer *h_buf;
11727 		h_buf = DUK_TVAL_GET_BUFFER(tv);
11728 		DUK_ASSERT(h_buf != NULL);
11729 		DUK_ASSERT(DUK_HBUFFER_MAX_BYTELEN <= 0x7fffffffUL);  /* ensures no overflow */
11730 		p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4 + DUK_HBUFFER_GET_SIZE(h_buf), p);
11731 		p = duk__dump_hbuffer_raw(thr, p, h_buf);
11732 	} else {
11733 		p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4, p);
11734 		DUK_RAW_WRITE_U32_BE(p, 0);
11735 	}
11736 	return p;
11737 }
11738 
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)11739 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) {
11740 	duk_tval *tv;
11741 	duk_uint32_t val;
11742 
11743 	tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) func, DUK_HTHREAD_GET_STRING(thr, stridx));
11744 	if (tv != NULL && DUK_TVAL_IS_NUMBER(tv)) {
11745 		val = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv);
11746 	} else {
11747 		val = def_value;
11748 	}
11749 	p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4, p);
11750 	DUK_RAW_WRITE_U32_BE(p, val);
11751 	return p;
11752 }
11753 
duk__dump_varmap(duk_hthread * thr,duk_uint8_t * p,duk_bufwriter_ctx * bw_ctx,duk_hobject * func)11754 DUK_LOCAL duk_uint8_t *duk__dump_varmap(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func) {
11755 	duk_tval *tv;
11756 
11757 	tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) func, DUK_HTHREAD_STRING_INT_VARMAP(thr));
11758 	if (tv != NULL && DUK_TVAL_IS_OBJECT(tv)) {
11759 		duk_hobject *h;
11760 		duk_uint_fast32_t i;
11761 
11762 		h = DUK_TVAL_GET_OBJECT(tv);
11763 		DUK_ASSERT(h != NULL);
11764 
11765 		/* We know _Varmap only has own properties so walk property
11766 		 * table directly.  We also know _Varmap is dense and all
11767 		 * values are numbers; assert for these.  GC and finalizers
11768 		 * shouldn't affect _Varmap so side effects should be fine.
11769 		 */
11770 		for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h); i++) {
11771 			duk_hstring *key;
11772 			duk_tval *tv_val;
11773 			duk_uint32_t val;
11774 
11775 			key = DUK_HOBJECT_E_GET_KEY(thr->heap, h, i);
11776 			DUK_ASSERT(key != NULL);  /* _Varmap is dense */
11777 			DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, h, i));
11778 			tv_val = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, h, i);
11779 			DUK_ASSERT(tv_val != NULL);
11780 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_val));  /* known to be number; in fact an integer */
11781 #if defined(DUK_USE_FASTINT)
11782 			DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv_val));
11783 			DUK_ASSERT(DUK_TVAL_GET_FASTINT(tv_val) == (duk_int64_t) DUK_TVAL_GET_FASTINT_U32(tv_val));  /* known to be 32-bit */
11784 			val = DUK_TVAL_GET_FASTINT_U32(tv_val);
11785 #else
11786 			val = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv_val);
11787 #endif
11788 
11789 			DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL);  /* ensures no overflow */
11790 			p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4 + DUK_HSTRING_GET_BYTELEN(key) + 4, p);
11791 			p = duk__dump_hstring_raw(p, key);
11792 			DUK_RAW_WRITE_U32_BE(p, val);
11793 		}
11794 	}
11795 	p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4, p);
11796 	DUK_RAW_WRITE_U32_BE(p, 0);  /* end of _Varmap */
11797 	return p;
11798 }
11799 
duk__dump_formals(duk_hthread * thr,duk_uint8_t * p,duk_bufwriter_ctx * bw_ctx,duk_hobject * func)11800 DUK_LOCAL duk_uint8_t *duk__dump_formals(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func) {
11801 	duk_tval *tv;
11802 
11803 	tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) func, DUK_HTHREAD_STRING_INT_FORMALS(thr));
11804 	if (tv != NULL && DUK_TVAL_IS_OBJECT(tv)) {
11805 		duk_hobject *h;
11806 		duk_uint_fast32_t i;
11807 
11808 		h = DUK_TVAL_GET_OBJECT(tv);
11809 		DUK_ASSERT(h != NULL);
11810 
11811 		/* We know _Formals is dense and all entries will be in the
11812 		 * array part.  GC and finalizers shouldn't affect _Formals
11813 		 * so side effects should be fine.
11814 		 */
11815 		for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(h); i++) {
11816 			duk_tval *tv_val;
11817 			duk_hstring *varname;
11818 
11819 			tv_val = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, h, i);
11820 			DUK_ASSERT(tv_val != NULL);
11821 			if (DUK_TVAL_IS_STRING(tv_val)) {
11822 				/* Array is dense and contains only strings, but ASIZE may
11823 				 * be larger than used part and there are UNUSED entries.
11824 				 */
11825 				varname = DUK_TVAL_GET_STRING(tv_val);
11826 				DUK_ASSERT(varname != NULL);
11827 
11828 				DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL);  /* ensures no overflow */
11829 				p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4 + DUK_HSTRING_GET_BYTELEN(varname), p);
11830 				p = duk__dump_hstring_raw(p, varname);
11831 			}
11832 		}
11833 	}
11834 	p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4, p);
11835 	DUK_RAW_WRITE_U32_BE(p, 0);  /* end of _Formals */
11836 	return p;
11837 }
11838 
duk__dump_func(duk_context * ctx,duk_hcompiledfunction * func,duk_bufwriter_ctx * bw_ctx,duk_uint8_t * p)11839 static duk_uint8_t *duk__dump_func(duk_context *ctx, duk_hcompiledfunction *func, duk_bufwriter_ctx *bw_ctx, duk_uint8_t *p) {
11840 	duk_hthread *thr;
11841 	duk_tval *tv, *tv_end;
11842 	duk_instr_t *ins, *ins_end;
11843 	duk_hobject **fn, **fn_end;
11844 	duk_hstring *h_str;
11845 	duk_uint32_t count_instr;
11846 	duk_uint32_t tmp32;
11847 	duk_uint16_t tmp16;
11848 	duk_double_t d;
11849 
11850 	thr = (duk_hthread *) ctx;
11851 	DUK_UNREF(ctx);
11852 	DUK_UNREF(thr);
11853 
11854 	DUK_DD(DUK_DDPRINT("dumping function %p to %p: "
11855 	                   "consts=[%p,%p[ (%ld bytes, %ld items), "
11856 	                   "funcs=[%p,%p[ (%ld bytes, %ld items), "
11857 	                   "code=[%p,%p[ (%ld bytes, %ld items)",
11858 	                   (void *) func,
11859 	                   (void *) p,
11860 	                   (void *) DUK_HCOMPILEDFUNCTION_GET_CONSTS_BASE(thr->heap, func),
11861 	                   (void *) DUK_HCOMPILEDFUNCTION_GET_CONSTS_END(thr->heap, func),
11862 	                   (long) DUK_HCOMPILEDFUNCTION_GET_CONSTS_SIZE(thr->heap, func),
11863 	                   (long) DUK_HCOMPILEDFUNCTION_GET_CONSTS_COUNT(thr->heap, func),
11864 	                   (void *) DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE(thr->heap, func),
11865 	                   (void *) DUK_HCOMPILEDFUNCTION_GET_FUNCS_END(thr->heap, func),
11866 	                   (long) DUK_HCOMPILEDFUNCTION_GET_FUNCS_SIZE(thr->heap, func),
11867 	                   (long) DUK_HCOMPILEDFUNCTION_GET_FUNCS_COUNT(thr->heap, func),
11868 	                   (void *) DUK_HCOMPILEDFUNCTION_GET_CODE_BASE(thr->heap, func),
11869 	                   (void *) DUK_HCOMPILEDFUNCTION_GET_CODE_END(thr->heap, func),
11870 	                   (long) DUK_HCOMPILEDFUNCTION_GET_CODE_SIZE(thr->heap, func),
11871 	                   (long) DUK_HCOMPILEDFUNCTION_GET_CODE_COUNT(thr->heap, func)));
11872 
11873 	DUK_ASSERT(DUK_USE_ESBC_MAX_BYTES <= 0x7fffffffUL);  /* ensures no overflow */
11874 	count_instr = (duk_uint32_t) DUK_HCOMPILEDFUNCTION_GET_CODE_COUNT(thr->heap, func);
11875 	p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 3 * 4 + 2 * 2 + 3 * 4 + count_instr * 4, p);
11876 
11877 	/* Fixed header info. */
11878 	tmp32 = count_instr;
11879 	DUK_RAW_WRITE_U32_BE(p, tmp32);
11880 	tmp32 = (duk_uint32_t) DUK_HCOMPILEDFUNCTION_GET_CONSTS_COUNT(thr->heap, func);
11881 	DUK_RAW_WRITE_U32_BE(p, tmp32);
11882 	tmp32 = (duk_uint32_t) DUK_HCOMPILEDFUNCTION_GET_FUNCS_COUNT(thr->heap, func);
11883 	DUK_RAW_WRITE_U32_BE(p, tmp32);
11884 	tmp16 = func->nregs;
11885 	DUK_RAW_WRITE_U16_BE(p, tmp16);
11886 	tmp16 = func->nargs;
11887 	DUK_RAW_WRITE_U16_BE(p, tmp16);
11888 #if defined(DUK_USE_DEBUGGER_SUPPORT)
11889 	tmp32 = func->start_line;
11890 	DUK_RAW_WRITE_U32_BE(p, tmp32);
11891 	tmp32 = func->end_line;
11892 	DUK_RAW_WRITE_U32_BE(p, tmp32);
11893 #else
11894 	DUK_RAW_WRITE_U32_BE(p, 0);
11895 	DUK_RAW_WRITE_U32_BE(p, 0);
11896 #endif
11897 	tmp32 = ((duk_heaphdr *) func)->h_flags & DUK_HEAPHDR_FLAGS_FLAG_MASK;
11898 	DUK_RAW_WRITE_U32_BE(p, tmp32);
11899 
11900 	/* Bytecode instructions: endian conversion needed unless
11901 	 * platform is big endian.
11902 	 */
11903 	ins = DUK_HCOMPILEDFUNCTION_GET_CODE_BASE(thr->heap, func);
11904 	ins_end = DUK_HCOMPILEDFUNCTION_GET_CODE_END(thr->heap, func);
11905 	DUK_ASSERT((duk_size_t) (ins_end - ins) == (duk_size_t) count_instr);
11906 #if defined(DUK_USE_INTEGER_BE)
11907 	DUK_MEMCPY((void *) p, (const void *) ins, (size_t) (ins_end - ins));
11908 	p += (size_t) (ins_end - ins);
11909 #else
11910 	while (ins != ins_end) {
11911 		tmp32 = (duk_uint32_t) (*ins);
11912 		DUK_RAW_WRITE_U32_BE(p, tmp32);
11913 		ins++;
11914 	}
11915 #endif
11916 
11917 	/* Constants: variable size encoding. */
11918 	tv = DUK_HCOMPILEDFUNCTION_GET_CONSTS_BASE(thr->heap, func);
11919 	tv_end = DUK_HCOMPILEDFUNCTION_GET_CONSTS_END(thr->heap, func);
11920 	while (tv != tv_end) {
11921 		/* constants are strings or numbers now */
11922 		DUK_ASSERT(DUK_TVAL_IS_STRING(tv) ||
11923 		           DUK_TVAL_IS_NUMBER(tv));
11924 
11925 		if (DUK_TVAL_IS_STRING(tv)) {
11926 			h_str = DUK_TVAL_GET_STRING(tv);
11927 			DUK_ASSERT(h_str != NULL);
11928 			DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL);  /* ensures no overflow */
11929 			p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 1 + 4 + DUK_HSTRING_GET_BYTELEN(h_str), p),
11930 			*p++ = DUK__SER_STRING;
11931 			p = duk__dump_hstring_raw(p, h_str);
11932 		} else {
11933 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
11934 			p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 1 + 8, p);
11935 			*p++ = DUK__SER_NUMBER;
11936 			d = DUK_TVAL_GET_NUMBER(tv);
11937 			DUK_RAW_WRITE_DOUBLE_BE(p, d);
11938 		}
11939 		tv++;
11940 	}
11941 
11942 	/* Inner functions recursively. */
11943 	fn = (duk_hobject **) DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE(thr->heap, func);
11944 	fn_end = (duk_hobject **) DUK_HCOMPILEDFUNCTION_GET_FUNCS_END(thr->heap, func);
11945 	while (fn != fn_end) {
11946 		/* XXX: This causes recursion up to inner function depth
11947 		 * which is normally not an issue, e.g. mark-and-sweep uses
11948 		 * a recursion limiter to avoid C stack issues.  Avoiding
11949 		 * this would mean some sort of a work list or just refusing
11950 		 * to serialize deep functions.
11951 		 */
11952 		DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION(*fn));
11953 		p = duk__dump_func(ctx, (duk_hcompiledfunction *) *fn, bw_ctx, p);
11954 		fn++;
11955 	}
11956 
11957 	/* Object extra properties.
11958 	 *
11959 	 * There are some difference between function templates and functions.
11960 	 * For example, function templates don't have .length and nargs is
11961 	 * normally used to instantiate the functions.
11962 	 */
11963 
11964 	p = duk__dump_uint32_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_LENGTH, (duk_uint32_t) func->nargs);
11965 	p = duk__dump_string_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_NAME);
11966 	p = duk__dump_string_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_FILE_NAME);
11967 	p = duk__dump_buffer_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_INT_PC2LINE);
11968 	p = duk__dump_varmap(thr, p, bw_ctx, (duk_hobject *) func);
11969 	p = duk__dump_formals(thr, p, bw_ctx, (duk_hobject *) func);
11970 
11971 	DUK_DD(DUK_DDPRINT("serialized function %p -> final pointer %p", (void *) func, (void *) p));
11972 
11973 	return p;
11974 }
11975 
11976 /* Load a function from bytecode.  The function object returned here must
11977  * match what is created by duk_js_push_closure() with respect to its flags,
11978  * properties, etc.
11979  *
11980  * NOTE: there are intentionally no input buffer length / bound checks.
11981  * Adding them would be easy but wouldn't ensure memory safety as untrusted
11982  * or broken bytecode is unsafe during execution unless the opcodes themselves
11983  * are validated (which is quite complex, especially for indirect opcodes).
11984  */
11985 
11986 #define DUK__ASSERT_LEFT(n) do { \
11987 		DUK_ASSERT((duk_size_t) (p_end - p) >= (duk_size_t) (n)); \
11988 	} while (0)
11989 
duk__load_func(duk_context * ctx,duk_uint8_t * p,duk_uint8_t * p_end)11990 static duk_uint8_t *duk__load_func(duk_context *ctx, duk_uint8_t *p, duk_uint8_t *p_end) {
11991 	duk_hthread *thr;
11992 	duk_hcompiledfunction *h_fun;
11993 	duk_hbuffer *h_data;
11994 	duk_size_t data_size;
11995 	duk_uint32_t count_instr, count_const, count_funcs;
11996 	duk_uint32_t n;
11997 	duk_uint32_t tmp32;
11998 	duk_small_uint_t const_type;
11999 	duk_uint8_t *fun_data;
12000 	duk_uint8_t *q;
12001 	duk_idx_t idx_base;
12002 	duk_tval *tv1;
12003 	duk_uarridx_t arr_idx;
12004 
12005 	/* XXX: There's some overlap with duk_js_closure() here, but
12006 	 * seems difficult to share code.  Ensure that the final function
12007 	 * looks the same as created by duk_js_closure().
12008 	 */
12009 
12010 	DUK_ASSERT(ctx != NULL);
12011 	thr = (duk_hthread *) ctx;
12012 
12013 	DUK_DD(DUK_DDPRINT("loading function, p=%p, p_end=%p", (void *) p, (void *) p_end));
12014 
12015 	DUK__ASSERT_LEFT(3 * 4);
12016 	count_instr = DUK_RAW_READ_U32_BE(p);
12017 	count_const = DUK_RAW_READ_U32_BE(p);
12018 	count_funcs = DUK_RAW_READ_U32_BE(p);
12019 
12020 	data_size = sizeof(duk_tval) * count_const +
12021 	            sizeof(duk_hobject *) * count_funcs +
12022 	            sizeof(duk_instr_t) * count_instr;
12023 
12024 	DUK_DD(DUK_DDPRINT("instr=%ld, const=%ld, funcs=%ld, data_size=%ld",
12025 	                   (long) count_instr, (long) count_const,
12026 	                   (long) count_const, (long) data_size));
12027 
12028 	/* Value stack is used to ensure reachability of constants and
12029 	 * inner functions being loaded.  Require enough space to handle
12030 	 * large functions correctly.
12031 	 */
12032 	duk_require_stack(ctx, 2 + count_const + count_funcs);
12033 	idx_base = duk_get_top(ctx);
12034 
12035 	/* Push function object, init flags etc.  This must match
12036 	 * duk_js_push_closure() quite carefully.
12037 	 */
12038 	duk_push_compiledfunction(ctx);
12039 	h_fun = duk_get_hcompiledfunction(ctx, -1);
12040 	DUK_ASSERT(h_fun != NULL);
12041 	DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION((duk_hobject *) h_fun));
12042 	DUK_ASSERT(DUK_HCOMPILEDFUNCTION_GET_DATA(thr->heap, h_fun) == NULL);
12043 	DUK_ASSERT(DUK_HCOMPILEDFUNCTION_GET_FUNCS(thr->heap, h_fun) == NULL);
12044 	DUK_ASSERT(DUK_HCOMPILEDFUNCTION_GET_BYTECODE(thr->heap, h_fun) == NULL);
12045 
12046 	h_fun->nregs = DUK_RAW_READ_U16_BE(p);
12047 	h_fun->nargs = DUK_RAW_READ_U16_BE(p);
12048 #if defined(DUK_USE_DEBUGGER_SUPPORT)
12049 	h_fun->start_line = DUK_RAW_READ_U32_BE(p);
12050 	h_fun->end_line = DUK_RAW_READ_U32_BE(p);
12051 #else
12052 	p += 8;  /* skip line info */
12053 #endif
12054 
12055 	/* duk_hcompiledfunction flags; quite version specific */
12056 	tmp32 = DUK_RAW_READ_U32_BE(p);
12057 	DUK_HEAPHDR_SET_FLAGS((duk_heaphdr *) h_fun, tmp32);
12058 
12059 	/* standard prototype */
12060 	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, &h_fun->obj, thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
12061 
12062 	/* assert just a few critical flags */
12063 	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) h_fun) == DUK_HTYPE_OBJECT);
12064 	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUND(&h_fun->obj));
12065 	DUK_ASSERT(DUK_HOBJECT_HAS_COMPILEDFUNCTION(&h_fun->obj));
12066 	DUK_ASSERT(!DUK_HOBJECT_HAS_NATIVEFUNCTION(&h_fun->obj));
12067 	DUK_ASSERT(!DUK_HOBJECT_HAS_THREAD(&h_fun->obj));
12068 	DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARRAY(&h_fun->obj));
12069 	DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(&h_fun->obj));
12070 	DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(&h_fun->obj));
12071 
12072 	/* Create function 'data' buffer but don't attach it yet. */
12073 	fun_data = (duk_uint8_t *) duk_push_fixed_buffer(ctx, data_size);
12074 	DUK_ASSERT(fun_data != NULL);
12075 
12076 	/* Load bytecode instructions. */
12077 	DUK_ASSERT(sizeof(duk_instr_t) == 4);
12078 	DUK__ASSERT_LEFT(count_instr * sizeof(duk_instr_t));
12079 #if defined(DUK_USE_INTEGER_BE)
12080 	q = fun_data + sizeof(duk_tval) * count_const + sizeof(duk_hobject *) * count_funcs;
12081 	DUK_MEMCPY((void *) q,
12082 	           (const void *) p,
12083 	           sizeof(duk_instr_t) * count_instr);
12084 	p += sizeof(duk_instr_t) * count_instr;
12085 #else
12086 	q = fun_data + sizeof(duk_tval) * count_const + sizeof(duk_hobject *) * count_funcs;
12087 	for (n = count_instr; n > 0; n--) {
12088 		*((duk_instr_t *) (void *) q) = DUK_RAW_READ_U32_BE(p);
12089 		q += sizeof(duk_instr_t);
12090 	}
12091 #endif
12092 
12093 	/* Load constants onto value stack but don't yet copy to buffer. */
12094 	for (n = count_const; n > 0; n--) {
12095 		DUK__ASSERT_LEFT(1);
12096 		const_type = DUK_RAW_READ_U8(p);
12097 		switch (const_type) {
12098 		case DUK__SER_STRING: {
12099 			p = duk__load_string_raw(ctx, p);
12100 			break;
12101 		}
12102 		case DUK__SER_NUMBER: {
12103 			/* Important to do a fastint check so that constants are
12104 			 * properly read back as fastints.
12105 			 */
12106 			duk_tval tv_tmp;
12107 			duk_double_t val;
12108 			DUK__ASSERT_LEFT(8);
12109 			val = DUK_RAW_READ_DOUBLE_BE(p);
12110 			DUK_TVAL_SET_NUMBER_CHKFAST(&tv_tmp, val);
12111 			duk_push_tval(ctx, &tv_tmp);
12112 			break;
12113 		}
12114 		default: {
12115 			goto format_error;
12116 		}
12117 		}
12118 	}
12119 
12120 	/* Load inner functions to value stack, but don't yet copy to buffer. */
12121 	for (n = count_funcs; n > 0; n--) {
12122 		p = duk__load_func(ctx, p, p_end);
12123 		if (p == NULL) {
12124 			goto format_error;
12125 		}
12126 	}
12127 
12128 	/* With constants and inner functions on value stack, we can now
12129 	 * atomically finish the function 'data' buffer, bump refcounts,
12130 	 * etc.
12131 	 *
12132 	 * Here we take advantage of the value stack being just a duk_tval
12133 	 * array: we can just memcpy() the constants as long as we incref
12134 	 * them afterwards.
12135 	 */
12136 
12137 	h_data = (duk_hbuffer *) duk_get_hbuffer(ctx, idx_base + 1);
12138 	DUK_ASSERT(h_data != NULL);
12139 	DUK_ASSERT(!DUK_HBUFFER_HAS_DYNAMIC(h_data));
12140 	DUK_HCOMPILEDFUNCTION_SET_DATA(thr->heap, h_fun, h_data);
12141 	DUK_HBUFFER_INCREF(thr, h_data);
12142 
12143 	tv1 = duk_get_tval(ctx, idx_base + 2);  /* may be NULL if no constants or inner funcs */
12144 	DUK_ASSERT((count_const == 0 && count_funcs == 0) || tv1 != NULL);
12145 
12146 	q = fun_data;
12147 	if (count_const > 0) {
12148 		/* Explicit zero size check to avoid NULL 'tv1'. */
12149 		DUK_MEMCPY((void *) q, (const void *) tv1, sizeof(duk_tval) * count_const);
12150 		for (n = count_const; n > 0; n--) {
12151 			DUK_TVAL_INCREF_FAST(thr, (duk_tval *) (void *) q);  /* no side effects */
12152 			q += sizeof(duk_tval);
12153 		}
12154 		tv1 += count_const;
12155 	}
12156 
12157 	DUK_HCOMPILEDFUNCTION_SET_FUNCS(thr->heap, h_fun, (duk_hobject **) (void *) q);
12158 	for (n = count_funcs; n > 0; n--) {
12159 		duk_hobject *h_obj;
12160 
12161 		DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv1));
12162 		h_obj = DUK_TVAL_GET_OBJECT(tv1);
12163 		DUK_ASSERT(h_obj != NULL);
12164 		tv1++;
12165 		DUK_HOBJECT_INCREF(thr, h_obj);
12166 
12167 		*((duk_hobject **) (void *) q) = h_obj;
12168 		q += sizeof(duk_hobject *);
12169 	}
12170 
12171 	DUK_HCOMPILEDFUNCTION_SET_BYTECODE(thr->heap, h_fun, (duk_instr_t *) (void *) q);
12172 
12173 	/* The function object is now reachable and refcounts are fine,
12174 	 * so we can pop off all the temporaries.
12175 	 */
12176 	DUK_DDD(DUK_DDDPRINT("function is reachable, reset top; func: %!iT", duk_get_tval(ctx, idx_base)));
12177 	duk_set_top(ctx, idx_base + 1);
12178 
12179 	/* Setup function properties. */
12180 	tmp32 = DUK_RAW_READ_U32_BE(p);
12181 	duk_push_u32(ctx, tmp32);
12182 	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_NONE);
12183 
12184 	p = duk__load_string_raw(ctx, p);
12185 	if (DUK_HOBJECT_HAS_NAMEBINDING((duk_hobject *) h_fun)) {
12186 		/* Original function instance/template had NAMEBINDING.
12187 		 * Must create a lexical environment on loading to allow
12188 		 * recursive functions like 'function foo() { foo(); }'.
12189 		 */
12190 		duk_hobject *proto;
12191 
12192 		proto = thr->builtins[DUK_BIDX_GLOBAL_ENV];
12193 		(void) duk_push_object_helper_proto(ctx,
12194 		                                    DUK_HOBJECT_FLAG_EXTENSIBLE |
12195 		                                    DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV),
12196 		                                    proto);
12197 		duk_dup(ctx, -2);                                 /* -> [ func funcname env funcname ] */
12198 		duk_dup(ctx, idx_base);                           /* -> [ func funcname env funcname func ] */
12199 		duk_xdef_prop(ctx, -3, DUK_PROPDESC_FLAGS_NONE);  /* -> [ func funcname env ] */
12200 		duk_xdef_prop_stridx(ctx, idx_base, DUK_STRIDX_INT_LEXENV, DUK_PROPDESC_FLAGS_WC);
12201 		/* since closure has NEWENV, never define DUK_STRIDX_INT_VARENV, as it
12202 		 * will be ignored anyway
12203 		 */
12204 	}
12205 	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_NONE);
12206 
12207 	p = duk__load_string_raw(ctx, p);
12208 	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_FILE_NAME, DUK_PROPDESC_FLAGS_WC);
12209 
12210 	duk_push_object(ctx);
12211 	duk_dup(ctx, -2);
12212 	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_CONSTRUCTOR, DUK_PROPDESC_FLAGS_WC);  /* func.prototype.constructor = func */
12213 	duk_compact(ctx, -1);
12214 	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_PROTOTYPE, DUK_PROPDESC_FLAGS_W);
12215 
12216 	p = duk__load_buffer_raw(ctx, p);
12217 	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_PC2LINE, DUK_PROPDESC_FLAGS_WC);
12218 
12219 	duk_push_object(ctx);  /* _Varmap */
12220 	for (;;) {
12221 		/* XXX: awkward */
12222 		p = duk__load_string_raw(ctx, p);
12223 		if (duk_get_length(ctx, -1) == 0) {
12224 			duk_pop(ctx);
12225 			break;
12226 		}
12227 		tmp32 = DUK_RAW_READ_U32_BE(p);
12228 		duk_push_u32(ctx, tmp32);
12229 		duk_put_prop(ctx, -3);
12230 	}
12231 	duk_compact(ctx, -1);
12232 	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_VARMAP, DUK_PROPDESC_FLAGS_NONE);
12233 
12234 	duk_push_array(ctx);  /* _Formals */
12235 	for (arr_idx = 0; ; arr_idx++) {
12236 		/* XXX: awkward */
12237 		p = duk__load_string_raw(ctx, p);
12238 		if (duk_get_length(ctx, -1) == 0) {
12239 			duk_pop(ctx);
12240 			break;
12241 		}
12242 		duk_put_prop_index(ctx, -2, arr_idx);
12243 	}
12244 	duk_compact(ctx, -1);
12245 	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_FORMALS, DUK_PROPDESC_FLAGS_NONE);
12246 
12247 	/* Return with final function pushed on stack top. */
12248 	DUK_DD(DUK_DDPRINT("final loaded function: %!iT", duk_get_tval(ctx, -1)));
12249 	DUK_ASSERT_TOP(ctx, idx_base + 1);
12250 	return p;
12251 
12252  format_error:
12253 	return NULL;
12254 }
12255 
duk_dump_function(duk_context * ctx)12256 DUK_EXTERNAL void duk_dump_function(duk_context *ctx) {
12257 	duk_hthread *thr;
12258 	duk_hcompiledfunction *func;
12259 	duk_bufwriter_ctx bw_ctx_alloc;
12260 	duk_bufwriter_ctx *bw_ctx = &bw_ctx_alloc;
12261 	duk_uint8_t *p;
12262 
12263 	DUK_ASSERT(ctx != NULL);
12264 	thr = (duk_hthread *) ctx;
12265 
12266 	/* Bound functions don't have all properties so we'd either need to
12267 	 * lookup the non-bound target function or reject bound functions.
12268 	 * For now, bound functions are rejected.
12269 	 */
12270 	func = duk_require_hcompiledfunction(ctx, -1);
12271 	DUK_ASSERT(func != NULL);
12272 	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUND(&func->obj));
12273 
12274 	/* Estimating the result size beforehand would be costly, so
12275 	 * start with a reasonable size and extend as needed.
12276 	 */
12277 	DUK_BW_INIT_PUSHBUF(thr, bw_ctx, DUK__BYTECODE_INITIAL_ALLOC);
12278 	p = DUK_BW_GET_PTR(thr, bw_ctx);
12279 	*p++ = DUK__SER_MARKER;
12280 	*p++ = DUK__SER_VERSION;
12281 	p = duk__dump_func(ctx, func, bw_ctx, p);
12282 	DUK_BW_SET_PTR(thr, bw_ctx, p);
12283 	DUK_BW_COMPACT(thr, bw_ctx);
12284 
12285 	DUK_DD(DUK_DDPRINT("serialized result: %!T", duk_get_tval(ctx, -1)));
12286 
12287 	duk_remove(ctx, -2);  /* [ ... func buf ] -> [ ... buf ] */
12288 }
12289 
duk_load_function(duk_context * ctx)12290 DUK_EXTERNAL void duk_load_function(duk_context *ctx) {
12291 	duk_hthread *thr;
12292 	duk_uint8_t *p_buf, *p, *p_end;
12293 	duk_size_t sz;
12294 
12295 	DUK_ASSERT(ctx != NULL);
12296 	thr = (duk_hthread *) ctx;
12297 	DUK_UNREF(ctx);
12298 
12299 	p_buf = (duk_uint8_t *) duk_require_buffer(ctx, -1, &sz);
12300 	DUK_ASSERT(p_buf != NULL);
12301 
12302 	/* The caller is responsible for being sure that bytecode being loaded
12303 	 * is valid and trusted.  Invalid bytecode can cause memory unsafe
12304 	 * behavior directly during loading or later during bytecode execution
12305 	 * (instruction validation would be quite complex to implement).
12306 	 *
12307 	 * This signature check is the only sanity check for detecting
12308 	 * accidental invalid inputs.  The initial 0xFF byte ensures no
12309 	 * ordinary string will be accepted by accident.
12310 	 */
12311 	p = p_buf;
12312 	p_end = p_buf + sz;
12313 	if (sz < 2 || p[0] != DUK__SER_MARKER || p[1] != DUK__SER_VERSION) {
12314 		goto format_error;
12315 	}
12316 	p += 2;
12317 
12318 	p = duk__load_func(ctx, p, p_end);
12319 	if (p == NULL) {
12320 		goto format_error;
12321 	}
12322 
12323 	duk_remove(ctx, -2);  /* [ ... buf func ] -> [ ... func ] */
12324 	return;
12325 
12326  format_error:
12327 	DUK_ERROR_TYPE(thr, DUK_STR_DECODE_FAILED);
12328 }
12329 
12330 #undef DUK__SER_MARKER
12331 #undef DUK__SER_VERSION
12332 #undef DUK__SER_STRING
12333 #undef DUK__SER_NUMBER
12334 #undef DUK__BYTECODE_INITIAL_ALLOC
12335 
12336 #else  /* DUK_USE_BYTECODE_DUMP_SUPPORT */
12337 
duk_dump_function(duk_context * ctx)12338 DUK_EXTERNAL void duk_dump_function(duk_context *ctx) {
12339 	DUK_ERROR_UNSUPPORTED_DEFMSG((duk_hthread *) ctx);
12340 }
12341 
duk_load_function(duk_context * ctx)12342 DUK_EXTERNAL void duk_load_function(duk_context *ctx) {
12343 	DUK_ERROR_UNSUPPORTED_DEFMSG((duk_hthread *) ctx);
12344 }
12345 
12346 #endif  /* DUK_USE_BYTECODE_DUMP_SUPPORT */
12347 /*
12348  *  Calls.
12349  *
12350  *  Protected variants should avoid ever throwing an error.
12351  */
12352 
12353 /* include removed: duk_internal.h */
12354 
12355 /* Prepare value stack for a method call through an object property.
12356  * May currently throw an error e.g. when getting the property.
12357  */
duk__call_prop_prep_stack(duk_context * ctx,duk_idx_t normalized_obj_index,duk_idx_t nargs)12358 DUK_LOCAL void duk__call_prop_prep_stack(duk_context *ctx, duk_idx_t normalized_obj_index, duk_idx_t nargs) {
12359 	DUK_ASSERT_CTX_VALID(ctx);
12360 
12361 	DUK_DDD(DUK_DDDPRINT("duk__call_prop_prep_stack, normalized_obj_index=%ld, nargs=%ld, stacktop=%ld",
12362 	                     (long) normalized_obj_index, (long) nargs, (long) duk_get_top(ctx)));
12363 
12364 	/* [... key arg1 ... argN] */
12365 
12366 	/* duplicate key */
12367 	duk_dup(ctx, -nargs - 1);  /* Note: -nargs alone would fail for nargs == 0, this is OK */
12368 	duk_get_prop(ctx, normalized_obj_index);
12369 
12370 	DUK_DDD(DUK_DDDPRINT("func: %!T", (duk_tval *) duk_get_tval(ctx, -1)));
12371 
12372 	/* [... key arg1 ... argN func] */
12373 
12374 	duk_replace(ctx, -nargs - 2);
12375 
12376 	/* [... func arg1 ... argN] */
12377 
12378 	duk_dup(ctx, normalized_obj_index);
12379 	duk_insert(ctx, -nargs - 1);
12380 
12381 	/* [... func this arg1 ... argN] */
12382 }
12383 
duk_call(duk_context * ctx,duk_idx_t nargs)12384 DUK_EXTERNAL void duk_call(duk_context *ctx, duk_idx_t nargs) {
12385 	duk_hthread *thr = (duk_hthread *) ctx;
12386 	duk_small_uint_t call_flags;
12387 	duk_idx_t idx_func;
12388 
12389 	DUK_ASSERT_CTX_VALID(ctx);
12390 	DUK_ASSERT(thr != NULL);
12391 
12392 	idx_func = duk_get_top(ctx) - nargs - 1;
12393 	if (idx_func < 0 || nargs < 0) {
12394 		/* note that we can't reliably pop anything here */
12395 		DUK_ERROR_API(thr, DUK_STR_INVALID_CALL_ARGS);
12396 	}
12397 
12398 	/* XXX: awkward; we assume there is space for this, overwrite
12399 	 * directly instead?
12400 	 */
12401 	duk_push_undefined(ctx);
12402 	duk_insert(ctx, idx_func + 1);
12403 
12404 	call_flags = 0;  /* not protected, respect reclimit, not constructor */
12405 
12406 	duk_handle_call_unprotected(thr,           /* thread */
12407 	                            nargs,         /* num_stack_args */
12408 	                            call_flags);   /* call_flags */
12409 }
12410 
duk_call_method(duk_context * ctx,duk_idx_t nargs)12411 DUK_EXTERNAL void duk_call_method(duk_context *ctx, duk_idx_t nargs) {
12412 	duk_hthread *thr = (duk_hthread *) ctx;
12413 	duk_small_uint_t call_flags;
12414 	duk_idx_t idx_func;
12415 
12416 	DUK_ASSERT_CTX_VALID(ctx);
12417 	DUK_ASSERT(thr != NULL);
12418 
12419 	idx_func = duk_get_top(ctx) - nargs - 2;  /* must work for nargs <= 0 */
12420 	if (idx_func < 0 || nargs < 0) {
12421 		/* note that we can't reliably pop anything here */
12422 		DUK_ERROR_API(thr, DUK_STR_INVALID_CALL_ARGS);
12423 	}
12424 
12425 	call_flags = 0;  /* not protected, respect reclimit, not constructor */
12426 
12427 	duk_handle_call_unprotected(thr,           /* thread */
12428 	                            nargs,         /* num_stack_args */
12429 	                            call_flags);   /* call_flags */
12430 }
12431 
duk_call_prop(duk_context * ctx,duk_idx_t obj_index,duk_idx_t nargs)12432 DUK_EXTERNAL void duk_call_prop(duk_context *ctx, duk_idx_t obj_index, duk_idx_t nargs) {
12433 	/*
12434 	 *  XXX: if duk_handle_call() took values through indices, this could be
12435 	 *  made much more sensible.  However, duk_handle_call() needs to fudge
12436 	 *  the 'this' and 'func' values to handle bound function chains, which
12437 	 *  is now done "in-place", so this is not a trivial change.
12438 	 */
12439 
12440 	DUK_ASSERT_CTX_VALID(ctx);
12441 
12442 	obj_index = duk_require_normalize_index(ctx, obj_index);  /* make absolute */
12443 	if (DUK_UNLIKELY(nargs < 0)) {
12444 		DUK_ERROR_API((duk_hthread *) ctx, DUK_STR_INVALID_CALL_ARGS);
12445 	}
12446 
12447 	duk__call_prop_prep_stack(ctx, obj_index, nargs);
12448 
12449 	duk_call_method(ctx, nargs);
12450 }
12451 
duk_pcall(duk_context * ctx,duk_idx_t nargs)12452 DUK_EXTERNAL duk_int_t duk_pcall(duk_context *ctx, duk_idx_t nargs) {
12453 	duk_hthread *thr = (duk_hthread *) ctx;
12454 	duk_small_uint_t call_flags;
12455 	duk_idx_t idx_func;
12456 	duk_int_t rc;
12457 
12458 	DUK_ASSERT_CTX_VALID(ctx);
12459 	DUK_ASSERT(thr != NULL);
12460 
12461 	idx_func = duk_get_top(ctx) - nargs - 1;  /* must work for nargs <= 0 */
12462 	if (idx_func < 0 || nargs < 0) {
12463 		/* We can't reliably pop anything here because the stack input
12464 		 * shape is incorrect.  So we throw an error; if the caller has
12465 		 * no catch point for this, a fatal error will occur.  Another
12466 		 * alternative would be to just return an error.  But then the
12467 		 * stack would be in an unknown state which might cause some
12468 		 * very hard to diagnose problems later on.  Also note that even
12469 		 * if we did not throw an error here, the underlying call handler
12470 		 * might STILL throw an out-of-memory error or some other internal
12471 		 * fatal error.
12472 		 */
12473 		DUK_ERROR_API(thr, DUK_STR_INVALID_CALL_ARGS);
12474 		return DUK_EXEC_ERROR;  /* unreachable */
12475 	}
12476 
12477 	/* awkward; we assume there is space for this */
12478 	duk_push_undefined(ctx);
12479 	duk_insert(ctx, idx_func + 1);
12480 
12481 	call_flags = 0;  /* respect reclimit, not constructor */
12482 
12483 	rc = duk_handle_call_protected(thr,           /* thread */
12484 	                               nargs,         /* num_stack_args */
12485 	                               call_flags);   /* call_flags */
12486 
12487 	return rc;
12488 }
12489 
duk_pcall_method(duk_context * ctx,duk_idx_t nargs)12490 DUK_EXTERNAL duk_int_t duk_pcall_method(duk_context *ctx, duk_idx_t nargs) {
12491 	duk_hthread *thr = (duk_hthread *) ctx;
12492 	duk_small_uint_t call_flags;
12493 	duk_idx_t idx_func;
12494 	duk_int_t rc;
12495 
12496 	DUK_ASSERT_CTX_VALID(ctx);
12497 	DUK_ASSERT(thr != NULL);
12498 
12499 	idx_func = duk_get_top(ctx) - nargs - 2;  /* must work for nargs <= 0 */
12500 	if (idx_func < 0 || nargs < 0) {
12501 		/* See comments in duk_pcall(). */
12502 		DUK_ERROR_API(thr, DUK_STR_INVALID_CALL_ARGS);
12503 		return DUK_EXEC_ERROR;  /* unreachable */
12504 	}
12505 
12506 	call_flags = 0;  /* respect reclimit, not constructor */
12507 
12508 	rc = duk_handle_call_protected(thr,           /* thread */
12509 	                               nargs,         /* num_stack_args */
12510 	                               call_flags);   /* call_flags */
12511 
12512 	return rc;
12513 }
12514 
duk__pcall_prop_raw(duk_context * ctx)12515 DUK_LOCAL duk_ret_t duk__pcall_prop_raw(duk_context *ctx) {
12516 	duk_idx_t obj_index;
12517 	duk_idx_t nargs;
12518 
12519 	/* Get the original arguments.  Note that obj_index may be a relative
12520 	 * index so the stack must have the same top when we use it.
12521 	 */
12522 
12523 	DUK_ASSERT_CTX_VALID(ctx);
12524 
12525 	obj_index = (duk_idx_t) duk_get_int(ctx, -2);
12526 	nargs = (duk_idx_t) duk_get_int(ctx, -1);
12527 	duk_pop_2(ctx);
12528 
12529 	obj_index = duk_require_normalize_index(ctx, obj_index);  /* make absolute */
12530 	duk__call_prop_prep_stack(ctx, obj_index, nargs);
12531 	duk_call_method(ctx, nargs);
12532 	return 1;
12533 }
12534 
duk_pcall_prop(duk_context * ctx,duk_idx_t obj_index,duk_idx_t nargs)12535 DUK_EXTERNAL duk_int_t duk_pcall_prop(duk_context *ctx, duk_idx_t obj_index, duk_idx_t nargs) {
12536 	/*
12537 	 *  Must be careful to catch errors related to value stack manipulation
12538 	 *  and property lookup, not just the call itself.
12539 	 */
12540 
12541 	DUK_ASSERT_CTX_VALID(ctx);
12542 
12543 	duk_push_idx(ctx, obj_index);
12544 	if (DUK_UNLIKELY(nargs < 0)) {
12545 		DUK_ERROR_API((duk_hthread *) ctx, DUK_STR_INVALID_CALL_ARGS);
12546 	}
12547 	duk_push_idx(ctx, nargs);
12548 
12549 	/* Inputs: explicit arguments (nargs), +1 for key, +2 for obj_index/nargs passing.
12550 	 * If the value stack does not contain enough args, an error is thrown; this matches
12551 	 * behavior of the other protected call API functions.
12552 	 */
12553 	return duk_safe_call(ctx, duk__pcall_prop_raw, nargs + 1 + 2 /*nargs*/, 1 /*nrets*/);
12554 }
12555 
duk_safe_call(duk_context * ctx,duk_safe_call_function func,duk_idx_t nargs,duk_idx_t nrets)12556 DUK_EXTERNAL duk_int_t duk_safe_call(duk_context *ctx, duk_safe_call_function func, duk_idx_t nargs, duk_idx_t nrets) {
12557 	duk_hthread *thr = (duk_hthread *) ctx;
12558 	duk_int_t rc;
12559 
12560 	DUK_ASSERT_CTX_VALID(ctx);
12561 	DUK_ASSERT(thr != NULL);
12562 
12563 	if (duk_get_top(ctx) < nargs || nargs < 0 || nrets < 0) {
12564 		/* See comments in duk_pcall(). */
12565 		DUK_ERROR_API(thr, DUK_STR_INVALID_CALL_ARGS);
12566 		return DUK_EXEC_ERROR;  /* unreachable */
12567 	}
12568 
12569 	rc = duk_handle_safe_call(thr,           /* thread */
12570 	                          func,          /* func */
12571 	                          nargs,         /* num_stack_args */
12572 	                          nrets);        /* num_stack_res */
12573 
12574 	return rc;
12575 }
12576 
duk_new(duk_context * ctx,duk_idx_t nargs)12577 DUK_EXTERNAL void duk_new(duk_context *ctx, duk_idx_t nargs) {
12578 	/*
12579 	 *  There are two [[Construct]] operations in the specification:
12580 	 *
12581 	 *    - E5 Section 13.2.2: for Function objects
12582 	 *    - E5 Section 15.3.4.5.2: for "bound" Function objects
12583 	 *
12584 	 *  The chain of bound functions is resolved in Section 15.3.4.5.2,
12585 	 *  with arguments "piling up" until the [[Construct]] internal
12586 	 *  method is called on the final, actual Function object.  Note
12587 	 *  that the "prototype" property is looked up *only* from the
12588 	 *  final object, *before* calling the constructor.
12589 	 *
12590 	 *  Currently we follow the bound function chain here to get the
12591 	 *  "prototype" property value from the final, non-bound function.
12592 	 *  However, we let duk_handle_call() handle the argument "piling"
12593 	 *  when the constructor is called.  The bound function chain is
12594 	 *  thus now processed twice.
12595 	 *
12596 	 *  When constructing new Array instances, an unnecessary object is
12597 	 *  created and discarded now: the standard [[Construct]] creates an
12598 	 *  object, and calls the Array constructor.  The Array constructor
12599 	 *  returns an Array instance, which is used as the result value for
12600 	 *  the "new" operation; the object created before the Array constructor
12601 	 *  call is discarded.
12602 	 *
12603 	 *  This would be easy to fix, e.g. by knowing that the Array constructor
12604 	 *  will always create a replacement object and skip creating the fallback
12605 	 *  object in that case.
12606 	 *
12607 	 *  Note: functions called via "new" need to know they are called as a
12608 	 *  constructor.  For instance, built-in constructors behave differently
12609 	 *  depending on how they are called.
12610 	 */
12611 
12612 	/* XXX: merge this with duk_js_call.c, as this function implements
12613 	 * core semantics (or perhaps merge the two files altogether).
12614 	 */
12615 
12616 	duk_hthread *thr = (duk_hthread *) ctx;
12617 	duk_hobject *proto;
12618 	duk_hobject *cons;
12619 	duk_hobject *fallback;
12620 	duk_idx_t idx_cons;
12621 	duk_small_uint_t call_flags;
12622 
12623 	DUK_ASSERT_CTX_VALID(ctx);
12624 
12625 	/* [... constructor arg1 ... argN] */
12626 
12627 	idx_cons = duk_require_normalize_index(ctx, -nargs - 1);
12628 
12629 	DUK_DDD(DUK_DDDPRINT("top=%ld, nargs=%ld, idx_cons=%ld",
12630 	                     (long) duk_get_top(ctx), (long) nargs, (long) idx_cons));
12631 
12632 	/* XXX: code duplication */
12633 
12634 	/*
12635 	 *  Figure out the final, non-bound constructor, to get "prototype"
12636 	 *  property.
12637 	 */
12638 
12639 	duk_dup(ctx, idx_cons);
12640 	for (;;) {
12641 		duk_tval *tv;
12642 		tv = DUK_GET_TVAL_NEGIDX(ctx, -1);
12643 		DUK_ASSERT(tv != NULL);
12644 
12645 		if (DUK_TVAL_IS_OBJECT(tv)) {
12646 			cons = DUK_TVAL_GET_OBJECT(tv);
12647 			DUK_ASSERT(cons != NULL);
12648 			if (!DUK_HOBJECT_IS_CALLABLE(cons) || !DUK_HOBJECT_HAS_CONSTRUCTABLE(cons)) {
12649 				/* Checking callability of the immediate target
12650 				 * is important, same for constructability.
12651 				 * Checking it for functions down the bound
12652 				 * function chain is not strictly necessary
12653 				 * because .bind() should normally reject them.
12654 				 * But it's good to check anyway because it's
12655 				 * technically possible to edit the bound function
12656 				 * chain via internal keys.
12657 				 */
12658 				goto not_constructable;
12659 			}
12660 			if (!DUK_HOBJECT_HAS_BOUND(cons)) {
12661 				break;
12662 			}
12663 		} else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
12664 			/* Lightfuncs cannot be bound. */
12665 			break;
12666 		} else {
12667 			/* Anything else is not constructable. */
12668 			goto not_constructable;
12669 		}
12670 		duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_TARGET);  /* -> [... cons target] */
12671 		duk_remove(ctx, -2);                                  /* -> [... target] */
12672 	}
12673 	DUK_ASSERT(duk_is_callable(ctx, -1));
12674 	DUK_ASSERT(duk_is_lightfunc(ctx, -1) ||
12675 	           (duk_get_hobject(ctx, -1) != NULL && !DUK_HOBJECT_HAS_BOUND(duk_get_hobject(ctx, -1))));
12676 
12677 	/* [... constructor arg1 ... argN final_cons] */
12678 
12679 	/*
12680 	 *  Create "fallback" object to be used as the object instance,
12681 	 *  unless the constructor returns a replacement value.
12682 	 *  Its internal prototype needs to be set based on "prototype"
12683 	 *  property of the constructor.
12684 	 */
12685 
12686 	duk_push_object(ctx);  /* class Object, extensible */
12687 
12688 	/* [... constructor arg1 ... argN final_cons fallback] */
12689 
12690 	duk_get_prop_stridx(ctx, -2, DUK_STRIDX_PROTOTYPE);
12691 	proto = duk_get_hobject(ctx, -1);
12692 	if (!proto) {
12693 		DUK_DDD(DUK_DDDPRINT("constructor has no 'prototype' property, or value not an object "
12694 		                     "-> leave standard Object prototype as fallback prototype"));
12695 	} else {
12696 		DUK_DDD(DUK_DDDPRINT("constructor has 'prototype' property with object value "
12697 		                     "-> set fallback prototype to that value: %!iO", (duk_heaphdr *) proto));
12698 		fallback = duk_get_hobject(ctx, -2);
12699 		DUK_ASSERT(fallback != NULL);
12700 		DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, fallback, proto);
12701 	}
12702 	duk_pop(ctx);
12703 
12704 	/* [... constructor arg1 ... argN final_cons fallback] */
12705 
12706 	/*
12707 	 *  Manipulate callstack for the call.
12708 	 */
12709 
12710 	duk_dup_top(ctx);
12711 	duk_insert(ctx, idx_cons + 1);  /* use fallback as 'this' value */
12712 	duk_insert(ctx, idx_cons);      /* also stash it before constructor,
12713 	                                 * in case we need it (as the fallback value)
12714 	                                 */
12715 	duk_pop(ctx);                   /* pop final_cons */
12716 
12717 
12718 	/* [... fallback constructor fallback(this) arg1 ... argN];
12719 	 * Note: idx_cons points to first 'fallback', not 'constructor'.
12720 	 */
12721 
12722 	DUK_DDD(DUK_DDDPRINT("before call, idx_cons+1 (constructor) -> %!T, idx_cons+2 (fallback/this) -> %!T, "
12723 	                     "nargs=%ld, top=%ld",
12724 	                     (duk_tval *) duk_get_tval(ctx, idx_cons + 1),
12725 	                     (duk_tval *) duk_get_tval(ctx, idx_cons + 2),
12726 	                     (long) nargs,
12727 	                     (long) duk_get_top(ctx)));
12728 
12729 	/*
12730 	 *  Call the constructor function (called in "constructor mode").
12731 	 */
12732 
12733 	call_flags = DUK_CALL_FLAG_CONSTRUCTOR_CALL;  /* not protected, respect reclimit, is a constructor call */
12734 
12735 	duk_handle_call_unprotected(thr,           /* thread */
12736 	                            nargs,         /* num_stack_args */
12737 	                            call_flags);   /* call_flags */
12738 
12739 	/* [... fallback retval] */
12740 
12741 	DUK_DDD(DUK_DDDPRINT("constructor call finished, fallback=%!iT, retval=%!iT",
12742 	                     (duk_tval *) duk_get_tval(ctx, -2),
12743 	                     (duk_tval *) duk_get_tval(ctx, -1)));
12744 
12745 	/*
12746 	 *  Determine whether to use the constructor return value as the created
12747 	 *  object instance or not.
12748 	 */
12749 
12750 	if (duk_is_object(ctx, -1)) {
12751 		duk_remove(ctx, -2);
12752 	} else {
12753 		duk_pop(ctx);
12754 	}
12755 
12756 	/*
12757 	 *  Augment created errors upon creation (not when they are thrown or
12758 	 *  rethrown).  __FILE__ and __LINE__ are not desirable here; the call
12759 	 *  stack reflects the caller which is correct.
12760 	 */
12761 
12762 #ifdef DUK_USE_AUGMENT_ERROR_CREATE
12763 	duk_hthread_sync_currpc(thr);
12764 	duk_err_augment_error_create(thr, thr, NULL, 0, 1 /*noblame_fileline*/);
12765 #endif
12766 
12767 	/* [... retval] */
12768 
12769 	return;
12770 
12771  not_constructable:
12772 	DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONSTRUCTABLE);
12773 }
12774 
duk__pnew_helper(duk_context * ctx)12775 DUK_LOCAL duk_ret_t duk__pnew_helper(duk_context *ctx) {
12776 	duk_uint_t nargs;
12777 
12778 	nargs = duk_to_uint(ctx, -1);
12779 	duk_pop(ctx);
12780 
12781 	duk_new(ctx, nargs);
12782 	return 1;
12783 }
12784 
duk_pnew(duk_context * ctx,duk_idx_t nargs)12785 DUK_EXTERNAL duk_int_t duk_pnew(duk_context *ctx, duk_idx_t nargs) {
12786 	duk_int_t rc;
12787 
12788 	DUK_ASSERT_CTX_VALID(ctx);
12789 
12790 	/* For now, just use duk_safe_call() to wrap duk_new().  We can't
12791 	 * simply use a protected duk_handle_call() because there's post
12792 	 * processing which might throw.  It should be possible to ensure
12793 	 * the post processing never throws (except in internal errors and
12794 	 * out of memory etc which are always allowed) and then remove this
12795 	 * wrapper.
12796 	 */
12797 
12798 	if (DUK_UNLIKELY(nargs < 0)) {
12799 		DUK_ERROR_API((duk_hthread *) ctx, DUK_STR_INVALID_CALL_ARGS);
12800 	}
12801 	duk_push_uint(ctx, nargs);
12802 	rc = duk_safe_call(ctx, duk__pnew_helper, nargs + 2 /*nargs*/, 1 /*nrets*/);
12803 	return rc;
12804 }
12805 
duk_is_constructor_call(duk_context * ctx)12806 DUK_EXTERNAL duk_bool_t duk_is_constructor_call(duk_context *ctx) {
12807 	duk_hthread *thr = (duk_hthread *) ctx;
12808 	duk_activation *act;
12809 
12810 	DUK_ASSERT_CTX_VALID(ctx);
12811 	DUK_ASSERT(thr != NULL);
12812 	DUK_ASSERT_DISABLE(thr->callstack_top >= 0);
12813 
12814 	act = duk_hthread_get_current_activation(thr);
12815 	if (act != NULL) {
12816 		return ((act->flags & DUK_ACT_FLAG_CONSTRUCT) != 0 ? 1 : 0);
12817 	}
12818 	return 0;
12819 }
12820 
duk_is_strict_call(duk_context * ctx)12821 DUK_EXTERNAL duk_bool_t duk_is_strict_call(duk_context *ctx) {
12822 	duk_hthread *thr = (duk_hthread *) ctx;
12823 	duk_activation *act;
12824 
12825 	/* For user code this could just return 1 (strict) always
12826 	 * because all Duktape/C functions are considered strict,
12827 	 * and strict is also the default when nothing is running.
12828 	 * However, Duktape may call this function internally when
12829 	 * the current activation is an Ecmascript function, so
12830 	 * this cannot be replaced by a 'return 1' without fixing
12831 	 * the internal call sites.
12832 	 */
12833 
12834 	DUK_ASSERT_CTX_VALID(ctx);
12835 	DUK_ASSERT(thr != NULL);
12836 	DUK_ASSERT_DISABLE(thr->callstack_top >= 0);
12837 
12838 	act = duk_hthread_get_current_activation(thr);
12839 	if (act == NULL) {
12840 		/* Strict by default. */
12841 		return 1;
12842 	}
12843 	return ((act->flags & DUK_ACT_FLAG_STRICT) != 0 ? 1 : 0);
12844 }
12845 
12846 /*
12847  *  Duktape/C function magic
12848  */
12849 
duk_get_current_magic(duk_context * ctx)12850 DUK_EXTERNAL duk_int_t duk_get_current_magic(duk_context *ctx) {
12851 	duk_hthread *thr = (duk_hthread *) ctx;
12852 	duk_activation *act;
12853 	duk_hobject *func;
12854 
12855 	DUK_ASSERT_CTX_VALID(ctx);
12856 	DUK_ASSERT(thr != NULL);
12857 	DUK_ASSERT_DISABLE(thr->callstack_top >= 0);
12858 
12859 	act = duk_hthread_get_current_activation(thr);
12860 	if (act) {
12861 		func = DUK_ACT_GET_FUNC(act);
12862 		if (!func) {
12863 			duk_tval *tv = &act->tv_func;
12864 			duk_small_uint_t lf_flags;
12865 			lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv);
12866 			return (duk_int_t) DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags);
12867 		}
12868 		DUK_ASSERT(func != NULL);
12869 
12870 		if (DUK_HOBJECT_IS_NATIVEFUNCTION(func)) {
12871 			duk_hnativefunction *nf = (duk_hnativefunction *) func;
12872 			return (duk_int_t) nf->magic;
12873 		}
12874 	}
12875 	return 0;
12876 }
12877 
duk_get_magic(duk_context * ctx,duk_idx_t index)12878 DUK_EXTERNAL duk_int_t duk_get_magic(duk_context *ctx, duk_idx_t index) {
12879 	duk_hthread *thr = (duk_hthread *) ctx;
12880 	duk_tval *tv;
12881 	duk_hobject *h;
12882 
12883 	DUK_ASSERT_CTX_VALID(ctx);
12884 
12885 	tv = duk_require_tval(ctx, index);
12886 	if (DUK_TVAL_IS_OBJECT(tv)) {
12887 		h = DUK_TVAL_GET_OBJECT(tv);
12888 		DUK_ASSERT(h != NULL);
12889 		if (!DUK_HOBJECT_HAS_NATIVEFUNCTION(h)) {
12890 			goto type_error;
12891 		}
12892 		return (duk_int_t) ((duk_hnativefunction *) h)->magic;
12893 	} else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
12894 		duk_small_uint_t lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv);
12895 		return (duk_int_t) DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags);
12896 	}
12897 
12898 	/* fall through */
12899  type_error:
12900 	DUK_ERROR_TYPE(thr, DUK_STR_UNEXPECTED_TYPE);
12901 	return 0;
12902 }
12903 
duk_set_magic(duk_context * ctx,duk_idx_t index,duk_int_t magic)12904 DUK_EXTERNAL void duk_set_magic(duk_context *ctx, duk_idx_t index, duk_int_t magic) {
12905 	duk_hnativefunction *nf;
12906 
12907 	DUK_ASSERT_CTX_VALID(ctx);
12908 
12909 	nf = duk_require_hnativefunction(ctx, index);
12910 	DUK_ASSERT(nf != NULL);
12911 	nf->magic = (duk_int16_t) magic;
12912 }
12913 /*
12914  *  Encoding and decoding basic formats: hex, base64.
12915  *
12916  *  These are in-place operations which may allow an optimized implementation.
12917  *
12918  *  Base-64: https://tools.ietf.org/html/rfc4648#section-4
12919  */
12920 
12921 /* include removed: duk_internal.h */
12922 
12923 /* Shared handling for encode/decode argument.  Fast path handling for
12924  * buffer and string values because they're the most common.  In particular,
12925  * avoid creating a temporary string or buffer when possible.
12926  */
duk__prep_codec_arg(duk_context * ctx,duk_idx_t index,duk_size_t * out_len)12927 DUK_LOCAL const duk_uint8_t *duk__prep_codec_arg(duk_context *ctx, duk_idx_t index, duk_size_t *out_len) {
12928 	DUK_ASSERT(duk_is_valid_index(ctx, index));  /* checked by caller */
12929 	if (duk_is_buffer(ctx, index)) {
12930 		return (const duk_uint8_t *) duk_get_buffer(ctx, index, out_len);
12931 	} else {
12932 		return (const duk_uint8_t *) duk_to_lstring(ctx, index, out_len);
12933 	}
12934 }
12935 
12936 #if defined(DUK_USE_BASE64_FASTPATH)
duk__base64_encode_helper(const duk_uint8_t * src,duk_size_t srclen,duk_uint8_t * dst)12937 DUK_LOCAL void duk__base64_encode_helper(const duk_uint8_t *src, duk_size_t srclen, duk_uint8_t *dst) {
12938 	duk_uint_t t;
12939 	duk_size_t n_full, n_full3, n_final;
12940 	const duk_uint8_t *src_end_fast;
12941 
12942 	n_full = srclen / 3;  /* full 3-byte -> 4-char conversions */
12943 	n_full3 = n_full * 3;
12944 	n_final = srclen - n_full3;
12945 	DUK_ASSERT_DISABLE(n_final >= 0);
12946 	DUK_ASSERT(n_final <= 2);
12947 
12948 	src_end_fast = src + n_full3;
12949 	while (DUK_UNLIKELY(src != src_end_fast)) {
12950 		t = (duk_uint_t) (*src++);
12951 		t = (t << 8) + (duk_uint_t) (*src++);
12952 		t = (t << 8) + (duk_uint_t) (*src++);
12953 
12954 		*dst++ = duk_base64_enctab[t >> 18];
12955 		*dst++ = duk_base64_enctab[(t >> 12) & 0x3f];
12956 		*dst++ = duk_base64_enctab[(t >> 6) & 0x3f];
12957 		*dst++ = duk_base64_enctab[t & 0x3f];
12958 
12959 #if 0  /* Tested: not faster on x64 */
12960 		/* aaaaaabb bbbbcccc ccdddddd */
12961 		dst[0] = duk_base64_enctab[(src[0] >> 2) & 0x3f];
12962 		dst[1] = duk_base64_enctab[((src[0] << 4) & 0x30) | ((src[1] >> 4) & 0x0f)];
12963 		dst[2] = duk_base64_enctab[((src[1] << 2) & 0x3f) | ((src[2] >> 6) & 0x03)];
12964 		dst[3] = duk_base64_enctab[src[2] & 0x3f];
12965 		src += 3; dst += 4;
12966 #endif
12967 	}
12968 
12969 	switch (n_final) {
12970 	/* case 0: nop */
12971 	case 1: {
12972 		/* XX== */
12973 		t = (duk_uint_t) (*src++);
12974 		*dst++ = duk_base64_enctab[t >> 2];           /* XXXXXX-- */
12975 		*dst++ = duk_base64_enctab[(t << 4) & 0x3f];  /* ------XX */
12976 		*dst++ = DUK_ASC_EQUALS;
12977 		*dst++ = DUK_ASC_EQUALS;
12978 		break;
12979 	}
12980 	case 2: {
12981 		/* XXX= */
12982 		t = (duk_uint_t) (*src++);
12983 		t = (t << 8) + (duk_uint_t) (*src++);
12984 		*dst++ = duk_base64_enctab[t >> 10];          /* XXXXXX-- -------- */
12985 		*dst++ = duk_base64_enctab[(t >> 4) & 0x3f];  /* ------XX XXXX---- */
12986 		*dst++ = duk_base64_enctab[(t << 2) & 0x3f];  /* -------- ----XXXX */
12987 		*dst++ = DUK_ASC_EQUALS;
12988 		break;
12989 	}
12990 	}
12991 }
12992 #else  /* DUK_USE_BASE64_FASTPATH */
duk__base64_encode_helper(const duk_uint8_t * src,duk_size_t srclen,duk_uint8_t * dst)12993 DUK_LOCAL void duk__base64_encode_helper(const duk_uint8_t *src, duk_size_t srclen, duk_uint8_t *dst) {
12994 	duk_small_uint_t i, snip;
12995 	duk_uint_t t;
12996 	duk_uint_fast8_t x, y;
12997 	const duk_uint8_t *src_end;
12998 
12999 	src_end = src + srclen;
13000 
13001 	while (src < src_end) {
13002 		/* read 3 bytes into 't', padded by zero */
13003 		snip = 4;
13004 		t = 0;
13005 		for (i = 0; i < 3; i++) {
13006 			t = t << 8;
13007 			if (src >= src_end) {
13008 				snip--;
13009 			} else {
13010 				t += (duk_uint_t) (*src++);
13011 			}
13012 		}
13013 
13014 		/*
13015 		 *  Missing bytes    snip     base64 example
13016 		 *    0               4         XXXX
13017 		 *    1               3         XXX=
13018 		 *    2               2         XX==
13019 		 */
13020 
13021 		DUK_ASSERT(snip >= 2 && snip <= 4);
13022 
13023 		for (i = 0; i < 4; i++) {
13024 			x = (duk_uint_fast8_t) ((t >> 18) & 0x3f);
13025 			t = t << 6;
13026 
13027 			/* A straightforward 64-byte lookup would be faster
13028 			 * and cleaner, but this is shorter.
13029 			 */
13030 			if (i >= snip) {
13031 				y = '=';
13032 			} else if (x <= 25) {
13033 				y = x + 'A';
13034 			} else if (x <= 51) {
13035 				y = x - 26 + 'a';
13036 			} else if (x <= 61) {
13037 				y = x - 52 + '0';
13038 			} else if (x == 62) {
13039 				y = '+';
13040 			} else {
13041 				y = '/';
13042 			}
13043 
13044 			*dst++ = (duk_uint8_t) y;
13045 		}
13046 	}
13047 }
13048 #endif  /* DUK_USE_BASE64_FASTPATH */
13049 
13050 #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)13051 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) {
13052 	duk_int_t x;
13053 	duk_int_t t;
13054 	duk_small_uint_t n_equal;
13055 	duk_small_uint_t n_chars;
13056 	const duk_uint8_t *src_end;
13057 	const duk_uint8_t *src_end_safe;
13058 
13059 	src_end = src + srclen;
13060 	src_end_safe = src_end - 4;  /* if 'src < src_end_safe', safe to read 4 bytes */
13061 
13062 	/* Innermost fast path processes 4 valid base-64 characters at a time
13063 	 * but bails out on whitespace, padding chars ('=') and invalid chars.
13064 	 * Once the slow path segment has been processed, we return to the
13065 	 * inner fast path again.  This handles e.g. base64 with newlines
13066 	 * reasonably well because the majority of a line is in the fast path.
13067 	 */
13068 	for (;;) {
13069 		/* Fast path, handle units with just actual encoding characters. */
13070 
13071 		while (src <= src_end_safe) {
13072 			/* The lookup byte is intentionally sign extended to (at least)
13073 			 * 32 bits and then ORed.  This ensures that is at least 1 byte
13074 			 * is negative, the highest bit of 't' will be set at the end
13075 			 * and we don't need to check every byte.
13076 			 */
13077 			DUK_DDD(DUK_DDDPRINT("fast loop: src=%p, src_end_safe=%p, src_end=%p",
13078 			                     (const void *) src, (const void *) src_end_safe, (const void *) src_end));
13079 
13080 			t = (duk_int_t) duk_base64_dectab[*src++];
13081 			t = (t << 6) | (duk_int_t) duk_base64_dectab[*src++];
13082 			t = (t << 6) | (duk_int_t) duk_base64_dectab[*src++];
13083 			t = (t << 6) | (duk_int_t) duk_base64_dectab[*src++];
13084 
13085 			if (DUK_UNLIKELY(t < 0)) {
13086 				DUK_DDD(DUK_DDDPRINT("fast loop unit was not clean, process one slow path unit"));
13087 				src -= 4;
13088 				break;
13089 			}
13090 
13091 			DUK_ASSERT(t <= 0xffffffL);
13092 			DUK_ASSERT((t >> 24) == 0);
13093 			*dst++ = (duk_uint8_t) (t >> 16);
13094 			*dst++ = (duk_uint8_t) ((t >> 8) & 0xff);
13095 			*dst++ = (duk_uint8_t) (t & 0xff);
13096 		}
13097 
13098 		/* Handle one slow path unit (or finish if we're done). */
13099 
13100 		n_equal = 0;
13101 		n_chars = 0;
13102 		t = 0;
13103 		for (;;) {
13104 			DUK_DDD(DUK_DDDPRINT("slow loop: src=%p, src_end=%p, n_chars=%ld, n_equal=%ld, t=%ld",
13105 			                     (const void *) src, (const void *) src_end, (long) n_chars, (long) n_equal, (long) t));
13106 
13107 			if (DUK_UNLIKELY(src >= src_end)) {
13108 				goto done;  /* two level break */
13109 			}
13110 
13111 			x = duk_base64_dectab[*src++];
13112 			if (DUK_UNLIKELY(x < 0)) {
13113 				if (x == -2) {
13114 					continue;  /* allowed ascii whitespace */
13115 				} else if (x == -3) {
13116 					n_equal++;
13117 					t <<= 6;
13118 				} else {
13119 					DUK_ASSERT(x == -1);
13120 					goto error;
13121 				}
13122 			} else {
13123 				DUK_ASSERT(x >= 0 && x <= 63);
13124 				if (n_equal > 0) {
13125 					/* Don't allow actual chars after equal sign. */
13126 					goto error;
13127 				}
13128 				t = (t << 6) + x;
13129 			}
13130 
13131 			if (DUK_UNLIKELY(n_chars == 3)) {
13132 				/* Emit 3 bytes and backtrack if there was padding.  There's
13133 				 * always space for the whole 3 bytes so no check needed.
13134 				 */
13135 				DUK_ASSERT(t <= 0xffffffL);
13136 				DUK_ASSERT((t >> 24) == 0);
13137 				*dst++ = (duk_uint8_t) (t >> 16);
13138 				*dst++ = (duk_uint8_t) ((t >> 8) & 0xff);
13139 				*dst++ = (duk_uint8_t) (t & 0xff);
13140 
13141 				if (DUK_UNLIKELY(n_equal > 0)) {
13142 					DUK_ASSERT(n_equal <= 4);
13143 
13144 					/* There may be whitespace between the equal signs. */
13145 					if (n_equal == 1) {
13146 						/* XXX= */
13147 						dst -= 1;
13148 					} else if (n_equal == 2) {
13149 						/* XX== */
13150 						dst -= 2;
13151 					} else {
13152 						goto error;  /* invalid padding */
13153 					}
13154 
13155 					/* Continue parsing after padding, allows concatenated,
13156 					 * padded base64.
13157 					 */
13158 				}
13159 				break;  /* back to fast loop */
13160 			} else {
13161 				n_chars++;
13162 			}
13163 		}
13164 	}
13165  done:
13166 	DUK_DDD(DUK_DDDPRINT("done; src=%p, src_end=%p, n_chars=%ld",
13167 	                     (const void *) src, (const void *) src_end, (long) n_chars));
13168 
13169 	DUK_ASSERT(src == src_end);
13170 
13171 	if (n_chars != 0) {
13172 		/* Here we'd have the option of decoding unpadded base64
13173 		 * (e.g. "xxxxyy" instead of "xxxxyy==".  Currently not
13174 		 * accepted.
13175 		 */
13176 		goto error;
13177 	}
13178 
13179 	*out_dst_final = dst;
13180 	return 1;
13181 
13182  error:
13183 	return 0;
13184 }
13185 #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)13186 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) {
13187 	duk_uint_t t;
13188 	duk_uint_fast8_t x, y;
13189 	duk_small_uint_t group_idx;
13190 	duk_small_uint_t n_equal;
13191 	const duk_uint8_t *src_end;
13192 
13193 	src_end = src + srclen;
13194 	t = 0;
13195 	group_idx = 0;
13196 	n_equal = 0;
13197 
13198 	while (src < src_end) {
13199 		x = *src++;
13200 
13201 		if (x >= 'A' && x <= 'Z') {
13202 			y = x - 'A' + 0;
13203 		} else if (x >= 'a' && x <= 'z') {
13204 			y = x - 'a' + 26;
13205 		} else if (x >= '0' && x <= '9') {
13206 			y = x - '0' + 52;
13207 		} else if (x == '+') {
13208 			y = 62;
13209 		} else if (x == '/') {
13210 			y = 63;
13211 		} else if (x == '=') {
13212 			/* We don't check the zero padding bytes here right now
13213 			 * (that they're actually zero).  This seems to be common
13214 			 * behavior for base-64 decoders.
13215 			 */
13216 
13217 			n_equal++;
13218 			t <<= 6;  /* shift in zeroes */
13219 			goto skip_add;
13220 		} else if (x == 0x09 || x == 0x0a || x == 0x0d || x == 0x20) {
13221 			/* allow basic ASCII whitespace */
13222 			continue;
13223 		} else {
13224 			goto error;
13225 		}
13226 
13227 		if (n_equal > 0) {
13228 			/* Don't allow mixed padding and actual chars. */
13229 			goto error;
13230 		}
13231 		t = (t << 6) + y;
13232 	 skip_add:
13233 
13234 		if (group_idx == 3) {
13235 			/* output 3 bytes from 't' */
13236 			*dst++ = (duk_uint8_t) ((t >> 16) & 0xff);
13237 			*dst++ = (duk_uint8_t) ((t >> 8) & 0xff);
13238 			*dst++ = (duk_uint8_t) (t & 0xff);
13239 
13240 			if (DUK_UNLIKELY(n_equal > 0)) {
13241 				/* Backtrack. */
13242 				DUK_ASSERT(n_equal <= 4);
13243 				if (n_equal == 1) {
13244 					dst -= 1;
13245 				} else if (n_equal == 2) {
13246 					dst -= 2;
13247 				} else {
13248 					goto error;  /* invalid padding */
13249 				}
13250 
13251 				/* Here we can choose either to end parsing and ignore
13252 				 * whatever follows, or to continue parsing in case
13253 				 * multiple (possibly padded) base64 strings have been
13254 				 * concatenated.  Currently, keep on parsing.
13255 				 */
13256 				n_equal = 0;
13257 			}
13258 
13259 			t = 0;
13260 			group_idx = 0;
13261 		} else {
13262 			group_idx++;
13263 		}
13264 	}
13265 
13266 	if (group_idx != 0) {
13267 		/* Here we'd have the option of decoding unpadded base64
13268 		 * (e.g. "xxxxyy" instead of "xxxxyy==".  Currently not
13269 		 * accepted.
13270 		 */
13271 		goto error;
13272 	}
13273 
13274 	*out_dst_final = dst;
13275 	return 1;
13276 
13277  error:
13278 	return 0;
13279 }
13280 #endif  /* DUK_USE_BASE64_FASTPATH */
13281 
duk_base64_encode(duk_context * ctx,duk_idx_t index)13282 DUK_EXTERNAL const char *duk_base64_encode(duk_context *ctx, duk_idx_t index) {
13283 	duk_hthread *thr = (duk_hthread *) ctx;
13284 	const duk_uint8_t *src;
13285 	duk_size_t srclen;
13286 	duk_size_t dstlen;
13287 	duk_uint8_t *dst;
13288 	const char *ret;
13289 
13290 	DUK_ASSERT_CTX_VALID(ctx);
13291 
13292 	/* XXX: optimize for string inputs: no need to coerce to a buffer
13293 	 * which makes a copy of the input.
13294 	 */
13295 
13296 	index = duk_require_normalize_index(ctx, index);
13297 	src = duk__prep_codec_arg(ctx, index, &srclen);
13298 	/* Note: for srclen=0, src may be NULL */
13299 
13300 	/* Computation must not wrap; this limit works for 32-bit size_t:
13301 	 * >>> srclen = 3221225469
13302 	 * >>> '%x' % ((srclen + 2) / 3 * 4)
13303 	 * 'fffffffc'
13304 	 */
13305 	if (srclen > 3221225469UL) {
13306 		goto type_error;
13307 	}
13308 	dstlen = (srclen + 2) / 3 * 4;
13309 	dst = (duk_uint8_t *) duk_push_fixed_buffer(ctx, dstlen);
13310 
13311 	duk__base64_encode_helper((const duk_uint8_t *) src, srclen, dst);
13312 
13313 	ret = duk_to_string(ctx, -1);
13314 	duk_replace(ctx, index);
13315 	return ret;
13316 
13317  type_error:
13318 	DUK_ERROR_TYPE(thr, DUK_STR_ENCODE_FAILED);
13319 	return NULL;  /* never here */
13320 }
13321 
duk_base64_decode(duk_context * ctx,duk_idx_t index)13322 DUK_EXTERNAL void duk_base64_decode(duk_context *ctx, duk_idx_t index) {
13323 	duk_hthread *thr = (duk_hthread *) ctx;
13324 	const duk_uint8_t *src;
13325 	duk_size_t srclen;
13326 	duk_size_t dstlen;
13327 	duk_uint8_t *dst;
13328 	duk_uint8_t *dst_final;
13329 	duk_bool_t retval;
13330 
13331 	DUK_ASSERT_CTX_VALID(ctx);
13332 
13333 	/* XXX: optimize for buffer inputs: no need to coerce to a string
13334 	 * which causes an unnecessary interning.
13335 	 */
13336 
13337 	index = duk_require_normalize_index(ctx, index);
13338 	src = duk__prep_codec_arg(ctx, index, &srclen);
13339 
13340 	/* Computation must not wrap, only srclen + 3 is at risk of
13341 	 * wrapping because after that the number gets smaller.
13342 	 * This limit works for 32-bit size_t:
13343 	 * 0x100000000 - 3 - 1 = 4294967292
13344 	 */
13345 	if (srclen > 4294967292UL) {
13346 		goto type_error;
13347 	}
13348 	dstlen = (srclen + 3) / 4 * 3;  /* upper limit, assuming no whitespace etc */
13349 	dst = (duk_uint8_t *) duk_push_dynamic_buffer(ctx, dstlen);
13350 	/* Note: for dstlen=0, dst may be NULL */
13351 
13352 	retval = duk__base64_decode_helper((const duk_uint8_t *) src, srclen, dst, &dst_final);
13353 	if (!retval) {
13354 		goto type_error;
13355 	}
13356 
13357 	/* XXX: convert to fixed buffer? */
13358 	(void) duk_resize_buffer(ctx, -1, (duk_size_t) (dst_final - dst));
13359 	duk_replace(ctx, index);
13360 	return;
13361 
13362  type_error:
13363 	DUK_ERROR_TYPE(thr, DUK_STR_DECODE_FAILED);
13364 }
13365 
duk_hex_encode(duk_context * ctx,duk_idx_t index)13366 DUK_EXTERNAL const char *duk_hex_encode(duk_context *ctx, duk_idx_t index) {
13367 	const duk_uint8_t *inp;
13368 	duk_size_t len;
13369 	duk_size_t i;
13370 	duk_uint8_t *buf;
13371 	const char *ret;
13372 #if defined(DUK_USE_HEX_FASTPATH)
13373 	duk_size_t len_safe;
13374 	duk_uint16_t *p16;
13375 #endif
13376 
13377 	DUK_ASSERT_CTX_VALID(ctx);
13378 
13379 	index = duk_require_normalize_index(ctx, index);
13380 	inp = duk__prep_codec_arg(ctx, index, &len);
13381 	DUK_ASSERT(inp != NULL || len == 0);
13382 
13383 	/* Fixed buffer, no zeroing because we'll fill all the data. */
13384 	buf = (duk_uint8_t *) duk_push_buffer_raw(ctx, len * 2, DUK_BUF_FLAG_NOZERO /*flags*/);
13385 	DUK_ASSERT(buf != NULL);
13386 
13387 #if defined(DUK_USE_HEX_FASTPATH)
13388 	DUK_ASSERT((((duk_size_t) buf) & 0x01U) == 0);   /* pointer is aligned, guaranteed for fixed buffer */
13389 	p16 = (duk_uint16_t *) (void *) buf;
13390 	len_safe = len & ~0x03U;
13391 	for (i = 0; i < len_safe; i += 4) {
13392 		p16[0] = duk_hex_enctab[inp[i]];
13393 		p16[1] = duk_hex_enctab[inp[i + 1]];
13394 		p16[2] = duk_hex_enctab[inp[i + 2]];
13395 		p16[3] = duk_hex_enctab[inp[i + 3]];
13396 		p16 += 4;
13397 	}
13398 	for (; i < len; i++) {
13399 		*p16++ = duk_hex_enctab[inp[i]];
13400 	}
13401 #else  /* DUK_USE_HEX_FASTPATH */
13402 	for (i = 0; i < len; i++) {
13403 		duk_small_uint_t t;
13404 		t = (duk_small_uint_t) inp[i];
13405 		buf[i*2 + 0] = duk_lc_digits[t >> 4];
13406 		buf[i*2 + 1] = duk_lc_digits[t & 0x0f];
13407 	}
13408 #endif  /* DUK_USE_HEX_FASTPATH */
13409 
13410 	/* XXX: Using a string return value forces a string intern which is
13411 	 * not always necessary.  As a rough performance measure, hex encode
13412 	 * time for tests/perf/test-hex-encode.js dropped from ~35s to ~15s
13413 	 * without string coercion.  Change to returning a buffer and let the
13414 	 * caller coerce to string if necessary?
13415 	 */
13416 
13417 	ret = duk_to_string(ctx, -1);
13418 	duk_replace(ctx, index);
13419 	return ret;
13420 }
13421 
duk_hex_decode(duk_context * ctx,duk_idx_t index)13422 DUK_EXTERNAL void duk_hex_decode(duk_context *ctx, duk_idx_t index) {
13423 	duk_hthread *thr = (duk_hthread *) ctx;
13424 	const duk_uint8_t *inp;
13425 	duk_size_t len;
13426 	duk_size_t i;
13427 	duk_int_t t;
13428 	duk_uint8_t *buf;
13429 #if defined(DUK_USE_HEX_FASTPATH)
13430 	duk_int_t chk;
13431 	duk_uint8_t *p;
13432 	duk_size_t len_safe;
13433 #endif
13434 
13435 	DUK_ASSERT_CTX_VALID(ctx);
13436 
13437 	index = duk_require_normalize_index(ctx, index);
13438 	inp = duk__prep_codec_arg(ctx, index, &len);
13439 	DUK_ASSERT(inp != NULL || len == 0);
13440 
13441 	if (len & 0x01) {
13442 		goto type_error;
13443 	}
13444 
13445 	/* Fixed buffer, no zeroing because we'll fill all the data. */
13446 	buf = (duk_uint8_t *) duk_push_buffer_raw(ctx, len / 2, DUK_BUF_FLAG_NOZERO /*flags*/);
13447 	DUK_ASSERT(buf != NULL);
13448 
13449 #if defined(DUK_USE_HEX_FASTPATH)
13450 	p = buf;
13451 	len_safe = len & ~0x07U;
13452 	for (i = 0; i < len_safe; i += 8) {
13453 		t = ((duk_int_t) duk_hex_dectab_shift4[inp[i]]) |
13454 		    ((duk_int_t) duk_hex_dectab[inp[i + 1]]);
13455 		chk = t;
13456 		p[0] = (duk_uint8_t) t;
13457 		t = ((duk_int_t) duk_hex_dectab_shift4[inp[i + 2]]) |
13458 		    ((duk_int_t) duk_hex_dectab[inp[i + 3]]);
13459 		chk |= t;
13460 		p[1] = (duk_uint8_t) t;
13461 		t = ((duk_int_t) duk_hex_dectab_shift4[inp[i + 4]]) |
13462 		    ((duk_int_t) duk_hex_dectab[inp[i + 5]]);
13463 		chk |= t;
13464 		p[2] = (duk_uint8_t) t;
13465 		t = ((duk_int_t) duk_hex_dectab_shift4[inp[i + 6]]) |
13466 		    ((duk_int_t) duk_hex_dectab[inp[i + 7]]);
13467 		chk |= t;
13468 		p[3] = (duk_uint8_t) t;
13469 		p += 4;
13470 
13471 		/* Check if any lookup above had a negative result. */
13472 		if (DUK_UNLIKELY(chk < 0)) {
13473 			goto type_error;
13474 		}
13475 	}
13476 	for (; i < len; i += 2) {
13477 		t = (((duk_int_t) duk_hex_dectab[inp[i]]) << 4) |
13478 		    ((duk_int_t) duk_hex_dectab[inp[i + 1]]);
13479 		if (DUK_UNLIKELY(t < 0)) {
13480 			goto type_error;
13481 		}
13482 		*p++ = (duk_uint8_t) t;
13483 	}
13484 #else  /* DUK_USE_HEX_FASTPATH */
13485 	for (i = 0; i < len; i += 2) {
13486 		/* For invalid characters the value -1 gets extended to
13487 		 * at least 16 bits.  If either nybble is invalid, the
13488 		 * resulting 't' will be < 0.
13489 		 */
13490 		t = (((duk_int_t) duk_hex_dectab[inp[i]]) << 4) |
13491 		    ((duk_int_t) duk_hex_dectab[inp[i + 1]]);
13492 		if (DUK_UNLIKELY(t < 0)) {
13493 			goto type_error;
13494 		}
13495 		buf[i >> 1] = (duk_uint8_t) t;
13496 	}
13497 #endif  /* DUK_USE_HEX_FASTPATH */
13498 
13499 	duk_replace(ctx, index);
13500 	return;
13501 
13502  type_error:
13503 	DUK_ERROR_TYPE(thr, DUK_STR_DECODE_FAILED);
13504 }
13505 
duk_json_encode(duk_context * ctx,duk_idx_t index)13506 DUK_EXTERNAL const char *duk_json_encode(duk_context *ctx, duk_idx_t index) {
13507 #ifdef DUK_USE_ASSERTIONS
13508 	duk_idx_t top_at_entry;
13509 #endif
13510 	const char *ret;
13511 
13512 	DUK_ASSERT_CTX_VALID(ctx);
13513 #ifdef DUK_USE_ASSERTIONS
13514 	top_at_entry = duk_get_top(ctx);
13515 #endif
13516 
13517 	index = duk_require_normalize_index(ctx, index);
13518 	duk_bi_json_stringify_helper(ctx,
13519 	                             index /*idx_value*/,
13520 	                             DUK_INVALID_INDEX /*idx_replacer*/,
13521 	                             DUK_INVALID_INDEX /*idx_space*/,
13522 	                             0 /*flags*/);
13523 	DUK_ASSERT(duk_is_string(ctx, -1));
13524 	duk_replace(ctx, index);
13525 	ret = duk_get_string(ctx, index);
13526 
13527 	DUK_ASSERT(duk_get_top(ctx) == top_at_entry);
13528 
13529 	return ret;
13530 }
13531 
duk_json_decode(duk_context * ctx,duk_idx_t index)13532 DUK_EXTERNAL void duk_json_decode(duk_context *ctx, duk_idx_t index) {
13533 #ifdef DUK_USE_ASSERTIONS
13534 	duk_idx_t top_at_entry;
13535 #endif
13536 
13537 	DUK_ASSERT_CTX_VALID(ctx);
13538 #ifdef DUK_USE_ASSERTIONS
13539 	top_at_entry = duk_get_top(ctx);
13540 #endif
13541 
13542 	index = duk_require_normalize_index(ctx, index);
13543 	duk_bi_json_parse_helper(ctx,
13544 	                         index /*idx_value*/,
13545 	                         DUK_INVALID_INDEX /*idx_reviver*/,
13546 	                         0 /*flags*/);
13547 	duk_replace(ctx, index);
13548 
13549 	DUK_ASSERT(duk_get_top(ctx) == top_at_entry);
13550 }
13551 /*
13552  *  Compilation and evaluation
13553  */
13554 
13555 /* include removed: duk_internal.h */
13556 
13557 typedef struct duk__compile_raw_args duk__compile_raw_args;
13558 struct duk__compile_raw_args {
13559 	duk_size_t src_length;  /* should be first on 64-bit platforms */
13560 	const duk_uint8_t *src_buffer;
13561 	duk_uint_t flags;
13562 };
13563 
13564 /* Eval is just a wrapper now. */
duk_eval_raw(duk_context * ctx,const char * src_buffer,duk_size_t src_length,duk_uint_t flags)13565 DUK_EXTERNAL duk_int_t duk_eval_raw(duk_context *ctx, const char *src_buffer, duk_size_t src_length, duk_uint_t flags) {
13566 	duk_uint_t comp_flags;
13567 	duk_int_t rc;
13568 
13569 	DUK_ASSERT_CTX_VALID(ctx);
13570 
13571 	/* Note: strictness is *not* inherited from the current Duktape/C.
13572 	 * This would be confusing because the current strictness state
13573 	 * depends on whether we're running inside a Duktape/C activation
13574 	 * (= strict mode) or outside of any activation (= non-strict mode).
13575 	 * See tests/api/test-eval-strictness.c for more discussion.
13576 	 */
13577 
13578 	/* [ ... source? filename? ] (depends on flags) */
13579 
13580 	comp_flags = flags;
13581 	comp_flags |= DUK_COMPILE_EVAL;
13582 	rc = duk_compile_raw(ctx, src_buffer, src_length, comp_flags);  /* may be safe, or non-safe depending on flags */
13583 
13584 	/* [ ... closure/error ] */
13585 
13586 	if (rc != DUK_EXEC_SUCCESS) {
13587 		rc = DUK_EXEC_ERROR;
13588 		goto got_rc;
13589 	}
13590 
13591 	duk_push_global_object(ctx);  /* explicit 'this' binding, see GH-164 */
13592 
13593 	if (flags & DUK_COMPILE_SAFE) {
13594 		rc = duk_pcall_method(ctx, 0);
13595 	} else {
13596 		duk_call_method(ctx, 0);
13597 		rc = DUK_EXEC_SUCCESS;
13598 	}
13599 
13600 	/* [ ... result/error ] */
13601 
13602  got_rc:
13603 	if (flags & DUK_COMPILE_NORESULT) {
13604 		duk_pop(ctx);
13605 	}
13606 
13607 	return rc;
13608 }
13609 
13610 /* Helper which can be called both directly and with duk_safe_call(). */
duk__do_compile(duk_context * ctx)13611 DUK_LOCAL duk_ret_t duk__do_compile(duk_context *ctx) {
13612 	duk_hthread *thr = (duk_hthread *) ctx;
13613 	duk__compile_raw_args *comp_args;
13614 	duk_uint_t flags;
13615 	duk_small_uint_t comp_flags;
13616 	duk_hcompiledfunction *h_templ;
13617 
13618 	DUK_ASSERT_CTX_VALID(ctx);
13619 
13620 	/* Note: strictness is not inherited from the current Duktape/C
13621 	 * context.  Otherwise it would not be possible to compile
13622 	 * non-strict code inside a Duktape/C activation (which is
13623 	 * always strict now).  See tests/api/test-eval-strictness.c
13624 	 * for discussion.
13625 	 */
13626 
13627 	/* [ ... source? filename? &comp_args ] (depends on flags) */
13628 
13629 	comp_args = (duk__compile_raw_args *) duk_require_pointer(ctx, -1);
13630 	flags = comp_args->flags;
13631 	duk_pop(ctx);
13632 
13633 	/* [ ... source? filename? ] */
13634 
13635 	if (flags & DUK_COMPILE_NOFILENAME) {
13636 		/* Automatic filename: 'eval' or 'input'. */
13637 		duk_push_hstring_stridx(ctx, (flags & DUK_COMPILE_EVAL) ? DUK_STRIDX_EVAL : DUK_STRIDX_INPUT);
13638 	}
13639 
13640 	/* [ ... source? filename ] */
13641 
13642 	if (!comp_args->src_buffer) {
13643 		duk_hstring *h_sourcecode;
13644 
13645 		h_sourcecode = duk_get_hstring(ctx, -2);
13646 		if ((flags & DUK_COMPILE_NOSOURCE) ||  /* args incorrect */
13647 		    (h_sourcecode == NULL)) {          /* e.g. duk_push_string_file_raw() pushed undefined */
13648 			/* XXX: when this error is caused by a nonexistent
13649 			 * file given to duk_peval_file() or similar, the
13650 			 * error message is not the best possible.
13651 			 */
13652 			DUK_ERROR_API(thr, DUK_STR_NO_SOURCECODE);
13653 		}
13654 		DUK_ASSERT(h_sourcecode != NULL);
13655 		comp_args->src_buffer = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_sourcecode);
13656 		comp_args->src_length = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_sourcecode);
13657 	}
13658 	DUK_ASSERT(comp_args->src_buffer != NULL);
13659 
13660 	/* XXX: unnecessary translation of flags */
13661 	comp_flags = 0;
13662 	if (flags & DUK_COMPILE_EVAL) {
13663 		comp_flags |= DUK_JS_COMPILE_FLAG_EVAL;
13664 	}
13665 	if (flags & DUK_COMPILE_FUNCTION) {
13666 		comp_flags |= DUK_JS_COMPILE_FLAG_EVAL |
13667 		              DUK_JS_COMPILE_FLAG_FUNCEXPR;
13668 	}
13669 	if (flags & DUK_COMPILE_STRICT) {
13670 		comp_flags |= DUK_JS_COMPILE_FLAG_STRICT;
13671 	}
13672 
13673 	/* [ ... source? filename ] */
13674 
13675 	duk_js_compile(thr, comp_args->src_buffer, comp_args->src_length, comp_flags);
13676 
13677 	/* [ ... source? func_template ] */
13678 
13679 	if (flags & DUK_COMPILE_NOSOURCE) {
13680 		;
13681 	} else {
13682 		duk_remove(ctx, -2);
13683 	}
13684 
13685 	/* [ ... func_template ] */
13686 
13687 	h_templ = (duk_hcompiledfunction *) duk_get_hobject(ctx, -1);
13688 	DUK_ASSERT(h_templ != NULL);
13689 	duk_js_push_closure(thr,
13690 	                   h_templ,
13691 	                   thr->builtins[DUK_BIDX_GLOBAL_ENV],
13692 	                   thr->builtins[DUK_BIDX_GLOBAL_ENV],
13693 	                   1 /*add_auto_proto*/);
13694 	duk_remove(ctx, -2);   /* -> [ ... closure ] */
13695 
13696 	/* [ ... closure ] */
13697 
13698 	return 1;
13699 }
13700 
duk_compile_raw(duk_context * ctx,const char * src_buffer,duk_size_t src_length,duk_uint_t flags)13701 DUK_EXTERNAL duk_int_t duk_compile_raw(duk_context *ctx, const char *src_buffer, duk_size_t src_length, duk_uint_t flags) {
13702 	duk__compile_raw_args comp_args_alloc;
13703 	duk__compile_raw_args *comp_args = &comp_args_alloc;
13704 
13705 	DUK_ASSERT_CTX_VALID(ctx);
13706 
13707 	if ((flags & DUK_COMPILE_STRLEN) && (src_buffer != NULL)) {
13708 		/* String length is computed here to avoid multiple evaluation
13709 		 * of a macro argument in the calling side.
13710 		 */
13711 		src_length = DUK_STRLEN(src_buffer);
13712 	}
13713 
13714 	comp_args->src_buffer = (const duk_uint8_t *) src_buffer;
13715 	comp_args->src_length = src_length;
13716 	comp_args->flags = flags;
13717 	duk_push_pointer(ctx, (void *) comp_args);
13718 
13719 	/* [ ... source? filename? &comp_args ] (depends on flags) */
13720 
13721 	if (flags & DUK_COMPILE_SAFE) {
13722 		duk_int_t rc;
13723 		duk_int_t nargs;
13724 		duk_int_t nrets = 1;
13725 
13726 		/* Arguments can be: [ source? filename? &comp_args] so that
13727 		 * nargs is 1 to 3.  Call site encodes the correct nargs count
13728 		 * directly into flags.
13729 		 */
13730 		nargs = flags & 0x07;
13731 		DUK_ASSERT(nargs == (1 +
13732 		                     ((flags & DUK_COMPILE_NOSOURCE) ? 0 : 1) +
13733 		                     ((flags & DUK_COMPILE_NOFILENAME) ? 0 : 1)));
13734 		rc = duk_safe_call(ctx, duk__do_compile, nargs, nrets);
13735 
13736 		/* [ ... closure ] */
13737 		return rc;
13738 	}
13739 
13740 	(void) duk__do_compile(ctx);
13741 
13742 	/* [ ... closure ] */
13743 	return DUK_EXEC_SUCCESS;
13744 }
13745 /*
13746  *  Debugging related API calls
13747  */
13748 
13749 /* include removed: duk_internal.h */
13750 
duk_push_context_dump(duk_context * ctx)13751 DUK_EXTERNAL void duk_push_context_dump(duk_context *ctx) {
13752 	duk_idx_t idx;
13753 	duk_idx_t top;
13754 
13755 	DUK_ASSERT_CTX_VALID(ctx);
13756 
13757 	/* We don't duk_require_stack() here now, but rely on the caller having
13758 	 * enough space.
13759 	 */
13760 
13761 	top = duk_get_top(ctx);
13762 	duk_push_array(ctx);
13763 	for (idx = 0; idx < top; idx++) {
13764 		duk_dup(ctx, idx);
13765 		duk_put_prop_index(ctx, -2, idx);
13766 	}
13767 
13768 	/* XXX: conversion errors should not propagate outwards.
13769 	 * Perhaps values need to be coerced individually?
13770 	 */
13771 	duk_bi_json_stringify_helper(ctx,
13772 	                             duk_get_top_index(ctx),  /*idx_value*/
13773 	                             DUK_INVALID_INDEX,  /*idx_replacer*/
13774 	                             DUK_INVALID_INDEX,  /*idx_space*/
13775 	                             DUK_JSON_FLAG_EXT_CUSTOM |
13776 	                             DUK_JSON_FLAG_ASCII_ONLY |
13777 	                             DUK_JSON_FLAG_AVOID_KEY_QUOTES /*flags*/);
13778 
13779 	duk_push_sprintf(ctx, "ctx: top=%ld, stack=%s", (long) top, (const char *) duk_safe_to_string(ctx, -1));
13780 	duk_replace(ctx, -3);  /* [ ... arr jsonx(arr) res ] -> [ ... res jsonx(arr) ] */
13781 	duk_pop(ctx);
13782 	DUK_ASSERT(duk_is_string(ctx, -1));
13783 }
13784 
13785 #if defined(DUK_USE_DEBUGGER_SUPPORT)
13786 
duk_debugger_attach_custom(duk_context * ctx,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)13787 DUK_EXTERNAL void duk_debugger_attach_custom(duk_context *ctx,
13788                                              duk_debug_read_function read_cb,
13789                                              duk_debug_write_function write_cb,
13790                                              duk_debug_peek_function peek_cb,
13791                                              duk_debug_read_flush_function read_flush_cb,
13792                                              duk_debug_write_flush_function write_flush_cb,
13793                                              duk_debug_request_function request_cb,
13794                                              duk_debug_detached_function detached_cb,
13795                                              void *udata) {
13796 	duk_hthread *thr = (duk_hthread *) ctx;
13797 	duk_heap *heap;
13798 	const char *str;
13799 	duk_size_t len;
13800 
13801 	/* XXX: should there be an error or an automatic detach if
13802 	 * already attached?
13803 	 */
13804 
13805 	DUK_D(DUK_DPRINT("application called duk_debugger_attach()"));
13806 
13807 	DUK_ASSERT_CTX_VALID(ctx);
13808 	DUK_ASSERT(read_cb != NULL);
13809 	DUK_ASSERT(write_cb != NULL);
13810 	/* Other callbacks are optional. */
13811 
13812 	heap = thr->heap;
13813 	heap->dbg_read_cb = read_cb;
13814 	heap->dbg_write_cb = write_cb;
13815 	heap->dbg_peek_cb = peek_cb;
13816 	heap->dbg_read_flush_cb = read_flush_cb;
13817 	heap->dbg_write_flush_cb = write_flush_cb;
13818 	heap->dbg_request_cb = request_cb;
13819 	heap->dbg_detached_cb = detached_cb;
13820 	heap->dbg_udata = udata;
13821 	heap->dbg_have_next_byte = 0;
13822 
13823 	/* Start in paused state. */
13824 	heap->dbg_processing = 0;
13825 	heap->dbg_paused = 1;
13826 	heap->dbg_state_dirty = 1;
13827 	heap->dbg_force_restart = 0;
13828 	heap->dbg_step_type = 0;
13829 	heap->dbg_step_thread = NULL;
13830 	heap->dbg_step_csindex = 0;
13831 	heap->dbg_step_startline = 0;
13832 	heap->dbg_exec_counter = 0;
13833 	heap->dbg_last_counter = 0;
13834 	heap->dbg_last_time = 0.0;
13835 
13836 	/* Send version identification and flush right afterwards.  Note that
13837 	 * we must write raw, unframed bytes here.
13838 	 */
13839 	duk_push_sprintf(ctx, "%ld %ld %s %s\n",
13840 	                 (long) DUK_DEBUG_PROTOCOL_VERSION,
13841 	                 (long) DUK_VERSION,
13842 	                 (const char *) DUK_GIT_DESCRIBE,
13843 	                 (const char *) DUK_USE_TARGET_INFO);
13844 	str = duk_get_lstring(ctx, -1, &len);
13845 	DUK_ASSERT(str != NULL);
13846 	duk_debug_write_bytes(thr, (const duk_uint8_t *) str, len);
13847 	duk_debug_write_flush(thr);
13848 	duk_pop(ctx);
13849 }
13850 
duk_debugger_detach(duk_context * ctx)13851 DUK_EXTERNAL void duk_debugger_detach(duk_context *ctx) {
13852 	duk_hthread *thr;
13853 
13854 	DUK_D(DUK_DPRINT("application called duk_debugger_detach()"));
13855 
13856 	DUK_ASSERT_CTX_VALID(ctx);
13857 	thr = (duk_hthread *) ctx;
13858 	DUK_ASSERT(thr != NULL);
13859 	DUK_ASSERT(thr->heap != NULL);
13860 
13861 	/* Can be called multiple times with no harm. */
13862 	duk_debug_do_detach(thr->heap);
13863 }
13864 
duk_debugger_cooperate(duk_context * ctx)13865 DUK_EXTERNAL void duk_debugger_cooperate(duk_context *ctx) {
13866 	duk_hthread *thr;
13867 	duk_bool_t processed_messages;
13868 
13869 	DUK_ASSERT_CTX_VALID(ctx);
13870 	thr = (duk_hthread *) ctx;
13871 	DUK_ASSERT(thr != NULL);
13872 	DUK_ASSERT(thr->heap != NULL);
13873 
13874 	if (!DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap)) {
13875 		return;
13876 	}
13877 	if (thr->callstack_top > 0 || thr->heap->dbg_processing) {
13878 		/* Calling duk_debugger_cooperate() while Duktape is being
13879 		 * called into is not supported.  This is not a 100% check
13880 		 * but prevents any damage in most cases.
13881 		 */
13882 		return;
13883 	}
13884 
13885 	processed_messages = duk_debug_process_messages(thr, 1 /*no_block*/);
13886 	DUK_UNREF(processed_messages);
13887 }
13888 
duk_debugger_notify(duk_context * ctx,duk_idx_t nvalues)13889 DUK_EXTERNAL duk_bool_t duk_debugger_notify(duk_context *ctx, duk_idx_t nvalues) {
13890 	duk_hthread *thr;
13891 	duk_idx_t top;
13892 	duk_idx_t idx;
13893 	duk_bool_t ret = 0;
13894 
13895 	DUK_ASSERT_CTX_VALID(ctx);
13896 	thr = (duk_hthread *) ctx;
13897 	DUK_ASSERT(thr != NULL);
13898 	DUK_ASSERT(thr->heap != NULL);
13899 
13900 	DUK_D(DUK_DPRINT("application called duk_debugger_notify() with nvalues=%ld", (long) nvalues));
13901 
13902 	top = duk_get_top(ctx);
13903 	if (top < nvalues) {
13904 		DUK_ERROR_API(thr, "not enough stack values for notify");
13905 		return ret;  /* unreachable */
13906 	}
13907 	if (DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap)) {
13908 		duk_debug_write_notify(thr, DUK_DBG_CMD_APPNOTIFY);
13909 		for (idx = top - nvalues; idx < top; idx++) {
13910 			duk_tval *tv = DUK_GET_TVAL_POSIDX(ctx, idx);
13911 			duk_debug_write_tval(thr, tv);
13912 		}
13913 		duk_debug_write_eom(thr);
13914 
13915 		/* Return non-zero (true) if we have a good reason to believe
13916 		 * the notify was delivered; if we're still attached at least
13917 		 * a transport error was not indicated by the transport write
13918 		 * callback.  This is not a 100% guarantee of course.
13919 		 */
13920 		if (DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap)) {
13921 			ret = 1;
13922 		}
13923 	}
13924 	duk_pop_n(ctx, nvalues);
13925 	return ret;
13926 }
13927 
duk_debugger_pause(duk_context * ctx)13928 DUK_EXTERNAL void duk_debugger_pause(duk_context *ctx) {
13929 	duk_hthread *thr;
13930 
13931 	DUK_ASSERT_CTX_VALID(ctx);
13932 	thr = (duk_hthread *) ctx;
13933 	DUK_ASSERT(thr != NULL);
13934 	DUK_ASSERT(thr->heap != NULL);
13935 
13936 	DUK_D(DUK_DPRINT("application called duk_debugger_pause()"));
13937 
13938 	/* Treat like a debugger statement: ignore when not attached. */
13939 	if (DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap)) {
13940 		DUK_HEAP_SET_PAUSED(thr->heap);
13941 
13942 		/* Pause on the next opcode executed.  This is always safe to do even
13943 		 * inside the debugger message loop: the interrupt counter will be reset
13944 		 * to its proper value when the message loop exits.
13945 		 */
13946 		thr->interrupt_init = 1;
13947 		thr->interrupt_counter = 0;
13948 	}
13949 }
13950 
13951 #else  /* DUK_USE_DEBUGGER_SUPPORT */
13952 
duk_debugger_attach_custom(duk_context * ctx,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)13953 DUK_EXTERNAL void duk_debugger_attach_custom(duk_context *ctx,
13954                                              duk_debug_read_function read_cb,
13955                                              duk_debug_write_function write_cb,
13956                                              duk_debug_peek_function peek_cb,
13957                                              duk_debug_read_flush_function read_flush_cb,
13958                                              duk_debug_write_flush_function write_flush_cb,
13959                                              duk_debug_request_function request_cb,
13960                                              duk_debug_detached_function detached_cb,
13961                                              void *udata) {
13962 	DUK_ASSERT_CTX_VALID(ctx);
13963 	DUK_UNREF(read_cb);
13964 	DUK_UNREF(write_cb);
13965 	DUK_UNREF(peek_cb);
13966 	DUK_UNREF(read_flush_cb);
13967 	DUK_UNREF(write_flush_cb);
13968 	DUK_UNREF(request_cb);
13969 	DUK_UNREF(detached_cb);
13970 	DUK_UNREF(udata);
13971 	DUK_ERROR_API((duk_hthread *) ctx, "no debugger support");
13972 }
13973 
duk_debugger_detach(duk_context * ctx)13974 DUK_EXTERNAL void duk_debugger_detach(duk_context *ctx) {
13975 	DUK_ASSERT_CTX_VALID(ctx);
13976 	DUK_ERROR_API((duk_hthread *) ctx, "no debugger support");
13977 }
13978 
duk_debugger_cooperate(duk_context * ctx)13979 DUK_EXTERNAL void duk_debugger_cooperate(duk_context *ctx) {
13980 	/* nop */
13981 	DUK_ASSERT_CTX_VALID(ctx);
13982 	DUK_UNREF(ctx);
13983 }
13984 
duk_debugger_notify(duk_context * ctx,duk_idx_t nvalues)13985 DUK_EXTERNAL duk_bool_t duk_debugger_notify(duk_context *ctx, duk_idx_t nvalues) {
13986 	duk_idx_t top;
13987 
13988 	DUK_ASSERT_CTX_VALID(ctx);
13989 
13990 	top = duk_get_top(ctx);
13991 	if (top < nvalues) {
13992 		DUK_ERROR_API((duk_hthread *) ctx, "not enough stack values for notify");
13993 		return 0;  /* unreachable */
13994 	}
13995 
13996 	/* No debugger support, just pop values. */
13997 	duk_pop_n(ctx, nvalues);
13998 	return 0;
13999 }
14000 
duk_debugger_pause(duk_context * ctx)14001 DUK_EXTERNAL void duk_debugger_pause(duk_context *ctx) {
14002 	/* Treat like debugger statement: nop */
14003 	DUK_ASSERT_CTX_VALID(ctx);
14004 	DUK_UNREF(ctx);
14005 }
14006 
14007 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
14008 /*
14009  *  Heap creation and destruction
14010  */
14011 
14012 /* include removed: duk_internal.h */
14013 
14014 typedef struct duk_internal_thread_state duk_internal_thread_state;
14015 
14016 struct duk_internal_thread_state {
14017 	duk_ljstate lj;
14018 	duk_bool_t handling_error;
14019 	duk_hthread *curr_thread;
14020 	duk_int_t call_recursion_depth;
14021 };
14022 
14023 DUK_EXTERNAL
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)14024 duk_context *duk_create_heap(duk_alloc_function alloc_func,
14025                              duk_realloc_function realloc_func,
14026                              duk_free_function free_func,
14027                              void *heap_udata,
14028                              duk_fatal_function fatal_handler) {
14029 	duk_heap *heap = NULL;
14030 	duk_context *ctx;
14031 
14032 	/* Assume that either all memory funcs are NULL or non-NULL, mixed
14033 	 * cases will now be unsafe.
14034 	 */
14035 
14036 	/* XXX: just assert non-NULL values here and make caller arguments
14037 	 * do the defaulting to the default implementations (smaller code)?
14038 	 */
14039 
14040 	if (!alloc_func) {
14041 		DUK_ASSERT(realloc_func == NULL);
14042 		DUK_ASSERT(free_func == NULL);
14043 #if defined(DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS)
14044 		alloc_func = duk_default_alloc_function;
14045 		realloc_func = duk_default_realloc_function;
14046 		free_func = duk_default_free_function;
14047 #else
14048 		DUK_D(DUK_DPRINT("no allocation functions given and no default providers"));
14049 		return NULL;
14050 #endif
14051 	} else {
14052 		DUK_ASSERT(realloc_func != NULL);
14053 		DUK_ASSERT(free_func != NULL);
14054 	}
14055 
14056 	if (!fatal_handler) {
14057 		fatal_handler = duk_default_fatal_handler;
14058 	}
14059 
14060 	DUK_ASSERT(alloc_func != NULL);
14061 	DUK_ASSERT(realloc_func != NULL);
14062 	DUK_ASSERT(free_func != NULL);
14063 	DUK_ASSERT(fatal_handler != NULL);
14064 
14065 	heap = duk_heap_alloc(alloc_func, realloc_func, free_func, heap_udata, fatal_handler);
14066 	if (!heap) {
14067 		return NULL;
14068 	}
14069 	ctx = (duk_context *) heap->heap_thread;
14070 	DUK_ASSERT(ctx != NULL);
14071 	DUK_ASSERT(((duk_hthread *) ctx)->heap != NULL);
14072 	return ctx;
14073 }
14074 
duk_destroy_heap(duk_context * ctx)14075 DUK_EXTERNAL void duk_destroy_heap(duk_context *ctx) {
14076 	duk_hthread *thr = (duk_hthread *) ctx;
14077 	duk_heap *heap;
14078 
14079 	if (!ctx) {
14080 		return;
14081 	}
14082 	heap = thr->heap;
14083 	DUK_ASSERT(heap != NULL);
14084 
14085 	duk_heap_free(heap);
14086 }
14087 
duk_suspend(duk_context * ctx,duk_thread_state * state)14088 DUK_EXTERNAL void duk_suspend(duk_context *ctx, duk_thread_state *state) {
14089 	duk_hthread *thr = (duk_hthread *) ctx;
14090 	duk_internal_thread_state *snapshot = (duk_internal_thread_state *) (void *) state;
14091 	duk_heap *heap;
14092 	duk_ljstate *lj;
14093 
14094 	DUK_ASSERT_CTX_VALID(ctx);
14095 	DUK_ASSERT(thr != NULL);
14096 	DUK_ASSERT(thr->heap != NULL);
14097 	DUK_ASSERT(state != NULL);  /* unvalidated */
14098 
14099 	heap = thr->heap;
14100 	lj = &heap->lj;
14101 
14102 	duk_push_tval(ctx, &lj->value1);
14103 	duk_push_tval(ctx, &lj->value2);
14104 
14105 	DUK_MEMCPY((void *) &snapshot->lj, (const void *) lj, sizeof(duk_ljstate));
14106 	snapshot->handling_error = heap->handling_error;
14107 	snapshot->curr_thread = heap->curr_thread;
14108 	snapshot->call_recursion_depth = heap->call_recursion_depth;
14109 
14110 	lj->jmpbuf_ptr = NULL;
14111 	lj->type = DUK_LJ_TYPE_UNKNOWN;
14112 	DUK_TVAL_SET_UNDEFINED(&lj->value1);
14113 	DUK_TVAL_SET_UNDEFINED(&lj->value2);
14114 	heap->handling_error = 0;
14115 	heap->curr_thread = NULL;
14116 	heap->call_recursion_depth = 0;
14117 }
14118 
duk_resume(duk_context * ctx,const duk_thread_state * state)14119 DUK_EXTERNAL void duk_resume(duk_context *ctx, const duk_thread_state *state) {
14120 	duk_hthread *thr = (duk_hthread *) ctx;
14121 	const duk_internal_thread_state *snapshot = (const duk_internal_thread_state *) (const void *) state;
14122 	duk_heap *heap;
14123 
14124 	DUK_ASSERT_CTX_VALID(ctx);
14125 	DUK_ASSERT(thr != NULL);
14126 	DUK_ASSERT(thr->heap != NULL);
14127 	DUK_ASSERT(state != NULL);  /* unvalidated */
14128 
14129 	heap = thr->heap;
14130 
14131 	DUK_MEMCPY((void *) &heap->lj, (const void *) &snapshot->lj, sizeof(duk_ljstate));
14132 	heap->handling_error = snapshot->handling_error;
14133 	heap->curr_thread = snapshot->curr_thread;
14134 	heap->call_recursion_depth = snapshot->call_recursion_depth;
14135 
14136 	duk_pop_2(ctx);
14137 }
14138 
14139 /* XXX: better place for this */
duk_set_global_object(duk_context * ctx)14140 DUK_EXTERNAL void duk_set_global_object(duk_context *ctx) {
14141 	duk_hthread *thr = (duk_hthread *) ctx;
14142 	duk_hobject *h_glob;
14143 	duk_hobject *h_prev_glob;
14144 	duk_hobject *h_env;
14145 	duk_hobject *h_prev_env;
14146 
14147 	DUK_D(DUK_DPRINT("replace global object with: %!T", duk_get_tval(ctx, -1)));
14148 
14149 	h_glob = duk_require_hobject(ctx, -1);
14150 	DUK_ASSERT(h_glob != NULL);
14151 
14152 	/*
14153 	 *  Replace global object.
14154 	 */
14155 
14156 	h_prev_glob = thr->builtins[DUK_BIDX_GLOBAL];
14157 	DUK_UNREF(h_prev_glob);
14158 	thr->builtins[DUK_BIDX_GLOBAL] = h_glob;
14159 	DUK_HOBJECT_INCREF(thr, h_glob);
14160 	DUK_HOBJECT_DECREF_ALLOWNULL(thr, h_prev_glob);  /* side effects, in theory (referenced by global env) */
14161 
14162 	/*
14163 	 *  Replace lexical environment for global scope
14164 	 *
14165 	 *  Create a new object environment for the global lexical scope.
14166 	 *  We can't just reset the _Target property of the current one,
14167 	 *  because the lexical scope is shared by other threads with the
14168 	 *  same (initial) built-ins.
14169 	 */
14170 
14171 	(void) duk_push_object_helper(ctx,
14172 	                              DUK_HOBJECT_FLAG_EXTENSIBLE |
14173 	                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJENV),
14174 	                              -1);  /* no prototype, updated below */
14175 
14176 	duk_dup(ctx, -2);
14177 	duk_dup(ctx, -3);
14178 
14179 	/* [ ... new_glob new_env new_glob new_glob ] */
14180 
14181 	duk_xdef_prop_stridx(thr, -3, DUK_STRIDX_INT_TARGET, DUK_PROPDESC_FLAGS_NONE);
14182 	duk_xdef_prop_stridx(thr, -2, DUK_STRIDX_INT_THIS, DUK_PROPDESC_FLAGS_NONE);
14183 
14184 	/* [ ... new_glob new_env ] */
14185 
14186 	h_env = duk_get_hobject(ctx, -1);
14187 	DUK_ASSERT(h_env != NULL);
14188 
14189 	h_prev_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
14190 	thr->builtins[DUK_BIDX_GLOBAL_ENV] = h_env;
14191 	DUK_HOBJECT_INCREF(thr, h_env);
14192 	DUK_HOBJECT_DECREF_ALLOWNULL(thr, h_prev_env);  /* side effects */
14193 	DUK_UNREF(h_env);  /* without refcounts */
14194 	DUK_UNREF(h_prev_env);
14195 
14196 	/* [ ... new_glob new_env ] */
14197 
14198 	duk_pop_2(ctx);
14199 
14200 	/* [ ... ] */
14201 }
14202 /*
14203  *  Logging
14204  *
14205  *  Current logging primitive is a sprintf-style log which is convenient
14206  *  for most C code.  Another useful primitive would be to log N arguments
14207  *  from value stack (like the Ecmascript binding does).
14208  */
14209 
14210 /* include removed: duk_internal.h */
14211 
duk_log_va(duk_context * ctx,duk_int_t level,const char * fmt,va_list ap)14212 DUK_EXTERNAL void duk_log_va(duk_context *ctx, duk_int_t level, const char *fmt, va_list ap) {
14213 	/* stridx_logfunc[] must be static to allow initializer with old compilers like BCC */
14214 	static const duk_uint16_t stridx_logfunc[6] = {
14215 		DUK_STRIDX_LC_TRACE, DUK_STRIDX_LC_DEBUG, DUK_STRIDX_LC_INFO,
14216 		DUK_STRIDX_LC_WARN, DUK_STRIDX_LC_ERROR, DUK_STRIDX_LC_FATAL
14217 	};
14218 
14219 	DUK_ASSERT_CTX_VALID(ctx);
14220 
14221 	if (level < 0) {
14222 		level = 0;
14223 	} else if (level > (int) (sizeof(stridx_logfunc) / sizeof(duk_uint16_t)) - 1) {
14224 		level = (int) (sizeof(stridx_logfunc) / sizeof(duk_uint16_t)) - 1;
14225 	}
14226 
14227 	duk_push_hobject_bidx(ctx, DUK_BIDX_LOGGER_CONSTRUCTOR);
14228 	duk_get_prop_stridx(ctx, -1, DUK_STRIDX_CLOG);
14229 	duk_get_prop_stridx(ctx, -1, stridx_logfunc[level]);
14230 	duk_dup(ctx, -2);
14231 
14232 	/* [ ... Logger clog logfunc clog ] */
14233 
14234 	duk_push_vsprintf(ctx, fmt, ap);
14235 
14236 	/* [ ... Logger clog logfunc clog(=this) msg ] */
14237 
14238 	duk_call_method(ctx, 1 /*nargs*/);
14239 
14240 	/* [ ... Logger clog res ] */
14241 
14242 	duk_pop_3(ctx);
14243 }
14244 
duk_log(duk_context * ctx,duk_int_t level,const char * fmt,...)14245 DUK_EXTERNAL void duk_log(duk_context *ctx, duk_int_t level, const char *fmt, ...) {
14246 	va_list ap;
14247 
14248 	DUK_ASSERT_CTX_VALID(ctx);
14249 
14250 	va_start(ap, fmt);
14251 	duk_log_va(ctx, level, fmt, ap);
14252 	va_end(ap);
14253 }
14254 /*
14255  *  Memory calls.
14256  */
14257 
14258 /* include removed: duk_internal.h */
14259 
duk_alloc_raw(duk_context * ctx,duk_size_t size)14260 DUK_EXTERNAL void *duk_alloc_raw(duk_context *ctx, duk_size_t size) {
14261 	duk_hthread *thr = (duk_hthread *) ctx;
14262 
14263 	DUK_ASSERT_CTX_VALID(ctx);
14264 
14265 	return DUK_ALLOC_RAW(thr->heap, size);
14266 }
14267 
duk_free_raw(duk_context * ctx,void * ptr)14268 DUK_EXTERNAL void duk_free_raw(duk_context *ctx, void *ptr) {
14269 	duk_hthread *thr = (duk_hthread *) ctx;
14270 
14271 	DUK_ASSERT_CTX_VALID(ctx);
14272 
14273 	DUK_FREE_RAW(thr->heap, ptr);
14274 }
14275 
duk_realloc_raw(duk_context * ctx,void * ptr,duk_size_t size)14276 DUK_EXTERNAL void *duk_realloc_raw(duk_context *ctx, void *ptr, duk_size_t size) {
14277 	duk_hthread *thr = (duk_hthread *) ctx;
14278 
14279 	DUK_ASSERT_CTX_VALID(ctx);
14280 
14281 	return DUK_REALLOC_RAW(thr->heap, ptr, size);
14282 }
14283 
duk_alloc(duk_context * ctx,duk_size_t size)14284 DUK_EXTERNAL void *duk_alloc(duk_context *ctx, duk_size_t size) {
14285 	duk_hthread *thr = (duk_hthread *) ctx;
14286 
14287 	DUK_ASSERT_CTX_VALID(ctx);
14288 
14289 	return DUK_ALLOC(thr->heap, size);
14290 }
14291 
duk_free(duk_context * ctx,void * ptr)14292 DUK_EXTERNAL void duk_free(duk_context *ctx, void *ptr) {
14293 	duk_hthread *thr = (duk_hthread *) ctx;
14294 
14295 	DUK_ASSERT_CTX_VALID(ctx);
14296 
14297 	DUK_FREE(thr->heap, ptr);
14298 }
14299 
duk_realloc(duk_context * ctx,void * ptr,duk_size_t size)14300 DUK_EXTERNAL void *duk_realloc(duk_context *ctx, void *ptr, duk_size_t size) {
14301 	duk_hthread *thr = (duk_hthread *) ctx;
14302 
14303 	DUK_ASSERT_CTX_VALID(ctx);
14304 
14305 	/*
14306 	 *  Note: since this is an exposed API call, there should be
14307 	 *  no way a mark-and-sweep could have a side effect on the
14308 	 *  memory allocation behind 'ptr'; the pointer should never
14309 	 *  be something that Duktape wants to change.
14310 	 *
14311 	 *  Thus, no need to use DUK_REALLOC_INDIRECT (and we don't
14312 	 *  have the storage location here anyway).
14313 	 */
14314 
14315 	return DUK_REALLOC(thr->heap, ptr, size);
14316 }
14317 
duk_get_memory_functions(duk_context * ctx,duk_memory_functions * out_funcs)14318 DUK_EXTERNAL void duk_get_memory_functions(duk_context *ctx, duk_memory_functions *out_funcs) {
14319 	duk_hthread *thr = (duk_hthread *) ctx;
14320 	duk_heap *heap;
14321 
14322 	DUK_ASSERT_CTX_VALID(ctx);
14323 	DUK_ASSERT(out_funcs != NULL);
14324 	DUK_ASSERT(thr != NULL);
14325 	DUK_ASSERT(thr->heap != NULL);
14326 
14327 	heap = thr->heap;
14328 	out_funcs->alloc_func = heap->alloc_func;
14329 	out_funcs->realloc_func = heap->realloc_func;
14330 	out_funcs->free_func = heap->free_func;
14331 	out_funcs->udata = heap->heap_udata;
14332 }
14333 
duk_gc(duk_context * ctx,duk_uint_t flags)14334 DUK_EXTERNAL void duk_gc(duk_context *ctx, duk_uint_t flags) {
14335 #ifdef DUK_USE_MARK_AND_SWEEP
14336 	duk_hthread *thr = (duk_hthread *) ctx;
14337 	duk_heap *heap;
14338 
14339 	DUK_UNREF(flags);
14340 
14341 	/* NULL accepted */
14342 	if (!ctx) {
14343 		return;
14344 	}
14345 	DUK_ASSERT_CTX_VALID(ctx);
14346 	heap = thr->heap;
14347 	DUK_ASSERT(heap != NULL);
14348 
14349 	DUK_D(DUK_DPRINT("mark-and-sweep requested by application"));
14350 	duk_heap_mark_and_sweep(heap, 0);
14351 #else
14352 	DUK_D(DUK_DPRINT("mark-and-sweep requested by application but mark-and-sweep not enabled, ignoring"));
14353 	DUK_UNREF(ctx);
14354 	DUK_UNREF(flags);
14355 #endif
14356 }
14357 /*
14358  *  Object handling: property access and other support functions.
14359  */
14360 
14361 /* include removed: duk_internal.h */
14362 
14363 /*
14364  *  Property handling
14365  *
14366  *  The API exposes only the most common property handling functions.
14367  *  The caller can invoke Ecmascript built-ins for full control (e.g.
14368  *  defineProperty, getOwnPropertyDescriptor).
14369  */
14370 
duk_get_prop(duk_context * ctx,duk_idx_t obj_index)14371 DUK_EXTERNAL duk_bool_t duk_get_prop(duk_context *ctx, duk_idx_t obj_index) {
14372 	duk_hthread *thr = (duk_hthread *) ctx;
14373 	duk_tval *tv_obj;
14374 	duk_tval *tv_key;
14375 	duk_bool_t rc;
14376 
14377 	DUK_ASSERT_CTX_VALID(ctx);
14378 
14379 	/* Note: copying tv_obj and tv_key to locals to shield against a valstack
14380 	 * resize is not necessary for a property get right now.
14381 	 */
14382 
14383 	tv_obj = duk_require_tval(ctx, obj_index);
14384 	tv_key = duk_require_tval(ctx, -1);
14385 
14386 	rc = duk_hobject_getprop(thr, tv_obj, tv_key);
14387 	DUK_ASSERT(rc == 0 || rc == 1);
14388 	/* a value is left on stack regardless of rc */
14389 
14390 	duk_remove(ctx, -2);  /* remove key */
14391 	return rc;  /* 1 if property found, 0 otherwise */
14392 }
14393 
duk_get_prop_string(duk_context * ctx,duk_idx_t obj_index,const char * key)14394 DUK_EXTERNAL duk_bool_t duk_get_prop_string(duk_context *ctx, duk_idx_t obj_index, const char *key) {
14395 	DUK_ASSERT_CTX_VALID(ctx);
14396 	DUK_ASSERT(key != NULL);
14397 
14398 	obj_index = duk_require_normalize_index(ctx, obj_index);
14399 	duk_push_string(ctx, key);
14400 	return duk_get_prop(ctx, obj_index);
14401 }
14402 
duk_get_prop_index(duk_context * ctx,duk_idx_t obj_index,duk_uarridx_t arr_index)14403 DUK_EXTERNAL duk_bool_t duk_get_prop_index(duk_context *ctx, duk_idx_t obj_index, duk_uarridx_t arr_index) {
14404 	DUK_ASSERT_CTX_VALID(ctx);
14405 
14406 	obj_index = duk_require_normalize_index(ctx, obj_index);
14407 	duk_push_uarridx(ctx, arr_index);
14408 	return duk_get_prop(ctx, obj_index);
14409 }
14410 
duk_get_prop_stridx(duk_context * ctx,duk_idx_t obj_index,duk_small_int_t stridx)14411 DUK_INTERNAL duk_bool_t duk_get_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx) {
14412 	duk_hthread *thr = (duk_hthread *) ctx;
14413 
14414 	DUK_ASSERT_CTX_VALID(ctx);
14415 	DUK_ASSERT_DISABLE(stridx >= 0);
14416 	DUK_ASSERT(stridx < DUK_HEAP_NUM_STRINGS);
14417 	DUK_UNREF(thr);
14418 
14419 	obj_index = duk_require_normalize_index(ctx, obj_index);
14420 	duk_push_hstring(ctx, DUK_HTHREAD_GET_STRING(thr, stridx));
14421 	return duk_get_prop(ctx, obj_index);
14422 }
14423 
duk_get_prop_stridx_boolean(duk_context * ctx,duk_idx_t obj_index,duk_small_int_t stridx,duk_bool_t * out_has_prop)14424 DUK_INTERNAL duk_bool_t duk_get_prop_stridx_boolean(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx, duk_bool_t *out_has_prop) {
14425 	duk_bool_t rc;
14426 
14427 	DUK_ASSERT_CTX_VALID(ctx);
14428 	DUK_ASSERT_DISABLE(stridx >= 0);
14429 	DUK_ASSERT(stridx < DUK_HEAP_NUM_STRINGS);
14430 
14431 	rc = duk_get_prop_stridx(ctx, obj_index, stridx);
14432 	if (out_has_prop) {
14433 		*out_has_prop = rc;
14434 	}
14435 	rc = duk_to_boolean(ctx, -1);
14436 	DUK_ASSERT(rc == 0 || rc == 1);
14437 	duk_pop(ctx);
14438 	return rc;
14439 }
14440 
duk__put_prop_shared(duk_context * ctx,duk_idx_t obj_idx,duk_idx_t idx_key)14441 DUK_LOCAL duk_bool_t duk__put_prop_shared(duk_context *ctx, duk_idx_t obj_idx, duk_idx_t idx_key) {
14442 	duk_hthread *thr = (duk_hthread *) ctx;
14443 	duk_tval *tv_obj;
14444 	duk_tval *tv_key;
14445 	duk_tval *tv_val;
14446 	duk_small_int_t throw_flag;
14447 	duk_bool_t rc;
14448 
14449 	/* Note: copying tv_obj and tv_key to locals to shield against a valstack
14450 	 * resize is not necessary for a property put right now (putprop protects
14451 	 * against it internally).
14452 	 */
14453 
14454 	/* Key and value indices are either (-2, -1) or (-1, -2).  Given idx_key,
14455 	 * idx_val is always (idx_key ^ 0x01).
14456 	 */
14457 	DUK_ASSERT((idx_key == -2 && (idx_key ^ 1) == -1) ||
14458 	           (idx_key == -1 && (idx_key ^ 1) == -2));
14459 	tv_obj = duk_require_tval(ctx, obj_idx);
14460 	tv_key = duk_require_tval(ctx, idx_key);
14461 	tv_val = duk_require_tval(ctx, idx_key ^ 1);
14462 	throw_flag = duk_is_strict_call(ctx);
14463 
14464 	rc = duk_hobject_putprop(thr, tv_obj, tv_key, tv_val, throw_flag);
14465 	DUK_ASSERT(rc == 0 || rc == 1);
14466 
14467 	duk_pop_2(ctx);  /* remove key and value */
14468 	return rc;  /* 1 if property found, 0 otherwise */
14469 }
14470 
duk_put_prop(duk_context * ctx,duk_idx_t obj_idx)14471 DUK_EXTERNAL duk_bool_t duk_put_prop(duk_context *ctx, duk_idx_t obj_idx) {
14472 	DUK_ASSERT_CTX_VALID(ctx);
14473 	return duk__put_prop_shared(ctx, obj_idx, -2);
14474 }
14475 
duk_put_prop_string(duk_context * ctx,duk_idx_t obj_idx,const char * key)14476 DUK_EXTERNAL duk_bool_t duk_put_prop_string(duk_context *ctx, duk_idx_t obj_idx, const char *key) {
14477 	DUK_ASSERT_CTX_VALID(ctx);
14478 	DUK_ASSERT(key != NULL);
14479 
14480 	/* Careful here and with other duk_put_prop_xxx() helpers: the
14481 	 * target object and the property value may be in the same value
14482 	 * stack slot (unusual, but still conceptually clear).
14483 	 */
14484 	obj_idx = duk_normalize_index(ctx, obj_idx);
14485 	(void) duk_push_string(ctx, key);
14486 	return duk__put_prop_shared(ctx, obj_idx, -1);
14487 }
14488 
duk_put_prop_index(duk_context * ctx,duk_idx_t obj_idx,duk_uarridx_t arr_idx)14489 DUK_EXTERNAL duk_bool_t duk_put_prop_index(duk_context *ctx, duk_idx_t obj_idx, duk_uarridx_t arr_idx) {
14490 	DUK_ASSERT_CTX_VALID(ctx);
14491 
14492 	obj_idx = duk_require_normalize_index(ctx, obj_idx);
14493 	duk_push_uarridx(ctx, arr_idx);
14494 	return duk__put_prop_shared(ctx, obj_idx, -1);
14495 }
14496 
duk_put_prop_stridx(duk_context * ctx,duk_idx_t obj_idx,duk_small_int_t stridx)14497 DUK_INTERNAL duk_bool_t duk_put_prop_stridx(duk_context *ctx, duk_idx_t obj_idx, duk_small_int_t stridx) {
14498 	duk_hthread *thr = (duk_hthread *) ctx;
14499 
14500 	DUK_ASSERT_CTX_VALID(ctx);
14501 	DUK_ASSERT_DISABLE(stridx >= 0);
14502 	DUK_ASSERT(stridx < DUK_HEAP_NUM_STRINGS);
14503 	DUK_UNREF(thr);
14504 
14505 	obj_idx = duk_require_normalize_index(ctx, obj_idx);
14506 	duk_push_hstring(ctx, DUK_HTHREAD_GET_STRING(thr, stridx));
14507 	return duk__put_prop_shared(ctx, obj_idx, -1);
14508 }
14509 
duk_del_prop(duk_context * ctx,duk_idx_t obj_index)14510 DUK_EXTERNAL duk_bool_t duk_del_prop(duk_context *ctx, duk_idx_t obj_index) {
14511 	duk_hthread *thr = (duk_hthread *) ctx;
14512 	duk_tval *tv_obj;
14513 	duk_tval *tv_key;
14514 	duk_small_int_t throw_flag;
14515 	duk_bool_t rc;
14516 
14517 	DUK_ASSERT_CTX_VALID(ctx);
14518 
14519 	/* Note: copying tv_obj and tv_key to locals to shield against a valstack
14520 	 * resize is not necessary for a property delete right now.
14521 	 */
14522 
14523 	tv_obj = duk_require_tval(ctx, obj_index);
14524 	tv_key = duk_require_tval(ctx, -1);
14525 	throw_flag = duk_is_strict_call(ctx);
14526 
14527 	rc = duk_hobject_delprop(thr, tv_obj, tv_key, throw_flag);
14528 	DUK_ASSERT(rc == 0 || rc == 1);
14529 
14530 	duk_pop(ctx);  /* remove key */
14531 	return rc;
14532 }
14533 
duk_del_prop_string(duk_context * ctx,duk_idx_t obj_index,const char * key)14534 DUK_EXTERNAL duk_bool_t duk_del_prop_string(duk_context *ctx, duk_idx_t obj_index, const char *key) {
14535 	DUK_ASSERT_CTX_VALID(ctx);
14536 	DUK_ASSERT(key != NULL);
14537 
14538 	obj_index = duk_require_normalize_index(ctx, obj_index);
14539 	duk_push_string(ctx, key);
14540 	return duk_del_prop(ctx, obj_index);
14541 }
14542 
duk_del_prop_index(duk_context * ctx,duk_idx_t obj_index,duk_uarridx_t arr_index)14543 DUK_EXTERNAL duk_bool_t duk_del_prop_index(duk_context *ctx, duk_idx_t obj_index, duk_uarridx_t arr_index) {
14544 	DUK_ASSERT_CTX_VALID(ctx);
14545 
14546 	obj_index = duk_require_normalize_index(ctx, obj_index);
14547 	duk_push_uarridx(ctx, arr_index);
14548 	return duk_del_prop(ctx, obj_index);
14549 }
14550 
duk_del_prop_stridx(duk_context * ctx,duk_idx_t obj_index,duk_small_int_t stridx)14551 DUK_INTERNAL duk_bool_t duk_del_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx) {
14552 	duk_hthread *thr = (duk_hthread *) ctx;
14553 
14554 	DUK_ASSERT_CTX_VALID(ctx);
14555 	DUK_ASSERT_DISABLE(stridx >= 0);
14556 	DUK_ASSERT(stridx < DUK_HEAP_NUM_STRINGS);
14557 	DUK_UNREF(thr);
14558 
14559 	obj_index = duk_require_normalize_index(ctx, obj_index);
14560 	duk_push_hstring(ctx, DUK_HTHREAD_GET_STRING(thr, stridx));
14561 	return duk_del_prop(ctx, obj_index);
14562 }
14563 
duk_has_prop(duk_context * ctx,duk_idx_t obj_index)14564 DUK_EXTERNAL duk_bool_t duk_has_prop(duk_context *ctx, duk_idx_t obj_index) {
14565 	duk_hthread *thr = (duk_hthread *) ctx;
14566 	duk_tval *tv_obj;
14567 	duk_tval *tv_key;
14568 	duk_bool_t rc;
14569 
14570 	DUK_ASSERT_CTX_VALID(ctx);
14571 
14572 	/* Note: copying tv_obj and tv_key to locals to shield against a valstack
14573 	 * resize is not necessary for a property existence check right now.
14574 	 */
14575 
14576 	tv_obj = duk_require_tval(ctx, obj_index);
14577 	tv_key = duk_require_tval(ctx, -1);
14578 
14579 	rc = duk_hobject_hasprop(thr, tv_obj, tv_key);
14580 	DUK_ASSERT(rc == 0 || rc == 1);
14581 
14582 	duk_pop(ctx);  /* remove key */
14583 	return rc;  /* 1 if property found, 0 otherwise */
14584 }
14585 
duk_has_prop_string(duk_context * ctx,duk_idx_t obj_index,const char * key)14586 DUK_EXTERNAL duk_bool_t duk_has_prop_string(duk_context *ctx, duk_idx_t obj_index, const char *key) {
14587 	DUK_ASSERT_CTX_VALID(ctx);
14588 	DUK_ASSERT(key != NULL);
14589 
14590 	obj_index = duk_require_normalize_index(ctx, obj_index);
14591 	duk_push_string(ctx, key);
14592 	return duk_has_prop(ctx, obj_index);
14593 }
14594 
duk_has_prop_index(duk_context * ctx,duk_idx_t obj_index,duk_uarridx_t arr_index)14595 DUK_EXTERNAL duk_bool_t duk_has_prop_index(duk_context *ctx, duk_idx_t obj_index, duk_uarridx_t arr_index) {
14596 	DUK_ASSERT_CTX_VALID(ctx);
14597 
14598 	obj_index = duk_require_normalize_index(ctx, obj_index);
14599 	duk_push_uarridx(ctx, arr_index);
14600 	return duk_has_prop(ctx, obj_index);
14601 }
14602 
duk_has_prop_stridx(duk_context * ctx,duk_idx_t obj_index,duk_small_int_t stridx)14603 DUK_INTERNAL duk_bool_t duk_has_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx) {
14604 	duk_hthread *thr = (duk_hthread *) ctx;
14605 
14606 	DUK_ASSERT_CTX_VALID(ctx);
14607 	DUK_ASSERT_DISABLE(stridx >= 0);
14608 	DUK_ASSERT(stridx < DUK_HEAP_NUM_STRINGS);
14609 	DUK_UNREF(thr);
14610 
14611 	obj_index = duk_require_normalize_index(ctx, obj_index);
14612 	duk_push_hstring(ctx, DUK_HTHREAD_GET_STRING(thr, stridx));
14613 	return duk_has_prop(ctx, obj_index);
14614 }
14615 
14616 /* Define own property without inheritance looks and such.  This differs from
14617  * [[DefineOwnProperty]] because special behaviors (like Array 'length') are
14618  * not invoked by this method.  The caller must be careful to invoke any such
14619  * behaviors if necessary.
14620  */
duk_xdef_prop(duk_context * ctx,duk_idx_t obj_index,duk_small_uint_t desc_flags)14621 DUK_INTERNAL void duk_xdef_prop(duk_context *ctx, duk_idx_t obj_index, duk_small_uint_t desc_flags) {
14622 	duk_hthread *thr = (duk_hthread *) ctx;
14623 	duk_hobject *obj;
14624 	duk_hstring *key;
14625 
14626 	DUK_ASSERT_CTX_VALID(ctx);
14627 
14628 	obj = duk_require_hobject(ctx, obj_index);
14629 	DUK_ASSERT(obj != NULL);
14630 	key = duk_to_hstring(ctx, -2);
14631 	DUK_ASSERT(key != NULL);
14632 	DUK_ASSERT(duk_require_tval(ctx, -1) != NULL);
14633 
14634 	duk_hobject_define_property_internal(thr, obj, key, desc_flags);
14635 
14636 	duk_pop(ctx);  /* pop key */
14637 }
14638 
duk_xdef_prop_index(duk_context * ctx,duk_idx_t obj_index,duk_uarridx_t arr_index,duk_small_uint_t desc_flags)14639 DUK_INTERNAL void duk_xdef_prop_index(duk_context *ctx, duk_idx_t obj_index, duk_uarridx_t arr_index, duk_small_uint_t desc_flags) {
14640 	duk_hthread *thr = (duk_hthread *) ctx;
14641 	duk_hobject *obj;
14642 
14643 	DUK_ASSERT_CTX_VALID(ctx);
14644 
14645 	obj = duk_require_hobject(ctx, obj_index);
14646 	DUK_ASSERT(obj != NULL);
14647 
14648 	duk_hobject_define_property_internal_arridx(thr, obj, arr_index, desc_flags);
14649 	/* value popped by call */
14650 }
14651 
duk_xdef_prop_stridx(duk_context * ctx,duk_idx_t obj_index,duk_small_int_t stridx,duk_small_uint_t desc_flags)14652 DUK_INTERNAL void duk_xdef_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx, duk_small_uint_t desc_flags) {
14653 	duk_hthread *thr = (duk_hthread *) ctx;
14654 	duk_hobject *obj;
14655 	duk_hstring *key;
14656 
14657 	DUK_ASSERT_CTX_VALID(ctx);
14658 	DUK_ASSERT_DISABLE(stridx >= 0);
14659 	DUK_ASSERT(stridx < DUK_HEAP_NUM_STRINGS);
14660 
14661 	obj = duk_require_hobject(ctx, obj_index);
14662 	DUK_ASSERT(obj != NULL);
14663 	key = DUK_HTHREAD_GET_STRING(thr, stridx);
14664 	DUK_ASSERT(key != NULL);
14665 	DUK_ASSERT(duk_require_tval(ctx, -1) != NULL);
14666 
14667 	duk_hobject_define_property_internal(thr, obj, key, desc_flags);
14668 	/* value popped by call */
14669 }
14670 
duk_xdef_prop_stridx_builtin(duk_context * ctx,duk_idx_t obj_index,duk_small_int_t stridx,duk_small_int_t builtin_idx,duk_small_uint_t desc_flags)14671 DUK_INTERNAL void duk_xdef_prop_stridx_builtin(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx, duk_small_int_t builtin_idx, duk_small_uint_t desc_flags) {
14672 	duk_hthread *thr = (duk_hthread *) ctx;
14673 	duk_hobject *obj;
14674 	duk_hstring *key;
14675 
14676 	DUK_ASSERT_CTX_VALID(ctx);
14677 	DUK_ASSERT_DISABLE(stridx >= 0);
14678 	DUK_ASSERT(stridx < DUK_HEAP_NUM_STRINGS);
14679 	DUK_ASSERT_DISABLE(builtin_idx >= 0);
14680 	DUK_ASSERT(builtin_idx < DUK_NUM_BUILTINS);
14681 
14682 	obj = duk_require_hobject(ctx, obj_index);
14683 	DUK_ASSERT(obj != NULL);
14684 	key = DUK_HTHREAD_GET_STRING(thr, stridx);
14685 	DUK_ASSERT(key != NULL);
14686 
14687 	duk_push_hobject(ctx, thr->builtins[builtin_idx]);
14688 	duk_hobject_define_property_internal(thr, obj, key, desc_flags);
14689 	/* value popped by call */
14690 }
14691 
14692 /* This is a rare property helper; it sets the global thrower (E5 Section 13.2.3)
14693  * setter/getter into an object property.  This is needed by the 'arguments'
14694  * object creation code, function instance creation code, and Function.prototype.bind().
14695  */
14696 
duk_xdef_prop_stridx_thrower(duk_context * ctx,duk_idx_t obj_index,duk_small_int_t stridx,duk_small_uint_t desc_flags)14697 DUK_INTERNAL void duk_xdef_prop_stridx_thrower(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx, duk_small_uint_t desc_flags) {
14698 	duk_hthread *thr = (duk_hthread *) ctx;
14699 	duk_hobject *obj = duk_require_hobject(ctx, obj_index);
14700 	duk_hobject *thrower = thr->builtins[DUK_BIDX_TYPE_ERROR_THROWER];
14701 	duk_hobject_define_accessor_internal(thr, obj, DUK_HTHREAD_GET_STRING(thr, stridx), thrower, thrower, desc_flags);
14702 }
14703 
14704 /* Object.defineProperty() equivalent C binding. */
duk_def_prop(duk_context * ctx,duk_idx_t obj_index,duk_uint_t flags)14705 DUK_EXTERNAL void duk_def_prop(duk_context *ctx, duk_idx_t obj_index, duk_uint_t flags) {
14706 	duk_hthread *thr = (duk_hthread *) ctx;
14707 	duk_idx_t idx_base;
14708 	duk_hobject *obj;
14709 	duk_hstring *key;
14710 	duk_idx_t idx_value;
14711 	duk_hobject *get;
14712 	duk_hobject *set;
14713 	duk_uint_t is_data_desc;
14714 	duk_uint_t is_acc_desc;
14715 
14716 	DUK_ASSERT_CTX_VALID(ctx);
14717 
14718 	obj = duk_require_hobject(ctx, obj_index);
14719 
14720 	is_data_desc = flags & (DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_HAVE_WRITABLE);
14721 	is_acc_desc = flags & (DUK_DEFPROP_HAVE_GETTER | DUK_DEFPROP_HAVE_SETTER);
14722 	if (is_data_desc && is_acc_desc) {
14723 		/* "Have" flags must not be conflicting so that they would
14724 		 * apply to both a plain property and an accessor at the same
14725 		 * time.
14726 		 */
14727 		goto fail_invalid_desc;
14728 	}
14729 
14730 	idx_base = duk_get_top_index(ctx);
14731 	if (flags & DUK_DEFPROP_HAVE_SETTER) {
14732 		duk_require_type_mask(ctx, idx_base, DUK_TYPE_MASK_UNDEFINED |
14733 		                                     DUK_TYPE_MASK_OBJECT |
14734 		                                     DUK_TYPE_MASK_LIGHTFUNC);
14735 		set = duk_get_hobject_or_lfunc_coerce(ctx, idx_base);
14736 		if (set != NULL && !DUK_HOBJECT_IS_CALLABLE(set)) {
14737 			goto fail_not_callable;
14738 		}
14739 		idx_base--;
14740 	} else {
14741 		set = NULL;
14742 	}
14743 	if (flags & DUK_DEFPROP_HAVE_GETTER) {
14744 		duk_require_type_mask(ctx, idx_base, DUK_TYPE_MASK_UNDEFINED |
14745 		                                     DUK_TYPE_MASK_OBJECT |
14746 		                                     DUK_TYPE_MASK_LIGHTFUNC);
14747 		get = duk_get_hobject_or_lfunc_coerce(ctx, idx_base);
14748 		if (get != NULL && !DUK_HOBJECT_IS_CALLABLE(get)) {
14749 			goto fail_not_callable;
14750 		}
14751 		idx_base--;
14752 	} else {
14753 		get = NULL;
14754 	}
14755 	if (flags & DUK_DEFPROP_HAVE_VALUE) {
14756 		idx_value = idx_base;
14757 		idx_base--;
14758 	} else {
14759 		idx_value = (duk_idx_t) -1;
14760 	}
14761 	key = duk_require_hstring(ctx, idx_base);
14762 
14763 	duk_require_valid_index(ctx, idx_base);
14764 
14765 	duk_hobject_define_property_helper(ctx,
14766 	                                   flags /*defprop_flags*/,
14767 	                                   obj,
14768 	                                   key,
14769 	                                   idx_value,
14770 	                                   get,
14771 	                                   set);
14772 
14773 	/* Clean up stack */
14774 
14775 	duk_set_top(ctx, idx_base);
14776 
14777 	/* [ ... obj ... ] */
14778 
14779 	return;
14780 
14781  fail_invalid_desc:
14782 	DUK_ERROR_TYPE(thr, DUK_STR_INVALID_DESCRIPTOR);
14783 	return;
14784 
14785  fail_not_callable:
14786 	DUK_ERROR_TYPE(thr, DUK_STR_NOT_CALLABLE);
14787 	return;
14788 }
14789 
14790 /*
14791  *  Object related
14792  *
14793  *  Note: seal() and freeze() are accessible through Ecmascript bindings,
14794  *  and are not exposed through the API.
14795  */
14796 
duk_compact(duk_context * ctx,duk_idx_t obj_index)14797 DUK_EXTERNAL void duk_compact(duk_context *ctx, duk_idx_t obj_index) {
14798 	duk_hthread *thr = (duk_hthread *) ctx;
14799 	duk_hobject *obj;
14800 
14801 	DUK_ASSERT_CTX_VALID(ctx);
14802 
14803 	obj = duk_get_hobject(ctx, obj_index);
14804 	if (obj) {
14805 		/* Note: this may fail, caller should protect the call if necessary */
14806 		duk_hobject_compact_props(thr, obj);
14807 	}
14808 }
14809 
14810 /* XXX: the duk_hobject_enum.c stack APIs should be reworked */
14811 
duk_enum(duk_context * ctx,duk_idx_t obj_index,duk_uint_t enum_flags)14812 DUK_EXTERNAL void duk_enum(duk_context *ctx, duk_idx_t obj_index, duk_uint_t enum_flags) {
14813 	DUK_ASSERT_CTX_VALID(ctx);
14814 
14815 	duk_dup(ctx, obj_index);
14816 	duk_require_hobject_or_lfunc_coerce(ctx, -1);
14817 	duk_hobject_enumerator_create(ctx, enum_flags);   /* [target] -> [enum] */
14818 }
14819 
duk_next(duk_context * ctx,duk_idx_t enum_index,duk_bool_t get_value)14820 DUK_EXTERNAL duk_bool_t duk_next(duk_context *ctx, duk_idx_t enum_index, duk_bool_t get_value) {
14821 	DUK_ASSERT_CTX_VALID(ctx);
14822 
14823 	duk_require_hobject(ctx, enum_index);
14824 	duk_dup(ctx, enum_index);
14825 	return duk_hobject_enumerator_next(ctx, get_value);
14826 }
14827 
14828 /*
14829  *  Helpers for writing multiple properties
14830  */
14831 
duk_put_function_list(duk_context * ctx,duk_idx_t obj_index,const duk_function_list_entry * funcs)14832 DUK_EXTERNAL void duk_put_function_list(duk_context *ctx, duk_idx_t obj_index, const duk_function_list_entry *funcs) {
14833 	const duk_function_list_entry *ent = funcs;
14834 
14835 	DUK_ASSERT_CTX_VALID(ctx);
14836 
14837 	obj_index = duk_require_normalize_index(ctx, obj_index);
14838 	if (ent != NULL) {
14839 		while (ent->key != NULL) {
14840 			duk_push_c_function(ctx, ent->value, ent->nargs);
14841 			duk_put_prop_string(ctx, obj_index, ent->key);
14842 			ent++;
14843 		}
14844 	}
14845 }
14846 
duk_put_number_list(duk_context * ctx,duk_idx_t obj_index,const duk_number_list_entry * numbers)14847 DUK_EXTERNAL void duk_put_number_list(duk_context *ctx, duk_idx_t obj_index, const duk_number_list_entry *numbers) {
14848 	const duk_number_list_entry *ent = numbers;
14849 
14850 	DUK_ASSERT_CTX_VALID(ctx);
14851 
14852 	obj_index = duk_require_normalize_index(ctx, obj_index);
14853 	if (ent != NULL) {
14854 		while (ent->key != NULL) {
14855 			duk_push_number(ctx, ent->value);
14856 			duk_put_prop_string(ctx, obj_index, ent->key);
14857 			ent++;
14858 		}
14859 	}
14860 }
14861 
14862 /*
14863  *  Shortcut for accessing global object properties
14864  */
14865 
duk_get_global_string(duk_context * ctx,const char * key)14866 DUK_EXTERNAL duk_bool_t duk_get_global_string(duk_context *ctx, const char *key) {
14867 	duk_hthread *thr = (duk_hthread *) ctx;
14868 	duk_bool_t ret;
14869 
14870 	DUK_ASSERT_CTX_VALID(ctx);
14871 	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
14872 
14873 	/* XXX: direct implementation */
14874 
14875 	duk_push_hobject(ctx, thr->builtins[DUK_BIDX_GLOBAL]);
14876 	ret = duk_get_prop_string(ctx, -1, key);
14877 	duk_remove(ctx, -2);
14878 	return ret;
14879 }
14880 
duk_put_global_string(duk_context * ctx,const char * key)14881 DUK_EXTERNAL duk_bool_t duk_put_global_string(duk_context *ctx, const char *key) {
14882 	duk_hthread *thr = (duk_hthread *) ctx;
14883 	duk_bool_t ret;
14884 
14885 	DUK_ASSERT_CTX_VALID(ctx);
14886 	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
14887 
14888 	/* XXX: direct implementation */
14889 
14890 	duk_push_hobject(ctx, thr->builtins[DUK_BIDX_GLOBAL]);
14891 	duk_insert(ctx, -2);
14892 	ret = duk_put_prop_string(ctx, -2, key);  /* [ ... global val ] -> [ ... global ] */
14893 	duk_pop(ctx);
14894 	return ret;
14895 }
14896 
14897 /*
14898  *  Object prototype
14899  */
14900 
duk_get_prototype(duk_context * ctx,duk_idx_t index)14901 DUK_EXTERNAL void duk_get_prototype(duk_context *ctx, duk_idx_t index) {
14902 	duk_hthread *thr = (duk_hthread *) ctx;
14903 	duk_hobject *obj;
14904 	duk_hobject *proto;
14905 
14906 	DUK_ASSERT_CTX_VALID(ctx);
14907 	DUK_UNREF(thr);
14908 
14909 	obj = duk_require_hobject(ctx, index);
14910 	DUK_ASSERT(obj != NULL);
14911 
14912 	/* XXX: shared helper for duk_push_hobject_or_undefined()? */
14913 	proto = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, obj);
14914 	if (proto) {
14915 		duk_push_hobject(ctx, proto);
14916 	} else {
14917 		duk_push_undefined(ctx);
14918 	}
14919 }
14920 
duk_set_prototype(duk_context * ctx,duk_idx_t index)14921 DUK_EXTERNAL void duk_set_prototype(duk_context *ctx, duk_idx_t index) {
14922 	duk_hthread *thr = (duk_hthread *) ctx;
14923 	duk_hobject *obj;
14924 	duk_hobject *proto;
14925 
14926 	DUK_ASSERT_CTX_VALID(ctx);
14927 
14928 	obj = duk_require_hobject(ctx, index);
14929 	DUK_ASSERT(obj != NULL);
14930 	duk_require_type_mask(ctx, -1, DUK_TYPE_MASK_UNDEFINED |
14931 	                               DUK_TYPE_MASK_OBJECT);
14932 	proto = duk_get_hobject(ctx, -1);
14933 	/* proto can also be NULL here (allowed explicitly) */
14934 
14935 #if defined(DUK_USE_ROM_OBJECTS)
14936 	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {
14937 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);  /* XXX: "read only object"? */
14938 		return;
14939 	}
14940 #endif
14941 
14942 	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, obj, proto);
14943 
14944 	duk_pop(ctx);
14945 }
14946 
14947 /*
14948  *  Object finalizer
14949  */
14950 
14951 /* XXX: these could be implemented as macros calling an internal function
14952  * directly.
14953  * XXX: same issue as with Duktape.fin: there's no way to delete the property
14954  * now (just set it to undefined).
14955  */
duk_get_finalizer(duk_context * ctx,duk_idx_t index)14956 DUK_EXTERNAL void duk_get_finalizer(duk_context *ctx, duk_idx_t index) {
14957 	DUK_ASSERT_CTX_VALID(ctx);
14958 
14959 	duk_get_prop_stridx(ctx, index, DUK_STRIDX_INT_FINALIZER);
14960 }
14961 
duk_set_finalizer(duk_context * ctx,duk_idx_t index)14962 DUK_EXTERNAL void duk_set_finalizer(duk_context *ctx, duk_idx_t index) {
14963 	DUK_ASSERT_CTX_VALID(ctx);
14964 
14965 	duk_put_prop_stridx(ctx, index, DUK_STRIDX_INT_FINALIZER);
14966 }
14967 /*
14968  *  API calls related to general value stack manipulation: resizing the value
14969  *  stack, pushing and popping values, type checking and reading values,
14970  *  coercing values, etc.
14971  *
14972  *  Also contains internal functions (such as duk_get_tval()), defined
14973  *  in duk_api_internal.h, with semantics similar to the public API.
14974  */
14975 
14976 /* XXX: repetition of stack pre-checks -> helper or macro or inline */
14977 /* XXX: shared api error strings, and perhaps even throw code for rare cases? */
14978 
14979 /* include removed: duk_internal.h */
14980 
14981 /*
14982  *  Forward declarations
14983  */
14984 
14985 DUK_LOCAL_DECL duk_idx_t duk__push_c_function_raw(duk_context *ctx, duk_c_function func, duk_idx_t nargs, duk_uint_t flags);
14986 
14987 /*
14988  *  Global state for working around missing variadic macros
14989  */
14990 
14991 #ifndef DUK_USE_VARIADIC_MACROS
14992 DUK_EXTERNAL const char *duk_api_global_filename = NULL;
14993 DUK_EXTERNAL duk_int_t duk_api_global_line = 0;
14994 #endif
14995 
14996 /*
14997  *  Misc helpers
14998  */
14999 
15000 /* Check that there's room to push one value. */
15001 #if defined(DUK_USE_VALSTACK_UNSAFE)
15002 /* Faster but value stack overruns are memory unsafe. */
15003 #define DUK__CHECK_SPACE() do { \
15004 		DUK_ASSERT(!(thr->valstack_top >= thr->valstack_end)); \
15005 	} while (0)
15006 #else
15007 #define DUK__CHECK_SPACE() do { \
15008 		if (DUK_UNLIKELY(thr->valstack_top >= thr->valstack_end)) { \
15009 			DUK_ERROR_API(thr, DUK_STR_PUSH_BEYOND_ALLOC_STACK); \
15010 		} \
15011 	} while (0)
15012 #endif
15013 
15014 DUK_LOCAL_DECL duk_heaphdr *duk__get_tagged_heaphdr_raw(duk_context *ctx, duk_idx_t index, duk_uint_t tag);
15015 
duk__api_coerce_d2i(duk_context * ctx,duk_idx_t index,duk_bool_t require)15016 DUK_LOCAL duk_int_t duk__api_coerce_d2i(duk_context *ctx, duk_idx_t index, duk_bool_t require) {
15017 	duk_hthread *thr;
15018 	duk_tval *tv;
15019 	duk_small_int_t c;
15020 	duk_double_t d;
15021 
15022 	thr = (duk_hthread *) ctx;
15023 
15024 	tv = duk_get_tval(ctx, index);
15025 	if (tv == NULL) {
15026 		goto error_notnumber;
15027 	}
15028 
15029 	/*
15030 	 *  Special cases like NaN and +/- Infinity are handled explicitly
15031 	 *  because a plain C coercion from double to int handles these cases
15032 	 *  in undesirable ways.  For instance, NaN may coerce to INT_MIN
15033 	 *  (not zero), and INT_MAX + 1 may coerce to INT_MIN (not INT_MAX).
15034 	 *
15035 	 *  This double-to-int coercion differs from ToInteger() because it
15036 	 *  has a finite range (ToInteger() allows e.g. +/- Infinity).  It
15037 	 *  also differs from ToInt32() because the INT_MIN/INT_MAX clamping
15038 	 *  depends on the size of the int type on the platform.  In particular,
15039 	 *  on platforms with a 64-bit int type, the full range is allowed.
15040 	 */
15041 
15042 #if defined(DUK_USE_FASTINT)
15043 	if (DUK_TVAL_IS_FASTINT(tv)) {
15044 		duk_int64_t t = DUK_TVAL_GET_FASTINT(tv);
15045 #if (DUK_INT_MAX <= 0x7fffffffL)
15046 		/* Clamping only necessary for 32-bit ints. */
15047 		if (t < DUK_INT_MIN) {
15048 			t = DUK_INT_MIN;
15049 		} else if (t > DUK_INT_MAX) {
15050 			t = DUK_INT_MAX;
15051 		}
15052 #endif
15053 		return (duk_int_t) t;
15054 	}
15055 #endif
15056 
15057 	if (DUK_TVAL_IS_NUMBER(tv)) {
15058 		d = DUK_TVAL_GET_NUMBER(tv);
15059 		c = (duk_small_int_t) DUK_FPCLASSIFY(d);
15060 		if (c == DUK_FP_NAN) {
15061 			return 0;
15062 		} else if (d < (duk_double_t) DUK_INT_MIN) {
15063 			/* covers -Infinity */
15064 			return DUK_INT_MIN;
15065 		} else if (d > (duk_double_t) DUK_INT_MAX) {
15066 			/* covers +Infinity */
15067 			return DUK_INT_MAX;
15068 		} else {
15069 			/* coerce towards zero */
15070 			return (duk_int_t) d;
15071 		}
15072 	}
15073 
15074  error_notnumber:
15075 
15076 	if (require) {
15077 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, index, "number", DUK_STR_NOT_NUMBER);
15078 		/* not reachable */
15079 	}
15080 	return 0;
15081 }
15082 
duk__api_coerce_d2ui(duk_context * ctx,duk_idx_t index,duk_bool_t require)15083 DUK_LOCAL duk_uint_t duk__api_coerce_d2ui(duk_context *ctx, duk_idx_t index, duk_bool_t require) {
15084 	duk_hthread *thr;
15085 	duk_tval *tv;
15086 	duk_small_int_t c;
15087 	duk_double_t d;
15088 
15089 	/* Same as above but for unsigned int range. */
15090 
15091 	thr = (duk_hthread *) ctx;
15092 
15093 	tv = duk_get_tval(ctx, index);
15094 	if (tv == NULL) {
15095 		goto error_notnumber;
15096 	}
15097 
15098 #if defined(DUK_USE_FASTINT)
15099 	if (DUK_TVAL_IS_FASTINT(tv)) {
15100 		duk_int64_t t = DUK_TVAL_GET_FASTINT(tv);
15101 		if (t < 0) {
15102 			t = 0;
15103 		}
15104 #if (DUK_UINT_MAX <= 0xffffffffUL)
15105 		/* Clamping only necessary for 32-bit ints. */
15106 		else if (t > DUK_UINT_MAX) {
15107 			t = DUK_UINT_MAX;
15108 		}
15109 #endif
15110 		return (duk_uint_t) t;
15111 	}
15112 #endif
15113 
15114 	if (DUK_TVAL_IS_NUMBER(tv)) {
15115 		d = DUK_TVAL_GET_NUMBER(tv);
15116 		c = (duk_small_int_t) DUK_FPCLASSIFY(d);
15117 		if (c == DUK_FP_NAN) {
15118 			return 0;
15119 		} else if (d < 0.0) {
15120 			/* covers -Infinity */
15121 			return (duk_uint_t) 0;
15122 		} else if (d > (duk_double_t) DUK_UINT_MAX) {
15123 			/* covers +Infinity */
15124 			return (duk_uint_t) DUK_UINT_MAX;
15125 		} else {
15126 			/* coerce towards zero */
15127 			return (duk_uint_t) d;
15128 		}
15129 	}
15130 
15131  error_notnumber:
15132 
15133 	if (require) {
15134 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, index, "number", DUK_STR_NOT_NUMBER);
15135 		/* not reachable */
15136 	}
15137 	return 0;
15138 }
15139 
15140 /*
15141  *  Stack index validation/normalization and getting a stack duk_tval ptr.
15142  *
15143  *  These are called by many API entrypoints so the implementations must be
15144  *  fast and "inlined".
15145  *
15146  *  There's some repetition because of this; keep the functions in sync.
15147  */
15148 
duk_normalize_index(duk_context * ctx,duk_idx_t index)15149 DUK_EXTERNAL duk_idx_t duk_normalize_index(duk_context *ctx, duk_idx_t index) {
15150 	duk_hthread *thr = (duk_hthread *) ctx;
15151 	duk_uidx_t vs_size;
15152 	duk_uidx_t uindex;
15153 
15154 	DUK_ASSERT_CTX_VALID(ctx);
15155 	DUK_ASSERT(DUK_INVALID_INDEX < 0);
15156 
15157 	/* Care must be taken to avoid pointer wrapping in the index
15158 	 * validation.  For instance, on a 32-bit platform with 8-byte
15159 	 * duk_tval the index 0x20000000UL would wrap the memory space
15160 	 * once.
15161 	 */
15162 
15163 	/* Assume value stack sizes (in elements) fits into duk_idx_t. */
15164 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
15165 	vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
15166 	DUK_ASSERT_DISABLE(vs_size >= 0);  /* unsigned */
15167 
15168 	if (index < 0) {
15169 		uindex = vs_size + (duk_uidx_t) index;
15170 	} else {
15171 		/* since index non-negative */
15172 		DUK_ASSERT(index != DUK_INVALID_INDEX);
15173 		uindex = (duk_uidx_t) index;
15174 	}
15175 
15176 	/* DUK_INVALID_INDEX won't be accepted as a valid index. */
15177 	DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);
15178 
15179 	if (DUK_LIKELY(uindex < vs_size)) {
15180 		return (duk_idx_t) uindex;
15181 	}
15182 	return DUK_INVALID_INDEX;
15183 }
15184 
duk_require_normalize_index(duk_context * ctx,duk_idx_t index)15185 DUK_EXTERNAL duk_idx_t duk_require_normalize_index(duk_context *ctx, duk_idx_t index) {
15186 	duk_hthread *thr = (duk_hthread *) ctx;
15187 	duk_uidx_t vs_size;
15188 	duk_uidx_t uindex;
15189 
15190 	DUK_ASSERT_CTX_VALID(ctx);
15191 	DUK_ASSERT(DUK_INVALID_INDEX < 0);
15192 
15193 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
15194 	vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
15195 	DUK_ASSERT_DISABLE(vs_size >= 0);  /* unsigned */
15196 
15197 	if (index < 0) {
15198 		uindex = vs_size + (duk_uidx_t) index;
15199 	} else {
15200 		DUK_ASSERT(index != DUK_INVALID_INDEX);
15201 		uindex = (duk_uidx_t) index;
15202 	}
15203 
15204 	/* DUK_INVALID_INDEX won't be accepted as a valid index. */
15205 	DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);
15206 
15207 	if (DUK_LIKELY(uindex < vs_size)) {
15208 		return (duk_idx_t) uindex;
15209 	}
15210 	DUK_ERROR_API_INDEX(thr, index);
15211 	return 0;  /* unreachable */
15212 }
15213 
duk_get_tval(duk_context * ctx,duk_idx_t index)15214 DUK_INTERNAL duk_tval *duk_get_tval(duk_context *ctx, duk_idx_t index) {
15215 	duk_hthread *thr = (duk_hthread *) ctx;
15216 	duk_uidx_t vs_size;
15217 	duk_uidx_t uindex;
15218 
15219 	DUK_ASSERT_CTX_VALID(ctx);
15220 	DUK_ASSERT(DUK_INVALID_INDEX < 0);
15221 
15222 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
15223 	vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
15224 	DUK_ASSERT_DISABLE(vs_size >= 0);  /* unsigned */
15225 
15226 	if (index < 0) {
15227 		uindex = vs_size + (duk_uidx_t) index;
15228 	} else {
15229 		DUK_ASSERT(index != DUK_INVALID_INDEX);
15230 		uindex = (duk_uidx_t) index;
15231 	}
15232 
15233 	/* DUK_INVALID_INDEX won't be accepted as a valid index. */
15234 	DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);
15235 
15236 	if (DUK_LIKELY(uindex < vs_size)) {
15237 		return thr->valstack_bottom + uindex;
15238 	}
15239 	return NULL;
15240 }
15241 
duk_require_tval(duk_context * ctx,duk_idx_t index)15242 DUK_INTERNAL duk_tval *duk_require_tval(duk_context *ctx, duk_idx_t index) {
15243 	duk_hthread *thr = (duk_hthread *) ctx;
15244 	duk_uidx_t vs_size;
15245 	duk_uidx_t uindex;
15246 
15247 	DUK_ASSERT_CTX_VALID(ctx);
15248 	DUK_ASSERT(DUK_INVALID_INDEX < 0);
15249 
15250 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
15251 	vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
15252 	DUK_ASSERT_DISABLE(vs_size >= 0);  /* unsigned */
15253 
15254 	/* Use unsigned arithmetic to optimize comparison. */
15255 	if (index < 0) {
15256 		uindex = vs_size + (duk_uidx_t) index;
15257 	} else {
15258 		DUK_ASSERT(index != DUK_INVALID_INDEX);
15259 		uindex = (duk_uidx_t) index;
15260 	}
15261 
15262 	/* DUK_INVALID_INDEX won't be accepted as a valid index. */
15263 	DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);
15264 
15265 	if (DUK_LIKELY(uindex < vs_size)) {
15266 		return thr->valstack_bottom + uindex;
15267 	}
15268 	DUK_ERROR_API_INDEX(thr, index);
15269 	return NULL;
15270 }
15271 
15272 /* Non-critical. */
duk_is_valid_index(duk_context * ctx,duk_idx_t index)15273 DUK_EXTERNAL duk_bool_t duk_is_valid_index(duk_context *ctx, duk_idx_t index) {
15274 	DUK_ASSERT_CTX_VALID(ctx);
15275 	DUK_ASSERT(DUK_INVALID_INDEX < 0);
15276 
15277 	return (duk_normalize_index(ctx, index) >= 0);
15278 }
15279 
15280 /* Non-critical. */
duk_require_valid_index(duk_context * ctx,duk_idx_t index)15281 DUK_EXTERNAL void duk_require_valid_index(duk_context *ctx, duk_idx_t index) {
15282 	duk_hthread *thr = (duk_hthread *) ctx;
15283 
15284 	DUK_ASSERT_CTX_VALID(ctx);
15285 	DUK_ASSERT(DUK_INVALID_INDEX < 0);
15286 
15287 	if (duk_normalize_index(ctx, index) < 0) {
15288 		DUK_ERROR_API_INDEX(thr, index);
15289 		return;  /* unreachable */
15290 	}
15291 }
15292 
15293 /*
15294  *  Value stack top handling
15295  */
15296 
duk_get_top(duk_context * ctx)15297 DUK_EXTERNAL duk_idx_t duk_get_top(duk_context *ctx) {
15298 	duk_hthread *thr = (duk_hthread *) ctx;
15299 
15300 	DUK_ASSERT_CTX_VALID(ctx);
15301 
15302 	return (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
15303 }
15304 
15305 /* Set stack top within currently allocated range, but don't reallocate.
15306  * This is performance critical especially for call handling, so whenever
15307  * changing, profile and look at generated code.
15308  */
duk_set_top(duk_context * ctx,duk_idx_t index)15309 DUK_EXTERNAL void duk_set_top(duk_context *ctx, duk_idx_t index) {
15310 	duk_hthread *thr = (duk_hthread *) ctx;
15311 	duk_uidx_t vs_size;
15312 	duk_uidx_t vs_limit;
15313 	duk_uidx_t uindex;
15314 	duk_tval *tv;
15315 
15316 	DUK_ASSERT_CTX_VALID(ctx);
15317 	DUK_ASSERT(DUK_INVALID_INDEX < 0);
15318 
15319 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
15320 	DUK_ASSERT(thr->valstack_end >= thr->valstack_bottom);
15321 	vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
15322 	vs_limit = (duk_uidx_t) (thr->valstack_end - thr->valstack_bottom);
15323 
15324 	if (index < 0) {
15325 		/* Negative indices are always within allocated stack but
15326 		 * must not go below zero index.
15327 		 */
15328 		uindex = vs_size + (duk_uidx_t) index;
15329 	} else {
15330 		/* Positive index can be higher than valstack top but must
15331 		 * not go above allocated stack (equality is OK).
15332 		 */
15333 		uindex = (duk_uidx_t) index;
15334 	}
15335 
15336 	/* DUK_INVALID_INDEX won't be accepted as a valid index. */
15337 	DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);
15338 	DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_limit);
15339 
15340 #if defined(DUK_USE_VALSTACK_UNSAFE)
15341 	DUK_ASSERT(uindex <= vs_limit);
15342 	DUK_UNREF(vs_limit);
15343 #else
15344 	if (DUK_UNLIKELY(uindex > vs_limit)) {
15345 		DUK_ERROR_API_INDEX(thr, index);
15346 		return;  /* unreachable */
15347 	}
15348 #endif
15349 	DUK_ASSERT(uindex <= vs_limit);
15350 
15351 	/* Handle change in value stack top.  Respect value stack
15352 	 * initialization policy: 'undefined' above top.  Note that
15353 	 * DECREF may cause a side effect that reallocates valstack,
15354 	 * so must relookup after DECREF.
15355 	 */
15356 
15357 	if (uindex >= vs_size) {
15358 		/* Stack size increases or stays the same. */
15359 #if defined(DUK_USE_ASSERTIONS)
15360 		duk_uidx_t count;
15361 
15362 		count = uindex - vs_size;
15363 		while (count != 0) {
15364 			count--;
15365 			tv = thr->valstack_top + count;
15366 			DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv));
15367 		}
15368 #endif
15369 		thr->valstack_top = thr->valstack_bottom + uindex;
15370 	} else {
15371 		/* Stack size decreases. */
15372 #if defined(DUK_USE_REFERENCE_COUNTING)
15373 		duk_uidx_t count;
15374 
15375 		count = vs_size - uindex;
15376 		DUK_ASSERT(count > 0);
15377 		while (count > 0) {
15378 			count--;
15379 			tv = --thr->valstack_top;  /* tv -> value just before prev top value; must relookup */
15380 			DUK_ASSERT(tv >= thr->valstack_bottom);
15381 			DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv);  /* side effects */
15382 		}
15383 #else  /* DUK_USE_REFERENCE_COUNTING */
15384 		duk_uidx_t count;
15385 		duk_tval *tv_end;
15386 
15387 		count = vs_size - uindex;
15388 		tv = thr->valstack_top;
15389 		tv_end = tv - count;
15390 		DUK_ASSERT(tv > tv_end);
15391 		do {
15392 			tv--;
15393 			DUK_TVAL_SET_UNDEFINED(tv);
15394 		} while (tv != tv_end);
15395 		thr->valstack_top = tv_end;
15396 #endif  /* DUK_USE_REFERENCE_COUNTING */
15397 	}
15398 }
15399 
duk_get_top_index(duk_context * ctx)15400 DUK_EXTERNAL duk_idx_t duk_get_top_index(duk_context *ctx) {
15401 	duk_hthread *thr = (duk_hthread *) ctx;
15402 	duk_idx_t ret;
15403 
15404 	DUK_ASSERT_CTX_VALID(ctx);
15405 
15406 	ret = ((duk_idx_t) (thr->valstack_top - thr->valstack_bottom)) - 1;
15407 	if (DUK_UNLIKELY(ret < 0)) {
15408 		/* Return invalid index; if caller uses this without checking
15409 		 * in another API call, the index won't map to a valid stack
15410 		 * entry.
15411 		 */
15412 		return DUK_INVALID_INDEX;
15413 	}
15414 	return ret;
15415 }
15416 
duk_require_top_index(duk_context * ctx)15417 DUK_EXTERNAL duk_idx_t duk_require_top_index(duk_context *ctx) {
15418 	duk_hthread *thr = (duk_hthread *) ctx;
15419 	duk_idx_t ret;
15420 
15421 	DUK_ASSERT_CTX_VALID(ctx);
15422 
15423 	ret = ((duk_idx_t) (thr->valstack_top - thr->valstack_bottom)) - 1;
15424 	if (DUK_UNLIKELY(ret < 0)) {
15425 		DUK_ERROR_API_INDEX(thr, -1);
15426 		return 0;  /* unreachable */
15427 	}
15428 	return ret;
15429 }
15430 
15431 /*
15432  *  Value stack resizing.
15433  *
15434  *  This resizing happens above the current "top": the value stack can be
15435  *  grown or shrunk, but the "top" is not affected.  The value stack cannot
15436  *  be resized to a size below the current "top".
15437  *
15438  *  The low level reallocation primitive must carefully recompute all value
15439  *  stack pointers, and must also work if ALL pointers are NULL.  The resize
15440  *  is quite tricky because the valstack realloc may cause a mark-and-sweep,
15441  *  which may run finalizers.  Running finalizers may resize the valstack
15442  *  recursively (the same value stack we're working on).  So, after realloc
15443  *  returns, we know that the valstack "top" should still be the same (there
15444  *  should not be live values above the "top"), but its underlying size and
15445  *  pointer may have changed.
15446  */
15447 
15448 /* XXX: perhaps refactor this to allow caller to specify some parameters, or
15449  * at least a 'compact' flag which skips any spare or round-up .. useful for
15450  * emergency gc.
15451  */
15452 
duk__resize_valstack(duk_context * ctx,duk_size_t new_size)15453 DUK_LOCAL duk_bool_t duk__resize_valstack(duk_context *ctx, duk_size_t new_size) {
15454 	duk_hthread *thr = (duk_hthread *) ctx;
15455 	duk_ptrdiff_t old_bottom_offset;
15456 	duk_ptrdiff_t old_top_offset;
15457 	duk_ptrdiff_t old_end_offset_post;
15458 #ifdef DUK_USE_DEBUG
15459 	duk_ptrdiff_t old_end_offset_pre;
15460 	duk_tval *old_valstack_pre;
15461 	duk_tval *old_valstack_post;
15462 #endif
15463 	duk_tval *new_valstack;
15464 	duk_size_t new_alloc_size;
15465 	duk_tval *p;
15466 
15467 	DUK_ASSERT_CTX_VALID(ctx);
15468 	DUK_ASSERT(thr != NULL);
15469 	DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
15470 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
15471 	DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
15472 	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack) <= new_size);  /* can't resize below 'top' */
15473 	DUK_ASSERT(new_size <= thr->valstack_max);  /* valstack limit caller has check, prevents wrapping */
15474 	DUK_ASSERT(new_size <= DUK_SIZE_MAX / sizeof(duk_tval));  /* specific assert for wrapping */
15475 
15476 	/* get pointer offsets for tweaking below */
15477 	old_bottom_offset = (((duk_uint8_t *) thr->valstack_bottom) - ((duk_uint8_t *) thr->valstack));
15478 	old_top_offset = (((duk_uint8_t *) thr->valstack_top) - ((duk_uint8_t *) thr->valstack));
15479 #ifdef DUK_USE_DEBUG
15480 	old_end_offset_pre = (((duk_uint8_t *) thr->valstack_end) - ((duk_uint8_t *) thr->valstack));  /* not very useful, used for debugging */
15481 	old_valstack_pre = thr->valstack;
15482 #endif
15483 
15484 	/* Allocate a new valstack.
15485 	 *
15486 	 * Note: cannot use a plain DUK_REALLOC() because a mark-and-sweep may
15487 	 * invalidate the original thr->valstack base pointer inside the realloc
15488 	 * process.  See doc/memory-management.rst.
15489 	 */
15490 
15491 	new_alloc_size = sizeof(duk_tval) * new_size;
15492 	new_valstack = (duk_tval *) DUK_REALLOC_INDIRECT(thr->heap, duk_hthread_get_valstack_ptr, (void *) thr, new_alloc_size);
15493 	if (!new_valstack) {
15494 		/* Because new_size != 0, if condition doesn't need to be
15495 		 * (new_valstack != NULL || new_size == 0).
15496 		 */
15497 		DUK_ASSERT(new_size != 0);
15498 		DUK_D(DUK_DPRINT("failed to resize valstack to %lu entries (%lu bytes)",
15499 		                 (unsigned long) new_size, (unsigned long) new_alloc_size));
15500 		return 0;
15501 	}
15502 
15503 	/* Note: the realloc may have triggered a mark-and-sweep which may
15504 	 * have resized our valstack internally.  However, the mark-and-sweep
15505 	 * MUST NOT leave the stack bottom/top in a different state.  Particular
15506 	 * assumptions and facts:
15507 	 *
15508 	 *   - The thr->valstack pointer may be different after realloc,
15509 	 *     and the offset between thr->valstack_end <-> thr->valstack
15510 	 *     may have changed.
15511 	 *   - The offset between thr->valstack_bottom <-> thr->valstack
15512 	 *     and thr->valstack_top <-> thr->valstack MUST NOT have changed,
15513 	 *     because mark-and-sweep must adhere to a strict stack policy.
15514 	 *     In other words, logical bottom and top MUST NOT have changed.
15515 	 *   - All values above the top are unreachable but are initialized
15516 	 *     to UNDEFINED, up to the post-realloc valstack_end.
15517 	 *   - 'old_end_offset' must be computed after realloc to be correct.
15518 	 */
15519 
15520 	DUK_ASSERT((((duk_uint8_t *) thr->valstack_bottom) - ((duk_uint8_t *) thr->valstack)) == old_bottom_offset);
15521 	DUK_ASSERT((((duk_uint8_t *) thr->valstack_top) - ((duk_uint8_t *) thr->valstack)) == old_top_offset);
15522 
15523 	/* success, fixup pointers */
15524 	old_end_offset_post = (((duk_uint8_t *) thr->valstack_end) - ((duk_uint8_t *) thr->valstack));  /* must be computed after realloc */
15525 #ifdef DUK_USE_DEBUG
15526 	old_valstack_post = thr->valstack;
15527 #endif
15528 	thr->valstack = new_valstack;
15529 	thr->valstack_end = new_valstack + new_size;
15530 #if !defined(DUK_USE_PREFER_SIZE)
15531 	thr->valstack_size = new_size;
15532 #endif
15533 	thr->valstack_bottom = (duk_tval *) (void *) ((duk_uint8_t *) new_valstack + old_bottom_offset);
15534 	thr->valstack_top = (duk_tval *) (void *) ((duk_uint8_t *) new_valstack + old_top_offset);
15535 
15536 	DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
15537 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
15538 	DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
15539 
15540 	/* useful for debugging */
15541 #ifdef DUK_USE_DEBUG
15542 	if (old_end_offset_pre != old_end_offset_post) {
15543 		DUK_D(DUK_DPRINT("valstack was resized during valstack_resize(), probably by mark-and-sweep; "
15544 		                 "end offset changed: %lu -> %lu",
15545 		                 (unsigned long) old_end_offset_pre,
15546 		                 (unsigned long) old_end_offset_post));
15547 	}
15548 	if (old_valstack_pre != old_valstack_post) {
15549 		DUK_D(DUK_DPRINT("valstack pointer changed during valstack_resize(), probably by mark-and-sweep: %p -> %p",
15550 		                 (void *) old_valstack_pre,
15551 		                 (void *) old_valstack_post));
15552 	}
15553 #endif
15554 
15555 	DUK_DD(DUK_DDPRINT("resized valstack to %lu elements (%lu bytes), bottom=%ld, top=%ld, "
15556 	                   "new pointers: start=%p end=%p bottom=%p top=%p",
15557 	                   (unsigned long) new_size, (unsigned long) new_alloc_size,
15558 	                   (long) (thr->valstack_bottom - thr->valstack),
15559 	                   (long) (thr->valstack_top - thr->valstack),
15560 	                   (void *) thr->valstack, (void *) thr->valstack_end,
15561 	                   (void *) thr->valstack_bottom, (void *) thr->valstack_top));
15562 
15563 	/* Init newly allocated slots (only). */
15564 	p = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + old_end_offset_post);
15565 	while (p < thr->valstack_end) {
15566 		/* Never executed if new size is smaller. */
15567 		DUK_TVAL_SET_UNDEFINED(p);
15568 		p++;
15569 	}
15570 
15571 	/* Assert for value stack initialization policy. */
15572 #if defined(DUK_USE_ASSERTIONS)
15573 	p = thr->valstack_top;
15574 	while (p < thr->valstack_end) {
15575 		DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(p));
15576 		p++;
15577 	}
15578 #endif
15579 
15580 	return 1;
15581 }
15582 
15583 DUK_INTERNAL
duk_valstack_resize_raw(duk_context * ctx,duk_size_t min_new_size,duk_small_uint_t flags)15584 duk_bool_t duk_valstack_resize_raw(duk_context *ctx,
15585                                    duk_size_t min_new_size,
15586                                    duk_small_uint_t flags) {
15587 	duk_hthread *thr = (duk_hthread *) ctx;
15588 	duk_size_t old_size;
15589 	duk_size_t new_size;
15590 	duk_bool_t is_shrink = 0;
15591 	duk_small_uint_t shrink_flag = (flags & DUK_VSRESIZE_FLAG_SHRINK);
15592 	duk_small_uint_t compact_flag = (flags & DUK_VSRESIZE_FLAG_COMPACT);
15593 	duk_small_uint_t throw_flag = (flags & DUK_VSRESIZE_FLAG_THROW);
15594 
15595 	DUK_DDD(DUK_DDDPRINT("check valstack resize: min_new_size=%lu, curr_size=%ld, curr_top=%ld, "
15596 	                     "curr_bottom=%ld, shrink=%d, compact=%d, throw=%d",
15597 	                     (unsigned long) min_new_size,
15598 	                     (long) (thr->valstack_end - thr->valstack),
15599 	                     (long) (thr->valstack_top - thr->valstack),
15600 	                     (long) (thr->valstack_bottom - thr->valstack),
15601 	                     (int) shrink_flag, (int) compact_flag, (int) throw_flag));
15602 
15603 	DUK_ASSERT_CTX_VALID(ctx);
15604 	DUK_ASSERT(thr != NULL);
15605 	DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
15606 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
15607 	DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
15608 
15609 #if defined(DUK_USE_PREFER_SIZE)
15610 	old_size = (duk_size_t) (thr->valstack_end - thr->valstack);
15611 #else
15612 	DUK_ASSERT((duk_size_t) (thr->valstack_end - thr->valstack) == thr->valstack_size);
15613 	old_size = thr->valstack_size;
15614 #endif
15615 
15616 	if (min_new_size <= old_size) {
15617 		is_shrink = 1;
15618 		if (!shrink_flag ||
15619 		    old_size - min_new_size < DUK_VALSTACK_SHRINK_THRESHOLD) {
15620 			DUK_DDD(DUK_DDDPRINT("no need to grow or shrink valstack"));
15621 			return 1;
15622 		}
15623 	}
15624 
15625 	new_size = min_new_size;
15626 	if (!compact_flag) {
15627 		if (is_shrink) {
15628 			/* shrink case; leave some spare */
15629 			new_size += DUK_VALSTACK_SHRINK_SPARE;
15630 		}
15631 
15632 		/* round up roughly to next 'grow step' */
15633 		new_size = (new_size / DUK_VALSTACK_GROW_STEP + 1) * DUK_VALSTACK_GROW_STEP;
15634 	}
15635 
15636 	DUK_DD(DUK_DDPRINT("want to %s valstack: %lu -> %lu elements (min_new_size %lu)",
15637 	                   (const char *) (new_size > old_size ? "grow" : "shrink"),
15638 	                   (unsigned long) old_size, (unsigned long) new_size,
15639 	                   (unsigned long) min_new_size));
15640 
15641 	if (new_size > thr->valstack_max) {
15642 		/* Note: may be triggered even if minimal new_size would not reach the limit,
15643 		 * plan limit accordingly (taking DUK_VALSTACK_GROW_STEP into account).
15644 		 */
15645 		if (throw_flag) {
15646 			DUK_ERROR_RANGE(thr, DUK_STR_VALSTACK_LIMIT);
15647 		} else {
15648 			return 0;
15649 		}
15650 	}
15651 
15652 	/*
15653 	 *  When resizing the valstack, a mark-and-sweep may be triggered for
15654 	 *  the allocation of the new valstack.  If the mark-and-sweep needs
15655 	 *  to use our thread for something, it may cause *the same valstack*
15656 	 *  to be resized recursively.  This happens e.g. when mark-and-sweep
15657 	 *  finalizers are called.  This is taken into account carefully in
15658 	 *  duk__resize_valstack().
15659 	 *
15660 	 *  'new_size' is known to be <= valstack_max, which ensures that
15661 	 *  size_t and pointer arithmetic won't wrap in duk__resize_valstack().
15662 	 */
15663 
15664 	if (!duk__resize_valstack(ctx, new_size)) {
15665 		if (is_shrink) {
15666 			DUK_DD(DUK_DDPRINT("valstack resize failed, but is a shrink, ignore"));
15667 			return 1;
15668 		}
15669 
15670 		DUK_DD(DUK_DDPRINT("valstack resize failed"));
15671 
15672 		if (throw_flag) {
15673 			DUK_ERROR_ALLOC_DEFMSG(thr);
15674 		} else {
15675 			return 0;
15676 		}
15677 	}
15678 
15679 	DUK_DDD(DUK_DDDPRINT("valstack resize successful"));
15680 	return 1;
15681 }
15682 
duk_check_stack(duk_context * ctx,duk_idx_t extra)15683 DUK_EXTERNAL duk_bool_t duk_check_stack(duk_context *ctx, duk_idx_t extra) {
15684 	duk_hthread *thr = (duk_hthread *) ctx;
15685 	duk_size_t min_new_size;
15686 
15687 	DUK_ASSERT_CTX_VALID(ctx);
15688 	DUK_ASSERT(thr != NULL);
15689 
15690 	if (DUK_UNLIKELY(extra < 0)) {
15691 		/* Clamping to zero makes the API more robust to calling code
15692 		 * calculation errors.
15693 		 */
15694 		extra = 0;
15695 	}
15696 
15697 	min_new_size = (thr->valstack_top - thr->valstack) + extra + DUK_VALSTACK_INTERNAL_EXTRA;
15698 	return duk_valstack_resize_raw(ctx,
15699 	                               min_new_size,         /* min_new_size */
15700 	                               0 /* no shrink */ |   /* flags */
15701 	                               0 /* no compact */ |
15702 	                               0 /* no throw */);
15703 }
15704 
duk_require_stack(duk_context * ctx,duk_idx_t extra)15705 DUK_EXTERNAL void duk_require_stack(duk_context *ctx, duk_idx_t extra) {
15706 	duk_hthread *thr = (duk_hthread *) ctx;
15707 	duk_size_t min_new_size;
15708 
15709 	DUK_ASSERT_CTX_VALID(ctx);
15710 	DUK_ASSERT(thr != NULL);
15711 
15712 	if (DUK_UNLIKELY(extra < 0)) {
15713 		/* Clamping to zero makes the API more robust to calling code
15714 		 * calculation errors.
15715 		 */
15716 		extra = 0;
15717 	}
15718 
15719 	min_new_size = (thr->valstack_top - thr->valstack) + extra + DUK_VALSTACK_INTERNAL_EXTRA;
15720 	(void) duk_valstack_resize_raw(ctx,
15721 	                               min_new_size,  /* min_new_size */
15722 	                               0 /* no shrink */ |   /* flags */
15723 	                               0 /* no compact */ |
15724 	                               DUK_VSRESIZE_FLAG_THROW);
15725 }
15726 
duk_check_stack_top(duk_context * ctx,duk_idx_t top)15727 DUK_EXTERNAL duk_bool_t duk_check_stack_top(duk_context *ctx, duk_idx_t top) {
15728 	duk_hthread *thr;
15729 	duk_size_t min_new_size;
15730 
15731 	DUK_ASSERT_CTX_VALID(ctx);
15732 	thr = (duk_hthread *) ctx;
15733 
15734 	if (DUK_UNLIKELY(top < 0)) {
15735 		/* Clamping to zero makes the API more robust to calling code
15736 		 * calculation errors.
15737 		 */
15738 		top = 0;
15739 	}
15740 
15741 	min_new_size = (thr->valstack_bottom - thr->valstack) + top + DUK_VALSTACK_INTERNAL_EXTRA;
15742 	return duk_valstack_resize_raw(ctx,
15743 	                               min_new_size,  /* min_new_size */
15744 	                               0 /* no shrink */ |   /* flags */
15745 	                               0 /* no compact */ |
15746 	                               0 /* no throw */);
15747 }
15748 
duk_require_stack_top(duk_context * ctx,duk_idx_t top)15749 DUK_EXTERNAL void duk_require_stack_top(duk_context *ctx, duk_idx_t top) {
15750 	duk_hthread *thr;
15751 	duk_size_t min_new_size;
15752 
15753 	DUK_ASSERT_CTX_VALID(ctx);
15754 	thr = (duk_hthread *) ctx;
15755 
15756 	if (DUK_UNLIKELY(top < 0)) {
15757 		/* Clamping to zero makes the API more robust to calling code
15758 		 * calculation errors.
15759 		 */
15760 		top = 0;
15761 	}
15762 
15763 	min_new_size = (thr->valstack_bottom - thr->valstack) + top + DUK_VALSTACK_INTERNAL_EXTRA;
15764 	(void) duk_valstack_resize_raw(ctx,
15765 	                               min_new_size,  /* min_new_size */
15766 	                               0 /* no shrink */ |   /* flags */
15767 	                               0 /* no compact */ |
15768 	                               DUK_VSRESIZE_FLAG_THROW);
15769 }
15770 
15771 /*
15772  *  Basic stack manipulation: swap, dup, insert, replace, etc
15773  */
15774 
duk_swap(duk_context * ctx,duk_idx_t index1,duk_idx_t index2)15775 DUK_EXTERNAL void duk_swap(duk_context *ctx, duk_idx_t index1, duk_idx_t index2) {
15776 	duk_tval *tv1;
15777 	duk_tval *tv2;
15778 	duk_tval tv_tmp;
15779 
15780 	DUK_ASSERT_CTX_VALID(ctx);
15781 
15782 	tv1 = duk_require_tval(ctx, index1);
15783 	DUK_ASSERT(tv1 != NULL);
15784 	tv2 = duk_require_tval(ctx, index2);
15785 	DUK_ASSERT(tv2 != NULL);
15786 
15787 	/* If tv1==tv2 this is a NOP, no check is needed */
15788 	DUK_TVAL_SET_TVAL(&tv_tmp, tv1);
15789 	DUK_TVAL_SET_TVAL(tv1, tv2);
15790 	DUK_TVAL_SET_TVAL(tv2, &tv_tmp);
15791 }
15792 
duk_swap_top(duk_context * ctx,duk_idx_t index)15793 DUK_EXTERNAL void duk_swap_top(duk_context *ctx, duk_idx_t index) {
15794 	DUK_ASSERT_CTX_VALID(ctx);
15795 
15796 	duk_swap(ctx, index, -1);
15797 }
15798 
duk_dup(duk_context * ctx,duk_idx_t from_index)15799 DUK_EXTERNAL void duk_dup(duk_context *ctx, duk_idx_t from_index) {
15800 	duk_hthread *thr;
15801 	duk_tval *tv_from;
15802 	duk_tval *tv_to;
15803 
15804 	DUK_ASSERT_CTX_VALID(ctx);
15805 	thr = (duk_hthread *) ctx;
15806 	DUK__CHECK_SPACE();
15807 
15808 	tv_from = duk_require_tval(ctx, from_index);
15809 	tv_to = thr->valstack_top++;
15810 	DUK_ASSERT(tv_from != NULL);
15811 	DUK_ASSERT(tv_to != NULL);
15812 	DUK_TVAL_SET_TVAL(tv_to, tv_from);
15813 	DUK_TVAL_INCREF(thr, tv_to);  /* no side effects */
15814 }
15815 
duk_dup_top(duk_context * ctx)15816 DUK_EXTERNAL void duk_dup_top(duk_context *ctx) {
15817 	duk_hthread *thr;
15818 	duk_tval *tv_from;
15819 	duk_tval *tv_to;
15820 
15821 	DUK_ASSERT_CTX_VALID(ctx);
15822 	thr = (duk_hthread *) ctx;
15823 	DUK__CHECK_SPACE();
15824 
15825 	if (thr->valstack_top - thr->valstack_bottom <= 0) {
15826 		DUK_ERROR_API_INDEX(thr, -1);
15827 		return;  /* unreachable */
15828 	}
15829 	tv_from = thr->valstack_top - 1;
15830 	tv_to = thr->valstack_top++;
15831 	DUK_ASSERT(tv_from != NULL);
15832 	DUK_ASSERT(tv_to != NULL);
15833 	DUK_TVAL_SET_TVAL(tv_to, tv_from);
15834 	DUK_TVAL_INCREF(thr, tv_to);  /* no side effects */
15835 }
15836 
duk_insert(duk_context * ctx,duk_idx_t to_index)15837 DUK_EXTERNAL void duk_insert(duk_context *ctx, duk_idx_t to_index) {
15838 	duk_tval *p;
15839 	duk_tval *q;
15840 	duk_tval tv_tmp;
15841 	duk_size_t nbytes;
15842 
15843 	DUK_ASSERT_CTX_VALID(ctx);
15844 
15845 	p = duk_require_tval(ctx, to_index);
15846 	DUK_ASSERT(p != NULL);
15847 	q = duk_require_tval(ctx, -1);
15848 	DUK_ASSERT(q != NULL);
15849 
15850 	DUK_ASSERT(q >= p);
15851 
15852 	/*              nbytes
15853 	 *           <--------->
15854 	 *    [ ... | p | x | x | q ]
15855 	 * => [ ... | q | p | x | x ]
15856 	 */
15857 
15858 	nbytes = (duk_size_t) (((duk_uint8_t *) q) - ((duk_uint8_t *) p));  /* Note: 'q' is top-1 */
15859 
15860 	DUK_DDD(DUK_DDDPRINT("duk_insert: to_index=%ld, p=%p, q=%p, nbytes=%lu",
15861 	                     (long) to_index, (void *) p, (void *) q, (unsigned long) nbytes));
15862 
15863 	/* No net refcount changes. */
15864 
15865 	if (nbytes > 0) {
15866 		DUK_TVAL_SET_TVAL(&tv_tmp, q);
15867 		DUK_ASSERT(nbytes > 0);
15868 		DUK_MEMMOVE((void *) (p + 1), (const void *) p, (size_t) nbytes);
15869 		DUK_TVAL_SET_TVAL(p, &tv_tmp);
15870 	} else {
15871 		/* nop: insert top to top */
15872 		DUK_ASSERT(nbytes == 0);
15873 		DUK_ASSERT(p == q);
15874 	}
15875 }
15876 
duk_replace(duk_context * ctx,duk_idx_t to_index)15877 DUK_EXTERNAL void duk_replace(duk_context *ctx, duk_idx_t to_index) {
15878 	duk_hthread *thr = (duk_hthread *) ctx;
15879 	duk_tval *tv1;
15880 	duk_tval *tv2;
15881 	duk_tval tv_tmp;
15882 
15883 	DUK_ASSERT_CTX_VALID(ctx);
15884 
15885 	tv1 = duk_require_tval(ctx, -1);
15886 	DUK_ASSERT(tv1 != NULL);
15887 	tv2 = duk_require_tval(ctx, to_index);
15888 	DUK_ASSERT(tv2 != NULL);
15889 
15890 	/* For tv1 == tv2, both pointing to stack top, the end result
15891 	 * is same as duk_pop(ctx).
15892 	 */
15893 	DUK_TVAL_SET_TVAL(&tv_tmp, tv2);
15894 	DUK_TVAL_SET_TVAL(tv2, tv1);
15895 	DUK_TVAL_SET_UNDEFINED(tv1);
15896 	thr->valstack_top--;
15897 	DUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */
15898 }
15899 
duk_copy(duk_context * ctx,duk_idx_t from_index,duk_idx_t to_index)15900 DUK_EXTERNAL void duk_copy(duk_context *ctx, duk_idx_t from_index, duk_idx_t to_index) {
15901 	duk_hthread *thr = (duk_hthread *) ctx;
15902 	duk_tval *tv1;
15903 	duk_tval *tv2;
15904 
15905 	DUK_ASSERT_CTX_VALID(ctx);
15906 	DUK_UNREF(thr);  /* w/o refcounting */
15907 
15908 	tv1 = duk_require_tval(ctx, from_index);
15909 	DUK_ASSERT(tv1 != NULL);
15910 	tv2 = duk_require_tval(ctx, to_index);
15911 	DUK_ASSERT(tv2 != NULL);
15912 
15913 	/* For tv1 == tv2, this is a no-op (no explicit check needed). */
15914 	DUK_TVAL_SET_TVAL_UPDREF(thr, tv2, tv1);  /* side effects */
15915 }
15916 
duk_remove(duk_context * ctx,duk_idx_t index)15917 DUK_EXTERNAL void duk_remove(duk_context *ctx, duk_idx_t index) {
15918 	duk_hthread *thr = (duk_hthread *) ctx;
15919 	duk_tval *p;
15920 	duk_tval *q;
15921 #ifdef DUK_USE_REFERENCE_COUNTING
15922 	duk_tval tv_tmp;
15923 #endif
15924 	duk_size_t nbytes;
15925 
15926 	DUK_ASSERT_CTX_VALID(ctx);
15927 
15928 	p = duk_require_tval(ctx, index);
15929 	DUK_ASSERT(p != NULL);
15930 	q = duk_require_tval(ctx, -1);
15931 	DUK_ASSERT(q != NULL);
15932 
15933 	DUK_ASSERT(q >= p);
15934 
15935 	/*              nbytes            zero size case
15936 	 *           <--------->
15937 	 *    [ ... | p | x | x | q ]     [ ... | p==q ]
15938 	 * => [ ... | x | x | q ]         [ ... ]
15939 	 */
15940 
15941 #ifdef DUK_USE_REFERENCE_COUNTING
15942 	/* use a temp: decref only when valstack reachable values are correct */
15943 	DUK_TVAL_SET_TVAL(&tv_tmp, p);
15944 #endif
15945 
15946 	nbytes = (duk_size_t) (((duk_uint8_t *) q) - ((duk_uint8_t *) p));  /* Note: 'q' is top-1 */
15947 	DUK_MEMMOVE((void *) p, (const void *) (p + 1), (size_t) nbytes);  /* zero size not an issue: pointers are valid */
15948 
15949 	DUK_TVAL_SET_UNDEFINED(q);
15950 	thr->valstack_top--;
15951 
15952 #ifdef DUK_USE_REFERENCE_COUNTING
15953 	DUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */
15954 #endif
15955 }
15956 
15957 /*
15958  *  Stack slice primitives
15959  */
15960 
duk_xcopymove_raw(duk_context * to_ctx,duk_context * from_ctx,duk_idx_t count,duk_bool_t is_copy)15961 DUK_EXTERNAL void duk_xcopymove_raw(duk_context *to_ctx, duk_context *from_ctx, duk_idx_t count, duk_bool_t is_copy) {
15962 	duk_hthread *to_thr = (duk_hthread *) to_ctx;
15963 	duk_hthread *from_thr = (duk_hthread *) from_ctx;
15964 	void *src;
15965 	duk_size_t nbytes;
15966 	duk_tval *p;
15967 	duk_tval *q;
15968 
15969 	/* XXX: several pointer comparison issues here */
15970 
15971 	DUK_ASSERT_CTX_VALID(to_ctx);
15972 	DUK_ASSERT_CTX_VALID(from_ctx);
15973 	DUK_ASSERT(to_ctx != NULL);
15974 	DUK_ASSERT(from_ctx != NULL);
15975 
15976 	if (to_ctx == from_ctx) {
15977 		DUK_ERROR_API(to_thr, DUK_STR_INVALID_CONTEXT);
15978 		return;
15979 	}
15980 	if ((count < 0) ||
15981 	    (count > (duk_idx_t) to_thr->valstack_max)) {
15982 		/* Maximum value check ensures 'nbytes' won't wrap below. */
15983 		DUK_ERROR_API(to_thr, DUK_STR_INVALID_COUNT);
15984 		return;
15985 	}
15986 
15987 	nbytes = sizeof(duk_tval) * count;
15988 	if (nbytes == 0) {
15989 		return;
15990 	}
15991 	DUK_ASSERT(to_thr->valstack_top <= to_thr->valstack_end);
15992 	if ((duk_size_t) ((duk_uint8_t *) to_thr->valstack_end - (duk_uint8_t *) to_thr->valstack_top) < nbytes) {
15993 		DUK_ERROR_API(to_thr, DUK_STR_PUSH_BEYOND_ALLOC_STACK);
15994 	}
15995 	src = (void *) ((duk_uint8_t *) from_thr->valstack_top - nbytes);
15996 	if (src < (void *) from_thr->valstack_bottom) {
15997 		DUK_ERROR_API(to_thr, DUK_STR_INVALID_COUNT);
15998 	}
15999 
16000 	/* copy values (no overlap even if to_ctx == from_ctx; that's not
16001 	 * allowed now anyway)
16002 	 */
16003 	DUK_ASSERT(nbytes > 0);
16004 	DUK_MEMCPY((void *) to_thr->valstack_top, (const void *) src, (size_t) nbytes);
16005 
16006 	p = to_thr->valstack_top;
16007 	to_thr->valstack_top = (duk_tval *) (void *) (((duk_uint8_t *) p) + nbytes);
16008 
16009 	if (is_copy) {
16010 		/* Incref copies, keep originals. */
16011 		q = to_thr->valstack_top;
16012 		while (p < q) {
16013 			DUK_TVAL_INCREF(to_thr, p);  /* no side effects */
16014 			p++;
16015 		}
16016 	} else {
16017 		/* No net refcount change. */
16018 		p = from_thr->valstack_top;
16019 		q = (duk_tval *) (void *) (((duk_uint8_t *) p) - nbytes);
16020 		from_thr->valstack_top = q;
16021 
16022 		while (p > q) {
16023 			p--;
16024 			DUK_TVAL_SET_UNDEFINED(p);
16025 			/* XXX: fast primitive to set a bunch of values to UNDEFINED */
16026 		}
16027 	}
16028 }
16029 
16030 /*
16031  *  Get/require
16032  */
16033 
duk_require_undefined(duk_context * ctx,duk_idx_t index)16034 DUK_EXTERNAL void duk_require_undefined(duk_context *ctx, duk_idx_t index) {
16035 	duk_hthread *thr = (duk_hthread *) ctx;
16036 	duk_tval *tv;
16037 
16038 	DUK_ASSERT_CTX_VALID(ctx);
16039 
16040 	tv = duk_get_tval(ctx, index);
16041 	if (tv && DUK_TVAL_IS_UNDEFINED(tv)) {
16042 		return;
16043 	}
16044 	DUK_ERROR_REQUIRE_TYPE_INDEX(thr, index, "undefined", DUK_STR_NOT_UNDEFINED);
16045 	return;  /* not reachable */
16046 }
16047 
duk_require_null(duk_context * ctx,duk_idx_t index)16048 DUK_EXTERNAL void duk_require_null(duk_context *ctx, duk_idx_t index) {
16049 	duk_hthread *thr = (duk_hthread *) ctx;
16050 	duk_tval *tv;
16051 
16052 	DUK_ASSERT_CTX_VALID(ctx);
16053 
16054 	tv = duk_get_tval(ctx, index);
16055 	if (tv && DUK_TVAL_IS_NULL(tv)) {
16056 		return;
16057 	}
16058 	DUK_ERROR_REQUIRE_TYPE_INDEX(thr, index, "null", DUK_STR_NOT_NULL);
16059 	return;  /* not reachable */
16060 }
16061 
duk_get_boolean(duk_context * ctx,duk_idx_t index)16062 DUK_EXTERNAL duk_bool_t duk_get_boolean(duk_context *ctx, duk_idx_t index) {
16063 	duk_bool_t ret = 0;  /* default: false */
16064 	duk_tval *tv;
16065 
16066 	DUK_ASSERT_CTX_VALID(ctx);
16067 
16068 	tv = duk_get_tval(ctx, index);
16069 	if (tv && DUK_TVAL_IS_BOOLEAN(tv)) {
16070 		ret = DUK_TVAL_GET_BOOLEAN(tv);
16071 	}
16072 
16073 	DUK_ASSERT(ret == 0 || ret == 1);
16074 	return ret;
16075 }
16076 
duk_require_boolean(duk_context * ctx,duk_idx_t index)16077 DUK_EXTERNAL duk_bool_t duk_require_boolean(duk_context *ctx, duk_idx_t index) {
16078 	duk_hthread *thr = (duk_hthread *) ctx;
16079 	duk_tval *tv;
16080 
16081 	DUK_ASSERT_CTX_VALID(ctx);
16082 
16083 	tv = duk_get_tval(ctx, index);
16084 	if (tv && DUK_TVAL_IS_BOOLEAN(tv)) {
16085 		duk_bool_t ret = DUK_TVAL_GET_BOOLEAN(tv);
16086 		DUK_ASSERT(ret == 0 || ret == 1);
16087 		return ret;
16088 	}
16089 	DUK_ERROR_REQUIRE_TYPE_INDEX(thr, index, "boolean", DUK_STR_NOT_BOOLEAN);
16090 	return 0;  /* not reachable */
16091 }
16092 
duk_get_number(duk_context * ctx,duk_idx_t index)16093 DUK_EXTERNAL duk_double_t duk_get_number(duk_context *ctx, duk_idx_t index) {
16094 	duk_double_union ret;
16095 	duk_tval *tv;
16096 
16097 	DUK_ASSERT_CTX_VALID(ctx);
16098 
16099 	ret.d = DUK_DOUBLE_NAN;  /* default: NaN */
16100 	tv = duk_get_tval(ctx, index);
16101 	if (tv && DUK_TVAL_IS_NUMBER(tv)) {
16102 		ret.d = DUK_TVAL_GET_NUMBER(tv);
16103 	}
16104 
16105 	/*
16106 	 *  Number should already be in NaN-normalized form, but let's
16107 	 *  normalize anyway.
16108 	 */
16109 
16110 	DUK_DBLUNION_NORMALIZE_NAN_CHECK(&ret);
16111 	return ret.d;
16112 }
16113 
duk_require_number(duk_context * ctx,duk_idx_t index)16114 DUK_EXTERNAL duk_double_t duk_require_number(duk_context *ctx, duk_idx_t index) {
16115 	duk_hthread *thr = (duk_hthread *) ctx;
16116 	duk_tval *tv;
16117 
16118 	DUK_ASSERT_CTX_VALID(ctx);
16119 
16120 	tv = duk_get_tval(ctx, index);
16121 	if (tv && DUK_TVAL_IS_NUMBER(tv)) {
16122 		duk_double_union ret;
16123 		ret.d = DUK_TVAL_GET_NUMBER(tv);
16124 
16125 		/*
16126 		 *  Number should already be in NaN-normalized form,
16127 		 *  but let's normalize anyway.
16128 		 */
16129 
16130 		DUK_DBLUNION_NORMALIZE_NAN_CHECK(&ret);
16131 		return ret.d;
16132 	}
16133 	DUK_ERROR_REQUIRE_TYPE_INDEX(thr, index, "number", DUK_STR_NOT_NUMBER);
16134 	return DUK_DOUBLE_NAN;  /* not reachable */
16135 }
16136 
duk_get_int(duk_context * ctx,duk_idx_t index)16137 DUK_EXTERNAL duk_int_t duk_get_int(duk_context *ctx, duk_idx_t index) {
16138 	/* Custom coercion for API */
16139 	DUK_ASSERT_CTX_VALID(ctx);
16140 	return (duk_int_t) duk__api_coerce_d2i(ctx, index, 0 /*require*/);
16141 }
16142 
duk_get_uint(duk_context * ctx,duk_idx_t index)16143 DUK_EXTERNAL duk_uint_t duk_get_uint(duk_context *ctx, duk_idx_t index) {
16144 	/* Custom coercion for API */
16145 	DUK_ASSERT_CTX_VALID(ctx);
16146 	return (duk_uint_t) duk__api_coerce_d2ui(ctx, index, 0 /*require*/);
16147 }
16148 
duk_require_int(duk_context * ctx,duk_idx_t index)16149 DUK_EXTERNAL duk_int_t duk_require_int(duk_context *ctx, duk_idx_t index) {
16150 	/* Custom coercion for API */
16151 	DUK_ASSERT_CTX_VALID(ctx);
16152 	return (duk_int_t) duk__api_coerce_d2i(ctx, index, 1 /*require*/);
16153 }
16154 
duk_require_uint(duk_context * ctx,duk_idx_t index)16155 DUK_EXTERNAL duk_uint_t duk_require_uint(duk_context *ctx, duk_idx_t index) {
16156 	/* Custom coercion for API */
16157 	DUK_ASSERT_CTX_VALID(ctx);
16158 	return (duk_uint_t) duk__api_coerce_d2ui(ctx, index, 1 /*require*/);
16159 }
16160 
duk_get_lstring(duk_context * ctx,duk_idx_t index,duk_size_t * out_len)16161 DUK_EXTERNAL const char *duk_get_lstring(duk_context *ctx, duk_idx_t index, duk_size_t *out_len) {
16162 	const char *ret;
16163 	duk_tval *tv;
16164 
16165 	DUK_ASSERT_CTX_VALID(ctx);
16166 
16167 	/* default: NULL, length 0 */
16168 	ret = NULL;
16169 	if (out_len) {
16170 		*out_len = 0;
16171 	}
16172 
16173 	tv = duk_get_tval(ctx, index);
16174 	if (tv && DUK_TVAL_IS_STRING(tv)) {
16175 		/* Here we rely on duk_hstring instances always being zero
16176 		 * terminated even if the actual string is not.
16177 		 */
16178 		duk_hstring *h = DUK_TVAL_GET_STRING(tv);
16179 		DUK_ASSERT(h != NULL);
16180 		ret = (const char *) DUK_HSTRING_GET_DATA(h);
16181 		if (out_len) {
16182 			*out_len = DUK_HSTRING_GET_BYTELEN(h);
16183 		}
16184 	}
16185 
16186 	return ret;
16187 }
16188 
duk_require_lstring(duk_context * ctx,duk_idx_t index,duk_size_t * out_len)16189 DUK_EXTERNAL const char *duk_require_lstring(duk_context *ctx, duk_idx_t index, duk_size_t *out_len) {
16190 	duk_hthread *thr = (duk_hthread *) ctx;
16191 	const char *ret;
16192 
16193 	DUK_ASSERT_CTX_VALID(ctx);
16194 
16195 	/* Note: this check relies on the fact that even a zero-size string
16196 	 * has a non-NULL pointer.
16197 	 */
16198 	ret = duk_get_lstring(ctx, index, out_len);
16199 	if (ret) {
16200 		return ret;
16201 	}
16202 	DUK_ERROR_REQUIRE_TYPE_INDEX(thr, index, "string", DUK_STR_NOT_STRING);
16203 	return NULL;  /* not reachable */
16204 }
16205 
duk_get_string(duk_context * ctx,duk_idx_t index)16206 DUK_EXTERNAL const char *duk_get_string(duk_context *ctx, duk_idx_t index) {
16207 	DUK_ASSERT_CTX_VALID(ctx);
16208 
16209 	return duk_get_lstring(ctx, index, NULL);
16210 }
16211 
duk_require_string(duk_context * ctx,duk_idx_t index)16212 DUK_EXTERNAL const char *duk_require_string(duk_context *ctx, duk_idx_t index) {
16213 	DUK_ASSERT_CTX_VALID(ctx);
16214 
16215 	return duk_require_lstring(ctx, index, NULL);
16216 }
16217 
duk_get_pointer(duk_context * ctx,duk_idx_t index)16218 DUK_EXTERNAL void *duk_get_pointer(duk_context *ctx, duk_idx_t index) {
16219 	duk_tval *tv;
16220 
16221 	DUK_ASSERT_CTX_VALID(ctx);
16222 
16223 	tv = duk_get_tval(ctx, index);
16224 	if (tv && DUK_TVAL_IS_POINTER(tv)) {
16225 		void *p = DUK_TVAL_GET_POINTER(tv);  /* may be NULL */
16226 		return (void *) p;
16227 	}
16228 
16229 	return NULL;
16230 }
16231 
duk_require_pointer(duk_context * ctx,duk_idx_t index)16232 DUK_EXTERNAL void *duk_require_pointer(duk_context *ctx, duk_idx_t index) {
16233 	duk_hthread *thr = (duk_hthread *) ctx;
16234 	duk_tval *tv;
16235 
16236 	DUK_ASSERT_CTX_VALID(ctx);
16237 
16238 	/* Note: here we must be wary of the fact that a pointer may be
16239 	 * valid and be a NULL.
16240 	 */
16241 	tv = duk_get_tval(ctx, index);
16242 	if (tv && DUK_TVAL_IS_POINTER(tv)) {
16243 		void *p = DUK_TVAL_GET_POINTER(tv);  /* may be NULL */
16244 		return (void *) p;
16245 	}
16246 	DUK_ERROR_REQUIRE_TYPE_INDEX(thr, index, "pointer", DUK_STR_NOT_POINTER);
16247 	return NULL;  /* not reachable */
16248 }
16249 
16250 #if 0  /*unused*/
16251 DUK_INTERNAL void *duk_get_voidptr(duk_context *ctx, duk_idx_t index) {
16252 	duk_tval *tv;
16253 
16254 	DUK_ASSERT_CTX_VALID(ctx);
16255 
16256 	tv = duk_get_tval(ctx, index);
16257 	if (tv && DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
16258 		duk_heaphdr *h = DUK_TVAL_GET_HEAPHDR(tv);
16259 		DUK_ASSERT(h != NULL);
16260 		return (void *) h;
16261 	}
16262 
16263 	return NULL;
16264 }
16265 #endif
16266 
duk__get_buffer_helper(duk_context * ctx,duk_idx_t index,duk_size_t * out_size,duk_bool_t throw_flag)16267 DUK_LOCAL void *duk__get_buffer_helper(duk_context *ctx, duk_idx_t index, duk_size_t *out_size, duk_bool_t throw_flag) {
16268 	duk_hthread *thr = (duk_hthread *) ctx;
16269 	duk_tval *tv;
16270 
16271 	DUK_ASSERT_CTX_VALID(ctx);
16272 	DUK_UNREF(thr);
16273 
16274 	if (out_size != NULL) {
16275 		*out_size = 0;
16276 	}
16277 
16278 	tv = duk_get_tval(ctx, index);
16279 	if (tv && DUK_TVAL_IS_BUFFER(tv)) {
16280 		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
16281 		DUK_ASSERT(h != NULL);
16282 		if (out_size) {
16283 			*out_size = DUK_HBUFFER_GET_SIZE(h);
16284 		}
16285 		return (void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h);  /* may be NULL (but only if size is 0) */
16286 	}
16287 
16288 	if (throw_flag) {
16289 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, index, "buffer", DUK_STR_NOT_BUFFER);
16290 	}
16291 	return NULL;
16292 }
16293 
duk_get_buffer(duk_context * ctx,duk_idx_t index,duk_size_t * out_size)16294 DUK_EXTERNAL void *duk_get_buffer(duk_context *ctx, duk_idx_t index, duk_size_t *out_size) {
16295 	return duk__get_buffer_helper(ctx, index, out_size, 0 /*throw_flag*/);
16296 }
16297 
duk_require_buffer(duk_context * ctx,duk_idx_t index,duk_size_t * out_size)16298 DUK_EXTERNAL void *duk_require_buffer(duk_context *ctx, duk_idx_t index, duk_size_t *out_size) {
16299 	return duk__get_buffer_helper(ctx, index, out_size, 1 /*throw_flag*/);
16300 }
16301 
duk__get_buffer_data_helper(duk_context * ctx,duk_idx_t index,duk_size_t * out_size,duk_bool_t throw_flag)16302 DUK_LOCAL void *duk__get_buffer_data_helper(duk_context *ctx, duk_idx_t index, duk_size_t *out_size, duk_bool_t throw_flag) {
16303 	duk_hthread *thr = (duk_hthread *) ctx;
16304 	duk_tval *tv;
16305 
16306 	DUK_ASSERT_CTX_VALID(ctx);
16307 	DUK_UNREF(thr);
16308 
16309 	if (out_size != NULL) {
16310 		*out_size = 0;
16311 	}
16312 
16313 	tv = duk_get_tval(ctx, index);
16314 	if (tv == NULL) {
16315 		goto fail;
16316 	}
16317 
16318 	if (DUK_TVAL_IS_BUFFER(tv)) {
16319 		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
16320 		DUK_ASSERT(h != NULL);
16321 		if (out_size) {
16322 			*out_size = DUK_HBUFFER_GET_SIZE(h);
16323 		}
16324 		return (void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h);  /* may be NULL (but only if size is 0) */
16325 	} else if (DUK_TVAL_IS_OBJECT(tv)) {
16326 		duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
16327 		DUK_ASSERT(h != NULL);
16328 		if (DUK_HOBJECT_IS_BUFFEROBJECT(h)) {
16329 			/* XXX: this is probably a useful shared helper: for a
16330 			 * duk_hbufferobject, get a validated buffer pointer/length.
16331 			 */
16332 			duk_hbufferobject *h_bufobj = (duk_hbufferobject *) h;
16333 			DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj);
16334 
16335 			if (h_bufobj->buf != NULL &&
16336 			    DUK_HBUFFEROBJECT_VALID_SLICE(h_bufobj)) {
16337 				duk_uint8_t *p;
16338 
16339 				p = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf);
16340 				if (out_size != NULL) {
16341 					*out_size = (duk_size_t) h_bufobj->length;
16342 				}
16343 				return (void *) (p + h_bufobj->offset);
16344 			}
16345 			/* if slice not fully valid, treat as error */
16346 		}
16347 	}
16348 
16349  fail:
16350 	if (throw_flag) {
16351 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, index, "buffer", DUK_STR_NOT_BUFFER);
16352 	}
16353 	return NULL;
16354 }
16355 
duk_get_buffer_data(duk_context * ctx,duk_idx_t index,duk_size_t * out_size)16356 DUK_EXTERNAL void *duk_get_buffer_data(duk_context *ctx, duk_idx_t index, duk_size_t *out_size) {
16357 	return duk__get_buffer_data_helper(ctx, index, out_size, 0 /*throw_flag*/);
16358 }
16359 
duk_require_buffer_data(duk_context * ctx,duk_idx_t index,duk_size_t * out_size)16360 DUK_EXTERNAL void *duk_require_buffer_data(duk_context *ctx, duk_idx_t index, duk_size_t *out_size) {
16361 	return duk__get_buffer_data_helper(ctx, index, out_size, 1 /*throw_flag*/);
16362 }
16363 
16364 /* Raw helper for getting a value from the stack, checking its tag.
16365  * The tag cannot be a number because numbers don't have an internal
16366  * tag in the packed representation.
16367  */
16368 
duk__get_tagged_heaphdr_raw(duk_context * ctx,duk_idx_t index,duk_uint_t tag)16369 DUK_LOCAL duk_heaphdr *duk__get_tagged_heaphdr_raw(duk_context *ctx, duk_idx_t index, duk_uint_t tag) {
16370 	duk_tval *tv;
16371 
16372 	DUK_ASSERT_CTX_VALID(ctx);
16373 
16374 	tv = duk_get_tval(ctx, index);
16375 	if (tv && (DUK_TVAL_GET_TAG(tv) == tag)) {
16376 		duk_heaphdr *ret;
16377 		ret = DUK_TVAL_GET_HEAPHDR(tv);
16378 		DUK_ASSERT(ret != NULL);  /* tagged null pointers should never occur */
16379 		return ret;
16380 	}
16381 
16382 	return (duk_heaphdr *) NULL;
16383 }
16384 
duk_get_hstring(duk_context * ctx,duk_idx_t index)16385 DUK_INTERNAL duk_hstring *duk_get_hstring(duk_context *ctx, duk_idx_t index) {
16386 	return (duk_hstring *) duk__get_tagged_heaphdr_raw(ctx, index, DUK_TAG_STRING);
16387 }
16388 
duk_require_hstring(duk_context * ctx,duk_idx_t index)16389 DUK_INTERNAL duk_hstring *duk_require_hstring(duk_context *ctx, duk_idx_t index) {
16390 	duk_heaphdr *h;
16391 	h = duk__get_tagged_heaphdr_raw(ctx, index, DUK_TAG_STRING);
16392 	if (h == NULL) {
16393 		DUK_ERROR_REQUIRE_TYPE_INDEX(ctx, index, "string", DUK_STR_NOT_STRING);
16394 	}
16395 	return (duk_hstring *) h;
16396 }
16397 
duk_get_hobject(duk_context * ctx,duk_idx_t index)16398 DUK_INTERNAL duk_hobject *duk_get_hobject(duk_context *ctx, duk_idx_t index) {
16399 	return (duk_hobject *) duk__get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT);
16400 }
16401 
duk_require_hobject(duk_context * ctx,duk_idx_t index)16402 DUK_INTERNAL duk_hobject *duk_require_hobject(duk_context *ctx, duk_idx_t index) {
16403 	duk_heaphdr *h;
16404 	h = duk__get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT);
16405 	if (h == NULL) {
16406 		DUK_ERROR_REQUIRE_TYPE_INDEX(ctx, index, "object", DUK_STR_NOT_OBJECT);
16407 	}
16408 	return (duk_hobject *) h;
16409 }
16410 
duk_get_hbuffer(duk_context * ctx,duk_idx_t index)16411 DUK_INTERNAL duk_hbuffer *duk_get_hbuffer(duk_context *ctx, duk_idx_t index) {
16412 	return (duk_hbuffer *) duk__get_tagged_heaphdr_raw(ctx, index, DUK_TAG_BUFFER);
16413 }
16414 
duk_require_hbuffer(duk_context * ctx,duk_idx_t index)16415 DUK_INTERNAL duk_hbuffer *duk_require_hbuffer(duk_context *ctx, duk_idx_t index) {
16416 	duk_heaphdr *h;
16417 	h = duk__get_tagged_heaphdr_raw(ctx, index, DUK_TAG_BUFFER);
16418 	if (h == NULL) {
16419 		DUK_ERROR_REQUIRE_TYPE_INDEX(ctx, index, "buffer", DUK_STR_NOT_BUFFER);
16420 	}
16421 	return (duk_hbuffer *) h;
16422 }
16423 
duk_get_hthread(duk_context * ctx,duk_idx_t index)16424 DUK_INTERNAL duk_hthread *duk_get_hthread(duk_context *ctx, duk_idx_t index) {
16425 	duk_hobject *h = (duk_hobject *) duk__get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT);
16426 	if (h != NULL && !DUK_HOBJECT_IS_THREAD(h)) {
16427 		h = NULL;
16428 	}
16429 	return (duk_hthread *) h;
16430 }
16431 
duk_require_hthread(duk_context * ctx,duk_idx_t index)16432 DUK_INTERNAL duk_hthread *duk_require_hthread(duk_context *ctx, duk_idx_t index) {
16433 	duk_hthread *thr = (duk_hthread *) ctx;
16434 	duk_hobject *h = (duk_hobject *) duk__get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT);
16435 	if (!(h != NULL && DUK_HOBJECT_IS_THREAD(h))) {
16436 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, index, "thread", DUK_STR_NOT_THREAD);
16437 	}
16438 	return (duk_hthread *) h;
16439 }
16440 
duk_get_hcompiledfunction(duk_context * ctx,duk_idx_t index)16441 DUK_INTERNAL duk_hcompiledfunction *duk_get_hcompiledfunction(duk_context *ctx, duk_idx_t index) {
16442 	duk_hobject *h = (duk_hobject *) duk__get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT);
16443 	if (h != NULL && !DUK_HOBJECT_IS_COMPILEDFUNCTION(h)) {
16444 		h = NULL;
16445 	}
16446 	return (duk_hcompiledfunction *) h;
16447 }
16448 
duk_require_hcompiledfunction(duk_context * ctx,duk_idx_t index)16449 DUK_INTERNAL duk_hcompiledfunction *duk_require_hcompiledfunction(duk_context *ctx, duk_idx_t index) {
16450 	duk_hthread *thr = (duk_hthread *) ctx;
16451 	duk_hobject *h = (duk_hobject *) duk__get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT);
16452 	if (!(h != NULL && DUK_HOBJECT_IS_COMPILEDFUNCTION(h))) {
16453 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, index, "compiledfunction", DUK_STR_NOT_COMPILEDFUNCTION);
16454 	}
16455 	return (duk_hcompiledfunction *) h;
16456 }
16457 
duk_get_hnativefunction(duk_context * ctx,duk_idx_t index)16458 DUK_INTERNAL duk_hnativefunction *duk_get_hnativefunction(duk_context *ctx, duk_idx_t index) {
16459 	duk_hobject *h = (duk_hobject *) duk__get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT);
16460 	if (h != NULL && !DUK_HOBJECT_IS_NATIVEFUNCTION(h)) {
16461 		h = NULL;
16462 	}
16463 	return (duk_hnativefunction *) h;
16464 }
16465 
duk_require_hnativefunction(duk_context * ctx,duk_idx_t index)16466 DUK_INTERNAL duk_hnativefunction *duk_require_hnativefunction(duk_context *ctx, duk_idx_t index) {
16467 	duk_hthread *thr = (duk_hthread *) ctx;
16468 	duk_hobject *h = (duk_hobject *) duk__get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT);
16469 	if (!(h != NULL && DUK_HOBJECT_IS_NATIVEFUNCTION(h))) {
16470 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, index, "nativefunction", DUK_STR_NOT_NATIVEFUNCTION);
16471 	}
16472 	return (duk_hnativefunction *) h;
16473 }
16474 
duk_get_c_function(duk_context * ctx,duk_idx_t index)16475 DUK_EXTERNAL duk_c_function duk_get_c_function(duk_context *ctx, duk_idx_t index) {
16476 	duk_tval *tv;
16477 	duk_hobject *h;
16478 	duk_hnativefunction *f;
16479 
16480 	DUK_ASSERT_CTX_VALID(ctx);
16481 
16482 	tv = duk_get_tval(ctx, index);
16483 	if (!tv) {
16484 		return NULL;
16485 	}
16486 	if (!DUK_TVAL_IS_OBJECT(tv)) {
16487 		return NULL;
16488 	}
16489 	h = DUK_TVAL_GET_OBJECT(tv);
16490 	DUK_ASSERT(h != NULL);
16491 
16492 	if (!DUK_HOBJECT_IS_NATIVEFUNCTION(h)) {
16493 		return NULL;
16494 	}
16495 	DUK_ASSERT(DUK_HOBJECT_HAS_NATIVEFUNCTION(h));
16496 	f = (duk_hnativefunction *) h;
16497 
16498 	return f->func;
16499 }
16500 
duk_require_c_function(duk_context * ctx,duk_idx_t index)16501 DUK_EXTERNAL duk_c_function duk_require_c_function(duk_context *ctx, duk_idx_t index) {
16502 	duk_hthread *thr = (duk_hthread *) ctx;
16503 	duk_c_function ret;
16504 
16505 	DUK_ASSERT_CTX_VALID(ctx);
16506 
16507 	ret = duk_get_c_function(ctx, index);
16508 	if (!ret) {
16509 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, index, "nativefunction", DUK_STR_NOT_NATIVEFUNCTION);
16510 	}
16511 	return ret;
16512 }
16513 
duk_require_function(duk_context * ctx,duk_idx_t index)16514 DUK_EXTERNAL void duk_require_function(duk_context *ctx, duk_idx_t index) {
16515 	if (!duk_is_function(ctx, index)) {
16516 		DUK_ERROR_REQUIRE_TYPE_INDEX((duk_hthread *) ctx, index, "function", DUK_STR_NOT_FUNCTION);
16517 	}
16518 }
16519 
duk_get_context(duk_context * ctx,duk_idx_t index)16520 DUK_EXTERNAL duk_context *duk_get_context(duk_context *ctx, duk_idx_t index) {
16521 	DUK_ASSERT_CTX_VALID(ctx);
16522 
16523 	return (duk_context *) duk_get_hthread(ctx, index);
16524 }
16525 
duk_require_context(duk_context * ctx,duk_idx_t index)16526 DUK_EXTERNAL duk_context *duk_require_context(duk_context *ctx, duk_idx_t index) {
16527 	DUK_ASSERT_CTX_VALID(ctx);
16528 
16529 	return (duk_context *) duk_require_hthread(ctx, index);
16530 }
16531 
duk_get_heapptr(duk_context * ctx,duk_idx_t index)16532 DUK_EXTERNAL void *duk_get_heapptr(duk_context *ctx, duk_idx_t index) {
16533 	duk_tval *tv;
16534 	void *ret;
16535 
16536 	DUK_ASSERT_CTX_VALID(ctx);
16537 
16538 	tv = duk_get_tval(ctx, index);
16539 	if (tv && DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
16540 		ret = (void *) DUK_TVAL_GET_HEAPHDR(tv);
16541 		DUK_ASSERT(ret != NULL);
16542 		return ret;
16543 	}
16544 
16545 	return (void *) NULL;
16546 }
16547 
duk_require_heapptr(duk_context * ctx,duk_idx_t index)16548 DUK_EXTERNAL void *duk_require_heapptr(duk_context *ctx, duk_idx_t index) {
16549 	duk_hthread *thr = (duk_hthread *) ctx;
16550 	duk_tval *tv;
16551 	void *ret;
16552 
16553 	DUK_ASSERT_CTX_VALID(ctx);
16554 
16555 	tv = duk_require_tval(ctx, index);
16556 	DUK_ASSERT(tv != NULL);
16557 	if (DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
16558 		ret = (void *) DUK_TVAL_GET_HEAPHDR(tv);
16559 		DUK_ASSERT(ret != NULL);
16560 		return ret;
16561 	}
16562 
16563 	DUK_ERROR_REQUIRE_TYPE_INDEX(thr, index, "heapobject", DUK_STR_UNEXPECTED_TYPE);
16564 	return (void *) NULL;  /* not reachable */
16565 }
16566 
16567 #if 0
16568 /* This would be pointless: we'd return NULL for both lightfuncs and
16569  * unexpected types.
16570  */
16571 DUK_INTERNAL duk_hobject *duk_get_hobject_or_lfunc(duk_context *ctx, duk_idx_t index) {
16572 }
16573 #endif
16574 
16575 /* Useful for internal call sites where we either expect an object (function)
16576  * or a lightfunc.  Accepts an object (returned as is) or a lightfunc (coerced
16577  * to an object).  Return value is NULL if value is neither an object nor a
16578  * lightfunc.
16579  */
duk_get_hobject_or_lfunc_coerce(duk_context * ctx,duk_idx_t index)16580 DUK_INTERNAL duk_hobject *duk_get_hobject_or_lfunc_coerce(duk_context *ctx, duk_idx_t index) {
16581 	duk_tval *tv;
16582 
16583 	DUK_ASSERT_CTX_VALID(ctx);
16584 
16585 	tv = duk_require_tval(ctx, index);
16586 	DUK_ASSERT(tv != NULL);
16587 	if (DUK_TVAL_IS_OBJECT(tv)) {
16588 		return DUK_TVAL_GET_OBJECT(tv);
16589 	} else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
16590 		duk_to_object(ctx, index);
16591 		return duk_require_hobject(ctx, index);
16592 	}
16593 
16594 	return NULL;
16595 }
16596 
16597 /* Useful for internal call sites where we either expect an object (function)
16598  * or a lightfunc.  Returns NULL for a lightfunc.
16599  */
duk_require_hobject_or_lfunc(duk_context * ctx,duk_idx_t index)16600 DUK_INTERNAL duk_hobject *duk_require_hobject_or_lfunc(duk_context *ctx, duk_idx_t index) {
16601 	duk_hthread *thr = (duk_hthread *) ctx;
16602 	duk_tval *tv;
16603 
16604 	DUK_ASSERT_CTX_VALID(ctx);
16605 
16606 	tv = duk_require_tval(ctx, index);
16607 	DUK_ASSERT(tv != NULL);
16608 	if (DUK_TVAL_IS_OBJECT(tv)) {
16609 		return DUK_TVAL_GET_OBJECT(tv);
16610 	} else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
16611 		return NULL;
16612 	}
16613 	DUK_ERROR_REQUIRE_TYPE_INDEX(thr, index, "object", DUK_STR_NOT_OBJECT);
16614 	return NULL;  /* not reachable */
16615 }
16616 
16617 /* Useful for internal call sites where we either expect an object (function)
16618  * or a lightfunc.  Accepts an object (returned as is) or a lightfunc (coerced
16619  * to an object).  Return value is never NULL.
16620  */
duk_require_hobject_or_lfunc_coerce(duk_context * ctx,duk_idx_t index)16621 DUK_INTERNAL duk_hobject *duk_require_hobject_or_lfunc_coerce(duk_context *ctx, duk_idx_t index) {
16622 	duk_hthread *thr = (duk_hthread *) ctx;
16623 	duk_tval *tv;
16624 
16625 	DUK_ASSERT_CTX_VALID(ctx);
16626 
16627 	tv = duk_require_tval(ctx, index);
16628 	if (DUK_TVAL_IS_OBJECT(tv)) {
16629 		return DUK_TVAL_GET_OBJECT(tv);
16630 	} else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
16631 		duk_to_object(ctx, index);
16632 		return duk_require_hobject(ctx, index);
16633 	}
16634 	DUK_ERROR_REQUIRE_TYPE_INDEX(thr, index, "object", DUK_STR_NOT_OBJECT);
16635 	return NULL;  /* not reachable */
16636 }
16637 
duk_get_hobject_with_class(duk_context * ctx,duk_idx_t index,duk_small_uint_t classnum)16638 DUK_INTERNAL duk_hobject *duk_get_hobject_with_class(duk_context *ctx, duk_idx_t index, duk_small_uint_t classnum) {
16639 	duk_hobject *h;
16640 
16641 	DUK_ASSERT_CTX_VALID(ctx);
16642 	DUK_ASSERT_DISABLE(classnum >= 0);  /* unsigned */
16643 	DUK_ASSERT(classnum <= DUK_HOBJECT_CLASS_MAX);
16644 
16645 	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT);
16646 	if (h != NULL && DUK_HOBJECT_GET_CLASS_NUMBER(h) != classnum) {
16647 		h = NULL;
16648 	}
16649 	return h;
16650 }
16651 
duk_require_hobject_with_class(duk_context * ctx,duk_idx_t index,duk_small_uint_t classnum)16652 DUK_INTERNAL duk_hobject *duk_require_hobject_with_class(duk_context *ctx, duk_idx_t index, duk_small_uint_t classnum) {
16653 	duk_hthread *thr;
16654 	duk_hobject *h;
16655 
16656 	DUK_ASSERT_CTX_VALID(ctx);
16657 	DUK_ASSERT_DISABLE(classnum >= 0);  /* unsigned */
16658 	DUK_ASSERT(classnum <= DUK_HOBJECT_CLASS_MAX);
16659 	thr = (duk_hthread *) ctx;
16660 
16661 	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(ctx, index, DUK_TAG_OBJECT);
16662 	if (!(h != NULL && DUK_HOBJECT_GET_CLASS_NUMBER(h) == classnum)) {
16663 		duk_hstring *h_class;
16664 		h_class = DUK_HTHREAD_GET_STRING(thr, DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(classnum));
16665 		DUK_UNREF(h_class);
16666 
16667 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, index, (const char *) DUK_HSTRING_GET_DATA(h_class), DUK_STR_UNEXPECTED_TYPE);
16668 	}
16669 	return h;
16670 }
16671 
duk_get_length(duk_context * ctx,duk_idx_t index)16672 DUK_EXTERNAL duk_size_t duk_get_length(duk_context *ctx, duk_idx_t index) {
16673 	duk_tval *tv;
16674 
16675 	DUK_ASSERT_CTX_VALID(ctx);
16676 
16677 	tv = duk_get_tval(ctx, index);
16678 	if (!tv) {
16679 		return 0;
16680 	}
16681 
16682 	switch (DUK_TVAL_GET_TAG(tv)) {
16683 	case DUK_TAG_UNDEFINED:
16684 	case DUK_TAG_NULL:
16685 	case DUK_TAG_BOOLEAN:
16686 	case DUK_TAG_POINTER:
16687 		return 0;
16688 	case DUK_TAG_STRING: {
16689 		duk_hstring *h = DUK_TVAL_GET_STRING(tv);
16690 		DUK_ASSERT(h != NULL);
16691 		return (duk_size_t) DUK_HSTRING_GET_CHARLEN(h);
16692 	}
16693 	case DUK_TAG_OBJECT: {
16694 		duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
16695 		DUK_ASSERT(h != NULL);
16696 		return (duk_size_t) duk_hobject_get_length((duk_hthread *) ctx, h);
16697 	}
16698 	case DUK_TAG_BUFFER: {
16699 		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
16700 		DUK_ASSERT(h != NULL);
16701 		return (duk_size_t) DUK_HBUFFER_GET_SIZE(h);
16702 	}
16703 	case DUK_TAG_LIGHTFUNC: {
16704 		duk_small_uint_t lf_flags;
16705 		lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv);
16706 		return (duk_size_t) DUK_LFUNC_FLAGS_GET_LENGTH(lf_flags);
16707 	}
16708 #if defined(DUK_USE_FASTINT)
16709 	case DUK_TAG_FASTINT:
16710 #endif
16711 	default:
16712 		/* number */
16713 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
16714 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
16715 		return 0;
16716 	}
16717 
16718 	DUK_UNREACHABLE();
16719 }
16720 
duk_set_length(duk_context * ctx,duk_idx_t index,duk_size_t length)16721 DUK_INTERNAL void duk_set_length(duk_context *ctx, duk_idx_t index, duk_size_t length) {
16722 	duk_hthread *thr = (duk_hthread *) ctx;
16723 	duk_hobject *h;
16724 
16725 	DUK_ASSERT_CTX_VALID(ctx);
16726 
16727 	h = duk_get_hobject(ctx, index);
16728 	if (!h) {
16729 		return;
16730 	}
16731 
16732 	duk_hobject_set_length(thr, h, (duk_uint32_t) length);  /* XXX: typing */
16733 }
16734 
16735 /*
16736  *  Conversions and coercions
16737  *
16738  *  The conversion/coercions are in-place operations on the value stack.
16739  *  Some operations are implemented here directly, while others call a
16740  *  helper in duk_js_ops.c after validating arguments.
16741  */
16742 
16743 /* E5 Section 8.12.8 */
16744 
duk__defaultvalue_coerce_attempt(duk_context * ctx,duk_idx_t index,duk_small_int_t func_stridx)16745 DUK_LOCAL duk_bool_t duk__defaultvalue_coerce_attempt(duk_context *ctx, duk_idx_t index, duk_small_int_t func_stridx) {
16746 	if (duk_get_prop_stridx(ctx, index, func_stridx)) {
16747 		/* [ ... func ] */
16748 		if (duk_is_callable(ctx, -1)) {
16749 			duk_dup(ctx, index);         /* -> [ ... func this ] */
16750 			duk_call_method(ctx, 0);     /* -> [ ... retval ] */
16751 			if (duk_is_primitive(ctx, -1)) {
16752 				duk_replace(ctx, index);
16753 				return 1;
16754 			}
16755 			/* [ ... retval ]; popped below */
16756 		}
16757 	}
16758 	duk_pop(ctx);  /* [ ... func/retval ] -> [ ... ] */
16759 	return 0;
16760 }
16761 
duk_to_defaultvalue(duk_context * ctx,duk_idx_t index,duk_int_t hint)16762 DUK_EXTERNAL void duk_to_defaultvalue(duk_context *ctx, duk_idx_t index, duk_int_t hint) {
16763 	duk_hthread *thr = (duk_hthread *) ctx;
16764 	duk_hobject *obj;
16765 	/* inline initializer for coercers[] is not allowed by old compilers like BCC */
16766 	duk_small_int_t coercers[2];
16767 
16768 	DUK_ASSERT_CTX_VALID(ctx);
16769 	DUK_ASSERT(thr != NULL);
16770 
16771 	coercers[0] = DUK_STRIDX_VALUE_OF;
16772 	coercers[1] = DUK_STRIDX_TO_STRING;
16773 
16774 	index = duk_require_normalize_index(ctx, index);
16775 	obj = duk_require_hobject_or_lfunc(ctx, index);
16776 
16777 	if (hint == DUK_HINT_NONE) {
16778 		if (obj != NULL && DUK_HOBJECT_GET_CLASS_NUMBER(obj) == DUK_HOBJECT_CLASS_DATE) {
16779 			hint = DUK_HINT_STRING;
16780 		} else {
16781 			hint = DUK_HINT_NUMBER;
16782 		}
16783 	}
16784 
16785 	if (hint == DUK_HINT_STRING) {
16786 		coercers[0] = DUK_STRIDX_TO_STRING;
16787 		coercers[1] = DUK_STRIDX_VALUE_OF;
16788 	}
16789 
16790 	if (duk__defaultvalue_coerce_attempt(ctx, index, coercers[0])) {
16791 		return;
16792 	}
16793 
16794 	if (duk__defaultvalue_coerce_attempt(ctx, index, coercers[1])) {
16795 		return;
16796 	}
16797 
16798 	DUK_ERROR_TYPE(thr, DUK_STR_DEFAULTVALUE_COERCE_FAILED);
16799 }
16800 
duk_to_undefined(duk_context * ctx,duk_idx_t index)16801 DUK_EXTERNAL void duk_to_undefined(duk_context *ctx, duk_idx_t index) {
16802 	duk_hthread *thr = (duk_hthread *) ctx;
16803 	duk_tval *tv;
16804 
16805 	DUK_ASSERT_CTX_VALID(ctx);
16806 	DUK_UNREF(thr);
16807 
16808 	tv = duk_require_tval(ctx, index);
16809 	DUK_ASSERT(tv != NULL);
16810 	DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv);  /* side effects */
16811 }
16812 
duk_to_null(duk_context * ctx,duk_idx_t index)16813 DUK_EXTERNAL void duk_to_null(duk_context *ctx, duk_idx_t index) {
16814 	duk_hthread *thr = (duk_hthread *) ctx;
16815 	duk_tval *tv;
16816 
16817 	DUK_ASSERT_CTX_VALID(ctx);
16818 	DUK_UNREF(thr);
16819 
16820 	tv = duk_require_tval(ctx, index);
16821 	DUK_ASSERT(tv != NULL);
16822 	DUK_TVAL_SET_NULL_UPDREF(thr, tv);  /* side effects */
16823 }
16824 
16825 /* E5 Section 9.1 */
duk_to_primitive(duk_context * ctx,duk_idx_t index,duk_int_t hint)16826 DUK_EXTERNAL void duk_to_primitive(duk_context *ctx, duk_idx_t index, duk_int_t hint) {
16827 	DUK_ASSERT_CTX_VALID(ctx);
16828 	DUK_ASSERT(hint == DUK_HINT_NONE || hint == DUK_HINT_NUMBER || hint == DUK_HINT_STRING);
16829 
16830 	index = duk_require_normalize_index(ctx, index);
16831 
16832 	if (!duk_check_type_mask(ctx, index, DUK_TYPE_MASK_OBJECT |
16833 	                                     DUK_TYPE_MASK_LIGHTFUNC)) {
16834 		/* everything except object stay as is */
16835 		return;
16836 	}
16837 	duk_to_defaultvalue(ctx, index, hint);
16838 }
16839 
16840 /* E5 Section 9.2 */
duk_to_boolean(duk_context * ctx,duk_idx_t index)16841 DUK_EXTERNAL duk_bool_t duk_to_boolean(duk_context *ctx, duk_idx_t index) {
16842 	duk_hthread *thr = (duk_hthread *) ctx;
16843 	duk_tval *tv;
16844 	duk_bool_t val;
16845 
16846 	DUK_ASSERT_CTX_VALID(ctx);
16847 	DUK_UNREF(thr);
16848 
16849 	index = duk_require_normalize_index(ctx, index);
16850 
16851 	tv = duk_require_tval(ctx, index);
16852 	DUK_ASSERT(tv != NULL);
16853 
16854 	val = duk_js_toboolean(tv);
16855 	DUK_ASSERT(val == 0 || val == 1);
16856 
16857 	/* Note: no need to re-lookup tv, conversion is side effect free */
16858 	DUK_ASSERT(tv != NULL);
16859 	DUK_TVAL_SET_BOOLEAN_UPDREF(thr, tv, val);  /* side effects */
16860 	return val;
16861 }
16862 
duk_to_number(duk_context * ctx,duk_idx_t index)16863 DUK_EXTERNAL duk_double_t duk_to_number(duk_context *ctx, duk_idx_t index) {
16864 	duk_hthread *thr = (duk_hthread *) ctx;
16865 	duk_tval *tv;
16866 	duk_double_t d;
16867 
16868 	DUK_ASSERT_CTX_VALID(ctx);
16869 
16870 	tv = duk_require_tval(ctx, index);
16871 	DUK_ASSERT(tv != NULL);
16872 	/* XXX: fastint? */
16873 	d = duk_js_tonumber(thr, tv);
16874 
16875 	/* Note: need to re-lookup because ToNumber() may have side effects */
16876 	tv = duk_require_tval(ctx, index);
16877 	DUK_TVAL_SET_NUMBER_UPDREF(thr, tv, d);  /* side effects */
16878 	return d;
16879 }
16880 
16881 /* XXX: combine all the integer conversions: they share everything
16882  * but the helper function for coercion.
16883  */
16884 
16885 typedef duk_double_t (*duk__toint_coercer)(duk_hthread *thr, duk_tval *tv);
16886 
duk__to_int_uint_helper(duk_context * ctx,duk_idx_t index,duk__toint_coercer coerce_func)16887 DUK_LOCAL duk_double_t duk__to_int_uint_helper(duk_context *ctx, duk_idx_t index, duk__toint_coercer coerce_func) {
16888 	duk_hthread *thr = (duk_hthread *) ctx;
16889 	duk_tval *tv;
16890 	duk_double_t d;
16891 
16892 	DUK_ASSERT_CTX_VALID(ctx);
16893 
16894 	tv = duk_require_tval(ctx, index);
16895 	DUK_ASSERT(tv != NULL);
16896 	d = coerce_func(thr, tv);
16897 
16898 	/* XXX: fastint? */
16899 
16900 	/* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */
16901 	tv = duk_require_tval(ctx, index);
16902 	DUK_TVAL_SET_NUMBER_UPDREF(thr, tv, d);  /* side effects */
16903 	return d;
16904 }
16905 
duk_to_int(duk_context * ctx,duk_idx_t index)16906 DUK_EXTERNAL duk_int_t duk_to_int(duk_context *ctx, duk_idx_t index) {
16907 	/* Value coercion (in stack): ToInteger(), E5 Section 9.4
16908 	 * API return value coercion: custom
16909 	 */
16910 	DUK_ASSERT_CTX_VALID(ctx);
16911 	(void) duk__to_int_uint_helper(ctx, index, duk_js_tointeger);
16912 	return (duk_int_t) duk__api_coerce_d2i(ctx, index, 0 /*require*/);
16913 }
16914 
duk_to_uint(duk_context * ctx,duk_idx_t index)16915 DUK_EXTERNAL duk_uint_t duk_to_uint(duk_context *ctx, duk_idx_t index) {
16916 	/* Value coercion (in stack): ToInteger(), E5 Section 9.4
16917 	 * API return value coercion: custom
16918 	 */
16919 	DUK_ASSERT_CTX_VALID(ctx);
16920 	(void) duk__to_int_uint_helper(ctx, index, duk_js_tointeger);
16921 	return (duk_uint_t) duk__api_coerce_d2ui(ctx, index, 0 /*require*/);
16922 }
16923 
duk_to_int32(duk_context * ctx,duk_idx_t index)16924 DUK_EXTERNAL duk_int32_t duk_to_int32(duk_context *ctx, duk_idx_t index) {
16925 	duk_hthread *thr = (duk_hthread *) ctx;
16926 	duk_tval *tv;
16927 	duk_int32_t ret;
16928 
16929 	DUK_ASSERT_CTX_VALID(ctx);
16930 
16931 	tv = duk_require_tval(ctx, index);
16932 	DUK_ASSERT(tv != NULL);
16933 	ret = duk_js_toint32(thr, tv);
16934 
16935 	/* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */
16936 	tv = duk_require_tval(ctx, index);
16937 	DUK_TVAL_SET_FASTINT_I32_UPDREF(thr, tv, ret);  /* side effects */
16938 	return ret;
16939 }
16940 
duk_to_uint32(duk_context * ctx,duk_idx_t index)16941 DUK_EXTERNAL duk_uint32_t duk_to_uint32(duk_context *ctx, duk_idx_t index) {
16942 	duk_hthread *thr = (duk_hthread *) ctx;
16943 	duk_tval *tv;
16944 	duk_uint32_t ret;
16945 
16946 	DUK_ASSERT_CTX_VALID(ctx);
16947 
16948 	tv = duk_require_tval(ctx, index);
16949 	DUK_ASSERT(tv != NULL);
16950 	ret = duk_js_touint32(thr, tv);
16951 
16952 	/* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */
16953 	tv = duk_require_tval(ctx, index);
16954 	DUK_TVAL_SET_FASTINT_U32_UPDREF(thr, tv, ret);  /* side effects */
16955 	return ret;
16956 }
16957 
duk_to_uint16(duk_context * ctx,duk_idx_t index)16958 DUK_EXTERNAL duk_uint16_t duk_to_uint16(duk_context *ctx, duk_idx_t index) {
16959 	duk_hthread *thr = (duk_hthread *) ctx;
16960 	duk_tval *tv;
16961 	duk_uint16_t ret;
16962 
16963 	DUK_ASSERT_CTX_VALID(ctx);
16964 
16965 	tv = duk_require_tval(ctx, index);
16966 	DUK_ASSERT(tv != NULL);
16967 	ret = duk_js_touint16(thr, tv);
16968 
16969 	/* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */
16970 	tv = duk_require_tval(ctx, index);
16971 	DUK_TVAL_SET_FASTINT_U32_UPDREF(thr, tv, ret);  /* side effects */
16972 	return ret;
16973 }
16974 
16975 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
16976 /* Special coercion for Uint8ClampedArray. */
duk_to_uint8clamped(duk_context * ctx,duk_idx_t index)16977 DUK_INTERNAL duk_uint8_t duk_to_uint8clamped(duk_context *ctx, duk_idx_t index) {
16978 	duk_double_t d;
16979 	duk_double_t t;
16980 	duk_uint8_t ret;
16981 
16982 	/* XXX: Simplify this algorithm, should be possible to come up with
16983 	 * a shorter and faster algorithm by inspecting IEEE representation
16984 	 * directly.
16985 	 */
16986 
16987 	d = duk_to_number(ctx, index);
16988 	if (d <= 0.0) {
16989 		return 0;
16990 	} else if (d >= 255) {
16991 		return 255;
16992 	} else if (DUK_ISNAN(d)) {
16993 		/* Avoid NaN-to-integer coercion as it is compiler specific. */
16994 		return 0;
16995 	}
16996 
16997 	t = d - DUK_FLOOR(d);
16998 	if (t == 0.5) {
16999 		/* Exact halfway, round to even. */
17000 		ret = (duk_uint8_t) d;
17001 		ret = (ret + 1) & 0xfe;  /* Example: d=3.5, t=0.5 -> ret = (3 + 1) & 0xfe = 4 & 0xfe = 4
17002 		                          * Example: d=4.5, t=0.5 -> ret = (4 + 1) & 0xfe = 5 & 0xfe = 4
17003 		                          */
17004 	} else {
17005 		/* Not halfway, round to nearest. */
17006 		ret = (duk_uint8_t) (d + 0.5);
17007 	}
17008 	return ret;
17009 }
17010 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
17011 
duk_to_lstring(duk_context * ctx,duk_idx_t index,duk_size_t * out_len)17012 DUK_EXTERNAL const char *duk_to_lstring(duk_context *ctx, duk_idx_t index, duk_size_t *out_len) {
17013 	DUK_ASSERT_CTX_VALID(ctx);
17014 
17015 	(void) duk_to_string(ctx, index);
17016 	return duk_require_lstring(ctx, index, out_len);
17017 }
17018 
duk__safe_to_string_raw(duk_context * ctx)17019 DUK_LOCAL duk_ret_t duk__safe_to_string_raw(duk_context *ctx) {
17020 	DUK_ASSERT_CTX_VALID(ctx);
17021 
17022 	duk_to_string(ctx, -1);
17023 	return 1;
17024 }
17025 
duk_safe_to_lstring(duk_context * ctx,duk_idx_t index,duk_size_t * out_len)17026 DUK_EXTERNAL const char *duk_safe_to_lstring(duk_context *ctx, duk_idx_t index, duk_size_t *out_len) {
17027 	DUK_ASSERT_CTX_VALID(ctx);
17028 
17029 	index = duk_require_normalize_index(ctx, index);
17030 
17031 	/* We intentionally ignore the duk_safe_call() return value and only
17032 	 * check the output type.  This way we don't also need to check that
17033 	 * the returned value is indeed a string in the success case.
17034 	 */
17035 
17036 	duk_dup(ctx, index);
17037 	(void) duk_safe_call(ctx, duk__safe_to_string_raw, 1 /*nargs*/, 1 /*nrets*/);
17038 	if (!duk_is_string(ctx, -1)) {
17039 		/* Error: try coercing error to string once. */
17040 		(void) duk_safe_call(ctx, duk__safe_to_string_raw, 1 /*nargs*/, 1 /*nrets*/);
17041 		if (!duk_is_string(ctx, -1)) {
17042 			/* Double error */
17043 			duk_pop(ctx);
17044 			duk_push_hstring_stridx(ctx, DUK_STRIDX_UC_ERROR);
17045 		} else {
17046 			;
17047 		}
17048 	} else {
17049 		;
17050 	}
17051 	DUK_ASSERT(duk_is_string(ctx, -1));
17052 	DUK_ASSERT(duk_get_string(ctx, -1) != NULL);
17053 
17054 	duk_replace(ctx, index);
17055 	return duk_get_lstring(ctx, index, out_len);
17056 }
17057 
17058 #if defined(DUK_USE_DEBUGGER_SUPPORT)  /* only needed by debugger for now */
duk_safe_to_hstring(duk_context * ctx,duk_idx_t index)17059 DUK_INTERNAL duk_hstring *duk_safe_to_hstring(duk_context *ctx, duk_idx_t index) {
17060 	(void) duk_safe_to_string(ctx, index);
17061 	DUK_ASSERT(duk_is_string(ctx, index));
17062 	DUK_ASSERT(duk_get_hstring(ctx, index) != NULL);
17063 	return duk_get_hstring(ctx, index);
17064 }
17065 #endif
17066 
17067 /* Coerce top into Object.prototype.toString() output. */
duk_to_object_class_string_top(duk_context * ctx)17068 DUK_INTERNAL void duk_to_object_class_string_top(duk_context *ctx) {
17069 	duk_hthread *thr;
17070 	duk_uint_t typemask;
17071 	duk_hstring *h_strclass;
17072 
17073 	DUK_ASSERT_CTX_VALID(ctx);
17074 	thr = (duk_hthread *) ctx;
17075 	DUK_UNREF(thr);
17076 
17077 	typemask = duk_get_type_mask(ctx, -1);
17078 	if (typemask & DUK_TYPE_MASK_UNDEFINED) {
17079 		h_strclass = DUK_HTHREAD_STRING_UC_UNDEFINED(thr);
17080 	} else if (typemask & DUK_TYPE_MASK_NULL) {
17081 		h_strclass = DUK_HTHREAD_STRING_UC_NULL(thr);
17082 	} else {
17083 		duk_hobject *h_obj;
17084 
17085 		duk_to_object(ctx, -1);
17086 		h_obj = duk_get_hobject(ctx, -1);
17087 		DUK_ASSERT(h_obj != NULL);
17088 
17089 		h_strclass = DUK_HOBJECT_GET_CLASS_STRING(thr->heap, h_obj);
17090 	}
17091 	DUK_ASSERT(h_strclass != NULL);
17092 
17093 	duk_pop(ctx);
17094 	duk_push_sprintf(ctx, "[object %s]", (const char *) DUK_HSTRING_GET_DATA(h_strclass));
17095 }
17096 
17097 #if !defined(DUK_USE_PARANOID_ERRORS)
duk_push_hobject_class_string(duk_context * ctx,duk_hobject * h)17098 DUK_INTERNAL void duk_push_hobject_class_string(duk_context *ctx, duk_hobject *h) {
17099 	duk_hthread *thr;
17100 	duk_hstring *h_strclass;
17101 
17102 	DUK_ASSERT_CTX_VALID(ctx);
17103 	DUK_ASSERT(h != NULL);
17104 	thr = (duk_hthread *) ctx;
17105 	DUK_UNREF(thr);
17106 
17107 	h_strclass = DUK_HOBJECT_GET_CLASS_STRING(thr->heap, h);
17108 	DUK_ASSERT(h_strclass != NULL);
17109 	duk_push_sprintf(ctx, "[object %s]", (const char *) DUK_HSTRING_GET_DATA(h_strclass));
17110 }
17111 #endif  /* !DUK_USE_PARANOID_ERRORS */
17112 
17113 /* XXX: other variants like uint, u32 etc */
duk_to_int_clamped_raw(duk_context * ctx,duk_idx_t index,duk_int_t minval,duk_int_t maxval,duk_bool_t * out_clamped)17114 DUK_INTERNAL duk_int_t duk_to_int_clamped_raw(duk_context *ctx, duk_idx_t index, duk_int_t minval, duk_int_t maxval, duk_bool_t *out_clamped) {
17115 	duk_hthread *thr = (duk_hthread *) ctx;
17116 	duk_tval *tv;
17117 	duk_tval tv_tmp;
17118 	duk_double_t d, dmin, dmax;
17119 	duk_int_t res;
17120 	duk_bool_t clamped = 0;
17121 
17122 	DUK_ASSERT_CTX_VALID(ctx);
17123 
17124 	tv = duk_require_tval(ctx, index);
17125 	DUK_ASSERT(tv != NULL);
17126 	d = duk_js_tointeger(thr, tv);  /* E5 Section 9.4, ToInteger() */
17127 
17128 	dmin = (duk_double_t) minval;
17129 	dmax = (duk_double_t) maxval;
17130 
17131 	if (d < dmin) {
17132 		clamped = 1;
17133 		res = minval;
17134 		d = dmin;
17135 	} else if (d > dmax) {
17136 		clamped = 1;
17137 		res = maxval;
17138 		d = dmax;
17139 	} else {
17140 		res = (duk_int_t) d;
17141 	}
17142 	DUK_UNREF(d);  /* SCANBUILD: with suitable dmin/dmax limits 'd' is unused */
17143 	/* 'd' and 'res' agree here */
17144 
17145 	/* Relookup in case duk_js_tointeger() ends up e.g. coercing an object. */
17146 	tv = duk_get_tval(ctx, index);
17147 	DUK_ASSERT(tv != NULL);  /* not popped by side effect */
17148 	DUK_TVAL_SET_TVAL(&tv_tmp, tv);
17149 #if defined(DUK_USE_FASTINT)
17150 #if (DUK_INT_MAX <= 0x7fffffffL)
17151 	DUK_TVAL_SET_FASTINT_I32(tv, res);
17152 #else
17153 	/* Clamping needed if duk_int_t is 64 bits. */
17154 	if (res >= DUK_FASTINT_MIN && res <= DUK_FASTINT_MAX) {
17155 		DUK_TVAL_SET_FASTINT(tv, res);
17156 	} else {
17157 		DUK_TVAL_SET_NUMBER(tv, d);
17158 	}
17159 #endif
17160 #else
17161 	DUK_TVAL_SET_NUMBER(tv, d);  /* no need to incref */
17162 #endif
17163 	DUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */
17164 
17165 	if (out_clamped) {
17166 		*out_clamped = clamped;
17167 	} else {
17168 		/* coerced value is updated to value stack even when RangeError thrown */
17169 		if (clamped) {
17170 			DUK_ERROR_RANGE(thr, DUK_STR_NUMBER_OUTSIDE_RANGE);
17171 		}
17172 	}
17173 
17174 	return res;
17175 }
17176 
duk_to_int_clamped(duk_context * ctx,duk_idx_t index,duk_idx_t minval,duk_idx_t maxval)17177 DUK_INTERNAL duk_int_t duk_to_int_clamped(duk_context *ctx, duk_idx_t index, duk_idx_t minval, duk_idx_t maxval) {
17178 	duk_bool_t dummy;
17179 	return duk_to_int_clamped_raw(ctx, index, minval, maxval, &dummy);
17180 }
17181 
duk_to_int_check_range(duk_context * ctx,duk_idx_t index,duk_int_t minval,duk_int_t maxval)17182 DUK_INTERNAL duk_int_t duk_to_int_check_range(duk_context *ctx, duk_idx_t index, duk_int_t minval, duk_int_t maxval) {
17183 	return duk_to_int_clamped_raw(ctx, index, minval, maxval, NULL);  /* out_clamped==NULL -> RangeError if outside range */
17184 }
17185 
duk_to_string(duk_context * ctx,duk_idx_t index)17186 DUK_EXTERNAL const char *duk_to_string(duk_context *ctx, duk_idx_t index) {
17187 	duk_hthread *thr = (duk_hthread *) ctx;
17188 	duk_tval *tv;
17189 
17190 	DUK_ASSERT_CTX_VALID(ctx);
17191 	DUK_UNREF(thr);
17192 
17193 	index = duk_require_normalize_index(ctx, index);
17194 
17195 	tv = duk_require_tval(ctx, index);
17196 	DUK_ASSERT(tv != NULL);
17197 
17198 	switch (DUK_TVAL_GET_TAG(tv)) {
17199 	case DUK_TAG_UNDEFINED: {
17200 		duk_push_hstring_stridx(ctx, DUK_STRIDX_LC_UNDEFINED);
17201 		break;
17202 	}
17203 	case DUK_TAG_NULL: {
17204 		duk_push_hstring_stridx(ctx, DUK_STRIDX_LC_NULL);
17205 		break;
17206 	}
17207 	case DUK_TAG_BOOLEAN: {
17208 		if (DUK_TVAL_GET_BOOLEAN(tv)) {
17209 			duk_push_hstring_stridx(ctx, DUK_STRIDX_TRUE);
17210 		} else {
17211 			duk_push_hstring_stridx(ctx, DUK_STRIDX_FALSE);
17212 		}
17213 		break;
17214 	}
17215 	case DUK_TAG_STRING: {
17216 		/* nop */
17217 		goto skip_replace;
17218 	}
17219 	case DUK_TAG_OBJECT: {
17220 		duk_to_primitive(ctx, index, DUK_HINT_STRING);
17221 		return duk_to_string(ctx, index);  /* Note: recursive call */
17222 	}
17223 	case DUK_TAG_BUFFER: {
17224 		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
17225 
17226 		/* Note: this allows creation of internal strings. */
17227 
17228 		DUK_ASSERT(h != NULL);
17229 		duk_push_lstring(ctx,
17230 		                 (const char *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h),
17231 		                 (duk_size_t) DUK_HBUFFER_GET_SIZE(h));
17232 		break;
17233 	}
17234 	case DUK_TAG_POINTER: {
17235 		void *ptr = DUK_TVAL_GET_POINTER(tv);
17236 		if (ptr != NULL) {
17237 			duk_push_sprintf(ctx, DUK_STR_FMT_PTR, (void *) ptr);
17238 		} else {
17239 			/* Represent a null pointer as 'null' to be consistent with
17240 			 * the JX format variant.  Native '%p' format for a NULL
17241 			 * pointer may be e.g. '(nil)'.
17242 			 */
17243 			duk_push_hstring_stridx(ctx, DUK_STRIDX_LC_NULL);
17244 		}
17245 		break;
17246 	}
17247 	case DUK_TAG_LIGHTFUNC: {
17248 		/* Should match Function.prototype.toString() */
17249 		duk_push_lightfunc_tostring(ctx, tv);
17250 		break;
17251 	}
17252 #if defined(DUK_USE_FASTINT)
17253 	case DUK_TAG_FASTINT:
17254 #endif
17255 	default: {
17256 		/* number */
17257 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
17258 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
17259 		duk_push_tval(ctx, tv);
17260 		duk_numconv_stringify(ctx,
17261 		                      10 /*radix*/,
17262 		                      0 /*precision:shortest*/,
17263 		                      0 /*force_exponential*/);
17264 		break;
17265 	}
17266 	}
17267 
17268 	duk_replace(ctx, index);
17269 
17270  skip_replace:
17271 	return duk_require_string(ctx, index);
17272 }
17273 
duk_to_hstring(duk_context * ctx,duk_idx_t index)17274 DUK_INTERNAL duk_hstring *duk_to_hstring(duk_context *ctx, duk_idx_t index) {
17275 	duk_hstring *ret;
17276 	DUK_ASSERT_CTX_VALID(ctx);
17277 	duk_to_string(ctx, index);
17278 	ret = duk_get_hstring(ctx, index);
17279 	DUK_ASSERT(ret != NULL);
17280 	return ret;
17281 }
17282 
duk_to_buffer_raw(duk_context * ctx,duk_idx_t index,duk_size_t * out_size,duk_uint_t mode)17283 DUK_EXTERNAL void *duk_to_buffer_raw(duk_context *ctx, duk_idx_t index, duk_size_t *out_size, duk_uint_t mode) {
17284 	duk_hthread *thr = (duk_hthread *) ctx;
17285 	duk_hbuffer *h_buf;
17286 	const duk_uint8_t *src_data;
17287 	duk_size_t src_size;
17288 	duk_uint8_t *dst_data;
17289 
17290 	DUK_ASSERT_CTX_VALID(ctx);
17291 	DUK_UNREF(thr);
17292 
17293 	index = duk_require_normalize_index(ctx, index);
17294 
17295 	h_buf = duk_get_hbuffer(ctx, index);
17296 	if (h_buf != NULL) {
17297 		/* Buffer is kept as is, with the fixed/dynamic nature of the
17298 		 * buffer only changed if requested.  An external buffer
17299 		 * is converted into a non-external dynamic buffer in a
17300 		 * duk_to_dynamic_buffer() call.
17301 		 */
17302 		duk_uint_t tmp;
17303 		duk_uint8_t *tmp_ptr;
17304 
17305 		tmp_ptr = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_buf);
17306 		src_data = (const duk_uint8_t *) tmp_ptr;
17307 		src_size = DUK_HBUFFER_GET_SIZE(h_buf);
17308 
17309 		tmp = (DUK_HBUFFER_HAS_DYNAMIC(h_buf) ? DUK_BUF_MODE_DYNAMIC : DUK_BUF_MODE_FIXED);
17310 		if ((tmp == mode && !DUK_HBUFFER_HAS_EXTERNAL(h_buf)) ||
17311 		    mode == DUK_BUF_MODE_DONTCARE) {
17312 			/* Note: src_data may be NULL if input is a zero-size
17313 			 * dynamic buffer.
17314 			 */
17315 			dst_data = tmp_ptr;
17316 			goto skip_copy;
17317 		}
17318 	} else {
17319 		/* Non-buffer value is first ToString() coerced, then converted
17320 		 * to a buffer (fixed buffer is used unless a dynamic buffer is
17321 		 * explicitly requested).
17322 		 */
17323 
17324 		src_data = (const duk_uint8_t *) duk_to_lstring(ctx, index, &src_size);
17325 	}
17326 
17327 	dst_data = (duk_uint8_t *) duk_push_buffer(ctx, src_size, (mode == DUK_BUF_MODE_DYNAMIC) /*dynamic*/);
17328 	if (DUK_LIKELY(src_size > 0)) {
17329 		/* When src_size == 0, src_data may be NULL (if source
17330 		 * buffer is dynamic), and dst_data may be NULL (if
17331 		 * target buffer is dynamic).  Avoid zero-size memcpy()
17332 		 * with an invalid pointer.
17333 		 */
17334 		DUK_MEMCPY((void *) dst_data, (const void *) src_data, (size_t) src_size);
17335 	}
17336 	duk_replace(ctx, index);
17337  skip_copy:
17338 
17339 	if (out_size) {
17340 		*out_size = src_size;
17341 	}
17342 	return dst_data;
17343 }
17344 
duk_to_pointer(duk_context * ctx,duk_idx_t index)17345 DUK_EXTERNAL void *duk_to_pointer(duk_context *ctx, duk_idx_t index) {
17346 	duk_tval *tv;
17347 	void *res;
17348 
17349 	DUK_ASSERT_CTX_VALID(ctx);
17350 
17351 	index = duk_require_normalize_index(ctx, index);
17352 
17353 	tv = duk_require_tval(ctx, index);
17354 	DUK_ASSERT(tv != NULL);
17355 
17356 	switch (DUK_TVAL_GET_TAG(tv)) {
17357 	case DUK_TAG_UNDEFINED:
17358 	case DUK_TAG_NULL:
17359 	case DUK_TAG_BOOLEAN:
17360 		res = NULL;
17361 		break;
17362 	case DUK_TAG_POINTER:
17363 		res = DUK_TVAL_GET_POINTER(tv);
17364 		break;
17365 	case DUK_TAG_STRING:
17366 	case DUK_TAG_OBJECT:
17367 	case DUK_TAG_BUFFER:
17368 		/* Heap allocated: return heap pointer which is NOT useful
17369 		 * for the caller, except for debugging.
17370 		 */
17371 		res = (void *) DUK_TVAL_GET_HEAPHDR(tv);
17372 		break;
17373 	case DUK_TAG_LIGHTFUNC:
17374 		/* Function pointers do not always cast correctly to void *
17375 		 * (depends on memory and segmentation model for instance),
17376 		 * so they coerce to NULL.
17377 		 */
17378 		res = NULL;
17379 		break;
17380 #if defined(DUK_USE_FASTINT)
17381 	case DUK_TAG_FASTINT:
17382 #endif
17383 	default:
17384 		/* number */
17385 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
17386 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
17387 		res = NULL;
17388 		break;
17389 	}
17390 
17391 	duk_push_pointer(ctx, res);
17392 	duk_replace(ctx, index);
17393 	return res;
17394 }
17395 
duk_to_object(duk_context * ctx,duk_idx_t index)17396 DUK_EXTERNAL void duk_to_object(duk_context *ctx, duk_idx_t index) {
17397 	duk_hthread *thr = (duk_hthread *) ctx;
17398 	duk_tval *tv;
17399 	duk_uint_t flags = 0;   /* shared flags for a subset of types */
17400 	duk_small_int_t proto = 0;
17401 
17402 	DUK_ASSERT_CTX_VALID(ctx);
17403 
17404 	index = duk_require_normalize_index(ctx, index);
17405 
17406 	tv = duk_require_tval(ctx, index);
17407 	DUK_ASSERT(tv != NULL);
17408 
17409 	switch (DUK_TVAL_GET_TAG(tv)) {
17410 	case DUK_TAG_UNDEFINED:
17411 	case DUK_TAG_NULL: {
17412 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_OBJECT_COERCIBLE);
17413 		break;
17414 	}
17415 	case DUK_TAG_BOOLEAN: {
17416 		flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
17417 		        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_BOOLEAN);
17418 		proto = DUK_BIDX_BOOLEAN_PROTOTYPE;
17419 		goto create_object;
17420 	}
17421 	case DUK_TAG_STRING: {
17422 		flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
17423 		        DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ |
17424 		        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_STRING);
17425 		proto = DUK_BIDX_STRING_PROTOTYPE;
17426 		goto create_object;
17427 	}
17428 	case DUK_TAG_OBJECT: {
17429 		/* nop */
17430 		break;
17431 	}
17432 	case DUK_TAG_BUFFER: {
17433 		/* A plain buffer coerces to a Duktape.Buffer because it's the
17434 		 * object counterpart of the plain buffer value.  But it might
17435 		 * still make more sense to produce an ArrayBuffer here?
17436 		 */
17437 
17438 		duk_hbufferobject *h_bufobj;
17439 		duk_hbuffer *h_val;
17440 
17441 		h_val = DUK_TVAL_GET_BUFFER(tv);
17442 		DUK_ASSERT(h_val != NULL);
17443 
17444 		h_bufobj = duk_push_bufferobject_raw(ctx,
17445 		                                     DUK_HOBJECT_FLAG_EXTENSIBLE |
17446 		                                     DUK_HOBJECT_FLAG_BUFFEROBJECT |
17447 		                                     DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_BUFFER),
17448 		                                     DUK_BIDX_BUFFER_PROTOTYPE);
17449 		DUK_ASSERT(h_bufobj != NULL);
17450 		DUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE((duk_hobject *) h_bufobj));
17451 		DUK_ASSERT(DUK_HOBJECT_IS_BUFFEROBJECT((duk_hobject *) h_bufobj));
17452 
17453 		h_bufobj->buf = h_val;
17454 		DUK_HBUFFER_INCREF(thr, h_val);
17455 		DUK_ASSERT(h_bufobj->offset == 0);
17456 		h_bufobj->length = (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_val);
17457 		DUK_ASSERT(h_bufobj->shift == 0);
17458 		DUK_ASSERT(h_bufobj->elem_type == DUK_HBUFFEROBJECT_ELEM_UINT8);
17459 
17460 		DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj);
17461 		goto replace_value;
17462 	}
17463 	case DUK_TAG_POINTER: {
17464 		flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
17465 		        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_POINTER);
17466 		proto = DUK_BIDX_POINTER_PROTOTYPE;
17467 		goto create_object;
17468 	}
17469 	case DUK_TAG_LIGHTFUNC: {
17470 		/* Lightfunc coerces to a Function instance with concrete
17471 		 * properties.  Since 'length' is virtual for Duktape/C
17472 		 * functions, don't need to define that.
17473 		 *
17474 		 * The result is made extensible to mimic what happens to
17475 		 * strings:
17476 		 *   > Object.isExtensible(Object('foo'))
17477 		 *   true
17478 		 */
17479 		duk_small_uint_t lf_flags;
17480 		duk_idx_t nargs;
17481 		duk_small_uint_t lf_len;
17482 		duk_c_function func;
17483 		duk_hnativefunction *nf;
17484 
17485 		DUK_TVAL_GET_LIGHTFUNC(tv, func, lf_flags);
17486 
17487 		nargs = (duk_idx_t) DUK_LFUNC_FLAGS_GET_NARGS(lf_flags);
17488 		if (nargs == DUK_LFUNC_NARGS_VARARGS) {
17489 			nargs = (duk_idx_t) DUK_VARARGS;
17490 		}
17491 		flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
17492 		        DUK_HOBJECT_FLAG_CONSTRUCTABLE |
17493 		        DUK_HOBJECT_FLAG_NATIVEFUNCTION |
17494 	                DUK_HOBJECT_FLAG_NEWENV |
17495 	                DUK_HOBJECT_FLAG_STRICT |
17496 	                DUK_HOBJECT_FLAG_NOTAIL |
17497 			/* DUK_HOBJECT_FLAG_EXOTIC_DUKFUNC: omitted here intentionally */
17498 	                DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION);
17499 		(void) duk__push_c_function_raw(ctx, func, nargs, flags);
17500 
17501 		lf_len = DUK_LFUNC_FLAGS_GET_LENGTH(lf_flags);
17502 		if ((duk_idx_t) lf_len != nargs) {
17503 			/* Explicit length is only needed if it differs from 'nargs'. */
17504 			duk_push_int(ctx, (duk_int_t) lf_len);
17505 			duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_NONE);
17506 		}
17507 		duk_push_lightfunc_name(ctx, tv);
17508 		duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_NONE);
17509 
17510 		nf = duk_get_hnativefunction(ctx, -1);
17511 		DUK_ASSERT(nf != NULL);
17512 		nf->magic = (duk_int16_t) DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags);
17513 
17514 		/* Enable DUKFUNC exotic behavior once properties are set up. */
17515 		DUK_HOBJECT_SET_EXOTIC_DUKFUNC((duk_hobject *) nf);
17516 		goto replace_value;
17517 	}
17518 #if defined(DUK_USE_FASTINT)
17519 	case DUK_TAG_FASTINT:
17520 #endif
17521 	default: {
17522 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
17523 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
17524 		flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
17525 		               DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_NUMBER);
17526 		proto = DUK_BIDX_NUMBER_PROTOTYPE;
17527 		goto create_object;
17528 	}
17529 	}
17530 	return;
17531 
17532  create_object:
17533 	(void) duk_push_object_helper(ctx, flags, proto);
17534 
17535 	/* Note: Boolean prototype's internal value property is not writable,
17536 	 * but duk_xdef_prop_stridx() disregards the write protection.  Boolean
17537 	 * instances are immutable.
17538 	 *
17539 	 * String and buffer special behaviors are already enabled which is not
17540 	 * ideal, but a write to the internal value is not affected by them.
17541 	 */
17542 	duk_dup(ctx, index);
17543 	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);
17544 
17545  replace_value:
17546 	duk_replace(ctx, index);
17547 }
17548 
17549 /*
17550  *  Type checking
17551  */
17552 
duk__tag_check(duk_context * ctx,duk_idx_t index,duk_small_uint_t tag)17553 DUK_LOCAL duk_bool_t duk__tag_check(duk_context *ctx, duk_idx_t index, duk_small_uint_t tag) {
17554 	duk_tval *tv;
17555 
17556 	tv = duk_get_tval(ctx, index);
17557 	if (!tv) {
17558 		return 0;
17559 	}
17560 	return (DUK_TVAL_GET_TAG(tv) == tag);
17561 }
17562 
duk__obj_flag_any_default_false(duk_context * ctx,duk_idx_t index,duk_uint_t flag_mask)17563 DUK_LOCAL duk_bool_t duk__obj_flag_any_default_false(duk_context *ctx, duk_idx_t index, duk_uint_t flag_mask) {
17564 	duk_hobject *obj;
17565 
17566 	DUK_ASSERT_CTX_VALID(ctx);
17567 
17568 	obj = duk_get_hobject(ctx, index);
17569 	if (obj) {
17570 		return (DUK_HEAPHDR_CHECK_FLAG_BITS((duk_heaphdr *) obj, flag_mask) ? 1 : 0);
17571 	}
17572 	return 0;
17573 }
17574 
duk_get_type(duk_context * ctx,duk_idx_t index)17575 DUK_EXTERNAL duk_int_t duk_get_type(duk_context *ctx, duk_idx_t index) {
17576 	duk_tval *tv;
17577 
17578 	DUK_ASSERT_CTX_VALID(ctx);
17579 
17580 	tv = duk_get_tval(ctx, index);
17581 	if (!tv) {
17582 		return DUK_TYPE_NONE;
17583 	}
17584 	switch (DUK_TVAL_GET_TAG(tv)) {
17585 	case DUK_TAG_UNDEFINED:
17586 		return DUK_TYPE_UNDEFINED;
17587 	case DUK_TAG_NULL:
17588 		return DUK_TYPE_NULL;
17589 	case DUK_TAG_BOOLEAN:
17590 		return DUK_TYPE_BOOLEAN;
17591 	case DUK_TAG_STRING:
17592 		return DUK_TYPE_STRING;
17593 	case DUK_TAG_OBJECT:
17594 		return DUK_TYPE_OBJECT;
17595 	case DUK_TAG_BUFFER:
17596 		return DUK_TYPE_BUFFER;
17597 	case DUK_TAG_POINTER:
17598 		return DUK_TYPE_POINTER;
17599 	case DUK_TAG_LIGHTFUNC:
17600 		return DUK_TYPE_LIGHTFUNC;
17601 #if defined(DUK_USE_FASTINT)
17602 	case DUK_TAG_FASTINT:
17603 #endif
17604 	default:
17605 		/* Note: number has no explicit tag (in 8-byte representation) */
17606 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
17607 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
17608 		return DUK_TYPE_NUMBER;
17609 	}
17610 	DUK_UNREACHABLE();
17611 }
17612 
17613 #if defined(DUK_USE_VERBOSE_ERRORS) && defined(DUK_USE_PARANOID_ERRORS)
17614 DUK_LOCAL const char *duk__type_names[] = {
17615 	"none",
17616 	"undefined",
17617 	"null",
17618 	"boolean",
17619 	"number",
17620 	"string",
17621 	"object",
17622 	"buffer",
17623 	"pointer",
17624 	"lightfunc"
17625 };
17626 
duk_get_type_name(duk_context * ctx,duk_idx_t index)17627 DUK_INTERNAL const char *duk_get_type_name(duk_context *ctx, duk_idx_t index) {
17628 	duk_int_t type_tag;
17629 
17630 	type_tag = duk_get_type(ctx, index);
17631 	DUK_ASSERT(type_tag >= DUK_TYPE_MIN && type_tag <= DUK_TYPE_MAX);
17632 	DUK_ASSERT(DUK_TYPE_MIN == 0 && sizeof(duk__type_names) / sizeof(const char *) == DUK_TYPE_MAX + 1);
17633 
17634 	return duk__type_names[type_tag];
17635 }
17636 #endif
17637 
duk_check_type(duk_context * ctx,duk_idx_t index,duk_int_t type)17638 DUK_EXTERNAL duk_bool_t duk_check_type(duk_context *ctx, duk_idx_t index, duk_int_t type) {
17639 	DUK_ASSERT_CTX_VALID(ctx);
17640 
17641 	return (duk_get_type(ctx, index) == type) ? 1 : 0;
17642 }
17643 
duk_get_type_mask(duk_context * ctx,duk_idx_t index)17644 DUK_EXTERNAL duk_uint_t duk_get_type_mask(duk_context *ctx, duk_idx_t index) {
17645 	duk_tval *tv;
17646 
17647 	DUK_ASSERT_CTX_VALID(ctx);
17648 
17649 	tv = duk_get_tval(ctx, index);
17650 	if (!tv) {
17651 		return DUK_TYPE_MASK_NONE;
17652 	}
17653 	switch (DUK_TVAL_GET_TAG(tv)) {
17654 	case DUK_TAG_UNDEFINED:
17655 		return DUK_TYPE_MASK_UNDEFINED;
17656 	case DUK_TAG_NULL:
17657 		return DUK_TYPE_MASK_NULL;
17658 	case DUK_TAG_BOOLEAN:
17659 		return DUK_TYPE_MASK_BOOLEAN;
17660 	case DUK_TAG_STRING:
17661 		return DUK_TYPE_MASK_STRING;
17662 	case DUK_TAG_OBJECT:
17663 		return DUK_TYPE_MASK_OBJECT;
17664 	case DUK_TAG_BUFFER:
17665 		return DUK_TYPE_MASK_BUFFER;
17666 	case DUK_TAG_POINTER:
17667 		return DUK_TYPE_MASK_POINTER;
17668 	case DUK_TAG_LIGHTFUNC:
17669 		return DUK_TYPE_MASK_LIGHTFUNC;
17670 #if defined(DUK_USE_FASTINT)
17671 	case DUK_TAG_FASTINT:
17672 #endif
17673 	default:
17674 		/* Note: number has no explicit tag (in 8-byte representation) */
17675 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
17676 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
17677 		return DUK_TYPE_MASK_NUMBER;
17678 	}
17679 	DUK_UNREACHABLE();
17680 }
17681 
duk_check_type_mask(duk_context * ctx,duk_idx_t index,duk_uint_t mask)17682 DUK_EXTERNAL duk_bool_t duk_check_type_mask(duk_context *ctx, duk_idx_t index, duk_uint_t mask) {
17683 	duk_hthread *thr = (duk_hthread *) ctx;
17684 
17685 	DUK_ASSERT_CTX_VALID(ctx);
17686 
17687 	if (duk_get_type_mask(ctx, index) & mask) {
17688 		return 1;
17689 	}
17690 	if (mask & DUK_TYPE_MASK_THROW) {
17691 		DUK_ERROR_TYPE(thr, DUK_STR_UNEXPECTED_TYPE);
17692 		DUK_UNREACHABLE();
17693 	}
17694 	return 0;
17695 }
17696 
duk_is_undefined(duk_context * ctx,duk_idx_t index)17697 DUK_EXTERNAL duk_bool_t duk_is_undefined(duk_context *ctx, duk_idx_t index) {
17698 	DUK_ASSERT_CTX_VALID(ctx);
17699 	return duk__tag_check(ctx, index, DUK_TAG_UNDEFINED);
17700 }
17701 
duk_is_null(duk_context * ctx,duk_idx_t index)17702 DUK_EXTERNAL duk_bool_t duk_is_null(duk_context *ctx, duk_idx_t index) {
17703 	DUK_ASSERT_CTX_VALID(ctx);
17704 	return duk__tag_check(ctx, index, DUK_TAG_NULL);
17705 }
17706 
duk_is_null_or_undefined(duk_context * ctx,duk_idx_t index)17707 DUK_EXTERNAL duk_bool_t duk_is_null_or_undefined(duk_context *ctx, duk_idx_t index) {
17708 	duk_tval *tv;
17709 	duk_small_uint_t tag;
17710 
17711 	DUK_ASSERT_CTX_VALID(ctx);
17712 
17713 	tv = duk_get_tval(ctx, index);
17714 	if (!tv) {
17715 		return 0;
17716 	}
17717 	tag = DUK_TVAL_GET_TAG(tv);
17718 	return (tag == DUK_TAG_UNDEFINED) || (tag == DUK_TAG_NULL);
17719 }
17720 
duk_is_boolean(duk_context * ctx,duk_idx_t index)17721 DUK_EXTERNAL duk_bool_t duk_is_boolean(duk_context *ctx, duk_idx_t index) {
17722 	DUK_ASSERT_CTX_VALID(ctx);
17723 	return duk__tag_check(ctx, index, DUK_TAG_BOOLEAN);
17724 }
17725 
duk_is_number(duk_context * ctx,duk_idx_t index)17726 DUK_EXTERNAL duk_bool_t duk_is_number(duk_context *ctx, duk_idx_t index) {
17727 	duk_tval *tv;
17728 
17729 	DUK_ASSERT_CTX_VALID(ctx);
17730 
17731 	/*
17732 	 *  Number is special because it doesn't have a specific
17733 	 *  tag in the 8-byte representation.
17734 	 */
17735 
17736 	/* XXX: shorter version for 12-byte representation? */
17737 
17738 	tv = duk_get_tval(ctx, index);
17739 	if (!tv) {
17740 		return 0;
17741 	}
17742 	return DUK_TVAL_IS_NUMBER(tv);
17743 }
17744 
duk_is_nan(duk_context * ctx,duk_idx_t index)17745 DUK_EXTERNAL duk_bool_t duk_is_nan(duk_context *ctx, duk_idx_t index) {
17746 	/* XXX: This will now return false for non-numbers, even though they would
17747 	 * coerce to NaN (as a general rule).  In particular, duk_get_number()
17748 	 * returns a NaN for non-numbers, so should this function also return
17749 	 * true for non-numbers?
17750 	 */
17751 
17752 	duk_tval *tv;
17753 
17754 	DUK_ASSERT_CTX_VALID(ctx);
17755 
17756 	tv = duk_get_tval(ctx, index);
17757 	if (!tv || !DUK_TVAL_IS_NUMBER(tv)) {
17758 		return 0;
17759 	}
17760 	return DUK_ISNAN(DUK_TVAL_GET_NUMBER(tv));
17761 }
17762 
duk_is_string(duk_context * ctx,duk_idx_t index)17763 DUK_EXTERNAL duk_bool_t duk_is_string(duk_context *ctx, duk_idx_t index) {
17764 	DUK_ASSERT_CTX_VALID(ctx);
17765 	return duk__tag_check(ctx, index, DUK_TAG_STRING);
17766 }
17767 
duk_is_object(duk_context * ctx,duk_idx_t index)17768 DUK_EXTERNAL duk_bool_t duk_is_object(duk_context *ctx, duk_idx_t index) {
17769 	DUK_ASSERT_CTX_VALID(ctx);
17770 	return duk__tag_check(ctx, index, DUK_TAG_OBJECT);
17771 }
17772 
duk_is_buffer(duk_context * ctx,duk_idx_t index)17773 DUK_EXTERNAL duk_bool_t duk_is_buffer(duk_context *ctx, duk_idx_t index) {
17774 	DUK_ASSERT_CTX_VALID(ctx);
17775 	return duk__tag_check(ctx, index, DUK_TAG_BUFFER);
17776 }
17777 
17778 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_is_buffer_data(duk_context * ctx,duk_idx_t idx)17779 DUK_EXTERNAL duk_bool_t duk_is_buffer_data(duk_context *ctx, duk_idx_t idx) {
17780 	duk_tval *tv;
17781 
17782 	DUK_ASSERT_CTX_VALID(ctx);
17783 
17784 	tv = duk_get_tval(ctx, idx);
17785 	if (tv == NULL) {
17786 		return 0;
17787 	}
17788 	if (DUK_TVAL_IS_BUFFER(tv)) {
17789 		return 1;
17790 	} else if (DUK_TVAL_IS_OBJECT(tv)) {
17791 		duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
17792 		DUK_ASSERT(h != NULL);
17793 		if (DUK_HOBJECT_IS_BUFFEROBJECT(h)) {
17794 			return 1;
17795 		}
17796 	}
17797 	return 0;
17798 }
17799 #else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
duk_is_buffer_data(duk_context * ctx,duk_idx_t idx)17800 DUK_EXTERNAL duk_bool_t duk_is_buffer_data(duk_context *ctx, duk_idx_t idx) {
17801 	DUK_ASSERT_CTX_VALID(ctx);
17802 
17803 	return duk_is_buffer(ctx, idx);
17804 }
17805 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
17806 
duk_is_pointer(duk_context * ctx,duk_idx_t index)17807 DUK_EXTERNAL duk_bool_t duk_is_pointer(duk_context *ctx, duk_idx_t index) {
17808 	DUK_ASSERT_CTX_VALID(ctx);
17809 	return duk__tag_check(ctx, index, DUK_TAG_POINTER);
17810 }
17811 
duk_is_lightfunc(duk_context * ctx,duk_idx_t index)17812 DUK_EXTERNAL duk_bool_t duk_is_lightfunc(duk_context *ctx, duk_idx_t index) {
17813 	DUK_ASSERT_CTX_VALID(ctx);
17814 	return duk__tag_check(ctx, index, DUK_TAG_LIGHTFUNC);
17815 }
17816 
duk_is_array(duk_context * ctx,duk_idx_t index)17817 DUK_EXTERNAL duk_bool_t duk_is_array(duk_context *ctx, duk_idx_t index) {
17818 	duk_hobject *obj;
17819 
17820 	DUK_ASSERT_CTX_VALID(ctx);
17821 
17822 	obj = duk_get_hobject(ctx, index);
17823 	if (obj) {
17824 		return (DUK_HOBJECT_GET_CLASS_NUMBER(obj) == DUK_HOBJECT_CLASS_ARRAY ? 1 : 0);
17825 	}
17826 	return 0;
17827 }
17828 
duk_is_function(duk_context * ctx,duk_idx_t index)17829 DUK_EXTERNAL duk_bool_t duk_is_function(duk_context *ctx, duk_idx_t index) {
17830 	duk_tval *tv;
17831 
17832 	DUK_ASSERT_CTX_VALID(ctx);
17833 
17834 	tv = duk_get_tval(ctx, index);
17835 	if (tv && DUK_TVAL_IS_LIGHTFUNC(tv)) {
17836 		return 1;
17837 	}
17838 	return duk__obj_flag_any_default_false(ctx,
17839 	                                       index,
17840 	                                       DUK_HOBJECT_FLAG_COMPILEDFUNCTION |
17841 	                                       DUK_HOBJECT_FLAG_NATIVEFUNCTION |
17842 	                                       DUK_HOBJECT_FLAG_BOUND);
17843 }
17844 
duk_is_c_function(duk_context * ctx,duk_idx_t index)17845 DUK_EXTERNAL duk_bool_t duk_is_c_function(duk_context *ctx, duk_idx_t index) {
17846 	DUK_ASSERT_CTX_VALID(ctx);
17847 	return duk__obj_flag_any_default_false(ctx,
17848 	                                       index,
17849 	                                       DUK_HOBJECT_FLAG_NATIVEFUNCTION);
17850 }
17851 
duk_is_ecmascript_function(duk_context * ctx,duk_idx_t index)17852 DUK_EXTERNAL duk_bool_t duk_is_ecmascript_function(duk_context *ctx, duk_idx_t index) {
17853 	DUK_ASSERT_CTX_VALID(ctx);
17854 	return duk__obj_flag_any_default_false(ctx,
17855 	                                       index,
17856 	                                       DUK_HOBJECT_FLAG_COMPILEDFUNCTION);
17857 }
17858 
duk_is_bound_function(duk_context * ctx,duk_idx_t index)17859 DUK_EXTERNAL duk_bool_t duk_is_bound_function(duk_context *ctx, duk_idx_t index) {
17860 	DUK_ASSERT_CTX_VALID(ctx);
17861 	return duk__obj_flag_any_default_false(ctx,
17862 	                                       index,
17863 	                                       DUK_HOBJECT_FLAG_BOUND);
17864 }
17865 
duk_is_thread(duk_context * ctx,duk_idx_t index)17866 DUK_EXTERNAL duk_bool_t duk_is_thread(duk_context *ctx, duk_idx_t index) {
17867 	DUK_ASSERT_CTX_VALID(ctx);
17868 	return duk__obj_flag_any_default_false(ctx,
17869 	                                       index,
17870 	                                       DUK_HOBJECT_FLAG_THREAD);
17871 }
17872 
duk_is_fixed_buffer(duk_context * ctx,duk_idx_t index)17873 DUK_EXTERNAL duk_bool_t duk_is_fixed_buffer(duk_context *ctx, duk_idx_t index) {
17874 	duk_tval *tv;
17875 
17876 	DUK_ASSERT_CTX_VALID(ctx);
17877 
17878 	tv = duk_get_tval(ctx, index);
17879 	if (tv && DUK_TVAL_IS_BUFFER(tv)) {
17880 		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
17881 		DUK_ASSERT(h != NULL);
17882 		return (DUK_HBUFFER_HAS_DYNAMIC(h) ? 0 : 1);
17883 	}
17884 	return 0;
17885 }
17886 
duk_is_dynamic_buffer(duk_context * ctx,duk_idx_t index)17887 DUK_EXTERNAL duk_bool_t duk_is_dynamic_buffer(duk_context *ctx, duk_idx_t index) {
17888 	duk_tval *tv;
17889 
17890 	DUK_ASSERT_CTX_VALID(ctx);
17891 
17892 	tv = duk_get_tval(ctx, index);
17893 	if (tv && DUK_TVAL_IS_BUFFER(tv)) {
17894 		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
17895 		DUK_ASSERT(h != NULL);
17896 		return (DUK_HBUFFER_HAS_DYNAMIC(h) && !DUK_HBUFFER_HAS_EXTERNAL(h) ? 1 : 0);
17897 	}
17898 	return 0;
17899 }
17900 
duk_is_external_buffer(duk_context * ctx,duk_idx_t index)17901 DUK_EXTERNAL duk_bool_t duk_is_external_buffer(duk_context *ctx, duk_idx_t index) {
17902 	duk_tval *tv;
17903 
17904 	DUK_ASSERT_CTX_VALID(ctx);
17905 
17906 	tv = duk_get_tval(ctx, index);
17907 	if (tv && DUK_TVAL_IS_BUFFER(tv)) {
17908 		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
17909 		DUK_ASSERT(h != NULL);
17910 		return (DUK_HBUFFER_HAS_DYNAMIC(h) && DUK_HBUFFER_HAS_EXTERNAL(h) ? 1 : 0);
17911 	}
17912 	return 0;
17913 }
17914 
duk_get_error_code(duk_context * ctx,duk_idx_t index)17915 DUK_EXTERNAL duk_errcode_t duk_get_error_code(duk_context *ctx, duk_idx_t index) {
17916 	duk_hthread *thr = (duk_hthread *) ctx;
17917 	duk_hobject *h;
17918 	duk_uint_t sanity;
17919 
17920 	DUK_ASSERT_CTX_VALID(ctx);
17921 
17922 	h = duk_get_hobject(ctx, index);
17923 
17924 	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
17925 	do {
17926 		if (!h) {
17927 			return DUK_ERR_NONE;
17928 		}
17929 		if (h == thr->builtins[DUK_BIDX_EVAL_ERROR_PROTOTYPE]) {
17930 			return DUK_ERR_EVAL_ERROR;
17931 		}
17932 		if (h == thr->builtins[DUK_BIDX_RANGE_ERROR_PROTOTYPE]) {
17933 			return DUK_ERR_RANGE_ERROR;
17934 		}
17935 		if (h == thr->builtins[DUK_BIDX_REFERENCE_ERROR_PROTOTYPE]) {
17936 			return DUK_ERR_REFERENCE_ERROR;
17937 		}
17938 		if (h == thr->builtins[DUK_BIDX_SYNTAX_ERROR_PROTOTYPE]) {
17939 			return DUK_ERR_SYNTAX_ERROR;
17940 		}
17941 		if (h == thr->builtins[DUK_BIDX_TYPE_ERROR_PROTOTYPE]) {
17942 			return DUK_ERR_TYPE_ERROR;
17943 		}
17944 		if (h == thr->builtins[DUK_BIDX_URI_ERROR_PROTOTYPE]) {
17945 			return DUK_ERR_URI_ERROR;
17946 		}
17947 		if (h == thr->builtins[DUK_BIDX_ERROR_PROTOTYPE]) {
17948 			return DUK_ERR_ERROR;
17949 		}
17950 
17951 		h = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
17952 	} while (--sanity > 0);
17953 
17954 	return DUK_ERR_NONE;
17955 }
17956 
17957 /*
17958  *  Pushers
17959  */
17960 
duk_push_tval(duk_context * ctx,duk_tval * tv)17961 DUK_INTERNAL void duk_push_tval(duk_context *ctx, duk_tval *tv) {
17962 	duk_hthread *thr;
17963 	duk_tval *tv_slot;
17964 
17965 	DUK_ASSERT_CTX_VALID(ctx);
17966 	DUK_ASSERT(tv != NULL);
17967 	thr = (duk_hthread *) ctx;
17968 	DUK__CHECK_SPACE();
17969 	tv_slot = thr->valstack_top++;
17970 	DUK_TVAL_SET_TVAL(tv_slot, tv);
17971 	DUK_TVAL_INCREF(thr, tv);  /* no side effects */
17972 }
17973 
duk_push_undefined(duk_context * ctx)17974 DUK_EXTERNAL void duk_push_undefined(duk_context *ctx) {
17975 	duk_hthread *thr;
17976 
17977 	DUK_ASSERT_CTX_VALID(ctx);
17978 	thr = (duk_hthread *) ctx;
17979 	DUK__CHECK_SPACE();
17980 
17981 	/* Because value stack init policy is 'undefined above top',
17982 	 * we don't need to write, just assert.
17983 	 */
17984 	thr->valstack_top++;
17985 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top - 1));
17986 }
17987 
duk_push_null(duk_context * ctx)17988 DUK_EXTERNAL void duk_push_null(duk_context *ctx) {
17989 	duk_hthread *thr;
17990 	duk_tval *tv_slot;
17991 
17992 	DUK_ASSERT_CTX_VALID(ctx);
17993 	thr = (duk_hthread *) ctx;
17994 	DUK__CHECK_SPACE();
17995 	tv_slot = thr->valstack_top++;
17996 	DUK_TVAL_SET_NULL(tv_slot);
17997 }
17998 
duk_push_boolean(duk_context * ctx,duk_bool_t val)17999 DUK_EXTERNAL void duk_push_boolean(duk_context *ctx, duk_bool_t val) {
18000 	duk_hthread *thr;
18001 	duk_tval *tv_slot;
18002 	duk_small_int_t b;
18003 
18004 	DUK_ASSERT_CTX_VALID(ctx);
18005 	thr = (duk_hthread *) ctx;
18006 	DUK__CHECK_SPACE();
18007 	b = (val ? 1 : 0);  /* ensure value is 1 or 0 (not other non-zero) */
18008 	tv_slot = thr->valstack_top++;
18009 	DUK_TVAL_SET_BOOLEAN(tv_slot, b);
18010 }
18011 
duk_push_true(duk_context * ctx)18012 DUK_EXTERNAL void duk_push_true(duk_context *ctx) {
18013 	duk_hthread *thr;
18014 	duk_tval *tv_slot;
18015 
18016 	DUK_ASSERT_CTX_VALID(ctx);
18017 	thr = (duk_hthread *) ctx;
18018 	DUK__CHECK_SPACE();
18019 	tv_slot = thr->valstack_top++;
18020 	DUK_TVAL_SET_BOOLEAN_TRUE(tv_slot);
18021 }
18022 
duk_push_false(duk_context * ctx)18023 DUK_EXTERNAL void duk_push_false(duk_context *ctx) {
18024 	duk_hthread *thr;
18025 	duk_tval *tv_slot;
18026 
18027 	DUK_ASSERT_CTX_VALID(ctx);
18028 	thr = (duk_hthread *) ctx;
18029 	DUK__CHECK_SPACE();
18030 	tv_slot = thr->valstack_top++;
18031 	DUK_TVAL_SET_BOOLEAN_FALSE(tv_slot);
18032 }
18033 
18034 /* normalize NaN which may not match our canonical internal NaN */
duk_push_number(duk_context * ctx,duk_double_t val)18035 DUK_EXTERNAL void duk_push_number(duk_context *ctx, duk_double_t val) {
18036 	duk_hthread *thr;
18037 	duk_tval *tv_slot;
18038 	duk_double_union du;
18039 
18040 	DUK_ASSERT_CTX_VALID(ctx);
18041 	thr = (duk_hthread *) ctx;
18042 	DUK__CHECK_SPACE();
18043 	du.d = val;
18044 	DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);
18045 	tv_slot = thr->valstack_top++;
18046 	DUK_TVAL_SET_NUMBER(tv_slot, du.d);
18047 }
18048 
duk_push_int(duk_context * ctx,duk_int_t val)18049 DUK_EXTERNAL void duk_push_int(duk_context *ctx, duk_int_t val) {
18050 #if defined(DUK_USE_FASTINT)
18051 	duk_hthread *thr;
18052 	duk_tval *tv_slot;
18053 
18054 	DUK_ASSERT_CTX_VALID(ctx);
18055 	thr = (duk_hthread *) ctx;
18056 	DUK__CHECK_SPACE();
18057 	tv_slot = thr->valstack_top++;
18058 #if DUK_INT_MAX <= 0x7fffffffL
18059 	DUK_TVAL_SET_FASTINT_I32(tv_slot, (duk_int32_t) val);
18060 #else
18061 	if (val >= DUK_FASTINT_MIN && val <= DUK_FASTINT_MAX) {
18062 		DUK_TVAL_SET_FASTINT(tv_slot, (duk_int64_t) val);
18063 	} else {
18064 		duk_double_t = (duk_double_t) val;
18065 		DUK_TVAL_SET_NUMBER(tv_slot, d);
18066 	}
18067 #endif
18068 #else  /* DUK_USE_FASTINT */
18069 	duk_hthread *thr;
18070 	duk_tval *tv_slot;
18071 	duk_double_t d;
18072 
18073 	DUK_ASSERT_CTX_VALID(ctx);
18074 	thr = (duk_hthread *) ctx;
18075 	DUK__CHECK_SPACE();
18076 	d = (duk_double_t) val;
18077 	tv_slot = thr->valstack_top++;
18078 	DUK_TVAL_SET_NUMBER(tv_slot, d);
18079 #endif  /* DUK_USE_FASTINT */
18080 }
18081 
duk_push_uint(duk_context * ctx,duk_uint_t val)18082 DUK_EXTERNAL void duk_push_uint(duk_context *ctx, duk_uint_t val) {
18083 #if defined(DUK_USE_FASTINT)
18084 	duk_hthread *thr;
18085 	duk_tval *tv_slot;
18086 
18087 	DUK_ASSERT_CTX_VALID(ctx);
18088 	thr = (duk_hthread *) ctx;
18089 	DUK__CHECK_SPACE();
18090 	tv_slot = thr->valstack_top++;
18091 #if DUK_UINT_MAX <= 0xffffffffUL
18092 	DUK_TVAL_SET_FASTINT_U32(tv_slot, (duk_uint32_t) val);
18093 #else
18094 	if (val <= DUK_FASTINT_MAX) {  /* val is unsigned so >= 0 */
18095 		/* XXX: take advantage of val being unsigned, no need to mask */
18096 		DUK_TVAL_SET_FASTINT(tv_slot, (duk_int64_t) val);
18097 	} else {
18098 		duk_double_t = (duk_double_t) val;
18099 		DUK_TVAL_SET_NUMBER(tv_slot, d);
18100 	}
18101 #endif
18102 #else  /* DUK_USE_FASTINT */
18103 	duk_hthread *thr;
18104 	duk_tval *tv_slot;
18105 	duk_double_t d;
18106 
18107 	DUK_ASSERT_CTX_VALID(ctx);
18108 	thr = (duk_hthread *) ctx;
18109 	DUK__CHECK_SPACE();
18110 	d = (duk_double_t) val;
18111 	tv_slot = thr->valstack_top++;
18112 	DUK_TVAL_SET_NUMBER(tv_slot, d);
18113 #endif  /* DUK_USE_FASTINT */
18114 }
18115 
duk_push_nan(duk_context * ctx)18116 DUK_EXTERNAL void duk_push_nan(duk_context *ctx) {
18117 	duk_hthread *thr;
18118 	duk_tval *tv_slot;
18119 	duk_double_union du;
18120 
18121 	DUK_ASSERT_CTX_VALID(ctx);
18122 	thr = (duk_hthread *) ctx;
18123 	DUK__CHECK_SPACE();
18124 	DUK_DBLUNION_SET_NAN(&du);
18125 	DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
18126 	tv_slot = thr->valstack_top++;
18127 	DUK_TVAL_SET_NUMBER(tv_slot, du.d);
18128 }
18129 
duk_push_lstring(duk_context * ctx,const char * str,duk_size_t len)18130 DUK_EXTERNAL const char *duk_push_lstring(duk_context *ctx, const char *str, duk_size_t len) {
18131 	duk_hthread *thr = (duk_hthread *) ctx;
18132 	duk_hstring *h;
18133 	duk_tval *tv_slot;
18134 
18135 	DUK_ASSERT_CTX_VALID(ctx);
18136 
18137 	/* check stack before interning (avoid hanging temp) */
18138 	if (thr->valstack_top >= thr->valstack_end) {
18139 		DUK_ERROR_API(thr, DUK_STR_PUSH_BEYOND_ALLOC_STACK);
18140 	}
18141 
18142 	/* NULL with zero length represents an empty string; NULL with higher
18143 	 * length is also now trated like an empty string although it is
18144 	 * a bit dubious.  This is unlike duk_push_string() which pushes a
18145 	 * 'null' if the input string is a NULL.
18146 	 */
18147 	if (!str) {
18148 		len = 0;
18149 	}
18150 
18151 	/* Check for maximum string length */
18152 	if (len > DUK_HSTRING_MAX_BYTELEN) {
18153 		DUK_ERROR_RANGE(thr, DUK_STR_STRING_TOO_LONG);
18154 	}
18155 
18156 	h = duk_heap_string_intern_checked(thr, (const duk_uint8_t *) str, (duk_uint32_t) len);
18157 	DUK_ASSERT(h != NULL);
18158 
18159 	tv_slot = thr->valstack_top++;
18160 	DUK_TVAL_SET_STRING(tv_slot, h);
18161 	DUK_HSTRING_INCREF(thr, h);  /* no side effects */
18162 
18163 	return (const char *) DUK_HSTRING_GET_DATA(h);
18164 }
18165 
duk_push_string(duk_context * ctx,const char * str)18166 DUK_EXTERNAL const char *duk_push_string(duk_context *ctx, const char *str) {
18167 	DUK_ASSERT_CTX_VALID(ctx);
18168 
18169 	if (str) {
18170 		return duk_push_lstring(ctx, str, DUK_STRLEN(str));
18171 	} else {
18172 		duk_push_null(ctx);
18173 		return NULL;
18174 	}
18175 }
18176 
18177 #ifdef DUK_USE_FILE_IO
18178 /* This is a bit clunky because it is ANSI C portable.  Should perhaps
18179  * relocate to another file because this is potentially platform
18180  * dependent.
18181  */
duk_push_string_file_raw(duk_context * ctx,const char * path,duk_uint_t flags)18182 DUK_EXTERNAL const char *duk_push_string_file_raw(duk_context *ctx, const char *path, duk_uint_t flags) {
18183 	duk_hthread *thr = (duk_hthread *) ctx;
18184 	duk_file *f = NULL;
18185 	char *buf;
18186 	long sz;  /* ANSI C typing */
18187 
18188 	DUK_ASSERT_CTX_VALID(ctx);
18189 
18190 	if (!path) {
18191 		goto fail;
18192 	}
18193 	f = DUK_FOPEN(path, "rb");
18194 	if (!f) {
18195 		goto fail;
18196 	}
18197 	if (DUK_FSEEK(f, 0, SEEK_END) < 0) {
18198 		goto fail;
18199 	}
18200 	sz = DUK_FTELL(f);
18201 	if (sz < 0) {
18202 		goto fail;
18203 	}
18204 	if (DUK_FSEEK(f, 0, SEEK_SET) < 0) {
18205 		goto fail;
18206 	}
18207 	buf = (char *) duk_push_fixed_buffer(ctx, (duk_size_t) sz);
18208 	DUK_ASSERT(buf != NULL);
18209 	if ((duk_size_t) DUK_FREAD(buf, 1, (size_t) sz, f) != (duk_size_t) sz) {
18210 		goto fail;
18211 	}
18212 	(void) DUK_FCLOSE(f);  /* ignore fclose() error */
18213 	f = NULL;
18214 	return duk_to_string(ctx, -1);
18215 
18216  fail:
18217 	if (f) {
18218 		DUK_FCLOSE(f);
18219 	}
18220 
18221 	if (flags != 0) {
18222 		DUK_ASSERT(flags == DUK_STRING_PUSH_SAFE);  /* only flag now */
18223 		duk_push_undefined(ctx);
18224 	} else {
18225 		/* XXX: string not shared because it is conditional */
18226 		DUK_ERROR_TYPE(thr, "read file error");
18227 	}
18228 	return NULL;
18229 }
18230 #else
duk_push_string_file_raw(duk_context * ctx,const char * path,duk_uint_t flags)18231 DUK_EXTERNAL const char *duk_push_string_file_raw(duk_context *ctx, const char *path, duk_uint_t flags) {
18232 	duk_hthread *thr = (duk_hthread *) ctx;
18233 	DUK_ASSERT_CTX_VALID(ctx);
18234 	DUK_UNREF(path);
18235 
18236 	if (flags != 0) {
18237 		DUK_ASSERT(flags == DUK_STRING_PUSH_SAFE);  /* only flag now */
18238 		duk_push_undefined(ctx);
18239 	} else {
18240 		/* XXX: string not shared because it is conditional */
18241 		DUK_ERROR_UNSUPPORTED(thr, "file I/O disabled");
18242 	}
18243 	return NULL;
18244 }
18245 #endif  /* DUK_USE_FILE_IO */
18246 
duk_push_pointer(duk_context * ctx,void * val)18247 DUK_EXTERNAL void duk_push_pointer(duk_context *ctx, void *val) {
18248 	duk_hthread *thr;
18249 	duk_tval *tv_slot;
18250 
18251 	DUK_ASSERT_CTX_VALID(ctx);
18252 	thr = (duk_hthread *) ctx;
18253 	DUK__CHECK_SPACE();
18254 	tv_slot = thr->valstack_top++;
18255 	DUK_TVAL_SET_POINTER(tv_slot, val);
18256 }
18257 
duk__push_this_helper(duk_context * ctx,duk_small_uint_t check_object_coercible)18258 DUK_LOCAL void duk__push_this_helper(duk_context *ctx, duk_small_uint_t check_object_coercible) {
18259 	duk_hthread *thr;
18260 	duk_tval *tv_slot;
18261 
18262 	DUK_ASSERT_CTX_VALID(ctx);
18263 	DUK_ASSERT_DISABLE(thr->callstack_top >= 0);  /* avoid warning (unsigned) */
18264 	thr = (duk_hthread *) ctx;
18265 	DUK_ASSERT(thr->callstack_top <= thr->callstack_size);
18266 	DUK__CHECK_SPACE();
18267 
18268 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top));  /* because of valstack init policy */
18269 	tv_slot = thr->valstack_top++;
18270 
18271 	if (DUK_UNLIKELY(thr->callstack_top == 0)) {
18272 		if (check_object_coercible) {
18273 			goto type_error;
18274 		}
18275 		/* 'undefined' already on stack top */
18276 	} else {
18277 		duk_tval *tv;
18278 
18279 		/* 'this' binding is just before current activation's bottom */
18280 		DUK_ASSERT(thr->valstack_bottom > thr->valstack);
18281 		tv = thr->valstack_bottom - 1;
18282 		if (check_object_coercible &&
18283 		    (DUK_TVAL_IS_UNDEFINED(tv) || DUK_TVAL_IS_NULL(tv))) {
18284 			/* XXX: better macro for DUK_TVAL_IS_UNDEFINED_OR_NULL(tv) */
18285 			goto type_error;
18286 		}
18287 
18288 		DUK_TVAL_SET_TVAL(tv_slot, tv);
18289 		DUK_TVAL_INCREF(thr, tv);
18290 	}
18291 	return;
18292 
18293  type_error:
18294 	DUK_ERROR_TYPE(thr, DUK_STR_NOT_OBJECT_COERCIBLE);
18295 }
18296 
duk_push_this(duk_context * ctx)18297 DUK_EXTERNAL void duk_push_this(duk_context *ctx) {
18298 	DUK_ASSERT_CTX_VALID(ctx);
18299 
18300 	duk__push_this_helper(ctx, 0 /*check_object_coercible*/);
18301 }
18302 
duk_push_this_check_object_coercible(duk_context * ctx)18303 DUK_INTERNAL void duk_push_this_check_object_coercible(duk_context *ctx) {
18304 	DUK_ASSERT_CTX_VALID(ctx);
18305 
18306 	duk__push_this_helper(ctx, 1 /*check_object_coercible*/);
18307 }
18308 
duk_push_this_coercible_to_object(duk_context * ctx)18309 DUK_INTERNAL duk_hobject *duk_push_this_coercible_to_object(duk_context *ctx) {
18310 	duk_hobject *h;
18311 
18312 	DUK_ASSERT_CTX_VALID(ctx);
18313 
18314 	duk__push_this_helper(ctx, 1 /*check_object_coercible*/);
18315 	duk_to_object(ctx, -1);
18316 	h = duk_get_hobject(ctx, -1);
18317 	DUK_ASSERT(h != NULL);
18318 	return h;
18319 }
18320 
duk_push_this_coercible_to_string(duk_context * ctx)18321 DUK_INTERNAL duk_hstring *duk_push_this_coercible_to_string(duk_context *ctx) {
18322 	duk_hstring *h;
18323 
18324 	DUK_ASSERT_CTX_VALID(ctx);
18325 
18326 	duk__push_this_helper(ctx, 1 /*check_object_coercible*/);
18327 	duk_to_string(ctx, -1);
18328 	h = duk_get_hstring(ctx, -1);
18329 	DUK_ASSERT(h != NULL);
18330 	return h;
18331 }
18332 
duk_get_borrowed_this_tval(duk_context * ctx)18333 DUK_INTERNAL duk_tval *duk_get_borrowed_this_tval(duk_context *ctx) {
18334 	duk_hthread *thr;
18335 
18336 	DUK_ASSERT(ctx != NULL);
18337 	thr = (duk_hthread *) ctx;
18338 
18339 	DUK_ASSERT(thr->callstack_top > 0);  /* caller required to know */
18340 	DUK_ASSERT(thr->valstack_bottom > thr->valstack);  /* consequence of above */
18341 	DUK_ASSERT(thr->valstack_bottom - 1 >= thr->valstack);  /* 'this' binding exists */
18342 
18343 	return thr->valstack_bottom - 1;
18344 }
18345 
duk_push_current_function(duk_context * ctx)18346 DUK_EXTERNAL void duk_push_current_function(duk_context *ctx) {
18347 	duk_hthread *thr = (duk_hthread *) ctx;
18348 	duk_activation *act;
18349 
18350 	DUK_ASSERT_CTX_VALID(ctx);
18351 	DUK_ASSERT(thr != NULL);
18352 	DUK_ASSERT_DISABLE(thr->callstack_top >= 0);
18353 	DUK_ASSERT(thr->callstack_top <= thr->callstack_size);
18354 
18355 	act = duk_hthread_get_current_activation(thr);
18356 	if (act) {
18357 		duk_push_tval(ctx, &act->tv_func);
18358 	} else {
18359 		duk_push_undefined(ctx);
18360 	}
18361 }
18362 
duk_push_current_thread(duk_context * ctx)18363 DUK_EXTERNAL void duk_push_current_thread(duk_context *ctx) {
18364 	duk_hthread *thr = (duk_hthread *) ctx;
18365 
18366 	DUK_ASSERT_CTX_VALID(ctx);
18367 	DUK_ASSERT(thr != NULL);
18368 
18369 	if (thr->heap->curr_thread) {
18370 		duk_push_hobject(ctx, (duk_hobject *) thr->heap->curr_thread);
18371 	} else {
18372 		duk_push_undefined(ctx);
18373 	}
18374 }
18375 
duk_push_global_object(duk_context * ctx)18376 DUK_EXTERNAL void duk_push_global_object(duk_context *ctx) {
18377 	DUK_ASSERT_CTX_VALID(ctx);
18378 
18379 	duk_push_hobject_bidx(ctx, DUK_BIDX_GLOBAL);
18380 }
18381 
18382 /* XXX: size optimize */
duk__push_stash(duk_context * ctx)18383 DUK_LOCAL void duk__push_stash(duk_context *ctx) {
18384 	DUK_ASSERT_CTX_VALID(ctx);
18385 	if (!duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_VALUE)) {
18386 		DUK_DDD(DUK_DDDPRINT("creating heap/global/thread stash on first use"));
18387 		duk_pop(ctx);
18388 		duk_push_object_internal(ctx);
18389 		duk_dup_top(ctx);
18390 		duk_xdef_prop_stridx(ctx, -3, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_C);  /* [ ... parent stash stash ] -> [ ... parent stash ] */
18391 	}
18392 	duk_remove(ctx, -2);
18393 }
18394 
duk_push_heap_stash(duk_context * ctx)18395 DUK_EXTERNAL void duk_push_heap_stash(duk_context *ctx) {
18396 	duk_hthread *thr = (duk_hthread *) ctx;
18397 	duk_heap *heap;
18398 	DUK_ASSERT_CTX_VALID(ctx);
18399 	heap = thr->heap;
18400 	DUK_ASSERT(heap->heap_object != NULL);
18401 	duk_push_hobject(ctx, heap->heap_object);
18402 	duk__push_stash(ctx);
18403 }
18404 
duk_push_global_stash(duk_context * ctx)18405 DUK_EXTERNAL void duk_push_global_stash(duk_context *ctx) {
18406 	DUK_ASSERT_CTX_VALID(ctx);
18407 	duk_push_global_object(ctx);
18408 	duk__push_stash(ctx);
18409 }
18410 
duk_push_thread_stash(duk_context * ctx,duk_context * target_ctx)18411 DUK_EXTERNAL void duk_push_thread_stash(duk_context *ctx, duk_context *target_ctx) {
18412 	duk_hthread *thr = (duk_hthread *) ctx;
18413 	DUK_ASSERT_CTX_VALID(ctx);
18414 	if (!target_ctx) {
18415 		DUK_ERROR_API(thr, DUK_STR_INVALID_CALL_ARGS);
18416 		return;  /* not reached */
18417 	}
18418 	duk_push_hobject(ctx, (duk_hobject *) target_ctx);
18419 	duk__push_stash(ctx);
18420 }
18421 
18422 /* XXX: duk_ssize_t would be useful here */
duk__try_push_vsprintf(duk_context * ctx,void * buf,duk_size_t sz,const char * fmt,va_list ap)18423 DUK_LOCAL duk_int_t duk__try_push_vsprintf(duk_context *ctx, void *buf, duk_size_t sz, const char *fmt, va_list ap) {
18424 	duk_int_t len;
18425 
18426 	DUK_ASSERT_CTX_VALID(ctx);
18427 	DUK_UNREF(ctx);
18428 
18429 	/* NUL terminator handling doesn't matter here */
18430 	len = DUK_VSNPRINTF((char *) buf, sz, fmt, ap);
18431 	if (len < (duk_int_t) sz) {
18432 		/* Return value of 'sz' or more indicates output was (potentially)
18433 		 * truncated.
18434 		 */
18435 		return (duk_int_t) len;
18436 	}
18437 	return -1;
18438 }
18439 
duk_push_vsprintf(duk_context * ctx,const char * fmt,va_list ap)18440 DUK_EXTERNAL const char *duk_push_vsprintf(duk_context *ctx, const char *fmt, va_list ap) {
18441 	duk_hthread *thr = (duk_hthread *) ctx;
18442 	duk_uint8_t stack_buf[DUK_PUSH_SPRINTF_INITIAL_SIZE];
18443 	duk_size_t sz = DUK_PUSH_SPRINTF_INITIAL_SIZE;
18444 	duk_bool_t pushed_buf = 0;
18445 	void *buf;
18446 	duk_int_t len;  /* XXX: duk_ssize_t */
18447 	const char *res;
18448 
18449 	DUK_ASSERT_CTX_VALID(ctx);
18450 
18451 	/* special handling of fmt==NULL */
18452 	if (!fmt) {
18453 		duk_hstring *h_str;
18454 		duk_push_hstring_stridx(ctx, DUK_STRIDX_EMPTY_STRING);
18455 		h_str = DUK_HTHREAD_STRING_EMPTY_STRING(thr);  /* rely on interning, must be this string */
18456 		return (const char *) DUK_HSTRING_GET_DATA(h_str);
18457 	}
18458 
18459 	/* initial estimate based on format string */
18460 	sz = DUK_STRLEN(fmt) + 16;  /* format plus something to avoid just missing */
18461 	if (sz < DUK_PUSH_SPRINTF_INITIAL_SIZE) {
18462 		sz = DUK_PUSH_SPRINTF_INITIAL_SIZE;
18463 	}
18464 	DUK_ASSERT(sz > 0);
18465 
18466 	/* Try to make do with a stack buffer to avoid allocating a temporary buffer.
18467 	 * This works 99% of the time which is quite nice.
18468 	 */
18469 	for (;;) {
18470 		va_list ap_copy;  /* copied so that 'ap' can be reused */
18471 
18472 		if (sz <= sizeof(stack_buf)) {
18473 			buf = stack_buf;
18474 		} else if (!pushed_buf) {
18475 			pushed_buf = 1;
18476 			buf = duk_push_dynamic_buffer(ctx, sz);
18477 		} else {
18478 			buf = duk_resize_buffer(ctx, -1, sz);
18479 		}
18480 		DUK_ASSERT(buf != NULL);
18481 
18482 		DUK_VA_COPY(ap_copy, ap);
18483 		len = duk__try_push_vsprintf(ctx, buf, sz, fmt, ap_copy);
18484 		va_end(ap_copy);
18485 		if (len >= 0) {
18486 			break;
18487 		}
18488 
18489 		/* failed, resize and try again */
18490 		sz = sz * 2;
18491 		if (sz >= DUK_PUSH_SPRINTF_SANITY_LIMIT) {
18492 			DUK_ERROR_API(thr, DUK_STR_SPRINTF_TOO_LONG);
18493 		}
18494 	}
18495 
18496 	/* Cannot use duk_to_string() on the buffer because it is usually
18497 	 * larger than 'len'.  Also, 'buf' is usually a stack buffer.
18498 	 */
18499 	res = duk_push_lstring(ctx, (const char *) buf, (duk_size_t) len);  /* [ buf? res ] */
18500 	if (pushed_buf) {
18501 		duk_remove(ctx, -2);
18502 	}
18503 	return res;
18504 }
18505 
duk_push_sprintf(duk_context * ctx,const char * fmt,...)18506 DUK_EXTERNAL const char *duk_push_sprintf(duk_context *ctx, const char *fmt, ...) {
18507 	va_list ap;
18508 	const char *ret;
18509 
18510 	DUK_ASSERT_CTX_VALID(ctx);
18511 
18512 	/* allow fmt==NULL */
18513 	va_start(ap, fmt);
18514 	ret = duk_push_vsprintf(ctx, fmt, ap);
18515 	va_end(ap);
18516 
18517 	return ret;
18518 }
18519 
duk_push_object_helper(duk_context * ctx,duk_uint_t hobject_flags_and_class,duk_small_int_t prototype_bidx)18520 DUK_INTERNAL duk_idx_t duk_push_object_helper(duk_context *ctx, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx) {
18521 	duk_hthread *thr = (duk_hthread *) ctx;
18522 	duk_tval *tv_slot;
18523 	duk_hobject *h;
18524 	duk_idx_t ret;
18525 
18526 	DUK_ASSERT_CTX_VALID(ctx);
18527 	DUK_ASSERT(prototype_bidx == -1 ||
18528 	           (prototype_bidx >= 0 && prototype_bidx < DUK_NUM_BUILTINS));
18529 
18530 	/* check stack first */
18531 	if (thr->valstack_top >= thr->valstack_end) {
18532 		DUK_ERROR_API(thr, DUK_STR_PUSH_BEYOND_ALLOC_STACK);
18533 	}
18534 
18535 	h = duk_hobject_alloc(thr->heap, hobject_flags_and_class);
18536 	if (!h) {
18537 		DUK_ERROR_ALLOC_DEFMSG(thr);
18538 	}
18539 
18540 	DUK_DDD(DUK_DDDPRINT("created object with flags: 0x%08lx", (unsigned long) h->hdr.h_flags));
18541 
18542 	tv_slot = thr->valstack_top;
18543 	DUK_TVAL_SET_OBJECT(tv_slot, h);
18544 	DUK_HOBJECT_INCREF(thr, h);  /* no side effects */
18545 	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
18546 	thr->valstack_top++;
18547 
18548 	/* object is now reachable */
18549 
18550 	if (prototype_bidx >= 0) {
18551 		DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h, thr->builtins[prototype_bidx]);
18552 	} else {
18553 		DUK_ASSERT(prototype_bidx == -1);
18554 		DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h) == NULL);
18555 	}
18556 
18557 	return ret;
18558 }
18559 
duk_push_object_helper_proto(duk_context * ctx,duk_uint_t hobject_flags_and_class,duk_hobject * proto)18560 DUK_INTERNAL duk_idx_t duk_push_object_helper_proto(duk_context *ctx, duk_uint_t hobject_flags_and_class, duk_hobject *proto) {
18561 	duk_hthread *thr = (duk_hthread *) ctx;
18562 	duk_idx_t ret;
18563 	duk_hobject *h;
18564 
18565 	DUK_ASSERT_CTX_VALID(ctx);
18566 
18567 	ret = duk_push_object_helper(ctx, hobject_flags_and_class, -1);
18568 	h = duk_get_hobject(ctx, -1);
18569 	DUK_ASSERT(h != NULL);
18570 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h) == NULL);
18571 	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h, proto);
18572 	return ret;
18573 }
18574 
duk_push_object(duk_context * ctx)18575 DUK_EXTERNAL duk_idx_t duk_push_object(duk_context *ctx) {
18576 	DUK_ASSERT_CTX_VALID(ctx);
18577 
18578 	return duk_push_object_helper(ctx,
18579 	                              DUK_HOBJECT_FLAG_EXTENSIBLE |
18580 	                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
18581 	                              DUK_BIDX_OBJECT_PROTOTYPE);
18582 }
18583 
duk_push_array(duk_context * ctx)18584 DUK_EXTERNAL duk_idx_t duk_push_array(duk_context *ctx) {
18585 	duk_hthread *thr = (duk_hthread *) ctx;
18586 	duk_hobject *obj;
18587 	duk_idx_t ret;
18588 
18589 	DUK_ASSERT_CTX_VALID(ctx);
18590 
18591 	ret = duk_push_object_helper(ctx,
18592 	                             DUK_HOBJECT_FLAG_EXTENSIBLE |
18593 	                             DUK_HOBJECT_FLAG_ARRAY_PART |
18594 	                             DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAY),
18595 	                             DUK_BIDX_ARRAY_PROTOTYPE);
18596 
18597 	obj = duk_require_hobject(ctx, ret);
18598 
18599 	/*
18600 	 *  An array must have a 'length' property (E5 Section 15.4.5.2).
18601 	 *  The special array behavior flag must only be enabled once the
18602 	 *  length property has been added.
18603 	 *
18604 	 *  The internal property must be a number (and preferably a
18605 	 *  fastint if fastint support is enabled).
18606 	 */
18607 
18608 	duk_push_int(ctx, 0);
18609 #if defined(DUK_USE_FASTINT)
18610 	DUK_ASSERT(DUK_TVAL_IS_FASTINT(duk_require_tval(ctx, -1)));
18611 #endif
18612 
18613 	duk_hobject_define_property_internal(thr,
18614 	                                     obj,
18615 	                                     DUK_HTHREAD_STRING_LENGTH(thr),
18616 	                                     DUK_PROPDESC_FLAGS_W);
18617 	DUK_HOBJECT_SET_EXOTIC_ARRAY(obj);
18618 
18619 	return ret;
18620 }
18621 
duk_push_thread_raw(duk_context * ctx,duk_uint_t flags)18622 DUK_EXTERNAL duk_idx_t duk_push_thread_raw(duk_context *ctx, duk_uint_t flags) {
18623 	duk_hthread *thr = (duk_hthread *) ctx;
18624 	duk_hthread *obj;
18625 	duk_idx_t ret;
18626 	duk_tval *tv_slot;
18627 
18628 	DUK_ASSERT_CTX_VALID(ctx);
18629 
18630 	/* check stack first */
18631 	if (thr->valstack_top >= thr->valstack_end) {
18632 		DUK_ERROR_API(thr, DUK_STR_PUSH_BEYOND_ALLOC_STACK);
18633 	}
18634 
18635 	obj = duk_hthread_alloc(thr->heap,
18636 	                        DUK_HOBJECT_FLAG_EXTENSIBLE |
18637 	                        DUK_HOBJECT_FLAG_THREAD |
18638 	                        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_THREAD));
18639 	if (!obj) {
18640 		DUK_ERROR_ALLOC_DEFMSG(thr);
18641 	}
18642 	obj->state = DUK_HTHREAD_STATE_INACTIVE;
18643 #if defined(DUK_USE_ROM_STRINGS)
18644 	/* Nothing to initialize, strs[] is in ROM. */
18645 #else
18646 #if defined(DUK_USE_HEAPPTR16)
18647 	obj->strs16 = thr->strs16;
18648 #else
18649 	obj->strs = thr->strs;
18650 #endif
18651 #endif
18652 	DUK_DDD(DUK_DDDPRINT("created thread object with flags: 0x%08lx", (unsigned long) obj->obj.hdr.h_flags));
18653 
18654 	/* make the new thread reachable */
18655 	tv_slot = thr->valstack_top;
18656 	DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
18657 	DUK_HTHREAD_INCREF(thr, obj);
18658 	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
18659 	thr->valstack_top++;
18660 
18661 	/* important to do this *after* pushing, to make the thread reachable for gc */
18662 	if (!duk_hthread_init_stacks(thr->heap, obj)) {
18663 		DUK_ERROR_ALLOC_DEFMSG(thr);
18664 	}
18665 
18666 	/* initialize built-ins - either by copying or creating new ones */
18667 	if (flags & DUK_THREAD_NEW_GLOBAL_ENV) {
18668 		duk_hthread_create_builtin_objects(obj);
18669 	} else {
18670 		duk_hthread_copy_builtin_objects(thr, obj);
18671 	}
18672 
18673 	/* default prototype (Note: 'obj' must be reachable) */
18674 	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, (duk_hobject *) obj, obj->builtins[DUK_BIDX_THREAD_PROTOTYPE]);
18675 
18676 	/* Initial stack size satisfies the stack spare constraints so there
18677 	 * is no need to require stack here.
18678 	 */
18679 	DUK_ASSERT(DUK_VALSTACK_INITIAL_SIZE >=
18680 	           DUK_VALSTACK_API_ENTRY_MINIMUM + DUK_VALSTACK_INTERNAL_EXTRA);
18681 
18682 	return ret;
18683 }
18684 
duk_push_compiledfunction(duk_context * ctx)18685 DUK_INTERNAL duk_idx_t duk_push_compiledfunction(duk_context *ctx) {
18686 	duk_hthread *thr = (duk_hthread *) ctx;
18687 	duk_hcompiledfunction *obj;
18688 	duk_idx_t ret;
18689 	duk_tval *tv_slot;
18690 
18691 	DUK_ASSERT_CTX_VALID(ctx);
18692 
18693 	/* check stack first */
18694 	if (thr->valstack_top >= thr->valstack_end) {
18695 		DUK_ERROR_API(thr, DUK_STR_PUSH_BEYOND_ALLOC_STACK);
18696 	}
18697 
18698 	/* Template functions are not strictly constructable (they don't
18699 	 * have a "prototype" property for instance), so leave the
18700 	 * DUK_HOBJECT_FLAG_CONSRUCTABLE flag cleared here.
18701 	 */
18702 
18703 	obj = duk_hcompiledfunction_alloc(thr->heap,
18704 	                                  DUK_HOBJECT_FLAG_EXTENSIBLE |
18705 	                                  DUK_HOBJECT_FLAG_COMPILEDFUNCTION |
18706 	                                  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION));
18707 	if (!obj) {
18708 		DUK_ERROR_ALLOC_DEFMSG(thr);
18709 	}
18710 
18711 	DUK_DDD(DUK_DDDPRINT("created compiled function object with flags: 0x%08lx", (unsigned long) obj->obj.hdr.h_flags));
18712 
18713 	tv_slot = thr->valstack_top;
18714 	DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
18715 	DUK_HOBJECT_INCREF(thr, obj);
18716 	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
18717 	thr->valstack_top++;
18718 
18719 	/* default prototype (Note: 'obj' must be reachable) */
18720 	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, (duk_hobject *) obj, thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
18721 
18722 	return ret;
18723 }
18724 
duk__push_c_function_raw(duk_context * ctx,duk_c_function func,duk_idx_t nargs,duk_uint_t flags)18725 DUK_LOCAL duk_idx_t duk__push_c_function_raw(duk_context *ctx, duk_c_function func, duk_idx_t nargs, duk_uint_t flags) {
18726 	duk_hthread *thr = (duk_hthread *) ctx;
18727 	duk_hnativefunction *obj;
18728 	duk_idx_t ret;
18729 	duk_tval *tv_slot;
18730 	duk_int16_t func_nargs;
18731 
18732 	DUK_ASSERT_CTX_VALID(ctx);
18733 
18734 	/* check stack first */
18735 	if (thr->valstack_top >= thr->valstack_end) {
18736 		DUK_ERROR_API(thr, DUK_STR_PUSH_BEYOND_ALLOC_STACK);
18737 	}
18738 	if (func == NULL) {
18739 		goto api_error;
18740 	}
18741 	if (nargs >= 0 && nargs < DUK_HNATIVEFUNCTION_NARGS_MAX) {
18742 		func_nargs = (duk_int16_t) nargs;
18743 	} else if (nargs == DUK_VARARGS) {
18744 		func_nargs = DUK_HNATIVEFUNCTION_NARGS_VARARGS;
18745 	} else {
18746 		goto api_error;
18747 	}
18748 
18749 	obj = duk_hnativefunction_alloc(thr->heap, flags);
18750 	if (!obj) {
18751 		DUK_ERROR_ALLOC_DEFMSG(thr);
18752 	}
18753 
18754 	obj->func = func;
18755 	obj->nargs = func_nargs;
18756 
18757 	DUK_DDD(DUK_DDDPRINT("created native function object with flags: 0x%08lx, nargs=%ld",
18758 	                     (unsigned long) obj->obj.hdr.h_flags, (long) obj->nargs));
18759 
18760 	tv_slot = thr->valstack_top;
18761 	DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
18762 	DUK_HOBJECT_INCREF(thr, obj);
18763 	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
18764 	thr->valstack_top++;
18765 
18766 	/* default prototype (Note: 'obj' must be reachable) */
18767 	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, (duk_hobject *) obj, thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
18768 
18769 	return ret;
18770 
18771  api_error:
18772 	DUK_ERROR_API(thr, DUK_STR_INVALID_CALL_ARGS);
18773 	return 0;  /* not reached */
18774 }
18775 
duk_push_c_function(duk_context * ctx,duk_c_function func,duk_int_t nargs)18776 DUK_EXTERNAL duk_idx_t duk_push_c_function(duk_context *ctx, duk_c_function func, duk_int_t nargs) {
18777 	duk_uint_t flags;
18778 
18779 	DUK_ASSERT_CTX_VALID(ctx);
18780 
18781 	flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
18782 	        DUK_HOBJECT_FLAG_CONSTRUCTABLE |
18783 	        DUK_HOBJECT_FLAG_NATIVEFUNCTION |
18784 	        DUK_HOBJECT_FLAG_NEWENV |
18785 	        DUK_HOBJECT_FLAG_STRICT |
18786 	        DUK_HOBJECT_FLAG_NOTAIL |
18787 	        DUK_HOBJECT_FLAG_EXOTIC_DUKFUNC |
18788 	        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION);
18789 
18790 	return duk__push_c_function_raw(ctx, func, nargs, flags);
18791 }
18792 
duk_push_c_function_noexotic(duk_context * ctx,duk_c_function func,duk_int_t nargs)18793 DUK_INTERNAL void duk_push_c_function_noexotic(duk_context *ctx, duk_c_function func, duk_int_t nargs) {
18794 	duk_uint_t flags;
18795 
18796 	DUK_ASSERT_CTX_VALID(ctx);
18797 
18798 	flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
18799 	        DUK_HOBJECT_FLAG_CONSTRUCTABLE |
18800 	        DUK_HOBJECT_FLAG_NATIVEFUNCTION |
18801 	        DUK_HOBJECT_FLAG_NEWENV |
18802 	        DUK_HOBJECT_FLAG_STRICT |
18803 	        DUK_HOBJECT_FLAG_NOTAIL |
18804 	        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION);
18805 
18806 	(void) duk__push_c_function_raw(ctx, func, nargs, flags);
18807 }
18808 
duk_push_c_function_noconstruct_noexotic(duk_context * ctx,duk_c_function func,duk_int_t nargs)18809 DUK_INTERNAL void duk_push_c_function_noconstruct_noexotic(duk_context *ctx, duk_c_function func, duk_int_t nargs) {
18810 	duk_uint_t flags;
18811 
18812 	DUK_ASSERT_CTX_VALID(ctx);
18813 
18814 	flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
18815 	        DUK_HOBJECT_FLAG_NATIVEFUNCTION |
18816 	        DUK_HOBJECT_FLAG_NEWENV |
18817 	        DUK_HOBJECT_FLAG_STRICT |
18818 	        DUK_HOBJECT_FLAG_NOTAIL |
18819 	        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION);
18820 
18821 	(void) duk__push_c_function_raw(ctx, func, nargs, flags);
18822 }
18823 
duk_push_c_lightfunc(duk_context * ctx,duk_c_function func,duk_idx_t nargs,duk_idx_t length,duk_int_t magic)18824 DUK_EXTERNAL duk_idx_t duk_push_c_lightfunc(duk_context *ctx, duk_c_function func, duk_idx_t nargs, duk_idx_t length, duk_int_t magic) {
18825 	duk_hthread *thr = (duk_hthread *) ctx;
18826 	duk_tval tv_tmp;
18827 	duk_small_uint_t lf_flags;
18828 
18829 	DUK_ASSERT_CTX_VALID(ctx);
18830 
18831 	/* check stack first */
18832 	if (thr->valstack_top >= thr->valstack_end) {
18833 		DUK_ERROR_API(thr, DUK_STR_PUSH_BEYOND_ALLOC_STACK);
18834 	}
18835 
18836 	if (nargs >= DUK_LFUNC_NARGS_MIN && nargs <= DUK_LFUNC_NARGS_MAX) {
18837 		/* as is */
18838 	} else if (nargs == DUK_VARARGS) {
18839 		nargs = DUK_LFUNC_NARGS_VARARGS;
18840 	} else {
18841 		goto api_error;
18842 	}
18843 	if (!(length >= DUK_LFUNC_LENGTH_MIN && length <= DUK_LFUNC_LENGTH_MAX)) {
18844 		goto api_error;
18845 	}
18846 	if (!(magic >= DUK_LFUNC_MAGIC_MIN && magic <= DUK_LFUNC_MAGIC_MAX)) {
18847 		goto api_error;
18848 	}
18849 
18850 	lf_flags = DUK_LFUNC_FLAGS_PACK(magic, length, nargs);
18851 	DUK_TVAL_SET_LIGHTFUNC(&tv_tmp, func, lf_flags);
18852 	duk_push_tval(ctx, &tv_tmp);  /* XXX: direct valstack write */
18853 	DUK_ASSERT(thr->valstack_top != thr->valstack_bottom);
18854 	return ((duk_idx_t) (thr->valstack_top - thr->valstack_bottom)) - 1;
18855 
18856  api_error:
18857 	DUK_ERROR_API(thr, DUK_STR_INVALID_CALL_ARGS);
18858 	return 0;  /* not reached */
18859 }
18860 
duk_push_bufferobject_raw(duk_context * ctx,duk_uint_t hobject_flags_and_class,duk_small_int_t prototype_bidx)18861 DUK_INTERNAL duk_hbufferobject *duk_push_bufferobject_raw(duk_context *ctx, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx) {
18862 	duk_hthread *thr = (duk_hthread *) ctx;
18863 	duk_hbufferobject *obj;
18864 	duk_tval *tv_slot;
18865 
18866 	DUK_ASSERT(ctx != NULL);
18867 	DUK_ASSERT(prototype_bidx >= 0);
18868 
18869 	/* check stack first */
18870 	if (thr->valstack_top >= thr->valstack_end) {
18871 		DUK_ERROR_API(thr, DUK_STR_PUSH_BEYOND_ALLOC_STACK);
18872 	}
18873 
18874 	obj = duk_hbufferobject_alloc(thr->heap, hobject_flags_and_class);
18875 	if (!obj) {
18876 		DUK_ERROR_ALLOC_DEFMSG(thr);
18877 	}
18878 
18879 	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, (duk_hobject *) obj, thr->builtins[prototype_bidx]);
18880 	DUK_ASSERT_HBUFFEROBJECT_VALID(obj);
18881 
18882 	tv_slot = thr->valstack_top;
18883 	DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
18884 	DUK_HOBJECT_INCREF(thr, obj);
18885 	thr->valstack_top++;
18886 
18887 	return obj;
18888 }
18889 
18890 /* XXX: There's quite a bit of overlap with buffer creation handling in
18891  * duk_bi_buffer.c.  Look for overlap and refactor.
18892  */
18893 #define DUK__PACK_ARGS(classnum,protobidx,elemtype,elemshift,isview) \
18894 	(((classnum) << 24) | ((protobidx) << 16) | ((elemtype) << 8) | ((elemshift) << 4) | (isview))
18895 
18896 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
18897 static const duk_uint32_t duk__bufobj_flags_lookup[] = {
18898 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_BUFFER,            DUK_BIDX_BUFFER_PROTOTYPE,            DUK_HBUFFEROBJECT_ELEM_UINT8,        0, 0),  /* DUK_BUFOBJ_DUKTAPE_BUFFER */
18899 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_BUFFER,            DUK_BIDX_NODEJS_BUFFER_PROTOTYPE,     DUK_HBUFFEROBJECT_ELEM_UINT8,        0, 0),  /* DUK_BUFOBJ_NODEJS_BUFFER */
18900 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_ARRAYBUFFER,       DUK_BIDX_ARRAYBUFFER_PROTOTYPE,       DUK_HBUFFEROBJECT_ELEM_UINT8,        0, 0),  /* DUK_BUFOBJ_ARRAYBUFFER */
18901 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_DATAVIEW,          DUK_BIDX_DATAVIEW_PROTOTYPE,          DUK_HBUFFEROBJECT_ELEM_UINT8,        0, 1),  /* DUK_BUFOBJ_DATAVIEW */
18902 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_INT8ARRAY,         DUK_BIDX_INT8ARRAY_PROTOTYPE,         DUK_HBUFFEROBJECT_ELEM_INT8,         0, 1),  /* DUK_BUFOBJ_INT8ARRAY */
18903 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT8ARRAY,        DUK_BIDX_UINT8ARRAY_PROTOTYPE,        DUK_HBUFFEROBJECT_ELEM_UINT8,        0, 1),  /* DUK_BUFOBJ_UINT8ARRAY */
18904 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY, DUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE, DUK_HBUFFEROBJECT_ELEM_UINT8CLAMPED, 0, 1),  /* DUK_BUFOBJ_UINT8CLAMPEDARRAY */
18905 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_INT16ARRAY,        DUK_BIDX_INT16ARRAY_PROTOTYPE,        DUK_HBUFFEROBJECT_ELEM_INT16,        1, 1),  /* DUK_BUFOBJ_INT16ARRAY */
18906 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT16ARRAY,       DUK_BIDX_UINT16ARRAY_PROTOTYPE,       DUK_HBUFFEROBJECT_ELEM_UINT16,       1, 1),  /* DUK_BUFOBJ_UINT16ARRAY */
18907 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_INT32ARRAY,        DUK_BIDX_INT32ARRAY_PROTOTYPE,        DUK_HBUFFEROBJECT_ELEM_INT32,        2, 1),  /* DUK_BUFOBJ_INT32ARRAY */
18908 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT32ARRAY,       DUK_BIDX_UINT32ARRAY_PROTOTYPE,       DUK_HBUFFEROBJECT_ELEM_UINT32,       2, 1),  /* DUK_BUFOBJ_UINT32ARRAY */
18909 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_FLOAT32ARRAY,      DUK_BIDX_FLOAT32ARRAY_PROTOTYPE,      DUK_HBUFFEROBJECT_ELEM_FLOAT32,      2, 1),  /* DUK_BUFOBJ_FLOAT32ARRAY */
18910 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_FLOAT64ARRAY,      DUK_BIDX_FLOAT64ARRAY_PROTOTYPE,      DUK_HBUFFEROBJECT_ELEM_FLOAT64,      3, 1)   /* DUK_BUFOBJ_FLOAT64ARRAY */
18911 };
18912 #else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
18913 /* Only allow Duktape.Buffer when support disabled. */
18914 static const duk_uint32_t duk__bufobj_flags_lookup[] = {
18915 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_BUFFER,            DUK_BIDX_BUFFER_PROTOTYPE,            DUK_HBUFFEROBJECT_ELEM_UINT8,        0, 0)   /* DUK_BUFOBJ_DUKTAPE_BUFFER */
18916 };
18917 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
18918 #undef DUK__PACK_ARGS
18919 
duk_push_buffer_object(duk_context * ctx,duk_idx_t idx_buffer,duk_size_t byte_offset,duk_size_t byte_length,duk_uint_t flags)18920 DUK_EXTERNAL void duk_push_buffer_object(duk_context *ctx, duk_idx_t idx_buffer, duk_size_t byte_offset, duk_size_t byte_length, duk_uint_t flags) {
18921 	duk_hthread *thr;
18922 	duk_hbufferobject *h_bufobj;
18923 	duk_hbuffer *h_val;
18924 	duk_uint32_t tmp;
18925 	duk_uint_t classnum;
18926 	duk_uint_t protobidx;
18927 	duk_uint_t lookupidx;
18928 	duk_uint_t uint_offset, uint_length, uint_added;
18929 
18930 	DUK_ASSERT_CTX_VALID(ctx);
18931 	thr = (duk_hthread *) ctx;
18932 	DUK_UNREF(thr);
18933 
18934 	/* The underlying types for offset/length in duk_hbufferobject is
18935 	 * duk_uint_t; make sure argument values fit and that offset + length
18936 	 * does not wrap.
18937 	 */
18938 	uint_offset = (duk_uint_t) byte_offset;
18939 	uint_length = (duk_uint_t) byte_length;
18940 	if (sizeof(duk_size_t) != sizeof(duk_uint_t)) {
18941 		if ((duk_size_t) uint_offset != byte_offset || (duk_size_t) uint_length != byte_length) {
18942 			goto range_error;
18943 		}
18944 	}
18945 	uint_added = uint_offset + uint_length;
18946 	if (uint_added < uint_offset) {
18947 		goto range_error;
18948 	}
18949 	DUK_ASSERT(uint_added >= uint_offset && uint_added >= uint_length);
18950 
18951 	DUK_ASSERT_DISABLE(flags >= 0);  /* flags is unsigned */
18952 	lookupidx = flags & 0x0f;  /* 4 low bits */
18953 	if (lookupidx >= sizeof(duk__bufobj_flags_lookup) / sizeof(duk_uint32_t)) {
18954 		goto arg_error;
18955 	}
18956 	tmp = duk__bufobj_flags_lookup[lookupidx];
18957 	classnum = tmp >> 24;
18958 	protobidx = (tmp >> 16) & 0xff;
18959 
18960 	h_val = duk_require_hbuffer(ctx, idx_buffer);
18961 	DUK_ASSERT(h_val != NULL);
18962 
18963 	h_bufobj = duk_push_bufferobject_raw(ctx,
18964 	                                     DUK_HOBJECT_FLAG_EXTENSIBLE |
18965 	                                     DUK_HOBJECT_FLAG_BUFFEROBJECT |
18966 	                                     DUK_HOBJECT_CLASS_AS_FLAGS(classnum),
18967 	                                     protobidx);
18968 	DUK_ASSERT(h_bufobj != NULL);
18969 
18970 	h_bufobj->buf = h_val;
18971 	DUK_HBUFFER_INCREF(thr, h_val);
18972 	h_bufobj->offset = uint_offset;
18973 	h_bufobj->length = uint_length;
18974 	h_bufobj->shift = (tmp >> 4) & 0x0f;
18975 	h_bufobj->elem_type = (tmp >> 8) & 0xff;
18976 	h_bufobj->is_view = tmp & 0x0f;
18977 	DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj);
18978 
18979 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
18980 	/* TypedArray views need an automatic ArrayBuffer which must be
18981 	 * provided as .buffer property of the view.  Just create a new
18982 	 * ArrayBuffer sharing the same underlying buffer.
18983 	 *
18984 	 * The ArrayBuffer offset is always set to zero, so that if one
18985 	 * accesses the ArrayBuffer at the view's .byteOffset, the value
18986 	 * matches the view at index 0.
18987 	 */
18988 	if (flags & DUK_BUFOBJ_CREATE_ARRBUF) {
18989 		h_bufobj = duk_push_bufferobject_raw(ctx,
18990 		                                     DUK_HOBJECT_FLAG_EXTENSIBLE |
18991 		                                     DUK_HOBJECT_FLAG_BUFFEROBJECT |
18992 		                                     DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAYBUFFER),
18993 		                                     DUK_BIDX_ARRAYBUFFER_PROTOTYPE);
18994 
18995 		DUK_ASSERT(h_bufobj != NULL);
18996 
18997 		h_bufobj->buf = h_val;
18998 		DUK_HBUFFER_INCREF(thr, h_val);
18999 		h_bufobj->offset = 0;
19000 		h_bufobj->length = uint_offset + uint_length;  /* Wrap checked above. */
19001 		DUK_ASSERT(h_bufobj->shift == 0);
19002 		h_bufobj->elem_type = DUK_HBUFFEROBJECT_ELEM_UINT8;
19003 		DUK_ASSERT(h_bufobj->is_view == 0);
19004 		DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj);
19005 
19006 		duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LC_BUFFER, DUK_PROPDESC_FLAGS_NONE);
19007 		duk_compact(ctx, -1);
19008 	}
19009 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
19010 
19011 	return;
19012 
19013  range_error:
19014 	DUK_ERROR_RANGE(thr, DUK_STR_INVALID_CALL_ARGS);
19015 	return;  /* not reached */
19016 
19017  arg_error:
19018 	DUK_ERROR_TYPE(thr, DUK_STR_INVALID_CALL_ARGS);
19019 	return;  /* not reached */
19020 }
19021 
duk_push_error_object_va_raw(duk_context * ctx,duk_errcode_t err_code,const char * filename,duk_int_t line,const char * fmt,va_list ap)19022 DUK_EXTERNAL duk_idx_t duk_push_error_object_va_raw(duk_context *ctx, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, va_list ap) {
19023 	duk_hthread *thr = (duk_hthread *) ctx;
19024 	duk_idx_t ret;
19025 	duk_hobject *proto;
19026 #ifdef DUK_USE_AUGMENT_ERROR_CREATE
19027 	duk_bool_t noblame_fileline;
19028 #endif
19029 
19030 	DUK_ASSERT_CTX_VALID(ctx);
19031 	DUK_ASSERT(thr != NULL);
19032 	DUK_UNREF(filename);
19033 	DUK_UNREF(line);
19034 
19035 	/* Error code also packs a tracedata related flag. */
19036 #ifdef DUK_USE_AUGMENT_ERROR_CREATE
19037 	noblame_fileline = err_code & DUK_ERRCODE_FLAG_NOBLAME_FILELINE;
19038 #endif
19039 	err_code = err_code & (~DUK_ERRCODE_FLAG_NOBLAME_FILELINE);
19040 
19041 	/* error gets its 'name' from the prototype */
19042 	proto = duk_error_prototype_from_code(thr, err_code);
19043 	ret = duk_push_object_helper_proto(ctx,
19044 	                                   DUK_HOBJECT_FLAG_EXTENSIBLE |
19045 	                                   DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ERROR),
19046 	                                   proto);
19047 
19048 	/* ... and its 'message' from an instance property */
19049 	if (fmt) {
19050 		duk_push_vsprintf(ctx, fmt, ap);
19051 		duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_MESSAGE, DUK_PROPDESC_FLAGS_WC);
19052 	} else {
19053 		/* If no explicit message given, put error code into message field
19054 		 * (as a number).  This is not fully in keeping with the Ecmascript
19055 		 * error model because messages are supposed to be strings (Error
19056 		 * constructors use ToString() on their argument).  However, it's
19057 		 * probably more useful than having a separate 'code' property.
19058 		 */
19059 		duk_push_int(ctx, err_code);
19060 		duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_MESSAGE, DUK_PROPDESC_FLAGS_WC);
19061 	}
19062 
19063 	/* XXX: .code = err_code disabled, not sure if useful */
19064 
19065 	/* Creation time error augmentation */
19066 #ifdef DUK_USE_AUGMENT_ERROR_CREATE
19067 	/* filename may be NULL in which case file/line is not recorded */
19068 	duk_err_augment_error_create(thr, thr, filename, line, noblame_fileline);  /* may throw an error */
19069 #endif
19070 
19071 	return ret;
19072 }
19073 
duk_push_error_object_raw(duk_context * ctx,duk_errcode_t err_code,const char * filename,duk_int_t line,const char * fmt,...)19074 DUK_EXTERNAL duk_idx_t duk_push_error_object_raw(duk_context *ctx, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, ...) {
19075 	va_list ap;
19076 	duk_idx_t ret;
19077 
19078 	DUK_ASSERT_CTX_VALID(ctx);
19079 
19080 	va_start(ap, fmt);
19081 	ret = duk_push_error_object_va_raw(ctx, err_code, filename, line, fmt, ap);
19082 	va_end(ap);
19083 	return ret;
19084 }
19085 
19086 #if !defined(DUK_USE_VARIADIC_MACROS)
duk_push_error_object_stash(duk_context * ctx,duk_errcode_t err_code,const char * fmt,...)19087 DUK_EXTERNAL duk_idx_t duk_push_error_object_stash(duk_context *ctx, duk_errcode_t err_code, const char *fmt, ...) {
19088 	const char *filename = duk_api_global_filename;
19089 	duk_int_t line = duk_api_global_line;
19090 	va_list ap;
19091 	duk_idx_t ret;
19092 
19093 	DUK_ASSERT_CTX_VALID(ctx);
19094 
19095 	duk_api_global_filename = NULL;
19096 	duk_api_global_line = 0;
19097 	va_start(ap, fmt);
19098 	ret = duk_push_error_object_va_raw(ctx, err_code, filename, line, fmt, ap);
19099 	va_end(ap);
19100 	return ret;
19101 }
19102 #endif  /* DUK_USE_VARIADIC_MACROS */
19103 
duk_push_buffer_raw(duk_context * ctx,duk_size_t size,duk_small_uint_t flags)19104 DUK_EXTERNAL void *duk_push_buffer_raw(duk_context *ctx, duk_size_t size, duk_small_uint_t flags) {
19105 	duk_hthread *thr = (duk_hthread *) ctx;
19106 	duk_tval *tv_slot;
19107 	duk_hbuffer *h;
19108 	void *buf_data;
19109 
19110 	DUK_ASSERT_CTX_VALID(ctx);
19111 
19112 	/* check stack first */
19113 	if (thr->valstack_top >= thr->valstack_end) {
19114 		DUK_ERROR_API(thr, DUK_STR_PUSH_BEYOND_ALLOC_STACK);
19115 	}
19116 
19117 	/* Check for maximum buffer length. */
19118 	if (size > DUK_HBUFFER_MAX_BYTELEN) {
19119 		DUK_ERROR_RANGE(thr, DUK_STR_BUFFER_TOO_LONG);
19120 	}
19121 
19122 	h = duk_hbuffer_alloc(thr->heap, size, flags, &buf_data);
19123 	if (!h) {
19124 		DUK_ERROR_ALLOC_DEFMSG(thr);
19125 	}
19126 
19127 	tv_slot = thr->valstack_top;
19128 	DUK_TVAL_SET_BUFFER(tv_slot, h);
19129 	DUK_HBUFFER_INCREF(thr, h);
19130 	thr->valstack_top++;
19131 
19132 	return (void *) buf_data;
19133 }
19134 
19135 #if defined(DUK_USE_ASSERTIONS)
duk__validate_push_heapptr(duk_context * ctx,void * ptr)19136 DUK_LOCAL void duk__validate_push_heapptr(duk_context *ctx, void *ptr) {
19137 	duk_heaphdr *h;
19138 	duk_heaphdr *curr;
19139 	duk_hthread *thr;
19140 	duk_bool_t found = 0;
19141 
19142 	thr = (duk_hthread *) ctx;
19143 	h = (duk_heaphdr *) ptr;
19144 	if (h == NULL) {
19145 		/* Allowed. */
19146 		return;
19147 	}
19148 	DUK_ASSERT(h != NULL);
19149 	DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
19150 
19151 	/* One particular problem case is where an object has been
19152 	 * queued for finalization but the finalizer hasn't yet been
19153 	 * executed.
19154 	 *
19155 	 * Corner case: we're running in a finalizer for object X, and
19156 	 * user code calls duk_push_heapptr() for X itself.  In this
19157 	 * case X will be in finalize_list, and we can detect the case
19158 	 * by seeing that X's FINALIZED flag is set (which is done before
19159 	 * the finalizer starts executing).
19160 	 */
19161 	for (curr = thr->heap->finalize_list;
19162 	     curr != NULL;
19163 	     curr = DUK_HEAPHDR_GET_NEXT(thr->heap, curr)) {
19164 		if (curr == h) {
19165 			if (DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) h)) {
19166 				/* Object is currently being finalized. */
19167 				DUK_ASSERT(found == 0);  /* Would indicate corrupted lists. */
19168 				found = 1;
19169 			} else {
19170 				DUK_ASSERT(0);
19171 			}
19172 		}
19173 	}
19174 
19175 	/* Also check for the refzero_list; must not be there unless it is
19176 	 * being finalized when duk_push_heapptr() is called.
19177 	 *
19178 	 * Corner case: similar to finalize_list.
19179 	 */
19180 #if defined(DUK_USE_REFERENCE_COUNTING)
19181 	for (curr = thr->heap->refzero_list;
19182 	     curr != NULL;
19183 	     curr = DUK_HEAPHDR_GET_NEXT(thr->heap, curr)) {
19184 		if (curr == h) {
19185 			if (DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) h)) {
19186 				/* Object is currently being finalized. */
19187 				DUK_ASSERT(found == 0);  /* Would indicate corrupted lists. */
19188 				found = 1;
19189 			} else {
19190 				DUK_ASSERT(0);
19191 			}
19192 		}
19193 	}
19194 #endif
19195 
19196 	/* If not present in finalize_list or refzero_list, the pointer
19197 	 * must be either in heap_allocated or the string table.
19198 	 */
19199 	if (DUK_HEAPHDR_GET_TYPE(h) == DUK_HTYPE_STRING) {
19200 		/* String table assert check omitted from 1.x branch
19201 		 * backport.
19202 		 */
19203 	} else {
19204 		for (curr = thr->heap->heap_allocated;
19205 		     curr != NULL;
19206 		     curr = DUK_HEAPHDR_GET_NEXT(thr->heap, curr)) {
19207 			if (curr == h) {
19208 				DUK_ASSERT(found == 0);  /* Would indicate corrupted lists. */
19209 				found = 1;
19210 			}
19211 		}
19212 		DUK_ASSERT(found != 0);
19213 	}
19214 }
19215 #endif  /* DUK_USE_ASSERTIONS */
19216 
duk_push_heapptr(duk_context * ctx,void * ptr)19217 DUK_EXTERNAL duk_idx_t duk_push_heapptr(duk_context *ctx, void *ptr) {
19218 	duk_hthread *thr = (duk_hthread *) ctx;
19219 	duk_idx_t ret;
19220 
19221 	DUK_ASSERT_CTX_VALID(ctx);
19222 
19223 	/* Reviving an object using a heap pointer is a dangerous API
19224 	 * operation: if the application doesn't guarantee that the
19225 	 * pointer target is always reachable, difficult-to-diagnose
19226 	 * problems may ensue.  Try to validate the 'ptr' argument to
19227 	 * the extent possible.
19228 	 */
19229 
19230 #if defined(DUK_USE_ASSERTIONS)
19231 	duk__validate_push_heapptr(ctx, ptr);
19232 #endif
19233 
19234 	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
19235 
19236 	if (ptr == NULL) {
19237 		goto push_undefined;
19238 	}
19239 
19240 	switch ((int) DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) ptr)) {
19241 	case DUK_HTYPE_STRING:
19242 		duk_push_hstring(ctx, (duk_hstring *) ptr);
19243 		break;
19244 	case DUK_HTYPE_OBJECT:
19245 		duk_push_hobject(ctx, (duk_hobject *) ptr);
19246 		break;
19247 	case DUK_HTYPE_BUFFER:
19248 		duk_push_hbuffer(ctx, (duk_hbuffer *) ptr);
19249 		break;
19250 	default:
19251 		goto push_undefined;
19252 	}
19253 	return ret;
19254 
19255  push_undefined:
19256 	duk_push_undefined(ctx);
19257 	return ret;
19258 }
19259 
duk_push_object_internal(duk_context * ctx)19260 DUK_INTERNAL duk_idx_t duk_push_object_internal(duk_context *ctx) {
19261 	return duk_push_object_helper(ctx,
19262 	                              DUK_HOBJECT_FLAG_EXTENSIBLE |
19263 	                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
19264 	                              -1);  /* no prototype */
19265 }
19266 
duk_push_hstring(duk_context * ctx,duk_hstring * h)19267 DUK_INTERNAL void duk_push_hstring(duk_context *ctx, duk_hstring *h) {
19268 	duk_tval tv;
19269 	DUK_ASSERT_CTX_VALID(ctx);
19270 	DUK_ASSERT(h != NULL);
19271 	DUK_TVAL_SET_STRING(&tv, h);
19272 	duk_push_tval(ctx, &tv);
19273 }
19274 
duk_push_hstring_stridx(duk_context * ctx,duk_small_int_t stridx)19275 DUK_INTERNAL void duk_push_hstring_stridx(duk_context *ctx, duk_small_int_t stridx) {
19276 	duk_hthread *thr = (duk_hthread *) ctx;
19277 	DUK_UNREF(thr);
19278 	DUK_ASSERT(stridx >= 0 && stridx < DUK_HEAP_NUM_STRINGS);
19279 	duk_push_hstring(ctx, DUK_HTHREAD_GET_STRING(thr, stridx));
19280 }
19281 
duk_push_hobject(duk_context * ctx,duk_hobject * h)19282 DUK_INTERNAL void duk_push_hobject(duk_context *ctx, duk_hobject *h) {
19283 	duk_tval tv;
19284 	DUK_ASSERT_CTX_VALID(ctx);
19285 	DUK_ASSERT(h != NULL);
19286 	DUK_TVAL_SET_OBJECT(&tv, h);
19287 	duk_push_tval(ctx, &tv);
19288 }
19289 
duk_push_hbuffer(duk_context * ctx,duk_hbuffer * h)19290 DUK_INTERNAL void duk_push_hbuffer(duk_context *ctx, duk_hbuffer *h) {
19291 	duk_tval tv;
19292 	DUK_ASSERT_CTX_VALID(ctx);
19293 	DUK_ASSERT(h != NULL);
19294 	DUK_TVAL_SET_BUFFER(&tv, h);
19295 	duk_push_tval(ctx, &tv);
19296 }
19297 
duk_push_hobject_bidx(duk_context * ctx,duk_small_int_t builtin_idx)19298 DUK_INTERNAL void duk_push_hobject_bidx(duk_context *ctx, duk_small_int_t builtin_idx) {
19299 	duk_hthread *thr = (duk_hthread *) ctx;
19300 	DUK_ASSERT_CTX_VALID(ctx);
19301 	DUK_ASSERT(thr != NULL);
19302 	DUK_ASSERT(builtin_idx >= 0 && builtin_idx < DUK_NUM_BUILTINS);
19303 	DUK_ASSERT(thr->builtins[builtin_idx] != NULL);
19304 	duk_push_hobject(ctx, thr->builtins[builtin_idx]);
19305 }
19306 
19307 /*
19308  *  Poppers
19309  */
19310 
duk_pop_n(duk_context * ctx,duk_idx_t count)19311 DUK_EXTERNAL void duk_pop_n(duk_context *ctx, duk_idx_t count) {
19312 	duk_hthread *thr = (duk_hthread *) ctx;
19313 	duk_tval *tv;
19314 
19315 	DUK_ASSERT_CTX_VALID(ctx);
19316 
19317 	if (DUK_UNLIKELY(count < 0)) {
19318 		DUK_ERROR_API(thr, DUK_STR_INVALID_COUNT);
19319 		return;
19320 	}
19321 
19322 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
19323 	if (DUK_UNLIKELY((duk_size_t) (thr->valstack_top - thr->valstack_bottom) < (duk_size_t) count)) {
19324 		DUK_ERROR_API(thr, DUK_STR_POP_TOO_MANY);
19325 	}
19326 
19327 	/*
19328 	 *  Must be very careful here, every DECREF may cause reallocation
19329 	 *  of our valstack.
19330 	 */
19331 
19332 	/* XXX: inlined DECREF macro would be nice here: no NULL check,
19333 	 * refzero queueing but no refzero algorithm run (= no pointer
19334 	 * instability), inline code.
19335 	 */
19336 
19337 	/* XXX: optimize loops */
19338 
19339 #if defined(DUK_USE_REFERENCE_COUNTING)
19340 	while (count > 0) {
19341 		count--;
19342 		tv = --thr->valstack_top;  /* tv points to element just below prev top */
19343 		DUK_ASSERT(tv >= thr->valstack_bottom);
19344 		DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv);  /* side effects */
19345 	}
19346 #else
19347 	tv = thr->valstack_top;
19348 	while (count > 0) {
19349 		count--;
19350 		tv--;
19351 		DUK_ASSERT(tv >= thr->valstack_bottom);
19352 		DUK_TVAL_SET_UNDEFINED(tv);
19353 	}
19354 	thr->valstack_top = tv;
19355 #endif
19356 
19357 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
19358 }
19359 
19360 /* Popping one element is called so often that when footprint is not an issue,
19361  * compile a specialized function for it.
19362  */
19363 #if defined(DUK_USE_PREFER_SIZE)
duk_pop(duk_context * ctx)19364 DUK_EXTERNAL void duk_pop(duk_context *ctx) {
19365 	DUK_ASSERT_CTX_VALID(ctx);
19366 	duk_pop_n(ctx, 1);
19367 }
19368 #else
duk_pop(duk_context * ctx)19369 DUK_EXTERNAL void duk_pop(duk_context *ctx) {
19370 	duk_hthread *thr = (duk_hthread *) ctx;
19371 	duk_tval *tv;
19372 	DUK_ASSERT_CTX_VALID(ctx);
19373 
19374 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
19375 	if (DUK_UNLIKELY(thr->valstack_top == thr->valstack_bottom)) {
19376 		DUK_ERROR_API(thr, DUK_STR_POP_TOO_MANY);
19377 	}
19378 
19379 	tv = --thr->valstack_top;  /* tv points to element just below prev top */
19380 	DUK_ASSERT(tv >= thr->valstack_bottom);
19381 #ifdef DUK_USE_REFERENCE_COUNTING
19382 	DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv);  /* side effects */
19383 #else
19384 	DUK_TVAL_SET_UNDEFINED(tv);
19385 #endif
19386 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
19387 }
19388 #endif  /* !DUK_USE_PREFER_SIZE */
19389 
duk_pop_2(duk_context * ctx)19390 DUK_EXTERNAL void duk_pop_2(duk_context *ctx) {
19391 	DUK_ASSERT_CTX_VALID(ctx);
19392 	duk_pop_n(ctx, 2);
19393 }
19394 
duk_pop_3(duk_context * ctx)19395 DUK_EXTERNAL void duk_pop_3(duk_context *ctx) {
19396 	DUK_ASSERT_CTX_VALID(ctx);
19397 	duk_pop_n(ctx, 3);
19398 }
19399 
19400 /*
19401  *  Error throwing
19402  */
19403 
duk_throw(duk_context * ctx)19404 DUK_EXTERNAL void duk_throw(duk_context *ctx) {
19405 	duk_hthread *thr = (duk_hthread *) ctx;
19406 
19407 	DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
19408 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
19409 	DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
19410 
19411 	if (thr->valstack_top == thr->valstack_bottom) {
19412 		DUK_ERROR_API(thr, DUK_STR_INVALID_CALL_ARGS);
19413 	}
19414 
19415 	/* Errors are augmented when they are created, not when they are
19416 	 * thrown or re-thrown.  The current error handler, however, runs
19417 	 * just before an error is thrown.
19418 	 */
19419 
19420 	/* Sync so that augmentation sees up-to-date activations, NULL
19421 	 * thr->ptr_curr_pc so that it's not used if side effects occur
19422 	 * in augmentation or longjmp handling.
19423 	 */
19424 	duk_hthread_sync_and_null_currpc(thr);
19425 
19426 #if defined(DUK_USE_AUGMENT_ERROR_THROW)
19427 	DUK_DDD(DUK_DDDPRINT("THROW ERROR (API): %!dT (before throw augment)", (duk_tval *) duk_get_tval(ctx, -1)));
19428 	duk_err_augment_error_throw(thr);
19429 #endif
19430 	DUK_DDD(DUK_DDDPRINT("THROW ERROR (API): %!dT (after throw augment)", (duk_tval *) duk_get_tval(ctx, -1)));
19431 
19432 	duk_err_setup_heap_ljstate(thr, DUK_LJ_TYPE_THROW);
19433 
19434 	/* thr->heap->lj.jmpbuf_ptr is checked by duk_err_longjmp() so we don't
19435 	 * need to check that here.  If the value is NULL, a panic occurs because
19436 	 * we can't return.
19437 	 */
19438 
19439 	duk_err_longjmp(thr);
19440 	DUK_UNREACHABLE();
19441 }
19442 
duk_fatal(duk_context * ctx,duk_errcode_t err_code,const char * err_msg)19443 DUK_EXTERNAL void duk_fatal(duk_context *ctx, duk_errcode_t err_code, const char *err_msg) {
19444 	duk_hthread *thr = (duk_hthread *) ctx;
19445 
19446 	DUK_ASSERT_CTX_VALID(ctx);
19447 	DUK_ASSERT(thr != NULL);
19448 	DUK_ASSERT(thr->heap != NULL);
19449 	DUK_ASSERT(thr->heap->fatal_func != NULL);
19450 
19451 	DUK_D(DUK_DPRINT("fatal error occurred, code %ld, message %s",
19452 	                 (long) err_code, (const char *) err_msg));
19453 
19454 	/* fatal_func should be noreturn, but noreturn declarations on function
19455 	 * pointers has a very spotty support apparently so it's not currently
19456 	 * done.
19457 	 */
19458 	thr->heap->fatal_func(ctx, err_code, err_msg);
19459 
19460 	DUK_PANIC(DUK_ERR_API_ERROR, "fatal handler returned");
19461 }
19462 
duk_error_va_raw(duk_context * ctx,duk_errcode_t err_code,const char * filename,duk_int_t line,const char * fmt,va_list ap)19463 DUK_EXTERNAL void duk_error_va_raw(duk_context *ctx, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, va_list ap) {
19464 	DUK_ASSERT_CTX_VALID(ctx);
19465 
19466 	duk_push_error_object_va_raw(ctx, err_code, filename, line, fmt, ap);
19467 	duk_throw(ctx);
19468 }
19469 
duk_error_raw(duk_context * ctx,duk_errcode_t err_code,const char * filename,duk_int_t line,const char * fmt,...)19470 DUK_EXTERNAL void duk_error_raw(duk_context *ctx, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, ...) {
19471 	va_list ap;
19472 
19473 	DUK_ASSERT_CTX_VALID(ctx);
19474 
19475 	va_start(ap, fmt);
19476 	duk_push_error_object_va_raw(ctx, err_code, filename, line, fmt, ap);
19477 	va_end(ap);
19478 	duk_throw(ctx);
19479 }
19480 
19481 #if !defined(DUK_USE_VARIADIC_MACROS)
duk_error_stash(duk_context * ctx,duk_errcode_t err_code,const char * fmt,...)19482 DUK_EXTERNAL void duk_error_stash(duk_context *ctx, duk_errcode_t err_code, const char *fmt, ...) {
19483 	const char *filename;
19484 	duk_int_t line;
19485 	va_list ap;
19486 
19487 	DUK_ASSERT_CTX_VALID(ctx);
19488 
19489 	filename = duk_api_global_filename;
19490 	line = duk_api_global_line;
19491 	duk_api_global_filename = NULL;
19492 	duk_api_global_line = 0;
19493 
19494 	va_start(ap, fmt);
19495 	duk_push_error_object_va_raw(ctx, err_code, filename, line, fmt, ap);
19496 	va_end(ap);
19497 	duk_throw(ctx);
19498 }
19499 #endif  /* DUK_USE_VARIADIC_MACROS */
19500 
19501 /*
19502  *  Comparison
19503  */
19504 
duk_equals(duk_context * ctx,duk_idx_t index1,duk_idx_t index2)19505 DUK_EXTERNAL duk_bool_t duk_equals(duk_context *ctx, duk_idx_t index1, duk_idx_t index2) {
19506 	duk_hthread *thr = (duk_hthread *) ctx;
19507 	duk_tval *tv1, *tv2;
19508 
19509 	DUK_ASSERT_CTX_VALID(ctx);
19510 
19511 	tv1 = duk_get_tval(ctx, index1);
19512 	tv2 = duk_get_tval(ctx, index2);
19513 	if ((tv1 == NULL) || (tv2 == NULL)) {
19514 		return 0;
19515 	}
19516 
19517 	/* Coercion may be needed, the helper handles that by pushing the
19518 	 * tagged values to the stack.
19519 	 */
19520 	return duk_js_equals(thr, tv1, tv2);
19521 }
19522 
duk_strict_equals(duk_context * ctx,duk_idx_t index1,duk_idx_t index2)19523 DUK_EXTERNAL duk_bool_t duk_strict_equals(duk_context *ctx, duk_idx_t index1, duk_idx_t index2) {
19524 	duk_tval *tv1, *tv2;
19525 
19526 	DUK_ASSERT_CTX_VALID(ctx);
19527 
19528 	tv1 = duk_get_tval(ctx, index1);
19529 	tv2 = duk_get_tval(ctx, index2);
19530 	if ((tv1 == NULL) || (tv2 == NULL)) {
19531 		return 0;
19532 	}
19533 
19534 	/* No coercions or other side effects, so safe */
19535 	return duk_js_strict_equals(tv1, tv2);
19536 }
19537 
19538 /*
19539  *  instanceof
19540  */
19541 
duk_instanceof(duk_context * ctx,duk_idx_t index1,duk_idx_t index2)19542 DUK_EXTERNAL duk_bool_t duk_instanceof(duk_context *ctx, duk_idx_t index1, duk_idx_t index2) {
19543 	duk_tval *tv1, *tv2;
19544 
19545 	DUK_ASSERT_CTX_VALID(ctx);
19546 
19547 	/* Index validation is strict, which differs from duk_equals().
19548 	 * The strict behavior mimics how instanceof itself works, e.g.
19549 	 * it is a TypeError if rval is not a -callable- object.  It would
19550 	 * be somewhat inconsistent if rval would be allowed to be
19551 	 * non-existent without a TypeError.
19552 	 */
19553 	tv1 = duk_require_tval(ctx, index1);
19554 	DUK_ASSERT(tv1 != NULL);
19555 	tv2 = duk_require_tval(ctx, index2);
19556 	DUK_ASSERT(tv2 != NULL);
19557 
19558 	return duk_js_instanceof((duk_hthread *) ctx, tv1, tv2);
19559 }
19560 
19561 /*
19562  *  Lightfunc
19563  */
19564 
duk_push_lightfunc_name(duk_context * ctx,duk_tval * tv)19565 DUK_INTERNAL void duk_push_lightfunc_name(duk_context *ctx, duk_tval *tv) {
19566 	duk_c_function func;
19567 
19568 	DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv));
19569 
19570 	/* Lightfunc name, includes Duktape/C native function pointer, which
19571 	 * can often be used to locate the function from a symbol table.
19572 	 * The name also includes the 16-bit duk_tval flags field because it
19573 	 * includes the magic value.  Because a single native function often
19574 	 * provides different functionality depending on the magic value, it
19575 	 * seems reasonably to include it in the name.
19576 	 *
19577 	 * On the other hand, a complicated name increases string table
19578 	 * pressure in low memory environments (but only when function name
19579 	 * is accessed).
19580 	 */
19581 
19582 	func = DUK_TVAL_GET_LIGHTFUNC_FUNCPTR(tv);
19583 	duk_push_sprintf(ctx, "light_");
19584 	duk_push_string_funcptr(ctx, (duk_uint8_t *) &func, sizeof(func));
19585 	duk_push_sprintf(ctx, "_%04x", (unsigned int) DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv));
19586 	duk_concat(ctx, 3);
19587 }
19588 
duk_push_lightfunc_tostring(duk_context * ctx,duk_tval * tv)19589 DUK_INTERNAL void duk_push_lightfunc_tostring(duk_context *ctx, duk_tval *tv) {
19590 	DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv));
19591 
19592 	duk_push_string(ctx, "function ");
19593 	duk_push_lightfunc_name(ctx, tv);
19594 	duk_push_string(ctx, "() {\"light\"}");
19595 	duk_concat(ctx, 3);
19596 }
19597 
19598 /*
19599  *  Function pointers
19600  *
19601  *  Printing function pointers is non-portable, so we do that by hex printing
19602  *  bytes from memory.
19603  */
19604 
duk_push_string_funcptr(duk_context * ctx,duk_uint8_t * ptr,duk_size_t sz)19605 DUK_INTERNAL void duk_push_string_funcptr(duk_context *ctx, duk_uint8_t *ptr, duk_size_t sz) {
19606 	duk_uint8_t buf[32 * 2];
19607 	duk_uint8_t *p, *q;
19608 	duk_small_uint_t i;
19609 	duk_small_uint_t t;
19610 
19611 	DUK_ASSERT(sz <= 32);  /* sanity limit for function pointer size */
19612 
19613 	p = buf;
19614 #if defined(DUK_USE_INTEGER_LE)
19615 	q = ptr + sz;
19616 #else
19617 	q = ptr;
19618 #endif
19619 	for (i = 0; i < sz; i++) {
19620 #if defined(DUK_USE_INTEGER_LE)
19621 		t = *(--q);
19622 #else
19623 		t = *(q++);
19624 #endif
19625 		*p++ = duk_lc_digits[t >> 4];
19626 		*p++ = duk_lc_digits[t & 0x0f];
19627 	}
19628 
19629 	duk_push_lstring(ctx, (const char *) buf, sz * 2);
19630 }
19631 
19632 #if !defined(DUK_USE_PARANOID_ERRORS)
19633 /*
19634  *  Push readable string summarizing duk_tval.  The operation is side effect
19635  *  free and will only throw from internal errors (e.g. out of memory).
19636  *  This is used by e.g. property access code to summarize a key/base safely,
19637  *  and is not intended to be fast (but small and safe).
19638  */
19639 
19640 #define DUK__READABLE_STRING_MAXCHARS 32
19641 
19642 /* String sanitizer which escapes ASCII control characters and a few other
19643  * ASCII characters, passes Unicode as is, and replaces invalid UTF-8 with
19644  * question marks.  No errors are thrown for any input string, except in out
19645  * of memory situations.
19646  */
duk__push_hstring_readable_unicode(duk_context * ctx,duk_hstring * h_input)19647 DUK_LOCAL void duk__push_hstring_readable_unicode(duk_context *ctx, duk_hstring *h_input) {
19648 	duk_hthread *thr;
19649 	const duk_uint8_t *p, *p_start, *p_end;
19650 	duk_uint8_t buf[DUK_UNICODE_MAX_XUTF8_LENGTH * DUK__READABLE_STRING_MAXCHARS +
19651 	                2 /*quotes*/ + 3 /*periods*/];
19652 	duk_uint8_t *q;
19653 	duk_ucodepoint_t cp;
19654 	duk_small_uint_t nchars;
19655 
19656 	DUK_ASSERT_CTX_VALID(ctx);
19657 	DUK_ASSERT(h_input != NULL);
19658 	thr = (duk_hthread *) ctx;
19659 
19660 	p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
19661 	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
19662 	p = p_start;
19663 	q = buf;
19664 
19665 	nchars = 0;
19666 	*q++ = (duk_uint8_t) DUK_ASC_SINGLEQUOTE;
19667 	for (;;) {
19668 		if (p >= p_end) {
19669 			break;
19670 		}
19671 		if (nchars == DUK__READABLE_STRING_MAXCHARS) {
19672 			*q++ = (duk_uint8_t) DUK_ASC_PERIOD;
19673 			*q++ = (duk_uint8_t) DUK_ASC_PERIOD;
19674 			*q++ = (duk_uint8_t) DUK_ASC_PERIOD;
19675 			break;
19676 		}
19677 		if (duk_unicode_decode_xutf8(thr, &p, p_start, p_end, &cp)) {
19678 			if (cp < 0x20 || cp == 0x7f || cp == DUK_ASC_SINGLEQUOTE || cp == DUK_ASC_BACKSLASH) {
19679 				DUK_ASSERT(DUK_UNICODE_MAX_XUTF8_LENGTH >= 4);  /* estimate is valid */
19680 				DUK_ASSERT((cp >> 4) <= 0x0f);
19681 				*q++ = (duk_uint8_t) DUK_ASC_BACKSLASH;
19682 				*q++ = (duk_uint8_t) DUK_ASC_LC_X;
19683 				*q++ = (duk_uint8_t) duk_lc_digits[cp >> 4];
19684 				*q++ = (duk_uint8_t) duk_lc_digits[cp & 0x0f];
19685 			} else {
19686 				q += duk_unicode_encode_xutf8(cp, q);
19687 			}
19688 		} else {
19689 			p++;  /* advance manually */
19690 			*q++ = (duk_uint8_t) DUK_ASC_QUESTION;
19691 		}
19692 		nchars++;
19693 	}
19694 	*q++ = (duk_uint8_t) DUK_ASC_SINGLEQUOTE;
19695 
19696 	duk_push_lstring(ctx, (const char *) buf, (duk_size_t) (q - buf));
19697 }
19698 
duk_push_string_tval_readable(duk_context * ctx,duk_tval * tv)19699 DUK_INTERNAL const char *duk_push_string_tval_readable(duk_context *ctx, duk_tval *tv) {
19700 	duk_hthread *thr;
19701 
19702 	DUK_ASSERT_CTX_VALID(ctx);
19703 	thr = (duk_hthread *) ctx;
19704 	DUK_UNREF(thr);
19705 
19706 	if (tv == NULL) {
19707 		duk_push_string(ctx, "none");
19708 	} else {
19709 		switch (DUK_TVAL_GET_TAG(tv)) {
19710 		case DUK_TAG_STRING: {
19711 			duk__push_hstring_readable_unicode(ctx, DUK_TVAL_GET_STRING(tv));
19712 			break;
19713 		}
19714 		case DUK_TAG_OBJECT: {
19715 			duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
19716 			DUK_ASSERT(h != NULL);
19717 			duk_push_hobject_class_string(ctx, h);
19718 			break;
19719 		}
19720 		case DUK_TAG_BUFFER: {
19721 			/* XXX: Hex encoded, length limited buffer summary here? */
19722 			duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
19723 			DUK_ASSERT(h != NULL);
19724 			duk_push_sprintf(ctx, "[buffer:%ld]", (long) DUK_HBUFFER_GET_SIZE(h));
19725 			break;
19726 		}
19727 		case DUK_TAG_POINTER: {
19728 			/* Surround with parentheses like in JX, ensures NULL pointer
19729 			 * is distinguishable from null value ("(null)" vs "null").
19730 			 */
19731 			duk_push_tval(ctx, tv);
19732 			duk_push_sprintf(ctx, "(%s)", duk_to_string(ctx, -1));
19733 			duk_remove(ctx, -2);
19734 			break;
19735 		}
19736 		default: {
19737 			duk_push_tval(ctx, tv);
19738 			break;
19739 		}
19740 		}
19741 	}
19742 
19743 	return duk_to_string(ctx, -1);
19744 }
19745 
duk_push_string_readable(duk_context * ctx,duk_idx_t index)19746 DUK_INTERNAL const char *duk_push_string_readable(duk_context *ctx, duk_idx_t index) {
19747 	DUK_ASSERT_CTX_VALID(ctx);
19748 	return duk_push_string_tval_readable(ctx, duk_get_tval(ctx, index));
19749 }
19750 #endif  /* !DUK_USE_PARANOID_ERRORS */
19751 
19752 #undef DUK__CHECK_SPACE
19753 #undef DUK__PACK_ARGS
19754 #undef DUK__READABLE_STRING_MAXCHARS
19755 /*
19756  *  String manipulation
19757  */
19758 
19759 /* include removed: duk_internal.h */
19760 
duk__concat_and_join_helper(duk_context * ctx,duk_idx_t count_in,duk_bool_t is_join)19761 DUK_LOCAL void duk__concat_and_join_helper(duk_context *ctx, duk_idx_t count_in, duk_bool_t is_join) {
19762 	duk_hthread *thr = (duk_hthread *) ctx;
19763 	duk_uint_t count;
19764 	duk_uint_t i;
19765 	duk_size_t idx;
19766 	duk_size_t len;
19767 	duk_hstring *h;
19768 	duk_uint8_t *buf;
19769 
19770 	DUK_ASSERT_CTX_VALID(ctx);
19771 
19772 	if (DUK_UNLIKELY(count_in <= 0)) {
19773 		if (count_in < 0) {
19774 			DUK_ERROR_API(thr, DUK_STR_INVALID_COUNT);
19775 			return;
19776 		}
19777 		DUK_ASSERT(count_in == 0);
19778 		duk_push_hstring_stridx(ctx, DUK_STRIDX_EMPTY_STRING);
19779 		return;
19780 	}
19781 	count = (duk_uint_t) count_in;
19782 
19783 	if (is_join) {
19784 		duk_size_t t1, t2, limit;
19785 		h = duk_to_hstring(ctx, -((duk_idx_t) count) - 1);
19786 		DUK_ASSERT(h != NULL);
19787 
19788 		/* A bit tricky overflow test, see doc/code-issues.rst. */
19789 		t1 = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h);
19790 		t2 = (duk_size_t) (count - 1);
19791 		limit = (duk_size_t) DUK_HSTRING_MAX_BYTELEN;
19792 		if (DUK_UNLIKELY(t2 != 0 && t1 > limit / t2)) {
19793 			/* Combined size of separators already overflows */
19794 			goto error_overflow;
19795 		}
19796 		len = (duk_size_t) (t1 * t2);
19797 	} else {
19798 		len = (duk_size_t) 0;
19799 	}
19800 
19801 	for (i = count; i >= 1; i--) {
19802 		duk_size_t new_len;
19803 		duk_to_string(ctx, -((duk_idx_t) i));
19804 		h = duk_require_hstring(ctx, -((duk_idx_t) i));
19805 		new_len = len + (duk_size_t) DUK_HSTRING_GET_BYTELEN(h);
19806 
19807 		/* Impose a string maximum length, need to handle overflow
19808 		 * correctly.
19809 		 */
19810 		if (new_len < len ||  /* wrapped */
19811 		    new_len > (duk_size_t) DUK_HSTRING_MAX_BYTELEN) {
19812 			goto error_overflow;
19813 		}
19814 		len = new_len;
19815 	}
19816 
19817 	DUK_DDD(DUK_DDDPRINT("join/concat %lu strings, total length %lu bytes",
19818 	                     (unsigned long) count, (unsigned long) len));
19819 
19820 	/* use stack allocated buffer to ensure reachability in errors (e.g. intern error) */
19821 	buf = (duk_uint8_t *) duk_push_fixed_buffer(ctx, len);
19822 	DUK_ASSERT(buf != NULL);
19823 
19824 	/* [... (sep) str1 str2 ... strN buf] */
19825 
19826 	idx = 0;
19827 	for (i = count; i >= 1; i--) {
19828 		if (is_join && i != count) {
19829 			h = duk_require_hstring(ctx, -((duk_idx_t) count) - 2);  /* extra -1 for buffer */
19830 			DUK_MEMCPY(buf + idx, DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
19831 			idx += DUK_HSTRING_GET_BYTELEN(h);
19832 		}
19833 		h = duk_require_hstring(ctx, -((duk_idx_t) i) - 1);  /* extra -1 for buffer */
19834 		DUK_MEMCPY(buf + idx, DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
19835 		idx += DUK_HSTRING_GET_BYTELEN(h);
19836 	}
19837 
19838 	DUK_ASSERT(idx == len);
19839 
19840 	/* [... (sep) str1 str2 ... strN buf] */
19841 
19842 	/* get rid of the strings early to minimize memory use before intern */
19843 
19844 	if (is_join) {
19845 		duk_replace(ctx, -((duk_idx_t) count) - 2);  /* overwrite sep */
19846 		duk_pop_n(ctx, count);
19847 	} else {
19848 		duk_replace(ctx, -((duk_idx_t) count) - 1);  /* overwrite str1 */
19849 		duk_pop_n(ctx, count-1);
19850 	}
19851 
19852 	/* [... buf] */
19853 
19854 	(void) duk_to_string(ctx, -1);
19855 
19856 	/* [... res] */
19857 	return;
19858 
19859  error_overflow:
19860 	DUK_ERROR_RANGE(thr, DUK_STR_CONCAT_RESULT_TOO_LONG);
19861 }
19862 
duk_concat(duk_context * ctx,duk_idx_t count)19863 DUK_EXTERNAL void duk_concat(duk_context *ctx, duk_idx_t count) {
19864 	DUK_ASSERT_CTX_VALID(ctx);
19865 
19866 	duk__concat_and_join_helper(ctx, count, 0 /*is_join*/);
19867 }
19868 
duk_join(duk_context * ctx,duk_idx_t count)19869 DUK_EXTERNAL void duk_join(duk_context *ctx, duk_idx_t count) {
19870 	DUK_ASSERT_CTX_VALID(ctx);
19871 
19872 	duk__concat_and_join_helper(ctx, count, 1 /*is_join*/);
19873 }
19874 
19875 /* XXX: could map/decode be unified with duk_unicode_support.c code?
19876  * Case conversion needs also the character surroundings though.
19877  */
19878 
duk_decode_string(duk_context * ctx,duk_idx_t index,duk_decode_char_function callback,void * udata)19879 DUK_EXTERNAL void duk_decode_string(duk_context *ctx, duk_idx_t index, duk_decode_char_function callback, void *udata) {
19880 	duk_hthread *thr = (duk_hthread *) ctx;
19881 	duk_hstring *h_input;
19882 	const duk_uint8_t *p, *p_start, *p_end;
19883 	duk_codepoint_t cp;
19884 
19885 	DUK_ASSERT_CTX_VALID(ctx);
19886 
19887 	h_input = duk_require_hstring(ctx, index);
19888 	DUK_ASSERT(h_input != NULL);
19889 
19890 	p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
19891 	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
19892 	p = p_start;
19893 
19894 	for (;;) {
19895 		if (p >= p_end) {
19896 			break;
19897 		}
19898 		cp = (int) duk_unicode_decode_xutf8_checked(thr, &p, p_start, p_end);
19899 		callback(udata, cp);
19900 	}
19901 }
19902 
duk_map_string(duk_context * ctx,duk_idx_t index,duk_map_char_function callback,void * udata)19903 DUK_EXTERNAL void duk_map_string(duk_context *ctx, duk_idx_t index, duk_map_char_function callback, void *udata) {
19904 	duk_hthread *thr = (duk_hthread *) ctx;
19905 	duk_hstring *h_input;
19906 	duk_bufwriter_ctx bw_alloc;
19907 	duk_bufwriter_ctx *bw;
19908 	const duk_uint8_t *p, *p_start, *p_end;
19909 	duk_codepoint_t cp;
19910 
19911 	DUK_ASSERT_CTX_VALID(ctx);
19912 
19913 	index = duk_normalize_index(ctx, index);
19914 
19915 	h_input = duk_require_hstring(ctx, index);
19916 	DUK_ASSERT(h_input != NULL);
19917 
19918 	bw = &bw_alloc;
19919 	DUK_BW_INIT_PUSHBUF(thr, bw, DUK_HSTRING_GET_BYTELEN(h_input));  /* reasonable output estimate */
19920 
19921 	p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
19922 	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
19923 	p = p_start;
19924 
19925 	for (;;) {
19926 		/* XXX: could write output in chunks with fewer ensure calls,
19927 		 * but relative benefit would be small here.
19928 		 */
19929 
19930 		if (p >= p_end) {
19931 			break;
19932 		}
19933 		cp = (int) duk_unicode_decode_xutf8_checked(thr, &p, p_start, p_end);
19934 		cp = callback(udata, cp);
19935 
19936 		DUK_BW_WRITE_ENSURE_XUTF8(thr, bw, cp);
19937 	}
19938 
19939 	DUK_BW_COMPACT(thr, bw);
19940 	duk_to_string(ctx, -1);
19941 	duk_replace(ctx, index);
19942 }
19943 
duk_substring(duk_context * ctx,duk_idx_t index,duk_size_t start_offset,duk_size_t end_offset)19944 DUK_EXTERNAL void duk_substring(duk_context *ctx, duk_idx_t index, duk_size_t start_offset, duk_size_t end_offset) {
19945 	duk_hthread *thr = (duk_hthread *) ctx;
19946 	duk_hstring *h;
19947 	duk_hstring *res;
19948 	duk_size_t start_byte_offset;
19949 	duk_size_t end_byte_offset;
19950 
19951 	DUK_ASSERT_CTX_VALID(ctx);
19952 
19953 	index = duk_require_normalize_index(ctx, index);
19954 	h = duk_require_hstring(ctx, index);
19955 	DUK_ASSERT(h != NULL);
19956 
19957 	if (end_offset >= DUK_HSTRING_GET_CHARLEN(h)) {
19958 		end_offset = DUK_HSTRING_GET_CHARLEN(h);
19959 	}
19960 	if (start_offset > end_offset) {
19961 		start_offset = end_offset;
19962 	}
19963 
19964 	DUK_ASSERT_DISABLE(start_offset >= 0);
19965 	DUK_ASSERT(start_offset <= end_offset && start_offset <= DUK_HSTRING_GET_CHARLEN(h));
19966 	DUK_ASSERT_DISABLE(end_offset >= 0);
19967 	DUK_ASSERT(end_offset >= start_offset && end_offset <= DUK_HSTRING_GET_CHARLEN(h));
19968 
19969 	/* guaranteed by string limits */
19970 	DUK_ASSERT(start_offset <= DUK_UINT32_MAX);
19971 	DUK_ASSERT(end_offset <= DUK_UINT32_MAX);
19972 
19973 	start_byte_offset = (duk_size_t) duk_heap_strcache_offset_char2byte(thr, h, (duk_uint_fast32_t) start_offset);
19974 	end_byte_offset = (duk_size_t) duk_heap_strcache_offset_char2byte(thr, h, (duk_uint_fast32_t) end_offset);
19975 
19976 	DUK_ASSERT(end_byte_offset >= start_byte_offset);
19977 	DUK_ASSERT(end_byte_offset - start_byte_offset <= DUK_UINT32_MAX);  /* guaranteed by string limits */
19978 
19979 	/* no size check is necessary */
19980 	res = duk_heap_string_intern_checked(thr,
19981 	                                     DUK_HSTRING_GET_DATA(h) + start_byte_offset,
19982 	                                     (duk_uint32_t) (end_byte_offset - start_byte_offset));
19983 
19984 	duk_push_hstring(ctx, res);
19985 	duk_replace(ctx, index);
19986 }
19987 
19988 /* XXX: this is quite clunky.  Add Unicode helpers to scan backwards and
19989  * forwards with a callback to process codepoints?
19990  */
duk_trim(duk_context * ctx,duk_idx_t index)19991 DUK_EXTERNAL void duk_trim(duk_context *ctx, duk_idx_t index) {
19992 	duk_hthread *thr = (duk_hthread *) ctx;
19993 	duk_hstring *h;
19994 	const duk_uint8_t *p, *p_start, *p_end, *p_tmp1, *p_tmp2;  /* pointers for scanning */
19995 	const duk_uint8_t *q_start, *q_end;  /* start (incl) and end (excl) of trimmed part */
19996 	duk_codepoint_t cp;
19997 
19998 	DUK_ASSERT_CTX_VALID(ctx);
19999 
20000 	index = duk_require_normalize_index(ctx, index);
20001 	h = duk_require_hstring(ctx, index);
20002 	DUK_ASSERT(h != NULL);
20003 
20004 	p_start = DUK_HSTRING_GET_DATA(h);
20005 	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h);
20006 
20007 	p = p_start;
20008 	while (p < p_end) {
20009 		p_tmp1 = p;
20010 		cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p_tmp1, p_start, p_end);
20011 		if (!(duk_unicode_is_whitespace(cp) || duk_unicode_is_line_terminator(cp))) {
20012 			break;
20013 		}
20014 		p = p_tmp1;
20015 	}
20016 	q_start = p;
20017 	if (p == p_end) {
20018 		/* entire string is whitespace */
20019 		q_end = p;
20020 		goto scan_done;
20021 	}
20022 
20023 	p = p_end;
20024 	while (p > p_start) {
20025 		p_tmp1 = p;
20026 		while (p > p_start) {
20027 			p--;
20028 			if (((*p) & 0xc0) != 0x80) {
20029 				break;
20030 			}
20031 		}
20032 		p_tmp2 = p;
20033 
20034 		cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p_tmp2, p_start, p_end);
20035 		if (!(duk_unicode_is_whitespace(cp) || duk_unicode_is_line_terminator(cp))) {
20036 			p = p_tmp1;
20037 			break;
20038 		}
20039 	}
20040 	q_end = p;
20041 
20042  scan_done:
20043 	/* This may happen when forward and backward scanning disagree
20044 	 * (possible for non-extended-UTF-8 strings).
20045 	 */
20046 	if (q_end < q_start) {
20047 		q_end = q_start;
20048 	}
20049 
20050 	DUK_ASSERT(q_start >= p_start && q_start <= p_end);
20051 	DUK_ASSERT(q_end >= p_start && q_end <= p_end);
20052 	DUK_ASSERT(q_end >= q_start);
20053 
20054 	DUK_DDD(DUK_DDDPRINT("trim: p_start=%p, p_end=%p, q_start=%p, q_end=%p",
20055 	                     (const void *) p_start, (const void *) p_end,
20056 	                     (const void *) q_start, (const void *) q_end));
20057 
20058 	if (q_start == p_start && q_end == p_end) {
20059 		DUK_DDD(DUK_DDDPRINT("nothing was trimmed: avoid interning (hashing etc)"));
20060 		return;
20061 	}
20062 
20063 	duk_push_lstring(ctx, (const char *) q_start, (duk_size_t) (q_end - q_start));
20064 	duk_replace(ctx, index);
20065 }
20066 
duk_char_code_at(duk_context * ctx,duk_idx_t index,duk_size_t char_offset)20067 DUK_EXTERNAL duk_codepoint_t duk_char_code_at(duk_context *ctx, duk_idx_t index, duk_size_t char_offset) {
20068 	duk_hthread *thr = (duk_hthread *) ctx;
20069 	duk_hstring *h;
20070 	duk_ucodepoint_t cp;
20071 
20072 	DUK_ASSERT_CTX_VALID(ctx);
20073 
20074 	h = duk_require_hstring(ctx, index);
20075 	DUK_ASSERT(h != NULL);
20076 
20077 	DUK_ASSERT_DISABLE(char_offset >= 0);  /* always true, arg is unsigned */
20078 	if (char_offset >= DUK_HSTRING_GET_CHARLEN(h)) {
20079 		return 0;
20080 	}
20081 
20082 	DUK_ASSERT(char_offset <= DUK_UINT_MAX);  /* guaranteed by string limits */
20083 	cp = duk_hstring_char_code_at_raw(thr, h, (duk_uint_t) char_offset);
20084 	return (duk_codepoint_t) cp;
20085 }
20086 /*
20087  *  Variable access
20088  */
20089 
20090 /* include removed: duk_internal.h */
20091 
duk_get_var(duk_context * ctx)20092 DUK_EXTERNAL void duk_get_var(duk_context *ctx) {
20093 	duk_hthread *thr = (duk_hthread *) ctx;
20094 	duk_activation *act;
20095 	duk_hstring *h_varname;
20096 	duk_small_int_t throw_flag = 1;  /* always throw ReferenceError for unresolvable */
20097 
20098 	DUK_ASSERT_CTX_VALID(ctx);
20099 
20100 	h_varname = duk_require_hstring(ctx, -1);  /* XXX: tostring? */
20101 	DUK_ASSERT(h_varname != NULL);
20102 
20103 	act = duk_hthread_get_current_activation(thr);
20104 	if (act) {
20105 		(void) duk_js_getvar_activation(thr, act, h_varname, throw_flag);  /* -> [ ... varname val this ] */
20106 	} else {
20107 		/* Outside any activation -> look up from global. */
20108 		DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL_ENV] != NULL);
20109 		(void) duk_js_getvar_envrec(thr, thr->builtins[DUK_BIDX_GLOBAL_ENV], h_varname, throw_flag);
20110 	}
20111 
20112 	/* [ ... varname val this ]  (because throw_flag == 1, always resolved) */
20113 
20114 	duk_pop(ctx);
20115 	duk_remove(ctx, -2);
20116 
20117 	/* [ ... val ] */
20118 
20119 	/* Return value would be pointless: because throw_flag==1, we always
20120 	 * throw if the identifier doesn't resolve.
20121 	 */
20122 	return;
20123 }
20124 
duk_put_var(duk_context * ctx)20125 DUK_EXTERNAL void duk_put_var(duk_context *ctx) {
20126 	duk_hthread *thr = (duk_hthread *) ctx;
20127 	duk_activation *act;
20128 	duk_hstring *h_varname;
20129 	duk_tval *tv_val;
20130 	duk_small_int_t throw_flag;
20131 
20132 	DUK_ASSERT_CTX_VALID(ctx);
20133 
20134 	h_varname = duk_require_hstring(ctx, -2);  /* XXX: tostring? */
20135 	DUK_ASSERT(h_varname != NULL);
20136 
20137 	tv_val = duk_require_tval(ctx, -1);
20138 
20139 	throw_flag = duk_is_strict_call(ctx);
20140 
20141 	act = duk_hthread_get_current_activation(thr);
20142 	if (act) {
20143 		duk_js_putvar_activation(thr, act, h_varname, tv_val, throw_flag);  /* -> [ ... varname val this ] */
20144 	} else {
20145 		/* Outside any activation -> put to global. */
20146 		DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL_ENV] != NULL);
20147 		duk_js_putvar_envrec(thr, thr->builtins[DUK_BIDX_GLOBAL_ENV], h_varname, tv_val, throw_flag);
20148 	}
20149 
20150 	/* [ ... varname val ] */
20151 
20152 	duk_pop_2(ctx);
20153 
20154 	/* [ ... ] */
20155 
20156 	return;
20157 }
20158 
duk_del_var(duk_context * ctx)20159 DUK_EXTERNAL duk_bool_t duk_del_var(duk_context *ctx) {
20160 	DUK_ASSERT_CTX_VALID(ctx);
20161 
20162 	DUK_ERROR_UNIMPLEMENTED_DEFMSG((duk_hthread *) ctx);
20163 	return 0;
20164 }
20165 
duk_has_var(duk_context * ctx)20166 DUK_EXTERNAL duk_bool_t duk_has_var(duk_context *ctx) {
20167 	DUK_ASSERT_CTX_VALID(ctx);
20168 
20169 	DUK_ERROR_UNIMPLEMENTED_DEFMSG((duk_hthread *) ctx);
20170 	return 0;
20171 }
20172 /*
20173  *  Array built-ins
20174  *
20175  *  Note that most Array built-ins are intentionally generic and work even
20176  *  when the 'this' binding is not an Array instance.  To ensure this,
20177  *  Array algorithms do not assume "magical" Array behavior for the "length"
20178  *  property, for instance.
20179  *
20180  *  XXX: the "Throw" flag should be set for (almost?) all [[Put]] and
20181  *  [[Delete]] operations, but it's currently false throughout.  Go through
20182  *  all put/delete cases and check throw flag use.  Need a new API primitive
20183  *  which allows throws flag to be specified.
20184  *
20185  *  XXX: array lengths above 2G won't work reliably.  There are many places
20186  *  where one needs a full signed 32-bit range ([-0xffffffff, 0xffffffff],
20187  *  i.e. -33- bits).  Although array 'length' cannot be written to be outside
20188  *  the unsigned 32-bit range (E5.1 Section 15.4.5.1 throws a RangeError if so)
20189  *  some intermediate values may be above 0xffffffff and this may not be always
20190  *  correctly handled now (duk_uint32_t is not enough for all algorithms).
20191  *
20192  *  For instance, push() can legitimately write entries beyond length 0xffffffff
20193  *  and cause a RangeError only at the end.  To do this properly, the current
20194  *  push() implementation tracks the array index using a 'double' instead of a
20195  *  duk_uint32_t (which is somewhat awkward).  See test-bi-array-push-maxlen.js.
20196  *
20197  *  On using "put" vs. "def" prop
20198  *  =============================
20199  *
20200  *  Code below must be careful to use the appropriate primitive as it matters
20201  *  for compliance.  When using "put" there may be inherited properties in
20202  *  Array.prototype which cause side effects when values are written.  When
20203  *  using "define" there are no such side effects, and many test262 test cases
20204  *  check for this (for real world code, such side effects are very rare).
20205  *  Both "put" and "define" are used in the E5.1 specification; as a rule,
20206  *  "put" is used when modifying an existing array (or a non-array 'this'
20207  *  binding) and "define" for setting values into a fresh result array.
20208  *
20209  *  Also note that Array instance 'length' should be writable, but not
20210  *  enumerable and definitely not configurable: even Duktape code internally
20211  *  assumes that an Array instance will always have a 'length' property.
20212  *  Preventing deletion of the property is critical.
20213  */
20214 
20215 /* include removed: duk_internal.h */
20216 
20217 /* Perform an intermediate join when this many elements have been pushed
20218  * on the value stack.
20219  */
20220 #define  DUK__ARRAY_MID_JOIN_LIMIT  4096
20221 
20222 /* Shared entry code for many Array built-ins.  Note that length is left
20223  * on stack (it could be popped, but that's not necessary).
20224  */
duk__push_this_obj_len_u32(duk_context * ctx)20225 DUK_LOCAL duk_uint32_t duk__push_this_obj_len_u32(duk_context *ctx) {
20226 	duk_uint32_t len;
20227 
20228 	(void) duk_push_this_coercible_to_object(ctx);
20229 	duk_get_prop_stridx(ctx, -1, DUK_STRIDX_LENGTH);
20230 	len = duk_to_uint32(ctx, -1);
20231 
20232 	/* -> [ ... ToObject(this) ToUint32(length) ] */
20233 	return len;
20234 }
20235 
duk__push_this_obj_len_u32_limited(duk_context * ctx)20236 DUK_LOCAL duk_uint32_t duk__push_this_obj_len_u32_limited(duk_context *ctx) {
20237 	/* Range limited to [0, 0x7fffffff] range, i.e. range that can be
20238 	 * represented with duk_int32_t.  Use this when the method doesn't
20239 	 * handle the full 32-bit unsigned range correctly.
20240 	 */
20241 	duk_uint32_t ret = duk__push_this_obj_len_u32(ctx);
20242 	if (DUK_UNLIKELY(ret >= 0x80000000UL)) {
20243 		DUK_ERROR_RANGE((duk_hthread *) ctx, DUK_STR_ARRAY_LENGTH_OVER_2G);
20244 	}
20245 	return ret;
20246 }
20247 
20248 /*
20249  *  Constructor
20250  */
20251 
duk_bi_array_constructor(duk_context * ctx)20252 DUK_INTERNAL duk_ret_t duk_bi_array_constructor(duk_context *ctx) {
20253 	duk_idx_t nargs;
20254 	duk_double_t d;
20255 	duk_uint32_t len;
20256 	duk_idx_t i;
20257 
20258 	nargs = duk_get_top(ctx);
20259 	duk_push_array(ctx);
20260 
20261 	if (nargs == 1 && duk_is_number(ctx, 0)) {
20262 		/* XXX: expensive check (also shared elsewhere - so add a shared internal API call?) */
20263 		d = duk_get_number(ctx, 0);
20264 		len = duk_to_uint32(ctx, 0);
20265 		if (((duk_double_t) len) != d) {
20266 			return DUK_RET_RANGE_ERROR;
20267 		}
20268 
20269 		/* XXX: if 'len' is low, may want to ensure array part is kept:
20270 		 * the caller is likely to want a dense array.
20271 		 */
20272 		duk_push_u32(ctx, len);
20273 		duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W);  /* [ ToUint32(len) array ToUint32(len) ] -> [ ToUint32(len) array ] */
20274 		return 1;
20275 	}
20276 
20277 	/* XXX: optimize by creating array into correct size directly, and
20278 	 * operating on the array part directly; values can be memcpy()'d from
20279 	 * value stack directly as long as refcounts are increased.
20280 	 */
20281 	for (i = 0; i < nargs; i++) {
20282 		duk_dup(ctx, i);
20283 		duk_xdef_prop_index_wec(ctx, -2, (duk_uarridx_t) i);
20284 	}
20285 
20286 	duk_push_u32(ctx, (duk_uint32_t) nargs);
20287 	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W);
20288 	return 1;
20289 }
20290 
20291 /*
20292  *  isArray()
20293  */
20294 
duk_bi_array_constructor_is_array(duk_context * ctx)20295 DUK_INTERNAL duk_ret_t duk_bi_array_constructor_is_array(duk_context *ctx) {
20296 	duk_hobject *h;
20297 
20298 	h = duk_get_hobject_with_class(ctx, 0, DUK_HOBJECT_CLASS_ARRAY);
20299 	duk_push_boolean(ctx, (h != NULL));
20300 	return 1;
20301 }
20302 
20303 /*
20304  *  toString()
20305  */
20306 
duk_bi_array_prototype_to_string(duk_context * ctx)20307 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_to_string(duk_context *ctx) {
20308 	(void) duk_push_this_coercible_to_object(ctx);
20309 	duk_get_prop_stridx(ctx, -1, DUK_STRIDX_JOIN);
20310 
20311 	/* [ ... this func ] */
20312 	if (!duk_is_callable(ctx, -1)) {
20313 		/* Fall back to the initial (original) Object.toString().  We don't
20314 		 * currently have pointers to the built-in functions, only the top
20315 		 * level global objects (like "Array") so this is now done in a bit
20316 		 * of a hacky manner.  It would be cleaner to push the (original)
20317 		 * function and use duk_call_method().
20318 		 */
20319 
20320 		/* XXX: 'this' will be ToObject() coerced twice, which is incorrect
20321 		 * but should have no visible side effects.
20322 		 */
20323 		DUK_DDD(DUK_DDDPRINT("this.join is not callable, fall back to (original) Object.toString"));
20324 		duk_set_top(ctx, 0);
20325 		return duk_bi_object_prototype_to_string(ctx);  /* has access to 'this' binding */
20326 	}
20327 
20328 	/* [ ... this func ] */
20329 
20330 	duk_insert(ctx, -2);
20331 
20332 	/* [ ... func this ] */
20333 
20334 	DUK_DDD(DUK_DDDPRINT("calling: func=%!iT, this=%!iT",
20335 	                     (duk_tval *) duk_get_tval(ctx, -2),
20336 	                     (duk_tval *) duk_get_tval(ctx, -1)));
20337 	duk_call_method(ctx, 0);
20338 
20339 	return 1;
20340 }
20341 
20342 /*
20343  *  concat()
20344  */
20345 
duk_bi_array_prototype_concat(duk_context * ctx)20346 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_concat(duk_context *ctx) {
20347 	duk_idx_t i, n;
20348 	duk_uarridx_t idx, idx_last;
20349 	duk_uarridx_t j, len;
20350 	duk_hobject *h;
20351 
20352 	/* XXX: the insert here is a bit expensive if there are a lot of items.
20353 	 * It could also be special cased in the outermost for loop quite easily
20354 	 * (as the element is dup()'d anyway).
20355 	 */
20356 
20357 	(void) duk_push_this_coercible_to_object(ctx);
20358 	duk_insert(ctx, 0);
20359 	n = duk_get_top(ctx);
20360 	duk_push_array(ctx);  /* -> [ ToObject(this) item1 ... itemN arr ] */
20361 
20362 	/* NOTE: The Array special behaviors are NOT invoked by duk_xdef_prop_index()
20363 	 * (which differs from the official algorithm).  If no error is thrown, this
20364 	 * doesn't matter as the length is updated at the end.  However, if an error
20365 	 * is thrown, the length will be unset.  That shouldn't matter because the
20366 	 * caller won't get a reference to the intermediate value.
20367 	 */
20368 
20369 	idx = 0;
20370 	idx_last = 0;
20371 	for (i = 0; i < n; i++) {
20372 		DUK_ASSERT_TOP(ctx, n + 1);
20373 
20374 		/* [ ToObject(this) item1 ... itemN arr ] */
20375 
20376 		duk_dup(ctx, i);
20377 		h = duk_get_hobject_with_class(ctx, -1, DUK_HOBJECT_CLASS_ARRAY);
20378 		if (!h) {
20379 			duk_xdef_prop_index_wec(ctx, -2, idx++);
20380 			idx_last = idx;
20381 			continue;
20382 		}
20383 
20384 		/* [ ToObject(this) item1 ... itemN arr item(i) ] */
20385 
20386 		/* XXX: an array can have length higher than 32 bits; this is not handled
20387 		 * correctly now.
20388 		 */
20389 		len = (duk_uarridx_t) duk_get_length(ctx, -1);
20390 		for (j = 0; j < len; j++) {
20391 			if (duk_get_prop_index(ctx, -1, j)) {
20392 				/* [ ToObject(this) item1 ... itemN arr item(i) item(i)[j] ] */
20393 				duk_xdef_prop_index_wec(ctx, -3, idx++);
20394 				idx_last = idx;
20395 			} else {
20396 				idx++;
20397 				duk_pop(ctx);
20398 #if defined(DUK_USE_NONSTD_ARRAY_CONCAT_TRAILER)
20399 				/* According to E5.1 Section 15.4.4.4 nonexistent trailing
20400 				 * elements do not affect 'length' of the result.  Test262
20401 				 * and other engines disagree, so update idx_last here too.
20402 				 */
20403 				idx_last = idx;
20404 #else
20405 				/* Strict standard behavior, ignore trailing elements for
20406 				 * result 'length'.
20407 				 */
20408 #endif
20409 			}
20410 		}
20411 		duk_pop(ctx);
20412 	}
20413 
20414 	/* The E5.1 Section 15.4.4.4 algorithm doesn't set the length explicitly
20415 	 * in the end, but because we're operating with an internal value which
20416 	 * is known to be an array, this should be equivalent.
20417 	 */
20418 	duk_push_uarridx(ctx, idx_last);
20419 	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W);
20420 
20421 	DUK_ASSERT_TOP(ctx, n + 1);
20422 	return 1;
20423 }
20424 
20425 /*
20426  *  join(), toLocaleString()
20427  *
20428  *  Note: checking valstack is necessary, but only in the per-element loop.
20429  *
20430  *  Note: the trivial approach of pushing all the elements on the value stack
20431  *  and then calling duk_join() fails when the array contains a large number
20432  *  of elements.  This problem can't be offloaded to duk_join() because the
20433  *  elements to join must be handled here and have special handling.  Current
20434  *  approach is to do intermediate joins with very large number of elements.
20435  *  There is no fancy handling; the prefix gets re-joined multiple times.
20436  */
20437 
duk_bi_array_prototype_join_shared(duk_context * ctx)20438 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_join_shared(duk_context *ctx) {
20439 	duk_uint32_t len, count;
20440 	duk_uint32_t idx;
20441 	duk_small_int_t to_locale_string = duk_get_current_magic(ctx);
20442 	duk_idx_t valstack_required;
20443 
20444 	/* For join(), nargs is 1.  For toLocaleString(), nargs is 0 and
20445 	 * setting the top essentially pushes an undefined to the stack,
20446 	 * thus defaulting to a comma separator.
20447 	 */
20448 	duk_set_top(ctx, 1);
20449 	if (duk_is_undefined(ctx, 0)) {
20450 		duk_pop(ctx);
20451 		duk_push_hstring_stridx(ctx, DUK_STRIDX_COMMA);
20452 	} else {
20453 		duk_to_string(ctx, 0);
20454 	}
20455 
20456 	len = duk__push_this_obj_len_u32(ctx);
20457 
20458 	/* [ sep ToObject(this) len ] */
20459 
20460 	DUK_DDD(DUK_DDDPRINT("sep=%!T, this=%!T, len=%lu",
20461 	                     (duk_tval *) duk_get_tval(ctx, 0),
20462 	                     (duk_tval *) duk_get_tval(ctx, 1),
20463 	                     (unsigned long) len));
20464 
20465 	/* The extra (+4) is tight. */
20466 	valstack_required = (len >= DUK__ARRAY_MID_JOIN_LIMIT ?
20467 	                     DUK__ARRAY_MID_JOIN_LIMIT : len) + 4;
20468 	duk_require_stack(ctx, valstack_required);
20469 
20470 	duk_dup(ctx, 0);
20471 
20472 	/* [ sep ToObject(this) len sep ] */
20473 
20474 	count = 0;
20475 	idx = 0;
20476 	for (;;) {
20477 		if (count >= DUK__ARRAY_MID_JOIN_LIMIT ||   /* intermediate join to avoid valstack overflow */
20478 		    idx >= len) { /* end of loop (careful with len==0) */
20479 			/* [ sep ToObject(this) len sep str0 ... str(count-1) ] */
20480 			DUK_DDD(DUK_DDDPRINT("mid/final join, count=%ld, idx=%ld, len=%ld",
20481 			                     (long) count, (long) idx, (long) len));
20482 			duk_join(ctx, (duk_idx_t) count);  /* -> [ sep ToObject(this) len str ] */
20483 			duk_dup(ctx, 0);                   /* -> [ sep ToObject(this) len str sep ] */
20484 			duk_insert(ctx, -2);               /* -> [ sep ToObject(this) len sep str ] */
20485 			count = 1;
20486 		}
20487 		if (idx >= len) {
20488 			/* if true, the stack already contains the final result */
20489 			break;
20490 		}
20491 
20492 		duk_get_prop_index(ctx, 1, (duk_uarridx_t) idx);
20493 		if (duk_is_null_or_undefined(ctx, -1)) {
20494 			duk_pop(ctx);
20495 			duk_push_hstring_stridx(ctx, DUK_STRIDX_EMPTY_STRING);
20496 		} else {
20497 			if (to_locale_string) {
20498 				duk_to_object(ctx, -1);
20499 				duk_get_prop_stridx(ctx, -1, DUK_STRIDX_TO_LOCALE_STRING);
20500 				duk_insert(ctx, -2);  /* -> [ ... toLocaleString ToObject(val) ] */
20501 				duk_call_method(ctx, 0);
20502 				duk_to_string(ctx, -1);
20503 			} else {
20504 				duk_to_string(ctx, -1);
20505 			}
20506 		}
20507 
20508 		count++;
20509 		idx++;
20510 	}
20511 
20512 	/* [ sep ToObject(this) len sep result ] */
20513 
20514 	return 1;
20515 }
20516 
20517 /*
20518  *  pop(), push()
20519  */
20520 
duk_bi_array_prototype_pop(duk_context * ctx)20521 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_pop(duk_context *ctx) {
20522 	duk_uint32_t len;
20523 	duk_uint32_t idx;
20524 
20525 	DUK_ASSERT_TOP(ctx, 0);
20526 	len = duk__push_this_obj_len_u32(ctx);
20527 	if (len == 0) {
20528 		duk_push_int(ctx, 0);
20529 		duk_put_prop_stridx(ctx, 0, DUK_STRIDX_LENGTH);
20530 		return 0;
20531 	}
20532 	idx = len - 1;
20533 
20534 	duk_get_prop_index(ctx, 0, (duk_uarridx_t) idx);
20535 	duk_del_prop_index(ctx, 0, (duk_uarridx_t) idx);
20536 	duk_push_u32(ctx, idx);
20537 	duk_put_prop_stridx(ctx, 0, DUK_STRIDX_LENGTH);
20538 	return 1;
20539 }
20540 
duk_bi_array_prototype_push(duk_context * ctx)20541 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_push(duk_context *ctx) {
20542 	/* Note: 'this' is not necessarily an Array object.  The push()
20543 	 * algorithm is supposed to work for other kinds of objects too,
20544 	 * so the algorithm has e.g. an explicit update for the 'length'
20545 	 * property which is normally "magical" in arrays.
20546 	 */
20547 
20548 	duk_uint32_t len;
20549 	duk_idx_t i, n;
20550 
20551 	n = duk_get_top(ctx);
20552 	len = duk__push_this_obj_len_u32(ctx);
20553 
20554 	/* [ arg1 ... argN obj length ] */
20555 
20556 	/* Technically Array.prototype.push() can create an Array with length
20557 	 * longer than 2^32-1, i.e. outside the 32-bit range.  The final length
20558 	 * is *not* wrapped to 32 bits in the specification.
20559 	 *
20560 	 * This implementation tracks length with a uint32 because it's much
20561 	 * more practical.
20562 	 *
20563 	 * See: test-bi-array-push-maxlen.js.
20564 	 */
20565 
20566 	if (len + (duk_uint32_t) n < len) {
20567 		DUK_D(DUK_DPRINT("Array.prototype.push() would go beyond 32-bit length, throw"));
20568 		return DUK_RET_RANGE_ERROR;
20569 	}
20570 
20571 	for (i = 0; i < n; i++) {
20572 		duk_dup(ctx, i);
20573 		duk_put_prop_index(ctx, -3, len + i);
20574 	}
20575 	len += n;
20576 
20577 	duk_push_u32(ctx, len);
20578 	duk_dup_top(ctx);
20579 	duk_put_prop_stridx(ctx, -4, DUK_STRIDX_LENGTH);
20580 
20581 	/* [ arg1 ... argN obj length new_length ] */
20582 	return 1;
20583 }
20584 
20585 /*
20586  *  sort()
20587  *
20588  *  Currently qsort with random pivot.  This is now really, really slow,
20589  *  because there is no fast path for array parts.
20590  *
20591  *  Signed indices are used because qsort() leaves and degenerate cases
20592  *  may use a negative offset.
20593  */
20594 
duk__array_sort_compare(duk_context * ctx,duk_int_t idx1,duk_int_t idx2)20595 DUK_LOCAL duk_small_int_t duk__array_sort_compare(duk_context *ctx, duk_int_t idx1, duk_int_t idx2) {
20596 	duk_bool_t have1, have2;
20597 	duk_bool_t undef1, undef2;
20598 	duk_small_int_t ret;
20599 	duk_idx_t idx_obj = 1;  /* fixed offsets in valstack */
20600 	duk_idx_t idx_fn = 0;
20601 	duk_hstring *h1, *h2;
20602 
20603 	/* Fast exit if indices are identical.  This is valid for a non-existent property,
20604 	 * for an undefined value, and almost always for ToString() coerced comparison of
20605 	 * arbitrary values (corner cases where this is not the case include e.g. a an
20606 	 * object with varying ToString() coercion).
20607 	 *
20608 	 * The specification does not prohibit "caching" of values read from the array, so
20609 	 * assuming equality for comparing an index with itself falls into the category of
20610 	 * "caching".
20611 	 *
20612 	 * Also, compareFn may be inconsistent, so skipping a call to compareFn here may
20613 	 * have an effect on the final result.  The specification does not require any
20614 	 * specific behavior for inconsistent compare functions, so again, this fast path
20615 	 * is OK.
20616 	 */
20617 
20618 	if (idx1 == idx2) {
20619 		DUK_DDD(DUK_DDDPRINT("duk__array_sort_compare: idx1=%ld, idx2=%ld -> indices identical, quick exit",
20620 		                     (long) idx1, (long) idx2));
20621 		return 0;
20622 	}
20623 
20624 	have1 = duk_get_prop_index(ctx, idx_obj, (duk_uarridx_t) idx1);
20625 	have2 = duk_get_prop_index(ctx, idx_obj, (duk_uarridx_t) idx2);
20626 
20627 	DUK_DDD(DUK_DDDPRINT("duk__array_sort_compare: idx1=%ld, idx2=%ld, have1=%ld, have2=%ld, val1=%!T, val2=%!T",
20628 	                     (long) idx1, (long) idx2, (long) have1, (long) have2,
20629 	                     (duk_tval *) duk_get_tval(ctx, -2), (duk_tval *) duk_get_tval(ctx, -1)));
20630 
20631 	if (have1) {
20632 		if (have2) {
20633 			;
20634 		} else {
20635 			ret = -1;
20636 			goto pop_ret;
20637 		}
20638 	} else {
20639 		if (have2) {
20640 			ret = 1;
20641 			goto pop_ret;
20642 		} else {
20643 			ret = 0;
20644 			goto pop_ret;
20645 		}
20646 	}
20647 
20648 	undef1 = duk_is_undefined(ctx, -2);
20649 	undef2 = duk_is_undefined(ctx, -1);
20650 	if (undef1) {
20651 		if (undef2) {
20652 			ret = 0;
20653 			goto pop_ret;
20654 		} else {
20655 			ret = 1;
20656 			goto pop_ret;
20657 		}
20658 	} else {
20659 		if (undef2) {
20660 			ret = -1;
20661 			goto pop_ret;
20662 		} else {
20663 			;
20664 		}
20665 	}
20666 
20667 	if (!duk_is_undefined(ctx, idx_fn)) {
20668 		duk_double_t d;
20669 
20670 		/* no need to check callable; duk_call() will do that */
20671 		duk_dup(ctx, idx_fn);    /* -> [ ... x y fn ] */
20672 		duk_insert(ctx, -3);     /* -> [ ... fn x y ] */
20673 		duk_call(ctx, 2);        /* -> [ ... res ] */
20674 
20675 		/* The specification is a bit vague what to do if the return
20676 		 * value is not a number.  Other implementations seem to
20677 		 * tolerate non-numbers but e.g. V8 won't apparently do a
20678 		 * ToNumber().
20679 		 */
20680 
20681 		/* XXX: best behavior for real world compatibility? */
20682 
20683 		d = duk_to_number(ctx, -1);
20684 		if (d < 0.0) {
20685 			ret = -1;
20686 		} else if (d > 0.0) {
20687 			ret = 1;
20688 		} else {
20689 			ret = 0;
20690 		}
20691 
20692 		duk_pop(ctx);
20693 		DUK_DDD(DUK_DDDPRINT("-> result %ld (from comparefn, after coercion)", (long) ret));
20694 		return ret;
20695 	}
20696 
20697 	/* string compare is the default (a bit oddly) */
20698 
20699 	h1 = duk_to_hstring(ctx, -2);
20700 	h2 = duk_to_hstring(ctx, -1);
20701 	DUK_ASSERT(h1 != NULL);
20702 	DUK_ASSERT(h2 != NULL);
20703 
20704 	ret = duk_js_string_compare(h1, h2);  /* retval is directly usable */
20705 	goto pop_ret;
20706 
20707  pop_ret:
20708 	duk_pop_2(ctx);
20709 	DUK_DDD(DUK_DDDPRINT("-> result %ld", (long) ret));
20710 	return ret;
20711 }
20712 
duk__array_sort_swap(duk_context * ctx,duk_int_t l,duk_int_t r)20713 DUK_LOCAL void duk__array_sort_swap(duk_context *ctx, duk_int_t l, duk_int_t r) {
20714 	duk_bool_t have_l, have_r;
20715 	duk_idx_t idx_obj = 1;  /* fixed offset in valstack */
20716 
20717 	if (l == r) {
20718 		return;
20719 	}
20720 
20721 	/* swap elements; deal with non-existent elements correctly */
20722 	have_l = duk_get_prop_index(ctx, idx_obj, (duk_uarridx_t) l);
20723 	have_r = duk_get_prop_index(ctx, idx_obj, (duk_uarridx_t) r);
20724 
20725 	if (have_r) {
20726 		/* right exists, [[Put]] regardless whether or not left exists */
20727 		duk_put_prop_index(ctx, idx_obj, (duk_uarridx_t) l);
20728 	} else {
20729 		duk_del_prop_index(ctx, idx_obj, (duk_uarridx_t) l);
20730 		duk_pop(ctx);
20731 	}
20732 
20733 	if (have_l) {
20734 		duk_put_prop_index(ctx, idx_obj, (duk_uarridx_t) r);
20735 	} else {
20736 		duk_del_prop_index(ctx, idx_obj, (duk_uarridx_t) r);
20737 		duk_pop(ctx);
20738 	}
20739 }
20740 
20741 #if defined(DUK_USE_DDDPRINT)
20742 /* Debug print which visualizes the qsort partitioning process. */
duk__debuglog_qsort_state(duk_context * ctx,duk_int_t lo,duk_int_t hi,duk_int_t pivot)20743 DUK_LOCAL void duk__debuglog_qsort_state(duk_context *ctx, duk_int_t lo, duk_int_t hi, duk_int_t pivot) {
20744 	char buf[4096];
20745 	char *ptr = buf;
20746 	duk_int_t i, n;
20747 	n = (duk_int_t) duk_get_length(ctx, 1);
20748 	if (n > 4000) {
20749 		n = 4000;
20750 	}
20751 	*ptr++ = '[';
20752 	for (i = 0; i < n; i++) {
20753 		if (i == pivot) {
20754 			*ptr++ = '|';
20755 		} else if (i == lo) {
20756 			*ptr++ = '<';
20757 		} else if (i == hi) {
20758 			*ptr++ = '>';
20759 		} else if (i >= lo && i <= hi) {
20760 			*ptr++ = '-';
20761 		} else {
20762 			*ptr++ = ' ';
20763 		}
20764 	}
20765 	*ptr++ = ']';
20766 	*ptr++ = '\0';
20767 
20768 	DUK_DDD(DUK_DDDPRINT("%s   (lo=%ld, hi=%ld, pivot=%ld)",
20769 	                     (const char *) buf, (long) lo, (long) hi, (long) pivot));
20770 }
20771 #endif
20772 
duk__array_qsort(duk_context * ctx,duk_int_t lo,duk_int_t hi)20773 DUK_LOCAL void duk__array_qsort(duk_context *ctx, duk_int_t lo, duk_int_t hi) {
20774 	duk_hthread *thr = (duk_hthread *) ctx;
20775 	duk_int_t p, l, r;
20776 
20777 	/* The lo/hi indices may be crossed and hi < 0 is possible at entry. */
20778 
20779 	DUK_DDD(DUK_DDDPRINT("duk__array_qsort: lo=%ld, hi=%ld, obj=%!T",
20780 	                     (long) lo, (long) hi, (duk_tval *) duk_get_tval(ctx, 1)));
20781 
20782 	DUK_ASSERT_TOP(ctx, 3);
20783 
20784 	/* In some cases it may be that lo > hi, or hi < 0; these
20785 	 * degenerate cases happen e.g. for empty arrays, and in
20786 	 * recursion leaves.
20787 	 */
20788 
20789 	/* trivial cases */
20790 	if (hi - lo < 1) {
20791 		DUK_DDD(DUK_DDDPRINT("degenerate case, return immediately"));
20792 		return;
20793 	}
20794 	DUK_ASSERT(hi > lo);
20795 	DUK_ASSERT(hi - lo + 1 >= 2);
20796 
20797 	/* randomized pivot selection */
20798 	p = lo + (duk_util_tinyrandom_get_bits(thr, 30) % (hi - lo + 1));  /* rnd in [lo,hi] */
20799 	DUK_ASSERT(p >= lo && p <= hi);
20800 	DUK_DDD(DUK_DDDPRINT("lo=%ld, hi=%ld, chose pivot p=%ld",
20801 	                     (long) lo, (long) hi, (long) p));
20802 
20803 	/* move pivot out of the way */
20804 	duk__array_sort_swap(ctx, p, lo);
20805 	p = lo;
20806 	DUK_DDD(DUK_DDDPRINT("pivot moved out of the way: %!T", (duk_tval *) duk_get_tval(ctx, 1)));
20807 
20808 	l = lo + 1;
20809 	r = hi;
20810 	for (;;) {
20811 		/* find elements to swap */
20812 		for (;;) {
20813 			DUK_DDD(DUK_DDDPRINT("left scan: l=%ld, r=%ld, p=%ld",
20814 			                     (long) l, (long) r, (long) p));
20815 			if (l >= hi) {
20816 				break;
20817 			}
20818 			if (duk__array_sort_compare(ctx, l, p) >= 0) {  /* !(l < p) */
20819 				break;
20820 			}
20821 			l++;
20822 		}
20823 		for (;;) {
20824 			DUK_DDD(DUK_DDDPRINT("right scan: l=%ld, r=%ld, p=%ld",
20825 			                     (long) l, (long) r, (long) p));
20826 			if (r <= lo) {
20827 				break;
20828 			}
20829 			if (duk__array_sort_compare(ctx, p, r) >= 0) {  /* !(p < r) */
20830 				break;
20831 			}
20832 			r--;
20833 		}
20834 		if (l >= r) {
20835 			goto done;
20836 		}
20837 		DUK_ASSERT(l < r);
20838 
20839 		DUK_DDD(DUK_DDDPRINT("swap %ld and %ld", (long) l, (long) r));
20840 
20841 		duk__array_sort_swap(ctx, l, r);
20842 
20843 		DUK_DDD(DUK_DDDPRINT("after swap: %!T", (duk_tval *) duk_get_tval(ctx, 1)));
20844 		l++;
20845 		r--;
20846 	}
20847  done:
20848 	/* Note that 'l' and 'r' may cross, i.e. r < l */
20849 	DUK_ASSERT(l >= lo && l <= hi);
20850 	DUK_ASSERT(r >= lo && r <= hi);
20851 
20852 	/* XXX: there's no explicit recursion bound here now.  For the average
20853 	 * qsort recursion depth O(log n) that's not really necessary: e.g. for
20854 	 * 2**32 recursion depth would be about 32 which is OK.  However, qsort
20855 	 * worst case recursion depth is O(n) which may be a problem.
20856 	 */
20857 
20858 	/* move pivot to its final place */
20859 	DUK_DDD(DUK_DDDPRINT("before final pivot swap: %!T", (duk_tval *) duk_get_tval(ctx, 1)));
20860 	duk__array_sort_swap(ctx, lo, r);
20861 
20862 #if defined(DUK_USE_DDDPRINT)
20863 	duk__debuglog_qsort_state(ctx, lo, hi, r);
20864 #endif
20865 
20866 	DUK_DDD(DUK_DDDPRINT("recurse: pivot=%ld, obj=%!T", (long) r, (duk_tval *) duk_get_tval(ctx, 1)));
20867 	duk__array_qsort(ctx, lo, r - 1);
20868 	duk__array_qsort(ctx, r + 1, hi);
20869 }
20870 
duk_bi_array_prototype_sort(duk_context * ctx)20871 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_sort(duk_context *ctx) {
20872 	duk_uint32_t len;
20873 
20874 	/* XXX: len >= 0x80000000 won't work below because a signed type
20875 	 * is needed by qsort.
20876 	 */
20877 	len = duk__push_this_obj_len_u32_limited(ctx);
20878 
20879 	/* stack[0] = compareFn
20880 	 * stack[1] = ToObject(this)
20881 	 * stack[2] = ToUint32(length)
20882 	 */
20883 
20884 	if (len > 0) {
20885 		/* avoid degenerate cases, so that (len - 1) won't underflow */
20886 		duk__array_qsort(ctx, (duk_int_t) 0, (duk_int_t) (len - 1));
20887 	}
20888 
20889 	DUK_ASSERT_TOP(ctx, 3);
20890 	duk_pop(ctx);
20891 	return 1;  /* return ToObject(this) */
20892 }
20893 
20894 /*
20895  *  splice()
20896  */
20897 
20898 /* XXX: this compiles to over 500 bytes now, even without special handling
20899  * for an array part.  Uses signed ints so does not handle full array range correctly.
20900  */
20901 
20902 /* XXX: can shift() / unshift() use the same helper?
20903  *   shift() is (close to?) <--> splice(0, 1)
20904  *   unshift is (close to?) <--> splice(0, 0, [items])?
20905  */
20906 
duk_bi_array_prototype_splice(duk_context * ctx)20907 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_splice(duk_context *ctx) {
20908 	duk_idx_t nargs;
20909 	duk_uint32_t len;
20910 	duk_bool_t have_delcount;
20911 	duk_int_t item_count;
20912 	duk_int_t act_start;
20913 	duk_int_t del_count;
20914 	duk_int_t i, n;
20915 
20916 	DUK_UNREF(have_delcount);
20917 
20918 	nargs = duk_get_top(ctx);
20919 	if (nargs < 2) {
20920 		duk_set_top(ctx, 2);
20921 		nargs = 2;
20922 		have_delcount = 0;
20923 	} else {
20924 		have_delcount = 1;
20925 	}
20926 
20927 	/* XXX: len >= 0x80000000 won't work below because we need to be
20928 	 * able to represent -len.
20929 	 */
20930 	len = duk__push_this_obj_len_u32_limited(ctx);
20931 
20932 	act_start = duk_to_int_clamped(ctx, 0, -((duk_int_t) len), (duk_int_t) len);
20933 	if (act_start < 0) {
20934 		act_start = len + act_start;
20935 	}
20936 	DUK_ASSERT(act_start >= 0 && act_start <= (duk_int_t) len);
20937 
20938 #ifdef DUK_USE_NONSTD_ARRAY_SPLICE_DELCOUNT
20939 	if (have_delcount) {
20940 #endif
20941 		del_count = duk_to_int_clamped(ctx, 1, 0, len - act_start);
20942 #ifdef DUK_USE_NONSTD_ARRAY_SPLICE_DELCOUNT
20943 	} else {
20944 		/* E5.1 standard behavior when deleteCount is not given would be
20945 		 * to treat it just like if 'undefined' was given, which coerces
20946 		 * ultimately to 0.  Real world behavior is to splice to the end
20947 		 * of array, see test-bi-array-proto-splice-no-delcount.js.
20948 		 */
20949 		del_count = len - act_start;
20950 	}
20951 #endif
20952 
20953 	DUK_ASSERT(nargs >= 2);
20954 	item_count = (duk_int_t) (nargs - 2);
20955 
20956 	DUK_ASSERT(del_count >= 0 && del_count <= (duk_int_t) len - act_start);
20957 	DUK_ASSERT(del_count + act_start <= (duk_int_t) len);
20958 
20959 	/* For now, restrict result array into 32-bit length range. */
20960 	if (((duk_double_t) len) - ((duk_double_t) del_count) + ((duk_double_t) item_count) > (duk_double_t) DUK_UINT32_MAX) {
20961 		DUK_D(DUK_DPRINT("Array.prototype.splice() would go beyond 32-bit length, throw"));
20962 		return DUK_RET_RANGE_ERROR;
20963 	}
20964 
20965 	duk_push_array(ctx);
20966 
20967 	/* stack[0] = start
20968 	 * stack[1] = deleteCount
20969 	 * stack[2...nargs-1] = items
20970 	 * stack[nargs] = ToObject(this)               -3
20971 	 * stack[nargs+1] = ToUint32(length)           -2
20972 	 * stack[nargs+2] = result array               -1
20973 	 */
20974 
20975 	DUK_ASSERT_TOP(ctx, nargs + 3);
20976 
20977 	/* Step 9: copy elements-to-be-deleted into the result array */
20978 
20979 	for (i = 0; i < del_count; i++) {
20980 		if (duk_get_prop_index(ctx, -3, (duk_uarridx_t) (act_start + i))) {
20981 			duk_xdef_prop_index_wec(ctx, -2, i);  /* throw flag irrelevant (false in std alg) */
20982 		} else {
20983 			duk_pop(ctx);
20984 		}
20985 	}
20986 	duk_push_u32(ctx, (duk_uint32_t) del_count);
20987 	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W);
20988 
20989 	/* Steps 12 and 13: reorganize elements to make room for itemCount elements */
20990 
20991 	if (item_count < del_count) {
20992 		/*    [ A B C D E F G H ]    rel_index = 2, del_count 3, item count 1
20993 		 * -> [ A B F G H ]          (conceptual intermediate step)
20994 		 * -> [ A B . F G H ]        (placeholder marked)
20995 		 *    [ A B C F G H ]        (actual result at this point, C will be replaced)
20996 		 */
20997 
20998 		DUK_ASSERT_TOP(ctx, nargs + 3);
20999 
21000 		n = len - del_count;
21001 		for (i = act_start; i < n; i++) {
21002 			if (duk_get_prop_index(ctx, -3, (duk_uarridx_t) (i + del_count))) {
21003 				duk_put_prop_index(ctx, -4, (duk_uarridx_t) (i + item_count));
21004 			} else {
21005 				duk_pop(ctx);
21006 				duk_del_prop_index(ctx, -3, (duk_uarridx_t) (i + item_count));
21007 			}
21008 		}
21009 
21010 		DUK_ASSERT_TOP(ctx, nargs + 3);
21011 
21012 		/* loop iterator init and limit changed from standard algorithm */
21013 		n = len - del_count + item_count;
21014 		for (i = len - 1; i >= n; i--) {
21015 			duk_del_prop_index(ctx, -3, (duk_uarridx_t) i);
21016 		}
21017 
21018 		DUK_ASSERT_TOP(ctx, nargs + 3);
21019 	} else if (item_count > del_count) {
21020 		/*    [ A B C D E F G H ]    rel_index = 2, del_count 3, item count 4
21021 		 * -> [ A B F G H ]          (conceptual intermediate step)
21022 		 * -> [ A B . . . . F G H ]  (placeholder marked)
21023 		 *    [ A B C D E F F G H ]  (actual result at this point)
21024 		 */
21025 
21026 		DUK_ASSERT_TOP(ctx, nargs + 3);
21027 
21028 		/* loop iterator init and limit changed from standard algorithm */
21029 		for (i = len - del_count - 1; i >= act_start; i--) {
21030 			if (duk_get_prop_index(ctx, -3, (duk_uarridx_t) (i + del_count))) {
21031 				duk_put_prop_index(ctx, -4, (duk_uarridx_t) (i + item_count));
21032 			} else {
21033 				duk_pop(ctx);
21034 				duk_del_prop_index(ctx, -3, (duk_uarridx_t) (i + item_count));
21035 			}
21036 		}
21037 
21038 		DUK_ASSERT_TOP(ctx, nargs + 3);
21039 	} else {
21040 		/*    [ A B C D E F G H ]    rel_index = 2, del_count 3, item count 3
21041 		 * -> [ A B F G H ]          (conceptual intermediate step)
21042 		 * -> [ A B . . . F G H ]    (placeholder marked)
21043 		 *    [ A B C D E F G H ]    (actual result at this point)
21044 		 */
21045 	}
21046 	DUK_ASSERT_TOP(ctx, nargs + 3);
21047 
21048 	/* Step 15: insert itemCount elements into the hole made above */
21049 
21050 	for (i = 0; i < item_count; i++) {
21051 		duk_dup(ctx, i + 2);  /* args start at index 2 */
21052 		duk_put_prop_index(ctx, -4, (duk_uarridx_t) (act_start + i));
21053 	}
21054 
21055 	/* Step 16: update length; note that the final length may be above 32 bit range
21056 	 * (but we checked above that this isn't the case here)
21057 	 */
21058 
21059 	duk_push_u32(ctx, len - del_count + item_count);
21060 	duk_put_prop_stridx(ctx, -4, DUK_STRIDX_LENGTH);
21061 
21062 	/* result array is already at the top of stack */
21063 	DUK_ASSERT_TOP(ctx, nargs + 3);
21064 	return 1;
21065 }
21066 
21067 /*
21068  *  reverse()
21069  */
21070 
duk_bi_array_prototype_reverse(duk_context * ctx)21071 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_reverse(duk_context *ctx) {
21072 	duk_uint32_t len;
21073 	duk_uint32_t middle;
21074 	duk_uint32_t lower, upper;
21075 	duk_bool_t have_lower, have_upper;
21076 
21077 	len = duk__push_this_obj_len_u32(ctx);
21078 	middle = len / 2;
21079 
21080 	/* If len <= 1, middle will be 0 and for-loop bails out
21081 	 * immediately (0 < 0 -> false).
21082 	 */
21083 
21084 	for (lower = 0; lower < middle; lower++) {
21085 		DUK_ASSERT(len >= 2);
21086 		DUK_ASSERT_TOP(ctx, 2);
21087 
21088 		DUK_ASSERT(len >= lower + 1);
21089 		upper = len - lower - 1;
21090 
21091 		have_lower = duk_get_prop_index(ctx, -2, (duk_uarridx_t) lower);
21092 		have_upper = duk_get_prop_index(ctx, -3, (duk_uarridx_t) upper);
21093 
21094 		/* [ ToObject(this) ToUint32(length) lowerValue upperValue ] */
21095 
21096 		if (have_upper) {
21097 			duk_put_prop_index(ctx, -4, (duk_uarridx_t) lower);
21098 		} else {
21099 			duk_del_prop_index(ctx, -4, (duk_uarridx_t) lower);
21100 			duk_pop(ctx);
21101 		}
21102 
21103 		if (have_lower) {
21104 			duk_put_prop_index(ctx, -3, (duk_uarridx_t) upper);
21105 		} else {
21106 			duk_del_prop_index(ctx, -3, (duk_uarridx_t) upper);
21107 			duk_pop(ctx);
21108 		}
21109 
21110 		DUK_ASSERT_TOP(ctx, 2);
21111 	}
21112 
21113 	DUK_ASSERT_TOP(ctx, 2);
21114 	duk_pop(ctx);  /* -> [ ToObject(this) ] */
21115 	return 1;
21116 }
21117 
21118 /*
21119  *  slice()
21120  */
21121 
duk_bi_array_prototype_slice(duk_context * ctx)21122 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_slice(duk_context *ctx) {
21123 	duk_uint32_t len;
21124 	duk_int_t start, end;
21125 	duk_int_t i;
21126 	duk_uarridx_t idx;
21127 	duk_uint32_t res_length = 0;
21128 
21129 	/* XXX: len >= 0x80000000 won't work below because we need to be
21130 	 * able to represent -len.
21131 	 */
21132 	len = duk__push_this_obj_len_u32_limited(ctx);
21133 	duk_push_array(ctx);
21134 
21135 	/* stack[0] = start
21136 	 * stack[1] = end
21137 	 * stack[2] = ToObject(this)
21138 	 * stack[3] = ToUint32(length)
21139 	 * stack[4] = result array
21140 	 */
21141 
21142 	start = duk_to_int_clamped(ctx, 0, -((duk_int_t) len), (duk_int_t) len);
21143 	if (start < 0) {
21144 		start = len + start;
21145 	}
21146 	/* XXX: could duk_is_undefined() provide defaulting undefined to 'len'
21147 	 * (the upper limit)?
21148 	 */
21149 	if (duk_is_undefined(ctx, 1)) {
21150 		end = len;
21151 	} else {
21152 		end = duk_to_int_clamped(ctx, 1, -((duk_int_t) len), (duk_int_t) len);
21153 		if (end < 0) {
21154 			end = len + end;
21155 		}
21156 	}
21157 	DUK_ASSERT(start >= 0 && (duk_uint32_t) start <= len);
21158 	DUK_ASSERT(end >= 0 && (duk_uint32_t) end <= len);
21159 
21160 	idx = 0;
21161 	for (i = start; i < end; i++) {
21162 		DUK_ASSERT_TOP(ctx, 5);
21163 		if (duk_get_prop_index(ctx, 2, (duk_uarridx_t) i)) {
21164 			duk_xdef_prop_index_wec(ctx, 4, idx);
21165 			res_length = idx + 1;
21166 		} else {
21167 			duk_pop(ctx);
21168 		}
21169 		idx++;
21170 		DUK_ASSERT_TOP(ctx, 5);
21171 	}
21172 
21173 	duk_push_u32(ctx, res_length);
21174 	duk_xdef_prop_stridx(ctx, 4, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W);
21175 
21176 	DUK_ASSERT_TOP(ctx, 5);
21177 	return 1;
21178 }
21179 
21180 /*
21181  *  shift()
21182  */
21183 
duk_bi_array_prototype_shift(duk_context * ctx)21184 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_shift(duk_context *ctx) {
21185 	duk_uint32_t len;
21186 	duk_uint32_t i;
21187 
21188 	len = duk__push_this_obj_len_u32(ctx);
21189 	if (len == 0) {
21190 		duk_push_int(ctx, 0);
21191 		duk_put_prop_stridx(ctx, 0, DUK_STRIDX_LENGTH);
21192 		return 0;
21193 	}
21194 
21195 	duk_get_prop_index(ctx, 0, 0);
21196 
21197 	/* stack[0] = object (this)
21198 	 * stack[1] = ToUint32(length)
21199 	 * stack[2] = elem at index 0 (retval)
21200 	 */
21201 
21202 	for (i = 1; i < len; i++) {
21203 		DUK_ASSERT_TOP(ctx, 3);
21204 		if (duk_get_prop_index(ctx, 0, (duk_uarridx_t) i)) {
21205 			/* fromPresent = true */
21206 			duk_put_prop_index(ctx, 0, (duk_uarridx_t) (i - 1));
21207 		} else {
21208 			/* fromPresent = false */
21209 			duk_del_prop_index(ctx, 0, (duk_uarridx_t) (i - 1));
21210 			duk_pop(ctx);
21211 		}
21212 	}
21213 	duk_del_prop_index(ctx, 0, (duk_uarridx_t) (len - 1));
21214 
21215 	duk_push_u32(ctx, (duk_uint32_t) (len - 1));
21216 	duk_put_prop_stridx(ctx, 0, DUK_STRIDX_LENGTH);
21217 
21218 	DUK_ASSERT_TOP(ctx, 3);
21219 	return 1;
21220 }
21221 
21222 /*
21223  *  unshift()
21224  */
21225 
duk_bi_array_prototype_unshift(duk_context * ctx)21226 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_unshift(duk_context *ctx) {
21227 	duk_idx_t nargs;
21228 	duk_uint32_t len;
21229 	duk_uint32_t i;
21230 
21231 	nargs = duk_get_top(ctx);
21232 	len = duk__push_this_obj_len_u32(ctx);
21233 
21234 	/* stack[0...nargs-1] = unshift args (vararg)
21235 	 * stack[nargs] = ToObject(this)
21236 	 * stack[nargs+1] = ToUint32(length)
21237 	 */
21238 
21239 	DUK_ASSERT_TOP(ctx, nargs + 2);
21240 
21241 	/* Note: unshift() may operate on indices above unsigned 32-bit range
21242 	 * and the final length may be >= 2**32.  However, we restrict the
21243 	 * final result to 32-bit range for practicality.
21244 	 */
21245 
21246 	if (len + (duk_uint32_t) nargs < len) {
21247 		DUK_D(DUK_DPRINT("Array.prototype.unshift() would go beyond 32-bit length, throw"));
21248 		return DUK_RET_RANGE_ERROR;
21249 	}
21250 
21251 	i = len;
21252 	while (i > 0) {
21253 		DUK_ASSERT_TOP(ctx, nargs + 2);
21254 		i--;
21255 		/* k+argCount-1; note that may be above 32-bit range */
21256 
21257 		if (duk_get_prop_index(ctx, -2, (duk_uarridx_t) i)) {
21258 			/* fromPresent = true */
21259 			/* [ ... ToObject(this) ToUint32(length) val ] */
21260 			duk_put_prop_index(ctx, -3, (duk_uarridx_t) (i + nargs));  /* -> [ ... ToObject(this) ToUint32(length) ] */
21261 		} else {
21262 			/* fromPresent = false */
21263 			/* [ ... ToObject(this) ToUint32(length) val ] */
21264 			duk_pop(ctx);
21265 			duk_del_prop_index(ctx, -2, (duk_uarridx_t) (i + nargs));  /* -> [ ... ToObject(this) ToUint32(length) ] */
21266 		}
21267 		DUK_ASSERT_TOP(ctx, nargs + 2);
21268 	}
21269 
21270 	for (i = 0; i < (duk_uint32_t) nargs; i++) {
21271 		DUK_ASSERT_TOP(ctx, nargs + 2);
21272 		duk_dup(ctx, i);  /* -> [ ... ToObject(this) ToUint32(length) arg[i] ] */
21273 		duk_put_prop_index(ctx, -3, (duk_uarridx_t) i);
21274 		DUK_ASSERT_TOP(ctx, nargs + 2);
21275 	}
21276 
21277 	DUK_ASSERT_TOP(ctx, nargs + 2);
21278 	duk_push_u32(ctx, len + nargs);
21279 	duk_dup_top(ctx);  /* -> [ ... ToObject(this) ToUint32(length) final_len final_len ] */
21280 	duk_put_prop_stridx(ctx, -4, DUK_STRIDX_LENGTH);
21281 	return 1;
21282 }
21283 
21284 /*
21285  *  indexOf(), lastIndexOf()
21286  */
21287 
duk_bi_array_prototype_indexof_shared(duk_context * ctx)21288 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_indexof_shared(duk_context *ctx) {
21289 	duk_idx_t nargs;
21290 	duk_int_t i, len;
21291 	duk_int_t from_index;
21292 	duk_small_int_t idx_step = duk_get_current_magic(ctx);  /* idx_step is +1 for indexOf, -1 for lastIndexOf */
21293 
21294 	/* lastIndexOf() needs to be a vararg function because we must distinguish
21295 	 * between an undefined fromIndex and a "not given" fromIndex; indexOf() is
21296 	 * made vararg for symmetry although it doesn't strictly need to be.
21297 	 */
21298 
21299 	nargs = duk_get_top(ctx);
21300 	duk_set_top(ctx, 2);
21301 
21302 	/* XXX: must be able to represent -len */
21303 	len = (duk_int_t) duk__push_this_obj_len_u32_limited(ctx);
21304 	if (len == 0) {
21305 		goto not_found;
21306 	}
21307 
21308 	/* Index clamping is a bit tricky, we must ensure that we'll only iterate
21309 	 * through elements that exist and that the specific requirements from E5.1
21310 	 * Sections 15.4.4.14 and 15.4.4.15 are fulfilled; especially:
21311 	 *
21312 	 *   - indexOf: clamp to [-len,len], negative handling -> [0,len],
21313 	 *     if clamped result is len, for-loop bails out immediately
21314 	 *
21315 	 *   - lastIndexOf: clamp to [-len-1, len-1], negative handling -> [-1, len-1],
21316 	 *     if clamped result is -1, for-loop bails out immediately
21317 	 *
21318 	 * If fromIndex is not given, ToInteger(undefined) = 0, which is correct
21319 	 * for indexOf() but incorrect for lastIndexOf().  Hence special handling,
21320 	 * and why lastIndexOf() needs to be a vararg function.
21321 	 */
21322 
21323 	if (nargs >= 2) {
21324 		/* indexOf: clamp fromIndex to [-len, len]
21325 		 * (if fromIndex == len, for-loop terminates directly)
21326 		 *
21327 		 * lastIndexOf: clamp fromIndex to [-len - 1, len - 1]
21328 		 * (if clamped to -len-1 -> fromIndex becomes -1, terminates for-loop directly)
21329 		 */
21330 		from_index = duk_to_int_clamped(ctx,
21331 		                                1,
21332 		                                (idx_step > 0 ? -len : -len - 1),
21333 		                                (idx_step > 0 ? len : len - 1));
21334 		if (from_index < 0) {
21335 			/* for lastIndexOf, result may be -1 (mark immediate termination) */
21336 			from_index = len + from_index;
21337 		}
21338 	} else {
21339 		/* for indexOf, ToInteger(undefined) would be 0, i.e. correct, but
21340 		 * handle both indexOf and lastIndexOf specially here.
21341 		 */
21342 		if (idx_step > 0) {
21343 			from_index = 0;
21344 		} else {
21345 			from_index = len - 1;
21346 		}
21347 	}
21348 
21349 	/* stack[0] = searchElement
21350 	 * stack[1] = fromIndex
21351 	 * stack[2] = object
21352 	 * stack[3] = length (not needed, but not popped above)
21353 	 */
21354 
21355 	for (i = from_index; i >= 0 && i < len; i += idx_step) {
21356 		DUK_ASSERT_TOP(ctx, 4);
21357 
21358 		if (duk_get_prop_index(ctx, 2, (duk_uarridx_t) i)) {
21359 			DUK_ASSERT_TOP(ctx, 5);
21360 			if (duk_strict_equals(ctx, 0, 4)) {
21361 				duk_push_int(ctx, i);
21362 				return 1;
21363 			}
21364 		}
21365 
21366 		duk_pop(ctx);
21367 	}
21368 
21369  not_found:
21370 	duk_push_int(ctx, -1);
21371 	return 1;
21372 }
21373 
21374 /*
21375  *  every(), some(), forEach(), map(), filter()
21376  */
21377 
21378 #define DUK__ITER_EVERY    0
21379 #define DUK__ITER_SOME     1
21380 #define DUK__ITER_FOREACH  2
21381 #define DUK__ITER_MAP      3
21382 #define DUK__ITER_FILTER   4
21383 
21384 /* XXX: This helper is a bit awkward because the handling for the different iteration
21385  * callers is quite different.  This now compiles to a bit less than 500 bytes, so with
21386  * 5 callers the net result is about 100 bytes / caller.
21387  */
21388 
duk_bi_array_prototype_iter_shared(duk_context * ctx)21389 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_iter_shared(duk_context *ctx) {
21390 	duk_uint32_t len;
21391 	duk_uint32_t i;
21392 	duk_uarridx_t k;
21393 	duk_bool_t bval;
21394 	duk_small_int_t iter_type = duk_get_current_magic(ctx);
21395 	duk_uint32_t res_length = 0;
21396 
21397 	/* each call this helper serves has nargs==2 */
21398 	DUK_ASSERT_TOP(ctx, 2);
21399 
21400 	len = duk__push_this_obj_len_u32(ctx);
21401 	duk_require_callable(ctx, 0);
21402 	/* if thisArg not supplied, behave as if undefined was supplied */
21403 
21404 	if (iter_type == DUK__ITER_MAP || iter_type == DUK__ITER_FILTER) {
21405 		duk_push_array(ctx);
21406 	} else {
21407 		duk_push_undefined(ctx);
21408 	}
21409 
21410 	/* stack[0] = callback
21411 	 * stack[1] = thisArg
21412 	 * stack[2] = object
21413 	 * stack[3] = ToUint32(length)  (unused, but avoid unnecessary pop)
21414 	 * stack[4] = result array (or undefined)
21415 	 */
21416 
21417 	k = 0;  /* result index for filter() */
21418 	for (i = 0; i < len; i++) {
21419 		DUK_ASSERT_TOP(ctx, 5);
21420 
21421 		if (!duk_get_prop_index(ctx, 2, (duk_uarridx_t) i)) {
21422 #if defined(DUK_USE_NONSTD_ARRAY_MAP_TRAILER)
21423 			/* Real world behavior for map(): trailing non-existent
21424 			 * elements don't invoke the user callback, but are still
21425 			 * counted towards result 'length'.
21426 			 */
21427 			if (iter_type == DUK__ITER_MAP) {
21428 				res_length = i + 1;
21429 			}
21430 #else
21431 			/* Standard behavior for map(): trailing non-existent
21432 			 * elements don't invoke the user callback and are not
21433 			 * counted towards result 'length'.
21434 			 */
21435 #endif
21436 			duk_pop(ctx);
21437 			continue;
21438 		}
21439 
21440 		/* The original value needs to be preserved for filter(), hence
21441 		 * this funny order.  We can't re-get the value because of side
21442 		 * effects.
21443 		 */
21444 
21445 		duk_dup(ctx, 0);
21446 		duk_dup(ctx, 1);
21447 		duk_dup(ctx, -3);
21448 		duk_push_u32(ctx, i);
21449 		duk_dup(ctx, 2);  /* [ ... val callback thisArg val i obj ] */
21450 		duk_call_method(ctx, 3); /* -> [ ... val retval ] */
21451 
21452 		switch (iter_type) {
21453 		case DUK__ITER_EVERY:
21454 			bval = duk_to_boolean(ctx, -1);
21455 			if (!bval) {
21456 				/* stack top contains 'false' */
21457 				return 1;
21458 			}
21459 			break;
21460 		case DUK__ITER_SOME:
21461 			bval = duk_to_boolean(ctx, -1);
21462 			if (bval) {
21463 				/* stack top contains 'true' */
21464 				return 1;
21465 			}
21466 			break;
21467 		case DUK__ITER_FOREACH:
21468 			/* nop */
21469 			break;
21470 		case DUK__ITER_MAP:
21471 			duk_dup(ctx, -1);
21472 			duk_xdef_prop_index_wec(ctx, 4, (duk_uarridx_t) i);  /* retval to result[i] */
21473 			res_length = i + 1;
21474 			break;
21475 		case DUK__ITER_FILTER:
21476 			bval = duk_to_boolean(ctx, -1);
21477 			if (bval) {
21478 				duk_dup(ctx, -2);  /* orig value */
21479 				duk_xdef_prop_index_wec(ctx, 4, (duk_uarridx_t) k);
21480 				k++;
21481 				res_length = k;
21482 			}
21483 			break;
21484 		default:
21485 			DUK_UNREACHABLE();
21486 			break;
21487 		}
21488 		duk_pop_2(ctx);
21489 
21490 		DUK_ASSERT_TOP(ctx, 5);
21491 	}
21492 
21493 	switch (iter_type) {
21494 	case DUK__ITER_EVERY:
21495 		duk_push_true(ctx);
21496 		break;
21497 	case DUK__ITER_SOME:
21498 		duk_push_false(ctx);
21499 		break;
21500 	case DUK__ITER_FOREACH:
21501 		duk_push_undefined(ctx);
21502 		break;
21503 	case DUK__ITER_MAP:
21504 	case DUK__ITER_FILTER:
21505 		DUK_ASSERT_TOP(ctx, 5);
21506 		DUK_ASSERT(duk_is_array(ctx, -1));  /* topmost element is the result array already */
21507 		duk_push_u32(ctx, res_length);
21508 		duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W);
21509 		break;
21510 	default:
21511 		DUK_UNREACHABLE();
21512 		break;
21513 	}
21514 
21515 	return 1;
21516 }
21517 
21518 /*
21519  *  reduce(), reduceRight()
21520  */
21521 
duk_bi_array_prototype_reduce_shared(duk_context * ctx)21522 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_reduce_shared(duk_context *ctx) {
21523 	duk_idx_t nargs;
21524 	duk_bool_t have_acc;
21525 	duk_uint32_t i, len;
21526 	duk_small_int_t idx_step = duk_get_current_magic(ctx);  /* idx_step is +1 for reduce, -1 for reduceRight */
21527 
21528 	/* We're a varargs function because we need to detect whether
21529 	 * initialValue was given or not.
21530 	 */
21531 	nargs = duk_get_top(ctx);
21532 	DUK_DDD(DUK_DDDPRINT("nargs=%ld", (long) nargs));
21533 
21534 	duk_set_top(ctx, 2);
21535 	len = duk__push_this_obj_len_u32(ctx);
21536 	if (!duk_is_callable(ctx, 0)) {
21537 		goto type_error;
21538 	}
21539 
21540 	/* stack[0] = callback fn
21541 	 * stack[1] = initialValue
21542 	 * stack[2] = object (coerced this)
21543 	 * stack[3] = length (not needed, but not popped above)
21544 	 * stack[4] = accumulator
21545 	 */
21546 
21547 	have_acc = 0;
21548 	if (nargs >= 2) {
21549 		duk_dup(ctx, 1);
21550 		have_acc = 1;
21551 	}
21552 	DUK_DDD(DUK_DDDPRINT("have_acc=%ld, acc=%!T",
21553 	                     (long) have_acc, (duk_tval *) duk_get_tval(ctx, 3)));
21554 
21555 	/* For len == 0, i is initialized to len - 1 which underflows.
21556 	 * The condition (i < len) will then exit the for-loop on the
21557 	 * first round which is correct.  Similarly, loop termination
21558 	 * happens by i underflowing.
21559 	 */
21560 
21561 	for (i = (idx_step >= 0 ? 0 : len - 1);
21562 	     i < len;  /* i >= 0 would always be true */
21563 	     i += idx_step) {
21564 		DUK_DDD(DUK_DDDPRINT("i=%ld, len=%ld, have_acc=%ld, top=%ld, acc=%!T",
21565 		                     (long) i, (long) len, (long) have_acc,
21566 		                     (long) duk_get_top(ctx),
21567 		                     (duk_tval *) duk_get_tval(ctx, 4)));
21568 
21569 		DUK_ASSERT((have_acc && duk_get_top(ctx) == 5) ||
21570 		           (!have_acc && duk_get_top(ctx) == 4));
21571 
21572 		if (!duk_has_prop_index(ctx, 2, (duk_uarridx_t) i)) {
21573 			continue;
21574 		}
21575 
21576 		if (!have_acc) {
21577 			DUK_ASSERT_TOP(ctx, 4);
21578 			duk_get_prop_index(ctx, 2, (duk_uarridx_t) i);
21579 			have_acc = 1;
21580 			DUK_ASSERT_TOP(ctx, 5);
21581 		} else {
21582 			DUK_ASSERT_TOP(ctx, 5);
21583 			duk_dup(ctx, 0);
21584 			duk_dup(ctx, 4);
21585 			duk_get_prop_index(ctx, 2, (duk_uarridx_t) i);
21586 			duk_push_u32(ctx, i);
21587 			duk_dup(ctx, 2);
21588 			DUK_DDD(DUK_DDDPRINT("calling reduce function: func=%!T, prev=%!T, curr=%!T, idx=%!T, obj=%!T",
21589 			                     (duk_tval *) duk_get_tval(ctx, -5), (duk_tval *) duk_get_tval(ctx, -4),
21590 			                     (duk_tval *) duk_get_tval(ctx, -3), (duk_tval *) duk_get_tval(ctx, -2),
21591 			                     (duk_tval *) duk_get_tval(ctx, -1)));
21592 			duk_call(ctx, 4);
21593 			DUK_DDD(DUK_DDDPRINT("-> result: %!T", (duk_tval *) duk_get_tval(ctx, -1)));
21594 			duk_replace(ctx, 4);
21595 			DUK_ASSERT_TOP(ctx, 5);
21596 		}
21597 	}
21598 
21599 	if (!have_acc) {
21600 		goto type_error;
21601 	}
21602 
21603 	DUK_ASSERT_TOP(ctx, 5);
21604 	return 1;
21605 
21606  type_error:
21607 	return DUK_RET_TYPE_ERROR;
21608 }
21609 
21610 #undef DUK__ARRAY_MID_JOIN_LIMIT
21611 
21612 #undef DUK__ITER_EVERY
21613 #undef DUK__ITER_SOME
21614 #undef DUK__ITER_FOREACH
21615 #undef DUK__ITER_MAP
21616 #undef DUK__ITER_FILTER
21617 /*
21618  *  Boolean built-ins
21619  */
21620 
21621 /* include removed: duk_internal.h */
21622 
21623 /* Shared helper to provide toString() and valueOf().  Checks 'this', gets
21624  * the primitive value to stack top, and optionally coerces with ToString().
21625  */
duk_bi_boolean_prototype_tostring_shared(duk_context * ctx)21626 DUK_INTERNAL duk_ret_t duk_bi_boolean_prototype_tostring_shared(duk_context *ctx) {
21627 	duk_tval *tv;
21628 	duk_hobject *h;
21629 	duk_small_int_t coerce_tostring = duk_get_current_magic(ctx);
21630 
21631 	/* XXX: there is room to use a shared helper here, many built-ins
21632 	 * check the 'this' type, and if it's an object, check its class,
21633 	 * then get its internal value, etc.
21634 	 */
21635 
21636 	duk_push_this(ctx);
21637 	tv = duk_get_tval(ctx, -1);
21638 	DUK_ASSERT(tv != NULL);
21639 
21640 	if (DUK_TVAL_IS_BOOLEAN(tv)) {
21641 		goto type_ok;
21642 	} else if (DUK_TVAL_IS_OBJECT(tv)) {
21643 		h = DUK_TVAL_GET_OBJECT(tv);
21644 		DUK_ASSERT(h != NULL);
21645 
21646 		if (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_BOOLEAN) {
21647 			duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_VALUE);
21648 			DUK_ASSERT(duk_is_boolean(ctx, -1));
21649 			goto type_ok;
21650 		}
21651 	}
21652 
21653 	return DUK_RET_TYPE_ERROR;
21654 
21655  type_ok:
21656 	if (coerce_tostring) {
21657 		duk_to_string(ctx, -1);
21658 	}
21659 	return 1;
21660 }
21661 
duk_bi_boolean_constructor(duk_context * ctx)21662 DUK_INTERNAL duk_ret_t duk_bi_boolean_constructor(duk_context *ctx) {
21663 	duk_hthread *thr = (duk_hthread *) ctx;
21664 	duk_hobject *h_this;
21665 
21666 	DUK_UNREF(thr);
21667 
21668 	duk_to_boolean(ctx, 0);
21669 
21670 	if (duk_is_constructor_call(ctx)) {
21671 		/* XXX: helper; rely on Boolean.prototype as being non-writable, non-configurable */
21672 		duk_push_this(ctx);
21673 		h_this = duk_get_hobject(ctx, -1);
21674 		DUK_ASSERT(h_this != NULL);
21675 		DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_this) == thr->builtins[DUK_BIDX_BOOLEAN_PROTOTYPE]);
21676 
21677 		DUK_HOBJECT_SET_CLASS_NUMBER(h_this, DUK_HOBJECT_CLASS_BOOLEAN);
21678 
21679 		duk_dup(ctx, 0);  /* -> [ val obj val ] */
21680 		duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);  /* XXX: proper flags? */
21681 	}  /* unbalanced stack */
21682 
21683 	return 1;
21684 }
21685 /*
21686  *  Duktape.Buffer, Node.js Buffer, and Khronos/ES6 TypedArray built-ins
21687  */
21688 
21689 /* include removed: duk_internal.h */
21690 
21691 /*
21692  *  Misc helpers
21693  */
21694 
21695 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
21696 /* Map DUK_HBUFFEROBJECT_ELEM_xxx to duk_hobject class number.
21697  * Sync with duk_hbufferobject.h and duk_hobject.h.
21698  */
21699 static const duk_uint8_t duk__buffer_class_from_elemtype[9] = {
21700 	DUK_HOBJECT_CLASS_UINT8ARRAY,
21701 	DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY,
21702 	DUK_HOBJECT_CLASS_INT8ARRAY,
21703 	DUK_HOBJECT_CLASS_UINT16ARRAY,
21704 	DUK_HOBJECT_CLASS_INT16ARRAY,
21705 	DUK_HOBJECT_CLASS_UINT32ARRAY,
21706 	DUK_HOBJECT_CLASS_INT32ARRAY,
21707 	DUK_HOBJECT_CLASS_FLOAT32ARRAY,
21708 	DUK_HOBJECT_CLASS_FLOAT64ARRAY
21709 };
21710 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
21711 
21712 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
21713 /* Map DUK_HBUFFEROBJECT_ELEM_xxx to prototype object built-in index.
21714  * Sync with duk_hbufferobject.h.
21715  */
21716 static const duk_uint8_t duk__buffer_proto_from_elemtype[9] = {
21717 	DUK_BIDX_UINT8ARRAY_PROTOTYPE,
21718 	DUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE,
21719 	DUK_BIDX_INT8ARRAY_PROTOTYPE,
21720 	DUK_BIDX_UINT16ARRAY_PROTOTYPE,
21721 	DUK_BIDX_INT16ARRAY_PROTOTYPE,
21722 	DUK_BIDX_UINT32ARRAY_PROTOTYPE,
21723 	DUK_BIDX_INT32ARRAY_PROTOTYPE,
21724 	DUK_BIDX_FLOAT32ARRAY_PROTOTYPE,
21725 	DUK_BIDX_FLOAT64ARRAY_PROTOTYPE
21726 };
21727 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
21728 
21729 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
21730 /* Map DUK__FLX_xxx to byte size.
21731  */
21732 static const duk_uint8_t duk__buffer_nbytes_from_fldtype[6] = {
21733 	1,  /* DUK__FLD_8BIT */
21734 	2,  /* DUK__FLD_16BIT */
21735 	4,  /* DUK__FLD_32BIT */
21736 	4,  /* DUK__FLD_FLOAT */
21737 	8,  /* DUK__FLD_DOUBLE */
21738 	0   /* DUK__FLD_VARINT; not relevant here */
21739 };
21740 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
21741 
21742 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
21743 /* Bitfield for each DUK_HBUFFEROBJECT_ELEM_xxx indicating which element types
21744  * are compatible with a blind byte copy for the TypedArray set() method (also
21745  * used for TypedArray constructor).  Array index is target buffer elem type,
21746  * bitfield indicates compatible source types.  The types must have same byte
21747  * size and they must be coercion compatible.
21748  */
21749 static duk_uint16_t duk__buffer_elemtype_copy_compatible[9] = {
21750 	/* xxx -> DUK_HBUFFEROBJECT_ELEM_UINT8 */
21751 	(1U << DUK_HBUFFEROBJECT_ELEM_UINT8) |
21752 		(1U << DUK_HBUFFEROBJECT_ELEM_UINT8CLAMPED) |
21753 		(1U << DUK_HBUFFEROBJECT_ELEM_INT8),
21754 
21755 	/* xxx -> DUK_HBUFFEROBJECT_ELEM_UINT8CLAMPED
21756 	 * Note: INT8 is -not- copy compatible, e.g. -1 would coerce to 0x00.
21757 	 */
21758 	(1U << DUK_HBUFFEROBJECT_ELEM_UINT8) |
21759 		(1U << DUK_HBUFFEROBJECT_ELEM_UINT8CLAMPED),
21760 
21761 	/* xxx -> DUK_HBUFFEROBJECT_ELEM_INT8 */
21762 	(1U << DUK_HBUFFEROBJECT_ELEM_UINT8) |
21763 		(1U << DUK_HBUFFEROBJECT_ELEM_UINT8CLAMPED) |
21764 		(1U << DUK_HBUFFEROBJECT_ELEM_INT8),
21765 
21766 	/* xxx -> DUK_HBUFFEROBJECT_ELEM_UINT16 */
21767 	(1U << DUK_HBUFFEROBJECT_ELEM_UINT16) |
21768 		(1U << DUK_HBUFFEROBJECT_ELEM_INT16),
21769 
21770 	/* xxx -> DUK_HBUFFEROBJECT_ELEM_INT16 */
21771 	(1U << DUK_HBUFFEROBJECT_ELEM_UINT16) |
21772 		(1U << DUK_HBUFFEROBJECT_ELEM_INT16),
21773 
21774 	/* xxx -> DUK_HBUFFEROBJECT_ELEM_UINT32 */
21775 	(1U << DUK_HBUFFEROBJECT_ELEM_UINT32) |
21776 		(1U << DUK_HBUFFEROBJECT_ELEM_INT32),
21777 
21778 	/* xxx -> DUK_HBUFFEROBJECT_ELEM_INT32 */
21779 	(1U << DUK_HBUFFEROBJECT_ELEM_UINT32) |
21780 		(1U << DUK_HBUFFEROBJECT_ELEM_INT32),
21781 
21782 	/* xxx -> DUK_HBUFFEROBJECT_ELEM_FLOAT32 */
21783 	(1U << DUK_HBUFFEROBJECT_ELEM_FLOAT32),
21784 
21785 	/* xxx -> DUK_HBUFFEROBJECT_ELEM_FLOAT64 */
21786 	(1U << DUK_HBUFFEROBJECT_ELEM_FLOAT64)
21787 };
21788 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
21789 
21790 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
21791 /* Shared helper. */
duk__getrequire_bufobj_this(duk_context * ctx,duk_bool_t throw_flag)21792 DUK_LOCAL duk_hbufferobject *duk__getrequire_bufobj_this(duk_context *ctx, duk_bool_t throw_flag) {
21793 	duk_hthread *thr;
21794 	duk_tval *tv;
21795 	duk_hbufferobject *h_this;
21796 
21797 	DUK_ASSERT(ctx != NULL);
21798 	thr = (duk_hthread *) ctx;
21799 
21800 	tv = duk_get_borrowed_this_tval(ctx);
21801 	DUK_ASSERT(tv != NULL);
21802 	if (DUK_TVAL_IS_OBJECT(tv)) {
21803 		h_this = (duk_hbufferobject *) DUK_TVAL_GET_OBJECT(tv);
21804 		DUK_ASSERT(h_this != NULL);
21805 		if (DUK_HOBJECT_IS_BUFFEROBJECT((duk_hobject *) h_this)) {
21806 			DUK_ASSERT_HBUFFEROBJECT_VALID(h_this);
21807 			return h_this;
21808 		}
21809 	}
21810 
21811 	if (throw_flag) {
21812 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_BUFFER);
21813 	}
21814 	return NULL;
21815 }
21816 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
21817 
21818 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
21819 /* Check that 'this' is a duk_hbufferobject and return a pointer to it. */
duk__get_bufobj_this(duk_context * ctx)21820 DUK_LOCAL duk_hbufferobject *duk__get_bufobj_this(duk_context *ctx) {
21821 	return duk__getrequire_bufobj_this(ctx, 0);
21822 }
21823 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
21824 
21825 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
21826 /* Check that 'this' is a duk_hbufferobject and return a pointer to it
21827  * (NULL if not).
21828  */
duk__require_bufobj_this(duk_context * ctx)21829 DUK_LOCAL duk_hbufferobject *duk__require_bufobj_this(duk_context *ctx) {
21830 	return duk__getrequire_bufobj_this(ctx, 1);
21831 }
21832 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
21833 
21834 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
21835 /* Check that value is a duk_hbufferobject and return a pointer to it. */
duk__require_bufobj_value(duk_context * ctx,duk_idx_t index)21836 DUK_LOCAL duk_hbufferobject *duk__require_bufobj_value(duk_context *ctx, duk_idx_t index) {
21837 	duk_hthread *thr;
21838 	duk_tval *tv;
21839 	duk_hbufferobject *h_obj;
21840 
21841 	thr = (duk_hthread *) ctx;
21842 
21843 	/* Don't accept relative indices now. */
21844 	DUK_ASSERT(index >= 0);
21845 
21846 	tv = duk_require_tval(ctx, index);
21847 	DUK_ASSERT(tv != NULL);
21848 	if (DUK_TVAL_IS_OBJECT(tv)) {
21849 		h_obj = (duk_hbufferobject *) DUK_TVAL_GET_OBJECT(tv);
21850 		DUK_ASSERT(h_obj != NULL);
21851 		if (DUK_HOBJECT_IS_BUFFEROBJECT((duk_hobject *) h_obj)) {
21852 			DUK_ASSERT_HBUFFEROBJECT_VALID(h_obj);
21853 			return h_obj;
21854 		}
21855 	}
21856 
21857 	DUK_ERROR_TYPE(thr, DUK_STR_NOT_BUFFER);
21858 	return NULL;  /* not reachable */
21859 }
21860 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
21861 
duk__set_bufobj_buffer(duk_context * ctx,duk_hbufferobject * h_bufobj,duk_hbuffer * h_val)21862 DUK_LOCAL void duk__set_bufobj_buffer(duk_context *ctx, duk_hbufferobject *h_bufobj, duk_hbuffer *h_val) {
21863 	duk_hthread *thr;
21864 
21865 	thr = (duk_hthread *) ctx;
21866 	DUK_UNREF(thr);
21867 
21868 	DUK_ASSERT(ctx != NULL);
21869 	DUK_ASSERT(h_bufobj != NULL);
21870 	DUK_ASSERT(h_bufobj->buf == NULL);  /* no need to decref */
21871 	DUK_ASSERT(h_val != NULL);
21872 	DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj);
21873 
21874 	h_bufobj->buf = h_val;
21875 	DUK_HBUFFER_INCREF(thr, h_val);
21876 	h_bufobj->length = (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_val);
21877 	DUK_ASSERT(h_bufobj->shift == 0);
21878 	DUK_ASSERT(h_bufobj->elem_type == DUK_HBUFFEROBJECT_ELEM_UINT8);
21879 
21880 	DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj);
21881 }
21882 
21883 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk__push_arraybuffer_with_length(duk_context * ctx,duk_uint_t len)21884 DUK_LOCAL duk_hbufferobject *duk__push_arraybuffer_with_length(duk_context *ctx, duk_uint_t len) {
21885 	duk_hbuffer *h_val;
21886 	duk_hbufferobject *h_bufobj;
21887 
21888 	(void) duk_push_fixed_buffer(ctx, (duk_size_t) len);
21889 	h_val = (duk_hbuffer *) duk_get_hbuffer(ctx, -1);
21890 	DUK_ASSERT(h_val != NULL);
21891 
21892 	h_bufobj = duk_push_bufferobject_raw(ctx,
21893 	                                     DUK_HOBJECT_FLAG_EXTENSIBLE |
21894 	                                     DUK_HOBJECT_FLAG_BUFFEROBJECT |
21895 	                                     DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAYBUFFER),
21896 	                                     DUK_BIDX_ARRAYBUFFER_PROTOTYPE);
21897 	DUK_ASSERT(h_bufobj != NULL);
21898 
21899 	duk__set_bufobj_buffer(ctx, h_bufobj, h_val);
21900 	DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj);
21901 
21902 	return h_bufobj;
21903 }
21904 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
21905 
21906 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
21907 /* Shared offset/length coercion helper. */
duk__resolve_offset_opt_length(duk_context * ctx,duk_hbufferobject * 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)21908 DUK_LOCAL void duk__resolve_offset_opt_length(duk_context *ctx,
21909                                               duk_hbufferobject *h_bufarg,
21910                                               duk_idx_t idx_offset,
21911                                               duk_idx_t idx_length,
21912                                               duk_uint_t *out_offset,
21913                                               duk_uint_t *out_length,
21914                                               duk_bool_t throw_flag) {
21915 	duk_hthread *thr;
21916 	duk_int_t offset_signed;
21917 	duk_int_t length_signed;
21918 	duk_uint_t offset;
21919 	duk_uint_t length;
21920 
21921 	thr = (duk_hthread *) ctx;
21922 	DUK_UNREF(thr);
21923 
21924 	offset_signed = duk_to_int(ctx, idx_offset);
21925 	if (offset_signed < 0) {
21926 		goto fail_range;
21927 	}
21928 	offset = (duk_uint_t) offset_signed;
21929 	if (offset > h_bufarg->length) {
21930 		goto fail_range;
21931 	}
21932 	DUK_ASSERT_DISABLE(offset >= 0);  /* unsigned */
21933 	DUK_ASSERT(offset <= h_bufarg->length);
21934 
21935 	if (duk_is_undefined(ctx, idx_length)) {
21936 		DUK_ASSERT(h_bufarg->length >= offset);
21937 		length = h_bufarg->length - offset;  /* >= 0 */
21938 	} else {
21939 		length_signed = duk_to_int(ctx, idx_length);
21940 		if (length_signed < 0) {
21941 			goto fail_range;
21942 		}
21943 		length = (duk_uint_t) length_signed;
21944 		DUK_ASSERT(h_bufarg->length >= offset);
21945 		if (length > h_bufarg->length - offset) {
21946 			/* Unlike for negative arguments, some call sites
21947 			 * want length to be clamped if it's positive.
21948 			 */
21949 			if (throw_flag) {
21950 				goto fail_range;
21951 			} else {
21952 				length = h_bufarg->length - offset;
21953 			}
21954 		}
21955 	}
21956 	DUK_ASSERT_DISABLE(length >= 0);  /* unsigned */
21957 	DUK_ASSERT(offset + length <= h_bufarg->length);
21958 
21959 	*out_offset = offset;
21960 	*out_length = length;
21961 	return;
21962 
21963  fail_range:
21964 	DUK_ERROR_RANGE(thr, DUK_STR_INVALID_CALL_ARGS);
21965 }
21966 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
21967 
21968 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
21969 /* Shared lenient buffer length clamping helper.  No negative indices, no
21970  * element/byte shifting.
21971  */
duk__clamp_startend_nonegidx_noshift(duk_context * ctx,duk_hbufferobject * h_bufobj,duk_idx_t idx_start,duk_idx_t idx_end,duk_int_t * out_start_offset,duk_int_t * out_end_offset)21972 DUK_LOCAL void duk__clamp_startend_nonegidx_noshift(duk_context *ctx,
21973                                                     duk_hbufferobject *h_bufobj,
21974                                                     duk_idx_t idx_start,
21975                                                     duk_idx_t idx_end,
21976                                                     duk_int_t *out_start_offset,
21977                                                     duk_int_t *out_end_offset) {
21978 	duk_int_t buffer_length;
21979 	duk_int_t start_offset;
21980 	duk_int_t end_offset;
21981 
21982 	DUK_ASSERT(out_start_offset != NULL);
21983 	DUK_ASSERT(out_end_offset != NULL);
21984 
21985 	buffer_length = (duk_int_t) h_bufobj->length;
21986 
21987 	/* undefined coerces to zero which is correct */
21988 	start_offset = duk_to_int_clamped(ctx, idx_start, 0, buffer_length);
21989 	if (duk_is_undefined(ctx, idx_end)) {
21990 		end_offset = buffer_length;
21991 	} else {
21992 		end_offset = duk_to_int_clamped(ctx, idx_end, start_offset, buffer_length);
21993 	}
21994 
21995 	DUK_ASSERT(start_offset >= 0);
21996 	DUK_ASSERT(start_offset <= buffer_length);
21997 	DUK_ASSERT(end_offset >= 0);
21998 	DUK_ASSERT(end_offset <= buffer_length);
21999 	DUK_ASSERT(start_offset <= end_offset);
22000 
22001 	*out_start_offset = start_offset;
22002 	*out_end_offset = end_offset;
22003 }
22004 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
22005 
22006 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
22007 /* Shared lenient buffer length clamping helper.  Indices are treated as
22008  * element indices (though output values are byte offsets) which only
22009  * really matters for TypedArray views as other buffer object have a zero
22010  * shift.  Negative indices are counted from end of input slice; crossed
22011  * indices are clamped to zero length; and final indices are clamped
22012  * against input slice.  Used for e.g. ArrayBuffer slice().
22013  */
duk__clamp_startend_negidx_shifted(duk_context * ctx,duk_hbufferobject * h_bufobj,duk_idx_t idx_start,duk_idx_t idx_end,duk_int_t * out_start_offset,duk_int_t * out_end_offset)22014 DUK_LOCAL void duk__clamp_startend_negidx_shifted(duk_context *ctx,
22015                                                   duk_hbufferobject *h_bufobj,
22016                                                   duk_idx_t idx_start,
22017                                                   duk_idx_t idx_end,
22018                                                   duk_int_t *out_start_offset,
22019                                                   duk_int_t *out_end_offset) {
22020 	duk_int_t buffer_length;
22021 	duk_int_t start_offset;
22022 	duk_int_t end_offset;
22023 
22024 	DUK_ASSERT(out_start_offset != NULL);
22025 	DUK_ASSERT(out_end_offset != NULL);
22026 
22027 	buffer_length = (duk_int_t) h_bufobj->length;
22028 	buffer_length >>= h_bufobj->shift;  /* as elements */
22029 
22030 	/* Resolve start/end offset as element indices first; arguments
22031 	 * at idx_start/idx_end are element offsets.  Working with element
22032 	 * indices first also avoids potential for wrapping.
22033 	 */
22034 
22035 	start_offset = duk_to_int(ctx, idx_start);
22036 	if (start_offset < 0) {
22037 		start_offset = buffer_length + start_offset;
22038 	}
22039 	if (duk_is_undefined(ctx, idx_end)) {
22040 		end_offset = buffer_length;
22041 	} else {
22042 		end_offset = duk_to_int(ctx, idx_end);
22043 		if (end_offset < 0) {
22044 			end_offset = buffer_length + end_offset;
22045 		}
22046 	}
22047 	/* Note: start_offset/end_offset can still be < 0 here. */
22048 
22049 	if (start_offset < 0) {
22050 		start_offset = 0;
22051 	} else if (start_offset > buffer_length) {
22052 		start_offset = buffer_length;
22053 	}
22054 	if (end_offset < start_offset) {
22055 		end_offset = start_offset;
22056 	} else if (end_offset > buffer_length) {
22057 		end_offset = buffer_length;
22058 	}
22059 	DUK_ASSERT(start_offset >= 0);
22060 	DUK_ASSERT(start_offset <= buffer_length);
22061 	DUK_ASSERT(end_offset >= 0);
22062 	DUK_ASSERT(end_offset <= buffer_length);
22063 	DUK_ASSERT(start_offset <= end_offset);
22064 
22065 	/* Convert indices to byte offsets. */
22066 	start_offset <<= h_bufobj->shift;
22067 	end_offset <<= h_bufobj->shift;
22068 
22069 	*out_start_offset = start_offset;
22070 	*out_end_offset = end_offset;
22071 }
22072 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
22073 
22074 /*
22075  *  Indexed read/write helpers (also used from outside this file)
22076  */
22077 
duk_hbufferobject_push_validated_read(duk_context * ctx,duk_hbufferobject * h_bufobj,duk_uint8_t * p,duk_small_uint_t elem_size)22078 DUK_INTERNAL void duk_hbufferobject_push_validated_read(duk_context *ctx, duk_hbufferobject *h_bufobj, duk_uint8_t *p, duk_small_uint_t elem_size) {
22079 	duk_double_union du;
22080 
22081 	DUK_MEMCPY((void *) du.uc, (const void *) p, (size_t) elem_size);
22082 
22083 	switch (h_bufobj->elem_type) {
22084 	case DUK_HBUFFEROBJECT_ELEM_UINT8:
22085 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
22086 	case DUK_HBUFFEROBJECT_ELEM_UINT8CLAMPED:
22087 #endif
22088 		duk_push_uint(ctx, (duk_uint_t) du.uc[0]);
22089 		break;
22090 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
22091 	/* These are not needed when only Duktape.Buffer is supported. */
22092 	case DUK_HBUFFEROBJECT_ELEM_INT8:
22093 		duk_push_int(ctx, (duk_int_t) (duk_int8_t) du.uc[0]);
22094 		break;
22095 	case DUK_HBUFFEROBJECT_ELEM_UINT16:
22096 		duk_push_uint(ctx, (duk_uint_t) du.us[0]);
22097 		break;
22098 	case DUK_HBUFFEROBJECT_ELEM_INT16:
22099 		duk_push_int(ctx, (duk_int_t) (duk_int16_t) du.us[0]);
22100 		break;
22101 	case DUK_HBUFFEROBJECT_ELEM_UINT32:
22102 		duk_push_uint(ctx, (duk_uint_t) du.ui[0]);
22103 		break;
22104 	case DUK_HBUFFEROBJECT_ELEM_INT32:
22105 		duk_push_int(ctx, (duk_int_t) (duk_int32_t) du.ui[0]);
22106 		break;
22107 	case DUK_HBUFFEROBJECT_ELEM_FLOAT32:
22108 		duk_push_number(ctx, (duk_double_t) du.f[0]);
22109 		break;
22110 	case DUK_HBUFFEROBJECT_ELEM_FLOAT64:
22111 		duk_push_number(ctx, (duk_double_t) du.d);
22112 		break;
22113 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
22114 	default:
22115 		DUK_UNREACHABLE();
22116 	}
22117 }
22118 
duk_hbufferobject_validated_write(duk_context * ctx,duk_hbufferobject * h_bufobj,duk_uint8_t * p,duk_small_uint_t elem_size)22119 DUK_INTERNAL void duk_hbufferobject_validated_write(duk_context *ctx, duk_hbufferobject *h_bufobj, duk_uint8_t *p, duk_small_uint_t elem_size) {
22120 	duk_double_union du;
22121 
22122 	/* NOTE! Caller must ensure that any side effects from the
22123 	 * coercions below are safe.  If that cannot be guaranteed
22124 	 * (which is normally the case), caller must coerce the
22125 	 * argument using duk_to_number() before any pointer
22126 	 * validations; the result of duk_to_number() always coerces
22127 	 * without side effects here.
22128 	 */
22129 
22130 	switch (h_bufobj->elem_type) {
22131 	case DUK_HBUFFEROBJECT_ELEM_UINT8:
22132 		du.uc[0] = (duk_uint8_t) duk_to_uint32(ctx, -1);
22133 		break;
22134 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
22135 	/* These are not needed when only Duktape.Buffer is supported. */
22136 	case DUK_HBUFFEROBJECT_ELEM_UINT8CLAMPED:
22137 		du.uc[0] = (duk_uint8_t) duk_to_uint8clamped(ctx, -1);
22138 		break;
22139 	case DUK_HBUFFEROBJECT_ELEM_INT8:
22140 		du.uc[0] = (duk_uint8_t) duk_to_int32(ctx, -1);
22141 		break;
22142 	case DUK_HBUFFEROBJECT_ELEM_UINT16:
22143 		du.us[0] = (duk_uint16_t) duk_to_uint32(ctx, -1);
22144 		break;
22145 	case DUK_HBUFFEROBJECT_ELEM_INT16:
22146 		du.us[0] = (duk_uint16_t) duk_to_int32(ctx, -1);
22147 		break;
22148 	case DUK_HBUFFEROBJECT_ELEM_UINT32:
22149 		du.ui[0] = (duk_uint32_t) duk_to_uint32(ctx, -1);
22150 		break;
22151 	case DUK_HBUFFEROBJECT_ELEM_INT32:
22152 		du.ui[0] = (duk_uint32_t) duk_to_int32(ctx, -1);
22153 		break;
22154 	case DUK_HBUFFEROBJECT_ELEM_FLOAT32:
22155 		du.f[0] = (duk_float_t) duk_to_number(ctx, -1);
22156 		break;
22157 	case DUK_HBUFFEROBJECT_ELEM_FLOAT64:
22158 		du.d = (duk_double_t) duk_to_number(ctx, -1);
22159 		break;
22160 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
22161 	default:
22162 		DUK_UNREACHABLE();
22163 	}
22164 
22165 	DUK_MEMCPY((void *) p, (const void *) du.uc, (size_t) elem_size);
22166 }
22167 
22168 /*
22169  *  Duktape.Buffer: constructor
22170  */
22171 
duk_bi_buffer_constructor(duk_context * ctx)22172 DUK_INTERNAL duk_ret_t duk_bi_buffer_constructor(duk_context *ctx) {
22173 	duk_hthread *thr;
22174 	duk_size_t buf_size;
22175 	duk_small_int_t buf_dynamic;
22176 	duk_uint8_t *buf_data;
22177 	const duk_uint8_t *src_data;
22178 
22179 	thr = (duk_hthread *) ctx;
22180 	DUK_UNREF(thr);
22181 
22182 	/*
22183 	 *  Constructor arguments are currently somewhat compatible with
22184 	 *  (keep it that way if possible):
22185 	 *
22186 	 *    http://nodejs.org/api/buffer.html
22187 	 *
22188 	 *  Note that the ToBuffer() coercion (duk_to_buffer()) does NOT match
22189 	 *  the constructor behavior.
22190 	 */
22191 
22192 	buf_dynamic = duk_get_boolean(ctx, 1);  /* default to false */
22193 
22194 	switch (duk_get_type(ctx, 0)) {
22195 	case DUK_TYPE_NUMBER: {
22196 		/* new buffer of specified size */
22197 		buf_size = (duk_size_t) duk_to_int(ctx, 0);
22198 		(void) duk_push_buffer(ctx, buf_size, buf_dynamic);
22199 		break;
22200 	}
22201 	case DUK_TYPE_BUFFER: {
22202 		/* return input buffer, converted to a Duktape.Buffer object
22203 		 * if called as a constructor (no change if called as a
22204 		 * function).
22205 		 */
22206 		duk_set_top(ctx, 1);
22207 		break;
22208 	}
22209 	case DUK_TYPE_STRING: {
22210 		/* new buffer with string contents */
22211 		src_data = (const duk_uint8_t *) duk_get_lstring(ctx, 0, &buf_size);
22212 		DUK_ASSERT(src_data != NULL);  /* even for zero-length string */
22213 		buf_data = (duk_uint8_t *) duk_push_buffer(ctx, buf_size, buf_dynamic);
22214 		DUK_MEMCPY((void *) buf_data, (const void *) src_data, (size_t) buf_size);
22215 		break;
22216 	}
22217 	case DUK_TYPE_OBJECT: {
22218 		/* For all duk_hbufferobjects, get the plain buffer inside
22219 		 * without making a copy.  This is compatible with Duktape 1.2
22220 		 * but means that a slice/view information is ignored and the
22221 		 * full underlying buffer is returned.
22222 		 *
22223 		 * If called as a constructor, a new Duktape.Buffer object
22224 		 * pointing to the same plain buffer is created below.
22225 		 */
22226 		duk_hbufferobject *h_bufobj;
22227 		h_bufobj = (duk_hbufferobject *) duk_get_hobject(ctx, 0);
22228 		DUK_ASSERT(h_bufobj != NULL);
22229 		if (!DUK_HOBJECT_IS_BUFFEROBJECT((duk_hobject *) h_bufobj)) {
22230 			return DUK_RET_TYPE_ERROR;
22231 		}
22232 		if (h_bufobj->buf == NULL) {
22233 			return DUK_RET_TYPE_ERROR;
22234 		}
22235 		duk_push_hbuffer(ctx, h_bufobj->buf);
22236 		break;
22237 	}
22238 	case DUK_TYPE_NONE:
22239 	default: {
22240 		return DUK_RET_TYPE_ERROR;
22241 	}
22242 	}
22243 	DUK_ASSERT(duk_is_buffer(ctx, -1));
22244 
22245 	/* stack is unbalanced, but: [ <something> buf ] */
22246 
22247 	if (duk_is_constructor_call(ctx)) {
22248 		duk_hbufferobject *h_bufobj;
22249 		duk_hbuffer *h_val;
22250 
22251 		h_val = duk_get_hbuffer(ctx, -1);
22252 		DUK_ASSERT(h_val != NULL);
22253 
22254 		h_bufobj = duk_push_bufferobject_raw(ctx,
22255 		                                     DUK_HOBJECT_FLAG_EXTENSIBLE |
22256 		                                     DUK_HOBJECT_FLAG_BUFFEROBJECT |
22257 		                                     DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_BUFFER),
22258 		                                     DUK_BIDX_BUFFER_PROTOTYPE);
22259 		DUK_ASSERT(h_bufobj != NULL);
22260 
22261 		duk__set_bufobj_buffer(ctx, h_bufobj, h_val);
22262 
22263 		DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj);
22264 	}
22265 	/* Note: unbalanced stack on purpose */
22266 
22267 	return 1;
22268 }
22269 
22270 /*
22271  *  Node.js Buffer: constructor
22272  */
22273 
22274 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_constructor(duk_context * ctx)22275 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_constructor(duk_context *ctx) {
22276 	/* Internal class is Object: Object.prototype.toString.call(new Buffer(0))
22277 	 * prints "[object Object]".
22278 	 */
22279 	duk_int_t len;
22280 	duk_int_t i;
22281 	duk_hbuffer *h_buf;
22282 	duk_hbufferobject *h_bufobj;
22283 	duk_size_t buf_size;
22284 
22285 	switch (duk_get_type(ctx, 0)) {
22286 	case DUK_TYPE_BUFFER: {
22287 		/* Custom behavior: plain buffer is used as internal buffer
22288 		 * without making a copy (matches Duktape.Buffer).
22289 		 */
22290 		duk_set_top(ctx, 1);  /* -> [ buffer ] */
22291 		break;
22292 	}
22293 	case DUK_TYPE_NUMBER: {
22294 		len = duk_to_int_clamped(ctx, 0, 0, DUK_INT_MAX);
22295 		(void) duk_push_fixed_buffer(ctx, (duk_size_t) len);
22296 		break;
22297 	}
22298 	case DUK_TYPE_OBJECT: {
22299 		duk_uint8_t *buf;
22300 
22301 		(void) duk_get_prop_string(ctx, 0, "length");
22302 		len = duk_to_int_clamped(ctx, -1, 0, DUK_INT_MAX);
22303 		duk_pop(ctx);
22304 		buf = (duk_uint8_t *) duk_push_fixed_buffer(ctx, (duk_size_t) len);
22305 		for (i = 0; i < len; i++) {
22306 			/* XXX: fast path for array arguments? */
22307 			duk_get_prop_index(ctx, 0, (duk_uarridx_t) i);
22308 			buf[i] = (duk_uint8_t) (duk_to_uint32(ctx, -1) & 0xffU);
22309 			duk_pop(ctx);
22310 		}
22311 		break;
22312 	}
22313 	case DUK_TYPE_STRING: {
22314 		/* ignore encoding for now */
22315 		duk_dup(ctx, 0);
22316 		(void) duk_to_buffer(ctx, -1, &buf_size);
22317 		break;
22318 	}
22319 	default:
22320 		return DUK_RET_TYPE_ERROR;
22321 	}
22322 
22323 	DUK_ASSERT(duk_is_buffer(ctx, -1));
22324 	h_buf = duk_get_hbuffer(ctx, -1);
22325 	DUK_ASSERT(h_buf != NULL);
22326 
22327 	h_bufobj = duk_push_bufferobject_raw(ctx,
22328 	                                     DUK_HOBJECT_FLAG_EXTENSIBLE |
22329 	                                     DUK_HOBJECT_FLAG_BUFFEROBJECT |
22330 	                                     DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_BUFFER),
22331 	                                     DUK_BIDX_NODEJS_BUFFER_PROTOTYPE);
22332 	DUK_ASSERT(h_bufobj != NULL);
22333 
22334 	h_bufobj->buf = h_buf;
22335 	DUK_HBUFFER_INCREF(thr, h_buf);
22336 	DUK_ASSERT(h_bufobj->offset == 0);
22337 	h_bufobj->length = (duk_int_t) DUK_HBUFFER_GET_SIZE(h_buf);
22338 	DUK_ASSERT(h_bufobj->elem_type == DUK_HBUFFEROBJECT_ELEM_UINT8);
22339 
22340 	DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj);
22341 
22342 	return 1;
22343 }
22344 #else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
duk_bi_nodejs_buffer_constructor(duk_context * ctx)22345 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_constructor(duk_context *ctx) {
22346 	DUK_UNREF(ctx);
22347 	return DUK_RET_UNSUPPORTED_ERROR;
22348 }
22349 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
22350 
22351 /*
22352  *  ArrayBuffer, DataView, and TypedArray constructors
22353  */
22354 
22355 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_arraybuffer_constructor(duk_context * ctx)22356 DUK_INTERNAL duk_ret_t duk_bi_arraybuffer_constructor(duk_context *ctx) {
22357 	duk_hthread *thr;
22358 	duk_hbufferobject *h_bufobj;
22359 	duk_hbuffer *h_val;
22360 
22361 	DUK_ASSERT_CTX_VALID(ctx);
22362 	thr = (duk_hthread *) ctx;
22363 	DUK_UNREF(thr);
22364 
22365 	/* XXX: function flag to make this automatic? */
22366 	if (!duk_is_constructor_call(ctx)) {
22367 		return DUK_RET_TYPE_ERROR;
22368 	}
22369 
22370 	if (duk_is_buffer(ctx, 0)) {
22371 		/* Custom behavior: plain buffer is used as internal buffer
22372 		 * without making a copy (matches Duktape.Buffer).
22373 		 */
22374 
22375 		h_val = duk_get_hbuffer(ctx, 0);
22376 		DUK_ASSERT(h_val != NULL);
22377 
22378 		/* XXX: accept any duk_hbufferobject type as an input also? */
22379 	} else {
22380 		duk_int_t len;
22381 		len = duk_to_int(ctx, 0);
22382 		if (len < 0) {
22383 			goto fail_length;
22384 		}
22385 		(void) duk_push_fixed_buffer(ctx, (duk_size_t) len);
22386 		h_val = (duk_hbuffer *) duk_get_hbuffer(ctx, -1);
22387 		DUK_ASSERT(h_val != NULL);
22388 
22389 #if !defined(DUK_USE_ZERO_BUFFER_DATA)
22390 		/* Khronos/ES6 requires zeroing even when DUK_USE_ZERO_BUFFER_DATA
22391 		 * is not set.
22392 		 */
22393 		DUK_ASSERT(!DUK_HBUFFER_HAS_DYNAMIC((duk_hbuffer *) h_val));
22394 		DUK_MEMZERO((void *) DUK_HBUFFER_FIXED_GET_DATA_PTR(thr->heap, h_val), (duk_size_t) len);
22395 #endif
22396 	}
22397 
22398 	h_bufobj = duk_push_bufferobject_raw(ctx,
22399 	                                     DUK_HOBJECT_FLAG_EXTENSIBLE |
22400 	                                     DUK_HOBJECT_FLAG_BUFFEROBJECT |
22401 	                                     DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAYBUFFER),
22402 	                                     DUK_BIDX_ARRAYBUFFER_PROTOTYPE);
22403 	DUK_ASSERT(h_bufobj != NULL);
22404 
22405 	duk__set_bufobj_buffer(ctx, h_bufobj, h_val);
22406 	DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj);
22407 
22408 	return 1;
22409 
22410  fail_length:
22411 	return DUK_RET_RANGE_ERROR;
22412 }
22413 #else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
duk_bi_arraybuffer_constructor(duk_context * ctx)22414 DUK_INTERNAL duk_ret_t duk_bi_arraybuffer_constructor(duk_context *ctx) {
22415 	DUK_UNREF(ctx);
22416 	return DUK_RET_UNSUPPORTED_ERROR;
22417 }
22418 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
22419 
22420 
22421 /* Format of magic, bits:
22422  *   0...1: elem size shift (0-3)
22423  *   2...5: elem type (DUK_HBUFFEROBJECT_ELEM_xxx)
22424  */
22425 
22426 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_typedarray_constructor(duk_context * ctx)22427 DUK_INTERNAL duk_ret_t duk_bi_typedarray_constructor(duk_context *ctx) {
22428 	duk_hthread *thr;
22429 	duk_tval *tv;
22430 	duk_hobject *h_obj;
22431 	duk_hbufferobject *h_bufobj = NULL;
22432 	duk_hbufferobject *h_bufarr = NULL;
22433 	duk_hbufferobject *h_bufarg = NULL;
22434 	duk_hbuffer *h_val;
22435 	duk_small_uint_t magic;
22436 	duk_small_uint_t shift;
22437 	duk_small_uint_t elem_type;
22438 	duk_small_uint_t elem_size;
22439 	duk_small_uint_t class_num;
22440 	duk_small_uint_t proto_bidx;
22441 	duk_uint_t align_mask;
22442 	duk_uint_t elem_length;
22443 	duk_int_t elem_length_signed;
22444 	duk_uint_t byte_length;
22445 	duk_small_uint_t copy_mode;
22446 
22447 	thr = (duk_hthread *) ctx;
22448 	DUK_UNREF(thr);
22449 
22450 	/* XXX: function flag to make this automatic? */
22451 	if (!duk_is_constructor_call(ctx)) {
22452 		return DUK_RET_TYPE_ERROR;
22453 	}
22454 
22455 	/* We could fit built-in index into magic but that'd make the magic
22456 	 * number dependent on built-in numbering (genbuiltins.py doesn't
22457 	 * handle that yet).  So map both class and prototype from the
22458 	 * element type.
22459 	 */
22460 	magic = duk_get_current_magic(ctx);
22461 	shift = magic & 0x03;               /* bits 0...1: shift */
22462 	elem_type = (magic >> 2) & 0x0f;    /* bits 2...5: type */
22463 	elem_size = 1 << shift;
22464 	align_mask = elem_size - 1;
22465 	DUK_ASSERT(elem_type < sizeof(duk__buffer_proto_from_elemtype) / sizeof(duk_uint8_t));
22466 	proto_bidx = duk__buffer_proto_from_elemtype[elem_type];
22467 	DUK_ASSERT(proto_bidx < DUK_NUM_BUILTINS);
22468 	DUK_ASSERT(elem_type < sizeof(duk__buffer_class_from_elemtype) / sizeof(duk_uint8_t));
22469 	class_num = duk__buffer_class_from_elemtype[elem_type];
22470 
22471 	DUK_DD(DUK_DDPRINT("typedarray constructor, magic=%d, shift=%d, elem_type=%d, "
22472 	                   "elem_size=%d, proto_bidx=%d, class_num=%d",
22473 	                   (int) magic, (int) shift, (int) elem_type, (int) elem_size,
22474 	                   (int) proto_bidx, (int) class_num));
22475 
22476 	/* Argument variants.  When the argument is an ArrayBuffer a view to
22477 	 * the same buffer is created; otherwise a new ArrayBuffer is always
22478 	 * created.
22479 	 */
22480 
22481 	tv = duk_get_tval(ctx, 0);
22482 	DUK_ASSERT(tv != NULL);  /* arg count */
22483 	if (DUK_TVAL_IS_OBJECT(tv)) {
22484 		h_obj = DUK_TVAL_GET_OBJECT(tv);
22485 		DUK_ASSERT(h_obj != NULL);
22486 
22487 		if (DUK_HOBJECT_GET_CLASS_NUMBER(h_obj) == DUK_HOBJECT_CLASS_ARRAYBUFFER) {
22488 			/* ArrayBuffer: unlike any other argument variant, create
22489 			 * a view into the existing buffer.
22490 			 */
22491 
22492 			duk_int_t byte_offset_signed;
22493 			duk_uint_t byte_offset;
22494 
22495 			h_bufarg = (duk_hbufferobject *) h_obj;
22496 
22497 			byte_offset_signed = duk_to_int(ctx, 1);
22498 			if (byte_offset_signed < 0) {
22499 				goto fail_arguments;
22500 			}
22501 			byte_offset = (duk_uint_t) byte_offset_signed;
22502 			if (byte_offset > h_bufarg->length ||
22503 			    (byte_offset & align_mask) != 0) {
22504 				/* Must be >= 0 and multiple of element size. */
22505 				goto fail_arguments;
22506 			}
22507 			if (duk_is_undefined(ctx, 2)) {
22508 				DUK_ASSERT(h_bufarg->length >= byte_offset);
22509 				byte_length = h_bufarg->length - byte_offset;
22510 				if ((byte_length & align_mask) != 0) {
22511 					/* Must be element size multiple from
22512 					 * start offset to end of buffer.
22513 					 */
22514 					goto fail_arguments;
22515 				}
22516 				elem_length = (byte_length >> shift);
22517 			} else {
22518 				elem_length_signed = duk_to_int(ctx, 2);
22519 				if (elem_length_signed < 0) {
22520 					goto fail_arguments;
22521 				}
22522 				elem_length = (duk_uint_t) elem_length_signed;
22523 				byte_length = elem_length << shift;
22524 				if ((byte_length >> shift) != elem_length) {
22525 					/* Byte length would overflow. */
22526 					/* XXX: easier check with less code? */
22527 					goto fail_arguments;
22528 				}
22529 				DUK_ASSERT(h_bufarg->length >= byte_offset);
22530 				if (byte_length > h_bufarg->length - byte_offset) {
22531 					/* Not enough data. */
22532 					goto fail_arguments;
22533 				}
22534 			}
22535 			DUK_UNREF(elem_length);
22536 			DUK_ASSERT_DISABLE(byte_offset >= 0);
22537 			DUK_ASSERT(byte_offset <= h_bufarg->length);
22538 			DUK_ASSERT_DISABLE(byte_length >= 0);
22539 			DUK_ASSERT(byte_offset + byte_length <= h_bufarg->length);
22540 			DUK_ASSERT((elem_length << shift) == byte_length);
22541 
22542 			h_bufobj = duk_push_bufferobject_raw(ctx,
22543 			                                     DUK_HOBJECT_FLAG_EXTENSIBLE |
22544 			                                     DUK_HOBJECT_FLAG_BUFFEROBJECT |
22545 			                                     DUK_HOBJECT_CLASS_AS_FLAGS(class_num),
22546 			                                     proto_bidx);
22547 			h_val = h_bufarg->buf;
22548 			if (h_val == NULL) {
22549 				return DUK_RET_TYPE_ERROR;
22550 			}
22551 			h_bufobj->buf = h_val;
22552 			DUK_HBUFFER_INCREF(thr, h_val);
22553 			h_bufobj->offset = h_bufarg->offset + byte_offset;
22554 			h_bufobj->length = byte_length;
22555 			h_bufobj->shift = (duk_uint8_t) shift;
22556 			h_bufobj->elem_type = (duk_uint8_t) elem_type;
22557 			h_bufobj->is_view = 1;
22558 			DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj);
22559 
22560 			/* Set .buffer to the argument ArrayBuffer. */
22561 			duk_dup(ctx, 0);
22562 			duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LC_BUFFER, DUK_PROPDESC_FLAGS_NONE);
22563 			duk_compact(ctx, -1);
22564 			return 1;
22565 		} else if (DUK_HOBJECT_IS_BUFFEROBJECT(h_obj)) {
22566 			/* TypedArray (or other non-ArrayBuffer duk_hbufferobject).
22567 			 * Conceptually same behavior as for an Array-like argument,
22568 			 * with a few fast paths.
22569 			 */
22570 
22571 			h_bufarg = (duk_hbufferobject *) h_obj;
22572 			DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufarg);
22573 			elem_length_signed = (duk_int_t) (h_bufarg->length >> h_bufarg->shift);
22574 			if (h_bufarg->buf == NULL) {
22575 				return DUK_RET_TYPE_ERROR;
22576 			}
22577 
22578 			/* Select copy mode.  Must take into account element
22579 			 * compatibility and validity of the underlying source
22580 			 * buffer.
22581 			 */
22582 
22583 			DUK_DDD(DUK_DDDPRINT("selecting copy mode for bufobj arg, "
22584 			                     "src byte_length=%ld, src shift=%d, "
22585 			                     "src/dst elem_length=%ld; "
22586 			                     "dst shift=%d -> dst byte_length=%ld",
22587 			                     (long) h_bufarg->length, (int) h_bufarg->shift,
22588 			                     (long) elem_length_signed, (int) shift,
22589 			                     (long) (elem_length_signed << shift)));
22590 
22591 			copy_mode = 2;  /* default is explicit index read/write copy */
22592 			DUK_ASSERT(elem_type < sizeof(duk__buffer_elemtype_copy_compatible) / sizeof(duk_uint16_t));
22593 			if (DUK_HBUFFEROBJECT_VALID_SLICE(h_bufarg)) {
22594 				if ((duk__buffer_elemtype_copy_compatible[elem_type] & (1 << h_bufarg->elem_type)) != 0) {
22595 					DUK_DDD(DUK_DDDPRINT("source/target are copy compatible, memcpy"));
22596 					DUK_ASSERT(shift == h_bufarg->shift);  /* byte sizes will match */
22597 					copy_mode = 0;
22598 				} else {
22599 					DUK_DDD(DUK_DDDPRINT("source/target not copy compatible but valid, fast copy"));
22600 					copy_mode = 1;
22601 				}
22602 			}
22603 		} else {
22604 			/* Array or Array-like */
22605 			elem_length_signed = (duk_int_t) duk_get_length(ctx, 0);
22606 			copy_mode = 2;
22607 		}
22608 	} else if (DUK_TVAL_IS_BUFFER(tv)) {
22609 		/* Accept plain buffer values like array initializers
22610 		 * (new in Duktape 1.4.0).
22611 		 */
22612 		duk_hbuffer *h_srcbuf;
22613 		h_srcbuf = DUK_TVAL_GET_BUFFER(tv);
22614 		elem_length_signed = (duk_int_t) DUK_HBUFFER_GET_SIZE(h_srcbuf);
22615 		copy_mode = 2;  /* XXX: could add fast path for u8 compatible views */
22616 	} else {
22617 		/* Non-object argument is simply int coerced, matches
22618 		 * V8 behavior (except for "null", which we coerce to
22619 		 * 0 but V8 TypeErrors).
22620 		 */
22621 		elem_length_signed = duk_to_int(ctx, 0);
22622 		copy_mode = 3;
22623 	}
22624 	if (elem_length_signed < 0) {
22625 		goto fail_arguments;
22626 	}
22627 	elem_length = (duk_uint_t) elem_length_signed;
22628 	byte_length = (duk_uint_t) (elem_length << shift);
22629 	if ((byte_length >> shift) != elem_length) {
22630 		/* Byte length would overflow. */
22631 		/* XXX: easier check with less code? */
22632 		goto fail_arguments;
22633 	}
22634 
22635 	DUK_DDD(DUK_DDDPRINT("elem_length=%ld, byte_length=%ld",
22636 	                     (long) elem_length, (long) byte_length));
22637 
22638 	/* ArrayBuffer argument is handled specially above; the rest of the
22639 	 * argument variants are handled by shared code below.
22640 	 */
22641 
22642 	/* Push a new ArrayBuffer (becomes view .buffer) */
22643 	h_bufarr = duk__push_arraybuffer_with_length(ctx, byte_length);
22644 	DUK_ASSERT(h_bufarr != NULL);
22645 	h_val = h_bufarr->buf;
22646 	DUK_ASSERT(h_val != NULL);
22647 
22648 	/* Push the resulting view object and attach the ArrayBuffer. */
22649 	h_bufobj = duk_push_bufferobject_raw(ctx,
22650 	                                     DUK_HOBJECT_FLAG_EXTENSIBLE |
22651 	                                     DUK_HOBJECT_FLAG_BUFFEROBJECT |
22652 	                                     DUK_HOBJECT_CLASS_AS_FLAGS(class_num),
22653 	                                     proto_bidx);
22654 
22655 	h_bufobj->buf = h_val;
22656 	DUK_HBUFFER_INCREF(thr, h_val);
22657 	DUK_ASSERT(h_bufobj->offset == 0);
22658 	h_bufobj->length = byte_length;
22659 	h_bufobj->shift = (duk_uint8_t) shift;
22660 	h_bufobj->elem_type = (duk_uint8_t) elem_type;
22661 	h_bufobj->is_view = 1;
22662 	DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj);
22663 
22664 	/* Set .buffer */
22665 	duk_dup(ctx, -2);
22666 	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LC_BUFFER, DUK_PROPDESC_FLAGS_NONE);
22667 	duk_compact(ctx, -1);
22668 
22669 	/* Copy values, the copy method depends on the arguments.
22670 	 *
22671 	 * Copy mode decision may depend on the validity of the underlying
22672 	 * buffer of the source argument; there must be no harmful side effects
22673 	 * from there to here for copy_mode to still be valid.
22674 	 */
22675 	DUK_DDD(DUK_DDDPRINT("copy mode: %d", (int) copy_mode));
22676 	switch (copy_mode) {
22677 	case 0: {
22678 		/* Use byte copy. */
22679 
22680 		duk_uint8_t *p_src;
22681 		duk_uint8_t *p_dst;
22682 
22683 		DUK_ASSERT(h_bufobj != NULL);
22684 		DUK_ASSERT(h_bufobj->buf != NULL);
22685 		DUK_ASSERT(DUK_HBUFFEROBJECT_VALID_SLICE(h_bufobj));
22686 		DUK_ASSERT(h_bufarg != NULL);
22687 		DUK_ASSERT(h_bufarg->buf != NULL);
22688 		DUK_ASSERT(DUK_HBUFFEROBJECT_VALID_SLICE(h_bufarg));
22689 
22690 		p_dst = DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_bufobj);
22691 		p_src = DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_bufarg);
22692 
22693 		DUK_DDD(DUK_DDDPRINT("using memcpy: p_src=%p, p_dst=%p, byte_length=%ld",
22694 		                     (void *) p_src, (void *) p_dst, (long) byte_length));
22695 
22696 		DUK_MEMCPY((void *) p_dst, (const void *) p_src, (size_t) byte_length);
22697 		break;
22698 	}
22699 	case 1: {
22700 		/* Copy values through direct validated reads and writes. */
22701 
22702 		duk_small_uint_t src_elem_size;
22703 		duk_small_uint_t dst_elem_size;
22704 		duk_uint8_t *p_src;
22705 		duk_uint8_t *p_src_end;
22706 		duk_uint8_t *p_dst;
22707 
22708 		DUK_ASSERT(h_bufobj != NULL);
22709 		DUK_ASSERT(h_bufobj->buf != NULL);
22710 		DUK_ASSERT(DUK_HBUFFEROBJECT_VALID_SLICE(h_bufobj));
22711 		DUK_ASSERT(h_bufarg != NULL);
22712 		DUK_ASSERT(h_bufarg->buf != NULL);
22713 		DUK_ASSERT(DUK_HBUFFEROBJECT_VALID_SLICE(h_bufarg));
22714 
22715 		src_elem_size = 1 << h_bufarg->shift;
22716 		dst_elem_size = elem_size;
22717 
22718 		p_src = DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_bufarg);
22719 		p_dst = DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_bufobj);
22720 		p_src_end = p_src + h_bufarg->length;
22721 
22722 		DUK_DDD(DUK_DDDPRINT("using fast copy: p_src=%p, p_src_end=%p, p_dst=%p, "
22723 		                     "src_elem_size=%d, dst_elem_size=%d",
22724 		                     (void *) p_src, (void *) p_src_end, (void *) p_dst,
22725 		                     (int) src_elem_size, (int) dst_elem_size));
22726 
22727 		while (p_src != p_src_end) {
22728 			DUK_DDD(DUK_DDDPRINT("fast path per element copy loop: "
22729 			                     "p_src=%p, p_src_end=%p, p_dst=%p",
22730 			                     (void *) p_src, (void *) p_src_end, (void *) p_dst));
22731 			/* A validated read() is always a number, so it's write coercion
22732 			 * is always side effect free an won't invalidate pointers etc.
22733 			 */
22734 			duk_hbufferobject_push_validated_read(ctx, h_bufarg, p_src, src_elem_size);
22735 			duk_hbufferobject_validated_write(ctx, h_bufobj, p_dst, dst_elem_size);
22736 			duk_pop(ctx);
22737 			p_src += src_elem_size;
22738 			p_dst += dst_elem_size;
22739 		}
22740 		break;
22741 	}
22742 	case 2: {
22743 		/* Copy values by index reads and writes.  Let virtual
22744 		 * property handling take care of coercion.
22745 		 */
22746 		duk_uint_t i;
22747 
22748 		DUK_DDD(DUK_DDDPRINT("using slow copy"));
22749 
22750 		for (i = 0; i < elem_length; i++) {
22751 			duk_get_prop_index(ctx, 0, (duk_uarridx_t) i);
22752 			duk_put_prop_index(ctx, -2, (duk_uarridx_t) i);
22753 		}
22754 		break;
22755 	}
22756 	default:
22757 	case 3: {
22758 		/* No copy, leave zero bytes in the buffer.  There's no
22759 		 * ambiguity with Float32/Float64 because zero bytes also
22760 		 * represent 0.0.
22761 		 */
22762 #if !defined(DUK_USE_ZERO_BUFFER_DATA)
22763 		/* Khronos/ES6 requires zeroing even when DUK_USE_ZERO_BUFFER_DATA
22764 		 * is not set.
22765 		 */
22766 		DUK_ASSERT(!DUK_HBUFFER_HAS_DYNAMIC((duk_hbuffer *) h_val));
22767 		DUK_MEMZERO((void *) DUK_HBUFFER_FIXED_GET_DATA_PTR(thr->heap, h_val), (duk_size_t) byte_length);
22768 #endif
22769 
22770 		DUK_DDD(DUK_DDDPRINT("using no copy"));
22771 		break;
22772 	}
22773 	}
22774 
22775 	return 1;
22776 
22777  fail_arguments:
22778 	return DUK_RET_RANGE_ERROR;
22779 }
22780 #else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
duk_bi_typedarray_constructor(duk_context * ctx)22781 DUK_INTERNAL duk_ret_t duk_bi_typedarray_constructor(duk_context *ctx) {
22782 	DUK_UNREF(ctx);
22783 	return DUK_RET_UNSUPPORTED_ERROR;
22784 }
22785 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
22786 
22787 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_dataview_constructor(duk_context * ctx)22788 DUK_INTERNAL duk_ret_t duk_bi_dataview_constructor(duk_context *ctx) {
22789 	duk_hbufferobject *h_bufarg;
22790 	duk_hbufferobject *h_bufobj;
22791 	duk_hbuffer *h_val;
22792 	duk_uint_t offset;
22793 	duk_uint_t length;
22794 
22795 	/* XXX: function flag to make this automatic? */
22796 	if (!duk_is_constructor_call(ctx)) {
22797 		return DUK_RET_TYPE_ERROR;
22798 	}
22799 
22800 	h_bufarg = duk__require_bufobj_value(ctx, 0);
22801 	DUK_ASSERT(h_bufarg != NULL);
22802 
22803 	duk__resolve_offset_opt_length(ctx, h_bufarg, 1, 2, &offset, &length, 1 /*throw_flag*/);
22804 	DUK_ASSERT(offset <= h_bufarg->length);
22805 	DUK_ASSERT(offset + length <= h_bufarg->length);
22806 
22807 	h_bufobj = duk_push_bufferobject_raw(ctx,
22808 	                                     DUK_HOBJECT_FLAG_EXTENSIBLE |
22809 	                                     DUK_HOBJECT_FLAG_BUFFEROBJECT |
22810 	                                     DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DATAVIEW),
22811 	                                     DUK_BIDX_DATAVIEW_PROTOTYPE);
22812 
22813 	h_val = h_bufarg->buf;
22814 	if (h_val == NULL) {
22815 		return DUK_RET_TYPE_ERROR;
22816 	}
22817 	h_bufobj->buf = h_val;
22818 	DUK_HBUFFER_INCREF(thr, h_val);
22819 	h_bufobj->offset = h_bufarg->offset + offset;
22820 	h_bufobj->length = length;
22821 	DUK_ASSERT(h_bufobj->shift == 0);
22822 	DUK_ASSERT(h_bufobj->elem_type == DUK_HBUFFEROBJECT_ELEM_UINT8);
22823 	h_bufobj->is_view = 1;
22824 
22825 	/* The DataView .buffer property is ordinarily set to the argument
22826 	 * which is an ArrayBuffer.  We accept any duk_hbufferobject as
22827 	 * an argument and .buffer will be set to the argument regardless
22828 	 * of what it is.  This may be a bit confusing if the argument
22829 	 * is e.g. a DataView or another TypedArray view.
22830 	 *
22831 	 * XXX: Copy .buffer property from a DataView/TypedArray argument?
22832 	 * Create a fresh ArrayBuffer for Duktape.Buffer and Node.js Buffer
22833 	 * arguments?  See: test-bug-dataview-buffer-prop.js.
22834 	 */
22835 
22836 	duk_dup(ctx, 0);
22837 	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LC_BUFFER, DUK_PROPDESC_FLAGS_NONE);
22838 	duk_compact(ctx, -1);
22839 
22840 	DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj);
22841 	return 1;
22842 }
22843 #else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
duk_bi_dataview_constructor(duk_context * ctx)22844 DUK_INTERNAL duk_ret_t duk_bi_dataview_constructor(duk_context *ctx) {
22845 	DUK_UNREF(ctx);
22846 	return DUK_RET_UNSUPPORTED_ERROR;
22847 }
22848 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
22849 
22850 /*
22851  *  ArrayBuffer.isView()
22852  */
22853 
22854 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_arraybuffer_isview(duk_context * ctx)22855 DUK_INTERNAL duk_ret_t duk_bi_arraybuffer_isview(duk_context *ctx) {
22856 	duk_hobject *h_obj;
22857 	duk_bool_t ret = 0;
22858 
22859 	h_obj = duk_get_hobject(ctx, 0);
22860 	if (h_obj != NULL && DUK_HOBJECT_IS_BUFFEROBJECT(h_obj)) {
22861 		ret = ((duk_hbufferobject *) h_obj)->is_view;
22862 	}
22863 	duk_push_boolean(ctx, ret);
22864 	return 1;
22865 }
22866 #else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
duk_bi_arraybuffer_isview(duk_context * ctx)22867 DUK_INTERNAL duk_ret_t duk_bi_arraybuffer_isview(duk_context *ctx) {
22868 	DUK_UNREF(ctx);
22869 	return DUK_RET_UNSUPPORTED_ERROR;
22870 }
22871 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
22872 
22873 /*
22874  *  Node.js Buffer: toString([encoding], [start], [end])
22875  */
22876 
22877 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_tostring(duk_context * ctx)22878 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_tostring(duk_context *ctx) {
22879 	duk_hthread *thr;
22880 	duk_hbufferobject *h_this;
22881 	duk_int_t start_offset, end_offset;
22882 	duk_uint8_t *buf_slice;
22883 	duk_size_t slice_length;
22884 
22885 	thr = (duk_hthread *) ctx;
22886 	DUK_UNREF(thr);
22887 
22888 	h_this = duk__get_bufobj_this(ctx);
22889 	if (h_this == NULL) {
22890 		/* XXX: happens e.g. when evaluating: String(Buffer.prototype). */
22891 		duk_push_string(ctx, "[object Object]");
22892 		return 1;
22893 	}
22894 	DUK_ASSERT_HBUFFEROBJECT_VALID(h_this);
22895 
22896 	/* ignore encoding for now */
22897 
22898 	duk__clamp_startend_nonegidx_noshift(ctx, h_this, 1 /*idx_start*/, 2 /*idx_end*/, &start_offset, &end_offset);
22899 
22900 	slice_length = (duk_size_t) (end_offset - start_offset);
22901 	buf_slice = (duk_uint8_t *) duk_push_fixed_buffer(ctx, slice_length);
22902 	DUK_ASSERT(buf_slice != NULL);
22903 
22904 	if (h_this->buf == NULL) {
22905 		goto type_error;
22906 	}
22907 
22908 	if (DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_EXCL(h_this, start_offset + slice_length)) {
22909 		DUK_MEMCPY((void *) buf_slice,
22910 		           (const void *) (DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_this) + start_offset),
22911 		           (size_t) slice_length);
22912 	} else {
22913 		/* not covered, return all zeroes */
22914 		;
22915 	}
22916 
22917 	duk_to_string(ctx, -1);
22918 	return 1;
22919 
22920  type_error:
22921 	return DUK_RET_TYPE_ERROR;
22922 }
22923 #else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
duk_bi_nodejs_buffer_tostring(duk_context * ctx)22924 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_tostring(duk_context *ctx) {
22925 	DUK_UNREF(ctx);
22926 	return DUK_RET_UNSUPPORTED_ERROR;
22927 }
22928 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
22929 
22930 /*
22931  *  Duktape.Buffer: toString(), valueOf()
22932  */
22933 
22934 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_buffer_prototype_tostring_shared(duk_context * ctx)22935 DUK_INTERNAL duk_ret_t duk_bi_buffer_prototype_tostring_shared(duk_context *ctx) {
22936 	duk_hthread *thr;
22937 	duk_tval *tv;
22938 	duk_small_int_t to_string = duk_get_current_magic(ctx);
22939 
22940 	thr = (duk_hthread *) ctx;
22941 	DUK_UNREF(thr);
22942 
22943 	tv = duk_get_borrowed_this_tval(ctx);
22944 	DUK_ASSERT(tv != NULL);
22945 
22946 	if (DUK_TVAL_IS_BUFFER(tv)) {
22947 		duk_hbuffer *h_buf;
22948 		h_buf = DUK_TVAL_GET_BUFFER(tv);
22949 		DUK_ASSERT(h_buf != NULL);
22950 		duk_push_hbuffer(ctx, h_buf);
22951 	} else if (DUK_TVAL_IS_OBJECT(tv)) {
22952 		duk_hobject *h;
22953 		duk_hbufferobject *h_bufobj;
22954 
22955 		/* Accept any duk_hbufferobject, though we're only normally
22956 		 * called for Duktape.Buffer values.
22957 		 */
22958 		h = DUK_TVAL_GET_OBJECT(tv);
22959 		DUK_ASSERT(h != NULL);
22960 		if (!DUK_HOBJECT_IS_BUFFEROBJECT(h)) {
22961 			DUK_DD(DUK_DDPRINT("toString/valueOf() called for a non-bufferobject object"));
22962 			goto type_error;
22963 		}
22964 		h_bufobj = (duk_hbufferobject *) h;
22965 		DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj);
22966 
22967 		if (h_bufobj->buf == NULL) {
22968 			DUK_DD(DUK_DDPRINT("toString/valueOf() called for a bufferobject with NULL buf"));
22969 			goto type_error;
22970 		}
22971 		duk_push_hbuffer(ctx, h_bufobj->buf);
22972 	} else {
22973 		goto type_error;
22974 	}
22975 
22976 	if (to_string) {
22977 		duk_to_string(ctx, -1);
22978 	}
22979 	return 1;
22980 
22981  type_error:
22982 	return DUK_RET_TYPE_ERROR;
22983 }
22984 #else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
duk_bi_buffer_prototype_tostring_shared(duk_context * ctx)22985 DUK_INTERNAL duk_ret_t duk_bi_buffer_prototype_tostring_shared(duk_context *ctx) {
22986 	DUK_UNREF(ctx);
22987 	return DUK_RET_UNSUPPORTED_ERROR;
22988 }
22989 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
22990 
22991 /*
22992  *  Node.js Buffer.prototype: toJSON()
22993  */
22994 
22995 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_tojson(duk_context * ctx)22996 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_tojson(duk_context *ctx) {
22997 	duk_hthread *thr;
22998 	duk_hbufferobject *h_this;
22999 	duk_uint8_t *buf;
23000 	duk_uint_t i;
23001 
23002 	thr = (duk_hthread *) ctx;
23003 	DUK_UNREF(thr);
23004 	h_this = duk__require_bufobj_this(ctx);
23005 	DUK_ASSERT(h_this != NULL);
23006 
23007 	if (h_this->buf == NULL || !DUK_HBUFFEROBJECT_VALID_SLICE(h_this)) {
23008 		/* Serialize uncovered backing buffer as a null; doesn't
23009 		 * really matter as long we're memory safe.
23010 		 */
23011 		duk_push_null(ctx);
23012 		return 1;
23013 	}
23014 
23015 	duk_push_object(ctx);
23016 	duk_push_hstring_stridx(ctx, DUK_STRIDX_UC_BUFFER);
23017 	duk_put_prop_stridx(ctx, -2, DUK_STRIDX_TYPE);
23018 
23019 	duk_push_array(ctx);
23020 	for (i = 0; i < h_this->length; i++) {
23021 		/* XXX: regetting the pointer may be overkill - we're writing
23022 		 * to a side-effect free array here.
23023 		 */
23024 		DUK_ASSERT(h_this->buf != NULL);
23025 		buf = DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_this);
23026 		duk_push_uint(ctx, (duk_uint_t) buf[i]);
23027 		duk_put_prop_index(ctx, -2, (duk_idx_t) i);
23028 	}
23029 	duk_put_prop_stridx(ctx, -2, DUK_STRIDX_DATA);
23030 
23031 	return 1;
23032 }
23033 #else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
duk_bi_nodejs_buffer_tojson(duk_context * ctx)23034 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_tojson(duk_context *ctx) {
23035 	DUK_UNREF(ctx);
23036 	return DUK_RET_UNSUPPORTED_ERROR;
23037 }
23038 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
23039 
23040 /*
23041  *  Node.js Buffer.prototype.equals()
23042  *  Node.js Buffer.prototype.compare()
23043  *  Node.js Buffer.compare()
23044  */
23045 
23046 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_buffer_compare_shared(duk_context * ctx)23047 DUK_INTERNAL duk_ret_t duk_bi_buffer_compare_shared(duk_context *ctx) {
23048 	duk_hthread *thr;
23049 	duk_small_uint_t magic;
23050 	duk_hbufferobject *h_bufarg1;
23051 	duk_hbufferobject *h_bufarg2;
23052 	duk_small_int_t comp_res;
23053 
23054 	thr = (duk_hthread *) ctx;
23055 	DUK_UNREF(thr);
23056 
23057 	magic = duk_get_current_magic(ctx);
23058 	if (magic & 0x02) {
23059 		/* Static call style. */
23060 		h_bufarg1 = duk__require_bufobj_value(ctx, 0);
23061 		h_bufarg2 = duk__require_bufobj_value(ctx, 1);
23062 	} else {
23063 		h_bufarg1 = duk__require_bufobj_this(ctx);
23064 		h_bufarg2 = duk__require_bufobj_value(ctx, 0);
23065 	}
23066 	DUK_ASSERT(h_bufarg1 != NULL);
23067 	DUK_ASSERT(h_bufarg2 != NULL);
23068 
23069 	/* We want to compare the slice/view areas of the arguments.
23070 	 * If either slice/view is invalid (underlying buffer is shorter)
23071 	 * ensure equals() is false, but otherwise the only thing that
23072 	 * matters is to be memory safe.
23073 	 */
23074 
23075 	if (DUK_HBUFFEROBJECT_VALID_SLICE(h_bufarg1) &&
23076 	    DUK_HBUFFEROBJECT_VALID_SLICE(h_bufarg2)) {
23077 		comp_res = duk_js_data_compare((const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufarg1->buf) + h_bufarg1->offset,
23078 		                               (const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufarg2->buf) + h_bufarg2->offset,
23079 		                               (duk_size_t) h_bufarg1->length,
23080 		                               (duk_size_t) h_bufarg2->length);
23081 	} else {
23082 		comp_res = -1;  /* either nonzero value is ok */
23083 	}
23084 
23085 	if (magic & 0x01) {
23086 		/* compare: similar to string comparison but for buffer data. */
23087 		duk_push_int(ctx, comp_res);
23088 	} else {
23089 		/* equals */
23090 		duk_push_boolean(ctx, (comp_res == 0));
23091 	}
23092 
23093 	return 1;
23094 }
23095 #else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
duk_bi_buffer_compare_shared(duk_context * ctx)23096 DUK_INTERNAL duk_ret_t duk_bi_buffer_compare_shared(duk_context *ctx) {
23097 	DUK_UNREF(ctx);
23098 	return DUK_RET_UNSUPPORTED_ERROR;
23099 }
23100 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
23101 
23102 /*
23103  *  Node.js Buffer.prototype.fill()
23104  */
23105 
23106 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_fill(duk_context * ctx)23107 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_fill(duk_context *ctx) {
23108 	duk_hthread *thr;
23109 	duk_hbufferobject *h_this;
23110 	const duk_uint8_t *fill_str_ptr;
23111 	duk_size_t fill_str_len;
23112 	duk_uint8_t fill_value;
23113 	duk_int_t fill_offset;
23114 	duk_int_t fill_end;
23115 	duk_size_t fill_length;
23116 	duk_uint8_t *p;
23117 
23118 	thr = (duk_hthread *) ctx;
23119 	DUK_UNREF(thr);
23120 
23121 	h_this = duk__require_bufobj_this(ctx);
23122 	DUK_ASSERT(h_this != NULL);
23123 	if (h_this->buf == NULL) {
23124 		return DUK_RET_TYPE_ERROR;
23125 	}
23126 
23127 	/* [ value offset end ] */
23128 
23129 	if (duk_is_string(ctx, 0)) {
23130 		fill_str_ptr = (const duk_uint8_t *) duk_get_lstring(ctx, 0, &fill_str_len);
23131 		DUK_ASSERT(fill_str_ptr != NULL);
23132 	} else {
23133 		fill_value = (duk_uint8_t) duk_to_uint32(ctx, 0);
23134 		fill_str_ptr = (const duk_uint8_t *) &fill_value;
23135 		fill_str_len = 1;
23136 	}
23137 
23138 	/* Fill offset handling is more lenient than in Node.js. */
23139 
23140 	duk__clamp_startend_nonegidx_noshift(ctx, h_this, 1 /*idx_start*/, 2 /*idx_end*/, &fill_offset, &fill_end);
23141 
23142 	DUK_DDD(DUK_DDDPRINT("fill: fill_value=%02x, fill_offset=%ld, fill_end=%ld, view length=%ld",
23143 	                     (unsigned int) fill_value, (long) fill_offset, (long) fill_end, (long) h_this->length));
23144 
23145 	DUK_ASSERT(fill_end - fill_offset >= 0);
23146 	DUK_ASSERT(h_this->buf != NULL);
23147 
23148 	p = (DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_this) + fill_offset);
23149 	fill_length = (duk_size_t) (fill_end - fill_offset);
23150 	if (fill_str_len == 1) {
23151 		/* Handle single character fills as memset() even when
23152 		 * the fill data comes from a one-char argument.
23153 		 */
23154 		DUK_MEMSET((void *) p, (int) fill_str_ptr[0], (size_t) fill_length);
23155 	} else if (fill_str_len > 1) {
23156 		duk_size_t i, n, t;
23157 
23158 		for (i = 0, n = (fill_end - fill_offset), t = 0; i < n; i++) {
23159 			p[i] = fill_str_ptr[t++];
23160 			if (t >= fill_str_len) {
23161 				t = 0;
23162 			}
23163 		}
23164 	} else {
23165 		DUK_DDD(DUK_DDDPRINT("zero size fill pattern, ignore silently"));
23166 	}
23167 
23168 	/* Return the Buffer to allow chaining: b.fill(0x11).fill(0x22, 3, 5).toString() */
23169 	duk_push_this(ctx);
23170 	return 1;
23171 }
23172 #else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
duk_bi_nodejs_buffer_fill(duk_context * ctx)23173 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_fill(duk_context *ctx) {
23174 	DUK_UNREF(ctx);
23175 	return DUK_RET_UNSUPPORTED_ERROR;
23176 }
23177 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
23178 
23179 /*
23180  *  Node.js Buffer.prototype.write(string, [offset], [length], [encoding])
23181  */
23182 
23183 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_write(duk_context * ctx)23184 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_write(duk_context *ctx) {
23185 	duk_hthread *thr;
23186 	duk_hbufferobject *h_this;
23187 	duk_uint_t offset;
23188 	duk_uint_t length;
23189 	const duk_uint8_t *str_data;
23190 	duk_size_t str_len;
23191 
23192 	thr = (duk_hthread *) ctx;
23193 	DUK_UNREF(thr);
23194 
23195 	h_this = duk__require_bufobj_this(ctx);
23196 	DUK_ASSERT(h_this != NULL);
23197 
23198 	/* Argument must be a string, e.g. a buffer is not allowed. */
23199 	str_data = (const duk_uint8_t *) duk_require_lstring(ctx, 0, &str_len);
23200 
23201 	duk__resolve_offset_opt_length(ctx, h_this, 1, 2, &offset, &length, 0 /*throw_flag*/);
23202 	DUK_ASSERT(offset <= h_this->length);
23203 	DUK_ASSERT(offset + length <= h_this->length);
23204 
23205 	/* XXX: encoding is ignored now. */
23206 
23207 	if (length > str_len) {
23208 		length = (duk_uint_t) str_len;
23209 	}
23210 
23211 	if (DUK_HBUFFEROBJECT_VALID_SLICE(h_this)) {
23212 		/* Cannot overlap. */
23213 		DUK_MEMCPY((void *) (DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_this) + offset),
23214 		           (const void *) str_data,
23215 		           (size_t) length);
23216 	} else {
23217 		DUK_DDD(DUK_DDDPRINT("write() target buffer is not covered, silent ignore"));
23218 	}
23219 
23220 	duk_push_uint(ctx, length);
23221 	return 1;
23222 }
23223 #else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
duk_bi_nodejs_buffer_write(duk_context * ctx)23224 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_write(duk_context *ctx) {
23225 	DUK_UNREF(ctx);
23226 	return DUK_RET_UNSUPPORTED_ERROR;
23227 }
23228 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
23229 
23230 /*
23231  *  Node.js Buffer.prototype.copy()
23232  */
23233 
23234 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_copy(duk_context * ctx)23235 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_copy(duk_context *ctx) {
23236 	duk_hthread *thr;
23237 	duk_hbufferobject *h_this;
23238 	duk_hbufferobject *h_bufarg;
23239 	duk_int_t source_length;
23240 	duk_int_t target_length;
23241 	duk_int_t target_start, source_start, source_end;
23242 	duk_uint_t target_ustart, source_ustart, source_uend;
23243 	duk_uint_t copy_size = 0;
23244 
23245 	/* [ targetBuffer targetStart sourceStart sourceEnd ] */
23246 
23247 	thr = (duk_hthread *) ctx;
23248 	DUK_UNREF(thr);
23249 
23250 	h_this = duk__require_bufobj_this(ctx);
23251 	h_bufarg = duk__require_bufobj_value(ctx, 0);
23252 	DUK_ASSERT(h_this != NULL);
23253 	DUK_ASSERT(h_bufarg != NULL);
23254 	source_length = (duk_int_t) h_this->length;
23255 	target_length = (duk_int_t) h_bufarg->length;
23256 
23257 	target_start = duk_to_int(ctx, 1);
23258 	source_start = duk_to_int(ctx, 2);
23259 	if (duk_is_undefined(ctx, 3)) {
23260 		source_end = source_length;
23261 	} else {
23262 		source_end = duk_to_int(ctx, 3);
23263 	}
23264 
23265 	DUK_DDD(DUK_DDDPRINT("checking copy args: target_start=%ld, target_length=%ld, "
23266 	                     "source_start=%ld, source_end=%ld, source_length=%ld",
23267 	                     (long) target_start, (long) h_bufarg->length,
23268 	                     (long) source_start, (long) source_end, (long) source_length));
23269 
23270 	/* This behavior mostly mimics Node.js now. */
23271 
23272 	if (source_start < 0 || source_end < 0 || target_start < 0) {
23273 		/* Negative offsets cause a RangeError. */
23274 		goto fail_bounds;
23275 	}
23276 	source_ustart = (duk_uint_t) source_start;
23277 	source_uend = (duk_uint_t) source_end;
23278 	target_ustart = (duk_uint_t) target_start;
23279 	if (source_ustart >= source_uend ||  /* crossed offsets or zero size */
23280 	    source_ustart >= (duk_uint_t) source_length ||  /* source out-of-bounds (but positive) */
23281 	    target_ustart >= (duk_uint_t) target_length) {  /* target out-of-bounds (but positive) */
23282 		goto silent_ignore;
23283 	}
23284 	if (source_uend >= (duk_uint_t) source_length) {
23285 		/* Source end clamped silently to available length. */
23286 		source_uend = source_length;
23287 	}
23288 	copy_size = source_uend - source_ustart;
23289 	if (target_ustart + copy_size > (duk_uint_t) target_length) {
23290 		/* Clamp to target's end if too long.
23291 		 *
23292 		 * NOTE: there's no overflow possibility in the comparison;
23293 		 * both target_ustart and copy_size are >= 0 and based on
23294 		 * values in duk_int_t range.  Adding them as duk_uint_t
23295 		 * values is then guaranteed not to overflow.
23296 		 */
23297 		DUK_ASSERT(target_ustart + copy_size >= target_ustart);  /* no overflow */
23298 		DUK_ASSERT(target_ustart + copy_size >= copy_size);  /* no overflow */
23299 		copy_size = (duk_uint_t) target_length - target_ustart;
23300 	}
23301 
23302 	DUK_DDD(DUK_DDDPRINT("making copy: target_ustart=%lu source_ustart=%lu copy_size=%lu",
23303 	                     (unsigned long) target_ustart, (unsigned long) source_ustart,
23304 	                     (unsigned long) copy_size));
23305 
23306 	DUK_ASSERT(copy_size >= 1);
23307 	DUK_ASSERT(source_ustart <= (duk_uint_t) source_length);
23308 	DUK_ASSERT(source_ustart + copy_size <= (duk_uint_t) source_length);
23309 	DUK_ASSERT(target_ustart <= (duk_uint_t) target_length);
23310 	DUK_ASSERT(target_ustart + copy_size <= (duk_uint_t) target_length);
23311 
23312 	/* Ensure copy is covered by underlying buffers. */
23313 	DUK_ASSERT(h_bufarg->buf != NULL);  /* length check */
23314 	DUK_ASSERT(h_this->buf != NULL);    /* length check */
23315 	if (DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_EXCL(h_bufarg, target_ustart + copy_size) &&
23316 	    DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_EXCL(h_this, source_ustart + copy_size)) {
23317 		/* Must use memmove() because copy area may overlap (source and target
23318 		 * buffer may be the same, or from different slices.
23319 		 */
23320 		DUK_MEMMOVE((void *) (DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_bufarg) + target_ustart),
23321 		            (const void *) (DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_this) + source_ustart),
23322 		            (size_t) copy_size);
23323 	} else {
23324 		DUK_DDD(DUK_DDDPRINT("buffer copy not covered by underlying buffer(s), ignoring"));
23325 	}
23326 
23327  silent_ignore:
23328 	/* Return value is like write(), number of bytes written.
23329 	 * The return value matters because of code like:
23330 	 * "off += buf.copy(...)".
23331          */
23332 	duk_push_uint(ctx, copy_size);
23333 	return 1;
23334 
23335  fail_bounds:
23336 	return DUK_RET_RANGE_ERROR;
23337 }
23338 #else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
duk_bi_nodejs_buffer_copy(duk_context * ctx)23339 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_copy(duk_context *ctx) {
23340 	DUK_UNREF(ctx);
23341 	return DUK_RET_UNSUPPORTED_ERROR;
23342 }
23343 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
23344 
23345 /*
23346  *  TypedArray.prototype.set()
23347  *
23348  *  TypedArray set() is pretty interesting to implement because:
23349  *
23350  *    - The source argument may be a plain array or a typedarray.  If the
23351  *      source is a TypedArray, values are decoded and re-encoded into the
23352  *      target (not as a plain byte copy).  This may happen even when the
23353  *      element byte size is the same, e.g. integer values may be re-encoded
23354  *      into floats.
23355  *
23356  *    - Source and target may refer to the same underlying buffer, so that
23357  *      the set() operation may overlap.  The specification requires that this
23358  *      must work as if a copy was made before the operation.  Note that this
23359  *      is NOT a simple memmove() situation because the source and target
23360  *      byte sizes may be different -- e.g. a 4-byte source (Int8Array) may
23361  *      expand to a 16-byte target (Uint32Array) so that the target overlaps
23362  *      the source both from beginning and the end (unlike in typical memmove).
23363  *
23364  *    - Even if 'buf' pointers of the source and target differ, there's no
23365  *      guarantee that their memory areas don't overlap.  This may be the
23366  *      case with external buffers.
23367  *
23368  *  Even so, it is nice to optimize for the common case:
23369  *
23370  *    - Source and target separate buffers or non-overlapping.
23371  *
23372  *    - Source and target have a compatible type so that a plain byte copy
23373  *      is possible.  Note that while e.g. uint8 and int8 are compatible
23374  *      (coercion one way or another doesn't change the byte representation),
23375  *      e.g. int8 and uint8clamped are NOT compatible when writing int8
23376  *      values into uint8clamped typedarray (-1 would clamp to 0 for instance).
23377  *
23378  *  See test-bi-typedarray-proto-set.js.
23379  */
23380 
23381 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_typedarray_set(duk_context * ctx)23382 DUK_INTERNAL duk_ret_t duk_bi_typedarray_set(duk_context *ctx) {
23383 	duk_hthread *thr;
23384 	duk_hbufferobject *h_this;
23385 	duk_hobject *h_obj;
23386 	duk_uarridx_t i, n;
23387 	duk_int_t offset_signed;
23388 	duk_uint_t offset_elems;
23389 	duk_uint_t offset_bytes;
23390 
23391 	thr = (duk_hthread *) ctx;
23392 	DUK_UNREF(thr);
23393 
23394 	h_this = duk__require_bufobj_this(ctx);
23395 	DUK_ASSERT(h_this != NULL);
23396 	DUK_ASSERT_HBUFFEROBJECT_VALID(h_this);
23397 
23398 	if (h_this->buf == NULL) {
23399 		DUK_DDD(DUK_DDDPRINT("source neutered, skip copy"));
23400 		return 0;
23401 	}
23402 
23403 	h_obj = duk_require_hobject(ctx, 0);
23404 	DUK_ASSERT(h_obj != NULL);
23405 
23406 	/* XXX: V8 throws a TypeError for negative values.  Would it
23407 	 * be more useful to interpret negative offsets here from the
23408 	 * end of the buffer too?
23409 	 */
23410 	offset_signed = duk_to_int(ctx, 1);
23411 	if (offset_signed < 0) {
23412 		return DUK_RET_TYPE_ERROR;
23413 	}
23414 	offset_elems = (duk_uint_t) offset_signed;
23415 	offset_bytes = offset_elems << h_this->shift;
23416 	if ((offset_bytes >> h_this->shift) != offset_elems) {
23417 		/* Byte length would overflow. */
23418 		/* XXX: easier check with less code? */
23419 		return DUK_RET_RANGE_ERROR;
23420 	}
23421 	if (offset_bytes > h_this->length) {
23422 		/* Equality may be OK but >length not.  Checking
23423 		 * this explicitly avoids some overflow cases
23424 		 * below.
23425 		 */
23426 		return DUK_RET_RANGE_ERROR;
23427 	}
23428 	DUK_ASSERT(offset_bytes <= h_this->length);
23429 
23430 	/* Fast path: source is a TypedArray (or any bufferobject). */
23431 
23432 	if (DUK_HOBJECT_IS_BUFFEROBJECT(h_obj)) {
23433 		duk_hbufferobject *h_bufarg;
23434 		duk_uint16_t comp_mask;
23435 		duk_small_int_t no_overlap = 0;
23436 		duk_uint_t src_length;
23437 		duk_uint_t dst_length;
23438 		duk_uint_t dst_length_elems;
23439 		duk_uint8_t *p_src_base;
23440 		duk_uint8_t *p_src_end;
23441 		duk_uint8_t *p_src;
23442 		duk_uint8_t *p_dst_base;
23443 		duk_uint8_t *p_dst;
23444 		duk_small_uint_t src_elem_size;
23445 		duk_small_uint_t dst_elem_size;
23446 
23447 		h_bufarg = (duk_hbufferobject *) h_obj;
23448 		DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufarg);
23449 
23450 		if (h_bufarg->buf == NULL) {
23451 			DUK_DDD(DUK_DDDPRINT("target neutered, skip copy"));
23452 			return 0;
23453 		}
23454 
23455 		/* Nominal size check. */
23456 		src_length = h_bufarg->length;  /* bytes in source */
23457 		dst_length_elems = (src_length >> h_bufarg->shift);  /* elems in source and dest */
23458 		dst_length = dst_length_elems << h_this->shift;  /* bytes in dest */
23459 		if ((dst_length >> h_this->shift) != dst_length_elems) {
23460 			/* Byte length would overflow. */
23461 			/* XXX: easier check with less code? */
23462 			return DUK_RET_RANGE_ERROR;
23463 		}
23464 		DUK_DDD(DUK_DDDPRINT("nominal size check: src_length=%ld, dst_length=%ld",
23465 		                     (long) src_length, (long) dst_length));
23466 		DUK_ASSERT(offset_bytes <= h_this->length);
23467 		if (dst_length > h_this->length - offset_bytes) {
23468 			/* Overflow not an issue because subtraction is used on the right
23469 			 * side and guaranteed to be >= 0.
23470 			 */
23471 			DUK_DDD(DUK_DDDPRINT("copy exceeds target buffer nominal length"));
23472 			return DUK_RET_RANGE_ERROR;
23473 		}
23474 		if (!DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_EXCL(h_this, offset_bytes + dst_length)) {
23475 			DUK_DDD(DUK_DDDPRINT("copy not covered by underlying target buffer, ignore"));
23476 			return 0;
23477 		}
23478 
23479 		p_src_base = DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_bufarg);
23480 		p_dst_base = DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_this) + offset_bytes;
23481 
23482 		/* Check actual underlying buffers for validity and that they
23483 		 * cover the copy.  No side effects are allowed after the check
23484 		 * so that the validity status doesn't change.
23485 		 */
23486 		if (!DUK_HBUFFEROBJECT_VALID_SLICE(h_this) ||
23487 		    !DUK_HBUFFEROBJECT_VALID_SLICE(h_bufarg)) {
23488 			/* The condition could be more narrow and check for the
23489 			 * copy area only, but there's no need for fine grained
23490 			 * behavior when the underlying buffer is misconfigured.
23491 			 */
23492 			DUK_DDD(DUK_DDDPRINT("source and/or target not covered by underlying buffer, skip copy"));
23493 			return 0;
23494 		}
23495 
23496 		/* We want to do a straight memory copy if possible: this is
23497 		 * an important operation because .set() is the TypedArray
23498 		 * way to copy chunks of memory.  However, because set()
23499 		 * conceptually works in terms of elements, not all views are
23500 		 * compatible with direct byte copying.
23501 		 *
23502 		 * If we do manage a direct copy, the "overlap issue" handled
23503 		 * below can just be solved using memmove() because the source
23504 		 * and destination element sizes are necessarily equal.
23505 		 */
23506 
23507 		DUK_ASSERT(h_this->elem_type < sizeof(duk__buffer_elemtype_copy_compatible) / sizeof(duk_uint16_t));
23508 		comp_mask = duk__buffer_elemtype_copy_compatible[h_this->elem_type];
23509 		if (comp_mask & (1 << h_bufarg->elem_type)) {
23510 			DUK_ASSERT(src_length == dst_length);
23511 
23512 			DUK_DDD(DUK_DDDPRINT("fast path: able to use memmove() because views are compatible"));
23513 			DUK_MEMMOVE((void *) p_dst_base, (const void *) p_src_base, (size_t) dst_length);
23514 			return 0;
23515 		}
23516 		DUK_DDD(DUK_DDDPRINT("fast path: views are not compatible with a byte copy, copy by item"));
23517 
23518 		/* We want to avoid making a copy to process set() but that's
23519 		 * not always possible: the source and the target may overlap
23520 		 * and because element sizes are different, the overlap cannot
23521 		 * always be handled with a memmove() or choosing the copy
23522 		 * direction in a certain way.  For example, if source type is
23523 		 * uint8 and target type is uint32, the target area may exceed
23524 		 * the source area from both ends!
23525 		 *
23526 		 * Note that because external buffers may point to the same
23527 		 * memory areas, we must ultimately make this check using
23528 		 * pointers.
23529 		 *
23530 		 * NOTE: careful with side effects: any side effect may cause
23531 		 * a buffer resize (or external buffer pointer/length update)!
23532 		 */
23533 
23534 		DUK_DDD(DUK_DDDPRINT("overlap check: p_src_base=%p, src_length=%ld, "
23535 		                     "p_dst_base=%p, dst_length=%ld",
23536 		                     (void *) p_src_base, (long) src_length,
23537 		                     (void *) p_dst_base, (long) dst_length));
23538 
23539 		if (p_src_base >= p_dst_base + dst_length ||  /* source starts after dest ends */
23540 		    p_src_base + src_length <= p_dst_base) {   /* source ends before dest starts */
23541 			no_overlap = 1;
23542 		}
23543 
23544 		if (!no_overlap) {
23545 			/* There's overlap: the desired end result is that
23546 			 * conceptually a copy is made to avoid "trampling"
23547 			 * of source data by destination writes.  We make
23548 			 * an actual temporary copy to handle this case.
23549 			 */
23550 			duk_uint8_t *p_src_copy;
23551 
23552 			DUK_DDD(DUK_DDDPRINT("there is overlap, make a copy of the source"));
23553 			p_src_copy = (duk_uint8_t *) duk_push_fixed_buffer(ctx, src_length);
23554 			DUK_ASSERT(p_src_copy != NULL);
23555 			DUK_MEMCPY((void *) p_src_copy, (const void *) p_src_base, (size_t) src_length);
23556 
23557 			p_src_base = p_src_copy;  /* use p_src_base from now on */
23558 		}
23559 		/* Value stack intentionally mixed size here. */
23560 
23561 		DUK_DDD(DUK_DDDPRINT("after overlap check: p_src_base=%p, src_length=%ld, "
23562 		                     "p_dst_base=%p, dst_length=%ld, valstack top=%ld",
23563 		                     (void *) p_src_base, (long) src_length,
23564 		                     (void *) p_dst_base, (long) dst_length,
23565 		                     (long) duk_get_top(ctx)));
23566 
23567 		/* Ready to make the copy.  We must proceed element by element
23568 		 * and must avoid any side effects that might cause the buffer
23569 		 * validity check above to become invalid.
23570 		 *
23571 		 * Although we work through the value stack here, only plain
23572 		 * numbers are handled which should be side effect safe.
23573 		 */
23574 
23575 		src_elem_size = 1 << h_bufarg->shift;
23576 		dst_elem_size = 1 << h_this->shift;
23577 		p_src = p_src_base;
23578 		p_dst = p_dst_base;
23579 		p_src_end = p_src_base + src_length;
23580 
23581 		while (p_src != p_src_end) {
23582 			DUK_DDD(DUK_DDDPRINT("fast path per element copy loop: "
23583 			                     "p_src=%p, p_src_end=%p, p_dst=%p",
23584 			                     (void *) p_src, (void *) p_src_end, (void *) p_dst));
23585 			/* A validated read() is always a number, so it's write coercion
23586 			 * is always side effect free an won't invalidate pointers etc.
23587 			 */
23588 			duk_hbufferobject_push_validated_read(ctx, h_bufarg, p_src, src_elem_size);
23589 			duk_hbufferobject_validated_write(ctx, h_this, p_dst, dst_elem_size);
23590 			duk_pop(ctx);
23591 			p_src += src_elem_size;
23592 			p_dst += dst_elem_size;
23593 		}
23594 
23595 		return 0;
23596 	} else {
23597 		/* Slow path: quite slow, but we save space by using the property code
23598 		 * to write coerce target values.  We don't need to worry about overlap
23599 		 * here because the source is not a TypedArray.
23600 		 *
23601 		 * We could use the bufferobject write coercion helper but since the
23602 		 * property read may have arbitrary side effects, full validity checks
23603 		 * would be needed for every element anyway.
23604 		 */
23605 
23606 		n = (duk_uarridx_t) duk_get_length(ctx, 0);
23607 		DUK_ASSERT(offset_bytes <= h_this->length);
23608 		if ((n << h_this->shift) > h_this->length - offset_bytes) {
23609 			/* Overflow not an issue because subtraction is used on the right
23610 			 * side and guaranteed to be >= 0.
23611 			 */
23612 			DUK_DDD(DUK_DDDPRINT("copy exceeds target buffer nominal length"));
23613 			return DUK_RET_RANGE_ERROR;
23614 		}
23615 
23616 		/* There's no need to check for buffer validity status for the
23617 		 * target here: the property access code will do that for each
23618 		 * element.  Moreover, if we did check the validity here, side
23619 		 * effects from reading the source argument might invalidate
23620 		 * the results anyway.
23621 		 */
23622 
23623 		DUK_ASSERT_TOP(ctx, 2);
23624 		duk_push_this(ctx);
23625 
23626 		for (i = 0; i < n; i++) {
23627 			duk_get_prop_index(ctx, 0, i);
23628 			duk_put_prop_index(ctx, 2, offset_elems + i);
23629 		}
23630 	}
23631 
23632 	return 0;
23633 }
23634 #else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
duk_bi_typedarray_set(duk_context * ctx)23635 DUK_INTERNAL duk_ret_t duk_bi_typedarray_set(duk_context *ctx) {
23636 	DUK_UNREF(ctx);
23637 	return DUK_RET_UNSUPPORTED_ERROR;
23638 }
23639 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
23640 
23641 /*
23642  *  Node.js Buffer.prototype.slice([start], [end])
23643  *  ArrayBuffer.prototype.slice(begin, [end])
23644  *  TypedArray.prototype.slice(begin, [end])
23645  *
23646  *  The API calls are almost identical; negative indices are counted from end
23647  *  of buffer, and final indices are clamped (allowing crossed indices).  Main
23648  *  differences:
23649  *
23650  *    - Copy/view behavior; Node.js .slice() and TypedArray .subarray() create
23651  *      views, ArrayBuffer .slice() creates a copy
23652  *
23653  *    - Resulting object has a different class and prototype depending on the
23654  *      call (or 'this' argument)
23655  *
23656  *    - TypedArray .subarray() arguments are element indices, not byte offsets
23657  */
23658 
23659 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_buffer_slice_shared(duk_context * ctx)23660 DUK_INTERNAL duk_ret_t duk_bi_buffer_slice_shared(duk_context *ctx) {
23661 	duk_hthread *thr;
23662 	duk_small_int_t magic;
23663 	duk_small_uint_t res_class_num;
23664 	duk_hobject *res_proto;
23665 	duk_hbufferobject *h_this;
23666 	duk_hbufferobject *h_bufobj;
23667 	duk_hbuffer *h_val;
23668 	duk_int_t start_offset, end_offset;
23669 	duk_uint_t slice_length;
23670 
23671 	thr = (duk_hthread *) ctx;
23672 	DUK_UNREF(thr);
23673 
23674 	/* [ start end ] */
23675 
23676 	magic = duk_get_current_magic(ctx);
23677 	h_this = duk__require_bufobj_this(ctx);
23678 
23679 	/* Slice offsets are element (not byte) offsets, which only matters
23680 	 * for TypedArray views, Node.js Buffer and ArrayBuffer have shift
23681 	 * zero so byte and element offsets are the same.  Negative indices
23682 	 * are counted from end of slice, crossed indices are allowed (and
23683 	 * result in zero length result), and final values are clamped
23684 	 * against the current slice.  There's intentionally no check
23685 	 * against the underlying buffer here.
23686 	 */
23687 
23688 	duk__clamp_startend_negidx_shifted(ctx, h_this, 0 /*idx_start*/, 1 /*idx_end*/, &start_offset, &end_offset);
23689 	DUK_ASSERT(end_offset >= start_offset);
23690 	slice_length = (duk_uint_t) (end_offset - start_offset);
23691 
23692 	/* The resulting buffer object gets the same class and prototype as
23693 	 * the buffer in 'this', e.g. if the input is a Node.js Buffer the
23694 	 * result is a Node.js Buffer; if the input is a Float32Array, the
23695 	 * result is a Float32Array.
23696 	 *
23697 	 * For the class number this seems correct.  The internal prototype
23698 	 * is not so clear: if 'this' is a bufferobject with a non-standard
23699 	 * prototype object, that value gets copied over into the result
23700 	 * (instead of using the standard prototype for that object type).
23701 	 */
23702 
23703 	res_class_num = DUK_HOBJECT_GET_CLASS_NUMBER((duk_hobject *) h_this);
23704 	h_bufobj = duk_push_bufferobject_raw(ctx,
23705 	                                     DUK_HOBJECT_FLAG_EXTENSIBLE |
23706 	                                     DUK_HOBJECT_FLAG_BUFFEROBJECT |
23707 	                                     DUK_HOBJECT_CLASS_AS_FLAGS(res_class_num),
23708 	                                     DUK_BIDX_OBJECT_PROTOTYPE);  /* replaced */
23709 	DUK_ASSERT(h_bufobj != NULL);
23710 	res_proto = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_this);  /* may be NULL */
23711 	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, (duk_hobject *) h_bufobj, res_proto);
23712 
23713 	DUK_ASSERT(h_bufobj->length == 0);
23714 	h_bufobj->shift = h_this->shift;  /* inherit */
23715 	h_bufobj->elem_type = h_this->elem_type;  /* inherit */
23716 	h_bufobj->is_view = magic & 0x01;
23717 	DUK_ASSERT(h_bufobj->is_view == 0 || h_bufobj->is_view == 1);
23718 
23719 	h_val = h_this->buf;
23720 	if (h_val == NULL) {
23721 		return DUK_RET_TYPE_ERROR;
23722 	}
23723 
23724 	if (magic & 0x02) {
23725 		/* non-zero: make copy */
23726 		duk_uint8_t *p_copy;
23727 		duk_size_t copy_length;
23728 
23729 		p_copy = (duk_uint8_t *) duk_push_fixed_buffer(ctx, (duk_size_t) slice_length);
23730 		DUK_ASSERT(p_copy != NULL);
23731 
23732 		/* Copy slice, respecting underlying buffer limits; remainder
23733 		 * is left as zero.
23734 		 */
23735 		copy_length = DUK_HBUFFEROBJECT_CLAMP_BYTELENGTH(h_this, slice_length);
23736 		DUK_MEMCPY((void *) p_copy,
23737 		           (const void *) (DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_this) + start_offset),
23738 		           copy_length);
23739 
23740 		h_val = duk_get_hbuffer(ctx, -1);
23741 		DUK_ASSERT(h_val != NULL);
23742 
23743 		h_bufobj->buf = h_val;
23744 		DUK_HBUFFER_INCREF(thr, h_val);
23745 		h_bufobj->length = slice_length;
23746 		DUK_ASSERT(h_bufobj->offset == 0);
23747 
23748 		duk_pop(ctx);  /* reachable so pop OK */
23749 	} else {
23750 		h_bufobj->buf = h_val;
23751 		DUK_HBUFFER_INCREF(thr, h_val);
23752 		h_bufobj->length = slice_length;
23753 		h_bufobj->offset = (duk_uint_t) (h_this->offset + start_offset);
23754 
23755 		/* Copy the .buffer property, needed for TypedArray.prototype.subarray().
23756 		 *
23757 		 * XXX: limit copy only for TypedArray classes specifically?
23758 		 */
23759 
23760 		duk_push_this(ctx);
23761 		if (duk_get_prop_stridx(ctx, -1, DUK_STRIDX_LC_BUFFER)) {
23762 			duk_xdef_prop_stridx(ctx, -3, DUK_STRIDX_LC_BUFFER, DUK_PROPDESC_FLAGS_NONE);
23763 			duk_pop(ctx);
23764 		} else {
23765 			duk_pop_2(ctx);
23766 		}
23767 	}
23768 	/* unbalanced stack on purpose */
23769 
23770 	DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj);
23771 	return 1;
23772 }
23773 #else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
duk_bi_buffer_slice_shared(duk_context * ctx)23774 DUK_INTERNAL duk_ret_t duk_bi_buffer_slice_shared(duk_context *ctx) {
23775 	DUK_UNREF(ctx);
23776 	return DUK_RET_UNSUPPORTED_ERROR;
23777 }
23778 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
23779 
23780 /*
23781  *  Node.js Buffer.isEncoding()
23782  */
23783 
23784 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_is_encoding(duk_context * ctx)23785 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_is_encoding(duk_context *ctx) {
23786 	const char *encoding;
23787 
23788 	/* only accept lowercase 'utf8' now. */
23789 
23790 	encoding = duk_to_string(ctx, 0);
23791 	DUK_ASSERT(duk_is_string(ctx, 0));  /* guaranteed by duk_to_string() */
23792 	duk_push_boolean(ctx, DUK_STRCMP(encoding, "utf8") == 0);
23793 	return 1;
23794 }
23795 #else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
duk_bi_nodejs_buffer_is_encoding(duk_context * ctx)23796 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_is_encoding(duk_context *ctx) {
23797 	DUK_UNREF(ctx);
23798 	return DUK_RET_UNSUPPORTED_ERROR;
23799 }
23800 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
23801 
23802 /*
23803  *  Node.js Buffer.isBuffer()
23804  */
23805 
23806 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_is_buffer(duk_context * ctx)23807 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_is_buffer(duk_context *ctx) {
23808 	duk_hthread *thr;
23809 	duk_tval *tv;
23810 	duk_hobject *h;
23811 	duk_hobject *h_proto;
23812 	duk_bool_t ret = 0;
23813 
23814 	thr = (duk_hthread *) ctx;
23815 
23816 	DUK_ASSERT(duk_get_top(ctx) >= 1);  /* nargs */
23817 	tv = duk_get_tval(ctx, 0);
23818 	DUK_ASSERT(tv != NULL);
23819 
23820 	if (DUK_TVAL_IS_OBJECT(tv)) {
23821 		h = DUK_TVAL_GET_OBJECT(tv);
23822 		DUK_ASSERT(h != NULL);
23823 
23824 		h_proto = thr->builtins[DUK_BIDX_NODEJS_BUFFER_PROTOTYPE];
23825 		DUK_ASSERT(h_proto != NULL);
23826 
23827 		h = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
23828 		if (h) {
23829 			ret = duk_hobject_prototype_chain_contains(thr, h, h_proto, 0 /*ignore_loop*/);
23830 		}
23831 	}
23832 
23833 	duk_push_boolean(ctx, ret);
23834 	return 1;
23835 }
23836 #else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
duk_bi_nodejs_buffer_is_buffer(duk_context * ctx)23837 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_is_buffer(duk_context *ctx) {
23838 	DUK_UNREF(ctx);
23839 	return DUK_RET_UNSUPPORTED_ERROR;
23840 }
23841 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
23842 
23843 /*
23844  *  Node.js Buffer.byteLength()
23845  */
23846 
23847 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_byte_length(duk_context * ctx)23848 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_byte_length(duk_context *ctx) {
23849 	const char *str;
23850 	duk_size_t len;
23851 
23852 	/* At the moment Buffer(<str>) will just use the string bytes as
23853 	 * is (ignoring encoding), so we return the string length here
23854 	 * unconditionally.
23855 	 */
23856 
23857 	str = duk_to_lstring(ctx, 0, &len);
23858 	DUK_UNREF(str);
23859 	duk_push_size_t(ctx, len);
23860 	return 1;
23861 }
23862 #else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
duk_bi_nodejs_buffer_byte_length(duk_context * ctx)23863 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_byte_length(duk_context *ctx) {
23864 	DUK_UNREF(ctx);
23865 	return DUK_RET_UNSUPPORTED_ERROR;
23866 }
23867 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
23868 
23869 /*
23870  *  Node.js Buffer.concat()
23871  */
23872 
23873 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_concat(duk_context * ctx)23874 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_concat(duk_context *ctx) {
23875 	duk_hthread *thr;
23876 	duk_hobject *h_arg;
23877 	duk_int_t total_length = 0;
23878 	duk_hbufferobject *h_bufobj;
23879 	duk_hbufferobject *h_bufres;
23880 	duk_hbuffer *h_val;
23881 	duk_uint_t i, n;
23882 	duk_uint8_t *p;
23883 	duk_size_t space_left;
23884 	duk_size_t copy_size;
23885 
23886 	thr = (duk_hthread *) ctx;
23887 	DUK_UNREF(thr);
23888 
23889 	/* Node.js accepts only actual Arrays. */
23890 	h_arg = duk_require_hobject(ctx, 0);
23891 	if (DUK_HOBJECT_GET_CLASS_NUMBER(h_arg) != DUK_HOBJECT_CLASS_ARRAY) {
23892 		return DUK_RET_TYPE_ERROR;
23893 	}
23894 
23895 	/* Compute result length and validate argument buffers. */
23896 	n = (duk_uint_t) duk_get_length(ctx, 0);
23897 	for (i = 0; i < n; i++) {
23898 		/* Neutered checks not necessary here: neutered buffers have
23899 		 * zero 'length' so we'll effectively skip them.
23900 		 */
23901 		DUK_ASSERT_TOP(ctx, 2);  /* [ array totalLength ] */
23902 		duk_get_prop_index(ctx, 0, (duk_uarridx_t) i);  /* -> [ array totalLength buf ] */
23903 		h_bufobj = duk__require_bufobj_value(ctx, 2);
23904 		DUK_ASSERT(h_bufobj != NULL);
23905 		total_length += h_bufobj->length;
23906 		duk_pop(ctx);
23907 	}
23908 	if (n == 1) {
23909 		/* For the case n==1 Node.js doesn't seem to type check
23910 		 * the sole member but we do it before returning it.
23911 		 * For this case only the original buffer object is
23912 		 * returned (not a copy).
23913 		 */
23914 		duk_get_prop_index(ctx, 0, 0);
23915 		return 1;
23916 	}
23917 
23918 	/* User totalLength overrides a computed length, but we'll check
23919 	 * every copy in the copy loop.  Note that duk_to_uint() can
23920 	 * technically have arbitrary side effects so we need to recheck
23921 	 * the buffers in the copy loop.
23922 	 */
23923 	if (!duk_is_undefined(ctx, 1) && n > 0) {
23924 		/* For n == 0, Node.js ignores totalLength argument and
23925 		 * returns a zero length buffer.
23926 		 */
23927 		total_length = duk_to_int(ctx, 1);
23928 	}
23929 	if (total_length < 0) {
23930 		return DUK_RET_RANGE_ERROR;
23931 	}
23932 
23933 	h_bufres = duk_push_bufferobject_raw(ctx,
23934 	                                     DUK_HOBJECT_FLAG_EXTENSIBLE |
23935 	                                     DUK_HOBJECT_FLAG_BUFFEROBJECT |
23936 	                                     DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_BUFFER),
23937 	                                     DUK_BIDX_NODEJS_BUFFER_PROTOTYPE);
23938 	DUK_ASSERT(h_bufres != NULL);
23939 
23940 	p = (duk_uint8_t *) duk_push_fixed_buffer(ctx, total_length);
23941 	DUK_ASSERT(p != NULL);
23942 	space_left = total_length;
23943 
23944 	for (i = 0; i < n; i++) {
23945 		DUK_ASSERT_TOP(ctx, 4);  /* [ array totalLength bufres buf ] */
23946 
23947 		duk_get_prop_index(ctx, 0, (duk_uarridx_t) i);
23948 		h_bufobj = duk__require_bufobj_value(ctx, 4);
23949 		DUK_ASSERT(h_bufobj != NULL);
23950 
23951 		copy_size = h_bufobj->length;
23952 		if (copy_size > space_left) {
23953 			copy_size = space_left;
23954 		}
23955 
23956 		if (h_bufobj->buf != NULL &&
23957 		    DUK_HBUFFEROBJECT_VALID_SLICE(h_bufobj)) {
23958 			DUK_MEMCPY((void *) p,
23959 			           (const void *) DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_bufobj),
23960 			           copy_size);
23961 		} else {
23962 			/* Just skip, leaving zeroes in the result. */
23963 			;
23964 		}
23965 		p += copy_size;
23966 		space_left -= copy_size;
23967 
23968 		duk_pop(ctx);
23969 	}
23970 
23971 	h_val = duk_get_hbuffer(ctx, -1);
23972 	DUK_ASSERT(h_val != NULL);
23973 
23974 	duk__set_bufobj_buffer(ctx, h_bufres, h_val);
23975 	DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufres);
23976 
23977 	duk_pop(ctx);  /* pop plain buffer, now reachable through h_bufres */
23978 
23979 	return 1;  /* return h_bufres */
23980 }
23981 #else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
duk_bi_nodejs_buffer_concat(duk_context * ctx)23982 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_concat(duk_context *ctx) {
23983 	DUK_UNREF(ctx);
23984 	return DUK_RET_UNSUPPORTED_ERROR;
23985 }
23986 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
23987 
23988 /*
23989  *  Shared readfield and writefield methods
23990  *
23991  *  The readfield/writefield methods need support for endianness and field
23992  *  types.  All offsets are byte based so no offset shifting is needed.
23993  */
23994 
23995 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
23996 /* Format of magic, bits:
23997  *   0...1: field type; 0=uint8, 1=uint16, 2=uint32, 3=float, 4=double, 5=unused, 6=unused, 7=unused
23998  *       3: endianness: 0=little, 1=big
23999  *       4: signed: 1=yes, 0=no
24000  *       5: typedarray: 1=yes, 0=no
24001  */
24002 #define  DUK__FLD_8BIT         0
24003 #define  DUK__FLD_16BIT        1
24004 #define  DUK__FLD_32BIT        2
24005 #define  DUK__FLD_FLOAT        3
24006 #define  DUK__FLD_DOUBLE       4
24007 #define  DUK__FLD_VARINT       5
24008 #define  DUK__FLD_BIGENDIAN    (1 << 3)
24009 #define  DUK__FLD_SIGNED       (1 << 4)
24010 #define  DUK__FLD_TYPEDARRAY   (1 << 5)
24011 
24012 /* XXX: split into separate functions for each field type? */
duk_bi_buffer_readfield(duk_context * ctx)24013 DUK_INTERNAL duk_ret_t duk_bi_buffer_readfield(duk_context *ctx) {
24014 	duk_hthread *thr;
24015 	duk_small_int_t magic = (duk_small_int_t) duk_get_current_magic(ctx);
24016 	duk_small_int_t magic_ftype;
24017 	duk_small_int_t magic_bigendian;
24018 	duk_small_int_t magic_signed;
24019 	duk_small_int_t magic_typedarray;
24020 	duk_small_int_t endswap;
24021 	duk_hbufferobject *h_this;
24022 	duk_bool_t no_assert;
24023 	duk_int_t offset_signed;
24024 	duk_uint_t offset;
24025 	duk_uint_t buffer_length;
24026 	duk_uint_t check_length;
24027 	duk_uint8_t *buf;
24028 	duk_double_union du;
24029 
24030 	thr = (duk_hthread *) ctx;
24031 	DUK_UNREF(thr);
24032 
24033 	magic_ftype = magic & 0x0007;
24034 	magic_bigendian = magic & 0x0008;
24035 	magic_signed = magic & 0x0010;
24036 	magic_typedarray = magic & 0x0020;
24037 
24038 	h_this = duk__require_bufobj_this(ctx);
24039 	DUK_ASSERT(h_this != NULL);
24040 	buffer_length = h_this->length;
24041 
24042 	/* [ offset noAssert                 ], when ftype != DUK__FLD_VARINT */
24043 	/* [ offset fieldByteLength noAssert ], when ftype == DUK__FLD_VARINT */
24044 	/* [ offset littleEndian             ], when DUK__FLD_TYPEDARRAY (regardless of ftype) */
24045 
24046 	/* Handle TypedArray vs. Node.js Buffer arg differences */
24047 	if (magic_typedarray) {
24048 		no_assert = 0;
24049 #if defined(DUK_USE_INTEGER_LE)
24050 		endswap = !duk_to_boolean(ctx, 1);  /* 1=little endian */
24051 #else
24052 		endswap = duk_to_boolean(ctx, 1);  /* 1=little endian */
24053 #endif
24054 	} else {
24055 		no_assert = duk_to_boolean(ctx, (magic_ftype == DUK__FLD_VARINT) ? 2 : 1);
24056 #if defined(DUK_USE_INTEGER_LE)
24057 		endswap = magic_bigendian;
24058 #else
24059 		endswap = !magic_bigendian;
24060 #endif
24061 	}
24062 
24063 	/* Offset is coerced first to signed integer range and then to unsigned.
24064 	 * This ensures we can add a small byte length (1-8) to the offset in
24065 	 * bound checks and not wrap.
24066 	 */
24067 	offset_signed = duk_to_int(ctx, 0);
24068 	offset = (duk_uint_t) offset_signed;
24069 	if (offset_signed < 0) {
24070 		goto fail_bounds;
24071 	}
24072 
24073 	DUK_DDD(DUK_DDDPRINT("readfield, buffer_length=%ld, offset=%ld, no_assert=%d, "
24074 	                     "magic=%04x, magic_fieldtype=%d, magic_bigendian=%d, magic_signed=%d, "
24075 	                     "endswap=%d",
24076 	                     (long) buffer_length, (long) offset, (int) no_assert,
24077 	                     (unsigned int) magic, (int) magic_ftype, (int) (magic_bigendian >> 3),
24078 	                     (int) (magic_signed >> 4), (int) endswap));
24079 
24080 	/* Update 'buffer_length' to be the effective, safe limit which
24081 	 * takes into account the underlying buffer.  This value will be
24082 	 * potentially invalidated by any side effect.
24083 	 */
24084 	check_length = DUK_HBUFFEROBJECT_CLAMP_BYTELENGTH(h_this, buffer_length);
24085 	DUK_DDD(DUK_DDDPRINT("buffer_length=%ld, check_length=%ld",
24086 	                     (long) buffer_length, (long) check_length));
24087 
24088 	if (h_this->buf) {
24089 		buf = DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_this);
24090 	} else {
24091 		/* Neutered.  We could go into the switch-case safely with
24092 		 * buf == NULL because check_length == 0.  To avoid scanbuild
24093 		 * warnings, fail directly instead.
24094 		 */
24095 		DUK_ASSERT(check_length == 0);
24096 		goto fail_neutered;
24097 	}
24098 	DUK_ASSERT(buf != NULL);
24099 
24100 	switch (magic_ftype) {
24101 	case DUK__FLD_8BIT: {
24102 		duk_uint8_t tmp;
24103 		if (offset + 1U > check_length) {
24104 			goto fail_bounds;
24105 		}
24106 		tmp = buf[offset];
24107 		if (magic_signed) {
24108 			duk_push_int(ctx, (duk_int_t) ((duk_int8_t) tmp));
24109 		} else {
24110 			duk_push_uint(ctx, (duk_uint_t) tmp);
24111 		}
24112 		break;
24113 	}
24114 	case DUK__FLD_16BIT: {
24115 		duk_uint16_t tmp;
24116 		if (offset + 2U > check_length) {
24117 			goto fail_bounds;
24118 		}
24119 		DUK_MEMCPY((void *) du.uc, (const void *) (buf + offset), 2);
24120 		tmp = du.us[0];
24121 		if (endswap) {
24122 			tmp = DUK_BSWAP16(tmp);
24123 		}
24124 		if (magic_signed) {
24125 			duk_push_int(ctx, (duk_int_t) ((duk_int16_t) tmp));
24126 		} else {
24127 			duk_push_uint(ctx, (duk_uint_t) tmp);
24128 		}
24129 		break;
24130 	}
24131 	case DUK__FLD_32BIT: {
24132 		duk_uint32_t tmp;
24133 		if (offset + 4U > check_length) {
24134 			goto fail_bounds;
24135 		}
24136 		DUK_MEMCPY((void *) du.uc, (const void *) (buf + offset), 4);
24137 		tmp = du.ui[0];
24138 		if (endswap) {
24139 			tmp = DUK_BSWAP32(tmp);
24140 		}
24141 		if (magic_signed) {
24142 			duk_push_int(ctx, (duk_int_t) ((duk_int32_t) tmp));
24143 		} else {
24144 			duk_push_uint(ctx, (duk_uint_t) tmp);
24145 		}
24146 		break;
24147 	}
24148 	case DUK__FLD_FLOAT: {
24149 		duk_uint32_t tmp;
24150 		if (offset + 4U > check_length) {
24151 			goto fail_bounds;
24152 		}
24153 		DUK_MEMCPY((void *) du.uc, (const void *) (buf + offset), 4);
24154 		if (endswap) {
24155 			tmp = du.ui[0];
24156 			tmp = DUK_BSWAP32(tmp);
24157 			du.ui[0] = tmp;
24158 		}
24159 		duk_push_number(ctx, (duk_double_t) du.f[0]);
24160 		break;
24161 	}
24162 	case DUK__FLD_DOUBLE: {
24163 		if (offset + 8U > check_length) {
24164 			goto fail_bounds;
24165 		}
24166 		DUK_MEMCPY((void *) du.uc, (const void *) (buf + offset), 8);
24167 		if (endswap) {
24168 			DUK_DBLUNION_BSWAP64(&du);
24169 		}
24170 		duk_push_number(ctx, (duk_double_t) du.d);
24171 		break;
24172 	}
24173 	case DUK__FLD_VARINT: {
24174 		/* Node.js Buffer variable width integer field.  We don't really
24175 		 * care about speed here, so aim for shortest algorithm.
24176 		 */
24177 		duk_int_t field_bytelen;
24178 		duk_int_t i, i_step, i_end;
24179 #if defined(DUK_USE_64BIT_OPS)
24180 		duk_int64_t tmp;
24181 		duk_small_uint_t shift_tmp;
24182 #else
24183 		duk_double_t tmp;
24184 		duk_small_int_t highbyte;
24185 #endif
24186 		const duk_uint8_t *p;
24187 
24188 		field_bytelen = duk_get_int(ctx, 1);  /* avoid side effects! */
24189 		if (field_bytelen < 1 || field_bytelen > 6) {
24190 			goto fail_field_length;
24191 		}
24192 		if (offset + (duk_uint_t) field_bytelen > check_length) {
24193 			goto fail_bounds;
24194 		}
24195 		p = (const duk_uint8_t *) (buf + offset);
24196 
24197 		/* Slow gathering of value using either 64-bit arithmetic
24198 		 * or IEEE doubles if 64-bit types not available.  Handling
24199 		 * of negative numbers is a bit non-obvious in both cases.
24200 		 */
24201 
24202 		if (magic_bigendian) {
24203 			/* Gather in big endian */
24204 			i = 0;
24205 			i_step = 1;
24206 			i_end = field_bytelen;  /* one i_step over */
24207 		} else {
24208 			/* Gather in little endian */
24209 			i = field_bytelen - 1;
24210 			i_step = -1;
24211 			i_end = -1;  /* one i_step over */
24212 		}
24213 
24214 #if defined(DUK_USE_64BIT_OPS)
24215 		tmp = 0;
24216 		do {
24217 			DUK_ASSERT(i >= 0 && i < field_bytelen);
24218 			tmp = (tmp << 8) + (duk_int64_t) p[i];
24219 			i += i_step;
24220 		} while (i != i_end);
24221 
24222 		if (magic_signed) {
24223 			/* Shift to sign extend. */
24224 			shift_tmp = 64 - (field_bytelen * 8);
24225 			tmp = (tmp << shift_tmp) >> shift_tmp;
24226 		}
24227 
24228 		duk_push_i64(ctx, tmp);
24229 #else
24230 		highbyte = p[i];
24231 		if (magic_signed && (highbyte & 0x80) != 0) {
24232 			/* 0xff => 255 - 256 = -1; 0x80 => 128 - 256 = -128 */
24233 			tmp = (duk_double_t) (highbyte - 256);
24234 		} else {
24235 			tmp = (duk_double_t) highbyte;
24236 		}
24237 		for (;;) {
24238 			i += i_step;
24239 			if (i == i_end) {
24240 				break;
24241 			}
24242 			DUK_ASSERT(i >= 0 && i < field_bytelen);
24243 			tmp = (tmp * 256.0) + (duk_double_t) p[i];
24244 		}
24245 
24246 		duk_push_number(ctx, tmp);
24247 #endif
24248 		break;
24249 	}
24250 	default: {  /* should never happen but default here */
24251 		goto fail_bounds;
24252 	}
24253 	}
24254 
24255 	return 1;
24256 
24257  fail_neutered:
24258  fail_field_length:
24259  fail_bounds:
24260 	if (no_assert) {
24261 		/* Node.js return value for noAssert out-of-bounds reads is
24262 		 * usually (but not always) NaN.  Return NaN consistently.
24263 		 */
24264 		duk_push_nan(ctx);
24265 		return 1;
24266 	}
24267 
24268 	return DUK_RET_RANGE_ERROR;
24269 }
24270 #else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
duk_bi_buffer_readfield(duk_context * ctx)24271 DUK_INTERNAL duk_ret_t duk_bi_buffer_readfield(duk_context *ctx) {
24272 	DUK_UNREF(ctx);
24273 	return DUK_RET_UNSUPPORTED_ERROR;
24274 }
24275 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
24276 
24277 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
24278 /* XXX: split into separate functions for each field type? */
duk_bi_buffer_writefield(duk_context * ctx)24279 DUK_INTERNAL duk_ret_t duk_bi_buffer_writefield(duk_context *ctx) {
24280 	duk_hthread *thr;
24281 	duk_small_int_t magic = (duk_small_int_t) duk_get_current_magic(ctx);
24282 	duk_small_int_t magic_ftype;
24283 	duk_small_int_t magic_bigendian;
24284 	duk_small_int_t magic_signed;
24285 	duk_small_int_t magic_typedarray;
24286 	duk_small_int_t endswap;
24287 	duk_hbufferobject *h_this;
24288 	duk_bool_t no_assert;
24289 	duk_int_t offset_signed;
24290 	duk_uint_t offset;
24291 	duk_uint_t buffer_length;
24292 	duk_uint_t check_length;
24293 	duk_uint8_t *buf;
24294 	duk_double_union du;
24295 	duk_int_t nbytes = 0;
24296 
24297 	thr = (duk_hthread *) ctx;
24298 	DUK_UNREF(thr);
24299 
24300 	magic_ftype = magic & 0x0007;
24301 	magic_bigendian = magic & 0x0008;
24302 	magic_signed = magic & 0x0010;
24303 	magic_typedarray = magic & 0x0020;
24304 	DUK_UNREF(magic_signed);
24305 
24306 	h_this = duk__require_bufobj_this(ctx);
24307 	DUK_ASSERT(h_this != NULL);
24308 	buffer_length = h_this->length;
24309 
24310 	/* [ value  offset noAssert                 ], when ftype != DUK__FLD_VARINT */
24311 	/* [ value  offset fieldByteLength noAssert ], when ftype == DUK__FLD_VARINT */
24312 	/* [ offset value  littleEndian             ], when DUK__FLD_TYPEDARRAY (regardless of ftype) */
24313 
24314 	/* Handle TypedArray vs. Node.js Buffer arg differences */
24315 	if (magic_typedarray) {
24316 		no_assert = 0;
24317 #if defined(DUK_USE_INTEGER_LE)
24318 		endswap = !duk_to_boolean(ctx, 2);  /* 1=little endian */
24319 #else
24320 		endswap = duk_to_boolean(ctx, 2);  /* 1=little endian */
24321 #endif
24322 		duk_swap(ctx, 0, 1);  /* offset/value order different from Node.js */
24323 	} else {
24324 		no_assert = duk_to_boolean(ctx, (magic_ftype == DUK__FLD_VARINT) ? 3 : 2);
24325 #if defined(DUK_USE_INTEGER_LE)
24326 		endswap = magic_bigendian;
24327 #else
24328 		endswap = !magic_bigendian;
24329 #endif
24330 	}
24331 
24332 	/* Offset is coerced first to signed integer range and then to unsigned.
24333 	 * This ensures we can add a small byte length (1-8) to the offset in
24334 	 * bound checks and not wrap.
24335 	 */
24336 	offset_signed = duk_to_int(ctx, 1);
24337 	offset = (duk_uint_t) offset_signed;
24338 
24339 	/* We need 'nbytes' even for a failed offset; return value must be
24340 	 * (offset + nbytes) even when write fails due to invalid offset.
24341 	 */
24342 	if (magic_ftype != DUK__FLD_VARINT) {
24343 		DUK_ASSERT(magic_ftype >= 0 && magic_ftype < (duk_small_int_t) (sizeof(duk__buffer_nbytes_from_fldtype) / sizeof(duk_uint8_t)));
24344 		nbytes = duk__buffer_nbytes_from_fldtype[magic_ftype];
24345 	} else {
24346 		nbytes = duk_get_int(ctx, 2);
24347 		if (nbytes < 1 || nbytes > 6) {
24348 			goto fail_field_length;
24349 		}
24350 	}
24351 	DUK_ASSERT(nbytes >= 1 && nbytes <= 8);
24352 
24353 	/* Now we can check offset validity. */
24354 	if (offset_signed < 0) {
24355 		goto fail_bounds;
24356 	}
24357 
24358 	DUK_DDD(DUK_DDDPRINT("writefield, value=%!T, buffer_length=%ld, offset=%ld, no_assert=%d, "
24359 	                     "magic=%04x, magic_fieldtype=%d, magic_bigendian=%d, magic_signed=%d, "
24360 	                     "endswap=%d",
24361 	                     duk_get_tval(ctx, 0), (long) buffer_length, (long) offset, (int) no_assert,
24362 	                     (unsigned int) magic, (int) magic_ftype, (int) (magic_bigendian >> 3),
24363 	                     (int) (magic_signed >> 4), (int) endswap));
24364 
24365 	/* Coerce value to a number before computing check_length, so that
24366 	 * the field type specific coercion below can't have side effects
24367 	 * that would invalidate check_length.
24368 	 */
24369 	duk_to_number(ctx, 0);
24370 
24371 	/* Update 'buffer_length' to be the effective, safe limit which
24372 	 * takes into account the underlying buffer.  This value will be
24373 	 * potentially invalidated by any side effect.
24374 	 */
24375 	check_length = DUK_HBUFFEROBJECT_CLAMP_BYTELENGTH(h_this, buffer_length);
24376 	DUK_DDD(DUK_DDDPRINT("buffer_length=%ld, check_length=%ld",
24377 	                     (long) buffer_length, (long) check_length));
24378 
24379 	if (h_this->buf) {
24380 		buf = DUK_HBUFFEROBJECT_GET_SLICE_BASE(thr->heap, h_this);
24381 	} else {
24382 		/* Neutered.  We could go into the switch-case safely with
24383 		 * buf == NULL because check_length == 0.  To avoid scanbuild
24384 		 * warnings, fail directly instead.
24385 		 */
24386 		DUK_ASSERT(check_length == 0);
24387 		goto fail_neutered;
24388 	}
24389 	DUK_ASSERT(buf != NULL);
24390 
24391 	switch (magic_ftype) {
24392 	case DUK__FLD_8BIT: {
24393 		if (offset + 1U > check_length) {
24394 			goto fail_bounds;
24395 		}
24396 		/* sign doesn't matter when writing */
24397 		buf[offset] = (duk_uint8_t) duk_to_uint32(ctx, 0);
24398 		break;
24399 	}
24400 	case DUK__FLD_16BIT: {
24401 		duk_uint16_t tmp;
24402 		if (offset + 2U > check_length) {
24403 			goto fail_bounds;
24404 		}
24405 		tmp = (duk_uint16_t) duk_to_uint32(ctx, 0);
24406 		if (endswap) {
24407 			tmp = DUK_BSWAP16(tmp);
24408 		}
24409 		du.us[0] = tmp;
24410 		/* sign doesn't matter when writing */
24411 		DUK_MEMCPY((void *) (buf + offset), (const void *) du.uc, 2);
24412 		break;
24413 	}
24414 	case DUK__FLD_32BIT: {
24415 		duk_uint32_t tmp;
24416 		if (offset + 4U > check_length) {
24417 			goto fail_bounds;
24418 		}
24419 		tmp = (duk_uint32_t) duk_to_uint32(ctx, 0);
24420 		if (endswap) {
24421 			tmp = DUK_BSWAP32(tmp);
24422 		}
24423 		du.ui[0] = tmp;
24424 		/* sign doesn't matter when writing */
24425 		DUK_MEMCPY((void *) (buf + offset), (const void *) du.uc, 4);
24426 		break;
24427 	}
24428 	case DUK__FLD_FLOAT: {
24429 		duk_uint32_t tmp;
24430 		if (offset + 4U > check_length) {
24431 			goto fail_bounds;
24432 		}
24433 		du.f[0] = (duk_float_t) duk_to_number(ctx, 0);
24434 		if (endswap) {
24435 			tmp = du.ui[0];
24436 			tmp = DUK_BSWAP32(tmp);
24437 			du.ui[0] = tmp;
24438 		}
24439 		/* sign doesn't matter when writing */
24440 		DUK_MEMCPY((void *) (buf + offset), (const void *) du.uc, 4);
24441 		break;
24442 	}
24443 	case DUK__FLD_DOUBLE: {
24444 		if (offset + 8U > check_length) {
24445 			goto fail_bounds;
24446 		}
24447 		du.d = (duk_double_t) duk_to_number(ctx, 0);
24448 		if (endswap) {
24449 			DUK_DBLUNION_BSWAP64(&du);
24450 		}
24451 		/* sign doesn't matter when writing */
24452 		DUK_MEMCPY((void *) (buf + offset), (const void *) du.uc, 8);
24453 		break;
24454 	}
24455 	case DUK__FLD_VARINT: {
24456 		/* Node.js Buffer variable width integer field.  We don't really
24457 		 * care about speed here, so aim for shortest algorithm.
24458 		 */
24459 		duk_int_t field_bytelen;
24460 		duk_int_t i, i_step, i_end;
24461 #if defined(DUK_USE_64BIT_OPS)
24462 		duk_int64_t tmp;
24463 #else
24464 		duk_double_t tmp;
24465 #endif
24466 		duk_uint8_t *p;
24467 
24468 		field_bytelen = (duk_int_t) nbytes;
24469 		if (offset + (duk_uint_t) field_bytelen > check_length) {
24470 			goto fail_bounds;
24471 		}
24472 
24473 		/* Slow writing of value using either 64-bit arithmetic
24474 		 * or IEEE doubles if 64-bit types not available.  There's
24475 		 * no special sign handling when writing varints.
24476 		 */
24477 
24478 		if (magic_bigendian) {
24479 			/* Write in big endian */
24480 			i = field_bytelen;  /* one i_step added at top of loop */
24481 			i_step = -1;
24482 			i_end = 0;
24483 		} else {
24484 			/* Write in little endian */
24485 			i = -1;  /* one i_step added at top of loop */
24486 			i_step = 1;
24487 			i_end = field_bytelen - 1;
24488 		}
24489 
24490 		/* XXX: The duk_to_number() cast followed by integer coercion
24491 		 * is platform specific so NaN, +/- Infinity, and out-of-bounds
24492 		 * values result in platform specific output now.
24493 		 * See: test-bi-nodejs-buffer-proto-varint-special.js
24494 		 */
24495 
24496 #if defined(DUK_USE_64BIT_OPS)
24497 		tmp = (duk_int64_t) duk_to_number(ctx, 0);
24498 		p = (duk_uint8_t *) (buf + offset);
24499 		do {
24500 			i += i_step;
24501 			DUK_ASSERT(i >= 0 && i < field_bytelen);
24502 			p[i] = (duk_uint8_t) (tmp & 0xff);
24503 			tmp = tmp >> 8;  /* unnecessary shift for last byte */
24504 		} while (i != i_end);
24505 #else
24506 		tmp = duk_to_number(ctx, 0);
24507 		p = (duk_uint8_t *) (buf + offset);
24508 		do {
24509 			i += i_step;
24510 			tmp = DUK_FLOOR(tmp);
24511 			DUK_ASSERT(i >= 0 && i < field_bytelen);
24512 			p[i] = (duk_uint8_t) (DUK_FMOD(tmp, 256.0));
24513 			tmp = tmp / 256.0;  /* unnecessary div for last byte */
24514 		} while (i != i_end);
24515 #endif
24516 		break;
24517 	}
24518 	default: {  /* should never happen but default here */
24519 		goto fail_bounds;
24520 	}
24521 	}
24522 
24523 	/* Node.js Buffer: return offset + #bytes written (i.e. next
24524 	 * write offset).
24525 	 */
24526 	if (magic_typedarray) {
24527 		/* For TypedArrays 'undefined' return value is specified
24528 		 * by ES6 (matches V8).
24529 		 */
24530 		return 0;
24531 	}
24532 	duk_push_uint(ctx, offset + nbytes);
24533 	return 1;
24534 
24535  fail_neutered:
24536  fail_field_length:
24537  fail_bounds:
24538 	if (no_assert) {
24539 		/* Node.js return value for failed writes is offset + #bytes
24540 		 * that would have been written.
24541 		 */
24542 		/* XXX: for negative input offsets, 'offset' will be a large
24543 		 * positive value so the result here is confusing.
24544 		 */
24545 		if (magic_typedarray) {
24546 			return 0;
24547 		}
24548 		duk_push_uint(ctx, offset + nbytes);
24549 		return 1;
24550 	}
24551 	return DUK_RET_RANGE_ERROR;
24552 }
24553 #else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
duk_bi_buffer_writefield(duk_context * ctx)24554 DUK_INTERNAL duk_ret_t duk_bi_buffer_writefield(duk_context *ctx) {
24555 	DUK_UNREF(ctx);
24556 	return DUK_RET_UNSUPPORTED_ERROR;
24557 }
24558 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
24559 
24560 #undef  DUK__FLD_8BIT
24561 #undef  DUK__FLD_16BIT
24562 #undef  DUK__FLD_32BIT
24563 #undef  DUK__FLD_FLOAT
24564 #undef  DUK__FLD_DOUBLE
24565 #undef  DUK__FLD_VARINT
24566 #undef  DUK__FLD_BIGENDIAN
24567 #undef  DUK__FLD_SIGNED
24568 #undef  DUK__FLD_TYPEDARRAY
24569 /*
24570  *  Date built-ins
24571  *
24572  *  Unlike most built-ins, Date has some platform dependencies for getting
24573  *  UTC time, converting between UTC and local time, and parsing and
24574  *  formatting time values.  These are all abstracted behind DUK_USE_xxx
24575  *  config options.  There are built-in platform specific providers for
24576  *  POSIX and Windows, but external providers can also be used.
24577  *
24578  *  See doc/datetime.rst.
24579  *
24580  */
24581 
24582 /* include removed: duk_internal.h */
24583 
24584 /*
24585  *  Forward declarations
24586  */
24587 
24588 DUK_LOCAL_DECL duk_double_t duk__push_this_get_timeval_tzoffset(duk_context *ctx, duk_small_uint_t flags, duk_int_t *out_tzoffset);
24589 DUK_LOCAL_DECL duk_double_t duk__push_this_get_timeval(duk_context *ctx, duk_small_uint_t flags);
24590 DUK_LOCAL_DECL void duk__twodigit_year_fixup(duk_context *ctx, duk_idx_t idx_val);
24591 DUK_LOCAL_DECL duk_ret_t duk__set_this_timeval_from_dparts(duk_context *ctx, duk_double_t *dparts, duk_small_uint_t flags);
24592 
24593 /*
24594  *  Other file level defines
24595  */
24596 
24597 /* Debug macro to print all parts and dparts (used manually because of debug level). */
24598 #define  DUK__DPRINT_PARTS_AND_DPARTS(parts,dparts)  do { \
24599 		DUK_D(DUK_DPRINT("parts: %ld %ld %ld %ld %ld %ld %ld %ld, dparts: %lf %lf %lf %lf %lf %lf %lf %lf", \
24600 		                 (long) (parts)[0], (long) (parts)[1], \
24601 		                 (long) (parts)[2], (long) (parts)[3], \
24602 		                 (long) (parts)[4], (long) (parts)[5], \
24603 		                 (long) (parts)[6], (long) (parts)[7], \
24604 		                 (double) (dparts)[0], (double) (dparts)[1], \
24605 		                 (double) (dparts)[2], (double) (dparts)[3], \
24606 		                 (double) (dparts)[4], (double) (dparts)[5], \
24607 		                 (double) (dparts)[6], (double) (dparts)[7])); \
24608 	} while (0)
24609 #define  DUK__DPRINT_PARTS(parts)  do { \
24610 		DUK_D(DUK_DPRINT("parts: %ld %ld %ld %ld %ld %ld %ld %ld", \
24611 		                 (long) (parts)[0], (long) (parts)[1], \
24612 		                 (long) (parts)[2], (long) (parts)[3], \
24613 		                 (long) (parts)[4], (long) (parts)[5], \
24614 		                 (long) (parts)[6], (long) (parts)[7])); \
24615 	} while (0)
24616 #define  DUK__DPRINT_DPARTS(dparts)  do { \
24617 		DUK_D(DUK_DPRINT("dparts: %lf %lf %lf %lf %lf %lf %lf %lf", \
24618 		                 (double) (dparts)[0], (double) (dparts)[1], \
24619 		                 (double) (dparts)[2], (double) (dparts)[3], \
24620 		                 (double) (dparts)[4], (double) (dparts)[5], \
24621 		                 (double) (dparts)[6], (double) (dparts)[7])); \
24622 	} while (0)
24623 
24624 /* Equivalent year for DST calculations outside [1970,2038[ range, see
24625  * E5 Section 15.9.1.8.  Equivalent year has the same leap-year-ness and
24626  * starts with the same weekday on Jan 1.
24627  * https://bugzilla.mozilla.org/show_bug.cgi?id=351066
24628  */
24629 #define DUK__YEAR(x) ((duk_uint8_t) ((x) - 1970))
24630 DUK_LOCAL duk_uint8_t duk__date_equivyear[14] = {
24631 #if 1
24632 	/* This is based on V8 EquivalentYear() algorithm (see src/genequivyear.py):
24633 	 * http://code.google.com/p/v8/source/browse/trunk/src/date.h#146
24634 	 */
24635 
24636 	/* non-leap year: sunday, monday, ... */
24637 	DUK__YEAR(2023), DUK__YEAR(2035), DUK__YEAR(2019), DUK__YEAR(2031),
24638 	DUK__YEAR(2015), DUK__YEAR(2027), DUK__YEAR(2011),
24639 
24640 	/* leap year: sunday, monday, ... */
24641 	DUK__YEAR(2012), DUK__YEAR(2024), DUK__YEAR(2008), DUK__YEAR(2020),
24642 	DUK__YEAR(2032), DUK__YEAR(2016), DUK__YEAR(2028)
24643 #endif
24644 
24645 #if 0
24646 	/* This is based on Rhino EquivalentYear() algorithm:
24647 	 * https://github.com/mozilla/rhino/blob/f99cc11d616f0cdda2c42bde72b3484df6182947/src/org/mozilla/javascript/NativeDate.java
24648 	 */
24649 
24650 	/* non-leap year: sunday, monday, ... */
24651 	DUK__YEAR(1978), DUK__YEAR(1973), DUK__YEAR(1985), DUK__YEAR(1986),
24652 	DUK__YEAR(1981), DUK__YEAR(1971), DUK__YEAR(1977),
24653 
24654 	/* leap year: sunday, monday, ... */
24655 	DUK__YEAR(1984), DUK__YEAR(1996), DUK__YEAR(1980), DUK__YEAR(1992),
24656 	DUK__YEAR(1976), DUK__YEAR(1988), DUK__YEAR(1972)
24657 #endif
24658 };
24659 #undef DUK__YEAR
24660 
24661 /*
24662  *  ISO 8601 subset parser.
24663  */
24664 
24665 /* Parser part count. */
24666 #define DUK__NUM_ISO8601_PARSER_PARTS  9
24667 
24668 /* Parser part indices. */
24669 #define DUK__PI_YEAR         0
24670 #define DUK__PI_MONTH        1
24671 #define DUK__PI_DAY          2
24672 #define DUK__PI_HOUR         3
24673 #define DUK__PI_MINUTE       4
24674 #define DUK__PI_SECOND       5
24675 #define DUK__PI_MILLISECOND  6
24676 #define DUK__PI_TZHOUR       7
24677 #define DUK__PI_TZMINUTE     8
24678 
24679 /* Parser part masks. */
24680 #define DUK__PM_YEAR         (1 << DUK__PI_YEAR)
24681 #define DUK__PM_MONTH        (1 << DUK__PI_MONTH)
24682 #define DUK__PM_DAY          (1 << DUK__PI_DAY)
24683 #define DUK__PM_HOUR         (1 << DUK__PI_HOUR)
24684 #define DUK__PM_MINUTE       (1 << DUK__PI_MINUTE)
24685 #define DUK__PM_SECOND       (1 << DUK__PI_SECOND)
24686 #define DUK__PM_MILLISECOND  (1 << DUK__PI_MILLISECOND)
24687 #define DUK__PM_TZHOUR       (1 << DUK__PI_TZHOUR)
24688 #define DUK__PM_TZMINUTE     (1 << DUK__PI_TZMINUTE)
24689 
24690 /* Parser separator indices. */
24691 #define DUK__SI_PLUS         0
24692 #define DUK__SI_MINUS        1
24693 #define DUK__SI_T            2
24694 #define DUK__SI_SPACE        3
24695 #define DUK__SI_COLON        4
24696 #define DUK__SI_PERIOD       5
24697 #define DUK__SI_Z            6
24698 #define DUK__SI_NUL          7
24699 
24700 /* Parser separator masks. */
24701 #define DUK__SM_PLUS         (1 << DUK__SI_PLUS)
24702 #define DUK__SM_MINUS        (1 << DUK__SI_MINUS)
24703 #define DUK__SM_T            (1 << DUK__SI_T)
24704 #define DUK__SM_SPACE        (1 << DUK__SI_SPACE)
24705 #define DUK__SM_COLON        (1 << DUK__SI_COLON)
24706 #define DUK__SM_PERIOD       (1 << DUK__SI_PERIOD)
24707 #define DUK__SM_Z            (1 << DUK__SI_Z)
24708 #define DUK__SM_NUL          (1 << DUK__SI_NUL)
24709 
24710 /* Rule control flags. */
24711 #define DUK__CF_NEG          (1 << 0)  /* continue matching, set neg_tzoffset flag */
24712 #define DUK__CF_ACCEPT       (1 << 1)  /* accept string */
24713 #define DUK__CF_ACCEPT_NUL   (1 << 2)  /* accept string if next char is NUL (otherwise reject) */
24714 
24715 #define DUK__PACK_RULE(partmask,sepmask,nextpart,flags)  \
24716 	((duk_uint32_t) (partmask) + \
24717 	 (((duk_uint32_t) (sepmask)) << 9) + \
24718 	 (((duk_uint32_t) (nextpart)) << 17) + \
24719 	 (((duk_uint32_t) (flags)) << 21))
24720 
24721 #define DUK__UNPACK_RULE(rule,var_nextidx,var_flags)  do { \
24722 		(var_nextidx) = (duk_small_uint_t) (((rule) >> 17) & 0x0f); \
24723 		(var_flags) = (duk_small_uint_t) ((rule) >> 21); \
24724 	} while (0)
24725 
24726 #define DUK__RULE_MASK_PART_SEP  0x1ffffUL
24727 
24728 /* Matching separator index is used in the control table */
24729 DUK_LOCAL const duk_uint8_t duk__parse_iso8601_seps[] = {
24730 	DUK_ASC_PLUS /*0*/, DUK_ASC_MINUS /*1*/, DUK_ASC_UC_T /*2*/, DUK_ASC_SPACE /*3*/,
24731 	DUK_ASC_COLON /*4*/, DUK_ASC_PERIOD /*5*/, DUK_ASC_UC_Z /*6*/, DUK_ASC_NUL /*7*/
24732 };
24733 
24734 /* Rule table: first matching rule is used to determine what to do next. */
24735 DUK_LOCAL const duk_uint32_t duk__parse_iso8601_control[] = {
24736 	DUK__PACK_RULE(DUK__PM_YEAR, DUK__SM_MINUS, DUK__PI_MONTH, 0),
24737 	DUK__PACK_RULE(DUK__PM_MONTH, DUK__SM_MINUS, DUK__PI_DAY, 0),
24738 	DUK__PACK_RULE(DUK__PM_YEAR | DUK__PM_MONTH | DUK__PM_DAY, DUK__SM_T | DUK__SM_SPACE, DUK__PI_HOUR, 0),
24739 	DUK__PACK_RULE(DUK__PM_HOUR, DUK__SM_COLON, DUK__PI_MINUTE, 0),
24740 	DUK__PACK_RULE(DUK__PM_MINUTE, DUK__SM_COLON, DUK__PI_SECOND, 0),
24741 	DUK__PACK_RULE(DUK__PM_SECOND, DUK__SM_PERIOD, DUK__PI_MILLISECOND, 0),
24742 	DUK__PACK_RULE(DUK__PM_TZHOUR, DUK__SM_COLON, DUK__PI_TZMINUTE, 0),
24743 	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),
24744 	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),
24745 	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),
24746 	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)
24747 
24748 	/* Note1: the specification doesn't require matching a time form with
24749 	 *        just hours ("HH"), but we accept it here, e.g. "2012-01-02T12Z".
24750 	 *
24751 	 * Note2: the specification doesn't require matching a timezone offset
24752 	 *        with just hours ("HH"), but accept it here, e.g. "2012-01-02T03:04:05+02"
24753 	 */
24754 };
24755 
duk__parse_string_iso8601_subset(duk_context * ctx,const char * str)24756 DUK_LOCAL duk_bool_t duk__parse_string_iso8601_subset(duk_context *ctx, const char *str) {
24757 	duk_int_t parts[DUK__NUM_ISO8601_PARSER_PARTS];
24758 	duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
24759 	duk_double_t d;
24760 	const duk_uint8_t *p;
24761 	duk_small_uint_t part_idx = 0;
24762 	duk_int_t accum = 0;
24763 	duk_small_uint_t ndigits = 0;
24764 	duk_bool_t neg_year = 0;
24765 	duk_bool_t neg_tzoffset = 0;
24766 	duk_uint_fast8_t ch;
24767 	duk_small_uint_t i;
24768 
24769 	/* During parsing, month and day are one-based; set defaults here. */
24770 	DUK_MEMZERO(parts, sizeof(parts));
24771 	DUK_ASSERT(parts[DUK_DATE_IDX_YEAR] == 0);  /* don't care value, year is mandatory */
24772 	parts[DUK_DATE_IDX_MONTH] = 1;
24773 	parts[DUK_DATE_IDX_DAY] = 1;
24774 
24775 	/* Special handling for year sign. */
24776 	p = (const duk_uint8_t *) str;
24777 	ch = p[0];
24778 	if (ch == DUK_ASC_PLUS) {
24779 		p++;
24780 	} else if (ch == DUK_ASC_MINUS) {
24781 		neg_year = 1;
24782 		p++;
24783 	}
24784 
24785 	for (;;) {
24786 		ch = *p++;
24787 		DUK_DDD(DUK_DDDPRINT("parsing, part_idx=%ld, char=%ld ('%c')",
24788 		                     (long) part_idx, (long) ch,
24789 		                     (int) ((ch >= 0x20 && ch <= 0x7e) ? ch : DUK_ASC_QUESTION)));
24790 
24791 		if (ch >= DUK_ASC_0 && ch <= DUK_ASC_9) {
24792 			if (ndigits >= 9) {
24793 				DUK_DDD(DUK_DDDPRINT("too many digits -> reject"));
24794 				goto reject;
24795 			}
24796 			if (part_idx == DUK__PI_MILLISECOND /*msec*/ && ndigits >= 3) {
24797 				/* ignore millisecond fractions after 3 */
24798 			} else {
24799 				accum = accum * 10 + ((duk_int_t) ch) - ((duk_int_t) DUK_ASC_0) + 0x00;
24800 				ndigits++;
24801 			}
24802 		} else {
24803 			duk_uint_fast32_t match_val;
24804 			duk_small_int_t sep_idx;
24805 
24806 			if (ndigits <= 0) {
24807 				goto reject;
24808 			}
24809 			if (part_idx == DUK__PI_MILLISECOND) {
24810 				/* complete the millisecond field */
24811 				while (ndigits < 3) {
24812 					accum *= 10;
24813 					ndigits++;
24814 				}
24815 			}
24816 			parts[part_idx] = accum;
24817 			DUK_DDD(DUK_DDDPRINT("wrote part %ld -> value %ld", (long) part_idx, (long) accum));
24818 
24819 			accum = 0;
24820 			ndigits = 0;
24821 
24822 			for (i = 0; i < (duk_small_uint_t) (sizeof(duk__parse_iso8601_seps) / sizeof(duk_uint8_t)); i++) {
24823 				if (duk__parse_iso8601_seps[i] == ch) {
24824 					break;
24825 				}
24826 			}
24827 			if (i == (duk_small_uint_t) (sizeof(duk__parse_iso8601_seps) / sizeof(duk_uint8_t))) {
24828 				DUK_DDD(DUK_DDDPRINT("separator character doesn't match -> reject"));
24829 				goto reject;
24830 			}
24831 
24832 			sep_idx = i;
24833 			match_val = (1UL << part_idx) + (1UL << (sep_idx + 9));  /* match against rule part/sep bits */
24834 
24835 			for (i = 0; i < (duk_small_uint_t) (sizeof(duk__parse_iso8601_control) / sizeof(duk_uint32_t)); i++) {
24836 				duk_uint_fast32_t rule = duk__parse_iso8601_control[i];
24837 				duk_small_uint_t nextpart;
24838 				duk_small_uint_t cflags;
24839 
24840 				DUK_DDD(DUK_DDDPRINT("part_idx=%ld, sep_idx=%ld, match_val=0x%08lx, considering rule=0x%08lx",
24841 				                     (long) part_idx, (long) sep_idx,
24842 				                     (unsigned long) match_val, (unsigned long) rule));
24843 
24844 				if ((rule & match_val) != match_val) {
24845 					continue;
24846 				}
24847 
24848 				DUK__UNPACK_RULE(rule, nextpart, cflags);
24849 
24850 				DUK_DDD(DUK_DDDPRINT("rule match -> part_idx=%ld, sep_idx=%ld, match_val=0x%08lx, "
24851 				                     "rule=0x%08lx -> nextpart=%ld, cflags=0x%02lx",
24852 				                     (long) part_idx, (long) sep_idx,
24853 				                     (unsigned long) match_val, (unsigned long) rule,
24854 				                     (long) nextpart, (unsigned long) cflags));
24855 
24856 				if (cflags & DUK__CF_NEG) {
24857 					neg_tzoffset = 1;
24858 				}
24859 
24860 				if (cflags & DUK__CF_ACCEPT) {
24861 					goto accept;
24862 				}
24863 
24864 				if (cflags & DUK__CF_ACCEPT_NUL) {
24865 					DUK_ASSERT(*(p - 1) != (char) 0);
24866 					if (*p == DUK_ASC_NUL) {
24867 						goto accept;
24868 					}
24869 					goto reject;
24870 				}
24871 
24872 				part_idx = nextpart;
24873 				break;
24874 			}  /* rule match */
24875 
24876 			if (i == (duk_small_uint_t) (sizeof(duk__parse_iso8601_control) / sizeof(duk_uint32_t))) {
24877 				DUK_DDD(DUK_DDDPRINT("no rule matches -> reject"));
24878 				goto reject;
24879 			}
24880 
24881 			if (ch == 0) {
24882 				/* This shouldn't be necessary, but check just in case
24883 				 * to avoid any chance of overruns.
24884 				 */
24885 				DUK_DDD(DUK_DDDPRINT("NUL after rule matching (should not happen) -> reject"));
24886 				goto reject;
24887 			}
24888 		}  /* if-digit-else-ctrl */
24889 	}  /* char loop */
24890 
24891 	/* We should never exit the loop above. */
24892 	DUK_UNREACHABLE();
24893 
24894  reject:
24895 	DUK_DDD(DUK_DDDPRINT("reject"));
24896 	return 0;
24897 
24898  accept:
24899 	DUK_DDD(DUK_DDDPRINT("accept"));
24900 
24901 	/* Apply timezone offset to get the main parts in UTC */
24902 	if (neg_year) {
24903 		parts[DUK__PI_YEAR] = -parts[DUK__PI_YEAR];
24904 	}
24905 	if (neg_tzoffset) {
24906 		parts[DUK__PI_HOUR] += parts[DUK__PI_TZHOUR];
24907 		parts[DUK__PI_MINUTE] += parts[DUK__PI_TZMINUTE];
24908 	} else {
24909 		parts[DUK__PI_HOUR] -= parts[DUK__PI_TZHOUR];
24910 		parts[DUK__PI_MINUTE] -= parts[DUK__PI_TZMINUTE];
24911 	}
24912 	parts[DUK__PI_MONTH] -= 1;  /* zero-based month */
24913 	parts[DUK__PI_DAY] -= 1;  /* zero-based day */
24914 
24915 	/* Use double parts, they tolerate unnormalized time.
24916 	 *
24917 	 * Note: DUK_DATE_IDX_WEEKDAY is initialized with a bogus value (DUK__PI_TZHOUR)
24918 	 * on purpose.  It won't be actually used by duk_bi_date_get_timeval_from_dparts(),
24919 	 * but will make the value initialized just in case, and avoid any
24920 	 * potential for Valgrind issues.
24921 	 */
24922 	for (i = 0; i < DUK_DATE_IDX_NUM_PARTS; i++) {
24923 		DUK_DDD(DUK_DDDPRINT("part[%ld] = %ld", (long) i, (long) parts[i]));
24924 		dparts[i] = parts[i];
24925 	}
24926 
24927 	d = duk_bi_date_get_timeval_from_dparts(dparts, 0 /*flags*/);
24928 	duk_push_number(ctx, d);
24929 	return 1;
24930 }
24931 
24932 /*
24933  *  Date/time parsing helper.
24934  *
24935  *  Parse a datetime string into a time value.  We must first try to parse
24936  *  the input according to the standard format in E5.1 Section 15.9.1.15.
24937  *  If that fails, we can try to parse using custom parsing, which can
24938  *  either be platform neutral (custom code) or platform specific (using
24939  *  existing platform API calls).
24940  *
24941  *  Note in particular that we must parse whatever toString(), toUTCString(),
24942  *  and toISOString() can produce; see E5.1 Section 15.9.4.2.
24943  *
24944  *  Returns 1 to allow tail calling.
24945  *
24946  *  There is much room for improvement here with respect to supporting
24947  *  alternative datetime formats.  For instance, V8 parses '2012-01-01' as
24948  *  UTC and '2012/01/01' as local time.
24949  */
24950 
duk__parse_string(duk_context * ctx,const char * str)24951 DUK_LOCAL duk_ret_t duk__parse_string(duk_context *ctx, const char *str) {
24952 	/* XXX: there is a small risk here: because the ISO 8601 parser is
24953 	 * very loose, it may end up parsing some datetime values which
24954 	 * would be better parsed with a platform specific parser.
24955 	 */
24956 
24957 	DUK_ASSERT(str != NULL);
24958 	DUK_DDD(DUK_DDDPRINT("parse datetime from string '%s'", (const char *) str));
24959 
24960 	if (duk__parse_string_iso8601_subset(ctx, str) != 0) {
24961 		return 1;
24962 	}
24963 
24964 #if defined(DUK_USE_DATE_PARSE_STRING)
24965 	/* Contract, either:
24966 	 * - Push value on stack and return 1
24967 	 * - Don't push anything on stack and return 0
24968 	 */
24969 
24970 	if (DUK_USE_DATE_PARSE_STRING(ctx, str) != 0) {
24971 		return 1;
24972 	}
24973 #else
24974 	/* No platform-specific parsing, this is not an error. */
24975 #endif
24976 
24977 	duk_push_nan(ctx);
24978 	return 1;
24979 }
24980 
24981 /*
24982  *  Calendar helpers
24983  *
24984  *  Some helpers are used for getters and can operate on normalized values
24985  *  which can be represented with 32-bit signed integers.  Other helpers are
24986  *  needed by setters and operate on un-normalized double values, must watch
24987  *  out for non-finite numbers etc.
24988  */
24989 
24990 DUK_LOCAL duk_uint8_t duk__days_in_month[12] = {
24991 	(duk_uint8_t) 31, (duk_uint8_t) 28, (duk_uint8_t) 31, (duk_uint8_t) 30,
24992 	(duk_uint8_t) 31, (duk_uint8_t) 30, (duk_uint8_t) 31, (duk_uint8_t) 31,
24993 	(duk_uint8_t) 30, (duk_uint8_t) 31, (duk_uint8_t) 30, (duk_uint8_t) 31
24994 };
24995 
24996 /* Maximum iteration count for computing UTC-to-local time offset when
24997  * creating an Ecmascript time value from local parts.
24998  */
24999 #define DUK__LOCAL_TZOFFSET_MAXITER   4
25000 
25001 /* Because 'day since epoch' can be negative and is used to compute weekday
25002  * using a modulo operation, add this multiple of 7 to avoid negative values
25003  * when year is below 1970 epoch.  Ecmascript time values are restricted to
25004  * +/- 100 million days from epoch, so this adder fits nicely into 32 bits.
25005  * Round to a multiple of 7 (= floor(100000000 / 7) * 7) and add margin.
25006  */
25007 #define DUK__WEEKDAY_MOD_ADDER  (20000000 * 7)  /* 0x08583b00 */
25008 
duk_bi_date_is_leap_year(duk_int_t year)25009 DUK_INTERNAL duk_bool_t duk_bi_date_is_leap_year(duk_int_t year) {
25010 	if ((year % 4) != 0) {
25011 		return 0;
25012 	}
25013 	if ((year % 100) != 0) {
25014 		return 1;
25015 	}
25016 	if ((year % 400) != 0) {
25017 		return 0;
25018 	}
25019 	return 1;
25020 }
25021 
duk_bi_date_timeval_in_valid_range(duk_double_t x)25022 DUK_INTERNAL duk_bool_t duk_bi_date_timeval_in_valid_range(duk_double_t x) {
25023 	return (x >= -DUK_DATE_MSEC_100M_DAYS && x <= DUK_DATE_MSEC_100M_DAYS);
25024 }
25025 
duk_bi_date_timeval_in_leeway_range(duk_double_t x)25026 DUK_INTERNAL duk_bool_t duk_bi_date_timeval_in_leeway_range(duk_double_t x) {
25027 	return (x >= -DUK_DATE_MSEC_100M_DAYS_LEEWAY && x <= DUK_DATE_MSEC_100M_DAYS_LEEWAY);
25028 }
25029 
duk_bi_date_year_in_valid_range(duk_double_t x)25030 DUK_INTERNAL duk_bool_t duk_bi_date_year_in_valid_range(duk_double_t x) {
25031 	return (x >= DUK_DATE_MIN_ECMA_YEAR && x <= DUK_DATE_MAX_ECMA_YEAR);
25032 }
25033 
duk__timeclip(duk_double_t x)25034 DUK_LOCAL duk_double_t duk__timeclip(duk_double_t x) {
25035 	if (!DUK_ISFINITE(x)) {
25036 		return DUK_DOUBLE_NAN;
25037 	}
25038 
25039 	if (!duk_bi_date_timeval_in_valid_range(x)) {
25040 		return DUK_DOUBLE_NAN;
25041 	}
25042 
25043 	x = duk_js_tointeger_number(x);
25044 
25045 	/* Here we'd have the option to normalize -0 to +0. */
25046 	return x;
25047 }
25048 
25049 /* Integer division which floors also negative values correctly. */
duk__div_floor(duk_int_t a,duk_int_t b)25050 DUK_LOCAL duk_int_t duk__div_floor(duk_int_t a, duk_int_t b) {
25051 	DUK_ASSERT(b > 0);
25052 	if (a >= 0) {
25053 		return a / b;
25054 	} else {
25055 		/* e.g. a = -4, b = 5  -->  -4 - 5 + 1 / 5  -->  -8 / 5  -->  -1
25056 		 *      a = -5, b = 5  -->  -5 - 5 + 1 / 5  -->  -9 / 5  -->  -1
25057 		 *      a = -6, b = 5  -->  -6 - 5 + 1 / 5  -->  -10 / 5  -->  -2
25058 		 */
25059 		return (a - b + 1) / b;
25060 	}
25061 }
25062 
25063 /* Compute day number of the first day of a given year. */
duk__day_from_year(duk_int_t year)25064 DUK_LOCAL duk_int_t duk__day_from_year(duk_int_t year) {
25065 	/* Note: in integer arithmetic, (x / 4) is same as floor(x / 4) for non-negative
25066 	 * values, but is incorrect for negative ones.
25067 	 */
25068 	return 365 * (year - 1970)
25069 	       + duk__div_floor(year - 1969, 4)
25070 	       - duk__div_floor(year - 1901, 100)
25071 	       + duk__div_floor(year - 1601, 400);
25072 }
25073 
25074 /* 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)25075 DUK_LOCAL duk_int_t duk__year_from_day(duk_int_t day, duk_small_int_t *out_day_within_year) {
25076 	duk_int_t year;
25077 	duk_int_t diff_days;
25078 
25079 	/* estimate year upwards (towards positive infinity), then back down;
25080 	 * two iterations should be enough
25081 	 */
25082 
25083 	if (day >= 0) {
25084 		year = 1970 + day / 365;
25085 	} else {
25086 		year = 1970 + day / 366;
25087 	}
25088 
25089 	for (;;) {
25090 		diff_days = duk__day_from_year(year) - day;
25091 		DUK_DDD(DUK_DDDPRINT("year=%ld day=%ld, diff_days=%ld", (long) year, (long) day, (long) diff_days));
25092 		if (diff_days <= 0) {
25093 			DUK_ASSERT(-diff_days < 366);  /* fits into duk_small_int_t */
25094 			*out_day_within_year = -diff_days;
25095 			DUK_DDD(DUK_DDDPRINT("--> year=%ld, day-within-year=%ld",
25096 			                     (long) year, (long) *out_day_within_year));
25097 			DUK_ASSERT(*out_day_within_year >= 0);
25098 			DUK_ASSERT(*out_day_within_year < (duk_bi_date_is_leap_year(year) ? 366 : 365));
25099 			return year;
25100 		}
25101 
25102 		/* Note: this is very tricky; we must never 'overshoot' the
25103 		 * correction downwards.
25104 		 */
25105 		year -= 1 + (diff_days - 1) / 366;  /* conservative */
25106 	}
25107 }
25108 
25109 /* Given a (year, month, day-within-month) triple, compute day number.
25110  * The input triple is un-normalized and may contain non-finite values.
25111  */
duk__make_day(duk_double_t year,duk_double_t month,duk_double_t day)25112 DUK_LOCAL duk_double_t duk__make_day(duk_double_t year, duk_double_t month, duk_double_t day) {
25113 	duk_int_t day_num;
25114 	duk_bool_t is_leap;
25115 	duk_small_int_t i, n;
25116 
25117 	/* Assume that year, month, day are all coerced to whole numbers.
25118 	 * They may also be NaN or infinity, in which case this function
25119 	 * must return NaN or infinity to ensure time value becomes NaN.
25120 	 * If 'day' is NaN, the final return will end up returning a NaN,
25121 	 * so it doesn't need to be checked here.
25122 	 */
25123 
25124 	if (!DUK_ISFINITE(year) || !DUK_ISFINITE(month)) {
25125 		return DUK_DOUBLE_NAN;
25126 	}
25127 
25128 	year += DUK_FLOOR(month / 12.0);
25129 
25130 	month = DUK_FMOD(month, 12.0);
25131 	if (month < 0.0) {
25132 		/* handle negative values */
25133 		month += 12.0;
25134 	}
25135 
25136 	/* The algorithm in E5.1 Section 15.9.1.12 normalizes month, but
25137 	 * does not normalize the day-of-month (nor check whether or not
25138 	 * it is finite) because it's not necessary for finding the day
25139 	 * number which matches the (year,month) pair.
25140 	 *
25141 	 * We assume that duk__day_from_year() is exact here.
25142 	 *
25143 	 * Without an explicit infinity / NaN check in the beginning,
25144 	 * day_num would be a bogus integer here.
25145 	 *
25146 	 * It's possible for 'year' to be out of integer range here.
25147 	 * If so, we need to return NaN without integer overflow.
25148 	 * This fixes test-bug-setyear-overflow.js.
25149 	 */
25150 
25151 	if (!duk_bi_date_year_in_valid_range(year)) {
25152 		DUK_DD(DUK_DDPRINT("year not in ecmascript valid range, avoid integer overflow: %lf", (double) year));
25153 		return DUK_DOUBLE_NAN;
25154 	}
25155 	day_num = duk__day_from_year((duk_int_t) year);
25156 	is_leap = duk_bi_date_is_leap_year((duk_int_t) year);
25157 
25158 	n = (duk_small_int_t) month;
25159 	for (i = 0; i < n; i++) {
25160 		day_num += duk__days_in_month[i];
25161 		if (i == 1 && is_leap) {
25162 			day_num++;
25163 		}
25164 	}
25165 
25166 	/* If 'day' is NaN, returns NaN. */
25167 	return (duk_double_t) day_num + day;
25168 }
25169 
25170 /* Split time value into parts.  The time value is assumed to be an internal
25171  * one, i.e. finite, no fractions.  Possible local time adjustment has already
25172  * been applied when reading the time value.
25173  */
duk_bi_date_timeval_to_parts(duk_double_t d,duk_int_t * parts,duk_double_t * dparts,duk_small_uint_t flags)25174 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) {
25175 	duk_double_t d1, d2;
25176 	duk_int_t t1, t2;
25177 	duk_int_t day_since_epoch;
25178 	duk_int_t year;  /* does not fit into 16 bits */
25179 	duk_small_int_t day_in_year;
25180 	duk_small_int_t month;
25181 	duk_small_int_t day;
25182 	duk_small_int_t dim;
25183 	duk_int_t jan1_since_epoch;
25184 	duk_small_int_t jan1_weekday;
25185 	duk_int_t equiv_year;
25186 	duk_small_uint_t i;
25187 	duk_bool_t is_leap;
25188 	duk_small_int_t arridx;
25189 
25190 	DUK_ASSERT(DUK_ISFINITE(d));    /* caller checks */
25191 	DUK_ASSERT(DUK_FLOOR(d) == d);  /* no fractions in internal time */
25192 
25193 	/* The timevalue must be in valid Ecmascript range, but since a local
25194 	 * time offset can be applied, we need to allow a +/- 24h leeway to
25195 	 * the value.  In other words, although the UTC time is within the
25196 	 * Ecmascript range, the local part values can be just outside of it.
25197 	 */
25198 	DUK_UNREF(duk_bi_date_timeval_in_leeway_range);
25199 	DUK_ASSERT(duk_bi_date_timeval_in_leeway_range(d));
25200 
25201 	/* these computations are guaranteed to be exact for the valid
25202 	 * E5 time value range, assuming milliseconds without fractions.
25203 	 */
25204 	d1 = (duk_double_t) DUK_FMOD(d, (double) DUK_DATE_MSEC_DAY);
25205 	if (d1 < 0.0) {
25206 		/* deal with negative values */
25207 		d1 += (duk_double_t) DUK_DATE_MSEC_DAY;
25208 	}
25209 	d2 = DUK_FLOOR((double) (d / (duk_double_t) DUK_DATE_MSEC_DAY));
25210 	DUK_ASSERT(d2 * ((duk_double_t) DUK_DATE_MSEC_DAY) + d1 == d);
25211 	/* now expected to fit into a 32-bit integer */
25212 	t1 = (duk_int_t) d1;
25213 	t2 = (duk_int_t) d2;
25214 	day_since_epoch = t2;
25215 	DUK_ASSERT((duk_double_t) t1 == d1);
25216 	DUK_ASSERT((duk_double_t) t2 == d2);
25217 
25218 	/* t1 = milliseconds within day (fits 32 bit)
25219 	 * t2 = day number from epoch (fits 32 bit, may be negative)
25220 	 */
25221 
25222 	parts[DUK_DATE_IDX_MILLISECOND] = t1 % 1000; t1 /= 1000;
25223 	parts[DUK_DATE_IDX_SECOND] = t1 % 60; t1 /= 60;
25224 	parts[DUK_DATE_IDX_MINUTE] = t1 % 60; t1 /= 60;
25225 	parts[DUK_DATE_IDX_HOUR] = t1;
25226 	DUK_ASSERT(parts[DUK_DATE_IDX_MILLISECOND] >= 0 && parts[DUK_DATE_IDX_MILLISECOND] <= 999);
25227 	DUK_ASSERT(parts[DUK_DATE_IDX_SECOND] >= 0 && parts[DUK_DATE_IDX_SECOND] <= 59);
25228 	DUK_ASSERT(parts[DUK_DATE_IDX_MINUTE] >= 0 && parts[DUK_DATE_IDX_MINUTE] <= 59);
25229 	DUK_ASSERT(parts[DUK_DATE_IDX_HOUR] >= 0 && parts[DUK_DATE_IDX_HOUR] <= 23);
25230 
25231 	DUK_DDD(DUK_DDDPRINT("d=%lf, d1=%lf, d2=%lf, t1=%ld, t2=%ld, parts: hour=%ld min=%ld sec=%ld msec=%ld",
25232 	                     (double) d, (double) d1, (double) d2, (long) t1, (long) t2,
25233 	                     (long) parts[DUK_DATE_IDX_HOUR],
25234 	                     (long) parts[DUK_DATE_IDX_MINUTE],
25235 	                     (long) parts[DUK_DATE_IDX_SECOND],
25236 	                     (long) parts[DUK_DATE_IDX_MILLISECOND]));
25237 
25238 	/* This assert depends on the input parts representing time inside
25239 	 * the Ecmascript range.
25240 	 */
25241 	DUK_ASSERT(t2 + DUK__WEEKDAY_MOD_ADDER >= 0);
25242 	parts[DUK_DATE_IDX_WEEKDAY] = (t2 + 4 + DUK__WEEKDAY_MOD_ADDER) % 7;  /* E5.1 Section 15.9.1.6 */
25243 	DUK_ASSERT(parts[DUK_DATE_IDX_WEEKDAY] >= 0 && parts[DUK_DATE_IDX_WEEKDAY] <= 6);
25244 
25245 	year = duk__year_from_day(t2, &day_in_year);
25246 	day = day_in_year;
25247 	is_leap = duk_bi_date_is_leap_year(year);
25248 	for (month = 0; month < 12; month++) {
25249 		dim = duk__days_in_month[month];
25250 		if (month == 1 && is_leap) {
25251 			dim++;
25252 		}
25253 		DUK_DDD(DUK_DDDPRINT("month=%ld, dim=%ld, day=%ld",
25254 		                     (long) month, (long) dim, (long) day));
25255 		if (day < dim) {
25256 			break;
25257 		}
25258 		day -= dim;
25259 	}
25260 	DUK_DDD(DUK_DDDPRINT("final month=%ld", (long) month));
25261 	DUK_ASSERT(month >= 0 && month <= 11);
25262 	DUK_ASSERT(day >= 0 && day <= 31);
25263 
25264 	/* Equivalent year mapping, used to avoid DST trouble when platform
25265 	 * may fail to provide reasonable DST answers for dates outside the
25266 	 * ordinary range (e.g. 1970-2038).  An equivalent year has the same
25267 	 * leap-year-ness as the original year and begins on the same weekday
25268 	 * (Jan 1).
25269 	 *
25270 	 * The year 2038 is avoided because there seem to be problems with it
25271 	 * on some platforms.  The year 1970 is also avoided as there were
25272 	 * practical problems with it; an equivalent year is used for it too,
25273 	 * which breaks some DST computations for 1970 right now, see e.g.
25274 	 * test-bi-date-tzoffset-brute-fi.js.
25275 	 */
25276 	if ((flags & DUK_DATE_FLAG_EQUIVYEAR) && (year < 1971 || year > 2037)) {
25277 		DUK_ASSERT(is_leap == 0 || is_leap == 1);
25278 
25279 		jan1_since_epoch = day_since_epoch - day_in_year;  /* day number for Jan 1 since epoch */
25280 		DUK_ASSERT(jan1_since_epoch + DUK__WEEKDAY_MOD_ADDER >= 0);
25281 		jan1_weekday = (jan1_since_epoch + 4 + DUK__WEEKDAY_MOD_ADDER) % 7;  /* E5.1 Section 15.9.1.6 */
25282 		DUK_ASSERT(jan1_weekday >= 0 && jan1_weekday <= 6);
25283 		arridx = jan1_weekday;
25284 		if (is_leap) {
25285 			arridx += 7;
25286 		}
25287 		DUK_ASSERT(arridx >= 0 && arridx < (duk_small_int_t) (sizeof(duk__date_equivyear) / sizeof(duk_uint8_t)));
25288 
25289 		equiv_year = (duk_int_t) duk__date_equivyear[arridx] + 1970;
25290 		year = equiv_year;
25291 		DUK_DDD(DUK_DDDPRINT("equiv year mapping, year=%ld, day_in_year=%ld, day_since_epoch=%ld, "
25292 		                     "jan1_since_epoch=%ld, jan1_weekday=%ld -> equiv year %ld",
25293 		                     (long) year, (long) day_in_year, (long) day_since_epoch,
25294 		                     (long) jan1_since_epoch, (long) jan1_weekday, (long) equiv_year));
25295 	}
25296 
25297 	parts[DUK_DATE_IDX_YEAR] = year;
25298 	parts[DUK_DATE_IDX_MONTH] = month;
25299 	parts[DUK_DATE_IDX_DAY] = day;
25300 
25301 	if (flags & DUK_DATE_FLAG_ONEBASED) {
25302 		parts[DUK_DATE_IDX_MONTH]++;  /* zero-based -> one-based */
25303 		parts[DUK_DATE_IDX_DAY]++;    /* -""- */
25304 	}
25305 
25306 	if (dparts != NULL) {
25307 		for (i = 0; i < DUK_DATE_IDX_NUM_PARTS; i++) {
25308 			dparts[i] = (duk_double_t) parts[i];
25309 		}
25310 	}
25311 }
25312 
25313 /* Compute time value from (double) parts.  The parts can be either UTC
25314  * or local time; if local, they need to be (conceptually) converted into
25315  * UTC time.  The parts may represent valid or invalid time, and may be
25316  * wildly out of range (but may cancel each other and still come out in
25317  * the valid Date range).
25318  */
duk_bi_date_get_timeval_from_dparts(duk_double_t * dparts,duk_small_uint_t flags)25319 DUK_INTERNAL duk_double_t duk_bi_date_get_timeval_from_dparts(duk_double_t *dparts, duk_small_uint_t flags) {
25320 #if defined(DUK_USE_PARANOID_DATE_COMPUTATION)
25321 	/* See comments below on MakeTime why these are volatile. */
25322 	volatile duk_double_t tmp_time;
25323 	volatile duk_double_t tmp_day;
25324 	volatile duk_double_t d;
25325 #else
25326 	duk_double_t tmp_time;
25327 	duk_double_t tmp_day;
25328 	duk_double_t d;
25329 #endif
25330 	duk_small_uint_t i;
25331 	duk_int_t tzoff, tzoffprev1, tzoffprev2;
25332 
25333 	/* Expects 'this' at top of stack on entry. */
25334 
25335 	/* Coerce all finite parts with ToInteger().  ToInteger() must not
25336 	 * be called for NaN/Infinity because it will convert e.g. NaN to
25337 	 * zero.  If ToInteger() has already been called, this has no side
25338 	 * effects and is idempotent.
25339 	 *
25340 	 * Don't read dparts[DUK_DATE_IDX_WEEKDAY]; it will cause Valgrind
25341 	 * issues if the value is uninitialized.
25342 	 */
25343 	for (i = 0; i <= DUK_DATE_IDX_MILLISECOND; i++) {
25344 		/* SCANBUILD: scan-build complains here about assigned value
25345 		 * being garbage or undefined.  This is correct but operating
25346 		 * on undefined values has no ill effect and is ignored by the
25347 		 * caller in the case where this happens.
25348 		 */
25349 		d = dparts[i];
25350 		if (DUK_ISFINITE(d)) {
25351 			dparts[i] = duk_js_tointeger_number(d);
25352 		}
25353 	}
25354 
25355 	/* Use explicit steps in computation to try to ensure that
25356 	 * computation happens with intermediate results coerced to
25357 	 * double values (instead of using something more accurate).
25358 	 * E.g. E5.1 Section 15.9.1.11 requires use of IEEE 754
25359 	 * rules (= Ecmascript '+' and '*' operators).
25360 	 *
25361 	 * Without 'volatile' even this approach fails on some platform
25362 	 * and compiler combinations.  For instance, gcc 4.8.1 on Ubuntu
25363 	 * 64-bit, with -m32 and without -std=c99, test-bi-date-canceling.js
25364 	 * would fail because of some optimizations when computing tmp_time
25365 	 * (MakeTime below).  Adding 'volatile' to tmp_time solved this
25366 	 * particular problem (annoyingly, also adding debug prints or
25367 	 * running the executable under valgrind hides it).
25368 	 */
25369 
25370 	/* MakeTime */
25371 	tmp_time = 0.0;
25372 	tmp_time += dparts[DUK_DATE_IDX_HOUR] * ((duk_double_t) DUK_DATE_MSEC_HOUR);
25373 	tmp_time += dparts[DUK_DATE_IDX_MINUTE] * ((duk_double_t) DUK_DATE_MSEC_MINUTE);
25374 	tmp_time += dparts[DUK_DATE_IDX_SECOND] * ((duk_double_t) DUK_DATE_MSEC_SECOND);
25375 	tmp_time += dparts[DUK_DATE_IDX_MILLISECOND];
25376 
25377 	/* MakeDay */
25378 	tmp_day = duk__make_day(dparts[DUK_DATE_IDX_YEAR], dparts[DUK_DATE_IDX_MONTH], dparts[DUK_DATE_IDX_DAY]);
25379 
25380 	/* MakeDate */
25381 	d = tmp_day * ((duk_double_t) DUK_DATE_MSEC_DAY) + tmp_time;
25382 
25383 	DUK_DDD(DUK_DDDPRINT("time=%lf day=%lf --> timeval=%lf",
25384 	                     (double) tmp_time, (double) tmp_day, (double) d));
25385 
25386 	/* Optional UTC conversion. */
25387 	if (flags & DUK_DATE_FLAG_LOCALTIME) {
25388 		/* DUK_USE_DATE_GET_LOCAL_TZOFFSET() needs to be called with a
25389 		 * time value computed from UTC parts.  At this point we only
25390 		 * have 'd' which is a time value computed from local parts, so
25391 		 * it is off by the UTC-to-local time offset which we don't know
25392 		 * yet.  The current solution for computing the UTC-to-local
25393 		 * time offset is to iterate a few times and detect a fixed
25394 		 * point or a two-cycle loop (or a sanity iteration limit),
25395 		 * see test-bi-date-local-parts.js and test-bi-date-tzoffset-basic-fi.js.
25396 		 *
25397 		 * E5.1 Section 15.9.1.9:
25398 		 * UTC(t) = t - LocalTZA - DaylightSavingTA(t - LocalTZA)
25399 		 *
25400 		 * For NaN/inf, DUK_USE_DATE_GET_LOCAL_TZOFFSET() returns 0.
25401 		 */
25402 
25403 #if 0
25404 		/* Old solution: don't iterate, incorrect */
25405 		tzoff = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d);
25406 		DUK_DDD(DUK_DDDPRINT("tzoffset w/o iteration, tzoff=%ld", (long) tzoff));
25407 		d -= tzoff * 1000L;
25408 		DUK_UNREF(tzoffprev1);
25409 		DUK_UNREF(tzoffprev2);
25410 #endif
25411 
25412 		/* Iteration solution */
25413 		tzoff = 0;
25414 		tzoffprev1 = 999999999L;  /* invalid value which never matches */
25415 		for (i = 0; i < DUK__LOCAL_TZOFFSET_MAXITER; i++) {
25416 			tzoffprev2 = tzoffprev1;
25417 			tzoffprev1 = tzoff;
25418 			tzoff = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d - tzoff * 1000L);
25419 			DUK_DDD(DUK_DDDPRINT("tzoffset iteration, i=%d, tzoff=%ld, tzoffprev1=%ld tzoffprev2=%ld",
25420 			                     (int) i, (long) tzoff, (long) tzoffprev1, (long) tzoffprev2));
25421 			if (tzoff == tzoffprev1) {
25422 				DUK_DDD(DUK_DDDPRINT("tzoffset iteration finished, i=%d, tzoff=%ld, tzoffprev1=%ld, tzoffprev2=%ld",
25423 				                     (int) i, (long) tzoff, (long) tzoffprev1, (long) tzoffprev2));
25424 				break;
25425 			} else if (tzoff == tzoffprev2) {
25426 				/* Two value cycle, see e.g. test-bi-date-tzoffset-basic-fi.js.
25427 				 * In these cases, favor a higher tzoffset to get a consistent
25428 				 * result which is independent of iteration count.  Not sure if
25429 				 * this is a generically correct solution.
25430 				 */
25431 				DUK_DDD(DUK_DDDPRINT("tzoffset iteration two-value cycle, i=%d, tzoff=%ld, tzoffprev1=%ld, tzoffprev2=%ld",
25432 				                     (int) i, (long) tzoff, (long) tzoffprev1, (long) tzoffprev2));
25433 				if (tzoffprev1 > tzoff) {
25434 					tzoff = tzoffprev1;
25435 				}
25436 				break;
25437 			}
25438 		}
25439 		DUK_DDD(DUK_DDDPRINT("tzoffset iteration, tzoff=%ld", (long) tzoff));
25440 		d -= tzoff * 1000L;
25441 	}
25442 
25443 	/* TimeClip(), which also handles Infinity -> NaN conversion */
25444 	d = duk__timeclip(d);
25445 
25446 	return d;
25447 }
25448 
25449 /*
25450  *  API oriented helpers
25451  */
25452 
25453 /* Push 'this' binding, check that it is a Date object; then push the
25454  * internal time value.  At the end, stack is: [ ... this timeval ].
25455  * Returns the time value.  Local time adjustment is done if requested.
25456  */
duk__push_this_get_timeval_tzoffset(duk_context * ctx,duk_small_uint_t flags,duk_int_t * out_tzoffset)25457 DUK_LOCAL duk_double_t duk__push_this_get_timeval_tzoffset(duk_context *ctx, duk_small_uint_t flags, duk_int_t *out_tzoffset) {
25458 	duk_hthread *thr = (duk_hthread *) ctx;
25459 	duk_hobject *h;
25460 	duk_double_t d;
25461 	duk_int_t tzoffset = 0;
25462 
25463 	duk_push_this(ctx);
25464 	h = duk_get_hobject(ctx, -1);  /* XXX: getter with class check, useful in built-ins */
25465 	if (h == NULL || DUK_HOBJECT_GET_CLASS_NUMBER(h) != DUK_HOBJECT_CLASS_DATE) {
25466 		DUK_ERROR_TYPE(thr, "expected Date");
25467 	}
25468 
25469 	duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_VALUE);
25470 	d = duk_to_number(ctx, -1);
25471 	duk_pop(ctx);
25472 
25473 	if (DUK_ISNAN(d)) {
25474 		if (flags & DUK_DATE_FLAG_NAN_TO_ZERO) {
25475 			d = 0.0;
25476 		}
25477 		if (flags & DUK_DATE_FLAG_NAN_TO_RANGE_ERROR) {
25478 			DUK_ERROR_RANGE(thr, "Invalid Date");
25479 		}
25480 	}
25481 	/* if no NaN handling flag, may still be NaN here, but not Inf */
25482 	DUK_ASSERT(!DUK_ISINF(d));
25483 
25484 	if (flags & DUK_DATE_FLAG_LOCALTIME) {
25485 		/* Note: DST adjustment is determined using UTC time.
25486 		 * If 'd' is NaN, tzoffset will be 0.
25487 		 */
25488 		tzoffset = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d);  /* seconds */
25489 		d += tzoffset * 1000L;
25490 	}
25491 	if (out_tzoffset) {
25492 		*out_tzoffset = tzoffset;
25493 	}
25494 
25495 	/* [ ... this ] */
25496 	return d;
25497 }
25498 
duk__push_this_get_timeval(duk_context * ctx,duk_small_uint_t flags)25499 DUK_LOCAL duk_double_t duk__push_this_get_timeval(duk_context *ctx, duk_small_uint_t flags) {
25500 	return duk__push_this_get_timeval_tzoffset(ctx, flags, NULL);
25501 }
25502 
25503 /* Set timeval to 'this' from dparts, push the new time value onto the
25504  * value stack and return 1 (caller can then tail call us).  Expects
25505  * the value stack to contain 'this' on the stack top.
25506  */
duk__set_this_timeval_from_dparts(duk_context * ctx,duk_double_t * dparts,duk_small_uint_t flags)25507 DUK_LOCAL duk_ret_t duk__set_this_timeval_from_dparts(duk_context *ctx, duk_double_t *dparts, duk_small_uint_t flags) {
25508 	duk_double_t d;
25509 
25510 	/* [ ... this ] */
25511 
25512 	d = duk_bi_date_get_timeval_from_dparts(dparts, flags);
25513 	duk_push_number(ctx, d);  /* -> [ ... this timeval_new ] */
25514 	duk_dup_top(ctx);         /* -> [ ... this timeval_new timeval_new ] */
25515 	duk_put_prop_stridx(ctx, -3, DUK_STRIDX_INT_VALUE);
25516 
25517 	/* stack top: new time value, return 1 to allow tail calls */
25518 	return 1;
25519 }
25520 
25521 /* '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)25522 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) {
25523 	char yearstr[8];   /* "-123456\0" */
25524 	char tzstr[8];     /* "+11:22\0" */
25525 	char sep = (flags & DUK_DATE_FLAG_SEP_T) ? DUK_ASC_UC_T : DUK_ASC_SPACE;
25526 
25527 	DUK_ASSERT(parts[DUK_DATE_IDX_MONTH] >= 1 && parts[DUK_DATE_IDX_MONTH] <= 12);
25528 	DUK_ASSERT(parts[DUK_DATE_IDX_DAY] >= 1 && parts[DUK_DATE_IDX_DAY] <= 31);
25529 	DUK_ASSERT(parts[DUK_DATE_IDX_YEAR] >= -999999 && parts[DUK_DATE_IDX_YEAR] <= 999999);
25530 
25531 	/* Note: %06d for positive value, %07d for negative value to include
25532 	 * sign and 6 digits.
25533 	 */
25534 	DUK_SNPRINTF(yearstr,
25535 	             sizeof(yearstr),
25536 	             (parts[DUK_DATE_IDX_YEAR] >= 0 && parts[DUK_DATE_IDX_YEAR] <= 9999) ? "%04ld" :
25537 	                    ((parts[DUK_DATE_IDX_YEAR] >= 0) ? "+%06ld" : "%07ld"),
25538 	             (long) parts[DUK_DATE_IDX_YEAR]);
25539 	yearstr[sizeof(yearstr) - 1] = (char) 0;
25540 
25541 	if (flags & DUK_DATE_FLAG_LOCALTIME) {
25542 		/* tzoffset seconds are dropped; 16 bits suffice for
25543 		 * time offset in minutes
25544 		 */
25545 		if (tzoffset >= 0) {
25546 			duk_small_int_t tmp = tzoffset / 60;
25547 			DUK_SNPRINTF(tzstr, sizeof(tzstr), "+%02d:%02d", (int) (tmp / 60), (int) (tmp % 60));
25548 		} else {
25549 			duk_small_int_t tmp = -tzoffset / 60;
25550 			DUK_SNPRINTF(tzstr, sizeof(tzstr), "-%02d:%02d", (int) (tmp / 60), (int) (tmp % 60));
25551 		}
25552 		tzstr[sizeof(tzstr) - 1] = (char) 0;
25553 	} else {
25554 		tzstr[0] = DUK_ASC_UC_Z;
25555 		tzstr[1] = (char) 0;
25556 	}
25557 
25558 	/* Unlike year, the other parts fit into 16 bits so %d format
25559 	 * is portable.
25560 	 */
25561 	if ((flags & DUK_DATE_FLAG_TOSTRING_DATE) && (flags & DUK_DATE_FLAG_TOSTRING_TIME)) {
25562 		DUK_SPRINTF((char *) out_buf, "%s-%02d-%02d%c%02d:%02d:%02d.%03d%s",
25563 		            (const char *) yearstr, (int) parts[DUK_DATE_IDX_MONTH], (int) parts[DUK_DATE_IDX_DAY], (int) sep,
25564 		            (int) parts[DUK_DATE_IDX_HOUR], (int) parts[DUK_DATE_IDX_MINUTE],
25565 		            (int) parts[DUK_DATE_IDX_SECOND], (int) parts[DUK_DATE_IDX_MILLISECOND], (const char *) tzstr);
25566 	} else if (flags & DUK_DATE_FLAG_TOSTRING_DATE) {
25567 		DUK_SPRINTF((char *) out_buf, "%s-%02d-%02d",
25568 		            (const char *) yearstr, (int) parts[DUK_DATE_IDX_MONTH], (int) parts[DUK_DATE_IDX_DAY]);
25569 	} else {
25570 		DUK_ASSERT(flags & DUK_DATE_FLAG_TOSTRING_TIME);
25571 		DUK_SPRINTF((char *) out_buf, "%02d:%02d:%02d.%03d%s",
25572 		            (int) parts[DUK_DATE_IDX_HOUR], (int) parts[DUK_DATE_IDX_MINUTE],
25573 		            (int) parts[DUK_DATE_IDX_SECOND], (int) parts[DUK_DATE_IDX_MILLISECOND],
25574 		            (const char *) tzstr);
25575 	}
25576 }
25577 
25578 /* Helper for string conversion calls: check 'this' binding, get the
25579  * internal time value, and format date and/or time in a few formats.
25580  * Return value allows tail calls.
25581  */
duk__to_string_helper(duk_context * ctx,duk_small_uint_t flags)25582 DUK_LOCAL duk_ret_t duk__to_string_helper(duk_context *ctx, duk_small_uint_t flags) {
25583 	duk_double_t d;
25584 	duk_int_t parts[DUK_DATE_IDX_NUM_PARTS];
25585 	duk_int_t tzoffset;  /* seconds, doesn't fit into 16 bits */
25586 	duk_bool_t rc;
25587 	duk_uint8_t buf[DUK_BI_DATE_ISO8601_BUFSIZE];
25588 
25589 	DUK_UNREF(rc);  /* unreferenced with some options */
25590 
25591 	d = duk__push_this_get_timeval_tzoffset(ctx, flags, &tzoffset);
25592 	if (DUK_ISNAN(d)) {
25593 		duk_push_hstring_stridx(ctx, DUK_STRIDX_INVALID_DATE);
25594 		return 1;
25595 	}
25596 	DUK_ASSERT(DUK_ISFINITE(d));
25597 
25598 	/* formatters always get one-based month/day-of-month */
25599 	duk_bi_date_timeval_to_parts(d, parts, NULL, DUK_DATE_FLAG_ONEBASED);
25600 	DUK_ASSERT(parts[DUK_DATE_IDX_MONTH] >= 1 && parts[DUK_DATE_IDX_MONTH] <= 12);
25601 	DUK_ASSERT(parts[DUK_DATE_IDX_DAY] >= 1 && parts[DUK_DATE_IDX_DAY] <= 31);
25602 
25603 	if (flags & DUK_DATE_FLAG_TOSTRING_LOCALE) {
25604 		/* try locale specific formatter; if it refuses to format the
25605 		 * string, fall back to an ISO 8601 formatted value in local
25606 		 * time.
25607 		 */
25608 #if defined(DUK_USE_DATE_FORMAT_STRING)
25609 		/* Contract, either:
25610 		 * - Push string to value stack and return 1
25611 		 * - Don't push anything and return 0
25612 		 */
25613 
25614 		rc = DUK_USE_DATE_FORMAT_STRING(ctx, parts, tzoffset, flags);
25615 		if (rc != 0) {
25616 			return 1;
25617 		}
25618 #else
25619 		/* No locale specific formatter; this is OK, we fall back
25620 		 * to ISO 8601.
25621 		 */
25622 #endif
25623 	}
25624 
25625 	/* Different calling convention than above used because the helper
25626 	 * is shared.
25627 	 */
25628 	duk__format_parts_iso8601(parts, tzoffset, flags, buf);
25629 	duk_push_string(ctx, (const char *) buf);
25630 	return 1;
25631 }
25632 
25633 /* Helper for component getter calls: check 'this' binding, get the
25634  * internal time value, split it into parts (either as UTC time or
25635  * local time), push a specified component as a return value to the
25636  * value stack and return 1 (caller can then tail call us).
25637  */
duk__get_part_helper(duk_context * ctx,duk_small_uint_t flags_and_idx)25638 DUK_LOCAL duk_ret_t duk__get_part_helper(duk_context *ctx, duk_small_uint_t flags_and_idx) {
25639 	duk_double_t d;
25640 	duk_int_t parts[DUK_DATE_IDX_NUM_PARTS];
25641 	duk_small_uint_t idx_part = (duk_small_uint_t) (flags_and_idx >> DUK_DATE_FLAG_VALUE_SHIFT);  /* unpack args */
25642 
25643 	DUK_ASSERT_DISABLE(idx_part >= 0);  /* unsigned */
25644 	DUK_ASSERT(idx_part < DUK_DATE_IDX_NUM_PARTS);
25645 
25646 	d = duk__push_this_get_timeval(ctx, flags_and_idx);
25647 	if (DUK_ISNAN(d)) {
25648 		duk_push_nan(ctx);
25649 		return 1;
25650 	}
25651 	DUK_ASSERT(DUK_ISFINITE(d));
25652 
25653 	duk_bi_date_timeval_to_parts(d, parts, NULL, flags_and_idx);  /* no need to mask idx portion */
25654 
25655 	/* Setter APIs detect special year numbers (0...99) and apply a +1900
25656 	 * only in certain cases.  The legacy getYear() getter applies -1900
25657 	 * unconditionally.
25658 	 */
25659 	duk_push_int(ctx, (flags_and_idx & DUK_DATE_FLAG_SUB1900) ? parts[idx_part] - 1900 : parts[idx_part]);
25660 	return 1;
25661 }
25662 
25663 /* Helper for component setter calls: check 'this' binding, get the
25664  * internal time value, split it into parts (either as UTC time or
25665  * local time), modify one or more components as specified, recompute
25666  * the time value, set it as the internal value.  Finally, push the
25667  * new time value as a return value to the value stack and return 1
25668  * (caller can then tail call us).
25669  */
duk__set_part_helper(duk_context * ctx,duk_small_uint_t flags_and_maxnargs)25670 DUK_LOCAL duk_ret_t duk__set_part_helper(duk_context *ctx, duk_small_uint_t flags_and_maxnargs) {
25671 	duk_double_t d;
25672 	duk_int_t parts[DUK_DATE_IDX_NUM_PARTS];
25673 	duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
25674 	duk_idx_t nargs;
25675 	duk_small_uint_t maxnargs = (duk_small_uint_t) (flags_and_maxnargs >> DUK_DATE_FLAG_VALUE_SHIFT);  /* unpack args */
25676 	duk_small_uint_t idx_first, idx;
25677 	duk_small_uint_t i;
25678 
25679 	nargs = duk_get_top(ctx);
25680 	d = duk__push_this_get_timeval(ctx, flags_and_maxnargs);
25681 	DUK_ASSERT(DUK_ISFINITE(d) || DUK_ISNAN(d));
25682 
25683 	if (DUK_ISFINITE(d)) {
25684 		duk_bi_date_timeval_to_parts(d, parts, dparts, flags_and_maxnargs);
25685 	} else {
25686 		/* NaN timevalue: we need to coerce the arguments, but
25687 		 * the resulting internal timestamp needs to remain NaN.
25688 		 * This works but is not pretty: parts and dparts will
25689 		 * be partially uninitialized, but we only write to them.
25690 		 */
25691 	}
25692 
25693 	/*
25694 	 *  Determining which datetime components to overwrite based on
25695 	 *  stack arguments is a bit complicated, but important to factor
25696 	 *  out from setters themselves for compactness.
25697 	 *
25698 	 *  If DUK_DATE_FLAG_TIMESETTER, maxnargs indicates setter type:
25699 	 *
25700 	 *   1 -> millisecond
25701 	 *   2 -> second, [millisecond]
25702 	 *   3 -> minute, [second], [millisecond]
25703 	 *   4 -> hour, [minute], [second], [millisecond]
25704 	 *
25705 	 *  Else:
25706 	 *
25707 	 *   1 -> date
25708 	 *   2 -> month, [date]
25709 	 *   3 -> year, [month], [date]
25710 	 *
25711 	 *  By comparing nargs and maxnargs (and flags) we know which
25712 	 *  components to override.  We rely on part index ordering.
25713 	 */
25714 
25715 	if (flags_and_maxnargs & DUK_DATE_FLAG_TIMESETTER) {
25716 		DUK_ASSERT(maxnargs >= 1 && maxnargs <= 4);
25717 		idx_first = DUK_DATE_IDX_MILLISECOND - (maxnargs - 1);
25718 	} else {
25719 		DUK_ASSERT(maxnargs >= 1 && maxnargs <= 3);
25720 		idx_first = DUK_DATE_IDX_DAY - (maxnargs - 1);
25721 	}
25722 	DUK_ASSERT_DISABLE(idx_first >= 0);  /* unsigned */
25723 	DUK_ASSERT(idx_first < DUK_DATE_IDX_NUM_PARTS);
25724 
25725 	for (i = 0; i < maxnargs; i++) {
25726 		if ((duk_idx_t) i >= nargs) {
25727 			/* no argument given -> leave components untouched */
25728 			break;
25729 		}
25730 		idx = idx_first + i;
25731 		DUK_ASSERT_DISABLE(idx >= 0);  /* unsigned */
25732 		DUK_ASSERT(idx < DUK_DATE_IDX_NUM_PARTS);
25733 
25734 		if (idx == DUK_DATE_IDX_YEAR && (flags_and_maxnargs & DUK_DATE_FLAG_YEAR_FIXUP)) {
25735 			duk__twodigit_year_fixup(ctx, (duk_idx_t) i);
25736 		}
25737 
25738 		dparts[idx] = duk_to_number(ctx, i);
25739 
25740 		if (idx == DUK_DATE_IDX_DAY) {
25741 			/* Day-of-month is one-based in the API, but zero-based
25742 			 * internally, so fix here.  Note that month is zero-based
25743 			 * both in the API and internally.
25744 			 */
25745 			/* SCANBUILD: complains about use of uninitialized values.
25746 			 * The complaint is correct, but operating in undefined
25747 			 * values here is intentional in some cases and the caller
25748 			 * ignores the results.
25749 			 */
25750 			dparts[idx] -= 1.0;
25751 		}
25752 	}
25753 
25754 	/* Leaves new timevalue on stack top and returns 1, which is correct
25755 	 * for part setters.
25756 	 */
25757 	if (DUK_ISFINITE(d)) {
25758 		return duk__set_this_timeval_from_dparts(ctx, dparts, flags_and_maxnargs);
25759 	} else {
25760 		/* Internal timevalue is already NaN, so don't touch it. */
25761 		duk_push_nan(ctx);
25762 		return 1;
25763 	}
25764 }
25765 
25766 /* Apply ToNumber() to specified index; if ToInteger(val) in [0,99], add
25767  * 1900 and replace value at idx_val.
25768  */
duk__twodigit_year_fixup(duk_context * ctx,duk_idx_t idx_val)25769 DUK_LOCAL void duk__twodigit_year_fixup(duk_context *ctx, duk_idx_t idx_val) {
25770 	duk_double_t d;
25771 
25772 	/* XXX: idx_val would fit into 16 bits, but using duk_small_uint_t
25773 	 * might not generate better code due to casting.
25774 	 */
25775 
25776 	/* E5 Sections 15.9.3.1, B.2.4, B.2.5 */
25777 	duk_to_number(ctx, idx_val);
25778 	if (duk_is_nan(ctx, idx_val)) {
25779 		return;
25780 	}
25781 	duk_dup(ctx, idx_val);
25782 	duk_to_int(ctx, -1);
25783 	d = duk_get_number(ctx, -1);  /* get as double to handle huge numbers correctly */
25784 	if (d >= 0.0 && d <= 99.0) {
25785 		d += 1900.0;
25786 		duk_push_number(ctx, d);
25787 		duk_replace(ctx, idx_val);
25788 	}
25789 	duk_pop(ctx);
25790 }
25791 
25792 /* Set datetime parts from stack arguments, defaulting any missing values.
25793  * Day-of-week is not set; it is not required when setting the time value.
25794  */
duk__set_parts_from_args(duk_context * ctx,duk_double_t * dparts,duk_idx_t nargs)25795 DUK_LOCAL void duk__set_parts_from_args(duk_context *ctx, duk_double_t *dparts, duk_idx_t nargs) {
25796 	duk_double_t d;
25797 	duk_small_uint_t i;
25798 	duk_small_uint_t idx;
25799 
25800 	/* Causes a ToNumber() coercion, but doesn't break coercion order since
25801 	 * year is coerced first anyway.
25802 	 */
25803 	duk__twodigit_year_fixup(ctx, 0);
25804 
25805 	/* There are at most 7 args, but we use 8 here so that also
25806 	 * DUK_DATE_IDX_WEEKDAY gets initialized (to zero) to avoid the potential
25807 	 * for any Valgrind gripes later.
25808 	 */
25809 	for (i = 0; i < 8; i++) {
25810 		/* Note: rely on index ordering */
25811 		idx = DUK_DATE_IDX_YEAR + i;
25812 		if ((duk_idx_t) i < nargs) {
25813 			d = duk_to_number(ctx, (duk_idx_t) i);
25814 			if (idx == DUK_DATE_IDX_DAY) {
25815 				/* Convert day from one-based to zero-based (internal).  This may
25816 				 * cause the day part to be negative, which is OK.
25817 				 */
25818 				d -= 1.0;
25819 			}
25820 		} else {
25821 			/* All components default to 0 except day-of-month which defaults
25822 			 * to 1.  However, because our internal day-of-month is zero-based,
25823 			 * it also defaults to zero here.
25824 			 */
25825 			d = 0.0;
25826 		}
25827 		dparts[idx] = d;
25828 	}
25829 
25830 	DUK_DDD(DUK_DDDPRINT("parts from args -> %lf %lf %lf %lf %lf %lf %lf %lf",
25831 	                     (double) dparts[0], (double) dparts[1],
25832 	                     (double) dparts[2], (double) dparts[3],
25833 	                     (double) dparts[4], (double) dparts[5],
25834 	                     (double) dparts[6], (double) dparts[7]));
25835 }
25836 
25837 /*
25838  *  Helper to format a time value into caller buffer, used by logging.
25839  *  'out_buf' must be at least DUK_BI_DATE_ISO8601_BUFSIZE long.
25840  */
25841 
duk_bi_date_format_timeval(duk_double_t timeval,duk_uint8_t * out_buf)25842 DUK_INTERNAL void duk_bi_date_format_timeval(duk_double_t timeval, duk_uint8_t *out_buf) {
25843 	duk_int_t parts[DUK_DATE_IDX_NUM_PARTS];
25844 
25845 	duk_bi_date_timeval_to_parts(timeval,
25846 	                             parts,
25847 	                             NULL,
25848 	                             DUK_DATE_FLAG_ONEBASED);
25849 
25850 	duk__format_parts_iso8601(parts,
25851 	                          0 /*tzoffset*/,
25852 	                          DUK_DATE_FLAG_TOSTRING_DATE |
25853 	                          DUK_DATE_FLAG_TOSTRING_TIME |
25854 	                          DUK_DATE_FLAG_SEP_T /*flags*/,
25855 	                          out_buf);
25856 }
25857 
25858 /*
25859  *  Indirect magic value lookup for Date methods.
25860  *
25861  *  Date methods don't put their control flags into the function magic value
25862  *  because they wouldn't fit into a LIGHTFUNC's magic field.  Instead, the
25863  *  magic value is set to an index pointing to the array of control flags
25864  *  below.
25865  *
25866  *  This must be kept in strict sync with genbuiltins.py!
25867  */
25868 
25869 static duk_uint16_t duk__date_magics[] = {
25870 	/* 0: toString */
25871 	DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_LOCALTIME,
25872 
25873 	/* 1: toDateString */
25874 	DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_LOCALTIME,
25875 
25876 	/* 2: toTimeString */
25877 	DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_LOCALTIME,
25878 
25879 	/* 3: toLocaleString */
25880 	DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_TOSTRING_LOCALE + DUK_DATE_FLAG_LOCALTIME,
25881 
25882 	/* 4: toLocaleDateString */
25883 	DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_LOCALE + DUK_DATE_FLAG_LOCALTIME,
25884 
25885 	/* 5: toLocaleTimeString */
25886 	DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_TOSTRING_LOCALE + DUK_DATE_FLAG_LOCALTIME,
25887 
25888 	/* 6: toUTCString */
25889 	DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_TIME,
25890 
25891 	/* 7: toISOString */
25892 	DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_NAN_TO_RANGE_ERROR + DUK_DATE_FLAG_SEP_T,
25893 
25894 	/* 8: getFullYear */
25895 	DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_YEAR << DUK_DATE_FLAG_VALUE_SHIFT),
25896 
25897 	/* 9: getUTCFullYear */
25898 	0 + (DUK_DATE_IDX_YEAR << DUK_DATE_FLAG_VALUE_SHIFT),
25899 
25900 	/* 10: getMonth */
25901 	DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_MONTH << DUK_DATE_FLAG_VALUE_SHIFT),
25902 
25903 	/* 11: getUTCMonth */
25904 	0 + (DUK_DATE_IDX_MONTH << DUK_DATE_FLAG_VALUE_SHIFT),
25905 
25906 	/* 12: getDate */
25907 	DUK_DATE_FLAG_ONEBASED + DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_DAY << DUK_DATE_FLAG_VALUE_SHIFT),
25908 
25909 	/* 13: getUTCDate */
25910 	DUK_DATE_FLAG_ONEBASED + (DUK_DATE_IDX_DAY << DUK_DATE_FLAG_VALUE_SHIFT),
25911 
25912 	/* 14: getDay */
25913 	DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_WEEKDAY << DUK_DATE_FLAG_VALUE_SHIFT),
25914 
25915 	/* 15: getUTCDay */
25916 	0 + (DUK_DATE_IDX_WEEKDAY << DUK_DATE_FLAG_VALUE_SHIFT),
25917 
25918 	/* 16: getHours */
25919 	DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_HOUR << DUK_DATE_FLAG_VALUE_SHIFT),
25920 
25921 	/* 17: getUTCHours */
25922 	0 + (DUK_DATE_IDX_HOUR << DUK_DATE_FLAG_VALUE_SHIFT),
25923 
25924 	/* 18: getMinutes */
25925 	DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_MINUTE << DUK_DATE_FLAG_VALUE_SHIFT),
25926 
25927 	/* 19: getUTCMinutes */
25928 	0 + (DUK_DATE_IDX_MINUTE << DUK_DATE_FLAG_VALUE_SHIFT),
25929 
25930 	/* 20: getSeconds */
25931 	DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_SECOND << DUK_DATE_FLAG_VALUE_SHIFT),
25932 
25933 	/* 21: getUTCSeconds */
25934 	0 + (DUK_DATE_IDX_SECOND << DUK_DATE_FLAG_VALUE_SHIFT),
25935 
25936 	/* 22: getMilliseconds */
25937 	DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_MILLISECOND << DUK_DATE_FLAG_VALUE_SHIFT),
25938 
25939 	/* 23: getUTCMilliseconds */
25940 	0 + (DUK_DATE_IDX_MILLISECOND << DUK_DATE_FLAG_VALUE_SHIFT),
25941 
25942 	/* 24: setMilliseconds */
25943 	DUK_DATE_FLAG_TIMESETTER + DUK_DATE_FLAG_LOCALTIME + (1 << DUK_DATE_FLAG_VALUE_SHIFT),
25944 
25945 	/* 25: setUTCMilliseconds */
25946 	DUK_DATE_FLAG_TIMESETTER + (1 << DUK_DATE_FLAG_VALUE_SHIFT),
25947 
25948 	/* 26: setSeconds */
25949 	DUK_DATE_FLAG_TIMESETTER + DUK_DATE_FLAG_LOCALTIME + (2 << DUK_DATE_FLAG_VALUE_SHIFT),
25950 
25951 	/* 27: setUTCSeconds */
25952 	DUK_DATE_FLAG_TIMESETTER + (2 << DUK_DATE_FLAG_VALUE_SHIFT),
25953 
25954 	/* 28: setMinutes */
25955 	DUK_DATE_FLAG_TIMESETTER + DUK_DATE_FLAG_LOCALTIME + (3 << DUK_DATE_FLAG_VALUE_SHIFT),
25956 
25957 	/* 29: setUTCMinutes */
25958 	DUK_DATE_FLAG_TIMESETTER + (3 << DUK_DATE_FLAG_VALUE_SHIFT),
25959 
25960 	/* 30: setHours */
25961 	DUK_DATE_FLAG_TIMESETTER + DUK_DATE_FLAG_LOCALTIME + (4 << DUK_DATE_FLAG_VALUE_SHIFT),
25962 
25963 	/* 31: setUTCHours */
25964 	DUK_DATE_FLAG_TIMESETTER + (4 << DUK_DATE_FLAG_VALUE_SHIFT),
25965 
25966 	/* 32: setDate */
25967 	DUK_DATE_FLAG_LOCALTIME + (1 << DUK_DATE_FLAG_VALUE_SHIFT),
25968 
25969 	/* 33: setUTCDate */
25970 	0 + (1 << DUK_DATE_FLAG_VALUE_SHIFT),
25971 
25972 	/* 34: setMonth */
25973 	DUK_DATE_FLAG_LOCALTIME + (2 << DUK_DATE_FLAG_VALUE_SHIFT),
25974 
25975 	/* 35: setUTCMonth */
25976 	0 + (2 << DUK_DATE_FLAG_VALUE_SHIFT),
25977 
25978 	/* 36: setFullYear */
25979 	DUK_DATE_FLAG_NAN_TO_ZERO + DUK_DATE_FLAG_LOCALTIME + (3 << DUK_DATE_FLAG_VALUE_SHIFT),
25980 
25981 	/* 37: setUTCFullYear */
25982 	DUK_DATE_FLAG_NAN_TO_ZERO + (3 << DUK_DATE_FLAG_VALUE_SHIFT),
25983 
25984 	/* 38: getYear */
25985 	DUK_DATE_FLAG_LOCALTIME + DUK_DATE_FLAG_SUB1900 + (DUK_DATE_IDX_YEAR << DUK_DATE_FLAG_VALUE_SHIFT),
25986 
25987 	/* 39: setYear */
25988 	DUK_DATE_FLAG_NAN_TO_ZERO + DUK_DATE_FLAG_YEAR_FIXUP + (3 << DUK_DATE_FLAG_VALUE_SHIFT),
25989 };
25990 
duk__date_get_indirect_magic(duk_context * ctx)25991 DUK_LOCAL duk_small_uint_t duk__date_get_indirect_magic(duk_context *ctx) {
25992 	duk_small_int_t magicidx = (duk_small_uint_t) duk_get_current_magic(ctx);
25993 	DUK_ASSERT(magicidx >= 0 && magicidx < (duk_small_int_t) (sizeof(duk__date_magics) / sizeof(duk_uint16_t)));
25994 	return (duk_small_uint_t) duk__date_magics[magicidx];
25995 }
25996 
25997 /*
25998  *  Constructor calls
25999  */
26000 
duk_bi_date_constructor(duk_context * ctx)26001 DUK_INTERNAL duk_ret_t duk_bi_date_constructor(duk_context *ctx) {
26002 	duk_idx_t nargs = duk_get_top(ctx);
26003 	duk_bool_t is_cons = duk_is_constructor_call(ctx);
26004 	duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
26005 	duk_double_t d;
26006 
26007 	DUK_DDD(DUK_DDDPRINT("Date constructor, nargs=%ld, is_cons=%ld", (long) nargs, (long) is_cons));
26008 
26009 	duk_push_object_helper(ctx,
26010 	                       DUK_HOBJECT_FLAG_EXTENSIBLE |
26011 	                       DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DATE),
26012 	                       DUK_BIDX_DATE_PROTOTYPE);
26013 
26014 	/* Unlike most built-ins, the internal [[PrimitiveValue]] of a Date
26015 	 * is mutable.
26016 	 */
26017 
26018 	if (nargs == 0 || !is_cons) {
26019 		d = duk__timeclip(DUK_USE_DATE_GET_NOW(ctx));
26020 		duk_push_number(ctx, d);
26021 		duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_W);
26022 		if (!is_cons) {
26023 			/* called as a normal function: return new Date().toString() */
26024 			duk_to_string(ctx, -1);
26025 		}
26026 		return 1;
26027 	} else if (nargs == 1) {
26028 		duk_to_primitive(ctx, 0, DUK_HINT_NONE);
26029 		if (duk_is_string(ctx, 0)) {
26030 			duk__parse_string(ctx, duk_to_string(ctx, 0));
26031 			duk_replace(ctx, 0);  /* may be NaN */
26032 		}
26033 		d = duk__timeclip(duk_to_number(ctx, 0));
26034 		duk_push_number(ctx, d);
26035 		duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_W);
26036 		return 1;
26037 	}
26038 
26039 	duk__set_parts_from_args(ctx, dparts, nargs);
26040 
26041 	/* Parts are in local time, convert when setting. */
26042 
26043 	(void) duk__set_this_timeval_from_dparts(ctx, dparts, DUK_DATE_FLAG_LOCALTIME /*flags*/);  /* -> [ ... this timeval ] */
26044 	duk_pop(ctx);  /* -> [ ... this ] */
26045 	return 1;
26046 }
26047 
duk_bi_date_constructor_parse(duk_context * ctx)26048 DUK_INTERNAL duk_ret_t duk_bi_date_constructor_parse(duk_context *ctx) {
26049 	return duk__parse_string(ctx, duk_to_string(ctx, 0));
26050 }
26051 
duk_bi_date_constructor_utc(duk_context * ctx)26052 DUK_INTERNAL duk_ret_t duk_bi_date_constructor_utc(duk_context *ctx) {
26053 	duk_idx_t nargs = duk_get_top(ctx);
26054 	duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
26055 	duk_double_t d;
26056 
26057 	/* Behavior for nargs < 2 is implementation dependent: currently we'll
26058 	 * set a NaN time value (matching V8 behavior) in this case.
26059 	 */
26060 
26061 	if (nargs < 2) {
26062 		duk_push_nan(ctx);
26063 	} else {
26064 		duk__set_parts_from_args(ctx, dparts, nargs);
26065 		d = duk_bi_date_get_timeval_from_dparts(dparts, 0 /*flags*/);
26066 		duk_push_number(ctx, d);
26067 	}
26068 	return 1;
26069 }
26070 
duk_bi_date_constructor_now(duk_context * ctx)26071 DUK_INTERNAL duk_ret_t duk_bi_date_constructor_now(duk_context *ctx) {
26072 	duk_double_t d;
26073 
26074 	d = DUK_USE_DATE_GET_NOW(ctx);
26075 	DUK_ASSERT(duk__timeclip(d) == d);  /* TimeClip() should never be necessary */
26076 	duk_push_number(ctx, d);
26077 	return 1;
26078 }
26079 
26080 /*
26081  *  String/JSON conversions
26082  *
26083  *  Human readable conversions are now basically ISO 8601 with a space
26084  *  (instead of 'T') as the date/time separator.  This is a good baseline
26085  *  and is platform independent.
26086  *
26087  *  A shared native helper to provide many conversions.  Magic value contains
26088  *  a set of flags.  The helper provides:
26089  *
26090  *    toString()
26091  *    toDateString()
26092  *    toTimeString()
26093  *    toLocaleString()
26094  *    toLocaleDateString()
26095  *    toLocaleTimeString()
26096  *    toUTCString()
26097  *    toISOString()
26098  *
26099  *  Notes:
26100  *
26101  *    - Date.prototype.toGMTString() and Date.prototype.toUTCString() are
26102  *      required to be the same Ecmascript function object (!), so it is
26103  *      omitted from here.
26104  *
26105  *    - Date.prototype.toUTCString(): E5.1 specification does not require a
26106  *      specific format, but result should be human readable.  The
26107  *      specification suggests using ISO 8601 format with a space (instead
26108  *      of 'T') separator if a more human readable format is not available.
26109  *
26110  *    - Date.prototype.toISOString(): unlike other conversion functions,
26111  *      toISOString() requires a RangeError for invalid date values.
26112  */
26113 
duk_bi_date_prototype_tostring_shared(duk_context * ctx)26114 DUK_INTERNAL duk_ret_t duk_bi_date_prototype_tostring_shared(duk_context *ctx) {
26115 	duk_small_uint_t flags = duk__date_get_indirect_magic(ctx);
26116 	return duk__to_string_helper(ctx, flags);
26117 }
26118 
duk_bi_date_prototype_value_of(duk_context * ctx)26119 DUK_INTERNAL duk_ret_t duk_bi_date_prototype_value_of(duk_context *ctx) {
26120 	/* This native function is also used for Date.prototype.getTime()
26121 	 * as their behavior is identical.
26122 	 */
26123 
26124 	duk_double_t d = duk__push_this_get_timeval(ctx, 0 /*flags*/);  /* -> [ this ] */
26125 	DUK_ASSERT(DUK_ISFINITE(d) || DUK_ISNAN(d));
26126 	duk_push_number(ctx, d);
26127 	return 1;
26128 }
26129 
duk_bi_date_prototype_to_json(duk_context * ctx)26130 DUK_INTERNAL duk_ret_t duk_bi_date_prototype_to_json(duk_context *ctx) {
26131 	/* Note: toJSON() is a generic function which works even if 'this'
26132 	 * is not a Date.  The sole argument is ignored.
26133 	 */
26134 
26135 	duk_push_this(ctx);
26136 	duk_to_object(ctx, -1);
26137 
26138 	duk_dup_top(ctx);
26139 	duk_to_primitive(ctx, -1, DUK_HINT_NUMBER);
26140 	if (duk_is_number(ctx, -1)) {
26141 		duk_double_t d = duk_get_number(ctx, -1);
26142 		if (!DUK_ISFINITE(d)) {
26143 			duk_push_null(ctx);
26144 			return 1;
26145 		}
26146 	}
26147 	duk_pop(ctx);
26148 
26149 	duk_get_prop_stridx(ctx, -1, DUK_STRIDX_TO_ISO_STRING);
26150 	duk_dup(ctx, -2);  /* -> [ O toIsoString O ] */
26151 	duk_call_method(ctx, 0);
26152 	return 1;
26153 }
26154 
26155 /*
26156  *  Getters.
26157  *
26158  *  Implementing getters is quite easy.  The internal time value is either
26159  *  NaN, or represents milliseconds (without fractions) from Jan 1, 1970.
26160  *  The internal time value can be converted to integer parts, and each
26161  *  part will be normalized and will fit into a 32-bit signed integer.
26162  *
26163  *  A shared native helper to provide all getters.  Magic value contains
26164  *  a set of flags and also packs the date component index argument.  The
26165  *  helper provides:
26166  *
26167  *    getFullYear()
26168  *    getUTCFullYear()
26169  *    getMonth()
26170  *    getUTCMonth()
26171  *    getDate()
26172  *    getUTCDate()
26173  *    getDay()
26174  *    getUTCDay()
26175  *    getHours()
26176  *    getUTCHours()
26177  *    getMinutes()
26178  *    getUTCMinutes()
26179  *    getSeconds()
26180  *    getUTCSeconds()
26181  *    getMilliseconds()
26182  *    getUTCMilliseconds()
26183  *    getYear()
26184  *
26185  *  Notes:
26186  *
26187  *    - Date.prototype.getDate(): 'date' means day-of-month, and is
26188  *      zero-based in internal calculations but public API expects it to
26189  *      be one-based.
26190  *
26191  *    - Date.prototype.getTime() and Date.prototype.valueOf() have identical
26192  *      behavior.  They have separate function objects, but share the same C
26193  *      function (duk_bi_date_prototype_value_of).
26194  */
26195 
duk_bi_date_prototype_get_shared(duk_context * ctx)26196 DUK_INTERNAL duk_ret_t duk_bi_date_prototype_get_shared(duk_context *ctx) {
26197 	duk_small_uint_t flags_and_idx = duk__date_get_indirect_magic(ctx);
26198 	return duk__get_part_helper(ctx, flags_and_idx);
26199 }
26200 
duk_bi_date_prototype_get_timezone_offset(duk_context * ctx)26201 DUK_INTERNAL duk_ret_t duk_bi_date_prototype_get_timezone_offset(duk_context *ctx) {
26202 	/*
26203 	 *  Return (t - LocalTime(t)) in minutes:
26204 	 *
26205 	 *    t - LocalTime(t) = t - (t + LocalTZA + DaylightSavingTA(t))
26206 	 *                     = -(LocalTZA + DaylightSavingTA(t))
26207 	 *
26208 	 *  where DaylightSavingTA() is checked for time 't'.
26209 	 *
26210 	 *  Note that the sign of the result is opposite to common usage,
26211 	 *  e.g. for EE(S)T which normally is +2h or +3h from UTC, this
26212 	 *  function returns -120 or -180.
26213 	 *
26214 	 */
26215 
26216 	duk_double_t d;
26217 	duk_int_t tzoffset;
26218 
26219 	/* Note: DST adjustment is determined using UTC time. */
26220 	d = duk__push_this_get_timeval(ctx, 0 /*flags*/);
26221 	DUK_ASSERT(DUK_ISFINITE(d) || DUK_ISNAN(d));
26222 	if (DUK_ISNAN(d)) {
26223 		duk_push_nan(ctx);
26224 	} else {
26225 		DUK_ASSERT(DUK_ISFINITE(d));
26226 		tzoffset = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d);
26227 		duk_push_int(ctx, -tzoffset / 60);
26228 	}
26229 	return 1;
26230 }
26231 
26232 /*
26233  *  Setters.
26234  *
26235  *  Setters are a bit more complicated than getters.  Component setters
26236  *  break down the current time value into its (normalized) component
26237  *  parts, replace one or more components with -unnormalized- new values,
26238  *  and the components are then converted back into a time value.  As an
26239  *  example of using unnormalized values:
26240  *
26241  *    var d = new Date(1234567890);
26242  *
26243  *  is equivalent to:
26244  *
26245  *    var d = new Date(0);
26246  *    d.setUTCMilliseconds(1234567890);
26247  *
26248  *  A shared native helper to provide almost all setters.  Magic value
26249  *  contains a set of flags and also packs the "maxnargs" argument.  The
26250  *  helper provides:
26251  *
26252  *    setMilliseconds()
26253  *    setUTCMilliseconds()
26254  *    setSeconds()
26255  *    setUTCSeconds()
26256  *    setMinutes()
26257  *    setUTCMinutes()
26258  *    setHours()
26259  *    setUTCHours()
26260  *    setDate()
26261  *    setUTCDate()
26262  *    setMonth()
26263  *    setUTCMonth()
26264  *    setFullYear()
26265  *    setUTCFullYear()
26266  *    setYear()
26267  *
26268  *  Notes:
26269  *
26270  *    - Date.prototype.setYear() (Section B addition): special year check
26271  *      is omitted.  NaN / Infinity will just flow through and ultimately
26272  *      result in a NaN internal time value.
26273  *
26274  *    - Date.prototype.setYear() does not have optional arguments for
26275  *      setting month and day-in-month (like setFullYear()), but we indicate
26276  *      'maxnargs' to be 3 to get the year written to the correct component
26277  *      index in duk__set_part_helper().  The function has nargs == 1, so only
26278  *      the year will be set regardless of actual argument count.
26279  */
26280 
duk_bi_date_prototype_set_shared(duk_context * ctx)26281 DUK_INTERNAL duk_ret_t duk_bi_date_prototype_set_shared(duk_context *ctx) {
26282 	duk_small_uint_t flags_and_maxnargs = duk__date_get_indirect_magic(ctx);
26283 	return duk__set_part_helper(ctx, flags_and_maxnargs);
26284 }
26285 
duk_bi_date_prototype_set_time(duk_context * ctx)26286 DUK_INTERNAL duk_ret_t duk_bi_date_prototype_set_time(duk_context *ctx) {
26287 	duk_double_t d;
26288 
26289 	(void) duk__push_this_get_timeval(ctx, 0 /*flags*/); /* -> [ timeval this ] */
26290 	d = duk__timeclip(duk_to_number(ctx, 0));
26291 	duk_push_number(ctx, d);
26292 	duk_dup_top(ctx);
26293 	duk_put_prop_stridx(ctx, -3, DUK_STRIDX_INT_VALUE); /* -> [ timeval this timeval ] */
26294 
26295 	return 1;
26296 }
26297 /*
26298  *  Unix-like Date providers
26299  *
26300  *  Generally useful Unix / POSIX / ANSI Date providers.
26301  */
26302 
26303 /* include removed: duk_internal.h */
26304 
26305 /* The necessary #includes are in place in duk_config.h. */
26306 
26307 /* Buffer sizes for some UNIX calls.  Larger than strictly necessary
26308  * to avoid Valgrind errors.
26309  */
26310 #define DUK__STRPTIME_BUF_SIZE  64
26311 #define DUK__STRFTIME_BUF_SIZE  64
26312 
26313 #if defined(DUK_USE_DATE_NOW_GETTIMEOFDAY)
26314 /* Get current Ecmascript time (= UNIX/Posix time, but in milliseconds). */
duk_bi_date_get_now_gettimeofday(duk_context * ctx)26315 DUK_INTERNAL duk_double_t duk_bi_date_get_now_gettimeofday(duk_context *ctx) {
26316 	duk_hthread *thr = (duk_hthread *) ctx;
26317 	struct timeval tv;
26318 	duk_double_t d;
26319 
26320 	if (gettimeofday(&tv, NULL) != 0) {
26321 		DUK_ERROR_INTERNAL_DEFMSG(thr);
26322 	}
26323 
26324 	d = ((duk_double_t) tv.tv_sec) * 1000.0 +
26325 	    ((duk_double_t) (tv.tv_usec / 1000));
26326 	DUK_ASSERT(DUK_FLOOR(d) == d);  /* no fractions */
26327 
26328 	return d;
26329 }
26330 #endif  /* DUK_USE_DATE_NOW_GETTIMEOFDAY */
26331 
26332 #if defined(DUK_USE_DATE_NOW_TIME)
26333 /* Not a very good provider: only full seconds are available. */
duk_bi_date_get_now_time(duk_context * ctx)26334 DUK_INTERNAL duk_double_t duk_bi_date_get_now_time(duk_context *ctx) {
26335 	time_t t;
26336 
26337 	DUK_UNREF(ctx);
26338 	t = time(NULL);
26339 	return ((duk_double_t) t) * 1000.0;
26340 }
26341 #endif  /* DUK_USE_DATE_NOW_TIME */
26342 
26343 #if defined(DUK_USE_DATE_TZO_GMTIME) || defined(DUK_USE_DATE_TZO_GMTIME_R)
26344 /* Get local time offset (in seconds) for a certain (UTC) instant 'd'. */
duk_bi_date_get_local_tzoffset_gmtime(duk_double_t d)26345 DUK_INTERNAL duk_int_t duk_bi_date_get_local_tzoffset_gmtime(duk_double_t d) {
26346 	time_t t, t1, t2;
26347 	duk_int_t parts[DUK_DATE_IDX_NUM_PARTS];
26348 	duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
26349 	struct tm tms[2];
26350 #ifdef DUK_USE_DATE_TZO_GMTIME
26351 	struct tm *tm_ptr;
26352 #endif
26353 
26354 	/* For NaN/inf, the return value doesn't matter. */
26355 	if (!DUK_ISFINITE(d)) {
26356 		return 0;
26357 	}
26358 
26359 	/* If not within Ecmascript range, some integer time calculations
26360 	 * won't work correctly (and some asserts will fail), so bail out
26361 	 * if so.  This fixes test-bug-date-insane-setyear.js.  There is
26362 	 * a +/- 24h leeway in this range check to avoid a test262 corner
26363 	 * case documented in test-bug-date-timeval-edges.js.
26364 	 */
26365 	if (!duk_bi_date_timeval_in_leeway_range(d)) {
26366 		DUK_DD(DUK_DDPRINT("timeval not within valid range, skip tzoffset computation to avoid integer overflows"));
26367 		return 0;
26368 	}
26369 
26370 	/*
26371 	 *  This is a bit tricky to implement portably.  The result depends
26372 	 *  on the timestamp (specifically, DST depends on the timestamp).
26373 	 *  If e.g. UNIX APIs are used, they'll have portability issues with
26374 	 *  very small and very large years.
26375 	 *
26376 	 *  Current approach:
26377 	 *
26378 	 *  - Stay within portable UNIX limits by using equivalent year mapping.
26379 	 *    Avoid year 1970 and 2038 as some conversions start to fail, at
26380 	 *    least on some platforms.  Avoiding 1970 means that there are
26381 	 *    currently DST discrepancies for 1970.
26382 	 *
26383 	 *  - Create a UTC and local time breakdowns from 't'.  Then create
26384 	 *    a time_t using gmtime() and localtime() and compute the time
26385 	 *    difference between the two.
26386 	 *
26387 	 *  Equivalent year mapping (E5 Section 15.9.1.8):
26388 	 *
26389 	 *    If the host environment provides functionality for determining
26390 	 *    daylight saving time, the implementation of ECMAScript is free
26391 	 *    to map the year in question to an equivalent year (same
26392 	 *    leap-year-ness and same starting week day for the year) for which
26393 	 *    the host environment provides daylight saving time information.
26394 	 *    The only restriction is that all equivalent years should produce
26395 	 *    the same result.
26396 	 *
26397 	 *  This approach is quite reasonable but not entirely correct, e.g.
26398 	 *  the specification also states (E5 Section 15.9.1.8):
26399 	 *
26400 	 *    The implementation of ECMAScript should not try to determine
26401 	 *    whether the exact time was subject to daylight saving time, but
26402 	 *    just whether daylight saving time would have been in effect if
26403 	 *    the _current daylight saving time algorithm_ had been used at the
26404 	 *    time.  This avoids complications such as taking into account the
26405 	 *    years that the locale observed daylight saving time year round.
26406 	 *
26407 	 *  Since we rely on the platform APIs for conversions between local
26408 	 *  time and UTC, we can't guarantee the above.  Rather, if the platform
26409 	 *  has historical DST rules they will be applied.  This seems to be the
26410 	 *  general preferred direction in Ecmascript standardization (or at least
26411 	 *  implementations) anyway, and even the equivalent year mapping should
26412 	 *  be disabled if the platform is known to handle DST properly for the
26413 	 *  full Ecmascript range.
26414 	 *
26415 	 *  The following has useful discussion and links:
26416 	 *
26417 	 *    https://bugzilla.mozilla.org/show_bug.cgi?id=351066
26418 	 */
26419 
26420 	duk_bi_date_timeval_to_parts(d, parts, dparts, DUK_DATE_FLAG_EQUIVYEAR /*flags*/);
26421 	DUK_ASSERT(parts[DUK_DATE_IDX_YEAR] >= 1970 && parts[DUK_DATE_IDX_YEAR] <= 2038);
26422 
26423 	d = duk_bi_date_get_timeval_from_dparts(dparts, 0 /*flags*/);
26424 	DUK_ASSERT(d >= 0 && d < 2147483648.0 * 1000.0);  /* unsigned 31-bit range */
26425 	t = (time_t) (d / 1000.0);
26426 	DUK_DDD(DUK_DDDPRINT("timeval: %lf -> time_t %ld", (double) d, (long) t));
26427 
26428 	DUK_MEMZERO((void *) tms, sizeof(struct tm) * 2);
26429 
26430 #if defined(DUK_USE_DATE_TZO_GMTIME_R)
26431 	(void) gmtime_r(&t, &tms[0]);
26432 	(void) localtime_r(&t, &tms[1]);
26433 #elif defined(DUK_USE_DATE_TZO_GMTIME)
26434 	tm_ptr = gmtime(&t);
26435 	DUK_MEMCPY((void *) &tms[0], tm_ptr, sizeof(struct tm));
26436 	tm_ptr = localtime(&t);
26437 	DUK_MEMCPY((void *) &tms[1], tm_ptr, sizeof(struct tm));
26438 #else
26439 #error internal error
26440 #endif
26441 	DUK_DDD(DUK_DDDPRINT("gmtime result: tm={sec:%ld,min:%ld,hour:%ld,mday:%ld,mon:%ld,year:%ld,"
26442 	                     "wday:%ld,yday:%ld,isdst:%ld}",
26443 	                     (long) tms[0].tm_sec, (long) tms[0].tm_min, (long) tms[0].tm_hour,
26444 	                     (long) tms[0].tm_mday, (long) tms[0].tm_mon, (long) tms[0].tm_year,
26445 	                     (long) tms[0].tm_wday, (long) tms[0].tm_yday, (long) tms[0].tm_isdst));
26446 	DUK_DDD(DUK_DDDPRINT("localtime result: tm={sec:%ld,min:%ld,hour:%ld,mday:%ld,mon:%ld,year:%ld,"
26447 	                     "wday:%ld,yday:%ld,isdst:%ld}",
26448 	                     (long) tms[1].tm_sec, (long) tms[1].tm_min, (long) tms[1].tm_hour,
26449 	                     (long) tms[1].tm_mday, (long) tms[1].tm_mon, (long) tms[1].tm_year,
26450 	                     (long) tms[1].tm_wday, (long) tms[1].tm_yday, (long) tms[1].tm_isdst));
26451 
26452 	/* tm_isdst is both an input and an output to mktime(), use 0 to
26453 	 * avoid DST handling in mktime():
26454 	 * - https://github.com/svaarala/duktape/issues/406
26455 	 * - http://stackoverflow.com/questions/8558919/mktime-and-tm-isdst
26456 	 */
26457 	tms[0].tm_isdst = 0;
26458 	tms[1].tm_isdst = 0;
26459 	t1 = mktime(&tms[0]);  /* UTC */
26460 	t2 = mktime(&tms[1]);  /* local */
26461 	if (t1 == (time_t) -1 || t2 == (time_t) -1) {
26462 		/* This check used to be for (t < 0) but on some platforms
26463 		 * time_t is unsigned and apparently the proper way to detect
26464 		 * an mktime() error return is the cast above.  See e.g.:
26465 		 * http://pubs.opengroup.org/onlinepubs/009695299/functions/mktime.html
26466 		 */
26467 		goto error;
26468 	}
26469 	DUK_DDD(DUK_DDDPRINT("t1=%ld (utc), t2=%ld (local)", (long) t1, (long) t2));
26470 
26471 	/* Compute final offset in seconds, positive if local time ahead of
26472 	 * UTC (returned value is UTC-to-local offset).
26473 	 *
26474 	 * difftime() returns a double, so coercion to int generates quite
26475 	 * a lot of code.  Direct subtraction is not portable, however.
26476 	 * XXX: allow direct subtraction on known platforms.
26477 	 */
26478 #if 0
26479 	return (duk_int_t) (t2 - t1);
26480 #endif
26481 	return (duk_int_t) difftime(t2, t1);
26482 
26483  error:
26484 	/* XXX: return something more useful, so that caller can throw? */
26485 	DUK_D(DUK_DPRINT("mktime() failed, d=%lf", (double) d));
26486 	return 0;
26487 }
26488 #endif  /* DUK_USE_DATE_TZO_GMTIME */
26489 
26490 #if defined(DUK_USE_DATE_PRS_STRPTIME)
duk_bi_date_parse_string_strptime(duk_context * ctx,const char * str)26491 DUK_INTERNAL duk_bool_t duk_bi_date_parse_string_strptime(duk_context *ctx, const char *str) {
26492 	struct tm tm;
26493 	time_t t;
26494 	char buf[DUK__STRPTIME_BUF_SIZE];
26495 
26496 	/* copy to buffer with spare to avoid Valgrind gripes from strptime */
26497 	DUK_ASSERT(str != NULL);
26498 	DUK_MEMZERO(buf, sizeof(buf));  /* valgrind whine without this */
26499 	DUK_SNPRINTF(buf, sizeof(buf), "%s", (const char *) str);
26500 	buf[sizeof(buf) - 1] = (char) 0;
26501 
26502 	DUK_DDD(DUK_DDDPRINT("parsing: '%s'", (const char *) buf));
26503 
26504 	DUK_MEMZERO(&tm, sizeof(tm));
26505 	if (strptime((const char *) buf, "%c", &tm) != NULL) {
26506 		DUK_DDD(DUK_DDDPRINT("before mktime: tm={sec:%ld,min:%ld,hour:%ld,mday:%ld,mon:%ld,year:%ld,"
26507 		                     "wday:%ld,yday:%ld,isdst:%ld}",
26508 		                     (long) tm.tm_sec, (long) tm.tm_min, (long) tm.tm_hour,
26509 		                     (long) tm.tm_mday, (long) tm.tm_mon, (long) tm.tm_year,
26510 		                     (long) tm.tm_wday, (long) tm.tm_yday, (long) tm.tm_isdst));
26511 		tm.tm_isdst = -1;  /* negative: dst info not available */
26512 
26513 		t = mktime(&tm);
26514 		DUK_DDD(DUK_DDDPRINT("mktime() -> %ld", (long) t));
26515 		if (t >= 0) {
26516 			duk_push_number(ctx, ((duk_double_t) t) * 1000.0);
26517 			return 1;
26518 		}
26519 	}
26520 
26521 	return 0;
26522 }
26523 #endif  /* DUK_USE_DATE_PRS_STRPTIME */
26524 
26525 #if defined(DUK_USE_DATE_PRS_GETDATE)
duk_bi_date_parse_string_getdate(duk_context * ctx,const char * str)26526 DUK_INTERNAL duk_bool_t duk_bi_date_parse_string_getdate(duk_context *ctx, const char *str) {
26527 	struct tm tm;
26528 	duk_small_int_t rc;
26529 	time_t t;
26530 
26531 	/* For this to work, DATEMSK must be set, so this is not very
26532 	 * convenient for an embeddable interpreter.
26533 	 */
26534 
26535 	DUK_MEMZERO(&tm, sizeof(struct tm));
26536 	rc = (duk_small_int_t) getdate_r(str, &tm);
26537 	DUK_DDD(DUK_DDDPRINT("getdate_r() -> %ld", (long) rc));
26538 
26539 	if (rc == 0) {
26540 		t = mktime(&tm);
26541 		DUK_DDD(DUK_DDDPRINT("mktime() -> %ld", (long) t));
26542 		if (t >= 0) {
26543 			duk_push_number(ctx, (duk_double_t) t);
26544 			return 1;
26545 		}
26546 	}
26547 
26548 	return 0;
26549 }
26550 #endif  /* DUK_USE_DATE_PRS_GETDATE */
26551 
26552 #if defined(DUK_USE_DATE_FMT_STRFTIME)
duk_bi_date_format_parts_strftime(duk_context * ctx,duk_int_t * parts,duk_int_t tzoffset,duk_small_uint_t flags)26553 DUK_INTERNAL duk_bool_t duk_bi_date_format_parts_strftime(duk_context *ctx, duk_int_t *parts, duk_int_t tzoffset, duk_small_uint_t flags) {
26554 	char buf[DUK__STRFTIME_BUF_SIZE];
26555 	struct tm tm;
26556 	const char *fmt;
26557 
26558 	DUK_UNREF(tzoffset);
26559 
26560 	/* If the platform doesn't support the entire Ecmascript range, we need
26561 	 * to return 0 so that the caller can fall back to the default formatter.
26562 	 *
26563 	 * For now, assume that if time_t is 8 bytes or more, the whole Ecmascript
26564 	 * range is supported.  For smaller time_t values (4 bytes in practice),
26565 	 * assumes that the signed 32-bit range is supported.
26566 	 *
26567 	 * XXX: detect this more correctly per platform.  The size of time_t is
26568 	 * probably not an accurate guarantee of strftime() supporting or not
26569 	 * supporting a large time range (the full Ecmascript range).
26570 	 */
26571 	if (sizeof(time_t) < 8 &&
26572 	   (parts[DUK_DATE_IDX_YEAR] < 1970 || parts[DUK_DATE_IDX_YEAR] > 2037)) {
26573 		/* be paranoid for 32-bit time values (even avoiding negative ones) */
26574 		return 0;
26575 	}
26576 
26577 	DUK_MEMZERO(&tm, sizeof(tm));
26578 	tm.tm_sec = parts[DUK_DATE_IDX_SECOND];
26579 	tm.tm_min = parts[DUK_DATE_IDX_MINUTE];
26580 	tm.tm_hour = parts[DUK_DATE_IDX_HOUR];
26581 	tm.tm_mday = parts[DUK_DATE_IDX_DAY];       /* already one-based */
26582 	tm.tm_mon = parts[DUK_DATE_IDX_MONTH] - 1;  /* one-based -> zero-based */
26583 	tm.tm_year = parts[DUK_DATE_IDX_YEAR] - 1900;
26584 	tm.tm_wday = parts[DUK_DATE_IDX_WEEKDAY];
26585 	tm.tm_isdst = 0;
26586 
26587 	DUK_MEMZERO(buf, sizeof(buf));
26588 	if ((flags & DUK_DATE_FLAG_TOSTRING_DATE) && (flags & DUK_DATE_FLAG_TOSTRING_TIME)) {
26589 		fmt = "%c";
26590 	} else if (flags & DUK_DATE_FLAG_TOSTRING_DATE) {
26591 		fmt = "%x";
26592 	} else {
26593 		DUK_ASSERT(flags & DUK_DATE_FLAG_TOSTRING_TIME);
26594 		fmt = "%X";
26595 	}
26596 	(void) strftime(buf, sizeof(buf) - 1, fmt, &tm);
26597 	DUK_ASSERT(buf[sizeof(buf) - 1] == 0);
26598 
26599 	duk_push_string(ctx, buf);
26600 	return 1;
26601 }
26602 #endif  /* DUK_USE_DATE_FMT_STRFTIME */
26603 
26604 #undef DUK__STRPTIME_BUF_SIZE
26605 #undef DUK__STRFTIME_BUF_SIZE
26606 /*
26607  *  Windows Date providers
26608  *
26609  *  Platform specific links:
26610  *
26611  *    - http://msdn.microsoft.com/en-us/library/windows/desktop/ms725473(v=vs.85).aspx
26612  */
26613 
26614 /* include removed: duk_internal.h */
26615 
26616 /* The necessary #includes are in place in duk_config.h. */
26617 
26618 #if defined(DUK_USE_DATE_NOW_WINDOWS) || defined(DUK_USE_DATE_TZO_WINDOWS)
26619 /* Shared Windows helpers. */
duk__convert_systime_to_ularge(const SYSTEMTIME * st,ULARGE_INTEGER * res)26620 DUK_LOCAL void duk__convert_systime_to_ularge(const SYSTEMTIME *st, ULARGE_INTEGER *res) {
26621 	FILETIME ft;
26622 	if (SystemTimeToFileTime(st, &ft) == 0) {
26623 		DUK_D(DUK_DPRINT("SystemTimeToFileTime() failed, returning 0"));
26624 		res->QuadPart = 0;
26625 	} else {
26626 		res->LowPart = ft.dwLowDateTime;
26627 		res->HighPart = ft.dwHighDateTime;
26628 	}
26629 }
duk__set_systime_jan1970(SYSTEMTIME * st)26630 DUK_LOCAL void duk__set_systime_jan1970(SYSTEMTIME *st) {
26631 	DUK_MEMZERO((void *) st, sizeof(*st));
26632 	st->wYear = 1970;
26633 	st->wMonth = 1;
26634 	st->wDayOfWeek = 4;  /* not sure whether or not needed; Thursday */
26635 	st->wDay = 1;
26636 	DUK_ASSERT(st->wHour == 0);
26637 	DUK_ASSERT(st->wMinute == 0);
26638 	DUK_ASSERT(st->wSecond == 0);
26639 	DUK_ASSERT(st->wMilliseconds == 0);
26640 }
26641 #endif  /* defined(DUK_USE_DATE_NOW_WINDOWS) || defined(DUK_USE_DATE_TZO_WINDOWS) */
26642 
26643 #ifdef DUK_USE_DATE_NOW_WINDOWS
duk_bi_date_get_now_windows(duk_context * ctx)26644 DUK_INTERNAL duk_double_t duk_bi_date_get_now_windows(duk_context *ctx) {
26645 	/* Suggested step-by-step method from documentation of RtlTimeToSecondsSince1970:
26646 	 * http://msdn.microsoft.com/en-us/library/windows/desktop/ms724928(v=vs.85).aspx
26647 	 */
26648 	SYSTEMTIME st1, st2;
26649 	ULARGE_INTEGER tmp1, tmp2;
26650 
26651 	DUK_UNREF(ctx);
26652 
26653 	GetSystemTime(&st1);
26654 	duk__convert_systime_to_ularge((const SYSTEMTIME *) &st1, &tmp1);
26655 
26656 	duk__set_systime_jan1970(&st2);
26657 	duk__convert_systime_to_ularge((const SYSTEMTIME *) &st2, &tmp2);
26658 
26659 	/* Difference is in 100ns units, convert to milliseconds w/o fractions */
26660 	return (duk_double_t) ((tmp1.QuadPart - tmp2.QuadPart) / 10000LL);
26661 }
26662 #endif  /* DUK_USE_DATE_NOW_WINDOWS */
26663 
26664 
26665 #if defined(DUK_USE_DATE_TZO_WINDOWS)
duk_bi_date_get_local_tzoffset_windows(duk_double_t d)26666 DUK_INTERNAL_DECL duk_int_t duk_bi_date_get_local_tzoffset_windows(duk_double_t d) {
26667 	SYSTEMTIME st1;
26668 	SYSTEMTIME st2;
26669 	SYSTEMTIME st3;
26670 	ULARGE_INTEGER tmp1;
26671 	ULARGE_INTEGER tmp2;
26672 	ULARGE_INTEGER tmp3;
26673 	FILETIME ft1;
26674 
26675 	/* XXX: handling of timestamps outside Windows supported range.
26676 	 * How does Windows deal with dates before 1600?  Does windows
26677 	 * support all Ecmascript years (like -200000 and +200000)?
26678 	 * Should equivalent year mapping be used here too?  If so, use
26679 	 * a shared helper (currently integrated into timeval-to-parts).
26680 	 */
26681 
26682 	/* Use the approach described in "Remarks" of FileTimeToLocalFileTime:
26683 	 * http://msdn.microsoft.com/en-us/library/windows/desktop/ms724277(v=vs.85).aspx
26684 	 */
26685 
26686 	duk__set_systime_jan1970(&st1);
26687 	duk__convert_systime_to_ularge((const SYSTEMTIME *) &st1, &tmp1);
26688 	tmp2.QuadPart = (ULONGLONG) (d * 10000.0);  /* millisec -> 100ns units since jan 1, 1970 */
26689 	tmp2.QuadPart += tmp1.QuadPart;             /* input 'd' in Windows UTC, 100ns units */
26690 
26691 	ft1.dwLowDateTime = tmp2.LowPart;
26692 	ft1.dwHighDateTime = tmp2.HighPart;
26693 	FileTimeToSystemTime((const FILETIME *) &ft1, &st2);
26694 	if (SystemTimeToTzSpecificLocalTime((LPTIME_ZONE_INFORMATION) NULL, &st2, &st3) == 0) {
26695 		DUK_D(DUK_DPRINT("SystemTimeToTzSpecificLocalTime() failed, return tzoffset 0"));
26696 		return 0;
26697 	}
26698 	duk__convert_systime_to_ularge((const SYSTEMTIME *) &st3, &tmp3);
26699 
26700 	/* Positive if local time ahead of UTC. */
26701 	return (duk_int_t) (((LONGLONG) tmp3.QuadPart - (LONGLONG) tmp2.QuadPart) / 10000000LL);  /* seconds */
26702 }
26703 #endif  /* DUK_USE_DATE_TZO_WINDOWS */
26704 /*
26705  *  Duktape built-ins
26706  *
26707  *  Size optimization note: it might seem that vararg multipurpose functions
26708  *  like fin(), enc(), and dec() are not very size optimal, but using a single
26709  *  user-visible Ecmascript function saves a lot of run-time footprint; each
26710  *  Function instance takes >100 bytes.  Using a shared native helper and a
26711  *  'magic' value won't save much if there are multiple Function instances
26712  *  anyway.
26713  */
26714 
26715 /* include removed: duk_internal.h */
26716 
26717 /* Raw helper to extract internal information / statistics about a value.
26718  * The return values are version specific and must not expose anything
26719  * that would lead to security issues (e.g. exposing compiled function
26720  * 'data' buffer might be an issue).  Currently only counts and sizes and
26721  * such are given so there should not be a security impact.
26722  */
duk_bi_duktape_object_info(duk_context * ctx)26723 DUK_INTERNAL duk_ret_t duk_bi_duktape_object_info(duk_context *ctx) {
26724 	duk_hthread *thr = (duk_hthread *) ctx;
26725 	duk_tval *tv;
26726 	duk_heaphdr *h;
26727 	duk_int_t i, n;
26728 
26729 	DUK_UNREF(thr);
26730 
26731 	/* result array */
26732 	duk_push_array(ctx);  /* -> [ val arr ] */
26733 
26734 	/* type tag (public) */
26735 	duk_push_int(ctx, duk_get_type(ctx, 0));
26736 
26737 	/* address */
26738 	tv = duk_get_tval(ctx, 0);
26739 	DUK_ASSERT(tv != NULL);  /* because arg count is 1 */
26740 	if (DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
26741 		h = DUK_TVAL_GET_HEAPHDR(tv);
26742 		duk_push_pointer(ctx, (void *) h);
26743 	} else {
26744 		/* internal type tag */
26745 		duk_push_int(ctx, (duk_int_t) DUK_TVAL_GET_TAG(tv));
26746 		goto done;
26747 	}
26748 	DUK_ASSERT(h != NULL);
26749 
26750 	/* refcount */
26751 #ifdef DUK_USE_REFERENCE_COUNTING
26752 	duk_push_size_t(ctx, DUK_HEAPHDR_GET_REFCOUNT(h));
26753 #else
26754 	duk_push_undefined(ctx);
26755 #endif
26756 
26757 	/* heaphdr size and additional allocation size, followed by
26758 	 * type specific stuff (with varying value count)
26759 	 */
26760 	switch ((duk_small_int_t) DUK_HEAPHDR_GET_TYPE(h)) {
26761 	case DUK_HTYPE_STRING: {
26762 		duk_hstring *h_str = (duk_hstring *) h;
26763 		duk_push_uint(ctx, (duk_uint_t) (sizeof(duk_hstring) + DUK_HSTRING_GET_BYTELEN(h_str) + 1));
26764 		break;
26765 	}
26766 	case DUK_HTYPE_OBJECT: {
26767 		duk_hobject *h_obj = (duk_hobject *) h;
26768 		duk_small_uint_t hdr_size;
26769 		if (DUK_HOBJECT_IS_COMPILEDFUNCTION(h_obj)) {
26770 			hdr_size = (duk_small_uint_t) sizeof(duk_hcompiledfunction);
26771 		} else if (DUK_HOBJECT_IS_NATIVEFUNCTION(h_obj)) {
26772 			hdr_size = (duk_small_uint_t) sizeof(duk_hnativefunction);
26773 		} else if (DUK_HOBJECT_IS_THREAD(h_obj)) {
26774 			hdr_size = (duk_small_uint_t) sizeof(duk_hthread);
26775 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
26776 		} else if (DUK_HOBJECT_IS_BUFFEROBJECT(h_obj)) {
26777 			hdr_size = (duk_small_uint_t) sizeof(duk_hbufferobject);
26778 #endif
26779 		} else {
26780 			hdr_size = (duk_small_uint_t) sizeof(duk_hobject);
26781 		}
26782 		duk_push_uint(ctx, (duk_uint_t) hdr_size);
26783 		duk_push_uint(ctx, (duk_uint_t) DUK_HOBJECT_P_ALLOC_SIZE(h_obj));
26784 		duk_push_uint(ctx, (duk_uint_t) DUK_HOBJECT_GET_ESIZE(h_obj));
26785 		/* Note: e_next indicates the number of gc-reachable entries
26786 		 * in the entry part, and also indicates the index where the
26787 		 * next new property would be inserted.  It does *not* indicate
26788 		 * the number of non-NULL keys present in the object.  That
26789 		 * value could be counted separately but requires a pass through
26790 		 * the key list.
26791 		 */
26792 		duk_push_uint(ctx, (duk_uint_t) DUK_HOBJECT_GET_ENEXT(h_obj));
26793 		duk_push_uint(ctx, (duk_uint_t) DUK_HOBJECT_GET_ASIZE(h_obj));
26794 		duk_push_uint(ctx, (duk_uint_t) DUK_HOBJECT_GET_HSIZE(h_obj));
26795 		if (DUK_HOBJECT_IS_COMPILEDFUNCTION(h_obj)) {
26796 			duk_hbuffer *h_data = (duk_hbuffer *) DUK_HCOMPILEDFUNCTION_GET_DATA(thr->heap, (duk_hcompiledfunction *) h_obj);
26797 			if (h_data) {
26798 				duk_push_uint(ctx, (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_data));
26799 			} else {
26800 				duk_push_uint(ctx, 0);
26801 			}
26802 		}
26803 		break;
26804 	}
26805 	case DUK_HTYPE_BUFFER: {
26806 		duk_hbuffer *h_buf = (duk_hbuffer *) h;
26807 		if (DUK_HBUFFER_HAS_DYNAMIC(h_buf)) {
26808 			if (DUK_HBUFFER_HAS_EXTERNAL(h_buf)) {
26809 				duk_push_uint(ctx, (duk_uint_t) (sizeof(duk_hbuffer_external)));
26810 			} else {
26811 				/* When alloc_size == 0 the second allocation may not
26812 				 * actually exist.
26813 				 */
26814 				duk_push_uint(ctx, (duk_uint_t) (sizeof(duk_hbuffer_dynamic)));
26815 			}
26816 			duk_push_uint(ctx, (duk_uint_t) (DUK_HBUFFER_GET_SIZE(h_buf)));
26817 		} else {
26818 			duk_push_uint(ctx, (duk_uint_t) (sizeof(duk_hbuffer_fixed) + DUK_HBUFFER_GET_SIZE(h_buf) + 1));
26819 		}
26820 		break;
26821 
26822 	}
26823 	}
26824 
26825  done:
26826 	/* set values into ret array */
26827 	/* XXX: primitive to make array from valstack slice */
26828 	n = duk_get_top(ctx);
26829 	for (i = 2; i < n; i++) {
26830 		duk_dup(ctx, i);
26831 		duk_put_prop_index(ctx, 1, i - 2);
26832 	}
26833 	duk_dup(ctx, 1);
26834 	return 1;
26835 }
26836 
duk_bi_duktape_object_act(duk_context * ctx)26837 DUK_INTERNAL duk_ret_t duk_bi_duktape_object_act(duk_context *ctx) {
26838 	duk_hthread *thr = (duk_hthread *) ctx;
26839 	duk_activation *act;
26840 	duk_uint_fast32_t pc;
26841 	duk_uint_fast32_t line;
26842 	duk_int_t level;
26843 
26844 	/* -1             = top callstack entry, callstack[callstack_top - 1]
26845 	 * -callstack_top = bottom callstack entry, callstack[0]
26846 	 */
26847 	level = duk_to_int(ctx, 0);
26848 	if (level >= 0 || -level > (duk_int_t) thr->callstack_top) {
26849 		return 0;
26850 	}
26851 	DUK_ASSERT(level >= -((duk_int_t) thr->callstack_top) && level <= -1);
26852 	act = thr->callstack + thr->callstack_top + level;
26853 
26854 	duk_push_object(ctx);
26855 
26856 	duk_push_tval(ctx, &act->tv_func);
26857 
26858 	/* Relevant PC is just before current one because PC is
26859 	 * post-incremented.  This should match what error augment
26860 	 * code does.
26861 	 */
26862 	pc = duk_hthread_get_act_prev_pc(thr, act);
26863 	duk_push_uint(ctx, (duk_uint_t) pc);
26864 
26865 #if defined(DUK_USE_PC2LINE)
26866 	line = duk_hobject_pc2line_query(ctx, -2, pc);
26867 #else
26868 	line = 0;
26869 #endif
26870 	duk_push_uint(ctx, (duk_uint_t) line);
26871 
26872 	/* Providing access to e.g. act->lex_env would be dangerous: these
26873 	 * internal structures must never be accessible to the application.
26874 	 * Duktape relies on them having consistent data, and this consistency
26875 	 * is only asserted for, not checked for.
26876 	 */
26877 
26878 	/* [ level obj func pc line ] */
26879 
26880 	/* XXX: version specific array format instead? */
26881 	duk_xdef_prop_stridx_wec(ctx, -4, DUK_STRIDX_LINE_NUMBER);
26882 	duk_xdef_prop_stridx_wec(ctx, -3, DUK_STRIDX_PC);
26883 	duk_xdef_prop_stridx_wec(ctx, -2, DUK_STRIDX_LC_FUNCTION);
26884 	return 1;
26885 }
26886 
duk_bi_duktape_object_gc(duk_context * ctx)26887 DUK_INTERNAL duk_ret_t duk_bi_duktape_object_gc(duk_context *ctx) {
26888 #ifdef DUK_USE_MARK_AND_SWEEP
26889 	duk_hthread *thr = (duk_hthread *) ctx;
26890 	duk_small_uint_t flags;
26891 	duk_bool_t rc;
26892 
26893 	flags = (duk_small_uint_t) duk_get_uint(ctx, 0);
26894 	rc = duk_heap_mark_and_sweep(thr->heap, flags);
26895 
26896 	/* XXX: Not sure what the best return value would be in the API.
26897 	 * Return a boolean for now.  Note that rc == 0 is success (true).
26898 	 */
26899 	duk_push_boolean(ctx, !rc);
26900 	return 1;
26901 #else
26902 	DUK_UNREF(ctx);
26903 	return 0;
26904 #endif
26905 }
26906 
duk_bi_duktape_object_fin(duk_context * ctx)26907 DUK_INTERNAL duk_ret_t duk_bi_duktape_object_fin(duk_context *ctx) {
26908 	(void) duk_require_hobject(ctx, 0);
26909 	if (duk_get_top(ctx) >= 2) {
26910 		/* Set: currently a finalizer is disabled by setting it to
26911 		 * undefined; this does not remove the property at the moment.
26912 		 * The value could be type checked to be either a function
26913 		 * or something else; if something else, the property could
26914 		 * be deleted.
26915 		 */
26916 		duk_set_top(ctx, 2);
26917 		(void) duk_put_prop_stridx(ctx, 0, DUK_STRIDX_INT_FINALIZER);
26918 		return 0;
26919 	} else {
26920 		/* Get. */
26921 		DUK_ASSERT(duk_get_top(ctx) == 1);
26922 		duk_get_prop_stridx(ctx, 0, DUK_STRIDX_INT_FINALIZER);
26923 		return 1;
26924 	}
26925 }
26926 
duk_bi_duktape_object_enc(duk_context * ctx)26927 DUK_INTERNAL duk_ret_t duk_bi_duktape_object_enc(duk_context *ctx) {
26928 	duk_hthread *thr = (duk_hthread *) ctx;
26929 	duk_hstring *h_str;
26930 
26931 	DUK_UNREF(thr);
26932 
26933 	/* Vararg function: must be careful to check/require arguments.
26934 	 * The JSON helpers accept invalid indices and treat them like
26935 	 * non-existent optional parameters.
26936 	 */
26937 
26938 	h_str = duk_require_hstring(ctx, 0);
26939 	duk_require_valid_index(ctx, 1);
26940 
26941 	if (h_str == DUK_HTHREAD_STRING_HEX(thr)) {
26942 		duk_set_top(ctx, 2);
26943 		duk_hex_encode(ctx, 1);
26944 		DUK_ASSERT_TOP(ctx, 2);
26945 	} else if (h_str == DUK_HTHREAD_STRING_BASE64(thr)) {
26946 		duk_set_top(ctx, 2);
26947 		duk_base64_encode(ctx, 1);
26948 		DUK_ASSERT_TOP(ctx, 2);
26949 #ifdef DUK_USE_JX
26950 	} else if (h_str == DUK_HTHREAD_STRING_JX(thr)) {
26951 		duk_bi_json_stringify_helper(ctx,
26952 		                             1 /*idx_value*/,
26953 		                             2 /*idx_replacer*/,
26954 		                             3 /*idx_space*/,
26955 		                             DUK_JSON_FLAG_EXT_CUSTOM |
26956 		                             DUK_JSON_FLAG_ASCII_ONLY |
26957 		                             DUK_JSON_FLAG_AVOID_KEY_QUOTES /*flags*/);
26958 #endif
26959 #ifdef DUK_USE_JC
26960 	} else if (h_str == DUK_HTHREAD_STRING_JC(thr)) {
26961 		duk_bi_json_stringify_helper(ctx,
26962 		                             1 /*idx_value*/,
26963 		                             2 /*idx_replacer*/,
26964 		                             3 /*idx_space*/,
26965 		                             DUK_JSON_FLAG_EXT_COMPATIBLE |
26966 		                             DUK_JSON_FLAG_ASCII_ONLY /*flags*/);
26967 #endif
26968 	} else {
26969 		return DUK_RET_TYPE_ERROR;
26970 	}
26971 	return 1;
26972 }
26973 
duk_bi_duktape_object_dec(duk_context * ctx)26974 DUK_INTERNAL duk_ret_t duk_bi_duktape_object_dec(duk_context *ctx) {
26975 	duk_hthread *thr = (duk_hthread *) ctx;
26976 	duk_hstring *h_str;
26977 
26978 	DUK_UNREF(thr);
26979 
26980 	/* Vararg function: must be careful to check/require arguments.
26981 	 * The JSON helpers accept invalid indices and treat them like
26982 	 * non-existent optional parameters.
26983 	 */
26984 
26985 	h_str = duk_require_hstring(ctx, 0);
26986 	duk_require_valid_index(ctx, 1);
26987 
26988 	if (h_str == DUK_HTHREAD_STRING_HEX(thr)) {
26989 		duk_set_top(ctx, 2);
26990 		duk_hex_decode(ctx, 1);
26991 		DUK_ASSERT_TOP(ctx, 2);
26992 	} else if (h_str == DUK_HTHREAD_STRING_BASE64(thr)) {
26993 		duk_set_top(ctx, 2);
26994 		duk_base64_decode(ctx, 1);
26995 		DUK_ASSERT_TOP(ctx, 2);
26996 #ifdef DUK_USE_JX
26997 	} else if (h_str == DUK_HTHREAD_STRING_JX(thr)) {
26998 		duk_bi_json_parse_helper(ctx,
26999 		                         1 /*idx_value*/,
27000 		                         2 /*idx_replacer*/,
27001 		                         DUK_JSON_FLAG_EXT_CUSTOM /*flags*/);
27002 #endif
27003 #ifdef DUK_USE_JC
27004 	} else if (h_str == DUK_HTHREAD_STRING_JC(thr)) {
27005 		duk_bi_json_parse_helper(ctx,
27006 		                         1 /*idx_value*/,
27007 		                         2 /*idx_replacer*/,
27008 		                         DUK_JSON_FLAG_EXT_COMPATIBLE /*flags*/);
27009 #endif
27010 	} else {
27011 		return DUK_RET_TYPE_ERROR;
27012 	}
27013 	return 1;
27014 }
27015 
27016 /*
27017  *  Compact an object
27018  */
27019 
duk_bi_duktape_object_compact(duk_context * ctx)27020 DUK_INTERNAL duk_ret_t duk_bi_duktape_object_compact(duk_context *ctx) {
27021 	DUK_ASSERT_TOP(ctx, 1);
27022 	duk_compact(ctx, 0);
27023 	return 1;  /* return the argument object */
27024 }
27025 /*
27026  *  Error built-ins
27027  */
27028 
27029 /* include removed: duk_internal.h */
27030 
duk_bi_error_constructor_shared(duk_context * ctx)27031 DUK_INTERNAL duk_ret_t duk_bi_error_constructor_shared(duk_context *ctx) {
27032 	/* Behavior for constructor and non-constructor call is
27033 	 * the same except for augmenting the created error.  When
27034 	 * called as a constructor, the caller (duk_new()) will handle
27035 	 * augmentation; when called as normal function, we need to do
27036 	 * it here.
27037 	 */
27038 
27039 	duk_hthread *thr = (duk_hthread *) ctx;
27040 	duk_small_int_t bidx_prototype = duk_get_current_magic(ctx);
27041 
27042 	/* same for both error and each subclass like TypeError */
27043 	duk_uint_t flags_and_class = DUK_HOBJECT_FLAG_EXTENSIBLE |
27044 	                             DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ERROR);
27045 
27046 	DUK_UNREF(thr);
27047 
27048 	duk_push_object_helper(ctx, flags_and_class, bidx_prototype);
27049 
27050 	/* If message is undefined, the own property 'message' is not set at
27051 	 * all to save property space.  An empty message is inherited anyway.
27052 	 */
27053 	if (!duk_is_undefined(ctx, 0)) {
27054 		duk_to_string(ctx, 0);
27055 		duk_dup(ctx, 0);  /* [ message error message ] */
27056 		duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_MESSAGE, DUK_PROPDESC_FLAGS_WC);
27057 	}
27058 
27059 	/* Augment the error if called as a normal function.  __FILE__ and __LINE__
27060 	 * are not desirable in this case.
27061 	 */
27062 
27063 #ifdef DUK_USE_AUGMENT_ERROR_CREATE
27064 	if (!duk_is_constructor_call(ctx)) {
27065 		duk_err_augment_error_create(thr, thr, NULL, 0, 1 /*noblame_fileline*/);
27066 	}
27067 #endif
27068 
27069 	return 1;
27070 }
27071 
duk_bi_error_prototype_to_string(duk_context * ctx)27072 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_to_string(duk_context *ctx) {
27073 	/* XXX: optimize with more direct internal access */
27074 
27075 	duk_push_this(ctx);
27076 	(void) duk_require_hobject_or_lfunc_coerce(ctx, -1);
27077 
27078 	/* [ ... this ] */
27079 
27080 	duk_get_prop_stridx(ctx, -1, DUK_STRIDX_NAME);
27081 	if (duk_is_undefined(ctx, -1)) {
27082 		duk_pop(ctx);
27083 		duk_push_string(ctx, "Error");
27084 	} else {
27085 		duk_to_string(ctx, -1);
27086 	}
27087 
27088 	/* [ ... this name ] */
27089 
27090 	/* XXX: Are steps 6 and 7 in E5 Section 15.11.4.4 duplicated by
27091 	 * accident or are they actually needed?  The first ToString()
27092 	 * could conceivably return 'undefined'.
27093 	 */
27094 	duk_get_prop_stridx(ctx, -2, DUK_STRIDX_MESSAGE);
27095 	if (duk_is_undefined(ctx, -1)) {
27096 		duk_pop(ctx);
27097 		duk_push_string(ctx, "");
27098 	} else {
27099 		duk_to_string(ctx, -1);
27100 	}
27101 
27102 	/* [ ... this name message ] */
27103 
27104 	if (duk_get_length(ctx, -2) == 0) {
27105 		/* name is empty -> return message */
27106 		return 1;
27107 	}
27108 	if (duk_get_length(ctx, -1) == 0) {
27109 		/* message is empty -> return name */
27110 		duk_pop(ctx);
27111 		return 1;
27112 	}
27113 	duk_push_string(ctx, ": ");
27114 	duk_insert(ctx, -2);  /* ... name ': ' message */
27115 	duk_concat(ctx, 3);
27116 
27117 	return 1;
27118 }
27119 
27120 #if defined(DUK_USE_TRACEBACKS)
27121 
27122 /*
27123  *  Traceback handling
27124  *
27125  *  The unified helper decodes the traceback and produces various requested
27126  *  outputs.  It should be optimized for size, and may leave garbage on stack,
27127  *  only the topmost return value matters.  For instance, traceback separator
27128  *  and decoded strings are pushed even when looking for filename only.
27129  *
27130  *  NOTE: although _Tracedata is an internal property, user code can currently
27131  *  write to the array (or replace it with something other than an array).
27132  *  The code below must tolerate arbitrary _Tracedata.  It can throw errors
27133  *  etc, but cannot cause a segfault or memory unsafe behavior.
27134  */
27135 
27136 /* constants arbitrary, chosen for small loads */
27137 #define DUK__OUTPUT_TYPE_TRACEBACK   (-1)
27138 #define DUK__OUTPUT_TYPE_FILENAME    0
27139 #define DUK__OUTPUT_TYPE_LINENUMBER  1
27140 
duk__error_getter_helper(duk_context * ctx,duk_small_int_t output_type)27141 DUK_LOCAL duk_ret_t duk__error_getter_helper(duk_context *ctx, duk_small_int_t output_type) {
27142 	duk_hthread *thr = (duk_hthread *) ctx;
27143 	duk_idx_t idx_td;
27144 	duk_small_int_t i;  /* traceback depth fits into 16 bits */
27145 	duk_small_int_t t;  /* stack type fits into 16 bits */
27146 	duk_small_int_t count_func = 0;  /* traceback depth ensures fits into 16 bits */
27147 	const char *str_tailcall = " tailcall";
27148 	const char *str_strict = " strict";
27149 	const char *str_construct = " construct";
27150 	const char *str_prevyield = " preventsyield";
27151 	const char *str_directeval = " directeval";
27152 	const char *str_empty = "";
27153 
27154 	DUK_ASSERT_TOP(ctx, 0);  /* fixed arg count */
27155 	DUK_UNREF(thr);
27156 
27157 	duk_push_this(ctx);
27158 	duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_TRACEDATA);
27159 	idx_td = duk_get_top_index(ctx);
27160 
27161 	duk_push_hstring_stridx(ctx, DUK_STRIDX_NEWLINE_4SPACE);
27162 	duk_push_this(ctx);
27163 
27164 	/* [ ... this tracedata sep this ] */
27165 
27166 	/* XXX: skip null filename? */
27167 
27168 	if (duk_check_type(ctx, idx_td, DUK_TYPE_OBJECT)) {
27169 		/* Current tracedata contains 2 entries per callstack entry. */
27170 		for (i = 0; ; i += 2) {
27171 			duk_int_t pc;
27172 			duk_int_t line;
27173 			duk_int_t flags;
27174 			duk_double_t d;
27175 			const char *funcname;
27176 			const char *filename;
27177 			duk_hobject *h_func;
27178 			duk_hstring *h_name;
27179 
27180 			duk_require_stack(ctx, 5);
27181 			duk_get_prop_index(ctx, idx_td, i);
27182 			duk_get_prop_index(ctx, idx_td, i + 1);
27183 			d = duk_to_number(ctx, -1);
27184 			pc = (duk_int_t) DUK_FMOD(d, DUK_DOUBLE_2TO32);
27185 			flags = (duk_int_t) DUK_FLOOR(d / DUK_DOUBLE_2TO32);
27186 			t = (duk_small_int_t) duk_get_type(ctx, -2);
27187 
27188 			if (t == DUK_TYPE_OBJECT || t == DUK_TYPE_LIGHTFUNC) {
27189 				/*
27190 				 *  Ecmascript/native function call or lightfunc call
27191 				 */
27192 
27193 				count_func++;
27194 
27195 				/* [ ... v1(func) v2(pc+flags) ] */
27196 
27197 				h_func = duk_get_hobject(ctx, -2);  /* NULL for lightfunc */
27198 
27199 				duk_get_prop_stridx(ctx, -2, DUK_STRIDX_NAME);
27200 				duk_get_prop_stridx(ctx, -3, DUK_STRIDX_FILE_NAME);
27201 
27202 #if defined(DUK_USE_PC2LINE)
27203 				line = duk_hobject_pc2line_query(ctx, -4, (duk_uint_fast32_t) pc);
27204 #else
27205 				line = 0;
27206 #endif
27207 
27208 				/* [ ... v1 v2 name filename ] */
27209 
27210 				/* When looking for .fileName/.lineNumber, blame first
27211 				 * function which has a .fileName.
27212 				 */
27213 				if (duk_is_string(ctx, -1)) {
27214 					if (output_type == DUK__OUTPUT_TYPE_FILENAME) {
27215 						return 1;
27216 					} else if (output_type == DUK__OUTPUT_TYPE_LINENUMBER) {
27217 						duk_push_int(ctx, line);
27218 						return 1;
27219 					}
27220 				}
27221 
27222 				/* XXX: Change 'anon' handling here too, to use empty string for anonymous functions? */
27223 				/* XXX: Could be improved by coercing to a readable duk_tval (especially string escaping) */
27224 				h_name = duk_get_hstring(ctx, -2);  /* may be NULL */
27225 				funcname = (h_name == NULL || h_name == DUK_HTHREAD_STRING_EMPTY_STRING(thr)) ?
27226 				           "[anon]" : (const char *) DUK_HSTRING_GET_DATA(h_name);
27227 				filename = duk_get_string(ctx, -1);
27228 				filename = filename ? filename : "";
27229 				DUK_ASSERT(funcname != NULL);
27230 				DUK_ASSERT(filename != NULL);
27231 
27232 				if (h_func == NULL) {
27233 					duk_push_sprintf(ctx, "at %s light%s%s%s%s%s",
27234 					                 (const char *) funcname,
27235 					                 (const char *) ((flags & DUK_ACT_FLAG_STRICT) ? str_strict : str_empty),
27236 					                 (const char *) ((flags & DUK_ACT_FLAG_TAILCALLED) ? str_tailcall : str_empty),
27237 					                 (const char *) ((flags & DUK_ACT_FLAG_CONSTRUCT) ? str_construct : str_empty),
27238 					                 (const char *) ((flags & DUK_ACT_FLAG_DIRECT_EVAL) ? str_directeval : str_empty),
27239 					                 (const char *) ((flags & DUK_ACT_FLAG_PREVENT_YIELD) ? str_prevyield : str_empty));
27240 				} else if (DUK_HOBJECT_HAS_NATIVEFUNCTION(h_func)) {
27241 					duk_push_sprintf(ctx, "at %s (%s) native%s%s%s%s%s",
27242 					                 (const char *) funcname,
27243 					                 (const char *) filename,
27244 					                 (const char *) ((flags & DUK_ACT_FLAG_STRICT) ? str_strict : str_empty),
27245 					                 (const char *) ((flags & DUK_ACT_FLAG_TAILCALLED) ? str_tailcall : str_empty),
27246 					                 (const char *) ((flags & DUK_ACT_FLAG_CONSTRUCT) ? str_construct : str_empty),
27247 					                 (const char *) ((flags & DUK_ACT_FLAG_DIRECT_EVAL) ? str_directeval : str_empty),
27248 					                 (const char *) ((flags & DUK_ACT_FLAG_PREVENT_YIELD) ? str_prevyield : str_empty));
27249 				} else {
27250 					duk_push_sprintf(ctx, "at %s (%s:%ld)%s%s%s%s%s",
27251 					                 (const char *) funcname,
27252 					                 (const char *) filename,
27253 					                 (long) line,
27254 					                 (const char *) ((flags & DUK_ACT_FLAG_STRICT) ? str_strict : str_empty),
27255 					                 (const char *) ((flags & DUK_ACT_FLAG_TAILCALLED) ? str_tailcall : str_empty),
27256 					                 (const char *) ((flags & DUK_ACT_FLAG_CONSTRUCT) ? str_construct : str_empty),
27257 					                 (const char *) ((flags & DUK_ACT_FLAG_DIRECT_EVAL) ? str_directeval : str_empty),
27258 					                 (const char *) ((flags & DUK_ACT_FLAG_PREVENT_YIELD) ? str_prevyield : str_empty));
27259 				}
27260 				duk_replace(ctx, -5);   /* [ ... v1 v2 name filename str ] -> [ ... str v2 name filename ] */
27261 				duk_pop_n(ctx, 3);      /* -> [ ... str ] */
27262 			} else if (t == DUK_TYPE_STRING) {
27263 				/*
27264 				 *  __FILE__ / __LINE__ entry, here 'pc' is line number directly.
27265 				 *  Sometimes __FILE__ / __LINE__ is reported as the source for
27266 				 *  the error (fileName, lineNumber), sometimes not.
27267 				 */
27268 
27269 				/* [ ... v1(filename) v2(line+flags) ] */
27270 
27271 				/* When looking for .fileName/.lineNumber, blame compilation
27272 				 * or C call site unless flagged not to do so.
27273 				 */
27274 				if (!(flags & DUK_TB_FLAG_NOBLAME_FILELINE)) {
27275 					if (output_type == DUK__OUTPUT_TYPE_FILENAME) {
27276 						duk_pop(ctx);
27277 						return 1;
27278 					} else if (output_type == DUK__OUTPUT_TYPE_LINENUMBER) {
27279 						duk_push_int(ctx, pc);
27280 						return 1;
27281 					}
27282 				}
27283 
27284 				duk_push_sprintf(ctx, "at [anon] (%s:%ld) internal",
27285 				                 (const char *) duk_get_string(ctx, -2), (long) pc);
27286 				duk_replace(ctx, -3);  /* [ ... v1 v2 str ] -> [ ... str v2 ] */
27287 				duk_pop(ctx);          /* -> [ ... str ] */
27288 			} else {
27289 				/* unknown, ignore */
27290 				duk_pop_2(ctx);
27291 				break;
27292 			}
27293 		}
27294 
27295 		if (count_func >= DUK_USE_TRACEBACK_DEPTH) {
27296 			/* Possibly truncated; there is no explicit truncation
27297 			 * marker so this is the best we can do.
27298 			 */
27299 
27300 			duk_push_hstring_stridx(ctx, DUK_STRIDX_BRACKETED_ELLIPSIS);
27301 		}
27302 	}
27303 
27304 	/* [ ... this tracedata sep this str1 ... strN ] */
27305 
27306 	if (output_type != DUK__OUTPUT_TYPE_TRACEBACK) {
27307 		return 0;
27308 	} else {
27309 		/* The 'this' after 'sep' will get ToString() coerced by
27310 		 * duk_join() automatically.  We don't want to do that
27311 		 * coercion when providing .fileName or .lineNumber (GH-254).
27312 		 */
27313 		duk_join(ctx, duk_get_top(ctx) - (idx_td + 2) /*count, not including sep*/);
27314 		return 1;
27315 	}
27316 }
27317 
27318 /* XXX: Output type could be encoded into native function 'magic' value to
27319  * save space.  For setters the stridx could be encoded into 'magic'.
27320  */
27321 
duk_bi_error_prototype_stack_getter(duk_context * ctx)27322 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_stack_getter(duk_context *ctx) {
27323 	return duk__error_getter_helper(ctx, DUK__OUTPUT_TYPE_TRACEBACK);
27324 }
27325 
duk_bi_error_prototype_filename_getter(duk_context * ctx)27326 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_filename_getter(duk_context *ctx) {
27327 	return duk__error_getter_helper(ctx, DUK__OUTPUT_TYPE_FILENAME);
27328 }
27329 
duk_bi_error_prototype_linenumber_getter(duk_context * ctx)27330 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_linenumber_getter(duk_context *ctx) {
27331 	return duk__error_getter_helper(ctx, DUK__OUTPUT_TYPE_LINENUMBER);
27332 }
27333 
27334 #undef DUK__OUTPUT_TYPE_TRACEBACK
27335 #undef DUK__OUTPUT_TYPE_FILENAME
27336 #undef DUK__OUTPUT_TYPE_LINENUMBER
27337 
27338 #else  /* DUK_USE_TRACEBACKS */
27339 
27340 /*
27341  *  Traceback handling when tracebacks disabled.
27342  *
27343  *  The fileName / lineNumber stubs are now necessary because built-in
27344  *  data will include the accessor properties in Error.prototype.  If those
27345  *  are removed for builds without tracebacks, these can also be removed.
27346  *  'stack' should still be present and produce a ToString() equivalent:
27347  *  this is useful for user code which prints a stacktrace and expects to
27348  *  see something useful.  A normal stacktrace also begins with a ToString()
27349  *  of the error so this makes sense.
27350  */
27351 
duk_bi_error_prototype_stack_getter(duk_context * ctx)27352 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_stack_getter(duk_context *ctx) {
27353 	/* XXX: remove this native function and map 'stack' accessor
27354 	 * to the toString() implementation directly.
27355 	 */
27356 	return duk_bi_error_prototype_to_string(ctx);
27357 }
27358 
duk_bi_error_prototype_filename_getter(duk_context * ctx)27359 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_filename_getter(duk_context *ctx) {
27360 	DUK_UNREF(ctx);
27361 	return 0;
27362 }
27363 
duk_bi_error_prototype_linenumber_getter(duk_context * ctx)27364 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_linenumber_getter(duk_context *ctx) {
27365 	DUK_UNREF(ctx);
27366 	return 0;
27367 }
27368 
27369 #endif  /* DUK_USE_TRACEBACKS */
27370 
duk__error_setter_helper(duk_context * ctx,duk_small_uint_t stridx_key)27371 DUK_LOCAL duk_ret_t duk__error_setter_helper(duk_context *ctx, duk_small_uint_t stridx_key) {
27372 	/* Attempt to write 'stack', 'fileName', 'lineNumber' works as if
27373 	 * user code called Object.defineProperty() to create an overriding
27374 	 * own property.  This allows user code to overwrite .fileName etc
27375 	 * intuitively as e.g. "err.fileName = 'dummy'" as one might expect.
27376 	 * See https://github.com/svaarala/duktape/issues/387.
27377 	 */
27378 
27379 	DUK_ASSERT_TOP(ctx, 1);  /* fixed arg count: value */
27380 
27381 	duk_push_this(ctx);
27382 	duk_push_hstring_stridx(ctx, (duk_small_int_t) stridx_key);
27383 	duk_dup(ctx, 0);
27384 
27385 	/* [ ... obj key value ] */
27386 
27387 	DUK_DD(DUK_DDPRINT("error setter: %!T %!T %!T",
27388 	                   duk_get_tval(ctx, -3), duk_get_tval(ctx, -2), duk_get_tval(ctx, -1)));
27389 
27390 	duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_VALUE |
27391 	                      DUK_DEFPROP_HAVE_WRITABLE | DUK_DEFPROP_WRITABLE |
27392 	                      DUK_DEFPROP_HAVE_ENUMERABLE | /*not enumerable*/
27393 	                      DUK_DEFPROP_HAVE_CONFIGURABLE | DUK_DEFPROP_CONFIGURABLE);
27394 	return 0;
27395 }
27396 
duk_bi_error_prototype_stack_setter(duk_context * ctx)27397 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_stack_setter(duk_context *ctx) {
27398 	return duk__error_setter_helper(ctx, DUK_STRIDX_STACK);
27399 }
27400 
duk_bi_error_prototype_filename_setter(duk_context * ctx)27401 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_filename_setter(duk_context *ctx) {
27402 	return duk__error_setter_helper(ctx, DUK_STRIDX_FILE_NAME);
27403 }
27404 
duk_bi_error_prototype_linenumber_setter(duk_context * ctx)27405 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_linenumber_setter(duk_context *ctx) {
27406 	return duk__error_setter_helper(ctx, DUK_STRIDX_LINE_NUMBER);
27407 }
27408 /*
27409  *  Function built-ins
27410  */
27411 
27412 /* include removed: duk_internal.h */
27413 
duk_bi_function_constructor(duk_context * ctx)27414 DUK_INTERNAL duk_ret_t duk_bi_function_constructor(duk_context *ctx) {
27415 	duk_hthread *thr = (duk_hthread *) ctx;
27416 	duk_hstring *h_sourcecode;
27417 	duk_idx_t nargs;
27418 	duk_idx_t i;
27419 	duk_small_uint_t comp_flags;
27420 	duk_hcompiledfunction *func;
27421 	duk_hobject *outer_lex_env;
27422 	duk_hobject *outer_var_env;
27423 
27424 	/* normal and constructor calls have identical semantics */
27425 
27426 	nargs = duk_get_top(ctx);
27427 	for (i = 0; i < nargs; i++) {
27428 		duk_to_string(ctx, i);
27429 	}
27430 
27431 	if (nargs == 0) {
27432 		duk_push_string(ctx, "");
27433 		duk_push_string(ctx, "");
27434 	} else if (nargs == 1) {
27435 		/* XXX: cover this with the generic >1 case? */
27436 		duk_push_string(ctx, "");
27437 	} else {
27438 		duk_insert(ctx, 0);   /* [ arg1 ... argN-1 body] -> [body arg1 ... argN-1] */
27439 		duk_push_string(ctx, ",");
27440 		duk_insert(ctx, 1);
27441 		duk_join(ctx, nargs - 1);
27442 	}
27443 
27444 	/* [ body formals ], formals is comma separated list that needs to be parsed */
27445 
27446 	DUK_ASSERT_TOP(ctx, 2);
27447 
27448 	/* XXX: this placeholder is not always correct, but use for now.
27449 	 * It will fail in corner cases; see test-dev-func-cons-args.js.
27450 	 */
27451 	duk_push_string(ctx, "function(");
27452 	duk_dup(ctx, 1);
27453 	duk_push_string(ctx, "){");
27454 	duk_dup(ctx, 0);
27455 	duk_push_string(ctx, "}");
27456 	duk_concat(ctx, 5);
27457 
27458 	/* [ body formals source ] */
27459 
27460 	DUK_ASSERT_TOP(ctx, 3);
27461 
27462 	/* strictness is not inherited, intentional */
27463 	comp_flags = DUK_JS_COMPILE_FLAG_FUNCEXPR;
27464 
27465 	duk_push_hstring_stridx(ctx, DUK_STRIDX_COMPILE);  /* XXX: copy from caller? */  /* XXX: ignored now */
27466 	h_sourcecode = duk_require_hstring(ctx, -2);
27467 	duk_js_compile(thr,
27468 	               (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_sourcecode),
27469 	               (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_sourcecode),
27470 	               comp_flags);
27471 	func = (duk_hcompiledfunction *) duk_get_hobject(ctx, -1);
27472 	DUK_ASSERT(func != NULL);
27473 	DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION((duk_hobject *) func));
27474 
27475 	/* [ body formals source template ] */
27476 
27477 	/* only outer_lex_env matters, as functions always get a new
27478 	 * variable declaration environment.
27479 	 */
27480 
27481 	outer_lex_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
27482 	outer_var_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
27483 
27484 	duk_js_push_closure(thr, func, outer_var_env, outer_lex_env, 1 /*add_auto_proto*/);
27485 
27486 	/* [ body formals source template closure ] */
27487 
27488 	return 1;
27489 }
27490 
duk_bi_function_prototype(duk_context * ctx)27491 DUK_INTERNAL duk_ret_t duk_bi_function_prototype(duk_context *ctx) {
27492 	/* ignore arguments, return undefined (E5 Section 15.3.4) */
27493 	DUK_UNREF(ctx);
27494 	return 0;
27495 }
27496 
duk_bi_function_prototype_to_string(duk_context * ctx)27497 DUK_INTERNAL duk_ret_t duk_bi_function_prototype_to_string(duk_context *ctx) {
27498 	duk_tval *tv;
27499 
27500 	/*
27501 	 *  E5 Section 15.3.4.2 places few requirements on the output of
27502 	 *  this function:
27503 	 *
27504 	 *    - The result is an implementation dependent representation
27505 	 *      of the function; in particular
27506 	 *
27507 	 *    - The result must follow the syntax of a FunctionDeclaration.
27508 	 *      In particular, the function must have a name (even in the
27509 	 *      case of an anonymous function or a function with an empty
27510 	 *      name).
27511 	 *
27512 	 *    - Note in particular that the output does NOT need to compile
27513 	 *      into anything useful.
27514 	 */
27515 
27516 
27517 	/* XXX: faster internal way to get this */
27518 	duk_push_this(ctx);
27519 	tv = duk_get_tval(ctx, -1);
27520 	DUK_ASSERT(tv != NULL);
27521 
27522 	if (DUK_TVAL_IS_OBJECT(tv)) {
27523 		duk_hobject *obj = DUK_TVAL_GET_OBJECT(tv);
27524 		const char *func_name;
27525 
27526 		/* Function name: missing/undefined is mapped to empty string,
27527 		 * otherwise coerce to string.
27528 		 */
27529 		/* XXX: currently no handling for non-allowed identifier characters,
27530 		 * e.g. a '{' in the function name.
27531 		 */
27532 		duk_get_prop_stridx(ctx, -1, DUK_STRIDX_NAME);
27533 		if (duk_is_undefined(ctx, -1)) {
27534 			func_name = "";
27535 		} else {
27536 			func_name = duk_to_string(ctx, -1);
27537 			DUK_ASSERT(func_name != NULL);
27538 		}
27539 
27540 		/* Indicate function type in the function body using a dummy
27541 		 * directive.
27542 		 */
27543 		if (DUK_HOBJECT_HAS_COMPILEDFUNCTION(obj)) {
27544 			duk_push_sprintf(ctx, "function %s() {\"ecmascript\"}", (const char *) func_name);
27545 		} else if (DUK_HOBJECT_HAS_NATIVEFUNCTION(obj)) {
27546 			duk_push_sprintf(ctx, "function %s() {\"native\"}", (const char *) func_name);
27547 		} else if (DUK_HOBJECT_HAS_BOUND(obj)) {
27548 			duk_push_sprintf(ctx, "function %s() {\"bound\"}", (const char *) func_name);
27549 		} else {
27550 			goto type_error;
27551 		}
27552 	} else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
27553 		duk_push_lightfunc_tostring(ctx, tv);
27554 	} else {
27555 		goto type_error;
27556 	}
27557 
27558 	return 1;
27559 
27560  type_error:
27561 	return DUK_RET_TYPE_ERROR;
27562 }
27563 
duk_bi_function_prototype_apply(duk_context * ctx)27564 DUK_INTERNAL duk_ret_t duk_bi_function_prototype_apply(duk_context *ctx) {
27565 	duk_idx_t len;
27566 	duk_idx_t i;
27567 
27568 	DUK_ASSERT_TOP(ctx, 2);  /* not a vararg function */
27569 
27570 	duk_push_this(ctx);
27571 	if (!duk_is_callable(ctx, -1)) {
27572 		DUK_DDD(DUK_DDDPRINT("func is not callable"));
27573 		goto type_error;
27574 	}
27575 	duk_insert(ctx, 0);
27576 	DUK_ASSERT_TOP(ctx, 3);
27577 
27578 	DUK_DDD(DUK_DDDPRINT("func=%!iT, thisArg=%!iT, argArray=%!iT",
27579 	                     (duk_tval *) duk_get_tval(ctx, 0),
27580 	                     (duk_tval *) duk_get_tval(ctx, 1),
27581 	                     (duk_tval *) duk_get_tval(ctx, 2)));
27582 
27583 	/* [ func thisArg argArray ] */
27584 
27585 	if (duk_is_null_or_undefined(ctx, 2)) {
27586 		DUK_DDD(DUK_DDDPRINT("argArray is null/undefined, no args"));
27587 		len = 0;
27588 	} else if (!duk_is_object(ctx, 2)) {
27589 		goto type_error;
27590 	} else {
27591 		DUK_DDD(DUK_DDDPRINT("argArray is an object"));
27592 
27593 		/* XXX: make this an internal helper */
27594 		duk_get_prop_stridx(ctx, 2, DUK_STRIDX_LENGTH);
27595 		len = (duk_idx_t) duk_to_uint32(ctx, -1);  /* ToUint32() coercion required */
27596 		duk_pop(ctx);
27597 
27598 		duk_require_stack(ctx, len);
27599 
27600 		DUK_DDD(DUK_DDDPRINT("argArray length is %ld", (long) len));
27601 		for (i = 0; i < len; i++) {
27602 			duk_get_prop_index(ctx, 2, i);
27603 		}
27604 	}
27605 	duk_remove(ctx, 2);
27606 	DUK_ASSERT_TOP(ctx, 2 + len);
27607 
27608 	/* [ func thisArg arg1 ... argN ] */
27609 
27610 	DUK_DDD(DUK_DDDPRINT("apply, func=%!iT, thisArg=%!iT, len=%ld",
27611 	                     (duk_tval *) duk_get_tval(ctx, 0),
27612 	                     (duk_tval *) duk_get_tval(ctx, 1),
27613 	                     (long) len));
27614 	duk_call_method(ctx, len);
27615 	return 1;
27616 
27617  type_error:
27618 	return DUK_RET_TYPE_ERROR;
27619 }
27620 
duk_bi_function_prototype_call(duk_context * ctx)27621 DUK_INTERNAL duk_ret_t duk_bi_function_prototype_call(duk_context *ctx) {
27622 	duk_idx_t nargs;
27623 
27624 	/* Step 1 is not necessary because duk_call_method() will take
27625 	 * care of it.
27626 	 */
27627 
27628 	/* vararg function, thisArg needs special handling */
27629 	nargs = duk_get_top(ctx);  /* = 1 + arg count */
27630 	if (nargs == 0) {
27631 		duk_push_undefined(ctx);
27632 		nargs++;
27633 	}
27634 	DUK_ASSERT(nargs >= 1);
27635 
27636 	/* [ thisArg arg1 ... argN ] */
27637 
27638 	duk_push_this(ctx);  /* 'func' in the algorithm */
27639 	duk_insert(ctx, 0);
27640 
27641 	/* [ func thisArg arg1 ... argN ] */
27642 
27643 	DUK_DDD(DUK_DDDPRINT("func=%!iT, thisArg=%!iT, argcount=%ld, top=%ld",
27644 	                     (duk_tval *) duk_get_tval(ctx, 0),
27645 	                     (duk_tval *) duk_get_tval(ctx, 1),
27646 	                     (long) (nargs - 1),
27647 	                     (long) duk_get_top(ctx)));
27648 	duk_call_method(ctx, nargs - 1);
27649 	return 1;
27650 }
27651 
27652 /* XXX: the implementation now assumes "chained" bound functions,
27653  * whereas "collapsed" bound functions (where there is ever only
27654  * one bound function which directly points to a non-bound, final
27655  * function) would require a "collapsing" implementation which
27656  * merges argument lists etc here.
27657  */
duk_bi_function_prototype_bind(duk_context * ctx)27658 DUK_INTERNAL duk_ret_t duk_bi_function_prototype_bind(duk_context *ctx) {
27659 	duk_hobject *h_bound;
27660 	duk_hobject *h_target;
27661 	duk_idx_t nargs;
27662 	duk_idx_t i;
27663 
27664 	/* vararg function, careful arg handling (e.g. thisArg may not be present) */
27665 	nargs = duk_get_top(ctx);  /* = 1 + arg count */
27666 	if (nargs == 0) {
27667 		duk_push_undefined(ctx);
27668 		nargs++;
27669 	}
27670 	DUK_ASSERT(nargs >= 1);
27671 
27672 	duk_push_this(ctx);
27673 	if (!duk_is_callable(ctx, -1)) {
27674 		DUK_DDD(DUK_DDDPRINT("func is not callable"));
27675 		goto type_error;
27676 	}
27677 
27678 	/* [ thisArg arg1 ... argN func ]  (thisArg+args == nargs total) */
27679 	DUK_ASSERT_TOP(ctx, nargs + 1);
27680 
27681 	/* create bound function object */
27682 	duk_push_object_helper(ctx,
27683 	                       DUK_HOBJECT_FLAG_EXTENSIBLE |
27684 	                       DUK_HOBJECT_FLAG_BOUND |
27685 	                       DUK_HOBJECT_FLAG_CONSTRUCTABLE |
27686 	                       DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION),
27687 	                       DUK_BIDX_FUNCTION_PROTOTYPE);
27688 	h_bound = duk_get_hobject(ctx, -1);
27689 	DUK_ASSERT(h_bound != NULL);
27690 
27691 	/* [ thisArg arg1 ... argN func boundFunc ] */
27692 	duk_dup(ctx, -2);  /* func */
27693 	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_TARGET, DUK_PROPDESC_FLAGS_NONE);
27694 
27695 	duk_dup(ctx, 0);   /* thisArg */
27696 	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_THIS, DUK_PROPDESC_FLAGS_NONE);
27697 
27698 	duk_push_array(ctx);
27699 
27700 	/* [ thisArg arg1 ... argN func boundFunc argArray ] */
27701 
27702 	for (i = 0; i < nargs - 1; i++) {
27703 		duk_dup(ctx, 1 + i);
27704 		duk_put_prop_index(ctx, -2, i);
27705 	}
27706 	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_ARGS, DUK_PROPDESC_FLAGS_NONE);
27707 
27708 	/* [ thisArg arg1 ... argN func boundFunc ] */
27709 
27710 	/* bound function 'length' property is interesting */
27711 	h_target = duk_get_hobject(ctx, -2);
27712 	if (h_target == NULL ||  /* lightfunc */
27713 	    DUK_HOBJECT_GET_CLASS_NUMBER(h_target) == DUK_HOBJECT_CLASS_FUNCTION) {
27714 		/* For lightfuncs, simply read the virtual property. */
27715 		duk_int_t tmp;
27716 		duk_get_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH);
27717 		tmp = duk_to_int(ctx, -1) - (nargs - 1);  /* step 15.a */
27718 		duk_pop(ctx);
27719 		duk_push_int(ctx, (tmp < 0 ? 0 : tmp));
27720 	} else {
27721 		duk_push_int(ctx, 0);
27722 	}
27723 	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_NONE);  /* attrs in E5 Section 15.3.5.1 */
27724 
27725 	/* caller and arguments must use the same thrower, [[ThrowTypeError]] */
27726 	duk_xdef_prop_stridx_thrower(ctx, -1, DUK_STRIDX_CALLER, DUK_PROPDESC_FLAGS_NONE);
27727 	duk_xdef_prop_stridx_thrower(ctx, -1, DUK_STRIDX_LC_ARGUMENTS, DUK_PROPDESC_FLAGS_NONE);
27728 
27729 	/* these non-standard properties are copied for convenience */
27730 	/* XXX: 'copy properties' API call? */
27731 	duk_get_prop_stridx(ctx, -2, DUK_STRIDX_NAME);
27732 	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_WC);
27733 	duk_get_prop_stridx(ctx, -2, DUK_STRIDX_FILE_NAME);
27734 	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_FILE_NAME, DUK_PROPDESC_FLAGS_WC);
27735 
27736 	/* The 'strict' flag is copied to get the special [[Get]] of E5.1
27737 	 * Section 15.3.5.4 to apply when a 'caller' value is a strict bound
27738 	 * function.  Not sure if this is correct, because the specification
27739 	 * is a bit ambiguous on this point but it would make sense.
27740 	 */
27741 	if (h_target == NULL) {
27742 		/* Lightfuncs are always strict. */
27743 		DUK_HOBJECT_SET_STRICT(h_bound);
27744 	} else if (DUK_HOBJECT_HAS_STRICT(h_target)) {
27745 		DUK_HOBJECT_SET_STRICT(h_bound);
27746 	}
27747 	DUK_DDD(DUK_DDDPRINT("created bound function: %!iT", (duk_tval *) duk_get_tval(ctx, -1)));
27748 
27749 	return 1;
27750 
27751  type_error:
27752 	return DUK_RET_TYPE_ERROR;
27753 }
27754 /*
27755  *  Global object built-ins
27756  */
27757 
27758 /* include removed: duk_internal.h */
27759 
27760 /*
27761  *  Encoding/decoding helpers
27762  */
27763 
27764 /* XXX: Could add fast path (for each transform callback) with direct byte
27765  * lookups (no shifting) and no explicit check for x < 0x80 before table
27766  * lookup.
27767  */
27768 
27769 /* Macros for creating and checking bitmasks for character encoding.
27770  * Bit number is a bit counterintuitive, but minimizes code size.
27771  */
27772 #define DUK__MKBITS(a,b,c,d,e,f,g,h)  ((duk_uint8_t) ( \
27773 	((a) << 0) | ((b) << 1) | ((c) << 2) | ((d) << 3) | \
27774 	((e) << 4) | ((f) << 5) | ((g) << 6) | ((h) << 7) \
27775 	))
27776 #define DUK__CHECK_BITMASK(table,cp)  ((table)[(cp) >> 3] & (1 << ((cp) & 0x07)))
27777 
27778 /* E5.1 Section 15.1.3.3: uriReserved + uriUnescaped + '#' */
27779 DUK_LOCAL const duk_uint8_t duk__encode_uriunescaped_table[16] = {
27780 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x00-0x0f */
27781 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x10-0x1f */
27782 	DUK__MKBITS(0, 1, 0, 1, 1, 0, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1),  /* 0x20-0x2f */
27783 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 0, 1, 0, 1),  /* 0x30-0x3f */
27784 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1),  /* 0x40-0x4f */
27785 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 1),  /* 0x50-0x5f */
27786 	DUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1),  /* 0x60-0x6f */
27787 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 1, 0),  /* 0x70-0x7f */
27788 };
27789 
27790 /* E5.1 Section 15.1.3.4: uriUnescaped */
27791 DUK_LOCAL const duk_uint8_t duk__encode_uricomponent_unescaped_table[16] = {
27792 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x00-0x0f */
27793 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x10-0x1f */
27794 	DUK__MKBITS(0, 1, 0, 0, 0, 0, 0, 1), DUK__MKBITS(1, 1, 1, 0, 0, 1, 1, 0),  /* 0x20-0x2f */
27795 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 0, 0, 0, 0, 0, 0),  /* 0x30-0x3f */
27796 	DUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1),  /* 0x40-0x4f */
27797 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 1),  /* 0x50-0x5f */
27798 	DUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1),  /* 0x60-0x6f */
27799 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 1, 0),  /* 0x70-0x7f */
27800 };
27801 
27802 /* E5.1 Section 15.1.3.1: uriReserved + '#' */
27803 DUK_LOCAL const duk_uint8_t duk__decode_uri_reserved_table[16] = {
27804 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x00-0x0f */
27805 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x10-0x1f */
27806 	DUK__MKBITS(0, 0, 0, 1, 1, 0, 1, 0), DUK__MKBITS(0, 0, 0, 1, 1, 0, 0, 1),  /* 0x20-0x2f */
27807 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 1, 1, 0, 1, 0, 1),  /* 0x30-0x3f */
27808 	DUK__MKBITS(1, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x40-0x4f */
27809 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x50-0x5f */
27810 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x60-0x6f */
27811 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x70-0x7f */
27812 };
27813 
27814 /* E5.1 Section 15.1.3.2: empty */
27815 DUK_LOCAL const duk_uint8_t duk__decode_uri_component_reserved_table[16] = {
27816 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x00-0x0f */
27817 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x10-0x1f */
27818 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x20-0x2f */
27819 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x30-0x3f */
27820 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x40-0x4f */
27821 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x50-0x5f */
27822 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x60-0x6f */
27823 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x70-0x7f */
27824 };
27825 
27826 #ifdef DUK_USE_SECTION_B
27827 /* E5.1 Section B.2.2, step 7. */
27828 DUK_LOCAL const duk_uint8_t duk__escape_unescaped_table[16] = {
27829 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x00-0x0f */
27830 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x10-0x1f */
27831 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 1, 1, 0, 1, 1, 1),  /* 0x20-0x2f */
27832 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 0, 0, 0, 0, 0, 0),  /* 0x30-0x3f */
27833 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1),  /* 0x40-0x4f */
27834 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 1),  /* 0x50-0x5f */
27835 	DUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1),  /* 0x60-0x6f */
27836 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 0)   /* 0x70-0x7f */
27837 };
27838 #endif  /* DUK_USE_SECTION_B */
27839 
27840 #undef DUK__MKBITS
27841 
27842 typedef struct {
27843 	duk_hthread *thr;
27844 	duk_hstring *h_str;
27845 	duk_bufwriter_ctx bw;
27846 	const duk_uint8_t *p;
27847 	const duk_uint8_t *p_start;
27848 	const duk_uint8_t *p_end;
27849 } duk__transform_context;
27850 
27851 typedef void (*duk__transform_callback)(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp);
27852 
27853 /* XXX: refactor and share with other code */
duk__decode_hex_escape(const duk_uint8_t * p,duk_small_int_t n)27854 DUK_LOCAL duk_small_int_t duk__decode_hex_escape(const duk_uint8_t *p, duk_small_int_t n) {
27855 	duk_small_int_t ch;
27856 	duk_small_int_t t = 0;
27857 
27858 	while (n > 0) {
27859 		t = t * 16;
27860 		ch = (duk_small_int_t) duk_hex_dectab[*p++];
27861 		if (DUK_LIKELY(ch >= 0)) {
27862 			t += ch;
27863 		} else {
27864 			return -1;
27865 		}
27866 		n--;
27867 	}
27868 	return t;
27869 }
27870 
duk__transform_helper(duk_context * ctx,duk__transform_callback callback,const void * udata)27871 DUK_LOCAL int duk__transform_helper(duk_context *ctx, duk__transform_callback callback, const void *udata) {
27872 	duk_hthread *thr = (duk_hthread *) ctx;
27873 	duk__transform_context tfm_ctx_alloc;
27874 	duk__transform_context *tfm_ctx = &tfm_ctx_alloc;
27875 	duk_codepoint_t cp;
27876 
27877 	tfm_ctx->thr = thr;
27878 
27879 	tfm_ctx->h_str = duk_to_hstring(ctx, 0);
27880 	DUK_ASSERT(tfm_ctx->h_str != NULL);
27881 
27882 	DUK_BW_INIT_PUSHBUF(thr, &tfm_ctx->bw, DUK_HSTRING_GET_BYTELEN(tfm_ctx->h_str));  /* initial size guess */
27883 
27884 	tfm_ctx->p_start = DUK_HSTRING_GET_DATA(tfm_ctx->h_str);
27885 	tfm_ctx->p_end = tfm_ctx->p_start + DUK_HSTRING_GET_BYTELEN(tfm_ctx->h_str);
27886 	tfm_ctx->p = tfm_ctx->p_start;
27887 
27888 	while (tfm_ctx->p < tfm_ctx->p_end) {
27889 		cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &tfm_ctx->p, tfm_ctx->p_start, tfm_ctx->p_end);
27890 		callback(tfm_ctx, udata, cp);
27891 	}
27892 
27893 	DUK_BW_COMPACT(thr, &tfm_ctx->bw);
27894 
27895 	duk_to_string(ctx, -1);
27896 	return 1;
27897 }
27898 
duk__transform_callback_encode_uri(duk__transform_context * tfm_ctx,const void * udata,duk_codepoint_t cp)27899 DUK_LOCAL void duk__transform_callback_encode_uri(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp) {
27900 	duk_uint8_t xutf8_buf[DUK_UNICODE_MAX_XUTF8_LENGTH];
27901 	duk_small_int_t len;
27902 	duk_codepoint_t cp1, cp2;
27903 	duk_small_int_t i, t;
27904 	const duk_uint8_t *unescaped_table = (const duk_uint8_t *) udata;
27905 
27906 	/* UTF-8 encoded bytes escaped as %xx%xx%xx... -> 3 * nbytes.
27907 	 * Codepoint range is restricted so this is a slightly too large
27908 	 * but doesn't matter.
27909 	 */
27910 	DUK_BW_ENSURE(tfm_ctx->thr, &tfm_ctx->bw, 3 * DUK_UNICODE_MAX_XUTF8_LENGTH);
27911 
27912 	if (cp < 0) {
27913 		goto uri_error;
27914 	} else if ((cp < 0x80L) && DUK__CHECK_BITMASK(unescaped_table, cp)) {
27915 		DUK_BW_WRITE_RAW_U8(tfm_ctx->thr, &tfm_ctx->bw, (duk_uint8_t) cp);
27916 		return;
27917 	} else if (cp >= 0xdc00L && cp <= 0xdfffL) {
27918 		goto uri_error;
27919 	} else if (cp >= 0xd800L && cp <= 0xdbffL) {
27920 		/* Needs lookahead */
27921 		if (duk_unicode_decode_xutf8(tfm_ctx->thr, &tfm_ctx->p, tfm_ctx->p_start, tfm_ctx->p_end, (duk_ucodepoint_t *) &cp2) == 0) {
27922 			goto uri_error;
27923 		}
27924 		if (!(cp2 >= 0xdc00L && cp2 <= 0xdfffL)) {
27925 			goto uri_error;
27926 		}
27927 		cp1 = cp;
27928 		cp = ((cp1 - 0xd800L) << 10) + (cp2 - 0xdc00L) + 0x10000L;
27929 	} else if (cp > 0x10ffffL) {
27930 		/* Although we can allow non-BMP characters (they'll decode
27931 		 * back into surrogate pairs), we don't allow extended UTF-8
27932 		 * characters; they would encode to URIs which won't decode
27933 		 * back because of strict UTF-8 checks in URI decoding.
27934 		 * (However, we could just as well allow them here.)
27935 		 */
27936 		goto uri_error;
27937 	} else {
27938 		/* Non-BMP characters within valid UTF-8 range: encode as is.
27939 		 * They'll decode back into surrogate pairs if the escaped
27940 		 * output is decoded.
27941 		 */
27942 		;
27943 	}
27944 
27945 	len = duk_unicode_encode_xutf8((duk_ucodepoint_t) cp, xutf8_buf);
27946 	for (i = 0; i < len; i++) {
27947 		t = (int) xutf8_buf[i];
27948 		DUK_BW_WRITE_RAW_U8_3(tfm_ctx->thr,
27949 		                      &tfm_ctx->bw,
27950 		                      DUK_ASC_PERCENT,
27951 		                      (duk_uint8_t) duk_uc_nybbles[t >> 4],
27952                                       (duk_uint8_t) duk_uc_nybbles[t & 0x0f]);
27953 	}
27954 
27955 	return;
27956 
27957  uri_error:
27958 	DUK_ERROR(tfm_ctx->thr, DUK_ERR_URI_ERROR, "invalid input");
27959 }
27960 
duk__transform_callback_decode_uri(duk__transform_context * tfm_ctx,const void * udata,duk_codepoint_t cp)27961 DUK_LOCAL void duk__transform_callback_decode_uri(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp) {
27962 	const duk_uint8_t *reserved_table = (const duk_uint8_t *) udata;
27963 	duk_small_uint_t utf8_blen;
27964 	duk_codepoint_t min_cp;
27965 	duk_small_int_t t;  /* must be signed */
27966 	duk_small_uint_t i;
27967 
27968 	/* Maximum write size: XUTF8 path writes max DUK_UNICODE_MAX_XUTF8_LENGTH,
27969 	 * percent escape path writes max two times CESU-8 encoded BMP length.
27970 	 */
27971 	DUK_BW_ENSURE(tfm_ctx->thr,
27972 	              &tfm_ctx->bw,
27973 	              (DUK_UNICODE_MAX_XUTF8_LENGTH >= 2 * DUK_UNICODE_MAX_CESU8_BMP_LENGTH ?
27974 	              DUK_UNICODE_MAX_XUTF8_LENGTH : DUK_UNICODE_MAX_CESU8_BMP_LENGTH));
27975 
27976 	if (cp == (duk_codepoint_t) '%') {
27977 		const duk_uint8_t *p = tfm_ctx->p;
27978 		duk_size_t left = (duk_size_t) (tfm_ctx->p_end - p);  /* bytes left */
27979 
27980 		DUK_DDD(DUK_DDDPRINT("percent encoding, left=%ld", (long) left));
27981 
27982 		if (left < 2) {
27983 			goto uri_error;
27984 		}
27985 
27986 		t = duk__decode_hex_escape(p, 2);
27987 		DUK_DDD(DUK_DDDPRINT("first byte: %ld", (long) t));
27988 		if (t < 0) {
27989 			goto uri_error;
27990 		}
27991 
27992 		if (t < 0x80) {
27993 			if (DUK__CHECK_BITMASK(reserved_table, t)) {
27994 				/* decode '%xx' to '%xx' if decoded char in reserved set */
27995 				DUK_ASSERT(tfm_ctx->p - 1 >= tfm_ctx->p_start);
27996 				DUK_BW_WRITE_RAW_U8_3(tfm_ctx->thr,
27997 				                      &tfm_ctx->bw,
27998 				                      DUK_ASC_PERCENT,
27999 				                      p[0],
28000 				                      p[1]);
28001 			} else {
28002 				DUK_BW_WRITE_RAW_U8(tfm_ctx->thr, &tfm_ctx->bw, (duk_uint8_t) t);
28003 			}
28004 			tfm_ctx->p += 2;
28005 			return;
28006 		}
28007 
28008 		/* Decode UTF-8 codepoint from a sequence of hex escapes.  The
28009 		 * first byte of the sequence has been decoded to 't'.
28010 		 *
28011 		 * Note that UTF-8 validation must be strict according to the
28012 		 * specification: E5.1 Section 15.1.3, decode algorithm step
28013 		 * 4.d.vii.8.  URIError from non-shortest encodings is also
28014 		 * specifically noted in the spec.
28015 		 */
28016 
28017 		DUK_ASSERT(t >= 0x80);
28018 		if (t < 0xc0) {
28019 			/* continuation byte */
28020 			goto uri_error;
28021 		} else if (t < 0xe0) {
28022 			/* 110x xxxx; 2 bytes */
28023 			utf8_blen = 2;
28024 			min_cp = 0x80L;
28025 			cp = t & 0x1f;
28026 		} else if (t < 0xf0) {
28027 			/* 1110 xxxx; 3 bytes */
28028 			utf8_blen = 3;
28029 			min_cp = 0x800L;
28030 			cp = t & 0x0f;
28031 		} else if (t < 0xf8) {
28032 			/* 1111 0xxx; 4 bytes */
28033 			utf8_blen = 4;
28034 			min_cp = 0x10000L;
28035 			cp = t & 0x07;
28036 		} else {
28037 			/* extended utf-8 not allowed for URIs */
28038 			goto uri_error;
28039 		}
28040 
28041 		if (left < utf8_blen * 3 - 1) {
28042 			/* '%xx%xx...%xx', p points to char after first '%' */
28043 			goto uri_error;
28044 		}
28045 
28046 		p += 3;
28047 		for (i = 1; i < utf8_blen; i++) {
28048 			/* p points to digit part ('%xy', p points to 'x') */
28049 			t = duk__decode_hex_escape(p, 2);
28050 			DUK_DDD(DUK_DDDPRINT("i=%ld utf8_blen=%ld cp=%ld t=0x%02lx",
28051 			                     (long) i, (long) utf8_blen, (long) cp, (unsigned long) t));
28052 			if (t < 0) {
28053 				goto uri_error;
28054 			}
28055 			if ((t & 0xc0) != 0x80) {
28056 				goto uri_error;
28057 			}
28058 			cp = (cp << 6) + (t & 0x3f);
28059 			p += 3;
28060 		}
28061 		p--;  /* p overshoots */
28062 		tfm_ctx->p = p;
28063 
28064 		DUK_DDD(DUK_DDDPRINT("final cp=%ld, min_cp=%ld", (long) cp, (long) min_cp));
28065 
28066 		if (cp < min_cp || cp > 0x10ffffL || (cp >= 0xd800L && cp <= 0xdfffL)) {
28067 			goto uri_error;
28068 		}
28069 
28070 		/* The E5.1 algorithm checks whether or not a decoded codepoint
28071 		 * is below 0x80 and perhaps may be in the "reserved" set.
28072 		 * This seems pointless because the single byte UTF-8 case is
28073 		 * handled separately, and non-shortest encodings are rejected.
28074 		 * So, 'cp' cannot be below 0x80 here, and thus cannot be in
28075 		 * the reserved set.
28076 		 */
28077 
28078 		/* utf-8 validation ensures these */
28079 		DUK_ASSERT(cp >= 0x80L && cp <= 0x10ffffL);
28080 
28081 		if (cp >= 0x10000L) {
28082 			cp -= 0x10000L;
28083 			DUK_ASSERT(cp < 0x100000L);
28084 
28085 			DUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, ((cp >> 10) + 0xd800L));
28086 			DUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, ((cp & 0x03ffUL) + 0xdc00L));
28087 		} else {
28088 			DUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, cp);
28089 		}
28090 	} else {
28091 		DUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, cp);
28092 	}
28093 	return;
28094 
28095  uri_error:
28096 	DUK_ERROR(tfm_ctx->thr, DUK_ERR_URI_ERROR, "invalid input");
28097 }
28098 
28099 #ifdef DUK_USE_SECTION_B
duk__transform_callback_escape(duk__transform_context * tfm_ctx,const void * udata,duk_codepoint_t cp)28100 DUK_LOCAL void duk__transform_callback_escape(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp) {
28101 	DUK_UNREF(udata);
28102 
28103 	DUK_BW_ENSURE(tfm_ctx->thr, &tfm_ctx->bw, 6);
28104 
28105 	if (cp < 0) {
28106 		goto esc_error;
28107 	} else if ((cp < 0x80L) && DUK__CHECK_BITMASK(duk__escape_unescaped_table, cp)) {
28108 		DUK_BW_WRITE_RAW_U8(tfm_ctx->thr, &tfm_ctx->bw, (duk_uint8_t) cp);
28109 	} else if (cp < 0x100L) {
28110 		DUK_BW_WRITE_RAW_U8_3(tfm_ctx->thr,
28111 		                      &tfm_ctx->bw,
28112 		                      (duk_uint8_t) DUK_ASC_PERCENT,
28113 		                      (duk_uint8_t) duk_uc_nybbles[cp >> 4],
28114 		                      (duk_uint8_t) duk_uc_nybbles[cp & 0x0f]);
28115 	} else if (cp < 0x10000L) {
28116 		DUK_BW_WRITE_RAW_U8_6(tfm_ctx->thr,
28117 		                      &tfm_ctx->bw,
28118 		                      (duk_uint8_t) DUK_ASC_PERCENT,
28119 		                      (duk_uint8_t) DUK_ASC_LC_U,
28120 		                      (duk_uint8_t) duk_uc_nybbles[cp >> 12],
28121 		                      (duk_uint8_t) duk_uc_nybbles[(cp >> 8) & 0x0f],
28122 		                      (duk_uint8_t) duk_uc_nybbles[(cp >> 4) & 0x0f],
28123 		                      (duk_uint8_t) duk_uc_nybbles[cp & 0x0f]);
28124 	} else {
28125 		/* Characters outside BMP cannot be escape()'d.  We could
28126 		 * encode them as surrogate pairs (for codepoints inside
28127 		 * valid UTF-8 range, but not extended UTF-8).  Because
28128 		 * escape() and unescape() are legacy functions, we don't.
28129 		 */
28130 		goto esc_error;
28131 	}
28132 
28133 	return;
28134 
28135  esc_error:
28136 	DUK_ERROR_TYPE(tfm_ctx->thr, "invalid input");
28137 }
28138 
duk__transform_callback_unescape(duk__transform_context * tfm_ctx,const void * udata,duk_codepoint_t cp)28139 DUK_LOCAL void duk__transform_callback_unescape(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp) {
28140 	duk_small_int_t t;
28141 
28142 	DUK_UNREF(udata);
28143 
28144 	if (cp == (duk_codepoint_t) '%') {
28145 		const duk_uint8_t *p = tfm_ctx->p;
28146 		duk_size_t left = (duk_size_t) (tfm_ctx->p_end - p);  /* bytes left */
28147 
28148 		if (left >= 5 && p[0] == 'u' &&
28149 		    ((t = duk__decode_hex_escape(p + 1, 4)) >= 0)) {
28150 			cp = (duk_codepoint_t) t;
28151 			tfm_ctx->p += 5;
28152 		} else if (left >= 2 &&
28153 		           ((t = duk__decode_hex_escape(p, 2)) >= 0)) {
28154 			cp = (duk_codepoint_t) t;
28155 			tfm_ctx->p += 2;
28156 		}
28157 	}
28158 
28159 	DUK_BW_WRITE_ENSURE_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, cp);
28160 }
28161 #endif  /* DUK_USE_SECTION_B */
28162 
28163 /*
28164  *  Eval
28165  *
28166  *  Eval needs to handle both a "direct eval" and an "indirect eval".
28167  *  Direct eval handling needs access to the caller's activation so that its
28168  *  lexical environment can be accessed.  A direct eval is only possible from
28169  *  Ecmascript code; an indirect eval call is possible also from C code.
28170  *  When an indirect eval call is made from C code, there may not be a
28171  *  calling activation at all which needs careful handling.
28172  */
28173 
duk_bi_global_object_eval(duk_context * ctx)28174 DUK_INTERNAL duk_ret_t duk_bi_global_object_eval(duk_context *ctx) {
28175 	duk_hthread *thr = (duk_hthread *) ctx;
28176 	duk_hstring *h;
28177 	duk_activation *act_caller;
28178 	duk_activation *act_eval;
28179 	duk_activation *act;
28180 	duk_hcompiledfunction *func;
28181 	duk_hobject *outer_lex_env;
28182 	duk_hobject *outer_var_env;
28183 	duk_bool_t this_to_global = 1;
28184 	duk_small_uint_t comp_flags;
28185 	duk_int_t level = -2;
28186 
28187 	DUK_ASSERT(duk_get_top(ctx) == 1 || duk_get_top(ctx) == 2);  /* 2 when called by debugger */
28188 	DUK_ASSERT(thr->callstack_top >= 1);  /* at least this function exists */
28189 	DUK_ASSERT(((thr->callstack + thr->callstack_top - 1)->flags & DUK_ACT_FLAG_DIRECT_EVAL) == 0 || /* indirect eval */
28190 	           (thr->callstack_top >= 2));  /* if direct eval, calling activation must exist */
28191 
28192 	/*
28193 	 *  callstack_top - 1 --> this function
28194 	 *  callstack_top - 2 --> caller (may not exist)
28195 	 *
28196 	 *  If called directly from C, callstack_top might be 1.  If calling
28197 	 *  activation doesn't exist, call must be indirect.
28198 	 */
28199 
28200 	h = duk_get_hstring(ctx, 0);
28201 	if (!h) {
28202 		return 1;  /* return arg as-is */
28203 	}
28204 
28205 #if defined(DUK_USE_DEBUGGER_SUPPORT)
28206 	/* NOTE: level is used only by the debugger and should never be present
28207 	 * for an Ecmascript eval().
28208 	 */
28209 	DUK_ASSERT(level == -2);  /* by default, use caller's environment */
28210 	if (duk_get_top(ctx) >= 2 && duk_is_number(ctx, 1)) {
28211 		level = duk_get_int(ctx, 1);
28212 	}
28213 	DUK_ASSERT(level <= -2);  /* This is guaranteed by debugger code. */
28214 #endif
28215 
28216 	/* [ source ] */
28217 
28218 	comp_flags = DUK_JS_COMPILE_FLAG_EVAL;
28219 	act_eval = thr->callstack + thr->callstack_top - 1;    /* this function */
28220 	if (thr->callstack_top >= (duk_size_t) -level) {
28221 		/* Have a calling activation, check for direct eval (otherwise
28222 		 * assume indirect eval.
28223 		 */
28224 		act_caller = thr->callstack + thr->callstack_top + level;  /* caller */
28225 		if ((act_caller->flags & DUK_ACT_FLAG_STRICT) &&
28226 		    (act_eval->flags & DUK_ACT_FLAG_DIRECT_EVAL)) {
28227 			/* Only direct eval inherits strictness from calling code
28228 			 * (E5.1 Section 10.1.1).
28229 			 */
28230 			comp_flags |= DUK_JS_COMPILE_FLAG_STRICT;
28231 		}
28232 	} else {
28233 		DUK_ASSERT((act_eval->flags & DUK_ACT_FLAG_DIRECT_EVAL) == 0);
28234 	}
28235 	act_caller = NULL;  /* avoid dereference after potential callstack realloc */
28236 	act_eval = NULL;
28237 
28238 	duk_push_hstring_stridx(ctx, DUK_STRIDX_INPUT);  /* XXX: copy from caller? */
28239 	duk_js_compile(thr,
28240 	               (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h),
28241 	               (duk_size_t) DUK_HSTRING_GET_BYTELEN(h),
28242 	               comp_flags);
28243 	func = (duk_hcompiledfunction *) duk_get_hobject(ctx, -1);
28244 	DUK_ASSERT(func != NULL);
28245 	DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION((duk_hobject *) func));
28246 
28247 	/* [ source template ] */
28248 
28249 	/* E5 Section 10.4.2 */
28250 	DUK_ASSERT(thr->callstack_top >= 1);
28251 	act = thr->callstack + thr->callstack_top - 1;  /* this function */
28252 	if (act->flags & DUK_ACT_FLAG_DIRECT_EVAL) {
28253 		DUK_ASSERT(thr->callstack_top >= 2);
28254 		act = thr->callstack + thr->callstack_top + level;  /* caller */
28255 		if (act->lex_env == NULL) {
28256 			DUK_ASSERT(act->var_env == NULL);
28257 			DUK_DDD(DUK_DDDPRINT("delayed environment initialization"));
28258 
28259 			/* this may have side effects, so re-lookup act */
28260 			duk_js_init_activation_environment_records_delayed(thr, act);
28261 			act = thr->callstack + thr->callstack_top + level;
28262 		}
28263 		DUK_ASSERT(act->lex_env != NULL);
28264 		DUK_ASSERT(act->var_env != NULL);
28265 
28266 		this_to_global = 0;
28267 
28268 		if (DUK_HOBJECT_HAS_STRICT((duk_hobject *) func)) {
28269 			duk_hobject *new_env;
28270 			duk_hobject *act_lex_env;
28271 
28272 			DUK_DDD(DUK_DDDPRINT("direct eval call to a strict function -> "
28273 			                     "var_env and lex_env to a fresh env, "
28274 			                     "this_binding to caller's this_binding"));
28275 
28276 			act_lex_env = act->lex_env;
28277 			act = NULL;  /* invalidated */
28278 
28279 			(void) duk_push_object_helper_proto(ctx,
28280 			                                    DUK_HOBJECT_FLAG_EXTENSIBLE |
28281 			                                    DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV),
28282 			                                    act_lex_env);
28283 			new_env = duk_require_hobject(ctx, -1);
28284 			DUK_ASSERT(new_env != NULL);
28285 			DUK_DDD(DUK_DDDPRINT("new_env allocated: %!iO",
28286 			                     (duk_heaphdr *) new_env));
28287 
28288 			outer_lex_env = new_env;
28289 			outer_var_env = new_env;
28290 
28291 			duk_insert(ctx, 0);  /* stash to bottom of value stack to keep new_env reachable for duration of eval */
28292 
28293 			/* compiler's responsibility */
28294 			DUK_ASSERT(DUK_HOBJECT_HAS_NEWENV((duk_hobject *) func));
28295 		} else {
28296 			DUK_DDD(DUK_DDDPRINT("direct eval call to a non-strict function -> "
28297 			                     "var_env and lex_env to caller's envs, "
28298 			                     "this_binding to caller's this_binding"));
28299 
28300 			outer_lex_env = act->lex_env;
28301 			outer_var_env = act->var_env;
28302 
28303 			/* compiler's responsibility */
28304 			DUK_ASSERT(!DUK_HOBJECT_HAS_NEWENV((duk_hobject *) func));
28305 		}
28306 	} else {
28307 		DUK_DDD(DUK_DDDPRINT("indirect eval call -> var_env and lex_env to "
28308 		                     "global object, this_binding to global object"));
28309 
28310 		this_to_global = 1;
28311 		outer_lex_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
28312 		outer_var_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
28313 	}
28314 	act = NULL;
28315 
28316 	/* Eval code doesn't need an automatic .prototype object. */
28317 	duk_js_push_closure(thr, func, outer_var_env, outer_lex_env, 0 /*add_auto_proto*/);
28318 
28319 	/* [ source template closure ] */
28320 
28321 	if (this_to_global) {
28322 		DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
28323 		duk_push_hobject_bidx(ctx, DUK_BIDX_GLOBAL);
28324 	} else {
28325 		duk_tval *tv;
28326 		DUK_ASSERT(thr->callstack_top >= 2);
28327 		act = thr->callstack + thr->callstack_top + level;  /* caller */
28328 		tv = thr->valstack + act->idx_bottom - 1;  /* this is just beneath bottom */
28329 		DUK_ASSERT(tv >= thr->valstack);
28330 		duk_push_tval(ctx, tv);
28331 	}
28332 
28333 	DUK_DDD(DUK_DDDPRINT("eval -> lex_env=%!iO, var_env=%!iO, this_binding=%!T",
28334 	                     (duk_heaphdr *) outer_lex_env,
28335 	                     (duk_heaphdr *) outer_var_env,
28336 	                     duk_get_tval(ctx, -1)));
28337 
28338 	/* [ source template closure this ] */
28339 
28340 	duk_call_method(ctx, 0);
28341 
28342 	/* [ source template result ] */
28343 
28344 	return 1;
28345 }
28346 
28347 /*
28348  *  Parsing of ints and floats
28349  */
28350 
duk_bi_global_object_parse_int(duk_context * ctx)28351 DUK_INTERNAL duk_ret_t duk_bi_global_object_parse_int(duk_context *ctx) {
28352 	duk_int32_t radix;
28353 	duk_small_uint_t s2n_flags;
28354 
28355 	DUK_ASSERT_TOP(ctx, 2);
28356 	duk_to_string(ctx, 0);
28357 
28358 	radix = duk_to_int32(ctx, 1);
28359 
28360 	s2n_flags = DUK_S2N_FLAG_TRIM_WHITE |
28361 	            DUK_S2N_FLAG_ALLOW_GARBAGE |
28362 	            DUK_S2N_FLAG_ALLOW_PLUS |
28363 	            DUK_S2N_FLAG_ALLOW_MINUS |
28364 	            DUK_S2N_FLAG_ALLOW_LEADING_ZERO |
28365 	            DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT;
28366 
28367 	/* Specification stripPrefix maps to DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT.
28368 	 *
28369 	 * Don't autodetect octals (from leading zeroes), require user code to
28370 	 * provide an explicit radix 8 for parsing octal.  See write-up from Mozilla:
28371 	 * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt#ECMAScript_5_Removes_Octal_Interpretation
28372 	 */
28373 
28374 	if (radix != 0) {
28375 		if (radix < 2 || radix > 36) {
28376 			goto ret_nan;
28377 		}
28378 		if (radix != 16) {
28379 			s2n_flags &= ~DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT;
28380 		}
28381 	} else {
28382 		radix = 10;
28383 	}
28384 
28385 	duk_dup(ctx, 0);
28386 	duk_numconv_parse(ctx, radix, s2n_flags);
28387 	return 1;
28388 
28389  ret_nan:
28390 	duk_push_nan(ctx);
28391 	return 1;
28392 }
28393 
duk_bi_global_object_parse_float(duk_context * ctx)28394 DUK_INTERNAL duk_ret_t duk_bi_global_object_parse_float(duk_context *ctx) {
28395 	duk_small_uint_t s2n_flags;
28396 	duk_int32_t radix;
28397 
28398 	DUK_ASSERT_TOP(ctx, 1);
28399 	duk_to_string(ctx, 0);
28400 
28401 	radix = 10;
28402 
28403 	/* XXX: check flags */
28404 	s2n_flags = DUK_S2N_FLAG_TRIM_WHITE |
28405 	            DUK_S2N_FLAG_ALLOW_EXP |
28406 	            DUK_S2N_FLAG_ALLOW_GARBAGE |
28407 	            DUK_S2N_FLAG_ALLOW_PLUS |
28408 	            DUK_S2N_FLAG_ALLOW_MINUS |
28409 	            DUK_S2N_FLAG_ALLOW_INF |
28410 	            DUK_S2N_FLAG_ALLOW_FRAC |
28411 	            DUK_S2N_FLAG_ALLOW_NAKED_FRAC |
28412 	            DUK_S2N_FLAG_ALLOW_EMPTY_FRAC |
28413 	            DUK_S2N_FLAG_ALLOW_LEADING_ZERO;
28414 
28415 	duk_numconv_parse(ctx, radix, s2n_flags);
28416 	return 1;
28417 }
28418 
28419 /*
28420  *  Number checkers
28421  */
28422 
duk_bi_global_object_is_nan(duk_context * ctx)28423 DUK_INTERNAL duk_ret_t duk_bi_global_object_is_nan(duk_context *ctx) {
28424 	duk_double_t d = duk_to_number(ctx, 0);
28425 	duk_push_boolean(ctx, DUK_ISNAN(d));
28426 	return 1;
28427 }
28428 
duk_bi_global_object_is_finite(duk_context * ctx)28429 DUK_INTERNAL duk_ret_t duk_bi_global_object_is_finite(duk_context *ctx) {
28430 	duk_double_t d = duk_to_number(ctx, 0);
28431 	duk_push_boolean(ctx, DUK_ISFINITE(d));
28432 	return 1;
28433 }
28434 
28435 /*
28436  *  URI handling
28437  */
28438 
duk_bi_global_object_decode_uri(duk_context * ctx)28439 DUK_INTERNAL duk_ret_t duk_bi_global_object_decode_uri(duk_context *ctx) {
28440 	return duk__transform_helper(ctx, duk__transform_callback_decode_uri, (const void *) duk__decode_uri_reserved_table);
28441 }
28442 
duk_bi_global_object_decode_uri_component(duk_context * ctx)28443 DUK_INTERNAL duk_ret_t duk_bi_global_object_decode_uri_component(duk_context *ctx) {
28444 	return duk__transform_helper(ctx, duk__transform_callback_decode_uri, (const void *) duk__decode_uri_component_reserved_table);
28445 }
28446 
duk_bi_global_object_encode_uri(duk_context * ctx)28447 DUK_INTERNAL duk_ret_t duk_bi_global_object_encode_uri(duk_context *ctx) {
28448 	return duk__transform_helper(ctx, duk__transform_callback_encode_uri, (const void *) duk__encode_uriunescaped_table);
28449 }
28450 
duk_bi_global_object_encode_uri_component(duk_context * ctx)28451 DUK_INTERNAL duk_ret_t duk_bi_global_object_encode_uri_component(duk_context *ctx) {
28452 	return duk__transform_helper(ctx, duk__transform_callback_encode_uri, (const void *) duk__encode_uricomponent_unescaped_table);
28453 }
28454 
28455 #ifdef DUK_USE_SECTION_B
duk_bi_global_object_escape(duk_context * ctx)28456 DUK_INTERNAL duk_ret_t duk_bi_global_object_escape(duk_context *ctx) {
28457 	return duk__transform_helper(ctx, duk__transform_callback_escape, (const void *) NULL);
28458 }
28459 
duk_bi_global_object_unescape(duk_context * ctx)28460 DUK_INTERNAL duk_ret_t duk_bi_global_object_unescape(duk_context *ctx) {
28461 	return duk__transform_helper(ctx, duk__transform_callback_unescape, (const void *) NULL);
28462 }
28463 #else  /* DUK_USE_SECTION_B */
duk_bi_global_object_escape(duk_context * ctx)28464 DUK_INTERNAL duk_ret_t duk_bi_global_object_escape(duk_context *ctx) {
28465 	DUK_UNREF(ctx);
28466 	return DUK_RET_UNSUPPORTED_ERROR;
28467 }
28468 
duk_bi_global_object_unescape(duk_context * ctx)28469 DUK_INTERNAL duk_ret_t duk_bi_global_object_unescape(duk_context *ctx) {
28470 	DUK_UNREF(ctx);
28471 	return DUK_RET_UNSUPPORTED_ERROR;
28472 }
28473 #endif  /* DUK_USE_SECTION_B */
28474 
28475 #if defined(DUK_USE_BROWSER_LIKE) && (defined(DUK_USE_FILE_IO) || defined(DUK_USE_DEBUGGER_SUPPORT))
duk_bi_global_object_print_helper(duk_context * ctx)28476 DUK_INTERNAL duk_ret_t duk_bi_global_object_print_helper(duk_context *ctx) {
28477 	duk_hthread *thr = (duk_hthread *) ctx;
28478 	duk_int_t magic;
28479 	duk_idx_t nargs;
28480 	const duk_uint8_t *buf;
28481 	duk_size_t sz_buf;
28482 	const char nl = (const char) DUK_ASC_LF;
28483 #ifndef DUK_USE_PREFER_SIZE
28484 	duk_uint8_t buf_stack[256];
28485 #endif
28486 #ifdef DUK_USE_FILE_IO
28487 	duk_file *f_out;
28488 #endif
28489 
28490 	DUK_UNREF(thr);
28491 
28492 	magic = duk_get_current_magic(ctx);
28493 	DUK_UNREF(magic);
28494 
28495 	nargs = duk_get_top(ctx);
28496 
28497 	/* If argument count is 1 and first argument is a buffer, write the buffer
28498 	 * as raw data into the file without a newline; this allows exact control
28499 	 * over stdout/stderr without an additional entrypoint (useful for now).
28500 	 *
28501 	 * Otherwise current print/alert semantics are to ToString() coerce
28502 	 * arguments, join them with a single space, and append a newline.
28503 	 */
28504 
28505 	if (nargs == 1 && duk_is_buffer(ctx, 0)) {
28506 		buf = (const duk_uint8_t *) duk_get_buffer(ctx, 0, &sz_buf);
28507 		DUK_ASSERT(buf != NULL);
28508 	} else if (nargs > 0) {
28509 #ifdef DUK_USE_PREFER_SIZE
28510 		/* Compact but lots of churn. */
28511 		duk_push_hstring_stridx(thr, DUK_STRIDX_SPACE);
28512 		duk_insert(ctx, 0);
28513 		duk_join(ctx, nargs);
28514 		duk_push_string(thr, "\n");
28515 		duk_concat(ctx, 2);
28516 		buf = (const duk_uint8_t *) duk_get_lstring(ctx, -1, &sz_buf);
28517 		DUK_ASSERT(buf != NULL);
28518 #else  /* DUK_USE_PREFER_SIZE */
28519 		/* Higher footprint, less churn. */
28520 		duk_idx_t i;
28521 		duk_size_t sz_str;
28522 		const duk_uint8_t *p_str;
28523 		duk_uint8_t *p;
28524 
28525 		sz_buf = (duk_size_t) nargs;  /* spaces (nargs - 1) + newline */
28526 		for (i = 0; i < nargs; i++) {
28527 			(void) duk_to_lstring(ctx, i, &sz_str);
28528 			sz_buf += sz_str;
28529 		}
28530 
28531 		if (sz_buf <= sizeof(buf_stack)) {
28532 			p = (duk_uint8_t *) buf_stack;
28533 		} else {
28534 			p = (duk_uint8_t *) duk_push_fixed_buffer(ctx, sz_buf);
28535 			DUK_ASSERT(p != NULL);
28536 		}
28537 
28538 		buf = (const duk_uint8_t *) p;
28539 		for (i = 0; i < nargs; i++) {
28540 			p_str = (const duk_uint8_t *) duk_get_lstring(ctx, i, &sz_str);
28541 			DUK_ASSERT(p_str != NULL);
28542 			DUK_MEMCPY((void *) p, (const void *) p_str, sz_str);
28543 			p += sz_str;
28544 			*p++ = (duk_uint8_t) (i == nargs - 1 ? DUK_ASC_LF : DUK_ASC_SPACE);
28545 		}
28546 		DUK_ASSERT((const duk_uint8_t *) p == buf + sz_buf);
28547 #endif  /* DUK_USE_PREFER_SIZE */
28548 	} else {
28549 		buf = (const duk_uint8_t *) &nl;
28550 		sz_buf = 1;
28551 	}
28552 
28553 	/* 'buf' contains the string to write, 'sz_buf' contains the length
28554 	 * (which may be zero).
28555 	 */
28556 	DUK_ASSERT(buf != NULL);
28557 
28558 	if (sz_buf == 0) {
28559 		return 0;
28560 	}
28561 
28562 #ifdef DUK_USE_FILE_IO
28563 	f_out = (magic ? DUK_STDERR : DUK_STDOUT);
28564 	DUK_FWRITE((const void *) buf, 1, (size_t) sz_buf, f_out);
28565 	DUK_FFLUSH(f_out);
28566 #endif
28567 
28568 #if defined(DUK_USE_DEBUGGER_SUPPORT) && defined(DUK_USE_DEBUGGER_FWD_PRINTALERT)
28569 	if (DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap)) {
28570 		duk_debug_write_notify(thr, magic ? DUK_DBG_CMD_ALERT : DUK_DBG_CMD_PRINT);
28571 		duk_debug_write_string(thr, (const char *) buf, sz_buf);
28572 		duk_debug_write_eom(thr);
28573 	}
28574 #endif
28575 	return 0;
28576 }
28577 #elif defined(DUK_USE_BROWSER_LIKE)  /* print provider */
duk_bi_global_object_print_helper(duk_context * ctx)28578 DUK_INTERNAL duk_ret_t duk_bi_global_object_print_helper(duk_context *ctx) {
28579 	DUK_UNREF(ctx);
28580 	return 0;
28581 }
28582 #else  /* print provider */
duk_bi_global_object_print_helper(duk_context * ctx)28583 DUK_INTERNAL duk_ret_t duk_bi_global_object_print_helper(duk_context *ctx) {
28584 	DUK_UNREF(ctx);
28585 	return DUK_RET_UNSUPPORTED_ERROR;
28586 }
28587 #endif  /* print provider */
28588 
28589 /*
28590  *  CommonJS require() and modules support
28591  */
28592 
28593 #if defined(DUK_USE_COMMONJS_MODULES)
duk__bi_global_resolve_module_id(duk_context * ctx,const char * req_id,const char * mod_id)28594 DUK_LOCAL void duk__bi_global_resolve_module_id(duk_context *ctx, const char *req_id, const char *mod_id) {
28595 	duk_hthread *thr = (duk_hthread *) ctx;
28596 	duk_uint8_t buf[DUK_BI_COMMONJS_MODULE_ID_LIMIT];
28597 	duk_uint8_t *p;
28598 	duk_uint8_t *q;
28599 	duk_uint8_t *q_last;  /* last component */
28600 	duk_int_t int_rc;
28601 
28602 	DUK_ASSERT(req_id != NULL);
28603 	/* mod_id may be NULL */
28604 
28605 	/*
28606 	 *  A few notes on the algorithm:
28607 	 *
28608 	 *    - Terms are not allowed to begin with a period unless the term
28609 	 *      is either '.' or '..'.  This simplifies implementation (and
28610 	 *      is within CommonJS modules specification).
28611 	 *
28612 	 *    - There are few output bound checks here.  This is on purpose:
28613 	 *      the resolution input is length checked and the output is never
28614 	 *      longer than the input.  The resolved output is written directly
28615 	 *      over the input because it's never longer than the input at any
28616 	 *      point in the algorithm.
28617 	 *
28618 	 *    - Non-ASCII characters are processed as individual bytes and
28619 	 *      need no special treatment.  However, U+0000 terminates the
28620 	 *      algorithm; this is not an issue because U+0000 is not a
28621 	 *      desirable term character anyway.
28622 	 */
28623 
28624 	/*
28625 	 *  Set up the resolution input which is the requested ID directly
28626 	 *  (if absolute or no current module path) or with current module
28627 	 *  ID prepended (if relative and current module path exists).
28628 	 *
28629 	 *  Suppose current module is 'foo/bar' and relative path is './quux'.
28630 	 *  The 'bar' component must be replaced so the initial input here is
28631 	 *  'foo/bar/.././quux'.
28632 	 */
28633 
28634 	if (mod_id != NULL && req_id[0] == '.') {
28635 		int_rc = DUK_SNPRINTF((char *) buf, sizeof(buf), "%s/../%s", mod_id, req_id);
28636 	} else {
28637 		int_rc = DUK_SNPRINTF((char *) buf, sizeof(buf), "%s", req_id);
28638 	}
28639 	if (int_rc >= (duk_int_t) sizeof(buf) || int_rc < 0) {
28640 		/* Potentially truncated, NUL not guaranteed in any case.
28641 		 * The (int_rc < 0) case should not occur in practice.
28642 		 */
28643 		DUK_DD(DUK_DDPRINT("resolve error: temporary working module ID doesn't fit into resolve buffer"));
28644 		goto resolve_error;
28645 	}
28646 	DUK_ASSERT(DUK_STRLEN((const char *) buf) < sizeof(buf));  /* at most sizeof(buf) - 1 */
28647 
28648 	DUK_DDD(DUK_DDDPRINT("input module id: '%s'", (const char *) buf));
28649 
28650 	/*
28651 	 *  Resolution loop.  At the top of the loop we're expecting a valid
28652 	 *  term: '.', '..', or a non-empty identifier not starting with a period.
28653 	 */
28654 
28655 	p = buf;
28656 	q = buf;
28657 	for (;;) {
28658 		duk_uint_fast8_t c;
28659 
28660 		/* Here 'p' always points to the start of a term.
28661 		 *
28662 		 * We can also unconditionally reset q_last here: if this is
28663 		 * the last (non-empty) term q_last will have the right value
28664 		 * on loop exit.
28665 		 */
28666 
28667 		DUK_ASSERT(p >= q);  /* output is never longer than input during resolution */
28668 
28669 		DUK_DDD(DUK_DDDPRINT("resolve loop top: p -> '%s', q=%p, buf=%p",
28670 		                     (const char *) p, (void *) q, (void *) buf));
28671 
28672 		q_last = q;
28673 
28674 		c = *p++;
28675 		if (DUK_UNLIKELY(c == 0)) {
28676 			DUK_DD(DUK_DDPRINT("resolve error: requested ID must end with a non-empty term"));
28677 			goto resolve_error;
28678 		} else if (DUK_UNLIKELY(c == '.')) {
28679 			c = *p++;
28680 			if (c == '/') {
28681 				/* Term was '.' and is eaten entirely (including dup slashes). */
28682 				goto eat_dup_slashes;
28683 			}
28684 			if (c == '.' && *p == '/') {
28685 				/* Term was '..', backtrack resolved name by one component.
28686 				 *  q[-1] = previous slash (or beyond start of buffer)
28687 				 *  q[-2] = last char of previous component (or beyond start of buffer)
28688 				 */
28689 				p++;  /* eat (first) input slash */
28690 				DUK_ASSERT(q >= buf);
28691 				if (q == buf) {
28692 					DUK_DD(DUK_DDPRINT("resolve error: term was '..' but nothing to backtrack"));
28693 					goto resolve_error;
28694 				}
28695 				DUK_ASSERT(*(q - 1) == '/');
28696 				q--;  /* backtrack to last output slash (dups already eliminated) */
28697 				for (;;) {
28698 					/* Backtrack to previous slash or start of buffer. */
28699 					DUK_ASSERT(q >= buf);
28700 					if (q == buf) {
28701 						break;
28702 					}
28703 					if (*(q - 1) == '/') {
28704 						break;
28705 					}
28706 					q--;
28707 				}
28708 				goto eat_dup_slashes;
28709 			}
28710 			DUK_DD(DUK_DDPRINT("resolve error: term begins with '.' but is not '.' or '..' (not allowed now)"));
28711 			goto resolve_error;
28712 		} else if (DUK_UNLIKELY(c == '/')) {
28713 			/* e.g. require('/foo'), empty terms not allowed */
28714 			DUK_DD(DUK_DDPRINT("resolve error: empty term (not allowed now)"));
28715 			goto resolve_error;
28716 		} else {
28717 			for (;;) {
28718 				/* Copy term name until end or '/'. */
28719 				*q++ = c;
28720 				c = *p++;
28721 				if (DUK_UNLIKELY(c == 0)) {
28722 					/* This was the last term, and q_last was
28723 					 * updated to match this term at loop top.
28724 					 */
28725 					goto loop_done;
28726 				} else if (DUK_UNLIKELY(c == '/')) {
28727 					*q++ = '/';
28728 					break;
28729 				} else {
28730 					/* write on next loop */
28731 				}
28732 			}
28733 		}
28734 
28735 	 eat_dup_slashes:
28736 		for (;;) {
28737 			/* eat dup slashes */
28738 			c = *p;
28739 			if (DUK_LIKELY(c != '/')) {
28740 				break;
28741 			}
28742 			p++;
28743 		}
28744 	}
28745  loop_done:
28746 	/* Output #1: resolved absolute name */
28747 	DUK_ASSERT(q >= buf);
28748 	duk_push_lstring(ctx, (const char *) buf, (size_t) (q - buf));
28749 
28750 	/* Output #2: last component name */
28751 	DUK_ASSERT(q >= q_last);
28752 	DUK_ASSERT(q_last >= buf);
28753 	duk_push_lstring(ctx, (const char *) q_last, (size_t) (q - q_last));
28754 
28755 	DUK_DD(DUK_DDPRINT("after resolving module name: buf=%p, q_last=%p, q=%p",
28756 	                   (void *) buf, (void *) q_last, (void *) q));
28757 	return;
28758 
28759  resolve_error:
28760 	DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "cannot resolve module id: %s", (const char *) req_id);
28761 }
28762 #endif  /* DUK_USE_COMMONJS_MODULES */
28763 
28764 #if defined(DUK_USE_COMMONJS_MODULES)
28765 /* Stack indices for better readability */
28766 #define DUK__IDX_REQUESTED_ID   0  /* Module id requested */
28767 #define DUK__IDX_REQUIRE        1  /* Current require() function */
28768 #define DUK__IDX_REQUIRE_ID     2  /* The base ID of the current require() function, resolution base */
28769 #define DUK__IDX_RESOLVED_ID    3  /* Resolved, normalized absolute module ID */
28770 #define DUK__IDX_LASTCOMP       4  /* Last component name in resolved path */
28771 #define DUK__IDX_DUKTAPE        5  /* Duktape object */
28772 #define DUK__IDX_MODLOADED      6  /* Duktape.modLoaded[] module cache */
28773 #define DUK__IDX_UNDEFINED      7  /* 'undefined', artifact of lookup */
28774 #define DUK__IDX_FRESH_REQUIRE  8  /* New require() function for module, updated resolution base */
28775 #define DUK__IDX_EXPORTS        9  /* Default exports table */
28776 #define DUK__IDX_MODULE         10  /* Module object containing module.exports, etc */
28777 
duk_bi_global_object_require(duk_context * ctx)28778 DUK_INTERNAL duk_ret_t duk_bi_global_object_require(duk_context *ctx) {
28779 	const char *str_req_id;  /* requested identifier */
28780 	const char *str_mod_id;  /* require.id of current module */
28781 	duk_int_t pcall_rc;
28782 
28783 	/* NOTE: we try to minimize code size by avoiding unnecessary pops,
28784 	 * so the stack looks a bit cluttered in this function.  DUK_ASSERT_TOP()
28785 	 * assertions are used to ensure stack configuration is correct at each
28786 	 * step.
28787 	 */
28788 
28789 	/*
28790 	 *  Resolve module identifier into canonical absolute form.
28791 	 */
28792 
28793 	str_req_id = duk_require_string(ctx, DUK__IDX_REQUESTED_ID);
28794 	duk_push_current_function(ctx);
28795 	duk_get_prop_stridx(ctx, -1, DUK_STRIDX_ID);
28796 	str_mod_id = duk_get_string(ctx, DUK__IDX_REQUIRE_ID);  /* ignore non-strings */
28797 	DUK_DDD(DUK_DDDPRINT("resolve module id: requested=%!T, currentmodule=%!T",
28798 	                     duk_get_tval(ctx, DUK__IDX_REQUESTED_ID),
28799 	                     duk_get_tval(ctx, DUK__IDX_REQUIRE_ID)));
28800 	duk__bi_global_resolve_module_id(ctx, str_req_id, str_mod_id);
28801 	str_req_id = NULL;
28802 	str_mod_id = NULL;
28803 	DUK_DDD(DUK_DDDPRINT("resolved module id: requested=%!T, currentmodule=%!T, result=%!T, lastcomp=%!T",
28804 	                     duk_get_tval(ctx, DUK__IDX_REQUESTED_ID),
28805 	                     duk_get_tval(ctx, DUK__IDX_REQUIRE_ID),
28806 	                     duk_get_tval(ctx, DUK__IDX_RESOLVED_ID),
28807 	                     duk_get_tval(ctx, DUK__IDX_LASTCOMP)));
28808 
28809 	/* [ requested_id require require.id resolved_id last_comp ] */
28810 	DUK_ASSERT_TOP(ctx, DUK__IDX_LASTCOMP + 1);
28811 
28812 	/*
28813 	 *  Cached module check.
28814 	 *
28815 	 *  If module has been loaded or its loading has already begun without
28816 	 *  finishing, return the same cached value ('exports').  The value is
28817 	 *  registered when module load starts so that circular references can
28818 	 *  be supported to some extent.
28819 	 */
28820 
28821 	duk_push_hobject_bidx(ctx, DUK_BIDX_DUKTAPE);
28822 	duk_get_prop_stridx(ctx, DUK__IDX_DUKTAPE, DUK_STRIDX_MOD_LOADED);  /* Duktape.modLoaded */
28823 	(void) duk_require_hobject(ctx, DUK__IDX_MODLOADED);
28824 	DUK_ASSERT_TOP(ctx, DUK__IDX_MODLOADED + 1);
28825 
28826 	duk_dup(ctx, DUK__IDX_RESOLVED_ID);
28827 	if (duk_get_prop(ctx, DUK__IDX_MODLOADED)) {
28828 		/* [ requested_id require require.id resolved_id last_comp Duktape Duktape.modLoaded Duktape.modLoaded[id] ] */
28829 		DUK_DD(DUK_DDPRINT("module already loaded: %!T",
28830 		                   duk_get_tval(ctx, DUK__IDX_RESOLVED_ID)));
28831 		duk_get_prop_stridx(ctx, -1, DUK_STRIDX_EXPORTS);  /* return module.exports */
28832 		return 1;
28833 	}
28834 	DUK_ASSERT_TOP(ctx, DUK__IDX_UNDEFINED + 1);
28835 
28836 	/* [ requested_id require require.id resolved_id last_comp Duktape Duktape.modLoaded undefined ] */
28837 
28838 	/*
28839 	 *  Module not loaded (and loading not started previously).
28840 	 *
28841 	 *  Create a new require() function with 'id' set to resolved ID
28842 	 *  of module being loaded.  Also create 'exports' and 'module'
28843 	 *  tables but don't register exports to the loaded table yet.
28844 	 *  We don't want to do that unless the user module search callbacks
28845 	 *  succeeds in finding the module.
28846 	 */
28847 
28848 	DUK_D(DUK_DPRINT("loading module %!T, resolution base %!T, requested ID %!T -> resolved ID %!T, last component %!T",
28849                          duk_get_tval(ctx, DUK__IDX_RESOLVED_ID),
28850                          duk_get_tval(ctx, DUK__IDX_REQUIRE_ID),
28851                          duk_get_tval(ctx, DUK__IDX_REQUESTED_ID),
28852                          duk_get_tval(ctx, DUK__IDX_RESOLVED_ID),
28853                          duk_get_tval(ctx, DUK__IDX_LASTCOMP)));
28854 
28855 	/* Fresh require: require.id is left configurable (but not writable)
28856 	 * so that is not easy to accidentally tweak it, but it can still be
28857 	 * done with Object.defineProperty().
28858 	 *
28859 	 * XXX: require.id could also be just made non-configurable, as there
28860 	 * is no practical reason to touch it.
28861 	 */
28862 	duk_push_c_function(ctx, duk_bi_global_object_require, 1 /*nargs*/);
28863 	duk_push_hstring_stridx(ctx, DUK_STRIDX_REQUIRE);
28864 	duk_xdef_prop_stridx(ctx, DUK__IDX_FRESH_REQUIRE, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_NONE);
28865 	duk_dup(ctx, DUK__IDX_RESOLVED_ID);
28866 	duk_xdef_prop_stridx(ctx, DUK__IDX_FRESH_REQUIRE, DUK_STRIDX_ID, DUK_PROPDESC_FLAGS_C);  /* a fresh require() with require.id = resolved target module id */
28867 
28868 	/* Module table:
28869 	 * - module.exports: initial exports table (may be replaced by user)
28870 	 * - module.id is non-writable and non-configurable, as the CommonJS
28871 	 *   spec suggests this if possible
28872 	 * - module.filename: not set, defaults to resolved ID if not explicitly
28873 	 *   set by modSearch() (note capitalization, not .fileName, matches Node.js)
28874 	 * - module.name: not set, defaults to last component of resolved ID if
28875 	 *   not explicitly set by modSearch()
28876 	 */
28877 	duk_push_object(ctx);  /* exports */
28878 	duk_push_object(ctx);  /* module */
28879 	duk_dup(ctx, DUK__IDX_EXPORTS);
28880 	duk_xdef_prop_stridx(ctx, DUK__IDX_MODULE, DUK_STRIDX_EXPORTS, DUK_PROPDESC_FLAGS_WC);  /* module.exports = exports */
28881 	duk_dup(ctx, DUK__IDX_RESOLVED_ID);  /* resolved id: require(id) must return this same module */
28882 	duk_xdef_prop_stridx(ctx, DUK__IDX_MODULE, DUK_STRIDX_ID, DUK_PROPDESC_FLAGS_NONE);  /* module.id = resolved_id */
28883 	duk_compact(ctx, DUK__IDX_MODULE);  /* module table remains registered to modLoaded, minimize its size */
28884 	DUK_ASSERT_TOP(ctx, DUK__IDX_MODULE + 1);
28885 
28886 	DUK_DD(DUK_DDPRINT("module table created: %!T", duk_get_tval(ctx, DUK__IDX_MODULE)));
28887 
28888 	/* [ requested_id require require.id resolved_id last_comp Duktape Duktape.modLoaded undefined fresh_require exports module ] */
28889 
28890 	/* Register the module table early to modLoaded[] so that we can
28891 	 * support circular references even in modSearch().  If an error
28892 	 * is thrown, we'll delete the reference.
28893 	 */
28894 	duk_dup(ctx, DUK__IDX_RESOLVED_ID);
28895 	duk_dup(ctx, DUK__IDX_MODULE);
28896 	duk_put_prop(ctx, DUK__IDX_MODLOADED);  /* Duktape.modLoaded[resolved_id] = module */
28897 
28898 	/*
28899 	 *  Call user provided module search function and build the wrapped
28900 	 *  module source code (if necessary).  The module search function
28901 	 *  can be used to implement pure Ecmacsript, pure C, and mixed
28902 	 *  Ecmascript/C modules.
28903 	 *
28904 	 *  The module search function can operate on the exports table directly
28905 	 *  (e.g. DLL code can register values to it).  It can also return a
28906 	 *  string which is interpreted as module source code (if a non-string
28907 	 *  is returned the module is assumed to be a pure C one).  If a module
28908 	 *  cannot be found, an error must be thrown by the user callback.
28909 	 *
28910 	 *  Because Duktape.modLoaded[] already contains the module being
28911 	 *  loaded, circular references for C modules should also work
28912 	 *  (although expected to be quite rare).
28913 	 */
28914 
28915 	duk_push_string(ctx, "(function(require,exports,module){");
28916 
28917 	/* Duktape.modSearch(resolved_id, fresh_require, exports, module). */
28918 	duk_get_prop_stridx(ctx, DUK__IDX_DUKTAPE, DUK_STRIDX_MOD_SEARCH);  /* Duktape.modSearch */
28919 	duk_dup(ctx, DUK__IDX_RESOLVED_ID);
28920 	duk_dup(ctx, DUK__IDX_FRESH_REQUIRE);
28921 	duk_dup(ctx, DUK__IDX_EXPORTS);
28922 	duk_dup(ctx, DUK__IDX_MODULE);  /* [ ... Duktape.modSearch resolved_id last_comp fresh_require exports module ] */
28923 	pcall_rc = duk_pcall(ctx, 4 /*nargs*/);  /* -> [ ... source ] */
28924 	DUK_ASSERT_TOP(ctx, DUK__IDX_MODULE + 3);
28925 
28926 	if (pcall_rc != DUK_EXEC_SUCCESS) {
28927 		/* Delete entry in Duktape.modLoaded[] and rethrow. */
28928 		goto delete_rethrow;
28929 	}
28930 
28931 	/* If user callback did not return source code, module loading
28932 	 * is finished (user callback initialized exports table directly).
28933 	 */
28934 	if (!duk_is_string(ctx, -1)) {
28935 		/* User callback did not return source code, so module loading
28936 		 * is finished: just update modLoaded with final module.exports
28937 		 * and we're done.
28938 		 */
28939 		goto return_exports;
28940 	}
28941 
28942 	/* Finish the wrapped module source.  Force module.filename as the
28943 	 * function .fileName so it gets set for functions defined within a
28944 	 * module.  This also ensures loggers created within the module get
28945 	 * the module ID (or overridden filename) as their default logger name.
28946 	 * (Note capitalization: .filename matches Node.js while .fileName is
28947 	 * used elsewhere in Duktape.)
28948 	 */
28949 	duk_push_string(ctx, "\n})");  /* Newline allows module last line to contain a // comment. */
28950 	duk_concat(ctx, 3);
28951 	if (!duk_get_prop_stridx(ctx, DUK__IDX_MODULE, DUK_STRIDX_FILENAME)) {
28952 		/* module.filename for .fileName, default to resolved ID if
28953 		 * not present.
28954 		 */
28955 		duk_pop(ctx);
28956 		duk_dup(ctx, DUK__IDX_RESOLVED_ID);
28957 	}
28958 	duk_eval_raw(ctx, NULL, 0, DUK_COMPILE_EVAL);
28959 
28960 	/* Module has now evaluated to a wrapped module function.  Force its
28961 	 * .name to match module.name (defaults to last component of resolved
28962 	 * ID) so that it is shown in stack traces too.  Note that we must not
28963 	 * introduce an actual name binding into the function scope (which is
28964 	 * usually the case with a named function) because it would affect the
28965 	 * scope seen by the module and shadow accesses to globals of the same name.
28966 	 * This is now done by compiling the function as anonymous and then forcing
28967 	 * its .name without setting a "has name binding" flag.
28968 	 */
28969 
28970 	duk_push_hstring_stridx(ctx, DUK_STRIDX_NAME);
28971 	if (!duk_get_prop_stridx(ctx, DUK__IDX_MODULE, DUK_STRIDX_NAME)) {
28972 		/* module.name for .name, default to last component if
28973 		 * not present.
28974 		 */
28975 		duk_pop(ctx);
28976 		duk_dup(ctx, DUK__IDX_LASTCOMP);
28977 	}
28978 	duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_FORCE);
28979 
28980 	/*
28981 	 *  Call the wrapped module function.
28982 	 *
28983 	 *  Use a protected call so that we can update Duktape.modLoaded[resolved_id]
28984 	 *  even if the module throws an error.
28985 	 */
28986 
28987 	/* [ requested_id require require.id resolved_id last_comp Duktape Duktape.modLoaded undefined fresh_require exports module mod_func ] */
28988 	DUK_ASSERT_TOP(ctx, DUK__IDX_MODULE + 2);
28989 
28990 	duk_dup(ctx, DUK__IDX_EXPORTS);  /* exports (this binding) */
28991 	duk_dup(ctx, DUK__IDX_FRESH_REQUIRE);  /* fresh require (argument) */
28992 	duk_get_prop_stridx(ctx, DUK__IDX_MODULE, DUK_STRIDX_EXPORTS);  /* relookup exports from module.exports in case it was changed by modSearch */
28993 	duk_dup(ctx, DUK__IDX_MODULE);  /* module (argument) */
28994 	DUK_ASSERT_TOP(ctx, DUK__IDX_MODULE + 6);
28995 
28996 	/* [ requested_id require require.id resolved_id last_comp Duktape Duktape.modLoaded undefined fresh_require exports module mod_func exports fresh_require exports module ] */
28997 
28998 	pcall_rc = duk_pcall_method(ctx, 3 /*nargs*/);
28999 	if (pcall_rc != DUK_EXEC_SUCCESS) {
29000 		/* Module loading failed.  Node.js will forget the module
29001 		 * registration so that another require() will try to load
29002 		 * the module again.  Mimic that behavior.
29003 		 */
29004 		goto delete_rethrow;
29005 	}
29006 
29007 	/* [ requested_id require require.id resolved_id last_comp Duktape Duktape.modLoaded undefined fresh_require exports module result(ignored) ] */
29008 	DUK_ASSERT_TOP(ctx, DUK__IDX_MODULE + 2);
29009 
29010 	/* fall through */
29011 
29012  return_exports:
29013 	duk_get_prop_stridx(ctx, DUK__IDX_MODULE, DUK_STRIDX_EXPORTS);
29014 	duk_compact(ctx, -1);  /* compact the exports table */
29015 	return 1;  /* return module.exports */
29016 
29017  delete_rethrow:
29018 	duk_dup(ctx, DUK__IDX_RESOLVED_ID);
29019 	duk_del_prop(ctx, DUK__IDX_MODLOADED);  /* delete Duktape.modLoaded[resolved_id] */
29020 	duk_throw(ctx);  /* rethrow original error */
29021 	return 0;  /* not reachable */
29022 }
29023 
29024 #undef DUK__IDX_REQUESTED_ID
29025 #undef DUK__IDX_REQUIRE
29026 #undef DUK__IDX_REQUIRE_ID
29027 #undef DUK__IDX_RESOLVED_ID
29028 #undef DUK__IDX_LASTCOMP
29029 #undef DUK__IDX_DUKTAPE
29030 #undef DUK__IDX_MODLOADED
29031 #undef DUK__IDX_UNDEFINED
29032 #undef DUK__IDX_FRESH_REQUIRE
29033 #undef DUK__IDX_EXPORTS
29034 #undef DUK__IDX_MODULE
29035 #else
duk_bi_global_object_require(duk_context * ctx)29036 DUK_INTERNAL duk_ret_t duk_bi_global_object_require(duk_context *ctx) {
29037 	DUK_UNREF(ctx);
29038 	return DUK_RET_UNSUPPORTED_ERROR;
29039 }
29040 #endif  /* DUK_USE_COMMONJS_MODULES */
29041 /*
29042  *  JSON built-ins.
29043  *
29044  *  See doc/json.rst.
29045  *
29046  *  Codepoints are handled as duk_uint_fast32_t to ensure that the full
29047  *  unsigned 32-bit range is supported.  This matters to e.g. JX.
29048  *
29049  *  Input parsing doesn't do an explicit end-of-input check at all.  This is
29050  *  safe: input string data is always NUL-terminated (0x00) and valid JSON
29051  *  inputs never contain plain NUL characters, so that as long as syntax checks
29052  *  are correct, we'll never read past the NUL.  This approach reduces code size
29053  *  and improves parsing performance, but it's critical that syntax checks are
29054  *  indeed correct!
29055  */
29056 
29057 /* include removed: duk_internal.h */
29058 
29059 /*
29060  *  Local defines and forward declarations.
29061  */
29062 
29063 #define DUK__JSON_DECSTR_BUFSIZE 128
29064 #define DUK__JSON_DECSTR_CHUNKSIZE 64
29065 #define DUK__JSON_ENCSTR_CHUNKSIZE 64
29066 #define DUK__JSON_STRINGIFY_BUFSIZE 128
29067 #define DUK__JSON_MAX_ESC_LEN 10  /* '\Udeadbeef' */
29068 
29069 DUK_LOCAL_DECL void duk__dec_syntax_error(duk_json_dec_ctx *js_ctx);
29070 DUK_LOCAL_DECL void duk__dec_eat_white(duk_json_dec_ctx *js_ctx);
29071 DUK_LOCAL_DECL duk_uint8_t duk__dec_peek(duk_json_dec_ctx *js_ctx);
29072 DUK_LOCAL_DECL duk_uint8_t duk__dec_get(duk_json_dec_ctx *js_ctx);
29073 DUK_LOCAL_DECL duk_uint8_t duk__dec_get_nonwhite(duk_json_dec_ctx *js_ctx);
29074 DUK_LOCAL_DECL duk_uint_fast32_t duk__dec_decode_hex_escape(duk_json_dec_ctx *js_ctx, duk_small_uint_t n);
29075 DUK_LOCAL_DECL void duk__dec_req_stridx(duk_json_dec_ctx *js_ctx, duk_small_uint_t stridx);
29076 DUK_LOCAL_DECL void duk__dec_string(duk_json_dec_ctx *js_ctx);
29077 #ifdef DUK_USE_JX
29078 DUK_LOCAL_DECL void duk__dec_plain_string(duk_json_dec_ctx *js_ctx);
29079 DUK_LOCAL_DECL void duk__dec_pointer(duk_json_dec_ctx *js_ctx);
29080 DUK_LOCAL_DECL void duk__dec_buffer(duk_json_dec_ctx *js_ctx);
29081 #endif
29082 DUK_LOCAL_DECL void duk__dec_number(duk_json_dec_ctx *js_ctx);
29083 DUK_LOCAL_DECL void duk__dec_objarr_entry(duk_json_dec_ctx *js_ctx);
29084 DUK_LOCAL_DECL void duk__dec_objarr_exit(duk_json_dec_ctx *js_ctx);
29085 DUK_LOCAL_DECL void duk__dec_object(duk_json_dec_ctx *js_ctx);
29086 DUK_LOCAL_DECL void duk__dec_array(duk_json_dec_ctx *js_ctx);
29087 DUK_LOCAL_DECL void duk__dec_value(duk_json_dec_ctx *js_ctx);
29088 DUK_LOCAL_DECL void duk__dec_reviver_walk(duk_json_dec_ctx *js_ctx);
29089 
29090 DUK_LOCAL_DECL void duk__emit_1(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch);
29091 DUK_LOCAL_DECL void duk__emit_2(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch1, duk_uint_fast8_t ch2);
29092 DUK_LOCAL_DECL void duk__unemit_1(duk_json_enc_ctx *js_ctx);
29093 DUK_LOCAL_DECL void duk__emit_hstring(duk_json_enc_ctx *js_ctx, duk_hstring *h);
29094 #if defined(DUK_USE_FASTINT)
29095 DUK_LOCAL_DECL void duk__emit_cstring(duk_json_enc_ctx *js_ctx, const char *p);
29096 #endif
29097 DUK_LOCAL_DECL void duk__emit_stridx(duk_json_enc_ctx *js_ctx, duk_small_uint_t stridx);
29098 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);
29099 DUK_LOCAL_DECL void duk__enc_key_autoquote(duk_json_enc_ctx *js_ctx, duk_hstring *k);
29100 DUK_LOCAL_DECL void duk__enc_quote_string(duk_json_enc_ctx *js_ctx, duk_hstring *h_str);
29101 DUK_LOCAL_DECL void duk__enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top);
29102 DUK_LOCAL_DECL void duk__enc_objarr_exit(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top);
29103 DUK_LOCAL_DECL void duk__enc_object(duk_json_enc_ctx *js_ctx);
29104 DUK_LOCAL_DECL void duk__enc_array(duk_json_enc_ctx *js_ctx);
29105 DUK_LOCAL_DECL duk_bool_t duk__enc_value(duk_json_enc_ctx *js_ctx, duk_idx_t idx_holder);
29106 DUK_LOCAL_DECL duk_bool_t duk__enc_allow_into_proplist(duk_tval *tv);
29107 DUK_LOCAL_DECL void duk__enc_double(duk_json_enc_ctx *js_ctx);
29108 #if defined(DUK_USE_FASTINT)
29109 DUK_LOCAL_DECL void duk__enc_fastint_tval(duk_json_enc_ctx *js_ctx, duk_tval *tv);
29110 #endif
29111 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
29112 DUK_LOCAL_DECL void duk__enc_buffer(duk_json_enc_ctx *js_ctx, duk_hbuffer *h);
29113 DUK_LOCAL_DECL void duk__enc_pointer(duk_json_enc_ctx *js_ctx, void *ptr);
29114 DUK_LOCAL_DECL void duk__enc_bufferobject(duk_json_enc_ctx *js_ctx, duk_hbufferobject *h_bufobj);
29115 #endif
29116 DUK_LOCAL_DECL void duk__enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_int_t depth);
29117 
29118 /*
29119  *  Helper tables
29120  */
29121 
29122 #if defined(DUK_USE_JSON_QUOTESTRING_FASTPATH)
29123 DUK_LOCAL const duk_uint8_t duk__json_quotestr_lookup[256] = {
29124 	/* 0x00 ... 0x7f: as is
29125 	 * 0x80: escape generically
29126 	 * 0x81: slow path
29127 	 * 0xa0 ... 0xff: backslash + one char
29128 	 */
29129 
29130 	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xe2, 0xf4, 0xee, 0x80, 0xe6, 0xf2, 0x80, 0x80,
29131 	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
29132 	0x20, 0x21, 0xa2, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
29133 	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
29134 	0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
29135 	0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0xdc, 0x5d, 0x5e, 0x5f,
29136 	0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
29137 	0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x81,
29138 	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
29139 	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
29140 	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
29141 	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
29142 	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
29143 	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
29144 	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
29145 	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81
29146 };
29147 #else  /* DUK_USE_JSON_QUOTESTRING_FASTPATH */
29148 DUK_LOCAL const duk_uint8_t duk__json_quotestr_esc[14] = {
29149 	DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL,
29150 	DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL,
29151 	DUK_ASC_LC_B, DUK_ASC_LC_T, DUK_ASC_LC_N, DUK_ASC_NUL,
29152 	DUK_ASC_LC_F, DUK_ASC_LC_R
29153 };
29154 #endif  /* DUK_USE_JSON_QUOTESTRING_FASTPATH */
29155 
29156 #if defined(DUK_USE_JSON_DECSTRING_FASTPATH)
29157 DUK_LOCAL const duk_uint8_t duk__json_decstr_lookup[256] = {
29158 	/* 0x00: slow path
29159 	 * other: as is
29160 	 */
29161 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29162 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29163 	0x20, 0x21, 0x00, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
29164 	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
29165 	0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
29166 	0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x00, 0x5d, 0x5e, 0x5f,
29167 	0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
29168 	0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
29169 	0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
29170 	0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
29171 	0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
29172 	0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
29173 	0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
29174 	0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
29175 	0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
29176 	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
29177 };
29178 #endif  /* DUK_USE_JSON_DECSTRING_FASTPATH */
29179 
29180 #if defined(DUK_USE_JSON_EATWHITE_FASTPATH)
29181 DUK_LOCAL const duk_uint8_t duk__json_eatwhite_lookup[256] = {
29182 	/* 0x00: finish (non-white)
29183 	 * 0x01: continue
29184 	 */
29185 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00,
29186 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29187 	0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29188 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29189 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29190 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29191 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29192 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29193 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29194 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29195 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29196 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29197 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29198 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29199 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29200 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
29201 };
29202 #endif  /* DUK_USE_JSON_EATWHITE_FASTPATH */
29203 
29204 #if defined(DUK_USE_JSON_DECNUMBER_FASTPATH)
29205 DUK_LOCAL const duk_uint8_t duk__json_decnumber_lookup[256] = {
29206 	/* 0x00: finish (not part of number)
29207 	 * 0x01: continue
29208 	 */
29209 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29210 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29211 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00,
29212 	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29213 	0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29214 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29215 	0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29216 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29217 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29218 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29219 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29220 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29221 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29222 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29223 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29224 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
29225 };
29226 #endif  /* DUK_USE_JSON_DECNUMBER_FASTPATH */
29227 
29228 /*
29229  *  Parsing implementation.
29230  *
29231  *  JSON lexer is now separate from duk_lexer.c because there are numerous
29232  *  small differences making it difficult to share the lexer.
29233  *
29234  *  The parser here works with raw bytes directly; this works because all
29235  *  JSON delimiters are ASCII characters.  Invalid xUTF-8 encoded values
29236  *  inside strings will be passed on without normalization; this is not a
29237  *  compliance concern because compliant inputs will always be valid
29238  *  CESU-8 encodings.
29239  */
29240 
duk__dec_syntax_error(duk_json_dec_ctx * js_ctx)29241 DUK_LOCAL void duk__dec_syntax_error(duk_json_dec_ctx *js_ctx) {
29242 	/* Shared handler to minimize parser size.  Cause will be
29243 	 * hidden, unfortunately, but we'll have an offset which
29244 	 * is often quite enough.
29245 	 */
29246 	DUK_ERROR_FMT1(js_ctx->thr, DUK_ERR_SYNTAX_ERROR, DUK_STR_FMT_INVALID_JSON,
29247 	               (long) (js_ctx->p - js_ctx->p_start));
29248 }
29249 
duk__dec_eat_white(duk_json_dec_ctx * js_ctx)29250 DUK_LOCAL void duk__dec_eat_white(duk_json_dec_ctx *js_ctx) {
29251 	const duk_uint8_t *p;
29252 	duk_uint8_t t;
29253 
29254 	p = js_ctx->p;
29255 	for (;;) {
29256 		DUK_ASSERT(p <= js_ctx->p_end);
29257 		t = *p;
29258 
29259 #if defined(DUK_USE_JSON_EATWHITE_FASTPATH)
29260 		/* This fast path is pretty marginal in practice.
29261 		 * XXX: candidate for removal.
29262 		 */
29263 		DUK_ASSERT(duk__json_eatwhite_lookup[0x00] == 0x00);  /* end-of-input breaks */
29264 		if (duk__json_eatwhite_lookup[t] == 0) {
29265 			break;
29266 		}
29267 #else  /* DUK_USE_JSON_EATWHITE_FASTPATH */
29268 		if (!(t == 0x20 || t == 0x0a || t == 0x0d || t == 0x09)) {
29269 			/* NUL also comes here.  Comparison order matters, 0x20
29270 			 * is most common whitespace.
29271 			 */
29272 			break;
29273 		}
29274 #endif  /* DUK_USE_JSON_EATWHITE_FASTPATH */
29275 		p++;
29276 	}
29277 	js_ctx->p = p;
29278 }
29279 
duk__dec_peek(duk_json_dec_ctx * js_ctx)29280 DUK_LOCAL duk_uint8_t duk__dec_peek(duk_json_dec_ctx *js_ctx) {
29281 	DUK_ASSERT(js_ctx->p <= js_ctx->p_end);
29282 	return *js_ctx->p;
29283 }
29284 
duk__dec_get(duk_json_dec_ctx * js_ctx)29285 DUK_LOCAL duk_uint8_t duk__dec_get(duk_json_dec_ctx *js_ctx) {
29286 	DUK_ASSERT(js_ctx->p <= js_ctx->p_end);
29287 	return *js_ctx->p++;
29288 }
29289 
duk__dec_get_nonwhite(duk_json_dec_ctx * js_ctx)29290 DUK_LOCAL duk_uint8_t duk__dec_get_nonwhite(duk_json_dec_ctx *js_ctx) {
29291 	duk__dec_eat_white(js_ctx);
29292 	return duk__dec_get(js_ctx);
29293 }
29294 
29295 /* 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)29296 DUK_LOCAL duk_uint_fast32_t duk__dec_decode_hex_escape(duk_json_dec_ctx *js_ctx, duk_small_uint_t n) {
29297 	duk_small_uint_t i;
29298 	duk_uint_fast32_t res = 0;
29299 	duk_uint8_t x;
29300 	duk_small_int_t t;
29301 
29302 	for (i = 0; i < n; i++) {
29303 		/* XXX: share helper from lexer; duk_lexer.c / hexval(). */
29304 
29305 		x = duk__dec_get(js_ctx);
29306 		DUK_DDD(DUK_DDDPRINT("decode_hex_escape: i=%ld, n=%ld, res=%ld, x=%ld",
29307 		                     (long) i, (long) n, (long) res, (long) x));
29308 
29309 		/* x == 0x00 (EOF) causes syntax_error */
29310 		DUK_ASSERT(duk_hex_dectab[0] == -1);
29311 		t = duk_hex_dectab[x & 0xff];
29312 		if (DUK_LIKELY(t >= 0)) {
29313 			res = (res * 16) + t;
29314 		} else {
29315 			/* catches EOF and invalid digits */
29316 			goto syntax_error;
29317 		}
29318 	}
29319 
29320 	DUK_DDD(DUK_DDDPRINT("final hex decoded value: %ld", (long) res));
29321 	return res;
29322 
29323  syntax_error:
29324 	duk__dec_syntax_error(js_ctx);
29325 	DUK_UNREACHABLE();
29326 	return 0;
29327 }
29328 
duk__dec_req_stridx(duk_json_dec_ctx * js_ctx,duk_small_uint_t stridx)29329 DUK_LOCAL void duk__dec_req_stridx(duk_json_dec_ctx *js_ctx, duk_small_uint_t stridx) {
29330 	duk_hstring *h;
29331 	const duk_uint8_t *p;
29332 	duk_uint8_t x, y;
29333 
29334 	/* First character has already been eaten and checked by the caller.
29335 	 * We can scan until a NUL in stridx string because no built-in strings
29336 	 * have internal NULs.
29337 	 */
29338 
29339 	DUK_ASSERT_DISABLE(stridx >= 0);  /* unsigned */
29340 	DUK_ASSERT(stridx < DUK_HEAP_NUM_STRINGS);
29341 	h = DUK_HTHREAD_GET_STRING(js_ctx->thr, stridx);
29342 	DUK_ASSERT(h != NULL);
29343 
29344 	p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h) + 1;
29345 	DUK_ASSERT(*(js_ctx->p - 1) == *(p - 1));  /* first character has been matched */
29346 
29347 	for (;;) {
29348 		x = *p;
29349 		if (x == 0) {
29350 			break;
29351 		}
29352 		y = duk__dec_get(js_ctx);
29353 		if (x != y) {
29354 			/* Catches EOF of JSON input. */
29355 			goto syntax_error;
29356 		}
29357 		p++;
29358 	}
29359 
29360 	return;
29361 
29362  syntax_error:
29363 	duk__dec_syntax_error(js_ctx);
29364 	DUK_UNREACHABLE();
29365 }
29366 
duk__dec_string_escape(duk_json_dec_ctx * js_ctx,duk_uint8_t ** ext_p)29367 DUK_LOCAL duk_small_int_t duk__dec_string_escape(duk_json_dec_ctx *js_ctx, duk_uint8_t **ext_p) {
29368 	duk_uint_fast32_t cp;
29369 
29370 	/* EOF (-1) will be cast to an unsigned value first
29371 	 * and then re-cast for the switch.  In any case, it
29372 	 * will match the default case (syntax error).
29373 	 */
29374 	cp = (duk_uint_fast32_t) duk__dec_get(js_ctx);
29375 	switch ((int) cp) {
29376 	case DUK_ASC_BACKSLASH: break;
29377 	case DUK_ASC_DOUBLEQUOTE: break;
29378 	case DUK_ASC_SLASH: break;
29379 	case DUK_ASC_LC_T: cp = 0x09; break;
29380 	case DUK_ASC_LC_N: cp = 0x0a; break;
29381 	case DUK_ASC_LC_R: cp = 0x0d; break;
29382 	case DUK_ASC_LC_F: cp = 0x0c; break;
29383 	case DUK_ASC_LC_B: cp = 0x08; break;
29384 	case DUK_ASC_LC_U: {
29385 		cp = duk__dec_decode_hex_escape(js_ctx, 4);
29386 		break;
29387 	}
29388 #ifdef DUK_USE_JX
29389 	case DUK_ASC_UC_U: {
29390 		if (js_ctx->flag_ext_custom) {
29391 			cp = duk__dec_decode_hex_escape(js_ctx, 8);
29392 		} else {
29393 			return 1;  /* syntax error */
29394 		}
29395 		break;
29396 	}
29397 	case DUK_ASC_LC_X: {
29398 		if (js_ctx->flag_ext_custom) {
29399 			cp = duk__dec_decode_hex_escape(js_ctx, 2);
29400 		} else {
29401 			return 1;  /* syntax error */
29402 		}
29403 		break;
29404 	}
29405 #endif  /* DUK_USE_JX */
29406 	default:
29407 		/* catches EOF (0x00) */
29408 		return 1;  /* syntax error */
29409 	}
29410 
29411 	DUK_RAW_WRITE_XUTF8(*ext_p, cp);
29412 
29413 	return 0;
29414 }
29415 
duk__dec_string(duk_json_dec_ctx * js_ctx)29416 DUK_LOCAL void duk__dec_string(duk_json_dec_ctx *js_ctx) {
29417 	duk_hthread *thr = js_ctx->thr;
29418 	duk_context *ctx = (duk_context *) thr;
29419 	duk_bufwriter_ctx bw_alloc;
29420 	duk_bufwriter_ctx *bw;
29421 	duk_uint8_t *q;
29422 
29423 	/* '"' was eaten by caller */
29424 
29425 	/* Note that we currently parse -bytes-, not codepoints.
29426 	 * All non-ASCII extended UTF-8 will encode to bytes >= 0x80,
29427 	 * so they'll simply pass through (valid UTF-8 or not).
29428 	 */
29429 
29430 	bw = &bw_alloc;
29431 	DUK_BW_INIT_PUSHBUF(js_ctx->thr, bw, DUK__JSON_DECSTR_BUFSIZE);
29432 	q = DUK_BW_GET_PTR(js_ctx->thr, bw);
29433 
29434 #if defined(DUK_USE_JSON_DECSTRING_FASTPATH)
29435 	for (;;) {
29436 		duk_small_uint_t safe;
29437 		duk_uint8_t b, x;
29438 		const duk_uint8_t *p;
29439 
29440 		/* Select a safe loop count where no output checks are
29441 		 * needed assuming we won't encounter escapes.  Input
29442 		 * bound checks are not necessary as a NUL (guaranteed)
29443 		 * will cause a SyntaxError before we read out of bounds.
29444 		 */
29445 
29446 		safe = DUK__JSON_DECSTR_CHUNKSIZE;
29447 
29448 		/* Ensure space for 1:1 output plus one escape. */
29449 		q = DUK_BW_ENSURE_RAW(js_ctx->thr, bw, safe + DUK_UNICODE_MAX_XUTF8_LENGTH, q);
29450 
29451 		p = js_ctx->p;  /* temp copy, write back for next loop */
29452 		for (;;) {
29453 			if (safe == 0) {
29454 				js_ctx->p = p;
29455 				break;
29456 			}
29457 			safe--;
29458 
29459 			/* End of input (NUL) goes through slow path and causes SyntaxError. */
29460 			DUK_ASSERT(duk__json_decstr_lookup[0] == 0x00);
29461 
29462 			b = *p++;
29463 			x = (duk_small_int_t) duk__json_decstr_lookup[b];
29464 			if (DUK_LIKELY(x != 0)) {
29465 				/* Fast path, decode as is. */
29466 				*q++ = b;
29467 			} else if (b == DUK_ASC_DOUBLEQUOTE) {
29468 				js_ctx->p = p;
29469 				goto found_quote;
29470 			} else if (b == DUK_ASC_BACKSLASH) {
29471 				/* We've ensured space for one escaped input; then
29472 				 * bail out and recheck (this makes escape handling
29473 				 * quite slow but it's uncommon).
29474 				 */
29475 				js_ctx->p = p;
29476 				if (duk__dec_string_escape(js_ctx, &q) != 0) {
29477 					goto syntax_error;
29478 				}
29479 				break;
29480 			} else {
29481 				js_ctx->p = p;
29482 				goto syntax_error;
29483 			}
29484 		}
29485 	}
29486  found_quote:
29487 #else  /* DUK_USE_JSON_DECSTRING_FASTPATH */
29488 	for (;;) {
29489 		duk_uint8_t x;
29490 
29491 		q = DUK_BW_ENSURE_RAW(js_ctx->thr, bw, DUK_UNICODE_MAX_XUTF8_LENGTH, q);
29492 
29493 		x = duk__dec_get(js_ctx);
29494 
29495 		if (x == DUK_ASC_DOUBLEQUOTE) {
29496 			break;
29497 		} else if (x == DUK_ASC_BACKSLASH) {
29498 			if (duk__dec_string_escape(js_ctx, &q) != 0) {
29499 				goto syntax_error;
29500 			}
29501 		} else if (x < 0x20) {
29502 			/* catches EOF (NUL) */
29503 			goto syntax_error;
29504 		} else {
29505 			*q++ = (duk_uint8_t) x;
29506 		}
29507 	}
29508 #endif  /* DUK_USE_JSON_DECSTRING_FASTPATH */
29509 
29510 	DUK_BW_SETPTR_AND_COMPACT(js_ctx->thr, bw, q);
29511 	duk_to_string(ctx, -1);
29512 
29513 	/* [ ... str ] */
29514 
29515 	return;
29516 
29517  syntax_error:
29518 	duk__dec_syntax_error(js_ctx);
29519 	DUK_UNREACHABLE();
29520 }
29521 
29522 #ifdef DUK_USE_JX
29523 /* Decode a plain string consisting entirely of identifier characters.
29524  * Used to parse plain keys (e.g. "foo: 123").
29525  */
duk__dec_plain_string(duk_json_dec_ctx * js_ctx)29526 DUK_LOCAL void duk__dec_plain_string(duk_json_dec_ctx *js_ctx) {
29527 	duk_hthread *thr = js_ctx->thr;
29528 	duk_context *ctx = (duk_context *) thr;
29529 	const duk_uint8_t *p;
29530 	duk_small_int_t x;
29531 
29532 	/* Caller has already eaten the first char so backtrack one byte. */
29533 
29534 	js_ctx->p--;  /* safe */
29535 	p = js_ctx->p;
29536 
29537 	/* Here again we parse bytes, and non-ASCII UTF-8 will cause end of
29538 	 * parsing (which is correct except if there are non-shortest encodings).
29539 	 * There is also no need to check explicitly for end of input buffer as
29540 	 * the input is NUL padded and NUL will exit the parsing loop.
29541 	 *
29542 	 * Because no unescaping takes place, we can just scan to the end of the
29543 	 * plain string and intern from the input buffer.
29544 	 */
29545 
29546 	for (;;) {
29547 		x = *p;
29548 
29549 		/* There is no need to check the first character specially here
29550 		 * (i.e. reject digits): the caller only accepts valid initial
29551 		 * characters and won't call us if the first character is a digit.
29552 		 * This also ensures that the plain string won't be empty.
29553 		 */
29554 
29555 		if (!duk_unicode_is_identifier_part((duk_codepoint_t) x)) {
29556 			break;
29557 		}
29558 		p++;
29559 	}
29560 
29561 	duk_push_lstring(ctx, (const char *) js_ctx->p, (duk_size_t) (p - js_ctx->p));
29562 	js_ctx->p = p;
29563 
29564 	/* [ ... str ] */
29565 }
29566 #endif  /* DUK_USE_JX */
29567 
29568 #ifdef DUK_USE_JX
duk__dec_pointer(duk_json_dec_ctx * js_ctx)29569 DUK_LOCAL void duk__dec_pointer(duk_json_dec_ctx *js_ctx) {
29570 	duk_hthread *thr = js_ctx->thr;
29571 	duk_context *ctx = (duk_context *) thr;
29572 	const duk_uint8_t *p;
29573 	duk_small_int_t x;
29574 	void *voidptr;
29575 
29576 	/* Caller has already eaten the first character ('(') which we don't need. */
29577 
29578 	p = js_ctx->p;
29579 
29580 	for (;;) {
29581 		x = *p;
29582 
29583 		/* Assume that the native representation never contains a closing
29584 		 * parenthesis.
29585 		 */
29586 
29587 		if (x == DUK_ASC_RPAREN) {
29588 			break;
29589 		} else if (x <= 0) {
29590 			/* NUL term or -1 (EOF), NUL check would suffice */
29591 			goto syntax_error;
29592 		}
29593 		p++;
29594 	}
29595 
29596 	/* There is no need to NUL delimit the sscanf() call: trailing garbage is
29597 	 * ignored and there is always a NUL terminator which will force an error
29598 	 * if no error is encountered before it.  It's possible that the scan
29599 	 * would scan further than between [js_ctx->p,p[ though and we'd advance
29600 	 * by less than the scanned value.
29601 	 *
29602 	 * Because pointers are platform specific, a failure to scan a pointer
29603 	 * results in a null pointer which is a better placeholder than a missing
29604 	 * value or an error.
29605 	 */
29606 
29607 	voidptr = NULL;
29608 	(void) DUK_SSCANF((const char *) js_ctx->p, DUK_STR_FMT_PTR, &voidptr);
29609 	duk_push_pointer(ctx, voidptr);
29610 	js_ctx->p = p + 1;  /* skip ')' */
29611 
29612 	/* [ ... ptr ] */
29613 
29614 	return;
29615 
29616  syntax_error:
29617 	duk__dec_syntax_error(js_ctx);
29618 	DUK_UNREACHABLE();
29619 }
29620 #endif  /* DUK_USE_JX */
29621 
29622 #ifdef DUK_USE_JX
duk__dec_buffer(duk_json_dec_ctx * js_ctx)29623 DUK_LOCAL void duk__dec_buffer(duk_json_dec_ctx *js_ctx) {
29624 	duk_hthread *thr = js_ctx->thr;
29625 	duk_context *ctx = (duk_context *) thr;
29626 	const duk_uint8_t *p;
29627 	duk_uint8_t *buf;
29628 	duk_size_t src_len;
29629 	duk_small_int_t x;
29630 
29631 	/* Caller has already eaten the first character ('|') which we don't need. */
29632 
29633 	p = js_ctx->p;
29634 
29635 	/* XXX: Would be nice to share the fast path loop from duk_hex_decode()
29636 	 * and avoid creating a temporary buffer.  However, there are some
29637 	 * differences which prevent trivial sharing:
29638 	 *
29639 	 *   - Pipe char detection
29640 	 *   - EOF detection
29641 	 *   - Unknown length of input and output
29642 	 *
29643 	 * The best approach here would be a bufwriter and a reasonaly sized
29644 	 * safe inner loop (e.g. 64 output bytes at a time).
29645 	 */
29646 
29647 	for (;;) {
29648 		x = *p;
29649 
29650 		/* This loop intentionally does not ensure characters are valid
29651 		 * ([0-9a-fA-F]) because the hex decode call below will do that.
29652 		 */
29653 		if (x == DUK_ASC_PIPE) {
29654 			break;
29655 		} else if (x <= 0) {
29656 			/* NUL term or -1 (EOF), NUL check would suffice */
29657 			goto syntax_error;
29658 		}
29659 		p++;
29660 	}
29661 
29662 	src_len = (duk_size_t) (p - js_ctx->p);
29663 	buf = (duk_uint8_t *) duk_push_fixed_buffer(ctx, src_len);
29664 	DUK_ASSERT(buf != NULL);
29665 	DUK_MEMCPY((void *) buf, (const void *) js_ctx->p, src_len);
29666 	duk_hex_decode(ctx, -1);
29667 
29668 	js_ctx->p = p + 1;  /* skip '|' */
29669 
29670 	/* [ ... buf ] */
29671 
29672 	return;
29673 
29674  syntax_error:
29675 	duk__dec_syntax_error(js_ctx);
29676 	DUK_UNREACHABLE();
29677 }
29678 #endif  /* DUK_USE_JX */
29679 
29680 /* Parse a number, other than NaN or +/- Infinity */
duk__dec_number(duk_json_dec_ctx * js_ctx)29681 DUK_LOCAL void duk__dec_number(duk_json_dec_ctx *js_ctx) {
29682 	duk_context *ctx = (duk_context *) js_ctx->thr;
29683 	const duk_uint8_t *p_start;
29684 	const duk_uint8_t *p;
29685 	duk_uint8_t x;
29686 	duk_small_uint_t s2n_flags;
29687 
29688 	DUK_DDD(DUK_DDDPRINT("parse_number"));
29689 
29690 	p_start = js_ctx->p;
29691 
29692 	/* First pass parse is very lenient (e.g. allows '1.2.3') and extracts a
29693 	 * string for strict number parsing.
29694 	 */
29695 
29696 	p = js_ctx->p;
29697 	for (;;) {
29698 		x = *p;
29699 
29700 		DUK_DDD(DUK_DDDPRINT("parse_number: p_start=%p, p=%p, p_end=%p, x=%ld",
29701 		                     (const void *) p_start, (const void *) p,
29702 		                     (const void *) js_ctx->p_end, (long) x));
29703 
29704 #if defined(DUK_USE_JSON_DECNUMBER_FASTPATH)
29705 		/* This fast path is pretty marginal in practice.
29706 		 * XXX: candidate for removal.
29707 		 */
29708 		DUK_ASSERT(duk__json_decnumber_lookup[0x00] == 0x00);  /* end-of-input breaks */
29709 		if (duk__json_decnumber_lookup[x] == 0) {
29710 			break;
29711 		}
29712 #else  /* DUK_USE_JSON_DECNUMBER_FASTPATH */
29713 		if (!((x >= DUK_ASC_0 && x <= DUK_ASC_9) ||
29714 		      (x == DUK_ASC_PERIOD || x == DUK_ASC_LC_E ||
29715 		       x == DUK_ASC_UC_E || x == DUK_ASC_MINUS || x == DUK_ASC_PLUS))) {
29716 			/* Plus sign must be accepted for positive exponents
29717 			 * (e.g. '1.5e+2').  This clause catches NULs.
29718 			 */
29719 			break;
29720 		}
29721 #endif  /* DUK_USE_JSON_DECNUMBER_FASTPATH */
29722 		p++;  /* safe, because matched (NUL causes a break) */
29723 	}
29724 	js_ctx->p = p;
29725 
29726 	DUK_ASSERT(js_ctx->p > p_start);
29727 	duk_push_lstring(ctx, (const char *) p_start, (duk_size_t) (p - p_start));
29728 
29729 	s2n_flags = DUK_S2N_FLAG_ALLOW_EXP |
29730 	            DUK_S2N_FLAG_ALLOW_MINUS |  /* but don't allow leading plus */
29731 	            DUK_S2N_FLAG_ALLOW_FRAC;
29732 
29733 	DUK_DDD(DUK_DDDPRINT("parse_number: string before parsing: %!T",
29734 	                     (duk_tval *) duk_get_tval(ctx, -1)));
29735 	duk_numconv_parse(ctx, 10 /*radix*/, s2n_flags);
29736 	if (duk_is_nan(ctx, -1)) {
29737 		duk__dec_syntax_error(js_ctx);
29738 	}
29739 	DUK_ASSERT(duk_is_number(ctx, -1));
29740 	DUK_DDD(DUK_DDDPRINT("parse_number: final number: %!T",
29741 	                     (duk_tval *) duk_get_tval(ctx, -1)));
29742 
29743 	/* [ ... num ] */
29744 }
29745 
duk__dec_objarr_entry(duk_json_dec_ctx * js_ctx)29746 DUK_LOCAL void duk__dec_objarr_entry(duk_json_dec_ctx *js_ctx) {
29747 	duk_context *ctx = (duk_context *) js_ctx->thr;
29748 	duk_require_stack(ctx, DUK_JSON_DEC_REQSTACK);
29749 
29750 	/* c recursion check */
29751 
29752 	DUK_ASSERT(js_ctx->recursion_depth >= 0);
29753 	DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
29754 	if (js_ctx->recursion_depth >= js_ctx->recursion_limit) {
29755 		DUK_ERROR_RANGE((duk_hthread *) ctx, DUK_STR_JSONDEC_RECLIMIT);
29756 	}
29757 	js_ctx->recursion_depth++;
29758 }
29759 
duk__dec_objarr_exit(duk_json_dec_ctx * js_ctx)29760 DUK_LOCAL void duk__dec_objarr_exit(duk_json_dec_ctx *js_ctx) {
29761 	/* c recursion check */
29762 
29763 	DUK_ASSERT(js_ctx->recursion_depth > 0);
29764 	DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
29765 	js_ctx->recursion_depth--;
29766 }
29767 
duk__dec_object(duk_json_dec_ctx * js_ctx)29768 DUK_LOCAL void duk__dec_object(duk_json_dec_ctx *js_ctx) {
29769 	duk_context *ctx = (duk_context *) js_ctx->thr;
29770 	duk_int_t key_count;  /* XXX: a "first" flag would suffice */
29771 	duk_uint8_t x;
29772 
29773 	DUK_DDD(DUK_DDDPRINT("parse_object"));
29774 
29775 	duk__dec_objarr_entry(js_ctx);
29776 
29777 	duk_push_object(ctx);
29778 
29779 	/* Initial '{' has been checked and eaten by caller. */
29780 
29781 	key_count = 0;
29782 	for (;;) {
29783 		x = duk__dec_get_nonwhite(js_ctx);
29784 
29785 		DUK_DDD(DUK_DDDPRINT("parse_object: obj=%!T, x=%ld, key_count=%ld",
29786 		                     (duk_tval *) duk_get_tval(ctx, -1),
29787 		                     (long) x, (long) key_count));
29788 
29789 		/* handle comma and closing brace */
29790 
29791 		if (x == DUK_ASC_COMMA && key_count > 0) {
29792 			/* accept comma, expect new value */
29793 			x = duk__dec_get_nonwhite(js_ctx);
29794 		} else if (x == DUK_ASC_RCURLY) {
29795 			/* eat closing brace */
29796 			break;
29797 		} else if (key_count == 0) {
29798 			/* accept anything, expect first value (EOF will be
29799 			 * caught by key parsing below.
29800 			 */
29801 			;
29802 		} else {
29803 			/* catches EOF (NUL) and initial comma */
29804 			goto syntax_error;
29805 		}
29806 
29807 		/* parse key and value */
29808 
29809 		if (x == DUK_ASC_DOUBLEQUOTE) {
29810 			duk__dec_string(js_ctx);
29811 #ifdef DUK_USE_JX
29812 		} else if (js_ctx->flag_ext_custom &&
29813 		           duk_unicode_is_identifier_start((duk_codepoint_t) x)) {
29814 			duk__dec_plain_string(js_ctx);
29815 #endif
29816 		} else {
29817 			goto syntax_error;
29818 		}
29819 
29820 		/* [ ... obj key ] */
29821 
29822 		x = duk__dec_get_nonwhite(js_ctx);
29823 		if (x != DUK_ASC_COLON) {
29824 			goto syntax_error;
29825 		}
29826 
29827 		duk__dec_value(js_ctx);
29828 
29829 		/* [ ... obj key val ] */
29830 
29831 		duk_xdef_prop_wec(ctx, -3);
29832 
29833 		/* [ ... obj ] */
29834 
29835 		key_count++;
29836 	}
29837 
29838 	/* [ ... obj ] */
29839 
29840 	DUK_DDD(DUK_DDDPRINT("parse_object: final object is %!T",
29841 	                     (duk_tval *) duk_get_tval(ctx, -1)));
29842 
29843 	duk__dec_objarr_exit(js_ctx);
29844 	return;
29845 
29846  syntax_error:
29847 	duk__dec_syntax_error(js_ctx);
29848 	DUK_UNREACHABLE();
29849 }
29850 
duk__dec_array(duk_json_dec_ctx * js_ctx)29851 DUK_LOCAL void duk__dec_array(duk_json_dec_ctx *js_ctx) {
29852 	duk_context *ctx = (duk_context *) js_ctx->thr;
29853 	duk_uarridx_t arr_idx;
29854 	duk_uint8_t x;
29855 
29856 	DUK_DDD(DUK_DDDPRINT("parse_array"));
29857 
29858 	duk__dec_objarr_entry(js_ctx);
29859 
29860 	duk_push_array(ctx);
29861 
29862 	/* Initial '[' has been checked and eaten by caller. */
29863 
29864 	arr_idx = 0;
29865 	for (;;) {
29866 		x = duk__dec_get_nonwhite(js_ctx);
29867 
29868 		DUK_DDD(DUK_DDDPRINT("parse_array: arr=%!T, x=%ld, arr_idx=%ld",
29869 		                     (duk_tval *) duk_get_tval(ctx, -1),
29870 		                     (long) x, (long) arr_idx));
29871 
29872 		/* handle comma and closing bracket */
29873 
29874 		if ((x == DUK_ASC_COMMA) && (arr_idx != 0)) {
29875 			/* accept comma, expect new value */
29876 			;
29877 		} else if (x == DUK_ASC_RBRACKET) {
29878 			/* eat closing bracket */
29879 			break;
29880 		} else if (arr_idx == 0) {
29881 			/* accept anything, expect first value (EOF will be
29882 			 * caught by duk__dec_value() below.
29883 			 */
29884 			js_ctx->p--;  /* backtrack (safe) */
29885 		} else {
29886 			/* catches EOF (NUL) and initial comma */
29887 			goto syntax_error;
29888 		}
29889 
29890 		/* parse value */
29891 
29892 		duk__dec_value(js_ctx);
29893 
29894 		/* [ ... arr val ] */
29895 
29896 		duk_xdef_prop_index_wec(ctx, -2, arr_idx);
29897 		arr_idx++;
29898 	}
29899 
29900 	/* Must set 'length' explicitly when using duk_xdef_prop_xxx() to
29901 	 * set the values.
29902 	 */
29903 
29904 	duk_set_length(ctx, -1, arr_idx);
29905 
29906 	/* [ ... arr ] */
29907 
29908 	DUK_DDD(DUK_DDDPRINT("parse_array: final array is %!T",
29909 	                     (duk_tval *) duk_get_tval(ctx, -1)));
29910 
29911 	duk__dec_objarr_exit(js_ctx);
29912 	return;
29913 
29914  syntax_error:
29915 	duk__dec_syntax_error(js_ctx);
29916 	DUK_UNREACHABLE();
29917 }
29918 
duk__dec_value(duk_json_dec_ctx * js_ctx)29919 DUK_LOCAL void duk__dec_value(duk_json_dec_ctx *js_ctx) {
29920 	duk_context *ctx = (duk_context *) js_ctx->thr;
29921 	duk_uint8_t x;
29922 
29923 	x = duk__dec_get_nonwhite(js_ctx);
29924 
29925 	DUK_DDD(DUK_DDDPRINT("parse_value: initial x=%ld", (long) x));
29926 
29927 	/* Note: duk__dec_req_stridx() backtracks one char */
29928 
29929 	if (x == DUK_ASC_DOUBLEQUOTE) {
29930 		duk__dec_string(js_ctx);
29931 	} else if ((x >= DUK_ASC_0 && x <= DUK_ASC_9) || (x == DUK_ASC_MINUS)) {
29932 #ifdef DUK_USE_JX
29933 		if (js_ctx->flag_ext_custom && x == DUK_ASC_MINUS && duk__dec_peek(js_ctx) == DUK_ASC_UC_I) {
29934 			duk__dec_req_stridx(js_ctx, DUK_STRIDX_MINUS_INFINITY);  /* "-Infinity", '-' has been eaten */
29935 			duk_push_number(ctx, -DUK_DOUBLE_INFINITY);
29936 		} else {
29937 #else
29938 		{  /* unconditional block */
29939 #endif
29940 			/* We already ate 'x', so backup one byte. */
29941 			js_ctx->p--;  /* safe */
29942 			duk__dec_number(js_ctx);
29943 		}
29944 	} else if (x == DUK_ASC_LC_T) {
29945 		duk__dec_req_stridx(js_ctx, DUK_STRIDX_TRUE);
29946 		duk_push_true(ctx);
29947 	} else if (x == DUK_ASC_LC_F) {
29948 		duk__dec_req_stridx(js_ctx, DUK_STRIDX_FALSE);
29949 		duk_push_false(ctx);
29950 	} else if (x == DUK_ASC_LC_N) {
29951 		duk__dec_req_stridx(js_ctx, DUK_STRIDX_LC_NULL);
29952 		duk_push_null(ctx);
29953 #ifdef DUK_USE_JX
29954 	} else if (js_ctx->flag_ext_custom && x == DUK_ASC_LC_U) {
29955 		duk__dec_req_stridx(js_ctx, DUK_STRIDX_LC_UNDEFINED);
29956 		duk_push_undefined(ctx);
29957 	} else if (js_ctx->flag_ext_custom && x == DUK_ASC_UC_N) {
29958 		duk__dec_req_stridx(js_ctx, DUK_STRIDX_NAN);
29959 		duk_push_nan(ctx);
29960 	} else if (js_ctx->flag_ext_custom && x == DUK_ASC_UC_I) {
29961 		duk__dec_req_stridx(js_ctx, DUK_STRIDX_INFINITY);
29962 		duk_push_number(ctx, DUK_DOUBLE_INFINITY);
29963 	} else if (js_ctx->flag_ext_custom && x == DUK_ASC_LPAREN) {
29964 		duk__dec_pointer(js_ctx);
29965 	} else if (js_ctx->flag_ext_custom && x == DUK_ASC_PIPE) {
29966 		duk__dec_buffer(js_ctx);
29967 #endif
29968 	} else if (x == DUK_ASC_LCURLY) {
29969 		duk__dec_object(js_ctx);
29970 	} else if (x == DUK_ASC_LBRACKET) {
29971 		duk__dec_array(js_ctx);
29972 	} else {
29973 		/* catches EOF (NUL) */
29974 		goto syntax_error;
29975 	}
29976 
29977 	duk__dec_eat_white(js_ctx);
29978 
29979 	/* [ ... val ] */
29980 	return;
29981 
29982  syntax_error:
29983 	duk__dec_syntax_error(js_ctx);
29984 	DUK_UNREACHABLE();
29985 }
29986 
29987 /* Recursive value reviver, implements the Walk() algorithm.  No C recursion
29988  * check is done here because the initial parsing step will already ensure
29989  * there is a reasonable limit on C recursion depth and hence object depth.
29990  */
29991 DUK_LOCAL void duk__dec_reviver_walk(duk_json_dec_ctx *js_ctx) {
29992 	duk_context *ctx = (duk_context *) js_ctx->thr;
29993 	duk_hobject *h;
29994 	duk_uarridx_t i, arr_len;
29995 
29996 	DUK_DDD(DUK_DDDPRINT("walk: top=%ld, holder=%!T, name=%!T",
29997 	                     (long) duk_get_top(ctx),
29998 	                     (duk_tval *) duk_get_tval(ctx, -2),
29999 	                     (duk_tval *) duk_get_tval(ctx, -1)));
30000 
30001 	duk_dup_top(ctx);
30002 	duk_get_prop(ctx, -3);  /* -> [ ... holder name val ] */
30003 
30004 	h = duk_get_hobject(ctx, -1);
30005 	if (h != NULL) {
30006 		if (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAY) {
30007 			arr_len = (duk_uarridx_t) duk_get_length(ctx, -1);
30008 			for (i = 0; i < arr_len; i++) {
30009 				/* [ ... holder name val ] */
30010 
30011 				DUK_DDD(DUK_DDDPRINT("walk: array, top=%ld, i=%ld, arr_len=%ld, holder=%!T, name=%!T, val=%!T",
30012 				                     (long) duk_get_top(ctx), (long) i, (long) arr_len,
30013 				                     (duk_tval *) duk_get_tval(ctx, -3), (duk_tval *) duk_get_tval(ctx, -2),
30014 				                     (duk_tval *) duk_get_tval(ctx, -1)));
30015 
30016 				/* XXX: push_uint_string / push_u32_string */
30017 				duk_dup_top(ctx);
30018 				duk_push_uint(ctx, (duk_uint_t) i);
30019 				duk_to_string(ctx, -1);  /* -> [ ... holder name val val ToString(i) ] */
30020 				duk__dec_reviver_walk(js_ctx);  /* -> [ ... holder name val new_elem ] */
30021 
30022 				if (duk_is_undefined(ctx, -1)) {
30023 					duk_pop(ctx);
30024 					duk_del_prop_index(ctx, -1, i);
30025 				} else {
30026 					/* XXX: duk_xdef_prop_index_wec() would be more appropriate
30027 					 * here but it currently makes some assumptions that might
30028 					 * not hold (e.g. that previous property is not an accessor).
30029 					 */
30030 					duk_put_prop_index(ctx, -2, i);
30031 				}
30032 			}
30033 		} else {
30034 			/* [ ... holder name val ] */
30035 			duk_enum(ctx, -1, DUK_ENUM_OWN_PROPERTIES_ONLY /*flags*/);
30036 			while (duk_next(ctx, -1 /*enum_index*/, 0 /*get_value*/)) {
30037 				DUK_DDD(DUK_DDDPRINT("walk: object, top=%ld, holder=%!T, name=%!T, val=%!T, enum=%!iT, obj_key=%!T",
30038 				                     (long) duk_get_top(ctx), (duk_tval *) duk_get_tval(ctx, -5),
30039 				                     (duk_tval *) duk_get_tval(ctx, -4), (duk_tval *) duk_get_tval(ctx, -3),
30040 				                     (duk_tval *) duk_get_tval(ctx, -2), (duk_tval *) duk_get_tval(ctx, -1)));
30041 
30042 				/* [ ... holder name val enum obj_key ] */
30043 				duk_dup(ctx, -3);
30044 				duk_dup(ctx, -2);
30045 
30046 				/* [ ... holder name val enum obj_key val obj_key ] */
30047 				duk__dec_reviver_walk(js_ctx);
30048 
30049 				/* [ ... holder name val enum obj_key new_elem ] */
30050 				if (duk_is_undefined(ctx, -1)) {
30051 					duk_pop(ctx);
30052 					duk_del_prop(ctx, -3);
30053 				} else {
30054 					/* XXX: duk_xdef_prop_index_wec() would be more appropriate
30055 					 * here but it currently makes some assumptions that might
30056 					 * not hold (e.g. that previous property is not an accessor).
30057 					 *
30058 					 * Using duk_put_prop() works incorrectly with '__proto__'
30059 					 * if the own property with that name has been deleted.  This
30060 					 * does not happen normally, but a clever reviver can trigger
30061 					 * that, see complex reviver case in: test-bug-json-parse-__proto__.js.
30062 					 */
30063 					duk_put_prop(ctx, -4);
30064 				}
30065 			}
30066 			duk_pop(ctx);  /* pop enum */
30067 		}
30068 	}
30069 
30070 	/* [ ... holder name val ] */
30071 
30072 	duk_dup(ctx, js_ctx->idx_reviver);
30073 	duk_insert(ctx, -4);  /* -> [ ... reviver holder name val ] */
30074 	duk_call_method(ctx, 2);  /* -> [ ... res ] */
30075 
30076 	DUK_DDD(DUK_DDDPRINT("walk: top=%ld, result=%!T",
30077 	                     (long) duk_get_top(ctx), (duk_tval *) duk_get_tval(ctx, -1)));
30078 }
30079 
30080 /*
30081  *  Stringify implementation.
30082  */
30083 
30084 #define DUK__EMIT_1(js_ctx,ch)          duk__emit_1((js_ctx), (duk_uint_fast8_t) (ch))
30085 #define DUK__EMIT_2(js_ctx,ch1,ch2)     duk__emit_2((js_ctx), (duk_uint_fast8_t) (ch1), (duk_uint_fast8_t) (ch2))
30086 #define DUK__EMIT_HSTR(js_ctx,h)        duk__emit_hstring((js_ctx), (h))
30087 #if defined(DUK_USE_FASTINT) || defined(DUK_USE_JX) || defined(DUK_USE_JC)
30088 #define DUK__EMIT_CSTR(js_ctx,p)        duk__emit_cstring((js_ctx), (p))
30089 #endif
30090 #define DUK__EMIT_STRIDX(js_ctx,i)      duk__emit_stridx((js_ctx), (i))
30091 #define DUK__UNEMIT_1(js_ctx)           duk__unemit_1((js_ctx))
30092 
30093 DUK_LOCAL void duk__emit_1(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch) {
30094 	DUK_BW_WRITE_ENSURE_U8(js_ctx->thr, &js_ctx->bw, ch);
30095 }
30096 
30097 DUK_LOCAL void duk__emit_2(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch1, duk_uint_fast8_t ch2) {
30098 	DUK_BW_WRITE_ENSURE_U8_2(js_ctx->thr, &js_ctx->bw, ch1, ch2);
30099 }
30100 
30101 DUK_LOCAL void duk__emit_hstring(duk_json_enc_ctx *js_ctx, duk_hstring *h) {
30102 	DUK_BW_WRITE_ENSURE_HSTRING(js_ctx->thr, &js_ctx->bw, h);
30103 }
30104 
30105 #if defined(DUK_USE_FASTINT) || defined(DUK_USE_JX) || defined(DUK_USE_JC)
30106 DUK_LOCAL void duk__emit_cstring(duk_json_enc_ctx *js_ctx, const char *str) {
30107 	DUK_BW_WRITE_ENSURE_CSTRING(js_ctx->thr, &js_ctx->bw, str);
30108 }
30109 #endif
30110 
30111 DUK_LOCAL void duk__emit_stridx(duk_json_enc_ctx *js_ctx, duk_small_uint_t stridx) {
30112 	duk_hstring *h;
30113 
30114 	DUK_ASSERT_DISABLE(stridx >= 0);  /* unsigned */
30115 	DUK_ASSERT(stridx < DUK_HEAP_NUM_STRINGS);
30116 	h = DUK_HTHREAD_GET_STRING(js_ctx->thr, stridx);
30117 	DUK_ASSERT(h != NULL);
30118 
30119 	DUK_BW_WRITE_ENSURE_HSTRING(js_ctx->thr, &js_ctx->bw, h);
30120 }
30121 
30122 DUK_LOCAL void duk__unemit_1(duk_json_enc_ctx *js_ctx) {
30123 	DUK_ASSERT(DUK_BW_GET_SIZE(js_ctx->thr, &js_ctx->bw) >= 1);
30124 	DUK_BW_ADD_PTR(js_ctx->thr, &js_ctx->bw, -1);
30125 }
30126 
30127 #define DUK__MKESC(nybbles,esc1,esc2)  \
30128 	(((duk_uint_fast32_t) (nybbles)) << 16) | \
30129 	(((duk_uint_fast32_t) (esc1)) << 8) | \
30130 	((duk_uint_fast32_t) (esc2))
30131 
30132 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) {
30133 	duk_uint_fast32_t tmp;
30134 	duk_small_uint_t dig;
30135 
30136 	DUK_UNREF(js_ctx);
30137 
30138 	/* Caller ensures space for at least DUK__JSON_MAX_ESC_LEN. */
30139 
30140 	/* Select appropriate escape format automatically, and set 'tmp' to a
30141 	 * value encoding both the escape format character and the nybble count:
30142 	 *
30143 	 *   (nybble_count << 16) | (escape_char1) | (escape_char2)
30144 	 */
30145 
30146 #ifdef DUK_USE_JX
30147 	if (DUK_LIKELY(cp < 0x100UL)) {
30148 		if (DUK_UNLIKELY(js_ctx->flag_ext_custom)) {
30149 			tmp = DUK__MKESC(2, DUK_ASC_BACKSLASH, DUK_ASC_LC_X);
30150 		} else {
30151 			tmp = DUK__MKESC(4, DUK_ASC_BACKSLASH, DUK_ASC_LC_U);
30152 		}
30153 	} else
30154 #endif
30155 	if (DUK_LIKELY(cp < 0x10000UL)) {
30156 		tmp = DUK__MKESC(4, DUK_ASC_BACKSLASH, DUK_ASC_LC_U);
30157 	} else {
30158 #ifdef DUK_USE_JX
30159 		if (DUK_LIKELY(js_ctx->flag_ext_custom)) {
30160 			tmp = DUK__MKESC(8, DUK_ASC_BACKSLASH, DUK_ASC_UC_U);
30161 		} else
30162 #endif
30163 		{
30164 			/* In compatible mode and standard JSON mode, output
30165 			 * something useful for non-BMP characters.  This won't
30166 			 * roundtrip but will still be more or less readable and
30167 			 * more useful than an error.
30168 			 */
30169 			tmp = DUK__MKESC(8, DUK_ASC_UC_U, DUK_ASC_PLUS);
30170 		}
30171 	}
30172 
30173 	*q++ = (duk_uint8_t) ((tmp >> 8) & 0xff);
30174 	*q++ = (duk_uint8_t) (tmp & 0xff);
30175 
30176 	tmp = tmp >> 16;
30177 	while (tmp > 0) {
30178 		tmp--;
30179 		dig = (duk_small_uint_t) ((cp >> (4 * tmp)) & 0x0f);
30180 		*q++ = duk_lc_digits[dig];
30181 	}
30182 
30183 	return q;
30184 }
30185 
30186 DUK_LOCAL void duk__enc_key_autoquote(duk_json_enc_ctx *js_ctx, duk_hstring *k) {
30187 	const duk_int8_t *p, *p_start, *p_end;  /* Note: intentionally signed. */
30188 	duk_size_t k_len;
30189 	duk_codepoint_t cp;
30190 
30191 	DUK_ASSERT(k != NULL);
30192 
30193 	/* Accept ASCII strings which conform to identifier requirements
30194 	 * as being emitted without key quotes.  Since we only accept ASCII
30195 	 * there's no need for actual decoding: 'p' is intentionally signed
30196 	 * so that bytes >= 0x80 extend to negative values and are rejected
30197 	 * as invalid identifier codepoints.
30198 	 */
30199 
30200 	if (js_ctx->flag_avoid_key_quotes) {
30201 		k_len = DUK_HSTRING_GET_BYTELEN(k);
30202 		p_start = (const duk_int8_t *) DUK_HSTRING_GET_DATA(k);
30203 		p_end = p_start + k_len;
30204 		p = p_start;
30205 
30206 		if (p == p_end) {
30207 			/* Zero length string is not accepted without quotes */
30208 			goto quote_normally;
30209 		}
30210 		cp = (duk_codepoint_t) (*p++);
30211 		if (DUK_UNLIKELY(!duk_unicode_is_identifier_start(cp))) {
30212 			goto quote_normally;
30213 		}
30214 		while (p < p_end) {
30215 			cp = (duk_codepoint_t) (*p++);
30216 			if (DUK_UNLIKELY(!duk_unicode_is_identifier_part(cp))) {
30217 				goto quote_normally;
30218 			}
30219 		}
30220 
30221 		/* This seems faster than emitting bytes one at a time and
30222 		 * then potentially rewinding.
30223 		 */
30224 		DUK__EMIT_HSTR(js_ctx, k);
30225 		return;
30226 	}
30227 
30228  quote_normally:
30229 	duk__enc_quote_string(js_ctx, k);
30230 }
30231 
30232 /* The Quote(value) operation: quote a string.
30233  *
30234  * Stack policy: [ ] -> [ ].
30235  */
30236 
30237 DUK_LOCAL void duk__enc_quote_string(duk_json_enc_ctx *js_ctx, duk_hstring *h_str) {
30238 	duk_hthread *thr = js_ctx->thr;
30239 	const duk_uint8_t *p, *p_start, *p_end, *p_now, *p_tmp;
30240 	duk_uint8_t *q;
30241 	duk_ucodepoint_t cp;  /* typed for duk_unicode_decode_xutf8() */
30242 
30243 	DUK_DDD(DUK_DDDPRINT("duk__enc_quote_string: h_str=%!O", (duk_heaphdr *) h_str));
30244 
30245 	DUK_ASSERT(h_str != NULL);
30246 	p_start = DUK_HSTRING_GET_DATA(h_str);
30247 	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_str);
30248 	p = p_start;
30249 
30250 	DUK__EMIT_1(js_ctx, DUK_ASC_DOUBLEQUOTE);
30251 
30252 	/* Encode string in small chunks, estimating the maximum expansion so that
30253 	 * there's no need to ensure space while processing the chunk.
30254 	 */
30255 
30256 	while (p < p_end) {
30257 		duk_size_t left, now, space;
30258 
30259 		left = (duk_size_t) (p_end - p);
30260 		now = (left > DUK__JSON_ENCSTR_CHUNKSIZE ?
30261 		       DUK__JSON_ENCSTR_CHUNKSIZE : left);
30262 
30263 		/* Maximum expansion per input byte is 6:
30264 		 *   - invalid UTF-8 byte causes "\uXXXX" to be emitted (6/1 = 6).
30265 		 *   - 2-byte UTF-8 encodes as "\uXXXX" (6/2 = 3).
30266 		 *   - 4-byte UTF-8 encodes as "\Uxxxxxxxx" (10/4 = 2.5).
30267 		 */
30268 		space = now * 6;
30269 		q = DUK_BW_ENSURE_GETPTR(thr, &js_ctx->bw, space);
30270 
30271 		p_now = p + now;
30272 
30273 		while (p < p_now) {
30274 #if defined(DUK_USE_JSON_QUOTESTRING_FASTPATH)
30275 			duk_uint8_t b;
30276 
30277 			b = duk__json_quotestr_lookup[*p++];
30278 			if (DUK_LIKELY(b < 0x80)) {
30279 				/* Most input bytes go through here. */
30280 				*q++ = b;
30281 			} else if (b >= 0xa0) {
30282 				*q++ = DUK_ASC_BACKSLASH;
30283 				*q++ = (duk_uint8_t) (b - 0x80);
30284 			} else if (b == 0x80) {
30285 				cp = (duk_ucodepoint_t) (*(p - 1));
30286 				q = duk__emit_esc_auto_fast(js_ctx, cp, q);
30287 			} else if (b == 0x7f && js_ctx->flag_ascii_only) {
30288 				/* 0x7F is special */
30289 				DUK_ASSERT(b == 0x81);
30290 				cp = (duk_ucodepoint_t) 0x7f;
30291 				q = duk__emit_esc_auto_fast(js_ctx, cp, q);
30292 			} else {
30293 				DUK_ASSERT(b == 0x81);
30294 				p--;
30295 
30296 				/* slow path is shared */
30297 #else  /* DUK_USE_JSON_QUOTESTRING_FASTPATH */
30298 			cp = *p;
30299 
30300 			if (DUK_LIKELY(cp <= 0x7f)) {
30301 				/* ascii fast path: avoid decoding utf-8 */
30302 				p++;
30303 				if (cp == 0x22 || cp == 0x5c) {
30304 					/* double quote or backslash */
30305 					*q++ = DUK_ASC_BACKSLASH;
30306 					*q++ = (duk_uint8_t) cp;
30307 				} else if (cp < 0x20) {
30308 					duk_uint_fast8_t esc_char;
30309 
30310 					/* This approach is a bit shorter than a straight
30311 					 * if-else-ladder and also a bit faster.
30312 					 */
30313 					if (cp < (sizeof(duk__json_quotestr_esc) / sizeof(duk_uint8_t)) &&
30314 					    (esc_char = duk__json_quotestr_esc[cp]) != 0) {
30315 						*q++ = DUK_ASC_BACKSLASH;
30316 						*q++ = (duk_uint8_t) esc_char;
30317 					} else {
30318 						q = duk__emit_esc_auto_fast(js_ctx, cp, q);
30319 					}
30320 				} else if (cp == 0x7f && js_ctx->flag_ascii_only) {
30321 					q = duk__emit_esc_auto_fast(js_ctx, cp, q);
30322 				} else {
30323 					/* any other printable -> as is */
30324 					*q++ = (duk_uint8_t) cp;
30325 				}
30326 			} else {
30327 				/* slow path is shared */
30328 #endif  /* DUK_USE_JSON_QUOTESTRING_FASTPATH */
30329 
30330 				/* slow path decode */
30331 
30332 				/* If XUTF-8 decoding fails, treat the offending byte as a codepoint directly
30333 				 * and go forward one byte.  This is of course very lossy, but allows some kind
30334 				 * of output to be produced even for internal strings which don't conform to
30335 				 * XUTF-8.  All standard Ecmascript strings are always CESU-8, so this behavior
30336 				 * does not violate the Ecmascript specification.  The behavior is applied to
30337 				 * all modes, including Ecmascript standard JSON.  Because the current XUTF-8
30338 				 * decoding is not very strict, this behavior only really affects initial bytes
30339 				 * and truncated codepoints.
30340 				 *
30341 				 * Another alternative would be to scan forwards to start of next codepoint
30342 				 * (or end of input) and emit just one replacement codepoint.
30343 				 */
30344 
30345 				p_tmp = p;
30346 				if (!duk_unicode_decode_xutf8(thr, &p, p_start, p_end, &cp)) {
30347 					/* Decode failed. */
30348 					cp = *p_tmp;
30349 					p = p_tmp + 1;
30350 				}
30351 
30352 #ifdef DUK_USE_NONSTD_JSON_ESC_U2028_U2029
30353 				if (js_ctx->flag_ascii_only || cp == 0x2028 || cp == 0x2029) {
30354 #else
30355 				if (js_ctx->flag_ascii_only) {
30356 #endif
30357 					q = duk__emit_esc_auto_fast(js_ctx, cp, q);
30358 				} else {
30359 					/* as is */
30360 					DUK_RAW_WRITE_XUTF8(q, cp);
30361 				}
30362 			}
30363 		}
30364 
30365 		DUK_BW_SET_PTR(thr, &js_ctx->bw, q);
30366 	}
30367 
30368 	DUK__EMIT_1(js_ctx, DUK_ASC_DOUBLEQUOTE);
30369 }
30370 
30371 /* Encode a double (checked by caller) from stack top.  Stack top may be
30372  * replaced by serialized string but is not popped (caller does that).
30373  */
30374 DUK_LOCAL void duk__enc_double(duk_json_enc_ctx *js_ctx) {
30375 	duk_hthread *thr;
30376 	duk_context *ctx;
30377 	duk_tval *tv;
30378 	duk_double_t d;
30379 	duk_small_int_t c;
30380 	duk_small_int_t s;
30381 	duk_small_uint_t stridx;
30382 	duk_small_uint_t n2s_flags;
30383 	duk_hstring *h_str;
30384 
30385 	DUK_ASSERT(js_ctx != NULL);
30386 	thr = js_ctx->thr;
30387 	DUK_ASSERT(thr != NULL);
30388 	ctx = (duk_context *) thr;
30389 
30390 	/* Caller must ensure 'tv' is indeed a double and not a fastint! */
30391 	tv = DUK_GET_TVAL_NEGIDX(ctx, -1);
30392 	DUK_ASSERT(DUK_TVAL_IS_DOUBLE(tv));
30393 	d = DUK_TVAL_GET_DOUBLE(tv);
30394 
30395 	c = (duk_small_int_t) DUK_FPCLASSIFY(d);
30396 	s = (duk_small_int_t) DUK_SIGNBIT(d);
30397 	DUK_UNREF(s);
30398 
30399 	if (DUK_LIKELY(!(c == DUK_FP_INFINITE || c == DUK_FP_NAN))) {
30400 		DUK_ASSERT(DUK_ISFINITE(d));
30401 
30402 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
30403 		/* Negative zero needs special handling in JX/JC because
30404 		 * it would otherwise serialize to '0', not '-0'.
30405 		 */
30406 		if (DUK_UNLIKELY(c == DUK_FP_ZERO && s != 0 &&
30407 		                 (js_ctx->flag_ext_custom_or_compatible))) {
30408 			duk_push_hstring_stridx(ctx, DUK_STRIDX_MINUS_ZERO);  /* '-0' */
30409 		} else
30410 #endif  /* DUK_USE_JX || DUK_USE_JC */
30411 		{
30412 			n2s_flags = 0;
30413 			/* [ ... number ] -> [ ... string ] */
30414 			duk_numconv_stringify(ctx, 10 /*radix*/, 0 /*digits*/, n2s_flags);
30415 		}
30416 		h_str = duk_to_hstring(ctx, -1);
30417 		DUK_ASSERT(h_str != NULL);
30418 		DUK__EMIT_HSTR(js_ctx, h_str);
30419 		return;
30420 	}
30421 
30422 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
30423 	if (!(js_ctx->flags & (DUK_JSON_FLAG_EXT_CUSTOM |
30424 	                       DUK_JSON_FLAG_EXT_COMPATIBLE))) {
30425 		stridx = DUK_STRIDX_LC_NULL;
30426 	} else if (c == DUK_FP_NAN) {
30427 		stridx = js_ctx->stridx_custom_nan;
30428 	} else if (s == 0) {
30429 		stridx = js_ctx->stridx_custom_posinf;
30430 	} else {
30431 		stridx = js_ctx->stridx_custom_neginf;
30432 	}
30433 #else
30434 	stridx = DUK_STRIDX_LC_NULL;
30435 #endif
30436 	DUK__EMIT_STRIDX(js_ctx, stridx);
30437 }
30438 
30439 #if defined(DUK_USE_FASTINT)
30440 /* Encode a fastint from duk_tval ptr, no value stack effects. */
30441 DUK_LOCAL void duk__enc_fastint_tval(duk_json_enc_ctx *js_ctx, duk_tval *tv) {
30442 	duk_int64_t v;
30443 
30444 	/* Fastint range is signed 48-bit so longest value is -2^47 = -140737488355328
30445 	 * (16 chars long), longest signed 64-bit value is -2^63 = -9223372036854775808
30446 	 * (20 chars long).  Alloc space for 64-bit range to be safe.
30447 	 */
30448 	duk_uint8_t buf[20 + 1];
30449 
30450 	/* Caller must ensure 'tv' is indeed a fastint! */
30451 	DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv));
30452 	v = DUK_TVAL_GET_FASTINT(tv);
30453 
30454 	/* XXX: There are no format strings in duk_config.h yet, could add
30455 	 * one for formatting duk_int64_t.  For now, assumes "%lld" and that
30456 	 * "long long" type exists.  Could also rely on C99 directly but that
30457 	 * won't work for older MSVC.
30458 	 */
30459 	DUK_SPRINTF((char *) buf, "%lld", (long long) v);
30460 	DUK__EMIT_CSTR(js_ctx, (const char *) buf);
30461 }
30462 #endif
30463 
30464 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
30465 #if defined(DUK_USE_HEX_FASTPATH)
30466 DUK_LOCAL duk_uint8_t *duk__enc_buffer_data_hex(const duk_uint8_t *src, duk_size_t src_len, duk_uint8_t *dst) {
30467 	duk_uint8_t *q;
30468 	duk_uint16_t *q16;
30469 	duk_small_uint_t x;
30470 	duk_size_t i, len_safe;
30471 #if !defined(DUK_USE_UNALIGNED_ACCESSES_POSSIBLE)
30472 	duk_bool_t shift_dst;
30473 #endif
30474 
30475 	/* Unlike in duk_hex_encode() 'dst' is not necessarily aligned by 2.
30476 	 * For platforms where unaligned accesses are not allowed, shift 'dst'
30477 	 * ahead by 1 byte to get alignment and then DUK_MEMMOVE() the result
30478 	 * in place.  The faster encoding loop makes up the difference.
30479 	 * There's always space for one extra byte because a terminator always
30480 	 * follows the hex data and that's been accounted for by the caller.
30481 	 */
30482 
30483 #if defined(DUK_USE_UNALIGNED_ACCESSES_POSSIBLE)
30484 	q16 = (duk_uint16_t *) (void *) dst;
30485 #else
30486 	shift_dst = (duk_bool_t) (((duk_size_t) dst) & 0x01U);
30487 	if (shift_dst) {
30488 		DUK_DD(DUK_DDPRINT("unaligned accesses not possible, dst not aligned -> step to dst + 1"));
30489 		q16 = (duk_uint16_t *) (void *) (dst + 1);
30490 	} else {
30491 		DUK_DD(DUK_DDPRINT("unaligned accesses not possible, dst is aligned"));
30492 		q16 = (duk_uint16_t *) (void *) dst;
30493 	}
30494 	DUK_ASSERT((((duk_size_t) q16) & 0x01U) == 0);
30495 #endif
30496 
30497 	len_safe = src_len & ~0x03U;
30498 	for (i = 0; i < len_safe; i += 4) {
30499 		q16[0] = duk_hex_enctab[src[i]];
30500 		q16[1] = duk_hex_enctab[src[i + 1]];
30501 		q16[2] = duk_hex_enctab[src[i + 2]];
30502 		q16[3] = duk_hex_enctab[src[i + 3]];
30503 		q16 += 4;
30504 	}
30505 	q = (duk_uint8_t *) q16;
30506 
30507 #if !defined(DUK_USE_UNALIGNED_ACCESSES_POSSIBLE)
30508 	if (shift_dst) {
30509 		q--;
30510 		DUK_MEMMOVE((void *) dst, (const void *) (dst + 1), 2 * len_safe);
30511 		DUK_ASSERT(dst + 2 * len_safe == q);
30512 	}
30513 #endif
30514 
30515 	for (; i < src_len; i++) {
30516 		x = src[i];
30517 		*q++ = duk_lc_digits[x >> 4];
30518 		*q++ = duk_lc_digits[x & 0x0f];
30519 	}
30520 
30521 	return q;
30522 }
30523 #else  /* DUK_USE_HEX_FASTPATH */
30524 DUK_LOCAL duk_uint8_t *duk__enc_buffer_data_hex(const duk_uint8_t *src, duk_size_t src_len, duk_uint8_t *dst) {
30525 	const duk_uint8_t *p;
30526 	const duk_uint8_t *p_end;
30527 	duk_uint8_t *q;
30528 	duk_small_uint_t x;
30529 
30530 	p = src;
30531 	p_end = src + src_len;
30532 	q = dst;
30533 	while (p != p_end) {
30534 		x = *p++;
30535 		*q++ = duk_lc_digits[x >> 4];
30536 		*q++ = duk_lc_digits[x & 0x0f];
30537 	}
30538 
30539 	return q;
30540 }
30541 #endif  /* DUK_USE_HEX_FASTPATH */
30542 
30543 DUK_LOCAL void duk__enc_buffer_data(duk_json_enc_ctx *js_ctx, duk_uint8_t *buf_data, duk_size_t buf_len) {
30544 	duk_hthread *thr;
30545 	duk_uint8_t *q;
30546 	duk_size_t space;
30547 
30548 	thr = js_ctx->thr;
30549 
30550 	DUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible);  /* caller checks */
30551 	DUK_ASSERT(js_ctx->flag_ext_custom_or_compatible);
30552 
30553 	/* Buffer values are encoded in (lowercase) hex to make the
30554 	 * binary data readable.  Base64 or similar would be more
30555 	 * compact but less readable, and the point of JX/JC
30556 	 * variants is to be as useful to a programmer as possible.
30557 	 */
30558 
30559 	/* The #ifdef clutter here needs to handle the three cases:
30560 	 * (1) JX+JC, (2) JX only, (3) JC only.
30561 	 */
30562 
30563 	/* Note: space must cater for both JX and JC. */
30564 	space = 9 + buf_len * 2 + 2;
30565 	DUK_ASSERT(DUK_HBUFFER_MAX_BYTELEN <= 0x7ffffffeUL);
30566 	DUK_ASSERT((space - 2) / 2 >= buf_len);  /* overflow not possible, buffer limits */
30567 	q = DUK_BW_ENSURE_GETPTR(thr, &js_ctx->bw, space);
30568 
30569 #if defined(DUK_USE_JX) && defined(DUK_USE_JC)
30570 	if (js_ctx->flag_ext_custom)
30571 #endif
30572 #if defined(DUK_USE_JX)
30573 	{
30574 		*q++ = DUK_ASC_PIPE;
30575 		q = duk__enc_buffer_data_hex(buf_data, buf_len, q);
30576 		*q++ = DUK_ASC_PIPE;
30577 
30578 	}
30579 #endif
30580 #if defined(DUK_USE_JX) && defined(DUK_USE_JC)
30581 	else
30582 #endif
30583 #if defined(DUK_USE_JC)
30584 	{
30585 		DUK_ASSERT(js_ctx->flag_ext_compatible);
30586 		DUK_MEMCPY((void *) q, (const void *) "{\"_buf\":\"", 9);  /* len: 9 */
30587 		q += 9;
30588 		q = duk__enc_buffer_data_hex(buf_data, buf_len, q);
30589 		*q++ = DUK_ASC_DOUBLEQUOTE;
30590 		*q++ = DUK_ASC_RCURLY;
30591 	}
30592 #endif
30593 
30594 	DUK_BW_SET_PTR(thr, &js_ctx->bw, q);
30595 }
30596 
30597 DUK_LOCAL void duk__enc_buffer(duk_json_enc_ctx *js_ctx, duk_hbuffer *h) {
30598 	duk__enc_buffer_data(js_ctx,
30599 	                     (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(js_ctx->thr->heap, h),
30600 	                     (duk_size_t) DUK_HBUFFER_GET_SIZE(h));
30601 }
30602 #endif  /* DUK_USE_JX || DUK_USE_JC */
30603 
30604 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
30605 DUK_LOCAL void duk__enc_pointer(duk_json_enc_ctx *js_ctx, void *ptr) {
30606 	char buf[64];  /* XXX: how to figure correct size? */
30607 	const char *fmt;
30608 
30609 	DUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible);  /* caller checks */
30610 	DUK_ASSERT(js_ctx->flag_ext_custom_or_compatible);
30611 
30612 	DUK_MEMZERO(buf, sizeof(buf));
30613 
30614 	/* The #ifdef clutter here needs to handle the three cases:
30615 	 * (1) JX+JC, (2) JX only, (3) JC only.
30616 	 */
30617 #if defined(DUK_USE_JX) && defined(DUK_USE_JC)
30618 	if (js_ctx->flag_ext_custom)
30619 #endif
30620 #if defined(DUK_USE_JX)
30621 	{
30622 		fmt = ptr ? "(%p)" : "(null)";
30623 	}
30624 #endif
30625 #if defined(DUK_USE_JX) && defined(DUK_USE_JC)
30626 	else
30627 #endif
30628 #if defined(DUK_USE_JC)
30629 	{
30630 		DUK_ASSERT(js_ctx->flag_ext_compatible);
30631 		fmt = ptr ? "{\"_ptr\":\"%p\"}" : "{\"_ptr\":\"null\"}";
30632 	}
30633 #endif
30634 
30635 	/* When ptr == NULL, the format argument is unused. */
30636 	DUK_SNPRINTF(buf, sizeof(buf) - 1, fmt, ptr);  /* must not truncate */
30637 	DUK__EMIT_CSTR(js_ctx, buf);
30638 }
30639 #endif  /* DUK_USE_JX || DUK_USE_JC */
30640 
30641 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
30642 DUK_LOCAL void duk__enc_bufferobject(duk_json_enc_ctx *js_ctx, duk_hbufferobject *h_bufobj) {
30643 	DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj);
30644 
30645 	if (h_bufobj->buf == NULL || !DUK_HBUFFEROBJECT_VALID_SLICE(h_bufobj)) {
30646 		DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);
30647 	} else {
30648 		/* Handle both full and partial slice (as long as covered). */
30649 		duk__enc_buffer_data(js_ctx,
30650 		                     (duk_uint8_t *) DUK_HBUFFEROBJECT_GET_SLICE_BASE(js_ctx->thr->heap, h_bufobj),
30651 		                     (duk_size_t) h_bufobj->length);
30652 	}
30653 }
30654 #endif  /* DUK_USE_JX || DUK_USE_JC */
30655 
30656 /* Indent helper.  Calling code relies on js_ctx->recursion_depth also being
30657  * directly related to indent depth.
30658  */
30659 #if defined(DUK_USE_PREFER_SIZE)
30660 DUK_LOCAL void duk__enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_int_t depth) {
30661 	DUK_ASSERT(js_ctx->h_gap != NULL);
30662 	DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(js_ctx->h_gap) > 0);  /* caller guarantees */
30663 
30664 	DUK__EMIT_1(js_ctx, 0x0a);
30665 	while (depth-- > 0) {
30666 		DUK__EMIT_HSTR(js_ctx, js_ctx->h_gap);
30667 	}
30668 }
30669 #else  /* DUK_USE_PREFER_SIZE */
30670 DUK_LOCAL void duk__enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_int_t depth) {
30671 	const duk_uint8_t *gap_data;
30672 	duk_size_t gap_len;
30673 	duk_size_t avail_bytes;   /* bytes of indent available for copying */
30674 	duk_size_t need_bytes;    /* bytes of indent still needed */
30675 	duk_uint8_t *p_start;
30676 	duk_uint8_t *p;
30677 
30678 	DUK_ASSERT(js_ctx->h_gap != NULL);
30679 	DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(js_ctx->h_gap) > 0);  /* caller guarantees */
30680 
30681 	DUK__EMIT_1(js_ctx, 0x0a);
30682 	if (DUK_UNLIKELY(depth == 0)) {
30683 		return;
30684 	}
30685 
30686 	/* To handle deeper indents efficiently, make use of copies we've
30687 	 * already emitted.  In effect we can emit a sequence of 1, 2, 4,
30688 	 * 8, etc copies, and then finish the last run.  Byte counters
30689 	 * avoid multiply with gap_len on every loop.
30690 	 */
30691 
30692 	gap_data = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(js_ctx->h_gap);
30693 	gap_len = (duk_size_t) DUK_HSTRING_GET_BYTELEN(js_ctx->h_gap);
30694 	DUK_ASSERT(gap_len > 0);
30695 
30696 	need_bytes = gap_len * depth;
30697 	p = DUK_BW_ENSURE_GETPTR(js_ctx->thr, &js_ctx->bw, need_bytes);
30698 	p_start = p;
30699 
30700 	DUK_MEMCPY((void *) p, (const void *) gap_data, (size_t) gap_len);
30701 	p += gap_len;
30702 	avail_bytes = gap_len;
30703 	DUK_ASSERT(need_bytes >= gap_len);
30704 	need_bytes -= gap_len;
30705 
30706 	while (need_bytes >= avail_bytes) {
30707 		DUK_MEMCPY((void *) p, (const void *) p_start, (size_t) avail_bytes);
30708 		p += avail_bytes;
30709 		need_bytes -= avail_bytes;
30710 		avail_bytes <<= 1;
30711 	}
30712 
30713 	DUK_ASSERT(need_bytes < avail_bytes);  /* need_bytes may be zero */
30714 	DUK_MEMCPY((void *) p, (const void *) p_start, (size_t) need_bytes);
30715 	p += need_bytes;
30716 	/*avail_bytes += need_bytes*/
30717 
30718 	DUK_BW_SET_PTR(js_ctx->thr, &js_ctx->bw, p);
30719 }
30720 #endif  /* DUK_USE_PREFER_SIZE */
30721 
30722 /* Shared entry handling for object/array serialization. */
30723 DUK_LOCAL void duk__enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top) {
30724 	duk_context *ctx = (duk_context *) js_ctx->thr;
30725 	duk_hobject *h_target;
30726 	duk_uint_fast32_t i, n;
30727 
30728 	*entry_top = duk_get_top(ctx);
30729 
30730 	duk_require_stack(ctx, DUK_JSON_ENC_REQSTACK);
30731 
30732 	/* Loop check using a hybrid approach: a fixed-size visited[] array
30733 	 * with overflow in a loop check object.
30734 	 */
30735 
30736 	h_target = duk_get_hobject(ctx, -1);  /* object or array */
30737 	DUK_ASSERT(h_target != NULL);
30738 
30739 	n = js_ctx->recursion_depth;
30740 	if (DUK_UNLIKELY(n > DUK_JSON_ENC_LOOPARRAY)) {
30741 		n = DUK_JSON_ENC_LOOPARRAY;
30742 	}
30743 	for (i = 0; i < n; i++) {
30744 		if (DUK_UNLIKELY(js_ctx->visiting[i] == h_target)) {
30745 			DUK_DD(DUK_DDPRINT("slow path loop detect"));
30746 			DUK_ERROR_TYPE((duk_hthread *) ctx, DUK_STR_CYCLIC_INPUT);
30747 		}
30748 	}
30749 	if (js_ctx->recursion_depth < DUK_JSON_ENC_LOOPARRAY) {
30750 		js_ctx->visiting[js_ctx->recursion_depth] = h_target;
30751 	} else {
30752 		duk_push_sprintf(ctx, DUK_STR_FMT_PTR, (void *) h_target);
30753 		duk_dup_top(ctx);  /* -> [ ... voidp voidp ] */
30754 		if (duk_has_prop(ctx, js_ctx->idx_loop)) {
30755 			DUK_ERROR_TYPE((duk_hthread *) ctx, DUK_STR_CYCLIC_INPUT);
30756 		}
30757 		duk_push_true(ctx);  /* -> [ ... voidp true ] */
30758 		duk_put_prop(ctx, js_ctx->idx_loop);  /* -> [ ... ] */
30759 	}
30760 
30761 	/* C recursion check. */
30762 
30763 	DUK_ASSERT(js_ctx->recursion_depth >= 0);
30764 	DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
30765 	if (js_ctx->recursion_depth >= js_ctx->recursion_limit) {
30766 		DUK_ERROR_RANGE((duk_hthread *) ctx, DUK_STR_JSONENC_RECLIMIT);
30767 	}
30768 	js_ctx->recursion_depth++;
30769 
30770 	DUK_DDD(DUK_DDDPRINT("shared entry finished: top=%ld, loop=%!T",
30771 	                     (long) duk_get_top(ctx), (duk_tval *) duk_get_tval(ctx, js_ctx->idx_loop)));
30772 }
30773 
30774 /* Shared exit handling for object/array serialization. */
30775 DUK_LOCAL void duk__enc_objarr_exit(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top) {
30776 	duk_context *ctx = (duk_context *) js_ctx->thr;
30777 	duk_hobject *h_target;
30778 
30779 	/* C recursion check. */
30780 
30781 	DUK_ASSERT(js_ctx->recursion_depth > 0);
30782 	DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
30783 	js_ctx->recursion_depth--;
30784 
30785 	/* Loop check. */
30786 
30787 	h_target = duk_get_hobject(ctx, *entry_top - 1);  /* original target at entry_top - 1 */
30788 	DUK_ASSERT(h_target != NULL);
30789 
30790 	if (js_ctx->recursion_depth < DUK_JSON_ENC_LOOPARRAY) {
30791 		/* Previous entry was inside visited[], nothing to do. */
30792 	} else {
30793 		duk_push_sprintf(ctx, DUK_STR_FMT_PTR, (void *) h_target);
30794 		duk_del_prop(ctx, js_ctx->idx_loop);  /* -> [ ... ] */
30795 	}
30796 
30797 	/* Restore stack top after unbalanced code paths. */
30798 	duk_set_top(ctx, *entry_top);
30799 
30800 	DUK_DDD(DUK_DDDPRINT("shared entry finished: top=%ld, loop=%!T",
30801 	                     (long) duk_get_top(ctx), (duk_tval *) duk_get_tval(ctx, js_ctx->idx_loop)));
30802 }
30803 
30804 /* The JO(value) operation: encode object.
30805  *
30806  * Stack policy: [ object ] -> [ object ].
30807  */
30808 DUK_LOCAL void duk__enc_object(duk_json_enc_ctx *js_ctx) {
30809 	duk_context *ctx = (duk_context *) js_ctx->thr;
30810 	duk_hstring *h_key;
30811 	duk_idx_t entry_top;
30812 	duk_idx_t idx_obj;
30813 	duk_idx_t idx_keys;
30814 	duk_bool_t emitted;
30815 	duk_uarridx_t arr_len, i;
30816 	duk_size_t prev_size;
30817 
30818 	DUK_DDD(DUK_DDDPRINT("duk__enc_object: obj=%!T", (duk_tval *) duk_get_tval(ctx, -1)));
30819 
30820 	duk__enc_objarr_entry(js_ctx, &entry_top);
30821 
30822 	idx_obj = entry_top - 1;
30823 
30824 	if (js_ctx->idx_proplist >= 0) {
30825 		idx_keys = js_ctx->idx_proplist;
30826 	} else {
30827 		/* XXX: would be nice to enumerate an object at specified index */
30828 		duk_dup(ctx, idx_obj);
30829 		(void) duk_hobject_get_enumerated_keys(ctx, DUK_ENUM_OWN_PROPERTIES_ONLY /*flags*/);  /* [ ... target ] -> [ ... target keys ] */
30830 		idx_keys = duk_require_normalize_index(ctx, -1);
30831 		/* leave stack unbalanced on purpose */
30832 	}
30833 
30834 	DUK_DDD(DUK_DDDPRINT("idx_keys=%ld, h_keys=%!T",
30835 	                     (long) idx_keys, (duk_tval *) duk_get_tval(ctx, idx_keys)));
30836 
30837 	/* Steps 8-10 have been merged to avoid a "partial" variable. */
30838 
30839 	DUK__EMIT_1(js_ctx, DUK_ASC_LCURLY);
30840 
30841 	/* XXX: keys is an internal object with all keys to be processed
30842 	 * in its (gapless) array part.  Because nobody can touch the keys
30843 	 * object, we could iterate its array part directly (keeping in mind
30844 	 * that it can be reallocated).
30845 	 */
30846 
30847 	arr_len = (duk_uarridx_t) duk_get_length(ctx, idx_keys);
30848 	emitted = 0;
30849 	for (i = 0; i < arr_len; i++) {
30850 		duk_get_prop_index(ctx, idx_keys, i);  /* -> [ ... key ] */
30851 
30852 		DUK_DDD(DUK_DDDPRINT("object property loop: holder=%!T, key=%!T",
30853 		                     (duk_tval *) duk_get_tval(ctx, idx_obj),
30854 		                     (duk_tval *) duk_get_tval(ctx, -1)));
30855 
30856 		h_key = duk_get_hstring(ctx, -1);
30857 		DUK_ASSERT(h_key != NULL);
30858 
30859 		prev_size = DUK_BW_GET_SIZE(js_ctx->thr, &js_ctx->bw);
30860 		if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
30861 			duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth);
30862 			duk__enc_key_autoquote(js_ctx, h_key);
30863 			DUK__EMIT_2(js_ctx, DUK_ASC_COLON, DUK_ASC_SPACE);
30864 		} else {
30865 			duk__enc_key_autoquote(js_ctx, h_key);
30866 			DUK__EMIT_1(js_ctx, DUK_ASC_COLON);
30867 		}
30868 
30869 		/* [ ... key ] */
30870 
30871 		if (DUK_UNLIKELY(duk__enc_value(js_ctx, idx_obj) == 0)) {
30872 			/* Value would yield 'undefined', so skip key altogether.
30873 			 * Side effects have already happened.
30874 			 */
30875 			DUK_BW_SET_SIZE(js_ctx->thr, &js_ctx->bw, prev_size);
30876 		} else {
30877 			DUK__EMIT_1(js_ctx, DUK_ASC_COMMA);
30878 			emitted = 1;
30879 		}
30880 
30881 		/* [ ... ] */
30882 	}
30883 
30884 	if (emitted) {
30885 		DUK_ASSERT(*((duk_uint8_t *) DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw) - 1) == DUK_ASC_COMMA);
30886 		DUK__UNEMIT_1(js_ctx);  /* eat trailing comma */
30887 		if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
30888 			DUK_ASSERT(js_ctx->recursion_depth >= 1);
30889 			duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1);
30890 		}
30891 	}
30892 	DUK__EMIT_1(js_ctx, DUK_ASC_RCURLY);
30893 
30894 	duk__enc_objarr_exit(js_ctx, &entry_top);
30895 
30896 	DUK_ASSERT_TOP(ctx, entry_top);
30897 }
30898 
30899 /* The JA(value) operation: encode array.
30900  *
30901  * Stack policy: [ array ] -> [ array ].
30902  */
30903 DUK_LOCAL void duk__enc_array(duk_json_enc_ctx *js_ctx) {
30904 	duk_context *ctx = (duk_context *) js_ctx->thr;
30905 	duk_idx_t entry_top;
30906 	duk_idx_t idx_arr;
30907 	duk_bool_t emitted;
30908 	duk_uarridx_t i, arr_len;
30909 
30910 	DUK_DDD(DUK_DDDPRINT("duk__enc_array: array=%!T",
30911 	                     (duk_tval *) duk_get_tval(ctx, -1)));
30912 
30913 	duk__enc_objarr_entry(js_ctx, &entry_top);
30914 
30915 	idx_arr = entry_top - 1;
30916 
30917 	/* Steps 8-10 have been merged to avoid a "partial" variable. */
30918 
30919 	DUK__EMIT_1(js_ctx, DUK_ASC_LBRACKET);
30920 
30921 	arr_len = (duk_uarridx_t) duk_get_length(ctx, idx_arr);
30922 	emitted = 0;
30923 	for (i = 0; i < arr_len; i++) {
30924 		DUK_DDD(DUK_DDDPRINT("array entry loop: array=%!T, index=%ld, arr_len=%ld",
30925 		                     (duk_tval *) duk_get_tval(ctx, idx_arr),
30926 		                     (long) i, (long) arr_len));
30927 
30928 		if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
30929 			DUK_ASSERT(js_ctx->recursion_depth >= 1);
30930 			duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth);
30931 		}
30932 
30933 		/* XXX: duk_push_uint_string() */
30934 		duk_push_uint(ctx, (duk_uint_t) i);
30935 		duk_to_string(ctx, -1);  /* -> [ ... key ] */
30936 
30937 		/* [ ... key ] */
30938 
30939 		if (DUK_UNLIKELY(duk__enc_value(js_ctx, idx_arr) == 0)) {
30940 			/* Value would normally be omitted, replace with 'null'. */
30941 			DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);
30942 		} else {
30943 			;
30944 		}
30945 
30946 		/* [ ... ] */
30947 
30948 		DUK__EMIT_1(js_ctx, DUK_ASC_COMMA);
30949 		emitted = 1;
30950 	}
30951 
30952 	if (emitted) {
30953 		DUK_ASSERT(*((duk_uint8_t *) DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw) - 1) == DUK_ASC_COMMA);
30954 		DUK__UNEMIT_1(js_ctx);  /* eat trailing comma */
30955 		if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
30956 			DUK_ASSERT(js_ctx->recursion_depth >= 1);
30957 			duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1);
30958 		}
30959 	}
30960 	DUK__EMIT_1(js_ctx, DUK_ASC_RBRACKET);
30961 
30962 	duk__enc_objarr_exit(js_ctx, &entry_top);
30963 
30964 	DUK_ASSERT_TOP(ctx, entry_top);
30965 }
30966 
30967 /* The Str(key, holder) operation.
30968  *
30969  * Stack policy: [ ... key ] -> [ ... ]
30970  */
30971 DUK_LOCAL duk_bool_t duk__enc_value(duk_json_enc_ctx *js_ctx, duk_idx_t idx_holder) {
30972 	duk_context *ctx = (duk_context *) js_ctx->thr;
30973 	duk_hthread *thr = (duk_hthread *) ctx;
30974 	duk_hobject *h_tmp;
30975 	duk_tval *tv;
30976 	duk_tval *tv_holder;
30977 	duk_tval *tv_key;
30978 	duk_small_int_t c;
30979 
30980 	DUK_DDD(DUK_DDDPRINT("duk__enc_value: idx_holder=%ld, holder=%!T, key=%!T",
30981 	                     (long) idx_holder, (duk_tval *) duk_get_tval(ctx, idx_holder),
30982 	                     (duk_tval *) duk_get_tval(ctx, -1)));
30983 
30984 	DUK_UNREF(thr);
30985 
30986 	tv_holder = DUK_GET_TVAL_POSIDX(ctx, idx_holder);
30987 	DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv_holder));
30988 	tv_key = DUK_GET_TVAL_NEGIDX(ctx, -1);
30989 	DUK_ASSERT(DUK_TVAL_IS_STRING(tv_key));
30990 	(void) duk_hobject_getprop(thr, tv_holder, tv_key);
30991 
30992 	/* -> [ ... key val ] */
30993 
30994 	DUK_DDD(DUK_DDDPRINT("value=%!T", (duk_tval *) duk_get_tval(ctx, -1)));
30995 
30996 	h_tmp = duk_get_hobject_or_lfunc_coerce(ctx, -1);
30997 	if (h_tmp != NULL) {
30998 		duk_get_prop_stridx(ctx, -1, DUK_STRIDX_TO_JSON);
30999 		h_tmp = duk_get_hobject_or_lfunc_coerce(ctx, -1);  /* toJSON() can also be a lightfunc */
31000 
31001 		if (h_tmp != NULL && DUK_HOBJECT_IS_CALLABLE(h_tmp)) {
31002 			DUK_DDD(DUK_DDDPRINT("value is object, has callable toJSON() -> call it"));
31003 			/* XXX: duk_dup_unvalidated(ctx, -2) etc. */
31004 			duk_dup(ctx, -2);         /* -> [ ... key val toJSON val ] */
31005 			duk_dup(ctx, -4);         /* -> [ ... key val toJSON val key ] */
31006 			duk_call_method(ctx, 1);  /* -> [ ... key val val' ] */
31007 			duk_remove(ctx, -2);      /* -> [ ... key val' ] */
31008 		} else {
31009 			duk_pop(ctx);             /* -> [ ... key val ] */
31010 		}
31011 	}
31012 
31013 	/* [ ... key val ] */
31014 
31015 	DUK_DDD(DUK_DDDPRINT("value=%!T", (duk_tval *) duk_get_tval(ctx, -1)));
31016 
31017 	if (js_ctx->h_replacer) {
31018 		/* XXX: Here a "slice copy" would be useful. */
31019 		DUK_DDD(DUK_DDDPRINT("replacer is set, call replacer"));
31020 		duk_push_hobject(ctx, js_ctx->h_replacer);  /* -> [ ... key val replacer ] */
31021 		duk_dup(ctx, idx_holder);                   /* -> [ ... key val replacer holder ] */
31022 		duk_dup(ctx, -4);                           /* -> [ ... key val replacer holder key ] */
31023 		duk_dup(ctx, -4);                           /* -> [ ... key val replacer holder key val ] */
31024 		duk_call_method(ctx, 2);                    /* -> [ ... key val val' ] */
31025 		duk_remove(ctx, -2);                        /* -> [ ... key val' ] */
31026 	}
31027 
31028 	/* [ ... key val ] */
31029 
31030 	DUK_DDD(DUK_DDDPRINT("value=%!T", (duk_tval *) duk_get_tval(ctx, -1)));
31031 
31032 	tv = DUK_GET_TVAL_NEGIDX(ctx, -1);
31033 	if (DUK_TVAL_IS_OBJECT(tv)) {
31034 		duk_hobject *h;
31035 
31036 		h = DUK_TVAL_GET_OBJECT(tv);
31037 		DUK_ASSERT(h != NULL);
31038 
31039 		if (DUK_HOBJECT_IS_BUFFEROBJECT(h)) {
31040 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
31041 			duk_hbufferobject *h_bufobj;
31042 			h_bufobj = (duk_hbufferobject *) h;
31043 			DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj);
31044 
31045 			/* Conceptually we'd extract the plain underlying buffer
31046 			 * or its slice and then do a type mask check below to
31047 			 * see if we should reject it.  Do the mask check here
31048 			 * instead to avoid making a copy of the buffer slice.
31049 			 */
31050 
31051 			if (js_ctx->mask_for_undefined & DUK_TYPE_MASK_BUFFER) {
31052 				DUK_DDD(DUK_DDDPRINT("-> bufferobject (-> plain buffer) will result in undefined (type mask check)"));
31053 				goto pop2_undef;
31054 			}
31055 			DUK_DDD(DUK_DDDPRINT("-> bufferobject won't result in undefined, encode directly"));
31056 			duk__enc_bufferobject(js_ctx, h_bufobj);
31057 			goto pop2_emitted;
31058 #else
31059 			DUK_DDD(DUK_DDDPRINT("no JX/JC support, bufferobject/buffer will always result in undefined"));
31060 			goto pop2_undef;
31061 #endif
31062 		} else {
31063 			c = (duk_small_int_t) DUK_HOBJECT_GET_CLASS_NUMBER(h);
31064 			switch ((int) c) {
31065 			case DUK_HOBJECT_CLASS_NUMBER: {
31066 				DUK_DDD(DUK_DDDPRINT("value is a Number object -> coerce with ToNumber()"));
31067 				duk_to_number(ctx, -1);
31068 				/* The coercion potentially invokes user .valueOf() and .toString()
31069 				 * but can't result in a function value because [[DefaultValue]] would
31070 				 * reject such a result: test-dev-json-stringify-coercion-1.js.
31071 				 */
31072 				DUK_ASSERT(!duk_is_callable(ctx, -1));
31073 				break;
31074 			}
31075 			case DUK_HOBJECT_CLASS_STRING: {
31076 				DUK_DDD(DUK_DDDPRINT("value is a String object -> coerce with ToString()"));
31077 				duk_to_string(ctx, -1);
31078 				/* Same coercion behavior as for Number. */
31079 				DUK_ASSERT(!duk_is_callable(ctx, -1));
31080 				break;
31081 			}
31082 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
31083 			case DUK_HOBJECT_CLASS_POINTER:
31084 #endif
31085 			case DUK_HOBJECT_CLASS_BOOLEAN: {
31086 				DUK_DDD(DUK_DDDPRINT("value is a Boolean/Buffer/Pointer object -> get internal value"));
31087 				duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_VALUE);
31088 				duk_remove(ctx, -2);
31089 				break;
31090 			}
31091 			default: {
31092 				/* Normal object which doesn't get automatically coerced to a
31093 				 * primitive value.  Functions are checked for specially.  The
31094 				 * primitive value coercions for Number, String, Pointer, and
31095 				 * Boolean can't result in functions so suffices to check here.
31096 				 */
31097 				DUK_ASSERT(h != NULL);
31098 				if (DUK_HOBJECT_IS_CALLABLE(h)) {
31099 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
31100 					if (js_ctx->flags & (DUK_JSON_FLAG_EXT_CUSTOM |
31101 					                     DUK_JSON_FLAG_EXT_COMPATIBLE)) {
31102 						/* We only get here when doing non-standard JSON encoding */
31103 						DUK_DDD(DUK_DDDPRINT("-> function allowed, serialize to custom format"));
31104 						DUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible);
31105 						DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_function);
31106 						goto pop2_emitted;
31107 					} else {
31108 						DUK_DDD(DUK_DDDPRINT("-> will result in undefined (function)"));
31109 						goto pop2_undef;
31110 					}
31111 #else  /* DUK_USE_JX || DUK_USE_JC */
31112 					DUK_DDD(DUK_DDDPRINT("-> will result in undefined (function)"));
31113 					goto pop2_undef;
31114 #endif  /* DUK_USE_JX || DUK_USE_JC */
31115 				}
31116 			}
31117 			}  /* end switch */
31118 		}
31119 	}
31120 
31121 	/* [ ... key val ] */
31122 
31123 	DUK_DDD(DUK_DDDPRINT("value=%!T", (duk_tval *) duk_get_tval(ctx, -1)));
31124 
31125 	if (duk_check_type_mask(ctx, -1, js_ctx->mask_for_undefined)) {
31126 		/* will result in undefined */
31127 		DUK_DDD(DUK_DDDPRINT("-> will result in undefined (type mask check)"));
31128 		goto pop2_undef;
31129 	}
31130 	tv = DUK_GET_TVAL_NEGIDX(ctx, -1);
31131 
31132 	switch (DUK_TVAL_GET_TAG(tv)) {
31133 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
31134 	/* When JX/JC not in use, the type mask above will avoid this case if needed. */
31135 	case DUK_TAG_UNDEFINED: {
31136 		DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_undefined);
31137 		break;
31138 	}
31139 #endif
31140 	case DUK_TAG_NULL: {
31141 		DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);
31142 		break;
31143 	}
31144 	case DUK_TAG_BOOLEAN: {
31145 		DUK__EMIT_STRIDX(js_ctx, DUK_TVAL_GET_BOOLEAN(tv) ?
31146 		                 DUK_STRIDX_TRUE : DUK_STRIDX_FALSE);
31147 		break;
31148 	}
31149 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
31150 	/* When JX/JC not in use, the type mask above will avoid this case if needed. */
31151 	case DUK_TAG_POINTER: {
31152 		duk__enc_pointer(js_ctx, DUK_TVAL_GET_POINTER(tv));
31153 		break;
31154 	}
31155 #endif  /* DUK_USE_JX || DUK_USE_JC */
31156 	case DUK_TAG_STRING: {
31157 		duk_hstring *h = DUK_TVAL_GET_STRING(tv);
31158 		DUK_ASSERT(h != NULL);
31159 
31160 		duk__enc_quote_string(js_ctx, h);
31161 		break;
31162 	}
31163 	case DUK_TAG_OBJECT: {
31164 		duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
31165 		DUK_ASSERT(h != NULL);
31166 
31167 		/* Function values are handled completely above (including
31168 		 * coercion results):
31169 		 */
31170 		DUK_ASSERT(!DUK_HOBJECT_IS_CALLABLE(h));
31171 
31172 		if (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAY) {
31173 			duk__enc_array(js_ctx);
31174 		} else {
31175 			duk__enc_object(js_ctx);
31176 		}
31177 		break;
31178 	}
31179 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
31180 	/* When JX/JC not in use, the type mask above will avoid this case if needed. */
31181 	case DUK_TAG_BUFFER: {
31182 		duk__enc_buffer(js_ctx, DUK_TVAL_GET_BUFFER(tv));
31183 		break;
31184 	}
31185 #endif  /* DUK_USE_JX || DUK_USE_JC */
31186 	case DUK_TAG_LIGHTFUNC: {
31187 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
31188 		/* We only get here when doing non-standard JSON encoding */
31189 		DUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible);
31190 		DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_function);
31191 #else
31192 		/* Standard JSON omits functions */
31193 		DUK_UNREACHABLE();
31194 #endif
31195 		break;
31196 	}
31197 #if defined(DUK_USE_FASTINT)
31198 	case DUK_TAG_FASTINT:
31199 		/* Number serialization has a significant impact relative to
31200 		 * other fast path code, so careful fast path for fastints.
31201 		 */
31202 		duk__enc_fastint_tval(js_ctx, tv);
31203 		break;
31204 #endif
31205 	default: {
31206 		/* number */
31207 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
31208 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
31209 		/* XXX: A fast path for usual integers would be useful when
31210 		 * fastint support is not enabled.
31211 		 */
31212 		duk__enc_double(js_ctx);
31213 		break;
31214 	}
31215 	}
31216 
31217  pop2_emitted:
31218 	duk_pop_2(ctx); /* [ ... key val ] -> [ ... ] */
31219 	return 1;  /* emitted */
31220 
31221  pop2_undef:
31222 	duk_pop_2(ctx);  /* [ ... key val ] -> [ ... ] */
31223 	return 0;  /* not emitted */
31224 }
31225 
31226 /* E5 Section 15.12.3, main algorithm, step 4.b.ii steps 1-4. */
31227 DUK_LOCAL duk_bool_t duk__enc_allow_into_proplist(duk_tval *tv) {
31228 	duk_hobject *h;
31229 	duk_small_int_t c;
31230 
31231 	DUK_ASSERT(tv != NULL);
31232 	if (DUK_TVAL_IS_STRING(tv) || DUK_TVAL_IS_NUMBER(tv)) {
31233 		return 1;
31234 	} else if (DUK_TVAL_IS_OBJECT(tv)) {
31235 		h = DUK_TVAL_GET_OBJECT(tv);
31236 		DUK_ASSERT(h != NULL);
31237 		c = (duk_small_int_t) DUK_HOBJECT_GET_CLASS_NUMBER(h);
31238 		if (c == DUK_HOBJECT_CLASS_STRING || c == DUK_HOBJECT_CLASS_NUMBER) {
31239 			return 1;
31240 		}
31241 	}
31242 
31243 	return 0;
31244 }
31245 
31246 /*
31247  *  JSON.stringify() fast path
31248  *
31249  *  Otherwise supports full JSON, JX, and JC features, but bails out on any
31250  *  possible side effect which might change the value being serialized.  The
31251  *  fast path can take advantage of the fact that the value being serialized
31252  *  is unchanged so that we can walk directly through property tables etc.
31253  */
31254 
31255 #if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
31256 DUK_LOCAL duk_bool_t duk__json_stringify_fast_value(duk_json_enc_ctx *js_ctx, duk_tval *tv) {
31257 	duk_uint_fast32_t i, n;
31258 
31259 	DUK_DDD(DUK_DDDPRINT("stringify fast: %!T", tv));
31260 
31261 	DUK_ASSERT(js_ctx != NULL);
31262 	DUK_ASSERT(js_ctx->thr != NULL);
31263 
31264 #if 0 /* disabled for now */
31265  restart_match:
31266 #endif
31267 
31268 	DUK_ASSERT(tv != NULL);
31269 
31270 	switch (DUK_TVAL_GET_TAG(tv)) {
31271 	case DUK_TAG_UNDEFINED: {
31272 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
31273 		if (js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible) {
31274 			DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_undefined);
31275 			break;
31276 		} else {
31277 			goto emit_undefined;
31278 		}
31279 #else
31280 		goto emit_undefined;
31281 #endif
31282 	}
31283 	case DUK_TAG_NULL: {
31284 		DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);
31285 		break;
31286 	}
31287 	case DUK_TAG_BOOLEAN: {
31288 		DUK__EMIT_STRIDX(js_ctx, DUK_TVAL_GET_BOOLEAN(tv) ?
31289 		                 DUK_STRIDX_TRUE : DUK_STRIDX_FALSE);
31290 		break;
31291 	}
31292 	case DUK_TAG_STRING: {
31293 		duk_hstring *h;
31294 
31295 		h = DUK_TVAL_GET_STRING(tv);
31296 		DUK_ASSERT(h != NULL);
31297 		duk__enc_quote_string(js_ctx, h);
31298 		break;
31299 	}
31300 	case DUK_TAG_OBJECT: {
31301 		duk_hobject *obj;
31302 		duk_tval *tv_val;
31303 		duk_bool_t emitted = 0;
31304 		duk_uint32_t c_bit, c_all, c_array, c_unbox, c_undef,
31305 		             c_func, c_bufobj, c_object;
31306 
31307 		/* For objects JSON.stringify() only looks for own, enumerable
31308 		 * properties which is nice for the fast path here.
31309 		 *
31310 		 * For arrays JSON.stringify() uses [[Get]] so it will actually
31311 		 * inherit properties during serialization!  This fast path
31312 		 * supports gappy arrays as long as there's no actual inherited
31313 		 * property (which might be a getter etc).
31314 		 *
31315 		 * Since recursion only happens for objects, we can have both
31316 		 * recursion and loop checks here.  We use a simple, depth-limited
31317 		 * loop check in the fast path because the object-based tracking
31318 		 * is very slow (when tested, it accounted for 50% of fast path
31319 		 * execution time for input data with a lot of small objects!).
31320 		 */
31321 
31322 		/* XXX: for real world code, could just ignore array inheritance
31323 		 * and only look at array own properties.
31324 		 */
31325 
31326 		/* We rely on a few object flag / class number relationships here,
31327 		 * assert for them.
31328 		 */
31329 
31330 		obj = DUK_TVAL_GET_OBJECT(tv);
31331 		DUK_ASSERT(obj != NULL);
31332 		DUK_ASSERT_HOBJECT_VALID(obj);
31333 
31334 		/* Once recursion depth is increased, exit path must decrease
31335 		 * it (though it's OK to abort the fast path).
31336 		 */
31337 
31338 		DUK_ASSERT(js_ctx->recursion_depth >= 0);
31339 		DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
31340 		if (js_ctx->recursion_depth >= js_ctx->recursion_limit) {
31341 			DUK_DD(DUK_DDPRINT("fast path recursion limit"));
31342 			DUK_ERROR_RANGE(js_ctx->thr, DUK_STR_JSONDEC_RECLIMIT);
31343 		}
31344 
31345 		for (i = 0, n = (duk_uint_fast32_t) js_ctx->recursion_depth; i < n; i++) {
31346 			if (DUK_UNLIKELY(js_ctx->visiting[i] == obj)) {
31347 				DUK_DD(DUK_DDPRINT("fast path loop detect"));
31348 				DUK_ERROR_TYPE(js_ctx->thr, DUK_STR_CYCLIC_INPUT);
31349 			}
31350 		}
31351 
31352 		/* Guaranteed by recursion_limit setup so we don't have to
31353 		 * check twice.
31354 		 */
31355 		DUK_ASSERT(js_ctx->recursion_depth < DUK_JSON_ENC_LOOPARRAY);
31356 		js_ctx->visiting[js_ctx->recursion_depth] = obj;
31357 		js_ctx->recursion_depth++;
31358 
31359 		/* If object has a .toJSON() property, we can't be certain
31360 		 * that it wouldn't mutate any value arbitrarily, so bail
31361 		 * out of the fast path.
31362 		 *
31363 		 * If an object is a Proxy we also can't avoid side effects
31364 		 * so abandon.
31365 		 */
31366 		/* XXX: non-callable .toJSON() doesn't need to cause an abort
31367 		 * but does at the moment, probably not worth fixing.
31368 		 */
31369 		if (duk_hobject_hasprop_raw(js_ctx->thr, obj, DUK_HTHREAD_STRING_TO_JSON(js_ctx->thr)) ||
31370 		    DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(obj)) {
31371 			DUK_DD(DUK_DDPRINT("object has a .toJSON property or object is a Proxy, abort fast path"));
31372 			goto abort_fastpath;
31373 		}
31374 
31375 		/* We could use a switch-case for the class number but it turns out
31376 		 * a small if-else ladder on class masks is better.  The if-ladder
31377 		 * should be in order of relevancy.
31378 		 */
31379 
31380 		/* XXX: move masks to js_ctx? they don't change during one
31381 		 * fast path invocation.
31382 		 */
31383 		DUK_ASSERT(DUK_HOBJECT_CLASS_MAX <= 31);
31384 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
31385 		if (js_ctx->flag_ext_custom_or_compatible) {
31386 			c_all = DUK_HOBJECT_CMASK_ALL;
31387 			c_array = DUK_HOBJECT_CMASK_ARRAY;
31388 			c_unbox = DUK_HOBJECT_CMASK_NUMBER |
31389 			          DUK_HOBJECT_CMASK_STRING |
31390 			          DUK_HOBJECT_CMASK_BOOLEAN |
31391 			          DUK_HOBJECT_CMASK_POINTER;
31392 			c_func = DUK_HOBJECT_CMASK_FUNCTION;
31393 			c_bufobj = DUK_HOBJECT_CMASK_ALL_BUFFEROBJECTS;
31394 			c_undef = 0;
31395 			c_object = c_all & ~(c_array | c_unbox | c_func | c_bufobj | c_undef);
31396 		}
31397 		else
31398 #endif
31399 		{
31400 			c_all = DUK_HOBJECT_CMASK_ALL;
31401 			c_array = DUK_HOBJECT_CMASK_ARRAY;
31402 			c_unbox = DUK_HOBJECT_CMASK_NUMBER |
31403 			          DUK_HOBJECT_CMASK_STRING |
31404 			          DUK_HOBJECT_CMASK_BOOLEAN;
31405 			c_func = 0;
31406 			c_bufobj = 0;
31407 			c_undef = DUK_HOBJECT_CMASK_FUNCTION |
31408 			          DUK_HOBJECT_CMASK_POINTER |
31409 			          DUK_HOBJECT_CMASK_ALL_BUFFEROBJECTS;
31410 			c_object = c_all & ~(c_array | c_unbox | c_func | c_bufobj | c_undef);
31411 		}
31412 
31413 		c_bit = DUK_HOBJECT_GET_CLASS_MASK(obj);
31414 		if (c_bit & c_object) {
31415 			/* All other object types. */
31416 			DUK__EMIT_1(js_ctx, DUK_ASC_LCURLY);
31417 
31418 			/* A non-Array object should not have an array part in practice.
31419 			 * But since it is supported internally (and perhaps used at some
31420 			 * point), check and abandon if that's the case.
31421 			 */
31422 			if (DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
31423 				DUK_DD(DUK_DDPRINT("non-Array object has array part, abort fast path"));
31424 				goto abort_fastpath;
31425 			}
31426 
31427 			for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(obj); i++) {
31428 				duk_hstring *k;
31429 				duk_size_t prev_size;
31430 
31431 				k = DUK_HOBJECT_E_GET_KEY(js_ctx->thr->heap, obj, i);
31432 				if (!k) {
31433 					continue;
31434 				}
31435 				if (!DUK_HOBJECT_E_SLOT_IS_ENUMERABLE(js_ctx->thr->heap, obj, i)) {
31436 					continue;
31437 				}
31438 				if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(js_ctx->thr->heap, obj, i)) {
31439 					/* Getter might have arbitrary side effects,
31440 					 * so bail out.
31441 					 */
31442 					DUK_DD(DUK_DDPRINT("property is an accessor, abort fast path"));
31443 					goto abort_fastpath;
31444 				}
31445 				if (DUK_HSTRING_HAS_INTERNAL(k)) {
31446 					continue;
31447 				}
31448 
31449 				tv_val = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(js_ctx->thr->heap, obj, i);
31450 
31451 				prev_size = DUK_BW_GET_SIZE(js_ctx->thr, &js_ctx->bw);
31452 				if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
31453 					duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth);
31454 					duk__enc_key_autoquote(js_ctx, k);
31455 					DUK__EMIT_2(js_ctx, DUK_ASC_COLON, DUK_ASC_SPACE);
31456 				} else {
31457 					duk__enc_key_autoquote(js_ctx, k);
31458 					DUK__EMIT_1(js_ctx, DUK_ASC_COLON);
31459 				}
31460 
31461 				if (duk__json_stringify_fast_value(js_ctx, tv_val) == 0) {
31462 					DUK_DD(DUK_DDPRINT("prop value not supported, rewind key and colon"));
31463 					DUK_BW_SET_SIZE(js_ctx->thr, &js_ctx->bw, prev_size);
31464 				} else {
31465 					DUK__EMIT_1(js_ctx, DUK_ASC_COMMA);
31466 					emitted = 1;
31467 				}
31468 			}
31469 
31470 			/* If any non-Array value had enumerable virtual own
31471 			 * properties, they should be serialized here.  Standard
31472 			 * types don't.
31473 			 */
31474 
31475 			if (emitted) {
31476 				DUK_ASSERT(*((duk_uint8_t *) DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw) - 1) == DUK_ASC_COMMA);
31477 				DUK__UNEMIT_1(js_ctx);  /* eat trailing comma */
31478 				if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
31479 					DUK_ASSERT(js_ctx->recursion_depth >= 1);
31480 					duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1);
31481 				}
31482 			}
31483 			DUK__EMIT_1(js_ctx, DUK_ASC_RCURLY);
31484 		} else if (c_bit & c_array) {
31485 			duk_uint_fast32_t arr_len;
31486 			duk_uint_fast32_t asize;
31487 
31488 			DUK__EMIT_1(js_ctx, DUK_ASC_LBRACKET);
31489 
31490 			/* Assume arrays are dense in the fast path. */
31491 			if (!DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
31492 				DUK_DD(DUK_DDPRINT("Array object is sparse, abort fast path"));
31493 				goto abort_fastpath;
31494 			}
31495 
31496 			arr_len = (duk_uint_fast32_t) duk_hobject_get_length(js_ctx->thr, obj);
31497 			asize = (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(obj);
31498 			if (arr_len > asize) {
31499 				/* Array length is larger than 'asize'.  This shouldn't
31500 				 * happen in practice.  Bail out just in case.
31501 				 */
31502 				DUK_DD(DUK_DDPRINT("arr_len > asize, abort fast path"));
31503 				goto abort_fastpath;
31504 			}
31505 			/* Array part may be larger than 'length'; if so, iterate
31506 			 * only up to array 'length'.
31507 			 */
31508 			for (i = 0; i < arr_len; i++) {
31509 				DUK_ASSERT(i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(obj));
31510 
31511 				tv_val = DUK_HOBJECT_A_GET_VALUE_PTR(js_ctx->thr->heap, obj, i);
31512 
31513 				if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
31514 					duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth);
31515 				}
31516 
31517 				if (DUK_UNLIKELY(DUK_TVAL_IS_UNUSED(tv_val))) {
31518 					/* Gap in array; check for inherited property,
31519 					 * bail out if one exists.  This should be enough
31520 					 * to support gappy arrays for all practical code.
31521 					 */
31522 					duk_hstring *h_tmp;
31523 					duk_bool_t has_inherited;
31524 
31525 					/* XXX: refactor into an internal helper, pretty awkward */
31526 					duk_push_uint((duk_context *) js_ctx->thr, (duk_uint_t) i);
31527 					h_tmp = duk_to_hstring((duk_context *) js_ctx->thr, -1);
31528 					DUK_ASSERT(h_tmp != NULL);
31529 					has_inherited = duk_hobject_hasprop_raw(js_ctx->thr, obj, h_tmp);
31530 					duk_pop((duk_context *) js_ctx->thr);
31531 
31532 					if (has_inherited) {
31533 						DUK_D(DUK_DPRINT("gap in array, conflicting inherited property, abort fast path"));
31534 						goto abort_fastpath;
31535 					}
31536 
31537 					/* Ordinary gap, undefined encodes to 'null' in
31538 					 * standard JSON (and no JX/JC support here now).
31539 					 */
31540 					DUK_D(DUK_DPRINT("gap in array, no conflicting inherited property, remain on fast path"));
31541 #if defined(DUK_USE_JX)
31542 					DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_undefined);
31543 #else
31544 					DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);
31545 #endif
31546 				} else {
31547 					if (duk__json_stringify_fast_value(js_ctx, tv_val) == 0) {
31548 						DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);
31549 					}
31550 				}
31551 
31552 				DUK__EMIT_1(js_ctx, DUK_ASC_COMMA);
31553 				emitted = 1;
31554 			}
31555 
31556 			if (emitted) {
31557 				DUK_ASSERT(*((duk_uint8_t *) DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw) - 1) == DUK_ASC_COMMA);
31558 				DUK__UNEMIT_1(js_ctx);  /* eat trailing comma */
31559 				if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
31560 					DUK_ASSERT(js_ctx->recursion_depth >= 1);
31561 					duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1);
31562 				}
31563 			}
31564 			DUK__EMIT_1(js_ctx, DUK_ASC_RBRACKET);
31565 		} else if (c_bit & c_unbox) {
31566 			/* Certain boxed types are required to go through
31567 			 * automatic unboxing.  Rely on internal value being
31568 			 * sane (to avoid infinite recursion).
31569 			 */
31570 #if 1
31571 			/* The code below is incorrect if .toString() or .valueOf() have
31572 			 * have been overridden.  The correct approach would be to look up
31573 			 * the method(s) and if they resolve to the built-in function we
31574 			 * can safely bypass it and look up the internal value directly.
31575 			 * Unimplemented for now, abort fast path for boxed values.
31576 			 */
31577 			goto abort_fastpath;
31578 #else  /* disabled */
31579 			/* Disabled until fixed, see above. */
31580 			duk_tval *tv_internal;
31581 
31582 			DUK_DD(DUK_DDPRINT("auto unboxing in fast path"));
31583 
31584 			tv_internal = duk_hobject_get_internal_value_tval_ptr(js_ctx->thr->heap, obj);
31585 			DUK_ASSERT(tv_internal != NULL);
31586 			DUK_ASSERT(DUK_TVAL_IS_STRING(tv_internal) ||
31587 			           DUK_TVAL_IS_NUMBER(tv_internal) ||
31588 			           DUK_TVAL_IS_BOOLEAN(tv_internal) ||
31589 			           DUK_TVAL_IS_POINTER(tv_internal));
31590 
31591 			tv = tv_internal;
31592 			DUK_ASSERT(js_ctx->recursion_depth > 0);
31593 			js_ctx->recursion_depth--;  /* required to keep recursion depth correct */
31594 			goto restart_match;
31595 #endif  /* disabled */
31596 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
31597 		} else if (c_bit & c_func) {
31598 			DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_function);
31599 		} else if (c_bit & c_bufobj) {
31600 			duk__enc_bufferobject(js_ctx, (duk_hbufferobject *) obj);
31601 #endif
31602 		} else {
31603 			DUK_ASSERT((c_bit & c_undef) != 0);
31604 
31605 			/* Must decrease recursion depth before returning. */
31606 			DUK_ASSERT(js_ctx->recursion_depth > 0);
31607 			DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
31608 			js_ctx->recursion_depth--;
31609 			goto emit_undefined;
31610 		}
31611 
31612 		DUK_ASSERT(js_ctx->recursion_depth > 0);
31613 		DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
31614 		js_ctx->recursion_depth--;
31615 		break;
31616 	}
31617 	case DUK_TAG_BUFFER: {
31618 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
31619 		if (js_ctx->flag_ext_custom_or_compatible) {
31620 			duk__enc_buffer(js_ctx, DUK_TVAL_GET_BUFFER(tv));
31621 			break;
31622 		} else {
31623 			goto emit_undefined;
31624 		}
31625 #else
31626 		goto emit_undefined;
31627 #endif
31628 	}
31629 	case DUK_TAG_POINTER: {
31630 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
31631 		if (js_ctx->flag_ext_custom_or_compatible) {
31632 			duk__enc_pointer(js_ctx, DUK_TVAL_GET_POINTER(tv));
31633 			break;
31634 		} else {
31635 			goto emit_undefined;
31636 		}
31637 #else
31638 		goto emit_undefined;
31639 #endif
31640 	}
31641 	case DUK_TAG_LIGHTFUNC: {
31642 		/* A lightfunc might also inherit a .toJSON() so just bail out. */
31643 		/* XXX: Could just lookup .toJSON() and continue in fast path,
31644 		 * as it would almost never be defined.
31645 		 */
31646 		DUK_DD(DUK_DDPRINT("value is a lightfunc, abort fast path"));
31647 		goto abort_fastpath;
31648 	}
31649 #if defined(DUK_USE_FASTINT)
31650 	case DUK_TAG_FASTINT: {
31651 		/* Number serialization has a significant impact relative to
31652 		 * other fast path code, so careful fast path for fastints.
31653 		 */
31654 		duk__enc_fastint_tval(js_ctx, tv);
31655 		break;
31656 	}
31657 #endif
31658 	default: {
31659 		/* XXX: A fast path for usual integers would be useful when
31660 		 * fastint support is not enabled.
31661 		 */
31662 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
31663 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
31664 
31665 		/* XXX: Stack discipline is annoying, could be changed in numconv. */
31666 		duk_push_tval((duk_context *) js_ctx->thr, tv);
31667 		duk__enc_double(js_ctx);
31668 		duk_pop((duk_context *) js_ctx->thr);
31669 
31670 #if 0
31671 		/* Could also rely on native sprintf(), but it will handle
31672 		 * values like NaN, Infinity, -0, exponent notation etc in
31673 		 * a JSON-incompatible way.
31674 		 */
31675 		duk_double_t d;
31676 		char buf[64];
31677 
31678 		DUK_ASSERT(DUK_TVAL_IS_DOUBLE(tv));
31679 		d = DUK_TVAL_GET_DOUBLE(tv);
31680 		DUK_SPRINTF(buf, "%lg", d);
31681 		DUK__EMIT_CSTR(js_ctx, buf);
31682 #endif
31683 	}
31684 	}
31685 	return 1;  /* not undefined */
31686 
31687  emit_undefined:
31688 	return 0;  /* value was undefined/unsupported */
31689 
31690  abort_fastpath:
31691 	/* Error message doesn't matter: the error is ignored anyway. */
31692 	DUK_DD(DUK_DDPRINT("aborting fast path"));
31693 	DUK_ERROR_INTERNAL_DEFMSG(js_ctx->thr);
31694 	return 0;  /* unreachable */
31695 }
31696 
31697 DUK_LOCAL duk_ret_t duk__json_stringify_fast(duk_context *ctx) {
31698 	duk_json_enc_ctx *js_ctx;
31699 	duk_tval *tv;
31700 
31701 	DUK_ASSERT(ctx != NULL);
31702 	tv = DUK_GET_TVAL_NEGIDX(ctx, -2);
31703 	DUK_ASSERT(DUK_TVAL_IS_POINTER(tv));
31704 	js_ctx = (duk_json_enc_ctx *) DUK_TVAL_GET_POINTER(tv);
31705 	DUK_ASSERT(js_ctx != NULL);
31706 
31707 	tv = DUK_GET_TVAL_NEGIDX(ctx, -1);
31708 	if (duk__json_stringify_fast_value(js_ctx, tv) == 0) {
31709 		DUK_DD(DUK_DDPRINT("top level value not supported, fail fast path"));
31710 		return DUK_RET_ERROR;  /* error message doesn't matter, ignored anyway */
31711 	}
31712 
31713 	return 0;
31714 }
31715 #endif  /* DUK_USE_JSON_STRINGIFY_FASTPATH */
31716 
31717 /*
31718  *  Top level wrappers
31719  */
31720 
31721 DUK_INTERNAL
31722 void duk_bi_json_parse_helper(duk_context *ctx,
31723                               duk_idx_t idx_value,
31724                               duk_idx_t idx_reviver,
31725                               duk_small_uint_t flags) {
31726 	duk_hthread *thr = (duk_hthread *) ctx;
31727 	duk_json_dec_ctx js_ctx_alloc;
31728 	duk_json_dec_ctx *js_ctx = &js_ctx_alloc;
31729 	duk_hstring *h_text;
31730 #ifdef DUK_USE_ASSERTIONS
31731 	duk_idx_t entry_top = duk_get_top(ctx);
31732 #endif
31733 
31734 	/* negative top-relative indices not allowed now */
31735 	DUK_ASSERT(idx_value == DUK_INVALID_INDEX || idx_value >= 0);
31736 	DUK_ASSERT(idx_reviver == DUK_INVALID_INDEX || idx_reviver >= 0);
31737 
31738 	DUK_DDD(DUK_DDDPRINT("JSON parse start: text=%!T, reviver=%!T, flags=0x%08lx, stack_top=%ld",
31739 	                     (duk_tval *) duk_get_tval(ctx, idx_value),
31740 	                     (duk_tval *) duk_get_tval(ctx, idx_reviver),
31741 	                     (unsigned long) flags,
31742 	                     (long) duk_get_top(ctx)));
31743 
31744 	DUK_MEMZERO(&js_ctx_alloc, sizeof(js_ctx_alloc));
31745 	js_ctx->thr = thr;
31746 #ifdef DUK_USE_EXPLICIT_NULL_INIT
31747 	/* nothing now */
31748 #endif
31749 	js_ctx->recursion_limit = DUK_USE_JSON_DEC_RECLIMIT;
31750 	DUK_ASSERT(js_ctx->recursion_depth == 0);
31751 
31752 	/* Flag handling currently assumes that flags are consistent.  This is OK
31753 	 * because the call sites are now strictly controlled.
31754 	 */
31755 
31756 	js_ctx->flags = flags;
31757 #if defined(DUK_USE_JX)
31758 	js_ctx->flag_ext_custom = flags & DUK_JSON_FLAG_EXT_CUSTOM;
31759 #endif
31760 #if defined(DUK_USE_JC)
31761 	js_ctx->flag_ext_compatible = flags & DUK_JSON_FLAG_EXT_COMPATIBLE;
31762 #endif
31763 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
31764 	js_ctx->flag_ext_custom_or_compatible = flags & (DUK_JSON_FLAG_EXT_CUSTOM | DUK_JSON_FLAG_EXT_COMPATIBLE);
31765 #endif
31766 
31767 	h_text = duk_to_hstring(ctx, idx_value);  /* coerce in-place */
31768 	DUK_ASSERT(h_text != NULL);
31769 
31770 	/* JSON parsing code is allowed to read [p_start,p_end]: p_end is
31771 	 * valid and points to the string NUL terminator (which is always
31772 	 * guaranteed for duk_hstrings.
31773 	 */
31774 	js_ctx->p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_text);
31775 	js_ctx->p = js_ctx->p_start;
31776 	js_ctx->p_end = ((const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_text)) +
31777 	                DUK_HSTRING_GET_BYTELEN(h_text);
31778 	DUK_ASSERT(*(js_ctx->p_end) == 0x00);
31779 
31780 	duk__dec_value(js_ctx);  /* -> [ ... value ] */
31781 
31782 	/* Trailing whitespace has been eaten by duk__dec_value(), so if
31783 	 * we're not at end of input here, it's a SyntaxError.
31784 	 */
31785 
31786 	if (js_ctx->p != js_ctx->p_end) {
31787 		duk__dec_syntax_error(js_ctx);
31788 	}
31789 
31790 	if (duk_is_callable(ctx, idx_reviver)) {
31791 		DUK_DDD(DUK_DDDPRINT("applying reviver: %!T",
31792 		                     (duk_tval *) duk_get_tval(ctx, idx_reviver)));
31793 
31794 		js_ctx->idx_reviver = idx_reviver;
31795 
31796 		duk_push_object(ctx);
31797 		duk_dup(ctx, -2);  /* -> [ ... val root val ] */
31798 		duk_put_prop_stridx(ctx, -2, DUK_STRIDX_EMPTY_STRING);  /* default attrs ok */
31799 		duk_push_hstring_stridx(ctx, DUK_STRIDX_EMPTY_STRING);  /* -> [ ... val root "" ] */
31800 
31801 		DUK_DDD(DUK_DDDPRINT("start reviver walk, root=%!T, name=%!T",
31802 		                     (duk_tval *) duk_get_tval(ctx, -2),
31803 		                     (duk_tval *) duk_get_tval(ctx, -1)));
31804 
31805 		duk__dec_reviver_walk(js_ctx);  /* [ ... val root "" ] -> [ ... val val' ] */
31806 		duk_remove(ctx, -2);            /* -> [ ... val' ] */
31807 	} else {
31808 		DUK_DDD(DUK_DDDPRINT("reviver does not exist or is not callable: %!T",
31809 		                     (duk_tval *) duk_get_tval(ctx, idx_reviver)));
31810 	}
31811 
31812 	/* Final result is at stack top. */
31813 
31814 	DUK_DDD(DUK_DDDPRINT("JSON parse end: text=%!T, reviver=%!T, flags=0x%08lx, result=%!T, stack_top=%ld",
31815 	                     (duk_tval *) duk_get_tval(ctx, idx_value),
31816 	                     (duk_tval *) duk_get_tval(ctx, idx_reviver),
31817 	                     (unsigned long) flags,
31818 	                     (duk_tval *) duk_get_tval(ctx, -1),
31819 	                     (long) duk_get_top(ctx)));
31820 
31821 	DUK_ASSERT(duk_get_top(ctx) == entry_top + 1);
31822 }
31823 
31824 DUK_INTERNAL
31825 void duk_bi_json_stringify_helper(duk_context *ctx,
31826                                   duk_idx_t idx_value,
31827                                   duk_idx_t idx_replacer,
31828                                   duk_idx_t idx_space,
31829                                   duk_small_uint_t flags) {
31830 	duk_hthread *thr = (duk_hthread *) ctx;
31831 	duk_json_enc_ctx js_ctx_alloc;
31832 	duk_json_enc_ctx *js_ctx = &js_ctx_alloc;
31833 	duk_hobject *h;
31834 	duk_idx_t idx_holder;
31835 	duk_idx_t entry_top;
31836 
31837 	/* negative top-relative indices not allowed now */
31838 	DUK_ASSERT(idx_value == DUK_INVALID_INDEX || idx_value >= 0);
31839 	DUK_ASSERT(idx_replacer == DUK_INVALID_INDEX || idx_replacer >= 0);
31840 	DUK_ASSERT(idx_space == DUK_INVALID_INDEX || idx_space >= 0);
31841 
31842 	DUK_DDD(DUK_DDDPRINT("JSON stringify start: value=%!T, replacer=%!T, space=%!T, flags=0x%08lx, stack_top=%ld",
31843 	                     (duk_tval *) duk_get_tval(ctx, idx_value),
31844 	                     (duk_tval *) duk_get_tval(ctx, idx_replacer),
31845 	                     (duk_tval *) duk_get_tval(ctx, idx_space),
31846 	                     (unsigned long) flags,
31847 	                     (long) duk_get_top(ctx)));
31848 
31849 	entry_top = duk_get_top(ctx);
31850 
31851 	/*
31852 	 *  Context init
31853 	 */
31854 
31855 	DUK_MEMZERO(&js_ctx_alloc, sizeof(js_ctx_alloc));
31856 	js_ctx->thr = thr;
31857 #ifdef DUK_USE_EXPLICIT_NULL_INIT
31858 	js_ctx->h_replacer = NULL;
31859 	js_ctx->h_gap = NULL;
31860 #endif
31861 	js_ctx->idx_proplist = -1;
31862 
31863 	/* Flag handling currently assumes that flags are consistent.  This is OK
31864 	 * because the call sites are now strictly controlled.
31865 	 */
31866 
31867 	js_ctx->flags = flags;
31868 	js_ctx->flag_ascii_only = flags & DUK_JSON_FLAG_ASCII_ONLY;
31869 	js_ctx->flag_avoid_key_quotes = flags & DUK_JSON_FLAG_AVOID_KEY_QUOTES;
31870 #ifdef DUK_USE_JX
31871 	js_ctx->flag_ext_custom = flags & DUK_JSON_FLAG_EXT_CUSTOM;
31872 #endif
31873 #ifdef DUK_USE_JC
31874 	js_ctx->flag_ext_compatible = flags & DUK_JSON_FLAG_EXT_COMPATIBLE;
31875 #endif
31876 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
31877 	js_ctx->flag_ext_custom_or_compatible = flags & (DUK_JSON_FLAG_EXT_CUSTOM | DUK_JSON_FLAG_EXT_COMPATIBLE);
31878 #endif
31879 
31880 	/* The #ifdef clutter here handles the JX/JC enable/disable
31881 	 * combinations properly.
31882 	 */
31883 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
31884 	js_ctx->stridx_custom_undefined = DUK_STRIDX_LC_NULL;  /* standard JSON; array gaps */
31885 #if defined(DUK_USE_JX)
31886 	if (flags & DUK_JSON_FLAG_EXT_CUSTOM) {
31887 		js_ctx->stridx_custom_undefined = DUK_STRIDX_LC_UNDEFINED;
31888 		js_ctx->stridx_custom_nan = DUK_STRIDX_NAN;
31889 		js_ctx->stridx_custom_neginf = DUK_STRIDX_MINUS_INFINITY;
31890 		js_ctx->stridx_custom_posinf = DUK_STRIDX_INFINITY;
31891 		js_ctx->stridx_custom_function =
31892 		        (flags & DUK_JSON_FLAG_AVOID_KEY_QUOTES) ?
31893 		                DUK_STRIDX_JSON_EXT_FUNCTION2 :
31894 		                DUK_STRIDX_JSON_EXT_FUNCTION1;
31895 	}
31896 #endif  /* DUK_USE_JX */
31897 #if defined(DUK_USE_JX) && defined(DUK_USE_JC)
31898 	else
31899 #endif  /* DUK_USE_JX && DUK_USE_JC */
31900 #if defined(DUK_USE_JC)
31901 	if (js_ctx->flags & DUK_JSON_FLAG_EXT_COMPATIBLE) {
31902 		js_ctx->stridx_custom_undefined = DUK_STRIDX_JSON_EXT_UNDEFINED;
31903 		js_ctx->stridx_custom_nan = DUK_STRIDX_JSON_EXT_NAN;
31904 		js_ctx->stridx_custom_neginf = DUK_STRIDX_JSON_EXT_NEGINF;
31905 		js_ctx->stridx_custom_posinf = DUK_STRIDX_JSON_EXT_POSINF;
31906 		js_ctx->stridx_custom_function = DUK_STRIDX_JSON_EXT_FUNCTION1;
31907 	}
31908 #endif  /* DUK_USE_JC */
31909 #endif  /* DUK_USE_JX || DUK_USE_JC */
31910 
31911 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
31912 	if (js_ctx->flags & (DUK_JSON_FLAG_EXT_CUSTOM |
31913 	                     DUK_JSON_FLAG_EXT_COMPATIBLE)) {
31914 		DUK_ASSERT(js_ctx->mask_for_undefined == 0);  /* already zero */
31915 	}
31916 	else
31917 #endif  /* DUK_USE_JX || DUK_USE_JC */
31918 	{
31919 		js_ctx->mask_for_undefined = DUK_TYPE_MASK_UNDEFINED |
31920 		                             DUK_TYPE_MASK_POINTER |
31921 		                             DUK_TYPE_MASK_BUFFER |
31922 		                             DUK_TYPE_MASK_LIGHTFUNC;
31923 	}
31924 
31925 	DUK_BW_INIT_PUSHBUF(thr, &js_ctx->bw, DUK__JSON_STRINGIFY_BUFSIZE);
31926 
31927 	js_ctx->idx_loop = duk_push_object_internal(ctx);
31928 	DUK_ASSERT(js_ctx->idx_loop >= 0);
31929 
31930 	/* [ ... buf loop ] */
31931 
31932 	/*
31933 	 *  Process replacer/proplist (2nd argument to JSON.stringify)
31934 	 */
31935 
31936 	h = duk_get_hobject(ctx, idx_replacer);
31937 	if (h != NULL) {
31938 		if (DUK_HOBJECT_IS_CALLABLE(h)) {
31939 			js_ctx->h_replacer = h;
31940 		} else if (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAY) {
31941 			/* Here the specification requires correct array index enumeration
31942 			 * which is a bit tricky for sparse arrays (it is handled by the
31943 			 * enum setup code).  We now enumerate ancestors too, although the
31944 			 * specification is not very clear on whether that is required.
31945 			 */
31946 
31947 			duk_uarridx_t plist_idx = 0;
31948 			duk_small_uint_t enum_flags;
31949 
31950 			js_ctx->idx_proplist = duk_push_array(ctx);  /* XXX: array internal? */
31951 
31952 			enum_flags = DUK_ENUM_ARRAY_INDICES_ONLY |
31953 			             DUK_ENUM_SORT_ARRAY_INDICES;  /* expensive flag */
31954 			duk_enum(ctx, idx_replacer, enum_flags);
31955 			while (duk_next(ctx, -1 /*enum_index*/, 1 /*get_value*/)) {
31956 				/* [ ... proplist enum_obj key val ] */
31957 				if (duk__enc_allow_into_proplist(duk_get_tval(ctx, -1))) {
31958 					/* XXX: duplicates should be eliminated here */
31959 					DUK_DDD(DUK_DDDPRINT("proplist enum: key=%!T, val=%!T --> accept",
31960 					                     (duk_tval *) duk_get_tval(ctx, -2),
31961 					                     (duk_tval *) duk_get_tval(ctx, -1)));
31962 					duk_to_string(ctx, -1);  /* extra coercion of strings is OK */
31963 					duk_put_prop_index(ctx, -4, plist_idx);  /* -> [ ... proplist enum_obj key ] */
31964 					plist_idx++;
31965 					duk_pop(ctx);
31966 				} else {
31967 					DUK_DDD(DUK_DDDPRINT("proplist enum: key=%!T, val=%!T --> reject",
31968 					                     (duk_tval *) duk_get_tval(ctx, -2),
31969 					                     (duk_tval *) duk_get_tval(ctx, -1)));
31970 					duk_pop_2(ctx);
31971 				}
31972                         }
31973                         duk_pop(ctx);  /* pop enum */
31974 
31975 			/* [ ... proplist ] */
31976 		}
31977 	}
31978 
31979 	/* [ ... buf loop (proplist) ] */
31980 
31981 	/*
31982 	 *  Process space (3rd argument to JSON.stringify)
31983 	 */
31984 
31985 	h = duk_get_hobject(ctx, idx_space);
31986 	if (h != NULL) {
31987 		int c = DUK_HOBJECT_GET_CLASS_NUMBER(h);
31988 		if (c == DUK_HOBJECT_CLASS_NUMBER) {
31989 			duk_to_number(ctx, idx_space);
31990 		} else if (c == DUK_HOBJECT_CLASS_STRING) {
31991 			duk_to_string(ctx, idx_space);
31992 		}
31993 	}
31994 
31995 	if (duk_is_number(ctx, idx_space)) {
31996 		duk_small_int_t nspace;
31997 		/* spaces[] must be static to allow initializer with old compilers like BCC */
31998 		static const char spaces[10] = {
31999 			DUK_ASC_SPACE, DUK_ASC_SPACE, DUK_ASC_SPACE, DUK_ASC_SPACE,
32000 			DUK_ASC_SPACE, DUK_ASC_SPACE, DUK_ASC_SPACE, DUK_ASC_SPACE,
32001 			DUK_ASC_SPACE, DUK_ASC_SPACE
32002 		};  /* XXX: helper */
32003 
32004 		/* ToInteger() coercion; NaN -> 0, infinities are clamped to 0 and 10 */
32005 		nspace = (duk_small_int_t) duk_to_int_clamped(ctx, idx_space, 0 /*minval*/, 10 /*maxval*/);
32006 		DUK_ASSERT(nspace >= 0 && nspace <= 10);
32007 
32008 		duk_push_lstring(ctx, spaces, (duk_size_t) nspace);
32009 		js_ctx->h_gap = duk_get_hstring(ctx, -1);
32010 		DUK_ASSERT(js_ctx->h_gap != NULL);
32011 	} else if (duk_is_string(ctx, idx_space)) {
32012 		/* XXX: substring in-place at idx_place? */
32013 		duk_dup(ctx, idx_space);
32014 		duk_substring(ctx, -1, 0, 10);  /* clamp to 10 chars */
32015 		js_ctx->h_gap = duk_get_hstring(ctx, -1);
32016 		DUK_ASSERT(js_ctx->h_gap != NULL);
32017 	} else {
32018 		/* nop */
32019 	}
32020 
32021 	if (js_ctx->h_gap != NULL) {
32022 		/* if gap is empty, behave as if not given at all */
32023 		if (DUK_HSTRING_GET_CHARLEN(js_ctx->h_gap) == 0) {
32024 			js_ctx->h_gap = NULL;
32025 		}
32026 	}
32027 
32028 	/* [ ... buf loop (proplist) (gap) ] */
32029 
32030 	/*
32031 	 *  Fast path: assume no mutation, iterate object property tables
32032 	 *  directly; bail out if that assumption doesn't hold.
32033 	 */
32034 
32035 #if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
32036 	if (js_ctx->h_replacer == NULL &&  /* replacer is a mutation risk */
32037 	    js_ctx->idx_proplist == -1) {  /* proplist is very rare */
32038 		duk_int_t pcall_rc;
32039 #ifdef DUK_USE_MARK_AND_SWEEP
32040 		duk_small_uint_t prev_mark_and_sweep_base_flags;
32041 #endif
32042 
32043 		DUK_DD(DUK_DDPRINT("try JSON.stringify() fast path"));
32044 
32045 		/* Use recursion_limit to ensure we don't overwrite js_ctx->visiting[]
32046 		 * array so we don't need two counter checks in the fast path.  The
32047 		 * slow path has a much larger recursion limit which we'll use if
32048 		 * necessary.
32049 		 */
32050 		DUK_ASSERT(DUK_USE_JSON_ENC_RECLIMIT >= DUK_JSON_ENC_LOOPARRAY);
32051 		js_ctx->recursion_limit = DUK_JSON_ENC_LOOPARRAY;
32052 		DUK_ASSERT(js_ctx->recursion_depth == 0);
32053 
32054 		/* Execute the fast path in a protected call.  If any error is thrown,
32055 		 * fall back to the slow path.  This includes e.g. recursion limit
32056 		 * because the fast path has a smaller recursion limit (and simpler,
32057 		 * limited loop detection).
32058 		 */
32059 
32060 		duk_push_pointer(ctx, (void *) js_ctx);
32061 		duk_dup(ctx, idx_value);
32062 
32063 #if defined(DUK_USE_MARK_AND_SWEEP)
32064 		/* Must prevent finalizers which may have arbitrary side effects. */
32065 		prev_mark_and_sweep_base_flags = thr->heap->mark_and_sweep_base_flags;
32066 		thr->heap->mark_and_sweep_base_flags |=
32067 			DUK_MS_FLAG_NO_FINALIZERS |         /* avoid attempts to add/remove object keys */
32068 		        DUK_MS_FLAG_NO_OBJECT_COMPACTION;   /* avoid attempt to compact any objects */
32069 #endif
32070 
32071 		pcall_rc = duk_safe_call(ctx, duk__json_stringify_fast, 2 /*nargs*/, 0 /*nret*/);
32072 
32073 #if defined(DUK_USE_MARK_AND_SWEEP)
32074 		thr->heap->mark_and_sweep_base_flags = prev_mark_and_sweep_base_flags;
32075 #endif
32076 		if (pcall_rc == DUK_EXEC_SUCCESS) {
32077 			DUK_DD(DUK_DDPRINT("fast path successful"));
32078 			DUK_BW_PUSH_AS_STRING(thr, &js_ctx->bw);
32079 			goto replace_finished;
32080 		}
32081 
32082 		/* We come here for actual aborts (like encountering .toJSON())
32083 		 * but also for recursion/loop errors.  Bufwriter size can be
32084 		 * kept because we'll probably need at least as much as we've
32085 		 * allocated so far.
32086 		 */
32087 		DUK_D(DUK_DPRINT("fast path failed, serialize using slow path instead"));
32088 		DUK_BW_RESET_SIZE(thr, &js_ctx->bw);
32089 		js_ctx->recursion_depth = 0;
32090 	}
32091 #endif
32092 
32093 	/*
32094 	 *  Create wrapper object and serialize
32095 	 */
32096 
32097 	idx_holder = duk_push_object(ctx);
32098 	duk_dup(ctx, idx_value);
32099 	duk_put_prop_stridx(ctx, -2, DUK_STRIDX_EMPTY_STRING);
32100 
32101 	DUK_DDD(DUK_DDDPRINT("before: flags=0x%08lx, loop=%!T, replacer=%!O, "
32102 	                     "proplist=%!T, gap=%!O, holder=%!T",
32103 	                     (unsigned long) js_ctx->flags,
32104 	                     (duk_tval *) duk_get_tval(ctx, js_ctx->idx_loop),
32105 	                     (duk_heaphdr *) js_ctx->h_replacer,
32106 	                     (duk_tval *) (js_ctx->idx_proplist >= 0 ? duk_get_tval(ctx, js_ctx->idx_proplist) : NULL),
32107 	                     (duk_heaphdr *) js_ctx->h_gap,
32108 	                     (duk_tval *) duk_get_tval(ctx, -1)));
32109 
32110 	/* serialize the wrapper with empty string key */
32111 
32112 	duk_push_hstring_stridx(ctx, DUK_STRIDX_EMPTY_STRING);
32113 
32114 	/* [ ... buf loop (proplist) (gap) holder "" ] */
32115 
32116 	js_ctx->recursion_limit = DUK_USE_JSON_ENC_RECLIMIT;
32117 	DUK_ASSERT(js_ctx->recursion_depth == 0);
32118 
32119 	if (DUK_UNLIKELY(duk__enc_value(js_ctx, idx_holder) == 0)) {  /* [ ... holder key ] -> [ ... holder ] */
32120 		/* Result is undefined. */
32121 		duk_push_undefined(ctx);
32122 	} else {
32123 		/* Convert buffer to result string. */
32124 		DUK_BW_PUSH_AS_STRING(thr, &js_ctx->bw);
32125 	}
32126 
32127 	DUK_DDD(DUK_DDDPRINT("after: flags=0x%08lx, loop=%!T, replacer=%!O, "
32128 	                     "proplist=%!T, gap=%!O, holder=%!T",
32129 	                     (unsigned long) js_ctx->flags,
32130 	                     (duk_tval *) duk_get_tval(ctx, js_ctx->idx_loop),
32131 	                     (duk_heaphdr *) js_ctx->h_replacer,
32132 	                     (duk_tval *) (js_ctx->idx_proplist >= 0 ? duk_get_tval(ctx, js_ctx->idx_proplist) : NULL),
32133 	                     (duk_heaphdr *) js_ctx->h_gap,
32134 	                     (duk_tval *) duk_get_tval(ctx, idx_holder)));
32135 
32136 	/* The stack has a variable shape here, so force it to the
32137 	 * desired one explicitly.
32138 	 */
32139 
32140 #if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
32141  replace_finished:
32142 #endif
32143 	duk_replace(ctx, entry_top);
32144 	duk_set_top(ctx, entry_top + 1);
32145 
32146 	DUK_DDD(DUK_DDDPRINT("JSON stringify end: value=%!T, replacer=%!T, space=%!T, "
32147 	                     "flags=0x%08lx, result=%!T, stack_top=%ld",
32148 	                     (duk_tval *) duk_get_tval(ctx, idx_value),
32149 	                     (duk_tval *) duk_get_tval(ctx, idx_replacer),
32150 	                     (duk_tval *) duk_get_tval(ctx, idx_space),
32151 	                     (unsigned long) flags,
32152 	                     (duk_tval *) duk_get_tval(ctx, -1),
32153 	                     (long) duk_get_top(ctx)));
32154 
32155 	DUK_ASSERT(duk_get_top(ctx) == entry_top + 1);
32156 }
32157 
32158 /*
32159  *  Entry points
32160  */
32161 
32162 DUK_INTERNAL duk_ret_t duk_bi_json_object_parse(duk_context *ctx) {
32163 	duk_bi_json_parse_helper(ctx,
32164 	                         0 /*idx_value*/,
32165 	                         1 /*idx_replacer*/,
32166 	                         0 /*flags*/);
32167 	return 1;
32168 }
32169 
32170 DUK_INTERNAL duk_ret_t duk_bi_json_object_stringify(duk_context *ctx) {
32171 	duk_bi_json_stringify_helper(ctx,
32172 	                             0 /*idx_value*/,
32173 	                             1 /*idx_replacer*/,
32174 	                             2 /*idx_space*/,
32175 	                             0 /*flags*/);
32176 	return 1;
32177 }
32178 
32179 #undef DUK__JSON_DECSTR_BUFSIZE
32180 #undef DUK__JSON_DECSTR_CHUNKSIZE
32181 #undef DUK__JSON_ENCSTR_CHUNKSIZE
32182 #undef DUK__JSON_STRINGIFY_BUFSIZE
32183 #undef DUK__JSON_MAX_ESC_LEN
32184 /*
32185  *  Logging support
32186  */
32187 
32188 /* include removed: duk_internal.h */
32189 
32190 /* 3-letter log level strings */
32191 DUK_LOCAL const duk_uint8_t duk__log_level_strings[] = {
32192 	(duk_uint8_t) DUK_ASC_UC_T, (duk_uint8_t) DUK_ASC_UC_R, (duk_uint8_t) DUK_ASC_UC_C,
32193 	(duk_uint8_t) DUK_ASC_UC_D, (duk_uint8_t) DUK_ASC_UC_B, (duk_uint8_t) DUK_ASC_UC_G,
32194 	(duk_uint8_t) DUK_ASC_UC_I, (duk_uint8_t) DUK_ASC_UC_N, (duk_uint8_t) DUK_ASC_UC_F,
32195 	(duk_uint8_t) DUK_ASC_UC_W, (duk_uint8_t) DUK_ASC_UC_R, (duk_uint8_t) DUK_ASC_UC_N,
32196 	(duk_uint8_t) DUK_ASC_UC_E, (duk_uint8_t) DUK_ASC_UC_R, (duk_uint8_t) DUK_ASC_UC_R,
32197 	(duk_uint8_t) DUK_ASC_UC_F, (duk_uint8_t) DUK_ASC_UC_T, (duk_uint8_t) DUK_ASC_UC_L
32198 };
32199 
32200 /* Constructor */
32201 DUK_INTERNAL duk_ret_t duk_bi_logger_constructor(duk_context *ctx) {
32202 	duk_hthread *thr = (duk_hthread *) ctx;
32203 	duk_idx_t nargs;
32204 
32205 	/* Calling as a non-constructor is not meaningful. */
32206 	if (!duk_is_constructor_call(ctx)) {
32207 		return DUK_RET_TYPE_ERROR;
32208 	}
32209 
32210 	nargs = duk_get_top(ctx);
32211 	duk_set_top(ctx, 1);
32212 
32213 	duk_push_this(ctx);
32214 
32215 	/* [ name this ] */
32216 
32217 	if (nargs == 0) {
32218 		/* Automatic defaulting of logger name from caller.  This would
32219 		 * work poorly with tail calls, but constructor calls are currently
32220 		 * never tail calls, so tail calls are not an issue now.
32221 		 */
32222 
32223 		if (thr->callstack_top >= 2) {
32224 			duk_activation *act_caller = thr->callstack + thr->callstack_top - 2;
32225 			duk_hobject *func_caller;
32226 
32227 			func_caller = DUK_ACT_GET_FUNC(act_caller);
32228 			if (func_caller) {
32229 				/* Stripping the filename might be a good idea
32230 				 * ("/foo/bar/quux.js" -> logger name "quux"),
32231 				 * but now used verbatim.
32232 				 */
32233 				duk_push_hobject(ctx, func_caller);
32234 				duk_get_prop_stridx(ctx, -1, DUK_STRIDX_FILE_NAME);
32235 				duk_replace(ctx, 0);
32236 			}
32237 		}
32238 	}
32239 	/* the stack is unbalanced here on purpose; we only rely on the
32240 	 * initial two values: [ name this ].
32241 	 */
32242 
32243 	if (duk_is_string(ctx, 0)) {
32244 		duk_dup(ctx, 0);
32245 		duk_put_prop_stridx(ctx, 1, DUK_STRIDX_LC_N);
32246 	} else {
32247 		/* don't set 'n' at all, inherited value is used as name */
32248 	}
32249 
32250 	duk_compact(ctx, 1);
32251 
32252 	return 0;  /* keep default instance */
32253 }
32254 
32255 /* Default function to format objects.  Tries to use toLogString() but falls
32256  * back to toString().  Any errors are propagated out without catching.
32257  */
32258 DUK_INTERNAL duk_ret_t duk_bi_logger_prototype_fmt(duk_context *ctx) {
32259 	if (duk_get_prop_stridx(ctx, 0, DUK_STRIDX_TO_LOG_STRING)) {
32260 		/* [ arg toLogString ] */
32261 
32262 		duk_dup(ctx, 0);
32263 		duk_call_method(ctx, 0);
32264 
32265 		/* [ arg result ] */
32266 		return 1;
32267 	}
32268 
32269 	/* [ arg undefined ] */
32270 	duk_pop(ctx);
32271 	duk_to_string(ctx, 0);
32272 	return 1;
32273 }
32274 
32275 /* Default function to write a formatted log line.  Writes to stderr,
32276  * appending a newline to the log line.
32277  *
32278  * The argument is a buffer whose visible size contains the log message.
32279  * This function should avoid coercing the buffer to a string to avoid
32280  * string table traffic.
32281  */
32282 DUK_INTERNAL duk_ret_t duk_bi_logger_prototype_raw(duk_context *ctx) {
32283 	const char *data;
32284 	duk_size_t data_len;
32285 
32286 	DUK_UNREF(ctx);
32287 	DUK_UNREF(data);
32288 	DUK_UNREF(data_len);
32289 
32290 #ifdef DUK_USE_FILE_IO
32291 	data = (const char *) duk_require_buffer(ctx, 0, &data_len);
32292 	DUK_FWRITE((const void *) data, 1, data_len, DUK_STDERR);
32293 	DUK_FPUTC((int) '\n', DUK_STDERR);
32294 	DUK_FFLUSH(DUK_STDERR);
32295 #else
32296 	/* nop */
32297 #endif
32298 	return 0;
32299 }
32300 
32301 /* Log frontend shared helper, magic value indicates log level.  Provides
32302  * frontend functions: trace(), debug(), info(), warn(), error(), fatal().
32303  * This needs to have small footprint, reasonable performance, minimal
32304  * memory churn, etc.
32305  */
32306 DUK_INTERNAL duk_ret_t duk_bi_logger_prototype_log_shared(duk_context *ctx) {
32307 	duk_hthread *thr = (duk_hthread *) ctx;
32308 	duk_double_t now;
32309 	duk_small_int_t entry_lev = duk_get_current_magic(ctx);
32310 	duk_small_int_t logger_lev;
32311 	duk_int_t nargs;
32312 	duk_int_t i;
32313 	duk_size_t tot_len;
32314 	const duk_uint8_t *arg_str;
32315 	duk_size_t arg_len;
32316 	duk_uint8_t *buf, *p;
32317 	const duk_uint8_t *q;
32318 	duk_uint8_t date_buf[DUK_BI_DATE_ISO8601_BUFSIZE];
32319 	duk_size_t date_len;
32320 	duk_small_int_t rc;
32321 
32322 	DUK_ASSERT(entry_lev >= 0 && entry_lev <= 5);
32323 	DUK_UNREF(thr);
32324 
32325 	/* XXX: sanitize to printable (and maybe ASCII) */
32326 	/* XXX: better multiline */
32327 
32328 	/*
32329 	 *  Logger arguments are:
32330 	 *
32331 	 *    magic: log level (0-5)
32332 	 *    this: logger
32333 	 *    stack: plain log args
32334 	 *
32335 	 *  We want to minimize memory churn so a two-pass approach
32336 	 *  is used: first pass formats arguments and computes final
32337 	 *  string length, second pass copies strings either into a
32338 	 *  pre-allocated and reused buffer (short messages) or into a
32339 	 *  newly allocated fixed buffer.  If the backend function plays
32340 	 *  nice, it won't coerce the buffer to a string (and thus
32341 	 *  intern it).
32342 	 */
32343 
32344 	nargs = duk_get_top(ctx);
32345 
32346 	/* [ arg1 ... argN this ] */
32347 
32348 	/*
32349 	 *  Log level check
32350 	 */
32351 
32352 	duk_push_this(ctx);
32353 
32354 	duk_get_prop_stridx(ctx, -1, DUK_STRIDX_LC_L);
32355 	logger_lev = (duk_small_int_t) duk_get_int(ctx, -1);
32356 	if (entry_lev < logger_lev) {
32357 		return 0;
32358 	}
32359 	/* log level could be popped but that's not necessary */
32360 
32361 	now = DUK_USE_DATE_GET_NOW(ctx);
32362 	duk_bi_date_format_timeval(now, date_buf);
32363 	date_len = DUK_STRLEN((const char *) date_buf);
32364 
32365 	duk_get_prop_stridx(ctx, -2, DUK_STRIDX_LC_N);
32366 	duk_to_string(ctx, -1);
32367 	DUK_ASSERT(duk_is_string(ctx, -1));
32368 
32369 	/* [ arg1 ... argN this loggerLevel loggerName ] */
32370 
32371 	/*
32372 	 *  Pass 1
32373 	 */
32374 
32375 	/* Line format: <time> <entryLev> <loggerName>: <msg> */
32376 
32377 	tot_len = 0;
32378 	tot_len += 3 +  /* separators: space, space, colon */
32379 	           3 +  /* level string */
32380 	           date_len +  /* time */
32381 	           duk_get_length(ctx, -1);  /* loggerName */
32382 
32383 	for (i = 0; i < nargs; i++) {
32384 		/* When formatting an argument to a string, errors may happen from multiple
32385 		 * causes.  In general we want to catch obvious errors like a toLogString()
32386 		 * throwing an error, but we don't currently try to catch every possible
32387 		 * error.  In particular, internal errors (like out of memory or stack) are
32388 		 * not caught.  Also, we expect Error toString() to not throw an error.
32389 		 */
32390 		if (duk_is_object(ctx, i)) {
32391 			/* duk_pcall_prop() may itself throw an error, but we're content
32392 			 * in catching the obvious errors (like toLogString() throwing an
32393 			 * error).
32394 			 */
32395 			duk_push_hstring_stridx(ctx, DUK_STRIDX_FMT);
32396 			duk_dup(ctx, i);
32397 			/* [ arg1 ... argN this loggerLevel loggerName 'fmt' arg ] */
32398 			/* call: this.fmt(arg) */
32399 			rc = duk_pcall_prop(ctx, -5 /*obj_index*/, 1 /*nargs*/);
32400 			if (rc) {
32401 				/* Keep the error as the result (coercing it might fail below,
32402 				 * but we don't catch that now).
32403 				 */
32404 				;
32405 			}
32406 			duk_replace(ctx, i);
32407 		}
32408 		(void) duk_to_lstring(ctx, i, &arg_len);
32409 		tot_len++;  /* sep (even before first one) */
32410 		tot_len += arg_len;
32411 	}
32412 
32413 	/*
32414 	 *  Pass 2
32415 	 */
32416 
32417 	/* XXX: There used to be a shared log buffer here, but it was removed
32418 	 * when dynamic buffer spare was removed.  The problem with using
32419 	 * bufwriter is that, without the spare, the buffer gets passed on
32420 	 * as an argument to the raw() call so it'd need to be resized
32421 	 * (reallocated) anyway.  If raw() call convention is changed, this
32422 	 * could be made more efficient.
32423 	 */
32424 
32425 	buf = (duk_uint8_t *) duk_push_fixed_buffer(ctx, tot_len);
32426 	DUK_ASSERT(buf != NULL);
32427 	p = buf;
32428 
32429 	DUK_MEMCPY((void *) p, (const void *) date_buf, (size_t) date_len);
32430 	p += date_len;
32431 	*p++ = (duk_uint8_t) DUK_ASC_SPACE;
32432 
32433 	q = duk__log_level_strings + (entry_lev * 3);
32434 	DUK_MEMCPY((void *) p, (const void *) q, (size_t) 3);
32435 	p += 3;
32436 
32437 	*p++ = (duk_uint8_t) DUK_ASC_SPACE;
32438 
32439 	arg_str = (const duk_uint8_t *) duk_get_lstring(ctx, -2, &arg_len);
32440 	DUK_MEMCPY((void *) p, (const void *) arg_str, (size_t) arg_len);
32441 	p += arg_len;
32442 
32443 	*p++ = (duk_uint8_t) DUK_ASC_COLON;
32444 
32445 	for (i = 0; i < nargs; i++) {
32446 		*p++ = (duk_uint8_t) DUK_ASC_SPACE;
32447 
32448 		arg_str = (const duk_uint8_t *) duk_get_lstring(ctx, i, &arg_len);
32449 		DUK_ASSERT(arg_str != NULL);
32450 		DUK_MEMCPY((void *) p, (const void *) arg_str, (size_t) arg_len);
32451 		p += arg_len;
32452 	}
32453 	DUK_ASSERT(buf + tot_len == p);
32454 
32455 	/* [ arg1 ... argN this loggerLevel loggerName buffer ] */
32456 
32457 #if defined(DUK_USE_DEBUGGER_SUPPORT) && defined(DUK_USE_DEBUGGER_FWD_LOGGING)
32458 	/* Do debugger forwarding before raw() because the raw() function
32459 	 * doesn't get the log level right now.
32460 	 */
32461 	if (DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap)) {
32462 		const char *log_buf;
32463 		duk_size_t sz_buf;
32464 		log_buf = (const char *) duk_get_buffer(ctx, -1, &sz_buf);
32465 		DUK_ASSERT(log_buf != NULL);
32466 		duk_debug_write_notify(thr, DUK_DBG_CMD_LOG);
32467 		duk_debug_write_int(thr, (duk_int32_t) entry_lev);
32468 		duk_debug_write_string(thr, (const char *) log_buf, sz_buf);
32469 		duk_debug_write_eom(thr);
32470 	}
32471 #endif
32472 
32473 	/* Call this.raw(msg); look up through the instance allows user to override
32474 	 * the raw() function in the instance or in the prototype for maximum
32475 	 * flexibility.
32476 	 */
32477 	duk_push_hstring_stridx(ctx, DUK_STRIDX_RAW);
32478 	duk_dup(ctx, -2);
32479 	/* [ arg1 ... argN this loggerLevel loggerName buffer 'raw' buffer ] */
32480 	duk_call_prop(ctx, -6, 1);  /* this.raw(buffer) */
32481 
32482 	return 0;
32483 }
32484 /*
32485  *  Math built-ins
32486  */
32487 
32488 /* include removed: duk_internal.h */
32489 
32490 #if defined(DUK_USE_MATH_BUILTIN)
32491 
32492 /*
32493  *  Use static helpers which can work with math.h functions matching
32494  *  the following signatures. This is not portable if any of these math
32495  *  functions is actually a macro.
32496  *
32497  *  Typing here is intentionally 'double' wherever values interact with
32498  *  the standard library APIs.
32499  */
32500 
32501 typedef double (*duk__one_arg_func)(double);
32502 typedef double (*duk__two_arg_func)(double, double);
32503 
32504 DUK_LOCAL duk_ret_t duk__math_minmax(duk_context *ctx, duk_double_t initial, duk__two_arg_func min_max) {
32505 	duk_idx_t n = duk_get_top(ctx);
32506 	duk_idx_t i;
32507 	duk_double_t res = initial;
32508 	duk_double_t t;
32509 
32510 	/*
32511 	 *  Note: fmax() does not match the E5 semantics.  E5 requires
32512 	 *  that if -any- input to Math.max() is a NaN, the result is a
32513 	 *  NaN.  fmax() will return a NaN only if -both- inputs are NaN.
32514 	 *  Same applies to fmin().
32515 	 *
32516 	 *  Note: every input value must be coerced with ToNumber(), even
32517 	 *  if we know the result will be a NaN anyway: ToNumber() may have
32518 	 *  side effects for which even order of evaluation matters.
32519 	 */
32520 
32521 	for (i = 0; i < n; i++) {
32522 		t = duk_to_number(ctx, i);
32523 		if (DUK_FPCLASSIFY(t) == DUK_FP_NAN || DUK_FPCLASSIFY(res) == DUK_FP_NAN) {
32524 			/* Note: not normalized, but duk_push_number() will normalize */
32525 			res = (duk_double_t) DUK_DOUBLE_NAN;
32526 		} else {
32527 			res = (duk_double_t) min_max(res, (double) t);
32528 		}
32529 	}
32530 
32531 	duk_push_number(ctx, res);
32532 	return 1;
32533 }
32534 
32535 DUK_LOCAL double duk__fmin_fixed(double x, double y) {
32536 	/* fmin() with args -0 and +0 is not guaranteed to return
32537 	 * -0 as Ecmascript requires.
32538 	 */
32539 	if (x == 0 && y == 0) {
32540 		/* XXX: what's the safest way of creating a negative zero? */
32541 		if (DUK_SIGNBIT(x) != 0 || DUK_SIGNBIT(y) != 0) {
32542 			return -0.0;
32543 		} else {
32544 			return +0.0;
32545 		}
32546 	}
32547 #ifdef DUK_USE_MATH_FMIN
32548 	return DUK_FMIN(x, y);
32549 #else
32550 	return (x < y ? x : y);
32551 #endif
32552 }
32553 
32554 DUK_LOCAL double duk__fmax_fixed(double x, double y) {
32555 	/* fmax() with args -0 and +0 is not guaranteed to return
32556 	 * +0 as Ecmascript requires.
32557 	 */
32558 	if (x == 0 && y == 0) {
32559 		if (DUK_SIGNBIT(x) == 0 || DUK_SIGNBIT(y) == 0) {
32560 			return +0.0;
32561 		} else {
32562 			return -0.0;
32563 		}
32564 	}
32565 #ifdef DUK_USE_MATH_FMAX
32566 	return DUK_FMAX(x, y);
32567 #else
32568 	return (x > y ? x : y);
32569 #endif
32570 }
32571 
32572 DUK_LOCAL double duk__round_fixed(double x) {
32573 	/* Numbers half-way between integers must be rounded towards +Infinity,
32574 	 * e.g. -3.5 must be rounded to -3 (not -4).  When rounded to zero, zero
32575 	 * sign must be set appropriately.  E5.1 Section 15.8.2.15.
32576 	 *
32577 	 * Note that ANSI C round() is "round to nearest integer, away from zero",
32578 	 * which is incorrect for negative values.  Here we make do with floor().
32579 	 */
32580 
32581 	duk_small_int_t c = (duk_small_int_t) DUK_FPCLASSIFY(x);
32582 	if (c == DUK_FP_NAN || c == DUK_FP_INFINITE || c == DUK_FP_ZERO) {
32583 		return x;
32584 	}
32585 
32586 	/*
32587 	 *  x is finite and non-zero
32588 	 *
32589 	 *  -1.6 -> floor(-1.1) -> -2
32590 	 *  -1.5 -> floor(-1.0) -> -1  (towards +Inf)
32591 	 *  -1.4 -> floor(-0.9) -> -1
32592 	 *  -0.5 -> -0.0               (special case)
32593 	 *  -0.1 -> -0.0               (special case)
32594 	 *  +0.1 -> +0.0               (special case)
32595 	 *  +0.5 -> floor(+1.0) -> 1   (towards +Inf)
32596 	 *  +1.4 -> floor(+1.9) -> 1
32597 	 *  +1.5 -> floor(+2.0) -> 2   (towards +Inf)
32598 	 *  +1.6 -> floor(+2.1) -> 2
32599 	 */
32600 
32601 	if (x >= -0.5 && x < 0.5) {
32602 		/* +0.5 is handled by floor, this is on purpose */
32603 		if (x < 0.0) {
32604 			return -0.0;
32605 		} else {
32606 			return +0.0;
32607 		}
32608 	}
32609 
32610 	return DUK_FLOOR(x + 0.5);
32611 }
32612 
32613 DUK_LOCAL double duk__pow_fixed(double x, double y) {
32614 	/* The ANSI C pow() semantics differ from Ecmascript.
32615 	 *
32616 	 * E.g. when x==1 and y is +/- infinite, the Ecmascript required
32617 	 * result is NaN, while at least Linux pow() returns 1.
32618 	 */
32619 
32620 	duk_small_int_t cx, cy, sx;
32621 
32622 	DUK_UNREF(cx);
32623 	DUK_UNREF(sx);
32624 	cy = (duk_small_int_t) DUK_FPCLASSIFY(y);
32625 
32626 	if (cy == DUK_FP_NAN) {
32627 		goto ret_nan;
32628 	}
32629 	if (DUK_FABS(x) == 1.0 && cy == DUK_FP_INFINITE) {
32630 		goto ret_nan;
32631 	}
32632 #if defined(DUK_USE_POW_NETBSD_WORKAROUND)
32633 	/* See test-bug-netbsd-math-pow.js: NetBSD 6.0 on x86 (at least) does not
32634 	 * correctly handle some cases where x=+/-0.  Specific fixes to these
32635 	 * here.
32636 	 */
32637 	cx = (duk_small_int_t) DUK_FPCLASSIFY(x);
32638 	if (cx == DUK_FP_ZERO && y < 0.0) {
32639 		sx = (duk_small_int_t) DUK_SIGNBIT(x);
32640 		if (sx == 0) {
32641 			/* Math.pow(+0,y) should be Infinity when y<0.  NetBSD pow()
32642 			 * returns -Infinity instead when y is <0 and finite.  The
32643 			 * if-clause also catches y == -Infinity (which works even
32644 			 * without the fix).
32645 			 */
32646 			return DUK_DOUBLE_INFINITY;
32647 		} else {
32648 			/* Math.pow(-0,y) where y<0 should be:
32649 			 *   - -Infinity if y<0 and an odd integer
32650 			 *   - Infinity otherwise
32651 			 * NetBSD pow() returns -Infinity for all finite y<0.  The
32652 			 * if-clause also catches y == -Infinity (which works even
32653 			 * without the fix).
32654 			 */
32655 
32656 			/* fmod() return value has same sign as input (negative) so
32657 			 * the result here will be in the range ]-2,0], 1 indicates
32658 			 * odd.  If x is -Infinity, NaN is returned and the odd check
32659 			 * always concludes "not odd" which results in desired outcome.
32660 			 */
32661 			double tmp = DUK_FMOD(y, 2);
32662 			if (tmp == -1.0) {
32663 				return -DUK_DOUBLE_INFINITY;
32664 			} else {
32665 				/* Not odd, or y == -Infinity */
32666 				return DUK_DOUBLE_INFINITY;
32667 			}
32668 		}
32669 	}
32670 #endif
32671 	return DUK_POW(x, y);
32672 
32673  ret_nan:
32674 	return DUK_DOUBLE_NAN;
32675 }
32676 
32677 /* Wrappers for calling standard math library methods.  These may be required
32678  * on platforms where one or more of the math built-ins are defined as macros
32679  * or inline functions and are thus not suitable to be used as function pointers.
32680  */
32681 #if defined(DUK_USE_AVOID_PLATFORM_FUNCPTRS)
32682 DUK_LOCAL double duk__fabs(double x) {
32683 	return DUK_FABS(x);
32684 }
32685 DUK_LOCAL double duk__acos(double x) {
32686 	return DUK_ACOS(x);
32687 }
32688 DUK_LOCAL double duk__asin(double x) {
32689 	return DUK_ASIN(x);
32690 }
32691 DUK_LOCAL double duk__atan(double x) {
32692 	return DUK_ATAN(x);
32693 }
32694 DUK_LOCAL double duk__ceil(double x) {
32695 	return DUK_CEIL(x);
32696 }
32697 DUK_LOCAL double duk__cos(double x) {
32698 	return DUK_COS(x);
32699 }
32700 DUK_LOCAL double duk__exp(double x) {
32701 	return DUK_EXP(x);
32702 }
32703 DUK_LOCAL double duk__floor(double x) {
32704 	return DUK_FLOOR(x);
32705 }
32706 DUK_LOCAL double duk__log(double x) {
32707 	return DUK_LOG(x);
32708 }
32709 DUK_LOCAL double duk__sin(double x) {
32710 	return DUK_SIN(x);
32711 }
32712 DUK_LOCAL double duk__sqrt(double x) {
32713 	return DUK_SQRT(x);
32714 }
32715 DUK_LOCAL double duk__tan(double x) {
32716 	return DUK_TAN(x);
32717 }
32718 DUK_LOCAL double duk__atan2(double x, double y) {
32719 	return DUK_ATAN2(x, y);
32720 }
32721 #endif  /* DUK_USE_AVOID_PLATFORM_FUNCPTRS */
32722 
32723 /* order must match constants in genbuiltins.py */
32724 DUK_LOCAL const duk__one_arg_func duk__one_arg_funcs[] = {
32725 #if defined(DUK_USE_AVOID_PLATFORM_FUNCPTRS)
32726 	duk__fabs,
32727 	duk__acos,
32728 	duk__asin,
32729 	duk__atan,
32730 	duk__ceil,
32731 	duk__cos,
32732 	duk__exp,
32733 	duk__floor,
32734 	duk__log,
32735 	duk__round_fixed,
32736 	duk__sin,
32737 	duk__sqrt,
32738 	duk__tan
32739 #else
32740 	DUK_FABS,
32741 	DUK_ACOS,
32742 	DUK_ASIN,
32743 	DUK_ATAN,
32744 	DUK_CEIL,
32745 	DUK_COS,
32746 	DUK_EXP,
32747 	DUK_FLOOR,
32748 	DUK_LOG,
32749 	duk__round_fixed,
32750 	DUK_SIN,
32751 	DUK_SQRT,
32752 	DUK_TAN
32753 #endif
32754 };
32755 
32756 /* order must match constants in genbuiltins.py */
32757 DUK_LOCAL const duk__two_arg_func duk__two_arg_funcs[] = {
32758 #if defined(DUK_USE_AVOID_PLATFORM_FUNCPTRS)
32759 	duk__atan2,
32760 	duk__pow_fixed
32761 #else
32762 	DUK_ATAN2,
32763 	duk__pow_fixed
32764 #endif
32765 };
32766 
32767 DUK_INTERNAL duk_ret_t duk_bi_math_object_onearg_shared(duk_context *ctx) {
32768 	duk_small_int_t fun_idx = duk_get_current_magic(ctx);
32769 	duk__one_arg_func fun;
32770 
32771 	DUK_ASSERT(fun_idx >= 0);
32772 	DUK_ASSERT(fun_idx < (duk_small_int_t) (sizeof(duk__one_arg_funcs) / sizeof(duk__one_arg_func)));
32773 	fun = duk__one_arg_funcs[fun_idx];
32774 	duk_push_number(ctx, (duk_double_t) fun((double) duk_to_number(ctx, 0)));
32775 	return 1;
32776 }
32777 
32778 DUK_INTERNAL duk_ret_t duk_bi_math_object_twoarg_shared(duk_context *ctx) {
32779 	duk_small_int_t fun_idx = duk_get_current_magic(ctx);
32780 	duk__two_arg_func fun;
32781 
32782 	DUK_ASSERT(fun_idx >= 0);
32783 	DUK_ASSERT(fun_idx < (duk_small_int_t) (sizeof(duk__two_arg_funcs) / sizeof(duk__two_arg_func)));
32784 	fun = duk__two_arg_funcs[fun_idx];
32785 	duk_push_number(ctx, (duk_double_t) fun((double) duk_to_number(ctx, 0), (double) duk_to_number(ctx, 1)));
32786 	return 1;
32787 }
32788 
32789 DUK_INTERNAL duk_ret_t duk_bi_math_object_max(duk_context *ctx) {
32790 	return duk__math_minmax(ctx, -DUK_DOUBLE_INFINITY, duk__fmax_fixed);
32791 }
32792 
32793 DUK_INTERNAL duk_ret_t duk_bi_math_object_min(duk_context *ctx) {
32794 	return duk__math_minmax(ctx, DUK_DOUBLE_INFINITY, duk__fmin_fixed);
32795 }
32796 
32797 DUK_INTERNAL duk_ret_t duk_bi_math_object_random(duk_context *ctx) {
32798 	duk_push_number(ctx, (duk_double_t) duk_util_tinyrandom_get_double((duk_hthread *) ctx));
32799 	return 1;
32800 }
32801 
32802 #else  /* DUK_USE_MATH_BUILTIN */
32803 
32804 /* A stubbed built-in is useful for e.g. compilation torture testing with BCC. */
32805 
32806 DUK_INTERNAL duk_ret_t duk_bi_math_object_onearg_shared(duk_context *ctx) {
32807 	DUK_UNREF(ctx);
32808 	return DUK_RET_UNIMPLEMENTED_ERROR;
32809 }
32810 
32811 DUK_INTERNAL duk_ret_t duk_bi_math_object_twoarg_shared(duk_context *ctx) {
32812 	DUK_UNREF(ctx);
32813 	return DUK_RET_UNIMPLEMENTED_ERROR;
32814 }
32815 
32816 DUK_INTERNAL duk_ret_t duk_bi_math_object_max(duk_context *ctx) {
32817 	DUK_UNREF(ctx);
32818 	return DUK_RET_UNIMPLEMENTED_ERROR;
32819 }
32820 
32821 DUK_INTERNAL duk_ret_t duk_bi_math_object_min(duk_context *ctx) {
32822 	DUK_UNREF(ctx);
32823 	return DUK_RET_UNIMPLEMENTED_ERROR;
32824 }
32825 
32826 DUK_INTERNAL duk_ret_t duk_bi_math_object_random(duk_context *ctx) {
32827 	DUK_UNREF(ctx);
32828 	return DUK_RET_UNIMPLEMENTED_ERROR;
32829 }
32830 
32831 #endif  /* DUK_USE_MATH_BUILTIN */
32832 /*
32833  *  Number built-ins
32834  */
32835 
32836 /* include removed: duk_internal.h */
32837 
32838 DUK_LOCAL duk_double_t duk__push_this_number_plain(duk_context *ctx) {
32839 	duk_hobject *h;
32840 
32841 	/* Number built-in accepts a plain number or a Number object (whose
32842 	 * internal value is operated on).  Other types cause TypeError.
32843 	 */
32844 
32845 	duk_push_this(ctx);
32846 	if (duk_is_number(ctx, -1)) {
32847 		DUK_DDD(DUK_DDDPRINT("plain number value: %!T", (duk_tval *) duk_get_tval(ctx, -1)));
32848 		goto done;
32849 	}
32850 	h = duk_get_hobject(ctx, -1);
32851 	if (!h ||
32852 	    (DUK_HOBJECT_GET_CLASS_NUMBER(h) != DUK_HOBJECT_CLASS_NUMBER)) {
32853 		DUK_DDD(DUK_DDDPRINT("unacceptable this value: %!T", (duk_tval *) duk_get_tval(ctx, -1)));
32854 		DUK_ERROR_TYPE((duk_hthread *) ctx, "number expected");
32855 	}
32856 	duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_VALUE);
32857 	DUK_ASSERT(duk_is_number(ctx, -1));
32858 	DUK_DDD(DUK_DDDPRINT("number object: %!T, internal value: %!T",
32859 	                     (duk_tval *) duk_get_tval(ctx, -2), (duk_tval *) duk_get_tval(ctx, -1)));
32860 	duk_remove(ctx, -2);
32861 
32862  done:
32863 	return duk_get_number(ctx, -1);
32864 }
32865 
32866 DUK_INTERNAL duk_ret_t duk_bi_number_constructor(duk_context *ctx) {
32867 	duk_hthread *thr = (duk_hthread *) ctx;
32868 	duk_idx_t nargs;
32869 	duk_hobject *h_this;
32870 
32871 	DUK_UNREF(thr);
32872 
32873 	/*
32874 	 *  The Number constructor uses ToNumber(arg) for number coercion
32875 	 *  (coercing an undefined argument to NaN).  However, if the
32876 	 *  argument is not given at all, +0 must be used instead.  To do
32877 	 *  this, a vararg function is used.
32878 	 */
32879 
32880 	nargs = duk_get_top(ctx);
32881 	if (nargs == 0) {
32882 		duk_push_int(ctx, 0);
32883 	}
32884 	duk_to_number(ctx, 0);
32885 	duk_set_top(ctx, 1);
32886 	DUK_ASSERT_TOP(ctx, 1);
32887 
32888 	if (!duk_is_constructor_call(ctx)) {
32889 		return 1;
32890 	}
32891 
32892 	/*
32893 	 *  E5 Section 15.7.2.1 requires that the constructed object
32894 	 *  must have the original Number.prototype as its internal
32895 	 *  prototype.  However, since Number.prototype is non-writable
32896 	 *  and non-configurable, this doesn't have to be enforced here:
32897 	 *  The default object (bound to 'this') is OK, though we have
32898 	 *  to change its class.
32899 	 *
32900 	 *  Internal value set to ToNumber(arg) or +0; if no arg given,
32901 	 *  ToNumber(undefined) = NaN, so special treatment is needed
32902 	 *  (above).  String internal value is immutable.
32903 	 */
32904 
32905 	/* XXX: helper */
32906 	duk_push_this(ctx);
32907 	h_this = duk_get_hobject(ctx, -1);
32908 	DUK_ASSERT(h_this != NULL);
32909 	DUK_HOBJECT_SET_CLASS_NUMBER(h_this, DUK_HOBJECT_CLASS_NUMBER);
32910 
32911 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_this) == thr->builtins[DUK_BIDX_NUMBER_PROTOTYPE]);
32912 	DUK_ASSERT(DUK_HOBJECT_GET_CLASS_NUMBER(h_this) == DUK_HOBJECT_CLASS_NUMBER);
32913 	DUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE(h_this));
32914 
32915 	duk_dup(ctx, 0);  /* -> [ val obj val ] */
32916 	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);
32917 	return 0;  /* no return value -> don't replace created value */
32918 }
32919 
32920 DUK_INTERNAL duk_ret_t duk_bi_number_prototype_value_of(duk_context *ctx) {
32921 	(void) duk__push_this_number_plain(ctx);
32922 	return 1;
32923 }
32924 
32925 DUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_string(duk_context *ctx) {
32926 	duk_small_int_t radix;
32927 	duk_small_uint_t n2s_flags;
32928 
32929 	(void) duk__push_this_number_plain(ctx);
32930 	if (duk_is_undefined(ctx, 0)) {
32931 		radix = 10;
32932 	} else {
32933 		radix = (duk_small_int_t) duk_to_int_check_range(ctx, 0, 2, 36);
32934 	}
32935 	DUK_DDD(DUK_DDDPRINT("radix=%ld", (long) radix));
32936 
32937 	n2s_flags = 0;
32938 
32939 	duk_numconv_stringify(ctx,
32940 	                      radix /*radix*/,
32941 	                      0 /*digits*/,
32942 	                      n2s_flags /*flags*/);
32943 	return 1;
32944 }
32945 
32946 DUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_locale_string(duk_context *ctx) {
32947 	/* XXX: just use toString() for now; permitted although not recommended.
32948 	 * nargs==1, so radix is passed to toString().
32949 	 */
32950 	return duk_bi_number_prototype_to_string(ctx);
32951 }
32952 
32953 /*
32954  *  toFixed(), toExponential(), toPrecision()
32955  */
32956 
32957 /* XXX: shared helper for toFixed(), toExponential(), toPrecision()? */
32958 
32959 DUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_fixed(duk_context *ctx) {
32960 	duk_small_int_t frac_digits;
32961 	duk_double_t d;
32962 	duk_small_int_t c;
32963 	duk_small_uint_t n2s_flags;
32964 
32965 	frac_digits = (duk_small_int_t) duk_to_int_check_range(ctx, 0, 0, 20);
32966 	d = duk__push_this_number_plain(ctx);
32967 
32968 	c = (duk_small_int_t) DUK_FPCLASSIFY(d);
32969 	if (c == DUK_FP_NAN || c == DUK_FP_INFINITE) {
32970 		goto use_to_string;
32971 	}
32972 
32973 	if (d >= 1.0e21 || d <= -1.0e21) {
32974 		goto use_to_string;
32975 	}
32976 
32977 	n2s_flags = DUK_N2S_FLAG_FIXED_FORMAT |
32978 	            DUK_N2S_FLAG_FRACTION_DIGITS;
32979 
32980 	duk_numconv_stringify(ctx,
32981 	                      10 /*radix*/,
32982 	                      frac_digits /*digits*/,
32983 	                      n2s_flags /*flags*/);
32984 	return 1;
32985 
32986  use_to_string:
32987 	DUK_ASSERT_TOP(ctx, 2);
32988 	duk_to_string(ctx, -1);
32989 	return 1;
32990 }
32991 
32992 DUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_exponential(duk_context *ctx) {
32993 	duk_bool_t frac_undefined;
32994 	duk_small_int_t frac_digits;
32995 	duk_double_t d;
32996 	duk_small_int_t c;
32997 	duk_small_uint_t n2s_flags;
32998 
32999 	d = duk__push_this_number_plain(ctx);
33000 
33001 	frac_undefined = duk_is_undefined(ctx, 0);
33002 	duk_to_int(ctx, 0);  /* for side effects */
33003 
33004 	c = (duk_small_int_t) DUK_FPCLASSIFY(d);
33005 	if (c == DUK_FP_NAN || c == DUK_FP_INFINITE) {
33006 		goto use_to_string;
33007 	}
33008 
33009 	frac_digits = (duk_small_int_t) duk_to_int_check_range(ctx, 0, 0, 20);
33010 
33011 	n2s_flags = DUK_N2S_FLAG_FORCE_EXP |
33012 	           (frac_undefined ? 0 : DUK_N2S_FLAG_FIXED_FORMAT);
33013 
33014 	duk_numconv_stringify(ctx,
33015 	                      10 /*radix*/,
33016 	                      frac_digits + 1 /*leading digit + fractions*/,
33017 	                      n2s_flags /*flags*/);
33018 	return 1;
33019 
33020  use_to_string:
33021 	DUK_ASSERT_TOP(ctx, 2);
33022 	duk_to_string(ctx, -1);
33023 	return 1;
33024 }
33025 
33026 DUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_precision(duk_context *ctx) {
33027 	/* The specification has quite awkward order of coercion and
33028 	 * checks for toPrecision().  The operations below are a bit
33029 	 * reordered, within constraints of observable side effects.
33030 	 */
33031 
33032 	duk_double_t d;
33033 	duk_small_int_t prec;
33034 	duk_small_int_t c;
33035 	duk_small_uint_t n2s_flags;
33036 
33037 	DUK_ASSERT_TOP(ctx, 1);
33038 
33039 	d = duk__push_this_number_plain(ctx);
33040 	if (duk_is_undefined(ctx, 0)) {
33041 		goto use_to_string;
33042 	}
33043 	DUK_ASSERT_TOP(ctx, 2);
33044 
33045 	duk_to_int(ctx, 0);  /* for side effects */
33046 
33047 	c = (duk_small_int_t) DUK_FPCLASSIFY(d);
33048 	if (c == DUK_FP_NAN || c == DUK_FP_INFINITE) {
33049 		goto use_to_string;
33050 	}
33051 
33052 	prec = (duk_small_int_t) duk_to_int_check_range(ctx, 0, 1, 21);
33053 
33054 	n2s_flags = DUK_N2S_FLAG_FIXED_FORMAT |
33055 	            DUK_N2S_FLAG_NO_ZERO_PAD;
33056 
33057 	duk_numconv_stringify(ctx,
33058 	                      10 /*radix*/,
33059 	                      prec /*digits*/,
33060 	                      n2s_flags /*flags*/);
33061 	return 1;
33062 
33063  use_to_string:
33064 	/* Used when precision is undefined; also used for NaN (-> "NaN"),
33065 	 * and +/- infinity (-> "Infinity", "-Infinity").
33066 	 */
33067 
33068 	DUK_ASSERT_TOP(ctx, 2);
33069 	duk_to_string(ctx, -1);
33070 	return 1;
33071 }
33072 /*
33073  *  Object built-ins
33074  */
33075 
33076 /* include removed: duk_internal.h */
33077 
33078 DUK_INTERNAL duk_ret_t duk_bi_object_constructor(duk_context *ctx) {
33079 	if (!duk_is_constructor_call(ctx) &&
33080 	    !duk_is_null_or_undefined(ctx, 0)) {
33081 		duk_to_object(ctx, 0);
33082 		return 1;
33083 	}
33084 
33085 	if (duk_is_object(ctx, 0)) {
33086 		return 1;
33087 	}
33088 
33089 	/* Pointer and buffer primitive values are treated like other
33090 	 * primitives values which have a fully fledged object counterpart:
33091 	 * promote to an object value.  Lightfuncs are coerced with
33092 	 * ToObject() even they could also be returned as is.
33093 	 */
33094 	if (duk_check_type_mask(ctx, 0, DUK_TYPE_MASK_STRING |
33095 	                                DUK_TYPE_MASK_BOOLEAN |
33096 	                                DUK_TYPE_MASK_NUMBER |
33097 	                                DUK_TYPE_MASK_POINTER |
33098 	                                DUK_TYPE_MASK_BUFFER |
33099 	                                DUK_TYPE_MASK_LIGHTFUNC)) {
33100 		duk_to_object(ctx, 0);
33101 		return 1;
33102 	}
33103 
33104 	duk_push_object_helper(ctx,
33105 	                       DUK_HOBJECT_FLAG_EXTENSIBLE |
33106 	                       DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
33107 	                       DUK_BIDX_OBJECT_PROTOTYPE);
33108 	return 1;
33109 }
33110 
33111 /* Shared helper to implement Object.getPrototypeOf and the ES6
33112  * Object.prototype.__proto__ getter.
33113  *
33114  * http://www.ecma-international.org/ecma-262/6.0/index.html#sec-get-object.prototype.__proto__
33115  */
33116 DUK_INTERNAL duk_ret_t duk_bi_object_getprototype_shared(duk_context *ctx) {
33117 	duk_hthread *thr = (duk_hthread *) ctx;
33118 	duk_hobject *h;
33119 	duk_hobject *proto;
33120 
33121 	DUK_UNREF(thr);
33122 
33123 	/* magic: 0=getter call, 1=Object.getPrototypeOf */
33124 	if (duk_get_current_magic(ctx) == 0) {
33125 		duk_push_this_coercible_to_object(ctx);
33126 		duk_insert(ctx, 0);
33127 	}
33128 
33129 	h = duk_require_hobject_or_lfunc(ctx, 0);
33130 	/* h is NULL for lightfunc */
33131 
33132 	/* XXX: should the API call handle this directly, i.e. attempt
33133 	 * to duk_push_hobject(ctx, null) would push a null instead?
33134 	 * (On the other hand 'undefined' would be just as logical, but
33135 	 * not wanted here.)
33136 	 */
33137 
33138 	if (h == NULL) {
33139 		duk_push_hobject_bidx(ctx, DUK_BIDX_FUNCTION_PROTOTYPE);
33140 	} else {
33141 		proto = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
33142 		if (proto) {
33143 			duk_push_hobject(ctx, proto);
33144 		} else {
33145 			duk_push_null(ctx);
33146 		}
33147 	}
33148 	return 1;
33149 }
33150 
33151 /* Shared helper to implement ES6 Object.setPrototypeOf and
33152  * Object.prototype.__proto__ setter.
33153  *
33154  * http://www.ecma-international.org/ecma-262/6.0/index.html#sec-get-object.prototype.__proto__
33155  * http://www.ecma-international.org/ecma-262/6.0/index.html#sec-object.setprototypeof
33156  */
33157 DUK_INTERNAL duk_ret_t duk_bi_object_setprototype_shared(duk_context *ctx) {
33158 	duk_hthread *thr = (duk_hthread *) ctx;
33159 	duk_hobject *h_obj;
33160 	duk_hobject *h_new_proto;
33161 	duk_hobject *h_curr;
33162 	duk_ret_t ret_success = 1;  /* retval for success path */
33163 
33164 	/* Preliminaries for __proto__ and setPrototypeOf (E6 19.1.2.18 steps 1-4);
33165 	 * magic: 0=setter call, 1=Object.setPrototypeOf
33166 	 */
33167 	if (duk_get_current_magic(ctx) == 0) {
33168 		duk_push_this_check_object_coercible(ctx);
33169 		duk_insert(ctx, 0);
33170 		if (!duk_check_type_mask(ctx, 1, DUK_TYPE_MASK_NULL | DUK_TYPE_MASK_OBJECT)) {
33171 			return 0;
33172 		}
33173 
33174 		/* __proto__ setter returns 'undefined' on success unlike the
33175 		 * setPrototypeOf() call which returns the target object.
33176 		 */
33177 		ret_success = 0;
33178 	} else {
33179 		duk_require_object_coercible(ctx, 0);
33180 		duk_require_type_mask(ctx, 1, DUK_TYPE_MASK_NULL | DUK_TYPE_MASK_OBJECT);
33181 	}
33182 
33183 	h_new_proto = duk_get_hobject(ctx, 1);
33184 	/* h_new_proto may be NULL */
33185 	if (duk_is_lightfunc(ctx, 0)) {
33186 		if (h_new_proto == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]) {
33187 			goto skip;
33188 		}
33189 		goto fail_nonextensible;
33190 	}
33191 	h_obj = duk_get_hobject(ctx, 0);
33192 	if (!h_obj) {
33193 		goto skip;
33194 	}
33195 	DUK_ASSERT(h_obj != NULL);
33196 
33197 	/* [[SetPrototypeOf]] standard behavior, E6 9.1.2 */
33198 	/* TODO: implement Proxy object support here */
33199 
33200 	if (h_new_proto == DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_obj)) {
33201 		goto skip;
33202 	}
33203 	if (!DUK_HOBJECT_HAS_EXTENSIBLE(h_obj)) {
33204 		goto fail_nonextensible;
33205 	}
33206 	for (h_curr = h_new_proto; h_curr != NULL; h_curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_curr)) {
33207 		/* Loop prevention */
33208 		if (h_curr == h_obj) {
33209 			goto fail_loop;
33210 		}
33211 	}
33212 	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h_obj, h_new_proto);
33213 	/* fall thru */
33214 
33215  skip:
33216 	duk_set_top(ctx, 1);
33217 	return ret_success;
33218 
33219  fail_nonextensible:
33220  fail_loop:
33221 	return DUK_RET_TYPE_ERROR;
33222 }
33223 
33224 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_get_own_property_descriptor(duk_context *ctx) {
33225 	/* XXX: no need for indirect call */
33226 	return duk_hobject_object_get_own_property_descriptor(ctx);
33227 }
33228 
33229 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_create(duk_context *ctx) {
33230 	duk_tval *tv;
33231 	duk_hobject *proto = NULL;
33232 
33233 	DUK_ASSERT_TOP(ctx, 2);
33234 
33235 	tv = duk_get_tval(ctx, 0);
33236 	DUK_ASSERT(tv != NULL);
33237 	if (DUK_TVAL_IS_NULL(tv)) {
33238 		;
33239 	} else if (DUK_TVAL_IS_OBJECT(tv)) {
33240 		proto = DUK_TVAL_GET_OBJECT(tv);
33241 		DUK_ASSERT(proto != NULL);
33242 	} else {
33243 		return DUK_RET_TYPE_ERROR;
33244 	}
33245 
33246 	(void) duk_push_object_helper_proto(ctx,
33247 	                                    DUK_HOBJECT_FLAG_EXTENSIBLE |
33248 	                                    DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
33249 	                                    proto);
33250 
33251 	if (!duk_is_undefined(ctx, 1)) {
33252 		/* [ O Properties obj ] */
33253 
33254 		duk_replace(ctx, 0);
33255 
33256 		/* [ obj Properties ] */
33257 
33258 		/* Just call the "original" Object.defineProperties() to
33259 		 * finish up.
33260 		 */
33261 
33262 		return duk_bi_object_constructor_define_properties(ctx);
33263 	}
33264 
33265 	/* [ O Properties obj ] */
33266 
33267 	return 1;
33268 }
33269 
33270 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_define_property(duk_context *ctx) {
33271 	duk_hobject *obj;
33272 	duk_hstring *key;
33273 	duk_hobject *get;
33274 	duk_hobject *set;
33275 	duk_idx_t idx_value;
33276 	duk_uint_t defprop_flags;
33277 
33278 	DUK_ASSERT(ctx != NULL);
33279 
33280 	DUK_DDD(DUK_DDDPRINT("Object.defineProperty(): ctx=%p obj=%!T key=%!T desc=%!T",
33281 	                     (void *) ctx,
33282 	                     (duk_tval *) duk_get_tval(ctx, 0),
33283 	                     (duk_tval *) duk_get_tval(ctx, 1),
33284 	                     (duk_tval *) duk_get_tval(ctx, 2)));
33285 
33286 	/* [ obj key desc ] */
33287 
33288 	/* Lightfuncs are currently supported by coercing to a temporary
33289 	 * Function object; changes will be allowed (the coerced value is
33290 	 * extensible) but will be lost.
33291 	 */
33292 	obj = duk_require_hobject_or_lfunc_coerce(ctx, 0);
33293 	(void) duk_to_string(ctx, 1);
33294 	key = duk_require_hstring(ctx, 1);
33295 	(void) duk_require_hobject(ctx, 2);
33296 
33297 	DUK_ASSERT(obj != NULL);
33298 	DUK_ASSERT(key != NULL);
33299 	DUK_ASSERT(duk_get_hobject(ctx, 2) != NULL);
33300 
33301 	/*
33302 	 *  Validate and convert argument property descriptor (an Ecmascript
33303 	 *  object) into a set of defprop_flags and possibly property value,
33304 	 *  getter, and/or setter values on the value stack.
33305 	 *
33306 	 *  Lightfunc set/get values are coerced to full Functions.
33307 	 */
33308 
33309 	duk_hobject_prepare_property_descriptor(ctx,
33310 	                                        2 /*idx_desc*/,
33311 	                                        &defprop_flags,
33312 	                                        &idx_value,
33313 	                                        &get,
33314 	                                        &set);
33315 
33316 	/*
33317 	 *  Use Object.defineProperty() helper for the actual operation.
33318 	 */
33319 
33320 	duk_hobject_define_property_helper(ctx,
33321 	                                   defprop_flags,
33322 	                                   obj,
33323 	                                   key,
33324 	                                   idx_value,
33325 	                                   get,
33326 	                                   set);
33327 
33328 	/* Ignore the normalize/validate helper outputs on the value stack,
33329 	 * they're popped automatically.
33330 	 */
33331 
33332 	/*
33333 	 *  Return target object.
33334 	 */
33335 
33336 	duk_push_hobject(ctx, obj);
33337 	return 1;
33338 }
33339 
33340 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_define_properties(duk_context *ctx) {
33341 	duk_small_uint_t pass;
33342 	duk_uint_t defprop_flags;
33343 	duk_hobject *obj;
33344 	duk_idx_t idx_value;
33345 	duk_hobject *get;
33346 	duk_hobject *set;
33347 
33348 	/* Lightfunc handling by ToObject() coercion. */
33349 	obj = duk_require_hobject_or_lfunc_coerce(ctx, 0);  /* target */
33350 	DUK_ASSERT(obj != NULL);
33351 
33352 	duk_to_object(ctx, 1);        /* properties object */
33353 
33354 	DUK_DDD(DUK_DDDPRINT("target=%!iT, properties=%!iT",
33355 	                     (duk_tval *) duk_get_tval(ctx, 0),
33356 	                     (duk_tval *) duk_get_tval(ctx, 1)));
33357 
33358 	/*
33359 	 *  Two pass approach to processing the property descriptors.
33360 	 *  On first pass validate and normalize all descriptors before
33361 	 *  any changes are made to the target object.  On second pass
33362 	 *  make the actual modifications to the target object.
33363 	 *
33364 	 *  Right now we'll just use the same normalize/validate helper
33365 	 *  on both passes, ignoring its outputs on the first pass.
33366 	 */
33367 
33368 	for (pass = 0; pass < 2; pass++) {
33369 		duk_set_top(ctx, 2);  /* -> [ hobject props ] */
33370 		duk_enum(ctx, 1, DUK_ENUM_OWN_PROPERTIES_ONLY /*enum_flags*/);
33371 
33372 		for (;;) {
33373 			duk_hstring *key;
33374 
33375 			/* [ hobject props enum(props) ] */
33376 
33377 			duk_set_top(ctx, 3);
33378 
33379 			if (!duk_next(ctx, 2, 1 /*get_value*/)) {
33380 				break;
33381 			}
33382 
33383 			DUK_DDD(DUK_DDDPRINT("-> key=%!iT, desc=%!iT",
33384 			                     (duk_tval *) duk_get_tval(ctx, -2),
33385 			                     (duk_tval *) duk_get_tval(ctx, -1)));
33386 
33387 			/* [ hobject props enum(props) key desc ] */
33388 
33389 			duk_hobject_prepare_property_descriptor(ctx,
33390 			                                        4 /*idx_desc*/,
33391 			                                        &defprop_flags,
33392 			                                        &idx_value,
33393 			                                        &get,
33394 			                                        &set);
33395 
33396 			/* [ hobject props enum(props) key desc value? getter? setter? ] */
33397 
33398 			if (pass == 0) {
33399 				continue;
33400 			}
33401 
33402 			key = duk_get_hstring(ctx, 3);
33403 			DUK_ASSERT(key != NULL);
33404 
33405 			duk_hobject_define_property_helper(ctx,
33406 			                                   defprop_flags,
33407 			                                   obj,
33408 			                                   key,
33409 			                                   idx_value,
33410 			                                   get,
33411 			                                   set);
33412 		}
33413 	}
33414 
33415 	/*
33416 	 *  Return target object
33417 	 */
33418 
33419 	duk_dup(ctx, 0);
33420 	return 1;
33421 }
33422 
33423 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_seal_freeze_shared(duk_context *ctx) {
33424 	duk_hthread *thr = (duk_hthread *) ctx;
33425 	duk_hobject *h;
33426 	duk_bool_t is_freeze;
33427 
33428 	h = duk_require_hobject_or_lfunc(ctx, 0);
33429 	if (!h) {
33430 		/* Lightfunc, always success. */
33431 		return 1;
33432 	}
33433 
33434 	is_freeze = (duk_bool_t) duk_get_current_magic(ctx);
33435 	duk_hobject_object_seal_freeze_helper(thr, h, is_freeze);
33436 
33437 	/* Sealed and frozen objects cannot gain any more properties,
33438 	 * so this is a good time to compact them.
33439 	 */
33440 	duk_hobject_compact_props(thr, h);
33441 
33442 	return 1;
33443 }
33444 
33445 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_prevent_extensions(duk_context *ctx) {
33446 	duk_hthread *thr = (duk_hthread *) ctx;
33447 	duk_hobject *h;
33448 
33449 	h = duk_require_hobject_or_lfunc(ctx, 0);
33450 	if (!h) {
33451 		/* Lightfunc, always success. */
33452 		return 1;
33453 	}
33454 	DUK_ASSERT(h != NULL);
33455 
33456 	DUK_HOBJECT_CLEAR_EXTENSIBLE(h);
33457 
33458 	/* A non-extensible object cannot gain any more properties,
33459 	 * so this is a good time to compact.
33460 	 */
33461 	duk_hobject_compact_props(thr, h);
33462 
33463 	return 1;
33464 }
33465 
33466 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_is_sealed_frozen_shared(duk_context *ctx) {
33467 	duk_hobject *h;
33468 	duk_bool_t is_frozen;
33469 	duk_bool_t rc;
33470 
33471 	h = duk_require_hobject_or_lfunc(ctx, 0);
33472 	if (!h) {
33473 		duk_push_true(ctx);  /* frozen and sealed */
33474 	} else {
33475 		is_frozen = duk_get_current_magic(ctx);
33476 		rc = duk_hobject_object_is_sealed_frozen_helper((duk_hthread *) ctx, h, is_frozen /*is_frozen*/);
33477 		duk_push_boolean(ctx, rc);
33478 	}
33479 	return 1;
33480 }
33481 
33482 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_is_extensible(duk_context *ctx) {
33483 	duk_hobject *h;
33484 
33485 	h = duk_require_hobject_or_lfunc(ctx, 0);
33486 	if (!h) {
33487 		duk_push_false(ctx);
33488 	} else {
33489 		duk_push_boolean(ctx, DUK_HOBJECT_HAS_EXTENSIBLE(h));
33490 	}
33491 	return 1;
33492 }
33493 
33494 /* Shared helper for Object.getOwnPropertyNames() and Object.keys().
33495  * Magic: 0=getOwnPropertyNames, 1=Object.keys.
33496  */
33497 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_keys_shared(duk_context *ctx) {
33498 	duk_hthread *thr = (duk_hthread *) ctx;
33499 	duk_hobject *obj;
33500 #if defined(DUK_USE_ES6_PROXY)
33501 	duk_hobject *h_proxy_target;
33502 	duk_hobject *h_proxy_handler;
33503 	duk_hobject *h_trap_result;
33504 	duk_uarridx_t i, len, idx;
33505 #endif
33506 	duk_small_uint_t enum_flags;
33507 
33508 	DUK_ASSERT_TOP(ctx, 1);
33509 	DUK_UNREF(thr);
33510 
33511 	obj = duk_require_hobject_or_lfunc_coerce(ctx, 0);
33512 	DUK_ASSERT(obj != NULL);
33513 	DUK_UNREF(obj);
33514 
33515 #if defined(DUK_USE_ES6_PROXY)
33516 	if (DUK_LIKELY(!duk_hobject_proxy_check(thr,
33517 	                                        obj,
33518 	                                        &h_proxy_target,
33519 	                                        &h_proxy_handler))) {
33520 		goto skip_proxy;
33521 	}
33522 
33523 	duk_push_hobject(ctx, h_proxy_handler);
33524 	if (!duk_get_prop_stridx(ctx, -1, DUK_STRIDX_OWN_KEYS)) {
33525 		/* Careful with reachability here: don't pop 'obj' before pushing
33526 		 * proxy target.
33527 		 */
33528 		DUK_DDD(DUK_DDDPRINT("no ownKeys trap, get keys of target instead"));
33529 		duk_pop_2(ctx);
33530 		duk_push_hobject(ctx, h_proxy_target);
33531 		duk_replace(ctx, 0);
33532 		DUK_ASSERT_TOP(ctx, 1);
33533 		goto skip_proxy;
33534 	}
33535 
33536 	/* [ obj handler trap ] */
33537 	duk_insert(ctx, -2);
33538 	duk_push_hobject(ctx, h_proxy_target);  /* -> [ obj trap handler target ] */
33539 	duk_call_method(ctx, 1 /*nargs*/);      /* -> [ obj trap_result ] */
33540 	h_trap_result = duk_require_hobject(ctx, -1);
33541 	DUK_UNREF(h_trap_result);
33542 
33543 	len = (duk_uarridx_t) duk_get_length(ctx, -1);
33544 	idx = 0;
33545 	duk_push_array(ctx);
33546 	for (i = 0; i < len; i++) {
33547 		/* [ obj trap_result res_arr ] */
33548 		if (duk_get_prop_index(ctx, -2, i) && duk_is_string(ctx, -1)) {
33549 			/* XXX: for Object.keys() we should check enumerability of key */
33550 			/* [ obj trap_result res_arr propname ] */
33551 			duk_put_prop_index(ctx, -2, idx);
33552 			idx++;
33553 		} else {
33554 			duk_pop(ctx);
33555 		}
33556 	}
33557 
33558 	/* XXX: missing trap result validation for non-configurable target keys
33559 	 * (must be present), for non-extensible target all target keys must be
33560 	 * present and no extra keys can be present.
33561 	 * http://www.ecma-international.org/ecma-262/6.0/#sec-proxy-object-internal-methods-and-internal-slots-ownpropertykeys
33562 	 */
33563 
33564 	/* XXX: for Object.keys() the [[OwnPropertyKeys]] result (trap result)
33565 	 * should be filtered so that only enumerable keys remain.  Enumerability
33566 	 * should be checked with [[GetOwnProperty]] on the original object
33567 	 * (i.e., the proxy in this case).  If the proxy has a getOwnPropertyDescriptor
33568 	 * trap, it should be triggered for every property.  If the proxy doesn't have
33569 	 * the trap, enumerability should be checked against the target object instead.
33570 	 * We don't do any of this now, so Object.keys() and Object.getOwnPropertyNames()
33571 	 * return the same result now for proxy traps.  We still do clean up the trap
33572 	 * result, so that Object.keys() and Object.getOwnPropertyNames() will return a
33573 	 * clean array of strings without gaps.
33574 	 */
33575 	return 1;
33576 
33577  skip_proxy:
33578 #endif  /* DUK_USE_ES6_PROXY */
33579 
33580 	DUK_ASSERT_TOP(ctx, 1);
33581 
33582 	if (duk_get_current_magic(ctx)) {
33583 		/* Object.keys */
33584 		enum_flags = DUK_ENUM_OWN_PROPERTIES_ONLY |
33585 		             DUK_ENUM_NO_PROXY_BEHAVIOR;
33586 	} else {
33587 		/* Object.getOwnPropertyNames */
33588 		enum_flags = DUK_ENUM_INCLUDE_NONENUMERABLE |
33589 		             DUK_ENUM_OWN_PROPERTIES_ONLY |
33590 		             DUK_ENUM_NO_PROXY_BEHAVIOR;
33591 	}
33592 
33593 	return duk_hobject_get_enumerated_keys(ctx, enum_flags);
33594 }
33595 
33596 DUK_INTERNAL duk_ret_t duk_bi_object_prototype_to_string(duk_context *ctx) {
33597 	duk_push_this(ctx);
33598 	duk_to_object_class_string_top(ctx);
33599 	return 1;
33600 }
33601 
33602 DUK_INTERNAL duk_ret_t duk_bi_object_prototype_to_locale_string(duk_context *ctx) {
33603 	DUK_ASSERT_TOP(ctx, 0);
33604 	(void) duk_push_this_coercible_to_object(ctx);
33605 	duk_get_prop_stridx(ctx, 0, DUK_STRIDX_TO_STRING);
33606 	if (!duk_is_callable(ctx, 1)) {
33607 		return DUK_RET_TYPE_ERROR;
33608 	}
33609 	duk_dup(ctx, 0);  /* -> [ O toString O ] */
33610 	duk_call_method(ctx, 0);  /* XXX: call method tail call? */
33611 	return 1;
33612 }
33613 
33614 DUK_INTERNAL duk_ret_t duk_bi_object_prototype_value_of(duk_context *ctx) {
33615 	(void) duk_push_this_coercible_to_object(ctx);
33616 	return 1;
33617 }
33618 
33619 DUK_INTERNAL duk_ret_t duk_bi_object_prototype_is_prototype_of(duk_context *ctx) {
33620 	duk_hthread *thr = (duk_hthread *) ctx;
33621 	duk_hobject *h_v;
33622 	duk_hobject *h_obj;
33623 
33624 	DUK_ASSERT_TOP(ctx, 1);
33625 
33626 	h_v = duk_get_hobject(ctx, 0);
33627 	if (!h_v) {
33628 		duk_push_false(ctx);  /* XXX: tail call: return duk_push_false(ctx) */
33629 		return 1;
33630 	}
33631 
33632 	h_obj = duk_push_this_coercible_to_object(ctx);
33633 	DUK_ASSERT(h_obj != NULL);
33634 
33635 	/* E5.1 Section 15.2.4.6, step 3.a, lookup proto once before compare.
33636 	 * Prototype loops should cause an error to be thrown.
33637 	 */
33638 	duk_push_boolean(ctx, duk_hobject_prototype_chain_contains(thr, DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_v), h_obj, 0 /*ignore_loop*/));
33639 	return 1;
33640 }
33641 
33642 DUK_INTERNAL duk_ret_t duk_bi_object_prototype_has_own_property(duk_context *ctx) {
33643 	return duk_hobject_object_ownprop_helper(ctx, 0 /*required_desc_flags*/);
33644 }
33645 
33646 DUK_INTERNAL duk_ret_t duk_bi_object_prototype_property_is_enumerable(duk_context *ctx) {
33647 	return duk_hobject_object_ownprop_helper(ctx, DUK_PROPDESC_FLAG_ENUMERABLE /*required_desc_flags*/);
33648 }
33649 /*
33650  *  Pointer built-ins
33651  */
33652 
33653 /* include removed: duk_internal.h */
33654 
33655 /*
33656  *  Constructor
33657  */
33658 
33659 DUK_INTERNAL duk_ret_t duk_bi_pointer_constructor(duk_context *ctx) {
33660 	/* XXX: this behavior is quite useless now; it would be nice to be able
33661 	 * to create pointer values from e.g. numbers or strings.  Numbers are
33662 	 * problematic on 64-bit platforms though.  Hex encoded strings?
33663 	 */
33664 	if (duk_get_top(ctx) == 0) {
33665 		duk_push_pointer(ctx, NULL);
33666 	} else {
33667 		duk_to_pointer(ctx, 0);
33668 	}
33669 	DUK_ASSERT(duk_is_pointer(ctx, 0));
33670 	duk_set_top(ctx, 1);
33671 
33672 	if (duk_is_constructor_call(ctx)) {
33673 		duk_push_object_helper(ctx,
33674 		                       DUK_HOBJECT_FLAG_EXTENSIBLE |
33675 		                       DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_POINTER),
33676 		                       DUK_BIDX_POINTER_PROTOTYPE);
33677 
33678 		/* Pointer object internal value is immutable */
33679 		duk_dup(ctx, 0);
33680 		duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);
33681 	}
33682 	/* Note: unbalanced stack on purpose */
33683 
33684 	return 1;
33685 }
33686 
33687 /*
33688  *  toString(), valueOf()
33689  */
33690 
33691 DUK_INTERNAL duk_ret_t duk_bi_pointer_prototype_tostring_shared(duk_context *ctx) {
33692 	duk_tval *tv;
33693 	duk_small_int_t to_string = duk_get_current_magic(ctx);
33694 
33695 	duk_push_this(ctx);
33696 	tv = duk_require_tval(ctx, -1);
33697 	DUK_ASSERT(tv != NULL);
33698 
33699 	if (DUK_TVAL_IS_POINTER(tv)) {
33700 		/* nop */
33701 	} else if (DUK_TVAL_IS_OBJECT(tv)) {
33702 		duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
33703 		DUK_ASSERT(h != NULL);
33704 
33705 		/* Must be a "pointer object", i.e. class "Pointer" */
33706 		if (DUK_HOBJECT_GET_CLASS_NUMBER(h) != DUK_HOBJECT_CLASS_POINTER) {
33707 			goto type_error;
33708 		}
33709 
33710 		duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_VALUE);
33711 	} else {
33712 		goto type_error;
33713 	}
33714 
33715 	if (to_string) {
33716 		duk_to_string(ctx, -1);
33717 	}
33718 	return 1;
33719 
33720  type_error:
33721 	return DUK_RET_TYPE_ERROR;
33722 }
33723 /*
33724  *  Proxy built-in (ES6)
33725  */
33726 
33727 /* include removed: duk_internal.h */
33728 
33729 #if defined(DUK_USE_ES6_PROXY)
33730 DUK_INTERNAL duk_ret_t duk_bi_proxy_constructor(duk_context *ctx) {
33731 	duk_hobject *h_target;
33732 	duk_hobject *h_handler;
33733 
33734 	if (!duk_is_constructor_call(ctx)) {
33735 		return DUK_RET_TYPE_ERROR;
33736 	}
33737 
33738 	/* Reject a proxy object as the target because it would need
33739 	 * special handler in property lookups.  (ES6 has no such restriction)
33740 	 */
33741 	h_target = duk_require_hobject_or_lfunc_coerce(ctx, 0);
33742 	DUK_ASSERT(h_target != NULL);
33743 	if (DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h_target)) {
33744 		return DUK_RET_TYPE_ERROR;
33745 	}
33746 
33747 	/* Reject a proxy object as the handler because it would cause
33748 	 * potentially unbounded recursion.  (ES6 has no such restriction)
33749 	 */
33750 	h_handler = duk_require_hobject_or_lfunc_coerce(ctx, 1);
33751 	DUK_ASSERT(h_handler != NULL);
33752 	if (DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h_handler)) {
33753 		return DUK_RET_TYPE_ERROR;
33754 	}
33755 
33756 	/* XXX: the returned value is exotic in ES6, but we use a
33757 	 * simple object here with no prototype.  Without a prototype,
33758 	 * [[DefaultValue]] coercion fails which is abit confusing.
33759 	 * No callable check/handling in the current Proxy subset.
33760 	 */
33761 	(void) duk_push_object_helper_proto(ctx,
33762 	                                    DUK_HOBJECT_FLAG_EXTENSIBLE |
33763 	                                    DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ |
33764 	                                    DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
33765 	                                    NULL);
33766 	DUK_ASSERT_TOP(ctx, 3);
33767 
33768 	/* Make _Target and _Handler non-configurable and non-writable.
33769 	 * They can still be forcibly changed by C code (both user and
33770 	 * Duktape internal), but not by Ecmascript code.
33771 	 */
33772 
33773 	/* Proxy target */
33774 	duk_dup(ctx, 0);
33775 	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_TARGET, DUK_PROPDESC_FLAGS_NONE);
33776 
33777 	/* Proxy handler */
33778 	duk_dup(ctx, 1);
33779 	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_HANDLER, DUK_PROPDESC_FLAGS_NONE);
33780 
33781 	return 1;  /* replacement handler */
33782 }
33783 #else  /* DUK_USE_ES6_PROXY */
33784 DUK_INTERNAL duk_ret_t duk_bi_proxy_constructor(duk_context *ctx) {
33785 	DUK_UNREF(ctx);
33786 	return DUK_RET_UNSUPPORTED_ERROR;
33787 }
33788 #endif  /* DUK_USE_ES6_PROXY */
33789 /*
33790  *  RegExp built-ins
33791  */
33792 
33793 /* include removed: duk_internal.h */
33794 
33795 #ifdef DUK_USE_REGEXP_SUPPORT
33796 
33797 DUK_LOCAL void duk__get_this_regexp(duk_context *ctx) {
33798 	duk_hobject *h;
33799 
33800 	duk_push_this(ctx);
33801 	h = duk_require_hobject_with_class(ctx, -1, DUK_HOBJECT_CLASS_REGEXP);
33802 	DUK_ASSERT(h != NULL);
33803 	DUK_UNREF(h);
33804 	duk_insert(ctx, 0);  /* prepend regexp to valstack 0 index */
33805 }
33806 
33807 /* XXX: much to improve (code size) */
33808 DUK_INTERNAL duk_ret_t duk_bi_regexp_constructor(duk_context *ctx) {
33809 	duk_hthread *thr = (duk_hthread *) ctx;
33810 	duk_hobject *h_pattern;
33811 
33812 	DUK_ASSERT_TOP(ctx, 2);
33813 	h_pattern = duk_get_hobject(ctx, 0);
33814 
33815 	if (!duk_is_constructor_call(ctx) &&
33816 	    h_pattern != NULL &&
33817 	    DUK_HOBJECT_GET_CLASS_NUMBER(h_pattern) == DUK_HOBJECT_CLASS_REGEXP &&
33818 	    duk_is_undefined(ctx, 1)) {
33819 		/* Called as a function, pattern has [[Class]] "RegExp" and
33820 		 * flags is undefined -> return object as is.
33821 		 */
33822 		duk_dup(ctx, 0);
33823 		return 1;
33824 	}
33825 
33826 	/* Else functionality is identical for function call and constructor
33827 	 * call.
33828 	 */
33829 
33830 	if (h_pattern != NULL &&
33831 	    DUK_HOBJECT_GET_CLASS_NUMBER(h_pattern) == DUK_HOBJECT_CLASS_REGEXP) {
33832 		if (duk_is_undefined(ctx, 1)) {
33833 			duk_bool_t flag_g, flag_i, flag_m;
33834 			duk_get_prop_stridx(ctx, 0, DUK_STRIDX_SOURCE);
33835 			flag_g = duk_get_prop_stridx_boolean(ctx, 0, DUK_STRIDX_GLOBAL, NULL);
33836 			flag_i = duk_get_prop_stridx_boolean(ctx, 0, DUK_STRIDX_IGNORE_CASE, NULL);
33837 			flag_m = duk_get_prop_stridx_boolean(ctx, 0, DUK_STRIDX_MULTILINE, NULL);
33838 
33839 			duk_push_sprintf(ctx, "%s%s%s",
33840 			                 (const char *) (flag_g ? "g" : ""),
33841 			                 (const char *) (flag_i ? "i" : ""),
33842 			                 (const char *) (flag_m ? "m" : ""));
33843 
33844 			/* [ ... pattern flags ] */
33845 		} else {
33846 			return DUK_RET_TYPE_ERROR;
33847 		}
33848 	} else {
33849 		if (duk_is_undefined(ctx, 0)) {
33850 			duk_push_string(ctx, "");
33851 		} else {
33852 			duk_dup(ctx, 0);
33853 			duk_to_string(ctx, -1);
33854 		}
33855 		if (duk_is_undefined(ctx, 1)) {
33856 			duk_push_string(ctx, "");
33857 		} else {
33858 			duk_dup(ctx, 1);
33859 			duk_to_string(ctx, -1);
33860 		}
33861 
33862 		/* [ ... pattern flags ] */
33863 	}
33864 
33865 	DUK_DDD(DUK_DDDPRINT("RegExp constructor/function call, pattern=%!T, flags=%!T",
33866 	                     (duk_tval *) duk_get_tval(ctx, -2), (duk_tval *) duk_get_tval(ctx, -1)));
33867 
33868 	/* [ ... pattern flags ] */
33869 
33870 	duk_regexp_compile(thr);
33871 
33872 	/* [ ... bytecode escaped_source ] */
33873 
33874 	duk_regexp_create_instance(thr);
33875 
33876 	/* [ ... RegExp ] */
33877 
33878 	return 1;
33879 }
33880 
33881 DUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_exec(duk_context *ctx) {
33882 	duk__get_this_regexp(ctx);
33883 
33884 	/* [ regexp input ] */
33885 
33886 	duk_regexp_match((duk_hthread *) ctx);
33887 
33888 	/* [ result ] */
33889 
33890 	return 1;
33891 }
33892 
33893 DUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_test(duk_context *ctx) {
33894 	duk__get_this_regexp(ctx);
33895 
33896 	/* [ regexp input ] */
33897 
33898 	/* result object is created and discarded; wasteful but saves code space */
33899 	duk_regexp_match((duk_hthread *) ctx);
33900 
33901 	/* [ result ] */
33902 
33903 	duk_push_boolean(ctx, (duk_is_null(ctx, -1) ? 0 : 1));
33904 
33905 	return 1;
33906 }
33907 
33908 DUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_to_string(duk_context *ctx) {
33909 	duk_hstring *h_bc;
33910 	duk_small_int_t re_flags;
33911 
33912 #if 0
33913 	/* A little tricky string approach to provide the flags string.
33914 	 * This depends on the specific flag values in duk_regexp.h,
33915 	 * which needs to be asserted for.  In practice this doesn't
33916 	 * produce more compact code than the easier approach in use.
33917 	 */
33918 
33919 	const char *flag_strings = "gim\0gi\0gm\0g\0";
33920 	duk_uint8_t flag_offsets[8] = {
33921 		(duk_uint8_t) 3,   /* flags: ""    */
33922 		(duk_uint8_t) 10,  /* flags: "g"   */
33923 		(duk_uint8_t) 5,   /* flags: "i"   */
33924 		(duk_uint8_t) 4,   /* flags: "gi"  */
33925 		(duk_uint8_t) 2,   /* flags: "m"   */
33926 		(duk_uint8_t) 7,   /* flags: "gm"  */
33927 		(duk_uint8_t) 1,   /* flags: "im"  */
33928 		(duk_uint8_t) 0,   /* flags: "gim" */
33929 	};
33930 	DUK_ASSERT(DUK_RE_FLAG_GLOBAL == 1);
33931 	DUK_ASSERT(DUK_RE_FLAG_IGNORE_CASE == 2);
33932 	DUK_ASSERT(DUK_RE_FLAG_MULTILINE == 4);
33933 #endif
33934 
33935 	duk__get_this_regexp(ctx);
33936 
33937 	/* [ regexp ] */
33938 
33939 	duk_get_prop_stridx(ctx, 0, DUK_STRIDX_SOURCE);
33940 	duk_get_prop_stridx(ctx, 0, DUK_STRIDX_INT_BYTECODE);
33941 	h_bc = duk_get_hstring(ctx, -1);
33942 	DUK_ASSERT(h_bc != NULL);
33943 	DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(h_bc) >= 1);
33944 	DUK_ASSERT(DUK_HSTRING_GET_CHARLEN(h_bc) >= 1);
33945 	DUK_ASSERT(DUK_HSTRING_GET_DATA(h_bc)[0] < 0x80);
33946 	re_flags = (duk_small_int_t) DUK_HSTRING_GET_DATA(h_bc)[0];
33947 
33948 	/* [ regexp source bytecode ] */
33949 
33950 #if 1
33951 	/* This is a cleaner approach and also produces smaller code than
33952 	 * the other alternative.  Use duk_require_string() for format
33953 	 * safety (although the source property should always exist).
33954 	 */
33955 	duk_push_sprintf(ctx, "/%s/%s%s%s",
33956 	                 (const char *) duk_require_string(ctx, -2),  /* require to be safe */
33957 	                 (re_flags & DUK_RE_FLAG_GLOBAL) ? "g" : "",
33958 	                 (re_flags & DUK_RE_FLAG_IGNORE_CASE) ? "i" : "",
33959 	                 (re_flags & DUK_RE_FLAG_MULTILINE) ? "m" : "");
33960 #else
33961 	/* This should not be necessary because no-one should tamper with the
33962 	 * regexp bytecode, but is prudent to avoid potential segfaults if that
33963 	 * were to happen for some reason.
33964 	 */
33965 	re_flags &= 0x07;
33966 	DUK_ASSERT(re_flags >= 0 && re_flags <= 7);  /* three flags */
33967 	duk_push_sprintf(ctx, "/%s/%s",
33968 	                 (const char *) duk_require_string(ctx, -2),
33969 	                 (const char *) (flag_strings + flag_offsets[re_flags]));
33970 #endif
33971 
33972 	return 1;
33973 }
33974 
33975 #else  /* DUK_USE_REGEXP_SUPPORT */
33976 
33977 DUK_INTERNAL duk_ret_t duk_bi_regexp_constructor(duk_context *ctx) {
33978 	DUK_UNREF(ctx);
33979 	return DUK_RET_UNSUPPORTED_ERROR;
33980 }
33981 
33982 DUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_exec(duk_context *ctx) {
33983 	DUK_UNREF(ctx);
33984 	return DUK_RET_UNSUPPORTED_ERROR;
33985 }
33986 
33987 DUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_test(duk_context *ctx) {
33988 	DUK_UNREF(ctx);
33989 	return DUK_RET_UNSUPPORTED_ERROR;
33990 }
33991 
33992 DUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_to_string(duk_context *ctx) {
33993 	DUK_UNREF(ctx);
33994 	return DUK_RET_UNSUPPORTED_ERROR;
33995 }
33996 
33997 #endif  /* DUK_USE_REGEXP_SUPPORT */
33998 /*
33999  *  String built-ins
34000  */
34001 
34002 /* XXX: There are several limitations in the current implementation for
34003  * strings with >= 0x80000000UL characters.  In some cases one would need
34004  * to be able to represent the range [-0xffffffff,0xffffffff] and so on.
34005  * Generally character and byte length are assumed to fit into signed 32
34006  * bits (< 0x80000000UL).  Places with issues are not marked explicitly
34007  * below in all cases, look for signed type usage (duk_int_t etc) for
34008  * offsets/lengths.
34009  */
34010 
34011 /* include removed: duk_internal.h */
34012 
34013 /*
34014  *  Constructor
34015  */
34016 
34017 DUK_INTERNAL duk_ret_t duk_bi_string_constructor(duk_context *ctx) {
34018 	/* String constructor needs to distinguish between an argument not given at all
34019 	 * vs. given as 'undefined'.  We're a vararg function to handle this properly.
34020 	 */
34021 
34022 	if (duk_get_top(ctx) == 0) {
34023 		duk_push_hstring_stridx(ctx, DUK_STRIDX_EMPTY_STRING);
34024 	} else {
34025 		duk_to_string(ctx, 0);
34026 	}
34027 	DUK_ASSERT(duk_is_string(ctx, 0));
34028 	duk_set_top(ctx, 1);
34029 
34030 	if (duk_is_constructor_call(ctx)) {
34031 		duk_push_object_helper(ctx,
34032 		                       DUK_HOBJECT_FLAG_EXTENSIBLE |
34033 		                       DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ |
34034 		                       DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_STRING),
34035 		                       DUK_BIDX_STRING_PROTOTYPE);
34036 
34037 		/* String object internal value is immutable */
34038 		duk_dup(ctx, 0);
34039 		duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);
34040 	}
34041 	/* Note: unbalanced stack on purpose */
34042 
34043 	return 1;
34044 }
34045 
34046 DUK_INTERNAL duk_ret_t duk_bi_string_constructor_from_char_code(duk_context *ctx) {
34047 	duk_hthread *thr = (duk_hthread *) ctx;
34048 	duk_bufwriter_ctx bw_alloc;
34049 	duk_bufwriter_ctx *bw;
34050 	duk_idx_t i, n;
34051 	duk_ucodepoint_t cp;
34052 
34053 	/* XXX: It would be nice to build the string directly but ToUint16()
34054 	 * coercion is needed so a generic helper would not be very
34055 	 * helpful (perhaps coerce the value stack first here and then
34056 	 * build a string from a duk_tval number sequence in one go?).
34057 	 */
34058 
34059 	n = duk_get_top(ctx);
34060 
34061 	bw = &bw_alloc;
34062 	DUK_BW_INIT_PUSHBUF(thr, bw, n);  /* initial estimate for ASCII only codepoints */
34063 
34064 	for (i = 0; i < n; i++) {
34065 		/* XXX: could improve bufwriter handling to write multiple codepoints
34066 		 * with one ensure call but the relative benefit would be quite small.
34067 		 */
34068 
34069 #if defined(DUK_USE_NONSTD_STRING_FROMCHARCODE_32BIT)
34070 		/* ToUint16() coercion is mandatory in the E5.1 specification, but
34071 		 * this non-compliant behavior makes more sense because we support
34072 		 * non-BMP codepoints.  Don't use CESU-8 because that'd create
34073 		 * surrogate pairs.
34074 		 */
34075 
34076 		cp = (duk_ucodepoint_t) duk_to_uint32(ctx, i);
34077 		DUK_BW_WRITE_ENSURE_XUTF8(thr, bw, cp);
34078 #else
34079 		cp = (duk_ucodepoint_t) duk_to_uint16(ctx, i);
34080 		DUK_BW_WRITE_ENSURE_CESU8(thr, bw, cp);
34081 #endif
34082 	}
34083 
34084 	DUK_BW_COMPACT(thr, bw);
34085 	duk_to_string(ctx, -1);
34086 	return 1;
34087 }
34088 
34089 /*
34090  *  toString(), valueOf()
34091  */
34092 
34093 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_to_string(duk_context *ctx) {
34094 	duk_tval *tv;
34095 
34096 	duk_push_this(ctx);
34097 	tv = duk_require_tval(ctx, -1);
34098 	DUK_ASSERT(tv != NULL);
34099 
34100 	if (DUK_TVAL_IS_STRING(tv)) {
34101 		/* return as is */
34102 		return 1;
34103 	} else if (DUK_TVAL_IS_OBJECT(tv)) {
34104 		duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
34105 		DUK_ASSERT(h != NULL);
34106 
34107 		/* Must be a "string object", i.e. class "String" */
34108 		if (DUK_HOBJECT_GET_CLASS_NUMBER(h) != DUK_HOBJECT_CLASS_STRING) {
34109 			goto type_error;
34110 		}
34111 
34112 		duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_VALUE);
34113 		DUK_ASSERT(duk_is_string(ctx, -1));
34114 
34115 		return 1;
34116 	} else {
34117 		goto type_error;
34118 	}
34119 
34120 	/* never here, but fall through */
34121 
34122  type_error:
34123 	return DUK_RET_TYPE_ERROR;
34124 }
34125 
34126 /*
34127  *  Character and charcode access
34128  */
34129 
34130 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_char_at(duk_context *ctx) {
34131 	duk_int_t pos;
34132 
34133 	/* XXX: faster implementation */
34134 
34135 	(void) duk_push_this_coercible_to_string(ctx);
34136 	pos = duk_to_int(ctx, 0);
34137 	duk_substring(ctx, -1, pos, pos + 1);
34138 	return 1;
34139 }
34140 
34141 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_char_code_at(duk_context *ctx) {
34142 	duk_hthread *thr = (duk_hthread *) ctx;
34143 	duk_int_t pos;
34144 	duk_hstring *h;
34145 	duk_bool_t clamped;
34146 
34147 	/* XXX: faster implementation */
34148 
34149 	DUK_DDD(DUK_DDDPRINT("arg=%!T", (duk_tval *) duk_get_tval(ctx, 0)));
34150 
34151 	h = duk_push_this_coercible_to_string(ctx);
34152 	DUK_ASSERT(h != NULL);
34153 
34154 	pos = duk_to_int_clamped_raw(ctx,
34155 	                             0 /*index*/,
34156 	                             0 /*min(incl)*/,
34157 	                             DUK_HSTRING_GET_CHARLEN(h) - 1 /*max(incl)*/,
34158 	                             &clamped /*out_clamped*/);
34159 	if (clamped) {
34160 		duk_push_number(ctx, DUK_DOUBLE_NAN);
34161 		return 1;
34162 	}
34163 
34164 	duk_push_u32(ctx, (duk_uint32_t) duk_hstring_char_code_at_raw(thr, h, pos));
34165 	return 1;
34166 }
34167 
34168 /*
34169  *  substring(), substr(), slice()
34170  */
34171 
34172 /* XXX: any chance of merging these three similar but still slightly
34173  * different algorithms so that footprint would be reduced?
34174  */
34175 
34176 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_substring(duk_context *ctx) {
34177 	duk_hstring *h;
34178 	duk_int_t start_pos, end_pos;
34179 	duk_int_t len;
34180 
34181 	h = duk_push_this_coercible_to_string(ctx);
34182 	DUK_ASSERT(h != NULL);
34183 	len = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h);
34184 
34185 	/* [ start end str ] */
34186 
34187 	start_pos = duk_to_int_clamped(ctx, 0, 0, len);
34188 	if (duk_is_undefined(ctx, 1)) {
34189 		end_pos = len;
34190 	} else {
34191 		end_pos = duk_to_int_clamped(ctx, 1, 0, len);
34192 	}
34193 	DUK_ASSERT(start_pos >= 0 && start_pos <= len);
34194 	DUK_ASSERT(end_pos >= 0 && end_pos <= len);
34195 
34196 	if (start_pos > end_pos) {
34197 		duk_int_t tmp = start_pos;
34198 		start_pos = end_pos;
34199 		end_pos = tmp;
34200 	}
34201 
34202 	DUK_ASSERT(end_pos >= start_pos);
34203 
34204 	duk_substring(ctx, -1, (duk_size_t) start_pos, (duk_size_t) end_pos);
34205 	return 1;
34206 }
34207 
34208 #ifdef DUK_USE_SECTION_B
34209 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_substr(duk_context *ctx) {
34210 	duk_hstring *h;
34211 	duk_int_t start_pos, end_pos;
34212 	duk_int_t len;
34213 
34214 	/* Unlike non-obsolete String calls, substr() algorithm in E5.1
34215 	 * specification will happily coerce undefined and null to strings
34216 	 * ("undefined" and "null").
34217 	 */
34218 	duk_push_this(ctx);
34219 	h = duk_to_hstring(ctx, -1);
34220 	DUK_ASSERT(h != NULL);
34221 	len = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h);
34222 
34223 	/* [ start length str ] */
34224 
34225 	/* The implementation for computing of start_pos and end_pos differs
34226 	 * from the standard algorithm, but is intended to result in the exactly
34227 	 * same behavior.  This is not always obvious.
34228 	 */
34229 
34230 	/* combines steps 2 and 5; -len ensures max() not needed for step 5 */
34231 	start_pos = duk_to_int_clamped(ctx, 0, -len, len);
34232 	if (start_pos < 0) {
34233 		start_pos = len + start_pos;
34234 	}
34235 	DUK_ASSERT(start_pos >= 0 && start_pos <= len);
34236 
34237 	/* combines steps 3, 6; step 7 is not needed */
34238 	if (duk_is_undefined(ctx, 1)) {
34239 		end_pos = len;
34240 	} else {
34241 		DUK_ASSERT(start_pos <= len);
34242 		end_pos = start_pos + duk_to_int_clamped(ctx, 1, 0, len - start_pos);
34243 	}
34244 	DUK_ASSERT(start_pos >= 0 && start_pos <= len);
34245 	DUK_ASSERT(end_pos >= 0 && end_pos <= len);
34246 	DUK_ASSERT(end_pos >= start_pos);
34247 
34248 	duk_substring(ctx, -1, (duk_size_t) start_pos, (duk_size_t) end_pos);
34249 	return 1;
34250 }
34251 #else  /* DUK_USE_SECTION_B */
34252 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_substr(duk_context *ctx) {
34253 	DUK_UNREF(ctx);
34254 	return DUK_RET_UNSUPPORTED_ERROR;
34255 }
34256 #endif  /* DUK_USE_SECTION_B */
34257 
34258 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_slice(duk_context *ctx) {
34259 	duk_hstring *h;
34260 	duk_int_t start_pos, end_pos;
34261 	duk_int_t len;
34262 
34263 	h = duk_push_this_coercible_to_string(ctx);
34264 	DUK_ASSERT(h != NULL);
34265 	len = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h);
34266 
34267 	/* [ start end str ] */
34268 
34269 	start_pos = duk_to_int_clamped(ctx, 0, -len, len);
34270 	if (start_pos < 0) {
34271 		start_pos = len + start_pos;
34272 	}
34273 	if (duk_is_undefined(ctx, 1)) {
34274 		end_pos = len;
34275 	} else {
34276 		end_pos = duk_to_int_clamped(ctx, 1, -len, len);
34277 		if (end_pos < 0) {
34278 			end_pos = len + end_pos;
34279 		}
34280 	}
34281 	DUK_ASSERT(start_pos >= 0 && start_pos <= len);
34282 	DUK_ASSERT(end_pos >= 0 && end_pos <= len);
34283 
34284 	if (end_pos < start_pos) {
34285 		end_pos = start_pos;
34286 	}
34287 
34288 	DUK_ASSERT(end_pos >= start_pos);
34289 
34290 	duk_substring(ctx, -1, (duk_size_t) start_pos, (duk_size_t) end_pos);
34291 	return 1;
34292 }
34293 
34294 /*
34295  *  Case conversion
34296  */
34297 
34298 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_caseconv_shared(duk_context *ctx) {
34299 	duk_hthread *thr = (duk_hthread *) ctx;
34300 	duk_small_int_t uppercase = duk_get_current_magic(ctx);
34301 
34302 	(void) duk_push_this_coercible_to_string(ctx);
34303 	duk_unicode_case_convert_string(thr, (duk_bool_t) uppercase);
34304 	return 1;
34305 }
34306 
34307 /*
34308  *  indexOf() and lastIndexOf()
34309  */
34310 
34311 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_indexof_shared(duk_context *ctx) {
34312 	duk_hthread *thr = (duk_hthread *) ctx;
34313 	duk_hstring *h_this;
34314 	duk_hstring *h_search;
34315 	duk_int_t clen_this;
34316 	duk_int_t cpos;
34317 	duk_int_t bpos;
34318 	const duk_uint8_t *p_start, *p_end, *p;
34319 	const duk_uint8_t *q_start;
34320 	duk_int_t q_blen;
34321 	duk_uint8_t firstbyte;
34322 	duk_uint8_t t;
34323 	duk_small_int_t is_lastindexof = duk_get_current_magic(ctx);  /* 0=indexOf, 1=lastIndexOf */
34324 
34325 	h_this = duk_push_this_coercible_to_string(ctx);
34326 	DUK_ASSERT(h_this != NULL);
34327 	clen_this = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h_this);
34328 
34329 	h_search = duk_to_hstring(ctx, 0);
34330 	DUK_ASSERT(h_search != NULL);
34331 	q_start = DUK_HSTRING_GET_DATA(h_search);
34332 	q_blen = (duk_int_t) DUK_HSTRING_GET_BYTELEN(h_search);
34333 
34334 	duk_to_number(ctx, 1);
34335 	if (duk_is_nan(ctx, 1) && is_lastindexof) {
34336 		/* indexOf: NaN should cause pos to be zero.
34337 		 * lastIndexOf: NaN should cause pos to be +Infinity
34338 		 * (and later be clamped to len).
34339 		 */
34340 		cpos = clen_this;
34341 	} else {
34342 		cpos = duk_to_int_clamped(ctx, 1, 0, clen_this);
34343 	}
34344 
34345 	/* Empty searchstring always matches; cpos must be clamped here.
34346 	 * (If q_blen were < 0 due to clamped coercion, it would also be
34347 	 * caught here.)
34348 	 */
34349 	if (q_blen <= 0) {
34350 		duk_push_int(ctx, cpos);
34351 		return 1;
34352 	}
34353 	DUK_ASSERT(q_blen > 0);
34354 
34355 	bpos = (duk_int_t) duk_heap_strcache_offset_char2byte(thr, h_this, (duk_uint32_t) cpos);
34356 
34357 	p_start = DUK_HSTRING_GET_DATA(h_this);
34358 	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_this);
34359 	p = p_start + bpos;
34360 
34361 	/* This loop is optimized for size.  For speed, there should be
34362 	 * two separate loops, and we should ensure that memcmp() can be
34363 	 * used without an extra "will searchstring fit" check.  Doing
34364 	 * the preconditioning for 'p' and 'p_end' is easy but cpos
34365 	 * must be updated if 'p' is wound back (backward scanning).
34366 	 */
34367 
34368 	firstbyte = q_start[0];  /* leading byte of match string */
34369 	while (p <= p_end && p >= p_start) {
34370 		t = *p;
34371 
34372 		/* For Ecmascript strings, this check can only match for
34373 		 * initial UTF-8 bytes (not continuation bytes).  For other
34374 		 * strings all bets are off.
34375 		 */
34376 
34377 		if ((t == firstbyte) && ((duk_size_t) (p_end - p) >= (duk_size_t) q_blen)) {
34378 			DUK_ASSERT(q_blen > 0);  /* no issues with memcmp() zero size, even if broken */
34379 			if (DUK_MEMCMP((const void *) p, (const void *) q_start, (size_t) q_blen) == 0) {
34380 				duk_push_int(ctx, cpos);
34381 				return 1;
34382 			}
34383 		}
34384 
34385 		/* track cpos while scanning */
34386 		if (is_lastindexof) {
34387 			/* when going backwards, we decrement cpos 'early';
34388 			 * 'p' may point to a continuation byte of the char
34389 			 * at offset 'cpos', but that's OK because we'll
34390 			 * backtrack all the way to the initial byte.
34391 			 */
34392 			if ((t & 0xc0) != 0x80) {
34393 				cpos--;
34394 			}
34395 			p--;
34396 		} else {
34397 			if ((t & 0xc0) != 0x80) {
34398 				cpos++;
34399 			}
34400 			p++;
34401 		}
34402 	}
34403 
34404 	/* Not found.  Empty string case is handled specially above. */
34405 	duk_push_int(ctx, -1);
34406 	return 1;
34407 }
34408 
34409 /*
34410  *  replace()
34411  */
34412 
34413 /* XXX: the current implementation works but is quite clunky; it compiles
34414  * to almost 1,4kB of x86 code so it needs to be simplified (better approach,
34415  * shared helpers, etc).  Some ideas for refactoring:
34416  *
34417  * - a primitive to convert a string into a regexp matcher (reduces matching
34418  *   code at the cost of making matching much slower)
34419  * - use replace() as a basic helper for match() and split(), which are both
34420  *   much simpler
34421  * - API call to get_prop and to_boolean
34422  */
34423 
34424 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_replace(duk_context *ctx) {
34425 	duk_hthread *thr = (duk_hthread *) ctx;
34426 	duk_hstring *h_input;
34427 	duk_hstring *h_match;
34428 	duk_hstring *h_search;
34429 	duk_hobject *h_re;
34430 	duk_bufwriter_ctx bw_alloc;
34431 	duk_bufwriter_ctx *bw;
34432 #ifdef DUK_USE_REGEXP_SUPPORT
34433 	duk_bool_t is_regexp;
34434 	duk_bool_t is_global;
34435 #endif
34436 	duk_bool_t is_repl_func;
34437 	duk_uint32_t match_start_coff, match_start_boff;
34438 #ifdef DUK_USE_REGEXP_SUPPORT
34439 	duk_int_t match_caps;
34440 #endif
34441 	duk_uint32_t prev_match_end_boff;
34442 	const duk_uint8_t *r_start, *r_end, *r;   /* repl string scan */
34443 	duk_size_t tmp_sz;
34444 
34445 	DUK_ASSERT_TOP(ctx, 2);
34446 	h_input = duk_push_this_coercible_to_string(ctx);
34447 	DUK_ASSERT(h_input != NULL);
34448 
34449 	bw = &bw_alloc;
34450 	DUK_BW_INIT_PUSHBUF(thr, bw, DUK_HSTRING_GET_BYTELEN(h_input));  /* input size is good output starting point */
34451 
34452 	DUK_ASSERT_TOP(ctx, 4);
34453 
34454 	/* stack[0] = search value
34455 	 * stack[1] = replace value
34456 	 * stack[2] = input string
34457 	 * stack[3] = result buffer
34458 	 */
34459 
34460 	h_re = duk_get_hobject_with_class(ctx, 0, DUK_HOBJECT_CLASS_REGEXP);
34461 	if (h_re) {
34462 #ifdef DUK_USE_REGEXP_SUPPORT
34463 		is_regexp = 1;
34464 		is_global = duk_get_prop_stridx_boolean(ctx, 0, DUK_STRIDX_GLOBAL, NULL);
34465 
34466 		if (is_global) {
34467 			/* start match from beginning */
34468 			duk_push_int(ctx, 0);
34469 			duk_put_prop_stridx(ctx, 0, DUK_STRIDX_LAST_INDEX);
34470 		}
34471 #else  /* DUK_USE_REGEXP_SUPPORT */
34472 		return DUK_RET_UNSUPPORTED_ERROR;
34473 #endif  /* DUK_USE_REGEXP_SUPPORT */
34474 	} else {
34475 		duk_to_string(ctx, 0);
34476 #ifdef DUK_USE_REGEXP_SUPPORT
34477 		is_regexp = 0;
34478 		is_global = 0;
34479 #endif
34480 	}
34481 
34482 	if (duk_is_function(ctx, 1)) {
34483 		is_repl_func = 1;
34484 		r_start = NULL;
34485 		r_end = NULL;
34486 	} else {
34487 		duk_hstring *h_repl;
34488 
34489 		is_repl_func = 0;
34490 		h_repl = duk_to_hstring(ctx, 1);
34491 		DUK_ASSERT(h_repl != NULL);
34492 		r_start = DUK_HSTRING_GET_DATA(h_repl);
34493 		r_end = r_start + DUK_HSTRING_GET_BYTELEN(h_repl);
34494 	}
34495 
34496 	prev_match_end_boff = 0;
34497 
34498 	for (;;) {
34499 		/*
34500 		 *  If matching with a regexp:
34501 		 *    - non-global RegExp: lastIndex not touched on a match, zeroed
34502 		 *      on a non-match
34503 		 *    - global RegExp: on match, lastIndex will be updated by regexp
34504 		 *      executor to point to next char after the matching part (so that
34505 		 *      characters in the matching part are not matched again)
34506 		 *
34507 		 *  If matching with a string:
34508 		 *    - always non-global match, find first occurrence
34509 		 *
34510 		 *  We need:
34511 		 *    - The character offset of start-of-match for the replacer function
34512 		 *    - The byte offsets for start-of-match and end-of-match to implement
34513 		 *      the replacement values $&, $`, and $', and to copy non-matching
34514 		 *      input string portions (including header and trailer) verbatim.
34515 		 *
34516 		 *  NOTE: the E5.1 specification is a bit vague how the RegExp should
34517 		 *  behave in the replacement process; e.g. is matching done first for
34518 		 *  all matches (in the global RegExp case) before any replacer calls
34519 		 *  are made?  See: test-bi-string-proto-replace.js for discussion.
34520 		 */
34521 
34522 		DUK_ASSERT_TOP(ctx, 4);
34523 
34524 #ifdef DUK_USE_REGEXP_SUPPORT
34525 		if (is_regexp) {
34526 			duk_dup(ctx, 0);
34527 			duk_dup(ctx, 2);
34528 			duk_regexp_match(thr);  /* [ ... regexp input ] -> [ res_obj ] */
34529 			if (!duk_is_object(ctx, -1)) {
34530 				duk_pop(ctx);
34531 				break;
34532 			}
34533 
34534 			duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INDEX);
34535 			DUK_ASSERT(duk_is_number(ctx, -1));
34536 			match_start_coff = duk_get_int(ctx, -1);
34537 			duk_pop(ctx);
34538 
34539 			duk_get_prop_index(ctx, -1, 0);
34540 			DUK_ASSERT(duk_is_string(ctx, -1));
34541 			h_match = duk_get_hstring(ctx, -1);
34542 			DUK_ASSERT(h_match != NULL);
34543 			duk_pop(ctx);  /* h_match is borrowed, remains reachable through match_obj */
34544 
34545 			if (DUK_HSTRING_GET_BYTELEN(h_match) == 0) {
34546 				/* This should be equivalent to match() algorithm step 8.f.iii.2:
34547 				 * detect an empty match and allow it, but don't allow it twice.
34548 				 */
34549 				duk_uint32_t last_index;
34550 
34551 				duk_get_prop_stridx(ctx, 0, DUK_STRIDX_LAST_INDEX);
34552 				last_index = (duk_uint32_t) duk_get_uint(ctx, -1);
34553 				DUK_DDD(DUK_DDDPRINT("empty match, bump lastIndex: %ld -> %ld",
34554 				                     (long) last_index, (long) (last_index + 1)));
34555 				duk_pop(ctx);
34556 				duk_push_int(ctx, last_index + 1);
34557 				duk_put_prop_stridx(ctx, 0, DUK_STRIDX_LAST_INDEX);
34558 			}
34559 
34560 			DUK_ASSERT(duk_get_length(ctx, -1) <= DUK_INT_MAX);  /* string limits */
34561 			match_caps = (duk_int_t) duk_get_length(ctx, -1);
34562 		} else {
34563 #else  /* DUK_USE_REGEXP_SUPPORT */
34564 		{  /* unconditionally */
34565 #endif  /* DUK_USE_REGEXP_SUPPORT */
34566 			const duk_uint8_t *p_start, *p_end, *p;   /* input string scan */
34567 			const duk_uint8_t *q_start;               /* match string */
34568 			duk_size_t q_blen;
34569 
34570 #ifdef DUK_USE_REGEXP_SUPPORT
34571 			DUK_ASSERT(!is_global);  /* single match always */
34572 #endif
34573 
34574 			p_start = DUK_HSTRING_GET_DATA(h_input);
34575 			p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
34576 			p = p_start;
34577 
34578 			h_search = duk_get_hstring(ctx, 0);
34579 			DUK_ASSERT(h_search != NULL);
34580 			q_start = DUK_HSTRING_GET_DATA(h_search);
34581 			q_blen = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_search);
34582 
34583 			p_end -= q_blen;  /* ensure full memcmp() fits in while */
34584 
34585 			match_start_coff = 0;
34586 
34587 			while (p <= p_end) {
34588 				DUK_ASSERT(p + q_blen <= DUK_HSTRING_GET_DATA(h_input) + DUK_HSTRING_GET_BYTELEN(h_input));
34589 				if (DUK_MEMCMP((const void *) p, (const void *) q_start, (size_t) q_blen) == 0) {
34590 					duk_dup(ctx, 0);
34591 					h_match = duk_get_hstring(ctx, -1);
34592 					DUK_ASSERT(h_match != NULL);
34593 #ifdef DUK_USE_REGEXP_SUPPORT
34594 					match_caps = 0;
34595 #endif
34596 					goto found;
34597 				}
34598 
34599 				/* track utf-8 non-continuation bytes */
34600 				if ((p[0] & 0xc0) != 0x80) {
34601 					match_start_coff++;
34602 				}
34603 				p++;
34604 			}
34605 
34606 			/* not found */
34607 			break;
34608 		}
34609 	 found:
34610 
34611 		/* stack[0] = search value
34612 		 * stack[1] = replace value
34613 		 * stack[2] = input string
34614 		 * stack[3] = result buffer
34615 		 * stack[4] = regexp match OR match string
34616 		 */
34617 
34618 		match_start_boff = duk_heap_strcache_offset_char2byte(thr, h_input, match_start_coff);
34619 
34620 		tmp_sz = (duk_size_t) (match_start_boff - prev_match_end_boff);
34621 		DUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff, tmp_sz);
34622 
34623 		prev_match_end_boff = match_start_boff + DUK_HSTRING_GET_BYTELEN(h_match);
34624 
34625 		if (is_repl_func) {
34626 			duk_idx_t idx_args;
34627 			duk_hstring *h_repl;
34628 
34629 			/* regexp res_obj is at index 4 */
34630 
34631 			duk_dup(ctx, 1);
34632 			idx_args = duk_get_top(ctx);
34633 
34634 #ifdef DUK_USE_REGEXP_SUPPORT
34635 			if (is_regexp) {
34636 				duk_int_t idx;
34637 				duk_require_stack(ctx, match_caps + 2);
34638 				for (idx = 0; idx < match_caps; idx++) {
34639 					/* match followed by capture(s) */
34640 					duk_get_prop_index(ctx, 4, idx);
34641 				}
34642 			} else {
34643 #else  /* DUK_USE_REGEXP_SUPPORT */
34644 			{  /* unconditionally */
34645 #endif  /* DUK_USE_REGEXP_SUPPORT */
34646 				/* match == search string, by definition */
34647 				duk_dup(ctx, 0);
34648 			}
34649 			duk_push_int(ctx, match_start_coff);
34650 			duk_dup(ctx, 2);
34651 
34652 			/* [ ... replacer match [captures] match_char_offset input ] */
34653 
34654 			duk_call(ctx, duk_get_top(ctx) - idx_args);
34655 			h_repl = duk_to_hstring(ctx, -1);  /* -> [ ... repl_value ] */
34656 			DUK_ASSERT(h_repl != NULL);
34657 
34658 			DUK_BW_WRITE_ENSURE_HSTRING(thr, bw, h_repl);
34659 
34660 			duk_pop(ctx);  /* repl_value */
34661 		} else {
34662 			r = r_start;
34663 
34664 			while (r < r_end) {
34665 				duk_int_t ch1;
34666 				duk_int_t ch2;
34667 #ifdef DUK_USE_REGEXP_SUPPORT
34668 				duk_int_t ch3;
34669 #endif
34670 				duk_size_t left;
34671 
34672 				ch1 = *r++;
34673 				if (ch1 != DUK_ASC_DOLLAR) {
34674 					goto repl_write;
34675 				}
34676 				left = r_end - r;
34677 
34678 				if (left <= 0) {
34679 					goto repl_write;
34680 				}
34681 
34682 				ch2 = r[0];
34683 				switch ((int) ch2) {
34684 				case DUK_ASC_DOLLAR: {
34685 					ch1 = (1 << 8) + DUK_ASC_DOLLAR;
34686 					goto repl_write;
34687 				}
34688 				case DUK_ASC_AMP: {
34689 					DUK_BW_WRITE_ENSURE_HSTRING(thr, bw, h_match);
34690 					r++;
34691 					continue;
34692 				}
34693 				case DUK_ASC_GRAVE: {
34694 					tmp_sz = (duk_size_t) match_start_boff;
34695 					DUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input), tmp_sz);
34696 					r++;
34697 					continue;
34698 				}
34699 				case DUK_ASC_SINGLEQUOTE: {
34700 					duk_uint32_t match_end_boff;
34701 
34702 					/* Use match charlen instead of bytelen, just in case the input and
34703 					 * match codepoint encodings would have different lengths.
34704 					 */
34705 					match_end_boff = duk_heap_strcache_offset_char2byte(thr,
34706 					                                                    h_input,
34707 					                                                    match_start_coff + DUK_HSTRING_GET_CHARLEN(h_match));
34708 
34709 					tmp_sz = (duk_size_t) (DUK_HSTRING_GET_BYTELEN(h_input) - match_end_boff);
34710 					DUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input) + match_end_boff, tmp_sz);
34711 					r++;
34712 					continue;
34713 				}
34714 				default: {
34715 #ifdef DUK_USE_REGEXP_SUPPORT
34716 					duk_int_t capnum, captmp, capadv;
34717 					/* XXX: optional check, match_caps is zero if no regexp,
34718 					 * so dollar will be interpreted literally anyway.
34719 					 */
34720 
34721 					if (!is_regexp) {
34722 						goto repl_write;
34723 					}
34724 
34725 					if (!(ch2 >= DUK_ASC_0 && ch2 <= DUK_ASC_9)) {
34726 						goto repl_write;
34727 					}
34728 					capnum = ch2 - DUK_ASC_0;
34729 					capadv = 1;
34730 
34731 					if (left >= 2) {
34732 						ch3 = r[1];
34733 						if (ch3 >= DUK_ASC_0 && ch3 <= DUK_ASC_9) {
34734 							captmp = capnum * 10 + (ch3 - DUK_ASC_0);
34735 							if (captmp < match_caps) {
34736 								capnum = captmp;
34737 								capadv = 2;
34738 							}
34739 						}
34740 					}
34741 
34742 					if (capnum > 0 && capnum < match_caps) {
34743 						DUK_ASSERT(is_regexp != 0);  /* match_caps == 0 without regexps */
34744 
34745 						/* regexp res_obj is at offset 4 */
34746 						duk_get_prop_index(ctx, 4, (duk_uarridx_t) capnum);
34747 						if (duk_is_string(ctx, -1)) {
34748 							duk_hstring *h_tmp_str;
34749 
34750 							h_tmp_str = duk_get_hstring(ctx, -1);
34751 							DUK_ASSERT(h_tmp_str != NULL);
34752 
34753 							DUK_BW_WRITE_ENSURE_HSTRING(thr, bw, h_tmp_str);
34754 						} else {
34755 							/* undefined -> skip (replaced with empty) */
34756 						}
34757 						duk_pop(ctx);
34758 						r += capadv;
34759 						continue;
34760 					} else {
34761 						goto repl_write;
34762 					}
34763 #else  /* DUK_USE_REGEXP_SUPPORT */
34764 					goto repl_write;  /* unconditionally */
34765 #endif  /* DUK_USE_REGEXP_SUPPORT */
34766 				}  /* default case */
34767 				}  /* switch (ch2) */
34768 
34769 			 repl_write:
34770 				/* ch1 = (r_increment << 8) + byte */
34771 
34772 				DUK_BW_WRITE_ENSURE_U8(thr, bw, (duk_uint8_t) (ch1 & 0xff));
34773 				r += ch1 >> 8;
34774 			}  /* while repl */
34775 		}  /* if (is_repl_func) */
34776 
34777 		duk_pop(ctx);  /* pop regexp res_obj or match string */
34778 
34779 #ifdef DUK_USE_REGEXP_SUPPORT
34780 		if (!is_global) {
34781 #else
34782 		{  /* unconditionally; is_global==0 */
34783 #endif
34784 			break;
34785 		}
34786 	}
34787 
34788 	/* trailer */
34789 	tmp_sz = (duk_size_t) (DUK_HSTRING_GET_BYTELEN(h_input) - prev_match_end_boff);
34790 	DUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff, tmp_sz);
34791 
34792 	DUK_ASSERT_TOP(ctx, 4);
34793 	DUK_BW_COMPACT(thr, bw);
34794 	duk_to_string(ctx, -1);
34795 	return 1;
34796 }
34797 
34798 /*
34799  *  split()
34800  */
34801 
34802 /* XXX: very messy now, but works; clean up, remove unused variables (nomimally
34803  * used so compiler doesn't complain).
34804  */
34805 
34806 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_split(duk_context *ctx) {
34807 	duk_hthread *thr = (duk_hthread *) ctx;
34808 	duk_hstring *h_input;
34809 	duk_hstring *h_sep;
34810 	duk_uint32_t limit;
34811 	duk_uint32_t arr_idx;
34812 #ifdef DUK_USE_REGEXP_SUPPORT
34813 	duk_bool_t is_regexp;
34814 #endif
34815 	duk_bool_t matched;  /* set to 1 if any match exists (needed for empty input special case) */
34816 	duk_uint32_t prev_match_end_coff, prev_match_end_boff;
34817 	duk_uint32_t match_start_boff, match_start_coff;
34818 	duk_uint32_t match_end_boff, match_end_coff;
34819 
34820 	DUK_UNREF(thr);
34821 
34822 	h_input = duk_push_this_coercible_to_string(ctx);
34823 	DUK_ASSERT(h_input != NULL);
34824 
34825 	duk_push_array(ctx);
34826 
34827 	if (duk_is_undefined(ctx, 1)) {
34828 		limit = 0xffffffffUL;
34829 	} else {
34830 		limit = duk_to_uint32(ctx, 1);
34831 	}
34832 
34833 	if (limit == 0) {
34834 		return 1;
34835 	}
34836 
34837 	/* If the separator is a RegExp, make a "clone" of it.  The specification
34838 	 * algorithm calls [[Match]] directly for specific indices; we emulate this
34839 	 * by tweaking lastIndex and using a "force global" variant of duk_regexp_match()
34840 	 * which will use global-style matching even when the RegExp itself is non-global.
34841 	 */
34842 
34843 	if (duk_is_undefined(ctx, 0)) {
34844 		/* The spec algorithm first does "R = ToString(separator)" before checking
34845 		 * whether separator is undefined.  Since this is side effect free, we can
34846 		 * skip the ToString() here.
34847 		 */
34848 		duk_dup(ctx, 2);
34849 		duk_put_prop_index(ctx, 3, 0);
34850 		return 1;
34851 	} else if (duk_get_hobject_with_class(ctx, 0, DUK_HOBJECT_CLASS_REGEXP) != NULL) {
34852 #ifdef DUK_USE_REGEXP_SUPPORT
34853 		duk_push_hobject_bidx(ctx, DUK_BIDX_REGEXP_CONSTRUCTOR);
34854 		duk_dup(ctx, 0);
34855 		duk_new(ctx, 1);  /* [ ... RegExp val ] -> [ ... res ] */
34856 		duk_replace(ctx, 0);
34857 		/* lastIndex is initialized to zero by new RegExp() */
34858 		is_regexp = 1;
34859 #else
34860 		return DUK_RET_UNSUPPORTED_ERROR;
34861 #endif
34862 	} else {
34863 		duk_to_string(ctx, 0);
34864 #ifdef DUK_USE_REGEXP_SUPPORT
34865 		is_regexp = 0;
34866 #endif
34867 	}
34868 
34869 	/* stack[0] = separator (string or regexp)
34870 	 * stack[1] = limit
34871 	 * stack[2] = input string
34872 	 * stack[3] = result array
34873 	 */
34874 
34875 	prev_match_end_boff = 0;
34876 	prev_match_end_coff = 0;
34877 	arr_idx = 0;
34878 	matched = 0;
34879 
34880 	for (;;) {
34881 		/*
34882 		 *  The specification uses RegExp [[Match]] to attempt match at specific
34883 		 *  offsets.  We don't have such a primitive, so we use an actual RegExp
34884 		 *  and tweak lastIndex.  Since the RegExp may be non-global, we use a
34885 		 *  special variant which forces global-like behavior for matching.
34886 		 */
34887 
34888 		DUK_ASSERT_TOP(ctx, 4);
34889 
34890 #ifdef DUK_USE_REGEXP_SUPPORT
34891 		if (is_regexp) {
34892 			duk_dup(ctx, 0);
34893 			duk_dup(ctx, 2);
34894 			duk_regexp_match_force_global(thr);  /* [ ... regexp input ] -> [ res_obj ] */
34895 			if (!duk_is_object(ctx, -1)) {
34896 				duk_pop(ctx);
34897 				break;
34898 			}
34899 			matched = 1;
34900 
34901 			duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INDEX);
34902 			DUK_ASSERT(duk_is_number(ctx, -1));
34903 			match_start_coff = duk_get_int(ctx, -1);
34904 			match_start_boff = duk_heap_strcache_offset_char2byte(thr, h_input, match_start_coff);
34905 			duk_pop(ctx);
34906 
34907 			if (match_start_coff == DUK_HSTRING_GET_CHARLEN(h_input)) {
34908 				/* don't allow an empty match at the end of the string */
34909 				duk_pop(ctx);
34910 				break;
34911 			}
34912 
34913 			duk_get_prop_stridx(ctx, 0, DUK_STRIDX_LAST_INDEX);
34914 			DUK_ASSERT(duk_is_number(ctx, -1));
34915 			match_end_coff = duk_get_int(ctx, -1);
34916 			match_end_boff = duk_heap_strcache_offset_char2byte(thr, h_input, match_end_coff);
34917 			duk_pop(ctx);
34918 
34919 			/* empty match -> bump and continue */
34920 			if (prev_match_end_boff == match_end_boff) {
34921 				duk_push_int(ctx, match_end_coff + 1);
34922 				duk_put_prop_stridx(ctx, 0, DUK_STRIDX_LAST_INDEX);
34923 				duk_pop(ctx);
34924 				continue;
34925 			}
34926 		} else {
34927 #else  /* DUK_USE_REGEXP_SUPPORT */
34928 		{  /* unconditionally */
34929 #endif  /* DUK_USE_REGEXP_SUPPORT */
34930 			const duk_uint8_t *p_start, *p_end, *p;   /* input string scan */
34931 			const duk_uint8_t *q_start;               /* match string */
34932 			duk_size_t q_blen, q_clen;
34933 
34934 			p_start = DUK_HSTRING_GET_DATA(h_input);
34935 			p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
34936 			p = p_start + prev_match_end_boff;
34937 
34938 			h_sep = duk_get_hstring(ctx, 0);
34939 			DUK_ASSERT(h_sep != NULL);
34940 			q_start = DUK_HSTRING_GET_DATA(h_sep);
34941 			q_blen = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_sep);
34942 			q_clen = (duk_size_t) DUK_HSTRING_GET_CHARLEN(h_sep);
34943 
34944 			p_end -= q_blen;  /* ensure full memcmp() fits in while */
34945 
34946 			match_start_coff = prev_match_end_coff;
34947 
34948 			if (q_blen == 0) {
34949 				/* Handle empty separator case: it will always match, and always
34950 				 * triggers the check in step 13.c.iii initially.  Note that we
34951 				 * must skip to either end of string or start of first codepoint,
34952 				 * skipping over any continuation bytes!
34953 				 *
34954 				 * Don't allow an empty string to match at the end of the input.
34955 				 */
34956 
34957 				matched = 1;  /* empty separator can always match */
34958 
34959 				match_start_coff++;
34960 				p++;
34961 				while (p < p_end) {
34962 					if ((p[0] & 0xc0) != 0x80) {
34963 						goto found;
34964 					}
34965 					p++;
34966 				}
34967 				goto not_found;
34968 			}
34969 
34970 			DUK_ASSERT(q_blen > 0 && q_clen > 0);
34971 			while (p <= p_end) {
34972 				DUK_ASSERT(p + q_blen <= DUK_HSTRING_GET_DATA(h_input) + DUK_HSTRING_GET_BYTELEN(h_input));
34973 				DUK_ASSERT(q_blen > 0);  /* no issues with empty memcmp() */
34974 				if (DUK_MEMCMP((const void *) p, (const void *) q_start, (size_t) q_blen) == 0) {
34975 					/* never an empty match, so step 13.c.iii can't be triggered */
34976 					goto found;
34977 				}
34978 
34979 				/* track utf-8 non-continuation bytes */
34980 				if ((p[0] & 0xc0) != 0x80) {
34981 					match_start_coff++;
34982 				}
34983 				p++;
34984 			}
34985 
34986 		 not_found:
34987 			/* not found */
34988 			break;
34989 
34990 		 found:
34991 			matched = 1;
34992 			match_start_boff = (duk_uint32_t) (p - p_start);
34993 			match_end_coff = (duk_uint32_t) (match_start_coff + q_clen);  /* constrained by string length */
34994 			match_end_boff = (duk_uint32_t) (match_start_boff + q_blen);  /* ditto */
34995 
34996 			/* empty match (may happen with empty separator) -> bump and continue */
34997 			if (prev_match_end_boff == match_end_boff) {
34998 				prev_match_end_boff++;
34999 				prev_match_end_coff++;
35000 				continue;
35001 			}
35002 		}  /* if (is_regexp) */
35003 
35004 		/* stack[0] = separator (string or regexp)
35005 		 * stack[1] = limit
35006 		 * stack[2] = input string
35007 		 * stack[3] = result array
35008 		 * stack[4] = regexp res_obj (if is_regexp)
35009 		 */
35010 
35011 		DUK_DDD(DUK_DDDPRINT("split; match_start b=%ld,c=%ld, match_end b=%ld,c=%ld, prev_end b=%ld,c=%ld",
35012 		                     (long) match_start_boff, (long) match_start_coff,
35013 		                     (long) match_end_boff, (long) match_end_coff,
35014 		                     (long) prev_match_end_boff, (long) prev_match_end_coff));
35015 
35016 		duk_push_lstring(ctx,
35017 		                 (const char *) (DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff),
35018 		                 (duk_size_t) (match_start_boff - prev_match_end_boff));
35019 		duk_put_prop_index(ctx, 3, arr_idx);
35020 		arr_idx++;
35021 		if (arr_idx >= limit) {
35022 			goto hit_limit;
35023 		}
35024 
35025 #ifdef DUK_USE_REGEXP_SUPPORT
35026 		if (is_regexp) {
35027 			duk_size_t i, len;
35028 
35029 			len = duk_get_length(ctx, 4);
35030 			for (i = 1; i < len; i++) {
35031 				DUK_ASSERT(i <= DUK_UARRIDX_MAX);  /* cannot have >4G captures */
35032 				duk_get_prop_index(ctx, 4, (duk_uarridx_t) i);
35033 				duk_put_prop_index(ctx, 3, arr_idx);
35034 				arr_idx++;
35035 				if (arr_idx >= limit) {
35036 					goto hit_limit;
35037 				}
35038 			}
35039 
35040 			duk_pop(ctx);
35041 			/* lastIndex already set up for next match */
35042 		} else {
35043 #else  /* DUK_USE_REGEXP_SUPPORT */
35044 		{  /* unconditionally */
35045 #endif  /* DUK_USE_REGEXP_SUPPORT */
35046 			/* no action */
35047 		}
35048 
35049 		prev_match_end_boff = match_end_boff;
35050 		prev_match_end_coff = match_end_coff;
35051 		continue;
35052 	}  /* for */
35053 
35054 	/* Combined step 11 (empty string special case) and 14-15. */
35055 
35056 	DUK_DDD(DUK_DDDPRINT("split trailer; prev_end b=%ld,c=%ld",
35057 	                     (long) prev_match_end_boff, (long) prev_match_end_coff));
35058 
35059 	if (DUK_HSTRING_GET_CHARLEN(h_input) > 0 || !matched) {
35060 		/* Add trailer if:
35061 		 *   a) non-empty input
35062 		 *   b) empty input and no (zero size) match found (step 11)
35063 		 */
35064 
35065 		duk_push_lstring(ctx,
35066 		                 (const char *) DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff,
35067 		                 (duk_size_t) (DUK_HSTRING_GET_BYTELEN(h_input) - prev_match_end_boff));
35068 		duk_put_prop_index(ctx, 3, arr_idx);
35069 		/* No arr_idx update or limit check */
35070 	}
35071 
35072 	return 1;
35073 
35074  hit_limit:
35075 #ifdef DUK_USE_REGEXP_SUPPORT
35076 	if (is_regexp) {
35077 		duk_pop(ctx);
35078 	}
35079 #endif
35080 
35081 	return 1;
35082 }
35083 
35084 /*
35085  *  Various
35086  */
35087 
35088 #ifdef DUK_USE_REGEXP_SUPPORT
35089 DUK_LOCAL void duk__to_regexp_helper(duk_context *ctx, duk_idx_t index, duk_bool_t force_new) {
35090 	duk_hobject *h;
35091 
35092 	/* Shared helper for match() steps 3-4, search() steps 3-4. */
35093 
35094 	DUK_ASSERT(index >= 0);
35095 
35096 	if (force_new) {
35097 		goto do_new;
35098 	}
35099 
35100 	h = duk_get_hobject_with_class(ctx, index, DUK_HOBJECT_CLASS_REGEXP);
35101 	if (!h) {
35102 		goto do_new;
35103 	}
35104 	return;
35105 
35106  do_new:
35107 	duk_push_hobject_bidx(ctx, DUK_BIDX_REGEXP_CONSTRUCTOR);
35108 	duk_dup(ctx, index);
35109 	duk_new(ctx, 1);  /* [ ... RegExp val ] -> [ ... res ] */
35110 	duk_replace(ctx, index);
35111 }
35112 #endif  /* DUK_USE_REGEXP_SUPPORT */
35113 
35114 #ifdef DUK_USE_REGEXP_SUPPORT
35115 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_search(duk_context *ctx) {
35116 	duk_hthread *thr = (duk_hthread *) ctx;
35117 
35118 	/* Easiest way to implement the search required by the specification
35119 	 * is to do a RegExp test() with lastIndex forced to zero.  To avoid
35120 	 * side effects on the argument, "clone" the RegExp if a RegExp was
35121 	 * given as input.
35122 	 *
35123 	 * The global flag of the RegExp should be ignored; setting lastIndex
35124 	 * to zero (which happens when "cloning" the RegExp) should have an
35125 	 * equivalent effect.
35126 	 */
35127 
35128 	DUK_ASSERT_TOP(ctx, 1);
35129 	(void) duk_push_this_coercible_to_string(ctx);  /* at index 1 */
35130 	duk__to_regexp_helper(ctx, 0 /*index*/, 1 /*force_new*/);
35131 
35132 	/* stack[0] = regexp
35133 	 * stack[1] = string
35134 	 */
35135 
35136 	/* Avoid using RegExp.prototype methods, as they're writable and
35137 	 * configurable and may have been changed.
35138 	 */
35139 
35140 	duk_dup(ctx, 0);
35141 	duk_dup(ctx, 1);  /* [ ... re_obj input ] */
35142 	duk_regexp_match(thr);  /* -> [ ... res_obj ] */
35143 
35144 	if (!duk_is_object(ctx, -1)) {
35145 		duk_push_int(ctx, -1);
35146 		return 1;
35147 	}
35148 
35149 	duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INDEX);
35150 	DUK_ASSERT(duk_is_number(ctx, -1));
35151 	return 1;
35152 }
35153 #else  /* DUK_USE_REGEXP_SUPPORT */
35154 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_search(duk_context *ctx) {
35155 	DUK_UNREF(ctx);
35156 	return DUK_RET_UNSUPPORTED_ERROR;
35157 }
35158 #endif  /* DUK_USE_REGEXP_SUPPORT */
35159 
35160 #ifdef DUK_USE_REGEXP_SUPPORT
35161 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_match(duk_context *ctx) {
35162 	duk_hthread *thr = (duk_hthread *) ctx;
35163 	duk_bool_t global;
35164 	duk_int_t prev_last_index;
35165 	duk_int_t this_index;
35166 	duk_int_t arr_idx;
35167 
35168 	DUK_ASSERT_TOP(ctx, 1);
35169 	(void) duk_push_this_coercible_to_string(ctx);
35170 	duk__to_regexp_helper(ctx, 0 /*index*/, 0 /*force_new*/);
35171 	global = duk_get_prop_stridx_boolean(ctx, 0, DUK_STRIDX_GLOBAL, NULL);
35172 	DUK_ASSERT_TOP(ctx, 2);
35173 
35174 	/* stack[0] = regexp
35175 	 * stack[1] = string
35176 	 */
35177 
35178 	if (!global) {
35179 		duk_regexp_match(thr);  /* -> [ res_obj ] */
35180 		return 1;  /* return 'res_obj' */
35181 	}
35182 
35183 	/* Global case is more complex. */
35184 
35185 	/* [ regexp string ] */
35186 
35187 	duk_push_int(ctx, 0);
35188 	duk_put_prop_stridx(ctx, 0, DUK_STRIDX_LAST_INDEX);
35189 	duk_push_array(ctx);
35190 
35191 	/* [ regexp string res_arr ] */
35192 
35193 	prev_last_index = 0;
35194 	arr_idx = 0;
35195 
35196 	for (;;) {
35197 		DUK_ASSERT_TOP(ctx, 3);
35198 
35199 		duk_dup(ctx, 0);
35200 		duk_dup(ctx, 1);
35201 		duk_regexp_match(thr);  /* -> [ ... regexp string ] -> [ ... res_obj ] */
35202 
35203 		if (!duk_is_object(ctx, -1)) {
35204 			duk_pop(ctx);
35205 			break;
35206 		}
35207 
35208 		duk_get_prop_stridx(ctx, 0, DUK_STRIDX_LAST_INDEX);
35209 		DUK_ASSERT(duk_is_number(ctx, -1));
35210 		this_index = duk_get_int(ctx, -1);
35211 		duk_pop(ctx);
35212 
35213 		if (this_index == prev_last_index) {
35214 			this_index++;
35215 			duk_push_int(ctx, this_index);
35216 			duk_put_prop_stridx(ctx, 0, DUK_STRIDX_LAST_INDEX);
35217 		}
35218 		prev_last_index = this_index;
35219 
35220 		duk_get_prop_index(ctx, -1, 0);  /* match string */
35221 		duk_put_prop_index(ctx, 2, arr_idx);
35222 		arr_idx++;
35223 		duk_pop(ctx);  /* res_obj */
35224 	}
35225 
35226 	if (arr_idx == 0) {
35227 		duk_push_null(ctx);
35228 	}
35229 
35230 	return 1;  /* return 'res_arr' or 'null' */
35231 }
35232 #else  /* DUK_USE_REGEXP_SUPPORT */
35233 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_match(duk_context *ctx) {
35234 	DUK_UNREF(ctx);
35235 	return DUK_RET_UNSUPPORTED_ERROR;
35236 }
35237 #endif  /* DUK_USE_REGEXP_SUPPORT */
35238 
35239 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_concat(duk_context *ctx) {
35240 	/* duk_concat() coerces arguments with ToString() in correct order */
35241 	(void) duk_push_this_coercible_to_string(ctx);
35242 	duk_insert(ctx, 0);  /* this is relatively expensive */
35243 	duk_concat(ctx, duk_get_top(ctx));
35244 	return 1;
35245 }
35246 
35247 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_trim(duk_context *ctx) {
35248 	DUK_ASSERT_TOP(ctx, 0);
35249 	(void) duk_push_this_coercible_to_string(ctx);
35250 	duk_trim(ctx, 0);
35251 	DUK_ASSERT_TOP(ctx, 1);
35252 	return 1;
35253 }
35254 
35255 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_locale_compare(duk_context *ctx) {
35256 	duk_hstring *h1;
35257 	duk_hstring *h2;
35258 	duk_size_t h1_len, h2_len, prefix_len;
35259 	duk_small_int_t ret = 0;
35260 	duk_small_int_t rc;
35261 
35262 	/* The current implementation of localeCompare() is simply a codepoint
35263 	 * by codepoint comparison, implemented with a simple string compare
35264 	 * because UTF-8 should preserve codepoint ordering (assuming valid
35265 	 * shortest UTF-8 encoding).
35266 	 *
35267 	 * The specification requires that the return value must be related
35268 	 * to the sort order: e.g. negative means that 'this' comes before
35269 	 * 'that' in sort order.  We assume an ascending sort order.
35270 	 */
35271 
35272 	/* XXX: could share code with duk_js_ops.c, duk_js_compare_helper */
35273 
35274 	h1 = duk_push_this_coercible_to_string(ctx);
35275 	DUK_ASSERT(h1 != NULL);
35276 
35277 	h2 = duk_to_hstring(ctx, 0);
35278 	DUK_ASSERT(h2 != NULL);
35279 
35280 	h1_len = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h1);
35281 	h2_len = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h2);
35282 	prefix_len = (h1_len <= h2_len ? h1_len : h2_len);
35283 
35284 	/* Zero size compare not an issue with DUK_MEMCMP. */
35285 	rc = (duk_small_int_t) DUK_MEMCMP((const void *) DUK_HSTRING_GET_DATA(h1),
35286 	                                  (const void *) DUK_HSTRING_GET_DATA(h2),
35287 	                                  (size_t) prefix_len);
35288 
35289 	if (rc < 0) {
35290 		ret = -1;
35291 		goto done;
35292 	} else if (rc > 0) {
35293 		ret = 1;
35294 		goto done;
35295 	}
35296 
35297 	/* prefix matches, lengths matter now */
35298 	if (h1_len > h2_len) {
35299 		ret = 1;
35300 		goto done;
35301 	} else if (h1_len == h2_len) {
35302 		DUK_ASSERT(ret == 0);
35303 		goto done;
35304 	}
35305 	ret = -1;
35306 	goto done;
35307 
35308  done:
35309 	duk_push_int(ctx, (duk_int_t) ret);
35310 	return 1;
35311 }
35312 /*
35313  *  Thread builtins
35314  */
35315 
35316 /* include removed: duk_internal.h */
35317 
35318 /*
35319  *  Constructor
35320  */
35321 
35322 DUK_INTERNAL duk_ret_t duk_bi_thread_constructor(duk_context *ctx) {
35323 	duk_hthread *new_thr;
35324 	duk_hobject *func;
35325 
35326 	/* XXX: need a duk_require_func_or_lfunc_coerce() */
35327 	if (!duk_is_callable(ctx, 0)) {
35328 		return DUK_RET_TYPE_ERROR;
35329 	}
35330 	func = duk_require_hobject_or_lfunc_coerce(ctx, 0);
35331 	DUK_ASSERT(func != NULL);
35332 
35333 	duk_push_thread(ctx);
35334 	new_thr = (duk_hthread *) duk_get_hobject(ctx, -1);
35335 	DUK_ASSERT(new_thr != NULL);
35336 	new_thr->state = DUK_HTHREAD_STATE_INACTIVE;
35337 
35338 	/* push initial function call to new thread stack; this is
35339 	 * picked up by resume().
35340 	 */
35341 	duk_push_hobject((duk_context *) new_thr, func);
35342 
35343 	return 1;  /* return thread */
35344 }
35345 
35346 /*
35347  *  Resume a thread.
35348  *
35349  *  The thread must be in resumable state, either (a) new thread which hasn't
35350  *  yet started, or (b) a thread which has previously yielded.  This method
35351  *  must be called from an Ecmascript function.
35352  *
35353  *  Args:
35354  *    - thread
35355  *    - value
35356  *    - isError (defaults to false)
35357  *
35358  *  Note: yield and resume handling is currently asymmetric.
35359  */
35360 
35361 DUK_INTERNAL duk_ret_t duk_bi_thread_resume(duk_context *ctx) {
35362 	duk_hthread *thr = (duk_hthread *) ctx;
35363 	duk_hthread *thr_resume;
35364 	duk_tval *tv;
35365 	duk_hobject *func;
35366 	duk_hobject *caller_func;
35367 	duk_small_int_t is_error;
35368 
35369 	DUK_DDD(DUK_DDDPRINT("Duktape.Thread.resume(): thread=%!T, value=%!T, is_error=%!T",
35370 	                     (duk_tval *) duk_get_tval(ctx, 0),
35371 	                     (duk_tval *) duk_get_tval(ctx, 1),
35372 	                     (duk_tval *) duk_get_tval(ctx, 2)));
35373 
35374 	DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);
35375 	DUK_ASSERT(thr->heap->curr_thread == thr);
35376 
35377 	thr_resume = duk_require_hthread(ctx, 0);
35378 	is_error = (duk_small_int_t) duk_to_boolean(ctx, 2);
35379 	duk_set_top(ctx, 2);
35380 
35381 	/* [ thread value ] */
35382 
35383 	/*
35384 	 *  Thread state and calling context checks
35385 	 */
35386 
35387 	if (thr->callstack_top < 2) {
35388 		DUK_DD(DUK_DDPRINT("resume state invalid: callstack should contain at least 2 entries (caller and Duktape.Thread.resume)"));
35389 		goto state_error;
35390 	}
35391 	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 1) != NULL);  /* us */
35392 	DUK_ASSERT(DUK_HOBJECT_IS_NATIVEFUNCTION(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 1)));
35393 	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 2) != NULL);  /* caller */
35394 
35395 	caller_func = DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 2);
35396 	if (!DUK_HOBJECT_IS_COMPILEDFUNCTION(caller_func)) {
35397 		DUK_DD(DUK_DDPRINT("resume state invalid: caller must be Ecmascript code"));
35398 		goto state_error;
35399 	}
35400 
35401 	/* Note: there is no requirement that: 'thr->callstack_preventcount == 1'
35402 	 * like for yield.
35403 	 */
35404 
35405 	if (thr_resume->state != DUK_HTHREAD_STATE_INACTIVE &&
35406 	    thr_resume->state != DUK_HTHREAD_STATE_YIELDED) {
35407 		DUK_DD(DUK_DDPRINT("resume state invalid: target thread must be INACTIVE or YIELDED"));
35408 		goto state_error;
35409 	}
35410 
35411 	DUK_ASSERT(thr_resume->state == DUK_HTHREAD_STATE_INACTIVE ||
35412 	           thr_resume->state == DUK_HTHREAD_STATE_YIELDED);
35413 
35414 	/* Further state-dependent pre-checks */
35415 
35416 	if (thr_resume->state == DUK_HTHREAD_STATE_YIELDED) {
35417 		/* no pre-checks now, assume a previous yield() has left things in
35418 		 * tip-top shape (longjmp handler will assert for these).
35419 		 */
35420 	} else {
35421 		DUK_ASSERT(thr_resume->state == DUK_HTHREAD_STATE_INACTIVE);
35422 
35423 		if ((thr_resume->callstack_top != 0) ||
35424 		    (thr_resume->valstack_top - thr_resume->valstack != 1)) {
35425 			goto state_invalid_initial;
35426 		}
35427 		tv = &thr_resume->valstack_top[-1];
35428 		DUK_ASSERT(tv >= thr_resume->valstack && tv < thr_resume->valstack_top);
35429 		if (!DUK_TVAL_IS_OBJECT(tv)) {
35430 			goto state_invalid_initial;
35431 		}
35432 		func = DUK_TVAL_GET_OBJECT(tv);
35433 		DUK_ASSERT(func != NULL);
35434 		if (!DUK_HOBJECT_IS_COMPILEDFUNCTION(func)) {
35435 			/* Note: cannot be a bound function either right now,
35436 			 * this would be easy to relax though.
35437 			 */
35438 			goto state_invalid_initial;
35439 		}
35440 
35441 	}
35442 
35443 	/*
35444 	 *  The error object has been augmented with a traceback and other
35445 	 *  info from its creation point -- usually another thread.  The
35446 	 *  error handler is called here right before throwing, but it also
35447 	 *  runs in the resumer's thread.  It might be nice to get a traceback
35448 	 *  from the resumee but this is not the case now.
35449 	 */
35450 
35451 #if defined(DUK_USE_AUGMENT_ERROR_THROW)
35452 	if (is_error) {
35453 		DUK_ASSERT_TOP(ctx, 2);  /* value (error) is at stack top */
35454 		duk_err_augment_error_throw(thr);  /* in resumer's context */
35455 	}
35456 #endif
35457 
35458 #ifdef DUK_USE_DEBUG
35459 	if (is_error) {
35460 		DUK_DDD(DUK_DDDPRINT("RESUME ERROR: thread=%!T, value=%!T",
35461 		                     (duk_tval *) duk_get_tval(ctx, 0),
35462 		                     (duk_tval *) duk_get_tval(ctx, 1)));
35463 	} else if (thr_resume->state == DUK_HTHREAD_STATE_YIELDED) {
35464 		DUK_DDD(DUK_DDDPRINT("RESUME NORMAL: thread=%!T, value=%!T",
35465 		                     (duk_tval *) duk_get_tval(ctx, 0),
35466 		                     (duk_tval *) duk_get_tval(ctx, 1)));
35467 	} else {
35468 		DUK_DDD(DUK_DDDPRINT("RESUME INITIAL: thread=%!T, value=%!T",
35469 		                     (duk_tval *) duk_get_tval(ctx, 0),
35470 		                     (duk_tval *) duk_get_tval(ctx, 1)));
35471 	}
35472 #endif
35473 
35474 	thr->heap->lj.type = DUK_LJ_TYPE_RESUME;
35475 
35476 	/* lj value2: thread */
35477 	DUK_ASSERT(thr->valstack_bottom < thr->valstack_top);
35478 	DUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value2, &thr->valstack_bottom[0]);  /* side effects */
35479 
35480 	/* lj value1: value */
35481 	DUK_ASSERT(thr->valstack_bottom + 1 < thr->valstack_top);
35482 	DUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value1, &thr->valstack_bottom[1]);  /* side effects */
35483 	DUK_TVAL_CHKFAST_INPLACE(&thr->heap->lj.value1);
35484 
35485 	thr->heap->lj.iserror = is_error;
35486 
35487 	DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL);  /* call is from executor, so we know we have a jmpbuf */
35488 	duk_err_longjmp(thr);  /* execution resumes in bytecode executor */
35489 	return 0;  /* never here */
35490 
35491  state_invalid_initial:
35492 	DUK_ERROR_TYPE(thr, "invalid initial thread state/stack");
35493 	return 0;  /* never here */
35494 
35495  state_error:
35496 	DUK_ERROR_TYPE(thr, "invalid state");
35497 	return 0;  /* never here */
35498 }
35499 
35500 /*
35501  *  Yield the current thread.
35502  *
35503  *  The thread must be in yieldable state: it must have a resumer, and there
35504  *  must not be any yield-preventing calls (native calls and constructor calls,
35505  *  currently) in the thread's call stack (otherwise a resume would not be
35506  *  possible later).  This method must be called from an Ecmascript function.
35507  *
35508  *  Args:
35509  *    - value
35510  *    - isError (defaults to false)
35511  *
35512  *  Note: yield and resume handling is currently asymmetric.
35513  */
35514 
35515 DUK_INTERNAL duk_ret_t duk_bi_thread_yield(duk_context *ctx) {
35516 	duk_hthread *thr = (duk_hthread *) ctx;
35517 	duk_hobject *caller_func;
35518 	duk_small_int_t is_error;
35519 
35520 	DUK_DDD(DUK_DDDPRINT("Duktape.Thread.yield(): value=%!T, is_error=%!T",
35521 	                     (duk_tval *) duk_get_tval(ctx, 0),
35522 	                     (duk_tval *) duk_get_tval(ctx, 1)));
35523 
35524 	DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);
35525 	DUK_ASSERT(thr->heap->curr_thread == thr);
35526 
35527 	is_error = (duk_small_int_t) duk_to_boolean(ctx, 1);
35528 	duk_set_top(ctx, 1);
35529 
35530 	/* [ value ] */
35531 
35532 	/*
35533 	 *  Thread state and calling context checks
35534 	 */
35535 
35536 	if (!thr->resumer) {
35537 		DUK_DD(DUK_DDPRINT("yield state invalid: current thread must have a resumer"));
35538 		goto state_error;
35539 	}
35540 	DUK_ASSERT(thr->resumer->state == DUK_HTHREAD_STATE_RESUMED);
35541 
35542 	if (thr->callstack_top < 2) {
35543 		DUK_DD(DUK_DDPRINT("yield state invalid: callstack should contain at least 2 entries (caller and Duktape.Thread.yield)"));
35544 		goto state_error;
35545 	}
35546 	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 1) != NULL);  /* us */
35547 	DUK_ASSERT(DUK_HOBJECT_IS_NATIVEFUNCTION(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 1)));
35548 	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 2) != NULL);  /* caller */
35549 
35550 	caller_func = DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 2);
35551 	if (!DUK_HOBJECT_IS_COMPILEDFUNCTION(caller_func)) {
35552 		DUK_DD(DUK_DDPRINT("yield state invalid: caller must be Ecmascript code"));
35553 		goto state_error;
35554 	}
35555 
35556 	DUK_ASSERT(thr->callstack_preventcount >= 1);  /* should never be zero, because we (Duktape.Thread.yield) are on the stack */
35557 	if (thr->callstack_preventcount != 1) {
35558 		/* Note: the only yield-preventing call is Duktape.Thread.yield(), hence check for 1, not 0 */
35559 		DUK_DD(DUK_DDPRINT("yield state invalid: there must be no yield-preventing calls in current thread callstack (preventcount is %ld)",
35560 		                   (long) thr->callstack_preventcount));
35561 		goto state_error;
35562 	}
35563 
35564 	/*
35565 	 *  The error object has been augmented with a traceback and other
35566 	 *  info from its creation point -- usually the current thread.
35567 	 *  The error handler, however, is called right before throwing
35568 	 *  and runs in the yielder's thread.
35569 	 */
35570 
35571 #if defined(DUK_USE_AUGMENT_ERROR_THROW)
35572 	if (is_error) {
35573 		DUK_ASSERT_TOP(ctx, 1);  /* value (error) is at stack top */
35574 		duk_err_augment_error_throw(thr);  /* in yielder's context */
35575 	}
35576 #endif
35577 
35578 #ifdef DUK_USE_DEBUG
35579 	if (is_error) {
35580 		DUK_DDD(DUK_DDDPRINT("YIELD ERROR: value=%!T",
35581 		                     (duk_tval *) duk_get_tval(ctx, 0)));
35582 	} else {
35583 		DUK_DDD(DUK_DDDPRINT("YIELD NORMAL: value=%!T",
35584 		                     (duk_tval *) duk_get_tval(ctx, 0)));
35585 	}
35586 #endif
35587 
35588 	/*
35589 	 *  Process yield
35590 	 *
35591 	 *  After longjmp(), processing continues in bytecode executor longjmp
35592 	 *  handler, which will e.g. update thr->resumer to NULL.
35593 	 */
35594 
35595 	thr->heap->lj.type = DUK_LJ_TYPE_YIELD;
35596 
35597 	/* lj value1: value */
35598 	DUK_ASSERT(thr->valstack_bottom < thr->valstack_top);
35599 	DUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value1, &thr->valstack_bottom[0]);  /* side effects */
35600 	DUK_TVAL_CHKFAST_INPLACE(&thr->heap->lj.value1);
35601 
35602 	thr->heap->lj.iserror = is_error;
35603 
35604 	DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL);  /* call is from executor, so we know we have a jmpbuf */
35605 	duk_err_longjmp(thr);  /* execution resumes in bytecode executor */
35606 	return 0;  /* never here */
35607 
35608  state_error:
35609 	DUK_ERROR_TYPE(thr, "invalid state");
35610 	return 0;  /* never here */
35611 }
35612 
35613 DUK_INTERNAL duk_ret_t duk_bi_thread_current(duk_context *ctx) {
35614 	duk_push_current_thread(ctx);
35615 	return 1;
35616 }
35617 /*
35618  *  Type error thrower, E5 Section 13.2.3.
35619  */
35620 
35621 /* include removed: duk_internal.h */
35622 
35623 DUK_INTERNAL duk_ret_t duk_bi_type_error_thrower(duk_context *ctx) {
35624 	DUK_UNREF(ctx);
35625 	return DUK_RET_TYPE_ERROR;
35626 }
35627 /*
35628  *  Fixed buffer helper useful for debugging, requires no allocation
35629  *  which is critical for debugging.
35630  */
35631 
35632 /* include removed: duk_internal.h */
35633 
35634 #ifdef DUK_USE_DEBUG
35635 
35636 DUK_INTERNAL void duk_fb_put_bytes(duk_fixedbuffer *fb, const duk_uint8_t *buffer, duk_size_t length) {
35637 	duk_size_t avail;
35638 	duk_size_t copylen;
35639 
35640 	avail = (fb->offset >= fb->length ? (duk_size_t) 0 : (duk_size_t) (fb->length - fb->offset));
35641 	if (length > avail) {
35642 		copylen = avail;
35643 		fb->truncated = 1;
35644 	} else {
35645 		copylen = length;
35646 	}
35647 	DUK_MEMCPY(fb->buffer + fb->offset, buffer, copylen);
35648 	fb->offset += copylen;
35649 }
35650 
35651 DUK_INTERNAL void duk_fb_put_byte(duk_fixedbuffer *fb, duk_uint8_t x) {
35652 	duk_fb_put_bytes(fb, (const duk_uint8_t *) &x, 1);
35653 }
35654 
35655 DUK_INTERNAL void duk_fb_put_cstring(duk_fixedbuffer *fb, const char *x) {
35656 	duk_fb_put_bytes(fb, (const duk_uint8_t *) x, (duk_size_t) DUK_STRLEN(x));
35657 }
35658 
35659 DUK_INTERNAL void duk_fb_sprintf(duk_fixedbuffer *fb, const char *fmt, ...) {
35660 	duk_size_t avail;
35661 	va_list ap;
35662 
35663 	va_start(ap, fmt);
35664 	avail = (fb->offset >= fb->length ? (duk_size_t) 0 : (duk_size_t) (fb->length - fb->offset));
35665 	if (avail > 0) {
35666 		duk_int_t res = (duk_int_t) DUK_VSNPRINTF((char *) (fb->buffer + fb->offset), avail, fmt, ap);
35667 		if (res < 0) {
35668 			/* error */
35669 		} else if ((duk_size_t) res >= avail) {
35670 			/* (maybe) truncated */
35671 			fb->offset += avail;
35672 			if ((duk_size_t) res > avail) {
35673 				/* actual chars dropped (not just NUL term) */
35674 				fb->truncated = 1;
35675 			}
35676 		} else {
35677 			/* normal */
35678 			fb->offset += res;
35679 		}
35680 	}
35681 	va_end(ap);
35682 }
35683 
35684 DUK_INTERNAL void duk_fb_put_funcptr(duk_fixedbuffer *fb, duk_uint8_t *fptr, duk_size_t fptr_size) {
35685 	char buf[64+1];
35686 	duk_debug_format_funcptr(buf, sizeof(buf), fptr, fptr_size);
35687 	buf[sizeof(buf) - 1] = (char) 0;
35688 	duk_fb_put_cstring(fb, buf);
35689 }
35690 
35691 DUK_INTERNAL duk_bool_t duk_fb_is_full(duk_fixedbuffer *fb) {
35692 	return (fb->offset >= fb->length);
35693 }
35694 
35695 #endif  /* DUK_USE_DEBUG */
35696 /*
35697  *  Debug dumping of duk_heap.
35698  */
35699 
35700 /* include removed: duk_internal.h */
35701 
35702 #ifdef DUK_USE_DEBUG
35703 
35704 #if 0  /*unused*/
35705 DUK_LOCAL void duk__sanitize_snippet(char *buf, duk_size_t buf_size, duk_hstring *str) {
35706 	duk_size_t i;
35707 	duk_size_t nchars;
35708 	duk_size_t maxchars;
35709 	duk_uint8_t *data;
35710 
35711 	DUK_MEMZERO(buf, buf_size);
35712 
35713 	maxchars = (duk_size_t) (buf_size - 1);
35714 	data = DUK_HSTRING_GET_DATA(str);
35715 	nchars = ((duk_size_t) str->blen < maxchars ? (duk_size_t) str->blen : maxchars);
35716 	for (i = 0; i < nchars; i++) {
35717 		duk_small_int_t c = (duk_small_int_t) data[i];
35718 		if (c < 0x20 || c > 0x7e) {
35719 			c = '.';
35720 		}
35721 		buf[i] = (char) c;
35722 	}
35723 }
35724 #endif
35725 
35726 #if 0
35727 DUK_LOCAL const char *duk__get_heap_type_string(duk_heaphdr *hdr) {
35728 	switch (DUK_HEAPHDR_GET_TYPE(hdr)) {
35729 	case DUK_HTYPE_STRING:
35730 		return "string";
35731 	case DUK_HTYPE_OBJECT:
35732 		return "object";
35733 	case DUK_HTYPE_BUFFER:
35734 		return "buffer";
35735 	default:
35736 		return "???";
35737 	}
35738 }
35739 #endif
35740 
35741 #if 0
35742 DUK_LOCAL void duk__dump_indented(duk_heaphdr *obj, int index) {
35743 	DUK_UNREF(obj);
35744 	DUK_UNREF(index);
35745 	DUK_UNREF(duk__get_heap_type_string);
35746 
35747 #ifdef DUK_USE_REFERENCE_COUNTING
35748 	DUK_D(DUK_DPRINT("  [%ld]: %p %s (flags: 0x%08lx, ref: %ld) -> %!O",
35749 	                 (long) index,
35750 	                 (void *) obj,
35751 	                 (const char *) duk__get_heap_type_string(obj),
35752 	                 (unsigned long) DUK_HEAPHDR_GET_FLAGS(obj),
35753 	                 (long) DUK_HEAPHDR_GET_REFCOUNT(obj),
35754 	                 (duk_heaphdr *) obj));
35755 #else
35756 	DUK_D(DUK_DPRINT("  [%ld]: %p %s (flags: 0x%08lx) -> %!O",
35757 	                 (long) index,
35758 	                 (void *) obj,
35759 	                 (const char *) duk__get_heap_type_string(obj),
35760 	                 (unsigned long) DUK_HEAPHDR_GET_FLAGS(obj),
35761 	                 (duk_heaphdr *) obj));
35762 #endif
35763 }
35764 #endif
35765 
35766 #if 0  /*unused*/
35767 DUK_LOCAL void duk__dump_heaphdr_list(duk_heap *heap, duk_heaphdr *root, const char *name) {
35768 	duk_int_t count;
35769 	duk_heaphdr *curr;
35770 
35771 	DUK_UNREF(heap);
35772 	DUK_UNREF(name);
35773 
35774 	count = 0;
35775 	curr = root;
35776 	while (curr) {
35777 		count++;
35778 		curr = DUK_HEAPHDR_GET_NEXT(curr);
35779 	}
35780 
35781 	DUK_D(DUK_DPRINT("%s, %ld objects", (const char *) name, (long) count));
35782 
35783 	count = 0;
35784 	curr = root;
35785 	while (curr) {
35786 		count++;
35787 		duk__dump_indented(curr, count);
35788 		curr = DUK_HEAPHDR_GET_NEXT(curr);
35789 	}
35790 }
35791 #endif
35792 
35793 #if 0  /*unused*/
35794 DUK_LOCAL void duk__dump_stringtable(duk_heap *heap) {
35795 	duk_uint_fast32_t i;
35796 	char buf[64+1];
35797 
35798 	DUK_D(DUK_DPRINT("stringtable %p, used %ld, size %ld, load %ld%%",
35799 	                 (void *) heap->strtable,
35800 	                 (long) heap->st_used,
35801 	                 (long) heap->st_size,
35802 	                 (long) (((double) heap->st_used) / ((double) heap->st_size) * 100.0)));
35803 
35804 	for (i = 0; i < (duk_uint_fast32_t) heap->st_size; i++) {
35805 		duk_hstring *e = heap->strtable[i];
35806 
35807 		if (!e) {
35808 			DUK_D(DUK_DPRINT("  [%ld]: NULL", (long) i));
35809 		} else if (e == DUK_STRTAB_DELETED_MARKER(heap)) {
35810 			DUK_D(DUK_DPRINT("  [%ld]: DELETED", (long) i));
35811 		} else {
35812 			duk__sanitize_snippet(buf, sizeof(buf), e);
35813 
35814 #ifdef DUK_USE_REFERENCE_COUNTING
35815 			DUK_D(DUK_DPRINT("  [%ld]: %p (flags: 0x%08lx, ref: %ld) '%s', strhash=0x%08lx, blen=%ld, clen=%ld, "
35816 			                 "arridx=%ld, internal=%ld, reserved_word=%ld, strict_reserved_word=%ld, eval_or_arguments=%ld",
35817 			                 (long) i,
35818 			                 (void *) e,
35819 			                 (unsigned long) DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) e),
35820 			                 (long) DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) e),
35821 			                 (const char *) buf,
35822 			                 (unsigned long) e->hash,
35823 			                 (long) e->blen,
35824 			                 (long) e->clen,
35825 			                 (long) (DUK_HSTRING_HAS_ARRIDX(e) ? 1 : 0),
35826 			                 (long) (DUK_HSTRING_HAS_INTERNAL(e) ? 1 : 0),
35827 			                 (long) (DUK_HSTRING_HAS_RESERVED_WORD(e) ? 1 : 0),
35828 			                 (long) (DUK_HSTRING_HAS_STRICT_RESERVED_WORD(e) ? 1 : 0),
35829 			                 (long) (DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(e) ? 1 : 0)));
35830 #else
35831 			DUK_D(DUK_DPRINT("  [%ld]: %p (flags: 0x%08lx) '%s', strhash=0x%08lx, blen=%ld, clen=%ld, "
35832 			                 "arridx=%ld, internal=%ld, reserved_word=%ld, strict_reserved_word=%ld, eval_or_arguments=%ld",
35833 			                 (long) i,
35834 			                 (void *) e,
35835 			                 (unsigned long) DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) e),
35836 			                 (const char *) buf,
35837 			                 (long) e->hash,
35838 			                 (long) e->blen,
35839 			                 (long) e->clen,
35840 			                 (long) (DUK_HSTRING_HAS_ARRIDX(e) ? 1 : 0),
35841 			                 (long) (DUK_HSTRING_HAS_INTERNAL(e) ? 1 : 0),
35842 			                 (long) (DUK_HSTRING_HAS_RESERVED_WORD(e) ? 1 : 0),
35843 			                 (long) (DUK_HSTRING_HAS_STRICT_RESERVED_WORD(e) ? 1 : 0),
35844 			                 (long) (DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(e) ? 1 : 0)));
35845 #endif
35846 		}
35847 	}
35848 }
35849 #endif
35850 
35851 #if 0  /*unused*/
35852 DUK_LOCAL void duk__dump_strcache(duk_heap *heap) {
35853 	duk_uint_fast32_t i;
35854 	char buf[64+1];
35855 
35856 	DUK_D(DUK_DPRINT("stringcache"));
35857 
35858 	for (i = 0; i < (duk_uint_fast32_t) DUK_HEAP_STRCACHE_SIZE; i++) {
35859 		duk_strcache *c = &heap->strcache[i];
35860 		if (!c->h) {
35861 			DUK_D(DUK_DPRINT("  [%ld]: bidx=%ld, cidx=%ld, str=NULL",
35862 			                 (long) i, (long) c->bidx, (long) c->cidx));
35863 		} else {
35864 			duk__sanitize_snippet(buf, sizeof(buf), c->h);
35865 			DUK_D(DUK_DPRINT("  [%ld]: bidx=%ld cidx=%ld str=%s",
35866 			                 (long) i, (long) c->bidx, (long) c->cidx, (const char *) buf));
35867 		}
35868 	}
35869 }
35870 #endif
35871 
35872 #if 0  /*unused*/
35873 DUK_INTERNAL void duk_debug_dump_heap(duk_heap *heap) {
35874 	char buf[64+1];
35875 
35876 	DUK_D(DUK_DPRINT("=== heap %p ===", (void *) heap));
35877 	DUK_D(DUK_DPRINT("  flags: 0x%08lx", (unsigned long) heap->flags));
35878 
35879 	/* Note: there is no standard formatter for function pointers */
35880 #ifdef DUK_USE_GCC_PRAGMAS
35881 #pragma GCC diagnostic push
35882 #pragma GCC diagnostic ignored "-pedantic"
35883 #endif
35884 	duk_debug_format_funcptr(buf, sizeof(buf), (duk_uint8_t *) &heap->alloc_func, sizeof(heap->alloc_func));
35885 	DUK_D(DUK_DPRINT("  alloc_func: %s", (const char *) buf));
35886 	duk_debug_format_funcptr(buf, sizeof(buf), (duk_uint8_t *) &heap->realloc_func, sizeof(heap->realloc_func));
35887 	DUK_D(DUK_DPRINT("  realloc_func: %s", (const char *) buf));
35888 	duk_debug_format_funcptr(buf, sizeof(buf), (duk_uint8_t *) &heap->free_func, sizeof(heap->free_func));
35889 	DUK_D(DUK_DPRINT("  free_func: %s", (const char *) buf));
35890 	duk_debug_format_funcptr(buf, sizeof(buf), (duk_uint8_t *) &heap->fatal_func, sizeof(heap->fatal_func));
35891 	DUK_D(DUK_DPRINT("  fatal_func: %s", (const char *) buf));
35892 #ifdef DUK_USE_GCC_PRAGMAS
35893 #pragma GCC diagnostic pop
35894 #endif
35895 
35896 	DUK_D(DUK_DPRINT("  heap_udata: %p", (void *) heap->heap_udata));
35897 
35898 #ifdef DUK_USE_MARK_AND_SWEEP
35899 #ifdef DUK_USE_VOLUNTARY_GC
35900 	DUK_D(DUK_DPRINT("  mark-and-sweep trig counter: %ld", (long) heap->mark_and_sweep_trigger_counter));
35901 #endif
35902 	DUK_D(DUK_DPRINT("  mark-and-sweep rec depth: %ld", (long) heap->mark_and_sweep_recursion_depth));
35903 	DUK_D(DUK_DPRINT("  mark-and-sweep base flags: 0x%08lx", (unsigned long) heap->mark_and_sweep_base_flags));
35904 #endif
35905 
35906 	DUK_D(DUK_DPRINT("  lj.jmpbuf_ptr: %p", (void *) heap->lj.jmpbuf_ptr));
35907 	DUK_D(DUK_DPRINT("  lj.type: %ld", (long) heap->lj.type));
35908 	DUK_D(DUK_DPRINT("  lj.value1: %!T", (duk_tval *) &heap->lj.value1));
35909 	DUK_D(DUK_DPRINT("  lj.value2: %!T", (duk_tval *) &heap->lj.value2));
35910 	DUK_D(DUK_DPRINT("  lj.iserror: %ld", (long) heap->lj.iserror));
35911 
35912 	DUK_D(DUK_DPRINT("  handling_error: %ld", (long) heap->handling_error));
35913 
35914 	DUK_D(DUK_DPRINT("  heap_thread: %!@O", (duk_heaphdr *) heap->heap_thread));
35915 	DUK_D(DUK_DPRINT("  curr_thread: %!@O", (duk_heaphdr *) heap->curr_thread));
35916 	DUK_D(DUK_DPRINT("  heap_object: %!@O", (duk_heaphdr *) heap->heap_object));
35917 
35918 	DUK_D(DUK_DPRINT("  call_recursion_depth: %ld", (long) heap->call_recursion_depth));
35919 	DUK_D(DUK_DPRINT("  call_recursion_limit: %ld", (long) heap->call_recursion_limit));
35920 
35921 	DUK_D(DUK_DPRINT("  hash_seed: 0x%08lx", (unsigned long) heap->hash_seed));
35922 	DUK_D(DUK_DPRINT("  rnd_state: 0x%08lx", (unsigned long) heap->rnd_state));
35923 
35924 	duk__dump_strcache(heap);
35925 
35926 	duk__dump_heaphdr_list(heap, heap->heap_allocated, "heap allocated");
35927 
35928 #ifdef DUK_USE_REFERENCE_COUNTING
35929 	duk__dump_heaphdr_list(heap, heap->refzero_list, "refcounting refzero list");
35930 #endif
35931 
35932 #ifdef DUK_USE_MARK_AND_SWEEP
35933 	duk__dump_heaphdr_list(heap, heap->finalize_list, "mark-and-sweep finalize list");
35934 #endif
35935 
35936 	duk__dump_stringtable(heap);
35937 
35938 	/* heap->strs: not worth dumping */
35939 }
35940 #endif
35941 
35942 #endif  /* DUK_USE_DEBUG */
35943 /*
35944  *  Custom formatter for debug printing, allowing Duktape specific data
35945  *  structures (such as tagged values and heap objects) to be printed with
35946  *  a nice format string.  Because debug printing should not affect execution
35947  *  state, formatting here must be independent of execution (see implications
35948  *  below) and must not allocate memory.
35949  *
35950  *  Custom format tags begin with a '%!' to safely distinguish them from
35951  *  standard format tags.  The following conversions are supported:
35952  *
35953  *     %!T    tagged value (duk_tval *)
35954  *     %!O    heap object (duk_heaphdr *)
35955  *     %!I    decoded bytecode instruction
35956  *     %!C    bytecode instruction opcode name (arg is long)
35957  *
35958  *  Everything is serialized in a JSON-like manner.  The default depth is one
35959  *  level, internal prototype is not followed, and internal properties are not
35960  *  serialized.  The following modifiers change this behavior:
35961  *
35962  *     @      print pointers
35963  *     #      print binary representations (where applicable)
35964  *     d      deep traversal of own properties (not prototype)
35965  *     p      follow prototype chain (useless without 'd')
35966  *     i      include internal properties (other than prototype)
35967  *     x      hexdump buffers
35968  *     h      heavy formatting
35969  *
35970  *  For instance, the following serializes objects recursively, but does not
35971  *  follow the prototype chain nor print internal properties: "%!dO".
35972  *
35973  *  Notes:
35974  *
35975  *    * Standard snprintf return value semantics seem to vary.  This
35976  *      implementation returns the number of bytes it actually wrote
35977  *      (excluding the null terminator).  If retval == buffer size,
35978  *      output was truncated (except for corner cases).
35979  *
35980  *    * Output format is intentionally different from Ecmascript
35981  *      formatting requirements, as formatting here serves debugging
35982  *      of internals.
35983  *
35984  *    * Depth checking (and updating) is done in each type printer
35985  *      separately, to allow them to call each other freely.
35986  *
35987  *    * Some pathological structures might take ages to print (e.g.
35988  *      self recursion with 100 properties pointing to the object
35989  *      itself).  To guard against these, each printer also checks
35990  *      whether the output buffer is full; if so, early exit.
35991  *
35992  *    * Reference loops are detected using a loop stack.
35993  */
35994 
35995 /* include removed: duk_internal.h */
35996 
35997 #ifdef DUK_USE_DEBUG
35998 
35999 #include <stdio.h>
36000 #include <stdarg.h>
36001 #include <string.h>
36002 
36003 /* list of conversion specifiers that terminate a format tag;
36004  * this is unfortunately guesswork.
36005  */
36006 #define DUK__ALLOWED_STANDARD_SPECIFIERS  "diouxXeEfFgGaAcsCSpnm"
36007 
36008 /* maximum length of standard format tag that we support */
36009 #define DUK__MAX_FORMAT_TAG_LENGTH  32
36010 
36011 /* heapobj recursion depth when deep printing is selected */
36012 #define DUK__DEEP_DEPTH_LIMIT  8
36013 
36014 /* maximum recursion depth for loop detection stacks */
36015 #define DUK__LOOP_STACK_DEPTH  256
36016 
36017 /* must match bytecode defines now; build autogenerate? */
36018 DUK_LOCAL const char *duk__bc_optab[64] = {
36019 	"LDREG",    "STREG",    "LDCONST",  "LDINT",    "LDINTX",   "MPUTOBJ",  "MPUTOBJI", "MPUTARR",  "MPUTARRI", "NEW",
36020 	"NEWI",     "REGEXP",   "CSREG",    "CSREGI",   "GETVAR",   "PUTVAR",   "DECLVAR",  "DELVAR",   "CSVAR",    "CSVARI",
36021 	"CLOSURE",  "GETPROP",  "PUTPROP",  "DELPROP",  "CSPROP",   "CSPROPI",  "ADD",      "SUB",      "MUL",      "DIV",
36022 	"MOD",      "BAND",     "BOR",      "BXOR",     "BASL",     "BLSR",     "BASR",     "EQ",       "NEQ",      "SEQ",
36023 	"SNEQ",     "GT",       "GE",       "LT",       "LE",       "IF",       "JUMP",     "RETURN",   "CALL",     "CALLI",
36024 	"TRYCATCH", "EXTRA",    "PREINCR",  "PREDECR",  "POSTINCR", "POSTDECR", "PREINCV",  "PREDECV",  "POSTINCV", "POSTDECV",
36025 	"PREINCP",  "PREDECP",  "POSTINCP", "POSTDECP"
36026 };
36027 
36028 DUK_LOCAL const char *duk__bc_extraoptab[256] = {
36029 	"NOP", "INVALID", "LDTHIS", "LDUNDEF", "LDNULL", "LDTRUE", "LDFALSE", "NEWOBJ", "NEWARR", "SETALEN",
36030 	"TYPEOF", "TYPEOFID", "INITENUM", "NEXTENUM", "INITSET", "INITSETI", "INITGET", "INITGETI", "ENDTRY", "ENDCATCH",
36031 	"ENDFIN", "THROW", "INVLHS", "UNM", "UNP", "DEBUGGER", "BREAK", "CONTINUE", "BNOT", "LNOT",
36032 	"INSTOF", "IN", "LABEL", "ENDLABEL", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
36033 	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
36034 
36035 	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
36036 	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
36037 	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
36038 	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
36039 	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
36040 
36041 	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
36042 	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
36043 	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
36044 	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
36045 	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
36046 
36047 	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
36048 	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
36049 	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
36050 	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
36051 	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
36052 
36053 	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
36054 	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
36055 	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
36056 	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
36057 	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX",
36058 
36059 	"XXX", "XXX", "XXX", "XXX", "XXX", "XXX"
36060 };
36061 
36062 typedef struct duk__dprint_state duk__dprint_state;
36063 struct duk__dprint_state {
36064 	duk_fixedbuffer *fb;
36065 
36066 	/* loop_stack_index could be perhaps be replaced by 'depth', but it's nice
36067 	 * to not couple these two mechanisms unnecessarily.
36068 	 */
36069 	duk_hobject *loop_stack[DUK__LOOP_STACK_DEPTH];
36070 	duk_int_t loop_stack_index;
36071 	duk_int_t loop_stack_limit;
36072 
36073 	duk_int_t depth;
36074 	duk_int_t depth_limit;
36075 
36076 	duk_bool_t pointer;
36077 	duk_bool_t heavy;
36078 	duk_bool_t binary;
36079 	duk_bool_t follow_proto;
36080 	duk_bool_t internal;
36081 	duk_bool_t hexdump;
36082 };
36083 
36084 /* helpers */
36085 DUK_LOCAL_DECL void duk__print_hstring(duk__dprint_state *st, duk_hstring *k, duk_bool_t quotes);
36086 DUK_LOCAL_DECL void duk__print_hobject(duk__dprint_state *st, duk_hobject *h);
36087 DUK_LOCAL_DECL void duk__print_hbuffer(duk__dprint_state *st, duk_hbuffer *h);
36088 DUK_LOCAL_DECL void duk__print_tval(duk__dprint_state *st, duk_tval *tv);
36089 DUK_LOCAL_DECL void duk__print_instr(duk__dprint_state *st, duk_instr_t ins);
36090 DUK_LOCAL_DECL void duk__print_heaphdr(duk__dprint_state *st, duk_heaphdr *h);
36091 DUK_LOCAL_DECL void duk__print_shared_heaphdr(duk__dprint_state *st, duk_heaphdr *h);
36092 DUK_LOCAL_DECL void duk__print_shared_heaphdr_string(duk__dprint_state *st, duk_heaphdr_string *h);
36093 
36094 DUK_LOCAL void duk__print_shared_heaphdr(duk__dprint_state *st, duk_heaphdr *h) {
36095 	duk_fixedbuffer *fb = st->fb;
36096 
36097 	if (st->heavy) {
36098 		duk_fb_sprintf(fb, "(%p)", (void *) h);
36099 	}
36100 
36101 	if (!h) {
36102 		return;
36103 	}
36104 
36105 	if (st->binary) {
36106 		duk_size_t i;
36107 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LBRACKET);
36108 		for (i = 0; i < (duk_size_t) sizeof(*h); i++) {
36109 			duk_fb_sprintf(fb, "%02lx", (unsigned long) ((duk_uint8_t *)h)[i]);
36110 		}
36111 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RBRACKET);
36112 	}
36113 
36114 #ifdef DUK_USE_REFERENCE_COUNTING  /* currently implicitly also DUK_USE_DOUBLE_LINKED_HEAP */
36115 	if (st->heavy) {
36116 		duk_fb_sprintf(fb, "[h_next=%p,h_prev=%p,h_refcount=%lu,h_flags=%08lx,type=%ld,"
36117 		               "reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
36118 		               (void *) DUK_HEAPHDR_GET_NEXT(NULL, h),
36119 		               (void *) DUK_HEAPHDR_GET_PREV(NULL, h),
36120 		               (unsigned long) DUK_HEAPHDR_GET_REFCOUNT(h),
36121 		               (unsigned long) DUK_HEAPHDR_GET_FLAGS(h),
36122 		               (long) DUK_HEAPHDR_GET_TYPE(h),
36123 		               (long) (DUK_HEAPHDR_HAS_REACHABLE(h) ? 1 : 0),
36124 		               (long) (DUK_HEAPHDR_HAS_TEMPROOT(h) ? 1 : 0),
36125 		               (long) (DUK_HEAPHDR_HAS_FINALIZABLE(h) ? 1 : 0),
36126 		               (long) (DUK_HEAPHDR_HAS_FINALIZED(h) ? 1 : 0));
36127 	}
36128 #else
36129 	if (st->heavy) {
36130 		duk_fb_sprintf(fb, "[h_next=%p,h_flags=%08lx,type=%ld,reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
36131 		               (void *) DUK_HEAPHDR_GET_NEXT(NULL, h),
36132 		               (unsigned long) DUK_HEAPHDR_GET_FLAGS(h),
36133 		               (long) DUK_HEAPHDR_GET_TYPE(h),
36134 		               (long) (DUK_HEAPHDR_HAS_REACHABLE(h) ? 1 : 0),
36135 		               (long) (DUK_HEAPHDR_HAS_TEMPROOT(h) ? 1 : 0),
36136 		               (long) (DUK_HEAPHDR_HAS_FINALIZABLE(h) ? 1 : 0),
36137 		               (long) (DUK_HEAPHDR_HAS_FINALIZED(h) ? 1 : 0));
36138 	}
36139 #endif
36140 }
36141 
36142 DUK_LOCAL void duk__print_shared_heaphdr_string(duk__dprint_state *st, duk_heaphdr_string *h) {
36143 	duk_fixedbuffer *fb = st->fb;
36144 
36145 	if (st->heavy) {
36146 		duk_fb_sprintf(fb, "(%p)", (void *) h);
36147 	}
36148 
36149 	if (!h) {
36150 		return;
36151 	}
36152 
36153 	if (st->binary) {
36154 		duk_size_t i;
36155 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LBRACKET);
36156 		for (i = 0; i < (duk_size_t) sizeof(*h); i++) {
36157 			duk_fb_sprintf(fb, "%02lx", (unsigned long) ((duk_uint8_t *)h)[i]);
36158 		}
36159 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RBRACKET);
36160 	}
36161 
36162 #ifdef DUK_USE_REFERENCE_COUNTING
36163 	if (st->heavy) {
36164 		duk_fb_sprintf(fb, "[h_refcount=%lu,h_flags=%08lx,type=%ld,reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
36165 		               (unsigned long) DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h),
36166 		               (unsigned long) DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) h),
36167 		               (long) DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) h),
36168 		               (long) (DUK_HEAPHDR_HAS_REACHABLE((duk_heaphdr *) h) ? 1 : 0),
36169 		               (long) (DUK_HEAPHDR_HAS_TEMPROOT((duk_heaphdr *) h) ? 1 : 0),
36170 		               (long) (DUK_HEAPHDR_HAS_FINALIZABLE((duk_heaphdr *) h) ? 1 : 0),
36171 		               (long) (DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) h) ? 1 : 0));
36172 	}
36173 #else
36174 	if (st->heavy) {
36175 		duk_fb_sprintf(fb, "[h_flags=%08lx,type=%ld,reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
36176 		               (unsigned long) DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) h),
36177 		               (long) DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) h),
36178 		               (long) (DUK_HEAPHDR_HAS_REACHABLE((duk_heaphdr *) h) ? 1 : 0),
36179 		               (long) (DUK_HEAPHDR_HAS_TEMPROOT((duk_heaphdr *) h) ? 1 : 0),
36180 		               (long) (DUK_HEAPHDR_HAS_FINALIZABLE((duk_heaphdr *) h) ? 1 : 0),
36181 		               (long) (DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) h) ? 1 : 0));
36182 	}
36183 #endif
36184 }
36185 
36186 DUK_LOCAL void duk__print_hstring(duk__dprint_state *st, duk_hstring *h, duk_bool_t quotes) {
36187 	duk_fixedbuffer *fb = st->fb;
36188 	const duk_uint8_t *p;
36189 	const duk_uint8_t *p_end;
36190 
36191 	/* terminal type: no depth check */
36192 
36193 	if (duk_fb_is_full(fb)) {
36194 		return;
36195 	}
36196 
36197 	duk__print_shared_heaphdr_string(st, &h->hdr);
36198 
36199 	if (!h) {
36200 		duk_fb_put_cstring(fb, "NULL");
36201 		return;
36202 	}
36203 
36204 	p = DUK_HSTRING_GET_DATA(h);
36205 	p_end = p + DUK_HSTRING_GET_BYTELEN(h);
36206 
36207 	if (p_end > p && p[0] == DUK_ASC_UNDERSCORE) {
36208 		/* if property key begins with underscore, encode it with
36209 		 * forced quotes (e.g. "_Foo") to distinguish it from encoded
36210 		 * internal properties (e.g. \xffBar -> _Bar).
36211 		 */
36212 		quotes = 1;
36213 	}
36214 
36215 	if (quotes) {
36216 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_DOUBLEQUOTE);
36217 	}
36218 	while (p < p_end) {
36219 		duk_uint8_t ch = *p++;
36220 
36221 		/* two special escapes: '\' and '"', other printables as is */
36222 		if (ch == '\\') {
36223 			duk_fb_sprintf(fb, "\\\\");
36224 		} else if (ch == '"') {
36225 			duk_fb_sprintf(fb, "\\\"");
36226 		} else if (ch >= 0x20 && ch <= 0x7e) {
36227 			duk_fb_put_byte(fb, ch);
36228 		} else if (ch == 0xff && !quotes) {
36229 			/* encode \xffBar as _Bar if no quotes are applied, this is for
36230 			 * readable internal keys.
36231 			 */
36232 			duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_UNDERSCORE);
36233 		} else {
36234 			duk_fb_sprintf(fb, "\\x%02lx", (unsigned long) ch);
36235 		}
36236 	}
36237 	if (quotes) {
36238 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_DOUBLEQUOTE);
36239 	}
36240 #ifdef DUK_USE_REFERENCE_COUNTING
36241 	/* XXX: limit to quoted strings only, to save keys from being cluttered? */
36242 	duk_fb_sprintf(fb, "/%lu", (unsigned long) DUK_HEAPHDR_GET_REFCOUNT(&h->hdr));
36243 #endif
36244 }
36245 
36246 #ifdef DUK__COMMA
36247 #undef DUK__COMMA
36248 #endif
36249 #define DUK__COMMA()  do { \
36250 		if (first) { \
36251 			first = 0; \
36252 		} else { \
36253 			duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_COMMA); \
36254 		} \
36255 	} while (0)
36256 
36257 DUK_LOCAL void duk__print_hobject(duk__dprint_state *st, duk_hobject *h) {
36258 	duk_fixedbuffer *fb = st->fb;
36259 	duk_uint_fast32_t i;
36260 	duk_tval *tv;
36261 	duk_hstring *key;
36262 	duk_bool_t first = 1;
36263 	const char *brace1 = "{";
36264 	const char *brace2 = "}";
36265 	duk_bool_t pushed_loopstack = 0;
36266 
36267 	if (duk_fb_is_full(fb)) {
36268 		return;
36269 	}
36270 
36271 	duk__print_shared_heaphdr(st, &h->hdr);
36272 
36273 	if (h && DUK_HOBJECT_HAS_ARRAY_PART(h)) {
36274 		brace1 = "[";
36275 		brace2 = "]";
36276 	}
36277 
36278 	if (!h) {
36279 		duk_fb_put_cstring(fb, "NULL");
36280 		goto finished;
36281 	}
36282 
36283 	if (st->depth >= st->depth_limit) {
36284 		if (DUK_HOBJECT_IS_COMPILEDFUNCTION(h)) {
36285 			duk_fb_sprintf(fb, "%sobject/compiledfunction %p%s", (const char *) brace1, (void *) h, (const char *) brace2);
36286 		} else if (DUK_HOBJECT_IS_NATIVEFUNCTION(h)) {
36287 			duk_fb_sprintf(fb, "%sobject/nativefunction %p%s", (const char *) brace1, (void *) h, (const char *) brace2);
36288 		} else if (DUK_HOBJECT_IS_THREAD(h)) {
36289 			duk_fb_sprintf(fb, "%sobject/thread %p%s", (const char *) brace1, (void *) h, (const char *) brace2);
36290 		} else {
36291 			duk_fb_sprintf(fb, "%sobject %p%s", (const char *) brace1, (void *) h, (const char *) brace2);  /* may be NULL */
36292 		}
36293 		return;
36294 	}
36295 
36296 	for (i = 0; i < (duk_uint_fast32_t) st->loop_stack_index; i++) {
36297 		if (st->loop_stack[i] == h) {
36298 			duk_fb_sprintf(fb, "%sLOOP:%p%s", (const char *) brace1, (void *) h, (const char *) brace2);
36299 			return;
36300 		}
36301 	}
36302 
36303 	/* after this, return paths should 'goto finished' for decrement */
36304 	st->depth++;
36305 
36306 	if (st->loop_stack_index >= st->loop_stack_limit) {
36307 		duk_fb_sprintf(fb, "%sOUT-OF-LOOP-STACK%s", (const char *) brace1, (const char *) brace2);
36308 		goto finished;
36309 	}
36310 	st->loop_stack[st->loop_stack_index++] = h;
36311 	pushed_loopstack = 1;
36312 
36313 	/*
36314 	 *  Notation: double underscore used for internal properties which are not
36315 	 *  stored in the property allocation (e.g. '__valstack').
36316 	 */
36317 
36318 	duk_fb_put_cstring(fb, brace1);
36319 
36320 	if (DUK_HOBJECT_GET_PROPS(NULL, h)) {
36321 		duk_uint32_t a_limit;
36322 
36323 		a_limit = DUK_HOBJECT_GET_ASIZE(h);
36324 		if (st->internal) {
36325 			/* dump all allocated entries, unused entries print as 'unused',
36326 			 * note that these may extend beyond current 'length' and look
36327 			 * a bit funny.
36328 			 */
36329 		} else {
36330 			/* leave out trailing 'unused' elements */
36331 			while (a_limit > 0) {
36332 				tv = DUK_HOBJECT_A_GET_VALUE_PTR(NULL, h, a_limit - 1);
36333 				if (!DUK_TVAL_IS_UNUSED(tv)) {
36334 					break;
36335 				}
36336 				a_limit--;
36337 			}
36338 		}
36339 
36340 		for (i = 0; i < a_limit; i++) {
36341 			tv = DUK_HOBJECT_A_GET_VALUE_PTR(NULL, h, i);
36342 			DUK__COMMA();
36343 			duk__print_tval(st, tv);
36344 		}
36345 		for (i = 0; i < DUK_HOBJECT_GET_ENEXT(h); i++) {
36346 			key = DUK_HOBJECT_E_GET_KEY(NULL, h, i);
36347 			if (!key) {
36348 				continue;
36349 			}
36350 			if (!st->internal &&
36351 			    DUK_HSTRING_GET_BYTELEN(key) > 0 &&
36352 			    DUK_HSTRING_GET_DATA(key)[0] == 0xff) {
36353 				/* XXX: use DUK_HSTRING_FLAG_INTERNAL? */
36354 				continue;
36355 			}
36356 			DUK__COMMA();
36357 			duk__print_hstring(st, key, 0);
36358 			duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_COLON);
36359 			if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(NULL, h, i)) {
36360 				duk_fb_sprintf(fb, "[get:%p,set:%p]",
36361 				               (void *) DUK_HOBJECT_E_GET_VALUE(NULL, h, i).a.get,
36362 				               (void *) DUK_HOBJECT_E_GET_VALUE(NULL, h, i).a.set);
36363 			} else {
36364 				tv = &DUK_HOBJECT_E_GET_VALUE(NULL, h, i).v;
36365 				duk__print_tval(st, tv);
36366 			}
36367 			if (st->heavy) {
36368 				duk_fb_sprintf(fb, "<%02lx>", (unsigned long) DUK_HOBJECT_E_GET_FLAGS(NULL, h, i));
36369 			}
36370 		}
36371 	}
36372 	if (st->internal) {
36373 		if (DUK_HOBJECT_HAS_EXTENSIBLE(h)) {
36374 			DUK__COMMA(); duk_fb_sprintf(fb, "__extensible:true");
36375 		} else {
36376 			;
36377 		}
36378 		if (DUK_HOBJECT_HAS_CONSTRUCTABLE(h)) {
36379 			DUK__COMMA(); duk_fb_sprintf(fb, "__constructable:true");
36380 		} else {
36381 			;
36382 		}
36383 		if (DUK_HOBJECT_HAS_BOUND(h)) {
36384 			DUK__COMMA(); duk_fb_sprintf(fb, "__bound:true");
36385 		} else {
36386 			;
36387 		}
36388 		if (DUK_HOBJECT_HAS_COMPILEDFUNCTION(h)) {
36389 			DUK__COMMA(); duk_fb_sprintf(fb, "__compiledfunction:true");
36390 		} else {
36391 			;
36392 		}
36393 		if (DUK_HOBJECT_HAS_NATIVEFUNCTION(h)) {
36394 			DUK__COMMA(); duk_fb_sprintf(fb, "__nativefunction:true");
36395 		} else {
36396 			;
36397 		}
36398 		if (DUK_HOBJECT_HAS_THREAD(h)) {
36399 			DUK__COMMA(); duk_fb_sprintf(fb, "__thread:true");
36400 		} else {
36401 			;
36402 		}
36403 		if (DUK_HOBJECT_HAS_ARRAY_PART(h)) {
36404 			DUK__COMMA(); duk_fb_sprintf(fb, "__array_part:true");
36405 		} else {
36406 			;
36407 		}
36408 		if (DUK_HOBJECT_HAS_STRICT(h)) {
36409 			DUK__COMMA(); duk_fb_sprintf(fb, "__strict:true");
36410 		} else {
36411 			;
36412 		}
36413 		if (DUK_HOBJECT_HAS_NEWENV(h)) {
36414 			DUK__COMMA(); duk_fb_sprintf(fb, "__newenv:true");
36415 		} else {
36416 			;
36417 		}
36418 		if (DUK_HOBJECT_HAS_NAMEBINDING(h)) {
36419 			DUK__COMMA(); duk_fb_sprintf(fb, "__namebinding:true");
36420 		} else {
36421 			;
36422 		}
36423 		if (DUK_HOBJECT_HAS_CREATEARGS(h)) {
36424 			DUK__COMMA(); duk_fb_sprintf(fb, "__createargs:true");
36425 		} else {
36426 			;
36427 		}
36428 		if (DUK_HOBJECT_HAS_ENVRECCLOSED(h)) {
36429 			DUK__COMMA(); duk_fb_sprintf(fb, "__envrecclosed:true");
36430 		} else {
36431 			;
36432 		}
36433 		if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(h)) {
36434 			DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_array:true");
36435 		} else {
36436 			;
36437 		}
36438 		if (DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(h)) {
36439 			DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_stringobj:true");
36440 		} else {
36441 			;
36442 		}
36443 		if (DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(h)) {
36444 			DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_arguments:true");
36445 		} else {
36446 			;
36447 		}
36448 		if (DUK_HOBJECT_HAS_EXOTIC_DUKFUNC(h)) {
36449 			DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_dukfunc:true");
36450 		} else {
36451 			;
36452 		}
36453 		if (DUK_HOBJECT_IS_BUFFEROBJECT(h)) {
36454 			DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_bufferobj:true");
36455 		} else {
36456 			;
36457 		}
36458 		if (DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h)) {
36459 			DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_proxyobj:true");
36460 		} else {
36461 			;
36462 		}
36463 	}
36464 	if (st->internal && DUK_HOBJECT_IS_COMPILEDFUNCTION(h)) {
36465 		duk_hcompiledfunction *f = (duk_hcompiledfunction *) h;
36466 		DUK__COMMA(); duk_fb_put_cstring(fb, "__data:");
36467 		duk__print_hbuffer(st, (duk_hbuffer *) DUK_HCOMPILEDFUNCTION_GET_DATA(NULL, f));
36468 		DUK__COMMA(); duk_fb_sprintf(fb, "__nregs:%ld", (long) f->nregs);
36469 		DUK__COMMA(); duk_fb_sprintf(fb, "__nargs:%ld", (long) f->nargs);
36470 #if defined(DUK_USE_DEBUGGER_SUPPORT)
36471 		DUK__COMMA(); duk_fb_sprintf(fb, "__start_line:%ld", (long) f->start_line);
36472 		DUK__COMMA(); duk_fb_sprintf(fb, "__end_line:%ld", (long) f->end_line);
36473 #endif
36474 		DUK__COMMA(); duk_fb_put_cstring(fb, "__data:");
36475 		duk__print_hbuffer(st, (duk_hbuffer *) DUK_HCOMPILEDFUNCTION_GET_DATA(NULL, f));
36476 	} else if (st->internal && DUK_HOBJECT_IS_NATIVEFUNCTION(h)) {
36477 		duk_hnativefunction *f = (duk_hnativefunction *) h;
36478 		DUK__COMMA(); duk_fb_sprintf(fb, "__func:");
36479 		duk_fb_put_funcptr(fb, (duk_uint8_t *) &f->func, sizeof(f->func));
36480 		DUK__COMMA(); duk_fb_sprintf(fb, "__nargs:%ld", (long) f->nargs);
36481 		DUK__COMMA(); duk_fb_sprintf(fb, "__magic:%ld", (long) f->magic);
36482 	} else if (st->internal && DUK_HOBJECT_IS_BUFFEROBJECT(h)) {
36483 		duk_hbufferobject *b = (duk_hbufferobject *) h;
36484 		DUK__COMMA(); duk_fb_sprintf(fb, "__buf:");
36485 		duk__print_hbuffer(st, (duk_hbuffer *) b->buf);
36486 		DUK__COMMA(); duk_fb_sprintf(fb, "__offset:%ld", (long) b->offset);
36487 		DUK__COMMA(); duk_fb_sprintf(fb, "__length:%ld", (long) b->length);
36488 		DUK__COMMA(); duk_fb_sprintf(fb, "__shift:%ld", (long) b->shift);
36489 		DUK__COMMA(); duk_fb_sprintf(fb, "__elemtype:%ld", (long) b->elem_type);
36490 	} else if (st->internal && DUK_HOBJECT_IS_THREAD(h)) {
36491 		duk_hthread *t = (duk_hthread *) h;
36492 		DUK__COMMA(); duk_fb_sprintf(fb, "__strict:%ld", (long) t->strict);
36493 		DUK__COMMA(); duk_fb_sprintf(fb, "__state:%ld", (long) t->state);
36494 		DUK__COMMA(); duk_fb_sprintf(fb, "__unused1:%ld", (long) t->unused1);
36495 		DUK__COMMA(); duk_fb_sprintf(fb, "__unused2:%ld", (long) t->unused2);
36496 		DUK__COMMA(); duk_fb_sprintf(fb, "__valstack_max:%ld", (long) t->valstack_max);
36497 		DUK__COMMA(); duk_fb_sprintf(fb, "__callstack_max:%ld", (long) t->callstack_max);
36498 		DUK__COMMA(); duk_fb_sprintf(fb, "__catchstack_max:%ld", (long) t->catchstack_max);
36499 		DUK__COMMA(); duk_fb_sprintf(fb, "__valstack:%p", (void *) t->valstack);
36500 		DUK__COMMA(); duk_fb_sprintf(fb, "__valstack_end:%p/%ld", (void *) t->valstack_end, (long) (t->valstack_end - t->valstack));
36501 		DUK__COMMA(); duk_fb_sprintf(fb, "__valstack_bottom:%p/%ld", (void *) t->valstack_bottom, (long) (t->valstack_bottom - t->valstack));
36502 		DUK__COMMA(); duk_fb_sprintf(fb, "__valstack_top:%p/%ld", (void *) t->valstack_top, (long) (t->valstack_top - t->valstack));
36503 		DUK__COMMA(); duk_fb_sprintf(fb, "__catchstack:%p", (void *) t->catchstack);
36504 		DUK__COMMA(); duk_fb_sprintf(fb, "__catchstack_size:%ld", (long) t->catchstack_size);
36505 		DUK__COMMA(); duk_fb_sprintf(fb, "__catchstack_top:%ld", (long) t->catchstack_top);
36506 		DUK__COMMA(); duk_fb_sprintf(fb, "__resumer:"); duk__print_hobject(st, (duk_hobject *) t->resumer);
36507 		/* XXX: print built-ins array? */
36508 
36509 	}
36510 #ifdef DUK_USE_REFERENCE_COUNTING
36511 	if (st->internal) {
36512 		DUK__COMMA(); duk_fb_sprintf(fb, "__refcount:%lu", (unsigned long) DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h));
36513 	}
36514 #endif
36515 	if (st->internal) {
36516 		DUK__COMMA(); duk_fb_sprintf(fb, "__class:%ld", (long) DUK_HOBJECT_GET_CLASS_NUMBER(h));
36517 	}
36518 
36519 	DUK__COMMA(); duk_fb_sprintf(fb, "__heapptr:%p", (void *) h);  /* own pointer */
36520 
36521 	/* prototype should be last, for readability */
36522 	if (DUK_HOBJECT_GET_PROTOTYPE(NULL, h)) {
36523 		if (st->follow_proto) {
36524 			DUK__COMMA(); duk_fb_put_cstring(fb, "__prototype:"); duk__print_hobject(st, DUK_HOBJECT_GET_PROTOTYPE(NULL, h));
36525 		} else {
36526 			DUK__COMMA(); duk_fb_sprintf(fb, "__prototype:%p", (void *) DUK_HOBJECT_GET_PROTOTYPE(NULL, h));
36527 		}
36528 	}
36529 
36530 	duk_fb_put_cstring(fb, brace2);
36531 
36532 #if defined(DUK_USE_HOBJECT_HASH_PART)
36533 	if (st->heavy && DUK_HOBJECT_GET_HSIZE(h) > 0) {
36534 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LANGLE);
36535 		for (i = 0; i < DUK_HOBJECT_GET_HSIZE(h); i++) {
36536 			duk_uint_t h_idx = DUK_HOBJECT_H_GET_INDEX(NULL, h, i);
36537 			if (i > 0) {
36538 				duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_COMMA);
36539 			}
36540 			if (h_idx == DUK_HOBJECT_HASHIDX_UNUSED) {
36541 				duk_fb_sprintf(fb, "u");
36542 			} else if (h_idx == DUK_HOBJECT_HASHIDX_DELETED) {
36543 				duk_fb_sprintf(fb, "d");
36544 			} else {
36545 				duk_fb_sprintf(fb, "%ld", (long) h_idx);
36546 			}
36547 		}
36548 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RANGLE);
36549 	}
36550 #endif
36551 
36552  finished:
36553 	st->depth--;
36554 	if (pushed_loopstack) {
36555 		st->loop_stack_index--;
36556 		st->loop_stack[st->loop_stack_index] = NULL;
36557 	}
36558 }
36559 
36560 #undef DUK__COMMA
36561 
36562 DUK_LOCAL void duk__print_hbuffer(duk__dprint_state *st, duk_hbuffer *h) {
36563 	duk_fixedbuffer *fb = st->fb;
36564 	duk_size_t i, n;
36565 	duk_uint8_t *p;
36566 
36567 	if (duk_fb_is_full(fb)) {
36568 		return;
36569 	}
36570 
36571 	/* terminal type: no depth check */
36572 
36573 	if (!h) {
36574 		duk_fb_put_cstring(fb, "NULL");
36575 		return;
36576 	}
36577 
36578 	if (DUK_HBUFFER_HAS_DYNAMIC(h)) {
36579 		if (DUK_HBUFFER_HAS_EXTERNAL(h)) {
36580 			duk_hbuffer_external *g = (duk_hbuffer_external *) h;
36581 			duk_fb_sprintf(fb, "buffer:external:%p:%ld",
36582 			               (void *) DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(NULL, g),
36583 			               (long) DUK_HBUFFER_EXTERNAL_GET_SIZE(g));
36584 		} else {
36585 			duk_hbuffer_dynamic *g = (duk_hbuffer_dynamic *) h;
36586 			duk_fb_sprintf(fb, "buffer:dynamic:%p:%ld",
36587 			               (void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(NULL, g),
36588 			               (long) DUK_HBUFFER_DYNAMIC_GET_SIZE(g));
36589 		}
36590 	} else {
36591 		duk_fb_sprintf(fb, "buffer:fixed:%ld", (long) DUK_HBUFFER_GET_SIZE(h));
36592 	}
36593 
36594 #ifdef DUK_USE_REFERENCE_COUNTING
36595 	duk_fb_sprintf(fb, "/%lu", (unsigned long) DUK_HEAPHDR_GET_REFCOUNT(&h->hdr));
36596 #endif
36597 
36598 	if (st->hexdump) {
36599 		duk_fb_sprintf(fb, "=[");
36600 		n = DUK_HBUFFER_GET_SIZE(h);
36601 		p = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(NULL, h);
36602 		for (i = 0; i < n; i++) {
36603 			duk_fb_sprintf(fb, "%02lx", (unsigned long) p[i]);
36604 		}
36605 		duk_fb_sprintf(fb, "]");
36606 	}
36607 }
36608 
36609 DUK_LOCAL void duk__print_heaphdr(duk__dprint_state *st, duk_heaphdr *h) {
36610 	duk_fixedbuffer *fb = st->fb;
36611 
36612 	if (duk_fb_is_full(fb)) {
36613 		return;
36614 	}
36615 
36616 	if (!h) {
36617 		duk_fb_put_cstring(fb, "NULL");
36618 		return;
36619 	}
36620 
36621 	switch (DUK_HEAPHDR_GET_TYPE(h)) {
36622 	case DUK_HTYPE_STRING:
36623 		duk__print_hstring(st, (duk_hstring *) h, 1);
36624 		break;
36625 	case DUK_HTYPE_OBJECT:
36626 		duk__print_hobject(st, (duk_hobject *) h);
36627 		break;
36628 	case DUK_HTYPE_BUFFER:
36629 		duk__print_hbuffer(st, (duk_hbuffer *) h);
36630 		break;
36631 	default:
36632 		duk_fb_sprintf(fb, "[unknown htype %ld]", (long) DUK_HEAPHDR_GET_TYPE(h));
36633 		break;
36634 	}
36635 }
36636 
36637 DUK_LOCAL void duk__print_tval(duk__dprint_state *st, duk_tval *tv) {
36638 	duk_fixedbuffer *fb = st->fb;
36639 
36640 	if (duk_fb_is_full(fb)) {
36641 		return;
36642 	}
36643 
36644 	/* depth check is done when printing an actual type */
36645 
36646 	if (st->heavy) {
36647 		duk_fb_sprintf(fb, "(%p)", (void *) tv);
36648 	}
36649 
36650 	if (!tv) {
36651 		duk_fb_put_cstring(fb, "NULL");
36652 		return;
36653 	}
36654 
36655 	if (st->binary) {
36656 		duk_size_t i;
36657 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LBRACKET);
36658 		for (i = 0; i < (duk_size_t) sizeof(*tv); i++) {
36659 			duk_fb_sprintf(fb, "%02lx", (unsigned long) ((duk_uint8_t *)tv)[i]);
36660 		}
36661 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RBRACKET);
36662 	}
36663 
36664 	if (st->heavy) {
36665 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LANGLE);
36666 	}
36667 	switch (DUK_TVAL_GET_TAG(tv)) {
36668 	case DUK_TAG_UNDEFINED: {
36669 		duk_fb_put_cstring(fb, "undefined");
36670 		break;
36671 	}
36672 	case DUK_TAG_UNUSED: {
36673 		duk_fb_put_cstring(fb, "unused");
36674 		break;
36675 	}
36676 	case DUK_TAG_NULL: {
36677 		duk_fb_put_cstring(fb, "null");
36678 		break;
36679 	}
36680 	case DUK_TAG_BOOLEAN: {
36681 		duk_fb_put_cstring(fb, DUK_TVAL_GET_BOOLEAN(tv) ? "true" : "false");
36682 		break;
36683 	}
36684 	case DUK_TAG_STRING: {
36685 		/* Note: string is a terminal heap object, so no depth check here */
36686 		duk__print_hstring(st, DUK_TVAL_GET_STRING(tv), 1);
36687 		break;
36688 	}
36689 	case DUK_TAG_OBJECT: {
36690 		duk__print_hobject(st, DUK_TVAL_GET_OBJECT(tv));
36691 		break;
36692 	}
36693 	case DUK_TAG_BUFFER: {
36694 		duk__print_hbuffer(st, DUK_TVAL_GET_BUFFER(tv));
36695 		break;
36696 	}
36697 	case DUK_TAG_POINTER: {
36698 		duk_fb_sprintf(fb, "pointer:%p", (void *) DUK_TVAL_GET_POINTER(tv));
36699 		break;
36700 	}
36701 	case DUK_TAG_LIGHTFUNC: {
36702 		duk_c_function func;
36703 		duk_small_uint_t lf_flags;
36704 
36705 		DUK_TVAL_GET_LIGHTFUNC(tv, func, lf_flags);
36706 		duk_fb_sprintf(fb, "lightfunc:");
36707 		duk_fb_put_funcptr(fb, (duk_uint8_t *) &func, sizeof(func));
36708 		duk_fb_sprintf(fb, ":%04lx", (long) lf_flags);
36709 		break;
36710 	}
36711 #if defined(DUK_USE_FASTINT)
36712 	case DUK_TAG_FASTINT:
36713 #endif
36714 	default: {
36715 		/* IEEE double is approximately 16 decimal digits; print a couple extra */
36716 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
36717 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
36718 		duk_fb_sprintf(fb, "%.18g", (double) DUK_TVAL_GET_NUMBER(tv));
36719 		break;
36720 	}
36721 	}
36722 	if (st->heavy) {
36723 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RANGLE);
36724 	}
36725 }
36726 
36727 DUK_LOCAL void duk__print_instr(duk__dprint_state *st, duk_instr_t ins) {
36728 	duk_fixedbuffer *fb = st->fb;
36729 	duk_small_int_t op;
36730 	const char *op_name;
36731 	const char *extraop_name;
36732 
36733 	op = (duk_small_int_t) DUK_DEC_OP(ins);
36734 	op_name = duk__bc_optab[op];
36735 
36736 	/* XXX: option to fix opcode length so it lines up nicely */
36737 
36738 	if (op == DUK_OP_EXTRA) {
36739 		extraop_name = duk__bc_extraoptab[DUK_DEC_A(ins)];
36740 
36741 		duk_fb_sprintf(fb, "%s %ld, %ld",
36742 		               (const char *) extraop_name, (long) DUK_DEC_B(ins), (long) DUK_DEC_C(ins));
36743 	} else if (op == DUK_OP_JUMP) {
36744 		duk_int_t diff1 = DUK_DEC_ABC(ins) - DUK_BC_JUMP_BIAS;  /* from next pc */
36745 		duk_int_t diff2 = diff1 + 1;                            /* from curr pc */
36746 
36747 		duk_fb_sprintf(fb, "%s %ld (to pc%c%ld)",
36748 		               (const char *) op_name, (long) diff1,
36749 		               (int) (diff2 >= 0 ? '+' : '-'),  /* char format: use int */
36750 		               (long) (diff2 >= 0 ? diff2 : -diff2));
36751 	} else {
36752 		duk_fb_sprintf(fb, "%s %ld, %ld, %ld",
36753 		               (const char *) op_name, (long) DUK_DEC_A(ins),
36754 		               (long) DUK_DEC_B(ins), (long) DUK_DEC_C(ins));
36755 	}
36756 }
36757 
36758 DUK_LOCAL void duk__print_opcode(duk__dprint_state *st, duk_small_int_t opcode) {
36759 	duk_fixedbuffer *fb = st->fb;
36760 
36761 	if (opcode < DUK_BC_OP_MIN || opcode > DUK_BC_OP_MAX) {
36762 		duk_fb_sprintf(fb, "?(%ld)", (long) opcode);
36763 	} else {
36764 		duk_fb_sprintf(fb, "%s", (const char *) duk__bc_optab[opcode]);
36765 	}
36766 }
36767 
36768 DUK_INTERNAL duk_int_t duk_debug_vsnprintf(char *str, duk_size_t size, const char *format, va_list ap) {
36769 	duk_fixedbuffer fb;
36770 	const char *p = format;
36771 	const char *p_end = p + DUK_STRLEN(format);
36772 	duk_int_t retval;
36773 
36774 	DUK_MEMZERO(&fb, sizeof(fb));
36775 	fb.buffer = (duk_uint8_t *) str;
36776 	fb.length = size;
36777 	fb.offset = 0;
36778 	fb.truncated = 0;
36779 
36780 	while (p < p_end) {
36781 		char ch = *p++;
36782 		const char *p_begfmt = NULL;
36783 		duk_bool_t got_exclamation = 0;
36784 		duk_bool_t got_long = 0;  /* %lf, %ld etc */
36785 		duk__dprint_state st;
36786 
36787 		if (ch != DUK_ASC_PERCENT) {
36788 			duk_fb_put_byte(&fb, (duk_uint8_t) ch);
36789 			continue;
36790 		}
36791 
36792 		/*
36793 		 *  Format tag parsing.  Since we don't understand all the
36794 		 *  possible format tags allowed, we just scan for a terminating
36795 		 *  specifier and keep track of relevant modifiers that we do
36796 		 *  understand.  See man 3 printf.
36797 		 */
36798 
36799 		DUK_MEMZERO(&st, sizeof(st));
36800 		st.fb = &fb;
36801 		st.depth = 0;
36802 		st.depth_limit = 1;
36803 		st.loop_stack_index = 0;
36804 		st.loop_stack_limit = DUK__LOOP_STACK_DEPTH;
36805 
36806 		p_begfmt = p - 1;
36807 		while (p < p_end) {
36808 			ch = *p++;
36809 
36810 			if (ch == DUK_ASC_STAR) {
36811 				/* unsupported: would consume multiple args */
36812 				goto error;
36813 			} else if (ch == DUK_ASC_PERCENT) {
36814 				duk_fb_put_byte(&fb, (duk_uint8_t) DUK_ASC_PERCENT);
36815 				break;
36816 			} else if (ch == DUK_ASC_EXCLAMATION) {
36817 				got_exclamation = 1;
36818 			} else if (!got_exclamation && ch == DUK_ASC_LC_L) {
36819 				got_long = 1;
36820 			} else if (got_exclamation && ch == DUK_ASC_LC_D) {
36821 				st.depth_limit = DUK__DEEP_DEPTH_LIMIT;
36822 			} else if (got_exclamation && ch == DUK_ASC_LC_P) {
36823 				st.follow_proto = 1;
36824 			} else if (got_exclamation && ch == DUK_ASC_LC_I) {
36825 				st.internal = 1;
36826 			} else if (got_exclamation && ch == DUK_ASC_LC_X) {
36827 				st.hexdump = 1;
36828 			} else if (got_exclamation && ch == DUK_ASC_LC_H) {
36829 				st.heavy = 1;
36830 			} else if (got_exclamation && ch == DUK_ASC_ATSIGN) {
36831 				st.pointer = 1;
36832 			} else if (got_exclamation && ch == DUK_ASC_HASH) {
36833 				st.binary = 1;
36834 			} else if (got_exclamation && ch == DUK_ASC_UC_T) {
36835 				duk_tval *t = va_arg(ap, duk_tval *);
36836 				if (st.pointer && !st.heavy) {
36837 					duk_fb_sprintf(&fb, "(%p)", (void *) t);
36838 				}
36839 				duk__print_tval(&st, t);
36840 				break;
36841 			} else if (got_exclamation && ch == DUK_ASC_UC_O) {
36842 				duk_heaphdr *t = va_arg(ap, duk_heaphdr *);
36843 				if (st.pointer && !st.heavy) {
36844 					duk_fb_sprintf(&fb, "(%p)", (void *) t);
36845 				}
36846 				duk__print_heaphdr(&st, t);
36847 				break;
36848 			} else if (got_exclamation && ch == DUK_ASC_UC_I) {
36849 				duk_instr_t t = va_arg(ap, duk_instr_t);
36850 				duk__print_instr(&st, t);
36851 				break;
36852 			} else if (got_exclamation && ch == DUK_ASC_UC_C) {
36853 				long t = va_arg(ap, long);
36854 				duk__print_opcode(&st, (duk_small_int_t) t);
36855 				break;
36856 			} else if (!got_exclamation && strchr(DUK__ALLOWED_STANDARD_SPECIFIERS, (int) ch)) {
36857 				char fmtbuf[DUK__MAX_FORMAT_TAG_LENGTH];
36858 				duk_size_t fmtlen;
36859 
36860 				DUK_ASSERT(p >= p_begfmt);
36861 				fmtlen = (duk_size_t) (p - p_begfmt);
36862 				if (fmtlen >= sizeof(fmtbuf)) {
36863 					/* format is too large, abort */
36864 					goto error;
36865 				}
36866 				DUK_MEMZERO(fmtbuf, sizeof(fmtbuf));
36867 				DUK_MEMCPY(fmtbuf, p_begfmt, fmtlen);
36868 
36869 				/* assume exactly 1 arg, which is why '*' is forbidden; arg size still
36870 				 * depends on type though.
36871 				 */
36872 
36873 				if (ch == DUK_ASC_LC_F || ch == DUK_ASC_LC_G || ch == DUK_ASC_LC_E) {
36874 					/* %f and %lf both consume a 'long' */
36875 					double arg = va_arg(ap, double);
36876 					duk_fb_sprintf(&fb, fmtbuf, arg);
36877 				} else if (ch == DUK_ASC_LC_D && got_long) {
36878 					/* %ld */
36879 					long arg = va_arg(ap, long);
36880 					duk_fb_sprintf(&fb, fmtbuf, arg);
36881 				} else if (ch == DUK_ASC_LC_D) {
36882 					/* %d; only 16 bits are guaranteed */
36883 					int arg = va_arg(ap, int);
36884 					duk_fb_sprintf(&fb, fmtbuf, arg);
36885 				} else if (ch == DUK_ASC_LC_U && got_long) {
36886 					/* %lu */
36887 					unsigned long arg = va_arg(ap, unsigned long);
36888 					duk_fb_sprintf(&fb, fmtbuf, arg);
36889 				} else if (ch == DUK_ASC_LC_U) {
36890 					/* %u; only 16 bits are guaranteed */
36891 					unsigned int arg = va_arg(ap, unsigned int);
36892 					duk_fb_sprintf(&fb, fmtbuf, arg);
36893 				} else if (ch == DUK_ASC_LC_X && got_long) {
36894 					/* %lx */
36895 					unsigned long arg = va_arg(ap, unsigned long);
36896 					duk_fb_sprintf(&fb, fmtbuf, arg);
36897 				} else if (ch == DUK_ASC_LC_X) {
36898 					/* %x; only 16 bits are guaranteed */
36899 					unsigned int arg = va_arg(ap, unsigned int);
36900 					duk_fb_sprintf(&fb, fmtbuf, arg);
36901 				} else if (ch == DUK_ASC_LC_S) {
36902 					/* %s */
36903 					const char *arg = va_arg(ap, const char *);
36904 					if (arg == NULL) {
36905 						/* '%s' and NULL is not portable, so special case
36906 						 * it for debug printing.
36907 						 */
36908 						duk_fb_sprintf(&fb, "NULL");
36909 					} else {
36910 						duk_fb_sprintf(&fb, fmtbuf, arg);
36911 					}
36912 				} else if (ch == DUK_ASC_LC_P) {
36913 					/* %p */
36914 					void *arg = va_arg(ap, void *);
36915 					if (arg == NULL) {
36916 						/* '%p' and NULL is portable, but special case it
36917 						 * anyway to get a standard NULL marker in logs.
36918 						 */
36919 						duk_fb_sprintf(&fb, "NULL");
36920 					} else {
36921 						duk_fb_sprintf(&fb, fmtbuf, arg);
36922 					}
36923 				} else if (ch == DUK_ASC_LC_C) {
36924 					/* '%c', passed concretely as int */
36925 					int arg = va_arg(ap, int);
36926 					duk_fb_sprintf(&fb, fmtbuf, arg);
36927 				} else {
36928 					/* Should not happen. */
36929 					duk_fb_sprintf(&fb, "INVALID-FORMAT(%s)", (const char *) fmtbuf);
36930 				}
36931 				break;
36932 			} else {
36933 				/* ignore */
36934 			}
36935 		}
36936 	}
36937 	goto done;
36938 
36939  error:
36940 	duk_fb_put_cstring(&fb, "FMTERR");
36941 	/* fall through */
36942 
36943  done:
36944 	retval = (duk_int_t) fb.offset;
36945 	duk_fb_put_byte(&fb, (duk_uint8_t) 0);
36946 
36947 	/* return total chars written excluding terminator */
36948 	return retval;
36949 }
36950 
36951 #if 0  /*unused*/
36952 DUK_INTERNAL duk_int_t duk_debug_snprintf(char *str, duk_size_t size, const char *format, ...) {
36953 	duk_int_t retval;
36954 	va_list ap;
36955 	va_start(ap, format);
36956 	retval = duk_debug_vsnprintf(str, size, format, ap);
36957 	va_end(ap);
36958 	return retval;
36959 }
36960 #endif
36961 
36962 /* Formatting function pointers is tricky: there is no standard pointer for
36963  * function pointers and the size of a function pointer may depend on the
36964  * specific pointer type.  This helper formats a function pointer based on
36965  * its memory layout to get something useful on most platforms.
36966  */
36967 DUK_INTERNAL void duk_debug_format_funcptr(char *buf, duk_size_t buf_size, duk_uint8_t *fptr, duk_size_t fptr_size) {
36968 	duk_size_t i;
36969 	duk_uint8_t *p = (duk_uint8_t *) buf;
36970 	duk_uint8_t *p_end = (duk_uint8_t *) (buf + buf_size - 1);
36971 
36972 	DUK_MEMZERO(buf, buf_size);
36973 
36974 	for (i = 0; i < fptr_size; i++) {
36975 		duk_int_t left = (duk_int_t) (p_end - p);
36976 		duk_uint8_t ch;
36977 		if (left <= 0) {
36978 			break;
36979 		}
36980 
36981 		/* Quite approximate but should be useful for little and big endian. */
36982 #ifdef DUK_USE_INTEGER_BE
36983 		ch = fptr[i];
36984 #else
36985 		ch = fptr[fptr_size - 1 - i];
36986 #endif
36987 		p += DUK_SNPRINTF((char *) p, left, "%02lx", (unsigned long) ch);
36988 	}
36989 }
36990 
36991 #endif  /* DUK_USE_DEBUG */
36992 /*
36993  *  Duktape debugger
36994  */
36995 
36996 /* include removed: duk_internal.h */
36997 
36998 #if defined(DUK_USE_DEBUGGER_SUPPORT)
36999 
37000 /*
37001  *  Helper structs
37002  */
37003 
37004 typedef union {
37005 	void *p;
37006 	duk_uint_t b[1];
37007 	/* Use b[] to access the size of the union, which is strictly not
37008 	 * correct.  Can't use fixed size unless there's feature detection
37009 	 * for pointer byte size.
37010 	 */
37011 } duk__ptr_union;
37012 
37013 /*
37014  *  Detach handling
37015  */
37016 
37017 #define DUK__SET_CONN_BROKEN(thr,reason) do { \
37018 		/* For now shared handler is fine. */ \
37019 		duk__debug_do_detach1((thr)->heap, (reason)); \
37020 	} while (0)
37021 
37022 DUK_LOCAL void duk__debug_do_detach1(duk_heap *heap, duk_int_t reason) {
37023 	/* Can be called multiple times with no harm.  Mark the transport
37024 	 * bad (dbg_read_cb == NULL) and clear state except for the detached
37025 	 * callback and the udata field.  The detached callback is delayed
37026 	 * to the message loop so that it can be called between messages;
37027 	 * this avoids corner cases related to immediate debugger reattach
37028 	 * inside the detached callback.
37029 	 */
37030 
37031 	if (heap->dbg_detaching) {
37032 		DUK_D(DUK_DPRINT("debugger already detaching, ignore detach1"));
37033 		return;
37034 	}
37035 
37036 	DUK_D(DUK_DPRINT("debugger transport detaching, marking transport broken"));
37037 
37038 	heap->dbg_detaching = 1;  /* prevent multiple in-progress detaches */
37039 
37040 	if (heap->dbg_write_cb != NULL) {
37041 		duk_hthread *thr;
37042 
37043 		thr = heap->heap_thread;
37044 		DUK_ASSERT(thr != NULL);
37045 
37046 		duk_debug_write_notify(thr, DUK_DBG_CMD_DETACHING);
37047 		duk_debug_write_int(thr, reason);
37048 		duk_debug_write_eom(thr);
37049 	}
37050 
37051 	heap->dbg_read_cb = NULL;
37052 	heap->dbg_write_cb = NULL;
37053 	heap->dbg_peek_cb = NULL;
37054 	heap->dbg_read_flush_cb = NULL;
37055 	heap->dbg_write_flush_cb = NULL;
37056 	heap->dbg_request_cb = NULL;
37057 	/* heap->dbg_detached_cb: keep */
37058 	/* heap->dbg_udata: keep */
37059 	/* heap->dbg_processing: keep on purpose to avoid debugger re-entry in detaching state */
37060 	heap->dbg_paused = 0;
37061 	heap->dbg_state_dirty = 0;
37062 	heap->dbg_force_restart = 0;
37063 	heap->dbg_step_type = 0;
37064 	heap->dbg_step_thread = NULL;
37065 	heap->dbg_step_csindex = 0;
37066 	heap->dbg_step_startline = 0;
37067 	heap->dbg_have_next_byte = 0;
37068 
37069 	/* Ensure there are no stale active breakpoint pointers.
37070 	 * Breakpoint list is currently kept - we could empty it
37071 	 * here but we'd need to handle refcounts correctly, and
37072 	 * we'd need a 'thr' reference for that.
37073 	 *
37074 	 * XXX: clear breakpoint on either attach or detach?
37075 	 */
37076 	heap->dbg_breakpoints_active[0] = (duk_breakpoint *) NULL;
37077 }
37078 
37079 DUK_LOCAL void duk__debug_do_detach2(duk_heap *heap) {
37080 	duk_debug_detached_function detached_cb;
37081 	void *detached_udata;
37082 
37083 	/* Safe to call multiple times. */
37084 
37085 	detached_cb = heap->dbg_detached_cb;
37086 	detached_udata = heap->dbg_udata;
37087 	heap->dbg_detached_cb = NULL;
37088 	heap->dbg_udata = NULL;
37089 
37090 	if (detached_cb) {
37091 		/* Careful here: state must be wiped before the call
37092 		 * so that we can cleanly handle a re-attach from
37093 		 * inside the callback.
37094 		 */
37095 		DUK_D(DUK_DPRINT("detached during message loop, delayed call to detached_cb"));
37096 		detached_cb(detached_udata);
37097 	}
37098 
37099 	heap->dbg_detaching = 0;
37100 }
37101 
37102 DUK_INTERNAL void duk_debug_do_detach(duk_heap *heap) {
37103 	duk__debug_do_detach1(heap, 0);
37104 	duk__debug_do_detach2(heap);
37105 }
37106 
37107 /* Called on a read/write error: NULL all callbacks except the detached
37108  * callback so that we never accidentally call them after a read/write
37109  * error has been indicated.  This is especially important for the transport
37110  * I/O callbacks to fulfill guaranteed callback semantics.
37111  */
37112 DUK_LOCAL void duk__debug_null_most_callbacks(duk_hthread *thr) {
37113 	duk_heap *heap;
37114 	heap = thr->heap;
37115 	DUK_D(DUK_DPRINT("transport read/write error, NULL all callbacks expected detached"));
37116 	heap->dbg_read_cb = NULL;
37117 	heap->dbg_write_cb = NULL;  /* this is especially critical to avoid another write call in detach1() */
37118 	heap->dbg_peek_cb = NULL;
37119 	heap->dbg_read_flush_cb = NULL;
37120 	heap->dbg_write_flush_cb = NULL;
37121 	heap->dbg_request_cb = NULL;
37122 	/* keep heap->dbg_detached_cb */
37123 }
37124 
37125 /*
37126  *  Debug connection peek and flush primitives
37127  */
37128 
37129 DUK_INTERNAL duk_bool_t duk_debug_read_peek(duk_hthread *thr) {
37130 	duk_heap *heap;
37131 
37132 	DUK_ASSERT(thr != NULL);
37133 	heap = thr->heap;
37134 	DUK_ASSERT(heap != NULL);
37135 
37136 	if (heap->dbg_read_cb == NULL) {
37137 		DUK_D(DUK_DPRINT("attempt to peek in detached state, return zero (= no data)"));
37138 		return 0;
37139 	}
37140 	if (heap->dbg_peek_cb == NULL) {
37141 		DUK_DD(DUK_DDPRINT("no peek callback, return zero (= no data)"));
37142 		return 0;
37143 	}
37144 
37145 	return (duk_bool_t) (heap->dbg_peek_cb(heap->dbg_udata) > 0);
37146 }
37147 
37148 DUK_INTERNAL void duk_debug_read_flush(duk_hthread *thr) {
37149 	duk_heap *heap;
37150 
37151 	DUK_ASSERT(thr != NULL);
37152 	heap = thr->heap;
37153 	DUK_ASSERT(heap != NULL);
37154 
37155 	if (heap->dbg_read_cb == NULL) {
37156 		DUK_D(DUK_DPRINT("attempt to read flush in detached state, ignore"));
37157 		return;
37158 	}
37159 	if (heap->dbg_read_flush_cb == NULL) {
37160 		DUK_DD(DUK_DDPRINT("no read flush callback, ignore"));
37161 		return;
37162 	}
37163 
37164 	heap->dbg_read_flush_cb(heap->dbg_udata);
37165 }
37166 
37167 DUK_INTERNAL void duk_debug_write_flush(duk_hthread *thr) {
37168 	duk_heap *heap;
37169 
37170 	DUK_ASSERT(thr != NULL);
37171 	heap = thr->heap;
37172 	DUK_ASSERT(heap != NULL);
37173 
37174 	if (heap->dbg_read_cb == NULL) {
37175 		DUK_D(DUK_DPRINT("attempt to write flush in detached state, ignore"));
37176 		return;
37177 	}
37178 	if (heap->dbg_write_flush_cb == NULL) {
37179 		DUK_DD(DUK_DDPRINT("no write flush callback, ignore"));
37180 		return;
37181 	}
37182 
37183 	heap->dbg_write_flush_cb(heap->dbg_udata);
37184 }
37185 
37186 /*
37187  *  Debug connection skip primitives
37188  */
37189 
37190 /* Skip fully. */
37191 DUK_INTERNAL void duk_debug_skip_bytes(duk_hthread *thr, duk_size_t length) {
37192 	duk_uint8_t dummy[64];
37193 	duk_size_t now;
37194 
37195 	DUK_ASSERT(thr != NULL);
37196 
37197 	while (length > 0) {
37198 		now = (length > sizeof(dummy) ? sizeof(dummy) : length);
37199 		duk_debug_read_bytes(thr, dummy, now);
37200 		length -= now;
37201 	}
37202 }
37203 
37204 DUK_INTERNAL void duk_debug_skip_byte(duk_hthread *thr) {
37205 	DUK_ASSERT(thr != NULL);
37206 
37207 	(void) duk_debug_read_byte(thr);
37208 }
37209 
37210 /*
37211  *  Debug connection read primitives
37212  */
37213 
37214 /* Peek ahead in the stream one byte. */
37215 DUK_INTERNAL uint8_t duk_debug_peek_byte(duk_hthread *thr) {
37216 	/* It is important not to call this if the last byte read was an EOM.
37217 	 * Reading ahead in this scenario would cause unnecessary blocking if
37218 	 * another message is not available.
37219 	 */
37220 
37221 	duk_uint8_t x;
37222 
37223 	x = duk_debug_read_byte(thr);
37224 	thr->heap->dbg_have_next_byte = 1;
37225 	thr->heap->dbg_next_byte = x;
37226 	return x;
37227 }
37228 
37229 /* Read fully. */
37230 DUK_INTERNAL void duk_debug_read_bytes(duk_hthread *thr, duk_uint8_t *data, duk_size_t length) {
37231 	duk_heap *heap;
37232 	duk_uint8_t *p;
37233 	duk_size_t left;
37234 	duk_size_t got;
37235 
37236 	DUK_ASSERT(thr != NULL);
37237 	heap = thr->heap;
37238 	DUK_ASSERT(heap != NULL);
37239 
37240 	if (heap->dbg_read_cb == NULL) {
37241 		DUK_D(DUK_DPRINT("attempt to read %ld bytes in detached state, return zero data", (long) length));
37242 		goto fail;
37243 	}
37244 
37245 	/* NOTE: length may be zero */
37246 	p = data;
37247 	if (length >= 1 && heap->dbg_have_next_byte) {
37248 		heap->dbg_have_next_byte = 0;
37249 		*p++ = heap->dbg_next_byte;
37250 	}
37251 	for (;;) {
37252 		left = (duk_size_t) ((data + length) - p);
37253 		if (left == 0) {
37254 			break;
37255 		}
37256 		DUK_ASSERT(heap->dbg_read_cb != NULL);
37257 		DUK_ASSERT(left >= 1);
37258 #if defined(DUK_USE_DEBUGGER_TRANSPORT_TORTURE)
37259 		left = 1;
37260 #endif
37261 		got = heap->dbg_read_cb(heap->dbg_udata, (char *) p, left);
37262 		if (got == 0 || got > left) {
37263 			DUK_D(DUK_DPRINT("connection error during read, return zero data"));
37264 			duk__debug_null_most_callbacks(thr);  /* avoid calling write callback in detach1() */
37265 			DUK__SET_CONN_BROKEN(thr, 1);
37266 			goto fail;
37267 		}
37268 		p += got;
37269 	}
37270 	return;
37271 
37272  fail:
37273 	DUK_MEMZERO((void *) data, (size_t) length);
37274 }
37275 
37276 DUK_INTERNAL duk_uint8_t duk_debug_read_byte(duk_hthread *thr) {
37277 	duk_uint8_t x;
37278 
37279 	x = 0;  /* just in case callback is broken and won't write 'x' */
37280 	duk_debug_read_bytes(thr, &x, 1);
37281 	return x;
37282 }
37283 
37284 DUK_LOCAL duk_uint32_t duk__debug_read_uint32_raw(duk_hthread *thr) {
37285 	duk_uint8_t buf[4];
37286 
37287 	DUK_ASSERT(thr != NULL);
37288 
37289 	duk_debug_read_bytes(thr, buf, 4);
37290 	return ((duk_uint32_t) buf[0] << 24) |
37291 	       ((duk_uint32_t) buf[1] << 16) |
37292 	       ((duk_uint32_t) buf[2] << 8) |
37293 	       (duk_uint32_t) buf[3];
37294 }
37295 
37296 DUK_LOCAL duk_uint32_t duk__debug_read_int32_raw(duk_hthread *thr) {
37297 	return (duk_int32_t) duk__debug_read_uint32_raw(thr);
37298 }
37299 
37300 DUK_LOCAL duk_uint16_t duk__debug_read_uint16_raw(duk_hthread *thr) {
37301 	duk_uint8_t buf[2];
37302 
37303 	DUK_ASSERT(thr != NULL);
37304 
37305 	duk_debug_read_bytes(thr, buf, 2);
37306 	return ((duk_uint16_t) buf[0] << 8) |
37307 	       (duk_uint16_t) buf[1];
37308 }
37309 
37310 DUK_INTERNAL duk_int32_t duk_debug_read_int(duk_hthread *thr) {
37311 	duk_small_uint_t x;
37312 	duk_small_uint_t t;
37313 
37314 	DUK_ASSERT(thr != NULL);
37315 
37316 	x = duk_debug_read_byte(thr);
37317 	if (x >= 0xc0) {
37318 		t = duk_debug_read_byte(thr);
37319 		return (duk_int32_t) (((x - 0xc0) << 8) + t);
37320 	} else if (x >= 0x80) {
37321 		return (duk_int32_t) (x - 0x80);
37322 	} else if (x == DUK_DBG_IB_INT4) {
37323 		return (duk_int32_t) duk__debug_read_uint32_raw(thr);
37324 	}
37325 
37326 	DUK_D(DUK_DPRINT("debug connection error: failed to decode int"));
37327 	DUK__SET_CONN_BROKEN(thr, 1);
37328 	return 0;
37329 }
37330 
37331 DUK_LOCAL duk_hstring *duk__debug_read_hstring_raw(duk_hthread *thr, duk_uint32_t len) {
37332 	duk_context *ctx = (duk_context *) thr;
37333 	duk_uint8_t buf[31];
37334 	duk_uint8_t *p;
37335 
37336 	if (len <= sizeof(buf)) {
37337 		duk_debug_read_bytes(thr, buf, (duk_size_t) len);
37338 		duk_push_lstring(ctx, (const char *) buf, (duk_size_t) len);
37339 	} else {
37340 		p = (duk_uint8_t *) duk_push_fixed_buffer(ctx, (duk_size_t) len);
37341 		DUK_ASSERT(p != NULL);
37342 		duk_debug_read_bytes(thr, p, (duk_size_t) len);
37343 		duk_to_string(ctx, -1);
37344 	}
37345 
37346 	return duk_require_hstring(ctx, -1);
37347 }
37348 
37349 DUK_INTERNAL duk_hstring *duk_debug_read_hstring(duk_hthread *thr) {
37350 	duk_context *ctx = (duk_context *) thr;
37351 	duk_small_uint_t x;
37352 	duk_uint32_t len;
37353 
37354 	DUK_ASSERT(thr != NULL);
37355 
37356 	x = duk_debug_read_byte(thr);
37357 	if (x >= 0x60 && x <= 0x7f) {
37358 		/* For short strings, use a fixed temp buffer. */
37359 		len = (duk_uint32_t) (x - 0x60);
37360 	} else if (x == DUK_DBG_IB_STR2) {
37361 		len = (duk_uint32_t) duk__debug_read_uint16_raw(thr);
37362 	} else if (x == DUK_DBG_IB_STR4) {
37363 		len = (duk_uint32_t) duk__debug_read_uint32_raw(thr);
37364 	} else {
37365 		goto fail;
37366 	}
37367 
37368 	return duk__debug_read_hstring_raw(thr, len);
37369 
37370  fail:
37371 	DUK_D(DUK_DPRINT("debug connection error: failed to decode int"));
37372 	DUK__SET_CONN_BROKEN(thr, 1);
37373 	duk_push_hstring_stridx(thr, DUK_STRIDX_EMPTY_STRING);  /* always push some string */
37374 	return duk_require_hstring(ctx, -1);
37375 }
37376 
37377 DUK_LOCAL duk_hbuffer *duk__debug_read_hbuffer_raw(duk_hthread *thr, duk_uint32_t len) {
37378 	duk_context *ctx = (duk_context *) thr;
37379 	duk_uint8_t *p;
37380 
37381 	p = (duk_uint8_t *) duk_push_fixed_buffer(ctx, (duk_size_t) len);
37382 	DUK_ASSERT(p != NULL);
37383 	duk_debug_read_bytes(thr, p, (duk_size_t) len);
37384 
37385 	return duk_require_hbuffer(ctx, -1);
37386 }
37387 
37388 DUK_LOCAL void *duk__debug_read_pointer_raw(duk_hthread *thr) {
37389 	duk_small_uint_t x;
37390 	duk__ptr_union pu;
37391 
37392 	DUK_ASSERT(thr != NULL);
37393 
37394 	x = duk_debug_read_byte(thr);
37395 	if (x != sizeof(pu)) {
37396 		goto fail;
37397 	}
37398 	duk_debug_read_bytes(thr, (duk_uint8_t *) &pu.p, sizeof(pu));
37399 #if defined(DUK_USE_INTEGER_LE)
37400 	duk_byteswap_bytes((duk_uint8_t *) pu.b, sizeof(pu));
37401 #endif
37402 	return (void *) pu.p;
37403 
37404  fail:
37405 	DUK_D(DUK_DPRINT("debug connection error: failed to decode pointer"));
37406 	DUK__SET_CONN_BROKEN(thr, 1);
37407 	return (void *) NULL;
37408 }
37409 
37410 DUK_LOCAL duk_double_t duk__debug_read_double_raw(duk_hthread *thr) {
37411 	duk_double_union du;
37412 
37413 	DUK_ASSERT(sizeof(du.uc) == 8);
37414 	duk_debug_read_bytes(thr, (duk_uint8_t *) du.uc, sizeof(du.uc));
37415 	DUK_DBLUNION_DOUBLE_NTOH(&du);
37416 	return du.d;
37417 }
37418 
37419 #if 0
37420 DUK_INTERNAL duk_heaphdr *duk_debug_read_heapptr(duk_hthread *thr) {
37421 	duk_small_uint_t x;
37422 
37423 	DUK_ASSERT(thr != NULL);
37424 
37425 	x = duk_debug_read_byte(thr);
37426 	if (x != DUK_DBG_IB_HEAPPTR) {
37427 		goto fail;
37428 	}
37429 
37430 	return (duk_heaphdr *) duk__debug_read_pointer_raw(thr);
37431 
37432  fail:
37433 	DUK_D(DUK_DPRINT("debug connection error: failed to decode heapptr"));
37434 	DUK__SET_CONN_BROKEN(thr, 1);
37435 	return NULL;
37436 }
37437 #endif
37438 
37439 DUK_INTERNAL duk_heaphdr *duk_debug_read_any_ptr(duk_hthread *thr) {
37440 	duk_small_uint_t x;
37441 
37442 	DUK_ASSERT(thr != NULL);
37443 
37444 	x = duk_debug_read_byte(thr);
37445 	switch (x) {
37446 	case DUK_DBG_IB_OBJECT:
37447 	case DUK_DBG_IB_POINTER:
37448 	case DUK_DBG_IB_HEAPPTR:
37449 		/* Accept any pointer-like value; for 'object' dvalue, read
37450 		 * and ignore the class number.
37451 		 */
37452 		if (x == DUK_DBG_IB_OBJECT) {
37453 			duk_debug_skip_byte(thr);
37454 		}
37455 		break;
37456 	default:
37457 		goto fail;
37458 	}
37459 
37460 	return (duk_heaphdr *) duk__debug_read_pointer_raw(thr);
37461 
37462  fail:
37463 	DUK_D(DUK_DPRINT("debug connection error: failed to decode any pointer (object, pointer, heapptr)"));
37464 	DUK__SET_CONN_BROKEN(thr, 1);
37465 	return NULL;
37466 }
37467 
37468 DUK_INTERNAL duk_tval *duk_debug_read_tval(duk_hthread *thr) {
37469 	duk_context *ctx = (duk_context *) thr;
37470 	duk_uint8_t x;
37471 	duk_uint_t t;
37472 	duk_uint32_t len;
37473 
37474 	DUK_ASSERT(thr != NULL);
37475 
37476 	x = duk_debug_read_byte(thr);
37477 
37478 	if (x >= 0xc0) {
37479 		t = (duk_uint_t) (x - 0xc0);
37480 		t = (t << 8) + duk_debug_read_byte(thr);
37481 		duk_push_uint(ctx, (duk_uint_t) t);
37482 		goto return_ptr;
37483 	}
37484 	if (x >= 0x80) {
37485 		duk_push_uint(ctx, (duk_uint_t) (x - 0x80));
37486 		goto return_ptr;
37487 	}
37488 	if (x >= 0x60) {
37489 		len = (duk_uint32_t) (x - 0x60);
37490 		duk__debug_read_hstring_raw(thr, len);
37491 		goto return_ptr;
37492 	}
37493 
37494 	switch (x) {
37495 	case DUK_DBG_IB_INT4: {
37496 		duk_int32_t i = duk__debug_read_int32_raw(thr);
37497 		duk_push_i32(ctx, i);
37498 		break;
37499 	}
37500 	case DUK_DBG_IB_STR4: {
37501 		len = duk__debug_read_uint32_raw(thr);
37502 		duk__debug_read_hstring_raw(thr, len);
37503 		break;
37504 	}
37505 	case DUK_DBG_IB_STR2: {
37506 		len = duk__debug_read_uint16_raw(thr);
37507 		duk__debug_read_hstring_raw(thr, len);
37508 		break;
37509 	}
37510 	case DUK_DBG_IB_BUF4: {
37511 		len = duk__debug_read_uint32_raw(thr);
37512 		duk__debug_read_hbuffer_raw(thr, len);
37513 		break;
37514 	}
37515 	case DUK_DBG_IB_BUF2: {
37516 		len = duk__debug_read_uint16_raw(thr);
37517 		duk__debug_read_hbuffer_raw(thr, len);
37518 		break;
37519 	}
37520 	case DUK_DBG_IB_UNDEFINED: {
37521 		duk_push_undefined(ctx);
37522 		break;
37523 	}
37524 	case DUK_DBG_IB_NULL: {
37525 		duk_push_null(ctx);
37526 		break;
37527 	}
37528 	case DUK_DBG_IB_TRUE: {
37529 		duk_push_true(ctx);
37530 		break;
37531 	}
37532 	case DUK_DBG_IB_FALSE: {
37533 		duk_push_false(ctx);
37534 		break;
37535 	}
37536 	case DUK_DBG_IB_NUMBER: {
37537 		duk_double_t d;
37538 		d = duk__debug_read_double_raw(thr);
37539 		duk_push_number(ctx, d);
37540 		break;
37541 	}
37542 	case DUK_DBG_IB_OBJECT: {
37543 		duk_heaphdr *h;
37544 		duk_debug_skip_byte(thr);
37545 		h = (duk_heaphdr *) duk__debug_read_pointer_raw(thr);
37546 		duk_push_heapptr(thr, (void *) h);
37547 		break;
37548 	}
37549 	case DUK_DBG_IB_POINTER: {
37550 		void *ptr;
37551 		ptr = duk__debug_read_pointer_raw(thr);
37552 		duk_push_pointer(thr, ptr);
37553 		break;
37554 	}
37555 	case DUK_DBG_IB_LIGHTFUNC: {
37556 		/* XXX: Not needed for now, so not implemented.  Note that
37557 		 * function pointers may have different size/layout than
37558 		 * a void pointer.
37559 		 */
37560 		DUK_D(DUK_DPRINT("reading lightfunc values unimplemented"));
37561 		goto fail;
37562 	}
37563 	case DUK_DBG_IB_HEAPPTR: {
37564 		duk_heaphdr *h;
37565 		h = (duk_heaphdr *) duk__debug_read_pointer_raw(thr);
37566 		duk_push_heapptr(thr, (void *) h);
37567 		break;
37568 	}
37569 	case DUK_DBG_IB_UNUSED:  /* unused: not accepted in inbound messages */
37570 	default:
37571 		goto fail;
37572 	}
37573 
37574  return_ptr:
37575 	return DUK_GET_TVAL_NEGIDX(thr, -1);
37576 
37577  fail:
37578 	DUK_D(DUK_DPRINT("debug connection error: failed to decode tval"));
37579 	DUK__SET_CONN_BROKEN(thr, 1);
37580 	return NULL;
37581 }
37582 
37583 /*
37584  *  Debug connection write primitives
37585  */
37586 
37587 /* Write fully. */
37588 DUK_INTERNAL void duk_debug_write_bytes(duk_hthread *thr, const duk_uint8_t *data, duk_size_t length) {
37589 	duk_heap *heap;
37590 	const duk_uint8_t *p;
37591 	duk_size_t left;
37592 	duk_size_t got;
37593 
37594 	DUK_ASSERT(thr != NULL);
37595 	DUK_ASSERT(length == 0 || data != NULL);
37596 	heap = thr->heap;
37597 	DUK_ASSERT(heap != NULL);
37598 
37599 	if (heap->dbg_write_cb == NULL) {
37600 		DUK_D(DUK_DPRINT("attempt to write %ld bytes in detached state, ignore", (long) length));
37601 		return;
37602 	}
37603 	if (length == 0) {
37604 		/* Avoid doing an actual write callback with length == 0,
37605 		 * because that's reserved for a write flush.
37606 		 */
37607 		return;
37608 	}
37609 	DUK_ASSERT(data != NULL);
37610 
37611 	p = data;
37612 	for (;;) {
37613 		left = (duk_size_t) ((data + length) - p);
37614 		if (left == 0) {
37615 			break;
37616 		}
37617 		DUK_ASSERT(heap->dbg_write_cb != NULL);
37618 		DUK_ASSERT(left >= 1);
37619 #if defined(DUK_USE_DEBUGGER_TRANSPORT_TORTURE)
37620 		left = 1;
37621 #endif
37622 		got = heap->dbg_write_cb(heap->dbg_udata, (const char *) p, left);
37623 		if (got == 0 || got > left) {
37624 			duk__debug_null_most_callbacks(thr);  /* avoid calling write callback in detach1() */
37625 			DUK_D(DUK_DPRINT("connection error during write"));
37626 			DUK__SET_CONN_BROKEN(thr, 1);
37627 			return;
37628 		}
37629 		p += got;
37630 	}
37631 }
37632 
37633 DUK_INTERNAL void duk_debug_write_byte(duk_hthread *thr, duk_uint8_t x) {
37634 	duk_debug_write_bytes(thr, (const duk_uint8_t *) &x, 1);
37635 }
37636 
37637 DUK_INTERNAL void duk_debug_write_unused(duk_hthread *thr) {
37638 	duk_debug_write_byte(thr, DUK_DBG_IB_UNUSED);
37639 }
37640 
37641 DUK_INTERNAL void duk_debug_write_undefined(duk_hthread *thr) {
37642 	duk_debug_write_byte(thr, DUK_DBG_IB_UNDEFINED);
37643 }
37644 
37645 #if defined(DUK_USE_DEBUGGER_INSPECT)
37646 DUK_INTERNAL void duk_debug_write_null(duk_hthread *thr) {
37647 	duk_debug_write_byte(thr, DUK_DBG_IB_NULL);
37648 }
37649 #endif
37650 
37651 DUK_INTERNAL void duk_debug_write_boolean(duk_hthread *thr, duk_uint_t val) {
37652 	duk_debug_write_byte(thr, val ? DUK_DBG_IB_TRUE : DUK_DBG_IB_FALSE);
37653 }
37654 
37655 /* Write signed 32-bit integer. */
37656 DUK_INTERNAL void duk_debug_write_int(duk_hthread *thr, duk_int32_t x) {
37657 	duk_uint8_t buf[5];
37658 	duk_size_t len;
37659 
37660 	DUK_ASSERT(thr != NULL);
37661 
37662 	if (x >= 0 && x <= 0x3fL) {
37663 		buf[0] = (duk_uint8_t) (0x80 + x);
37664 		len = 1;
37665 	} else if (x >= 0 && x <= 0x3fffL) {
37666 		buf[0] = (duk_uint8_t) (0xc0 + (x >> 8));
37667 		buf[1] = (duk_uint8_t) (x & 0xff);
37668 		len = 2;
37669 	} else {
37670 		/* Signed integers always map to 4 bytes now. */
37671 		buf[0] = (duk_uint8_t) DUK_DBG_IB_INT4;
37672 		buf[1] = (duk_uint8_t) ((x >> 24) & 0xff);
37673 		buf[2] = (duk_uint8_t) ((x >> 16) & 0xff);
37674 		buf[3] = (duk_uint8_t) ((x >> 8) & 0xff);
37675 		buf[4] = (duk_uint8_t) (x & 0xff);
37676 		len = 5;
37677 	}
37678 	duk_debug_write_bytes(thr, buf, len);
37679 }
37680 
37681 /* Write unsigned 32-bit integer. */
37682 DUK_INTERNAL void duk_debug_write_uint(duk_hthread *thr, duk_uint32_t x) {
37683 	/* The debugger protocol doesn't support a plain integer encoding for
37684 	 * the full 32-bit unsigned range (only 32-bit signed).  For now,
37685 	 * unsigned 32-bit values simply written as signed ones.  This is not
37686 	 * a concrete issue except for 32-bit heaphdr fields.  Proper solutions
37687 	 * would be to (a) write such integers as IEEE doubles or (b) add an
37688 	 * unsigned 32-bit dvalue.
37689 	 */
37690 	if (x >= 0x80000000UL) {
37691 		DUK_D(DUK_DPRINT("writing unsigned integer 0x%08lx as signed integer",
37692 		                 (long) x));
37693 	}
37694 	duk_debug_write_int(thr, (duk_int32_t) x);
37695 }
37696 
37697 DUK_INTERNAL void duk_debug_write_strbuf(duk_hthread *thr, const char *data, duk_size_t length, duk_uint8_t marker_base) {
37698 	duk_uint8_t buf[5];
37699 	duk_size_t buflen;
37700 
37701 	DUK_ASSERT(thr != NULL);
37702 	DUK_ASSERT(length == 0 || data != NULL);
37703 
37704 	if (length <= 0x1fUL && marker_base == DUK_DBG_IB_STR4) {
37705 		/* For strings, special form for short lengths. */
37706 		buf[0] = (duk_uint8_t) (0x60 + length);
37707 		buflen = 1;
37708 	} else if (length <= 0xffffUL) {
37709 		buf[0] = (duk_uint8_t) (marker_base + 1);
37710 		buf[1] = (duk_uint8_t) (length >> 8);
37711 		buf[2] = (duk_uint8_t) (length & 0xff);
37712 		buflen = 3;
37713 	} else {
37714 		buf[0] = (duk_uint8_t) marker_base;
37715 		buf[1] = (duk_uint8_t) (length >> 24);
37716 		buf[2] = (duk_uint8_t) ((length >> 16) & 0xff);
37717 		buf[3] = (duk_uint8_t) ((length >> 8) & 0xff);
37718 		buf[4] = (duk_uint8_t) (length & 0xff);
37719 		buflen = 5;
37720 	}
37721 
37722 	duk_debug_write_bytes(thr, (const duk_uint8_t *) buf, buflen);
37723 	duk_debug_write_bytes(thr, (const duk_uint8_t *) data, length);
37724 }
37725 
37726 DUK_INTERNAL void duk_debug_write_string(duk_hthread *thr, const char *data, duk_size_t length) {
37727 	duk_debug_write_strbuf(thr, data, length, DUK_DBG_IB_STR4);
37728 }
37729 
37730 DUK_INTERNAL void duk_debug_write_cstring(duk_hthread *thr, const char *data) {
37731 	DUK_ASSERT(thr != NULL);
37732 
37733 	duk_debug_write_string(thr,
37734 	                       data,
37735 	                       data ? DUK_STRLEN(data) : 0);
37736 }
37737 
37738 DUK_INTERNAL void duk_debug_write_hstring(duk_hthread *thr, duk_hstring *h) {
37739 	DUK_ASSERT(thr != NULL);
37740 
37741 	/* XXX: differentiate null pointer from empty string? */
37742 	duk_debug_write_string(thr,
37743 	                       (h != NULL ? (const char *) DUK_HSTRING_GET_DATA(h) : NULL),
37744 	                       (h != NULL ? (duk_size_t) DUK_HSTRING_GET_BYTELEN(h) : 0));
37745 }
37746 
37747 DUK_LOCAL void duk__debug_write_hstring_safe_top(duk_hthread *thr) {
37748 	duk_context *ctx = (duk_context *) thr;
37749 	duk_debug_write_hstring(thr, duk_safe_to_hstring(ctx, -1));
37750 }
37751 
37752 DUK_INTERNAL void duk_debug_write_buffer(duk_hthread *thr, const char *data, duk_size_t length) {
37753 	duk_debug_write_strbuf(thr, data, length, DUK_DBG_IB_BUF4);
37754 }
37755 
37756 DUK_INTERNAL void duk_debug_write_hbuffer(duk_hthread *thr, duk_hbuffer *h) {
37757 	DUK_ASSERT(thr != NULL);
37758 
37759 	duk_debug_write_buffer(thr,
37760 	                       (h != NULL ? (const char *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h) : NULL),
37761 	                       (h != NULL ? (duk_size_t) DUK_HBUFFER_GET_SIZE(h) : 0));
37762 }
37763 
37764 DUK_LOCAL void duk__debug_write_pointer_raw(duk_hthread *thr, void *ptr, duk_uint8_t ibyte) {
37765 	duk_uint8_t buf[2];
37766 	duk__ptr_union pu;
37767 
37768 	DUK_ASSERT(thr != NULL);
37769 	DUK_ASSERT(sizeof(ptr) >= 1 && sizeof(ptr) <= 16);
37770 	/* ptr may be NULL */
37771 
37772 	buf[0] = ibyte;
37773 	buf[1] = sizeof(pu);
37774 	duk_debug_write_bytes(thr, buf, 2);
37775 	pu.p = (void *) ptr;
37776 #if defined(DUK_USE_INTEGER_LE)
37777 	duk_byteswap_bytes((duk_uint8_t *) pu.b, sizeof(pu));
37778 #endif
37779 	duk_debug_write_bytes(thr, (const duk_uint8_t *) &pu.p, (duk_size_t) sizeof(pu));
37780 }
37781 
37782 DUK_INTERNAL void duk_debug_write_pointer(duk_hthread *thr, void *ptr) {
37783 	duk__debug_write_pointer_raw(thr, ptr, DUK_DBG_IB_POINTER);
37784 }
37785 
37786 #if defined(DUK_USE_DEBUGGER_DUMPHEAP) || defined(DUK_USE_DEBUGGER_INSPECT)
37787 DUK_INTERNAL void duk_debug_write_heapptr(duk_hthread *thr, duk_heaphdr *h) {
37788 	duk__debug_write_pointer_raw(thr, (void *) h, DUK_DBG_IB_HEAPPTR);
37789 }
37790 #endif  /* DUK_USE_DEBUGGER_DUMPHEAP || DUK_USE_DEBUGGER_INSPECT */
37791 
37792 DUK_INTERNAL void duk_debug_write_hobject(duk_hthread *thr, duk_hobject *obj) {
37793 	duk_uint8_t buf[3];
37794 	duk__ptr_union pu;
37795 
37796 	DUK_ASSERT(thr != NULL);
37797 	DUK_ASSERT(sizeof(obj) >= 1 && sizeof(obj) <= 16);
37798 	DUK_ASSERT(obj != NULL);
37799 
37800 	buf[0] = DUK_DBG_IB_OBJECT;
37801 	buf[1] = (duk_uint8_t) DUK_HOBJECT_GET_CLASS_NUMBER(obj);
37802 	buf[2] = sizeof(pu);
37803 	duk_debug_write_bytes(thr, buf, 3);
37804 	pu.p = (void *) obj;
37805 #if defined(DUK_USE_INTEGER_LE)
37806 	duk_byteswap_bytes((duk_uint8_t *) pu.b, sizeof(pu));
37807 #endif
37808 	duk_debug_write_bytes(thr, (const duk_uint8_t *) &pu.p, (duk_size_t) sizeof(pu));
37809 }
37810 
37811 DUK_INTERNAL void duk_debug_write_tval(duk_hthread *thr, duk_tval *tv) {
37812 	duk_c_function lf_func;
37813 	duk_small_uint_t lf_flags;
37814 	duk_uint8_t buf[4];
37815 	duk_double_union du1;
37816 	duk_double_union du2;
37817 	duk_int32_t i32;
37818 
37819 	DUK_ASSERT(thr != NULL);
37820 	DUK_ASSERT(tv != NULL);
37821 
37822 	switch (DUK_TVAL_GET_TAG(tv)) {
37823 	case DUK_TAG_UNDEFINED:
37824 		duk_debug_write_byte(thr, DUK_DBG_IB_UNDEFINED);
37825 		break;
37826 	case DUK_TAG_UNUSED:
37827 		duk_debug_write_byte(thr, DUK_DBG_IB_UNUSED);
37828 		break;
37829 	case DUK_TAG_NULL:
37830 		duk_debug_write_byte(thr, DUK_DBG_IB_NULL);
37831 		break;
37832 	case DUK_TAG_BOOLEAN:
37833 		DUK_ASSERT(DUK_TVAL_GET_BOOLEAN(tv) == 0 ||
37834 		           DUK_TVAL_GET_BOOLEAN(tv) == 1);
37835 		duk_debug_write_boolean(thr, DUK_TVAL_GET_BOOLEAN(tv));
37836 		break;
37837 	case DUK_TAG_POINTER:
37838 		duk_debug_write_pointer(thr, (void *) DUK_TVAL_GET_POINTER(tv));
37839 		break;
37840 	case DUK_TAG_LIGHTFUNC:
37841 		DUK_TVAL_GET_LIGHTFUNC(tv, lf_func, lf_flags);
37842 		buf[0] = DUK_DBG_IB_LIGHTFUNC;
37843 		buf[1] = (duk_uint8_t) (lf_flags >> 8);
37844 		buf[2] = (duk_uint8_t) (lf_flags & 0xff);
37845 		buf[3] = sizeof(lf_func);
37846 		duk_debug_write_bytes(thr, buf, 4);
37847 		duk_debug_write_bytes(thr, (const duk_uint8_t *) &lf_func, sizeof(lf_func));
37848 		break;
37849 	case DUK_TAG_STRING:
37850 		duk_debug_write_hstring(thr, DUK_TVAL_GET_STRING(tv));
37851 		break;
37852 	case DUK_TAG_OBJECT:
37853 		duk_debug_write_hobject(thr, DUK_TVAL_GET_OBJECT(tv));
37854 		break;
37855 	case DUK_TAG_BUFFER:
37856 		duk_debug_write_hbuffer(thr, DUK_TVAL_GET_BUFFER(tv));
37857 		break;
37858 #if defined(DUK_USE_FASTINT)
37859 	case DUK_TAG_FASTINT:
37860 #endif
37861 	default:
37862 		/* Numbers are normalized to big (network) endian.  We can
37863 		 * (but are not required) to use integer dvalues when there's
37864 		 * no loss of precision.
37865 		 *
37866 		 * XXX: share check with other code; this check is slow but
37867 		 * reliable and doesn't require careful exponent/mantissa
37868 		 * mask tricks as in the fastint downgrade code.
37869 		 */
37870 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
37871 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
37872 		du1.d = DUK_TVAL_GET_NUMBER(tv);
37873 		i32 = (duk_int32_t) du1.d;
37874 		du2.d = (duk_double_t) i32;
37875 
37876 		DUK_DD(DUK_DDPRINT("i32=%ld du1=%02x%02x%02x%02x%02x%02x%02x%02x "
37877 		                   "du2=%02x%02x%02x%02x%02x%02x%02x%02x",
37878 		                   (long) i32,
37879 		                   (unsigned int) du1.uc[0], (unsigned int) du1.uc[1],
37880 		                   (unsigned int) du1.uc[2], (unsigned int) du1.uc[3],
37881 		                   (unsigned int) du1.uc[4], (unsigned int) du1.uc[5],
37882 		                   (unsigned int) du1.uc[6], (unsigned int) du1.uc[7],
37883 		                   (unsigned int) du2.uc[0], (unsigned int) du2.uc[1],
37884 		                   (unsigned int) du2.uc[2], (unsigned int) du2.uc[3],
37885 		                   (unsigned int) du2.uc[4], (unsigned int) du2.uc[5],
37886 		                   (unsigned int) du2.uc[6], (unsigned int) du2.uc[7]));
37887 
37888 		if (DUK_MEMCMP((const void *) du1.uc, (const void *) du2.uc, sizeof(du1.uc)) == 0) {
37889 			duk_debug_write_int(thr, i32);
37890 		} else {
37891 			DUK_DBLUNION_DOUBLE_HTON(&du1);
37892 			duk_debug_write_byte(thr, DUK_DBG_IB_NUMBER);
37893 			duk_debug_write_bytes(thr, (const duk_uint8_t *) du1.uc, sizeof(du1.uc));
37894 		}
37895 	}
37896 }
37897 
37898 #if defined(DUK_USE_DEBUGGER_DUMPHEAP)
37899 /* Variant for writing duk_tvals so that any heap allocated values are
37900  * written out as tagged heap pointers.
37901  */
37902 DUK_LOCAL void duk__debug_write_tval_heapptr(duk_hthread *thr, duk_tval *tv) {
37903 	if (DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
37904 		duk_heaphdr *h = DUK_TVAL_GET_HEAPHDR(tv);
37905 		duk_debug_write_heapptr(thr, h);
37906 	} else {
37907 		duk_debug_write_tval(thr, tv);
37908 	}
37909 }
37910 #endif  /* DUK_USE_DEBUGGER_DUMPHEAP */
37911 
37912 /*
37913  *  Debug connection message write helpers
37914  */
37915 
37916 #if 0  /* unused */
37917 DUK_INTERNAL void duk_debug_write_request(duk_hthread *thr, duk_small_uint_t command) {
37918 	duk_debug_write_byte(thr, DUK_DBG_IB_REQUEST);
37919 	duk_debug_write_int(thr, command);
37920 }
37921 #endif
37922 
37923 DUK_INTERNAL void duk_debug_write_reply(duk_hthread *thr) {
37924 	duk_debug_write_byte(thr, DUK_DBG_IB_REPLY);
37925 }
37926 
37927 DUK_INTERNAL void duk_debug_write_error_eom(duk_hthread *thr, duk_small_uint_t err_code, const char *msg) {
37928 	/* Allow NULL 'msg' */
37929 	duk_debug_write_byte(thr, DUK_DBG_IB_ERROR);
37930 	duk_debug_write_int(thr, (duk_int32_t) err_code);
37931 	duk_debug_write_cstring(thr, msg);
37932 	duk_debug_write_eom(thr);
37933 }
37934 
37935 DUK_INTERNAL void duk_debug_write_notify(duk_hthread *thr, duk_small_uint_t command) {
37936 	duk_debug_write_byte(thr, DUK_DBG_IB_NOTIFY);
37937 	duk_debug_write_int(thr, command);
37938 }
37939 
37940 DUK_INTERNAL void duk_debug_write_eom(duk_hthread *thr) {
37941 	duk_debug_write_byte(thr, DUK_DBG_IB_EOM);
37942 
37943 	/* As an initial implementation, write flush after every EOM (and the
37944 	 * version identifier).  A better implementation would flush only when
37945 	 * Duktape is finished processing messages so that a flush only happens
37946 	 * after all outbound messages are finished on that occasion.
37947 	 */
37948 	duk_debug_write_flush(thr);
37949 }
37950 
37951 /*
37952  *  Status message and helpers
37953  */
37954 
37955 DUK_INTERNAL duk_uint_fast32_t duk_debug_curr_line(duk_hthread *thr) {
37956 	duk_context *ctx = (duk_context *) thr;
37957 	duk_activation *act;
37958 	duk_uint_fast32_t line;
37959 	duk_uint_fast32_t pc;
37960 
37961 	act = duk_hthread_get_current_activation(thr);  /* may be NULL */
37962 	if (act == NULL) {
37963 		return 0;
37964 	}
37965 
37966 	/* We're conceptually between two opcodes; act->pc indicates the next
37967 	 * instruction to be executed.  This is usually the correct pc/line to
37968 	 * indicate in Status.  (For the 'debugger' statement this now reports
37969 	 * the pc/line after the debugger statement because the debugger opcode
37970 	 * has already been executed.)
37971 	 */
37972 
37973 	pc = duk_hthread_get_act_curr_pc(thr, act);
37974 
37975 	/* XXX: this should be optimized to be a raw query and avoid valstack
37976 	 * operations if possible.
37977 	 */
37978 	duk_push_tval(ctx, &act->tv_func);
37979 	line = duk_hobject_pc2line_query(ctx, -1, pc);
37980 	duk_pop(ctx);
37981 	return line;
37982 }
37983 
37984 DUK_INTERNAL void duk_debug_send_status(duk_hthread *thr) {
37985 	duk_context *ctx = (duk_context *) thr;
37986 	duk_activation *act;
37987 
37988 	duk_debug_write_notify(thr, DUK_DBG_CMD_STATUS);
37989 	duk_debug_write_int(thr, thr->heap->dbg_paused);
37990 
37991 	DUK_ASSERT_DISABLE(thr->callstack_top >= 0);  /* unsigned */
37992 	if (thr->callstack_top == 0) {
37993 		duk_debug_write_undefined(thr);
37994 		duk_debug_write_undefined(thr);
37995 		duk_debug_write_int(thr, 0);
37996 		duk_debug_write_int(thr, 0);
37997 	} else {
37998 		act = thr->callstack + thr->callstack_top - 1;
37999 		duk_push_tval(ctx, &act->tv_func);
38000 		duk_get_prop_string(ctx, -1, "fileName");
38001 		duk__debug_write_hstring_safe_top(thr);
38002 		duk_get_prop_string(ctx, -2, "name");
38003 		duk__debug_write_hstring_safe_top(thr);
38004 		duk_pop_3(ctx);
38005 		/* Report next pc/line to be executed. */
38006 		duk_debug_write_uint(thr, (duk_uint32_t) duk_debug_curr_line(thr));
38007 		act = thr->callstack + thr->callstack_top - 1;
38008 		duk_debug_write_uint(thr, (duk_uint32_t) duk_hthread_get_act_curr_pc(thr, act));
38009 	}
38010 
38011 	duk_debug_write_eom(thr);
38012 }
38013 
38014 #if defined(DUK_USE_DEBUGGER_THROW_NOTIFY)
38015 DUK_INTERNAL void duk_debug_send_throw(duk_hthread *thr, duk_bool_t fatal) {
38016 	/*
38017 	 *  NFY <int: 5> <int: fatal> <str: msg> <str: filename> <int: linenumber> EOM
38018 	 */
38019 
38020 	duk_context *ctx = (duk_context *) thr;
38021 	duk_activation *act;
38022 	duk_uint32_t pc;
38023 
38024 	DUK_ASSERT(thr->valstack_top > thr->valstack);  /* At least: ... [err] */
38025 
38026 	duk_debug_write_notify(thr, DUK_DBG_CMD_THROW);
38027 	duk_debug_write_int(thr, fatal);
38028 
38029 	/* Report thrown value to client coerced to string */
38030 	duk_dup(ctx, -1);
38031 	duk__debug_write_hstring_safe_top(thr);
38032 	duk_pop(ctx);
38033 
38034 	if (duk_is_error(ctx, -1)) {
38035 		/* Error instance, use augmented error data directly */
38036 		duk_get_prop_stridx(ctx, -1, DUK_STRIDX_FILE_NAME);
38037 		duk__debug_write_hstring_safe_top(thr);
38038 		duk_get_prop_stridx(ctx, -2, DUK_STRIDX_LINE_NUMBER);
38039 		duk_debug_write_uint(thr, duk_get_uint(ctx, -1));
38040 		duk_pop_2(ctx);
38041 	} else {
38042 		/* For anything other than an Error instance, we calculate the
38043 		 * error location directly from the current activation if one
38044 		 * exists.
38045 		 */
38046 		if (thr->callstack_top > 0) {
38047 			act = thr->callstack + thr->callstack_top - 1;
38048 			duk_push_tval(ctx, &act->tv_func);
38049 			duk_get_prop_string(ctx, -1, "fileName");
38050 			duk__debug_write_hstring_safe_top(thr);
38051 			act = thr->callstack + thr->callstack_top - 1;
38052 			pc = duk_hthread_get_act_prev_pc(thr, act);
38053 			duk_debug_write_uint(thr, (duk_uint32_t) duk_hobject_pc2line_query(ctx, -2, pc));
38054 			duk_pop_2(ctx);
38055 		} else {
38056 			/* Can happen if duk_throw() is called on an empty
38057 			 * callstack.
38058 			 */
38059 			duk_debug_write_cstring(thr, "");
38060 			duk_debug_write_uint(thr, 0);
38061 		}
38062 	}
38063 
38064 	duk_debug_write_eom(thr);
38065 }
38066 #endif  /* DUK_USE_DEBUGGER_THROW_NOTIFY */
38067 
38068 /*
38069  *  Debug message processing
38070  */
38071 
38072 /* Skip dvalue. */
38073 DUK_LOCAL duk_bool_t duk__debug_skip_dvalue(duk_hthread *thr) {
38074 	duk_uint8_t x;
38075 	duk_uint32_t len;
38076 
38077 	x = duk_debug_read_byte(thr);
38078 
38079 	if (x >= 0xc0) {
38080 		duk_debug_skip_byte(thr);
38081 		return 0;
38082 	}
38083 	if (x >= 0x80) {
38084 		return 0;
38085 	}
38086 	if (x >= 0x60) {
38087 		duk_debug_skip_bytes(thr, x - 0x60);
38088 		return 0;
38089 	}
38090 	switch(x) {
38091 	case DUK_DBG_IB_EOM:
38092 		return 1;  /* Return 1: got EOM */
38093 	case DUK_DBG_IB_REQUEST:
38094 	case DUK_DBG_IB_REPLY:
38095 	case DUK_DBG_IB_ERROR:
38096 	case DUK_DBG_IB_NOTIFY:
38097 		break;
38098 	case DUK_DBG_IB_INT4:
38099 		(void) duk__debug_read_uint32_raw(thr);
38100 		break;
38101 	case DUK_DBG_IB_STR4:
38102 	case DUK_DBG_IB_BUF4:
38103 		len = duk__debug_read_uint32_raw(thr);
38104 		duk_debug_skip_bytes(thr, len);
38105 		break;
38106 	case DUK_DBG_IB_STR2:
38107 	case DUK_DBG_IB_BUF2:
38108 		len = duk__debug_read_uint16_raw(thr);
38109 		duk_debug_skip_bytes(thr, len);
38110 		break;
38111 	case DUK_DBG_IB_UNUSED:
38112 	case DUK_DBG_IB_UNDEFINED:
38113 	case DUK_DBG_IB_NULL:
38114 	case DUK_DBG_IB_TRUE:
38115 	case DUK_DBG_IB_FALSE:
38116 		break;
38117 	case DUK_DBG_IB_NUMBER:
38118 		duk_debug_skip_bytes(thr, 8);
38119 		break;
38120 	case DUK_DBG_IB_OBJECT:
38121 		duk_debug_skip_byte(thr);
38122 		len = duk_debug_read_byte(thr);
38123 		duk_debug_skip_bytes(thr, len);
38124 		break;
38125 	case DUK_DBG_IB_POINTER:
38126 	case DUK_DBG_IB_HEAPPTR:
38127 		len = duk_debug_read_byte(thr);
38128 		duk_debug_skip_bytes(thr, len);
38129 		break;
38130 	case DUK_DBG_IB_LIGHTFUNC:
38131 		duk_debug_skip_bytes(thr, 2);
38132 		len = duk_debug_read_byte(thr);
38133 		duk_debug_skip_bytes(thr, len);
38134 		break;
38135 	default:
38136 		goto fail;
38137 	}
38138 
38139 	return 0;
38140 
38141  fail:
38142 	DUK__SET_CONN_BROKEN(thr, 1);
38143 	return 1;  /* Pretend like we got EOM */
38144 }
38145 
38146 /* Skip dvalues to EOM. */
38147 DUK_LOCAL void duk__debug_skip_to_eom(duk_hthread *thr) {
38148 	for (;;) {
38149 		if (duk__debug_skip_dvalue(thr)) {
38150 			break;
38151 		}
38152 	}
38153 }
38154 
38155 /*
38156  *  Simple commands
38157  */
38158 
38159 DUK_LOCAL void duk__debug_handle_basic_info(duk_hthread *thr, duk_heap *heap) {
38160 	DUK_UNREF(heap);
38161 	DUK_D(DUK_DPRINT("debug command Version"));
38162 
38163 	duk_debug_write_reply(thr);
38164 	duk_debug_write_int(thr, DUK_VERSION);
38165 	duk_debug_write_cstring(thr, DUK_GIT_DESCRIBE);
38166 	duk_debug_write_cstring(thr, DUK_USE_TARGET_INFO);
38167 #if defined(DUK_USE_DOUBLE_LE)
38168 	duk_debug_write_int(thr, 1);
38169 #elif defined(DUK_USE_DOUBLE_ME)
38170 	duk_debug_write_int(thr, 2);
38171 #elif defined(DUK_USE_DOUBLE_BE)
38172 	duk_debug_write_int(thr, 3);
38173 #else
38174 	duk_debug_write_int(thr, 0);
38175 #endif
38176 	duk_debug_write_int(thr, (duk_int_t) sizeof(void *));
38177 	duk_debug_write_eom(thr);
38178 }
38179 
38180 DUK_LOCAL void duk__debug_handle_trigger_status(duk_hthread *thr, duk_heap *heap) {
38181 	DUK_UNREF(heap);
38182 	DUK_D(DUK_DPRINT("debug command TriggerStatus"));
38183 
38184 	duk_debug_write_reply(thr);
38185 	duk_debug_write_eom(thr);
38186 	heap->dbg_state_dirty = 1;
38187 }
38188 
38189 DUK_LOCAL void duk__debug_handle_pause(duk_hthread *thr, duk_heap *heap) {
38190 	DUK_D(DUK_DPRINT("debug command Pause"));
38191 
38192 	DUK_HEAP_SET_PAUSED(heap);
38193 	duk_debug_write_reply(thr);
38194 	duk_debug_write_eom(thr);
38195 }
38196 
38197 DUK_LOCAL void duk__debug_handle_resume(duk_hthread *thr, duk_heap *heap) {
38198 	DUK_D(DUK_DPRINT("debug command Resume"));
38199 
38200 	DUK_HEAP_CLEAR_PAUSED(heap);
38201 	duk_debug_write_reply(thr);
38202 	duk_debug_write_eom(thr);
38203 }
38204 
38205 DUK_LOCAL void duk__debug_handle_step(duk_hthread *thr, duk_heap *heap, duk_int32_t cmd) {
38206 	duk_small_uint_t step_type;
38207 	duk_uint_fast32_t line;
38208 
38209 	DUK_D(DUK_DPRINT("debug command StepInto/StepOver/StepOut: %d", (int) cmd));
38210 
38211 	if (cmd == DUK_DBG_CMD_STEPINTO) {
38212 		step_type = DUK_STEP_TYPE_INTO;
38213 	} else if (cmd == DUK_DBG_CMD_STEPOVER) {
38214 		step_type = DUK_STEP_TYPE_OVER;
38215 	} else {
38216 		DUK_ASSERT(cmd == DUK_DBG_CMD_STEPOUT);
38217 		step_type = DUK_STEP_TYPE_OUT;
38218 	}
38219 
38220 	line = duk_debug_curr_line(thr);
38221 	if (line > 0) {
38222 		heap->dbg_paused = 0;
38223 		heap->dbg_step_type = step_type;
38224 		heap->dbg_step_thread = thr;
38225 		heap->dbg_step_csindex = thr->callstack_top - 1;
38226 		heap->dbg_step_startline = line;
38227 		heap->dbg_state_dirty = 1;
38228 	} else {
38229 		DUK_D(DUK_DPRINT("cannot determine current line, stepinto/stepover/stepout ignored"));
38230 	}
38231 	duk_debug_write_reply(thr);
38232 	duk_debug_write_eom(thr);
38233 }
38234 
38235 DUK_LOCAL void duk__debug_handle_list_break(duk_hthread *thr, duk_heap *heap) {
38236 	duk_small_int_t i;
38237 
38238 	DUK_D(DUK_DPRINT("debug command ListBreak"));
38239 	duk_debug_write_reply(thr);
38240 	for (i = 0; i < (duk_small_int_t) heap->dbg_breakpoint_count; i++) {
38241 		duk_debug_write_hstring(thr, heap->dbg_breakpoints[i].filename);
38242 		duk_debug_write_uint(thr, (duk_uint32_t) heap->dbg_breakpoints[i].line);
38243 	}
38244 	duk_debug_write_eom(thr);
38245 }
38246 
38247 DUK_LOCAL void duk__debug_handle_add_break(duk_hthread *thr, duk_heap *heap) {
38248 	duk_hstring *filename;
38249 	duk_uint32_t linenumber;
38250 	duk_small_int_t idx;
38251 
38252 	DUK_UNREF(heap);
38253 
38254 	filename = duk_debug_read_hstring(thr);
38255 	linenumber = (duk_uint32_t) duk_debug_read_int(thr);
38256 	DUK_D(DUK_DPRINT("debug command AddBreak: %!O:%ld", (duk_hobject *) filename, (long) linenumber));
38257 	idx = duk_debug_add_breakpoint(thr, filename, linenumber);
38258 	if (idx >= 0) {
38259 		duk_debug_write_reply(thr);
38260 		duk_debug_write_int(thr, (duk_int32_t) idx);
38261 		duk_debug_write_eom(thr);
38262 	} else {
38263 		duk_debug_write_error_eom(thr, DUK_DBG_ERR_TOOMANY, "no space for breakpoint");
38264 	}
38265 }
38266 
38267 DUK_LOCAL void duk__debug_handle_del_break(duk_hthread *thr, duk_heap *heap) {
38268 	duk_small_uint_t idx;
38269 
38270 	DUK_UNREF(heap);
38271 
38272 	DUK_D(DUK_DPRINT("debug command DelBreak"));
38273 	idx = (duk_small_uint_t) duk_debug_read_int(thr);
38274 	if (duk_debug_remove_breakpoint(thr, idx)) {
38275 		duk_debug_write_reply(thr);
38276 		duk_debug_write_eom(thr);
38277 	} else {
38278 		duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid breakpoint index");
38279 	}
38280 }
38281 
38282 DUK_LOCAL void duk__debug_handle_get_var(duk_hthread *thr, duk_heap *heap) {
38283 	duk_context *ctx = (duk_context *) thr;
38284 	duk_hstring *str;
38285 	duk_bool_t rc;
38286 	duk_int32_t level;
38287 
38288 	DUK_UNREF(heap);
38289 	DUK_D(DUK_DPRINT("debug command GetVar"));
38290 
38291 	str = duk_debug_read_hstring(thr);  /* push to stack */
38292 	DUK_ASSERT(str != NULL);
38293 	if (duk_debug_peek_byte(thr) != DUK_DBG_IB_EOM) {
38294 		level = duk_debug_read_int(thr);  /* optional callstack level */
38295 		if (level >= 0 || -level > (duk_int32_t) thr->callstack_top) {
38296 			DUK_D(DUK_DPRINT("invalid callstack level for GetVar"));
38297 			duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid callstack level");
38298 			return;
38299 		}
38300 	} else {
38301 		level = -1;
38302 	}
38303 
38304 	if (thr->callstack_top > 0) {
38305 		rc = duk_js_getvar_activation(thr,
38306 		                              thr->callstack + thr->callstack_top + level,
38307 		                              str,
38308 		                              0);
38309 	} else {
38310 		/* No activation, no variable access.  Could also pretend
38311 		 * we're in the global program context and read stuff off
38312 		 * the global object.
38313 		 */
38314 		DUK_D(DUK_DPRINT("callstack empty, no activation -> ignore getvar"));
38315 		rc = 0;
38316 	}
38317 
38318 	duk_debug_write_reply(thr);
38319 	if (rc) {
38320 		duk_debug_write_int(thr, 1);
38321 		DUK_ASSERT(duk_get_tval(ctx, -2) != NULL);
38322 		duk_debug_write_tval(thr, duk_get_tval(ctx, -2));
38323 	} else {
38324 		duk_debug_write_int(thr, 0);
38325 		duk_debug_write_unused(thr);
38326 	}
38327 	duk_debug_write_eom(thr);
38328 }
38329 
38330 DUK_LOCAL void duk__debug_handle_put_var(duk_hthread *thr, duk_heap *heap) {
38331 	duk_hstring *str;
38332 	duk_tval *tv;
38333 	duk_int32_t level;
38334 
38335 	DUK_UNREF(heap);
38336 	DUK_D(DUK_DPRINT("debug command PutVar"));
38337 
38338 	str = duk_debug_read_hstring(thr);  /* push to stack */
38339 	DUK_ASSERT(str != NULL);
38340 	tv = duk_debug_read_tval(thr);
38341 	if (tv == NULL) {
38342 		/* detached */
38343 		return;
38344 	}
38345 	if (duk_debug_peek_byte(thr) != DUK_DBG_IB_EOM) {
38346 		level = duk_debug_read_int(thr);  /* optional callstack level */
38347 		if (level >= 0 || -level > (duk_int32_t) thr->callstack_top) {
38348 			DUK_D(DUK_DPRINT("invalid callstack level for PutVar"));
38349 			duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid callstack level");
38350 			return;
38351 		}
38352 	} else {
38353 		level = -1;
38354 	}
38355 
38356 	if (thr->callstack_top > 0) {
38357 		duk_js_putvar_activation(thr,
38358 		                         thr->callstack + thr->callstack_top + level,
38359 		                         str,
38360 		                         tv,
38361 		                         0);
38362 	} else {
38363 		DUK_D(DUK_DPRINT("callstack empty, no activation -> ignore putvar"));
38364 	}
38365 
38366 	/* XXX: Current putvar implementation doesn't have a success flag,
38367 	 * add one and send to debug client?
38368 	 */
38369 	duk_debug_write_reply(thr);
38370 	duk_debug_write_eom(thr);
38371 }
38372 
38373 DUK_LOCAL void duk__debug_handle_get_call_stack(duk_hthread *thr, duk_heap *heap) {
38374 	duk_context *ctx = (duk_context *) thr;
38375 	duk_hthread *curr_thr = thr;
38376 	duk_activation *curr_act;
38377 	duk_uint_fast32_t pc;
38378 	duk_uint_fast32_t line;
38379 	duk_size_t i;
38380 
38381 	DUK_ASSERT(thr != NULL);
38382 	DUK_UNREF(heap);
38383 
38384 	duk_debug_write_reply(thr);
38385 	while (curr_thr != NULL) {
38386 		i = curr_thr->callstack_top;
38387 		while (i > 0) {
38388 			i--;
38389 			curr_act = curr_thr->callstack + i;
38390 
38391 			/* PC/line semantics here are:
38392 			 *   - For callstack top we're conceptually between two
38393 			 *     opcodes and current PC indicates next line to
38394 			 *     execute, so report that (matches Status).
38395 			 *   - For other activations we're conceptually still
38396 			 *     executing the instruction at PC-1, so report that
38397 			 *     (matches error stacktrace behavior).
38398 			 *   - See: https://github.com/svaarala/duktape/issues/281
38399 			 */
38400 
38401 			/* XXX: optimize to use direct reads, i.e. avoid
38402 			 * value stack operations.
38403 			 */
38404 			duk_push_tval(ctx, &curr_act->tv_func);
38405 			duk_get_prop_stridx(ctx, -1, DUK_STRIDX_FILE_NAME);
38406 			duk__debug_write_hstring_safe_top(thr);
38407 			duk_get_prop_stridx(ctx, -2, DUK_STRIDX_NAME);
38408 			duk__debug_write_hstring_safe_top(thr);
38409 			pc = duk_hthread_get_act_curr_pc(thr, curr_act);
38410 			if (i != curr_thr->callstack_top - 1 && pc > 0) {
38411 				pc--;
38412 			}
38413 			line = duk_hobject_pc2line_query(ctx, -3, pc);
38414 			duk_debug_write_uint(thr, (duk_uint32_t) line);
38415 			duk_debug_write_uint(thr, (duk_uint32_t) pc);
38416 			duk_pop_3(ctx);
38417 		}
38418 		curr_thr = curr_thr->resumer;
38419 	}
38420 	/* SCANBUILD: warning about 'thr' potentially being NULL here,
38421 	 * warning is incorrect because thr != NULL always here.
38422 	 */
38423 	duk_debug_write_eom(thr);
38424 }
38425 
38426 DUK_LOCAL void duk__debug_handle_get_locals(duk_hthread *thr, duk_heap *heap) {
38427 	duk_context *ctx = (duk_context *) thr;
38428 	duk_activation *curr_act;
38429 	duk_int32_t level;
38430 	duk_hstring *varname;
38431 
38432 	DUK_UNREF(heap);
38433 
38434 	if (duk_debug_peek_byte(thr) != DUK_DBG_IB_EOM) {
38435 		level = duk_debug_read_int(thr);  /* optional callstack level */
38436 		if (level >= 0 || -level > (duk_int32_t) thr->callstack_top) {
38437 			DUK_D(DUK_DPRINT("invalid callstack level for GetLocals"));
38438 			duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid callstack level");
38439 			return;
38440 		}
38441 		duk_debug_write_reply(thr);
38442 	} else {
38443 		duk_debug_write_reply(thr);
38444 		if (thr->callstack_top == 0) {
38445 			goto callstack_empty;
38446 		}
38447 		level = -1;
38448 	}
38449 
38450 	curr_act = thr->callstack + thr->callstack_top + level;
38451 
38452 	/* XXX: several nice-to-have improvements here:
38453 	 *   - Use direct reads avoiding value stack operations
38454 	 *   - Avoid triggering getters, indicate getter values to debug client
38455 	 *   - If side effects are possible, add error catching
38456 	 */
38457 
38458 	duk_push_tval(ctx, &curr_act->tv_func);
38459 	duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_VARMAP);
38460 	if (duk_is_object(ctx, -1)) {
38461 		duk_enum(ctx, -1, 0 /*enum_flags*/);
38462 		while (duk_next(ctx, -1 /*enum_index*/, 0 /*get_value*/)) {
38463 			varname = duk_get_hstring(ctx, -1);
38464 			DUK_ASSERT(varname != NULL);
38465 
38466 			duk_js_getvar_activation(thr, curr_act, varname, 0 /*throw_flag*/);
38467 			/* [ ... func varmap enum key value this ] */
38468 			duk_debug_write_hstring(thr, duk_get_hstring(ctx, -3));
38469 			duk_debug_write_tval(thr, duk_get_tval(ctx, -2));
38470 			duk_pop_3(ctx);  /* -> [ ... func varmap enum ] */
38471 		}
38472 	} else {
38473 		DUK_D(DUK_DPRINT("varmap is not an object in GetLocals, ignore"));
38474 	}
38475 
38476  callstack_empty:
38477 	duk_debug_write_eom(thr);
38478 }
38479 
38480 DUK_LOCAL void duk__debug_handle_eval(duk_hthread *thr, duk_heap *heap) {
38481 	duk_context *ctx = (duk_context *) thr;
38482 	duk_small_uint_t call_flags;
38483 	duk_int_t call_ret;
38484 	duk_small_int_t eval_err;
38485 	duk_int32_t level;
38486 
38487 	DUK_UNREF(heap);
38488 
38489 	DUK_D(DUK_DPRINT("debug command Eval"));
38490 
38491 	/* The eval code is executed within the lexical environment of a specified
38492 	 * activation.  For now, use global object eval() function, with the eval
38493 	 * considered a 'direct call to eval'.
38494 	 *
38495 	 * Callstack level for debug commands only affects scope -- the callstack
38496 	 * as seen by, e.g. Duktape.act() will be the same regardless.
38497 	 */
38498 
38499 	/* nargs == 2 so we can pass a callstack level to eval(). */
38500 	duk_push_c_function(ctx, duk_bi_global_object_eval, 2 /*nargs*/);
38501 	duk_push_undefined(ctx);  /* 'this' binding shouldn't matter here */
38502 
38503 	(void) duk_debug_read_hstring(thr);
38504 	if (duk_debug_peek_byte(thr) != DUK_DBG_IB_EOM) {
38505 		level = duk_debug_read_int(thr);  /* optional callstack level */
38506 		if (level >= 0 || -level > (duk_int32_t) thr->callstack_top) {
38507 			DUK_D(DUK_DPRINT("invalid callstack level for Eval"));
38508 			duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid callstack level");
38509 			return;
38510 		}
38511 	}
38512 	else {
38513 		level = -1;
38514 	}
38515 	DUK_ASSERT(level < 0 && -level <= (duk_int32_t) thr->callstack_top);
38516 	duk_push_int(ctx, level - 1);  /* compensate for eval() call */
38517 
38518 	/* [ ... eval "eval" eval_input level ] */
38519 
38520 	call_flags = 0;
38521 	if (thr->callstack_top >= (duk_size_t) -level) {
38522 		duk_activation *act;
38523 		duk_hobject *fun;
38524 
38525 		act = thr->callstack + thr->callstack_top + level;
38526 		fun = DUK_ACT_GET_FUNC(act);
38527 		if (fun != NULL && DUK_HOBJECT_IS_COMPILEDFUNCTION(fun)) {
38528 			/* Direct eval requires that there's a current
38529 			 * activation and it is an Ecmascript function.
38530 			 * When Eval is executed from e.g. cooperate API
38531 			 * call we'll need to do an indirect eval instead.
38532 			 */
38533 			call_flags |= DUK_CALL_FLAG_DIRECT_EVAL;
38534 		}
38535 	}
38536 
38537 	call_ret = duk_handle_call_protected(thr, 2 /*num_stack_args*/, call_flags);
38538 
38539 	if (call_ret == DUK_EXEC_SUCCESS) {
38540 		eval_err = 0;
38541 		/* Use result value as is. */
38542 	} else {
38543 		/* For errors a string coerced result is most informative
38544 		 * right now, as the debug client doesn't have the capability
38545 		 * to traverse the error object.
38546 		 */
38547 		eval_err = 1;
38548 		duk_safe_to_string(ctx, -1);
38549 	}
38550 
38551 	/* [ ... result ] */
38552 
38553 	duk_debug_write_reply(thr);
38554 	duk_debug_write_int(thr, (duk_int32_t) eval_err);
38555 	DUK_ASSERT(duk_get_tval(ctx, -1) != NULL);
38556 	duk_debug_write_tval(thr, duk_get_tval(ctx, -1));
38557 	duk_debug_write_eom(thr);
38558 }
38559 
38560 DUK_LOCAL void duk__debug_handle_detach(duk_hthread *thr, duk_heap *heap) {
38561 	DUK_UNREF(heap);
38562 	DUK_D(DUK_DPRINT("debug command Detach"));
38563 
38564 	duk_debug_write_reply(thr);
38565 	duk_debug_write_eom(thr);
38566 
38567 	DUK_D(DUK_DPRINT("debug connection detached, mark broken"));
38568 	DUK__SET_CONN_BROKEN(thr, 0);  /* not an error */
38569 }
38570 
38571 DUK_LOCAL void duk__debug_handle_apprequest(duk_hthread *thr, duk_heap *heap) {
38572 	duk_context *ctx = (duk_context *) thr;
38573 	duk_idx_t old_top;
38574 
38575 	DUK_D(DUK_DPRINT("debug command AppRequest"));
38576 
38577 	old_top = duk_get_top(ctx);  /* save stack top */
38578 
38579 	if (heap->dbg_request_cb != NULL) {
38580 		duk_idx_t nrets;
38581 		duk_idx_t nvalues = 0;
38582 		duk_idx_t top, idx;
38583 
38584 		/* Read tvals from the message and push them onto the valstack,
38585 		 * then call the request callback to process the request.
38586 		 */
38587 		while (duk_debug_peek_byte(thr) != DUK_DBG_IB_EOM) {
38588 			duk_tval *tv;
38589 			if (!duk_check_stack(ctx, 1)) {
38590 				DUK_D(DUK_DPRINT("failed to allocate space for request dvalue(s)"));
38591 				goto fail;
38592 			}
38593 			tv = duk_debug_read_tval(thr);  /* push to stack */
38594 			if (tv == NULL) {
38595 				/* detached */
38596 				return;
38597 			}
38598 			nvalues++;
38599 		}
38600 		DUK_ASSERT(duk_get_top(ctx) == old_top + nvalues);
38601 
38602 		/* Request callback should push values for reply to client onto valstack */
38603 		DUK_D(DUK_DPRINT("calling into AppRequest request_cb with nvalues=%ld, old_top=%ld, top=%ld",
38604 		                 (long) nvalues, (long) old_top, (long) duk_get_top(ctx)));
38605 		nrets = heap->dbg_request_cb(ctx, heap->dbg_udata, nvalues);
38606 		DUK_D(DUK_DPRINT("returned from AppRequest request_cb; nvalues=%ld -> nrets=%ld, old_top=%ld, top=%ld",
38607 		                 (long) nvalues, (long) nrets, (long) old_top, (long) duk_get_top(ctx)));
38608 		if (nrets >= 0) {
38609 			DUK_ASSERT(duk_get_top(ctx) >= old_top + nrets);
38610 			if (duk_get_top(ctx) < old_top + nrets) {
38611 				DUK_D(DUK_DPRINT("AppRequest callback doesn't match value stack configuration, "
38612 				                 "top=%ld < old_top=%ld + nrets=%ld; "
38613 				                 "this might mean it's unsafe to continue!",
38614 				                 (long) duk_get_top(ctx), (long) old_top, (long) nrets));
38615 				goto fail;
38616 			}
38617 
38618 			/* Reply with tvals pushed by request callback */
38619 			duk_debug_write_byte(thr, DUK_DBG_IB_REPLY);
38620 			top = duk_get_top(ctx);
38621 			for (idx = top - nrets; idx < top; idx++) {
38622 				duk_debug_write_tval(thr, DUK_GET_TVAL_POSIDX(ctx, idx));
38623 			}
38624 			duk_debug_write_eom(thr);
38625 		} else {
38626 			DUK_ASSERT(duk_get_top(ctx) >= old_top + 1);
38627 			if (duk_get_top(ctx) < old_top + 1) {
38628 				DUK_D(DUK_DPRINT("request callback return value doesn't match value stack configuration"));
38629 				goto fail;
38630 			}
38631 			duk_debug_write_error_eom(thr, DUK_DBG_ERR_APPLICATION, duk_get_string(ctx, -1));
38632 		}
38633 
38634 		duk_set_top(ctx, old_top);  /* restore stack top */
38635 	} else {
38636 		DUK_D(DUK_DPRINT("no request callback, treat AppRequest as unsupported"));
38637 		duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNSUPPORTED, "AppRequest unsupported by target");
38638 	}
38639 
38640 	return;
38641 
38642  fail:
38643 	duk_set_top(ctx, old_top);  /* restore stack top */
38644 	DUK__SET_CONN_BROKEN(thr, 1);
38645 }
38646 
38647 /*
38648  *  DumpHeap command
38649  */
38650 
38651 #if defined(DUK_USE_DEBUGGER_DUMPHEAP)
38652 /* XXX: this has some overlap with object inspection; remove this and make
38653  * DumpHeap return lists of heapptrs instead?
38654  */
38655 DUK_LOCAL void duk__debug_dump_heaphdr(duk_hthread *thr, duk_heap *heap, duk_heaphdr *hdr) {
38656 	DUK_UNREF(heap);
38657 
38658 	duk_debug_write_heapptr(thr, hdr);
38659 	duk_debug_write_uint(thr, (duk_uint32_t) DUK_HEAPHDR_GET_TYPE(hdr));
38660 	duk_debug_write_uint(thr, (duk_uint32_t) DUK_HEAPHDR_GET_FLAGS_RAW(hdr));
38661 #if defined(DUK_USE_REFERENCE_COUNTING)
38662 	duk_debug_write_uint(thr, (duk_uint32_t) DUK_HEAPHDR_GET_REFCOUNT(hdr));
38663 #else
38664 	duk_debug_write_int(thr, (duk_int32_t) -1);
38665 #endif
38666 
38667 	switch (DUK_HEAPHDR_GET_TYPE(hdr)) {
38668 	case DUK_HTYPE_STRING: {
38669 		duk_hstring *h = (duk_hstring *) hdr;
38670 
38671 		duk_debug_write_uint(thr, (duk_int32_t) DUK_HSTRING_GET_BYTELEN(h));
38672 		duk_debug_write_uint(thr, (duk_int32_t) DUK_HSTRING_GET_CHARLEN(h));
38673 		duk_debug_write_uint(thr, (duk_int32_t) DUK_HSTRING_GET_HASH(h));
38674 		duk_debug_write_hstring(thr, h);
38675 		break;
38676 	}
38677 	case DUK_HTYPE_OBJECT: {
38678 		duk_hobject *h = (duk_hobject *) hdr;
38679 		duk_hstring *k;
38680 		duk_uint_fast32_t i;
38681 
38682 		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_CLASS_NUMBER(h));
38683 		duk_debug_write_heapptr(thr, (duk_heaphdr *) DUK_HOBJECT_GET_PROTOTYPE(heap, h));
38684 		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_ESIZE(h));
38685 		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_ENEXT(h));
38686 		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_ASIZE(h));
38687 		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_HSIZE(h));
38688 
38689 		for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h); i++) {
38690 			duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_E_GET_FLAGS(heap, h, i));
38691 			k = DUK_HOBJECT_E_GET_KEY(heap, h, i);
38692 			duk_debug_write_heapptr(thr, (duk_heaphdr *) k);
38693 			if (k == NULL) {
38694 				duk_debug_write_int(thr, 0);  /* isAccessor */
38695 				duk_debug_write_unused(thr);
38696 				continue;
38697 			}
38698 			if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, h, i)) {
38699 				duk_debug_write_int(thr, 1);  /* isAccessor */
38700 				duk_debug_write_heapptr(thr, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.get);
38701 				duk_debug_write_heapptr(thr, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.set);
38702 			} else {
38703 				duk_debug_write_int(thr, 0);  /* isAccessor */
38704 
38705 				duk__debug_write_tval_heapptr(thr, &DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->v);
38706 			}
38707 		}
38708 
38709 		for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(h); i++) {
38710 			/* Note: array dump will include elements beyond
38711 			 * 'length'.
38712 			 */
38713 			duk__debug_write_tval_heapptr(thr, DUK_HOBJECT_A_GET_VALUE_PTR(heap, h, i));
38714 		}
38715 		break;
38716 	}
38717 	case DUK_HTYPE_BUFFER: {
38718 		duk_hbuffer *h = (duk_hbuffer *) hdr;
38719 
38720 		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HBUFFER_GET_SIZE(h));
38721 		duk_debug_write_buffer(thr, (const char *) DUK_HBUFFER_GET_DATA_PTR(heap, h), (duk_size_t) DUK_HBUFFER_GET_SIZE(h));
38722 		break;
38723 	}
38724 	default: {
38725 		DUK_D(DUK_DPRINT("invalid htype: %d", (int) DUK_HEAPHDR_GET_TYPE(hdr)));
38726 	}
38727 	}
38728 }
38729 
38730 DUK_LOCAL void duk__debug_dump_heap_allocated(duk_hthread *thr, duk_heap *heap) {
38731 	duk_heaphdr *hdr;
38732 
38733 	hdr = heap->heap_allocated;
38734 	while (hdr != NULL) {
38735 		duk__debug_dump_heaphdr(thr, heap, hdr);
38736 		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
38737 	}
38738 }
38739 
38740 #if defined(DUK_USE_STRTAB_CHAIN)
38741 DUK_LOCAL void duk__debug_dump_strtab_chain(duk_hthread *thr, duk_heap *heap) {
38742 	duk_uint_fast32_t i, j;
38743 	duk_strtab_entry *e;
38744 #if defined(DUK_USE_HEAPPTR16)
38745 	duk_uint16_t *lst;
38746 #else
38747 	duk_hstring **lst;
38748 #endif
38749 	duk_hstring *h;
38750 
38751 	for (i = 0; i < DUK_STRTAB_CHAIN_SIZE; i++) {
38752 		e = heap->strtable + i;
38753 		if (e->listlen > 0) {
38754 #if defined(DUK_USE_HEAPPTR16)
38755 			lst = (duk_uint16_t *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, e->u.strlist16);
38756 #else
38757 			lst = e->u.strlist;
38758 #endif
38759 			DUK_ASSERT(lst != NULL);
38760 
38761 			for (j = 0; j < e->listlen; j++) {
38762 #if defined(DUK_USE_HEAPPTR16)
38763 				h = DUK_USE_HEAPPTR_DEC16(heap->heap_udata, lst[j]);
38764 #else
38765 				h = lst[j];
38766 #endif
38767 				if (h != NULL) {
38768 					duk__debug_dump_heaphdr(thr, heap, (duk_heaphdr *) h);
38769 				}
38770 			}
38771 		} else {
38772 #if defined(DUK_USE_HEAPPTR16)
38773 			h = DUK_USE_HEAPPTR_DEC16(heap->heap_udata, e->u.str16);
38774 #else
38775 			h = e->u.str;
38776 #endif
38777 			if (h != NULL) {
38778 				duk__debug_dump_heaphdr(thr, heap, (duk_heaphdr *) h);
38779 			}
38780 		}
38781 	}
38782 }
38783 #endif  /* DUK_USE_STRTAB_CHAIN */
38784 
38785 #if defined(DUK_USE_STRTAB_PROBE)
38786 DUK_LOCAL void duk__debug_dump_strtab_probe(duk_hthread *thr, duk_heap *heap) {
38787 	duk_uint32_t i;
38788 	duk_hstring *h;
38789 
38790 	for (i = 0; i < heap->st_size; i++) {
38791 #if defined(DUK_USE_HEAPPTR16)
38792 		h = DUK_USE_HEAPPTR_DEC16(heap->heap_udata, heap->strtable16[i]);
38793 #else
38794 		h = heap->strtable[i];
38795 #endif
38796 		if (h == NULL || h == DUK_STRTAB_DELETED_MARKER(heap)) {
38797 			continue;
38798 		}
38799 
38800 		duk__debug_dump_heaphdr(thr, heap, (duk_heaphdr *) h);
38801 	}
38802 }
38803 #endif  /* DUK_USE_STRTAB_PROBE */
38804 
38805 DUK_LOCAL void duk__debug_handle_dump_heap(duk_hthread *thr, duk_heap *heap) {
38806 	DUK_D(DUK_DPRINT("debug command DumpHeap"));
38807 
38808 	duk_debug_write_reply(thr);
38809 	duk__debug_dump_heap_allocated(thr, heap);
38810 #if defined(DUK_USE_STRTAB_CHAIN)
38811 	duk__debug_dump_strtab_chain(thr, heap);
38812 #endif
38813 #if defined(DUK_USE_STRTAB_PROBE)
38814 	duk__debug_dump_strtab_probe(thr, heap);
38815 #endif
38816 	duk_debug_write_eom(thr);
38817 }
38818 #endif  /* DUK_USE_DEBUGGER_DUMPHEAP */
38819 
38820 DUK_LOCAL void duk__debug_handle_get_bytecode(duk_hthread *thr, duk_heap *heap) {
38821 	duk_activation *act;
38822 	duk_hcompiledfunction *fun = NULL;
38823 	duk_size_t i, n;
38824 	duk_tval *tv;
38825 	duk_hobject **fn;
38826 	duk_int32_t level = -1;
38827 	duk_uint8_t ibyte;
38828 
38829 	DUK_UNREF(heap);
38830 
38831 	DUK_D(DUK_DPRINT("debug command GetBytecode"));
38832 
38833 	ibyte = duk_debug_peek_byte(thr);
38834 	if (ibyte != DUK_DBG_IB_EOM) {
38835 		tv = duk_debug_read_tval(thr);
38836 		if (tv == NULL) {
38837 			/* detached */
38838 			return;
38839 		}
38840 		if (DUK_TVAL_IS_OBJECT(tv)) {
38841 			/* tentative, checked later */
38842 			fun = (duk_hcompiledfunction *) DUK_TVAL_GET_OBJECT(tv);
38843 			DUK_ASSERT(fun != NULL);
38844 		} else if (DUK_TVAL_IS_NUMBER(tv)) {
38845 			level = (duk_int32_t) DUK_TVAL_GET_NUMBER(tv);
38846 		} else {
38847 			DUK_D(DUK_DPRINT("invalid argument to GetBytecode: %!T", tv));
38848 			goto fail_args;
38849 		}
38850 	}
38851 
38852 	if (fun == NULL) {
38853 		if (level >= 0 || -level > (duk_int32_t) thr->callstack_top) {
38854 			DUK_D(DUK_DPRINT("invalid callstack level for GetBytecode"));
38855 			goto fail_level;
38856 		}
38857 		act = thr->callstack + thr->callstack_top + level;
38858 		fun = (duk_hcompiledfunction *) DUK_ACT_GET_FUNC(act);
38859 	}
38860 
38861 	if (fun == NULL || !DUK_HOBJECT_IS_COMPILEDFUNCTION((duk_hobject *) fun)) {
38862 		DUK_D(DUK_DPRINT("invalid argument to GetBytecode: %!O", fun));
38863 		goto fail_args;
38864 	}
38865 	DUK_ASSERT(fun != NULL && DUK_HOBJECT_IS_COMPILEDFUNCTION((duk_hobject *) fun));
38866 
38867 	duk_debug_write_reply(thr);
38868 	n = DUK_HCOMPILEDFUNCTION_GET_CONSTS_COUNT(heap, fun);
38869 	duk_debug_write_int(thr, (duk_int32_t) n);
38870 	tv = DUK_HCOMPILEDFUNCTION_GET_CONSTS_BASE(heap, fun);
38871 	for (i = 0; i < n; i++) {
38872 		duk_debug_write_tval(thr, tv);
38873 		tv++;
38874 	}
38875 	n = DUK_HCOMPILEDFUNCTION_GET_FUNCS_COUNT(heap, fun);
38876 	duk_debug_write_int(thr, (duk_int32_t) n);
38877 	fn = DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE(heap, fun);
38878 	for (i = 0; i < n; i++) {
38879 		duk_debug_write_hobject(thr, *fn);
38880 		fn++;
38881 	}
38882 	duk_debug_write_string(thr,
38883 	                       (const char *) DUK_HCOMPILEDFUNCTION_GET_CODE_BASE(heap, fun),
38884 	                       (duk_size_t) DUK_HCOMPILEDFUNCTION_GET_CODE_SIZE(heap, fun));
38885 	duk_debug_write_eom(thr);
38886 	return;
38887 
38888  fail_args:
38889 	duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid argument");
38890 	return;
38891 
38892  fail_level:
38893 	duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid callstack level");
38894 	return;
38895 }
38896 
38897 /*
38898  *  Object inspection commands: GetHeapObjInfo, GetObjPropDesc,
38899  *  GetObjPropDescRange
38900  */
38901 
38902 #if defined(DUK_USE_DEBUGGER_INSPECT)
38903 
38904 #if 0 /* pruned */
38905 DUK_LOCAL const char * const duk__debug_getinfo_heaphdr_keys[] = {
38906 	"reachable",
38907 	"temproot",
38908 	"finalizable",
38909 	"finalized",
38910 	"readonly"
38911 	/* NULL not needed here */
38912 };
38913 DUK_LOCAL duk_uint_t duk__debug_getinfo_heaphdr_masks[] = {
38914 	DUK_HEAPHDR_FLAG_REACHABLE,
38915 	DUK_HEAPHDR_FLAG_TEMPROOT,
38916 	DUK_HEAPHDR_FLAG_FINALIZABLE,
38917 	DUK_HEAPHDR_FLAG_FINALIZED,
38918 	DUK_HEAPHDR_FLAG_READONLY,
38919 	0  /* terminator */
38920 };
38921 #endif
38922 DUK_LOCAL const char * const duk__debug_getinfo_hstring_keys[] = {
38923 #if 0
38924 	"arridx",
38925 	"internal",
38926 	"reserved_word",
38927 	"strict_reserved_word",
38928 	"eval_or_arguments",
38929 #endif
38930 	"extdata"
38931 	/* NULL not needed here */
38932 };
38933 DUK_LOCAL duk_uint_t duk__debug_getinfo_hstring_masks[] = {
38934 #if 0
38935 	DUK_HSTRING_FLAG_ARRIDX,
38936 	DUK_HSTRING_FLAG_INTERNAL,
38937 	DUK_HSTRING_FLAG_RESERVED_WORD,
38938 	DUK_HSTRING_FLAG_STRICT_RESERVED_WORD,
38939 	DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS,
38940 #endif
38941 	DUK_HSTRING_FLAG_EXTDATA,
38942 	0  /* terminator */
38943 };
38944 DUK_LOCAL const char * const duk__debug_getinfo_hobject_keys[] = {
38945 	"extensible",
38946 	"constructable",
38947 	"bound",
38948 	"compiledfunction",
38949 	"nativefunction",
38950 	"bufferobject",
38951 	"thread",
38952 	"array_part",
38953 	"strict",
38954 	"notail",
38955 	"newenv",
38956 	"namebinding",
38957 	"createargs",
38958 	"envrecclosed",
38959 	"exotic_array",
38960 	"exotic_stringobj",
38961 	"exotic_arguments",
38962 	"exotic_dukfunc",
38963 	"exotic_proxyobj"
38964 	/* NULL not needed here */
38965 };
38966 DUK_LOCAL duk_uint_t duk__debug_getinfo_hobject_masks[] = {
38967 	DUK_HOBJECT_FLAG_EXTENSIBLE,
38968 	DUK_HOBJECT_FLAG_CONSTRUCTABLE,
38969 	DUK_HOBJECT_FLAG_BOUND,
38970 	DUK_HOBJECT_FLAG_COMPILEDFUNCTION,
38971 	DUK_HOBJECT_FLAG_NATIVEFUNCTION,
38972 	DUK_HOBJECT_FLAG_BUFFEROBJECT,
38973 	DUK_HOBJECT_FLAG_THREAD,
38974 	DUK_HOBJECT_FLAG_ARRAY_PART,
38975 	DUK_HOBJECT_FLAG_STRICT,
38976 	DUK_HOBJECT_FLAG_NOTAIL,
38977 	DUK_HOBJECT_FLAG_NEWENV,
38978 	DUK_HOBJECT_FLAG_NAMEBINDING,
38979 	DUK_HOBJECT_FLAG_CREATEARGS,
38980 	DUK_HOBJECT_FLAG_ENVRECCLOSED,
38981 	DUK_HOBJECT_FLAG_EXOTIC_ARRAY,
38982 	DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ,
38983 	DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS,
38984 	DUK_HOBJECT_FLAG_EXOTIC_DUKFUNC,
38985 	DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ,
38986 	0  /* terminator */
38987 };
38988 DUK_LOCAL const char * const duk__debug_getinfo_hbuffer_keys[] = {
38989 	"dynamic",
38990 	"external"
38991 	/* NULL not needed here */
38992 };
38993 DUK_LOCAL duk_uint_t duk__debug_getinfo_hbuffer_masks[] = {
38994 	DUK_HBUFFER_FLAG_DYNAMIC,
38995 	DUK_HBUFFER_FLAG_EXTERNAL,
38996 	0  /* terminator */
38997 };
38998 
38999 DUK_LOCAL void duk__debug_getinfo_flags_key(duk_hthread *thr, const char *key) {
39000 	duk_debug_write_uint(thr, 0);
39001 	duk_debug_write_cstring(thr, key);
39002 }
39003 
39004 DUK_LOCAL void duk__debug_getinfo_prop_uint(duk_hthread *thr, const char *key, duk_uint_t val) {
39005 	duk_debug_write_uint(thr, 0);
39006 	duk_debug_write_cstring(thr, key);
39007 	duk_debug_write_uint(thr, val);
39008 }
39009 
39010 DUK_LOCAL void duk__debug_getinfo_prop_int(duk_hthread *thr, const char *key, duk_int_t val) {
39011 	duk_debug_write_uint(thr, 0);
39012 	duk_debug_write_cstring(thr, key);
39013 	duk_debug_write_int(thr, val);
39014 }
39015 
39016 DUK_LOCAL void duk__debug_getinfo_prop_bool(duk_hthread *thr, const char *key, duk_bool_t val) {
39017 	duk_debug_write_uint(thr, 0);
39018 	duk_debug_write_cstring(thr, key);
39019 	duk_debug_write_boolean(thr, val);
39020 }
39021 
39022 DUK_LOCAL void duk__debug_getinfo_bitmask(duk_hthread *thr, const char * const * keys, duk_uint_t *masks, duk_uint_t flags) {
39023 	const char *key;
39024 	duk_uint_t mask;
39025 
39026 	for (;;) {
39027 		mask = *masks++;
39028 		if (!mask) {
39029 			break;
39030 		}
39031 		key = *keys++;
39032 		DUK_ASSERT(key != NULL);
39033 
39034 		DUK_DD(DUK_DDPRINT("inspect bitmask: key=%s, mask=0x%08lx, flags=0x%08lx", key, (unsigned long) mask, (unsigned long) flags));
39035 		duk__debug_getinfo_prop_bool(thr, key, flags & mask);
39036 	}
39037 }
39038 
39039 /* Inspect a property using a virtual index into a conceptual property list
39040  * consisting of (1) all array part items from [0,a_size[ (even when above
39041  * .length) and (2) all entry part items from [0,e_next[.  Unused slots are
39042  * indicated using dvalue 'unused'.
39043  */
39044 DUK_LOCAL duk_bool_t duk__debug_getprop_index(duk_hthread *thr, duk_heap *heap, duk_hobject *h_obj, duk_uint_t idx) {
39045 	duk_uint_t a_size;
39046 	duk_tval *tv;
39047 	duk_hstring *h_key;
39048 	duk_hobject *h_getset;
39049 	duk_uint_t flags;
39050 
39051 	DUK_UNREF(heap);
39052 
39053 	a_size = DUK_HOBJECT_GET_ASIZE(h_obj);
39054 	if (idx < a_size) {
39055 		duk_debug_write_uint(thr, DUK_PROPDESC_FLAGS_WEC);
39056 		duk_debug_write_uint(thr, idx);
39057 		tv = DUK_HOBJECT_A_GET_VALUE_PTR(heap, h_obj, idx);
39058 		duk_debug_write_tval(thr, tv);
39059 		return 1;
39060 	}
39061 
39062 	idx -= a_size;
39063 	if (idx >= DUK_HOBJECT_GET_ENEXT(h_obj)) {
39064 		return 0;
39065 	}
39066 
39067 	h_key = DUK_HOBJECT_E_GET_KEY(heap, h_obj, idx);
39068 	if (h_key == NULL) {
39069 		duk_debug_write_uint(thr, 0);
39070 		duk_debug_write_null(thr);
39071 		duk_debug_write_unused(thr);
39072 		return 1;
39073 	}
39074 
39075 	flags = DUK_HOBJECT_E_GET_FLAGS(heap, h_obj, idx);
39076 	if (DUK_HSTRING_HAS_INTERNAL(h_key)) {
39077 		flags |= DUK_DBG_PROPFLAG_INTERNAL;
39078 	}
39079 	duk_debug_write_uint(thr, flags);
39080 	duk_debug_write_hstring(thr, h_key);
39081 	if (flags & DUK_PROPDESC_FLAG_ACCESSOR) {
39082 		h_getset = DUK_HOBJECT_E_GET_VALUE_GETTER(heap, h_obj, idx);
39083 		if (h_getset) {
39084 			duk_debug_write_hobject(thr, h_getset);
39085 		} else {
39086 			duk_debug_write_null(thr);
39087 		}
39088 		h_getset = DUK_HOBJECT_E_GET_VALUE_SETTER(heap, h_obj, idx);
39089 		if (h_getset) {
39090 			duk_debug_write_hobject(thr, h_getset);
39091 		} else {
39092 			duk_debug_write_null(thr);
39093 		}
39094 	} else {
39095 		tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap, h_obj, idx);
39096 		duk_debug_write_tval(thr, tv);
39097 	}
39098 	return 1;
39099 }
39100 
39101 DUK_LOCAL void duk__debug_handle_get_heap_obj_info(duk_hthread *thr, duk_heap *heap) {
39102 	duk_heaphdr *h;
39103 
39104 	DUK_D(DUK_DPRINT("debug command GetHeapObjInfo"));
39105 	DUK_UNREF(heap);
39106 
39107 	h = duk_debug_read_any_ptr(thr);
39108 	if (!h) {
39109 		duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid target");
39110 		return;
39111 	}
39112 
39113 	duk_debug_write_reply(thr);
39114 
39115 	/* As with all inspection code, we rely on the debug client providing
39116 	 * a valid, non-stale pointer: there's no portable way to safely
39117 	 * validate the pointer here.
39118 	 */
39119 
39120 	duk__debug_getinfo_flags_key(thr, "heapptr");
39121 	duk_debug_write_heapptr(thr, h);
39122 
39123 	/* XXX: comes out as signed now */
39124 	duk__debug_getinfo_prop_uint(thr, "heaphdr_flags", (duk_uint_t) DUK_HEAPHDR_GET_FLAGS(h));
39125 	duk__debug_getinfo_prop_uint(thr, "heaphdr_type", (duk_uint_t) DUK_HEAPHDR_GET_TYPE(h));
39126 #if defined(DUK_USE_REFERENCE_COUNTING)
39127 	duk__debug_getinfo_prop_uint(thr, "refcount", (duk_uint_t) DUK_HEAPHDR_GET_REFCOUNT(h));
39128 #endif
39129 #if 0 /* pruned */
39130 	duk__debug_getinfo_bitmask(thr,
39131 	                           duk__debug_getinfo_heaphdr_keys,
39132 	                           duk__debug_getinfo_heaphdr_masks,
39133 	                           DUK_HEAPHDR_GET_FLAGS_RAW(h));
39134 #endif
39135 
39136 	switch (DUK_HEAPHDR_GET_TYPE(h)) {
39137 	case DUK_HTYPE_STRING: {
39138 		duk_hstring *h_str;
39139 
39140 		h_str = (duk_hstring *) h;
39141 		duk__debug_getinfo_bitmask(thr,
39142 		                           duk__debug_getinfo_hstring_keys,
39143 		                           duk__debug_getinfo_hstring_masks,
39144 		                           DUK_HEAPHDR_GET_FLAGS_RAW(h));
39145 		duk__debug_getinfo_prop_uint(thr, "bytelen", DUK_HSTRING_GET_BYTELEN(h_str));
39146 		duk__debug_getinfo_prop_uint(thr, "charlen", DUK_HSTRING_GET_CHARLEN(h_str));
39147 		duk__debug_getinfo_prop_uint(thr, "hash", DUK_HSTRING_GET_HASH(h_str));
39148 		duk__debug_getinfo_flags_key(thr, "data");
39149 		duk_debug_write_hstring(thr, h_str);
39150 		break;
39151 	}
39152 	case DUK_HTYPE_OBJECT: {
39153 		duk_hobject *h_obj;
39154 		duk_hobject *h_proto;
39155 
39156 		h_obj = (duk_hobject *) h;
39157 		h_proto = DUK_HOBJECT_GET_PROTOTYPE(heap, h_obj);
39158 
39159 		/* duk_hobject specific fields. */
39160 		duk__debug_getinfo_bitmask(thr,
39161 		                           duk__debug_getinfo_hobject_keys,
39162 		                           duk__debug_getinfo_hobject_masks,
39163 		                           DUK_HEAPHDR_GET_FLAGS_RAW(h));
39164 		duk__debug_getinfo_prop_uint(thr, "class_number", DUK_HOBJECT_GET_CLASS_NUMBER(h_obj));
39165 		duk__debug_getinfo_flags_key(thr, "class_name");
39166 		duk_debug_write_hstring(thr, DUK_HOBJECT_GET_CLASS_STRING(heap, h_obj));
39167 		duk__debug_getinfo_flags_key(thr, "prototype");
39168 		if (h_proto != NULL) {
39169 			duk_debug_write_hobject(thr, h_proto);
39170 		} else {
39171 			duk_debug_write_null(thr);
39172 		}
39173 		duk__debug_getinfo_flags_key(thr, "props");
39174 		duk_debug_write_pointer(thr, (void *) DUK_HOBJECT_GET_PROPS(heap, h_obj));
39175 		duk__debug_getinfo_prop_uint(thr, "e_size", (duk_uint_t) DUK_HOBJECT_GET_ESIZE(h_obj));
39176 		duk__debug_getinfo_prop_uint(thr, "e_next", (duk_uint_t) DUK_HOBJECT_GET_ENEXT(h_obj));
39177 		duk__debug_getinfo_prop_uint(thr, "a_size", (duk_uint_t) DUK_HOBJECT_GET_ASIZE(h_obj));
39178 		duk__debug_getinfo_prop_uint(thr, "h_size", (duk_uint_t) DUK_HOBJECT_GET_HSIZE(h_obj));
39179 
39180 		/* duk_hnativefunction specific fields. */
39181 		if (DUK_HOBJECT_IS_NATIVEFUNCTION(h_obj)) {
39182 			duk_hnativefunction *h_fun;
39183 			h_fun = (duk_hnativefunction *) h_obj;
39184 
39185 			duk__debug_getinfo_prop_int(thr, "nargs", h_fun->nargs);
39186 			duk__debug_getinfo_prop_int(thr, "magic", h_fun->magic);
39187 			duk__debug_getinfo_prop_bool(thr, "varargs", h_fun->magic == DUK_HNATIVEFUNCTION_NARGS_VARARGS);
39188 			/* Native function pointer may be different from a void pointer,
39189 			 * and we serialize it from memory directly now (no byte swapping etc).
39190 			 */
39191 			duk__debug_getinfo_flags_key(thr, "funcptr");
39192 			duk_debug_write_buffer(thr, (const char *) &h_fun->func, sizeof(h_fun->func));
39193 		}
39194 
39195 		if (DUK_HOBJECT_IS_COMPILEDFUNCTION(h_obj)) {
39196 			duk_hcompiledfunction *h_fun;
39197 			duk_hbuffer *h_buf;
39198 			h_fun = (duk_hcompiledfunction *) h_obj;
39199 
39200 			duk__debug_getinfo_prop_int(thr, "nregs", h_fun->nregs);
39201 			duk__debug_getinfo_prop_int(thr, "nargs", h_fun->nargs);
39202 			duk__debug_getinfo_prop_uint(thr, "start_line", h_fun->start_line);
39203 			duk__debug_getinfo_prop_uint(thr, "end_line", h_fun->end_line);
39204 			h_buf = (duk_hbuffer *) DUK_HCOMPILEDFUNCTION_GET_DATA(thr->heap, h_fun);
39205 			if (h_buf != NULL) {
39206 				duk__debug_getinfo_flags_key(thr, "data");
39207 				duk_debug_write_heapptr(thr, (duk_heaphdr *) h_buf);
39208 			}
39209 		}
39210 
39211 		if (DUK_HOBJECT_IS_THREAD(h_obj)) {
39212 			/* XXX: Currently no inspection of threads, e.g. value stack, call
39213 			 * stack, catch stack, etc.
39214 			 */
39215 			duk_hthread *h_thr;
39216 			h_thr = (duk_hthread *) h_obj;
39217 			DUK_UNREF(h_thr);
39218 		}
39219 
39220 		if (DUK_HOBJECT_IS_BUFFEROBJECT(h_obj)) {
39221 			duk_hbufferobject *h_bufobj;
39222 			h_bufobj = (duk_hbufferobject *) h_obj;
39223 
39224 			duk__debug_getinfo_prop_uint(thr, "slice_offset", h_bufobj->offset);
39225 			duk__debug_getinfo_prop_uint(thr, "slice_length", h_bufobj->length);
39226 			duk__debug_getinfo_prop_uint(thr, "elem_shift", (duk_uint_t) h_bufobj->shift);
39227 			duk__debug_getinfo_prop_uint(thr, "elem_type", (duk_uint_t) h_bufobj->elem_type);
39228 			duk__debug_getinfo_prop_bool(thr, "is_view", (duk_uint_t) h_bufobj->is_view);
39229 			if (h_bufobj->buf != NULL) {
39230 				duk__debug_getinfo_flags_key(thr, "buffer");
39231 				duk_debug_write_heapptr(thr, (duk_heaphdr *) h_bufobj->buf);
39232 			}
39233 		}
39234 		break;
39235 	}
39236 	case DUK_HTYPE_BUFFER: {
39237 		duk_hbuffer *h_buf;
39238 
39239 		h_buf = (duk_hbuffer *) h;
39240 		duk__debug_getinfo_bitmask(thr,
39241 		                           duk__debug_getinfo_hbuffer_keys,
39242 		                           duk__debug_getinfo_hbuffer_masks,
39243 		                           DUK_HEAPHDR_GET_FLAGS_RAW(h));
39244 		duk__debug_getinfo_prop_uint(thr, "size", (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_buf));
39245 		duk__debug_getinfo_flags_key(thr, "dataptr");
39246 		duk_debug_write_pointer(thr, (void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_buf));
39247 		duk__debug_getinfo_flags_key(thr, "data");
39248 		duk_debug_write_hbuffer(thr, h_buf);  /* tolerates NULL h_buf */
39249 		break;
39250 	}
39251 	default: {
39252 		/* Since we already started writing the reply, just emit nothing. */
39253 		DUK_D(DUK_DPRINT("inspect target pointer has invalid heaphdr type"));
39254 	}
39255 	}
39256 
39257 	duk_debug_write_eom(thr);
39258 }
39259 
39260 DUK_LOCAL void duk__debug_handle_get_obj_prop_desc(duk_hthread *thr, duk_heap *heap) {
39261 	duk_heaphdr *h;
39262 	duk_hobject *h_obj;
39263 	duk_hstring *h_key;
39264 	duk_propdesc desc;
39265 
39266 	DUK_D(DUK_DPRINT("debug command GetObjPropDesc"));
39267 	DUK_UNREF(heap);
39268 
39269 	h = duk_debug_read_any_ptr(thr);
39270 	if (!h) {
39271 		duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid target");
39272 		return;
39273 	}
39274 	h_key = duk_debug_read_hstring(thr);
39275 	if (h == NULL || DUK_HEAPHDR_GET_TYPE(h) != DUK_HTYPE_OBJECT || h_key == NULL) {
39276 		goto fail_args;
39277 	}
39278 	h_obj = (duk_hobject *) h;
39279 
39280 	if (duk_hobject_get_own_propdesc(thr, h_obj, h_key, &desc, 0 /*flags*/)) {
39281 		duk_int_t virtual_idx;
39282 		duk_bool_t rc;
39283 
39284 		/* To use the shared helper need the virtual index. */
39285 		DUK_ASSERT(desc.e_idx >= 0 || desc.a_idx >= 0);
39286 		virtual_idx = (desc.a_idx >= 0 ? desc.a_idx :
39287 		               (duk_int_t) DUK_HOBJECT_GET_ASIZE(h_obj) + desc.e_idx);
39288 
39289 		duk_debug_write_reply(thr);
39290 		rc = duk__debug_getprop_index(thr, heap, h_obj, (duk_uint_t) virtual_idx);
39291 		DUK_ASSERT(rc == 1);
39292 		DUK_UNREF(rc);
39293 		duk_debug_write_eom(thr);
39294 	} else {
39295 		duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "not found");
39296 	}
39297 	return;
39298 
39299  fail_args:
39300 	duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid args");
39301 }
39302 
39303 DUK_LOCAL void duk__debug_handle_get_obj_prop_desc_range(duk_hthread *thr, duk_heap *heap) {
39304 	duk_heaphdr *h;
39305 	duk_hobject *h_obj;
39306 	duk_uint_t idx, idx_start, idx_end;
39307 
39308 	DUK_D(DUK_DPRINT("debug command GetObjPropDescRange"));
39309 	DUK_UNREF(heap);
39310 
39311 	h = duk_debug_read_any_ptr(thr);
39312 	idx_start = duk_debug_read_int(thr);
39313 	idx_end = duk_debug_read_int(thr);
39314 	if (h == NULL || DUK_HEAPHDR_GET_TYPE(h) != DUK_HTYPE_OBJECT) {
39315 		goto fail_args;
39316 	}
39317 	h_obj = (duk_hobject *) h;
39318 
39319 	/* The index range space is conceptually the array part followed by the
39320 	 * entry part.  Unlike normal enumeration all slots are exposed here as
39321 	 * is and return 'unused' if the slots are not in active use.  In particular
39322 	 * the array part is included for the full a_size regardless of what the
39323 	 * array .length is.
39324 	 */
39325 
39326 	duk_debug_write_reply(thr);
39327 	for (idx = idx_start; idx < idx_end; idx++) {
39328 		if (!duk__debug_getprop_index(thr, heap, h_obj, idx)) {
39329 			break;
39330 		}
39331 	}
39332 	duk_debug_write_eom(thr);
39333 	return;
39334 
39335  fail_args:
39336 	duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid args");
39337 }
39338 
39339 #endif  /* DUK_USE_DEBUGGER_INSPECT */
39340 
39341 /*
39342  *  Process incoming debug requests
39343  *
39344  *  Individual request handlers can push temporaries on the value stack and
39345  *  rely on duk__debug_process_message() to restore the value stack top
39346  *  automatically.
39347  */
39348 
39349 /* Process one debug message.  Automatically restore value stack top to its
39350  * entry value, so that individual message handlers don't need exact value
39351  * stack handling which is convenient.
39352  */
39353 DUK_LOCAL void duk__debug_process_message(duk_hthread *thr) {
39354 	duk_context *ctx = (duk_context *) thr;
39355 	duk_heap *heap;
39356 	duk_uint8_t x;
39357 	duk_int32_t cmd;
39358 	duk_idx_t entry_top;
39359 
39360 	DUK_ASSERT(thr != NULL);
39361 	heap = thr->heap;
39362 	DUK_ASSERT(heap != NULL);
39363 	DUK_UNREF(ctx);
39364 
39365 	entry_top = duk_get_top(ctx);
39366 
39367 	x = duk_debug_read_byte(thr);
39368 	switch (x) {
39369 	case DUK_DBG_IB_REQUEST: {
39370 		cmd = duk_debug_read_int(thr);
39371 		switch (cmd) {
39372 		case DUK_DBG_CMD_BASICINFO: {
39373 			duk__debug_handle_basic_info(thr, heap);
39374 			break;
39375 		}
39376 		case DUK_DBG_CMD_TRIGGERSTATUS: {
39377 			duk__debug_handle_trigger_status(thr, heap);
39378 			break;
39379 		}
39380 		case DUK_DBG_CMD_PAUSE: {
39381 			duk__debug_handle_pause(thr, heap);
39382 			break;
39383 		}
39384 		case DUK_DBG_CMD_RESUME: {
39385 			duk__debug_handle_resume(thr, heap);
39386 			break;
39387 		}
39388 		case DUK_DBG_CMD_STEPINTO:
39389 		case DUK_DBG_CMD_STEPOVER:
39390 		case DUK_DBG_CMD_STEPOUT: {
39391 			duk__debug_handle_step(thr, heap, cmd);
39392 			break;
39393 		}
39394 		case DUK_DBG_CMD_LISTBREAK: {
39395 			duk__debug_handle_list_break(thr, heap);
39396 			break;
39397 		}
39398 		case DUK_DBG_CMD_ADDBREAK: {
39399 			duk__debug_handle_add_break(thr, heap);
39400 			break;
39401 		}
39402 		case DUK_DBG_CMD_DELBREAK: {
39403 			duk__debug_handle_del_break(thr, heap);
39404 			break;
39405 		}
39406 		case DUK_DBG_CMD_GETVAR: {
39407 			duk__debug_handle_get_var(thr, heap);
39408 			break;
39409 		}
39410 		case DUK_DBG_CMD_PUTVAR: {
39411 			duk__debug_handle_put_var(thr, heap);
39412 			break;
39413 		}
39414 		case DUK_DBG_CMD_GETCALLSTACK: {
39415 			duk__debug_handle_get_call_stack(thr, heap);
39416 			break;
39417 		}
39418 		case DUK_DBG_CMD_GETLOCALS: {
39419 			duk__debug_handle_get_locals(thr, heap);
39420 			break;
39421 		}
39422 		case DUK_DBG_CMD_EVAL: {
39423 			duk__debug_handle_eval(thr, heap);
39424 			break;
39425 		}
39426 		case DUK_DBG_CMD_DETACH: {
39427 			/* The actual detached_cb call is postponed to message loop so
39428 			 * we don't need any special precautions here (just skip to EOM
39429 			 * on the already closed connection).
39430 			 */
39431 			duk__debug_handle_detach(thr, heap);
39432 			break;
39433 		}
39434 #if defined(DUK_USE_DEBUGGER_DUMPHEAP)
39435 		case DUK_DBG_CMD_DUMPHEAP: {
39436 			duk__debug_handle_dump_heap(thr, heap);
39437 			break;
39438 		}
39439 #endif  /* DUK_USE_DEBUGGER_DUMPHEAP */
39440 		case DUK_DBG_CMD_GETBYTECODE: {
39441 			duk__debug_handle_get_bytecode(thr, heap);
39442 			break;
39443 		}
39444 		case DUK_DBG_CMD_APPREQUEST: {
39445 			duk__debug_handle_apprequest(thr, heap);
39446 			break;
39447 		}
39448 #if defined(DUK_USE_DEBUGGER_INSPECT)
39449 		case DUK_DBG_CMD_GETHEAPOBJINFO: {
39450 			duk__debug_handle_get_heap_obj_info(thr, heap);
39451 			break;
39452 		}
39453 		case DUK_DBG_CMD_GETOBJPROPDESC: {
39454 			duk__debug_handle_get_obj_prop_desc(thr, heap);
39455 			break;
39456 		}
39457 		case DUK_DBG_CMD_GETOBJPROPDESCRANGE: {
39458 			duk__debug_handle_get_obj_prop_desc_range(thr, heap);
39459 			break;
39460 		}
39461 #endif  /* DUK_USE_DEBUGGER_INSPECT */
39462 		default: {
39463 			DUK_D(DUK_DPRINT("debug command unsupported: %d", (int) cmd));
39464 			duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNSUPPORTED, "unsupported command");
39465 		}
39466 		}  /* switch cmd */
39467 		break;
39468 	}
39469 	case DUK_DBG_IB_REPLY: {
39470 		DUK_D(DUK_DPRINT("debug reply, skipping"));
39471 		break;
39472 	}
39473 	case DUK_DBG_IB_ERROR: {
39474 		DUK_D(DUK_DPRINT("debug error, skipping"));
39475 		break;
39476 	}
39477 	case DUK_DBG_IB_NOTIFY: {
39478 		DUK_D(DUK_DPRINT("debug notify, skipping"));
39479 		break;
39480 	}
39481 	default: {
39482 		DUK_D(DUK_DPRINT("invalid initial byte, drop connection: %d", (int) x));
39483 		goto fail;
39484 	}
39485 	}  /* switch initial byte */
39486 
39487 	DUK_ASSERT(duk_get_top(ctx) >= entry_top);
39488 	duk_set_top(ctx, entry_top);
39489 	duk__debug_skip_to_eom(thr);
39490 	return;
39491 
39492  fail:
39493 	DUK_ASSERT(duk_get_top(ctx) >= entry_top);
39494 	duk_set_top(ctx, entry_top);
39495 	DUK__SET_CONN_BROKEN(thr, 1);
39496 	return;
39497 }
39498 
39499 DUK_LOCAL void duk__check_resend_status(duk_hthread *thr) {
39500 	if (thr->heap->dbg_read_cb != NULL && thr->heap->dbg_state_dirty) {
39501 		duk_debug_send_status(thr);
39502 		thr->heap->dbg_state_dirty = 0;
39503 	}
39504 }
39505 
39506 DUK_INTERNAL duk_bool_t duk_debug_process_messages(duk_hthread *thr, duk_bool_t no_block) {
39507 	duk_context *ctx = (duk_context *) thr;
39508 #if defined(DUK_USE_ASSERTIONS)
39509 	duk_idx_t entry_top;
39510 #endif
39511 	duk_bool_t retval = 0;
39512 
39513 	DUK_ASSERT(thr != NULL);
39514 	DUK_UNREF(ctx);
39515 	DUK_ASSERT(thr->heap != NULL);
39516 #if defined(DUK_USE_ASSERTIONS)
39517 	entry_top = duk_get_top(ctx);
39518 #endif
39519 
39520 	DUK_D(DUK_DPRINT("process debug messages: read_cb=%s, no_block=%ld, detaching=%ld, processing=%ld",
39521 	                 thr->heap->dbg_read_cb ? "not NULL" : "NULL", (long) no_block,
39522 	                 (long) thr->heap->dbg_detaching, (long) thr->heap->dbg_processing));
39523 	DUK_DD(DUK_DDPRINT("top at entry: %ld", (long) duk_get_top(ctx)));
39524 
39525 	/* thr->heap->dbg_detaching may be != 0 if a debugger write outside
39526 	 * the message loop caused a transport error and detach1() to run.
39527 	 */
39528 	DUK_ASSERT(thr->heap->dbg_detaching == 0 || thr->heap->dbg_detaching == 1);
39529 	DUK_ASSERT(thr->heap->dbg_processing == 0);
39530 	thr->heap->dbg_processing = 1;
39531 
39532 	/* Ensure dirty state causes a Status even if never process any
39533 	 * messages.  This is expected by the bytecode executor when in
39534 	 * the running state.
39535 	 */
39536 	duk__check_resend_status(thr);
39537 
39538 	for (;;) {
39539 		/* Process messages until we're no longer paused or we peek
39540 		 * and see there's nothing to read right now.
39541 		 */
39542 		DUK_DD(DUK_DDPRINT("top at loop top: %ld", (long) duk_get_top(ctx)));
39543 		DUK_ASSERT(thr->heap->dbg_processing == 1);
39544 
39545 		while (thr->heap->dbg_read_cb == NULL && thr->heap->dbg_detaching) {
39546 			/* Detach is pending; can be triggered from outside the
39547 			 * debugger loop (e.g. Status notify write error) or by
39548 			 * previous message handling.  Call detached callback
39549 			 * here, in a controlled state, to ensure a possible
39550 			 * reattach inside the detached_cb is handled correctly.
39551 			 *
39552 			 * Recheck for detach in a while loop: an immediate
39553 			 * reattach involves a call to duk_debugger_attach()
39554 			 * which writes a debugger handshake line immediately
39555 			 * inside the API call.  If the transport write fails
39556 			 * for that handshake, we can immediately end up in a
39557 			 * "transport broken, detaching" case several times here.
39558 			 * Loop back until we're either cleanly attached or
39559 			 * fully detached.
39560 			 *
39561 			 * NOTE: Reset dbg_processing = 1 forcibly, in case we
39562 			 * re-attached; duk_debugger_attach() sets dbg_processing
39563 			 * to 0 at the moment.
39564 			 */
39565 
39566 			DUK_D(DUK_DPRINT("detach pending (dbg_read_cb == NULL, dbg_detaching != 0), call detach2"));
39567 
39568 			duk__debug_do_detach2(thr->heap);
39569 			thr->heap->dbg_processing = 1;  /* may be set to 0 by duk_debugger_attach() inside callback */
39570 
39571 			DUK_D(DUK_DPRINT("after detach2 (and possible reattach): dbg_read_cb=%s, dbg_detaching=%ld",
39572 			                 thr->heap->dbg_read_cb ? "not NULL" : "NULL", (long) thr->heap->dbg_detaching));
39573 		}
39574 		DUK_ASSERT(thr->heap->dbg_detaching == 0);  /* true even with reattach */
39575 		DUK_ASSERT(thr->heap->dbg_processing == 1);  /* even after a detach and possible reattach */
39576 
39577 		if (thr->heap->dbg_read_cb == NULL) {
39578 			DUK_D(DUK_DPRINT("debug connection broken (and not detaching), stop processing messages"));
39579 			break;
39580 		}
39581 
39582 		if (!thr->heap->dbg_paused || no_block) {
39583 			if (!duk_debug_read_peek(thr)) {
39584 				/* Note: peek cannot currently trigger a detach
39585 				 * so the dbg_detaching == 0 assert outside the
39586 				 * loop is correct.
39587 				 */
39588 				DUK_D(DUK_DPRINT("processing debug message, peek indicated no data, stop processing messages"));
39589 				break;
39590 			}
39591 			DUK_D(DUK_DPRINT("processing debug message, peek indicated there is data, handle it"));
39592 		} else {
39593 			DUK_D(DUK_DPRINT("paused, process debug message, blocking if necessary"));
39594 		}
39595 
39596 		duk__check_resend_status(thr);
39597 		duk__debug_process_message(thr);
39598 		duk__check_resend_status(thr);
39599 
39600 		retval = 1;  /* processed one or more messages */
39601 	}
39602 
39603 	DUK_ASSERT(thr->heap->dbg_detaching == 0);
39604 	DUK_ASSERT(thr->heap->dbg_processing == 1);
39605 	thr->heap->dbg_processing = 0;
39606 
39607 	/* As an initial implementation, read flush after exiting the message
39608 	 * loop.  If transport is broken, this is a no-op (with debug logs).
39609 	 */
39610 	duk_debug_read_flush(thr);  /* this cannot initiate a detach */
39611 	DUK_ASSERT(thr->heap->dbg_detaching == 0);
39612 
39613 	DUK_DD(DUK_DDPRINT("top at exit: %ld", (long) duk_get_top(ctx)));
39614 
39615 #if defined(DUK_USE_ASSERTIONS)
39616 	/* Easy to get wrong, so assert for it. */
39617 	DUK_ASSERT(entry_top == duk_get_top(ctx));
39618 #endif
39619 
39620 	return retval;
39621 }
39622 
39623 /*
39624  *  Halt execution helper
39625  */
39626 
39627 /* Halt execution and enter a debugger message loop until execution is resumed
39628  * by the client.  PC for the current activation may be temporarily decremented
39629  * so that the "current" instruction will be shown by the client.  This helper
39630  * is callable from anywhere, also outside bytecode executor.
39631  */
39632 
39633 DUK_INTERNAL void duk_debug_halt_execution(duk_hthread *thr, duk_bool_t use_prev_pc) {
39634 	duk_activation *act;
39635 	duk_hcompiledfunction *fun;
39636 	duk_instr_t *old_pc = NULL;
39637 
39638 	DUK_ASSERT(thr != NULL);
39639 	DUK_ASSERT(thr->heap != NULL);
39640 	DUK_ASSERT(DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap));
39641 	DUK_ASSERT(thr->heap->dbg_processing == 0);
39642 
39643 	DUK_HEAP_SET_PAUSED(thr->heap);
39644 
39645 	act = duk_hthread_get_current_activation(thr);
39646 
39647 	/* NOTE: act may be NULL if an error is thrown outside of any activation,
39648 	 * which may happen in the case of, e.g. syntax errors.
39649 	 */
39650 
39651 	/* Decrement PC if that was requested, this requires a PC sync. */
39652 	if (act != NULL) {
39653 		duk_hthread_sync_currpc(thr);
39654 		old_pc = act->curr_pc;
39655 		fun = (duk_hcompiledfunction *) DUK_ACT_GET_FUNC(act);
39656 
39657 		/* Short circuit if is safe: if act->curr_pc != NULL, 'fun' is
39658 		 * guaranteed to be a non-NULL Ecmascript function.
39659 		 */
39660 		DUK_ASSERT(act->curr_pc == NULL ||
39661 		           (fun != NULL && DUK_HOBJECT_IS_COMPILEDFUNCTION((duk_hobject *) fun)));
39662 		if (use_prev_pc &&
39663 		    act->curr_pc != NULL &&
39664 		    act->curr_pc > DUK_HCOMPILEDFUNCTION_GET_CODE_BASE(thr->heap, fun)) {
39665 			act->curr_pc--;
39666 		}
39667 	}
39668 
39669 	/* Process debug messages until we are no longer paused. */
39670 
39671 	/* NOTE: This is a bit fragile.  It's important to ensure that
39672 	 * duk_debug_process_messages() never throws an error or
39673 	 * act->curr_pc will never be reset.
39674 	 */
39675 
39676 	thr->heap->dbg_state_dirty = 1;
39677 	while (thr->heap->dbg_paused) {
39678 		DUK_ASSERT(DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap));
39679 		DUK_ASSERT(thr->heap->dbg_processing);
39680 		duk_debug_process_messages(thr, 0 /*no_block*/);
39681 	}
39682 
39683 	/* XXX: Decrementing and restoring act->curr_pc works now, but if the
39684 	 * debugger message loop gains the ability to adjust the current PC
39685 	 * (e.g. a forced jump) restoring the PC here will break.  Another
39686 	 * approach would be to use a state flag for the "decrement 1 from
39687 	 * topmost activation's PC" and take it into account whenever dealing
39688 	 * with PC values.
39689 	 */
39690 	if (act != NULL) {
39691 		act->curr_pc = old_pc;  /* restore PC */
39692 	}
39693 }
39694 
39695 /*
39696  *  Breakpoint management
39697  */
39698 
39699 DUK_INTERNAL duk_small_int_t duk_debug_add_breakpoint(duk_hthread *thr, duk_hstring *filename, duk_uint32_t line) {
39700 	duk_heap *heap;
39701 	duk_breakpoint *b;
39702 
39703 	/* Caller must trigger recomputation of active breakpoint list.  To
39704 	 * ensure stale values are not used if that doesn't happen, clear the
39705 	 * active breakpoint list here.
39706 	 */
39707 
39708 	DUK_ASSERT(thr != NULL);
39709 	DUK_ASSERT(filename != NULL);
39710 	heap = thr->heap;
39711 	DUK_ASSERT(heap != NULL);
39712 
39713 	if (heap->dbg_breakpoint_count >= DUK_HEAP_MAX_BREAKPOINTS) {
39714 		DUK_D(DUK_DPRINT("failed to add breakpoint for %O:%ld, all breakpoint slots used",
39715 		                 (duk_heaphdr *) filename, (long) line));
39716 		return -1;
39717 	}
39718 	heap->dbg_breakpoints_active[0] = (duk_breakpoint *) NULL;
39719 	b = heap->dbg_breakpoints + (heap->dbg_breakpoint_count++);
39720 	b->filename = filename;
39721 	b->line = line;
39722 	DUK_HSTRING_INCREF(thr, filename);
39723 
39724 	return heap->dbg_breakpoint_count - 1;  /* index */
39725 }
39726 
39727 DUK_INTERNAL duk_bool_t duk_debug_remove_breakpoint(duk_hthread *thr, duk_small_uint_t breakpoint_index) {
39728 	duk_heap *heap;
39729 	duk_hstring *h;
39730 	duk_breakpoint *b;
39731 	duk_size_t move_size;
39732 
39733 	/* Caller must trigger recomputation of active breakpoint list.  To
39734 	 * ensure stale values are not used if that doesn't happen, clear the
39735 	 * active breakpoint list here.
39736 	 */
39737 
39738 	DUK_ASSERT(thr != NULL);
39739 	heap = thr->heap;
39740 	DUK_ASSERT(heap != NULL);
39741 	DUK_ASSERT(DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap));
39742 	DUK_ASSERT_DISABLE(breakpoint_index >= 0);  /* unsigned */
39743 
39744 	if (breakpoint_index >= heap->dbg_breakpoint_count) {
39745 		DUK_D(DUK_DPRINT("invalid breakpoint index: %ld", (long) breakpoint_index));
39746 		return 0;
39747 	}
39748 	b = heap->dbg_breakpoints + breakpoint_index;
39749 
39750 	h = b->filename;
39751 	DUK_ASSERT(h != NULL);
39752 
39753 	move_size = sizeof(duk_breakpoint) * (heap->dbg_breakpoint_count - breakpoint_index - 1);
39754 	if (move_size > 0) {
39755 		DUK_MEMMOVE((void *) b,
39756 		            (const void *) (b + 1),
39757 		            (size_t) move_size);
39758 	}
39759 	heap->dbg_breakpoint_count--;
39760 	heap->dbg_breakpoints_active[0] = (duk_breakpoint *) NULL;
39761 
39762 	DUK_HSTRING_DECREF(thr, h);  /* side effects */
39763 	DUK_UNREF(h);  /* w/o refcounting */
39764 
39765 	/* Breakpoint entries above the used area are left as garbage. */
39766 
39767 	return 1;
39768 }
39769 
39770 #undef DUK__SET_CONN_BROKEN
39771 
39772 #else  /* DUK_USE_DEBUGGER_SUPPORT */
39773 
39774 /* No debugger support. */
39775 
39776 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
39777 /*
39778  *  Augmenting errors at their creation site and their throw site.
39779  *
39780  *  When errors are created, traceback data is added by built-in code
39781  *  and a user error handler (if defined) can process or replace the
39782  *  error.  Similarly, when errors are thrown, a user error handler
39783  *  (if defined) can process or replace the error.
39784  *
39785  *  Augmentation and other processing at error creation time is nice
39786  *  because an error is only created once, but it may be thrown and
39787  *  rethrown multiple times.  User error handler registered for processing
39788  *  an error at its throw site must be careful to handle rethrowing in
39789  *  a useful manner.
39790  *
39791  *  Error augmentation may throw an internal error (e.g. alloc error).
39792  *
39793  *  Ecmascript allows throwing any values, so all values cannot be
39794  *  augmented.  Currently, the built-in augmentation at error creation
39795  *  only augments error values which are Error instances (= have the
39796  *  built-in Error.prototype in their prototype chain) and are also
39797  *  extensible.  User error handlers have no limitations in this respect.
39798  */
39799 
39800 /* include removed: duk_internal.h */
39801 
39802 /*
39803  *  Helper for calling a user error handler.
39804  *
39805  *  'thr' must be the currently active thread; the error handler is called
39806  *  in its context.  The valstack of 'thr' must have the error value on
39807  *  top, and will be replaced by another error value based on the return
39808  *  value of the error handler.
39809  *
39810  *  The helper calls duk_handle_call() recursively in protected mode.
39811  *  Before that call happens, no longjmps should happen; as a consequence,
39812  *  we must assume that the valstack contains enough temporary space for
39813  *  arguments and such.
39814  *
39815  *  While the error handler runs, any errors thrown will not trigger a
39816  *  recursive error handler call (this is implemented using a heap level
39817  *  flag which will "follow" through any coroutines resumed inside the
39818  *  error handler).  If the error handler is not callable or throws an
39819  *  error, the resulting error replaces the original error (for Duktape
39820  *  internal errors, duk_error_throw.c further substitutes this error with
39821  *  a DoubleError which is not ideal).  This would be easy to change and
39822  *  even signal to the caller.
39823  *
39824  *  The user error handler is stored in 'Duktape.errCreate' or
39825  *  'Duktape.errThrow' depending on whether we're augmenting the error at
39826  *  creation or throw time.  There are several alternatives to this approach,
39827  *  see doc/error-objects.rst for discussion.
39828  *
39829  *  Note: since further longjmp()s may occur while calling the error handler
39830  *  (for many reasons, e.g. a labeled 'break' inside the handler), the
39831  *  caller can make no assumptions on the thr->heap->lj state after the
39832  *  call (this affects especially duk_error_throw.c).  This is not an issue
39833  *  as long as the caller writes to the lj state only after the error handler
39834  *  finishes.
39835  */
39836 
39837 #if defined(DUK_USE_ERRTHROW) || defined(DUK_USE_ERRCREATE)
39838 DUK_LOCAL void duk__err_augment_user(duk_hthread *thr, duk_small_uint_t stridx_cb) {
39839 	duk_context *ctx = (duk_context *) thr;
39840 	duk_tval *tv_hnd;
39841 	duk_small_uint_t call_flags;
39842 	duk_int_t rc;
39843 
39844 	DUK_ASSERT(thr != NULL);
39845 	DUK_ASSERT(thr->heap != NULL);
39846 	DUK_ASSERT_DISABLE(stridx_cb >= 0);  /* unsigned */
39847 	DUK_ASSERT(stridx_cb < DUK_HEAP_NUM_STRINGS);
39848 
39849 	if (DUK_HEAP_HAS_ERRHANDLER_RUNNING(thr->heap)) {
39850 		DUK_DD(DUK_DDPRINT("recursive call to error handler, ignore"));
39851 		return;
39852 	}
39853 
39854 	/*
39855 	 *  Check whether or not we have an error handler.
39856 	 *
39857 	 *  We must be careful of not triggering an error when looking up the
39858 	 *  property.  For instance, if the property is a getter, we don't want
39859 	 *  to call it, only plain values are allowed.  The value, if it exists,
39860 	 *  is not checked.  If the value is not a function, a TypeError happens
39861 	 *  when it is called and that error replaces the original one.
39862 	 */
39863 
39864 	DUK_ASSERT_VALSTACK_SPACE(thr, 4);  /* 3 entries actually needed below */
39865 
39866 	/* [ ... errval ] */
39867 
39868 	if (thr->builtins[DUK_BIDX_DUKTAPE] == NULL) {
39869 		/* When creating built-ins, some of the built-ins may not be set
39870 		 * and we want to tolerate that when throwing errors.
39871 		 */
39872 		DUK_DD(DUK_DDPRINT("error occurred when DUK_BIDX_DUKTAPE is NULL, ignoring"));
39873 		return;
39874 	}
39875 	tv_hnd = duk_hobject_find_existing_entry_tval_ptr(thr->heap,
39876 	                                                  thr->builtins[DUK_BIDX_DUKTAPE],
39877 	                                                  DUK_HTHREAD_GET_STRING(thr, stridx_cb));
39878 	if (tv_hnd == NULL) {
39879 		DUK_DD(DUK_DDPRINT("error handler does not exist or is not a plain value: %!T",
39880 		                   (duk_tval *) tv_hnd));
39881 		return;
39882 	}
39883 	DUK_DDD(DUK_DDDPRINT("error handler dump (callability not checked): %!T",
39884 	                     (duk_tval *) tv_hnd));
39885 	duk_push_tval(ctx, tv_hnd);
39886 
39887 	/* [ ... errval errhandler ] */
39888 
39889 	duk_insert(ctx, -2);  /* -> [ ... errhandler errval ] */
39890 	duk_push_undefined(ctx);
39891 	duk_insert(ctx, -2);  /* -> [ ... errhandler undefined(= this) errval ] */
39892 
39893 	/* [ ... errhandler undefined errval ] */
39894 
39895 	/*
39896 	 *  DUK_CALL_FLAG_IGNORE_RECLIMIT causes duk_handle_call() to ignore C
39897 	 *  recursion depth limit (and won't increase it either).  This is
39898 	 *  dangerous, but useful because it allows the error handler to run
39899 	 *  even if the original error is caused by C recursion depth limit.
39900 	 *
39901 	 *  The heap level DUK_HEAP_FLAG_ERRHANDLER_RUNNING is set for the
39902 	 *  duration of the error handler and cleared afterwards.  This flag
39903 	 *  prevents the error handler from running recursively.  The flag is
39904 	 *  heap level so that the flag properly controls even coroutines
39905 	 *  launched by an error handler.  Since the flag is heap level, it is
39906 	 *  critical to restore it correctly.
39907 	 *
39908 	 *  We ignore errors now: a success return and an error value both
39909 	 *  replace the original error value.  (This would be easy to change.)
39910 	 */
39911 
39912 	DUK_ASSERT(!DUK_HEAP_HAS_ERRHANDLER_RUNNING(thr->heap));  /* since no recursive error handler calls */
39913 	DUK_HEAP_SET_ERRHANDLER_RUNNING(thr->heap);
39914 
39915 	call_flags = DUK_CALL_FLAG_IGNORE_RECLIMIT;  /* ignore reclimit, not constructor */
39916 
39917 	rc = duk_handle_call_protected(thr,
39918 	                               1,            /* num args */
39919 	                               call_flags);  /* call_flags */
39920 	DUK_UNREF(rc);  /* no need to check now: both success and error are OK */
39921 
39922 	DUK_ASSERT(DUK_HEAP_HAS_ERRHANDLER_RUNNING(thr->heap));
39923 	DUK_HEAP_CLEAR_ERRHANDLER_RUNNING(thr->heap);
39924 
39925 	/* [ ... errval ] */
39926 }
39927 #endif  /* DUK_USE_ERRTHROW || DUK_USE_ERRCREATE */
39928 
39929 /*
39930  *  Add ._Tracedata to an error on the stack top.
39931  */
39932 
39933 #if defined(DUK_USE_TRACEBACKS)
39934 DUK_LOCAL void duk__add_traceback(duk_hthread *thr, duk_hthread *thr_callstack, const char *c_filename, duk_int_t c_line, duk_bool_t noblame_fileline) {
39935 	duk_context *ctx = (duk_context *) thr;
39936 	duk_small_uint_t depth;
39937 	duk_int_t i, i_min;
39938 	duk_uarridx_t arr_idx;
39939 	duk_double_t d;
39940 
39941 	DUK_ASSERT(thr != NULL);
39942 	DUK_ASSERT(thr_callstack != NULL);
39943 	DUK_ASSERT(ctx != NULL);
39944 
39945 	/* [ ... error ] */
39946 
39947 	/*
39948 	 *  The traceback format is pretty arcane in an attempt to keep it compact
39949 	 *  and cheap to create.  It may change arbitrarily from version to version.
39950 	 *  It should be decoded/accessed through version specific accessors only.
39951 	 *
39952 	 *  See doc/error-objects.rst.
39953 	 */
39954 
39955 	DUK_DDD(DUK_DDDPRINT("adding traceback to object: %!T",
39956 	                     (duk_tval *) duk_get_tval(ctx, -1)));
39957 
39958 	duk_push_array(ctx);  /* XXX: specify array size, as we know it */
39959 	arr_idx = 0;
39960 
39961 	/* Compiler SyntaxErrors (and other errors) come first, and are
39962 	 * blamed by default (not flagged "noblame").
39963 	 */
39964 	if (thr->compile_ctx != NULL && thr->compile_ctx->h_filename != NULL) {
39965 		duk_push_hstring(ctx, thr->compile_ctx->h_filename);
39966 		duk_xdef_prop_index_wec(ctx, -2, arr_idx);
39967 		arr_idx++;
39968 
39969 		duk_push_uint(ctx, (duk_uint_t) thr->compile_ctx->curr_token.start_line);  /* (flags<<32) + (line), flags = 0 */
39970 		duk_xdef_prop_index_wec(ctx, -2, arr_idx);
39971 		arr_idx++;
39972 	}
39973 
39974 	/* Filename/line from C macros (__FILE__, __LINE__) are added as an
39975 	 * entry with a special format: (string, number).  The number contains
39976 	 * the line and flags.
39977 	 */
39978 
39979 	/* XXX: optimize: allocate an array part to the necessary size (upwards
39980 	 * estimate) and fill in the values directly into the array part; finally
39981 	 * update 'length'.
39982 	 */
39983 
39984 	/* XXX: using duk_put_prop_index() would cause obscure error cases when Array.prototype
39985 	 * has write-protected array index named properties.  This was seen as DoubleErrors
39986 	 * in e.g. some test262 test cases.  Using duk_xdef_prop_index() is better but heavier.
39987 	 * The best fix is to fill in the tracedata directly into the array part.  There are
39988 	 * no side effect concerns if the array part is allocated directly and only INCREFs
39989 	 * happen after that.
39990 	 */
39991 
39992 	/* [ ... error arr ] */
39993 
39994 	if (c_filename) {
39995 		duk_push_string(ctx, c_filename);
39996 		duk_xdef_prop_index_wec(ctx, -2, arr_idx);
39997 		arr_idx++;
39998 
39999 		d = (noblame_fileline ? ((duk_double_t) DUK_TB_FLAG_NOBLAME_FILELINE) * DUK_DOUBLE_2TO32 : 0.0) +
40000 		    (duk_double_t) c_line;
40001 		duk_push_number(ctx, d);
40002 		duk_xdef_prop_index_wec(ctx, -2, arr_idx);
40003 		arr_idx++;
40004 	}
40005 
40006 	/* traceback depth doesn't take into account the filename/line
40007 	 * special handling above (intentional)
40008 	 */
40009 	depth = DUK_USE_TRACEBACK_DEPTH;
40010 	i_min = (thr_callstack->callstack_top > (duk_size_t) depth ? (duk_int_t) (thr_callstack->callstack_top - depth) : 0);
40011 	DUK_ASSERT(i_min >= 0);
40012 
40013 	/* [ ... error arr ] */
40014 
40015 	DUK_ASSERT(thr_callstack->callstack_top <= DUK_INT_MAX);  /* callstack limits */
40016 	for (i = (duk_int_t) (thr_callstack->callstack_top - 1); i >= i_min; i--) {
40017 		duk_uint32_t pc;
40018 
40019 		/*
40020 		 *  Note: each API operation potentially resizes the callstack,
40021 		 *  so be careful to re-lookup after every operation.  Currently
40022 		 *  these is no issue because we don't store a temporary 'act'
40023 		 *  pointer at all.  (This would be a non-issue if we operated
40024 		 *  directly on the array part.)
40025 		 */
40026 
40027 		/* [... arr] */
40028 
40029 		DUK_ASSERT_DISABLE(thr_callstack->callstack[i].pc >= 0);  /* unsigned */
40030 
40031 		/* Add function object. */
40032 		duk_push_tval(ctx, &(thr_callstack->callstack + i)->tv_func);
40033 		duk_xdef_prop_index_wec(ctx, -2, arr_idx);
40034 		arr_idx++;
40035 
40036 		/* Add a number containing: pc, activation flags.
40037 		 *
40038 		 * PC points to next instruction, find offending PC.  Note that
40039 		 * PC == 0 for native code.
40040 		 */
40041 		pc = duk_hthread_get_act_prev_pc(thr_callstack, thr_callstack->callstack + i);
40042 		DUK_ASSERT_DISABLE(pc >= 0);  /* unsigned */
40043 		DUK_ASSERT((duk_double_t) pc < DUK_DOUBLE_2TO32);  /* assume PC is at most 32 bits and non-negative */
40044 		d = ((duk_double_t) thr_callstack->callstack[i].flags) * DUK_DOUBLE_2TO32 + (duk_double_t) pc;
40045 		duk_push_number(ctx, d);  /* -> [... arr num] */
40046 		duk_xdef_prop_index_wec(ctx, -2, arr_idx);
40047 		arr_idx++;
40048 	}
40049 
40050 	/* XXX: set with duk_hobject_set_length() when tracedata is filled directly */
40051 	duk_push_uint(ctx, (duk_uint_t) arr_idx);
40052 	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_WC);
40053 
40054 	/* [ ... error arr ] */
40055 
40056 	duk_xdef_prop_stridx_wec(ctx, -2, DUK_STRIDX_INT_TRACEDATA);  /* -> [ ... error ] */
40057 }
40058 #endif  /* DUK_USE_TRACEBACKS */
40059 
40060 /*
40061  *  Add .fileName and .lineNumber to an error on the stack top.
40062  */
40063 
40064 #if !defined(DUK_USE_TRACEBACKS)
40065 DUK_LOCAL void duk__add_fileline(duk_hthread *thr, duk_hthread *thr_callstack, const char *c_filename, duk_int_t c_line, duk_bool_t noblame_fileline) {
40066 	duk_context *ctx;
40067 #if defined(DUK_USE_ASSERTIONS)
40068 	duk_int_t entry_top;
40069 #endif
40070 
40071 	ctx = (duk_context *) thr;
40072 #if defined(DUK_USE_ASSERTIONS)
40073 	entry_top = duk_get_top(ctx);
40074 #endif
40075 
40076 	/*
40077 	 *  If tracebacks are disabled, 'fileName' and 'lineNumber' are added
40078 	 *  as plain own properties.  Since Error.prototype has accessors of
40079 	 *  the same name, we need to define own properties directly (cannot
40080 	 *  just use e.g. duk_put_prop_stridx).  Existing properties are not
40081 	 *  overwritten in case they already exist.
40082 	 */
40083 
40084 	if (thr->compile_ctx != NULL && thr->compile_ctx->h_filename != NULL) {
40085 		/* Compiler SyntaxError (or other error) gets the primary blame.
40086 		 * Currently no flag to prevent blaming.
40087 		 */
40088 		duk_push_uint(ctx, (duk_uint_t) thr->compile_ctx->curr_token.start_line);
40089 		duk_push_hstring(ctx, thr->compile_ctx->h_filename);
40090 	} else if (c_filename && !noblame_fileline) {
40091 		/* C call site gets blamed next, unless flagged not to do so.
40092 		 * XXX: file/line is disabled in minimal builds, so disable this
40093 		 * too when appropriate.
40094 		 */
40095 		duk_push_int(ctx, c_line);
40096 		duk_push_string(ctx, c_filename);
40097 	} else {
40098 		/* Finally, blame the innermost callstack entry which has a
40099 		 * .fileName property.
40100 		 */
40101 		duk_small_uint_t depth;
40102 		duk_int_t i, i_min;
40103 		duk_uint32_t ecma_line;
40104 
40105 		depth = DUK_USE_TRACEBACK_DEPTH;
40106 		i_min = (thr_callstack->callstack_top > (duk_size_t) depth ? (duk_int_t) (thr_callstack->callstack_top - depth) : 0);
40107 		DUK_ASSERT(i_min >= 0);
40108 
40109 		DUK_ASSERT(thr_callstack->callstack_top <= DUK_INT_MAX);  /* callstack limits */
40110 		for (i = (duk_int_t) (thr_callstack->callstack_top - 1); i >= i_min; i--) {
40111 			duk_activation *act;
40112 			duk_hobject *func;
40113 			duk_uint32_t pc;
40114 
40115 			DUK_UNREF(pc);
40116 			act = thr_callstack->callstack + i;
40117 			DUK_ASSERT(act >= thr_callstack->callstack && act < thr_callstack->callstack + thr_callstack->callstack_size);
40118 
40119 			func = DUK_ACT_GET_FUNC(act);
40120 			if (func == NULL) {
40121 				/* Lightfunc, not blamed now. */
40122 				continue;
40123 			}
40124 
40125 			/* PC points to next instruction, find offending PC,
40126 			 * PC == 0 for native code.
40127 			 */
40128 			pc = duk_hthread_get_act_prev_pc(thr, act);  /* thr argument only used for thr->heap, so specific thread doesn't matter */
40129 			DUK_ASSERT_DISABLE(pc >= 0);  /* unsigned */
40130 			DUK_ASSERT((duk_double_t) pc < DUK_DOUBLE_2TO32);  /* assume PC is at most 32 bits and non-negative */
40131 			act = NULL;  /* invalidated by pushes, so get out of the way */
40132 
40133 			duk_push_hobject(ctx, func);
40134 
40135 			/* [ ... error func ] */
40136 
40137 			duk_get_prop_stridx(ctx, -1, DUK_STRIDX_FILE_NAME);
40138 			if (!duk_is_string(ctx, -1)) {
40139 				duk_pop_2(ctx);
40140 				continue;
40141 			}
40142 
40143 			/* [ ... error func fileName ] */
40144 
40145 			ecma_line = 0;
40146 #if defined(DUK_USE_PC2LINE)
40147 			if (DUK_HOBJECT_IS_COMPILEDFUNCTION(func)) {
40148 				ecma_line = duk_hobject_pc2line_query(ctx, -2, (duk_uint_fast32_t) pc);
40149 			} else {
40150 				/* Native function, no relevant lineNumber. */
40151 			}
40152 #endif  /* DUK_USE_PC2LINE */
40153 			duk_push_u32(ctx, ecma_line);
40154 
40155 			/* [ ... error func fileName lineNumber ] */
40156 
40157 			duk_replace(ctx, -3);
40158 
40159 			/* [ ... error lineNumber fileName ] */
40160 			goto define_props;
40161 		}
40162 
40163 		/* No activation matches, use undefined for both .fileName and
40164 		 * .lineNumber (matches what we do with a _Tracedata based
40165 		 * no-match lookup.
40166 		 */
40167 		duk_push_undefined(ctx);
40168 		duk_push_undefined(ctx);
40169 	}
40170 
40171  define_props:
40172 	/* [ ... error lineNumber fileName ] */
40173 #if defined(DUK_USE_ASSERTIONS)
40174 	DUK_ASSERT(duk_get_top(ctx) == entry_top + 2);
40175 #endif
40176 	duk_xdef_prop_stridx(ctx, -3, DUK_STRIDX_FILE_NAME, DUK_PROPDESC_FLAGS_WC | DUK_PROPDESC_FLAG_NO_OVERWRITE);
40177 	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LINE_NUMBER, DUK_PROPDESC_FLAGS_WC | DUK_PROPDESC_FLAG_NO_OVERWRITE);
40178 }
40179 #endif  /* !DUK_USE_TRACEBACKS */
40180 
40181 /*
40182  *  Add line number to a compiler error.
40183  */
40184 
40185 DUK_LOCAL void duk__add_compiler_error_line(duk_hthread *thr) {
40186 	duk_context *ctx;
40187 
40188 	/* Append a "(line NNN)" to the "message" property of any error
40189 	 * thrown during compilation.  Usually compilation errors are
40190 	 * SyntaxErrors but they can also be out-of-memory errors and
40191 	 * the like.
40192 	 */
40193 
40194 	/* [ ... error ] */
40195 
40196 	ctx = (duk_context *) thr;
40197 	DUK_ASSERT(duk_is_object(ctx, -1));
40198 
40199 	if (!(thr->compile_ctx != NULL && thr->compile_ctx->h_filename != NULL)) {
40200 		return;
40201 	}
40202 
40203 	DUK_DDD(DUK_DDDPRINT("compile error, before adding line info: %!T",
40204 	                     (duk_tval *) duk_get_tval(ctx, -1)));
40205 
40206 	if (duk_get_prop_stridx(ctx, -1, DUK_STRIDX_MESSAGE)) {
40207 		duk_push_sprintf(ctx, " (line %ld)", (long) thr->compile_ctx->curr_token.start_line);
40208 		duk_concat(ctx, 2);
40209 		duk_put_prop_stridx(ctx, -2, DUK_STRIDX_MESSAGE);
40210 	} else {
40211 		duk_pop(ctx);
40212 	}
40213 
40214 	DUK_DDD(DUK_DDDPRINT("compile error, after adding line info: %!T",
40215 	                     (duk_tval *) duk_get_tval(ctx, -1)));
40216 }
40217 
40218 /*
40219  *  Augment an error being created using Duktape specific properties
40220  *  like _Tracedata or .fileName/.lineNumber.
40221  */
40222 
40223 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
40224 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_small_int_t noblame_fileline, duk_hobject *obj) {
40225 	duk_context *ctx = (duk_context *) thr;
40226 #if defined(DUK_USE_ASSERTIONS)
40227 	duk_int_t entry_top;
40228 #endif
40229 
40230 #if defined(DUK_USE_ASSERTIONS)
40231 	entry_top = duk_get_top(ctx);
40232 #endif
40233 	DUK_ASSERT(obj != NULL);
40234 
40235 	DUK_UNREF(obj);  /* unreferenced w/o tracebacks */
40236 	DUK_UNREF(ctx);  /* unreferenced w/o asserts */
40237 
40238 	duk__add_compiler_error_line(thr);
40239 
40240 #if defined(DUK_USE_TRACEBACKS)
40241 	/* If tracebacks are enabled, the '_Tracedata' property is the only
40242 	 * thing we need: 'fileName' and 'lineNumber' are virtual properties
40243 	 * which use '_Tracedata'.
40244 	 */
40245 	if (duk_hobject_hasprop_raw(thr, obj, DUK_HTHREAD_STRING_INT_TRACEDATA(thr))) {
40246 		DUK_DDD(DUK_DDDPRINT("error value already has a '_Tracedata' property, not modifying it"));
40247 	} else {
40248 		duk__add_traceback(thr, thr_callstack, c_filename, c_line, noblame_fileline);
40249 	}
40250 #else
40251 	/* Without tracebacks the concrete .fileName and .lineNumber need
40252 	 * to be added directly.
40253 	 */
40254 	duk__add_fileline(thr, thr_callstack, c_filename, c_line, noblame_fileline);
40255 #endif
40256 
40257 #if defined(DUK_USE_ASSERTIONS)
40258 	DUK_ASSERT(duk_get_top(ctx) == entry_top);
40259 #endif
40260 }
40261 #endif  /* DUK_USE_AUGMENT_ERROR_CREATE */
40262 
40263 /*
40264  *  Augment an error at creation time with _Tracedata/fileName/lineNumber
40265  *  and allow a user error handler (if defined) to process/replace the error.
40266  *  The error to be augmented is at the stack top.
40267  *
40268  *  thr: thread containing the error value
40269  *  thr_callstack: thread which should be used for generating callstack etc.
40270  *  c_filename: C __FILE__ related to the error
40271  *  c_line: C __LINE__ related to the error
40272  *  noblame_fileline: if true, don't fileName/line as error source, otherwise use traceback
40273  *                    (needed because user code filename/line are reported but internal ones
40274  *                    are not)
40275  *
40276  *  XXX: rename noblame_fileline to flags field; combine it to some existing
40277  *  field (there are only a few call sites so this may not be worth it).
40278  */
40279 
40280 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
40281 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_bool_t noblame_fileline) {
40282 	duk_context *ctx = (duk_context *) thr;
40283 	duk_hobject *obj;
40284 
40285 	DUK_ASSERT(thr != NULL);
40286 	DUK_ASSERT(thr_callstack != NULL);
40287 	DUK_ASSERT(ctx != NULL);
40288 
40289 	/* [ ... error ] */
40290 
40291 	/*
40292 	 *  Criteria for augmenting:
40293 	 *
40294 	 *   - augmentation enabled in build (naturally)
40295 	 *   - error value internal prototype chain contains the built-in
40296 	 *     Error prototype object (i.e. 'val instanceof Error')
40297 	 *
40298 	 *  Additional criteria for built-in augmenting:
40299 	 *
40300 	 *   - error value is an extensible object
40301 	 */
40302 
40303 	obj = duk_get_hobject(ctx, -1);
40304 	if (!obj) {
40305 		DUK_DDD(DUK_DDDPRINT("value is not an object, skip both built-in and user augment"));
40306 		return;
40307 	}
40308 	if (!duk_hobject_prototype_chain_contains(thr, obj, thr->builtins[DUK_BIDX_ERROR_PROTOTYPE], 1 /*ignore_loop*/)) {
40309 		/* If the value has a prototype loop, it's critical not to
40310 		 * throw here.  Instead, assume the value is not to be
40311 		 * augmented.
40312 		 */
40313 		DUK_DDD(DUK_DDDPRINT("value is not an error instance, skip both built-in and user augment"));
40314 		return;
40315 	}
40316 	if (DUK_HOBJECT_HAS_EXTENSIBLE(obj)) {
40317 		DUK_DDD(DUK_DDDPRINT("error meets criteria, built-in augment"));
40318 		duk__err_augment_builtin_create(thr, thr_callstack, c_filename, c_line, noblame_fileline, obj);
40319 	} else {
40320 		DUK_DDD(DUK_DDDPRINT("error does not meet criteria, no built-in augment"));
40321 	}
40322 
40323 	/* [ ... error ] */
40324 
40325 #if defined(DUK_USE_ERRCREATE)
40326 	duk__err_augment_user(thr, DUK_STRIDX_ERR_CREATE);
40327 #endif
40328 }
40329 #endif  /* DUK_USE_AUGMENT_ERROR_CREATE */
40330 
40331 /*
40332  *  Augment an error at throw time; allow a user error handler (if defined)
40333  *  to process/replace the error.  The error to be augmented is at the
40334  *  stack top.
40335  */
40336 
40337 #if defined(DUK_USE_AUGMENT_ERROR_THROW)
40338 DUK_INTERNAL void duk_err_augment_error_throw(duk_hthread *thr) {
40339 #if defined(DUK_USE_ERRTHROW)
40340 	duk__err_augment_user(thr, DUK_STRIDX_ERR_THROW);
40341 #endif  /* DUK_USE_ERRTHROW */
40342 }
40343 #endif  /* DUK_USE_AUGMENT_ERROR_THROW */
40344 /*
40345  *  Do a longjmp call, calling the fatal error handler if no
40346  *  catchpoint exists.
40347  */
40348 
40349 /* include removed: duk_internal.h */
40350 
40351 DUK_INTERNAL void duk_err_longjmp(duk_hthread *thr) {
40352 	DUK_ASSERT(thr != NULL);
40353 
40354 	DUK_DD(DUK_DDPRINT("longjmp error: type=%d iserror=%d value1=%!T value2=%!T",
40355 	                   (int) thr->heap->lj.type, (int) thr->heap->lj.iserror,
40356 	                   &thr->heap->lj.value1, &thr->heap->lj.value2));
40357 
40358 #if !defined(DUK_USE_CPP_EXCEPTIONS)
40359 	/* If we don't have a jmpbuf_ptr, there is little we can do
40360 	 * except panic.  The caller's expectation is that we never
40361 	 * return.
40362 	 *
40363 	 * With C++ exceptions we now just propagate an uncaught error
40364 	 * instead of invoking the fatal error handler.  Because there's
40365 	 * a dummy jmpbuf for C++ exceptions now, this could be changed.
40366 	 */
40367 	if (!thr->heap->lj.jmpbuf_ptr) {
40368 
40369 		DUK_D(DUK_DPRINT("uncaught error: type=%d iserror=%d value1=%!T value2=%!T",
40370 		                 (int) thr->heap->lj.type, (int) thr->heap->lj.iserror,
40371 		                 &thr->heap->lj.value1, &thr->heap->lj.value2));
40372 
40373 		duk_fatal((duk_context *) thr, DUK_ERR_UNCAUGHT_ERROR, "uncaught error");
40374 		DUK_UNREACHABLE();
40375 	}
40376 #endif  /* DUK_USE_CPP_EXCEPTIONS */
40377 
40378 #if defined(DUK_USE_CPP_EXCEPTIONS)
40379 	{
40380 		duk_internal_exception exc;  /* dummy */
40381 		throw exc;
40382 	}
40383 #else  /* DUK_USE_CPP_EXCEPTIONS */
40384 	DUK_LONGJMP(thr->heap->lj.jmpbuf_ptr->jb);
40385 #endif  /* DUK_USE_CPP_EXCEPTIONS */
40386 
40387 	DUK_UNREACHABLE();
40388 }
40389 /*
40390  *  Error helpers
40391  */
40392 
40393 /* include removed: duk_internal.h */
40394 
40395 /*
40396  *  Helper to walk the thread chain and see if there is an active error
40397  *  catcher.  Protected calls or finally blocks aren't considered catching.
40398  */
40399 
40400 #if defined(DUK_USE_DEBUGGER_SUPPORT) && \
40401     (defined(DUK_USE_DEBUGGER_THROW_NOTIFY) || defined(DUK_USE_DEBUGGER_PAUSE_UNCAUGHT))
40402 DUK_LOCAL duk_bool_t duk__have_active_catcher(duk_hthread *thr) {
40403 	/*
40404 	 * XXX: As noted above, a protected API call won't be counted as a
40405 	 * catcher. This is usually convenient, e.g. in the case of a top-
40406 	 * level duk_pcall(), but may not always be desirable. Perhaps add an
40407 	 * argument to treat them as catchers?
40408 	 */
40409 
40410 	duk_size_t i;
40411 
40412 	DUK_ASSERT(thr != NULL);
40413 
40414 	while (thr != NULL) {
40415 		for (i = 0; i < thr->catchstack_top; i++) {
40416 			duk_catcher *cat = thr->catchstack + i;
40417 			if (DUK_CAT_HAS_CATCH_ENABLED(cat)) {
40418 				return 1;  /* all we need to know */
40419 			}
40420 		}
40421 		thr = thr->resumer;
40422 	}
40423 	return 0;
40424 }
40425 #endif  /* DUK_USE_DEBUGGER_SUPPORT && (DUK_USE_DEBUGGER_THROW_NOTIFY || DUK_USE_DEBUGGER_PAUSE_UNCAUGHT) */
40426 
40427 /*
40428  *  Get prototype object for an integer error code.
40429  */
40430 
40431 DUK_INTERNAL duk_hobject *duk_error_prototype_from_code(duk_hthread *thr, duk_errcode_t code) {
40432 	switch (code) {
40433 	case DUK_ERR_EVAL_ERROR:
40434 		return thr->builtins[DUK_BIDX_EVAL_ERROR_PROTOTYPE];
40435 	case DUK_ERR_RANGE_ERROR:
40436 		return thr->builtins[DUK_BIDX_RANGE_ERROR_PROTOTYPE];
40437 	case DUK_ERR_REFERENCE_ERROR:
40438 		return thr->builtins[DUK_BIDX_REFERENCE_ERROR_PROTOTYPE];
40439 	case DUK_ERR_SYNTAX_ERROR:
40440 		return thr->builtins[DUK_BIDX_SYNTAX_ERROR_PROTOTYPE];
40441 	case DUK_ERR_TYPE_ERROR:
40442 		return thr->builtins[DUK_BIDX_TYPE_ERROR_PROTOTYPE];
40443 	case DUK_ERR_URI_ERROR:
40444 		return thr->builtins[DUK_BIDX_URI_ERROR_PROTOTYPE];
40445 
40446 	/* XXX: more specific error classes? */
40447 	case DUK_ERR_UNIMPLEMENTED_ERROR:
40448 	case DUK_ERR_INTERNAL_ERROR:
40449 	case DUK_ERR_ALLOC_ERROR:
40450 	case DUK_ERR_ASSERTION_ERROR:
40451 	case DUK_ERR_API_ERROR:
40452 	case DUK_ERR_ERROR:
40453 	default:
40454 		return thr->builtins[DUK_BIDX_ERROR_PROTOTYPE];
40455 	}
40456 }
40457 
40458 /*
40459  *  Exposed helper for setting up heap longjmp state.
40460  */
40461 
40462 DUK_INTERNAL void duk_err_setup_heap_ljstate(duk_hthread *thr, duk_small_int_t lj_type) {
40463 #if defined(DUK_USE_DEBUGGER_SUPPORT)
40464 	/* If something is thrown with the debugger attached and nobody will
40465 	 * catch it, execution is paused before the longjmp, turning over
40466 	 * control to the debug client.  This allows local state to be examined
40467 	 * before the stack is unwound.  Errors are not intercepted when debug
40468 	 * message loop is active (e.g. for Eval).
40469 	 */
40470 
40471 	/* XXX: Allow customizing the pause and notify behavior at runtime
40472 	 * using debugger runtime flags.  For now the behavior is fixed using
40473 	 * config options.
40474 	 */
40475 #if defined(DUK_USE_DEBUGGER_THROW_NOTIFY) || defined(DUK_USE_DEBUGGER_PAUSE_UNCAUGHT)
40476 	if (DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap) &&
40477 	    !thr->heap->dbg_processing &&
40478 	    lj_type == DUK_LJ_TYPE_THROW) {
40479 		duk_context *ctx = (duk_context *) thr;
40480 		duk_bool_t fatal;
40481 		duk_hobject *h_obj;
40482 
40483 		/* Don't intercept a DoubleError, we may have caused the initial double
40484 		 * fault and attempting to intercept it will cause us to be called
40485 		 * recursively and exhaust the C stack.
40486 		 */
40487 		h_obj = duk_get_hobject(ctx, -1);
40488 		if (h_obj == thr->builtins[DUK_BIDX_DOUBLE_ERROR]) {
40489 			DUK_D(DUK_DPRINT("built-in DoubleError instance thrown, not intercepting"));
40490 			goto skip_throw_intercept;
40491 		}
40492 
40493 		DUK_D(DUK_DPRINT("throw with debugger attached, report to client"));
40494 
40495 		fatal = !duk__have_active_catcher(thr);
40496 
40497 #if defined(DUK_USE_DEBUGGER_THROW_NOTIFY)
40498 		/* Report it to the debug client */
40499 		duk_debug_send_throw(thr, fatal);
40500 #endif
40501 
40502 #if defined(DUK_USE_DEBUGGER_PAUSE_UNCAUGHT)
40503 		if (fatal) {
40504 			DUK_D(DUK_DPRINT("throw will be fatal, halt before longjmp"));
40505 			duk_debug_halt_execution(thr, 1 /*use_prev_pc*/);
40506 		}
40507 #endif
40508 	}
40509 
40510  skip_throw_intercept:
40511 #endif  /* DUK_USE_DEBUGGER_THROW_NOTIFY || DUK_USE_DEBUGGER_PAUSE_UNCAUGHT */
40512 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
40513 
40514 	thr->heap->lj.type = lj_type;
40515 
40516 	DUK_ASSERT(thr->valstack_top > thr->valstack);
40517 	DUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value1, thr->valstack_top - 1);  /* side effects */
40518 
40519 	duk_pop((duk_context *) thr);
40520 }
40521 /*
40522  *  Create and throw an Ecmascript error object based on a code and a message.
40523  *
40524  *  Used when we throw errors internally.  Ecmascript generated error objects
40525  *  are created by Ecmascript code, and the throwing is handled by the bytecode
40526  *  executor.
40527  */
40528 
40529 /* include removed: duk_internal.h */
40530 
40531 /*
40532  *  Create and throw an error (originating from Duktape internally)
40533  *
40534  *  Push an error object on top of the stack, possibly throw augmenting
40535  *  the error, and finally longjmp.
40536  *
40537  *  If an error occurs while we're dealing with the current error, we might
40538  *  enter an infinite recursion loop.  This is prevented by detecting a
40539  *  "double fault" through the heap->handling_error flag; the recursion
40540  *  then stops at the second level.
40541  */
40542 
40543 #ifdef DUK_USE_VERBOSE_ERRORS
40544 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) {
40545 #else
40546 DUK_INTERNAL void duk_err_create_and_throw(duk_hthread *thr, duk_errcode_t code) {
40547 #endif
40548 	duk_context *ctx = (duk_context *) thr;
40549 	duk_bool_t double_error = thr->heap->handling_error;
40550 
40551 #ifdef DUK_USE_VERBOSE_ERRORS
40552 	DUK_DD(DUK_DDPRINT("duk_err_create_and_throw(): code=%ld, msg=%s, filename=%s, line=%ld",
40553 	                   (long) code, (const char *) msg,
40554 	                   (const char *) filename, (long) line));
40555 #else
40556 	DUK_DD(DUK_DDPRINT("duk_err_create_and_throw(): code=%ld", (long) code));
40557 #endif
40558 
40559 	DUK_ASSERT(thr != NULL);
40560 	DUK_ASSERT(ctx != NULL);
40561 
40562 	thr->heap->handling_error = 1;
40563 
40564 	if (!double_error) {
40565 		/* Allow headroom for calls during error handling (see GH-191).
40566 		 * We allow space for 10 additional recursions, with one extra
40567 		 * for, e.g. a print() call at the deepest level.
40568 		 */
40569 		DUK_ASSERT(thr->callstack_max == DUK_CALLSTACK_DEFAULT_MAX);
40570 		thr->callstack_max = DUK_CALLSTACK_DEFAULT_MAX + DUK_CALLSTACK_GROW_STEP + 11;
40571 	}
40572 
40573 	DUK_ASSERT(thr->callstack_max == DUK_CALLSTACK_DEFAULT_MAX + DUK_CALLSTACK_GROW_STEP + 11);  /* just making sure */
40574 
40575 	/* Sync so that augmentation sees up-to-date activations, NULL
40576 	 * thr->ptr_curr_pc so that it's not used if side effects occur
40577 	 * in augmentation or longjmp handling.
40578 	 */
40579 	duk_hthread_sync_and_null_currpc(thr);
40580 
40581 	/*
40582 	 *  Create and push an error object onto the top of stack.
40583 	 *  If a "double error" occurs, use a fixed error instance
40584 	 *  to avoid further trouble.
40585 	 */
40586 
40587 	/* XXX: if attempt to push beyond allocated valstack, this double fault
40588 	 * handling fails miserably.  We should really write the double error
40589 	 * directly to thr->heap->lj.value1 and avoid valstack use entirely.
40590 	 */
40591 
40592 	if (double_error) {
40593 		if (thr->builtins[DUK_BIDX_DOUBLE_ERROR]) {
40594 			DUK_D(DUK_DPRINT("double fault detected -> push built-in fixed 'double error' instance"));
40595 			duk_push_hobject_bidx(ctx, DUK_BIDX_DOUBLE_ERROR);
40596 		} else {
40597 			DUK_D(DUK_DPRINT("double fault detected; there is no built-in fixed 'double error' instance "
40598 			                 "-> push the error code as a number"));
40599 			duk_push_int(ctx, (duk_int_t) code);
40600 		}
40601 	} else {
40602 		/* Error object is augmented at its creation here. */
40603 		duk_require_stack(ctx, 1);
40604 		/* XXX: unnecessary '%s' formatting here, but cannot use
40605 		 * 'msg' as a format string directly.
40606 		 */
40607 #ifdef DUK_USE_VERBOSE_ERRORS
40608 		duk_push_error_object_raw(ctx,
40609 		                          code | DUK_ERRCODE_FLAG_NOBLAME_FILELINE,
40610 		                          filename,
40611 		                          line,
40612 		                          "%s",
40613 		                          (const char *) msg);
40614 #else
40615 		duk_push_error_object_raw(ctx,
40616 		                          code | DUK_ERRCODE_FLAG_NOBLAME_FILELINE,
40617 		                          NULL,
40618 		                          0,
40619 		                          NULL);
40620 #endif
40621 	}
40622 
40623 	/*
40624 	 *  Augment error (throw time), unless alloc/double error
40625 	 */
40626 
40627 	if (double_error || code == DUK_ERR_ALLOC_ERROR) {
40628 		DUK_D(DUK_DPRINT("alloc or double error: skip throw augmenting to avoid further trouble"));
40629 	} else {
40630 #if defined(DUK_USE_AUGMENT_ERROR_THROW)
40631 		DUK_DDD(DUK_DDDPRINT("THROW ERROR (INTERNAL): %!iT (before throw augment)",
40632 		                     (duk_tval *) duk_get_tval(ctx, -1)));
40633 		duk_err_augment_error_throw(thr);
40634 #endif
40635 	}
40636 
40637 	/*
40638 	 *  Finally, longjmp
40639 	 */
40640 
40641 	duk_err_setup_heap_ljstate(thr, DUK_LJ_TYPE_THROW);
40642 
40643 	thr->callstack_max = DUK_CALLSTACK_DEFAULT_MAX;  /* reset callstack limit */
40644 	thr->heap->handling_error = 0;
40645 
40646 	DUK_DDD(DUK_DDDPRINT("THROW ERROR (INTERNAL): %!iT, %!iT (after throw augment)",
40647 	                     (duk_tval *) &thr->heap->lj.value1, (duk_tval *) &thr->heap->lj.value2));
40648 
40649 	duk_err_longjmp(thr);
40650 	DUK_UNREACHABLE();
40651 }
40652 
40653 /*
40654  *  Helper for C function call negative return values.
40655  */
40656 
40657 DUK_INTERNAL void duk_error_throw_from_negative_rc(duk_hthread *thr, duk_ret_t rc) {
40658 	duk_context *ctx = (duk_context *) thr;
40659 	const char *msg;
40660 	duk_errcode_t code;
40661 
40662 	DUK_ASSERT(thr != NULL);
40663 	DUK_ASSERT(rc < 0);
40664 
40665 	/* XXX: this generates quite large code - perhaps select the error
40666 	 * class based on the code and then just use the error 'name'?
40667 	 */
40668 	/* XXX: shared strings */
40669 
40670 	code = -rc;
40671 
40672 	switch (rc) {
40673 	case DUK_RET_UNIMPLEMENTED_ERROR:  msg = "unimplemented"; break;
40674 	case DUK_RET_UNSUPPORTED_ERROR:    msg = "unsupported"; break;
40675 	case DUK_RET_INTERNAL_ERROR:       msg = "internal"; break;
40676 	case DUK_RET_ALLOC_ERROR:          msg = "alloc"; break;
40677 	case DUK_RET_ASSERTION_ERROR:      msg = "assertion"; break;
40678 	case DUK_RET_API_ERROR:            msg = "api"; break;
40679 	case DUK_RET_UNCAUGHT_ERROR:       msg = "uncaught"; break;
40680 	case DUK_RET_ERROR:                msg = "error"; break;
40681 	case DUK_RET_EVAL_ERROR:           msg = "eval"; break;
40682 	case DUK_RET_RANGE_ERROR:          msg = "range"; break;
40683 	case DUK_RET_REFERENCE_ERROR:      msg = "reference"; break;
40684 	case DUK_RET_SYNTAX_ERROR:         msg = "syntax"; break;
40685 	case DUK_RET_TYPE_ERROR:           msg = "type"; break;
40686 	case DUK_RET_URI_ERROR:            msg = "uri"; break;
40687 	default:                           msg = "unknown"; break;
40688 	}
40689 
40690 	DUK_ASSERT(msg != NULL);
40691 
40692 	/*
40693 	 *  The __FILE__ and __LINE__ information is intentionally not used in the
40694 	 *  creation of the error object, as it isn't useful in the tracedata.  The
40695 	 *  tracedata still contains the function which returned the negative return
40696 	 *  code, and having the file/line of this function isn't very useful.
40697 	 */
40698 
40699 	duk_error_raw(ctx, code, NULL, 0, "%s error (rc %ld)", (const char *) msg, (long) rc);
40700 	DUK_UNREACHABLE();
40701 }
40702 /*
40703  *  duk_hbuffer allocation and freeing.
40704  */
40705 
40706 /* include removed: duk_internal.h */
40707 
40708 /* Allocate a new duk_hbuffer of a certain type and return a pointer to it
40709  * (NULL on error).  Write buffer data pointer to 'out_bufdata' (only if
40710  * allocation successful).
40711  */
40712 DUK_INTERNAL duk_hbuffer *duk_hbuffer_alloc(duk_heap *heap, duk_size_t size, duk_small_uint_t flags, void **out_bufdata) {
40713 	duk_hbuffer *res = NULL;
40714 	duk_size_t header_size;
40715 	duk_size_t alloc_size;
40716 
40717 	DUK_ASSERT(heap != NULL);
40718 	DUK_ASSERT(out_bufdata != NULL);
40719 
40720 	DUK_DDD(DUK_DDDPRINT("allocate hbuffer"));
40721 
40722 	/* Size sanity check.  Should not be necessary because caller is
40723 	 * required to check this, but we don't want to cause a segfault
40724 	 * if the size wraps either in duk_size_t computation or when
40725 	 * storing the size in a 16-bit field.
40726 	 */
40727 	if (size > DUK_HBUFFER_MAX_BYTELEN) {
40728 		DUK_D(DUK_DPRINT("hbuffer alloc failed: size too large: %ld", (long) size));
40729 		return NULL;  /* no need to write 'out_bufdata' */
40730 	}
40731 
40732 	if (flags & DUK_BUF_FLAG_EXTERNAL) {
40733 		header_size = sizeof(duk_hbuffer_external);
40734 		alloc_size = sizeof(duk_hbuffer_external);
40735 	} else if (flags & DUK_BUF_FLAG_DYNAMIC) {
40736 		header_size = sizeof(duk_hbuffer_dynamic);
40737 		alloc_size = sizeof(duk_hbuffer_dynamic);
40738 	} else {
40739 		header_size = sizeof(duk_hbuffer_fixed);
40740 		alloc_size = sizeof(duk_hbuffer_fixed) + size;
40741 		DUK_ASSERT(alloc_size >= sizeof(duk_hbuffer_fixed));  /* no wrapping */
40742 	}
40743 
40744 	res = (duk_hbuffer *) DUK_ALLOC(heap, alloc_size);
40745 	if (!res) {
40746 		goto error;
40747 	}
40748 
40749 	/* zero everything unless requested not to do so */
40750 #if defined(DUK_USE_ZERO_BUFFER_DATA)
40751 	DUK_MEMZERO((void *) res,
40752 	            (flags & DUK_BUF_FLAG_NOZERO) ? header_size : alloc_size);
40753 #else
40754 	DUK_MEMZERO((void *) res, header_size);
40755 #endif
40756 
40757 	if (flags & DUK_BUF_FLAG_EXTERNAL) {
40758 		duk_hbuffer_external *h;
40759 		h = (duk_hbuffer_external *) res;
40760 		DUK_UNREF(h);
40761 		*out_bufdata = NULL;
40762 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
40763 #if defined(DUK_USE_HEAPPTR16)
40764 /* the compressed pointer is zeroed which maps to NULL, so nothing to do. */
40765 #else
40766 		DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(heap, h, NULL);
40767 #endif
40768 #endif
40769 		DUK_ASSERT(DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(heap, h) == NULL);
40770 	} else if (flags & DUK_BUF_FLAG_DYNAMIC) {
40771 		duk_hbuffer_dynamic *h = (duk_hbuffer_dynamic *) res;
40772 		void *ptr;
40773 
40774 		if (size > 0) {
40775 			DUK_ASSERT(!(flags & DUK_BUF_FLAG_EXTERNAL));  /* alloc external with size zero */
40776 			DUK_DDD(DUK_DDDPRINT("dynamic buffer with nonzero size, alloc actual buffer"));
40777 #ifdef DUK_USE_ZERO_BUFFER_DATA
40778 			ptr = DUK_ALLOC_ZEROED(heap, size);
40779 #else
40780 			ptr = DUK_ALLOC(heap, size);
40781 #endif
40782 			if (!ptr) {
40783 				/* Because size > 0, NULL check is correct */
40784 				goto error;
40785 			}
40786 			*out_bufdata = ptr;
40787 
40788 			DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap, h, ptr);
40789 		} else {
40790 			*out_bufdata = NULL;
40791 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
40792 #if defined(DUK_USE_HEAPPTR16)
40793 /* the compressed pointer is zeroed which maps to NULL, so nothing to do. */
40794 #else
40795 			DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap, h, NULL);
40796 #endif
40797 #endif
40798 			DUK_ASSERT(DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, h) == NULL);
40799 		}
40800 	} else {
40801 		*out_bufdata = (void *) ((duk_hbuffer_fixed *) res + 1);
40802 	}
40803 
40804 	DUK_HBUFFER_SET_SIZE(res, size);
40805 
40806 	DUK_HEAPHDR_SET_TYPE(&res->hdr, DUK_HTYPE_BUFFER);
40807 	if (flags & DUK_BUF_FLAG_DYNAMIC) {
40808 		DUK_HBUFFER_SET_DYNAMIC(res);
40809 		if (flags & DUK_BUF_FLAG_EXTERNAL) {
40810 			DUK_HBUFFER_SET_EXTERNAL(res);
40811 		}
40812 	} else {
40813 		DUK_ASSERT(!(flags & DUK_BUF_FLAG_EXTERNAL));
40814 	}
40815         DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap, &res->hdr);
40816 
40817 	DUK_DDD(DUK_DDDPRINT("allocated hbuffer: %p", (void *) res));
40818 	return res;
40819 
40820  error:
40821 	DUK_DD(DUK_DDPRINT("hbuffer allocation failed"));
40822 
40823 	DUK_FREE(heap, res);
40824 	return NULL;  /* no need to write 'out_bufdata' */
40825 }
40826 
40827 /* For indirect allocs. */
40828 
40829 DUK_INTERNAL void *duk_hbuffer_get_dynalloc_ptr(duk_heap *heap, void *ud) {
40830 	duk_hbuffer_dynamic *buf = (duk_hbuffer_dynamic *) ud;
40831 	DUK_UNREF(heap);
40832 	return (void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, buf);
40833 }
40834 /*
40835  *  duk_hbuffer operations such as resizing and inserting/appending data to
40836  *  a dynamic buffer.
40837  *
40838  *  Append operations append to the end of the buffer and they are relatively
40839  *  efficient: the buffer is grown with a "spare" part relative to the buffer
40840  *  size to minimize reallocations.  Insert operations need to move existing
40841  *  data forward in the buffer with memmove() and are not very efficient.
40842  *  They are used e.g. by the regexp compiler to "backpatch" regexp bytecode.
40843  */
40844 
40845 /* include removed: duk_internal.h */
40846 
40847 /*
40848  *  Resizing
40849  */
40850 
40851 DUK_INTERNAL void duk_hbuffer_resize(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t new_size) {
40852 	void *res;
40853 	duk_size_t prev_size;
40854 
40855 	DUK_ASSERT(thr != NULL);
40856 	DUK_ASSERT(buf != NULL);
40857 	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf));
40858 	DUK_ASSERT(!DUK_HBUFFER_HAS_EXTERNAL(buf));
40859 
40860 	/*
40861 	 *  Maximum size check
40862 	 */
40863 
40864 	if (new_size > DUK_HBUFFER_MAX_BYTELEN) {
40865 		DUK_ERROR_RANGE(thr, "buffer too long");
40866 	}
40867 
40868 	/*
40869 	 *  Note: use indirect realloc variant just in case mark-and-sweep
40870 	 *  (finalizers) might resize this same buffer during garbage
40871 	 *  collection.
40872 	 */
40873 
40874 	res = DUK_REALLOC_INDIRECT(thr->heap, duk_hbuffer_get_dynalloc_ptr, (void *) buf, new_size);
40875 	if (res != NULL || new_size == 0) {
40876 		/* 'res' may be NULL if new allocation size is 0. */
40877 
40878 		DUK_DDD(DUK_DDDPRINT("resized dynamic buffer %p:%ld -> %p:%ld",
40879 		                     (void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, buf),
40880 		                     (long) DUK_HBUFFER_DYNAMIC_GET_SIZE(buf),
40881 		                     (void *) res,
40882 		                     (long) new_size));
40883 
40884 		/*
40885 		 *  The entire allocated buffer area, regardless of actual used
40886 		 *  size, is kept zeroed in resizes for simplicity.  If the buffer
40887 		 *  is grown, zero the new part.
40888 		 */
40889 
40890 		prev_size = DUK_HBUFFER_DYNAMIC_GET_SIZE(buf);
40891 		if (new_size > prev_size) {
40892 			DUK_ASSERT(new_size - prev_size > 0);
40893 #ifdef DUK_USE_ZERO_BUFFER_DATA
40894 			DUK_MEMZERO((void *) ((char *) res + prev_size),
40895 			            (duk_size_t) (new_size - prev_size));
40896 #endif
40897 		}
40898 
40899 		DUK_HBUFFER_DYNAMIC_SET_SIZE(buf, new_size);
40900 		DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(thr->heap, buf, res);
40901 	} else {
40902 		DUK_ERROR_ALLOC_DEFMSG(thr);
40903 	}
40904 
40905 	DUK_ASSERT(res != NULL || new_size == 0);
40906 }
40907 
40908 DUK_INTERNAL void duk_hbuffer_reset(duk_hthread *thr, duk_hbuffer_dynamic *buf) {
40909 	DUK_ASSERT(thr != NULL);
40910 	DUK_ASSERT(buf != NULL);
40911 	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf));
40912 	DUK_ASSERT(!DUK_HBUFFER_HAS_EXTERNAL(buf));
40913 
40914 	duk_hbuffer_resize(thr, buf, 0);
40915 }
40916 /* include removed: duk_internal.h */
40917 
40918 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
40919 DUK_INTERNAL duk_uint_t duk_hbufferobject_clamp_bytelength(duk_hbufferobject *h_bufobj, duk_uint_t len) {
40920 	duk_uint_t buf_size;
40921 	duk_uint_t buf_avail;
40922 
40923 	DUK_ASSERT(h_bufobj != NULL);
40924 	DUK_ASSERT(h_bufobj->buf != NULL);
40925 
40926 	buf_size = (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_bufobj->buf);
40927 	if (h_bufobj->offset > buf_size) {
40928 		/* Slice starting point is beyond current length. */
40929 		return 0;
40930 	}
40931 	buf_avail = buf_size - h_bufobj->offset;
40932 
40933 	return buf_avail >= len ? len : buf_avail;
40934 }
40935 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
40936 /*
40937  *  duk_heap allocation and freeing.
40938  */
40939 
40940 /* include removed: duk_internal.h */
40941 
40942 /* Constants for built-in string data depacking. */
40943 #define DUK__BITPACK_LETTER_LIMIT  26
40944 #define DUK__BITPACK_UNDERSCORE    26
40945 #define DUK__BITPACK_FF            27
40946 #define DUK__BITPACK_SWITCH1       29
40947 #define DUK__BITPACK_SWITCH        30
40948 #define DUK__BITPACK_SEVENBIT      31
40949 
40950 #if defined(DUK_USE_ROM_STRINGS)
40951 /* Fixed seed value used with ROM strings. */
40952 #define DUK__FIXED_HASH_SEED       0xabcd1234
40953 #endif
40954 
40955 /*
40956  *  Free a heap object.
40957  *
40958  *  Free heap object and its internal (non-heap) pointers.  Assumes that
40959  *  caller has removed the object from heap allocated list or the string
40960  *  intern table, and any weak references (which strings may have) have
40961  *  been already dealt with.
40962  */
40963 
40964 DUK_INTERNAL void duk_free_hobject_inner(duk_heap *heap, duk_hobject *h) {
40965 	DUK_ASSERT(heap != NULL);
40966 	DUK_ASSERT(h != NULL);
40967 
40968 	DUK_FREE(heap, DUK_HOBJECT_GET_PROPS(heap, h));
40969 
40970 	if (DUK_HOBJECT_IS_COMPILEDFUNCTION(h)) {
40971 		duk_hcompiledfunction *f = (duk_hcompiledfunction *) h;
40972 		DUK_UNREF(f);
40973 		/* Currently nothing to free; 'data' is a heap object */
40974 	} else if (DUK_HOBJECT_IS_NATIVEFUNCTION(h)) {
40975 		duk_hnativefunction *f = (duk_hnativefunction *) h;
40976 		DUK_UNREF(f);
40977 		/* Currently nothing to free */
40978 	} else if (DUK_HOBJECT_IS_THREAD(h)) {
40979 		duk_hthread *t = (duk_hthread *) h;
40980 		DUK_FREE(heap, t->valstack);
40981 		DUK_FREE(heap, t->callstack);
40982 		DUK_FREE(heap, t->catchstack);
40983 		/* Don't free h->resumer because it exists in the heap.
40984 		 * Callstack entries also contain function pointers which
40985 		 * are not freed for the same reason.
40986 		 */
40987 
40988 		/* XXX: with 'caller' property the callstack would need
40989 		 * to be unwound to update the 'caller' properties of
40990 		 * functions in the callstack.
40991 		 */
40992 	}
40993 }
40994 
40995 DUK_INTERNAL void duk_free_hbuffer_inner(duk_heap *heap, duk_hbuffer *h) {
40996 	DUK_ASSERT(heap != NULL);
40997 	DUK_ASSERT(h != NULL);
40998 
40999 	if (DUK_HBUFFER_HAS_DYNAMIC(h) && !DUK_HBUFFER_HAS_EXTERNAL(h)) {
41000 		duk_hbuffer_dynamic *g = (duk_hbuffer_dynamic *) h;
41001 		DUK_DDD(DUK_DDDPRINT("free dynamic buffer %p", (void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, g)));
41002 		DUK_FREE(heap, DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, g));
41003 	}
41004 }
41005 
41006 DUK_INTERNAL void duk_free_hstring_inner(duk_heap *heap, duk_hstring *h) {
41007 	DUK_ASSERT(heap != NULL);
41008 	DUK_ASSERT(h != NULL);
41009 
41010 	DUK_UNREF(heap);
41011 	DUK_UNREF(h);
41012 
41013 #if defined(DUK_USE_HSTRING_EXTDATA) && defined(DUK_USE_EXTSTR_FREE)
41014 	if (DUK_HSTRING_HAS_EXTDATA(h)) {
41015 		DUK_DDD(DUK_DDDPRINT("free extstr: hstring %!O, extdata: %p",
41016 		                     h, DUK_HSTRING_GET_EXTDATA((duk_hstring_external *) h)));
41017 		DUK_USE_EXTSTR_FREE(heap->heap_udata, (const void *) DUK_HSTRING_GET_EXTDATA((duk_hstring_external *) h));
41018 	}
41019 #endif
41020 }
41021 
41022 DUK_INTERNAL void duk_heap_free_heaphdr_raw(duk_heap *heap, duk_heaphdr *hdr) {
41023 	DUK_ASSERT(heap);
41024 	DUK_ASSERT(hdr);
41025 
41026 	DUK_DDD(DUK_DDDPRINT("free heaphdr %p, htype %ld", (void *) hdr, (long) DUK_HEAPHDR_GET_TYPE(hdr)));
41027 
41028 	switch ((int) DUK_HEAPHDR_GET_TYPE(hdr)) {
41029 	case DUK_HTYPE_STRING:
41030 		duk_free_hstring_inner(heap, (duk_hstring *) hdr);
41031 		break;
41032 	case DUK_HTYPE_OBJECT:
41033 		duk_free_hobject_inner(heap, (duk_hobject *) hdr);
41034 		break;
41035 	case DUK_HTYPE_BUFFER:
41036 		duk_free_hbuffer_inner(heap, (duk_hbuffer *) hdr);
41037 		break;
41038 	default:
41039 		DUK_UNREACHABLE();
41040 	}
41041 
41042 	DUK_FREE(heap, hdr);
41043 }
41044 
41045 /*
41046  *  Free the heap.
41047  *
41048  *  Frees heap-related non-heap-tracked allocations such as the
41049  *  string intern table; then frees the heap allocated objects;
41050  *  and finally frees the heap structure itself.  Reference counts
41051  *  and GC markers are ignored (and not updated) in this process,
41052  *  and finalizers won't be called.
41053  *
41054  *  The heap pointer and heap object pointers must not be used
41055  *  after this call.
41056  */
41057 
41058 DUK_LOCAL void duk__free_allocated(duk_heap *heap) {
41059 	duk_heaphdr *curr;
41060 	duk_heaphdr *next;
41061 
41062 	curr = heap->heap_allocated;
41063 	while (curr) {
41064 		/* We don't log or warn about freeing zero refcount objects
41065 		 * because they may happen with finalizer processing.
41066 		 */
41067 
41068 		DUK_DDD(DUK_DDDPRINT("FINALFREE (allocated): %!iO",
41069 		                     (duk_heaphdr *) curr));
41070 		next = DUK_HEAPHDR_GET_NEXT(heap, curr);
41071 		duk_heap_free_heaphdr_raw(heap, curr);
41072 		curr = next;
41073 	}
41074 }
41075 
41076 #if defined(DUK_USE_REFERENCE_COUNTING)
41077 DUK_LOCAL void duk__free_refzero_list(duk_heap *heap) {
41078 	duk_heaphdr *curr;
41079 	duk_heaphdr *next;
41080 
41081 	curr = heap->refzero_list;
41082 	while (curr) {
41083 		DUK_DDD(DUK_DDDPRINT("FINALFREE (refzero_list): %!iO",
41084 		                     (duk_heaphdr *) curr));
41085 		next = DUK_HEAPHDR_GET_NEXT(heap, curr);
41086 		duk_heap_free_heaphdr_raw(heap, curr);
41087 		curr = next;
41088 	}
41089 }
41090 #endif
41091 
41092 #if defined(DUK_USE_MARK_AND_SWEEP)
41093 DUK_LOCAL void duk__free_markandsweep_finalize_list(duk_heap *heap) {
41094 	duk_heaphdr *curr;
41095 	duk_heaphdr *next;
41096 
41097 	curr = heap->finalize_list;
41098 	while (curr) {
41099 		DUK_DDD(DUK_DDDPRINT("FINALFREE (finalize_list): %!iO",
41100 		                     (duk_heaphdr *) curr));
41101 		next = DUK_HEAPHDR_GET_NEXT(heap, curr);
41102 		duk_heap_free_heaphdr_raw(heap, curr);
41103 		curr = next;
41104 	}
41105 }
41106 #endif
41107 
41108 DUK_LOCAL void duk__free_stringtable(duk_heap *heap) {
41109 	/* strings are only tracked by stringtable */
41110 	duk_heap_free_strtab(heap);
41111 }
41112 
41113 DUK_LOCAL void duk__free_run_finalizers(duk_heap *heap) {
41114 	duk_hthread *thr;
41115 	duk_heaphdr *curr;
41116 	duk_uint_t round_no;
41117 	duk_size_t count_all;
41118 	duk_size_t count_finalized;
41119 	duk_size_t curr_limit;
41120 
41121 	DUK_ASSERT(heap != NULL);
41122 	DUK_ASSERT(heap->heap_thread != NULL);
41123 
41124 #if defined(DUK_USE_REFERENCE_COUNTING)
41125 	DUK_ASSERT(heap->refzero_list == NULL);  /* refzero not running -> must be empty */
41126 #endif
41127 #if defined(DUK_USE_MARK_AND_SWEEP)
41128 	DUK_ASSERT(heap->finalize_list == NULL);  /* mark-and-sweep not running -> must be empty */
41129 #endif
41130 
41131 	/* XXX: here again finalizer thread is the heap_thread which needs
41132 	 * to be coordinated with finalizer thread fixes.
41133 	 */
41134 	thr = heap->heap_thread;
41135 	DUK_ASSERT(thr != NULL);
41136 
41137 	/* Prevent mark-and-sweep for the pending finalizers, also prevents
41138 	 * refzero handling from moving objects away from the heap_allocated
41139 	 * list.  (The flag meaning is slightly abused here.)
41140 	 */
41141 	DUK_ASSERT(!DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap));
41142 	DUK_HEAP_SET_MARKANDSWEEP_RUNNING(heap);
41143 
41144 	curr_limit = 0;  /* suppress warning, not used */
41145 	for (round_no = 0; ; round_no++) {
41146 		curr = heap->heap_allocated;
41147 		count_all = 0;
41148 		count_finalized = 0;
41149 		while (curr) {
41150 			count_all++;
41151 			if (DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT) {
41152 				/* Only objects in heap_allocated may have finalizers.  Check that
41153 				 * the object itself has a _Finalizer property (own or inherited)
41154 				 * so that we don't execute finalizers for e.g. Proxy objects.
41155 				 */
41156 				DUK_ASSERT(thr != NULL);
41157 				DUK_ASSERT(curr != NULL);
41158 
41159 				if (duk_hobject_hasprop_raw(thr, (duk_hobject *) curr, DUK_HTHREAD_STRING_INT_FINALIZER(thr))) {
41160 					if (!DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) curr)) {
41161 						DUK_ASSERT(DUK_HEAP_HAS_FINALIZER_NORESCUE(heap));  /* maps to finalizer 2nd argument */
41162 						duk_hobject_run_finalizer(thr, (duk_hobject *) curr);
41163 						count_finalized++;
41164 					}
41165 				}
41166 			}
41167 			curr = DUK_HEAPHDR_GET_NEXT(heap, curr);
41168 		}
41169 
41170 		/* Each round of finalizer execution may spawn new finalizable objects
41171 		 * which is normal behavior for some applications.  Allow multiple
41172 		 * rounds of finalization, but use a shrinking limit based on the
41173 		 * first round to detect the case where a runaway finalizer creates
41174 		 * an unbounded amount of new finalizable objects.  Finalizer rescue
41175 		 * is not supported: the semantics are unclear because most of the
41176 		 * objects being finalized here are already reachable.  The finalizer
41177 		 * is given a boolean to indicate that rescue is not possible.
41178 		 *
41179 		 * See discussion in: https://github.com/svaarala/duktape/pull/473
41180 		 */
41181 
41182 		if (round_no == 0) {
41183 			/* Cannot wrap: each object is at least 8 bytes so count is
41184 			 * at most 1/8 of that.
41185 			 */
41186 			curr_limit = count_all * 2;
41187 		} else {
41188 			curr_limit = (curr_limit * 3) / 4;   /* Decrease by 25% every round */
41189 		}
41190 		DUK_D(DUK_DPRINT("finalizer round %ld complete, %ld objects, tried to execute %ld finalizers, current limit is %ld",
41191 		                 (long) round_no, (long) count_all, (long) count_finalized, (long) curr_limit));
41192 
41193 		if (count_finalized == 0) {
41194 			DUK_D(DUK_DPRINT("no more finalizable objects, forced finalization finished"));
41195 			break;
41196 		}
41197 		if (count_finalized >= curr_limit) {
41198 			DUK_D(DUK_DPRINT("finalizer count above limit, potentially runaway finalizer; skip remaining finalizers"));
41199 			break;
41200 		}
41201 	}
41202 
41203 	DUK_ASSERT(DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap));
41204 	DUK_HEAP_CLEAR_MARKANDSWEEP_RUNNING(heap);
41205 }
41206 
41207 DUK_INTERNAL void duk_heap_free(duk_heap *heap) {
41208 	DUK_D(DUK_DPRINT("free heap: %p", (void *) heap));
41209 
41210 #if defined(DUK_USE_DEBUG)
41211 	duk_heap_dump_strtab(heap);
41212 #endif
41213 
41214 #if defined(DUK_USE_DEBUGGER_SUPPORT)
41215 	/* Detach a debugger if attached (can be called multiple times)
41216 	 * safely.
41217 	 */
41218 	/* XXX: Add a flag to reject an attempt to re-attach?  Otherwise
41219 	 * the detached callback may immediately reattach.
41220 	 */
41221 	duk_debug_do_detach(heap);
41222 #endif
41223 
41224 	/* Execute finalizers before freeing the heap, even for reachable
41225 	 * objects, and regardless of whether or not mark-and-sweep is
41226 	 * enabled.  This gives finalizers the chance to free any native
41227 	 * resources like file handles, allocations made outside Duktape,
41228 	 * etc.  This is quite tricky to get right, so that all finalizer
41229 	 * guarantees are honored.
41230 	 *
41231 	 * XXX: this perhaps requires an execution time limit.
41232 	 */
41233 	DUK_D(DUK_DPRINT("execute finalizers before freeing heap"));
41234 #if defined(DUK_USE_MARK_AND_SWEEP)
41235 	/* Run mark-and-sweep a few times just in case (unreachable object
41236 	 * finalizers run already here).  The last round must rescue objects
41237 	 * from the previous round without running any more finalizers.  This
41238 	 * ensures rescued objects get their FINALIZED flag cleared so that
41239 	 * their finalizer is called once more in forced finalization to
41240 	 * satisfy finalizer guarantees.  However, we don't want to run any
41241 	 * more finalizer because that'd required one more loop, and so on.
41242 	 */
41243 	DUK_D(DUK_DPRINT("forced gc #1 in heap destruction"));
41244 	duk_heap_mark_and_sweep(heap, 0);
41245 	DUK_D(DUK_DPRINT("forced gc #2 in heap destruction"));
41246 	duk_heap_mark_and_sweep(heap, 0);
41247 	DUK_D(DUK_DPRINT("forced gc #3 in heap destruction (don't run finalizers)"));
41248 	duk_heap_mark_and_sweep(heap, DUK_MS_FLAG_SKIP_FINALIZERS);  /* skip finalizers; queue finalizable objects to heap_allocated */
41249 #endif
41250 
41251 	DUK_HEAP_SET_FINALIZER_NORESCUE(heap);  /* rescue no longer supported */
41252 	duk__free_run_finalizers(heap);
41253 
41254 	/* Note: heap->heap_thread, heap->curr_thread, and heap->heap_object
41255 	 * are on the heap allocated list.
41256 	 */
41257 
41258 	DUK_D(DUK_DPRINT("freeing heap objects of heap: %p", (void *) heap));
41259 	duk__free_allocated(heap);
41260 
41261 #if defined(DUK_USE_REFERENCE_COUNTING)
41262 	DUK_D(DUK_DPRINT("freeing refzero list of heap: %p", (void *) heap));
41263 	duk__free_refzero_list(heap);
41264 #endif
41265 
41266 #if defined(DUK_USE_MARK_AND_SWEEP)
41267 	DUK_D(DUK_DPRINT("freeing mark-and-sweep finalize list of heap: %p", (void *) heap));
41268 	duk__free_markandsweep_finalize_list(heap);
41269 #endif
41270 
41271 	DUK_D(DUK_DPRINT("freeing string table of heap: %p", (void *) heap));
41272 	duk__free_stringtable(heap);
41273 
41274 	DUK_D(DUK_DPRINT("freeing heap structure: %p", (void *) heap));
41275 	heap->free_func(heap->heap_udata, heap);
41276 }
41277 
41278 /*
41279  *  Allocate a heap.
41280  *
41281  *  String table is initialized with built-in strings from genbuiltins.py,
41282  *  either by dynamically creating the strings or by referring to ROM strings.
41283  */
41284 
41285 #if defined(DUK_USE_ROM_STRINGS)
41286 DUK_LOCAL duk_bool_t duk__init_heap_strings(duk_heap *heap) {
41287 #if defined(DUK_USE_ASSERTIONS)
41288 	duk_small_uint_t i;
41289 #endif
41290 
41291 	/* With ROM-based strings, heap->strs[] and thr->strs[] are omitted
41292 	 * so nothing to initialize for strs[].
41293 	 */
41294 
41295 #if defined(DUK_USE_ASSERTIONS)
41296 	for (i = 0; i < sizeof(duk_rom_strings) / sizeof(const duk_hstring *); i++) {
41297 		duk_uint32_t hash;
41298 		const duk_hstring *h;
41299 		h = duk_rom_strings[i];
41300 		DUK_ASSERT(h != NULL);
41301 		hash = duk_heap_hashstring(heap, (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
41302 		DUK_DD(DUK_DDPRINT("duk_rom_strings[%d] -> hash 0x%08lx, computed 0x%08lx",
41303 		                   (int) i, (unsigned long) DUK_HSTRING_GET_HASH(h), (unsigned long) hash));
41304 		DUK_ASSERT(hash == (duk_uint32_t) DUK_HSTRING_GET_HASH(h));
41305 	}
41306 #endif
41307 	return 1;
41308 }
41309 #else  /* DUK_USE_ROM_STRINGS */
41310 DUK_LOCAL duk_bool_t duk__init_heap_strings(duk_heap *heap) {
41311 	duk_bitdecoder_ctx bd_ctx;
41312 	duk_bitdecoder_ctx *bd = &bd_ctx;  /* convenience */
41313 	duk_small_uint_t i, j;
41314 
41315 	DUK_MEMZERO(&bd_ctx, sizeof(bd_ctx));
41316 	bd->data = (const duk_uint8_t *) duk_strings_data;
41317 	bd->length = (duk_size_t) DUK_STRDATA_DATA_LENGTH;
41318 
41319 	for (i = 0; i < DUK_HEAP_NUM_STRINGS; i++) {
41320 		duk_uint8_t tmp[DUK_STRDATA_MAX_STRLEN];
41321 		duk_hstring *h;
41322 		duk_small_uint_t len;
41323 		duk_small_uint_t mode;
41324 		duk_small_uint_t t;
41325 
41326 		len = duk_bd_decode(bd, 5);
41327 		mode = 32;  /* 0 = uppercase, 32 = lowercase (= 'a' - 'A') */
41328 		for (j = 0; j < len; j++) {
41329 			t = duk_bd_decode(bd, 5);
41330 			if (t < DUK__BITPACK_LETTER_LIMIT) {
41331 				t = t + DUK_ASC_UC_A + mode;
41332 			} else if (t == DUK__BITPACK_UNDERSCORE) {
41333 				t = DUK_ASC_UNDERSCORE;
41334 			} else if (t == DUK__BITPACK_FF) {
41335 				/* Internal keys are prefixed with 0xFF in the stringtable
41336 				 * (which makes them invalid UTF-8 on purpose).
41337 				 */
41338 				t = 0xff;
41339 			} else if (t == DUK__BITPACK_SWITCH1) {
41340 				t = duk_bd_decode(bd, 5);
41341 				DUK_ASSERT_DISABLE(t >= 0);  /* unsigned */
41342 				DUK_ASSERT(t <= 25);
41343 				t = t + DUK_ASC_UC_A + (mode ^ 32);
41344 			} else if (t == DUK__BITPACK_SWITCH) {
41345 				mode = mode ^ 32;
41346 				t = duk_bd_decode(bd, 5);
41347 				DUK_ASSERT_DISABLE(t >= 0);
41348 				DUK_ASSERT(t <= 25);
41349 				t = t + DUK_ASC_UC_A + mode;
41350 			} else if (t == DUK__BITPACK_SEVENBIT) {
41351 				t = duk_bd_decode(bd, 7);
41352 			}
41353 			tmp[j] = (duk_uint8_t) t;
41354 		}
41355 
41356 		/* No need to length check string: it will never exceed even
41357 		 * the 16-bit length maximum.
41358 		 */
41359 		DUK_ASSERT(len <= 0xffffUL);
41360 		DUK_DDD(DUK_DDDPRINT("intern built-in string %ld", (long) i));
41361 		h = duk_heap_string_intern(heap, tmp, len);
41362 		if (!h) {
41363 			goto error;
41364 		}
41365 		DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h));
41366 
41367 		/* Special flags checks.  Since these strings are always
41368 		 * reachable and a string cannot appear twice in the string
41369 		 * table, there's no need to check/set these flags elsewhere.
41370 		 * The 'internal' flag is set by string intern code.
41371 		 */
41372 		if (i == DUK_STRIDX_EVAL || i == DUK_STRIDX_LC_ARGUMENTS) {
41373 			DUK_HSTRING_SET_EVAL_OR_ARGUMENTS(h);
41374 		}
41375 		if (i >= DUK_STRIDX_START_RESERVED && i < DUK_STRIDX_END_RESERVED) {
41376 			DUK_HSTRING_SET_RESERVED_WORD(h);
41377 			if (i >= DUK_STRIDX_START_STRICT_RESERVED) {
41378 				DUK_HSTRING_SET_STRICT_RESERVED_WORD(h);
41379 			}
41380 		}
41381 
41382 		DUK_DDD(DUK_DDDPRINT("interned: %!O", (duk_heaphdr *) h));
41383 
41384 		/* XXX: The incref macro takes a thread pointer but doesn't
41385 		 * use it right now.
41386 		 */
41387 		DUK_HSTRING_INCREF(_never_referenced_, h);
41388 
41389 #if defined(DUK_USE_HEAPPTR16)
41390 		heap->strs16[i] = DUK_USE_HEAPPTR_ENC16(heap->heap_udata, (void *) h);
41391 #else
41392 		heap->strs[i] = h;
41393 #endif
41394 	}
41395 
41396 	return 1;
41397 
41398  error:
41399 	return 0;
41400 }
41401 #endif  /* DUK_USE_ROM_STRINGS */
41402 
41403 DUK_LOCAL duk_bool_t duk__init_heap_thread(duk_heap *heap) {
41404 	duk_hthread *thr;
41405 
41406 	DUK_DD(DUK_DDPRINT("heap init: alloc heap thread"));
41407 	thr = duk_hthread_alloc(heap,
41408 	                        DUK_HOBJECT_FLAG_EXTENSIBLE |
41409 	                        DUK_HOBJECT_FLAG_THREAD |
41410 	                        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_THREAD));
41411 	if (!thr) {
41412 		DUK_D(DUK_DPRINT("failed to alloc heap_thread"));
41413 		return 0;
41414 	}
41415 	thr->state = DUK_HTHREAD_STATE_INACTIVE;
41416 #if defined(DUK_USE_ROM_STRINGS)
41417 	/* No strs[] pointer. */
41418 #else  /* DUK_USE_ROM_STRINGS */
41419 #if defined(DUK_USE_HEAPPTR16)
41420 	thr->strs16 = heap->strs16;
41421 #else
41422 	thr->strs = heap->strs;
41423 #endif
41424 #endif  /* DUK_USE_ROM_STRINGS */
41425 
41426 	heap->heap_thread = thr;
41427 	DUK_HTHREAD_INCREF(thr, thr);  /* Note: first argument not really used */
41428 
41429 	/* 'thr' is now reachable */
41430 
41431 	if (!duk_hthread_init_stacks(heap, thr)) {
41432 		return 0;
41433 	}
41434 
41435 	/* XXX: this may now fail, and is not handled correctly */
41436 	duk_hthread_create_builtin_objects(thr);
41437 
41438 	/* default prototype (Note: 'thr' must be reachable) */
41439 	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, (duk_hobject *) thr, thr->builtins[DUK_BIDX_THREAD_PROTOTYPE]);
41440 
41441 	return 1;
41442 }
41443 
41444 #if defined(DUK_USE_DEBUG)
41445 #define DUK__DUMPSZ(t)  do { \
41446 		DUK_D(DUK_DPRINT("" #t "=%ld", (long) sizeof(t))); \
41447 	} while (0)
41448 
41449 /* These is not 100% because format would need to be non-portable "long long".
41450  * Also print out as doubles to catch cases where the "long" type is not wide
41451  * enough; the limits will then not be printed accurately but the magnitude
41452  * will be correct.
41453  */
41454 #define DUK__DUMPLM_SIGNED_RAW(t,a,b)  do { \
41455 		DUK_D(DUK_DPRINT(t "=[%ld,%ld]=[%lf,%lf]", \
41456 		                 (long) (a), (long) (b), \
41457 		                 (double) (a), (double) (b))); \
41458 	} while (0)
41459 #define DUK__DUMPLM_UNSIGNED_RAW(t,a,b)  do { \
41460 		DUK_D(DUK_DPRINT(t "=[%lu,%lu]=[%lf,%lf]", \
41461 		                 (unsigned long) (a), (unsigned long) (b), \
41462 		                 (double) (a), (double) (b))); \
41463 	} while (0)
41464 #define DUK__DUMPLM_SIGNED(t)  do { \
41465 		DUK__DUMPLM_SIGNED_RAW("DUK_" #t "_{MIN,MAX}", DUK_##t##_MIN, DUK_##t##_MAX); \
41466 	} while (0)
41467 #define DUK__DUMPLM_UNSIGNED(t)  do { \
41468 		DUK__DUMPLM_UNSIGNED_RAW("DUK_" #t "_{MIN,MAX}", DUK_##t##_MIN, DUK_##t##_MAX); \
41469 	} while (0)
41470 
41471 DUK_LOCAL void duk__dump_type_sizes(void) {
41472 	DUK_D(DUK_DPRINT("sizeof()"));
41473 
41474 	/* basic platform types */
41475 	DUK__DUMPSZ(char);
41476 	DUK__DUMPSZ(short);
41477 	DUK__DUMPSZ(int);
41478 	DUK__DUMPSZ(long);
41479 	DUK__DUMPSZ(double);
41480 	DUK__DUMPSZ(void *);
41481 	DUK__DUMPSZ(size_t);
41482 
41483 	/* basic types from duk_features.h */
41484 	DUK__DUMPSZ(duk_uint8_t);
41485 	DUK__DUMPSZ(duk_int8_t);
41486 	DUK__DUMPSZ(duk_uint16_t);
41487 	DUK__DUMPSZ(duk_int16_t);
41488 	DUK__DUMPSZ(duk_uint32_t);
41489 	DUK__DUMPSZ(duk_int32_t);
41490 	DUK__DUMPSZ(duk_uint64_t);
41491 	DUK__DUMPSZ(duk_int64_t);
41492 	DUK__DUMPSZ(duk_uint_least8_t);
41493 	DUK__DUMPSZ(duk_int_least8_t);
41494 	DUK__DUMPSZ(duk_uint_least16_t);
41495 	DUK__DUMPSZ(duk_int_least16_t);
41496 	DUK__DUMPSZ(duk_uint_least32_t);
41497 	DUK__DUMPSZ(duk_int_least32_t);
41498 #if defined(DUK_USE_64BIT_OPS)
41499 	DUK__DUMPSZ(duk_uint_least64_t);
41500 	DUK__DUMPSZ(duk_int_least64_t);
41501 #endif
41502 	DUK__DUMPSZ(duk_uint_fast8_t);
41503 	DUK__DUMPSZ(duk_int_fast8_t);
41504 	DUK__DUMPSZ(duk_uint_fast16_t);
41505 	DUK__DUMPSZ(duk_int_fast16_t);
41506 	DUK__DUMPSZ(duk_uint_fast32_t);
41507 	DUK__DUMPSZ(duk_int_fast32_t);
41508 #if defined(DUK_USE_64BIT_OPS)
41509 	DUK__DUMPSZ(duk_uint_fast64_t);
41510 	DUK__DUMPSZ(duk_int_fast64_t);
41511 #endif
41512 	DUK__DUMPSZ(duk_uintptr_t);
41513 	DUK__DUMPSZ(duk_intptr_t);
41514 	DUK__DUMPSZ(duk_uintmax_t);
41515 	DUK__DUMPSZ(duk_intmax_t);
41516 	DUK__DUMPSZ(duk_double_t);
41517 
41518 	/* important chosen base types */
41519 	DUK__DUMPSZ(duk_int_t);
41520 	DUK__DUMPSZ(duk_uint_t);
41521 	DUK__DUMPSZ(duk_int_fast_t);
41522 	DUK__DUMPSZ(duk_uint_fast_t);
41523 	DUK__DUMPSZ(duk_small_int_t);
41524 	DUK__DUMPSZ(duk_small_uint_t);
41525 	DUK__DUMPSZ(duk_small_int_fast_t);
41526 	DUK__DUMPSZ(duk_small_uint_fast_t);
41527 
41528 	/* some derived types */
41529 	DUK__DUMPSZ(duk_codepoint_t);
41530 	DUK__DUMPSZ(duk_ucodepoint_t);
41531 	DUK__DUMPSZ(duk_idx_t);
41532 	DUK__DUMPSZ(duk_errcode_t);
41533 	DUK__DUMPSZ(duk_uarridx_t);
41534 
41535 	/* tval */
41536 	DUK__DUMPSZ(duk_double_union);
41537 	DUK__DUMPSZ(duk_tval);
41538 
41539 	/* structs from duk_forwdecl.h */
41540 	DUK__DUMPSZ(duk_jmpbuf);  /* just one 'int' for C++ exceptions */
41541 	DUK__DUMPSZ(duk_heaphdr);
41542 	DUK__DUMPSZ(duk_heaphdr_string);
41543 	DUK__DUMPSZ(duk_hstring);
41544 	DUK__DUMPSZ(duk_hstring_external);
41545 	DUK__DUMPSZ(duk_hobject);
41546 	DUK__DUMPSZ(duk_hcompiledfunction);
41547 	DUK__DUMPSZ(duk_hnativefunction);
41548 	DUK__DUMPSZ(duk_hthread);
41549 	DUK__DUMPSZ(duk_hbuffer);
41550 	DUK__DUMPSZ(duk_hbuffer_fixed);
41551 	DUK__DUMPSZ(duk_hbuffer_dynamic);
41552 	DUK__DUMPSZ(duk_hbuffer_external);
41553 	DUK__DUMPSZ(duk_propaccessor);
41554 	DUK__DUMPSZ(duk_propvalue);
41555 	DUK__DUMPSZ(duk_propdesc);
41556 	DUK__DUMPSZ(duk_heap);
41557 #if defined(DUK_USE_STRTAB_CHAIN)
41558 	DUK__DUMPSZ(duk_strtab_entry);
41559 #endif
41560 	DUK__DUMPSZ(duk_activation);
41561 	DUK__DUMPSZ(duk_catcher);
41562 	DUK__DUMPSZ(duk_strcache);
41563 	DUK__DUMPSZ(duk_ljstate);
41564 	DUK__DUMPSZ(duk_fixedbuffer);
41565 	DUK__DUMPSZ(duk_bitdecoder_ctx);
41566 	DUK__DUMPSZ(duk_bitencoder_ctx);
41567 	DUK__DUMPSZ(duk_token);
41568 	DUK__DUMPSZ(duk_re_token);
41569 	DUK__DUMPSZ(duk_lexer_point);
41570 	DUK__DUMPSZ(duk_lexer_ctx);
41571 	DUK__DUMPSZ(duk_compiler_instr);
41572 	DUK__DUMPSZ(duk_compiler_func);
41573 	DUK__DUMPSZ(duk_compiler_ctx);
41574 	DUK__DUMPSZ(duk_re_matcher_ctx);
41575 	DUK__DUMPSZ(duk_re_compiler_ctx);
41576 }
41577 DUK_LOCAL void duk__dump_type_limits(void) {
41578 	DUK_D(DUK_DPRINT("limits"));
41579 
41580 	/* basic types */
41581 	DUK__DUMPLM_SIGNED(INT8);
41582 	DUK__DUMPLM_UNSIGNED(UINT8);
41583 	DUK__DUMPLM_SIGNED(INT_FAST8);
41584 	DUK__DUMPLM_UNSIGNED(UINT_FAST8);
41585 	DUK__DUMPLM_SIGNED(INT_LEAST8);
41586 	DUK__DUMPLM_UNSIGNED(UINT_LEAST8);
41587 	DUK__DUMPLM_SIGNED(INT16);
41588 	DUK__DUMPLM_UNSIGNED(UINT16);
41589 	DUK__DUMPLM_SIGNED(INT_FAST16);
41590 	DUK__DUMPLM_UNSIGNED(UINT_FAST16);
41591 	DUK__DUMPLM_SIGNED(INT_LEAST16);
41592 	DUK__DUMPLM_UNSIGNED(UINT_LEAST16);
41593 	DUK__DUMPLM_SIGNED(INT32);
41594 	DUK__DUMPLM_UNSIGNED(UINT32);
41595 	DUK__DUMPLM_SIGNED(INT_FAST32);
41596 	DUK__DUMPLM_UNSIGNED(UINT_FAST32);
41597 	DUK__DUMPLM_SIGNED(INT_LEAST32);
41598 	DUK__DUMPLM_UNSIGNED(UINT_LEAST32);
41599 #if defined(DUK_USE_64BIT_OPS)
41600 	DUK__DUMPLM_SIGNED(INT64);
41601 	DUK__DUMPLM_UNSIGNED(UINT64);
41602 	DUK__DUMPLM_SIGNED(INT_FAST64);
41603 	DUK__DUMPLM_UNSIGNED(UINT_FAST64);
41604 	DUK__DUMPLM_SIGNED(INT_LEAST64);
41605 	DUK__DUMPLM_UNSIGNED(UINT_LEAST64);
41606 #endif
41607 	DUK__DUMPLM_SIGNED(INTPTR);
41608 	DUK__DUMPLM_UNSIGNED(UINTPTR);
41609 	DUK__DUMPLM_SIGNED(INTMAX);
41610 	DUK__DUMPLM_UNSIGNED(UINTMAX);
41611 
41612 	/* derived types */
41613 	DUK__DUMPLM_SIGNED(INT);
41614 	DUK__DUMPLM_UNSIGNED(UINT);
41615 	DUK__DUMPLM_SIGNED(INT_FAST);
41616 	DUK__DUMPLM_UNSIGNED(UINT_FAST);
41617 	DUK__DUMPLM_SIGNED(SMALL_INT);
41618 	DUK__DUMPLM_UNSIGNED(SMALL_UINT);
41619 	DUK__DUMPLM_SIGNED(SMALL_INT_FAST);
41620 	DUK__DUMPLM_UNSIGNED(SMALL_UINT_FAST);
41621 }
41622 #undef DUK__DUMPSZ
41623 #undef DUK__DUMPLM_SIGNED_RAW
41624 #undef DUK__DUMPLM_UNSIGNED_RAW
41625 #undef DUK__DUMPLM_SIGNED
41626 #undef DUK__DUMPLM_UNSIGNED
41627 
41628 DUK_LOCAL void duk__dump_misc_options(void) {
41629 	DUK_D(DUK_DPRINT("DUK_VERSION: %ld", (long) DUK_VERSION));
41630 	DUK_D(DUK_DPRINT("DUK_GIT_DESCRIBE: %s", DUK_GIT_DESCRIBE));
41631 	DUK_D(DUK_DPRINT("OS string: %s", DUK_USE_OS_STRING));
41632 	DUK_D(DUK_DPRINT("architecture string: %s", DUK_USE_ARCH_STRING));
41633 	DUK_D(DUK_DPRINT("compiler string: %s", DUK_USE_COMPILER_STRING));
41634 #if defined(DUK_USE_PACKED_TVAL)
41635 	DUK_D(DUK_DPRINT("DUK_USE_PACKED_TVAL: yes"));
41636 #else
41637 	DUK_D(DUK_DPRINT("DUK_USE_PACKED_TVAL: no"));
41638 #endif
41639 #if defined(DUK_USE_VARIADIC_MACROS)
41640 	DUK_D(DUK_DPRINT("DUK_USE_VARIADIC_MACROS: yes"));
41641 #else
41642 	DUK_D(DUK_DPRINT("DUK_USE_VARIADIC_MACROS: no"));
41643 #endif
41644 #if defined(DUK_USE_INTEGER_LE)
41645 	DUK_D(DUK_DPRINT("integer endianness: little"));
41646 #elif defined(DUK_USE_INTEGER_ME)
41647 	DUK_D(DUK_DPRINT("integer endianness: mixed"));
41648 #elif defined(DUK_USE_INTEGER_BE)
41649 	DUK_D(DUK_DPRINT("integer endianness: big"));
41650 #else
41651 	DUK_D(DUK_DPRINT("integer endianness: ???"));
41652 #endif
41653 #if defined(DUK_USE_DOUBLE_LE)
41654 	DUK_D(DUK_DPRINT("IEEE double endianness: little"));
41655 #elif defined(DUK_USE_DOUBLE_ME)
41656 	DUK_D(DUK_DPRINT("IEEE double endianness: mixed"));
41657 #elif defined(DUK_USE_DOUBLE_BE)
41658 	DUK_D(DUK_DPRINT("IEEE double endianness: big"));
41659 #else
41660 	DUK_D(DUK_DPRINT("IEEE double endianness: ???"));
41661 #endif
41662 }
41663 #endif  /* DUK_USE_DEBUG */
41664 
41665 DUK_INTERNAL
41666 duk_heap *duk_heap_alloc(duk_alloc_function alloc_func,
41667                          duk_realloc_function realloc_func,
41668                          duk_free_function free_func,
41669                          void *heap_udata,
41670                          duk_fatal_function fatal_func) {
41671 	duk_heap *res = NULL;
41672 
41673 	/* Silence a few global unused warnings here. */
41674 	DUK_UNREF(duk_str_unsupported);
41675 
41676 	DUK_D(DUK_DPRINT("allocate heap"));
41677 
41678 	/*
41679 	 *  Debug dump type sizes
41680 	 */
41681 
41682 #if defined(DUK_USE_DEBUG)
41683 	duk__dump_misc_options();
41684 	duk__dump_type_sizes();
41685 	duk__dump_type_limits();
41686 #endif
41687 
41688 	/*
41689 	 *  If selftests enabled, run them as early as possible
41690 	 */
41691 #if defined(DUK_USE_SELF_TESTS)
41692 	DUK_D(DUK_DPRINT("running self tests"));
41693 	duk_selftest_run_tests();
41694 	DUK_D(DUK_DPRINT("self tests passed"));
41695 #endif
41696 
41697 	/*
41698 	 *  Computed values (e.g. INFINITY)
41699 	 */
41700 
41701 #if defined(DUK_USE_COMPUTED_NAN)
41702 	do {
41703 		/* Workaround for some exotic platforms where NAN is missing
41704 		 * and the expression (0.0 / 0.0) does NOT result in a NaN.
41705 		 * Such platforms use the global 'duk_computed_nan' which must
41706 		 * be initialized at runtime.  Use 'volatile' to ensure that
41707 		 * the compiler will actually do the computation and not try
41708 		 * to do constant folding which might result in the original
41709 		 * problem.
41710 		 */
41711 		volatile double dbl1 = 0.0;
41712 		volatile double dbl2 = 0.0;
41713 		duk_computed_nan = dbl1 / dbl2;
41714 	} while (0);
41715 #endif
41716 
41717 #if defined(DUK_USE_COMPUTED_INFINITY)
41718 	do {
41719 		/* Similar workaround for INFINITY. */
41720 		volatile double dbl1 = 1.0;
41721 		volatile double dbl2 = 0.0;
41722 		duk_computed_infinity = dbl1 / dbl2;
41723 	} while (0);
41724 #endif
41725 
41726 	/*
41727 	 *  Allocate heap struct
41728 	 *
41729 	 *  Use a raw call, all macros expect the heap to be initialized
41730 	 */
41731 
41732 	res = (duk_heap *) alloc_func(heap_udata, sizeof(duk_heap));
41733 	if (!res) {
41734 		goto error;
41735 	}
41736 
41737 	/*
41738 	 *  Zero the struct, and start initializing roughly in order
41739 	 */
41740 
41741 	DUK_MEMZERO(res, sizeof(*res));
41742 
41743 	/* explicit NULL inits */
41744 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
41745 	res->heap_udata = NULL;
41746 	res->heap_allocated = NULL;
41747 #if defined(DUK_USE_REFERENCE_COUNTING)
41748 	res->refzero_list = NULL;
41749 	res->refzero_list_tail = NULL;
41750 #endif
41751 #if defined(DUK_USE_MARK_AND_SWEEP)
41752 	res->finalize_list = NULL;
41753 #endif
41754 	res->heap_thread = NULL;
41755 	res->curr_thread = NULL;
41756 	res->heap_object = NULL;
41757 #if defined(DUK_USE_STRTAB_CHAIN)
41758 	/* nothing to NULL */
41759 #elif defined(DUK_USE_STRTAB_PROBE)
41760 #if defined(DUK_USE_HEAPPTR16)
41761 	res->strtable16 = (duk_uint16_t *) NULL;
41762 #else
41763 	res->strtable = (duk_hstring **) NULL;
41764 #endif
41765 #endif
41766 #if defined(DUK_USE_ROM_STRINGS)
41767 	/* no res->strs[] */
41768 #else  /* DUK_USE_ROM_STRINGS */
41769 #if defined(DUK_USE_HEAPPTR16)
41770 	/* res->strs16[] is zeroed and zero decodes to NULL, so no NULL inits. */
41771 #else
41772 	{
41773 		duk_small_uint_t i;
41774 	        for (i = 0; i < DUK_HEAP_NUM_STRINGS; i++) {
41775 			res->strs[i] = NULL;
41776 	        }
41777 	}
41778 #endif
41779 #endif  /* DUK_USE_ROM_STRINGS */
41780 #if defined(DUK_USE_DEBUGGER_SUPPORT)
41781 	res->dbg_read_cb = NULL;
41782 	res->dbg_write_cb = NULL;
41783 	res->dbg_peek_cb = NULL;
41784 	res->dbg_read_flush_cb = NULL;
41785 	res->dbg_write_flush_cb = NULL;
41786 	res->dbg_request_cb = NULL;
41787 	res->dbg_udata = NULL;
41788 	res->dbg_step_thread = NULL;
41789 #endif
41790 #endif  /* DUK_USE_EXPLICIT_NULL_INIT */
41791 
41792 	res->alloc_func = alloc_func;
41793 	res->realloc_func = realloc_func;
41794 	res->free_func = free_func;
41795 	res->heap_udata = heap_udata;
41796 	res->fatal_func = fatal_func;
41797 
41798 #if defined(DUK_USE_HEAPPTR16)
41799 	/* XXX: zero assumption */
41800 	res->heapptr_null16 = DUK_USE_HEAPPTR_ENC16(res->heap_udata, (void *) NULL);
41801 	res->heapptr_deleted16 = DUK_USE_HEAPPTR_ENC16(res->heap_udata, (void *) DUK_STRTAB_DELETED_MARKER(res));
41802 #endif
41803 
41804 	/* res->mark_and_sweep_trigger_counter == 0 -> now causes immediate GC; which is OK */
41805 
41806 	res->call_recursion_depth = 0;
41807 	res->call_recursion_limit = DUK_USE_NATIVE_CALL_RECLIMIT;
41808 
41809 	/* XXX: use the pointer as a seed for now: mix in time at least */
41810 
41811 	/* The casts through duk_intr_pt is to avoid the following GCC warning:
41812 	 *
41813 	 *   warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
41814 	 *
41815 	 * This still generates a /Wp64 warning on VS2010 when compiling for x86.
41816 	 */
41817 #if defined(DUK_USE_ROM_STRINGS)
41818 	/* XXX: make a common DUK_USE_ option, and allow custom fixed seed? */
41819 	DUK_D(DUK_DPRINT("using rom strings, force heap hash_seed to fixed value 0x%08lx", (long) DUK__FIXED_HASH_SEED));
41820 	res->hash_seed = (duk_uint32_t) DUK__FIXED_HASH_SEED;
41821 #else  /* DUK_USE_ROM_STRINGS */
41822 	res->hash_seed = (duk_uint32_t) (duk_intptr_t) res;
41823 #if !defined(DUK_USE_STRHASH_DENSE)
41824 	res->hash_seed ^= 5381;  /* Bernstein hash init value is normally 5381; XOR it in in case pointer low bits are 0 */
41825 #endif
41826 #endif  /* DUK_USE_ROM_STRINGS */
41827 	res->rnd_state = (duk_uint32_t) (duk_intptr_t) res;
41828 
41829 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
41830 	res->lj.jmpbuf_ptr = NULL;
41831 #endif
41832 	DUK_ASSERT(res->lj.type == DUK_LJ_TYPE_UNKNOWN);  /* zero */
41833 
41834 	DUK_TVAL_SET_UNDEFINED(&res->lj.value1);
41835 	DUK_TVAL_SET_UNDEFINED(&res->lj.value2);
41836 
41837 #if (DUK_STRTAB_INITIAL_SIZE < DUK_UTIL_MIN_HASH_PRIME)
41838 #error initial heap stringtable size is defined incorrectly
41839 #endif
41840 
41841 	/*
41842 	 *  Init stringtable: fixed variant
41843 	 */
41844 
41845 #if defined(DUK_USE_STRTAB_CHAIN)
41846 	DUK_MEMZERO(res->strtable, sizeof(duk_strtab_entry) * DUK_STRTAB_CHAIN_SIZE);
41847 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
41848 	{
41849 		duk_small_uint_t i;
41850 	        for (i = 0; i < DUK_STRTAB_CHAIN_SIZE; i++) {
41851 #if defined(DUK_USE_HEAPPTR16)
41852 			res->strtable[i].u.str16 = res->heapptr_null16;
41853 #else
41854 			res->strtable[i].u.str = NULL;
41855 #endif
41856 	        }
41857 	}
41858 #endif  /* DUK_USE_EXPLICIT_NULL_INIT */
41859 #endif  /* DUK_USE_STRTAB_CHAIN */
41860 
41861 	/*
41862 	 *  Init stringtable: probe variant
41863 	 */
41864 
41865 #if defined(DUK_USE_STRTAB_PROBE)
41866 #if defined(DUK_USE_HEAPPTR16)
41867 	res->strtable16 = (duk_uint16_t *) alloc_func(heap_udata, sizeof(duk_uint16_t) * DUK_STRTAB_INITIAL_SIZE);
41868 	if (!res->strtable16) {
41869 		goto error;
41870 	}
41871 #else  /* DUK_USE_HEAPPTR16 */
41872 	res->strtable = (duk_hstring **) alloc_func(heap_udata, sizeof(duk_hstring *) * DUK_STRTAB_INITIAL_SIZE);
41873 	if (!res->strtable) {
41874 		goto error;
41875 	}
41876 #endif  /* DUK_USE_HEAPPTR16 */
41877 	res->st_size = DUK_STRTAB_INITIAL_SIZE;
41878 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
41879 	{
41880 		duk_small_uint_t i;
41881 		DUK_ASSERT(res->st_size == DUK_STRTAB_INITIAL_SIZE);
41882 	        for (i = 0; i < DUK_STRTAB_INITIAL_SIZE; i++) {
41883 #if defined(DUK_USE_HEAPPTR16)
41884 			res->strtable16[i] = res->heapptr_null16;
41885 #else
41886 			res->strtable[i] = NULL;
41887 #endif
41888 	        }
41889 	}
41890 #else  /* DUK_USE_EXPLICIT_NULL_INIT */
41891 #if defined(DUK_USE_HEAPPTR16)
41892 	DUK_MEMZERO(res->strtable16, sizeof(duk_uint16_t) * DUK_STRTAB_INITIAL_SIZE);
41893 #else
41894 	DUK_MEMZERO(res->strtable, sizeof(duk_hstring *) * DUK_STRTAB_INITIAL_SIZE);
41895 #endif
41896 #endif  /* DUK_USE_EXPLICIT_NULL_INIT */
41897 #endif  /* DUK_USE_STRTAB_PROBE */
41898 
41899 	/*
41900 	 *  Init stringcache
41901 	 */
41902 
41903 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
41904 	{
41905 		duk_small_uint_t i;
41906 		for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
41907 			res->strcache[i].h = NULL;
41908 		}
41909 	}
41910 #endif
41911 
41912 	/* XXX: error handling is incomplete.  It would be cleanest if
41913 	 * there was a setjmp catchpoint, so that all init code could
41914 	 * freely throw errors.  If that were the case, the return code
41915 	 * passing here could be removed.
41916 	 */
41917 
41918 	/*
41919 	 *  Init built-in strings
41920 	 */
41921 
41922 	DUK_DD(DUK_DDPRINT("HEAP: INIT STRINGS"));
41923 	if (!duk__init_heap_strings(res)) {
41924 		goto error;
41925 	}
41926 
41927 	/*
41928 	 *  Init the heap thread
41929 	 */
41930 
41931 	DUK_DD(DUK_DDPRINT("HEAP: INIT HEAP THREAD"));
41932 	if (!duk__init_heap_thread(res)) {
41933 		goto error;
41934 	}
41935 
41936 	DUK_ASSERT(res->heap_thread != NULL);
41937 	res->rnd_state ^= (duk_uint32_t) DUK_USE_DATE_GET_NOW((duk_context *) res->heap_thread);
41938 
41939 	/*
41940 	 *  Init the heap object
41941 	 */
41942 
41943 	DUK_DD(DUK_DDPRINT("HEAP: INIT HEAP OBJECT"));
41944 	DUK_ASSERT(res->heap_thread != NULL);
41945 	res->heap_object = duk_hobject_alloc(res, DUK_HOBJECT_FLAG_EXTENSIBLE |
41946 	                                          DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT));
41947 	if (!res->heap_object) {
41948 		goto error;
41949 	}
41950 	DUK_HOBJECT_INCREF(res->heap_thread, res->heap_object);
41951 
41952 	/*
41953 	 *  All done
41954 	 */
41955 
41956 	DUK_D(DUK_DPRINT("allocated heap: %p", (void *) res));
41957 	return res;
41958 
41959  error:
41960 	DUK_D(DUK_DPRINT("heap allocation failed"));
41961 
41962 	if (res) {
41963 		/* assumes that allocated pointers and alloc funcs are valid
41964 		 * if res exists
41965 		 */
41966 		DUK_ASSERT(res->alloc_func != NULL);
41967 		DUK_ASSERT(res->realloc_func != NULL);
41968 		DUK_ASSERT(res->free_func != NULL);
41969 		duk_heap_free(res);
41970 	}
41971 	return NULL;
41972 }
41973 
41974 #undef DUK__BITPACK_LETTER_LIMIT
41975 #undef DUK__BITPACK_UNDERSCORE
41976 #undef DUK__BITPACK_FF
41977 #undef DUK__BITPACK_SWITCH1
41978 #undef DUK__BITPACK_SWITCH
41979 #undef DUK__BITPACK_SEVENBIT
41980 #undef DUK__FIXED_HASH_SEED
41981 /*
41982  *  String hash computation (interning).
41983  *
41984  *  String hashing is performance critical because a string hash is computed
41985  *  for all new strings which are candidates to be added to the string table.
41986  *  However, strings actually added to the string table go through a codepoint
41987  *  length calculation which dominates performance because it goes through
41988  *  every byte of the input string (but only for strings added).
41989  *
41990  *  The string hash algorithm should be fast, but on the other hand provide
41991  *  good enough hashes to ensure both string table and object property table
41992  *  hash tables work reasonably well (i.e., there aren't too many collisions
41993  *  with real world inputs).  Unless the hash is cryptographic, it's always
41994  *  possible to craft inputs with maximal hash collisions.
41995  *
41996  *  NOTE: The hash algorithms must match src/dukutil.py:duk_heap_hashstring()
41997  *  for ROM string support!
41998  */
41999 
42000 /* include removed: duk_internal.h */
42001 
42002 #if defined(DUK_USE_STRHASH_DENSE)
42003 /* Constants for duk_hashstring(). */
42004 #define DUK__STRHASH_SHORTSTRING   4096L
42005 #define DUK__STRHASH_MEDIUMSTRING  (256L * 1024L)
42006 #define DUK__STRHASH_BLOCKSIZE     256L
42007 
42008 DUK_INTERNAL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const duk_uint8_t *str, duk_size_t len) {
42009 	duk_uint32_t hash;
42010 
42011 	/* Use Murmurhash2 directly for short strings, and use "block skipping"
42012 	 * for long strings: hash an initial part and then sample the rest of
42013 	 * the string with reasonably sized chunks.  An initial offset for the
42014 	 * sampling is computed based on a hash of the initial part of the string;
42015 	 * this is done to (usually) avoid the case where all long strings have
42016 	 * certain offset ranges which are never sampled.
42017 	 *
42018 	 * Skip should depend on length and bound the total time to roughly
42019 	 * logarithmic.  With current values:
42020 	 *
42021 	 *   1M string => 256 * 241 = 61696 bytes (0.06M) of hashing
42022 	 *   1G string => 256 * 16321 = 4178176 bytes (3.98M) of hashing
42023 	 *
42024 	 * XXX: It would be better to compute the skip offset more "smoothly"
42025 	 * instead of having a few boundary values.
42026 	 */
42027 
42028 	/* note: mixing len into seed improves hashing when skipping */
42029 	duk_uint32_t str_seed = heap->hash_seed ^ ((duk_uint32_t) len);
42030 
42031 	if (len <= DUK__STRHASH_SHORTSTRING) {
42032 		hash = duk_util_hashbytes(str, len, str_seed);
42033 	} else {
42034 		duk_size_t off;
42035 		duk_size_t skip;
42036 
42037 		if (len <= DUK__STRHASH_MEDIUMSTRING) {
42038 			skip = (duk_size_t) (16 * DUK__STRHASH_BLOCKSIZE + DUK__STRHASH_BLOCKSIZE);
42039 		} else {
42040 			skip = (duk_size_t) (256 * DUK__STRHASH_BLOCKSIZE + DUK__STRHASH_BLOCKSIZE);
42041 		}
42042 
42043 		hash = duk_util_hashbytes(str, (duk_size_t) DUK__STRHASH_SHORTSTRING, str_seed);
42044 		off = DUK__STRHASH_SHORTSTRING + (skip * (hash % 256)) / 256;
42045 
42046 		/* XXX: inefficient loop */
42047 		while (off < len) {
42048 			duk_size_t left = len - off;
42049 			duk_size_t now = (duk_size_t) (left > DUK__STRHASH_BLOCKSIZE ? DUK__STRHASH_BLOCKSIZE : left);
42050 			hash ^= duk_util_hashbytes(str + off, now, str_seed);
42051 			off += skip;
42052 		}
42053 	}
42054 
42055 #if defined(DUK_USE_STRHASH16)
42056 	/* Truncate to 16 bits here, so that a computed hash can be compared
42057 	 * against a hash stored in a 16-bit field.
42058 	 */
42059 	hash &= 0x0000ffffUL;
42060 #endif
42061 	return hash;
42062 }
42063 
42064 #undef DUK__STRHASH_SHORTSTRING
42065 #undef DUK__STRHASH_MEDIUMSTRING
42066 #undef DUK__STRHASH_BLOCKSIZE
42067 #else  /* DUK_USE_STRHASH_DENSE */
42068 DUK_INTERNAL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const duk_uint8_t *str, duk_size_t len) {
42069 	duk_uint32_t hash;
42070 	duk_size_t step;
42071 	duk_size_t off;
42072 
42073 	/* Slightly modified "Bernstein hash" from:
42074 	 *
42075 	 *     http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx
42076 	 *
42077 	 * Modifications: string skipping and reverse direction similar to
42078 	 * Lua 5.1.5, and different hash initializer.
42079 	 *
42080 	 * The reverse direction ensures last byte it always included in the
42081 	 * hash which is a good default as changing parts of the string are
42082 	 * more often in the suffix than in the prefix.
42083 	 */
42084 
42085 	hash = heap->hash_seed ^ ((duk_uint32_t) len);  /* Bernstein hash init value is normally 5381 */
42086 	step = (len >> DUK_USE_STRHASH_SKIP_SHIFT) + 1;
42087 	for (off = len; off >= step; off -= step) {
42088 		DUK_ASSERT(off >= 1);  /* off >= step, and step >= 1 */
42089 		hash = (hash * 33) + str[off - 1];
42090 	}
42091 
42092 #if defined(DUK_USE_STRHASH16)
42093 	/* Truncate to 16 bits here, so that a computed hash can be compared
42094 	 * against a hash stored in a 16-bit field.
42095 	 */
42096 	hash &= 0x0000ffffUL;
42097 #endif
42098 	return hash;
42099 }
42100 #endif  /* DUK_USE_STRHASH_DENSE */
42101 /*
42102  *  Mark-and-sweep garbage collection.
42103  */
42104 
42105 /* include removed: duk_internal.h */
42106 
42107 #ifdef DUK_USE_MARK_AND_SWEEP
42108 
42109 DUK_LOCAL_DECL void duk__mark_heaphdr(duk_heap *heap, duk_heaphdr *h);
42110 DUK_LOCAL_DECL void duk__mark_tval(duk_heap *heap, duk_tval *tv);
42111 
42112 /*
42113  *  Misc
42114  */
42115 
42116 /* Select a thread for mark-and-sweep use.
42117  *
42118  * XXX: This needs to change later.
42119  */
42120 DUK_LOCAL duk_hthread *duk__get_temp_hthread(duk_heap *heap) {
42121 	if (heap->curr_thread) {
42122 		return heap->curr_thread;
42123 	}
42124 	return heap->heap_thread;  /* may be NULL, too */
42125 }
42126 
42127 /*
42128  *  Marking functions for heap types: mark children recursively
42129  */
42130 
42131 DUK_LOCAL void duk__mark_hstring(duk_heap *heap, duk_hstring *h) {
42132 	DUK_UNREF(heap);
42133 	DUK_UNREF(h);
42134 
42135 	DUK_DDD(DUK_DDDPRINT("duk__mark_hstring: %p", (void *) h));
42136 	DUK_ASSERT(h);
42137 
42138 	/* nothing to process */
42139 }
42140 
42141 DUK_LOCAL void duk__mark_hobject(duk_heap *heap, duk_hobject *h) {
42142 	duk_uint_fast32_t i;
42143 
42144 	DUK_DDD(DUK_DDDPRINT("duk__mark_hobject: %p", (void *) h));
42145 
42146 	DUK_ASSERT(h);
42147 
42148 	/* XXX: use advancing pointers instead of index macros -> faster and smaller? */
42149 
42150 	for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h); i++) {
42151 		duk_hstring *key = DUK_HOBJECT_E_GET_KEY(heap, h, i);
42152 		if (!key) {
42153 			continue;
42154 		}
42155 		duk__mark_heaphdr(heap, (duk_heaphdr *) key);
42156 		if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, h, i)) {
42157 			duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.get);
42158 			duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.set);
42159 		} else {
42160 			duk__mark_tval(heap, &DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->v);
42161 		}
42162 	}
42163 
42164 	for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(h); i++) {
42165 		duk__mark_tval(heap, DUK_HOBJECT_A_GET_VALUE_PTR(heap, h, i));
42166 	}
42167 
42168 	/* hash part is a 'weak reference' and does not contribute */
42169 
42170 	duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HOBJECT_GET_PROTOTYPE(heap, h));
42171 
42172 	if (DUK_HOBJECT_IS_COMPILEDFUNCTION(h)) {
42173 		duk_hcompiledfunction *f = (duk_hcompiledfunction *) h;
42174 		duk_tval *tv, *tv_end;
42175 		duk_hobject **fn, **fn_end;
42176 
42177 		/* 'data' is reachable through every compiled function which
42178 		 * contains a reference.
42179 		 */
42180 
42181 		duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HCOMPILEDFUNCTION_GET_DATA(heap, f));
42182 
42183 		if (DUK_HCOMPILEDFUNCTION_GET_DATA(heap, f) != NULL) {
42184 			tv = DUK_HCOMPILEDFUNCTION_GET_CONSTS_BASE(heap, f);
42185 			tv_end = DUK_HCOMPILEDFUNCTION_GET_CONSTS_END(heap, f);
42186 			while (tv < tv_end) {
42187 				duk__mark_tval(heap, tv);
42188 				tv++;
42189 			}
42190 
42191 			fn = DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE(heap, f);
42192 			fn_end = DUK_HCOMPILEDFUNCTION_GET_FUNCS_END(heap, f);
42193 			while (fn < fn_end) {
42194 				duk__mark_heaphdr(heap, (duk_heaphdr *) *fn);
42195 				fn++;
42196 			}
42197 		} else {
42198 			/* May happen in some out-of-memory corner cases. */
42199 			DUK_D(DUK_DPRINT("duk_hcompiledfunction 'data' is NULL, skipping marking"));
42200 		}
42201 	} else if (DUK_HOBJECT_IS_NATIVEFUNCTION(h)) {
42202 		duk_hnativefunction *f = (duk_hnativefunction *) h;
42203 		DUK_UNREF(f);
42204 		/* nothing to mark */
42205 	} else if (DUK_HOBJECT_IS_BUFFEROBJECT(h)) {
42206 		duk_hbufferobject *b = (duk_hbufferobject *) h;
42207 		duk__mark_heaphdr(heap, (duk_heaphdr *) b->buf);
42208 	} else if (DUK_HOBJECT_IS_THREAD(h)) {
42209 		duk_hthread *t = (duk_hthread *) h;
42210 		duk_tval *tv;
42211 
42212 		tv = t->valstack;
42213 		while (tv < t->valstack_top) {
42214 			duk__mark_tval(heap, tv);
42215 			tv++;
42216 		}
42217 
42218 		for (i = 0; i < (duk_uint_fast32_t) t->callstack_top; i++) {
42219 			duk_activation *act = t->callstack + i;
42220 			duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_ACT_GET_FUNC(act));
42221 			duk__mark_heaphdr(heap, (duk_heaphdr *) act->var_env);
42222 			duk__mark_heaphdr(heap, (duk_heaphdr *) act->lex_env);
42223 #ifdef DUK_USE_NONSTD_FUNC_CALLER_PROPERTY
42224 			duk__mark_heaphdr(heap, (duk_heaphdr *) act->prev_caller);
42225 #endif
42226 		}
42227 
42228 #if 0  /* nothing now */
42229 		for (i = 0; i < (duk_uint_fast32_t) t->catchstack_top; i++) {
42230 			duk_catcher *cat = t->catchstack + i;
42231 		}
42232 #endif
42233 
42234 		duk__mark_heaphdr(heap, (duk_heaphdr *) t->resumer);
42235 
42236 		/* XXX: duk_small_uint_t would be enough for this loop */
42237 		for (i = 0; i < DUK_NUM_BUILTINS; i++) {
42238 			duk__mark_heaphdr(heap, (duk_heaphdr *) t->builtins[i]);
42239 		}
42240 	}
42241 }
42242 
42243 /* recursion tracking happens here only */
42244 DUK_LOCAL void duk__mark_heaphdr(duk_heap *heap, duk_heaphdr *h) {
42245 	DUK_DDD(DUK_DDDPRINT("duk__mark_heaphdr %p, type %ld",
42246 	                     (void *) h,
42247 	                     (h != NULL ? (long) DUK_HEAPHDR_GET_TYPE(h) : (long) -1)));
42248 	if (!h) {
42249 		return;
42250 	}
42251 #if defined(DUK_USE_ROM_OBJECTS)
42252 	if (DUK_HEAPHDR_HAS_READONLY(h)) {
42253 		DUK_DDD(DUK_DDDPRINT("readonly object %p, skip", (void *) h));
42254 		return;
42255 	}
42256 #endif
42257 	if (DUK_HEAPHDR_HAS_REACHABLE(h)) {
42258 		DUK_DDD(DUK_DDDPRINT("already marked reachable, skip"));
42259 		return;
42260 	}
42261 	DUK_HEAPHDR_SET_REACHABLE(h);
42262 
42263 	if (heap->mark_and_sweep_recursion_depth >= DUK_USE_MARK_AND_SWEEP_RECLIMIT) {
42264 		/* log this with a normal debug level because this should be relatively rare */
42265 		DUK_D(DUK_DPRINT("mark-and-sweep recursion limit reached, marking as temproot: %p", (void *) h));
42266 		DUK_HEAP_SET_MARKANDSWEEP_RECLIMIT_REACHED(heap);
42267 		DUK_HEAPHDR_SET_TEMPROOT(h);
42268 		return;
42269 	}
42270 
42271 	heap->mark_and_sweep_recursion_depth++;
42272 
42273 	switch ((int) DUK_HEAPHDR_GET_TYPE(h)) {
42274 	case DUK_HTYPE_STRING:
42275 		duk__mark_hstring(heap, (duk_hstring *) h);
42276 		break;
42277 	case DUK_HTYPE_OBJECT:
42278 		duk__mark_hobject(heap, (duk_hobject *) h);
42279 		break;
42280 	case DUK_HTYPE_BUFFER:
42281 		/* nothing to mark */
42282 		break;
42283 	default:
42284 		DUK_D(DUK_DPRINT("attempt to mark heaphdr %p with invalid htype %ld", (void *) h, (long) DUK_HEAPHDR_GET_TYPE(h)));
42285 		DUK_UNREACHABLE();
42286 	}
42287 
42288 	heap->mark_and_sweep_recursion_depth--;
42289 }
42290 
42291 DUK_LOCAL void duk__mark_tval(duk_heap *heap, duk_tval *tv) {
42292 	DUK_DDD(DUK_DDDPRINT("duk__mark_tval %p", (void *) tv));
42293 	if (!tv) {
42294 		return;
42295 	}
42296 	if (DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
42297 		duk__mark_heaphdr(heap, DUK_TVAL_GET_HEAPHDR(tv));
42298 	}
42299 }
42300 
42301 /*
42302  *  Mark the heap.
42303  */
42304 
42305 DUK_LOCAL void duk__mark_roots_heap(duk_heap *heap) {
42306 	duk_small_uint_t i;
42307 
42308 	DUK_DD(DUK_DDPRINT("duk__mark_roots_heap: %p", (void *) heap));
42309 
42310 	duk__mark_heaphdr(heap, (duk_heaphdr *) heap->heap_thread);
42311 	duk__mark_heaphdr(heap, (duk_heaphdr *) heap->heap_object);
42312 
42313 	for (i = 0; i < DUK_HEAP_NUM_STRINGS; i++) {
42314 		duk_hstring *h = DUK_HEAP_GET_STRING(heap, i);
42315 		duk__mark_heaphdr(heap, (duk_heaphdr *) h);
42316 	}
42317 
42318 	duk__mark_tval(heap, &heap->lj.value1);
42319 	duk__mark_tval(heap, &heap->lj.value2);
42320 
42321 #if defined(DUK_USE_DEBUGGER_SUPPORT)
42322 	for (i = 0; i < heap->dbg_breakpoint_count; i++) {
42323 		duk__mark_heaphdr(heap, (duk_heaphdr *) heap->dbg_breakpoints[i].filename);
42324 	}
42325 #endif
42326 }
42327 
42328 /*
42329  *  Mark refzero_list objects.
42330  *
42331  *  Objects on the refzero_list have no inbound references.  They might have
42332  *  outbound references to objects that we might free, which would invalidate
42333  *  any references held by the refzero objects.  A refzero object might also
42334  *  be rescued by refcount finalization.  Refzero objects are treated as
42335  *  reachability roots to ensure they (or anything they point to) are not
42336  *  freed in mark-and-sweep.
42337  */
42338 
42339 #ifdef DUK_USE_REFERENCE_COUNTING
42340 DUK_LOCAL void duk__mark_refzero_list(duk_heap *heap) {
42341 	duk_heaphdr *hdr;
42342 
42343 	DUK_DD(DUK_DDPRINT("duk__mark_refzero_list: %p", (void *) heap));
42344 
42345 	hdr = heap->refzero_list;
42346 	while (hdr) {
42347 		duk__mark_heaphdr(heap, hdr);
42348 		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
42349 	}
42350 }
42351 #endif
42352 
42353 /*
42354  *  Mark unreachable, finalizable objects.
42355  *
42356  *  Such objects will be moved aside and their finalizers run later.  They have
42357  *  to be treated as reachability roots for their properties etc to remain
42358  *  allocated.  This marking is only done for unreachable values which would
42359  *  be swept later (refzero_list is thus excluded).
42360  *
42361  *  Objects are first marked FINALIZABLE and only then marked as reachability
42362  *  roots; otherwise circular references might be handled inconsistently.
42363  */
42364 
42365 DUK_LOCAL void duk__mark_finalizable(duk_heap *heap) {
42366 	duk_hthread *thr;
42367 	duk_heaphdr *hdr;
42368 	duk_size_t count_finalizable = 0;
42369 
42370 	DUK_DD(DUK_DDPRINT("duk__mark_finalizable: %p", (void *) heap));
42371 
42372 	thr = duk__get_temp_hthread(heap);
42373 	DUK_ASSERT(thr != NULL);
42374 
42375 	hdr = heap->heap_allocated;
42376 	while (hdr) {
42377 		/* A finalizer is looked up from the object and up its prototype chain
42378 		 * (which allows inherited finalizers).  A prototype loop must not cause
42379 		 * an error to be thrown here; duk_hobject_hasprop_raw() will ignore a
42380 		 * prototype loop silently and indicate that the property doesn't exist.
42381 		 */
42382 
42383 		if (!DUK_HEAPHDR_HAS_REACHABLE(hdr) &&
42384 		    DUK_HEAPHDR_GET_TYPE(hdr) == DUK_HTYPE_OBJECT &&
42385 		    !DUK_HEAPHDR_HAS_FINALIZED(hdr) &&
42386 		    duk_hobject_hasprop_raw(thr, (duk_hobject *) hdr, DUK_HTHREAD_STRING_INT_FINALIZER(thr))) {
42387 
42388 			/* heaphdr:
42389 			 *  - is not reachable
42390 			 *  - is an object
42391 			 *  - is not a finalized object
42392 			 *  - has a finalizer
42393 			 */
42394 
42395 			DUK_DD(DUK_DDPRINT("unreachable heap object will be "
42396 			                   "finalized -> mark as finalizable "
42397 			                   "and treat as a reachability root: %p",
42398 			                   (void *) hdr));
42399 			DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(hdr));
42400 			DUK_HEAPHDR_SET_FINALIZABLE(hdr);
42401 			count_finalizable ++;
42402 		}
42403 
42404 		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
42405 	}
42406 
42407 	if (count_finalizable == 0) {
42408 		return;
42409 	}
42410 
42411 	DUK_DD(DUK_DDPRINT("marked %ld heap objects as finalizable, now mark them reachable",
42412 	                   (long) count_finalizable));
42413 
42414 	hdr = heap->heap_allocated;
42415 	while (hdr) {
42416 		if (DUK_HEAPHDR_HAS_FINALIZABLE(hdr)) {
42417 			duk__mark_heaphdr(heap, hdr);
42418 		}
42419 
42420 		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
42421 	}
42422 
42423 	/* Caller will finish the marking process if we hit a recursion limit. */
42424 }
42425 
42426 /*
42427  *  Mark objects on finalize_list.
42428  *
42429  */
42430 
42431 DUK_LOCAL void duk__mark_finalize_list(duk_heap *heap) {
42432 	duk_heaphdr *hdr;
42433 #ifdef DUK_USE_DEBUG
42434 	duk_size_t count_finalize_list = 0;
42435 #endif
42436 
42437 	DUK_DD(DUK_DDPRINT("duk__mark_finalize_list: %p", (void *) heap));
42438 
42439 	hdr = heap->finalize_list;
42440 	while (hdr) {
42441 		duk__mark_heaphdr(heap, hdr);
42442 		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
42443 #ifdef DUK_USE_DEBUG
42444 		count_finalize_list++;
42445 #endif
42446 	}
42447 
42448 #ifdef DUK_USE_DEBUG
42449 	if (count_finalize_list > 0) {
42450 		DUK_D(DUK_DPRINT("marked %ld objects on the finalize_list as reachable (previous finalizer run skipped)",
42451 		                 (long) count_finalize_list));
42452 	}
42453 #endif
42454 }
42455 
42456 /*
42457  *  Fallback marking handler if recursion limit is reached.
42458  *
42459  *  Iterates 'temproots' until recursion limit is no longer hit.  Note
42460  *  that temproots may reside either in heap allocated list or the
42461  *  refzero work list.  This is a slow scan, but guarantees that we
42462  *  finish with a bounded C stack.
42463  *
42464  *  Note that nodes may have been marked as temproots before this
42465  *  scan begun, OR they may have been marked during the scan (as
42466  *  we process nodes recursively also during the scan).  This is
42467  *  intended behavior.
42468  */
42469 
42470 #ifdef DUK_USE_DEBUG
42471 DUK_LOCAL void duk__handle_temproot(duk_heap *heap, duk_heaphdr *hdr, duk_size_t *count) {
42472 #else
42473 DUK_LOCAL void duk__handle_temproot(duk_heap *heap, duk_heaphdr *hdr) {
42474 #endif
42475 	if (!DUK_HEAPHDR_HAS_TEMPROOT(hdr)) {
42476 		DUK_DDD(DUK_DDDPRINT("not a temp root: %p", (void *) hdr));
42477 		return;
42478 	}
42479 
42480 	DUK_DDD(DUK_DDDPRINT("found a temp root: %p", (void *) hdr));
42481 	DUK_HEAPHDR_CLEAR_TEMPROOT(hdr);
42482 	DUK_HEAPHDR_CLEAR_REACHABLE(hdr);  /* done so that duk__mark_heaphdr() works correctly */
42483 	duk__mark_heaphdr(heap, hdr);
42484 
42485 #ifdef DUK_USE_DEBUG
42486 	(*count)++;
42487 #endif
42488 }
42489 
42490 DUK_LOCAL void duk__mark_temproots_by_heap_scan(duk_heap *heap) {
42491 	duk_heaphdr *hdr;
42492 #ifdef DUK_USE_DEBUG
42493 	duk_size_t count;
42494 #endif
42495 
42496 	DUK_DD(DUK_DDPRINT("duk__mark_temproots_by_heap_scan: %p", (void *) heap));
42497 
42498 	while (DUK_HEAP_HAS_MARKANDSWEEP_RECLIMIT_REACHED(heap)) {
42499 		DUK_DD(DUK_DDPRINT("recursion limit reached, doing heap scan to continue from temproots"));
42500 
42501 #ifdef DUK_USE_DEBUG
42502 		count = 0;
42503 #endif
42504 		DUK_HEAP_CLEAR_MARKANDSWEEP_RECLIMIT_REACHED(heap);
42505 
42506 		hdr = heap->heap_allocated;
42507 		while (hdr) {
42508 #ifdef DUK_USE_DEBUG
42509 			duk__handle_temproot(heap, hdr, &count);
42510 #else
42511 			duk__handle_temproot(heap, hdr);
42512 #endif
42513 			hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
42514 		}
42515 
42516 		/* must also check refzero_list */
42517 #ifdef DUK_USE_REFERENCE_COUNTING
42518 		hdr = heap->refzero_list;
42519 		while (hdr) {
42520 #ifdef DUK_USE_DEBUG
42521 			duk__handle_temproot(heap, hdr, &count);
42522 #else
42523 			duk__handle_temproot(heap, hdr);
42524 #endif
42525 			hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
42526 		}
42527 #endif  /* DUK_USE_REFERENCE_COUNTING */
42528 
42529 #ifdef DUK_USE_DEBUG
42530 		DUK_DD(DUK_DDPRINT("temproot mark heap scan processed %ld temp roots", (long) count));
42531 #endif
42532 	}
42533 }
42534 
42535 /*
42536  *  Finalize refcounts for heap elements just about to be freed.
42537  *  This must be done for all objects before freeing to avoid any
42538  *  stale pointer dereferences.
42539  *
42540  *  Note that this must deduce the set of objects to be freed
42541  *  identically to duk__sweep_heap().
42542  */
42543 
42544 #ifdef DUK_USE_REFERENCE_COUNTING
42545 DUK_LOCAL void duk__finalize_refcounts(duk_heap *heap) {
42546 	duk_hthread *thr;
42547 	duk_heaphdr *hdr;
42548 
42549 	thr = duk__get_temp_hthread(heap);
42550 	DUK_ASSERT(thr != NULL);
42551 
42552 	DUK_DD(DUK_DDPRINT("duk__finalize_refcounts: heap=%p, hthread=%p",
42553 	                   (void *) heap, (void *) thr));
42554 
42555 	hdr = heap->heap_allocated;
42556 	while (hdr) {
42557 		if (!DUK_HEAPHDR_HAS_REACHABLE(hdr)) {
42558 			/*
42559 			 *  Unreachable object about to be swept.  Finalize target refcounts
42560 			 *  (objects which the unreachable object points to) without doing
42561 			 *  refzero processing.  Recursive decrefs are also prevented when
42562 			 *  refzero processing is disabled.
42563 			 *
42564 			 *  Value cannot be a finalizable object, as they have been made
42565 			 *  temporarily reachable for this round.
42566 			 */
42567 
42568 			DUK_DDD(DUK_DDDPRINT("unreachable object, refcount finalize before sweeping: %p", (void *) hdr));
42569 			duk_heaphdr_refcount_finalize(thr, hdr);
42570 		}
42571 
42572 		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
42573 	}
42574 }
42575 #endif  /* DUK_USE_REFERENCE_COUNTING */
42576 
42577 /*
42578  *  Clear (reachable) flags of refzero work list.
42579  */
42580 
42581 #ifdef DUK_USE_REFERENCE_COUNTING
42582 DUK_LOCAL void duk__clear_refzero_list_flags(duk_heap *heap) {
42583 	duk_heaphdr *hdr;
42584 
42585 	DUK_DD(DUK_DDPRINT("duk__clear_refzero_list_flags: %p", (void *) heap));
42586 
42587 	hdr = heap->refzero_list;
42588 	while (hdr) {
42589 		DUK_HEAPHDR_CLEAR_REACHABLE(hdr);
42590 		DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(hdr));
42591 		/* DUK_HEAPHDR_HAS_FINALIZED may or may not be set. */
42592 		DUK_ASSERT(!DUK_HEAPHDR_HAS_TEMPROOT(hdr));
42593 		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
42594 	}
42595 }
42596 #endif  /* DUK_USE_REFERENCE_COUNTING */
42597 
42598 /*
42599  *  Clear (reachable) flags of finalize_list
42600  *
42601  *  We could mostly do in the sweep phase when we move objects from the
42602  *  heap into the finalize_list.  However, if a finalizer run is skipped
42603  *  during a mark-and-sweep, the objects on the finalize_list will be marked
42604  *  reachable during the next mark-and-sweep.  Since they're already on the
42605  *  finalize_list, no-one will be clearing their REACHABLE flag so we do it
42606  *  here.  (This now overlaps with the sweep handling in a harmless way.)
42607  */
42608 
42609 DUK_LOCAL void duk__clear_finalize_list_flags(duk_heap *heap) {
42610 	duk_heaphdr *hdr;
42611 
42612 	DUK_DD(DUK_DDPRINT("duk__clear_finalize_list_flags: %p", (void *) heap));
42613 
42614 	hdr = heap->finalize_list;
42615 	while (hdr) {
42616 		DUK_HEAPHDR_CLEAR_REACHABLE(hdr);
42617 		DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(hdr));
42618 		DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(hdr));
42619 		DUK_ASSERT(!DUK_HEAPHDR_HAS_TEMPROOT(hdr));
42620 		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
42621 	}
42622 }
42623 
42624 /*
42625  *  Sweep stringtable
42626  */
42627 
42628 #if defined(DUK_USE_STRTAB_CHAIN)
42629 
42630 /* XXX: skip count_free w/o debug? */
42631 #if defined(DUK_USE_HEAPPTR16)
42632 DUK_LOCAL void duk__sweep_string_chain16(duk_heap *heap, duk_uint16_t *slot, duk_size_t *count_keep, duk_size_t *count_free) {
42633 	duk_uint16_t h16 = *slot;
42634 	duk_hstring *h;
42635 	duk_uint16_t null16 = heap->heapptr_null16;
42636 
42637 	if (h16 == null16) {
42638 		/* nop */
42639 		return;
42640 	}
42641 	h = (duk_hstring *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, h16);
42642 	DUK_ASSERT(h != NULL);
42643 
42644 	if (DUK_HEAPHDR_HAS_REACHABLE((duk_heaphdr *) h)) {
42645 		DUK_HEAPHDR_CLEAR_REACHABLE((duk_heaphdr *) h);
42646 		(*count_keep)++;
42647 	} else {
42648 #if defined(DUK_USE_REFERENCE_COUNTING)
42649 		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) == 0);
42650 #endif
42651 		/* deal with weak references first */
42652 		duk_heap_strcache_string_remove(heap, (duk_hstring *) h);
42653 		*slot = null16;
42654 
42655 		/* free inner references (these exist e.g. when external
42656 		 * strings are enabled)
42657 		 */
42658 		duk_free_hstring_inner(heap, h);
42659 		DUK_FREE(heap, h);
42660 		(*count_free)++;
42661 	}
42662 }
42663 #else  /* DUK_USE_HEAPPTR16 */
42664 DUK_LOCAL void duk__sweep_string_chain(duk_heap *heap, duk_hstring **slot, duk_size_t *count_keep, duk_size_t *count_free) {
42665 	duk_hstring *h = *slot;
42666 
42667 	if (h == NULL) {
42668 		/* nop */
42669 		return;
42670 	}
42671 
42672 	if (DUK_HEAPHDR_HAS_REACHABLE((duk_heaphdr *) h)) {
42673 		DUK_HEAPHDR_CLEAR_REACHABLE((duk_heaphdr *) h);
42674 		(*count_keep)++;
42675 	} else {
42676 #if defined(DUK_USE_REFERENCE_COUNTING)
42677 		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) == 0);
42678 #endif
42679 		/* deal with weak references first */
42680 		duk_heap_strcache_string_remove(heap, (duk_hstring *) h);
42681 		*slot = NULL;
42682 
42683 		/* free inner references (these exist e.g. when external
42684 		 * strings are enabled)
42685 		 */
42686 		duk_free_hstring_inner(heap, h);
42687 		DUK_FREE(heap, h);
42688 		(*count_free)++;
42689 	}
42690 }
42691 #endif  /* DUK_USE_HEAPPTR16 */
42692 
42693 DUK_LOCAL void duk__sweep_stringtable_chain(duk_heap *heap, duk_size_t *out_count_keep) {
42694 	duk_strtab_entry *e;
42695 	duk_uint_fast32_t i;
42696 	duk_size_t count_free = 0;
42697 	duk_size_t count_keep = 0;
42698 	duk_size_t j, n;
42699 #if defined(DUK_USE_HEAPPTR16)
42700 	duk_uint16_t *lst;
42701 #else
42702 	duk_hstring **lst;
42703 #endif
42704 
42705 	DUK_DD(DUK_DDPRINT("duk__sweep_stringtable: %p", (void *) heap));
42706 
42707 	/* Non-zero refcounts should not happen for unreachable strings,
42708 	 * because we refcount finalize all unreachable objects which
42709 	 * should have decreased unreachable string refcounts to zero
42710 	 * (even for cycles).
42711 	 */
42712 
42713 	for (i = 0; i < DUK_STRTAB_CHAIN_SIZE; i++) {
42714 		e = heap->strtable + i;
42715 		if (e->listlen == 0) {
42716 #if defined(DUK_USE_HEAPPTR16)
42717 			duk__sweep_string_chain16(heap, &e->u.str16, &count_keep, &count_free);
42718 #else
42719 			duk__sweep_string_chain(heap, &e->u.str, &count_keep, &count_free);
42720 #endif
42721 		} else {
42722 #if defined(DUK_USE_HEAPPTR16)
42723 			lst = (duk_uint16_t *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, e->u.strlist16);
42724 #else
42725 			lst = e->u.strlist;
42726 #endif
42727 			for (j = 0, n = e->listlen; j < n; j++) {
42728 #if defined(DUK_USE_HEAPPTR16)
42729 				duk__sweep_string_chain16(heap, lst + j, &count_keep, &count_free);
42730 #else
42731 				duk__sweep_string_chain(heap, lst + j, &count_keep, &count_free);
42732 #endif
42733 			}
42734 		}
42735 	}
42736 
42737 	DUK_D(DUK_DPRINT("mark-and-sweep sweep stringtable: %ld freed, %ld kept",
42738 	                 (long) count_free, (long) count_keep));
42739 	*out_count_keep = count_keep;
42740 }
42741 #endif  /* DUK_USE_STRTAB_CHAIN */
42742 
42743 #if defined(DUK_USE_STRTAB_PROBE)
42744 DUK_LOCAL void duk__sweep_stringtable_probe(duk_heap *heap, duk_size_t *out_count_keep) {
42745 	duk_hstring *h;
42746 	duk_uint_fast32_t i;
42747 #ifdef DUK_USE_DEBUG
42748 	duk_size_t count_free = 0;
42749 #endif
42750 	duk_size_t count_keep = 0;
42751 
42752 	DUK_DD(DUK_DDPRINT("duk__sweep_stringtable: %p", (void *) heap));
42753 
42754 	for (i = 0; i < heap->st_size; i++) {
42755 #if defined(DUK_USE_HEAPPTR16)
42756 		h = (duk_hstring *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, heap->strtable16[i]);
42757 #else
42758 		h = heap->strtable[i];
42759 #endif
42760 		if (h == NULL || h == DUK_STRTAB_DELETED_MARKER(heap)) {
42761 			continue;
42762 		} else if (DUK_HEAPHDR_HAS_REACHABLE((duk_heaphdr *) h)) {
42763 			DUK_HEAPHDR_CLEAR_REACHABLE((duk_heaphdr *) h);
42764 			count_keep++;
42765 			continue;
42766 		}
42767 
42768 #ifdef DUK_USE_DEBUG
42769 		count_free++;
42770 #endif
42771 
42772 #if defined(DUK_USE_REFERENCE_COUNTING)
42773 		/* Non-zero refcounts should not happen for unreachable strings,
42774 		 * because we refcount finalize all unreachable objects which
42775 		 * should have decreased unreachable string refcounts to zero
42776 		 * (even for cycles).
42777 		 */
42778 		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) == 0);
42779 #endif
42780 
42781 		DUK_DDD(DUK_DDDPRINT("sweep string, not reachable: %p", (void *) h));
42782 
42783 		/* deal with weak references first */
42784 		duk_heap_strcache_string_remove(heap, (duk_hstring *) h);
42785 
42786 		/* remove the string (mark DELETED), could also call
42787 		 * duk_heap_string_remove() but that would be slow and
42788 		 * pointless because we already know the slot.
42789 		 */
42790 #if defined(DUK_USE_HEAPPTR16)
42791 		heap->strtable16[i] = heap->heapptr_deleted16;
42792 #else
42793 		heap->strtable[i] = DUK_STRTAB_DELETED_MARKER(heap);
42794 #endif
42795 
42796 		/* free inner references (these exist e.g. when external
42797 		 * strings are enabled)
42798 		 */
42799 		duk_free_hstring_inner(heap, (duk_hstring *) h);
42800 
42801 		/* finally free the struct itself */
42802 		DUK_FREE(heap, h);
42803 	}
42804 
42805 #ifdef DUK_USE_DEBUG
42806 	DUK_D(DUK_DPRINT("mark-and-sweep sweep stringtable: %ld freed, %ld kept",
42807 	                 (long) count_free, (long) count_keep));
42808 #endif
42809 	*out_count_keep = count_keep;
42810 }
42811 #endif  /* DUK_USE_STRTAB_PROBE */
42812 
42813 /*
42814  *  Sweep heap
42815  */
42816 
42817 DUK_LOCAL void duk__sweep_heap(duk_heap *heap, duk_int_t flags, duk_size_t *out_count_keep) {
42818 	duk_heaphdr *prev;  /* last element that was left in the heap */
42819 	duk_heaphdr *curr;
42820 	duk_heaphdr *next;
42821 #ifdef DUK_USE_DEBUG
42822 	duk_size_t count_free = 0;
42823 	duk_size_t count_finalize = 0;
42824 	duk_size_t count_rescue = 0;
42825 #endif
42826 	duk_size_t count_keep = 0;
42827 
42828 	DUK_UNREF(flags);
42829 	DUK_DD(DUK_DDPRINT("duk__sweep_heap: %p", (void *) heap));
42830 
42831 	prev = NULL;
42832 	curr = heap->heap_allocated;
42833 	heap->heap_allocated = NULL;
42834 	while (curr) {
42835 		/* Strings and ROM objects are never placed on the heap allocated list. */
42836 		DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) != DUK_HTYPE_STRING);
42837 		DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(curr));
42838 
42839 		next = DUK_HEAPHDR_GET_NEXT(heap, curr);
42840 
42841 		if (DUK_HEAPHDR_HAS_REACHABLE(curr)) {
42842 			/*
42843 			 *  Reachable object, keep
42844 			 */
42845 
42846 			DUK_DDD(DUK_DDDPRINT("sweep, reachable: %p", (void *) curr));
42847 
42848 			if (DUK_HEAPHDR_HAS_FINALIZABLE(curr)) {
42849 				/*
42850 				 *  If object has been marked finalizable, move it to the
42851 				 *  "to be finalized" work list.  It will be collected on
42852 				 *  the next mark-and-sweep if it is still unreachable
42853 				 *  after running the finalizer.
42854 				 */
42855 
42856 				DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(curr));
42857 				DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT);
42858 				DUK_DDD(DUK_DDDPRINT("object has finalizer, move to finalization work list: %p", (void *) curr));
42859 
42860 #ifdef DUK_USE_DOUBLE_LINKED_HEAP
42861 				if (heap->finalize_list) {
42862 					DUK_HEAPHDR_SET_PREV(heap, heap->finalize_list, curr);
42863 				}
42864 				DUK_HEAPHDR_SET_PREV(heap, curr, NULL);
42865 #endif
42866 				DUK_HEAPHDR_SET_NEXT(heap, curr, heap->finalize_list);
42867 				DUK_ASSERT_HEAPHDR_LINKS(heap, curr);
42868 				heap->finalize_list = curr;
42869 #ifdef DUK_USE_DEBUG
42870 				count_finalize++;
42871 #endif
42872 			} else {
42873 				/*
42874 				 *  Object will be kept; queue object back to heap_allocated (to tail)
42875 				 */
42876 
42877 				if (DUK_HEAPHDR_HAS_FINALIZED(curr)) {
42878 					/*
42879 					 *  Object's finalizer was executed on last round, and
42880 					 *  object has been happily rescued.
42881 					 */
42882 
42883 					DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(curr));
42884 					DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT);
42885 					DUK_DD(DUK_DDPRINT("object rescued during mark-and-sweep finalization: %p", (void *) curr));
42886 #ifdef DUK_USE_DEBUG
42887 					count_rescue++;
42888 #endif
42889 				} else {
42890 					/*
42891 					 *  Plain, boring reachable object.
42892 					 */
42893 					DUK_DD(DUK_DDPRINT("keep object: %!iO", curr));
42894 					count_keep++;
42895 				}
42896 
42897 				if (!heap->heap_allocated) {
42898 					heap->heap_allocated = curr;
42899 				}
42900 				if (prev) {
42901 					DUK_HEAPHDR_SET_NEXT(heap, prev, curr);
42902 				}
42903 #ifdef DUK_USE_DOUBLE_LINKED_HEAP
42904 				DUK_HEAPHDR_SET_PREV(heap, curr, prev);
42905 #endif
42906 				DUK_ASSERT_HEAPHDR_LINKS(heap, prev);
42907 				DUK_ASSERT_HEAPHDR_LINKS(heap, curr);
42908 				prev = curr;
42909 			}
42910 
42911 			DUK_HEAPHDR_CLEAR_REACHABLE(curr);
42912 			DUK_HEAPHDR_CLEAR_FINALIZED(curr);
42913 			DUK_HEAPHDR_CLEAR_FINALIZABLE(curr);
42914 
42915 			DUK_ASSERT(!DUK_HEAPHDR_HAS_REACHABLE(curr));
42916 			DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(curr));
42917 			DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(curr));
42918 
42919 			curr = next;
42920 		} else {
42921 			/*
42922 			 *  Unreachable object, free
42923 			 */
42924 
42925 			DUK_DDD(DUK_DDDPRINT("sweep, not reachable: %p", (void *) curr));
42926 
42927 #if defined(DUK_USE_REFERENCE_COUNTING)
42928 			/* Non-zero refcounts should not happen because we refcount
42929 			 * finalize all unreachable objects which should cancel out
42930 			 * refcounts (even for cycles).
42931 			 */
42932 			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(curr) == 0);
42933 #endif
42934 			DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(curr));
42935 
42936 			if (DUK_HEAPHDR_HAS_FINALIZED(curr)) {
42937 				DUK_DDD(DUK_DDDPRINT("finalized object not rescued: %p", (void *) curr));
42938 			}
42939 
42940 			/* Note: object cannot be a finalizable unreachable object, as
42941 			 * they have been marked temporarily reachable for this round,
42942 			 * and are handled above.
42943 			 */
42944 
42945 #ifdef DUK_USE_DEBUG
42946 			count_free++;
42947 #endif
42948 
42949 			/* weak refs should be handled here, but no weak refs for
42950 			 * any non-string objects exist right now.
42951 			 */
42952 
42953 			/* free object and all auxiliary (non-heap) allocs */
42954 			duk_heap_free_heaphdr_raw(heap, curr);
42955 
42956 			curr = next;
42957 		}
42958 	}
42959 	if (prev) {
42960 		DUK_HEAPHDR_SET_NEXT(heap, prev, NULL);
42961 	}
42962 	DUK_ASSERT_HEAPHDR_LINKS(heap, prev);
42963 
42964 #ifdef DUK_USE_DEBUG
42965 	DUK_D(DUK_DPRINT("mark-and-sweep sweep objects (non-string): %ld freed, %ld kept, %ld rescued, %ld queued for finalization",
42966 	                 (long) count_free, (long) count_keep, (long) count_rescue, (long) count_finalize));
42967 #endif
42968 	*out_count_keep = count_keep;
42969 }
42970 
42971 /*
42972  *  Run (object) finalizers in the "to be finalized" work list.
42973  */
42974 
42975 DUK_LOCAL void duk__run_object_finalizers(duk_heap *heap, duk_small_uint_t flags) {
42976 	duk_heaphdr *curr;
42977 	duk_heaphdr *next;
42978 #ifdef DUK_USE_DEBUG
42979 	duk_size_t count = 0;
42980 #endif
42981 	duk_hthread *thr;
42982 
42983 	DUK_DD(DUK_DDPRINT("duk__run_object_finalizers: %p", (void *) heap));
42984 
42985 	thr = duk__get_temp_hthread(heap);
42986 	DUK_ASSERT(thr != NULL);
42987 
42988 	curr = heap->finalize_list;
42989 	while (curr) {
42990 		DUK_DDD(DUK_DDDPRINT("mark-and-sweep finalize: %p", (void *) curr));
42991 
42992 		DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT);  /* only objects have finalizers */
42993 		DUK_ASSERT(!DUK_HEAPHDR_HAS_REACHABLE(curr));                /* flags have been already cleared */
42994 		DUK_ASSERT(!DUK_HEAPHDR_HAS_TEMPROOT(curr));
42995 		DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(curr));
42996 		DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(curr));
42997 		DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(curr));  /* No finalizers for ROM objects */
42998 
42999 		/* Keep heap->finalize_list up-to-date during the list walk.
43000 		 * This has no functional impact, but does matter e.g. for
43001 		 * duk_push_heapptr() asserts when assertions are enabled.
43002 		 */
43003 		heap->finalize_list = curr;
43004 
43005 		if (DUK_LIKELY((flags & DUK_MS_FLAG_SKIP_FINALIZERS) == 0)) {
43006 			/* Run the finalizer, duk_hobject_run_finalizer() sets FINALIZED.
43007 			 * Next mark-and-sweep will collect the object unless it has
43008 			 * become reachable (i.e. rescued).  FINALIZED prevents the
43009 			 * finalizer from being executed again before that.
43010 			 */
43011 			duk_hobject_run_finalizer(thr, (duk_hobject *) curr);  /* must never longjmp */
43012 			DUK_ASSERT(DUK_HEAPHDR_HAS_FINALIZED(curr));
43013 
43014 			/* XXX: could clear FINALIZED already here; now cleared in
43015 			 * next mark-and-sweep.
43016 			 */
43017 		} else {
43018 			/* Used during heap destruction: don't actually run finalizers
43019 			 * because we're heading into forced finalization.  Instead,
43020 			 * queue finalizable objects back to the heap_allocated list.
43021 			 */
43022 			DUK_D(DUK_DPRINT("skip finalizers flag set, queue object to heap_allocated without finalizing"));
43023 			DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(curr));
43024 		}
43025 
43026 		/* queue back to heap_allocated */
43027 		next = DUK_HEAPHDR_GET_NEXT(heap, curr);
43028 		DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap, curr);
43029 
43030 		curr = next;
43031 #ifdef DUK_USE_DEBUG
43032 		count++;
43033 #endif
43034 	}
43035 
43036 	/* finalize_list will always be processed completely */
43037 	heap->finalize_list = NULL;
43038 
43039 #ifdef DUK_USE_DEBUG
43040 	DUK_D(DUK_DPRINT("mark-and-sweep finalize objects: %ld finalizers called", (long) count));
43041 #endif
43042 }
43043 
43044 /*
43045  *  Object compaction.
43046  *
43047  *  Compaction is assumed to never throw an error.
43048  */
43049 
43050 DUK_LOCAL int duk__protected_compact_object(duk_context *ctx) {
43051 	/* XXX: for threads, compact value stack, call stack, catch stack? */
43052 
43053 	duk_hobject *obj = duk_get_hobject(ctx, -1);
43054 	DUK_ASSERT(obj != NULL);
43055 	duk_hobject_compact_props((duk_hthread *) ctx, obj);
43056 	return 0;
43057 }
43058 
43059 #ifdef DUK_USE_DEBUG
43060 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) {
43061 #else
43062 DUK_LOCAL void duk__compact_object_list(duk_heap *heap, duk_hthread *thr, duk_heaphdr *start) {
43063 #endif
43064 	duk_heaphdr *curr;
43065 #ifdef DUK_USE_DEBUG
43066 	duk_size_t old_size, new_size;
43067 #endif
43068 	duk_hobject *obj;
43069 
43070 	DUK_UNREF(heap);
43071 
43072 	curr = start;
43073 	while (curr) {
43074 		DUK_DDD(DUK_DDDPRINT("mark-and-sweep compact: %p", (void *) curr));
43075 
43076 		if (DUK_HEAPHDR_GET_TYPE(curr) != DUK_HTYPE_OBJECT) {
43077 			goto next;
43078 		}
43079 		obj = (duk_hobject *) curr;
43080 
43081 #ifdef DUK_USE_DEBUG
43082 		old_size = DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE(obj),
43083 		                                      DUK_HOBJECT_GET_ASIZE(obj),
43084 		                                      DUK_HOBJECT_GET_HSIZE(obj));
43085 #endif
43086 
43087 		DUK_DD(DUK_DDPRINT("compact object: %p", (void *) obj));
43088 		duk_push_hobject((duk_context *) thr, obj);
43089 		/* XXX: disable error handlers for duration of compaction? */
43090 		duk_safe_call((duk_context *) thr, duk__protected_compact_object, 1, 0);
43091 
43092 #ifdef DUK_USE_DEBUG
43093 		new_size = DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE(obj),
43094 		                                      DUK_HOBJECT_GET_ASIZE(obj),
43095 		                                      DUK_HOBJECT_GET_HSIZE(obj));
43096 #endif
43097 
43098 #ifdef DUK_USE_DEBUG
43099 		(*p_count_compact)++;
43100 		(*p_count_bytes_saved) += (duk_size_t) (old_size - new_size);
43101 #endif
43102 
43103 	 next:
43104 		curr = DUK_HEAPHDR_GET_NEXT(heap, curr);
43105 #ifdef DUK_USE_DEBUG
43106 		(*p_count_check)++;
43107 #endif
43108 	}
43109 }
43110 
43111 DUK_LOCAL void duk__compact_objects(duk_heap *heap) {
43112 	/* XXX: which lists should participate?  to be finalized? */
43113 #ifdef DUK_USE_DEBUG
43114 	duk_size_t count_check = 0;
43115 	duk_size_t count_compact = 0;
43116 	duk_size_t count_bytes_saved = 0;
43117 #endif
43118 	duk_hthread *thr;
43119 
43120 	DUK_DD(DUK_DDPRINT("duk__compact_objects: %p", (void *) heap));
43121 
43122 	thr = duk__get_temp_hthread(heap);
43123 	DUK_ASSERT(thr != NULL);
43124 
43125 #ifdef DUK_USE_DEBUG
43126 	duk__compact_object_list(heap, thr, heap->heap_allocated, &count_check, &count_compact, &count_bytes_saved);
43127 	duk__compact_object_list(heap, thr, heap->finalize_list, &count_check, &count_compact, &count_bytes_saved);
43128 #ifdef DUK_USE_REFERENCE_COUNTING
43129 	duk__compact_object_list(heap, thr, heap->refzero_list, &count_check, &count_compact, &count_bytes_saved);
43130 #endif
43131 #else
43132 	duk__compact_object_list(heap, thr, heap->heap_allocated);
43133 	duk__compact_object_list(heap, thr, heap->finalize_list);
43134 #ifdef DUK_USE_REFERENCE_COUNTING
43135 	duk__compact_object_list(heap, thr, heap->refzero_list);
43136 #endif
43137 #endif
43138 
43139 #ifdef DUK_USE_DEBUG
43140 	DUK_D(DUK_DPRINT("mark-and-sweep compact objects: %ld checked, %ld compaction attempts, %ld bytes saved by compaction",
43141 	                 (long) count_check, (long) count_compact, (long) count_bytes_saved));
43142 #endif
43143 }
43144 
43145 /*
43146  *  Assertion helpers.
43147  */
43148 
43149 #ifdef DUK_USE_ASSERTIONS
43150 DUK_LOCAL void duk__assert_heaphdr_flags(duk_heap *heap) {
43151 	duk_heaphdr *hdr;
43152 
43153 	hdr = heap->heap_allocated;
43154 	while (hdr) {
43155 		DUK_ASSERT(!DUK_HEAPHDR_HAS_REACHABLE(hdr));
43156 		DUK_ASSERT(!DUK_HEAPHDR_HAS_TEMPROOT(hdr));
43157 		DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(hdr));
43158 		/* may have FINALIZED */
43159 		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
43160 	}
43161 
43162 #ifdef DUK_USE_REFERENCE_COUNTING
43163 	hdr = heap->refzero_list;
43164 	while (hdr) {
43165 		DUK_ASSERT(!DUK_HEAPHDR_HAS_REACHABLE(hdr));
43166 		DUK_ASSERT(!DUK_HEAPHDR_HAS_TEMPROOT(hdr));
43167 		DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(hdr));
43168 		/* DUK_HEAPHDR_HAS_FINALIZED may be set if we're doing a
43169 		 * refzero finalization and mark-and-sweep gets triggered
43170 		 * during the finalizer.
43171 		 */
43172 		/* DUK_HEAPHDR_HAS_FINALIZED may or may not be set. */
43173 		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
43174 	}
43175 #endif  /* DUK_USE_REFERENCE_COUNTING */
43176 }
43177 
43178 #ifdef DUK_USE_REFERENCE_COUNTING
43179 DUK_LOCAL void duk__assert_valid_refcounts(duk_heap *heap) {
43180 	duk_heaphdr *hdr = heap->heap_allocated;
43181 	while (hdr) {
43182 		if (DUK_HEAPHDR_GET_REFCOUNT(hdr) == 0 &&
43183 		    DUK_HEAPHDR_HAS_FINALIZED(hdr)) {
43184 			/* An object may be in heap_allocated list with a zero
43185 			 * refcount if it has just been finalized and is waiting
43186 			 * to be collected by the next cycle.
43187 			 */
43188 		} else if (DUK_HEAPHDR_GET_REFCOUNT(hdr) == 0) {
43189 			/* An object may be in heap_allocated list with a zero
43190 			 * refcount also if it is a temporary object created by
43191 			 * a finalizer; because finalization now runs inside
43192 			 * mark-and-sweep, such objects will not be queued to
43193 			 * refzero_list and will thus appear here with refcount
43194 			 * zero.
43195 			 */
43196 #if 0  /* this case can no longer occur because refcount is unsigned */
43197 		} else if (DUK_HEAPHDR_GET_REFCOUNT(hdr) < 0) {
43198 			DUK_D(DUK_DPRINT("invalid refcount: %ld, %p -> %!O",
43199 			                 (hdr != NULL ? (long) DUK_HEAPHDR_GET_REFCOUNT(hdr) : (long) 0),
43200 			                 (void *) hdr, (duk_heaphdr *) hdr));
43201 			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(hdr) > 0);
43202 #endif
43203 		}
43204 		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
43205 	}
43206 }
43207 #endif  /* DUK_USE_REFERENCE_COUNTING */
43208 #endif  /* DUK_USE_ASSERTIONS */
43209 
43210 /*
43211  *  Finalizer torture.  Do one fake finalizer call which causes side effects
43212  *  similar to one or more finalizers on actual objects.
43213  */
43214 
43215 #if defined(DUK_USE_MARKANDSWEEP_FINALIZER_TORTURE)
43216 DUK_LOCAL duk_ret_t duk__markandsweep_fake_finalizer(duk_context *ctx) {
43217 	DUK_D(DUK_DPRINT("fake mark-and-sweep torture finalizer executed"));
43218 
43219 	/* Require a lot of stack to force a value stack grow/shrink.
43220 	 * Recursive mark-and-sweep is prevented by allocation macros
43221 	 * so this won't trigger another mark-and-sweep.
43222 	 */
43223 	duk_require_stack(ctx, 100000);
43224 
43225 	/* XXX: do something to force a callstack grow/shrink, perhaps
43226 	 * just a manual forced resize or a forced relocating realloc?
43227 	 */
43228 
43229 	return 0;
43230 }
43231 
43232 DUK_LOCAL void duk__markandsweep_torture_finalizer(duk_hthread *thr) {
43233 	duk_context *ctx;
43234 	duk_int_t rc;
43235 
43236 	DUK_ASSERT(thr != NULL);
43237 	ctx = (duk_context *) thr;
43238 
43239 	/* Avoid fake finalization when callstack limit has been reached.
43240 	 * Otherwise a callstack limit error will be created, then refzero'ed.
43241 	 */
43242 	if (thr->heap->call_recursion_depth >= thr->heap->call_recursion_limit ||
43243 	    thr->callstack_size + 2 * DUK_CALLSTACK_GROW_STEP >= thr->callstack_max /*approximate*/) {
43244 		DUK_D(DUK_DPRINT("call recursion depth reached, avoid fake mark-and-sweep torture finalizer"));
43245 		return;
43246 	}
43247 
43248 	/* Run fake finalizer.  Avoid creating unnecessary garbage. */
43249 	duk_push_c_function(ctx, duk__markandsweep_fake_finalizer, 0 /*nargs*/);
43250 	rc = duk_pcall(ctx, 0 /*nargs*/);
43251 	DUK_UNREF(rc);  /* ignored */
43252 	duk_pop(ctx);
43253 }
43254 #endif  /* DUK_USE_MARKANDSWEEP_FINALIZER_TORTURE */
43255 
43256 /*
43257  *  Main mark-and-sweep function.
43258  *
43259  *  'flags' represents the features requested by the caller.  The current
43260  *  heap->mark_and_sweep_base_flags is ORed automatically into the flags;
43261  *  the base flags mask typically prevents certain mark-and-sweep operations
43262  *  to avoid trouble.
43263  */
43264 
43265 DUK_INTERNAL duk_bool_t duk_heap_mark_and_sweep(duk_heap *heap, duk_small_uint_t flags) {
43266 	duk_hthread *thr;
43267 	duk_size_t count_keep_obj;
43268 	duk_size_t count_keep_str;
43269 #ifdef DUK_USE_VOLUNTARY_GC
43270 	duk_size_t tmp;
43271 #endif
43272 
43273 	if (DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap)) {
43274 		DUK_D(DUK_DPRINT("refuse to do a recursive mark-and-sweep"));
43275 		return 0;
43276 	}
43277 
43278 	/* XXX: thread selection for mark-and-sweep is currently a hack.
43279 	 * If we don't have a thread, the entire mark-and-sweep is now
43280 	 * skipped (although we could just skip finalizations).
43281 	 */
43282 
43283 	/* If thr != NULL, the thr may still be in the middle of
43284 	 * initialization.
43285 	 * XXX: Improve the thread viability test.
43286 	 */
43287 	thr = duk__get_temp_hthread(heap);
43288 	if (thr == NULL) {
43289 		DUK_D(DUK_DPRINT("gc skipped because we don't have a temp thread"));
43290 
43291 		/* reset voluntary gc trigger count */
43292 #ifdef DUK_USE_VOLUNTARY_GC
43293 		heap->mark_and_sweep_trigger_counter = DUK_HEAP_MARK_AND_SWEEP_TRIGGER_SKIP;
43294 #endif
43295 		return 0;  /* OK */
43296 	}
43297 
43298 	/* If debugger is paused, garbage collection is disabled by default. */
43299 	/* XXX: will need a force flag if garbage collection is triggered
43300 	 * explicitly during paused state.
43301 	 */
43302 #if defined(DUK_USE_DEBUGGER_SUPPORT)
43303 	if (DUK_HEAP_IS_PAUSED(heap)) {
43304 		/* Checking this here rather that in memory alloc primitives
43305 		 * reduces checking code there but means a failed allocation
43306 		 * will go through a few retries before giving up.  That's
43307 		 * fine because this only happens during debugging.
43308 		 */
43309 		DUK_D(DUK_DPRINT("gc skipped because debugger is paused"));
43310 		return 0;
43311 	}
43312 #endif
43313 
43314 	DUK_D(DUK_DPRINT("garbage collect (mark-and-sweep) starting, requested flags: 0x%08lx, effective flags: 0x%08lx",
43315 	                 (unsigned long) flags, (unsigned long) (flags | heap->mark_and_sweep_base_flags)));
43316 
43317 	flags |= heap->mark_and_sweep_base_flags;
43318 
43319 	/*
43320 	 *  Assertions before
43321 	 */
43322 
43323 #ifdef DUK_USE_ASSERTIONS
43324 	DUK_ASSERT(!DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap));
43325 	DUK_ASSERT(!DUK_HEAP_HAS_MARKANDSWEEP_RECLIMIT_REACHED(heap));
43326 	DUK_ASSERT(heap->mark_and_sweep_recursion_depth == 0);
43327 	duk__assert_heaphdr_flags(heap);
43328 #ifdef DUK_USE_REFERENCE_COUNTING
43329 	/* Note: DUK_HEAP_HAS_REFZERO_FREE_RUNNING(heap) may be true; a refcount
43330 	 * finalizer may trigger a mark-and-sweep.
43331 	 */
43332 	duk__assert_valid_refcounts(heap);
43333 #endif  /* DUK_USE_REFERENCE_COUNTING */
43334 #endif  /* DUK_USE_ASSERTIONS */
43335 
43336 	/*
43337 	 *  Begin
43338 	 */
43339 
43340 	DUK_HEAP_SET_MARKANDSWEEP_RUNNING(heap);
43341 
43342 	/*
43343 	 *  Mark roots, hoping that recursion limit is not normally hit.
43344 	 *  If recursion limit is hit, run additional reachability rounds
43345 	 *  starting from "temproots" until marking is complete.
43346 	 *
43347 	 *  Marking happens in two phases: first we mark actual reachability
43348 	 *  roots (and run "temproots" to complete the process).  Then we
43349 	 *  check which objects are unreachable and are finalizable; such
43350 	 *  objects are marked as FINALIZABLE and marked as reachability
43351 	 *  (and "temproots" is run again to complete the process).
43352 	 *
43353 	 *  The heap finalize_list must also be marked as a reachability root.
43354 	 *  There may be objects on the list from a previous round if the
43355 	 *  previous run had finalizer skip flag.
43356 	 */
43357 
43358 	duk__mark_roots_heap(heap);               /* main reachability roots */
43359 #ifdef DUK_USE_REFERENCE_COUNTING
43360 	duk__mark_refzero_list(heap);             /* refzero_list treated as reachability roots */
43361 #endif
43362 	duk__mark_temproots_by_heap_scan(heap);   /* temproots */
43363 
43364 	duk__mark_finalizable(heap);              /* mark finalizable as reachability roots */
43365 	duk__mark_finalize_list(heap);            /* mark finalizer work list as reachability roots */
43366 	duk__mark_temproots_by_heap_scan(heap);   /* temproots */
43367 
43368 	/*
43369 	 *  Sweep garbage and remove marking flags, and move objects with
43370 	 *  finalizers to the finalizer work list.
43371 	 *
43372 	 *  Objects to be swept need to get their refcounts finalized before
43373 	 *  they are swept.  In other words, their target object refcounts
43374 	 *  need to be decreased.  This has to be done before freeing any
43375 	 *  objects to avoid decref'ing dangling pointers (which may happen
43376 	 *  even without bugs, e.g. with reference loops)
43377 	 *
43378 	 *  Because strings don't point to other heap objects, similar
43379 	 *  finalization is not necessary for strings.
43380 	 */
43381 
43382 	/* XXX: more emergency behavior, e.g. find smaller hash sizes etc */
43383 
43384 #ifdef DUK_USE_REFERENCE_COUNTING
43385 	duk__finalize_refcounts(heap);
43386 #endif
43387 	duk__sweep_heap(heap, flags, &count_keep_obj);
43388 #if defined(DUK_USE_STRTAB_CHAIN)
43389 	duk__sweep_stringtable_chain(heap, &count_keep_str);
43390 #elif defined(DUK_USE_STRTAB_PROBE)
43391 	duk__sweep_stringtable_probe(heap, &count_keep_str);
43392 #else
43393 #error internal error, invalid strtab options
43394 #endif
43395 #ifdef DUK_USE_REFERENCE_COUNTING
43396 	duk__clear_refzero_list_flags(heap);
43397 #endif
43398 	duk__clear_finalize_list_flags(heap);
43399 
43400 	/*
43401 	 *  Object compaction (emergency only).
43402 	 *
43403 	 *  Object compaction is a separate step after sweeping, as there is
43404 	 *  more free memory for it to work with.  Also, currently compaction
43405 	 *  may insert new objects into the heap allocated list and the string
43406 	 *  table which we don't want to do during a sweep (the reachability
43407 	 *  flags of such objects would be incorrect).  The objects inserted
43408 	 *  are currently:
43409 	 *
43410 	 *    - a temporary duk_hbuffer for a new properties allocation
43411 	 *    - if array part is abandoned, string keys are interned
43412 	 *
43413 	 *  The object insertions go to the front of the list, so they do not
43414 	 *  cause an infinite loop (they are not compacted).
43415 	 */
43416 
43417 	if ((flags & DUK_MS_FLAG_EMERGENCY) &&
43418 	    !(flags & DUK_MS_FLAG_NO_OBJECT_COMPACTION)) {
43419 		duk__compact_objects(heap);
43420 	}
43421 
43422 	/*
43423 	 *  String table resize check.
43424 	 *
43425 	 *  Note: this may silently (and safely) fail if GC is caused by an
43426 	 *  allocation call in stringtable resize_hash().  Resize_hash()
43427 	 *  will prevent a recursive call to itself by setting the
43428 	 *  DUK_MS_FLAG_NO_STRINGTABLE_RESIZE in heap->mark_and_sweep_base_flags.
43429 	 */
43430 
43431 	/* XXX: stringtable emergency compaction? */
43432 
43433 	/* XXX: remove this feature entirely? it would only matter for
43434 	 * emergency GC.  Disable for lowest memory builds.
43435 	 */
43436 #if defined(DUK_USE_MS_STRINGTABLE_RESIZE)
43437 	if (!(flags & DUK_MS_FLAG_NO_STRINGTABLE_RESIZE)) {
43438 		DUK_DD(DUK_DDPRINT("resize stringtable: %p", (void *) heap));
43439 		duk_heap_force_strtab_resize(heap);
43440 	} else {
43441 		DUK_D(DUK_DPRINT("stringtable resize skipped because DUK_MS_FLAG_NO_STRINGTABLE_RESIZE is set"));
43442 	}
43443 #endif
43444 
43445 	/*
43446 	 *  Finalize objects in the finalization work list.  Finalized
43447 	 *  objects are queued back to heap_allocated with FINALIZED set.
43448 	 *
43449 	 *  Since finalizers may cause arbitrary side effects, they are
43450 	 *  prevented during string table and object property allocation
43451 	 *  resizing using the DUK_MS_FLAG_NO_FINALIZERS flag in
43452 	 *  heap->mark_and_sweep_base_flags.  In this case the objects
43453 	 *  remain in the finalization work list after mark-and-sweep
43454 	 *  exits and they may be finalized on the next pass.
43455 	 *
43456 	 *  Finalization currently happens inside "MARKANDSWEEP_RUNNING"
43457 	 *  protection (no mark-and-sweep may be triggered by the
43458 	 *  finalizers).  As a side effect:
43459 	 *
43460 	 *    1) an out-of-memory error inside a finalizer will not
43461 	 *       cause a mark-and-sweep and may cause the finalizer
43462 	 *       to fail unnecessarily
43463 	 *
43464 	 *    2) any temporary objects whose refcount decreases to zero
43465 	 *       during finalization will not be put into refzero_list;
43466 	 *       they can only be collected by another mark-and-sweep
43467 	 *
43468 	 *  This is not optimal, but since the sweep for this phase has
43469 	 *  already happened, this is probably good enough for now.
43470 	 */
43471 
43472 #if defined(DUK_USE_MARKANDSWEEP_FINALIZER_TORTURE)
43473 	/* Cannot simulate individual finalizers because finalize_list only
43474 	 * contains objects with actual finalizers.  But simulate side effects
43475 	 * from finalization by doing a bogus function call and resizing the
43476 	 * stacks.
43477 	 */
43478 	if (flags & DUK_MS_FLAG_NO_FINALIZERS) {
43479 		DUK_D(DUK_DPRINT("skip mark-and-sweep torture finalizer, DUK_MS_FLAG_NO_FINALIZERS is set"));
43480 	} else if (!(thr->valstack != NULL && thr->callstack != NULL && thr->catchstack != NULL)) {
43481 		DUK_D(DUK_DPRINT("skip mark-and-sweep torture finalizer, thread not yet viable"));
43482 	} else {
43483 		DUK_D(DUK_DPRINT("run mark-and-sweep torture finalizer"));
43484 		duk__markandsweep_torture_finalizer(thr);
43485 	}
43486 #endif  /* DUK_USE_MARKANDSWEEP_FINALIZER_TORTURE */
43487 
43488 	if (flags & DUK_MS_FLAG_NO_FINALIZERS) {
43489 		DUK_D(DUK_DPRINT("finalizer run skipped because DUK_MS_FLAG_NO_FINALIZERS is set"));
43490 	} else {
43491 		duk__run_object_finalizers(heap, flags);
43492 	}
43493 
43494 	/*
43495 	 *  Finish
43496 	 */
43497 
43498 	DUK_HEAP_CLEAR_MARKANDSWEEP_RUNNING(heap);
43499 
43500 	/*
43501 	 *  Assertions after
43502 	 */
43503 
43504 #ifdef DUK_USE_ASSERTIONS
43505 	DUK_ASSERT(!DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap));
43506 	DUK_ASSERT(!DUK_HEAP_HAS_MARKANDSWEEP_RECLIMIT_REACHED(heap));
43507 	DUK_ASSERT(heap->mark_and_sweep_recursion_depth == 0);
43508 	duk__assert_heaphdr_flags(heap);
43509 #ifdef DUK_USE_REFERENCE_COUNTING
43510 	/* Note: DUK_HEAP_HAS_REFZERO_FREE_RUNNING(heap) may be true; a refcount
43511 	 * finalizer may trigger a mark-and-sweep.
43512 	 */
43513 	duk__assert_valid_refcounts(heap);
43514 #endif  /* DUK_USE_REFERENCE_COUNTING */
43515 #endif  /* DUK_USE_ASSERTIONS */
43516 
43517 	/*
43518 	 *  Reset trigger counter
43519 	 */
43520 
43521 #ifdef DUK_USE_VOLUNTARY_GC
43522 	tmp = (count_keep_obj + count_keep_str) / 256;
43523 	heap->mark_and_sweep_trigger_counter = (duk_int_t) (
43524 	    (tmp * DUK_HEAP_MARK_AND_SWEEP_TRIGGER_MULT) +
43525 	    DUK_HEAP_MARK_AND_SWEEP_TRIGGER_ADD);
43526 	DUK_D(DUK_DPRINT("garbage collect (mark-and-sweep) finished: %ld objects kept, %ld strings kept, trigger reset to %ld",
43527 	                 (long) count_keep_obj, (long) count_keep_str, (long) heap->mark_and_sweep_trigger_counter));
43528 #else
43529 	DUK_D(DUK_DPRINT("garbage collect (mark-and-sweep) finished: %ld objects kept, %ld strings kept, no voluntary trigger",
43530 	                 (long) count_keep_obj, (long) count_keep_str));
43531 #endif
43532 
43533 	return 0;  /* OK */
43534 }
43535 
43536 #else  /* DUK_USE_MARK_AND_SWEEP */
43537 
43538 /* no mark-and-sweep gc */
43539 
43540 #endif  /* DUK_USE_MARK_AND_SWEEP */
43541 /*
43542  *  Memory allocation handling.
43543  */
43544 
43545 /* include removed: duk_internal.h */
43546 
43547 /*
43548  *  Helpers
43549  *
43550  *  The fast path checks are done within a macro to ensure "inlining"
43551  *  while the slow path actions use a helper (which won't typically be
43552  *  inlined in size optimized builds).
43553  */
43554 
43555 #if defined(DUK_USE_MARK_AND_SWEEP) && defined(DUK_USE_VOLUNTARY_GC)
43556 #define DUK__VOLUNTARY_PERIODIC_GC(heap)  do { \
43557 		(heap)->mark_and_sweep_trigger_counter--; \
43558 		if ((heap)->mark_and_sweep_trigger_counter <= 0) { \
43559 			duk__run_voluntary_gc(heap); \
43560 		} \
43561 	} while (0)
43562 
43563 DUK_LOCAL void duk__run_voluntary_gc(duk_heap *heap) {
43564 	if (DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap)) {
43565 		DUK_DD(DUK_DDPRINT("mark-and-sweep in progress -> skip voluntary mark-and-sweep now"));
43566 	} else {
43567 		duk_small_uint_t flags;
43568 		duk_bool_t rc;
43569 
43570 		DUK_D(DUK_DPRINT("triggering voluntary mark-and-sweep"));
43571 		flags = 0;
43572 		rc = duk_heap_mark_and_sweep(heap, flags);
43573 		DUK_UNREF(rc);
43574 	}
43575 }
43576 #else
43577 #define DUK__VOLUNTARY_PERIODIC_GC(heap)  /* no voluntary gc */
43578 #endif  /* DUK_USE_MARK_AND_SWEEP && DUK_USE_VOLUNTARY_GC */
43579 
43580 /*
43581  *  Allocate memory with garbage collection
43582  */
43583 
43584 #ifdef DUK_USE_MARK_AND_SWEEP
43585 DUK_INTERNAL void *duk_heap_mem_alloc(duk_heap *heap, duk_size_t size) {
43586 	void *res;
43587 	duk_bool_t rc;
43588 	duk_small_int_t i;
43589 
43590 	DUK_ASSERT(heap != NULL);
43591 	DUK_ASSERT_DISABLE(size >= 0);
43592 
43593 	/*
43594 	 *  Voluntary periodic GC (if enabled)
43595 	 */
43596 
43597 	DUK__VOLUNTARY_PERIODIC_GC(heap);
43598 
43599 	/*
43600 	 *  First attempt
43601 	 */
43602 
43603 #ifdef DUK_USE_GC_TORTURE
43604 	/* simulate alloc failure on every alloc (except when mark-and-sweep is running) */
43605 	if (!DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap)) {
43606 		DUK_DDD(DUK_DDDPRINT("gc torture enabled, pretend that first alloc attempt fails"));
43607 		res = NULL;
43608 		DUK_UNREF(res);
43609 		goto skip_attempt;
43610 	}
43611 #endif
43612 	res = heap->alloc_func(heap->heap_udata, size);
43613 	if (res || size == 0) {
43614 		/* for zero size allocations NULL is allowed */
43615 		return res;
43616 	}
43617 #ifdef DUK_USE_GC_TORTURE
43618  skip_attempt:
43619 #endif
43620 
43621 	DUK_D(DUK_DPRINT("first alloc attempt failed, attempt to gc and retry"));
43622 
43623 	/*
43624 	 *  Avoid a GC if GC is already running.  This can happen at a late
43625 	 *  stage in a GC when we try to e.g. resize the stringtable
43626 	 *  or compact objects.
43627 	 */
43628 
43629 	if (DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap)) {
43630 		DUK_D(DUK_DPRINT("duk_heap_mem_alloc() failed, gc in progress (gc skipped), alloc size %ld", (long) size));
43631 		return NULL;
43632 	}
43633 
43634 	/*
43635 	 *  Retry with several GC attempts.  Initial attempts are made without
43636 	 *  emergency mode; later attempts use emergency mode which minimizes
43637 	 *  memory allocations forcibly.
43638 	 */
43639 
43640 	for (i = 0; i < DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT; i++) {
43641 		duk_small_uint_t flags;
43642 
43643 		flags = 0;
43644 		if (i >= DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_EMERGENCY_LIMIT - 1) {
43645 			flags |= DUK_MS_FLAG_EMERGENCY;
43646 		}
43647 
43648 		rc = duk_heap_mark_and_sweep(heap, flags);
43649 		DUK_UNREF(rc);
43650 
43651 		res = heap->alloc_func(heap->heap_udata, size);
43652 		if (res) {
43653 			DUK_D(DUK_DPRINT("duk_heap_mem_alloc() succeeded after gc (pass %ld), alloc size %ld",
43654 			                 (long) (i + 1), (long) size));
43655 			return res;
43656 		}
43657 	}
43658 
43659 	DUK_D(DUK_DPRINT("duk_heap_mem_alloc() failed even after gc, alloc size %ld", (long) size));
43660 	return NULL;
43661 }
43662 #else  /* DUK_USE_MARK_AND_SWEEP */
43663 /*
43664  *  Compared to a direct macro expansion this wrapper saves a few
43665  *  instructions because no heap dereferencing is required.
43666  */
43667 DUK_INTERNAL void *duk_heap_mem_alloc(duk_heap *heap, duk_size_t size) {
43668 	DUK_ASSERT(heap != NULL);
43669 	DUK_ASSERT_DISABLE(size >= 0);
43670 
43671 	return heap->alloc_func(heap->heap_udata, size);
43672 }
43673 #endif  /* DUK_USE_MARK_AND_SWEEP */
43674 
43675 DUK_INTERNAL void *duk_heap_mem_alloc_zeroed(duk_heap *heap, duk_size_t size) {
43676 	void *res;
43677 
43678 	DUK_ASSERT(heap != NULL);
43679 	DUK_ASSERT_DISABLE(size >= 0);
43680 
43681 	res = DUK_ALLOC(heap, size);
43682 	if (res) {
43683 		/* assume memset with zero size is OK */
43684 		DUK_MEMZERO(res, size);
43685 	}
43686 	return res;
43687 }
43688 
43689 /*
43690  *  Reallocate memory with garbage collection
43691  */
43692 
43693 #ifdef DUK_USE_MARK_AND_SWEEP
43694 DUK_INTERNAL void *duk_heap_mem_realloc(duk_heap *heap, void *ptr, duk_size_t newsize) {
43695 	void *res;
43696 	duk_bool_t rc;
43697 	duk_small_int_t i;
43698 
43699 	DUK_ASSERT(heap != NULL);
43700 	/* ptr may be NULL */
43701 	DUK_ASSERT_DISABLE(newsize >= 0);
43702 
43703 	/*
43704 	 *  Voluntary periodic GC (if enabled)
43705 	 */
43706 
43707 	DUK__VOLUNTARY_PERIODIC_GC(heap);
43708 
43709 	/*
43710 	 *  First attempt
43711 	 */
43712 
43713 #ifdef DUK_USE_GC_TORTURE
43714 	/* simulate alloc failure on every realloc (except when mark-and-sweep is running) */
43715 	if (!DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap)) {
43716 		DUK_DDD(DUK_DDDPRINT("gc torture enabled, pretend that first realloc attempt fails"));
43717 		res = NULL;
43718 		DUK_UNREF(res);
43719 		goto skip_attempt;
43720 	}
43721 #endif
43722 	res = heap->realloc_func(heap->heap_udata, ptr, newsize);
43723 	if (res || newsize == 0) {
43724 		/* for zero size allocations NULL is allowed */
43725 		return res;
43726 	}
43727 #ifdef DUK_USE_GC_TORTURE
43728  skip_attempt:
43729 #endif
43730 
43731 	DUK_D(DUK_DPRINT("first realloc attempt failed, attempt to gc and retry"));
43732 
43733 	/*
43734 	 *  Avoid a GC if GC is already running.  See duk_heap_mem_alloc().
43735 	 */
43736 
43737 	if (DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap)) {
43738 		DUK_D(DUK_DPRINT("duk_heap_mem_realloc() failed, gc in progress (gc skipped), alloc size %ld", (long) newsize));
43739 		return NULL;
43740 	}
43741 
43742 	/*
43743 	 *  Retry with several GC attempts.  Initial attempts are made without
43744 	 *  emergency mode; later attempts use emergency mode which minimizes
43745 	 *  memory allocations forcibly.
43746 	 */
43747 
43748 	for (i = 0; i < DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT; i++) {
43749 		duk_small_uint_t flags;
43750 
43751 		flags = 0;
43752 		if (i >= DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_EMERGENCY_LIMIT - 1) {
43753 			flags |= DUK_MS_FLAG_EMERGENCY;
43754 		}
43755 
43756 		rc = duk_heap_mark_and_sweep(heap, flags);
43757 		DUK_UNREF(rc);
43758 
43759 		res = heap->realloc_func(heap->heap_udata, ptr, newsize);
43760 		if (res || newsize == 0) {
43761 			DUK_D(DUK_DPRINT("duk_heap_mem_realloc() succeeded after gc (pass %ld), alloc size %ld",
43762 			                 (long) (i + 1), (long) newsize));
43763 			return res;
43764 		}
43765 	}
43766 
43767 	DUK_D(DUK_DPRINT("duk_heap_mem_realloc() failed even after gc, alloc size %ld", (long) newsize));
43768 	return NULL;
43769 }
43770 #else  /* DUK_USE_MARK_AND_SWEEP */
43771 /* saves a few instructions to have this wrapper (see comment on duk_heap_mem_alloc) */
43772 DUK_INTERNAL void *duk_heap_mem_realloc(duk_heap *heap, void *ptr, duk_size_t newsize) {
43773 	DUK_ASSERT(heap != NULL);
43774 	/* ptr may be NULL */
43775 	DUK_ASSERT_DISABLE(newsize >= 0);
43776 
43777 	return heap->realloc_func(heap->heap_udata, ptr, newsize);
43778 }
43779 #endif  /* DUK_USE_MARK_AND_SWEEP */
43780 
43781 /*
43782  *  Reallocate memory with garbage collection, using a callback to provide
43783  *  the current allocated pointer.  This variant is used when a mark-and-sweep
43784  *  (e.g. finalizers) might change the original pointer.
43785  */
43786 
43787 #ifdef DUK_USE_MARK_AND_SWEEP
43788 DUK_INTERNAL void *duk_heap_mem_realloc_indirect(duk_heap *heap, duk_mem_getptr cb, void *ud, duk_size_t newsize) {
43789 	void *res;
43790 	duk_bool_t rc;
43791 	duk_small_int_t i;
43792 
43793 	DUK_ASSERT(heap != NULL);
43794 	DUK_ASSERT_DISABLE(newsize >= 0);
43795 
43796 	/*
43797 	 *  Voluntary periodic GC (if enabled)
43798 	 */
43799 
43800 	DUK__VOLUNTARY_PERIODIC_GC(heap);
43801 
43802 	/*
43803 	 *  First attempt
43804 	 */
43805 
43806 #ifdef DUK_USE_GC_TORTURE
43807 	/* simulate alloc failure on every realloc (except when mark-and-sweep is running) */
43808 	if (!DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap)) {
43809 		DUK_DDD(DUK_DDDPRINT("gc torture enabled, pretend that first indirect realloc attempt fails"));
43810 		res = NULL;
43811 		DUK_UNREF(res);
43812 		goto skip_attempt;
43813 	}
43814 #endif
43815 	res = heap->realloc_func(heap->heap_udata, cb(heap, ud), newsize);
43816 	if (res || newsize == 0) {
43817 		/* for zero size allocations NULL is allowed */
43818 		return res;
43819 	}
43820 #ifdef DUK_USE_GC_TORTURE
43821  skip_attempt:
43822 #endif
43823 
43824 	DUK_D(DUK_DPRINT("first indirect realloc attempt failed, attempt to gc and retry"));
43825 
43826 	/*
43827 	 *  Avoid a GC if GC is already running.  See duk_heap_mem_alloc().
43828 	 */
43829 
43830 	if (DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap)) {
43831 		DUK_D(DUK_DPRINT("duk_heap_mem_realloc_indirect() failed, gc in progress (gc skipped), alloc size %ld", (long) newsize));
43832 		return NULL;
43833 	}
43834 
43835 	/*
43836 	 *  Retry with several GC attempts.  Initial attempts are made without
43837 	 *  emergency mode; later attempts use emergency mode which minimizes
43838 	 *  memory allocations forcibly.
43839 	 */
43840 
43841 	for (i = 0; i < DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT; i++) {
43842 		duk_small_uint_t flags;
43843 
43844 #ifdef DUK_USE_ASSERTIONS
43845 		void *ptr_pre;  /* ptr before mark-and-sweep */
43846 		void *ptr_post;
43847 #endif
43848 
43849 #ifdef DUK_USE_ASSERTIONS
43850 		ptr_pre = cb(heap, ud);
43851 #endif
43852 		flags = 0;
43853 		if (i >= DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_EMERGENCY_LIMIT - 1) {
43854 			flags |= DUK_MS_FLAG_EMERGENCY;
43855 		}
43856 
43857 		rc = duk_heap_mark_and_sweep(heap, flags);
43858 		DUK_UNREF(rc);
43859 #ifdef DUK_USE_ASSERTIONS
43860 		ptr_post = cb(heap, ud);
43861 		if (ptr_pre != ptr_post) {
43862 			/* useful for debugging */
43863 			DUK_DD(DUK_DDPRINT("note: base pointer changed by mark-and-sweep: %p -> %p",
43864 			                   (void *) ptr_pre, (void *) ptr_post));
43865 		}
43866 #endif
43867 
43868 		/* Note: key issue here is to re-lookup the base pointer on every attempt.
43869 		 * The pointer being reallocated may change after every mark-and-sweep.
43870 		 */
43871 
43872 		res = heap->realloc_func(heap->heap_udata, cb(heap, ud), newsize);
43873 		if (res || newsize == 0) {
43874 			DUK_D(DUK_DPRINT("duk_heap_mem_realloc_indirect() succeeded after gc (pass %ld), alloc size %ld",
43875 			                 (long) (i + 1), (long) newsize));
43876 			return res;
43877 		}
43878 	}
43879 
43880 	DUK_D(DUK_DPRINT("duk_heap_mem_realloc_indirect() failed even after gc, alloc size %ld", (long) newsize));
43881 	return NULL;
43882 }
43883 #else  /* DUK_USE_MARK_AND_SWEEP */
43884 /* saves a few instructions to have this wrapper (see comment on duk_heap_mem_alloc) */
43885 DUK_INTERNAL void *duk_heap_mem_realloc_indirect(duk_heap *heap, duk_mem_getptr cb, void *ud, duk_size_t newsize) {
43886 	return heap->realloc_func(heap->heap_udata, cb(heap, ud), newsize);
43887 }
43888 #endif  /* DUK_USE_MARK_AND_SWEEP */
43889 
43890 /*
43891  *  Free memory
43892  */
43893 
43894 #ifdef DUK_USE_MARK_AND_SWEEP
43895 DUK_INTERNAL void duk_heap_mem_free(duk_heap *heap, void *ptr) {
43896 	DUK_ASSERT(heap != NULL);
43897 	/* ptr may be NULL */
43898 
43899 	/* Must behave like a no-op with NULL and any pointer returned from
43900 	 * malloc/realloc with zero size.
43901 	 */
43902 	heap->free_func(heap->heap_udata, ptr);
43903 
43904 	/* Count free operations toward triggering a GC but never actually trigger
43905 	 * a GC from a free.  Otherwise code which frees internal structures would
43906 	 * need to put in NULLs at every turn to ensure the object is always in
43907 	 * consistent state for a mark-and-sweep.
43908 	 */
43909 #ifdef DUK_USE_VOLUNTARY_GC
43910 	heap->mark_and_sweep_trigger_counter--;
43911 #endif
43912 }
43913 #else
43914 /* saves a few instructions to have this wrapper (see comment on duk_heap_mem_alloc) */
43915 DUK_INTERNAL void duk_heap_mem_free(duk_heap *heap, void *ptr) {
43916 	DUK_ASSERT(heap != NULL);
43917 	/* ptr may be NULL */
43918 
43919 	/* Note: must behave like a no-op with NULL and any pointer
43920 	 * returned from malloc/realloc with zero size.
43921 	 */
43922 	heap->free_func(heap->heap_udata, ptr);
43923 }
43924 #endif
43925 /*
43926  *  Support functions for duk_heap.
43927  */
43928 
43929 /* include removed: duk_internal.h */
43930 
43931 #if defined(DUK_USE_DOUBLE_LINKED_HEAP) && defined(DUK_USE_REFERENCE_COUNTING)
43932 /* arbitrary remove only works with double linked heap, and is only required by
43933  * reference counting so far.
43934  */
43935 DUK_INTERNAL void duk_heap_remove_any_from_heap_allocated(duk_heap *heap, duk_heaphdr *hdr) {
43936 	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(hdr) != DUK_HTYPE_STRING);
43937 
43938 	if (DUK_HEAPHDR_GET_PREV(heap, hdr)) {
43939 		DUK_HEAPHDR_SET_NEXT(heap, DUK_HEAPHDR_GET_PREV(heap, hdr), DUK_HEAPHDR_GET_NEXT(heap, hdr));
43940 	} else {
43941 		heap->heap_allocated = DUK_HEAPHDR_GET_NEXT(heap, hdr);
43942 	}
43943 	if (DUK_HEAPHDR_GET_NEXT(heap, hdr)) {
43944 		DUK_HEAPHDR_SET_PREV(heap, DUK_HEAPHDR_GET_NEXT(heap, hdr), DUK_HEAPHDR_GET_PREV(heap, hdr));
43945 	} else {
43946 		;
43947 	}
43948 
43949 	/* The prev/next pointers of the removed duk_heaphdr are left as garbage.
43950 	 * It's up to the caller to ensure they're written before inserting the
43951 	 * object back.
43952 	 */
43953 }
43954 #endif
43955 
43956 DUK_INTERNAL void duk_heap_insert_into_heap_allocated(duk_heap *heap, duk_heaphdr *hdr) {
43957 	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(hdr) != DUK_HTYPE_STRING);
43958 
43959 #ifdef DUK_USE_DOUBLE_LINKED_HEAP
43960 	if (heap->heap_allocated) {
43961 		DUK_ASSERT(DUK_HEAPHDR_GET_PREV(heap, heap->heap_allocated) == NULL);
43962 		DUK_HEAPHDR_SET_PREV(heap, heap->heap_allocated, hdr);
43963 	}
43964 	DUK_HEAPHDR_SET_PREV(heap, hdr, NULL);
43965 #endif
43966 	DUK_HEAPHDR_SET_NEXT(heap, hdr, heap->heap_allocated);
43967 	heap->heap_allocated = hdr;
43968 }
43969 
43970 #ifdef DUK_USE_INTERRUPT_COUNTER
43971 DUK_INTERNAL void duk_heap_switch_thread(duk_heap *heap, duk_hthread *new_thr) {
43972 	duk_hthread *curr_thr;
43973 
43974 	DUK_ASSERT(heap != NULL);
43975 
43976 	if (new_thr != NULL) {
43977 		curr_thr = heap->curr_thread;
43978 		if (curr_thr == NULL) {
43979 			/* For initial entry use default value; zero forces an
43980 			 * interrupt before executing the first insturction.
43981 			 */
43982 			DUK_DD(DUK_DDPRINT("switch thread, initial entry, init default interrupt counter"));
43983 			new_thr->interrupt_counter = 0;
43984 			new_thr->interrupt_init = 0;
43985 		} else {
43986 			/* Copy interrupt counter/init value state to new thread (if any).
43987 			 * It's OK for new_thr to be the same as curr_thr.
43988 			 */
43989 #if defined(DUK_USE_DEBUG)
43990 			if (new_thr != curr_thr) {
43991 				DUK_DD(DUK_DDPRINT("switch thread, not initial entry, copy interrupt counter"));
43992 			}
43993 #endif
43994 			new_thr->interrupt_counter = curr_thr->interrupt_counter;
43995 			new_thr->interrupt_init = curr_thr->interrupt_init;
43996 		}
43997 	} else {
43998 		DUK_DD(DUK_DDPRINT("switch thread, new thread is NULL, no interrupt counter changes"));
43999 	}
44000 
44001 	heap->curr_thread = new_thr;  /* may be NULL */
44002 }
44003 #endif  /* DUK_USE_INTERRUPT_COUNTER */
44004 /*
44005  *  Reference counting implementation.
44006  */
44007 
44008 /* include removed: duk_internal.h */
44009 
44010 #ifdef DUK_USE_REFERENCE_COUNTING
44011 
44012 #ifndef DUK_USE_DOUBLE_LINKED_HEAP
44013 #error internal error, reference counting requires a double linked heap
44014 #endif
44015 
44016 /*
44017  *  Misc
44018  */
44019 
44020 DUK_LOCAL void duk__queue_refzero(duk_heap *heap, duk_heaphdr *hdr) {
44021 	/* tail insert: don't disturb head in case refzero is running */
44022 
44023 	if (heap->refzero_list != NULL) {
44024 		duk_heaphdr *hdr_prev;
44025 
44026 		hdr_prev = heap->refzero_list_tail;
44027 		DUK_ASSERT(hdr_prev != NULL);
44028 		DUK_ASSERT(DUK_HEAPHDR_GET_NEXT(heap, hdr_prev) == NULL);
44029 
44030 		DUK_HEAPHDR_SET_NEXT(heap, hdr, NULL);
44031 		DUK_HEAPHDR_SET_PREV(heap, hdr, hdr_prev);
44032 		DUK_HEAPHDR_SET_NEXT(heap, hdr_prev, hdr);
44033 		DUK_ASSERT_HEAPHDR_LINKS(heap, hdr);
44034 		DUK_ASSERT_HEAPHDR_LINKS(heap, hdr_prev);
44035 		heap->refzero_list_tail = hdr;
44036 	} else {
44037 		DUK_ASSERT(heap->refzero_list_tail == NULL);
44038 		DUK_HEAPHDR_SET_NEXT(heap, hdr, NULL);
44039 		DUK_HEAPHDR_SET_PREV(heap, hdr, NULL);
44040 		DUK_ASSERT_HEAPHDR_LINKS(heap, hdr);
44041 		heap->refzero_list = hdr;
44042 		heap->refzero_list_tail = hdr;
44043 	}
44044 }
44045 
44046 /*
44047  *  Heap object refcount finalization.
44048  *
44049  *  When an object is about to be freed, all other objects it refers to must
44050  *  be decref'd.  Refcount finalization does NOT free the object or its inner
44051  *  allocations (mark-and-sweep shares these helpers), it just manipulates
44052  *  the refcounts.
44053  *
44054  *  Note that any of the decref's may cause a refcount to drop to zero, BUT
44055  *  it will not be processed inline; instead, because refzero is already
44056  *  running, the objects will just be queued to refzero list and processed
44057  *  later.  This eliminates C recursion.
44058  */
44059 
44060 DUK_LOCAL void duk__refcount_finalize_hobject(duk_hthread *thr, duk_hobject *h) {
44061 	duk_uint_fast32_t i;
44062 
44063 	DUK_ASSERT(h);
44064 	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) h) == DUK_HTYPE_OBJECT);
44065 
44066 	/* XXX: better to get base and walk forwards? */
44067 
44068 	for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h); i++) {
44069 		duk_hstring *key = DUK_HOBJECT_E_GET_KEY(thr->heap, h, i);
44070 		if (!key) {
44071 			continue;
44072 		}
44073 		duk_heaphdr_decref(thr, (duk_heaphdr *) key);
44074 		if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, h, i)) {
44075 			duk_heaphdr_decref_allownull(thr, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, h, i));
44076 			duk_heaphdr_decref_allownull(thr, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, h, i));
44077 		} else {
44078 			duk_tval_decref(thr, DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, h, i));
44079 		}
44080 	}
44081 
44082 	for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(h); i++) {
44083 		duk_tval_decref(thr, DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, h, i));
44084 	}
44085 
44086 	/* hash part is a 'weak reference' and does not contribute */
44087 
44088 	duk_heaphdr_decref_allownull(thr, (duk_heaphdr *) DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h));
44089 
44090 	if (DUK_HOBJECT_IS_COMPILEDFUNCTION(h)) {
44091 		duk_hcompiledfunction *f = (duk_hcompiledfunction *) h;
44092 		duk_tval *tv, *tv_end;
44093 		duk_hobject **funcs, **funcs_end;
44094 
44095 		if (DUK_HCOMPILEDFUNCTION_GET_DATA(thr->heap, f) != NULL) {
44096 			tv = DUK_HCOMPILEDFUNCTION_GET_CONSTS_BASE(thr->heap, f);
44097 			tv_end = DUK_HCOMPILEDFUNCTION_GET_CONSTS_END(thr->heap, f);
44098 			while (tv < tv_end) {
44099 				duk_tval_decref(thr, tv);
44100 				tv++;
44101 			}
44102 
44103 			funcs = DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE(thr->heap, f);
44104 			funcs_end = DUK_HCOMPILEDFUNCTION_GET_FUNCS_END(thr->heap, f);
44105 			while (funcs < funcs_end) {
44106 				duk_heaphdr_decref(thr, (duk_heaphdr *) *funcs);
44107 				funcs++;
44108 			}
44109 		} else {
44110 			/* May happen in some out-of-memory corner cases. */
44111 			DUK_D(DUK_DPRINT("duk_hcompiledfunction 'data' is NULL, skipping decref"));
44112 		}
44113 
44114 		duk_heaphdr_decref(thr, (duk_heaphdr *) DUK_HCOMPILEDFUNCTION_GET_DATA(thr->heap, f));
44115 	} else if (DUK_HOBJECT_IS_NATIVEFUNCTION(h)) {
44116 		duk_hnativefunction *f = (duk_hnativefunction *) h;
44117 		DUK_UNREF(f);
44118 		/* nothing to finalize */
44119 	} else if (DUK_HOBJECT_IS_BUFFEROBJECT(h)) {
44120 		duk_hbufferobject *b = (duk_hbufferobject *) h;
44121 		if (b->buf) {
44122 			duk_heaphdr_decref(thr, (duk_heaphdr *) b->buf);
44123 		}
44124 	} else if (DUK_HOBJECT_IS_THREAD(h)) {
44125 		duk_hthread *t = (duk_hthread *) h;
44126 		duk_tval *tv;
44127 
44128 		tv = t->valstack;
44129 		while (tv < t->valstack_top) {
44130 			duk_tval_decref(thr, tv);
44131 			tv++;
44132 		}
44133 
44134 		for (i = 0; i < (duk_uint_fast32_t) t->callstack_top; i++) {
44135 			duk_activation *act = t->callstack + i;
44136 			duk_heaphdr_decref_allownull(thr, (duk_heaphdr *) DUK_ACT_GET_FUNC(act));
44137 			duk_heaphdr_decref_allownull(thr, (duk_heaphdr *) act->var_env);
44138 			duk_heaphdr_decref_allownull(thr, (duk_heaphdr *) act->lex_env);
44139 #ifdef DUK_USE_NONSTD_FUNC_CALLER_PROPERTY
44140 			duk_heaphdr_decref_allownull(thr, (duk_heaphdr *) act->prev_caller);
44141 #endif
44142 		}
44143 
44144 #if 0  /* nothing now */
44145 		for (i = 0; i < (duk_uint_fast32_t) t->catchstack_top; i++) {
44146 			duk_catcher *cat = t->catchstack + i;
44147 		}
44148 #endif
44149 
44150 		for (i = 0; i < DUK_NUM_BUILTINS; i++) {
44151 			duk_heaphdr_decref_allownull(thr, (duk_heaphdr *) t->builtins[i]);
44152 		}
44153 
44154 		duk_heaphdr_decref_allownull(thr, (duk_heaphdr *) t->resumer);
44155 	}
44156 }
44157 
44158 DUK_INTERNAL void duk_heaphdr_refcount_finalize(duk_hthread *thr, duk_heaphdr *hdr) {
44159 	DUK_ASSERT(hdr);
44160 
44161 	switch ((int) DUK_HEAPHDR_GET_TYPE(hdr)) {
44162 	case DUK_HTYPE_OBJECT:
44163 		duk__refcount_finalize_hobject(thr, (duk_hobject *) hdr);
44164 		break;
44165 	case DUK_HTYPE_BUFFER:
44166 		/* nothing to finalize */
44167 		break;
44168 	case DUK_HTYPE_STRING:
44169 		/* cannot happen: strings are not put into refzero list (they don't even have the next/prev pointers) */
44170 	default:
44171 		DUK_UNREACHABLE();
44172 	}
44173 }
44174 
44175 #if defined(DUK_USE_REFZERO_FINALIZER_TORTURE)
44176 DUK_LOCAL duk_ret_t duk__refcount_fake_finalizer(duk_context *ctx) {
44177 	DUK_UNREF(ctx);
44178 	DUK_D(DUK_DPRINT("fake refcount torture finalizer executed"));
44179 #if 0
44180 	DUK_DD(DUK_DDPRINT("fake torture finalizer for: %!T", duk_get_tval(ctx, 0)));
44181 #endif
44182 	/* Require a lot of stack to force a value stack grow/shrink. */
44183 	duk_require_stack(ctx, 100000);
44184 
44185 	/* XXX: do something to force a callstack grow/shrink, perhaps
44186 	 * just a manual forced resize?
44187 	 */
44188 	return 0;
44189 }
44190 
44191 DUK_LOCAL void duk__refcount_run_torture_finalizer(duk_hthread *thr, duk_hobject *obj) {
44192 	duk_context *ctx;
44193 	duk_int_t rc;
44194 
44195 	DUK_ASSERT(thr != NULL);
44196 	DUK_ASSERT(obj != NULL);
44197 	ctx = (duk_context *) thr;
44198 
44199 	/* Avoid fake finalization for the duk__refcount_fake_finalizer function
44200 	 * itself, otherwise we're in infinite recursion.
44201 	 */
44202 	if (DUK_HOBJECT_HAS_NATIVEFUNCTION(obj)) {
44203 		if (((duk_hnativefunction *) obj)->func == duk__refcount_fake_finalizer) {
44204 			DUK_DD(DUK_DDPRINT("avoid fake torture finalizer for duk__refcount_fake_finalizer itself"));
44205 			return;
44206 		}
44207 	}
44208 	/* Avoid fake finalization when callstack limit has been reached.
44209 	 * Otherwise a callstack limit error will be created, then refzero'ed,
44210 	 * and we're in an infinite loop.
44211 	 */
44212 	if (thr->heap->call_recursion_depth >= thr->heap->call_recursion_limit ||
44213 	    thr->callstack_size + 2 * DUK_CALLSTACK_GROW_STEP >= thr->callstack_max /*approximate*/) {
44214 		DUK_D(DUK_DPRINT("call recursion depth reached, avoid fake torture finalizer"));
44215 		return;
44216 	}
44217 
44218 	/* Run fake finalizer.  Avoid creating new refzero queue entries
44219 	 * so that we are not forced into a forever loop.
44220 	 */
44221 	duk_push_c_function(ctx, duk__refcount_fake_finalizer, 1 /*nargs*/);
44222 	duk_push_hobject(ctx, obj);
44223 	rc = duk_pcall(ctx, 1);
44224 	DUK_UNREF(rc);  /* ignored */
44225 	duk_pop(ctx);
44226 }
44227 #endif  /* DUK_USE_REFZERO_FINALIZER_TORTURE */
44228 
44229 /*
44230  *  Refcount memory freeing loop.
44231  *
44232  *  Frees objects in the refzero_pending list until the list becomes
44233  *  empty.  When an object is freed, its references get decref'd and
44234  *  may cause further objects to be queued for freeing.
44235  *
44236  *  This could be expanded to allow incremental freeing: just bail out
44237  *  early and resume at a future alloc/decref/refzero.
44238  */
44239 
44240 DUK_LOCAL void duk__refzero_free_pending(duk_hthread *thr) {
44241 	duk_heaphdr *h1, *h2;
44242 	duk_heap *heap;
44243 	duk_int_t count = 0;
44244 
44245 	DUK_ASSERT(thr != NULL);
44246 	DUK_ASSERT(thr->heap != NULL);
44247 	heap = thr->heap;
44248 	DUK_ASSERT(heap != NULL);
44249 
44250 	/*
44251 	 *  Detect recursive invocation
44252 	 */
44253 
44254 	if (DUK_HEAP_HAS_REFZERO_FREE_RUNNING(heap)) {
44255 		DUK_DDD(DUK_DDDPRINT("refzero free running, skip run"));
44256 		return;
44257 	}
44258 
44259 	/*
44260 	 *  Churn refzero_list until empty
44261 	 */
44262 
44263 	DUK_HEAP_SET_REFZERO_FREE_RUNNING(heap);
44264 	while (heap->refzero_list) {
44265 		duk_hobject *obj;
44266 		duk_bool_t rescued = 0;
44267 
44268 		/*
44269 		 *  Pick an object from the head (don't remove yet).
44270 		 */
44271 
44272 		h1 = heap->refzero_list;
44273 		obj = (duk_hobject *) h1;
44274 		DUK_DD(DUK_DDPRINT("refzero processing %p: %!O", (void *) h1, (duk_heaphdr *) h1));
44275 		DUK_ASSERT(DUK_HEAPHDR_GET_PREV(heap, h1) == NULL);
44276 		DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(h1) == DUK_HTYPE_OBJECT);  /* currently, always the case */
44277 
44278 #if defined(DUK_USE_REFZERO_FINALIZER_TORTURE)
44279 		/* Torture option to shake out finalizer side effect issues:
44280 		 * make a bogus function call for every finalizable object,
44281 		 * essentially simulating the case where everything has a
44282 		 * finalizer.
44283 		 */
44284 		DUK_DD(DUK_DDPRINT("refzero torture enabled, fake finalizer"));
44285 		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(h1) == 0);
44286 		DUK_HEAPHDR_PREINC_REFCOUNT(h1);  /* bump refcount to prevent refzero during finalizer processing */
44287 		duk__refcount_run_torture_finalizer(thr, obj);  /* must never longjmp */
44288 		DUK_HEAPHDR_PREDEC_REFCOUNT(h1);  /* remove artificial bump */
44289 		DUK_ASSERT_DISABLE(h1->h_refcount >= 0);  /* refcount is unsigned, so always true */
44290 #endif
44291 
44292 		/*
44293 		 *  Finalizer check.
44294 		 *
44295 		 *  Note: running a finalizer may have arbitrary side effects, e.g.
44296 		 *  queue more objects on refzero_list (tail), or even trigger a
44297 		 *  mark-and-sweep.
44298 		 *
44299 		 *  Note: quick reject check should match vast majority of
44300 		 *  objects and must be safe (not throw any errors, ever).
44301 		 */
44302 
44303 		/* An object may have FINALIZED here if it was finalized by mark-and-sweep
44304 		 * on a previous run and refcount then decreased to zero.  We won't run the
44305 		 * finalizer again here.
44306 		 */
44307 
44308 		/* A finalizer is looked up from the object and up its prototype chain
44309 		 * (which allows inherited finalizers).
44310 		 */
44311 		if (duk_hobject_hasprop_raw(thr, obj, DUK_HTHREAD_STRING_INT_FINALIZER(thr))) {
44312 			DUK_DDD(DUK_DDDPRINT("object has a finalizer, run it"));
44313 
44314 			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(h1) == 0);
44315 			DUK_HEAPHDR_PREINC_REFCOUNT(h1);  /* bump refcount to prevent refzero during finalizer processing */
44316 
44317 			duk_hobject_run_finalizer(thr, obj);  /* must never longjmp */
44318 			DUK_ASSERT(DUK_HEAPHDR_HAS_FINALIZED(h1));  /* duk_hobject_run_finalizer() sets */
44319 
44320 			DUK_HEAPHDR_PREDEC_REFCOUNT(h1);  /* remove artificial bump */
44321 			DUK_ASSERT_DISABLE(h1->h_refcount >= 0);  /* refcount is unsigned, so always true */
44322 
44323 			if (DUK_HEAPHDR_GET_REFCOUNT(h1) != 0) {
44324 				DUK_DDD(DUK_DDDPRINT("-> object refcount after finalization non-zero, object will be rescued"));
44325 				rescued = 1;
44326 			} else {
44327 				DUK_DDD(DUK_DDDPRINT("-> object refcount still zero after finalization, object will be freed"));
44328 			}
44329 		}
44330 
44331 		/* Refzero head is still the same.  This is the case even if finalizer
44332 		 * inserted more refzero objects; they are inserted to the tail.
44333 		 */
44334 		DUK_ASSERT(h1 == heap->refzero_list);
44335 
44336 		/*
44337 		 *  Remove the object from the refzero list.  This cannot be done
44338 		 *  before a possible finalizer has been executed; the finalizer
44339 		 *  may trigger a mark-and-sweep, and mark-and-sweep must be able
44340 		 *  to traverse a complete refzero_list.
44341 		 */
44342 
44343 		h2 = DUK_HEAPHDR_GET_NEXT(heap, h1);
44344 		if (h2) {
44345 			DUK_HEAPHDR_SET_PREV(heap, h2, NULL);  /* not strictly necessary */
44346 			heap->refzero_list = h2;
44347 		} else {
44348 			heap->refzero_list = NULL;
44349 			heap->refzero_list_tail = NULL;
44350 		}
44351 
44352 		/*
44353 		 *  Rescue or free.
44354 		 */
44355 
44356 		if (rescued) {
44357 			/* yes -> move back to heap allocated */
44358 			DUK_DD(DUK_DDPRINT("object rescued during refcount finalization: %p", (void *) h1));
44359 			DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(h1));
44360 			DUK_ASSERT(DUK_HEAPHDR_HAS_FINALIZED(h1));
44361 			DUK_HEAPHDR_CLEAR_FINALIZED(h1);
44362 			h2 = heap->heap_allocated;
44363 			DUK_HEAPHDR_SET_PREV(heap, h1, NULL);
44364 			if (h2) {
44365 				DUK_HEAPHDR_SET_PREV(heap, h2, h1);
44366 			}
44367 			DUK_HEAPHDR_SET_NEXT(heap, h1, h2);
44368 			DUK_ASSERT_HEAPHDR_LINKS(heap, h1);
44369 			DUK_ASSERT_HEAPHDR_LINKS(heap, h2);
44370 			heap->heap_allocated = h1;
44371 		} else {
44372 			/* no -> decref members, then free */
44373 			duk__refcount_finalize_hobject(thr, obj);
44374 			duk_heap_free_heaphdr_raw(heap, h1);
44375 		}
44376 
44377 		count++;
44378 	}
44379 	DUK_HEAP_CLEAR_REFZERO_FREE_RUNNING(heap);
44380 
44381 	DUK_DDD(DUK_DDDPRINT("refzero processed %ld objects", (long) count));
44382 
44383 	/*
44384 	 *  Once the whole refzero cascade has been freed, check for
44385 	 *  a voluntary mark-and-sweep.
44386 	 */
44387 
44388 #if defined(DUK_USE_MARK_AND_SWEEP) && defined(DUK_USE_VOLUNTARY_GC)
44389 	/* 'count' is more or less comparable to normal trigger counter update
44390 	 * which happens in memory block (re)allocation.
44391 	 */
44392 	heap->mark_and_sweep_trigger_counter -= count;
44393 	if (heap->mark_and_sweep_trigger_counter <= 0) {
44394 		if (DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap)) {
44395 			DUK_D(DUK_DPRINT("mark-and-sweep in progress -> skip voluntary mark-and-sweep now"));
44396 		} else {
44397 			duk_bool_t rc;
44398 			duk_small_uint_t flags = 0;  /* not emergency */
44399 			DUK_D(DUK_DPRINT("refcount triggering mark-and-sweep"));
44400 			rc = duk_heap_mark_and_sweep(heap, flags);
44401 			DUK_UNREF(rc);
44402 			DUK_D(DUK_DPRINT("refcount triggered mark-and-sweep => rc %ld", (long) rc));
44403 		}
44404 	}
44405 #endif  /* DUK_USE_MARK_AND_SWEEP && DUK_USE_VOLUNTARY_GC */
44406 }
44407 
44408 /*
44409  *  Incref and decref functions.
44410  *
44411  *  Decref may trigger immediate refzero handling, which may free and finalize
44412  *  an arbitrary number of objects.
44413  *
44414  */
44415 
44416 DUK_INTERNAL void duk_heaphdr_refzero(duk_hthread *thr, duk_heaphdr *h) {
44417 	duk_heap *heap;
44418 
44419 	DUK_ASSERT(thr != NULL);
44420 	DUK_ASSERT(h != NULL);
44421 
44422 	heap = thr->heap;
44423 	DUK_DDD(DUK_DDDPRINT("refzero %p: %!O", (void *) h, (duk_heaphdr *) h));
44424 
44425 	/*
44426 	 *  Refzero handling is skipped entirely if (1) mark-and-sweep is
44427 	 *  running or (2) execution is paused in the debugger.  The objects
44428 	 *  are left in the heap, and will be freed by mark-and-sweep or
44429 	 *  eventual heap destruction.
44430 	 *
44431 	 *  This is necessary during mark-and-sweep because refcounts are also
44432 	 *  updated during the sweep phase (otherwise objects referenced by a
44433 	 *  swept object would have incorrect refcounts) which then calls here.
44434 	 *  This could be avoided by using separate decref macros in
44435 	 *  mark-and-sweep; however, mark-and-sweep also calls finalizers which
44436 	 *  would use the ordinary decref macros anyway and still call this
44437 	 *  function.
44438 	 *
44439 	 *  This check must be enabled also when mark-and-sweep support has been
44440 	 *  disabled: the flag is also used in heap destruction when running
44441 	 *  finalizers for remaining objects, and the flag prevents objects from
44442 	 *  being moved around in heap linked lists.
44443 	 */
44444 
44445 	/* XXX: ideally this would be just one flag (maybe a derived one) so
44446 	 * that a single bit test is sufficient to check the condition.
44447 	 */
44448 #if defined(DUK_USE_DEBUGGER_SUPPORT)
44449 	if (DUK_UNLIKELY(DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap) || DUK_HEAP_IS_PAUSED(heap))) {
44450 #else
44451 	if (DUK_UNLIKELY(DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap))) {
44452 #endif
44453 		DUK_DDD(DUK_DDDPRINT("refzero handling suppressed when mark-and-sweep running, object: %p", (void *) h));
44454 		return;
44455 	}
44456 
44457 	switch ((duk_small_int_t) DUK_HEAPHDR_GET_TYPE(h)) {
44458 	case DUK_HTYPE_STRING:
44459 		/*
44460 		 *  Strings have no internal references but do have "weak"
44461 		 *  references in the string cache.  Also note that strings
44462 		 *  are not on the heap_allocated list like other heap
44463 		 *  elements.
44464 		 */
44465 
44466 		duk_heap_strcache_string_remove(heap, (duk_hstring *) h);
44467 		duk_heap_string_remove(heap, (duk_hstring *) h);
44468 		duk_heap_free_heaphdr_raw(heap, h);
44469 		break;
44470 
44471 	case DUK_HTYPE_OBJECT:
44472 		/*
44473 		 *  Objects have internal references.  Must finalize through
44474 		 *  the "refzero" work list.
44475 		 */
44476 
44477 		duk_heap_remove_any_from_heap_allocated(heap, h);
44478 		duk__queue_refzero(heap, h);
44479 		duk__refzero_free_pending(thr);
44480 		break;
44481 
44482 	case DUK_HTYPE_BUFFER:
44483 		/*
44484 		 *  Buffers have no internal references.  However, a dynamic
44485 		 *  buffer has a separate allocation for the buffer.  This is
44486 		 *  freed by duk_heap_free_heaphdr_raw().
44487 		 */
44488 
44489 		duk_heap_remove_any_from_heap_allocated(heap, h);
44490 		duk_heap_free_heaphdr_raw(heap, h);
44491 		break;
44492 
44493 	default:
44494 		DUK_D(DUK_DPRINT("invalid heap type in decref: %ld", (long) DUK_HEAPHDR_GET_TYPE(h)));
44495 		DUK_UNREACHABLE();
44496 	}
44497 }
44498 
44499 #if !defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
44500 DUK_INTERNAL void duk_tval_incref(duk_tval *tv) {
44501 	DUK_ASSERT(tv != NULL);
44502 
44503 	if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv)) {
44504 		duk_heaphdr *h = DUK_TVAL_GET_HEAPHDR(tv);
44505 		DUK_ASSERT(h != NULL);
44506 		DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
44507 		DUK_ASSERT_DISABLE(h->h_refcount >= 0);
44508 		DUK_HEAPHDR_PREINC_REFCOUNT(h);
44509 	}
44510 }
44511 #endif
44512 
44513 #if 0  /* unused */
44514 DUK_INTERNAL void duk_tval_incref_allownull(duk_tval *tv) {
44515 	if (tv == NULL) {
44516 		return;
44517 	}
44518 	if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv)) {
44519 		duk_heaphdr *h = DUK_TVAL_GET_HEAPHDR(tv);
44520 		DUK_ASSERT(h != NULL);
44521 		DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
44522 		DUK_ASSERT_DISABLE(h->h_refcount >= 0);
44523 		DUK_HEAPHDR_PREINC_REFCOUNT(h);
44524 	}
44525 }
44526 #endif
44527 
44528 DUK_INTERNAL void duk_tval_decref(duk_hthread *thr, duk_tval *tv) {
44529 	DUK_ASSERT(thr != NULL);
44530 	DUK_ASSERT(tv != NULL);
44531 
44532 	if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv)) {
44533 		duk_heaphdr *h = DUK_TVAL_GET_HEAPHDR(tv);
44534 		DUK_ASSERT(h != NULL);
44535 		DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
44536 		duk_heaphdr_decref(thr, h);
44537 	}
44538 }
44539 
44540 #if 0  /* unused */
44541 DUK_INTERNAL void duk_tval_decref_allownull(duk_hthread *thr, duk_tval *tv) {
44542 	DUK_ASSERT(thr != NULL);
44543 
44544 	if (tv == NULL) {
44545 		return;
44546 	}
44547 	if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv)) {
44548 		duk_heaphdr *h = DUK_TVAL_GET_HEAPHDR(tv);
44549 		DUK_ASSERT(h != NULL);
44550 		DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
44551 		duk_heaphdr_decref(thr, h);
44552 	}
44553 }
44554 #endif
44555 
44556 #if !defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
44557 DUK_INTERNAL void duk_heaphdr_incref(duk_heaphdr *h) {
44558 	DUK_ASSERT(h != NULL);
44559 	DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
44560 	DUK_ASSERT_DISABLE(DUK_HEAPHDR_GET_REFCOUNT(h) >= 0);
44561 
44562 #if defined(DUK_USE_ROM_OBJECTS)
44563 	if (DUK_HEAPHDR_HAS_READONLY(h)) {
44564 		return;
44565 	}
44566 #endif
44567 
44568 	DUK_HEAPHDR_PREINC_REFCOUNT(h);
44569 }
44570 #endif
44571 
44572 #if 0  /* unused */
44573 DUK_INTERNAL void duk_heaphdr_incref_allownull(duk_heaphdr *h) {
44574 	if (h == NULL) {
44575 		return;
44576 	}
44577 	DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
44578 	DUK_ASSERT_DISABLE(DUK_HEAPHDR_GET_REFCOUNT(h) >= 0);
44579 
44580 	DUK_HEAPHDR_PREINC_REFCOUNT(h);
44581 }
44582 #endif
44583 
44584 DUK_INTERNAL void duk_heaphdr_decref(duk_hthread *thr, duk_heaphdr *h) {
44585 	DUK_ASSERT(thr != NULL);
44586 	DUK_ASSERT(thr->heap != NULL);
44587 	DUK_ASSERT(h != NULL);
44588 	DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
44589 	DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(h) >= 1);
44590 
44591 #if defined(DUK_USE_ROM_OBJECTS)
44592 	if (DUK_HEAPHDR_HAS_READONLY(h)) {
44593 		return;
44594 	}
44595 #endif
44596 	if (DUK_HEAPHDR_PREDEC_REFCOUNT(h) != 0) {
44597 		return;
44598 	}
44599 	duk_heaphdr_refzero(thr, h);
44600 }
44601 
44602 DUK_INTERNAL void duk_heaphdr_decref_allownull(duk_hthread *thr, duk_heaphdr *h) {
44603 	DUK_ASSERT(thr != NULL);
44604 	DUK_ASSERT(thr->heap != NULL);
44605 
44606 	if (h == NULL) {
44607 		return;
44608 	}
44609 	DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
44610 
44611 #if defined(DUK_USE_ROM_OBJECTS)
44612 	if (DUK_HEAPHDR_HAS_READONLY(h)) {
44613 		return;
44614 	}
44615 #endif
44616 	DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(h) >= 1);
44617 	if (DUK_HEAPHDR_PREDEC_REFCOUNT(h) != 0) {
44618 		return;
44619 	}
44620 	duk_heaphdr_refzero(thr, h);
44621 }
44622 
44623 #else
44624 
44625 /* no refcounting */
44626 
44627 #endif  /* DUK_USE_REFERENCE_COUNTING */
44628 /*
44629  *  String cache.
44630  *
44631  *  Provides a cache to optimize indexed string lookups.  The cache keeps
44632  *  track of (byte offset, char offset) states for a fixed number of strings.
44633  *  Otherwise we'd need to scan from either end of the string, as we store
44634  *  strings in (extended) UTF-8.
44635  */
44636 
44637 /* include removed: duk_internal.h */
44638 
44639 /*
44640  *  Delete references to given hstring from the heap string cache.
44641  *
44642  *  String cache references are 'weak': they are not counted towards
44643  *  reference counts, nor serve as roots for mark-and-sweep.  When an
44644  *  object is about to be freed, such references need to be removed.
44645  */
44646 
44647 DUK_INTERNAL void duk_heap_strcache_string_remove(duk_heap *heap, duk_hstring *h) {
44648 	duk_small_int_t i;
44649 	for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
44650 		duk_strcache *c = heap->strcache + i;
44651 		if (c->h == h) {
44652 			DUK_DD(DUK_DDPRINT("deleting weak strcache reference to hstring %p from heap %p",
44653 			                   (void *) h, (void *) heap));
44654 			c->h = NULL;
44655 
44656 			/* XXX: the string shouldn't appear twice, but we now loop to the
44657 			 * end anyway; if fixed, add a looping assertion to ensure there
44658 			 * is no duplicate.
44659 			 */
44660 		}
44661 	}
44662 }
44663 
44664 /*
44665  *  String scanning helpers
44666  *
44667  *  All bytes other than UTF-8 continuation bytes ([0x80,0xbf]) are
44668  *  considered to contribute a character.  This must match how string
44669  *  character length is computed.
44670  */
44671 
44672 DUK_LOCAL const duk_uint8_t *duk__scan_forwards(const duk_uint8_t *p, const duk_uint8_t *q, duk_uint_fast32_t n) {
44673 	while (n > 0) {
44674 		for (;;) {
44675 			p++;
44676 			if (p >= q) {
44677 				return NULL;
44678 			}
44679 			if ((*p & 0xc0) != 0x80) {
44680 				break;
44681 			}
44682 		}
44683 		n--;
44684 	}
44685 	return p;
44686 }
44687 
44688 DUK_LOCAL const duk_uint8_t *duk__scan_backwards(const duk_uint8_t *p, const duk_uint8_t *q, duk_uint_fast32_t n) {
44689 	while (n > 0) {
44690 		for (;;) {
44691 			p--;
44692 			if (p < q) {
44693 				return NULL;
44694 			}
44695 			if ((*p & 0xc0) != 0x80) {
44696 				break;
44697 			}
44698 		}
44699 		n--;
44700 	}
44701 	return p;
44702 }
44703 
44704 /*
44705  *  Convert char offset to byte offset
44706  *
44707  *  Avoid using the string cache if possible: for ASCII strings byte and
44708  *  char offsets are equal and for short strings direct scanning may be
44709  *  better than using the string cache (which may evict a more important
44710  *  entry).
44711  *
44712  *  Typing now assumes 32-bit string byte/char offsets (duk_uint_fast32_t).
44713  *  Better typing might be to use duk_size_t.
44714  */
44715 
44716 DUK_INTERNAL duk_uint_fast32_t duk_heap_strcache_offset_char2byte(duk_hthread *thr, duk_hstring *h, duk_uint_fast32_t char_offset) {
44717 	duk_heap *heap;
44718 	duk_strcache *sce;
44719 	duk_uint_fast32_t byte_offset;
44720 	duk_small_int_t i;
44721 	duk_bool_t use_cache;
44722 	duk_uint_fast32_t dist_start, dist_end, dist_sce;
44723 	const duk_uint8_t *p_start;
44724 	const duk_uint8_t *p_end;
44725 	const duk_uint8_t *p_found;
44726 
44727 	if (char_offset > DUK_HSTRING_GET_CHARLEN(h)) {
44728 		goto error;
44729 	}
44730 
44731 	/*
44732 	 *  For ASCII strings, the answer is simple.
44733 	 */
44734 
44735 	if (DUK_HSTRING_IS_ASCII(h)) {
44736 		/* clen == blen -> pure ascii */
44737 		return char_offset;
44738 	}
44739 
44740 	/*
44741 	 *  For non-ASCII strings, we need to scan forwards or backwards
44742 	 *  from some starting point.  The starting point may be the start
44743 	 *  or end of the string, or some cached midpoint in the string
44744 	 *  cache.
44745 	 *
44746 	 *  For "short" strings we simply scan without checking or updating
44747 	 *  the cache.  For longer strings we check and update the cache as
44748 	 *  necessary, inserting a new cache entry if none exists.
44749 	 */
44750 
44751 	DUK_DDD(DUK_DDDPRINT("non-ascii string %p, char_offset=%ld, clen=%ld, blen=%ld",
44752 	                     (void *) h, (long) char_offset,
44753 	                     (long) DUK_HSTRING_GET_CHARLEN(h),
44754 	                     (long) DUK_HSTRING_GET_BYTELEN(h)));
44755 
44756 	heap = thr->heap;
44757 	sce = NULL;
44758 	use_cache = (DUK_HSTRING_GET_CHARLEN(h) > DUK_HEAP_STRINGCACHE_NOCACHE_LIMIT);
44759 
44760 	if (use_cache) {
44761 #ifdef DUK_USE_DDDPRINT
44762 		DUK_DDD(DUK_DDDPRINT("stringcache before char2byte (using cache):"));
44763 		for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
44764 			duk_strcache *c = heap->strcache + i;
44765 			DUK_DDD(DUK_DDDPRINT("  [%ld] -> h=%p, cidx=%ld, bidx=%ld",
44766 			                     (long) i, (void *) c->h, (long) c->cidx, (long) c->bidx));
44767 		}
44768 #endif
44769 
44770 		for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
44771 			duk_strcache *c = heap->strcache + i;
44772 
44773 			if (c->h == h) {
44774 				sce = c;
44775 				break;
44776 			}
44777 		}
44778 	}
44779 
44780 	/*
44781 	 *  Scan from shortest distance:
44782 	 *    - start of string
44783 	 *    - end of string
44784 	 *    - cache entry (if exists)
44785 	 */
44786 
44787 	DUK_ASSERT(DUK_HSTRING_GET_CHARLEN(h) >= char_offset);
44788 	dist_start = char_offset;
44789 	dist_end = DUK_HSTRING_GET_CHARLEN(h) - char_offset;
44790 	dist_sce = 0; DUK_UNREF(dist_sce);  /* initialize for debug prints, needed if sce==NULL */
44791 
44792 	p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
44793 	p_end = (const duk_uint8_t *) (p_start + DUK_HSTRING_GET_BYTELEN(h));
44794 	p_found = NULL;
44795 
44796 	if (sce) {
44797 		if (char_offset >= sce->cidx) {
44798 			dist_sce = char_offset - sce->cidx;
44799 			if ((dist_sce <= dist_start) && (dist_sce <= dist_end)) {
44800 				DUK_DDD(DUK_DDDPRINT("non-ascii string, use_cache=%ld, sce=%p:%ld:%ld, "
44801 				                     "dist_start=%ld, dist_end=%ld, dist_sce=%ld => "
44802 				                     "scan forwards from sce",
44803 				                     (long) use_cache, (void *) (sce ? sce->h : NULL),
44804 				                     (sce ? (long) sce->cidx : (long) -1),
44805 				                     (sce ? (long) sce->bidx : (long) -1),
44806 				                     (long) dist_start, (long) dist_end, (long) dist_sce));
44807 
44808 				p_found = duk__scan_forwards(p_start + sce->bidx,
44809 				                             p_end,
44810 				                             dist_sce);
44811 				goto scan_done;
44812 			}
44813 		} else {
44814 			dist_sce = sce->cidx - char_offset;
44815 			if ((dist_sce <= dist_start) && (dist_sce <= dist_end)) {
44816 				DUK_DDD(DUK_DDDPRINT("non-ascii string, use_cache=%ld, sce=%p:%ld:%ld, "
44817 				                     "dist_start=%ld, dist_end=%ld, dist_sce=%ld => "
44818 				                     "scan backwards from sce",
44819 				                     (long) use_cache, (void *) (sce ? sce->h : NULL),
44820 				                     (sce ? (long) sce->cidx : (long) -1),
44821 				                     (sce ? (long) sce->bidx : (long) -1),
44822 				                     (long) dist_start, (long) dist_end, (long) dist_sce));
44823 
44824 				p_found = duk__scan_backwards(p_start + sce->bidx,
44825 				                              p_start,
44826 				                              dist_sce);
44827 				goto scan_done;
44828 			}
44829 		}
44830 	}
44831 
44832 	/* no sce, or sce scan not best */
44833 
44834 	if (dist_start <= dist_end) {
44835 		DUK_DDD(DUK_DDDPRINT("non-ascii string, use_cache=%ld, sce=%p:%ld:%ld, "
44836 		                     "dist_start=%ld, dist_end=%ld, dist_sce=%ld => "
44837 		                     "scan forwards from string start",
44838 		                     (long) use_cache, (void *) (sce ? sce->h : NULL),
44839 		                     (sce ? (long) sce->cidx : (long) -1),
44840 		                     (sce ? (long) sce->bidx : (long) -1),
44841 		                     (long) dist_start, (long) dist_end, (long) dist_sce));
44842 
44843 		p_found = duk__scan_forwards(p_start,
44844 		                             p_end,
44845 		                             dist_start);
44846 	} else {
44847 		DUK_DDD(DUK_DDDPRINT("non-ascii string, use_cache=%ld, sce=%p:%ld:%ld, "
44848 		                     "dist_start=%ld, dist_end=%ld, dist_sce=%ld => "
44849 		                     "scan backwards from string end",
44850 		                     (long) use_cache, (void *) (sce ? sce->h : NULL),
44851 		                     (sce ? (long) sce->cidx : (long) -1),
44852 		                     (sce ? (long) sce->bidx : (long) -1),
44853 		                     (long) dist_start, (long) dist_end, (long) dist_sce));
44854 
44855 		p_found = duk__scan_backwards(p_end,
44856 		                              p_start,
44857 		                              dist_end);
44858 	}
44859 
44860  scan_done:
44861 
44862 	if (!p_found) {
44863 		/* Scan error: this shouldn't normally happen; it could happen if
44864 		 * string is not valid UTF-8 data, and clen/blen are not consistent
44865 		 * with the scanning algorithm.
44866 		 */
44867 		goto error;
44868 	}
44869 
44870 	DUK_ASSERT(p_found >= p_start);
44871 	DUK_ASSERT(p_found <= p_end);  /* may be equal */
44872 	byte_offset = (duk_uint32_t) (p_found - p_start);
44873 
44874 	DUK_DDD(DUK_DDDPRINT("-> string %p, cidx %ld -> bidx %ld",
44875 	                     (void *) h, (long) char_offset, (long) byte_offset));
44876 
44877 	/*
44878 	 *  Update cache entry (allocating if necessary), and move the
44879 	 *  cache entry to the first place (in an "LRU" policy).
44880 	 */
44881 
44882 	if (use_cache) {
44883 		/* update entry, allocating if necessary */
44884 		if (!sce) {
44885 			sce = heap->strcache + DUK_HEAP_STRCACHE_SIZE - 1;  /* take last entry */
44886 			sce->h = h;
44887 		}
44888 		DUK_ASSERT(sce != NULL);
44889 		sce->bidx = (duk_uint32_t) (p_found - p_start);
44890 		sce->cidx = (duk_uint32_t) char_offset;
44891 
44892 		/* LRU: move our entry to first */
44893 		if (sce > &heap->strcache[0]) {
44894 			/*
44895 			 *   A                  C
44896 			 *   B                  A
44897 			 *   C <- sce    ==>    B
44898 			 *   D                  D
44899 			 */
44900 			duk_strcache tmp;
44901 
44902 			tmp = *sce;
44903 			DUK_MEMMOVE((void *) (&heap->strcache[1]),
44904 			            (const void *) (&heap->strcache[0]),
44905 			            (size_t) (((char *) sce) - ((char *) &heap->strcache[0])));
44906 			heap->strcache[0] = tmp;
44907 
44908 			/* 'sce' points to the wrong entry here, but is no longer used */
44909 		}
44910 #ifdef DUK_USE_DDDPRINT
44911 		DUK_DDD(DUK_DDDPRINT("stringcache after char2byte (using cache):"));
44912 		for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
44913 			duk_strcache *c = heap->strcache + i;
44914 			DUK_DDD(DUK_DDDPRINT("  [%ld] -> h=%p, cidx=%ld, bidx=%ld",
44915 			                     (long) i, (void *) c->h, (long) c->cidx, (long) c->bidx));
44916 		}
44917 #endif
44918 	}
44919 
44920 	return byte_offset;
44921 
44922  error:
44923 	DUK_ERROR_INTERNAL_DEFMSG(thr);
44924 	return 0;
44925 }
44926 /*
44927  *  Heap stringtable handling, string interning.
44928  */
44929 
44930 /* include removed: duk_internal.h */
44931 
44932 #if defined(DUK_USE_STRTAB_PROBE)
44933 #define DUK__HASH_INITIAL(hash,h_size)        DUK_STRTAB_HASH_INITIAL((hash),(h_size))
44934 #define DUK__HASH_PROBE_STEP(hash)            DUK_STRTAB_HASH_PROBE_STEP((hash))
44935 #define DUK__DELETED_MARKER(heap)             DUK_STRTAB_DELETED_MARKER((heap))
44936 #endif
44937 
44938 #if defined(DUK_USE_MARK_AND_SWEEP)
44939 #define DUK__PREVENT_MS_SIDE_EFFECTS(heap) do { \
44940 		(heap)->mark_and_sweep_base_flags |= \
44941 		        DUK_MS_FLAG_NO_STRINGTABLE_RESIZE |  /* avoid recursive string table call */ \
44942 		        DUK_MS_FLAG_NO_FINALIZERS |          /* avoid pressure to add/remove strings, invalidation of call data argument, etc. */ \
44943 		        DUK_MS_FLAG_NO_OBJECT_COMPACTION;    /* avoid array abandoning which interns strings */ \
44944 	} while (0)
44945 #endif
44946 
44947 /*
44948  *  Create a hstring and insert into the heap.  The created object
44949  *  is directly garbage collectable with reference count zero.
44950  *
44951  *  The caller must place the interned string into the stringtable
44952  *  immediately (without chance of a longjmp); otherwise the string
44953  *  is lost.
44954  */
44955 
44956 DUK_LOCAL
44957 duk_hstring *duk__alloc_init_hstring(duk_heap *heap,
44958                                      const duk_uint8_t *str,
44959                                      duk_uint32_t blen,
44960                                      duk_uint32_t strhash,
44961                                      const duk_uint8_t *extdata) {
44962 	duk_hstring *res = NULL;
44963 	duk_uint8_t *data;
44964 	duk_size_t alloc_size;
44965 	duk_uarridx_t dummy;
44966 	duk_uint32_t clen;
44967 
44968 #if defined(DUK_USE_STRLEN16)
44969 	/* If blen <= 0xffffUL, clen is also guaranteed to be <= 0xffffUL. */
44970 	if (blen > 0xffffUL) {
44971 		DUK_D(DUK_DPRINT("16-bit string blen/clen active and blen over 16 bits, reject intern"));
44972 		return NULL;
44973 	}
44974 #endif
44975 
44976 	if (extdata) {
44977 		alloc_size = (duk_size_t) sizeof(duk_hstring_external);
44978 		res = (duk_hstring *) DUK_ALLOC(heap, alloc_size);
44979 		if (!res) {
44980 			goto alloc_error;
44981 		}
44982 		DUK_MEMZERO(res, sizeof(duk_hstring_external));
44983 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
44984 		DUK_HEAPHDR_STRING_INIT_NULLS(&res->hdr);
44985 #endif
44986 		DUK_HEAPHDR_SET_TYPE_AND_FLAGS(&res->hdr, DUK_HTYPE_STRING, DUK_HSTRING_FLAG_EXTDATA);
44987 
44988 		((duk_hstring_external *) res)->extdata = extdata;
44989 	} else {
44990 		/* NUL terminate for convenient C access */
44991 		alloc_size = (duk_size_t) (sizeof(duk_hstring) + blen + 1);
44992 		res = (duk_hstring *) DUK_ALLOC(heap, alloc_size);
44993 		if (!res) {
44994 			goto alloc_error;
44995 		}
44996 		DUK_MEMZERO(res, sizeof(duk_hstring));
44997 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
44998 		DUK_HEAPHDR_STRING_INIT_NULLS(&res->hdr);
44999 #endif
45000 		DUK_HEAPHDR_SET_TYPE_AND_FLAGS(&res->hdr, DUK_HTYPE_STRING, 0);
45001 
45002 		data = (duk_uint8_t *) (res + 1);
45003 		DUK_MEMCPY(data, str, blen);
45004 		data[blen] = (duk_uint8_t) 0;
45005 	}
45006 
45007 	DUK_ASSERT(!DUK_HSTRING_HAS_ARRIDX(res));
45008 	if (duk_js_to_arrayindex_raw_string(str, blen, &dummy)) {
45009 		DUK_HSTRING_SET_ARRIDX(res);
45010 	}
45011 
45012 	/* All strings beginning with 0xff are treated as "internal",
45013 	 * even strings interned by the user.  This allows user code to
45014 	 * create internal properties too, and makes behavior consistent
45015 	 * in case user code happens to use a string also used by Duktape
45016 	 * (such as string has already been interned and has the 'internal'
45017 	 * flag set).
45018 	 */
45019 	DUK_ASSERT(!DUK_HSTRING_HAS_INTERNAL(res));
45020 	if (blen > 0 && str[0] == (duk_uint8_t) 0xff) {
45021 		DUK_HSTRING_SET_INTERNAL(res);
45022 	}
45023 
45024 	DUK_HSTRING_SET_HASH(res, strhash);
45025 	DUK_HSTRING_SET_BYTELEN(res, blen);
45026 
45027 	clen = (duk_uint32_t) duk_unicode_unvalidated_utf8_length(str, (duk_size_t) blen);
45028 	DUK_ASSERT(clen <= blen);
45029 #if defined(DUK_USE_HSTRING_CLEN)
45030 	DUK_HSTRING_SET_CHARLEN(res, clen);
45031 #endif
45032 
45033 	/* Using an explicit 'ASCII' flag has larger footprint (one call site
45034 	 * only) but is quite useful for the case when there's no explicit
45035 	 * 'clen' in duk_hstring.
45036 	 */
45037 	DUK_ASSERT(!DUK_HSTRING_HAS_ASCII(res));
45038 	if (clen == blen) {
45039 		DUK_HSTRING_SET_ASCII(res);
45040 	}
45041 
45042 	DUK_DDD(DUK_DDDPRINT("interned string, hash=0x%08lx, blen=%ld, clen=%ld, has_arridx=%ld, has_extdata=%ld",
45043 	                     (unsigned long) DUK_HSTRING_GET_HASH(res),
45044 	                     (long) DUK_HSTRING_GET_BYTELEN(res),
45045 	                     (long) DUK_HSTRING_GET_CHARLEN(res),
45046 	                     (long) (DUK_HSTRING_HAS_ARRIDX(res) ? 1 : 0),
45047 	                     (long) (DUK_HSTRING_HAS_EXTDATA(res) ? 1 : 0)));
45048 
45049 	return res;
45050 
45051  alloc_error:
45052 	DUK_FREE(heap, res);
45053 	return NULL;
45054 }
45055 
45056 /*
45057  *  String table algorithm: fixed size string table with array chaining
45058  *
45059  *  The top level string table has a fixed size, with each slot holding
45060  *  either NULL, string pointer, or pointer to a separately allocated
45061  *  string pointer list.
45062  *
45063  *  This is good for low memory environments using a pool allocator: the
45064  *  top level allocation has a fixed size and the pointer lists have quite
45065  *  small allocation size, which further matches the typical pool sizes
45066  *  needed by objects, strings, property tables, etc.
45067  */
45068 
45069 #if defined(DUK_USE_STRTAB_CHAIN)
45070 
45071 #if defined(DUK_USE_HEAPPTR16)
45072 DUK_LOCAL duk_bool_t duk__insert_hstring_chain(duk_heap *heap, duk_hstring *h) {
45073 	duk_small_uint_t slotidx;
45074 	duk_strtab_entry *e;
45075 	duk_uint16_t *lst;
45076 	duk_uint16_t *new_lst;
45077 	duk_size_t i, n;
45078 	duk_uint16_t null16 = heap->heapptr_null16;
45079 	duk_uint16_t h16 = DUK_USE_HEAPPTR_ENC16(heap->heap_udata, (void *) h);
45080 
45081 	DUK_ASSERT(heap != NULL);
45082 	DUK_ASSERT(h != NULL);
45083 
45084 	slotidx = DUK_HSTRING_GET_HASH(h) % DUK_STRTAB_CHAIN_SIZE;
45085 	DUK_ASSERT(slotidx < DUK_STRTAB_CHAIN_SIZE);
45086 
45087 	e = heap->strtable + slotidx;
45088 	if (e->listlen == 0) {
45089 		if (e->u.str16 == null16) {
45090 			e->u.str16 = h16;
45091 		} else {
45092 			/* Now two entries in the same slot, alloc list */
45093 			lst = (duk_uint16_t *) DUK_ALLOC(heap, sizeof(duk_uint16_t) * 2);
45094 			if (lst == NULL) {
45095 				return 1;  /* fail */
45096 			}
45097 			lst[0] = e->u.str16;
45098 			lst[1] = h16;
45099 			e->u.strlist16 = DUK_USE_HEAPPTR_ENC16(heap->heap_udata, (void *) lst);
45100 			e->listlen = 2;
45101 		}
45102 	} else {
45103 		DUK_ASSERT(e->u.strlist16 != null16);
45104 		lst = (duk_uint16_t *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, e->u.strlist16);
45105 		DUK_ASSERT(lst != NULL);
45106 		for (i = 0, n = e->listlen; i < n; i++) {
45107 			if (lst[i] == null16) {
45108 				lst[i] = h16;
45109 				return 0;
45110 			}
45111 		}
45112 
45113 		if (e->listlen + 1 == 0) {
45114 			/* Overflow, relevant mainly when listlen is 16 bits. */
45115 			return 1;  /* fail */
45116 		}
45117 
45118 		new_lst = (duk_uint16_t *) DUK_REALLOC(heap, lst, sizeof(duk_uint16_t) * (e->listlen + 1));
45119 		if (new_lst == NULL) {
45120 			return 1;  /* fail */
45121 		}
45122 		new_lst[e->listlen++] = h16;
45123 		e->u.strlist16 = DUK_USE_HEAPPTR_ENC16(heap->heap_udata, (void *) new_lst);
45124 	}
45125 	return 0;
45126 }
45127 #else  /* DUK_USE_HEAPPTR16 */
45128 DUK_LOCAL duk_bool_t duk__insert_hstring_chain(duk_heap *heap, duk_hstring *h) {
45129 	duk_small_uint_t slotidx;
45130 	duk_strtab_entry *e;
45131 	duk_hstring **lst;
45132 	duk_hstring **new_lst;
45133 	duk_size_t i, n;
45134 
45135 	DUK_ASSERT(heap != NULL);
45136 	DUK_ASSERT(h != NULL);
45137 
45138 	slotidx = DUK_HSTRING_GET_HASH(h) % DUK_STRTAB_CHAIN_SIZE;
45139 	DUK_ASSERT(slotidx < DUK_STRTAB_CHAIN_SIZE);
45140 
45141 	e = heap->strtable + slotidx;
45142 	if (e->listlen == 0) {
45143 		if (e->u.str == NULL) {
45144 			e->u.str = h;
45145 		} else {
45146 			/* Now two entries in the same slot, alloc list */
45147 			lst = (duk_hstring **) DUK_ALLOC(heap, sizeof(duk_hstring *) * 2);
45148 			if (lst == NULL) {
45149 				return 1;  /* fail */
45150 			}
45151 			lst[0] = e->u.str;
45152 			lst[1] = h;
45153 			e->u.strlist = lst;
45154 			e->listlen = 2;
45155 		}
45156 	} else {
45157 		DUK_ASSERT(e->u.strlist != NULL);
45158 		lst = e->u.strlist;
45159 		for (i = 0, n = e->listlen; i < n; i++) {
45160 			if (lst[i] == NULL) {
45161 				lst[i] = h;
45162 				return 0;
45163 			}
45164 		}
45165 
45166 		if (e->listlen + 1 == 0) {
45167 			/* Overflow, relevant mainly when listlen is 16 bits. */
45168 			return 1;  /* fail */
45169 		}
45170 
45171 		new_lst = (duk_hstring **) DUK_REALLOC(heap, e->u.strlist, sizeof(duk_hstring *) * (e->listlen + 1));
45172 		if (new_lst == NULL) {
45173 			return 1;  /* fail */
45174 		}
45175 		new_lst[e->listlen++] = h;
45176 		e->u.strlist = new_lst;
45177 	}
45178 	return 0;
45179 }
45180 #endif  /* DUK_USE_HEAPPTR16 */
45181 
45182 #if defined(DUK_USE_HEAPPTR16)
45183 DUK_LOCAL duk_hstring *duk__find_matching_string_chain(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t strhash) {
45184 	duk_small_uint_t slotidx;
45185 	duk_strtab_entry *e;
45186 	duk_uint16_t *lst;
45187 	duk_size_t i, n;
45188 	duk_uint16_t null16 = heap->heapptr_null16;
45189 
45190 	DUK_ASSERT(heap != NULL);
45191 
45192 	slotidx = strhash % DUK_STRTAB_CHAIN_SIZE;
45193 	DUK_ASSERT(slotidx < DUK_STRTAB_CHAIN_SIZE);
45194 
45195 	e = heap->strtable + slotidx;
45196 	if (e->listlen == 0) {
45197 		if (e->u.str16 != null16) {
45198 			duk_hstring *h = (duk_hstring *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, e->u.str16);
45199 			DUK_ASSERT(h != NULL);
45200 			if (DUK_HSTRING_GET_BYTELEN(h) == blen &&
45201 			    DUK_MEMCMP((const void *) str, (const void *) DUK_HSTRING_GET_DATA(h), (size_t) blen) == 0) {
45202 				return h;
45203 			}
45204 		}
45205 	} else {
45206 		DUK_ASSERT(e->u.strlist16 != null16);
45207 		lst = (duk_uint16_t *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, e->u.strlist16);
45208 		DUK_ASSERT(lst != NULL);
45209 		for (i = 0, n = e->listlen; i < n; i++) {
45210 			if (lst[i] != null16) {
45211 				duk_hstring *h = (duk_hstring *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, lst[i]);
45212 				DUK_ASSERT(h != NULL);
45213 				if (DUK_HSTRING_GET_BYTELEN(h) == blen &&
45214 				    DUK_MEMCMP((const void *) str, (const void *) DUK_HSTRING_GET_DATA(h), (size_t) blen) == 0) {
45215 					return h;
45216 				}
45217 			}
45218 		}
45219 	}
45220 
45221 	return NULL;
45222 }
45223 #else  /* DUK_USE_HEAPPTR16 */
45224 DUK_LOCAL duk_hstring *duk__find_matching_string_chain(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t strhash) {
45225 	duk_small_uint_t slotidx;
45226 	duk_strtab_entry *e;
45227 	duk_hstring **lst;
45228 	duk_size_t i, n;
45229 
45230 	DUK_ASSERT(heap != NULL);
45231 
45232 	slotidx = strhash % DUK_STRTAB_CHAIN_SIZE;
45233 	DUK_ASSERT(slotidx < DUK_STRTAB_CHAIN_SIZE);
45234 
45235 	e = heap->strtable + slotidx;
45236 	if (e->listlen == 0) {
45237 		if (e->u.str != NULL &&
45238 	           DUK_HSTRING_GET_BYTELEN(e->u.str) == blen &&
45239 	           DUK_MEMCMP((const void *) str, (const void *) DUK_HSTRING_GET_DATA(e->u.str), (size_t) blen) == 0) {
45240 			return e->u.str;
45241 		}
45242 	} else {
45243 		DUK_ASSERT(e->u.strlist != NULL);
45244 		lst = e->u.strlist;
45245 		for (i = 0, n = e->listlen; i < n; i++) {
45246 			if (lst[i] != NULL &&
45247 		           DUK_HSTRING_GET_BYTELEN(lst[i]) == blen &&
45248 		           DUK_MEMCMP((const void *) str, (const void *) DUK_HSTRING_GET_DATA(lst[i]), (size_t) blen) == 0) {
45249 				return lst[i];
45250 			}
45251 		}
45252 	}
45253 
45254 	return NULL;
45255 }
45256 #endif  /* DUK_USE_HEAPPTR16 */
45257 
45258 #if defined(DUK_USE_HEAPPTR16)
45259 DUK_LOCAL void duk__remove_matching_hstring_chain(duk_heap *heap, duk_hstring *h) {
45260 	duk_small_uint_t slotidx;
45261 	duk_strtab_entry *e;
45262 	duk_uint16_t *lst;
45263 	duk_size_t i, n;
45264 	duk_uint16_t h16;
45265 	duk_uint16_t null16 = heap->heapptr_null16;
45266 
45267 	DUK_ASSERT(heap != NULL);
45268 	DUK_ASSERT(h != NULL);
45269 
45270 	slotidx = DUK_HSTRING_GET_HASH(h) % DUK_STRTAB_CHAIN_SIZE;
45271 	DUK_ASSERT(slotidx < DUK_STRTAB_CHAIN_SIZE);
45272 
45273 	DUK_ASSERT(h != NULL);
45274 	h16 = DUK_USE_HEAPPTR_ENC16(heap->heap_udata, (void *) h);
45275 
45276 	e = heap->strtable + slotidx;
45277 	if (e->listlen == 0) {
45278 		if (e->u.str16 == h16) {
45279 			e->u.str16 = null16;
45280 			return;
45281 		}
45282 	} else {
45283 		DUK_ASSERT(e->u.strlist16 != null16);
45284 		lst = (duk_uint16_t *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, e->u.strlist16);
45285 		DUK_ASSERT(lst != NULL);
45286 		for (i = 0, n = e->listlen; i < n; i++) {
45287 			if (lst[i] == h16) {
45288 				lst[i] = null16;
45289 				return;
45290 			}
45291 		}
45292 	}
45293 
45294 	DUK_D(DUK_DPRINT("failed to find string that should be in stringtable"));
45295 	DUK_UNREACHABLE();
45296 	return;
45297 }
45298 #else  /* DUK_USE_HEAPPTR16 */
45299 DUK_LOCAL void duk__remove_matching_hstring_chain(duk_heap *heap, duk_hstring *h) {
45300 	duk_small_uint_t slotidx;
45301 	duk_strtab_entry *e;
45302 	duk_hstring **lst;
45303 	duk_size_t i, n;
45304 
45305 	DUK_ASSERT(heap != NULL);
45306 	DUK_ASSERT(h != NULL);
45307 
45308 	slotidx = DUK_HSTRING_GET_HASH(h) % DUK_STRTAB_CHAIN_SIZE;
45309 	DUK_ASSERT(slotidx < DUK_STRTAB_CHAIN_SIZE);
45310 
45311 	e = heap->strtable + slotidx;
45312 	if (e->listlen == 0) {
45313 		DUK_ASSERT(h != NULL);
45314 		if (e->u.str == h) {
45315 			e->u.str = NULL;
45316 			return;
45317 		}
45318 	} else {
45319 		DUK_ASSERT(e->u.strlist != NULL);
45320 		lst = e->u.strlist;
45321 		for (i = 0, n = e->listlen; i < n; i++) {
45322 			DUK_ASSERT(h != NULL);
45323 			if (lst[i] == h) {
45324 				lst[i] = NULL;
45325 				return;
45326 			}
45327 		}
45328 	}
45329 
45330 	DUK_D(DUK_DPRINT("failed to find string that should be in stringtable"));
45331 	DUK_UNREACHABLE();
45332 	return;
45333 }
45334 #endif  /* DUK_USE_HEAPPTR16 */
45335 
45336 #if defined(DUK_USE_DEBUG)
45337 DUK_INTERNAL void duk_heap_dump_strtab(duk_heap *heap) {
45338 	duk_strtab_entry *e;
45339 	duk_small_uint_t i;
45340 	duk_size_t j, n, used;
45341 #if defined(DUK_USE_HEAPPTR16)
45342 	duk_uint16_t *lst;
45343 	duk_uint16_t null16 = heap->heapptr_null16;
45344 #else
45345 	duk_hstring **lst;
45346 #endif
45347 
45348 	DUK_ASSERT(heap != NULL);
45349 
45350 	for (i = 0; i < DUK_STRTAB_CHAIN_SIZE; i++) {
45351 		e = heap->strtable + i;
45352 
45353 		if (e->listlen == 0) {
45354 #if defined(DUK_USE_HEAPPTR16)
45355 			DUK_DD(DUK_DDPRINT("[%03d] -> plain %d", (int) i, (int) (e->u.str16 != null16 ? 1 : 0)));
45356 #else
45357 			DUK_DD(DUK_DDPRINT("[%03d] -> plain %d", (int) i, (int) (e->u.str ? 1 : 0)));
45358 #endif
45359 		} else {
45360 			used = 0;
45361 #if defined(DUK_USE_HEAPPTR16)
45362 			lst = (duk_uint16_t *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, e->u.strlist16);
45363 #else
45364 			lst = e->u.strlist;
45365 #endif
45366 			DUK_ASSERT(lst != NULL);
45367 			for (j = 0, n = e->listlen; j < n; j++) {
45368 #if defined(DUK_USE_HEAPPTR16)
45369 				if (lst[j] != null16) {
45370 #else
45371 				if (lst[j] != NULL) {
45372 #endif
45373 					used++;
45374 				}
45375 			}
45376 			DUK_DD(DUK_DDPRINT("[%03d] -> array %d/%d", (int) i, (int) used, (int) e->listlen));
45377 		}
45378 	}
45379 }
45380 #endif  /* DUK_USE_DEBUG */
45381 
45382 #endif  /* DUK_USE_STRTAB_CHAIN */
45383 
45384 /*
45385  *  String table algorithm: closed hashing with a probe sequence
45386  *
45387  *  This is the default algorithm and works fine for environments with
45388  *  minimal memory constraints.
45389  */
45390 
45391 #if defined(DUK_USE_STRTAB_PROBE)
45392 
45393 /* Count actually used (non-NULL, non-DELETED) entries. */
45394 DUK_LOCAL duk_int_t duk__count_used_probe(duk_heap *heap) {
45395 	duk_int_t res = 0;
45396 	duk_uint_fast32_t i, n;
45397 #if defined(DUK_USE_HEAPPTR16)
45398 	duk_uint16_t null16 = heap->heapptr_null16;
45399 	duk_uint16_t deleted16 = heap->heapptr_deleted16;
45400 #endif
45401 
45402 	n = (duk_uint_fast32_t) heap->st_size;
45403 	for (i = 0; i < n; i++) {
45404 #if defined(DUK_USE_HEAPPTR16)
45405 		if (heap->strtable16[i] != null16 && heap->strtable16[i] != deleted16) {
45406 #else
45407 		if (heap->strtable[i] != NULL && heap->strtable[i] != DUK__DELETED_MARKER(heap)) {
45408 #endif
45409 			res++;
45410 		}
45411 	}
45412 	return res;
45413 }
45414 
45415 #if defined(DUK_USE_HEAPPTR16)
45416 DUK_LOCAL void duk__insert_hstring_probe(duk_heap *heap, duk_uint16_t *entries16, duk_uint32_t size, duk_uint32_t *p_used, duk_hstring *h) {
45417 #else
45418 DUK_LOCAL void duk__insert_hstring_probe(duk_heap *heap, duk_hstring **entries, duk_uint32_t size, duk_uint32_t *p_used, duk_hstring *h) {
45419 #endif
45420 	duk_uint32_t i;
45421 	duk_uint32_t step;
45422 #if defined(DUK_USE_HEAPPTR16)
45423 	duk_uint16_t null16 = heap->heapptr_null16;
45424 	duk_uint16_t deleted16 = heap->heapptr_deleted16;
45425 #endif
45426 
45427 	DUK_ASSERT(size > 0);
45428 
45429 	i = DUK__HASH_INITIAL(DUK_HSTRING_GET_HASH(h), size);
45430 	step = DUK__HASH_PROBE_STEP(DUK_HSTRING_GET_HASH(h));
45431 	for (;;) {
45432 #if defined(DUK_USE_HEAPPTR16)
45433 		duk_uint16_t e16 = entries16[i];
45434 #else
45435 		duk_hstring *e = entries[i];
45436 #endif
45437 
45438 #if defined(DUK_USE_HEAPPTR16)
45439 		/* XXX: could check for e16 == 0 because NULL is guaranteed to
45440 		 * encode to zero.
45441 		 */
45442 		if (e16 == null16) {
45443 #else
45444 		if (e == NULL) {
45445 #endif
45446 			DUK_DDD(DUK_DDDPRINT("insert hit (null): %ld", (long) i));
45447 #if defined(DUK_USE_HEAPPTR16)
45448 			entries16[i] = DUK_USE_HEAPPTR_ENC16(heap->heap_udata, (void *) h);
45449 #else
45450 			entries[i] = h;
45451 #endif
45452 			(*p_used)++;
45453 			break;
45454 #if defined(DUK_USE_HEAPPTR16)
45455 		} else if (e16 == deleted16) {
45456 #else
45457 		} else if (e == DUK__DELETED_MARKER(heap)) {
45458 #endif
45459 			/* st_used remains the same, DELETED is counted as used */
45460 			DUK_DDD(DUK_DDDPRINT("insert hit (deleted): %ld", (long) i));
45461 #if defined(DUK_USE_HEAPPTR16)
45462 			entries16[i] = DUK_USE_HEAPPTR_ENC16(heap->heap_udata, (void *) h);
45463 #else
45464 			entries[i] = h;
45465 #endif
45466 			break;
45467 		}
45468 		DUK_DDD(DUK_DDDPRINT("insert miss: %ld", (long) i));
45469 		i = (i + step) % size;
45470 
45471 		/* looping should never happen */
45472 		DUK_ASSERT(i != DUK__HASH_INITIAL(DUK_HSTRING_GET_HASH(h), size));
45473 	}
45474 }
45475 
45476 #if defined(DUK_USE_HEAPPTR16)
45477 DUK_LOCAL duk_hstring *duk__find_matching_string_probe(duk_heap *heap, duk_uint16_t *entries16, duk_uint32_t size, const duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t strhash) {
45478 #else
45479 DUK_LOCAL duk_hstring *duk__find_matching_string_probe(duk_heap *heap, duk_hstring **entries, duk_uint32_t size, const duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t strhash) {
45480 #endif
45481 	duk_uint32_t i;
45482 	duk_uint32_t step;
45483 
45484 	DUK_ASSERT(size > 0);
45485 
45486 	i = DUK__HASH_INITIAL(strhash, size);
45487 	step = DUK__HASH_PROBE_STEP(strhash);
45488 	for (;;) {
45489 		duk_hstring *e;
45490 #if defined(DUK_USE_HEAPPTR16)
45491 		e = (duk_hstring *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, entries16[i]);
45492 #else
45493 		e = entries[i];
45494 #endif
45495 
45496 		if (!e) {
45497 			return NULL;
45498 		}
45499 		if (e != DUK__DELETED_MARKER(heap) && DUK_HSTRING_GET_BYTELEN(e) == blen) {
45500 			if (DUK_MEMCMP((const void *) str, (const void *) DUK_HSTRING_GET_DATA(e), (size_t) blen) == 0) {
45501 				DUK_DDD(DUK_DDDPRINT("find matching hit: %ld (step %ld, size %ld)",
45502 				                     (long) i, (long) step, (long) size));
45503 				return e;
45504 			}
45505 		}
45506 		DUK_DDD(DUK_DDDPRINT("find matching miss: %ld (step %ld, size %ld)",
45507 		                     (long) i, (long) step, (long) size));
45508 		i = (i + step) % size;
45509 
45510 		/* looping should never happen */
45511 		DUK_ASSERT(i != DUK__HASH_INITIAL(strhash, size));
45512 	}
45513 	DUK_UNREACHABLE();
45514 }
45515 
45516 #if defined(DUK_USE_HEAPPTR16)
45517 DUK_LOCAL void duk__remove_matching_hstring_probe(duk_heap *heap, duk_uint16_t *entries16, duk_uint32_t size, duk_hstring *h) {
45518 #else
45519 DUK_LOCAL void duk__remove_matching_hstring_probe(duk_heap *heap, duk_hstring **entries, duk_uint32_t size, duk_hstring *h) {
45520 #endif
45521 	duk_uint32_t i;
45522 	duk_uint32_t step;
45523 	duk_uint32_t hash;
45524 #if defined(DUK_USE_HEAPPTR16)
45525 	duk_uint16_t null16 = heap->heapptr_null16;
45526 	duk_uint16_t h16 = DUK_USE_HEAPPTR_ENC16(heap->heap_udata, (void *) h);
45527 #endif
45528 
45529 	DUK_ASSERT(size > 0);
45530 
45531 	hash = DUK_HSTRING_GET_HASH(h);
45532 	i = DUK__HASH_INITIAL(hash, size);
45533 	step = DUK__HASH_PROBE_STEP(hash);
45534 	for (;;) {
45535 #if defined(DUK_USE_HEAPPTR16)
45536 		duk_uint16_t e16 = entries16[i];
45537 #else
45538 		duk_hstring *e = entries[i];
45539 #endif
45540 
45541 #if defined(DUK_USE_HEAPPTR16)
45542 		if (e16 == null16) {
45543 #else
45544 		if (!e) {
45545 #endif
45546 			DUK_UNREACHABLE();
45547 			break;
45548 		}
45549 #if defined(DUK_USE_HEAPPTR16)
45550 		if (e16 == h16) {
45551 #else
45552 		if (e == h) {
45553 #endif
45554 			/* st_used remains the same, DELETED is counted as used */
45555 			DUK_DDD(DUK_DDDPRINT("free matching hit: %ld", (long) i));
45556 #if defined(DUK_USE_HEAPPTR16)
45557 			entries16[i] = heap->heapptr_deleted16;
45558 #else
45559 			entries[i] = DUK__DELETED_MARKER(heap);
45560 #endif
45561 			break;
45562 		}
45563 
45564 		DUK_DDD(DUK_DDDPRINT("free matching miss: %ld", (long) i));
45565 		i = (i + step) % size;
45566 
45567 		/* looping should never happen */
45568 		DUK_ASSERT(i != DUK__HASH_INITIAL(hash, size));
45569 	}
45570 }
45571 
45572 DUK_LOCAL duk_bool_t duk__resize_strtab_raw_probe(duk_heap *heap, duk_uint32_t new_size) {
45573 #if defined(DUK_USE_DEBUG)
45574 	duk_uint32_t old_used = heap->st_used;
45575 #endif
45576 	duk_uint32_t old_size = heap->st_size;
45577 #if defined(DUK_USE_HEAPPTR16)
45578 	duk_uint16_t *old_entries = heap->strtable16;
45579 	duk_uint16_t *new_entries = NULL;
45580 #else
45581 	duk_hstring **old_entries = heap->strtable;
45582 	duk_hstring **new_entries = NULL;
45583 #endif
45584 	duk_uint32_t new_used = 0;
45585 	duk_uint32_t i;
45586 
45587 #if defined(DUK_USE_DEBUG)
45588 	DUK_UNREF(old_used);  /* unused with some debug level combinations */
45589 #endif
45590 
45591 #ifdef DUK_USE_DDDPRINT
45592 	DUK_DDD(DUK_DDDPRINT("attempt to resize stringtable: %ld entries, %ld bytes, %ld used, %ld%% load -> %ld entries, %ld bytes, %ld used, %ld%% load",
45593 	                     (long) old_size, (long) (sizeof(duk_hstring *) * old_size), (long) old_used,
45594 	                     (long) (((double) old_used) / ((double) old_size) * 100.0),
45595 	                     (long) new_size, (long) (sizeof(duk_hstring *) * new_size), (long) duk__count_used_probe(heap),
45596 	                     (long) (((double) duk__count_used_probe(heap)) / ((double) new_size) * 100.0)));
45597 #endif
45598 
45599 	DUK_ASSERT(new_size > (duk_uint32_t) duk__count_used_probe(heap));  /* required for rehash to succeed, equality not that useful */
45600 	DUK_ASSERT(old_entries);
45601 
45602 	/*
45603 	 *  The attempt to allocate may cause a GC.  Such a GC must not attempt to resize
45604 	 *  the stringtable (though it can be swept); finalizer execution and object
45605 	 *  compaction must also be postponed to avoid the pressure to add strings to the
45606 	 *  string table.  Call site must prevent these.
45607 	 */
45608 
45609 #if defined(DUK_USE_MARK_AND_SWEEP)
45610 	DUK_ASSERT(heap->mark_and_sweep_base_flags & DUK_MS_FLAG_NO_STRINGTABLE_RESIZE);
45611 	DUK_ASSERT(heap->mark_and_sweep_base_flags & DUK_MS_FLAG_NO_FINALIZERS);
45612 	DUK_ASSERT(heap->mark_and_sweep_base_flags & DUK_MS_FLAG_NO_OBJECT_COMPACTION);
45613 #endif
45614 
45615 #if defined(DUK_USE_HEAPPTR16)
45616 	new_entries = (duk_uint16_t *) DUK_ALLOC(heap, sizeof(duk_uint16_t) * new_size);
45617 #else
45618 	new_entries = (duk_hstring **) DUK_ALLOC(heap, sizeof(duk_hstring *) * new_size);
45619 #endif
45620 
45621 	if (!new_entries) {
45622 		goto resize_error;
45623 	}
45624 
45625 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
45626 	for (i = 0; i < new_size; i++) {
45627 #if defined(DUK_USE_HEAPPTR16)
45628 		new_entries[i] = heap->heapptr_null16;
45629 #else
45630 		new_entries[i] = NULL;
45631 #endif
45632 	}
45633 #else
45634 #if defined(DUK_USE_HEAPPTR16)
45635 	/* Relies on NULL encoding to zero. */
45636 	DUK_MEMZERO(new_entries, sizeof(duk_uint16_t) * new_size);
45637 #else
45638 	DUK_MEMZERO(new_entries, sizeof(duk_hstring *) * new_size);
45639 #endif
45640 #endif
45641 
45642 	/* Because new_size > duk__count_used_probe(heap), guaranteed to work */
45643 	for (i = 0; i < old_size; i++) {
45644 		duk_hstring *e;
45645 
45646 #if defined(DUK_USE_HEAPPTR16)
45647 		e = (duk_hstring *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, old_entries[i]);
45648 #else
45649 		e = old_entries[i];
45650 #endif
45651 		if (e == NULL || e == DUK__DELETED_MARKER(heap)) {
45652 			continue;
45653 		}
45654 		/* checking for DUK__DELETED_MARKER is not necessary here, but helper does it now */
45655 		duk__insert_hstring_probe(heap, new_entries, new_size, &new_used, e);
45656 	}
45657 
45658 #ifdef DUK_USE_DDPRINT
45659 	DUK_DD(DUK_DDPRINT("resized stringtable: %ld entries, %ld bytes, %ld used, %ld%% load -> %ld entries, %ld bytes, %ld used, %ld%% load",
45660 	                   (long) old_size, (long) (sizeof(duk_hstring *) * old_size), (long) old_used,
45661 	                   (long) (((double) old_used) / ((double) old_size) * 100.0),
45662 	                   (long) new_size, (long) (sizeof(duk_hstring *) * new_size), (long) new_used,
45663 	                   (long) (((double) new_used) / ((double) new_size) * 100.0)));
45664 #endif
45665 
45666 #if defined(DUK_USE_HEAPPTR16)
45667 	DUK_FREE(heap, heap->strtable16);
45668 	heap->strtable16 = new_entries;
45669 #else
45670 	DUK_FREE(heap, heap->strtable);
45671 	heap->strtable = new_entries;
45672 #endif
45673 	heap->st_size = new_size;
45674 	heap->st_used = new_used;  /* may be less, since DELETED entries are NULLed by rehash */
45675 
45676 	return 0;  /* OK */
45677 
45678  resize_error:
45679 	DUK_FREE(heap, new_entries);
45680 	return 1;  /* FAIL */
45681 }
45682 
45683 DUK_LOCAL duk_bool_t duk__resize_strtab_probe(duk_heap *heap) {
45684 	duk_uint32_t new_size;
45685 	duk_bool_t ret;
45686 
45687 	new_size = (duk_uint32_t) duk__count_used_probe(heap);
45688 	if (new_size >= 0x80000000UL) {
45689 		new_size = DUK_STRTAB_HIGHEST_32BIT_PRIME;
45690 	} else {
45691 		new_size = duk_util_get_hash_prime(DUK_STRTAB_GROW_ST_SIZE(new_size));
45692 		new_size = duk_util_get_hash_prime(new_size);
45693 	}
45694 	DUK_ASSERT(new_size > 0);
45695 
45696 	/* rehash even if old and new sizes are the same to get rid of
45697 	 * DELETED entries.
45698 	*/
45699 
45700 	ret = duk__resize_strtab_raw_probe(heap, new_size);
45701 
45702 	return ret;
45703 }
45704 
45705 DUK_LOCAL duk_bool_t duk__recheck_strtab_size_probe(duk_heap *heap, duk_uint32_t new_used) {
45706 	duk_uint32_t new_free;
45707 	duk_uint32_t tmp1;
45708 	duk_uint32_t tmp2;
45709 
45710 	DUK_ASSERT(new_used <= heap->st_size);  /* grow by at most one */
45711 	new_free = heap->st_size - new_used;    /* unsigned intentionally */
45712 
45713 	/* new_free / size <= 1 / DIV  <=>  new_free <= size / DIV */
45714 	/* new_used / size <= 1 / DIV  <=>  new_used <= size / DIV */
45715 
45716 	tmp1 = heap->st_size / DUK_STRTAB_MIN_FREE_DIVISOR;
45717 	tmp2 = heap->st_size / DUK_STRTAB_MIN_USED_DIVISOR;
45718 
45719 	if (new_free <= tmp1 || new_used <= tmp2) {
45720 		/* load factor too low or high, count actually used entries and resize */
45721 		return duk__resize_strtab_probe(heap);
45722 	} else {
45723 		return 0;  /* OK */
45724 	}
45725 }
45726 
45727 #if defined(DUK_USE_DEBUG)
45728 DUK_INTERNAL void duk_heap_dump_strtab(duk_heap *heap) {
45729 	duk_uint32_t i;
45730 	duk_hstring *h;
45731 
45732 	DUK_ASSERT(heap != NULL);
45733 #if defined(DUK_USE_HEAPPTR16)
45734 	DUK_ASSERT(heap->strtable16 != NULL);
45735 #else
45736 	DUK_ASSERT(heap->strtable != NULL);
45737 #endif
45738 	DUK_UNREF(h);
45739 
45740 	for (i = 0; i < heap->st_size; i++) {
45741 #if defined(DUK_USE_HEAPPTR16)
45742 		h = (duk_hstring *) DUK_USE_HEAPPTR_DEC16(heap->strtable16[i]);
45743 #else
45744 		h = heap->strtable[i];
45745 #endif
45746 
45747 		DUK_DD(DUK_DDPRINT("[%03d] -> %p", (int) i, (void *) h));
45748 	}
45749 }
45750 #endif  /* DUK_USE_DEBUG */
45751 
45752 #endif  /* DUK_USE_STRTAB_PROBE */
45753 
45754 /*
45755  *  Raw intern and lookup
45756  */
45757 
45758 DUK_LOCAL duk_hstring *duk__do_intern(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t strhash) {
45759 	duk_hstring *res;
45760 	const duk_uint8_t *extdata;
45761 #if defined(DUK_USE_MARK_AND_SWEEP)
45762 	duk_small_uint_t prev_mark_and_sweep_base_flags;
45763 #endif
45764 
45765 	/* Prevent any side effects on the string table and the caller provided
45766 	 * str/blen arguments while interning is in progress.  For example, if
45767 	 * the caller provided str/blen from a dynamic buffer, a finalizer might
45768 	 * resize that dynamic buffer, invalidating the call arguments.
45769 	 */
45770 #if defined(DUK_USE_MARK_AND_SWEEP)
45771 	DUK_ASSERT((heap->mark_and_sweep_base_flags & DUK_MS_FLAG_NO_STRINGTABLE_RESIZE) == 0);
45772 	prev_mark_and_sweep_base_flags = heap->mark_and_sweep_base_flags;
45773 	DUK__PREVENT_MS_SIDE_EFFECTS(heap);
45774 #endif
45775 
45776 #if defined(DUK_USE_STRTAB_PROBE)
45777 	if (duk__recheck_strtab_size_probe(heap, heap->st_used + 1)) {
45778 		goto failed;
45779 	}
45780 #endif
45781 
45782 	/* For manual testing only. */
45783 #if 0
45784 	{
45785 		duk_size_t i;
45786 		DUK_PRINTF("INTERN: \"");
45787 		for (i = 0; i < blen; i++) {
45788 			duk_uint8_t x = str[i];
45789 			if (x >= 0x20 && x <= 0x7e && x != '"' && x != '\\') {
45790 				DUK_PRINTF("%c", (int) x);  /* char: use int cast */
45791 			} else {
45792 				DUK_PRINTF("\\x%02lx", (long) x);
45793 			}
45794 		}
45795 		DUK_PRINTF("\"\n");
45796 	}
45797 #endif
45798 
45799 #if defined(DUK_USE_HSTRING_EXTDATA) && defined(DUK_USE_EXTSTR_INTERN_CHECK)
45800 	extdata = (const duk_uint8_t *) DUK_USE_EXTSTR_INTERN_CHECK(heap->heap_udata, (void *) DUK_LOSE_CONST(str), (duk_size_t) blen);
45801 #else
45802 	extdata = (const duk_uint8_t *) NULL;
45803 #endif
45804 	res = duk__alloc_init_hstring(heap, str, blen, strhash, extdata);
45805 	if (!res) {
45806 		goto failed;
45807 	}
45808 
45809 #if defined(DUK_USE_STRTAB_CHAIN)
45810 	if (duk__insert_hstring_chain(heap, res)) {
45811 		/* failed */
45812 		DUK_FREE(heap, res);
45813 		goto failed;
45814 	}
45815 #elif defined(DUK_USE_STRTAB_PROBE)
45816 	/* guaranteed to succeed */
45817 	duk__insert_hstring_probe(heap,
45818 #if defined(DUK_USE_HEAPPTR16)
45819 	                          heap->strtable16,
45820 #else
45821 	                          heap->strtable,
45822 #endif
45823 	                          heap->st_size,
45824 	                          &heap->st_used,
45825 	                          res);
45826 #else
45827 #error internal error, invalid strtab options
45828 #endif
45829 
45830 	/* Note: hstring is in heap but has refcount zero and is not strongly reachable.
45831 	 * Caller should increase refcount and make the hstring reachable before any
45832 	 * operations which require allocation (and possible gc).
45833 	 */
45834 
45835  done:
45836 #if defined(DUK_USE_MARK_AND_SWEEP)
45837 	heap->mark_and_sweep_base_flags = prev_mark_and_sweep_base_flags;
45838 #endif
45839 	return res;
45840 
45841  failed:
45842 	res = NULL;
45843 	goto done;
45844 }
45845 
45846 DUK_LOCAL duk_hstring *duk__do_lookup(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t *out_strhash) {
45847 	duk_hstring *res;
45848 
45849 	DUK_ASSERT(out_strhash);
45850 
45851 	*out_strhash = duk_heap_hashstring(heap, str, (duk_size_t) blen);
45852 
45853 #if defined(DUK_USE_ROM_STRINGS)
45854 	{
45855 		duk_small_uint_t i;
45856 		/* XXX: This is VERY inefficient now, and should be e.g. a
45857 		 * binary search or perfect hash, to be fixed.
45858 		 */
45859 		for (i = 0; i < (duk_small_uint_t) (sizeof(duk_rom_strings) / sizeof(duk_hstring *)); i++) {
45860 			duk_hstring *romstr;
45861 			romstr = (duk_hstring *) DUK_LOSE_CONST(duk_rom_strings[i]);
45862 			if (blen == DUK_HSTRING_GET_BYTELEN(romstr) &&
45863 			    DUK_MEMCMP((const void *) str, (const void *) DUK_HSTRING_GET_DATA(romstr), blen) == 0) {
45864 				DUK_DD(DUK_DDPRINT("intern check: rom string: %!O, computed hash 0x%08lx, rom hash 0x%08lx",
45865 				                   romstr, (unsigned long) *out_strhash, (unsigned long) DUK_HSTRING_GET_HASH(romstr)));
45866 				DUK_ASSERT(*out_strhash == DUK_HSTRING_GET_HASH(romstr));
45867 				*out_strhash = DUK_HSTRING_GET_HASH(romstr);
45868 				return romstr;
45869 			}
45870 		}
45871 	}
45872 #endif  /* DUK_USE_ROM_STRINGS */
45873 
45874 #if defined(DUK_USE_STRTAB_CHAIN)
45875 	res = duk__find_matching_string_chain(heap, str, blen, *out_strhash);
45876 #elif defined(DUK_USE_STRTAB_PROBE)
45877 	res = duk__find_matching_string_probe(heap,
45878 #if defined(DUK_USE_HEAPPTR16)
45879 	                                      heap->strtable16,
45880 #else
45881 	                                      heap->strtable,
45882 #endif
45883 	                                      heap->st_size,
45884 	                                      str,
45885 	                                      blen,
45886 	                                      *out_strhash);
45887 #else
45888 #error internal error, invalid strtab options
45889 #endif
45890 
45891 	return res;
45892 }
45893 
45894 /*
45895  *  Exposed calls
45896  */
45897 
45898 #if 0  /*unused*/
45899 DUK_INTERNAL duk_hstring *duk_heap_string_lookup(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen) {
45900 	duk_uint32_t strhash;  /* dummy */
45901 	return duk__do_lookup(heap, str, blen, &strhash);
45902 }
45903 #endif
45904 
45905 DUK_INTERNAL duk_hstring *duk_heap_string_intern(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen) {
45906 	duk_hstring *res;
45907 	duk_uint32_t strhash;
45908 
45909 	/* caller is responsible for ensuring this */
45910 	DUK_ASSERT(blen <= DUK_HSTRING_MAX_BYTELEN);
45911 
45912 	res = duk__do_lookup(heap, str, blen, &strhash);
45913 	if (res) {
45914 		return res;
45915 	}
45916 
45917 	res = duk__do_intern(heap, str, blen, strhash);
45918 	return res;  /* may be NULL */
45919 }
45920 
45921 DUK_INTERNAL duk_hstring *duk_heap_string_intern_checked(duk_hthread *thr, const duk_uint8_t *str, duk_uint32_t blen) {
45922 	duk_hstring *res = duk_heap_string_intern(thr->heap, str, blen);
45923 	if (!res) {
45924 		DUK_ERROR_ALLOC_DEFMSG(thr);
45925 	}
45926 	return res;
45927 }
45928 
45929 #if 0  /*unused*/
45930 DUK_INTERNAL duk_hstring *duk_heap_string_lookup_u32(duk_heap *heap, duk_uint32_t val) {
45931 	char buf[DUK_STRTAB_U32_MAX_STRLEN+1];
45932 	DUK_SNPRINTF(buf, sizeof(buf), "%lu", (unsigned long) val);
45933 	buf[sizeof(buf) - 1] = (char) 0;
45934 	DUK_ASSERT(DUK_STRLEN(buf) <= DUK_UINT32_MAX);  /* formatted result limited */
45935 	return duk_heap_string_lookup(heap, (const duk_uint8_t *) buf, (duk_uint32_t) DUK_STRLEN(buf));
45936 }
45937 #endif
45938 
45939 DUK_INTERNAL duk_hstring *duk_heap_string_intern_u32(duk_heap *heap, duk_uint32_t val) {
45940 	char buf[DUK_STRTAB_U32_MAX_STRLEN+1];
45941 	DUK_SNPRINTF(buf, sizeof(buf), "%lu", (unsigned long) val);
45942 	buf[sizeof(buf) - 1] = (char) 0;
45943 	DUK_ASSERT(DUK_STRLEN(buf) <= DUK_UINT32_MAX);  /* formatted result limited */
45944 	return duk_heap_string_intern(heap, (const duk_uint8_t *) buf, (duk_uint32_t) DUK_STRLEN(buf));
45945 }
45946 
45947 DUK_INTERNAL duk_hstring *duk_heap_string_intern_u32_checked(duk_hthread *thr, duk_uint32_t val) {
45948 	duk_hstring *res = duk_heap_string_intern_u32(thr->heap, val);
45949 	if (!res) {
45950 		DUK_ERROR_ALLOC_DEFMSG(thr);
45951 	}
45952 	return res;
45953 }
45954 
45955 /* find and remove string from stringtable; caller must free the string itself */
45956 #if defined(DUK_USE_REFERENCE_COUNTING)
45957 DUK_INTERNAL void duk_heap_string_remove(duk_heap *heap, duk_hstring *h) {
45958 	DUK_DDD(DUK_DDDPRINT("remove string from stringtable: %!O", (duk_heaphdr *) h));
45959 
45960 #if defined(DUK_USE_STRTAB_CHAIN)
45961 	duk__remove_matching_hstring_chain(heap, h);
45962 #elif defined(DUK_USE_STRTAB_PROBE)
45963 	duk__remove_matching_hstring_probe(heap,
45964 #if defined(DUK_USE_HEAPPTR16)
45965 	                                   heap->strtable16,
45966 #else
45967 	                                   heap->strtable,
45968 #endif
45969 	                                   heap->st_size,
45970 	                                   h);
45971 #else
45972 #error internal error, invalid strtab options
45973 #endif
45974 }
45975 #endif
45976 
45977 #if defined(DUK_USE_MARK_AND_SWEEP) && defined(DUK_USE_MS_STRINGTABLE_RESIZE)
45978 DUK_INTERNAL void duk_heap_force_strtab_resize(duk_heap *heap) {
45979 	duk_small_uint_t prev_mark_and_sweep_base_flags;
45980 	/* Force a resize so that DELETED entries are eliminated.
45981 	 * Another option would be duk__recheck_strtab_size_probe();
45982 	 * but since that happens on every intern anyway, this whole
45983 	 * check can now be disabled.
45984 	 */
45985 
45986 	DUK_ASSERT((heap->mark_and_sweep_base_flags & DUK_MS_FLAG_NO_STRINGTABLE_RESIZE) == 0);
45987 	prev_mark_and_sweep_base_flags = heap->mark_and_sweep_base_flags;
45988 	DUK__PREVENT_MS_SIDE_EFFECTS(heap);
45989 
45990 #if defined(DUK_USE_STRTAB_CHAIN)
45991 	DUK_UNREF(heap);
45992 #elif defined(DUK_USE_STRTAB_PROBE)
45993 	(void) duk__resize_strtab_probe(heap);
45994 #endif
45995 
45996 	heap->mark_and_sweep_base_flags = prev_mark_and_sweep_base_flags;
45997 }
45998 #endif
45999 
46000 #if defined(DUK_USE_STRTAB_CHAIN)
46001 DUK_INTERNAL void duk_heap_free_strtab(duk_heap *heap) {
46002 	/* Free strings in the stringtable and any allocations needed
46003 	 * by the stringtable itself.
46004 	 */
46005 	duk_uint_fast32_t i, j;
46006 	duk_strtab_entry *e;
46007 #if defined(DUK_USE_HEAPPTR16)
46008 	duk_uint16_t *lst;
46009 	duk_uint16_t null16 = heap->heapptr_null16;
46010 #else
46011 	duk_hstring **lst;
46012 #endif
46013 	duk_hstring *h;
46014 
46015 	for (i = 0; i < DUK_STRTAB_CHAIN_SIZE; i++) {
46016 		e = heap->strtable + i;
46017 		if (e->listlen > 0) {
46018 #if defined(DUK_USE_HEAPPTR16)
46019 			lst = (duk_uint16_t *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, e->u.strlist16);
46020 #else
46021 			lst = e->u.strlist;
46022 #endif
46023 			DUK_ASSERT(lst != NULL);
46024 
46025 			for (j = 0; j < e->listlen; j++) {
46026 #if defined(DUK_USE_HEAPPTR16)
46027 				h = DUK_USE_HEAPPTR_DEC16(heap->heap_udata, lst[j]);
46028 				lst[j] = null16;
46029 #else
46030 				h = lst[j];
46031 				lst[j] = NULL;
46032 #endif
46033 				/* strings may have inner refs (extdata) in some cases */
46034 				if (h != NULL) {
46035 					duk_free_hstring_inner(heap, h);
46036 					DUK_FREE(heap, h);
46037 				}
46038 			}
46039 #if defined(DUK_USE_HEAPPTR16)
46040 			e->u.strlist16 = null16;
46041 #else
46042 			e->u.strlist = NULL;
46043 #endif
46044 			DUK_FREE(heap, lst);
46045 		} else {
46046 #if defined(DUK_USE_HEAPPTR16)
46047 			h = DUK_USE_HEAPPTR_DEC16(heap->heap_udata, e->u.str16);
46048 			e->u.str16 = null16;
46049 #else
46050 			h = e->u.str;
46051 			e->u.str = NULL;
46052 #endif
46053 			if (h != NULL) {
46054 				duk_free_hstring_inner(heap, h);
46055 				DUK_FREE(heap, h);
46056 			}
46057 		}
46058 		e->listlen = 0;
46059 	}
46060 }
46061 #endif  /* DUK_USE_STRTAB_CHAIN */
46062 
46063 #if defined(DUK_USE_STRTAB_PROBE)
46064 DUK_INTERNAL void duk_heap_free_strtab(duk_heap *heap) {
46065 	duk_uint_fast32_t i;
46066 	duk_hstring *h;
46067 
46068 #if defined(DUK_USE_HEAPPTR16)
46069 	if (heap->strtable16) {
46070 #else
46071 	if (heap->strtable) {
46072 #endif
46073 		for (i = 0; i < (duk_uint_fast32_t) heap->st_size; i++) {
46074 #if defined(DUK_USE_HEAPPTR16)
46075 			h = (duk_hstring *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, heap->strtable16[i]);
46076 #else
46077 			h = heap->strtable[i];
46078 #endif
46079 			if (h == NULL || h == DUK_STRTAB_DELETED_MARKER(heap)) {
46080 				continue;
46081 			}
46082 			DUK_ASSERT(h != NULL);
46083 
46084 			/* strings may have inner refs (extdata) in some cases */
46085 			duk_free_hstring_inner(heap, h);
46086 			DUK_FREE(heap, h);
46087 #if 0  /* not strictly necessary */
46088 			heap->strtable[i] = NULL;
46089 #endif
46090 		}
46091 #if defined(DUK_USE_HEAPPTR16)
46092 		DUK_FREE(heap, heap->strtable16);
46093 #else
46094 		DUK_FREE(heap, heap->strtable);
46095 #endif
46096 #if 0  /* not strictly necessary */
46097 		heap->strtable = NULL;
46098 #endif
46099 	}
46100 }
46101 #endif  /* DUK_USE_STRTAB_PROBE */
46102 
46103 /* Undefine local defines */
46104 #undef DUK__HASH_INITIAL
46105 #undef DUK__HASH_PROBE_STEP
46106 #undef DUK__DELETED_MARKER
46107 /*
46108  *  Hobject allocation.
46109  *
46110  *  Provides primitive allocation functions for all object types (plain object,
46111  *  compiled function, native function, thread).  The object return is not yet
46112  *  in "heap allocated" list and has a refcount of zero, so caller must careful.
46113  */
46114 
46115 /* include removed: duk_internal.h */
46116 
46117 DUK_LOCAL void duk__init_object_parts(duk_heap *heap, duk_hobject *obj, duk_uint_t hobject_flags) {
46118 #ifdef DUK_USE_EXPLICIT_NULL_INIT
46119 	DUK_HOBJECT_SET_PROPS(heap, obj, NULL);
46120 #endif
46121 
46122 	/* XXX: macro? sets both heaphdr and object flags */
46123 	obj->hdr.h_flags = hobject_flags;
46124 	DUK_HEAPHDR_SET_TYPE(&obj->hdr, DUK_HTYPE_OBJECT);  /* also goes into flags */
46125 
46126 #if defined(DUK_USE_HEAPPTR16)
46127 	/* Zero encoded pointer is required to match NULL */
46128 	DUK_HEAPHDR_SET_NEXT(heap, &obj->hdr, NULL);
46129 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
46130 	DUK_HEAPHDR_SET_PREV(heap, &obj->hdr, NULL);
46131 #endif
46132 #endif
46133 	DUK_ASSERT_HEAPHDR_LINKS(heap, &obj->hdr);
46134 	DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap, &obj->hdr);
46135 
46136 	/*
46137 	 *  obj->props is intentionally left as NULL, and duk_hobject_props.c must deal
46138 	 *  with this properly.  This is intentional: empty objects consume a minimum
46139 	 *  amount of memory.  Further, an initial allocation might fail and cause
46140 	 *  'obj' to "leak" (require a mark-and-sweep) since it is not reachable yet.
46141 	 */
46142 }
46143 
46144 /*
46145  *  Allocate an duk_hobject.
46146  *
46147  *  The allocated object has no allocation for properties; the caller may
46148  *  want to force a resize if a desired size is known.
46149  *
46150  *  The allocated object has zero reference count and is not reachable.
46151  *  The caller MUST make the object reachable and increase its reference
46152  *  count before invoking any operation that might require memory allocation.
46153  */
46154 
46155 DUK_INTERNAL duk_hobject *duk_hobject_alloc(duk_heap *heap, duk_uint_t hobject_flags) {
46156 	duk_hobject *res;
46157 
46158 	DUK_ASSERT(heap != NULL);
46159 
46160 	/* different memory layout, alloc size, and init */
46161 	DUK_ASSERT((hobject_flags & DUK_HOBJECT_FLAG_COMPILEDFUNCTION) == 0);
46162 	DUK_ASSERT((hobject_flags & DUK_HOBJECT_FLAG_NATIVEFUNCTION) == 0);
46163 	DUK_ASSERT((hobject_flags & DUK_HOBJECT_FLAG_THREAD) == 0);
46164 
46165 	res = (duk_hobject *) DUK_ALLOC(heap, sizeof(duk_hobject));
46166 	if (!res) {
46167 		return NULL;
46168 	}
46169 	DUK_MEMZERO(res, sizeof(duk_hobject));
46170 
46171 	duk__init_object_parts(heap, res, hobject_flags);
46172 
46173 	return res;
46174 }
46175 
46176 DUK_INTERNAL duk_hcompiledfunction *duk_hcompiledfunction_alloc(duk_heap *heap, duk_uint_t hobject_flags) {
46177 	duk_hcompiledfunction *res;
46178 
46179 	res = (duk_hcompiledfunction *) DUK_ALLOC(heap, sizeof(duk_hcompiledfunction));
46180 	if (!res) {
46181 		return NULL;
46182 	}
46183 	DUK_MEMZERO(res, sizeof(duk_hcompiledfunction));
46184 
46185 	duk__init_object_parts(heap, &res->obj, hobject_flags);
46186 
46187 #ifdef DUK_USE_EXPLICIT_NULL_INIT
46188 #ifdef DUK_USE_HEAPPTR16
46189 	/* NULL pointer is required to encode to zero, so memset is enough. */
46190 #else
46191 	res->data = NULL;
46192 	res->funcs = NULL;
46193 	res->bytecode = NULL;
46194 #endif
46195 #endif
46196 
46197 	return res;
46198 }
46199 
46200 DUK_INTERNAL duk_hnativefunction *duk_hnativefunction_alloc(duk_heap *heap, duk_uint_t hobject_flags) {
46201 	duk_hnativefunction *res;
46202 
46203 	res = (duk_hnativefunction *) DUK_ALLOC(heap, sizeof(duk_hnativefunction));
46204 	if (!res) {
46205 		return NULL;
46206 	}
46207 	DUK_MEMZERO(res, sizeof(duk_hnativefunction));
46208 
46209 	duk__init_object_parts(heap, &res->obj, hobject_flags);
46210 
46211 #ifdef DUK_USE_EXPLICIT_NULL_INIT
46212 	res->func = NULL;
46213 #endif
46214 
46215 	return res;
46216 }
46217 
46218 DUK_INTERNAL duk_hbufferobject *duk_hbufferobject_alloc(duk_heap *heap, duk_uint_t hobject_flags) {
46219 	duk_hbufferobject *res;
46220 
46221 	res = (duk_hbufferobject *) DUK_ALLOC(heap, sizeof(duk_hbufferobject));
46222 	if (!res) {
46223 		return NULL;
46224 	}
46225 	DUK_MEMZERO(res, sizeof(duk_hbufferobject));
46226 
46227 	duk__init_object_parts(heap, &res->obj, hobject_flags);
46228 
46229 #ifdef DUK_USE_EXPLICIT_NULL_INIT
46230 	res->buf = NULL;
46231 #endif
46232 
46233 	DUK_ASSERT_HBUFFEROBJECT_VALID(res);
46234 	return res;
46235 }
46236 
46237 /*
46238  *  Allocate a new thread.
46239  *
46240  *  Leaves the built-ins array uninitialized.  The caller must either
46241  *  initialize a new global context or share existing built-ins from
46242  *  another thread.
46243  */
46244 
46245 DUK_INTERNAL duk_hthread *duk_hthread_alloc(duk_heap *heap, duk_uint_t hobject_flags) {
46246 	duk_hthread *res;
46247 
46248 	res = (duk_hthread *) DUK_ALLOC(heap, sizeof(duk_hthread));
46249 	if (!res) {
46250 		return NULL;
46251 	}
46252 	DUK_MEMZERO(res, sizeof(duk_hthread));
46253 
46254 	duk__init_object_parts(heap, &res->obj, hobject_flags);
46255 
46256 #ifdef DUK_USE_EXPLICIT_NULL_INIT
46257 	res->ptr_curr_pc = NULL;
46258 	res->heap = NULL;
46259 	res->valstack = NULL;
46260 	res->valstack_end = NULL;
46261 	res->valstack_bottom = NULL;
46262 	res->valstack_top = NULL;
46263 	res->callstack = NULL;
46264 	res->catchstack = NULL;
46265 	res->resumer = NULL;
46266 	res->compile_ctx = NULL,
46267 #ifdef DUK_USE_HEAPPTR16
46268 	res->strs16 = NULL;
46269 #else
46270 	res->strs = NULL;
46271 #endif
46272 	{
46273 		int i;
46274 		for (i = 0; i < DUK_NUM_BUILTINS; i++) {
46275 			res->builtins[i] = NULL;
46276 		}
46277 	}
46278 #endif
46279 	/* when nothing is running, API calls are in non-strict mode */
46280 	DUK_ASSERT(res->strict == 0);
46281 
46282 	res->heap = heap;
46283 	res->valstack_max = DUK_VALSTACK_DEFAULT_MAX;
46284 	res->callstack_max = DUK_CALLSTACK_DEFAULT_MAX;
46285 	res->catchstack_max = DUK_CATCHSTACK_DEFAULT_MAX;
46286 
46287 	return res;
46288 }
46289 
46290 #if 0  /* unused now */
46291 DUK_INTERNAL duk_hobject *duk_hobject_alloc_checked(duk_hthread *thr, duk_uint_t hobject_flags) {
46292 	duk_hobject *res = duk_hobject_alloc(thr->heap, hobject_flags);
46293 	if (!res) {
46294 		DUK_ERROR_ALLOC_DEFMSG(thr);
46295 	}
46296 	return res;
46297 }
46298 #endif
46299 /*
46300  *  Hobject enumeration support.
46301  *
46302  *  Creates an internal enumeration state object to be used e.g. with for-in
46303  *  enumeration.  The state object contains a snapshot of target object keys
46304  *  and internal control state for enumeration.  Enumerator flags allow caller
46305  *  to e.g. request internal/non-enumerable properties, and to enumerate only
46306  *  "own" properties.
46307  *
46308  *  Also creates the result value for e.g. Object.keys() based on the same
46309  *  internal structure.
46310  *
46311  *  This snapshot-based enumeration approach is used to simplify enumeration:
46312  *  non-snapshot-based approaches are difficult to reconcile with mutating
46313  *  the enumeration target, running multiple long-lived enumerators at the
46314  *  same time, garbage collection details, etc.  The downside is that the
46315  *  enumerator object is memory inefficient especially for iterating arrays.
46316  */
46317 
46318 /* include removed: duk_internal.h */
46319 
46320 /* XXX: identify enumeration target with an object index (not top of stack) */
46321 
46322 /* must match exactly the number of internal properties inserted to enumerator */
46323 #define DUK__ENUM_START_INDEX  2
46324 
46325 DUK_LOCAL const duk_uint16_t duk__bufferobject_virtual_props[] = {
46326 	DUK_STRIDX_LENGTH,
46327 	DUK_STRIDX_BYTE_LENGTH,
46328 	DUK_STRIDX_BYTE_OFFSET,
46329 	DUK_STRIDX_BYTES_PER_ELEMENT
46330 };
46331 
46332 /*
46333  *  Helper to sort array index keys.  The keys are in the enumeration object
46334  *  entry part, starting from DUK__ENUM_START_INDEX, and the entry part is dense.
46335  *
46336  *  We use insertion sort because it is simple (leading to compact code,)
46337  *  works nicely in-place, and minimizes operations if data is already sorted
46338  *  or nearly sorted (which is a very common case here).  It also minimizes
46339  *  the use of element comparisons in general.  This is nice because element
46340  *  comparisons here involve re-parsing the string keys into numbers each
46341  *  time, which is naturally very expensive.
46342  *
46343  *  Note that the entry part values are all "true", e.g.
46344  *
46345  *    "1" -> true, "3" -> true, "2" -> true
46346  *
46347  *  so it suffices to only work in the key part without exchanging any keys,
46348  *  simplifying the sort.
46349  *
46350  *  http://en.wikipedia.org/wiki/Insertion_sort
46351  *
46352  *  (Compiles to about 160 bytes now as a stand-alone function.)
46353  */
46354 
46355 DUK_LOCAL void duk__sort_array_indices(duk_hthread *thr, duk_hobject *h_obj) {
46356 	duk_hstring **keys;
46357 	duk_hstring **p_curr, **p_insert, **p_end;
46358 	duk_hstring *h_curr;
46359 	duk_uarridx_t val_highest, val_curr, val_insert;
46360 
46361 	DUK_ASSERT(h_obj != NULL);
46362 	DUK_ASSERT(DUK_HOBJECT_GET_ENEXT(h_obj) >= 2);  /* control props */
46363 	DUK_UNREF(thr);
46364 
46365 	if (DUK_HOBJECT_GET_ENEXT(h_obj) <= 1 + DUK__ENUM_START_INDEX) {
46366 		return;
46367 	}
46368 
46369 	keys = DUK_HOBJECT_E_GET_KEY_BASE(thr->heap, h_obj);
46370 	p_end = keys + DUK_HOBJECT_GET_ENEXT(h_obj);
46371 	keys += DUK__ENUM_START_INDEX;
46372 
46373 	DUK_DDD(DUK_DDDPRINT("keys=%p, p_end=%p (after skipping enum props)",
46374 	                     (void *) keys, (void *) p_end));
46375 
46376 #ifdef DUK_USE_DDDPRINT
46377 	{
46378 		duk_uint_fast32_t i;
46379 		for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h_obj); i++) {
46380 			DUK_DDD(DUK_DDDPRINT("initial: %ld %p -> %!O",
46381 			                     (long) i,
46382 			                     (void *) DUK_HOBJECT_E_GET_KEY_PTR(thr->heap, h_obj, i),
46383 			                     (duk_heaphdr *) DUK_HOBJECT_E_GET_KEY(thr->heap, h_obj, i)));
46384 		}
46385 	}
46386 #endif
46387 
46388 	val_highest = DUK_HSTRING_GET_ARRIDX_SLOW(keys[0]);
46389 	for (p_curr = keys + 1; p_curr < p_end; p_curr++) {
46390 		DUK_ASSERT(*p_curr != NULL);
46391 		val_curr = DUK_HSTRING_GET_ARRIDX_SLOW(*p_curr);
46392 
46393 		if (val_curr >= val_highest) {
46394 			DUK_DDD(DUK_DDDPRINT("p_curr=%p, p_end=%p, val_highest=%ld, val_curr=%ld -> "
46395 			                     "already in correct order, next",
46396 			                     (void *) p_curr, (void *) p_end, (long) val_highest, (long) val_curr));
46397 			val_highest = val_curr;
46398 			continue;
46399 		}
46400 
46401 		DUK_DDD(DUK_DDDPRINT("p_curr=%p, p_end=%p, val_highest=%ld, val_curr=%ld -> "
46402 		                     "needs to be inserted",
46403 		                     (void *) p_curr, (void *) p_end, (long) val_highest, (long) val_curr));
46404 
46405 		/* Needs to be inserted; scan backwards, since we optimize
46406 		 * for the case where elements are nearly in order.
46407 		 */
46408 
46409 		p_insert = p_curr - 1;
46410 		for (;;) {
46411 			val_insert = DUK_HSTRING_GET_ARRIDX_SLOW(*p_insert);
46412 			if (val_insert < val_curr) {
46413 				DUK_DDD(DUK_DDDPRINT("p_insert=%p, val_insert=%ld, val_curr=%ld -> insert after this",
46414 				                     (void *) p_insert, (long) val_insert, (long) val_curr));
46415 				p_insert++;
46416 				break;
46417 			}
46418 			if (p_insert == keys) {
46419 				DUK_DDD(DUK_DDDPRINT("p_insert=%p -> out of keys, insert to beginning", (void *) p_insert));
46420 				break;
46421 			}
46422 			DUK_DDD(DUK_DDDPRINT("p_insert=%p, val_insert=%ld, val_curr=%ld -> search backwards",
46423 			                     (void *) p_insert, (long) val_insert, (long) val_curr));
46424 			p_insert--;
46425 		}
46426 
46427 		DUK_DDD(DUK_DDDPRINT("final p_insert=%p", (void *) p_insert));
46428 
46429 		/*        .-- p_insert   .-- p_curr
46430 		 *        v              v
46431 		 *  | ... | insert | ... | curr
46432 		 */
46433 
46434 		h_curr = *p_curr;
46435 		DUK_DDD(DUK_DDDPRINT("memmove: dest=%p, src=%p, size=%ld, h_curr=%p",
46436 		                     (void *) (p_insert + 1), (void *) p_insert,
46437 		                     (long) (p_curr - p_insert), (void *) h_curr));
46438 
46439 		DUK_MEMMOVE((void *) (p_insert + 1),
46440 		            (const void *) p_insert,
46441 		            (size_t) ((p_curr - p_insert) * sizeof(duk_hstring *)));
46442 		*p_insert = h_curr;
46443 		/* keep val_highest */
46444 	}
46445 
46446 #ifdef DUK_USE_DDDPRINT
46447 	{
46448 		duk_uint_fast32_t i;
46449 		for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h_obj); i++) {
46450 			DUK_DDD(DUK_DDDPRINT("final: %ld %p -> %!O",
46451 			                     (long) i,
46452 			                     (void *) DUK_HOBJECT_E_GET_KEY_PTR(thr->heap, h_obj, i),
46453 			                     (duk_heaphdr *) DUK_HOBJECT_E_GET_KEY(thr->heap, h_obj, i)));
46454 		}
46455 	}
46456 #endif
46457 }
46458 
46459 /*
46460  *  Create an internal enumerator object E, which has its keys ordered
46461  *  to match desired enumeration ordering.  Also initialize internal control
46462  *  properties for enumeration.
46463  *
46464  *  Note: if an array was used to hold enumeration keys instead, an array
46465  *  scan would be needed to eliminate duplicates found in the prototype chain.
46466  */
46467 
46468 DUK_INTERNAL void duk_hobject_enumerator_create(duk_context *ctx, duk_small_uint_t enum_flags) {
46469 	duk_hthread *thr = (duk_hthread *) ctx;
46470 	duk_hobject *enum_target;
46471 	duk_hobject *curr;
46472 	duk_hobject *res;
46473 #if defined(DUK_USE_ES6_PROXY)
46474 	duk_hobject *h_proxy_target;
46475 	duk_hobject *h_proxy_handler;
46476 	duk_hobject *h_trap_result;
46477 #endif
46478 	duk_uint_fast32_t i, len;  /* used for array, stack, and entry indices */
46479 
46480 	DUK_ASSERT(ctx != NULL);
46481 
46482 	DUK_DDD(DUK_DDDPRINT("create enumerator, stack top: %ld", (long) duk_get_top(ctx)));
46483 
46484 	enum_target = duk_require_hobject(ctx, -1);
46485 	DUK_ASSERT(enum_target != NULL);
46486 
46487 	duk_push_object_internal(ctx);
46488 	res = duk_require_hobject(ctx, -1);
46489 
46490 	DUK_DDD(DUK_DDDPRINT("created internal object"));
46491 
46492 	/* [enum_target res] */
46493 
46494 	/* Target must be stored so that we can recheck whether or not
46495 	 * keys still exist when we enumerate.  This is not done if the
46496 	 * enumeration result comes from a proxy trap as there is no
46497 	 * real object to check against.
46498 	 */
46499 	duk_push_hobject(ctx, enum_target);
46500 	duk_put_prop_stridx(ctx, -2, DUK_STRIDX_INT_TARGET);
46501 
46502 	/* Initialize index so that we skip internal control keys. */
46503 	duk_push_int(ctx, DUK__ENUM_START_INDEX);
46504 	duk_put_prop_stridx(ctx, -2, DUK_STRIDX_INT_NEXT);
46505 
46506 	/*
46507 	 *  Proxy object handling
46508 	 */
46509 
46510 #if defined(DUK_USE_ES6_PROXY)
46511 	if (DUK_LIKELY((enum_flags & DUK_ENUM_NO_PROXY_BEHAVIOR) != 0)) {
46512 		goto skip_proxy;
46513 	}
46514 	if (DUK_LIKELY(!duk_hobject_proxy_check(thr,
46515 	                                        enum_target,
46516 	                                        &h_proxy_target,
46517 	                                        &h_proxy_handler))) {
46518 		goto skip_proxy;
46519 	}
46520 
46521 	DUK_DDD(DUK_DDDPRINT("proxy enumeration"));
46522 	duk_push_hobject(ctx, h_proxy_handler);
46523 	if (!duk_get_prop_stridx(ctx, -1, DUK_STRIDX_ENUMERATE)) {
46524 		/* No need to replace the 'enum_target' value in stack, only the
46525 		 * enum_target reference.  This also ensures that the original
46526 		 * enum target is reachable, which keeps the proxy and the proxy
46527 		 * target reachable.  We do need to replace the internal _Target.
46528 		 */
46529 		DUK_DDD(DUK_DDDPRINT("no enumerate trap, enumerate proxy target instead"));
46530 		DUK_DDD(DUK_DDDPRINT("h_proxy_target=%!O", (duk_heaphdr *) h_proxy_target));
46531 		enum_target = h_proxy_target;
46532 
46533 		duk_push_hobject(ctx, enum_target);  /* -> [ ... enum_target res handler undefined target ] */
46534 		duk_put_prop_stridx(ctx, -4, DUK_STRIDX_INT_TARGET);
46535 
46536 		duk_pop_2(ctx);  /* -> [ ... enum_target res ] */
46537 		goto skip_proxy;
46538 	}
46539 
46540 	/* [ ... enum_target res handler trap ] */
46541 	duk_insert(ctx, -2);
46542 	duk_push_hobject(ctx, h_proxy_target);    /* -> [ ... enum_target res trap handler target ] */
46543 	duk_call_method(ctx, 1 /*nargs*/);        /* -> [ ... enum_target res trap_result ] */
46544 	h_trap_result = duk_require_hobject(ctx, -1);
46545 	DUK_UNREF(h_trap_result);
46546 
46547 	/* Copy trap result keys into the enumerator object. */
46548 	len = (duk_uint_fast32_t) duk_get_length(ctx, -1);
46549 	for (i = 0; i < len; i++) {
46550 		/* XXX: not sure what the correct semantic details are here,
46551 		 * e.g. handling of missing values (gaps), handling of non-array
46552 		 * trap results, etc.
46553 		 *
46554 		 * For keys, we simply skip non-string keys which seems to be
46555 		 * consistent with how e.g. Object.keys() will process proxy trap
46556 		 * results (ES6, Section 19.1.2.14).
46557 		 */
46558 		if (duk_get_prop_index(ctx, -1, i) && duk_is_string(ctx, -1)) {
46559 			/* [ ... enum_target res trap_result val ] */
46560 			duk_push_true(ctx);
46561 			/* [ ... enum_target res trap_result val true ] */
46562 			duk_put_prop(ctx, -4);
46563 		} else {
46564 			duk_pop(ctx);
46565 		}
46566 	}
46567 	/* [ ... enum_target res trap_result ] */
46568 	duk_pop(ctx);
46569 	duk_remove(ctx, -2);
46570 
46571 	/* [ ... res ] */
46572 
46573 	/* The internal _Target property is kept pointing to the original
46574 	 * enumeration target (the proxy object), so that the enumerator
46575 	 * 'next' operation can read property values if so requested.  The
46576 	 * fact that the _Target is a proxy disables key existence check
46577 	 * during enumeration.
46578 	 */
46579 	DUK_DDD(DUK_DDDPRINT("proxy enumeration, final res: %!O", (duk_heaphdr *) res));
46580 	goto compact_and_return;
46581 
46582  skip_proxy:
46583 #endif  /* DUK_USE_ES6_PROXY */
46584 
46585 	curr = enum_target;
46586 	while (curr) {
46587 		/*
46588 		 *  Virtual properties.
46589 		 *
46590 		 *  String and buffer indices are virtual and always enumerable,
46591 		 *  'length' is virtual and non-enumerable.  Array and arguments
46592 		 *  object props have special behavior but are concrete.
46593 		 */
46594 
46595 		if (DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(curr) ||
46596 		    DUK_HOBJECT_IS_BUFFEROBJECT(curr)) {
46597 			/* String and buffer enumeration behavior is identical now,
46598 			 * so use shared handler.
46599 			 */
46600 			if (DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(curr)) {
46601 				duk_hstring *h_val;
46602 				h_val = duk_hobject_get_internal_value_string(thr->heap, curr);
46603 				DUK_ASSERT(h_val != NULL);  /* string objects must not created without internal value */
46604 				len = (duk_uint_fast32_t) DUK_HSTRING_GET_CHARLEN(h_val);
46605 			} else {
46606 				duk_hbufferobject *h_bufobj;
46607 				DUK_ASSERT(DUK_HOBJECT_IS_BUFFEROBJECT(curr));
46608 				h_bufobj = (duk_hbufferobject *) curr;
46609 				if (h_bufobj == NULL) {
46610 					/* Neutered buffer, zero length seems
46611 					 * like good behavior here.
46612 					 */
46613 					len = 0;
46614 				} else {
46615 					/* There's intentionally no check for
46616 					 * current underlying buffer length.
46617 					 */
46618 					len = (duk_uint_fast32_t) (h_bufobj->length >> h_bufobj->shift);
46619 				}
46620 			}
46621 
46622 			for (i = 0; i < len; i++) {
46623 				duk_hstring *k;
46624 
46625 				k = duk_heap_string_intern_u32_checked(thr, i);
46626 				DUK_ASSERT(k);
46627 				duk_push_hstring(ctx, k);
46628 				duk_push_true(ctx);
46629 
46630 				/* [enum_target res key true] */
46631 				duk_put_prop(ctx, -3);
46632 
46633 				/* [enum_target res] */
46634 			}
46635 
46636 			/* 'length' and other virtual properties are not
46637 			 * enumerable, but are included if non-enumerable
46638 			 * properties are requested.
46639 			 */
46640 
46641 			if (enum_flags & DUK_ENUM_INCLUDE_NONENUMERABLE) {
46642 				duk_uint_fast32_t n;
46643 
46644 				if (DUK_HOBJECT_IS_BUFFEROBJECT(curr)) {
46645 					n = sizeof(duk__bufferobject_virtual_props) / sizeof(duk_uint16_t);
46646 				} else {
46647 					DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(curr));
46648 					DUK_ASSERT(duk__bufferobject_virtual_props[0] == DUK_STRIDX_LENGTH);
46649 					n = 1;  /* only 'length' */
46650 				}
46651 
46652 				for (i = 0; i < n; i++) {
46653 					duk_push_hstring_stridx(ctx, duk__bufferobject_virtual_props[i]);
46654 					duk_push_true(ctx);
46655 					duk_put_prop(ctx, -3);
46656 				}
46657 
46658 			}
46659 		} else if (DUK_HOBJECT_HAS_EXOTIC_DUKFUNC(curr)) {
46660 			if (enum_flags & DUK_ENUM_INCLUDE_NONENUMERABLE) {
46661 				duk_push_hstring_stridx(ctx, DUK_STRIDX_LENGTH);
46662 				duk_push_true(ctx);
46663 				duk_put_prop(ctx, -3);
46664 			}
46665 		}
46666 
46667 		/*
46668 		 *  Array part
46669 		 *
46670 		 *  Note: ordering between array and entry part must match 'abandon array'
46671 		 *  behavior in duk_hobject_props.c: key order after an array is abandoned
46672 		 *  must be the same.
46673 		 */
46674 
46675 		for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(curr); i++) {
46676 			duk_hstring *k;
46677 			duk_tval *tv;
46678 
46679 			tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, curr, i);
46680 			if (DUK_TVAL_IS_UNUSED(tv)) {
46681 				continue;
46682 			}
46683 			k = duk_heap_string_intern_u32_checked(thr, i);
46684 			DUK_ASSERT(k);
46685 
46686 			duk_push_hstring(ctx, k);
46687 			duk_push_true(ctx);
46688 
46689 			/* [enum_target res key true] */
46690 			duk_put_prop(ctx, -3);
46691 
46692 			/* [enum_target res] */
46693 		}
46694 
46695 		/*
46696 		 *  Entries part
46697 		 */
46698 
46699 		for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(curr); i++) {
46700 			duk_hstring *k;
46701 
46702 			k = DUK_HOBJECT_E_GET_KEY(thr->heap, curr, i);
46703 			if (!k) {
46704 				continue;
46705 			}
46706 			if (!DUK_HOBJECT_E_SLOT_IS_ENUMERABLE(thr->heap, curr, i) &&
46707 			    !(enum_flags & DUK_ENUM_INCLUDE_NONENUMERABLE)) {
46708 				continue;
46709 			}
46710 			if (DUK_HSTRING_HAS_INTERNAL(k) &&
46711 			    !(enum_flags & DUK_ENUM_INCLUDE_INTERNAL)) {
46712 				continue;
46713 			}
46714 			if ((enum_flags & DUK_ENUM_ARRAY_INDICES_ONLY) &&
46715 			    (DUK_HSTRING_GET_ARRIDX_SLOW(k) == DUK_HSTRING_NO_ARRAY_INDEX)) {
46716 				continue;
46717 			}
46718 
46719 			DUK_ASSERT(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, curr, i) ||
46720 			           !DUK_TVAL_IS_UNUSED(&DUK_HOBJECT_E_GET_VALUE_PTR(thr->heap, curr, i)->v));
46721 
46722 			duk_push_hstring(ctx, k);
46723 			duk_push_true(ctx);
46724 
46725 			/* [enum_target res key true] */
46726 			duk_put_prop(ctx, -3);
46727 
46728 			/* [enum_target res] */
46729 		}
46730 
46731 		if (enum_flags & DUK_ENUM_OWN_PROPERTIES_ONLY) {
46732 			break;
46733 		}
46734 
46735 		curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr);
46736 	}
46737 
46738 	/* [enum_target res] */
46739 
46740 	duk_remove(ctx, -2);
46741 
46742 	/* [res] */
46743 
46744 	if ((enum_flags & (DUK_ENUM_ARRAY_INDICES_ONLY | DUK_ENUM_SORT_ARRAY_INDICES)) ==
46745 	                  (DUK_ENUM_ARRAY_INDICES_ONLY | DUK_ENUM_SORT_ARRAY_INDICES)) {
46746 		/*
46747 		 *  Some E5/E5.1 algorithms require that array indices are iterated
46748 		 *  in a strictly ascending order.  This is the case for e.g.
46749 		 *  Array.prototype.forEach() and JSON.stringify() PropertyList
46750 		 *  handling.
46751 		 *
46752 		 *  To ensure this property for arrays with an array part (and
46753 		 *  arbitrary objects too, since e.g. forEach() can be applied
46754 		 *  to an array), the caller can request that we sort the keys
46755 		 *  here.
46756 		 */
46757 
46758 		/* XXX: avoid this at least when enum_target is an Array, it has an
46759 		 * array part, and no ancestor properties were included?  Not worth
46760 		 * it for JSON, but maybe worth it for forEach().
46761 		 */
46762 
46763 		/* XXX: may need a 'length' filter for forEach()
46764 		 */
46765 		DUK_DDD(DUK_DDDPRINT("sort array indices by caller request"));
46766 		duk__sort_array_indices(thr, res);
46767 	}
46768 
46769 #if defined(DUK_USE_ES6_PROXY)
46770  compact_and_return:
46771 #endif
46772 	/* compact; no need to seal because object is internal */
46773 	duk_hobject_compact_props(thr, res);
46774 
46775 	DUK_DDD(DUK_DDDPRINT("created enumerator object: %!iT", (duk_tval *) duk_get_tval(ctx, -1)));
46776 }
46777 
46778 /*
46779  *  Returns non-zero if a key and/or value was enumerated, and:
46780  *
46781  *   [enum] -> [key]        (get_value == 0)
46782  *   [enum] -> [key value]  (get_value == 1)
46783  *
46784  *  Returns zero without pushing anything on the stack otherwise.
46785  */
46786 DUK_INTERNAL duk_bool_t duk_hobject_enumerator_next(duk_context *ctx, duk_bool_t get_value) {
46787 	duk_hthread *thr = (duk_hthread *) ctx;
46788 	duk_hobject *e;
46789 	duk_hobject *enum_target;
46790 	duk_hstring *res = NULL;
46791 	duk_uint_fast32_t idx;
46792 	duk_bool_t check_existence;
46793 
46794 	DUK_ASSERT(ctx != NULL);
46795 
46796 	/* [... enum] */
46797 
46798 	e = duk_require_hobject(ctx, -1);
46799 
46800 	/* XXX use get tval ptr, more efficient */
46801 	duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_NEXT);
46802 	idx = (duk_uint_fast32_t) duk_require_uint(ctx, -1);
46803 	duk_pop(ctx);
46804 	DUK_DDD(DUK_DDDPRINT("enumeration: index is: %ld", (long) idx));
46805 
46806 	/* Enumeration keys are checked against the enumeration target (to see
46807 	 * that they still exist).  In the proxy enumeration case _Target will
46808 	 * be the proxy, and checking key existence against the proxy is not
46809 	 * required (or sensible, as the keys may be fully virtual).
46810 	 */
46811 	duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_TARGET);
46812 	enum_target = duk_require_hobject(ctx, -1);
46813 	DUK_ASSERT(enum_target != NULL);
46814 #if defined(DUK_USE_ES6_PROXY)
46815 	check_existence = (!DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(enum_target));
46816 #else
46817 	check_existence = 1;
46818 #endif
46819 	duk_pop(ctx);  /* still reachable */
46820 
46821 	DUK_DDD(DUK_DDDPRINT("getting next enum value, enum_target=%!iO, enumerator=%!iT",
46822 	                     (duk_heaphdr *) enum_target, (duk_tval *) duk_get_tval(ctx, -1)));
46823 
46824 	/* no array part */
46825 	for (;;) {
46826 		duk_hstring *k;
46827 
46828 		if (idx >= DUK_HOBJECT_GET_ENEXT(e)) {
46829 			DUK_DDD(DUK_DDDPRINT("enumeration: ran out of elements"));
46830 			break;
46831 		}
46832 
46833 		/* we know these because enum objects are internally created */
46834 		k = DUK_HOBJECT_E_GET_KEY(thr->heap, e, idx);
46835 		DUK_ASSERT(k != NULL);
46836 		DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, e, idx));
46837 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(&DUK_HOBJECT_E_GET_VALUE(thr->heap, e, idx).v));
46838 
46839 		idx++;
46840 
46841 		/* recheck that the property still exists */
46842 		if (check_existence && !duk_hobject_hasprop_raw(thr, enum_target, k)) {
46843 			DUK_DDD(DUK_DDDPRINT("property deleted during enumeration, skip"));
46844 			continue;
46845 		}
46846 
46847 		DUK_DDD(DUK_DDDPRINT("enumeration: found element, key: %!O", (duk_heaphdr *) k));
46848 		res = k;
46849 		break;
46850 	}
46851 
46852 	DUK_DDD(DUK_DDDPRINT("enumeration: updating next index to %ld", (long) idx));
46853 
46854 	duk_push_u32(ctx, (duk_uint32_t) idx);
46855 	duk_put_prop_stridx(ctx, -2, DUK_STRIDX_INT_NEXT);
46856 
46857 	/* [... enum] */
46858 
46859 	if (res) {
46860 		duk_push_hstring(ctx, res);
46861 		if (get_value) {
46862 			duk_push_hobject(ctx, enum_target);
46863 			duk_dup(ctx, -2);      /* -> [... enum key enum_target key] */
46864 			duk_get_prop(ctx, -2); /* -> [... enum key enum_target val] */
46865 			duk_remove(ctx, -2);   /* -> [... enum key val] */
46866 			duk_remove(ctx, -3);   /* -> [... key val] */
46867 		} else {
46868 			duk_remove(ctx, -2);   /* -> [... key] */
46869 		}
46870 		return 1;
46871 	} else {
46872 		duk_pop(ctx);  /* -> [...] */
46873 		return 0;
46874 	}
46875 }
46876 
46877 /*
46878  *  Get enumerated keys in an Ecmascript array.  Matches Object.keys() behavior
46879  *  described in E5 Section 15.2.3.14.
46880  */
46881 
46882 DUK_INTERNAL duk_ret_t duk_hobject_get_enumerated_keys(duk_context *ctx, duk_small_uint_t enum_flags) {
46883 	duk_hthread *thr = (duk_hthread *) ctx;
46884 	duk_hobject *e;
46885 	duk_uint_fast32_t i;
46886 	duk_uint_fast32_t idx;
46887 
46888 	DUK_ASSERT(ctx != NULL);
46889 	DUK_ASSERT(duk_get_hobject(ctx, -1) != NULL);
46890 	DUK_UNREF(thr);
46891 
46892 	/* Create a temporary enumerator to get the (non-duplicated) key list;
46893 	 * the enumerator state is initialized without being needed, but that
46894 	 * has little impact.
46895 	 */
46896 
46897 	duk_hobject_enumerator_create(ctx, enum_flags);
46898 	duk_push_array(ctx);
46899 
46900 	/* [enum_target enum res] */
46901 
46902 	e = duk_require_hobject(ctx, -2);
46903 	DUK_ASSERT(e != NULL);
46904 
46905 	idx = 0;
46906 	for (i = DUK__ENUM_START_INDEX; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(e); i++) {
46907 		duk_hstring *k;
46908 
46909 		k = DUK_HOBJECT_E_GET_KEY(thr->heap, e, i);
46910 		DUK_ASSERT(k);  /* enumerator must have no keys deleted */
46911 
46912 		/* [enum_target enum res] */
46913 		duk_push_hstring(ctx, k);
46914 		duk_put_prop_index(ctx, -2, idx);
46915 		idx++;
46916 	}
46917 
46918 	/* [enum_target enum res] */
46919 	duk_remove(ctx, -2);
46920 
46921 	/* [enum_target res] */
46922 
46923 	return 1;  /* return 1 to allow callers to tail call */
46924 }
46925 /*
46926  *  Run an duk_hobject finalizer.  Used for both reference counting
46927  *  and mark-and-sweep algorithms.  Must never throw an error.
46928  *
46929  *  There is no return value.  Any return value or error thrown by
46930  *  the finalizer is ignored (although errors are debug logged).
46931  *
46932  *  Notes:
46933  *
46934  *    - The thread used for calling the finalizer is the same as the
46935  *      'thr' argument.  This may need to change later.
46936  *
46937  *    - The finalizer thread 'top' assertions are there because it is
46938  *      critical that strict stack policy is observed (i.e. no cruft
46939  *      left on the finalizer stack).
46940  */
46941 
46942 /* include removed: duk_internal.h */
46943 
46944 DUK_LOCAL duk_ret_t duk__finalize_helper(duk_context *ctx) {
46945 	duk_hthread *thr;
46946 
46947 	DUK_ASSERT(ctx != NULL);
46948 	thr = (duk_hthread *) ctx;
46949 
46950 	DUK_DDD(DUK_DDDPRINT("protected finalization helper running"));
46951 
46952 	/* [... obj] */
46953 
46954 	/* XXX: Finalizer lookup should traverse the prototype chain (to allow
46955 	 * inherited finalizers) but should not invoke accessors or proxy object
46956 	 * behavior.  At the moment this lookup will invoke proxy behavior, so
46957 	 * caller must ensure that this function is not called if the target is
46958 	 * a Proxy.
46959 	 */
46960 
46961 	duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_FINALIZER);  /* -> [... obj finalizer] */
46962 	if (!duk_is_callable(ctx, -1)) {
46963 		DUK_DDD(DUK_DDDPRINT("-> no finalizer or finalizer not callable"));
46964 		return 0;
46965 	}
46966 	duk_dup(ctx, -2);
46967 	duk_push_boolean(ctx, DUK_HEAP_HAS_FINALIZER_NORESCUE(thr->heap));
46968 	DUK_DDD(DUK_DDDPRINT("-> finalizer found, calling finalizer"));
46969 	duk_call(ctx, 2);  /* [ ... obj finalizer obj heapDestruct ]  -> [ ... obj retval ] */
46970 	DUK_DDD(DUK_DDDPRINT("finalizer finished successfully"));
46971 	return 0;
46972 
46973 	/* Note: we rely on duk_safe_call() to fix up the stack for the caller,
46974 	 * so we don't need to pop stuff here.  There is no return value;
46975 	 * caller determines rescued status based on object refcount.
46976 	 */
46977 }
46978 
46979 DUK_INTERNAL void duk_hobject_run_finalizer(duk_hthread *thr, duk_hobject *obj) {
46980 	duk_context *ctx = (duk_context *) thr;
46981 	duk_ret_t rc;
46982 #ifdef DUK_USE_ASSERTIONS
46983 	duk_idx_t entry_top;
46984 #endif
46985 
46986 	DUK_DDD(DUK_DDDPRINT("running object finalizer for object: %p", (void *) obj));
46987 
46988 	DUK_ASSERT(thr != NULL);
46989 	DUK_ASSERT(ctx != NULL);
46990 	DUK_ASSERT(obj != NULL);
46991 	DUK_ASSERT_VALSTACK_SPACE(thr, 1);
46992 
46993 #ifdef DUK_USE_ASSERTIONS
46994 	entry_top = duk_get_top(ctx);
46995 #endif
46996 	/*
46997 	 *  Get and call the finalizer.  All of this must be wrapped
46998 	 *  in a protected call, because even getting the finalizer
46999 	 *  may trigger an error (getter may throw one, for instance).
47000 	 */
47001 
47002 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));
47003 	if (DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) obj)) {
47004 		DUK_D(DUK_DPRINT("object already finalized, avoid running finalizer twice: %!O", obj));
47005 		return;
47006 	}
47007 	DUK_HEAPHDR_SET_FINALIZED((duk_heaphdr *) obj);  /* ensure never re-entered until rescue cycle complete */
47008 	if (DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(obj)) {
47009 		/* This shouldn't happen; call sites should avoid looking up
47010 		 * _Finalizer "through" a Proxy, but ignore if we come here
47011 		 * with a Proxy to avoid finalizer re-entry.
47012 		 */
47013 		DUK_D(DUK_DPRINT("object is a proxy, skip finalizer call"));
47014 		return;
47015 	}
47016 
47017 	/* XXX: use a NULL error handler for the finalizer call? */
47018 
47019 	DUK_DDD(DUK_DDDPRINT("-> finalizer found, calling wrapped finalize helper"));
47020 	duk_push_hobject(ctx, obj);  /* this also increases refcount by one */
47021 	rc = duk_safe_call(ctx, duk__finalize_helper, 0 /*nargs*/, 1 /*nrets*/);  /* -> [... obj retval/error] */
47022 	DUK_ASSERT_TOP(ctx, entry_top + 2);  /* duk_safe_call discipline */
47023 
47024 	if (rc != DUK_EXEC_SUCCESS) {
47025 		/* Note: we ask for one return value from duk_safe_call to get this
47026 		 * error debugging here.
47027 		 */
47028 		DUK_D(DUK_DPRINT("wrapped finalizer call failed for object %p (ignored); error: %!T",
47029 		                 (void *) obj, (duk_tval *) duk_get_tval(ctx, -1)));
47030 	}
47031 	duk_pop_2(ctx);  /* -> [...] */
47032 
47033 	DUK_ASSERT_TOP(ctx, entry_top);
47034 }
47035 /*
47036  *  Misc support functions
47037  */
47038 
47039 /* include removed: duk_internal.h */
47040 
47041 DUK_INTERNAL duk_bool_t duk_hobject_prototype_chain_contains(duk_hthread *thr, duk_hobject *h, duk_hobject *p, duk_bool_t ignore_loop) {
47042 	duk_uint_t sanity;
47043 
47044 	DUK_ASSERT(thr != NULL);
47045 
47046 	/* False if the object is NULL or the prototype 'p' is NULL.
47047 	 * In particular, false if both are NULL (don't compare equal).
47048 	 */
47049 	if (h == NULL || p == NULL) {
47050 		return 0;
47051 	}
47052 
47053 	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
47054 	do {
47055 		if (h == p) {
47056 			return 1;
47057 		}
47058 
47059 		if (sanity-- == 0) {
47060 			if (ignore_loop) {
47061 				break;
47062 			} else {
47063 				DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
47064 			}
47065 		}
47066 		h = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
47067 	} while (h);
47068 
47069 	return 0;
47070 }
47071 
47072 DUK_INTERNAL void duk_hobject_set_prototype_updref(duk_hthread *thr, duk_hobject *h, duk_hobject *p) {
47073 #ifdef DUK_USE_REFERENCE_COUNTING
47074 	duk_hobject *tmp;
47075 
47076 	DUK_ASSERT(h);
47077 	tmp = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
47078 	DUK_HOBJECT_SET_PROTOTYPE(thr->heap, h, p);
47079 	DUK_HOBJECT_INCREF_ALLOWNULL(thr, p);  /* avoid problems if p == h->prototype */
47080 	DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);
47081 #else
47082 	DUK_ASSERT(h);
47083 	DUK_UNREF(thr);
47084 	DUK_HOBJECT_SET_PROTOTYPE(thr->heap, h, p);
47085 #endif
47086 }
47087 /*
47088  *  Helpers for creating and querying pc2line debug data, which
47089  *  converts a bytecode program counter to a source line number.
47090  *
47091  *  The run-time pc2line data is bit-packed, and documented in:
47092  *
47093  *    doc/function-objects.rst
47094  */
47095 
47096 /* include removed: duk_internal.h */
47097 
47098 #if defined(DUK_USE_PC2LINE)
47099 
47100 /* Generate pc2line data for an instruction sequence, leaving a buffer on stack top. */
47101 DUK_INTERNAL void duk_hobject_pc2line_pack(duk_hthread *thr, duk_compiler_instr *instrs, duk_uint_fast32_t length) {
47102 	duk_context *ctx = (duk_context *) thr;
47103 	duk_hbuffer_dynamic *h_buf;
47104 	duk_bitencoder_ctx be_ctx_alloc;
47105 	duk_bitencoder_ctx *be_ctx = &be_ctx_alloc;
47106 	duk_uint32_t *hdr;
47107 	duk_size_t new_size;
47108 	duk_uint_fast32_t num_header_entries;
47109 	duk_uint_fast32_t curr_offset;
47110 	duk_int_fast32_t curr_line, next_line, diff_line;
47111 	duk_uint_fast32_t curr_pc;
47112 	duk_uint_fast32_t hdr_index;
47113 
47114 	DUK_ASSERT(length <= DUK_COMPILER_MAX_BYTECODE_LENGTH);
47115 
47116 	/* XXX: add proper spare handling to dynamic buffer, to minimize
47117 	 * reallocs; currently there is no spare at all.
47118 	 */
47119 
47120 	num_header_entries = (length + DUK_PC2LINE_SKIP - 1) / DUK_PC2LINE_SKIP;
47121 	curr_offset = (duk_uint_fast32_t) (sizeof(duk_uint32_t) + num_header_entries * sizeof(duk_uint32_t) * 2);
47122 
47123 	duk_push_dynamic_buffer(ctx, (duk_size_t) curr_offset);
47124 	h_buf = (duk_hbuffer_dynamic *) duk_get_hbuffer(ctx, -1);
47125 	DUK_ASSERT(h_buf != NULL);
47126 	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(h_buf) && !DUK_HBUFFER_HAS_EXTERNAL(h_buf));
47127 
47128 	hdr = (duk_uint32_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h_buf);
47129 	DUK_ASSERT(hdr != NULL);
47130 	hdr[0] = (duk_uint32_t) length;  /* valid pc range is [0, length[ */
47131 
47132 	curr_pc = 0U;
47133 	while (curr_pc < length) {
47134 		new_size = (duk_size_t) (curr_offset + DUK_PC2LINE_MAX_DIFF_LENGTH);
47135 		duk_hbuffer_resize(thr, h_buf, new_size);
47136 
47137 		hdr = (duk_uint32_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h_buf);
47138 		DUK_ASSERT(hdr != NULL);
47139 		DUK_ASSERT(curr_pc < length);
47140 		hdr_index = 1 + (curr_pc / DUK_PC2LINE_SKIP) * 2;
47141 		curr_line = (duk_int_fast32_t) instrs[curr_pc].line;
47142 		hdr[hdr_index + 0] = (duk_uint32_t) curr_line;
47143 		hdr[hdr_index + 1] = (duk_uint32_t) curr_offset;
47144 
47145 #if 0
47146 		DUK_DDD(DUK_DDDPRINT("hdr[%ld]: pc=%ld line=%ld offset=%ld",
47147 		                     (long) (curr_pc / DUK_PC2LINE_SKIP),
47148 		                     (long) curr_pc,
47149 		                     (long) hdr[hdr_index + 0],
47150 		                     (long) hdr[hdr_index + 1]));
47151 #endif
47152 
47153 		DUK_MEMZERO(be_ctx, sizeof(*be_ctx));
47154 		be_ctx->data = ((duk_uint8_t *) hdr) + curr_offset;
47155 		be_ctx->length = (duk_size_t) DUK_PC2LINE_MAX_DIFF_LENGTH;
47156 
47157 		for (;;) {
47158 			curr_pc++;
47159 			if ( ((curr_pc % DUK_PC2LINE_SKIP) == 0) ||  /* end of diff run */
47160 			     (curr_pc >= length) ) {                 /* end of bytecode */
47161 				break;
47162 			}
47163 			DUK_ASSERT(curr_pc < length);
47164 			next_line = (duk_int32_t) instrs[curr_pc].line;
47165 			diff_line = next_line - curr_line;
47166 
47167 #if 0
47168 			DUK_DDD(DUK_DDDPRINT("curr_line=%ld, next_line=%ld -> diff_line=%ld",
47169 			                     (long) curr_line, (long) next_line, (long) diff_line));
47170 #endif
47171 
47172 			if (diff_line == 0) {
47173 				/* 0 */
47174 				duk_be_encode(be_ctx, 0, 1);
47175 			} else if (diff_line >= 1 && diff_line <= 4) {
47176 				/* 1 0 <2 bits> */
47177 				duk_be_encode(be_ctx, (0x02 << 2) + (diff_line - 1), 4);
47178 			} else if (diff_line >= -0x80 && diff_line <= 0x7f) {
47179 				/* 1 1 0 <8 bits> */
47180 				DUK_ASSERT(diff_line + 0x80 >= 0 && diff_line + 0x80 <= 0xff);
47181 				duk_be_encode(be_ctx, (0x06 << 8) + (diff_line + 0x80), 11);
47182 			} else {
47183 				/* 1 1 1 <32 bits>
47184 				 * Encode in two parts to avoid bitencode 24-bit limitation
47185 				 */
47186 				duk_be_encode(be_ctx, (0x07 << 16) + ((next_line >> 16) & 0xffffU), 19);
47187 				duk_be_encode(be_ctx, next_line & 0xffffU, 16);
47188 			}
47189 
47190 			curr_line = next_line;
47191 		}
47192 
47193 		duk_be_finish(be_ctx);
47194 		DUK_ASSERT(!be_ctx->truncated);
47195 
47196 		/* be_ctx->offset == length of encoded bitstream */
47197 		curr_offset += (duk_uint_fast32_t) be_ctx->offset;
47198 	}
47199 
47200 	/* compact */
47201 	new_size = (duk_size_t) curr_offset;
47202 	duk_hbuffer_resize(thr, h_buf, new_size);
47203 
47204 	(void) duk_to_fixed_buffer(ctx, -1, NULL);
47205 
47206 	DUK_DDD(DUK_DDDPRINT("final pc2line data: pc_limit=%ld, length=%ld, %lf bits/opcode --> %!ixT",
47207 	                     (long) length, (long) new_size, (double) new_size * 8.0 / (double) length,
47208 	                     (duk_tval *) duk_get_tval(ctx, -1)));
47209 }
47210 
47211 /* PC is unsigned.  If caller does PC arithmetic and gets a negative result,
47212  * it will map to a large PC which is out of bounds and causes a zero to be
47213  * returned.
47214  */
47215 DUK_LOCAL duk_uint_fast32_t duk__hobject_pc2line_query_raw(duk_hthread *thr, duk_hbuffer_fixed *buf, duk_uint_fast32_t pc) {
47216 	duk_bitdecoder_ctx bd_ctx_alloc;
47217 	duk_bitdecoder_ctx *bd_ctx = &bd_ctx_alloc;
47218 	duk_uint32_t *hdr;
47219 	duk_uint_fast32_t start_offset;
47220 	duk_uint_fast32_t pc_limit;
47221 	duk_uint_fast32_t hdr_index;
47222 	duk_uint_fast32_t pc_base;
47223 	duk_uint_fast32_t n;
47224 	duk_uint_fast32_t curr_line;
47225 
47226 	DUK_ASSERT(buf != NULL);
47227 	DUK_ASSERT(!DUK_HBUFFER_HAS_DYNAMIC((duk_hbuffer *) buf) && !DUK_HBUFFER_HAS_EXTERNAL((duk_hbuffer *) buf));
47228 	DUK_UNREF(thr);
47229 
47230 	/*
47231 	 *  Use the index in the header to find the right starting point
47232 	 */
47233 
47234 	hdr_index = pc / DUK_PC2LINE_SKIP;
47235 	pc_base = hdr_index * DUK_PC2LINE_SKIP;
47236 	n = pc - pc_base;
47237 
47238 	if (DUK_HBUFFER_FIXED_GET_SIZE(buf) <= sizeof(duk_uint32_t)) {
47239 		DUK_DD(DUK_DDPRINT("pc2line lookup failed: buffer is smaller than minimal header"));
47240 		goto error;
47241 	}
47242 
47243 	hdr = (duk_uint32_t *) (void *) DUK_HBUFFER_FIXED_GET_DATA_PTR(thr->heap, buf);
47244 	pc_limit = hdr[0];
47245 	if (pc >= pc_limit) {
47246 		/* Note: pc is unsigned and cannot be negative */
47247 		DUK_DD(DUK_DDPRINT("pc2line lookup failed: pc out of bounds (pc=%ld, limit=%ld)",
47248 		                   (long) pc, (long) pc_limit));
47249 		goto error;
47250 	}
47251 
47252 	curr_line = hdr[1 + hdr_index * 2];
47253 	start_offset = hdr[1 + hdr_index * 2 + 1];
47254 	if ((duk_size_t) start_offset > DUK_HBUFFER_FIXED_GET_SIZE(buf)) {
47255 		DUK_DD(DUK_DDPRINT("pc2line lookup failed: start_offset out of bounds (start_offset=%ld, buffer_size=%ld)",
47256 		                   (long) start_offset, (long) DUK_HBUFFER_GET_SIZE((duk_hbuffer *) buf)));
47257 		goto error;
47258 	}
47259 
47260 	/*
47261 	 *  Iterate the bitstream (line diffs) until PC is reached
47262 	 */
47263 
47264 	DUK_MEMZERO(bd_ctx, sizeof(*bd_ctx));
47265 	bd_ctx->data = ((duk_uint8_t *) hdr) + start_offset;
47266 	bd_ctx->length = (duk_size_t) (DUK_HBUFFER_FIXED_GET_SIZE(buf) - start_offset);
47267 
47268 #if 0
47269 	DUK_DDD(DUK_DDDPRINT("pc2line lookup: pc=%ld -> hdr_index=%ld, pc_base=%ld, n=%ld, start_offset=%ld",
47270 	                     (long) pc, (long) hdr_index, (long) pc_base, (long) n, (long) start_offset));
47271 #endif
47272 
47273 	while (n > 0) {
47274 #if 0
47275 		DUK_DDD(DUK_DDDPRINT("lookup: n=%ld, curr_line=%ld", (long) n, (long) curr_line));
47276 #endif
47277 
47278 		if (duk_bd_decode_flag(bd_ctx)) {
47279 			if (duk_bd_decode_flag(bd_ctx)) {
47280 				if (duk_bd_decode_flag(bd_ctx)) {
47281 					/* 1 1 1 <32 bits> */
47282 					duk_uint_fast32_t t;
47283 					t = duk_bd_decode(bd_ctx, 16);  /* workaround: max nbits = 24 now */
47284 					t = (t << 16) + duk_bd_decode(bd_ctx, 16);
47285 					curr_line = t;
47286 				} else {
47287 					/* 1 1 0 <8 bits> */
47288 					duk_uint_fast32_t t;
47289 					t = duk_bd_decode(bd_ctx, 8);
47290 					curr_line = curr_line + t - 0x80;
47291 				}
47292 			} else {
47293 				/* 1 0 <2 bits> */
47294 				duk_uint_fast32_t t;
47295 				t = duk_bd_decode(bd_ctx, 2);
47296 				curr_line = curr_line + t + 1;
47297 			}
47298 		} else {
47299 			/* 0: no change */
47300 		}
47301 
47302 		n--;
47303 	}
47304 
47305 	DUK_DDD(DUK_DDDPRINT("pc2line lookup result: pc %ld -> line %ld", (long) pc, (long) curr_line));
47306 	return curr_line;
47307 
47308  error:
47309 	DUK_D(DUK_DPRINT("pc2line conversion failed for pc=%ld", (long) pc));
47310 	return 0;
47311 }
47312 
47313 DUK_INTERNAL duk_uint_fast32_t duk_hobject_pc2line_query(duk_context *ctx, duk_idx_t idx_func, duk_uint_fast32_t pc) {
47314 	duk_hbuffer_fixed *pc2line;
47315 	duk_uint_fast32_t line;
47316 
47317 	/* XXX: now that pc2line is used by the debugger quite heavily in
47318 	 * checked execution, this should be optimized to avoid value stack
47319 	 * and perhaps also implement some form of pc2line caching (see
47320 	 * future work in debugger.rst).
47321 	 */
47322 
47323 	duk_get_prop_stridx(ctx, idx_func, DUK_STRIDX_INT_PC2LINE);
47324 	pc2line = (duk_hbuffer_fixed *) duk_get_hbuffer(ctx, -1);
47325 	if (pc2line != NULL) {
47326 		DUK_ASSERT(!DUK_HBUFFER_HAS_DYNAMIC((duk_hbuffer *) pc2line) && !DUK_HBUFFER_HAS_EXTERNAL((duk_hbuffer *) pc2line));
47327 		line = duk__hobject_pc2line_query_raw((duk_hthread *) ctx, pc2line, (duk_uint_fast32_t) pc);
47328 	} else {
47329 		line = 0;
47330 	}
47331 	duk_pop(ctx);
47332 
47333 	return line;
47334 }
47335 
47336 #endif  /* DUK_USE_PC2LINE */
47337 /*
47338  *  Hobject property set/get functionality.
47339  *
47340  *  This is very central functionality for size, performance, and compliance.
47341  *  It is also rather intricate; see hobject-algorithms.rst for discussion on
47342  *  the algorithms and memory-management.rst for discussion on refcounts and
47343  *  side effect issues.
47344  *
47345  *  Notes:
47346  *
47347  *    - It might be tempting to assert "refcount nonzero" for objects
47348  *      being operated on, but that's not always correct: objects with
47349  *      a zero refcount may be operated on by the refcount implementation
47350  *      (finalization) for instance.  Hence, no refcount assertions are made.
47351  *
47352  *    - Many operations (memory allocation, identifier operations, etc)
47353  *      may cause arbitrary side effects (e.g. through GC and finalization).
47354  *      These side effects may invalidate duk_tval pointers which point to
47355  *      areas subject to reallocation (like value stack).  Heap objects
47356  *      themselves have stable pointers.  Holding heap object pointers or
47357  *      duk_tval copies is not problematic with respect to side effects;
47358  *      care must be taken when holding and using argument duk_tval pointers.
47359  *
47360  *    - If a finalizer is executed, it may operate on the the same object
47361  *      we're currently dealing with.  For instance, the finalizer might
47362  *      delete a certain property which has already been looked up and
47363  *      confirmed to exist.  Ideally finalizers would be disabled if GC
47364  *      happens during property access.  At the moment property table realloc
47365  *      disables finalizers, and all DECREFs may cause arbitrary changes so
47366  *      handle DECREF carefully.
47367  *
47368  *    - The order of operations for a DECREF matters.  When DECREF is executed,
47369  *      the entire object graph must be consistent; note that a refzero may
47370  *      lead to a mark-and-sweep through a refcount finalizer.
47371  */
47372 
47373 /*
47374  *  XXX: array indices are mostly typed as duk_uint32_t here; duk_uarridx_t
47375  *  might be more appropriate.
47376  */
47377 
47378 /*
47379  *  XXX: duk_uint_fast32_t should probably be used in many places here.
47380  */
47381 
47382 /* include removed: duk_internal.h */
47383 
47384 /*
47385  *  Local defines
47386  */
47387 
47388 #define DUK__NO_ARRAY_INDEX             DUK_HSTRING_NO_ARRAY_INDEX
47389 
47390 /* hash probe sequence */
47391 #define DUK__HASH_INITIAL(hash,h_size)  DUK_HOBJECT_HASH_INITIAL((hash),(h_size))
47392 #define DUK__HASH_PROBE_STEP(hash)      DUK_HOBJECT_HASH_PROBE_STEP((hash))
47393 
47394 /* marker values for hash part */
47395 #define DUK__HASH_UNUSED                DUK_HOBJECT_HASHIDX_UNUSED
47396 #define DUK__HASH_DELETED               DUK_HOBJECT_HASHIDX_DELETED
47397 
47398 /* valstack space that suffices for all local calls, including recursion
47399  * of other than Duktape calls (getters etc)
47400  */
47401 #define DUK__VALSTACK_SPACE             10
47402 
47403 /* valstack space allocated especially for proxy lookup which does a
47404  * recursive property lookup
47405  */
47406 #define DUK__VALSTACK_PROXY_LOOKUP      20
47407 
47408 /*
47409  *  Local prototypes
47410  */
47411 
47412 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);
47413 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);
47414 DUK_LOCAL_DECL void duk__check_arguments_map_for_delete(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *temp_desc);
47415 
47416 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);
47417 DUK_LOCAL_DECL duk_bool_t duk__handle_put_array_length(duk_hthread *thr, duk_hobject *obj);
47418 
47419 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);
47420 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);
47421 DUK_LOCAL duk_uint32_t duk__get_old_array_length(duk_hthread *thr, duk_hobject *obj, duk_propdesc *temp_desc);
47422 
47423 /*
47424  *  Misc helpers
47425  */
47426 
47427 /* Convert a duk_tval number (caller checks) to a 32-bit index.  Returns
47428  * DUK__NO_ARRAY_INDEX if the number is not whole or not a valid array
47429  * index.
47430  */
47431 /* XXX: for fastints, could use a variant which assumes a double duk_tval
47432  * (and doesn't need to check for fastint again).
47433  */
47434 DUK_LOCAL duk_uint32_t duk__tval_number_to_arr_idx(duk_tval *tv) {
47435 	duk_double_t dbl;
47436 	duk_uint32_t idx;
47437 
47438 	DUK_ASSERT(tv != NULL);
47439 	DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
47440 
47441 	/* -0 is accepted here as index 0 because ToString(-0) == "0" which is
47442 	 * in canonical form and thus an array index.
47443 	 */
47444 	dbl = DUK_TVAL_GET_NUMBER(tv);
47445 	idx = (duk_uint32_t) dbl;
47446 	if ((duk_double_t) idx == dbl) {
47447 	        /* Is whole and within 32 bit range.  If the value happens to be 0xFFFFFFFF,
47448 		 * it's not a valid array index but will then match DUK__NO_ARRAY_INDEX.
47449 		 */
47450 		return idx;
47451 	}
47452 	return DUK__NO_ARRAY_INDEX;
47453 }
47454 
47455 #if defined(DUK_USE_FASTINT)
47456 /* Convert a duk_tval fastint (caller checks) to a 32-bit index. */
47457 DUK_LOCAL duk_uint32_t duk__tval_fastint_to_arr_idx(duk_tval *tv) {
47458 	duk_int64_t t;
47459 
47460 	DUK_ASSERT(tv != NULL);
47461 	DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv));
47462 
47463 	t = DUK_TVAL_GET_FASTINT(tv);
47464 	if ((t & ~0xffffffffULL) != 0) {
47465 		/* Catches >0x100000000 and negative values. */
47466 		return DUK__NO_ARRAY_INDEX;
47467 	}
47468 
47469 	/* If the value happens to be 0xFFFFFFFF, it's not a valid array index
47470 	 * but will then match DUK__NO_ARRAY_INDEX.
47471 	 */
47472 	return (duk_uint32_t) t;
47473 }
47474 #endif  /* DUK_USE_FASTINT */
47475 
47476 /* Push an arbitrary duk_tval to the stack, coerce it to string, and return
47477  * both a duk_hstring pointer and an array index (or DUK__NO_ARRAY_INDEX).
47478  */
47479 DUK_LOCAL duk_uint32_t duk__push_tval_to_hstring_arr_idx(duk_context *ctx, duk_tval *tv, duk_hstring **out_h) {
47480 	duk_uint32_t arr_idx;
47481 	duk_hstring *h;
47482 
47483 	DUK_ASSERT(ctx != NULL);
47484 	DUK_ASSERT(tv != NULL);
47485 	DUK_ASSERT(out_h != NULL);
47486 
47487 	duk_push_tval(ctx, tv);
47488 	duk_to_string(ctx, -1);
47489 	h = duk_get_hstring(ctx, -1);
47490 	DUK_ASSERT(h != NULL);
47491 	*out_h = h;
47492 
47493 	arr_idx = DUK_HSTRING_GET_ARRIDX_FAST(h);
47494 	return arr_idx;
47495 }
47496 
47497 /* String is an own (virtual) property of a lightfunc. */
47498 DUK_LOCAL duk_bool_t duk__key_is_lightfunc_ownprop(duk_hthread *thr, duk_hstring *key) {
47499 	DUK_UNREF(thr);
47500 	return (key == DUK_HTHREAD_STRING_LENGTH(thr) ||
47501 	        key == DUK_HTHREAD_STRING_NAME(thr));
47502 }
47503 
47504 /*
47505  *  Helpers for managing property storage size
47506  */
47507 
47508 /* Get default hash part size for a certain entry part size. */
47509 #if defined(DUK_USE_HOBJECT_HASH_PART)
47510 DUK_LOCAL duk_uint32_t duk__get_default_h_size(duk_uint32_t e_size) {
47511 	DUK_ASSERT(e_size <= DUK_HOBJECT_MAX_PROPERTIES);
47512 
47513 	if (e_size >= DUK_HOBJECT_E_USE_HASH_LIMIT) {
47514 		duk_uint32_t res;
47515 
47516 		/* result: hash_prime(floor(1.2 * e_size)) */
47517 		res = duk_util_get_hash_prime(e_size + e_size / DUK_HOBJECT_H_SIZE_DIVISOR);
47518 
47519 		/* if fails, e_size will be zero = not an issue, except performance-wise */
47520 		DUK_ASSERT(res == 0 || res > e_size);
47521 		return res;
47522 	} else {
47523 		return 0;
47524 	}
47525 }
47526 #endif  /* USE_PROP_HASH_PART */
47527 
47528 /* Get minimum entry part growth for a certain size. */
47529 DUK_LOCAL duk_uint32_t duk__get_min_grow_e(duk_uint32_t e_size) {
47530 	duk_uint32_t res;
47531 
47532 	DUK_ASSERT(e_size <= DUK_HOBJECT_MAX_PROPERTIES);
47533 
47534 	res = (e_size + DUK_HOBJECT_E_MIN_GROW_ADD) / DUK_HOBJECT_E_MIN_GROW_DIVISOR;
47535 	DUK_ASSERT(res >= 1);  /* important for callers */
47536 	return res;
47537 }
47538 
47539 /* Get minimum array part growth for a certain size. */
47540 DUK_LOCAL duk_uint32_t duk__get_min_grow_a(duk_uint32_t a_size) {
47541 	duk_uint32_t res;
47542 
47543 	DUK_ASSERT((duk_size_t) a_size <= DUK_HOBJECT_MAX_PROPERTIES);
47544 
47545 	res = (a_size + DUK_HOBJECT_A_MIN_GROW_ADD) / DUK_HOBJECT_A_MIN_GROW_DIVISOR;
47546 	DUK_ASSERT(res >= 1);  /* important for callers */
47547 	return res;
47548 }
47549 
47550 /* Count actually used entry part entries (non-NULL keys). */
47551 DUK_LOCAL duk_uint32_t duk__count_used_e_keys(duk_hthread *thr, duk_hobject *obj) {
47552 	duk_uint_fast32_t i;
47553 	duk_uint_fast32_t n = 0;
47554 	duk_hstring **e;
47555 
47556 	DUK_ASSERT(obj != NULL);
47557 	DUK_UNREF(thr);
47558 
47559 	e = DUK_HOBJECT_E_GET_KEY_BASE(thr->heap, obj);
47560 	for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
47561 		if (*e++) {
47562 			n++;
47563 		}
47564 	}
47565 	return (duk_uint32_t) n;
47566 }
47567 
47568 /* Count actually used array part entries and array minimum size.
47569  * NOTE: 'out_min_size' can be computed much faster by starting from the
47570  * end and breaking out early when finding first used entry, but this is
47571  * not needed now.
47572  */
47573 DUK_LOCAL void duk__compute_a_stats(duk_hthread *thr, duk_hobject *obj, duk_uint32_t *out_used, duk_uint32_t *out_min_size) {
47574 	duk_uint_fast32_t i;
47575 	duk_uint_fast32_t used = 0;
47576 	duk_uint_fast32_t highest_idx = (duk_uint_fast32_t) -1;  /* see below */
47577 	duk_tval *a;
47578 
47579 	DUK_ASSERT(obj != NULL);
47580 	DUK_ASSERT(out_used != NULL);
47581 	DUK_ASSERT(out_min_size != NULL);
47582 	DUK_UNREF(thr);
47583 
47584 	a = DUK_HOBJECT_A_GET_BASE(thr->heap, obj);
47585 	for (i = 0; i < DUK_HOBJECT_GET_ASIZE(obj); i++) {
47586 		duk_tval *tv = a++;
47587 		if (!DUK_TVAL_IS_UNUSED(tv)) {
47588 			used++;
47589 			highest_idx = i;
47590 		}
47591 	}
47592 
47593 	/* Initial value for highest_idx is -1 coerced to unsigned.  This
47594 	 * is a bit odd, but (highest_idx + 1) will then wrap to 0 below
47595 	 * for out_min_size as intended.
47596 	 */
47597 
47598 	*out_used = used;
47599 	*out_min_size = highest_idx + 1;  /* 0 if no used entries */
47600 }
47601 
47602 /* Check array density and indicate whether or not the array part should be abandoned. */
47603 DUK_LOCAL duk_bool_t duk__abandon_array_density_check(duk_uint32_t a_used, duk_uint32_t a_size) {
47604 	/*
47605 	 *  Array abandon check; abandon if:
47606 	 *
47607 	 *    new_used / new_size < limit
47608 	 *    new_used < limit * new_size        || limit is 3 bits fixed point
47609 	 *    new_used < limit' / 8 * new_size   || *8
47610 	 *    8*new_used < limit' * new_size     || :8
47611 	 *    new_used < limit' * (new_size / 8)
47612 	 *
47613 	 *  Here, new_used = a_used, new_size = a_size.
47614 	 *
47615 	 *  Note: some callers use approximate values for a_used and/or a_size
47616 	 *  (e.g. dropping a '+1' term).  This doesn't affect the usefulness
47617 	 *  of the check, but may confuse debugging.
47618 	 */
47619 
47620 	return (a_used < DUK_HOBJECT_A_ABANDON_LIMIT * (a_size >> 3));
47621 }
47622 
47623 /* Fast check for extending array: check whether or not a slow density check is required. */
47624 DUK_LOCAL duk_bool_t duk__abandon_array_slow_check_required(duk_uint32_t arr_idx, duk_uint32_t old_size) {
47625 	/*
47626 	 *  In a fast check we assume old_size equals old_used (i.e., existing
47627 	 *  array is fully dense).
47628 	 *
47629 	 *  Slow check if:
47630 	 *
47631 	 *    (new_size - old_size) / old_size > limit
47632 	 *    new_size - old_size > limit * old_size
47633 	 *    new_size > (1 + limit) * old_size        || limit' is 3 bits fixed point
47634 	 *    new_size > (1 + (limit' / 8)) * old_size || * 8
47635 	 *    8 * new_size > (8 + limit') * old_size   || : 8
47636 	 *    new_size > (8 + limit') * (old_size / 8)
47637 	 *    new_size > limit'' * (old_size / 8)      || limit'' = 9 -> max 25% increase
47638 	 *    arr_idx + 1 > limit'' * (old_size / 8)
47639 	 *
47640 	 *  This check doesn't work well for small values, so old_size is rounded
47641 	 *  up for the check (and the '+ 1' of arr_idx can be ignored in practice):
47642 	 *
47643 	 *    arr_idx > limit'' * ((old_size + 7) / 8)
47644 	 */
47645 
47646 	return (arr_idx > DUK_HOBJECT_A_FAST_RESIZE_LIMIT * ((old_size + 7) >> 3));
47647 }
47648 
47649 /*
47650  *  Proxy helpers
47651  */
47652 
47653 #if defined(DUK_USE_ES6_PROXY)
47654 DUK_INTERNAL duk_bool_t duk_hobject_proxy_check(duk_hthread *thr, duk_hobject *obj, duk_hobject **out_target, duk_hobject **out_handler) {
47655 	duk_tval *tv_target;
47656 	duk_tval *tv_handler;
47657 	duk_hobject *h_target;
47658 	duk_hobject *h_handler;
47659 
47660 	DUK_ASSERT(thr != NULL);
47661 	DUK_ASSERT(obj != NULL);
47662 	DUK_ASSERT(out_target != NULL);
47663 	DUK_ASSERT(out_handler != NULL);
47664 
47665 	/* Caller doesn't need to check exotic proxy behavior (but does so for
47666 	 * some fast paths).
47667 	 */
47668 	if (DUK_LIKELY(!DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(obj))) {
47669 		return 0;
47670 	}
47671 
47672 	tv_handler = duk_hobject_find_existing_entry_tval_ptr(thr->heap, obj, DUK_HTHREAD_STRING_INT_HANDLER(thr));
47673 	if (!tv_handler) {
47674 		DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REVOKED);
47675 		return 0;
47676 	}
47677 	DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv_handler));
47678 	h_handler = DUK_TVAL_GET_OBJECT(tv_handler);
47679 	DUK_ASSERT(h_handler != NULL);
47680 	*out_handler = h_handler;
47681 	tv_handler = NULL;  /* avoid issues with relocation */
47682 
47683 	tv_target = duk_hobject_find_existing_entry_tval_ptr(thr->heap, obj, DUK_HTHREAD_STRING_INT_TARGET(thr));
47684 	if (!tv_target) {
47685 		DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REVOKED);
47686 		return 0;
47687 	}
47688 	DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv_target));
47689 	h_target = DUK_TVAL_GET_OBJECT(tv_target);
47690 	DUK_ASSERT(h_target != NULL);
47691 	*out_target = h_target;
47692 	tv_target = NULL;  /* avoid issues with relocation */
47693 
47694 	return 1;
47695 }
47696 #endif  /* DUK_USE_ES6_PROXY */
47697 
47698 /* Get Proxy target object.  If the argument is not a Proxy, return it as is.
47699  * If a Proxy is revoked, an error is thrown.
47700  */
47701 #if defined(DUK_USE_ES6_PROXY)
47702 DUK_INTERNAL duk_hobject *duk_hobject_resolve_proxy_target(duk_hthread *thr, duk_hobject *obj) {
47703 	duk_hobject *h_target;
47704 	duk_hobject *h_handler;
47705 
47706 	DUK_ASSERT(thr != NULL);
47707 	DUK_ASSERT(obj != NULL);
47708 
47709 	/* Resolve Proxy targets until Proxy chain ends.  No explicit check for
47710 	 * a Proxy loop: user code cannot create such a loop without tweaking
47711 	 * internal properties directly.
47712 	 */
47713 
47714 	while (DUK_UNLIKELY(DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(obj))) {
47715 		if (duk_hobject_proxy_check(thr, obj, &h_target, &h_handler)) {
47716 			DUK_ASSERT(h_target != NULL);
47717 			obj = h_target;
47718 		} else {
47719 			break;
47720 		}
47721 	}
47722 
47723 	DUK_ASSERT(obj != NULL);
47724 	return obj;
47725 }
47726 #endif  /* DUK_USE_ES6_PROXY */
47727 
47728 #if defined(DUK_USE_ES6_PROXY)
47729 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) {
47730 	duk_context *ctx = (duk_context *) thr;
47731 	duk_hobject *h_handler;
47732 
47733 	DUK_ASSERT(thr != NULL);
47734 	DUK_ASSERT(obj != NULL);
47735 	DUK_ASSERT(tv_key != NULL);
47736 	DUK_ASSERT(out_target != NULL);
47737 
47738 	if (!duk_hobject_proxy_check(thr, obj, out_target, &h_handler)) {
47739 		return 0;
47740 	}
47741 	DUK_ASSERT(*out_target != NULL);
47742 	DUK_ASSERT(h_handler != NULL);
47743 
47744 	/* XXX: At the moment Duktape accesses internal keys like _Finalizer using a
47745 	 * normal property set/get which would allow a proxy handler to interfere with
47746 	 * such behavior and to get access to internal key strings.  This is not a problem
47747 	 * as such because internal key strings can be created in other ways too (e.g.
47748 	 * through buffers).  The best fix is to change Duktape internal lookups to
47749 	 * skip proxy behavior.  Until that, internal property accesses bypass the
47750 	 * proxy and are applied to the target (as if the handler did not exist).
47751 	 * This has some side effects, see test-bi-proxy-internal-keys.js.
47752 	 */
47753 
47754 	if (DUK_TVAL_IS_STRING(tv_key)) {
47755 		duk_hstring *h_key = (duk_hstring *) DUK_TVAL_GET_STRING(tv_key);
47756 		DUK_ASSERT(h_key != NULL);
47757 		if (DUK_HSTRING_HAS_INTERNAL(h_key)) {
47758 			DUK_DDD(DUK_DDDPRINT("internal key, skip proxy handler and apply to target"));
47759 			return 0;
47760 		}
47761 	}
47762 
47763 	/* The handler is looked up with a normal property lookup; it may be an
47764 	 * accessor or the handler object itself may be a proxy object.  If the
47765 	 * handler is a proxy, we need to extend the valstack as we make a
47766 	 * recursive proxy check without a function call in between (in fact
47767 	 * there is no limit to the potential recursion here).
47768 	 *
47769 	 * (For sanity, proxy creation rejects another proxy object as either
47770 	 * the handler or the target at the moment so recursive proxy cases
47771 	 * are not realized now.)
47772 	 */
47773 
47774 	/* XXX: C recursion limit if proxies are allowed as handler/target values */
47775 
47776 	duk_require_stack(ctx, DUK__VALSTACK_PROXY_LOOKUP);
47777 	duk_push_hobject(ctx, h_handler);
47778 	if (duk_get_prop_stridx(ctx, -1, stridx_trap)) {
47779 		/* -> [ ... handler trap ] */
47780 		duk_insert(ctx, -2);  /* -> [ ... trap handler ] */
47781 
47782 		/* stack prepped for func call: [ ... trap handler ] */
47783 		return 1;
47784 	} else {
47785 		duk_pop_2(ctx);
47786 		return 0;
47787 	}
47788 }
47789 #endif  /* DUK_USE_ES6_PROXY */
47790 
47791 /*
47792  *  Reallocate property allocation, moving properties to the new allocation.
47793  *
47794  *  Includes key compaction, rehashing, and can also optionally abandoning
47795  *  the array part, 'migrating' array entries into the beginning of the
47796  *  new entry part.  Arguments are not validated here, so e.g. new_h_size
47797  *  MUST be a valid prime.
47798  *
47799  *  There is no support for in-place reallocation or just compacting keys
47800  *  without resizing the property allocation.  This is intentional to keep
47801  *  code size minimal.
47802  *
47803  *  The implementation is relatively straightforward, except for the array
47804  *  abandonment process.  Array abandonment requires that new string keys
47805  *  are interned, which may trigger GC.  All keys interned so far must be
47806  *  reachable for GC at all times; valstack is used for that now.
47807  *
47808  *  Also, a GC triggered during this reallocation process must not interfere
47809  *  with the object being resized.  This is currently controlled by using
47810  *  heap->mark_and_sweep_base_flags to indicate that no finalizers will be
47811  *  executed (as they can affect ANY object) and no objects are compacted
47812  *  (it would suffice to protect this particular object only, though).
47813  *
47814  *  Note: a non-checked variant would be nice but is a bit tricky to
47815  *  implement for the array abandonment process.  It's easy for
47816  *  everything else.
47817  *
47818  *  Note: because we need to potentially resize the valstack (as part
47819  *  of abandoning the array part), any tval pointers to the valstack
47820  *  will become invalid after this call.
47821  */
47822 
47823 DUK_LOCAL
47824 void duk__realloc_props(duk_hthread *thr,
47825                         duk_hobject *obj,
47826                         duk_uint32_t new_e_size,
47827                         duk_uint32_t new_a_size,
47828                         duk_uint32_t new_h_size,
47829                         duk_bool_t abandon_array) {
47830 	duk_context *ctx = (duk_context *) thr;
47831 #ifdef DUK_USE_MARK_AND_SWEEP
47832 	duk_small_uint_t prev_mark_and_sweep_base_flags;
47833 #endif
47834 	duk_uint32_t new_alloc_size;
47835 	duk_uint32_t new_e_size_adjusted;
47836 	duk_uint8_t *new_p;
47837 	duk_hstring **new_e_k;
47838 	duk_propvalue *new_e_pv;
47839 	duk_uint8_t *new_e_f;
47840 	duk_tval *new_a;
47841 	duk_uint32_t *new_h;
47842 	duk_uint32_t new_e_next;
47843 	duk_uint_fast32_t i;
47844 
47845 	DUK_ASSERT(thr != NULL);
47846 	DUK_ASSERT(ctx != NULL);
47847 	DUK_ASSERT(obj != NULL);
47848 	DUK_ASSERT(!abandon_array || new_a_size == 0);  /* if abandon_array, new_a_size must be 0 */
47849 	DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL || (DUK_HOBJECT_GET_ESIZE(obj) == 0 && DUK_HOBJECT_GET_ASIZE(obj) == 0));
47850 	DUK_ASSERT(new_h_size == 0 || new_h_size >= new_e_size);  /* required to guarantee success of rehashing,
47851 	                                                           * intentionally use unadjusted new_e_size
47852 	                                                           */
47853 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));
47854 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
47855 
47856 	/*
47857 	 *  Pre resize assertions.
47858 	 */
47859 
47860 #ifdef DUK_USE_ASSERTIONS
47861 	/* XXX: pre-checks (such as no duplicate keys) */
47862 #endif
47863 
47864 	/*
47865 	 *  For property layout 1, tweak e_size to ensure that the whole entry
47866 	 *  part (key + val + flags) is a suitable multiple for alignment
47867 	 *  (platform specific).
47868 	 *
47869 	 *  Property layout 2 does not require this tweaking and is preferred
47870 	 *  on low RAM platforms requiring alignment.
47871 	 */
47872 
47873 #if defined(DUK_USE_HOBJECT_LAYOUT_2) || defined(DUK_USE_HOBJECT_LAYOUT_3)
47874 	DUK_DDD(DUK_DDDPRINT("using layout 2 or 3, no need to pad e_size: %ld", (long) new_e_size));
47875 	new_e_size_adjusted = new_e_size;
47876 #elif defined(DUK_USE_HOBJECT_LAYOUT_1) && (DUK_HOBJECT_ALIGN_TARGET == 1)
47877 	DUK_DDD(DUK_DDDPRINT("using layout 1, but no need to pad e_size: %ld", (long) new_e_size));
47878 	new_e_size_adjusted = new_e_size;
47879 #elif defined(DUK_USE_HOBJECT_LAYOUT_1) && ((DUK_HOBJECT_ALIGN_TARGET == 4) || (DUK_HOBJECT_ALIGN_TARGET == 8))
47880 	new_e_size_adjusted = (new_e_size + DUK_HOBJECT_ALIGN_TARGET - 1) & (~(DUK_HOBJECT_ALIGN_TARGET - 1));
47881 	DUK_DDD(DUK_DDDPRINT("using layout 1, and alignment target is %ld, adjusted e_size: %ld -> %ld",
47882 	                     (long) DUK_HOBJECT_ALIGN_TARGET, (long) new_e_size, (long) new_e_size_adjusted));
47883 	DUK_ASSERT(new_e_size_adjusted >= new_e_size);
47884 #else
47885 #error invalid hobject layout defines
47886 #endif
47887 
47888 	/*
47889 	 *  Debug logging after adjustment.
47890 	 */
47891 
47892 	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 "
47893 	                     "{e_size=%ld,a_size=%ld,h_size=%ld}, abandon_array=%ld, unadjusted new_e_size=%ld",
47894 	                     (void *) obj,
47895 	                     (long) DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE(obj),
47896 	                                                       DUK_HOBJECT_GET_ASIZE(obj),
47897 	                                                       DUK_HOBJECT_GET_HSIZE(obj)),
47898 	                     (long) DUK_HOBJECT_P_COMPUTE_SIZE(new_e_size_adjusted, new_a_size, new_h_size),
47899 	                     (void *) DUK_HOBJECT_GET_PROPS(thr->heap, obj),
47900 	                     (long) DUK_HOBJECT_GET_ESIZE(obj),
47901 	                     (long) DUK_HOBJECT_GET_ENEXT(obj),
47902 	                     (long) DUK_HOBJECT_GET_ASIZE(obj),
47903 	                     (long) DUK_HOBJECT_GET_HSIZE(obj),
47904 	                     (long) new_e_size_adjusted,
47905 	                     (long) new_a_size,
47906 	                     (long) new_h_size,
47907 	                     (long) abandon_array,
47908 	                     (long) new_e_size));
47909 
47910 	/*
47911 	 *  Property count check.  This is the only point where we ensure that
47912 	 *  we don't get more (allocated) property space that we can handle.
47913 	 *  There aren't hard limits as such, but some algorithms fail (e.g.
47914 	 *  finding next higher prime, selecting hash part size) if we get too
47915 	 *  close to the 4G property limit.
47916 	 *
47917 	 *  Since this works based on allocation size (not actually used size),
47918 	 *  the limit is a bit approximate but good enough in practice.
47919 	 */
47920 
47921 	if (new_e_size_adjusted + new_a_size > DUK_HOBJECT_MAX_PROPERTIES) {
47922 		DUK_ERROR_ALLOC_DEFMSG(thr);
47923 	}
47924 
47925 	/*
47926 	 *  Compute new alloc size and alloc new area.
47927 	 *
47928 	 *  The new area is allocated as a dynamic buffer and placed into the
47929 	 *  valstack for reachability.  The actual buffer is then detached at
47930 	 *  the end.
47931 	 *
47932 	 *  Note: heap_mark_and_sweep_base_flags are altered here to ensure
47933 	 *  no-one touches this object while we're resizing and rehashing it.
47934 	 *  The flags must be reset on every exit path after it.  Finalizers
47935 	 *  and compaction is prevented currently for all objects while it
47936 	 *  would be enough to restrict it only for the current object.
47937 	 */
47938 
47939 #ifdef DUK_USE_MARK_AND_SWEEP
47940 	prev_mark_and_sweep_base_flags = thr->heap->mark_and_sweep_base_flags;
47941 	thr->heap->mark_and_sweep_base_flags |=
47942 	        DUK_MS_FLAG_NO_FINALIZERS |         /* avoid attempts to add/remove object keys */
47943 	        DUK_MS_FLAG_NO_OBJECT_COMPACTION;   /* avoid attempt to compact the current object */
47944 #endif
47945 
47946 	new_alloc_size = DUK_HOBJECT_P_COMPUTE_SIZE(new_e_size_adjusted, new_a_size, new_h_size);
47947 	DUK_DDD(DUK_DDDPRINT("new hobject allocation size is %ld", (long) new_alloc_size));
47948 	new_e_next = 0;
47949 	new_e_k = NULL;
47950 	if (new_alloc_size == 0) {
47951 		/* for zero size, don't push anything on valstack */
47952 		DUK_ASSERT(new_e_size_adjusted == 0);
47953 		DUK_ASSERT(new_a_size == 0);
47954 		DUK_ASSERT(new_h_size == 0);
47955 		new_p = NULL;
47956 	} else {
47957 		/* This may trigger mark-and-sweep with arbitrary side effects,
47958 		 * including an attempted resize of the object we're resizing,
47959 		 * executing a finalizer which may add or remove properties of
47960 		 * the object we're resizing etc.
47961 		 */
47962 
47963 #if 0  /* XXX: inject test */
47964 		if (1) {
47965 			goto alloc_failed;
47966 		}
47967 #endif
47968 		new_p = (duk_uint8_t *) DUK_ALLOC(thr->heap, new_alloc_size);
47969 		if (new_p == NULL) {
47970 			/* NULL always indicates alloc failure because
47971 			 * new_alloc_size > 0.
47972 			 */
47973 			goto alloc_failed;
47974 		}
47975 	}
47976 
47977 	/* Set up pointers to the new property area: this is hidden behind a macro
47978 	 * because it is memory layout specific.
47979 	 */
47980 	DUK_HOBJECT_P_SET_REALLOC_PTRS(new_p, new_e_k, new_e_pv, new_e_f, new_a, new_h,
47981 	                               new_e_size_adjusted, new_a_size, new_h_size);
47982 	DUK_UNREF(new_h);  /* happens when hash part dropped */
47983 
47984 	/* if new_p == NULL, all of these pointers are NULL */
47985 	DUK_ASSERT((new_p != NULL) ||
47986 	           (new_e_k == NULL && new_e_pv == NULL && new_e_f == NULL &&
47987 	            new_a == NULL && new_h == NULL));
47988 
47989 	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",
47990 	                     (long) new_alloc_size, (void *) new_e_k, (void *) new_e_pv, (void *) new_e_f,
47991 	                     (void *) new_a, (void *) new_h));
47992 
47993 	/*
47994 	 *  Migrate array to start of entries if requested.
47995 	 *
47996 	 *  Note: from an enumeration perspective the order of entry keys matters.
47997 	 *  Array keys should appear wherever they appeared before the array abandon
47998 	 *  operation.
47999 	 */
48000 
48001 	if (abandon_array) {
48002 		/*
48003 		 *  Note: assuming new_a_size == 0, and that entry part contains
48004 		 *  no conflicting keys, refcounts do not need to be adjusted for
48005 		 *  the values, as they remain exactly the same.
48006 		 *
48007 		 *  The keys, however, need to be interned, incref'd, and be
48008 		 *  reachable for GC.  Any intern attempt may trigger a GC and
48009 		 *  claim any non-reachable strings, so every key must be reachable
48010 		 *  at all times.
48011 		 *
48012 		 *  A longjmp must not occur here, as the new_p allocation would
48013 		 *  be freed without these keys being decref'd, hence the messy
48014 		 *  decref handling if intern fails.
48015 		 */
48016 		DUK_ASSERT(new_a_size == 0);
48017 
48018 		for (i = 0; i < DUK_HOBJECT_GET_ASIZE(obj); i++) {
48019 			duk_tval *tv1;
48020 			duk_tval *tv2;
48021 			duk_hstring *key;
48022 
48023 			DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL);
48024 
48025 			tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, i);
48026 			if (DUK_TVAL_IS_UNUSED(tv1)) {
48027 				continue;
48028 			}
48029 
48030 			DUK_ASSERT(new_p != NULL && new_e_k != NULL &&
48031 			           new_e_pv != NULL && new_e_f != NULL);
48032 
48033 			/*
48034 			 *  Intern key via the valstack to ensure reachability behaves
48035 			 *  properly.  We must avoid longjmp's here so use non-checked
48036 			 *  primitives.
48037 			 *
48038 			 *  Note: duk_check_stack() potentially reallocs the valstack,
48039 			 *  invalidating any duk_tval pointers to valstack.  Callers
48040 			 *  must be careful.
48041 			 */
48042 
48043 			/* never shrinks; auto-adds DUK_VALSTACK_INTERNAL_EXTRA, which is generous */
48044 			if (!duk_check_stack(ctx, 1)) {
48045 				goto abandon_error;
48046 			}
48047 			DUK_ASSERT_VALSTACK_SPACE(thr, 1);
48048 			key = duk_heap_string_intern_u32(thr->heap, i);
48049 			if (!key) {
48050 				goto abandon_error;
48051 			}
48052 			duk_push_hstring(ctx, key);  /* keep key reachable for GC etc; guaranteed not to fail */
48053 
48054 			/* key is now reachable in the valstack */
48055 
48056 			DUK_HSTRING_INCREF(thr, key);   /* second incref for the entry reference */
48057 			new_e_k[new_e_next] = key;
48058 			tv2 = &new_e_pv[new_e_next].v;  /* array entries are all plain values */
48059 			DUK_TVAL_SET_TVAL(tv2, tv1);
48060 			new_e_f[new_e_next] = DUK_PROPDESC_FLAG_WRITABLE |
48061 			                      DUK_PROPDESC_FLAG_ENUMERABLE |
48062 			                      DUK_PROPDESC_FLAG_CONFIGURABLE;
48063 			new_e_next++;
48064 
48065 			/* Note: new_e_next matches pushed temp key count, and nothing can
48066 			 * fail above between the push and this point.
48067 			 */
48068 		}
48069 
48070 		DUK_DDD(DUK_DDDPRINT("abandon array: pop %ld key temps from valstack", (long) new_e_next));
48071 		duk_pop_n(ctx, new_e_next);
48072 	}
48073 
48074 	/*
48075 	 *  Copy keys and values in the entry part (compacting them at the same time).
48076 	 */
48077 
48078 	for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
48079 		duk_hstring *key;
48080 
48081 		DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL);
48082 
48083 		key = DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i);
48084 		if (!key) {
48085 			continue;
48086 		}
48087 
48088 		DUK_ASSERT(new_p != NULL && new_e_k != NULL &&
48089 		           new_e_pv != NULL && new_e_f != NULL);
48090 
48091 		new_e_k[new_e_next] = key;
48092 		new_e_pv[new_e_next] = DUK_HOBJECT_E_GET_VALUE(thr->heap, obj, i);
48093 		new_e_f[new_e_next] = DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, i);
48094 		new_e_next++;
48095 	}
48096 	/* the entries [new_e_next, new_e_size_adjusted[ are left uninitialized on purpose (ok, not gc reachable) */
48097 
48098 	/*
48099 	 *  Copy array elements to new array part.
48100 	 */
48101 
48102 	if (new_a_size > DUK_HOBJECT_GET_ASIZE(obj)) {
48103 		/* copy existing entries as is */
48104 		DUK_ASSERT(new_p != NULL && new_a != NULL);
48105 		if (DUK_HOBJECT_GET_ASIZE(obj) > 0) {
48106 			/* Avoid zero copy with an invalid pointer.  If obj->p is NULL,
48107 			 * the 'new_a' pointer will be invalid which is not allowed even
48108 			 * when copy size is zero.
48109 			 */
48110 			DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL);
48111 			DUK_ASSERT(DUK_HOBJECT_GET_ASIZE(obj) > 0);
48112 			DUK_MEMCPY((void *) new_a, (void *) DUK_HOBJECT_A_GET_BASE(thr->heap, obj), sizeof(duk_tval) * DUK_HOBJECT_GET_ASIZE(obj));
48113 		}
48114 
48115 		/* fill new entries with -unused- (required, gc reachable) */
48116 		for (i = DUK_HOBJECT_GET_ASIZE(obj); i < new_a_size; i++) {
48117 			duk_tval *tv = &new_a[i];
48118 			DUK_TVAL_SET_UNUSED(tv);
48119 		}
48120 	} else {
48121 #ifdef DUK_USE_ASSERTIONS
48122 		/* caller must have decref'd values above new_a_size (if that is necessary) */
48123 		if (!abandon_array) {
48124 			for (i = new_a_size; i < DUK_HOBJECT_GET_ASIZE(obj); i++) {
48125 				duk_tval *tv;
48126 				tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, i);
48127 
48128 				/* current assertion is quite strong: decref's and set to unused */
48129 				DUK_ASSERT(DUK_TVAL_IS_UNUSED(tv));
48130 			}
48131 		}
48132 #endif
48133 		if (new_a_size > 0) {
48134 			/* Avoid zero copy with an invalid pointer.  If obj->p is NULL,
48135 			 * the 'new_a' pointer will be invalid which is not allowed even
48136 			 * when copy size is zero.
48137 			 */
48138 			DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL);
48139 			DUK_ASSERT(new_a_size > 0);
48140 			DUK_MEMCPY((void *) new_a, (void *) DUK_HOBJECT_A_GET_BASE(thr->heap, obj), sizeof(duk_tval) * new_a_size);
48141 		}
48142 	}
48143 
48144 	/*
48145 	 *  Rebuild the hash part always from scratch (guaranteed to finish).
48146 	 *
48147 	 *  Any resize of hash part requires rehashing.  In addition, by rehashing
48148 	 *  get rid of any elements marked deleted (DUK__HASH_DELETED) which is critical
48149 	 *  to ensuring the hash part never fills up.
48150 	 */
48151 
48152 #if defined(DUK_USE_HOBJECT_HASH_PART)
48153 	if (DUK_UNLIKELY(new_h_size > 0)) {
48154 		DUK_ASSERT(new_h != NULL);
48155 
48156 		/* fill new_h with u32 0xff = UNUSED */
48157 		DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL);
48158 		DUK_ASSERT(new_h_size > 0);
48159 		DUK_MEMSET(new_h, 0xff, sizeof(duk_uint32_t) * new_h_size);
48160 
48161 		DUK_ASSERT(new_e_next <= new_h_size);  /* equality not actually possible */
48162 		for (i = 0; i < new_e_next; i++) {
48163 			duk_hstring *key = new_e_k[i];
48164 			duk_uint32_t j, step;
48165 
48166 			DUK_ASSERT(key != NULL);
48167 			j = DUK__HASH_INITIAL(DUK_HSTRING_GET_HASH(key), new_h_size);
48168 			step = DUK__HASH_PROBE_STEP(DUK_HSTRING_GET_HASH(key));
48169 
48170 			for (;;) {
48171 				DUK_ASSERT(new_h[j] != DUK__HASH_DELETED);  /* should never happen */
48172 				if (new_h[j] == DUK__HASH_UNUSED) {
48173 					DUK_DDD(DUK_DDDPRINT("rebuild hit %ld -> %ld", (long) j, (long) i));
48174 					new_h[j] = i;
48175 					break;
48176 				}
48177 				DUK_DDD(DUK_DDDPRINT("rebuild miss %ld, step %ld", (long) j, (long) step));
48178 				j = (j + step) % new_h_size;
48179 
48180 				/* guaranteed to finish */
48181 				DUK_ASSERT(j != (duk_uint32_t) DUK__HASH_INITIAL(DUK_HSTRING_GET_HASH(key), new_h_size));
48182 			}
48183 		}
48184 	} else {
48185 		DUK_DDD(DUK_DDDPRINT("no hash part, no rehash"));
48186 	}
48187 #endif  /* DUK_USE_HOBJECT_HASH_PART */
48188 
48189 	/*
48190 	 *  Nice debug log.
48191 	 */
48192 
48193 	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 "
48194 	                   "{p=%p,e_size=%ld,e_next=%ld,a_size=%ld,h_size=%ld}, abandon_array=%ld, unadjusted new_e_size=%ld",
48195 	                   (void *) obj,
48196 	                   (long) DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE(obj),
48197 	                                                     DUK_HOBJECT_GET_ASIZE(obj),
48198 	                                                     DUK_HOBJECT_GET_HSIZE(obj)),
48199 	                   (long) new_alloc_size,
48200 	                   (void *) DUK_HOBJECT_GET_PROPS(thr->heap, obj),
48201 	                   (long) DUK_HOBJECT_GET_ESIZE(obj),
48202 	                   (long) DUK_HOBJECT_GET_ENEXT(obj),
48203 	                   (long) DUK_HOBJECT_GET_ASIZE(obj),
48204 	                   (long) DUK_HOBJECT_GET_HSIZE(obj),
48205 	                   (void *) new_p,
48206 	                   (long) new_e_size_adjusted,
48207 	                   (long) new_e_next,
48208 	                   (long) new_a_size,
48209 	                   (long) new_h_size,
48210 	                   (long) abandon_array,
48211 	                   (long) new_e_size));
48212 
48213 	/*
48214 	 *  All done, switch properties ('p') allocation to new one.
48215 	 */
48216 
48217 	DUK_FREE(thr->heap, DUK_HOBJECT_GET_PROPS(thr->heap, obj));  /* NULL obj->p is OK */
48218 	DUK_HOBJECT_SET_PROPS(thr->heap, obj, new_p);
48219 	DUK_HOBJECT_SET_ESIZE(obj, new_e_size_adjusted);
48220 	DUK_HOBJECT_SET_ENEXT(obj, new_e_next);
48221 	DUK_HOBJECT_SET_ASIZE(obj, new_a_size);
48222 	DUK_HOBJECT_SET_HSIZE(obj, new_h_size);
48223 
48224 	/* clear array part flag only after switching */
48225 	if (abandon_array) {
48226 		DUK_HOBJECT_CLEAR_ARRAY_PART(obj);
48227 	}
48228 
48229 	DUK_DDD(DUK_DDDPRINT("resize result: %!O", (duk_heaphdr *) obj));
48230 
48231 #ifdef DUK_USE_MARK_AND_SWEEP
48232 	thr->heap->mark_and_sweep_base_flags = prev_mark_and_sweep_base_flags;
48233 #endif
48234 
48235 	/*
48236 	 *  Post resize assertions.
48237 	 */
48238 
48239 #ifdef DUK_USE_ASSERTIONS
48240 	/* XXX: post-checks (such as no duplicate keys) */
48241 #endif
48242 	return;
48243 
48244 	/*
48245 	 *  Abandon array failed, need to decref keys already inserted
48246 	 *  into the beginning of new_e_k before unwinding valstack.
48247 	 */
48248 
48249  abandon_error:
48250  alloc_failed:
48251 	DUK_D(DUK_DPRINT("object property table resize failed"));
48252 
48253 	i = new_e_next;
48254 	while (i > 0) {
48255 		i--;
48256 		DUK_ASSERT(new_e_k != NULL);
48257 		DUK_ASSERT(new_e_k[i] != NULL);
48258 		DUK_HSTRING_DECREF(thr, new_e_k[i]);  /* side effects */
48259 	}
48260 
48261 	DUK_FREE(thr->heap, new_p);  /* OK for NULL. */
48262 
48263 #ifdef DUK_USE_MARK_AND_SWEEP
48264 	thr->heap->mark_and_sweep_base_flags = prev_mark_and_sweep_base_flags;
48265 #endif
48266 
48267 	DUK_ERROR_ALLOC_DEFMSG(thr);
48268 }
48269 
48270 /*
48271  *  Helpers to resize properties allocation on specific needs.
48272  */
48273 
48274 /* Grow entry part allocation for one additional entry. */
48275 DUK_LOCAL void duk__grow_props_for_new_entry_item(duk_hthread *thr, duk_hobject *obj) {
48276 	duk_uint32_t old_e_used;  /* actually used, non-NULL entries */
48277 	duk_uint32_t new_e_size;
48278 	duk_uint32_t new_a_size;
48279 	duk_uint32_t new_h_size;
48280 
48281 	DUK_ASSERT(thr != NULL);
48282 	DUK_ASSERT(obj != NULL);
48283 
48284 	/* Duktape 0.11.0 and prior tried to optimize the resize by not
48285 	 * counting the number of actually used keys prior to the resize.
48286 	 * This worked mostly well but also caused weird leak-like behavior
48287 	 * as in: test-bug-object-prop-alloc-unbounded.js.  So, now we count
48288 	 * the keys explicitly to compute the new entry part size.
48289 	 */
48290 
48291 	old_e_used = duk__count_used_e_keys(thr, obj);
48292 	new_e_size = old_e_used + duk__get_min_grow_e(old_e_used);
48293 #if defined(DUK_USE_HOBJECT_HASH_PART)
48294 	new_h_size = duk__get_default_h_size(new_e_size);
48295 #else
48296 	new_h_size = 0;
48297 #endif
48298 	new_a_size = DUK_HOBJECT_GET_ASIZE(obj);
48299 	DUK_ASSERT(new_e_size >= old_e_used + 1);  /* duk__get_min_grow_e() is always >= 1 */
48300 
48301 	duk__realloc_props(thr, obj, new_e_size, new_a_size, new_h_size, 0);
48302 }
48303 
48304 /* Grow array part for a new highest array index. */
48305 DUK_LOCAL void duk__grow_props_for_array_item(duk_hthread *thr, duk_hobject *obj, duk_uint32_t highest_arr_idx) {
48306 	duk_uint32_t new_e_size;
48307 	duk_uint32_t new_a_size;
48308 	duk_uint32_t new_h_size;
48309 
48310 	DUK_ASSERT(thr != NULL);
48311 	DUK_ASSERT(obj != NULL);
48312 	DUK_ASSERT(highest_arr_idx >= DUK_HOBJECT_GET_ASIZE(obj));
48313 
48314 	/* minimum new length is highest_arr_idx + 1 */
48315 
48316 	new_e_size = DUK_HOBJECT_GET_ESIZE(obj);
48317 	new_h_size = DUK_HOBJECT_GET_HSIZE(obj);
48318 	new_a_size = highest_arr_idx + duk__get_min_grow_a(highest_arr_idx);
48319 	DUK_ASSERT(new_a_size >= highest_arr_idx + 1);  /* duk__get_min_grow_a() is always >= 1 */
48320 
48321 	duk__realloc_props(thr, obj, new_e_size, new_a_size, new_h_size, 0);
48322 }
48323 
48324 /* Abandon array part, moving array entries into entries part.
48325  * This requires a props resize, which is a heavy operation.
48326  * We also compact the entries part while we're at it, although
48327  * this is not strictly required.
48328  */
48329 DUK_LOCAL void duk__abandon_array_checked(duk_hthread *thr, duk_hobject *obj) {
48330 	duk_uint32_t new_e_size;
48331 	duk_uint32_t new_a_size;
48332 	duk_uint32_t new_h_size;
48333 	duk_uint32_t e_used;  /* actually used, non-NULL keys */
48334 	duk_uint32_t a_used;
48335 	duk_uint32_t a_size;
48336 
48337 	DUK_ASSERT(thr != NULL);
48338 	DUK_ASSERT(obj != NULL);
48339 
48340 	e_used = duk__count_used_e_keys(thr, obj);
48341 	duk__compute_a_stats(thr, obj, &a_used, &a_size);
48342 
48343 	/*
48344 	 *  Must guarantee all actually used array entries will fit into
48345 	 *  new entry part.  Add one growth step to ensure we don't run out
48346 	 *  of space right away.
48347 	 */
48348 
48349 	new_e_size = e_used + a_used;
48350 	new_e_size = new_e_size + duk__get_min_grow_e(new_e_size);
48351 	new_a_size = 0;
48352 #if defined(DUK_USE_HOBJECT_HASH_PART)
48353 	new_h_size = duk__get_default_h_size(new_e_size);
48354 #else
48355 	new_h_size = 0;
48356 #endif
48357 
48358 	DUK_DD(DUK_DDPRINT("abandon array part for hobject %p, "
48359 	                   "array stats before: e_used=%ld, a_used=%ld, a_size=%ld; "
48360 	                   "resize to e_size=%ld, a_size=%ld, h_size=%ld",
48361 	                   (void *) obj, (long) e_used, (long) a_used, (long) a_size,
48362 	                   (long) new_e_size, (long) new_a_size, (long) new_h_size));
48363 
48364 	duk__realloc_props(thr, obj, new_e_size, new_a_size, new_h_size, 1);
48365 }
48366 
48367 /*
48368  *  Compact an object.  Minimizes allocation size for objects which are
48369  *  not likely to be extended.  This is useful for internal and non-
48370  *  extensible objects, but can also be called for non-extensible objects.
48371  *  May abandon the array part if it is computed to be too sparse.
48372  *
48373  *  This call is relatively expensive, as it needs to scan both the
48374  *  entries and the array part.
48375  *
48376  *  The call may fail due to allocation error.
48377  */
48378 
48379 DUK_INTERNAL void duk_hobject_compact_props(duk_hthread *thr, duk_hobject *obj) {
48380 	duk_uint32_t e_size;       /* currently used -> new size */
48381 	duk_uint32_t a_size;       /* currently required */
48382 	duk_uint32_t a_used;       /* actually used */
48383 	duk_uint32_t h_size;
48384 	duk_bool_t abandon_array;
48385 
48386 	DUK_ASSERT(thr != NULL);
48387 	DUK_ASSERT(obj != NULL);
48388 
48389 #if defined(DUK_USE_ROM_OBJECTS)
48390 	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {
48391 		DUK_DD(DUK_DDPRINT("ignore attempt to compact a rom object"));
48392 		return;
48393 	}
48394 #endif
48395 
48396 	e_size = duk__count_used_e_keys(thr, obj);
48397 	duk__compute_a_stats(thr, obj, &a_used, &a_size);
48398 
48399 	DUK_DD(DUK_DDPRINT("compacting hobject, used e keys %ld, used a keys %ld, min a size %ld, "
48400 	                   "resized array density would be: %ld/%ld = %lf",
48401 	                   (long) e_size, (long) a_used, (long) a_size,
48402 	                   (long) a_used, (long) a_size,
48403 	                   (double) a_used / (double) a_size));
48404 
48405 	if (duk__abandon_array_density_check(a_used, a_size)) {
48406 		DUK_DD(DUK_DDPRINT("decided to abandon array during compaction, a_used=%ld, a_size=%ld",
48407 		                   (long) a_used, (long) a_size));
48408 		abandon_array = 1;
48409 		e_size += a_used;
48410 		a_size = 0;
48411 	} else {
48412 		DUK_DD(DUK_DDPRINT("decided to keep array during compaction"));
48413 		abandon_array = 0;
48414 	}
48415 
48416 #if defined(DUK_USE_HOBJECT_HASH_PART)
48417 	if (e_size >= DUK_HOBJECT_E_USE_HASH_LIMIT) {
48418 		h_size = duk__get_default_h_size(e_size);
48419 	} else {
48420 		h_size = 0;
48421 	}
48422 #else
48423 	h_size = 0;
48424 #endif
48425 
48426 	DUK_DD(DUK_DDPRINT("compacting hobject -> new e_size %ld, new a_size=%ld, new h_size=%ld, abandon_array=%ld",
48427 	                   (long) e_size, (long) a_size, (long) h_size, (long) abandon_array));
48428 
48429 	duk__realloc_props(thr, obj, e_size, a_size, h_size, abandon_array);
48430 }
48431 
48432 /*
48433  *  Find an existing key from entry part either by linear scan or by
48434  *  using the hash index (if it exists).
48435  *
48436  *  Sets entry index (and possibly the hash index) to output variables,
48437  *  which allows the caller to update the entry and hash entries in-place.
48438  *  If entry is not found, both values are set to -1.  If entry is found
48439  *  but there is no hash part, h_idx is set to -1.
48440  */
48441 
48442 DUK_INTERNAL void duk_hobject_find_existing_entry(duk_heap *heap, duk_hobject *obj, duk_hstring *key, duk_int_t *e_idx, duk_int_t *h_idx) {
48443 	DUK_ASSERT(obj != NULL);
48444 	DUK_ASSERT(key != NULL);
48445 	DUK_ASSERT(e_idx != NULL);
48446 	DUK_ASSERT(h_idx != NULL);
48447 	DUK_UNREF(heap);
48448 
48449 	if (DUK_LIKELY(DUK_HOBJECT_GET_HSIZE(obj) == 0))
48450 	{
48451 		/* Linear scan: more likely because most objects are small.
48452 		 * This is an important fast path.
48453 		 *
48454 		 * XXX: this might be worth inlining for property lookups.
48455 		 */
48456 		duk_uint_fast32_t i;
48457 		duk_uint_fast32_t n;
48458 		duk_hstring **h_keys_base;
48459 		DUK_DDD(DUK_DDDPRINT("duk_hobject_find_existing_entry() using linear scan for lookup"));
48460 
48461 		h_keys_base = DUK_HOBJECT_E_GET_KEY_BASE(heap, obj);
48462 		n = DUK_HOBJECT_GET_ENEXT(obj);
48463 		for (i = 0; i < n; i++) {
48464 			if (h_keys_base[i] == key) {
48465 				*e_idx = i;
48466 				*h_idx = -1;
48467 				return;
48468 			}
48469 		}
48470 	}
48471 #if defined(DUK_USE_HOBJECT_HASH_PART)
48472 	else
48473 	{
48474 		/* hash lookup */
48475 		duk_uint32_t n;
48476 		duk_uint32_t i, step;
48477 		duk_uint32_t *h_base;
48478 
48479 		DUK_DDD(DUK_DDDPRINT("duk_hobject_find_existing_entry() using hash part for lookup"));
48480 
48481 		h_base = DUK_HOBJECT_H_GET_BASE(heap, obj);
48482 		n = DUK_HOBJECT_GET_HSIZE(obj);
48483 		i = DUK__HASH_INITIAL(DUK_HSTRING_GET_HASH(key), n);
48484 		step = DUK__HASH_PROBE_STEP(DUK_HSTRING_GET_HASH(key));
48485 
48486 		for (;;) {
48487 			duk_uint32_t t;
48488 
48489 			DUK_ASSERT_DISABLE(i >= 0);  /* unsigned */
48490 			DUK_ASSERT(i < DUK_HOBJECT_GET_HSIZE(obj));
48491 			t = h_base[i];
48492 			DUK_ASSERT(t == DUK__HASH_UNUSED || t == DUK__HASH_DELETED ||
48493 			           (t < DUK_HOBJECT_GET_ESIZE(obj)));  /* t >= 0 always true, unsigned */
48494 
48495 			if (t == DUK__HASH_UNUSED) {
48496 				break;
48497 			} else if (t == DUK__HASH_DELETED) {
48498 				DUK_DDD(DUK_DDDPRINT("lookup miss (deleted) i=%ld, t=%ld",
48499 				                     (long) i, (long) t));
48500 			} else {
48501 				DUK_ASSERT(t < DUK_HOBJECT_GET_ESIZE(obj));
48502 				if (DUK_HOBJECT_E_GET_KEY(heap, obj, t) == key) {
48503 					DUK_DDD(DUK_DDDPRINT("lookup hit i=%ld, t=%ld -> key %p",
48504 					                     (long) i, (long) t, (void *) key));
48505 					*e_idx = t;
48506 					*h_idx = i;
48507 					return;
48508 				}
48509 				DUK_DDD(DUK_DDDPRINT("lookup miss i=%ld, t=%ld",
48510 				                     (long) i, (long) t));
48511 			}
48512 			i = (i + step) % n;
48513 
48514 			/* guaranteed to finish, as hash is never full */
48515 			DUK_ASSERT(i != (duk_uint32_t) DUK__HASH_INITIAL(DUK_HSTRING_GET_HASH(key), n));
48516 		}
48517 	}
48518 #endif  /* DUK_USE_HOBJECT_HASH_PART */
48519 
48520 	/* not found */
48521 	*e_idx = -1;
48522 	*h_idx = -1;
48523 }
48524 
48525 /* For internal use: get non-accessor entry value */
48526 DUK_INTERNAL duk_tval *duk_hobject_find_existing_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_hstring *key) {
48527 	duk_int_t e_idx;
48528 	duk_int_t h_idx;
48529 
48530 	DUK_ASSERT(obj != NULL);
48531 	DUK_ASSERT(key != NULL);
48532 	DUK_UNREF(heap);
48533 
48534 	duk_hobject_find_existing_entry(heap, obj, key, &e_idx, &h_idx);
48535 	if (e_idx >= 0 && !DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, obj, e_idx)) {
48536 		return DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap, obj, e_idx);
48537 	} else {
48538 		return NULL;
48539 	}
48540 }
48541 
48542 /* For internal use: get non-accessor entry value and attributes */
48543 DUK_INTERNAL duk_tval *duk_hobject_find_existing_entry_tval_ptr_and_attrs(duk_heap *heap, duk_hobject *obj, duk_hstring *key, duk_int_t *out_attrs) {
48544 	duk_int_t e_idx;
48545 	duk_int_t h_idx;
48546 
48547 	DUK_ASSERT(obj != NULL);
48548 	DUK_ASSERT(key != NULL);
48549 	DUK_ASSERT(out_attrs != NULL);
48550 	DUK_UNREF(heap);
48551 
48552 	duk_hobject_find_existing_entry(heap, obj, key, &e_idx, &h_idx);
48553 	if (e_idx >= 0 && !DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, obj, e_idx)) {
48554 		*out_attrs = DUK_HOBJECT_E_GET_FLAGS(heap, obj, e_idx);
48555 		return DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap, obj, e_idx);
48556 	} else {
48557 		*out_attrs = 0;
48558 		return NULL;
48559 	}
48560 }
48561 
48562 /* For internal use: get array part value */
48563 DUK_INTERNAL duk_tval *duk_hobject_find_existing_array_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_uarridx_t i) {
48564 	duk_tval *tv;
48565 
48566 	DUK_ASSERT(obj != NULL);
48567 	DUK_UNREF(heap);
48568 
48569 	if (!DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
48570 		return NULL;
48571 	}
48572 	if (i >= DUK_HOBJECT_GET_ASIZE(obj)) {
48573 		return NULL;
48574 	}
48575 	tv = DUK_HOBJECT_A_GET_VALUE_PTR(heap, obj, i);
48576 	return tv;
48577 }
48578 
48579 /*
48580  *  Allocate and initialize a new entry, resizing the properties allocation
48581  *  if necessary.  Returns entry index (e_idx) or throws an error if alloc fails.
48582  *
48583  *  Sets the key of the entry (increasing the key's refcount), and updates
48584  *  the hash part if it exists.  Caller must set value and flags, and update
48585  *  the entry value refcount.  A decref for the previous value is not necessary.
48586  */
48587 
48588 DUK_LOCAL duk_bool_t duk__alloc_entry_checked(duk_hthread *thr, duk_hobject *obj, duk_hstring *key) {
48589 	duk_uint32_t idx;
48590 
48591 	DUK_ASSERT(thr != NULL);
48592 	DUK_ASSERT(obj != NULL);
48593 	DUK_ASSERT(key != NULL);
48594 	DUK_ASSERT(DUK_HOBJECT_GET_ENEXT(obj) <= DUK_HOBJECT_GET_ESIZE(obj));
48595 
48596 #ifdef DUK_USE_ASSERTIONS
48597 	/* key must not already exist in entry part */
48598 	{
48599 		duk_uint_fast32_t i;
48600 		for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
48601 			DUK_ASSERT(DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i) != key);
48602 		}
48603 	}
48604 #endif
48605 
48606 	if (DUK_HOBJECT_GET_ENEXT(obj) >= DUK_HOBJECT_GET_ESIZE(obj)) {
48607 		/* only need to guarantee 1 more slot, but allocation growth is in chunks */
48608 		DUK_DDD(DUK_DDDPRINT("entry part full, allocate space for one more entry"));
48609 		duk__grow_props_for_new_entry_item(thr, obj);
48610 	}
48611 	DUK_ASSERT(DUK_HOBJECT_GET_ENEXT(obj) < DUK_HOBJECT_GET_ESIZE(obj));
48612 	idx = DUK_HOBJECT_POSTINC_ENEXT(obj);
48613 
48614 	/* previous value is assumed to be garbage, so don't touch it */
48615 	DUK_HOBJECT_E_SET_KEY(thr->heap, obj, idx, key);
48616 	DUK_HSTRING_INCREF(thr, key);
48617 
48618 #if defined(DUK_USE_HOBJECT_HASH_PART)
48619 	if (DUK_UNLIKELY(DUK_HOBJECT_GET_HSIZE(obj) > 0)) {
48620 		duk_uint32_t n;
48621 		duk_uint32_t i, step;
48622 		duk_uint32_t *h_base = DUK_HOBJECT_H_GET_BASE(thr->heap, obj);
48623 
48624 		n = DUK_HOBJECT_GET_HSIZE(obj);
48625 		i = DUK__HASH_INITIAL(DUK_HSTRING_GET_HASH(key), n);
48626 		step = DUK__HASH_PROBE_STEP(DUK_HSTRING_GET_HASH(key));
48627 
48628 		for (;;) {
48629 			duk_uint32_t t = h_base[i];
48630 			if (t == DUK__HASH_UNUSED || t == DUK__HASH_DELETED) {
48631 				DUK_DDD(DUK_DDDPRINT("duk__alloc_entry_checked() inserted key into hash part, %ld -> %ld",
48632 				                     (long) i, (long) idx));
48633 				DUK_ASSERT_DISABLE(i >= 0);  /* unsigned */
48634 				DUK_ASSERT(i < DUK_HOBJECT_GET_HSIZE(obj));
48635 				DUK_ASSERT_DISABLE(idx >= 0);
48636 				DUK_ASSERT(idx < DUK_HOBJECT_GET_ESIZE(obj));
48637 				h_base[i] = idx;
48638 				break;
48639 			}
48640 			DUK_DDD(DUK_DDDPRINT("duk__alloc_entry_checked() miss %ld", (long) i));
48641 			i = (i + step) % n;
48642 
48643 			/* guaranteed to find an empty slot */
48644 			DUK_ASSERT(i != (duk_uint32_t) DUK__HASH_INITIAL(DUK_HSTRING_GET_HASH(key), DUK_HOBJECT_GET_HSIZE(obj)));
48645 		}
48646 	}
48647 #endif  /* DUK_USE_HOBJECT_HASH_PART */
48648 
48649 	/* Note: we could return the hash index here too, but it's not
48650 	 * needed right now.
48651 	 */
48652 
48653 	DUK_ASSERT_DISABLE(idx >= 0);
48654 	DUK_ASSERT(idx < DUK_HOBJECT_GET_ESIZE(obj));
48655 	DUK_ASSERT(idx < DUK_HOBJECT_GET_ENEXT(obj));
48656 	return idx;
48657 }
48658 
48659 /*
48660  *  Object internal value
48661  *
48662  *  Returned value is guaranteed to be reachable / incref'd, caller does not need
48663  *  to incref OR decref.  No proxies or accessors are invoked, no prototype walk.
48664  */
48665 
48666 DUK_INTERNAL duk_bool_t duk_hobject_get_internal_value(duk_heap *heap, duk_hobject *obj, duk_tval *tv_out) {
48667 	duk_int_t e_idx;
48668 	duk_int_t h_idx;
48669 
48670 	DUK_ASSERT(heap != NULL);
48671 	DUK_ASSERT(obj != NULL);
48672 	DUK_ASSERT(tv_out != NULL);
48673 
48674 	/* always in entry part, no need to look up parents etc */
48675 	duk_hobject_find_existing_entry(heap, obj, DUK_HEAP_STRING_INT_VALUE(heap), &e_idx, &h_idx);
48676 	if (e_idx >= 0) {
48677 		DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, obj, e_idx));
48678 		DUK_TVAL_SET_TVAL(tv_out, DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap, obj, e_idx));
48679 		return 1;
48680 	}
48681 	DUK_TVAL_SET_UNDEFINED(tv_out);
48682 	return 0;
48683 }
48684 
48685 DUK_INTERNAL duk_hstring *duk_hobject_get_internal_value_string(duk_heap *heap, duk_hobject *obj) {
48686 	duk_tval tv;
48687 
48688 	DUK_ASSERT(heap != NULL);
48689 	DUK_ASSERT(obj != NULL);
48690 
48691 	/* This is not strictly necessary, but avoids compiler warnings; e.g.
48692 	 * gcc won't reliably detect that no uninitialized data is read below.
48693 	 */
48694 	DUK_MEMZERO((void *) &tv, sizeof(duk_tval));
48695 
48696 	if (duk_hobject_get_internal_value(heap, obj, &tv)) {
48697 		duk_hstring *h;
48698 		DUK_ASSERT(DUK_TVAL_IS_STRING(&tv));
48699 		h = DUK_TVAL_GET_STRING(&tv);
48700 		return h;
48701 	}
48702 
48703 	return NULL;
48704 }
48705 
48706 /*
48707  *  Arguments handling helpers (argument map mainly).
48708  *
48709  *  An arguments object has exotic behavior for some numeric indices.
48710  *  Accesses may translate to identifier operations which may have
48711  *  arbitrary side effects (potentially invalidating any duk_tval
48712  *  pointers).
48713  */
48714 
48715 /* Lookup 'key' from arguments internal 'map', perform a variable lookup
48716  * if mapped, and leave the result on top of stack (and return non-zero).
48717  * Used in E5 Section 10.6 algorithms [[Get]] and [[GetOwnProperty]].
48718  */
48719 DUK_LOCAL
48720 duk_bool_t duk__lookup_arguments_map(duk_hthread *thr,
48721                                      duk_hobject *obj,
48722                                      duk_hstring *key,
48723                                      duk_propdesc *temp_desc,
48724                                      duk_hobject **out_map,
48725                                      duk_hobject **out_varenv) {
48726 	duk_context *ctx = (duk_context *) thr;
48727 	duk_hobject *map;
48728 	duk_hobject *varenv;
48729 	duk_bool_t rc;
48730 
48731 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
48732 
48733 	DUK_DDD(DUK_DDDPRINT("arguments map lookup: thr=%p, obj=%p, key=%p, temp_desc=%p "
48734 	                     "(obj -> %!O, key -> %!O)",
48735 	                     (void *) thr, (void *) obj, (void *) key, (void *) temp_desc,
48736 	                     (duk_heaphdr *) obj, (duk_heaphdr *) key));
48737 
48738 	if (!duk_hobject_get_own_propdesc(thr, obj, DUK_HTHREAD_STRING_INT_MAP(thr), temp_desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
48739 		DUK_DDD(DUK_DDDPRINT("-> no 'map'"));
48740 		return 0;
48741 	}
48742 
48743 	map = duk_require_hobject(ctx, -1);
48744 	DUK_ASSERT(map != NULL);
48745 	duk_pop(ctx);  /* map is reachable through obj */
48746 
48747 	if (!duk_hobject_get_own_propdesc(thr, map, key, temp_desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
48748 		DUK_DDD(DUK_DDDPRINT("-> 'map' exists, but key not in map"));
48749 		return 0;
48750 	}
48751 
48752 	/* [... varname] */
48753 	DUK_DDD(DUK_DDDPRINT("-> 'map' exists, and contains key, key is mapped to argument/variable binding %!T",
48754 	                     (duk_tval *) duk_get_tval(ctx, -1)));
48755 	DUK_ASSERT(duk_is_string(ctx, -1));  /* guaranteed when building arguments */
48756 
48757 	/* get varenv for varname (callee's declarative lexical environment) */
48758 	rc = duk_hobject_get_own_propdesc(thr, obj, DUK_HTHREAD_STRING_INT_VARENV(thr), temp_desc, DUK_GETDESC_FLAG_PUSH_VALUE);
48759 	DUK_UNREF(rc);
48760 	DUK_ASSERT(rc != 0);  /* arguments MUST have an initialized lexical environment reference */
48761 	varenv = duk_require_hobject(ctx, -1);
48762 	DUK_ASSERT(varenv != NULL);
48763 	duk_pop(ctx);  /* varenv remains reachable through 'obj' */
48764 
48765 	DUK_DDD(DUK_DDDPRINT("arguments varenv is: %!dO", (duk_heaphdr *) varenv));
48766 
48767 	/* success: leave varname in stack */
48768 	*out_map = map;
48769 	*out_varenv = varenv;
48770 	return 1;  /* [... varname] */
48771 }
48772 
48773 /* Lookup 'key' from arguments internal 'map', and leave replacement value
48774  * on stack top if mapped (and return non-zero).
48775  * Used in E5 Section 10.6 algorithm for [[GetOwnProperty]] (used by [[Get]]).
48776  */
48777 DUK_LOCAL duk_bool_t duk__check_arguments_map_for_get(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *temp_desc) {
48778 	duk_context *ctx = (duk_context *) thr;
48779 	duk_hobject *map;
48780 	duk_hobject *varenv;
48781 	duk_hstring *varname;
48782 
48783 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
48784 
48785 	if (!duk__lookup_arguments_map(thr, obj, key, temp_desc, &map, &varenv)) {
48786 		DUK_DDD(DUK_DDDPRINT("arguments: key not mapped, no exotic get behavior"));
48787 		return 0;
48788 	}
48789 
48790 	/* [... varname] */
48791 
48792 	varname = duk_require_hstring(ctx, -1);
48793 	DUK_ASSERT(varname != NULL);
48794 	duk_pop(ctx);  /* varname is still reachable */
48795 
48796 	DUK_DDD(DUK_DDDPRINT("arguments object automatic getvar for a bound variable; "
48797 	                     "key=%!O, varname=%!O",
48798 	                     (duk_heaphdr *) key,
48799 	                     (duk_heaphdr *) varname));
48800 
48801 	(void) duk_js_getvar_envrec(thr, varenv, varname, 1 /*throw*/);
48802 
48803 	/* [... value this_binding] */
48804 
48805 	duk_pop(ctx);
48806 
48807 	/* leave result on stack top */
48808 	return 1;
48809 }
48810 
48811 /* Lookup 'key' from arguments internal 'map', perform a variable write if mapped.
48812  * Used in E5 Section 10.6 algorithm for [[DefineOwnProperty]] (used by [[Put]]).
48813  * Assumes stack top contains 'put' value (which is NOT popped).
48814  */
48815 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) {
48816 	duk_context *ctx = (duk_context *) thr;
48817 	duk_hobject *map;
48818 	duk_hobject *varenv;
48819 	duk_hstring *varname;
48820 
48821 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
48822 
48823 	if (!duk__lookup_arguments_map(thr, obj, key, temp_desc, &map, &varenv)) {
48824 		DUK_DDD(DUK_DDDPRINT("arguments: key not mapped, no exotic put behavior"));
48825 		return;
48826 	}
48827 
48828 	/* [... put_value varname] */
48829 
48830 	varname = duk_require_hstring(ctx, -1);
48831 	DUK_ASSERT(varname != NULL);
48832 	duk_pop(ctx);  /* varname is still reachable */
48833 
48834 	DUK_DDD(DUK_DDDPRINT("arguments object automatic putvar for a bound variable; "
48835 	                     "key=%!O, varname=%!O, value=%!T",
48836 	                     (duk_heaphdr *) key,
48837 	                     (duk_heaphdr *) varname,
48838 	                     (duk_tval *) duk_require_tval(ctx, -1)));
48839 
48840 	/* [... put_value] */
48841 
48842 	/*
48843 	 *  Note: although arguments object variable mappings are only established
48844 	 *  for non-strict functions (and a call to a non-strict function created
48845 	 *  the arguments object in question), an inner strict function may be doing
48846 	 *  the actual property write.  Hence the throw_flag applied here comes from
48847 	 *  the property write call.
48848 	 */
48849 
48850 	duk_js_putvar_envrec(thr, varenv, varname, duk_require_tval(ctx, -1), throw_flag);
48851 
48852 	/* [... put_value] */
48853 }
48854 
48855 /* Lookup 'key' from arguments internal 'map', delete mapping if found.
48856  * Used in E5 Section 10.6 algorithm for [[Delete]].  Note that the
48857  * variable/argument itself (where the map points) is not deleted.
48858  */
48859 DUK_LOCAL void duk__check_arguments_map_for_delete(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *temp_desc) {
48860 	duk_context *ctx = (duk_context *) thr;
48861 	duk_hobject *map;
48862 
48863 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
48864 
48865 	if (!duk_hobject_get_own_propdesc(thr, obj, DUK_HTHREAD_STRING_INT_MAP(thr), temp_desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
48866 		DUK_DDD(DUK_DDDPRINT("arguments: key not mapped, no exotic delete behavior"));
48867 		return;
48868 	}
48869 
48870 	map = duk_require_hobject(ctx, -1);
48871 	DUK_ASSERT(map != NULL);
48872 	duk_pop(ctx);  /* map is reachable through obj */
48873 
48874 	DUK_DDD(DUK_DDDPRINT("-> have 'map', delete key %!O from map (if exists)); ignore result",
48875 	                     (duk_heaphdr *) key));
48876 
48877 	/* Note: no recursion issue, we can trust 'map' to behave */
48878 	DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_BEHAVIOR(map));
48879 	DUK_DDD(DUK_DDDPRINT("map before deletion: %!O", (duk_heaphdr *) map));
48880 	(void) duk_hobject_delprop_raw(thr, map, key, 0);  /* ignore result */
48881 	DUK_DDD(DUK_DDDPRINT("map after deletion: %!O", (duk_heaphdr *) map));
48882 }
48883 
48884 /*
48885  *  Ecmascript compliant [[GetOwnProperty]](P), for internal use only.
48886  *
48887  *  If property is found:
48888  *    - Fills descriptor fields to 'out_desc'
48889  *    - If DUK_GETDESC_FLAG_PUSH_VALUE is set, pushes a value related to the
48890  *      property onto the stack ('undefined' for accessor properties).
48891  *    - Returns non-zero
48892  *
48893  *  If property is not found:
48894  *    - 'out_desc' is left in untouched state (possibly garbage)
48895  *    - Nothing is pushed onto the stack (not even with DUK_GETDESC_FLAG_PUSH_VALUE
48896  *      set)
48897  *    - Returns zero
48898  *
48899  *  Notes:
48900  *
48901  *    - Getting a property descriptor may cause an allocation (and hence
48902  *      GC) to take place, hence reachability and refcount of all related
48903  *      values matter.  Reallocation of value stack, properties, etc may
48904  *      invalidate many duk_tval pointers (concretely, those which reside
48905  *      in memory areas subject to reallocation).  However, heap object
48906  *      pointers are never affected (heap objects have stable pointers).
48907  *
48908  *    - The value of a plain property is always reachable and has a non-zero
48909  *      reference count.
48910  *
48911  *    - The value of a virtual property is not necessarily reachable from
48912  *      elsewhere and may have a refcount of zero.  Hence we push it onto
48913  *      the valstack for the caller, which ensures it remains reachable
48914  *      while it is needed.
48915  *
48916  *    - There are no virtual accessor properties.  Hence, all getters and
48917  *      setters are always related to concretely stored properties, which
48918  *      ensures that the get/set functions in the resulting descriptor are
48919  *      reachable and have non-zero refcounts.  Should there be virtual
48920  *      accessor properties later, this would need to change.
48921  */
48922 
48923 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) {
48924 	duk_context *ctx = (duk_context *) thr;
48925 	duk_tval *tv;
48926 
48927 	DUK_DDD(DUK_DDDPRINT("duk_hobject_get_own_propdesc: thr=%p, obj=%p, key=%p, out_desc=%p, flags=%lx, "
48928 	                     "arr_idx=%ld (obj -> %!O, key -> %!O)",
48929 	                     (void *) thr, (void *) obj, (void *) key, (void *) out_desc,
48930 	                     (long) flags, (long) arr_idx,
48931 	                     (duk_heaphdr *) obj, (duk_heaphdr *) key));
48932 
48933 	DUK_ASSERT(ctx != NULL);
48934 	DUK_ASSERT(thr != NULL);
48935 	DUK_ASSERT(thr->heap != NULL);
48936 	DUK_ASSERT(obj != NULL);
48937 	DUK_ASSERT(key != NULL);
48938 	DUK_ASSERT(out_desc != NULL);
48939 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
48940 
48941 	/* XXX: optimize this filling behavior later */
48942 	out_desc->flags = 0;
48943 	out_desc->get = NULL;
48944 	out_desc->set = NULL;
48945 	out_desc->e_idx = -1;
48946 	out_desc->h_idx = -1;
48947 	out_desc->a_idx = -1;
48948 
48949 	/*
48950 	 *  Array part
48951 	 */
48952 
48953 	if (DUK_HOBJECT_HAS_ARRAY_PART(obj) && arr_idx != DUK__NO_ARRAY_INDEX) {
48954 		if (arr_idx < DUK_HOBJECT_GET_ASIZE(obj)) {
48955 			tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, arr_idx);
48956 			if (!DUK_TVAL_IS_UNUSED(tv)) {
48957 				DUK_DDD(DUK_DDDPRINT("-> found in array part"));
48958 				if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
48959 					duk_push_tval(ctx, tv);
48960 				}
48961 				/* implicit attributes */
48962 				out_desc->flags = DUK_PROPDESC_FLAG_WRITABLE |
48963 				                  DUK_PROPDESC_FLAG_CONFIGURABLE |
48964 				                  DUK_PROPDESC_FLAG_ENUMERABLE;
48965 				out_desc->a_idx = arr_idx;
48966 				goto prop_found;
48967 			}
48968 		}
48969 		/* assume array part is comprehensive (contains all array indexed elements
48970 		 * or none of them); hence no need to check the entries part here.
48971 		 */
48972 		DUK_DDD(DUK_DDDPRINT("-> not found as a concrete property (has array part, "
48973 		                     "should be there if present)"));
48974 		goto prop_not_found_concrete;
48975 	}
48976 
48977 	/*
48978 	 *  Entries part
48979 	 */
48980 
48981 	duk_hobject_find_existing_entry(thr->heap, obj, key, &out_desc->e_idx, &out_desc->h_idx);
48982 	if (out_desc->e_idx >= 0) {
48983 		duk_int_t e_idx = out_desc->e_idx;
48984 		out_desc->flags = DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, e_idx);
48985 		if (out_desc->flags & DUK_PROPDESC_FLAG_ACCESSOR) {
48986 			DUK_DDD(DUK_DDDPRINT("-> found accessor property in entry part"));
48987 			out_desc->get = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, obj, e_idx);
48988 			out_desc->set = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, obj, e_idx);
48989 			if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
48990 				/* a dummy undefined value is pushed to make valstack
48991 				 * behavior uniform for caller
48992 				 */
48993 				duk_push_undefined(ctx);
48994 			}
48995 		} else {
48996 			DUK_DDD(DUK_DDDPRINT("-> found plain property in entry part"));
48997 			tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, e_idx);
48998 			if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
48999 				duk_push_tval(ctx, tv);
49000 			}
49001 		}
49002 		goto prop_found;
49003 	}
49004 
49005 	/*
49006 	 *  Not found as a concrete property, check whether a String object
49007 	 *  virtual property matches.
49008 	 */
49009 
49010  prop_not_found_concrete:
49011 
49012 	if (DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(obj)) {
49013 		DUK_DDD(DUK_DDDPRINT("string object exotic property get for key: %!O, arr_idx: %ld",
49014 		                     (duk_heaphdr *) key, (long) arr_idx));
49015 
49016 		if (arr_idx != DUK__NO_ARRAY_INDEX) {
49017 			duk_hstring *h_val;
49018 
49019 			DUK_DDD(DUK_DDDPRINT("array index exists"));
49020 
49021 			h_val = duk_hobject_get_internal_value_string(thr->heap, obj);
49022 			DUK_ASSERT(h_val);
49023 			if (arr_idx < DUK_HSTRING_GET_CHARLEN(h_val)) {
49024 				DUK_DDD(DUK_DDDPRINT("-> found, array index inside string"));
49025 				if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
49026 					duk_push_hstring(ctx, h_val);
49027 					duk_substring(ctx, -1, arr_idx, arr_idx + 1);  /* [str] -> [substr] */
49028 				}
49029 				out_desc->flags = DUK_PROPDESC_FLAG_ENUMERABLE |  /* E5 Section 15.5.5.2 */
49030 				                  DUK_PROPDESC_FLAG_VIRTUAL;
49031 
49032 				DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj));
49033 				return 1;  /* cannot be e.g. arguments exotic, since exotic 'traits' are mutually exclusive */
49034 			} else {
49035 				/* index is above internal string length -> property is fully normal */
49036 				DUK_DDD(DUK_DDDPRINT("array index outside string -> normal property"));
49037 			}
49038 		} else if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
49039 			duk_hstring *h_val;
49040 
49041 			DUK_DDD(DUK_DDDPRINT("-> found, key is 'length', length exotic behavior"));
49042 
49043 			h_val = duk_hobject_get_internal_value_string(thr->heap, obj);
49044 			DUK_ASSERT(h_val != NULL);
49045 			if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
49046 				duk_push_uint(ctx, (duk_uint_t) DUK_HSTRING_GET_CHARLEN(h_val));
49047 			}
49048 			out_desc->flags = DUK_PROPDESC_FLAG_VIRTUAL;  /* E5 Section 15.5.5.1 */
49049 
49050 			DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj));
49051 			return 1;  /* cannot be arguments exotic */
49052 		}
49053 	} else if (DUK_HOBJECT_IS_BUFFEROBJECT(obj)) {
49054 		duk_hbufferobject *h_bufobj;
49055 		duk_uint_t byte_off;
49056 		duk_small_uint_t elem_size;
49057 
49058 		h_bufobj = (duk_hbufferobject *) obj;
49059 		DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj);
49060 		DUK_DDD(DUK_DDDPRINT("bufferobject property get for key: %!O, arr_idx: %ld",
49061 		                     (duk_heaphdr *) key, (long) arr_idx));
49062 
49063 		if (arr_idx != DUK__NO_ARRAY_INDEX) {
49064 			DUK_DDD(DUK_DDDPRINT("array index exists"));
49065 
49066 			/* Careful with wrapping: arr_idx upshift may easily wrap, whereas
49067 			 * length downshift won't.
49068 			 */
49069 			if (arr_idx < (h_bufobj->length >> h_bufobj->shift)) {
49070 				byte_off = arr_idx << h_bufobj->shift;  /* no wrap assuming h_bufobj->length is valid */
49071 				elem_size = 1 << h_bufobj->shift;
49072 				if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
49073 					duk_uint8_t *data;
49074 
49075 					if (h_bufobj->buf != NULL && DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) {
49076 						data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) + h_bufobj->offset + byte_off;
49077 						duk_hbufferobject_push_validated_read(ctx, h_bufobj, data, elem_size);
49078 					} else {
49079 						DUK_D(DUK_DPRINT("bufferobject access out of underlying buffer, ignoring (read zero)"));
49080 						duk_push_uint(ctx, 0);
49081 					}
49082 				}
49083 				out_desc->flags = DUK_PROPDESC_FLAG_WRITABLE |
49084 				                  DUK_PROPDESC_FLAG_ENUMERABLE |
49085 				                  DUK_PROPDESC_FLAG_VIRTUAL;
49086 
49087 				DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj));
49088 				return 1;  /* cannot be e.g. arguments exotic, since exotic 'traits' are mutually exclusive */
49089 			} else {
49090 				/* index is above internal buffer length -> property is fully normal */
49091 				DUK_DDD(DUK_DDDPRINT("array index outside buffer -> normal property"));
49092 			}
49093 		} else if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
49094 			DUK_DDD(DUK_DDDPRINT("-> found, key is 'length', length exotic behavior"));
49095 
49096 			if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
49097 				/* Length in elements: take into account shift, but
49098 				 * intentionally don't check the underlying buffer here.
49099 				 */
49100 				duk_push_uint(ctx, h_bufobj->length >> h_bufobj->shift);
49101 			}
49102 			out_desc->flags = DUK_PROPDESC_FLAG_VIRTUAL;
49103 
49104 			DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj));
49105 			return 1;  /* cannot be arguments exotic */
49106 		} else if (key == DUK_HTHREAD_STRING_BYTE_LENGTH(thr)) {
49107 			/* If neutered must return 0; length is zeroed during
49108 			 * neutering.
49109 			 */
49110 			if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
49111 				duk_push_uint(ctx, h_bufobj->length);
49112 			}
49113 			out_desc->flags = DUK_PROPDESC_FLAG_VIRTUAL;
49114 			return 1;  /* cannot be arguments exotic */
49115 		} else if (key == DUK_HTHREAD_STRING_BYTE_OFFSET(thr)) {
49116 			/* If neutered must return 0; offset is zeroed during
49117 			 * neutering.
49118 			 */
49119 			if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
49120 				duk_push_uint(ctx, h_bufobj->offset);
49121 			}
49122 			out_desc->flags = DUK_PROPDESC_FLAG_VIRTUAL;
49123 			return 1;  /* cannot be arguments exotic */
49124 		} else if (key == DUK_HTHREAD_STRING_BYTES_PER_ELEMENT(thr)) {
49125 			if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
49126 				duk_push_uint(ctx, 1 << h_bufobj->shift);
49127 			}
49128 			out_desc->flags = DUK_PROPDESC_FLAG_VIRTUAL;
49129 			return 1;  /* cannot be arguments exotic */
49130 		}
49131 	} else if (DUK_HOBJECT_HAS_EXOTIC_DUKFUNC(obj)) {
49132 		DUK_DDD(DUK_DDDPRINT("duktape/c object exotic property get for key: %!O, arr_idx: %ld",
49133 		                     (duk_heaphdr *) key, (long) arr_idx));
49134 
49135 		if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
49136 			DUK_DDD(DUK_DDDPRINT("-> found, key is 'length', length exotic behavior"));
49137 
49138 			if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
49139 				duk_int16_t func_nargs = ((duk_hnativefunction *) obj)->nargs;
49140 				duk_push_int(ctx, func_nargs == DUK_HNATIVEFUNCTION_NARGS_VARARGS ? 0 : func_nargs);
49141 			}
49142 			out_desc->flags = DUK_PROPDESC_FLAG_VIRTUAL;  /* not enumerable */
49143 
49144 			DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj));
49145 			return 1;  /* cannot be arguments exotic */
49146 		}
49147 	}
49148 
49149 	/* Array properties have exotic behavior but they are concrete,
49150 	 * so no special handling here.
49151 	 *
49152 	 * Arguments exotic behavior (E5 Section 10.6, [[GetOwnProperty]]
49153 	 * is only relevant as a post-check implemented below; hence no
49154 	 * check here.
49155 	 */
49156 
49157 	/*
49158 	 *  Not found as concrete or virtual
49159 	 */
49160 
49161 	DUK_DDD(DUK_DDDPRINT("-> not found (virtual, entry part, or array part)"));
49162 	return 0;
49163 
49164 	/*
49165 	 *  Found
49166 	 *
49167 	 *  Arguments object has exotic post-processing, see E5 Section 10.6,
49168 	 *  description of [[GetOwnProperty]] variant for arguments.
49169 	 */
49170 
49171  prop_found:
49172 	DUK_DDD(DUK_DDDPRINT("-> property found, checking for arguments exotic post-behavior"));
49173 
49174 	/* Notes:
49175 	 *  - only numbered indices are relevant, so arr_idx fast reject is good
49176 	 *    (this is valid unless there are more than 4**32-1 arguments).
49177 	 *  - since variable lookup has no side effects, this can be skipped if
49178 	 *    DUK_GETDESC_FLAG_PUSH_VALUE is not set.
49179 	 */
49180 
49181 	if (DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj) &&
49182 	    arr_idx != DUK__NO_ARRAY_INDEX &&
49183 	    (flags & DUK_GETDESC_FLAG_PUSH_VALUE)) {
49184 		duk_propdesc temp_desc;
49185 
49186 		/* Magically bound variable cannot be an accessor.  However,
49187 		 * there may be an accessor property (or a plain property) in
49188 		 * place with magic behavior removed.  This happens e.g. when
49189 		 * a magic property is redefined with defineProperty().
49190 		 * Cannot assert for "not accessor" here.
49191 		 */
49192 
49193 		/* replaces top of stack with new value if necessary */
49194 		DUK_ASSERT((flags & DUK_GETDESC_FLAG_PUSH_VALUE) != 0);
49195 
49196 		if (duk__check_arguments_map_for_get(thr, obj, key, &temp_desc)) {
49197 			DUK_DDD(DUK_DDDPRINT("-> arguments exotic behavior overrides result: %!T -> %!T",
49198 			                     (duk_tval *) duk_get_tval(ctx, -2),
49199 			                     (duk_tval *) duk_get_tval(ctx, -1)));
49200 			/* [... old_result result] -> [... result] */
49201 			duk_remove(ctx, -2);
49202 		}
49203 	}
49204 
49205 	return 1;
49206 }
49207 
49208 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) {
49209 	DUK_ASSERT(thr != NULL);
49210 	DUK_ASSERT(obj != NULL);
49211 	DUK_ASSERT(key != NULL);
49212 	DUK_ASSERT(out_desc != NULL);
49213 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
49214 
49215 	return duk__get_own_propdesc_raw(thr, obj, key, DUK_HSTRING_GET_ARRIDX_SLOW(key), out_desc, flags);
49216 }
49217 
49218 /*
49219  *  Ecmascript compliant [[GetProperty]](P), for internal use only.
49220  *
49221  *  If property is found:
49222  *    - Fills descriptor fields to 'out_desc'
49223  *    - If DUK_GETDESC_FLAG_PUSH_VALUE is set, pushes a value related to the
49224  *      property onto the stack ('undefined' for accessor properties).
49225  *    - Returns non-zero
49226  *
49227  *  If property is not found:
49228  *    - 'out_desc' is left in untouched state (possibly garbage)
49229  *    - Nothing is pushed onto the stack (not even with DUK_GETDESC_FLAG_PUSH_VALUE
49230  *      set)
49231  *    - Returns zero
49232  *
49233  *  May cause arbitrary side effects and invalidate (most) duk_tval
49234  *  pointers.
49235  */
49236 
49237 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) {
49238 	duk_hobject *curr;
49239 	duk_uint32_t arr_idx;
49240 	duk_uint_t sanity;
49241 
49242 	DUK_ASSERT(thr != NULL);
49243 	DUK_ASSERT(thr->heap != NULL);
49244 	DUK_ASSERT(obj != NULL);
49245 	DUK_ASSERT(key != NULL);
49246 	DUK_ASSERT(out_desc != NULL);
49247 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
49248 
49249 	arr_idx = DUK_HSTRING_GET_ARRIDX_FAST(key);
49250 
49251 	DUK_DDD(DUK_DDDPRINT("duk__get_propdesc: thr=%p, obj=%p, key=%p, out_desc=%p, flags=%lx, "
49252 	                     "arr_idx=%ld (obj -> %!O, key -> %!O)",
49253 	                     (void *) thr, (void *) obj, (void *) key, (void *) out_desc,
49254 	                     (long) flags, (long) arr_idx,
49255 	                     (duk_heaphdr *) obj, (duk_heaphdr *) key));
49256 
49257 	curr = obj;
49258 	DUK_ASSERT(curr != NULL);
49259 	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
49260 	do {
49261 		if (duk__get_own_propdesc_raw(thr, curr, key, arr_idx, out_desc, flags)) {
49262 			/* stack contains value (if requested), 'out_desc' is set */
49263 			return 1;
49264 		}
49265 
49266 		/* not found in 'curr', next in prototype chain; impose max depth */
49267 		if (sanity-- == 0) {
49268 			if (flags & DUK_GETDESC_FLAG_IGNORE_PROTOLOOP) {
49269 				/* treat like property not found */
49270 				break;
49271 			} else {
49272 				DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
49273 			}
49274 		}
49275 		curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr);
49276 	} while (curr);
49277 
49278 	/* out_desc is left untouched (possibly garbage), caller must use return
49279 	 * value to determine whether out_desc can be looked up
49280 	 */
49281 
49282 	return 0;
49283 }
49284 
49285 /*
49286  *  Shallow fast path checks for accessing array elements with numeric
49287  *  indices.  The goal is to try to avoid coercing an array index to an
49288  *  (interned) string for the most common lookups, in particular, for
49289  *  standard Array objects.
49290  *
49291  *  Interning is avoided but only for a very narrow set of cases:
49292  *    - Object has array part, index is within array allocation, and
49293  *      value is not unused (= key exists)
49294  *    - Object has no interfering exotic behavior (e.g. arguments or
49295  *      string object exotic behaviors interfere, array exotic
49296  *      behavior does not).
49297  *
49298  *  Current shortcoming: if key does not exist (even if it is within
49299  *  the array allocation range) a slow path lookup with interning is
49300  *  always required.  This can probably be fixed so that there is a
49301  *  quick fast path for non-existent elements as well, at least for
49302  *  standard Array objects.
49303  */
49304 
49305 DUK_LOCAL duk_tval *duk__getprop_shallow_fastpath_array_tval(duk_hthread *thr, duk_hobject *obj, duk_tval *tv_key) {
49306 	duk_tval *tv;
49307 	duk_uint32_t idx;
49308 
49309 	DUK_UNREF(thr);
49310 
49311 	if (!(DUK_HOBJECT_HAS_ARRAY_PART(obj) &&
49312 	     !DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj) &&
49313 	     !DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(obj) &&
49314 	     !DUK_HOBJECT_IS_BUFFEROBJECT(obj) &&
49315 	     !DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(obj))) {
49316 		/* Must have array part and no conflicting exotic behaviors.
49317 		 * Doesn't need to have array special behavior, e.g. Arguments
49318 		 * object has array part.
49319 		 */
49320 		return NULL;
49321 	}
49322 
49323 	/* Arrays never have other exotic behaviors. */
49324 
49325 	DUK_DDD(DUK_DDDPRINT("fast path attempt (no exotic string/arguments/buffer "
49326 	                     "behavior, object has array part)"));
49327 
49328 #if defined(DUK_USE_FASTINT)
49329 	if (DUK_TVAL_IS_FASTINT(tv_key)) {
49330 		idx = duk__tval_fastint_to_arr_idx(tv_key);
49331 	} else
49332 #endif
49333 	if (DUK_TVAL_IS_DOUBLE(tv_key)) {
49334 		idx = duk__tval_number_to_arr_idx(tv_key);
49335 	} else {
49336 		DUK_DDD(DUK_DDDPRINT("key is not a number"));
49337 		return NULL;
49338 	}
49339 
49340 	/* If index is not valid, idx will be DUK__NO_ARRAY_INDEX which
49341 	 * is 0xffffffffUL.  We don't need to check for that explicitly
49342 	 * because 0xffffffffUL will never be inside object 'a_size'.
49343 	 */
49344 
49345 	if (idx >= DUK_HOBJECT_GET_ASIZE(obj)) {
49346 		DUK_DDD(DUK_DDDPRINT("key is not an array index or outside array part"));
49347 		return NULL;
49348 	}
49349 	DUK_ASSERT(idx != 0xffffffffUL);
49350 	DUK_ASSERT(idx != DUK__NO_ARRAY_INDEX);
49351 
49352 	/* XXX: for array instances we could take a shortcut here and assume
49353 	 * Array.prototype doesn't contain an array index property.
49354 	 */
49355 
49356 	DUK_DDD(DUK_DDDPRINT("key is a valid array index and inside array part"));
49357 	tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, idx);
49358 	if (!DUK_TVAL_IS_UNUSED(tv)) {
49359 		DUK_DDD(DUK_DDDPRINT("-> fast path successful"));
49360 		return tv;
49361 	}
49362 
49363 	DUK_DDD(DUK_DDDPRINT("fast path attempt failed, fall back to slow path"));
49364 	return NULL;
49365 }
49366 
49367 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, duk_propdesc *temp_desc) {
49368 	duk_tval *tv;
49369 	duk_uint32_t idx;
49370 	duk_uint32_t old_len, new_len;
49371 
49372 	if (!(DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj) &&
49373 	      DUK_HOBJECT_HAS_ARRAY_PART(obj) &&
49374 	      DUK_HOBJECT_HAS_EXTENSIBLE(obj))) {
49375 		return 0;
49376 	}
49377 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));  /* caller ensures */
49378 
49379 #if defined(DUK_USE_FASTINT)
49380 	if (DUK_TVAL_IS_FASTINT(tv_key)) {
49381 		idx = duk__tval_fastint_to_arr_idx(tv_key);
49382 	} else
49383 #endif
49384 	if (DUK_TVAL_IS_DOUBLE(tv_key)) {
49385 		idx = duk__tval_number_to_arr_idx(tv_key);
49386 	} else {
49387 		DUK_DDD(DUK_DDDPRINT("key is not a number"));
49388 		return 0;
49389 	}
49390 
49391 	/* If index is not valid, idx will be DUK__NO_ARRAY_INDEX which
49392 	 * is 0xffffffffUL.  We don't need to check for that explicitly
49393 	 * because 0xffffffffUL will never be inside object 'a_size'.
49394 	 */
49395 
49396 	if (idx >= DUK_HOBJECT_GET_ASIZE(obj)) {  /* for resizing of array part, use slow path */
49397 		return 0;
49398 	}
49399 	DUK_ASSERT(idx != 0xffffffffUL);
49400 	DUK_ASSERT(idx != DUK__NO_ARRAY_INDEX);
49401 
49402 	old_len = duk__get_old_array_length(thr, obj, temp_desc);
49403 
49404 	if (idx >= old_len) {
49405 		DUK_DDD(DUK_DDDPRINT("write new array entry requires length update "
49406 		                     "(arr_idx=%ld, old_len=%ld)",
49407 		                     (long) idx, (long) old_len));
49408 		if (!(temp_desc->flags & DUK_PROPDESC_FLAG_WRITABLE)) {
49409 			DUK_ERROR_TYPE(thr, DUK_STR_NOT_WRITABLE);
49410 			return 0;  /* not reachable */
49411 		}
49412 		new_len = idx + 1;
49413 
49414 		/* No resize has occurred so temp_desc->e_idx is still OK */
49415 		tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, temp_desc->e_idx);
49416 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
49417 		DUK_TVAL_SET_FASTINT_U32(tv, new_len);  /* no need for decref/incref because value is a number */
49418 	} else {
49419 		;
49420 	}
49421 
49422 	tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, idx);
49423 	DUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv_val);  /* side effects */
49424 
49425 	DUK_DDD(DUK_DDDPRINT("array fast path success for index %ld", (long) idx));
49426 	return 1;
49427 }
49428 
49429 /*
49430  *  Fast path for bufferobject getprop/putprop
49431  */
49432 
49433 DUK_LOCAL duk_bool_t duk__getprop_fastpath_bufobj_tval(duk_hthread *thr, duk_hobject *obj, duk_tval *tv_key) {
49434 	duk_context *ctx;
49435 	duk_uint32_t idx;
49436 	duk_hbufferobject *h_bufobj;
49437 	duk_uint_t byte_off;
49438 	duk_small_uint_t elem_size;
49439 	duk_uint8_t *data;
49440 
49441 	ctx = (duk_context *) thr;
49442 
49443 	if (!DUK_HOBJECT_IS_BUFFEROBJECT(obj)) {
49444 		return 0;
49445 	}
49446 	h_bufobj = (duk_hbufferobject *) obj;
49447 
49448 #if defined(DUK_USE_FASTINT)
49449 	if (DUK_TVAL_IS_FASTINT(tv_key)) {
49450 		idx = duk__tval_fastint_to_arr_idx(tv_key);
49451 	} else
49452 #endif
49453 	if (DUK_TVAL_IS_DOUBLE(tv_key)) {
49454 		idx = duk__tval_number_to_arr_idx(tv_key);
49455 	} else {
49456 		return 0;
49457 	}
49458 
49459 	/* If index is not valid, idx will be DUK__NO_ARRAY_INDEX which
49460 	 * is 0xffffffffUL.  We don't need to check for that explicitly
49461 	 * because 0xffffffffUL will never be inside bufferobject length.
49462 	 */
49463 
49464 	/* Careful with wrapping (left shifting idx would be unsafe). */
49465 	if (idx >= (h_bufobj->length >> h_bufobj->shift)) {
49466 		return 0;
49467 	}
49468 	DUK_ASSERT(idx != DUK__NO_ARRAY_INDEX);
49469 
49470 	byte_off = idx << h_bufobj->shift;  /* no wrap assuming h_bufobj->length is valid */
49471 	elem_size = 1 << h_bufobj->shift;
49472 
49473 	if (h_bufobj->buf != NULL && DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) {
49474 		data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) + h_bufobj->offset + byte_off;
49475 		duk_hbufferobject_push_validated_read(ctx, h_bufobj, data, elem_size);
49476 	} else {
49477 		DUK_D(DUK_DPRINT("bufferobject access out of underlying buffer, ignoring (read zero)"));
49478 		duk_push_uint(ctx, 0);
49479 	}
49480 
49481 	return 1;
49482 }
49483 
49484 DUK_LOCAL duk_bool_t duk__putprop_fastpath_bufobj_tval(duk_hthread *thr, duk_hobject *obj, duk_tval *tv_key, duk_tval *tv_val) {
49485 	duk_context *ctx;
49486 	duk_uint32_t idx;
49487 	duk_hbufferobject *h_bufobj;
49488 	duk_uint_t byte_off;
49489 	duk_small_uint_t elem_size;
49490 	duk_uint8_t *data;
49491 
49492 	ctx = (duk_context *) thr;
49493 
49494 	if (!(DUK_HOBJECT_IS_BUFFEROBJECT(obj) &&
49495 	      DUK_TVAL_IS_NUMBER(tv_val))) {
49496 		return 0;
49497 	}
49498 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));  /* caller ensures; rom objects are never bufferobjects now */
49499 
49500 	h_bufobj = (duk_hbufferobject *) obj;
49501 #if defined(DUK_USE_FASTINT)
49502 	if (DUK_TVAL_IS_FASTINT(tv_key)) {
49503 		idx = duk__tval_fastint_to_arr_idx(tv_key);
49504 	} else
49505 #endif
49506 	if (DUK_TVAL_IS_DOUBLE(tv_key)) {
49507 		idx = duk__tval_number_to_arr_idx(tv_key);
49508 	} else {
49509 		return 0;
49510 	}
49511 
49512 	/* If index is not valid, idx will be DUK__NO_ARRAY_INDEX which
49513 	 * is 0xffffffffUL.  We don't need to check for that explicitly
49514 	 * because 0xffffffffUL will never be inside bufferobject length.
49515 	 */
49516 
49517 	/* Careful with wrapping (left shifting idx would be unsafe). */
49518 	if (idx >= (h_bufobj->length >> h_bufobj->shift)) {
49519 		return 0;
49520 	}
49521 	DUK_ASSERT(idx != DUK__NO_ARRAY_INDEX);
49522 
49523 	byte_off = idx << h_bufobj->shift;  /* no wrap assuming h_bufobj->length is valid */
49524 	elem_size = 1 << h_bufobj->shift;
49525 
49526 	/* Value is required to be a number in the fast path so there
49527 	 * are no side effects in write coercion.
49528 	 */
49529 	duk_push_tval(ctx, tv_val);
49530 	DUK_ASSERT(duk_is_number(ctx, -1));
49531 
49532 	if (h_bufobj->buf != NULL && DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) {
49533 		data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) + h_bufobj->offset + byte_off;
49534 		duk_hbufferobject_validated_write(ctx, h_bufobj, data, elem_size);
49535 	} else {
49536 		DUK_D(DUK_DPRINT("bufferobject access out of underlying buffer, ignoring (write skipped)"));
49537 	}
49538 
49539 	duk_pop(ctx);
49540 	return 1;
49541 }
49542 
49543 /*
49544  *  GETPROP: Ecmascript property read.
49545  */
49546 
49547 DUK_INTERNAL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key) {
49548 	duk_context *ctx = (duk_context *) thr;
49549 	duk_tval tv_obj_copy;
49550 	duk_tval tv_key_copy;
49551 	duk_hobject *curr = NULL;
49552 	duk_hstring *key = NULL;
49553 	duk_uint32_t arr_idx = DUK__NO_ARRAY_INDEX;
49554 	duk_propdesc desc;
49555 	duk_uint_t sanity;
49556 
49557 	DUK_DDD(DUK_DDDPRINT("getprop: thr=%p, obj=%p, key=%p (obj -> %!T, key -> %!T)",
49558 	                     (void *) thr, (void *) tv_obj, (void *) tv_key,
49559 	                     (duk_tval *) tv_obj, (duk_tval *) tv_key));
49560 
49561 	DUK_ASSERT(ctx != NULL);
49562 	DUK_ASSERT(thr != NULL);
49563 	DUK_ASSERT(thr->heap != NULL);
49564 	DUK_ASSERT(tv_obj != NULL);
49565 	DUK_ASSERT(tv_key != NULL);
49566 
49567 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
49568 
49569 	/*
49570 	 *  Make a copy of tv_obj, tv_key, and tv_val to avoid any issues of
49571 	 *  them being invalidated by a valstack resize.
49572 	 *
49573 	 *  XXX: this is now an overkill for many fast paths.  Rework this
49574 	 *  to be faster (although switching to a valstack discipline might
49575 	 *  be a better solution overall).
49576 	 */
49577 
49578 	DUK_TVAL_SET_TVAL(&tv_obj_copy, tv_obj);
49579 	DUK_TVAL_SET_TVAL(&tv_key_copy, tv_key);
49580 	tv_obj = &tv_obj_copy;
49581 	tv_key = &tv_key_copy;
49582 
49583 	/*
49584 	 *  Coercion and fast path processing
49585 	 */
49586 
49587 	switch (DUK_TVAL_GET_TAG(tv_obj)) {
49588 	case DUK_TAG_UNDEFINED:
49589 	case DUK_TAG_NULL: {
49590 		/* Note: unconditional throw */
49591 		DUK_DDD(DUK_DDDPRINT("base object is undefined or null -> reject"));
49592 #if defined(DUK_USE_PARANOID_ERRORS)
49593 		DUK_ERROR_TYPE(thr, DUK_STR_INVALID_BASE);
49594 #else
49595 		DUK_ERROR_FMT2(thr, DUK_ERR_TYPE_ERROR, "cannot read property %s of %s",
49596 		               duk_push_string_tval_readable(ctx, tv_key), duk_push_string_tval_readable(ctx, tv_obj));
49597 #endif
49598 		return 0;
49599 	}
49600 
49601 	case DUK_TAG_BOOLEAN: {
49602 		DUK_DDD(DUK_DDDPRINT("base object is a boolean, start lookup from boolean prototype"));
49603 		curr = thr->builtins[DUK_BIDX_BOOLEAN_PROTOTYPE];
49604 		break;
49605 	}
49606 
49607 	case DUK_TAG_STRING: {
49608 		duk_hstring *h = DUK_TVAL_GET_STRING(tv_obj);
49609 		duk_int_t pop_count;
49610 
49611 #if defined(DUK_USE_FASTINT)
49612 		if (DUK_TVAL_IS_FASTINT(tv_key)) {
49613 			arr_idx = duk__tval_fastint_to_arr_idx(tv_key);
49614 			DUK_DDD(DUK_DDDPRINT("base object string, key is a fast-path fastint; arr_idx %ld", (long) arr_idx));
49615 			pop_count = 0;
49616 		} else
49617 #endif
49618 		if (DUK_TVAL_IS_NUMBER(tv_key)) {
49619 			arr_idx = duk__tval_number_to_arr_idx(tv_key);
49620 			DUK_DDD(DUK_DDDPRINT("base object string, key is a fast-path number; arr_idx %ld", (long) arr_idx));
49621 			pop_count = 0;
49622 		} else {
49623 			arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
49624 			DUK_ASSERT(key != NULL);
49625 			DUK_DDD(DUK_DDDPRINT("base object string, key is a non-fast-path number; after "
49626 			                     "coercion key is %!T, arr_idx %ld",
49627 			                     (duk_tval *) duk_get_tval(ctx, -1), (long) arr_idx));
49628 			pop_count = 1;
49629 		}
49630 
49631 		if (arr_idx != DUK__NO_ARRAY_INDEX &&
49632 		    arr_idx < DUK_HSTRING_GET_CHARLEN(h)) {
49633 			duk_pop_n(ctx, pop_count);
49634 			duk_push_hstring(ctx, h);
49635 			duk_substring(ctx, -1, arr_idx, arr_idx + 1);  /* [str] -> [substr] */
49636 
49637 			DUK_DDD(DUK_DDDPRINT("-> %!T (base is string, key is an index inside string length "
49638 			                     "after coercion -> return char)",
49639 			                     (duk_tval *) duk_get_tval(ctx, -1)));
49640 			return 1;
49641 		}
49642 
49643 		if (pop_count == 0) {
49644 			/* This is a pretty awkward control flow, but we need to recheck the
49645 			 * key coercion here.
49646 			 */
49647 			arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
49648 			DUK_ASSERT(key != NULL);
49649 			DUK_DDD(DUK_DDDPRINT("base object string, key is a non-fast-path number; after "
49650 			                     "coercion key is %!T, arr_idx %ld",
49651 			                     (duk_tval *) duk_get_tval(ctx, -1), (long) arr_idx));
49652 		}
49653 
49654 		if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
49655 			duk_pop(ctx);  /* [key] -> [] */
49656 			duk_push_uint(ctx, (duk_uint_t) DUK_HSTRING_GET_CHARLEN(h));  /* [] -> [res] */
49657 
49658 			DUK_DDD(DUK_DDDPRINT("-> %!T (base is string, key is 'length' after coercion -> "
49659 			                     "return string length)",
49660 			                     (duk_tval *) duk_get_tval(ctx, -1)));
49661 			return 1;
49662 		}
49663 		DUK_DDD(DUK_DDDPRINT("base object is a string, start lookup from string prototype"));
49664 		curr = thr->builtins[DUK_BIDX_STRING_PROTOTYPE];
49665 		goto lookup;  /* avoid double coercion */
49666 	}
49667 
49668 	case DUK_TAG_OBJECT: {
49669 		duk_tval *tmp;
49670 
49671 		curr = DUK_TVAL_GET_OBJECT(tv_obj);
49672 		DUK_ASSERT(curr != NULL);
49673 
49674 		tmp = duk__getprop_shallow_fastpath_array_tval(thr, curr, tv_key);
49675 		if (tmp) {
49676 			duk_push_tval(ctx, tmp);
49677 
49678 			DUK_DDD(DUK_DDDPRINT("-> %!T (base is object, key is a number, array part "
49679 			                     "fast path)",
49680 			                     (duk_tval *) duk_get_tval(ctx, -1)));
49681 			return 1;
49682 		}
49683 
49684 		if (duk__getprop_fastpath_bufobj_tval(thr, curr, tv_key) != 0) {
49685 			/* Read value pushed on stack. */
49686 			DUK_DDD(DUK_DDDPRINT("-> %!T (base is bufobj, key is a number, bufferobject "
49687 			                     "fast path)",
49688 			                     (duk_tval *) duk_get_tval(ctx, -1)));
49689 			return 1;
49690 		}
49691 
49692 #if defined(DUK_USE_ES6_PROXY)
49693 		if (DUK_UNLIKELY(DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(curr))) {
49694 			duk_hobject *h_target;
49695 
49696 			if (duk__proxy_check_prop(thr, curr, DUK_STRIDX_GET, tv_key, &h_target)) {
49697 				/* -> [ ... trap handler ] */
49698 				DUK_DDD(DUK_DDDPRINT("-> proxy object 'get' for key %!T", (duk_tval *) tv_key));
49699 				duk_push_hobject(ctx, h_target);  /* target */
49700 				duk_push_tval(ctx, tv_key);       /* P */
49701 				duk_push_tval(ctx, tv_obj);       /* Receiver: Proxy object */
49702 				duk_call_method(ctx, 3 /*nargs*/);
49703 
49704 				/* Target object must be checked for a conflicting
49705 				 * non-configurable property.
49706 				 */
49707 				arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
49708 				DUK_ASSERT(key != NULL);
49709 
49710 				if (duk__get_own_propdesc_raw(thr, h_target, key, arr_idx, &desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
49711 					duk_tval *tv_hook = duk_require_tval(ctx, -3);  /* value from hook */
49712 					duk_tval *tv_targ = duk_require_tval(ctx, -1);  /* value from target */
49713 					duk_bool_t datadesc_reject;
49714 					duk_bool_t accdesc_reject;
49715 
49716 					DUK_DDD(DUK_DDDPRINT("proxy 'get': target has matching property %!O, check for "
49717 					                     "conflicting property; tv_hook=%!T, tv_targ=%!T, desc.flags=0x%08lx, "
49718 					                     "desc.get=%p, desc.set=%p",
49719 					                     (duk_heaphdr *) key, (duk_tval *) tv_hook, (duk_tval *) tv_targ,
49720 					                     (unsigned long) desc.flags,
49721 					                     (void *) desc.get, (void *) desc.set));
49722 
49723 					datadesc_reject = !(desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
49724 					                  !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) &&
49725 					                  !(desc.flags & DUK_PROPDESC_FLAG_WRITABLE) &&
49726 					                  !duk_js_samevalue(tv_hook, tv_targ);
49727 					accdesc_reject = (desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
49728 					                 !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) &&
49729 					                 (desc.get == NULL) &&
49730 					                 !DUK_TVAL_IS_UNDEFINED(tv_hook);
49731 					if (datadesc_reject || accdesc_reject) {
49732 						DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);
49733 					}
49734 
49735 					duk_pop_2(ctx);
49736 				} else {
49737 					duk_pop(ctx);
49738 				}
49739 				return 1;  /* return value */
49740 			}
49741 
49742 			curr = h_target;  /* resume lookup from target */
49743 			DUK_TVAL_SET_OBJECT(tv_obj, curr);
49744 		}
49745 #endif  /* DUK_USE_ES6_PROXY */
49746 
49747 		if (DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(curr)) {
49748 			arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
49749 			DUK_ASSERT(key != NULL);
49750 
49751 			if (duk__check_arguments_map_for_get(thr, curr, key, &desc)) {
49752 				DUK_DDD(DUK_DDDPRINT("-> %!T (base is object with arguments exotic behavior, "
49753 				                     "key matches magically bound property -> skip standard "
49754 				                     "Get with replacement value)",
49755 				                     (duk_tval *) duk_get_tval(ctx, -1)));
49756 
49757 				/* no need for 'caller' post-check, because 'key' must be an array index */
49758 
49759 				duk_remove(ctx, -2);  /* [key result] -> [result] */
49760 				return 1;
49761 			}
49762 
49763 			goto lookup;  /* avoid double coercion */
49764 		}
49765 		break;
49766 	}
49767 
49768 	/* Buffer has virtual properties similar to string, but indexed values
49769 	 * are numbers, not 1-byte buffers/strings which would perform badly.
49770 	 */
49771 	case DUK_TAG_BUFFER: {
49772 		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv_obj);
49773 		duk_int_t pop_count;
49774 
49775 		/*
49776 		 *  Because buffer values are often looped over, a number fast path
49777 		 *  is important.
49778 		 */
49779 
49780 #if defined(DUK_USE_FASTINT)
49781 		if (DUK_TVAL_IS_FASTINT(tv_key)) {
49782 			arr_idx = duk__tval_fastint_to_arr_idx(tv_key);
49783 			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a fast-path fastint; arr_idx %ld", (long) arr_idx));
49784 			pop_count = 0;
49785 		}
49786 		else
49787 #endif
49788 		if (DUK_TVAL_IS_NUMBER(tv_key)) {
49789 			arr_idx = duk__tval_number_to_arr_idx(tv_key);
49790 			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a fast-path number; arr_idx %ld", (long) arr_idx));
49791 			pop_count = 0;
49792 		} else {
49793 			arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
49794 			DUK_ASSERT(key != NULL);
49795 			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a non-fast-path number; after "
49796 			                     "coercion key is %!T, arr_idx %ld",
49797 			                     (duk_tval *) duk_get_tval(ctx, -1), (long) arr_idx));
49798 			pop_count = 1;
49799 		}
49800 
49801 		if (arr_idx != DUK__NO_ARRAY_INDEX &&
49802 		    arr_idx < DUK_HBUFFER_GET_SIZE(h)) {
49803 			duk_pop_n(ctx, pop_count);
49804 			duk_push_uint(ctx, ((duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h))[arr_idx]);
49805 
49806 			DUK_DDD(DUK_DDDPRINT("-> %!T (base is buffer, key is an index inside buffer length "
49807 			                     "after coercion -> return byte as number)",
49808 			                     (duk_tval *) duk_get_tval(ctx, -1)));
49809 			return 1;
49810 		}
49811 
49812 		if (pop_count == 0) {
49813 			/* This is a pretty awkward control flow, but we need to recheck the
49814 			 * key coercion here.
49815 			 */
49816 			arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
49817 			DUK_ASSERT(key != NULL);
49818 			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a non-fast-path number; after "
49819 			                     "coercion key is %!T, arr_idx %ld",
49820 			                     (duk_tval *) duk_get_tval(ctx, -1), (long) arr_idx));
49821 		}
49822 
49823 		if (key == DUK_HTHREAD_STRING_LENGTH(thr) ||
49824 		    key == DUK_HTHREAD_STRING_BYTE_LENGTH(thr)) {
49825 			duk_pop(ctx);  /* [key] -> [] */
49826 			duk_push_uint(ctx, (duk_uint_t) DUK_HBUFFER_GET_SIZE(h));  /* [] -> [res] */
49827 
49828 			DUK_DDD(DUK_DDDPRINT("-> %!T (base is buffer, key is 'length' or 'byteLength' "
49829 			                     "after coercion -> return buffer length)",
49830 			                     (duk_tval *) duk_get_tval(ctx, -1)));
49831 			return 1;
49832 		} else if (key == DUK_HTHREAD_STRING_BYTE_OFFSET(thr)) {
49833 			duk_pop(ctx);  /* [key] -> [] */
49834 			duk_push_uint(ctx, 0);  /* [] -> [res] */
49835 
49836 			DUK_DDD(DUK_DDDPRINT("-> %!T (base is buffer, key is 'byteOffset' after coercion -> "
49837 			                     "return 0 for consistency with Buffer objects)",
49838 			                     (duk_tval *) duk_get_tval(ctx, -1)));
49839 			return 1;
49840 		} else if (key == DUK_HTHREAD_STRING_BYTES_PER_ELEMENT(thr)) {
49841 			duk_pop(ctx);  /* [key] -> [] */
49842 			duk_push_uint(ctx, 1);  /* [] -> [res] */
49843 
49844 			DUK_DDD(DUK_DDDPRINT("-> %!T (base is buffer, key is 'BYTES_PER_ELEMENT' after coercion -> "
49845 			                     "return 1 for consistency with Buffer objects)",
49846 			                     (duk_tval *) duk_get_tval(ctx, -1)));
49847 			return 1;
49848 		}
49849 
49850 		DUK_DDD(DUK_DDDPRINT("base object is a buffer, start lookup from buffer prototype"));
49851 		curr = thr->builtins[DUK_BIDX_BUFFER_PROTOTYPE];
49852 		goto lookup;  /* avoid double coercion */
49853 	}
49854 
49855 	case DUK_TAG_POINTER: {
49856 		DUK_DDD(DUK_DDDPRINT("base object is a pointer, start lookup from pointer prototype"));
49857 		curr = thr->builtins[DUK_BIDX_POINTER_PROTOTYPE];
49858 		break;
49859 	}
49860 
49861 	case DUK_TAG_LIGHTFUNC: {
49862 		duk_int_t lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv_obj);
49863 
49864 		/* Must coerce key: if key is an object, it may coerce to e.g. 'length'. */
49865 		arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
49866 
49867 		if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
49868 			duk_int_t lf_len = DUK_LFUNC_FLAGS_GET_LENGTH(lf_flags);
49869 			duk_pop(ctx);
49870 			duk_push_int(ctx, lf_len);
49871 			return 1;
49872 		} else if (key == DUK_HTHREAD_STRING_NAME(thr)) {
49873 			duk_pop(ctx);
49874 			duk_push_lightfunc_name(ctx, tv_obj);
49875 			return 1;
49876 		}
49877 
49878 		DUK_DDD(DUK_DDDPRINT("base object is a lightfunc, start lookup from function prototype"));
49879 		curr = thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE];
49880 		goto lookup;  /* avoid double coercion */
49881 	}
49882 
49883 #if defined(DUK_USE_FASTINT)
49884 	case DUK_TAG_FASTINT:
49885 #endif
49886 	default: {
49887 		/* number */
49888 		DUK_DDD(DUK_DDDPRINT("base object is a number, start lookup from number prototype"));
49889 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv_obj));
49890 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_obj));
49891 		curr = thr->builtins[DUK_BIDX_NUMBER_PROTOTYPE];
49892 		break;
49893 	}
49894 	}
49895 
49896 	/* key coercion (unless already coerced above) */
49897 	DUK_ASSERT(key == NULL);
49898 	arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
49899 	DUK_ASSERT(key != NULL);
49900 
49901 	/*
49902 	 *  Property lookup
49903 	 */
49904 
49905  lookup:
49906 	/* [key] (coerced) */
49907 	DUK_ASSERT(curr != NULL);
49908 	DUK_ASSERT(key != NULL);
49909 
49910 	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
49911 	do {
49912 		if (!duk__get_own_propdesc_raw(thr, curr, key, arr_idx, &desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
49913 			goto next_in_chain;
49914 		}
49915 
49916 		if (desc.get != NULL) {
49917 			/* accessor with defined getter */
49918 			DUK_ASSERT((desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) != 0);
49919 
49920 			duk_pop(ctx);                     /* [key undefined] -> [key] */
49921 			duk_push_hobject(ctx, desc.get);
49922 			duk_push_tval(ctx, tv_obj);       /* note: original, uncoerced base */
49923 #ifdef DUK_USE_NONSTD_GETTER_KEY_ARGUMENT
49924 			duk_dup(ctx, -3);
49925 			duk_call_method(ctx, 1);          /* [key getter this key] -> [key retval] */
49926 #else
49927 			duk_call_method(ctx, 0);          /* [key getter this] -> [key retval] */
49928 #endif
49929 		} else {
49930 			/* [key value] or [key undefined] */
49931 
49932 			/* data property or accessor without getter */
49933 			DUK_ASSERT(((desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) == 0) ||
49934 			           (desc.get == NULL));
49935 
49936 			/* if accessor without getter, return value is undefined */
49937 			DUK_ASSERT(((desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) == 0) ||
49938 			           duk_is_undefined(ctx, -1));
49939 
49940 			/* Note: for an accessor without getter, falling through to
49941 			 * check for "caller" exotic behavior is unnecessary as
49942 			 * "undefined" will never activate the behavior.  But it does
49943 			 * no harm, so we'll do it anyway.
49944 			 */
49945 		}
49946 
49947 		goto found;  /* [key result] */
49948 
49949 	 next_in_chain:
49950 		/* XXX: option to pretend property doesn't exist if sanity limit is
49951 		 * hit might be useful.
49952 		 */
49953 		if (sanity-- == 0) {
49954 			DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
49955 		}
49956 		curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr);
49957 	} while (curr);
49958 
49959 	/*
49960 	 *  Not found
49961 	 */
49962 
49963 	duk_to_undefined(ctx, -1);  /* [key] -> [undefined] (default value) */
49964 
49965 	DUK_DDD(DUK_DDDPRINT("-> %!T (not found)", (duk_tval *) duk_get_tval(ctx, -1)));
49966 	return 0;
49967 
49968 	/*
49969 	 *  Found; post-processing (Function and arguments objects)
49970 	 */
49971 
49972  found:
49973 	/* [key result] */
49974 
49975 #if !defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
49976 	/* Special behavior for 'caller' property of (non-bound) function objects
49977 	 * and non-strict Arguments objects: if 'caller' -value- (!) is a strict
49978 	 * mode function, throw a TypeError (E5 Sections 15.3.5.4, 10.6).
49979 	 * Quite interestingly, a non-strict function with no formal arguments
49980 	 * will get an arguments object -without- special 'caller' behavior!
49981 	 *
49982 	 * The E5.1 spec is a bit ambiguous if this special behavior applies when
49983 	 * a bound function is the base value (not the 'caller' value): Section
49984 	 * 15.3.4.5 (describing bind()) states that [[Get]] for bound functions
49985 	 * matches that of Section 15.3.5.4 ([[Get]] for Function instances).
49986 	 * However, Section 13.3.5.4 has "NOTE: Function objects created using
49987 	 * Function.prototype.bind use the default [[Get]] internal method."
49988 	 * The current implementation assumes this means that bound functions
49989 	 * should not have the special [[Get]] behavior.
49990 	 *
49991 	 * The E5.1 spec is also a bit unclear if the TypeError throwing is
49992 	 * applied if the 'caller' value is a strict bound function.  The
49993 	 * current implementation will throw even for both strict non-bound
49994 	 * and strict bound functions.
49995 	 *
49996 	 * See test-dev-strict-func-as-caller-prop-value.js for quite extensive
49997 	 * tests.
49998 	 *
49999 	 * This exotic behavior is disabled when the non-standard 'caller' property
50000 	 * is enabled, as it conflicts with the free use of 'caller'.
50001 	 */
50002 	if (key == DUK_HTHREAD_STRING_CALLER(thr) &&
50003 	    DUK_TVAL_IS_OBJECT(tv_obj)) {
50004 		duk_hobject *orig = DUK_TVAL_GET_OBJECT(tv_obj);
50005 		DUK_ASSERT(orig != NULL);
50006 
50007 		if (DUK_HOBJECT_IS_NONBOUND_FUNCTION(orig) ||
50008 		    DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(orig)) {
50009 			duk_hobject *h;
50010 
50011 			/* XXX: The TypeError is currently not applied to bound
50012 			 * functions because the 'strict' flag is not copied by
50013 			 * bind().  This may or may not be correct, the specification
50014 			 * only refers to the value being a "strict mode Function
50015 			 * object" which is ambiguous.
50016 			 */
50017 			DUK_ASSERT(!DUK_HOBJECT_HAS_BOUND(orig));
50018 
50019 			h = duk_get_hobject(ctx, -1);  /* NULL if not an object */
50020 			if (h &&
50021 			    DUK_HOBJECT_IS_FUNCTION(h) &&
50022 			    DUK_HOBJECT_HAS_STRICT(h)) {
50023 				/* XXX: sufficient to check 'strict', assert for 'is function' */
50024 				DUK_ERROR_TYPE(thr, DUK_STR_STRICT_CALLER_READ);
50025 			}
50026 		}
50027 	}
50028 #endif   /* !DUK_USE_NONSTD_FUNC_CALLER_PROPERTY */
50029 
50030 	duk_remove(ctx, -2);  /* [key result] -> [result] */
50031 
50032 	DUK_DDD(DUK_DDDPRINT("-> %!T (found)", (duk_tval *) duk_get_tval(ctx, -1)));
50033 	return 1;
50034 }
50035 
50036 /*
50037  *  HASPROP: Ecmascript property existence check ("in" operator).
50038  *
50039  *  Interestingly, the 'in' operator does not do any coercion of
50040  *  the target object.
50041  */
50042 
50043 DUK_INTERNAL duk_bool_t duk_hobject_hasprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key) {
50044 	duk_context *ctx = (duk_context *) thr;
50045 	duk_tval tv_key_copy;
50046 	duk_hobject *obj;
50047 	duk_hstring *key;
50048 	duk_uint32_t arr_idx;
50049 	duk_bool_t rc;
50050 	duk_propdesc desc;
50051 
50052 	DUK_DDD(DUK_DDDPRINT("hasprop: thr=%p, obj=%p, key=%p (obj -> %!T, key -> %!T)",
50053 	                     (void *) thr, (void *) tv_obj, (void *) tv_key,
50054 	                     (duk_tval *) tv_obj, (duk_tval *) tv_key));
50055 
50056 	DUK_ASSERT(thr != NULL);
50057 	DUK_ASSERT(thr->heap != NULL);
50058 	DUK_ASSERT(tv_obj != NULL);
50059 	DUK_ASSERT(tv_key != NULL);
50060 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
50061 
50062 	DUK_TVAL_SET_TVAL(&tv_key_copy, tv_key);
50063 	tv_key = &tv_key_copy;
50064 
50065 	/*
50066 	 *  The 'in' operator requires an object as its right hand side,
50067 	 *  throwing a TypeError unconditionally if this is not the case.
50068 	 *
50069 	 *  However, lightfuncs need to behave like fully fledged objects
50070 	 *  here to be maximally transparent, so we need to handle them
50071 	 *  here.
50072 	 */
50073 
50074 	/* XXX: Refactor key coercion so that it's only called once.  It can't
50075 	 * be trivially lifted here because the object must be type checked
50076 	 * first.
50077 	 */
50078 
50079 	if (DUK_TVAL_IS_OBJECT(tv_obj)) {
50080 		obj = DUK_TVAL_GET_OBJECT(tv_obj);
50081 		DUK_ASSERT(obj != NULL);
50082 
50083 		arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
50084 	} else if (DUK_TVAL_IS_LIGHTFUNC(tv_obj)) {
50085 		arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
50086 		if (duk__key_is_lightfunc_ownprop(thr, key)) {
50087 			/* FOUND */
50088 			rc = 1;
50089 			goto pop_and_return;
50090 		}
50091 
50092 		/* If not found, resume existence check from Function.prototype.
50093 		 * We can just substitute the value in this case; nothing will
50094 		 * need the original base value (as would be the case with e.g.
50095 		 * setters/getters.
50096 		 */
50097 		obj = thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE];
50098 	} else {
50099 		/* Note: unconditional throw */
50100 		DUK_DDD(DUK_DDDPRINT("base object is not an object -> reject"));
50101 		DUK_ERROR_TYPE(thr, DUK_STR_INVALID_BASE);
50102 	}
50103 
50104 	/* XXX: fast path for arrays? */
50105 
50106 	DUK_ASSERT(key != NULL);
50107 	DUK_ASSERT(obj != NULL);
50108 	DUK_UNREF(arr_idx);
50109 
50110 #if defined(DUK_USE_ES6_PROXY)
50111 	if (DUK_UNLIKELY(DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(obj))) {
50112 		duk_hobject *h_target;
50113 		duk_bool_t tmp_bool;
50114 
50115 		/* XXX: the key in 'key in obj' is string coerced before we're called
50116 		 * (which is the required behavior in E5/E5.1/E6) so the key is a string
50117 		 * here already.
50118 		 */
50119 
50120 		if (duk__proxy_check_prop(thr, obj, DUK_STRIDX_HAS, tv_key, &h_target)) {
50121 			/* [ ... key trap handler ] */
50122 			DUK_DDD(DUK_DDDPRINT("-> proxy object 'has' for key %!T", (duk_tval *) tv_key));
50123 			duk_push_hobject(ctx, h_target);  /* target */
50124 			duk_push_tval(ctx, tv_key);       /* P */
50125 			duk_call_method(ctx, 2 /*nargs*/);
50126 			tmp_bool = duk_to_boolean(ctx, -1);
50127 			if (!tmp_bool) {
50128 				/* Target object must be checked for a conflicting
50129 				 * non-configurable property.
50130 				 */
50131 
50132 				if (duk__get_own_propdesc_raw(thr, h_target, key, arr_idx, &desc, 0 /*flags*/)) {  /* don't push value */
50133 					DUK_DDD(DUK_DDDPRINT("proxy 'has': target has matching property %!O, check for "
50134 					                     "conflicting property; desc.flags=0x%08lx, "
50135 					                     "desc.get=%p, desc.set=%p",
50136 					                     (duk_heaphdr *) key, (unsigned long) desc.flags,
50137 					                     (void *) desc.get, (void *) desc.set));
50138 					/* XXX: Extensibility check for target uses IsExtensible().  If we
50139 					 * implemented the isExtensible trap and didn't reject proxies as
50140 					 * proxy targets, it should be respected here.
50141 					 */
50142 					if (!((desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) &&  /* property is configurable and */
50143 					      DUK_HOBJECT_HAS_EXTENSIBLE(h_target))) {          /* ... target is extensible */
50144 						DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);
50145 					}
50146 				}
50147 			}
50148 
50149 			duk_pop_2(ctx);  /* [ key trap_result ] -> [] */
50150 			return tmp_bool;
50151 		}
50152 
50153 		obj = h_target;  /* resume check from proxy target */
50154 	}
50155 #endif  /* DUK_USE_ES6_PROXY */
50156 
50157 	/* XXX: inline into a prototype walking loop? */
50158 
50159 	rc = duk__get_propdesc(thr, obj, key, &desc, 0 /*flags*/);  /* don't push value */
50160 	/* fall through */
50161 
50162  pop_and_return:
50163 	duk_pop(ctx);  /* [ key ] -> [] */
50164 	return rc;
50165 }
50166 
50167 /*
50168  *  HASPROP variant used internally.
50169  *
50170  *  This primitive must never throw an error, callers rely on this.
50171  *  In particular, don't throw an error for prototype loops; instead,
50172  *  pretend like the property doesn't exist if a prototype sanity limit
50173  *  is reached.
50174  *
50175  *  Does not implement proxy behavior: if applied to a proxy object,
50176  *  returns key existence on the proxy object itself.
50177  */
50178 
50179 DUK_INTERNAL duk_bool_t duk_hobject_hasprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key) {
50180 	duk_propdesc dummy;
50181 
50182 	DUK_ASSERT(thr != NULL);
50183 	DUK_ASSERT(thr->heap != NULL);
50184 	DUK_ASSERT(obj != NULL);
50185 	DUK_ASSERT(key != NULL);
50186 
50187 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
50188 
50189 	return duk__get_propdesc(thr, obj, key, &dummy, DUK_GETDESC_FLAG_IGNORE_PROTOLOOP);  /* don't push value */
50190 }
50191 
50192 /*
50193  *  Helper: handle Array object 'length' write which automatically
50194  *  deletes properties, see E5 Section 15.4.5.1, step 3.  This is
50195  *  quite tricky to get right.
50196  *
50197  *  Used by duk_hobject_putprop().
50198  */
50199 
50200 DUK_LOCAL duk_uint32_t duk__get_old_array_length(duk_hthread *thr, duk_hobject *obj, duk_propdesc *temp_desc) {
50201 	duk_bool_t rc;
50202 	duk_tval *tv;
50203 	duk_uint32_t res;
50204 
50205 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
50206 
50207 	/* This function is only called for objects with array exotic behavior.
50208 	 * The [[DefineOwnProperty]] algorithm for arrays requires that
50209 	 * 'length' can never have a value outside the unsigned 32-bit range,
50210 	 * attempt to write such a value is a RangeError.  Here we can thus
50211 	 * assert for this.  When Duktape internals go around the official
50212 	 * property write interface (doesn't happen often) this assumption is
50213 	 * easy to accidentally break, so such code must be written carefully.
50214 	 * See test-bi-array-push-maxlen.js.
50215 	 */
50216 
50217 	rc = duk__get_own_propdesc_raw(thr, obj, DUK_HTHREAD_STRING_LENGTH(thr), DUK__NO_ARRAY_INDEX, temp_desc, 0 /*flags*/);  /* don't push value */
50218 	DUK_UNREF(rc);
50219 	DUK_ASSERT(rc != 0);  /* arrays MUST have a 'length' property */
50220 	DUK_ASSERT(temp_desc->e_idx >= 0);
50221 
50222 	tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, temp_desc->e_idx);
50223 	DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));  /* array 'length' is always a number, as we coerce it */
50224 	DUK_ASSERT(DUK_TVAL_GET_NUMBER(tv) >= 0.0);
50225 	DUK_ASSERT(DUK_TVAL_GET_NUMBER(tv) <= (double) 0xffffffffUL);
50226 	DUK_ASSERT((duk_double_t) (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv) == DUK_TVAL_GET_NUMBER(tv));
50227 #if defined(DUK_USE_FASTINT)
50228 	/* Downgrade checks are not made everywhere, so 'length' is not always
50229 	 * a fastint (it is a number though).  This can be removed once length
50230 	 * is always guaranteed to be a fastint.
50231 	 */
50232 	DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv) || DUK_TVAL_IS_DOUBLE(tv));
50233 	if (DUK_TVAL_IS_FASTINT(tv)) {
50234 		res = (duk_uint32_t) DUK_TVAL_GET_FASTINT_U32(tv);
50235 	} else {
50236 		res = (duk_uint32_t) DUK_TVAL_GET_DOUBLE(tv);
50237 	}
50238 #else
50239 	res = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv);
50240 #endif  /* DUK_USE_FASTINT */
50241 
50242 	return res;
50243 }
50244 
50245 DUK_LOCAL duk_uint32_t duk__to_new_array_length_checked(duk_hthread *thr) {
50246 	duk_context *ctx = (duk_context *) thr;
50247 	duk_uint32_t res;
50248 	duk_double_t d;
50249 
50250 	/* Input value should be on stack top and will be coerced and
50251 	 * popped.  Refuse to update an Array's 'length' to a value
50252 	 * outside the 32-bit range.  Negative zero is accepted as zero.
50253 	 */
50254 
50255 	/* XXX: fastint */
50256 
50257 	d = duk_to_number(ctx, -1);
50258 	res = (duk_uint32_t) d;
50259 	if ((duk_double_t) res != d) {
50260 		DUK_ERROR_RANGE(thr, DUK_STR_INVALID_ARRAY_LENGTH);
50261 	}
50262 	duk_pop(ctx);
50263 	return res;
50264 }
50265 
50266 /* Delete elements required by a smaller length, taking into account
50267  * potentially non-configurable elements.  Returns non-zero if all
50268  * elements could be deleted, and zero if all or some elements could
50269  * not be deleted.  Also writes final "target length" to 'out_result_len'.
50270  * This is the length value that should go into the 'length' property
50271  * (must be set by the caller).  Never throws an error.
50272  */
50273 DUK_LOCAL
50274 duk_bool_t duk__handle_put_array_length_smaller(duk_hthread *thr,
50275                                                 duk_hobject *obj,
50276                                                 duk_uint32_t old_len,
50277                                                 duk_uint32_t new_len,
50278                                                 duk_bool_t force_flag,
50279                                                 duk_uint32_t *out_result_len) {
50280 	duk_uint32_t target_len;
50281 	duk_uint_fast32_t i;
50282 	duk_uint32_t arr_idx;
50283 	duk_hstring *key;
50284 	duk_tval *tv;
50285 	duk_bool_t rc;
50286 
50287 	DUK_DDD(DUK_DDDPRINT("new array length smaller than old (%ld -> %ld), "
50288 	                     "probably need to remove elements",
50289 	                     (long) old_len, (long) new_len));
50290 
50291 	/*
50292 	 *  New length is smaller than old length, need to delete properties above
50293 	 *  the new length.
50294 	 *
50295 	 *  If array part exists, this is straightforward: array entries cannot
50296 	 *  be non-configurable so this is guaranteed to work.
50297 	 *
50298 	 *  If array part does not exist, array-indexed values are scattered
50299 	 *  in the entry part, and some may not be configurable (preventing length
50300 	 *  from becoming lower than their index + 1).  To handle the algorithm
50301 	 *  in E5 Section 15.4.5.1, step l correctly, we scan the entire property
50302 	 *  set twice.
50303 	 */
50304 
50305 	DUK_ASSERT(thr != NULL);
50306 	DUK_ASSERT(obj != NULL);
50307 	DUK_ASSERT(new_len < old_len);
50308 	DUK_ASSERT(out_result_len != NULL);
50309 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
50310 
50311 	if (DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
50312 		/*
50313 		 *  All defined array-indexed properties are in the array part
50314 		 *  (we assume the array part is comprehensive), and all array
50315 		 *  entries are writable, configurable, and enumerable.  Thus,
50316 		 *  nothing can prevent array entries from being deleted.
50317 		 */
50318 
50319 		DUK_DDD(DUK_DDDPRINT("have array part, easy case"));
50320 
50321 		if (old_len < DUK_HOBJECT_GET_ASIZE(obj)) {
50322 			/* XXX: assertion that entries >= old_len are already unused */
50323 			i = old_len;
50324 		} else {
50325 			i = DUK_HOBJECT_GET_ASIZE(obj);
50326 		}
50327 		DUK_ASSERT(i <= DUK_HOBJECT_GET_ASIZE(obj));
50328 
50329 		while (i > new_len) {
50330 			i--;
50331 			tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, i);
50332 			DUK_TVAL_SET_UNUSED_UPDREF(thr, tv);  /* side effects */
50333 		}
50334 
50335 		*out_result_len = new_len;
50336 		return 1;
50337 	} else {
50338 		/*
50339 		 *  Entries part is a bit more complex
50340 		 */
50341 
50342 		/* Stage 1: find highest preventing non-configurable entry (if any).
50343 		 * When forcing, ignore non-configurability.
50344 		 */
50345 
50346 		DUK_DDD(DUK_DDDPRINT("no array part, slow case"));
50347 
50348 		DUK_DDD(DUK_DDDPRINT("array length write, no array part, stage 1: find target_len "
50349 		                     "(highest preventing non-configurable entry (if any))"));
50350 
50351 		target_len = new_len;
50352 		if (force_flag) {
50353 			DUK_DDD(DUK_DDDPRINT("array length write, no array part; force flag -> skip stage 1"));
50354 			goto skip_stage1;
50355 		}
50356 		for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
50357 			key = DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i);
50358 			if (!key) {
50359 				DUK_DDD(DUK_DDDPRINT("skip entry index %ld: null key", (long) i));
50360 				continue;
50361 			}
50362 			if (!DUK_HSTRING_HAS_ARRIDX(key)) {
50363 				DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key not an array index", (long) i));
50364 				continue;
50365 			}
50366 
50367 			DUK_ASSERT(DUK_HSTRING_HAS_ARRIDX(key));  /* XXX: macro checks for array index flag, which is unnecessary here */
50368 			arr_idx = DUK_HSTRING_GET_ARRIDX_SLOW(key);
50369 			DUK_ASSERT(arr_idx != DUK__NO_ARRAY_INDEX);
50370 			DUK_ASSERT(arr_idx < old_len);  /* consistency requires this */
50371 
50372 			if (arr_idx < new_len) {
50373 				DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key is array index %ld, below new_len",
50374 				                     (long) i, (long) arr_idx));
50375 				continue;
50376 			}
50377 			if (DUK_HOBJECT_E_SLOT_IS_CONFIGURABLE(thr->heap, obj, i)) {
50378 				DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key is a relevant array index %ld, but configurable",
50379 				                     (long) i, (long) arr_idx));
50380 				continue;
50381 			}
50382 
50383 			/* relevant array index is non-configurable, blocks write */
50384 			if (arr_idx >= target_len) {
50385 				DUK_DDD(DUK_DDDPRINT("entry at index %ld has arr_idx %ld, is not configurable, "
50386 				                     "update target_len %ld -> %ld",
50387 				                     (long) i, (long) arr_idx, (long) target_len,
50388 				                     (long) (arr_idx + 1)));
50389 				target_len = arr_idx + 1;
50390 			}
50391 		}
50392 	 skip_stage1:
50393 
50394 		/* stage 2: delete configurable entries above target length */
50395 
50396 		DUK_DDD(DUK_DDDPRINT("old_len=%ld, new_len=%ld, target_len=%ld",
50397 		                     (long) old_len, (long) new_len, (long) target_len));
50398 
50399 		DUK_DDD(DUK_DDDPRINT("array length write, no array part, stage 2: remove "
50400 		                     "entries >= target_len"));
50401 
50402 		for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
50403 			key = DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i);
50404 			if (!key) {
50405 				DUK_DDD(DUK_DDDPRINT("skip entry index %ld: null key", (long) i));
50406 				continue;
50407 			}
50408 			if (!DUK_HSTRING_HAS_ARRIDX(key)) {
50409 				DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key not an array index", (long) i));
50410 				continue;
50411 			}
50412 
50413 			DUK_ASSERT(DUK_HSTRING_HAS_ARRIDX(key));  /* XXX: macro checks for array index flag, which is unnecessary here */
50414 			arr_idx = DUK_HSTRING_GET_ARRIDX_SLOW(key);
50415 			DUK_ASSERT(arr_idx != DUK__NO_ARRAY_INDEX);
50416 			DUK_ASSERT(arr_idx < old_len);  /* consistency requires this */
50417 
50418 			if (arr_idx < target_len) {
50419 				DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key is array index %ld, below target_len",
50420 				                     (long) i, (long) arr_idx));
50421 				continue;
50422 			}
50423 			DUK_ASSERT(force_flag || DUK_HOBJECT_E_SLOT_IS_CONFIGURABLE(thr->heap, obj, i));  /* stage 1 guarantees */
50424 
50425 			DUK_DDD(DUK_DDDPRINT("delete entry index %ld: key is array index %ld",
50426 			                     (long) i, (long) arr_idx));
50427 
50428 			/*
50429 			 *  Slow delete, but we don't care as we're already in a very slow path.
50430 			 *  The delete always succeeds: key has no exotic behavior, property
50431 			 *  is configurable, and no resize occurs.
50432 			 */
50433 			rc = duk_hobject_delprop_raw(thr, obj, key, force_flag ? DUK_DELPROP_FLAG_FORCE : 0);
50434 			DUK_UNREF(rc);
50435 			DUK_ASSERT(rc != 0);
50436 		}
50437 
50438 		/* stage 3: update length (done by caller), decide return code */
50439 
50440 		DUK_DDD(DUK_DDDPRINT("array length write, no array part, stage 3: update length (done by caller)"));
50441 
50442 		*out_result_len = target_len;
50443 
50444 		if (target_len == new_len) {
50445 			DUK_DDD(DUK_DDDPRINT("target_len matches new_len, return success"));
50446 			return 1;
50447 		}
50448 		DUK_DDD(DUK_DDDPRINT("target_len does not match new_len (some entry prevented "
50449 		                     "full length adjustment), return error"));
50450 		return 0;
50451 	}
50452 
50453 	DUK_UNREACHABLE();
50454 }
50455 
50456 /* XXX: is valstack top best place for argument? */
50457 DUK_LOCAL duk_bool_t duk__handle_put_array_length(duk_hthread *thr, duk_hobject *obj) {
50458 	duk_context *ctx = (duk_context *) thr;
50459 	duk_propdesc desc;
50460 	duk_uint32_t old_len;
50461 	duk_uint32_t new_len;
50462 	duk_uint32_t result_len;
50463 	duk_tval *tv;
50464 	duk_bool_t rc;
50465 
50466 	DUK_DDD(DUK_DDDPRINT("handling a put operation to array 'length' exotic property, "
50467 	                     "new val: %!T",
50468 	                     (duk_tval *) duk_get_tval(ctx, -1)));
50469 
50470 	DUK_ASSERT(thr != NULL);
50471 	DUK_ASSERT(ctx != NULL);
50472 	DUK_ASSERT(obj != NULL);
50473 
50474 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
50475 
50476 	DUK_ASSERT(duk_is_valid_index(ctx, -1));
50477 
50478 	/*
50479 	 *  Get old and new length
50480 	 */
50481 
50482 	old_len = duk__get_old_array_length(thr, obj, &desc);
50483 	duk_dup(ctx, -1);  /* [in_val in_val] */
50484 	new_len = duk__to_new_array_length_checked(thr);  /* -> [in_val] */
50485 	DUK_DDD(DUK_DDDPRINT("old_len=%ld, new_len=%ld", (long) old_len, (long) new_len));
50486 
50487 	/*
50488 	 *  Writability check
50489 	 */
50490 
50491 	if (!(desc.flags & DUK_PROPDESC_FLAG_WRITABLE)) {
50492 		DUK_DDD(DUK_DDDPRINT("length is not writable, fail"));
50493 		return 0;
50494 	}
50495 
50496 	/*
50497 	 *  New length not lower than old length => no changes needed
50498 	 *  (not even array allocation).
50499 	 */
50500 
50501 	if (new_len >= old_len) {
50502 		DUK_DDD(DUK_DDDPRINT("new length is higher than old length, just update length, no deletions"));
50503 
50504 		DUK_ASSERT(desc.e_idx >= 0);
50505 		DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, desc.e_idx));
50506 		tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, desc.e_idx);
50507 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
50508 		/* no decref needed for a number */
50509 		DUK_TVAL_SET_FASTINT_U32(tv, new_len);
50510 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
50511 		return 1;
50512 	}
50513 
50514 	DUK_DDD(DUK_DDDPRINT("new length is lower than old length, probably must delete entries"));
50515 
50516 	/*
50517 	 *  New length lower than old length => delete elements, then
50518 	 *  update length.
50519 	 *
50520 	 *  Note: even though a bunch of elements have been deleted, the 'desc' is
50521 	 *  still valid as properties haven't been resized (and entries compacted).
50522 	 */
50523 
50524 	rc = duk__handle_put_array_length_smaller(thr, obj, old_len, new_len, 0 /*force_flag*/, &result_len);
50525 	DUK_ASSERT(result_len >= new_len && result_len <= old_len);
50526 
50527 	DUK_ASSERT(desc.e_idx >= 0);
50528 	DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, desc.e_idx));
50529 	tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, desc.e_idx);
50530 	DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
50531 	/* no decref needed for a number */
50532 	DUK_TVAL_SET_FASTINT_U32(tv, result_len);
50533 	DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
50534 
50535 	/* XXX: shrink array allocation or entries compaction here? */
50536 
50537 	return rc;
50538 }
50539 
50540 /*
50541  *  PUTPROP: Ecmascript property write.
50542  *
50543  *  Unlike Ecmascript primitive which returns nothing, returns 1 to indicate
50544  *  success and 0 to indicate failure (assuming throw is not set).
50545  *
50546  *  This is an extremely tricky function.  Some examples:
50547  *
50548  *    * Currently a decref may trigger a GC, which may compact an object's
50549  *      property allocation.  Consequently, any entry indices (e_idx) will
50550  *      be potentially invalidated by a decref.
50551  *
50552  *    * Exotic behaviors (strings, arrays, arguments object) require,
50553  *      among other things:
50554  *
50555  *      - Preprocessing before and postprocessing after an actual property
50556  *        write.  For example, array index write requires pre-checking the
50557  *        array 'length' property for access control, and may require an
50558  *        array 'length' update after the actual write has succeeded (but
50559  *        not if it fails).
50560  *
50561  *      - Deletion of multiple entries, as a result of array 'length' write.
50562  *
50563  *    * Input values are taken as pointers which may point to the valstack.
50564  *      If valstack is resized because of the put (this may happen at least
50565  *      when the array part is abandoned), the pointers can be invalidated.
50566  *      (We currently make a copy of all of the input values to avoid issues.)
50567  */
50568 
50569 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) {
50570 	duk_context *ctx = (duk_context *) thr;
50571 	duk_tval tv_obj_copy;
50572 	duk_tval tv_key_copy;
50573 	duk_tval tv_val_copy;
50574 	duk_hobject *orig = NULL;  /* NULL if tv_obj is primitive */
50575 	duk_hobject *curr;
50576 	duk_hstring *key = NULL;
50577 	duk_propdesc desc;
50578 	duk_tval *tv;
50579 	duk_uint32_t arr_idx;
50580 	duk_bool_t rc;
50581 	duk_int_t e_idx;
50582 	duk_uint_t sanity;
50583 	duk_uint32_t new_array_length = 0;  /* 0 = no update */
50584 
50585 	DUK_DDD(DUK_DDDPRINT("putprop: thr=%p, obj=%p, key=%p, val=%p, throw=%ld "
50586 	                     "(obj -> %!T, key -> %!T, val -> %!T)",
50587 	                     (void *) thr, (void *) tv_obj, (void *) tv_key, (void *) tv_val,
50588 	                     (long) throw_flag, (duk_tval *) tv_obj, (duk_tval *) tv_key, (duk_tval *) tv_val));
50589 
50590 	DUK_ASSERT(thr != NULL);
50591 	DUK_ASSERT(thr->heap != NULL);
50592 	DUK_ASSERT(ctx != NULL);
50593 	DUK_ASSERT(tv_obj != NULL);
50594 	DUK_ASSERT(tv_key != NULL);
50595 	DUK_ASSERT(tv_val != NULL);
50596 
50597 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
50598 
50599 	/*
50600 	 *  Make a copy of tv_obj, tv_key, and tv_val to avoid any issues of
50601 	 *  them being invalidated by a valstack resize.
50602 	 *
50603 	 *  XXX: this is an overkill for some paths, so optimize this later
50604 	 *  (or maybe switch to a stack arguments model entirely).
50605 	 */
50606 
50607 	DUK_TVAL_SET_TVAL(&tv_obj_copy, tv_obj);
50608 	DUK_TVAL_SET_TVAL(&tv_key_copy, tv_key);
50609 	DUK_TVAL_SET_TVAL(&tv_val_copy, tv_val);
50610 	tv_obj = &tv_obj_copy;
50611 	tv_key = &tv_key_copy;
50612 	tv_val = &tv_val_copy;
50613 
50614 	/*
50615 	 *  Coercion and fast path processing.
50616 	 */
50617 
50618 	switch (DUK_TVAL_GET_TAG(tv_obj)) {
50619 	case DUK_TAG_UNDEFINED:
50620 	case DUK_TAG_NULL: {
50621 		/* Note: unconditional throw */
50622 		DUK_DDD(DUK_DDDPRINT("base object is undefined or null -> reject (object=%!iT)",
50623 		                     (duk_tval *) tv_obj));
50624 #if defined(DUK_USE_PARANOID_ERRORS)
50625 		DUK_ERROR_TYPE(thr, DUK_STR_INVALID_BASE);
50626 #else
50627 		DUK_ERROR_FMT2(thr, DUK_ERR_TYPE_ERROR, "cannot write property %s of %s",
50628 		               duk_push_string_tval_readable(ctx, tv_key), duk_push_string_tval_readable(ctx, tv_obj));
50629 #endif
50630 		return 0;
50631 	}
50632 
50633 	case DUK_TAG_BOOLEAN: {
50634 		DUK_DDD(DUK_DDDPRINT("base object is a boolean, start lookup from boolean prototype"));
50635 		curr = thr->builtins[DUK_BIDX_BOOLEAN_PROTOTYPE];
50636 		break;
50637 	}
50638 
50639 	case DUK_TAG_STRING: {
50640 		duk_hstring *h = DUK_TVAL_GET_STRING(tv_obj);
50641 
50642 		/*
50643 		 *  Note: currently no fast path for array index writes.
50644 		 *  They won't be possible anyway as strings are immutable.
50645 		 */
50646 
50647 		DUK_ASSERT(key == NULL);
50648 		arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
50649 		DUK_ASSERT(key != NULL);
50650 
50651 		if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
50652 			goto fail_not_writable;
50653 		}
50654 
50655 		if (arr_idx != DUK__NO_ARRAY_INDEX &&
50656 		    arr_idx < DUK_HSTRING_GET_CHARLEN(h)) {
50657 			goto fail_not_writable;
50658 		}
50659 
50660 		DUK_DDD(DUK_DDDPRINT("base object is a string, start lookup from string prototype"));
50661 		curr = thr->builtins[DUK_BIDX_STRING_PROTOTYPE];
50662 		goto lookup;  /* avoid double coercion */
50663 	}
50664 
50665 	case DUK_TAG_OBJECT: {
50666 		orig = DUK_TVAL_GET_OBJECT(tv_obj);
50667 		DUK_ASSERT(orig != NULL);
50668 
50669 #if defined(DUK_USE_ROM_OBJECTS)
50670 		/* With this check in place fast paths won't need read-only
50671 		 * object checks.  This is technically incorrect if there are
50672 		 * setters that cause no writes to ROM objects, but current
50673 		 * built-ins don't have such setters.
50674 		 */
50675 		if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) orig)) {
50676 			DUK_DD(DUK_DDPRINT("attempt to putprop on read-only target object"));
50677 			goto fail_not_writable_no_pop;  /* Must avoid duk_pop() in exit path */
50678 		}
50679 #endif
50680 
50681 		/* The fast path for array property put is not fully compliant:
50682 		 * If one places conflicting number-indexed properties into
50683 		 * Array.prototype (for example, a non-writable Array.prototype[7])
50684 		 * the fast path will incorrectly ignore them.
50685 		 *
50686 		 * This fast path could be made compliant by falling through
50687 		 * to the slow path if the previous value was UNUSED.  This would
50688 		 * also remove the need to check for extensibility.  Right now a
50689 		 * non-extensible array is slower than an extensible one as far
50690 		 * as writes are concerned.
50691 		 *
50692 		 * The fast path behavior is documented in more detail here:
50693 		 * tests/ecmascript/test-misc-array-fast-write.js
50694 		 */
50695 
50696 		if (duk__putprop_shallow_fastpath_array_tval(thr, orig, tv_key, tv_val, &desc) != 0) {
50697 			DUK_DDD(DUK_DDDPRINT("array fast path success"));
50698 			return 1;
50699 		}
50700 
50701 		if (duk__putprop_fastpath_bufobj_tval(thr, orig, tv_key, tv_val) != 0) {
50702 			DUK_DDD(DUK_DDDPRINT("base is bufobj, key is a number, bufferobject fast path"));
50703 			return 1;
50704 		}
50705 
50706 #if defined(DUK_USE_ES6_PROXY)
50707 		if (DUK_UNLIKELY(DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(orig))) {
50708 			duk_hobject *h_target;
50709 			duk_bool_t tmp_bool;
50710 
50711 			if (duk__proxy_check_prop(thr, orig, DUK_STRIDX_SET, tv_key, &h_target)) {
50712 				/* -> [ ... trap handler ] */
50713 				DUK_DDD(DUK_DDDPRINT("-> proxy object 'set' for key %!T", (duk_tval *) tv_key));
50714 				duk_push_hobject(ctx, h_target);  /* target */
50715 				duk_push_tval(ctx, tv_key);       /* P */
50716 				duk_push_tval(ctx, tv_val);       /* V */
50717 				duk_push_tval(ctx, tv_obj);       /* Receiver: Proxy object */
50718 				duk_call_method(ctx, 4 /*nargs*/);
50719 				tmp_bool = duk_to_boolean(ctx, -1);
50720 				duk_pop(ctx);
50721 				if (!tmp_bool) {
50722 					goto fail_proxy_rejected;
50723 				}
50724 
50725 				/* Target object must be checked for a conflicting
50726 				 * non-configurable property.
50727 				 */
50728 				arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
50729 				DUK_ASSERT(key != NULL);
50730 
50731 				if (duk__get_own_propdesc_raw(thr, h_target, key, arr_idx, &desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
50732 					duk_tval *tv_targ = duk_require_tval(ctx, -1);
50733 					duk_bool_t datadesc_reject;
50734 					duk_bool_t accdesc_reject;
50735 
50736 					DUK_DDD(DUK_DDDPRINT("proxy 'set': target has matching property %!O, check for "
50737 					                     "conflicting property; tv_val=%!T, tv_targ=%!T, desc.flags=0x%08lx, "
50738 					                     "desc.get=%p, desc.set=%p",
50739 					                     (duk_heaphdr *) key, (duk_tval *) tv_val, (duk_tval *) tv_targ,
50740 					                     (unsigned long) desc.flags,
50741 					                     (void *) desc.get, (void *) desc.set));
50742 
50743 					datadesc_reject = !(desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
50744 					                  !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) &&
50745 					                  !(desc.flags & DUK_PROPDESC_FLAG_WRITABLE) &&
50746 					                  !duk_js_samevalue(tv_val, tv_targ);
50747 					accdesc_reject = (desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
50748 					                 !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) &&
50749 					                 (desc.set == NULL);
50750 					if (datadesc_reject || accdesc_reject) {
50751 						DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);
50752 					}
50753 
50754 					duk_pop_2(ctx);
50755 				} else {
50756 					duk_pop(ctx);
50757 				}
50758 				return 1;  /* success */
50759 			}
50760 
50761 			orig = h_target;  /* resume write to target */
50762 			DUK_TVAL_SET_OBJECT(tv_obj, orig);
50763 		}
50764 #endif  /* DUK_USE_ES6_PROXY */
50765 
50766 		curr = orig;
50767 		break;
50768 	}
50769 
50770 	case DUK_TAG_BUFFER: {
50771 		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv_obj);
50772 		duk_int_t pop_count = 0;
50773 
50774 		/*
50775 		 *  Because buffer values may be looped over and read/written
50776 		 *  from, an array index fast path is important.
50777 		 */
50778 
50779 #if defined(DUK_USE_FASTINT)
50780 		if (DUK_TVAL_IS_FASTINT(tv_key)) {
50781 			arr_idx = duk__tval_fastint_to_arr_idx(tv_key);
50782 			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a fast-path fastint; arr_idx %ld", (long) arr_idx));
50783 			pop_count = 0;
50784 		} else
50785 #endif
50786 		if (DUK_TVAL_IS_NUMBER(tv_key)) {
50787 			arr_idx = duk__tval_number_to_arr_idx(tv_key);
50788 			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a fast-path number; arr_idx %ld", (long) arr_idx));
50789 			pop_count = 0;
50790 		} else {
50791 			arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
50792 			DUK_ASSERT(key != NULL);
50793 			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a non-fast-path number; after "
50794 			                     "coercion key is %!T, arr_idx %ld",
50795 			                     (duk_tval *) duk_get_tval(ctx, -1), (long) arr_idx));
50796 			pop_count = 1;
50797 		}
50798 
50799 		if (arr_idx != DUK__NO_ARRAY_INDEX &&
50800 		    arr_idx < DUK_HBUFFER_GET_SIZE(h)) {
50801 			duk_uint8_t *data;
50802 			DUK_DDD(DUK_DDDPRINT("writing to buffer data at index %ld", (long) arr_idx));
50803 			data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h);
50804 
50805 			/* XXX: duk_to_int() ensures we'll get 8 lowest bits as
50806 			 * as input is within duk_int_t range (capped outside it).
50807 			 */
50808 #if defined(DUK_USE_FASTINT)
50809 			/* Buffer writes are often integers. */
50810 			if (DUK_TVAL_IS_FASTINT(tv_val)) {
50811 				data[arr_idx] = (duk_uint8_t) DUK_TVAL_GET_FASTINT_U32(tv_val);
50812 			}
50813 			else
50814 #endif
50815 			{
50816 				duk_push_tval(ctx, tv_val);
50817 				data[arr_idx] = (duk_uint8_t) duk_to_uint32(ctx, -1);
50818 				pop_count++;
50819 			}
50820 
50821 			duk_pop_n(ctx, pop_count);
50822 			DUK_DDD(DUK_DDDPRINT("result: success (buffer data write)"));
50823 			return 1;
50824 		}
50825 
50826 		if (pop_count == 0) {
50827 			/* This is a pretty awkward control flow, but we need to recheck the
50828 			 * key coercion here.
50829 			 */
50830 			arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
50831 			DUK_ASSERT(key != NULL);
50832 			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a non-fast-path number; after "
50833 			                     "coercion key is %!T, arr_idx %ld",
50834 			                     (duk_tval *) duk_get_tval(ctx, -1), (long) arr_idx));
50835 		}
50836 
50837 		if (key == DUK_HTHREAD_STRING_LENGTH(thr) ||
50838 		    key == DUK_HTHREAD_STRING_BYTE_LENGTH(thr) ||
50839 		    key == DUK_HTHREAD_STRING_BYTE_OFFSET(thr) ||
50840 		    key == DUK_HTHREAD_STRING_BYTES_PER_ELEMENT(thr)) {
50841 			goto fail_not_writable;
50842 		}
50843 
50844 		DUK_DDD(DUK_DDDPRINT("base object is a buffer, start lookup from buffer prototype"));
50845 		curr = thr->builtins[DUK_BIDX_BUFFER_PROTOTYPE];
50846 		goto lookup;  /* avoid double coercion */
50847 	}
50848 
50849 	case DUK_TAG_POINTER: {
50850 		DUK_DDD(DUK_DDDPRINT("base object is a pointer, start lookup from pointer prototype"));
50851 		curr = thr->builtins[DUK_BIDX_POINTER_PROTOTYPE];
50852 		break;
50853 	}
50854 
50855 	case DUK_TAG_LIGHTFUNC: {
50856 		/* All lightfunc own properties are non-writable and the lightfunc
50857 		 * is considered non-extensible.  However, the write may be captured
50858 		 * by an inherited setter which means we can't stop the lookup here.
50859 		 */
50860 
50861 		arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
50862 
50863 		if (duk__key_is_lightfunc_ownprop(thr, key)) {
50864 			goto fail_not_writable;
50865 		}
50866 
50867 		DUK_DDD(DUK_DDDPRINT("base object is a lightfunc, start lookup from function prototype"));
50868 		curr = thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE];
50869 		goto lookup;  /* avoid double coercion */
50870 	}
50871 
50872 #if defined(DUK_USE_FASTINT)
50873 	case DUK_TAG_FASTINT:
50874 #endif
50875 	default: {
50876 		/* number */
50877 		DUK_DDD(DUK_DDDPRINT("base object is a number, start lookup from number prototype"));
50878 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_obj));
50879 		curr = thr->builtins[DUK_BIDX_NUMBER_PROTOTYPE];
50880 		break;
50881 	}
50882 	}
50883 
50884 	DUK_ASSERT(key == NULL);
50885 	arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
50886 	DUK_ASSERT(key != NULL);
50887 
50888  lookup:
50889 
50890 	/*
50891 	 *  Check whether the property already exists in the prototype chain.
50892 	 *  Note that the actual write goes into the original base object
50893 	 *  (except if an accessor property captures the write).
50894 	 */
50895 
50896 	/* [key] */
50897 
50898 	DUK_ASSERT(curr != NULL);
50899 	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
50900 	do {
50901 		if (!duk__get_own_propdesc_raw(thr, curr, key, arr_idx, &desc, 0 /*flags*/)) {  /* don't push value */
50902 			goto next_in_chain;
50903 		}
50904 
50905 		if (desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
50906 			/*
50907 			 *  Found existing accessor property (own or inherited).
50908 			 *  Call setter with 'this' set to orig, and value as the only argument.
50909 			 *  Setter calls are OK even for ROM objects.
50910 			 *
50911 			 *  Note: no exotic arguments object behavior, because [[Put]] never
50912 			 *  calls [[DefineOwnProperty]] (E5 Section 8.12.5, step 5.b).
50913 			 */
50914 
50915 			duk_hobject *setter;
50916 
50917 			DUK_DD(DUK_DDPRINT("put to an own or inherited accessor, calling setter"));
50918 
50919 			setter = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, curr, desc.e_idx);
50920 			if (!setter) {
50921 				goto fail_no_setter;
50922 			}
50923 			duk_push_hobject(ctx, setter);
50924 			duk_push_tval(ctx, tv_obj);  /* note: original, uncoerced base */
50925 			duk_push_tval(ctx, tv_val);  /* [key setter this val] */
50926 #ifdef DUK_USE_NONSTD_SETTER_KEY_ARGUMENT
50927 			duk_dup(ctx, -4);
50928 			duk_call_method(ctx, 2);     /* [key setter this val key] -> [key retval] */
50929 #else
50930 			duk_call_method(ctx, 1);     /* [key setter this val] -> [key retval] */
50931 #endif
50932 			duk_pop(ctx);                /* ignore retval -> [key] */
50933 			goto success_no_arguments_exotic;
50934 		}
50935 
50936 		if (orig == NULL) {
50937 			/*
50938 			 *  Found existing own or inherited plain property, but original
50939 			 *  base is a primitive value.
50940 			 */
50941 			DUK_DD(DUK_DDPRINT("attempt to create a new property in a primitive base object"));
50942 			goto fail_base_primitive;
50943 		}
50944 
50945 		if (curr != orig) {
50946 			/*
50947 			 *  Found existing inherited plain property.
50948 			 *  Do an access control check, and if OK, write
50949 			 *  new property to 'orig'.
50950 			 */
50951 			if (!DUK_HOBJECT_HAS_EXTENSIBLE(orig)) {
50952 				DUK_DD(DUK_DDPRINT("found existing inherited plain property, but original object is not extensible"));
50953 				goto fail_not_extensible;
50954 			}
50955 			if (!(desc.flags & DUK_PROPDESC_FLAG_WRITABLE)) {
50956 				DUK_DD(DUK_DDPRINT("found existing inherited plain property, original object is extensible, but inherited property is not writable"));
50957 				goto fail_not_writable;
50958 			}
50959 			DUK_DD(DUK_DDPRINT("put to new property, object extensible, inherited property found and is writable"));
50960 			goto create_new;
50961 		} else {
50962 			/*
50963 			 *  Found existing own (non-inherited) plain property.
50964 			 *  Do an access control check and update in place.
50965 			 */
50966 
50967 			if (!(desc.flags & DUK_PROPDESC_FLAG_WRITABLE)) {
50968 				DUK_DD(DUK_DDPRINT("found existing own (non-inherited) plain property, but property is not writable"));
50969 				goto fail_not_writable;
50970 			}
50971 			if (desc.flags & DUK_PROPDESC_FLAG_VIRTUAL) {
50972 				DUK_DD(DUK_DDPRINT("found existing own (non-inherited) virtual property, property is writable"));
50973 				if (DUK_HOBJECT_IS_BUFFEROBJECT(curr)) {
50974 					duk_hbufferobject *h_bufobj;
50975 					duk_uint_t byte_off;
50976 					duk_small_uint_t elem_size;
50977 
50978 					h_bufobj = (duk_hbufferobject *) curr;
50979 					DUK_ASSERT_HBUFFEROBJECT_VALID(h_bufobj);
50980 
50981 					DUK_DD(DUK_DDPRINT("writable virtual property is in buffer object"));
50982 
50983 					/* Careful with wrapping: arr_idx upshift may easily wrap, whereas
50984 					 * length downshift won't.
50985 					 */
50986 					if (arr_idx < (h_bufobj->length >> h_bufobj->shift)) {
50987 						duk_uint8_t *data;
50988 						DUK_DDD(DUK_DDDPRINT("writing to buffer data at index %ld", (long) arr_idx));
50989 
50990 						DUK_ASSERT(arr_idx != DUK__NO_ARRAY_INDEX);  /* index/length check guarantees */
50991 						byte_off = arr_idx << h_bufobj->shift;       /* no wrap assuming h_bufobj->length is valid */
50992 						elem_size = 1 << h_bufobj->shift;
50993 
50994 						/* Coerce to number before validating pointers etc so that the
50995 						 * number coercions in duk_hbufferobject_validated_write() are
50996 						 * guaranteed to be side effect free and not invalidate the
50997 						 * pointer checks we do here.
50998 						 */
50999 						duk_push_tval(ctx, tv_val);
51000 						duk_to_number(ctx, -1);
51001 
51002 						if (h_bufobj->buf != NULL && DUK_HBUFFEROBJECT_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) {
51003 							data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) + h_bufobj->offset + byte_off;
51004 							duk_hbufferobject_validated_write(ctx, h_bufobj, data, elem_size);
51005 						} else {
51006 							DUK_D(DUK_DPRINT("bufferobject access out of underlying buffer, ignoring (write skipped)"));
51007 						}
51008 						duk_pop(ctx);
51009 						goto success_no_arguments_exotic;
51010 					}
51011 				}
51012 
51013 				goto fail_internal;  /* should not happen */
51014 			}
51015 			DUK_DD(DUK_DDPRINT("put to existing own plain property, property is writable"));
51016 			goto update_old;
51017 		}
51018 		DUK_UNREACHABLE();
51019 
51020 	 next_in_chain:
51021 		/* XXX: option to pretend property doesn't exist if sanity limit is
51022 		 * hit might be useful.
51023 		 */
51024 		if (sanity-- == 0) {
51025 			DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
51026 		}
51027 		curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr);
51028 	} while (curr);
51029 
51030 	/*
51031 	 *  Property not found in prototype chain.
51032 	 */
51033 
51034 	DUK_DDD(DUK_DDDPRINT("property not found in prototype chain"));
51035 
51036 	if (orig == NULL) {
51037 		DUK_DD(DUK_DDPRINT("attempt to create a new property in a primitive base object"));
51038 		goto fail_base_primitive;
51039 	}
51040 
51041 	if (!DUK_HOBJECT_HAS_EXTENSIBLE(orig)) {
51042 		DUK_DD(DUK_DDPRINT("put to a new property (not found in prototype chain), but original object not extensible"));
51043 		goto fail_not_extensible;
51044 	}
51045 
51046 	goto create_new;
51047 
51048  update_old:
51049 
51050 	/*
51051 	 *  Update an existing property of the base object.
51052 	 */
51053 
51054 	/* [key] */
51055 
51056 	DUK_DDD(DUK_DDDPRINT("update an existing property of the original object"));
51057 
51058 	DUK_ASSERT(orig != NULL);
51059 #if defined(DUK_USE_ROM_OBJECTS)
51060 	/* This should not happen because DUK_TAG_OBJECT case checks
51061 	 * for this already, but check just in case.
51062 	 */
51063 	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) orig)) {
51064 		goto fail_not_writable;
51065 	}
51066 #endif
51067 
51068 	/* Although there are writable virtual properties (e.g. plain buffer
51069 	 * and buffer object number indices), they are handled before we come
51070 	 * here.
51071 	 */
51072 	DUK_ASSERT((desc.flags & DUK_PROPDESC_FLAG_VIRTUAL) == 0);
51073 	DUK_ASSERT(desc.a_idx >= 0 || desc.e_idx >= 0);
51074 
51075 	if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(orig) &&
51076 	    key == DUK_HTHREAD_STRING_LENGTH(thr)) {
51077 		/*
51078 		 *  Write to 'length' of an array is a very complex case
51079 		 *  handled in a helper which updates both the array elements
51080 		 *  and writes the new 'length'.  The write may result in an
51081 		 *  unconditional RangeError or a partial write (indicated
51082 		 *  by a return code).
51083 		 *
51084 		 *  Note: the helper has an unnecessary writability check
51085 		 *  for 'length', we already know it is writable.
51086 		 */
51087 
51088 		DUK_DDD(DUK_DDDPRINT("writing existing 'length' property to array exotic, invoke complex helper"));
51089 
51090 		/* XXX: the helper currently assumes stack top contains new
51091 		 * 'length' value and the whole calling convention is not very
51092 		 * compatible with what we need.
51093 		 */
51094 
51095 		duk_push_tval(ctx, tv_val);  /* [key val] */
51096 		rc = duk__handle_put_array_length(thr, orig);
51097 		duk_pop(ctx);  /* [key val] -> [key] */
51098 		if (!rc) {
51099 			goto fail_array_length_partial;
51100 		}
51101 
51102 		/* key is 'length', cannot match argument exotic behavior */
51103 		goto success_no_arguments_exotic;
51104 	}
51105 
51106 	if (desc.e_idx >= 0) {
51107 		tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, orig, desc.e_idx);
51108 		DUK_DDD(DUK_DDDPRINT("previous entry value: %!iT", (duk_tval *) tv));
51109 		DUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv_val);  /* side effects */
51110 		/* don't touch property attributes or hash part */
51111 		DUK_DD(DUK_DDPRINT("put to an existing entry at index %ld -> new value %!iT",
51112 		                   (long) desc.e_idx, (duk_tval *) tv));
51113 	} else {
51114 		/* Note: array entries are always writable, so the writability check
51115 		 * above is pointless for them.  The check could be avoided with some
51116 		 * refactoring but is probably not worth it.
51117 		 */
51118 
51119 		DUK_ASSERT(desc.a_idx >= 0);
51120 		tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, orig, desc.a_idx);
51121 		DUK_DDD(DUK_DDDPRINT("previous array value: %!iT", (duk_tval *) tv));
51122 		DUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv_val);  /* side effects */
51123 		DUK_DD(DUK_DDPRINT("put to an existing array entry at index %ld -> new value %!iT",
51124 		                   (long) desc.a_idx, (duk_tval *) tv));
51125 	}
51126 
51127 	/* Regardless of whether property is found in entry or array part,
51128 	 * it may have arguments exotic behavior (array indices may reside
51129 	 * in entry part for abandoned / non-existent array parts).
51130 	 */
51131 	goto success_with_arguments_exotic;
51132 
51133  create_new:
51134 
51135 	/*
51136 	 *  Create a new property in the original object.
51137 	 *
51138 	 *  Exotic properties need to be reconsidered here from a write
51139 	 *  perspective (not just property attributes perspective).
51140 	 *  However, the property does not exist in the object already,
51141 	 *  so this limits the kind of exotic properties that apply.
51142 	 */
51143 
51144 	/* [key] */
51145 
51146 	DUK_DDD(DUK_DDDPRINT("create new property to original object"));
51147 
51148 	DUK_ASSERT(orig != NULL);
51149 
51150 #if defined(DUK_USE_ROM_OBJECTS)
51151 	/* This should not happen because DUK_TAG_OBJECT case checks
51152 	 * for this already, but check just in case.
51153 	 */
51154 	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) orig)) {
51155 		goto fail_not_writable;
51156 	}
51157 #endif
51158 
51159 	/* Not possible because array object 'length' is present
51160 	 * from its creation and cannot be deleted, and is thus
51161 	 * caught as an existing property above.
51162 	 */
51163 	DUK_ASSERT(!(DUK_HOBJECT_HAS_EXOTIC_ARRAY(orig) &&
51164 	             key == DUK_HTHREAD_STRING_LENGTH(thr)));
51165 
51166 	if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(orig) &&
51167 	    arr_idx != DUK__NO_ARRAY_INDEX) {
51168 		/* automatic length update */
51169 		duk_uint32_t old_len;
51170 
51171 		old_len = duk__get_old_array_length(thr, orig, &desc);
51172 
51173 		if (arr_idx >= old_len) {
51174 			DUK_DDD(DUK_DDDPRINT("write new array entry requires length update "
51175 			                     "(arr_idx=%ld, old_len=%ld)",
51176 			                     (long) arr_idx, (long) old_len));
51177 
51178 			if (!(desc.flags & DUK_PROPDESC_FLAG_WRITABLE)) {
51179 				DUK_DD(DUK_DDPRINT("attempt to extend array, but array 'length' is not writable"));
51180 				goto fail_not_writable;
51181 			}
51182 
51183 			/* Note: actual update happens once write has been completed
51184 			 * without error below.  The write should always succeed
51185 			 * from a specification viewpoint, but we may e.g. run out
51186 			 * of memory.  It's safer in this order.
51187 			 */
51188 
51189 			DUK_ASSERT(arr_idx != 0xffffffffUL);
51190 			new_array_length = arr_idx + 1;  /* flag for later write */
51191 		} else {
51192 			DUK_DDD(DUK_DDDPRINT("write new array entry does not require length update "
51193 			                     "(arr_idx=%ld, old_len=%ld)",
51194 			                     (long) arr_idx, (long) old_len));
51195 		}
51196 	}
51197 
51198  /* write_to_array_part: */
51199 
51200 	/*
51201 	 *  Write to array part?
51202 	 *
51203 	 *  Note: array abandonding requires a property resize which uses
51204 	 *  'rechecks' valstack for temporaries and may cause any existing
51205 	 *  valstack pointers to be invalidated.  To protect against this,
51206 	 *  tv_obj, tv_key, and tv_val are copies of the original inputs.
51207 	 */
51208 
51209 	if (arr_idx != DUK__NO_ARRAY_INDEX &&
51210 	    DUK_HOBJECT_HAS_ARRAY_PART(orig)) {
51211 		if (arr_idx < DUK_HOBJECT_GET_ASIZE(orig)) {
51212 			goto no_array_growth;
51213 		}
51214 
51215 		/*
51216 		 *  Array needs to grow, but we don't want it becoming too sparse.
51217 		 *  If it were to become sparse, abandon array part, moving all
51218 		 *  array entries into the entries part (for good).
51219 		 *
51220 		 *  Since we don't keep track of actual density (used vs. size) of
51221 		 *  the array part, we need to estimate somehow.  The check is made
51222 		 *  in two parts:
51223 		 *
51224 		 *    - Check whether the resize need is small compared to the
51225 		 *      current size (relatively); if so, resize without further
51226 		 *      checking (essentially we assume that the original part is
51227 		 *      "dense" so that the result would be dense enough).
51228 		 *
51229 		 *    - Otherwise, compute the resize using an actual density
51230 		 *      measurement based on counting the used array entries.
51231 		 */
51232 
51233 		DUK_DDD(DUK_DDDPRINT("write to new array requires array resize, decide whether to do a "
51234 		                     "fast resize without abandon check (arr_idx=%ld, old_size=%ld)",
51235 		                     (long) arr_idx, (long) DUK_HOBJECT_GET_ASIZE(orig)));
51236 
51237 		if (duk__abandon_array_slow_check_required(arr_idx, DUK_HOBJECT_GET_ASIZE(orig))) {
51238 			duk_uint32_t old_used;
51239 			duk_uint32_t old_size;
51240 
51241 			DUK_DDD(DUK_DDDPRINT("=> fast check is NOT OK, do slow check for array abandon"));
51242 
51243 			duk__compute_a_stats(thr, orig, &old_used, &old_size);
51244 
51245 			DUK_DDD(DUK_DDDPRINT("abandon check, array stats: old_used=%ld, old_size=%ld, arr_idx=%ld",
51246 			                     (long) old_used, (long) old_size, (long) arr_idx));
51247 
51248 			/* Note: intentionally use approximations to shave a few instructions:
51249 			 *   a_used = old_used  (accurate: old_used + 1)
51250 			 *   a_size = arr_idx   (accurate: arr_idx + 1)
51251 			 */
51252 			if (duk__abandon_array_density_check(old_used, arr_idx)) {
51253 				DUK_DD(DUK_DDPRINT("write to new array entry beyond current length, "
51254 				                   "decided to abandon array part (would become too sparse)"));
51255 
51256 				/* abandoning requires a props allocation resize and
51257 				 * 'rechecks' the valstack, invalidating any existing
51258 				 * valstack value pointers!
51259 				 */
51260 				duk__abandon_array_checked(thr, orig);
51261 				DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(orig));
51262 
51263 				goto write_to_entry_part;
51264 			}
51265 
51266 			DUK_DDD(DUK_DDDPRINT("=> decided to keep array part"));
51267 		} else {
51268 			DUK_DDD(DUK_DDDPRINT("=> fast resize is OK"));
51269 		}
51270 
51271 		DUK_DD(DUK_DDPRINT("write to new array entry beyond current length, "
51272 		                   "decided to extend current allocation"));
51273 
51274 		duk__grow_props_for_array_item(thr, orig, arr_idx);
51275 
51276 	 no_array_growth:
51277 
51278 		/* Note: assume array part is comprehensive, so that either
51279 		 * the write goes to the array part, or we've abandoned the
51280 		 * array above (and will not come here).
51281 		 */
51282 
51283 		DUK_ASSERT(DUK_HOBJECT_HAS_ARRAY_PART(orig));
51284 		DUK_ASSERT(arr_idx < DUK_HOBJECT_GET_ASIZE(orig));
51285 
51286 		tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, orig, arr_idx);
51287 		/* prev value must be unused, no decref */
51288 		DUK_ASSERT(DUK_TVAL_IS_UNUSED(tv));
51289 		DUK_TVAL_SET_TVAL(tv, tv_val);
51290 		DUK_TVAL_INCREF(thr, tv);
51291 		DUK_DD(DUK_DDPRINT("put to new array entry: %ld -> %!T",
51292 		                   (long) arr_idx, (duk_tval *) tv));
51293 
51294 		/* Note: array part values are [[Writable]], [[Enumerable]],
51295 		 * and [[Configurable]] which matches the required attributes
51296 		 * here.
51297 		 */
51298 		goto entry_updated;
51299 	}
51300 
51301  write_to_entry_part:
51302 
51303 	/*
51304 	 *  Write to entry part
51305 	 */
51306 
51307 	/* entry allocation updates hash part and increases the key
51308 	 * refcount; may need a props allocation resize but doesn't
51309 	 * 'recheck' the valstack.
51310 	 */
51311 	e_idx = duk__alloc_entry_checked(thr, orig, key);
51312 	DUK_ASSERT(e_idx >= 0);
51313 
51314 	tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, orig, e_idx);
51315 	/* prev value can be garbage, no decref */
51316 	DUK_TVAL_SET_TVAL(tv, tv_val);
51317 	DUK_TVAL_INCREF(thr, tv);
51318 	DUK_HOBJECT_E_SET_FLAGS(thr->heap, orig, e_idx, DUK_PROPDESC_FLAGS_WEC);
51319 	goto entry_updated;
51320 
51321  entry_updated:
51322 
51323 	/*
51324 	 *  Possible pending array length update, which must only be done
51325 	 *  if the actual entry write succeeded.
51326 	 */
51327 
51328 	if (new_array_length > 0) {
51329 		/*
51330 		 *  Note: zero works as a "no update" marker because the new length
51331 		 *  can never be zero after a new property is written.
51332 		 *
51333 		 *  Note: must re-lookup because calls above (e.g. duk__alloc_entry_checked())
51334 		 *  may realloc and compact properties and hence change e_idx.
51335 		 */
51336 
51337 		DUK_DDD(DUK_DDDPRINT("write successful, pending array length update to: %ld",
51338 		                     (long) new_array_length));
51339 
51340 		rc = duk__get_own_propdesc_raw(thr, orig, DUK_HTHREAD_STRING_LENGTH(thr), DUK__NO_ARRAY_INDEX, &desc, 0 /*flags*/);  /* don't push value */
51341 		DUK_UNREF(rc);
51342 		DUK_ASSERT(rc != 0);
51343 		DUK_ASSERT(desc.e_idx >= 0);
51344 
51345 		tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, orig, desc.e_idx);
51346 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
51347 		/* no need for decref/incref because value is a number */
51348 		DUK_TVAL_SET_FASTINT_U32(tv, new_array_length);
51349 	}
51350 
51351 	/*
51352 	 *  Arguments exotic behavior not possible for new properties: all
51353 	 *  magically bound properties are initially present in the arguments
51354 	 *  object, and if they are deleted, the binding is also removed from
51355 	 *  parameter map.
51356 	 */
51357 
51358 	goto success_no_arguments_exotic;
51359 
51360  success_with_arguments_exotic:
51361 
51362 	/*
51363 	 *  Arguments objects have exotic [[DefineOwnProperty]] which updates
51364 	 *  the internal 'map' of arguments for writes to currently mapped
51365 	 *  arguments.  More conretely, writes to mapped arguments generate
51366 	 *  a write to a bound variable.
51367 	 *
51368 	 *  The [[Put]] algorithm invokes [[DefineOwnProperty]] for existing
51369 	 *  data properties and new properties, but not for existing accessors.
51370 	 *  Hence, in E5 Section 10.6 ([[DefinedOwnProperty]] algorithm), we
51371 	 *  have a Desc with 'Value' (and possibly other properties too), and
51372 	 *  we end up in step 5.b.i.
51373 	 */
51374 
51375 	if (arr_idx != DUK__NO_ARRAY_INDEX &&
51376 	    DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(orig)) {
51377 		/* Note: only numbered indices are relevant, so arr_idx fast reject
51378 		 * is good (this is valid unless there are more than 4**32-1 arguments).
51379 		 */
51380 
51381 		DUK_DDD(DUK_DDDPRINT("putprop successful, arguments exotic behavior needed"));
51382 
51383 		/* Note: we can reuse 'desc' here */
51384 
51385 		/* XXX: top of stack must contain value, which helper doesn't touch,
51386 		 * rework to use tv_val directly?
51387 		 */
51388 
51389 		duk_push_tval(ctx, tv_val);
51390 		(void) duk__check_arguments_map_for_put(thr, orig, key, &desc, throw_flag);
51391 		duk_pop(ctx);
51392 	}
51393 	/* fall thru */
51394 
51395  success_no_arguments_exotic:
51396 	/* shared exit path now */
51397 	DUK_DDD(DUK_DDDPRINT("result: success"));
51398 	duk_pop(ctx);  /* remove key */
51399 	return 1;
51400 
51401 #if defined(DUK_USE_ES6_PROXY)
51402  fail_proxy_rejected:
51403 	DUK_DDD(DUK_DDDPRINT("result: error, proxy rejects"));
51404 	if (throw_flag) {
51405 		DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);
51406 	}
51407 	/* Note: no key on stack */
51408 	return 0;
51409 #endif
51410 
51411  fail_base_primitive:
51412 	DUK_DDD(DUK_DDDPRINT("result: error, base primitive"));
51413 	if (throw_flag) {
51414 #if defined(DUK_USE_PARANOID_ERRORS)
51415 		DUK_ERROR_TYPE(thr, DUK_STR_INVALID_BASE);
51416 #else
51417 		DUK_ERROR_FMT2(thr, DUK_ERR_TYPE_ERROR, "cannot write property %s of %s",
51418 		               duk_push_string_tval_readable(ctx, tv_key), duk_push_string_tval_readable(ctx, tv_obj));
51419 #endif
51420 	}
51421 	duk_pop(ctx);  /* remove key */
51422 	return 0;
51423 
51424  fail_not_extensible:
51425 	DUK_DDD(DUK_DDDPRINT("result: error, not extensible"));
51426 	if (throw_flag) {
51427 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_EXTENSIBLE);
51428 	}
51429 	duk_pop(ctx);  /* remove key */
51430 	return 0;
51431 
51432  fail_not_writable:
51433 	DUK_DDD(DUK_DDDPRINT("result: error, not writable"));
51434 	if (throw_flag) {
51435 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_WRITABLE);
51436 	}
51437 	duk_pop(ctx);  /* remove key */
51438 	return 0;
51439 
51440 #if defined(DUK_USE_ROM_OBJECTS)
51441  fail_not_writable_no_pop:
51442 	DUK_DDD(DUK_DDDPRINT("result: error, not writable"));
51443 	if (throw_flag) {
51444 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_WRITABLE);
51445 	}
51446 	return 0;
51447 #endif
51448 
51449  fail_array_length_partial:
51450 	DUK_DDD(DUK_DDDPRINT("result: error, array length write only partially successful"));
51451 	if (throw_flag) {
51452 		DUK_ERROR_TYPE(thr, DUK_STR_ARRAY_LENGTH_WRITE_FAILED);
51453 	}
51454 	duk_pop(ctx);  /* remove key */
51455 	return 0;
51456 
51457  fail_no_setter:
51458 	DUK_DDD(DUK_DDDPRINT("result: error, accessor property without setter"));
51459 	if (throw_flag) {
51460 		DUK_ERROR_TYPE(thr, DUK_STR_SETTER_UNDEFINED);
51461 	}
51462 	duk_pop(ctx);  /* remove key */
51463 	return 0;
51464 
51465  fail_internal:
51466 	DUK_DDD(DUK_DDDPRINT("result: error, internal"));
51467 	if (throw_flag) {
51468 		DUK_ERROR_INTERNAL_DEFMSG(thr);
51469 	}
51470 	duk_pop(ctx);  /* remove key */
51471 	return 0;
51472 }
51473 
51474 /*
51475  *  Ecmascript compliant [[Delete]](P, Throw).
51476  */
51477 
51478 DUK_INTERNAL duk_bool_t duk_hobject_delprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags) {
51479 	duk_propdesc desc;
51480 	duk_tval *tv;
51481 	duk_uint32_t arr_idx;
51482 	duk_bool_t throw_flag;
51483 	duk_bool_t force_flag;
51484 
51485 	throw_flag = (flags & DUK_DELPROP_FLAG_THROW);
51486 	force_flag = (flags & DUK_DELPROP_FLAG_FORCE);
51487 
51488 	DUK_DDD(DUK_DDDPRINT("delprop_raw: thr=%p, obj=%p, key=%p, throw=%ld, force=%ld (obj -> %!O, key -> %!O)",
51489 	                     (void *) thr, (void *) obj, (void *) key, (long) throw_flag, (long) force_flag,
51490 	                     (duk_heaphdr *) obj, (duk_heaphdr *) key));
51491 
51492 	DUK_ASSERT(thr != NULL);
51493 	DUK_ASSERT(thr->heap != NULL);
51494 	DUK_ASSERT(obj != NULL);
51495 	DUK_ASSERT(key != NULL);
51496 
51497 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
51498 
51499 	arr_idx = DUK_HSTRING_GET_ARRIDX_FAST(key);
51500 
51501 	/* 0 = don't push current value */
51502 	if (!duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &desc, 0 /*flags*/)) {  /* don't push value */
51503 		DUK_DDD(DUK_DDDPRINT("property not found, succeed always"));
51504 		goto success;
51505 	}
51506 
51507 #if defined(DUK_USE_ROM_OBJECTS)
51508 	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {
51509 		DUK_DD(DUK_DDPRINT("attempt to delprop on read-only target object"));
51510 		goto fail_not_configurable;
51511 	}
51512 #endif
51513 
51514 	if ((desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) == 0 && !force_flag) {
51515 		goto fail_not_configurable;
51516 	}
51517 	if (desc.a_idx < 0 && desc.e_idx < 0) {
51518 		/* Currently there are no deletable virtual properties, but
51519 		 * with force_flag we might attempt to delete one.
51520 		 */
51521 		goto fail_virtual;
51522 	}
51523 
51524 	if (desc.a_idx >= 0) {
51525 		DUK_ASSERT(desc.e_idx < 0);
51526 
51527 		tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, desc.a_idx);
51528 		DUK_TVAL_SET_UNUSED_UPDREF(thr, tv);  /* side effects */
51529 		goto success;
51530 	} else {
51531 		duk_hobject *h_get = NULL;
51532 		duk_hobject *h_set = NULL;
51533 		duk_tval tv_tmp;
51534 
51535 		DUK_ASSERT(desc.a_idx < 0);
51536 
51537 		/* Set property slot to an empty state.  Careful not to invoke
51538 		 * any side effects while using desc.e_idx so that it doesn't
51539 		 * get invalidated by a finalizer mutating our object.
51540 		 */
51541 
51542 		/* remove hash entry (no decref) */
51543 #if defined(DUK_USE_HOBJECT_HASH_PART)
51544 		if (desc.h_idx >= 0) {
51545 			duk_uint32_t *h_base = DUK_HOBJECT_H_GET_BASE(thr->heap, obj);
51546 
51547 			DUK_DDD(DUK_DDDPRINT("removing hash entry at h_idx %ld", (long) desc.h_idx));
51548 			DUK_ASSERT(DUK_HOBJECT_GET_HSIZE(obj) > 0);
51549 			DUK_ASSERT((duk_uint32_t) desc.h_idx < DUK_HOBJECT_GET_HSIZE(obj));
51550 			h_base[desc.h_idx] = DUK__HASH_DELETED;
51551 		} else {
51552 			DUK_ASSERT(DUK_HOBJECT_GET_HSIZE(obj) == 0);
51553 		}
51554 #else
51555 		DUK_ASSERT(DUK_HOBJECT_GET_HSIZE(obj) == 0);
51556 #endif
51557 
51558 		/* remove value */
51559 		DUK_DDD(DUK_DDDPRINT("before removing value, e_idx %ld, key %p, key at slot %p",
51560 		                     (long) desc.e_idx, (void *) key, (void *) DUK_HOBJECT_E_GET_KEY(thr->heap, obj, desc.e_idx)));
51561 		DUK_DDD(DUK_DDDPRINT("removing value at e_idx %ld", (long) desc.e_idx));
51562 		DUK_MEMSET((void *) &tv_tmp, 0, sizeof(tv_tmp));
51563 		DUK_TVAL_SET_UNDEFINED(&tv_tmp);
51564 		if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, desc.e_idx)) {
51565 			h_get = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, obj, desc.e_idx);
51566 			h_set = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, obj, desc.e_idx);
51567 			DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, desc.e_idx, NULL);
51568 			DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, desc.e_idx, NULL);
51569 		} else {
51570 			tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, desc.e_idx);
51571 			DUK_TVAL_SET_TVAL(&tv_tmp, tv);
51572 			DUK_TVAL_SET_UNDEFINED(tv);
51573 		}
51574 #if 0
51575 		/* Not strictly necessary because if key == NULL, flag MUST be ignored. */
51576 		DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, desc.e_idx, 0);
51577 #endif
51578 
51579 		/* remove key */
51580 		DUK_DDD(DUK_DDDPRINT("before removing key, e_idx %ld, key %p, key at slot %p",
51581 		                     (long) desc.e_idx, (void *) key, (void *) DUK_HOBJECT_E_GET_KEY(thr->heap, obj, desc.e_idx)));
51582 		DUK_DDD(DUK_DDDPRINT("removing key at e_idx %ld", (long) desc.e_idx));
51583 		DUK_ASSERT(key == DUK_HOBJECT_E_GET_KEY(thr->heap, obj, desc.e_idx));
51584 		DUK_HOBJECT_E_SET_KEY(thr->heap, obj, desc.e_idx, NULL);
51585 
51586 		/* Do decrefs only with safe pointers to avoid side effects
51587 		 * disturbing e_idx.
51588 		 */
51589 		DUK_TVAL_DECREF(thr, &tv_tmp);
51590 		DUK_HOBJECT_DECREF_ALLOWNULL(thr, h_get);
51591 		DUK_HOBJECT_DECREF_ALLOWNULL(thr, h_set);
51592 		DUK_HSTRING_DECREF(thr, key);
51593 		goto success;
51594 	}
51595 
51596 	DUK_UNREACHABLE();
51597 
51598  success:
51599 	/*
51600 	 *  Argument exotic [[Delete]] behavior (E5 Section 10.6) is
51601 	 *  a post-check, keeping arguments internal 'map' in sync with
51602 	 *  any successful deletes (note that property does not need to
51603 	 *  exist for delete to 'succeed').
51604 	 *
51605 	 *  Delete key from 'map'.  Since 'map' only contains array index
51606 	 *  keys, we can use arr_idx for a fast skip.
51607 	 */
51608 
51609 	DUK_DDD(DUK_DDDPRINT("delete successful, check for arguments exotic behavior"));
51610 
51611 	if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj)) {
51612 		/* Note: only numbered indices are relevant, so arr_idx fast reject
51613 		 * is good (this is valid unless there are more than 4**32-1 arguments).
51614 		 */
51615 
51616 		DUK_DDD(DUK_DDDPRINT("delete successful, arguments exotic behavior needed"));
51617 
51618 		/* Note: we can reuse 'desc' here */
51619 		(void) duk__check_arguments_map_for_delete(thr, obj, key, &desc);
51620 	}
51621 
51622 	DUK_DDD(DUK_DDDPRINT("delete successful"));
51623 	return 1;
51624 
51625  fail_virtual:
51626 	DUK_DDD(DUK_DDDPRINT("delete failed: property found, force flag, but virtual"));
51627 
51628 	if (throw_flag) {
51629 		DUK_ERROR_TYPE(thr, DUK_STR_PROPERTY_IS_VIRTUAL);
51630 	}
51631 	return 0;
51632 
51633  fail_not_configurable:
51634 	DUK_DDD(DUK_DDDPRINT("delete failed: property found, not configurable"));
51635 
51636 	if (throw_flag) {
51637 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);
51638 	}
51639 	return 0;
51640 }
51641 
51642 /*
51643  *  DELPROP: Ecmascript property deletion.
51644  */
51645 
51646 DUK_INTERNAL duk_bool_t duk_hobject_delprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key, duk_bool_t throw_flag) {
51647 	duk_context *ctx = (duk_context *) thr;
51648 	duk_hstring *key = NULL;
51649 #if defined(DUK_USE_ES6_PROXY)
51650 	duk_propdesc desc;
51651 #endif
51652 	duk_int_t entry_top;
51653 	duk_uint32_t arr_idx = DUK__NO_ARRAY_INDEX;
51654 	duk_bool_t rc;
51655 
51656 	DUK_DDD(DUK_DDDPRINT("delprop: thr=%p, obj=%p, key=%p (obj -> %!T, key -> %!T)",
51657 	                     (void *) thr, (void *) tv_obj, (void *) tv_key,
51658 	                     (duk_tval *) tv_obj, (duk_tval *) tv_key));
51659 
51660 	DUK_ASSERT(ctx != NULL);
51661 	DUK_ASSERT(thr != NULL);
51662 	DUK_ASSERT(thr->heap != NULL);
51663 	DUK_ASSERT(tv_obj != NULL);
51664 	DUK_ASSERT(tv_key != NULL);
51665 
51666 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
51667 
51668 	/* Storing the entry top is cheaper here to ensure stack is correct at exit,
51669 	 * as there are several paths out.
51670 	 */
51671 	entry_top = duk_get_top(ctx);
51672 
51673 	if (DUK_TVAL_IS_UNDEFINED(tv_obj) ||
51674 	    DUK_TVAL_IS_NULL(tv_obj)) {
51675 		DUK_DDD(DUK_DDDPRINT("base object is undefined or null -> reject"));
51676 		goto fail_invalid_base_uncond;
51677 	}
51678 
51679 	duk_push_tval(ctx, tv_obj);
51680 	duk_push_tval(ctx, tv_key);
51681 
51682 	tv_obj = DUK_GET_TVAL_NEGIDX(ctx, -2);
51683 	if (DUK_TVAL_IS_OBJECT(tv_obj)) {
51684 		duk_hobject *obj = DUK_TVAL_GET_OBJECT(tv_obj);
51685 		DUK_ASSERT(obj != NULL);
51686 
51687 #if defined(DUK_USE_ES6_PROXY)
51688 		if (DUK_UNLIKELY(DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(obj))) {
51689 			duk_hobject *h_target;
51690 			duk_bool_t tmp_bool;
51691 
51692 			/* Note: proxy handling must happen before key is string coerced. */
51693 
51694 			if (duk__proxy_check_prop(thr, obj, DUK_STRIDX_DELETE_PROPERTY, tv_key, &h_target)) {
51695 				/* -> [ ... obj key trap handler ] */
51696 				DUK_DDD(DUK_DDDPRINT("-> proxy object 'deleteProperty' for key %!T", (duk_tval *) tv_key));
51697 				duk_push_hobject(ctx, h_target);  /* target */
51698 				duk_dup(ctx, -4);  /* P */
51699 				duk_call_method(ctx, 2 /*nargs*/);
51700 				tmp_bool = duk_to_boolean(ctx, -1);
51701 				duk_pop(ctx);
51702 				if (!tmp_bool) {
51703 					goto fail_proxy_rejected;  /* retval indicates delete failed */
51704 				}
51705 
51706 				/* Target object must be checked for a conflicting
51707 				 * non-configurable property.
51708 				 */
51709 				tv_key = DUK_GET_TVAL_NEGIDX(ctx, -1);
51710 				arr_idx = duk__push_tval_to_hstring_arr_idx(ctx, tv_key, &key);
51711 				DUK_ASSERT(key != NULL);
51712 
51713 				if (duk__get_own_propdesc_raw(thr, h_target, key, arr_idx, &desc, 0 /*flags*/)) {  /* don't push value */
51714 					int desc_reject;
51715 
51716 					DUK_DDD(DUK_DDDPRINT("proxy 'deleteProperty': target has matching property %!O, check for "
51717 					                     "conflicting property; desc.flags=0x%08lx, "
51718 					                     "desc.get=%p, desc.set=%p",
51719 					                     (duk_heaphdr *) key, (unsigned long) desc.flags,
51720 					                     (void *) desc.get, (void *) desc.set));
51721 
51722 					desc_reject = !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE);
51723 					if (desc_reject) {
51724 						/* unconditional */
51725 						DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);
51726 					}
51727 				}
51728 				rc = 1;  /* success */
51729 				goto done_rc;
51730 			}
51731 
51732 			obj = h_target;  /* resume delete to target */
51733 		}
51734 #endif  /* DUK_USE_ES6_PROXY */
51735 
51736 		duk_to_string(ctx, -1);
51737 		key = duk_get_hstring(ctx, -1);
51738 		DUK_ASSERT(key != NULL);
51739 
51740 		rc = duk_hobject_delprop_raw(thr, obj, key, throw_flag ? DUK_DELPROP_FLAG_THROW : 0);
51741 		goto done_rc;
51742 	} else if (DUK_TVAL_IS_STRING(tv_obj)) {
51743 		/* XXX: unnecessary string coercion for array indices,
51744 		 * intentional to keep small.
51745 		 */
51746 		duk_hstring *h = DUK_TVAL_GET_STRING(tv_obj);
51747 		DUK_ASSERT(h != NULL);
51748 
51749 		duk_to_string(ctx, -1);
51750 		key = duk_get_hstring(ctx, -1);
51751 		DUK_ASSERT(key != NULL);
51752 
51753 		if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
51754 			goto fail_not_configurable;
51755 		}
51756 
51757 		arr_idx = DUK_HSTRING_GET_ARRIDX_FAST(key);
51758 
51759 		if (arr_idx != DUK__NO_ARRAY_INDEX &&
51760 		    arr_idx < DUK_HSTRING_GET_CHARLEN(h)) {
51761 			goto fail_not_configurable;
51762 		}
51763 	} else if (DUK_TVAL_IS_BUFFER(tv_obj)) {
51764 		/* XXX: unnecessary string coercion for array indices,
51765 		 * intentional to keep small; some overlap with string
51766 		 * handling.
51767 		 */
51768 		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv_obj);
51769 		DUK_ASSERT(h != NULL);
51770 
51771 		duk_to_string(ctx, -1);
51772 		key = duk_get_hstring(ctx, -1);
51773 		DUK_ASSERT(key != NULL);
51774 
51775 		if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
51776 			goto fail_not_configurable;
51777 		}
51778 
51779 		arr_idx = DUK_HSTRING_GET_ARRIDX_FAST(key);
51780 
51781 		if (arr_idx != DUK__NO_ARRAY_INDEX &&
51782 		    arr_idx < DUK_HBUFFER_GET_SIZE(h)) {
51783 			goto fail_not_configurable;
51784 		}
51785 	} else if (DUK_TVAL_IS_LIGHTFUNC(tv_obj)) {
51786 		/* Lightfunc virtual properties are non-configurable, so
51787 		 * reject if match any of them.
51788 		 */
51789 
51790 		duk_to_string(ctx, -1);
51791 		key = duk_get_hstring(ctx, -1);
51792 		DUK_ASSERT(key != NULL);
51793 
51794 		if (duk__key_is_lightfunc_ownprop(thr, key)) {
51795 			goto fail_not_configurable;
51796 		}
51797 	}
51798 
51799 	/* non-object base, no offending virtual property */
51800 	rc = 1;
51801 	goto done_rc;
51802 
51803  done_rc:
51804 	duk_set_top(ctx, entry_top);
51805 	return rc;
51806 
51807  fail_invalid_base_uncond:
51808 	/* Note: unconditional throw */
51809 	DUK_ASSERT(duk_get_top(ctx) == entry_top);
51810 #if defined(DUK_USE_PARANOID_ERRORS)
51811 	DUK_ERROR_TYPE(thr, DUK_STR_INVALID_BASE);
51812 #else
51813 	DUK_ERROR_FMT2(thr, DUK_ERR_TYPE_ERROR, "cannot delete property %s of %s",
51814 	               duk_push_string_tval_readable(ctx, tv_key), duk_push_string_tval_readable(ctx, tv_obj));
51815 #endif
51816 	return 0;
51817 
51818 #if defined(DUK_USE_ES6_PROXY)
51819  fail_proxy_rejected:
51820 	if (throw_flag) {
51821 		DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);
51822 	}
51823 	duk_set_top(ctx, entry_top);
51824 	return 0;
51825 #endif
51826 
51827  fail_not_configurable:
51828 	if (throw_flag) {
51829 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);
51830 	}
51831 	duk_set_top(ctx, entry_top);
51832 	return 0;
51833 }
51834 
51835 /*
51836  *  Internal helper to define a property with specific flags, ignoring
51837  *  normal semantics such as extensibility, write protection etc.
51838  *  Overwrites any existing value and attributes unless caller requests
51839  *  that value only be updated if it doesn't already exists.
51840  *
51841  *  Does not support:
51842  *    - virtual properties (error if write attempted)
51843  *    - getter/setter properties (error if write attempted)
51844  *    - non-default (!= WEC) attributes for array entries (error if attempted)
51845  *    - array abandoning: if array part exists, it is always extended
51846  *    - array 'length' updating
51847  *
51848  *  Stack: [... in_val] -> []
51849  *
51850  *  Used for e.g. built-in initialization and environment record
51851  *  operations.
51852  */
51853 
51854 DUK_INTERNAL void duk_hobject_define_property_internal(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags) {
51855 	duk_context *ctx = (duk_context *) thr;
51856 	duk_propdesc desc;
51857 	duk_uint32_t arr_idx;
51858 	duk_int_t e_idx;
51859 	duk_tval *tv1 = NULL;
51860 	duk_tval *tv2 = NULL;
51861 	duk_small_uint_t propflags = flags & DUK_PROPDESC_FLAGS_MASK;  /* mask out flags not actually stored */
51862 
51863 	DUK_DDD(DUK_DDDPRINT("define new property (internal): thr=%p, obj=%!O, key=%!O, flags=0x%02lx, val=%!T",
51864 	                     (void *) thr, (duk_heaphdr *) obj, (duk_heaphdr *) key,
51865 	                     (unsigned long) flags, (duk_tval *) duk_get_tval(ctx, -1)));
51866 
51867 	DUK_ASSERT(thr != NULL);
51868 	DUK_ASSERT(thr->heap != NULL);
51869 	DUK_ASSERT(obj != NULL);
51870 	DUK_ASSERT(key != NULL);
51871 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));
51872 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
51873 	DUK_ASSERT(duk_is_valid_index(ctx, -1));  /* contains value */
51874 
51875 	arr_idx = DUK_HSTRING_GET_ARRIDX_SLOW(key);
51876 
51877 	if (duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &desc, 0 /*flags*/)) {  /* don't push value */
51878 		if (desc.e_idx >= 0) {
51879 			if (flags & DUK_PROPDESC_FLAG_NO_OVERWRITE) {
51880 				DUK_DDD(DUK_DDDPRINT("property already exists in the entry part -> skip as requested"));
51881 				goto pop_exit;
51882 			}
51883 			DUK_DDD(DUK_DDDPRINT("property already exists in the entry part -> update value and attributes"));
51884 			if (DUK_UNLIKELY(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, desc.e_idx))) {
51885 				DUK_D(DUK_DPRINT("existing property is an accessor, not supported"));
51886 				goto error_internal;
51887 			}
51888 
51889 			DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, desc.e_idx, propflags);
51890 			tv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, desc.e_idx);
51891 		} else if (desc.a_idx >= 0) {
51892 			if (flags & DUK_PROPDESC_FLAG_NO_OVERWRITE) {
51893 				DUK_DDD(DUK_DDDPRINT("property already exists in the array part -> skip as requested"));
51894 				goto pop_exit;
51895 			}
51896 			DUK_DDD(DUK_DDDPRINT("property already exists in the array part -> update value (assert attributes)"));
51897 			if (propflags != DUK_PROPDESC_FLAGS_WEC) {
51898 				DUK_D(DUK_DPRINT("existing property in array part, but propflags not WEC (0x%02lx)",
51899 				                 (unsigned long) propflags));
51900 				goto error_internal;
51901 			}
51902 
51903 			tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, desc.a_idx);
51904 		} else {
51905 			if (flags & DUK_PROPDESC_FLAG_NO_OVERWRITE) {
51906 				DUK_DDD(DUK_DDDPRINT("property already exists but is virtual -> skip as requested"));
51907 				goto pop_exit;
51908 			}
51909 			DUK_DDD(DUK_DDDPRINT("property already exists but is virtual -> failure"));
51910 			goto error_virtual;
51911 		}
51912 
51913 		goto write_value;
51914 	}
51915 
51916 	if (DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
51917 		if (arr_idx != DUK__NO_ARRAY_INDEX) {
51918 			DUK_DDD(DUK_DDDPRINT("property does not exist, object has array part -> possibly extend array part and write value (assert attributes)"));
51919 			DUK_ASSERT(propflags == DUK_PROPDESC_FLAGS_WEC);
51920 
51921 			/* always grow the array, no sparse / abandon support here */
51922 			if (arr_idx >= DUK_HOBJECT_GET_ASIZE(obj)) {
51923 				duk__grow_props_for_array_item(thr, obj, arr_idx);
51924 			}
51925 
51926 			DUK_ASSERT(arr_idx < DUK_HOBJECT_GET_ASIZE(obj));
51927 			tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, arr_idx);
51928 			goto write_value;
51929 		}
51930 	}
51931 
51932 	DUK_DDD(DUK_DDDPRINT("property does not exist, object belongs in entry part -> allocate new entry and write value and attributes"));
51933 	e_idx = duk__alloc_entry_checked(thr, obj, key);  /* increases key refcount */
51934 	DUK_ASSERT(e_idx >= 0);
51935 	DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, e_idx, propflags);
51936 	tv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, e_idx);
51937 	/* new entry: previous value is garbage; set to undefined to share write_value */
51938 	DUK_TVAL_SET_UNDEFINED(tv1);
51939 	goto write_value;
51940 
51941  write_value:
51942 	/* tv1 points to value storage */
51943 
51944 	tv2 = duk_require_tval(ctx, -1);  /* late lookup, avoid side effects */
51945 	DUK_DDD(DUK_DDDPRINT("writing/updating value: %!T -> %!T",
51946 	                     (duk_tval *) tv1, (duk_tval *) tv2));
51947 
51948 	DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2);  /* side effects */
51949 	goto pop_exit;
51950 
51951  pop_exit:
51952 	duk_pop(ctx);  /* remove in_val */
51953 	return;
51954 
51955  error_internal:
51956 	DUK_ERROR_INTERNAL_DEFMSG(thr);
51957 	return;
51958 
51959  error_virtual:
51960 	DUK_ERROR_TYPE(thr, DUK_STR_REDEFINE_VIRT_PROP);
51961 	return;
51962 }
51963 
51964 /*
51965  *  Fast path for defining array indexed values without interning the key.
51966  *  This is used by e.g. code for Array prototype and traceback creation so
51967  *  must avoid interning.
51968  */
51969 
51970 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) {
51971 	duk_context *ctx = (duk_context *) thr;
51972 	duk_hstring *key;
51973 	duk_tval *tv1, *tv2;
51974 
51975 	DUK_DDD(DUK_DDDPRINT("define new property (internal) arr_idx fast path: thr=%p, obj=%!O, "
51976 	                     "arr_idx=%ld, flags=0x%02lx, val=%!T",
51977 	                     (void *) thr, obj, (long) arr_idx, (unsigned long) flags,
51978 	                     (duk_tval *) duk_get_tval(ctx, -1)));
51979 
51980 	DUK_ASSERT(thr != NULL);
51981 	DUK_ASSERT(thr->heap != NULL);
51982 	DUK_ASSERT(obj != NULL);
51983 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));
51984 
51985 	if (DUK_HOBJECT_HAS_ARRAY_PART(obj) &&
51986 	    arr_idx != DUK__NO_ARRAY_INDEX &&
51987 	    flags == DUK_PROPDESC_FLAGS_WEC) {
51988 		DUK_ASSERT((flags & DUK_PROPDESC_FLAG_NO_OVERWRITE) == 0);  /* covered by comparison */
51989 
51990 		DUK_DDD(DUK_DDDPRINT("define property to array part (property may or may not exist yet)"));
51991 
51992 		/* always grow the array, no sparse / abandon support here */
51993 		if (arr_idx >= DUK_HOBJECT_GET_ASIZE(obj)) {
51994 			duk__grow_props_for_array_item(thr, obj, arr_idx);
51995 		}
51996 
51997 		DUK_ASSERT(arr_idx < DUK_HOBJECT_GET_ASIZE(obj));
51998 		tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, arr_idx);
51999 		tv2 = duk_require_tval(ctx, -1);
52000 
52001 		DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2);  /* side effects */
52002 
52003 		duk_pop(ctx);  /* [ ...val ] -> [ ... ] */
52004 		return;
52005 	}
52006 
52007 	DUK_DDD(DUK_DDDPRINT("define property fast path didn't work, use slow path"));
52008 
52009 	duk_push_uint(ctx, (duk_uint_t) arr_idx);
52010 	key = duk_to_hstring(ctx, -1);
52011 	DUK_ASSERT(key != NULL);
52012 	duk_insert(ctx, -2);  /* [ ... val key ] -> [ ... key val ] */
52013 
52014 	duk_hobject_define_property_internal(thr, obj, key, flags);
52015 
52016 	duk_pop(ctx);  /* [ ... key ] -> [ ... ] */
52017 }
52018 
52019 /*
52020  *  Internal helper for defining an accessor property, ignoring
52021  *  normal semantics such as extensibility, write protection etc.
52022  *  Overwrites any existing value and attributes.  This is called
52023  *  very rarely, so the implementation first sets a value to undefined
52024  *  and then changes the entry to an accessor (this is to save code space).
52025  */
52026 
52027 DUK_INTERNAL void duk_hobject_define_accessor_internal(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_hobject *getter, duk_hobject *setter, duk_small_uint_t propflags) {
52028 	duk_context *ctx = (duk_context *) thr;
52029 	duk_int_t e_idx;
52030 	duk_int_t h_idx;
52031 
52032 	DUK_DDD(DUK_DDDPRINT("define new accessor (internal): thr=%p, obj=%!O, key=%!O, "
52033 	                     "getter=%!O, setter=%!O, flags=0x%02lx",
52034 	                     (void *) thr, (duk_heaphdr *) obj, (duk_heaphdr *) key,
52035 	                     (duk_heaphdr *) getter, (duk_heaphdr *) setter,
52036 	                     (unsigned long) propflags));
52037 
52038 	DUK_ASSERT(thr != NULL);
52039 	DUK_ASSERT(thr->heap != NULL);
52040 	DUK_ASSERT(obj != NULL);
52041 	DUK_ASSERT(key != NULL);
52042 	DUK_ASSERT((propflags & ~DUK_PROPDESC_FLAGS_MASK) == 0);
52043 	/* setter and/or getter may be NULL */
52044 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));
52045 
52046 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
52047 
52048 	/* force the property to 'undefined' to create a slot for it */
52049 	duk_push_undefined(ctx);
52050 	duk_hobject_define_property_internal(thr, obj, key, propflags);
52051 	duk_hobject_find_existing_entry(thr->heap, obj, key, &e_idx, &h_idx);
52052 	DUK_DDD(DUK_DDDPRINT("accessor slot: e_idx=%ld, h_idx=%ld", (long) e_idx, (long) h_idx));
52053 	DUK_ASSERT(e_idx >= 0);
52054 	DUK_ASSERT((duk_uint32_t) e_idx < DUK_HOBJECT_GET_ENEXT(obj));
52055 
52056 	/* no need to decref, as previous value is 'undefined' */
52057 	DUK_HOBJECT_E_SLOT_SET_ACCESSOR(thr->heap, obj, e_idx);
52058 	DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, e_idx, getter);
52059 	DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, e_idx, setter);
52060 	DUK_HOBJECT_INCREF_ALLOWNULL(thr, getter);
52061 	DUK_HOBJECT_INCREF_ALLOWNULL(thr, setter);
52062 }
52063 
52064 /*
52065  *  Internal helpers for managing object 'length'
52066  */
52067 
52068 /* XXX: awkward helpers */
52069 
52070 DUK_INTERNAL void duk_hobject_set_length(duk_hthread *thr, duk_hobject *obj, duk_uint32_t length) {
52071 	duk_context *ctx = (duk_context *) thr;
52072 	duk_push_hobject(ctx, obj);
52073 	duk_push_hstring_stridx(ctx, DUK_STRIDX_LENGTH);
52074 	duk_push_u32(ctx, length);
52075 	(void) duk_hobject_putprop(thr,
52076 	                           DUK_GET_TVAL_NEGIDX(ctx, -3),
52077 	                           DUK_GET_TVAL_NEGIDX(ctx, -2),
52078 	                           DUK_GET_TVAL_NEGIDX(ctx, -1),
52079 	                           0);
52080 	duk_pop_n(ctx, 3);
52081 }
52082 
52083 DUK_INTERNAL void duk_hobject_set_length_zero(duk_hthread *thr, duk_hobject *obj) {
52084 	duk_hobject_set_length(thr, obj, 0);
52085 }
52086 
52087 DUK_INTERNAL duk_uint32_t duk_hobject_get_length(duk_hthread *thr, duk_hobject *obj) {
52088 	duk_context *ctx = (duk_context *) thr;
52089 	duk_double_t val;
52090 	duk_push_hobject(ctx, obj);
52091 	duk_push_hstring_stridx(ctx, DUK_STRIDX_LENGTH);
52092 	(void) duk_hobject_getprop(thr,
52093 	                           DUK_GET_TVAL_NEGIDX(ctx, -2),
52094 	                           DUK_GET_TVAL_NEGIDX(ctx, -1));
52095 	val = duk_to_number(ctx, -1);
52096 	duk_pop_n(ctx, 3);
52097 	if (val >= 0.0 && val < DUK_DOUBLE_2TO32) {
52098 		return (duk_uint32_t) val;
52099 	}
52100 	return 0;
52101 }
52102 
52103 /*
52104  *  Object.getOwnPropertyDescriptor()  (E5 Sections 15.2.3.3, 8.10.4)
52105  *
52106  *  This is an actual function call.
52107  */
52108 
52109 DUK_INTERNAL duk_ret_t duk_hobject_object_get_own_property_descriptor(duk_context *ctx) {
52110 	duk_hthread *thr = (duk_hthread *) ctx;
52111 	duk_hobject *obj;
52112 	duk_hstring *key;
52113 	duk_propdesc pd;
52114 	duk_bool_t rc;
52115 
52116 	DUK_ASSERT(ctx != NULL);
52117 	DUK_ASSERT(thr != NULL);
52118 	DUK_ASSERT(thr->heap != NULL);
52119 
52120 	obj = duk_require_hobject_or_lfunc_coerce(ctx, 0);
52121 	(void) duk_to_string(ctx, 1);
52122 	key = duk_require_hstring(ctx, 1);
52123 
52124 	DUK_ASSERT(obj != NULL);
52125 	DUK_ASSERT(key != NULL);
52126 
52127 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
52128 
52129 	rc = duk_hobject_get_own_propdesc(thr, obj, key, &pd, DUK_GETDESC_FLAG_PUSH_VALUE);
52130 	if (!rc) {
52131 		duk_push_undefined(ctx);
52132 
52133 		/* [obj key undefined] */
52134 		return 1;
52135 	}
52136 
52137 	duk_push_object(ctx);
52138 
52139 	/* [obj key value desc] */
52140 
52141 	if (DUK_PROPDESC_IS_ACCESSOR(&pd)) {
52142 		/* If a setter/getter is missing (undefined), the descriptor must
52143 		 * still have the property present with the value 'undefined'.
52144 		 */
52145 		if (pd.get) {
52146 			duk_push_hobject(ctx, pd.get);
52147 		} else {
52148 			duk_push_undefined(ctx);
52149 		}
52150 		duk_put_prop_stridx(ctx, -2, DUK_STRIDX_GET);
52151 		if (pd.set) {
52152 			duk_push_hobject(ctx, pd.set);
52153 		} else {
52154 			duk_push_undefined(ctx);
52155 		}
52156 		duk_put_prop_stridx(ctx, -2, DUK_STRIDX_SET);
52157 	} else {
52158 		duk_dup(ctx, -2);  /* [obj key value desc value] */
52159 		duk_put_prop_stridx(ctx, -2, DUK_STRIDX_VALUE);
52160 		duk_push_boolean(ctx, DUK_PROPDESC_IS_WRITABLE(&pd));
52161 		duk_put_prop_stridx(ctx, -2, DUK_STRIDX_WRITABLE);
52162 
52163 		/* [obj key value desc] */
52164 	}
52165 	duk_push_boolean(ctx, DUK_PROPDESC_IS_ENUMERABLE(&pd));
52166 	duk_put_prop_stridx(ctx, -2, DUK_STRIDX_ENUMERABLE);
52167 	duk_push_boolean(ctx, DUK_PROPDESC_IS_CONFIGURABLE(&pd));
52168 	duk_put_prop_stridx(ctx, -2, DUK_STRIDX_CONFIGURABLE);
52169 
52170 	/* [obj key value desc] */
52171 	return 1;
52172 }
52173 
52174 /*
52175  *  NormalizePropertyDescriptor() related helper.
52176  *
52177  *  Internal helper which validates and normalizes a property descriptor
52178  *  represented as an Ecmascript object (e.g. argument to defineProperty()).
52179  *  The output of this conversion is a set of defprop_flags and possibly
52180  *  some values pushed on the value stack; some subset of: property value,
52181  *  getter, setter.  Caller must manage stack top carefully because the
52182  *  number of values pushed depends on the input property descriptor.
52183  *
52184  *  The original descriptor object must not be altered in the process.
52185  */
52186 
52187 /* XXX: very basic optimization -> duk_get_prop_stridx_top */
52188 
52189 DUK_INTERNAL
52190 void duk_hobject_prepare_property_descriptor(duk_context *ctx,
52191                                              duk_idx_t idx_in,
52192                                              duk_uint_t *out_defprop_flags,
52193                                              duk_idx_t *out_idx_value,
52194                                              duk_hobject **out_getter,
52195                                              duk_hobject **out_setter) {
52196 	duk_hthread *thr = (duk_hthread *) ctx;
52197 	duk_idx_t idx_value = -1;
52198 	duk_hobject *getter = NULL;
52199 	duk_hobject *setter = NULL;
52200 	duk_bool_t is_data_desc = 0;
52201 	duk_bool_t is_acc_desc = 0;
52202 	duk_uint_t defprop_flags = 0;
52203 
52204 	DUK_ASSERT(ctx != NULL);
52205 	DUK_ASSERT(out_defprop_flags != NULL);
52206 	DUK_ASSERT(out_idx_value != NULL);
52207 	DUK_ASSERT(out_getter != NULL);
52208 	DUK_ASSERT(out_setter != NULL);
52209 
52210 	/* Must be an object, otherwise TypeError (E5.1 Section 8.10.5, step 1). */
52211 	idx_in = duk_require_normalize_index(ctx, idx_in);
52212 	(void) duk_require_hobject(ctx, idx_in);
52213 
52214 	/* The coercion order must match the ToPropertyDescriptor() algorithm
52215 	 * so that side effects in coercion happen in the correct order.
52216 	 * (This order also happens to be compatible with duk_def_prop(),
52217 	 * although it doesn't matter in practice.)
52218 	 */
52219 
52220 	if (duk_get_prop_stridx(ctx, idx_in, DUK_STRIDX_VALUE)) {
52221 		is_data_desc = 1;
52222 		defprop_flags |= DUK_DEFPROP_HAVE_VALUE;
52223 		idx_value = duk_get_top_index(ctx);
52224 		/* Leave 'value' on stack */
52225 	} else {
52226 		duk_pop(ctx);
52227 	}
52228 
52229 	if (duk_get_prop_stridx(ctx, idx_in, DUK_STRIDX_WRITABLE)) {
52230 		is_data_desc = 1;
52231 		if (duk_to_boolean(ctx, -1)) {
52232 			defprop_flags |= DUK_DEFPROP_HAVE_WRITABLE | DUK_DEFPROP_WRITABLE;
52233 		} else {
52234 			defprop_flags |= DUK_DEFPROP_HAVE_WRITABLE;
52235 		}
52236 	}
52237 	duk_pop(ctx);
52238 
52239 	if (duk_get_prop_stridx(ctx, idx_in, DUK_STRIDX_GET)) {
52240 		duk_tval *tv = duk_require_tval(ctx, -1);
52241 		duk_hobject *h_get;
52242 
52243 		if (DUK_TVAL_IS_UNDEFINED(tv)) {
52244 			/* undefined is accepted */
52245 			DUK_ASSERT(getter == NULL);
52246 		} else {
52247 			/* NOTE: lightfuncs are coerced to full functions because
52248 			 * lightfuncs don't fit into a property value slot.  This
52249 			 * has some side effects, see test-dev-lightfunc-accessor.js.
52250 			 */
52251 			h_get = duk_get_hobject_or_lfunc_coerce(ctx, -1);
52252 			if (h_get == NULL || !DUK_HOBJECT_IS_CALLABLE(h_get)) {
52253 				goto type_error;
52254 			}
52255 			getter = h_get;
52256 		}
52257 		is_acc_desc = 1;
52258 		defprop_flags |= DUK_DEFPROP_HAVE_GETTER;
52259 		/* Leave 'getter' on stack */
52260 	} else {
52261 		duk_pop(ctx);
52262 	}
52263 
52264 	if (duk_get_prop_stridx(ctx, idx_in, DUK_STRIDX_SET)) {
52265 		duk_tval *tv = duk_require_tval(ctx, -1);
52266 		duk_hobject *h_set;
52267 
52268 		if (DUK_TVAL_IS_UNDEFINED(tv)) {
52269 			/* undefined is accepted */
52270 			DUK_ASSERT(setter == NULL);
52271 		}  else {
52272 			/* NOTE: lightfuncs are coerced to full functions because
52273 			 * lightfuncs don't fit into a property value slot.  This
52274 			 * has some side effects, see test-dev-lightfunc-accessor.js.
52275 			 */
52276 			h_set = duk_get_hobject_or_lfunc_coerce(ctx, -1);
52277 			if (h_set == NULL || !DUK_HOBJECT_IS_CALLABLE(h_set)) {
52278 				goto type_error;
52279 			}
52280 			setter = h_set;
52281 		}
52282 		is_acc_desc = 1;
52283 		defprop_flags |= DUK_DEFPROP_HAVE_SETTER;
52284 		/* Leave 'setter' on stack */
52285 	} else {
52286 		duk_pop(ctx);
52287 	}
52288 
52289 	if (duk_get_prop_stridx(ctx, idx_in, DUK_STRIDX_ENUMERABLE)) {
52290 		if (duk_to_boolean(ctx, -1)) {
52291 			defprop_flags |= DUK_DEFPROP_HAVE_ENUMERABLE | DUK_DEFPROP_ENUMERABLE;
52292 		} else {
52293 			defprop_flags |= DUK_DEFPROP_HAVE_ENUMERABLE;
52294 		}
52295 	}
52296 	duk_pop(ctx);
52297 
52298 	if (duk_get_prop_stridx(ctx, idx_in, DUK_STRIDX_CONFIGURABLE)) {
52299 		if (duk_to_boolean(ctx, -1)) {
52300 			defprop_flags |= DUK_DEFPROP_HAVE_CONFIGURABLE | DUK_DEFPROP_CONFIGURABLE;
52301 		} else {
52302 			defprop_flags |= DUK_DEFPROP_HAVE_CONFIGURABLE;
52303 		}
52304 	}
52305 	duk_pop(ctx);
52306 
52307 	if (is_data_desc && is_acc_desc) {
52308 		goto type_error;
52309 	}
52310 
52311 	*out_defprop_flags = defprop_flags;
52312 	*out_idx_value = idx_value;
52313 	*out_getter = getter;
52314 	*out_setter = setter;
52315 
52316 	/* [ ... value? getter? setter? ] */
52317 	return;
52318 
52319  type_error:
52320 	DUK_ERROR_TYPE(thr, DUK_STR_INVALID_DESCRIPTOR);
52321 }
52322 
52323 /*
52324  *  Object.defineProperty() related helper  (E5 Section 15.2.3.6)
52325  *
52326  *  Inlines all [[DefineOwnProperty]] exotic behaviors.
52327  *
52328  *  Note: Ecmascript compliant [[DefineOwnProperty]](P, Desc, Throw) is not
52329  *  implemented directly, but Object.defineProperty() serves its purpose.
52330  *  We don't need the [[DefineOwnProperty]] internally and we don't have a
52331  *  property descriptor with 'missing values' so it's easier to avoid it
52332  *  entirely.
52333  *
52334  *  Note: this is only called for actual objects, not primitive values.
52335  *  This must support virtual properties for full objects (e.g. Strings)
52336  *  but not for plain values (e.g. strings).  Lightfuncs, even though
52337  *  primitive in a sense, are treated like objects and accepted as target
52338  *  values.
52339  */
52340 
52341 /* XXX: this is a major target for size optimization */
52342 DUK_INTERNAL
52343 void duk_hobject_define_property_helper(duk_context *ctx,
52344                                         duk_uint_t defprop_flags,
52345                                         duk_hobject *obj,
52346                                         duk_hstring *key,
52347                                         duk_idx_t idx_value,
52348                                         duk_hobject *get,
52349                                         duk_hobject *set) {
52350 	duk_hthread *thr = (duk_hthread *) ctx;
52351 	duk_uint32_t arr_idx;
52352 	duk_tval tv;
52353 	duk_bool_t has_enumerable;
52354 	duk_bool_t has_configurable;
52355 	duk_bool_t has_writable;
52356 	duk_bool_t has_value;
52357 	duk_bool_t has_get;
52358 	duk_bool_t has_set;
52359 	duk_bool_t is_enumerable;
52360 	duk_bool_t is_configurable;
52361 	duk_bool_t is_writable;
52362 	duk_bool_t throw_flag;
52363 	duk_bool_t force_flag;
52364 	duk_small_uint_t new_flags;
52365 	duk_propdesc curr;
52366 	duk_uint32_t arridx_new_array_length;  /* != 0 => post-update for array 'length' (used when key is an array index) */
52367 	duk_uint32_t arrlen_old_len;
52368 	duk_uint32_t arrlen_new_len;
52369 	duk_bool_t pending_write_protect;
52370 
52371 	DUK_ASSERT(thr != NULL);
52372 	DUK_ASSERT(thr->heap != NULL);
52373 	DUK_ASSERT(ctx != NULL);
52374 	DUK_ASSERT(obj != NULL);
52375 	DUK_ASSERT(key != NULL);
52376 	/* idx_value may be < 0 (no value), set and get may be NULL */
52377 
52378 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
52379 
52380 	/* All the flags fit in 16 bits, so will fit into duk_bool_t. */
52381 
52382 	has_writable = (defprop_flags & DUK_DEFPROP_HAVE_WRITABLE);
52383 	has_enumerable = (defprop_flags & DUK_DEFPROP_HAVE_ENUMERABLE);
52384 	has_configurable = (defprop_flags & DUK_DEFPROP_HAVE_CONFIGURABLE);
52385 	has_value = (defprop_flags & DUK_DEFPROP_HAVE_VALUE);
52386 	has_get = (defprop_flags & DUK_DEFPROP_HAVE_GETTER);
52387 	has_set = (defprop_flags & DUK_DEFPROP_HAVE_SETTER);
52388 	is_writable = (defprop_flags & DUK_DEFPROP_WRITABLE);
52389 	is_enumerable = (defprop_flags & DUK_DEFPROP_ENUMERABLE);
52390 	is_configurable = (defprop_flags & DUK_DEFPROP_CONFIGURABLE);
52391 	throw_flag = 1;   /* Object.defineProperty() calls [[DefineOwnProperty]] with Throw=true */
52392 	force_flag = (defprop_flags & DUK_DEFPROP_FORCE);
52393 
52394 	arr_idx = DUK_HSTRING_GET_ARRIDX_SLOW(key);
52395 
52396 	arridx_new_array_length = 0;
52397 	pending_write_protect = 0;
52398 	arrlen_old_len = 0;
52399 	arrlen_new_len = 0;
52400 
52401 	DUK_DDD(DUK_DDDPRINT("has_enumerable=%ld is_enumerable=%ld "
52402 	                     "has_configurable=%ld is_configurable=%ld "
52403 	                     "has_writable=%ld is_writable=%ld "
52404 	                     "has_value=%ld value=%!T "
52405 	                     "has_get=%ld get=%p=%!O "
52406 	                     "has_set=%ld set=%p=%!O "
52407 	                     "arr_idx=%ld",
52408 	                     (long) has_enumerable, (long) is_enumerable,
52409 	                     (long) has_configurable, (long) is_configurable,
52410 	                     (long) has_writable, (long) is_writable,
52411 	                     (long) has_value, (duk_tval *) (idx_value >= 0 ? duk_get_tval(ctx, idx_value) : NULL),
52412 	                     (long) has_get, (void *) get, (duk_heaphdr *) get,
52413 	                     (long) has_set, (void *) set, (duk_heaphdr *) set,
52414 	                     (long) arr_idx));
52415 
52416 	/*
52417 	 *  Array exotic behaviors can be implemented at this point.  The local variables
52418 	 *  are essentially a 'value copy' of the input descriptor (Desc), which is modified
52419 	 *  by the Array [[DefineOwnProperty]] (E5 Section 15.4.5.1).
52420 	 */
52421 
52422 	if (!DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {
52423 		goto skip_array_exotic;
52424 	}
52425 
52426 	if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
52427 		/* E5 Section 15.4.5.1, step 3, steps a - i are implemented here, j - n at the end */
52428 		if (!has_value) {
52429 			DUK_DDD(DUK_DDDPRINT("exotic array behavior for 'length', but no value in descriptor -> normal behavior"));
52430 			goto skip_array_exotic;
52431 		}
52432 
52433 		DUK_DDD(DUK_DDDPRINT("exotic array behavior for 'length', value present in descriptor -> exotic behavior"));
52434 
52435 		/*
52436 		 *  Get old and new length
52437 		 */
52438 
52439 		/* Note: reuse 'curr' as a temp propdesc */
52440 		arrlen_old_len = duk__get_old_array_length(thr, obj, &curr);
52441 
52442 		duk_dup(ctx, idx_value);
52443 		arrlen_new_len = duk__to_new_array_length_checked(thr);
52444 		duk_push_u32(ctx, arrlen_new_len);
52445 		duk_replace(ctx, idx_value);  /* step 3.e: replace 'Desc.[[Value]]' */
52446 
52447 		DUK_DDD(DUK_DDDPRINT("old_len=%ld, new_len=%ld", (long) arrlen_old_len, (long) arrlen_new_len));
52448 
52449 		if (arrlen_new_len >= arrlen_old_len) {
52450 			/* standard behavior, step 3.f.i */
52451 			DUK_DDD(DUK_DDDPRINT("new length is same or higher as previous => standard behavior"));
52452 			goto skip_array_exotic;
52453 		}
52454 		DUK_DDD(DUK_DDDPRINT("new length is smaller than previous => exotic post behavior"));
52455 
52456 		/* XXX: consolidated algorithm step 15.f -> redundant? */
52457 		if (!(curr.flags & DUK_PROPDESC_FLAG_WRITABLE) && !force_flag) {
52458 			/* Note: 'curr' refers to 'length' propdesc */
52459 			goto fail_not_writable_array_length;
52460 		}
52461 
52462 		/* steps 3.h and 3.i */
52463 		if (has_writable && !is_writable) {
52464 			DUK_DDD(DUK_DDDPRINT("desc writable is false, force it back to true, and flag pending write protect"));
52465 			is_writable = 1;
52466 			pending_write_protect = 1;
52467 		}
52468 
52469 		/* remaining actual steps are carried out if standard DefineOwnProperty succeeds */
52470 	} else if (arr_idx != DUK__NO_ARRAY_INDEX) {
52471 		/* XXX: any chance of unifying this with the 'length' key handling? */
52472 
52473 		/* E5 Section 15.4.5.1, step 4 */
52474 		duk_uint32_t old_len;
52475 
52476 		/* Note: use 'curr' as a temp propdesc */
52477 		old_len = duk__get_old_array_length(thr, obj, &curr);
52478 
52479 		if (arr_idx >= old_len) {
52480 			DUK_DDD(DUK_DDDPRINT("defineProperty requires array length update "
52481 			                     "(arr_idx=%ld, old_len=%ld)",
52482 			                     (long) arr_idx, (long) old_len));
52483 
52484 			if (!(curr.flags & DUK_PROPDESC_FLAG_WRITABLE)) {
52485 				/* Note: 'curr' refers to 'length' propdesc */
52486 				goto fail_not_writable_array_length;
52487 			}
52488 
52489 			/* actual update happens once write has been completed without
52490 			 * error below.
52491 			 */
52492 			DUK_ASSERT(arr_idx != 0xffffffffUL);
52493 			arridx_new_array_length = arr_idx + 1;
52494 		} else {
52495 			DUK_DDD(DUK_DDDPRINT("defineProperty does not require length update "
52496 			                     "(arr_idx=%ld, old_len=%ld) -> standard behavior",
52497 			                     (long) arr_idx, (long) old_len));
52498 		}
52499 	}
52500  skip_array_exotic:
52501 
52502 	/* XXX: There is currently no support for writing buffer object
52503 	 * indexed elements here.  Attempt to do so will succeed and
52504 	 * write a concrete property into the buffer object.  This should
52505 	 * be fixed at some point but because buffers are a custom feature
52506 	 * anyway, this is relatively unimportant.
52507 	 */
52508 
52509 	/*
52510 	 *  Actual Object.defineProperty() default algorithm.
52511 	 */
52512 
52513 	/*
52514 	 *  First check whether property exists; if not, simple case.  This covers
52515 	 *  steps 1-4.
52516 	 */
52517 
52518 	if (!duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &curr, DUK_GETDESC_FLAG_PUSH_VALUE)) {
52519 		DUK_DDD(DUK_DDDPRINT("property does not exist"));
52520 
52521 		if (!DUK_HOBJECT_HAS_EXTENSIBLE(obj) && !force_flag) {
52522 			goto fail_not_extensible;
52523 		}
52524 
52525 		/* XXX: share final setting code for value and flags?  difficult because
52526 		 * refcount code is different.  Share entry allocation?  But can't allocate
52527 		 * until array index checked.
52528 		 */
52529 
52530 		/* steps 4.a and 4.b are tricky */
52531 		if (has_set || has_get) {
52532 			duk_int_t e_idx;
52533 
52534 			DUK_DDD(DUK_DDDPRINT("create new accessor property"));
52535 
52536 			DUK_ASSERT(has_set || set == NULL);
52537 			DUK_ASSERT(has_get || get == NULL);
52538 			DUK_ASSERT(!has_value);
52539 			DUK_ASSERT(!has_writable);
52540 
52541 			new_flags = DUK_PROPDESC_FLAG_ACCESSOR;  /* defaults, E5 Section 8.6.1, Table 7 */
52542 			if (has_enumerable && is_enumerable) {
52543 				new_flags |= DUK_PROPDESC_FLAG_ENUMERABLE;
52544 			}
52545 			if (has_configurable && is_configurable) {
52546 				new_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;
52547 			}
52548 
52549 			if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
52550 				DUK_DDD(DUK_DDDPRINT("accessor cannot go to array part, abandon array"));
52551 				duk__abandon_array_checked(thr, obj);
52552 			}
52553 
52554 			/* write to entry part */
52555 			e_idx = duk__alloc_entry_checked(thr, obj, key);
52556 			DUK_ASSERT(e_idx >= 0);
52557 
52558 			DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, e_idx, get);
52559 			DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, e_idx, set);
52560 			DUK_HOBJECT_INCREF_ALLOWNULL(thr, get);
52561 			DUK_HOBJECT_INCREF_ALLOWNULL(thr, set);
52562 
52563 			DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, e_idx, new_flags);
52564 			goto success_exotics;
52565 		} else {
52566 			duk_int_t e_idx;
52567 			duk_tval *tv2;
52568 
52569 			DUK_DDD(DUK_DDDPRINT("create new data property"));
52570 
52571 			DUK_ASSERT(!has_set);
52572 			DUK_ASSERT(!has_get);
52573 
52574 			new_flags = 0;  /* defaults, E5 Section 8.6.1, Table 7 */
52575 			if (has_writable && is_writable) {
52576 				new_flags |= DUK_PROPDESC_FLAG_WRITABLE;
52577 			}
52578 			if (has_enumerable && is_enumerable) {
52579 				new_flags |= DUK_PROPDESC_FLAG_ENUMERABLE;
52580 			}
52581 			if (has_configurable && is_configurable) {
52582 				new_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;
52583 			}
52584 			if (has_value) {
52585 				duk_tval *tv_tmp = duk_require_tval(ctx, idx_value);
52586 				DUK_TVAL_SET_TVAL(&tv, tv_tmp);
52587 			} else {
52588 				DUK_TVAL_SET_UNDEFINED(&tv);  /* default value */
52589 			}
52590 
52591 			if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
52592 				if (new_flags == DUK_PROPDESC_FLAGS_WEC) {
52593 #if 0
52594 					DUK_DDD(DUK_DDDPRINT("new data property attributes match array defaults, attempt to write to array part"));
52595 					/* may become sparse...*/
52596 #endif
52597 					/* XXX: handling for array part missing now; this doesn't affect
52598 					 * compliance but causes array entry writes using defineProperty()
52599 					 * to always abandon array part.
52600 					 */
52601 				}
52602 				DUK_DDD(DUK_DDDPRINT("new data property cannot go to array part, abandon array"));
52603 				duk__abandon_array_checked(thr, obj);
52604 				/* fall through */
52605 			}
52606 
52607 			/* write to entry part */
52608 			e_idx = duk__alloc_entry_checked(thr, obj, key);
52609 			DUK_ASSERT(e_idx >= 0);
52610 			tv2 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, e_idx);
52611 			DUK_TVAL_SET_TVAL(tv2, &tv);
52612 			DUK_TVAL_INCREF(thr, tv2);
52613 
52614 			DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, e_idx, new_flags);
52615 			goto success_exotics;
52616 		}
52617 		DUK_UNREACHABLE();
52618 	}
52619 
52620 	/* we currently assume virtual properties are not configurable (as none of them are) */
52621 	DUK_ASSERT((curr.e_idx >= 0 || curr.a_idx >= 0) || !(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE));
52622 
52623 	/* [obj key desc value get set curr_value] */
52624 
52625 	/*
52626 	 *  Property already exists.  Steps 5-6 detect whether any changes need
52627 	 *  to be made.
52628 	 */
52629 
52630 	if (has_enumerable) {
52631 		if (is_enumerable) {
52632 			if (!(curr.flags & DUK_PROPDESC_FLAG_ENUMERABLE)) {
52633 				goto need_check;
52634 			}
52635 		} else {
52636 			if (curr.flags & DUK_PROPDESC_FLAG_ENUMERABLE) {
52637 				goto need_check;
52638 			}
52639 		}
52640 	}
52641 	if (has_configurable) {
52642 		if (is_configurable) {
52643 			if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE)) {
52644 				goto need_check;
52645 			}
52646 		} else {
52647 			if (curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) {
52648 				goto need_check;
52649 			}
52650 		}
52651 	}
52652 	if (has_value) {
52653 		duk_tval *tmp1;
52654 		duk_tval *tmp2;
52655 
52656 		/* attempt to change from accessor to data property */
52657 		if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
52658 			goto need_check;
52659 		}
52660 
52661 		tmp1 = duk_require_tval(ctx, -1);         /* curr value */
52662 		tmp2 = duk_require_tval(ctx, idx_value);  /* new value */
52663 		if (!duk_js_samevalue(tmp1, tmp2)) {
52664 			goto need_check;
52665 		}
52666 	}
52667 	if (has_writable) {
52668 		/* attempt to change from accessor to data property */
52669 		if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
52670 			goto need_check;
52671 		}
52672 
52673 		if (is_writable) {
52674 			if (!(curr.flags & DUK_PROPDESC_FLAG_WRITABLE)) {
52675 				goto need_check;
52676 			}
52677 		} else {
52678 			if (curr.flags & DUK_PROPDESC_FLAG_WRITABLE) {
52679 				goto need_check;
52680 			}
52681 		}
52682 	}
52683 	if (has_set) {
52684 		if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
52685 			if (set != curr.set) {
52686 				goto need_check;
52687 			}
52688 		} else {
52689 			goto need_check;
52690 		}
52691 	}
52692 	if (has_get) {
52693 		if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
52694 			if (get != curr.get) {
52695 				goto need_check;
52696 			}
52697 		} else {
52698 			goto need_check;
52699 		}
52700 	}
52701 
52702 	/* property exists, either 'desc' is empty, or all values
52703 	 * match (SameValue)
52704 	 */
52705 	goto success_no_exotics;
52706 
52707  need_check:
52708 
52709 	/*
52710 	 *  Some change(s) need to be made.  Steps 7-11.
52711 	 */
52712 
52713 	/* shared checks for all descriptor types */
52714 	if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
52715 		if (has_configurable && is_configurable) {
52716 			goto fail_not_configurable;
52717 		}
52718 		if (has_enumerable) {
52719 			if (curr.flags & DUK_PROPDESC_FLAG_ENUMERABLE) {
52720 				if (!is_enumerable) {
52721 					goto fail_not_configurable;
52722 				}
52723 			} else {
52724 				if (is_enumerable) {
52725 					goto fail_not_configurable;
52726 				}
52727 			}
52728 		}
52729 	}
52730 
52731 	/* Reject attempt to change virtual properties: not part of the
52732 	 * standard algorithm, applies currently to e.g. virtual index
52733 	 * properties of buffer objects (which are virtual but writable).
52734 	 * (Cannot "force" modification of a virtual property.)
52735 	 */
52736 	if (curr.flags & DUK_PROPDESC_FLAG_VIRTUAL) {
52737 		goto fail_virtual;
52738 	}
52739 
52740 	/* Reject attempt to change a read-only object. */
52741 #if defined(DUK_USE_ROM_OBJECTS)
52742 	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {
52743 		DUK_DD(DUK_DDPRINT("attempt to define property on read-only target object"));
52744 		goto fail_not_configurable;
52745 	}
52746 #endif
52747 
52748 	/* descriptor type specific checks */
52749 	if (has_set || has_get) {
52750 		/* IsAccessorDescriptor(desc) == true */
52751 		DUK_ASSERT(!has_writable);
52752 		DUK_ASSERT(!has_value);
52753 
52754 		if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
52755 			/* curr and desc are accessors */
52756 			if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
52757 				if (has_set && set != curr.set) {
52758 					goto fail_not_configurable;
52759 				}
52760 				if (has_get && get != curr.get) {
52761 					goto fail_not_configurable;
52762 				}
52763 			}
52764 		} else {
52765 			duk_bool_t rc;
52766 			duk_tval *tv1;
52767 			duk_tval tv_tmp;
52768 
52769 			/* curr is data, desc is accessor */
52770 			if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
52771 				goto fail_not_configurable;
52772 			}
52773 
52774 			DUK_DDD(DUK_DDDPRINT("convert property to accessor property"));
52775 			if (curr.a_idx >= 0) {
52776 				DUK_DDD(DUK_DDDPRINT("property to convert is stored in an array entry, abandon array and re-lookup"));
52777 				duk__abandon_array_checked(thr, obj);
52778 				duk_pop(ctx);  /* remove old value */
52779 				rc = duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &curr, DUK_GETDESC_FLAG_PUSH_VALUE);
52780 				DUK_UNREF(rc);
52781 				DUK_ASSERT(rc != 0);
52782 				DUK_ASSERT(curr.e_idx >= 0 && curr.a_idx < 0);
52783 			}
52784 
52785 			DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, curr.e_idx));
52786 
52787 			/* Avoid side effects that might disturb curr.e_idx until
52788 			 * we're done editing the slot.
52789 			 */
52790 			tv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, curr.e_idx);
52791 			DUK_TVAL_SET_TVAL(&tv_tmp, tv1);
52792 			DUK_TVAL_SET_UNDEFINED(tv1);
52793 
52794 			DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, curr.e_idx, NULL);
52795 			DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, curr.e_idx, NULL);
52796 			DUK_HOBJECT_E_SLOT_CLEAR_WRITABLE(thr->heap, obj, curr.e_idx);
52797 			DUK_HOBJECT_E_SLOT_SET_ACCESSOR(thr->heap, obj, curr.e_idx);
52798 
52799 			DUK_DDD(DUK_DDDPRINT("flags after data->accessor conversion: 0x%02lx",
52800 			                     (unsigned long) DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, curr.e_idx)));
52801 
52802 			DUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */
52803 
52804 			/* re-lookup to update curr.flags
52805 			 * XXX: would be faster to update directly
52806 			 */
52807 			duk_pop(ctx);  /* remove old value */
52808 			rc = duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &curr, DUK_GETDESC_FLAG_PUSH_VALUE);
52809 			DUK_UNREF(rc);
52810 			DUK_ASSERT(rc != 0);
52811 		}
52812 	} else if (has_value || has_writable) {
52813 		/* IsDataDescriptor(desc) == true */
52814 		DUK_ASSERT(!has_set);
52815 		DUK_ASSERT(!has_get);
52816 
52817 		if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
52818 			duk_bool_t rc;
52819 			duk_hobject *h_get;
52820 			duk_hobject *h_set;
52821 
52822 			/* curr is accessor, desc is data */
52823 			if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
52824 				goto fail_not_configurable;
52825 			}
52826 
52827 			/* curr is accessor -> cannot be in array part */
52828 			DUK_ASSERT(curr.e_idx >= 0 && curr.a_idx < 0);
52829 
52830 			DUK_DDD(DUK_DDDPRINT("convert property to data property"));
52831 
52832 			/* Avoid side effects that might disturb curr.e_idx until
52833 			 * we're done editing the slot.
52834 			 */
52835 			DUK_ASSERT(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, curr.e_idx));
52836 			h_get = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, obj, curr.e_idx);
52837 			DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, curr.e_idx, NULL);
52838 			h_set = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, obj, curr.e_idx);
52839 			DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, curr.e_idx, NULL);
52840 
52841 			DUK_TVAL_SET_UNDEFINED(DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, curr.e_idx));
52842 			DUK_HOBJECT_E_SLOT_CLEAR_WRITABLE(thr->heap, obj, curr.e_idx);
52843 			DUK_HOBJECT_E_SLOT_CLEAR_ACCESSOR(thr->heap, obj, curr.e_idx);
52844 
52845 			DUK_DDD(DUK_DDDPRINT("flags after accessor->data conversion: 0x%02lx",
52846 			                     (unsigned long) DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, curr.e_idx)));
52847 
52848 			DUK_HOBJECT_DECREF_ALLOWNULL(thr, h_get);  /* side effects */
52849 			DUK_HOBJECT_DECREF_ALLOWNULL(thr, h_set);  /* side effects */
52850 
52851 			/* re-lookup to update curr.flags
52852 			 * XXX: would be faster to update directly
52853 			 */
52854 			duk_pop(ctx);  /* remove old value */
52855 			rc = duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &curr, DUK_GETDESC_FLAG_PUSH_VALUE);
52856 			DUK_UNREF(rc);
52857 			DUK_ASSERT(rc != 0);
52858 		} else {
52859 			/* curr and desc are data */
52860 			if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
52861 				if (!(curr.flags & DUK_PROPDESC_FLAG_WRITABLE) && has_writable && is_writable) {
52862 					goto fail_not_configurable;
52863 				}
52864 				/* Note: changing from writable to non-writable is OK */
52865 				if (!(curr.flags & DUK_PROPDESC_FLAG_WRITABLE) && has_value) {
52866 					duk_tval *tmp1 = duk_require_tval(ctx, -1);         /* curr value */
52867 					duk_tval *tmp2 = duk_require_tval(ctx, idx_value);  /* new value */
52868 					if (!duk_js_samevalue(tmp1, tmp2)) {
52869 						goto fail_not_configurable;
52870 					}
52871 				}
52872 			}
52873 		}
52874 	} else {
52875 		/* IsGenericDescriptor(desc) == true; this means in practice that 'desc'
52876 		 * only has [[Enumerable]] or [[Configurable]] flag updates, which are
52877 		 * allowed at this point.
52878 		 */
52879 
52880 		DUK_ASSERT(!has_value && !has_writable && !has_get && !has_set);
52881 	}
52882 
52883 	/*
52884 	 *  Start doing property attributes updates.  Steps 12-13.
52885 	 *
52886 	 *  Start by computing new attribute flags without writing yet.
52887 	 *  Property type conversion is done above if necessary.
52888 	 */
52889 
52890 	new_flags = curr.flags;
52891 
52892 	if (has_enumerable) {
52893 		if (is_enumerable) {
52894 			new_flags |= DUK_PROPDESC_FLAG_ENUMERABLE;
52895 		} else {
52896 			new_flags &= ~DUK_PROPDESC_FLAG_ENUMERABLE;
52897 		}
52898 	}
52899 	if (has_configurable) {
52900 		if (is_configurable) {
52901 			new_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;
52902 		} else {
52903 			new_flags &= ~DUK_PROPDESC_FLAG_CONFIGURABLE;
52904 		}
52905 	}
52906 	if (has_writable) {
52907 		if (is_writable) {
52908 			new_flags |= DUK_PROPDESC_FLAG_WRITABLE;
52909 		} else {
52910 			new_flags &= ~DUK_PROPDESC_FLAG_WRITABLE;
52911 		}
52912 	}
52913 
52914 	/* XXX: write protect after flag? -> any chance of handling it here? */
52915 
52916 	DUK_DDD(DUK_DDDPRINT("new flags that we want to write: 0x%02lx",
52917 	                     (unsigned long) new_flags));
52918 
52919 	/*
52920 	 *  Check whether we need to abandon an array part (if it exists)
52921 	 */
52922 
52923 	if (curr.a_idx >= 0) {
52924 		duk_bool_t rc;
52925 
52926 		DUK_ASSERT(curr.e_idx < 0);
52927 
52928 		if (new_flags == DUK_PROPDESC_FLAGS_WEC) {
52929 			duk_tval *tv1, *tv2;
52930 
52931 			DUK_DDD(DUK_DDDPRINT("array index, new property attributes match array defaults, update in-place"));
52932 
52933 			DUK_ASSERT(curr.flags == DUK_PROPDESC_FLAGS_WEC);  /* must have been, since in array part */
52934 			DUK_ASSERT(!has_set);
52935 			DUK_ASSERT(!has_get);
52936 
52937 			tv2 = duk_require_tval(ctx, idx_value);
52938 			tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, curr.a_idx);
52939 			DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2);  /* side effects */
52940 			goto success_exotics;
52941 		}
52942 
52943 		DUK_DDD(DUK_DDDPRINT("array index, new property attributes do not match array defaults, abandon array and re-lookup"));
52944 		duk__abandon_array_checked(thr, obj);
52945 		duk_pop(ctx);  /* remove old value */
52946 		rc = duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &curr, DUK_GETDESC_FLAG_PUSH_VALUE);
52947 		DUK_UNREF(rc);
52948 		DUK_ASSERT(rc != 0);
52949 		DUK_ASSERT(curr.e_idx >= 0 && curr.a_idx < 0);
52950 	}
52951 
52952 	DUK_DDD(DUK_DDDPRINT("updating existing property in entry part"));
52953 
52954 	/* array case is handled comprehensively above */
52955 	DUK_ASSERT(curr.e_idx >= 0 && curr.a_idx < 0);
52956 
52957 	DUK_DDD(DUK_DDDPRINT("update existing property attributes"));
52958 	DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, curr.e_idx, new_flags);
52959 
52960 	if (has_set) {
52961 		duk_hobject *tmp;
52962 
52963 		DUK_DDD(DUK_DDDPRINT("update existing property setter"));
52964 		DUK_ASSERT(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, curr.e_idx));
52965 
52966 		tmp = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, obj, curr.e_idx);
52967 		DUK_UNREF(tmp);
52968 		DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, curr.e_idx, set);
52969 		DUK_HOBJECT_INCREF_ALLOWNULL(thr, set);
52970 		DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);  /* side effects */
52971 	}
52972 	if (has_get) {
52973 		duk_hobject *tmp;
52974 
52975 		DUK_DDD(DUK_DDDPRINT("update existing property getter"));
52976 		DUK_ASSERT(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, curr.e_idx));
52977 
52978 		tmp = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, obj, curr.e_idx);
52979 		DUK_UNREF(tmp);
52980 		DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, curr.e_idx, get);
52981 		DUK_HOBJECT_INCREF_ALLOWNULL(thr, get);
52982 		DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);  /* side effects */
52983 	}
52984 	if (has_value) {
52985 		duk_tval *tv1, *tv2;
52986 
52987 		DUK_DDD(DUK_DDDPRINT("update existing property value"));
52988 		DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, curr.e_idx));
52989 
52990 		tv2 = duk_require_tval(ctx, idx_value);
52991 		tv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, curr.e_idx);
52992 		DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2);  /* side effects */
52993 	}
52994 
52995 	/*
52996 	 *  Standard algorithm succeeded without errors, check for exotic post-behaviors.
52997 	 *
52998 	 *  Arguments exotic behavior in E5 Section 10.6 occurs after the standard
52999 	 *  [[DefineOwnProperty]] has completed successfully.
53000 	 *
53001 	 *  Array exotic behavior in E5 Section 15.4.5.1 is implemented partly
53002 	 *  prior to the default [[DefineOwnProperty]], but:
53003 	 *    - for an array index key (e.g. "10") the final 'length' update occurs here
53004 	 *    - for 'length' key the element deletion and 'length' update occurs here
53005 	 */
53006 
53007  success_exotics:
53008 
53009 	/* [obj key desc value get set curr_value] */
53010 
53011 	if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {
53012 		if (arridx_new_array_length > 0) {
53013 			duk_tval *tmp;
53014 			duk_bool_t rc;
53015 
53016 			/*
53017 			 *  Note: zero works as a "no update" marker because the new length
53018 			 *  can never be zero after a new property is written.
53019 			 */
53020 
53021 			/* E5 Section 15.4.5.1, steps 4.e.i - 4.e.ii */
53022 
53023 			DUK_DDD(DUK_DDDPRINT("defineProperty successful, pending array length update to: %ld",
53024 			                     (long) arridx_new_array_length));
53025 
53026 			/* Note: reuse 'curr' */
53027 			rc = duk__get_own_propdesc_raw(thr, obj, DUK_HTHREAD_STRING_LENGTH(thr), DUK__NO_ARRAY_INDEX, &curr, 0 /*flags*/);  /* don't push value */
53028 			DUK_UNREF(rc);
53029 			DUK_ASSERT(rc != 0);
53030 			DUK_ASSERT(curr.e_idx >= 0);
53031 
53032 			tmp = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, curr.e_idx);
53033 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tmp));
53034 			/* no need for decref/incref because value is a number */
53035 			DUK_TVAL_SET_FASTINT_U32(tmp, arridx_new_array_length);
53036 		}
53037 		if (key == DUK_HTHREAD_STRING_LENGTH(thr) && arrlen_new_len < arrlen_old_len) {
53038 			/*
53039 			 *  E5 Section 15.4.5.1, steps 3.k - 3.n.  The order at the end combines
53040 			 *  the error case 3.l.iii and the success case 3.m-3.n.
53041 			 *
53042 			 *  Note: 'length' is always in entries part, so no array abandon issues for
53043 			 *  'writable' update.
53044 			 */
53045 
53046 			/* XXX: investigate whether write protect can be handled above, if we
53047 			 * just update length here while ignoring its protected status
53048 			 */
53049 
53050 			duk_tval *tmp;
53051 			duk_uint32_t result_len;
53052 			duk_bool_t rc;
53053 
53054 			DUK_DDD(DUK_DDDPRINT("defineProperty successful, key is 'length', exotic array behavior, "
53055 			                     "doing array element deletion and length update"));
53056 
53057 			rc = duk__handle_put_array_length_smaller(thr, obj, arrlen_old_len, arrlen_new_len, force_flag, &result_len);
53058 
53059 			/* update length (curr points to length, and we assume it's still valid) */
53060 			DUK_ASSERT(result_len >= arrlen_new_len && result_len <= arrlen_old_len);
53061 
53062 			DUK_ASSERT(curr.e_idx >= 0);
53063 			DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, curr.e_idx));
53064 			tmp = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, curr.e_idx);
53065 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tmp));
53066 			/* no decref needed for a number */
53067 			DUK_TVAL_SET_FASTINT_U32(tmp, result_len);
53068 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tmp));
53069 
53070 			if (pending_write_protect) {
53071 				DUK_DDD(DUK_DDDPRINT("setting array length non-writable (pending writability update)"));
53072 				DUK_HOBJECT_E_SLOT_CLEAR_WRITABLE(thr->heap, obj, curr.e_idx);
53073 			}
53074 
53075 			/*
53076 			 *  XXX: shrink array allocation or entries compaction here?
53077 			 */
53078 
53079 			if (!rc) {
53080 				goto fail_array_length_partial;
53081 			}
53082 		}
53083 	} else if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj)) {
53084 		duk_hobject *map;
53085 		duk_hobject *varenv;
53086 
53087 		DUK_ASSERT(arridx_new_array_length == 0);
53088 		DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj));  /* traits are separate; in particular, arguments not an array */
53089 
53090 		map = NULL;
53091 		varenv = NULL;
53092 		if (!duk__lookup_arguments_map(thr, obj, key, &curr, &map, &varenv)) {
53093 			goto success_no_exotics;
53094 		}
53095 		DUK_ASSERT(map != NULL);
53096 		DUK_ASSERT(varenv != NULL);
53097 
53098 		/* [obj key desc value get set curr_value varname] */
53099 
53100 		if (has_set || has_get) {
53101 			/* = IsAccessorDescriptor(Desc) */
53102 			DUK_DDD(DUK_DDDPRINT("defineProperty successful, key mapped to arguments 'map' "
53103 			                     "changed to an accessor, delete arguments binding"));
53104 
53105 			(void) duk_hobject_delprop_raw(thr, map, key, 0);  /* ignore result */
53106 		} else {
53107 			/* Note: this order matters (final value before deleting map entry must be done) */
53108 			DUK_DDD(DUK_DDDPRINT("defineProperty successful, key mapped to arguments 'map', "
53109 			                     "check for value update / binding deletion"));
53110 
53111 			if (has_value) {
53112 				duk_hstring *varname;
53113 
53114 				DUK_DDD(DUK_DDDPRINT("defineProperty successful, key mapped to arguments 'map', "
53115 				                     "update bound value (variable/argument)"));
53116 
53117 				varname = duk_require_hstring(ctx, -1);
53118 				DUK_ASSERT(varname != NULL);
53119 
53120 				DUK_DDD(DUK_DDDPRINT("arguments object automatic putvar for a bound variable; "
53121 				                     "key=%!O, varname=%!O, value=%!T",
53122 				                     (duk_heaphdr *) key,
53123 				                     (duk_heaphdr *) varname,
53124 				                     (duk_tval *) duk_require_tval(ctx, idx_value)));
53125 
53126 				/* strict flag for putvar comes from our caller (currently: fixed) */
53127 				duk_js_putvar_envrec(thr, varenv, varname, duk_require_tval(ctx, idx_value), throw_flag);
53128 			}
53129 			if (has_writable && !is_writable) {
53130 				DUK_DDD(DUK_DDDPRINT("defineProperty successful, key mapped to arguments 'map', "
53131 				                     "changed to non-writable, delete arguments binding"));
53132 
53133 				(void) duk_hobject_delprop_raw(thr, map, key, 0);  /* ignore result */
53134 			}
53135 		}
53136 
53137 		/* 'varname' is in stack in this else branch, leaving an unbalanced stack below,
53138 		 * but this doesn't matter now.
53139 		 */
53140 	}
53141 
53142  success_no_exotics:
53143 	return;
53144 
53145  fail_virtual:
53146 	DUK_ERROR_TYPE(thr, DUK_STR_PROPERTY_IS_VIRTUAL);
53147 	return;
53148 
53149  fail_not_writable_array_length:
53150 	DUK_ERROR_TYPE(thr, DUK_STR_ARRAY_LENGTH_NOT_WRITABLE);
53151 	return;
53152 
53153  fail_not_extensible:
53154 	DUK_ERROR_TYPE(thr, DUK_STR_NOT_EXTENSIBLE);
53155 	return;
53156 
53157  fail_not_configurable:
53158 	DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);
53159 	return;
53160 
53161  fail_array_length_partial:
53162 	DUK_ERROR_TYPE(thr, DUK_STR_ARRAY_LENGTH_WRITE_FAILED);
53163 	return;
53164 }
53165 
53166 /*
53167  *  Object.prototype.hasOwnProperty() and Object.prototype.propertyIsEnumerable().
53168  */
53169 
53170 DUK_INTERNAL duk_bool_t duk_hobject_object_ownprop_helper(duk_context *ctx, duk_small_uint_t required_desc_flags) {
53171 	duk_hthread *thr = (duk_hthread *) ctx;
53172 	duk_hstring *h_v;
53173 	duk_hobject *h_obj;
53174 	duk_propdesc desc;
53175 	duk_bool_t ret;
53176 
53177 	/* coercion order matters */
53178 	h_v = duk_to_hstring(ctx, 0);
53179 	DUK_ASSERT(h_v != NULL);
53180 
53181 	h_obj = duk_push_this_coercible_to_object(ctx);
53182 	DUK_ASSERT(h_obj != NULL);
53183 
53184 	ret = duk_hobject_get_own_propdesc(thr, h_obj, h_v, &desc, 0 /*flags*/);  /* don't push value */
53185 
53186 	duk_push_boolean(ctx, ret && ((desc.flags & required_desc_flags) == required_desc_flags));
53187 	return 1;
53188 }
53189 
53190 /*
53191  *  Object.seal() and Object.freeze()  (E5 Sections 15.2.3.8 and 15.2.3.9)
53192  *
53193  *  Since the algorithms are similar, a helper provides both functions.
53194  *  Freezing is essentially sealing + making plain properties non-writable.
53195  *
53196  *  Note: virtual (non-concrete) properties which are non-configurable but
53197  *  writable would pose some problems, but such properties do not currently
53198  *  exist (all virtual properties are non-configurable and non-writable).
53199  *  If they did exist, the non-configurability does NOT prevent them from
53200  *  becoming non-writable.  However, this change should be recorded somehow
53201  *  so that it would turn up (e.g. when getting the property descriptor),
53202  *  requiring some additional flags in the object.
53203  */
53204 
53205 DUK_INTERNAL void duk_hobject_object_seal_freeze_helper(duk_hthread *thr, duk_hobject *obj, duk_bool_t is_freeze) {
53206 	duk_uint_fast32_t i;
53207 
53208 	DUK_ASSERT(thr != NULL);
53209 	DUK_ASSERT(thr->heap != NULL);
53210 	DUK_ASSERT(obj != NULL);
53211 
53212 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
53213 
53214 #if defined(DUK_USE_ROM_OBJECTS)
53215 	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {
53216 		DUK_DD(DUK_DDPRINT("attempt to seal/freeze a readonly object, reject"));
53217 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);
53218 	}
53219 #endif
53220 
53221 	/*
53222 	 *  Abandon array part because all properties must become non-configurable.
53223 	 *  Note that this is now done regardless of whether this is always the case
53224 	 *  (skips check, but performance problem if caller would do this many times
53225 	 *  for the same object; not likely).
53226 	 */
53227 
53228 	duk__abandon_array_checked(thr, obj);
53229 	DUK_ASSERT(DUK_HOBJECT_GET_ASIZE(obj) == 0);
53230 
53231 	for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
53232 		duk_uint8_t *fp;
53233 
53234 		/* since duk__abandon_array_checked() causes a resize, there should be no gaps in keys */
53235 		DUK_ASSERT(DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i) != NULL);
53236 
53237 		/* avoid multiple computations of flags address; bypasses macros */
53238 		fp = DUK_HOBJECT_E_GET_FLAGS_PTR(thr->heap, obj, i);
53239 		if (is_freeze && !((*fp) & DUK_PROPDESC_FLAG_ACCESSOR)) {
53240 			*fp &= ~(DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_CONFIGURABLE);
53241 		} else {
53242 			*fp &= ~DUK_PROPDESC_FLAG_CONFIGURABLE;
53243 		}
53244 	}
53245 
53246 	DUK_HOBJECT_CLEAR_EXTENSIBLE(obj);
53247 
53248 	/* no need to compact since we already did that in duk__abandon_array_checked()
53249 	 * (regardless of whether an array part existed or not.
53250 	 */
53251 
53252 	return;
53253 }
53254 
53255 /*
53256  *  Object.isSealed() and Object.isFrozen()  (E5 Sections 15.2.3.11, 15.2.3.13)
53257  *
53258  *  Since the algorithms are similar, a helper provides both functions.
53259  *  Freezing is essentially sealing + making plain properties non-writable.
53260  *
53261  *  Note: all virtual (non-concrete) properties are currently non-configurable
53262  *  and non-writable (and there are no accessor virtual properties), so they don't
53263  *  need to be considered here now.
53264  */
53265 
53266 DUK_INTERNAL duk_bool_t duk_hobject_object_is_sealed_frozen_helper(duk_hthread *thr, duk_hobject *obj, duk_bool_t is_frozen) {
53267 	duk_uint_fast32_t i;
53268 
53269 	DUK_ASSERT(obj != NULL);
53270 	DUK_UNREF(thr);
53271 
53272 	/* Note: no allocation pressure, no need to check refcounts etc */
53273 
53274 	/* must not be extensible */
53275 	if (DUK_HOBJECT_HAS_EXTENSIBLE(obj)) {
53276 		return 0;
53277 	}
53278 
53279 	/* all virtual properties are non-configurable and non-writable */
53280 
53281 	/* entry part must not contain any configurable properties, or
53282 	 * writable properties (if is_frozen).
53283 	 */
53284 	for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
53285 		duk_small_uint_t flags;
53286 
53287 		if (!DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i)) {
53288 			continue;
53289 		}
53290 
53291 		/* avoid multiple computations of flags address; bypasses macros */
53292 		flags = (duk_small_uint_t) DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, i);
53293 
53294 		if (flags & DUK_PROPDESC_FLAG_CONFIGURABLE) {
53295 			return 0;
53296 		}
53297 		if (is_frozen &&
53298 		    !(flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
53299 		    (flags & DUK_PROPDESC_FLAG_WRITABLE)) {
53300 			return 0;
53301 		}
53302 	}
53303 
53304 	/* array part must not contain any non-unused properties, as they would
53305 	 * be configurable and writable.
53306 	 */
53307 	for (i = 0; i < DUK_HOBJECT_GET_ASIZE(obj); i++) {
53308 		duk_tval *tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, i);
53309 		if (!DUK_TVAL_IS_UNUSED(tv)) {
53310 			return 0;
53311 		}
53312 	}
53313 
53314 	return 1;
53315 }
53316 
53317 /*
53318  *  Object.preventExtensions() and Object.isExtensible()  (E5 Sections 15.2.3.10, 15.2.3.13)
53319  *
53320  *  Not needed, implemented by macros DUK_HOBJECT_{HAS,CLEAR,SET}_EXTENSIBLE
53321  *  and the Object built-in bindings.
53322  */
53323 
53324 /* Undefine local defines */
53325 
53326 #undef DUK__NO_ARRAY_INDEX
53327 #undef DUK__HASH_INITIAL
53328 #undef DUK__HASH_PROBE_STEP
53329 #undef DUK__HASH_UNUSED
53330 #undef DUK__HASH_DELETED
53331 #undef DUK__VALSTACK_SPACE
53332 /*
53333  *  Misc support functions
53334  */
53335 
53336 /* include removed: duk_internal.h */
53337 
53338 DUK_INTERNAL duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr, duk_hstring *h, duk_uint_t pos) {
53339 	duk_uint32_t boff;
53340 	const duk_uint8_t *p, *p_start, *p_end;
53341 	duk_ucodepoint_t cp;
53342 
53343 	/* Caller must check character offset to be inside the string. */
53344 	DUK_ASSERT(thr != NULL);
53345 	DUK_ASSERT(h != NULL);
53346 	DUK_ASSERT_DISABLE(pos >= 0);  /* unsigned */
53347 	DUK_ASSERT(pos < (duk_uint_t) DUK_HSTRING_GET_CHARLEN(h));
53348 
53349 	boff = duk_heap_strcache_offset_char2byte(thr, h, (duk_uint32_t) pos);
53350 	DUK_DDD(DUK_DDDPRINT("charCodeAt: pos=%ld -> boff=%ld, str=%!O",
53351 	                     (long) pos, (long) boff, (duk_heaphdr *) h));
53352 	DUK_ASSERT_DISABLE(boff >= 0);
53353 	DUK_ASSERT(boff < DUK_HSTRING_GET_BYTELEN(h));
53354 
53355 	p_start = DUK_HSTRING_GET_DATA(h);
53356 	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h);
53357 	p = p_start + boff;
53358 	DUK_DDD(DUK_DDDPRINT("p_start=%p, p_end=%p, p=%p",
53359 	                     (const void *) p_start, (const void *) p_end,
53360 	                     (const void *) p));
53361 
53362 	/* This may throw an error though not for valid E5 strings. */
53363 	cp = duk_unicode_decode_xutf8_checked(thr, &p, p_start, p_end);
53364 	return cp;
53365 }
53366 
53367 #if !defined(DUK_USE_HSTRING_CLEN)
53368 DUK_INTERNAL duk_size_t duk_hstring_get_charlen(duk_hstring *h) {
53369 	if (DUK_HSTRING_HAS_ASCII(h)) {
53370 		/* Most practical strings will go here. */
53371 		return DUK_HSTRING_GET_BYTELEN(h);
53372 	} else {
53373 		return duk_unicode_unvalidated_utf8_length(DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
53374 	}
53375 }
53376 #endif  /* !DUK_USE_HSTRING_CLEN */
53377 /*
53378  *  duk_hthread allocation and freeing.
53379  */
53380 
53381 /* include removed: duk_internal.h */
53382 
53383 /*
53384  *  Allocate initial stacks for a thread.  Note that 'thr' must be reachable
53385  *  as a garbage collection may be triggered by the allocation attempts.
53386  *  Returns zero (without leaking memory) if init fails.
53387  */
53388 
53389 DUK_INTERNAL duk_bool_t duk_hthread_init_stacks(duk_heap *heap, duk_hthread *thr) {
53390 	duk_size_t alloc_size;
53391 	duk_size_t i;
53392 
53393 	DUK_ASSERT(heap != NULL);
53394 	DUK_ASSERT(thr != NULL);
53395 	DUK_ASSERT(thr->valstack == NULL);
53396 	DUK_ASSERT(thr->valstack_end == NULL);
53397 	DUK_ASSERT(thr->valstack_bottom == NULL);
53398 	DUK_ASSERT(thr->valstack_top == NULL);
53399 	DUK_ASSERT(thr->callstack == NULL);
53400 	DUK_ASSERT(thr->catchstack == NULL);
53401 
53402 	/* valstack */
53403 	alloc_size = sizeof(duk_tval) * DUK_VALSTACK_INITIAL_SIZE;
53404 	thr->valstack = (duk_tval *) DUK_ALLOC(heap, alloc_size);
53405 	if (!thr->valstack) {
53406 		goto fail;
53407 	}
53408 	DUK_MEMZERO(thr->valstack, alloc_size);
53409 	thr->valstack_end = thr->valstack + DUK_VALSTACK_INITIAL_SIZE;
53410 #if !defined(DUK_USE_PREFER_SIZE)
53411 	thr->valstack_size = DUK_VALSTACK_INITIAL_SIZE;
53412 #endif
53413 	thr->valstack_bottom = thr->valstack;
53414 	thr->valstack_top = thr->valstack;
53415 
53416 	for (i = 0; i < DUK_VALSTACK_INITIAL_SIZE; i++) {
53417 		DUK_TVAL_SET_UNDEFINED(&thr->valstack[i]);
53418 	}
53419 
53420 	/* callstack */
53421 	alloc_size = sizeof(duk_activation) * DUK_CALLSTACK_INITIAL_SIZE;
53422 	thr->callstack = (duk_activation *) DUK_ALLOC(heap, alloc_size);
53423 	if (!thr->callstack) {
53424 		goto fail;
53425 	}
53426 	DUK_MEMZERO(thr->callstack, alloc_size);
53427 	thr->callstack_size = DUK_CALLSTACK_INITIAL_SIZE;
53428 	DUK_ASSERT(thr->callstack_top == 0);
53429 
53430 	/* catchstack */
53431 	alloc_size = sizeof(duk_catcher) * DUK_CATCHSTACK_INITIAL_SIZE;
53432 	thr->catchstack = (duk_catcher *) DUK_ALLOC(heap, alloc_size);
53433 	if (!thr->catchstack) {
53434 		goto fail;
53435 	}
53436 	DUK_MEMZERO(thr->catchstack, alloc_size);
53437 	thr->catchstack_size = DUK_CATCHSTACK_INITIAL_SIZE;
53438 	DUK_ASSERT(thr->catchstack_top == 0);
53439 
53440 	return 1;
53441 
53442  fail:
53443 	DUK_FREE(heap, thr->valstack);
53444 	DUK_FREE(heap, thr->callstack);
53445 	DUK_FREE(heap, thr->catchstack);
53446 
53447 	thr->valstack = NULL;
53448 	thr->callstack = NULL;
53449 	thr->catchstack = NULL;
53450 	return 0;
53451 }
53452 
53453 /* For indirect allocs. */
53454 
53455 DUK_INTERNAL void *duk_hthread_get_valstack_ptr(duk_heap *heap, void *ud) {
53456 	duk_hthread *thr = (duk_hthread *) ud;
53457 	DUK_UNREF(heap);
53458 	return (void *) thr->valstack;
53459 }
53460 
53461 DUK_INTERNAL void *duk_hthread_get_callstack_ptr(duk_heap *heap, void *ud) {
53462 	duk_hthread *thr = (duk_hthread *) ud;
53463 	DUK_UNREF(heap);
53464 	return (void *) thr->callstack;
53465 }
53466 
53467 DUK_INTERNAL void *duk_hthread_get_catchstack_ptr(duk_heap *heap, void *ud) {
53468 	duk_hthread *thr = (duk_hthread *) ud;
53469 	DUK_UNREF(heap);
53470 	return (void *) thr->catchstack;
53471 }
53472 /*
53473  *  Initialize built-in objects.  Current thread must have a valstack
53474  *  and initialization errors may longjmp, so a setjmp() catch point
53475  *  must exist.
53476  */
53477 
53478 /* include removed: duk_internal.h */
53479 
53480 /*
53481  *  Encoding constants, must match genbuiltins.py
53482  */
53483 
53484 #define DUK__CLASS_BITS                  5
53485 #define DUK__BIDX_BITS                   7
53486 #define DUK__STRIDX_BITS                 9  /* XXX: try to optimize to 8 (would now be possible, <200 used) */
53487 #define DUK__NATIDX_BITS                 8
53488 #define DUK__NUM_NORMAL_PROPS_BITS       6
53489 #define DUK__NUM_FUNC_PROPS_BITS         6
53490 #define DUK__PROP_FLAGS_BITS             3
53491 #define DUK__STRING_LENGTH_BITS          8
53492 #define DUK__STRING_CHAR_BITS            7
53493 #define DUK__LENGTH_PROP_BITS            3
53494 #define DUK__NARGS_BITS                  3
53495 #define DUK__PROP_TYPE_BITS              3
53496 #define DUK__MAGIC_BITS                  16
53497 
53498 #define DUK__NARGS_VARARGS_MARKER        0x07
53499 #define DUK__NO_CLASS_MARKER             0x00   /* 0 = DUK_HOBJECT_CLASS_UNUSED */
53500 #define DUK__NO_BIDX_MARKER              0x7f
53501 #define DUK__NO_STRIDX_MARKER            0xff
53502 
53503 #define DUK__PROP_TYPE_DOUBLE            0
53504 #define DUK__PROP_TYPE_STRING            1
53505 #define DUK__PROP_TYPE_STRIDX            2
53506 #define DUK__PROP_TYPE_BUILTIN           3
53507 #define DUK__PROP_TYPE_UNDEFINED         4
53508 #define DUK__PROP_TYPE_BOOLEAN_TRUE      5
53509 #define DUK__PROP_TYPE_BOOLEAN_FALSE     6
53510 #define DUK__PROP_TYPE_ACCESSOR          7
53511 
53512 /*
53513  *  Create built-in objects by parsing an init bitstream generated
53514  *  by genbuiltins.py.
53515  */
53516 
53517 #if defined(DUK_USE_ROM_OBJECTS)
53518 #if defined(DUK_USE_ROM_GLOBAL_CLONE) || defined(DUK_USE_ROM_GLOBAL_INHERIT)
53519 DUK_LOCAL void duk__duplicate_ram_global_object(duk_hthread *thr) {
53520 	duk_context *ctx;
53521 	duk_hobject *h1;
53522 #if defined(DUK_USE_ROM_GLOBAL_CLONE)
53523 	duk_hobject *h2;
53524 	duk_uint8_t *props;
53525 	duk_size_t alloc_size;
53526 #endif
53527 
53528 	ctx = (duk_context *) thr;
53529 
53530 	/* XXX: refactor into internal helper, duk_clone_hobject() */
53531 
53532 #if defined(DUK_USE_ROM_GLOBAL_INHERIT)
53533 	/* Inherit from ROM-based global object: less RAM usage, less transparent. */
53534 	duk_push_object_helper(ctx,
53535 	                       DUK_HOBJECT_FLAG_EXTENSIBLE |
53536 	                       DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_GLOBAL),
53537 	                       DUK_BIDX_GLOBAL);
53538 	h1 = duk_get_hobject(ctx, -1);
53539 	DUK_ASSERT(h1 != NULL);
53540 #elif defined(DUK_USE_ROM_GLOBAL_CLONE)
53541 	/* Clone the properties of the ROM-based global object to create a
53542 	 * fully RAM-based global object.  Uses more memory than the inherit
53543 	 * model but more compliant.
53544 	 */
53545 	duk_push_object_helper(ctx,
53546 	                       DUK_HOBJECT_FLAG_EXTENSIBLE |
53547 	                       DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_GLOBAL),
53548 	                       DUK_BIDX_OBJECT_PROTOTYPE);
53549 	h1 = duk_get_hobject(ctx, -1);
53550 	DUK_ASSERT(h1 != NULL);
53551 	h2 = thr->builtins[DUK_BIDX_GLOBAL];
53552 	DUK_ASSERT(h2 != NULL);
53553 
53554 	/* Copy the property table verbatim; this handles attributes etc.
53555 	 * For ROM objects it's not necessary (or possible) to update
53556 	 * refcounts so leave them as is.
53557 	 */
53558 	alloc_size = DUK_HOBJECT_P_ALLOC_SIZE(h2);
53559 	DUK_ASSERT(alloc_size > 0);
53560 	props = DUK_ALLOC(thr->heap, alloc_size);
53561 	if (!props) {
53562 		DUK_ERROR_ALLOC_DEFMSG(thr);
53563 		return;
53564 	}
53565 	DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, h2) != NULL);
53566 	DUK_MEMCPY((void *) props, (const void *) DUK_HOBJECT_GET_PROPS(thr->heap, h2), alloc_size);
53567 
53568 	/* XXX: keep property attributes or tweak them here?
53569 	 * Properties will now be non-configurable even when they're
53570 	 * normally configurable for the global object.
53571 	 */
53572 
53573 	DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, h1) == NULL);
53574 	DUK_HOBJECT_SET_PROPS(thr->heap, h1, props);
53575 	DUK_HOBJECT_SET_ESIZE(h1, DUK_HOBJECT_GET_ESIZE(h2));
53576 	DUK_HOBJECT_SET_ENEXT(h1, DUK_HOBJECT_GET_ENEXT(h2));
53577 	DUK_HOBJECT_SET_ASIZE(h1, DUK_HOBJECT_GET_ASIZE(h2));
53578 	DUK_HOBJECT_SET_HSIZE(h1, DUK_HOBJECT_GET_HSIZE(h2));
53579 #else
53580 #error internal error in defines
53581 #endif
53582 
53583 	duk_hobject_compact_props(thr, h1);
53584 	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
53585 	DUK_ASSERT(!DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE((duk_heaphdr *) thr->builtins[DUK_BIDX_GLOBAL]));  /* no need to decref */
53586 	thr->builtins[DUK_BIDX_GLOBAL] = h1;
53587 	DUK_HOBJECT_INCREF(thr, h1);
53588 	DUK_D(DUK_DPRINT("duplicated global object: %!O", h1));
53589 
53590 
53591 	/* Create a fresh object environment for the global scope.  This is
53592 	 * needed so that the global scope points to the newly created RAM-based
53593 	 * global object.
53594 	 */
53595 	duk_push_object_helper(ctx,
53596 	                       DUK_HOBJECT_FLAG_EXTENSIBLE |
53597 	                       DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJENV),
53598 	                       -1);  /* no prototype */
53599 	h1 = duk_get_hobject(ctx, -1);
53600 	DUK_ASSERT(h1 != NULL);
53601 	duk_dup(ctx, -2); /* -> [ ... new_global new_globalenv new_global ] */
53602 	duk_xdef_prop_stridx(thr, -2, DUK_STRIDX_INT_TARGET, DUK_PROPDESC_FLAGS_NONE);
53603 	/* provideThis=false */
53604 
53605 	duk_hobject_compact_props(thr, h1);
53606 	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL_ENV] != NULL);
53607 	DUK_ASSERT(!DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE((duk_heaphdr *) thr->builtins[DUK_BIDX_GLOBAL_ENV]));  /* no need to decref */
53608 	thr->builtins[DUK_BIDX_GLOBAL_ENV] = h1;
53609 	DUK_HOBJECT_INCREF(thr, h1);
53610 	DUK_D(DUK_DPRINT("duplicated global env: %!O", h1));
53611 
53612 	duk_pop_2(ctx);
53613 }
53614 #endif  /* DUK_USE_ROM_GLOBAL_CLONE || DUK_USE_ROM_GLOBAL_INHERIT */
53615 
53616 DUK_INTERNAL void duk_hthread_create_builtin_objects(duk_hthread *thr) {
53617 	/* Setup builtins from ROM objects.  All heaps/threads will share
53618 	 * the same readonly objects.
53619 	 */
53620 	duk_small_uint_t i;
53621 
53622 	for (i = 0; i < DUK_NUM_BUILTINS; i++) {
53623 		duk_hobject *h;
53624 		h = (duk_hobject *) DUK_LOSE_CONST(duk_rom_builtins_bidx[i]);
53625 		DUK_ASSERT(h != NULL);
53626 		thr->builtins[i] = h;
53627 	}
53628 
53629 #if defined(DUK_USE_ROM_GLOBAL_CLONE) || defined(DUK_USE_ROM_GLOBAL_INHERIT)
53630 	/* By default the global object is read-only which is often much
53631 	 * more of an issue than having read-only built-in objects (like
53632 	 * RegExp, Date, etc).  Use a RAM-based copy of the global object
53633 	 * and the global environment object for convenience.
53634 	 */
53635 	duk__duplicate_ram_global_object(thr);
53636 #endif
53637 }
53638 #else  /* DUK_USE_ROM_OBJECTS */
53639 DUK_LOCAL void duk__push_stridx(duk_context *ctx, duk_bitdecoder_ctx *bd) {
53640 	duk_small_uint_t n;
53641 
53642 	n = (duk_small_uint_t) duk_bd_decode(bd, DUK__STRIDX_BITS);
53643 	DUK_ASSERT_DISABLE(n >= 0);  /* unsigned */
53644 	DUK_ASSERT(n < DUK_HEAP_NUM_STRINGS);
53645 	duk_push_hstring_stridx(ctx, n);
53646 }
53647 DUK_LOCAL void duk__push_string(duk_context *ctx, duk_bitdecoder_ctx *bd) {
53648 	duk_small_uint_t n;
53649 	duk_small_uint_t i;
53650 	duk_uint8_t *p;
53651 
53652 	n = (duk_small_uint_t) duk_bd_decode(bd, DUK__STRING_LENGTH_BITS);
53653 	p = (duk_uint8_t *) duk_push_fixed_buffer(ctx, n);
53654 	for (i = 0; i < n; i++) {
53655 		*p++ = (duk_uint8_t) duk_bd_decode(bd, DUK__STRING_CHAR_BITS);
53656 	}
53657 	duk_to_string(ctx, -1);
53658 }
53659 DUK_LOCAL void duk__push_stridx_or_string(duk_context *ctx, duk_bitdecoder_ctx *bd) {
53660 	if (duk_bd_decode_flag(bd)) {
53661 		duk__push_string(ctx, bd);
53662 	} else {
53663 		duk__push_stridx(ctx, bd);
53664 	}
53665 }
53666 DUK_LOCAL void duk__push_double(duk_context *ctx, duk_bitdecoder_ctx *bd) {
53667 	duk_double_union du;
53668 	duk_small_uint_t i;
53669 
53670 	for (i = 0; i < 8; i++) {
53671 		/* Encoding endianness must match target memory layout,
53672 		 * build scripts and genbuiltins.py must ensure this.
53673 		 */
53674 		du.uc[i] = (duk_uint8_t) duk_bd_decode(bd, 8);
53675 	}
53676 
53677 	duk_push_number(ctx, du.d);  /* push operation normalizes NaNs */
53678 }
53679 
53680 DUK_INTERNAL void duk_hthread_create_builtin_objects(duk_hthread *thr) {
53681 	duk_context *ctx = (duk_context *) thr;
53682 	duk_bitdecoder_ctx bd_ctx;
53683 	duk_bitdecoder_ctx *bd = &bd_ctx;  /* convenience */
53684 	duk_hobject *h;
53685 	duk_small_uint_t i, j;
53686 
53687 	DUK_D(DUK_DPRINT("INITBUILTINS BEGIN: DUK_NUM_BUILTINS=%d, DUK_NUM_BUILTINS_ALL=%d", (int) DUK_NUM_BUILTINS, (int) DUK_NUM_ALL_BUILTINS));
53688 
53689 	DUK_MEMZERO(&bd_ctx, sizeof(bd_ctx));
53690 	bd->data = (const duk_uint8_t *) duk_builtins_data;
53691 	bd->length = (duk_size_t) DUK_BUILTINS_DATA_LENGTH;
53692 
53693 	/*
53694 	 *  First create all built-in bare objects on the empty valstack.
53695 	 *
53696 	 *  Built-ins in the index range [0,DUK_NUM_BUILTINS-1] have value
53697 	 *  stack indices matching their eventual thr->builtins[] index.
53698 	 *
53699 	 *  Built-ins in the index range [DUK_NUM_BUILTINS,DUK_NUM_ALL_BUILTINS]
53700 	 *  will exist on the value stack during init but won't be placed
53701 	 *  into thr->builtins[].  These are objects referenced in some way
53702 	 *  from thr->builtins[] roots but which don't need to be indexed by
53703 	 *  Duktape through thr->builtins[] (e.g. user custom objects).
53704 	 */
53705 
53706 	duk_require_stack(ctx, DUK_NUM_ALL_BUILTINS);
53707 
53708 	DUK_DD(DUK_DDPRINT("create empty built-ins"));
53709 	DUK_ASSERT_TOP(ctx, 0);
53710 	for (i = 0; i < DUK_NUM_ALL_BUILTINS; i++) {
53711 		duk_small_uint_t class_num;
53712 		duk_small_int_t len = -1;  /* must be signed */
53713 
53714 		class_num = (duk_small_uint_t) duk_bd_decode(bd, DUK__CLASS_BITS);
53715 		len = (duk_small_int_t) duk_bd_decode_flagged(bd, DUK__LENGTH_PROP_BITS, (duk_int32_t) -1 /*def_value*/);
53716 
53717 		if (class_num == DUK_HOBJECT_CLASS_FUNCTION) {
53718 			duk_small_uint_t natidx;
53719 			duk_int_t c_nargs;  /* must hold DUK_VARARGS */
53720 			duk_c_function c_func;
53721 			duk_int16_t magic;
53722 
53723 			DUK_DDD(DUK_DDDPRINT("len=%ld", (long) len));
53724 			DUK_ASSERT(len >= 0);
53725 
53726 			natidx = (duk_small_uint_t) duk_bd_decode(bd, DUK__NATIDX_BITS);
53727 			c_func = duk_bi_native_functions[natidx];
53728 
53729 			c_nargs = (duk_small_uint_t) duk_bd_decode_flagged(bd, DUK__NARGS_BITS, len /*def_value*/);
53730 			if (c_nargs == DUK__NARGS_VARARGS_MARKER) {
53731 				c_nargs = DUK_VARARGS;
53732 			}
53733 
53734 			/* XXX: set magic directly here? (it could share the c_nargs arg) */
53735 			duk_push_c_function_noexotic(ctx, c_func, c_nargs);
53736 
53737 			h = duk_require_hobject(ctx, -1);
53738 			DUK_ASSERT(h != NULL);
53739 
53740 			/* Currently all built-in native functions are strict.
53741 			 * duk_push_c_function() now sets strict flag, so
53742 			 * assert for it.
53743 			 */
53744 			DUK_ASSERT(DUK_HOBJECT_HAS_STRICT(h));
53745 
53746 			/* XXX: function properties */
53747 
53748 			/* Built-in 'name' is not writable by default.  Function '.name'
53749 			 * is writable to allow user code to set a '.name' on a native
53750 			 * function.
53751 			 */
53752 			duk__push_stridx_or_string(ctx, bd);
53753 			duk_xdef_prop_stridx(ctx,
53754 			                     -2,
53755 			                     DUK_STRIDX_NAME,
53756 			                     (i == DUK_BIDX_FUNCTION_PROTOTYPE) ?
53757 			                         DUK_PROPDESC_FLAGS_W : DUK_PROPDESC_FLAGS_NONE);
53758 
53759 			/* Almost all global level Function objects are constructable
53760 			 * but not all: Function.prototype is a non-constructable,
53761 			 * callable Function.
53762 			 */
53763 			if (duk_bd_decode_flag(bd)) {
53764 				DUK_ASSERT(DUK_HOBJECT_HAS_CONSTRUCTABLE(h));
53765 			} else {
53766 				DUK_HOBJECT_CLEAR_CONSTRUCTABLE(h);
53767 			}
53768 
53769 			/* Cast converts magic to 16-bit signed value */
53770 			magic = (duk_int16_t) duk_bd_decode_flagged(bd, DUK__MAGIC_BITS, 0 /*def_value*/);
53771 			((duk_hnativefunction *) h)->magic = magic;
53772 		} else {
53773 			/* XXX: ARRAY_PART for Array prototype? */
53774 
53775 			duk_push_object_helper(ctx,
53776 			                       DUK_HOBJECT_FLAG_EXTENSIBLE,
53777 			                       -1);  /* no prototype or class yet */
53778 
53779 			h = duk_require_hobject(ctx, -1);
53780 			DUK_ASSERT(h != NULL);
53781 		}
53782 
53783 		DUK_HOBJECT_SET_CLASS_NUMBER(h, class_num);
53784 
53785 		if (i < DUK_NUM_BUILTINS) {
53786 			thr->builtins[i] = h;
53787 			DUK_HOBJECT_INCREF(thr, &h->hdr);
53788 		}
53789 
53790 		if (len >= 0) {
53791 			/*
53792 			 *  For top-level objects, 'length' property has the following
53793 			 *  default attributes: non-writable, non-enumerable, non-configurable
53794 			 *  (E5 Section 15).
53795 			 *
53796 			 *  However, 'length' property for Array.prototype has attributes
53797 			 *  expected of an Array instance which are different: writable,
53798 			 *  non-enumerable, non-configurable (E5 Section 15.4.5.2).
53799 			 *
53800 			 *  This is currently determined implicitly based on class; there are
53801 			 *  no attribute flags in the init data.
53802 			 */
53803 
53804 			duk_push_int(ctx, len);
53805 			duk_xdef_prop_stridx(ctx,
53806 			                     -2,
53807 			                     DUK_STRIDX_LENGTH,
53808 			                     (class_num == DUK_HOBJECT_CLASS_ARRAY ?  /* only Array.prototype matches */
53809 			                      DUK_PROPDESC_FLAGS_W : DUK_PROPDESC_FLAGS_NONE));
53810 		}
53811 
53812 		/* enable exotic behaviors last */
53813 
53814 		if (class_num == DUK_HOBJECT_CLASS_ARRAY) {
53815 			DUK_HOBJECT_SET_EXOTIC_ARRAY(h);
53816 		}
53817 		if (class_num == DUK_HOBJECT_CLASS_STRING) {
53818 			DUK_HOBJECT_SET_EXOTIC_STRINGOBJ(h);
53819 		}
53820 
53821 		/* some assertions */
53822 
53823 		DUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE(h));
53824 		/* DUK_HOBJECT_FLAG_CONSTRUCTABLE varies */
53825 		DUK_ASSERT(!DUK_HOBJECT_HAS_BOUND(h));
53826 		DUK_ASSERT(!DUK_HOBJECT_HAS_COMPILEDFUNCTION(h));
53827 		/* DUK_HOBJECT_FLAG_NATIVEFUNCTION varies */
53828 		DUK_ASSERT(!DUK_HOBJECT_HAS_THREAD(h));
53829 		DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(h));       /* currently, even for Array.prototype */
53830 		/* DUK_HOBJECT_FLAG_STRICT varies */
53831 		DUK_ASSERT(!DUK_HOBJECT_HAS_NATIVEFUNCTION(h) ||  /* all native functions have NEWENV */
53832 		           DUK_HOBJECT_HAS_NEWENV(h));
53833 		DUK_ASSERT(!DUK_HOBJECT_HAS_NAMEBINDING(h));
53834 		DUK_ASSERT(!DUK_HOBJECT_HAS_CREATEARGS(h));
53835 		DUK_ASSERT(!DUK_HOBJECT_HAS_ENVRECCLOSED(h));
53836 		/* DUK_HOBJECT_FLAG_EXOTIC_ARRAY varies */
53837 		/* DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ varies */
53838 		DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(h));
53839 
53840 		DUK_DDD(DUK_DDDPRINT("created built-in %ld, class=%ld, length=%ld", (long) i, (long) class_num, (long) len));
53841 	}
53842 
53843 	/*
53844 	 *  Then decode the builtins init data (see genbuiltins.py) to
53845 	 *  init objects
53846 	 */
53847 
53848 	DUK_DD(DUK_DDPRINT("initialize built-in object properties"));
53849 	for (i = 0; i < DUK_NUM_ALL_BUILTINS; i++) {
53850 		duk_small_uint_t t;
53851 		duk_small_uint_t num;
53852 
53853 		DUK_DDD(DUK_DDDPRINT("initializing built-in object at index %ld", (long) i));
53854 		h = duk_require_hobject(ctx, i);
53855 		DUK_ASSERT(h != NULL);
53856 
53857 		t = (duk_small_uint_t) duk_bd_decode(bd, DUK__BIDX_BITS);
53858 		if (t != DUK__NO_BIDX_MARKER) {
53859 			DUK_DDD(DUK_DDDPRINT("set internal prototype: built-in %ld", (long) t));
53860 			DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h, duk_require_hobject(ctx, t));
53861 		}
53862 
53863 		t = (duk_small_uint_t) duk_bd_decode(bd, DUK__BIDX_BITS);
53864 		if (t != DUK__NO_BIDX_MARKER) {
53865 			/* 'prototype' property for all built-in objects (which have it) has attributes:
53866 			 *  [[Writable]] = false,
53867 			 *  [[Enumerable]] = false,
53868 			 *  [[Configurable]] = false
53869 			 */
53870 			DUK_DDD(DUK_DDDPRINT("set external prototype: built-in %ld", (long) t));
53871 			duk_xdef_prop_stridx_builtin(ctx, i, DUK_STRIDX_PROTOTYPE, t, DUK_PROPDESC_FLAGS_NONE);
53872 		}
53873 
53874 		t = (duk_small_uint_t) duk_bd_decode(bd, DUK__BIDX_BITS);
53875 		if (t != DUK__NO_BIDX_MARKER) {
53876 			/* 'constructor' property for all built-in objects (which have it) has attributes:
53877 			 *  [[Writable]] = true,
53878 			 *  [[Enumerable]] = false,
53879 			 *  [[Configurable]] = true
53880 			 */
53881 			DUK_DDD(DUK_DDDPRINT("set external constructor: built-in %ld", (long) t));
53882 			duk_xdef_prop_stridx_builtin(ctx, i, DUK_STRIDX_CONSTRUCTOR, t, DUK_PROPDESC_FLAGS_WC);
53883 		}
53884 
53885 		/* normal valued properties */
53886 		num = (duk_small_uint_t) duk_bd_decode(bd, DUK__NUM_NORMAL_PROPS_BITS);
53887 		DUK_DDD(DUK_DDDPRINT("built-in object %ld, %ld normal valued properties", (long) i, (long) num));
53888 		for (j = 0; j < num; j++) {
53889 			duk_small_uint_t prop_flags;
53890 
53891 			duk__push_stridx_or_string(ctx, bd);
53892 
53893 			/*
53894 			 *  Property attribute defaults are defined in E5 Section 15 (first
53895 			 *  few pages); there is a default for all properties and a special
53896 			 *  default for 'length' properties.  Variation from the defaults is
53897 			 *  signaled using a single flag bit in the bitstream.
53898 			 */
53899 
53900 			if (duk_bd_decode_flag(bd)) {
53901 				prop_flags = (duk_small_uint_t) duk_bd_decode(bd, DUK__PROP_FLAGS_BITS);
53902 			} else {
53903 				prop_flags = DUK_PROPDESC_FLAGS_WC;
53904 			}
53905 
53906 			t = (duk_small_uint_t) duk_bd_decode(bd, DUK__PROP_TYPE_BITS);
53907 
53908 			DUK_DDD(DUK_DDDPRINT("built-in %ld, normal-valued property %ld, key %!T, flags 0x%02lx, type %ld",
53909 			                     (long) i, (long) j, duk_get_tval(ctx, -1), (unsigned long) prop_flags, (long) t));
53910 
53911 			switch (t) {
53912 			case DUK__PROP_TYPE_DOUBLE: {
53913 				duk__push_double(ctx, bd);
53914 				break;
53915 			}
53916 			case DUK__PROP_TYPE_STRING: {
53917 				duk__push_string(ctx, bd);
53918 				break;
53919 			}
53920 			case DUK__PROP_TYPE_STRIDX: {
53921 				duk__push_stridx(ctx, bd);
53922 				break;
53923 			}
53924 			case DUK__PROP_TYPE_BUILTIN: {
53925 				duk_small_uint_t bidx;
53926 
53927 				bidx = (duk_small_uint_t) duk_bd_decode(bd, DUK__BIDX_BITS);
53928 				DUK_ASSERT(bidx != DUK__NO_BIDX_MARKER);
53929 				duk_dup(ctx, (duk_idx_t) bidx);
53930 				break;
53931 			}
53932 			case DUK__PROP_TYPE_UNDEFINED: {
53933 				duk_push_undefined(ctx);
53934 				break;
53935 			}
53936 			case DUK__PROP_TYPE_BOOLEAN_TRUE: {
53937 				duk_push_true(ctx);
53938 				break;
53939 			}
53940 			case DUK__PROP_TYPE_BOOLEAN_FALSE: {
53941 				duk_push_false(ctx);
53942 				break;
53943 			}
53944 			case DUK__PROP_TYPE_ACCESSOR: {
53945 				duk_small_uint_t natidx_getter = (duk_small_uint_t) duk_bd_decode(bd, DUK__NATIDX_BITS);
53946 				duk_small_uint_t natidx_setter = (duk_small_uint_t) duk_bd_decode(bd, DUK__NATIDX_BITS);
53947 				duk_c_function c_func_getter;
53948 				duk_c_function c_func_setter;
53949 
53950 				/* XXX: this is a bit awkward because there is no exposed helper
53951 				 * in the API style, only this internal helper.
53952 				 */
53953 				DUK_DDD(DUK_DDDPRINT("built-in accessor property: objidx=%ld, key=%!T, getteridx=%ld, setteridx=%ld, flags=0x%04lx",
53954 				                     (long) i, duk_get_tval(ctx, -1), (long) natidx_getter, (long) natidx_setter, (unsigned long) prop_flags));
53955 
53956 				c_func_getter = duk_bi_native_functions[natidx_getter];
53957 				c_func_setter = duk_bi_native_functions[natidx_setter];
53958 				duk_push_c_function_noconstruct_noexotic(ctx, c_func_getter, 0);  /* always 0 args */
53959 				duk_push_c_function_noconstruct_noexotic(ctx, c_func_setter, 1);  /* always 1 arg */
53960 
53961 				/* XXX: magic for getter/setter? use duk_def_prop()? */
53962 
53963 				DUK_ASSERT((prop_flags & DUK_PROPDESC_FLAG_WRITABLE) == 0);  /* genbuiltins.py ensures */
53964 
53965 				prop_flags |= DUK_PROPDESC_FLAG_ACCESSOR;  /* accessor flag not encoded explicitly */
53966 				duk_hobject_define_accessor_internal(thr,
53967 				                                     duk_require_hobject(ctx, i),
53968 				                                     duk_get_hstring(ctx, -3),
53969 				                                     duk_require_hobject(ctx, -2),
53970 				                                     duk_require_hobject(ctx, -1),
53971 				                                     prop_flags);
53972 				duk_pop_3(ctx);  /* key, getter and setter, now reachable through object */
53973 				goto skip_value;
53974 			}
53975 			default: {
53976 				/* exhaustive */
53977 				DUK_UNREACHABLE();
53978 			}
53979 			}
53980 
53981 			DUK_ASSERT((prop_flags & DUK_PROPDESC_FLAG_ACCESSOR) == 0);
53982 			duk_xdef_prop(ctx, i, prop_flags);
53983 
53984 		 skip_value:
53985 			continue;  /* avoid empty label at the end of a compound statement */
53986 		}
53987 
53988 		/* native function properties */
53989 		num = (duk_small_uint_t) duk_bd_decode(bd, DUK__NUM_FUNC_PROPS_BITS);
53990 		DUK_DDD(DUK_DDDPRINT("built-in object %ld, %ld function valued properties", (long) i, (long) num));
53991 		for (j = 0; j < num; j++) {
53992 			duk_hstring *h_key;
53993 			duk_small_uint_t natidx;
53994 			duk_int_t c_nargs;  /* must hold DUK_VARARGS */
53995 			duk_small_uint_t c_length;
53996 			duk_int16_t magic;
53997 			duk_c_function c_func;
53998 			duk_hnativefunction *h_func;
53999 #if defined(DUK_USE_LIGHTFUNC_BUILTINS)
54000 			duk_small_int_t lightfunc_eligible;
54001 #endif
54002 
54003 			duk__push_stridx_or_string(ctx, bd);
54004 			h_key = duk_get_hstring(ctx, -1);
54005 			DUK_ASSERT(h_key != NULL);
54006 			DUK_UNREF(h_key);
54007 			natidx = (duk_small_uint_t) duk_bd_decode(bd, DUK__NATIDX_BITS);
54008 
54009 			c_length = (duk_small_uint_t) duk_bd_decode(bd, DUK__LENGTH_PROP_BITS);
54010 			c_nargs = (duk_int_t) duk_bd_decode_flagged(bd, DUK__NARGS_BITS, (duk_int32_t) c_length /*def_value*/);
54011 			if (c_nargs == DUK__NARGS_VARARGS_MARKER) {
54012 				c_nargs = DUK_VARARGS;
54013 			}
54014 
54015 			c_func = duk_bi_native_functions[natidx];
54016 
54017 			DUK_DDD(DUK_DDDPRINT("built-in %ld, function-valued property %ld, key %!O, natidx %ld, length %ld, nargs %ld",
54018 			                     (long) i, (long) j, (duk_heaphdr *) h_key, (long) natidx, (long) c_length,
54019 			                     (c_nargs == DUK_VARARGS ? (long) -1 : (long) c_nargs)));
54020 
54021 			/* Cast converts magic to 16-bit signed value */
54022 			magic = (duk_int16_t) duk_bd_decode_flagged(bd, DUK__MAGIC_BITS, 0);
54023 
54024 #if defined(DUK_USE_LIGHTFUNC_BUILTINS)
54025 			lightfunc_eligible =
54026 				((c_nargs >= DUK_LFUNC_NARGS_MIN && c_nargs <= DUK_LFUNC_NARGS_MAX) || (c_nargs == DUK_VARARGS)) &&
54027 				(c_length <= DUK_LFUNC_LENGTH_MAX) &&
54028 				(magic >= DUK_LFUNC_MAGIC_MIN && magic <= DUK_LFUNC_MAGIC_MAX);
54029 
54030 			if (h_key == DUK_HTHREAD_STRING_EVAL(thr) ||
54031 			    h_key == DUK_HTHREAD_STRING_YIELD(thr) ||
54032 			    h_key == DUK_HTHREAD_STRING_RESUME(thr) ||
54033 			    h_key == DUK_HTHREAD_STRING_REQUIRE(thr)) {
54034 				/* These functions have trouble working as lightfuncs.
54035 				 * Some of them have specific asserts and some may have
54036 			         * additional properties (e.g. 'require.id' may be written).
54037 				 */
54038 				DUK_D(DUK_DPRINT("reject as lightfunc: key=%!O, i=%d, j=%d", (duk_heaphdr *) h_key, (int) i, (int) j));
54039 				lightfunc_eligible = 0;
54040 			}
54041 
54042 			if (lightfunc_eligible) {
54043 				duk_tval tv_lfunc;
54044 				duk_small_uint_t lf_nargs = (c_nargs == DUK_VARARGS ? DUK_LFUNC_NARGS_VARARGS : c_nargs);
54045 				duk_small_uint_t lf_flags = DUK_LFUNC_FLAGS_PACK(magic, c_length, lf_nargs);
54046 				DUK_TVAL_SET_LIGHTFUNC(&tv_lfunc, c_func, lf_flags);
54047 				duk_push_tval(ctx, &tv_lfunc);
54048 				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(ctx, -1)));
54049 				goto lightfunc_skip;
54050 			}
54051 
54052 			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));
54053 #endif  /* DUK_USE_LIGHTFUNC_BUILTINS */
54054 
54055 			/* [ (builtin objects) name ] */
54056 
54057 			duk_push_c_function_noconstruct_noexotic(ctx, c_func, c_nargs);
54058 			h_func = duk_require_hnativefunction(ctx, -1);
54059 			DUK_UNREF(h_func);
54060 
54061 			/* Currently all built-in native functions are strict.
54062 			 * This doesn't matter for many functions, but e.g.
54063 			 * String.prototype.charAt (and other string functions)
54064 			 * rely on being strict so that their 'this' binding is
54065 			 * not automatically coerced.
54066 			 */
54067 			DUK_HOBJECT_SET_STRICT((duk_hobject *) h_func);
54068 
54069 			/* No built-in functions are constructable except the top
54070 			 * level ones (Number, etc).
54071 			 */
54072 			DUK_ASSERT(!DUK_HOBJECT_HAS_CONSTRUCTABLE((duk_hobject *) h_func));
54073 
54074 			/* XXX: any way to avoid decoding magic bit; there are quite
54075 			 * many function properties and relatively few with magic values.
54076 			 */
54077 			h_func->magic = magic;
54078 
54079 			/* [ (builtin objects) name func ] */
54080 
54081 			duk_push_int(ctx, c_length);
54082 			duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_NONE);
54083 
54084 			duk_dup(ctx, -2);
54085 			duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_NONE);
54086 
54087 			/* XXX: other properties of function instances; 'arguments', 'caller'. */
54088 
54089 			DUK_DD(DUK_DDPRINT("built-in object %ld, function property %ld -> %!T",
54090 			                   (long) i, (long) j, (duk_tval *) duk_get_tval(ctx, -1)));
54091 
54092 			/* [ (builtin objects) name func ] */
54093 
54094 			/*
54095 			 *  The default property attributes are correct for all
54096 			 *  function valued properties of built-in objects now.
54097 			 */
54098 
54099 #if defined(DUK_USE_LIGHTFUNC_BUILTINS)
54100 		 lightfunc_skip:
54101 #endif
54102 
54103 			duk_xdef_prop(ctx, i, DUK_PROPDESC_FLAGS_WC);
54104 
54105 			/* [ (builtin objects) ] */
54106 		}
54107 	}
54108 
54109 	/*
54110 	 *  Special post-tweaks, for cases not covered by the init data format.
54111 	 *
54112 	 *  - Set Date.prototype.toGMTString to Date.prototype.toUTCString.
54113 	 *    toGMTString is required to have the same Function object as
54114 	 *    toUTCString in E5 Section B.2.6.  Note that while Smjs respects
54115 	 *    this, V8 does not (the Function objects are distinct).
54116 	 *
54117 	 *  - Make DoubleError non-extensible.
54118 	 *
54119 	 *  - Add info about most important effective compile options to Duktape.
54120 	 *
54121 	 *  - Possibly remove some properties (values or methods) which are not
54122 	 *    desirable with current feature options but are not currently
54123 	 *    conditional in init data.
54124 	 */
54125 
54126 	duk_get_prop_stridx(ctx, DUK_BIDX_DATE_PROTOTYPE, DUK_STRIDX_TO_UTC_STRING);
54127 	duk_xdef_prop_stridx(ctx, DUK_BIDX_DATE_PROTOTYPE, DUK_STRIDX_TO_GMT_STRING, DUK_PROPDESC_FLAGS_WC);
54128 
54129 	h = duk_require_hobject(ctx, DUK_BIDX_DOUBLE_ERROR);
54130 	DUK_ASSERT(h != NULL);
54131 	DUK_HOBJECT_CLEAR_EXTENSIBLE(h);
54132 
54133 #if !defined(DUK_USE_ES6_OBJECT_PROTO_PROPERTY)
54134 	DUK_DD(DUK_DDPRINT("delete Object.prototype.__proto__ built-in which is not enabled in features"));
54135 	(void) duk_hobject_delprop_raw(thr, thr->builtins[DUK_BIDX_OBJECT_PROTOTYPE], DUK_HTHREAD_STRING___PROTO__(thr), DUK_DELPROP_FLAG_THROW);
54136 #endif
54137 
54138 #if !defined(DUK_USE_ES6_OBJECT_SETPROTOTYPEOF)
54139 	DUK_DD(DUK_DDPRINT("delete Object.setPrototypeOf built-in which is not enabled in features"));
54140 	(void) duk_hobject_delprop_raw(thr, thr->builtins[DUK_BIDX_OBJECT_CONSTRUCTOR], DUK_HTHREAD_STRING_SET_PROTOTYPE_OF(thr), DUK_DELPROP_FLAG_THROW);
54141 #endif
54142 
54143 	/* XXX: relocate */
54144 	duk_push_string(ctx,
54145 			/* Endianness indicator */
54146 #if defined(DUK_USE_INTEGER_LE)
54147 	                "l"
54148 #elif defined(DUK_USE_INTEGER_BE)
54149 	                "b"
54150 #elif defined(DUK_USE_INTEGER_ME)  /* integer mixed endian not really used now */
54151 	                "m"
54152 #else
54153 	                "?"
54154 #endif
54155 #if defined(DUK_USE_DOUBLE_LE)
54156 	                "l"
54157 #elif defined(DUK_USE_DOUBLE_BE)
54158 	                "b"
54159 #elif defined(DUK_USE_DOUBLE_ME)
54160 	                "m"
54161 #else
54162 	                "?"
54163 #endif
54164 	                " "
54165 			/* Packed or unpacked tval */
54166 #if defined(DUK_USE_PACKED_TVAL)
54167 	                "p"
54168 #else
54169 	                "u"
54170 #endif
54171 #if defined(DUK_USE_FASTINT)
54172 			"f"
54173 #endif
54174 			" "
54175 			/* Low memory options */
54176 #if defined(DUK_USE_STRTAB_CHAIN)
54177 			"c"  /* chain */
54178 #elif defined(DUK_USE_STRTAB_PROBE)
54179 			"p"  /* probe */
54180 #else
54181 			"?"
54182 #endif
54183 #if !defined(DUK_USE_HEAPPTR16) && !defined(DUK_DATAPTR16) && !defined(DUK_FUNCPTR16)
54184 			"n"
54185 #endif
54186 #if defined(DUK_USE_HEAPPTR16)
54187 			"h"
54188 #endif
54189 #if defined(DUK_USE_DATAPTR16)
54190 			"d"
54191 #endif
54192 #if defined(DUK_USE_FUNCPTR16)
54193 			"f"
54194 #endif
54195 #if defined(DUK_USE_REFCOUNT16)
54196 			"R"
54197 #endif
54198 #if defined(DUK_USE_STRHASH16)
54199 			"H"
54200 #endif
54201 #if defined(DUK_USE_STRLEN16)
54202 			"S"
54203 #endif
54204 #if defined(DUK_USE_BUFLEN16)
54205 			"B"
54206 #endif
54207 #if defined(DUK_USE_OBJSIZES16)
54208 			"O"
54209 #endif
54210 #if defined(DUK_USE_LIGHTFUNC_BUILTINS)
54211 			"L"
54212 #endif
54213 #if defined(DUK_USE_ROM_STRINGS) || defined(DUK_USE_ROM_OBJECTS)
54214 			/* XXX: This won't be shown in practice now
54215 			 * because this code is not run when builtins
54216 			 * are in ROM.
54217 			 */
54218 			"Z"
54219 #endif
54220 	                " "
54221 			/* Object property allocation layout */
54222 #if defined(DUK_USE_HOBJECT_LAYOUT_1)
54223 			"p1"
54224 #elif defined(DUK_USE_HOBJECT_LAYOUT_2)
54225 			"p2"
54226 #elif defined(DUK_USE_HOBJECT_LAYOUT_3)
54227 			"p3"
54228 #else
54229 			"p?"
54230 #endif
54231 			" "
54232 			/* Alignment guarantee */
54233 #if (DUK_USE_ALIGN_BY == 4)
54234 			"a4"
54235 #elif (DUK_USE_ALIGN_BY == 8)
54236 			"a8"
54237 #elif (DUK_USE_ALIGN_BY == 1)
54238 			"a1"
54239 #else
54240 #error invalid DUK_USE_ALIGN_BY
54241 #endif
54242 			" "
54243 			/* Architecture, OS, and compiler strings */
54244 	                DUK_USE_ARCH_STRING
54245 			" "
54246 	                DUK_USE_OS_STRING
54247 			" "
54248 	                DUK_USE_COMPILER_STRING);
54249 	duk_xdef_prop_stridx(ctx, DUK_BIDX_DUKTAPE, DUK_STRIDX_ENV, DUK_PROPDESC_FLAGS_WC);
54250 
54251 	/*
54252 	 *  InitJS code - Ecmascript code evaluated from a built-in source
54253 	 *  which provides e.g. backward compatibility.  User can also provide
54254 	 *  JS code to be evaluated at startup.
54255 	 */
54256 
54257 #ifdef DUK_USE_BUILTIN_INITJS
54258 	/* XXX: compression */
54259 	DUK_DD(DUK_DDPRINT("running built-in initjs"));
54260 	duk_eval_string(ctx, (const char *) duk_initjs_data);  /* initjs data is NUL terminated */
54261 	duk_pop(ctx);
54262 #endif  /* DUK_USE_BUILTIN_INITJS */
54263 
54264 #ifdef DUK_USE_USER_INITJS
54265 	/* XXX: compression (as an option) */
54266 	DUK_DD(DUK_DDPRINT("running user initjs"));
54267 	duk_eval_string_noresult(ctx, (const char *) DUK_USE_USER_INITJS);
54268 #endif  /* DUK_USE_USER_INITJS */
54269 
54270 	/*
54271 	 *  Since built-ins are not often extended, compact them.
54272 	 */
54273 
54274 	DUK_DD(DUK_DDPRINT("compact built-ins"));
54275 	for (i = 0; i < DUK_NUM_ALL_BUILTINS; i++) {
54276 		duk_hobject_compact_props(thr, duk_require_hobject(ctx, i));
54277 	}
54278 
54279 	DUK_D(DUK_DPRINT("INITBUILTINS END"));
54280 
54281 #ifdef DUK_USE_DDPRINT
54282 	for (i = 0; i < DUK_NUM_ALL_BUILTINS; i++) {
54283 		DUK_DD(DUK_DDPRINT("built-in object %ld after initialization and compacting: %!@iO",
54284 		                   (long) i, (duk_heaphdr *) duk_require_hobject(ctx, i)));
54285 	}
54286 #endif
54287 
54288 	/*
54289 	 *  Pop built-ins from stack: they are now INCREF'd and
54290 	 *  reachable from the builtins[] array or indirectly
54291 	 *  through builtins[].
54292 	 */
54293 
54294 	duk_set_top(ctx, 0);
54295 	DUK_ASSERT_TOP(ctx, 0);
54296 }
54297 #endif  /* DUK_USE_ROM_OBJECTS */
54298 
54299 DUK_INTERNAL void duk_hthread_copy_builtin_objects(duk_hthread *thr_from, duk_hthread *thr_to) {
54300 	duk_small_uint_t i;
54301 
54302 	for (i = 0; i < DUK_NUM_BUILTINS; i++) {
54303 		thr_to->builtins[i] = thr_from->builtins[i];
54304 		DUK_HOBJECT_INCREF_ALLOWNULL(thr_to, thr_to->builtins[i]);  /* side effect free */
54305 	}
54306 }
54307 /*
54308  *  Thread support.
54309  */
54310 
54311 /* include removed: duk_internal.h */
54312 
54313 DUK_INTERNAL void duk_hthread_terminate(duk_hthread *thr) {
54314 	DUK_ASSERT(thr != NULL);
54315 
54316 	/* Order of unwinding is important */
54317 
54318 	duk_hthread_catchstack_unwind(thr, 0);
54319 
54320 	duk_hthread_callstack_unwind(thr, 0);  /* side effects, possibly errors */
54321 
54322 	thr->valstack_bottom = thr->valstack;
54323 	duk_set_top((duk_context *) thr, 0);  /* unwinds valstack, updating refcounts */
54324 
54325 	thr->state = DUK_HTHREAD_STATE_TERMINATED;
54326 
54327 	/* Here we could remove references to built-ins, but it may not be
54328 	 * worth the effort because built-ins are quite likely to be shared
54329 	 * with another (unterminated) thread, and terminated threads are also
54330 	 * usually garbage collected quite quickly.  Also, doing DECREFs
54331 	 * could trigger finalization, which would run on the current thread
54332 	 * and have access to only some of the built-ins.  Garbage collection
54333 	 * deals with this correctly already.
54334 	 */
54335 
54336 	/* XXX: Shrink the stacks to minimize memory usage?  May not
54337 	 * be worth the effort because terminated threads are usually
54338 	 * garbage collected quite soon.
54339 	 */
54340 }
54341 
54342 DUK_INTERNAL duk_activation *duk_hthread_get_current_activation(duk_hthread *thr) {
54343 	DUK_ASSERT(thr != NULL);
54344 
54345 	if (thr->callstack_top > 0) {
54346 		return thr->callstack + thr->callstack_top - 1;
54347 	} else {
54348 		return NULL;
54349 	}
54350 }
54351 
54352 #if defined(DUK_USE_DEBUGGER_SUPPORT)
54353 DUK_INTERNAL duk_uint_fast32_t duk_hthread_get_act_curr_pc(duk_hthread *thr, duk_activation *act) {
54354 	duk_instr_t *bcode;
54355 
54356 	DUK_ASSERT(thr != NULL);
54357 	DUK_ASSERT(act != NULL);
54358 	DUK_UNREF(thr);
54359 
54360 	/* XXX: store 'bcode' pointer to activation for faster lookup? */
54361 	if (act->func && DUK_HOBJECT_IS_COMPILEDFUNCTION(act->func)) {
54362 		bcode = DUK_HCOMPILEDFUNCTION_GET_CODE_BASE(thr->heap, (duk_hcompiledfunction *) (act->func));
54363 		return (duk_uint_fast32_t) (act->curr_pc - bcode);
54364 	}
54365 	return 0;
54366 }
54367 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
54368 
54369 DUK_INTERNAL duk_uint_fast32_t duk_hthread_get_act_prev_pc(duk_hthread *thr, duk_activation *act) {
54370 	duk_instr_t *bcode;
54371 	duk_uint_fast32_t ret;
54372 
54373 	DUK_ASSERT(thr != NULL);
54374 	DUK_ASSERT(act != NULL);
54375 	DUK_UNREF(thr);
54376 
54377 	if (act->func && DUK_HOBJECT_IS_COMPILEDFUNCTION(act->func)) {
54378 		bcode = DUK_HCOMPILEDFUNCTION_GET_CODE_BASE(thr->heap, (duk_hcompiledfunction *) (act->func));
54379 		ret = (duk_uint_fast32_t) (act->curr_pc - bcode);
54380 		if (ret > 0) {
54381 			ret--;
54382 		}
54383 		return ret;
54384 	}
54385 	return 0;
54386 }
54387 
54388 /* Write bytecode executor's curr_pc back to topmost activation (if any). */
54389 DUK_INTERNAL void duk_hthread_sync_currpc(duk_hthread *thr) {
54390 	duk_activation *act;
54391 
54392 	DUK_ASSERT(thr != NULL);
54393 
54394 	if (thr->ptr_curr_pc != NULL) {
54395 		/* ptr_curr_pc != NULL only when bytecode executor is active. */
54396 		DUK_ASSERT(thr->callstack_top > 0);
54397 		act = thr->callstack + thr->callstack_top - 1;
54398 		act->curr_pc = *thr->ptr_curr_pc;
54399 	}
54400 }
54401 
54402 DUK_INTERNAL void duk_hthread_sync_and_null_currpc(duk_hthread *thr) {
54403 	duk_activation *act;
54404 
54405 	DUK_ASSERT(thr != NULL);
54406 
54407 	if (thr->ptr_curr_pc != NULL) {
54408 		/* ptr_curr_pc != NULL only when bytecode executor is active. */
54409 		DUK_ASSERT(thr->callstack_top > 0);
54410 		act = thr->callstack + thr->callstack_top - 1;
54411 		act->curr_pc = *thr->ptr_curr_pc;
54412 		thr->ptr_curr_pc = NULL;
54413 	}
54414 }
54415 /*
54416  *  Manipulation of thread stacks (valstack, callstack, catchstack).
54417  *
54418  *  Ideally unwinding of stacks should have no side effects, which would
54419  *  then favor separate unwinding and shrink check primitives for each
54420  *  stack type.  A shrink check may realloc and thus have side effects.
54421  *
54422  *  However, currently callstack unwinding itself has side effects, as it
54423  *  needs to DECREF multiple objects, close environment records, etc.
54424  *  Stacks must thus be unwound in the correct order by the caller.
54425  *
54426  *  (XXX: This should be probably reworked so that there is a shared
54427  *  unwind primitive which handles all stacks as requested, and knows
54428  *  the proper order for unwinding.)
54429  *
54430  *  Valstack entries above 'top' are always kept initialized to
54431  *  "undefined unused".  Callstack and catchstack entries above 'top'
54432  *  are not zeroed and are left as garbage.
54433  *
54434  *  Value stack handling is mostly a part of the API implementation.
54435  */
54436 
54437 /* include removed: duk_internal.h */
54438 
54439 /* check that there is space for at least one new entry */
54440 DUK_INTERNAL void duk_hthread_callstack_grow(duk_hthread *thr) {
54441 	duk_activation *new_ptr;
54442 	duk_size_t old_size;
54443 	duk_size_t new_size;
54444 
54445 	DUK_ASSERT(thr != NULL);
54446 	DUK_ASSERT_DISABLE(thr->callstack_top >= 0);   /* avoid warning (unsigned) */
54447 	DUK_ASSERT(thr->callstack_size >= thr->callstack_top);
54448 
54449 	if (thr->callstack_top < thr->callstack_size) {
54450 		return;
54451 	}
54452 
54453 	old_size = thr->callstack_size;
54454 	new_size = old_size + DUK_CALLSTACK_GROW_STEP;
54455 
54456 	/* this is a bit approximate (errors out before max is reached); this is OK */
54457 	if (new_size >= thr->callstack_max) {
54458 		DUK_ERROR_RANGE(thr, DUK_STR_CALLSTACK_LIMIT);
54459 	}
54460 
54461 	DUK_DD(DUK_DDPRINT("growing callstack %ld -> %ld", (long) old_size, (long) new_size));
54462 
54463 	/*
54464 	 *  Note: must use indirect variant of DUK_REALLOC() because underlying
54465 	 *  pointer may be changed by mark-and-sweep.
54466 	 */
54467 
54468 	DUK_ASSERT(new_size > 0);
54469 	new_ptr = (duk_activation *) DUK_REALLOC_INDIRECT(thr->heap, duk_hthread_get_callstack_ptr, (void *) thr, sizeof(duk_activation) * new_size);
54470 	if (!new_ptr) {
54471 		/* No need for a NULL/zero-size check because new_size > 0) */
54472 		DUK_ERROR_ALLOC_DEFMSG(thr);
54473 	}
54474 	thr->callstack = new_ptr;
54475 	thr->callstack_size = new_size;
54476 
54477 	/* note: any entries above the callstack top are garbage and not zeroed */
54478 }
54479 
54480 DUK_INTERNAL void duk_hthread_callstack_shrink_check(duk_hthread *thr) {
54481 	duk_size_t new_size;
54482 	duk_activation *p;
54483 
54484 	DUK_ASSERT(thr != NULL);
54485 	DUK_ASSERT_DISABLE(thr->callstack_top >= 0);  /* avoid warning (unsigned) */
54486 	DUK_ASSERT(thr->callstack_size >= thr->callstack_top);
54487 
54488 	if (thr->callstack_size - thr->callstack_top < DUK_CALLSTACK_SHRINK_THRESHOLD) {
54489 		return;
54490 	}
54491 
54492 	new_size = thr->callstack_top + DUK_CALLSTACK_SHRINK_SPARE;
54493 	DUK_ASSERT(new_size >= thr->callstack_top);
54494 
54495 	DUK_DD(DUK_DDPRINT("shrinking callstack %ld -> %ld", (long) thr->callstack_size, (long) new_size));
54496 
54497 	/*
54498 	 *  Note: must use indirect variant of DUK_REALLOC() because underlying
54499 	 *  pointer may be changed by mark-and-sweep.
54500 	 */
54501 
54502 	/* shrink failure is not fatal */
54503 	p = (duk_activation *) DUK_REALLOC_INDIRECT(thr->heap, duk_hthread_get_callstack_ptr, (void *) thr, sizeof(duk_activation) * new_size);
54504 	if (p) {
54505 		thr->callstack = p;
54506 		thr->callstack_size = new_size;
54507 	} else {
54508 		/* Because new_size != 0, if condition doesn't need to be
54509 		 * (p != NULL || new_size == 0).
54510 		 */
54511 		DUK_ASSERT(new_size != 0);
54512 		DUK_D(DUK_DPRINT("callstack shrink failed, ignoring"));
54513 	}
54514 
54515 	/* note: any entries above the callstack top are garbage and not zeroed */
54516 }
54517 
54518 DUK_INTERNAL void duk_hthread_callstack_unwind(duk_hthread *thr, duk_size_t new_top) {
54519 	duk_size_t idx;
54520 
54521 	DUK_DDD(DUK_DDDPRINT("unwind callstack top of thread %p from %ld to %ld",
54522 	                     (void *) thr,
54523 	                     (thr != NULL ? (long) thr->callstack_top : (long) -1),
54524 	                     (long) new_top));
54525 
54526 	DUK_ASSERT(thr);
54527 	DUK_ASSERT(thr->heap);
54528 	DUK_ASSERT_DISABLE(new_top >= 0);  /* unsigned */
54529 	DUK_ASSERT((duk_size_t) new_top <= thr->callstack_top);  /* cannot grow */
54530 
54531 	/*
54532 	 *  The loop below must avoid issues with potential callstack
54533 	 *  reallocations.  A resize (and other side effects) may happen
54534 	 *  e.g. due to finalizer/errhandler calls caused by a refzero or
54535 	 *  mark-and-sweep.  Arbitrary finalizers may run, because when
54536 	 *  an environment record is refzero'd, it may refer to arbitrary
54537 	 *  values which also become refzero'd.
54538 	 *
54539 	 *  So, the pointer 'p' is re-looked-up below whenever a side effect
54540 	 *  might have changed it.
54541 	 */
54542 
54543 	idx = thr->callstack_top;
54544 	while (idx > new_top) {
54545 		duk_activation *act;
54546 		duk_hobject *func;
54547 #ifdef DUK_USE_REFERENCE_COUNTING
54548 		duk_hobject *tmp;
54549 #endif
54550 #ifdef DUK_USE_DEBUGGER_SUPPORT
54551 		duk_heap *heap;
54552 #endif
54553 
54554 		idx--;
54555 		DUK_ASSERT_DISABLE(idx >= 0);  /* unsigned */
54556 		DUK_ASSERT((duk_size_t) idx < thr->callstack_size);  /* true, despite side effect resizes */
54557 
54558 		act = thr->callstack + idx;
54559 		/* With lightfuncs, act 'func' may be NULL */
54560 
54561 #ifdef DUK_USE_NONSTD_FUNC_CALLER_PROPERTY
54562 		/*
54563 		 *  Restore 'caller' property for non-strict callee functions.
54564 		 */
54565 
54566 		func = DUK_ACT_GET_FUNC(act);
54567 		if (func != NULL && !DUK_HOBJECT_HAS_STRICT(func)) {
54568 			duk_tval *tv_caller;
54569 			duk_tval tv_tmp;
54570 			duk_hobject *h_tmp;
54571 
54572 			tv_caller = duk_hobject_find_existing_entry_tval_ptr(thr->heap, func, DUK_HTHREAD_STRING_CALLER(thr));
54573 
54574 			/* The act->prev_caller should only be set if the entry for 'caller'
54575 			 * exists (as it is only set in that case, and the property is not
54576 			 * configurable), but handle all the cases anyway.
54577 			 */
54578 
54579 			if (tv_caller) {
54580 				DUK_TVAL_SET_TVAL(&tv_tmp, tv_caller);
54581 				if (act->prev_caller) {
54582 					/* Just transfer the refcount from act->prev_caller to tv_caller,
54583 					 * so no need for a refcount update.  This is the expected case.
54584 					 */
54585 					DUK_TVAL_SET_OBJECT(tv_caller, act->prev_caller);
54586 					act->prev_caller = NULL;
54587 				} else {
54588 					DUK_TVAL_SET_NULL(tv_caller);   /* no incref needed */
54589 					DUK_ASSERT(act->prev_caller == NULL);
54590 				}
54591 				DUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */
54592 			} else {
54593 				h_tmp = act->prev_caller;
54594 				if (h_tmp) {
54595 					act->prev_caller = NULL;
54596 					DUK_HOBJECT_DECREF(thr, h_tmp);  /* side effects */
54597 				}
54598 			}
54599 			act = thr->callstack + idx;  /* avoid side effects */
54600 			DUK_ASSERT(act->prev_caller == NULL);
54601 		}
54602 #endif
54603 
54604 		/*
54605 		 *  Unwind debugger state.  If we unwind while stepping
54606 		 *  (either step over or step into), pause execution.
54607 		 */
54608 
54609 #if defined(DUK_USE_DEBUGGER_SUPPORT)
54610 		heap = thr->heap;
54611 		if (heap->dbg_step_thread == thr &&
54612 		    heap->dbg_step_csindex == idx) {
54613 			/* Pause for all step types: step into, step over, step out.
54614 			 * This is the only place explicitly handling a step out.
54615 			 */
54616 			DUK_HEAP_SET_PAUSED(heap);
54617 			DUK_ASSERT(heap->dbg_step_thread == NULL);
54618 		}
54619 #endif
54620 
54621 		/*
54622 		 *  Close environment record(s) if they exist.
54623 		 *
54624 		 *  Only variable environments are closed.  If lex_env != var_env, it
54625 		 *  cannot currently contain any register bound declarations.
54626 		 *
54627 		 *  Only environments created for a NEWENV function are closed.  If an
54628 		 *  environment is created for e.g. an eval call, it must not be closed.
54629 		 */
54630 
54631 		func = DUK_ACT_GET_FUNC(act);
54632 		if (func != NULL && !DUK_HOBJECT_HAS_NEWENV(func)) {
54633 			DUK_DDD(DUK_DDDPRINT("skip closing environments, envs not owned by this activation"));
54634 			goto skip_env_close;
54635 		}
54636 		/* func is NULL for lightfunc */
54637 
54638 		DUK_ASSERT(act->lex_env == act->var_env);
54639 		if (act->var_env != NULL) {
54640 			DUK_DDD(DUK_DDDPRINT("closing var_env record %p -> %!O",
54641 			                     (void *) act->var_env, (duk_heaphdr *) act->var_env));
54642 			duk_js_close_environment_record(thr, act->var_env, func, act->idx_bottom);
54643 			act = thr->callstack + idx;  /* avoid side effect issues */
54644 		}
54645 
54646 #if 0
54647 		if (act->lex_env != NULL) {
54648 			if (act->lex_env == act->var_env) {
54649 				/* common case, already closed, so skip */
54650 				DUK_DD(DUK_DDPRINT("lex_env and var_env are the same and lex_env "
54651 				                   "already closed -> skip closing lex_env"));
54652 				;
54653 			} else {
54654 				DUK_DD(DUK_DDPRINT("closing lex_env record %p -> %!O",
54655 				                   (void *) act->lex_env, (duk_heaphdr *) act->lex_env));
54656 				duk_js_close_environment_record(thr, act->lex_env, DUK_ACT_GET_FUNC(act), act->idx_bottom);
54657 				act = thr->callstack + idx;  /* avoid side effect issues */
54658 			}
54659 		}
54660 #endif
54661 
54662 		DUK_ASSERT((act->lex_env == NULL) ||
54663 		           ((duk_hobject_find_existing_entry_tval_ptr(thr->heap, act->lex_env, DUK_HTHREAD_STRING_INT_CALLEE(thr)) == NULL) &&
54664 		            (duk_hobject_find_existing_entry_tval_ptr(thr->heap, act->lex_env, DUK_HTHREAD_STRING_INT_VARMAP(thr)) == NULL) &&
54665 		            (duk_hobject_find_existing_entry_tval_ptr(thr->heap, act->lex_env, DUK_HTHREAD_STRING_INT_THREAD(thr)) == NULL) &&
54666 		            (duk_hobject_find_existing_entry_tval_ptr(thr->heap, act->lex_env, DUK_HTHREAD_STRING_INT_REGBASE(thr)) == NULL)));
54667 
54668 		DUK_ASSERT((act->var_env == NULL) ||
54669 		           ((duk_hobject_find_existing_entry_tval_ptr(thr->heap, act->var_env, DUK_HTHREAD_STRING_INT_CALLEE(thr)) == NULL) &&
54670 		            (duk_hobject_find_existing_entry_tval_ptr(thr->heap, act->var_env, DUK_HTHREAD_STRING_INT_VARMAP(thr)) == NULL) &&
54671 		            (duk_hobject_find_existing_entry_tval_ptr(thr->heap, act->var_env, DUK_HTHREAD_STRING_INT_THREAD(thr)) == NULL) &&
54672 		            (duk_hobject_find_existing_entry_tval_ptr(thr->heap, act->var_env, DUK_HTHREAD_STRING_INT_REGBASE(thr)) == NULL)));
54673 
54674 	 skip_env_close:
54675 
54676 		/*
54677 		 *  Update preventcount
54678 		 */
54679 
54680 		if (act->flags & DUK_ACT_FLAG_PREVENT_YIELD) {
54681 			DUK_ASSERT(thr->callstack_preventcount >= 1);
54682 			thr->callstack_preventcount--;
54683 		}
54684 
54685 		/*
54686 		 *  Reference count updates
54687 		 *
54688 		 *  Note: careful manipulation of refcounts.  The top is
54689 		 *  not updated yet, so all the activations are reachable
54690 		 *  for mark-and-sweep (which may be triggered by decref).
54691 		 *  However, the pointers are NULL so this is not an issue.
54692 		 */
54693 
54694 #ifdef DUK_USE_REFERENCE_COUNTING
54695 		tmp = act->var_env;
54696 #endif
54697 		act->var_env = NULL;
54698 #ifdef DUK_USE_REFERENCE_COUNTING
54699 		DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);
54700 		act = thr->callstack + idx;  /* avoid side effect issues */
54701 #endif
54702 
54703 #ifdef DUK_USE_REFERENCE_COUNTING
54704 		tmp = act->lex_env;
54705 #endif
54706 		act->lex_env = NULL;
54707 #ifdef DUK_USE_REFERENCE_COUNTING
54708 		DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);
54709 		act = thr->callstack + idx;  /* avoid side effect issues */
54710 #endif
54711 
54712 		/* Note: this may cause a corner case situation where a finalizer
54713 		 * may see a currently reachable activation whose 'func' is NULL.
54714 		 */
54715 #ifdef DUK_USE_REFERENCE_COUNTING
54716 		tmp = DUK_ACT_GET_FUNC(act);
54717 #endif
54718 		act->func = NULL;
54719 #ifdef DUK_USE_REFERENCE_COUNTING
54720 		DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);
54721 		act = thr->callstack + idx;  /* avoid side effect issues */
54722 		DUK_UNREF(act);
54723 #endif
54724 	}
54725 
54726 	thr->callstack_top = new_top;
54727 
54728 	/*
54729 	 *  We could clear the book-keeping variables for the topmost activation,
54730 	 *  but don't do so now.
54731 	 */
54732 #if 0
54733 	if (thr->callstack_top > 0) {
54734 		duk_activation *act = thr->callstack + thr->callstack_top - 1;
54735 		act->idx_retval = 0;
54736 	}
54737 #endif
54738 
54739 	/* Note: any entries above the callstack top are garbage and not zeroed.
54740 	 * Also topmost activation idx_retval is garbage (not zeroed), and must
54741 	 * be ignored.
54742 	 */
54743 }
54744 
54745 DUK_INTERNAL void duk_hthread_catchstack_grow(duk_hthread *thr) {
54746 	duk_catcher *new_ptr;
54747 	duk_size_t old_size;
54748 	duk_size_t new_size;
54749 
54750 	DUK_ASSERT(thr != NULL);
54751 	DUK_ASSERT_DISABLE(thr->catchstack_top);  /* avoid warning (unsigned) */
54752 	DUK_ASSERT(thr->catchstack_size >= thr->catchstack_top);
54753 
54754 	if (thr->catchstack_top < thr->catchstack_size) {
54755 		return;
54756 	}
54757 
54758 	old_size = thr->catchstack_size;
54759 	new_size = old_size + DUK_CATCHSTACK_GROW_STEP;
54760 
54761 	/* this is a bit approximate (errors out before max is reached); this is OK */
54762 	if (new_size >= thr->catchstack_max) {
54763 		DUK_ERROR_RANGE(thr, DUK_STR_CATCHSTACK_LIMIT);
54764 	}
54765 
54766 	DUK_DD(DUK_DDPRINT("growing catchstack %ld -> %ld", (long) old_size, (long) new_size));
54767 
54768 	/*
54769 	 *  Note: must use indirect variant of DUK_REALLOC() because underlying
54770 	 *  pointer may be changed by mark-and-sweep.
54771 	 */
54772 
54773 	DUK_ASSERT(new_size > 0);
54774 	new_ptr = (duk_catcher *) DUK_REALLOC_INDIRECT(thr->heap, duk_hthread_get_catchstack_ptr, (void *) thr, sizeof(duk_catcher) * new_size);
54775 	if (!new_ptr) {
54776 		/* No need for a NULL/zero-size check because new_size > 0) */
54777 		DUK_ERROR_ALLOC_DEFMSG(thr);
54778 	}
54779 	thr->catchstack = new_ptr;
54780 	thr->catchstack_size = new_size;
54781 
54782 	/* note: any entries above the catchstack top are garbage and not zeroed */
54783 }
54784 
54785 DUK_INTERNAL void duk_hthread_catchstack_shrink_check(duk_hthread *thr) {
54786 	duk_size_t new_size;
54787 	duk_catcher *p;
54788 
54789 	DUK_ASSERT(thr != NULL);
54790 	DUK_ASSERT_DISABLE(thr->catchstack_top >= 0);  /* avoid warning (unsigned) */
54791 	DUK_ASSERT(thr->catchstack_size >= thr->catchstack_top);
54792 
54793 	if (thr->catchstack_size - thr->catchstack_top < DUK_CATCHSTACK_SHRINK_THRESHOLD) {
54794 		return;
54795 	}
54796 
54797 	new_size = thr->catchstack_top + DUK_CATCHSTACK_SHRINK_SPARE;
54798 	DUK_ASSERT(new_size >= thr->catchstack_top);
54799 
54800 	DUK_DD(DUK_DDPRINT("shrinking catchstack %ld -> %ld", (long) thr->catchstack_size, (long) new_size));
54801 
54802 	/*
54803 	 *  Note: must use indirect variant of DUK_REALLOC() because underlying
54804 	 *  pointer may be changed by mark-and-sweep.
54805 	 */
54806 
54807 	/* shrink failure is not fatal */
54808 	p = (duk_catcher *) DUK_REALLOC_INDIRECT(thr->heap, duk_hthread_get_catchstack_ptr, (void *) thr, sizeof(duk_catcher) * new_size);
54809 	if (p) {
54810 		thr->catchstack = p;
54811 		thr->catchstack_size = new_size;
54812 	} else {
54813 		/* Because new_size != 0, if condition doesn't need to be
54814 		 * (p != NULL || new_size == 0).
54815 		 */
54816 		DUK_ASSERT(new_size != 0);
54817 		DUK_D(DUK_DPRINT("catchstack shrink failed, ignoring"));
54818 	}
54819 
54820 	/* note: any entries above the catchstack top are garbage and not zeroed */
54821 }
54822 
54823 DUK_INTERNAL void duk_hthread_catchstack_unwind(duk_hthread *thr, duk_size_t new_top) {
54824 	duk_size_t idx;
54825 
54826 	DUK_DDD(DUK_DDDPRINT("unwind catchstack top of thread %p from %ld to %ld",
54827 	                     (void *) thr,
54828 	                     (thr != NULL ? (long) thr->catchstack_top : (long) -1),
54829 	                     (long) new_top));
54830 
54831 	DUK_ASSERT(thr);
54832 	DUK_ASSERT(thr->heap);
54833 	DUK_ASSERT_DISABLE(new_top >= 0);  /* unsigned */
54834 	DUK_ASSERT((duk_size_t) new_top <= thr->catchstack_top);  /* cannot grow */
54835 
54836 	/*
54837 	 *  Since there are no references in the catcher structure,
54838 	 *  unwinding is quite simple.  The only thing we need to
54839 	 *  look out for is popping a possible lexical environment
54840 	 *  established for an active catch clause.
54841 	 */
54842 
54843 	idx = thr->catchstack_top;
54844 	while (idx > new_top) {
54845 		duk_catcher *p;
54846 		duk_activation *act;
54847 		duk_hobject *env;
54848 
54849 		idx--;
54850 		DUK_ASSERT_DISABLE(idx >= 0);  /* unsigned */
54851 		DUK_ASSERT((duk_size_t) idx < thr->catchstack_size);
54852 
54853 		p = thr->catchstack + idx;
54854 
54855 		if (DUK_CAT_HAS_LEXENV_ACTIVE(p)) {
54856 			DUK_DDD(DUK_DDDPRINT("unwinding catchstack idx %ld, callstack idx %ld, callstack top %ld: lexical environment active",
54857 			                     (long) idx, (long) p->callstack_index, (long) thr->callstack_top));
54858 
54859 			/* XXX: Here we have a nasty dependency: the need to manipulate
54860 			 * the callstack means that catchstack must always be unwound by
54861 			 * the caller before unwinding the callstack.  This should be fixed
54862 			 * later.
54863 			 */
54864 
54865 			/* Note that multiple catchstack entries may refer to the same
54866 			 * callstack entry.
54867 			 */
54868 			act = thr->callstack + p->callstack_index;
54869 			DUK_ASSERT(act >= thr->callstack);
54870 			DUK_ASSERT(act < thr->callstack + thr->callstack_top);
54871 
54872 			DUK_DDD(DUK_DDDPRINT("catchstack_index=%ld, callstack_index=%ld, lex_env=%!iO",
54873 			                     (long) idx, (long) p->callstack_index,
54874 			                     (duk_heaphdr *) act->lex_env));
54875 
54876 			env = act->lex_env;             /* current lex_env of the activation (created for catcher) */
54877 			DUK_ASSERT(env != NULL);        /* must be, since env was created when catcher was created */
54878 			act->lex_env = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, env);  /* prototype is lex_env before catcher created */
54879 			DUK_HOBJECT_DECREF(thr, env);
54880 
54881 			/* There is no need to decref anything else than 'env': if 'env'
54882 			 * becomes unreachable, refzero will handle decref'ing its prototype.
54883 			 */
54884 		}
54885 	}
54886 
54887 	thr->catchstack_top = new_top;
54888 
54889 	/* note: any entries above the catchstack top are garbage and not zeroed */
54890 }
54891 /*
54892  *  Call handling.
54893  *
54894  *  Main functions are:
54895  *
54896  *    - duk_handle_call_unprotected(): unprotected call to Ecmascript or
54897  *      Duktape/C function
54898  *    - duk_handle_call_protected(): protected call to Ecmascript or
54899  *      Duktape/C function
54900  *    - duk_handle_safe_call(): make a protected C call within current
54901  *      activation
54902  *    - duk_handle_ecma_call_setup(): Ecmascript-to-Ecmascript calls
54903  *      (not always possible), including tail calls and coroutine resume
54904  *
54905  *  See 'execution.rst'.
54906  *
54907  *  Note: setjmp() and local variables have a nasty interaction,
54908  *  see execution.rst; non-volatile locals modified after setjmp()
54909  *  call are not guaranteed to keep their value.
54910  */
54911 
54912 /* include removed: duk_internal.h */
54913 
54914 /*
54915  *  Forward declarations.
54916  */
54917 
54918 DUK_LOCAL void duk__handle_call_inner(duk_hthread *thr,
54919                                       duk_idx_t num_stack_args,
54920                                       duk_small_uint_t call_flags,
54921                                       duk_idx_t idx_func);
54922 DUK_LOCAL void duk__handle_call_error(duk_hthread *thr,
54923                                       duk_size_t entry_valstack_bottom_index,
54924                                       duk_size_t entry_valstack_end,
54925                                       duk_size_t entry_catchstack_top,
54926                                       duk_size_t entry_callstack_top,
54927                                       duk_int_t entry_call_recursion_depth,
54928                                       duk_hthread *entry_curr_thread,
54929                                       duk_uint_fast8_t entry_thread_state,
54930                                       duk_instr_t **entry_ptr_curr_pc,
54931                                       duk_idx_t idx_func,
54932                                       duk_jmpbuf *old_jmpbuf_ptr);
54933 DUK_LOCAL void duk__handle_safe_call_inner(duk_hthread *thr,
54934                                            duk_safe_call_function func,
54935                                            duk_idx_t idx_retbase,
54936                                            duk_idx_t num_stack_rets,
54937                                            duk_size_t entry_valstack_bottom_index,
54938                                            duk_size_t entry_callstack_top,
54939                                            duk_size_t entry_catchstack_top);
54940 DUK_LOCAL void duk__handle_safe_call_error(duk_hthread *thr,
54941                                            duk_idx_t idx_retbase,
54942                                            duk_idx_t num_stack_rets,
54943                                            duk_size_t entry_valstack_bottom_index,
54944                                            duk_size_t entry_callstack_top,
54945                                            duk_size_t entry_catchstack_top,
54946                                            duk_jmpbuf *old_jmpbuf_ptr);
54947 DUK_LOCAL void duk__handle_safe_call_shared(duk_hthread *thr,
54948                                             duk_idx_t idx_retbase,
54949                                             duk_idx_t num_stack_rets,
54950                                             duk_int_t entry_call_recursion_depth,
54951                                             duk_hthread *entry_curr_thread,
54952                                             duk_uint_fast8_t entry_thread_state,
54953                                             duk_instr_t **entry_ptr_curr_pc);
54954 
54955 /*
54956  *  Interrupt counter fixup (for development only).
54957  */
54958 
54959 #if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
54960 DUK_LOCAL void duk__interrupt_fixup(duk_hthread *thr, duk_hthread *entry_curr_thread) {
54961 	/* Currently the bytecode executor and executor interrupt
54962 	 * instruction counts are off because we don't execute the
54963 	 * interrupt handler when we're about to exit from the initial
54964 	 * user call into Duktape.
54965 	 *
54966 	 * If we were to execute the interrupt handler here, the counts
54967 	 * would match.  You can enable this block manually to check
54968 	 * that this is the case.
54969 	 */
54970 
54971 	DUK_ASSERT(thr != NULL);
54972 	DUK_ASSERT(thr->heap != NULL);
54973 
54974 #if defined(DUK_USE_INTERRUPT_DEBUG_FIXUP)
54975 	if (entry_curr_thread == NULL) {
54976 		thr->interrupt_init = thr->interrupt_init - thr->interrupt_counter;
54977 		thr->heap->inst_count_interrupt += thr->interrupt_init;
54978 		DUK_DD(DUK_DDPRINT("debug test: updated interrupt count on exit to "
54979 		                   "user code, instruction counts: executor=%ld, interrupt=%ld",
54980 		                   (long) thr->heap->inst_count_exec, (long) thr->heap->inst_count_interrupt));
54981 		DUK_ASSERT(thr->heap->inst_count_exec == thr->heap->inst_count_interrupt);
54982 	}
54983 #else
54984 	DUK_UNREF(thr);
54985 	DUK_UNREF(entry_curr_thread);
54986 #endif
54987 }
54988 #endif
54989 
54990 /*
54991  *  Arguments object creation.
54992  *
54993  *  Creating arguments objects involves many small details, see E5 Section
54994  *  10.6 for the specific requirements.  Much of the arguments object exotic
54995  *  behavior is implemented in duk_hobject_props.c, and is enabled by the
54996  *  object flag DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS.
54997  */
54998 
54999 DUK_LOCAL void duk__create_arguments_object(duk_hthread *thr,
55000                                             duk_hobject *func,
55001                                             duk_hobject *varenv,
55002                                             duk_idx_t idx_argbase,        /* idx of first argument on stack */
55003                                             duk_idx_t num_stack_args) {   /* num args starting from idx_argbase */
55004 	duk_context *ctx = (duk_context *) thr;
55005 	duk_hobject *arg;          /* 'arguments' */
55006 	duk_hobject *formals;      /* formals for 'func' (may be NULL if func is a C function) */
55007 	duk_idx_t i_arg;
55008 	duk_idx_t i_map;
55009 	duk_idx_t i_mappednames;
55010 	duk_idx_t i_formals;
55011 	duk_idx_t i_argbase;
55012 	duk_idx_t n_formals;
55013 	duk_idx_t idx;
55014 	duk_bool_t need_map;
55015 
55016 	DUK_DDD(DUK_DDDPRINT("creating arguments object for func=%!iO, varenv=%!iO, "
55017 	                     "idx_argbase=%ld, num_stack_args=%ld",
55018 	                     (duk_heaphdr *) func, (duk_heaphdr *) varenv,
55019 	                     (long) idx_argbase, (long) num_stack_args));
55020 
55021 	DUK_ASSERT(thr != NULL);
55022 	DUK_ASSERT(func != NULL);
55023 	DUK_ASSERT(DUK_HOBJECT_IS_NONBOUND_FUNCTION(func));
55024 	DUK_ASSERT(varenv != NULL);
55025 	DUK_ASSERT(idx_argbase >= 0);  /* assumed to bottom relative */
55026 	DUK_ASSERT(num_stack_args >= 0);
55027 
55028 	need_map = 0;
55029 
55030 	i_argbase = idx_argbase;
55031 	DUK_ASSERT(i_argbase >= 0);
55032 
55033 	duk_push_hobject(ctx, func);
55034 	duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_FORMALS);
55035 	formals = duk_get_hobject(ctx, -1);
55036 	n_formals = 0;
55037 	if (formals) {
55038 		duk_get_prop_stridx(ctx, -1, DUK_STRIDX_LENGTH);
55039 		n_formals = (duk_idx_t) duk_require_int(ctx, -1);
55040 		duk_pop(ctx);
55041 	}
55042 	duk_remove(ctx, -2);  /* leave formals on stack for later use */
55043 	i_formals = duk_require_top_index(ctx);
55044 
55045 	DUK_ASSERT(n_formals >= 0);
55046 	DUK_ASSERT(formals != NULL || n_formals == 0);
55047 
55048 	DUK_DDD(DUK_DDDPRINT("func=%!O, formals=%!O, n_formals=%ld",
55049 	                     (duk_heaphdr *) func, (duk_heaphdr *) formals,
55050 	                     (long) n_formals));
55051 
55052 	/* [ ... formals ] */
55053 
55054 	/*
55055 	 *  Create required objects:
55056 	 *    - 'arguments' object: array-like, but not an array
55057 	 *    - 'map' object: internal object, tied to 'arguments'
55058 	 *    - 'mappedNames' object: temporary value used during construction
55059 	 */
55060 
55061 	i_arg = duk_push_object_helper(ctx,
55062 	                               DUK_HOBJECT_FLAG_EXTENSIBLE |
55063 	                               DUK_HOBJECT_FLAG_ARRAY_PART |
55064 	                               DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARGUMENTS),
55065 	                               DUK_BIDX_OBJECT_PROTOTYPE);
55066 	DUK_ASSERT(i_arg >= 0);
55067 	arg = duk_require_hobject(ctx, -1);
55068 	DUK_ASSERT(arg != NULL);
55069 
55070 	i_map = duk_push_object_helper(ctx,
55071 	                               DUK_HOBJECT_FLAG_EXTENSIBLE |
55072 	                               DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
55073 	                               -1);  /* no prototype */
55074 	DUK_ASSERT(i_map >= 0);
55075 
55076 	i_mappednames = duk_push_object_helper(ctx,
55077 	                                       DUK_HOBJECT_FLAG_EXTENSIBLE |
55078 	                                       DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
55079 	                                       -1);  /* no prototype */
55080 	DUK_ASSERT(i_mappednames >= 0);
55081 
55082 	/* [ ... formals arguments map mappedNames ] */
55083 
55084 	DUK_DDD(DUK_DDDPRINT("created arguments related objects: "
55085 	                     "arguments at index %ld -> %!O "
55086 	                     "map at index %ld -> %!O "
55087 	                     "mappednames at index %ld -> %!O",
55088 	                     (long) i_arg, (duk_heaphdr *) duk_get_hobject(ctx, i_arg),
55089 	                     (long) i_map, (duk_heaphdr *) duk_get_hobject(ctx, i_map),
55090 	                     (long) i_mappednames, (duk_heaphdr *) duk_get_hobject(ctx, i_mappednames)));
55091 
55092 	/*
55093 	 *  Init arguments properties, map, etc.
55094 	 */
55095 
55096 	duk_push_int(ctx, num_stack_args);
55097 	duk_xdef_prop_stridx(ctx, i_arg, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_WC);
55098 
55099 	/*
55100 	 *  Init argument related properties
55101 	 */
55102 
55103 	/* step 11 */
55104 	idx = num_stack_args - 1;
55105 	while (idx >= 0) {
55106 		DUK_DDD(DUK_DDDPRINT("arg idx %ld, argbase=%ld, argidx=%ld",
55107 		                     (long) idx, (long) i_argbase, (long) (i_argbase + idx)));
55108 
55109 		DUK_DDD(DUK_DDDPRINT("define arguments[%ld]=arg", (long) idx));
55110 		duk_dup(ctx, i_argbase + idx);
55111 		duk_xdef_prop_index_wec(ctx, i_arg, (duk_uarridx_t) idx);
55112 		DUK_DDD(DUK_DDDPRINT("defined arguments[%ld]=arg", (long) idx));
55113 
55114 		/* step 11.c is relevant only if non-strict (checked in 11.c.ii) */
55115 		if (!DUK_HOBJECT_HAS_STRICT(func) && idx < n_formals) {
55116 			DUK_ASSERT(formals != NULL);
55117 
55118 			DUK_DDD(DUK_DDDPRINT("strict function, index within formals (%ld < %ld)",
55119 			                     (long) idx, (long) n_formals));
55120 
55121 			duk_get_prop_index(ctx, i_formals, idx);
55122 			DUK_ASSERT(duk_is_string(ctx, -1));
55123 
55124 			duk_dup(ctx, -1);  /* [ ... name name ] */
55125 
55126 			if (!duk_has_prop(ctx, i_mappednames)) {
55127 				/* steps 11.c.ii.1 - 11.c.ii.4, but our internal book-keeping
55128 				 * differs from the reference model
55129 				 */
55130 
55131 				/* [ ... name ] */
55132 
55133 				need_map = 1;
55134 
55135 				DUK_DDD(DUK_DDDPRINT("set mappednames[%s]=%ld",
55136 				                     (const char *) duk_get_string(ctx, -1),
55137 				                     (long) idx));
55138 				duk_dup(ctx, -1);                      /* name */
55139 				duk_push_uint(ctx, (duk_uint_t) idx);  /* index */
55140 				duk_to_string(ctx, -1);
55141 				duk_xdef_prop_wec(ctx, i_mappednames);  /* out of spec, must be configurable */
55142 
55143 				DUK_DDD(DUK_DDDPRINT("set map[%ld]=%s",
55144 				                     (long) idx,
55145 				                     duk_get_string(ctx, -1)));
55146 				duk_dup(ctx, -1);         /* name */
55147 				duk_xdef_prop_index_wec(ctx, i_map, (duk_uarridx_t) idx);  /* out of spec, must be configurable */
55148 			} else {
55149 				/* duk_has_prop() popped the second 'name' */
55150 			}
55151 
55152 			/* [ ... name ] */
55153 			duk_pop(ctx);  /* pop 'name' */
55154 		}
55155 
55156 		idx--;
55157 	}
55158 
55159 	DUK_DDD(DUK_DDDPRINT("actual arguments processed"));
55160 
55161 	/* step 12 */
55162 	if (need_map) {
55163 		DUK_DDD(DUK_DDDPRINT("adding 'map' and 'varenv' to arguments object"));
55164 
55165 		/* should never happen for a strict callee */
55166 		DUK_ASSERT(!DUK_HOBJECT_HAS_STRICT(func));
55167 
55168 		duk_dup(ctx, i_map);
55169 		duk_xdef_prop_stridx(ctx, i_arg, DUK_STRIDX_INT_MAP, DUK_PROPDESC_FLAGS_NONE);  /* out of spec, don't care */
55170 
55171 		/* The variable environment for magic variable bindings needs to be
55172 		 * given by the caller and recorded in the arguments object.
55173 		 *
55174 		 * See E5 Section 10.6, the creation of setters/getters.
55175 		 *
55176 		 * The variable environment also provides access to the callee, so
55177 		 * an explicit (internal) callee property is not needed.
55178 		 */
55179 
55180 		duk_push_hobject(ctx, varenv);
55181 		duk_xdef_prop_stridx(ctx, i_arg, DUK_STRIDX_INT_VARENV, DUK_PROPDESC_FLAGS_NONE);  /* out of spec, don't care */
55182 	}
55183 
55184 	/* steps 13-14 */
55185 	if (DUK_HOBJECT_HAS_STRICT(func)) {
55186 		/* Callee/caller are throwers and are not deletable etc.  They
55187 		 * could be implemented as virtual properties, but currently
55188 		 * there is no support for virtual properties which are accessors
55189 		 * (only plain virtual properties).  This would not be difficult
55190 		 * to change in duk_hobject_props, but we can make the throwers
55191 		 * normal, concrete properties just as easily.
55192 		 *
55193 		 * Note that the specification requires that the *same* thrower
55194 		 * built-in object is used here!  See E5 Section 10.6 main
55195 		 * algoritm, step 14, and Section 13.2.3 which describes the
55196 		 * thrower.  See test case test-arguments-throwers.js.
55197 		 */
55198 
55199 		DUK_DDD(DUK_DDDPRINT("strict function, setting caller/callee to throwers"));
55200 
55201 		duk_xdef_prop_stridx_thrower(ctx, i_arg, DUK_STRIDX_CALLER, DUK_PROPDESC_FLAGS_NONE);
55202 		duk_xdef_prop_stridx_thrower(ctx, i_arg, DUK_STRIDX_CALLEE, DUK_PROPDESC_FLAGS_NONE);
55203 	} else {
55204 		DUK_DDD(DUK_DDDPRINT("non-strict function, setting callee to actual value"));
55205 		duk_push_hobject(ctx, func);
55206 		duk_xdef_prop_stridx(ctx, i_arg, DUK_STRIDX_CALLEE, DUK_PROPDESC_FLAGS_WC);
55207 	}
55208 
55209 	/* set exotic behavior only after we're done */
55210 	if (need_map) {
55211 		/* Exotic behaviors are only enabled for arguments objects
55212 		 * which have a parameter map (see E5 Section 10.6 main
55213 		 * algorithm, step 12).
55214 		 *
55215 		 * In particular, a non-strict arguments object with no
55216 		 * mapped formals does *NOT* get exotic behavior, even
55217 		 * for e.g. "caller" property.  This seems counterintuitive
55218 		 * but seems to be the case.
55219 		 */
55220 
55221 		/* cannot be strict (never mapped variables) */
55222 		DUK_ASSERT(!DUK_HOBJECT_HAS_STRICT(func));
55223 
55224 		DUK_DDD(DUK_DDDPRINT("enabling exotic behavior for arguments object"));
55225 		DUK_HOBJECT_SET_EXOTIC_ARGUMENTS(arg);
55226 	} else {
55227 		DUK_DDD(DUK_DDDPRINT("not enabling exotic behavior for arguments object"));
55228 	}
55229 
55230 	DUK_DDD(DUK_DDDPRINT("final arguments related objects: "
55231 	                     "arguments at index %ld -> %!O "
55232 	                     "map at index %ld -> %!O "
55233 	                     "mappednames at index %ld -> %!O",
55234 	                     (long) i_arg, (duk_heaphdr *) duk_get_hobject(ctx, i_arg),
55235 	                     (long) i_map, (duk_heaphdr *) duk_get_hobject(ctx, i_map),
55236 	                     (long) i_mappednames, (duk_heaphdr *) duk_get_hobject(ctx, i_mappednames)));
55237 
55238 	/* [ args(n) [crud] formals arguments map mappednames ] */
55239 
55240 	duk_pop_2(ctx);
55241 	duk_remove(ctx, -2);
55242 
55243 	/* [ args [crud] arguments ] */
55244 }
55245 
55246 /* Helper for creating the arguments object and adding it to the env record
55247  * on top of the value stack.  This helper has a very strict dependency on
55248  * the shape of the input stack.
55249  */
55250 DUK_LOCAL void duk__handle_createargs_for_call(duk_hthread *thr,
55251                                                duk_hobject *func,
55252                                                duk_hobject *env,
55253                                                duk_idx_t num_stack_args) {
55254 	duk_context *ctx = (duk_context *) thr;
55255 
55256 	DUK_DDD(DUK_DDDPRINT("creating arguments object for function call"));
55257 
55258 	DUK_ASSERT(thr != NULL);
55259 	DUK_ASSERT(func != NULL);
55260 	DUK_ASSERT(env != NULL);
55261 	DUK_ASSERT(DUK_HOBJECT_HAS_CREATEARGS(func));
55262 	DUK_ASSERT(duk_get_top(ctx) >= num_stack_args + 1);
55263 
55264 	/* [ ... arg1 ... argN envobj ] */
55265 
55266 	duk__create_arguments_object(thr,
55267 	                             func,
55268 	                             env,
55269 	                             duk_get_top(ctx) - num_stack_args - 1,    /* idx_argbase */
55270 	                             num_stack_args);
55271 
55272 	/* [ ... arg1 ... argN envobj argobj ] */
55273 
55274 	duk_xdef_prop_stridx(ctx,
55275 	                     -2,
55276 	                     DUK_STRIDX_LC_ARGUMENTS,
55277 	                     DUK_HOBJECT_HAS_STRICT(func) ? DUK_PROPDESC_FLAGS_E :   /* strict: non-deletable, non-writable */
55278 	                                                    DUK_PROPDESC_FLAGS_WE);  /* non-strict: non-deletable, writable */
55279 	/* [ ... arg1 ... argN envobj ] */
55280 }
55281 
55282 /*
55283  *  Helper for handling a "bound function" chain when a call is being made.
55284  *
55285  *  Follows the bound function chain until a non-bound function is found.
55286  *  Prepends the bound arguments to the value stack (at idx_func + 2),
55287  *  updating 'num_stack_args' in the process.  The 'this' binding is also
55288  *  updated if necessary (at idx_func + 1).  Note that for constructor calls
55289  *  the 'this' binding is never updated by [[BoundThis]].
55290  *
55291  *  XXX: bound function chains could be collapsed at bound function creation
55292  *  time so that each bound function would point directly to a non-bound
55293  *  function.  This would make call time handling much easier.
55294  */
55295 
55296 DUK_LOCAL void duk__handle_bound_chain_for_call(duk_hthread *thr,
55297                                                 duk_idx_t idx_func,
55298                                                 duk_idx_t *p_num_stack_args,   /* may be changed by call */
55299                                                 duk_bool_t is_constructor_call) {
55300 	duk_context *ctx = (duk_context *) thr;
55301 	duk_idx_t num_stack_args;
55302 	duk_tval *tv_func;
55303 	duk_hobject *func;
55304 	duk_uint_t sanity;
55305 
55306 	DUK_ASSERT(thr != NULL);
55307 	DUK_ASSERT(p_num_stack_args != NULL);
55308 
55309 	/* On entry, item at idx_func is a bound, non-lightweight function,
55310 	 * but we don't rely on that below.
55311 	 */
55312 
55313 	num_stack_args = *p_num_stack_args;
55314 
55315 	sanity = DUK_HOBJECT_BOUND_CHAIN_SANITY;
55316 	do {
55317 		duk_idx_t i, len;
55318 
55319 		tv_func = duk_require_tval(ctx, idx_func);
55320 		DUK_ASSERT(tv_func != NULL);
55321 
55322 		if (DUK_TVAL_IS_LIGHTFUNC(tv_func)) {
55323 			/* Lightweight function: never bound, so terminate. */
55324 			break;
55325 		} else if (DUK_TVAL_IS_OBJECT(tv_func)) {
55326 			func = DUK_TVAL_GET_OBJECT(tv_func);
55327 			if (!DUK_HOBJECT_HAS_BOUND(func)) {
55328 				/* Normal non-bound function. */
55329 				break;
55330 			}
55331 		} else {
55332 			/* Function.prototype.bind() should never let this happen,
55333 			 * ugly error message is enough.
55334 			 */
55335 			DUK_ERROR_INTERNAL_DEFMSG(thr);
55336 		}
55337 		DUK_ASSERT(DUK_TVAL_GET_OBJECT(tv_func) != NULL);
55338 
55339 		/* XXX: this could be more compact by accessing the internal properties
55340 		 * directly as own properties (they cannot be inherited, and are not
55341 		 * externally visible).
55342 		 */
55343 
55344 		DUK_DDD(DUK_DDDPRINT("bound function encountered, ptr=%p, num_stack_args=%ld: %!T",
55345 		                     (void *) DUK_TVAL_GET_OBJECT(tv_func), (long) num_stack_args, tv_func));
55346 
55347 		/* [ ... func this arg1 ... argN ] */
55348 
55349 		if (is_constructor_call) {
55350 			/* See: tests/ecmascript/test-spec-bound-constructor.js */
55351 			DUK_DDD(DUK_DDDPRINT("constructor call: don't update this binding"));
55352 		} else {
55353 			duk_get_prop_stridx(ctx, idx_func, DUK_STRIDX_INT_THIS);
55354 			duk_replace(ctx, idx_func + 1);  /* idx_this = idx_func + 1 */
55355 		}
55356 
55357 		/* [ ... func this arg1 ... argN ] */
55358 
55359 		/* XXX: duk_get_length? */
55360 		duk_get_prop_stridx(ctx, idx_func, DUK_STRIDX_INT_ARGS);  /* -> [ ... func this arg1 ... argN _Args ] */
55361 		duk_get_prop_stridx(ctx, -1, DUK_STRIDX_LENGTH);          /* -> [ ... func this arg1 ... argN _Args length ] */
55362 		len = (duk_idx_t) duk_require_int(ctx, -1);
55363 		duk_pop(ctx);
55364 
55365 		duk_require_stack(ctx, len);
55366 		for (i = 0; i < len; i++) {
55367 			/* XXX: very slow - better to bulk allocate a gap, and copy
55368 			 * from args_array directly (we know it has a compact array
55369 			 * part, etc).
55370 			 */
55371 
55372 			/* [ ... func this <some bound args> arg1 ... argN _Args ] */
55373 			duk_get_prop_index(ctx, -1, i);
55374 			duk_insert(ctx, idx_func + 2 + i);  /* idx_args = idx_func + 2 */
55375 		}
55376 		num_stack_args += len;  /* must be updated to work properly (e.g. creation of 'arguments') */
55377 		duk_pop(ctx);
55378 
55379 		/* [ ... func this <bound args> arg1 ... argN ] */
55380 
55381 		duk_get_prop_stridx(ctx, idx_func, DUK_STRIDX_INT_TARGET);
55382 		duk_replace(ctx, idx_func);  /* replace in stack */
55383 
55384 		DUK_DDD(DUK_DDDPRINT("bound function handled, num_stack_args=%ld, idx_func=%ld, curr func=%!T",
55385 		                     (long) num_stack_args, (long) idx_func, duk_get_tval(ctx, idx_func)));
55386 	} while (--sanity > 0);
55387 
55388 	if (sanity == 0) {
55389 		DUK_ERROR_RANGE(thr, DUK_STR_BOUND_CHAIN_LIMIT);
55390 	}
55391 
55392 	DUK_DDD(DUK_DDDPRINT("final non-bound function is: %!T", duk_get_tval(ctx, idx_func)));
55393 
55394 #if defined(DUK_USE_ASSERTIONS)
55395 	tv_func = duk_require_tval(ctx, idx_func);
55396 	DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv_func) || DUK_TVAL_IS_OBJECT(tv_func));
55397 	if (DUK_TVAL_IS_OBJECT(tv_func)) {
55398 		func = DUK_TVAL_GET_OBJECT(tv_func);
55399 		DUK_ASSERT(func != NULL);
55400 		DUK_ASSERT(!DUK_HOBJECT_HAS_BOUND(func));
55401 		DUK_ASSERT(DUK_HOBJECT_HAS_COMPILEDFUNCTION(func) ||
55402 		           DUK_HOBJECT_HAS_NATIVEFUNCTION(func));
55403 	}
55404 #endif
55405 
55406 	/* write back */
55407 	*p_num_stack_args = num_stack_args;
55408 }
55409 
55410 /*
55411  *  Helper for setting up var_env and lex_env of an activation,
55412  *  assuming it does NOT have the DUK_HOBJECT_FLAG_NEWENV flag.
55413  */
55414 
55415 DUK_LOCAL void duk__handle_oldenv_for_call(duk_hthread *thr,
55416                                            duk_hobject *func,
55417                                            duk_activation *act) {
55418 	duk_tval *tv;
55419 
55420 	DUK_ASSERT(thr != NULL);
55421 	DUK_ASSERT(func != NULL);
55422 	DUK_ASSERT(act != NULL);
55423 	DUK_ASSERT(!DUK_HOBJECT_HAS_NEWENV(func));
55424 	DUK_ASSERT(!DUK_HOBJECT_HAS_CREATEARGS(func));
55425 
55426 	tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, func, DUK_HTHREAD_STRING_INT_LEXENV(thr));
55427 	if (tv) {
55428 		DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv));
55429 		DUK_ASSERT(DUK_HOBJECT_IS_ENV(DUK_TVAL_GET_OBJECT(tv)));
55430 		act->lex_env = DUK_TVAL_GET_OBJECT(tv);
55431 
55432 		tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, func, DUK_HTHREAD_STRING_INT_VARENV(thr));
55433 		if (tv) {
55434 			DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv));
55435 			DUK_ASSERT(DUK_HOBJECT_IS_ENV(DUK_TVAL_GET_OBJECT(tv)));
55436 			act->var_env = DUK_TVAL_GET_OBJECT(tv);
55437 		} else {
55438 			act->var_env = act->lex_env;
55439 		}
55440 	} else {
55441 		act->lex_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
55442 		act->var_env = act->lex_env;
55443 	}
55444 
55445 	DUK_HOBJECT_INCREF_ALLOWNULL(thr, act->lex_env);
55446 	DUK_HOBJECT_INCREF_ALLOWNULL(thr, act->var_env);
55447 }
55448 
55449 /*
55450  *  Helper for updating callee 'caller' property.
55451  */
55452 
55453 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
55454 DUK_LOCAL void duk__update_func_caller_prop(duk_hthread *thr, duk_hobject *func) {
55455 	duk_tval *tv_caller;
55456 	duk_hobject *h_tmp;
55457 	duk_activation *act_callee;
55458 	duk_activation *act_caller;
55459 
55460 	DUK_ASSERT(thr != NULL);
55461 	DUK_ASSERT(func != NULL);
55462 	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUND(func));  /* bound chain resolved */
55463 	DUK_ASSERT(thr->callstack_top >= 1);
55464 
55465 	if (DUK_HOBJECT_HAS_STRICT(func)) {
55466 		/* Strict functions don't get their 'caller' updated. */
55467 		return;
55468 	}
55469 
55470 	act_callee = thr->callstack + thr->callstack_top - 1;
55471 	act_caller = (thr->callstack_top >= 2 ? act_callee - 1 : NULL);
55472 
55473 	/* XXX: check .caller writability? */
55474 
55475 	/* Backup 'caller' property and update its value. */
55476 	tv_caller = duk_hobject_find_existing_entry_tval_ptr(thr->heap, func, DUK_HTHREAD_STRING_CALLER(thr));
55477 	if (tv_caller) {
55478 		/* If caller is global/eval code, 'caller' should be set to
55479 		 * 'null'.
55480 		 *
55481 		 * XXX: there is no exotic flag to infer this correctly now.
55482 		 * The NEWENV flag is used now which works as intended for
55483 		 * everything (global code, non-strict eval code, and functions)
55484 		 * except strict eval code.  Bound functions are never an issue
55485 		 * because 'func' has been resolved to a non-bound function.
55486 		 */
55487 
55488 		if (act_caller) {
55489 			/* act_caller->func may be NULL in some finalization cases,
55490 			 * just treat like we don't know the caller.
55491 			 */
55492 			if (act_caller->func && !DUK_HOBJECT_HAS_NEWENV(act_caller->func)) {
55493 				/* Setting to NULL causes 'caller' to be set to
55494 				 * 'null' as desired.
55495 				 */
55496 				act_caller = NULL;
55497 			}
55498 		}
55499 
55500 		if (DUK_TVAL_IS_OBJECT(tv_caller)) {
55501 			h_tmp = DUK_TVAL_GET_OBJECT(tv_caller);
55502 			DUK_ASSERT(h_tmp != NULL);
55503 			act_callee->prev_caller = h_tmp;
55504 
55505 			/* Previous value doesn't need refcount changes because its ownership
55506 			 * is transferred to prev_caller.
55507 			 */
55508 
55509 			if (act_caller) {
55510 				DUK_ASSERT(act_caller->func != NULL);
55511 				DUK_TVAL_SET_OBJECT(tv_caller, act_caller->func);
55512 				DUK_TVAL_INCREF(thr, tv_caller);
55513 			} else {
55514 				DUK_TVAL_SET_NULL(tv_caller);  /* no incref */
55515 			}
55516 		} else {
55517 			/* 'caller' must only take on 'null' or function value */
55518 			DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv_caller));
55519 			DUK_ASSERT(act_callee->prev_caller == NULL);
55520 			if (act_caller && act_caller->func) {
55521 				/* Tolerate act_caller->func == NULL which happens in
55522 				 * some finalization cases; treat like unknown caller.
55523 				 */
55524 				DUK_TVAL_SET_OBJECT(tv_caller, act_caller->func);
55525 				DUK_TVAL_INCREF(thr, tv_caller);
55526 			} else {
55527 				DUK_TVAL_SET_NULL(tv_caller);  /* no incref */
55528 			}
55529 		}
55530 	}
55531 }
55532 #endif  /* DUK_USE_NONSTD_FUNC_CALLER_PROPERTY */
55533 
55534 /*
55535  *  Determine the effective 'this' binding and coerce the current value
55536  *  on the valstack to the effective one (in-place, at idx_this).
55537  *
55538  *  The current this value in the valstack (at idx_this) represents either:
55539  *    - the caller's requested 'this' binding; or
55540  *    - a 'this' binding accumulated from the bound function chain
55541  *
55542  *  The final 'this' binding for the target function may still be
55543  *  different, and is determined as described in E5 Section 10.4.3.
55544  *
55545  *  For global and eval code (E5 Sections 10.4.1 and 10.4.2), we assume
55546  *  that the caller has provided the correct 'this' binding explicitly
55547  *  when calling, i.e.:
55548  *
55549  *    - global code: this=global object
55550  *    - direct eval: this=copy from eval() caller's this binding
55551  *    - other eval:  this=global object
55552  *
55553  *  Note: this function may cause a recursive function call with arbitrary
55554  *  side effects, because ToObject() may be called.
55555  */
55556 
55557 DUK_LOCAL void duk__coerce_effective_this_binding(duk_hthread *thr,
55558                                                   duk_hobject *func,
55559                                                   duk_idx_t idx_this) {
55560 	duk_context *ctx = (duk_context *) thr;
55561 	duk_tval *tv_this;
55562 	duk_hobject *obj_global;
55563 
55564 	if (func == NULL || DUK_HOBJECT_HAS_STRICT(func)) {
55565 		/* Lightfuncs are always considered strict. */
55566 		DUK_DDD(DUK_DDDPRINT("this binding: strict -> use directly"));
55567 		return;
55568 	}
55569 
55570 	/* XXX: byte offset */
55571 	tv_this = thr->valstack_bottom + idx_this;
55572 	switch (DUK_TVAL_GET_TAG(tv_this)) {
55573 	case DUK_TAG_OBJECT:
55574 	case DUK_TAG_LIGHTFUNC:  /* lightfuncs are treated like objects and not coerced */
55575 		DUK_DDD(DUK_DDDPRINT("this binding: non-strict, object -> use directly"));
55576 		break;
55577 	case DUK_TAG_UNDEFINED:
55578 	case DUK_TAG_NULL:
55579 		DUK_DDD(DUK_DDDPRINT("this binding: non-strict, undefined/null -> use global object"));
55580 		obj_global = thr->builtins[DUK_BIDX_GLOBAL];
55581 		/* XXX: avoid this check somehow */
55582 		if (DUK_LIKELY(obj_global != NULL)) {
55583 			DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv_this));  /* no need to decref previous value */
55584 			DUK_TVAL_SET_OBJECT(tv_this, obj_global);
55585 			DUK_HOBJECT_INCREF(thr, obj_global);
55586 		} else {
55587 			/* This may only happen if built-ins are being "torn down".
55588 			 * This behavior is out of specification scope.
55589 			 */
55590 			DUK_D(DUK_DPRINT("this binding: wanted to use global object, but it is NULL -> using undefined instead"));
55591 			DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv_this));  /* no need to decref previous value */
55592 			DUK_TVAL_SET_UNDEFINED(tv_this);  /* nothing to incref */
55593 		}
55594 		break;
55595 	default:
55596 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv_this));
55597 		DUK_DDD(DUK_DDDPRINT("this binding: non-strict, not object/undefined/null -> use ToObject(value)"));
55598 		duk_to_object(ctx, idx_this);  /* may have side effects */
55599 		break;
55600 	}
55601 }
55602 
55603 /*
55604  *  Shared helper for non-bound func lookup.
55605  *
55606  *  Returns duk_hobject * to the final non-bound function (NULL for lightfunc).
55607  */
55608 
55609 DUK_LOCAL duk_hobject *duk__nonbound_func_lookup(duk_context *ctx,
55610                                                  duk_idx_t idx_func,
55611                                                  duk_idx_t *out_num_stack_args,
55612                                                  duk_tval **out_tv_func,
55613                                                  duk_small_uint_t call_flags) {
55614 	duk_hthread *thr = (duk_hthread *) ctx;
55615 	duk_tval *tv_func;
55616 	duk_hobject *func;
55617 
55618 	for (;;) {
55619 		/* Use loop to minimize code size of relookup after bound function case */
55620 		tv_func = DUK_GET_TVAL_POSIDX(ctx, idx_func);
55621 		DUK_ASSERT(tv_func != NULL);
55622 
55623 		if (DUK_TVAL_IS_OBJECT(tv_func)) {
55624 			func = DUK_TVAL_GET_OBJECT(tv_func);
55625 			if (!DUK_HOBJECT_IS_CALLABLE(func)) {
55626 				goto not_callable_error;
55627 			}
55628 			if (DUK_HOBJECT_HAS_BOUND(func)) {
55629 				duk__handle_bound_chain_for_call(thr, idx_func, out_num_stack_args, call_flags & DUK_CALL_FLAG_CONSTRUCTOR_CALL);
55630 
55631 				/* The final object may be a normal function or a lightfunc.
55632 				 * We need to re-lookup tv_func because it may have changed
55633 				 * (also value stack may have been resized).  Loop again to
55634 				 * do that; we're guaranteed not to come here again.
55635 				 */
55636 				DUK_ASSERT(DUK_TVAL_IS_OBJECT(duk_require_tval(ctx, idx_func)) ||
55637 				           DUK_TVAL_IS_LIGHTFUNC(duk_require_tval(ctx, idx_func)));
55638 				continue;
55639 			}
55640 		} else if (DUK_TVAL_IS_LIGHTFUNC(tv_func)) {
55641 			func = NULL;
55642 		} else {
55643 			goto not_callable_error;
55644 		}
55645 		break;
55646 	}
55647 
55648 	DUK_ASSERT((DUK_TVAL_IS_OBJECT(tv_func) && DUK_HOBJECT_IS_CALLABLE(DUK_TVAL_GET_OBJECT(tv_func))) ||
55649 	           DUK_TVAL_IS_LIGHTFUNC(tv_func));
55650 	DUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUND(func));
55651 	DUK_ASSERT(func == NULL || (DUK_HOBJECT_IS_COMPILEDFUNCTION(func) ||
55652 	                            DUK_HOBJECT_IS_NATIVEFUNCTION(func)));
55653 
55654 	*out_tv_func = tv_func;
55655 	return func;
55656 
55657  not_callable_error:
55658 	DUK_ASSERT(tv_func != NULL);
55659 #if defined(DUK_USE_PARANOID_ERRORS)
55660 	DUK_ERROR_TYPE(thr, DUK_STR_NOT_CALLABLE);
55661 #else
55662 	DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "%s not callable", duk_push_string_tval_readable(ctx, tv_func));
55663 #endif
55664 	DUK_UNREACHABLE();
55665 	return NULL;  /* never executed */
55666 }
55667 
55668 /*
55669  *  Value stack resize and stack top adjustment helper.
55670  *
55671  *  XXX: This should all be merged to duk_valstack_resize_raw().
55672  */
55673 
55674 DUK_LOCAL void duk__adjust_valstack_and_top(duk_hthread *thr,
55675                                             duk_idx_t num_stack_args,
55676                                             duk_idx_t idx_args,
55677                                             duk_idx_t nregs,
55678                                             duk_idx_t nargs,
55679                                             duk_hobject *func) {
55680 	duk_context *ctx = (duk_context *) thr;
55681 	duk_size_t vs_min_size;
55682 	duk_bool_t adjusted_top = 0;
55683 
55684 	vs_min_size = (thr->valstack_bottom - thr->valstack) +  /* bottom of current func */
55685 	              idx_args;                                 /* bottom of new func */
55686 
55687 	if (nregs >= 0) {
55688 		DUK_ASSERT(nargs >= 0);
55689 		DUK_ASSERT(nregs >= nargs);
55690 		vs_min_size += nregs;
55691 	} else {
55692 		/* 'func' wants stack "as is" */
55693 		vs_min_size += num_stack_args;  /* num entries of new func at entry */
55694 	}
55695 	if (func == NULL || DUK_HOBJECT_IS_NATIVEFUNCTION(func)) {
55696 		vs_min_size += DUK_VALSTACK_API_ENTRY_MINIMUM;  /* Duktape/C API guaranteed entries (on top of args) */
55697 	}
55698 	vs_min_size += DUK_VALSTACK_INTERNAL_EXTRA;             /* + spare */
55699 
55700 	/* XXX: We can't resize the value stack to a size smaller than the
55701 	 * current top, so the order of the resize and adjusting the stack
55702 	 * top depends on the current vs. final size of the value stack.
55703 	 * The operations could be combined to avoid this, but the proper
55704 	 * fix is to only grow the value stack on a function call, and only
55705 	 * shrink it (without throwing if the shrink fails) on function
55706 	 * return.
55707 	 */
55708 
55709 	if (vs_min_size < (duk_size_t) (thr->valstack_top  - thr->valstack)) {
55710 		DUK_DDD(DUK_DDDPRINT(("final size smaller, set top before resize")));
55711 
55712 		DUK_ASSERT(nregs >= 0);  /* can't happen when keeping current stack size */
55713 		duk_set_top(ctx, idx_args + nargs);  /* clamp anything above nargs */
55714 		duk_set_top(ctx, idx_args + nregs);  /* extend with undefined */
55715 		adjusted_top = 1;
55716 	}
55717 
55718 	(void) duk_valstack_resize_raw((duk_context *) thr,
55719 	                               vs_min_size,
55720 	                               DUK_VSRESIZE_FLAG_SHRINK |      /* flags */
55721 	                               0 /* no compact */ |
55722 	                               DUK_VSRESIZE_FLAG_THROW);
55723 
55724 	if (!adjusted_top) {
55725 		if (nregs >= 0) {
55726 			DUK_ASSERT(nregs >= nargs);
55727 			duk_set_top(ctx, idx_args + nargs);  /* clamp anything above nargs */
55728 			duk_set_top(ctx, idx_args + nregs);  /* extend with undefined */
55729 		}
55730 	}
55731 }
55732 
55733 /*
55734  *  Manipulate value stack so that exactly 'num_stack_rets' return
55735  *  values are at 'idx_retbase' in every case, assuming there are
55736  *  'rc' return values on top of stack.
55737  *
55738  *  This is a bit tricky, because the called C function operates in
55739  *  the same activation record and may have e.g. popped the stack
55740  *  empty (below idx_retbase).
55741  */
55742 
55743 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) {
55744 	duk_context *ctx = (duk_context *) thr;
55745 	duk_idx_t idx_rcbase;
55746 
55747 	DUK_ASSERT(thr != NULL);
55748 	DUK_ASSERT(idx_retbase >= 0);
55749 	DUK_ASSERT(num_stack_rets >= 0);
55750 	DUK_ASSERT(num_actual_rets >= 0);
55751 
55752 	idx_rcbase = duk_get_top(ctx) - num_actual_rets;  /* base of known return values */
55753 
55754 	DUK_DDD(DUK_DDDPRINT("adjust valstack after func call: "
55755 	                     "num_stack_rets=%ld, num_actual_rets=%ld, stack_top=%ld, idx_retbase=%ld, idx_rcbase=%ld",
55756 	                     (long) num_stack_rets, (long) num_actual_rets, (long) duk_get_top(ctx),
55757 	                     (long) idx_retbase, (long) idx_rcbase));
55758 
55759 	DUK_ASSERT(idx_rcbase >= 0);  /* caller must check */
55760 
55761 	/* Ensure space for final configuration (idx_retbase + num_stack_rets)
55762 	 * and intermediate configurations.
55763 	 */
55764 	duk_require_stack_top(ctx,
55765 	                      (idx_rcbase > idx_retbase ? idx_rcbase : idx_retbase) +
55766 	                      num_stack_rets);
55767 
55768 	/* Chop extra retvals away / extend with undefined. */
55769 	duk_set_top(ctx, idx_rcbase + num_stack_rets);
55770 
55771 	if (idx_rcbase >= idx_retbase) {
55772 		duk_idx_t count = idx_rcbase - idx_retbase;
55773 		duk_idx_t i;
55774 
55775 		DUK_DDD(DUK_DDDPRINT("elements at/after idx_retbase have enough to cover func retvals "
55776 		                     "(idx_retbase=%ld, idx_rcbase=%ld)", (long) idx_retbase, (long) idx_rcbase));
55777 
55778 		/* nuke values at idx_retbase to get the first retval (initially
55779 		 * at idx_rcbase) to idx_retbase
55780 		 */
55781 
55782 		DUK_ASSERT(count >= 0);
55783 
55784 		for (i = 0; i < count; i++) {
55785 			/* XXX: inefficient; block remove primitive */
55786 			duk_remove(ctx, idx_retbase);
55787 		}
55788 	} else {
55789 		duk_idx_t count = idx_retbase - idx_rcbase;
55790 		duk_idx_t i;
55791 
55792 		DUK_DDD(DUK_DDDPRINT("not enough elements at/after idx_retbase to cover func retvals "
55793 		                     "(idx_retbase=%ld, idx_rcbase=%ld)", (long) idx_retbase, (long) idx_rcbase));
55794 
55795 		/* insert 'undefined' values at idx_rcbase to get the
55796 		 * return values to idx_retbase
55797 		 */
55798 
55799 		DUK_ASSERT(count > 0);
55800 
55801 		for (i = 0; i < count; i++) {
55802 			/* XXX: inefficient; block insert primitive */
55803 			duk_push_undefined(ctx);
55804 			duk_insert(ctx, idx_rcbase);
55805 		}
55806 	}
55807 }
55808 
55809 /*
55810  *  Misc shared helpers.
55811  */
55812 
55813 /* Get valstack index for the func argument or throw if insane stack. */
55814 DUK_LOCAL duk_idx_t duk__get_idx_func(duk_hthread *thr, duk_idx_t num_stack_args) {
55815 	duk_size_t off_stack_top;
55816 	duk_size_t off_stack_args;
55817 	duk_size_t off_stack_all;
55818 	duk_idx_t idx_func;         /* valstack index of 'func' and retval (relative to entry valstack_bottom) */
55819 
55820 	/* Argument validation and func/args offset. */
55821 	off_stack_top = (duk_size_t) ((duk_uint8_t *) thr->valstack_top - (duk_uint8_t *) thr->valstack_bottom);
55822 	off_stack_args = (duk_size_t) ((duk_size_t) num_stack_args * sizeof(duk_tval));
55823 	off_stack_all = off_stack_args + 2 * sizeof(duk_tval);
55824 	if (DUK_UNLIKELY(off_stack_all > off_stack_top)) {
55825 		/* Since stack indices are not reliable, we can't do anything useful
55826 		 * here.  Invoke the existing setjmp catcher, or if it doesn't exist,
55827 		 * call the fatal error handler.
55828 		 */
55829 		DUK_ERROR_API(thr, DUK_STR_INVALID_CALL_ARGS);
55830 		return 0;
55831 	}
55832 	idx_func = (duk_idx_t) ((off_stack_top - off_stack_all) / sizeof(duk_tval));
55833 	return idx_func;
55834 }
55835 
55836 /*
55837  *  duk_handle_call_protected() and duk_handle_call_unprotected():
55838  *  call into a Duktape/C or an Ecmascript function from any state.
55839  *
55840  *  Input stack (thr):
55841  *
55842  *    [ func this arg1 ... argN ]
55843  *
55844  *  Output stack (thr):
55845  *
55846  *    [ retval ]         (DUK_EXEC_SUCCESS)
55847  *    [ errobj ]         (DUK_EXEC_ERROR (normal error), protected call)
55848  *
55849  *  Even when executing a protected call an error may be thrown in rare cases
55850  *  such as an insane num_stack_args argument.  If there is no catchpoint for
55851  *  such errors, the fatal error handler is called.
55852  *
55853  *  The error handling path should be error free, even for out-of-memory
55854  *  errors, to ensure safe sandboxing.  (As of Duktape 1.4.0 this is not
55855  *  yet the case, see XXX notes below.)
55856  */
55857 
55858 DUK_INTERNAL duk_int_t duk_handle_call_protected(duk_hthread *thr,
55859                                                  duk_idx_t num_stack_args,
55860                                                  duk_small_uint_t call_flags) {
55861 	duk_context *ctx;
55862 	duk_size_t entry_valstack_bottom_index;
55863 	duk_size_t entry_valstack_end;
55864 	duk_size_t entry_callstack_top;
55865 	duk_size_t entry_catchstack_top;
55866 	duk_int_t entry_call_recursion_depth;
55867 	duk_hthread *entry_curr_thread;
55868 	duk_uint_fast8_t entry_thread_state;
55869 	duk_instr_t **entry_ptr_curr_pc;
55870 	duk_jmpbuf *old_jmpbuf_ptr = NULL;
55871 	duk_jmpbuf our_jmpbuf;
55872 	duk_idx_t idx_func;  /* valstack index of 'func' and retval (relative to entry valstack_bottom) */
55873 
55874 	/* XXX: Multiple tv_func lookups are now avoided by making a local
55875 	 * copy of tv_func.  Another approach would be to compute an offset
55876 	 * for tv_func from valstack bottom and recomputing the tv_func
55877 	 * pointer quickly as valstack + offset instead of calling duk_get_tval().
55878 	 */
55879 
55880 	ctx = (duk_context *) thr;
55881 	DUK_UNREF(ctx);
55882 	DUK_ASSERT(thr != NULL);
55883 	DUK_ASSERT_CTX_VALID(ctx);
55884 	DUK_ASSERT(num_stack_args >= 0);
55885 	/* XXX: currently NULL allocations are not supported; remove if later allowed */
55886 	DUK_ASSERT(thr->valstack != NULL);
55887 	DUK_ASSERT(thr->callstack != NULL);
55888 	DUK_ASSERT(thr->catchstack != NULL);
55889 
55890 	/* Argument validation and func/args offset. */
55891 	idx_func = duk__get_idx_func(thr, num_stack_args);
55892 
55893 	/* Preliminaries, required by setjmp() handler.  Must be careful not
55894 	 * to throw an unintended error here.
55895 	 */
55896 
55897 	entry_valstack_bottom_index = (duk_size_t) (thr->valstack_bottom - thr->valstack);
55898 #if defined(DUK_USE_PREFER_SIZE)
55899 	entry_valstack_end = (duk_size_t) (thr->valstack_end - thr->valstack);
55900 #else
55901 	DUK_ASSERT((duk_size_t) (thr->valstack_end - thr->valstack) == thr->valstack_size);
55902 	entry_valstack_end = thr->valstack_size;
55903 #endif
55904 	entry_callstack_top = thr->callstack_top;
55905 	entry_catchstack_top = thr->catchstack_top;
55906 	entry_call_recursion_depth = thr->heap->call_recursion_depth;
55907 	entry_curr_thread = thr->heap->curr_thread;  /* Note: may be NULL if first call */
55908 	entry_thread_state = thr->state;
55909 	entry_ptr_curr_pc = thr->ptr_curr_pc;  /* may be NULL */
55910 
55911 	DUK_DD(DUK_DDPRINT("duk_handle_call_protected: thr=%p, num_stack_args=%ld, "
55912 	                   "call_flags=0x%08lx (ignorerec=%ld, constructor=%ld), "
55913 	                   "valstack_top=%ld, idx_func=%ld, idx_args=%ld, rec_depth=%ld/%ld, "
55914 	                   "entry_valstack_bottom_index=%ld, entry_callstack_top=%ld, entry_catchstack_top=%ld, "
55915 	                   "entry_call_recursion_depth=%ld, entry_curr_thread=%p, entry_thread_state=%ld",
55916 	                   (void *) thr,
55917 	                   (long) num_stack_args,
55918 	                   (unsigned long) call_flags,
55919 	                   (long) ((call_flags & DUK_CALL_FLAG_IGNORE_RECLIMIT) != 0 ? 1 : 0),
55920 	                   (long) ((call_flags & DUK_CALL_FLAG_CONSTRUCTOR_CALL) != 0 ? 1 : 0),
55921 	                   (long) duk_get_top(ctx),
55922 	                   (long) idx_func,
55923 	                   (long) (idx_func + 2),
55924 	                   (long) thr->heap->call_recursion_depth,
55925 	                   (long) thr->heap->call_recursion_limit,
55926 	                   (long) entry_valstack_bottom_index,
55927 	                   (long) entry_callstack_top,
55928 	                   (long) entry_catchstack_top,
55929 	                   (long) entry_call_recursion_depth,
55930 	                   (void *) entry_curr_thread,
55931 	                   (long) entry_thread_state));
55932 
55933 	old_jmpbuf_ptr = thr->heap->lj.jmpbuf_ptr;
55934 	thr->heap->lj.jmpbuf_ptr = &our_jmpbuf;
55935 
55936 #if defined(DUK_USE_CPP_EXCEPTIONS)
55937 	try {
55938 #else
55939 	DUK_ASSERT(thr->heap->lj.jmpbuf_ptr == &our_jmpbuf);
55940 	if (DUK_SETJMP(our_jmpbuf.jb) == 0) {
55941 #endif
55942 		/* Call handling and success path.  Success path exit cleans
55943 		 * up almost all state.
55944 		 */
55945 		duk__handle_call_inner(thr, num_stack_args, call_flags, idx_func);
55946 
55947 		/* Success path handles */
55948 		DUK_ASSERT(thr->heap->call_recursion_depth == entry_call_recursion_depth);
55949 		DUK_ASSERT(thr->ptr_curr_pc == entry_ptr_curr_pc);
55950 
55951 		/* Longjmp state is kept clean in success path */
55952 		DUK_ASSERT(thr->heap->lj.type == DUK_LJ_TYPE_UNKNOWN);
55953 		DUK_ASSERT(thr->heap->lj.iserror == 0);
55954 		DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&thr->heap->lj.value1));
55955 		DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&thr->heap->lj.value2));
55956 
55957 		thr->heap->lj.jmpbuf_ptr = old_jmpbuf_ptr;
55958 
55959 		return DUK_EXEC_SUCCESS;
55960 #if defined(DUK_USE_CPP_EXCEPTIONS)
55961 	} catch (duk_internal_exception &exc) {
55962 #else
55963 	} else {
55964 #endif
55965 		/* Error; error value is in heap->lj.value1. */
55966 
55967 #if defined(DUK_USE_CPP_EXCEPTIONS)
55968 		DUK_UNREF(exc);
55969 #endif
55970 
55971 		duk__handle_call_error(thr,
55972 		                       entry_valstack_bottom_index,
55973 		                       entry_valstack_end,
55974 		                       entry_catchstack_top,
55975 		                       entry_callstack_top,
55976 		                       entry_call_recursion_depth,
55977 		                       entry_curr_thread,
55978 		                       entry_thread_state,
55979 		                       entry_ptr_curr_pc,
55980 		                       idx_func,
55981 		                       old_jmpbuf_ptr);
55982 
55983 		/* Longjmp state is cleaned up by error handling */
55984 		DUK_ASSERT(thr->heap->lj.type == DUK_LJ_TYPE_UNKNOWN);
55985 		DUK_ASSERT(thr->heap->lj.iserror == 0);
55986 		DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&thr->heap->lj.value1));
55987 		DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&thr->heap->lj.value2));
55988 		return DUK_EXEC_ERROR;
55989 	}
55990 #if defined(DUK_USE_CPP_EXCEPTIONS)
55991 	catch (std::exception &exc) {
55992 		const char *what = exc.what();
55993 		if (!what) {
55994 			what = "unknown";
55995 		}
55996 		DUK_D(DUK_DPRINT("unexpected c++ std::exception (perhaps thrown by user code)"));
55997 		try {
55998 			DUK_ERROR_FMT1(thr, DUK_ERR_API_ERROR, "caught invalid c++ std::exception '%s' (perhaps thrown by user code)", what);
55999 		} catch (duk_internal_exception exc) {
56000 			DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ std::exception"));
56001 			DUK_UNREF(exc);
56002 			duk__handle_call_error(thr,
56003 			                       entry_valstack_bottom_index,
56004 			                       entry_valstack_end,
56005 			                       entry_catchstack_top,
56006 			                       entry_callstack_top,
56007 			                       entry_call_recursion_depth,
56008 			                       entry_curr_thread,
56009 			                       entry_thread_state,
56010 			                       entry_ptr_curr_pc,
56011 			                       idx_func,
56012 			                       old_jmpbuf_ptr);
56013 			return DUK_EXEC_ERROR;
56014 		}
56015 	} catch (...) {
56016 		DUK_D(DUK_DPRINT("unexpected c++ exception (perhaps thrown by user code)"));
56017 		try {
56018 			DUK_ERROR_API(thr, "caught invalid c++ exception (perhaps thrown by user code)");
56019 		} catch (duk_internal_exception exc) {
56020 			DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ exception"));
56021 			DUK_UNREF(exc);
56022 			duk__handle_call_error(thr,
56023 			                       entry_valstack_bottom_index,
56024 			                       entry_valstack_end,
56025 			                       entry_catchstack_top,
56026 			                       entry_callstack_top,
56027 			                       entry_call_recursion_depth,
56028 			                       entry_curr_thread,
56029 			                       entry_thread_state,
56030 			                       entry_ptr_curr_pc,
56031 			                       idx_func,
56032 			                       old_jmpbuf_ptr);
56033 			return DUK_EXEC_ERROR;
56034 		}
56035 	}
56036 #endif
56037 }
56038 
56039 DUK_INTERNAL void duk_handle_call_unprotected(duk_hthread *thr,
56040                                               duk_idx_t num_stack_args,
56041                                               duk_small_uint_t call_flags) {
56042 	duk_idx_t idx_func;         /* valstack index of 'func' and retval (relative to entry valstack_bottom) */
56043 
56044 	/* Argument validation and func/args offset. */
56045 	idx_func = duk__get_idx_func(thr, num_stack_args);
56046 
56047 	duk__handle_call_inner(thr, num_stack_args, call_flags, idx_func);
56048 }
56049 
56050 DUK_LOCAL void duk__handle_call_inner(duk_hthread *thr,
56051                                       duk_idx_t num_stack_args,
56052                                       duk_small_uint_t call_flags,
56053                                       duk_idx_t idx_func) {
56054 	duk_context *ctx;
56055 	duk_size_t entry_valstack_bottom_index;
56056 	duk_size_t entry_valstack_end;
56057 	duk_size_t entry_callstack_top;
56058 	duk_size_t entry_catchstack_top;
56059 	duk_int_t entry_call_recursion_depth;
56060 	duk_hthread *entry_curr_thread;
56061 	duk_uint_fast8_t entry_thread_state;
56062 	duk_instr_t **entry_ptr_curr_pc;
56063 	duk_idx_t nargs;            /* # argument registers target function wants (< 0 => "as is") */
56064 	duk_idx_t nregs;            /* # total registers target function wants on entry (< 0 => "as is") */
56065 	duk_hobject *func;          /* 'func' on stack (borrowed reference) */
56066 	duk_tval *tv_func;          /* duk_tval ptr for 'func' on stack (borrowed reference) or tv_func_copy */
56067 	duk_tval tv_func_copy;      /* to avoid relookups */
56068 	duk_activation *act;
56069 	duk_hobject *env;
56070 	duk_ret_t rc;
56071 
56072 	ctx = (duk_context *) thr;
56073 	DUK_ASSERT(thr != NULL);
56074 	DUK_ASSERT_CTX_VALID(ctx);
56075 	DUK_ASSERT(ctx != NULL);
56076 	DUK_ASSERT(num_stack_args >= 0);
56077 	/* XXX: currently NULL allocations are not supported; remove if later allowed */
56078 	DUK_ASSERT(thr->valstack != NULL);
56079 	DUK_ASSERT(thr->callstack != NULL);
56080 	DUK_ASSERT(thr->catchstack != NULL);
56081 
56082 	DUK_DD(DUK_DDPRINT("duk__handle_call_inner: num_stack_args=%ld, call_flags=0x%08lx, top=%ld",
56083 	                   (long) num_stack_args, (long) call_flags, (long) duk_get_top(ctx)));
56084 
56085 	/*
56086 	 *  Store entry state.
56087 	 */
56088 
56089 	entry_valstack_bottom_index = (duk_size_t) (thr->valstack_bottom - thr->valstack);
56090 #if defined(DUK_USE_PREFER_SIZE)
56091 	entry_valstack_end = (duk_size_t) (thr->valstack_end - thr->valstack);
56092 #else
56093 	DUK_ASSERT((duk_size_t) (thr->valstack_end - thr->valstack) == thr->valstack_size);
56094 	entry_valstack_end = thr->valstack_size;
56095 #endif
56096 	entry_callstack_top = thr->callstack_top;
56097 	entry_catchstack_top = thr->catchstack_top;
56098 	entry_call_recursion_depth = thr->heap->call_recursion_depth;
56099 	entry_curr_thread = thr->heap->curr_thread;  /* Note: may be NULL if first call */
56100 	entry_thread_state = thr->state;
56101 	entry_ptr_curr_pc = thr->ptr_curr_pc;  /* may be NULL */
56102 
56103 	/* If thr->ptr_curr_pc is set, sync curr_pc to act->pc.  Then NULL
56104 	 * thr->ptr_curr_pc so that it's not accidentally used with an incorrect
56105 	 * activation when side effects occur.
56106 	 */
56107 	duk_hthread_sync_and_null_currpc(thr);
56108 
56109 	DUK_DD(DUK_DDPRINT("duk__handle_call_inner: thr=%p, num_stack_args=%ld, "
56110 	                   "call_flags=0x%08lx (ignorerec=%ld, constructor=%ld), "
56111 	                   "valstack_top=%ld, idx_func=%ld, idx_args=%ld, rec_depth=%ld/%ld, "
56112 	                   "entry_valstack_bottom_index=%ld, entry_callstack_top=%ld, entry_catchstack_top=%ld, "
56113 	                   "entry_call_recursion_depth=%ld, entry_curr_thread=%p, entry_thread_state=%ld",
56114 	                   (void *) thr,
56115 	                   (long) num_stack_args,
56116 	                   (unsigned long) call_flags,
56117 	                   (long) ((call_flags & DUK_CALL_FLAG_IGNORE_RECLIMIT) != 0 ? 1 : 0),
56118 	                   (long) ((call_flags & DUK_CALL_FLAG_CONSTRUCTOR_CALL) != 0 ? 1 : 0),
56119 	                   (long) duk_get_top(ctx),
56120 	                   (long) idx_func,
56121 	                   (long) (idx_func + 2),
56122 	                   (long) thr->heap->call_recursion_depth,
56123 	                   (long) thr->heap->call_recursion_limit,
56124 	                   (long) entry_valstack_bottom_index,
56125 	                   (long) entry_callstack_top,
56126 	                   (long) entry_catchstack_top,
56127 	                   (long) entry_call_recursion_depth,
56128 	                   (void *) entry_curr_thread,
56129 	                   (long) entry_thread_state));
56130 
56131 
56132 	/*
56133 	 *  Thread state check and book-keeping.
56134 	 */
56135 
56136 	if (thr == thr->heap->curr_thread) {
56137 		/* same thread */
56138 		if (thr->state != DUK_HTHREAD_STATE_RUNNING) {
56139 			/* should actually never happen, but check anyway */
56140 			goto thread_state_error;
56141 		}
56142 	} else {
56143 		/* different thread */
56144 		DUK_ASSERT(thr->heap->curr_thread == NULL ||
56145 		           thr->heap->curr_thread->state == DUK_HTHREAD_STATE_RUNNING);
56146 		if (thr->state != DUK_HTHREAD_STATE_INACTIVE) {
56147 			goto thread_state_error;
56148 		}
56149 		DUK_HEAP_SWITCH_THREAD(thr->heap, thr);
56150 		thr->state = DUK_HTHREAD_STATE_RUNNING;
56151 
56152 		/* Note: multiple threads may be simultaneously in the RUNNING
56153 		 * state, but not in the same "resume chain".
56154 		 */
56155 	}
56156 	DUK_ASSERT(thr->heap->curr_thread == thr);
56157 	DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);
56158 
56159 	/*
56160 	 *  C call recursion depth check, which provides a reasonable upper
56161 	 *  bound on maximum C stack size (arbitrary C stack growth is only
56162 	 *  possible by recursive handle_call / handle_safe_call calls).
56163 	 */
56164 
56165 	/* XXX: remove DUK_CALL_FLAG_IGNORE_RECLIMIT flag: there's now the
56166 	 * reclimit bump?
56167 	 */
56168 
56169 	DUK_ASSERT(thr->heap->call_recursion_depth >= 0);
56170 	DUK_ASSERT(thr->heap->call_recursion_depth <= thr->heap->call_recursion_limit);
56171 	if (call_flags & DUK_CALL_FLAG_IGNORE_RECLIMIT) {
56172 		DUK_DD(DUK_DDPRINT("ignoring reclimit for this call (probably an errhandler call)"));
56173 	} else {
56174 		if (thr->heap->call_recursion_depth >= thr->heap->call_recursion_limit) {
56175 			/* XXX: error message is a bit misleading: we reached a recursion
56176 			 * limit which is also essentially the same as a C callstack limit
56177 			 * (except perhaps with some relaxed threading assumptions).
56178 			 */
56179 			DUK_ERROR_RANGE(thr, DUK_STR_C_CALLSTACK_LIMIT);
56180 		}
56181 		thr->heap->call_recursion_depth++;
56182 	}
56183 
56184 	/*
56185 	 *  Check the function type, handle bound function chains, and prepare
56186 	 *  parameters for the rest of the call handling.  Also figure out the
56187 	 *  effective 'this' binding, which replaces the current value at
56188 	 *  idx_func + 1.
56189 	 *
56190 	 *  If the target function is a 'bound' one, follow the chain of 'bound'
56191 	 *  functions until a non-bound function is found.  During this process,
56192 	 *  bound arguments are 'prepended' to existing ones, and the "this"
56193 	 *  binding is overridden.  See E5 Section 15.3.4.5.1.
56194 	 *
56195 	 *  Lightfunc detection happens here too.  Note that lightweight functions
56196 	 *  can be wrapped by (non-lightweight) bound functions so we must resolve
56197 	 *  the bound function chain first.
56198 	 */
56199 
56200 	func = duk__nonbound_func_lookup(ctx, idx_func, &num_stack_args, &tv_func, call_flags);
56201 	DUK_TVAL_SET_TVAL(&tv_func_copy, tv_func);
56202 	tv_func = &tv_func_copy;  /* local copy to avoid relookups */
56203 
56204 	DUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUND(func));
56205 	DUK_ASSERT(func == NULL || (DUK_HOBJECT_IS_COMPILEDFUNCTION(func) ||
56206 	                            DUK_HOBJECT_IS_NATIVEFUNCTION(func)));
56207 
56208 	duk__coerce_effective_this_binding(thr, func, idx_func + 1);
56209 	DUK_DDD(DUK_DDDPRINT("effective 'this' binding is: %!T",
56210 	                     (duk_tval *) duk_get_tval(ctx, idx_func + 1)));
56211 
56212 	/* [ ... func this arg1 ... argN ] */
56213 
56214 	/*
56215 	 *  Setup a preliminary activation and figure out nargs/nregs.
56216 	 *
56217 	 *  Don't touch valstack_bottom or valstack_top yet so that Duktape API
56218 	 *  calls work normally.
56219 	 */
56220 
56221 	duk_hthread_callstack_grow(thr);
56222 
56223 	if (thr->callstack_top > 0) {
56224 		/*
56225 		 *  Update idx_retval of current activation.
56226 		 *
56227 		 *  Although it might seem this is not necessary (bytecode executor
56228 		 *  does this for Ecmascript-to-Ecmascript calls; other calls are
56229 		 *  handled here), this turns out to be necessary for handling yield
56230 		 *  and resume.  For them, an Ecmascript-to-native call happens, and
56231 		 *  the Ecmascript call's idx_retval must be set for things to work.
56232 		 */
56233 
56234 		(thr->callstack + thr->callstack_top - 1)->idx_retval = entry_valstack_bottom_index + idx_func;
56235 	}
56236 
56237 	DUK_ASSERT(thr->callstack_top < thr->callstack_size);
56238 	act = thr->callstack + thr->callstack_top;
56239 	thr->callstack_top++;
56240 	DUK_ASSERT(thr->callstack_top <= thr->callstack_size);
56241 	DUK_ASSERT(thr->valstack_top > thr->valstack_bottom);  /* at least effective 'this' */
56242 	DUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUND(func));
56243 
56244 	act->flags = 0;
56245 
56246 	/* For now all calls except Ecma-to-Ecma calls prevent a yield. */
56247 	act->flags |= DUK_ACT_FLAG_PREVENT_YIELD;
56248 	if (call_flags & DUK_CALL_FLAG_CONSTRUCTOR_CALL) {
56249 		act->flags |= DUK_ACT_FLAG_CONSTRUCT;
56250 	}
56251 	if (call_flags & DUK_CALL_FLAG_DIRECT_EVAL) {
56252 		act->flags |= DUK_ACT_FLAG_DIRECT_EVAL;
56253 	}
56254 
56255 	/* These base values are never used, but if the compiler doesn't know
56256 	 * that DUK_ERROR() won't return, these are needed to silence warnings.
56257 	 * On the other hand, scan-build will warn about the values not being
56258 	 * used, so add a DUK_UNREF.
56259 	 */
56260 	nargs = 0; DUK_UNREF(nargs);
56261 	nregs = 0; DUK_UNREF(nregs);
56262 
56263 	if (DUK_LIKELY(func != NULL)) {
56264 		if (DUK_HOBJECT_HAS_STRICT(func)) {
56265 			act->flags |= DUK_ACT_FLAG_STRICT;
56266 		}
56267 		if (DUK_HOBJECT_IS_COMPILEDFUNCTION(func)) {
56268 			nargs = ((duk_hcompiledfunction *) func)->nargs;
56269 			nregs = ((duk_hcompiledfunction *) func)->nregs;
56270 			DUK_ASSERT(nregs >= nargs);
56271 		} else if (DUK_HOBJECT_IS_NATIVEFUNCTION(func)) {
56272 			/* Note: nargs (and nregs) may be negative for a native,
56273 			 * function, which indicates that the function wants the
56274 			 * input stack "as is" (i.e. handles "vararg" arguments).
56275 			 */
56276 			nargs = ((duk_hnativefunction *) func)->nargs;
56277 			nregs = nargs;
56278 		} else {
56279 			/* XXX: this should be an assert */
56280 			DUK_ERROR_TYPE(thr, DUK_STR_NOT_CALLABLE);
56281 		}
56282 	} else {
56283 		duk_small_uint_t lf_flags;
56284 
56285 		DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv_func));
56286 		lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv_func);
56287 		nargs = DUK_LFUNC_FLAGS_GET_NARGS(lf_flags);
56288 		if (nargs == DUK_LFUNC_NARGS_VARARGS) {
56289 			nargs = -1;  /* vararg */
56290 		}
56291 		nregs = nargs;
56292 
56293 		act->flags |= DUK_ACT_FLAG_STRICT;
56294 	}
56295 
56296 	act->func = func;  /* NULL for lightfunc */
56297 	act->var_env = NULL;
56298 	act->lex_env = NULL;
56299 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
56300 	act->prev_caller = NULL;
56301 #endif
56302 	act->curr_pc = NULL;
56303 #if defined(DUK_USE_DEBUGGER_SUPPORT)
56304 	act->prev_line = 0;
56305 #endif
56306 	act->idx_bottom = entry_valstack_bottom_index + idx_func + 2;
56307 #if 0  /* topmost activation idx_retval is considered garbage, no need to init */
56308 	act->idx_retval = 0;
56309 #endif
56310 	DUK_TVAL_SET_TVAL(&act->tv_func, tv_func);  /* borrowed, no refcount */
56311 
56312 	/* XXX: remove the preventcount and make yield walk the callstack?
56313 	 * Or perhaps just use a single flag, not a counter, faster to just
56314 	 * set and restore?
56315 	 */
56316 	if (act->flags & DUK_ACT_FLAG_PREVENT_YIELD) {
56317 		/* duk_hthread_callstack_unwind() will decrease this on unwind */
56318 		thr->callstack_preventcount++;
56319 	}
56320 
56321 	/* XXX: Is this INCREF necessary? 'func' is always a borrowed
56322 	 * reference reachable through the value stack?  If changed, stack
56323 	 * unwind code also needs to be fixed to match.
56324 	 */
56325 	DUK_HOBJECT_INCREF_ALLOWNULL(thr, func);  /* act->func */
56326 
56327 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
56328 	if (func) {
56329 		duk__update_func_caller_prop(thr, func);
56330 		act = thr->callstack + thr->callstack_top - 1;
56331 	}
56332 #endif
56333 
56334 	/* [ ... func this arg1 ... argN ] */
56335 
56336 	/*
56337 	 *  Environment record creation and 'arguments' object creation.
56338 	 *  Named function expression name binding is handled by the
56339 	 *  compiler; the compiled function's parent env will contain
56340 	 *  the (immutable) binding already.
56341 	 *
56342 	 *  This handling is now identical for C and Ecmascript functions.
56343 	 *  C functions always have the 'NEWENV' flag set, so their
56344 	 *  environment record initialization is delayed (which is good).
56345 	 *
56346 	 *  Delayed creation (on demand) is handled in duk_js_var.c.
56347 	 */
56348 
56349 	DUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUND(func));  /* bound function chain has already been resolved */
56350 
56351 	if (DUK_LIKELY(func != NULL)) {
56352 		if (DUK_LIKELY(DUK_HOBJECT_HAS_NEWENV(func))) {
56353 			if (DUK_LIKELY(!DUK_HOBJECT_HAS_CREATEARGS(func))) {
56354 				/* Use a new environment but there's no 'arguments' object;
56355 				 * delayed environment initialization.  This is the most
56356 				 * common case.
56357 				 */
56358 				DUK_ASSERT(act->lex_env == NULL);
56359 				DUK_ASSERT(act->var_env == NULL);
56360 			} else {
56361 				/* Use a new environment and there's an 'arguments' object.
56362 				 * We need to initialize it right now.
56363 				 */
56364 
56365 				/* third arg: absolute index (to entire valstack) of idx_bottom of new activation */
56366 				env = duk_create_activation_environment_record(thr, func, act->idx_bottom);
56367 				DUK_ASSERT(env != NULL);
56368 
56369 				/* [ ... func this arg1 ... argN envobj ] */
56370 
56371 				DUK_ASSERT(DUK_HOBJECT_HAS_CREATEARGS(func));
56372 				duk__handle_createargs_for_call(thr, func, env, num_stack_args);
56373 
56374 				/* [ ... func this arg1 ... argN envobj ] */
56375 
56376 				act = thr->callstack + thr->callstack_top - 1;
56377 				act->lex_env = env;
56378 				act->var_env = env;
56379 				DUK_HOBJECT_INCREF(thr, env);
56380 				DUK_HOBJECT_INCREF(thr, env);  /* XXX: incref by count (2) directly */
56381 				duk_pop(ctx);
56382 			}
56383 		} else {
56384 			/* Use existing env (e.g. for non-strict eval); cannot have
56385 			 * an own 'arguments' object (but can refer to an existing one).
56386 			 */
56387 
56388 			DUK_ASSERT(!DUK_HOBJECT_HAS_CREATEARGS(func));
56389 
56390 			duk__handle_oldenv_for_call(thr, func, act);
56391 			/* No need to re-lookup 'act' at present: no side effects. */
56392 
56393 			DUK_ASSERT(act->lex_env != NULL);
56394 			DUK_ASSERT(act->var_env != NULL);
56395 		}
56396 	} else {
56397 		/* Lightfuncs are always native functions and have "newenv". */
56398 		DUK_ASSERT(act->lex_env == NULL);
56399 		DUK_ASSERT(act->var_env == NULL);
56400 	}
56401 
56402 	/* [ ... func this arg1 ... argN ] */
56403 
56404 	/*
56405 	 *  Setup value stack: clamp to 'nargs', fill up to 'nregs'
56406 	 *
56407 	 *  Value stack may either grow or shrink, depending on the
56408 	 *  number of func registers and the number of actual arguments.
56409 	 *  If nregs >= 0, func wants args clamped to 'nargs'; else it
56410 	 *  wants all args (= 'num_stack_args').
56411 	 */
56412 
56413 	/* XXX: optimize value stack operation */
56414 	/* XXX: don't want to shrink allocation here */
56415 
56416 	duk__adjust_valstack_and_top(thr,
56417 	                             num_stack_args,
56418 	                             idx_func + 2,
56419 	                             nregs,
56420 	                             nargs,
56421 	                             func);
56422 
56423 	/*
56424 	 *  Determine call type, then finalize activation, shift to
56425 	 *  new value stack bottom, and call the target.
56426 	 */
56427 
56428 	act = thr->callstack + thr->callstack_top - 1;
56429 	if (func != NULL && DUK_HOBJECT_IS_COMPILEDFUNCTION(func)) {
56430 		/*
56431 		 *  Ecmascript call
56432 		 */
56433 
56434 		duk_tval *tv_ret;
56435 		duk_tval *tv_funret;
56436 
56437 		DUK_ASSERT(func != NULL);
56438 		DUK_ASSERT(DUK_HOBJECT_HAS_COMPILEDFUNCTION(func));
56439 		act->curr_pc = DUK_HCOMPILEDFUNCTION_GET_CODE_BASE(thr->heap, (duk_hcompiledfunction *) func);
56440 
56441 		thr->valstack_bottom = thr->valstack_bottom + idx_func + 2;
56442 		/* keep current valstack_top */
56443 		DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
56444 		DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
56445 		DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
56446 
56447 		/* [ ... func this | arg1 ... argN ] ('this' must precede new bottom) */
56448 
56449 		/*
56450 		 *  Bytecode executor call.
56451 		 *
56452 		 *  Execute bytecode, handling any recursive function calls and
56453 		 *  thread resumptions.  Returns when execution would return from
56454 		 *  the entry level activation.  When the executor returns, a
56455 		 *  single return value is left on the stack top.
56456 		 *
56457 		 *  The only possible longjmp() is an error (DUK_LJ_TYPE_THROW),
56458 		 *  other types are handled internally by the executor.
56459 		 */
56460 
56461 		/* thr->ptr_curr_pc is set by bytecode executor early on entry */
56462 		DUK_ASSERT(thr->ptr_curr_pc == NULL);
56463 		DUK_DDD(DUK_DDDPRINT("entering bytecode execution"));
56464 		duk_js_execute_bytecode(thr);
56465 		DUK_DDD(DUK_DDDPRINT("returned from bytecode execution"));
56466 
56467 		/* Unwind. */
56468 
56469 		DUK_ASSERT(thr->catchstack_top >= entry_catchstack_top);  /* may need unwind */
56470 		DUK_ASSERT(thr->callstack_top == entry_callstack_top + 1);
56471 		DUK_ASSERT(thr->callstack_top == entry_callstack_top + 1);
56472 		duk_hthread_catchstack_unwind(thr, entry_catchstack_top);
56473 		duk_hthread_catchstack_shrink_check(thr);
56474 		duk_hthread_callstack_unwind(thr, entry_callstack_top);
56475 		duk_hthread_callstack_shrink_check(thr);
56476 
56477 		thr->valstack_bottom = thr->valstack + entry_valstack_bottom_index;
56478 		/* keep current valstack_top */
56479 		DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
56480 		DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
56481 		DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
56482 		DUK_ASSERT(thr->valstack_top - thr->valstack_bottom >= idx_func + 1);
56483 
56484 		/* Return value handling. */
56485 
56486 		/* [ ... func this (crud) retval ] */
56487 
56488 		tv_ret = thr->valstack_bottom + idx_func;
56489 		tv_funret = thr->valstack_top - 1;
56490 #if defined(DUK_USE_FASTINT)
56491 		/* Explicit check for fastint downgrade. */
56492 		DUK_TVAL_CHKFAST_INPLACE(tv_funret);
56493 #endif
56494 		DUK_TVAL_SET_TVAL_UPDREF(thr, tv_ret, tv_funret);  /* side effects */
56495 	} else {
56496 		/*
56497 		 *  Native call.
56498 		 */
56499 
56500 		duk_tval *tv_ret;
56501 		duk_tval *tv_funret;
56502 
56503 		thr->valstack_bottom = thr->valstack_bottom + idx_func + 2;
56504 		/* keep current valstack_top */
56505 		DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
56506 		DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
56507 		DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
56508 		DUK_ASSERT(func == NULL || ((duk_hnativefunction *) func)->func != NULL);
56509 
56510 		/* [ ... func this | arg1 ... argN ] ('this' must precede new bottom) */
56511 
56512 		/* For native calls must be NULL so we don't sync back */
56513 		DUK_ASSERT(thr->ptr_curr_pc == NULL);
56514 
56515 		if (func) {
56516 			rc = ((duk_hnativefunction *) func)->func((duk_context *) thr);
56517 		} else {
56518 			duk_c_function funcptr = DUK_TVAL_GET_LIGHTFUNC_FUNCPTR(tv_func);
56519 			rc = funcptr((duk_context *) thr);
56520 		}
56521 
56522 		/* Automatic error throwing, retval check. */
56523 
56524 		if (rc < 0) {
56525 			duk_error_throw_from_negative_rc(thr, rc);
56526 			DUK_UNREACHABLE();
56527 		} else if (rc > 1) {
56528 			DUK_ERROR_API(thr, "c function returned invalid rc");
56529 		}
56530 		DUK_ASSERT(rc == 0 || rc == 1);
56531 
56532 		/* Unwind. */
56533 
56534 		DUK_ASSERT(thr->catchstack_top == entry_catchstack_top);  /* no need to unwind */
56535 		DUK_ASSERT(thr->callstack_top == entry_callstack_top + 1);
56536 		duk_hthread_callstack_unwind(thr, entry_callstack_top);
56537 		duk_hthread_callstack_shrink_check(thr);
56538 
56539 		thr->valstack_bottom = thr->valstack + entry_valstack_bottom_index;
56540 		/* keep current valstack_top */
56541 		DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
56542 		DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
56543 		DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
56544 		DUK_ASSERT(thr->valstack_top - thr->valstack_bottom >= idx_func + 1);
56545 
56546 		/* Return value handling. */
56547 
56548 		/* XXX: should this happen in the callee's activation or after unwinding? */
56549 		tv_ret = thr->valstack_bottom + idx_func;
56550 		if (rc == 0) {
56551 			DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv_ret);  /* side effects */
56552 		} else {
56553 			/* [ ... func this (crud) retval ] */
56554 			tv_funret = thr->valstack_top - 1;
56555 #if defined(DUK_USE_FASTINT)
56556 			/* Explicit check for fastint downgrade. */
56557 			DUK_TVAL_CHKFAST_INPLACE(tv_funret);
56558 #endif
56559 			DUK_TVAL_SET_TVAL_UPDREF(thr, tv_ret, tv_funret);  /* side effects */
56560 		}
56561 	}
56562 
56563 	duk_set_top(ctx, idx_func + 1);  /* XXX: unnecessary, handle in adjust */
56564 
56565 	/* [ ... retval ] */
56566 
56567 	/* Ensure there is internal valstack spare before we exit; this may
56568 	 * throw an alloc error.  The same guaranteed size must be available
56569 	 * as before the call.  This is not optimal now: we store the valstack
56570 	 * allocated size during entry; this value may be higher than the
56571 	 * minimal guarantee for an application.
56572 	 */
56573 
56574 	/* XXX: we should never shrink here; when we error out later, we'd
56575 	 * need to potentially grow the value stack in error unwind which could
56576 	 * cause another error.
56577 	 */
56578 
56579 	(void) duk_valstack_resize_raw((duk_context *) thr,
56580 	                               entry_valstack_end,                    /* same as during entry */
56581 	                               DUK_VSRESIZE_FLAG_SHRINK |             /* flags */
56582 	                               DUK_VSRESIZE_FLAG_COMPACT |
56583 	                               DUK_VSRESIZE_FLAG_THROW);
56584 
56585 	/* Restore entry thread executor curr_pc stack frame pointer. */
56586 	thr->ptr_curr_pc = entry_ptr_curr_pc;
56587 
56588 	DUK_HEAP_SWITCH_THREAD(thr->heap, entry_curr_thread);  /* may be NULL */
56589 	thr->state = (duk_uint8_t) entry_thread_state;
56590 
56591 	DUK_ASSERT((thr->state == DUK_HTHREAD_STATE_INACTIVE && thr->heap->curr_thread == NULL) ||  /* first call */
56592 	           (thr->state == DUK_HTHREAD_STATE_INACTIVE && thr->heap->curr_thread != NULL) ||  /* other call */
56593 	           (thr->state == DUK_HTHREAD_STATE_RUNNING && thr->heap->curr_thread == thr));     /* current thread */
56594 
56595 	thr->heap->call_recursion_depth = entry_call_recursion_depth;
56596 
56597 	/* If the debugger is active we need to force an interrupt so that
56598 	 * debugger breakpoints are rechecked.  This is important for function
56599 	 * calls caused by side effects (e.g. when doing a DUK_OP_GETPROP), see
56600 	 * GH-303.  Only needed for success path, error path always causes a
56601 	 * breakpoint recheck in the executor.  It would be enough to set this
56602 	 * only when returning to an Ecmascript activation, but setting the flag
56603 	 * on every return should have no ill effect.
56604 	 */
56605 #if defined(DUK_USE_DEBUGGER_SUPPORT)
56606 	if (DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap)) {
56607 		DUK_DD(DUK_DDPRINT("returning with debugger enabled, force interrupt"));
56608 		DUK_ASSERT(thr->interrupt_counter <= thr->interrupt_init);
56609 		thr->interrupt_init -= thr->interrupt_counter;
56610 		thr->interrupt_counter = 0;
56611 		thr->heap->dbg_force_restart = 1;
56612 	}
56613 #endif
56614 
56615 #if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
56616 	duk__interrupt_fixup(thr, entry_curr_thread);
56617 #endif
56618 
56619 	return;
56620 
56621  thread_state_error:
56622 	DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "invalid thread state for call (%ld)", (long) thr->state);
56623 	DUK_UNREACHABLE();
56624 	return;  /* never executed */
56625 }
56626 
56627 DUK_LOCAL void duk__handle_call_error(duk_hthread *thr,
56628                                       duk_size_t entry_valstack_bottom_index,
56629                                       duk_size_t entry_valstack_end,
56630                                       duk_size_t entry_catchstack_top,
56631                                       duk_size_t entry_callstack_top,
56632                                       duk_int_t entry_call_recursion_depth,
56633                                       duk_hthread *entry_curr_thread,
56634                                       duk_uint_fast8_t entry_thread_state,
56635                                       duk_instr_t **entry_ptr_curr_pc,
56636                                       duk_idx_t idx_func,
56637                                       duk_jmpbuf *old_jmpbuf_ptr) {
56638 	duk_context *ctx;
56639 	duk_tval *tv_ret;
56640 
56641 	ctx = (duk_context *) thr;
56642 
56643 	DUK_DDD(DUK_DDDPRINT("error caught during duk__handle_call_inner(): %!T",
56644 	                     (duk_tval *) &thr->heap->lj.value1));
56645 
56646 	/* Other longjmp types are handled by executor before propagating
56647 	 * the error here.
56648 	 */
56649 	DUK_ASSERT(thr->heap->lj.type == DUK_LJ_TYPE_THROW);
56650 	DUK_ASSERT(thr->callstack_top >= entry_callstack_top);
56651 	DUK_ASSERT(thr->catchstack_top >= entry_catchstack_top);
56652 
56653 	/* We don't need to sync back thr->ptr_curr_pc here because
56654 	 * the bytecode executor always has a setjmp catchpoint which
56655 	 * does that before errors propagate to here.
56656 	 */
56657 	DUK_ASSERT(thr->ptr_curr_pc == NULL);
56658 
56659 	/* Restore the previous setjmp catcher so that any error in
56660 	 * error handling will propagate outwards rather than re-enter
56661 	 * the same handler.  However, the error handling path must be
56662 	 * designed to be error free so that sandboxing guarantees are
56663 	 * reliable, see e.g. https://github.com/svaarala/duktape/issues/476.
56664 	 */
56665 	thr->heap->lj.jmpbuf_ptr = old_jmpbuf_ptr;
56666 
56667 	/* XXX: callstack unwind may now throw an error when closing
56668 	 * scopes; this is a sandboxing issue, described in:
56669 	 * https://github.com/svaarala/duktape/issues/476
56670 	 */
56671 	duk_hthread_catchstack_unwind(thr, entry_catchstack_top);
56672 	duk_hthread_catchstack_shrink_check(thr);
56673 	duk_hthread_callstack_unwind(thr, entry_callstack_top);
56674 	duk_hthread_callstack_shrink_check(thr);
56675 
56676 	thr->valstack_bottom = thr->valstack + entry_valstack_bottom_index;
56677 	tv_ret = thr->valstack_bottom + idx_func;  /* XXX: byte offset? */
56678 	DUK_TVAL_SET_TVAL_UPDREF(thr, tv_ret, &thr->heap->lj.value1);  /* side effects */
56679 #if defined(DUK_USE_FASTINT)
56680 	/* Explicit check for fastint downgrade. */
56681 	DUK_TVAL_CHKFAST_INPLACE(tv_ret);
56682 #endif
56683 	duk_set_top(ctx, idx_func + 1);  /* XXX: could be eliminated with valstack adjust */
56684 
56685 	/* [ ... errobj ] */
56686 
56687 	/* Ensure there is internal valstack spare before we exit; this may
56688 	 * throw an alloc error.  The same guaranteed size must be available
56689 	 * as before the call.  This is not optimal now: we store the valstack
56690 	 * allocated size during entry; this value may be higher than the
56691 	 * minimal guarantee for an application.
56692 	 */
56693 
56694 	/* XXX: this needs to be reworked so that we never shrink the value
56695 	 * stack on function entry so that we never need to grow it here.
56696 	 * Needing to grow here is a sandboxing issue because we need to
56697 	 * allocate which may cause an error in the error handling path
56698 	 * and thus propagate an error out of a protected call.
56699 	 */
56700 
56701 	(void) duk_valstack_resize_raw((duk_context *) thr,
56702 	                               entry_valstack_end,                    /* same as during entry */
56703 	                               DUK_VSRESIZE_FLAG_SHRINK |             /* flags */
56704 	                               DUK_VSRESIZE_FLAG_COMPACT |
56705 	                               DUK_VSRESIZE_FLAG_THROW);
56706 
56707 
56708 	/* These are just convenience "wiping" of state.  Side effects should
56709 	 * not be an issue here: thr->heap and thr->heap->lj have a stable
56710 	 * pointer.  Finalizer runs etc capture even out-of-memory errors so
56711 	 * nothing should throw here.
56712 	 */
56713 	thr->heap->lj.type = DUK_LJ_TYPE_UNKNOWN;
56714 	thr->heap->lj.iserror = 0;
56715 	DUK_TVAL_SET_UNDEFINED_UPDREF(thr, &thr->heap->lj.value1);  /* side effects */
56716 	DUK_TVAL_SET_UNDEFINED_UPDREF(thr, &thr->heap->lj.value2);  /* side effects */
56717 
56718 	/* Restore entry thread executor curr_pc stack frame pointer. */
56719 	thr->ptr_curr_pc = entry_ptr_curr_pc;
56720 
56721 	DUK_HEAP_SWITCH_THREAD(thr->heap, entry_curr_thread);  /* may be NULL */
56722 	thr->state = (duk_uint8_t) entry_thread_state;
56723 
56724 	DUK_ASSERT((thr->state == DUK_HTHREAD_STATE_INACTIVE && thr->heap->curr_thread == NULL) ||  /* first call */
56725 	           (thr->state == DUK_HTHREAD_STATE_INACTIVE && thr->heap->curr_thread != NULL) ||  /* other call */
56726 	           (thr->state == DUK_HTHREAD_STATE_RUNNING && thr->heap->curr_thread == thr));     /* current thread */
56727 
56728 	thr->heap->call_recursion_depth = entry_call_recursion_depth;
56729 
56730 	/* If the debugger is active we need to force an interrupt so that
56731 	 * debugger breakpoints are rechecked.  This is important for function
56732 	 * calls caused by side effects (e.g. when doing a DUK_OP_GETPROP), see
56733 	 * GH-303.  Only needed for success path, error path always causes a
56734 	 * breakpoint recheck in the executor.  It would be enough to set this
56735 	 * only when returning to an Ecmascript activation, but setting the flag
56736 	 * on every return should have no ill effect.
56737 	 */
56738 #if defined(DUK_USE_DEBUGGER_SUPPORT)
56739 	if (DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap)) {
56740 		DUK_DD(DUK_DDPRINT("returning with debugger enabled, force interrupt"));
56741 		DUK_ASSERT(thr->interrupt_counter <= thr->interrupt_init);
56742 		thr->interrupt_init -= thr->interrupt_counter;
56743 		thr->interrupt_counter = 0;
56744 		thr->heap->dbg_force_restart = 1;
56745 	}
56746 #endif
56747 
56748 #if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
56749 	duk__interrupt_fixup(thr, entry_curr_thread);
56750 #endif
56751 }
56752 
56753 /*
56754  *  duk_handle_safe_call(): make a "C protected call" within the
56755  *  current activation.
56756  *
56757  *  The allowed thread states for making a call are the same as for
56758  *  duk_handle_call_xxx().
56759  *
56760  *  Error handling is similar to duk_handle_call_xxx(); errors may be thrown
56761  *  (and result in a fatal error) for insane arguments.
56762  */
56763 
56764 /* XXX: bump preventcount by one for the duration of this call? */
56765 
56766 DUK_INTERNAL duk_int_t duk_handle_safe_call(duk_hthread *thr,
56767                                             duk_safe_call_function func,
56768                                             duk_idx_t num_stack_args,
56769                                             duk_idx_t num_stack_rets) {
56770 	duk_context *ctx = (duk_context *) thr;
56771 	duk_size_t entry_valstack_bottom_index;
56772 	duk_size_t entry_callstack_top;
56773 	duk_size_t entry_catchstack_top;
56774 	duk_int_t entry_call_recursion_depth;
56775 	duk_hthread *entry_curr_thread;
56776 	duk_uint_fast8_t entry_thread_state;
56777 	duk_instr_t **entry_ptr_curr_pc;
56778 	duk_jmpbuf *old_jmpbuf_ptr = NULL;
56779 	duk_jmpbuf our_jmpbuf;
56780 	duk_idx_t idx_retbase;
56781 	duk_int_t retval;
56782 
56783 	DUK_ASSERT(thr != NULL);
56784 	DUK_ASSERT(ctx != NULL);
56785 
56786 	/* Note: careful with indices like '-x'; if 'x' is zero, it refers to bottom */
56787 	entry_valstack_bottom_index = (duk_size_t) (thr->valstack_bottom - thr->valstack);
56788 	entry_callstack_top = thr->callstack_top;
56789 	entry_catchstack_top = thr->catchstack_top;
56790 	entry_call_recursion_depth = thr->heap->call_recursion_depth;
56791 	entry_curr_thread = thr->heap->curr_thread;  /* Note: may be NULL if first call */
56792 	entry_thread_state = thr->state;
56793 	entry_ptr_curr_pc = thr->ptr_curr_pc;  /* may be NULL */
56794 	idx_retbase = duk_get_top(ctx) - num_stack_args;  /* Note: not a valid stack index if num_stack_args == 0 */
56795 
56796 	/* Note: cannot portably debug print a function pointer, hence 'func' not printed! */
56797 	DUK_DD(DUK_DDPRINT("duk_handle_safe_call: thr=%p, num_stack_args=%ld, num_stack_rets=%ld, "
56798 	                   "valstack_top=%ld, idx_retbase=%ld, rec_depth=%ld/%ld, "
56799 	                   "entry_valstack_bottom_index=%ld, entry_callstack_top=%ld, entry_catchstack_top=%ld, "
56800 	                   "entry_call_recursion_depth=%ld, entry_curr_thread=%p, entry_thread_state=%ld",
56801 	                   (void *) thr,
56802 	                   (long) num_stack_args,
56803 	                   (long) num_stack_rets,
56804 	                   (long) duk_get_top(ctx),
56805 	                   (long) idx_retbase,
56806 	                   (long) thr->heap->call_recursion_depth,
56807 	                   (long) thr->heap->call_recursion_limit,
56808 	                   (long) entry_valstack_bottom_index,
56809 	                   (long) entry_callstack_top,
56810 	                   (long) entry_catchstack_top,
56811 	                   (long) entry_call_recursion_depth,
56812 	                   (void *) entry_curr_thread,
56813 	                   (long) entry_thread_state));
56814 
56815 	if (idx_retbase < 0) {
56816 		/* Since stack indices are not reliable, we can't do anything useful
56817 		 * here.  Invoke the existing setjmp catcher, or if it doesn't exist,
56818 		 * call the fatal error handler.
56819 		 */
56820 
56821 		DUK_ERROR_API(thr, DUK_STR_INVALID_CALL_ARGS);
56822 	}
56823 
56824 	/* setjmp catchpoint setup */
56825 
56826 	old_jmpbuf_ptr = thr->heap->lj.jmpbuf_ptr;
56827 	thr->heap->lj.jmpbuf_ptr = &our_jmpbuf;
56828 
56829 #if defined(DUK_USE_CPP_EXCEPTIONS)
56830 	try {
56831 #else
56832 	DUK_ASSERT(thr->heap->lj.jmpbuf_ptr == &our_jmpbuf);
56833 	if (DUK_SETJMP(our_jmpbuf.jb) == 0) {
56834 		/* Success path. */
56835 #endif
56836 		DUK_DDD(DUK_DDDPRINT("safe_call setjmp catchpoint setup complete"));
56837 
56838 		duk__handle_safe_call_inner(thr,
56839 		                            func,
56840 		                            idx_retbase,
56841 		                            num_stack_rets,
56842 		                            entry_valstack_bottom_index,
56843 		                            entry_callstack_top,
56844 		                            entry_catchstack_top);
56845 
56846 		/* Longjmp state is kept clean in success path */
56847 		DUK_ASSERT(thr->heap->lj.type == DUK_LJ_TYPE_UNKNOWN);
56848 		DUK_ASSERT(thr->heap->lj.iserror == 0);
56849 		DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&thr->heap->lj.value1));
56850 		DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&thr->heap->lj.value2));
56851 
56852 		/* Note: either pointer may be NULL (at entry), so don't assert */
56853 		thr->heap->lj.jmpbuf_ptr = old_jmpbuf_ptr;
56854 
56855 		retval = DUK_EXEC_SUCCESS;
56856 #if defined(DUK_USE_CPP_EXCEPTIONS)
56857 	} catch (duk_internal_exception &exc) {
56858 		DUK_UNREF(exc);
56859 #else
56860 	} else {
56861 		/* Error path. */
56862 #endif
56863 		duk__handle_safe_call_error(thr,
56864 		                            idx_retbase,
56865 		                            num_stack_rets,
56866 		                            entry_valstack_bottom_index,
56867 		                            entry_callstack_top,
56868 		                            entry_catchstack_top,
56869 		                            old_jmpbuf_ptr);
56870 
56871 		/* Longjmp state is cleaned up by error handling */
56872 		DUK_ASSERT(thr->heap->lj.type == DUK_LJ_TYPE_UNKNOWN);
56873 		DUK_ASSERT(thr->heap->lj.iserror == 0);
56874 		DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&thr->heap->lj.value1));
56875 		DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&thr->heap->lj.value2));
56876 
56877 		retval = DUK_EXEC_ERROR;
56878 	}
56879 #if defined(DUK_USE_CPP_EXCEPTIONS)
56880 	catch (std::exception &exc) {
56881 		const char *what = exc.what();
56882 		if (!what) {
56883 			what = "unknown";
56884 		}
56885 		DUK_D(DUK_DPRINT("unexpected c++ std::exception (perhaps thrown by user code)"));
56886 		try {
56887 			DUK_ERROR_FMT1(thr, DUK_ERR_API_ERROR, "caught invalid c++ std::exception '%s' (perhaps thrown by user code)", what);
56888 		} catch (duk_internal_exception exc) {
56889 			DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ std::exception"));
56890 			DUK_UNREF(exc);
56891 			duk__handle_safe_call_error(thr,
56892 			                            idx_retbase,
56893 			                            num_stack_rets,
56894 			                            entry_valstack_bottom_index,
56895 			                            entry_callstack_top,
56896 			                            entry_catchstack_top,
56897 			                            old_jmpbuf_ptr);
56898 			retval = DUK_EXEC_ERROR;
56899 		}
56900 	} catch (...) {
56901 		DUK_D(DUK_DPRINT("unexpected c++ exception (perhaps thrown by user code)"));
56902 		try {
56903 			DUK_ERROR_API(thr, "caught invalid c++ exception (perhaps thrown by user code)");
56904 		} catch (duk_internal_exception exc) {
56905 			DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ exception"));
56906 			DUK_UNREF(exc);
56907 			duk__handle_safe_call_error(thr,
56908 			                            idx_retbase,
56909 			                            num_stack_rets,
56910 			                            entry_valstack_bottom_index,
56911 			                            entry_callstack_top,
56912 			                            entry_catchstack_top,
56913 			                            old_jmpbuf_ptr);
56914 			retval = DUK_EXEC_ERROR;
56915 		}
56916 	}
56917 #endif
56918 
56919 	DUK_ASSERT(thr->heap->lj.jmpbuf_ptr == old_jmpbuf_ptr);  /* success/error path both do this */
56920 
56921 	duk__handle_safe_call_shared(thr,
56922 	                             idx_retbase,
56923 	                             num_stack_rets,
56924 	                             entry_call_recursion_depth,
56925 	                             entry_curr_thread,
56926 	                             entry_thread_state,
56927 	                             entry_ptr_curr_pc);
56928 
56929 	return retval;
56930 }
56931 
56932 DUK_LOCAL void duk__handle_safe_call_inner(duk_hthread *thr,
56933                                            duk_safe_call_function func,
56934                                            duk_idx_t idx_retbase,
56935                                            duk_idx_t num_stack_rets,
56936                                            duk_size_t entry_valstack_bottom_index,
56937                                            duk_size_t entry_callstack_top,
56938                                            duk_size_t entry_catchstack_top) {
56939 	duk_context *ctx;
56940 	duk_ret_t rc;
56941 
56942 	DUK_ASSERT(thr != NULL);
56943 	ctx = (duk_context *) thr;
56944 	DUK_ASSERT_CTX_VALID(ctx);
56945 	DUK_UNREF(entry_valstack_bottom_index);
56946 	DUK_UNREF(entry_callstack_top);
56947 	DUK_UNREF(entry_catchstack_top);
56948 
56949 	/*
56950 	 *  Thread state check and book-keeping.
56951 	 */
56952 
56953 	if (thr == thr->heap->curr_thread) {
56954 		/* same thread */
56955 		if (thr->state != DUK_HTHREAD_STATE_RUNNING) {
56956 			/* should actually never happen, but check anyway */
56957 			goto thread_state_error;
56958 		}
56959 	} else {
56960 		/* different thread */
56961 		DUK_ASSERT(thr->heap->curr_thread == NULL ||
56962 		           thr->heap->curr_thread->state == DUK_HTHREAD_STATE_RUNNING);
56963 		if (thr->state != DUK_HTHREAD_STATE_INACTIVE) {
56964 			goto thread_state_error;
56965 		}
56966 		DUK_HEAP_SWITCH_THREAD(thr->heap, thr);
56967 		thr->state = DUK_HTHREAD_STATE_RUNNING;
56968 
56969 		/* Note: multiple threads may be simultaneously in the RUNNING
56970 		 * state, but not in the same "resume chain".
56971 		 */
56972 	}
56973 
56974 	DUK_ASSERT(thr->heap->curr_thread == thr);
56975 	DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);
56976 
56977 	/*
56978 	 *  Recursion limit check.
56979 	 *
56980 	 *  Note: there is no need for an "ignore recursion limit" flag
56981 	 *  for duk_handle_safe_call now.
56982 	 */
56983 
56984 	DUK_ASSERT(thr->heap->call_recursion_depth >= 0);
56985 	DUK_ASSERT(thr->heap->call_recursion_depth <= thr->heap->call_recursion_limit);
56986 	if (thr->heap->call_recursion_depth >= thr->heap->call_recursion_limit) {
56987 		/* XXX: error message is a bit misleading: we reached a recursion
56988 		 * limit which is also essentially the same as a C callstack limit
56989 		 * (except perhaps with some relaxed threading assumptions).
56990 		 */
56991 		DUK_ERROR_RANGE(thr, DUK_STR_C_CALLSTACK_LIMIT);
56992 	}
56993 	thr->heap->call_recursion_depth++;
56994 
56995 	/*
56996 	 *  Valstack spare check
56997 	 */
56998 
56999 	duk_require_stack(ctx, 0);  /* internal spare */
57000 
57001 	/*
57002 	 *  Make the C call
57003 	 */
57004 
57005 	rc = func(ctx);
57006 
57007 	DUK_DDD(DUK_DDDPRINT("safe_call, func rc=%ld", (long) rc));
57008 
57009 	/*
57010 	 *  Valstack manipulation for results.
57011 	 */
57012 
57013 	/* we're running inside the caller's activation, so no change in call/catch stack or valstack bottom */
57014 	DUK_ASSERT(thr->callstack_top == entry_callstack_top);
57015 	DUK_ASSERT(thr->catchstack_top == entry_catchstack_top);
57016 	DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
57017 	DUK_ASSERT((duk_size_t) (thr->valstack_bottom - thr->valstack) == entry_valstack_bottom_index);
57018 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
57019 	DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
57020 
57021 	if (rc < 0) {
57022 		duk_error_throw_from_negative_rc(thr, rc);
57023 	}
57024 	DUK_ASSERT(rc >= 0);
57025 
57026 	if (duk_get_top(ctx) < rc) {
57027 		DUK_ERROR_API(thr, "not enough stack values for safe_call rc");
57028 	}
57029 
57030 	DUK_ASSERT(thr->catchstack_top == entry_catchstack_top);  /* no need to unwind */
57031 	DUK_ASSERT(thr->callstack_top == entry_callstack_top);
57032 
57033 	duk__safe_call_adjust_valstack(thr, idx_retbase, num_stack_rets, rc);
57034 	return;
57035 
57036  thread_state_error:
57037 	DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "invalid thread state for safe_call (%ld)", (long) thr->state);
57038 	DUK_UNREACHABLE();
57039 }
57040 
57041 DUK_LOCAL void duk__handle_safe_call_error(duk_hthread *thr,
57042                                            duk_idx_t idx_retbase,
57043                                            duk_idx_t num_stack_rets,
57044                                            duk_size_t entry_valstack_bottom_index,
57045                                            duk_size_t entry_callstack_top,
57046                                            duk_size_t entry_catchstack_top,
57047                                            duk_jmpbuf *old_jmpbuf_ptr) {
57048 	duk_context *ctx;
57049 
57050 	DUK_ASSERT(thr != NULL);
57051 	ctx = (duk_context *) thr;
57052 	DUK_ASSERT_CTX_VALID(ctx);
57053 
57054 	/*
57055 	 *  Error during call.  The error value is at heap->lj.value1.
57056 	 *
57057 	 *  The very first thing we do is restore the previous setjmp catcher.
57058 	 *  This means that any error in error handling will propagate outwards
57059 	 *  instead of causing a setjmp() re-entry above.
57060 	 */
57061 
57062 	DUK_DDD(DUK_DDDPRINT("error caught during protected duk_handle_safe_call()"));
57063 
57064 	/* Other longjmp types are handled by executor before propagating
57065 	 * the error here.
57066 	 */
57067 	DUK_ASSERT(thr->heap->lj.type == DUK_LJ_TYPE_THROW);
57068 	DUK_ASSERT(thr->callstack_top >= entry_callstack_top);
57069 	DUK_ASSERT(thr->catchstack_top >= entry_catchstack_top);
57070 
57071 	/* Note: either pointer may be NULL (at entry), so don't assert. */
57072 	thr->heap->lj.jmpbuf_ptr = old_jmpbuf_ptr;
57073 
57074 	DUK_ASSERT(thr->catchstack_top >= entry_catchstack_top);
57075 	DUK_ASSERT(thr->callstack_top >= entry_callstack_top);
57076 	duk_hthread_catchstack_unwind(thr, entry_catchstack_top);
57077 	duk_hthread_catchstack_shrink_check(thr);
57078 	duk_hthread_callstack_unwind(thr, entry_callstack_top);
57079 	duk_hthread_callstack_shrink_check(thr);
57080 	thr->valstack_bottom = thr->valstack + entry_valstack_bottom_index;
57081 
57082 	/* [ ... | (crud) ] */
57083 
57084 	/* XXX: space in valstack?  see discussion in duk_handle_call_xxx(). */
57085 	duk_push_tval(ctx, &thr->heap->lj.value1);
57086 
57087 	/* [ ... | (crud) errobj ] */
57088 
57089 	DUK_ASSERT(duk_get_top(ctx) >= 1);  /* at least errobj must be on stack */
57090 
57091 	/* check that the valstack has space for the final amount and any
57092 	 * intermediate space needed; this is unoptimal but should be safe
57093 	 */
57094 	duk_require_stack_top(ctx, idx_retbase + num_stack_rets);  /* final configuration */
57095 	duk_require_stack(ctx, num_stack_rets);
57096 
57097 	duk__safe_call_adjust_valstack(thr, idx_retbase, num_stack_rets, 1);  /* 1 = num actual 'return values' */
57098 
57099 	/* [ ... | ] or [ ... | errobj (M * undefined)] where M = num_stack_rets - 1 */
57100 
57101 	/* These are just convenience "wiping" of state.  Side effects should
57102 	 * not be an issue here: thr->heap and thr->heap->lj have a stable
57103 	 * pointer.  Finalizer runs etc capture even out-of-memory errors so
57104 	 * nothing should throw here.
57105 	 */
57106 	thr->heap->lj.type = DUK_LJ_TYPE_UNKNOWN;
57107 	thr->heap->lj.iserror = 0;
57108 	DUK_TVAL_SET_UNDEFINED_UPDREF(thr, &thr->heap->lj.value1);  /* side effects */
57109 	DUK_TVAL_SET_UNDEFINED_UPDREF(thr, &thr->heap->lj.value2);  /* side effects */
57110 }
57111 
57112 DUK_LOCAL void duk__handle_safe_call_shared(duk_hthread *thr,
57113                                             duk_idx_t idx_retbase,
57114                                             duk_idx_t num_stack_rets,
57115                                             duk_int_t entry_call_recursion_depth,
57116                                             duk_hthread *entry_curr_thread,
57117                                             duk_uint_fast8_t entry_thread_state,
57118                                             duk_instr_t **entry_ptr_curr_pc) {
57119 	duk_context *ctx;
57120 
57121 	DUK_ASSERT(thr != NULL);
57122 	ctx = (duk_context *) thr;
57123 	DUK_ASSERT_CTX_VALID(ctx);
57124 	DUK_UNREF(ctx);
57125 	DUK_UNREF(idx_retbase);
57126 	DUK_UNREF(num_stack_rets);
57127 
57128 	/* Restore entry thread executor curr_pc stack frame pointer. */
57129 	thr->ptr_curr_pc = entry_ptr_curr_pc;
57130 
57131 	/* XXX: because we unwind stacks above, thr->heap->curr_thread is at
57132 	 * risk of pointing to an already freed thread.  This was indeed the
57133 	 * case in test-bug-multithread-valgrind.c, until duk_handle_call()
57134 	 * was fixed to restore thr->heap->curr_thread before rethrowing an
57135 	 * uncaught error.
57136 	 */
57137 	DUK_HEAP_SWITCH_THREAD(thr->heap, entry_curr_thread);  /* may be NULL */
57138 	thr->state = (duk_uint8_t) entry_thread_state;
57139 
57140 	DUK_ASSERT((thr->state == DUK_HTHREAD_STATE_INACTIVE && thr->heap->curr_thread == NULL) ||  /* first call */
57141 	           (thr->state == DUK_HTHREAD_STATE_INACTIVE && thr->heap->curr_thread != NULL) ||  /* other call */
57142 	           (thr->state == DUK_HTHREAD_STATE_RUNNING && thr->heap->curr_thread == thr));     /* current thread */
57143 
57144 	thr->heap->call_recursion_depth = entry_call_recursion_depth;
57145 
57146 	/* stack discipline consistency check */
57147 	DUK_ASSERT(duk_get_top(ctx) == idx_retbase + num_stack_rets);
57148 
57149 	/* A debugger forced interrupt check is not needed here, as
57150 	 * problematic safe calls are not caused by side effects.
57151 	 */
57152 
57153 #if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
57154 	duk__interrupt_fixup(thr, entry_curr_thread);
57155 #endif
57156 }
57157 
57158 /*
57159  *  Helper for handling an Ecmascript-to-Ecmascript call or an Ecmascript
57160  *  function (initial) Duktape.Thread.resume().
57161  *
57162  *  Compared to normal calls handled by duk_handle_call(), there are a
57163  *  bunch of differences:
57164  *
57165  *    - the call is never protected
57166  *    - there is no C recursion depth increase (hence an "ignore recursion
57167  *      limit" flag is not applicable)
57168  *    - instead of making the call, this helper just performs the thread
57169  *      setup and returns; the bytecode executor then restarts execution
57170  *      internally
57171  *    - ecmascript functions are never 'vararg' functions (they access
57172  *      varargs through the 'arguments' object)
57173  *
57174  *  The callstack of the target contains an earlier Ecmascript call in case
57175  *  of an Ecmascript-to-Ecmascript call (whose idx_retval is updated), or
57176  *  is empty in case of an initial Duktape.Thread.resume().
57177  *
57178  *  The first thing to do here is to figure out whether an ecma-to-ecma
57179  *  call is actually possible.  It's not always the case if the target is
57180  *  a bound function; the final function may be native.  In that case,
57181  *  return an error so caller can fall back to a normal call path.
57182  */
57183 
57184 DUK_INTERNAL duk_bool_t duk_handle_ecma_call_setup(duk_hthread *thr,
57185                                                    duk_idx_t num_stack_args,
57186                                                    duk_small_uint_t call_flags) {
57187 	duk_context *ctx = (duk_context *) thr;
57188 	duk_size_t entry_valstack_bottom_index;
57189 	duk_idx_t idx_func;     /* valstack index of 'func' and retval (relative to entry valstack_bottom) */
57190 	duk_idx_t idx_args;     /* valstack index of start of args (arg1) (relative to entry valstack_bottom) */
57191 	duk_idx_t nargs;        /* # argument registers target function wants (< 0 => never for ecma calls) */
57192 	duk_idx_t nregs;        /* # total registers target function wants on entry (< 0 => never for ecma calls) */
57193 	duk_hobject *func;      /* 'func' on stack (borrowed reference) */
57194 	duk_tval *tv_func;      /* duk_tval ptr for 'func' on stack (borrowed reference) */
57195 	duk_activation *act;
57196 	duk_hobject *env;
57197 	duk_bool_t use_tailcall;
57198 	duk_instr_t **entry_ptr_curr_pc;
57199 
57200 	DUK_ASSERT(thr != NULL);
57201 	DUK_ASSERT(ctx != NULL);
57202 	DUK_ASSERT(!((call_flags & DUK_CALL_FLAG_IS_RESUME) != 0 && (call_flags & DUK_CALL_FLAG_IS_TAILCALL) != 0));
57203 
57204 	/* XXX: assume these? */
57205 	DUK_ASSERT(thr->valstack != NULL);
57206 	DUK_ASSERT(thr->callstack != NULL);
57207 	DUK_ASSERT(thr->catchstack != NULL);
57208 
57209 	/* no need to handle thread state book-keeping here */
57210 	DUK_ASSERT((call_flags & DUK_CALL_FLAG_IS_RESUME) != 0 ||
57211 	           (thr->state == DUK_HTHREAD_STATE_RUNNING &&
57212 	            thr->heap->curr_thread == thr));
57213 
57214 	/* If thr->ptr_curr_pc is set, sync curr_pc to act->pc.  Then NULL
57215 	 * thr->ptr_curr_pc so that it's not accidentally used with an incorrect
57216 	 * activation when side effects occur.  If we end up not making the
57217 	 * call we must restore the value.
57218 	 */
57219 	entry_ptr_curr_pc = thr->ptr_curr_pc;
57220 	duk_hthread_sync_and_null_currpc(thr);
57221 
57222 	/* if a tail call:
57223 	 *   - an Ecmascript activation must be on top of the callstack
57224 	 *   - there cannot be any active catchstack entries
57225 	 */
57226 #if defined(DUK_USE_ASSERTIONS)
57227 	if (call_flags & DUK_CALL_FLAG_IS_TAILCALL) {
57228 		duk_size_t our_callstack_index;
57229 		duk_size_t i;
57230 
57231 		DUK_ASSERT(thr->callstack_top >= 1);
57232 		our_callstack_index = thr->callstack_top - 1;
57233 		DUK_ASSERT_DISABLE(our_callstack_index >= 0);
57234 		DUK_ASSERT(our_callstack_index < thr->callstack_size);
57235 		DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + our_callstack_index) != NULL);
57236 		DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION(DUK_ACT_GET_FUNC(thr->callstack + our_callstack_index)));
57237 
57238 		/* No entry in the catchstack which would actually catch a
57239 		 * throw can refer to the callstack entry being reused.
57240 		 * There *can* be catchstack entries referring to the current
57241 		 * callstack entry as long as they don't catch (e.g. label sites).
57242 		 */
57243 
57244 		for (i = 0; i < thr->catchstack_top; i++) {
57245 			DUK_ASSERT(thr->catchstack[i].callstack_index < our_callstack_index ||  /* refer to callstack entries below current */
57246 			           DUK_CAT_GET_TYPE(thr->catchstack + i) == DUK_CAT_TYPE_LABEL); /* or a non-catching entry */
57247 		}
57248 	}
57249 #endif  /* DUK_USE_ASSERTIONS */
57250 
57251 	entry_valstack_bottom_index = (duk_size_t) (thr->valstack_bottom - thr->valstack);
57252 	/* XXX: rework */
57253 	idx_func = duk_normalize_index(thr, -num_stack_args - 2);
57254 	idx_args = idx_func + 2;
57255 
57256 	DUK_DD(DUK_DDPRINT("handle_ecma_call_setup: thr=%p, "
57257 	                   "num_stack_args=%ld, call_flags=0x%08lx (resume=%ld, tailcall=%ld), "
57258 	                   "idx_func=%ld, idx_args=%ld, entry_valstack_bottom_index=%ld",
57259 	                   (void *) thr,
57260 	                   (long) num_stack_args,
57261 	                   (unsigned long) call_flags,
57262 	                   (long) ((call_flags & DUK_CALL_FLAG_IS_RESUME) != 0 ? 1 : 0),
57263 	                   (long) ((call_flags & DUK_CALL_FLAG_IS_TAILCALL) != 0 ? 1 : 0),
57264 	                   (long) idx_func,
57265 	                   (long) idx_args,
57266 	                   (long) entry_valstack_bottom_index));
57267 
57268 	if (DUK_UNLIKELY(idx_func < 0 || idx_args < 0)) {
57269 		/* XXX: assert? compiler is responsible for this never happening */
57270 		DUK_ERROR_API(thr, DUK_STR_INVALID_CALL_ARGS);
57271 	}
57272 
57273 	/*
57274 	 *  Check the function type, handle bound function chains, and prepare
57275 	 *  parameters for the rest of the call handling.  Also figure out the
57276 	 *  effective 'this' binding, which replaces the current value at
57277 	 *  idx_func + 1.
57278 	 *
57279 	 *  If the target function is a 'bound' one, follow the chain of 'bound'
57280 	 *  functions until a non-bound function is found.  During this process,
57281 	 *  bound arguments are 'prepended' to existing ones, and the "this"
57282 	 *  binding is overridden.  See E5 Section 15.3.4.5.1.
57283 	 *
57284 	 *  If the final target function cannot be handled by an ecma-to-ecma
57285 	 *  call, return to the caller with a return value indicating this case.
57286 	 *  The bound chain is resolved and the caller can resume with a plain
57287 	 *  function call.
57288 	 */
57289 
57290 	func = duk__nonbound_func_lookup(ctx, idx_func, &num_stack_args, &tv_func, call_flags);
57291 	if (func == NULL || !DUK_HOBJECT_IS_COMPILEDFUNCTION(func)) {
57292 		DUK_DDD(DUK_DDDPRINT("final target is a lightfunc/nativefunc, cannot do ecma-to-ecma call"));
57293 		thr->ptr_curr_pc = entry_ptr_curr_pc;
57294 		return 0;
57295 	}
57296 	/* XXX: tv_func is not actually needed */
57297 
57298 	DUK_ASSERT(func != NULL);
57299 	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUND(func));
57300 	DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION(func));
57301 
57302 	duk__coerce_effective_this_binding(thr, func, idx_func + 1);
57303 	DUK_DDD(DUK_DDDPRINT("effective 'this' binding is: %!T",
57304 	                     duk_get_tval(ctx, idx_func + 1)));
57305 
57306 	nargs = ((duk_hcompiledfunction *) func)->nargs;
57307 	nregs = ((duk_hcompiledfunction *) func)->nregs;
57308 	DUK_ASSERT(nregs >= nargs);
57309 
57310 	/* [ ... func this arg1 ... argN ] */
57311 
57312 	/*
57313 	 *  Preliminary activation record and valstack manipulation.
57314 	 *  The concrete actions depend on whether the we're dealing
57315 	 *  with a tail call (reuse an existing activation), a resume,
57316 	 *  or a normal call.
57317 	 *
57318 	 *  The basic actions, in varying order, are:
57319 	 *
57320 	 *    - Check stack size for call handling
57321 	 *    - Grow call stack if necessary (non-tail-calls)
57322 	 *    - Update current activation (idx_retval) if necessary
57323 	 *      (non-tail, non-resume calls)
57324 	 *    - Move start of args (idx_args) to valstack bottom
57325 	 *      (tail calls)
57326 	 *
57327 	 *  Don't touch valstack_bottom or valstack_top yet so that Duktape API
57328 	 *  calls work normally.
57329 	 */
57330 
57331 	/* XXX: some overlapping code; cleanup */
57332 	use_tailcall = call_flags & DUK_CALL_FLAG_IS_TAILCALL;
57333 #if !defined(DUK_USE_TAILCALL)
57334 	DUK_ASSERT(use_tailcall == 0);  /* compiler ensures this */
57335 #endif
57336 	if (use_tailcall) {
57337 		/* tailcall cannot be flagged to resume calls, and a
57338 		 * previous frame must exist
57339 		 */
57340 		DUK_ASSERT(thr->callstack_top >= 1);
57341 		DUK_ASSERT((call_flags & DUK_CALL_FLAG_IS_RESUME) == 0);
57342 
57343 		act = thr->callstack + thr->callstack_top - 1;
57344 		if (act->flags & DUK_ACT_FLAG_PREVENT_YIELD) {
57345 			/* See: test-bug-tailcall-preventyield-assert.c. */
57346 			DUK_DDD(DUK_DDDPRINT("tail call prevented by current activation having DUK_ACT_FLAG_PREVENTYIELD"));
57347 			use_tailcall = 0;
57348 		} else if (DUK_HOBJECT_HAS_NOTAIL(func)) {
57349 			DUK_D(DUK_DPRINT("tail call prevented by function having a notail flag"));
57350 			use_tailcall = 0;
57351 		}
57352 	}
57353 
57354 	if (use_tailcall) {
57355 		duk_tval *tv1, *tv2;
57356 		duk_size_t cs_index;
57357 		duk_int_t i_stk;  /* must be signed for loop structure */
57358 		duk_idx_t i_arg;
57359 
57360 		/*
57361 		 *  Tailcall handling
57362 		 *
57363 		 *  Although the callstack entry is reused, we need to explicitly unwind
57364 		 *  the current activation (or simulate an unwind).  In particular, the
57365 		 *  current activation must be closed, otherwise something like
57366 		 *  test-bug-reduce-judofyr.js results.  Also catchstack needs be unwound
57367 		 *  because there may be non-error-catching label entries in valid tail calls.
57368 		 */
57369 
57370 		DUK_DDD(DUK_DDDPRINT("is tail call, reusing activation at callstack top, at index %ld",
57371 		                     (long) (thr->callstack_top - 1)));
57372 
57373 		/* 'act' already set above */
57374 
57375 		DUK_ASSERT(!DUK_HOBJECT_HAS_BOUND(func));
57376 		DUK_ASSERT(!DUK_HOBJECT_HAS_NATIVEFUNCTION(func));
57377 		DUK_ASSERT(DUK_HOBJECT_HAS_COMPILEDFUNCTION(func));
57378 		DUK_ASSERT((act->flags & DUK_ACT_FLAG_PREVENT_YIELD) == 0);
57379 
57380 		/* Unwind catchstack entries referring to the callstack entry we're reusing */
57381 		cs_index = thr->callstack_top - 1;
57382 		DUK_ASSERT(thr->catchstack_top <= DUK_INT_MAX);  /* catchstack limits */
57383 		for (i_stk = (duk_int_t) (thr->catchstack_top - 1); i_stk >= 0; i_stk--) {
57384 			duk_catcher *cat = thr->catchstack + i_stk;
57385 			if (cat->callstack_index != cs_index) {
57386 				/* 'i' is the first entry we'll keep */
57387 				break;
57388 			}
57389 		}
57390 		duk_hthread_catchstack_unwind(thr, i_stk + 1);
57391 
57392 		/* Unwind the topmost callstack entry before reusing it */
57393 		DUK_ASSERT(thr->callstack_top > 0);
57394 		duk_hthread_callstack_unwind(thr, thr->callstack_top - 1);
57395 
57396 		/* Then reuse the unwound activation; callstack was not shrunk so there is always space */
57397 		thr->callstack_top++;
57398 		DUK_ASSERT(thr->callstack_top <= thr->callstack_size);
57399 		act = thr->callstack + thr->callstack_top - 1;
57400 
57401 		/* Start filling in the activation */
57402 		act->func = func;  /* don't want an intermediate exposed state with func == NULL */
57403 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
57404 		act->prev_caller = NULL;
57405 #endif
57406 		DUK_ASSERT(func != NULL);
57407 		DUK_ASSERT(DUK_HOBJECT_HAS_COMPILEDFUNCTION(func));
57408 		/* don't want an intermediate exposed state with invalid pc */
57409 		act->curr_pc = DUK_HCOMPILEDFUNCTION_GET_CODE_BASE(thr->heap, (duk_hcompiledfunction *) func);
57410 #if defined(DUK_USE_DEBUGGER_SUPPORT)
57411 		act->prev_line = 0;
57412 #endif
57413 		DUK_TVAL_SET_OBJECT(&act->tv_func, func);  /* borrowed, no refcount */
57414 #if defined(DUK_USE_REFERENCE_COUNTING)
57415 		DUK_HOBJECT_INCREF(thr, func);
57416 		act = thr->callstack + thr->callstack_top - 1;  /* side effects (currently none though) */
57417 #endif
57418 
57419 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
57420 #if defined(DUK_USE_TAILCALL)
57421 #error incorrect options: tail calls enabled with function caller property
57422 #endif
57423 		/* XXX: this doesn't actually work properly for tail calls, so
57424 		 * tail calls are disabled when DUK_USE_NONSTD_FUNC_CALLER_PROPERTY
57425 		 * is in use.
57426 		 */
57427 		duk__update_func_caller_prop(thr, func);
57428 		act = thr->callstack + thr->callstack_top - 1;
57429 #endif
57430 
57431 		act->flags = (DUK_HOBJECT_HAS_STRICT(func) ?
57432 		              DUK_ACT_FLAG_STRICT | DUK_ACT_FLAG_TAILCALLED :
57433 		              DUK_ACT_FLAG_TAILCALLED);
57434 
57435 		DUK_ASSERT(DUK_ACT_GET_FUNC(act) == func);      /* already updated */
57436 		DUK_ASSERT(act->var_env == NULL);   /* already NULLed (by unwind) */
57437 		DUK_ASSERT(act->lex_env == NULL);   /* already NULLed (by unwind) */
57438 		act->idx_bottom = entry_valstack_bottom_index;  /* tail call -> reuse current "frame" */
57439 		DUK_ASSERT(nregs >= 0);
57440 #if 0  /* topmost activation idx_retval is considered garbage, no need to init */
57441 		act->idx_retval = 0;
57442 #endif
57443 
57444 		/*
57445 		 *  Manipulate valstack so that args are on the current bottom and the
57446 		 *  previous caller's 'this' binding (which is the value preceding the
57447 		 *  current bottom) is replaced with the new 'this' binding:
57448 		 *
57449 		 *       [ ... this_old | (crud) func this_new arg1 ... argN ]
57450 		 *  -->  [ ... this_new | arg1 ... argN ]
57451 		 *
57452 		 *  For tail calling to work properly, the valstack bottom must not grow
57453 		 *  here; otherwise crud would accumulate on the valstack.
57454 		 */
57455 
57456 		tv1 = thr->valstack_bottom - 1;
57457 		tv2 = thr->valstack_bottom + idx_func + 1;
57458 		DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);  /* tv1 is -below- valstack_bottom */
57459 		DUK_ASSERT(tv2 >= thr->valstack_bottom && tv2 < thr->valstack_top);
57460 		DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2);  /* side effects */
57461 
57462 		for (i_arg = 0; i_arg < idx_args; i_arg++) {
57463 			/* XXX: block removal API primitive */
57464 			/* Note: 'func' is popped from valstack here, but it is
57465 			 * already reachable from the activation.
57466 			 */
57467 			duk_remove(ctx, 0);
57468 		}
57469 		idx_func = 0; DUK_UNREF(idx_func);  /* really 'not applicable' anymore, should not be referenced after this */
57470 		idx_args = 0;
57471 
57472 		/* [ ... this_new | arg1 ... argN ] */
57473 	} else {
57474 		DUK_DDD(DUK_DDDPRINT("not a tail call, pushing a new activation to callstack, to index %ld",
57475 		                     (long) (thr->callstack_top)));
57476 
57477 		duk_hthread_callstack_grow(thr);
57478 
57479 		if (call_flags & DUK_CALL_FLAG_IS_RESUME) {
57480 			DUK_DDD(DUK_DDDPRINT("is resume -> no update to current activation (may not even exist)"));
57481 		} else {
57482 			DUK_DDD(DUK_DDDPRINT("update to current activation idx_retval"));
57483 			DUK_ASSERT(thr->callstack_top < thr->callstack_size);
57484 			DUK_ASSERT(thr->callstack_top >= 1);
57485 			act = thr->callstack + thr->callstack_top - 1;
57486 			DUK_ASSERT(DUK_ACT_GET_FUNC(act) != NULL);
57487 			DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION(DUK_ACT_GET_FUNC(act)));
57488 			act->idx_retval = entry_valstack_bottom_index + idx_func;
57489 		}
57490 
57491 		DUK_ASSERT(thr->callstack_top < thr->callstack_size);
57492 		act = thr->callstack + thr->callstack_top;
57493 		thr->callstack_top++;
57494 		DUK_ASSERT(thr->callstack_top <= thr->callstack_size);
57495 
57496 		DUK_ASSERT(!DUK_HOBJECT_HAS_BOUND(func));
57497 		DUK_ASSERT(!DUK_HOBJECT_HAS_NATIVEFUNCTION(func));
57498 		DUK_ASSERT(DUK_HOBJECT_HAS_COMPILEDFUNCTION(func));
57499 
57500 		act->flags = (DUK_HOBJECT_HAS_STRICT(func) ?
57501 		              DUK_ACT_FLAG_STRICT :
57502 		              0);
57503 		act->func = func;
57504 		act->var_env = NULL;
57505 		act->lex_env = NULL;
57506 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
57507 		act->prev_caller = NULL;
57508 #endif
57509 		DUK_ASSERT(func != NULL);
57510 		DUK_ASSERT(DUK_HOBJECT_HAS_COMPILEDFUNCTION(func));
57511 		act->curr_pc = DUK_HCOMPILEDFUNCTION_GET_CODE_BASE(thr->heap, (duk_hcompiledfunction *) func);
57512 #if defined(DUK_USE_DEBUGGER_SUPPORT)
57513 		act->prev_line = 0;
57514 #endif
57515 		act->idx_bottom = entry_valstack_bottom_index + idx_args;
57516 		DUK_ASSERT(nregs >= 0);
57517 #if 0  /* topmost activation idx_retval is considered garbage, no need to init */
57518 		act->idx_retval = 0;
57519 #endif
57520 		DUK_TVAL_SET_OBJECT(&act->tv_func, func);  /* borrowed, no refcount */
57521 
57522 		DUK_HOBJECT_INCREF(thr, func);  /* act->func */
57523 
57524 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
57525 		duk__update_func_caller_prop(thr, func);
57526 		act = thr->callstack + thr->callstack_top - 1;
57527 #endif
57528 	}
57529 
57530 	/* [ ... func this arg1 ... argN ]  (not tail call)
57531 	 * [ this | arg1 ... argN ]         (tail call)
57532 	 *
57533 	 * idx_args updated to match
57534 	 */
57535 
57536 	/*
57537 	 *  Environment record creation and 'arguments' object creation.
57538 	 *  Named function expression name binding is handled by the
57539 	 *  compiler; the compiled function's parent env will contain
57540 	 *  the (immutable) binding already.
57541 	 *
57542 	 *  Delayed creation (on demand) is handled in duk_js_var.c.
57543 	 */
57544 
57545 	/* XXX: unify handling with native call. */
57546 
57547 	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUND(func));  /* bound function chain has already been resolved */
57548 
57549 	if (!DUK_HOBJECT_HAS_NEWENV(func)) {
57550 		/* use existing env (e.g. for non-strict eval); cannot have
57551 		 * an own 'arguments' object (but can refer to the existing one)
57552 		 */
57553 
57554 		duk__handle_oldenv_for_call(thr, func, act);
57555 		/* No need to re-lookup 'act' at present: no side effects. */
57556 
57557 		DUK_ASSERT(act->lex_env != NULL);
57558 		DUK_ASSERT(act->var_env != NULL);
57559 		goto env_done;
57560 	}
57561 
57562 	DUK_ASSERT(DUK_HOBJECT_HAS_NEWENV(func));
57563 
57564 	if (!DUK_HOBJECT_HAS_CREATEARGS(func)) {
57565 		/* no need to create environment record now; leave as NULL */
57566 		DUK_ASSERT(act->lex_env == NULL);
57567 		DUK_ASSERT(act->var_env == NULL);
57568 		goto env_done;
57569 	}
57570 
57571 	/* third arg: absolute index (to entire valstack) of idx_bottom of new activation */
57572 	env = duk_create_activation_environment_record(thr, func, act->idx_bottom);
57573 	DUK_ASSERT(env != NULL);
57574 
57575 	/* [ ... arg1 ... argN envobj ] */
57576 
57577 	/* original input stack before nargs/nregs handling must be
57578 	 * intact for 'arguments' object
57579 	 */
57580 	DUK_ASSERT(DUK_HOBJECT_HAS_CREATEARGS(func));
57581 	duk__handle_createargs_for_call(thr, func, env, num_stack_args);
57582 
57583 	/* [ ... arg1 ... argN envobj ] */
57584 
57585 	act = thr->callstack + thr->callstack_top - 1;
57586 	act->lex_env = env;
57587 	act->var_env = env;
57588 	DUK_HOBJECT_INCREF(thr, act->lex_env);
57589 	DUK_HOBJECT_INCREF(thr, act->var_env);
57590 	duk_pop(ctx);
57591 
57592  env_done:
57593 	/* [ ... arg1 ... argN ] */
57594 
57595 	/*
57596 	 *  Setup value stack: clamp to 'nargs', fill up to 'nregs'
57597 	 */
57598 
57599 	duk__adjust_valstack_and_top(thr,
57600 	                             num_stack_args,
57601 	                             idx_args,
57602 	                             nregs,
57603 	                             nargs,
57604 	                             func);
57605 
57606 	/*
57607 	 *  Shift to new valstack_bottom.
57608 	 */
57609 
57610 	thr->valstack_bottom = thr->valstack_bottom + idx_args;
57611 	/* keep current valstack_top */
57612 	DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
57613 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
57614 	DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
57615 
57616 	/*
57617 	 *  Return to bytecode executor, which will resume execution from
57618 	 *  the topmost activation.
57619 	 */
57620 
57621 	return 1;
57622 }
57623 /*
57624  *  Ecmascript compiler.
57625  *
57626  *  Parses an input string and generates a function template result.
57627  *  Compilation may happen in multiple contexts (global code, eval
57628  *  code, function code).
57629  *
57630  *  The parser uses a traditional top-down recursive parsing for the
57631  *  statement level, and an operator precedence based top-down approach
57632  *  for the expression level.  The attempt is to minimize the C stack
57633  *  depth.  Bytecode is generated directly without an intermediate
57634  *  representation (tree), at the cost of needing two passes over each
57635  *  function.
57636  *
57637  *  The top-down recursive parser functions are named "duk__parse_XXX".
57638  *
57639  *  Recursion limits are in key functions to prevent arbitrary C recursion:
57640  *  function body parsing, statement parsing, and expression parsing.
57641  *
57642  *  See doc/compiler.rst for discussion on the design.
57643  *
57644  *  A few typing notes:
57645  *
57646  *    - duk_regconst_t: unsigned, no marker value for "none"
57647  *    - duk_reg_t: signed, < 0 = none
57648  *    - PC values: duk_int_t, negative values used as markers
57649  */
57650 
57651 /* include removed: duk_internal.h */
57652 
57653 /* if highest bit of a register number is set, it refers to a constant instead */
57654 #define DUK__CONST_MARKER                 DUK_JS_CONST_MARKER
57655 
57656 /* for array and object literals */
57657 #define DUK__MAX_ARRAY_INIT_VALUES        20
57658 #define DUK__MAX_OBJECT_INIT_PAIRS        10
57659 
57660 /* XXX: hack, remove when const lookup is not O(n) */
57661 #define DUK__GETCONST_MAX_CONSTS_CHECK    256
57662 
57663 /* These limits are based on bytecode limits.  Max temps is limited
57664  * by duk_hcompiledfunction nargs/nregs fields being 16 bits.
57665  */
57666 #define DUK__MAX_CONSTS                   DUK_BC_BC_MAX
57667 #define DUK__MAX_FUNCS                    DUK_BC_BC_MAX
57668 #define DUK__MAX_TEMPS                    0xffffL
57669 
57670 /* Initial bytecode size allocation. */
57671 #define DUK__BC_INITIAL_INSTS 256
57672 
57673 #define DUK__RECURSION_INCREASE(comp_ctx,thr)  do { \
57674 		DUK_DDD(DUK_DDDPRINT("RECURSION INCREASE: %s:%ld", (const char *) DUK_FILE_MACRO, (long) DUK_LINE_MACRO)); \
57675 		duk__recursion_increase((comp_ctx)); \
57676 	} while (0)
57677 
57678 #define DUK__RECURSION_DECREASE(comp_ctx,thr)  do { \
57679 		DUK_DDD(DUK_DDDPRINT("RECURSION DECREASE: %s:%ld", (const char *) DUK_FILE_MACRO, (long) DUK_LINE_MACRO)); \
57680 		duk__recursion_decrease((comp_ctx)); \
57681 	} while (0)
57682 
57683 /* Value stack slot limits: these are quite approximate right now, and
57684  * because they overlap in control flow, some could be eliminated.
57685  */
57686 #define DUK__COMPILE_ENTRY_SLOTS          8
57687 #define DUK__FUNCTION_INIT_REQUIRE_SLOTS  16
57688 #define DUK__FUNCTION_BODY_REQUIRE_SLOTS  16
57689 #define DUK__PARSE_STATEMENTS_SLOTS       16
57690 #define DUK__PARSE_EXPR_SLOTS             16
57691 
57692 /* Temporary structure used to pass a stack allocated region through
57693  * duk_safe_call().
57694  */
57695 typedef struct {
57696 	duk_small_uint_t flags;
57697 	duk_compiler_ctx comp_ctx_alloc;
57698 	duk_lexer_point lex_pt_alloc;
57699 } duk__compiler_stkstate;
57700 
57701 /*
57702  *  Prototypes
57703  */
57704 
57705 /* lexing */
57706 DUK_LOCAL_DECL void duk__advance_helper(duk_compiler_ctx *comp_ctx, duk_small_int_t expect);
57707 DUK_LOCAL_DECL void duk__advance_expect(duk_compiler_ctx *comp_ctx, duk_small_int_t expect);
57708 DUK_LOCAL_DECL void duk__advance(duk_compiler_ctx *ctx);
57709 
57710 /* function helpers */
57711 DUK_LOCAL_DECL void duk__init_func_valstack_slots(duk_compiler_ctx *comp_ctx);
57712 DUK_LOCAL_DECL void duk__reset_func_for_pass2(duk_compiler_ctx *comp_ctx);
57713 DUK_LOCAL_DECL void duk__init_varmap_and_prologue_for_pass2(duk_compiler_ctx *comp_ctx, duk_reg_t *out_stmt_value_reg);
57714 DUK_LOCAL_DECL void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx, duk_bool_t force_no_namebind);
57715 DUK_LOCAL_DECL duk_int_t duk__cleanup_varmap(duk_compiler_ctx *comp_ctx);
57716 
57717 /* code emission */
57718 DUK_LOCAL_DECL duk_int_t duk__get_current_pc(duk_compiler_ctx *comp_ctx);
57719 DUK_LOCAL_DECL duk_compiler_instr *duk__get_instr_ptr(duk_compiler_ctx *comp_ctx, duk_int_t pc);
57720 DUK_LOCAL_DECL void duk__emit(duk_compiler_ctx *comp_ctx, duk_instr_t ins);
57721 #if 0  /* unused */
57722 DUK_LOCAL_DECL void duk__emit_op_only(duk_compiler_ctx *comp_ctx, duk_small_uint_t op);
57723 #endif
57724 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);
57725 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);
57726 #if 0  /* unused */
57727 DUK_LOCAL_DECL void duk__emit_a(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t a);
57728 #endif
57729 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);
57730 DUK_LOCAL_DECL void duk__emit_abc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op, duk_regconst_t abc);
57731 DUK_LOCAL_DECL void duk__emit_extraop_b_c(duk_compiler_ctx *comp_ctx, duk_small_uint_t extraop_flags, duk_regconst_t b, duk_regconst_t c);
57732 DUK_LOCAL_DECL void duk__emit_extraop_b(duk_compiler_ctx *comp_ctx, duk_small_uint_t extraop_flags, duk_regconst_t b);
57733 DUK_LOCAL_DECL void duk__emit_extraop_bc(duk_compiler_ctx *comp_ctx, duk_small_uint_t extraop, duk_regconst_t bc);
57734 DUK_LOCAL_DECL void duk__emit_extraop_only(duk_compiler_ctx *comp_ctx, duk_small_uint_t extraop_flags);
57735 DUK_LOCAL_DECL void duk__emit_load_int32(duk_compiler_ctx *comp_ctx, duk_reg_t reg, duk_int32_t val);
57736 DUK_LOCAL_DECL void duk__emit_load_int32_noshuffle(duk_compiler_ctx *comp_ctx, duk_reg_t reg, duk_int32_t val);
57737 DUK_LOCAL_DECL void duk__emit_jump(duk_compiler_ctx *comp_ctx, duk_int_t target_pc);
57738 DUK_LOCAL_DECL duk_int_t duk__emit_jump_empty(duk_compiler_ctx *comp_ctx);
57739 DUK_LOCAL_DECL void duk__insert_jump_entry(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc);
57740 DUK_LOCAL_DECL void duk__patch_jump(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc, duk_int_t target_pc);
57741 DUK_LOCAL_DECL void duk__patch_jump_here(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc);
57742 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);
57743 DUK_LOCAL_DECL void duk__emit_if_false_skip(duk_compiler_ctx *comp_ctx, duk_regconst_t regconst);
57744 DUK_LOCAL_DECL void duk__emit_if_true_skip(duk_compiler_ctx *comp_ctx, duk_regconst_t regconst);
57745 DUK_LOCAL_DECL void duk__emit_invalid(duk_compiler_ctx *comp_ctx);
57746 
57747 /* ivalue/ispec helpers */
57748 DUK_LOCAL_DECL void duk__copy_ispec(duk_compiler_ctx *comp_ctx, duk_ispec *src, duk_ispec *dst);
57749 DUK_LOCAL_DECL void duk__copy_ivalue(duk_compiler_ctx *comp_ctx, duk_ivalue *src, duk_ivalue *dst);
57750 DUK_LOCAL_DECL duk_bool_t duk__is_whole_get_int32(duk_double_t x, duk_int32_t *ival);
57751 DUK_LOCAL_DECL duk_reg_t duk__alloctemps(duk_compiler_ctx *comp_ctx, duk_small_int_t num);
57752 DUK_LOCAL_DECL duk_reg_t duk__alloctemp(duk_compiler_ctx *comp_ctx);
57753 DUK_LOCAL_DECL void duk__settemp_checkmax(duk_compiler_ctx *comp_ctx, duk_reg_t temp_next);
57754 DUK_LOCAL_DECL duk_regconst_t duk__getconst(duk_compiler_ctx *comp_ctx);
57755 DUK_LOCAL_DECL
57756 duk_regconst_t duk__ispec_toregconst_raw(duk_compiler_ctx *comp_ctx,
57757                                          duk_ispec *x,
57758                                          duk_reg_t forced_reg,
57759                                          duk_small_uint_t flags);
57760 DUK_LOCAL_DECL void duk__ispec_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ispec *x, duk_reg_t forced_reg);
57761 DUK_LOCAL_DECL void duk__ivalue_toplain_raw(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_reg_t forced_reg);
57762 DUK_LOCAL_DECL void duk__ivalue_toplain(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
57763 DUK_LOCAL_DECL void duk__ivalue_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
57764 DUK_LOCAL_DECL
57765 duk_regconst_t duk__ivalue_toregconst_raw(duk_compiler_ctx *comp_ctx,
57766                                           duk_ivalue *x,
57767                                           duk_reg_t forced_reg,
57768                                           duk_small_uint_t flags);
57769 DUK_LOCAL_DECL duk_reg_t duk__ivalue_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
57770 #if 0  /* unused */
57771 DUK_LOCAL_DECL duk_reg_t duk__ivalue_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
57772 #endif
57773 DUK_LOCAL_DECL void duk__ivalue_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_int_t forced_reg);
57774 DUK_LOCAL_DECL duk_regconst_t duk__ivalue_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
57775 DUK_LOCAL_DECL duk_regconst_t duk__ivalue_totempconst(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
57776 
57777 /* identifier handling */
57778 DUK_LOCAL_DECL duk_reg_t duk__lookup_active_register_binding(duk_compiler_ctx *comp_ctx);
57779 DUK_LOCAL_DECL duk_bool_t duk__lookup_lhs(duk_compiler_ctx *ctx, duk_reg_t *out_reg_varbind, duk_regconst_t *out_rc_varname);
57780 
57781 /* label handling */
57782 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);
57783 DUK_LOCAL_DECL void duk__update_label_flags(duk_compiler_ctx *comp_ctx, duk_int_t label_id, duk_small_uint_t flags);
57784 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);
57785 DUK_LOCAL_DECL void duk__reset_labels_to_length(duk_compiler_ctx *comp_ctx, duk_int_t len);
57786 
57787 /* top-down expression parser */
57788 DUK_LOCAL_DECL void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
57789 DUK_LOCAL_DECL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_ivalue *res);
57790 DUK_LOCAL_DECL duk_small_uint_t duk__expr_lbp(duk_compiler_ctx *comp_ctx);
57791 DUK_LOCAL_DECL duk_bool_t duk__expr_is_empty(duk_compiler_ctx *comp_ctx);
57792 
57793 /* exprtop is the top level variant which resets nud/led counts */
57794 DUK_LOCAL_DECL void duk__expr(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
57795 DUK_LOCAL_DECL void duk__exprtop(duk_compiler_ctx *ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
57796 
57797 /* convenience helpers */
57798 #if 0  /* unused */
57799 DUK_LOCAL_DECL duk_reg_t duk__expr_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
57800 #endif
57801 #if 0  /* unused */
57802 DUK_LOCAL_DECL duk_reg_t duk__expr_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
57803 #endif
57804 DUK_LOCAL_DECL void duk__expr_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags, duk_reg_t forced_reg);
57805 DUK_LOCAL_DECL duk_regconst_t duk__expr_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
57806 #if 0  /* unused */
57807 DUK_LOCAL_DECL duk_regconst_t duk__expr_totempconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
57808 #endif
57809 DUK_LOCAL_DECL void duk__expr_toplain(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
57810 DUK_LOCAL_DECL void duk__expr_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
57811 DUK_LOCAL_DECL duk_reg_t duk__exprtop_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
57812 #if 0  /* unused */
57813 DUK_LOCAL_DECL duk_reg_t duk__exprtop_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
57814 #endif
57815 DUK_LOCAL_DECL void duk__exprtop_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags, duk_reg_t forced_reg);
57816 DUK_LOCAL_DECL duk_regconst_t duk__exprtop_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
57817 #if 0  /* unused */
57818 DUK_LOCAL_DECL void duk__exprtop_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
57819 #endif
57820 
57821 /* expression parsing helpers */
57822 DUK_LOCAL_DECL duk_int_t duk__parse_arguments(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
57823 DUK_LOCAL_DECL void duk__nud_array_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
57824 DUK_LOCAL_DECL void duk__nud_object_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
57825 DUK_LOCAL_DECL duk_bool_t duk__nud_object_literal_key_check(duk_compiler_ctx *comp_ctx, duk_small_uint_t new_key_flags);
57826 
57827 /* statement parsing */
57828 DUK_LOCAL_DECL void duk__parse_var_decl(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t expr_flags, duk_reg_t *out_reg_varbind, duk_regconst_t *out_rc_varname);
57829 DUK_LOCAL_DECL void duk__parse_var_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t expr_flags);
57830 DUK_LOCAL_DECL void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site);
57831 DUK_LOCAL_DECL void duk__parse_switch_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site);
57832 DUK_LOCAL_DECL void duk__parse_if_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
57833 DUK_LOCAL_DECL void duk__parse_do_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site);
57834 DUK_LOCAL_DECL void duk__parse_while_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site);
57835 DUK_LOCAL_DECL void duk__parse_break_or_continue_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
57836 DUK_LOCAL_DECL void duk__parse_return_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
57837 DUK_LOCAL_DECL void duk__parse_throw_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
57838 DUK_LOCAL_DECL void duk__parse_try_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
57839 DUK_LOCAL_DECL void duk__parse_with_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
57840 DUK_LOCAL_DECL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_bool_t allow_source_elem);
57841 DUK_LOCAL_DECL duk_int_t duk__stmt_label_site(duk_compiler_ctx *comp_ctx, duk_int_t label_id);
57842 DUK_LOCAL_DECL void duk__parse_stmts(duk_compiler_ctx *comp_ctx, duk_bool_t allow_source_elem, duk_bool_t expect_eof);
57843 
57844 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_small_int_t expect_token);
57845 DUK_LOCAL_DECL void duk__parse_func_formals(duk_compiler_ctx *comp_ctx);
57846 DUK_LOCAL_DECL void duk__parse_func_like_raw(duk_compiler_ctx *comp_ctx, duk_bool_t is_decl, duk_bool_t is_setget);
57847 DUK_LOCAL_DECL duk_int_t duk__parse_func_like_fnum(duk_compiler_ctx *comp_ctx, duk_bool_t is_decl, duk_bool_t is_setget);
57848 
57849 /*
57850  *  Parser control values for tokens.  The token table is ordered by the
57851  *  DUK_TOK_XXX defines.
57852  *
57853  *  The binding powers are for lbp() use (i.e. for use in led() context).
57854  *  Binding powers are positive for typing convenience, and bits at the
57855  *  top should be reserved for flags.  Binding power step must be higher
57856  *  than 1 so that binding power "lbp - 1" can be used for right associative
57857  *  operators.  Currently a step of 2 is used (which frees one more bit for
57858  *  flags).
57859  */
57860 
57861 /* XXX: actually single step levels would work just fine, clean up */
57862 
57863 /* binding power "levels" (see doc/compiler.rst) */
57864 #define DUK__BP_INVALID                0             /* always terminates led() */
57865 #define DUK__BP_EOF                    2
57866 #define DUK__BP_CLOSING                4             /* token closes expression, e.g. ')', ']' */
57867 #define DUK__BP_FOR_EXPR               DUK__BP_CLOSING    /* bp to use when parsing a top level Expression */
57868 #define DUK__BP_COMMA                  6
57869 #define DUK__BP_ASSIGNMENT             8
57870 #define DUK__BP_CONDITIONAL            10
57871 #define DUK__BP_LOR                    12
57872 #define DUK__BP_LAND                   14
57873 #define DUK__BP_BOR                    16
57874 #define DUK__BP_BXOR                   18
57875 #define DUK__BP_BAND                   20
57876 #define DUK__BP_EQUALITY               22
57877 #define DUK__BP_RELATIONAL             24
57878 #define DUK__BP_SHIFT                  26
57879 #define DUK__BP_ADDITIVE               28
57880 #define DUK__BP_MULTIPLICATIVE         30
57881 #define DUK__BP_POSTFIX                32
57882 #define DUK__BP_CALL                   34
57883 #define DUK__BP_MEMBER                 36
57884 
57885 #define DUK__TOKEN_LBP_BP_MASK         0x1f
57886 #define DUK__TOKEN_LBP_FLAG_NO_REGEXP  (1 << 5)   /* regexp literal must not follow this token */
57887 #define DUK__TOKEN_LBP_FLAG_TERMINATES (1 << 6)   /* terminates expression; e.g. post-increment/-decrement */
57888 #define DUK__TOKEN_LBP_FLAG_UNUSED     (1 << 7)   /* spare */
57889 
57890 #define DUK__TOKEN_LBP_GET_BP(x)       ((duk_small_uint_t) (((x) & DUK__TOKEN_LBP_BP_MASK) * 2))
57891 
57892 #define DUK__MK_LBP(bp)                ((bp) >> 1)    /* bp is assumed to be even */
57893 #define DUK__MK_LBP_FLAGS(bp,flags)    (((bp) >> 1) | (flags))
57894 
57895 DUK_LOCAL const duk_uint8_t duk__token_lbp[] = {
57896 	DUK__MK_LBP(DUK__BP_EOF),                                 /* DUK_TOK_EOF */
57897 	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_IDENTIFIER */
57898 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_BREAK */
57899 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_CASE */
57900 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_CATCH */
57901 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_CONTINUE */
57902 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_DEBUGGER */
57903 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_DEFAULT */
57904 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_DELETE */
57905 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_DO */
57906 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_ELSE */
57907 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_FINALLY */
57908 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_FOR */
57909 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_FUNCTION */
57910 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_IF */
57911 	DUK__MK_LBP(DUK__BP_RELATIONAL),                          /* DUK_TOK_IN */
57912 	DUK__MK_LBP(DUK__BP_RELATIONAL),                          /* DUK_TOK_INSTANCEOF */
57913 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_NEW */
57914 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_RETURN */
57915 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_SWITCH */
57916 	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_THIS */
57917 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_THROW */
57918 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_TRY */
57919 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_TYPEOF */
57920 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_VAR */
57921 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_CONST */
57922 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_VOID */
57923 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_WHILE */
57924 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_WITH */
57925 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_CLASS */
57926 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_ENUM */
57927 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_EXPORT */
57928 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_EXTENDS */
57929 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_IMPORT */
57930 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_SUPER */
57931 	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_NULL */
57932 	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_TRUE */
57933 	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_FALSE */
57934 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_GET */
57935 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_SET */
57936 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_IMPLEMENTS */
57937 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_INTERFACE */
57938 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_LET */
57939 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_PACKAGE */
57940 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_PRIVATE */
57941 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_PROTECTED */
57942 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_PUBLIC */
57943 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_STATIC */
57944 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_YIELD */
57945 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_LCURLY */
57946 	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_RCURLY */
57947 	DUK__MK_LBP(DUK__BP_MEMBER),                              /* DUK_TOK_LBRACKET */
57948 	DUK__MK_LBP_FLAGS(DUK__BP_CLOSING, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_RBRACKET */
57949 	DUK__MK_LBP(DUK__BP_CALL),                                /* DUK_TOK_LPAREN */
57950 	DUK__MK_LBP_FLAGS(DUK__BP_CLOSING, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_RPAREN */
57951 	DUK__MK_LBP(DUK__BP_MEMBER),                              /* DUK_TOK_PERIOD */
57952 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_SEMICOLON */
57953 	DUK__MK_LBP(DUK__BP_COMMA),                               /* DUK_TOK_COMMA */
57954 	DUK__MK_LBP(DUK__BP_RELATIONAL),                          /* DUK_TOK_LT */
57955 	DUK__MK_LBP(DUK__BP_RELATIONAL),                          /* DUK_TOK_GT */
57956 	DUK__MK_LBP(DUK__BP_RELATIONAL),                          /* DUK_TOK_LE */
57957 	DUK__MK_LBP(DUK__BP_RELATIONAL),                          /* DUK_TOK_GE */
57958 	DUK__MK_LBP(DUK__BP_EQUALITY),                            /* DUK_TOK_EQ */
57959 	DUK__MK_LBP(DUK__BP_EQUALITY),                            /* DUK_TOK_NEQ */
57960 	DUK__MK_LBP(DUK__BP_EQUALITY),                            /* DUK_TOK_SEQ */
57961 	DUK__MK_LBP(DUK__BP_EQUALITY),                            /* DUK_TOK_SNEQ */
57962 	DUK__MK_LBP(DUK__BP_ADDITIVE),                            /* DUK_TOK_ADD */
57963 	DUK__MK_LBP(DUK__BP_ADDITIVE),                            /* DUK_TOK_SUB */
57964 	DUK__MK_LBP(DUK__BP_MULTIPLICATIVE),                      /* DUK_TOK_MUL */
57965 	DUK__MK_LBP(DUK__BP_MULTIPLICATIVE),                      /* DUK_TOK_DIV */
57966 	DUK__MK_LBP(DUK__BP_MULTIPLICATIVE),                      /* DUK_TOK_MOD */
57967 	DUK__MK_LBP(DUK__BP_POSTFIX),                             /* DUK_TOK_INCREMENT */
57968 	DUK__MK_LBP(DUK__BP_POSTFIX),                             /* DUK_TOK_DECREMENT */
57969 	DUK__MK_LBP(DUK__BP_SHIFT),                               /* DUK_TOK_ALSHIFT */
57970 	DUK__MK_LBP(DUK__BP_SHIFT),                               /* DUK_TOK_ARSHIFT */
57971 	DUK__MK_LBP(DUK__BP_SHIFT),                               /* DUK_TOK_RSHIFT */
57972 	DUK__MK_LBP(DUK__BP_BAND),                                /* DUK_TOK_BAND */
57973 	DUK__MK_LBP(DUK__BP_BOR),                                 /* DUK_TOK_BOR */
57974 	DUK__MK_LBP(DUK__BP_BXOR),                                /* DUK_TOK_BXOR */
57975 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_LNOT */
57976 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_BNOT */
57977 	DUK__MK_LBP(DUK__BP_LAND),                                /* DUK_TOK_LAND */
57978 	DUK__MK_LBP(DUK__BP_LOR),                                 /* DUK_TOK_LOR */
57979 	DUK__MK_LBP(DUK__BP_CONDITIONAL),                         /* DUK_TOK_QUESTION */
57980 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_COLON */
57981 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_EQUALSIGN */
57982 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_ADD_EQ */
57983 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_SUB_EQ */
57984 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_MUL_EQ */
57985 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_DIV_EQ */
57986 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_MOD_EQ */
57987 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_ALSHIFT_EQ */
57988 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_ARSHIFT_EQ */
57989 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_RSHIFT_EQ */
57990 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_BAND_EQ */
57991 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_BOR_EQ */
57992 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_BXOR_EQ */
57993 	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_NUMBER */
57994 	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_STRING */
57995 	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_REGEXP */
57996 };
57997 
57998 /*
57999  *  Misc helpers
58000  */
58001 
58002 DUK_LOCAL void duk__recursion_increase(duk_compiler_ctx *comp_ctx) {
58003 	DUK_ASSERT(comp_ctx != NULL);
58004 	DUK_ASSERT(comp_ctx->recursion_depth >= 0);
58005 	if (comp_ctx->recursion_depth >= comp_ctx->recursion_limit) {
58006 		DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_COMPILER_RECURSION_LIMIT);
58007 	}
58008 	comp_ctx->recursion_depth++;
58009 }
58010 
58011 DUK_LOCAL void duk__recursion_decrease(duk_compiler_ctx *comp_ctx) {
58012 	DUK_ASSERT(comp_ctx != NULL);
58013 	DUK_ASSERT(comp_ctx->recursion_depth > 0);
58014 	comp_ctx->recursion_depth--;
58015 }
58016 
58017 DUK_LOCAL duk_bool_t duk__hstring_is_eval_or_arguments(duk_compiler_ctx *comp_ctx, duk_hstring *h) {
58018 	DUK_UNREF(comp_ctx);
58019 	DUK_ASSERT(h != NULL);
58020 	return DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(h);
58021 }
58022 
58023 DUK_LOCAL duk_bool_t duk__hstring_is_eval_or_arguments_in_strict_mode(duk_compiler_ctx *comp_ctx, duk_hstring *h) {
58024 	DUK_ASSERT(h != NULL);
58025 	return (comp_ctx->curr_func.is_strict &&
58026 	        DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(h));
58027 }
58028 
58029 /*
58030  *  Parser duk__advance() token eating functions
58031  */
58032 
58033 /* XXX: valstack handling is awkward.  Add a valstack helper which
58034  * avoids dup():ing; valstack_copy(src, dst)?
58035  */
58036 
58037 DUK_LOCAL void duk__advance_helper(duk_compiler_ctx *comp_ctx, duk_small_int_t expect) {
58038 	duk_hthread *thr = comp_ctx->thr;
58039 	duk_context *ctx = (duk_context *) thr;
58040 	duk_bool_t regexp;
58041 
58042 	DUK_ASSERT(comp_ctx->curr_token.t >= 0 && comp_ctx->curr_token.t <= DUK_TOK_MAXVAL);  /* MAXVAL is inclusive */
58043 
58044 	/*
58045 	 *  Use current token to decide whether a RegExp can follow.
58046 	 *
58047 	 *  We can use either 't' or 't_nores'; the latter would not
58048 	 *  recognize keywords.  Some keywords can be followed by a
58049 	 *  RegExp (e.g. "return"), so using 't' is better.  This is
58050 	 *  not trivial, see doc/compiler.rst.
58051 	 */
58052 
58053 	regexp = 1;
58054 	if (duk__token_lbp[comp_ctx->curr_token.t] & DUK__TOKEN_LBP_FLAG_NO_REGEXP) {
58055 		regexp = 0;
58056 	}
58057 	if (comp_ctx->curr_func.reject_regexp_in_adv) {
58058 		comp_ctx->curr_func.reject_regexp_in_adv = 0;
58059 		regexp = 0;
58060 	}
58061 
58062 	if (expect >= 0 && comp_ctx->curr_token.t != expect) {
58063 		DUK_D(DUK_DPRINT("parse error: expect=%ld, got=%ld",
58064 		                 (long) expect, (long) comp_ctx->curr_token.t));
58065 		DUK_ERROR_SYNTAX(thr, DUK_STR_PARSE_ERROR);
58066 	}
58067 
58068 	/* make current token the previous; need to fiddle with valstack "backing store" */
58069 	DUK_MEMCPY(&comp_ctx->prev_token, &comp_ctx->curr_token, sizeof(duk_token));
58070 	duk_copy(ctx, comp_ctx->tok11_idx, comp_ctx->tok21_idx);
58071 	duk_copy(ctx, comp_ctx->tok12_idx, comp_ctx->tok22_idx);
58072 
58073 	/* parse new token */
58074 	duk_lexer_parse_js_input_element(&comp_ctx->lex,
58075 	                                 &comp_ctx->curr_token,
58076 	                                 comp_ctx->curr_func.is_strict,
58077 	                                 regexp);
58078 
58079 	DUK_DDD(DUK_DDDPRINT("advance: curr: tok=%ld/%ld,%ld,term=%ld,%!T,%!T "
58080 	                     "prev: tok=%ld/%ld,%ld,term=%ld,%!T,%!T",
58081 	                     (long) comp_ctx->curr_token.t,
58082 	                     (long) comp_ctx->curr_token.t_nores,
58083 	                     (long) comp_ctx->curr_token.start_line,
58084 	                     (long) comp_ctx->curr_token.lineterm,
58085 	                     (duk_tval *) duk_get_tval(ctx, comp_ctx->tok11_idx),
58086 	                     (duk_tval *) duk_get_tval(ctx, comp_ctx->tok12_idx),
58087 	                     (long) comp_ctx->prev_token.t,
58088 	                     (long) comp_ctx->prev_token.t_nores,
58089 	                     (long) comp_ctx->prev_token.start_line,
58090 	                     (long) comp_ctx->prev_token.lineterm,
58091 	                     (duk_tval *) duk_get_tval(ctx, comp_ctx->tok21_idx),
58092 	                     (duk_tval *) duk_get_tval(ctx, comp_ctx->tok22_idx)));
58093 }
58094 
58095 /* advance, expecting current token to be a specific token; parse next token in regexp context */
58096 DUK_LOCAL void duk__advance_expect(duk_compiler_ctx *comp_ctx, duk_small_int_t expect) {
58097 	duk__advance_helper(comp_ctx, expect);
58098 }
58099 
58100 /* advance, whatever the current token is; parse next token in regexp context */
58101 DUK_LOCAL void duk__advance(duk_compiler_ctx *comp_ctx) {
58102 	duk__advance_helper(comp_ctx, -1);
58103 }
58104 
58105 /*
58106  *  Helpers for duk_compiler_func.
58107  */
58108 
58109 /* init function state: inits valstack allocations */
58110 DUK_LOCAL void duk__init_func_valstack_slots(duk_compiler_ctx *comp_ctx) {
58111 	duk_compiler_func *func = &comp_ctx->curr_func;
58112 	duk_hthread *thr = comp_ctx->thr;
58113 	duk_context *ctx = (duk_context *) thr;
58114 	duk_idx_t entry_top;
58115 
58116 	entry_top = duk_get_top(ctx);
58117 
58118 	DUK_MEMZERO(func, sizeof(*func));  /* intentional overlap with earlier memzero */
58119 #ifdef DUK_USE_EXPLICIT_NULL_INIT
58120 	func->h_name = NULL;
58121 	func->h_consts = NULL;
58122 	func->h_funcs = NULL;
58123 	func->h_decls = NULL;
58124 	func->h_labelnames = NULL;
58125 	func->h_labelinfos = NULL;
58126 	func->h_argnames = NULL;
58127 	func->h_varmap = NULL;
58128 #endif
58129 
58130 	duk_require_stack(ctx, DUK__FUNCTION_INIT_REQUIRE_SLOTS);
58131 
58132 	DUK_BW_INIT_PUSHBUF(thr, &func->bw_code, DUK__BC_INITIAL_INSTS * sizeof(duk_compiler_instr));
58133 	/* code_idx = entry_top + 0 */
58134 
58135 	duk_push_array(ctx);
58136 	func->consts_idx = entry_top + 1;
58137 	func->h_consts = DUK_GET_HOBJECT_POSIDX(ctx, entry_top + 1);
58138 	DUK_ASSERT(func->h_consts != NULL);
58139 
58140 	duk_push_array(ctx);
58141 	func->funcs_idx = entry_top + 2;
58142 	func->h_funcs = DUK_GET_HOBJECT_POSIDX(ctx, entry_top + 2);
58143 	DUK_ASSERT(func->h_funcs != NULL);
58144 	DUK_ASSERT(func->fnum_next == 0);
58145 
58146 	duk_push_array(ctx);
58147 	func->decls_idx = entry_top + 3;
58148 	func->h_decls = DUK_GET_HOBJECT_POSIDX(ctx, entry_top + 3);
58149 	DUK_ASSERT(func->h_decls != NULL);
58150 
58151 	duk_push_array(ctx);
58152 	func->labelnames_idx = entry_top + 4;
58153 	func->h_labelnames = DUK_GET_HOBJECT_POSIDX(ctx, entry_top + 4);
58154 	DUK_ASSERT(func->h_labelnames != NULL);
58155 
58156 	duk_push_dynamic_buffer(ctx, 0);
58157 	func->labelinfos_idx = entry_top + 5;
58158 	func->h_labelinfos = (duk_hbuffer_dynamic *) duk_get_hbuffer(ctx, entry_top + 5);
58159 	DUK_ASSERT(func->h_labelinfos != NULL);
58160 	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(func->h_labelinfos) && !DUK_HBUFFER_HAS_EXTERNAL(func->h_labelinfos));
58161 
58162 	duk_push_array(ctx);
58163 	func->argnames_idx = entry_top + 6;
58164 	func->h_argnames = DUK_GET_HOBJECT_POSIDX(ctx, entry_top + 6);
58165 	DUK_ASSERT(func->h_argnames != NULL);
58166 
58167 	duk_push_object_internal(ctx);
58168 	func->varmap_idx = entry_top + 7;
58169 	func->h_varmap = DUK_GET_HOBJECT_POSIDX(ctx, entry_top + 7);
58170 	DUK_ASSERT(func->h_varmap != NULL);
58171 }
58172 
58173 /* reset function state (prepare for pass 2) */
58174 DUK_LOCAL void duk__reset_func_for_pass2(duk_compiler_ctx *comp_ctx) {
58175 	duk_compiler_func *func = &comp_ctx->curr_func;
58176 	duk_hthread *thr = comp_ctx->thr;
58177 	duk_context *ctx = (duk_context *) thr;
58178 
58179 	/* reset bytecode buffer but keep current size; pass 2 will
58180 	 * require same amount or more.
58181 	 */
58182 	DUK_BW_RESET_SIZE(thr, &func->bw_code);
58183 
58184 	duk_hobject_set_length_zero(thr, func->h_consts);
58185 	/* keep func->h_funcs; inner functions are not reparsed to avoid O(depth^2) parsing */
58186 	func->fnum_next = 0;
58187 	/* duk_hobject_set_length_zero(thr, func->h_funcs); */
58188 	duk_hobject_set_length_zero(thr, func->h_labelnames);
58189 	duk_hbuffer_reset(thr, func->h_labelinfos);
58190 	/* keep func->h_argnames; it is fixed for all passes */
58191 
58192 	/* truncated in case pass 3 needed */
58193 	duk_push_object_internal(ctx);
58194 	duk_replace(ctx, func->varmap_idx);
58195 	func->h_varmap = DUK_GET_HOBJECT_POSIDX(ctx, func->varmap_idx);
58196 	DUK_ASSERT(func->h_varmap != NULL);
58197 }
58198 
58199 /* cleanup varmap from any null entries, compact it, etc; returns number
58200  * of final entries after cleanup.
58201  */
58202 DUK_LOCAL duk_int_t duk__cleanup_varmap(duk_compiler_ctx *comp_ctx) {
58203 	duk_hthread *thr = comp_ctx->thr;
58204 	duk_context *ctx = (duk_context *) thr;
58205 	duk_hobject *h_varmap;
58206 	duk_hstring *h_key;
58207 	duk_tval *tv;
58208 	duk_uint32_t i, e_next;
58209 	duk_int_t ret;
58210 
58211 	/* [ ... varmap ] */
58212 
58213 	h_varmap = DUK_GET_HOBJECT_NEGIDX(ctx, -1);
58214 	DUK_ASSERT(h_varmap != NULL);
58215 
58216 	ret = 0;
58217 	e_next = DUK_HOBJECT_GET_ENEXT(h_varmap);
58218 	for (i = 0; i < e_next; i++) {
58219 		h_key = DUK_HOBJECT_E_GET_KEY(thr->heap, h_varmap, i);
58220 		if (!h_key) {
58221 			continue;
58222 		}
58223 
58224 		DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, h_varmap, i));
58225 
58226 		/* The entries can either be register numbers or 'null' values.
58227 		 * Thus, no need to DECREF them and get side effects.  DECREF'ing
58228 		 * the keys (strings) can cause memory to be freed but no side
58229 		 * effects as strings don't have finalizers.  This is why we can
58230 		 * rely on the object properties not changing from underneath us.
58231 		 */
58232 
58233 		tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, h_varmap, i);
58234 		if (!DUK_TVAL_IS_NUMBER(tv)) {
58235 			DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv));
58236 			DUK_HOBJECT_E_SET_KEY(thr->heap, h_varmap, i, NULL);
58237 			DUK_HSTRING_DECREF(thr, h_key);
58238 			/* when key is NULL, value is garbage so no need to set */
58239 		} else {
58240 			ret++;
58241 		}
58242 	}
58243 
58244 	duk_compact(ctx, -1);
58245 
58246 	return ret;
58247 }
58248 
58249 /* convert duk_compiler_func into a function template, leaving the result
58250  * on top of stack.
58251  */
58252 /* XXX: awkward and bloated asm -- use faster internal accesses */
58253 DUK_LOCAL void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx, duk_bool_t force_no_namebind) {
58254 	duk_compiler_func *func = &comp_ctx->curr_func;
58255 	duk_hthread *thr = comp_ctx->thr;
58256 	duk_context *ctx = (duk_context *) thr;
58257 	duk_hcompiledfunction *h_res;
58258 	duk_hbuffer_fixed *h_data;
58259 	duk_size_t consts_count;
58260 	duk_size_t funcs_count;
58261 	duk_size_t code_count;
58262 	duk_size_t code_size;
58263 	duk_size_t data_size;
58264 	duk_size_t i;
58265 	duk_tval *p_const;
58266 	duk_hobject **p_func;
58267 	duk_instr_t *p_instr;
58268 	duk_compiler_instr *q_instr;
58269 	duk_tval *tv;
58270 
58271 	DUK_DDD(DUK_DDDPRINT("converting duk_compiler_func to function/template"));
58272 
58273 	/*
58274 	 *  Push result object and init its flags
58275 	 */
58276 
58277 	/* Valstack should suffice here, required on function valstack init */
58278 
58279 	(void) duk_push_compiledfunction(ctx);
58280 	h_res = (duk_hcompiledfunction *) DUK_GET_HOBJECT_NEGIDX(ctx, -1);  /* XXX: specific getter */
58281 	DUK_ASSERT(h_res != NULL);
58282 
58283 	if (func->is_function) {
58284 		DUK_DDD(DUK_DDDPRINT("function -> set NEWENV"));
58285 		DUK_HOBJECT_SET_NEWENV((duk_hobject *) h_res);
58286 
58287 		if (!func->is_arguments_shadowed) {
58288 			/* arguments object would be accessible; note that shadowing
58289 			 * bindings are arguments or function declarations, neither
58290 			 * of which are deletable, so this is safe.
58291 			 */
58292 
58293 			if (func->id_access_arguments || func->may_direct_eval) {
58294 				DUK_DDD(DUK_DDDPRINT("function may access 'arguments' object directly or "
58295 				                     "indirectly -> set CREATEARGS"));
58296 				DUK_HOBJECT_SET_CREATEARGS((duk_hobject *) h_res);
58297 			}
58298 		}
58299 	} else if (func->is_eval && func->is_strict) {
58300 		DUK_DDD(DUK_DDDPRINT("strict eval code -> set NEWENV"));
58301 		DUK_HOBJECT_SET_NEWENV((duk_hobject *) h_res);
58302 	} else {
58303 		/* non-strict eval: env is caller's env or global env (direct vs. indirect call)
58304 		 * global code: env is is global env
58305 		 */
58306 		DUK_DDD(DUK_DDDPRINT("non-strict eval code or global code -> no NEWENV"));
58307 		DUK_ASSERT(!DUK_HOBJECT_HAS_NEWENV((duk_hobject *) h_res));
58308 	}
58309 
58310 	if (func->is_function && !func->is_decl && func->h_name != NULL && !force_no_namebind) {
58311 		/* Object literal set/get functions have a name (property
58312 		 * name) but must not have a lexical name binding, see
58313 		 * test-bug-getset-func-name.js.
58314 		 */
58315 		DUK_DDD(DUK_DDDPRINT("function expression with a name -> set NAMEBINDING"));
58316 		DUK_HOBJECT_SET_NAMEBINDING((duk_hobject *) h_res);
58317 	}
58318 
58319 	if (func->is_strict) {
58320 		DUK_DDD(DUK_DDDPRINT("function is strict -> set STRICT"));
58321 		DUK_HOBJECT_SET_STRICT((duk_hobject *) h_res);
58322 	}
58323 
58324 	if (func->is_notail) {
58325 		DUK_DDD(DUK_DDDPRINT("function is notail -> set NOTAIL"));
58326 		DUK_HOBJECT_SET_NOTAIL((duk_hobject *) h_res);
58327 	}
58328 
58329 	/*
58330 	 *  Build function fixed size 'data' buffer, which contains bytecode,
58331 	 *  constants, and inner function references.
58332 	 *
58333 	 *  During the building phase 'data' is reachable but incomplete.
58334 	 *  Only incref's occur during building (no refzero or GC happens),
58335 	 *  so the building process is atomic.
58336 	 */
58337 
58338 	consts_count = duk_hobject_get_length(thr, func->h_consts);
58339 	funcs_count = duk_hobject_get_length(thr, func->h_funcs) / 3;
58340 	code_count = DUK_BW_GET_SIZE(thr, &func->bw_code) / sizeof(duk_compiler_instr);
58341 	code_size = code_count * sizeof(duk_instr_t);
58342 
58343 	data_size = consts_count * sizeof(duk_tval) +
58344 	            funcs_count * sizeof(duk_hobject *) +
58345 	            code_size;
58346 
58347 	DUK_DDD(DUK_DDDPRINT("consts_count=%ld, funcs_count=%ld, code_size=%ld -> "
58348 	                     "data_size=%ld*%ld + %ld*%ld + %ld = %ld",
58349 	                     (long) consts_count, (long) funcs_count, (long) code_size,
58350 	                     (long) consts_count, (long) sizeof(duk_tval),
58351 	                     (long) funcs_count, (long) sizeof(duk_hobject *),
58352 	                     (long) code_size, (long) data_size));
58353 
58354 	duk_push_fixed_buffer(ctx, data_size);
58355 	h_data = (duk_hbuffer_fixed *) duk_get_hbuffer(ctx, -1);
58356 	DUK_ASSERT(h_data != NULL);
58357 
58358 	DUK_HCOMPILEDFUNCTION_SET_DATA(thr->heap, h_res, (duk_hbuffer *) h_data);
58359 	DUK_HEAPHDR_INCREF(thr, h_data);
58360 
58361 	p_const = (duk_tval *) (void *) DUK_HBUFFER_FIXED_GET_DATA_PTR(thr->heap, h_data);
58362 	for (i = 0; i < consts_count; i++) {
58363 		DUK_ASSERT(i <= DUK_UARRIDX_MAX);  /* const limits */
58364 		tv = duk_hobject_find_existing_array_entry_tval_ptr(thr->heap, func->h_consts, (duk_uarridx_t) i);
58365 		DUK_ASSERT(tv != NULL);
58366 		DUK_TVAL_SET_TVAL(p_const, tv);
58367 		p_const++;
58368 		DUK_TVAL_INCREF(thr, tv);  /* may be a string constant */
58369 
58370 		DUK_DDD(DUK_DDDPRINT("constant: %!T", (duk_tval *) tv));
58371 	}
58372 
58373 	p_func = (duk_hobject **) p_const;
58374 	DUK_HCOMPILEDFUNCTION_SET_FUNCS(thr->heap, h_res, p_func);
58375 	for (i = 0; i < funcs_count; i++) {
58376 		duk_hobject *h;
58377 		DUK_ASSERT(i * 3 <= DUK_UARRIDX_MAX);  /* func limits */
58378 		tv = duk_hobject_find_existing_array_entry_tval_ptr(thr->heap, func->h_funcs, (duk_uarridx_t) (i * 3));
58379 		DUK_ASSERT(tv != NULL);
58380 		DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv));
58381 		h = DUK_TVAL_GET_OBJECT(tv);
58382 		DUK_ASSERT(h != NULL);
58383 		DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION(h));
58384 		*p_func++ = h;
58385 		DUK_HOBJECT_INCREF(thr, h);
58386 
58387 		DUK_DDD(DUK_DDDPRINT("inner function: %p -> %!iO",
58388 		                     (void *) h, (duk_heaphdr *) h));
58389 	}
58390 
58391 	p_instr = (duk_instr_t *) p_func;
58392 	DUK_HCOMPILEDFUNCTION_SET_BYTECODE(thr->heap, h_res, p_instr);
58393 
58394 	/* copy bytecode instructions one at a time */
58395 	q_instr = (duk_compiler_instr *) (void *) DUK_BW_GET_BASEPTR(thr, &func->bw_code);
58396 	for (i = 0; i < code_count; i++) {
58397 		p_instr[i] = q_instr[i].ins;
58398 	}
58399 	/* Note: 'q_instr' is still used below */
58400 
58401 	DUK_ASSERT((duk_uint8_t *) (p_instr + code_count) == DUK_HBUFFER_FIXED_GET_DATA_PTR(thr->heap, h_data) + data_size);
58402 
58403 	duk_pop(ctx);  /* 'data' (and everything in it) is reachable through h_res now */
58404 
58405 	/*
58406 	 *  Init object properties
58407 	 *
58408 	 *  Properties should be added in decreasing order of access frequency.
58409 	 *  (Not very critical for function templates.)
58410 	 */
58411 
58412 	DUK_DDD(DUK_DDDPRINT("init function properties"));
58413 
58414 	/* [ ... res ] */
58415 
58416 	/* _Varmap: omitted if function is guaranteed not to do slow path identifier
58417 	 * accesses or if it would turn out to be empty of actual register mappings
58418 	 * after a cleanup.  When debugging is enabled, we always need the varmap to
58419 	 * be able to lookup variables at any point.
58420 	 */
58421 #if defined(DUK_USE_DEBUGGER_SUPPORT)
58422 	if (1) {
58423 #else
58424 	if (func->id_access_slow ||     /* directly uses slow accesses */
58425 	    func->may_direct_eval ||    /* may indirectly slow access through a direct eval */
58426 	    funcs_count > 0) {          /* has inner functions which may slow access (XXX: this can be optimized by looking at the inner functions) */
58427 #endif
58428 		duk_int_t num_used;
58429 		duk_dup(ctx, func->varmap_idx);
58430 		num_used = duk__cleanup_varmap(comp_ctx);
58431 		DUK_DDD(DUK_DDDPRINT("cleaned up varmap: %!T (num_used=%ld)",
58432 		                     (duk_tval *) duk_get_tval(ctx, -1), (long) num_used));
58433 
58434 		if (num_used > 0) {
58435 			duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_VARMAP, DUK_PROPDESC_FLAGS_NONE);
58436 		} else {
58437 			DUK_DDD(DUK_DDDPRINT("varmap is empty after cleanup -> no need to add"));
58438 			duk_pop(ctx);
58439 		}
58440 	}
58441 
58442 	/* _Formals: omitted if function is guaranteed not to need a (non-strict) arguments object */
58443 	if (1) {
58444 		/* XXX: Add a proper condition.  If formals list is omitted, recheck
58445 		 * handling for 'length' in duk_js_push_closure(); it currently relies
58446 		 * on _Formals being set.  Removal may need to be conditional to debugging
58447 		 * being enabled/disabled too.
58448 		 */
58449 		duk_dup(ctx, func->argnames_idx);
58450 		duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_FORMALS, DUK_PROPDESC_FLAGS_NONE);
58451 	}
58452 
58453 	/* name */
58454 	if (func->h_name) {
58455 		duk_push_hstring(ctx, func->h_name);
58456 		duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_NONE);
58457 	}
58458 
58459 	/* _Source */
58460 #if defined(DUK_USE_NONSTD_FUNC_SOURCE_PROPERTY)
58461 	if (0) {
58462 		/* XXX: Currently function source code is not stored, as it is not
58463 		 * required by the standard.  Source code should not be stored by
58464 		 * default (user should enable it explicitly), and the source should
58465 		 * probably be compressed with a trivial text compressor; average
58466 		 * compression of 20-30% is quite easy to achieve even with a trivial
58467 		 * compressor (RLE + backwards lookup).
58468 		 *
58469 		 * Debugging needs source code to be useful: sometimes input code is
58470 		 * not found in files as it may be generated and then eval()'d, given
58471 		 * by dynamic C code, etc.
58472 		 *
58473 		 * Other issues:
58474 		 *
58475 		 *   - Need tokenizer indices for start and end to substring
58476 		 *   - Always normalize function declaration part?
58477 		 *   - If we keep _Formals, only need to store body
58478 		 */
58479 
58480 		/*
58481 		 *  For global or eval code this is straightforward.  For functions
58482 		 *  created with the Function constructor we only get the source for
58483 		 *  the body and must manufacture the "function ..." part.
58484 		 *
58485 		 *  For instance, for constructed functions (v8):
58486 		 *
58487 		 *    > a = new Function("foo", "bar", "print(foo)");
58488 		 *    [Function]
58489 		 *    > a.toString()
58490 		 *    'function anonymous(foo,bar) {\nprint(foo)\n}'
58491 		 *
58492 		 *  Similarly for e.g. getters (v8):
58493 		 *
58494 		 *    > x = { get a(foo,bar) { print(foo); } }
58495 		 *    { a: [Getter] }
58496 		 *    > Object.getOwnPropertyDescriptor(x, 'a').get.toString()
58497 		 *    'function a(foo,bar) { print(foo); }'
58498 		 */
58499 
58500 #if 0
58501 		duk_push_string(ctx, "XXX");
58502 		duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_SOURCE, DUK_PROPDESC_FLAGS_NONE);
58503 #endif
58504 	}
58505 #endif  /* DUK_USE_NONSTD_FUNC_SOURCE_PROPERTY */
58506 
58507 	/* _Pc2line */
58508 #if defined(DUK_USE_PC2LINE)
58509 	if (1) {
58510 		/*
58511 		 *  Size-optimized pc->line mapping.
58512 		 */
58513 
58514 		DUK_ASSERT(code_count <= DUK_COMPILER_MAX_BYTECODE_LENGTH);
58515 		duk_hobject_pc2line_pack(thr, q_instr, (duk_uint_fast32_t) code_count);  /* -> pushes fixed buffer */
58516 		duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_INT_PC2LINE, DUK_PROPDESC_FLAGS_NONE);
58517 
58518 		/* XXX: if assertions enabled, walk through all valid PCs
58519 		 * and check line mapping.
58520 		 */
58521 	}
58522 #endif  /* DUK_USE_PC2LINE */
58523 
58524 	/* fileName */
58525 	if (comp_ctx->h_filename) {
58526 		/*
58527 		 *  Source filename (or equivalent), for identifying thrown errors.
58528 		 */
58529 
58530 		duk_push_hstring(ctx, comp_ctx->h_filename);
58531 		duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_FILE_NAME, DUK_PROPDESC_FLAGS_NONE);
58532 	}
58533 
58534 	/*
58535 	 *  Init remaining result fields
58536 	 *
58537 	 *  'nregs' controls how large a register frame is allocated.
58538 	 *
58539 	 *  'nargs' controls how many formal arguments are written to registers:
58540 	 *  r0, ... r(nargs-1).  The remaining registers are initialized to
58541 	 *  undefined.
58542 	 */
58543 
58544 	DUK_ASSERT(func->temp_max >= 0);
58545 	h_res->nregs = (duk_uint16_t) func->temp_max;
58546 	h_res->nargs = (duk_uint16_t) duk_hobject_get_length(thr, func->h_argnames);
58547 	DUK_ASSERT(h_res->nregs >= h_res->nargs);  /* pass2 allocation handles this */
58548 #if defined(DUK_USE_DEBUGGER_SUPPORT)
58549 	h_res->start_line = (duk_uint32_t) func->min_line;
58550 	h_res->end_line = (duk_uint32_t) func->max_line;
58551 #endif
58552 
58553 	DUK_DD(DUK_DDPRINT("converted function: %!ixT",
58554 	                   (duk_tval *) duk_get_tval(ctx, -1)));
58555 
58556 	/*
58557 	 *  Compact the function template.
58558 	 */
58559 
58560 	duk_compact(ctx, -1);
58561 
58562 	/*
58563 	 *  Debug dumping
58564 	 */
58565 
58566 #ifdef DUK_USE_DDDPRINT
58567 	{
58568 		duk_hcompiledfunction *h;
58569 		duk_instr_t *p, *p_start, *p_end;
58570 
58571 		h = (duk_hcompiledfunction *) duk_get_hobject(ctx, -1);
58572 		p_start = (duk_instr_t *) DUK_HCOMPILEDFUNCTION_GET_CODE_BASE(thr->heap, h);
58573 		p_end = (duk_instr_t *) DUK_HCOMPILEDFUNCTION_GET_CODE_END(thr->heap, h);
58574 
58575 		p = p_start;
58576 		while (p < p_end) {
58577 			DUK_DDD(DUK_DDDPRINT("BC %04ld: %!I        ; 0x%08lx op=%ld (%!C) a=%ld b=%ld c=%ld",
58578 			                     (long) (p - p_start),
58579 			                     (duk_instr_t) (*p),
58580 			                     (unsigned long) (*p),
58581 			                     (long) DUK_DEC_OP(*p),
58582 			                     (long) DUK_DEC_OP(*p),
58583 			                     (long) DUK_DEC_A(*p),
58584 			                     (long) DUK_DEC_B(*p),
58585 			                     (long) DUK_DEC_C(*p)));
58586 			p++;
58587 		}
58588 	}
58589 #endif
58590 }
58591 
58592 /*
58593  *  Code emission helpers
58594  *
58595  *  Some emission helpers understand the range of target and source reg/const
58596  *  values and automatically emit shuffling code if necessary.  This is the
58597  *  case when the slot in question (A, B, C) is used in the standard way and
58598  *  for opcodes the emission helpers explicitly understand (like DUK_OP_CALL).
58599  *
58600  *  The standard way is that:
58601  *    - slot A is a target register
58602  *    - slot B is a source register/constant
58603  *    - slot C is a source register/constant
58604  *
58605  *  If a slot is used in a non-standard way the caller must indicate this
58606  *  somehow.  If a slot is used as a target instead of a source (or vice
58607  *  versa), this can be indicated with a flag to trigger proper shuffling
58608  *  (e.g. DUK__EMIT_FLAG_B_IS_TARGET).  If the value in the slot is not
58609  *  register/const related at all, the caller must ensure that the raw value
58610  *  fits into the corresponding slot so as to not trigger shuffling.  The
58611  *  caller must set a "no shuffle" flag to ensure compilation fails if
58612  *  shuffling were to be triggered because of an internal error.
58613  *
58614  *  For slots B and C the raw slot size is 9 bits but one bit is reserved for
58615  *  the reg/const indicator.  To use the full 9-bit range for a raw value,
58616  *  shuffling must be disabled with the DUK__EMIT_FLAG_NO_SHUFFLE_{B,C} flag.
58617  *  Shuffling is only done for A, B, and C slots, not the larger BC or ABC slots.
58618  *
58619  *  There is call handling specific understanding in the A-B-C emitter to
58620  *  convert call setup and call instructions into indirect ones if necessary.
58621  */
58622 
58623 /* Code emission flags, passed in the 'opcode' field.  Opcode + flags
58624  * fit into 16 bits for now, so use duk_small_uint.t.
58625  */
58626 #define DUK__EMIT_FLAG_NO_SHUFFLE_A      (1 << 8)
58627 #define DUK__EMIT_FLAG_NO_SHUFFLE_B      (1 << 9)
58628 #define DUK__EMIT_FLAG_NO_SHUFFLE_C      (1 << 10)
58629 #define DUK__EMIT_FLAG_A_IS_SOURCE       (1 << 11)  /* slot A is a source (default: target) */
58630 #define DUK__EMIT_FLAG_B_IS_TARGET       (1 << 12)  /* slot B is a target (default: source) */
58631 #define DUK__EMIT_FLAG_C_IS_TARGET       (1 << 13)  /* slot C is a target (default: source) */
58632 #define DUK__EMIT_FLAG_B_IS_TARGETSOURCE (1 << 14)  /* slot B is both a target and a source (used by extraops like DUK_EXTRAOP_INSTOF */
58633 #define DUK__EMIT_FLAG_RESERVE_JUMPSLOT  (1 << 15)  /* reserve a jumpslot after instr before target spilling, used for NEXTENUM */
58634 
58635 /* XXX: clarify on when and where DUK__CONST_MARKER is allowed */
58636 /* XXX: opcode specific assertions on when consts are allowed */
58637 
58638 /* XXX: macro smaller than call? */
58639 DUK_LOCAL duk_int_t duk__get_current_pc(duk_compiler_ctx *comp_ctx) {
58640 	duk_compiler_func *func;
58641 	func = &comp_ctx->curr_func;
58642 	return (duk_int_t) (DUK_BW_GET_SIZE(comp_ctx->thr, &func->bw_code) / sizeof(duk_compiler_instr));
58643 }
58644 
58645 DUK_LOCAL duk_compiler_instr *duk__get_instr_ptr(duk_compiler_ctx *comp_ctx, duk_int_t pc) {
58646 	DUK_ASSERT(pc >= 0);
58647 	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)));
58648 	return ((duk_compiler_instr *) (void *) DUK_BW_GET_BASEPTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code)) + pc;
58649 }
58650 
58651 /* emit instruction; could return PC but that's not needed in the majority
58652  * of cases.
58653  */
58654 DUK_LOCAL void duk__emit(duk_compiler_ctx *comp_ctx, duk_instr_t ins) {
58655 #if defined(DUK_USE_PC2LINE)
58656 	duk_int_t line;
58657 #endif
58658 	duk_compiler_instr *instr;
58659 
58660 	DUK_DDD(DUK_DDDPRINT("duk__emit: 0x%08lx curr_token.start_line=%ld prev_token.start_line=%ld pc=%ld --> %!I",
58661 	                     (unsigned long) ins,
58662 	                     (long) comp_ctx->curr_token.start_line,
58663 	                     (long) comp_ctx->prev_token.start_line,
58664 	                     (long) duk__get_current_pc(comp_ctx),
58665 	                     (duk_instr_t) ins));
58666 
58667 	instr = (duk_compiler_instr *) (void *) DUK_BW_ENSURE_GETPTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code, sizeof(duk_compiler_instr));
58668 	DUK_BW_ADD_PTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code, sizeof(duk_compiler_instr));
58669 
58670 #if defined(DUK_USE_PC2LINE)
58671 	/* The line number tracking is a bit inconsistent right now, which
58672 	 * affects debugger accuracy.  Mostly call sites emit opcodes when
58673 	 * they have parsed a token (say a terminating semicolon) and called
58674 	 * duk__advance().  In this case the line number of the previous
58675 	 * token is the most accurate one (except in prologue where
58676 	 * prev_token.start_line is 0).  This is probably not 100% correct
58677 	 * right now.
58678 	 */
58679 	/* approximation, close enough */
58680 	line = comp_ctx->prev_token.start_line;
58681 	if (line == 0) {
58682 		line = comp_ctx->curr_token.start_line;
58683 	}
58684 #endif
58685 
58686 	instr->ins = ins;
58687 #if defined(DUK_USE_PC2LINE)
58688 	instr->line = line;
58689 #endif
58690 #if defined(DUK_USE_DEBUGGER_SUPPORT)
58691 	if (line < comp_ctx->curr_func.min_line) {
58692 		comp_ctx->curr_func.min_line = line;
58693 	}
58694 	if (line > comp_ctx->curr_func.max_line) {
58695 		comp_ctx->curr_func.max_line = line;
58696 	}
58697 #endif
58698 
58699 	/* Limit checks for bytecode byte size and line number. */
58700 	if (DUK_UNLIKELY(DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) > DUK_USE_ESBC_MAX_BYTES)) {
58701 		goto fail_bc_limit;
58702 	}
58703 #if defined(DUK_USE_PC2LINE) && defined(DUK_USE_ESBC_LIMITS)
58704 #if defined(DUK_USE_BUFLEN16)
58705 	/* Buffer length is bounded to 0xffff automatically, avoid compile warning. */
58706 	if (DUK_UNLIKELY(line > DUK_USE_ESBC_MAX_LINENUMBER)) {
58707 		goto fail_bc_limit;
58708 	}
58709 #else
58710 	if (DUK_UNLIKELY(line > DUK_USE_ESBC_MAX_LINENUMBER)) {
58711 		goto fail_bc_limit;
58712 	}
58713 #endif
58714 #endif
58715 
58716 	return;
58717 
58718   fail_bc_limit:
58719 	DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_BYTECODE_LIMIT);
58720 }
58721 
58722 /* Update function min/max line from current token.  Needed to improve
58723  * function line range information for debugging, so that e.g. opening
58724  * curly brace is covered by line range even when no opcodes are emitted
58725  * for the line containing the brace.
58726  */
58727 DUK_LOCAL void duk__update_lineinfo_currtoken(duk_compiler_ctx *comp_ctx) {
58728 #if defined(DUK_USE_DEBUGGER_SUPPORT)
58729 	duk_int_t line;
58730 
58731 	line = comp_ctx->curr_token.start_line;
58732 	if (line == 0) {
58733 		return;
58734 	}
58735 	if (line < comp_ctx->curr_func.min_line) {
58736 		comp_ctx->curr_func.min_line = line;
58737 	}
58738 	if (line > comp_ctx->curr_func.max_line) {
58739 		comp_ctx->curr_func.max_line = line;
58740 	}
58741 #else
58742 	DUK_UNREF(comp_ctx);
58743 #endif
58744 }
58745 
58746 #if 0 /* unused */
58747 DUK_LOCAL void duk__emit_op_only(duk_compiler_ctx *comp_ctx, duk_small_uint_t op) {
58748 	duk__emit(comp_ctx, DUK_ENC_OP_ABC(op, 0));
58749 }
58750 #endif
58751 
58752 /* Important main primitive. */
58753 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) {
58754 	duk_instr_t ins = 0;
58755 	duk_int_t a_out = -1;
58756 	duk_int_t b_out = -1;
58757 	duk_int_t c_out = -1;
58758 	duk_int_t tmp;
58759 
58760 	DUK_DDD(DUK_DDDPRINT("emit: op_flags=%04lx, a=%ld, b=%ld, c=%ld",
58761 	                     (unsigned long) op_flags, (long) a, (long) b, (long) c));
58762 
58763 	/* We could rely on max temp/const checks: if they don't exceed BC
58764 	 * limit, nothing here can either (just asserts would be enough).
58765 	 * Currently we check for the limits, which provides additional
58766 	 * protection against creating invalid bytecode due to compiler
58767 	 * bugs.
58768 	 */
58769 
58770 	DUK_ASSERT_DISABLE((op_flags & 0xff) >= DUK_BC_OP_MIN);  /* unsigned */
58771 	DUK_ASSERT((op_flags & 0xff) <= DUK_BC_OP_MAX);
58772 
58773 	/* Input shuffling happens before the actual operation, while output
58774 	 * shuffling happens afterwards.  Output shuffling decisions are still
58775 	 * made at the same time to reduce branch clutter; output shuffle decisions
58776 	 * are recorded into X_out variables.
58777 	 */
58778 
58779 	/* Slot A */
58780 
58781 #if defined(DUK_USE_SHUFFLE_TORTURE)
58782 	if (a <= DUK_BC_A_MAX && (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_A)) {
58783 #else
58784 	if (a <= DUK_BC_A_MAX) {
58785 #endif
58786 		;
58787 	} else if (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_A) {
58788 		DUK_D(DUK_DPRINT("out of regs: 'a' (reg) needs shuffling but shuffle prohibited, a: %ld", (long) a));
58789 		goto error_outofregs;
58790 	} else if (a <= DUK_BC_BC_MAX) {
58791 		comp_ctx->curr_func.needs_shuffle = 1;
58792 		tmp = comp_ctx->curr_func.shuffle1;
58793 		if (op_flags & DUK__EMIT_FLAG_A_IS_SOURCE) {
58794 			duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDREG, tmp, a));
58795 		} else {
58796 			duk_small_int_t op = op_flags & 0xff;
58797 			if (op == DUK_OP_CSVAR || op == DUK_OP_CSREG || op == DUK_OP_CSPROP) {
58798 				/* Special handling for call setup instructions.  The target
58799 				 * is expressed indirectly, but there is no output shuffling.
58800 				 */
58801 				DUK_ASSERT((op_flags & DUK__EMIT_FLAG_A_IS_SOURCE) == 0);
58802 				duk__emit_load_int32_noshuffle(comp_ctx, tmp, a);
58803 				DUK_ASSERT(DUK_OP_CSVARI == DUK_OP_CSVAR + 1);
58804 				DUK_ASSERT(DUK_OP_CSREGI == DUK_OP_CSREG + 1);
58805 				DUK_ASSERT(DUK_OP_CSPROPI == DUK_OP_CSPROP + 1);
58806 				op_flags++;  /* indirect opcode follows direct */
58807 			} else {
58808 				/* Output shuffle needed after main operation */
58809 				a_out = a;
58810 			}
58811 		}
58812 		a = tmp;
58813 	} else {
58814 		DUK_D(DUK_DPRINT("out of regs: 'a' (reg) needs shuffling but does not fit into BC, a: %ld", (long) a));
58815 		goto error_outofregs;
58816 	}
58817 
58818 	/* Slot B */
58819 
58820 	if (b & DUK__CONST_MARKER) {
58821 		DUK_ASSERT((op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_B) == 0);
58822 		DUK_ASSERT((op_flags & DUK__EMIT_FLAG_B_IS_TARGET) == 0);
58823 		DUK_ASSERT((op_flags & 0xff) != DUK_OP_CALL);
58824 		DUK_ASSERT((op_flags & 0xff) != DUK_OP_NEW);
58825 		b = b & ~DUK__CONST_MARKER;
58826 #if defined(DUK_USE_SHUFFLE_TORTURE)
58827 		if (0) {
58828 #else
58829 		if (b <= 0xff) {
58830 #endif
58831 			ins |= DUK_ENC_OP_A_B_C(0, 0, 0x100, 0);  /* const flag for B */
58832 		} else if (b <= DUK_BC_BC_MAX) {
58833 			comp_ctx->curr_func.needs_shuffle = 1;
58834 			tmp = comp_ctx->curr_func.shuffle2;
58835 			duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDCONST, tmp, b));
58836 			b = tmp;
58837 		} else {
58838 			DUK_D(DUK_DPRINT("out of regs: 'b' (const) needs shuffling but does not fit into BC, b: %ld", (long) b));
58839 			goto error_outofregs;
58840 		}
58841 	} else {
58842 #if defined(DUK_USE_SHUFFLE_TORTURE)
58843 		if (b <= 0xff && (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_B)) {
58844 #else
58845 		if (b <= 0xff) {
58846 #endif
58847 			;
58848 		} else if (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_B) {
58849 			if (b > DUK_BC_B_MAX) {
58850 				/* Note: 0xff != DUK_BC_B_MAX */
58851 				DUK_D(DUK_DPRINT("out of regs: 'b' (reg) needs shuffling but shuffle prohibited, b: %ld", (long) b));
58852 				goto error_outofregs;
58853 			}
58854 		} else if (b <= DUK_BC_BC_MAX) {
58855 			comp_ctx->curr_func.needs_shuffle = 1;
58856 			tmp = comp_ctx->curr_func.shuffle2;
58857 			if (op_flags & DUK__EMIT_FLAG_B_IS_TARGET) {
58858 				/* Output shuffle needed after main operation */
58859 				b_out = b;
58860 			}
58861 			if (!(op_flags & DUK__EMIT_FLAG_B_IS_TARGET) || (op_flags & DUK__EMIT_FLAG_B_IS_TARGETSOURCE)) {
58862 				duk_small_int_t op = op_flags & 0xff;
58863 				if (op == DUK_OP_CALL || op == DUK_OP_NEW ||
58864 				    op == DUK_OP_MPUTOBJ || op == DUK_OP_MPUTARR) {
58865 					/* Special handling for CALL/NEW/MPUTOBJ/MPUTARR shuffling.
58866 					 * For each, slot B identifies the first register of a range
58867 					 * of registers, so normal shuffling won't work.  Instead,
58868 					 * an indirect version of the opcode is used.
58869 					 */
58870 					DUK_ASSERT((op_flags & DUK__EMIT_FLAG_B_IS_TARGET) == 0);
58871 					duk__emit_load_int32_noshuffle(comp_ctx, tmp, b);
58872 					DUK_ASSERT(DUK_OP_CALLI == DUK_OP_CALL + 1);
58873 					DUK_ASSERT(DUK_OP_NEWI == DUK_OP_NEW + 1);
58874 					DUK_ASSERT(DUK_OP_MPUTOBJI == DUK_OP_MPUTOBJ + 1);
58875 					DUK_ASSERT(DUK_OP_MPUTARRI == DUK_OP_MPUTARR + 1);
58876 					op_flags++;  /* indirect opcode follows direct */
58877 				} else {
58878 					duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDREG, tmp, b));
58879 				}
58880 			}
58881 			b = tmp;
58882 		} else {
58883 			DUK_D(DUK_DPRINT("out of regs: 'b' (reg) needs shuffling but does not fit into BC, b: %ld", (long) b));
58884 			goto error_outofregs;
58885 		}
58886 	}
58887 
58888 	/* Slot C */
58889 
58890 	if (c & DUK__CONST_MARKER) {
58891 		DUK_ASSERT((op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_C) == 0);
58892 		DUK_ASSERT((op_flags & DUK__EMIT_FLAG_C_IS_TARGET) == 0);
58893 		c = c & ~DUK__CONST_MARKER;
58894 #if defined(DUK_USE_SHUFFLE_TORTURE)
58895 		if (0) {
58896 #else
58897 		if (c <= 0xff) {
58898 #endif
58899 			ins |= DUK_ENC_OP_A_B_C(0, 0, 0, 0x100);  /* const flag for C */
58900 		} else if (c <= DUK_BC_BC_MAX) {
58901 			comp_ctx->curr_func.needs_shuffle = 1;
58902 			tmp = comp_ctx->curr_func.shuffle3;
58903 			duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDCONST, tmp, c));
58904 			c = tmp;
58905 		} else {
58906 			DUK_D(DUK_DPRINT("out of regs: 'c' (const) needs shuffling but does not fit into BC, c: %ld", (long) c));
58907 			goto error_outofregs;
58908 		}
58909 	} else {
58910 #if defined(DUK_USE_SHUFFLE_TORTURE)
58911 		if (c <= 0xff && (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_C)) {
58912 #else
58913 		if (c <= 0xff) {
58914 #endif
58915 			;
58916 		} else if (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_C) {
58917 			if (c > DUK_BC_C_MAX) {
58918 				/* Note: 0xff != DUK_BC_C_MAX */
58919 				DUK_D(DUK_DPRINT("out of regs: 'c' (reg) needs shuffling but shuffle prohibited, c: %ld", (long) c));
58920 				goto error_outofregs;
58921 			}
58922 		} else if (c <= DUK_BC_BC_MAX) {
58923 			comp_ctx->curr_func.needs_shuffle = 1;
58924 			tmp = comp_ctx->curr_func.shuffle3;
58925 			if (op_flags & DUK__EMIT_FLAG_C_IS_TARGET) {
58926 				/* Output shuffle needed after main operation */
58927 				c_out = c;
58928 			} else {
58929 				duk_small_int_t op = op_flags & 0xff;
58930 				if (op == DUK_OP_EXTRA &&
58931 				    (a == DUK_EXTRAOP_INITGET || a == DUK_EXTRAOP_INITSET)) {
58932 					/* Special shuffling for INITGET/INITSET, where slot C
58933 					 * identifies a register pair and cannot be shuffled
58934 					 * normally.  Use an indirect variant instead.
58935 					 */
58936 					DUK_ASSERT((op_flags & DUK__EMIT_FLAG_C_IS_TARGET) == 0);
58937 					duk__emit_load_int32_noshuffle(comp_ctx, tmp, c);
58938 					DUK_ASSERT(DUK_EXTRAOP_INITGETI == DUK_EXTRAOP_INITGET + 1);
58939 					DUK_ASSERT(DUK_EXTRAOP_INITSETI == DUK_EXTRAOP_INITSET + 1);
58940 					a++;  /* indirect opcode follows direct */
58941 				} else {
58942 					duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDREG, tmp, c));
58943 				}
58944 			}
58945 			c = tmp;
58946 		} else {
58947 			DUK_D(DUK_DPRINT("out of regs: 'c' (reg) needs shuffling but does not fit into BC, c: %ld", (long) c));
58948 			goto error_outofregs;
58949 		}
58950 	}
58951 
58952 	/* Main operation */
58953 
58954 	DUK_ASSERT_DISABLE(a >= DUK_BC_A_MIN);  /* unsigned */
58955 	DUK_ASSERT(a <= DUK_BC_A_MAX);
58956 	DUK_ASSERT_DISABLE(b >= DUK_BC_B_MIN);  /* unsigned */
58957 	DUK_ASSERT(b <= DUK_BC_B_MAX);
58958 	DUK_ASSERT_DISABLE(c >= DUK_BC_C_MIN);  /* unsigned */
58959 	DUK_ASSERT(c <= DUK_BC_C_MAX);
58960 
58961 	ins |= DUK_ENC_OP_A_B_C(op_flags & 0xff, a, b, c);
58962 	duk__emit(comp_ctx, ins);
58963 
58964 	/* NEXTENUM needs a jump slot right after the main instruction.
58965 	 * When the JUMP is taken, output spilling is not needed so this
58966 	 * workaround is possible.  The jump slot PC is exceptionally
58967 	 * plumbed through comp_ctx to minimize call sites.
58968 	 */
58969 	if (op_flags & DUK__EMIT_FLAG_RESERVE_JUMPSLOT) {
58970 		comp_ctx->emit_jumpslot_pc = duk__get_current_pc(comp_ctx);
58971 		duk__emit_abc(comp_ctx, DUK_OP_JUMP, 0);
58972 	}
58973 
58974 	/* Output shuffling: only one output register is realistically possible.
58975 	 *
58976 	 * (Zero would normally be an OK marker value: if the target register
58977 	 * was zero, it would never be shuffled.  But with DUK_USE_SHUFFLE_TORTURE
58978 	 * this is no longer true, so use -1 as a marker instead.)
58979 	 */
58980 
58981 	if (a_out >= 0) {
58982 		DUK_ASSERT(b_out < 0);
58983 		DUK_ASSERT(c_out < 0);
58984 		duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, a, a_out));
58985 	} else if (b_out >= 0) {
58986 		DUK_ASSERT(a_out < 0);
58987 		DUK_ASSERT(c_out < 0);
58988 		duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, b, b_out));
58989 	} else if (c_out >= 0) {
58990 		DUK_ASSERT(b_out < 0);
58991 		DUK_ASSERT(c_out < 0);
58992 		duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, c, c_out));
58993 	}
58994 
58995 	return;
58996 
58997  error_outofregs:
58998 	DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_REG_LIMIT);
58999 }
59000 
59001 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) {
59002 	duk__emit_a_b_c(comp_ctx, op_flags | DUK__EMIT_FLAG_NO_SHUFFLE_C, a, b, 0);
59003 }
59004 
59005 #if 0  /* unused */
59006 DUK_LOCAL void duk__emit_a(duk_compiler_ctx *comp_ctx, int op_flags, int a) {
59007 	duk__emit_a_b_c(comp_ctx, op_flags | DUK__EMIT_FLAG_NO_SHUFFLE_B | DUK__EMIT_FLAG_NO_SHUFFLE_C, a, 0, 0);
59008 }
59009 #endif
59010 
59011 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) {
59012 	duk_instr_t ins;
59013 	duk_int_t tmp;
59014 
59015 	/* allow caller to give a const number with the DUK__CONST_MARKER */
59016 	bc = bc & (~DUK__CONST_MARKER);
59017 
59018 	DUK_ASSERT_DISABLE((op_flags & 0xff) >= DUK_BC_OP_MIN);  /* unsigned */
59019 	DUK_ASSERT((op_flags & 0xff) <= DUK_BC_OP_MAX);
59020 	DUK_ASSERT_DISABLE(bc >= DUK_BC_BC_MIN);  /* unsigned */
59021 	DUK_ASSERT(bc <= DUK_BC_BC_MAX);
59022 	DUK_ASSERT((bc & DUK__CONST_MARKER) == 0);
59023 
59024 	if (bc <= DUK_BC_BC_MAX) {
59025 		;
59026 	} else {
59027 		/* No BC shuffling now. */
59028 		goto error_outofregs;
59029 	}
59030 
59031 #if defined(DUK_USE_SHUFFLE_TORTURE)
59032 	if (a <= DUK_BC_A_MAX && (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_A)) {
59033 #else
59034 	if (a <= DUK_BC_A_MAX) {
59035 #endif
59036 		ins = DUK_ENC_OP_A_BC(op_flags & 0xff, a, bc);
59037 		duk__emit(comp_ctx, ins);
59038 	} else if (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_A) {
59039 		goto error_outofregs;
59040 	} else if (a <= DUK_BC_BC_MAX) {
59041 		comp_ctx->curr_func.needs_shuffle = 1;
59042 		tmp = comp_ctx->curr_func.shuffle1;
59043 		ins = DUK_ENC_OP_A_BC(op_flags & 0xff, tmp, bc);
59044 		if (op_flags & DUK__EMIT_FLAG_A_IS_SOURCE) {
59045 			duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDREG, tmp, a));
59046 			duk__emit(comp_ctx, ins);
59047 		} else {
59048 			duk__emit(comp_ctx, ins);
59049 			duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, tmp, a));
59050 		}
59051 	} else {
59052 		goto error_outofregs;
59053 	}
59054 	return;
59055 
59056  error_outofregs:
59057 	DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_REG_LIMIT);
59058 }
59059 
59060 DUK_LOCAL void duk__emit_abc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op, duk_regconst_t abc) {
59061 	duk_instr_t ins;
59062 
59063 	DUK_ASSERT_DISABLE(op >= DUK_BC_OP_MIN);  /* unsigned */
59064 	DUK_ASSERT(op <= DUK_BC_OP_MAX);
59065 	DUK_ASSERT_DISABLE(abc >= DUK_BC_ABC_MIN);  /* unsigned */
59066 	DUK_ASSERT(abc <= DUK_BC_ABC_MAX);
59067 	DUK_ASSERT((abc & DUK__CONST_MARKER) == 0);
59068 
59069 	if (abc <= DUK_BC_ABC_MAX) {
59070 		;
59071 	} else {
59072 		goto error_outofregs;
59073 	}
59074 	ins = DUK_ENC_OP_ABC(op, abc);
59075 	DUK_DDD(DUK_DDDPRINT("duk__emit_abc: 0x%08lx line=%ld pc=%ld op=%ld (%!C) abc=%ld (%!I)",
59076 	                     (unsigned long) ins, (long) comp_ctx->curr_token.start_line,
59077 	                     (long) duk__get_current_pc(comp_ctx), (long) op, (long) op,
59078 	                     (long) abc, (duk_instr_t) ins));
59079 	duk__emit(comp_ctx, ins);
59080 	return;
59081 
59082  error_outofregs:
59083 	DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_REG_LIMIT);
59084 }
59085 
59086 DUK_LOCAL void duk__emit_extraop_b_c(duk_compiler_ctx *comp_ctx, duk_small_uint_t extraop_flags, duk_regconst_t b, duk_regconst_t c) {
59087 	DUK_ASSERT_DISABLE((extraop_flags & 0xff) >= DUK_BC_EXTRAOP_MIN);  /* unsigned */
59088 	DUK_ASSERT((extraop_flags & 0xff) <= DUK_BC_EXTRAOP_MAX);
59089 	/* Setting "no shuffle A" is covered by the assert, but it's needed
59090 	 * with DUK_USE_SHUFFLE_TORTURE.
59091 	 */
59092 	duk__emit_a_b_c(comp_ctx,
59093 	                DUK_OP_EXTRA | DUK__EMIT_FLAG_NO_SHUFFLE_A | (extraop_flags & ~0xff),  /* transfer flags */
59094 	                extraop_flags & 0xff,
59095 	                b,
59096 	                c);
59097 }
59098 
59099 DUK_LOCAL void duk__emit_extraop_b(duk_compiler_ctx *comp_ctx, duk_small_uint_t extraop_flags, duk_regconst_t b) {
59100 	DUK_ASSERT_DISABLE((extraop_flags & 0xff) >= DUK_BC_EXTRAOP_MIN);  /* unsigned */
59101 	DUK_ASSERT((extraop_flags & 0xff) <= DUK_BC_EXTRAOP_MAX);
59102 	/* Setting "no shuffle A" is covered by the assert, but it's needed
59103 	 * with DUK_USE_SHUFFLE_TORTURE.
59104 	 */
59105 	duk__emit_a_b_c(comp_ctx,
59106 	                DUK_OP_EXTRA | DUK__EMIT_FLAG_NO_SHUFFLE_A | (extraop_flags & ~0xff),  /* transfer flags */
59107 	                extraop_flags & 0xff,
59108 	                b,
59109 	                0);
59110 }
59111 
59112 DUK_LOCAL void duk__emit_extraop_bc(duk_compiler_ctx *comp_ctx, duk_small_uint_t extraop, duk_regconst_t bc) {
59113 	DUK_ASSERT_DISABLE(extraop >= DUK_BC_EXTRAOP_MIN);  /* unsigned */
59114 	DUK_ASSERT(extraop <= DUK_BC_EXTRAOP_MAX);
59115 	/* Setting "no shuffle A" is covered by the assert, but it's needed
59116 	 * with DUK_USE_SHUFFLE_TORTURE.
59117 	 */
59118 	duk__emit_a_bc(comp_ctx,
59119 	               DUK_OP_EXTRA | DUK__EMIT_FLAG_NO_SHUFFLE_A,
59120 	               extraop,
59121 	               bc);
59122 }
59123 
59124 DUK_LOCAL void duk__emit_extraop_only(duk_compiler_ctx *comp_ctx, duk_small_uint_t extraop_flags) {
59125 	DUK_ASSERT_DISABLE((extraop_flags & 0xff) >= DUK_BC_EXTRAOP_MIN);  /* unsigned */
59126 	DUK_ASSERT((extraop_flags & 0xff) <= DUK_BC_EXTRAOP_MAX);
59127 	/* Setting "no shuffle A" is covered by the assert, but it's needed
59128 	 * with DUK_USE_SHUFFLE_TORTURE.
59129 	 */
59130 	duk__emit_a_b_c(comp_ctx,
59131 	                DUK_OP_EXTRA | DUK__EMIT_FLAG_NO_SHUFFLE_A | DUK__EMIT_FLAG_NO_SHUFFLE_B |
59132 	                    DUK__EMIT_FLAG_NO_SHUFFLE_C | (extraop_flags & ~0xff),  /* transfer flags */
59133 	                extraop_flags & 0xff,
59134 	                0,
59135 	                0);
59136 }
59137 
59138 DUK_LOCAL void duk__emit_load_int32_raw(duk_compiler_ctx *comp_ctx, duk_reg_t reg, duk_int32_t val, duk_small_uint_t op_flags) {
59139 	/* XXX: Shuffling support could be implemented here so that LDINT+LDINTX
59140 	 * would only shuffle once (instead of twice).  The current code works
59141 	 * though, and has a smaller compiler footprint.
59142 	 */
59143 
59144 	if ((val >= (duk_int32_t) DUK_BC_BC_MIN - (duk_int32_t) DUK_BC_LDINT_BIAS) &&
59145 	    (val <= (duk_int32_t) DUK_BC_BC_MAX - (duk_int32_t) DUK_BC_LDINT_BIAS)) {
59146 		DUK_DDD(DUK_DDDPRINT("emit LDINT to reg %ld for %ld", (long) reg, (long) val));
59147 		duk__emit_a_bc(comp_ctx, DUK_OP_LDINT | op_flags, reg, (duk_regconst_t) (val + (duk_int32_t) DUK_BC_LDINT_BIAS));
59148 	} else {
59149 		duk_int32_t hi = val >> DUK_BC_LDINTX_SHIFT;
59150 		duk_int32_t lo = val & ((((duk_int32_t) 1) << DUK_BC_LDINTX_SHIFT) - 1);
59151 		DUK_ASSERT(lo >= 0);
59152 		DUK_DDD(DUK_DDDPRINT("emit LDINT+LDINTX to reg %ld for %ld -> hi %ld, lo %ld",
59153 		                     (long) reg, (long) val, (long) hi, (long) lo));
59154 		duk__emit_a_bc(comp_ctx, DUK_OP_LDINT | op_flags, reg, (duk_regconst_t) (hi + (duk_int32_t) DUK_BC_LDINT_BIAS));
59155 		duk__emit_a_bc(comp_ctx, DUK_OP_LDINTX | op_flags, reg, (duk_regconst_t) lo);
59156 	}
59157 }
59158 
59159 DUK_LOCAL void duk__emit_load_int32(duk_compiler_ctx *comp_ctx, duk_reg_t reg, duk_int32_t val) {
59160 	duk__emit_load_int32_raw(comp_ctx, reg, val, 0 /*op_flags*/);
59161 }
59162 
59163 #if defined(DUK_USE_SHUFFLE_TORTURE)
59164 /* Used by duk__emit*() calls so that we don't shuffle the loadints that
59165  * are needed to handle indirect opcodes.
59166  */
59167 DUK_LOCAL void duk__emit_load_int32_noshuffle(duk_compiler_ctx *comp_ctx, duk_reg_t reg, duk_int32_t val) {
59168 	duk__emit_load_int32_raw(comp_ctx, reg, val, DUK__EMIT_FLAG_NO_SHUFFLE_A /*op_flags*/);
59169 }
59170 #else
59171 DUK_LOCAL void duk__emit_load_int32_noshuffle(duk_compiler_ctx *comp_ctx, duk_reg_t reg, duk_int32_t val) {
59172 	/* When torture not enabled, can just use the same helper because
59173 	 * 'reg' won't get spilled.
59174 	 */
59175 	DUK_ASSERT(reg <= DUK_BC_A_MAX);
59176 	duk__emit_load_int32(comp_ctx, reg, val);
59177 }
59178 #endif
59179 
59180 DUK_LOCAL void duk__emit_jump(duk_compiler_ctx *comp_ctx, duk_int_t target_pc) {
59181 	duk_int_t curr_pc;
59182 	duk_int_t offset;
59183 
59184 	curr_pc = (duk_int_t) (DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) / sizeof(duk_compiler_instr));
59185 	offset = (duk_int_t) target_pc - (duk_int_t) curr_pc - 1;
59186 	DUK_ASSERT(offset + DUK_BC_JUMP_BIAS >= DUK_BC_ABC_MIN);
59187 	DUK_ASSERT(offset + DUK_BC_JUMP_BIAS <= DUK_BC_ABC_MAX);
59188 	duk__emit_abc(comp_ctx, DUK_OP_JUMP, (duk_regconst_t) (offset + DUK_BC_JUMP_BIAS));
59189 }
59190 
59191 DUK_LOCAL duk_int_t duk__emit_jump_empty(duk_compiler_ctx *comp_ctx) {
59192 	duk_int_t ret;
59193 
59194 	ret = duk__get_current_pc(comp_ctx);  /* useful for patching jumps later */
59195 	duk__emit_abc(comp_ctx, DUK_OP_JUMP, 0);
59196 	return ret;
59197 }
59198 
59199 /* Insert an empty jump in the middle of code emitted earlier.  This is
59200  * currently needed for compiling for-in.
59201  */
59202 DUK_LOCAL void duk__insert_jump_entry(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc) {
59203 #if defined(DUK_USE_PC2LINE)
59204 	duk_int_t line;
59205 #endif
59206 	duk_compiler_instr *instr;
59207 	duk_size_t offset;
59208 
59209 	offset = jump_pc * sizeof(duk_compiler_instr),
59210 	instr = (duk_compiler_instr *) (void *)
59211 	        DUK_BW_INSERT_ENSURE_AREA(comp_ctx->thr,
59212 	                                  &comp_ctx->curr_func.bw_code,
59213 	                                  offset,
59214 	                                  sizeof(duk_compiler_instr));
59215 
59216 #if defined(DUK_USE_PC2LINE)
59217 	line = comp_ctx->curr_token.start_line;  /* approximation, close enough */
59218 #endif
59219 	instr->ins = DUK_ENC_OP_ABC(DUK_OP_JUMP, 0);
59220 #if defined(DUK_USE_PC2LINE)
59221 	instr->line = line;
59222 #endif
59223 
59224 	DUK_BW_ADD_PTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code, sizeof(duk_compiler_instr));
59225 	if (DUK_UNLIKELY(DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) > DUK_USE_ESBC_MAX_BYTES)) {
59226 		goto fail_bc_limit;
59227 	}
59228 	return;
59229 
59230   fail_bc_limit:
59231 	DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_BYTECODE_LIMIT);
59232 }
59233 
59234 /* Does not assume that jump_pc contains a DUK_OP_JUMP previously; this is intentional
59235  * to allow e.g. an INVALID opcode be overwritten with a JUMP (label management uses this).
59236  */
59237 DUK_LOCAL void duk__patch_jump(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc, duk_int_t target_pc) {
59238 	duk_compiler_instr *instr;
59239 	duk_int_t offset;
59240 
59241 	/* allow negative PCs, behave as a no-op */
59242 	if (jump_pc < 0) {
59243 		DUK_DDD(DUK_DDDPRINT("duk__patch_jump(): nop call, jump_pc=%ld (<0), target_pc=%ld",
59244 		                     (long) jump_pc, (long) target_pc));
59245 		return;
59246 	}
59247 	DUK_ASSERT(jump_pc >= 0);
59248 
59249 	/* XXX: range assert */
59250 	instr = duk__get_instr_ptr(comp_ctx, jump_pc);
59251 	DUK_ASSERT(instr != NULL);
59252 
59253 	/* XXX: range assert */
59254 	offset = target_pc - jump_pc - 1;
59255 
59256 	instr->ins = DUK_ENC_OP_ABC(DUK_OP_JUMP, offset + DUK_BC_JUMP_BIAS);
59257 	DUK_DDD(DUK_DDDPRINT("duk__patch_jump(): jump_pc=%ld, target_pc=%ld, offset=%ld",
59258 	                     (long) jump_pc, (long) target_pc, (long) offset));
59259 }
59260 
59261 DUK_LOCAL void duk__patch_jump_here(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc) {
59262 	duk__patch_jump(comp_ctx, jump_pc, duk__get_current_pc(comp_ctx));
59263 }
59264 
59265 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) {
59266 	duk_compiler_instr *instr;
59267 
59268 	DUK_ASSERT((reg_catch & DUK__CONST_MARKER) == 0);
59269 
59270 	instr = duk__get_instr_ptr(comp_ctx, ldconst_pc);
59271 	DUK_ASSERT(DUK_DEC_OP(instr->ins) == DUK_OP_LDCONST);
59272 	DUK_ASSERT(instr != NULL);
59273 	if (const_varname & DUK__CONST_MARKER) {
59274 		/* Have a catch variable. */
59275 		const_varname = const_varname & (~DUK__CONST_MARKER);
59276 		if (reg_catch > DUK_BC_BC_MAX || const_varname > DUK_BC_BC_MAX) {
59277 			/* Catch attempts to use out-of-range reg/const.  Without this
59278 			 * check Duktape 0.12.0 could generate invalid code which caused
59279 			 * an assert failure on execution.  This error is triggered e.g.
59280 			 * for functions with a lot of constants and a try-catch statement.
59281 			 * Shuffling or opcode semantics change is needed to fix the issue.
59282 			 * See: test-bug-trycatch-many-constants.js.
59283 			 */
59284 			DUK_D(DUK_DPRINT("failed to patch trycatch: flags=%ld, reg_catch=%ld, const_varname=%ld (0x%08lx)",
59285 			                 (long) flags, (long) reg_catch, (long) const_varname, (long) const_varname));
59286 			DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_REG_LIMIT);
59287 		}
59288 		instr->ins |= DUK_ENC_OP_A_BC(0, 0, const_varname);
59289 	} else {
59290 		/* No catch variable, e.g. a try-finally; replace LDCONST with
59291 		 * NOP to avoid a bogus LDCONST.
59292 		 */
59293 		instr->ins = DUK_ENC_OP_A(DUK_OP_EXTRA, DUK_EXTRAOP_NOP);
59294 	}
59295 
59296 	instr = duk__get_instr_ptr(comp_ctx, trycatch_pc);
59297 	DUK_ASSERT(instr != NULL);
59298 	DUK_ASSERT_DISABLE(flags >= DUK_BC_A_MIN);
59299 	DUK_ASSERT(flags <= DUK_BC_A_MAX);
59300 	instr->ins = DUK_ENC_OP_A_BC(DUK_OP_TRYCATCH, flags, reg_catch);
59301 }
59302 
59303 DUK_LOCAL void duk__emit_if_false_skip(duk_compiler_ctx *comp_ctx, duk_regconst_t regconst) {
59304 	duk__emit_a_b_c(comp_ctx,
59305 	                DUK_OP_IF | DUK__EMIT_FLAG_NO_SHUFFLE_A | DUK__EMIT_FLAG_NO_SHUFFLE_C,
59306 	                0 /*false*/,
59307 	                regconst,
59308 	                0 /*unused*/);
59309 }
59310 
59311 DUK_LOCAL void duk__emit_if_true_skip(duk_compiler_ctx *comp_ctx, duk_regconst_t regconst) {
59312 	duk__emit_a_b_c(comp_ctx,
59313 	                DUK_OP_IF | DUK__EMIT_FLAG_NO_SHUFFLE_A | DUK__EMIT_FLAG_NO_SHUFFLE_C,
59314 	                1 /*true*/,
59315 	                regconst,
59316 	                0 /*unused*/);
59317 }
59318 
59319 DUK_LOCAL void duk__emit_invalid(duk_compiler_ctx *comp_ctx) {
59320 	duk__emit_extraop_bc(comp_ctx, DUK_EXTRAOP_INVALID, 0);
59321 }
59322 
59323 /*
59324  *  Peephole optimizer for finished bytecode.
59325  *
59326  *  Does not remove opcodes; currently only straightens out unconditional
59327  *  jump chains which are generated by several control structures.
59328  */
59329 
59330 DUK_LOCAL void duk__peephole_optimize_bytecode(duk_compiler_ctx *comp_ctx) {
59331 	duk_compiler_instr *bc;
59332 	duk_small_uint_t iter;
59333 	duk_int_t i, n;
59334 	duk_int_t count_opt;
59335 
59336 	bc = (duk_compiler_instr *) (void *) DUK_BW_GET_BASEPTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code);
59337 #if defined(DUK_USE_BUFLEN16)
59338 	/* No need to assert, buffer size maximum is 0xffff. */
59339 #else
59340 	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 */
59341 #endif
59342 	n = (duk_int_t) (DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) / sizeof(duk_compiler_instr));
59343 
59344 	for (iter = 0; iter < DUK_COMPILER_PEEPHOLE_MAXITER; iter++) {
59345 		count_opt = 0;
59346 
59347 		for (i = 0; i < n; i++) {
59348 			duk_instr_t ins;
59349 			duk_int_t target_pc1;
59350 			duk_int_t target_pc2;
59351 
59352 			ins = bc[i].ins;
59353 			if (DUK_DEC_OP(ins) != DUK_OP_JUMP) {
59354 				continue;
59355 			}
59356 
59357 			target_pc1 = i + 1 + DUK_DEC_ABC(ins) - DUK_BC_JUMP_BIAS;
59358 			DUK_DDD(DUK_DDDPRINT("consider jump at pc %ld; target_pc=%ld", (long) i, (long) target_pc1));
59359 			DUK_ASSERT(target_pc1 >= 0);
59360 			DUK_ASSERT(target_pc1 < n);
59361 
59362 			/* Note: if target_pc1 == i, we'll optimize a jump to itself.
59363 			 * This does not need to be checked for explicitly; the case
59364 			 * is rare and max iter breaks us out.
59365 			 */
59366 
59367 			ins = bc[target_pc1].ins;
59368 			if (DUK_DEC_OP(ins) != DUK_OP_JUMP) {
59369 				continue;
59370 			}
59371 
59372 			target_pc2 = target_pc1 + 1 + DUK_DEC_ABC(ins) - DUK_BC_JUMP_BIAS;
59373 
59374 			DUK_DDD(DUK_DDDPRINT("optimizing jump at pc %ld; old target is %ld -> new target is %ld",
59375 			                     (long) i, (long) target_pc1, (long) target_pc2));
59376 
59377 			bc[i].ins = DUK_ENC_OP_ABC(DUK_OP_JUMP, target_pc2 - (i + 1) + DUK_BC_JUMP_BIAS);
59378 
59379 			count_opt++;
59380 		}
59381 
59382 		DUK_DD(DUK_DDPRINT("optimized %ld jumps on peephole round %ld", (long) count_opt, (long) (iter + 1)));
59383 
59384 		if (count_opt == 0) {
59385 			break;
59386 		}
59387 	}
59388 }
59389 
59390 /*
59391  *  Intermediate value helpers
59392  */
59393 
59394 #define DUK__ISREG(comp_ctx,x)              (((x) & DUK__CONST_MARKER) == 0)
59395 #define DUK__ISCONST(comp_ctx,x)            (((x) & DUK__CONST_MARKER) != 0)
59396 #define DUK__ISTEMP(comp_ctx,x)             (DUK__ISREG((comp_ctx), (x)) && (duk_regconst_t) (x) >= (duk_regconst_t) ((comp_ctx)->curr_func.temp_first))
59397 #define DUK__GETTEMP(comp_ctx)              ((comp_ctx)->curr_func.temp_next)
59398 #define DUK__SETTEMP(comp_ctx,x)            ((comp_ctx)->curr_func.temp_next = (x))  /* dangerous: must only lower (temp_max not updated) */
59399 #define DUK__SETTEMP_CHECKMAX(comp_ctx,x)   duk__settemp_checkmax((comp_ctx),(x))
59400 #define DUK__ALLOCTEMP(comp_ctx)            duk__alloctemp((comp_ctx))
59401 #define DUK__ALLOCTEMPS(comp_ctx,count)     duk__alloctemps((comp_ctx),(count))
59402 
59403 /* Flags for intermediate value coercions.  A flag for using a forced reg
59404  * is not needed, the forced_reg argument suffices and generates better
59405  * code (it is checked as it is used).
59406  */
59407 #define DUK__IVAL_FLAG_ALLOW_CONST          (1 << 0)  /* allow a constant to be returned */
59408 #define DUK__IVAL_FLAG_REQUIRE_TEMP         (1 << 1)  /* require a (mutable) temporary as a result (or a const if allowed) */
59409 #define DUK__IVAL_FLAG_REQUIRE_SHORT        (1 << 2)  /* require a short (8-bit) reg/const which fits into bytecode B/C slot */
59410 
59411 /* XXX: some code might benefit from DUK__SETTEMP_IFTEMP(ctx,x) */
59412 
59413 #if 0  /* enable manually for dumping */
59414 #define DUK__DUMP_ISPEC(compctx,ispec) do { duk__dump_ispec((compctx), (ispec)); } while (0)
59415 #define DUK__DUMP_IVALUE(compctx,ivalue) do { duk__dump_ivalue((compctx), (ivalue)); } while (0)
59416 
59417 DUK_LOCAL void duk__dump_ispec(duk_compiler_ctx *comp_ctx, duk_ispec *x) {
59418 	DUK_D(DUK_DPRINT("ispec dump: t=%ld regconst=0x%08lx, valstack_idx=%ld, value=%!T",
59419 	                 (long) x->t, (unsigned long) x->regconst, (long) x->valstack_idx,
59420 	                 duk_get_tval((duk_context *) comp_ctx->thr, x->valstack_idx)));
59421 }
59422 DUK_LOCAL void duk__dump_ivalue(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
59423 	DUK_D(DUK_DPRINT("ivalue dump: t=%ld op=%ld "
59424 	                 "x1={t=%ld regconst=0x%08lx valstack_idx=%ld value=%!T} "
59425 	                 "x2={t=%ld regconst=0x%08lx valstack_idx=%ld value=%!T}",
59426 		         (long) x->t, (long) x->op,
59427 	                 (long) x->x1.t, (unsigned long) x->x1.regconst, (long) x->x1.valstack_idx,
59428 	                 duk_get_tval((duk_context *) comp_ctx->thr, x->x1.valstack_idx),
59429 	                 (long) x->x2.t, (unsigned long) x->x2.regconst, (long) x->x2.valstack_idx,
59430 	                 duk_get_tval((duk_context *) comp_ctx->thr, x->x2.valstack_idx)));
59431 }
59432 #else
59433 #define DUK__DUMP_ISPEC(comp_ctx,x) do {} while (0)
59434 #define DUK__DUMP_IVALUE(comp_ctx,x) do {} while (0)
59435 #endif
59436 
59437 DUK_LOCAL void duk__copy_ispec(duk_compiler_ctx *comp_ctx, duk_ispec *src, duk_ispec *dst) {
59438 	duk_context *ctx = (duk_context *) comp_ctx->thr;
59439 
59440 	dst->t = src->t;
59441 	dst->regconst = src->regconst;
59442 	duk_copy(ctx, src->valstack_idx, dst->valstack_idx);
59443 }
59444 
59445 DUK_LOCAL void duk__copy_ivalue(duk_compiler_ctx *comp_ctx, duk_ivalue *src, duk_ivalue *dst) {
59446 	duk_context *ctx = (duk_context *) comp_ctx->thr;
59447 
59448 	dst->t = src->t;
59449 	dst->op = src->op;
59450 	dst->x1.t = src->x1.t;
59451 	dst->x1.regconst = src->x1.regconst;
59452 	dst->x2.t = src->x2.t;
59453 	dst->x2.regconst = src->x2.regconst;
59454 	duk_copy(ctx, src->x1.valstack_idx, dst->x1.valstack_idx);
59455 	duk_copy(ctx, src->x2.valstack_idx, dst->x2.valstack_idx);
59456 }
59457 
59458 /* XXX: to util */
59459 DUK_LOCAL duk_bool_t duk__is_whole_get_int32(duk_double_t x, duk_int32_t *ival) {
59460 	duk_small_int_t c;
59461 	duk_int32_t t;
59462 
59463 	c = DUK_FPCLASSIFY(x);
59464 	if (c == DUK_FP_NORMAL || (c == DUK_FP_ZERO && !DUK_SIGNBIT(x))) {
59465 		/* Don't allow negative zero as it will cause trouble with
59466 		 * LDINT+LDINTX.  But positive zero is OK.
59467 		 */
59468 		t = (duk_int32_t) x;
59469 		if ((duk_double_t) t == x) {
59470 			*ival = t;
59471 			return 1;
59472 		}
59473 	}
59474 
59475 	return 0;
59476 }
59477 
59478 DUK_LOCAL duk_reg_t duk__alloctemps(duk_compiler_ctx *comp_ctx, duk_small_int_t num) {
59479 	duk_reg_t res;
59480 
59481 	res = comp_ctx->curr_func.temp_next;
59482 	comp_ctx->curr_func.temp_next += num;
59483 
59484 	if (comp_ctx->curr_func.temp_next > DUK__MAX_TEMPS) {  /* == DUK__MAX_TEMPS is OK */
59485 		DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_TEMP_LIMIT);
59486 	}
59487 
59488 	/* maintain highest 'used' temporary, needed to figure out nregs of function */
59489 	if (comp_ctx->curr_func.temp_next > comp_ctx->curr_func.temp_max) {
59490 		comp_ctx->curr_func.temp_max = comp_ctx->curr_func.temp_next;
59491 	}
59492 
59493 	return res;
59494 }
59495 
59496 DUK_LOCAL duk_reg_t duk__alloctemp(duk_compiler_ctx *comp_ctx) {
59497 	return duk__alloctemps(comp_ctx, 1);
59498 }
59499 
59500 DUK_LOCAL void duk__settemp_checkmax(duk_compiler_ctx *comp_ctx, duk_reg_t temp_next) {
59501 	comp_ctx->curr_func.temp_next = temp_next;
59502 	if (temp_next > comp_ctx->curr_func.temp_max) {
59503 		comp_ctx->curr_func.temp_max = temp_next;
59504 	}
59505 }
59506 
59507 /* get const for value at valstack top */
59508 DUK_LOCAL duk_regconst_t duk__getconst(duk_compiler_ctx *comp_ctx) {
59509 	duk_hthread *thr = comp_ctx->thr;
59510 	duk_context *ctx = (duk_context *) thr;
59511 	duk_compiler_func *f = &comp_ctx->curr_func;
59512 	duk_tval *tv1;
59513 	duk_int_t i, n, n_check;
59514 
59515 	n = (duk_int_t) duk_get_length(ctx, f->consts_idx);
59516 
59517 	tv1 = DUK_GET_TVAL_NEGIDX(ctx, -1);
59518 	DUK_ASSERT(tv1 != NULL);
59519 
59520 #if defined(DUK_USE_FASTINT)
59521 	/* Explicit check for fastint downgrade. */
59522 	DUK_TVAL_CHKFAST_INPLACE(tv1);
59523 #endif
59524 
59525 	/* Sanity workaround for handling functions with a large number of
59526 	 * constants at least somewhat reasonably.  Otherwise checking whether
59527 	 * we already have the constant would grow very slow (as it is O(N^2)).
59528 	 */
59529 	n_check = (n > DUK__GETCONST_MAX_CONSTS_CHECK ? DUK__GETCONST_MAX_CONSTS_CHECK : n);
59530 	for (i = 0; i < n_check; i++) {
59531 		duk_tval *tv2 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, f->h_consts, i);
59532 
59533 		/* Strict equality is NOT enough, because we cannot use the same
59534 		 * constant for e.g. +0 and -0.
59535 		 */
59536 		if (duk_js_samevalue(tv1, tv2)) {
59537 			DUK_DDD(DUK_DDDPRINT("reused existing constant for %!T -> const index %ld",
59538 			                     (duk_tval *) tv1, (long) i));
59539 			duk_pop(ctx);
59540 			return (duk_regconst_t) (i | DUK__CONST_MARKER);
59541 		}
59542 	}
59543 
59544 	if (n > DUK__MAX_CONSTS) {
59545 		DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_CONST_LIMIT);
59546 	}
59547 
59548 	DUK_DDD(DUK_DDDPRINT("allocating new constant for %!T -> const index %ld",
59549 	                     (duk_tval *) tv1, (long) n));
59550 	(void) duk_put_prop_index(ctx, f->consts_idx, n);  /* invalidates tv1, tv2 */
59551 	return (duk_regconst_t) (n | DUK__CONST_MARKER);
59552 }
59553 
59554 /* Get the value represented by an duk_ispec to a register or constant.
59555  * The caller can control the result by indicating whether or not:
59556  *
59557  *   (1) a constant is allowed (sometimes the caller needs the result to
59558  *       be in a register)
59559  *
59560  *   (2) a temporary register is required (usually when caller requires
59561  *       the register to be safely mutable; normally either a bound
59562  *       register or a temporary register are both OK)
59563  *
59564  *   (3) a forced register target needs to be used
59565  *
59566  * Bytecode may be emitted to generate the necessary value.  The return
59567  * value is either a register or a constant.
59568  */
59569 
59570 DUK_LOCAL
59571 duk_regconst_t duk__ispec_toregconst_raw(duk_compiler_ctx *comp_ctx,
59572                                          duk_ispec *x,
59573                                          duk_reg_t forced_reg,
59574                                          duk_small_uint_t flags) {
59575 	duk_hthread *thr = comp_ctx->thr;
59576 	duk_context *ctx = (duk_context *) thr;
59577 
59578 	DUK_DDD(DUK_DDDPRINT("duk__ispec_toregconst_raw(): x={%ld:%ld:%!T}, "
59579 	                     "forced_reg=%ld, flags 0x%08lx: allow_const=%ld require_temp=%ld require_short=%ld",
59580 	                     (long) x->t,
59581 	                     (long) x->regconst,
59582 	                     (duk_tval *) duk_get_tval(ctx, x->valstack_idx),
59583 	                     (long) forced_reg,
59584 	                     (unsigned long) flags,
59585 	                     (long) ((flags & DUK__IVAL_FLAG_ALLOW_CONST) ? 1 : 0),
59586 	                     (long) ((flags & DUK__IVAL_FLAG_REQUIRE_TEMP) ? 1 : 0),
59587 	                     (long) ((flags & DUK__IVAL_FLAG_REQUIRE_SHORT) ? 1 : 0)));
59588 
59589 	switch (x->t) {
59590 	case DUK_ISPEC_VALUE: {
59591 		duk_tval *tv;
59592 
59593 		tv = DUK_GET_TVAL_POSIDX(ctx, x->valstack_idx);
59594 		DUK_ASSERT(tv != NULL);
59595 
59596 		switch (DUK_TVAL_GET_TAG(tv)) {
59597 		case DUK_TAG_UNDEFINED: {
59598 			/* Note: although there is no 'undefined' literal, undefined
59599 			 * values can occur during compilation as a result of e.g.
59600 			 * the 'void' operator.
59601 			 */
59602 			duk_reg_t dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
59603 			duk__emit_extraop_bc(comp_ctx, DUK_EXTRAOP_LDUNDEF, (duk_regconst_t) dest);
59604 			return (duk_regconst_t) dest;
59605 		}
59606 		case DUK_TAG_NULL: {
59607 			duk_reg_t dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
59608 			duk__emit_extraop_bc(comp_ctx, DUK_EXTRAOP_LDNULL, (duk_regconst_t) dest);
59609 			return (duk_regconst_t) dest;
59610 		}
59611 		case DUK_TAG_BOOLEAN: {
59612 			duk_reg_t dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
59613 			duk__emit_extraop_bc(comp_ctx,
59614 			                     (DUK_TVAL_GET_BOOLEAN(tv) ? DUK_EXTRAOP_LDTRUE : DUK_EXTRAOP_LDFALSE),
59615 			                     (duk_regconst_t) dest);
59616 			return (duk_regconst_t) dest;
59617 		}
59618 		case DUK_TAG_POINTER: {
59619 			DUK_UNREACHABLE();
59620 			break;
59621 		}
59622 		case DUK_TAG_STRING: {
59623 			duk_hstring *h;
59624 			duk_reg_t dest;
59625 			duk_regconst_t constidx;
59626 
59627 			h = DUK_TVAL_GET_STRING(tv);
59628 			DUK_UNREF(h);
59629 			DUK_ASSERT(h != NULL);
59630 
59631 #if 0  /* XXX: to be implemented? */
59632 			/* Use special opcodes to load short strings */
59633 			if (DUK_HSTRING_GET_BYTELEN(h) <= 2) {
59634 				/* Encode into a single opcode (18 bits can encode 1-2 bytes + length indicator) */
59635 			} else if (DUK_HSTRING_GET_BYTELEN(h) <= 6) {
59636 				/* Encode into a double constant (53 bits can encode 6*8 = 48 bits + 3-bit length */
59637 			}
59638 #endif
59639 			duk_dup(ctx, x->valstack_idx);
59640 			constidx = duk__getconst(comp_ctx);
59641 
59642 			if (flags & DUK__IVAL_FLAG_ALLOW_CONST) {
59643 				return constidx;
59644 			}
59645 
59646 			dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
59647 			duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, (duk_regconst_t) dest, constidx);
59648 			return (duk_regconst_t) dest;
59649 		}
59650 		case DUK_TAG_OBJECT: {
59651 			DUK_UNREACHABLE();
59652 			break;
59653 		}
59654 		case DUK_TAG_BUFFER: {
59655 			DUK_UNREACHABLE();
59656 			break;
59657 		}
59658 		case DUK_TAG_LIGHTFUNC: {
59659 			DUK_UNREACHABLE();
59660 			break;
59661 		}
59662 #if defined(DUK_USE_FASTINT)
59663 		case DUK_TAG_FASTINT:
59664 #endif
59665 		default: {
59666 			/* number */
59667 			duk_reg_t dest;
59668 			duk_regconst_t constidx;
59669 			duk_double_t dval;
59670 			duk_int32_t ival;
59671 
59672 			DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
59673 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
59674 			dval = DUK_TVAL_GET_NUMBER(tv);
59675 
59676 			if (!(flags & DUK__IVAL_FLAG_ALLOW_CONST)) {
59677 				/* A number can be loaded either through a constant, using
59678 				 * LDINT, or using LDINT+LDINTX.  LDINT is always a size win,
59679 				 * LDINT+LDINTX is not if the constant is used multiple times.
59680 				 * Currently always prefer LDINT+LDINTX over a double constant.
59681 				 */
59682 
59683 				if (duk__is_whole_get_int32(dval, &ival)) {
59684 					dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
59685 					duk__emit_load_int32(comp_ctx, dest, ival);
59686 					return (duk_regconst_t) dest;
59687 				}
59688 			}
59689 
59690 			duk_dup(ctx, x->valstack_idx);
59691 			constidx = duk__getconst(comp_ctx);
59692 
59693 			if (flags & DUK__IVAL_FLAG_ALLOW_CONST) {
59694 				return constidx;
59695 			} else {
59696 				dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
59697 				duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, (duk_regconst_t) dest, constidx);
59698 				return (duk_regconst_t) dest;
59699 			}
59700 		}
59701 		}  /* end switch */
59702 	}
59703 	case DUK_ISPEC_REGCONST: {
59704 		if (forced_reg >= 0) {
59705 			if (x->regconst & DUK__CONST_MARKER) {
59706 				duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, forced_reg, x->regconst);
59707 			} else if (x->regconst != (duk_regconst_t) forced_reg) {
59708 				duk__emit_a_bc(comp_ctx, DUK_OP_LDREG, forced_reg, x->regconst);
59709 			} else {
59710 				; /* already in correct reg */
59711 			}
59712 			return (duk_regconst_t) forced_reg;
59713 		}
59714 
59715 		DUK_ASSERT(forced_reg < 0);
59716 		if (x->regconst & DUK__CONST_MARKER) {
59717 			if (!(flags & DUK__IVAL_FLAG_ALLOW_CONST)) {
59718 				duk_reg_t dest = DUK__ALLOCTEMP(comp_ctx);
59719 				duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, (duk_regconst_t) dest, x->regconst);
59720 				return (duk_regconst_t) dest;
59721 			}
59722 			return x->regconst;
59723 		}
59724 
59725 		DUK_ASSERT(forced_reg < 0 && !(x->regconst & DUK__CONST_MARKER));
59726 		if ((flags & DUK__IVAL_FLAG_REQUIRE_TEMP) && !DUK__ISTEMP(comp_ctx, x->regconst)) {
59727 			duk_reg_t dest = DUK__ALLOCTEMP(comp_ctx);
59728 			duk__emit_a_bc(comp_ctx, DUK_OP_LDREG, (duk_regconst_t) dest, x->regconst);
59729 			return (duk_regconst_t) dest;
59730 		}
59731 		return x->regconst;
59732 	}
59733 	default: {
59734 		break;
59735 	}
59736 	}
59737 
59738 	DUK_ERROR_INTERNAL_DEFMSG(thr);
59739 	return 0;
59740 }
59741 
59742 DUK_LOCAL void duk__ispec_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ispec *x, duk_reg_t forced_reg) {
59743 	DUK_ASSERT(forced_reg >= 0);
59744 	(void) duk__ispec_toregconst_raw(comp_ctx, x, forced_reg, 0 /*flags*/);
59745 }
59746 
59747 /* Coerce an duk_ivalue to a 'plain' value by generating the necessary
59748  * arithmetic operations, property access, or variable access bytecode.
59749  * The duk_ivalue argument ('x') is converted into a plain value as a
59750  * side effect.
59751  */
59752 DUK_LOCAL void duk__ivalue_toplain_raw(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_reg_t forced_reg) {
59753 	duk_hthread *thr = comp_ctx->thr;
59754 	duk_context *ctx = (duk_context *) thr;
59755 
59756 	DUK_DDD(DUK_DDDPRINT("duk__ivalue_toplain_raw(): x={t=%ld,op=%ld,x1={%ld:%ld:%!T},x2={%ld:%ld:%!T}}, "
59757 	                     "forced_reg=%ld",
59758 	                     (long) x->t, (long) x->op,
59759 	                     (long) x->x1.t, (long) x->x1.regconst,
59760 	                     (duk_tval *) duk_get_tval(ctx, x->x1.valstack_idx),
59761 	                     (long) x->x2.t, (long) x->x2.regconst,
59762 	                     (duk_tval *) duk_get_tval(ctx, x->x2.valstack_idx),
59763 	                     (long) forced_reg));
59764 
59765 	switch (x->t) {
59766 	case DUK_IVAL_PLAIN: {
59767 		return;
59768 	}
59769 	/* XXX: support unary arithmetic ivalues (useful?) */
59770 	case DUK_IVAL_ARITH:
59771 	case DUK_IVAL_ARITH_EXTRAOP: {
59772 		duk_regconst_t arg1;
59773 		duk_regconst_t arg2;
59774 		duk_reg_t dest;
59775 		duk_tval *tv1;
59776 		duk_tval *tv2;
59777 
59778 		DUK_DDD(DUK_DDDPRINT("arith to plain conversion"));
59779 
59780 		/* inline arithmetic check for constant values */
59781 		/* XXX: use the exactly same arithmetic function here as in executor */
59782 		if (x->x1.t == DUK_ISPEC_VALUE && x->x2.t == DUK_ISPEC_VALUE && x->t == DUK_IVAL_ARITH) {
59783 			tv1 = DUK_GET_TVAL_POSIDX(ctx, x->x1.valstack_idx);
59784 			tv2 = DUK_GET_TVAL_POSIDX(ctx, x->x2.valstack_idx);
59785 			DUK_ASSERT(tv1 != NULL);
59786 			DUK_ASSERT(tv2 != NULL);
59787 
59788 			DUK_DDD(DUK_DDDPRINT("arith: tv1=%!T, tv2=%!T",
59789 			                     (duk_tval *) tv1,
59790 			                     (duk_tval *) tv2));
59791 
59792 			if (DUK_TVAL_IS_NUMBER(tv1) && DUK_TVAL_IS_NUMBER(tv2)) {
59793 				duk_double_t d1 = DUK_TVAL_GET_NUMBER(tv1);
59794 				duk_double_t d2 = DUK_TVAL_GET_NUMBER(tv2);
59795 				duk_double_t d3;
59796 				duk_bool_t accept = 1;
59797 
59798 				DUK_DDD(DUK_DDDPRINT("arith inline check: d1=%lf, d2=%lf, op=%ld",
59799 				                     (double) d1, (double) d2, (long) x->op));
59800 				switch (x->op) {
59801 				case DUK_OP_ADD:  d3 = d1 + d2; break;
59802 				case DUK_OP_SUB:  d3 = d1 - d2; break;
59803 				case DUK_OP_MUL:  d3 = d1 * d2; break;
59804 				case DUK_OP_DIV:  d3 = d1 / d2; break;
59805 				default:          accept = 0; break;
59806 				}
59807 
59808 				if (accept) {
59809 					duk_double_union du;
59810 					du.d = d3;
59811 					DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);
59812 					d3 = du.d;
59813 
59814 					x->t = DUK_IVAL_PLAIN;
59815 					DUK_ASSERT(x->x1.t == DUK_ISPEC_VALUE);
59816 					DUK_TVAL_SET_NUMBER(tv1, d3);  /* old value is number: no refcount */
59817 					return;
59818 				}
59819 			} else if (x->op == DUK_OP_ADD && DUK_TVAL_IS_STRING(tv1) && DUK_TVAL_IS_STRING(tv2)) {
59820 				/* inline string concatenation */
59821 				duk_dup(ctx, x->x1.valstack_idx);
59822 				duk_dup(ctx, x->x2.valstack_idx);
59823 				duk_concat(ctx, 2);
59824 				duk_replace(ctx, x->x1.valstack_idx);
59825 				x->t = DUK_IVAL_PLAIN;
59826 				DUK_ASSERT(x->x1.t == DUK_ISPEC_VALUE);
59827 				return;
59828 			}
59829 		}
59830 
59831 		arg1 = duk__ispec_toregconst_raw(comp_ctx, &x->x1, -1, DUK__IVAL_FLAG_ALLOW_CONST | DUK__IVAL_FLAG_REQUIRE_SHORT /*flags*/);
59832 		arg2 = duk__ispec_toregconst_raw(comp_ctx, &x->x2, -1, DUK__IVAL_FLAG_ALLOW_CONST | DUK__IVAL_FLAG_REQUIRE_SHORT /*flags*/);
59833 
59834 		/* If forced reg, use it as destination.  Otherwise try to
59835 		 * use either coerced ispec if it is a temporary.
59836 		 *
59837 		 * When using extraops, avoid reusing arg2 as dest because that
59838 		 * would lead to an LDREG shuffle below.  We still can't guarantee
59839 		 * dest != arg2 because we may have a forced_reg.
59840 		 */
59841 		if (forced_reg >= 0) {
59842 			dest = forced_reg;
59843 		} else if (DUK__ISTEMP(comp_ctx, arg1)) {
59844 			dest = (duk_reg_t) arg1;
59845 		} else if (DUK__ISTEMP(comp_ctx, arg2) && x->t != DUK_IVAL_ARITH_EXTRAOP) {
59846 			dest = (duk_reg_t) arg2;
59847 		} else {
59848 			dest = DUK__ALLOCTEMP(comp_ctx);
59849 		}
59850 
59851 		/* Extraop arithmetic opcodes must have destination same as
59852 		 * first source.  If second source matches destination we need
59853 		 * a temporary register to avoid clobbering the second source.
59854 		 *
59855 		 * XXX: change calling code to avoid this situation in most cases.
59856 		 */
59857 
59858 		if (x->t == DUK_IVAL_ARITH_EXTRAOP) {
59859 			if (!(DUK__ISREG(comp_ctx, arg1) && (duk_reg_t) arg1 == dest)) {
59860 				if (DUK__ISREG(comp_ctx, arg2) && (duk_reg_t) arg2 == dest) {
59861 					/* arg2 would be clobbered so reassign it to a temp. */
59862 					duk_reg_t tempreg;
59863 					tempreg = DUK__ALLOCTEMP(comp_ctx);
59864 					duk__emit_a_bc(comp_ctx, DUK_OP_LDREG, tempreg, arg2);
59865 					arg2 = tempreg;
59866 				}
59867 
59868 				if (DUK__ISREG(comp_ctx, arg1)) {
59869 					duk__emit_a_bc(comp_ctx, DUK_OP_LDREG, dest, arg1);
59870 				} else {
59871 					DUK_ASSERT(DUK__ISCONST(comp_ctx, arg1));
59872 					duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, dest, arg1);
59873 				}
59874 			}
59875 
59876 			/* Note: special DUK__EMIT_FLAG_B_IS_TARGETSOURCE
59877 			 * used to indicate that B is both a source and a
59878 			 * target register.  When shuffled, it needs to be
59879 			 * both input and output shuffled.
59880 			 */
59881 			DUK_ASSERT(DUK__ISREG(comp_ctx, dest));
59882 			duk__emit_extraop_b_c(comp_ctx,
59883 			                      x->op | DUK__EMIT_FLAG_B_IS_TARGET |
59884 			                              DUK__EMIT_FLAG_B_IS_TARGETSOURCE,
59885 			                      (duk_regconst_t) dest,
59886 			                      (duk_regconst_t) arg2);
59887 
59888 		} else {
59889 			DUK_ASSERT(DUK__ISREG(comp_ctx, dest));
59890 			duk__emit_a_b_c(comp_ctx, x->op, (duk_regconst_t) dest, arg1, arg2);
59891 		}
59892 
59893 		x->t = DUK_IVAL_PLAIN;
59894 		x->x1.t = DUK_ISPEC_REGCONST;
59895 		x->x1.regconst = (duk_regconst_t) dest;
59896 		return;
59897 	}
59898 	case DUK_IVAL_PROP: {
59899 		/* XXX: very similar to DUK_IVAL_ARITH - merge? */
59900 		duk_regconst_t arg1;
59901 		duk_regconst_t arg2;
59902 		duk_reg_t dest;
59903 
59904 		/* Need a short reg/const, does not have to be a mutable temp. */
59905 		arg1 = duk__ispec_toregconst_raw(comp_ctx, &x->x1, -1, DUK__IVAL_FLAG_ALLOW_CONST | DUK__IVAL_FLAG_REQUIRE_SHORT /*flags*/);
59906 		arg2 = duk__ispec_toregconst_raw(comp_ctx, &x->x2, -1, DUK__IVAL_FLAG_ALLOW_CONST | DUK__IVAL_FLAG_REQUIRE_SHORT /*flags*/);
59907 
59908 		/* Pick a destination register.  If either base value or key
59909 		 * happens to be a temp value, reuse it as the destination.
59910 		 *
59911 		 * XXX: The temp must be a "mutable" one, i.e. such that no
59912 		 * other expression is using it anymore.  Here this should be
59913 		 * the case because the value of a property access expression
59914 		 * is neither the base nor the key, but the lookup result.
59915 		 */
59916 
59917 		if (forced_reg >= 0) {
59918 			dest = forced_reg;
59919 		} else if (DUK__ISTEMP(comp_ctx, arg1)) {
59920 			dest = (duk_reg_t) arg1;
59921 		} else if (DUK__ISTEMP(comp_ctx, arg2)) {
59922 			dest = (duk_reg_t) arg2;
59923 		} else {
59924 			dest = DUK__ALLOCTEMP(comp_ctx);
59925 		}
59926 
59927 		duk__emit_a_b_c(comp_ctx, DUK_OP_GETPROP, (duk_regconst_t) dest, arg1, arg2);
59928 
59929 		x->t = DUK_IVAL_PLAIN;
59930 		x->x1.t = DUK_ISPEC_REGCONST;
59931 		x->x1.regconst = (duk_regconst_t) dest;
59932 		return;
59933 	}
59934 	case DUK_IVAL_VAR: {
59935 		/* x1 must be a string */
59936 		duk_reg_t dest;
59937 		duk_reg_t reg_varbind;
59938 		duk_regconst_t rc_varname;
59939 
59940 		DUK_ASSERT(x->x1.t == DUK_ISPEC_VALUE);
59941 
59942 		duk_dup(ctx, x->x1.valstack_idx);
59943 		if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
59944 			x->t = DUK_IVAL_PLAIN;
59945 			x->x1.t = DUK_ISPEC_REGCONST;
59946 			x->x1.regconst = (duk_regconst_t) reg_varbind;
59947 		} else {
59948 			dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
59949 			duk__emit_a_bc(comp_ctx, DUK_OP_GETVAR, (duk_regconst_t) dest, rc_varname);
59950 			x->t = DUK_IVAL_PLAIN;
59951 			x->x1.t = DUK_ISPEC_REGCONST;
59952 			x->x1.regconst = (duk_regconst_t) dest;
59953 		}
59954 		return;
59955 	}
59956 	case DUK_IVAL_NONE:
59957 	default: {
59958 		DUK_D(DUK_DPRINT("invalid ivalue type: %ld", (long) x->t));
59959 		break;
59960 	}
59961 	}
59962 
59963 	DUK_ERROR_INTERNAL_DEFMSG(thr);
59964 	return;
59965 }
59966 
59967 /* evaluate to plain value, no forced register (temp/bound reg both ok) */
59968 DUK_LOCAL void duk__ivalue_toplain(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
59969 	duk__ivalue_toplain_raw(comp_ctx, x, -1 /*forced_reg*/);
59970 }
59971 
59972 /* evaluate to final form (e.g. coerce GETPROP to code), throw away temp */
59973 DUK_LOCAL void duk__ivalue_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
59974 	duk_reg_t temp;
59975 
59976 	/* If duk__ivalue_toplain_raw() allocates a temp, forget it and
59977 	 * restore next temp state.
59978 	 */
59979 	temp = DUK__GETTEMP(comp_ctx);
59980 	duk__ivalue_toplain_raw(comp_ctx, x, -1 /*forced_reg*/);
59981 	DUK__SETTEMP(comp_ctx, temp);
59982 }
59983 
59984 /* Coerce an duk_ivalue to a register or constant; result register may
59985  * be a temp or a bound register.
59986  *
59987  * The duk_ivalue argument ('x') is converted into a regconst as a
59988  * side effect.
59989  */
59990 DUK_LOCAL
59991 duk_regconst_t duk__ivalue_toregconst_raw(duk_compiler_ctx *comp_ctx,
59992                                           duk_ivalue *x,
59993                                           duk_reg_t forced_reg,
59994                                           duk_small_uint_t flags) {
59995 	duk_hthread *thr = comp_ctx->thr;
59996 	duk_context *ctx = (duk_context *) thr;
59997 	duk_regconst_t reg;
59998 	DUK_UNREF(thr);
59999 	DUK_UNREF(ctx);
60000 
60001 	DUK_DDD(DUK_DDDPRINT("duk__ivalue_toregconst_raw(): x={t=%ld,op=%ld,x1={%ld:%ld:%!T},x2={%ld:%ld:%!T}}, "
60002 	                     "forced_reg=%ld, flags 0x%08lx: allow_const=%ld require_temp=%ld require_short=%ld",
60003 	                     (long) x->t, (long) x->op,
60004 	                     (long) x->x1.t, (long) x->x1.regconst,
60005 	                     (duk_tval *) duk_get_tval(ctx, x->x1.valstack_idx),
60006 	                     (long) x->x2.t, (long) x->x2.regconst,
60007 	                     (duk_tval *) duk_get_tval(ctx, x->x2.valstack_idx),
60008 	                     (long) forced_reg,
60009 	                     (unsigned long) flags,
60010 	                     (long) ((flags & DUK__IVAL_FLAG_ALLOW_CONST) ? 1 : 0),
60011 	                     (long) ((flags & DUK__IVAL_FLAG_REQUIRE_TEMP) ? 1 : 0),
60012 	                     (long) ((flags & DUK__IVAL_FLAG_REQUIRE_SHORT) ? 1 : 0)));
60013 
60014 	/* first coerce to a plain value */
60015 	duk__ivalue_toplain_raw(comp_ctx, x, forced_reg);
60016 	DUK_ASSERT(x->t == DUK_IVAL_PLAIN);
60017 
60018 	/* then to a register */
60019 	reg = duk__ispec_toregconst_raw(comp_ctx, &x->x1, forced_reg, flags);
60020 	x->x1.t = DUK_ISPEC_REGCONST;
60021 	x->x1.regconst = reg;
60022 
60023 	return reg;
60024 }
60025 
60026 DUK_LOCAL duk_reg_t duk__ivalue_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
60027 	return duk__ivalue_toregconst_raw(comp_ctx, x, -1, 0 /*flags*/);
60028 }
60029 
60030 #if 0  /* unused */
60031 DUK_LOCAL duk_reg_t duk__ivalue_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
60032 	return duk__ivalue_toregconst_raw(comp_ctx, x, -1, DUK__IVAL_FLAG_REQUIRE_TEMP /*flags*/);
60033 }
60034 #endif
60035 
60036 DUK_LOCAL void duk__ivalue_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_int_t forced_reg) {
60037 	DUK_ASSERT(forced_reg >= 0);
60038 	(void) duk__ivalue_toregconst_raw(comp_ctx, x, forced_reg, 0 /*flags*/);
60039 }
60040 
60041 DUK_LOCAL duk_regconst_t duk__ivalue_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
60042 	return duk__ivalue_toregconst_raw(comp_ctx, x, -1, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
60043 }
60044 
60045 DUK_LOCAL duk_regconst_t duk__ivalue_totempconst(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
60046 	return duk__ivalue_toregconst_raw(comp_ctx, x, -1, DUK__IVAL_FLAG_ALLOW_CONST | DUK__IVAL_FLAG_REQUIRE_TEMP /*flags*/);
60047 }
60048 
60049 /* The issues below can be solved with better flags */
60050 
60051 /* XXX: many operations actually want toforcedtemp() -- brand new temp? */
60052 /* XXX: need a toplain_ignore() which will only coerce a value to a temp
60053  * register if it might have a side effect.  Side-effect free values do not
60054  * need to be coerced.
60055  */
60056 
60057 /*
60058  *  Identifier handling
60059  */
60060 
60061 DUK_LOCAL duk_reg_t duk__lookup_active_register_binding(duk_compiler_ctx *comp_ctx) {
60062 	duk_hthread *thr = comp_ctx->thr;
60063 	duk_context *ctx = (duk_context *) thr;
60064 	duk_hstring *h_varname;
60065 	duk_reg_t ret;
60066 
60067 	DUK_DDD(DUK_DDDPRINT("resolving identifier reference to '%!T'",
60068 	                     (duk_tval *) duk_get_tval(ctx, -1)));
60069 
60070 	/*
60071 	 *  Special name handling
60072 	 */
60073 
60074 	h_varname = duk_get_hstring(ctx, -1);
60075 	DUK_ASSERT(h_varname != NULL);
60076 
60077 	if (h_varname == DUK_HTHREAD_STRING_LC_ARGUMENTS(thr)) {
60078 		DUK_DDD(DUK_DDDPRINT("flagging function as accessing 'arguments'"));
60079 		comp_ctx->curr_func.id_access_arguments = 1;
60080 	}
60081 
60082 	/*
60083 	 *  Inside one or more 'with' statements fall back to slow path always.
60084 	 *  (See e.g. test-stmt-with.js.)
60085 	 */
60086 
60087 	if (comp_ctx->curr_func.with_depth > 0) {
60088 		DUK_DDD(DUK_DDDPRINT("identifier lookup inside a 'with' -> fall back to slow path"));
60089 		goto slow_path;
60090 	}
60091 
60092 	/*
60093 	 *  Any catch bindings ("catch (e)") also affect identifier binding.
60094 	 *
60095 	 *  Currently, the varmap is modified for the duration of the catch
60096 	 *  clause to ensure any identifier accesses with the catch variable
60097 	 *  name will use slow path.
60098 	 */
60099 
60100 	duk_get_prop(ctx, comp_ctx->curr_func.varmap_idx);
60101 	if (duk_is_number(ctx, -1)) {
60102 		ret = duk_to_int(ctx, -1);
60103 		duk_pop(ctx);
60104 	} else {
60105 		duk_pop(ctx);
60106 		goto slow_path;
60107 	}
60108 
60109 	DUK_DDD(DUK_DDDPRINT("identifier lookup -> reg %ld", (long) ret));
60110 	return ret;
60111 
60112  slow_path:
60113 	DUK_DDD(DUK_DDDPRINT("identifier lookup -> slow path"));
60114 
60115 	comp_ctx->curr_func.id_access_slow = 1;
60116 	return (duk_reg_t) -1;
60117 }
60118 
60119 /* Lookup an identifier name in the current varmap, indicating whether the
60120  * identifier is register-bound and if not, allocating a constant for the
60121  * identifier name.  Returns 1 if register-bound, 0 otherwise.  Caller can
60122  * also check (out_reg_varbind >= 0) to check whether or not identifier is
60123  * register bound.  The caller must NOT use out_rc_varname at all unless
60124  * return code is 0 or out_reg_varbind is < 0; this is becuase out_rc_varname
60125  * is unsigned and doesn't have a "unused" / none value.
60126  */
60127 DUK_LOCAL duk_bool_t duk__lookup_lhs(duk_compiler_ctx *comp_ctx, duk_reg_t *out_reg_varbind, duk_regconst_t *out_rc_varname) {
60128 	duk_hthread *thr = comp_ctx->thr;
60129 	duk_context *ctx = (duk_context *) thr;
60130 	duk_reg_t reg_varbind;
60131 	duk_regconst_t rc_varname;
60132 
60133 	/* [ ... varname ] */
60134 
60135 	duk_dup_top(ctx);
60136 	reg_varbind = duk__lookup_active_register_binding(comp_ctx);
60137 
60138 	if (reg_varbind >= 0) {
60139 		*out_reg_varbind = reg_varbind;
60140 		*out_rc_varname = 0;  /* duk_regconst_t is unsigned, so use 0 as dummy value (ignored by caller) */
60141 		duk_pop(ctx);
60142 		return 1;
60143 	} else {
60144 		rc_varname = duk__getconst(comp_ctx);
60145 		*out_reg_varbind = -1;
60146 		*out_rc_varname = rc_varname;
60147 		return 0;
60148 	}
60149 }
60150 
60151 /*
60152  *  Label handling
60153  *
60154  *  Labels are initially added with flags prohibiting both break and continue.
60155  *  When the statement type is finally uncovered (after potentially multiple
60156  *  labels), all the labels are updated to allow/prohibit break and continue.
60157  */
60158 
60159 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) {
60160 	duk_hthread *thr = comp_ctx->thr;
60161 	duk_context *ctx = (duk_context *) thr;
60162 	duk_size_t n;
60163 	duk_size_t new_size;
60164 	duk_uint8_t *p;
60165 	duk_labelinfo *li_start, *li;
60166 
60167 	/* Duplicate (shadowing) labels are not allowed, except for the empty
60168 	 * labels (which are used as default labels for switch and iteration
60169 	 * statements).
60170 	 *
60171 	 * We could also allow shadowing of non-empty pending labels without any
60172 	 * other issues than breaking the required label shadowing requirements
60173 	 * of the E5 specification, see Section 12.12.
60174 	 */
60175 
60176 	p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, comp_ctx->curr_func.h_labelinfos);
60177 	li_start = (duk_labelinfo *) (void *) p;
60178 	li = (duk_labelinfo *) (void *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos));
60179 	n = (duk_size_t) (li - li_start);
60180 
60181 	while (li > li_start) {
60182 		li--;
60183 
60184 		if (li->h_label == h_label && h_label != DUK_HTHREAD_STRING_EMPTY_STRING(thr)) {
60185 			DUK_ERROR_SYNTAX(thr, DUK_STR_DUPLICATE_LABEL);
60186 		}
60187 	}
60188 
60189 	duk_push_hstring(ctx, h_label);
60190 	DUK_ASSERT(n <= DUK_UARRIDX_MAX);  /* label limits */
60191 	(void) duk_put_prop_index(ctx, comp_ctx->curr_func.labelnames_idx, (duk_uarridx_t) n);
60192 
60193 	new_size = (n + 1) * sizeof(duk_labelinfo);
60194 	duk_hbuffer_resize(thr, comp_ctx->curr_func.h_labelinfos, new_size);
60195 	/* XXX: spare handling, slow now */
60196 
60197 	/* relookup after possible realloc */
60198 	p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, comp_ctx->curr_func.h_labelinfos);
60199 	li_start = (duk_labelinfo *) (void *) p;
60200 	DUK_UNREF(li_start);  /* silence scan-build warning */
60201 	li = (duk_labelinfo *) (void *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos));
60202 	li--;
60203 
60204 	/* Labels can be used for iteration statements but also for other statements,
60205 	 * in particular a label can be used for a block statement.  All cases of a
60206 	 * named label accept a 'break' so that flag is set here.  Iteration statements
60207 	 * also allow 'continue', so that flag is updated when we figure out the
60208 	 * statement type.
60209 	 */
60210 
60211 	li->flags = DUK_LABEL_FLAG_ALLOW_BREAK;
60212 	li->label_id = label_id;
60213 	li->h_label = h_label;
60214 	li->catch_depth = comp_ctx->curr_func.catch_depth;   /* catch depth from current func */
60215 	li->pc_label = pc_label;
60216 
60217 	DUK_DDD(DUK_DDDPRINT("registered label: flags=0x%08lx, id=%ld, name=%!O, catch_depth=%ld, pc_label=%ld",
60218 	                     (unsigned long) li->flags, (long) li->label_id, (duk_heaphdr *) li->h_label,
60219 	                     (long) li->catch_depth, (long) li->pc_label));
60220 }
60221 
60222 /* Update all labels with matching label_id. */
60223 DUK_LOCAL void duk__update_label_flags(duk_compiler_ctx *comp_ctx, duk_int_t label_id, duk_small_uint_t flags) {
60224 	duk_uint8_t *p;
60225 	duk_labelinfo *li_start, *li;
60226 
60227 	p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(comp_ctx->thr->heap, comp_ctx->curr_func.h_labelinfos);
60228 	li_start = (duk_labelinfo *) (void *) p;
60229 	li = (duk_labelinfo *) (void *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos));
60230 
60231 	/* Match labels starting from latest; once label_id no longer matches, we can
60232 	 * safely exit without checking the rest of the labels (only the topmost labels
60233 	 * are ever updated).
60234 	 */
60235 	while (li > li_start) {
60236 		li--;
60237 
60238 		if (li->label_id != label_id) {
60239 			break;
60240 		}
60241 
60242 		DUK_DDD(DUK_DDDPRINT("updating (overwriting) label flags for li=%p, label_id=%ld, flags=%ld",
60243 		                     (void *) li, (long) label_id, (long) flags));
60244 
60245 		li->flags = flags;
60246 	}
60247 }
60248 
60249 /* Lookup active label information.  Break/continue distinction is necessary to handle switch
60250  * statement related labels correctly: a switch will only catch a 'break', not a 'continue'.
60251  *
60252  * An explicit label cannot appear multiple times in the active set, but empty labels (unlabelled
60253  * iteration and switch statements) can.  A break will match the closest unlabelled or labelled
60254  * statement.  A continue will match the closest unlabelled or labelled iteration statement.  It is
60255  * a syntax error if a continue matches a labelled switch statement; because an explicit label cannot
60256  * be duplicated, the continue cannot match any valid label outside the switch.
60257  *
60258  * A side effect of these rules is that a LABEL statement related to a switch should never actually
60259  * catch a continue abrupt completion at run-time.  Hence an INVALID opcode can be placed in the
60260  * continue slot of the switch's LABEL statement.
60261  */
60262 
60263 /* XXX: awkward, especially the bunch of separate output values -> output struct? */
60264 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) {
60265 	duk_hthread *thr = comp_ctx->thr;
60266 	duk_context *ctx = (duk_context *) thr;
60267 	duk_uint8_t *p;
60268 	duk_labelinfo *li_start, *li_end, *li;
60269 	duk_bool_t match = 0;
60270 
60271 	DUK_DDD(DUK_DDDPRINT("looking up active label: label='%!O', is_break=%ld",
60272 	                     (duk_heaphdr *) h_label, (long) is_break));
60273 
60274 	DUK_UNREF(ctx);
60275 
60276 	p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, comp_ctx->curr_func.h_labelinfos);
60277 	li_start = (duk_labelinfo *) (void *) p;
60278 	li_end = (duk_labelinfo *) (void *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos));
60279 	li = li_end;
60280 
60281 	/* Match labels starting from latest label because there can be duplicate empty
60282 	 * labels in the label set.
60283 	 */
60284 	while (li > li_start) {
60285 		li--;
60286 
60287 		if (li->h_label != h_label) {
60288 			DUK_DDD(DUK_DDDPRINT("labelinfo[%ld] ->'%!O' != %!O",
60289 			                     (long) (li - li_start),
60290 			                     (duk_heaphdr *) li->h_label,
60291 			                     (duk_heaphdr *) h_label));
60292 			continue;
60293 		}
60294 
60295 		DUK_DDD(DUK_DDDPRINT("labelinfo[%ld] -> '%!O' label name matches (still need to check type)",
60296 		                     (long) (li - li_start), (duk_heaphdr *) h_label));
60297 
60298 		/* currently all labels accept a break, so no explicit check for it now */
60299 		DUK_ASSERT(li->flags & DUK_LABEL_FLAG_ALLOW_BREAK);
60300 
60301 		if (is_break) {
60302 			/* break matches always */
60303 			match = 1;
60304 			break;
60305 		} else if (li->flags & DUK_LABEL_FLAG_ALLOW_CONTINUE) {
60306 			/* iteration statements allow continue */
60307 			match = 1;
60308 			break;
60309 		} else {
60310 			/* continue matched this label -- we can only continue if this is the empty
60311 			 * label, for which duplication is allowed, and thus there is hope of
60312 			 * finding a match deeper in the label stack.
60313 			 */
60314 			if (h_label != DUK_HTHREAD_STRING_EMPTY_STRING(thr)) {
60315 				DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_LABEL);
60316 			} else {
60317 				DUK_DDD(DUK_DDDPRINT("continue matched an empty label which does not "
60318 				                     "allow a continue -> continue lookup deeper in label stack"));
60319 			}
60320 		}
60321 	}
60322 	/* XXX: match flag is awkward, rework */
60323 	if (!match) {
60324 		DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_LABEL);
60325 	}
60326 
60327 	DUK_DDD(DUK_DDDPRINT("label match: %!O -> label_id %ld, catch_depth=%ld, pc_label=%ld",
60328 	                     (duk_heaphdr *) h_label, (long) li->label_id,
60329 	                     (long) li->catch_depth, (long) li->pc_label));
60330 
60331 	*out_label_id = li->label_id;
60332 	*out_label_catch_depth = li->catch_depth;
60333 	*out_label_pc = li->pc_label;
60334 	*out_is_closest = (li == li_end - 1);
60335 }
60336 
60337 DUK_LOCAL void duk__reset_labels_to_length(duk_compiler_ctx *comp_ctx, duk_int_t len) {
60338 	duk_hthread *thr = comp_ctx->thr;
60339 	duk_context *ctx = (duk_context *) thr;
60340 	duk_size_t new_size;
60341 
60342 	/* XXX: duk_set_length */
60343 	new_size = sizeof(duk_labelinfo) * (duk_size_t) len;
60344 	duk_push_int(ctx, len);
60345 	duk_put_prop_stridx(ctx, comp_ctx->curr_func.labelnames_idx, DUK_STRIDX_LENGTH);
60346 	duk_hbuffer_resize(thr, comp_ctx->curr_func.h_labelinfos, new_size);
60347 }
60348 
60349 /*
60350  *  Expression parsing: duk__expr_nud(), duk__expr_led(), duk__expr_lbp(), and helpers.
60351  *
60352  *  - duk__expr_nud(): ("null denotation"): process prev_token as a "start" of an expression (e.g. literal)
60353  *  - duk__expr_led(): ("left denotation"): process prev_token in the "middle" of an expression (e.g. operator)
60354  *  - duk__expr_lbp(): ("left-binding power"): return left-binding power of curr_token
60355  */
60356 
60357 /* object literal key tracking flags */
60358 #define DUK__OBJ_LIT_KEY_PLAIN  (1 << 0)  /* key encountered as a plain property */
60359 #define DUK__OBJ_LIT_KEY_GET    (1 << 1)  /* key encountered as a getter */
60360 #define DUK__OBJ_LIT_KEY_SET    (1 << 2)  /* key encountered as a setter */
60361 
60362 DUK_LOCAL void duk__nud_array_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
60363 	duk_hthread *thr = comp_ctx->thr;
60364 	duk_reg_t reg_obj;                 /* result reg */
60365 	duk_reg_t reg_temp;                /* temp reg */
60366 	duk_reg_t temp_start;              /* temp reg value for start of loop */
60367 	duk_small_uint_t max_init_values;  /* max # of values initialized in one MPUTARR set */
60368 	duk_small_uint_t num_values;       /* number of values in current MPUTARR set */
60369 	duk_uarridx_t curr_idx;            /* current (next) array index */
60370 	duk_uarridx_t start_idx;           /* start array index of current MPUTARR set */
60371 	duk_uarridx_t init_idx;            /* last array index explicitly initialized, +1 */
60372 	duk_bool_t require_comma;          /* next loop requires a comma */
60373 
60374 	/* DUK_TOK_LBRACKET already eaten, current token is right after that */
60375 	DUK_ASSERT(comp_ctx->prev_token.t == DUK_TOK_LBRACKET);
60376 
60377 	max_init_values = DUK__MAX_ARRAY_INIT_VALUES;  /* XXX: depend on available temps? */
60378 
60379 	reg_obj = DUK__ALLOCTEMP(comp_ctx);
60380 	duk__emit_extraop_b_c(comp_ctx,
60381 	                      DUK_EXTRAOP_NEWARR | DUK__EMIT_FLAG_B_IS_TARGET,
60382 	                      reg_obj,
60383 	                      0);  /* XXX: patch initial size afterwards? */
60384 	temp_start = DUK__GETTEMP(comp_ctx);
60385 
60386 	/*
60387 	 *  Emit initializers in sets of maximum max_init_values.
60388 	 *  Corner cases such as single value initializers do not have
60389 	 *  special handling now.
60390 	 *
60391 	 *  Elided elements must not be emitted as 'undefined' values,
60392 	 *  because such values would be enumerable (which is incorrect).
60393 	 *  Also note that trailing elisions must be reflected in the
60394 	 *  length of the final array but cause no elements to be actually
60395 	 *  inserted.
60396 	 */
60397 
60398 	curr_idx = 0;
60399 	init_idx = 0;         /* tracks maximum initialized index + 1 */
60400 	start_idx = 0;
60401 	require_comma = 0;
60402 
60403 	for (;;) {
60404 		num_values = 0;
60405 		DUK__SETTEMP(comp_ctx, temp_start);
60406 
60407 		if (comp_ctx->curr_token.t == DUK_TOK_RBRACKET) {
60408 			break;
60409 		}
60410 
60411 		for (;;) {
60412 			if (comp_ctx->curr_token.t == DUK_TOK_RBRACKET) {
60413 				/* the outer loop will recheck and exit */
60414 				break;
60415 			}
60416 
60417 			/* comma check */
60418 			if (require_comma) {
60419 				if (comp_ctx->curr_token.t == DUK_TOK_COMMA) {
60420 					/* comma after a value, expected */
60421 					duk__advance(comp_ctx);
60422 					require_comma = 0;
60423 					continue;
60424 				} else {
60425 					goto syntax_error;
60426 				}
60427 			} else {
60428 				if (comp_ctx->curr_token.t == DUK_TOK_COMMA) {
60429 					/* elision - flush */
60430 					curr_idx++;
60431 					duk__advance(comp_ctx);
60432 					/* if num_values > 0, MPUTARR emitted by outer loop after break */
60433 					break;
60434 				}
60435 			}
60436 			/* else an array initializer element */
60437 
60438 			/* initial index */
60439 			if (num_values == 0) {
60440 				start_idx = curr_idx;
60441 				reg_temp = DUK__ALLOCTEMP(comp_ctx);
60442 				duk__emit_load_int32(comp_ctx, reg_temp, (duk_int32_t) start_idx);
60443 			}
60444 
60445 			reg_temp = DUK__ALLOCTEMP(comp_ctx);   /* alloc temp just in case, to update max temp */
60446 			DUK__SETTEMP(comp_ctx, reg_temp);
60447 			duk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp /*forced_reg*/);
60448 			DUK__SETTEMP(comp_ctx, reg_temp + 1);
60449 
60450 			num_values++;
60451 			curr_idx++;
60452 			require_comma = 1;
60453 
60454 			if (num_values >= max_init_values) {
60455 				/* MPUTARR emitted by outer loop */
60456 				break;
60457 			}
60458 		}
60459 
60460 		if (num_values > 0) {
60461 			/* - A is a source register (it's not a write target, but used
60462 			 *   to identify the target object) but can be shuffled.
60463 			 * - B cannot be shuffled normally because it identifies a range
60464 			 *   of registers, the emitter has special handling for this
60465 			 *   (the "no shuffle" flag must not be set).
60466 			 * - C is a non-register number and cannot be shuffled, but
60467 			 *   never needs to be.
60468 			 */
60469 			duk__emit_a_b_c(comp_ctx,
60470 			                DUK_OP_MPUTARR |
60471 			                    DUK__EMIT_FLAG_NO_SHUFFLE_C |
60472 			                    DUK__EMIT_FLAG_A_IS_SOURCE,
60473 			                (duk_regconst_t) reg_obj,
60474 			                (duk_regconst_t) temp_start,
60475 			                (duk_regconst_t) num_values);
60476 			init_idx = start_idx + num_values;
60477 
60478 			/* num_values and temp_start reset at top of outer loop */
60479 		}
60480 	}
60481 
60482 	DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_RBRACKET);
60483 	duk__advance(comp_ctx);
60484 
60485 	DUK_DDD(DUK_DDDPRINT("array literal done, curridx=%ld, initidx=%ld",
60486 	                     (long) curr_idx, (long) init_idx));
60487 
60488 	/* trailing elisions? */
60489 	if (curr_idx > init_idx) {
60490 		/* yes, must set array length explicitly */
60491 		DUK_DDD(DUK_DDDPRINT("array literal has trailing elisions which affect its length"));
60492 		reg_temp = DUK__ALLOCTEMP(comp_ctx);
60493 		duk__emit_load_int32(comp_ctx, reg_temp, (duk_int_t) curr_idx);
60494 		duk__emit_extraop_b_c(comp_ctx,
60495 		                      DUK_EXTRAOP_SETALEN,
60496 		                      (duk_regconst_t) reg_obj,
60497 		                      (duk_regconst_t) reg_temp);
60498 	}
60499 
60500 	DUK__SETTEMP(comp_ctx, temp_start);
60501 
60502 	res->t = DUK_IVAL_PLAIN;
60503 	res->x1.t = DUK_ISPEC_REGCONST;
60504 	res->x1.regconst = (duk_regconst_t) reg_obj;
60505 	return;
60506 
60507  syntax_error:
60508 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_ARRAY_LITERAL);
60509 }
60510 
60511 /* duplicate/invalid key checks; returns 1 if syntax error */
60512 DUK_LOCAL duk_bool_t duk__nud_object_literal_key_check(duk_compiler_ctx *comp_ctx, duk_small_uint_t new_key_flags) {
60513 	duk_hthread *thr = comp_ctx->thr;
60514 	duk_context *ctx = (duk_context *) thr;
60515 	duk_small_uint_t key_flags;
60516 
60517 	/* [ ... key_obj key ] */
60518 
60519 	DUK_ASSERT(duk_is_string(ctx, -1));
60520 
60521 	/*
60522 	 *  'key_obj' tracks keys encountered so far by associating an
60523 	 *  integer with flags with already encountered keys.  The checks
60524 	 *  below implement E5 Section 11.1.5, step 4 for production:
60525 	 *
60526 	 *    PropertyNameAndValueList: PropertyNameAndValueList , PropertyAssignment
60527 	 */
60528 
60529 	duk_dup(ctx, -1);       /* [ ... key_obj key key ] */
60530 	duk_get_prop(ctx, -3);  /* [ ... key_obj key val ] */
60531 	key_flags = duk_to_int(ctx, -1);
60532 	duk_pop(ctx);           /* [ ... key_obj key ] */
60533 
60534 	if (new_key_flags & DUK__OBJ_LIT_KEY_PLAIN) {
60535 		if ((key_flags & DUK__OBJ_LIT_KEY_PLAIN) && comp_ctx->curr_func.is_strict) {
60536 			/* step 4.a */
60537 			DUK_DDD(DUK_DDDPRINT("duplicate key: plain key appears twice in strict mode"));
60538 			return 1;
60539 		}
60540 		if (key_flags & (DUK__OBJ_LIT_KEY_GET | DUK__OBJ_LIT_KEY_SET)) {
60541 			/* step 4.c */
60542 			DUK_DDD(DUK_DDDPRINT("duplicate key: plain key encountered after setter/getter"));
60543 			return 1;
60544 		}
60545 	} else {
60546 		if (key_flags & DUK__OBJ_LIT_KEY_PLAIN) {
60547 			/* step 4.b */
60548 			DUK_DDD(DUK_DDDPRINT("duplicate key: getter/setter encountered after plain key"));
60549 			return 1;
60550 		}
60551 		if (key_flags & new_key_flags) {
60552 			/* step 4.d */
60553 			DUK_DDD(DUK_DDDPRINT("duplicate key: getter/setter encountered twice"));
60554 			return 1;
60555 		}
60556 	}
60557 
60558 	new_key_flags |= key_flags;
60559 	DUK_DDD(DUK_DDDPRINT("setting/updating key %!T flags: 0x%08lx -> 0x%08lx",
60560 	                     (duk_tval *) duk_get_tval(ctx, -1),
60561 	                     (unsigned long) key_flags,
60562 	                     (unsigned long) new_key_flags));
60563 	duk_dup(ctx, -1);
60564 	duk_push_int(ctx, new_key_flags);   /* [ ... key_obj key key flags ] */
60565 	duk_put_prop(ctx, -4);              /* [ ... key_obj key ] */
60566 
60567 	return 0;
60568 }
60569 
60570 DUK_LOCAL void duk__nud_object_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
60571 	duk_hthread *thr = comp_ctx->thr;
60572 	duk_context *ctx = (duk_context *) thr;
60573 	duk_reg_t reg_obj;                /* result reg */
60574 	duk_reg_t reg_key;                /* temp reg for key literal */
60575 	duk_reg_t reg_temp;               /* temp reg */
60576 	duk_reg_t temp_start;             /* temp reg value for start of loop */
60577 	duk_small_uint_t max_init_pairs;  /* max # of key-value pairs initialized in one MPUTOBJ set */
60578 	duk_small_uint_t num_pairs;       /* number of pairs in current MPUTOBJ set */
60579 	duk_bool_t first;                 /* first value: comma must not precede the value */
60580 	duk_bool_t is_set, is_get;        /* temps */
60581 
60582 	DUK_ASSERT(comp_ctx->prev_token.t == DUK_TOK_LCURLY);
60583 
60584 	max_init_pairs = DUK__MAX_OBJECT_INIT_PAIRS;  /* XXX: depend on available temps? */
60585 
60586 	reg_obj = DUK__ALLOCTEMP(comp_ctx);
60587 	duk__emit_extraop_b_c(comp_ctx,
60588 	                      DUK_EXTRAOP_NEWOBJ | DUK__EMIT_FLAG_B_IS_TARGET,
60589 	                      reg_obj,
60590 	                      0);  /* XXX: patch initial size afterwards? */
60591 	temp_start = DUK__GETTEMP(comp_ctx);
60592 
60593 	/* temp object for tracking / detecting duplicate keys */
60594 	duk_push_object(ctx);
60595 
60596 	/*
60597 	 *  Emit initializers in sets of maximum max_init_pairs keys.
60598 	 *  Setter/getter is handled separately and terminates the
60599 	 *  current set of initializer values.  Corner cases such as
60600 	 *  single value initializers do not have special handling now.
60601 	 */
60602 
60603 	first = 1;
60604 	for (;;) {
60605 		num_pairs = 0;
60606 		DUK__SETTEMP(comp_ctx, temp_start);
60607 
60608 		if (comp_ctx->curr_token.t == DUK_TOK_RCURLY) {
60609 			break;
60610 		}
60611 
60612 		for (;;) {
60613 			/*
60614 			 *  Three possible element formats:
60615 			 *    1) PropertyName : AssignmentExpression
60616 			 *    2) get PropertyName () { FunctionBody }
60617 			 *    3) set PropertyName ( PropertySetParameterList ) { FunctionBody }
60618 			 *
60619 			 *  PropertyName can be IdentifierName (includes reserved words), a string
60620 			 *  literal, or a number literal.  Note that IdentifierName allows 'get' and
60621 			 *  'set' too, so we need to look ahead to the next token to distinguish:
60622 			 *
60623 			 *     { get : 1 }
60624 			 *
60625 			 *  and
60626 			 *
60627 			 *     { get foo() { return 1 } }
60628 			 *     { get get() { return 1 } }    // 'get' as getter propertyname
60629 			 *
60630 			 *  Finally, a trailing comma is allowed.
60631 			 *
60632 			 *  Key name is coerced to string at compile time (and ends up as a
60633 			 *  a string constant) even for numeric keys (e.g. "{1:'foo'}").
60634 			 *  These could be emitted using e.g. LDINT, but that seems hardly
60635 			 *  worth the effort and would increase code size.
60636 			 */
60637 
60638 			DUK_DDD(DUK_DDDPRINT("object literal inner loop, curr_token->t = %ld",
60639 			                     (long) comp_ctx->curr_token.t));
60640 
60641 			if (comp_ctx->curr_token.t == DUK_TOK_RCURLY) {
60642 				/* the outer loop will recheck and exit */
60643 				break;
60644 			}
60645 			if (num_pairs >= max_init_pairs) {
60646 				/* MPUTOBJ emitted by outer loop */
60647 				break;
60648 			}
60649 
60650 			if (first) {
60651 				first = 0;
60652 			} else {
60653 				if (comp_ctx->curr_token.t != DUK_TOK_COMMA) {
60654 					goto syntax_error;
60655 				}
60656 				duk__advance(comp_ctx);
60657 				if (comp_ctx->curr_token.t == DUK_TOK_RCURLY) {
60658 					/* trailing comma followed by rcurly */
60659 					break;
60660 				}
60661 			}
60662 
60663 			/* advance to get one step of lookup */
60664 			duk__advance(comp_ctx);
60665 
60666 			/* NOTE: "get" and "set" are not officially ReservedWords and the lexer
60667 			 * currently treats them always like ordinary identifiers (DUK_TOK_GET
60668 			 * and DUK_TOK_SET are unused).  They need to be detected based on the
60669 			 * identifier string content.
60670 			 */
60671 
60672 			is_get = (comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER &&
60673 			          comp_ctx->prev_token.str1 == DUK_HTHREAD_STRING_GET(thr));
60674 			is_set = (comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER &&
60675 			          comp_ctx->prev_token.str1 == DUK_HTHREAD_STRING_SET(thr));
60676 			if ((is_get || is_set) && comp_ctx->curr_token.t != DUK_TOK_COLON) {
60677 				/* getter/setter */
60678 				duk_int_t fnum;
60679 
60680 				if (comp_ctx->curr_token.t_nores == DUK_TOK_IDENTIFIER ||
60681 				    comp_ctx->curr_token.t_nores == DUK_TOK_STRING) {
60682 					/* same handling for identifiers and strings */
60683 					DUK_ASSERT(comp_ctx->curr_token.str1 != NULL);
60684 					duk_push_hstring(ctx, comp_ctx->curr_token.str1);
60685 				} else if (comp_ctx->curr_token.t == DUK_TOK_NUMBER) {
60686 					duk_push_number(ctx, comp_ctx->curr_token.num);
60687 					duk_to_string(ctx, -1);
60688 				} else {
60689 					goto syntax_error;
60690 				}
60691 
60692 				DUK_ASSERT(duk_is_string(ctx, -1));
60693 				if (duk__nud_object_literal_key_check(comp_ctx,
60694 				                                      (is_get ? DUK__OBJ_LIT_KEY_GET : DUK__OBJ_LIT_KEY_SET))) {
60695 					goto syntax_error;
60696 				}
60697 				reg_key = duk__getconst(comp_ctx);
60698 
60699 				if (num_pairs > 0) {
60700 					/* - A is a source register (it's not a write target, but used
60701 					 *   to identify the target object) but can be shuffled.
60702 					 * - B cannot be shuffled normally because it identifies a range
60703 					 *   of registers, the emitter has special handling for this
60704 					 *   (the "no shuffle" flag must not be set).
60705 					 * - C is a non-register number and cannot be shuffled, but
60706 					 *   never needs to be.
60707 					 */
60708 					duk__emit_a_b_c(comp_ctx,
60709 					                DUK_OP_MPUTOBJ |
60710 					                    DUK__EMIT_FLAG_NO_SHUFFLE_C |
60711 					                    DUK__EMIT_FLAG_A_IS_SOURCE,
60712 					                reg_obj,
60713 					                temp_start,
60714 					                num_pairs);
60715 					num_pairs = 0;
60716 					DUK__SETTEMP(comp_ctx, temp_start);
60717 				}
60718 
60719 				/* curr_token = get/set name */
60720 				fnum = duk__parse_func_like_fnum(comp_ctx, 0 /*is_decl*/, 1 /*is_setget*/);
60721 
60722 				DUK_ASSERT(DUK__GETTEMP(comp_ctx) == temp_start);
60723 				reg_temp = DUK__ALLOCTEMP(comp_ctx);
60724 				duk__emit_a_bc(comp_ctx,
60725 				               DUK_OP_LDCONST,
60726 				               (duk_regconst_t) reg_temp,
60727 				               (duk_regconst_t) reg_key);
60728 				reg_temp = DUK__ALLOCTEMP(comp_ctx);
60729 				duk__emit_a_bc(comp_ctx,
60730 				               DUK_OP_CLOSURE,
60731 				               (duk_regconst_t) reg_temp,
60732 				               (duk_regconst_t) fnum);
60733 
60734 				/* Slot C is used in a non-standard fashion (range of regs),
60735 				 * emitter code has special handling for it (must not set the
60736 				 * "no shuffle" flag).
60737 				 */
60738 				duk__emit_extraop_b_c(comp_ctx,
60739 				                      (is_get ? DUK_EXTRAOP_INITGET : DUK_EXTRAOP_INITSET),
60740 				                      reg_obj,
60741 				                      temp_start);   /* temp_start+0 = key, temp_start+1 = closure */
60742 
60743 				DUK__SETTEMP(comp_ctx, temp_start);
60744 			} else {
60745 				/* normal key/value */
60746 				if (comp_ctx->prev_token.t_nores == DUK_TOK_IDENTIFIER ||
60747 				    comp_ctx->prev_token.t_nores == DUK_TOK_STRING) {
60748 					/* same handling for identifiers and strings */
60749 					DUK_ASSERT(comp_ctx->prev_token.str1 != NULL);
60750 					duk_push_hstring(ctx, comp_ctx->prev_token.str1);
60751 				} else if (comp_ctx->prev_token.t == DUK_TOK_NUMBER) {
60752 					duk_push_number(ctx, comp_ctx->prev_token.num);
60753 					duk_to_string(ctx, -1);
60754 				} else {
60755 					goto syntax_error;
60756 				}
60757 
60758 				DUK_ASSERT(duk_is_string(ctx, -1));
60759 				if (duk__nud_object_literal_key_check(comp_ctx, DUK__OBJ_LIT_KEY_PLAIN)) {
60760 					goto syntax_error;
60761 				}
60762 				reg_key = duk__getconst(comp_ctx);
60763 
60764 				reg_temp = DUK__ALLOCTEMP(comp_ctx);
60765 				duk__emit_a_bc(comp_ctx,
60766 				               DUK_OP_LDCONST,
60767 				               (duk_regconst_t) reg_temp,
60768 				               (duk_regconst_t) reg_key);
60769 				duk__advance_expect(comp_ctx, DUK_TOK_COLON);
60770 
60771 				reg_temp = DUK__ALLOCTEMP(comp_ctx);  /* alloc temp just in case, to update max temp */
60772 				DUK__SETTEMP(comp_ctx, reg_temp);
60773 				duk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp /*forced_reg*/);
60774 				DUK__SETTEMP(comp_ctx, reg_temp + 1);
60775 
60776 				num_pairs++;
60777 			}
60778 		}
60779 
60780 		if (num_pairs > 0) {
60781 			/* See MPUTOBJ comments above. */
60782 			duk__emit_a_b_c(comp_ctx,
60783 			                DUK_OP_MPUTOBJ |
60784 			                    DUK__EMIT_FLAG_NO_SHUFFLE_C |
60785 			                    DUK__EMIT_FLAG_A_IS_SOURCE,
60786 			                reg_obj,
60787 			                temp_start,
60788 			                num_pairs);
60789 
60790 			/* num_pairs and temp_start reset at top of outer loop */
60791 		}
60792 	}
60793 
60794 	DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_RCURLY);
60795 	duk__advance(comp_ctx);
60796 
60797 	DUK__SETTEMP(comp_ctx, temp_start);
60798 
60799 	res->t = DUK_IVAL_PLAIN;
60800 	res->x1.t = DUK_ISPEC_REGCONST;
60801 	res->x1.regconst = (duk_regconst_t) reg_obj;
60802 
60803 	DUK_DDD(DUK_DDDPRINT("final tracking object: %!T",
60804 	                     (duk_tval *) duk_get_tval(ctx, -1)));
60805 	duk_pop(ctx);
60806 	return;
60807 
60808  syntax_error:
60809 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_OBJECT_LITERAL);
60810 }
60811 
60812 /* Parse argument list.  Arguments are written to temps starting from
60813  * "next temp".  Returns number of arguments parsed.  Expects left paren
60814  * to be already eaten, and eats the right paren before returning.
60815  */
60816 DUK_LOCAL duk_int_t duk__parse_arguments(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
60817 	duk_int_t nargs = 0;
60818 	duk_reg_t reg_temp;
60819 
60820 	/* Note: expect that caller has already eaten the left paren */
60821 
60822 	DUK_DDD(DUK_DDDPRINT("start parsing arguments, prev_token.t=%ld, curr_token.t=%ld",
60823 	                     (long) comp_ctx->prev_token.t, (long) comp_ctx->curr_token.t));
60824 
60825 	for (;;) {
60826 		if (comp_ctx->curr_token.t == DUK_TOK_RPAREN) {
60827 			break;
60828 		}
60829 		if (nargs > 0) {
60830 			duk__advance_expect(comp_ctx, DUK_TOK_COMMA);
60831 		}
60832 
60833 		/* We want the argument expression value to go to "next temp"
60834 		 * without additional moves.  That should almost always be the
60835 		 * case, but we double check after expression parsing.
60836 		 *
60837 		 * This is not the cleanest possible approach.
60838 		 */
60839 
60840 		reg_temp = DUK__ALLOCTEMP(comp_ctx);  /* bump up "allocated" reg count, just in case */
60841 		DUK__SETTEMP(comp_ctx, reg_temp);
60842 
60843 		/* binding power must be high enough to NOT allow comma expressions directly */
60844 		duk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp);  /* always allow 'in', coerce to 'tr' just in case */
60845 
60846 		DUK__SETTEMP(comp_ctx, reg_temp + 1);
60847 		nargs++;
60848 
60849 		DUK_DDD(DUK_DDDPRINT("argument #%ld written into reg %ld", (long) nargs, (long) reg_temp));
60850 	}
60851 
60852 	/* eat the right paren */
60853 	duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);
60854 
60855 	DUK_DDD(DUK_DDDPRINT("end parsing arguments"));
60856 
60857 	return nargs;
60858 }
60859 
60860 DUK_LOCAL duk_bool_t duk__expr_is_empty(duk_compiler_ctx *comp_ctx) {
60861 	/* empty expressions can be detected conveniently with nud/led counts */
60862 	return (comp_ctx->curr_func.nud_count == 0) &&
60863 	       (comp_ctx->curr_func.led_count == 0);
60864 }
60865 
60866 DUK_LOCAL void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
60867 	duk_hthread *thr = comp_ctx->thr;
60868 	duk_context *ctx = (duk_context *) thr;
60869 	duk_token *tk;
60870 	duk_reg_t temp_at_entry;
60871 	duk_small_int_t tok;
60872 	duk_uint32_t args;  /* temp variable to pass constants and flags to shared code */
60873 
60874 	/*
60875 	 *  ctx->prev_token     token to process with duk__expr_nud()
60876 	 *  ctx->curr_token     updated by caller
60877 	 *
60878 	 *  Note: the token in the switch below has already been eaten.
60879 	 */
60880 
60881 	temp_at_entry = DUK__GETTEMP(comp_ctx);
60882 
60883 	comp_ctx->curr_func.nud_count++;
60884 
60885 	tk = &comp_ctx->prev_token;
60886 	tok = tk->t;
60887 	res->t = DUK_IVAL_NONE;
60888 
60889 	DUK_DDD(DUK_DDDPRINT("duk__expr_nud(), prev_token.t=%ld, allow_in=%ld, paren_level=%ld",
60890 	                     (long) tk->t, (long) comp_ctx->curr_func.allow_in, (long) comp_ctx->curr_func.paren_level));
60891 
60892 	switch (tok) {
60893 
60894 	/* PRIMARY EXPRESSIONS */
60895 
60896 	case DUK_TOK_THIS: {
60897 		duk_reg_t reg_temp;
60898 		reg_temp = DUK__ALLOCTEMP(comp_ctx);
60899 		duk__emit_extraop_bc(comp_ctx,
60900 		                     DUK_EXTRAOP_LDTHIS,
60901 		                     (duk_regconst_t) reg_temp);
60902 		res->t = DUK_IVAL_PLAIN;
60903 		res->x1.t = DUK_ISPEC_REGCONST;
60904 		res->x1.regconst = (duk_regconst_t) reg_temp;
60905 		return;
60906 	}
60907 	case DUK_TOK_IDENTIFIER: {
60908 		res->t = DUK_IVAL_VAR;
60909 		res->x1.t = DUK_ISPEC_VALUE;
60910 		duk_push_hstring(ctx, tk->str1);
60911 		duk_replace(ctx, res->x1.valstack_idx);
60912 		return;
60913 	}
60914 	case DUK_TOK_NULL: {
60915 		duk_push_null(ctx);
60916 		goto plain_value;
60917 	}
60918 	case DUK_TOK_TRUE: {
60919 		duk_push_true(ctx);
60920 		goto plain_value;
60921 	}
60922 	case DUK_TOK_FALSE: {
60923 		duk_push_false(ctx);
60924 		goto plain_value;
60925 	}
60926 	case DUK_TOK_NUMBER: {
60927 		duk_push_number(ctx, tk->num);
60928 		goto plain_value;
60929 	}
60930 	case DUK_TOK_STRING: {
60931 		DUK_ASSERT(tk->str1 != NULL);
60932 		duk_push_hstring(ctx, tk->str1);
60933 		goto plain_value;
60934 	}
60935 	case DUK_TOK_REGEXP: {
60936 #ifdef DUK_USE_REGEXP_SUPPORT
60937 		duk_reg_t reg_temp;
60938 		duk_regconst_t rc_re_bytecode;  /* const */
60939 		duk_regconst_t rc_re_source;    /* const */
60940 
60941 		DUK_ASSERT(tk->str1 != NULL);
60942 		DUK_ASSERT(tk->str2 != NULL);
60943 
60944 		DUK_DDD(DUK_DDDPRINT("emitting regexp op, str1=%!O, str2=%!O",
60945 		                     (duk_heaphdr *) tk->str1,
60946 		                     (duk_heaphdr *) tk->str2));
60947 
60948 		reg_temp = DUK__ALLOCTEMP(comp_ctx);
60949 		duk_push_hstring(ctx, tk->str1);
60950 		duk_push_hstring(ctx, tk->str2);
60951 
60952 		/* [ ... pattern flags ] */
60953 
60954 		duk_regexp_compile(thr);
60955 
60956 		/* [ ... escaped_source bytecode ] */
60957 
60958 		rc_re_bytecode = duk__getconst(comp_ctx);
60959 		rc_re_source = duk__getconst(comp_ctx);
60960 
60961 		duk__emit_a_b_c(comp_ctx,
60962 		                DUK_OP_REGEXP,
60963 		                (duk_regconst_t) reg_temp /*a*/,
60964 		                rc_re_bytecode /*b*/,
60965 		                rc_re_source /*c*/);
60966 
60967 		res->t = DUK_IVAL_PLAIN;
60968 		res->x1.t = DUK_ISPEC_REGCONST;
60969 		res->x1.regconst = (duk_regconst_t) reg_temp;
60970 		return;
60971 #else  /* DUK_USE_REGEXP_SUPPORT */
60972 		goto syntax_error;
60973 #endif  /* DUK_USE_REGEXP_SUPPORT */
60974 	}
60975 	case DUK_TOK_LBRACKET: {
60976 		DUK_DDD(DUK_DDDPRINT("parsing array literal"));
60977 		duk__nud_array_literal(comp_ctx, res);
60978 		return;
60979 	}
60980 	case DUK_TOK_LCURLY: {
60981 		DUK_DDD(DUK_DDDPRINT("parsing object literal"));
60982 		duk__nud_object_literal(comp_ctx, res);
60983 		return;
60984 	}
60985 	case DUK_TOK_LPAREN: {
60986 		duk_bool_t prev_allow_in;
60987 
60988 		comp_ctx->curr_func.paren_level++;
60989 		prev_allow_in = comp_ctx->curr_func.allow_in;
60990 		comp_ctx->curr_func.allow_in = 1; /* reset 'allow_in' for parenthesized expression */
60991 
60992 		duk__expr(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);  /* Expression, terminates at a ')' */
60993 
60994 		duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);
60995 		comp_ctx->curr_func.allow_in = prev_allow_in;
60996 		comp_ctx->curr_func.paren_level--;
60997 		return;
60998 	}
60999 
61000 	/* MEMBER/NEW/CALL EXPRESSIONS */
61001 
61002 	case DUK_TOK_NEW: {
61003 		/*
61004 		 *  Parsing an expression starting with 'new' is tricky because
61005 		 *  there are multiple possible productions deriving from
61006 		 *  LeftHandSideExpression which begin with 'new'.
61007 		 *
61008 		 *  We currently resort to one-token lookahead to distinguish the
61009 		 *  cases.  Hopefully this is correct.  The binding power must be
61010 		 *  such that parsing ends at an LPAREN (CallExpression) but not at
61011 		 *  a PERIOD or LBRACKET (MemberExpression).
61012 		 *
61013 		 *  See doc/compiler.rst for discussion on the parsing approach,
61014 		 *  and testcases/test-dev-new.js for a bunch of documented tests.
61015 		 */
61016 
61017 		duk_reg_t reg_target;
61018 		duk_int_t nargs;
61019 
61020 		DUK_DDD(DUK_DDDPRINT("begin parsing new expression"));
61021 
61022 		reg_target = DUK__ALLOCTEMP(comp_ctx);
61023 		duk__expr_toforcedreg(comp_ctx, res, DUK__BP_CALL /*rbp_flags*/, reg_target /*forced_reg*/);
61024 		DUK__SETTEMP(comp_ctx, reg_target + 1);
61025 
61026 		if (comp_ctx->curr_token.t == DUK_TOK_LPAREN) {
61027 			/* 'new' MemberExpression Arguments */
61028 			DUK_DDD(DUK_DDDPRINT("new expression has argument list"));
61029 			duk__advance(comp_ctx);
61030 			nargs = duk__parse_arguments(comp_ctx, res);  /* parse args starting from "next temp", reg_target + 1 */
61031 			/* right paren eaten */
61032 		} else {
61033 			/* 'new' MemberExpression */
61034 			DUK_DDD(DUK_DDDPRINT("new expression has no argument list"));
61035 			nargs = 0;
61036 		}
61037 
61038 		/* Opcode slot C is used in a non-standard way, so shuffling
61039 		 * is not allowed.
61040 		 */
61041 		duk__emit_a_b_c(comp_ctx,
61042 		              DUK_OP_NEW | DUK__EMIT_FLAG_NO_SHUFFLE_A | DUK__EMIT_FLAG_NO_SHUFFLE_C,
61043 		              0 /*unused*/,
61044 		              reg_target /*target*/,
61045 		              nargs /*num_args*/);
61046 
61047 		DUK_DDD(DUK_DDDPRINT("end parsing new expression"));
61048 
61049 		res->t = DUK_IVAL_PLAIN;
61050 		res->x1.t = DUK_ISPEC_REGCONST;
61051 		res->x1.regconst = (duk_regconst_t) reg_target;
61052 		return;
61053 	}
61054 
61055 	/* FUNCTION EXPRESSIONS */
61056 
61057 	case DUK_TOK_FUNCTION: {
61058 		/* Function expression.  Note that any statement beginning with 'function'
61059 		 * is handled by the statement parser as a function declaration, or a
61060 		 * non-standard function expression/statement (or a SyntaxError).  We only
61061 		 * handle actual function expressions (occurring inside an expression) here.
61062 		 *
61063 		 * O(depth^2) parse count for inner functions is handled by recording a
61064 		 * lexer offset on the first compilation pass, so that the function can
61065 		 * be efficiently skipped on the second pass.  This is encapsulated into
61066 		 * duk__parse_func_like_fnum().
61067 		 */
61068 
61069 		duk_reg_t reg_temp;
61070 		duk_int_t fnum;
61071 
61072 		reg_temp = DUK__ALLOCTEMP(comp_ctx);
61073 
61074 		/* curr_token follows 'function' */
61075 		fnum = duk__parse_func_like_fnum(comp_ctx, 0 /*is_decl*/, 0 /*is_setget*/);
61076 		DUK_DDD(DUK_DDDPRINT("parsed inner function -> fnum %ld", (long) fnum));
61077 
61078 		duk__emit_a_bc(comp_ctx,
61079 		               DUK_OP_CLOSURE,
61080 		               (duk_regconst_t) reg_temp /*a*/,
61081 		               (duk_regconst_t) fnum /*bc*/);
61082 
61083 		res->t = DUK_IVAL_PLAIN;
61084 		res->x1.t = DUK_ISPEC_REGCONST;
61085 		res->x1.regconst = (duk_regconst_t) reg_temp;
61086 		return;
61087 	}
61088 
61089 	/* UNARY EXPRESSIONS */
61090 
61091 	case DUK_TOK_DELETE: {
61092 		/* Delete semantics are a bit tricky.  The description in E5 specification
61093 		 * is kind of confusing, because it distinguishes between resolvability of
61094 		 * a reference (which is only known at runtime) seemingly at compile time
61095 		 * (= SyntaxError throwing).
61096 		 */
61097 		duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
61098 		if (res->t == DUK_IVAL_VAR) {
61099 			/* not allowed in strict mode, regardless of whether resolves;
61100 			 * in non-strict mode DELVAR handles both non-resolving and
61101 			 * resolving cases (the specification description is a bit confusing).
61102 			 */
61103 
61104 			duk_reg_t reg_temp;
61105 			duk_reg_t reg_varbind;
61106 			duk_regconst_t rc_varname;
61107 
61108 			if (comp_ctx->curr_func.is_strict) {
61109 				DUK_ERROR_SYNTAX(thr, DUK_STR_CANNOT_DELETE_IDENTIFIER);
61110 			}
61111 
61112 			DUK__SETTEMP(comp_ctx, temp_at_entry);
61113 			reg_temp = DUK__ALLOCTEMP(comp_ctx);
61114 
61115 			duk_dup(ctx, res->x1.valstack_idx);
61116 			if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
61117 				/* register bound variables are non-configurable -> always false */
61118 				duk__emit_extraop_bc(comp_ctx,
61119 				                     DUK_EXTRAOP_LDFALSE,
61120 				                     (duk_regconst_t) reg_temp);
61121 			} else {
61122 				duk_dup(ctx, res->x1.valstack_idx);
61123 				rc_varname = duk__getconst(comp_ctx);
61124 				duk__emit_a_b(comp_ctx,
61125 				              DUK_OP_DELVAR,
61126 				              (duk_regconst_t) reg_temp,
61127 				              (duk_regconst_t) rc_varname);
61128 			}
61129 			res->t = DUK_IVAL_PLAIN;
61130 			res->x1.t = DUK_ISPEC_REGCONST;
61131 			res->x1.regconst = (duk_regconst_t) reg_temp;
61132 		} else if (res->t == DUK_IVAL_PROP) {
61133 			duk_reg_t reg_temp;
61134 			duk_reg_t reg_obj;
61135 			duk_regconst_t rc_key;
61136 
61137 			DUK__SETTEMP(comp_ctx, temp_at_entry);
61138 			reg_temp = DUK__ALLOCTEMP(comp_ctx);
61139 			reg_obj = duk__ispec_toregconst_raw(comp_ctx, &res->x1, -1 /*forced_reg*/, 0 /*flags*/);  /* don't allow const */
61140 			rc_key = duk__ispec_toregconst_raw(comp_ctx, &res->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
61141 			duk__emit_a_b_c(comp_ctx,
61142 			                DUK_OP_DELPROP,
61143 			                (duk_regconst_t) reg_temp,
61144 			                (duk_regconst_t) reg_obj,
61145 			                rc_key);
61146 
61147 			res->t = DUK_IVAL_PLAIN;
61148 			res->x1.t = DUK_ISPEC_REGCONST;
61149 			res->x1.regconst = (duk_regconst_t) reg_temp;
61150 		} else {
61151 			/* non-Reference deletion is always 'true', even in strict mode */
61152 			duk_push_true(ctx);
61153 			goto plain_value;
61154 		}
61155 		return;
61156 	}
61157 	case DUK_TOK_VOID: {
61158 		duk__expr_toplain_ignore(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
61159 		duk_push_undefined(ctx);
61160 		goto plain_value;
61161 	}
61162 	case DUK_TOK_TYPEOF: {
61163 		/* 'typeof' must handle unresolvable references without throwing
61164 		 * a ReferenceError (E5 Section 11.4.3).  Register mapped values
61165 		 * will never be unresolvable so special handling is only required
61166 		 * when an identifier is a "slow path" one.
61167 		 */
61168 		duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
61169 
61170 		if (res->t == DUK_IVAL_VAR) {
61171 			duk_reg_t reg_varbind;
61172 			duk_regconst_t rc_varname;
61173 			duk_reg_t reg_temp;
61174 
61175 			duk_dup(ctx, res->x1.valstack_idx);
61176 			if (!duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
61177 				DUK_DDD(DUK_DDDPRINT("typeof for an identifier name which could not be resolved "
61178 				                     "at compile time, need to use special run-time handling"));
61179 				reg_temp = DUK__ALLOCTEMP(comp_ctx);
61180 				duk__emit_extraop_b_c(comp_ctx,
61181 				                      DUK_EXTRAOP_TYPEOFID | DUK__EMIT_FLAG_B_IS_TARGET,
61182 				                      reg_temp,
61183 				                      rc_varname);
61184 				res->t = DUK_IVAL_PLAIN;
61185 				res->x1.t = DUK_ISPEC_REGCONST;
61186 				res->x1.regconst = (duk_regconst_t) reg_temp;
61187 				return;
61188 			}
61189 		}
61190 
61191 		args = (DUK_EXTRAOP_TYPEOF << 8) + 0;
61192 		goto unary_extraop;
61193 	}
61194 	case DUK_TOK_INCREMENT: {
61195 		args = (DUK_OP_PREINCR << 8) + 0;
61196 		goto preincdec;
61197 	}
61198 	case DUK_TOK_DECREMENT: {
61199 		args = (DUK_OP_PREDECR << 8) + 0;
61200 		goto preincdec;
61201 	}
61202 	case DUK_TOK_ADD: {
61203 		/* unary plus */
61204 		duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
61205 		if (res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_VALUE &&
61206 		    duk_is_number(ctx, res->x1.valstack_idx)) {
61207 			/* unary plus of a number is identity */
61208 			;
61209 			return;
61210 		}
61211 		args = (DUK_EXTRAOP_UNP << 8) + 0;
61212 		goto unary_extraop;
61213 	}
61214 	case DUK_TOK_SUB: {
61215 		/* unary minus */
61216 		duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
61217 		if (res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_VALUE &&
61218 		    duk_is_number(ctx, res->x1.valstack_idx)) {
61219 			/* this optimization is important to handle negative literals
61220 			 * (which are not directly provided by the lexical grammar)
61221 			 */
61222 			duk_tval *tv_num;
61223 			duk_double_union du;
61224 
61225 			tv_num = DUK_GET_TVAL_POSIDX(ctx, res->x1.valstack_idx);
61226 			DUK_ASSERT(tv_num != NULL);
61227 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_num));
61228 			du.d = DUK_TVAL_GET_NUMBER(tv_num);
61229 			du.d = -du.d;
61230 			DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);
61231 			DUK_TVAL_SET_NUMBER(tv_num, du.d);
61232 			return;
61233 		}
61234 		args = (DUK_EXTRAOP_UNM << 8) + 0;
61235 		goto unary_extraop;
61236 	}
61237 	case DUK_TOK_BNOT: {
61238 		duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
61239 		args = (DUK_EXTRAOP_BNOT << 8) + 0;
61240 		goto unary_extraop;
61241 	}
61242 	case DUK_TOK_LNOT: {
61243 		duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
61244 		if (res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_VALUE) {
61245 			/* Very minimal inlining to handle common idioms '!0' and '!1',
61246 			 * and also boolean arguments like '!false' and '!true'.
61247 			 */
61248 			duk_tval *tv_val;
61249 
61250 			tv_val = DUK_GET_TVAL_POSIDX(ctx, res->x1.valstack_idx);
61251 			DUK_ASSERT(tv_val != NULL);
61252 			if (DUK_TVAL_IS_NUMBER(tv_val)) {
61253 				duk_double_t d;
61254 				d = DUK_TVAL_GET_NUMBER(tv_val);
61255 				if (d == 0.0) {
61256 					/* Matches both +0 and -0 on purpose. */
61257 					DUK_DDD(DUK_DDDPRINT("inlined lnot: !0 -> true"));
61258 					DUK_TVAL_SET_BOOLEAN_TRUE(tv_val);
61259 					return;
61260 				} else if (d == 1.0) {
61261 					DUK_DDD(DUK_DDDPRINT("inlined lnot: !1 -> false"));
61262 					DUK_TVAL_SET_BOOLEAN_FALSE(tv_val);
61263 					return;
61264 				}
61265 			} else if (DUK_TVAL_IS_BOOLEAN(tv_val)) {
61266 				duk_small_int_t v;
61267 				v = DUK_TVAL_GET_BOOLEAN(tv_val);
61268 				DUK_DDD(DUK_DDDPRINT("inlined lnot boolean: %ld", (long) v));
61269 				DUK_ASSERT(v == 0 || v == 1);
61270 				DUK_TVAL_SET_BOOLEAN(tv_val, v ^ 0x01);
61271 				return;
61272 			}
61273 		}
61274 		args = (DUK_EXTRAOP_LNOT << 8) + 0;
61275 		goto unary_extraop;
61276 	}
61277 
61278 	}  /* end switch */
61279 
61280 	DUK_ERROR_SYNTAX(thr, DUK_STR_PARSE_ERROR);
61281 	return;
61282 
61283  unary_extraop:
61284 	{
61285 		/* Note: must coerce to a (writable) temp register, so that e.g. "!x" where x
61286 		 * is a reg-mapped variable works correctly (does not mutate the variable register).
61287 		 */
61288 
61289 		duk_reg_t reg_temp;
61290 		reg_temp = duk__ivalue_toregconst_raw(comp_ctx, res, -1 /*forced_reg*/, DUK__IVAL_FLAG_REQUIRE_TEMP /*flags*/);
61291 		duk__emit_extraop_bc(comp_ctx,
61292 		                     (args >> 8),
61293 		                     (duk_regconst_t) reg_temp);
61294 		res->t = DUK_IVAL_PLAIN;
61295 		res->x1.t = DUK_ISPEC_REGCONST;
61296 		res->x1.regconst = (duk_regconst_t) reg_temp;
61297 		return;
61298 	}
61299 
61300  preincdec:
61301 	{
61302 		/* preincrement and predecrement */
61303 		duk_reg_t reg_res;
61304 		duk_small_uint_t args_op = args >> 8;
61305 
61306 		/* Specific assumptions for opcode numbering. */
61307 		DUK_ASSERT(DUK_OP_PREINCR + 4 == DUK_OP_PREINCV);
61308 		DUK_ASSERT(DUK_OP_PREDECR + 4 == DUK_OP_PREDECV);
61309 		DUK_ASSERT(DUK_OP_PREINCR + 8 == DUK_OP_PREINCP);
61310 		DUK_ASSERT(DUK_OP_PREDECR + 8 == DUK_OP_PREDECP);
61311 
61312 		reg_res = DUK__ALLOCTEMP(comp_ctx);
61313 
61314 		duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
61315 		if (res->t == DUK_IVAL_VAR) {
61316 			duk_hstring *h_varname;
61317 			duk_reg_t reg_varbind;
61318 			duk_regconst_t rc_varname;
61319 
61320 			h_varname = duk_get_hstring(ctx, res->x1.valstack_idx);
61321 			DUK_ASSERT(h_varname != NULL);
61322 
61323 			if (duk__hstring_is_eval_or_arguments_in_strict_mode(comp_ctx, h_varname)) {
61324 				goto syntax_error;
61325 			}
61326 
61327 			duk_dup(ctx, res->x1.valstack_idx);
61328 			if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
61329 				duk__emit_a_bc(comp_ctx,
61330 				               args_op,  /* e.g. DUK_OP_PREINCR */
61331 				               (duk_regconst_t) reg_res,
61332 				               (duk_regconst_t) reg_varbind);
61333 			} else {
61334 				duk__emit_a_bc(comp_ctx,
61335 				                args_op + 4,  /* e.g. DUK_OP_PREINCV */
61336 				                (duk_regconst_t) reg_res,
61337 				                rc_varname);
61338 			}
61339 
61340 			DUK_DDD(DUK_DDDPRINT("preincdec to '%!O' -> reg_varbind=%ld, rc_varname=%ld",
61341 			                     (duk_heaphdr *) h_varname, (long) reg_varbind, (long) rc_varname));
61342 		} else if (res->t == DUK_IVAL_PROP) {
61343 			duk_reg_t reg_obj;  /* allocate to reg only (not const) */
61344 			duk_regconst_t rc_key;
61345 			reg_obj = duk__ispec_toregconst_raw(comp_ctx, &res->x1, -1 /*forced_reg*/, 0 /*flags*/);  /* don't allow const */
61346 			rc_key = duk__ispec_toregconst_raw(comp_ctx, &res->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
61347 			duk__emit_a_b_c(comp_ctx,
61348 			                args_op + 8,  /* e.g. DUK_OP_PREINCP */
61349 			                (duk_regconst_t) reg_res,
61350 			                (duk_regconst_t) reg_obj,
61351 			                rc_key);
61352 		} else {
61353 			/* Technically return value is not needed because INVLHS will
61354 			 * unconditially throw a ReferenceError.  Coercion is necessary
61355 			 * for proper semantics (consider ToNumber() called for an object).
61356 			 * Use DUK_EXTRAOP_UNP with a dummy register to get ToNumber().
61357 			 */
61358 
61359 			duk__ivalue_toforcedreg(comp_ctx, res, reg_res);
61360 			duk__emit_extraop_bc(comp_ctx,
61361 			                     DUK_EXTRAOP_UNP,
61362 			                     reg_res);  /* for side effects, result ignored */
61363 			duk__emit_extraop_only(comp_ctx,
61364 			                       DUK_EXTRAOP_INVLHS);
61365 		}
61366 		res->t = DUK_IVAL_PLAIN;
61367 		res->x1.t = DUK_ISPEC_REGCONST;
61368 		res->x1.regconst = (duk_regconst_t) reg_res;
61369 		DUK__SETTEMP(comp_ctx, reg_res + 1);
61370 		return;
61371 	}
61372 
61373  plain_value:
61374 	{
61375 		/* Stack top contains plain value */
61376 		res->t = DUK_IVAL_PLAIN;
61377 		res->x1.t = DUK_ISPEC_VALUE;
61378 		duk_replace(ctx, res->x1.valstack_idx);
61379 		return;
61380 	}
61381 
61382  syntax_error:
61383 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_EXPRESSION);
61384 }
61385 
61386 /* XXX: add flag to indicate whether caller cares about return value; this
61387  * affects e.g. handling of assignment expressions.  This change needs API
61388  * changes elsewhere too.
61389  */
61390 DUK_LOCAL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_ivalue *res) {
61391 	duk_hthread *thr = comp_ctx->thr;
61392 	duk_context *ctx = (duk_context *) thr;
61393 	duk_token *tk;
61394 	duk_small_int_t tok;
61395 	duk_uint32_t args;  /* temp variable to pass constants and flags to shared code */
61396 
61397 	/*
61398 	 *  ctx->prev_token     token to process with duk__expr_led()
61399 	 *  ctx->curr_token     updated by caller
61400 	 */
61401 
61402 	comp_ctx->curr_func.led_count++;
61403 
61404 	/* The token in the switch has already been eaten here */
61405 	tk = &comp_ctx->prev_token;
61406 	tok = tk->t;
61407 
61408 	DUK_DDD(DUK_DDDPRINT("duk__expr_led(), prev_token.t=%ld, allow_in=%ld, paren_level=%ld",
61409 	                     (long) tk->t, (long) comp_ctx->curr_func.allow_in, (long) comp_ctx->curr_func.paren_level));
61410 
61411 	/* XXX: default priority for infix operators is duk__expr_lbp(tok) -> get it here? */
61412 
61413 	switch (tok) {
61414 
61415 	/* PRIMARY EXPRESSIONS */
61416 
61417 	case DUK_TOK_PERIOD: {
61418 		/* Property access expressions are critical for correct LHS ordering,
61419 		 * see comments in duk__expr()!
61420 		 *
61421 		 * A conservative approach would be to use duk__ivalue_totempconst()
61422 		 * for 'left'.  However, allowing a reg-bound variable seems safe here
61423 		 * and is nice because "foo.bar" is a common expression.  If the ivalue
61424 		 * is used in an expression a GETPROP will occur before any changes to
61425 		 * the base value can occur.  If the ivalue is used as an assignment
61426 		 * LHS, the assignment code will ensure the base value is safe from
61427 		 * RHS mutation.
61428 		 */
61429 
61430 		/* XXX: This now coerces an identifier into a GETVAR to a temp, which
61431 		 * causes an extra LDREG in call setup.  It's sufficient to coerce to a
61432 		 * unary ivalue?
61433 		 */
61434 		duk__ivalue_toplain(comp_ctx, left);
61435 
61436 		/* NB: must accept reserved words as property name */
61437 		if (comp_ctx->curr_token.t_nores != DUK_TOK_IDENTIFIER) {
61438 			DUK_ERROR_SYNTAX(thr, DUK_STR_EXPECTED_IDENTIFIER);
61439 		}
61440 
61441 		res->t = DUK_IVAL_PROP;
61442 		duk__copy_ispec(comp_ctx, &left->x1, &res->x1);  /* left.x1 -> res.x1 */
61443 		DUK_ASSERT(comp_ctx->curr_token.str1 != NULL);
61444 		duk_push_hstring(ctx, comp_ctx->curr_token.str1);
61445 		duk_replace(ctx, res->x2.valstack_idx);
61446 		res->x2.t = DUK_ISPEC_VALUE;
61447 
61448 		/* special RegExp literal handling after IdentifierName */
61449 		comp_ctx->curr_func.reject_regexp_in_adv = 1;
61450 
61451 		duk__advance(comp_ctx);
61452 		return;
61453 	}
61454 	case DUK_TOK_LBRACKET: {
61455 		/* Property access expressions are critical for correct LHS ordering,
61456 		 * see comments in duk__expr()!
61457 		 */
61458 
61459 		/* XXX: optimize temp reg use */
61460 		/* XXX: similar coercion issue as in DUK_TOK_PERIOD */
61461 		/* XXX: coerce to regs? it might be better for enumeration use, where the
61462 		 * same PROP ivalue is used multiple times.  Or perhaps coerce PROP further
61463 		 * there?
61464 		 */
61465 		/* XXX: for simple cases like x['y'] an unnecessary LDREG is
61466 		 * emitted for the base value; could avoid it if we knew that
61467 		 * the key expression is safe (e.g. just a single literal).
61468 		 */
61469 
61470 		/* The 'left' value must not be a register bound variable
61471 		 * because it may be mutated during the rest of the expression
61472 		 * and E5.1 Section 11.2.1 specifies the order of evaluation
61473 		 * so that the base value is evaluated first.
61474 		 * See: test-bug-nested-prop-mutate.js.
61475 		 */
61476 		duk__ivalue_totempconst(comp_ctx, left);
61477 		duk__expr_toplain(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);  /* Expression, ']' terminates */
61478 		duk__advance_expect(comp_ctx, DUK_TOK_RBRACKET);
61479 
61480 		res->t = DUK_IVAL_PROP;
61481 		duk__copy_ispec(comp_ctx, &res->x1, &res->x2);   /* res.x1 -> res.x2 */
61482 		duk__copy_ispec(comp_ctx, &left->x1, &res->x1);  /* left.x1 -> res.x1 */
61483 		return;
61484 	}
61485 	case DUK_TOK_LPAREN: {
61486 		/* function call */
61487 		duk_reg_t reg_cs = DUK__ALLOCTEMPS(comp_ctx, 2);
61488 		duk_int_t nargs;
61489 		duk_small_uint_t call_flags = 0;
61490 
61491 		/*
61492 		 *  XXX: attempt to get the call result to "next temp" whenever
61493 		 *  possible to avoid unnecessary register shuffles.
61494 		 *
61495 		 *  XXX: CSPROP (and CSREG) can overwrite the call target register, and save one temp,
61496 		 *  if the call target is a temporary register and at the top of the temp reg "stack".
61497 		 */
61498 
61499 		/*
61500 		 *  Setup call: target and 'this' binding.  Three cases:
61501 		 *
61502 		 *    1. Identifier base (e.g. "foo()")
61503 		 *    2. Property base (e.g. "foo.bar()")
61504 		 *    3. Register base (e.g. "foo()()"; i.e. when a return value is a function)
61505 		 */
61506 
61507 		if (left->t == DUK_IVAL_VAR) {
61508 			duk_hstring *h_varname;
61509 			duk_reg_t reg_varbind;
61510 			duk_regconst_t rc_varname;
61511 
61512 			DUK_DDD(DUK_DDDPRINT("function call with identifier base"));
61513 
61514 			h_varname = duk_get_hstring(ctx, left->x1.valstack_idx);
61515 			DUK_ASSERT(h_varname != NULL);
61516 			if (h_varname == DUK_HTHREAD_STRING_EVAL(thr)) {
61517 				/* Potential direct eval call detected, flag the CALL
61518 				 * so that a run-time "direct eval" check is made and
61519 				 * special behavior may be triggered.  Note that this
61520 				 * does not prevent 'eval' from being register bound.
61521 				 */
61522 				DUK_DDD(DUK_DDDPRINT("function call with identifier 'eval' "
61523 				                     "-> enabling EVALCALL flag, marking function "
61524 				                     "as may_direct_eval"));
61525 				call_flags |= DUK_BC_CALL_FLAG_EVALCALL;
61526 
61527 				comp_ctx->curr_func.may_direct_eval = 1;
61528 			}
61529 
61530 			duk_dup(ctx, left->x1.valstack_idx);
61531 			if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
61532 				duk__emit_a_b(comp_ctx,
61533 				              DUK_OP_CSREG,
61534 				              (duk_regconst_t) (reg_cs + 0),
61535 				              (duk_regconst_t) reg_varbind);
61536 			} else {
61537 				duk__emit_a_b(comp_ctx,
61538 				              DUK_OP_CSVAR,
61539 				              (duk_regconst_t) (reg_cs + 0),
61540 				              rc_varname);
61541 			}
61542 		} else if (left->t == DUK_IVAL_PROP) {
61543 			DUK_DDD(DUK_DDDPRINT("function call with property base"));
61544 
61545 			duk__ispec_toforcedreg(comp_ctx, &left->x1, reg_cs + 0);  /* base */
61546 			duk__ispec_toforcedreg(comp_ctx, &left->x2, reg_cs + 1);  /* key */
61547 			duk__emit_a_b_c(comp_ctx,
61548 			                DUK_OP_CSPROP,
61549 			                (duk_regconst_t) (reg_cs + 0),
61550 			                (duk_regconst_t) (reg_cs + 0),
61551 			                (duk_regconst_t) (reg_cs + 1));  /* in-place setup */
61552 		} else {
61553 			DUK_DDD(DUK_DDDPRINT("function call with register base"));
61554 
61555 			duk__ivalue_toforcedreg(comp_ctx, left, reg_cs + 0);
61556 			duk__emit_a_b(comp_ctx,
61557 			              DUK_OP_CSREG,
61558 			              (duk_regconst_t) (reg_cs + 0),
61559 			              (duk_regconst_t) (reg_cs + 0));  /* in-place setup */
61560 		}
61561 
61562 		DUK__SETTEMP(comp_ctx, reg_cs + 2);
61563 		nargs = duk__parse_arguments(comp_ctx, res);  /* parse args starting from "next temp" */
61564 
61565 		/* Tailcalls are handled by back-patching the TAILCALL flag to the
61566 		 * already emitted instruction later (in return statement parser).
61567 		 * Since A and C have a special meaning here, they cannot be "shuffled".
61568 		 */
61569 
61570 		duk__emit_a_b_c(comp_ctx,
61571 		                DUK_OP_CALL | DUK__EMIT_FLAG_NO_SHUFFLE_A | DUK__EMIT_FLAG_NO_SHUFFLE_C,
61572 		                (duk_regconst_t) call_flags /*flags*/,
61573 		                (duk_regconst_t) reg_cs /*basereg*/,
61574 		                (duk_regconst_t) nargs /*numargs*/);
61575 		DUK__SETTEMP(comp_ctx, reg_cs + 1);    /* result in csreg */
61576 
61577 		res->t = DUK_IVAL_PLAIN;
61578 		res->x1.t = DUK_ISPEC_REGCONST;
61579 		res->x1.regconst = (duk_regconst_t) reg_cs;
61580 		return;
61581 	}
61582 
61583 	/* POSTFIX EXPRESSION */
61584 
61585 	case DUK_TOK_INCREMENT: {
61586 		args = (DUK_OP_POSTINCR << 8) + 0;
61587 		goto postincdec;
61588 	}
61589 	case DUK_TOK_DECREMENT: {
61590 		args = (DUK_OP_POSTDECR << 8) + 0;
61591 		goto postincdec;
61592 	}
61593 
61594 	/* MULTIPLICATIVE EXPRESSION */
61595 
61596 	case DUK_TOK_MUL: {
61597 		args = (DUK_OP_MUL << 8) + DUK__BP_MULTIPLICATIVE;  /* UnaryExpression */
61598 		goto binary;
61599 	}
61600 	case DUK_TOK_DIV: {
61601 		args = (DUK_OP_DIV << 8) + DUK__BP_MULTIPLICATIVE;  /* UnaryExpression */
61602 		goto binary;
61603 	}
61604 	case DUK_TOK_MOD: {
61605 		args = (DUK_OP_MOD << 8) + DUK__BP_MULTIPLICATIVE;  /* UnaryExpression */
61606 		goto binary;
61607 	}
61608 
61609 	/* ADDITIVE EXPRESSION */
61610 
61611 	case DUK_TOK_ADD: {
61612 		args = (DUK_OP_ADD << 8) + DUK__BP_ADDITIVE;  /* MultiplicativeExpression */
61613 		goto binary;
61614 	}
61615 	case DUK_TOK_SUB: {
61616 		args = (DUK_OP_SUB << 8) + DUK__BP_ADDITIVE;  /* MultiplicativeExpression */
61617 		goto binary;
61618 	}
61619 
61620 	/* SHIFT EXPRESSION */
61621 
61622 	case DUK_TOK_ALSHIFT: {
61623 		/* << */
61624 		args = (DUK_OP_BASL << 8) + DUK__BP_SHIFT;
61625 		goto binary;
61626 	}
61627 	case DUK_TOK_ARSHIFT: {
61628 		/* >> */
61629 		args = (DUK_OP_BASR << 8) + DUK__BP_SHIFT;
61630 		goto binary;
61631 	}
61632 	case DUK_TOK_RSHIFT: {
61633 		/* >>> */
61634 		args = (DUK_OP_BLSR << 8) + DUK__BP_SHIFT;
61635 		goto binary;
61636 	}
61637 
61638 	/* RELATIONAL EXPRESSION */
61639 
61640 	case DUK_TOK_LT: {
61641 		/* < */
61642 		args = (DUK_OP_LT << 8) + DUK__BP_RELATIONAL;
61643 		goto binary;
61644 	}
61645 	case DUK_TOK_GT: {
61646 		args = (DUK_OP_GT << 8) + DUK__BP_RELATIONAL;
61647 		goto binary;
61648 	}
61649 	case DUK_TOK_LE: {
61650 		args = (DUK_OP_LE << 8) + DUK__BP_RELATIONAL;
61651 		goto binary;
61652 	}
61653 	case DUK_TOK_GE: {
61654 		args = (DUK_OP_GE << 8) + DUK__BP_RELATIONAL;
61655 		goto binary;
61656 	}
61657 	case DUK_TOK_INSTANCEOF: {
61658 		args = (1 << 16 /*is_extra*/) + (DUK_EXTRAOP_INSTOF << 8) + DUK__BP_RELATIONAL;
61659 		goto binary;
61660 	}
61661 	case DUK_TOK_IN: {
61662 		args = (1 << 16 /*is_extra*/) + (DUK_EXTRAOP_IN << 8) + DUK__BP_RELATIONAL;
61663 		goto binary;
61664 	}
61665 
61666 	/* EQUALITY EXPRESSION */
61667 
61668 	case DUK_TOK_EQ: {
61669 		args = (DUK_OP_EQ << 8) + DUK__BP_EQUALITY;
61670 		goto binary;
61671 	}
61672 	case DUK_TOK_NEQ: {
61673 		args = (DUK_OP_NEQ << 8) + DUK__BP_EQUALITY;
61674 		goto binary;
61675 	}
61676 	case DUK_TOK_SEQ: {
61677 		args = (DUK_OP_SEQ << 8) + DUK__BP_EQUALITY;
61678 		goto binary;
61679 	}
61680 	case DUK_TOK_SNEQ: {
61681 		args = (DUK_OP_SNEQ << 8) + DUK__BP_EQUALITY;
61682 		goto binary;
61683 	}
61684 
61685 	/* BITWISE EXPRESSIONS */
61686 
61687 	case DUK_TOK_BAND: {
61688 		args = (DUK_OP_BAND << 8) + DUK__BP_BAND;
61689 		goto binary;
61690 	}
61691 	case DUK_TOK_BXOR: {
61692 		args = (DUK_OP_BXOR << 8) + DUK__BP_BXOR;
61693 		goto binary;
61694 	}
61695 	case DUK_TOK_BOR: {
61696 		args = (DUK_OP_BOR << 8) + DUK__BP_BOR;
61697 		goto binary;
61698 	}
61699 
61700 	/* LOGICAL EXPRESSIONS */
61701 
61702 	case DUK_TOK_LAND: {
61703 		/* syntactically left-associative but parsed as right-associative */
61704 		args = (1 << 8) + DUK__BP_LAND - 1;
61705 		goto binary_logical;
61706 	}
61707 	case DUK_TOK_LOR: {
61708 		/* syntactically left-associative but parsed as right-associative */
61709 		args = (0 << 8) + DUK__BP_LOR - 1;
61710 		goto binary_logical;
61711 	}
61712 
61713 	/* CONDITIONAL EXPRESSION */
61714 
61715 	case DUK_TOK_QUESTION: {
61716 		/* XXX: common reg allocation need is to reuse a sub-expression's temp reg,
61717 		 * but only if it really is a temp.  Nothing fancy here now.
61718 		 */
61719 		duk_reg_t reg_temp;
61720 		duk_int_t pc_jump1;
61721 		duk_int_t pc_jump2;
61722 
61723 		reg_temp = DUK__ALLOCTEMP(comp_ctx);
61724 		duk__ivalue_toforcedreg(comp_ctx, left, reg_temp);
61725 		duk__emit_if_true_skip(comp_ctx, reg_temp);
61726 		pc_jump1 = duk__emit_jump_empty(comp_ctx);  /* jump to false */
61727 		duk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp /*forced_reg*/);  /* AssignmentExpression */
61728 		duk__advance_expect(comp_ctx, DUK_TOK_COLON);
61729 		pc_jump2 = duk__emit_jump_empty(comp_ctx);  /* jump to end */
61730 		duk__patch_jump_here(comp_ctx, pc_jump1);
61731 		duk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp /*forced_reg*/);  /* AssignmentExpression */
61732 		duk__patch_jump_here(comp_ctx, pc_jump2);
61733 
61734 		DUK__SETTEMP(comp_ctx, reg_temp + 1);
61735 		res->t = DUK_IVAL_PLAIN;
61736 		res->x1.t = DUK_ISPEC_REGCONST;
61737 		res->x1.regconst = (duk_regconst_t) reg_temp;
61738 		return;
61739 	}
61740 
61741 	/* ASSIGNMENT EXPRESSION */
61742 
61743 	case DUK_TOK_EQUALSIGN: {
61744 		/*
61745 		 *  Assignments are right associative, allows e.g.
61746 		 *    a = 5;
61747 		 *    a += b = 9;   // same as a += (b = 9)
61748 		 *  -> expression value 14, a = 14, b = 9
61749 		 *
61750 		 *  Right associativiness is reflected in the BP for recursion,
61751 		 *  "-1" ensures assignment operations are allowed.
61752 		 *
61753 		 *  XXX: just use DUK__BP_COMMA (i.e. no need for 2-step bp levels)?
61754 		 */
61755 		args = (DUK_OP_NONE << 8) + DUK__BP_ASSIGNMENT - 1;   /* DUK_OP_NONE marks a 'plain' assignment */
61756 		goto assign;
61757 	}
61758 	case DUK_TOK_ADD_EQ: {
61759 		/* right associative */
61760 		args = (DUK_OP_ADD << 8) + DUK__BP_ASSIGNMENT - 1;
61761 		goto assign;
61762 	}
61763 	case DUK_TOK_SUB_EQ: {
61764 		/* right associative */
61765 		args = (DUK_OP_SUB << 8) + DUK__BP_ASSIGNMENT - 1;
61766 		goto assign;
61767 	}
61768 	case DUK_TOK_MUL_EQ: {
61769 		/* right associative */
61770 		args = (DUK_OP_MUL << 8) + DUK__BP_ASSIGNMENT - 1;
61771 		goto assign;
61772 	}
61773 	case DUK_TOK_DIV_EQ: {
61774 		/* right associative */
61775 		args = (DUK_OP_DIV << 8) + DUK__BP_ASSIGNMENT - 1;
61776 		goto assign;
61777 	}
61778 	case DUK_TOK_MOD_EQ: {
61779 		/* right associative */
61780 		args = (DUK_OP_MOD << 8) + DUK__BP_ASSIGNMENT - 1;
61781 		goto assign;
61782 	}
61783 	case DUK_TOK_ALSHIFT_EQ: {
61784 		/* right associative */
61785 		args = (DUK_OP_BASL << 8) + DUK__BP_ASSIGNMENT - 1;
61786 		goto assign;
61787 	}
61788 	case DUK_TOK_ARSHIFT_EQ: {
61789 		/* right associative */
61790 		args = (DUK_OP_BASR << 8) + DUK__BP_ASSIGNMENT - 1;
61791 		goto assign;
61792 	}
61793 	case DUK_TOK_RSHIFT_EQ: {
61794 		/* right associative */
61795 		args = (DUK_OP_BLSR << 8) + DUK__BP_ASSIGNMENT - 1;
61796 		goto assign;
61797 	}
61798 	case DUK_TOK_BAND_EQ: {
61799 		/* right associative */
61800 		args = (DUK_OP_BAND << 8) + DUK__BP_ASSIGNMENT - 1;
61801 		goto assign;
61802 	}
61803 	case DUK_TOK_BOR_EQ: {
61804 		/* right associative */
61805 		args = (DUK_OP_BOR << 8) + DUK__BP_ASSIGNMENT - 1;
61806 		goto assign;
61807 	}
61808 	case DUK_TOK_BXOR_EQ: {
61809 		/* right associative */
61810 		args = (DUK_OP_BXOR << 8) + DUK__BP_ASSIGNMENT - 1;
61811 		goto assign;
61812 	}
61813 
61814 	/* COMMA */
61815 
61816 	case DUK_TOK_COMMA: {
61817 		/* right associative */
61818 
61819 		duk__ivalue_toplain_ignore(comp_ctx, left);  /* need side effects, not value */
61820 		duk__expr_toplain(comp_ctx, res, DUK__BP_COMMA - 1 /*rbp_flags*/);
61821 
61822 		/* return 'res' (of right part) as our result */
61823 		return;
61824 	}
61825 
61826 	default: {
61827 		break;
61828 	}
61829 	}
61830 
61831 	DUK_D(DUK_DPRINT("parse error: unexpected token: %ld", (long) tok));
61832 	DUK_ERROR_SYNTAX(thr, DUK_STR_PARSE_ERROR);
61833 	return;
61834 
61835 #if 0
61836 	/* XXX: shared handling for 'duk__expr_lhs'? */
61837 	if (comp_ctx->curr_func.paren_level == 0 && XXX) {
61838 		comp_ctx->curr_func.duk__expr_lhs = 0;
61839 	}
61840 #endif
61841 
61842  binary:
61843 	/*
61844 	 *  Shared handling of binary operations
61845 	 *
61846 	 *  args = (is_extraop << 16) + (opcode << 8) + rbp
61847 	 */
61848 	{
61849 		duk__ivalue_toplain(comp_ctx, left);
61850 		duk__expr_toplain(comp_ctx, res, args & 0xff /*rbp_flags*/);
61851 
61852 		/* combine left->x1 and res->x1 (right->x1, really) -> (left->x1 OP res->x1) */
61853 		DUK_ASSERT(left->t == DUK_IVAL_PLAIN);
61854 		DUK_ASSERT(res->t == DUK_IVAL_PLAIN);
61855 
61856 		res->t = (args >> 16) ? DUK_IVAL_ARITH_EXTRAOP : DUK_IVAL_ARITH;
61857 		res->op = (args >> 8) & 0xff;
61858 
61859 		res->x2.t = res->x1.t;
61860 		res->x2.regconst = res->x1.regconst;
61861 		duk_copy(ctx, res->x1.valstack_idx, res->x2.valstack_idx);
61862 
61863 		res->x1.t = left->x1.t;
61864 		res->x1.regconst = left->x1.regconst;
61865 		duk_copy(ctx, left->x1.valstack_idx, res->x1.valstack_idx);
61866 
61867 		DUK_DDD(DUK_DDDPRINT("binary op, res: t=%ld, x1.t=%ld, x1.regconst=0x%08lx, x2.t=%ld, x2.regconst=0x%08lx",
61868 		                     (long) res->t, (long) res->x1.t, (unsigned long) res->x1.regconst, (long) res->x2.t, (unsigned long) res->x2.regconst));
61869 		return;
61870 	}
61871 
61872  binary_logical:
61873 	/*
61874 	 *  Shared handling for logical AND and logical OR.
61875 	 *
61876 	 *  args = (truthval << 8) + rbp
61877 	 *
61878 	 *  Truthval determines when to skip right-hand-side.
61879 	 *  For logical AND truthval=1, for logical OR truthval=0.
61880 	 *
61881 	 *  See doc/compiler.rst for discussion on compiling logical
61882 	 *  AND and OR expressions.  The approach here is very simplistic,
61883 	 *  generating extra jumps and multiple evaluations of truth values,
61884 	 *  but generates code on-the-fly with only local back-patching.
61885 	 *
61886 	 *  Both logical AND and OR are syntactically left-associated.
61887 	 *  However, logical ANDs are compiled as right associative
61888 	 *  expressions, i.e. "A && B && C" as "A && (B && C)", to allow
61889 	 *  skip jumps to skip over the entire tail.  Similarly for logical OR.
61890 	 */
61891 
61892 	{
61893 		duk_reg_t reg_temp;
61894 		duk_int_t pc_jump;
61895 		duk_small_uint_t args_truthval = args >> 8;
61896 		duk_small_uint_t args_rbp = args & 0xff;
61897 
61898 		/* XXX: unoptimal use of temps, resetting */
61899 
61900 		reg_temp = DUK__ALLOCTEMP(comp_ctx);
61901 
61902 		duk__ivalue_toforcedreg(comp_ctx, left, reg_temp);
61903 		duk__emit_a_b(comp_ctx,
61904 		              DUK_OP_IF | DUK__EMIT_FLAG_NO_SHUFFLE_A,
61905 		              (duk_regconst_t) args_truthval,
61906 		              (duk_regconst_t) reg_temp);  /* skip jump conditionally */
61907 		pc_jump = duk__emit_jump_empty(comp_ctx);
61908 		duk__expr_toforcedreg(comp_ctx, res, args_rbp /*rbp_flags*/, reg_temp /*forced_reg*/);
61909 		duk__patch_jump_here(comp_ctx, pc_jump);
61910 
61911 		res->t = DUK_IVAL_PLAIN;
61912 		res->x1.t = DUK_ISPEC_REGCONST;
61913 		res->x1.regconst = (duk_regconst_t) reg_temp;
61914 		return;
61915 	}
61916 
61917  assign:
61918 	/*
61919 	 *  Shared assignment expression handling
61920 	 *
61921 	 *  args = (opcode << 8) + rbp
61922 	 *
61923 	 *  If 'opcode' is DUK_OP_NONE, plain assignment without arithmetic.
61924 	 *  Syntactically valid left-hand-side forms which are not accepted as
61925 	 *  left-hand-side values (e.g. as in "f() = 1") must NOT cause a
61926 	 *  SyntaxError, but rather a run-time ReferenceError.
61927 	 *
61928 	 *  When evaluating X <op>= Y, the LHS (X) is conceptually evaluated
61929 	 *  to a temporary first.  The RHS is then evaluated.  Finally, the
61930 	 *  <op> is applied to the initial value of RHS (not the value after
61931 	 *  RHS evaluation), and written to X.  Doing so concretely generates
61932 	 *  inefficient code so we'd like to avoid the temporary when possible.
61933 	 *  See: https://github.com/svaarala/duktape/pull/992.
61934 	 *
61935 	 *  The expression value (final LHS value, written to RHS) is
61936 	 *  conceptually copied into a fresh temporary so that it won't
61937 	 *  change even if the LHS/RHS values change in outer expressions.
61938 	 *  For example, it'd be generally incorrect for the expression value
61939 	 *  to be the RHS register binding, unless there's a guarantee that it
61940 	 *  won't change during further expression evaluation.  Using the
61941 	 *  temporary concretely produces inefficient bytecode, so we try to
61942 	 *  avoid the extra temporary for some known-to-be-safe cases.
61943 	 *  Currently the only safe case we detect is a "top level assignment",
61944 	 *  for example "x = y + z;", where the assignment expression value is
61945 	 *  ignored.
61946 	 *  See: test-dev-assign-expr.js and test-bug-assign-mutate-gh381.js.
61947 	 */
61948 
61949 	{
61950 		duk_small_uint_t args_op = args >> 8;
61951 		duk_small_uint_t args_rbp = args & 0xff;
61952 		duk_bool_t toplevel_assign;
61953 
61954 		/* XXX: here we need to know if 'left' is left-hand-side compatible.
61955 		 * That information is no longer available from current expr parsing
61956 		 * state; it would need to be carried into the 'left' ivalue or by
61957 		 * some other means.
61958 		 */
61959 
61960 		/* A top-level assignment is e.g. "x = y;".  For these it's safe
61961 		 * to use the RHS as-is as the expression value, even if the RHS
61962 		 * is a reg-bound identifier.  The RHS ('res') is right associative
61963 		 * so it has consumed all other assignment level operations; the
61964 		 * only relevant lower binding power construct is comma operator
61965 		 * which will ignore the expression value provided here.  Usually
61966 		 * the top level assignment expression value is ignored, but it
61967 		 * is relevant for e.g. eval code.
61968 		 */
61969 		toplevel_assign = (comp_ctx->curr_func.nud_count == 1 && /* one token before */
61970 		                   comp_ctx->curr_func.led_count == 1);  /* one operator (= assign) */
61971 		DUK_DDD(DUK_DDDPRINT("assignment: nud_count=%ld, led_count=%ld, toplevel_assign=%ld",
61972 		                     (long) comp_ctx->curr_func.nud_count,
61973 		                     (long) comp_ctx->curr_func.led_count,
61974 		                     (long) toplevel_assign));
61975 
61976 		if (left->t == DUK_IVAL_VAR) {
61977 			duk_hstring *h_varname;
61978 			duk_reg_t reg_varbind;
61979 			duk_regconst_t rc_varname;
61980 
61981 			DUK_ASSERT(left->x1.t == DUK_ISPEC_VALUE);  /* LHS is already side effect free */
61982 
61983 			h_varname = duk_get_hstring(ctx, left->x1.valstack_idx);
61984 			DUK_ASSERT(h_varname != NULL);
61985 			if (duk__hstring_is_eval_or_arguments_in_strict_mode(comp_ctx, h_varname)) {
61986 				/* E5 Section 11.13.1 (and others for other assignments), step 4. */
61987 				goto syntax_error_lvalue;
61988 			}
61989 			duk_dup(ctx, left->x1.valstack_idx);
61990 			(void) duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname);
61991 
61992 			if (args_op == DUK_OP_NONE) {
61993 				duk__expr(comp_ctx, res, args_rbp /*rbp_flags*/);
61994 				if (toplevel_assign) {
61995 					/* Any 'res' will do. */
61996 					DUK_DDD(DUK_DDDPRINT("plain assignment, toplevel assign, use as is"));
61997 				} else {
61998 					/* 'res' must be a plain ivalue, and not register-bound variable. */
61999 					DUK_DDD(DUK_DDDPRINT("plain assignment, not toplevel assign, ensure not a reg-bound identifier"));
62000 					if (res->t != DUK_IVAL_PLAIN || (res->x1.t == DUK_ISPEC_REGCONST &&
62001 					                                 (res->x1.regconst & DUK__CONST_MARKER) == 0 &&
62002 					                                 !DUK__ISTEMP(comp_ctx, res->x1.regconst))) {
62003 						duk__ivalue_totempconst(comp_ctx, res);
62004 					}
62005 				}
62006 			} else {
62007 				/* For X <op>= Y we need to evaluate the pre-op
62008 				 * value of X before evaluating the RHS: the RHS
62009 				 * can change X, but when we do <op> we must use
62010 				 * the pre-op value.
62011 				 */
62012 				duk_reg_t reg_temp;
62013 
62014 				reg_temp = DUK__ALLOCTEMP(comp_ctx);
62015 
62016 				if (reg_varbind >= 0) {
62017 					duk_reg_t reg_res;
62018 					duk_reg_t reg_src;
62019 					duk_int_t pc_temp_load;
62020 					duk_int_t pc_before_rhs;
62021 					duk_int_t pc_after_rhs;
62022 
62023 					if (toplevel_assign) {
62024 						/* 'reg_varbind' is the operation result and can also
62025 						 * become the expression value for top level assignments
62026 						 * such as: "var x; x += y;".
62027 						 */
62028 						DUK_DD(DUK_DDPRINT("<op>= expression is top level, write directly to reg_varbind"));
62029 						reg_res = reg_varbind;
62030 					} else {
62031 						/* Not safe to use 'reg_varbind' as assignment expression
62032 						 * value, so go through a temp.
62033 						 */
62034 						DUK_DD(DUK_DDPRINT("<op>= expression is not top level, write to reg_temp"));
62035 						reg_res = reg_temp;  /* reg_res should be smallest possible */
62036 						reg_temp = DUK__ALLOCTEMP(comp_ctx);
62037 					}
62038 
62039 					/* Try to optimize X <op>= Y for reg-bound
62040 					 * variables.  Detect side-effect free RHS
62041 					 * narrowly by seeing whether it emits code.
62042 					 * If not, rewind the code emitter and overwrite
62043 					 * the unnecessary temp reg load.
62044 					 */
62045 
62046 					pc_temp_load = duk__get_current_pc(comp_ctx);
62047 					duk__emit_a_bc(comp_ctx,
62048 					               DUK_OP_LDREG,
62049 					               (duk_regconst_t) reg_temp,
62050 					               reg_varbind);
62051 
62052 					pc_before_rhs = duk__get_current_pc(comp_ctx);
62053 					duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
62054 					DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
62055 					pc_after_rhs = duk__get_current_pc(comp_ctx);
62056 
62057 					DUK_DD(DUK_DDPRINT("pc_temp_load=%ld, pc_before_rhs=%ld, pc_after_rhs=%ld",
62058 					                   (long) pc_temp_load, (long) pc_before_rhs,
62059 					                   (long) pc_after_rhs));
62060 
62061 					if (pc_after_rhs == pc_before_rhs) {
62062 						/* Note: if the reg_temp load generated shuffling
62063 						 * instructions, we may need to rewind more than
62064 						 * one instruction, so use explicit PC computation.
62065 						 */
62066 						DUK_DD(DUK_DDPRINT("rhs is side effect free, rewind and avoid unnecessary temp for reg-based <op>="));
62067 						DUK_BW_ADD_PTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code, (pc_temp_load - pc_before_rhs) * sizeof(duk_compiler_instr));
62068 						reg_src = reg_varbind;
62069 					} else {
62070 						DUK_DD(DUK_DDPRINT("rhs evaluation emitted code, not sure if rhs is side effect free; use temp reg for LHS"));
62071 						reg_src = reg_temp;
62072 					}
62073 
62074 					duk__emit_a_b_c(comp_ctx,
62075 					                args_op,
62076 					                (duk_regconst_t) reg_res,
62077 					                (duk_regconst_t) reg_src,
62078 					                res->x1.regconst);
62079 
62080 					res->x1.regconst = (duk_regconst_t) reg_res;
62081 
62082 					/* Ensure compact use of temps. */
62083 					if (DUK__ISTEMP(comp_ctx, reg_res)) {
62084 						DUK__SETTEMP(comp_ctx, reg_res + 1);
62085 					}
62086 				} else {
62087 					/* When LHS is not register bound, always go through a
62088 					 * temporary.  No optimization for top level assignment.
62089 					 */
62090 
62091 					duk__emit_a_bc(comp_ctx,
62092 					               DUK_OP_GETVAR,
62093 					               (duk_regconst_t) reg_temp,
62094 					               rc_varname);
62095 
62096 					duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
62097 					DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
62098 
62099 					duk__emit_a_b_c(comp_ctx,
62100 					                args_op,
62101 					                (duk_regconst_t) reg_temp,
62102 					                (duk_regconst_t) reg_temp,
62103 					                res->x1.regconst);
62104 					res->x1.regconst = (duk_regconst_t) reg_temp;
62105 				}
62106 
62107 				DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
62108 			}
62109 
62110 			/* At this point 'res' holds the potential expression value.
62111 			 * It can be basically any ivalue here, including a reg-bound
62112 			 * identifier (if code above deems it safe) or a unary/binary
62113 			 * operation.  Operations must be resolved to a side effect free
62114 			 * plain value, and the side effects must happen exactly once.
62115 			 */
62116 
62117 			if (reg_varbind >= 0) {
62118 				if (res->t != DUK_IVAL_PLAIN) {
62119 					/* Resolve 'res' directly into the LHS binding, and use
62120 					 * that as the expression value if safe.  If not safe,
62121 					 * resolve to a temp/const and copy to LHS.
62122 					 */
62123 					if (toplevel_assign) {
62124 						duk__ivalue_toforcedreg(comp_ctx, res, (duk_int_t) reg_varbind);
62125 					} else {
62126 						duk__ivalue_totempconst(comp_ctx, res);
62127 						duk__copy_ivalue(comp_ctx, res, left);  /* use 'left' as a temp */
62128 						duk__ivalue_toforcedreg(comp_ctx, left, (duk_int_t) reg_varbind);
62129 					}
62130 				} else {
62131 					/* Use 'res' as the expression value (it's side effect
62132 					 * free and may be a plain value, a register, or a
62133 					 * constant) and write it to the LHS binding too.
62134 					 */
62135 					duk__copy_ivalue(comp_ctx, res, left);  /* use 'left' as a temp */
62136 					duk__ivalue_toforcedreg(comp_ctx, left, (duk_int_t) reg_varbind);
62137 				}
62138 			} else {
62139 				/* Only a reg fits into 'A' so coerce 'res' into a register
62140 				 * for PUTVAR.
62141 				 *
62142 				 * XXX: here the current A/B/C split is suboptimal: we could
62143 				 * just use 9 bits for reg_res (and support constants) and 17
62144 				 * instead of 18 bits for the varname const index.
62145 				 */
62146 
62147 				duk__ivalue_toreg(comp_ctx, res);
62148 				duk__emit_a_bc(comp_ctx,
62149 				               DUK_OP_PUTVAR | DUK__EMIT_FLAG_A_IS_SOURCE,
62150 				               res->x1.regconst,
62151 				               rc_varname);
62152 			}
62153 
62154 			/* 'res' contains expression value */
62155 		} else if (left->t == DUK_IVAL_PROP) {
62156 			/* E5 Section 11.13.1 (and others) step 4 never matches for prop writes -> no check */
62157 			duk_reg_t reg_obj;
62158 			duk_regconst_t rc_key;
62159 			duk_regconst_t rc_res;
62160 			duk_reg_t reg_temp;
62161 
62162 			/* Property access expressions ('a[b]') are critical to correct
62163 			 * LHS evaluation ordering, see test-dev-assign-eval-order*.js.
62164 			 * We must make sure that the LHS target slot (base object and
62165 			 * key) don't change during RHS evaluation.  The only concrete
62166 			 * problem is a register reference to a variable-bound register
62167 			 * (i.e., non-temp).  Require temp regs for both key and base.
62168 			 *
62169 			 * Don't allow a constant for the object (even for a number
62170 			 * etc), as it goes into the 'A' field of the opcode.
62171 			 */
62172 
62173 			reg_obj = duk__ispec_toregconst_raw(comp_ctx,
62174 			                                    &left->x1,
62175 			                                    -1 /*forced_reg*/,
62176 			                                    DUK__IVAL_FLAG_REQUIRE_TEMP /*flags*/);
62177 
62178 			rc_key = duk__ispec_toregconst_raw(comp_ctx,
62179 			                                   &left->x2,
62180 			                                   -1 /*forced_reg*/,
62181 			                                   DUK__IVAL_FLAG_REQUIRE_TEMP | DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
62182 
62183 			/* Evaluate RHS only when LHS is safe. */
62184 
62185 			if (args_op == DUK_OP_NONE) {
62186 				duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
62187 				DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
62188 				rc_res = res->x1.regconst;
62189 			} else {
62190 				reg_temp = DUK__ALLOCTEMP(comp_ctx);
62191 				duk__emit_a_b_c(comp_ctx,
62192 				                DUK_OP_GETPROP,
62193 				                (duk_regconst_t) reg_temp,
62194 				                (duk_regconst_t) reg_obj,
62195 				                rc_key);
62196 
62197 				duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
62198 				DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
62199 
62200 				duk__emit_a_b_c(comp_ctx,
62201 				                args_op,
62202 				                (duk_regconst_t) reg_temp,
62203 				                (duk_regconst_t) reg_temp,
62204 				                res->x1.regconst);
62205 				rc_res = (duk_regconst_t) reg_temp;
62206 			}
62207 
62208 			duk__emit_a_b_c(comp_ctx,
62209 			                DUK_OP_PUTPROP | DUK__EMIT_FLAG_A_IS_SOURCE,
62210 			                (duk_regconst_t) reg_obj,
62211 			                rc_key,
62212 			                rc_res);
62213 
62214 			res->t = DUK_IVAL_PLAIN;
62215 			res->x1.t = DUK_ISPEC_REGCONST;
62216 			res->x1.regconst = rc_res;
62217 		} else {
62218 			/* No support for lvalues returned from new or function call expressions.
62219 			 * However, these must NOT cause compile-time SyntaxErrors, but run-time
62220 			 * ReferenceErrors.  Both left and right sides of the assignment must be
62221 			 * evaluated before throwing a ReferenceError.  For instance:
62222 			 *
62223 			 *     f() = g();
62224 			 *
62225 			 * must result in f() being evaluated, then g() being evaluated, and
62226 			 * finally, a ReferenceError being thrown.  See E5 Section 11.13.1.
62227 			 */
62228 
62229 			duk_regconst_t rc_res;
62230 
62231 			/* First evaluate LHS fully to ensure all side effects are out. */
62232 			duk__ivalue_toplain_ignore(comp_ctx, left);
62233 
62234 			/* Then evaluate RHS fully (its value becomes the expression value too).
62235 			 * Technically we'd need the side effect safety check here too, but because
62236 			 * we always throw using INVLHS the result doesn't matter.
62237 			 */
62238 			rc_res = duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
62239 
62240 			duk__emit_extraop_only(comp_ctx,
62241 			                       DUK_EXTRAOP_INVLHS);
62242 
62243 			res->t = DUK_IVAL_PLAIN;
62244 			res->x1.t = DUK_ISPEC_REGCONST;
62245 			res->x1.regconst = rc_res;
62246 		}
62247 
62248 		return;
62249 	}
62250 
62251  postincdec:
62252 	{
62253 		/*
62254 		 *  Post-increment/decrement will return the original value as its
62255 		 *  result value.  However, even that value will be coerced using
62256 		 *  ToNumber() which is quite awkward.  Specific bytecode opcodes
62257 		 *  are used to handle these semantics.
62258 		 *
62259 		 *  Note that post increment/decrement has a "no LineTerminator here"
62260 		 *  restriction.  This is handled by duk__expr_lbp(), which forcibly terminates
62261 		 *  the previous expression if a LineTerminator occurs before '++'/'--'.
62262 		 */
62263 
62264 		duk_reg_t reg_res;
62265 		duk_small_uint_t args_op = args >> 8;
62266 
62267 		/* Specific assumptions for opcode numbering. */
62268 		DUK_ASSERT(DUK_OP_POSTINCR + 4 == DUK_OP_POSTINCV);
62269 		DUK_ASSERT(DUK_OP_POSTDECR + 4 == DUK_OP_POSTDECV);
62270 		DUK_ASSERT(DUK_OP_POSTINCR + 8 == DUK_OP_POSTINCP);
62271 		DUK_ASSERT(DUK_OP_POSTDECR + 8 == DUK_OP_POSTDECP);
62272 
62273 		reg_res = DUK__ALLOCTEMP(comp_ctx);
62274 
62275 		if (left->t == DUK_IVAL_VAR) {
62276 			duk_hstring *h_varname;
62277 			duk_reg_t reg_varbind;
62278 			duk_regconst_t rc_varname;
62279 
62280 			h_varname = duk_get_hstring(ctx, left->x1.valstack_idx);
62281 			DUK_ASSERT(h_varname != NULL);
62282 
62283 			if (duk__hstring_is_eval_or_arguments_in_strict_mode(comp_ctx, h_varname)) {
62284 				goto syntax_error;
62285 			}
62286 
62287 			duk_dup(ctx, left->x1.valstack_idx);
62288 			if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
62289 				duk__emit_a_bc(comp_ctx,
62290 				               args_op,  /* e.g. DUK_OP_POSTINCR */
62291 				               (duk_regconst_t) reg_res,
62292 				               (duk_regconst_t) reg_varbind);
62293 			} else {
62294 				duk__emit_a_bc(comp_ctx,
62295 				               args_op + 4,  /* e.g. DUK_OP_POSTINCV */
62296 				               (duk_regconst_t) reg_res,
62297 				               rc_varname);
62298 			}
62299 
62300 			DUK_DDD(DUK_DDDPRINT("postincdec to '%!O' -> reg_varbind=%ld, rc_varname=%ld",
62301 			                     (duk_heaphdr *) h_varname, (long) reg_varbind, (long) rc_varname));
62302 		} else if (left->t == DUK_IVAL_PROP) {
62303 			duk_reg_t reg_obj;  /* allocate to reg only (not const) */
62304 			duk_regconst_t rc_key;
62305 
62306 			reg_obj = duk__ispec_toregconst_raw(comp_ctx, &left->x1, -1 /*forced_reg*/, 0 /*flags*/);  /* don't allow const */
62307 			rc_key = duk__ispec_toregconst_raw(comp_ctx, &left->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
62308 			duk__emit_a_b_c(comp_ctx,
62309 			                args_op + 8,  /* e.g. DUK_OP_POSTINCP */
62310 			                (duk_regconst_t) reg_res,
62311 			                (duk_regconst_t) reg_obj,
62312 			                rc_key);
62313 		} else {
62314 			/* Technically return value is not needed because INVLHS will
62315 			 * unconditially throw a ReferenceError.  Coercion is necessary
62316 			 * for proper semantics (consider ToNumber() called for an object).
62317 			 * Use DUK_EXTRAOP_UNP with a dummy register to get ToNumber().
62318 			 */
62319 			duk__ivalue_toforcedreg(comp_ctx, left, reg_res);
62320 			duk__emit_extraop_bc(comp_ctx,
62321 			                     DUK_EXTRAOP_UNP,
62322 			                     reg_res);  /* for side effects, result ignored */
62323 			duk__emit_extraop_only(comp_ctx,
62324 			                       DUK_EXTRAOP_INVLHS);
62325 		}
62326 
62327 		res->t = DUK_IVAL_PLAIN;
62328 		res->x1.t = DUK_ISPEC_REGCONST;
62329 		res->x1.regconst = (duk_regconst_t) reg_res;
62330 		DUK__SETTEMP(comp_ctx, reg_res + 1);
62331 		return;
62332 	}
62333 
62334  syntax_error:
62335 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_EXPRESSION);
62336 	return;
62337 
62338  syntax_error_lvalue:
62339 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_LVALUE);
62340 	return;
62341 }
62342 
62343 DUK_LOCAL duk_small_uint_t duk__expr_lbp(duk_compiler_ctx *comp_ctx) {
62344 	duk_small_int_t tok = comp_ctx->curr_token.t;
62345 
62346 	DUK_ASSERT(tok >= DUK_TOK_MINVAL && tok <= DUK_TOK_MAXVAL);
62347 	DUK_ASSERT(sizeof(duk__token_lbp) == DUK_TOK_MAXVAL + 1);
62348 
62349 	/* XXX: integrate support for this into led() instead?
62350 	 * Similar issue as post-increment/post-decrement.
62351 	 */
62352 
62353 	/* prevent duk__expr_led() by using a binding power less than anything valid */
62354 	if (tok == DUK_TOK_IN && !comp_ctx->curr_func.allow_in) {
62355 		return 0;
62356 	}
62357 
62358 	if ((tok == DUK_TOK_DECREMENT || tok == DUK_TOK_INCREMENT) &&
62359 	    (comp_ctx->curr_token.lineterm)) {
62360 		/* '++' or '--' in a post-increment/decrement position,
62361 		 * and a LineTerminator occurs between the operator and
62362 		 * the preceding expression.  Force the previous expr
62363 		 * to terminate, in effect treating e.g. "a,b\n++" as
62364 		 * "a,b;++" (= SyntaxError).
62365 		 */
62366 		return 0;
62367 	}
62368 
62369 	return DUK__TOKEN_LBP_GET_BP(duk__token_lbp[tok]);  /* format is bit packed */
62370 }
62371 
62372 /*
62373  *  Expression parsing.
62374  *
62375  *  Upon entry to 'expr' and its variants, 'curr_tok' is assumed to be the
62376  *  first token of the expression.  Upon exit, 'curr_tok' will be the first
62377  *  token not part of the expression (e.g. semicolon terminating an expression
62378  *  statement).
62379  */
62380 
62381 #define DUK__EXPR_RBP_MASK           0xff
62382 #define DUK__EXPR_FLAG_REJECT_IN     (1 << 8)   /* reject 'in' token (used for for-in) */
62383 #define DUK__EXPR_FLAG_ALLOW_EMPTY   (1 << 9)   /* allow empty expression */
62384 #define DUK__EXPR_FLAG_REQUIRE_INIT  (1 << 10)  /* require initializer for var/const */
62385 
62386 /* main expression parser function */
62387 DUK_LOCAL void duk__expr(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
62388 	duk_hthread *thr = comp_ctx->thr;
62389 	duk_context *ctx = (duk_context *) thr;
62390 	duk_ivalue tmp_alloc;   /* 'res' is used for "left", and 'tmp' for "right" */
62391 	duk_ivalue *tmp = &tmp_alloc;
62392 	duk_small_uint_t rbp;
62393 
62394 	DUK__RECURSION_INCREASE(comp_ctx, thr);
62395 
62396 	duk_require_stack(ctx, DUK__PARSE_EXPR_SLOTS);
62397 
62398 	/* filter out flags from exprtop rbp_flags here to save space */
62399 	rbp = rbp_flags & DUK__EXPR_RBP_MASK;
62400 
62401 	DUK_DDD(DUK_DDDPRINT("duk__expr(), rbp_flags=%ld, rbp=%ld, allow_in=%ld, paren_level=%ld",
62402 	                     (long) rbp_flags, (long) rbp, (long) comp_ctx->curr_func.allow_in,
62403 	                     (long) comp_ctx->curr_func.paren_level));
62404 
62405 	DUK_MEMZERO(&tmp_alloc, sizeof(tmp_alloc));
62406 	tmp->x1.valstack_idx = duk_get_top(ctx);
62407 	tmp->x2.valstack_idx = tmp->x1.valstack_idx + 1;
62408 	duk_push_undefined(ctx);
62409 	duk_push_undefined(ctx);
62410 
62411 	/* XXX: where to release temp regs in intermediate expressions?
62412 	 * e.g. 1+2+3 -> don't inflate temp register count when parsing this.
62413 	 * that particular expression temp regs can be forced here.
62414 	 */
62415 
62416 	/* XXX: increase ctx->expr_tokens here for every consumed token
62417 	 * (this would be a nice statistic)?
62418 	 */
62419 
62420 	if (comp_ctx->curr_token.t == DUK_TOK_SEMICOLON || comp_ctx->curr_token.t == DUK_TOK_RPAREN) {
62421 		/* XXX: possibly incorrect handling of empty expression */
62422 		DUK_DDD(DUK_DDDPRINT("empty expression"));
62423 		if (!(rbp_flags & DUK__EXPR_FLAG_ALLOW_EMPTY)) {
62424 			DUK_ERROR_SYNTAX(thr, DUK_STR_EMPTY_EXPR_NOT_ALLOWED);
62425 		}
62426 		res->t = DUK_IVAL_PLAIN;
62427 		res->x1.t = DUK_ISPEC_VALUE;
62428 		duk_push_undefined(ctx);
62429 		duk_replace(ctx, res->x1.valstack_idx);
62430 		goto cleanup;
62431 	}
62432 
62433 	duk__advance(comp_ctx);
62434 	duk__expr_nud(comp_ctx, res);  /* reuse 'res' as 'left' */
62435 	while (rbp < duk__expr_lbp(comp_ctx)) {
62436 		duk__advance(comp_ctx);
62437 		duk__expr_led(comp_ctx, res, tmp);
62438 		duk__copy_ivalue(comp_ctx, tmp, res);  /* tmp -> res */
62439 	}
62440 
62441  cleanup:
62442 	/* final result is already in 'res' */
62443 
62444 	duk_pop_2(ctx);
62445 
62446 	DUK__RECURSION_DECREASE(comp_ctx, thr);
62447 }
62448 
62449 DUK_LOCAL void duk__exprtop(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
62450 	duk_hthread *thr = comp_ctx->thr;
62451 
62452 	/* Note: these variables must reside in 'curr_func' instead of the global
62453 	 * context: when parsing function expressions, expression parsing is nested.
62454 	 */
62455 	comp_ctx->curr_func.nud_count = 0;
62456 	comp_ctx->curr_func.led_count = 0;
62457 	comp_ctx->curr_func.paren_level = 0;
62458 	comp_ctx->curr_func.expr_lhs = 1;
62459 	comp_ctx->curr_func.allow_in = (rbp_flags & DUK__EXPR_FLAG_REJECT_IN ? 0 : 1);
62460 
62461 	duk__expr(comp_ctx, res, rbp_flags);
62462 
62463 	if (!(rbp_flags & DUK__EXPR_FLAG_ALLOW_EMPTY) && duk__expr_is_empty(comp_ctx)) {
62464 		DUK_ERROR_SYNTAX(thr, DUK_STR_EMPTY_EXPR_NOT_ALLOWED);
62465 	}
62466 }
62467 
62468 /* A bunch of helpers (for size optimization) that combine duk__expr()/duk__exprtop()
62469  * and result conversions.
62470  *
62471  * Each helper needs at least 2-3 calls to make it worth while to wrap.
62472  */
62473 
62474 #if 0  /* unused */
62475 DUK_LOCAL duk_reg_t duk__expr_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
62476 	duk__expr(comp_ctx, res, rbp_flags);
62477 	return duk__ivalue_toreg(comp_ctx, res);
62478 }
62479 #endif
62480 
62481 #if 0  /* unused */
62482 DUK_LOCAL duk_reg_t duk__expr_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
62483 	duk__expr(comp_ctx, res, rbp_flags);
62484 	return duk__ivalue_totemp(comp_ctx, res);
62485 }
62486 #endif
62487 
62488 DUK_LOCAL void duk__expr_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags, duk_reg_t forced_reg) {
62489 	DUK_ASSERT(forced_reg >= 0);
62490 	duk__expr(comp_ctx, res, rbp_flags);
62491 	duk__ivalue_toforcedreg(comp_ctx, res, forced_reg);
62492 }
62493 
62494 DUK_LOCAL duk_regconst_t duk__expr_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
62495 	duk__expr(comp_ctx, res, rbp_flags);
62496 	return duk__ivalue_toregconst(comp_ctx, res);
62497 }
62498 
62499 #if 0  /* unused */
62500 DUK_LOCAL duk_regconst_t duk__expr_totempconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
62501 	duk__expr(comp_ctx, res, rbp_flags);
62502 	return duk__ivalue_totempconst(comp_ctx, res);
62503 }
62504 #endif
62505 
62506 DUK_LOCAL void duk__expr_toplain(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
62507 	duk__expr(comp_ctx, res, rbp_flags);
62508 	duk__ivalue_toplain(comp_ctx, res);
62509 }
62510 
62511 DUK_LOCAL void duk__expr_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
62512 	duk__expr(comp_ctx, res, rbp_flags);
62513 	duk__ivalue_toplain_ignore(comp_ctx, res);
62514 }
62515 
62516 DUK_LOCAL duk_reg_t duk__exprtop_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
62517 	duk__exprtop(comp_ctx, res, rbp_flags);
62518 	return duk__ivalue_toreg(comp_ctx, res);
62519 }
62520 
62521 #if 0  /* unused */
62522 DUK_LOCAL duk_reg_t duk__exprtop_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
62523 	duk__exprtop(comp_ctx, res, rbp_flags);
62524 	return duk__ivalue_totemp(comp_ctx, res);
62525 }
62526 #endif
62527 
62528 DUK_LOCAL void duk__exprtop_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags, duk_reg_t forced_reg) {
62529 	DUK_ASSERT(forced_reg >= 0);
62530 	duk__exprtop(comp_ctx, res, rbp_flags);
62531 	duk__ivalue_toforcedreg(comp_ctx, res, forced_reg);
62532 }
62533 
62534 DUK_LOCAL duk_regconst_t duk__exprtop_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
62535 	duk__exprtop(comp_ctx, res, rbp_flags);
62536 	return duk__ivalue_toregconst(comp_ctx, res);
62537 }
62538 
62539 #if 0  /* unused */
62540 DUK_LOCAL void duk__exprtop_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *res, int rbp_flags) {
62541 	duk__exprtop(comp_ctx, res, rbp_flags);
62542 	duk__ivalue_toplain_ignore(comp_ctx, res);
62543 }
62544 #endif
62545 
62546 /*
62547  *  Parse an individual source element (top level statement) or a statement.
62548  *
62549  *  Handles labeled statements automatically (peeling away labels before
62550  *  parsing an expression that follows the label(s)).
62551  *
62552  *  Upon entry, 'curr_tok' contains the first token of the statement (parsed
62553  *  in "allow regexp literal" mode).  Upon exit, 'curr_tok' contains the first
62554  *  token following the statement (if the statement has a terminator, this is
62555  *  the token after the terminator).
62556  */
62557 
62558 #ifdef DUK__HAS_VAL
62559 #undef DUK__HAS_VAL
62560 #endif
62561 #ifdef DUK__HAS_TERM
62562 #undef DUK__HAS_TERM
62563 #endif
62564 #ifdef DUK__ALLOW_AUTO_SEMI_ALWAYS
62565 #undef DUK__ALLOW_AUTO_SEMI_ALWAYS
62566 #endif
62567 #ifdef DUK__STILL_PROLOGUE
62568 #undef DUK__STILL_PROLOGUE
62569 #endif
62570 #ifdef DUK__IS_TERMINAL
62571 #undef DUK__IS_TERMINAL
62572 #endif
62573 
62574 #define DUK__HAS_VAL                  (1 << 0)  /* stmt has non-empty value */
62575 #define DUK__HAS_TERM                 (1 << 1)  /* stmt has explicit/implicit semicolon terminator */
62576 #define DUK__ALLOW_AUTO_SEMI_ALWAYS   (1 << 2)  /* allow automatic semicolon even without lineterm (compatibility) */
62577 #define DUK__STILL_PROLOGUE           (1 << 3)  /* statement does not terminate directive prologue */
62578 #define DUK__IS_TERMINAL              (1 << 4)  /* statement is guaranteed to be terminal (control doesn't flow to next statement) */
62579 
62580 /* Parse a single variable declaration (e.g. "i" or "i=10").  A leading 'var'
62581  * has already been eaten.  These is no return value in 'res', it is used only
62582  * as a temporary.
62583  *
62584  * When called from 'for-in' statement parser, the initializer expression must
62585  * not allow the 'in' token.  The caller supply additional expression parsing
62586  * flags (like DUK__EXPR_FLAG_REJECT_IN) in 'expr_flags'.
62587  *
62588  * Finally, out_rc_varname and out_reg_varbind are updated to reflect where
62589  * the identifier is bound:
62590  *
62591  *    If register bound:      out_reg_varbind >= 0, out_rc_varname == 0 (ignore)
62592  *    If not register bound:  out_reg_varbind < 0, out_rc_varname >= 0
62593  *
62594  * These allow the caller to use the variable for further assignment, e.g.
62595  * as is done in 'for-in' parsing.
62596  */
62597 
62598 DUK_LOCAL void duk__parse_var_decl(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t expr_flags, duk_reg_t *out_reg_varbind, duk_regconst_t *out_rc_varname) {
62599 	duk_hthread *thr = comp_ctx->thr;
62600 	duk_context *ctx = (duk_context *) thr;
62601 	duk_hstring *h_varname;
62602 	duk_reg_t reg_varbind;
62603 	duk_regconst_t rc_varname;
62604 
62605 	/* assume 'var' has been eaten */
62606 
62607 	/* Note: Identifier rejects reserved words */
62608 	if (comp_ctx->curr_token.t != DUK_TOK_IDENTIFIER) {
62609 		goto syntax_error;
62610 	}
62611 	h_varname = comp_ctx->curr_token.str1;
62612 
62613 	DUK_ASSERT(h_varname != NULL);
62614 
62615 	/* strict mode restrictions (E5 Section 12.2.1) */
62616 	if (duk__hstring_is_eval_or_arguments_in_strict_mode(comp_ctx, h_varname)) {
62617 		goto syntax_error;
62618 	}
62619 
62620 	/* register declarations in first pass */
62621 	if (comp_ctx->curr_func.in_scanning) {
62622 		duk_uarridx_t n;
62623 		DUK_DDD(DUK_DDDPRINT("register variable declaration %!O in pass 1",
62624 		                     (duk_heaphdr *) h_varname));
62625 		n = (duk_uarridx_t) duk_get_length(ctx, comp_ctx->curr_func.decls_idx);
62626 		duk_push_hstring(ctx, h_varname);
62627 		duk_put_prop_index(ctx, comp_ctx->curr_func.decls_idx, n);
62628 		duk_push_int(ctx, DUK_DECL_TYPE_VAR + (0 << 8));
62629 		duk_put_prop_index(ctx, comp_ctx->curr_func.decls_idx, n + 1);
62630 	}
62631 
62632 	duk_push_hstring(ctx, h_varname);  /* push before advancing to keep reachable */
62633 
62634 	/* register binding lookup is based on varmap (even in first pass) */
62635 	duk_dup_top(ctx);
62636 	(void) duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname);
62637 
62638 	duk__advance(comp_ctx);  /* eat identifier */
62639 
62640 	if (comp_ctx->curr_token.t == DUK_TOK_EQUALSIGN) {
62641 		duk__advance(comp_ctx);
62642 
62643 		DUK_DDD(DUK_DDDPRINT("vardecl, assign to '%!O' -> reg_varbind=%ld, rc_varname=%ld",
62644 		                     (duk_heaphdr *) h_varname, (long) reg_varbind, (long) rc_varname));
62645 
62646 		duk__exprtop(comp_ctx, res, DUK__BP_COMMA | expr_flags /*rbp_flags*/);  /* AssignmentExpression */
62647 
62648 		if (reg_varbind >= 0) {
62649 			duk__ivalue_toforcedreg(comp_ctx, res, reg_varbind);
62650 		} else {
62651 			duk_reg_t reg_val;
62652 			reg_val = duk__ivalue_toreg(comp_ctx, res);
62653 			duk__emit_a_bc(comp_ctx,
62654 			               DUK_OP_PUTVAR | DUK__EMIT_FLAG_A_IS_SOURCE,
62655 			               (duk_regconst_t) reg_val,
62656 			               rc_varname);
62657 		}
62658 	} else {
62659 		if (expr_flags & DUK__EXPR_FLAG_REQUIRE_INIT) {
62660 			/* Used for minimal 'const': initializer required. */
62661 			goto syntax_error;
62662 		}
62663 	}
62664 
62665 	duk_pop(ctx);  /* pop varname */
62666 
62667 	*out_rc_varname = rc_varname;
62668 	*out_reg_varbind = reg_varbind;
62669 
62670 	return;
62671 
62672  syntax_error:
62673 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_VAR_DECLARATION);
62674 }
62675 
62676 DUK_LOCAL void duk__parse_var_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t expr_flags) {
62677 	duk_reg_t reg_varbind;
62678 	duk_regconst_t rc_varname;
62679 
62680 	duk__advance(comp_ctx);  /* eat 'var' */
62681 
62682 	for (;;) {
62683 		/* rc_varname and reg_varbind are ignored here */
62684 		duk__parse_var_decl(comp_ctx, res, 0 | expr_flags, &reg_varbind, &rc_varname);
62685 
62686 		if (comp_ctx->curr_token.t != DUK_TOK_COMMA) {
62687 			break;
62688 		}
62689 		duk__advance(comp_ctx);
62690 	}
62691 }
62692 
62693 DUK_LOCAL void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {
62694 	duk_hthread *thr = comp_ctx->thr;
62695 	duk_context *ctx = (duk_context *) thr;
62696 	duk_int_t pc_v34_lhs;    /* start variant 3/4 left-hand-side code (L1 in doc/compiler.rst example) */
62697 	duk_reg_t temp_reset;    /* knock back "next temp" to this whenever possible */
62698 	duk_reg_t reg_temps;     /* preallocated temporaries (2) for variants 3 and 4 */
62699 
62700 	DUK_DDD(DUK_DDDPRINT("start parsing a for/for-in statement"));
62701 
62702 	/* Two temporaries are preallocated here for variants 3 and 4 which need
62703 	 * registers which are never clobbered by expressions in the loop
62704 	 * (concretely: for the enumerator object and the next enumerated value).
62705 	 * Variants 1 and 2 "release" these temps.
62706 	 */
62707 
62708 	reg_temps = DUK__ALLOCTEMPS(comp_ctx, 2);
62709 
62710 	temp_reset = DUK__GETTEMP(comp_ctx);
62711 
62712 	/*
62713 	 *  For/for-in main variants are:
62714 	 *
62715 	 *    1. for (ExpressionNoIn_opt; Expression_opt; Expression_opt) Statement
62716 	 *    2. for (var VariableDeclarationNoIn; Expression_opt; Expression_opt) Statement
62717 	 *    3. for (LeftHandSideExpression in Expression) Statement
62718 	 *    4. for (var VariableDeclarationNoIn in Expression) Statement
62719 	 *
62720 	 *  Parsing these without arbitrary lookahead or backtracking is relatively
62721 	 *  tricky but we manage to do so for now.
62722 	 *
62723 	 *  See doc/compiler.rst for a detailed discussion of control flow
62724 	 *  issues, evaluation order issues, etc.
62725 	 */
62726 
62727 	duk__advance(comp_ctx);  /* eat 'for' */
62728 	duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
62729 
62730 	DUK_DDD(DUK_DDDPRINT("detecting for/for-in loop variant, pc=%ld", (long) duk__get_current_pc(comp_ctx)));
62731 
62732 	/* a label site has been emitted by duk__parse_stmt() automatically
62733 	 * (it will also emit the ENDLABEL).
62734 	 */
62735 
62736 	if (comp_ctx->curr_token.t == DUK_TOK_VAR) {
62737 		/*
62738 		 *  Variant 2 or 4
62739 		 */
62740 
62741 		duk_reg_t reg_varbind;       /* variable binding register if register-bound (otherwise < 0) */
62742 		duk_regconst_t rc_varname;   /* variable name reg/const, if variable not register-bound */
62743 
62744 		duk__advance(comp_ctx);  /* eat 'var' */
62745 		duk__parse_var_decl(comp_ctx, res, DUK__EXPR_FLAG_REJECT_IN, &reg_varbind, &rc_varname);
62746 		DUK__SETTEMP(comp_ctx, temp_reset);
62747 
62748 		if (comp_ctx->curr_token.t == DUK_TOK_IN) {
62749 			/*
62750 			 *  Variant 4
62751 			 */
62752 
62753 			DUK_DDD(DUK_DDDPRINT("detected for variant 4: for (var VariableDeclarationNoIn in Expression) Statement"));
62754 			pc_v34_lhs = duk__get_current_pc(comp_ctx);  /* jump is inserted here */
62755 			if (reg_varbind >= 0) {
62756 				duk__emit_a_bc(comp_ctx,
62757 				               DUK_OP_LDREG,
62758 				               (duk_regconst_t) reg_varbind,
62759 				               (duk_regconst_t) (reg_temps + 0));
62760 			} else {
62761 				duk__emit_a_bc(comp_ctx,
62762 				               DUK_OP_PUTVAR | DUK__EMIT_FLAG_A_IS_SOURCE,
62763 				               (duk_regconst_t) (reg_temps + 0),
62764 				               rc_varname);
62765 			}
62766 			goto parse_3_or_4;
62767 		} else {
62768 			/*
62769 			 *  Variant 2
62770 			 */
62771 
62772 			DUK_DDD(DUK_DDDPRINT("detected for variant 2: for (var VariableDeclarationNoIn; Expression_opt; Expression_opt) Statement"));
62773 			for (;;) {
62774 				/* more initializers */
62775 				if (comp_ctx->curr_token.t != DUK_TOK_COMMA) {
62776 					break;
62777 				}
62778 				DUK_DDD(DUK_DDDPRINT("variant 2 has another variable initializer"));
62779 
62780 				duk__advance(comp_ctx);  /* eat comma */
62781 				duk__parse_var_decl(comp_ctx, res, DUK__EXPR_FLAG_REJECT_IN, &reg_varbind, &rc_varname);
62782 			}
62783 			goto parse_1_or_2;
62784 		}
62785 	} else {
62786 		/*
62787 		 *  Variant 1 or 3
62788 		 */
62789 
62790 		pc_v34_lhs = duk__get_current_pc(comp_ctx);  /* jump is inserted here (variant 3) */
62791 
62792 		/* Note that duk__exprtop() here can clobber any reg above current temp_next,
62793 		 * so any loop variables (e.g. enumerator) must be "preallocated".
62794 		 */
62795 
62796 		/* don't coerce yet to a plain value (variant 3 needs special handling) */
62797 		duk__exprtop(comp_ctx, res, DUK__BP_FOR_EXPR | DUK__EXPR_FLAG_REJECT_IN | DUK__EXPR_FLAG_ALLOW_EMPTY /*rbp_flags*/);  /* Expression */
62798 		if (comp_ctx->curr_token.t == DUK_TOK_IN) {
62799 			/*
62800 			 *  Variant 3
62801 			 */
62802 
62803 			/* XXX: need to determine LHS type, and check that it is LHS compatible */
62804 			DUK_DDD(DUK_DDDPRINT("detected for variant 3: for (LeftHandSideExpression in Expression) Statement"));
62805 			if (duk__expr_is_empty(comp_ctx)) {
62806 				goto syntax_error;  /* LeftHandSideExpression does not allow empty expression */
62807 			}
62808 
62809 			if (res->t == DUK_IVAL_VAR) {
62810 				duk_reg_t reg_varbind;
62811 				duk_regconst_t rc_varname;
62812 
62813 				duk_dup(ctx, res->x1.valstack_idx);
62814 				if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
62815 					duk__emit_a_bc(comp_ctx,
62816 					               DUK_OP_LDREG,
62817 					               (duk_regconst_t) reg_varbind,
62818 					               (duk_regconst_t) (reg_temps + 0));
62819 				} else {
62820 					duk__emit_a_bc(comp_ctx,
62821 					               DUK_OP_PUTVAR | DUK__EMIT_FLAG_A_IS_SOURCE,
62822 					               (duk_regconst_t) (reg_temps + 0),
62823 					               rc_varname);
62824 				}
62825 			} else if (res->t == DUK_IVAL_PROP) {
62826 				/* Don't allow a constant for the object (even for a number etc), as
62827 				 * it goes into the 'A' field of the opcode.
62828 				 */
62829 				duk_reg_t reg_obj;
62830 				duk_regconst_t rc_key;
62831 				reg_obj = duk__ispec_toregconst_raw(comp_ctx, &res->x1, -1 /*forced_reg*/, 0 /*flags*/);  /* don't allow const */
62832 				rc_key = duk__ispec_toregconst_raw(comp_ctx, &res->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
62833 				duk__emit_a_b_c(comp_ctx,
62834 				                DUK_OP_PUTPROP | DUK__EMIT_FLAG_A_IS_SOURCE,
62835 				                (duk_regconst_t) reg_obj,
62836 				                rc_key,
62837 				                (duk_regconst_t) (reg_temps + 0));
62838 			} else {
62839 				duk__ivalue_toplain_ignore(comp_ctx, res);  /* just in case */
62840 				duk__emit_extraop_only(comp_ctx,
62841 				                       DUK_EXTRAOP_INVLHS);
62842 			}
62843 			goto parse_3_or_4;
62844 		} else {
62845 			/*
62846 			 *  Variant 1
62847 			 */
62848 
62849 			DUK_DDD(DUK_DDDPRINT("detected for variant 1: for (ExpressionNoIn_opt; Expression_opt; Expression_opt) Statement"));
62850 			duk__ivalue_toplain_ignore(comp_ctx, res);
62851 			goto parse_1_or_2;
62852 		}
62853 	}
62854 
62855  parse_1_or_2:
62856 	/*
62857 	 *  Parse variant 1 or 2.  The first part expression (which differs
62858 	 *  in the variants) has already been parsed and its code emitted.
62859 	 *
62860 	 *  reg_temps + 0: unused
62861 	 *  reg_temps + 1: unused
62862 	 */
62863 	{
62864 		duk_regconst_t rc_cond;
62865 		duk_int_t pc_l1, pc_l2, pc_l3, pc_l4;
62866 		duk_int_t pc_jumpto_l3, pc_jumpto_l4;
62867 		duk_bool_t expr_c_empty;
62868 
62869 		DUK_DDD(DUK_DDDPRINT("shared code for parsing variants 1 and 2"));
62870 
62871 		/* "release" preallocated temps since we won't need them */
62872 		temp_reset = reg_temps + 0;
62873 		DUK__SETTEMP(comp_ctx, temp_reset);
62874 
62875 		duk__advance_expect(comp_ctx, DUK_TOK_SEMICOLON);
62876 
62877 		pc_l1 = duk__get_current_pc(comp_ctx);
62878 		duk__exprtop(comp_ctx, res, DUK__BP_FOR_EXPR | DUK__EXPR_FLAG_ALLOW_EMPTY /*rbp_flags*/);  /* Expression_opt */
62879 		if (duk__expr_is_empty(comp_ctx)) {
62880 			/* no need to coerce */
62881 			pc_jumpto_l3 = duk__emit_jump_empty(comp_ctx);  /* to body */
62882 			pc_jumpto_l4 = -1;  /* omitted */
62883 		} else {
62884 			rc_cond = duk__ivalue_toregconst(comp_ctx, res);
62885 			duk__emit_if_false_skip(comp_ctx, rc_cond);
62886 			pc_jumpto_l3 = duk__emit_jump_empty(comp_ctx);  /* to body */
62887 			pc_jumpto_l4 = duk__emit_jump_empty(comp_ctx);  /* to exit */
62888 		}
62889 		DUK__SETTEMP(comp_ctx, temp_reset);
62890 
62891 		duk__advance_expect(comp_ctx, DUK_TOK_SEMICOLON);
62892 
62893 		pc_l2 = duk__get_current_pc(comp_ctx);
62894 		duk__exprtop(comp_ctx, res, DUK__BP_FOR_EXPR | DUK__EXPR_FLAG_ALLOW_EMPTY /*rbp_flags*/);  /* Expression_opt */
62895 		if (duk__expr_is_empty(comp_ctx)) {
62896 			/* no need to coerce */
62897 			expr_c_empty = 1;
62898 			/* JUMP L1 omitted */
62899 		} else {
62900 			duk__ivalue_toplain_ignore(comp_ctx, res);
62901 			expr_c_empty = 0;
62902 			duk__emit_jump(comp_ctx, pc_l1);
62903 		}
62904 		DUK__SETTEMP(comp_ctx, temp_reset);
62905 
62906 		duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);
62907 
62908 		pc_l3 = duk__get_current_pc(comp_ctx);
62909 		duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
62910 		if (expr_c_empty) {
62911 			duk__emit_jump(comp_ctx, pc_l1);
62912 		} else {
62913 			duk__emit_jump(comp_ctx, pc_l2);
62914 		}
62915 		/* temp reset is not necessary after duk__parse_stmt(), which already does it */
62916 
62917 		pc_l4 = duk__get_current_pc(comp_ctx);
62918 
62919 		DUK_DDD(DUK_DDDPRINT("patching jumps: jumpto_l3: %ld->%ld, jumpto_l4: %ld->%ld, "
62920 		                     "break: %ld->%ld, continue: %ld->%ld",
62921 			             (long) pc_jumpto_l3, (long) pc_l3, (long) pc_jumpto_l4, (long) pc_l4,
62922 		                     (long) (pc_label_site + 1), (long) pc_l4, (long) (pc_label_site + 2), (long) pc_l2));
62923 
62924 		duk__patch_jump(comp_ctx, pc_jumpto_l3, pc_l3);
62925 		duk__patch_jump(comp_ctx, pc_jumpto_l4, pc_l4);
62926 		duk__patch_jump(comp_ctx,
62927 		                pc_label_site + 1,
62928 		                pc_l4);                         /* break jump */
62929 		duk__patch_jump(comp_ctx,
62930 		                pc_label_site + 2,
62931 		                expr_c_empty ? pc_l1 : pc_l2);  /* continue jump */
62932 	}
62933 	goto finished;
62934 
62935  parse_3_or_4:
62936 	/*
62937 	 *  Parse variant 3 or 4.
62938 	 *
62939 	 *  For variant 3 (e.g. "for (A in C) D;") the code for A (except the
62940 	 *  final property/variable write) has already been emitted.  The first
62941 	 *  instruction of that code is at pc_v34_lhs; a JUMP needs to be inserted
62942 	 *  there to satisfy control flow needs.
62943 	 *
62944 	 *  For variant 4, if the variable declaration had an initializer
62945 	 *  (e.g. "for (var A = B in C) D;") the code for the assignment
62946 	 *  (B) has already been emitted.
62947 	 *
62948 	 *  Variables set before entering here:
62949 	 *
62950 	 *    pc_v34_lhs:    insert a "JUMP L2" here (see doc/compiler.rst example).
62951 	 *    reg_temps + 0: iteration target value (written to LHS)
62952 	 *    reg_temps + 1: enumerator object
62953 	 */
62954 	{
62955 		duk_int_t pc_l1, pc_l2, pc_l3, pc_l4, pc_l5;
62956 		duk_int_t pc_jumpto_l2, pc_jumpto_l3, pc_jumpto_l4, pc_jumpto_l5;
62957 		duk_reg_t reg_target;
62958 
62959 		DUK_DDD(DUK_DDDPRINT("shared code for parsing variants 3 and 4, pc_v34_lhs=%ld", (long) pc_v34_lhs));
62960 
62961 		DUK__SETTEMP(comp_ctx, temp_reset);
62962 
62963 		/* First we need to insert a jump in the middle of previously
62964 		 * emitted code to get the control flow right.  No jumps can
62965 		 * cross the position where the jump is inserted.  See doc/compiler.rst
62966 		 * for discussion on the intricacies of control flow and side effects
62967 		 * for variants 3 and 4.
62968 		 */
62969 
62970 		duk__insert_jump_entry(comp_ctx, pc_v34_lhs);
62971 		pc_jumpto_l2 = pc_v34_lhs;  /* inserted jump */
62972 		pc_l1 = pc_v34_lhs + 1;     /* +1, right after inserted jump */
62973 
62974 		/* The code for writing reg_temps + 0 to the left hand side has already
62975 		 * been emitted.
62976 		 */
62977 
62978 		pc_jumpto_l3 = duk__emit_jump_empty(comp_ctx);  /* -> loop body */
62979 
62980 		duk__advance(comp_ctx);  /* eat 'in' */
62981 
62982 		/* Parse enumeration target and initialize enumerator.  For 'null' and 'undefined',
62983 		 * INITENUM will creates a 'null' enumerator which works like an empty enumerator
62984 		 * (E5 Section 12.6.4, step 3).  Note that INITENUM requires the value to be in a
62985 		 * register (constant not allowed).
62986 		 */
62987 
62988 		pc_l2 = duk__get_current_pc(comp_ctx);
62989 		reg_target = duk__exprtop_toreg(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);  /* Expression */
62990 		duk__emit_extraop_b_c(comp_ctx,
62991 		                      DUK_EXTRAOP_INITENUM | DUK__EMIT_FLAG_B_IS_TARGET,
62992 		                      (duk_regconst_t) (reg_temps + 1),
62993 		                      (duk_regconst_t) reg_target);
62994 		pc_jumpto_l4 = duk__emit_jump_empty(comp_ctx);
62995 		DUK__SETTEMP(comp_ctx, temp_reset);
62996 
62997 		duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);
62998 
62999 		pc_l3 = duk__get_current_pc(comp_ctx);
63000 		duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
63001 		/* temp reset is not necessary after duk__parse_stmt(), which already does it */
63002 
63003 		/* NEXTENUM needs a jump slot right after the main opcode.
63004 		 * We need the code emitter to reserve the slot: if there's
63005 		 * target shuffling, the target shuffle opcodes must happen
63006 		 * after the jump slot (for NEXTENUM the shuffle opcodes are
63007 		 * not needed if the enum is finished).
63008 		 */
63009 		pc_l4 = duk__get_current_pc(comp_ctx);
63010 		duk__emit_extraop_b_c(comp_ctx,
63011 		                      DUK_EXTRAOP_NEXTENUM | DUK__EMIT_FLAG_B_IS_TARGET | DUK__EMIT_FLAG_RESERVE_JUMPSLOT,
63012 		                      (duk_regconst_t) (reg_temps + 0),
63013 		                      (duk_regconst_t) (reg_temps + 1));
63014 		pc_jumpto_l5 = comp_ctx->emit_jumpslot_pc;  /* NEXTENUM jump slot: executed when enum finished */
63015 		duk__emit_jump(comp_ctx, pc_l1);  /* jump to next loop, using reg_v34_iter as iterated value */
63016 
63017 		pc_l5 = duk__get_current_pc(comp_ctx);
63018 
63019 		/* XXX: since the enumerator may be a memory expensive object,
63020 		 * perhaps clear it explicitly here?  If so, break jump must
63021 		 * go through this clearing operation.
63022 		 */
63023 
63024 		DUK_DDD(DUK_DDDPRINT("patching jumps: jumpto_l2: %ld->%ld, jumpto_l3: %ld->%ld, "
63025 		                     "jumpto_l4: %ld->%ld, jumpto_l5: %ld->%ld, "
63026 		                     "break: %ld->%ld, continue: %ld->%ld",
63027 			             (long) pc_jumpto_l2, (long) pc_l2, (long) pc_jumpto_l3, (long) pc_l3,
63028 			             (long) pc_jumpto_l4, (long) pc_l4, (long) pc_jumpto_l5, (long) pc_l5,
63029 		                     (long) (pc_label_site + 1), (long) pc_l5, (long) (pc_label_site + 2), (long) pc_l4));
63030 
63031 		duk__patch_jump(comp_ctx, pc_jumpto_l2, pc_l2);
63032 		duk__patch_jump(comp_ctx, pc_jumpto_l3, pc_l3);
63033 		duk__patch_jump(comp_ctx, pc_jumpto_l4, pc_l4);
63034 		duk__patch_jump(comp_ctx, pc_jumpto_l5, pc_l5);
63035 		duk__patch_jump(comp_ctx, pc_label_site + 1, pc_l5);  /* break jump */
63036 		duk__patch_jump(comp_ctx, pc_label_site + 2, pc_l4);  /* continue jump */
63037 	}
63038 	goto finished;
63039 
63040  finished:
63041 	DUK_DDD(DUK_DDDPRINT("end parsing a for/for-in statement"));
63042 	return;
63043 
63044  syntax_error:
63045 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_FOR);
63046 }
63047 
63048 DUK_LOCAL void duk__parse_switch_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {
63049 	duk_hthread *thr = comp_ctx->thr;
63050 	duk_reg_t temp_at_loop;
63051 	duk_regconst_t rc_switch;    /* reg/const for switch value */
63052 	duk_regconst_t rc_case;      /* reg/const for case value */
63053 	duk_reg_t reg_temp;          /* general temp register */
63054 	duk_int_t pc_prevcase = -1;
63055 	duk_int_t pc_prevstmt = -1;
63056 	duk_int_t pc_default = -1;   /* -1 == not set, -2 == pending (next statement list) */
63057 
63058 	/* Note: negative pc values are ignored when patching jumps, so no explicit checks needed */
63059 
63060 	/*
63061 	 *  Switch is pretty complicated because of several conflicting concerns:
63062 	 *
63063 	 *    - Want to generate code without an intermediate representation,
63064 	 *      i.e., in one go
63065 	 *
63066 	 *    - Case selectors are expressions, not values, and may thus e.g. throw
63067 	 *      exceptions (which causes evaluation order concerns)
63068 	 *
63069 	 *    - Evaluation semantics of case selectors and default clause need to be
63070 	 *      carefully implemented to provide correct behavior even with case value
63071 	 *      side effects
63072 	 *
63073 	 *    - Fall through case and default clauses; avoiding dead JUMPs if case
63074 	 *      ends with an unconditional jump (a break or a continue)
63075 	 *
63076 	 *    - The same case value may occur multiple times, but evaluation rules
63077 	 *      only process the first match before switching to a "propagation" mode
63078 	 *      where case values are no longer evaluated
63079 	 *
63080 	 *  See E5 Section 12.11.  Also see doc/compiler.rst for compilation
63081 	 *  discussion.
63082 	 */
63083 
63084 	duk__advance(comp_ctx);
63085 	duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
63086 	rc_switch = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
63087 	duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);
63088 	duk__advance_expect(comp_ctx, DUK_TOK_LCURLY);
63089 
63090 	DUK_DDD(DUK_DDDPRINT("switch value in register %ld", (long) rc_switch));
63091 
63092 	temp_at_loop = DUK__GETTEMP(comp_ctx);
63093 
63094 	for (;;) {
63095 		duk_int_t num_stmts;
63096 		duk_small_int_t tok;
63097 
63098 		/* sufficient for keeping temp reg numbers in check */
63099 		DUK__SETTEMP(comp_ctx, temp_at_loop);
63100 
63101 		if (comp_ctx->curr_token.t == DUK_TOK_RCURLY) {
63102 			break;
63103 		}
63104 
63105 		/*
63106 		 *  Parse a case or default clause.
63107 		 */
63108 
63109 		if (comp_ctx->curr_token.t == DUK_TOK_CASE) {
63110 			/*
63111 			 *  Case clause.
63112 			 *
63113 			 *  Note: cannot use reg_case as a temp register (for SEQ target)
63114 			 *  because it may be a constant.
63115 			 */
63116 
63117 			duk__patch_jump_here(comp_ctx, pc_prevcase);  /* chain jumps for case
63118 			                                               * evaluation and checking
63119 			                                               */
63120 
63121 			duk__advance(comp_ctx);
63122 			rc_case = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
63123 			duk__advance_expect(comp_ctx, DUK_TOK_COLON);
63124 
63125 			reg_temp = DUK__ALLOCTEMP(comp_ctx);
63126 			duk__emit_a_b_c(comp_ctx,
63127 			                DUK_OP_SEQ,
63128 			                (duk_regconst_t) reg_temp,
63129 			                rc_switch,
63130 			                rc_case);
63131 			duk__emit_if_true_skip(comp_ctx, (duk_regconst_t) reg_temp);
63132 
63133 			/* jump to next case clause */
63134 			pc_prevcase = duk__emit_jump_empty(comp_ctx);  /* no match, next case */
63135 
63136 			/* statements go here (if any) on next loop */
63137 		} else if (comp_ctx->curr_token.t == DUK_TOK_DEFAULT) {
63138 			/*
63139 			 *  Default clause.
63140 			 */
63141 
63142 			if (pc_default >= 0) {
63143 				goto syntax_error;
63144 			}
63145 			duk__advance(comp_ctx);
63146 			duk__advance_expect(comp_ctx, DUK_TOK_COLON);
63147 
63148 			/* Fix for https://github.com/svaarala/duktape/issues/155:
63149 			 * If 'default' is first clause (detected by pc_prevcase < 0)
63150 			 * we need to ensure we stay in the matching chain.
63151 			 */
63152 			if (pc_prevcase < 0) {
63153 				DUK_DD(DUK_DDPRINT("default clause is first, emit prevcase jump"));
63154 				pc_prevcase = duk__emit_jump_empty(comp_ctx);
63155 			}
63156 
63157 			/* default clause matches next statement list (if any) */
63158 			pc_default = -2;
63159 		} else {
63160 			/* Code is not accepted before the first case/default clause */
63161 			goto syntax_error;
63162 		}
63163 
63164 		/*
63165 		 *  Parse code after the clause.  Possible terminators are
63166 		 *  'case', 'default', and '}'.
63167 		 *
63168 		 *  Note that there may be no code at all, not even an empty statement,
63169 		 *  between case clauses.  This must be handled just like an empty statement
63170 		 *  (omitting seemingly pointless JUMPs), to avoid situations like
63171 		 *  test-bug-case-fallthrough.js.
63172 		 */
63173 
63174 		num_stmts = 0;
63175 		if (pc_default == -2) {
63176 			pc_default = duk__get_current_pc(comp_ctx);
63177 		}
63178 
63179 		/* Note: this is correct even for default clause statements:
63180 		 * they participate in 'fall-through' behavior even if the
63181 		 * default clause is in the middle.
63182 		 */
63183 		duk__patch_jump_here(comp_ctx, pc_prevstmt);  /* chain jumps for 'fall-through'
63184 		                                               * after a case matches.
63185 		                                               */
63186 
63187 		for (;;) {
63188 			tok = comp_ctx->curr_token.t;
63189 			if (tok == DUK_TOK_CASE || tok == DUK_TOK_DEFAULT ||
63190 			    tok == DUK_TOK_RCURLY) {
63191 				break;
63192 			}
63193 			num_stmts++;
63194 			duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
63195 		}
63196 
63197 		/* fall-through jump to next code of next case (backpatched) */
63198 		pc_prevstmt = duk__emit_jump_empty(comp_ctx);
63199 
63200 		/* XXX: would be nice to omit this jump when the jump is not
63201 		 * reachable, at least in the obvious cases (such as the case
63202 		 * ending with a 'break'.
63203 		 *
63204 		 * Perhaps duk__parse_stmt() could provide some info on whether
63205 		 * the statement is a "dead end"?
63206 		 *
63207 		 * If implemented, just set pc_prevstmt to -1 when not needed.
63208 		 */
63209 	}
63210 
63211 	DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_RCURLY);
63212 	duk__advance(comp_ctx);
63213 
63214 	/* default case control flow patchup; note that if pc_prevcase < 0
63215 	 * (i.e. no case clauses), control enters default case automatically.
63216 	 */
63217 	if (pc_default >= 0) {
63218 		/* default case exists: go there if no case matches */
63219 		duk__patch_jump(comp_ctx, pc_prevcase, pc_default);
63220 	} else {
63221 		/* default case does not exist, or no statements present
63222 		 * after default case: finish case evaluation
63223 		 */
63224 		duk__patch_jump_here(comp_ctx, pc_prevcase);
63225 	}
63226 
63227 	/* fall-through control flow patchup; note that pc_prevstmt may be
63228 	 * < 0 (i.e. no case clauses), in which case this is a no-op.
63229 	 */
63230 	duk__patch_jump_here(comp_ctx, pc_prevstmt);
63231 
63232 	/* continue jump not patched, an INVALID opcode remains there */
63233 	duk__patch_jump_here(comp_ctx, pc_label_site + 1);  /* break jump */
63234 
63235 	/* Note: 'fast' breaks will jump to pc_label_site + 1, which will
63236 	 * then jump here.  The double jump will be eliminated by a
63237 	 * peephole pass, resulting in an optimal jump here.  The label
63238 	 * site jumps will remain in bytecode and will waste code size.
63239 	 */
63240 
63241 	return;
63242 
63243  syntax_error:
63244 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_SWITCH);
63245 }
63246 
63247 DUK_LOCAL void duk__parse_if_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
63248 	duk_reg_t temp_reset;
63249 	duk_regconst_t rc_cond;
63250 	duk_int_t pc_jump_false;
63251 
63252 	DUK_DDD(DUK_DDDPRINT("begin parsing if statement"));
63253 
63254 	temp_reset = DUK__GETTEMP(comp_ctx);
63255 
63256 	duk__advance(comp_ctx);  /* eat 'if' */
63257 	duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
63258 
63259 	rc_cond = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
63260 	duk__emit_if_true_skip(comp_ctx, rc_cond);
63261 	pc_jump_false = duk__emit_jump_empty(comp_ctx);  /* jump to end or else part */
63262 	DUK__SETTEMP(comp_ctx, temp_reset);
63263 
63264 	duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);
63265 
63266 	duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
63267 
63268 	/* The 'else' ambiguity is resolved by 'else' binding to the innermost
63269 	 * construct, so greedy matching is correct here.
63270 	 */
63271 
63272 	if (comp_ctx->curr_token.t == DUK_TOK_ELSE) {
63273 		duk_int_t pc_jump_end;
63274 
63275 		DUK_DDD(DUK_DDDPRINT("if has else part"));
63276 
63277 		duk__advance(comp_ctx);
63278 
63279 		pc_jump_end = duk__emit_jump_empty(comp_ctx);  /* jump from true part to end */
63280 		duk__patch_jump_here(comp_ctx, pc_jump_false);
63281 
63282 		duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
63283 
63284 		duk__patch_jump_here(comp_ctx, pc_jump_end);
63285 	} else {
63286 		DUK_DDD(DUK_DDDPRINT("if does not have else part"));
63287 
63288 		duk__patch_jump_here(comp_ctx, pc_jump_false);
63289 	}
63290 
63291 	DUK_DDD(DUK_DDDPRINT("end parsing if statement"));
63292 }
63293 
63294 DUK_LOCAL void duk__parse_do_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {
63295 	duk_regconst_t rc_cond;
63296 	duk_int_t pc_start;
63297 
63298 	DUK_DDD(DUK_DDDPRINT("begin parsing do statement"));
63299 
63300 	duk__advance(comp_ctx);  /* eat 'do' */
63301 
63302 	pc_start = duk__get_current_pc(comp_ctx);
63303 	duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
63304 	duk__patch_jump_here(comp_ctx, pc_label_site + 2);  /* continue jump */
63305 
63306 	duk__advance_expect(comp_ctx, DUK_TOK_WHILE);
63307 	duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
63308 
63309 	rc_cond = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
63310 	duk__emit_if_false_skip(comp_ctx, rc_cond);
63311 	duk__emit_jump(comp_ctx, pc_start);
63312 	/* no need to reset temps, as we're finished emitting code */
63313 
63314 	duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);
63315 
63316 	duk__patch_jump_here(comp_ctx, pc_label_site + 1);  /* break jump */
63317 
63318 	DUK_DDD(DUK_DDDPRINT("end parsing do statement"));
63319 }
63320 
63321 DUK_LOCAL void duk__parse_while_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {
63322 	duk_reg_t temp_reset;
63323 	duk_regconst_t rc_cond;
63324 	duk_int_t pc_start;
63325 	duk_int_t pc_jump_false;
63326 
63327 	DUK_DDD(DUK_DDDPRINT("begin parsing while statement"));
63328 
63329 	temp_reset = DUK__GETTEMP(comp_ctx);
63330 
63331 	duk__advance(comp_ctx);  /* eat 'while' */
63332 
63333 	duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
63334 
63335 	pc_start = duk__get_current_pc(comp_ctx);
63336 	duk__patch_jump_here(comp_ctx, pc_label_site + 2);  /* continue jump */
63337 
63338 	rc_cond = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
63339 	duk__emit_if_true_skip(comp_ctx, rc_cond);
63340 	pc_jump_false = duk__emit_jump_empty(comp_ctx);
63341 	DUK__SETTEMP(comp_ctx, temp_reset);
63342 
63343 	duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);
63344 
63345 	duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
63346 	duk__emit_jump(comp_ctx, pc_start);
63347 
63348 	duk__patch_jump_here(comp_ctx, pc_jump_false);
63349 	duk__patch_jump_here(comp_ctx, pc_label_site + 1);  /* break jump */
63350 
63351 	DUK_DDD(DUK_DDDPRINT("end parsing while statement"));
63352 }
63353 
63354 DUK_LOCAL void duk__parse_break_or_continue_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
63355 	duk_hthread *thr = comp_ctx->thr;
63356 	duk_bool_t is_break = (comp_ctx->curr_token.t == DUK_TOK_BREAK);
63357 	duk_int_t label_id;
63358 	duk_int_t label_catch_depth;
63359 	duk_int_t label_pc;  /* points to LABEL; pc+1 = jump site for break; pc+2 = jump site for continue */
63360 	duk_bool_t label_is_closest;
63361 
63362 	DUK_UNREF(res);
63363 
63364 	duk__advance(comp_ctx);  /* eat 'break' or 'continue' */
63365 
63366 	if (comp_ctx->curr_token.t == DUK_TOK_SEMICOLON ||  /* explicit semi follows */
63367 	    comp_ctx->curr_token.lineterm ||                /* automatic semi will be inserted */
63368 	    comp_ctx->curr_token.allow_auto_semi) {         /* automatic semi will be inserted */
63369 		/* break/continue without label */
63370 
63371 		duk__lookup_active_label(comp_ctx, DUK_HTHREAD_STRING_EMPTY_STRING(thr), is_break, &label_id, &label_catch_depth, &label_pc, &label_is_closest);
63372 	} else if (comp_ctx->curr_token.t == DUK_TOK_IDENTIFIER) {
63373 		/* break/continue with label (label cannot be a reserved word, production is 'Identifier' */
63374 		DUK_ASSERT(comp_ctx->curr_token.str1 != NULL);
63375 		duk__lookup_active_label(comp_ctx, comp_ctx->curr_token.str1, is_break, &label_id, &label_catch_depth, &label_pc, &label_is_closest);
63376 		duk__advance(comp_ctx);
63377 	} else {
63378 		DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_BREAK_CONT_LABEL);
63379 	}
63380 
63381 	/* Use a fast break/continue when possible.  A fast break/continue is
63382 	 * just a jump to the LABEL break/continue jump slot, which then jumps
63383 	 * to an appropriate place (for break, going through ENDLABEL correctly).
63384 	 * The peephole optimizer will optimize the jump to a direct one.
63385 	 */
63386 
63387 	if (label_catch_depth == comp_ctx->curr_func.catch_depth &&
63388 	    label_is_closest) {
63389 		DUK_DDD(DUK_DDDPRINT("break/continue: is_break=%ld, label_id=%ld, label_is_closest=%ld, "
63390 		                     "label_catch_depth=%ld, catch_depth=%ld "
63391 		                     "-> use fast variant (direct jump)",
63392 		                     (long) is_break, (long) label_id, (long) label_is_closest,
63393 		                     (long) label_catch_depth, (long) comp_ctx->curr_func.catch_depth));
63394 
63395 		duk__emit_jump(comp_ctx, label_pc + (is_break ? 1 : 2));
63396 	} else {
63397 		DUK_DDD(DUK_DDDPRINT("break/continue: is_break=%ld, label_id=%ld, label_is_closest=%ld, "
63398 		                     "label_catch_depth=%ld, catch_depth=%ld "
63399 		                     "-> use slow variant (longjmp)",
63400 		                     (long) is_break, (long) label_id, (long) label_is_closest,
63401 		                     (long) label_catch_depth, (long) comp_ctx->curr_func.catch_depth));
63402 
63403 		duk__emit_extraop_bc(comp_ctx,
63404 		              is_break ? DUK_EXTRAOP_BREAK : DUK_EXTRAOP_CONTINUE,
63405 		              (duk_regconst_t) label_id);
63406 	}
63407 }
63408 
63409 DUK_LOCAL void duk__parse_return_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
63410 	duk_hthread *thr = comp_ctx->thr;
63411 	duk_regconst_t rc_val;
63412 	duk_small_uint_t ret_flags;
63413 
63414 	duk__advance(comp_ctx);  /* eat 'return' */
63415 
63416 	/* A 'return' statement is only allowed inside an actual function body,
63417 	 * not as part of eval or global code.
63418 	 */
63419 	if (!comp_ctx->curr_func.is_function) {
63420 		DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_RETURN);
63421 	}
63422 
63423 	ret_flags = 0;
63424 
63425 	if (comp_ctx->curr_token.t == DUK_TOK_SEMICOLON ||  /* explicit semi follows */
63426 	    comp_ctx->curr_token.lineterm ||                /* automatic semi will be inserted */
63427 	    comp_ctx->curr_token.allow_auto_semi) {         /* automatic semi will be inserted */
63428 		DUK_DDD(DUK_DDDPRINT("empty return value -> undefined"));
63429 		rc_val = 0;
63430 	} else {
63431 		duk_int_t pc_before_expr;
63432 		duk_int_t pc_after_expr;
63433 
63434 		DUK_DDD(DUK_DDDPRINT("return with a value"));
63435 
63436 		DUK_UNREF(pc_before_expr);
63437 		DUK_UNREF(pc_after_expr);
63438 
63439 		pc_before_expr = duk__get_current_pc(comp_ctx);
63440 		rc_val = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
63441 		pc_after_expr = duk__get_current_pc(comp_ctx);
63442 
63443 		/* Tail call check: if last opcode emitted was CALL(I), and
63444 		 * the context allows it, change the CALL(I) to a tail call.
63445 		 * This doesn't guarantee that a tail call will be allowed at
63446 		 * runtime, so the RETURN must still be emitted.  (Duktape
63447 		 * 0.10.0 avoided this and simulated a RETURN if a tail call
63448 		 * couldn't be used at runtime; but this didn't work
63449 		 * correctly with a thread yield/resume, see
63450 		 * test-bug-tailcall-thread-yield-resume.js for discussion.)
63451 		 *
63452 		 * In addition to the last opcode being CALL, we also need to
63453 		 * be sure that 'rc_val' is the result register of the CALL(I).
63454 		 * For instance, for the expression 'return 0, (function ()
63455 		 * { return 1; }), 2' the last opcode emitted is CALL (no
63456 		 * bytecode is emitted for '2') but 'rc_val' indicates
63457 		 * constant '2'.  Similarly if '2' is replaced by a register
63458 		 * bound variable, no opcodes are emitted but tail call would
63459 		 * be incorrect.
63460 		 *
63461 		 * This is tricky and easy to get wrong.  It would be best to
63462 		 * track enough expression metadata to check that 'rc_val' came
63463 		 * from that last CALL instruction.  We don't have that metadata
63464 		 * now, so we check that 'rc_val' is a temporary register result
63465 		 * (not a constant or a register bound variable).  There should
63466 		 * be no way currently for 'rc_val' to be a temporary for an
63467 		 * expression following the CALL instruction without emitting
63468 		 * some opcodes following the CALL.  This proxy check is used
63469 		 * below.
63470 		 *
63471 		 * See: test-bug-comma-expr-gh131.js.
63472 		 *
63473 		 * The non-standard 'caller' property disables tail calls
63474 		 * because they pose some special cases which haven't been
63475 		 * fixed yet.
63476 		 */
63477 
63478 #if defined(DUK_USE_TAILCALL)
63479 		if (comp_ctx->curr_func.catch_depth == 0 &&   /* no catchers */
63480 		    pc_after_expr > pc_before_expr) {         /* at least one opcode emitted */
63481 			duk_compiler_instr *instr;
63482 			duk_small_uint_t op;
63483 
63484 			instr = duk__get_instr_ptr(comp_ctx, pc_after_expr - 1);
63485 			DUK_ASSERT(instr != NULL);
63486 
63487 			op = (duk_small_uint_t) DUK_DEC_OP(instr->ins);
63488 			if ((op == DUK_OP_CALL || op == DUK_OP_CALLI) &&
63489 			    DUK__ISTEMP(comp_ctx, rc_val) /* see above */) {
63490 				DUK_DDD(DUK_DDDPRINT("return statement detected a tail call opportunity: "
63491 				                     "catch depth is 0, duk__exprtop() emitted >= 1 instructions, "
63492 				                     "and last instruction is a CALL "
63493 				                     "-> set TAILCALL flag"));
63494 				/* Just flip the single bit. */
63495 				instr->ins |= DUK_ENC_OP_A_B_C(0, DUK_BC_CALL_FLAG_TAILCALL, 0, 0);
63496 			}
63497 		}
63498 #endif  /* DUK_USE_TAILCALL */
63499 
63500 		ret_flags = DUK_BC_RETURN_FLAG_HAVE_RETVAL;
63501 	}
63502 
63503 	duk__emit_a_b(comp_ctx,
63504 	              DUK_OP_RETURN | DUK__EMIT_FLAG_NO_SHUFFLE_A,
63505 	              (duk_regconst_t) ret_flags /*flags*/,
63506 	              rc_val /*reg*/);
63507 }
63508 
63509 DUK_LOCAL void duk__parse_throw_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
63510 	duk_reg_t reg_val;
63511 
63512 	duk__advance(comp_ctx);  /* eat 'throw' */
63513 
63514 	/* Unlike break/continue, throw statement does not allow an empty value. */
63515 
63516 	if (comp_ctx->curr_token.lineterm) {
63517 		DUK_ERROR_SYNTAX(comp_ctx->thr, DUK_STR_INVALID_THROW);
63518 	}
63519 
63520 	reg_val = duk__exprtop_toreg(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
63521 	duk__emit_extraop_bc(comp_ctx,
63522 	                     DUK_EXTRAOP_THROW,
63523 	                     (duk_regconst_t) reg_val);
63524 }
63525 
63526 DUK_LOCAL void duk__parse_try_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
63527 	duk_hthread *thr = comp_ctx->thr;
63528 	duk_context *ctx = (duk_context *) thr;
63529 	duk_reg_t reg_catch;      /* reg_catch+0 and reg_catch+1 are reserved for TRYCATCH */
63530 	duk_regconst_t rc_varname = 0;
63531 	duk_small_uint_t trycatch_flags = 0;
63532 	duk_int_t pc_ldconst = -1;
63533 	duk_int_t pc_trycatch = -1;
63534 	duk_int_t pc_catch = -1;
63535 	duk_int_t pc_finally = -1;
63536 
63537 	DUK_UNREF(res);
63538 
63539 	/*
63540 	 *  See the following documentation for discussion:
63541 	 *
63542 	 *    doc/execution.rst: control flow details
63543 	 *
63544 	 *  Try, catch, and finally "parts" are Blocks, not Statements, so
63545 	 *  they must always be delimited by curly braces.  This is unlike e.g.
63546 	 *  the if statement, which accepts any Statement.  This eliminates any
63547 	 *  questions of matching parts of nested try statements.  The Block
63548 	 *  parsing is implemented inline here (instead of calling out).
63549 	 *
63550 	 *  Finally part has a 'let scoped' variable, which requires a few kinks
63551 	 *  here.
63552 	 */
63553 
63554 	comp_ctx->curr_func.catch_depth++;
63555 
63556 	duk__advance(comp_ctx);  /* eat 'try' */
63557 
63558 	reg_catch = DUK__ALLOCTEMPS(comp_ctx, 2);
63559 
63560 	/* The target for this LDCONST may need output shuffling, but we assume
63561 	 * that 'pc_ldconst' will be the LDCONST that we can patch later.  This
63562 	 * should be the case because there's no input shuffling.  (If there's
63563 	 * no catch clause, this LDCONST will be replaced with a NOP.)
63564 	 */
63565 	pc_ldconst = duk__get_current_pc(comp_ctx);
63566 	duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, reg_catch, 0 /*patched later*/);
63567 
63568 	pc_trycatch = duk__get_current_pc(comp_ctx);
63569 	duk__emit_invalid(comp_ctx);  /* TRYCATCH, cannot emit now (not enough info) */
63570 	duk__emit_invalid(comp_ctx);  /* jump for 'catch' case */
63571 	duk__emit_invalid(comp_ctx);  /* jump for 'finally' case or end (if no finally) */
63572 
63573 	/* try part */
63574 	duk__advance_expect(comp_ctx, DUK_TOK_LCURLY);
63575 	duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/);
63576 	/* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */
63577 	duk__emit_extraop_only(comp_ctx,
63578 	                       DUK_EXTRAOP_ENDTRY);
63579 
63580 	if (comp_ctx->curr_token.t == DUK_TOK_CATCH) {
63581 		/*
63582 		 *  The catch variable must be updated to reflect the new allocated
63583 		 *  register for the duration of the catch clause.  We need to store
63584 		 *  and restore the original value for the varmap entry (if any).
63585 		 */
63586 
63587 		/*
63588 		 *  Note: currently register bindings must be fixed for the entire
63589 		 *  function.  So, even though the catch variable is in a register
63590 		 *  we know, we must use an explicit environment record and slow path
63591 		 *  accesses to read/write the catch binding to make closures created
63592 		 *  within the catch clause work correctly.  This restriction should
63593 		 *  be fixable (at least in common cases) later.
63594 		 *
63595 		 *  See: test-bug-catch-binding-2.js.
63596 		 *
63597 		 *  XXX: improve to get fast path access to most catch clauses.
63598 		 */
63599 
63600 		duk_hstring *h_var;
63601 		duk_int_t varmap_value;  /* for storing/restoring the varmap binding for catch variable */
63602 
63603 		DUK_DDD(DUK_DDDPRINT("stack top at start of catch clause: %ld", (long) duk_get_top(ctx)));
63604 
63605 		trycatch_flags |= DUK_BC_TRYCATCH_FLAG_HAVE_CATCH;
63606 
63607 		pc_catch = duk__get_current_pc(comp_ctx);
63608 
63609 		duk__advance(comp_ctx);
63610 		duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
63611 
63612 		if (comp_ctx->curr_token.t != DUK_TOK_IDENTIFIER) {
63613 			/* Identifier, i.e. don't allow reserved words */
63614 			goto syntax_error;
63615 		}
63616 		h_var = comp_ctx->curr_token.str1;
63617 		DUK_ASSERT(h_var != NULL);
63618 
63619 		duk_push_hstring(ctx, h_var);  /* keep in on valstack, use borrowed ref below */
63620 
63621 		if (comp_ctx->curr_func.is_strict &&
63622 		    ((h_var == DUK_HTHREAD_STRING_EVAL(thr)) ||
63623 		     (h_var == DUK_HTHREAD_STRING_LC_ARGUMENTS(thr)))) {
63624 			DUK_DDD(DUK_DDDPRINT("catch identifier 'eval' or 'arguments' in strict mode -> SyntaxError"));
63625 			goto syntax_error;
63626 		}
63627 
63628 		duk_dup_top(ctx);
63629 		rc_varname = duk__getconst(comp_ctx);
63630 		DUK_DDD(DUK_DDDPRINT("catch clause, rc_varname=0x%08lx (%ld)",
63631 		                     (unsigned long) rc_varname, (long) rc_varname));
63632 
63633 		duk__advance(comp_ctx);
63634 		duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);
63635 
63636 		duk__advance_expect(comp_ctx, DUK_TOK_LCURLY);
63637 
63638 		DUK_DDD(DUK_DDDPRINT("varmap before modifying for catch clause: %!iT",
63639 		                     (duk_tval *) duk_get_tval(ctx, comp_ctx->curr_func.varmap_idx)));
63640 
63641 		duk_dup_top(ctx);
63642 		duk_get_prop(ctx, comp_ctx->curr_func.varmap_idx);
63643 		if (duk_is_undefined(ctx, -1)) {
63644 			varmap_value = -2;
63645 		} else if (duk_is_null(ctx, -1)) {
63646 			varmap_value = -1;
63647 		} else {
63648 			DUK_ASSERT(duk_is_number(ctx, -1));
63649 			varmap_value = duk_get_int(ctx, -1);
63650 			DUK_ASSERT(varmap_value >= 0);
63651 		}
63652 		duk_pop(ctx);
63653 
63654 #if 0
63655 		/* It'd be nice to do something like this - but it doesn't
63656 		 * work for closures created inside the catch clause.
63657 		 */
63658 		duk_dup_top(ctx);
63659 		duk_push_int(ctx, (duk_int_t) (reg_catch + 0));
63660 		duk_put_prop(ctx, comp_ctx->curr_func.varmap_idx);
63661 #endif
63662 		duk_dup_top(ctx);
63663 		duk_push_null(ctx);
63664 		duk_put_prop(ctx, comp_ctx->curr_func.varmap_idx);
63665 
63666 		duk__emit_a_bc(comp_ctx,
63667 		               DUK_OP_PUTVAR | DUK__EMIT_FLAG_A_IS_SOURCE,
63668 		               (duk_regconst_t) (reg_catch + 0) /*value*/,
63669 		               rc_varname /*varname*/);
63670 
63671 		DUK_DDD(DUK_DDDPRINT("varmap before parsing catch clause: %!iT",
63672 		                     (duk_tval *) duk_get_tval(ctx, comp_ctx->curr_func.varmap_idx)));
63673 
63674 		duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/);
63675 		/* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */
63676 
63677 		if (varmap_value == -2) {
63678 			/* not present */
63679 			duk_del_prop(ctx, comp_ctx->curr_func.varmap_idx);
63680 		} else {
63681 			if (varmap_value == -1) {
63682 				duk_push_null(ctx);
63683 			} else {
63684 				DUK_ASSERT(varmap_value >= 0);
63685 				duk_push_int(ctx, varmap_value);
63686 			}
63687 			duk_put_prop(ctx, comp_ctx->curr_func.varmap_idx);
63688 		}
63689 		/* varname is popped by above code */
63690 
63691 		DUK_DDD(DUK_DDDPRINT("varmap after restore catch clause: %!iT",
63692 		                     (duk_tval *) duk_get_tval(ctx, comp_ctx->curr_func.varmap_idx)));
63693 
63694 		duk__emit_extraop_only(comp_ctx,
63695 		                       DUK_EXTRAOP_ENDCATCH);
63696 
63697 		/*
63698 		 *  XXX: for now, indicate that an expensive catch binding
63699 		 *  declarative environment is always needed.  If we don't
63700 		 *  need it, we don't need the const_varname either.
63701 		 */
63702 
63703 		trycatch_flags |= DUK_BC_TRYCATCH_FLAG_CATCH_BINDING;
63704 
63705 		DUK_DDD(DUK_DDDPRINT("stack top at end of catch clause: %ld", (long) duk_get_top(ctx)));
63706 	}
63707 
63708 	if (comp_ctx->curr_token.t == DUK_TOK_FINALLY) {
63709 		trycatch_flags |= DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY;
63710 
63711 		pc_finally = duk__get_current_pc(comp_ctx);
63712 
63713 		duk__advance(comp_ctx);
63714 
63715 		duk__advance_expect(comp_ctx, DUK_TOK_LCURLY);
63716 		duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/);
63717 		/* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */
63718 		duk__emit_extraop_b(comp_ctx,
63719 		                    DUK_EXTRAOP_ENDFIN,
63720 		                    reg_catch);  /* rethrow */
63721 	}
63722 
63723 	if (!(trycatch_flags & DUK_BC_TRYCATCH_FLAG_HAVE_CATCH) &&
63724 	    !(trycatch_flags & DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY)) {
63725 		/* must have catch and/or finally */
63726 		goto syntax_error;
63727 	}
63728 
63729 	/* If there's no catch block, rc_varname will be 0 and duk__patch_trycatch()
63730 	 * will replace the LDCONST with a NOP.  For any actual constant (including
63731 	 * constant 0) the DUK__CONST_MARKER flag will be set in rc_varname.
63732 	 */
63733 
63734 	duk__patch_trycatch(comp_ctx,
63735 	                    pc_ldconst,
63736 	                    pc_trycatch,
63737 	                    reg_catch,
63738 	                    rc_varname,
63739 	                    trycatch_flags);
63740 
63741 	if (trycatch_flags & DUK_BC_TRYCATCH_FLAG_HAVE_CATCH) {
63742 		DUK_ASSERT(pc_catch >= 0);
63743 		duk__patch_jump(comp_ctx, pc_trycatch + 1, pc_catch);
63744 	}
63745 
63746 	if (trycatch_flags & DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY) {
63747 		DUK_ASSERT(pc_finally >= 0);
63748 		duk__patch_jump(comp_ctx, pc_trycatch + 2, pc_finally);
63749 	} else {
63750 		/* without finally, the second jump slot is used to jump to end of stmt */
63751 		duk__patch_jump_here(comp_ctx, pc_trycatch + 2);
63752 	}
63753 
63754 	comp_ctx->curr_func.catch_depth--;
63755 	return;
63756 
63757  syntax_error:
63758 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_TRY);
63759 }
63760 
63761 DUK_LOCAL void duk__parse_with_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
63762 	duk_int_t pc_trycatch;
63763 	duk_int_t pc_finished;
63764 	duk_reg_t reg_catch;
63765 	duk_small_uint_t trycatch_flags;
63766 
63767 	if (comp_ctx->curr_func.is_strict) {
63768 		DUK_ERROR_SYNTAX(comp_ctx->thr, DUK_STR_WITH_IN_STRICT_MODE);
63769 	}
63770 
63771 	comp_ctx->curr_func.catch_depth++;
63772 
63773 	duk__advance(comp_ctx);  /* eat 'with' */
63774 
63775 	reg_catch = DUK__ALLOCTEMPS(comp_ctx, 2);
63776 
63777 	duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
63778 	duk__exprtop_toforcedreg(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/, reg_catch);
63779 	duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);
63780 
63781 	pc_trycatch = duk__get_current_pc(comp_ctx);
63782 	trycatch_flags = DUK_BC_TRYCATCH_FLAG_WITH_BINDING;
63783 	duk__emit_a_bc(comp_ctx,
63784 	                DUK_OP_TRYCATCH | DUK__EMIT_FLAG_NO_SHUFFLE_A,
63785 	                (duk_regconst_t) trycatch_flags /*a*/,
63786 	                (duk_regconst_t) reg_catch /*bc*/);
63787 	duk__emit_invalid(comp_ctx);  /* catch jump */
63788 	duk__emit_invalid(comp_ctx);  /* finished jump */
63789 
63790 	duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
63791 	duk__emit_extraop_only(comp_ctx,
63792 	                       DUK_EXTRAOP_ENDTRY);
63793 
63794 	pc_finished = duk__get_current_pc(comp_ctx);
63795 
63796 	duk__patch_jump(comp_ctx, pc_trycatch + 2, pc_finished);
63797 
63798 	comp_ctx->curr_func.catch_depth--;
63799 }
63800 
63801 DUK_LOCAL duk_int_t duk__stmt_label_site(duk_compiler_ctx *comp_ctx, duk_int_t label_id) {
63802 	/* if a site already exists, nop: max one label site per statement */
63803 	if (label_id >= 0) {
63804 		return label_id;
63805 	}
63806 
63807 	label_id = comp_ctx->curr_func.label_next++;
63808 	DUK_DDD(DUK_DDDPRINT("allocated new label id for label site: %ld", (long) label_id));
63809 
63810 	duk__emit_extraop_bc(comp_ctx,
63811 	                     DUK_EXTRAOP_LABEL,
63812 	                     (duk_regconst_t) label_id);
63813 	duk__emit_invalid(comp_ctx);
63814 	duk__emit_invalid(comp_ctx);
63815 
63816 	return label_id;
63817 }
63818 
63819 /* Parse a single statement.
63820  *
63821  * Creates a label site (with an empty label) automatically for iteration
63822  * statements.  Also "peels off" any label statements for explicit labels.
63823  */
63824 DUK_LOCAL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_bool_t allow_source_elem) {
63825 	duk_hthread *thr = comp_ctx->thr;
63826 	duk_context *ctx = (duk_context *) thr;
63827 	duk_bool_t dir_prol_at_entry;    /* directive prologue status at entry */
63828 	duk_reg_t temp_at_entry;
63829 	duk_uarridx_t labels_len_at_entry;
63830 	duk_int_t pc_at_entry;           /* assumed to also be PC of "LABEL" */
63831 	duk_int_t stmt_id;
63832 	duk_small_uint_t stmt_flags = 0;
63833 	duk_int_t label_id = -1;
63834 	duk_small_uint_t tok;
63835 
63836 	DUK__RECURSION_INCREASE(comp_ctx, thr);
63837 
63838 	temp_at_entry = DUK__GETTEMP(comp_ctx);
63839 	pc_at_entry = duk__get_current_pc(comp_ctx);
63840 	labels_len_at_entry = (duk_uarridx_t) duk_get_length(ctx, comp_ctx->curr_func.labelnames_idx);
63841 	stmt_id = comp_ctx->curr_func.stmt_next++;
63842 	dir_prol_at_entry = comp_ctx->curr_func.in_directive_prologue;
63843 
63844 	DUK_UNREF(stmt_id);
63845 
63846 	DUK_DDD(DUK_DDDPRINT("parsing a statement, stmt_id=%ld, temp_at_entry=%ld, labels_len_at_entry=%ld, "
63847 	                     "is_strict=%ld, in_directive_prologue=%ld, catch_depth=%ld",
63848 	                     (long) stmt_id, (long) temp_at_entry, (long) labels_len_at_entry,
63849 	                     (long) comp_ctx->curr_func.is_strict, (long) comp_ctx->curr_func.in_directive_prologue,
63850 	                     (long) comp_ctx->curr_func.catch_depth));
63851 
63852 	/* The directive prologue flag is cleared by default so that it is
63853 	 * unset for any recursive statement parsing.  It is only "revived"
63854 	 * if a directive is detected.  (We could also make directives only
63855 	 * allowed if 'allow_source_elem' was true.)
63856 	 */
63857 	comp_ctx->curr_func.in_directive_prologue = 0;
63858 
63859  retry_parse:
63860 
63861 	DUK_DDD(DUK_DDDPRINT("try stmt parse, stmt_id=%ld, label_id=%ld, allow_source_elem=%ld, catch_depth=%ld",
63862 	                     (long) stmt_id, (long) label_id, (long) allow_source_elem,
63863 	                     (long) comp_ctx->curr_func.catch_depth));
63864 
63865 	/*
63866 	 *  Detect iteration statements; if encountered, establish an
63867 	 *  empty label.
63868 	 */
63869 
63870 	tok = comp_ctx->curr_token.t;
63871 	if (tok == DUK_TOK_FOR || tok == DUK_TOK_DO || tok == DUK_TOK_WHILE ||
63872 	    tok == DUK_TOK_SWITCH) {
63873 		DUK_DDD(DUK_DDDPRINT("iteration/switch statement -> add empty label"));
63874 
63875 		label_id = duk__stmt_label_site(comp_ctx, label_id);
63876 		duk__add_label(comp_ctx,
63877 		               DUK_HTHREAD_STRING_EMPTY_STRING(thr),
63878 		               pc_at_entry /*pc_label*/,
63879 		               label_id);
63880 	}
63881 
63882 	/*
63883 	 *  Main switch for statement / source element type.
63884 	 */
63885 
63886 	switch (comp_ctx->curr_token.t) {
63887 	case DUK_TOK_FUNCTION: {
63888 		/*
63889 		 *  Function declaration, function expression, or (non-standard)
63890 		 *  function statement.
63891 		 *
63892 		 *  The E5 specification only allows function declarations at
63893 		 *  the top level (in "source elements").  An ExpressionStatement
63894 		 *  is explicitly not allowed to begin with a "function" keyword
63895 		 *  (E5 Section 12.4).  Hence any non-error semantics for such
63896 		 *  non-top-level statements are non-standard.  Duktape semantics
63897 		 *  for function statements are modelled after V8, see
63898 		 *  test-dev-func-decl-outside-top.js.
63899 		 */
63900 
63901 #if defined(DUK_USE_NONSTD_FUNC_STMT)
63902 		/* Lenient: allow function declarations outside top level in
63903 		 * non-strict mode but reject them in strict mode.
63904 		 */
63905 		if (allow_source_elem || !comp_ctx->curr_func.is_strict)
63906 #else  /* DUK_USE_NONSTD_FUNC_STMT */
63907 		/* Strict: never allow function declarations outside top level. */
63908 		if (allow_source_elem)
63909 #endif  /* DUK_USE_NONSTD_FUNC_STMT */
63910 		{
63911 			/* FunctionDeclaration: not strictly a statement but handled as such.
63912 			 *
63913 			 * O(depth^2) parse count for inner functions is handled by recording a
63914 			 * lexer offset on the first compilation pass, so that the function can
63915 			 * be efficiently skipped on the second pass.  This is encapsulated into
63916 			 * duk__parse_func_like_fnum().
63917 			 */
63918 
63919 			duk_int_t fnum;
63920 
63921 			DUK_DDD(DUK_DDDPRINT("function declaration statement"));
63922 
63923 			duk__advance(comp_ctx);  /* eat 'function' */
63924 			fnum = duk__parse_func_like_fnum(comp_ctx, 1 /*is_decl*/, 0 /*is_setget*/);
63925 
63926 			if (comp_ctx->curr_func.in_scanning) {
63927 				duk_uarridx_t n;
63928 				duk_hstring *h_funcname;
63929 
63930 				duk_get_prop_index(ctx, comp_ctx->curr_func.funcs_idx, fnum * 3);
63931 				duk_get_prop_stridx(ctx, -1, DUK_STRIDX_NAME);  /* -> [ ... func name ] */
63932 				h_funcname = duk_get_hstring(ctx, -1);
63933 				DUK_ASSERT(h_funcname != NULL);
63934 
63935 				DUK_DDD(DUK_DDDPRINT("register function declaration %!O in pass 1, fnum %ld",
63936 				                     (duk_heaphdr *) h_funcname, (long) fnum));
63937 				n = (duk_uarridx_t) duk_get_length(ctx, comp_ctx->curr_func.decls_idx);
63938 				duk_push_hstring(ctx, h_funcname);
63939 				duk_put_prop_index(ctx, comp_ctx->curr_func.decls_idx, n);
63940 				duk_push_int(ctx, (duk_int_t) (DUK_DECL_TYPE_FUNC + (fnum << 8)));
63941 				duk_put_prop_index(ctx, comp_ctx->curr_func.decls_idx, n + 1);
63942 
63943 				duk_pop_n(ctx, 2);
63944 			}
63945 
63946 			/* no statement value (unlike function expression) */
63947 			stmt_flags = 0;
63948 			break;
63949 		} else {
63950 			DUK_ERROR_SYNTAX(thr, DUK_STR_FUNC_STMT_NOT_ALLOWED);
63951 		}
63952 		break;
63953 	}
63954 	case DUK_TOK_LCURLY: {
63955 		DUK_DDD(DUK_DDDPRINT("block statement"));
63956 		duk__advance(comp_ctx);
63957 		duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/);
63958 		/* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */
63959 		if (label_id >= 0) {
63960 			duk__patch_jump_here(comp_ctx, pc_at_entry + 1);  /* break jump */
63961 		}
63962 		stmt_flags = 0;
63963 		break;
63964 	}
63965 	case DUK_TOK_CONST: {
63966 		DUK_DDD(DUK_DDDPRINT("constant declaration statement"));
63967 		duk__parse_var_stmt(comp_ctx, res, DUK__EXPR_FLAG_REQUIRE_INIT /*expr_flags*/);
63968 		stmt_flags = DUK__HAS_TERM;
63969 		break;
63970 	}
63971 	case DUK_TOK_VAR: {
63972 		DUK_DDD(DUK_DDDPRINT("variable declaration statement"));
63973 		duk__parse_var_stmt(comp_ctx, res, 0 /*expr_flags*/);
63974 		stmt_flags = DUK__HAS_TERM;
63975 		break;
63976 	}
63977 	case DUK_TOK_SEMICOLON: {
63978 		/* empty statement with an explicit semicolon */
63979 		DUK_DDD(DUK_DDDPRINT("empty statement"));
63980 		stmt_flags = DUK__HAS_TERM;
63981 		break;
63982 	}
63983 	case DUK_TOK_IF: {
63984 		DUK_DDD(DUK_DDDPRINT("if statement"));
63985 		duk__parse_if_stmt(comp_ctx, res);
63986 		if (label_id >= 0) {
63987 			duk__patch_jump_here(comp_ctx, pc_at_entry + 1);  /* break jump */
63988 		}
63989 		stmt_flags = 0;
63990 		break;
63991 	}
63992 	case DUK_TOK_DO: {
63993 		/*
63994 		 *  Do-while statement is mostly trivial, but there is special
63995 		 *  handling for automatic semicolon handling (triggered by the
63996 		 *  DUK__ALLOW_AUTO_SEMI_ALWAYS) flag related to a bug filed at:
63997 		 *
63998 		 *    https://bugs.ecmascript.org/show_bug.cgi?id=8
63999 		 *
64000 		 *  See doc/compiler.rst for details.
64001 		 */
64002 		DUK_DDD(DUK_DDDPRINT("do statement"));
64003 		DUK_ASSERT(label_id >= 0);
64004 		duk__update_label_flags(comp_ctx,
64005 		                        label_id,
64006 		                        DUK_LABEL_FLAG_ALLOW_BREAK | DUK_LABEL_FLAG_ALLOW_CONTINUE);
64007 		duk__parse_do_stmt(comp_ctx, res, pc_at_entry);
64008 		stmt_flags = DUK__HAS_TERM | DUK__ALLOW_AUTO_SEMI_ALWAYS;  /* DUK__ALLOW_AUTO_SEMI_ALWAYS workaround */
64009 		break;
64010 	}
64011 	case DUK_TOK_WHILE: {
64012 		DUK_DDD(DUK_DDDPRINT("while statement"));
64013 		DUK_ASSERT(label_id >= 0);
64014 		duk__update_label_flags(comp_ctx,
64015 		                        label_id,
64016 		                        DUK_LABEL_FLAG_ALLOW_BREAK | DUK_LABEL_FLAG_ALLOW_CONTINUE);
64017 		duk__parse_while_stmt(comp_ctx, res, pc_at_entry);
64018 		stmt_flags = 0;
64019 		break;
64020 	}
64021 	case DUK_TOK_FOR: {
64022 		/*
64023 		 *  For/for-in statement is complicated to parse because
64024 		 *  determining the statement type (three-part for vs. a
64025 		 *  for-in) requires potential backtracking.
64026 		 *
64027 		 *  See the helper for the messy stuff.
64028 		 */
64029 		DUK_DDD(DUK_DDDPRINT("for/for-in statement"));
64030 		DUK_ASSERT(label_id >= 0);
64031 		duk__update_label_flags(comp_ctx,
64032 		                        label_id,
64033 		                        DUK_LABEL_FLAG_ALLOW_BREAK | DUK_LABEL_FLAG_ALLOW_CONTINUE);
64034 		duk__parse_for_stmt(comp_ctx, res, pc_at_entry);
64035 		stmt_flags = 0;
64036 		break;
64037 	}
64038 	case DUK_TOK_CONTINUE:
64039 	case DUK_TOK_BREAK: {
64040 		DUK_DDD(DUK_DDDPRINT("break/continue statement"));
64041 		duk__parse_break_or_continue_stmt(comp_ctx, res);
64042 		stmt_flags = DUK__HAS_TERM | DUK__IS_TERMINAL;
64043 		break;
64044 	}
64045 	case DUK_TOK_RETURN: {
64046 		DUK_DDD(DUK_DDDPRINT("return statement"));
64047 		duk__parse_return_stmt(comp_ctx, res);
64048 		stmt_flags = DUK__HAS_TERM | DUK__IS_TERMINAL;
64049 		break;
64050 	}
64051 	case DUK_TOK_WITH: {
64052 		DUK_DDD(DUK_DDDPRINT("with statement"));
64053 		comp_ctx->curr_func.with_depth++;
64054 		duk__parse_with_stmt(comp_ctx, res);
64055 		if (label_id >= 0) {
64056 			duk__patch_jump_here(comp_ctx, pc_at_entry + 1);  /* break jump */
64057 		}
64058 		comp_ctx->curr_func.with_depth--;
64059 		stmt_flags = 0;
64060 		break;
64061 	}
64062 	case DUK_TOK_SWITCH: {
64063 		/*
64064 		 *  The switch statement is pretty messy to compile.
64065 		 *  See the helper for details.
64066 		 */
64067 		DUK_DDD(DUK_DDDPRINT("switch statement"));
64068 		DUK_ASSERT(label_id >= 0);
64069 		duk__update_label_flags(comp_ctx,
64070 		                        label_id,
64071 		                        DUK_LABEL_FLAG_ALLOW_BREAK);  /* don't allow continue */
64072 		duk__parse_switch_stmt(comp_ctx, res, pc_at_entry);
64073 		stmt_flags = 0;
64074 		break;
64075 	}
64076 	case DUK_TOK_THROW: {
64077 		DUK_DDD(DUK_DDDPRINT("throw statement"));
64078 		duk__parse_throw_stmt(comp_ctx, res);
64079 		stmt_flags = DUK__HAS_TERM | DUK__IS_TERMINAL;
64080 		break;
64081 	}
64082 	case DUK_TOK_TRY: {
64083 		DUK_DDD(DUK_DDDPRINT("try statement"));
64084 		duk__parse_try_stmt(comp_ctx, res);
64085 		stmt_flags = 0;
64086 		break;
64087 	}
64088 	case DUK_TOK_DEBUGGER: {
64089 		duk__advance(comp_ctx);
64090 #if defined(DUK_USE_DEBUGGER_SUPPORT)
64091 		DUK_DDD(DUK_DDDPRINT("debugger statement: debugging enabled, emit debugger opcode"));
64092 		duk__emit_extraop_only(comp_ctx, DUK_EXTRAOP_DEBUGGER);
64093 #else
64094 		DUK_DDD(DUK_DDDPRINT("debugger statement: ignored"));
64095 #endif
64096 		stmt_flags = DUK__HAS_TERM;
64097 		break;
64098 	}
64099 	default: {
64100 		/*
64101 		 *  Else, must be one of:
64102 		 *    - ExpressionStatement, possibly a directive (String)
64103 		 *    - LabelledStatement (Identifier followed by ':')
64104 		 *
64105 		 *  Expressions beginning with 'function' keyword are covered by a case
64106 		 *  above (such expressions are not allowed in standard E5 anyway).
64107 		 *  Also expressions starting with '{' are interpreted as block
64108 		 *  statements.  See E5 Section 12.4.
64109 		 *
64110 		 *  Directive detection is tricky; see E5 Section 14.1 on directive
64111 		 *  prologue.  A directive is an expression statement with a single
64112 		 *  string literal and an explicit or automatic semicolon.  Escape
64113 		 *  characters are significant and no parens etc are allowed:
64114 		 *
64115 		 *    'use strict';          // valid 'use strict' directive
64116 		 *    'use\u0020strict';     // valid directive, not a 'use strict' directive
64117 		 *    ('use strict');        // not a valid directive
64118 		 *
64119 		 *  The expression is determined to consist of a single string literal
64120 		 *  based on duk__expr_nud() and duk__expr_led() call counts.  The string literal
64121 		 *  of a 'use strict' directive is determined to lack any escapes based
64122 		 *  num_escapes count from the lexer.  Note that other directives may be
64123 		 *  allowed to contain escapes, so a directive with escapes does not
64124 		 *  terminate a directive prologue.
64125 		 *
64126 		 *  We rely on the fact that the expression parser will not emit any
64127 		 *  code for a single token expression.  However, it will generate an
64128 		 *  intermediate value which we will then successfully ignore.
64129 		 *
64130 		 *  A similar approach is used for labels.
64131 		 */
64132 
64133 		duk_bool_t single_token;
64134 
64135 		DUK_DDD(DUK_DDDPRINT("expression statement"));
64136 		duk__exprtop(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
64137 
64138 		single_token = (comp_ctx->curr_func.nud_count == 1 &&  /* one token */
64139 		                comp_ctx->curr_func.led_count == 0);   /* no operators */
64140 
64141 		if (single_token &&
64142 		    comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER &&
64143 		    comp_ctx->curr_token.t == DUK_TOK_COLON) {
64144 			/*
64145 			 *  Detected label
64146 			 */
64147 
64148 			duk_hstring *h_lab;
64149 
64150 			/* expected ival */
64151 			DUK_ASSERT(res->t == DUK_IVAL_VAR);
64152 			DUK_ASSERT(res->x1.t == DUK_ISPEC_VALUE);
64153 			DUK_ASSERT(DUK_TVAL_IS_STRING(duk_get_tval(ctx, res->x1.valstack_idx)));
64154 			h_lab = comp_ctx->prev_token.str1;
64155 			DUK_ASSERT(h_lab != NULL);
64156 
64157 			DUK_DDD(DUK_DDDPRINT("explicit label site for label '%!O'",
64158 			                     (duk_heaphdr *) h_lab));
64159 
64160 			duk__advance(comp_ctx);  /* eat colon */
64161 
64162 			label_id = duk__stmt_label_site(comp_ctx, label_id);
64163 
64164 			duk__add_label(comp_ctx,
64165 			               h_lab,
64166 			               pc_at_entry /*pc_label*/,
64167 			               label_id);
64168 
64169 			/* a statement following a label cannot be a source element
64170 			 * (a function declaration).
64171 			 */
64172 			allow_source_elem = 0;
64173 
64174 			DUK_DDD(DUK_DDDPRINT("label handled, retry statement parsing"));
64175 			goto retry_parse;
64176 		}
64177 
64178 		stmt_flags = 0;
64179 
64180 		if (dir_prol_at_entry &&                           /* still in prologue */
64181 		    single_token &&                                /* single string token */
64182 		    comp_ctx->prev_token.t == DUK_TOK_STRING) {
64183 			/*
64184 			 *  Detected a directive
64185 			 */
64186 			duk_hstring *h_dir;
64187 
64188 			/* expected ival */
64189 			DUK_ASSERT(res->t == DUK_IVAL_PLAIN);
64190 			DUK_ASSERT(res->x1.t == DUK_ISPEC_VALUE);
64191 			DUK_ASSERT(DUK_TVAL_IS_STRING(duk_get_tval(ctx, res->x1.valstack_idx)));
64192 			h_dir = comp_ctx->prev_token.str1;
64193 			DUK_ASSERT(h_dir != NULL);
64194 
64195 			DUK_DDD(DUK_DDDPRINT("potential directive: %!O", h_dir));
64196 
64197 			stmt_flags |= DUK__STILL_PROLOGUE;
64198 
64199 			/* Note: escaped characters differentiate directives */
64200 
64201 			if (comp_ctx->prev_token.num_escapes > 0) {
64202 				DUK_DDD(DUK_DDDPRINT("directive contains escapes: valid directive "
64203 				                     "but we ignore such directives"));
64204 			} else {
64205 				/*
64206 				 * The length comparisons are present to handle
64207 				 * strings like "use strict\u0000foo" as required.
64208 				 */
64209 
64210 				if (DUK_HSTRING_GET_BYTELEN(h_dir) == 10 &&
64211 				    DUK_STRNCMP((const char *) DUK_HSTRING_GET_DATA(h_dir), "use strict", 10) == 0) {
64212 #if defined(DUK_USE_STRICT_DECL)
64213 					DUK_DDD(DUK_DDDPRINT("use strict directive detected: strict flag %ld -> %ld",
64214 					                     (long) comp_ctx->curr_func.is_strict, (long) 1));
64215 					comp_ctx->curr_func.is_strict = 1;
64216 #else
64217 					DUK_DDD(DUK_DDDPRINT("use strict detected but strict declarations disabled, ignoring"));
64218 #endif
64219 				} else if (DUK_HSTRING_GET_BYTELEN(h_dir) == 14 &&
64220 				           DUK_STRNCMP((const char *) DUK_HSTRING_GET_DATA(h_dir), "use duk notail", 14) == 0) {
64221 					DUK_DDD(DUK_DDDPRINT("use duk notail directive detected: notail flag %ld -> %ld",
64222 					                     (long) comp_ctx->curr_func.is_notail, (long) 1));
64223 					comp_ctx->curr_func.is_notail = 1;
64224 				} else {
64225 					DUK_DD(DUK_DDPRINT("unknown directive: '%!O', ignoring but not terminating "
64226 					                   "directive prologue", (duk_hobject *) h_dir));
64227 				}
64228 			}
64229 		} else {
64230 			DUK_DDD(DUK_DDDPRINT("non-directive expression statement or no longer in prologue; "
64231 			                     "prologue terminated if still active"));
64232                 }
64233 
64234 		stmt_flags |= DUK__HAS_VAL | DUK__HAS_TERM;
64235 	}
64236 	}  /* end switch (tok) */
64237 
64238 	/*
64239 	 *  Statement value handling.
64240 	 *
64241 	 *  Global code and eval code has an implicit return value
64242 	 *  which comes from the last statement with a value
64243 	 *  (technically a non-"empty" continuation, which is
64244 	 *  different from an empty statement).
64245 	 *
64246 	 *  Since we don't know whether a later statement will
64247 	 *  override the value of the current statement, we need
64248 	 *  to coerce the statement value to a register allocated
64249 	 *  for implicit return values.  In other cases we need
64250 	 *  to coerce the statement value to a plain value to get
64251 	 *  any side effects out (consider e.g. "foo.bar;").
64252 	 */
64253 
64254 	/* XXX: what about statements which leave a half-cooked value in 'res'
64255 	 * but have no stmt value?  Any such statements?
64256 	 */
64257 
64258 	if (stmt_flags & DUK__HAS_VAL) {
64259 		duk_reg_t reg_stmt_value = comp_ctx->curr_func.reg_stmt_value;
64260 		if (reg_stmt_value >= 0) {
64261 			duk__ivalue_toforcedreg(comp_ctx, res, reg_stmt_value);
64262 		} else {
64263 			duk__ivalue_toplain_ignore(comp_ctx, res);
64264 		}
64265 	} else {
64266 		;
64267 	}
64268 
64269 	/*
64270 	 *  Statement terminator check, including automatic semicolon
64271 	 *  handling.  After this step, 'curr_tok' should be the first
64272 	 *  token after a possible statement terminator.
64273 	 */
64274 
64275 	if (stmt_flags & DUK__HAS_TERM) {
64276 		if (comp_ctx->curr_token.t == DUK_TOK_SEMICOLON) {
64277 			DUK_DDD(DUK_DDDPRINT("explicit semicolon terminates statement"));
64278 			duk__advance(comp_ctx);
64279 		} else {
64280 			if (comp_ctx->curr_token.allow_auto_semi) {
64281 				DUK_DDD(DUK_DDDPRINT("automatic semicolon terminates statement"));
64282 			} else if (stmt_flags & DUK__ALLOW_AUTO_SEMI_ALWAYS) {
64283 				/* XXX: make this lenience dependent on flags or strictness? */
64284 				DUK_DDD(DUK_DDDPRINT("automatic semicolon terminates statement (allowed for compatibility "
64285 				                     "even though no lineterm present before next token)"));
64286 			} else {
64287 				DUK_ERROR_SYNTAX(thr, DUK_STR_UNTERMINATED_STMT);
64288 			}
64289 		}
64290 	} else {
64291 		DUK_DDD(DUK_DDDPRINT("statement has no terminator"));
64292 	}
64293 
64294 	/*
64295 	 *  Directive prologue tracking.
64296 	 */
64297 
64298 	if (stmt_flags & DUK__STILL_PROLOGUE) {
64299 		DUK_DDD(DUK_DDDPRINT("setting in_directive_prologue"));
64300 		comp_ctx->curr_func.in_directive_prologue = 1;
64301 	}
64302 
64303 	/*
64304 	 *  Cleanups (all statement parsing flows through here).
64305 	 *
64306 	 *  Pop label site and reset labels.  Reset 'next temp' to value at
64307 	 *  entry to reuse temps.
64308 	 */
64309 
64310 	if (label_id >= 0) {
64311 		duk__emit_extraop_bc(comp_ctx,
64312 		                     DUK_EXTRAOP_ENDLABEL,
64313 		                     (duk_regconst_t) label_id);
64314 	}
64315 
64316 	DUK__SETTEMP(comp_ctx, temp_at_entry);
64317 
64318 	duk__reset_labels_to_length(comp_ctx, labels_len_at_entry);
64319 
64320 	/* XXX: return indication of "terminalness" (e.g. a 'throw' is terminal) */
64321 
64322 	DUK__RECURSION_DECREASE(comp_ctx, thr);
64323 }
64324 
64325 #undef DUK__HAS_VAL
64326 #undef DUK__HAS_TERM
64327 #undef DUK__ALLOW_AUTO_SEMI_ALWAYS
64328 
64329 /*
64330  *  Parse a statement list.
64331  *
64332  *  Handles automatic semicolon insertion and implicit return value.
64333  *
64334  *  Upon entry, 'curr_tok' should contain the first token of the first
64335  *  statement (parsed in the "allow regexp literal" mode).  Upon exit,
64336  *  'curr_tok' contains the token following the statement list terminator
64337  *  (EOF or closing brace).
64338  */
64339 
64340 DUK_LOCAL void duk__parse_stmts(duk_compiler_ctx *comp_ctx, duk_bool_t allow_source_elem, duk_bool_t expect_eof) {
64341 	duk_hthread *thr = comp_ctx->thr;
64342 	duk_context *ctx = (duk_context *) thr;
64343 	duk_ivalue res_alloc;
64344 	duk_ivalue *res = &res_alloc;
64345 
64346 	/* Setup state.  Initial ivalue is 'undefined'. */
64347 
64348 	duk_require_stack(ctx, DUK__PARSE_STATEMENTS_SLOTS);
64349 
64350 	/* XXX: 'res' setup can be moved to function body level; in fact, two 'res'
64351 	 * intermediate values suffice for parsing of each function.  Nesting is needed
64352 	 * for nested functions (which may occur inside expressions).
64353 	 */
64354 
64355 	DUK_MEMZERO(&res_alloc, sizeof(res_alloc));
64356 	res->t = DUK_IVAL_PLAIN;
64357 	res->x1.t = DUK_ISPEC_VALUE;
64358 	res->x1.valstack_idx = duk_get_top(ctx);
64359 	res->x2.valstack_idx = res->x1.valstack_idx + 1;
64360 	duk_push_undefined(ctx);
64361 	duk_push_undefined(ctx);
64362 
64363 	/* Parse statements until a closing token (EOF or '}') is found. */
64364 
64365 	for (;;) {
64366 		/* Check whether statement list ends. */
64367 
64368 		if (expect_eof) {
64369 			if (comp_ctx->curr_token.t == DUK_TOK_EOF) {
64370 				break;
64371 			}
64372 		} else {
64373 			if (comp_ctx->curr_token.t == DUK_TOK_RCURLY) {
64374 				break;
64375 			}
64376 		}
64377 
64378 		/* Check statement type based on the first token type.
64379 		 *
64380 		 * Note: expression parsing helpers expect 'curr_tok' to
64381 		 * contain the first token of the expression upon entry.
64382 		 */
64383 
64384 		DUK_DDD(DUK_DDDPRINT("TOKEN %ld (non-whitespace, non-comment)", (long) comp_ctx->curr_token.t));
64385 
64386 		duk__parse_stmt(comp_ctx, res, allow_source_elem);
64387 	}
64388 
64389 	duk__advance(comp_ctx);
64390 
64391 	/* Tear down state. */
64392 
64393 	duk_pop_2(ctx);
64394 }
64395 
64396 /*
64397  *  Declaration binding instantiation conceptually happens when calling a
64398  *  function; for us it essentially means that function prologue.  The
64399  *  conceptual process is described in E5 Section 10.5.
64400  *
64401  *  We need to keep track of all encountered identifiers to (1) create an
64402  *  identifier-to-register map ("varmap"); and (2) detect duplicate
64403  *  declarations.  Identifiers which are not bound to registers still need
64404  *  to be tracked for detecting duplicates.  Currently such identifiers
64405  *  are put into the varmap with a 'null' value, which is later cleaned up.
64406  *
64407  *  To support functions with a large number of variable and function
64408  *  declarations, registers are not allocated beyond a certain limit;
64409  *  after that limit, variables and functions need slow path access.
64410  *  Arguments are currently always register bound, which imposes a hard
64411  *  (and relatively small) argument count limit.
64412  *
64413  *  Some bindings in E5 are not configurable (= deletable) and almost all
64414  *  are mutable (writable).  Exceptions are:
64415  *
64416  *    - The 'arguments' binding, established only if no shadowing argument
64417  *      or function declaration exists.  We handle 'arguments' creation
64418  *      and binding through an explicit slow path environment record.
64419  *
64420  *    - The "name" binding for a named function expression.  This is also
64421  *      handled through an explicit slow path environment record.
64422  */
64423 
64424 /* XXX: add support for variables to not be register bound always, to
64425  * handle cases with a very large number of variables?
64426  */
64427 
64428 DUK_LOCAL void duk__init_varmap_and_prologue_for_pass2(duk_compiler_ctx *comp_ctx, duk_reg_t *out_stmt_value_reg) {
64429 	duk_hthread *thr = comp_ctx->thr;
64430 	duk_context *ctx = (duk_context *) thr;
64431 	duk_hstring *h_name;
64432 	duk_bool_t configurable_bindings;
64433 	duk_uarridx_t num_args;
64434 	duk_uarridx_t num_decls;
64435 	duk_regconst_t rc_name;
64436 	duk_small_uint_t declvar_flags;
64437 	duk_uarridx_t i;
64438 #ifdef DUK_USE_ASSERTIONS
64439 	duk_idx_t entry_top;
64440 #endif
64441 
64442 #ifdef DUK_USE_ASSERTIONS
64443 	entry_top = duk_get_top(ctx);
64444 #endif
64445 
64446 	/*
64447 	 *  Preliminaries
64448 	 */
64449 
64450 	configurable_bindings = comp_ctx->curr_func.is_eval;
64451 	DUK_DDD(DUK_DDDPRINT("configurable_bindings=%ld", (long) configurable_bindings));
64452 
64453 	/* varmap is already in comp_ctx->curr_func.varmap_idx */
64454 
64455 	/*
64456 	 *  Function formal arguments, always bound to registers
64457 	 *  (there's no support for shuffling them now).
64458 	 */
64459 
64460 	num_args = (duk_uarridx_t) duk_get_length(ctx, comp_ctx->curr_func.argnames_idx);
64461 	DUK_DDD(DUK_DDDPRINT("num_args=%ld", (long) num_args));
64462 	/* XXX: check num_args */
64463 
64464 	for (i = 0; i < num_args; i++) {
64465 		duk_get_prop_index(ctx, comp_ctx->curr_func.argnames_idx, i);
64466 		h_name = duk_get_hstring(ctx, -1);
64467 		DUK_ASSERT(h_name != NULL);
64468 
64469 		if (comp_ctx->curr_func.is_strict) {
64470 			if (duk__hstring_is_eval_or_arguments(comp_ctx, h_name)) {
64471 				DUK_DDD(DUK_DDDPRINT("arg named 'eval' or 'arguments' in strict mode -> SyntaxError"));
64472 				goto error_argname;
64473 			}
64474 			duk_dup_top(ctx);
64475 			if (duk_has_prop(ctx, comp_ctx->curr_func.varmap_idx)) {
64476 				DUK_DDD(DUK_DDDPRINT("duplicate arg name in strict mode -> SyntaxError"));
64477 				goto error_argname;
64478 			}
64479 
64480 			/* Ensure argument name is not a reserved word in current
64481 			 * (final) strictness.  Formal argument parsing may not
64482 			 * catch reserved names if strictness changes during
64483 			 * parsing.
64484 			 *
64485 			 * We only need to do this in strict mode because non-strict
64486 			 * keyword are always detected in formal argument parsing.
64487 			 */
64488 
64489 			if (DUK_HSTRING_HAS_STRICT_RESERVED_WORD(h_name)) {
64490 				goto error_argname;
64491 			}
64492 		}
64493 
64494 		/* overwrite any previous binding of the same name; the effect is
64495 		 * that last argument of a certain name wins.
64496 		 */
64497 
64498 		/* only functions can have arguments */
64499 		DUK_ASSERT(comp_ctx->curr_func.is_function);
64500 		duk_push_uarridx(ctx, i);  /* -> [ ... name index ] */
64501 		duk_put_prop(ctx, comp_ctx->curr_func.varmap_idx); /* -> [ ... ] */
64502 
64503 		/* no code needs to be emitted, the regs already have values */
64504 	}
64505 
64506 	/* use temp_next for tracking register allocations */
64507 	DUK__SETTEMP_CHECKMAX(comp_ctx, (duk_reg_t) num_args);
64508 
64509 	/*
64510 	 *  After arguments, allocate special registers (like shuffling temps)
64511 	 */
64512 
64513 	if (out_stmt_value_reg) {
64514 		*out_stmt_value_reg = DUK__ALLOCTEMP(comp_ctx);
64515 	}
64516 	if (comp_ctx->curr_func.needs_shuffle) {
64517 		duk_reg_t shuffle_base = DUK__ALLOCTEMPS(comp_ctx, 3);
64518 		comp_ctx->curr_func.shuffle1 = shuffle_base;
64519 		comp_ctx->curr_func.shuffle2 = shuffle_base + 1;
64520 		comp_ctx->curr_func.shuffle3 = shuffle_base + 2;
64521 		DUK_D(DUK_DPRINT("shuffle registers needed by function, allocated: %ld %ld %ld",
64522 		                 (long) comp_ctx->curr_func.shuffle1,
64523 		                 (long) comp_ctx->curr_func.shuffle2,
64524 		                 (long) comp_ctx->curr_func.shuffle3));
64525 	}
64526 	if (comp_ctx->curr_func.temp_next > 0x100) {
64527 		DUK_D(DUK_DPRINT("not enough 8-bit regs: temp_next=%ld", (long) comp_ctx->curr_func.temp_next));
64528 		goto error_outofregs;
64529 	}
64530 
64531 	/*
64532 	 *  Function declarations
64533 	 */
64534 
64535 	num_decls = (duk_uarridx_t) duk_get_length(ctx, comp_ctx->curr_func.decls_idx);
64536 	DUK_DDD(DUK_DDDPRINT("num_decls=%ld -> %!T",
64537 	                     (long) num_decls,
64538 	                     (duk_tval *) duk_get_tval(ctx, comp_ctx->curr_func.decls_idx)));
64539 	for (i = 0; i < num_decls; i += 2) {
64540 		duk_int_t decl_type;
64541 		duk_int_t fnum;
64542 
64543 		duk_get_prop_index(ctx, comp_ctx->curr_func.decls_idx, i + 1);  /* decl type */
64544 		decl_type = duk_to_int(ctx, -1);
64545 		fnum = decl_type >> 8;  /* XXX: macros */
64546 		decl_type = decl_type & 0xff;
64547 		duk_pop(ctx);
64548 
64549 		if (decl_type != DUK_DECL_TYPE_FUNC) {
64550 			continue;
64551 		}
64552 
64553 		duk_get_prop_index(ctx, comp_ctx->curr_func.decls_idx, i);  /* decl name */
64554 
64555 		/* XXX: spilling */
64556 		if (comp_ctx->curr_func.is_function) {
64557 			duk_reg_t reg_bind;
64558 			duk_dup_top(ctx);
64559 			if (duk_has_prop(ctx, comp_ctx->curr_func.varmap_idx)) {
64560 				/* shadowed; update value */
64561 				duk_dup_top(ctx);
64562 				duk_get_prop(ctx, comp_ctx->curr_func.varmap_idx);
64563 				reg_bind = duk_to_int(ctx, -1);  /* [ ... name reg_bind ] */
64564 				duk__emit_a_bc(comp_ctx,
64565 				               DUK_OP_CLOSURE,
64566 				               (duk_regconst_t) reg_bind,
64567 				               (duk_regconst_t) fnum);
64568 			} else {
64569 				/* function: always register bound */
64570 				reg_bind = DUK__ALLOCTEMP(comp_ctx);
64571 				duk__emit_a_bc(comp_ctx,
64572 				               DUK_OP_CLOSURE,
64573 				               (duk_regconst_t) reg_bind,
64574 				               (duk_regconst_t) fnum);
64575 				duk_push_int(ctx, (duk_int_t) reg_bind);
64576 			}
64577 		} else {
64578 			/* Function declaration for global/eval code is emitted even
64579 			 * for duplicates, because of E5 Section 10.5, step 5.e of
64580 			 * E5.1 (special behavior for variable bound to global object).
64581 			 *
64582 			 * DECLVAR will not re-declare a variable as such, but will
64583 			 * update the binding value.
64584 			 */
64585 
64586 			duk_reg_t reg_temp = DUK__ALLOCTEMP(comp_ctx);
64587 			duk_dup_top(ctx);
64588 			rc_name = duk__getconst(comp_ctx);
64589 			duk_push_null(ctx);
64590 
64591 			duk__emit_a_bc(comp_ctx,
64592 			               DUK_OP_CLOSURE,
64593 			               (duk_regconst_t) reg_temp,
64594 			               (duk_regconst_t) fnum);
64595 
64596 			declvar_flags = DUK_PROPDESC_FLAG_WRITABLE |
64597 			                DUK_PROPDESC_FLAG_ENUMERABLE |
64598 			                DUK_BC_DECLVAR_FLAG_FUNC_DECL;
64599 
64600 			if (configurable_bindings) {
64601 				declvar_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;
64602 			}
64603 
64604 			duk__emit_a_b_c(comp_ctx,
64605 			                DUK_OP_DECLVAR | DUK__EMIT_FLAG_NO_SHUFFLE_A,
64606 			                (duk_regconst_t) declvar_flags /*flags*/,
64607 			                rc_name /*name*/,
64608 			                (duk_regconst_t) reg_temp /*value*/);
64609 
64610 			DUK__SETTEMP(comp_ctx, reg_temp);  /* forget temp */
64611 		}
64612 
64613 		DUK_DDD(DUK_DDDPRINT("function declaration to varmap: %!T -> %!T",
64614 		                     (duk_tval *) duk_get_tval(ctx, -2),
64615 		                     (duk_tval *) duk_get_tval(ctx, -1)));
64616 
64617 		duk_put_prop(ctx, comp_ctx->curr_func.varmap_idx);  /* [ ... name reg/null ] -> [ ... ] */
64618 	}
64619 
64620 	/*
64621 	 *  'arguments' binding is special; if a shadowing argument or
64622 	 *  function declaration exists, an arguments object will
64623 	 *  definitely not be needed, regardless of whether the identifier
64624 	 *  'arguments' is referenced inside the function body.
64625 	 */
64626 
64627 	if (duk_has_prop_stridx(ctx, comp_ctx->curr_func.varmap_idx, DUK_STRIDX_LC_ARGUMENTS)) {
64628 		DUK_DDD(DUK_DDDPRINT("'arguments' is shadowed by argument or function declaration "
64629 		                     "-> arguments object creation can be skipped"));
64630 		comp_ctx->curr_func.is_arguments_shadowed = 1;
64631 	}
64632 
64633 	/*
64634 	 *  Variable declarations.
64635 	 *
64636 	 *  Unlike function declarations, variable declaration values don't get
64637 	 *  assigned on entry.  If a binding of the same name already exists, just
64638 	 *  ignore it silently.
64639 	 */
64640 
64641 	for (i = 0; i < num_decls; i += 2) {
64642 		duk_int_t decl_type;
64643 
64644 		duk_get_prop_index(ctx, comp_ctx->curr_func.decls_idx, i + 1);  /* decl type */
64645 		decl_type = duk_to_int(ctx, -1);
64646 		decl_type = decl_type & 0xff;
64647 		duk_pop(ctx);
64648 
64649 		if (decl_type != DUK_DECL_TYPE_VAR) {
64650 			continue;
64651 		}
64652 
64653 		duk_get_prop_index(ctx, comp_ctx->curr_func.decls_idx, i);  /* decl name */
64654 
64655 		if (duk_has_prop(ctx, comp_ctx->curr_func.varmap_idx)) {
64656 			/* shadowed, ignore */
64657 		} else {
64658 			duk_get_prop_index(ctx, comp_ctx->curr_func.decls_idx, i);  /* decl name */
64659 			h_name = duk_get_hstring(ctx, -1);
64660 			DUK_ASSERT(h_name != NULL);
64661 
64662 			if (h_name == DUK_HTHREAD_STRING_LC_ARGUMENTS(thr) &&
64663 			    !comp_ctx->curr_func.is_arguments_shadowed) {
64664 				/* E5 Section steps 7-8 */
64665 				DUK_DDD(DUK_DDDPRINT("'arguments' not shadowed by a function declaration, "
64666 				                     "but appears as a variable declaration -> treat as "
64667 				                     "a no-op for variable declaration purposes"));
64668 				duk_pop(ctx);
64669 				continue;
64670 			}
64671 
64672 			/* XXX: spilling */
64673 			if (comp_ctx->curr_func.is_function) {
64674 				duk_reg_t reg_bind = DUK__ALLOCTEMP(comp_ctx);
64675 				/* no need to init reg, it will be undefined on entry */
64676 				duk_push_int(ctx, (duk_int_t) reg_bind);
64677 			} else {
64678 				duk_dup_top(ctx);
64679 				rc_name = duk__getconst(comp_ctx);
64680 				duk_push_null(ctx);
64681 
64682 				declvar_flags = DUK_PROPDESC_FLAG_WRITABLE |
64683 			                        DUK_PROPDESC_FLAG_ENUMERABLE |
64684 				                DUK_BC_DECLVAR_FLAG_UNDEF_VALUE;
64685 				if (configurable_bindings) {
64686 					declvar_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;
64687 				}
64688 
64689 				duk__emit_a_b_c(comp_ctx,
64690 				                DUK_OP_DECLVAR | DUK__EMIT_FLAG_NO_SHUFFLE_A,
64691 				                (duk_regconst_t) declvar_flags /*flags*/,
64692 				                rc_name /*name*/,
64693 				                (duk_regconst_t) 0 /*value*/);
64694 			}
64695 
64696 			duk_put_prop(ctx, comp_ctx->curr_func.varmap_idx);  /* [ ... name reg/null ] -> [ ... ] */
64697 		}
64698 	}
64699 
64700 	/*
64701 	 *  Wrap up
64702 	 */
64703 
64704 	DUK_DDD(DUK_DDDPRINT("varmap: %!T, is_arguments_shadowed=%ld",
64705 	                     (duk_tval *) duk_get_tval(ctx, comp_ctx->curr_func.varmap_idx),
64706 	                     (long) comp_ctx->curr_func.is_arguments_shadowed));
64707 
64708 	DUK_ASSERT_TOP(ctx, entry_top);
64709 	return;
64710 
64711  error_outofregs:
64712 	DUK_ERROR_RANGE(thr, DUK_STR_REG_LIMIT);
64713 	DUK_UNREACHABLE();
64714 	return;
64715 
64716  error_argname:
64717 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_ARG_NAME);
64718 	DUK_UNREACHABLE();
64719 	return;
64720 }
64721 
64722 /*
64723  *  Parse a function-body-like expression (FunctionBody or Program
64724  *  in E5 grammar) using a two-pass parse.  The productions appear
64725  *  in the following contexts:
64726  *
64727  *    - function expression
64728  *    - function statement
64729  *    - function declaration
64730  *    - getter in object literal
64731  *    - setter in object literal
64732  *    - global code
64733  *    - eval code
64734  *    - Function constructor body
64735  *
64736  *  This function only parses the statement list of the body; the argument
64737  *  list and possible function name must be initialized by the caller.
64738  *  For instance, for Function constructor, the argument names are originally
64739  *  on the value stack.  The parsing of statements ends either at an EOF or
64740  *  a closing brace; this is controlled by an input flag.
64741  *
64742  *  Note that there are many differences affecting parsing and even code
64743  *  generation:
64744  *
64745  *    - Global and eval code have an implicit return value generated
64746  *      by the last statement; function code does not
64747  *
64748  *    - Global code, eval code, and Function constructor body end in
64749  *      an EOF, other bodies in a closing brace ('}')
64750  *
64751  *  Upon entry, 'curr_tok' is ignored and the function will pull in the
64752  *  first token on its own.  Upon exit, 'curr_tok' is the terminating
64753  *  token (EOF or closing brace).
64754  */
64755 
64756 DUK_LOCAL void duk__parse_func_body(duk_compiler_ctx *comp_ctx, duk_bool_t expect_eof, duk_bool_t implicit_return_value, duk_small_int_t expect_token) {
64757 	duk_compiler_func *func;
64758 	duk_hthread *thr;
64759 	duk_context *ctx;
64760 	duk_reg_t reg_stmt_value = -1;
64761 	duk_lexer_point lex_pt;
64762 	duk_reg_t temp_first;
64763 	duk_small_int_t compile_round = 1;
64764 
64765 	DUK_ASSERT(comp_ctx != NULL);
64766 
64767 	thr = comp_ctx->thr;
64768 	ctx = (duk_context *) thr;
64769 	DUK_ASSERT(thr != NULL);
64770 
64771 	func = &comp_ctx->curr_func;
64772 	DUK_ASSERT(func != NULL);
64773 
64774 	DUK__RECURSION_INCREASE(comp_ctx, thr);
64775 
64776 	duk_require_stack(ctx, DUK__FUNCTION_BODY_REQUIRE_SLOTS);
64777 
64778 	/*
64779 	 *  Store lexer position for a later rewind
64780 	 */
64781 
64782 	DUK_LEXER_GETPOINT(&comp_ctx->lex, &lex_pt);
64783 
64784 	/*
64785 	 *  Program code (global and eval code) has an implicit return value
64786 	 *  from the last statement value (e.g. eval("1; 2+3;") returns 3).
64787 	 *  This is not the case with functions.  If implicit statement return
64788 	 *  value is requested, all statements are coerced to a register
64789 	 *  allocated here, and used in the implicit return statement below.
64790 	 */
64791 
64792 	/* XXX: this is pointless here because pass 1 is throw-away */
64793 	if (implicit_return_value) {
64794 		reg_stmt_value = DUK__ALLOCTEMP(comp_ctx);
64795 
64796 		/* If an implicit return value is needed by caller, it must be
64797 		 * initialized to 'undefined' because we don't know whether any
64798 		 * non-empty (where "empty" is a continuation type, and different
64799 		 * from an empty statement) statements will be executed.
64800 		 *
64801 		 * However, since 1st pass is a throwaway one, no need to emit
64802 		 * it here.
64803 		 */
64804 #if 0
64805 		duk__emit_extraop_bc(comp_ctx,
64806 		                     DUK_EXTRAOP_LDUNDEF,
64807 		                     0);
64808 #endif
64809 	}
64810 
64811 	/*
64812 	 *  First pass.
64813 	 *
64814 	 *  Gather variable/function declarations needed for second pass.
64815 	 *  Code generated is dummy and discarded.
64816 	 */
64817 
64818 	func->in_directive_prologue = 1;
64819 	func->in_scanning = 1;
64820 	func->may_direct_eval = 0;
64821 	func->id_access_arguments = 0;
64822 	func->id_access_slow = 0;
64823 	func->reg_stmt_value = reg_stmt_value;
64824 #if defined(DUK_USE_DEBUGGER_SUPPORT)
64825 	func->min_line = DUK_INT_MAX;
64826 	func->max_line = 0;
64827 #endif
64828 
64829 	/* duk__parse_stmts() expects curr_tok to be set; parse in "allow regexp literal" mode with current strictness */
64830 	if (expect_token >= 0) {
64831 		/* Eating a left curly; regexp mode is allowed by left curly
64832 		 * based on duk__token_lbp[] automatically.
64833 		 */
64834 		DUK_ASSERT(expect_token == DUK_TOK_LCURLY);
64835 		duk__update_lineinfo_currtoken(comp_ctx);
64836 		duk__advance_expect(comp_ctx, expect_token);
64837 	} else {
64838 		/* Need to set curr_token.t because lexing regexp mode depends on current
64839 		 * token type.  Zero value causes "allow regexp" mode.
64840 		 */
64841 		comp_ctx->curr_token.t = 0;
64842 		duk__advance(comp_ctx);
64843 	}
64844 
64845 	DUK_DDD(DUK_DDDPRINT("begin 1st pass"));
64846 	duk__parse_stmts(comp_ctx,
64847 	                 1,             /* allow source elements */
64848 	                 expect_eof);   /* expect EOF instead of } */
64849 	DUK_DDD(DUK_DDDPRINT("end 1st pass"));
64850 
64851 	/*
64852 	 *  Second (and possibly third) pass.
64853 	 *
64854 	 *  Generate actual code.  In most cases the need for shuffle
64855 	 *  registers is detected during pass 1, but in some corner cases
64856 	 *  we'll only detect it during pass 2 and a third pass is then
64857 	 *  needed (see GH-115).
64858 	 */
64859 
64860 	for (;;) {
64861 		duk_bool_t needs_shuffle_before = comp_ctx->curr_func.needs_shuffle;
64862 		compile_round++;
64863 
64864 		/*
64865 		 *  Rewind lexer.
64866 		 *
64867 		 *  duk__parse_stmts() expects curr_tok to be set; parse in "allow regexp
64868 		 *  literal" mode with current strictness.
64869 		 *
64870 		 *  curr_token line number info should be initialized for pass 2 before
64871 		 *  generating prologue, to ensure prologue bytecode gets nice line numbers.
64872 		 */
64873 
64874 		DUK_DDD(DUK_DDDPRINT("rewind lexer"));
64875 		DUK_LEXER_SETPOINT(&comp_ctx->lex, &lex_pt);
64876 		comp_ctx->curr_token.t = 0;  /* this is needed for regexp mode */
64877 		comp_ctx->curr_token.start_line = 0;  /* needed for line number tracking (becomes prev_token.start_line) */
64878 		duk__advance(comp_ctx);
64879 
64880 		/*
64881 		 *  Reset function state and perform register allocation, which creates
64882 		 *  'varmap' for second pass.  Function prologue for variable declarations,
64883 		 *  binding value initializations etc is emitted as a by-product.
64884 		 *
64885 		 *  Strict mode restrictions for duplicate and invalid argument
64886 		 *  names are checked here now that we know whether the function
64887 		 *  is actually strict.  See: test-dev-strict-mode-boundary.js.
64888 		 *
64889 		 *  Inner functions are compiled during pass 1 and are not reset.
64890 		 */
64891 
64892 		duk__reset_func_for_pass2(comp_ctx);
64893 		func->in_directive_prologue = 1;
64894 		func->in_scanning = 0;
64895 
64896 		/* must be able to emit code, alloc consts, etc. */
64897 
64898 		duk__init_varmap_and_prologue_for_pass2(comp_ctx,
64899 		                                        (implicit_return_value ? &reg_stmt_value : NULL));
64900 		func->reg_stmt_value = reg_stmt_value;
64901 
64902 		temp_first = DUK__GETTEMP(comp_ctx);
64903 
64904 		func->temp_first = temp_first;
64905 		func->temp_next = temp_first;
64906 		func->stmt_next = 0;
64907 		func->label_next = 0;
64908 
64909 		/* XXX: init or assert catch depth etc -- all values */
64910 		func->id_access_arguments = 0;
64911 		func->id_access_slow = 0;
64912 
64913 		/*
64914 		 *  Check function name validity now that we know strictness.
64915 		 *  This only applies to function declarations and expressions,
64916 		 *  not setter/getter name.
64917 		 *
64918 		 *  See: test-dev-strict-mode-boundary.js
64919 		 */
64920 
64921 		if (func->is_function && !func->is_setget && func->h_name != NULL) {
64922 			if (func->is_strict) {
64923 				if (duk__hstring_is_eval_or_arguments(comp_ctx, func->h_name)) {
64924 					DUK_DDD(DUK_DDDPRINT("func name is 'eval' or 'arguments' in strict mode"));
64925 					goto error_funcname;
64926 				}
64927 				if (DUK_HSTRING_HAS_STRICT_RESERVED_WORD(func->h_name)) {
64928 					DUK_DDD(DUK_DDDPRINT("func name is a reserved word in strict mode"));
64929 					goto error_funcname;
64930 				}
64931 			} else {
64932 				if (DUK_HSTRING_HAS_RESERVED_WORD(func->h_name) &&
64933 				    !DUK_HSTRING_HAS_STRICT_RESERVED_WORD(func->h_name)) {
64934 					DUK_DDD(DUK_DDDPRINT("func name is a reserved word in non-strict mode"));
64935 					goto error_funcname;
64936 				}
64937 			}
64938 		}
64939 
64940 		/*
64941 		 *  Second pass parsing.
64942 		 */
64943 
64944 		if (implicit_return_value) {
64945 			/* Default implicit return value. */
64946 			duk__emit_extraop_bc(comp_ctx,
64947 			                     DUK_EXTRAOP_LDUNDEF,
64948 			                     0);
64949 		}
64950 
64951 		DUK_DDD(DUK_DDDPRINT("begin 2nd pass"));
64952 		duk__parse_stmts(comp_ctx,
64953 		                 1,             /* allow source elements */
64954 		                 expect_eof);   /* expect EOF instead of } */
64955 		DUK_DDD(DUK_DDDPRINT("end 2nd pass"));
64956 
64957 		duk__update_lineinfo_currtoken(comp_ctx);
64958 
64959 		if (needs_shuffle_before == comp_ctx->curr_func.needs_shuffle) {
64960 			/* Shuffle decision not changed. */
64961 			break;
64962 		}
64963 		if (compile_round >= 3) {
64964 			/* Should never happen but avoid infinite loop just in case. */
64965 			DUK_D(DUK_DPRINT("more than 3 compile passes needed, should never happen"));
64966 			DUK_ERROR_INTERNAL_DEFMSG(thr);
64967 		}
64968 		DUK_D(DUK_DPRINT("need additional round to compile function, round now %d", (int) compile_round));
64969 	}
64970 
64971 	/*
64972 	 *  Emit a final RETURN.
64973 	 *
64974 	 *  It would be nice to avoid emitting an unnecessary "return" opcode
64975 	 *  if the current PC is not reachable.  However, this cannot be reliably
64976 	 *  detected; even if the previous instruction is an unconditional jump,
64977 	 *  there may be a previous jump which jumps to current PC (which is the
64978 	 *  case for iteration and conditional statements, for instance).
64979 	 */
64980 
64981 	/* XXX: request a "last statement is terminal" from duk__parse_stmt() and duk__parse_stmts();
64982 	 * we could avoid the last RETURN if we could ensure there is no way to get here
64983 	 * (directly or via a jump)
64984 	 */
64985 
64986 	DUK_ASSERT(comp_ctx->curr_func.catch_depth == 0);
64987 	if (reg_stmt_value >= 0) {
64988 		duk__emit_a_b(comp_ctx,
64989 		              DUK_OP_RETURN | DUK__EMIT_FLAG_NO_SHUFFLE_A,
64990 		              (duk_regconst_t) DUK_BC_RETURN_FLAG_HAVE_RETVAL /*flags*/,
64991 		              (duk_regconst_t) reg_stmt_value /*reg*/);
64992 	} else {
64993 		duk__emit_a_b(comp_ctx,
64994 		              DUK_OP_RETURN | DUK__EMIT_FLAG_NO_SHUFFLE_A,
64995 		              (duk_regconst_t) 0 /*flags*/,
64996 		              (duk_regconst_t) 0 /*reg(ignored)*/);
64997 	}
64998 
64999 	/*
65000 	 *  Peephole optimize JUMP chains.
65001 	 */
65002 
65003 	duk__peephole_optimize_bytecode(comp_ctx);
65004 
65005 	/*
65006 	 *  comp_ctx->curr_func is now ready to be converted into an actual
65007 	 *  function template.
65008 	 */
65009 
65010 	DUK__RECURSION_DECREASE(comp_ctx, thr);
65011 	return;
65012 
65013  error_funcname:
65014 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_FUNC_NAME);
65015 }
65016 
65017 /*
65018  *  Parse a function-like expression:
65019  *
65020  *    - function expression
65021  *    - function declaration
65022  *    - function statement (non-standard)
65023  *    - setter/getter
65024  *
65025  *  Adds the function to comp_ctx->curr_func function table and returns the
65026  *  function number.
65027  *
65028  *  On entry, curr_token points to:
65029  *
65030  *    - the token after 'function' for function expression/declaration/statement
65031  *    - the token after 'set' or 'get' for setter/getter
65032  */
65033 
65034 /* Parse formals. */
65035 DUK_LOCAL void duk__parse_func_formals(duk_compiler_ctx *comp_ctx) {
65036 	duk_hthread *thr = comp_ctx->thr;
65037 	duk_context *ctx = (duk_context *) thr;
65038 	duk_bool_t first = 1;
65039 	duk_uarridx_t n;
65040 
65041 	for (;;) {
65042 		if (comp_ctx->curr_token.t == DUK_TOK_RPAREN) {
65043 			break;
65044 		}
65045 
65046 		if (first) {
65047 			/* no comma */
65048 			first = 0;
65049 		} else {
65050 			duk__advance_expect(comp_ctx, DUK_TOK_COMMA);
65051 		}
65052 
65053 		/* Note: when parsing a formal list in non-strict context, e.g.
65054 		 * "implements" is parsed as an identifier.  When the function is
65055 		 * later detected to be strict, the argument list must be rechecked
65056 		 * against a larger set of reserved words (that of strict mode).
65057 		 * This is handled by duk__parse_func_body().  Here we recognize
65058 		 * whatever tokens are considered reserved in current strictness
65059 		 * (which is not always enough).
65060 		 */
65061 
65062 		if (comp_ctx->curr_token.t != DUK_TOK_IDENTIFIER) {
65063 			DUK_ERROR_SYNTAX(thr, "expected identifier");
65064 		}
65065 		DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_IDENTIFIER);
65066 		DUK_ASSERT(comp_ctx->curr_token.str1 != NULL);
65067 		DUK_DDD(DUK_DDDPRINT("formal argument: %!O",
65068 		                     (duk_heaphdr *) comp_ctx->curr_token.str1));
65069 
65070 		/* XXX: append primitive */
65071 		duk_push_hstring(ctx, comp_ctx->curr_token.str1);
65072 		n = (duk_uarridx_t) duk_get_length(ctx, comp_ctx->curr_func.argnames_idx);
65073 		duk_put_prop_index(ctx, comp_ctx->curr_func.argnames_idx, n);
65074 
65075 		duk__advance(comp_ctx);  /* eat identifier */
65076 	}
65077 }
65078 
65079 /* Parse a function-like expression, assuming that 'comp_ctx->curr_func' is
65080  * correctly set up.  Assumes that curr_token is just after 'function' (or
65081  * 'set'/'get' etc).
65082  */
65083 DUK_LOCAL void duk__parse_func_like_raw(duk_compiler_ctx *comp_ctx, duk_bool_t is_decl, duk_bool_t is_setget) {
65084 	duk_hthread *thr = comp_ctx->thr;
65085 	duk_context *ctx = (duk_context *) thr;
65086 
65087 	DUK_ASSERT(comp_ctx->curr_func.num_formals == 0);
65088 	DUK_ASSERT(comp_ctx->curr_func.is_function == 1);
65089 	DUK_ASSERT(comp_ctx->curr_func.is_eval == 0);
65090 	DUK_ASSERT(comp_ctx->curr_func.is_global == 0);
65091 	DUK_ASSERT(comp_ctx->curr_func.is_setget == is_setget);
65092 	DUK_ASSERT(comp_ctx->curr_func.is_decl == is_decl);
65093 
65094 	duk__update_lineinfo_currtoken(comp_ctx);
65095 
65096 	/*
65097 	 *  Function name (if any)
65098 	 *
65099 	 *  We don't check for prohibited names here, because we don't
65100 	 *  yet know whether the function will be strict.  Function body
65101 	 *  parsing handles this retroactively.
65102 	 *
65103 	 *  For function expressions and declarations function name must
65104 	 *  be an Identifer (excludes reserved words).  For setter/getter
65105 	 *  it is a PropertyName which allows reserved words and also
65106 	 *  strings and numbers (e.g. "{ get 1() { ... } }").
65107 	 */
65108 
65109 	if (is_setget) {
65110 		/* PropertyName -> IdentifierName | StringLiteral | NumericLiteral */
65111 		if (comp_ctx->curr_token.t_nores == DUK_TOK_IDENTIFIER ||
65112 		    comp_ctx->curr_token.t == DUK_TOK_STRING) {
65113 			duk_push_hstring(ctx, comp_ctx->curr_token.str1);       /* keep in valstack */
65114 		} else if (comp_ctx->curr_token.t == DUK_TOK_NUMBER) {
65115 			duk_push_number(ctx, comp_ctx->curr_token.num);
65116 			duk_to_string(ctx, -1);
65117 		} else {
65118 			DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_GETSET_NAME);
65119 		}
65120 		comp_ctx->curr_func.h_name = duk_get_hstring(ctx, -1);  /* borrowed reference */
65121 		DUK_ASSERT(comp_ctx->curr_func.h_name != NULL);
65122 		duk__advance(comp_ctx);
65123 	} else {
65124 		/* Function name is an Identifier (not IdentifierName), but we get
65125 		 * the raw name (not recognizing keywords) here and perform the name
65126 		 * checks only after pass 1.
65127 		 */
65128 		if (comp_ctx->curr_token.t_nores == DUK_TOK_IDENTIFIER) {
65129 			duk_push_hstring(ctx, comp_ctx->curr_token.str1);       /* keep in valstack */
65130 			comp_ctx->curr_func.h_name = duk_get_hstring(ctx, -1);  /* borrowed reference */
65131 			DUK_ASSERT(comp_ctx->curr_func.h_name != NULL);
65132 			duk__advance(comp_ctx);
65133 		} else {
65134 			/* valstack will be unbalanced, which is OK */
65135 			DUK_ASSERT(!is_setget);
65136 			if (is_decl) {
65137 				DUK_ERROR_SYNTAX(thr, DUK_STR_FUNC_NAME_REQUIRED);
65138 			}
65139 		}
65140 	}
65141 
65142 	DUK_DDD(DUK_DDDPRINT("function name: %!O",
65143 	                     (duk_heaphdr *) comp_ctx->curr_func.h_name));
65144 
65145 	/*
65146 	 *  Formal argument list
65147 	 *
65148 	 *  We don't check for prohibited names or for duplicate argument
65149 	 *  names here, becase we don't yet know whether the function will
65150 	 *  be strict.  Function body parsing handles this retroactively.
65151 	 */
65152 
65153 	duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
65154 
65155 	duk__parse_func_formals(comp_ctx);
65156 
65157 	DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_RPAREN);
65158 	duk__advance(comp_ctx);
65159 
65160 	/*
65161 	 *  Parse function body
65162 	 */
65163 
65164 	duk__parse_func_body(comp_ctx,
65165 	                     0,   /* expect_eof */
65166 	                     0,   /* implicit_return_value */
65167 	                     DUK_TOK_LCURLY);  /* expect_token */
65168 
65169 	/*
65170 	 *  Convert duk_compiler_func to a function template and add it
65171 	 *  to the parent function table.
65172 	 */
65173 
65174 	duk__convert_to_func_template(comp_ctx, is_setget /*force_no_namebind*/);  /* -> [ ... func ] */
65175 }
65176 
65177 /* Parse an inner function, adding the function template to the current function's
65178  * function table.  Return a function number to be used by the outer function.
65179  *
65180  * Avoiding O(depth^2) inner function parsing is handled here.  On the first pass,
65181  * compile and register the function normally into the 'funcs' array, also recording
65182  * a lexer point (offset/line) to the closing brace of the function.  On the second
65183  * pass, skip the function and return the same 'fnum' as on the first pass by using
65184  * a running counter.
65185  *
65186  * An unfortunate side effect of this is that when parsing the inner function, almost
65187  * nothing is known of the outer function, i.e. the inner function's scope.  We don't
65188  * need that information at the moment, but it would allow some optimizations if it
65189  * were used.
65190  */
65191 DUK_LOCAL duk_int_t duk__parse_func_like_fnum(duk_compiler_ctx *comp_ctx, duk_bool_t is_decl, duk_bool_t is_setget) {
65192 	duk_hthread *thr = comp_ctx->thr;
65193 	duk_context *ctx = (duk_context *) thr;
65194 	duk_compiler_func old_func;
65195 	duk_idx_t entry_top;
65196 	duk_int_t fnum;
65197 
65198 	/*
65199 	 *  On second pass, skip the function.
65200 	 */
65201 
65202 	if (!comp_ctx->curr_func.in_scanning) {
65203 		duk_lexer_point lex_pt;
65204 
65205 		fnum = comp_ctx->curr_func.fnum_next++;
65206 		duk_get_prop_index(ctx, comp_ctx->curr_func.funcs_idx, (duk_uarridx_t) (fnum * 3 + 1));
65207 		lex_pt.offset = duk_to_int(ctx, -1);
65208 		duk_pop(ctx);
65209 		duk_get_prop_index(ctx, comp_ctx->curr_func.funcs_idx, (duk_uarridx_t) (fnum * 3 + 2));
65210 		lex_pt.line = duk_to_int(ctx, -1);
65211 		duk_pop(ctx);
65212 
65213 		DUK_DDD(DUK_DDDPRINT("second pass of an inner func, skip the function, reparse closing brace; lex offset=%ld, line=%ld",
65214 		                     (long) lex_pt.offset, (long) lex_pt.line));
65215 
65216 		DUK_LEXER_SETPOINT(&comp_ctx->lex, &lex_pt);
65217 		comp_ctx->curr_token.t = 0;  /* this is needed for regexp mode */
65218 		comp_ctx->curr_token.start_line = 0;  /* needed for line number tracking (becomes prev_token.start_line) */
65219 		duk__advance(comp_ctx);
65220 		duk__advance_expect(comp_ctx, DUK_TOK_RCURLY);
65221 
65222 		return fnum;
65223 	}
65224 
65225 	/*
65226 	 *  On first pass, perform actual parsing.  Remember valstack top on entry
65227 	 *  to restore it later, and switch to using a new function in comp_ctx.
65228 	 */
65229 
65230 	entry_top = duk_get_top(ctx);
65231 	DUK_DDD(DUK_DDDPRINT("before func: entry_top=%ld, curr_tok.start_offset=%ld",
65232 	                     (long) entry_top, (long) comp_ctx->curr_token.start_offset));
65233 
65234 	DUK_MEMCPY(&old_func, &comp_ctx->curr_func, sizeof(duk_compiler_func));
65235 
65236 	DUK_MEMZERO(&comp_ctx->curr_func, sizeof(duk_compiler_func));
65237 	duk__init_func_valstack_slots(comp_ctx);
65238 	DUK_ASSERT(comp_ctx->curr_func.num_formals == 0);
65239 
65240 	/* inherit initial strictness from parent */
65241 	comp_ctx->curr_func.is_strict = old_func.is_strict;
65242 
65243 	DUK_ASSERT(comp_ctx->curr_func.is_notail == 0);
65244 	comp_ctx->curr_func.is_function = 1;
65245 	DUK_ASSERT(comp_ctx->curr_func.is_eval == 0);
65246 	DUK_ASSERT(comp_ctx->curr_func.is_global == 0);
65247 	comp_ctx->curr_func.is_setget = is_setget;
65248 	comp_ctx->curr_func.is_decl = is_decl;
65249 
65250 	/*
65251 	 *  Parse inner function
65252 	 */
65253 
65254 	duk__parse_func_like_raw(comp_ctx, is_decl, is_setget);  /* pushes function template */
65255 
65256 	/* prev_token.start_offset points to the closing brace here; when skipping
65257 	 * we're going to reparse the closing brace to ensure semicolon insertion
65258 	 * etc work as expected.
65259 	 */
65260 	DUK_DDD(DUK_DDDPRINT("after func: prev_tok.start_offset=%ld, curr_tok.start_offset=%ld",
65261 	                     (long) comp_ctx->prev_token.start_offset, (long) comp_ctx->curr_token.start_offset));
65262 	DUK_ASSERT(comp_ctx->lex.input[comp_ctx->prev_token.start_offset] == (duk_uint8_t) DUK_ASC_RCURLY);
65263 
65264 	/* XXX: append primitive */
65265 	DUK_ASSERT(duk_get_length(ctx, old_func.funcs_idx) == (duk_size_t) (old_func.fnum_next * 3));
65266 	fnum = old_func.fnum_next++;
65267 
65268 	if (fnum > DUK__MAX_FUNCS) {
65269 		DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_FUNC_LIMIT);
65270 	}
65271 
65272 	/* array writes autoincrement length */
65273 	(void) duk_put_prop_index(ctx, old_func.funcs_idx, (duk_uarridx_t) (fnum * 3));
65274 	duk_push_size_t(ctx, comp_ctx->prev_token.start_offset);
65275 	(void) duk_put_prop_index(ctx, old_func.funcs_idx, (duk_uarridx_t) (fnum * 3 + 1));
65276 	duk_push_int(ctx, comp_ctx->prev_token.start_line);
65277 	(void) duk_put_prop_index(ctx, old_func.funcs_idx, (duk_uarridx_t) (fnum * 3 + 2));
65278 
65279 	/*
65280 	 *  Cleanup: restore original function, restore valstack state.
65281 	 */
65282 
65283 	DUK_MEMCPY((void *) &comp_ctx->curr_func, (void *) &old_func, sizeof(duk_compiler_func));
65284 	duk_set_top(ctx, entry_top);
65285 
65286 	DUK_ASSERT_TOP(ctx, entry_top);
65287 
65288 	return fnum;
65289 }
65290 
65291 /*
65292  *  Compile input string into an executable function template without
65293  *  arguments.
65294  *
65295  *  The string is parsed as the "Program" production of Ecmascript E5.
65296  *  Compilation context can be either global code or eval code (see E5
65297  *  Sections 14 and 15.1.2.1).
65298  *
65299  *  Input stack:  [ ... filename ]
65300  *  Output stack: [ ... func_template ]
65301  */
65302 
65303 /* XXX: source code property */
65304 
65305 DUK_LOCAL duk_ret_t duk__js_compile_raw(duk_context *ctx) {
65306 	duk_hthread *thr = (duk_hthread *) ctx;
65307 	duk_hstring *h_filename;
65308 	duk__compiler_stkstate *comp_stk;
65309 	duk_compiler_ctx *comp_ctx;
65310 	duk_lexer_point *lex_pt;
65311 	duk_compiler_func *func;
65312 	duk_idx_t entry_top;
65313 	duk_bool_t is_strict;
65314 	duk_bool_t is_eval;
65315 	duk_bool_t is_funcexpr;
65316 	duk_small_uint_t flags;
65317 
65318 	DUK_ASSERT(thr != NULL);
65319 
65320 	/*
65321 	 *  Arguments check
65322 	 */
65323 
65324 	entry_top = duk_get_top(ctx);
65325 	DUK_ASSERT(entry_top >= 2);
65326 
65327 	comp_stk = (duk__compiler_stkstate *) duk_require_pointer(ctx, -1);
65328 	comp_ctx = &comp_stk->comp_ctx_alloc;
65329 	lex_pt = &comp_stk->lex_pt_alloc;
65330 	DUK_ASSERT(comp_ctx != NULL);
65331 	DUK_ASSERT(lex_pt != NULL);
65332 
65333 	flags = comp_stk->flags;
65334 	is_eval = (flags & DUK_JS_COMPILE_FLAG_EVAL ? 1 : 0);
65335 	is_strict = (flags & DUK_JS_COMPILE_FLAG_STRICT ? 1 : 0);
65336 	is_funcexpr = (flags & DUK_JS_COMPILE_FLAG_FUNCEXPR ? 1 : 0);
65337 
65338 	h_filename = duk_get_hstring(ctx, -2);  /* may be undefined */
65339 
65340 	/*
65341 	 *  Init compiler and lexer contexts
65342 	 */
65343 
65344 	func = &comp_ctx->curr_func;
65345 #ifdef DUK_USE_EXPLICIT_NULL_INIT
65346 	comp_ctx->thr = NULL;
65347 	comp_ctx->h_filename = NULL;
65348 	comp_ctx->prev_token.str1 = NULL;
65349 	comp_ctx->prev_token.str2 = NULL;
65350 	comp_ctx->curr_token.str1 = NULL;
65351 	comp_ctx->curr_token.str2 = NULL;
65352 #endif
65353 
65354 	duk_require_stack(ctx, DUK__COMPILE_ENTRY_SLOTS);
65355 
65356 	duk_push_dynamic_buffer(ctx, 0);       /* entry_top + 0 */
65357 	duk_push_undefined(ctx);               /* entry_top + 1 */
65358 	duk_push_undefined(ctx);               /* entry_top + 2 */
65359 	duk_push_undefined(ctx);               /* entry_top + 3 */
65360 	duk_push_undefined(ctx);               /* entry_top + 4 */
65361 
65362 	comp_ctx->thr = thr;
65363 	comp_ctx->h_filename = h_filename;
65364 	comp_ctx->tok11_idx = entry_top + 1;
65365 	comp_ctx->tok12_idx = entry_top + 2;
65366 	comp_ctx->tok21_idx = entry_top + 3;
65367 	comp_ctx->tok22_idx = entry_top + 4;
65368 	comp_ctx->recursion_limit = DUK_USE_COMPILER_RECLIMIT;
65369 
65370 	/* comp_ctx->lex has been pre-initialized by caller: it has been
65371 	 * zeroed and input/input_length has been set.
65372 	 */
65373 	comp_ctx->lex.thr = thr;
65374 	/* comp_ctx->lex.input and comp_ctx->lex.input_length filled by caller */
65375 	comp_ctx->lex.slot1_idx = comp_ctx->tok11_idx;
65376 	comp_ctx->lex.slot2_idx = comp_ctx->tok12_idx;
65377 	comp_ctx->lex.buf_idx = entry_top + 0;
65378 	comp_ctx->lex.buf = (duk_hbuffer_dynamic *) duk_get_hbuffer(ctx, entry_top + 0);
65379 	DUK_ASSERT(comp_ctx->lex.buf != NULL);
65380 	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(comp_ctx->lex.buf) && !DUK_HBUFFER_HAS_EXTERNAL(comp_ctx->lex.buf));
65381 	comp_ctx->lex.token_limit = DUK_COMPILER_TOKEN_LIMIT;
65382 
65383 	lex_pt->offset = 0;
65384 	lex_pt->line = 1;
65385 	DUK_LEXER_SETPOINT(&comp_ctx->lex, lex_pt);    /* fills window */
65386 	comp_ctx->curr_token.start_line = 0;  /* needed for line number tracking (becomes prev_token.start_line) */
65387 
65388 	/*
65389 	 *  Initialize function state for a zero-argument function
65390 	 */
65391 
65392 	duk__init_func_valstack_slots(comp_ctx);
65393 	DUK_ASSERT(func->num_formals == 0);
65394 
65395 	if (is_funcexpr) {
65396 		/* Name will be filled from function expression, not by caller.
65397 		 * This case is used by Function constructor and duk_compile()
65398 		 * API with the DUK_COMPILE_FUNCTION option.
65399 		 */
65400 		DUK_ASSERT(func->h_name == NULL);
65401 	} else {
65402 		duk_push_hstring_stridx(ctx, (is_eval ? DUK_STRIDX_EVAL :
65403 		                                        DUK_STRIDX_GLOBAL));
65404 		func->h_name = duk_get_hstring(ctx, -1);
65405 	}
65406 
65407 	/*
65408 	 *  Parse a function body or a function-like expression, depending
65409 	 *  on flags.
65410 	 */
65411 
65412 	func->is_strict = is_strict;
65413 	func->is_setget = 0;
65414 	func->is_decl = 0;
65415 
65416 	if (is_funcexpr) {
65417 		func->is_function = 1;
65418 		func->is_eval = 0;
65419 		func->is_global = 0;
65420 
65421 		duk__advance(comp_ctx);  /* init 'curr_token' */
65422 		duk__advance_expect(comp_ctx, DUK_TOK_FUNCTION);
65423 		(void) duk__parse_func_like_raw(comp_ctx,
65424 		                                0,      /* is_decl */
65425 		                                0);     /* is_setget */
65426 	} else {
65427 		func->is_function = 0;
65428 		func->is_eval = is_eval;
65429 		func->is_global = !is_eval;
65430 
65431 		duk__parse_func_body(comp_ctx,
65432 		                     1,             /* expect_eof */
65433 		                     1,             /* implicit_return_value */
65434 		                     -1);           /* expect_token */
65435 	}
65436 
65437 	/*
65438 	 *  Convert duk_compiler_func to a function template
65439 	 */
65440 
65441 	duk__convert_to_func_template(comp_ctx, 0 /*force_no_namebind*/);
65442 
65443 	/*
65444 	 *  Wrapping duk_safe_call() will mangle the stack, just return stack top
65445 	 */
65446 
65447 	/* [ ... filename (temps) func ] */
65448 
65449 	return 1;
65450 }
65451 
65452 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) {
65453 	duk_context *ctx = (duk_context *) thr;
65454 	duk__compiler_stkstate comp_stk;
65455 	duk_compiler_ctx *prev_ctx;
65456 	duk_ret_t safe_rc;
65457 
65458 	/* XXX: this illustrates that a C catchpoint implemented using duk_safe_call()
65459 	 * is a bit heavy at the moment.  The wrapper compiles to ~180 bytes on x64.
65460 	 * Alternatives would be nice.
65461 	 */
65462 
65463 	DUK_ASSERT(thr != NULL);
65464 	DUK_ASSERT(src_buffer != NULL);
65465 
65466 	/* preinitialize lexer state partially */
65467 	DUK_MEMZERO(&comp_stk, sizeof(comp_stk));
65468 	comp_stk.flags = flags;
65469 	DUK_LEXER_INITCTX(&comp_stk.comp_ctx_alloc.lex);
65470 	comp_stk.comp_ctx_alloc.lex.input = src_buffer;
65471 	comp_stk.comp_ctx_alloc.lex.input_length = src_length;
65472 
65473 	duk_push_pointer(ctx, (void *) &comp_stk);
65474 
65475 	/* [ ... filename &comp_stk ] */
65476 
65477 	prev_ctx = thr->compile_ctx;
65478 	thr->compile_ctx = &comp_stk.comp_ctx_alloc;  /* for duk_error_augment.c */
65479 	safe_rc = duk_safe_call(ctx, duk__js_compile_raw, 2 /*nargs*/, 1 /*nret*/);
65480 	thr->compile_ctx = prev_ctx;  /* must restore reliably before returning */
65481 
65482 	if (safe_rc != DUK_EXEC_SUCCESS) {
65483 		duk_throw(ctx);
65484 	}
65485 
65486 	/* [ ... template ] */
65487 }
65488 /*
65489  *  Ecmascript bytecode executor.
65490  */
65491 
65492 /* include removed: duk_internal.h */
65493 
65494 /*
65495  *  Local declarations.
65496  */
65497 
65498 DUK_LOCAL_DECL void duk__js_execute_bytecode_inner(duk_hthread *entry_thread, duk_size_t entry_callstack_top);
65499 
65500 /*
65501  *  Arithmetic, binary, and logical helpers.
65502  *
65503  *  Note: there is no opcode for logical AND or logical OR; this is on
65504  *  purpose, because the evalution order semantics for them make such
65505  *  opcodes pretty pointless: short circuiting means they are most
65506  *  comfortably implemented as jumps.  However, a logical NOT opcode
65507  *  is useful.
65508  *
65509  *  Note: careful with duk_tval pointers here: they are potentially
65510  *  invalidated by any DECREF and almost any API call.  It's still
65511  *  preferable to work without making a copy but that's not always
65512  *  possible.
65513  */
65514 
65515 DUK_LOCAL duk_double_t duk__compute_mod(duk_double_t d1, duk_double_t d2) {
65516 	/*
65517 	 *  Ecmascript modulus ('%') does not match IEEE 754 "remainder"
65518 	 *  operation (implemented by remainder() in C99) but does seem
65519 	 *  to match ANSI C fmod().
65520 	 *
65521 	 *  Compare E5 Section 11.5.3 and "man fmod".
65522 	 */
65523 
65524 	return (duk_double_t) DUK_FMOD((double) d1, (double) d2);
65525 }
65526 
65527 DUK_LOCAL void duk__vm_arith_add(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_uint_fast_t idx_z) {
65528 	/*
65529 	 *  Addition operator is different from other arithmetic
65530 	 *  operations in that it also provides string concatenation.
65531 	 *  Hence it is implemented separately.
65532 	 *
65533 	 *  There is a fast path for number addition.  Other cases go
65534 	 *  through potentially multiple coercions as described in the
65535 	 *  E5 specification.  It may be possible to reduce the number
65536 	 *  of coercions, but this must be done carefully to preserve
65537 	 *  the exact semantics.
65538 	 *
65539 	 *  E5 Section 11.6.1.
65540 	 *
65541 	 *  Custom types also have special behavior implemented here.
65542 	 */
65543 
65544 	duk_context *ctx = (duk_context *) thr;
65545 	duk_double_union du;
65546 
65547 	DUK_ASSERT(thr != NULL);
65548 	DUK_ASSERT(ctx != NULL);
65549 	DUK_ASSERT(tv_x != NULL);  /* may be reg or const */
65550 	DUK_ASSERT(tv_y != NULL);  /* may be reg or const */
65551 	DUK_ASSERT_DISABLE(idx_z >= 0);  /* unsigned */
65552 	DUK_ASSERT((duk_uint_t) idx_z < (duk_uint_t) duk_get_top(ctx));
65553 
65554 	/*
65555 	 *  Fast paths
65556 	 */
65557 
65558 #if defined(DUK_USE_FASTINT)
65559 	if (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {
65560 		duk_int64_t v1, v2, v3;
65561 		duk_int32_t v3_hi;
65562 		duk_tval *tv_z;
65563 
65564 		/* Input values are signed 48-bit so we can detect overflow
65565 		 * reliably from high bits or just a comparison.
65566 		 */
65567 
65568 		v1 = DUK_TVAL_GET_FASTINT(tv_x);
65569 		v2 = DUK_TVAL_GET_FASTINT(tv_y);
65570 		v3 = v1 + v2;
65571 		v3_hi = (duk_int32_t) (v3 >> 32);
65572 		if (DUK_LIKELY(v3_hi >= -0x8000LL && v3_hi <= 0x7fffLL)) {
65573 			tv_z = thr->valstack_bottom + idx_z;
65574 			DUK_TVAL_SET_FASTINT_UPDREF(thr, tv_z, v3);  /* side effects */
65575 			return;
65576 		} else {
65577 			/* overflow, fall through */
65578 			;
65579 		}
65580 	}
65581 #endif  /* DUK_USE_FASTINT */
65582 
65583 	if (DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y)) {
65584 		duk_tval *tv_z;
65585 
65586 		du.d = DUK_TVAL_GET_NUMBER(tv_x) + DUK_TVAL_GET_NUMBER(tv_y);
65587 		DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);
65588 		DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
65589 
65590 		tv_z = thr->valstack_bottom + idx_z;
65591 		DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_z, du.d);  /* side effects */
65592 		return;
65593 	}
65594 
65595 	/*
65596 	 *  Slow path: potentially requires function calls for coercion
65597 	 */
65598 
65599 	duk_push_tval(ctx, tv_x);
65600 	duk_push_tval(ctx, tv_y);
65601 	duk_to_primitive(ctx, -2, DUK_HINT_NONE);  /* side effects -> don't use tv_x, tv_y after */
65602 	duk_to_primitive(ctx, -1, DUK_HINT_NONE);
65603 
65604 	/* As a first approximation, buffer values are coerced to strings
65605 	 * for addition.  This means that adding two buffers currently
65606 	 * results in a string.
65607 	 */
65608 	if (duk_check_type_mask(ctx, -2, DUK_TYPE_MASK_STRING | DUK_TYPE_MASK_BUFFER) ||
65609 	    duk_check_type_mask(ctx, -1, DUK_TYPE_MASK_STRING | DUK_TYPE_MASK_BUFFER)) {
65610 		duk_to_string(ctx, -2);
65611 		duk_to_string(ctx, -1);
65612 		duk_concat(ctx, 2);  /* [... s1 s2] -> [... s1+s2] */
65613 		duk_replace(ctx, (duk_idx_t) idx_z);  /* side effects */
65614 	} else {
65615 		duk_double_t d1, d2;
65616 
65617 		d1 = duk_to_number(ctx, -2);
65618 		d2 = duk_to_number(ctx, -1);
65619 		DUK_ASSERT(duk_is_number(ctx, -2));
65620 		DUK_ASSERT(duk_is_number(ctx, -1));
65621 		DUK_ASSERT_DOUBLE_IS_NORMALIZED(d1);
65622 		DUK_ASSERT_DOUBLE_IS_NORMALIZED(d2);
65623 
65624 		du.d = d1 + d2;
65625 		DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);
65626 		DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
65627 
65628 		duk_pop_2(ctx);
65629 		duk_push_number(ctx, du.d);
65630 		duk_replace(ctx, (duk_idx_t) idx_z);  /* side effects */
65631 	}
65632 }
65633 
65634 DUK_LOCAL void duk__vm_arith_binary_op(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_idx_t idx_z, duk_small_uint_fast_t opcode) {
65635 	/*
65636 	 *  Arithmetic operations other than '+' have number-only semantics
65637 	 *  and are implemented here.  The separate switch-case here means a
65638 	 *  "double dispatch" of the arithmetic opcode, but saves code space.
65639 	 *
65640 	 *  E5 Sections 11.5, 11.5.1, 11.5.2, 11.5.3, 11.6, 11.6.1, 11.6.2, 11.6.3.
65641 	 */
65642 
65643 	duk_context *ctx = (duk_context *) thr;
65644 	duk_tval *tv_z;
65645 	duk_double_t d1, d2;
65646 	duk_double_union du;
65647 
65648 	DUK_ASSERT(thr != NULL);
65649 	DUK_ASSERT(ctx != NULL);
65650 	DUK_ASSERT(tv_x != NULL);  /* may be reg or const */
65651 	DUK_ASSERT(tv_y != NULL);  /* may be reg or const */
65652 	DUK_ASSERT_DISABLE(idx_z >= 0);  /* unsigned */
65653 	DUK_ASSERT((duk_uint_t) idx_z < (duk_uint_t) duk_get_top(ctx));
65654 
65655 #if defined(DUK_USE_FASTINT)
65656 	if (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {
65657 		duk_int64_t v1, v2, v3;
65658 		duk_int32_t v3_hi;
65659 
65660 		v1 = DUK_TVAL_GET_FASTINT(tv_x);
65661 		v2 = DUK_TVAL_GET_FASTINT(tv_y);
65662 
65663 		switch (opcode) {
65664 		case DUK_OP_SUB: {
65665 			v3 = v1 - v2;
65666 			break;
65667 		}
65668 		case DUK_OP_MUL: {
65669 			/* Must ensure result is 64-bit (no overflow); a
65670 			 * simple and sufficient fast path is to allow only
65671 			 * 32-bit inputs.  Avoid zero inputs to avoid
65672 			 * negative zero issues (-1 * 0 = -0, for instance).
65673 			 */
65674 			if (v1 >= -0x80000000LL && v1 <= 0x7fffffffLL && v1 != 0 &&
65675 			    v2 >= -0x80000000LL && v2 <= 0x7fffffffLL && v2 != 0) {
65676 				v3 = v1 * v2;
65677 			} else {
65678 				goto skip_fastint;
65679 			}
65680 			break;
65681 		}
65682 		case DUK_OP_DIV: {
65683 			/* Don't allow a zero divisor.  Fast path check by
65684 			 * "verifying" with multiplication.  Also avoid zero
65685 			 * dividend to avoid negative zero issues (0 / -1 = -0
65686 			 * for instance).
65687 			 */
65688 			if (v1 == 0 || v2 == 0) {
65689 				goto skip_fastint;
65690 			}
65691 			v3 = v1 / v2;
65692 			if (v3 * v2 != v1) {
65693 				goto skip_fastint;
65694 			}
65695 			break;
65696 		}
65697 		case DUK_OP_MOD: {
65698 			/* Don't allow a zero divisor.  Restrict both v1 and
65699 			 * v2 to positive values to avoid compiler specific
65700 			 * behavior.
65701 			 */
65702 			if (v1 < 1 || v2 < 1) {
65703 				goto skip_fastint;
65704 			}
65705 			v3 = v1 % v2;
65706 			DUK_ASSERT(v3 >= 0);
65707 			DUK_ASSERT(v3 < v2);
65708 			DUK_ASSERT(v1 - (v1 / v2) * v2 == v3);
65709 			break;
65710 		}
65711 		default: {
65712 			DUK_UNREACHABLE();
65713 			goto skip_fastint;
65714 		}
65715 		}
65716 
65717 		v3_hi = (duk_int32_t) (v3 >> 32);
65718 		if (DUK_LIKELY(v3_hi >= -0x8000LL && v3_hi <= 0x7fffLL)) {
65719 			tv_z = thr->valstack_bottom + idx_z;
65720 			DUK_TVAL_SET_FASTINT_UPDREF(thr, tv_z, v3);  /* side effects */
65721 			return;
65722 		}
65723 		/* fall through if overflow etc */
65724 	}
65725  skip_fastint:
65726 #endif  /* DUK_USE_FASTINT */
65727 
65728 	if (DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y)) {
65729 		/* fast path */
65730 		d1 = DUK_TVAL_GET_NUMBER(tv_x);
65731 		d2 = DUK_TVAL_GET_NUMBER(tv_y);
65732 	} else {
65733 		duk_push_tval(ctx, tv_x);
65734 		duk_push_tval(ctx, tv_y);
65735 		d1 = duk_to_number(ctx, -2);  /* side effects */
65736 		d2 = duk_to_number(ctx, -1);
65737 		DUK_ASSERT(duk_is_number(ctx, -2));
65738 		DUK_ASSERT(duk_is_number(ctx, -1));
65739 		DUK_ASSERT_DOUBLE_IS_NORMALIZED(d1);
65740 		DUK_ASSERT_DOUBLE_IS_NORMALIZED(d2);
65741 		duk_pop_2(ctx);
65742 	}
65743 
65744 	switch (opcode) {
65745 	case DUK_OP_SUB: {
65746 		du.d = d1 - d2;
65747 		break;
65748 	}
65749 	case DUK_OP_MUL: {
65750 		du.d = d1 * d2;
65751 		break;
65752 	}
65753 	case DUK_OP_DIV: {
65754 		du.d = d1 / d2;
65755 		break;
65756 	}
65757 	case DUK_OP_MOD: {
65758 		du.d = duk__compute_mod(d1, d2);
65759 		break;
65760 	}
65761 	default: {
65762 		DUK_UNREACHABLE();
65763 		du.d = DUK_DOUBLE_NAN;  /* should not happen */
65764 		break;
65765 	}
65766 	}
65767 
65768 	/* important to use normalized NaN with 8-byte tagged types */
65769 	DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);
65770 	DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
65771 
65772 	tv_z = thr->valstack_bottom + idx_z;
65773 	DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_z, du.d);  /* side effects */
65774 }
65775 
65776 DUK_LOCAL 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) {
65777 	/*
65778 	 *  Binary bitwise operations use different coercions (ToInt32, ToUint32)
65779 	 *  depending on the operation.  We coerce the arguments first using
65780 	 *  ToInt32(), and then cast to an 32-bit value if necessary.  Note that
65781 	 *  such casts must be correct even if there is no native 32-bit type
65782 	 *  (e.g., duk_int32_t and duk_uint32_t are 64-bit).
65783 	 *
65784 	 *  E5 Sections 11.10, 11.7.1, 11.7.2, 11.7.3
65785 	 */
65786 
65787 	duk_context *ctx = (duk_context *) thr;
65788 	duk_tval *tv_z;
65789 	duk_int32_t i1, i2, i3;
65790 	duk_uint32_t u1, u2, u3;
65791 #if defined(DUK_USE_FASTINT)
65792 	duk_int64_t fi3;
65793 #else
65794 	duk_double_t d3;
65795 #endif
65796 
65797 	DUK_ASSERT(thr != NULL);
65798 	DUK_ASSERT(ctx != NULL);
65799 	DUK_ASSERT(tv_x != NULL);  /* may be reg or const */
65800 	DUK_ASSERT(tv_y != NULL);  /* may be reg or const */
65801 	DUK_ASSERT_DISABLE(idx_z >= 0);  /* unsigned */
65802 	DUK_ASSERT((duk_uint_t) idx_z < (duk_uint_t) duk_get_top(ctx));
65803 
65804 #if defined(DUK_USE_FASTINT)
65805 	if (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {
65806 		i1 = (duk_int32_t) DUK_TVAL_GET_FASTINT_I32(tv_x);
65807 		i2 = (duk_int32_t) DUK_TVAL_GET_FASTINT_I32(tv_y);
65808 	}
65809 	else
65810 #endif  /* DUK_USE_FASTINT */
65811 	{
65812 		duk_push_tval(ctx, tv_x);
65813 		duk_push_tval(ctx, tv_y);
65814 		i1 = duk_to_int32(ctx, -2);
65815 		i2 = duk_to_int32(ctx, -1);
65816 		duk_pop_2(ctx);
65817 	}
65818 
65819 	switch (opcode) {
65820 	case DUK_OP_BAND: {
65821 		i3 = i1 & i2;
65822 		break;
65823 	}
65824 	case DUK_OP_BOR: {
65825 		i3 = i1 | i2;
65826 		break;
65827 	}
65828 	case DUK_OP_BXOR: {
65829 		i3 = i1 ^ i2;
65830 		break;
65831 	}
65832 	case DUK_OP_BASL: {
65833 		/* Signed shift, named "arithmetic" (asl) because the result
65834 		 * is signed, e.g. 4294967295 << 1 -> -2.  Note that result
65835 		 * must be masked.
65836 		 */
65837 
65838 		u2 = ((duk_uint32_t) i2) & 0xffffffffUL;
65839 		i3 = (duk_int32_t) (((duk_uint32_t) i1) << (u2 & 0x1fUL));  /* E5 Section 11.7.1, steps 7 and 8 */
65840 		i3 = i3 & ((duk_int32_t) 0xffffffffUL);                     /* Note: left shift, should mask */
65841 		break;
65842 	}
65843 	case DUK_OP_BASR: {
65844 		/* signed shift */
65845 
65846 		u2 = ((duk_uint32_t) i2) & 0xffffffffUL;
65847 		i3 = i1 >> (u2 & 0x1fUL);                      /* E5 Section 11.7.2, steps 7 and 8 */
65848 		break;
65849 	}
65850 	case DUK_OP_BLSR: {
65851 		/* unsigned shift */
65852 
65853 		u1 = ((duk_uint32_t) i1) & 0xffffffffUL;
65854 		u2 = ((duk_uint32_t) i2) & 0xffffffffUL;
65855 
65856 		/* special result value handling */
65857 		u3 = u1 >> (u2 & 0x1fUL);     /* E5 Section 11.7.2, steps 7 and 8 */
65858 #if defined(DUK_USE_FASTINT)
65859 		fi3 = (duk_int64_t) u3;
65860 		goto fastint_result_set;
65861 #else
65862 		d3 = (duk_double_t) u3;
65863 		goto result_set;
65864 #endif
65865 	}
65866 	default: {
65867 		DUK_UNREACHABLE();
65868 		i3 = 0;  /* should not happen */
65869 		break;
65870 	}
65871 	}
65872 
65873 #if defined(DUK_USE_FASTINT)
65874 	/* Result is always fastint compatible. */
65875 	/* XXX: Set 32-bit result (but must then handle signed and
65876 	 * unsigned results separately).
65877 	 */
65878 	fi3 = (duk_int64_t) i3;
65879 
65880  fastint_result_set:
65881 	tv_z = thr->valstack_bottom + idx_z;
65882 	DUK_TVAL_SET_FASTINT_UPDREF(thr, tv_z, fi3);  /* side effects */
65883 #else
65884 	d3 = (duk_double_t) i3;
65885 
65886  result_set:
65887 	DUK_ASSERT(!DUK_ISNAN(d3));            /* 'd3' is never NaN, so no need to normalize */
65888 	DUK_ASSERT_DOUBLE_IS_NORMALIZED(d3);   /* always normalized */
65889 
65890 	tv_z = thr->valstack_bottom + idx_z;
65891 	DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_z, d3);  /* side effects */
65892 #endif
65893 }
65894 
65895 /* In-place unary operation. */
65896 DUK_LOCAL void duk__vm_arith_unary_op(duk_hthread *thr, duk_tval *tv_x, duk_idx_t idx_x, duk_small_uint_fast_t opcode) {
65897 	/*
65898 	 *  Arithmetic operations other than '+' have number-only semantics
65899 	 *  and are implemented here.  The separate switch-case here means a
65900 	 *  "double dispatch" of the arithmetic opcode, but saves code space.
65901 	 *
65902 	 *  E5 Sections 11.5, 11.5.1, 11.5.2, 11.5.3, 11.6, 11.6.1, 11.6.2, 11.6.3.
65903 	 */
65904 
65905 	duk_context *ctx = (duk_context *) thr;
65906 	duk_double_t d1;
65907 	duk_double_union du;
65908 
65909 	DUK_ASSERT(thr != NULL);
65910 	DUK_ASSERT(ctx != NULL);
65911 	DUK_ASSERT(opcode == DUK_EXTRAOP_UNM || opcode == DUK_EXTRAOP_UNP);
65912 	DUK_ASSERT(tv_x != NULL);
65913 	DUK_ASSERT(idx_x >= 0);
65914 
65915 #if defined(DUK_USE_FASTINT)
65916 	if (DUK_TVAL_IS_FASTINT(tv_x)) {
65917 		duk_int64_t v1, v2;
65918 
65919 		v1 = DUK_TVAL_GET_FASTINT(tv_x);
65920 		if (opcode == DUK_EXTRAOP_UNM) {
65921 			/* The smallest fastint is no longer 48-bit when
65922 			 * negated.  Positive zero becames negative zero
65923 			 * (cannot be represented) when negated.
65924 			 */
65925 			if (DUK_LIKELY(v1 != DUK_FASTINT_MIN && v1 != 0)) {
65926 				v2 = -v1;
65927 				DUK_TVAL_SET_FASTINT(tv_x, v2);  /* no refcount changes */
65928 				return;
65929 			}
65930 		} else {
65931 			/* ToNumber() for a fastint is a no-op. */
65932 			DUK_ASSERT(opcode == DUK_EXTRAOP_UNP);
65933 			return;
65934 		}
65935 		/* fall through if overflow etc */
65936 	}
65937 #endif  /* DUK_USE_FASTINT */
65938 
65939 	if (!DUK_TVAL_IS_NUMBER(tv_x)) {
65940 		duk_to_number(ctx, idx_x);  /* side effects, perform in-place */
65941 		tv_x = DUK_GET_TVAL_POSIDX(ctx, idx_x);
65942 		DUK_ASSERT(tv_x != NULL);
65943 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_x));
65944 	}
65945 
65946 	d1 = DUK_TVAL_GET_NUMBER(tv_x);
65947 	if (opcode == DUK_EXTRAOP_UNM) {
65948 		du.d = -d1;
65949 	} else {
65950 		/* ToNumber() for a double is a no-op. */
65951 		DUK_ASSERT(opcode == DUK_EXTRAOP_UNP);
65952 		du.d = d1;
65953 	}
65954 	DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);  /* mandatory if du.d is a NaN */
65955 
65956 	DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
65957 
65958 #if defined(DUK_USE_FASTINT)
65959 	/* Unary plus is used to force a fastint check, so must include
65960 	 * downgrade check.
65961 	 */
65962 	DUK_TVAL_SET_NUMBER_CHKFAST(tv_x, du.d);  /* no refcount changes */
65963 #else
65964 	DUK_TVAL_SET_NUMBER(tv_x, du.d);  /* no refcount changes */
65965 #endif
65966 }
65967 
65968 DUK_LOCAL void duk__vm_bitwise_not(duk_hthread *thr, duk_tval *tv_x, duk_uint_fast_t idx_z) {
65969 	/*
65970 	 *  E5 Section 11.4.8
65971 	 */
65972 
65973 	duk_context *ctx = (duk_context *) thr;
65974 	duk_tval *tv_z;
65975 	duk_int32_t i1, i2;
65976 #if !defined(DUK_USE_FASTINT)
65977 	duk_double_t d2;
65978 #endif
65979 
65980 	DUK_ASSERT(thr != NULL);
65981 	DUK_ASSERT(ctx != NULL);
65982 	DUK_ASSERT(tv_x != NULL);  /* may be reg or const */
65983 	DUK_ASSERT_DISABLE(idx_z >= 0);
65984 	DUK_ASSERT((duk_uint_t) idx_z < (duk_uint_t) duk_get_top(ctx));
65985 
65986 #if defined(DUK_USE_FASTINT)
65987 	if (DUK_TVAL_IS_FASTINT(tv_x)) {
65988 		i1 = (duk_int32_t) DUK_TVAL_GET_FASTINT_I32(tv_x);
65989 	}
65990 	else
65991 #endif  /* DUK_USE_FASTINT */
65992 	{
65993 		duk_push_tval(ctx, tv_x);
65994 		i1 = duk_to_int32(ctx, -1);
65995 		duk_pop(ctx);
65996 	}
65997 
65998 	i2 = ~i1;
65999 
66000 #if defined(DUK_USE_FASTINT)
66001 	/* Result is always fastint compatible. */
66002 	tv_z = thr->valstack_bottom + idx_z;
66003 	DUK_TVAL_SET_FASTINT_I32_UPDREF(thr, tv_z, i2);  /* side effects */
66004 #else
66005 	d2 = (duk_double_t) i2;
66006 
66007 	DUK_ASSERT(!DUK_ISNAN(d2));            /* 'val' is never NaN, so no need to normalize */
66008 	DUK_ASSERT_DOUBLE_IS_NORMALIZED(d2);   /* always normalized */
66009 
66010 	tv_z = thr->valstack_bottom + idx_z;
66011 	DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_z, d2);  /* side effects */
66012 #endif
66013 }
66014 
66015 DUK_LOCAL void duk__vm_logical_not(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_z) {
66016 	/*
66017 	 *  E5 Section 11.4.9
66018 	 */
66019 
66020 	duk_bool_t res;
66021 
66022 	DUK_ASSERT(thr != NULL);
66023 	DUK_ASSERT(tv_x != NULL);  /* may be reg or const */
66024 	DUK_ASSERT(tv_z != NULL);  /* reg */
66025 
66026 	DUK_UNREF(thr);  /* w/o refcounts */
66027 
66028 	/* ToBoolean() does not require any operations with side effects so
66029 	 * we can do it efficiently.  For footprint it would be better to use
66030 	 * duk_js_toboolean() and then push+replace to the result slot.
66031 	 */
66032 	res = duk_js_toboolean(tv_x);  /* does not modify tv_x */
66033 	DUK_ASSERT(res == 0 || res == 1);
66034 	res ^= 1;
66035 	DUK_TVAL_SET_BOOLEAN_UPDREF(thr, tv_z, res);  /* side effects */
66036 }
66037 
66038 /*
66039  *  Longjmp and other control flow transfer for the bytecode executor.
66040  *
66041  *  The longjmp handler can handle all longjmp types: error, yield, and
66042  *  resume (pseudotypes are never actually thrown).
66043  *
66044  *  Error policy for longjmp: should not ordinarily throw errors; if errors
66045  *  occur (e.g. due to out-of-memory) they bubble outwards rather than being
66046  *  handled recursively.
66047  */
66048 
66049 #define DUK__LONGJMP_RESTART   0  /* state updated, restart bytecode execution */
66050 #define DUK__LONGJMP_RETHROW   1  /* exit bytecode executor by rethrowing an error to caller */
66051 
66052 #define DUK__RETHAND_RESTART   0  /* state updated, restart bytecode execution */
66053 #define DUK__RETHAND_FINISHED  1  /* exit bytecode execution with return value */
66054 
66055 /* XXX: optimize reconfig valstack operations so that resize, clamp, and setting
66056  * top are combined into one pass.
66057  */
66058 
66059 /* Reconfigure value stack for return to an Ecmascript function at 'act_idx'. */
66060 DUK_LOCAL void duk__reconfig_valstack_ecma_return(duk_hthread *thr, duk_size_t act_idx) {
66061 	duk_activation *act;
66062 	duk_hcompiledfunction *h_func;
66063 	duk_idx_t clamp_top;
66064 
66065 	DUK_ASSERT(thr != NULL);
66066 	DUK_ASSERT_DISABLE(act_idx >= 0);  /* unsigned */
66067 	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + act_idx) != NULL);
66068 	DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION(DUK_ACT_GET_FUNC(thr->callstack + act_idx)));
66069 	DUK_ASSERT_DISABLE(thr->callstack[act_idx].idx_retval >= 0);  /* unsigned */
66070 
66071 	/* Clamp so that values at 'clamp_top' and above are wiped and won't
66072 	 * retain reachable garbage.  Then extend to 'nregs' because we're
66073 	 * returning to an Ecmascript function.
66074 	 */
66075 
66076 	act = thr->callstack + act_idx;
66077 	h_func = (duk_hcompiledfunction *) DUK_ACT_GET_FUNC(act);
66078 
66079 	thr->valstack_bottom = thr->valstack + act->idx_bottom;
66080 	DUK_ASSERT(act->idx_retval >= act->idx_bottom);
66081 	clamp_top = (duk_idx_t) (act->idx_retval - act->idx_bottom + 1);  /* +1 = one retval */
66082 	duk_set_top((duk_context *) thr, clamp_top);
66083 	act = NULL;
66084 
66085 	(void) duk_valstack_resize_raw((duk_context *) thr,
66086 	                               (thr->valstack_bottom - thr->valstack) +  /* bottom of current func */
66087 	                                   h_func->nregs +                       /* reg count */
66088 	                                   DUK_VALSTACK_INTERNAL_EXTRA,          /* + spare */
66089 	                               DUK_VSRESIZE_FLAG_SHRINK |                /* flags */
66090 	                               0 /* no compact */ |
66091 	                               DUK_VSRESIZE_FLAG_THROW);
66092 
66093 	duk_set_top((duk_context *) thr, h_func->nregs);
66094 }
66095 
66096 DUK_LOCAL void duk__reconfig_valstack_ecma_catcher(duk_hthread *thr, duk_size_t act_idx, duk_size_t cat_idx) {
66097 	duk_activation *act;
66098 	duk_catcher *cat;
66099 	duk_hcompiledfunction *h_func;
66100 	duk_idx_t clamp_top;
66101 
66102 	DUK_ASSERT(thr != NULL);
66103 	DUK_ASSERT_DISABLE(act_idx >= 0);  /* unsigned */
66104 	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + act_idx) != NULL);
66105 	DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION(DUK_ACT_GET_FUNC(thr->callstack + act_idx)));
66106 	DUK_ASSERT_DISABLE(thr->callstack[act_idx].idx_retval >= 0);  /* unsigned */
66107 
66108 	act = thr->callstack + act_idx;
66109 	cat = thr->catchstack + cat_idx;
66110 	h_func = (duk_hcompiledfunction *) DUK_ACT_GET_FUNC(act);
66111 
66112 	thr->valstack_bottom = thr->valstack + act->idx_bottom;
66113 	DUK_ASSERT(cat->idx_base >= act->idx_bottom);
66114 	clamp_top = (duk_idx_t) (cat->idx_base - act->idx_bottom + 2);  /* +2 = catcher value, catcher lj_type */
66115 	duk_set_top((duk_context *) thr, clamp_top);
66116 	act = NULL;
66117 	cat = NULL;
66118 
66119 	(void) duk_valstack_resize_raw((duk_context *) thr,
66120 	                               (thr->valstack_bottom - thr->valstack) +  /* bottom of current func */
66121 	                                   h_func->nregs +                       /* reg count */
66122 	                                   DUK_VALSTACK_INTERNAL_EXTRA,          /* + spare */
66123 	                               DUK_VSRESIZE_FLAG_SHRINK |                /* flags */
66124 	                               0 /* no compact */ |
66125 	                               DUK_VSRESIZE_FLAG_THROW);
66126 
66127 	duk_set_top((duk_context *) thr, h_func->nregs);
66128 }
66129 
66130 /* Set catcher regs: idx_base+0 = value, idx_base+1 = lj_type. */
66131 DUK_LOCAL void duk__set_catcher_regs(duk_hthread *thr, duk_size_t cat_idx, duk_tval *tv_val_unstable, duk_small_uint_t lj_type) {
66132 	duk_tval *tv1;
66133 
66134 	DUK_ASSERT(thr != NULL);
66135 	DUK_ASSERT(tv_val_unstable != NULL);
66136 
66137 	tv1 = thr->valstack + thr->catchstack[cat_idx].idx_base;
66138 	DUK_ASSERT(tv1 < thr->valstack_top);
66139 	DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv_val_unstable);  /* side effects */
66140 
66141 	tv1 = thr->valstack + thr->catchstack[cat_idx].idx_base + 1;
66142 	DUK_ASSERT(tv1 < thr->valstack_top);
66143 
66144 	DUK_TVAL_SET_FASTINT_U32_UPDREF(thr, tv1, (duk_uint32_t) lj_type);  /* side effects */
66145 }
66146 
66147 DUK_LOCAL void duk__handle_catch(duk_hthread *thr, duk_size_t cat_idx, duk_tval *tv_val_unstable, duk_small_uint_t lj_type) {
66148 	duk_context *ctx;
66149 	duk_activation *act;
66150 
66151 	DUK_ASSERT(thr != NULL);
66152 	DUK_ASSERT(tv_val_unstable != NULL);
66153 	ctx = (duk_context *) thr;
66154 
66155 	duk__set_catcher_regs(thr, cat_idx, tv_val_unstable, lj_type);
66156 
66157 	duk_hthread_catchstack_unwind(thr, cat_idx + 1);
66158 	duk_hthread_callstack_unwind(thr, thr->catchstack[cat_idx].callstack_index + 1);
66159 
66160 	DUK_ASSERT(thr->callstack_top >= 1);
66161 	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 1) != NULL);
66162 	DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 1)));
66163 
66164 	duk__reconfig_valstack_ecma_catcher(thr, thr->callstack_top - 1, cat_idx);
66165 
66166 	DUK_ASSERT(thr->callstack_top >= 1);
66167 	act = thr->callstack + thr->callstack_top - 1;
66168 	act->curr_pc = thr->catchstack[cat_idx].pc_base + 0;  /* +0 = catch */
66169 	act = NULL;
66170 
66171 	/*
66172 	 *  If entering a 'catch' block which requires an automatic
66173 	 *  catch variable binding, create the lexical environment.
66174 	 *
66175 	 *  The binding is mutable (= writable) but not deletable.
66176 	 *  Step 4 for the catch production in E5 Section 12.14;
66177 	 *  no value is given for CreateMutableBinding 'D' argument,
66178 	 *  which implies the binding is not deletable.
66179 	 */
66180 
66181 	if (DUK_CAT_HAS_CATCH_BINDING_ENABLED(&thr->catchstack[cat_idx])) {
66182 		duk_hobject *new_env;
66183 		duk_hobject *act_lex_env;
66184 
66185 		DUK_DDD(DUK_DDDPRINT("catcher has an automatic catch binding"));
66186 
66187 		/* Note: 'act' is dangerous here because it may get invalidate at many
66188 		 * points, so we re-lookup it multiple times.
66189 		 */
66190 		DUK_ASSERT(thr->callstack_top >= 1);
66191 		act = thr->callstack + thr->callstack_top - 1;
66192 
66193 		if (act->lex_env == NULL) {
66194 			DUK_ASSERT(act->var_env == NULL);
66195 			DUK_DDD(DUK_DDDPRINT("delayed environment initialization"));
66196 
66197 			/* this may have side effects, so re-lookup act */
66198 			duk_js_init_activation_environment_records_delayed(thr, act);
66199 			act = thr->callstack + thr->callstack_top - 1;
66200 		}
66201 		DUK_ASSERT(act->lex_env != NULL);
66202 		DUK_ASSERT(act->var_env != NULL);
66203 		DUK_ASSERT(DUK_ACT_GET_FUNC(act) != NULL);
66204 		DUK_UNREF(act);  /* unreferenced without assertions */
66205 
66206 		act = thr->callstack + thr->callstack_top - 1;
66207 		act_lex_env = act->lex_env;
66208 		act = NULL;  /* invalidated */
66209 
66210 		(void) duk_push_object_helper_proto(ctx,
66211 		                                    DUK_HOBJECT_FLAG_EXTENSIBLE |
66212 		                                    DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV),
66213 		                                    act_lex_env);
66214 		new_env = DUK_GET_HOBJECT_NEGIDX(ctx, -1);
66215 		DUK_ASSERT(new_env != NULL);
66216 		DUK_DDD(DUK_DDDPRINT("new_env allocated: %!iO", (duk_heaphdr *) new_env));
66217 
66218 		/* Note: currently the catch binding is handled without a register
66219 		 * binding because we don't support dynamic register bindings (they
66220 		 * must be fixed for an entire function).  So, there is no need to
66221 		 * record regbases etc.
66222 		 */
66223 
66224 		DUK_ASSERT(thr->catchstack[cat_idx].h_varname != NULL);
66225 		duk_push_hstring(ctx, thr->catchstack[cat_idx].h_varname);
66226 		duk_push_tval(ctx, thr->valstack + thr->catchstack[cat_idx].idx_base);
66227 		duk_xdef_prop(ctx, -3, DUK_PROPDESC_FLAGS_W);  /* writable, not configurable */
66228 
66229 		act = thr->callstack + thr->callstack_top - 1;
66230 		act->lex_env = new_env;
66231 		DUK_HOBJECT_INCREF(thr, new_env);  /* reachable through activation */
66232 
66233 		DUK_CAT_SET_LEXENV_ACTIVE(&thr->catchstack[cat_idx]);
66234 
66235 		duk_pop(ctx);
66236 
66237 		DUK_DDD(DUK_DDDPRINT("new_env finished: %!iO", (duk_heaphdr *) new_env));
66238 	}
66239 
66240 	DUK_CAT_CLEAR_CATCH_ENABLED(&thr->catchstack[cat_idx]);
66241 }
66242 
66243 DUK_LOCAL void duk__handle_finally(duk_hthread *thr, duk_size_t cat_idx, duk_tval *tv_val_unstable, duk_small_uint_t lj_type) {
66244 	duk_activation *act;
66245 
66246 	DUK_ASSERT(thr != NULL);
66247 	DUK_ASSERT(tv_val_unstable != NULL);
66248 
66249 	duk__set_catcher_regs(thr, cat_idx, tv_val_unstable, lj_type);
66250 
66251 	duk_hthread_catchstack_unwind(thr, cat_idx + 1);  /* cat_idx catcher is kept, even for finally */
66252 	duk_hthread_callstack_unwind(thr, thr->catchstack[cat_idx].callstack_index + 1);
66253 
66254 	DUK_ASSERT(thr->callstack_top >= 1);
66255 	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 1) != NULL);
66256 	DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 1)));
66257 
66258 	duk__reconfig_valstack_ecma_catcher(thr, thr->callstack_top - 1, cat_idx);
66259 
66260 	DUK_ASSERT(thr->callstack_top >= 1);
66261 	act = thr->callstack + thr->callstack_top - 1;
66262 	act->curr_pc = thr->catchstack[cat_idx].pc_base + 1;  /* +1 = finally */
66263 	act = NULL;
66264 
66265 	DUK_CAT_CLEAR_FINALLY_ENABLED(&thr->catchstack[cat_idx]);
66266 }
66267 
66268 DUK_LOCAL void duk__handle_label(duk_hthread *thr, duk_size_t cat_idx, duk_small_uint_t lj_type) {
66269 	duk_activation *act;
66270 
66271 	DUK_ASSERT(thr != NULL);
66272 
66273 	DUK_ASSERT(thr->callstack_top >= 1);
66274 	act = thr->callstack + thr->callstack_top - 1;
66275 
66276 	DUK_ASSERT(DUK_ACT_GET_FUNC(act) != NULL);
66277 	DUK_ASSERT(DUK_HOBJECT_HAS_COMPILEDFUNCTION(DUK_ACT_GET_FUNC(act)));
66278 
66279 	/* +0 = break, +1 = continue */
66280 	act->curr_pc = thr->catchstack[cat_idx].pc_base + (lj_type == DUK_LJ_TYPE_CONTINUE ? 1 : 0);
66281 	act = NULL;  /* invalidated */
66282 
66283 	duk_hthread_catchstack_unwind(thr, cat_idx + 1);  /* keep label catcher */
66284 	/* no need to unwind callstack */
66285 
66286 	/* valstack should not need changes */
66287 #if defined(DUK_USE_ASSERTIONS)
66288 	DUK_ASSERT(thr->callstack_top >= 1);
66289 	act = thr->callstack + thr->callstack_top - 1;
66290 	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) ==
66291 	           (duk_size_t) ((duk_hcompiledfunction *) DUK_ACT_GET_FUNC(act))->nregs);
66292 #endif
66293 }
66294 
66295 /* Called for handling both a longjmp() with type DUK_LJ_TYPE_YIELD and
66296  * when a RETURN opcode terminates a thread and yields to the resumer.
66297  */
66298 DUK_LOCAL void duk__handle_yield(duk_hthread *thr, duk_hthread *resumer, duk_size_t act_idx, duk_tval *tv_val_unstable) {
66299 	duk_tval *tv1;
66300 
66301 	DUK_ASSERT(thr != NULL);
66302 	DUK_ASSERT(resumer != NULL);
66303 	DUK_ASSERT(tv_val_unstable != NULL);
66304 	DUK_ASSERT(DUK_ACT_GET_FUNC(resumer->callstack + act_idx) != NULL);
66305 	DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION(DUK_ACT_GET_FUNC(resumer->callstack + act_idx)));  /* resume caller must be an ecmascript func */
66306 
66307 	tv1 = resumer->valstack + resumer->callstack[act_idx].idx_retval;  /* return value from Duktape.Thread.resume() */
66308 	DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv_val_unstable);  /* side effects */
66309 
66310 	duk_hthread_callstack_unwind(resumer, act_idx + 1);  /* unwind to 'resume' caller */
66311 
66312 	/* no need to unwind catchstack */
66313 	duk__reconfig_valstack_ecma_return(resumer, act_idx);
66314 
66315 	/* caller must change active thread, and set thr->resumer to NULL */
66316 }
66317 
66318 DUK_LOCAL
66319 duk_small_uint_t duk__handle_longjmp(duk_hthread *thr,
66320                                      duk_hthread *entry_thread,
66321                                      duk_size_t entry_callstack_top) {
66322 	duk_size_t entry_callstack_index;
66323 	duk_small_uint_t retval = DUK__LONGJMP_RESTART;
66324 
66325 	DUK_ASSERT(thr != NULL);
66326 	DUK_ASSERT(entry_thread != NULL);
66327 	DUK_ASSERT(entry_callstack_top > 0);  /* guarantees entry_callstack_top - 1 >= 0 */
66328 
66329 	entry_callstack_index = entry_callstack_top - 1;
66330 
66331 	/* 'thr' is the current thread, as no-one resumes except us and we
66332 	 * switch 'thr' in that case.
66333 	 */
66334 	DUK_ASSERT(thr == thr->heap->curr_thread);
66335 
66336 	/*
66337 	 *  (Re)try handling the longjmp.
66338 	 *
66339 	 *  A longjmp handler may convert the longjmp to a different type and
66340 	 *  "virtually" rethrow by goto'ing to 'check_longjmp'.  Before the goto,
66341 	 *  the following must be updated:
66342 	 *    - the heap 'lj' state
66343 	 *    - 'thr' must reflect the "throwing" thread
66344 	 */
66345 
66346  check_longjmp:
66347 
66348 	DUK_DD(DUK_DDPRINT("handling longjmp: type=%ld, value1=%!T, value2=%!T, iserror=%ld",
66349 	                   (long) thr->heap->lj.type,
66350 	                   (duk_tval *) &thr->heap->lj.value1,
66351 	                   (duk_tval *) &thr->heap->lj.value2,
66352 	                   (long) thr->heap->lj.iserror));
66353 
66354 	switch (thr->heap->lj.type) {
66355 
66356 	case DUK_LJ_TYPE_RESUME: {
66357 		/*
66358 		 *  Note: lj.value1 is 'value', lj.value2 is 'resumee'.
66359 		 *  This differs from YIELD.
66360 		 */
66361 
66362 		duk_tval *tv;
66363 		duk_tval *tv2;
66364 		duk_size_t act_idx;
66365 		duk_hthread *resumee;
66366 
66367 		/* duk_bi_duk_object_yield() and duk_bi_duk_object_resume() ensure all of these are met */
66368 
66369 		DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);                                                         /* unchanged by Duktape.Thread.resume() */
66370 		DUK_ASSERT(thr->callstack_top >= 2);                                                                         /* Ecmascript activation + Duktape.Thread.resume() activation */
66371 		DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 1) != NULL &&
66372 		           DUK_HOBJECT_IS_NATIVEFUNCTION(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 1)) &&
66373 		           ((duk_hnativefunction *) DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 1))->func == duk_bi_thread_resume);
66374 		DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 2) != NULL &&
66375 		           DUK_HOBJECT_IS_COMPILEDFUNCTION(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 2)));      /* an Ecmascript function */
66376 		DUK_ASSERT_DISABLE((thr->callstack + thr->callstack_top - 2)->idx_retval >= 0);                              /* unsigned */
66377 
66378 		tv = &thr->heap->lj.value2;  /* resumee */
66379 		DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv));
66380 		DUK_ASSERT(DUK_TVAL_GET_OBJECT(tv) != NULL);
66381 		DUK_ASSERT(DUK_HOBJECT_IS_THREAD(DUK_TVAL_GET_OBJECT(tv)));
66382 		resumee = (duk_hthread *) DUK_TVAL_GET_OBJECT(tv);
66383 
66384 		DUK_ASSERT(resumee != NULL);
66385 		DUK_ASSERT(resumee->resumer == NULL);
66386 		DUK_ASSERT(resumee->state == DUK_HTHREAD_STATE_INACTIVE ||
66387 		           resumee->state == DUK_HTHREAD_STATE_YIELDED);                                                     /* checked by Duktape.Thread.resume() */
66388 		DUK_ASSERT(resumee->state != DUK_HTHREAD_STATE_YIELDED ||
66389 		           resumee->callstack_top >= 2);                                                                     /* YIELDED: Ecmascript activation + Duktape.Thread.yield() activation */
66390 		DUK_ASSERT(resumee->state != DUK_HTHREAD_STATE_YIELDED ||
66391 		           (DUK_ACT_GET_FUNC(resumee->callstack + resumee->callstack_top - 1) != NULL &&
66392 		            DUK_HOBJECT_IS_NATIVEFUNCTION(DUK_ACT_GET_FUNC(resumee->callstack + resumee->callstack_top - 1)) &&
66393 		            ((duk_hnativefunction *) DUK_ACT_GET_FUNC(resumee->callstack + resumee->callstack_top - 1))->func == duk_bi_thread_yield));
66394 		DUK_ASSERT(resumee->state != DUK_HTHREAD_STATE_YIELDED ||
66395 		           (DUK_ACT_GET_FUNC(resumee->callstack + resumee->callstack_top - 2) != NULL &&
66396 		            DUK_HOBJECT_IS_COMPILEDFUNCTION(DUK_ACT_GET_FUNC(resumee->callstack + resumee->callstack_top - 2))));      /* an Ecmascript function */
66397 		DUK_ASSERT_DISABLE(resumee->state != DUK_HTHREAD_STATE_YIELDED ||
66398 		           (resumee->callstack + resumee->callstack_top - 2)->idx_retval >= 0);                              /* idx_retval unsigned */
66399 		DUK_ASSERT(resumee->state != DUK_HTHREAD_STATE_INACTIVE ||
66400 		           resumee->callstack_top == 0);                                                                     /* INACTIVE: no activation, single function value on valstack */
66401 		DUK_ASSERT(resumee->state != DUK_HTHREAD_STATE_INACTIVE ||
66402 		           (resumee->valstack_top == resumee->valstack + 1 &&
66403 		            DUK_TVAL_IS_OBJECT(resumee->valstack_top - 1) &&
66404 		            DUK_HOBJECT_IS_COMPILEDFUNCTION(DUK_TVAL_GET_OBJECT(resumee->valstack_top - 1))));
66405 
66406 		if (thr->heap->lj.iserror) {
66407 			/*
66408 			 *  Throw the error in the resumed thread's context; the
66409 			 *  error value is pushed onto the resumee valstack.
66410 			 *
66411 			 *  Note: the callstack of the target may empty in this case
66412 			 *  too (i.e. the target thread has never been resumed).  The
66413 			 *  value stack will contain the initial function in that case,
66414 			 *  which we simply ignore.
66415 			 */
66416 
66417 			resumee->resumer = thr;
66418 			resumee->state = DUK_HTHREAD_STATE_RUNNING;
66419 			thr->state = DUK_HTHREAD_STATE_RESUMED;
66420 			DUK_HEAP_SWITCH_THREAD(thr->heap, resumee);
66421 			thr = resumee;
66422 
66423 			thr->heap->lj.type = DUK_LJ_TYPE_THROW;
66424 
66425 			/* thr->heap->lj.value1 is already the value to throw */
66426 			/* thr->heap->lj.value2 is 'thread', will be wiped out at the end */
66427 
66428 			DUK_ASSERT(thr->heap->lj.iserror);  /* already set */
66429 
66430 			DUK_DD(DUK_DDPRINT("-> resume with an error, converted to a throw in the resumee, propagate"));
66431 			goto check_longjmp;
66432 		} else if (resumee->state == DUK_HTHREAD_STATE_YIELDED) {
66433 			act_idx = resumee->callstack_top - 2;  /* Ecmascript function */
66434 			DUK_ASSERT_DISABLE(resumee->callstack[act_idx].idx_retval >= 0);  /* unsigned */
66435 
66436 			tv = resumee->valstack + resumee->callstack[act_idx].idx_retval;  /* return value from Duktape.Thread.yield() */
66437 			DUK_ASSERT(tv >= resumee->valstack && tv < resumee->valstack_top);
66438 			tv2 = &thr->heap->lj.value1;
66439 			DUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv2);  /* side effects */
66440 
66441 			duk_hthread_callstack_unwind(resumee, act_idx + 1);  /* unwind to 'yield' caller */
66442 
66443 			/* no need to unwind catchstack */
66444 
66445 			duk__reconfig_valstack_ecma_return(resumee, act_idx);
66446 
66447 			resumee->resumer = thr;
66448 			resumee->state = DUK_HTHREAD_STATE_RUNNING;
66449 			thr->state = DUK_HTHREAD_STATE_RESUMED;
66450 			DUK_HEAP_SWITCH_THREAD(thr->heap, resumee);
66451 #if 0
66452 			thr = resumee;  /* not needed, as we exit right away */
66453 #endif
66454 			DUK_DD(DUK_DDPRINT("-> resume with a value, restart execution in resumee"));
66455 			retval = DUK__LONGJMP_RESTART;
66456 			goto wipe_and_return;
66457 		} else {
66458 			duk_small_uint_t call_flags;
66459 			duk_bool_t setup_rc;
66460 
66461 			/* resumee: [... initial_func]  (currently actually: [initial_func]) */
66462 
66463 			duk_push_undefined((duk_context *) resumee);
66464 			tv = &thr->heap->lj.value1;
66465 			duk_push_tval((duk_context *) resumee, tv);
66466 
66467 			/* resumee: [... initial_func undefined(= this) resume_value ] */
66468 
66469 			call_flags = DUK_CALL_FLAG_IS_RESUME;  /* is resume, not a tail call */
66470 
66471 			setup_rc = duk_handle_ecma_call_setup(resumee,
66472 			                                      1,              /* num_stack_args */
66473 			                                      call_flags);    /* call_flags */
66474 			if (setup_rc == 0) {
66475 				/* Shouldn't happen but check anyway. */
66476 				DUK_ERROR_INTERNAL_DEFMSG(thr);
66477 			}
66478 
66479 			resumee->resumer = thr;
66480 			resumee->state = DUK_HTHREAD_STATE_RUNNING;
66481 			thr->state = DUK_HTHREAD_STATE_RESUMED;
66482 			DUK_HEAP_SWITCH_THREAD(thr->heap, resumee);
66483 #if 0
66484 			thr = resumee;  /* not needed, as we exit right away */
66485 #endif
66486 			DUK_DD(DUK_DDPRINT("-> resume with a value, restart execution in resumee"));
66487 			retval = DUK__LONGJMP_RESTART;
66488 			goto wipe_and_return;
66489 		}
66490 		DUK_UNREACHABLE();
66491 		break;  /* never here */
66492 	}
66493 
66494 	case DUK_LJ_TYPE_YIELD: {
66495 		/*
66496 		 *  Currently only allowed only if yielding thread has only
66497 		 *  Ecmascript activations (except for the Duktape.Thread.yield()
66498 		 *  call at the callstack top) and none of them constructor
66499 		 *  calls.
66500 		 *
66501 		 *  This excludes the 'entry' thread which will always have
66502 		 *  a preventcount > 0.
66503 		 */
66504 
66505 		duk_hthread *resumer;
66506 
66507 		/* duk_bi_duk_object_yield() and duk_bi_duk_object_resume() ensure all of these are met */
66508 
66509 		DUK_ASSERT(thr != entry_thread);                                                                             /* Duktape.Thread.yield() should prevent */
66510 		DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);                                                         /* unchanged from Duktape.Thread.yield() */
66511 		DUK_ASSERT(thr->callstack_top >= 2);                                                                         /* Ecmascript activation + Duktape.Thread.yield() activation */
66512 		DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 1) != NULL &&
66513 		           DUK_HOBJECT_IS_NATIVEFUNCTION(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 1)) &&
66514 		           ((duk_hnativefunction *) DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 1))->func == duk_bi_thread_yield);
66515 		DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 2) != NULL &&
66516 		           DUK_HOBJECT_IS_COMPILEDFUNCTION(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 2)));      /* an Ecmascript function */
66517 		DUK_ASSERT_DISABLE((thr->callstack + thr->callstack_top - 2)->idx_retval >= 0);                              /* unsigned */
66518 
66519 		resumer = thr->resumer;
66520 
66521 		DUK_ASSERT(resumer != NULL);
66522 		DUK_ASSERT(resumer->state == DUK_HTHREAD_STATE_RESUMED);                                                     /* written by a previous RESUME handling */
66523 		DUK_ASSERT(resumer->callstack_top >= 2);                                                                     /* Ecmascript activation + Duktape.Thread.resume() activation */
66524 		DUK_ASSERT(DUK_ACT_GET_FUNC(resumer->callstack + resumer->callstack_top - 1) != NULL &&
66525 		           DUK_HOBJECT_IS_NATIVEFUNCTION(DUK_ACT_GET_FUNC(resumer->callstack + resumer->callstack_top - 1)) &&
66526 		           ((duk_hnativefunction *) DUK_ACT_GET_FUNC(resumer->callstack + resumer->callstack_top - 1))->func == duk_bi_thread_resume);
66527 		DUK_ASSERT(DUK_ACT_GET_FUNC(resumer->callstack + resumer->callstack_top - 2) != NULL &&
66528 		           DUK_HOBJECT_IS_COMPILEDFUNCTION(DUK_ACT_GET_FUNC(resumer->callstack + resumer->callstack_top - 2)));        /* an Ecmascript function */
66529 		DUK_ASSERT_DISABLE((resumer->callstack + resumer->callstack_top - 2)->idx_retval >= 0);                      /* unsigned */
66530 
66531 		if (thr->heap->lj.iserror) {
66532 			thr->state = DUK_HTHREAD_STATE_YIELDED;
66533 			thr->resumer = NULL;
66534 			resumer->state = DUK_HTHREAD_STATE_RUNNING;
66535 			DUK_HEAP_SWITCH_THREAD(thr->heap, resumer);
66536 			thr = resumer;
66537 
66538 			thr->heap->lj.type = DUK_LJ_TYPE_THROW;
66539 			/* lj.value1 is already set */
66540 			DUK_ASSERT(thr->heap->lj.iserror);  /* already set */
66541 
66542 			DUK_DD(DUK_DDPRINT("-> yield an error, converted to a throw in the resumer, propagate"));
66543 			goto check_longjmp;
66544 		} else {
66545 			duk__handle_yield(thr, resumer, resumer->callstack_top - 2, &thr->heap->lj.value1);
66546 
66547 			thr->state = DUK_HTHREAD_STATE_YIELDED;
66548 			thr->resumer = NULL;
66549 			resumer->state = DUK_HTHREAD_STATE_RUNNING;
66550 			DUK_HEAP_SWITCH_THREAD(thr->heap, resumer);
66551 #if 0
66552 			thr = resumer;  /* not needed, as we exit right away */
66553 #endif
66554 
66555 			DUK_DD(DUK_DDPRINT("-> yield a value, restart execution in resumer"));
66556 			retval = DUK__LONGJMP_RESTART;
66557 			goto wipe_and_return;
66558 		}
66559 		DUK_UNREACHABLE();
66560 		break;  /* never here */
66561 	}
66562 
66563 	case DUK_LJ_TYPE_THROW: {
66564 		/*
66565 		 *  Three possible outcomes:
66566 		 *    * A try or finally catcher is found => resume there.
66567 		 *      (or)
66568 		 *    * The error propagates to the bytecode executor entry
66569 		 *      level (and we're in the entry thread) => rethrow
66570 		 *      with a new longjmp(), after restoring the previous
66571 		 *      catchpoint.
66572 		 *    * The error is not caught in the current thread, so
66573 		 *      the thread finishes with an error.  This works like
66574 		 *      a yielded error, except that the thread is finished
66575 		 *      and can no longer be resumed.  (There is always a
66576 		 *      resumer in this case.)
66577 		 *
66578 		 *  Note: until we hit the entry level, there can only be
66579 		 *  Ecmascript activations.
66580 		 */
66581 
66582 		duk_catcher *cat;
66583 		duk_hthread *resumer;
66584 
66585 		cat = thr->catchstack + thr->catchstack_top - 1;
66586 		while (cat >= thr->catchstack) {
66587 			if (thr == entry_thread &&
66588 			    cat->callstack_index < entry_callstack_index) {
66589 				/* entry level reached */
66590 				break;
66591 			}
66592 
66593 			if (DUK_CAT_HAS_CATCH_ENABLED(cat)) {
66594 				DUK_ASSERT(DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_TCF);
66595 
66596 				duk__handle_catch(thr,
66597 				                  cat - thr->catchstack,
66598 				                  &thr->heap->lj.value1,
66599 				                  DUK_LJ_TYPE_THROW);
66600 
66601 				DUK_DD(DUK_DDPRINT("-> throw caught by a 'catch' clause, restart execution"));
66602 				retval = DUK__LONGJMP_RESTART;
66603 				goto wipe_and_return;
66604 			}
66605 
66606 			if (DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
66607 				DUK_ASSERT(DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_TCF);
66608 				DUK_ASSERT(!DUK_CAT_HAS_CATCH_ENABLED(cat));
66609 
66610 				duk__handle_finally(thr,
66611 				                    cat - thr->catchstack,
66612 				                    &thr->heap->lj.value1,
66613 				                    DUK_LJ_TYPE_THROW);
66614 
66615 				DUK_DD(DUK_DDPRINT("-> throw caught by a 'finally' clause, restart execution"));
66616 				retval = DUK__LONGJMP_RESTART;
66617 				goto wipe_and_return;
66618 			}
66619 
66620 			cat--;
66621 		}
66622 
66623 		if (thr == entry_thread) {
66624 			/* not caught by anything before entry level; rethrow and let the
66625 			 * final catcher unwind everything
66626 			 */
66627 #if 0
66628 			duk_hthread_catchstack_unwind(thr, (cat - thr->catchstack) + 1);  /* leave 'cat' as top catcher (also works if catchstack exhausted) */
66629 			duk_hthread_callstack_unwind(thr, entry_callstack_index + 1);
66630 
66631 #endif
66632 			DUK_D(DUK_DPRINT("-> throw propagated up to entry level, rethrow and exit bytecode executor"));
66633 			retval = DUK__LONGJMP_RETHROW;
66634 			goto just_return;
66635 			/* Note: MUST NOT wipe_and_return here, as heap->lj must remain intact */
66636 		}
66637 
66638 		DUK_DD(DUK_DDPRINT("-> throw not caught by current thread, yield error to resumer and recheck longjmp"));
66639 
66640 		/* not caught by current thread, thread terminates (yield error to resumer);
66641 		 * note that this may cause a cascade if the resumer terminates with an uncaught
66642 		 * exception etc (this is OK, but needs careful testing)
66643 		 */
66644 
66645 		DUK_ASSERT(thr->resumer != NULL);
66646 		DUK_ASSERT(thr->resumer->callstack_top >= 2);  /* Ecmascript activation + Duktape.Thread.resume() activation */
66647 		DUK_ASSERT(DUK_ACT_GET_FUNC(thr->resumer->callstack + thr->resumer->callstack_top - 1) != NULL &&
66648 		           DUK_HOBJECT_IS_NATIVEFUNCTION(DUK_ACT_GET_FUNC(thr->resumer->callstack + thr->resumer->callstack_top - 1)) &&
66649 		           ((duk_hnativefunction *) DUK_ACT_GET_FUNC(thr->resumer->callstack + thr->resumer->callstack_top - 1))->func == duk_bi_thread_resume);  /* Duktape.Thread.resume() */
66650 		DUK_ASSERT(DUK_ACT_GET_FUNC(thr->resumer->callstack + thr->resumer->callstack_top - 2) != NULL &&
66651 		           DUK_HOBJECT_IS_COMPILEDFUNCTION(DUK_ACT_GET_FUNC(thr->resumer->callstack + thr->resumer->callstack_top - 2)));  /* an Ecmascript function */
66652 
66653 		resumer = thr->resumer;
66654 
66655 		/* reset longjmp */
66656 
66657 		DUK_ASSERT(thr->heap->lj.type == DUK_LJ_TYPE_THROW);  /* already set */
66658 		/* lj.value1 already set */
66659 
66660 		duk_hthread_terminate(thr);  /* updates thread state, minimizes its allocations */
66661 		DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_TERMINATED);
66662 
66663 		thr->resumer = NULL;
66664 		resumer->state = DUK_HTHREAD_STATE_RUNNING;
66665 		DUK_HEAP_SWITCH_THREAD(thr->heap, resumer);
66666 		thr = resumer;
66667 		goto check_longjmp;
66668 	}
66669 
66670 	case DUK_LJ_TYPE_BREAK:  /* pseudotypes, not used in actual longjmps */
66671 	case DUK_LJ_TYPE_CONTINUE:
66672 	case DUK_LJ_TYPE_RETURN:
66673 	case DUK_LJ_TYPE_NORMAL:
66674 	default: {
66675 		/* should never happen, but be robust */
66676 		DUK_D(DUK_DPRINT("caught unknown longjmp type %ld, treat as internal error", (long) thr->heap->lj.type));
66677 		goto convert_to_internal_error;
66678 	}
66679 
66680 	}  /* end switch */
66681 
66682 	DUK_UNREACHABLE();
66683 
66684  wipe_and_return:
66685 	/* this is not strictly necessary, but helps debugging */
66686 	thr->heap->lj.type = DUK_LJ_TYPE_UNKNOWN;
66687 	thr->heap->lj.iserror = 0;
66688 
66689 	DUK_TVAL_SET_UNDEFINED_UPDREF(thr, &thr->heap->lj.value1);  /* side effects */
66690 	DUK_TVAL_SET_UNDEFINED_UPDREF(thr, &thr->heap->lj.value2);  /* side effects */
66691 
66692  just_return:
66693 	return retval;
66694 
66695  convert_to_internal_error:
66696 	/* This could also be thrown internally (set the error, goto check_longjmp),
66697 	 * but it's better for internal errors to bubble outwards so that we won't
66698 	 * infinite loop in this catchpoint.
66699 	 */
66700 	DUK_ERROR_INTERNAL_DEFMSG(thr);
66701 	DUK_UNREACHABLE();
66702 	return retval;
66703 }
66704 
66705 /* Handle a BREAK/CONTINUE opcode.  Avoid using longjmp() for BREAK/CONTINUE
66706  * handling because it has a measurable performance impact in ordinary
66707  * environments and an extreme impact in Emscripten (GH-342).
66708  */
66709 DUK_LOCAL void duk__handle_break_or_continue(duk_hthread *thr,
66710                                              duk_uint_t label_id,
66711                                              duk_small_uint_t lj_type) {
66712 	duk_catcher *cat;
66713 	duk_size_t orig_callstack_index;
66714 
66715 	DUK_ASSERT(thr != NULL);
66716 
66717 	/*
66718 	 *  Find a matching label catcher or 'finally' catcher in
66719 	 *  the same function.
66720 	 *
66721 	 *  A label catcher must always exist and will match unless
66722 	 *  a 'finally' captures the break/continue first.  It is the
66723 	 *  compiler's responsibility to ensure that labels are used
66724 	 *  correctly.
66725 	 */
66726 
66727 	/* Note: thr->catchstack_top may be 0, so that cat < thr->catchstack
66728 	 * initially.  This is OK and intended.
66729 	 */
66730 	cat = thr->catchstack + thr->catchstack_top - 1;
66731 	DUK_ASSERT(thr->callstack_top > 0);
66732 	orig_callstack_index = thr->callstack_top - 1;
66733 
66734 	DUK_DDD(DUK_DDDPRINT("handling break/continue with label=%ld, callstack index=%ld",
66735 	                     (long) label_id, (long) cat->callstack_index));
66736 
66737 	while (cat >= thr->catchstack) {
66738 		if (cat->callstack_index != orig_callstack_index) {
66739 			break;
66740 		}
66741 		DUK_DDD(DUK_DDDPRINT("considering catcher %ld: type=%ld label=%ld",
66742 		                     (long) (cat - thr->catchstack),
66743 		                     (long) DUK_CAT_GET_TYPE(cat),
66744 		                     (long) DUK_CAT_GET_LABEL(cat)));
66745 
66746 		if (DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_TCF &&
66747 		    DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
66748 			duk_size_t cat_idx;
66749 			duk_tval tv_tmp;
66750 
66751 			cat_idx = (duk_size_t) (cat - thr->catchstack);  /* get before side effects */
66752 
66753 			DUK_TVAL_SET_FASTINT_U32(&tv_tmp, (duk_uint32_t) label_id);
66754 			duk__handle_finally(thr, cat_idx, &tv_tmp, lj_type);
66755 
66756 			DUK_DD(DUK_DDPRINT("-> break/continue caught by 'finally', restart execution"));
66757 			return;
66758 		}
66759 		if (DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_LABEL &&
66760 		    (duk_uint_t) DUK_CAT_GET_LABEL(cat) == label_id) {
66761 			duk_size_t cat_idx;
66762 
66763 			cat_idx = (duk_size_t) (cat - thr->catchstack);
66764 			duk__handle_label(thr, cat_idx, lj_type);
66765 
66766 			DUK_DD(DUK_DDPRINT("-> break/continue caught by a label catcher (in the same function), restart execution"));
66767 			return;
66768 		}
66769 		cat--;
66770 	}
66771 
66772 	/* should never happen, but be robust */
66773 	DUK_D(DUK_DPRINT("-> break/continue not caught by anything in the current function (should never happen), throw internal error"));
66774 	DUK_ERROR_INTERNAL_DEFMSG(thr);
66775 	return;
66776 }
66777 
66778 /* Handle a RETURN opcode.  Avoid using longjmp() for return handling because
66779  * it has a measurable performance impact in ordinary environments and an extreme
66780  * impact in Emscripten (GH-342).  Return value is on value stack top.
66781  */
66782 DUK_LOCAL duk_small_uint_t duk__handle_return(duk_hthread *thr,
66783                                               duk_hthread *entry_thread,
66784                                               duk_size_t entry_callstack_top) {
66785 	duk_tval *tv1;
66786 	duk_tval *tv2;
66787 	duk_hthread *resumer;
66788 	duk_catcher *cat;
66789 	duk_size_t new_cat_top;
66790 	duk_size_t orig_callstack_index;
66791 
66792 	/* We can directly access value stack here. */
66793 
66794 	DUK_ASSERT(thr != NULL);
66795 	DUK_ASSERT(entry_thread != NULL);
66796 	DUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);
66797 	tv1 = thr->valstack_top - 1;
66798 	DUK_TVAL_CHKFAST_INPLACE(tv1);  /* fastint downgrade check for return values */
66799 
66800 	/*
66801 	 *  Four possible outcomes:
66802 	 *
66803 	 *    1. A 'finally' in the same function catches the 'return'.
66804 	 *       It may continue to propagate when 'finally' is finished,
66805 	 *       or it may be neutralized by 'finally' (both handled by
66806 	 *       ENDFIN).
66807 	 *
66808 	 *    2. The return happens at the entry level of the bytecode
66809 	 *       executor, so return from the executor (in C stack).
66810 	 *
66811 	 *    3. There is a calling (Ecmascript) activation in the call
66812 	 *       stack => return to it, in the same executor instance.
66813 	 *
66814 	 *    4. There is no calling activation, and the thread is
66815 	 *       terminated.  There is always a resumer in this case,
66816 	 *       which gets the return value similarly to a 'yield'
66817 	 *       (except that the current thread can no longer be
66818 	 *       resumed).
66819 	 */
66820 
66821 	DUK_ASSERT(thr != NULL);
66822 	DUK_ASSERT(thr->callstack_top >= 1);
66823 	DUK_ASSERT(thr->catchstack != NULL);
66824 
66825 	/* XXX: does not work if thr->catchstack is NULL */
66826 	/* XXX: does not work if thr->catchstack is allocated but lowest pointer */
66827 
66828 	cat = thr->catchstack + thr->catchstack_top - 1;  /* may be < thr->catchstack initially */
66829 	DUK_ASSERT(thr->callstack_top > 0);  /* ensures callstack_top - 1 >= 0 */
66830 	orig_callstack_index = thr->callstack_top - 1;
66831 
66832 	while (cat >= thr->catchstack) {
66833 		if (cat->callstack_index != orig_callstack_index) {
66834 			break;
66835 		}
66836 		if (DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_TCF &&
66837 		    DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
66838 			duk_size_t cat_idx;
66839 
66840 			cat_idx = (duk_size_t) (cat - thr->catchstack);  /* get before side effects */
66841 
66842 			DUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);
66843 			duk__handle_finally(thr, cat_idx, thr->valstack_top - 1, DUK_LJ_TYPE_RETURN);
66844 
66845 			DUK_DD(DUK_DDPRINT("-> return caught by 'finally', restart execution"));
66846 			return DUK__RETHAND_RESTART;
66847 		}
66848 		cat--;
66849 	}
66850 	/* If out of catchstack, cat = thr->catchstack - 1;
66851 	 * new_cat_top will be 0 in that case.
66852 	 */
66853 	new_cat_top = (duk_size_t) ((cat + 1) - thr->catchstack);
66854 	cat = NULL;  /* avoid referencing, invalidated */
66855 
66856 	DUK_DDD(DUK_DDDPRINT("no catcher in catch stack, return to calling activation / yield"));
66857 
66858 	if (thr == entry_thread &&
66859 	    thr->callstack_top == entry_callstack_top) {
66860 		/* Return to the bytecode executor caller which will unwind stacks.
66861 		 * Return value is already on the stack top: [ ... retval ].
66862 		 */
66863 
66864 		/* XXX: could unwind catchstack here, so that call handling
66865 		 * didn't need to do that?
66866 		 */
66867 		DUK_DDD(DUK_DDDPRINT("-> return propagated up to entry level, exit bytecode executor"));
66868 		return DUK__RETHAND_FINISHED;
66869 	}
66870 
66871 	if (thr->callstack_top >= 2) {
66872 		/* There is a caller; it MUST be an Ecmascript caller (otherwise it would
66873 		 * match entry level check)
66874 		 */
66875 
66876 		DUK_DDD(DUK_DDDPRINT("return to Ecmascript caller, idx_retval=%ld, lj_value1=%!T",
66877 		                     (long) (thr->callstack + thr->callstack_top - 2)->idx_retval,
66878 		                     (duk_tval *) &thr->heap->lj.value1));
66879 
66880 		DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 2)));   /* must be ecmascript */
66881 
66882 		tv1 = thr->valstack + (thr->callstack + thr->callstack_top - 2)->idx_retval;
66883 		DUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);
66884 		tv2 = thr->valstack_top - 1;
66885 		DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2);  /* side effects */
66886 
66887 		DUK_DDD(DUK_DDDPRINT("return value at idx_retval=%ld is %!T",
66888 		                     (long) (thr->callstack + thr->callstack_top - 2)->idx_retval,
66889 		                     (duk_tval *) (thr->valstack + (thr->callstack + thr->callstack_top - 2)->idx_retval)));
66890 
66891 		duk_hthread_catchstack_unwind(thr, new_cat_top);  /* leave 'cat' as top catcher (also works if catchstack exhausted) */
66892 		duk_hthread_callstack_unwind(thr, thr->callstack_top - 1);
66893 		duk__reconfig_valstack_ecma_return(thr, thr->callstack_top - 1);
66894 
66895 		DUK_DD(DUK_DDPRINT("-> return not intercepted, restart execution in caller"));
66896 		return DUK__RETHAND_RESTART;
66897 	}
66898 
66899 	DUK_DD(DUK_DDPRINT("no calling activation, thread finishes (similar to yield)"));
66900 
66901 	DUK_ASSERT(thr->resumer != NULL);
66902 	DUK_ASSERT(thr->resumer->callstack_top >= 2);  /* Ecmascript activation + Duktape.Thread.resume() activation */
66903 	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->resumer->callstack + thr->resumer->callstack_top - 1) != NULL &&
66904 	           DUK_HOBJECT_IS_NATIVEFUNCTION(DUK_ACT_GET_FUNC(thr->resumer->callstack + thr->resumer->callstack_top - 1)) &&
66905 	           ((duk_hnativefunction *) DUK_ACT_GET_FUNC(thr->resumer->callstack + thr->resumer->callstack_top - 1))->func == duk_bi_thread_resume);  /* Duktape.Thread.resume() */
66906 	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->resumer->callstack + thr->resumer->callstack_top - 2) != NULL &&
66907 	           DUK_HOBJECT_IS_COMPILEDFUNCTION(DUK_ACT_GET_FUNC(thr->resumer->callstack + thr->resumer->callstack_top - 2)));  /* an Ecmascript function */
66908 	DUK_ASSERT_DISABLE((thr->resumer->callstack + thr->resumer->callstack_top - 2)->idx_retval >= 0);                /* unsigned */
66909 	DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);
66910 	DUK_ASSERT(thr->resumer->state == DUK_HTHREAD_STATE_RESUMED);
66911 
66912 	resumer = thr->resumer;
66913 
66914 	/* Share yield longjmp handler. */
66915 	DUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);
66916 	duk__handle_yield(thr, resumer, resumer->callstack_top - 2, thr->valstack_top - 1);
66917 
66918 	duk_hthread_terminate(thr);  /* updates thread state, minimizes its allocations */
66919 	DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_TERMINATED);
66920 
66921 	thr->resumer = NULL;
66922 	resumer->state = DUK_HTHREAD_STATE_RUNNING;
66923 	DUK_HEAP_SWITCH_THREAD(thr->heap, resumer);
66924 #if 0
66925 	thr = resumer;  /* not needed */
66926 #endif
66927 
66928 	DUK_DD(DUK_DDPRINT("-> return not caught, thread terminated; handle like yield, restart execution in resumer"));
66929 	return DUK__RETHAND_RESTART;
66930 }
66931 
66932 /*
66933  *  Executor interrupt handling
66934  *
66935  *  The handler is called whenever the interrupt countdown reaches zero
66936  *  (or below).  The handler must perform whatever checks are activated,
66937  *  e.g. check for cumulative step count to impose an execution step
66938  *  limit or check for breakpoints or other debugger interaction.
66939  *
66940  *  When the actions are done, the handler must reinit the interrupt
66941  *  init and counter values.  The 'init' value must indicate how many
66942  *  bytecode instructions are executed before the next interrupt.  The
66943  *  counter must interface with the bytecode executor loop.  Concretely,
66944  *  the new init value is normally one higher than the new counter value.
66945  *  For instance, to execute exactly one bytecode instruction the init
66946  *  value is set to 1 and the counter to 0.  If an error is thrown by the
66947  *  interrupt handler, the counters are set to the same value (e.g. both
66948  *  to 0 to cause an interrupt when the next bytecode instruction is about
66949  *  to be executed after error handling).
66950  *
66951  *  Maintaining the init/counter value properly is important for accurate
66952  *  behavior.  For instance, executor step limit needs a cumulative step
66953  *  count which is simply computed as a sum of 'init' values.  This must
66954  *  work accurately even when single stepping.
66955  */
66956 
66957 #if defined(DUK_USE_INTERRUPT_COUNTER)
66958 
66959 #define DUK__INT_NOACTION    0    /* no specific action, resume normal execution */
66960 #define DUK__INT_RESTART     1    /* must "goto restart_execution", e.g. breakpoints changed */
66961 
66962 #if defined(DUK_USE_DEBUGGER_SUPPORT)
66963 DUK_LOCAL void duk__interrupt_handle_debugger(duk_hthread *thr, duk_bool_t *out_immediate, duk_small_uint_t *out_interrupt_retval) {
66964 	duk_context *ctx;
66965 	duk_activation *act;
66966 	duk_breakpoint *bp;
66967 	duk_breakpoint **bp_active;
66968 	duk_uint_fast32_t line = 0;
66969 	duk_bool_t process_messages;
66970 	duk_bool_t processed_messages = 0;
66971 
66972 	DUK_ASSERT(thr->heap->dbg_processing == 0);  /* don't re-enter e.g. during Eval */
66973 
66974 	ctx = (duk_context *) thr;
66975 	act = thr->callstack + thr->callstack_top - 1;
66976 
66977 	/* It might seem that replacing 'thr->heap' with just 'heap' below
66978 	 * might be a good idea, but it increases code size slightly
66979 	 * (probably due to unnecessary spilling) at least on x64.
66980 	 */
66981 
66982 	/*
66983 	 *  Breakpoint and step state checks
66984 	 */
66985 
66986 	if (act->flags & DUK_ACT_FLAG_BREAKPOINT_ACTIVE ||
66987 	    (thr->heap->dbg_step_thread == thr &&
66988 	     thr->heap->dbg_step_csindex == thr->callstack_top - 1)) {
66989 		line = duk_debug_curr_line(thr);
66990 
66991 		if (act->prev_line != line) {
66992 			/* Stepped?  Step out is handled by callstack unwind. */
66993 			if ((thr->heap->dbg_step_type == DUK_STEP_TYPE_INTO ||
66994 			     thr->heap->dbg_step_type == DUK_STEP_TYPE_OVER) &&
66995 			    (thr->heap->dbg_step_thread == thr) &&
66996 			    (thr->heap->dbg_step_csindex == thr->callstack_top - 1) &&
66997 			    (line != thr->heap->dbg_step_startline)) {
66998 				DUK_D(DUK_DPRINT("STEP STATE TRIGGERED PAUSE at line %ld",
66999 				                 (long) line));
67000 
67001 				DUK_HEAP_SET_PAUSED(thr->heap);
67002 			}
67003 
67004 			/* Check for breakpoints only on line transition.
67005 			 * Breakpoint is triggered when we enter the target
67006 			 * line from a different line, and the previous line
67007 			 * was within the same function.
67008 			 *
67009 			 * This condition is tricky: the condition used to be
67010 			 * that transition to -or across- the breakpoint line
67011 			 * triggered the breakpoint.  This seems intuitively
67012 			 * better because it handles breakpoints on lines with
67013 			 * no emitted opcodes; but this leads to the issue
67014 			 * described in: https://github.com/svaarala/duktape/issues/263.
67015 			 */
67016 			bp_active = thr->heap->dbg_breakpoints_active;
67017 			for (;;) {
67018 				bp = *bp_active++;
67019 				if (bp == NULL) {
67020 					break;
67021 				}
67022 
67023 				DUK_ASSERT(bp->filename != NULL);
67024 				if (act->prev_line != bp->line && line == bp->line) {
67025 					DUK_D(DUK_DPRINT("BREAKPOINT TRIGGERED at %!O:%ld",
67026 					                 (duk_heaphdr *) bp->filename, (long) bp->line));
67027 
67028 					DUK_HEAP_SET_PAUSED(thr->heap);
67029 				}
67030 			}
67031 		} else {
67032 			;
67033 		}
67034 
67035 		act->prev_line = line;
67036 	}
67037 
67038 	/*
67039 	 *  Rate limit check for sending status update or peeking into
67040 	 *  the debug transport.  Both can be expensive operations that
67041 	 *  we don't want to do on every opcode.
67042 	 *
67043 	 *  Making sure the interval remains reasonable on a wide variety
67044 	 *  of targets and bytecode is difficult without a timestamp, so
67045 	 *  we use a Date-provided timestamp for the rate limit check.
67046 	 *  But since it's also expensive to get a timestamp, a bytecode
67047 	 *  counter is used to rate limit getting timestamps.
67048 	 */
67049 
67050 	process_messages = 0;
67051 	if (thr->heap->dbg_state_dirty || thr->heap->dbg_paused || thr->heap->dbg_detaching) {
67052 		/* Enter message processing loop for sending Status notifys and
67053 		 * to finish a pending detach.
67054 		 */
67055 		process_messages = 1;
67056 	}
67057 
67058 	/* XXX: remove heap->dbg_exec_counter, use heap->inst_count_interrupt instead? */
67059 	thr->heap->dbg_exec_counter += thr->interrupt_init;
67060 	if (thr->heap->dbg_exec_counter - thr->heap->dbg_last_counter >= DUK_HEAP_DBG_RATELIMIT_OPCODES) {
67061 		/* Overflow of the execution counter is fine and doesn't break
67062 		 * anything here.
67063 		 */
67064 
67065 		duk_double_t now, diff_last;
67066 
67067 		thr->heap->dbg_last_counter = thr->heap->dbg_exec_counter;
67068 		now = DUK_USE_DATE_GET_NOW(ctx);
67069 
67070 		diff_last = now - thr->heap->dbg_last_time;
67071 		if (diff_last < 0.0 || diff_last >= (duk_double_t) DUK_HEAP_DBG_RATELIMIT_MILLISECS) {
67072 			/* Negative value checked so that a "time jump" works
67073 			 * reasonably.
67074 			 *
67075 			 * Same interval is now used for status sending and
67076 			 * peeking.
67077 			 */
67078 
67079 			thr->heap->dbg_last_time = now;
67080 			thr->heap->dbg_state_dirty = 1;
67081 			process_messages = 1;
67082 		}
67083 	}
67084 
67085 	/*
67086 	 *  Process messages and send status if necessary.
67087 	 *
67088 	 *  If we're paused, we'll block for new messages.  If we're not
67089 	 *  paused, we'll process anything we can peek but won't block
67090 	 *  for more.  Detach (and re-attach) handling is all localized
67091 	 *  to duk_debug_process_messages() too.
67092 	 *
67093 	 *  Debugger writes outside the message loop may cause debugger
67094 	 *  detach1 phase to run, after which dbg_read_cb == NULL and
67095 	 *  dbg_detaching != 0.  The message loop will finish the detach
67096 	 *  by running detach2 phase, so enter the message loop also when
67097 	 *  detaching.
67098 	 */
67099 
67100 	act = NULL;  /* may be changed */
67101 	if (process_messages) {
67102 		DUK_ASSERT(thr->heap->dbg_processing == 0);
67103 		processed_messages = duk_debug_process_messages(thr, 0 /*no_block*/);
67104 		DUK_ASSERT(thr->heap->dbg_processing == 0);
67105 	}
67106 
67107 	/* Continue checked execution if there are breakpoints or we're stepping.
67108 	 * Also use checked execution if paused flag is active - it shouldn't be
67109 	 * because the debug message loop shouldn't terminate if it was.  Step out
67110 	 * is handled by callstack unwind and doesn't need checked execution.
67111 	 * Note that debugger may have detached due to error or explicit request
67112 	 * above, so we must recheck attach status.
67113 	 */
67114 
67115 	if (DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap)) {
67116 		act = thr->callstack + thr->callstack_top - 1;  /* relookup, may have changed */
67117 		if (act->flags & DUK_ACT_FLAG_BREAKPOINT_ACTIVE ||
67118 		    ((thr->heap->dbg_step_type == DUK_STEP_TYPE_INTO ||
67119 		      thr->heap->dbg_step_type == DUK_STEP_TYPE_OVER) &&
67120 		     thr->heap->dbg_step_thread == thr &&
67121 		     thr->heap->dbg_step_csindex == thr->callstack_top - 1) ||
67122 		     thr->heap->dbg_paused) {
67123 			*out_immediate = 1;
67124 		}
67125 
67126 		/* If we processed any debug messages breakpoints may have
67127 		 * changed; restart execution to re-check active breakpoints.
67128 		 */
67129 		if (processed_messages) {
67130 			DUK_D(DUK_DPRINT("processed debug messages, restart execution to recheck possibly changed breakpoints"));
67131 			*out_interrupt_retval = DUK__INT_RESTART;
67132 		}
67133 	} else {
67134 		DUK_D(DUK_DPRINT("debugger became detached, resume normal execution"));
67135 	}
67136 }
67137 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
67138 
67139 DUK_LOCAL duk_small_uint_t duk__executor_interrupt(duk_hthread *thr) {
67140 	duk_int_t ctr;
67141 	duk_activation *act;
67142 	duk_hcompiledfunction *fun;
67143 	duk_bool_t immediate = 0;
67144 	duk_small_uint_t retval;
67145 
67146 	DUK_ASSERT(thr != NULL);
67147 	DUK_ASSERT(thr->heap != NULL);
67148 	DUK_ASSERT(thr->callstack != NULL);
67149 	DUK_ASSERT(thr->callstack_top > 0);
67150 
67151 #if defined(DUK_USE_DEBUG)
67152 	thr->heap->inst_count_interrupt += thr->interrupt_init;
67153 	DUK_DD(DUK_DDPRINT("execution interrupt, counter=%ld, init=%ld, "
67154 	                   "instruction counts: executor=%ld, interrupt=%ld",
67155 	                   (long) thr->interrupt_counter, (long) thr->interrupt_init,
67156 	                   (long) thr->heap->inst_count_exec, (long) thr->heap->inst_count_interrupt));
67157 #endif
67158 
67159 	retval = DUK__INT_NOACTION;
67160 	ctr = DUK_HTHREAD_INTCTR_DEFAULT;
67161 
67162 	/*
67163 	 *  Avoid nested calls.  Concretely this happens during debugging, e.g.
67164 	 *  when we eval() an expression.
67165 	 *
67166 	 *  Also don't interrupt if we're currently doing debug processing
67167 	 *  (which can be initiated outside the bytecode executor) as this
67168 	 *  may cause the debugger to be called recursively.  Check required
67169 	 *  for correct operation of throw intercept and other "exotic" halting
67170 	 * scenarios.
67171 	 */
67172 
67173 #if defined(DUK_USE_DEBUGGER_SUPPORT)
67174 	if (DUK_HEAP_HAS_INTERRUPT_RUNNING(thr->heap) || thr->heap->dbg_processing) {
67175 #else
67176 	if (DUK_HEAP_HAS_INTERRUPT_RUNNING(thr->heap)) {
67177 #endif
67178 		DUK_DD(DUK_DDPRINT("nested executor interrupt, ignoring"));
67179 
67180 		/* Set a high interrupt counter; the original executor
67181 		 * interrupt invocation will rewrite before exiting.
67182 		 */
67183 		thr->interrupt_init = ctr;
67184 		thr->interrupt_counter = ctr - 1;
67185 		return DUK__INT_NOACTION;
67186 	}
67187 	DUK_HEAP_SET_INTERRUPT_RUNNING(thr->heap);
67188 
67189 	act = thr->callstack + thr->callstack_top - 1;
67190 
67191 	fun = (duk_hcompiledfunction *) DUK_ACT_GET_FUNC(act);
67192 	DUK_ASSERT(DUK_HOBJECT_HAS_COMPILEDFUNCTION((duk_hobject *) fun));
67193 
67194 	DUK_UNREF(fun);
67195 
67196 #if defined(DUK_USE_EXEC_TIMEOUT_CHECK)
67197 	/*
67198 	 *  Execution timeout check
67199 	 */
67200 
67201 	if (DUK_USE_EXEC_TIMEOUT_CHECK(thr->heap->heap_udata)) {
67202 		/* Keep throwing an error whenever we get here.  The unusual values
67203 		 * are set this way because no instruction is ever executed, we just
67204 		 * throw an error until all try/catch/finally and other catchpoints
67205 		 * have been exhausted.  Duktape/C code gets control at each protected
67206 		 * call but whenever it enters back into Duktape the RangeError gets
67207 		 * raised.  User exec timeout check must consistently indicate a timeout
67208 		 * until we've fully bubbled out of Duktape.
67209 		 */
67210 		DUK_D(DUK_DPRINT("execution timeout, throwing a RangeError"));
67211 		thr->interrupt_init = 0;
67212 		thr->interrupt_counter = 0;
67213 		DUK_HEAP_CLEAR_INTERRUPT_RUNNING(thr->heap);
67214 		DUK_ERROR_RANGE(thr, "execution timeout");
67215 	}
67216 #endif  /* DUK_USE_EXEC_TIMEOUT_CHECK */
67217 
67218 #if defined(DUK_USE_DEBUGGER_SUPPORT)
67219 	if (!thr->heap->dbg_processing &&
67220 	    (thr->heap->dbg_read_cb != NULL || thr->heap->dbg_detaching)) {
67221 		/* Avoid recursive re-entry; enter when we're attached or
67222 		 * detaching (to finish off the pending detach).
67223 		 */
67224 		duk__interrupt_handle_debugger(thr, &immediate, &retval);
67225 		act = thr->callstack + thr->callstack_top - 1;  /* relookup if changed */
67226 		DUK_UNREF(act);  /* 'act' is no longer accessed, scanbuild fix */
67227 	}
67228 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
67229 
67230 	/*
67231 	 *  Update the interrupt counter
67232 	 */
67233 
67234 	if (immediate) {
67235 		/* Cause an interrupt after executing one instruction. */
67236 		ctr = 1;
67237 	}
67238 
67239 	/* The counter value is one less than the init value: init value should
67240 	 * indicate how many instructions are executed before interrupt.  To
67241 	 * execute 1 instruction (after interrupt handler return), counter must
67242 	 * be 0.
67243 	 */
67244 	DUK_ASSERT(ctr >= 1);
67245 	thr->interrupt_init = ctr;
67246 	thr->interrupt_counter = ctr - 1;
67247 	DUK_HEAP_CLEAR_INTERRUPT_RUNNING(thr->heap);
67248 
67249 	return retval;
67250 }
67251 #endif  /* DUK_USE_INTERRUPT_COUNTER */
67252 
67253 /*
67254  *  Debugger handling for executor restart
67255  *
67256  *  Check for breakpoints, stepping, etc, and figure out if we should execute
67257  *  in checked or normal mode.  Note that we can't do this when an activation
67258  *  is created, because breakpoint status (and stepping status) may change
67259  *  later, so we must recheck every time we're executing an activation.
67260  *  This primitive should be side effect free to avoid changes during check.
67261  */
67262 
67263 #if defined(DUK_USE_DEBUGGER_SUPPORT)
67264 DUK_LOCAL void duk__executor_recheck_debugger(duk_hthread *thr, duk_activation *act, duk_hcompiledfunction *fun) {
67265 	duk_heap *heap;
67266 	duk_tval *tv_tmp;
67267 	duk_hstring *filename;
67268 	duk_small_uint_t bp_idx;
67269 	duk_breakpoint **bp_active;
67270 
67271 	DUK_ASSERT(thr != NULL);
67272 	DUK_ASSERT(act != NULL);
67273 	DUK_ASSERT(fun != NULL);
67274 
67275 	heap = thr->heap;
67276 	bp_active = heap->dbg_breakpoints_active;
67277 	act->flags &= ~DUK_ACT_FLAG_BREAKPOINT_ACTIVE;
67278 
67279 	tv_tmp = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) fun, DUK_HTHREAD_STRING_FILE_NAME(thr));
67280 	if (tv_tmp && DUK_TVAL_IS_STRING(tv_tmp)) {
67281 		filename = DUK_TVAL_GET_STRING(tv_tmp);
67282 
67283 		/* Figure out all active breakpoints.  A breakpoint is
67284 		 * considered active if the current function's fileName
67285 		 * matches the breakpoint's fileName, AND there is no
67286 		 * inner function that has matching line numbers
67287 		 * (otherwise a breakpoint would be triggered both
67288 		 * inside and outside of the inner function which would
67289 		 * be confusing).  Example:
67290 		 *
67291 		 *     function foo() {
67292 		 *         print('foo');
67293 		 *         function bar() {    <-.  breakpoints in these
67294 		 *             print('bar');     |  lines should not affect
67295 		 *         }                   <-'  foo() execution
67296 		 *         bar();
67297 		 *     }
67298 		 *
67299 		 * We need a few things that are only available when
67300 		 * debugger support is enabled: (1) a line range for
67301 		 * each function, and (2) access to the function
67302 		 * template to access the inner functions (and their
67303 		 * line ranges).
67304 		 *
67305 		 * It's important to have a narrow match for active
67306 		 * breakpoints so that we don't enter checked execution
67307 		 * when that's not necessary.  For instance, if we're
67308 		 * running inside a certain function and there's
67309 		 * breakpoint outside in (after the call site), we
67310 		 * don't want to slow down execution of the function.
67311 		 */
67312 
67313 		for (bp_idx = 0; bp_idx < heap->dbg_breakpoint_count; bp_idx++) {
67314 			duk_breakpoint *bp = heap->dbg_breakpoints + bp_idx;
67315 			duk_hobject **funcs, **funcs_end;
67316 			duk_hcompiledfunction *inner_fun;
67317 			duk_bool_t bp_match;
67318 
67319 			if (bp->filename == filename &&
67320 			    bp->line >= fun->start_line && bp->line <= fun->end_line) {
67321 				bp_match = 1;
67322 				DUK_DD(DUK_DDPRINT("breakpoint filename and line match: "
67323 				                   "%s:%ld vs. %s (line %ld vs. %ld-%ld)",
67324 				                   DUK_HSTRING_GET_DATA(bp->filename),
67325 				                   (long) bp->line,
67326 				                   DUK_HSTRING_GET_DATA(filename),
67327 				                   (long) bp->line,
67328 				                   (long) fun->start_line,
67329 				                   (long) fun->end_line));
67330 
67331 				funcs = DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE(thr->heap, fun);
67332 				funcs_end = DUK_HCOMPILEDFUNCTION_GET_FUNCS_END(thr->heap, fun);
67333 				while (funcs != funcs_end) {
67334 					inner_fun = (duk_hcompiledfunction *) *funcs;
67335 					DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION((duk_hobject *) inner_fun));
67336 					if (bp->line >= inner_fun->start_line && bp->line <= inner_fun->end_line) {
67337 						DUK_DD(DUK_DDPRINT("inner function masks ('captures') breakpoint"));
67338 						bp_match = 0;
67339 						break;
67340 					}
67341 					funcs++;
67342 				}
67343 
67344 				if (bp_match) {
67345 					/* No need to check for size of bp_active list,
67346 					 * it's always larger than maximum number of
67347 					 * breakpoints.
67348 					 */
67349 					act->flags |= DUK_ACT_FLAG_BREAKPOINT_ACTIVE;
67350 					*bp_active = heap->dbg_breakpoints + bp_idx;
67351 					bp_active++;
67352 				}
67353 			}
67354 		}
67355 	}
67356 
67357 	*bp_active = NULL;  /* terminate */
67358 
67359 	DUK_DD(DUK_DDPRINT("ACTIVE BREAKPOINTS: %ld", (long) (bp_active - thr->heap->dbg_breakpoints_active)));
67360 
67361 	/* Force pause if we were doing "step into" in another activation. */
67362 	if (thr->heap->dbg_step_thread != NULL &&
67363 	    thr->heap->dbg_step_type == DUK_STEP_TYPE_INTO &&
67364 	    (thr->heap->dbg_step_thread != thr ||
67365 	     thr->heap->dbg_step_csindex != thr->callstack_top - 1)) {
67366 		DUK_D(DUK_DPRINT("STEP INTO ACTIVE, FORCE PAUSED"));
67367 		DUK_HEAP_SET_PAUSED(thr->heap);
67368 	}
67369 
67370 	/* Force interrupt right away if we're paused or in "checked mode".
67371 	 * Step out is handled by callstack unwind.
67372 	 */
67373 	if (act->flags & (DUK_ACT_FLAG_BREAKPOINT_ACTIVE) ||
67374 	    thr->heap->dbg_paused ||
67375 	    (thr->heap->dbg_step_type != DUK_STEP_TYPE_OUT &&
67376 	     thr->heap->dbg_step_csindex == thr->callstack_top - 1)) {
67377 		/* We'll need to interrupt early so recompute the init
67378 		 * counter to reflect the number of bytecode instructions
67379 		 * executed so that step counts for e.g. debugger rate
67380 		 * limiting are accurate.
67381 		 */
67382 		DUK_ASSERT(thr->interrupt_counter <= thr->interrupt_init);
67383 		thr->interrupt_init = thr->interrupt_init - thr->interrupt_counter;
67384 		thr->interrupt_counter = 0;
67385 	}
67386 }
67387 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
67388 
67389 /*
67390  *  Ecmascript bytecode executor.
67391  *
67392  *  Resume execution for the current thread from its current activation.
67393  *  Returns when execution would return from the entry level activation,
67394  *  leaving a single return value on top of the stack.  Function calls
67395  *  and thread resumptions are handled internally.  If an error occurs,
67396  *  a longjmp() with type DUK_LJ_TYPE_THROW is called on the entry level
67397  *  setjmp() jmpbuf.
67398  *
67399  *  Ecmascript function calls and coroutine resumptions are handled
67400  *  internally (by the outer executor function) without recursive C calls.
67401  *  Other function calls are handled using duk_handle_call(), increasing
67402  *  C recursion depth.
67403  *
67404  *  Abrupt completions (= long control tranfers) are handled either
67405  *  directly by reconfiguring relevant stacks and restarting execution,
67406  *  or via a longjmp.  Longjmp-free handling is preferable for performance
67407  *  (especially Emscripten performance), and is used for: break, continue,
67408  *  and return.
67409  *
67410  *  For more detailed notes, see doc/execution.rst.
67411  *
67412  *  Also see doc/code-issues.rst for discussion of setjmp(), longjmp(),
67413  *  and volatile.
67414  */
67415 
67416 /* Presence of 'fun' is config based, there's a marginal performance
67417  * difference and the best option is architecture dependent.
67418  */
67419 #if defined(DUK_USE_EXEC_FUN_LOCAL)
67420 #define DUK__FUN()          fun
67421 #else
67422 #define DUK__FUN()          ((duk_hcompiledfunction *) DUK_ACT_GET_FUNC((thr)->callstack + (thr)->callstack_top - 1))
67423 #endif
67424 #define DUK__STRICT()       (DUK_HOBJECT_HAS_STRICT((duk_hobject *) DUK__FUN()))
67425 
67426 /* Reg/const access macros: these are very footprint and performance sensitive
67427  * so modify with care.
67428  */
67429 #define DUK__REG(x)         (*(thr->valstack_bottom + (x)))
67430 #define DUK__REGP(x)        (thr->valstack_bottom + (x))
67431 #define DUK__CONST(x)       (*(consts + (x)))
67432 #define DUK__CONSTP(x)      (consts + (x))
67433 #if 0
67434 #define DUK__REGCONST(x)    ((x) < DUK_BC_REGLIMIT ? DUK__REG((x)) : DUK__CONST((x) - DUK_BC_REGLIMIT))
67435 #define DUK__REGCONSTP(x)   ((x) < DUK_BC_REGLIMIT ? DUK__REGP((x)) : DUK__CONSTP((x) - DUK_BC_REGLIMIT))
67436 #define DUK__REGCONST(x)    *((((x) < DUK_BC_REGLIMIT ? thr->valstack_bottom : consts2) + (x)))
67437 #define DUK__REGCONSTP(x)   (((x) < DUK_BC_REGLIMIT ? thr->valstack_bottom : consts2) + (x))
67438 #endif
67439 /* This macro works when a regconst field is 9 bits, [0,0x1ff].  Adding
67440  * DUK_LIKELY/DUK_UNLIKELY increases code footprint and doesn't seem to
67441  * improve performance on x64 (and actually harms performance in some tests).
67442  */
67443 #define DUK__RCISREG(x)     (((x) & 0x100) == 0)
67444 #define DUK__REGCONST(x)    (*((DUK__RCISREG((x)) ? thr->valstack_bottom : consts2) + (x)))
67445 #define DUK__REGCONSTP(x)   ((DUK__RCISREG((x)) ? thr->valstack_bottom : consts2) + (x))
67446 
67447 #ifdef DUK_USE_VERBOSE_EXECUTOR_ERRORS
67448 #define DUK__INTERNAL_ERROR(msg)  do { \
67449 		DUK_ERROR_INTERNAL(thr, (msg)); \
67450 	} while (0)
67451 #else
67452 #define DUK__INTERNAL_ERROR(msg)  do { \
67453 		goto internal_error; \
67454 	} while (0)
67455 #endif
67456 
67457 #define DUK__SYNC_CURR_PC()  do { \
67458 		duk_activation *act; \
67459 		act = thr->callstack + thr->callstack_top - 1; \
67460 		act->curr_pc = curr_pc; \
67461 	} while (0)
67462 #define DUK__SYNC_AND_NULL_CURR_PC()  do { \
67463 		duk_activation *act; \
67464 		act = thr->callstack + thr->callstack_top - 1; \
67465 		act->curr_pc = curr_pc; \
67466 		thr->ptr_curr_pc = NULL; \
67467 	} while (0)
67468 
67469 DUK_LOCAL void duk__handle_executor_error(duk_heap *heap,
67470                                           duk_hthread *entry_thread,
67471                                           duk_size_t entry_callstack_top,
67472                                           duk_int_t entry_call_recursion_depth,
67473                                           duk_jmpbuf *entry_jmpbuf_ptr) {
67474 	duk_small_uint_t lj_ret;
67475 
67476 	/* Longjmp callers are required to sync-and-null thr->ptr_curr_pc
67477 	 * before longjmp.
67478 	 */
67479 	DUK_ASSERT(heap->curr_thread != NULL);
67480 	DUK_ASSERT(heap->curr_thread->ptr_curr_pc == NULL);
67481 
67482 	/* XXX: signalling the need to shrink check (only if unwound) */
67483 
67484 	/* Must be restored here to handle e.g. yields properly. */
67485 	heap->call_recursion_depth = entry_call_recursion_depth;
67486 
67487 	/* Switch to caller's setjmp() catcher so that if an error occurs
67488 	 * during error handling, it is always propagated outwards instead
67489 	 * of causing an infinite loop in our own handler.
67490 	 */
67491 	heap->lj.jmpbuf_ptr = (duk_jmpbuf *) entry_jmpbuf_ptr;
67492 
67493 	lj_ret = duk__handle_longjmp(heap->curr_thread, entry_thread, entry_callstack_top);
67494 
67495 	if (lj_ret == DUK__LONGJMP_RESTART) {
67496 		/* Restart bytecode execution, possibly with a changed thread. */
67497 		;
67498 	} else {
67499 		/* Rethrow error to calling state. */
67500 		DUK_ASSERT(lj_ret == DUK__LONGJMP_RETHROW);
67501 
67502 		/* Longjmp handling has restored jmpbuf_ptr. */
67503 		DUK_ASSERT(heap->lj.jmpbuf_ptr == entry_jmpbuf_ptr);
67504 
67505 		/* Thread may have changed, e.g. YIELD converted to THROW. */
67506 		duk_err_longjmp(heap->curr_thread);
67507 		DUK_UNREACHABLE();
67508 	}
67509 }
67510 
67511 /* Outer executor with setjmp/longjmp handling. */
67512 DUK_INTERNAL void duk_js_execute_bytecode(duk_hthread *exec_thr) {
67513 	/* Entry level info. */
67514 	duk_hthread *entry_thread;
67515 	duk_size_t entry_callstack_top;
67516 	duk_int_t entry_call_recursion_depth;
67517 	duk_jmpbuf *entry_jmpbuf_ptr;
67518 	duk_jmpbuf our_jmpbuf;
67519 	duk_heap *heap;
67520 
67521 	DUK_ASSERT(exec_thr != NULL);
67522 	DUK_ASSERT(exec_thr->heap != NULL);
67523 	DUK_ASSERT(exec_thr->heap->curr_thread != NULL);
67524 	DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR((duk_heaphdr *) exec_thr);
67525 	DUK_ASSERT(exec_thr->callstack_top >= 1);  /* at least one activation, ours */
67526 	DUK_ASSERT(DUK_ACT_GET_FUNC(exec_thr->callstack + exec_thr->callstack_top - 1) != NULL);
67527 	DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION(DUK_ACT_GET_FUNC(exec_thr->callstack + exec_thr->callstack_top - 1)));
67528 
67529 	entry_thread = exec_thr;
67530 	heap = entry_thread->heap;
67531 	entry_callstack_top = entry_thread->callstack_top;
67532 	entry_call_recursion_depth = entry_thread->heap->call_recursion_depth;
67533 	entry_jmpbuf_ptr = entry_thread->heap->lj.jmpbuf_ptr;
67534 
67535 	/*
67536 	 *  Note: we currently assume that the setjmp() catchpoint is
67537 	 *  not re-entrant (longjmp() cannot be called more than once
67538 	 *  for a single setjmp()).
67539 	 *
67540 	 *  See doc/code-issues.rst for notes on variable assignment
67541 	 *  before and after setjmp().
67542 	 */
67543 
67544 	for (;;) {
67545 		heap->lj.jmpbuf_ptr = &our_jmpbuf;
67546 		DUK_ASSERT(heap->lj.jmpbuf_ptr != NULL);
67547 
67548 #if defined(DUK_USE_CPP_EXCEPTIONS)
67549 		try {
67550 #else
67551 		DUK_ASSERT(heap->lj.jmpbuf_ptr == &our_jmpbuf);
67552 		if (DUK_SETJMP(our_jmpbuf.jb) == 0) {
67553 #endif
67554 			/* Execute bytecode until returned or longjmp(). */
67555 			duk__js_execute_bytecode_inner(entry_thread, entry_callstack_top);
67556 
67557 			/* Successful return: restore jmpbuf and return to caller. */
67558 			heap->lj.jmpbuf_ptr = entry_jmpbuf_ptr;
67559 
67560 			return;
67561 #if defined(DUK_USE_CPP_EXCEPTIONS)
67562 		} catch (duk_internal_exception &exc) {
67563 #else
67564 		} else {
67565 #endif
67566 #if defined(DUK_USE_CPP_EXCEPTIONS)
67567 			DUK_UNREF(exc);
67568 #endif
67569 			DUK_DDD(DUK_DDDPRINT("longjmp caught by bytecode executor"));
67570 
67571 			duk__handle_executor_error(heap,
67572 			                           entry_thread,
67573 			                           entry_callstack_top,
67574 			                           entry_call_recursion_depth,
67575 			                           entry_jmpbuf_ptr);
67576 		}
67577 #if defined(DUK_USE_CPP_EXCEPTIONS)
67578 		catch (std::exception &exc) {
67579 			const char *what = exc.what();
67580 			if (!what) {
67581 				what = "unknown";
67582 			}
67583 			DUK_D(DUK_DPRINT("unexpected c++ std::exception (perhaps thrown by user code)"));
67584 			try {
67585 				DUK_ASSERT(heap->curr_thread != NULL);
67586 				DUK_ERROR_FMT1(heap->curr_thread, DUK_ERR_API_ERROR, "caught invalid c++ std::exception '%s' (perhaps thrown by user code)", what);
67587 			} catch (duk_internal_exception exc) {
67588 				DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ std::exception"));
67589 				DUK_UNREF(exc);
67590 				duk__handle_executor_error(heap,
67591 				                           entry_thread,
67592 				                           entry_callstack_top,
67593 				                           entry_call_recursion_depth,
67594 				                           entry_jmpbuf_ptr);
67595 			}
67596 		} catch (...) {
67597 			DUK_D(DUK_DPRINT("unexpected c++ exception (perhaps thrown by user code)"));
67598 			try {
67599 				DUK_ASSERT(heap->curr_thread != NULL);
67600 				DUK_ERROR_API(heap->curr_thread, "caught invalid c++ exception (perhaps thrown by user code)");
67601 			} catch (duk_internal_exception exc) {
67602 				DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ exception"));
67603 				DUK_UNREF(exc);
67604 				duk__handle_executor_error(heap,
67605 				                           entry_thread,
67606 				                           entry_callstack_top,
67607 				                           entry_call_recursion_depth,
67608 				                           entry_jmpbuf_ptr);
67609 			}
67610 		}
67611 #endif
67612 	}
67613 
67614 	DUK_UNREACHABLE();
67615 }
67616 
67617 /* Inner executor, performance critical. */
67618 DUK_LOCAL DUK_NOINLINE void duk__js_execute_bytecode_inner(duk_hthread *entry_thread, duk_size_t entry_callstack_top) {
67619 	/* Current PC, accessed by other functions through thr->ptr_to_curr_pc.
67620 	 * Critical for performance.  It would be safest to make this volatile,
67621 	 * but that eliminates performance benefits; aliasing guarantees
67622 	 * should be enough though.
67623 	 */
67624 	duk_instr_t *curr_pc;         /* bytecode has a stable pointer */
67625 
67626 	/* Hot variables for interpretation.  Critical for performance,
67627 	 * but must add sparingly to minimize register shuffling.
67628 	 */
67629 	duk_hthread *thr;             /* stable */
67630 	duk_tval *consts;             /* stable */
67631 	duk_tval *consts2;            /* stable; precalculated for faster lookups */
67632 	duk_uint_fast32_t ins;
67633 	/* 'funcs' is quite rarely used, so no local for it */
67634 #if defined(DUK_USE_EXEC_FUN_LOCAL)
67635 	duk_hcompiledfunction *fun;
67636 #else
67637 	/* 'fun' is quite rarely used, so no local for it */
67638 #endif
67639 
67640 #ifdef DUK_USE_INTERRUPT_COUNTER
67641 	duk_int_t int_ctr;
67642 #endif
67643 
67644 #ifdef DUK_USE_ASSERTIONS
67645 	duk_size_t valstack_top_base;    /* valstack top, should match before interpreting each op (no leftovers) */
67646 #endif
67647 
67648 	/*
67649 	 *  Restart execution by reloading thread state.
67650 	 *
67651 	 *  Note that 'thr' and any thread configuration may have changed,
67652 	 *  so all local variables are suspect and we need to reinitialize.
67653 	 *
67654 	 *  The number of local variables should be kept to a minimum: if
67655 	 *  the variables are spilled, they will need to be loaded from
67656 	 *  memory anyway.
67657 	 *
67658 	 *  Any 'goto restart_execution;' code path in opcode dispatch must
67659 	 *  ensure 'curr_pc' is synced back to act->curr_pc before the goto
67660 	 *  takes place.
67661 	 *
67662 	 *  The interpreter must be very careful with memory pointers, as
67663 	 *  many pointers are not guaranteed to be 'stable' and may be
67664 	 *  reallocated and relocated on-the-fly quite easily (e.g. by a
67665 	 *  memory allocation or a property access).
67666 	 *
67667 	 *  The following are assumed to have stable pointers:
67668 	 *    - the current thread
67669 	 *    - the current function
67670 	 *    - the bytecode, constant table, inner function table of the
67671 	 *      current function (as they are a part of the function allocation)
67672 	 *
67673 	 *  The following are assumed to have semi-stable pointers:
67674 	 *    - the current activation entry: stable as long as callstack
67675 	 *      is not changed (reallocated by growing or shrinking), or
67676 	 *      by any garbage collection invocation (through finalizers)
67677 	 *    - Note in particular that ANY DECREF can invalidate the
67678 	 *      activation pointer, so for the most part a fresh lookup
67679 	 *      is required
67680 	 *
67681 	 *  The following are not assumed to have stable pointers at all:
67682 	 *    - the value stack (registers) of the current thread
67683 	 *    - the catch stack of the current thread
67684 	 *
67685 	 *  See execution.rst for discussion.
67686 	 */
67687 
67688  restart_execution:
67689 
67690 	/* Lookup current thread; use the stable 'entry_thread' for this to
67691 	 * avoid clobber warnings.  Any valid, reachable 'thr' value would be
67692 	 * fine for this, so using 'entry_thread' is just to silence warnings.
67693 	 */
67694 	thr = entry_thread->heap->curr_thread;
67695 	DUK_ASSERT(thr != NULL);
67696 	DUK_ASSERT(thr->callstack_top >= 1);
67697 	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 1) != NULL);
67698 	DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 1)));
67699 
67700 	thr->ptr_curr_pc = &curr_pc;
67701 
67702 	/* Relookup and initialize dispatch loop variables.  Debugger check. */
67703 	{
67704 		duk_activation *act;
67705 #if !defined(DUK_USE_EXEC_FUN_LOCAL)
67706 		duk_hcompiledfunction *fun;
67707 #endif
67708 
67709 		/* Assume interrupt init/counter are properly initialized here. */
67710 		/* Assume that thr->valstack_bottom has been set-up before getting here. */
67711 
67712 		act = thr->callstack + thr->callstack_top - 1;
67713 		fun = (duk_hcompiledfunction *) DUK_ACT_GET_FUNC(act);
67714 		DUK_ASSERT(fun != NULL);
67715 		DUK_ASSERT(thr->valstack_top - thr->valstack_bottom == fun->nregs);
67716 		consts = DUK_HCOMPILEDFUNCTION_GET_CONSTS_BASE(thr->heap, fun);
67717 		DUK_ASSERT(consts != NULL);
67718 		consts2 = consts - DUK_BC_REGLIMIT;
67719 
67720 #if defined(DUK_USE_DEBUGGER_SUPPORT)
67721 		if (DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap) && !thr->heap->dbg_processing) {
67722 			duk__executor_recheck_debugger(thr, act, fun);
67723 			act = thr->callstack + thr->callstack_top - 1;  /* relookup after side effects (no side effects currently however) */
67724 		}
67725 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
67726 
67727 #ifdef DUK_USE_ASSERTIONS
67728 		valstack_top_base = (duk_size_t) (thr->valstack_top - thr->valstack);
67729 #endif
67730 
67731 		/* Set up curr_pc for opcode dispatch. */
67732 		curr_pc = act->curr_pc;
67733 	}
67734 
67735 	DUK_DD(DUK_DDPRINT("restarting execution, thr %p, act idx %ld, fun %p,"
67736 	                   "consts %p, funcs %p, lev %ld, regbot %ld, regtop %ld, catchstack_top=%ld, "
67737 	                   "preventcount=%ld",
67738 	                   (void *) thr,
67739 	                   (long) (thr->callstack_top - 1),
67740 	                   (void *) DUK__FUN(),
67741 	                   (void *) DUK_HCOMPILEDFUNCTION_GET_CONSTS_BASE(thr->heap, DUK__FUN()),
67742 	                   (void *) DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE(thr->heap, DUK__FUN()),
67743 	                   (long) (thr->callstack_top - 1),
67744 	                   (long) (thr->valstack_bottom - thr->valstack),
67745 	                   (long) (thr->valstack_top - thr->valstack),
67746 	                   (long) thr->catchstack_top,
67747 	                   (long) thr->callstack_preventcount));
67748 
67749 	/* Dispatch loop. */
67750 
67751 	for (;;) {
67752 		DUK_ASSERT(thr->callstack_top >= 1);
67753 		DUK_ASSERT(thr->valstack_top - thr->valstack_bottom == DUK__FUN()->nregs);
67754 		DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack) == valstack_top_base);
67755 
67756 		/* Executor interrupt counter check, used to implement breakpoints,
67757 		 * debugging interface, execution timeouts, etc.  The counter is heap
67758 		 * specific but is maintained in the current thread to make the check
67759 		 * as fast as possible.  The counter is copied back to the heap struct
67760 		 * whenever a thread switch occurs by the DUK_HEAP_SWITCH_THREAD() macro.
67761 		 */
67762 #if defined(DUK_USE_INTERRUPT_COUNTER)
67763 		int_ctr = thr->interrupt_counter;
67764 		if (DUK_LIKELY(int_ctr > 0)) {
67765 			thr->interrupt_counter = int_ctr - 1;
67766 		} else {
67767 			/* Trigger at zero or below */
67768 			duk_small_uint_t exec_int_ret;
67769 
67770 			/* Write curr_pc back for the debugger. */
67771 			DUK_ASSERT(thr->callstack_top > 0);
67772 			{
67773 				duk_activation *act;
67774 				act = thr->callstack + thr->callstack_top - 1;
67775 				act->curr_pc = (duk_instr_t *) curr_pc;
67776 			}
67777 
67778 			/* Force restart caused by a function return; must recheck
67779 			 * debugger breakpoints before checking line transitions,
67780 			 * see GH-303.  Restart and then handle interrupt_counter
67781 			 * zero again.
67782 			 */
67783 #if defined(DUK_USE_DEBUGGER_SUPPORT)
67784 			if (thr->heap->dbg_force_restart) {
67785 				DUK_DD(DUK_DDPRINT("dbg_force_restart flag forced restart execution"));  /* GH-303 */
67786 				thr->heap->dbg_force_restart = 0;
67787 				goto restart_execution;
67788 			}
67789 #endif
67790 
67791 			exec_int_ret = duk__executor_interrupt(thr);
67792 			if (exec_int_ret == DUK__INT_RESTART) {
67793 				/* curr_pc synced back above */
67794 				goto restart_execution;
67795 			}
67796 		}
67797 #endif  /* DUK_USE_INTERRUPT_COUNTER */
67798 #if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
67799 		/* For cross-checking during development: ensure dispatch count
67800 		 * matches cumulative interrupt counter init value sums.
67801 		 */
67802 		thr->heap->inst_count_exec++;
67803 #endif
67804 
67805 #if defined(DUK_USE_ASSERTIONS) || defined(DUK_USE_DEBUG)
67806 		{
67807 			duk_activation *act;
67808 			act = thr->callstack + thr->callstack_top - 1;
67809 			DUK_ASSERT(curr_pc >= DUK_HCOMPILEDFUNCTION_GET_CODE_BASE(thr->heap, DUK__FUN()));
67810 			DUK_ASSERT(curr_pc < DUK_HCOMPILEDFUNCTION_GET_CODE_END(thr->heap, DUK__FUN()));
67811 			DUK_UNREF(act);  /* if debugging disabled */
67812 
67813 			DUK_DDD(DUK_DDDPRINT("executing bytecode: pc=%ld, ins=0x%08lx, op=%ld, valstack_top=%ld/%ld, nregs=%ld  -->  %!I",
67814 			                     (long) (curr_pc - DUK_HCOMPILEDFUNCTION_GET_CODE_BASE(thr->heap, DUK__FUN())),
67815 			                     (unsigned long) *curr_pc,
67816 			                     (long) DUK_DEC_OP(*curr_pc),
67817 			                     (long) (thr->valstack_top - thr->valstack),
67818 			                     (long) (thr->valstack_end - thr->valstack),
67819 			                     (long) (DUK__FUN() ? DUK__FUN()->nregs : -1),
67820 			                     (duk_instr_t) *curr_pc));
67821 		}
67822 #endif
67823 
67824 #if defined(DUK_USE_ASSERTIONS)
67825 		/* Quite heavy assert: check valstack policy.  Improper
67826 		 * shuffle instructions can write beyond valstack_top/end
67827 		 * so this check catches them in the act.
67828 		 */
67829 		{
67830 			duk_tval *tv;
67831 			tv = thr->valstack_top;
67832 			while (tv != thr->valstack_end) {
67833 				DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv));
67834 				tv++;
67835 			}
67836 		}
67837 #endif
67838 
67839 		ins = *curr_pc++;
67840 
67841 		/* Typing: use duk_small_(u)int_fast_t when decoding small
67842 		 * opcode fields (op, A, B, C) and duk_(u)int_fast_t when
67843 		 * decoding larger fields (e.g. BC which is 18 bits).  Use
67844 		 * unsigned variant by default, signed when the value is used
67845 		 * in signed arithmetic.  Using variable names such as 'a', 'b',
67846 		 * 'c', 'bc', etc makes it easier to spot typing mismatches.
67847 		 */
67848 
67849 		/* XXX: the best typing needs to be validated by perf measurement:
67850 		 * e.g. using a small type which is the cast to a larger duk_idx_t
67851 		 * may be slower than declaring the variable as a duk_idx_t in the
67852 		 * first place.
67853 		 */
67854 
67855 		/* XXX: use macros for the repetitive tval/refcount handling. */
67856 
67857 		switch ((int) DUK_DEC_OP(ins)) {
67858 		/* XXX: switch cast? */
67859 
67860 		case DUK_OP_LDREG: {
67861 			duk_small_uint_fast_t a;
67862 			duk_uint_fast_t bc;
67863 			duk_tval *tv1, *tv2;
67864 
67865 			a = DUK_DEC_A(ins); tv1 = DUK__REGP(a);
67866 			bc = DUK_DEC_BC(ins); tv2 = DUK__REGP(bc);
67867 			DUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv1, tv2);  /* side effects */
67868 			break;
67869 		}
67870 
67871 		case DUK_OP_STREG: {
67872 			duk_small_uint_fast_t a;
67873 			duk_uint_fast_t bc;
67874 			duk_tval *tv1, *tv2;
67875 
67876 			a = DUK_DEC_A(ins); tv1 = DUK__REGP(a);
67877 			bc = DUK_DEC_BC(ins); tv2 = DUK__REGP(bc);
67878 			DUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv2, tv1);  /* side effects */
67879 			break;
67880 		}
67881 
67882 		case DUK_OP_LDCONST: {
67883 			duk_small_uint_fast_t a;
67884 			duk_uint_fast_t bc;
67885 			duk_tval *tv1, *tv2;
67886 
67887 			a = DUK_DEC_A(ins); tv1 = DUK__REGP(a);
67888 			bc = DUK_DEC_BC(ins); tv2 = DUK__CONSTP(bc);
67889 			DUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv1, tv2);  /* side effects */
67890 			break;
67891 		}
67892 
67893 		case DUK_OP_LDINT: {
67894 			duk_small_uint_fast_t a;
67895 			duk_int_fast_t bc;
67896 			duk_tval *tv1;
67897 #if defined(DUK_USE_FASTINT)
67898 			duk_int32_t val;
67899 #else
67900 			duk_double_t val;
67901 #endif
67902 
67903 #if defined(DUK_USE_FASTINT)
67904 			a = DUK_DEC_A(ins); tv1 = DUK__REGP(a);
67905 			bc = DUK_DEC_BC(ins); val = (duk_int32_t) (bc - DUK_BC_LDINT_BIAS);
67906 			DUK_TVAL_SET_FASTINT_I32_UPDREF(thr, tv1, val);  /* side effects */
67907 #else
67908 			a = DUK_DEC_A(ins); tv1 = DUK__REGP(a);
67909 			bc = DUK_DEC_BC(ins); val = (duk_double_t) (bc - DUK_BC_LDINT_BIAS);
67910 			DUK_TVAL_SET_NUMBER_UPDREF(thr, tv1, val);  /* side effects */
67911 #endif
67912 			break;
67913 		}
67914 
67915 		case DUK_OP_LDINTX: {
67916 			duk_small_uint_fast_t a;
67917 			duk_tval *tv1;
67918 			duk_double_t val;
67919 
67920 			/* LDINTX is not necessarily in FASTINT range, so
67921 			 * no fast path for now.
67922 			 *
67923 			 * XXX: perhaps restrict LDINTX to fastint range, wider
67924 			 * range very rarely needed.
67925 			 */
67926 
67927 			a = DUK_DEC_A(ins); tv1 = DUK__REGP(a);
67928 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv1));
67929 			val = DUK_TVAL_GET_NUMBER(tv1) * ((duk_double_t) (1L << DUK_BC_LDINTX_SHIFT)) +
67930 			      (duk_double_t) DUK_DEC_BC(ins);
67931 #if defined(DUK_USE_FASTINT)
67932 			DUK_TVAL_SET_NUMBER_CHKFAST(tv1, val);
67933 #else
67934 			DUK_TVAL_SET_NUMBER(tv1, val);
67935 #endif
67936 			break;
67937 		}
67938 
67939 		case DUK_OP_MPUTOBJ:
67940 		case DUK_OP_MPUTOBJI: {
67941 			duk_context *ctx = (duk_context *) thr;
67942 			duk_small_uint_fast_t a;
67943 			duk_tval *tv1;
67944 			duk_hobject *obj;
67945 			duk_uint_fast_t idx;
67946 			duk_small_uint_fast_t count;
67947 
67948 			/* A -> register of target object
67949 			 * B -> first register of key/value pair list
67950 			 * C -> number of key/value pairs
67951 			 */
67952 
67953 			a = DUK_DEC_A(ins); tv1 = DUK__REGP(a);
67954 			DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv1));
67955 			obj = DUK_TVAL_GET_OBJECT(tv1);
67956 
67957 			idx = (duk_uint_fast_t) DUK_DEC_B(ins);
67958 			if (DUK_DEC_OP(ins) == DUK_OP_MPUTOBJI) {
67959 				duk_tval *tv_ind = DUK__REGP(idx);
67960 				DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_ind));
67961 				idx = (duk_uint_fast_t) DUK_TVAL_GET_NUMBER(tv_ind);
67962 			}
67963 
67964 			count = (duk_small_uint_fast_t) DUK_DEC_C(ins);
67965 
67966 #if defined(DUK_USE_EXEC_INDIRECT_BOUND_CHECK)
67967 			if (DUK_UNLIKELY(idx + count * 2 > (duk_uint_fast_t) duk_get_top(ctx))) {
67968 				/* XXX: use duk_is_valid_index() instead? */
67969 				/* XXX: improve check; check against nregs, not against top */
67970 				DUK__INTERNAL_ERROR("MPUTOBJ out of bounds");
67971 			}
67972 #endif
67973 
67974 			duk_push_hobject(ctx, obj);
67975 
67976 			while (count > 0) {
67977 				/* XXX: faster initialization (direct access or better primitives) */
67978 
67979 				duk_push_tval(ctx, DUK__REGP(idx));
67980 				DUK_ASSERT(duk_is_string(ctx, -1));
67981 				duk_push_tval(ctx, DUK__REGP(idx + 1));  /* -> [... obj key value] */
67982 				duk_xdef_prop_wec(ctx, -3);              /* -> [... obj] */
67983 
67984 				count--;
67985 				idx += 2;
67986 			}
67987 
67988 			duk_pop(ctx);  /* [... obj] -> [...] */
67989 			break;
67990 		}
67991 
67992 		case DUK_OP_MPUTARR:
67993 		case DUK_OP_MPUTARRI: {
67994 			duk_context *ctx = (duk_context *) thr;
67995 			duk_small_uint_fast_t a;
67996 			duk_tval *tv1;
67997 			duk_hobject *obj;
67998 			duk_uint_fast_t idx;
67999 			duk_small_uint_fast_t count;
68000 			duk_uint32_t arr_idx;
68001 
68002 			/* A -> register of target object
68003 			 * B -> first register of value data (start_index, value1, value2, ..., valueN)
68004 			 * C -> number of key/value pairs (N)
68005 			 */
68006 
68007 			a = DUK_DEC_A(ins); tv1 = DUK__REGP(a);
68008 			DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv1));
68009 			obj = DUK_TVAL_GET_OBJECT(tv1);
68010 			DUK_ASSERT(obj != NULL);
68011 
68012 			idx = (duk_uint_fast_t) DUK_DEC_B(ins);
68013 			if (DUK_DEC_OP(ins) == DUK_OP_MPUTARRI) {
68014 				duk_tval *tv_ind = DUK__REGP(idx);
68015 				DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_ind));
68016 				idx = (duk_uint_fast_t) DUK_TVAL_GET_NUMBER(tv_ind);
68017 			}
68018 
68019 			count = (duk_small_uint_fast_t) DUK_DEC_C(ins);
68020 
68021 #if defined(DUK_USE_EXEC_INDIRECT_BOUND_CHECK)
68022 			if (idx + count + 1 > (duk_uint_fast_t) duk_get_top(ctx)) {
68023 				/* XXX: use duk_is_valid_index() instead? */
68024 				/* XXX: improve check; check against nregs, not against top */
68025 				DUK__INTERNAL_ERROR("MPUTARR out of bounds");
68026 			}
68027 #endif
68028 
68029 			tv1 = DUK__REGP(idx);
68030 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv1));
68031 			arr_idx = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv1);
68032 			idx++;
68033 
68034 			duk_push_hobject(ctx, obj);
68035 
68036 			while (count > 0) {
68037 				/* duk_xdef_prop() will define an own property without any array
68038 				 * special behaviors.  We'll need to set the array length explicitly
68039 				 * in the end.  For arrays with elisions, the compiler will emit an
68040 				 * explicit SETALEN which will update the length.
68041 				 */
68042 
68043 				/* XXX: because we're dealing with 'own' properties of a fresh array,
68044 				 * the array initializer should just ensure that the array has a large
68045 				 * enough array part and write the values directly into array part,
68046 				 * and finally set 'length' manually in the end (as already happens now).
68047 				 */
68048 
68049 				duk_push_tval(ctx, DUK__REGP(idx));          /* -> [... obj value] */
68050 				duk_xdef_prop_index_wec(ctx, -2, arr_idx);   /* -> [... obj] */
68051 
68052 				/* XXX: could use at least one fewer loop counters */
68053 				count--;
68054 				idx++;
68055 				arr_idx++;
68056 			}
68057 
68058 			/* XXX: E5.1 Section 11.1.4 coerces the final length through
68059 			 * ToUint32() which is odd but happens now as a side effect of
68060 			 * 'arr_idx' type.
68061 			 */
68062 			duk_hobject_set_length(thr, obj, (duk_uint32_t) arr_idx);
68063 
68064 			duk_pop(ctx);  /* [... obj] -> [...] */
68065 			break;
68066 		}
68067 
68068 		case DUK_OP_NEW:
68069 		case DUK_OP_NEWI: {
68070 			duk_context *ctx = (duk_context *) thr;
68071 			duk_small_uint_fast_t c = DUK_DEC_C(ins);
68072 			duk_uint_fast_t idx;
68073 			duk_small_uint_fast_t i;
68074 
68075 			/* A -> unused (reserved for flags, for consistency with DUK_OP_CALL)
68076 			 * B -> target register and start reg: constructor, arg1, ..., argN
68077 			 *      (for DUK_OP_NEWI, 'b' is indirect)
68078 			 * C -> num args (N)
68079 			 */
68080 
68081 			/* duk_new() will call the constuctor using duk_handle_call().
68082 			 * A constructor call prevents a yield from inside the constructor,
68083 			 * even if the constructor is an Ecmascript function.
68084 			 */
68085 
68086 			/* Don't need to sync curr_pc here; duk_new() will do that
68087 			 * when it augments the created error.
68088 			 */
68089 
68090 			/* XXX: unnecessary copying of values?  Just set 'top' to
68091 			 * b + c, and let the return handling fix up the stack frame?
68092 			 */
68093 
68094 			idx = (duk_uint_fast_t) DUK_DEC_B(ins);
68095 			if (DUK_DEC_OP(ins) == DUK_OP_NEWI) {
68096 				duk_tval *tv_ind = DUK__REGP(idx);
68097 				DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_ind));
68098 				idx = (duk_uint_fast_t) DUK_TVAL_GET_NUMBER(tv_ind);
68099 			}
68100 
68101 #if defined(DUK_USE_EXEC_INDIRECT_BOUND_CHECK)
68102 			if (idx + c + 1 > (duk_uint_fast_t) duk_get_top(ctx)) {
68103 				/* XXX: use duk_is_valid_index() instead? */
68104 				/* XXX: improve check; check against nregs, not against top */
68105 				DUK__INTERNAL_ERROR("NEW out of bounds");
68106 			}
68107 #endif
68108 
68109 			duk_require_stack(ctx, (duk_idx_t) c);
68110 			duk_push_tval(ctx, DUK__REGP(idx));
68111 			for (i = 0; i < c; i++) {
68112 				duk_push_tval(ctx, DUK__REGP(idx + i + 1));
68113 			}
68114 			duk_new(ctx, (duk_idx_t) c);  /* [... constructor arg1 ... argN] -> [retval] */
68115 			DUK_DDD(DUK_DDDPRINT("NEW -> %!iT", (duk_tval *) duk_get_tval(ctx, -1)));
68116 			duk_replace(ctx, (duk_idx_t) idx);
68117 
68118 			/* When debugger is enabled, we need to recheck the activation
68119 			 * status after returning.  This is now handled by call handling
68120 			 * and heap->dbg_force_restart.
68121 			 */
68122 			break;
68123 		}
68124 
68125 		case DUK_OP_REGEXP: {
68126 #ifdef DUK_USE_REGEXP_SUPPORT
68127 			duk_context *ctx = (duk_context *) thr;
68128 			duk_small_uint_fast_t a = DUK_DEC_A(ins);
68129 			duk_small_uint_fast_t b = DUK_DEC_B(ins);
68130 			duk_small_uint_fast_t c = DUK_DEC_C(ins);
68131 
68132 			/* A -> target register
68133 			 * B -> bytecode (also contains flags)
68134 			 * C -> escaped source
68135 			 */
68136 
68137 			duk_push_tval(ctx, DUK__REGCONSTP(c));
68138 			duk_push_tval(ctx, DUK__REGCONSTP(b));  /* -> [ ... escaped_source bytecode ] */
68139 			duk_regexp_create_instance(thr);   /* -> [ ... regexp_instance ] */
68140 			DUK_DDD(DUK_DDDPRINT("regexp instance: %!iT", (duk_tval *) duk_get_tval(ctx, -1)));
68141 			duk_replace(ctx, (duk_idx_t) a);
68142 #else
68143 			/* The compiler should never emit DUK_OP_REGEXP if there is no
68144 			 * regexp support.
68145 			 */
68146 			DUK__INTERNAL_ERROR("no regexp support");
68147 #endif
68148 
68149 			break;
68150 		}
68151 
68152 		case DUK_OP_CSREG:
68153 		case DUK_OP_CSREGI: {
68154 			/*
68155 			 *  Assuming a register binds to a variable declared within this
68156 			 *  function (a declarative binding), the 'this' for the call
68157 			 *  setup is always 'undefined'.  E5 Section 10.2.1.1.6.
68158 			 */
68159 
68160 			duk_context *ctx = (duk_context *) thr;
68161 			duk_small_uint_fast_t b = DUK_DEC_B(ins);  /* restricted to regs */
68162 			duk_uint_fast_t idx;
68163 
68164 			/* A -> target register (A, A+1) for call setup
68165 			 *      (for DUK_OP_CSREGI, 'a' is indirect)
68166 			 * B -> register containing target function (not type checked here)
68167 			 */
68168 
68169 			/* XXX: direct manipulation, or duk_replace_tval() */
68170 
68171 			/* Note: target registers a and a+1 may overlap with DUK__REGP(b).
68172 			 * Careful here.
68173 			 */
68174 
68175 			idx = (duk_uint_fast_t) DUK_DEC_A(ins);
68176 			if (DUK_DEC_OP(ins) == DUK_OP_CSREGI) {
68177 				duk_tval *tv_ind = DUK__REGP(idx);
68178 				DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_ind));
68179 				idx = (duk_uint_fast_t) DUK_TVAL_GET_NUMBER(tv_ind);
68180 			}
68181 
68182 #if defined(DUK_USE_EXEC_INDIRECT_BOUND_CHECK)
68183 			if (idx + 2 > (duk_uint_fast_t) duk_get_top(ctx)) {
68184 				/* XXX: use duk_is_valid_index() instead? */
68185 				/* XXX: improve check; check against nregs, not against top */
68186 				DUK__INTERNAL_ERROR("CSREG out of bounds");
68187 			}
68188 #endif
68189 
68190 			duk_push_tval(ctx, DUK__REGP(b));
68191 			duk_replace(ctx, (duk_idx_t) idx);
68192 			duk_push_undefined(ctx);
68193 			duk_replace(ctx, (duk_idx_t) (idx + 1));
68194 			break;
68195 		}
68196 
68197 		case DUK_OP_GETVAR: {
68198 			duk_context *ctx = (duk_context *) thr;
68199 			duk_activation *act;
68200 			duk_small_uint_fast_t a = DUK_DEC_A(ins);
68201 			duk_uint_fast_t bc = DUK_DEC_BC(ins);
68202 			duk_tval *tv1;
68203 			duk_hstring *name;
68204 
68205 			tv1 = DUK__CONSTP(bc);
68206 			DUK_ASSERT(DUK_TVAL_IS_STRING(tv1));
68207 			name = DUK_TVAL_GET_STRING(tv1);
68208 			DUK_ASSERT(name != NULL);
68209 			DUK_DDD(DUK_DDDPRINT("GETVAR: '%!O'", (duk_heaphdr *) name));
68210 			act = thr->callstack + thr->callstack_top - 1;
68211 			(void) duk_js_getvar_activation(thr, act, name, 1 /*throw*/);  /* -> [... val this] */
68212 
68213 			duk_pop(ctx);  /* 'this' binding is not needed here */
68214 			duk_replace(ctx, (duk_idx_t) a);
68215 			break;
68216 		}
68217 
68218 		case DUK_OP_PUTVAR: {
68219 			duk_activation *act;
68220 			duk_small_uint_fast_t a = DUK_DEC_A(ins);
68221 			duk_uint_fast_t bc = DUK_DEC_BC(ins);
68222 			duk_tval *tv1;
68223 			duk_hstring *name;
68224 
68225 			tv1 = DUK__CONSTP(bc);
68226 			DUK_ASSERT(DUK_TVAL_IS_STRING(tv1));
68227 			name = DUK_TVAL_GET_STRING(tv1);
68228 			DUK_ASSERT(name != NULL);
68229 
68230 			/* XXX: putvar takes a duk_tval pointer, which is awkward and
68231 			 * should be reworked.
68232 			 */
68233 
68234 			tv1 = DUK__REGP(a);  /* val */
68235 			act = thr->callstack + thr->callstack_top - 1;
68236 			duk_js_putvar_activation(thr, act, name, tv1, DUK__STRICT());
68237 			break;
68238 		}
68239 
68240 		case DUK_OP_DECLVAR: {
68241 			duk_activation *act;
68242 			duk_context *ctx = (duk_context *) thr;
68243 			duk_small_uint_fast_t a = DUK_DEC_A(ins);
68244 			duk_small_uint_fast_t b = DUK_DEC_B(ins);
68245 			duk_small_uint_fast_t c = DUK_DEC_C(ins);
68246 			duk_tval *tv1;
68247 			duk_hstring *name;
68248 			duk_small_uint_t prop_flags;
68249 			duk_bool_t is_func_decl;
68250 			duk_bool_t is_undef_value;
68251 
68252 			tv1 = DUK__REGCONSTP(b);
68253 			DUK_ASSERT(DUK_TVAL_IS_STRING(tv1));
68254 			name = DUK_TVAL_GET_STRING(tv1);
68255 			DUK_ASSERT(name != NULL);
68256 
68257 			is_undef_value = ((a & DUK_BC_DECLVAR_FLAG_UNDEF_VALUE) != 0);
68258 			is_func_decl = ((a & DUK_BC_DECLVAR_FLAG_FUNC_DECL) != 0);
68259 
68260 			/* XXX: declvar takes an duk_tval pointer, which is awkward and
68261 			 * should be reworked.
68262 			 */
68263 
68264 			/* Compiler is responsible for selecting property flags (configurability,
68265 			 * writability, etc).
68266 			 */
68267 			prop_flags = a & DUK_PROPDESC_FLAGS_MASK;
68268 
68269 			if (is_undef_value) {
68270 				duk_push_undefined(ctx);
68271 			} else {
68272 				duk_push_tval(ctx, DUK__REGCONSTP(c));
68273 			}
68274 			tv1 = DUK_GET_TVAL_NEGIDX(ctx, -1);
68275 
68276 			act = thr->callstack + thr->callstack_top - 1;
68277 			if (duk_js_declvar_activation(thr, act, name, tv1, prop_flags, is_func_decl)) {
68278 				if (is_undef_value) {
68279 					/* Already declared but no initializer value
68280 					 * (e.g. 'var xyz;'), no-op.
68281 					 */
68282 				} else {
68283 					/* Already declared, update value. */
68284 					tv1 = DUK_GET_TVAL_NEGIDX(ctx, -1);
68285 					duk_js_putvar_activation(thr, act, name, tv1, DUK__STRICT());
68286 				}
68287 			}
68288 
68289 			duk_pop(ctx);
68290 			break;
68291 		}
68292 
68293 		case DUK_OP_DELVAR: {
68294 			duk_activation *act;
68295 			duk_context *ctx = (duk_context *) thr;
68296 			duk_small_uint_fast_t a = DUK_DEC_A(ins);
68297 			duk_small_uint_fast_t b = DUK_DEC_B(ins);
68298 			duk_tval *tv1;
68299 			duk_hstring *name;
68300 			duk_bool_t rc;
68301 
68302 			tv1 = DUK__REGCONSTP(b);
68303 			DUK_ASSERT(DUK_TVAL_IS_STRING(tv1));
68304 			name = DUK_TVAL_GET_STRING(tv1);
68305 			DUK_ASSERT(name != NULL);
68306 			DUK_DDD(DUK_DDDPRINT("DELVAR '%!O'", (duk_heaphdr *) name));
68307 			act = thr->callstack + thr->callstack_top - 1;
68308 			rc = duk_js_delvar_activation(thr, act, name);
68309 
68310 			duk_push_boolean(ctx, rc);
68311 			duk_replace(ctx, (duk_idx_t) a);
68312 			break;
68313 		}
68314 
68315 		case DUK_OP_CSVAR:
68316 		case DUK_OP_CSVARI: {
68317 			/* 'this' value:
68318 			 * E5 Section 6.b.i
68319 			 *
68320 			 * The only (standard) case where the 'this' binding is non-null is when
68321 			 *   (1) the variable is found in an object environment record, and
68322 			 *   (2) that object environment record is a 'with' block.
68323 			 *
68324 			 */
68325 
68326 			duk_context *ctx = (duk_context *) thr;
68327 			duk_activation *act;
68328 			duk_small_uint_fast_t b = DUK_DEC_B(ins);
68329 			duk_uint_fast_t idx;
68330 			duk_tval *tv1;
68331 			duk_hstring *name;
68332 
68333 			tv1 = DUK__REGCONSTP(b);
68334 			DUK_ASSERT(DUK_TVAL_IS_STRING(tv1));
68335 			name = DUK_TVAL_GET_STRING(tv1);
68336 			DUK_ASSERT(name != NULL);
68337 			act = thr->callstack + thr->callstack_top - 1;
68338 			(void) duk_js_getvar_activation(thr, act, name, 1 /*throw*/);  /* -> [... val this] */
68339 
68340 			/* Note: target registers a and a+1 may overlap with DUK__REGCONSTP(b)
68341 			 * and DUK__REGCONSTP(c).  Careful here.
68342 			 */
68343 
68344 			idx = (duk_uint_fast_t) DUK_DEC_A(ins);
68345 			if (DUK_DEC_OP(ins) == DUK_OP_CSVARI) {
68346 				duk_tval *tv_ind = DUK__REGP(idx);
68347 				DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_ind));
68348 				idx = (duk_uint_fast_t) DUK_TVAL_GET_NUMBER(tv_ind);
68349 			}
68350 
68351 #if defined(DUK_USE_EXEC_INDIRECT_BOUND_CHECK)
68352 			if (idx + 2 > (duk_uint_fast_t) duk_get_top(ctx)) {
68353 				/* XXX: use duk_is_valid_index() instead? */
68354 				/* XXX: improve check; check against nregs, not against top */
68355 				DUK__INTERNAL_ERROR("CSVAR out of bounds");
68356 			}
68357 #endif
68358 
68359 			duk_replace(ctx, (duk_idx_t) (idx + 1));  /* 'this' binding */
68360 			duk_replace(ctx, (duk_idx_t) idx);        /* variable value (function, we hope, not checked here) */
68361 			break;
68362 		}
68363 
68364 		case DUK_OP_CLOSURE: {
68365 			duk_context *ctx = (duk_context *) thr;
68366 			duk_activation *act;
68367 			duk_hcompiledfunction *fun;
68368 			duk_small_uint_fast_t a = DUK_DEC_A(ins);
68369 			duk_uint_fast_t bc = DUK_DEC_BC(ins);
68370 			duk_hobject *fun_temp;
68371 
68372 			/* A -> target reg
68373 			 * BC -> inner function index
68374 			 */
68375 
68376 			DUK_DDD(DUK_DDDPRINT("CLOSURE to target register %ld, fnum %ld (count %ld)",
68377 			                     (long) a, (long) bc, (long) DUK_HCOMPILEDFUNCTION_GET_FUNCS_COUNT(thr->heap, DUK__FUN())));
68378 
68379 			DUK_ASSERT_DISABLE(bc >= 0); /* unsigned */
68380 			DUK_ASSERT((duk_uint_t) bc < (duk_uint_t) DUK_HCOMPILEDFUNCTION_GET_FUNCS_COUNT(thr->heap, DUK__FUN()));
68381 
68382 			act = thr->callstack + thr->callstack_top - 1;
68383 			fun = (duk_hcompiledfunction *) DUK_ACT_GET_FUNC(act);
68384 			fun_temp = DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE(thr->heap, fun)[bc];
68385 			DUK_ASSERT(fun_temp != NULL);
68386 			DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION(fun_temp));
68387 
68388 			DUK_DDD(DUK_DDDPRINT("CLOSURE: function template is: %p -> %!O",
68389 			                     (void *) fun_temp, (duk_heaphdr *) fun_temp));
68390 
68391 			if (act->lex_env == NULL) {
68392 				DUK_ASSERT(act->var_env == NULL);
68393 				duk_js_init_activation_environment_records_delayed(thr, act);
68394 				act = thr->callstack + thr->callstack_top - 1;
68395 			}
68396 			DUK_ASSERT(act->lex_env != NULL);
68397 			DUK_ASSERT(act->var_env != NULL);
68398 
68399 			/* functions always have a NEWENV flag, i.e. they get a
68400 			 * new variable declaration environment, so only lex_env
68401 			 * matters here.
68402 			 */
68403 			duk_js_push_closure(thr,
68404 			                    (duk_hcompiledfunction *) fun_temp,
68405 			                    act->var_env,
68406 			                    act->lex_env,
68407 			                    1 /*add_auto_proto*/);
68408 			duk_replace(ctx, (duk_idx_t) a);
68409 
68410 			break;
68411 		}
68412 
68413 		case DUK_OP_GETPROP: {
68414 			duk_context *ctx = (duk_context *) thr;
68415 			duk_small_uint_fast_t a = DUK_DEC_A(ins);
68416 			duk_small_uint_fast_t b = DUK_DEC_B(ins);
68417 			duk_small_uint_fast_t c = DUK_DEC_C(ins);
68418 			duk_tval *tv_obj;
68419 			duk_tval *tv_key;
68420 			duk_bool_t rc;
68421 
68422 			/* A -> target reg
68423 			 * B -> object reg/const (may be const e.g. in "'foo'[1]")
68424 			 * C -> key reg/const
68425 			 */
68426 
68427 			tv_obj = DUK__REGCONSTP(b);
68428 			tv_key = DUK__REGCONSTP(c);
68429 			DUK_DDD(DUK_DDDPRINT("GETPROP: a=%ld obj=%!T, key=%!T",
68430 			                     (long) a,
68431 			                     (duk_tval *) DUK__REGCONSTP(b),
68432 			                     (duk_tval *) DUK__REGCONSTP(c)));
68433 			rc = duk_hobject_getprop(thr, tv_obj, tv_key);  /* -> [val] */
68434 			DUK_UNREF(rc);  /* ignore */
68435 			DUK_DDD(DUK_DDDPRINT("GETPROP --> %!T",
68436 			                     (duk_tval *) duk_get_tval(ctx, -1)));
68437 			tv_obj = NULL;  /* invalidated */
68438 			tv_key = NULL;  /* invalidated */
68439 
68440 			duk_replace(ctx, (duk_idx_t) a);    /* val */
68441 			break;
68442 		}
68443 
68444 		case DUK_OP_PUTPROP: {
68445 			duk_small_uint_fast_t a = DUK_DEC_A(ins);
68446 			duk_small_uint_fast_t b = DUK_DEC_B(ins);
68447 			duk_small_uint_fast_t c = DUK_DEC_C(ins);
68448 			duk_tval *tv_obj;
68449 			duk_tval *tv_key;
68450 			duk_tval *tv_val;
68451 			duk_bool_t rc;
68452 
68453 			/* A -> object reg
68454 			 * B -> key reg/const
68455 			 * C -> value reg/const
68456 			 *
68457 			 * Note: intentional difference to register arrangement
68458 			 * of e.g. GETPROP; 'A' must contain a register-only value.
68459 			 */
68460 
68461 			tv_obj = DUK__REGP(a);
68462 			tv_key = DUK__REGCONSTP(b);
68463 			tv_val = DUK__REGCONSTP(c);
68464 			DUK_DDD(DUK_DDDPRINT("PUTPROP: obj=%!T, key=%!T, val=%!T",
68465 			                     (duk_tval *) DUK__REGP(a),
68466 			                     (duk_tval *) DUK__REGCONSTP(b),
68467 			                     (duk_tval *) DUK__REGCONSTP(c)));
68468 			rc = duk_hobject_putprop(thr, tv_obj, tv_key, tv_val, DUK__STRICT());
68469 			DUK_UNREF(rc);  /* ignore */
68470 			DUK_DDD(DUK_DDDPRINT("PUTPROP --> obj=%!T, key=%!T, val=%!T",
68471 			                     (duk_tval *) DUK__REGP(a),
68472 			                     (duk_tval *) DUK__REGCONSTP(b),
68473 			                     (duk_tval *) DUK__REGCONSTP(c)));
68474 			tv_obj = NULL;  /* invalidated */
68475 			tv_key = NULL;  /* invalidated */
68476 			tv_val = NULL;  /* invalidated */
68477 
68478 			break;
68479 		}
68480 
68481 		case DUK_OP_DELPROP: {
68482 			duk_context *ctx = (duk_context *) thr;
68483 			duk_small_uint_fast_t a = DUK_DEC_A(ins);
68484 			duk_small_uint_fast_t b = DUK_DEC_B(ins);
68485 			duk_small_uint_fast_t c = DUK_DEC_C(ins);
68486 			duk_tval *tv_obj;
68487 			duk_tval *tv_key;
68488 			duk_bool_t rc;
68489 
68490 			/* A -> result reg
68491 			 * B -> object reg
68492 			 * C -> key reg/const
68493 			 */
68494 
68495 			tv_obj = DUK__REGP(b);
68496 			tv_key = DUK__REGCONSTP(c);
68497 			rc = duk_hobject_delprop(thr, tv_obj, tv_key, DUK__STRICT());
68498 			tv_obj = NULL;  /* invalidated */
68499 			tv_key = NULL;  /* invalidated */
68500 
68501 			duk_push_boolean(ctx, rc);
68502 			duk_replace(ctx, (duk_idx_t) a);    /* result */
68503 			break;
68504 		}
68505 
68506 		case DUK_OP_CSPROP:
68507 		case DUK_OP_CSPROPI: {
68508 			duk_context *ctx = (duk_context *) thr;
68509 			duk_small_uint_fast_t b = DUK_DEC_B(ins);
68510 			duk_small_uint_fast_t c = DUK_DEC_C(ins);
68511 			duk_uint_fast_t idx;
68512 			duk_tval *tv_obj;
68513 			duk_tval *tv_key;
68514 			duk_bool_t rc;
68515 
68516 			/* E5 Section 11.2.3, step 6.a.i */
68517 			/* E5 Section 10.4.3 */
68518 
68519 			/* XXX: allow object to be a const, e.g. in 'foo'.toString()?
68520 			 * On the other hand, DUK_REGCONSTP() is slower and generates
68521 			 * more code.
68522 			 */
68523 
68524 			tv_obj = DUK__REGP(b);
68525 			tv_key = DUK__REGCONSTP(c);
68526 			rc = duk_hobject_getprop(thr, tv_obj, tv_key);  /* -> [val] */
68527 			DUK_UNREF(rc);  /* unused */
68528 			tv_obj = NULL;  /* invalidated */
68529 			tv_key = NULL;  /* invalidated */
68530 
68531 			/* Note: target registers a and a+1 may overlap with DUK__REGP(b)
68532 			 * and DUK__REGCONSTP(c).  Careful here.
68533 			 */
68534 
68535 			idx = (duk_uint_fast_t) DUK_DEC_A(ins);
68536 			if (DUK_DEC_OP(ins) == DUK_OP_CSPROPI) {
68537 				duk_tval *tv_ind = DUK__REGP(idx);
68538 				DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_ind));
68539 				idx = (duk_uint_fast_t) DUK_TVAL_GET_NUMBER(tv_ind);
68540 			}
68541 
68542 #if defined(DUK_USE_EXEC_INDIRECT_BOUND_CHECK)
68543 			if (idx + 2 > (duk_uint_fast_t) duk_get_top(ctx)) {
68544 				/* XXX: use duk_is_valid_index() instead? */
68545 				/* XXX: improve check; check against nregs, not against top */
68546 				DUK__INTERNAL_ERROR("CSPROP out of bounds");
68547 			}
68548 #endif
68549 
68550 			duk_push_tval(ctx, DUK__REGP(b));         /* [ ... val obj ] */
68551 			duk_replace(ctx, (duk_idx_t) (idx + 1));  /* 'this' binding */
68552 			duk_replace(ctx, (duk_idx_t) idx);        /* val */
68553 			break;
68554 		}
68555 
68556 		case DUK_OP_ADD:
68557 		case DUK_OP_SUB:
68558 		case DUK_OP_MUL:
68559 		case DUK_OP_DIV:
68560 		case DUK_OP_MOD: {
68561 			duk_small_uint_fast_t a = DUK_DEC_A(ins);
68562 			duk_small_uint_fast_t b = DUK_DEC_B(ins);
68563 			duk_small_uint_fast_t c = DUK_DEC_C(ins);
68564 			duk_small_uint_fast_t op = DUK_DEC_OP(ins);
68565 
68566 			if (op == DUK_OP_ADD) {
68567 				/*
68568 				 *  Handling DUK_OP_ADD this way is more compact (experimentally)
68569 				 *  than a separate case with separate argument decoding.
68570 				 */
68571 				duk__vm_arith_add(thr, DUK__REGCONSTP(b), DUK__REGCONSTP(c), a);
68572 			} else {
68573 				duk__vm_arith_binary_op(thr, DUK__REGCONSTP(b), DUK__REGCONSTP(c), a, op);
68574 			}
68575 			break;
68576 		}
68577 
68578 		case DUK_OP_BAND:
68579 		case DUK_OP_BOR:
68580 		case DUK_OP_BXOR:
68581 		case DUK_OP_BASL:
68582 		case DUK_OP_BLSR:
68583 		case DUK_OP_BASR: {
68584 			duk_small_uint_fast_t a = DUK_DEC_A(ins);
68585 			duk_small_uint_fast_t b = DUK_DEC_B(ins);
68586 			duk_small_uint_fast_t c = DUK_DEC_C(ins);
68587 			duk_small_uint_fast_t op = DUK_DEC_OP(ins);
68588 
68589 			duk__vm_bitwise_binary_op(thr, DUK__REGCONSTP(b), DUK__REGCONSTP(c), a, op);
68590 			break;
68591 		}
68592 
68593 		case DUK_OP_EQ:
68594 		case DUK_OP_NEQ: {
68595 			duk_context *ctx = (duk_context *) thr;
68596 			duk_small_uint_fast_t a = DUK_DEC_A(ins);
68597 			duk_small_uint_fast_t b = DUK_DEC_B(ins);
68598 			duk_small_uint_fast_t c = DUK_DEC_C(ins);
68599 			duk_bool_t tmp;
68600 
68601 			/* E5 Sections 11.9.1, 11.9.3 */
68602 			tmp = duk_js_equals(thr, DUK__REGCONSTP(b), DUK__REGCONSTP(c));
68603 			if (DUK_DEC_OP(ins) == DUK_OP_NEQ) {
68604 				tmp = !tmp;
68605 			}
68606 			duk_push_boolean(ctx, tmp);
68607 			duk_replace(ctx, (duk_idx_t) a);
68608 			break;
68609 		}
68610 
68611 		case DUK_OP_SEQ:
68612 		case DUK_OP_SNEQ: {
68613 			duk_context *ctx = (duk_context *) thr;
68614 			duk_small_uint_fast_t a = DUK_DEC_A(ins);
68615 			duk_small_uint_fast_t b = DUK_DEC_B(ins);
68616 			duk_small_uint_fast_t c = DUK_DEC_C(ins);
68617 			duk_bool_t tmp;
68618 
68619 			/* E5 Sections 11.9.1, 11.9.3 */
68620 			tmp = duk_js_strict_equals(DUK__REGCONSTP(b), DUK__REGCONSTP(c));
68621 			if (DUK_DEC_OP(ins) == DUK_OP_SNEQ) {
68622 				tmp = !tmp;
68623 			}
68624 			duk_push_boolean(ctx, tmp);
68625 			duk_replace(ctx, (duk_idx_t) a);
68626 			break;
68627 		}
68628 
68629 		/* Note: combining comparison ops must be done carefully because
68630 		 * of uncomparable values (NaN): it's not necessarily true that
68631 		 * (x >= y) === !(x < y).  Also, evaluation order matters, and
68632 		 * although it would only seem to affect the compiler this is
68633 		 * actually not the case, because there are also run-time coercions
68634 		 * of the arguments (with potential side effects).
68635 		 *
68636 		 * XXX: can be combined; check code size.
68637 		 */
68638 
68639 		case DUK_OP_GT: {
68640 			duk_context *ctx = (duk_context *) thr;
68641 			duk_small_uint_fast_t a = DUK_DEC_A(ins);
68642 			duk_small_uint_fast_t b = DUK_DEC_B(ins);
68643 			duk_small_uint_fast_t c = DUK_DEC_C(ins);
68644 			duk_bool_t tmp;
68645 
68646 			/* x > y  -->  y < x */
68647 			tmp = duk_js_compare_helper(thr,
68648 			                            DUK__REGCONSTP(c),  /* y */
68649 			                            DUK__REGCONSTP(b),  /* x */
68650 			                            0);                 /* flags */
68651 
68652 			duk_push_boolean(ctx, tmp);
68653 			duk_replace(ctx, (duk_idx_t) a);
68654 			break;
68655 		}
68656 
68657 		case DUK_OP_GE: {
68658 			duk_context *ctx = (duk_context *) thr;
68659 			duk_small_uint_fast_t a = DUK_DEC_A(ins);
68660 			duk_small_uint_fast_t b = DUK_DEC_B(ins);
68661 			duk_small_uint_fast_t c = DUK_DEC_C(ins);
68662 			duk_bool_t tmp;
68663 
68664 			/* x >= y  -->  not (x < y) */
68665 			tmp = duk_js_compare_helper(thr,
68666 			                            DUK__REGCONSTP(b),  /* x */
68667 			                            DUK__REGCONSTP(c),  /* y */
68668 			                            DUK_COMPARE_FLAG_EVAL_LEFT_FIRST |
68669 			                            DUK_COMPARE_FLAG_NEGATE);  /* flags */
68670 
68671 			duk_push_boolean(ctx, tmp);
68672 			duk_replace(ctx, (duk_idx_t) a);
68673 			break;
68674 		}
68675 
68676 		case DUK_OP_LT: {
68677 			duk_context *ctx = (duk_context *) thr;
68678 			duk_small_uint_fast_t a = DUK_DEC_A(ins);
68679 			duk_small_uint_fast_t b = DUK_DEC_B(ins);
68680 			duk_small_uint_fast_t c = DUK_DEC_C(ins);
68681 			duk_bool_t tmp;
68682 
68683 			/* x < y */
68684 			tmp = duk_js_compare_helper(thr,
68685 			                            DUK__REGCONSTP(b),  /* x */
68686 			                            DUK__REGCONSTP(c),  /* y */
68687 			                            DUK_COMPARE_FLAG_EVAL_LEFT_FIRST);  /* flags */
68688 
68689 			duk_push_boolean(ctx, tmp);
68690 			duk_replace(ctx, (duk_idx_t) a);
68691 			break;
68692 		}
68693 
68694 		case DUK_OP_LE: {
68695 			duk_context *ctx = (duk_context *) thr;
68696 			duk_small_uint_fast_t a = DUK_DEC_A(ins);
68697 			duk_small_uint_fast_t b = DUK_DEC_B(ins);
68698 			duk_small_uint_fast_t c = DUK_DEC_C(ins);
68699 			duk_bool_t tmp;
68700 
68701 			/* x <= y  -->  not (x > y)  -->  not (y < x) */
68702 			tmp = duk_js_compare_helper(thr,
68703 			                            DUK__REGCONSTP(c),  /* y */
68704 			                            DUK__REGCONSTP(b),  /* x */
68705 			                            DUK_COMPARE_FLAG_NEGATE);  /* flags */
68706 
68707 			duk_push_boolean(ctx, tmp);
68708 			duk_replace(ctx, (duk_idx_t) a);
68709 			break;
68710 		}
68711 
68712 		case DUK_OP_IF: {
68713 			duk_small_uint_fast_t a = DUK_DEC_A(ins);
68714 			duk_small_uint_fast_t b = DUK_DEC_B(ins);
68715 			duk_bool_t tmp;
68716 
68717 			tmp = duk_js_toboolean(DUK__REGCONSTP(b));
68718 			if (tmp == (duk_bool_t) a) {
68719 				/* if boolean matches A, skip next inst */
68720 				curr_pc++;
68721 			} else {
68722 				;
68723 			}
68724 			break;
68725 		}
68726 
68727 		case DUK_OP_JUMP: {
68728 			duk_int_fast_t abc = DUK_DEC_ABC(ins);
68729 
68730 			curr_pc += abc - DUK_BC_JUMP_BIAS;
68731 			break;
68732 		}
68733 
68734 		case DUK_OP_RETURN: {
68735 			duk_context *ctx = (duk_context *) thr;
68736 			duk_small_uint_fast_t a = DUK_DEC_A(ins);
68737 			duk_small_uint_fast_t b = DUK_DEC_B(ins);
68738 			/* duk_small_uint_fast_t c = DUK_DEC_C(ins); */
68739 			duk_small_uint_t ret_result;
68740 
68741 			/* A -> flags
68742 			 * B -> return value reg/const
68743 			 * C -> currently unused
68744 			 */
68745 
68746 			DUK__SYNC_AND_NULL_CURR_PC();
68747 
68748 			/* duk__handle_return() is guaranteed never to throw, except
68749 			 * for potential out-of-memory situations which will then
68750 			 * propagate out of the executor longjmp handler.
68751 			 */
68752 
68753 			if (a & DUK_BC_RETURN_FLAG_HAVE_RETVAL) {
68754 				duk_push_tval(ctx, DUK__REGCONSTP(b));
68755 			} else {
68756 				duk_push_undefined(ctx);
68757 			}
68758 			ret_result = duk__handle_return(thr,
68759 				                        entry_thread,
68760 				                        entry_callstack_top);
68761 			if (ret_result == DUK__RETHAND_RESTART) {
68762 				goto restart_execution;
68763 			}
68764 			DUK_ASSERT(ret_result == DUK__RETHAND_FINISHED);
68765 
68766 			DUK_DDD(DUK_DDDPRINT("exiting executor after RETURN handling"));
68767 			return;
68768 		}
68769 
68770 		case DUK_OP_CALL:
68771 		case DUK_OP_CALLI: {
68772 			duk_context *ctx = (duk_context *) thr;
68773 			duk_small_uint_fast_t a = DUK_DEC_A(ins);
68774 			duk_small_uint_fast_t c = DUK_DEC_C(ins);
68775 			duk_uint_fast_t idx;
68776 			duk_small_uint_t call_flags;
68777 			duk_small_uint_t flag_tailcall;
68778 			duk_small_uint_t flag_evalcall;
68779 			duk_tval *tv_func;
68780 			duk_hobject *obj_func;
68781 			duk_bool_t setup_rc;
68782 			duk_idx_t num_stack_args;
68783 #if !defined(DUK_USE_EXEC_FUN_LOCAL)
68784 			duk_hcompiledfunction *fun;
68785 #endif
68786 
68787 			/* A -> flags
68788 			 * B -> base register for call (base -> func, base+1 -> this, base+2 -> arg1 ... base+2+N-1 -> argN)
68789 			 *      (for DUK_OP_CALLI, 'b' is indirect)
68790 			 * C -> nargs
68791 			 */
68792 
68793 			/* these are not necessarily 0 or 1 (may be other non-zero), that's ok */
68794 			flag_tailcall = (a & DUK_BC_CALL_FLAG_TAILCALL);
68795 			flag_evalcall = (a & DUK_BC_CALL_FLAG_EVALCALL);
68796 
68797 			idx = (duk_uint_fast_t) DUK_DEC_B(ins);
68798 			if (DUK_DEC_OP(ins) == DUK_OP_CALLI) {
68799 				duk_tval *tv_ind = DUK__REGP(idx);
68800 				DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_ind));
68801 				idx = (duk_uint_fast_t) DUK_TVAL_GET_NUMBER(tv_ind);
68802 			}
68803 
68804 #if defined(DUK_USE_EXEC_INDIRECT_BOUND_CHECK)
68805 			if (!duk_is_valid_index(ctx, (duk_idx_t) idx)) {
68806 				/* XXX: improve check; check against nregs, not against top */
68807 				DUK__INTERNAL_ERROR("CALL out of bounds");
68808 			}
68809 #endif
68810 
68811 			/*
68812 			 *  To determine whether to use an optimized Ecmascript-to-Ecmascript
68813 			 *  call, we need to know whether the final, non-bound function is an
68814 			 *  Ecmascript function.
68815 			 *
68816 			 *  This is now implemented so that we start to do an ecma-to-ecma call
68817 			 *  setup which will resolve the bound chain as the first thing.  If the
68818 			 *  final function is not eligible, the return value indicates that the
68819 			 *  ecma-to-ecma call is not possible.  The setup will overwrite the call
68820 			 *  target at DUK__REGP(idx) with the final, non-bound function (which
68821 			 *  may be a lightfunc), and fudge arguments if necessary.
68822 			 *
68823 			 *  XXX: If an ecma-to-ecma call is not possible, this initial call
68824 			 *  setup will do bound function chain resolution but won't do the
68825 			 *  "effective this binding" resolution which is quite confusing.
68826 			 *  Perhaps add a helper for doing bound function and effective this
68827 			 *  binding resolution - and call that explicitly?  Ecma-to-ecma call
68828 			 *  setup and normal function handling can then assume this prestep has
68829 			 *  been done by the caller.
68830 			 */
68831 
68832 			duk_set_top(ctx, (duk_idx_t) (idx + c + 2));   /* [ ... func this arg1 ... argN ] */
68833 
68834 			call_flags = 0;
68835 			if (flag_tailcall) {
68836 				/* We request a tail call, but in some corner cases
68837 				 * call handling can decide that a tail call is
68838 				 * actually not possible.
68839 				 * See: test-bug-tailcall-preventyield-assert.c.
68840 				 */
68841 				call_flags |= DUK_CALL_FLAG_IS_TAILCALL;
68842 			}
68843 
68844 			/* Compared to duk_handle_call():
68845 			 *   - protected call: never
68846 			 *   - ignore recursion limit: never
68847 			 */
68848 			num_stack_args = c;
68849 			setup_rc = duk_handle_ecma_call_setup(thr,
68850 			                                      num_stack_args,
68851 			                                      call_flags);
68852 
68853 			if (setup_rc) {
68854 				/* Ecma-to-ecma call possible, may or may not be a tail call.
68855 				 * Avoid C recursion by being clever.
68856 				 */
68857 				DUK_DDD(DUK_DDDPRINT("ecma-to-ecma call setup possible, restart execution"));
68858 				/* curr_pc synced by duk_handle_ecma_call_setup() */
68859 				goto restart_execution;
68860 			}
68861 			DUK_ASSERT(thr->ptr_curr_pc != NULL);  /* restored if ecma-to-ecma setup fails */
68862 
68863 			DUK_DDD(DUK_DDDPRINT("ecma-to-ecma call not possible, target is native (may be lightfunc)"));
68864 
68865 			/* Recompute argument count: bound function handling may have shifted. */
68866 			num_stack_args = duk_get_top(ctx) - (idx + 2);
68867 			DUK_DDD(DUK_DDDPRINT("recomputed arg count: %ld\n", (long) num_stack_args));
68868 
68869 			tv_func = DUK__REGP(idx);  /* Relookup if relocated */
68870 			if (DUK_TVAL_IS_LIGHTFUNC(tv_func)) {
68871 
68872 				call_flags = 0;  /* not protected, respect reclimit, not constructor */
68873 
68874 				/* There is no eval() special handling here: eval() is never
68875 				 * automatically converted to a lightfunc.
68876 				 */
68877 				DUK_ASSERT(DUK_TVAL_GET_LIGHTFUNC_FUNCPTR(tv_func) != duk_bi_global_object_eval);
68878 
68879 				duk_handle_call_unprotected(thr,
68880 				                            num_stack_args,
68881 				                            call_flags);
68882 
68883 				/* duk_js_call.c is required to restore the stack reserve
68884 				 * so we only need to reset the top.
68885 				 */
68886 #if !defined(DUK_USE_EXEC_FUN_LOCAL)
68887 				fun = DUK__FUN();
68888 #endif
68889 				duk_set_top(ctx, (duk_idx_t) fun->nregs);
68890 
68891 				/* No need to reinit setjmp() catchpoint, as call handling
68892 				 * will store and restore our state.
68893 				 */
68894 			} else {
68895 				/* Call setup checks callability. */
68896 				DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv_func));
68897 				obj_func = DUK_TVAL_GET_OBJECT(tv_func);
68898 				DUK_ASSERT(obj_func != NULL);
68899 				DUK_ASSERT(!DUK_HOBJECT_HAS_BOUND(obj_func));
68900 
68901 				/*
68902 				 *  Other cases, use C recursion.
68903 				 *
68904 				 *  If a tail call was requested we ignore it and execute a normal call.
68905 				 *  Since Duktape 0.11.0 the compiler emits a RETURN opcode even after
68906 				 *  a tail call to avoid test-bug-tailcall-thread-yield-resume.js.
68907 				 *
68908 				 *  Direct eval call: (1) call target (before following bound function
68909 				 *  chain) is the built-in eval() function, and (2) call was made with
68910 				 *  the identifier 'eval'.
68911 				 */
68912 
68913 				call_flags = 0;  /* not protected, respect reclimit, not constructor */
68914 
68915 				if (DUK_HOBJECT_IS_NATIVEFUNCTION(obj_func) &&
68916 				    ((duk_hnativefunction *) obj_func)->func == duk_bi_global_object_eval) {
68917 					if (flag_evalcall) {
68918 						DUK_DDD(DUK_DDDPRINT("call target is eval, call identifier was 'eval' -> direct eval"));
68919 						call_flags |= DUK_CALL_FLAG_DIRECT_EVAL;
68920 					} else {
68921 						DUK_DDD(DUK_DDDPRINT("call target is eval, call identifier was not 'eval' -> indirect eval"));
68922 					}
68923 				}
68924 
68925 				duk_handle_call_unprotected(thr,
68926 				                            num_stack_args,
68927 				                            call_flags);
68928 
68929 				/* duk_js_call.c is required to restore the stack reserve
68930 				 * so we only need to reset the top.
68931 				 */
68932 #if !defined(DUK_USE_EXEC_FUN_LOCAL)
68933 				fun = DUK__FUN();
68934 #endif
68935 				duk_set_top(ctx, (duk_idx_t) fun->nregs);
68936 
68937 				/* No need to reinit setjmp() catchpoint, as call handling
68938 				 * will store and restore our state.
68939 				 */
68940 			}
68941 
68942 			/* When debugger is enabled, we need to recheck the activation
68943 			 * status after returning.  This is now handled by call handling
68944 			 * and heap->dbg_force_restart.
68945 			 */
68946 			break;
68947 		}
68948 
68949 		case DUK_OP_TRYCATCH: {
68950 			duk_context *ctx = (duk_context *) thr;
68951 			duk_activation *act;
68952 			duk_catcher *cat;
68953 			duk_tval *tv1;
68954 			duk_small_uint_fast_t a;
68955 			duk_uint_fast_t bc;
68956 
68957 			/* A -> flags
68958 			 * BC -> reg_catch; base register for two registers used both during
68959 			 *       trycatch setup and when catch is triggered
68960 			 *
68961 			 *      If DUK_BC_TRYCATCH_FLAG_CATCH_BINDING set:
68962 			 *          reg_catch + 0: catch binding variable name (string).
68963 			 *          Automatic declarative environment is established for
68964 			 *          the duration of the 'catch' clause.
68965 			 *
68966 			 *      If DUK_BC_TRYCATCH_FLAG_WITH_BINDING set:
68967 			 *          reg_catch + 0: with 'target value', which is coerced to
68968 			 *          an object and then used as a bindind object for an
68969 			 *          environment record.  The binding is initialized here, for
68970 			 *          the 'try' clause.
68971 			 *
68972 			 * Note that a TRYCATCH generated for a 'with' statement has no
68973 			 * catch or finally parts.
68974 			 */
68975 
68976 			/* XXX: TRYCATCH handling should be reworked to avoid creating
68977 			 * an explicit scope unless it is actually needed (e.g. function
68978 			 * instances or eval is executed inside the catch block).  This
68979 			 * rework is not trivial because the compiler doesn't have an
68980 			 * intermediate representation.  When the rework is done, the
68981 			 * opcode format can also be made more straightforward.
68982 			 */
68983 
68984 			/* XXX: side effect handling is quite awkward here */
68985 
68986 			DUK_DDD(DUK_DDDPRINT("TRYCATCH: reg_catch=%ld, have_catch=%ld, "
68987 			                     "have_finally=%ld, catch_binding=%ld, with_binding=%ld (flags=0x%02lx)",
68988 			                     (long) DUK_DEC_BC(ins),
68989 			                     (long) (DUK_DEC_A(ins) & DUK_BC_TRYCATCH_FLAG_HAVE_CATCH ? 1 : 0),
68990 			                     (long) (DUK_DEC_A(ins) & DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY ? 1 : 0),
68991 			                     (long) (DUK_DEC_A(ins) & DUK_BC_TRYCATCH_FLAG_CATCH_BINDING ? 1 : 0),
68992 			                     (long) (DUK_DEC_A(ins) & DUK_BC_TRYCATCH_FLAG_WITH_BINDING ? 1 : 0),
68993 			                     (unsigned long) DUK_DEC_A(ins)));
68994 
68995 			a = DUK_DEC_A(ins);
68996 			bc = DUK_DEC_BC(ins);
68997 
68998 			act = thr->callstack + thr->callstack_top - 1;
68999 			DUK_ASSERT(thr->callstack_top >= 1);
69000 
69001 			/* 'with' target must be created first, in case we run out of memory */
69002 			/* XXX: refactor out? */
69003 
69004 			if (a & DUK_BC_TRYCATCH_FLAG_WITH_BINDING) {
69005 				DUK_DDD(DUK_DDDPRINT("need to initialize a with binding object"));
69006 
69007 				if (act->lex_env == NULL) {
69008 					DUK_ASSERT(act->var_env == NULL);
69009 					DUK_DDD(DUK_DDDPRINT("delayed environment initialization"));
69010 
69011 					/* must relookup act in case of side effects */
69012 					duk_js_init_activation_environment_records_delayed(thr, act);
69013 					act = thr->callstack + thr->callstack_top - 1;
69014 					DUK_UNREF(act);  /* 'act' is no longer accessed, scanbuild fix */
69015 				}
69016 				DUK_ASSERT(act->lex_env != NULL);
69017 				DUK_ASSERT(act->var_env != NULL);
69018 
69019 				(void) duk_push_object_helper(ctx,
69020 				                              DUK_HOBJECT_FLAG_EXTENSIBLE |
69021 				                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJENV),
69022 				                              -1);  /* no prototype, updated below */
69023 
69024 				duk_push_tval(ctx, DUK__REGP(bc));
69025 				duk_to_object(ctx, -1);
69026 				duk_dup(ctx, -1);
69027 
69028 				/* [ ... env target ] */
69029 				/* [ ... env target target ] */
69030 
69031 				duk_xdef_prop_stridx(thr, -3, DUK_STRIDX_INT_TARGET, DUK_PROPDESC_FLAGS_NONE);
69032 				duk_xdef_prop_stridx(thr, -2, DUK_STRIDX_INT_THIS, DUK_PROPDESC_FLAGS_NONE);  /* always provideThis=true */
69033 
69034 				/* [ ... env ] */
69035 
69036 				DUK_DDD(DUK_DDDPRINT("environment for with binding: %!iT",
69037 				                     (duk_tval *) duk_get_tval(ctx, -1)));
69038 			}
69039 
69040 			/* allocate catcher and populate it (should be atomic) */
69041 
69042 			duk_hthread_catchstack_grow(thr);
69043 			cat = thr->catchstack + thr->catchstack_top;
69044 			DUK_ASSERT(thr->catchstack_top + 1 <= thr->catchstack_size);
69045 			thr->catchstack_top++;
69046 
69047 			cat->flags = DUK_CAT_TYPE_TCF;
69048 			cat->h_varname = NULL;
69049 
69050 			if (a & DUK_BC_TRYCATCH_FLAG_HAVE_CATCH) {
69051 				cat->flags |= DUK_CAT_FLAG_CATCH_ENABLED;
69052 			}
69053 			if (a & DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY) {
69054 				cat->flags |= DUK_CAT_FLAG_FINALLY_ENABLED;
69055 			}
69056 			if (a & DUK_BC_TRYCATCH_FLAG_CATCH_BINDING) {
69057 				DUK_DDD(DUK_DDDPRINT("catch binding flag set to catcher"));
69058 				cat->flags |= DUK_CAT_FLAG_CATCH_BINDING_ENABLED;
69059 				tv1 = DUK__REGP(bc);
69060 				DUK_ASSERT(DUK_TVAL_IS_STRING(tv1));
69061 
69062 				/* borrowed reference; although 'tv1' comes from a register,
69063 				 * its value was loaded using LDCONST so the constant will
69064 				 * also exist and be reachable.
69065 				 */
69066 				cat->h_varname = DUK_TVAL_GET_STRING(tv1);
69067 			} else if (a & DUK_BC_TRYCATCH_FLAG_WITH_BINDING) {
69068 				/* env created above to stack top */
69069 				duk_hobject *new_env;
69070 
69071 				DUK_DDD(DUK_DDDPRINT("lexenv active flag set to catcher"));
69072 				cat->flags |= DUK_CAT_FLAG_LEXENV_ACTIVE;
69073 
69074 				DUK_DDD(DUK_DDDPRINT("activating object env: %!iT",
69075 				                     (duk_tval *) duk_get_tval(ctx, -1)));
69076 				new_env = DUK_GET_HOBJECT_NEGIDX(ctx, -1);
69077 				DUK_ASSERT(new_env != NULL);
69078 
69079 				act = thr->callstack + thr->callstack_top - 1;  /* relookup (side effects) */
69080 				DUK_ASSERT(act->lex_env != NULL);
69081 				DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, new_env, act->lex_env);  /* side effects */
69082 
69083 				act = thr->callstack + thr->callstack_top - 1;  /* relookup (side effects) */
69084 				act->lex_env = new_env;
69085 				DUK_HOBJECT_INCREF(thr, new_env);
69086 				duk_pop(ctx);
69087 			} else {
69088 				;
69089 			}
69090 
69091 			/* Registers 'bc' and 'bc + 1' are written in longjmp handling
69092 			 * and if their previous values (which are temporaries) become
69093 			 * unreachable -and- have a finalizer, there'll be a function
69094 			 * call during error handling which is not supported now (GH-287).
69095 			 * Ensure that both 'bc' and 'bc + 1' have primitive values to
69096 			 * guarantee no finalizer calls in error handling.  Scrubbing also
69097 			 * ensures finalizers for the previous values run here rather than
69098 			 * later.  Error handling related values are also written to 'bc'
69099 			 * and 'bc + 1' but those values never become unreachable during
69100 			 * error handling, so there's no side effect problem even if the
69101 			 * error value has a finalizer.
69102 			 */
69103 			duk_to_undefined(ctx, bc);
69104 			duk_to_undefined(ctx, bc + 1);
69105 
69106 			cat = thr->catchstack + thr->catchstack_top - 1;  /* relookup (side effects) */
69107 			cat->callstack_index = thr->callstack_top - 1;
69108 			cat->pc_base = (duk_instr_t *) curr_pc;  /* pre-incremented, points to first jump slot */
69109 			cat->idx_base = (duk_size_t) (thr->valstack_bottom - thr->valstack) + bc;
69110 
69111 			DUK_DDD(DUK_DDDPRINT("TRYCATCH catcher: flags=0x%08lx, callstack_index=%ld, pc_base=%ld, "
69112 			                     "idx_base=%ld, h_varname=%!O",
69113 			                     (unsigned long) cat->flags, (long) cat->callstack_index,
69114 			                     (long) cat->pc_base, (long) cat->idx_base, (duk_heaphdr *) cat->h_varname));
69115 
69116 			curr_pc += 2;  /* skip jump slots */
69117 			break;
69118 		}
69119 
69120 		/* Pre/post inc/dec for register variables, important for loops. */
69121 		case DUK_OP_PREINCR:
69122 		case DUK_OP_PREDECR:
69123 		case DUK_OP_POSTINCR:
69124 		case DUK_OP_POSTDECR: {
69125 			duk_context *ctx = (duk_context *) thr;
69126 			duk_small_uint_fast_t a = DUK_DEC_A(ins);
69127 			duk_uint_fast_t bc = DUK_DEC_BC(ins);
69128 			duk_tval *tv1, *tv2;
69129 			duk_double_t x, y, z;
69130 
69131 			/* Two lowest bits of opcode are used to distinguish
69132 			 * variants.  Bit 0 = inc(0)/dec(1), bit 1 = pre(0)/post(1).
69133 			 */
69134 			DUK_ASSERT((DUK_OP_PREINCR & 0x03) == 0x00);
69135 			DUK_ASSERT((DUK_OP_PREDECR & 0x03) == 0x01);
69136 			DUK_ASSERT((DUK_OP_POSTINCR & 0x03) == 0x02);
69137 			DUK_ASSERT((DUK_OP_POSTDECR & 0x03) == 0x03);
69138 
69139 			tv1 = DUK__REGP(bc);
69140 #if defined(DUK_USE_FASTINT)
69141 			if (DUK_TVAL_IS_FASTINT(tv1)) {
69142 				duk_int64_t x_fi, y_fi, z_fi;
69143 				x_fi = DUK_TVAL_GET_FASTINT(tv1);
69144 				if (ins & DUK_ENC_OP(0x01)) {
69145 					if (x_fi == DUK_FASTINT_MIN) {
69146 						goto skip_fastint;
69147 					}
69148 					y_fi = x_fi - 1;
69149 				} else {
69150 					if (x_fi == DUK_FASTINT_MAX) {
69151 						goto skip_fastint;
69152 					}
69153 					y_fi = x_fi + 1;
69154 				}
69155 
69156 				DUK_TVAL_SET_FASTINT(tv1, y_fi);  /* no need for refcount update */
69157 
69158 				tv2 = DUK__REGP(a);
69159 				z_fi = (ins & DUK_ENC_OP(0x02)) ? x_fi : y_fi;
69160 				DUK_TVAL_SET_FASTINT_UPDREF(thr, tv2, z_fi);  /* side effects */
69161 				break;
69162 			}
69163 		 skip_fastint:
69164 #endif
69165 			if (DUK_TVAL_IS_NUMBER(tv1)) {
69166 				/* Fast path for the case where the register
69167 				 * is a number (e.g. loop counter).
69168 				 */
69169 
69170 				x = DUK_TVAL_GET_NUMBER(tv1);
69171 				if (ins & DUK_ENC_OP(0x01)) {
69172 					y = x - 1.0;
69173 				} else {
69174 					y = x + 1.0;
69175 				}
69176 
69177 				DUK_TVAL_SET_NUMBER(tv1, y);  /* no need for refcount update */
69178 			} else {
69179 				x = duk_to_number(ctx, bc);
69180 
69181 				if (ins & DUK_ENC_OP(0x01)) {
69182 					y = x - 1.0;
69183 				} else {
69184 					y = x + 1.0;
69185 				}
69186 
69187 				duk_push_number(ctx, y);
69188 				duk_replace(ctx, bc);
69189 			}
69190 
69191 			tv2 = DUK__REGP(a);
69192 			z = (ins & DUK_ENC_OP(0x02)) ? x : y;
69193 			DUK_TVAL_SET_NUMBER_UPDREF(thr, tv2, z);  /* side effects */
69194 			break;
69195 		}
69196 
69197 		/* Preinc/predec for var-by-name, slow path. */
69198 		case DUK_OP_PREINCV:
69199 		case DUK_OP_PREDECV:
69200 		case DUK_OP_POSTINCV:
69201 		case DUK_OP_POSTDECV: {
69202 			duk_context *ctx = (duk_context *) thr;
69203 			duk_activation *act;
69204 			duk_small_uint_fast_t a = DUK_DEC_A(ins);
69205 			duk_uint_fast_t bc = DUK_DEC_BC(ins);
69206 			duk_double_t x, y;
69207 			duk_tval *tv1;
69208 			duk_hstring *name;
69209 
69210 			/* Two lowest bits of opcode are used to distinguish
69211 			 * variants.  Bit 0 = inc(0)/dec(1), bit 1 = pre(0)/post(1).
69212 			 */
69213 			DUK_ASSERT((DUK_OP_PREINCV & 0x03) == 0x00);
69214 			DUK_ASSERT((DUK_OP_PREDECV & 0x03) == 0x01);
69215 			DUK_ASSERT((DUK_OP_POSTINCV & 0x03) == 0x02);
69216 			DUK_ASSERT((DUK_OP_POSTDECV & 0x03) == 0x03);
69217 
69218 			tv1 = DUK__CONSTP(bc);
69219 			DUK_ASSERT(DUK_TVAL_IS_STRING(tv1));
69220 			name = DUK_TVAL_GET_STRING(tv1);
69221 			DUK_ASSERT(name != NULL);
69222 			act = thr->callstack + thr->callstack_top - 1;
69223 			(void) duk_js_getvar_activation(thr, act, name, 1 /*throw*/);  /* -> [... val this] */
69224 
69225 			/* XXX: fastint fast path would be very useful here */
69226 
69227 			x = duk_to_number(ctx, -2);
69228 			duk_pop_2(ctx);
69229 			if (ins & DUK_ENC_OP(0x01)) {
69230 				y = x - 1.0;
69231 			} else {
69232 				y = x + 1.0;
69233 			}
69234 
69235 			duk_push_number(ctx, y);
69236 			tv1 = DUK_GET_TVAL_NEGIDX(ctx, -1);
69237 			DUK_ASSERT(tv1 != NULL);
69238 			act = thr->callstack + thr->callstack_top - 1;
69239 			duk_js_putvar_activation(thr, act, name, tv1, DUK__STRICT());
69240 			duk_pop(ctx);
69241 
69242 			duk_push_number(ctx, (ins & DUK_ENC_OP(0x02)) ? x : y);
69243 			duk_replace(ctx, (duk_idx_t) a);
69244 			break;
69245 		}
69246 
69247 		/* Preinc/predec for object properties. */
69248 		case DUK_OP_PREINCP:
69249 		case DUK_OP_PREDECP:
69250 		case DUK_OP_POSTINCP:
69251 		case DUK_OP_POSTDECP: {
69252 			duk_context *ctx = (duk_context *) thr;
69253 			duk_small_uint_fast_t a = DUK_DEC_A(ins);
69254 			duk_small_uint_fast_t b = DUK_DEC_B(ins);
69255 			duk_small_uint_fast_t c = DUK_DEC_C(ins);
69256 			duk_tval *tv_obj;
69257 			duk_tval *tv_key;
69258 			duk_tval *tv_val;
69259 			duk_bool_t rc;
69260 			duk_double_t x, y;
69261 
69262 			/* A -> target reg
69263 			 * B -> object reg/const (may be const e.g. in "'foo'[1]")
69264 			 * C -> key reg/const
69265 			 */
69266 
69267 			/* Two lowest bits of opcode are used to distinguish
69268 			 * variants.  Bit 0 = inc(0)/dec(1), bit 1 = pre(0)/post(1).
69269 			 */
69270 			DUK_ASSERT((DUK_OP_PREINCP & 0x03) == 0x00);
69271 			DUK_ASSERT((DUK_OP_PREDECP & 0x03) == 0x01);
69272 			DUK_ASSERT((DUK_OP_POSTINCP & 0x03) == 0x02);
69273 			DUK_ASSERT((DUK_OP_POSTDECP & 0x03) == 0x03);
69274 
69275 			tv_obj = DUK__REGCONSTP(b);
69276 			tv_key = DUK__REGCONSTP(c);
69277 			rc = duk_hobject_getprop(thr, tv_obj, tv_key);  /* -> [val] */
69278 			DUK_UNREF(rc);  /* ignore */
69279 			tv_obj = NULL;  /* invalidated */
69280 			tv_key = NULL;  /* invalidated */
69281 
69282 			x = duk_to_number(ctx, -1);
69283 			duk_pop(ctx);
69284 			if (ins & DUK_ENC_OP(0x01)) {
69285 				y = x - 1.0;
69286 			} else {
69287 				y = x + 1.0;
69288 			}
69289 
69290 			duk_push_number(ctx, y);
69291 			tv_val = DUK_GET_TVAL_NEGIDX(ctx, -1);
69292 			DUK_ASSERT(tv_val != NULL);
69293 			tv_obj = DUK__REGCONSTP(b);
69294 			tv_key = DUK__REGCONSTP(c);
69295 			rc = duk_hobject_putprop(thr, tv_obj, tv_key, tv_val, DUK__STRICT());
69296 			DUK_UNREF(rc);  /* ignore */
69297 			tv_obj = NULL;  /* invalidated */
69298 			tv_key = NULL;  /* invalidated */
69299 			duk_pop(ctx);
69300 
69301 			duk_push_number(ctx, (ins & DUK_ENC_OP(0x02)) ? x : y);
69302 			duk_replace(ctx, (duk_idx_t) a);
69303 			break;
69304 		}
69305 
69306 		case DUK_OP_EXTRA: {
69307 			/* XXX: shared decoding of 'b' and 'c'? */
69308 
69309 			duk_small_uint_fast_t extraop = DUK_DEC_A(ins);
69310 			switch ((int) extraop) {
69311 			/* XXX: switch cast? */
69312 
69313 			case DUK_EXTRAOP_NOP: {
69314 				/* nop */
69315 				break;
69316 			}
69317 
69318 			case DUK_EXTRAOP_INVALID: {
69319 				DUK_ERROR_FMT1(thr, DUK_ERR_INTERNAL_ERROR, "INVALID opcode (%ld)", (long) DUK_DEC_BC(ins));
69320 				break;
69321 			}
69322 
69323 			case DUK_EXTRAOP_LDTHIS: {
69324 				/* Note: 'this' may be bound to any value, not just an object */
69325 				duk_uint_fast_t bc = DUK_DEC_BC(ins);
69326 				duk_tval *tv1, *tv2;
69327 
69328 				tv1 = DUK__REGP(bc);
69329 				tv2 = thr->valstack_bottom - 1;  /* 'this binding' is just under bottom */
69330 				DUK_ASSERT(tv2 >= thr->valstack);
69331 
69332 				DUK_DDD(DUK_DDDPRINT("LDTHIS: %!T to r%ld", (duk_tval *) tv2, (long) bc));
69333 
69334 				DUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv1, tv2);  /* side effects */
69335 				break;
69336 			}
69337 
69338 			case DUK_EXTRAOP_LDUNDEF: {
69339 				duk_uint_fast_t bc = DUK_DEC_BC(ins);
69340 				duk_tval *tv1;
69341 
69342 				tv1 = DUK__REGP(bc);
69343 				DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv1);  /* side effects */
69344 				break;
69345 			}
69346 
69347 			case DUK_EXTRAOP_LDNULL: {
69348 				duk_uint_fast_t bc = DUK_DEC_BC(ins);
69349 				duk_tval *tv1;
69350 
69351 				tv1 = DUK__REGP(bc);
69352 				DUK_TVAL_SET_NULL_UPDREF(thr, tv1);  /* side effects */
69353 				break;
69354 			}
69355 
69356 			case DUK_EXTRAOP_LDTRUE:
69357 			case DUK_EXTRAOP_LDFALSE: {
69358 				duk_uint_fast_t bc = DUK_DEC_BC(ins);
69359 				duk_tval *tv1;
69360 				duk_small_uint_fast_t bval = (extraop == DUK_EXTRAOP_LDTRUE ? 1 : 0);
69361 
69362 				tv1 = DUK__REGP(bc);
69363 				DUK_TVAL_SET_BOOLEAN_UPDREF(thr, tv1, bval);  /* side effects */
69364 				break;
69365 			}
69366 
69367 			case DUK_EXTRAOP_NEWOBJ: {
69368 				duk_context *ctx = (duk_context *) thr;
69369 				duk_small_uint_fast_t b = DUK_DEC_B(ins);
69370 
69371 				duk_push_object(ctx);
69372 				duk_replace(ctx, (duk_idx_t) b);
69373 				break;
69374 			}
69375 
69376 			case DUK_EXTRAOP_NEWARR: {
69377 				duk_context *ctx = (duk_context *) thr;
69378 				duk_small_uint_fast_t b = DUK_DEC_B(ins);
69379 
69380 				duk_push_array(ctx);
69381 				duk_replace(ctx, (duk_idx_t) b);
69382 				break;
69383 			}
69384 
69385 			case DUK_EXTRAOP_SETALEN: {
69386 				duk_small_uint_fast_t b;
69387 				duk_small_uint_fast_t c;
69388 				duk_tval *tv1;
69389 				duk_hobject *h;
69390 				duk_uint32_t len;
69391 
69392 				b = DUK_DEC_B(ins); tv1 = DUK__REGP(b);
69393 				DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv1));
69394 				h = DUK_TVAL_GET_OBJECT(tv1);
69395 
69396 				c = DUK_DEC_C(ins); tv1 = DUK__REGP(c);
69397 				DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv1));
69398 				len = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv1);
69399 
69400 				duk_hobject_set_length(thr, h, len);
69401 
69402 				break;
69403 			}
69404 
69405 			case DUK_EXTRAOP_TYPEOF: {
69406 				duk_context *ctx = (duk_context *) thr;
69407 				duk_uint_fast_t bc = DUK_DEC_BC(ins);
69408 				duk_push_hstring(ctx, duk_js_typeof(thr, DUK__REGP(bc)));
69409 				duk_replace(ctx, (duk_idx_t) bc);
69410 				break;
69411 			}
69412 
69413 			case DUK_EXTRAOP_TYPEOFID: {
69414 				duk_context *ctx = (duk_context *) thr;
69415 				duk_activation *act;
69416 				duk_small_uint_fast_t b = DUK_DEC_B(ins);
69417 				duk_small_uint_fast_t c = DUK_DEC_C(ins);
69418 				duk_hstring *name;
69419 				duk_tval *tv;
69420 
69421 				/* B -> target register
69422 				 * C -> constant index of identifier name
69423 				 */
69424 
69425 				tv = DUK__REGCONSTP(c);  /* XXX: this could be a DUK__CONSTP instead */
69426 				DUK_ASSERT(DUK_TVAL_IS_STRING(tv));
69427 				name = DUK_TVAL_GET_STRING(tv);
69428 				act = thr->callstack + thr->callstack_top - 1;
69429 				if (duk_js_getvar_activation(thr, act, name, 0 /*throw*/)) {
69430 					/* -> [... val this] */
69431 					tv = DUK_GET_TVAL_NEGIDX(ctx, -2);
69432 					duk_push_hstring(ctx, duk_js_typeof(thr, tv));
69433 					duk_replace(ctx, (duk_idx_t) b);
69434 					duk_pop_2(ctx);
69435 				} else {
69436 					/* unresolvable, no stack changes */
69437 					duk_push_hstring_stridx(ctx, DUK_STRIDX_LC_UNDEFINED);
69438 					duk_replace(ctx, (duk_idx_t) b);
69439 				}
69440 
69441 				break;
69442 			}
69443 
69444 			case DUK_EXTRAOP_INITENUM: {
69445 				duk_context *ctx = (duk_context *) thr;
69446 				duk_small_uint_fast_t b = DUK_DEC_B(ins);
69447 				duk_small_uint_fast_t c = DUK_DEC_C(ins);
69448 
69449 				/*
69450 				 *  Enumeration semantics come from for-in statement, E5 Section 12.6.4.
69451 				 *  If called with 'null' or 'undefined', this opcode returns 'null' as
69452 				 *  the enumerator, which is special cased in NEXTENUM.  This simplifies
69453 				 *  the compiler part
69454 				 */
69455 
69456 				/* B -> register for writing enumerator object
69457 				 * C -> value to be enumerated (register)
69458 				 */
69459 
69460 				if (duk_is_null_or_undefined(ctx, (duk_idx_t) c)) {
69461 					duk_push_null(ctx);
69462 					duk_replace(ctx, (duk_idx_t) b);
69463 				} else {
69464 					duk_dup(ctx, (duk_idx_t) c);
69465 					duk_to_object(ctx, -1);
69466 					duk_hobject_enumerator_create(ctx, 0 /*enum_flags*/);  /* [ ... val ] --> [ ... enum ] */
69467 					duk_replace(ctx, (duk_idx_t) b);
69468 				}
69469 				break;
69470 			}
69471 
69472 			case DUK_EXTRAOP_NEXTENUM: {
69473 				duk_context *ctx = (duk_context *) thr;
69474 				duk_small_uint_fast_t b = DUK_DEC_B(ins);
69475 				duk_small_uint_fast_t c = DUK_DEC_C(ins);
69476 
69477 				/*
69478 				 *  NEXTENUM checks whether the enumerator still has unenumerated
69479 				 *  keys.  If so, the next key is loaded to the target register
69480 				 *  and the next instruction is skipped.  Otherwise the next instruction
69481 				 *  will be executed, jumping out of the enumeration loop.
69482 				 */
69483 
69484 				/* B -> target register for next key
69485 				 * C -> enum register
69486 				 */
69487 
69488 				DUK_DDD(DUK_DDDPRINT("NEXTENUM: b->%!T, c->%!T",
69489 				                     (duk_tval *) duk_get_tval(ctx, (duk_idx_t) b),
69490 				                     (duk_tval *) duk_get_tval(ctx, (duk_idx_t) c)));
69491 
69492 				if (duk_is_object(ctx, (duk_idx_t) c)) {
69493 					/* XXX: assert 'c' is an enumerator */
69494 					duk_dup(ctx, (duk_idx_t) c);
69495 					if (duk_hobject_enumerator_next(ctx, 0 /*get_value*/)) {
69496 						/* [ ... enum ] -> [ ... next_key ] */
69497 						DUK_DDD(DUK_DDDPRINT("enum active, next key is %!T, skip jump slot ",
69498 						                     (duk_tval *) duk_get_tval(ctx, -1)));
69499 						curr_pc++;
69500 					} else {
69501 						/* [ ... enum ] -> [ ... ] */
69502 						DUK_DDD(DUK_DDDPRINT("enum finished, execute jump slot"));
69503 						duk_push_undefined(ctx);
69504 					}
69505 					duk_replace(ctx, (duk_idx_t) b);
69506 				} else {
69507 					/* 'null' enumerator case -> behave as with an empty enumerator */
69508 					DUK_ASSERT(duk_is_null(ctx, (duk_idx_t) c));
69509 					DUK_DDD(DUK_DDDPRINT("enum is null, execute jump slot"));
69510 				}
69511 				break;
69512 			}
69513 
69514 			case DUK_EXTRAOP_INITSET:
69515 			case DUK_EXTRAOP_INITSETI:
69516 			case DUK_EXTRAOP_INITGET:
69517 			case DUK_EXTRAOP_INITGETI: {
69518 				duk_context *ctx = (duk_context *) thr;
69519 				duk_bool_t is_set = (extraop == DUK_EXTRAOP_INITSET || extraop == DUK_EXTRAOP_INITSETI);
69520 				duk_small_uint_fast_t b = DUK_DEC_B(ins);
69521 				duk_uint_fast_t idx;
69522 
69523 				/* B -> object register
69524 				 * C -> C+0 contains key, C+1 closure (value)
69525 				 */
69526 
69527 				/*
69528 				 *  INITSET/INITGET are only used to initialize object literal keys.
69529 				 *  The compiler ensures that there cannot be a previous data property
69530 				 *  of the same name.  It also ensures that setter and getter can only
69531 				 *  be initialized once (or not at all).
69532 				 */
69533 
69534 				idx = (duk_uint_fast_t) DUK_DEC_C(ins);
69535 				if (extraop == DUK_EXTRAOP_INITSETI || extraop == DUK_EXTRAOP_INITGETI) {
69536 					duk_tval *tv_ind = DUK__REGP(idx);
69537 					DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_ind));
69538 					idx = (duk_uint_fast_t) DUK_TVAL_GET_NUMBER(tv_ind);
69539 				}
69540 
69541 #if defined(DUK_USE_EXEC_INDIRECT_BOUND_CHECK)
69542 				if (idx + 2 > (duk_uint_fast_t) duk_get_top(ctx)) {
69543 					/* XXX: use duk_is_valid_index() instead? */
69544 					/* XXX: improve check; check against nregs, not against top */
69545 					DUK__INTERNAL_ERROR("INITSET/INITGET out of bounds");
69546 				}
69547 #endif
69548 
69549 				/* XXX: this is now a very unoptimal implementation -- this can be
69550 				 * made very simple by direct manipulation of the object internals,
69551 				 * given the guarantees above.
69552 				 */
69553 
69554 				duk_push_hobject_bidx(ctx, DUK_BIDX_OBJECT_CONSTRUCTOR);
69555 				duk_get_prop_stridx(ctx, -1, DUK_STRIDX_DEFINE_PROPERTY);
69556 				duk_push_undefined(ctx);
69557 				duk_dup(ctx, (duk_idx_t) b);
69558 				duk_dup(ctx, (duk_idx_t) (idx + 0));
69559 				duk_push_object(ctx);  /* -> [ Object defineProperty undefined obj key desc ] */
69560 
69561 				duk_push_true(ctx);
69562 				duk_put_prop_stridx(ctx, -2, DUK_STRIDX_ENUMERABLE);
69563 				duk_push_true(ctx);
69564 				duk_put_prop_stridx(ctx, -2, DUK_STRIDX_CONFIGURABLE);
69565 				duk_dup(ctx, (duk_idx_t) (idx + 1));
69566 				duk_put_prop_stridx(ctx, -2, (is_set ? DUK_STRIDX_SET : DUK_STRIDX_GET));
69567 
69568 				DUK_DDD(DUK_DDDPRINT("INITGET/INITSET: obj=%!T, key=%!T, desc=%!T",
69569 				                     (duk_tval *) duk_get_tval(ctx, -3),
69570 				                     (duk_tval *) duk_get_tval(ctx, -2),
69571 				                     (duk_tval *) duk_get_tval(ctx, -1)));
69572 
69573 				duk_call_method(ctx, 3);  /* -> [ Object res ] */
69574 				duk_pop_2(ctx);
69575 
69576 				DUK_DDD(DUK_DDDPRINT("INITGET/INITSET AFTER: obj=%!T",
69577 				                     (duk_tval *) duk_get_tval(ctx, (duk_idx_t) b)));
69578 				break;
69579 			}
69580 
69581 			case DUK_EXTRAOP_ENDTRY: {
69582 				duk_catcher *cat;
69583 				duk_tval *tv1;
69584 
69585 				DUK_ASSERT(thr->catchstack_top >= 1);
69586 				DUK_ASSERT(thr->callstack_top >= 1);
69587 				DUK_ASSERT(thr->catchstack[thr->catchstack_top - 1].callstack_index == thr->callstack_top - 1);
69588 
69589 				cat = thr->catchstack + thr->catchstack_top - 1;
69590 
69591 				DUK_DDD(DUK_DDDPRINT("ENDTRY: clearing catch active flag (regardless of whether it was set or not)"));
69592 				DUK_CAT_CLEAR_CATCH_ENABLED(cat);
69593 
69594 				if (DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
69595 					DUK_DDD(DUK_DDDPRINT("ENDTRY: finally part is active, jump through 2nd jump slot with 'normal continuation'"));
69596 
69597 					tv1 = thr->valstack + cat->idx_base;
69598 					DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);
69599 					DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv1);  /* side effects */
69600 					tv1 = NULL;
69601 
69602 					tv1 = thr->valstack + cat->idx_base + 1;
69603 					DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);
69604 					DUK_TVAL_SET_FASTINT_U32_UPDREF(thr, tv1, (duk_uint32_t) DUK_LJ_TYPE_NORMAL);  /* side effects */
69605 					tv1 = NULL;
69606 
69607 					DUK_CAT_CLEAR_FINALLY_ENABLED(cat);
69608 				} else {
69609 					DUK_DDD(DUK_DDDPRINT("ENDTRY: no finally part, dismantle catcher, jump through 2nd jump slot (to end of statement)"));
69610 					duk_hthread_catchstack_unwind(thr, thr->catchstack_top - 1);
69611 					/* no need to unwind callstack */
69612 				}
69613 
69614 				curr_pc = cat->pc_base + 1;
69615 				break;
69616 			}
69617 
69618 			case DUK_EXTRAOP_ENDCATCH: {
69619 				duk_activation *act;
69620 				duk_catcher *cat;
69621 				duk_tval *tv1;
69622 
69623 				DUK_ASSERT(thr->catchstack_top >= 1);
69624 				DUK_ASSERT(thr->callstack_top >= 1);
69625 				DUK_ASSERT(thr->catchstack[thr->catchstack_top - 1].callstack_index == thr->callstack_top - 1);
69626 
69627 				cat = thr->catchstack + thr->catchstack_top - 1;
69628 				DUK_ASSERT(!DUK_CAT_HAS_CATCH_ENABLED(cat));  /* cleared before entering catch part */
69629 
69630 				act = thr->callstack + thr->callstack_top - 1;
69631 
69632 				if (DUK_CAT_HAS_LEXENV_ACTIVE(cat)) {
69633 					duk_hobject *prev_env;
69634 
69635 					/* 'with' binding has no catch clause, so can't be here unless a normal try-catch */
69636 					DUK_ASSERT(DUK_CAT_HAS_CATCH_BINDING_ENABLED(cat));
69637 					DUK_ASSERT(act->lex_env != NULL);
69638 
69639 					DUK_DDD(DUK_DDDPRINT("ENDCATCH: popping catcher part lexical environment"));
69640 
69641 					prev_env = act->lex_env;
69642 					DUK_ASSERT(prev_env != NULL);
69643 					act->lex_env = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, prev_env);
69644 					DUK_CAT_CLEAR_LEXENV_ACTIVE(cat);
69645 					DUK_HOBJECT_DECREF(thr, prev_env);  /* side effects */
69646 				}
69647 
69648 				if (DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
69649 					DUK_DDD(DUK_DDDPRINT("ENDCATCH: finally part is active, jump through 2nd jump slot with 'normal continuation'"));
69650 
69651 					tv1 = thr->valstack + cat->idx_base;
69652 					DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);
69653 					DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv1);  /* side effects */
69654 					tv1 = NULL;
69655 
69656 					tv1 = thr->valstack + cat->idx_base + 1;
69657 					DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);
69658 					DUK_TVAL_SET_FASTINT_U32_UPDREF(thr, tv1, (duk_uint32_t) DUK_LJ_TYPE_NORMAL);  /* side effects */
69659 					tv1 = NULL;
69660 
69661 					DUK_CAT_CLEAR_FINALLY_ENABLED(cat);
69662 				} else {
69663 					DUK_DDD(DUK_DDDPRINT("ENDCATCH: no finally part, dismantle catcher, jump through 2nd jump slot (to end of statement)"));
69664 					duk_hthread_catchstack_unwind(thr, thr->catchstack_top - 1);
69665 					/* no need to unwind callstack */
69666 				}
69667 
69668 				curr_pc = cat->pc_base + 1;
69669 				break;
69670 			}
69671 
69672 			case DUK_EXTRAOP_ENDFIN: {
69673 				duk_context *ctx = (duk_context *) thr;
69674 				duk_catcher *cat;
69675 				duk_tval *tv1;
69676 				duk_small_uint_t cont_type;
69677 				duk_small_uint_t ret_result;
69678 
69679 				/* Sync and NULL early. */
69680 				DUK__SYNC_AND_NULL_CURR_PC();
69681 
69682 				DUK_ASSERT(thr->catchstack_top >= 1);
69683 				DUK_ASSERT(thr->callstack_top >= 1);
69684 				DUK_ASSERT(thr->catchstack[thr->catchstack_top - 1].callstack_index == thr->callstack_top - 1);
69685 
69686 				cat = thr->catchstack + thr->catchstack_top - 1;
69687 
69688 				/* CATCH flag may be enabled or disabled here; it may be enabled if
69689 				 * the statement has a catch block but the try block does not throw
69690 				 * an error.
69691 				 */
69692 				DUK_ASSERT(!DUK_CAT_HAS_FINALLY_ENABLED(cat));  /* cleared before entering finally */
69693 				/* XXX: assert idx_base */
69694 
69695 				DUK_DDD(DUK_DDDPRINT("ENDFIN: completion value=%!T, type=%!T",
69696 				                     (duk_tval *) (thr->valstack + cat->idx_base + 0),
69697 				                     (duk_tval *) (thr->valstack + cat->idx_base + 1)));
69698 
69699 				tv1 = thr->valstack + cat->idx_base + 1;  /* type */
69700 				DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv1));
69701 				cont_type = (duk_small_uint_t) DUK_TVAL_GET_NUMBER(tv1);
69702 
69703 				switch (cont_type) {
69704 				case DUK_LJ_TYPE_NORMAL: {
69705 					DUK_DDD(DUK_DDDPRINT("ENDFIN: finally part finishing with 'normal' (non-abrupt) completion -> "
69706 					                     "dismantle catcher, resume execution after ENDFIN"));
69707 					duk_hthread_catchstack_unwind(thr, thr->catchstack_top - 1);
69708 					/* no need to unwind callstack */
69709 					goto restart_execution;
69710 				}
69711 				case DUK_LJ_TYPE_RETURN: {
69712 					DUK_DDD(DUK_DDDPRINT("ENDFIN: finally part finishing with 'return' complation -> dismantle "
69713 					                     "catcher, handle return, lj.value1=%!T", thr->valstack + cat->idx_base));
69714 
69715 					/* Not necessary to unwind catchstack: return handling will
69716 					 * do it.  The finally flag of 'cat' is no longer set.  The
69717 					 * catch flag may be set, but it's not checked by return handling.
69718 					 */
69719 					DUK_ASSERT(!DUK_CAT_HAS_FINALLY_ENABLED(cat));  /* cleared before entering finally */
69720 #if 0
69721 					duk_hthread_catchstack_unwind(thr, thr->catchstack_top - 1);
69722 #endif
69723 
69724 					duk_push_tval(ctx, thr->valstack + cat->idx_base);
69725 					ret_result = duk__handle_return(thr,
69726 						                        entry_thread,
69727 						                        entry_callstack_top);
69728 					if (ret_result == DUK__RETHAND_RESTART) {
69729 						goto restart_execution;
69730 					}
69731 					DUK_ASSERT(ret_result == DUK__RETHAND_FINISHED);
69732 
69733 					DUK_DDD(DUK_DDDPRINT("exiting executor after ENDFIN and RETURN (pseudo) longjmp type"));
69734 					return;
69735 				}
69736 				case DUK_LJ_TYPE_BREAK:
69737 				case DUK_LJ_TYPE_CONTINUE: {
69738 					duk_uint_t label_id;
69739 					duk_small_uint_t lj_type;
69740 
69741 					/* Not necessary to unwind catchstack: break/continue
69742 					 * handling will do it.  The finally flag of 'cat' is
69743 					 * no longer set.  The catch flag may be set, but it's
69744 					 * not checked by break/continue handling.
69745 					 */
69746 #if 0
69747 					duk_hthread_catchstack_unwind(thr, thr->catchstack_top - 1);
69748 #endif
69749 
69750 					tv1 = thr->valstack + cat->idx_base;
69751 					DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv1));
69752 #if defined(DUK_USE_FASTINT)
69753 					DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv1));
69754 					label_id = (duk_small_uint_t) DUK_TVAL_GET_FASTINT_U32(tv1);
69755 #else
69756 					label_id = (duk_small_uint_t) DUK_TVAL_GET_NUMBER(tv1);
69757 #endif
69758 					lj_type = cont_type;
69759 					duk__handle_break_or_continue(thr, label_id, lj_type);
69760 					goto restart_execution;
69761 				}
69762 				default: {
69763 					DUK_DDD(DUK_DDDPRINT("ENDFIN: finally part finishing with abrupt completion, lj_type=%ld -> "
69764 					                     "dismantle catcher, re-throw error",
69765 					                     (long) cont_type));
69766 
69767 					duk_push_tval(ctx, thr->valstack + cat->idx_base);
69768 
69769 					duk_err_setup_heap_ljstate(thr, (duk_small_int_t) cont_type);
69770 
69771 					DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL);  /* always in executor */
69772 					duk_err_longjmp(thr);
69773 					DUK_UNREACHABLE();
69774 				}
69775 				}
69776 
69777 				/* Must restart in all cases because we NULLed thr->ptr_curr_pc. */
69778 				DUK_UNREACHABLE();
69779 				break;
69780 			}
69781 
69782 			case DUK_EXTRAOP_THROW: {
69783 				duk_context *ctx = (duk_context *) thr;
69784 				duk_uint_fast_t bc = DUK_DEC_BC(ins);
69785 
69786 				/* Note: errors are augmented when they are created, not
69787 				 * when they are thrown.  So, don't augment here, it would
69788 				 * break re-throwing for instance.
69789 				 */
69790 
69791 				/* Sync so that augmentation sees up-to-date activations, NULL
69792 				 * thr->ptr_curr_pc so that it's not used if side effects occur
69793 				 * in augmentation or longjmp handling.
69794 				 */
69795 				DUK__SYNC_AND_NULL_CURR_PC();
69796 
69797 				duk_dup(ctx, (duk_idx_t) bc);
69798 				DUK_DDD(DUK_DDDPRINT("THROW ERROR (BYTECODE): %!dT (before throw augment)",
69799 				                     (duk_tval *) duk_get_tval(ctx, -1)));
69800 #if defined(DUK_USE_AUGMENT_ERROR_THROW)
69801 				duk_err_augment_error_throw(thr);
69802 				DUK_DDD(DUK_DDDPRINT("THROW ERROR (BYTECODE): %!dT (after throw augment)",
69803 				                     (duk_tval *) duk_get_tval(ctx, -1)));
69804 #endif
69805 
69806 				duk_err_setup_heap_ljstate(thr, DUK_LJ_TYPE_THROW);
69807 
69808 				DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL);  /* always in executor */
69809 				duk_err_longjmp(thr);
69810 				DUK_UNREACHABLE();
69811 				break;
69812 			}
69813 
69814 			case DUK_EXTRAOP_INVLHS: {
69815 				DUK_ERROR(thr, DUK_ERR_REFERENCE_ERROR, "invalid lvalue");
69816 
69817 				DUK_UNREACHABLE();
69818 				break;
69819 			}
69820 
69821 			case DUK_EXTRAOP_UNM:
69822 			case DUK_EXTRAOP_UNP: {
69823 				duk_uint_fast_t bc = DUK_DEC_BC(ins);
69824 				duk__vm_arith_unary_op(thr, DUK__REGP(bc), bc, extraop);
69825 				break;
69826 			}
69827 
69828 			case DUK_EXTRAOP_DEBUGGER: {
69829 				/* Opcode only emitted by compiler when debugger
69830 				 * support is enabled.  Ignore it silently without
69831 				 * debugger support, in case it has been loaded
69832 				 * from precompiled bytecode.
69833 				 */
69834 #if defined(DUK_USE_DEBUGGER_SUPPORT)
69835 				if (DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap)) {
69836 					DUK_D(DUK_DPRINT("DEBUGGER statement encountered, halt execution"));
69837 					DUK__SYNC_AND_NULL_CURR_PC();
69838 					duk_debug_halt_execution(thr, 1 /*use_prev_pc*/);
69839 					DUK_D(DUK_DPRINT("DEBUGGER statement finished, resume execution"));
69840 					goto restart_execution;
69841 				} else {
69842 					DUK_D(DUK_DPRINT("DEBUGGER statement ignored, debugger not attached"));
69843 				}
69844 #else
69845 				DUK_D(DUK_DPRINT("DEBUGGER statement ignored, no debugger support"));
69846 #endif
69847 				break;
69848 			}
69849 
69850 			case DUK_EXTRAOP_BREAK: {
69851 				duk_uint_fast_t bc = DUK_DEC_BC(ins);
69852 
69853 				DUK_DDD(DUK_DDDPRINT("BREAK: %ld", (long) bc));
69854 
69855 				DUK__SYNC_AND_NULL_CURR_PC();
69856 				duk__handle_break_or_continue(thr, (duk_uint_t) bc, DUK_LJ_TYPE_BREAK);
69857 				goto restart_execution;
69858 			}
69859 
69860 			case DUK_EXTRAOP_CONTINUE: {
69861 				duk_uint_fast_t bc = DUK_DEC_BC(ins);
69862 
69863 				DUK_DDD(DUK_DDDPRINT("CONTINUE: %ld", (long) bc));
69864 
69865 				DUK__SYNC_AND_NULL_CURR_PC();
69866 				duk__handle_break_or_continue(thr, (duk_uint_t) bc, DUK_LJ_TYPE_CONTINUE);
69867 				goto restart_execution;
69868 			}
69869 
69870 			case DUK_EXTRAOP_BNOT: {
69871 				duk_uint_fast_t bc = DUK_DEC_BC(ins);
69872 
69873 				duk__vm_bitwise_not(thr, DUK__REGP(bc), bc);
69874 				break;
69875 			}
69876 
69877 			case DUK_EXTRAOP_LNOT: {
69878 				duk_uint_fast_t bc = DUK_DEC_BC(ins);
69879 				duk_tval *tv1;
69880 
69881 				tv1 = DUK__REGP(bc);
69882 				duk__vm_logical_not(thr, tv1, tv1);
69883 				break;
69884 			}
69885 
69886 			case DUK_EXTRAOP_INSTOF: {
69887 				duk_context *ctx = (duk_context *) thr;
69888 				duk_small_uint_fast_t b = DUK_DEC_B(ins);
69889 				duk_small_uint_fast_t c = DUK_DEC_C(ins);
69890 				duk_bool_t tmp;
69891 
69892 				tmp = duk_js_instanceof(thr, DUK__REGP(b), DUK__REGCONSTP(c));
69893 				duk_push_boolean(ctx, tmp);
69894 				duk_replace(ctx, (duk_idx_t) b);
69895 				break;
69896 			}
69897 
69898 			case DUK_EXTRAOP_IN: {
69899 				duk_context *ctx = (duk_context *) thr;
69900 				duk_small_uint_fast_t b = DUK_DEC_B(ins);
69901 				duk_small_uint_fast_t c = DUK_DEC_C(ins);
69902 				duk_bool_t tmp;
69903 
69904 				tmp = duk_js_in(thr, DUK__REGP(b), DUK__REGCONSTP(c));
69905 				duk_push_boolean(ctx, tmp);
69906 				duk_replace(ctx, (duk_idx_t) b);
69907 				break;
69908 			}
69909 
69910 			case DUK_EXTRAOP_LABEL: {
69911 				duk_catcher *cat;
69912 				duk_uint_fast_t bc = DUK_DEC_BC(ins);
69913 
69914 				/* allocate catcher and populate it (should be atomic) */
69915 
69916 				duk_hthread_catchstack_grow(thr);
69917 				cat = thr->catchstack + thr->catchstack_top;
69918 				thr->catchstack_top++;
69919 
69920 				cat->flags = DUK_CAT_TYPE_LABEL | (bc << DUK_CAT_LABEL_SHIFT);
69921 				cat->callstack_index = thr->callstack_top - 1;
69922 				cat->pc_base = (duk_instr_t *) curr_pc;  /* pre-incremented, points to first jump slot */
69923 				cat->idx_base = 0;  /* unused for label */
69924 				cat->h_varname = NULL;
69925 
69926 				DUK_DDD(DUK_DDDPRINT("LABEL catcher: flags=0x%08lx, callstack_index=%ld, pc_base=%ld, "
69927 				                     "idx_base=%ld, h_varname=%!O, label_id=%ld",
69928 				                     (long) cat->flags, (long) cat->callstack_index, (long) cat->pc_base,
69929 				                     (long) cat->idx_base, (duk_heaphdr *) cat->h_varname, (long) DUK_CAT_GET_LABEL(cat)));
69930 
69931 				curr_pc += 2;  /* skip jump slots */
69932 				break;
69933 			}
69934 
69935 			case DUK_EXTRAOP_ENDLABEL: {
69936 				duk_catcher *cat;
69937 #if defined(DUK_USE_DDDPRINT) || defined(DUK_USE_ASSERTIONS)
69938 				duk_uint_fast_t bc = DUK_DEC_BC(ins);
69939 #endif
69940 #if defined(DUK_USE_DDDPRINT)
69941 				DUK_DDD(DUK_DDDPRINT("ENDLABEL %ld", (long) bc));
69942 #endif
69943 
69944 				DUK_ASSERT(thr->catchstack_top >= 1);
69945 
69946 				cat = thr->catchstack + thr->catchstack_top - 1;
69947 				DUK_UNREF(cat);
69948 				DUK_ASSERT(DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_LABEL);
69949 				DUK_ASSERT((duk_uint_fast_t) DUK_CAT_GET_LABEL(cat) == bc);
69950 
69951 				duk_hthread_catchstack_unwind(thr, thr->catchstack_top - 1);
69952 				/* no need to unwind callstack */
69953 				break;
69954 			}
69955 
69956 			default: {
69957 				DUK__INTERNAL_ERROR("invalid extra opcode");
69958 			}
69959 
69960 			}  /* end switch */
69961 
69962 			break;
69963 		}
69964 
69965 		default: {
69966 			/* this should never be possible, because the switch-case is
69967 			 * comprehensive
69968 			 */
69969 			DUK__INTERNAL_ERROR("invalid opcode");
69970 			break;
69971 		}
69972 
69973 		}  /* end switch */
69974 	}
69975 	DUK_UNREACHABLE();
69976 
69977 #ifndef DUK_USE_VERBOSE_EXECUTOR_ERRORS
69978  internal_error:
69979 	DUK_ERROR_INTERNAL(thr, "internal error in bytecode executor");
69980 #endif
69981 }
69982 
69983 #undef DUK__LONGJMP_RESTART
69984 #undef DUK__LONGJMP_FINISHED
69985 #undef DUK__LONGJMP_RETHROW
69986 
69987 #undef DUK__RETHAND_RESTART
69988 #undef DUK__RETHAND_FINISHED
69989 
69990 #undef DUK__FUN
69991 #undef DUK__STRICT
69992 #undef DUK__REG
69993 #undef DUK__REGP
69994 #undef DUK__CONST
69995 #undef DUK__CONSTP
69996 #undef DUK__RCISREG
69997 #undef DUK__REGCONST
69998 #undef DUK__REGCONSTP
69999 
70000 #undef DUK__INTERNAL_ERROR
70001 #undef DUK__SYNC_CURR_PC
70002 #undef DUK__SYNC_AND_NULL_CURR_PC
70003 /*
70004  *  Ecmascript specification algorithm and conversion helpers.
70005  *
70006  *  These helpers encapsulate the primitive Ecmascript operation
70007  *  semantics, and are used by the bytecode executor and the API
70008  *  (among other places).  Note that some primitives are only
70009  *  implemented as part of the API and have no "internal" helper.
70010  *  (This is the case when an internal helper would not really be
70011  *  useful; e.g. the operation is rare, uses value stack heavily,
70012  *  etc.)
70013  *
70014  *  The operation arguments depend on what is required to implement
70015  *  the operation:
70016  *
70017  *    - If an operation is simple and stateless, and has no side
70018  *      effects, it won't take an duk_hthread argument and its
70019  *      arguments may be duk_tval pointers (which are safe as long
70020  *      as no side effects take place).
70021  *
70022  *    - If complex coercions are required (e.g. a "ToNumber" coercion)
70023  *      or errors may be thrown, the operation takes an duk_hthread
70024  *      argument.  This also implies that the operation may have
70025  *      arbitrary side effects, invalidating any duk_tval pointers.
70026  *
70027  *    - For operations with potential side effects, arguments can be
70028  *      taken in several ways:
70029  *
70030  *      a) as duk_tval pointers, which makes sense if the "common case"
70031  *         can be resolved without side effects (e.g. coercion); the
70032  *         arguments are pushed to the valstack for coercion if
70033  *         necessary
70034  *
70035  *      b) as duk_tval values
70036  *
70037  *      c) implicitly on value stack top
70038  *
70039  *      d) as indices to the value stack
70040  *
70041  *  Future work:
70042  *
70043  *     - Argument styles may not be the most sensible in every case now.
70044  *
70045  *     - In-place coercions might be useful for several operations, if
70046  *       in-place coercion is OK for the bytecode executor and the API.
70047  */
70048 
70049 /* include removed: duk_internal.h */
70050 
70051 /*
70052  *  [[DefaultValue]]  (E5 Section 8.12.8)
70053  *
70054  *  ==> implemented in the API.
70055  */
70056 
70057 /*
70058  *  ToPrimitive()  (E5 Section 9.1)
70059  *
70060  *  ==> implemented in the API.
70061  */
70062 
70063 /*
70064  *  ToBoolean()  (E5 Section 9.2)
70065  */
70066 
70067 DUK_INTERNAL duk_bool_t duk_js_toboolean(duk_tval *tv) {
70068 	switch (DUK_TVAL_GET_TAG(tv)) {
70069 	case DUK_TAG_UNDEFINED:
70070 	case DUK_TAG_NULL:
70071 		return 0;
70072 	case DUK_TAG_BOOLEAN:
70073 		return DUK_TVAL_GET_BOOLEAN(tv);
70074 	case DUK_TAG_STRING: {
70075 		duk_hstring *h = DUK_TVAL_GET_STRING(tv);
70076 		DUK_ASSERT(h != NULL);
70077 		return (DUK_HSTRING_GET_BYTELEN(h) > 0 ? 1 : 0);
70078 	}
70079 	case DUK_TAG_OBJECT: {
70080 		return 1;
70081 	}
70082 	case DUK_TAG_BUFFER: {
70083 		/* mimic semantics for strings */
70084 		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
70085 		DUK_ASSERT(h != NULL);
70086 		return (DUK_HBUFFER_GET_SIZE(h) > 0 ? 1 : 0);
70087 	}
70088 	case DUK_TAG_POINTER: {
70089 		void *p = DUK_TVAL_GET_POINTER(tv);
70090 		return (p != NULL ? 1 : 0);
70091 	}
70092 	case DUK_TAG_LIGHTFUNC: {
70093 		return 1;
70094 	}
70095 #if defined(DUK_USE_FASTINT)
70096 	case DUK_TAG_FASTINT:
70097 		if (DUK_TVAL_GET_FASTINT(tv) != 0) {
70098 			return 1;
70099 		} else {
70100 			return 0;
70101 		}
70102 #endif
70103 	default: {
70104 		/* number */
70105 		duk_double_t d;
70106 		int c;
70107 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
70108 		DUK_ASSERT(DUK_TVAL_IS_DOUBLE(tv));
70109 		d = DUK_TVAL_GET_DOUBLE(tv);
70110 		c = DUK_FPCLASSIFY((double) d);
70111 		if (c == DUK_FP_ZERO || c == DUK_FP_NAN) {
70112 			return 0;
70113 		} else {
70114 			return 1;
70115 		}
70116 	}
70117 	}
70118 	DUK_UNREACHABLE();
70119 }
70120 
70121 /*
70122  *  ToNumber()  (E5 Section 9.3)
70123  *
70124  *  Value to convert must be on stack top, and is popped before exit.
70125  *
70126  *  See: http://www.cs.indiana.edu/~burger/FP-Printing-PLDI96.pdf
70127  *       http://www.cs.indiana.edu/~burger/fp/index.html
70128  *
70129  *  Notes on the conversion:
70130  *
70131  *    - There are specific requirements on the accuracy of the conversion
70132  *      through a "Mathematical Value" (MV), so this conversion is not
70133  *      trivial.
70134  *
70135  *    - Quick rejects (e.g. based on first char) are difficult because
70136  *      the grammar allows leading and trailing white space.
70137  *
70138  *    - Quick reject based on string length is difficult even after
70139  *      accounting for white space; there may be arbitrarily many
70140  *      decimal digits.
70141  *
70142  *    - Standard grammar allows decimal values ("123"), hex values
70143  *      ("0x123") and infinities
70144  *
70145  *    - Unlike source code literals, ToNumber() coerces empty strings
70146  *      and strings with only whitespace to zero (not NaN).
70147  */
70148 
70149 /* E5 Section 9.3.1 */
70150 DUK_LOCAL duk_double_t duk__tonumber_string_raw(duk_hthread *thr) {
70151 	duk_context *ctx = (duk_context *) thr;
70152 	duk_small_uint_t s2n_flags;
70153 	duk_double_t d;
70154 
70155 	/* Quite lenient, e.g. allow empty as zero, but don't allow trailing
70156 	 * garbage.
70157 	 */
70158 	s2n_flags = DUK_S2N_FLAG_TRIM_WHITE |
70159 	            DUK_S2N_FLAG_ALLOW_EXP |
70160 	            DUK_S2N_FLAG_ALLOW_PLUS |
70161 	            DUK_S2N_FLAG_ALLOW_MINUS |
70162 	            DUK_S2N_FLAG_ALLOW_INF |
70163 	            DUK_S2N_FLAG_ALLOW_FRAC |
70164 	            DUK_S2N_FLAG_ALLOW_NAKED_FRAC |
70165 	            DUK_S2N_FLAG_ALLOW_EMPTY_FRAC |
70166 	            DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO |
70167 	            DUK_S2N_FLAG_ALLOW_LEADING_ZERO |
70168 	            DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT;
70169 
70170 	duk_numconv_parse(ctx, 10 /*radix*/, s2n_flags);
70171 	d = duk_get_number(ctx, -1);
70172 	duk_pop(ctx);
70173 
70174 	return d;
70175 }
70176 
70177 DUK_INTERNAL duk_double_t duk_js_tonumber(duk_hthread *thr, duk_tval *tv) {
70178 	duk_context *ctx = (duk_hthread *) thr;
70179 
70180 	DUK_ASSERT(thr != NULL);
70181 	DUK_ASSERT(tv != NULL);
70182 
70183 	switch (DUK_TVAL_GET_TAG(tv)) {
70184 	case DUK_TAG_UNDEFINED: {
70185 		/* return a specific NaN (although not strictly necessary) */
70186 		duk_double_union du;
70187 		DUK_DBLUNION_SET_NAN(&du);
70188 		DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
70189 		return du.d;
70190 	}
70191 	case DUK_TAG_NULL: {
70192 		/* +0.0 */
70193 		return 0.0;
70194 	}
70195 	case DUK_TAG_BOOLEAN: {
70196 		if (DUK_TVAL_IS_BOOLEAN_TRUE(tv)) {
70197 			return 1.0;
70198 		}
70199 		return 0.0;
70200 	}
70201 	case DUK_TAG_STRING: {
70202 		duk_hstring *h = DUK_TVAL_GET_STRING(tv);
70203 		duk_push_hstring(ctx, h);
70204 		return duk__tonumber_string_raw(thr);
70205 	}
70206 	case DUK_TAG_OBJECT: {
70207 		/* Note: ToPrimitive(object,hint) == [[DefaultValue]](object,hint),
70208 		 * so use [[DefaultValue]] directly.
70209 		 */
70210 		duk_double_t d;
70211 		duk_push_tval(ctx, tv);
70212 		duk_to_defaultvalue(ctx, -1, DUK_HINT_NUMBER);  /* 'tv' becomes invalid */
70213 
70214 		/* recursive call for a primitive value (guaranteed not to cause second
70215 		 * recursion).
70216 		 */
70217 		d = duk_js_tonumber(thr, duk_require_tval(ctx, -1));
70218 
70219 		duk_pop(ctx);
70220 		return d;
70221 	}
70222 	case DUK_TAG_BUFFER: {
70223 		/* Coerce like a string.  This makes sense because addition also treats
70224 		 * buffers like strings.
70225 		 */
70226 		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
70227 		duk_push_hbuffer(ctx, h);
70228 		duk_to_string(ctx, -1);  /* XXX: expensive, but numconv now expects to see a string */
70229 		return duk__tonumber_string_raw(thr);
70230 	}
70231 	case DUK_TAG_POINTER: {
70232 		/* Coerce like boolean */
70233 		void *p = DUK_TVAL_GET_POINTER(tv);
70234 		return (p != NULL ? 1.0 : 0.0);
70235 	}
70236 	case DUK_TAG_LIGHTFUNC: {
70237 		/* +(function(){}) -> NaN */
70238 		return DUK_DOUBLE_NAN;
70239 	}
70240 #if defined(DUK_USE_FASTINT)
70241 	case DUK_TAG_FASTINT:
70242 		return (duk_double_t) DUK_TVAL_GET_FASTINT(tv);
70243 #endif
70244 	default: {
70245 		/* number */
70246 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
70247 		DUK_ASSERT(DUK_TVAL_IS_DOUBLE(tv));
70248 		return DUK_TVAL_GET_DOUBLE(tv);
70249 	}
70250 	}
70251 
70252 	DUK_UNREACHABLE();
70253 }
70254 
70255 /*
70256  *  ToInteger()  (E5 Section 9.4)
70257  */
70258 
70259 /* exposed, used by e.g. duk_bi_date.c */
70260 DUK_INTERNAL duk_double_t duk_js_tointeger_number(duk_double_t x) {
70261 	duk_small_int_t c = (duk_small_int_t) DUK_FPCLASSIFY(x);
70262 
70263 	if (c == DUK_FP_NAN) {
70264 		return 0.0;
70265 	} else if (c == DUK_FP_ZERO || c == DUK_FP_INFINITE) {
70266 		/* XXX: FP_ZERO check can be removed, the else clause handles it
70267 		 * correctly (preserving sign).
70268 		 */
70269 		return x;
70270 	} else {
70271 		duk_small_int_t s = (duk_small_int_t) DUK_SIGNBIT(x);
70272 		x = DUK_FLOOR(DUK_FABS(x));  /* truncate towards zero */
70273 		if (s) {
70274 			x = -x;
70275 		}
70276 		return x;
70277 	}
70278 }
70279 
70280 DUK_INTERNAL duk_double_t duk_js_tointeger(duk_hthread *thr, duk_tval *tv) {
70281 	/* XXX: fastint */
70282 	duk_double_t d = duk_js_tonumber(thr, tv);  /* invalidates tv */
70283 	return duk_js_tointeger_number(d);
70284 }
70285 
70286 /*
70287  *  ToInt32(), ToUint32(), ToUint16()  (E5 Sections 9.5, 9.6, 9.7)
70288  */
70289 
70290 /* combined algorithm matching E5 Sections 9.5 and 9.6 */
70291 DUK_LOCAL duk_double_t duk__toint32_touint32_helper(duk_double_t x, duk_bool_t is_toint32) {
70292 	duk_small_int_t c = (duk_small_int_t) DUK_FPCLASSIFY(x);
70293 	duk_small_int_t s;
70294 
70295 	if (c == DUK_FP_NAN || c == DUK_FP_ZERO || c == DUK_FP_INFINITE) {
70296 		return 0.0;
70297 	}
70298 
70299 
70300 	/* x = sign(x) * floor(abs(x)), i.e. truncate towards zero, keep sign */
70301 	s = (duk_small_int_t) DUK_SIGNBIT(x);
70302 	x = DUK_FLOOR(DUK_FABS(x));
70303 	if (s) {
70304 		x = -x;
70305 	}
70306 
70307 	/* NOTE: fmod(x) result sign is same as sign of x, which
70308 	 * differs from what Javascript wants (see Section 9.6).
70309 	 */
70310 
70311 	x = DUK_FMOD(x, DUK_DOUBLE_2TO32);    /* -> x in ]-2**32, 2**32[ */
70312 
70313 	if (x < 0.0) {
70314 		x += DUK_DOUBLE_2TO32;
70315 	}
70316 	/* -> x in [0, 2**32[ */
70317 
70318 	if (is_toint32) {
70319 		if (x >= DUK_DOUBLE_2TO31) {
70320 			/* x in [2**31, 2**32[ */
70321 
70322 			x -= DUK_DOUBLE_2TO32;  /* -> x in [-2**31,2**31[ */
70323 		}
70324 	}
70325 
70326 	return x;
70327 }
70328 
70329 DUK_INTERNAL duk_int32_t duk_js_toint32(duk_hthread *thr, duk_tval *tv) {
70330 	duk_double_t d;
70331 
70332 #if defined(DUK_USE_FASTINT)
70333 	if (DUK_TVAL_IS_FASTINT(tv)) {
70334 		return DUK_TVAL_GET_FASTINT_I32(tv);
70335 	}
70336 #endif
70337 
70338 	d = duk_js_tonumber(thr, tv);  /* invalidates tv */
70339 	d = duk__toint32_touint32_helper(d, 1);
70340 	DUK_ASSERT(DUK_FPCLASSIFY(d) == DUK_FP_ZERO || DUK_FPCLASSIFY(d) == DUK_FP_NORMAL);
70341 	DUK_ASSERT(d >= -2147483648.0 && d <= 2147483647.0);  /* [-0x80000000,0x7fffffff] */
70342 	DUK_ASSERT(d == ((duk_double_t) ((duk_int32_t) d)));  /* whole, won't clip */
70343 	return (duk_int32_t) d;
70344 }
70345 
70346 
70347 DUK_INTERNAL duk_uint32_t duk_js_touint32(duk_hthread *thr, duk_tval *tv) {
70348 	duk_double_t d;
70349 
70350 #if defined(DUK_USE_FASTINT)
70351 	if (DUK_TVAL_IS_FASTINT(tv)) {
70352 		return DUK_TVAL_GET_FASTINT_U32(tv);
70353 	}
70354 #endif
70355 
70356 	d = duk_js_tonumber(thr, tv);  /* invalidates tv */
70357 	d = duk__toint32_touint32_helper(d, 0);
70358 	DUK_ASSERT(DUK_FPCLASSIFY(d) == DUK_FP_ZERO || DUK_FPCLASSIFY(d) == DUK_FP_NORMAL);
70359 	DUK_ASSERT(d >= 0.0 && d <= 4294967295.0);  /* [0x00000000, 0xffffffff] */
70360 	DUK_ASSERT(d == ((duk_double_t) ((duk_uint32_t) d)));  /* whole, won't clip */
70361 	return (duk_uint32_t) d;
70362 
70363 }
70364 
70365 DUK_INTERNAL duk_uint16_t duk_js_touint16(duk_hthread *thr, duk_tval *tv) {
70366 	/* should be a safe way to compute this */
70367 	return (duk_uint16_t) (duk_js_touint32(thr, tv) & 0x0000ffffU);
70368 }
70369 
70370 /*
70371  *  ToString()  (E5 Section 9.8)
70372  *
70373  *  ==> implemented in the API.
70374  */
70375 
70376 /*
70377  *  ToObject()  (E5 Section 9.9)
70378  *
70379  *  ==> implemented in the API.
70380  */
70381 
70382 /*
70383  *  CheckObjectCoercible()  (E5 Section 9.10)
70384  *
70385  *  Note: no API equivalent now.
70386  */
70387 
70388 #if 0  /* unused */
70389 DUK_INTERNAL void duk_js_checkobjectcoercible(duk_hthread *thr, duk_tval *tv_x) {
70390 	duk_small_uint_t tag = DUK_TVAL_GET_TAG(tv_x);
70391 
70392 	/* Note: this must match ToObject() behavior */
70393 
70394 	if (tag == DUK_TAG_UNDEFINED ||
70395 	    tag == DUK_TAG_NULL ||
70396 	    tag == DUK_TAG_POINTER ||
70397 	    tag == DUK_TAG_BUFFER) {
70398 		DUK_ERROR_TYPE(thr, "not object coercible");
70399 	}
70400 }
70401 #endif
70402 
70403 /*
70404  *  IsCallable()  (E5 Section 9.11)
70405  *
70406  *  XXX: API equivalent is a separate implementation now, and this has
70407  *  currently no callers.
70408  */
70409 
70410 #if 0  /* unused */
70411 DUK_INTERNAL duk_bool_t duk_js_iscallable(duk_tval *tv_x) {
70412 	duk_hobject *obj;
70413 
70414 	if (!DUK_TVAL_IS_OBJECT(tv_x)) {
70415 		return 0;
70416 	}
70417 	obj = DUK_TVAL_GET_OBJECT(tv_x);
70418 	DUK_ASSERT(obj != NULL);
70419 
70420 	return DUK_HOBJECT_IS_CALLABLE(obj);
70421 }
70422 #endif
70423 
70424 /*
70425  *  Loose equality, strict equality, and SameValue (E5 Sections 11.9.1, 11.9.4,
70426  *  9.12).  These have much in common so they can share some helpers.
70427  *
70428  *  Future work notes:
70429  *
70430  *    - Current implementation (and spec definition) has recursion; this should
70431  *      be fixed if possible.
70432  *
70433  *    - String-to-number coercion should be possible without going through the
70434  *      value stack (and be more compact) if a shared helper is invoked.
70435  */
70436 
70437 /* Note that this is the same operation for strict and loose equality:
70438  *  - E5 Section 11.9.3, step 1.c (loose)
70439  *  - E5 Section 11.9.6, step 4 (strict)
70440  */
70441 
70442 DUK_LOCAL duk_bool_t duk__js_equals_number(duk_double_t x, duk_double_t y) {
70443 #if defined(DUK_USE_PARANOID_MATH)
70444 	/* Straightforward algorithm, makes fewer compiler assumptions. */
70445 	duk_small_int_t cx = (duk_small_int_t) DUK_FPCLASSIFY(x);
70446 	duk_small_int_t cy = (duk_small_int_t) DUK_FPCLASSIFY(y);
70447 	if (cx == DUK_FP_NAN || cy == DUK_FP_NAN) {
70448 		return 0;
70449 	}
70450 	if (cx == DUK_FP_ZERO && cy == DUK_FP_ZERO) {
70451 		return 1;
70452 	}
70453 	if (x == y) {
70454 		return 1;
70455 	}
70456 	return 0;
70457 #else  /* DUK_USE_PARANOID_MATH */
70458 	/* Better equivalent algorithm.  If the compiler is compliant, C and
70459 	 * Ecmascript semantics are identical for this particular comparison.
70460 	 * In particular, NaNs must never compare equal and zeroes must compare
70461 	 * equal regardless of sign.  Could also use a macro, but this inlines
70462 	 * already nicely (no difference on gcc, for instance).
70463 	 */
70464 	if (x == y) {
70465 		/* IEEE requires that NaNs compare false */
70466 		DUK_ASSERT(DUK_FPCLASSIFY(x) != DUK_FP_NAN);
70467 		DUK_ASSERT(DUK_FPCLASSIFY(y) != DUK_FP_NAN);
70468 		return 1;
70469 	} else {
70470 		/* IEEE requires that zeros compare the same regardless
70471 		 * of their signed, so if both x and y are zeroes, they
70472 		 * are caught above.
70473 		 */
70474 		DUK_ASSERT(!(DUK_FPCLASSIFY(x) == DUK_FP_ZERO && DUK_FPCLASSIFY(y) == DUK_FP_ZERO));
70475 		return 0;
70476 	}
70477 #endif  /* DUK_USE_PARANOID_MATH */
70478 }
70479 
70480 DUK_LOCAL duk_bool_t duk__js_samevalue_number(duk_double_t x, duk_double_t y) {
70481 #if defined(DUK_USE_PARANOID_MATH)
70482 	duk_small_int_t cx = (duk_small_int_t) DUK_FPCLASSIFY(x);
70483 	duk_small_int_t cy = (duk_small_int_t) DUK_FPCLASSIFY(y);
70484 
70485 	if (cx == DUK_FP_NAN && cy == DUK_FP_NAN) {
70486 		/* SameValue(NaN, NaN) = true, regardless of NaN sign or extra bits */
70487 		return 1;
70488 	}
70489 	if (cx == DUK_FP_ZERO && cy == DUK_FP_ZERO) {
70490 		/* Note: cannot assume that a non-zero return value of signbit() would
70491 		 * always be the same -- hence cannot (portably) use something like:
70492 		 *
70493 		 *     signbit(x) == signbit(y)
70494 		 */
70495 		duk_small_int_t sx = (DUK_SIGNBIT(x) ? 1 : 0);
70496 		duk_small_int_t sy = (DUK_SIGNBIT(y) ? 1 : 0);
70497 		return (sx == sy);
70498 	}
70499 
70500 	/* normal comparison; known:
70501 	 *   - both x and y are not NaNs (but one of them can be)
70502 	 *   - both x and y are not zero (but one of them can be)
70503 	 *   - x and y may be denormal or infinite
70504 	 */
70505 
70506 	return (x == y);
70507 #else  /* DUK_USE_PARANOID_MATH */
70508 	duk_small_int_t cx = (duk_small_int_t) DUK_FPCLASSIFY(x);
70509 	duk_small_int_t cy = (duk_small_int_t) DUK_FPCLASSIFY(y);
70510 
70511 	if (x == y) {
70512 		/* IEEE requires that NaNs compare false */
70513 		DUK_ASSERT(DUK_FPCLASSIFY(x) != DUK_FP_NAN);
70514 		DUK_ASSERT(DUK_FPCLASSIFY(y) != DUK_FP_NAN);
70515 
70516 		/* Using classification has smaller footprint than direct comparison. */
70517 		if (DUK_UNLIKELY(cx == DUK_FP_ZERO && cy == DUK_FP_ZERO)) {
70518 			/* Note: cannot assume that a non-zero return value of signbit() would
70519 			 * always be the same -- hence cannot (portably) use something like:
70520 			 *
70521 			 *     signbit(x) == signbit(y)
70522 			 */
70523 			duk_small_int_t sx = (DUK_SIGNBIT(x) ? 1 : 0);
70524 			duk_small_int_t sy = (DUK_SIGNBIT(y) ? 1 : 0);
70525 			return (sx == sy);
70526 		}
70527 		return 1;
70528 	} else {
70529 		/* IEEE requires that zeros compare the same regardless
70530 		 * of their signed, so if both x and y are zeroes, they
70531 		 * are caught above.
70532 		 */
70533 		DUK_ASSERT(!(DUK_FPCLASSIFY(x) == DUK_FP_ZERO && DUK_FPCLASSIFY(y) == DUK_FP_ZERO));
70534 
70535 		/* Difference to non-strict/strict comparison is that NaNs compare
70536 		 * equal and signed zero signs matter.
70537 		 */
70538 		if (DUK_UNLIKELY(cx == DUK_FP_NAN && cy == DUK_FP_NAN)) {
70539 			/* SameValue(NaN, NaN) = true, regardless of NaN sign or extra bits */
70540 			return 1;
70541 		}
70542 		return 0;
70543 	}
70544 #endif  /* DUK_USE_PARANOID_MATH */
70545 }
70546 
70547 DUK_INTERNAL duk_bool_t duk_js_equals_helper(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_int_t flags) {
70548 	duk_context *ctx = (duk_context *) thr;
70549 	duk_tval *tv_tmp;
70550 
70551 	/* If flags != 0 (strict or SameValue), thr can be NULL.  For loose
70552 	 * equals comparison it must be != NULL.
70553 	 */
70554 	DUK_ASSERT(flags != 0 || thr != NULL);
70555 
70556 	/*
70557 	 *  Same type?
70558 	 *
70559 	 *  Note: since number values have no explicit tag in the 8-byte
70560 	 *  representation, need the awkward if + switch.
70561 	 */
70562 
70563 #if defined(DUK_USE_FASTINT)
70564 	if (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {
70565 		if (DUK_TVAL_GET_FASTINT(tv_x) == DUK_TVAL_GET_FASTINT(tv_y)) {
70566 			return 1;
70567 		} else {
70568 			return 0;
70569 		}
70570 	}
70571 	else
70572 #endif
70573 	if (DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y)) {
70574 		/* Catches both doubles and cases where only one argument is a fastint */
70575 		if (DUK_UNLIKELY((flags & DUK_EQUALS_FLAG_SAMEVALUE) != 0)) {
70576 			/* SameValue */
70577 			return duk__js_samevalue_number(DUK_TVAL_GET_NUMBER(tv_x),
70578 			                                DUK_TVAL_GET_NUMBER(tv_y));
70579 		} else {
70580 			/* equals and strict equals */
70581 			return duk__js_equals_number(DUK_TVAL_GET_NUMBER(tv_x),
70582 			                             DUK_TVAL_GET_NUMBER(tv_y));
70583 		}
70584 	} else if (DUK_TVAL_GET_TAG(tv_x) == DUK_TVAL_GET_TAG(tv_y)) {
70585 		switch (DUK_TVAL_GET_TAG(tv_x)) {
70586 		case DUK_TAG_UNDEFINED:
70587 		case DUK_TAG_NULL: {
70588 			return 1;
70589 		}
70590 		case DUK_TAG_BOOLEAN: {
70591 			return DUK_TVAL_GET_BOOLEAN(tv_x) == DUK_TVAL_GET_BOOLEAN(tv_y);
70592 		}
70593 		case DUK_TAG_POINTER: {
70594 			return DUK_TVAL_GET_POINTER(tv_x) == DUK_TVAL_GET_POINTER(tv_y);
70595 		}
70596 		case DUK_TAG_STRING:
70597 		case DUK_TAG_OBJECT: {
70598 			/* heap pointer comparison suffices */
70599 			return DUK_TVAL_GET_HEAPHDR(tv_x) == DUK_TVAL_GET_HEAPHDR(tv_y);
70600 		}
70601 		case DUK_TAG_BUFFER: {
70602 			if ((flags & (DUK_EQUALS_FLAG_STRICT | DUK_EQUALS_FLAG_SAMEVALUE)) != 0) {
70603 				/* heap pointer comparison suffices */
70604 				return DUK_TVAL_GET_HEAPHDR(tv_x) == DUK_TVAL_GET_HEAPHDR(tv_y);
70605 			} else {
70606 				/* non-strict equality for buffers compares contents */
70607 				duk_hbuffer *h_x = DUK_TVAL_GET_BUFFER(tv_x);
70608 				duk_hbuffer *h_y = DUK_TVAL_GET_BUFFER(tv_y);
70609 				duk_size_t len_x = DUK_HBUFFER_GET_SIZE(h_x);
70610 				duk_size_t len_y = DUK_HBUFFER_GET_SIZE(h_y);
70611 				void *buf_x;
70612 				void *buf_y;
70613 				if (len_x != len_y) {
70614 					return 0;
70615 				}
70616 				buf_x = (void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_x);
70617 				buf_y = (void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_y);
70618 				/* if len_x == len_y == 0, buf_x and/or buf_y may
70619 				 * be NULL, but that's OK.
70620 				 */
70621 				DUK_ASSERT(len_x == len_y);
70622 				DUK_ASSERT(len_x == 0 || buf_x != NULL);
70623 				DUK_ASSERT(len_y == 0 || buf_y != NULL);
70624 				return (DUK_MEMCMP((const void *) buf_x, (const void *) buf_y, (size_t) len_x) == 0) ? 1 : 0;
70625 			}
70626 		}
70627 		case DUK_TAG_LIGHTFUNC: {
70628 			/* At least 'magic' has a significant impact on function
70629 			 * identity.
70630 			 */
70631 			duk_small_uint_t lf_flags_x;
70632 			duk_small_uint_t lf_flags_y;
70633 			duk_c_function func_x;
70634 			duk_c_function func_y;
70635 
70636 			DUK_TVAL_GET_LIGHTFUNC(tv_x, func_x, lf_flags_x);
70637 			DUK_TVAL_GET_LIGHTFUNC(tv_y, func_y, lf_flags_y);
70638 			return ((func_x == func_y) && (lf_flags_x == lf_flags_y)) ? 1 : 0;
70639 		}
70640 #if defined(DUK_USE_FASTINT)
70641 		case DUK_TAG_FASTINT:
70642 #endif
70643 		default: {
70644 			DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv_x));
70645 			DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv_y));
70646 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_x));
70647 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_y));
70648 			DUK_UNREACHABLE();
70649 			return 0;
70650 		}
70651 		}
70652 	}
70653 
70654 	if ((flags & (DUK_EQUALS_FLAG_STRICT | DUK_EQUALS_FLAG_SAMEVALUE)) != 0) {
70655 		return 0;
70656 	}
70657 
70658 	DUK_ASSERT(flags == 0);  /* non-strict equality from here on */
70659 
70660 	/*
70661 	 *  Types are different; various cases for non-strict comparison
70662 	 *
70663 	 *  Since comparison is symmetric, we use a "swap trick" to reduce
70664 	 *  code size.
70665 	 */
70666 
70667 	/* Undefined/null are considered equal (e.g. "null == undefined" -> true). */
70668 	if ((DUK_TVAL_IS_UNDEFINED(tv_x) && DUK_TVAL_IS_NULL(tv_y)) ||
70669 	    (DUK_TVAL_IS_NULL(tv_x) && DUK_TVAL_IS_UNDEFINED(tv_y))) {
70670 		return 1;
70671 	}
70672 
70673 	/* Number/string-or-buffer -> coerce string to number (e.g. "'1.5' == 1.5" -> true). */
70674 	if (DUK_TVAL_IS_NUMBER(tv_x) && (DUK_TVAL_IS_STRING(tv_y) || DUK_TVAL_IS_BUFFER(tv_y))) {
70675 		/* the next 'if' is guaranteed to match after swap */
70676 		tv_tmp = tv_x;
70677 		tv_x = tv_y;
70678 		tv_y = tv_tmp;
70679 	}
70680 	if ((DUK_TVAL_IS_STRING(tv_x) || DUK_TVAL_IS_BUFFER(tv_x)) && DUK_TVAL_IS_NUMBER(tv_y)) {
70681 		/* XXX: this is possible without resorting to the value stack */
70682 		duk_double_t d1, d2;
70683 		d2 = DUK_TVAL_GET_NUMBER(tv_y);
70684 		duk_push_tval(ctx, tv_x);
70685 		duk_to_string(ctx, -1);  /* buffer values are coerced first to string here */
70686 		duk_to_number(ctx, -1);
70687 		d1 = duk_require_number(ctx, -1);
70688 		duk_pop(ctx);
70689 		return duk__js_equals_number(d1, d2);
70690 	}
70691 
70692 	/* Buffer/string -> compare contents. */
70693 	if (DUK_TVAL_IS_BUFFER(tv_x) && DUK_TVAL_IS_STRING(tv_y)) {
70694 		tv_tmp = tv_x;
70695 		tv_x = tv_y;
70696 		tv_y = tv_tmp;
70697 	}
70698 	if (DUK_TVAL_IS_STRING(tv_x) && DUK_TVAL_IS_BUFFER(tv_y)) {
70699 		duk_hstring *h_x = DUK_TVAL_GET_STRING(tv_x);
70700 		duk_hbuffer *h_y = DUK_TVAL_GET_BUFFER(tv_y);
70701 		duk_size_t len_x = DUK_HSTRING_GET_BYTELEN(h_x);
70702 		duk_size_t len_y = DUK_HBUFFER_GET_SIZE(h_y);
70703 		const void *buf_x;
70704 		const void *buf_y;
70705 		if (len_x != len_y) {
70706 			return 0;
70707 		}
70708 		buf_x = (const void *) DUK_HSTRING_GET_DATA(h_x);
70709 		buf_y = (const void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_y);
70710 		/* if len_x == len_y == 0, buf_x and/or buf_y may
70711 		 * be NULL, but that's OK.
70712 		 */
70713 		DUK_ASSERT(len_x == len_y);
70714 		DUK_ASSERT(len_x == 0 || buf_x != NULL);
70715 		DUK_ASSERT(len_y == 0 || buf_y != NULL);
70716 		return (DUK_MEMCMP((const void *) buf_x, (const void *) buf_y, (size_t) len_x) == 0) ? 1 : 0;
70717 	}
70718 
70719 	/* Boolean/any -> coerce boolean to number and try again.  If boolean is
70720 	 * compared to a pointer, the final comparison after coercion now always
70721 	 * yields false (as pointer vs. number compares to false), but this is
70722 	 * not special cased.
70723 	 */
70724 	if (DUK_TVAL_IS_BOOLEAN(tv_x)) {
70725 		tv_tmp = tv_x;
70726 		tv_x = tv_y;
70727 		tv_y = tv_tmp;
70728 	}
70729 	if (DUK_TVAL_IS_BOOLEAN(tv_y)) {
70730 		/* ToNumber(bool) is +1.0 or 0.0.  Tagged boolean value is always 0 or 1. */
70731 		duk_bool_t rc;
70732 		DUK_ASSERT(DUK_TVAL_GET_BOOLEAN(tv_y) == 0 || DUK_TVAL_GET_BOOLEAN(tv_y) == 1);
70733 		duk_push_tval(ctx, tv_x);
70734 		duk_push_int(ctx, DUK_TVAL_GET_BOOLEAN(tv_y));
70735 		rc = duk_js_equals_helper(thr,
70736 		                          DUK_GET_TVAL_NEGIDX(ctx, -2),
70737 		                          DUK_GET_TVAL_NEGIDX(ctx, -1),
70738 		                          0 /*flags:nonstrict*/);
70739 		duk_pop_2(ctx);
70740 		return rc;
70741 	}
70742 
70743 	/* String-number-buffer/object -> coerce object to primitive (apparently without hint), then try again. */
70744 	if ((DUK_TVAL_IS_STRING(tv_x) || DUK_TVAL_IS_NUMBER(tv_x) || DUK_TVAL_IS_BUFFER(tv_x)) &&
70745 	    DUK_TVAL_IS_OBJECT(tv_y)) {
70746 		tv_tmp = tv_x;
70747 		tv_x = tv_y;
70748 		tv_y = tv_tmp;
70749 	}
70750 	if (DUK_TVAL_IS_OBJECT(tv_x) &&
70751 	    (DUK_TVAL_IS_STRING(tv_y) || DUK_TVAL_IS_NUMBER(tv_y) || DUK_TVAL_IS_BUFFER(tv_y))) {
70752 		duk_bool_t rc;
70753 		duk_push_tval(ctx, tv_x);
70754 		duk_push_tval(ctx, tv_y);
70755 		duk_to_primitive(ctx, -2, DUK_HINT_NONE);  /* apparently no hint? */
70756 		rc = duk_js_equals_helper(thr,
70757 		                          DUK_GET_TVAL_NEGIDX(ctx, -2),
70758 		                          DUK_GET_TVAL_NEGIDX(ctx, -1),
70759 		                          0 /*flags:nonstrict*/);
70760 		duk_pop_2(ctx);
70761 		return rc;
70762 	}
70763 
70764 	/* Nothing worked -> not equal. */
70765 	return 0;
70766 }
70767 
70768 /*
70769  *  Comparisons (x >= y, x > y, x <= y, x < y)
70770  *
70771  *  E5 Section 11.8.5: implement 'x < y' and then use negate and eval_left_first
70772  *  flags to get the rest.
70773  */
70774 
70775 /* XXX: this should probably just operate on the stack top, because it
70776  * needs to push stuff on the stack anyway...
70777  */
70778 
70779 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) {
70780 	duk_size_t prefix_len;
70781 	duk_small_int_t rc;
70782 
70783 	prefix_len = (len1 <= len2 ? len1 : len2);
70784 
70785 	/* DUK_MEMCMP() is guaranteed to return zero (equal) for zero length
70786 	 * inputs so no zero length check is needed.
70787 	 */
70788 	rc = DUK_MEMCMP((const void *) buf1,
70789 	                (const void *) buf2,
70790 	                (size_t) prefix_len);
70791 
70792 	if (rc < 0) {
70793 		return -1;
70794 	} else if (rc > 0) {
70795 		return 1;
70796 	}
70797 
70798 	/* prefix matches, lengths matter now */
70799 	if (len1 < len2) {
70800 		/* e.g. "x" < "xx" */
70801 		return -1;
70802 	} else if (len1 > len2) {
70803 		return 1;
70804 	}
70805 
70806 	return 0;
70807 }
70808 
70809 DUK_INTERNAL duk_small_int_t duk_js_string_compare(duk_hstring *h1, duk_hstring *h2) {
70810 	/*
70811 	 *  String comparison (E5 Section 11.8.5, step 4), which
70812 	 *  needs to compare codepoint by codepoint.
70813 	 *
70814 	 *  However, UTF-8 allows us to use strcmp directly: the shared
70815 	 *  prefix will be encoded identically (UTF-8 has unique encoding)
70816 	 *  and the first differing character can be compared with a simple
70817 	 *  unsigned byte comparison (which strcmp does).
70818 	 *
70819 	 *  This will not work properly for non-xutf-8 strings, but this
70820 	 *  is not an issue for compliance.
70821 	 */
70822 
70823 	DUK_ASSERT(h1 != NULL);
70824 	DUK_ASSERT(h2 != NULL);
70825 
70826 	return duk_js_data_compare((const duk_uint8_t *) DUK_HSTRING_GET_DATA(h1),
70827 	                           (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h2),
70828 	                           (duk_size_t) DUK_HSTRING_GET_BYTELEN(h1),
70829 	                           (duk_size_t) DUK_HSTRING_GET_BYTELEN(h2));
70830 }
70831 
70832 #if 0  /* unused */
70833 DUK_INTERNAL duk_small_int_t duk_js_buffer_compare(duk_heap *heap, duk_hbuffer *h1, duk_hbuffer *h2) {
70834 	/* Similar to String comparison. */
70835 
70836 	DUK_ASSERT(h1 != NULL);
70837 	DUK_ASSERT(h2 != NULL);
70838 	DUK_UNREF(heap);
70839 
70840 	return duk_js_data_compare((const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(heap, h1),
70841 	                           (const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(heap, h2),
70842 	                           (duk_size_t) DUK_HBUFFER_GET_SIZE(h1),
70843 	                           (duk_size_t) DUK_HBUFFER_GET_SIZE(h2));
70844 }
70845 #endif
70846 
70847 DUK_INTERNAL duk_bool_t duk_js_compare_helper(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_int_t flags) {
70848 	duk_context *ctx = (duk_context *) thr;
70849 	duk_double_t d1, d2;
70850 	duk_small_int_t c1, c2;
70851 	duk_small_int_t s1, s2;
70852 	duk_small_int_t rc;
70853 	duk_bool_t retval;
70854 
70855 	/* Fast path for fastints */
70856 #if defined(DUK_USE_FASTINT)
70857 	if (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {
70858 		duk_int64_t v1 = DUK_TVAL_GET_FASTINT(tv_x);
70859 		duk_int64_t v2 = DUK_TVAL_GET_FASTINT(tv_y);
70860 		if (v1 < v2) {
70861 			/* 'lt is true' */
70862 			retval = 1;
70863 		} else {
70864 			retval = 0;
70865 		}
70866 		if (flags & DUK_COMPARE_FLAG_NEGATE) {
70867 			retval ^= 1;
70868 		}
70869 		return retval;
70870 	}
70871 #endif  /* DUK_USE_FASTINT */
70872 
70873 	/* Fast path for numbers (one of which may be a fastint) */
70874 #if 1  /* XXX: make fast paths optional for size minimization? */
70875 	if (DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y)) {
70876 		d1 = DUK_TVAL_GET_NUMBER(tv_x);
70877 		d2 = DUK_TVAL_GET_NUMBER(tv_y);
70878 		c1 = DUK_FPCLASSIFY(d1);
70879 		c2 = DUK_FPCLASSIFY(d2);
70880 
70881 		if (c1 == DUK_FP_NORMAL && c2 == DUK_FP_NORMAL) {
70882 			/* XXX: this is a very narrow check, and doesn't cover
70883 			 * zeroes, subnormals, infinities, which compare normally.
70884 			 */
70885 
70886 			if (d1 < d2) {
70887 				/* 'lt is true' */
70888 				retval = 1;
70889 			} else {
70890 				retval = 0;
70891 			}
70892 			if (flags & DUK_COMPARE_FLAG_NEGATE) {
70893 				retval ^= 1;
70894 			}
70895 			return retval;
70896 		}
70897 	}
70898 #endif
70899 
70900 	/* Slow path */
70901 
70902 	duk_push_tval(ctx, tv_x);
70903 	duk_push_tval(ctx, tv_y);
70904 
70905 	if (flags & DUK_COMPARE_FLAG_EVAL_LEFT_FIRST) {
70906 		duk_to_primitive(ctx, -2, DUK_HINT_NUMBER);
70907 		duk_to_primitive(ctx, -1, DUK_HINT_NUMBER);
70908 	} else {
70909 		duk_to_primitive(ctx, -1, DUK_HINT_NUMBER);
70910 		duk_to_primitive(ctx, -2, DUK_HINT_NUMBER);
70911 	}
70912 
70913 	/* Note: reuse variables */
70914 	tv_x = DUK_GET_TVAL_NEGIDX(ctx, -2);
70915 	tv_y = DUK_GET_TVAL_NEGIDX(ctx, -1);
70916 
70917 	if (DUK_TVAL_IS_STRING(tv_x) && DUK_TVAL_IS_STRING(tv_y)) {
70918 		duk_hstring *h1 = DUK_TVAL_GET_STRING(tv_x);
70919 		duk_hstring *h2 = DUK_TVAL_GET_STRING(tv_y);
70920 		DUK_ASSERT(h1 != NULL);
70921 		DUK_ASSERT(h2 != NULL);
70922 
70923 		rc = duk_js_string_compare(h1, h2);
70924 		if (rc < 0) {
70925 			goto lt_true;
70926 		} else {
70927 			goto lt_false;
70928 		}
70929 	} else {
70930 		/* Ordering should not matter (E5 Section 11.8.5, step 3.a) but
70931 		 * preserve it just in case.
70932 		 */
70933 
70934 		if (flags & DUK_COMPARE_FLAG_EVAL_LEFT_FIRST) {
70935 			d1 = duk_to_number(ctx, -2);
70936 			d2 = duk_to_number(ctx, -1);
70937 		} else {
70938 			d2 = duk_to_number(ctx, -1);
70939 			d1 = duk_to_number(ctx, -2);
70940 		}
70941 
70942 		c1 = (duk_small_int_t) DUK_FPCLASSIFY(d1);
70943 		s1 = (duk_small_int_t) DUK_SIGNBIT(d1);
70944 		c2 = (duk_small_int_t) DUK_FPCLASSIFY(d2);
70945 		s2 = (duk_small_int_t) DUK_SIGNBIT(d2);
70946 
70947 		if (c1 == DUK_FP_NAN || c2 == DUK_FP_NAN) {
70948 			goto lt_undefined;
70949 		}
70950 
70951 		if (c1 == DUK_FP_ZERO && c2 == DUK_FP_ZERO) {
70952 			/* For all combinations: +0 < +0, +0 < -0, -0 < +0, -0 < -0,
70953 			 * steps e, f, and g.
70954 			 */
70955 			goto lt_false;
70956 		}
70957 
70958 		if (d1 == d2) {
70959 			goto lt_false;
70960 		}
70961 
70962 		if (c1 == DUK_FP_INFINITE && s1 == 0) {
70963 			/* x == +Infinity */
70964 			goto lt_false;
70965 		}
70966 
70967 		if (c2 == DUK_FP_INFINITE && s2 == 0) {
70968 			/* y == +Infinity */
70969 			goto lt_true;
70970 		}
70971 
70972 		if (c2 == DUK_FP_INFINITE && s2 != 0) {
70973 			/* y == -Infinity */
70974 			goto lt_false;
70975 		}
70976 
70977 		if (c1 == DUK_FP_INFINITE && s1 != 0) {
70978 			/* x == -Infinity */
70979 			goto lt_true;
70980 		}
70981 
70982 		if (d1 < d2) {
70983 			goto lt_true;
70984 		}
70985 
70986 		goto lt_false;
70987 	}
70988 
70989  lt_undefined:
70990 	/* Note: undefined from Section 11.8.5 always results in false
70991 	 * return (see e.g. Section 11.8.3) - hence special treatment here.
70992 	 */
70993 	retval = 0;
70994 	goto cleanup;
70995 
70996  lt_true:
70997 	if (flags & DUK_COMPARE_FLAG_NEGATE) {
70998 		retval = 0;
70999 		goto cleanup;
71000 	} else {
71001 		retval = 1;
71002 		goto cleanup;
71003 	}
71004 	/* never here */
71005 
71006  lt_false:
71007 	if (flags & DUK_COMPARE_FLAG_NEGATE) {
71008 		retval = 1;
71009 		goto cleanup;
71010 	} else {
71011 		retval = 0;
71012 		goto cleanup;
71013 	}
71014 	/* never here */
71015 
71016  cleanup:
71017 	duk_pop_2(ctx);
71018 	return retval;
71019 }
71020 
71021 /*
71022  *  instanceof
71023  */
71024 
71025 /*
71026  *  E5 Section 11.8.6 describes the main algorithm, which uses
71027  *  [[HasInstance]].  [[HasInstance]] is defined for only
71028  *  function objects:
71029  *
71030  *    - Normal functions:
71031  *      E5 Section 15.3.5.3
71032  *    - Functions established with Function.prototype.bind():
71033  *      E5 Section 15.3.4.5.3
71034  *
71035  *  For other objects, a TypeError is thrown.
71036  *
71037  *  Limited Proxy support: don't support 'getPrototypeOf' trap but
71038  *  continue lookup in Proxy target if the value is a Proxy.
71039  */
71040 
71041 DUK_INTERNAL duk_bool_t duk_js_instanceof(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y) {
71042 	duk_context *ctx = (duk_context *) thr;
71043 	duk_hobject *func;
71044 	duk_hobject *val;
71045 	duk_hobject *proto;
71046 	duk_uint_t sanity;
71047 
71048 	/*
71049 	 *  Get the values onto the stack first.  It would be possible to cover
71050 	 *  some normal cases without resorting to the value stack.
71051 	 *
71052 	 *  The right hand side could be a light function (as they generally
71053 	 *  behave like objects).  Light functions never have a 'prototype'
71054 	 *  property so E5.1 Section 15.3.5.3 step 3 always throws a TypeError.
71055 	 *  Using duk_require_hobject() is thus correct (except for error msg).
71056 	 */
71057 
71058 	duk_push_tval(ctx, tv_x);
71059 	duk_push_tval(ctx, tv_y);
71060 	func = duk_require_hobject(ctx, -1);
71061 
71062 	/*
71063 	 *  For bound objects, [[HasInstance]] just calls the target function
71064 	 *  [[HasInstance]].  If that is again a bound object, repeat until
71065 	 *  we find a non-bound Function object.
71066 	 */
71067 
71068 	/* XXX: this bound function resolution also happens elsewhere,
71069 	 * move into a shared helper.
71070 	 */
71071 
71072 	sanity = DUK_HOBJECT_BOUND_CHAIN_SANITY;
71073 	do {
71074 		/* check func supports [[HasInstance]] (this is checked for every function
71075 		 * in the bound chain, including the final one)
71076 		 */
71077 
71078 		if (!DUK_HOBJECT_IS_CALLABLE(func)) {
71079 			/*
71080 			 *  Note: of native Ecmascript objects, only Function instances
71081 			 *  have a [[HasInstance]] internal property.  Custom objects might
71082 			 *  also have it, but not in current implementation.
71083 			 *
71084 			 *  XXX: add a separate flag, DUK_HOBJECT_FLAG_ALLOW_INSTANCEOF?
71085 			 */
71086 			DUK_ERROR_TYPE(thr, "invalid instanceof rval");
71087 		}
71088 
71089 		if (!DUK_HOBJECT_HAS_BOUND(func)) {
71090 			break;
71091 		}
71092 
71093 		/* [ ... lval rval ] */
71094 
71095 		duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_TARGET);         /* -> [ ... lval rval new_rval ] */
71096 		duk_replace(ctx, -1);                                        /* -> [ ... lval new_rval ] */
71097 		func = duk_require_hobject(ctx, -1);
71098 
71099 		/* func support for [[HasInstance]] checked in the beginning of the loop */
71100 	} while (--sanity > 0);
71101 
71102 	if (sanity == 0) {
71103 		DUK_ERROR_RANGE(thr, DUK_STR_BOUND_CHAIN_LIMIT);
71104 	}
71105 
71106 	/*
71107 	 *  'func' is now a non-bound object which supports [[HasInstance]]
71108 	 *  (which here just means DUK_HOBJECT_FLAG_CALLABLE).  Move on
71109 	 *  to execute E5 Section 15.3.5.3.
71110 	 */
71111 
71112 	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUND(func));
71113 	DUK_ASSERT(DUK_HOBJECT_IS_CALLABLE(func));
71114 
71115 	/* [ ... lval rval(func) ] */
71116 
71117 	/* Handle lightfuncs through object coercion for now. */
71118 	/* XXX: direct implementation */
71119 	val = duk_get_hobject_or_lfunc_coerce(ctx, -2);
71120 	if (!val) {
71121 		goto pop_and_false;
71122 	}
71123 
71124 	duk_get_prop_stridx(ctx, -1, DUK_STRIDX_PROTOTYPE);  /* -> [ ... lval rval rval.prototype ] */
71125 	proto = duk_require_hobject(ctx, -1);
71126 	duk_pop(ctx);  /* -> [ ... lval rval ] */
71127 
71128 	DUK_ASSERT(val != NULL);
71129 
71130 #if defined(DUK_USE_ES6_PROXY)
71131 	val = duk_hobject_resolve_proxy_target(thr, val);
71132 	DUK_ASSERT(val != NULL);
71133 #endif
71134 
71135 	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
71136 	do {
71137 		/*
71138 		 *  Note: prototype chain is followed BEFORE first comparison.  This
71139 		 *  means that the instanceof lval is never itself compared to the
71140 		 *  rval.prototype property.  This is apparently intentional, see E5
71141 		 *  Section 15.3.5.3, step 4.a.
71142 		 *
71143 		 *  Also note:
71144 		 *
71145 		 *      js> (function() {}) instanceof Function
71146 		 *      true
71147 		 *      js> Function instanceof Function
71148 		 *      true
71149 		 *
71150 		 *  For the latter, h_proto will be Function.prototype, which is the
71151 		 *  built-in Function prototype.  Because Function.[[Prototype]] is
71152 		 *  also the built-in Function prototype, the result is true.
71153 		 */
71154 
71155 		DUK_ASSERT(val != NULL);
71156 		val = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, val);
71157 
71158 		if (!val) {
71159 			goto pop_and_false;
71160 		}
71161 
71162 		DUK_ASSERT(val != NULL);
71163 #if defined(DUK_USE_ES6_PROXY)
71164 		val = duk_hobject_resolve_proxy_target(thr, val);
71165 #endif
71166 
71167 		if (val == proto) {
71168 			goto pop_and_true;
71169 		}
71170 
71171 		/* follow prototype chain */
71172 	} while (--sanity > 0);
71173 
71174 	if (sanity == 0) {
71175 		DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
71176 	}
71177 	DUK_UNREACHABLE();
71178 
71179  pop_and_false:
71180 	duk_pop_2(ctx);
71181 	return 0;
71182 
71183  pop_and_true:
71184 	duk_pop_2(ctx);
71185 	return 1;
71186 }
71187 
71188 /*
71189  *  in
71190  */
71191 
71192 /*
71193  *  E5 Sections 11.8.7, 8.12.6.
71194  *
71195  *  Basically just a property existence check using [[HasProperty]].
71196  */
71197 
71198 DUK_INTERNAL duk_bool_t duk_js_in(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y) {
71199 	duk_context *ctx = (duk_context *) thr;
71200 	duk_bool_t retval;
71201 
71202 	/*
71203 	 *  Get the values onto the stack first.  It would be possible to cover
71204 	 *  some normal cases without resorting to the value stack (e.g. if
71205 	 *  lval is already a string).
71206 	 */
71207 
71208 	/* XXX: The ES5/5.1/6 specifications require that the key in 'key in obj'
71209 	 * must be string coerced before the internal HasProperty() algorithm is
71210 	 * invoked.  A fast path skipping coercion could be safely implemented for
71211 	 * numbers (as number-to-string coercion has no side effects).  For ES6
71212 	 * proxy behavior, the trap 'key' argument must be in a string coerced
71213 	 * form (which is a shame).
71214 	 */
71215 
71216 	/* TypeError if rval is not an object (or lightfunc which should behave
71217 	 * like a Function instance).
71218 	 */
71219 	duk_push_tval(ctx, tv_x);
71220 	duk_push_tval(ctx, tv_y);
71221 	duk_require_type_mask(ctx, -1, DUK_TYPE_MASK_OBJECT | DUK_TYPE_MASK_LIGHTFUNC);
71222 	duk_to_string(ctx, -2);               /* coerce lval with ToString() */
71223 
71224 	retval = duk_hobject_hasprop(thr,
71225 	                             DUK_GET_TVAL_NEGIDX(ctx, -1),
71226 	                             DUK_GET_TVAL_NEGIDX(ctx, -2));
71227 
71228 	duk_pop_2(ctx);
71229 	return retval;
71230 }
71231 
71232 /*
71233  *  typeof
71234  *
71235  *  E5 Section 11.4.3.
71236  *
71237  *  Very straightforward.  The only question is what to return for our
71238  *  non-standard tag / object types.
71239  *
71240  *  There is an unfortunate string constant define naming problem with
71241  *  typeof return values for e.g. "Object" and "object"; careful with
71242  *  the built-in string defines.  The LC_XXX defines are used for the
71243  *  lowercase variants now.
71244  */
71245 
71246 DUK_INTERNAL duk_hstring *duk_js_typeof(duk_hthread *thr, duk_tval *tv_x) {
71247 	duk_small_int_t stridx = 0;
71248 
71249 	DUK_UNREF(thr);
71250 
71251 	switch (DUK_TVAL_GET_TAG(tv_x)) {
71252 	case DUK_TAG_UNDEFINED: {
71253 		stridx = DUK_STRIDX_LC_UNDEFINED;
71254 		break;
71255 	}
71256 	case DUK_TAG_NULL: {
71257 		/* Note: not a typo, "object" is returned for a null value */
71258 		stridx = DUK_STRIDX_LC_OBJECT;
71259 		break;
71260 	}
71261 	case DUK_TAG_BOOLEAN: {
71262 		stridx = DUK_STRIDX_LC_BOOLEAN;
71263 		break;
71264 	}
71265 	case DUK_TAG_POINTER: {
71266 		/* implementation specific */
71267 		stridx = DUK_STRIDX_LC_POINTER;
71268 		break;
71269 	}
71270 	case DUK_TAG_STRING: {
71271 		stridx = DUK_STRIDX_LC_STRING;
71272 		break;
71273 	}
71274 	case DUK_TAG_OBJECT: {
71275 		duk_hobject *obj = DUK_TVAL_GET_OBJECT(tv_x);
71276 		DUK_ASSERT(obj != NULL);
71277 		if (DUK_HOBJECT_IS_CALLABLE(obj)) {
71278 			stridx = DUK_STRIDX_LC_FUNCTION;
71279 		} else {
71280 			stridx = DUK_STRIDX_LC_OBJECT;
71281 		}
71282 		break;
71283 	}
71284 	case DUK_TAG_BUFFER: {
71285 		/* implementation specific */
71286 		stridx = DUK_STRIDX_LC_BUFFER;
71287 		break;
71288 	}
71289 	case DUK_TAG_LIGHTFUNC: {
71290 		stridx = DUK_STRIDX_LC_FUNCTION;
71291 		break;
71292 	}
71293 #if defined(DUK_USE_FASTINT)
71294 	case DUK_TAG_FASTINT:
71295 #endif
71296 	default: {
71297 		/* number */
71298 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv_x));
71299 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_x));
71300 		stridx = DUK_STRIDX_LC_NUMBER;
71301 		break;
71302 	}
71303 	}
71304 
71305 	DUK_ASSERT(stridx >= 0 && stridx < DUK_HEAP_NUM_STRINGS);
71306 	return DUK_HTHREAD_GET_STRING(thr, stridx);
71307 }
71308 
71309 /*
71310  *  Array index and length
71311  *
71312  *  Array index: E5 Section 15.4
71313  *  Array length: E5 Section 15.4.5.1 steps 3.c - 3.d (array length write)
71314  *
71315  *  The DUK_HSTRING_GET_ARRIDX_SLOW() and DUK_HSTRING_GET_ARRIDX_FAST() macros
71316  *  call duk_js_to_arrayindex_string_helper().
71317  */
71318 
71319 DUK_INTERNAL duk_small_int_t duk_js_to_arrayindex_raw_string(const duk_uint8_t *str, duk_uint32_t blen, duk_uarridx_t *out_idx) {
71320 	duk_uarridx_t res;
71321 
71322 	if (blen == 0 || blen > 10) {
71323 		goto parse_fail;
71324 	}
71325 	if (str[0] == DUK_ASC_0 && blen > 1) {
71326 		goto parse_fail;
71327 	}
71328 
71329 	/* Accept 32-bit decimal integers, no leading zeroes, signs, etc.
71330 	 * Leading zeroes are not accepted (zero index "0" is an exception
71331 	 * handled above).
71332 	 */
71333 
71334 	res = 0;
71335 	while (blen-- > 0) {
71336 		duk_uint8_t c = *str++;
71337 		if (c >= DUK_ASC_0 && c <= DUK_ASC_9) {
71338 			/* Careful overflow handling.  When multiplying by 10:
71339 			 * - 0x19999998 x 10 = 0xfffffff0: no overflow, and adding
71340 			 *   0...9 is safe.
71341 			 * - 0x19999999 x 10 = 0xfffffffa: no overflow, adding
71342 			 *   0...5 is safe, 6...9 overflows.
71343 			 * - 0x1999999a x 10 = 0x100000004: always overflow.
71344 			 */
71345 			if (DUK_UNLIKELY(res >= 0x19999999UL)) {
71346 				if (res >= 0x1999999aUL) {
71347 					/* Always overflow. */
71348 					goto parse_fail;
71349 				}
71350 				DUK_ASSERT(res == 0x19999999UL);
71351 				c -= DUK_ASC_0;
71352 				if (c >= 6) {
71353 					goto parse_fail;
71354 				}
71355 				res = 0xfffffffaUL + c;
71356 				DUK_ASSERT(res >= 0xfffffffaUL);
71357 				DUK_ASSERT_DISABLE(res <= 0xffffffffUL);  /* range */
71358 			} else {
71359 				res = res * 10U + (duk_uint32_t) (c - DUK_ASC_0);
71360 			}
71361 		} else {
71362 			goto parse_fail;
71363 		}
71364 	}
71365 
71366 	*out_idx = res;
71367 	return 1;
71368 
71369  parse_fail:
71370 	*out_idx = DUK_HSTRING_NO_ARRAY_INDEX;
71371 	return 0;
71372 }
71373 
71374 /* Called by duk_hstring.h macros */
71375 DUK_INTERNAL duk_uarridx_t duk_js_to_arrayindex_string_helper(duk_hstring *h) {
71376 	duk_uarridx_t res;
71377 	duk_small_int_t rc;
71378 
71379 	if (!DUK_HSTRING_HAS_ARRIDX(h)) {
71380 		return DUK_HSTRING_NO_ARRAY_INDEX;
71381 	}
71382 
71383 	rc = duk_js_to_arrayindex_raw_string(DUK_HSTRING_GET_DATA(h),
71384 	                                     DUK_HSTRING_GET_BYTELEN(h),
71385 	                                     &res);
71386 	DUK_UNREF(rc);
71387 	DUK_ASSERT(rc != 0);
71388 	return res;
71389 }
71390 /*
71391  *  Identifier access and function closure handling.
71392  *
71393  *  Provides the primitives for slow path identifier accesses: GETVAR,
71394  *  PUTVAR, DELVAR, etc.  The fast path, direct register accesses, should
71395  *  be used for most identifier accesses.  Consequently, these slow path
71396  *  primitives should be optimized for maximum compactness.
71397  *
71398  *  Ecmascript environment records (declarative and object) are represented
71399  *  as internal objects with control keys.  Environment records have a
71400  *  parent record ("outer environment reference") which is represented by
71401  *  the implicit prototype for technical reasons (in other words, it is a
71402  *  convenient field).  The prototype chain is not followed in the ordinary
71403  *  sense for variable lookups.
71404  *
71405  *  See identifier-handling.rst for more details on the identifier algorithms
71406  *  and the internal representation.  See function-objects.rst for details on
71407  *  what function templates and instances are expected to look like.
71408  *
71409  *  Care must be taken to avoid duk_tval pointer invalidation caused by
71410  *  e.g. value stack or object resizing.
71411  *
71412  *  TODO: properties for function instances could be initialized much more
71413  *  efficiently by creating a property allocation for a certain size and
71414  *  filling in keys and values directly (and INCREFing both with "bulk incref"
71415  *  primitives.
71416  *
71417  *  XXX: duk_hobject_getprop() and duk_hobject_putprop() calls are a bit
71418  *  awkward (especially because they follow the prototype chain); rework
71419  *  if "raw" own property helpers are added.
71420  */
71421 
71422 /* include removed: duk_internal.h */
71423 
71424 /*
71425  *  Local result type for duk__get_identifier_reference() lookup.
71426  */
71427 
71428 typedef struct {
71429 	duk_hobject *holder;      /* for object-bound identifiers */
71430 	duk_tval *value;          /* for register-bound and declarative env identifiers */
71431 	duk_int_t attrs;          /* property attributes for identifier (relevant if value != NULL) */
71432 	duk_tval *this_binding;
71433 	duk_hobject *env;
71434 } duk__id_lookup_result;
71435 
71436 /*
71437  *  Create a new function object based on a "template function" which contains
71438  *  compiled bytecode, constants, etc, but lacks a lexical environment.
71439  *
71440  *  Ecmascript requires that each created closure is a separate object, with
71441  *  its own set of editable properties.  However, structured property values
71442  *  (such as the formal arguments list and the variable map) are shared.
71443  *  Also the bytecode, constants, and inner functions are shared.
71444  *
71445  *  See E5 Section 13.2 for detailed requirements on the function objects;
71446  *  there are no similar requirements for function "templates" which are an
71447  *  implementation dependent internal feature.  Also see function-objects.rst
71448  *  for a discussion on the function instance properties provided by this
71449  *  implementation.
71450  *
71451  *  Notes:
71452  *
71453  *   * Order of internal properties should match frequency of use, since the
71454  *     properties will be linearly scanned on lookup (functions usually don't
71455  *     have enough properties to warrant a hash part).
71456  *
71457  *   * The created closure is independent of its template; they do share the
71458  *     same 'data' buffer object, but the template object itself can be freed
71459  *     even if the closure object remains reachable.
71460  */
71461 
71462 DUK_LOCAL void duk__inc_data_inner_refcounts(duk_hthread *thr, duk_hcompiledfunction *f) {
71463 	duk_tval *tv, *tv_end;
71464 	duk_hobject **funcs, **funcs_end;
71465 
71466 	/* If function creation fails due to out-of-memory, the data buffer
71467 	 * pointer may be NULL in some cases.  That's actually possible for
71468 	 * GC code, but shouldn't be possible here because the incomplete
71469 	 * function will be unwound from the value stack and never instantiated.
71470 	 */
71471 	DUK_ASSERT(DUK_HCOMPILEDFUNCTION_GET_DATA(thr->heap, f) != NULL);
71472 	DUK_UNREF(thr);
71473 
71474 	tv = DUK_HCOMPILEDFUNCTION_GET_CONSTS_BASE(thr->heap, f);
71475 	tv_end = DUK_HCOMPILEDFUNCTION_GET_CONSTS_END(thr->heap, f);
71476 	while (tv < tv_end) {
71477 		DUK_TVAL_INCREF(thr, tv);
71478 		tv++;
71479 	}
71480 
71481 	funcs = DUK_HCOMPILEDFUNCTION_GET_FUNCS_BASE(thr->heap, f);
71482 	funcs_end = DUK_HCOMPILEDFUNCTION_GET_FUNCS_END(thr->heap, f);
71483 	while (funcs < funcs_end) {
71484 		DUK_HEAPHDR_INCREF(thr, (duk_heaphdr *) *funcs);
71485 		funcs++;
71486 	}
71487 }
71488 
71489 /* Push a new closure on the stack.
71490  *
71491  * Note: if fun_temp has NEWENV, i.e. a new lexical and variable declaration
71492  * is created when the function is called, only outer_lex_env matters
71493  * (outer_var_env is ignored and may or may not be same as outer_lex_env).
71494  */
71495 
71496 DUK_LOCAL const duk_uint16_t duk__closure_copy_proplist[] = {
71497 	/* order: most frequent to least frequent */
71498 	DUK_STRIDX_INT_VARMAP,
71499 	DUK_STRIDX_INT_FORMALS,
71500 	DUK_STRIDX_NAME,
71501 	DUK_STRIDX_INT_PC2LINE,
71502 	DUK_STRIDX_FILE_NAME,
71503 	DUK_STRIDX_INT_SOURCE
71504 };
71505 
71506 DUK_INTERNAL
71507 void duk_js_push_closure(duk_hthread *thr,
71508                          duk_hcompiledfunction *fun_temp,
71509                          duk_hobject *outer_var_env,
71510                          duk_hobject *outer_lex_env,
71511                          duk_bool_t add_auto_proto) {
71512 	duk_context *ctx = (duk_context *) thr;
71513 	duk_hcompiledfunction *fun_clos;
71514 	duk_small_uint_t i;
71515 	duk_uint_t len_value;
71516 
71517 	DUK_ASSERT(fun_temp != NULL);
71518 	DUK_ASSERT(DUK_HCOMPILEDFUNCTION_GET_DATA(thr->heap, fun_temp) != NULL);
71519 	DUK_ASSERT(DUK_HCOMPILEDFUNCTION_GET_FUNCS(thr->heap, fun_temp) != NULL);
71520 	DUK_ASSERT(DUK_HCOMPILEDFUNCTION_GET_BYTECODE(thr->heap, fun_temp) != NULL);
71521 	DUK_ASSERT(outer_var_env != NULL);
71522 	DUK_ASSERT(outer_lex_env != NULL);
71523 	DUK_UNREF(len_value);
71524 
71525 	duk_push_compiledfunction(ctx);
71526 	duk_push_hobject(ctx, &fun_temp->obj);  /* -> [ ... closure template ] */
71527 
71528 	fun_clos = (duk_hcompiledfunction *) duk_get_hcompiledfunction(ctx, -2);
71529 	DUK_ASSERT(fun_clos != NULL);
71530 	DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION((duk_hobject *) fun_clos));
71531 	DUK_ASSERT(DUK_HCOMPILEDFUNCTION_GET_DATA(thr->heap, fun_clos) == NULL);
71532 	DUK_ASSERT(DUK_HCOMPILEDFUNCTION_GET_FUNCS(thr->heap, fun_clos) == NULL);
71533 	DUK_ASSERT(DUK_HCOMPILEDFUNCTION_GET_BYTECODE(thr->heap, fun_clos) == NULL);
71534 
71535 	DUK_HCOMPILEDFUNCTION_SET_DATA(thr->heap, fun_clos, DUK_HCOMPILEDFUNCTION_GET_DATA(thr->heap, fun_temp));
71536 	DUK_HCOMPILEDFUNCTION_SET_FUNCS(thr->heap, fun_clos, DUK_HCOMPILEDFUNCTION_GET_FUNCS(thr->heap, fun_temp));
71537 	DUK_HCOMPILEDFUNCTION_SET_BYTECODE(thr->heap, fun_clos, DUK_HCOMPILEDFUNCTION_GET_BYTECODE(thr->heap, fun_temp));
71538 
71539 	/* Note: all references inside 'data' need to get their refcounts
71540 	 * upped too.  This is the case because refcounts are decreased
71541 	 * through every function referencing 'data' independently.
71542 	 */
71543 
71544 	DUK_HBUFFER_INCREF(thr, DUK_HCOMPILEDFUNCTION_GET_DATA(thr->heap, fun_clos));
71545 	duk__inc_data_inner_refcounts(thr, fun_temp);
71546 
71547 	fun_clos->nregs = fun_temp->nregs;
71548 	fun_clos->nargs = fun_temp->nargs;
71549 #if defined(DUK_USE_DEBUGGER_SUPPORT)
71550 	fun_clos->start_line = fun_temp->start_line;
71551 	fun_clos->end_line = fun_temp->end_line;
71552 #endif
71553 
71554 	DUK_ASSERT(DUK_HCOMPILEDFUNCTION_GET_DATA(thr->heap, fun_clos) != NULL);
71555 	DUK_ASSERT(DUK_HCOMPILEDFUNCTION_GET_FUNCS(thr->heap, fun_clos) != NULL);
71556 	DUK_ASSERT(DUK_HCOMPILEDFUNCTION_GET_BYTECODE(thr->heap, fun_clos) != NULL);
71557 
71558 	/* XXX: could also copy from template, but there's no way to have any
71559 	 * other value here now (used code has no access to the template).
71560 	 */
71561 	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, &fun_clos->obj, thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
71562 
71563 	/*
71564 	 *  Init/assert flags, copying them where appropriate.  Some flags
71565 	 *  (like NEWENV) are processed separately below.
71566 	 */
71567 
71568 	/* XXX: copy flags using a mask */
71569 
71570 	DUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE(&fun_clos->obj));
71571 	DUK_HOBJECT_SET_CONSTRUCTABLE(&fun_clos->obj);  /* Note: not set in template (has no "prototype") */
71572 	DUK_ASSERT(DUK_HOBJECT_HAS_CONSTRUCTABLE(&fun_clos->obj));
71573 	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUND(&fun_clos->obj));
71574 	DUK_ASSERT(DUK_HOBJECT_HAS_COMPILEDFUNCTION(&fun_clos->obj));
71575 	DUK_ASSERT(!DUK_HOBJECT_HAS_NATIVEFUNCTION(&fun_clos->obj));
71576 	DUK_ASSERT(!DUK_HOBJECT_HAS_THREAD(&fun_clos->obj));
71577 	/* DUK_HOBJECT_FLAG_ARRAY_PART: don't care */
71578 	if (DUK_HOBJECT_HAS_STRICT(&fun_temp->obj)) {
71579 		DUK_HOBJECT_SET_STRICT(&fun_clos->obj);
71580 	}
71581 	if (DUK_HOBJECT_HAS_NOTAIL(&fun_temp->obj)) {
71582 		DUK_HOBJECT_SET_NOTAIL(&fun_clos->obj);
71583 	}
71584 	/* DUK_HOBJECT_FLAG_NEWENV: handled below */
71585 	if (DUK_HOBJECT_HAS_NAMEBINDING(&fun_temp->obj)) {
71586 		/* Although NAMEBINDING is not directly needed for using
71587 		 * function instances, it's needed by bytecode dump/load
71588 		 * so copy it too.
71589 		 */
71590 		DUK_HOBJECT_SET_NAMEBINDING(&fun_clos->obj);
71591 	}
71592 	if (DUK_HOBJECT_HAS_CREATEARGS(&fun_temp->obj)) {
71593 		DUK_HOBJECT_SET_CREATEARGS(&fun_clos->obj);
71594 	}
71595 	DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARRAY(&fun_clos->obj));
71596 	DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(&fun_clos->obj));
71597 	DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(&fun_clos->obj));
71598 
71599 	/*
71600 	 *  Setup environment record properties based on the template and
71601 	 *  its flags.
71602 	 *
71603 	 *  If DUK_HOBJECT_HAS_NEWENV(fun_temp) is true, the environment
71604 	 *  records represent identifiers "outside" the function; the
71605 	 *  "inner" environment records are created on demand.  Otherwise,
71606 	 *  the environment records are those that will be directly used
71607 	 *  (e.g. for declarations).
71608 	 *
71609 	 *  _Lexenv is always set; _Varenv defaults to _Lexenv if missing,
71610 	 *  so _Varenv is only set if _Lexenv != _Varenv.
71611 	 *
71612 	 *  This is relatively complex, see doc/identifier-handling.rst.
71613 	 */
71614 
71615 	if (DUK_HOBJECT_HAS_NEWENV(&fun_temp->obj)) {
71616 		DUK_HOBJECT_SET_NEWENV(&fun_clos->obj);
71617 
71618 		if (DUK_HOBJECT_HAS_NAMEBINDING(&fun_temp->obj)) {
71619 			duk_hobject *proto;
71620 
71621 			/*
71622 			 *  Named function expression, name needs to be bound
71623 			 *  in an intermediate environment record.  The "outer"
71624 			 *  lexical/variable environment will thus be:
71625 			 *
71626 			 *  a) { funcname: <func>, __prototype: outer_lex_env }
71627 			 *  b) { funcname: <func>, __prototype:  <globalenv> }  (if outer_lex_env missing)
71628 			 */
71629 
71630 			DUK_ASSERT(duk_has_prop_stridx(ctx, -1, DUK_STRIDX_NAME));  /* required if NAMEBINDING set */
71631 
71632 			if (outer_lex_env) {
71633 				proto = outer_lex_env;
71634 			} else {
71635 				proto = thr->builtins[DUK_BIDX_GLOBAL_ENV];
71636 			}
71637 
71638 			/* -> [ ... closure template env ] */
71639 			(void) duk_push_object_helper_proto(ctx,
71640 			                                    DUK_HOBJECT_FLAG_EXTENSIBLE |
71641 			                                    DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV),
71642 			                                    proto);
71643 
71644 			/* It's important that duk_xdef_prop() is a 'raw define' so that any
71645 			 * properties in an ancestor are never an issue (they should never be
71646 			 * e.g. non-writable, but just in case).
71647 			 */
71648 			duk_get_prop_stridx(ctx, -2, DUK_STRIDX_NAME);       /* -> [ ... closure template env funcname ] */
71649 			duk_dup(ctx, -4);                                    /* -> [ ... closure template env funcname closure ] */
71650 			duk_xdef_prop(ctx, -3, DUK_PROPDESC_FLAGS_NONE);     /* -> [ ... closure template env ] */
71651 			/* env[funcname] = closure */
71652 
71653 			/* [ ... closure template env ] */
71654 
71655 			duk_xdef_prop_stridx(ctx, -3, DUK_STRIDX_INT_LEXENV, DUK_PROPDESC_FLAGS_WC);
71656 			/* since closure has NEWENV, never define DUK_STRIDX_INT_VARENV, as it
71657 			 * will be ignored anyway
71658 			 */
71659 
71660 			/* [ ... closure template ] */
71661 		} else {
71662 			/*
71663 			 *  Other cases (function declaration, anonymous function expression,
71664 			 *  strict direct eval code).  The "outer" environment will be whatever
71665 			 *  the caller gave us.
71666 			 */
71667 
71668 			duk_push_hobject(ctx, outer_lex_env);  /* -> [ ... closure template env ] */
71669 			duk_xdef_prop_stridx(ctx, -3, DUK_STRIDX_INT_LEXENV, DUK_PROPDESC_FLAGS_WC);
71670 			/* since closure has NEWENV, never define DUK_STRIDX_INT_VARENV, as it
71671 			 * will be ignored anyway
71672 			 */
71673 
71674 			/* [ ... closure template ] */
71675 		}
71676 	} else {
71677 		/*
71678 		 *  Function gets no new environment when called.  This is the
71679 		 *  case for global code, indirect eval code, and non-strict
71680 		 *  direct eval code.  There is no direct correspondence to the
71681 		 *  E5 specification, as global/eval code is not exposed as a
71682 		 *  function.
71683 		 */
71684 
71685 		DUK_ASSERT(!DUK_HOBJECT_HAS_NAMEBINDING(&fun_temp->obj));
71686 
71687 		duk_push_hobject(ctx, outer_lex_env);  /* -> [ ... closure template env ] */
71688 		duk_xdef_prop_stridx(ctx, -3, DUK_STRIDX_INT_LEXENV, DUK_PROPDESC_FLAGS_WC);
71689 
71690 		if (outer_var_env != outer_lex_env) {
71691 			duk_push_hobject(ctx, outer_var_env);  /* -> [ ... closure template env ] */
71692 			duk_xdef_prop_stridx(ctx, -3, DUK_STRIDX_INT_VARENV, DUK_PROPDESC_FLAGS_WC);
71693 		}
71694 	}
71695 #ifdef DUK_USE_DDDPRINT
71696 	duk_get_prop_stridx(ctx, -2, DUK_STRIDX_INT_VARENV);
71697 	duk_get_prop_stridx(ctx, -3, DUK_STRIDX_INT_LEXENV);
71698 	DUK_DDD(DUK_DDDPRINT("closure varenv -> %!ipT, lexenv -> %!ipT",
71699 	                     (duk_tval *) duk_get_tval(ctx, -2),
71700 	                     (duk_tval *) duk_get_tval(ctx, -1)));
71701 	duk_pop_2(ctx);
71702 #endif
71703 
71704 	/*
71705 	 *  Copy some internal properties directly
71706 	 *
71707 	 *  The properties will be writable and configurable, but not enumerable.
71708 	 */
71709 
71710 	/* [ ... closure template ] */
71711 
71712 	DUK_DDD(DUK_DDDPRINT("copying properties: closure=%!iT, template=%!iT",
71713 	                     (duk_tval *) duk_get_tval(ctx, -2),
71714 	                     (duk_tval *) duk_get_tval(ctx, -1)));
71715 
71716 	for (i = 0; i < (duk_small_uint_t) (sizeof(duk__closure_copy_proplist) / sizeof(duk_uint16_t)); i++) {
71717 		duk_small_int_t stridx = (duk_small_int_t) duk__closure_copy_proplist[i];
71718 		if (duk_get_prop_stridx(ctx, -1, stridx)) {
71719 			/* [ ... closure template val ] */
71720 			DUK_DDD(DUK_DDDPRINT("copying property, stridx=%ld -> found", (long) stridx));
71721 			duk_xdef_prop_stridx(ctx, -3, stridx, DUK_PROPDESC_FLAGS_WC);
71722 		} else {
71723 			DUK_DDD(DUK_DDDPRINT("copying property, stridx=%ld -> not found", (long) stridx));
71724 			duk_pop(ctx);
71725 		}
71726 	}
71727 
71728 	/*
71729 	 *  "length" maps to number of formals (E5 Section 13.2) for function
71730 	 *  declarations/expressions (non-bound functions).  Note that 'nargs'
71731 	 *  is NOT necessarily equal to the number of arguments.
71732 	 */
71733 
71734 	/* [ ... closure template ] */
71735 
71736 	len_value = 0;
71737 
71738 	/* XXX: use helper for size optimization */
71739 	if (duk_get_prop_stridx(ctx, -2, DUK_STRIDX_INT_FORMALS)) {
71740 		/* [ ... closure template formals ] */
71741 		DUK_ASSERT(duk_has_prop_stridx(ctx, -1, DUK_STRIDX_LENGTH));
71742 		DUK_ASSERT(duk_get_length(ctx, -1) <= DUK_UINT_MAX);  /* formal arg limits */
71743 		len_value = (duk_uint_t) duk_get_length(ctx, -1);
71744 	} else {
71745 		/* XXX: what to do if _Formals is not empty but compiler has
71746 		 * optimized it away -- read length from an explicit property
71747 		 * then?
71748 		 */
71749 	}
71750 	duk_pop(ctx);
71751 
71752 	duk_push_uint(ctx, len_value);  /* [ ... closure template len_value ] */
71753 	duk_xdef_prop_stridx(ctx, -3, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_NONE);
71754 
71755 	/*
71756 	 *  "prototype" is, by default, a fresh object with the "constructor"
71757 	 *  property.
71758 	 *
71759 	 *  Note that this creates a circular reference for every function
71760 	 *  instance (closure) which prevents refcount-based collection of
71761 	 *  function instances.
71762 	 *
71763 	 *  XXX: Try to avoid creating the default prototype object, because
71764 	 *  many functions are not used as constructors and the default
71765 	 *  prototype is unnecessary.  Perhaps it could be created on-demand
71766 	 *  when it is first accessed?
71767 	 */
71768 
71769 	/* [ ... closure template ] */
71770 
71771 	if (add_auto_proto) {
71772 		duk_push_object(ctx);  /* -> [ ... closure template newobj ] */
71773 		duk_dup(ctx, -3);          /* -> [ ... closure template newobj closure ] */
71774 		duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_CONSTRUCTOR, DUK_PROPDESC_FLAGS_WC);  /* -> [ ... closure template newobj ] */
71775 		duk_compact(ctx, -1);  /* compact the prototype */
71776 		duk_xdef_prop_stridx(ctx, -3, DUK_STRIDX_PROTOTYPE, DUK_PROPDESC_FLAGS_W);     /* -> [ ... closure template ] */
71777 	}
71778 
71779 	/*
71780 	 *  "arguments" and "caller" must be mapped to throwers for strict
71781 	 *  mode and bound functions (E5 Section 15.3.5).
71782 	 *
71783 	 *  XXX: This is expensive to have for every strict function instance.
71784 	 *  Try to implement as virtual properties or on-demand created properties.
71785 	 */
71786 
71787 	/* [ ... closure template ] */
71788 
71789 	if (DUK_HOBJECT_HAS_STRICT(&fun_clos->obj)) {
71790 		duk_xdef_prop_stridx_thrower(ctx, -2, DUK_STRIDX_CALLER, DUK_PROPDESC_FLAGS_NONE);
71791 		duk_xdef_prop_stridx_thrower(ctx, -2, DUK_STRIDX_LC_ARGUMENTS, DUK_PROPDESC_FLAGS_NONE);
71792 	} else {
71793 #ifdef DUK_USE_NONSTD_FUNC_CALLER_PROPERTY
71794 		DUK_DDD(DUK_DDDPRINT("function is non-strict and non-standard 'caller' property in use, add initial 'null' value"));
71795 		duk_push_null(ctx);
71796 		duk_xdef_prop_stridx(ctx, -3, DUK_STRIDX_CALLER, DUK_PROPDESC_FLAGS_NONE);
71797 #else
71798 		DUK_DDD(DUK_DDDPRINT("function is non-strict and non-standard 'caller' property not used"));
71799 #endif
71800 	}
71801 
71802 	/*
71803 	 *  "name" is a non-standard property found in at least V8, Rhino, smjs.
71804 	 *  For Rhino and smjs it is non-writable, non-enumerable, and non-configurable;
71805 	 *  for V8 it is writable, non-enumerable, non-configurable.  It is also defined
71806 	 *  for an anonymous function expression in which case the value is an empty string.
71807 	 *  We could also leave name 'undefined' for anonymous functions but that would
71808 	 *  differ from behavior of other engines, so use an empty string.
71809 	 *
71810 	 *  XXX: make optional?  costs something per function.
71811 	 */
71812 
71813 	/* [ ... closure template ] */
71814 
71815 	if (duk_get_prop_stridx(ctx, -1, DUK_STRIDX_NAME)) {
71816 		/* [ ... closure template name ] */
71817 		DUK_ASSERT(duk_is_string(ctx, -1));
71818 	} else {
71819 		/* [ ... closure template undefined ] */
71820 		duk_pop(ctx);
71821 		duk_push_hstring_stridx(ctx, DUK_STRIDX_EMPTY_STRING);
71822 	}
71823 	duk_xdef_prop_stridx(ctx, -3, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_NONE);  /* -> [ ... closure template ] */
71824 
71825 	/*
71826 	 *  Compact the closure, in most cases no properties will be added later.
71827 	 *  Also, without this the closures end up having unused property slots
71828 	 *  (e.g. in Duktape 0.9.0, 8 slots would be allocated and only 7 used).
71829 	 *  A better future solution would be to allocate the closure directly
71830 	 *  to correct size (and setup the properties directly without going
71831 	 *  through the API).
71832 	 */
71833 
71834 	duk_compact(ctx, -2);
71835 
71836 	/*
71837 	 *  Some assertions (E5 Section 13.2).
71838 	 */
71839 
71840 	DUK_ASSERT(DUK_HOBJECT_GET_CLASS_NUMBER(&fun_clos->obj) == DUK_HOBJECT_CLASS_FUNCTION);
71841 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, &fun_clos->obj) == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
71842 	DUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE(&fun_clos->obj));
71843 	DUK_ASSERT(duk_has_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH) != 0);
71844 	DUK_ASSERT(add_auto_proto == 0 || duk_has_prop_stridx(ctx, -2, DUK_STRIDX_PROTOTYPE) != 0);
71845 	DUK_ASSERT(duk_has_prop_stridx(ctx, -2, DUK_STRIDX_NAME) != 0);  /* non-standard */
71846 	DUK_ASSERT(!DUK_HOBJECT_HAS_STRICT(&fun_clos->obj) ||
71847 	           duk_has_prop_stridx(ctx, -2, DUK_STRIDX_CALLER) != 0);
71848 	DUK_ASSERT(!DUK_HOBJECT_HAS_STRICT(&fun_clos->obj) ||
71849 	           duk_has_prop_stridx(ctx, -2, DUK_STRIDX_LC_ARGUMENTS) != 0);
71850 
71851 	/*
71852 	 *  Finish
71853 	 */
71854 
71855 	/* [ ... closure template ] */
71856 
71857 	DUK_DDD(DUK_DDDPRINT("created function instance: template=%!iT -> closure=%!iT",
71858 	                     (duk_tval *) duk_get_tval(ctx, -1),
71859 	                     (duk_tval *) duk_get_tval(ctx, -2)));
71860 
71861 	duk_pop(ctx);
71862 
71863 	/* [ ... closure ] */
71864 }
71865 
71866 /*
71867  *  Delayed activation environment record initialization (for functions
71868  *  with NEWENV).
71869  *
71870  *  The non-delayed initialization is handled by duk_handle_call().
71871  */
71872 
71873 /* shared helper */
71874 DUK_INTERNAL
71875 duk_hobject *duk_create_activation_environment_record(duk_hthread *thr,
71876                                                       duk_hobject *func,
71877                                                       duk_size_t idx_bottom) {
71878 	duk_context *ctx = (duk_context *) thr;
71879 	duk_hobject *env;
71880 	duk_hobject *parent;
71881 	duk_tval *tv;
71882 
71883 	DUK_ASSERT(thr != NULL);
71884 	DUK_ASSERT(func != NULL);
71885 
71886 	tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, func, DUK_HTHREAD_STRING_INT_LEXENV(thr));
71887 	if (tv) {
71888 		DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv));
71889 		DUK_ASSERT(DUK_HOBJECT_IS_ENV(DUK_TVAL_GET_OBJECT(tv)));
71890 		parent = DUK_TVAL_GET_OBJECT(tv);
71891 	} else {
71892 		parent = thr->builtins[DUK_BIDX_GLOBAL_ENV];
71893 	}
71894 
71895 	(void) duk_push_object_helper(ctx,
71896 	                              DUK_HOBJECT_FLAG_EXTENSIBLE |
71897 	                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV),
71898 	                              -1);  /* no prototype, updated below */
71899 	env = duk_require_hobject(ctx, -1);
71900 	DUK_ASSERT(env != NULL);
71901 	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, env, parent);  /* parent env is the prototype */
71902 
71903 	/* open scope information, for compiled functions only */
71904 
71905 	if (DUK_HOBJECT_IS_COMPILEDFUNCTION(func)) {
71906 		duk_push_hthread(ctx, thr);
71907 		duk_xdef_prop_stridx_wec(ctx, -2, DUK_STRIDX_INT_THREAD);
71908 		duk_push_hobject(ctx, func);
71909 		duk_xdef_prop_stridx_wec(ctx, -2, DUK_STRIDX_INT_CALLEE);
71910 		duk_push_size_t(ctx, idx_bottom);
71911 		duk_xdef_prop_stridx_wec(ctx, -2, DUK_STRIDX_INT_REGBASE);
71912 	}
71913 
71914 	return env;
71915 }
71916 
71917 DUK_INTERNAL
71918 void duk_js_init_activation_environment_records_delayed(duk_hthread *thr,
71919                                                         duk_activation *act) {
71920 	duk_context *ctx = (duk_context *) thr;
71921 	duk_hobject *func;
71922 	duk_hobject *env;
71923 	duk_size_t act_off;
71924 
71925 	DUK_ASSERT(act != NULL);
71926 	act_off = (duk_size_t) ((duk_uint8_t *) act - (duk_uint8_t *) thr->callstack);
71927 	func = DUK_ACT_GET_FUNC(act);
71928 	DUK_ASSERT(func != NULL);
71929 	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUND(func));  /* bound functions are never in act 'func' */
71930 
71931 	/*
71932 	 *  Delayed initialization only occurs for 'NEWENV' functions.
71933 	 */
71934 
71935 	DUK_ASSERT(DUK_HOBJECT_HAS_NEWENV(func));
71936 	DUK_ASSERT(act->lex_env == NULL);
71937 	DUK_ASSERT(act->var_env == NULL);
71938 
71939 	env = duk_create_activation_environment_record(thr, func, act->idx_bottom);
71940 	DUK_ASSERT(env != NULL);
71941 	act = (duk_activation *) ((duk_uint8_t *) thr->callstack + act_off);
71942 
71943 	DUK_DDD(DUK_DDDPRINT("created delayed fresh env: %!ipO", (duk_heaphdr *) env));
71944 #ifdef DUK_USE_DDDPRINT
71945 	{
71946 		duk_hobject *p = env;
71947 		while (p) {
71948 			DUK_DDD(DUK_DDDPRINT("  -> %!ipO", (duk_heaphdr *) p));
71949 			p = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, p);
71950 		}
71951 	}
71952 #endif
71953 
71954 	act->lex_env = env;
71955 	act->var_env = env;
71956 	DUK_HOBJECT_INCREF(thr, env);  /* XXX: incref by count (here 2 times) */
71957 	DUK_HOBJECT_INCREF(thr, env);
71958 
71959 	duk_pop(ctx);
71960 }
71961 
71962 /*
71963  *  Closing environment records.
71964  *
71965  *  The environment record MUST be closed with the thread where its activation
71966  *  is.  In other words (if 'env' is open):
71967  *
71968  *    - 'thr' must match _env.thread
71969  *    - 'func' must match _env.callee
71970  *    - 'regbase' must match _env.regbase
71971  *
71972  *  These are not looked up from the env to minimize code size.
71973  *
71974  *  XXX: should access the own properties directly instead of using the API
71975  */
71976 
71977 DUK_INTERNAL void duk_js_close_environment_record(duk_hthread *thr, duk_hobject *env, duk_hobject *func, duk_size_t regbase) {
71978 	duk_context *ctx = (duk_context *) thr;
71979 	duk_uint_fast32_t i;
71980 
71981 	DUK_ASSERT(thr != NULL);
71982 	DUK_ASSERT(env != NULL);
71983 	/* func is NULL for lightfuncs */
71984 
71985 	if (!DUK_HOBJECT_IS_DECENV(env) || DUK_HOBJECT_HAS_ENVRECCLOSED(env)) {
71986 		DUK_DDD(DUK_DDDPRINT("environment record not a declarative record, "
71987 		                     "or already closed: %!iO",
71988 		                     (duk_heaphdr *) env));
71989 		return;
71990 	}
71991 
71992 	DUK_DDD(DUK_DDDPRINT("closing environment record: %!iO, func: %!iO, regbase: %ld",
71993 	                     (duk_heaphdr *) env, (duk_heaphdr *) func, (long) regbase));
71994 
71995 	duk_push_hobject(ctx, env);
71996 
71997 	/* assertions: env must be closed in the same thread as where it runs */
71998 #ifdef DUK_USE_ASSERTIONS
71999 	{
72000 		/* [... env] */
72001 
72002 		if (duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_CALLEE)) {
72003 			DUK_ASSERT(duk_is_object(ctx, -1));
72004 			DUK_ASSERT(duk_get_hobject(ctx, -1) == (duk_hobject *) func);
72005 		}
72006 		duk_pop(ctx);
72007 
72008 		if (duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_THREAD)) {
72009 			DUK_ASSERT(duk_is_object(ctx, -1));
72010 			DUK_ASSERT(duk_get_hobject(ctx, -1) == (duk_hobject *) thr);
72011 		}
72012 		duk_pop(ctx);
72013 
72014 		if (duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_REGBASE)) {
72015 			DUK_ASSERT(duk_is_number(ctx, -1));
72016 			DUK_ASSERT(duk_get_number(ctx, -1) == (double) regbase);
72017 		}
72018 		duk_pop(ctx);
72019 
72020 		/* [... env] */
72021 	}
72022 #endif
72023 
72024 	if (func != NULL && DUK_HOBJECT_IS_COMPILEDFUNCTION(func)) {
72025 		duk_hobject *varmap;
72026 		duk_hstring *key;
72027 		duk_tval *tv;
72028 		duk_uint_t regnum;
72029 
72030 		/* XXX: additional conditions when to close variables? we don't want to do it
72031 		 * unless the environment may have "escaped" (referenced in a function closure).
72032 		 * With delayed environments, the existence is probably good enough of a check.
72033 		 */
72034 
72035 		/* XXX: any way to detect faster whether something needs to be closed?
72036 		 * We now look up _Callee and then skip the rest.
72037 		 */
72038 
72039 		/* Note: we rely on the _Varmap having a bunch of nice properties, like:
72040 		 *  - being compacted and unmodified during this process
72041 		 *  - not containing an array part
72042 		 *  - having correct value types
72043 		 */
72044 
72045 		/* [... env] */
72046 
72047 		if (!duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_CALLEE)) {
72048 			DUK_DDD(DUK_DDDPRINT("env has no callee property, nothing to close; re-delete the control properties just in case"));
72049 			duk_pop(ctx);
72050 			goto skip_varmap;
72051 		}
72052 
72053 		/* [... env callee] */
72054 
72055 		if (!duk_get_prop_stridx(ctx, -1, DUK_STRIDX_INT_VARMAP)) {
72056 			DUK_DDD(DUK_DDDPRINT("callee has no varmap property, nothing to close; delete the control properties"));
72057 			duk_pop_2(ctx);
72058 			goto skip_varmap;
72059 		}
72060 		varmap = duk_require_hobject(ctx, -1);
72061 		DUK_ASSERT(varmap != NULL);
72062 
72063 		DUK_DDD(DUK_DDDPRINT("varmap: %!O", (duk_heaphdr *) varmap));
72064 
72065 		/* [... env callee varmap] */
72066 
72067 		DUK_DDD(DUK_DDDPRINT("copying bound register values, %ld bound regs", (long) DUK_HOBJECT_GET_ENEXT(varmap)));
72068 
72069 		for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(varmap); i++) {
72070 			key = DUK_HOBJECT_E_GET_KEY(thr->heap, varmap, i);
72071 			DUK_ASSERT(key != NULL);   /* assume keys are compacted */
72072 
72073 			DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, varmap, i));  /* assume plain values */
72074 
72075 			tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, varmap, i);
72076 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));  /* assume value is a number */
72077 			regnum = (duk_uint_t) DUK_TVAL_GET_NUMBER(tv);
72078 			DUK_ASSERT_DISABLE(regnum >= 0);  /* unsigned */
72079 			DUK_ASSERT(regnum < ((duk_hcompiledfunction *) func)->nregs);  /* regnum is sane */
72080 			DUK_ASSERT(thr->valstack + regbase + regnum >= thr->valstack);
72081 			DUK_ASSERT(thr->valstack + regbase + regnum < thr->valstack_top);
72082 
72083 			/* XXX: slightly awkward */
72084 			duk_push_hstring(ctx, key);
72085 			duk_push_tval(ctx, thr->valstack + regbase + regnum);
72086 			DUK_DDD(DUK_DDDPRINT("closing identifier '%s' -> reg %ld, value %!T",
72087 			                     (const char *) duk_require_string(ctx, -2),
72088 			                     (long) regnum,
72089 			                     (duk_tval *) duk_get_tval(ctx, -1)));
72090 
72091 			/* [... env callee varmap key val] */
72092 
72093 			/* if property already exists, overwrites silently */
72094 			duk_xdef_prop(ctx, -5, DUK_PROPDESC_FLAGS_WE);  /* writable but not deletable */
72095 		}
72096 
72097 		duk_pop_2(ctx);
72098 
72099 		/* [... env] */
72100 	}
72101 
72102  skip_varmap:
72103 
72104 	/* [... env] */
72105 
72106 	duk_del_prop_stridx(ctx, -1, DUK_STRIDX_INT_CALLEE);
72107 	duk_del_prop_stridx(ctx, -1, DUK_STRIDX_INT_THREAD);
72108 	duk_del_prop_stridx(ctx, -1, DUK_STRIDX_INT_REGBASE);
72109 
72110 	duk_pop(ctx);
72111 
72112 	DUK_HOBJECT_SET_ENVRECCLOSED(env);
72113 
72114 	DUK_DDD(DUK_DDDPRINT("environment record after being closed: %!O",
72115 	                     (duk_heaphdr *) env));
72116 }
72117 
72118 /*
72119  *  GETIDREF: a GetIdentifierReference-like helper.
72120  *
72121  *  Provides a parent traversing lookup and a single level lookup
72122  *  (for HasBinding).
72123  *
72124  *  Instead of returning the value, returns a bunch of values allowing
72125  *  the caller to read, write, or delete the binding.  Value pointers
72126  *  are duk_tval pointers which can be mutated directly as long as
72127  *  refcounts are properly updated.  Note that any operation which may
72128  *  reallocate valstacks or compact objects may invalidate the returned
72129  *  duk_tval (but not object) pointers, so caller must be very careful.
72130  *
72131  *  If starting environment record 'env' is given, 'act' is ignored.
72132  *  However, if 'env' is NULL, the caller may identify, in 'act', an
72133  *  activation which hasn't had its declarative environment initialized
72134  *  yet.  The activation registers are then looked up, and its parent
72135  *  traversed normally.
72136  *
72137  *  The 'out' structure values are only valid if the function returns
72138  *  success (non-zero).
72139  */
72140 
72141 /* lookup name from an open declarative record's registers */
72142 DUK_LOCAL
72143 duk_bool_t duk__getid_open_decl_env_regs(duk_hthread *thr,
72144                                          duk_hstring *name,
72145                                          duk_hobject *env,
72146                                          duk__id_lookup_result *out) {
72147 	duk_hthread *env_thr;
72148 	duk_hobject *env_func;
72149 	duk_size_t env_regbase;
72150 	duk_hobject *varmap;
72151 	duk_tval *tv;
72152 	duk_size_t reg_rel;
72153 	duk_size_t idx;
72154 
72155 	DUK_ASSERT(thr != NULL);
72156 	DUK_ASSERT(name != NULL);
72157 	DUK_ASSERT(env != NULL);
72158 	DUK_ASSERT(out != NULL);
72159 
72160 	DUK_ASSERT(DUK_HOBJECT_IS_DECENV(env));
72161 
72162 	tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, env, DUK_HTHREAD_STRING_INT_CALLEE(thr));
72163 	if (!tv) {
72164 		/* env is closed, should be missing _Callee, _Thread, _Regbase */
72165 		DUK_ASSERT(duk_hobject_find_existing_entry_tval_ptr(thr->heap, env, DUK_HTHREAD_STRING_INT_CALLEE(thr)) == NULL);
72166 		DUK_ASSERT(duk_hobject_find_existing_entry_tval_ptr(thr->heap, env, DUK_HTHREAD_STRING_INT_THREAD(thr)) == NULL);
72167 		DUK_ASSERT(duk_hobject_find_existing_entry_tval_ptr(thr->heap, env, DUK_HTHREAD_STRING_INT_REGBASE(thr)) == NULL);
72168 		return 0;
72169 	}
72170 
72171 	DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv));
72172 	DUK_ASSERT(DUK_TVAL_GET_OBJECT(tv) != NULL);
72173 	DUK_ASSERT(DUK_HOBJECT_IS_COMPILEDFUNCTION(DUK_TVAL_GET_OBJECT(tv)));
72174 	env_func = DUK_TVAL_GET_OBJECT(tv);
72175 	DUK_ASSERT(env_func != NULL);
72176 
72177 	tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, env_func, DUK_HTHREAD_STRING_INT_VARMAP(thr));
72178 	if (!tv) {
72179 		return 0;
72180 	}
72181 	DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv));
72182 	varmap = DUK_TVAL_GET_OBJECT(tv);
72183 	DUK_ASSERT(varmap != NULL);
72184 
72185 	tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, varmap, name);
72186 	if (!tv) {
72187 		return 0;
72188 	}
72189 	DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
72190 	reg_rel = (duk_size_t) DUK_TVAL_GET_NUMBER(tv);
72191 	DUK_ASSERT_DISABLE(reg_rel >= 0);  /* unsigned */
72192 	DUK_ASSERT(reg_rel < ((duk_hcompiledfunction *) env_func)->nregs);
72193 
72194 	tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, env, DUK_HTHREAD_STRING_INT_THREAD(thr));
72195 	DUK_ASSERT(tv != NULL);
72196 	DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv));
72197 	DUK_ASSERT(DUK_TVAL_GET_OBJECT(tv) != NULL);
72198 	DUK_ASSERT(DUK_HOBJECT_IS_THREAD(DUK_TVAL_GET_OBJECT(tv)));
72199 	env_thr = (duk_hthread *) DUK_TVAL_GET_OBJECT(tv);
72200 	DUK_ASSERT(env_thr != NULL);
72201 
72202 	/* Note: env_thr != thr is quite possible and normal, so careful
72203 	 * with what thread is used for valstack lookup.
72204 	 */
72205 
72206 	tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, env, DUK_HTHREAD_STRING_INT_REGBASE(thr));
72207 	DUK_ASSERT(tv != NULL);
72208 	DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
72209 	env_regbase = (duk_size_t) DUK_TVAL_GET_NUMBER(tv);
72210 
72211 	idx = env_regbase + reg_rel;
72212 	tv = env_thr->valstack + idx;
72213 	DUK_ASSERT(tv >= env_thr->valstack && tv < env_thr->valstack_end);  /* XXX: more accurate? */
72214 
72215 	out->value = tv;
72216 	out->attrs = DUK_PROPDESC_FLAGS_W;  /* registers are mutable, non-deletable */
72217 	out->this_binding = NULL;  /* implicit this value always undefined for
72218 	                            * declarative environment records.
72219 	                            */
72220 	out->env = env;
72221 	out->holder = NULL;
72222 
72223 	return 1;
72224 }
72225 
72226 /* lookup name from current activation record's functions' registers */
72227 DUK_LOCAL
72228 duk_bool_t duk__getid_activation_regs(duk_hthread *thr,
72229                                       duk_hstring *name,
72230                                       duk_activation *act,
72231                                       duk__id_lookup_result *out) {
72232 	duk_tval *tv;
72233 	duk_hobject *func;
72234 	duk_hobject *varmap;
72235 	duk_size_t reg_rel;
72236 	duk_size_t idx;
72237 
72238 	DUK_ASSERT(thr != NULL);
72239 	DUK_ASSERT(name != NULL);
72240 	DUK_ASSERT(act != NULL);
72241 	DUK_ASSERT(out != NULL);
72242 
72243 	func = DUK_ACT_GET_FUNC(act);
72244 	DUK_ASSERT(func != NULL);
72245 	DUK_ASSERT(DUK_HOBJECT_HAS_NEWENV(func));
72246 
72247 	if (!DUK_HOBJECT_IS_COMPILEDFUNCTION(func)) {
72248 		return 0;
72249 	}
72250 
72251 	tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, func, DUK_HTHREAD_STRING_INT_VARMAP(thr));
72252 	if (!tv) {
72253 		return 0;
72254 	}
72255 	DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv));
72256 	varmap = DUK_TVAL_GET_OBJECT(tv);
72257 	DUK_ASSERT(varmap != NULL);
72258 
72259 	tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, varmap, name);
72260 	if (!tv) {
72261 		return 0;
72262 	}
72263 	DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
72264 	reg_rel = (duk_size_t) DUK_TVAL_GET_NUMBER(tv);
72265 	DUK_ASSERT_DISABLE(reg_rel >= 0);
72266 	DUK_ASSERT(reg_rel < ((duk_hcompiledfunction *) func)->nregs);
72267 
72268 	idx = act->idx_bottom + reg_rel;
72269 	DUK_ASSERT(idx >= act->idx_bottom);
72270 	tv = thr->valstack + idx;
72271 
72272 	out->value = tv;
72273 	out->attrs = DUK_PROPDESC_FLAGS_W;  /* registers are mutable, non-deletable */
72274 	out->this_binding = NULL;  /* implicit this value always undefined for
72275 	                            * declarative environment records.
72276 	                            */
72277 	out->env = NULL;
72278 	out->holder = NULL;
72279 
72280 	return 1;
72281 }
72282 
72283 DUK_LOCAL
72284 duk_bool_t duk__get_identifier_reference(duk_hthread *thr,
72285                                          duk_hobject *env,
72286                                          duk_hstring *name,
72287                                          duk_activation *act,
72288                                          duk_bool_t parents,
72289                                          duk__id_lookup_result *out) {
72290 	duk_tval *tv;
72291 	duk_tval *tv_target;
72292 	duk_tval tv_name;
72293 	duk_uint_t sanity;
72294 
72295 	DUK_ASSERT(thr != NULL);
72296 	DUK_ASSERT(env != NULL || act != NULL);
72297 	DUK_ASSERT(name != NULL);
72298 	DUK_ASSERT(out != NULL);
72299 
72300 	DUK_ASSERT(!env || DUK_HOBJECT_IS_ENV(env));
72301 	DUK_ASSERT(!env || !DUK_HOBJECT_HAS_ARRAY_PART(env));
72302 
72303 	/*
72304 	 *  Conceptually, we look for the identifier binding by starting from
72305 	 *  'env' and following to chain of environment records (represented
72306 	 *  by the prototype chain).
72307 	 *
72308 	 *  If 'env' is NULL, the current activation does not yet have an
72309 	 *  allocated declarative environment record; this should be treated
72310 	 *  exactly as if the environment record existed but had no bindings
72311 	 *  other than register bindings.
72312 	 *
72313 	 *  Note: we assume that with the DUK_HOBJECT_FLAG_NEWENV cleared
72314 	 *  the environment will always be initialized immediately; hence
72315 	 *  a NULL 'env' should only happen with the flag set.  This is the
72316 	 *  case for: (1) function calls, and (2) strict, direct eval calls.
72317 	 */
72318 
72319 	if (env == NULL && act != NULL) {
72320 		duk_hobject *func;
72321 
72322 		DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference: env is NULL, activation is non-NULL -> "
72323 		                     "delayed env case, look up activation regs first"));
72324 
72325 		/*
72326 		 *  Try registers
72327 		 */
72328 
72329 		if (duk__getid_activation_regs(thr, name, act, out)) {
72330 			DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference successful: "
72331 			                     "name=%!O -> value=%!T, attrs=%ld, this=%!T, env=%!O, holder=%!O "
72332 			                     "(found from register bindings when env=NULL)",
72333 			                     (duk_heaphdr *) name, (duk_tval *) out->value,
72334 			                     (long) out->attrs, (duk_tval *) out->this_binding,
72335 			                     (duk_heaphdr *) out->env, (duk_heaphdr *) out->holder));
72336 			return 1;
72337 		}
72338 
72339 		DUK_DDD(DUK_DDDPRINT("not found in current activation regs"));
72340 
72341 		/*
72342 		 *  Not found in registers, proceed to the parent record.
72343 		 *  Here we need to determine what the parent would be,
72344 		 *  if 'env' was not NULL (i.e. same logic as when initializing
72345 		 *  the record).
72346 		 *
72347 		 *  Note that environment initialization is only deferred when
72348 		 *  DUK_HOBJECT_HAS_NEWENV is set, and this only happens for:
72349 		 *    - Function code
72350 		 *    - Strict eval code
72351 		 *
72352 		 *  We only need to check _Lexenv here; _Varenv exists only if it
72353 		 *  differs from _Lexenv (and thus _Lexenv will also be present).
72354 		 */
72355 
72356 		if (!parents) {
72357 			DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference failed, no parent traversal "
72358 			                     "(not found from register bindings when env=NULL)"));
72359 			goto fail_not_found;
72360 		}
72361 
72362 		func = DUK_ACT_GET_FUNC(act);
72363 		DUK_ASSERT(func != NULL);
72364 		DUK_ASSERT(DUK_HOBJECT_HAS_NEWENV(func));
72365 
72366 		tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, func, DUK_HTHREAD_STRING_INT_LEXENV(thr));
72367 		if (tv) {
72368 			DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv));
72369 			env = DUK_TVAL_GET_OBJECT(tv);
72370 		} else {
72371 			DUK_ASSERT(duk_hobject_find_existing_entry_tval_ptr(thr->heap, func, DUK_HTHREAD_STRING_INT_VARENV(thr)) == NULL);
72372 			env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
72373 		}
72374 
72375 		DUK_DDD(DUK_DDDPRINT("continue lookup from env: %!iO",
72376 		                     (duk_heaphdr *) env));
72377 	}
72378 
72379 	/*
72380 	 *  Prototype walking starting from 'env'.
72381 	 *
72382 	 *  ('act' is not needed anywhere here.)
72383 	 */
72384 
72385 	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
72386 	while (env != NULL) {
72387 		duk_small_int_t cl;
72388 		duk_int_t attrs;
72389 
72390 		DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference, name=%!O, considering env=%p -> %!iO",
72391 		                     (duk_heaphdr *) name,
72392 		                     (void *) env,
72393 		                     (duk_heaphdr *) env));
72394 
72395 		DUK_ASSERT(env != NULL);
72396 		DUK_ASSERT(DUK_HOBJECT_IS_ENV(env));
72397 		DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(env));
72398 
72399 		cl = DUK_HOBJECT_GET_CLASS_NUMBER(env);
72400 		DUK_ASSERT(cl == DUK_HOBJECT_CLASS_OBJENV || cl == DUK_HOBJECT_CLASS_DECENV);
72401 		if (cl == DUK_HOBJECT_CLASS_DECENV) {
72402 			/*
72403 			 *  Declarative environment record.
72404 			 *
72405 			 *  Identifiers can never be stored in ancestors and are
72406 			 *  always plain values, so we can use an internal helper
72407 			 *  and access the value directly with an duk_tval ptr.
72408 			 *
72409 			 *  A closed environment is only indicated by it missing
72410 			 *  the "book-keeping" properties required for accessing
72411 			 *  register-bound variables.
72412 			 */
72413 
72414 			if (DUK_HOBJECT_HAS_ENVRECCLOSED(env)) {
72415 				/* already closed */
72416 				goto skip_regs;
72417 			}
72418 
72419 			if (duk__getid_open_decl_env_regs(thr, name, env, out)) {
72420 				DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference successful: "
72421 				                     "name=%!O -> value=%!T, attrs=%ld, this=%!T, env=%!O, holder=%!O "
72422 				                     "(declarative environment record, scope open, found in regs)",
72423 				                     (duk_heaphdr *) name, (duk_tval *) out->value,
72424 				                     (long) out->attrs, (duk_tval *) out->this_binding,
72425 				                     (duk_heaphdr *) out->env, (duk_heaphdr *) out->holder));
72426 				return 1;
72427 			}
72428 		 skip_regs:
72429 
72430 			tv = duk_hobject_find_existing_entry_tval_ptr_and_attrs(thr->heap, env, name, &attrs);
72431 			if (tv) {
72432 				out->value = tv;
72433 				out->attrs = attrs;
72434 				out->this_binding = NULL;  /* implicit this value always undefined for
72435 				                            * declarative environment records.
72436 				                            */
72437 				out->env = env;
72438 				out->holder = env;
72439 
72440 				DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference successful: "
72441 				                     "name=%!O -> value=%!T, attrs=%ld, this=%!T, env=%!O, holder=%!O "
72442 				                     "(declarative environment record, found in properties)",
72443 				                     (duk_heaphdr *) name, (duk_tval *) out->value,
72444 				                     (long) out->attrs, (duk_tval *) out->this_binding,
72445 				                     (duk_heaphdr *) out->env, (duk_heaphdr *) out->holder));
72446 				return 1;
72447 			}
72448 		} else {
72449 			/*
72450 			 *  Object environment record.
72451 			 *
72452 			 *  Binding (target) object is an external, uncontrolled object.
72453 			 *  Identifier may be bound in an ancestor property, and may be
72454 			 *  an accessor.  Target can also be a Proxy which we must support
72455 			 *  here.
72456 			 */
72457 
72458 			/* XXX: we could save space by using _Target OR _This.  If _Target, assume
72459 			 * this binding is undefined.  If _This, assumes this binding is _This, and
72460 			 * target is also _This.  One property would then be enough.
72461 			 */
72462 
72463 			duk_hobject *target;
72464 			duk_bool_t found;
72465 
72466 			DUK_ASSERT(cl == DUK_HOBJECT_CLASS_OBJENV);
72467 
72468 			tv_target = duk_hobject_find_existing_entry_tval_ptr(thr->heap, env, DUK_HTHREAD_STRING_INT_TARGET(thr));
72469 			DUK_ASSERT(tv_target != NULL);
72470 			DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv_target));
72471 			target = DUK_TVAL_GET_OBJECT(tv_target);
72472 			DUK_ASSERT(target != NULL);
72473 
72474 			/* Target may be a Proxy or property may be an accessor, so we must
72475 			 * use an actual, Proxy-aware hasprop check here.
72476 			 *
72477 			 * out->holder is NOT set to the actual duk_hobject where the
72478 			 * property is found, but rather the object binding target object.
72479 			 */
72480 
72481 			if (DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(target)) {
72482 				DUK_ASSERT(name != NULL);
72483 				DUK_TVAL_SET_STRING(&tv_name, name);
72484 
72485 				found = duk_hobject_hasprop(thr, tv_target, &tv_name);
72486 			} else {
72487 				/* XXX: duk_hobject_hasprop() would be correct for
72488 				 * non-Proxy objects too, but it is about ~20-25%
72489 				 * slower at present so separate code paths for
72490 				 * Proxy and non-Proxy now.
72491 				 */
72492 				found = duk_hobject_hasprop_raw(thr, target, name);
72493 			}
72494 
72495 			if (found) {
72496 				out->value = NULL;  /* can't get value, may be accessor */
72497 				out->attrs = 0;     /* irrelevant when out->value == NULL */
72498 				tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, env, DUK_HTHREAD_STRING_INT_THIS(thr));
72499 				out->this_binding = tv;  /* may be NULL */
72500 				out->env = env;
72501 				out->holder = target;
72502 
72503 				DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference successful: "
72504 				                     "name=%!O -> value=%!T, attrs=%ld, this=%!T, env=%!O, holder=%!O "
72505 				                     "(object environment record)",
72506 				                     (duk_heaphdr *) name, (duk_tval *) out->value,
72507 				                     (long) out->attrs, (duk_tval *) out->this_binding,
72508 				                     (duk_heaphdr *) out->env, (duk_heaphdr *) out->holder));
72509 				return 1;
72510 			}
72511 		}
72512 
72513 		if (!parents) {
72514 			DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference failed, no parent traversal "
72515 			                     "(not found from first traversed env)"));
72516 			goto fail_not_found;
72517 		}
72518 
72519                 if (sanity-- == 0) {
72520                         DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
72521                 }
72522 		env = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, env);
72523 	};
72524 
72525 	/*
72526 	 *  Not found (even in global object)
72527 	 */
72528 
72529  fail_not_found:
72530 	return 0;
72531 }
72532 
72533 /*
72534  *  HASVAR: check identifier binding from a given environment record
72535  *  without traversing its parents.
72536  *
72537  *  This primitive is not exposed to user code as such, but is used
72538  *  internally for e.g. declaration binding instantiation.
72539  *
72540  *  See E5 Sections:
72541  *    10.2.1.1.1 HasBinding(N)
72542  *    10.2.1.2.1 HasBinding(N)
72543  *
72544  *  Note: strictness has no bearing on this check.  Hence we don't take
72545  *  a 'strict' parameter.
72546  */
72547 
72548 #if 0  /*unused*/
72549 DUK_INTERNAL
72550 duk_bool_t duk_js_hasvar_envrec(duk_hthread *thr,
72551                                 duk_hobject *env,
72552                                 duk_hstring *name) {
72553 	duk__id_lookup_result ref;
72554 	duk_bool_t parents;
72555 
72556 	DUK_DDD(DUK_DDDPRINT("hasvar: thr=%p, env=%p, name=%!O "
72557 	                     "(env -> %!dO)",
72558 	                     (void *) thr, (void *) env, (duk_heaphdr *) name,
72559 	                     (duk_heaphdr *) env));
72560 
72561 	DUK_ASSERT(thr != NULL);
72562 	DUK_ASSERT(env != NULL);
72563 	DUK_ASSERT(name != NULL);
72564 
72565         DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(env);
72566         DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(name);
72567 
72568 	DUK_ASSERT(DUK_HOBJECT_IS_ENV(env));
72569 	DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(env));
72570 
72571 	/* lookup results is ignored */
72572 	parents = 0;
72573 	return duk__get_identifier_reference(thr, env, name, NULL, parents, &ref);
72574 }
72575 #endif
72576 
72577 /*
72578  *  GETVAR
72579  *
72580  *  See E5 Sections:
72581  *    11.1.2 Identifier Reference
72582  *    10.3.1 Identifier Resolution
72583  *    11.13.1 Simple Assignment  [example of where the Reference is GetValue'd]
72584  *    8.7.1 GetValue (V)
72585  *    8.12.1 [[GetOwnProperty]] (P)
72586  *    8.12.2 [[GetProperty]] (P)
72587  *    8.12.3 [[Get]] (P)
72588  *
72589  *  If 'throw' is true, always leaves two values on top of stack: [val this].
72590  *
72591  *  If 'throw' is false, returns 0 if identifier cannot be resolved, and the
72592  *  stack will be unaffected in this case.  If identifier is resolved, returns
72593  *  1 and leaves [val this] on top of stack.
72594  *
72595  *  Note: the 'strict' flag of a reference returned by GetIdentifierReference
72596  *  is ignored by GetValue.  Hence we don't take a 'strict' parameter.
72597  *
72598  *  The 'throw' flag is needed for implementing 'typeof' for an unreferenced
72599  *  identifier.  An unreference identifier in other contexts generates a
72600  *  ReferenceError.
72601  */
72602 
72603 DUK_LOCAL
72604 duk_bool_t duk__getvar_helper(duk_hthread *thr,
72605                               duk_hobject *env,
72606                               duk_activation *act,
72607                               duk_hstring *name,
72608                               duk_bool_t throw_flag) {
72609 	duk_context *ctx = (duk_context *) thr;
72610 	duk__id_lookup_result ref;
72611 	duk_tval tv_tmp_obj;
72612 	duk_tval tv_tmp_key;
72613 	duk_bool_t parents;
72614 
72615 	DUK_DDD(DUK_DDDPRINT("getvar: thr=%p, env=%p, act=%p, name=%!O "
72616 	                     "(env -> %!dO)",
72617 	                     (void *) thr, (void *) env, (void *) act,
72618 	                     (duk_heaphdr *) name, (duk_heaphdr *) env));
72619 
72620 	DUK_ASSERT(thr != NULL);
72621 	DUK_ASSERT(name != NULL);
72622 	/* env and act may be NULL */
72623 
72624         DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(env);
72625         DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(name);
72626 
72627 	parents = 1;     /* follow parent chain */
72628 	if (duk__get_identifier_reference(thr, env, name, act, parents, &ref)) {
72629 		if (ref.value) {
72630 			DUK_ASSERT(ref.this_binding == NULL);  /* always for register bindings */
72631 			duk_push_tval(ctx, ref.value);
72632 			duk_push_undefined(ctx);
72633 		} else {
72634 			DUK_ASSERT(ref.holder != NULL);
72635 
72636 			/* Note: getprop may invoke any getter and invalidate any
72637 			 * duk_tval pointers, so this must be done first.
72638 			 */
72639 
72640 			if (ref.this_binding) {
72641 				duk_push_tval(ctx, ref.this_binding);
72642 			} else {
72643 				duk_push_undefined(ctx);
72644 			}
72645 
72646 			DUK_TVAL_SET_OBJECT(&tv_tmp_obj, ref.holder);
72647 			DUK_TVAL_SET_STRING(&tv_tmp_key, name);
72648 			(void) duk_hobject_getprop(thr, &tv_tmp_obj, &tv_tmp_key);  /* [this value] */
72649 
72650 			/* ref.value, ref.this.binding invalidated here by getprop call */
72651 
72652 			duk_insert(ctx, -2);  /* [this value] -> [value this] */
72653 		}
72654 
72655 		return 1;
72656 	} else {
72657 		if (throw_flag) {
72658 			DUK_ERROR_FMT1(thr, DUK_ERR_REFERENCE_ERROR,
72659 			               "identifier '%s' undefined",
72660 			               (const char *) DUK_HSTRING_GET_DATA(name));
72661 		}
72662 
72663 		return 0;
72664 	}
72665 }
72666 
72667 DUK_INTERNAL
72668 duk_bool_t duk_js_getvar_envrec(duk_hthread *thr,
72669                                 duk_hobject *env,
72670                                 duk_hstring *name,
72671                                 duk_bool_t throw_flag) {
72672 	return duk__getvar_helper(thr, env, NULL, name, throw_flag);
72673 }
72674 
72675 DUK_INTERNAL
72676 duk_bool_t duk_js_getvar_activation(duk_hthread *thr,
72677                                     duk_activation *act,
72678                                     duk_hstring *name,
72679                                     duk_bool_t throw_flag) {
72680 	DUK_ASSERT(act != NULL);
72681 	return duk__getvar_helper(thr, act->lex_env, act, name, throw_flag);
72682 }
72683 
72684 /*
72685  *  PUTVAR
72686  *
72687  *  See E5 Sections:
72688  *    11.1.2 Identifier Reference
72689  *    10.3.1 Identifier Resolution
72690  *    11.13.1 Simple Assignment  [example of where the Reference is PutValue'd]
72691  *    8.7.2 PutValue (V,W)  [see especially step 3.b, undefined -> automatic global in non-strict mode]
72692  *    8.12.4 [[CanPut]] (P)
72693  *    8.12.5 [[Put]] (P)
72694  *
72695  *  Note: may invalidate any valstack (or object) duk_tval pointers because
72696  *  putting a value may reallocate any object or any valstack.  Caller beware.
72697  */
72698 
72699 DUK_LOCAL
72700 void duk__putvar_helper(duk_hthread *thr,
72701                         duk_hobject *env,
72702                         duk_activation *act,
72703                         duk_hstring *name,
72704                         duk_tval *val,
72705                         duk_bool_t strict) {
72706 	duk__id_lookup_result ref;
72707 	duk_tval tv_tmp_obj;
72708 	duk_tval tv_tmp_key;
72709 	duk_bool_t parents;
72710 
72711 	DUK_DDD(DUK_DDDPRINT("putvar: thr=%p, env=%p, act=%p, name=%!O, val=%p, strict=%ld "
72712 	                     "(env -> %!dO, val -> %!T)",
72713 	                     (void *) thr, (void *) env, (void *) act,
72714 	                     (duk_heaphdr *) name, (void *) val, (long) strict,
72715 	                     (duk_heaphdr *) env, (duk_tval *) val));
72716 
72717 	DUK_ASSERT(thr != NULL);
72718 	DUK_ASSERT(name != NULL);
72719 	DUK_ASSERT(val != NULL);
72720 	/* env and act may be NULL */
72721 
72722         DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(env);
72723         DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(name);
72724 	DUK_ASSERT_REFCOUNT_NONZERO_TVAL(val);
72725 
72726 	/*
72727 	 *  In strict mode E5 protects 'eval' and 'arguments' from being
72728 	 *  assigned to (or even declared anywhere).  Attempt to do so
72729 	 *  should result in a compile time SyntaxError.  See the internal
72730 	 *  design documentation for details.
72731 	 *
72732 	 *  Thus, we should never come here, run-time, for strict code,
72733 	 *  and name 'eval' or 'arguments'.
72734 	 */
72735 
72736 	DUK_ASSERT(!strict ||
72737 	           (name != DUK_HTHREAD_STRING_EVAL(thr) &&
72738 	            name != DUK_HTHREAD_STRING_LC_ARGUMENTS(thr)));
72739 
72740 	/*
72741 	 *  Lookup variable and update in-place if found.
72742 	 */
72743 
72744 	parents = 1;     /* follow parent chain */
72745 
72746 	if (duk__get_identifier_reference(thr, env, name, act, parents, &ref)) {
72747 		if (ref.value && (ref.attrs & DUK_PROPDESC_FLAG_WRITABLE)) {
72748 			/* Update duk_tval in-place if pointer provided and the
72749 			 * property is writable.  If the property is not writable
72750 			 * (immutable binding), use duk_hobject_putprop() which
72751 			 * will respect mutability.
72752 			 */
72753 			duk_tval *tv_val;
72754 
72755 			DUK_ASSERT(ref.this_binding == NULL);  /* always for register bindings */
72756 
72757 			tv_val = ref.value;
72758 			DUK_ASSERT(tv_val != NULL);
72759 			DUK_TVAL_SET_TVAL_UPDREF(thr, tv_val, val);  /* side effects */
72760 
72761 			/* ref.value and ref.this_binding invalidated here */
72762 		} else {
72763 			DUK_ASSERT(ref.holder != NULL);
72764 
72765 			DUK_TVAL_SET_OBJECT(&tv_tmp_obj, ref.holder);
72766 			DUK_TVAL_SET_STRING(&tv_tmp_key, name);
72767 			(void) duk_hobject_putprop(thr, &tv_tmp_obj, &tv_tmp_key, val, strict);
72768 
72769 			/* ref.value and ref.this_binding invalidated here */
72770 		}
72771 
72772 		return;
72773 	}
72774 
72775 	/*
72776 	 *  Not found: write to global object (non-strict) or ReferenceError
72777 	 *  (strict); see E5 Section 8.7.2, step 3.
72778 	 */
72779 
72780 	if (strict) {
72781 		DUK_DDD(DUK_DDDPRINT("identifier binding not found, strict => reference error"));
72782 		DUK_ERROR(thr, DUK_ERR_REFERENCE_ERROR, "identifier not defined");
72783 	}
72784 
72785 	DUK_DDD(DUK_DDDPRINT("identifier binding not found, not strict => set to global"));
72786 
72787 	DUK_TVAL_SET_OBJECT(&tv_tmp_obj, thr->builtins[DUK_BIDX_GLOBAL]);
72788 	DUK_TVAL_SET_STRING(&tv_tmp_key, name);
72789 	(void) duk_hobject_putprop(thr, &tv_tmp_obj, &tv_tmp_key, val, 0);  /* 0 = no throw */
72790 
72791 	/* NB: 'val' may be invalidated here because put_value may realloc valstack,
72792 	 * caller beware.
72793 	 */
72794 }
72795 
72796 DUK_INTERNAL
72797 void duk_js_putvar_envrec(duk_hthread *thr,
72798                           duk_hobject *env,
72799                           duk_hstring *name,
72800                           duk_tval *val,
72801                           duk_bool_t strict) {
72802 	duk__putvar_helper(thr, env, NULL, name, val, strict);
72803 }
72804 
72805 DUK_INTERNAL
72806 void duk_js_putvar_activation(duk_hthread *thr,
72807                               duk_activation *act,
72808                               duk_hstring *name,
72809                               duk_tval *val,
72810                               duk_bool_t strict) {
72811 	DUK_ASSERT(act != NULL);
72812 	duk__putvar_helper(thr, act->lex_env, act, name, val, strict);
72813 }
72814 
72815 /*
72816  *  DELVAR
72817  *
72818  *  See E5 Sections:
72819  *    11.4.1 The delete operator
72820  *    10.2.1.1.5 DeleteBinding (N)  [declarative environment record]
72821  *    10.2.1.2.5 DeleteBinding (N)  [object environment record]
72822  *
72823  *  Variable bindings established inside eval() are deletable (configurable),
72824  *  other bindings are not, including variables declared in global level.
72825  *  Registers are always non-deletable, and the deletion of other bindings
72826  *  is controlled by the configurable flag.
72827  *
72828  *  For strict mode code, the 'delete' operator should fail with a compile
72829  *  time SyntaxError if applied to identifiers.  Hence, no strict mode
72830  *  run-time deletion of identifiers should ever happen.  This function
72831  *  should never be called from strict mode code!
72832  */
72833 
72834 DUK_LOCAL
72835 duk_bool_t duk__delvar_helper(duk_hthread *thr,
72836                               duk_hobject *env,
72837                               duk_activation *act,
72838                               duk_hstring *name) {
72839 	duk__id_lookup_result ref;
72840 	duk_bool_t parents;
72841 
72842 	DUK_DDD(DUK_DDDPRINT("delvar: thr=%p, env=%p, act=%p, name=%!O "
72843 	                     "(env -> %!dO)",
72844 	                     (void *) thr, (void *) env, (void *) act,
72845 	                     (duk_heaphdr *) name, (duk_heaphdr *) env));
72846 
72847 	DUK_ASSERT(thr != NULL);
72848 	DUK_ASSERT(name != NULL);
72849 	/* env and act may be NULL */
72850 
72851         DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(name);
72852 
72853 	parents = 1;     /* follow parent chain */
72854 
72855 	if (duk__get_identifier_reference(thr, env, name, act, parents, &ref)) {
72856 		if (ref.value && !(ref.attrs & DUK_PROPDESC_FLAG_CONFIGURABLE)) {
72857 			/* Identifier found in registers (always non-deletable)
72858 			 * or declarative environment record and non-configurable.
72859 			 */
72860 			return 0;
72861 		}
72862 		DUK_ASSERT(ref.holder != NULL);
72863 
72864 		return duk_hobject_delprop_raw(thr, ref.holder, name, 0);
72865 	}
72866 
72867 	/*
72868 	 *  Not found (even in global object).
72869 	 *
72870 	 *  In non-strict mode this is a silent SUCCESS (!), see E5 Section 11.4.1,
72871 	 *  step 3.b.  In strict mode this case is a compile time SyntaxError so
72872 	 *  we should not come here.
72873 	 */
72874 
72875 	DUK_DDD(DUK_DDDPRINT("identifier to be deleted not found: name=%!O "
72876 	                     "(treated as silent success)",
72877 	                     (duk_heaphdr *) name));
72878 	return 1;
72879 }
72880 
72881 #if 0  /*unused*/
72882 DUK_INTERNAL
72883 duk_bool_t duk_js_delvar_envrec(duk_hthread *thr,
72884                                 duk_hobject *env,
72885                                 duk_hstring *name) {
72886 	return duk__delvar_helper(thr, env, NULL, name);
72887 }
72888 #endif
72889 
72890 DUK_INTERNAL
72891 duk_bool_t duk_js_delvar_activation(duk_hthread *thr,
72892                                     duk_activation *act,
72893                                     duk_hstring *name) {
72894 	DUK_ASSERT(act != NULL);
72895 	return duk__delvar_helper(thr, act->lex_env, act, name);
72896 }
72897 
72898 /*
72899  *  DECLVAR
72900  *
72901  *  See E5 Sections:
72902  *    10.4.3 Entering Function Code
72903  *    10.5 Declaration Binding Instantion
72904  *    12.2 Variable Statement
72905  *    11.1.2 Identifier Reference
72906  *    10.3.1 Identifier Resolution
72907  *
72908  *  Variable declaration behavior is mainly discussed in Section 10.5,
72909  *  and is not discussed in the execution semantics (Sections 11-13).
72910  *
72911  *  Conceptually declarations happen when code (global, eval, function)
72912  *  is entered, before any user code is executed.  In practice, register-
72913  *  bound identifiers are 'declared' automatically (by virtue of being
72914  *  allocated to registers with the initial value 'undefined').  Other
72915  *  identifiers are declared in the function prologue with this primitive.
72916  *
72917  *  Since non-register bindings eventually back to an internal object's
72918  *  properties, the 'prop_flags' argument is used to specify binding
72919  *  type:
72920  *
72921  *    - Immutable binding: set DUK_PROPDESC_FLAG_WRITABLE to false
72922  *    - Non-deletable binding: set DUK_PROPDESC_FLAG_CONFIGURABLE to false
72923  *    - The flag DUK_PROPDESC_FLAG_ENUMERABLE should be set, although it
72924  *      doesn't really matter for internal objects
72925  *
72926  *  All bindings are non-deletable mutable bindings except:
72927  *
72928  *    - Declarations in eval code (mutable, deletable)
72929  *    - 'arguments' binding in strict function code (immutable)
72930  *    - Function name binding of a function expression (immutable)
72931  *
72932  *  Declarations may go to declarative environment records (always
72933  *  so for functions), but may also go to object environment records
72934  *  (e.g. global code).  The global object environment has special
72935  *  behavior when re-declaring a function (but not a variable); see
72936  *  E5.1 specification, Section 10.5, step 5.e.
72937  *
72938  *  Declarations always go to the 'top-most' environment record, i.e.
72939  *  we never check the record chain.  It's not an error even if a
72940  *  property (even an immutable or non-deletable one) of the same name
72941  *  already exists.
72942  *
72943  *  If a declared variable already exists, its value needs to be updated
72944  *  (if possible).  Returns 1 if a PUTVAR needs to be done by the caller;
72945  *  otherwise returns 0.
72946  */
72947 
72948 DUK_LOCAL
72949 duk_bool_t duk__declvar_helper(duk_hthread *thr,
72950                                duk_hobject *env,
72951                                duk_hstring *name,
72952                                duk_tval *val,
72953                                duk_small_int_t prop_flags,
72954                                duk_bool_t is_func_decl) {
72955 	duk_context *ctx = (duk_context *) thr;
72956 	duk_hobject *holder;
72957 	duk_bool_t parents;
72958 	duk__id_lookup_result ref;
72959 	duk_tval *tv;
72960 
72961 	DUK_DDD(DUK_DDDPRINT("declvar: thr=%p, env=%p, name=%!O, val=%!T, prop_flags=0x%08lx, is_func_decl=%ld "
72962 	                     "(env -> %!iO)",
72963 	                     (void *) thr, (void *) env, (duk_heaphdr *) name,
72964 	                     (duk_tval *) val, (unsigned long) prop_flags,
72965 	                     (unsigned int) is_func_decl, (duk_heaphdr *) env));
72966 
72967 	DUK_ASSERT(thr != NULL);
72968 	DUK_ASSERT(env != NULL);
72969 	DUK_ASSERT(name != NULL);
72970 	DUK_ASSERT(val != NULL);
72971 
72972 	/* Note: in strict mode the compiler should reject explicit
72973 	 * declaration of 'eval' or 'arguments'.  However, internal
72974 	 * bytecode may declare 'arguments' in the function prologue.
72975 	 * We don't bother checking (or asserting) for these now.
72976 	 */
72977 
72978 	/* Note: val is a stable duk_tval pointer.  The caller makes
72979 	 * a value copy into its stack frame, so 'tv_val' is not subject
72980 	 * to side effects here.
72981 	 */
72982 
72983 	/*
72984 	 *  Check whether already declared.
72985 	 *
72986 	 *  We need to check whether the binding exists in the environment
72987 	 *  without walking its parents.  However, we still need to check
72988 	 *  register-bound identifiers and the prototype chain of an object
72989 	 *  environment target object.
72990 	 */
72991 
72992 	parents = 0;  /* just check 'env' */
72993 	if (duk__get_identifier_reference(thr, env, name, NULL, parents, &ref)) {
72994 		duk_int_t e_idx;
72995 		duk_int_t h_idx;
72996 		duk_small_int_t flags;
72997 
72998 		/*
72999 		 *  Variable already declared, ignore re-declaration.
73000 		 *  The only exception is the updated behavior of E5.1 for
73001 		 *  global function declarations, E5.1 Section 10.5, step 5.e.
73002 		 *  This behavior does not apply to global variable declarations.
73003 		 */
73004 
73005 		if (!(is_func_decl && env == thr->builtins[DUK_BIDX_GLOBAL_ENV])) {
73006 			DUK_DDD(DUK_DDDPRINT("re-declare a binding, ignoring"));
73007 			return 1;  /* 1 -> needs a PUTVAR */
73008 		}
73009 
73010 		/*
73011 		 *  Special behavior in E5.1.
73012 		 *
73013 		 *  Note that even though parents == 0, the conflicting property
73014 		 *  may be an inherited property (currently our global object's
73015 		 *  prototype is Object.prototype).  Step 5.e first operates on
73016 		 *  the existing property (which is potentially in an ancestor)
73017 		 *  and then defines a new property in the global object (and
73018 		 *  never modifies the ancestor).
73019 		 *
73020 		 *  Also note that this logic would become even more complicated
73021 		 *  if the conflicting property might be a virtual one.  Object
73022 		 *  prototype has no virtual properties, though.
73023 		 *
73024 		 *  XXX: this is now very awkward, rework.
73025 		 */
73026 
73027 		DUK_DDD(DUK_DDDPRINT("re-declare a function binding in global object, "
73028 		                     "updated E5.1 processing"));
73029 
73030 		DUK_ASSERT(ref.holder != NULL);
73031 		holder = ref.holder;
73032 
73033 		/* holder will be set to the target object, not the actual object
73034 		 * where the property was found (see duk__get_identifier_reference()).
73035 		 */
73036 		DUK_ASSERT(DUK_HOBJECT_GET_CLASS_NUMBER(holder) == DUK_HOBJECT_CLASS_GLOBAL);
73037 		DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARRAY(holder));  /* global object doesn't have array part */
73038 
73039 		/* XXX: use a helper for prototype traversal; no loop check here */
73040 		/* must be found: was found earlier, and cannot be inherited */
73041 		for (;;) {
73042 			DUK_ASSERT(holder != NULL);
73043 			duk_hobject_find_existing_entry(thr->heap, holder, name, &e_idx, &h_idx);
73044 			if (e_idx >= 0) {
73045 				break;
73046 			}
73047 			/* SCANBUILD: NULL pointer dereference, doesn't actually trigger,
73048 			 * asserted above.
73049 			 */
73050 			holder = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, holder);
73051 		}
73052 		DUK_ASSERT(holder != NULL);
73053 		DUK_ASSERT(e_idx >= 0);
73054 		/* SCANBUILD: scan-build produces a NULL pointer dereference warning
73055 		 * below; it never actually triggers because holder is actually never
73056 		 * NULL.
73057 		 */
73058 
73059 		/* ref.holder is global object, holder is the object with the
73060 		 * conflicting property.
73061 		 */
73062 
73063 		flags = DUK_HOBJECT_E_GET_FLAGS(thr->heap, holder, e_idx);
73064 		if (!(flags & DUK_PROPDESC_FLAG_CONFIGURABLE)) {
73065 			if (flags & DUK_PROPDESC_FLAG_ACCESSOR) {
73066 				DUK_DDD(DUK_DDDPRINT("existing property is a non-configurable "
73067 				                     "accessor -> reject"));
73068 				goto fail_existing_attributes;
73069 			}
73070 			if (!((flags & DUK_PROPDESC_FLAG_WRITABLE) &&
73071 			      (flags & DUK_PROPDESC_FLAG_ENUMERABLE))) {
73072 				DUK_DDD(DUK_DDDPRINT("existing property is a non-configurable "
73073 				                     "plain property which is not writable and "
73074 				                     "enumerable -> reject"));
73075 				goto fail_existing_attributes;
73076 			}
73077 
73078 			DUK_DDD(DUK_DDDPRINT("existing property is not configurable but "
73079 			                     "is plain, enumerable, and writable -> "
73080 			                     "allow redeclaration"));
73081 		}
73082 
73083 		if (holder == ref.holder) {
73084 			/* XXX: if duk_hobject_define_property_internal() was updated
73085 			 * to handle a pre-existing accessor property, this would be
73086 			 * a simple call (like for the ancestor case).
73087 			 */
73088 			DUK_DDD(DUK_DDDPRINT("redefine, offending property in global object itself"));
73089 
73090 			if (flags & DUK_PROPDESC_FLAG_ACCESSOR) {
73091 				duk_hobject *tmp;
73092 
73093 				tmp = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, holder, e_idx);
73094 				DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, holder, e_idx, NULL);
73095 				DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);
73096 				DUK_UNREF(tmp);
73097 				tmp = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, holder, e_idx);
73098 				DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, holder, e_idx, NULL);
73099 				DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);
73100 				DUK_UNREF(tmp);
73101 			} else {
73102 				tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, holder, e_idx);
73103 				DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv);
73104 			}
73105 
73106 			/* Here val would be potentially invalid if we didn't make
73107 			 * a value copy at the caller.
73108 			 */
73109 
73110 			tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, holder, e_idx);
73111 			DUK_TVAL_SET_TVAL(tv, val);
73112 			DUK_TVAL_INCREF(thr, tv);
73113 			DUK_HOBJECT_E_SET_FLAGS(thr->heap, holder, e_idx, prop_flags);
73114 
73115 			DUK_DDD(DUK_DDDPRINT("updated global binding, final result: "
73116 			                     "value -> %!T, prop_flags=0x%08lx",
73117 			                     (duk_tval *) DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, holder, e_idx),
73118 			                     (unsigned long) prop_flags));
73119 		} else {
73120 			DUK_DDD(DUK_DDDPRINT("redefine, offending property in ancestor"));
73121 
73122 			DUK_ASSERT(ref.holder == thr->builtins[DUK_BIDX_GLOBAL]);
73123 			duk_push_tval(ctx, val);
73124 			duk_hobject_define_property_internal(thr, ref.holder, name, prop_flags);
73125 		}
73126 
73127 		return 0;
73128 	}
73129 
73130 	/*
73131 	 *  Not found (in registers or record objects).  Declare
73132 	 *  to current variable environment.
73133 	 */
73134 
73135 	/*
73136 	 *  Get holder object
73137 	 */
73138 
73139 	if (DUK_HOBJECT_IS_DECENV(env)) {
73140 		holder = env;
73141 	} else {
73142 		DUK_ASSERT(DUK_HOBJECT_IS_OBJENV(env));
73143 
73144 		tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, env, DUK_HTHREAD_STRING_INT_TARGET(thr));
73145 		DUK_ASSERT(tv != NULL);
73146 		DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv));
73147 		holder = DUK_TVAL_GET_OBJECT(tv);
73148 		DUK_ASSERT(holder != NULL);
73149 	}
73150 
73151 	/*
73152 	 *  Define new property
73153 	 *
73154 	 *  Note: this may fail if the holder is not extensible.
73155 	 */
73156 
73157 	/* XXX: this is awkward as we use an internal method which doesn't handle
73158 	 * extensibility etc correctly.  Basically we'd want to do a [[DefineOwnProperty]]
73159 	 * or Object.defineProperty() here.
73160 	 */
73161 
73162 	if (!DUK_HOBJECT_HAS_EXTENSIBLE(holder)) {
73163 		goto fail_not_extensible;
73164 	}
73165 
73166 	duk_push_hobject(ctx, holder);
73167 	duk_push_hstring(ctx, name);
73168 	duk_push_tval(ctx, val);
73169 	duk_xdef_prop(ctx, -3, prop_flags);  /* [holder name val] -> [holder] */
73170 	duk_pop(ctx);
73171 
73172 	return 0;
73173 
73174  fail_existing_attributes:
73175  fail_not_extensible:
73176 	DUK_ERROR_TYPE(thr, "declaration failed");
73177 	return 0;
73178 }
73179 
73180 DUK_INTERNAL
73181 duk_bool_t duk_js_declvar_activation(duk_hthread *thr,
73182                                      duk_activation *act,
73183                                      duk_hstring *name,
73184                                      duk_tval *val,
73185                                      duk_small_int_t prop_flags,
73186                                      duk_bool_t is_func_decl) {
73187 	duk_hobject *env;
73188 	duk_tval tv_val_copy;
73189 	duk_size_t act_off;
73190 
73191 	DUK_ASSERT(act != NULL);
73192 	act_off = (duk_size_t) ((duk_uint8_t *) act - (duk_uint8_t *) thr->callstack);
73193 
73194 	/*
73195 	 *  Make a value copy of the input val.  This ensures that
73196 	 *  side effects cannot invalidate the pointer.
73197 	 */
73198 
73199 	DUK_TVAL_SET_TVAL(&tv_val_copy, val);
73200 	val = &tv_val_copy;
73201 
73202 	/*
73203 	 *  Delayed env creation check
73204 	 */
73205 
73206 	if (!act->var_env) {
73207 		DUK_ASSERT(act->lex_env == NULL);
73208 		duk_js_init_activation_environment_records_delayed(thr, act);
73209 		act = (duk_activation *) ((duk_uint8_t *) thr->callstack + act_off);
73210 	}
73211 	DUK_ASSERT(act->lex_env != NULL);
73212 	DUK_ASSERT(act->var_env != NULL);
73213 
73214 	env = act->var_env;
73215 	DUK_ASSERT(env != NULL);
73216 	DUK_ASSERT(DUK_HOBJECT_IS_ENV(env));
73217 
73218 	return duk__declvar_helper(thr, env, name, val, prop_flags, is_func_decl);
73219 }
73220 /*
73221  *  Lexer for source files, ToNumber() string conversions, RegExp expressions,
73222  *  and JSON.
73223  *
73224  *  Provides a stream of Ecmascript tokens from an UTF-8/CESU-8 buffer.  The
73225  *  caller can also rewind the token stream into a certain position which is
73226  *  needed by the compiler part for multi-pass scanning.  Tokens are
73227  *  represented as duk_token structures, and contain line number information.
73228  *  Token types are identified with DUK_TOK_* defines.
73229  *
73230  *  Characters are decoded into a fixed size lookup window consisting of
73231  *  decoded Unicode code points, with window positions past the end of the
73232  *  input filled with an invalid codepoint (-1).  The tokenizer can thus
73233  *  perform multiple character lookups efficiently and with few sanity
73234  *  checks (such as access outside the end of the input), which keeps the
73235  *  tokenization code small at the cost of performance.
73236  *
73237  *  Character data in tokens, such as identifier names and string literals,
73238  *  is encoded into CESU-8 format on-the-fly while parsing the token in
73239  *  question.  The string data is made reachable to garbage collection by
73240  *  placing the token-related values in value stack entries allocated for
73241  *  this purpose by the caller.  The characters exist in Unicode code point
73242  *  form only in the fixed size lookup window, which keeps character data
73243  *  expansion (of especially ASCII data) low.
73244  *
73245  *  Token parsing supports the full range of Unicode characters as described
73246  *  in the E5 specification.  Parsing has been optimized for ASCII characters
73247  *  because ordinary Ecmascript code consists almost entirely of ASCII
73248  *  characters.  Matching of complex Unicode codepoint sets (such as in the
73249  *  IdentifierStart and IdentifierPart productions) is optimized for size,
73250  *  and is done using a linear scan of a bit-packed list of ranges.  This is
73251  *  very slow, but should never be entered unless the source code actually
73252  *  contains Unicode characters.
73253  *
73254  *  Ecmascript tokenization is partially context sensitive.  First,
73255  *  additional future reserved words are recognized in strict mode (see E5
73256  *  Section 7.6.1.2).  Second, a forward slash character ('/') can be
73257  *  recognized either as starting a RegExp literal or as a division operator,
73258  *  depending on context.  The caller must provide necessary context flags
73259  *  when requesting a new token.
73260  *
73261  *  Future work:
73262  *
73263  *    * Make line number tracking optional, as it consumes space.
73264  *
73265  *    * Add a feature flag for disabling UTF-8 decoding of input, as most
73266  *      source code is ASCII.  Because of Unicode escapes written in ASCII,
73267  *      this does not allow Unicode support to be removed from e.g.
73268  *      duk_unicode_is_identifier_start() nor does it allow removal of CESU-8
73269  *      encoding of e.g. string literals.
73270  *
73271  *    * Add a feature flag for disabling Unicode compliance of e.g. identifier
73272  *      names.  This allows for a build more than a kilobyte smaller, because
73273  *      Unicode ranges needed by duk_unicode_is_identifier_start() and
73274  *      duk_unicode_is_identifier_part() can be dropped.  String literals
73275  *      should still be allowed to contain escaped Unicode, so this still does
73276  *      not allow removal of CESU-8 encoding of e.g. string literals.
73277  *
73278  *    * Character lookup tables for codepoints above BMP could be stripped.
73279  *
73280  *    * Strictly speaking, E5 specification requires that source code consists
73281  *      of 16-bit code units, and if not, must be conceptually converted to
73282  *      that format first.  The current lexer processes Unicode code points
73283  *      and allows characters outside the BMP.  These should be converted to
73284  *      surrogate pairs while reading the source characters into the window,
73285  *      not after tokens have been formed (as is done now).  However, the fix
73286  *      is not trivial because two characters are decoded from one codepoint.
73287  *
73288  *    * Optimize for speed as well as size.  Large if-else ladders are (at
73289  *      least potentially) slow.
73290  */
73291 
73292 /* include removed: duk_internal.h */
73293 
73294 /*
73295  *  Various defines and file specific helper macros
73296  */
73297 
73298 #define DUK__MAX_RE_DECESC_DIGITS     9
73299 #define DUK__MAX_RE_QUANT_DIGITS      9   /* Does not allow e.g. 2**31-1, but one more would allow overflows of u32. */
73300 
73301 /* whether to use macros or helper function depends on call count */
73302 #define DUK__ISDIGIT(x)          ((x) >= DUK_ASC_0 && (x) <= DUK_ASC_9)
73303 #define DUK__ISHEXDIGIT(x)       duk__is_hex_digit((x))
73304 #define DUK__ISOCTDIGIT(x)       ((x) >= DUK_ASC_0 && (x) <= DUK_ASC_7)
73305 #define DUK__ISDIGIT03(x)        ((x) >= DUK_ASC_0 && (x) <= DUK_ASC_3)
73306 #define DUK__ISDIGIT47(x)        ((x) >= DUK_ASC_4 && (x) <= DUK_ASC_7)
73307 
73308 /* lexer character window helpers */
73309 #define DUK__LOOKUP(lex_ctx,index)        ((lex_ctx)->window[(index)].codepoint)
73310 #define DUK__ADVANCECHARS(lex_ctx,count)  duk__advance_bytes((lex_ctx), (count) * sizeof(duk_lexer_codepoint))
73311 #define DUK__ADVANCEBYTES(lex_ctx,count)  duk__advance_bytes((lex_ctx), (count))
73312 #define DUK__INITBUFFER(lex_ctx)          duk__initbuffer((lex_ctx))
73313 #define DUK__APPENDBUFFER(lex_ctx,x)      duk__appendbuffer((lex_ctx), (duk_codepoint_t) (x))
73314 
73315 /* lookup shorthands (note: assume context variable is named 'lex_ctx') */
73316 #define DUK__L0()  DUK__LOOKUP(lex_ctx, 0)
73317 #define DUK__L1()  DUK__LOOKUP(lex_ctx, 1)
73318 #define DUK__L2()  DUK__LOOKUP(lex_ctx, 2)
73319 #define DUK__L3()  DUK__LOOKUP(lex_ctx, 3)
73320 #define DUK__L4()  DUK__LOOKUP(lex_ctx, 4)
73321 #define DUK__L5()  DUK__LOOKUP(lex_ctx, 5)
73322 
73323 /* packed advance/token number macro used by multiple functions */
73324 #define DUK__ADVTOK(advbytes,tok)  ((((advbytes) * sizeof(duk_lexer_codepoint)) << 8) + (tok))
73325 
73326 /*
73327  *  Advance lookup window by N characters, filling in new characters as
73328  *  necessary.  After returning caller is guaranteed a character window of
73329  *  at least DUK_LEXER_WINDOW_SIZE characters.
73330  *
73331  *  The main function duk__advance_bytes() is called at least once per every
73332  *  token so it has a major lexer/compiler performance impact.  There are two
73333  *  variants for the main duk__advance_bytes() algorithm: a sliding window
73334  *  approach which is slightly faster at the cost of larger code footprint,
73335  *  and a simple copying one.
73336  *
73337  *  Decoding directly from the source string would be another lexing option.
73338  *  But the lookup window based approach has the advantage of hiding the
73339  *  source string and its encoding effectively which gives more flexibility
73340  *  going forward to e.g. support chunked streaming of source from flash.
73341  *
73342  *  Decodes UTF-8/CESU-8 leniently with support for code points from U+0000 to
73343  *  U+10FFFF, causing an error if the input is unparseable.  Leniency means:
73344  *
73345  *    * Unicode code point validation is intentionally not performed,
73346  *      except to check that the codepoint does not exceed 0x10ffff.
73347  *
73348  *    * In particular, surrogate pairs are allowed and not combined, which
73349  *      allows source files to represent all SourceCharacters with CESU-8.
73350  *      Broken surrogate pairs are allowed, as Ecmascript does not mandate
73351  *      their validation.
73352  *
73353  *    * Allow non-shortest UTF-8 encodings.
73354  *
73355  *  Leniency here causes few security concerns because all character data is
73356  *  decoded into Unicode codepoints before lexer processing, and is then
73357  *  re-encoded into CESU-8.  The source can be parsed as strict UTF-8 with
73358  *  a compiler option.  However, Ecmascript source characters include -all-
73359  *  16-bit unsigned integer codepoints, so leniency seems to be appropriate.
73360  *
73361  *  Note that codepoints above the BMP are not strictly SourceCharacters,
73362  *  but the lexer still accepts them as such.  Before ending up in a string
73363  *  or an identifier name, codepoints above BMP are converted into surrogate
73364  *  pairs and then CESU-8 encoded, resulting in 16-bit Unicode data as
73365  *  expected by Ecmascript.
73366  *
73367  *  An alternative approach to dealing with invalid or partial sequences
73368  *  would be to skip them and replace them with e.g. the Unicode replacement
73369  *  character U+FFFD.  This has limited utility because a replacement character
73370  *  will most likely cause a parse error, unless it occurs inside a string.
73371  *  Further, Ecmascript source is typically pure ASCII.
73372  *
73373  *  See:
73374  *
73375  *     http://en.wikipedia.org/wiki/UTF-8
73376  *     http://en.wikipedia.org/wiki/CESU-8
73377  *     http://tools.ietf.org/html/rfc3629
73378  *     http://en.wikipedia.org/wiki/UTF-8#Invalid_byte_sequences
73379  *
73380  *  Future work:
73381  *
73382  *    * Reject other invalid Unicode sequences (see Wikipedia entry for examples)
73383  *      in strict UTF-8 mode.
73384  *
73385  *    * Size optimize.  An attempt to use a 16-byte lookup table for the first
73386  *      byte resulted in a code increase though.
73387  *
73388  *    * Is checking against maximum 0x10ffff really useful?  4-byte encoding
73389  *      imposes a certain limit anyway.
73390  *
73391  *    * Support chunked streaming of source code.  Can be implemented either
73392  *      by streaming chunks of bytes or chunks of codepoints.
73393  */
73394 
73395 #if defined(DUK_USE_LEXER_SLIDING_WINDOW)
73396 DUK_LOCAL void duk__fill_lexer_buffer(duk_lexer_ctx *lex_ctx, duk_small_uint_t start_offset_bytes) {
73397 	duk_lexer_codepoint *cp, *cp_end;
73398 	duk_ucodepoint_t x;
73399 	duk_small_uint_t contlen;
73400 	const duk_uint8_t *p, *p_end;
73401 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
73402 	duk_ucodepoint_t mincp;
73403 #endif
73404 	duk_int_t input_line;
73405 
73406 	/* Use temporaries and update lex_ctx only when finished. */
73407 	input_line = lex_ctx->input_line;
73408 	p = lex_ctx->input + lex_ctx->input_offset;
73409 	p_end = lex_ctx->input + lex_ctx->input_length;
73410 
73411 	cp = (duk_lexer_codepoint *) (void *) ((duk_uint8_t *) lex_ctx->buffer + start_offset_bytes);
73412 	cp_end = lex_ctx->buffer + DUK_LEXER_BUFFER_SIZE;
73413 
73414 	for (; cp != cp_end; cp++) {
73415 		cp->offset = (duk_size_t) (p - lex_ctx->input);
73416 		cp->line = input_line;
73417 
73418 		/* XXX: potential issue with signed pointers, p_end < p. */
73419 		if (DUK_UNLIKELY(p >= p_end)) {
73420 			/* If input_offset were assigned a negative value, it would
73421 			 * result in a large positive value.  Most likely it would be
73422 			 * larger than input_length and be caught here.  In any case
73423 			 * no memory unsafe behavior would happen.
73424 			 */
73425 			cp->codepoint = -1;
73426 			continue;
73427 		}
73428 
73429 		x = (duk_ucodepoint_t) (*p++);
73430 
73431 		/* Fast path. */
73432 
73433 		if (DUK_LIKELY(x < 0x80UL)) {
73434 			DUK_ASSERT(x != 0x2028UL && x != 0x2029UL);  /* not LS/PS */
73435 			if (DUK_UNLIKELY(x <= 0x000dUL)) {
73436 				if ((x == 0x000aUL) ||
73437 				    ((x == 0x000dUL) && (p >= p_end || *p != 0x000aUL))) {
73438 					/* lookup for 0x000a above assumes shortest encoding now */
73439 
73440 					/* E5 Section 7.3, treat the following as newlines:
73441 					 *   LF
73442 					 *   CR [not followed by LF]
73443 					 *   LS
73444 					 *   PS
73445 					 *
73446 					 * For CR LF, CR is ignored if it is followed by LF, and the LF will bump
73447 					 * the line number.
73448 					 */
73449 					input_line++;
73450 				}
73451 			}
73452 
73453 			cp->codepoint = (duk_codepoint_t) x;
73454 			continue;
73455 		}
73456 
73457 		/* Slow path. */
73458 
73459 		if (x < 0xc0UL) {
73460 			/* 10xx xxxx -> invalid */
73461 			goto error_encoding;
73462 		} else if (x < 0xe0UL) {
73463 			/* 110x xxxx   10xx xxxx  */
73464 			contlen = 1;
73465 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
73466 			mincp = 0x80UL;
73467 #endif
73468 			x = x & 0x1fUL;
73469 		} else if (x < 0xf0UL) {
73470 			/* 1110 xxxx   10xx xxxx   10xx xxxx */
73471 			contlen = 2;
73472 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
73473 			mincp = 0x800UL;
73474 #endif
73475 			x = x & 0x0fUL;
73476 		} else if (x < 0xf8UL) {
73477 			/* 1111 0xxx   10xx xxxx   10xx xxxx   10xx xxxx */
73478 			contlen = 3;
73479 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
73480 			mincp = 0x10000UL;
73481 #endif
73482 			x = x & 0x07UL;
73483 		} else {
73484 			/* no point in supporting encodings of 5 or more bytes */
73485 			goto error_encoding;
73486 		}
73487 
73488 		DUK_ASSERT(p_end >= p);
73489 		if ((duk_size_t) contlen > (duk_size_t) (p_end - p)) {
73490 			goto error_clipped;
73491 		}
73492 
73493 		while (contlen > 0) {
73494 			duk_small_uint_t y;
73495 			y = *p++;
73496 			if ((y & 0xc0U) != 0x80U) {
73497 				/* check that byte has the form 10xx xxxx */
73498 				goto error_encoding;
73499 			}
73500 			x = x << 6;
73501 			x += y & 0x3fUL;
73502 			contlen--;
73503 		}
73504 
73505 		/* check final character validity */
73506 
73507 		if (x > 0x10ffffUL) {
73508 			goto error_encoding;
73509 		}
73510 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
73511 		if (x < mincp || (x >= 0xd800UL && x <= 0xdfffUL) || x == 0xfffeUL) {
73512 			goto error_encoding;
73513 		}
73514 #endif
73515 
73516 		DUK_ASSERT(x != 0x000aUL && x != 0x000dUL);
73517 		if ((x == 0x2028UL) || (x == 0x2029UL)) {
73518 			input_line++;
73519 		}
73520 
73521 		cp->codepoint = (duk_codepoint_t) x;
73522 	}
73523 
73524 	lex_ctx->input_offset = (duk_size_t) (p - lex_ctx->input);
73525 	lex_ctx->input_line = input_line;
73526 	return;
73527 
73528  error_clipped:   /* clipped codepoint */
73529  error_encoding:  /* invalid codepoint encoding or codepoint */
73530 	lex_ctx->input_offset = (duk_size_t) (p - lex_ctx->input);
73531 	lex_ctx->input_line = input_line;
73532 
73533 	DUK_ERROR_SYNTAX(lex_ctx->thr, "utf-8 decode failed");
73534 }
73535 
73536 DUK_LOCAL void duk__advance_bytes(duk_lexer_ctx *lex_ctx, duk_small_uint_t count_bytes) {
73537 	duk_small_uint_t used_bytes, avail_bytes;
73538 
73539 	DUK_ASSERT_DISABLE(count_bytes >= 0);  /* unsigned */
73540 	DUK_ASSERT(count_bytes <= (duk_small_uint_t) (DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint)));
73541 	DUK_ASSERT(lex_ctx->window >= lex_ctx->buffer);
73542 	DUK_ASSERT(lex_ctx->window < lex_ctx->buffer + DUK_LEXER_BUFFER_SIZE);
73543 	DUK_ASSERT((duk_uint8_t *) lex_ctx->window + count_bytes <= (duk_uint8_t *) lex_ctx->buffer + DUK_LEXER_BUFFER_SIZE * sizeof(duk_lexer_codepoint));
73544 
73545 	/* Zero 'count' is also allowed to make call sites easier.
73546 	 * Arithmetic in bytes generates better code in GCC.
73547 	 */
73548 
73549 	lex_ctx->window = (duk_lexer_codepoint *) (void *) ((duk_uint8_t *) lex_ctx->window + count_bytes);  /* avoid multiply */
73550 	used_bytes = (duk_small_uint_t) ((duk_uint8_t *) lex_ctx->window - (duk_uint8_t *) lex_ctx->buffer);
73551 	avail_bytes = DUK_LEXER_BUFFER_SIZE * sizeof(duk_lexer_codepoint) - used_bytes;
73552 	if (avail_bytes < (duk_small_uint_t) (DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint))) {
73553 		/* Not enough data to provide a full window, so "scroll" window to
73554 		 * start of buffer and fill up the rest.
73555 		 */
73556 		DUK_MEMMOVE((void *) lex_ctx->buffer,
73557 		            (const void *) lex_ctx->window,
73558 		            (size_t) avail_bytes);
73559 		lex_ctx->window = lex_ctx->buffer;
73560 		duk__fill_lexer_buffer(lex_ctx, avail_bytes);
73561 	}
73562 }
73563 
73564 DUK_LOCAL void duk__init_lexer_window(duk_lexer_ctx *lex_ctx) {
73565 	lex_ctx->window = lex_ctx->buffer;
73566 	duk__fill_lexer_buffer(lex_ctx, 0);
73567 }
73568 #else  /* DUK_USE_LEXER_SLIDING_WINDOW */
73569 DUK_LOCAL duk_codepoint_t duk__read_char(duk_lexer_ctx *lex_ctx) {
73570 	duk_ucodepoint_t x;
73571 	duk_small_uint_t len;
73572 	duk_small_uint_t i;
73573 	const duk_uint8_t *p;
73574 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
73575 	duk_ucodepoint_t mincp;
73576 #endif
73577 	duk_size_t input_offset;
73578 
73579 	input_offset = lex_ctx->input_offset;
73580 	if (DUK_UNLIKELY(input_offset >= lex_ctx->input_length)) {
73581 		/* If input_offset were assigned a negative value, it would
73582 		 * result in a large positive value.  Most likely it would be
73583 		 * larger than input_length and be caught here.  In any case
73584 		 * no memory unsafe behavior would happen.
73585 		 */
73586 		return -1;
73587 	}
73588 
73589 	p = lex_ctx->input + input_offset;
73590 	x = (duk_ucodepoint_t) (*p);
73591 
73592 	if (DUK_LIKELY(x < 0x80UL)) {
73593 		/* 0xxx xxxx -> fast path */
73594 
73595 		/* input offset tracking */
73596 		lex_ctx->input_offset++;
73597 
73598 		DUK_ASSERT(x != 0x2028UL && x != 0x2029UL);  /* not LS/PS */
73599 		if (DUK_UNLIKELY(x <= 0x000dUL)) {
73600 			if ((x == 0x000aUL) ||
73601 			    ((x == 0x000dUL) && (lex_ctx->input_offset >= lex_ctx->input_length ||
73602 			                         lex_ctx->input[lex_ctx->input_offset] != 0x000aUL))) {
73603 				/* lookup for 0x000a above assumes shortest encoding now */
73604 
73605 				/* E5 Section 7.3, treat the following as newlines:
73606 				 *   LF
73607 				 *   CR [not followed by LF]
73608 				 *   LS
73609 				 *   PS
73610 				 *
73611 				 * For CR LF, CR is ignored if it is followed by LF, and the LF will bump
73612 				 * the line number.
73613 				 */
73614 				lex_ctx->input_line++;
73615 			}
73616 		}
73617 
73618 		return (duk_codepoint_t) x;
73619 	}
73620 
73621 	/* Slow path. */
73622 
73623 	if (x < 0xc0UL) {
73624 		/* 10xx xxxx -> invalid */
73625 		goto error_encoding;
73626 	} else if (x < 0xe0UL) {
73627 		/* 110x xxxx   10xx xxxx  */
73628 		len = 2;
73629 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
73630 		mincp = 0x80UL;
73631 #endif
73632 		x = x & 0x1fUL;
73633 	} else if (x < 0xf0UL) {
73634 		/* 1110 xxxx   10xx xxxx   10xx xxxx */
73635 		len = 3;
73636 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
73637 		mincp = 0x800UL;
73638 #endif
73639 		x = x & 0x0fUL;
73640 	} else if (x < 0xf8UL) {
73641 		/* 1111 0xxx   10xx xxxx   10xx xxxx   10xx xxxx */
73642 		len = 4;
73643 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
73644 		mincp = 0x10000UL;
73645 #endif
73646 		x = x & 0x07UL;
73647 	} else {
73648 		/* no point in supporting encodings of 5 or more bytes */
73649 		goto error_encoding;
73650 	}
73651 
73652 	DUK_ASSERT(lex_ctx->input_length >= lex_ctx->input_offset);
73653 	if ((duk_size_t) len > (duk_size_t) (lex_ctx->input_length - lex_ctx->input_offset)) {
73654 		goto error_clipped;
73655 	}
73656 
73657 	p++;
73658 	for (i = 1; i < len; i++) {
73659 		duk_small_uint_t y;
73660 		y = *p++;
73661 		if ((y & 0xc0U) != 0x80U) {
73662 			/* check that byte has the form 10xx xxxx */
73663 			goto error_encoding;
73664 		}
73665 		x = x << 6;
73666 		x += y & 0x3fUL;
73667 	}
73668 
73669 	/* check final character validity */
73670 
73671 	if (x > 0x10ffffUL) {
73672 		goto error_encoding;
73673 	}
73674 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
73675 	if (x < mincp || (x >= 0xd800UL && x <= 0xdfffUL) || x == 0xfffeUL) {
73676 		goto error_encoding;
73677 	}
73678 #endif
73679 
73680 	/* input offset tracking */
73681 	lex_ctx->input_offset += len;
73682 
73683 	/* line tracking */
73684 	DUK_ASSERT(x != 0x000aUL && x != 0x000dUL);
73685 	if ((x == 0x2028UL) || (x == 0x2029UL)) {
73686 		lex_ctx->input_line++;
73687 	}
73688 
73689 	return (duk_codepoint_t) x;
73690 
73691  error_clipped:   /* clipped codepoint */
73692  error_encoding:  /* invalid codepoint encoding or codepoint */
73693 	DUK_ERROR_SYNTAX(lex_ctx->thr, "utf-8 decode failed");
73694 	return 0;
73695 }
73696 
73697 DUK_LOCAL void duk__advance_bytes(duk_lexer_ctx *lex_ctx, duk_small_uint_t count_bytes) {
73698 	duk_small_uint_t keep_bytes;
73699 	duk_lexer_codepoint *cp, *cp_end;
73700 
73701 	DUK_ASSERT_DISABLE(count_bytes >= 0);  /* unsigned */
73702 	DUK_ASSERT(count_bytes <= (duk_small_uint_t) (DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint)));
73703 
73704 	/* Zero 'count' is also allowed to make call sites easier. */
73705 
73706 	keep_bytes = DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint) - count_bytes;
73707 	DUK_MEMMOVE((void *) lex_ctx->window,
73708 	            (const void *) ((duk_uint8_t *) lex_ctx->window + count_bytes),
73709 	            (size_t) keep_bytes);
73710 
73711 	cp = (duk_lexer_codepoint *) ((duk_uint8_t *) lex_ctx->window + keep_bytes);
73712 	cp_end = lex_ctx->window + DUK_LEXER_WINDOW_SIZE;
73713 	for (; cp != cp_end; cp++) {
73714 		cp->offset = lex_ctx->input_offset;
73715 		cp->line = lex_ctx->input_line;
73716 		cp->codepoint = duk__read_char(lex_ctx);
73717 	}
73718 }
73719 
73720 DUK_LOCAL void duk__init_lexer_window(duk_lexer_ctx *lex_ctx) {
73721 	/* Call with count == DUK_LEXER_WINDOW_SIZE to fill buffer initially. */
73722 	duk__advance_bytes(lex_ctx, DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint));  /* fill window */
73723 }
73724 #endif  /* DUK_USE_LEXER_SLIDING_WINDOW */
73725 
73726 /*
73727  *  (Re)initialize the temporary byte buffer.  May be called extra times
73728  *  with little impact.
73729  */
73730 
73731 DUK_LOCAL void duk__initbuffer(duk_lexer_ctx *lex_ctx) {
73732 	/* Reuse buffer as is unless buffer has grown large. */
73733 	if (DUK_HBUFFER_DYNAMIC_GET_SIZE(lex_ctx->buf) < DUK_LEXER_TEMP_BUF_LIMIT) {
73734 		/* Keep current size */
73735 	} else {
73736 		duk_hbuffer_resize(lex_ctx->thr, lex_ctx->buf, DUK_LEXER_TEMP_BUF_LIMIT);
73737 	}
73738 
73739 	DUK_BW_INIT_WITHBUF(lex_ctx->thr, &lex_ctx->bw, lex_ctx->buf);
73740 }
73741 
73742 /*
73743  *  Append a Unicode codepoint to the temporary byte buffer.  Performs
73744  *  CESU-8 surrogate pair encoding for codepoints above the BMP.
73745  *  Existing surrogate pairs are allowed and also encoded into CESU-8.
73746  */
73747 
73748 DUK_LOCAL void duk__appendbuffer(duk_lexer_ctx *lex_ctx, duk_codepoint_t x) {
73749 	/*
73750 	 *  Since character data is only generated by decoding the source or by
73751 	 *  the compiler itself, we rely on the input codepoints being correct
73752 	 *  and avoid a check here.
73753 	 *
73754 	 *  Character data can also come here through decoding of Unicode
73755 	 *  escapes ("\udead\ubeef") so all 16-but unsigned values can be
73756 	 *  present, even when the source file itself is strict UTF-8.
73757 	 */
73758 
73759 	DUK_ASSERT(x >= 0 && x <= 0x10ffff);
73760 
73761 	DUK_BW_WRITE_ENSURE_CESU8(lex_ctx->thr, &lex_ctx->bw, (duk_ucodepoint_t) x);
73762 }
73763 
73764 /*
73765  *  Intern the temporary byte buffer into a valstack slot
73766  *  (in practice, slot1 or slot2).
73767  */
73768 
73769 DUK_LOCAL void duk__internbuffer(duk_lexer_ctx *lex_ctx, duk_idx_t valstack_idx) {
73770 	duk_context *ctx = (duk_context *) lex_ctx->thr;
73771 
73772 	DUK_ASSERT(valstack_idx == lex_ctx->slot1_idx || valstack_idx == lex_ctx->slot2_idx);
73773 
73774 	DUK_BW_PUSH_AS_STRING(lex_ctx->thr, &lex_ctx->bw);
73775 	duk_replace(ctx, valstack_idx);
73776 }
73777 
73778 /*
73779  *  Init lexer context
73780  */
73781 
73782 DUK_INTERNAL void duk_lexer_initctx(duk_lexer_ctx *lex_ctx) {
73783 	DUK_ASSERT(lex_ctx != NULL);
73784 
73785 	DUK_MEMZERO(lex_ctx, sizeof(*lex_ctx));
73786 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
73787 #if defined(DUK_USE_LEXER_SLIDING_WINDOW)
73788 	lex_ctx->window = NULL;
73789 #endif
73790 	lex_ctx->thr = NULL;
73791 	lex_ctx->input = NULL;
73792 	lex_ctx->buf = NULL;
73793 #endif
73794 }
73795 
73796 /*
73797  *  Set lexer input position and reinitialize lookup window.
73798  */
73799 
73800 /* NB: duk_lexer_getpoint() is a macro only */
73801 
73802 DUK_INTERNAL void duk_lexer_setpoint(duk_lexer_ctx *lex_ctx, duk_lexer_point *pt) {
73803 	DUK_ASSERT_DISABLE(pt->offset >= 0);  /* unsigned */
73804 	DUK_ASSERT(pt->line >= 1);
73805 	lex_ctx->input_offset = pt->offset;
73806 	lex_ctx->input_line = pt->line;
73807 	duk__init_lexer_window(lex_ctx);
73808 }
73809 
73810 /*
73811  *  Lexing helpers
73812  */
73813 
73814 /* numeric value of a hex digit (also covers octal and decimal digits) */
73815 DUK_LOCAL duk_codepoint_t duk__hexval(duk_lexer_ctx *lex_ctx, duk_codepoint_t x) {
73816 	duk_small_int_t t;
73817 
73818 	/* Here 'x' is a Unicode codepoint */
73819 	if (DUK_LIKELY(x >= 0 && x <= 0xff)) {
73820 		t = duk_hex_dectab[x];
73821 		if (DUK_LIKELY(t >= 0)) {
73822 			return t;
73823 		}
73824 	}
73825 
73826 	/* Throwing an error this deep makes the error rather vague, but
73827 	 * saves hundreds of bytes of code.
73828 	 */
73829 	DUK_ERROR_SYNTAX(lex_ctx->thr, "decode error");
73830 	return 0;
73831 }
73832 
73833 /* having this as a separate function provided a size benefit */
73834 DUK_LOCAL duk_bool_t duk__is_hex_digit(duk_codepoint_t x) {
73835 	if (DUK_LIKELY(x >= 0 && x <= 0xff)) {
73836 		return (duk_hex_dectab[x] >= 0);
73837 	}
73838 	return 0;
73839 }
73840 
73841 DUK_LOCAL duk_codepoint_t duk__decode_hexesc_from_window(duk_lexer_ctx *lex_ctx, duk_small_int_t lookup_offset) {
73842 	/* validation performed by duk__hexval */
73843 	return (duk__hexval(lex_ctx, lex_ctx->window[lookup_offset].codepoint) << 4) |
73844 	       (duk__hexval(lex_ctx, lex_ctx->window[lookup_offset + 1].codepoint));
73845 }
73846 
73847 DUK_LOCAL duk_codepoint_t duk__decode_uniesc_from_window(duk_lexer_ctx *lex_ctx, duk_small_int_t lookup_offset) {
73848 	/* validation performed by duk__hexval */
73849 	return (duk__hexval(lex_ctx, lex_ctx->window[lookup_offset].codepoint) << 12) |
73850 	       (duk__hexval(lex_ctx, lex_ctx->window[lookup_offset + 1].codepoint) << 8) |
73851 	       (duk__hexval(lex_ctx, lex_ctx->window[lookup_offset + 2].codepoint) << 4) |
73852 	       (duk__hexval(lex_ctx, lex_ctx->window[lookup_offset + 3].codepoint));
73853 }
73854 
73855 /*
73856  *  Parse Ecmascript source InputElementDiv or InputElementRegExp
73857  *  (E5 Section 7), skipping whitespace, comments, and line terminators.
73858  *
73859  *  Possible results are:
73860  *    (1) a token
73861  *    (2) a line terminator (skipped)
73862  *    (3) a comment (skipped)
73863  *    (4) EOF
73864  *
73865  *  White space is automatically skipped from the current position (but
73866  *  not after the input element).  If input has already ended, returns
73867  *  DUK_TOK_EOF indefinitely.  If a parse error occurs, uses an DUK_ERROR()
73868  *  macro call (and hence a longjmp through current heap longjmp context).
73869  *  Comments and line terminator tokens are automatically skipped.
73870  *
73871  *  The input element being matched is determined by regexp_mode; if set,
73872  *  parses a InputElementRegExp, otherwise a InputElementDiv.  The
73873  *  difference between these are handling of productions starting with a
73874  *  forward slash.
73875  *
73876  *  If strict_mode is set, recognizes additional future reserved words
73877  *  specific to strict mode, and refuses to parse octal literals.
73878  *
73879  *  The matching strategy below is to (currently) use a six character
73880  *  lookup window to quickly determine which production is the -longest-
73881  *  matching one, and then parse that.  The top-level if-else clauses
73882  *  match the first character, and the code blocks for each clause
73883  *  handle -all- alternatives for that first character.  Ecmascript
73884  *  specification uses the "longest match wins" semantics, so the order
73885  *  of the if-clauses matters.
73886  *
73887  *  Misc notes:
73888  *
73889  *    * Ecmascript numeric literals do not accept a sign character.
73890  *      Consequently e.g. "-1.0" is parsed as two tokens: a negative
73891  *      sign and a positive numeric literal.  The compiler performs
73892  *      the negation during compilation, so this has no adverse impact.
73893  *
73894  *    * There is no token for "undefined": it is just a value available
73895  *      from the global object (or simply established by doing a reference
73896  *      to an undefined value).
73897  *
73898  *    * Some contexts want Identifier tokens, which are IdentifierNames
73899  *      excluding reserved words, while some contexts want IdentifierNames
73900  *      directly.  In the latter case e.g. "while" is interpreted as an
73901  *      identifier name, not a DUK_TOK_WHILE token.  The solution here is
73902  *      to provide both token types: DUK_TOK_WHILE goes to 't' while
73903  *      DUK_TOK_IDENTIFIER goes to 't_nores', and 'slot1' always contains
73904  *      the identifier / keyword name.
73905  *
73906  *    * Directive prologue needs to identify string literals such as
73907  *      "use strict" and 'use strict', which are sensitive to line
73908  *      continuations and escape sequences.  For instance, "use\u0020strict"
73909  *      is a valid directive but is distinct from "use strict".  The solution
73910  *      here is to decode escapes while tokenizing, but to keep track of the
73911  *      number of escapes.  Directive detection can then check that the
73912  *      number of escapes is zero.
73913  *
73914  *    * Multi-line comments with one or more internal LineTerminator are
73915  *      treated like a line terminator to comply with automatic semicolon
73916  *      insertion.
73917  */
73918 
73919 DUK_INTERNAL
73920 void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx,
73921                                       duk_token *out_token,
73922                                       duk_bool_t strict_mode,
73923                                       duk_bool_t regexp_mode) {
73924 	duk_codepoint_t x;           /* temporary, must be signed and 32-bit to hold Unicode code points */
73925 	duk_small_uint_t advtok = 0; /* (advance << 8) + token_type, updated at function end,
73926 	                              * init is unnecessary but suppresses "may be used uninitialized" warnings.
73927 	                              */
73928 	duk_bool_t got_lineterm = 0;  /* got lineterm preceding non-whitespace, non-lineterm token */
73929 
73930 	if (++lex_ctx->token_count >= lex_ctx->token_limit) {
73931 		DUK_ERROR_RANGE(lex_ctx->thr, "token limit");
73932 		return;  /* unreachable */
73933 	}
73934 
73935 	out_token->t = DUK_TOK_EOF;
73936 	out_token->t_nores = -1;  /* marker: copy t if not changed */
73937 #if 0  /* not necessary to init, disabled for faster parsing */
73938 	out_token->num = DUK_DOUBLE_NAN;
73939 	out_token->str1 = NULL;
73940 	out_token->str2 = NULL;
73941 #endif
73942 	out_token->num_escapes = 0;
73943 	/* out_token->lineterm set by caller */
73944 
73945 	/* This would be nice, but parsing is faster without resetting the
73946 	 * value slots.  The only side effect is that references to temporary
73947 	 * string values may linger until lexing is finished; they're then
73948 	 * freed normally.
73949 	 */
73950 #if 0
73951 	duk_to_undefined((duk_context *) lex_ctx->thr, lex_ctx->slot1_idx);
73952 	duk_to_undefined((duk_context *) lex_ctx->thr, lex_ctx->slot2_idx);
73953 #endif
73954 
73955 	/* 'advtok' indicates how much to advance and which token id to assign
73956 	 * at the end.  This shared functionality minimizes code size.  All
73957 	 * code paths are required to set 'advtok' to some value, so no default
73958 	 * init value is used.  Code paths calling DUK_ERROR() never return so
73959 	 * they don't need to set advtok.
73960 	 */
73961 
73962 	/*
73963 	 *  Matching order:
73964 	 *
73965 	 *    Punctuator first chars, also covers comments, regexps
73966 	 *    LineTerminator
73967 	 *    Identifier or reserved word, also covers null/true/false literals
73968 	 *    NumericLiteral
73969 	 *    StringLiteral
73970 	 *    EOF
73971 	 *
73972 	 *  The order does not matter as long as the longest match is
73973 	 *  always correctly identified.  There are order dependencies
73974 	 *  in the clauses, so it's not trivial to convert to a switch.
73975 	 */
73976 
73977  restart_lineupdate:
73978 	out_token->start_line = lex_ctx->window[0].line;
73979 
73980  restart:
73981 	out_token->start_offset = lex_ctx->window[0].offset;
73982 
73983 	x = DUK__L0();
73984 
73985 	switch (x) {
73986 	case DUK_ASC_SPACE:
73987 	case DUK_ASC_HT:  /* fast paths for space and tab */
73988 		DUK__ADVANCECHARS(lex_ctx, 1);
73989 		goto restart;
73990 	case DUK_ASC_LF:  /* LF line terminator; CR LF and Unicode lineterms are handled in slow path */
73991 		DUK__ADVANCECHARS(lex_ctx, 1);
73992 		got_lineterm = 1;
73993 		goto restart_lineupdate;
73994 	case DUK_ASC_SLASH:  /* '/' */
73995 		if (DUK__L1() == '/') {
73996 			/*
73997 			 *  E5 Section 7.4, allow SourceCharacter (which is any 16-bit
73998 			 *  code point).
73999 			 */
74000 
74001 			/* DUK__ADVANCECHARS(lex_ctx, 2) would be correct here, but it unnecessary */
74002 			for (;;) {
74003 				x = DUK__L0();
74004 				if (x < 0 || duk_unicode_is_line_terminator(x)) {
74005 					break;
74006 				}
74007 				DUK__ADVANCECHARS(lex_ctx, 1);
74008 			}
74009 			goto restart;  /* line terminator will be handled on next round */
74010 		} else if (DUK__L1() == '*') {
74011 			/*
74012 			 *  E5 Section 7.4.  If the multi-line comment contains a newline,
74013 			 *  it is treated like a single line terminator for automatic
74014 			 *  semicolon insertion.
74015 			 */
74016 
74017 			duk_bool_t last_asterisk = 0;
74018 			DUK__ADVANCECHARS(lex_ctx, 2);
74019 			for (;;) {
74020 				x = DUK__L0();
74021 				if (x < 0) {
74022 					DUK_ERROR_SYNTAX(lex_ctx->thr, "eof in multiline comment");
74023 				}
74024 				DUK__ADVANCECHARS(lex_ctx, 1);
74025 				if (last_asterisk && x == '/') {
74026 					break;
74027 				}
74028 				if (duk_unicode_is_line_terminator(x)) {
74029 					got_lineterm = 1;
74030 				}
74031 				last_asterisk = (x == '*');
74032 			}
74033 			goto restart_lineupdate;
74034 		} else if (regexp_mode) {
74035 #if defined(DUK_USE_REGEXP_SUPPORT)
74036 			/*
74037 			 *  "/" followed by something in regexp mode.  See E5 Section 7.8.5.
74038 			 *
74039 			 *  RegExp parsing is a bit complex.  First, the regexp body is delimited
74040 			 *  by forward slashes, but the body may also contain forward slashes as
74041 			 *  part of an escape sequence or inside a character class (delimited by
74042 			 *  square brackets).  A mini state machine is used to implement these.
74043 			 *
74044 			 *  Further, an early (parse time) error must be thrown if the regexp
74045 			 *  would cause a run-time error when used in the expression new RegExp(...).
74046 			 *  Parsing here simply extracts the (candidate) regexp, and also accepts
74047 			 *  invalid regular expressions (which are delimited properly).  The caller
74048 			 *  (compiler) must perform final validation and regexp compilation.
74049 			 *
74050 			 *  RegExp first char may not be '/' (single line comment) or '*' (multi-
74051 			 *  line comment).  These have already been checked above, so there is no
74052 			 *  need below for special handling of the first regexp character as in
74053 			 *  the E5 productions.
74054 			 *
74055 			 *  About unicode escapes within regexp literals:
74056 			 *
74057 			 *      E5 Section 7.8.5 grammar does NOT accept \uHHHH escapes.
74058 			 *      However, Section 6 states that regexps accept the escapes,
74059 			 *      see paragraph starting with "In string literals...".
74060 			 *      The regexp grammar, which sees the decoded regexp literal
74061 			 *      (after lexical parsing) DOES have a \uHHHH unicode escape.
74062 			 *      So, for instance:
74063 			 *
74064 			 *          /\u1234/
74065 			 *
74066 			 *      should first be parsed by the lexical grammar as:
74067 			 *
74068 			 *          '\' 'u'      RegularExpressionBackslashSequence
74069 			 *          '1'          RegularExpressionNonTerminator
74070 			 *          '2'          RegularExpressionNonTerminator
74071 			 *          '3'          RegularExpressionNonTerminator
74072 			 *          '4'          RegularExpressionNonTerminator
74073 			 *
74074 			 *      and the escape itself is then parsed by the regexp engine.
74075 			 *      This is the current implementation.
74076 			 *
74077 			 *  Minor spec inconsistency:
74078 			 *
74079 			 *      E5 Section 7.8.5 RegularExpressionBackslashSequence is:
74080 			 *
74081 			 *         \ RegularExpressionNonTerminator
74082 			 *
74083 			 *      while Section A.1 RegularExpressionBackslashSequence is:
74084 			 *
74085 			 *         \ NonTerminator
74086 			 *
74087 			 *      The latter is not normative and a typo.
74088 			 *
74089 			 */
74090 
74091 			/* first, parse regexp body roughly */
74092 
74093 			duk_small_int_t state = 0;  /* 0=base, 1=esc, 2=class, 3=class+esc */
74094 
74095 			DUK__INITBUFFER(lex_ctx);
74096 			for (;;) {
74097 				DUK__ADVANCECHARS(lex_ctx, 1);  /* skip opening slash on first loop */
74098 				x = DUK__L0();
74099 				if (x < 0 || duk_unicode_is_line_terminator(x)) {
74100 					DUK_ERROR_SYNTAX(lex_ctx->thr, "eof or line terminator in regexp");
74101 				}
74102 				x = DUK__L0();  /* re-read to avoid spill / fetch */
74103 				if (state == 0) {
74104 					if (x == '/') {
74105 						DUK__ADVANCECHARS(lex_ctx, 1);  /* eat closing slash */
74106 						break;
74107 					} else if (x == '\\') {
74108 						state = 1;
74109 					} else if (x == '[') {
74110 						state = 2;
74111 					}
74112 				} else if (state == 1) {
74113 					state = 0;
74114 				} else if (state == 2) {
74115 					if (x == ']') {
74116 						state = 0;
74117 					} else if (x == '\\') {
74118 						state = 3;
74119 					}
74120 				} else { /* state == 3 */
74121 					state = 2;
74122 				}
74123 				DUK__APPENDBUFFER(lex_ctx, x);
74124 			}
74125 			duk__internbuffer(lex_ctx, lex_ctx->slot1_idx);
74126 			out_token->str1 = duk_get_hstring((duk_context *) lex_ctx->thr, lex_ctx->slot1_idx);
74127 
74128 			/* second, parse flags */
74129 
74130 			DUK__INITBUFFER(lex_ctx);
74131 			for (;;) {
74132 				x = DUK__L0();
74133 				if (!duk_unicode_is_identifier_part(x)) {
74134 					break;
74135 				}
74136 				x = DUK__L0();  /* re-read to avoid spill / fetch */
74137 				DUK__APPENDBUFFER(lex_ctx, x);
74138 				DUK__ADVANCECHARS(lex_ctx, 1);
74139 			}
74140 			duk__internbuffer(lex_ctx, lex_ctx->slot2_idx);
74141 			out_token->str2 = duk_get_hstring((duk_context *) lex_ctx->thr, lex_ctx->slot2_idx);
74142 
74143 			DUK__INITBUFFER(lex_ctx);  /* free some memory */
74144 
74145 			/* validation of the regexp is caller's responsibility */
74146 
74147 			advtok = DUK__ADVTOK(0, DUK_TOK_REGEXP);
74148 #else
74149 			DUK_ERROR_SYNTAX(lex_ctx->thr, "regexp support disabled");
74150 #endif
74151 		} else if (DUK__L1() == '=') {
74152 			/* "/=" and not in regexp mode */
74153 			advtok = DUK__ADVTOK(2, DUK_TOK_DIV_EQ);
74154 		} else {
74155 			/* "/" and not in regexp mode */
74156 			advtok = DUK__ADVTOK(1, DUK_TOK_DIV);
74157 		}
74158 		break;
74159 	case DUK_ASC_LCURLY:  /* '{' */
74160 		advtok = DUK__ADVTOK(1, DUK_TOK_LCURLY);
74161 		break;
74162 	case DUK_ASC_RCURLY:  /* '}' */
74163 		advtok = DUK__ADVTOK(1, DUK_TOK_RCURLY);
74164 		break;
74165 	case DUK_ASC_LPAREN:  /* '(' */
74166 		advtok = DUK__ADVTOK(1, DUK_TOK_LPAREN);
74167 		break;
74168 	case DUK_ASC_RPAREN:  /* ')' */
74169 		advtok = DUK__ADVTOK(1, DUK_TOK_RPAREN);
74170 		break;
74171 	case DUK_ASC_LBRACKET:  /* '[' */
74172 		advtok = DUK__ADVTOK(1, DUK_TOK_LBRACKET);
74173 		break;
74174 	case DUK_ASC_RBRACKET:  /* ']' */
74175 		advtok = DUK__ADVTOK(1, DUK_TOK_RBRACKET);
74176 		break;
74177 	case DUK_ASC_PERIOD:  /* '.' */
74178 		if (DUK__ISDIGIT(DUK__L1())) {
74179 			/* Period followed by a digit can only start DecimalLiteral
74180 			 * (handled in slow path).  We could jump straight into the
74181 			 * DecimalLiteral handling but should avoid goto to inside
74182 			 * a block.
74183 			 */
74184 			goto slow_path;
74185 		}
74186 		advtok = DUK__ADVTOK(1, DUK_TOK_PERIOD);
74187 		break;
74188 	case DUK_ASC_SEMICOLON:  /* ';' */
74189 		advtok = DUK__ADVTOK(1, DUK_TOK_SEMICOLON);
74190 		break;
74191 	case DUK_ASC_COMMA:  /* ',' */
74192 		advtok = DUK__ADVTOK(1, DUK_TOK_COMMA);
74193 		break;
74194 	case DUK_ASC_LANGLE:  /* '<' */
74195 		if (DUK__L1() == '<' && DUK__L2() == '=') {
74196 			advtok = DUK__ADVTOK(3, DUK_TOK_ALSHIFT_EQ);
74197 		} else if (DUK__L1() == '=') {
74198 			advtok = DUK__ADVTOK(2, DUK_TOK_LE);
74199 		} else if (DUK__L1() == '<') {
74200 			advtok = DUK__ADVTOK(2, DUK_TOK_ALSHIFT);
74201 		} else {
74202 			advtok = DUK__ADVTOK(1, DUK_TOK_LT);
74203 		}
74204 		break;
74205 	case DUK_ASC_RANGLE:  /* '>' */
74206 		if (DUK__L1() == '>' && DUK__L2() == '>' && DUK__L3() == '=') {
74207 			advtok = DUK__ADVTOK(4, DUK_TOK_RSHIFT_EQ);
74208 		} else if (DUK__L1() == '>' && DUK__L2() == '>') {
74209 			advtok = DUK__ADVTOK(3, DUK_TOK_RSHIFT);
74210 		} else if (DUK__L1() == '>' && DUK__L2() == '=') {
74211 			advtok = DUK__ADVTOK(3, DUK_TOK_ARSHIFT_EQ);
74212 		} else if (DUK__L1() == '=') {
74213 			advtok = DUK__ADVTOK(2, DUK_TOK_GE);
74214 		} else if (DUK__L1() == '>') {
74215 			advtok = DUK__ADVTOK(2, DUK_TOK_ARSHIFT);
74216 		} else {
74217 			advtok = DUK__ADVTOK(1, DUK_TOK_GT);
74218 		}
74219 		break;
74220 	case DUK_ASC_EQUALS:  /* '=' */
74221 		if (DUK__L1() == '=' && DUK__L2() == '=') {
74222 			advtok = DUK__ADVTOK(3, DUK_TOK_SEQ);
74223 		} else if (DUK__L1() == '=') {
74224 			advtok = DUK__ADVTOK(2, DUK_TOK_EQ);
74225 		} else {
74226 			advtok = DUK__ADVTOK(1, DUK_TOK_EQUALSIGN);
74227 		}
74228 		break;
74229 	case DUK_ASC_EXCLAMATION:  /* '!' */
74230 		if (DUK__L1() == '=' && DUK__L2() == '=') {
74231 			advtok = DUK__ADVTOK(3, DUK_TOK_SNEQ);
74232 		} else if (DUK__L1() == '=') {
74233 			advtok = DUK__ADVTOK(2, DUK_TOK_NEQ);
74234 		} else {
74235 			advtok = DUK__ADVTOK(1, DUK_TOK_LNOT);
74236 		}
74237 		break;
74238 	case DUK_ASC_PLUS:  /* '+' */
74239 		if (DUK__L1() == '+') {
74240 			advtok = DUK__ADVTOK(2, DUK_TOK_INCREMENT);
74241 		} else if (DUK__L1() == '=') {
74242 			advtok = DUK__ADVTOK(2, DUK_TOK_ADD_EQ);
74243 		} else {
74244 			advtok = DUK__ADVTOK(1, DUK_TOK_ADD);
74245 		}
74246 		break;
74247 	case DUK_ASC_MINUS:  /* '-' */
74248 		if (DUK__L1() == '-') {
74249 			advtok = DUK__ADVTOK(2, DUK_TOK_DECREMENT);
74250 		} else if (DUK__L1() == '=') {
74251 			advtok = DUK__ADVTOK(2, DUK_TOK_SUB_EQ);
74252 		} else {
74253 			advtok = DUK__ADVTOK(1, DUK_TOK_SUB);
74254 		}
74255 		break;
74256 	case DUK_ASC_STAR:  /* '*' */
74257 		if (DUK__L1() == '=') {
74258 			advtok = DUK__ADVTOK(2, DUK_TOK_MUL_EQ);
74259 		} else {
74260 			advtok = DUK__ADVTOK(1, DUK_TOK_MUL);
74261 		}
74262 		break;
74263 	case DUK_ASC_PERCENT:  /* '%' */
74264 		if (DUK__L1() == '=') {
74265 			advtok = DUK__ADVTOK(2, DUK_TOK_MOD_EQ);
74266 		} else {
74267 			advtok = DUK__ADVTOK(1, DUK_TOK_MOD);
74268 		}
74269 		break;
74270 	case DUK_ASC_AMP:  /* '&' */
74271 		if (DUK__L1() == '&') {
74272 			advtok = DUK__ADVTOK(2, DUK_TOK_LAND);
74273 		} else if (DUK__L1() == '=') {
74274 			advtok = DUK__ADVTOK(2, DUK_TOK_BAND_EQ);
74275 		} else {
74276 			advtok = DUK__ADVTOK(1, DUK_TOK_BAND);
74277 		}
74278 		break;
74279 	case DUK_ASC_PIPE:  /* '|' */
74280 		if (DUK__L1() == '|') {
74281 			advtok = DUK__ADVTOK(2, DUK_TOK_LOR);
74282 		} else if (DUK__L1() == '=') {
74283 			advtok = DUK__ADVTOK(2, DUK_TOK_BOR_EQ);
74284 		} else {
74285 			advtok = DUK__ADVTOK(1, DUK_TOK_BOR);
74286 		}
74287 		break;
74288 	case DUK_ASC_CARET:  /* '^' */
74289 		if (DUK__L1() == '=') {
74290 			advtok = DUK__ADVTOK(2, DUK_TOK_BXOR_EQ);
74291 		} else {
74292 			advtok = DUK__ADVTOK(1, DUK_TOK_BXOR);
74293 		}
74294 		break;
74295 	case DUK_ASC_TILDE:  /* '~' */
74296 		advtok = DUK__ADVTOK(1, DUK_TOK_BNOT);
74297 		break;
74298 	case DUK_ASC_QUESTION:  /* '?' */
74299 		advtok = DUK__ADVTOK(1, DUK_TOK_QUESTION);
74300 		break;
74301 	case DUK_ASC_COLON:  /* ':' */
74302 		advtok = DUK__ADVTOK(1, DUK_TOK_COLON);
74303 		break;
74304 	case DUK_ASC_DOUBLEQUOTE:    /* '"' */
74305 	case DUK_ASC_SINGLEQUOTE: {  /* '\'' */
74306 		duk_small_int_t quote = x;  /* Note: duk_uint8_t type yields larger code */
74307 		duk_small_int_t adv;
74308 
74309 		DUK__INITBUFFER(lex_ctx);
74310 		for (;;) {
74311 			DUK__ADVANCECHARS(lex_ctx, 1);  /* eat opening quote on first loop */
74312 			x = DUK__L0();
74313 			if (x < 0 || duk_unicode_is_line_terminator(x)) {
74314 				DUK_ERROR_SYNTAX(lex_ctx->thr, "eof or line terminator in string literal");
74315 			}
74316 			if (x == quote) {
74317 				DUK__ADVANCECHARS(lex_ctx, 1);  /* eat closing quote */
74318 				break;
74319 			}
74320 			if (x == '\\') {
74321 				/* DUK__L0        -> '\' char
74322 				 * DUK__L1 ... DUK__L5 -> more lookup
74323 				 */
74324 
74325 				x = DUK__L1();
74326 
74327 				/* How much to advance before next loop; note that next loop
74328 				 * will advance by 1 anyway, so -1 from the total escape
74329 				 * length (e.g. len('\uXXXX') - 1 = 6 - 1).  As a default,
74330 				 * 1 is good.
74331 				 */
74332 				adv = 2 - 1;  /* note: long live range */
74333 
74334 				if (x < 0) {
74335 					DUK_ERROR_SYNTAX(lex_ctx->thr, "eof or line terminator in string literal");
74336 				}
74337 				if (duk_unicode_is_line_terminator(x)) {
74338 					/* line continuation */
74339 					if (x == 0x000d && DUK__L2() == 0x000a) {
74340 						/* CR LF again a special case */
74341 						adv = 3 - 1;
74342 					}
74343 				} else if (x == '\'') {
74344 					DUK__APPENDBUFFER(lex_ctx, 0x0027);
74345 				} else if (x == '"') {
74346 					DUK__APPENDBUFFER(lex_ctx, 0x0022);
74347 				} else if (x == '\\') {
74348 					DUK__APPENDBUFFER(lex_ctx, 0x005c);
74349 				} else if (x == 'b') {
74350 					DUK__APPENDBUFFER(lex_ctx, 0x0008);
74351 				} else if (x == 'f') {
74352 					DUK__APPENDBUFFER(lex_ctx, 0x000c);
74353 				} else if (x == 'n') {
74354 					DUK__APPENDBUFFER(lex_ctx, 0x000a);
74355 				} else if (x == 'r') {
74356 					DUK__APPENDBUFFER(lex_ctx, 0x000d);
74357 				} else if (x == 't') {
74358 					DUK__APPENDBUFFER(lex_ctx, 0x0009);
74359 				} else if (x == 'v') {
74360 					DUK__APPENDBUFFER(lex_ctx, 0x000b);
74361 				} else if (x == 'x') {
74362 					adv = 4 - 1;
74363 					DUK__APPENDBUFFER(lex_ctx, duk__decode_hexesc_from_window(lex_ctx, 2));
74364 				} else if (x == 'u') {
74365 					adv = 6 - 1;
74366 					DUK__APPENDBUFFER(lex_ctx, duk__decode_uniesc_from_window(lex_ctx, 2));
74367 				} else if (DUK__ISDIGIT(x)) {
74368 					duk_codepoint_t ch = 0;  /* initialized to avoid warnings of unused var */
74369 
74370 					/*
74371 					 *  Octal escape or zero escape:
74372 					 *    \0                                     (lookahead not DecimalDigit)
74373 					 *    \1 ... \7                              (lookahead not DecimalDigit)
74374 					 *    \ZeroToThree OctalDigit                (lookahead not DecimalDigit)
74375 					 *    \FourToSeven OctalDigit                (no lookahead restrictions)
74376 					 *    \ZeroToThree OctalDigit OctalDigit     (no lookahead restrictions)
74377 					 *
74378 					 *  Zero escape is part of the standard syntax.  Octal escapes are
74379 					 *  defined in E5 Section B.1.2, and are only allowed in non-strict mode.
74380 					 *  Any other productions starting with a decimal digit are invalid.
74381 					 */
74382 
74383 					if (x == '0' && !DUK__ISDIGIT(DUK__L2())) {
74384 						/* Zero escape (also allowed in non-strict mode) */
74385 						ch = 0;
74386 						/* adv = 2 - 1 default OK */
74387 #if defined(DUK_USE_OCTAL_SUPPORT)
74388 					} else if (strict_mode) {
74389 						/* No other escape beginning with a digit in strict mode */
74390 						DUK_ERROR_SYNTAX(lex_ctx->thr, "invalid escape in string literal");
74391 					} else if (DUK__ISDIGIT03(x) && DUK__ISOCTDIGIT(DUK__L2()) && DUK__ISOCTDIGIT(DUK__L3())) {
74392 						/* Three digit octal escape, digits validated. */
74393 						adv = 4 - 1;
74394 						ch = (duk__hexval(lex_ctx, x) << 6) +
74395 						     (duk__hexval(lex_ctx, DUK__L2()) << 3) +
74396 						     duk__hexval(lex_ctx, DUK__L3());
74397 					} else if (((DUK__ISDIGIT03(x) && !DUK__ISDIGIT(DUK__L3())) || DUK__ISDIGIT47(x)) &&
74398 					           DUK__ISOCTDIGIT(DUK__L2())) {
74399 						/* Two digit octal escape, digits validated.
74400 						 *
74401 						 * The if-condition is a bit tricky.  We could catch e.g.
74402 						 * '\039' in the three-digit escape and fail it there (by
74403 					         * validating the digits), but we want to avoid extra
74404 						 * additional validation code.
74405 						 */
74406 						adv = 3 - 1;
74407 						ch = (duk__hexval(lex_ctx, x) << 3) +
74408 						     duk__hexval(lex_ctx, DUK__L2());
74409 					} else if (DUK__ISDIGIT(x) && !DUK__ISDIGIT(DUK__L2())) {
74410 						/* One digit octal escape, digit validated. */
74411 						/* adv = 2 default OK */
74412 						ch = duk__hexval(lex_ctx, x);
74413 #else
74414 					/* fall through to error */
74415 #endif
74416 					} else {
74417 						DUK_ERROR_SYNTAX(lex_ctx->thr, "invalid escape in string literal");
74418 					}
74419 
74420 					DUK__APPENDBUFFER(lex_ctx, ch);
74421 				} else {
74422 					/* escaped NonEscapeCharacter */
74423 					DUK__APPENDBUFFER(lex_ctx, x);
74424 				}
74425 				DUK__ADVANCECHARS(lex_ctx, adv);
74426 
74427 				/* Track number of escapes; count not really needed but directive
74428 				 * prologues need to detect whether there were any escapes or line
74429 				 * continuations or not.
74430 				 */
74431 				out_token->num_escapes++;
74432 			} else {
74433 				/* part of string */
74434 				DUK__APPENDBUFFER(lex_ctx, x);
74435 			}
74436 		}
74437 
74438 		duk__internbuffer(lex_ctx, lex_ctx->slot1_idx);
74439 		out_token->str1 = duk_get_hstring((duk_context *) lex_ctx->thr, lex_ctx->slot1_idx);
74440 
74441 		DUK__INITBUFFER(lex_ctx);  /* free some memory */
74442 
74443 		advtok = DUK__ADVTOK(0, DUK_TOK_STRING);
74444 		break;
74445 	}
74446 	default:
74447 		goto slow_path;
74448 	}  /* switch */
74449 
74450 	goto skip_slow_path;
74451 
74452  slow_path:
74453 	if (duk_unicode_is_line_terminator(x)) {
74454 		if (x == 0x000d && DUK__L1() == 0x000a) {
74455 			/*
74456 			 *  E5 Section 7.3: CR LF is detected as a single line terminator for
74457 			 *  line numbers.  Here we also detect it as a single line terminator
74458 			 *  token.
74459 			 */
74460 			DUK__ADVANCECHARS(lex_ctx, 2);
74461 		} else {
74462 			DUK__ADVANCECHARS(lex_ctx, 1);
74463 		}
74464 		got_lineterm = 1;
74465 		goto restart_lineupdate;
74466 	} else if (duk_unicode_is_identifier_start(x) || x == '\\') {
74467 		/*
74468 		 *  Parse an identifier and then check whether it is:
74469 		 *    - reserved word (keyword or other reserved word)
74470 		 *    - "null"  (NullLiteral)
74471 		 *    - "true"  (BooleanLiteral)
74472 		 *    - "false" (BooleanLiteral)
74473 		 *    - anything else => identifier
74474 		 *
74475 		 *  This does not follow the E5 productions cleanly, but is
74476 		 *  useful and compact.
74477 		 *
74478 		 *  Note that identifiers may contain Unicode escapes,
74479 		 *  see E5 Sections 6 and 7.6.  They must be decoded first,
74480 		 *  and the result checked against allowed characters.
74481 		 *  The above if-clause accepts an identifier start and an
74482 		 *  '\' character -- no other token can begin with a '\'.
74483 		 *
74484 		 *  Note that "get" and "set" are not reserved words in E5
74485 		 *  specification so they are recognized as plain identifiers
74486 		 *  (the tokens DUK_TOK_GET and DUK_TOK_SET are actually not
74487 		 *  used now).  The compiler needs to work around this.
74488 		 *
74489 		 *  Strictly speaking, following Ecmascript longest match
74490 		 *  specification, an invalid escape for the first character
74491 		 *  should cause a syntax error.  However, an invalid escape
74492 		 *  for IdentifierParts should just terminate the identifier
74493 		 *  early (longest match), and let the next tokenization
74494 		 *  fail.  For instance Rhino croaks with 'foo\z' when
74495 		 *  parsing the identifier.  This has little practical impact.
74496 		 */
74497 
74498 		duk_small_int_t i, i_end;
74499 		duk_bool_t first = 1;
74500 		duk_hstring *str;
74501 
74502 		DUK__INITBUFFER(lex_ctx);
74503 		for (;;) {
74504 			/* re-lookup first char on first loop */
74505 			if (DUK__L0() == '\\') {
74506 				duk_codepoint_t ch;
74507 				if (DUK__L1() != 'u') {
74508 					DUK_ERROR_SYNTAX(lex_ctx->thr, "invalid unicode escape in identifier");
74509 				}
74510 
74511 				ch = duk__decode_uniesc_from_window(lex_ctx, 2);
74512 
74513 				/* IdentifierStart is stricter than IdentifierPart, so if the first
74514 				 * character is escaped, must have a stricter check here.
74515 				 */
74516 				if (!(first ? duk_unicode_is_identifier_start(ch) : duk_unicode_is_identifier_part(ch))) {
74517 					DUK_ERROR_SYNTAX(lex_ctx->thr, "invalid unicode escape in identifier");
74518 				}
74519 				DUK__APPENDBUFFER(lex_ctx, ch);
74520 				DUK__ADVANCECHARS(lex_ctx, 6);
74521 
74522 				/* Track number of escapes: necessary for proper keyword
74523 				 * detection.
74524 				 */
74525 				out_token->num_escapes++;
74526 			} else {
74527 				/* Note: first character is checked against this.  But because
74528 				 * IdentifierPart includes all IdentifierStart characters, and
74529 				 * the first character (if unescaped) has already been checked
74530 				 * in the if condition, this is OK.
74531 				 */
74532 				if (!duk_unicode_is_identifier_part(DUK__L0())) {
74533 					break;
74534 				}
74535 				DUK__APPENDBUFFER(lex_ctx, DUK__L0());
74536 				DUK__ADVANCECHARS(lex_ctx, 1);
74537 			}
74538 			first = 0;
74539 		}
74540 
74541 		duk__internbuffer(lex_ctx, lex_ctx->slot1_idx);
74542 		out_token->str1 = duk_get_hstring((duk_context *) lex_ctx->thr, lex_ctx->slot1_idx);
74543 		str = out_token->str1;
74544 		DUK_ASSERT(str != NULL);
74545 		out_token->t_nores = DUK_TOK_IDENTIFIER;
74546 
74547 		DUK__INITBUFFER(lex_ctx);  /* free some memory */
74548 
74549 		/*
74550 		 *  Interned identifier is compared against reserved words, which are
74551 		 *  currently interned into the heap context.  See genbuiltins.py.
74552 		 *
74553 		 *  Note that an escape in the identifier disables recognition of
74554 		 *  keywords; e.g. "\u0069f = 1;" is a valid statement (assigns to
74555 		 *  identifier named "if").  This is not necessarily compliant,
74556 		 *  see test-dec-escaped-char-in-keyword.js.
74557 		 *
74558 		 *  Note: "get" and "set" are awkward.  They are not officially
74559 		 *  ReservedWords (and indeed e.g. "var set = 1;" is valid), and
74560 		 *  must come out as DUK_TOK_IDENTIFIER.  The compiler needs to
74561 		 *  work around this a bit.
74562 		 */
74563 
74564 		/* XXX: optimize by adding the token numbers directly into the
74565 		 * always interned duk_hstring objects (there should be enough
74566 		 * flag bits free for that)?
74567 		 */
74568 
74569 		i_end = (strict_mode ? DUK_STRIDX_END_RESERVED : DUK_STRIDX_START_STRICT_RESERVED);
74570 
74571 		advtok = DUK__ADVTOK(0, DUK_TOK_IDENTIFIER);
74572 		if (out_token->num_escapes == 0) {
74573 			for (i = DUK_STRIDX_START_RESERVED; i < i_end; i++) {
74574 				DUK_ASSERT(i >= 0 && i < DUK_HEAP_NUM_STRINGS);
74575 				if (DUK_HTHREAD_GET_STRING(lex_ctx->thr, i) == str) {
74576 					advtok = DUK__ADVTOK(0, DUK_STRIDX_TO_TOK(i));
74577 					break;
74578 				}
74579 			}
74580 		}
74581 	} else if (DUK__ISDIGIT(x) || (x == '.')) {
74582 		/* Note: decimal number may start with a period, but must be followed by a digit */
74583 
74584 		/*
74585 		 *  DecimalLiteral, HexIntegerLiteral, OctalIntegerLiteral
74586 		 *  "pre-parsing", followed by an actual, accurate parser step.
74587 		 *
74588 		 *  Note: the leading sign character ('+' or '-') is -not- part of
74589 		 *  the production in E5 grammar, and that the a DecimalLiteral
74590 		 *  starting with a '0' must be followed by a non-digit.  Leading
74591 		 *  zeroes are syntax errors and must be checked for.
74592 		 *
74593 		 *  XXX: the two step parsing process is quite awkward, it would
74594 		 *  be more straightforward to allow numconv to parse the longest
74595 		 *  valid prefix (it already does that, it only needs to indicate
74596 		 *  where the input ended).  However, the lexer decodes characters
74597 		 *  using a lookup window, so this is not a trivial change.
74598 		 */
74599 
74600 		/* XXX: because of the final check below (that the literal is not
74601 		 * followed by a digit), this could maybe be simplified, if we bail
74602 		 * out early from a leading zero (and if there are no periods etc).
74603 		 * Maybe too complex.
74604 		 */
74605 
74606 		duk_double_t val;
74607 		duk_bool_t int_only = 0;
74608 		duk_bool_t allow_hex = 0;
74609 		duk_small_int_t state;  /* 0=before period/exp,
74610 		                         * 1=after period, before exp
74611 		                         * 2=after exp, allow '+' or '-'
74612 		                         * 3=after exp and exp sign
74613 		                         */
74614 		duk_small_uint_t s2n_flags;
74615 		duk_codepoint_t y;
74616 
74617 		DUK__INITBUFFER(lex_ctx);
74618 		y = DUK__L1();
74619 		if (x == '0' && (y == 'x' || y == 'X')) {
74620 			DUK__APPENDBUFFER(lex_ctx, x);
74621 			DUK__APPENDBUFFER(lex_ctx, y);
74622 			DUK__ADVANCECHARS(lex_ctx, 2);
74623 			int_only = 1;
74624 			allow_hex = 1;
74625 #if defined(DUK_USE_OCTAL_SUPPORT)
74626 		} else if (!strict_mode && x == '0' && DUK__ISDIGIT(y)) {
74627 			/* Note: if DecimalLiteral starts with a '0', it can only be
74628 			 * followed by a period or an exponent indicator which starts
74629 			 * with 'e' or 'E'.  Hence the if-check above ensures that
74630 			 * OctalIntegerLiteral is the only valid NumericLiteral
74631 			 * alternative at this point (even if y is, say, '9').
74632 			 */
74633 
74634 			DUK__APPENDBUFFER(lex_ctx, x);
74635 			DUK__ADVANCECHARS(lex_ctx, 1);
74636 			int_only = 1;
74637 #endif
74638 		}
74639 
74640 		state = 0;
74641 		for (;;) {
74642 			x = DUK__L0();  /* re-lookup curr char on first round */
74643 			if (DUK__ISDIGIT(x)) {
74644 				/* Note: intentionally allow leading zeroes here, as the
74645 				 * actual parser will check for them.
74646 				 */
74647 				if (state == 2) {
74648 					state = 3;
74649 				}
74650 			} else if (allow_hex && DUK__ISHEXDIGIT(x)) {
74651 				/* Note: 'e' and 'E' are also accepted here. */
74652 				;
74653 			} else if (x == '.') {
74654 				if (state >= 1 || int_only) {
74655 					break;
74656 				} else {
74657 					state = 1;
74658 				}
74659 			} else if (x == 'e' || x == 'E') {
74660 				if (state >= 2 || int_only) {
74661 					break;
74662 				} else {
74663 					state = 2;
74664 				}
74665 			} else if (x == '-' || x == '+') {
74666 				if (state != 2) {
74667 					break;
74668 				} else {
74669 					state = 3;
74670 				}
74671 			} else {
74672 				break;
74673 			}
74674 			DUK__APPENDBUFFER(lex_ctx, x);
74675 			DUK__ADVANCECHARS(lex_ctx, 1);
74676 		}
74677 
74678 		/* XXX: better coercion */
74679 		duk__internbuffer(lex_ctx, lex_ctx->slot1_idx);
74680 
74681 		s2n_flags = DUK_S2N_FLAG_ALLOW_EXP |
74682 		            DUK_S2N_FLAG_ALLOW_FRAC |
74683 		            DUK_S2N_FLAG_ALLOW_NAKED_FRAC |
74684 		            DUK_S2N_FLAG_ALLOW_EMPTY_FRAC |
74685 #if defined(DUK_USE_OCTAL_SUPPORT)
74686 		            (strict_mode ? 0 : DUK_S2N_FLAG_ALLOW_AUTO_OCT_INT) |
74687 #endif
74688 		            DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT;
74689 
74690 		duk_dup((duk_context *) lex_ctx->thr, lex_ctx->slot1_idx);
74691 		duk_numconv_parse((duk_context *) lex_ctx->thr, 10 /*radix*/, s2n_flags);
74692 		val = duk_to_number((duk_context *) lex_ctx->thr, -1);
74693 		if (DUK_ISNAN(val)) {
74694 			DUK_ERROR_SYNTAX(lex_ctx->thr, "invalid numeric literal");
74695 		}
74696 		duk_replace((duk_context *) lex_ctx->thr, lex_ctx->slot1_idx);  /* could also just pop? */
74697 
74698 		DUK__INITBUFFER(lex_ctx);  /* free some memory */
74699 
74700 		/* Section 7.8.3 (note): NumericLiteral must be followed by something other than
74701 		 * IdentifierStart or DecimalDigit.
74702 		 */
74703 
74704 		if (DUK__ISDIGIT(DUK__L0()) || duk_unicode_is_identifier_start(DUK__L0())) {
74705 			DUK_ERROR_SYNTAX(lex_ctx->thr, "invalid numeric literal");
74706 		}
74707 
74708 		out_token->num = val;
74709 		advtok = DUK__ADVTOK(0, DUK_TOK_NUMBER);
74710 	} else if (duk_unicode_is_whitespace(DUK__LOOKUP(lex_ctx, 0))) {
74711 		DUK__ADVANCECHARS(lex_ctx, 1);
74712 		goto restart;
74713 	} else if (x < 0) {
74714 		advtok = DUK__ADVTOK(0, DUK_TOK_EOF);
74715 	} else {
74716 		DUK_ERROR_SYNTAX(lex_ctx->thr, "invalid token");
74717 	}
74718  skip_slow_path:
74719 
74720 	/*
74721 	 *  Shared exit path
74722 	 */
74723 
74724 	DUK__ADVANCEBYTES(lex_ctx, advtok >> 8);
74725 	out_token->t = advtok & 0xff;
74726 	if (out_token->t_nores < 0) {
74727 		out_token->t_nores = out_token->t;
74728 	}
74729 	out_token->lineterm = got_lineterm;
74730 
74731 	/* Automatic semicolon insertion is allowed if a token is preceded
74732 	 * by line terminator(s), or terminates a statement list (right curly
74733 	 * or EOF).
74734 	 */
74735 	if (got_lineterm || out_token->t == DUK_TOK_RCURLY || out_token->t == DUK_TOK_EOF) {
74736 		out_token->allow_auto_semi = 1;
74737 	} else {
74738 		out_token->allow_auto_semi = 0;
74739 	}
74740 }
74741 
74742 #if defined(DUK_USE_REGEXP_SUPPORT)
74743 
74744 /*
74745  *  Parse a RegExp token.  The grammar is described in E5 Section 15.10.
74746  *  Terminal constructions (such as quantifiers) are parsed directly here.
74747  *
74748  *  0xffffffffU is used as a marker for "infinity" in quantifiers.  Further,
74749  *  DUK__MAX_RE_QUANT_DIGITS limits the maximum number of digits that
74750  *  will be accepted for a quantifier.
74751  */
74752 
74753 DUK_INTERNAL void duk_lexer_parse_re_token(duk_lexer_ctx *lex_ctx, duk_re_token *out_token) {
74754 	duk_small_int_t advtok = 0;  /* init is unnecessary but suppresses "may be used uninitialized" warnings */
74755 	duk_codepoint_t x, y;
74756 
74757 	if (++lex_ctx->token_count >= lex_ctx->token_limit) {
74758 		DUK_ERROR_RANGE(lex_ctx->thr, "token limit");
74759 		return;  /* unreachable */
74760 	}
74761 
74762 	DUK_MEMZERO(out_token, sizeof(*out_token));
74763 
74764 	x = DUK__L0();
74765 	y = DUK__L1();
74766 
74767 	DUK_DDD(DUK_DDDPRINT("parsing regexp token, L0=%ld, L1=%ld", (long) x, (long) y));
74768 
74769 	switch (x) {
74770 	case '|': {
74771 		advtok = DUK__ADVTOK(1, DUK_RETOK_DISJUNCTION);
74772 		break;
74773 	}
74774 	case '^': {
74775 		advtok = DUK__ADVTOK(1, DUK_RETOK_ASSERT_START);
74776 		break;
74777 	}
74778 	case '$': {
74779 		advtok = DUK__ADVTOK(1, DUK_RETOK_ASSERT_END);
74780 		break;
74781 	}
74782 	case '?': {
74783 		out_token->qmin = 0;
74784 		out_token->qmax = 1;
74785 		if (y == '?') {
74786 			advtok = DUK__ADVTOK(2, DUK_RETOK_QUANTIFIER);
74787 			out_token->greedy = 0;
74788 		} else {
74789 			advtok = DUK__ADVTOK(1, DUK_RETOK_QUANTIFIER);
74790 			out_token->greedy = 1;
74791 		}
74792 		break;
74793 	}
74794 	case '*': {
74795 		out_token->qmin = 0;
74796 		out_token->qmax = DUK_RE_QUANTIFIER_INFINITE;
74797 		if (y == '?') {
74798 			advtok = DUK__ADVTOK(2, DUK_RETOK_QUANTIFIER);
74799 			out_token->greedy = 0;
74800 		} else {
74801 			advtok = DUK__ADVTOK(1, DUK_RETOK_QUANTIFIER);
74802 			out_token->greedy = 1;
74803 		}
74804 		break;
74805 	}
74806 	case '+': {
74807 		out_token->qmin = 1;
74808 		out_token->qmax = DUK_RE_QUANTIFIER_INFINITE;
74809 		if (y == '?') {
74810 			advtok = DUK__ADVTOK(2, DUK_RETOK_QUANTIFIER);
74811 			out_token->greedy = 0;
74812 		} else {
74813 			advtok = DUK__ADVTOK(1, DUK_RETOK_QUANTIFIER);
74814 			out_token->greedy = 1;
74815 		}
74816 		break;
74817 	}
74818 	case '{': {
74819 		/* Production allows 'DecimalDigits', including leading zeroes */
74820 		duk_uint_fast32_t val1 = 0;
74821 		duk_uint_fast32_t val2 = DUK_RE_QUANTIFIER_INFINITE;
74822 		duk_small_int_t digits = 0;
74823 #if defined(DUK_USE_ES6_REGEXP_BRACES)
74824 		duk_lexer_point lex_pt;
74825 #endif
74826 
74827 #if defined(DUK_USE_ES6_REGEXP_BRACES)
74828 		/* Store lexer position, restoring if quantifier is invalid. */
74829 		DUK_LEXER_GETPOINT(lex_ctx, &lex_pt);
74830 #endif
74831 
74832 		for (;;) {
74833 			DUK__ADVANCECHARS(lex_ctx, 1);  /* eat '{' on entry */
74834 			x = DUK__L0();
74835 			if (DUK__ISDIGIT(x)) {
74836 				digits++;
74837 				val1 = val1 * 10 + (duk_uint_fast32_t) duk__hexval(lex_ctx, x);
74838 			} else if (x == ',') {
74839 				if (digits > DUK__MAX_RE_QUANT_DIGITS) {
74840 					goto invalid_quantifier;
74841 				}
74842 				if (val2 != DUK_RE_QUANTIFIER_INFINITE) {
74843 					goto invalid_quantifier;
74844 				}
74845 				if (DUK__L1() == '}') {
74846 					/* form: { DecimalDigits , }, val1 = min count */
74847 					if (digits == 0) {
74848 						goto invalid_quantifier;
74849 					}
74850 					out_token->qmin = val1;
74851 					out_token->qmax = DUK_RE_QUANTIFIER_INFINITE;
74852 					DUK__ADVANCECHARS(lex_ctx, 2);
74853 					break;
74854 				}
74855 				val2 = val1;
74856 				val1 = 0;
74857 				digits = 0;  /* not strictly necessary because of lookahead '}' above */
74858 			} else if (x == '}') {
74859 				if (digits > DUK__MAX_RE_QUANT_DIGITS) {
74860 					goto invalid_quantifier;
74861 				}
74862 				if (digits == 0) {
74863 					goto invalid_quantifier;
74864 				}
74865 				if (val2 != DUK_RE_QUANTIFIER_INFINITE) {
74866 					/* val2 = min count, val1 = max count */
74867 					out_token->qmin = val2;
74868 					out_token->qmax = val1;
74869 				} else {
74870 					/* val1 = count */
74871 					out_token->qmin = val1;
74872 					out_token->qmax = val1;
74873 				}
74874 				DUK__ADVANCECHARS(lex_ctx, 1);
74875 				break;
74876 			} else {
74877 				goto invalid_quantifier;
74878 			}
74879 		}
74880 		if (DUK__L0() == '?') {
74881 			out_token->greedy = 0;
74882 			DUK__ADVANCECHARS(lex_ctx, 1);
74883 		} else {
74884 			out_token->greedy = 1;
74885 		}
74886 		advtok = DUK__ADVTOK(0, DUK_RETOK_QUANTIFIER);
74887 		break;
74888  invalid_quantifier:
74889 #if defined(DUK_USE_ES6_REGEXP_BRACES)
74890 		/* Failed to match the quantifier, restore lexer and parse
74891 		 * opening brace as a literal.
74892 		 */
74893 		DUK_LEXER_SETPOINT(lex_ctx, &lex_pt);
74894 		advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_CHAR);
74895 		out_token->num = '{';
74896 #else
74897 		DUK_ERROR_SYNTAX(lex_ctx->thr, "invalid regexp quantifier");
74898 #endif
74899 		break;
74900 	}
74901 	case '.': {
74902 		advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_PERIOD);
74903 		break;
74904 	}
74905 	case '\\': {
74906 		/* The E5.1 specification does not seem to allow IdentifierPart characters
74907 		 * to be used as identity escapes.  Unfortunately this includes '$', which
74908 		 * cannot be escaped as '\$'; it needs to be escaped e.g. as '\u0024'.
74909 		 * Many other implementations (including V8 and Rhino, for instance) do
74910 		 * accept '\$' as a valid identity escape, which is quite pragmatic.
74911 		 * See: test-regexp-identity-escape-dollar.js.
74912 		 */
74913 
74914 		advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_CHAR);  /* default: char escape (two chars) */
74915 		if (y == 'b') {
74916 			advtok = DUK__ADVTOK(2, DUK_RETOK_ASSERT_WORD_BOUNDARY);
74917 		} else if (y == 'B') {
74918 			advtok = DUK__ADVTOK(2, DUK_RETOK_ASSERT_NOT_WORD_BOUNDARY);
74919 		} else if (y == 'f') {
74920 			out_token->num = 0x000c;
74921 		} else if (y == 'n') {
74922 			out_token->num = 0x000a;
74923 		} else if (y == 't') {
74924 			out_token->num = 0x0009;
74925 		} else if (y == 'r') {
74926 			out_token->num = 0x000d;
74927 		} else if (y == 'v') {
74928 			out_token->num = 0x000b;
74929 		} else if (y == 'c') {
74930 			x = DUK__L2();
74931 			if ((x >= 'a' && x <= 'z') ||
74932 			    (x >= 'A' && x <= 'Z')) {
74933 				out_token->num = (x % 32);
74934 				advtok = DUK__ADVTOK(3, DUK_RETOK_ATOM_CHAR);
74935 			} else {
74936 				DUK_ERROR_SYNTAX(lex_ctx->thr, "invalid regexp escape");
74937 			}
74938 		} else if (y == 'x') {
74939 			out_token->num = duk__decode_hexesc_from_window(lex_ctx, 2);
74940 			advtok = DUK__ADVTOK(4, DUK_RETOK_ATOM_CHAR);
74941 		} else if (y == 'u') {
74942 			out_token->num = duk__decode_uniesc_from_window(lex_ctx, 2);
74943 			advtok = DUK__ADVTOK(6, DUK_RETOK_ATOM_CHAR);
74944 		} else if (y == 'd') {
74945 			advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_DIGIT);
74946 		} else if (y == 'D') {
74947 			advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_NOT_DIGIT);
74948 		} else if (y == 's') {
74949 			advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_WHITE);
74950 		} else if (y == 'S') {
74951 			advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_NOT_WHITE);
74952 		} else if (y == 'w') {
74953 			advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_WORD_CHAR);
74954 		} else if (y == 'W') {
74955 			advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_NOT_WORD_CHAR);
74956 		} else if (DUK__ISDIGIT(y)) {
74957 			/* E5 Section 15.10.2.11 */
74958 			if (y == '0') {
74959 				if (DUK__ISDIGIT(DUK__L2())) {
74960 					DUK_ERROR_SYNTAX(lex_ctx->thr, "invalid regexp escape");
74961 				}
74962 				out_token->num = 0x0000;
74963 				advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_CHAR);
74964 			} else {
74965 				/* XXX: shared parsing? */
74966 				duk_uint_fast32_t val = 0;
74967 				duk_small_int_t i;
74968 				for (i = 0; ; i++) {
74969 					if (i >= DUK__MAX_RE_DECESC_DIGITS) {
74970 						DUK_ERROR_SYNTAX(lex_ctx->thr, "invalid regexp escape");
74971 					}
74972 					DUK__ADVANCECHARS(lex_ctx, 1);  /* eat backslash on entry */
74973 					x = DUK__L0();
74974 					if (!DUK__ISDIGIT(x)) {
74975 						break;
74976 					}
74977 					val = val * 10 + (duk_uint_fast32_t) duk__hexval(lex_ctx, x);
74978 				}
74979 				/* DUK__L0() cannot be a digit, because the loop doesn't terminate if it is */
74980 				advtok = DUK__ADVTOK(0, DUK_RETOK_ATOM_BACKREFERENCE);
74981 				out_token->num = val;
74982 			}
74983 		} else if ((y >= 0 && !duk_unicode_is_identifier_part(y)) ||
74984 #if defined(DUK_USE_NONSTD_REGEXP_DOLLAR_ESCAPE)
74985 		           y == '$' ||
74986 #endif
74987 		           y == DUK_UNICODE_CP_ZWNJ ||
74988 		           y == DUK_UNICODE_CP_ZWJ) {
74989 			/* IdentityEscape, with dollar added as a valid additional
74990 			 * non-standard escape (see test-regexp-identity-escape-dollar.js).
74991 			 * Careful not to match end-of-buffer (<0) here.
74992 			 */
74993 			out_token->num = y;
74994 		} else {
74995 			DUK_ERROR_SYNTAX(lex_ctx->thr, "invalid regexp escape");
74996 		}
74997 		break;
74998 	}
74999 	case '(': {
75000 		/* XXX: naming is inconsistent: ATOM_END_GROUP ends an ASSERT_START_LOOKAHEAD */
75001 
75002 		if (y == '?') {
75003 			if (DUK__L2() == '=') {
75004 				/* (?= */
75005 				advtok = DUK__ADVTOK(3, DUK_RETOK_ASSERT_START_POS_LOOKAHEAD);
75006 			} else if (DUK__L2() == '!') {
75007 				/* (?! */
75008 				advtok = DUK__ADVTOK(3, DUK_RETOK_ASSERT_START_NEG_LOOKAHEAD);
75009 			} else if (DUK__L2() == ':') {
75010 				/* (?: */
75011 				advtok = DUK__ADVTOK(3, DUK_RETOK_ATOM_START_NONCAPTURE_GROUP);
75012 			} else {
75013 				DUK_ERROR_SYNTAX(lex_ctx->thr, "invalid regexp group");
75014 				return;
75015 			}
75016 		} else {
75017 			/* ( */
75018 			advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_START_CAPTURE_GROUP);
75019 		}
75020 		break;
75021 	}
75022 	case ')': {
75023 		advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_END_GROUP);
75024 		break;
75025 	}
75026 	case '[': {
75027 		/*
75028 		 *  To avoid creating a heavy intermediate value for the list of ranges,
75029 		 *  only the start token ('[' or '[^') is parsed here.  The regexp
75030 		 *  compiler parses the ranges itself.
75031 		 */
75032 		advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_START_CHARCLASS);
75033 		if (y == '^') {
75034 			advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_START_CHARCLASS_INVERTED);
75035 		}
75036 		break;
75037 	}
75038 #if !defined(DUK_USE_ES6_REGEXP_BRACES)
75039 	case '}':
75040 #endif
75041 	case ']': {
75042 		/* Although these could be parsed as PatternCharacters unambiguously (here),
75043 		 * E5 Section 15.10.1 grammar explicitly forbids these as PatternCharacters.
75044 		 */
75045 		DUK_ERROR_SYNTAX(lex_ctx->thr, "invalid regexp character");
75046 		break;
75047 	}
75048 	case -1: {
75049 		/* EOF */
75050 		advtok = DUK__ADVTOK(0, DUK_TOK_EOF);
75051 		break;
75052 	}
75053 	default: {
75054 		/* PatternCharacter, all excluded characters are matched by cases above */
75055 		advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_CHAR);
75056 		out_token->num = x;
75057 		break;
75058 	}
75059 	}
75060 
75061 	/*
75062 	 *  Shared exit path
75063 	 */
75064 
75065 	DUK__ADVANCEBYTES(lex_ctx, advtok >> 8);
75066 	out_token->t = advtok & 0xff;
75067 }
75068 
75069 /*
75070  *  Special parser for character classes; calls callback for every
75071  *  range parsed and returns the number of ranges present.
75072  */
75073 
75074 /* XXX: this duplicates functionality in duk_regexp.c where a similar loop is
75075  * required anyway.  We could use that BUT we need to update the regexp compiler
75076  * 'nranges' too.  Work this out a bit more cleanly to save space.
75077  */
75078 
75079 /* XXX: the handling of character range detection is a bit convoluted.
75080  * Try to simplify and make smaller.
75081  */
75082 
75083 /* XXX: logic for handling character ranges is now incorrect, it will accept
75084  * e.g. [\d-z] whereas it should croak from it?  SMJS accepts this too, though.
75085  *
75086  * Needs a read through and a lot of additional tests.
75087  */
75088 
75089 DUK_LOCAL
75090 void duk__emit_u16_direct_ranges(duk_lexer_ctx *lex_ctx,
75091                                  duk_re_range_callback gen_range,
75092                                  void *userdata,
75093                                  const duk_uint16_t *ranges,
75094                                  duk_small_int_t num) {
75095 	const duk_uint16_t *ranges_end;
75096 
75097 	DUK_UNREF(lex_ctx);
75098 
75099 	ranges_end = ranges + num;
75100 	while (ranges < ranges_end) {
75101 		/* mark range 'direct', bypass canonicalization (see Wiki) */
75102 		gen_range(userdata, (duk_codepoint_t) ranges[0], (duk_codepoint_t) ranges[1], 1);
75103 		ranges += 2;
75104 	}
75105 }
75106 
75107 DUK_INTERNAL void duk_lexer_parse_re_ranges(duk_lexer_ctx *lex_ctx, duk_re_range_callback gen_range, void *userdata) {
75108 	duk_codepoint_t start = -1;
75109 	duk_codepoint_t ch;
75110 	duk_codepoint_t x;
75111 	duk_bool_t dash = 0;
75112 
75113 	DUK_DD(DUK_DDPRINT("parsing regexp ranges"));
75114 
75115 	for (;;) {
75116 		x = DUK__L0();
75117 		DUK__ADVANCECHARS(lex_ctx, 1);
75118 
75119 		ch = -1;  /* not strictly necessary, but avoids "uninitialized variable" warnings */
75120 		DUK_UNREF(ch);
75121 
75122 		if (x < 0) {
75123 			DUK_ERROR_SYNTAX(lex_ctx->thr, "eof in character class");
75124 		} else if (x == ']') {
75125 			if (start >= 0) {
75126 				gen_range(userdata, start, start, 0);
75127 			}
75128 			break;
75129 		} else if (x == '-') {
75130 			if (start >= 0 && !dash && DUK__L0() != ']') {
75131 				/* '-' as a range indicator */
75132 				dash = 1;
75133 				continue;
75134 			} else {
75135 				/* '-' verbatim */
75136 				ch = x;
75137 			}
75138 		} else if (x == '\\') {
75139 			/*
75140 			 *  The escapes are same as outside a character class, except that \b has a
75141 			 *  different meaning, and \B and backreferences are prohibited (see E5
75142 			 *  Section 15.10.2.19).  However, it's difficult to share code because we
75143 			 *  handle e.g. "\n" very differently: here we generate a single character
75144 			 *  range for it.
75145 			 */
75146 
75147 			x = DUK__L0();
75148 			DUK__ADVANCECHARS(lex_ctx, 1);
75149 
75150 			if (x == 'b') {
75151 				/* Note: '\b' in char class is different than outside (assertion),
75152 				 * '\B' is not allowed and is caught by the duk_unicode_is_identifier_part()
75153 				 * check below.
75154 				 */
75155 				ch = 0x0008;
75156 			} else if (x == 'f') {
75157 				ch = 0x000c;
75158 			} else if (x == 'n') {
75159 				ch = 0x000a;
75160 			} else if (x == 't') {
75161 				ch = 0x0009;
75162 			} else if (x == 'r') {
75163 				ch = 0x000d;
75164 			} else if (x == 'v') {
75165 				ch = 0x000b;
75166 			} else if (x == 'c') {
75167 				x = DUK__L0();
75168 				DUK__ADVANCECHARS(lex_ctx, 1);
75169 				if ((x >= 'a' && x <= 'z') ||
75170 				    (x >= 'A' && x <= 'Z')) {
75171 					ch = (x % 32);
75172 				} else {
75173 					DUK_ERROR_SYNTAX(lex_ctx->thr, "invalid regexp escape");
75174 					return;  /* never reached, but avoids warnings of
75175 					          * potentially unused variables.
75176 					          */
75177 				}
75178 			} else if (x == 'x') {
75179 				ch = duk__decode_hexesc_from_window(lex_ctx, 0);
75180 				DUK__ADVANCECHARS(lex_ctx, 2);
75181 			} else if (x == 'u') {
75182 				ch = duk__decode_uniesc_from_window(lex_ctx, 0);
75183 				DUK__ADVANCECHARS(lex_ctx, 4);
75184 			} else if (x == 'd') {
75185 				duk__emit_u16_direct_ranges(lex_ctx,
75186 				                            gen_range,
75187 				                            userdata,
75188 				                            duk_unicode_re_ranges_digit,
75189 				                            sizeof(duk_unicode_re_ranges_digit) / sizeof(duk_uint16_t));
75190 				ch = -1;
75191 			} else if (x == 'D') {
75192 				duk__emit_u16_direct_ranges(lex_ctx,
75193 				                            gen_range,
75194 				                            userdata,
75195 				                            duk_unicode_re_ranges_not_digit,
75196 				                            sizeof(duk_unicode_re_ranges_not_digit) / sizeof(duk_uint16_t));
75197 				ch = -1;
75198 			} else if (x == 's') {
75199 				duk__emit_u16_direct_ranges(lex_ctx,
75200 				                            gen_range,
75201 				                            userdata,
75202 				                            duk_unicode_re_ranges_white,
75203 				                            sizeof(duk_unicode_re_ranges_white) / sizeof(duk_uint16_t));
75204 				ch = -1;
75205 			} else if (x == 'S') {
75206 				duk__emit_u16_direct_ranges(lex_ctx,
75207 				                            gen_range,
75208 				                            userdata,
75209 				                            duk_unicode_re_ranges_not_white,
75210 				                            sizeof(duk_unicode_re_ranges_not_white) / sizeof(duk_uint16_t));
75211 				ch = -1;
75212 			} else if (x == 'w') {
75213 				duk__emit_u16_direct_ranges(lex_ctx,
75214 				                            gen_range,
75215 				                            userdata,
75216 				                            duk_unicode_re_ranges_wordchar,
75217 				                            sizeof(duk_unicode_re_ranges_wordchar) / sizeof(duk_uint16_t));
75218 				ch = -1;
75219 			} else if (x == 'W') {
75220 				duk__emit_u16_direct_ranges(lex_ctx,
75221 				                            gen_range,
75222 				                            userdata,
75223 				                            duk_unicode_re_ranges_not_wordchar,
75224 				                            sizeof(duk_unicode_re_ranges_not_wordchar) / sizeof(duk_uint16_t));
75225 				ch = -1;
75226 			} else if (DUK__ISDIGIT(x)) {
75227 				/* DecimalEscape, only \0 is allowed, no leading zeroes are allowed */
75228 				if (x == '0' && !DUK__ISDIGIT(DUK__L0())) {
75229 					ch = 0x0000;
75230 				} else {
75231 					DUK_ERROR_SYNTAX(lex_ctx->thr, "invalid regexp escape");
75232 				}
75233 			} else if (!duk_unicode_is_identifier_part(x)
75234 #if defined(DUK_USE_NONSTD_REGEXP_DOLLAR_ESCAPE)
75235 			           || x == '$'
75236 #endif
75237 			          ) {
75238 				/* IdentityEscape */
75239 				ch = x;
75240 			} else {
75241 				DUK_ERROR_SYNTAX(lex_ctx->thr, "invalid regexp escape");
75242 			}
75243 		} else {
75244 			/* character represents itself */
75245 			ch = x;
75246 		}
75247 
75248 		/* ch is a literal character here or -1 if parsed entity was
75249 		 * an escape such as "\s".
75250 		 */
75251 
75252 		if (ch < 0) {
75253 			/* multi-character sets not allowed as part of ranges, see
75254 			 * E5 Section 15.10.2.15, abstract operation CharacterRange.
75255 			 */
75256 			if (start >= 0) {
75257 				if (dash) {
75258 					DUK_ERROR_SYNTAX(lex_ctx->thr, "invalid range");
75259 				} else {
75260 					gen_range(userdata, start, start, 0);
75261 					start = -1;
75262 					/* dash is already 0 */
75263 				}
75264 			}
75265 		} else {
75266 			if (start >= 0) {
75267 				if (dash) {
75268 					if (start > ch) {
75269 						DUK_ERROR_SYNTAX(lex_ctx->thr, "invalid range");
75270 					}
75271 					gen_range(userdata, start, ch, 0);
75272 					start = -1;
75273 					dash = 0;
75274 				} else {
75275 					gen_range(userdata, start, start, 0);
75276 					start = ch;
75277 					/* dash is already 0 */
75278 				}
75279 			} else {
75280 				start = ch;
75281 			}
75282 		}
75283 	}
75284 
75285 	return;
75286 }
75287 
75288 #endif  /* DUK_USE_REGEXP_SUPPORT */
75289 /*
75290  *  Number-to-string and string-to-number conversions.
75291  *
75292  *  Slow path number-to-string and string-to-number conversion is based on
75293  *  a Dragon4 variant, with fast paths for small integers.  Big integer
75294  *  arithmetic is needed for guaranteeing that the conversion is correct
75295  *  and uses a minimum number of digits.  The big number arithmetic has a
75296  *  fixed maximum size and does not require dynamic allocations.
75297  *
75298  *  See: doc/number-conversion.rst.
75299  */
75300 
75301 /* include removed: duk_internal.h */
75302 
75303 #define DUK__IEEE_DOUBLE_EXP_BIAS  1023
75304 #define DUK__IEEE_DOUBLE_EXP_MIN   (-1022)   /* biased exp == 0 -> denormal, exp -1022 */
75305 
75306 #define DUK__DIGITCHAR(x)  duk_lc_digits[(x)]
75307 
75308 /*
75309  *  Tables generated with src/gennumdigits.py.
75310  *
75311  *  duk__str2num_digits_for_radix indicates, for each radix, how many input
75312  *  digits should be considered significant for string-to-number conversion.
75313  *  The input is also padded to this many digits to give the Dragon4
75314  *  conversion enough (apparent) precision to work with.
75315  *
75316  *  duk__str2num_exp_limits indicates, for each radix, the radix-specific
75317  *  minimum/maximum exponent values (for a Dragon4 integer mantissa)
75318  *  below and above which the number is guaranteed to underflow to zero
75319  *  or overflow to Infinity.  This allows parsing to keep bigint values
75320  *  bounded.
75321  */
75322 
75323 DUK_LOCAL const duk_uint8_t duk__str2num_digits_for_radix[] = {
75324 	69, 44, 35, 30, 27, 25, 23, 22, 20, 20,    /* 2 to 11 */
75325 	20, 19, 19, 18, 18, 17, 17, 17, 16, 16,    /* 12 to 21 */
75326 	16, 16, 16, 15, 15, 15, 15, 15, 15, 14,    /* 22 to 31 */
75327 	14, 14, 14, 14, 14                         /* 31 to 36 */
75328 };
75329 
75330 typedef struct {
75331 	duk_int16_t upper;
75332 	duk_int16_t lower;
75333 } duk__exp_limits;
75334 
75335 DUK_LOCAL const duk__exp_limits duk__str2num_exp_limits[] = {
75336 	{ 957, -1147 }, { 605, -725 },  { 479, -575 },  { 414, -496 },
75337 	{ 372, -446 },  { 342, -411 },  { 321, -384 },  { 304, -364 },
75338 	{ 291, -346 },  { 279, -334 },  { 268, -323 },  { 260, -312 },
75339 	{ 252, -304 },  { 247, -296 },  { 240, -289 },  { 236, -283 },
75340 	{ 231, -278 },  { 227, -273 },  { 223, -267 },  { 220, -263 },
75341 	{ 216, -260 },  { 213, -256 },  { 210, -253 },  { 208, -249 },
75342 	{ 205, -246 },  { 203, -244 },  { 201, -241 },  { 198, -239 },
75343 	{ 196, -237 },  { 195, -234 },  { 193, -232 },  { 191, -230 },
75344 	{ 190, -228 },  { 188, -226 },  { 187, -225 },
75345 };
75346 
75347 /*
75348  *  Limited functionality bigint implementation.
75349  *
75350  *  Restricted to non-negative numbers with less than 32 * DUK__BI_MAX_PARTS bits,
75351  *  with the caller responsible for ensuring this is never exceeded.  No memory
75352  *  allocation (except stack) is needed for bigint computation.  Operations
75353  *  have been tailored for number conversion needs.
75354  *
75355  *  Argument order is "assignment order", i.e. target first, then arguments:
75356  *  x <- y * z  -->  duk__bi_mul(x, y, z);
75357  */
75358 
75359 /* This upper value has been experimentally determined; debug build will check
75360  * bigint size with assertions.
75361  */
75362 #define DUK__BI_MAX_PARTS  37  /* 37x32 = 1184 bits */
75363 
75364 #ifdef DUK_USE_DDDPRINT
75365 #define DUK__BI_PRINT(name,x)  duk__bi_print((name),(x))
75366 #else
75367 #define DUK__BI_PRINT(name,x)
75368 #endif
75369 
75370 /* Current size is about 152 bytes. */
75371 typedef struct {
75372 	duk_small_int_t n;
75373 	duk_uint32_t v[DUK__BI_MAX_PARTS];  /* low to high */
75374 } duk__bigint;
75375 
75376 #ifdef DUK_USE_DDDPRINT
75377 DUK_LOCAL void duk__bi_print(const char *name, duk__bigint *x) {
75378 	/* Overestimate required size; debug code so not critical to be tight. */
75379 	char buf[DUK__BI_MAX_PARTS * 9 + 64];
75380 	char *p = buf;
75381 	duk_small_int_t i;
75382 
75383 	/* No NUL term checks in this debug code. */
75384 	p += DUK_SPRINTF(p, "%p n=%ld", (void *) x, (long) x->n);
75385 	if (x->n == 0) {
75386 		p += DUK_SPRINTF(p, " 0");
75387 	}
75388 	for (i = x->n - 1; i >= 0; i--) {
75389 		p += DUK_SPRINTF(p, " %08lx", (unsigned long) x->v[i]);
75390 	}
75391 
75392 	DUK_DDD(DUK_DDDPRINT("%s: %s", (const char *) name, (const char *) buf));
75393 }
75394 #endif
75395 
75396 #ifdef DUK_USE_ASSERTIONS
75397 DUK_LOCAL duk_small_int_t duk__bi_is_valid(duk__bigint *x) {
75398 	return (duk_small_int_t)
75399 	       ( ((x->n >= 0) && (x->n <= DUK__BI_MAX_PARTS)) /* is valid size */ &&
75400 	         ((x->n == 0) || (x->v[x->n - 1] != 0)) /* is normalized */ );
75401 }
75402 #endif
75403 
75404 DUK_LOCAL void duk__bi_normalize(duk__bigint *x) {
75405 	duk_small_int_t i;
75406 
75407 	for (i = x->n - 1; i >= 0; i--) {
75408 		if (x->v[i] != 0) {
75409 			break;
75410 		}
75411 	}
75412 
75413 	/* Note: if 'x' is zero, x->n becomes 0 here */
75414 	x->n = i + 1;
75415 	DUK_ASSERT(duk__bi_is_valid(x));
75416 }
75417 
75418 /* x <- y */
75419 DUK_LOCAL void duk__bi_copy(duk__bigint *x, duk__bigint *y) {
75420 	duk_small_int_t n;
75421 
75422 	n = y->n;
75423 	x->n = n;
75424 	if (n == 0) {
75425 		return;
75426 	}
75427 	DUK_MEMCPY((void *) x->v, (const void *) y->v, (size_t) (sizeof(duk_uint32_t) * n));
75428 }
75429 
75430 DUK_LOCAL void duk__bi_set_small(duk__bigint *x, duk_uint32_t v) {
75431 	if (v == 0U) {
75432 		x->n = 0;
75433 	} else {
75434 		x->n = 1;
75435 		x->v[0] = v;
75436 	}
75437 	DUK_ASSERT(duk__bi_is_valid(x));
75438 }
75439 
75440 /* Return value: <0  <=>  x < y
75441  *                0  <=>  x == y
75442  *               >0  <=>  x > y
75443  */
75444 DUK_LOCAL int duk__bi_compare(duk__bigint *x, duk__bigint *y) {
75445 	duk_small_int_t i, nx, ny;
75446 	duk_uint32_t tx, ty;
75447 
75448 	DUK_ASSERT(duk__bi_is_valid(x));
75449 	DUK_ASSERT(duk__bi_is_valid(y));
75450 
75451 	nx = x->n;
75452 	ny = y->n;
75453 	if (nx > ny) {
75454 		goto ret_gt;
75455 	}
75456 	if (nx < ny) {
75457 		goto ret_lt;
75458 	}
75459 	for (i = nx - 1; i >= 0; i--) {
75460 		tx = x->v[i];
75461 		ty = y->v[i];
75462 
75463 		if (tx > ty) {
75464 			goto ret_gt;
75465 		}
75466 		if (tx < ty) {
75467 			goto ret_lt;
75468 		}
75469 	}
75470 
75471 	return 0;
75472 
75473  ret_gt:
75474 	return 1;
75475 
75476  ret_lt:
75477 	return -1;
75478 }
75479 
75480 /* x <- y + z */
75481 #ifdef DUK_USE_64BIT_OPS
75482 DUK_LOCAL void duk__bi_add(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
75483 	duk_uint64_t tmp;
75484 	duk_small_int_t i, ny, nz;
75485 
75486 	DUK_ASSERT(duk__bi_is_valid(y));
75487 	DUK_ASSERT(duk__bi_is_valid(z));
75488 
75489 	if (z->n > y->n) {
75490 		duk__bigint *t;
75491 		t = y; y = z; z = t;
75492 	}
75493 	DUK_ASSERT(y->n >= z->n);
75494 
75495 	ny = y->n; nz = z->n;
75496 	tmp = 0U;
75497 	for (i = 0; i < ny; i++) {
75498 		DUK_ASSERT(i < DUK__BI_MAX_PARTS);
75499 		tmp += y->v[i];
75500 		if (i < nz) {
75501 			tmp += z->v[i];
75502 		}
75503 		x->v[i] = (duk_uint32_t) (tmp & 0xffffffffUL);
75504 		tmp = tmp >> 32;
75505 	}
75506 	if (tmp != 0U) {
75507 		DUK_ASSERT(i < DUK__BI_MAX_PARTS);
75508 		x->v[i++] = (duk_uint32_t) tmp;
75509 	}
75510 	x->n = i;
75511 	DUK_ASSERT(x->n <= DUK__BI_MAX_PARTS);
75512 
75513 	/* no need to normalize */
75514 	DUK_ASSERT(duk__bi_is_valid(x));
75515 }
75516 #else  /* DUK_USE_64BIT_OPS */
75517 DUK_LOCAL void duk__bi_add(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
75518 	duk_uint32_t carry, tmp1, tmp2;
75519 	duk_small_int_t i, ny, nz;
75520 
75521 	DUK_ASSERT(duk__bi_is_valid(y));
75522 	DUK_ASSERT(duk__bi_is_valid(z));
75523 
75524 	if (z->n > y->n) {
75525 		duk__bigint *t;
75526 		t = y; y = z; z = t;
75527 	}
75528 	DUK_ASSERT(y->n >= z->n);
75529 
75530 	ny = y->n; nz = z->n;
75531 	carry = 0U;
75532 	for (i = 0; i < ny; i++) {
75533 		/* Carry is detected based on wrapping which relies on exact 32-bit
75534 		 * types.
75535 		 */
75536 		DUK_ASSERT(i < DUK__BI_MAX_PARTS);
75537 		tmp1 = y->v[i];
75538 		tmp2 = tmp1;
75539 		if (i < nz) {
75540 			tmp2 += z->v[i];
75541 		}
75542 
75543 		/* Careful with carry condition:
75544 		 *  - If carry not added: 0x12345678 + 0 + 0xffffffff = 0x12345677 (< 0x12345678)
75545 		 *  - If carry added:     0x12345678 + 1 + 0xffffffff = 0x12345678 (== 0x12345678)
75546 		 */
75547 		if (carry) {
75548 			tmp2++;
75549 			carry = (tmp2 <= tmp1 ? 1U : 0U);
75550 		} else {
75551 			carry = (tmp2 < tmp1 ? 1U : 0U);
75552 		}
75553 
75554 		x->v[i] = tmp2;
75555 	}
75556 	if (carry) {
75557 		DUK_ASSERT(i < DUK__BI_MAX_PARTS);
75558 		DUK_ASSERT(carry == 1U);
75559 		x->v[i++] = carry;
75560 	}
75561 	x->n = i;
75562 	DUK_ASSERT(x->n <= DUK__BI_MAX_PARTS);
75563 
75564 	/* no need to normalize */
75565 	DUK_ASSERT(duk__bi_is_valid(x));
75566 }
75567 #endif  /* DUK_USE_64BIT_OPS */
75568 
75569 /* x <- y + z */
75570 DUK_LOCAL void duk__bi_add_small(duk__bigint *x, duk__bigint *y, duk_uint32_t z) {
75571 	duk__bigint tmp;
75572 
75573 	DUK_ASSERT(duk__bi_is_valid(y));
75574 
75575 	/* XXX: this could be optimized; there is only one call site now though */
75576 	duk__bi_set_small(&tmp, z);
75577 	duk__bi_add(x, y, &tmp);
75578 
75579 	DUK_ASSERT(duk__bi_is_valid(x));
75580 }
75581 
75582 #if 0  /* unused */
75583 /* x <- x + y, use t as temp */
75584 DUK_LOCAL void duk__bi_add_copy(duk__bigint *x, duk__bigint *y, duk__bigint *t) {
75585 	duk__bi_add(t, x, y);
75586 	duk__bi_copy(x, t);
75587 }
75588 #endif
75589 
75590 /* x <- y - z, require x >= y => z >= 0, i.e. y >= z */
75591 #ifdef DUK_USE_64BIT_OPS
75592 DUK_LOCAL void duk__bi_sub(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
75593 	duk_small_int_t i, ny, nz;
75594 	duk_uint32_t ty, tz;
75595 	duk_int64_t tmp;
75596 
75597 	DUK_ASSERT(duk__bi_is_valid(y));
75598 	DUK_ASSERT(duk__bi_is_valid(z));
75599 	DUK_ASSERT(duk__bi_compare(y, z) >= 0);
75600 	DUK_ASSERT(y->n >= z->n);
75601 
75602 	ny = y->n; nz = z->n;
75603 	tmp = 0;
75604 	for (i = 0; i < ny; i++) {
75605 		ty = y->v[i];
75606 		if (i < nz) {
75607 			tz = z->v[i];
75608 		} else {
75609 			tz = 0;
75610 		}
75611 		tmp = (duk_int64_t) ty - (duk_int64_t) tz + tmp;
75612 		x->v[i] = (duk_uint32_t) (tmp & 0xffffffffUL);
75613 		tmp = tmp >> 32;  /* 0 or -1 */
75614 	}
75615 	DUK_ASSERT(tmp == 0);
75616 
75617 	x->n = i;
75618 	duk__bi_normalize(x);  /* need to normalize, may even cancel to 0 */
75619 	DUK_ASSERT(duk__bi_is_valid(x));
75620 }
75621 #else
75622 DUK_LOCAL void duk__bi_sub(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
75623 	duk_small_int_t i, ny, nz;
75624 	duk_uint32_t tmp1, tmp2, borrow;
75625 
75626 	DUK_ASSERT(duk__bi_is_valid(y));
75627 	DUK_ASSERT(duk__bi_is_valid(z));
75628 	DUK_ASSERT(duk__bi_compare(y, z) >= 0);
75629 	DUK_ASSERT(y->n >= z->n);
75630 
75631 	ny = y->n; nz = z->n;
75632 	borrow = 0U;
75633 	for (i = 0; i < ny; i++) {
75634 		/* Borrow is detected based on wrapping which relies on exact 32-bit
75635 		 * types.
75636 		 */
75637 		tmp1 = y->v[i];
75638 		tmp2 = tmp1;
75639 		if (i < nz) {
75640 			tmp2 -= z->v[i];
75641 		}
75642 
75643 		/* Careful with borrow condition:
75644 		 *  - If borrow not subtracted: 0x12345678 - 0 - 0xffffffff = 0x12345679 (> 0x12345678)
75645 		 *  - If borrow subtracted:     0x12345678 - 1 - 0xffffffff = 0x12345678 (== 0x12345678)
75646 		 */
75647 		if (borrow) {
75648 			tmp2--;
75649 			borrow = (tmp2 >= tmp1 ? 1U : 0U);
75650 		} else {
75651 			borrow = (tmp2 > tmp1 ? 1U : 0U);
75652 		}
75653 
75654 		x->v[i] = tmp2;
75655 	}
75656 	DUK_ASSERT(borrow == 0U);
75657 
75658 	x->n = i;
75659 	duk__bi_normalize(x);  /* need to normalize, may even cancel to 0 */
75660 	DUK_ASSERT(duk__bi_is_valid(x));
75661 }
75662 #endif
75663 
75664 #if 0  /* unused */
75665 /* x <- y - z */
75666 DUK_LOCAL void duk__bi_sub_small(duk__bigint *x, duk__bigint *y, duk_uint32_t z) {
75667 	duk__bigint tmp;
75668 
75669 	DUK_ASSERT(duk__bi_is_valid(y));
75670 
75671 	/* XXX: this could be optimized */
75672 	duk__bi_set_small(&tmp, z);
75673 	duk__bi_sub(x, y, &tmp);
75674 
75675 	DUK_ASSERT(duk__bi_is_valid(x));
75676 }
75677 #endif
75678 
75679 /* x <- x - y, use t as temp */
75680 DUK_LOCAL void duk__bi_sub_copy(duk__bigint *x, duk__bigint *y, duk__bigint *t) {
75681 	duk__bi_sub(t, x, y);
75682 	duk__bi_copy(x, t);
75683 }
75684 
75685 /* x <- y * z */
75686 DUK_LOCAL void duk__bi_mul(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
75687 	duk_small_int_t i, j, nx, nz;
75688 
75689 	DUK_ASSERT(duk__bi_is_valid(y));
75690 	DUK_ASSERT(duk__bi_is_valid(z));
75691 
75692 	nx = y->n + z->n;  /* max possible */
75693 	DUK_ASSERT(nx <= DUK__BI_MAX_PARTS);
75694 
75695 	if (nx == 0) {
75696 		/* Both inputs are zero; cases where only one is zero can go
75697 		 * through main algorithm.
75698 		 */
75699 		x->n = 0;
75700 		return;
75701 	}
75702 
75703 	DUK_MEMZERO((void *) x->v, (size_t) (sizeof(duk_uint32_t) * nx));
75704 	x->n = nx;
75705 
75706 	nz = z->n;
75707 	for (i = 0; i < y->n; i++) {
75708 #ifdef DUK_USE_64BIT_OPS
75709 		duk_uint64_t tmp = 0U;
75710 		for (j = 0; j < nz; j++) {
75711 			tmp += (duk_uint64_t) y->v[i] * (duk_uint64_t) z->v[j] + x->v[i+j];
75712 			x->v[i+j] = (duk_uint32_t) (tmp & 0xffffffffUL);
75713 			tmp = tmp >> 32;
75714 		}
75715 		if (tmp > 0) {
75716 			DUK_ASSERT(i + j < nx);
75717 			DUK_ASSERT(i + j < DUK__BI_MAX_PARTS);
75718 			DUK_ASSERT(x->v[i+j] == 0U);
75719 			x->v[i+j] = (duk_uint32_t) tmp;
75720 		}
75721 #else
75722 		/*
75723 		 *  Multiply + add + carry for 32-bit components using only 16x16->32
75724 		 *  multiplies and carry detection based on unsigned overflow.
75725 		 *
75726 		 *    1st mult, 32-bit: (A*2^16 + B)
75727 		 *    2nd mult, 32-bit: (C*2^16 + D)
75728 		 *    3rd add, 32-bit: E
75729 		 *    4th add, 32-bit: F
75730 		 *
75731 		 *      (AC*2^16 + B) * (C*2^16 + D) + E + F
75732 		 *    = AC*2^32 + AD*2^16 + BC*2^16 + BD + E + F
75733 		 *    = AC*2^32 + (AD + BC)*2^16 + (BD + E + F)
75734 		 *    = AC*2^32 + AD*2^16 + BC*2^16 + (BD + E + F)
75735 		 */
75736 		duk_uint32_t a, b, c, d, e, f;
75737 		duk_uint32_t r, s, t;
75738 
75739 		a = y->v[i]; b = a & 0xffffUL; a = a >> 16;
75740 
75741 		f = 0;
75742 		for (j = 0; j < nz; j++) {
75743 			c = z->v[j]; d = c & 0xffffUL; c = c >> 16;
75744 			e = x->v[i+j];
75745 
75746 			/* build result as: (r << 32) + s: start with (BD + E + F) */
75747 			r = 0;
75748 			s = b * d;
75749 
75750 			/* add E */
75751 			t = s + e;
75752 			if (t < s) { r++; }  /* carry */
75753 			s = t;
75754 
75755 			/* add F */
75756 			t = s + f;
75757 			if (t < s) { r++; }  /* carry */
75758 			s = t;
75759 
75760 			/* add BC*2^16 */
75761 			t = b * c;
75762 			r += (t >> 16);
75763 			t = s + ((t & 0xffffUL) << 16);
75764 			if (t < s) { r++; }  /* carry */
75765 			s = t;
75766 
75767 			/* add AD*2^16 */
75768 			t = a * d;
75769 			r += (t >> 16);
75770 			t = s + ((t & 0xffffUL) << 16);
75771 			if (t < s) { r++; }  /* carry */
75772 			s = t;
75773 
75774 			/* add AC*2^32 */
75775 			t = a * c;
75776 			r += t;
75777 
75778 			DUK_DDD(DUK_DDDPRINT("ab=%08lx cd=%08lx ef=%08lx -> rs=%08lx %08lx",
75779 			                     (unsigned long) y->v[i], (unsigned long) z->v[j],
75780 			                     (unsigned long) x->v[i+j], (unsigned long) r,
75781 			                     (unsigned long) s));
75782 
75783 			x->v[i+j] = s;
75784 			f = r;
75785 		}
75786 		if (f > 0U) {
75787 			DUK_ASSERT(i + j < nx);
75788 			DUK_ASSERT(i + j < DUK__BI_MAX_PARTS);
75789 			DUK_ASSERT(x->v[i+j] == 0U);
75790 			x->v[i+j] = (duk_uint32_t) f;
75791 		}
75792 #endif  /* DUK_USE_64BIT_OPS */
75793 	}
75794 
75795 	duk__bi_normalize(x);
75796 	DUK_ASSERT(duk__bi_is_valid(x));
75797 }
75798 
75799 /* x <- y * z */
75800 DUK_LOCAL void duk__bi_mul_small(duk__bigint *x, duk__bigint *y, duk_uint32_t z) {
75801 	duk__bigint tmp;
75802 
75803 	DUK_ASSERT(duk__bi_is_valid(y));
75804 
75805 	/* XXX: this could be optimized */
75806 	duk__bi_set_small(&tmp, z);
75807 	duk__bi_mul(x, y, &tmp);
75808 
75809 	DUK_ASSERT(duk__bi_is_valid(x));
75810 }
75811 
75812 /* x <- x * y, use t as temp */
75813 DUK_LOCAL void duk__bi_mul_copy(duk__bigint *x, duk__bigint *y, duk__bigint *t) {
75814 	duk__bi_mul(t, x, y);
75815 	duk__bi_copy(x, t);
75816 }
75817 
75818 /* x <- x * y, use t as temp */
75819 DUK_LOCAL void duk__bi_mul_small_copy(duk__bigint *x, duk_uint32_t y, duk__bigint *t) {
75820 	duk__bi_mul_small(t, x, y);
75821 	duk__bi_copy(x, t);
75822 }
75823 
75824 DUK_LOCAL int duk__bi_is_even(duk__bigint *x) {
75825 	DUK_ASSERT(duk__bi_is_valid(x));
75826 	return (x->n == 0) || ((x->v[0] & 0x01) == 0);
75827 }
75828 
75829 DUK_LOCAL int duk__bi_is_zero(duk__bigint *x) {
75830 	DUK_ASSERT(duk__bi_is_valid(x));
75831 	return (x->n == 0);  /* this is the case for normalized numbers */
75832 }
75833 
75834 /* Bigint is 2^52.  Used to detect normalized IEEE double mantissa values
75835  * which are at the lowest edge (next floating point value downwards has
75836  * a different exponent).  The lowest mantissa has the form:
75837  *
75838  *     1000........000    (52 zeroes; only "hidden bit" is set)
75839  */
75840 DUK_LOCAL duk_small_int_t duk__bi_is_2to52(duk__bigint *x) {
75841 	DUK_ASSERT(duk__bi_is_valid(x));
75842 	return (duk_small_int_t)
75843 	        (x->n == 2) && (x->v[0] == 0U) && (x->v[1] == (1U << (52-32)));
75844 }
75845 
75846 /* x <- (1<<y) */
75847 DUK_LOCAL void duk__bi_twoexp(duk__bigint *x, duk_small_int_t y) {
75848 	duk_small_int_t n, r;
75849 
75850 	n = (y / 32) + 1;
75851 	DUK_ASSERT(n > 0);
75852 	r = y % 32;
75853 	DUK_MEMZERO((void *) x->v, sizeof(duk_uint32_t) * n);
75854 	x->n = n;
75855 	x->v[n - 1] = (((duk_uint32_t) 1) << r);
75856 }
75857 
75858 /* x <- b^y; use t1 and t2 as temps */
75859 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) {
75860 	/* Fast path the binary case */
75861 
75862 	DUK_ASSERT(x != t1 && x != t2 && t1 != t2);  /* distinct bignums, easy mistake to make */
75863 	DUK_ASSERT(b >= 0);
75864 	DUK_ASSERT(y >= 0);
75865 
75866 	if (b == 2) {
75867 		duk__bi_twoexp(x, y);
75868 		return;
75869 	}
75870 
75871 	/* http://en.wikipedia.org/wiki/Exponentiation_by_squaring */
75872 
75873 	DUK_DDD(DUK_DDDPRINT("exp_small: b=%ld, y=%ld", (long) b, (long) y));
75874 
75875 	duk__bi_set_small(x, 1);
75876 	duk__bi_set_small(t1, b);
75877 	for (;;) {
75878 		/* Loop structure ensures that we don't compute t1^2 unnecessarily
75879 		 * on the final round, as that might create a bignum exceeding the
75880 		 * current DUK__BI_MAX_PARTS limit.
75881 		 */
75882 		if (y & 0x01) {
75883 			duk__bi_mul_copy(x, t1, t2);
75884 		}
75885 		y = y >> 1;
75886 		if (y == 0) {
75887 			break;
75888 		}
75889 		duk__bi_mul_copy(t1, t1, t2);
75890 	}
75891 
75892 	DUK__BI_PRINT("exp_small result", x);
75893 }
75894 
75895 /*
75896  *  A Dragon4 number-to-string variant, based on:
75897  *
75898  *    Guy L. Steele Jr., Jon L. White: "How to Print Floating-Point Numbers
75899  *    Accurately"
75900  *
75901  *    Robert G. Burger, R. Kent Dybvig: "Printing Floating-Point Numbers
75902  *    Quickly and Accurately"
75903  *
75904  *  The current algorithm is based on Figure 1 of the Burger-Dybvig paper,
75905  *  i.e. the base implementation without logarithm estimation speedups
75906  *  (these would increase code footprint considerably).  Fixed-format output
75907  *  does not follow the suggestions in the paper; instead, we generate an
75908  *  extra digit and round-with-carry.
75909  *
75910  *  The same algorithm is used for number parsing (with b=10 and B=2)
75911  *  by generating one extra digit and doing rounding manually.
75912  *
75913  *  See doc/number-conversion.rst for limitations.
75914  */
75915 
75916 /* Maximum number of digits generated. */
75917 #define DUK__MAX_OUTPUT_DIGITS          1040  /* (Number.MAX_VALUE).toString(2).length == 1024, + spare */
75918 
75919 /* Maximum number of characters in formatted value. */
75920 #define DUK__MAX_FORMATTED_LENGTH       1040  /* (-Number.MAX_VALUE).toString(2).length == 1025, + spare */
75921 
75922 /* Number and (minimum) size of bigints in the nc_ctx structure. */
75923 #define DUK__NUMCONV_CTX_NUM_BIGINTS    7
75924 #define DUK__NUMCONV_CTX_BIGINTS_SIZE   (sizeof(duk__bigint) * DUK__NUMCONV_CTX_NUM_BIGINTS)
75925 
75926 typedef struct {
75927 	/* Currently about 7*152 = 1064 bytes.  The space for these
75928 	 * duk__bigints is used also as a temporary buffer for generating
75929 	 * the final string.  This is a bit awkard; a union would be
75930 	 * more correct.
75931 	 */
75932 	duk__bigint f, r, s, mp, mm, t1, t2;
75933 
75934 	duk_small_int_t is_s2n;        /* if 1, doing a string-to-number; else doing a number-to-string */
75935 	duk_small_int_t is_fixed;      /* if 1, doing a fixed format output (not free format) */
75936 	duk_small_int_t req_digits;    /* requested number of output digits; 0 = free-format */
75937 	duk_small_int_t abs_pos;       /* digit position is absolute, not relative */
75938 	duk_small_int_t e;             /* exponent for 'f' */
75939 	duk_small_int_t b;             /* input radix */
75940 	duk_small_int_t B;             /* output radix */
75941 	duk_small_int_t k;             /* see algorithm */
75942 	duk_small_int_t low_ok;        /* see algorithm */
75943 	duk_small_int_t high_ok;       /* see algorithm */
75944 	duk_small_int_t unequal_gaps;  /* m+ != m- (very rarely) */
75945 
75946 	/* Buffer used for generated digits, values are in the range [0,B-1]. */
75947 	duk_uint8_t digits[DUK__MAX_OUTPUT_DIGITS];
75948 	duk_small_int_t count;  /* digit count */
75949 } duk__numconv_stringify_ctx;
75950 
75951 /* Note: computes with 'idx' in assertions, so caller beware.
75952  * 'idx' is preincremented, i.e. '1' on first call, because it
75953  * is more convenient for the caller.
75954  */
75955 #define DUK__DRAGON4_OUTPUT_PREINC(nc_ctx,preinc_idx,x)  do { \
75956 		DUK_ASSERT((preinc_idx) - 1 >= 0); \
75957 		DUK_ASSERT((preinc_idx) - 1 < DUK__MAX_OUTPUT_DIGITS); \
75958 		((nc_ctx)->digits[(preinc_idx) - 1]) = (duk_uint8_t) (x); \
75959 	} while (0)
75960 
75961 DUK_LOCAL duk_size_t duk__dragon4_format_uint32(duk_uint8_t *buf, duk_uint32_t x, duk_small_int_t radix) {
75962 	duk_uint8_t *p;
75963 	duk_size_t len;
75964 	duk_small_int_t dig;
75965 	duk_small_int_t t;
75966 
75967 	DUK_ASSERT(radix >= 2 && radix <= 36);
75968 
75969 	/* A 32-bit unsigned integer formats to at most 32 digits (the
75970 	 * worst case happens with radix == 2).  Output the digits backwards,
75971 	 * and use a memmove() to get them in the right place.
75972 	 */
75973 
75974 	p = buf + 32;
75975 	for (;;) {
75976 		t = x / radix;
75977 		dig = x - t * radix;
75978 		x = t;
75979 
75980 		DUK_ASSERT(dig >= 0 && dig < 36);
75981 		*(--p) = DUK__DIGITCHAR(dig);
75982 
75983 		if (x == 0) {
75984 			break;
75985 		}
75986 	}
75987 	len = (duk_size_t) ((buf + 32) - p);
75988 
75989 	DUK_MEMMOVE((void *) buf, (const void *) p, (size_t) len);
75990 
75991 	return len;
75992 }
75993 
75994 DUK_LOCAL void duk__dragon4_prepare(duk__numconv_stringify_ctx *nc_ctx) {
75995 	duk_small_int_t lowest_mantissa;
75996 
75997 #if 1
75998 	/* Assume IEEE round-to-even, so that shorter encoding can be used
75999 	 * when round-to-even would produce correct result.  By removing
76000 	 * this check (and having low_ok == high_ok == 0) the results would
76001 	 * still be accurate but in some cases longer than necessary.
76002 	 */
76003 	if (duk__bi_is_even(&nc_ctx->f)) {
76004 		DUK_DDD(DUK_DDDPRINT("f is even"));
76005 		nc_ctx->low_ok = 1;
76006 		nc_ctx->high_ok = 1;
76007 	} else {
76008 		DUK_DDD(DUK_DDDPRINT("f is odd"));
76009 		nc_ctx->low_ok = 0;
76010 		nc_ctx->high_ok = 0;
76011 	}
76012 #else
76013 	/* Note: not honoring round-to-even should work but now generates incorrect
76014 	 * results.  For instance, 1e23 serializes to "a000...", i.e. the first digit
76015 	 * equals the radix (10).  Scaling stops one step too early in this case.
76016 	 * Don't know why this is the case, but since this code path is unused, it
76017 	 * doesn't matter.
76018 	 */
76019 	nc_ctx->low_ok = 0;
76020 	nc_ctx->high_ok = 0;
76021 #endif
76022 
76023 	/* For string-to-number, pretend we never have the lowest mantissa as there
76024 	 * is no natural "precision" for inputs.  Having lowest_mantissa == 0, we'll
76025 	 * fall into the base cases for both e >= 0 and e < 0.
76026 	 */
76027 	if (nc_ctx->is_s2n) {
76028 		lowest_mantissa = 0;
76029 	} else {
76030 		lowest_mantissa = duk__bi_is_2to52(&nc_ctx->f);
76031 	}
76032 
76033 	nc_ctx->unequal_gaps = 0;
76034 	if (nc_ctx->e >= 0) {
76035 		/* exponent non-negative (and thus not minimum exponent) */
76036 
76037 		if (lowest_mantissa) {
76038 			/* (>= e 0) AND (= f (expt b (- p 1)))
76039 			 *
76040 			 * be <- (expt b e) == b^e
76041 			 * be1 <- (* be b) == (expt b (+ e 1)) == b^(e+1)
76042 			 * r <- (* f be1 2) == 2 * f * b^(e+1)    [if b==2 -> f * b^(e+2)]
76043 			 * s <- (* b 2)                           [if b==2 -> 4]
76044 			 * m+ <- be1 == b^(e+1)
76045 			 * m- <- be == b^e
76046 			 * k <- 0
76047 			 * B <- B
76048 			 * low_ok <- round
76049 			 * high_ok <- round
76050 			 */
76051 
76052 			DUK_DDD(DUK_DDDPRINT("non-negative exponent (not smallest exponent); "
76053 			                     "lowest mantissa value for this exponent -> "
76054 			                     "unequal gaps"));
76055 
76056 			duk__bi_exp_small(&nc_ctx->mm, nc_ctx->b, nc_ctx->e, &nc_ctx->t1, &nc_ctx->t2);  /* mm <- b^e */
76057 			duk__bi_mul_small(&nc_ctx->mp, &nc_ctx->mm, nc_ctx->b);  /* mp <- b^(e+1) */
76058 			duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->f, 2);
76059 			duk__bi_mul(&nc_ctx->r, &nc_ctx->t1, &nc_ctx->mp);       /* r <- (2 * f) * b^(e+1) */
76060 			duk__bi_set_small(&nc_ctx->s, nc_ctx->b * 2);            /* s <- 2 * b */
76061 			nc_ctx->unequal_gaps = 1;
76062 		} else {
76063 			/* (>= e 0) AND (not (= f (expt b (- p 1))))
76064 			 *
76065 			 * be <- (expt b e) == b^e
76066 			 * r <- (* f be 2) == 2 * f * b^e    [if b==2 -> f * b^(e+1)]
76067 			 * s <- 2
76068 			 * m+ <- be == b^e
76069 			 * m- <- be == b^e
76070 			 * k <- 0
76071 			 * B <- B
76072 			 * low_ok <- round
76073 			 * high_ok <- round
76074 			 */
76075 
76076 			DUK_DDD(DUK_DDDPRINT("non-negative exponent (not smallest exponent); "
76077 			                     "not lowest mantissa for this exponent -> "
76078 			                     "equal gaps"));
76079 
76080 			duk__bi_exp_small(&nc_ctx->mm, nc_ctx->b, nc_ctx->e, &nc_ctx->t1, &nc_ctx->t2);  /* mm <- b^e */
76081 			duk__bi_copy(&nc_ctx->mp, &nc_ctx->mm);                /* mp <- b^e */
76082 			duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->f, 2);
76083 			duk__bi_mul(&nc_ctx->r, &nc_ctx->t1, &nc_ctx->mp);     /* r <- (2 * f) * b^e */
76084 			duk__bi_set_small(&nc_ctx->s, 2);                      /* s <- 2 */
76085 		}
76086 	} else {
76087 		/* When doing string-to-number, lowest_mantissa is always 0 so
76088 		 * the exponent check, while incorrect, won't matter.
76089 		 */
76090 		if (nc_ctx->e > DUK__IEEE_DOUBLE_EXP_MIN /*not minimum exponent*/ &&
76091 		    lowest_mantissa /* lowest mantissa for this exponent*/) {
76092 			/* r <- (* f b 2)                                [if b==2 -> (* f 4)]
76093 			 * s <- (* (expt b (- 1 e)) 2) == b^(1-e) * 2    [if b==2 -> b^(2-e)]
76094 			 * m+ <- b == 2
76095 			 * m- <- 1
76096 			 * k <- 0
76097 			 * B <- B
76098 			 * low_ok <- round
76099 			 * high_ok <- round
76100 			 */
76101 
76102 			DUK_DDD(DUK_DDDPRINT("negative exponent; not minimum exponent and "
76103 			                     "lowest mantissa for this exponent -> "
76104 			                     "unequal gaps"));
76105 
76106 			duk__bi_mul_small(&nc_ctx->r, &nc_ctx->f, nc_ctx->b * 2);  /* r <- (2 * b) * f */
76107 			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 */
76108 			duk__bi_mul_small(&nc_ctx->s, &nc_ctx->t1, 2);             /* s <- b^(1-e) * 2 */
76109 			duk__bi_set_small(&nc_ctx->mp, 2);
76110 			duk__bi_set_small(&nc_ctx->mm, 1);
76111 			nc_ctx->unequal_gaps = 1;
76112 		} else {
76113 			/* r <- (* f 2)
76114 			 * s <- (* (expt b (- e)) 2) == b^(-e) * 2    [if b==2 -> b^(1-e)]
76115 			 * m+ <- 1
76116 			 * m- <- 1
76117 			 * k <- 0
76118 			 * B <- B
76119 			 * low_ok <- round
76120 			 * high_ok <- round
76121 			 */
76122 
76123 			DUK_DDD(DUK_DDDPRINT("negative exponent; minimum exponent or not "
76124 			                     "lowest mantissa for this exponent -> "
76125 			                     "equal gaps"));
76126 
76127 			duk__bi_mul_small(&nc_ctx->r, &nc_ctx->f, 2);            /* r <- 2 * f */
76128 			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 */
76129 			duk__bi_mul_small(&nc_ctx->s, &nc_ctx->t1, 2);           /* s <- b^(-e) * 2 */
76130 			duk__bi_set_small(&nc_ctx->mp, 1);
76131 			duk__bi_set_small(&nc_ctx->mm, 1);
76132 		}
76133 	}
76134 }
76135 
76136 DUK_LOCAL void duk__dragon4_scale(duk__numconv_stringify_ctx *nc_ctx) {
76137 	duk_small_int_t k = 0;
76138 
76139 	/* This is essentially the 'scale' algorithm, with recursion removed.
76140 	 * Note that 'k' is either correct immediately, or will move in one
76141 	 * direction in the loop.  There's no need to do the low/high checks
76142 	 * on every round (like the Scheme algorithm does).
76143 	 *
76144 	 * The scheme algorithm finds 'k' and updates 's' simultaneously,
76145 	 * while the logical algorithm finds 'k' with 's' having its initial
76146 	 * value, after which 's' is updated separately (see the Burger-Dybvig
76147 	 * paper, Section 3.1, steps 2 and 3).
76148 	 *
76149 	 * The case where m+ == m- (almost always) is optimized for, because
76150 	 * it reduces the bigint operations considerably and almost always
76151 	 * applies.  The scale loop only needs to work with m+, so this works.
76152 	 */
76153 
76154 	/* XXX: this algorithm could be optimized quite a lot by using e.g.
76155 	 * a logarithm based estimator for 'k' and performing B^n multiplication
76156 	 * using a lookup table or using some bit-representation based exp
76157 	 * algorithm.  Currently we just loop, with significant performance
76158 	 * impact for very large and very small numbers.
76159 	 */
76160 
76161 	DUK_DDD(DUK_DDDPRINT("scale: B=%ld, low_ok=%ld, high_ok=%ld",
76162 	                     (long) nc_ctx->B, (long) nc_ctx->low_ok, (long) nc_ctx->high_ok));
76163 	DUK__BI_PRINT("r(init)", &nc_ctx->r);
76164 	DUK__BI_PRINT("s(init)", &nc_ctx->s);
76165 	DUK__BI_PRINT("mp(init)", &nc_ctx->mp);
76166 	DUK__BI_PRINT("mm(init)", &nc_ctx->mm);
76167 
76168 	for (;;) {
76169 		DUK_DDD(DUK_DDDPRINT("scale loop (inc k), k=%ld", (long) k));
76170 		DUK__BI_PRINT("r", &nc_ctx->r);
76171 		DUK__BI_PRINT("s", &nc_ctx->s);
76172 		DUK__BI_PRINT("m+", &nc_ctx->mp);
76173 		DUK__BI_PRINT("m-", &nc_ctx->mm);
76174 
76175 		duk__bi_add(&nc_ctx->t1, &nc_ctx->r, &nc_ctx->mp);  /* t1 = (+ r m+) */
76176 		if (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) >= (nc_ctx->high_ok ? 0 : 1)) {
76177 			DUK_DDD(DUK_DDDPRINT("k is too low"));
76178 			/* r <- r
76179 			 * s <- (* s B)
76180 			 * m+ <- m+
76181 			 * m- <- m-
76182 			 * k <- (+ k 1)
76183 			 */
76184 
76185 			duk__bi_mul_small_copy(&nc_ctx->s, nc_ctx->B, &nc_ctx->t1);
76186 			k++;
76187 		} else {
76188 			break;
76189 		}
76190 	}
76191 
76192 	/* k > 0 -> k was too low, and cannot be too high */
76193 	if (k > 0) {
76194 		goto skip_dec_k;
76195 	}
76196 
76197 	for (;;) {
76198 		DUK_DDD(DUK_DDDPRINT("scale loop (dec k), k=%ld", (long) k));
76199 		DUK__BI_PRINT("r", &nc_ctx->r);
76200 		DUK__BI_PRINT("s", &nc_ctx->s);
76201 		DUK__BI_PRINT("m+", &nc_ctx->mp);
76202 		DUK__BI_PRINT("m-", &nc_ctx->mm);
76203 
76204 		duk__bi_add(&nc_ctx->t1, &nc_ctx->r, &nc_ctx->mp);  /* t1 = (+ r m+) */
76205 		duk__bi_mul_small(&nc_ctx->t2, &nc_ctx->t1, nc_ctx->B);   /* t2 = (* (+ r m+) B) */
76206 		if (duk__bi_compare(&nc_ctx->t2, &nc_ctx->s) <= (nc_ctx->high_ok ? -1 : 0)) {
76207 			DUK_DDD(DUK_DDDPRINT("k is too high"));
76208 			/* r <- (* r B)
76209 			 * s <- s
76210 			 * m+ <- (* m+ B)
76211 			 * m- <- (* m- B)
76212 			 * k <- (- k 1)
76213 			 */
76214 			duk__bi_mul_small_copy(&nc_ctx->r, nc_ctx->B, &nc_ctx->t1);
76215 			duk__bi_mul_small_copy(&nc_ctx->mp, nc_ctx->B, &nc_ctx->t1);
76216 			if (nc_ctx->unequal_gaps) {
76217 				DUK_DDD(DUK_DDDPRINT("m+ != m- -> need to update m- too"));
76218 				duk__bi_mul_small_copy(&nc_ctx->mm, nc_ctx->B, &nc_ctx->t1);
76219 			}
76220 			k--;
76221 		} else {
76222 			break;
76223 		}
76224 	}
76225 
76226  skip_dec_k:
76227 
76228 	if (!nc_ctx->unequal_gaps) {
76229 		DUK_DDD(DUK_DDDPRINT("equal gaps, copy m- from m+"));
76230 		duk__bi_copy(&nc_ctx->mm, &nc_ctx->mp);  /* mm <- mp */
76231 	}
76232 	nc_ctx->k = k;
76233 
76234 	DUK_DDD(DUK_DDDPRINT("final k: %ld", (long) k));
76235 	DUK__BI_PRINT("r(final)", &nc_ctx->r);
76236 	DUK__BI_PRINT("s(final)", &nc_ctx->s);
76237 	DUK__BI_PRINT("mp(final)", &nc_ctx->mp);
76238 	DUK__BI_PRINT("mm(final)", &nc_ctx->mm);
76239 }
76240 
76241 DUK_LOCAL void duk__dragon4_generate(duk__numconv_stringify_ctx *nc_ctx) {
76242 	duk_small_int_t tc1, tc2;    /* terminating conditions */
76243 	duk_small_int_t d;           /* current digit */
76244 	duk_small_int_t count = 0;   /* digit count */
76245 
76246 	/*
76247 	 *  Digit generation loop.
76248 	 *
76249 	 *  Different termination conditions:
76250 	 *
76251 	 *    1. Free format output.  Terminate when shortest accurate
76252 	 *       representation found.
76253 	 *
76254 	 *    2. Fixed format output, with specific number of digits.
76255 	 *       Ignore termination conditions, terminate when digits
76256 	 *       generated.  Caller requests an extra digit and rounds.
76257 	 *
76258 	 *    3. Fixed format output, with a specific absolute cut-off
76259 	 *       position (e.g. 10 digits after decimal point).  Note
76260 	 *       that we always generate at least one digit, even if
76261 	 *       the digit is below the cut-off point already.
76262 	 */
76263 
76264 	for (;;) {
76265 		DUK_DDD(DUK_DDDPRINT("generate loop, count=%ld, k=%ld, B=%ld, low_ok=%ld, high_ok=%ld",
76266 		                     (long) count, (long) nc_ctx->k, (long) nc_ctx->B,
76267 		                     (long) nc_ctx->low_ok, (long) nc_ctx->high_ok));
76268 		DUK__BI_PRINT("r", &nc_ctx->r);
76269 		DUK__BI_PRINT("s", &nc_ctx->s);
76270 		DUK__BI_PRINT("m+", &nc_ctx->mp);
76271 		DUK__BI_PRINT("m-", &nc_ctx->mm);
76272 
76273 		/* (quotient-remainder (* r B) s) using a dummy subtraction loop */
76274 		duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->r, nc_ctx->B);       /* t1 <- (* r B) */
76275 		d = 0;
76276 		for (;;) {
76277 			if (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) < 0) {
76278 				break;
76279 			}
76280 			duk__bi_sub_copy(&nc_ctx->t1, &nc_ctx->s, &nc_ctx->t2);  /* t1 <- t1 - s */
76281 			d++;
76282 		}
76283 		duk__bi_copy(&nc_ctx->r, &nc_ctx->t1);  /* r <- (remainder (* r B) s) */
76284 		                                        /* d <- (quotient (* r B) s)   (in range 0...B-1) */
76285 		DUK_DDD(DUK_DDDPRINT("-> d(quot)=%ld", (long) d));
76286 		DUK__BI_PRINT("r(rem)", &nc_ctx->r);
76287 
76288 		duk__bi_mul_small_copy(&nc_ctx->mp, nc_ctx->B, &nc_ctx->t2); /* m+ <- (* m+ B) */
76289 		duk__bi_mul_small_copy(&nc_ctx->mm, nc_ctx->B, &nc_ctx->t2); /* m- <- (* m- B) */
76290 		DUK__BI_PRINT("mp(upd)", &nc_ctx->mp);
76291 		DUK__BI_PRINT("mm(upd)", &nc_ctx->mm);
76292 
76293 		/* Terminating conditions.  For fixed width output, we just ignore the
76294 		 * terminating conditions (and pretend that tc1 == tc2 == false).  The
76295 		 * the current shortcut for fixed-format output is to generate a few
76296 		 * extra digits and use rounding (with carry) to finish the output.
76297 		 */
76298 
76299 		if (nc_ctx->is_fixed == 0) {
76300 			/* free-form */
76301 			tc1 = (duk__bi_compare(&nc_ctx->r, &nc_ctx->mm) <= (nc_ctx->low_ok ? 0 : -1));
76302 
76303 			duk__bi_add(&nc_ctx->t1, &nc_ctx->r, &nc_ctx->mp);  /* t1 <- (+ r m+) */
76304 			tc2 = (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) >= (nc_ctx->high_ok ? 0 : 1));
76305 
76306 			DUK_DDD(DUK_DDDPRINT("tc1=%ld, tc2=%ld", (long) tc1, (long) tc2));
76307 		} else {
76308 			/* fixed-format */
76309 			tc1 = 0;
76310 			tc2 = 0;
76311 		}
76312 
76313 		/* Count is incremented before DUK__DRAGON4_OUTPUT_PREINC() call
76314 		 * on purpose, which is taken into account by the macro.
76315 		 */
76316 		count++;
76317 
76318 		if (tc1) {
76319 			if (tc2) {
76320 				/* tc1 = true, tc2 = true */
76321 				duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->r, 2);
76322 				if (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) < 0) {  /* (< (* r 2) s) */
76323 					DUK_DDD(DUK_DDDPRINT("tc1=true, tc2=true, 2r > s: output d --> %ld (k=%ld)",
76324 					                     (long) d, (long) nc_ctx->k));
76325 					DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d);
76326 				} else {
76327 					DUK_DDD(DUK_DDDPRINT("tc1=true, tc2=true, 2r <= s: output d+1 --> %ld (k=%ld)",
76328 					                     (long) (d + 1), (long) nc_ctx->k));
76329 					DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d + 1);
76330 				}
76331 				break;
76332 			} else {
76333 				/* tc1 = true, tc2 = false */
76334 				DUK_DDD(DUK_DDDPRINT("tc1=true, tc2=false: output d --> %ld (k=%ld)",
76335 				                     (long) d, (long) nc_ctx->k));
76336 				DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d);
76337 				break;
76338 			}
76339 		} else {
76340 			if (tc2) {
76341 				/* tc1 = false, tc2 = true */
76342 				DUK_DDD(DUK_DDDPRINT("tc1=false, tc2=true: output d+1 --> %ld (k=%ld)",
76343 				                     (long) (d + 1), (long) nc_ctx->k));
76344 				DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d + 1);
76345 				break;
76346 			} else {
76347 				/* tc1 = false, tc2 = false */
76348 				DUK_DDD(DUK_DDDPRINT("tc1=false, tc2=false: output d --> %ld (k=%ld)",
76349 				                     (long) d, (long) nc_ctx->k));
76350 				DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d);
76351 
76352 				/* r <- r    (updated above: r <- (remainder (* r B) s)
76353 				 * s <- s
76354 				 * m+ <- m+  (updated above: m+ <- (* m+ B)
76355 				 * m- <- m-  (updated above: m- <- (* m- B)
76356 				 * B, low_ok, high_ok are fixed
76357 				 */
76358 
76359 				/* fall through and continue for-loop */
76360 			}
76361 		}
76362 
76363 		/* fixed-format termination conditions */
76364 		if (nc_ctx->is_fixed) {
76365 			if (nc_ctx->abs_pos) {
76366 				int pos = nc_ctx->k - count + 1;  /* count is already incremented, take into account */
76367 				DUK_DDD(DUK_DDDPRINT("fixed format, absolute: abs pos=%ld, k=%ld, count=%ld, req=%ld",
76368 				                     (long) pos, (long) nc_ctx->k, (long) count, (long) nc_ctx->req_digits));
76369 				if (pos <= nc_ctx->req_digits) {
76370 					DUK_DDD(DUK_DDDPRINT("digit position reached req_digits, end generate loop"));
76371 					break;
76372 				}
76373 			} else {
76374 				DUK_DDD(DUK_DDDPRINT("fixed format, relative: k=%ld, count=%ld, req=%ld",
76375 				                     (long) nc_ctx->k, (long) count, (long) nc_ctx->req_digits));
76376 				if (count >= nc_ctx->req_digits) {
76377 					DUK_DDD(DUK_DDDPRINT("digit count reached req_digits, end generate loop"));
76378 					break;
76379 				}
76380 			}
76381 		}
76382 	}  /* for */
76383 
76384 	nc_ctx->count = count;
76385 
76386 	DUK_DDD(DUK_DDDPRINT("generate finished"));
76387 
76388 #ifdef DUK_USE_DDDPRINT
76389 	{
76390 		duk_uint8_t buf[2048];
76391 		duk_small_int_t i, t;
76392 		DUK_MEMZERO(buf, sizeof(buf));
76393 		for (i = 0; i < nc_ctx->count; i++) {
76394 			t = nc_ctx->digits[i];
76395 			if (t < 0 || t > 36) {
76396 				buf[i] = (duk_uint8_t) '?';
76397 			} else {
76398 				buf[i] = (duk_uint8_t) DUK__DIGITCHAR(t);
76399 			}
76400 		}
76401 		DUK_DDD(DUK_DDDPRINT("-> generated digits; k=%ld, digits='%s'",
76402 		                     (long) nc_ctx->k, (const char *) buf));
76403 	}
76404 #endif
76405 }
76406 
76407 /* Round up digits to a given position.  If position is out-of-bounds,
76408  * does nothing.  If carry propagates over the first digit, a '1' is
76409  * prepended to digits and 'k' will be updated.  Return value indicates
76410  * whether carry propagated over the first digit.
76411  *
76412  * Note that nc_ctx->count is NOT updated based on the rounding position
76413  * (it is updated only if carry overflows over the first digit and an
76414  * extra digit is prepended).
76415  */
76416 DUK_LOCAL duk_small_int_t duk__dragon4_fixed_format_round(duk__numconv_stringify_ctx *nc_ctx, duk_small_int_t round_idx) {
76417 	duk_small_int_t t;
76418 	duk_uint8_t *p;
76419 	duk_uint8_t roundup_limit;
76420 	duk_small_int_t ret = 0;
76421 
76422 	/*
76423 	 *  round_idx points to the digit which is considered for rounding; the
76424 	 *  digit to its left is the final digit of the rounded value.  If round_idx
76425 	 *  is zero, rounding will be performed; the result will either be an empty
76426 	 *  rounded value or if carry happens a '1' digit is generated.
76427 	 */
76428 
76429 	if (round_idx >= nc_ctx->count) {
76430 		DUK_DDD(DUK_DDDPRINT("round_idx out of bounds (%ld >= %ld (count)) -> no rounding",
76431 		                     (long) round_idx, (long) nc_ctx->count));
76432 		return 0;
76433 	} else if (round_idx < 0) {
76434 		DUK_DDD(DUK_DDDPRINT("round_idx out of bounds (%ld < 0) -> no rounding",
76435 		                     (long) round_idx));
76436 		return 0;
76437 	}
76438 
76439 	/*
76440 	 *  Round-up limit.
76441 	 *
76442 	 *  For even values, divides evenly, e.g. 10 -> roundup_limit=5.
76443 	 *
76444 	 *  For odd values, rounds up, e.g. 3 -> roundup_limit=2.
76445 	 *  If radix is 3, 0/3 -> down, 1/3 -> down, 2/3 -> up.
76446 	 */
76447 	roundup_limit = (duk_uint8_t) ((nc_ctx->B + 1) / 2);
76448 
76449 	p = &nc_ctx->digits[round_idx];
76450 	if (*p >= roundup_limit) {
76451 		DUK_DDD(DUK_DDDPRINT("fixed-format rounding carry required"));
76452 		/* carry */
76453 		for (;;) {
76454 			*p = 0;
76455 			if (p == &nc_ctx->digits[0]) {
76456 				DUK_DDD(DUK_DDDPRINT("carry propagated to first digit -> special case handling"));
76457 				DUK_MEMMOVE((void *) (&nc_ctx->digits[1]),
76458 				            (const void *) (&nc_ctx->digits[0]),
76459 				            (size_t) (sizeof(char) * nc_ctx->count));
76460 				nc_ctx->digits[0] = 1;  /* don't increase 'count' */
76461 				nc_ctx->k++;  /* position of highest digit changed */
76462 				nc_ctx->count++;  /* number of digits changed */
76463 				ret = 1;
76464 				break;
76465 			}
76466 
76467 			DUK_DDD(DUK_DDDPRINT("fixed-format rounding carry: B=%ld, roundup_limit=%ld, p=%p, digits=%p",
76468 			                     (long) nc_ctx->B, (long) roundup_limit, (void *) p, (void *) nc_ctx->digits));
76469 			p--;
76470 			t = *p;
76471 			DUK_DDD(DUK_DDDPRINT("digit before carry: %ld", (long) t));
76472 			if (++t < nc_ctx->B) {
76473 				DUK_DDD(DUK_DDDPRINT("rounding carry terminated"));
76474 				*p = (duk_uint8_t) t;
76475 				break;
76476 			}
76477 
76478 			DUK_DDD(DUK_DDDPRINT("wraps, carry to next digit"));
76479 		}
76480 	}
76481 
76482 	return ret;
76483 }
76484 
76485 #define DUK__NO_EXP  (65536)  /* arbitrary marker, outside valid exp range */
76486 
76487 DUK_LOCAL void duk__dragon4_convert_and_push(duk__numconv_stringify_ctx *nc_ctx,
76488                                           duk_context *ctx,
76489                                           duk_small_int_t radix,
76490                                           duk_small_int_t digits,
76491                                           duk_small_uint_t flags,
76492                                           duk_small_int_t neg) {
76493 	duk_small_int_t k;
76494 	duk_small_int_t pos, pos_end;
76495 	duk_small_int_t expt;
76496 	duk_small_int_t dig;
76497 	duk_uint8_t *q;
76498 	duk_uint8_t *buf;
76499 
76500 	/*
76501 	 *  The string conversion here incorporates all the necessary Ecmascript
76502 	 *  semantics without attempting to be generic.  nc_ctx->digits contains
76503 	 *  nc_ctx->count digits (>= 1), with the topmost digit's 'position'
76504 	 *  indicated by nc_ctx->k as follows:
76505 	 *
76506 	 *    digits="123" count=3 k=0   -->   0.123
76507 	 *    digits="123" count=3 k=1   -->   1.23
76508 	 *    digits="123" count=3 k=5   -->   12300
76509 	 *    digits="123" count=3 k=-1  -->   0.0123
76510 	 *
76511 	 *  Note that the identifier names used for format selection are different
76512 	 *  in Burger-Dybvig paper and Ecmascript specification (quite confusingly
76513 	 *  so, because e.g. 'k' has a totally different meaning in each).  See
76514 	 *  documentation for discussion.
76515 	 *
76516 	 *  Ecmascript doesn't specify any specific behavior for format selection
76517 	 *  (e.g. when to use exponent notation) for non-base-10 numbers.
76518 	 *
76519 	 *  The bigint space in the context is reused for string output, as there
76520 	 *  is more than enough space for that (>1kB at the moment), and we avoid
76521 	 *  allocating even more stack.
76522 	 */
76523 
76524 	DUK_ASSERT(DUK__NUMCONV_CTX_BIGINTS_SIZE >= DUK__MAX_FORMATTED_LENGTH);
76525 	DUK_ASSERT(nc_ctx->count >= 1);
76526 
76527 	k = nc_ctx->k;
76528 	buf = (duk_uint8_t *) &nc_ctx->f;  /* XXX: union would be more correct */
76529 	q = buf;
76530 
76531 	/* Exponent handling: if exponent format is used, record exponent value and
76532 	 * fake k such that one leading digit is generated (e.g. digits=123 -> "1.23").
76533 	 *
76534 	 * toFixed() prevents exponent use; otherwise apply a set of criteria to
76535 	 * match the other API calls (toString(), toPrecision, etc).
76536 	 */
76537 
76538 	expt = DUK__NO_EXP;
76539 	if (!nc_ctx->abs_pos /* toFixed() */) {
76540 		if ((flags & DUK_N2S_FLAG_FORCE_EXP) ||             /* exponential notation forced */
76541 		    ((flags & DUK_N2S_FLAG_NO_ZERO_PAD) &&          /* fixed precision and zero padding would be required */
76542 	             (k - digits >= 1)) ||                          /* (e.g. k=3, digits=2 -> "12X") */
76543 		    ((k > 21 || k <= -6) && (radix == 10))) {       /* toString() conditions */
76544 			DUK_DDD(DUK_DDDPRINT("use exponential notation: k=%ld -> expt=%ld",
76545 			                     (long) k, (long) (k - 1)));
76546 			expt = k - 1;  /* e.g. 12.3 -> digits="123" k=2 -> 1.23e1 */
76547 			k = 1;  /* generate mantissa with a single leading whole number digit */
76548 		}
76549 	}
76550 
76551 	if (neg) {
76552 		*q++ = '-';
76553 	}
76554 
76555 	/* Start position (inclusive) and end position (exclusive) */
76556 	pos = (k >= 1 ? k : 1);
76557 	if (nc_ctx->is_fixed) {
76558 		if (nc_ctx->abs_pos) {
76559 			/* toFixed() */
76560 			pos_end = -digits;
76561 		} else {
76562 			pos_end = k - digits;
76563 		}
76564 	} else {
76565 		pos_end = k - nc_ctx->count;
76566 	}
76567 	if (pos_end > 0) {
76568 		pos_end = 0;
76569 	}
76570 
76571 	DUK_DDD(DUK_DDDPRINT("expt=%ld, k=%ld, count=%ld, pos=%ld, pos_end=%ld, is_fixed=%ld, "
76572 	                     "digits=%ld, abs_pos=%ld",
76573 	                     (long) expt, (long) k, (long) nc_ctx->count, (long) pos, (long) pos_end,
76574 	                     (long) nc_ctx->is_fixed, (long) digits, (long) nc_ctx->abs_pos));
76575 
76576 	/* Digit generation */
76577 	while (pos > pos_end) {
76578 		DUK_DDD(DUK_DDDPRINT("digit generation: pos=%ld, pos_end=%ld",
76579 		                     (long) pos, (long) pos_end));
76580 		if (pos == 0) {
76581 			*q++ = (duk_uint8_t) '.';
76582 		}
76583 		if (pos > k) {
76584 			*q++ = (duk_uint8_t) '0';
76585 		} else if (pos <= k - nc_ctx->count) {
76586 			*q++ = (duk_uint8_t) '0';
76587 		} else {
76588 			dig = nc_ctx->digits[k - pos];
76589 			DUK_ASSERT(dig >= 0 && dig < nc_ctx->B);
76590 			*q++ = (duk_uint8_t) DUK__DIGITCHAR(dig);
76591 		}
76592 
76593 		pos--;
76594 	}
76595 	DUK_ASSERT(pos <= 1);
76596 
76597 	/* Exponent */
76598 	if (expt != DUK__NO_EXP) {
76599 		/*
76600 		 *  Exponent notation for non-base-10 numbers isn't specified in Ecmascript
76601 		 *  specification, as it never explicitly turns up: non-decimal numbers can
76602 		 *  only be formatted with Number.prototype.toString([radix]) and for that,
76603 		 *  behavior is not explicitly specified.
76604 		 *
76605 		 *  Logical choices include formatting the exponent as decimal (e.g. binary
76606 		 *  100000 as 1e+5) or in current radix (e.g. binary 100000 as 1e+101).
76607 		 *  The Dragon4 algorithm (in the original paper) prints the exponent value
76608 		 *  in the target radix B.  However, for radix values 15 and above, the
76609 		 *  exponent separator 'e' is no longer easily parseable.  Consider, for
76610 		 *  instance, the number "1.faecee+1c".
76611 		 */
76612 
76613 		duk_size_t len;
76614 		char expt_sign;
76615 
76616 		*q++ = 'e';
76617 		if (expt >= 0) {
76618 			expt_sign = '+';
76619 		} else {
76620 			expt_sign = '-';
76621 			expt = -expt;
76622 		}
76623 		*q++ = (duk_uint8_t) expt_sign;
76624 		len = duk__dragon4_format_uint32(q, (duk_uint32_t) expt, radix);
76625 		q += len;
76626 	}
76627 
76628 	duk_push_lstring(ctx, (const char *) buf, (size_t) (q - buf));
76629 }
76630 
76631 /*
76632  *  Conversion helpers
76633  */
76634 
76635 DUK_LOCAL void duk__dragon4_double_to_ctx(duk__numconv_stringify_ctx *nc_ctx, duk_double_t x) {
76636 	duk_double_union u;
76637 	duk_uint32_t tmp;
76638 	duk_small_int_t expt;
76639 
76640 	/*
76641 	 *    seeeeeee eeeeffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff
76642 	 *       A        B        C        D        E        F        G        H
76643 	 *
76644 	 *    s       sign bit
76645 	 *    eee...  exponent field
76646 	 *    fff...  fraction
76647 	 *
76648 	 *    ieee value = 1.ffff... * 2^(e - 1023)  (normal)
76649 	 *               = 0.ffff... * 2^(-1022)     (denormal)
76650 	 *
76651 	 *    algorithm v = f * b^e
76652 	 */
76653 
76654 	DUK_DBLUNION_SET_DOUBLE(&u, x);
76655 
76656 	nc_ctx->f.n = 2;
76657 
76658 	tmp = DUK_DBLUNION_GET_LOW32(&u);
76659 	nc_ctx->f.v[0] = tmp;
76660 	tmp = DUK_DBLUNION_GET_HIGH32(&u);
76661 	nc_ctx->f.v[1] = tmp & 0x000fffffUL;
76662 	expt = (duk_small_int_t) ((tmp >> 20) & 0x07ffUL);
76663 
76664 	if (expt == 0) {
76665 		/* denormal */
76666 		expt = DUK__IEEE_DOUBLE_EXP_MIN - 52;
76667 		duk__bi_normalize(&nc_ctx->f);
76668 	} else {
76669 		/* normal: implicit leading 1-bit */
76670 		nc_ctx->f.v[1] |= 0x00100000UL;
76671 		expt = expt - DUK__IEEE_DOUBLE_EXP_BIAS - 52;
76672 		DUK_ASSERT(duk__bi_is_valid(&nc_ctx->f));  /* true, because v[1] has at least one bit set */
76673 	}
76674 
76675 	DUK_ASSERT(duk__bi_is_valid(&nc_ctx->f));
76676 
76677 	nc_ctx->e = expt;
76678 }
76679 
76680 DUK_LOCAL void duk__dragon4_ctx_to_double(duk__numconv_stringify_ctx *nc_ctx, duk_double_t *x) {
76681 	duk_double_union u;
76682 	duk_small_int_t expt;
76683 	duk_small_int_t i;
76684 	duk_small_int_t bitstart;
76685 	duk_small_int_t bitround;
76686 	duk_small_int_t bitidx;
76687 	duk_small_int_t skip_round;
76688 	duk_uint32_t t, v;
76689 
76690 	DUK_ASSERT(nc_ctx->count == 53 + 1);
76691 
76692 	/* Sometimes this assert is not true right now; it will be true after
76693 	 * rounding.  See: test-bug-numconv-mantissa-assert.js.
76694 	 */
76695 	DUK_ASSERT_DISABLE(nc_ctx->digits[0] == 1);  /* zero handled by caller */
76696 
76697 	/* Should not be required because the code below always sets both high
76698 	 * and low parts, but at least gcc-4.4.5 fails to deduce this correctly
76699 	 * (perhaps because the low part is set (seemingly) conditionally in a
76700 	 * loop), so this is here to avoid the bogus warning.
76701 	 */
76702 	DUK_MEMZERO((void *) &u, sizeof(u));
76703 
76704 	/*
76705 	 *  Figure out how generated digits match up with the mantissa,
76706 	 *  and then perform rounding.  If mantissa overflows, need to
76707 	 *  recompute the exponent (it is bumped and may overflow to
76708 	 *  infinity).
76709 	 *
76710 	 *  For normal numbers the leading '1' is hidden and ignored,
76711 	 *  and the last bit is used for rounding:
76712 	 *
76713 	 *                          rounding pt
76714 	 *       <--------52------->|
76715 	 *     1 x x x x ... x x x x|y  ==>  x x x x ... x x x x
76716 	 *
76717 	 *  For denormals, the leading '1' is included in the number,
76718 	 *  and the rounding point is different:
76719 	 *
76720 	 *                      rounding pt
76721 	 *     <--52 or less--->|
76722 	 *     1 x x x x ... x x|x x y  ==>  0 0 ... 1 x x ... x x
76723 	 *
76724 	 *  The largest denormals will have a mantissa beginning with
76725 	 *  a '1' (the explicit leading bit); smaller denormals will
76726 	 *  have leading zero bits.
76727 	 *
76728 	 *  If the exponent would become too high, the result becomes
76729 	 *  Infinity.  If the exponent is so small that the entire
76730 	 *  mantissa becomes zero, the result becomes zero.
76731 	 *
76732 	 *  Note: the Dragon4 'k' is off-by-one with respect to the IEEE
76733 	 *  exponent.  For instance, k==0 indicates that the leading '1'
76734 	 *  digit is at the first binary fraction position (0.1xxx...);
76735 	 *  the corresponding IEEE exponent would be -1.
76736 	 */
76737 
76738 	skip_round = 0;
76739 
76740  recheck_exp:
76741 
76742 	expt = nc_ctx->k - 1;   /* IEEE exp without bias */
76743 	if (expt > 1023) {
76744 		/* Infinity */
76745 		bitstart = -255;  /* needed for inf: causes mantissa to become zero,
76746 		                   * and rounding to be skipped.
76747 		                   */
76748 		expt = 2047;
76749 	} else if (expt >= -1022) {
76750 		/* normal */
76751 		bitstart = 1;  /* skip leading digit */
76752 		expt += DUK__IEEE_DOUBLE_EXP_BIAS;
76753 		DUK_ASSERT(expt >= 1 && expt <= 2046);
76754 	} else {
76755 		/* denormal or zero */
76756 		bitstart = 1023 + expt;  /* expt==-1023 -> bitstart=0 (leading 1);
76757 		                          * expt==-1024 -> bitstart=-1 (one left of leading 1), etc
76758 		                          */
76759 		expt = 0;
76760 	}
76761 	bitround = bitstart + 52;
76762 
76763 	DUK_DDD(DUK_DDDPRINT("ieee expt=%ld, bitstart=%ld, bitround=%ld",
76764 	                     (long) expt, (long) bitstart, (long) bitround));
76765 
76766 	if (!skip_round) {
76767 		if (duk__dragon4_fixed_format_round(nc_ctx, bitround)) {
76768 			/* Corner case: see test-numconv-parse-mant-carry.js.  We could
76769 			 * just bump the exponent and update bitstart, but it's more robust
76770 			 * to recompute (but avoid rounding twice).
76771 			 */
76772 			DUK_DDD(DUK_DDDPRINT("rounding caused exponent to be bumped, recheck exponent"));
76773 			skip_round = 1;
76774 			goto recheck_exp;
76775 		}
76776 	}
76777 
76778 	/*
76779 	 *  Create mantissa
76780 	 */
76781 
76782 	t = 0;
76783 	for (i = 0; i < 52; i++) {
76784 		bitidx = bitstart + 52 - 1 - i;
76785 		if (bitidx >= nc_ctx->count) {
76786 			v = 0;
76787 		} else if (bitidx < 0) {
76788 			v = 0;
76789 		} else {
76790 			v = nc_ctx->digits[bitidx];
76791 		}
76792 		DUK_ASSERT(v == 0 || v == 1);
76793 		t += v << (i % 32);
76794 		if (i == 31) {
76795 			/* low 32 bits is complete */
76796 			DUK_DBLUNION_SET_LOW32(&u, t);
76797 			t = 0;
76798 		}
76799 	}
76800 	/* t has high mantissa */
76801 
76802 	DUK_DDD(DUK_DDDPRINT("mantissa is complete: %08lx %08lx",
76803 	                     (unsigned long) t,
76804 	                     (unsigned long) DUK_DBLUNION_GET_LOW32(&u)));
76805 
76806 	DUK_ASSERT(expt >= 0 && expt <= 0x7ffL);
76807 	t += expt << 20;
76808 #if 0  /* caller handles sign change */
76809 	if (negative) {
76810 		t |= 0x80000000U;
76811 	}
76812 #endif
76813 	DUK_DBLUNION_SET_HIGH32(&u, t);
76814 
76815 	DUK_DDD(DUK_DDDPRINT("number is complete: %08lx %08lx",
76816 	                     (unsigned long) DUK_DBLUNION_GET_HIGH32(&u),
76817 	                     (unsigned long) DUK_DBLUNION_GET_LOW32(&u)));
76818 
76819 	*x = DUK_DBLUNION_GET_DOUBLE(&u);
76820 }
76821 
76822 /*
76823  *  Exposed number-to-string API
76824  *
76825  *  Input: [ number ]
76826  *  Output: [ string ]
76827  */
76828 
76829 DUK_INTERNAL void duk_numconv_stringify(duk_context *ctx, duk_small_int_t radix, duk_small_int_t digits, duk_small_uint_t flags) {
76830 	duk_double_t x;
76831 	duk_small_int_t c;
76832 	duk_small_int_t neg;
76833 	duk_uint32_t uval;
76834 	duk__numconv_stringify_ctx nc_ctx_alloc;  /* large context; around 2kB now */
76835 	duk__numconv_stringify_ctx *nc_ctx = &nc_ctx_alloc;
76836 
76837 	x = (duk_double_t) duk_require_number(ctx, -1);
76838 	duk_pop(ctx);
76839 
76840 	/*
76841 	 *  Handle special cases (NaN, infinity, zero).
76842 	 */
76843 
76844 	c = (duk_small_int_t) DUK_FPCLASSIFY(x);
76845 	if (DUK_SIGNBIT((double) x)) {
76846 		x = -x;
76847 		neg = 1;
76848 	} else {
76849 		neg = 0;
76850 	}
76851 
76852 	/* NaN sign bit is platform specific with unpacked, un-normalized NaNs */
76853 	DUK_ASSERT(c == DUK_FP_NAN || DUK_SIGNBIT((double) x) == 0);
76854 
76855 	if (c == DUK_FP_NAN) {
76856 		duk_push_hstring_stridx(ctx, DUK_STRIDX_NAN);
76857 		return;
76858 	} else if (c == DUK_FP_INFINITE) {
76859 		if (neg) {
76860 			/* -Infinity */
76861 			duk_push_hstring_stridx(ctx, DUK_STRIDX_MINUS_INFINITY);
76862 		} else {
76863 			/* Infinity */
76864 			duk_push_hstring_stridx(ctx, DUK_STRIDX_INFINITY);
76865 		}
76866 		return;
76867 	} else if (c == DUK_FP_ZERO) {
76868 		/* We can't shortcut zero here if it goes through special formatting
76869 		 * (such as forced exponential notation).
76870 		 */
76871 		;
76872 	}
76873 
76874 	/*
76875 	 *  Handle integers in 32-bit range (that is, [-(2**32-1),2**32-1])
76876 	 *  specially, as they're very likely for embedded programs.  This
76877 	 *  is now done for all radix values.  We must be careful not to use
76878 	 *  the fast path when special formatting (e.g. forced exponential)
76879 	 *  is in force.
76880 	 *
76881 	 *  XXX: could save space by supporting radix 10 only and using
76882 	 *  sprintf "%lu" for the fast path and for exponent formatting.
76883 	 */
76884 
76885 	uval = (unsigned int) x;
76886 	if (((double) uval) == x &&  /* integer number in range */
76887 	    flags == 0) {            /* no special formatting */
76888 		/* use bigint area as a temp */
76889 		duk_uint8_t *buf = (duk_uint8_t *) (&nc_ctx->f);
76890 		duk_uint8_t *p = buf;
76891 
76892 		DUK_ASSERT(DUK__NUMCONV_CTX_BIGINTS_SIZE >= 32 + 1);  /* max size: radix=2 + sign */
76893 		if (neg && uval != 0) {
76894 			/* no negative sign for zero */
76895 			*p++ = (duk_uint8_t) '-';
76896 		}
76897 		p += duk__dragon4_format_uint32(p, uval, radix);
76898 		duk_push_lstring(ctx, (const char *) buf, (duk_size_t) (p - buf));
76899 		return;
76900 	}
76901 
76902 	/*
76903 	 *  Dragon4 setup.
76904 	 *
76905 	 *  Convert double from IEEE representation for conversion;
76906 	 *  normal finite values have an implicit leading 1-bit.  The
76907 	 *  slow path algorithm doesn't handle zero, so zero is special
76908 	 *  cased here but still creates a valid nc_ctx, and goes
76909 	 *  through normal formatting in case special formatting has
76910 	 *  been requested (e.g. forced exponential format: 0 -> "0e+0").
76911 	 */
76912 
76913 	/* Would be nice to bulk clear the allocation, but the context
76914 	 * is 1-2 kilobytes and nothing should rely on it being zeroed.
76915 	 */
76916 #if 0
76917 	DUK_MEMZERO((void *) nc_ctx, sizeof(*nc_ctx));  /* slow init, do only for slow path cases */
76918 #endif
76919 
76920 	nc_ctx->is_s2n = 0;
76921 	nc_ctx->b = 2;
76922 	nc_ctx->B = radix;
76923 	nc_ctx->abs_pos = 0;
76924 	if (flags & DUK_N2S_FLAG_FIXED_FORMAT) {
76925 		nc_ctx->is_fixed = 1;
76926 		if (flags & DUK_N2S_FLAG_FRACTION_DIGITS) {
76927 			/* absolute req_digits; e.g. digits = 1 -> last digit is 0,
76928 			 * but add an extra digit for rounding.
76929 			 */
76930 			nc_ctx->abs_pos = 1;
76931 			nc_ctx->req_digits = (-digits + 1) - 1;
76932 		} else {
76933 			nc_ctx->req_digits = digits + 1;
76934 		}
76935 	} else {
76936 		nc_ctx->is_fixed = 0;
76937 		nc_ctx->req_digits = 0;
76938 	}
76939 
76940 	if (c == DUK_FP_ZERO) {
76941 		/* Zero special case: fake requested number of zero digits; ensure
76942 		 * no sign bit is printed.  Relative and absolute fixed format
76943 		 * require separate handling.
76944 		 */
76945 		duk_small_int_t count;
76946 		if (nc_ctx->is_fixed) {
76947 			if (nc_ctx->abs_pos) {
76948 				count = digits + 2;  /* lead zero + 'digits' fractions + 1 for rounding */
76949 			} else {
76950 				count = digits + 1;  /* + 1 for rounding */
76951 			}
76952 		} else {
76953 			count = 1;
76954 		}
76955 		DUK_DDD(DUK_DDDPRINT("count=%ld", (long) count));
76956 		DUK_ASSERT(count >= 1);
76957 		DUK_MEMZERO((void *) nc_ctx->digits, count);
76958 		nc_ctx->count = count;
76959 		nc_ctx->k = 1;  /* 0.000... */
76960 		neg = 0;
76961 		goto zero_skip;
76962 	}
76963 
76964 	duk__dragon4_double_to_ctx(nc_ctx, x);   /* -> sets 'f' and 'e' */
76965 	DUK__BI_PRINT("f", &nc_ctx->f);
76966 	DUK_DDD(DUK_DDDPRINT("e=%ld", (long) nc_ctx->e));
76967 
76968 	/*
76969 	 *  Dragon4 slow path digit generation.
76970 	 */
76971 
76972 	duk__dragon4_prepare(nc_ctx);  /* setup many variables in nc_ctx */
76973 
76974 	DUK_DDD(DUK_DDDPRINT("after prepare:"));
76975 	DUK__BI_PRINT("r", &nc_ctx->r);
76976 	DUK__BI_PRINT("s", &nc_ctx->s);
76977 	DUK__BI_PRINT("mp", &nc_ctx->mp);
76978 	DUK__BI_PRINT("mm", &nc_ctx->mm);
76979 
76980 	duk__dragon4_scale(nc_ctx);
76981 
76982 	DUK_DDD(DUK_DDDPRINT("after scale; k=%ld", (long) nc_ctx->k));
76983 	DUK__BI_PRINT("r", &nc_ctx->r);
76984 	DUK__BI_PRINT("s", &nc_ctx->s);
76985 	DUK__BI_PRINT("mp", &nc_ctx->mp);
76986 	DUK__BI_PRINT("mm", &nc_ctx->mm);
76987 
76988 	duk__dragon4_generate(nc_ctx);
76989 
76990 	/*
76991 	 *  Convert and push final string.
76992 	 */
76993 
76994  zero_skip:
76995 
76996 	if (flags & DUK_N2S_FLAG_FIXED_FORMAT) {
76997 		/* Perform fixed-format rounding. */
76998 		duk_small_int_t roundpos;
76999 		if (flags & DUK_N2S_FLAG_FRACTION_DIGITS) {
77000 			/* 'roundpos' is relative to nc_ctx->k and increases to the right
77001 			 * (opposite of how 'k' changes).
77002 			 */
77003 			roundpos = -digits;  /* absolute position for digit considered for rounding */
77004 			roundpos = nc_ctx->k - roundpos;
77005 		} else {
77006 			roundpos = digits;
77007 		}
77008 		DUK_DDD(DUK_DDDPRINT("rounding: k=%ld, count=%ld, digits=%ld, roundpos=%ld",
77009 		                     (long) nc_ctx->k, (long) nc_ctx->count, (long) digits, (long) roundpos));
77010 		(void) duk__dragon4_fixed_format_round(nc_ctx, roundpos);
77011 
77012 		/* Note: 'count' is currently not adjusted by rounding (i.e. the
77013 		 * digits are not "chopped off".  That shouldn't matter because
77014 		 * the digit position (absolute or relative) is passed on to the
77015 		 * convert-and-push function.
77016 		 */
77017 	}
77018 
77019 	duk__dragon4_convert_and_push(nc_ctx, ctx, radix, digits, flags, neg);
77020 }
77021 
77022 /*
77023  *  Exposed string-to-number API
77024  *
77025  *  Input: [ string ]
77026  *  Output: [ number ]
77027  *
77028  *  If number parsing fails, a NaN is pushed as the result.  If number parsing
77029  *  fails due to an internal error, an InternalError is thrown.
77030  */
77031 
77032 DUK_INTERNAL void duk_numconv_parse(duk_context *ctx, duk_small_int_t radix, duk_small_uint_t flags) {
77033 	duk_hthread *thr = (duk_hthread *) ctx;
77034 	duk__numconv_stringify_ctx nc_ctx_alloc;  /* large context; around 2kB now */
77035 	duk__numconv_stringify_ctx *nc_ctx = &nc_ctx_alloc;
77036 	duk_double_t res;
77037 	duk_hstring *h_str;
77038 	duk_small_int_t expt;
77039 	duk_small_int_t expt_neg;
77040 	duk_small_int_t expt_adj;
77041 	duk_small_int_t neg;
77042 	duk_small_int_t dig;
77043 	duk_small_int_t dig_whole;
77044 	duk_small_int_t dig_lzero;
77045 	duk_small_int_t dig_frac;
77046 	duk_small_int_t dig_expt;
77047 	duk_small_int_t dig_prec;
77048 	const duk__exp_limits *explim;
77049 	const duk_uint8_t *p;
77050 	duk_small_int_t ch;
77051 
77052 	/* This seems to waste a lot of stack frame entries, but good compilers
77053 	 * will compute these as needed below.  Some of these initial flags are
77054 	 * also modified in the code below, so they can't all be removed.
77055 	 */
77056 	duk_small_int_t trim_white = (flags & DUK_S2N_FLAG_TRIM_WHITE);
77057 	duk_small_int_t allow_expt = (flags & DUK_S2N_FLAG_ALLOW_EXP);
77058 	duk_small_int_t allow_garbage = (flags & DUK_S2N_FLAG_ALLOW_GARBAGE);
77059 	duk_small_int_t allow_plus = (flags & DUK_S2N_FLAG_ALLOW_PLUS);
77060 	duk_small_int_t allow_minus = (flags & DUK_S2N_FLAG_ALLOW_MINUS);
77061 	duk_small_int_t allow_infinity = (flags & DUK_S2N_FLAG_ALLOW_INF);
77062 	duk_small_int_t allow_frac = (flags & DUK_S2N_FLAG_ALLOW_FRAC);
77063 	duk_small_int_t allow_naked_frac = (flags & DUK_S2N_FLAG_ALLOW_NAKED_FRAC);
77064 	duk_small_int_t allow_empty_frac = (flags & DUK_S2N_FLAG_ALLOW_EMPTY_FRAC);
77065 	duk_small_int_t allow_empty = (flags & DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO);
77066 	duk_small_int_t allow_leading_zero = (flags & DUK_S2N_FLAG_ALLOW_LEADING_ZERO);
77067 	duk_small_int_t allow_auto_hex_int = (flags & DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT);
77068 	duk_small_int_t allow_auto_oct_int = (flags & DUK_S2N_FLAG_ALLOW_AUTO_OCT_INT);
77069 
77070 	DUK_DDD(DUK_DDDPRINT("parse number: %!T, radix=%ld, flags=0x%08lx",
77071 	                     (duk_tval *) duk_get_tval(ctx, -1),
77072 	                     (long) radix, (unsigned long) flags));
77073 
77074 	DUK_ASSERT(radix >= 2 && radix <= 36);
77075 	DUK_ASSERT(radix - 2 < (duk_small_int_t) sizeof(duk__str2num_digits_for_radix));
77076 
77077 	/*
77078 	 *  Preliminaries: trim, sign, Infinity check
77079 	 *
77080 	 *  We rely on the interned string having a NUL terminator, which will
77081 	 *  cause a parse failure wherever it is encountered.  As a result, we
77082 	 *  don't need separate pointer checks.
77083 	 *
77084 	 *  There is no special parsing for 'NaN' in the specification although
77085 	 *  'Infinity' (with an optional sign) is allowed in some contexts.
77086 	 *  Some contexts allow plus/minus sign, while others only allow the
77087 	 *  minus sign (like JSON.parse()).
77088 	 *
77089 	 *  Automatic hex number detection (leading '0x' or '0X') and octal
77090 	 *  number detection (leading '0' followed by at least one octal digit)
77091 	 *  is done here too.
77092 	 */
77093 
77094 	if (trim_white) {
77095 		/* Leading / trailing whitespace is sometimes accepted and
77096 		 * sometimes not.  After white space trimming, all valid input
77097 		 * characters are pure ASCII.
77098 		 */
77099 		duk_trim(ctx, -1);
77100 	}
77101 	h_str = duk_require_hstring(ctx, -1);
77102 	DUK_ASSERT(h_str != NULL);
77103 	p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_str);
77104 
77105 	neg = 0;
77106 	ch = *p;
77107 	if (ch == (duk_small_int_t) '+') {
77108 		if (!allow_plus) {
77109 			DUK_DDD(DUK_DDDPRINT("parse failed: leading plus sign not allowed"));
77110 			goto parse_fail;
77111 		}
77112 		p++;
77113 	} else if (ch == (duk_small_int_t) '-') {
77114 		if (!allow_minus) {
77115 			DUK_DDD(DUK_DDDPRINT("parse failed: leading minus sign not allowed"));
77116 			goto parse_fail;
77117 		}
77118 		p++;
77119 		neg = 1;
77120 	}
77121 
77122 	ch = *p;
77123 	if (allow_infinity && ch == (duk_small_int_t) 'I') {
77124 		/* Don't check for Infinity unless the context allows it.
77125 		 * 'Infinity' is a valid integer literal in e.g. base-36:
77126 		 *
77127 		 *   parseInt('Infinity', 36)
77128 		 *   1461559270678
77129 		 */
77130 
77131 		const duk_uint8_t *q;
77132 
77133 		/* borrow literal Infinity from builtin string */
77134 		q = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(DUK_HTHREAD_STRING_INFINITY(thr));
77135 		if (DUK_STRNCMP((const char *) p, (const char *) q, 8) == 0) {
77136 			if (!allow_garbage && (p[8] != (duk_uint8_t) 0)) {
77137 				DUK_DDD(DUK_DDDPRINT("parse failed: trailing garbage after matching 'Infinity' not allowed"));
77138 				goto parse_fail;
77139 			} else {
77140 				res = DUK_DOUBLE_INFINITY;
77141 				goto negcheck_and_ret;
77142 			}
77143 		}
77144 	}
77145 	if (ch == (duk_small_int_t) '0') {
77146 		duk_small_int_t detect_radix = 0;
77147 		ch = p[1];
77148 		if (allow_auto_hex_int && (ch == (duk_small_int_t) 'x' || ch == (duk_small_int_t) 'X')) {
77149 			DUK_DDD(DUK_DDDPRINT("detected 0x/0X hex prefix, changing radix and preventing fractions and exponent"));
77150 			detect_radix = 16;
77151 			allow_empty = 0;  /* interpret e.g. '0x' and '0xg' as a NaN (= parse error) */
77152 			p += 2;
77153 		} else if (allow_auto_oct_int && (ch >= (duk_small_int_t) '0' && ch <= (duk_small_int_t) '9')) {
77154 			DUK_DDD(DUK_DDDPRINT("detected 0n oct prefix, changing radix and preventing fractions and exponent"));
77155 			detect_radix = 8;
77156 			allow_empty = 1;  /* interpret e.g. '09' as '0', not NaN */
77157 			p += 1;
77158 		}
77159 		if (detect_radix > 0) {
77160 			radix = detect_radix;
77161 			allow_expt = 0;
77162 			allow_frac = 0;
77163 			allow_naked_frac = 0;
77164 			allow_empty_frac = 0;
77165 			allow_leading_zero = 1;  /* allow e.g. '0x0009' and '00077' */
77166 		}
77167 	}
77168 
77169 	/*
77170 	 *  Scan number and setup for Dragon4.
77171 	 *
77172 	 *  The fast path case is detected during setup: an integer which
77173 	 *  can be converted without rounding, no net exponent.  The fast
77174 	 *  path could be implemented as a separate scan, but may not really
77175 	 *  be worth it: the multiplications for building 'f' are not
77176 	 *  expensive when 'f' is small.
77177 	 *
77178 	 *  The significand ('f') must contain enough bits of (apparent)
77179 	 *  accuracy, so that Dragon4 will generate enough binary output digits.
77180 	 *  For decimal numbers, this means generating a 20-digit significand,
77181 	 *  which should yield enough practical accuracy to parse IEEE doubles.
77182 	 *  In fact, the Ecmascript specification explicitly allows an
77183 	 *  implementation to treat digits beyond 20 as zeroes (and even
77184 	 *  to round the 20th digit upwards).  For non-decimal numbers, the
77185 	 *  appropriate number of digits has been precomputed for comparable
77186 	 *  accuracy.
77187 	 *
77188 	 *  Digit counts:
77189 	 *
77190 	 *    [ dig_lzero ]
77191 	 *      |
77192 	 *     .+-..---[ dig_prec ]----.
77193 	 *     |  ||                   |
77194 	 *     0000123.456789012345678901234567890e+123456
77195 	 *     |     | |                         |  |    |
77196 	 *     `--+--' `------[ dig_frac ]-------'  `-+--'
77197 	 *        |                                   |
77198 	 *    [ dig_whole ]                       [ dig_expt ]
77199 	 *
77200 	 *    dig_frac and dig_expt are -1 if not present
77201 	 *    dig_lzero is only computed for whole number part
77202 	 *
77203 	 *  Parsing state
77204 	 *
77205 	 *     Parsing whole part      dig_frac < 0 AND dig_expt < 0
77206 	 *     Parsing fraction part   dig_frac >= 0 AND dig_expt < 0
77207 	 *     Parsing exponent part   dig_expt >= 0   (dig_frac may be < 0 or >= 0)
77208 	 *
77209 	 *  Note: in case we hit an implementation limit (like exponent range),
77210 	 *  we should throw an error, NOT return NaN or Infinity.  Even with
77211 	 *  very large exponent (or significand) values the final result may be
77212 	 *  finite, so NaN/Infinity would be incorrect.
77213 	 */
77214 
77215 	duk__bi_set_small(&nc_ctx->f, 0);
77216 	dig_prec = 0;
77217 	dig_lzero = 0;
77218 	dig_whole = 0;
77219 	dig_frac = -1;
77220 	dig_expt = -1;
77221 	expt = 0;
77222 	expt_adj = 0;  /* essentially tracks digit position of lowest 'f' digit */
77223 	expt_neg = 0;
77224 	for (;;) {
77225 		ch = *p++;
77226 
77227 		DUK_DDD(DUK_DDDPRINT("parse digits: p=%p, ch='%c' (%ld), expt=%ld, expt_adj=%ld, "
77228 		                     "dig_whole=%ld, dig_frac=%ld, dig_expt=%ld, dig_lzero=%ld, dig_prec=%ld",
77229 		                     (const void *) p, (int) ((ch >= 0x20 && ch <= 0x7e) ? ch : '?'), (long) ch,
77230 		                     (long) expt, (long) expt_adj, (long) dig_whole, (long) dig_frac,
77231 		                     (long) dig_expt, (long) dig_lzero, (long) dig_prec));
77232 		DUK__BI_PRINT("f", &nc_ctx->f);
77233 
77234 		/* Most common cases first. */
77235 		if (ch >= (duk_small_int_t) '0' && ch <= (duk_small_int_t) '9') {
77236 			dig = (int) ch - '0' + 0;
77237 		} else if (ch == (duk_small_int_t) '.') {
77238 			/* A leading digit is not required in some cases, e.g. accept ".123".
77239 			 * In other cases (JSON.parse()) a leading digit is required.  This
77240 			 * is checked for after the loop.
77241 			 */
77242 			if (dig_frac >= 0 || dig_expt >= 0) {
77243 				if (allow_garbage) {
77244 					DUK_DDD(DUK_DDDPRINT("garbage termination (invalid period)"));
77245 					break;
77246 				} else {
77247 					DUK_DDD(DUK_DDDPRINT("parse failed: period not allowed"));
77248 					goto parse_fail;
77249 				}
77250 			}
77251 
77252 			if (!allow_frac) {
77253 				/* Some contexts don't allow fractions at all; this can't be a
77254 				 * post-check because the state ('f' and expt) would be incorrect.
77255 				 */
77256 				if (allow_garbage) {
77257 					DUK_DDD(DUK_DDDPRINT("garbage termination (invalid first period)"));
77258 					break;
77259 				} else {
77260 					DUK_DDD(DUK_DDDPRINT("parse failed: fraction part not allowed"));
77261 				}
77262 			}
77263 
77264 			DUK_DDD(DUK_DDDPRINT("start fraction part"));
77265 			dig_frac = 0;
77266 			continue;
77267 		} else if (ch == (duk_small_int_t) 0) {
77268 			DUK_DDD(DUK_DDDPRINT("NUL termination"));
77269 			break;
77270 		} else if (allow_expt && dig_expt < 0 && (ch == (duk_small_int_t) 'e' || ch == (duk_small_int_t) 'E')) {
77271 			/* Note: we don't parse back exponent notation for anything else
77272 			 * than radix 10, so this is not an ambiguous check (e.g. hex
77273 			 * exponent values may have 'e' either as a significand digit
77274 			 * or as an exponent separator).
77275 			 *
77276 			 * If the exponent separator occurs twice, 'e' will be interpreted
77277 			 * as a digit (= 14) and will be rejected as an invalid decimal
77278 			 * digit.
77279 			 */
77280 
77281 			DUK_DDD(DUK_DDDPRINT("start exponent part"));
77282 
77283 			/* Exponent without a sign or with a +/- sign is accepted
77284 			 * by all call sites (even JSON.parse()).
77285 			 */
77286 			ch = *p;
77287 			if (ch == (duk_small_int_t) '-') {
77288 				expt_neg = 1;
77289 				p++;
77290 			} else if (ch == (duk_small_int_t) '+') {
77291 				p++;
77292 			}
77293 			dig_expt = 0;
77294 			continue;
77295 		} else if (ch >= (duk_small_int_t) 'a' && ch <= (duk_small_int_t) 'z') {
77296 			dig = (duk_small_int_t) (ch - (duk_small_int_t) 'a' + 0x0a);
77297 		} else if (ch >= (duk_small_int_t) 'A' && ch <= (duk_small_int_t) 'Z') {
77298 			dig = (duk_small_int_t) (ch - (duk_small_int_t) 'A' + 0x0a);
77299 		} else {
77300 			dig = 255;  /* triggers garbage digit check below */
77301 		}
77302 		DUK_ASSERT((dig >= 0 && dig <= 35) || dig == 255);
77303 
77304 		if (dig >= radix) {
77305 			if (allow_garbage) {
77306 				DUK_DDD(DUK_DDDPRINT("garbage termination"));
77307 				break;
77308 			} else {
77309 				DUK_DDD(DUK_DDDPRINT("parse failed: trailing garbage or invalid digit"));
77310 				goto parse_fail;
77311 			}
77312 		}
77313 
77314 		if (dig_expt < 0) {
77315 			/* whole or fraction digit */
77316 
77317 			if (dig_prec < duk__str2num_digits_for_radix[radix - 2]) {
77318 				/* significant from precision perspective */
77319 
77320 				duk_small_int_t f_zero = duk__bi_is_zero(&nc_ctx->f);
77321 				if (f_zero && dig == 0) {
77322 					/* Leading zero is not counted towards precision digits; not
77323 					 * in the integer part, nor in the fraction part.
77324 					 */
77325 					if (dig_frac < 0) {
77326 						dig_lzero++;
77327 					}
77328 				} else {
77329 					/* XXX: join these ops (multiply-accumulate), but only if
77330 					 * code footprint decreases.
77331 					 */
77332 					duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->f, radix);
77333 					duk__bi_add_small(&nc_ctx->f, &nc_ctx->t1, dig);
77334 					dig_prec++;
77335 				}
77336 			} else {
77337 				/* Ignore digits beyond a radix-specific limit, but note them
77338 				 * in expt_adj.
77339 				 */
77340 				expt_adj++;
77341 			}
77342 
77343 			if (dig_frac >= 0) {
77344 				dig_frac++;
77345 				expt_adj--;
77346 			} else {
77347 				dig_whole++;
77348 			}
77349 		} else {
77350 			/* exponent digit */
77351 
77352 			expt = expt * radix + dig;
77353 			if (expt > DUK_S2N_MAX_EXPONENT) {
77354 				/* impose a reasonable exponent limit, so that exp
77355 				 * doesn't need to get tracked using a bigint.
77356 				 */
77357 				DUK_DDD(DUK_DDDPRINT("parse failed: exponent too large"));
77358 				goto parse_explimit_error;
77359 			}
77360 			dig_expt++;
77361 		}
77362 	}
77363 
77364 	/* Leading zero. */
77365 
77366 	if (dig_lzero > 0 && dig_whole > 1) {
77367 		if (!allow_leading_zero) {
77368 			DUK_DDD(DUK_DDDPRINT("parse failed: leading zeroes not allowed in integer part"));
77369 			goto parse_fail;
77370 		}
77371 	}
77372 
77373 	/* Validity checks for various fraction formats ("0.1", ".1", "1.", "."). */
77374 
77375 	if (dig_whole == 0) {
77376 		if (dig_frac == 0) {
77377 			/* "." is not accepted in any format */
77378 			DUK_DDD(DUK_DDDPRINT("parse failed: plain period without leading or trailing digits"));
77379 			goto parse_fail;
77380 		} else if (dig_frac > 0) {
77381 			/* ".123" */
77382 			if (!allow_naked_frac) {
77383 				DUK_DDD(DUK_DDDPRINT("parse failed: fraction part not allowed without "
77384 				                     "leading integer digit(s)"));
77385 				goto parse_fail;
77386 			}
77387 		} else {
77388 			/* empty ("") is allowed in some formats (e.g. Number(''), as zero */
77389 			if (!allow_empty) {
77390 				DUK_DDD(DUK_DDDPRINT("parse failed: empty string not allowed (as zero)"));
77391 				goto parse_fail;
77392 			}
77393 		}
77394 	} else {
77395 		if (dig_frac == 0) {
77396 			/* "123." is allowed in some formats */
77397 			if (!allow_empty_frac) {
77398 				DUK_DDD(DUK_DDDPRINT("parse failed: empty fractions"));
77399 				goto parse_fail;
77400 			}
77401 		} else if (dig_frac > 0) {
77402 			/* "123.456" */
77403 			;
77404 		} else {
77405 			/* "123" */
77406 			;
77407 		}
77408 	}
77409 
77410 	/* Exponent without digits (e.g. "1e" or "1e+").  If trailing garbage is
77411 	 * allowed, ignore exponent part as garbage (= parse as "1", i.e. exp 0).
77412 	 */
77413 
77414 	if (dig_expt == 0) {
77415 		if (!allow_garbage) {
77416 			DUK_DDD(DUK_DDDPRINT("parse failed: empty exponent"));
77417 			goto parse_fail;
77418 		}
77419 		DUK_ASSERT(expt == 0);
77420 	}
77421 
77422 	if (expt_neg) {
77423 		expt = -expt;
77424 	}
77425 	DUK_DDD(DUK_DDDPRINT("expt=%ld, expt_adj=%ld, net exponent -> %ld",
77426 	                     (long) expt, (long) expt_adj, (long) (expt + expt_adj)));
77427 	expt += expt_adj;
77428 
77429 	/* Fast path check. */
77430 
77431 	if (nc_ctx->f.n <= 1 &&   /* 32-bit value */
77432 	    expt == 0    /* no net exponent */) {
77433 		/* Fast path is triggered for no exponent and also for balanced exponent
77434 		 * and fraction parts, e.g. for "1.23e2" == "123".  Remember to respect
77435 		 * zero sign.
77436 		 */
77437 
77438 		/* XXX: could accept numbers larger than 32 bits, e.g. up to 53 bits? */
77439 		DUK_DDD(DUK_DDDPRINT("fast path number parse"));
77440 		if (nc_ctx->f.n == 1) {
77441 			res = (double) nc_ctx->f.v[0];
77442 		} else {
77443 			res = 0.0;
77444 		}
77445 		goto negcheck_and_ret;
77446 	}
77447 
77448 	/* Significand ('f') padding. */
77449 
77450 	while (dig_prec < duk__str2num_digits_for_radix[radix - 2]) {
77451 		/* Pad significand with "virtual" zero digits so that Dragon4 will
77452 		 * have enough (apparent) precision to work with.
77453 		 */
77454 		DUK_DDD(DUK_DDDPRINT("dig_prec=%ld, pad significand with zero", (long) dig_prec));
77455 		duk__bi_mul_small_copy(&nc_ctx->f, radix, &nc_ctx->t1);
77456 		DUK__BI_PRINT("f", &nc_ctx->f);
77457 		expt--;
77458 		dig_prec++;
77459 	}
77460 
77461 	DUK_DDD(DUK_DDDPRINT("final exponent: %ld", (long) expt));
77462 
77463 	/* Detect zero special case. */
77464 
77465 	if (nc_ctx->f.n == 0) {
77466 		/* This may happen even after the fast path check, if exponent is
77467 		 * not balanced (e.g. "0e1").  Remember to respect zero sign.
77468 		 */
77469 		DUK_DDD(DUK_DDDPRINT("significand is zero"));
77470 		res = 0.0;
77471 		goto negcheck_and_ret;
77472 	}
77473 
77474 
77475 	/* Quick reject of too large or too small exponents.  This check
77476 	 * would be incorrect for zero (e.g. "0e1000" is zero, not Infinity)
77477 	 * so zero check must be above.
77478 	 */
77479 
77480 	explim = &duk__str2num_exp_limits[radix - 2];
77481 	if (expt > explim->upper) {
77482 		DUK_DDD(DUK_DDDPRINT("exponent too large -> infinite"));
77483 		res = (duk_double_t) DUK_DOUBLE_INFINITY;
77484 		goto negcheck_and_ret;
77485 	} else if (expt < explim->lower) {
77486 		DUK_DDD(DUK_DDDPRINT("exponent too small -> zero"));
77487 		res = (duk_double_t) 0.0;
77488 		goto negcheck_and_ret;
77489 	}
77490 
77491 	nc_ctx->is_s2n = 1;
77492 	nc_ctx->e = expt;
77493 	nc_ctx->b = radix;
77494 	nc_ctx->B = 2;
77495 	nc_ctx->is_fixed = 1;
77496 	nc_ctx->abs_pos = 0;
77497 	nc_ctx->req_digits = 53 + 1;
77498 
77499 	DUK__BI_PRINT("f", &nc_ctx->f);
77500 	DUK_DDD(DUK_DDDPRINT("e=%ld", (long) nc_ctx->e));
77501 
77502 	/*
77503 	 *  Dragon4 slow path (binary) digit generation.
77504 	 *  An extra digit is generated for rounding.
77505 	 */
77506 
77507 	duk__dragon4_prepare(nc_ctx);  /* setup many variables in nc_ctx */
77508 
77509 	DUK_DDD(DUK_DDDPRINT("after prepare:"));
77510 	DUK__BI_PRINT("r", &nc_ctx->r);
77511 	DUK__BI_PRINT("s", &nc_ctx->s);
77512 	DUK__BI_PRINT("mp", &nc_ctx->mp);
77513 	DUK__BI_PRINT("mm", &nc_ctx->mm);
77514 
77515 	duk__dragon4_scale(nc_ctx);
77516 
77517 	DUK_DDD(DUK_DDDPRINT("after scale; k=%ld", (long) nc_ctx->k));
77518 	DUK__BI_PRINT("r", &nc_ctx->r);
77519 	DUK__BI_PRINT("s", &nc_ctx->s);
77520 	DUK__BI_PRINT("mp", &nc_ctx->mp);
77521 	DUK__BI_PRINT("mm", &nc_ctx->mm);
77522 
77523 	duk__dragon4_generate(nc_ctx);
77524 
77525 	DUK_ASSERT(nc_ctx->count == 53 + 1);
77526 
77527 	/*
77528 	 *  Convert binary digits into an IEEE double.  Need to handle
77529 	 *  denormals and rounding correctly.
77530 	 */
77531 
77532 	duk__dragon4_ctx_to_double(nc_ctx, &res);
77533 	goto negcheck_and_ret;
77534 
77535  negcheck_and_ret:
77536 	if (neg) {
77537 		res = -res;
77538 	}
77539 	duk_pop(ctx);
77540 	duk_push_number(ctx, (double) res);
77541 	DUK_DDD(DUK_DDDPRINT("result: %!T", (duk_tval *) duk_get_tval(ctx, -1)));
77542 	return;
77543 
77544  parse_fail:
77545 	DUK_DDD(DUK_DDDPRINT("parse failed"));
77546 	duk_pop(ctx);
77547 	duk_push_nan(ctx);
77548 	return;
77549 
77550  parse_explimit_error:
77551 	DUK_DDD(DUK_DDDPRINT("parse failed, internal error, can't return a value"));
77552 	DUK_ERROR_RANGE(thr, "exponent too large");
77553 	return;
77554 }
77555 /*
77556  *  Regexp compilation.
77557  *
77558  *  See doc/regexp.rst for a discussion of the compilation approach and
77559  *  current limitations.
77560  *
77561  *  Regexp bytecode assumes jumps can be expressed with signed 32-bit
77562  *  integers.  Consequently the bytecode size must not exceed 0x7fffffffL.
77563  *  The implementation casts duk_size_t (buffer size) to duk_(u)int32_t
77564  *  in many places.  Although this could be changed, the bytecode format
77565  *  limit would still prevent regexps exceeding the signed 32-bit limit
77566  *  from working.
77567  *
77568  *  XXX: The implementation does not prevent bytecode from exceeding the
77569  *  maximum supported size.  This could be done by limiting the maximum
77570  *  input string size (assuming an upper bound can be computed for number
77571  *  of bytecode bytes emitted per input byte) or checking buffer maximum
77572  *  size when emitting bytecode (slower).
77573  */
77574 
77575 /* include removed: duk_internal.h */
77576 
77577 #ifdef DUK_USE_REGEXP_SUPPORT
77578 
77579 /*
77580  *  Helper macros
77581  */
77582 
77583 #define DUK__RE_INITIAL_BUFSIZE 64
77584 
77585 #undef DUK__RE_BUFLEN
77586 #define DUK__RE_BUFLEN(re_ctx) \
77587 	DUK_BW_GET_SIZE(re_ctx->thr, &re_ctx->bw)
77588 
77589 /*
77590  *  Disjunction struct: result of parsing a disjunction
77591  */
77592 
77593 typedef struct {
77594 	/* Number of characters that the atom matches (e.g. 3 for 'abc'),
77595 	 * -1 if atom is complex and number of matched characters either
77596 	 * varies or is not known.
77597 	 */
77598 	duk_int32_t charlen;
77599 
77600 #if 0
77601 	/* These are not needed to implement quantifier capture handling,
77602 	 * but might be needed at some point.
77603 	 */
77604 
77605 	/* re_ctx->captures at start and end of atom parsing.
77606 	 * Since 'captures' indicates highest capture number emitted
77607 	 * so far in a DUK_REOP_SAVE, the captures numbers saved by
77608 	 * the atom are: ]start_captures,end_captures].
77609 	 */
77610 	duk_uint32_t start_captures;
77611 	duk_uint32_t end_captures;
77612 #endif
77613 } duk__re_disjunction_info;
77614 
77615 /*
77616  *  Encoding helpers
77617  *
77618  *  Some of the typing is bytecode based, e.g. slice sizes are unsigned 32-bit
77619  *  even though the buffer operations will use duk_size_t.
77620  */
77621 
77622 /* XXX: the insert helpers should ensure that the bytecode result is not
77623  * larger than expected (or at least assert for it).  Many things in the
77624  * bytecode, like skip offsets, won't work correctly if the bytecode is
77625  * larger than say 2G.
77626  */
77627 
77628 DUK_LOCAL duk_uint32_t duk__encode_i32(duk_int32_t x) {
77629 	if (x < 0) {
77630 		return ((duk_uint32_t) (-x)) * 2 + 1;
77631 	} else {
77632 		return ((duk_uint32_t) x) * 2;
77633 	}
77634 }
77635 
77636 /* XXX: return type should probably be duk_size_t, or explicit checks are needed for
77637  * maximum size.
77638  */
77639 DUK_LOCAL duk_uint32_t duk__insert_u32(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_uint32_t x) {
77640 	duk_uint8_t buf[DUK_UNICODE_MAX_XUTF8_LENGTH];
77641 	duk_small_int_t len;
77642 
77643 	len = duk_unicode_encode_xutf8((duk_ucodepoint_t) x, buf);
77644 	DUK_BW_INSERT_ENSURE_BYTES(re_ctx->thr, &re_ctx->bw, offset, buf, len);
77645 	return (duk_uint32_t) len;
77646 }
77647 
77648 DUK_LOCAL duk_uint32_t duk__append_u32(duk_re_compiler_ctx *re_ctx, duk_uint32_t x) {
77649 	duk_uint8_t buf[DUK_UNICODE_MAX_XUTF8_LENGTH];
77650 	duk_small_int_t len;
77651 
77652 	len = duk_unicode_encode_xutf8((duk_ucodepoint_t) x, buf);
77653 	DUK_BW_WRITE_ENSURE_BYTES(re_ctx->thr, &re_ctx->bw, buf, len);
77654 	return (duk_uint32_t) len;
77655 }
77656 
77657 DUK_LOCAL duk_uint32_t duk__insert_i32(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_int32_t x) {
77658 	return duk__insert_u32(re_ctx, offset, duk__encode_i32(x));
77659 }
77660 
77661 #if 0  /* unused */
77662 DUK_LOCAL duk_uint32_t duk__append_i32(duk_re_compiler_ctx *re_ctx, duk_int32_t x) {
77663 	return duk__append_u32(re_ctx, duk__encode_i32(x));
77664 }
77665 #endif
77666 
77667 /* special helper for emitting u16 lists (used for character ranges for built-in char classes) */
77668 DUK_LOCAL void duk__append_u16_list(duk_re_compiler_ctx *re_ctx, const duk_uint16_t *values, duk_uint32_t count) {
77669 	/* Call sites don't need the result length so it's not accumulated. */
77670 	while (count > 0) {
77671 		(void) duk__append_u32(re_ctx, (duk_uint32_t) (*values++));
77672 		count--;
77673 	}
77674 }
77675 
77676 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) {
77677 	DUK_BW_INSERT_ENSURE_SLICE(re_ctx->thr, &re_ctx->bw, offset, data_offset, data_length);
77678 }
77679 
77680 DUK_LOCAL void duk__append_slice(duk_re_compiler_ctx *re_ctx, duk_uint32_t data_offset, duk_uint32_t data_length) {
77681 	DUK_BW_WRITE_ENSURE_SLICE(re_ctx->thr, &re_ctx->bw, data_offset, data_length);
77682 }
77683 
77684 DUK_LOCAL void duk__remove_slice(duk_re_compiler_ctx *re_ctx, duk_uint32_t data_offset, duk_uint32_t data_length) {
77685 	DUK_BW_REMOVE_ENSURE_SLICE(re_ctx->thr, &re_ctx->bw, data_offset, data_length);
77686 }
77687 
77688 /*
77689  *  Insert a jump offset at 'offset' to complete an instruction
77690  *  (the jump offset is always the last component of an instruction).
77691  *  The 'skip' argument must be computed relative to 'offset',
77692  *  -without- taking into account the skip field being inserted.
77693  *
77694  *       ... A B C ins X Y Z ...   (ins may be a JUMP, SPLIT1/SPLIT2, etc)
77695  *   =>  ... A B C ins SKIP X Y Z
77696  *
77697  *  Computing the final (adjusted) skip value, which is relative to the
77698  *  first byte of the next instruction, is a bit tricky because of the
77699  *  variable length UTF-8 encoding.  See doc/regexp.rst for discussion.
77700  */
77701 DUK_LOCAL duk_uint32_t duk__insert_jump_offset(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_int32_t skip) {
77702 	duk_small_int_t len;
77703 
77704 	/* XXX: solve into closed form (smaller code) */
77705 
77706 	if (skip < 0) {
77707 		/* two encoding attempts suffices */
77708 		len = duk_unicode_get_xutf8_length((duk_codepoint_t) duk__encode_i32(skip));
77709 		len = duk_unicode_get_xutf8_length((duk_codepoint_t) duk__encode_i32(skip - (duk_int32_t) len));
77710 		DUK_ASSERT(duk_unicode_get_xutf8_length(duk__encode_i32(skip - (duk_int32_t) len)) == len);  /* no change */
77711 		skip -= (duk_int32_t) len;
77712 	}
77713 	return duk__insert_i32(re_ctx, offset, skip);
77714 }
77715 
77716 DUK_LOCAL duk_uint32_t duk__append_jump_offset(duk_re_compiler_ctx *re_ctx, duk_int32_t skip) {
77717 	return (duk_uint32_t) duk__insert_jump_offset(re_ctx, (duk_uint32_t) DUK__RE_BUFLEN(re_ctx), skip);
77718 }
77719 
77720 /*
77721  *  duk_re_range_callback for generating character class ranges.
77722  *
77723  *  When ignoreCase is false, the range is simply emitted as is.
77724  *  We don't, for instance, eliminate duplicates or overlapping
77725  *  ranges in a character class.
77726  *
77727  *  When ignoreCase is true, the range needs to be normalized through
77728  *  canonicalization.  Unfortunately a canonicalized version of a
77729  *  continuous range is not necessarily continuous (e.g. [x-{] is
77730  *  continuous but [X-{] is not).  The current algorithm creates the
77731  *  canonicalized range(s) space efficiently at the cost of compile
77732  *  time execution time (see doc/regexp.rst for discussion).
77733  *
77734  *  Note that the ctx->nranges is a context-wide temporary value
77735  *  (this is OK because there cannot be multiple character classes
77736  *  being parsed simultaneously).
77737  */
77738 
77739 DUK_LOCAL void duk__generate_ranges(void *userdata, duk_codepoint_t r1, duk_codepoint_t r2, duk_bool_t direct) {
77740 	duk_re_compiler_ctx *re_ctx = (duk_re_compiler_ctx *) userdata;
77741 
77742 	DUK_DD(DUK_DDPRINT("duk__generate_ranges(): re_ctx=%p, range=[%ld,%ld] direct=%ld",
77743 	                   (void *) re_ctx, (long) r1, (long) r2, (long) direct));
77744 
77745 	if (!direct && (re_ctx->re_flags & DUK_RE_FLAG_IGNORE_CASE)) {
77746 		/*
77747 		 *  Canonicalize a range, generating result ranges as necessary.
77748 		 *  Needs to exhaustively scan the entire range (at most 65536
77749 		 *  code points).  If 'direct' is set, caller (lexer) has ensured
77750 		 *  that the range is already canonicalization compatible (this
77751 		 *  is used to avoid unnecessary canonicalization of built-in
77752 		 *  ranges like \W, which are not affected by canonicalization).
77753 		 *
77754 		 *  NOTE: here is one place where we don't want to support chars
77755 		 *  outside the BMP, because the exhaustive search would be
77756 		 *  massively larger.
77757 		 */
77758 
77759 		duk_codepoint_t i;
77760 		duk_codepoint_t t;
77761 		duk_codepoint_t r_start, r_end;
77762 
77763 		r_start = duk_unicode_re_canonicalize_char(re_ctx->thr, r1);
77764 		r_end = r_start;
77765 		for (i = r1 + 1; i <= r2; i++) {
77766 			t = duk_unicode_re_canonicalize_char(re_ctx->thr, i);
77767 			if (t == r_end + 1) {
77768 				r_end = t;
77769 			} else {
77770 				DUK_DD(DUK_DDPRINT("canonicalized, emit range: [%ld,%ld]", (long) r_start, (long) r_end));
77771 				duk__append_u32(re_ctx, (duk_uint32_t) r_start);
77772 				duk__append_u32(re_ctx, (duk_uint32_t) r_end);
77773 				re_ctx->nranges++;
77774 				r_start = t;
77775 				r_end = t;
77776 			}
77777 		}
77778 		DUK_DD(DUK_DDPRINT("canonicalized, emit range: [%ld,%ld]", (long) r_start, (long) r_end));
77779 		duk__append_u32(re_ctx, (duk_uint32_t) r_start);
77780 		duk__append_u32(re_ctx, (duk_uint32_t) r_end);
77781 		re_ctx->nranges++;
77782 	} else {
77783 		DUK_DD(DUK_DDPRINT("direct, emit range: [%ld,%ld]", (long) r1, (long) r2));
77784 		duk__append_u32(re_ctx, (duk_uint32_t) r1);
77785 		duk__append_u32(re_ctx, (duk_uint32_t) r2);
77786 		re_ctx->nranges++;
77787 	}
77788 }
77789 
77790 /*
77791  *  Parse regexp Disjunction.  Most of regexp compilation happens here.
77792  *
77793  *  Handles Disjunction, Alternative, and Term productions directly without
77794  *  recursion.  The only constructs requiring recursion are positive/negative
77795  *  lookaheads, capturing parentheses, and non-capturing parentheses.
77796  *
77797  *  The function determines whether the entire disjunction is a 'simple atom'
77798  *  (see doc/regexp.rst discussion on 'simple quantifiers') and if so,
77799  *  returns the atom character length which is needed by the caller to keep
77800  *  track of its own atom character length.  A disjunction with more than one
77801  *  alternative is never considered a simple atom (although in some cases
77802  *  that might be the case).
77803  *
77804  *  Return value: simple atom character length or < 0 if not a simple atom.
77805  *  Appends the bytecode for the disjunction matcher to the end of the temp
77806  *  buffer.
77807  *
77808  *  Regexp top level structure is:
77809  *
77810  *    Disjunction = Term*
77811  *                | Term* | Disjunction
77812  *
77813  *    Term = Assertion
77814  *         | Atom
77815  *         | Atom Quantifier
77816  *
77817  *  An empty Term sequence is a valid disjunction alternative (e.g. /|||c||/).
77818  *
77819  *  Notes:
77820  *
77821  *    * Tracking of the 'simple-ness' of the current atom vs. the entire
77822  *      disjunction are separate matters.  For instance, the disjunction
77823  *      may be complex, but individual atoms may be simple.  Furthermore,
77824  *      simple quantifiers are used whenever possible, even if the
77825  *      disjunction as a whole is complex.
77826  *
77827  *    * The estimate of whether an atom is simple is conservative now,
77828  *      and it would be possible to expand it.  For instance, captures
77829  *      cause the disjunction to be marked complex, even though captures
77830  *      -can- be handled by simple quantifiers with some minor modifications.
77831  *
77832  *    * Disjunction 'tainting' as 'complex' is handled at the end of the
77833  *      main for loop collectively for atoms.  Assertions, quantifiers,
77834  *      and '|' tokens need to taint the result manually if necessary.
77835  *      Assertions cannot add to result char length, only atoms (and
77836  *      quantifiers) can; currently quantifiers will taint the result
77837  *      as complex though.
77838  */
77839 
77840 DUK_LOCAL void duk__parse_disjunction(duk_re_compiler_ctx *re_ctx, duk_bool_t expect_eof, duk__re_disjunction_info *out_atom_info) {
77841 	duk_int32_t atom_start_offset = -1;                   /* negative -> no atom matched on previous round */
77842 	duk_int32_t atom_char_length = 0;                     /* negative -> complex atom */
77843 	duk_uint32_t atom_start_captures = re_ctx->captures;  /* value of re_ctx->captures at start of atom */
77844 	duk_int32_t unpatched_disjunction_split = -1;
77845 	duk_int32_t unpatched_disjunction_jump = -1;
77846 	duk_uint32_t entry_offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx);
77847 	duk_int32_t res_charlen = 0;  /* -1 if disjunction is complex, char length if simple */
77848 	duk__re_disjunction_info tmp_disj;
77849 
77850 	DUK_ASSERT(out_atom_info != NULL);
77851 
77852 	if (re_ctx->recursion_depth >= re_ctx->recursion_limit) {
77853 		DUK_ERROR_RANGE(re_ctx->thr, DUK_STR_REGEXP_COMPILER_RECURSION_LIMIT);
77854 	}
77855 	re_ctx->recursion_depth++;
77856 
77857 #if 0
77858 	out_atom_info->start_captures = re_ctx->captures;
77859 #endif
77860 
77861 	for (;;) {
77862 		/* atom_char_length, atom_start_offset, atom_start_offset reflect the
77863 		 * atom matched on the previous loop.  If a quantifier is encountered
77864 		 * on this loop, these are needed to handle the quantifier correctly.
77865 		 * new_atom_char_length etc are for the atom parsed on this round;
77866 		 * they're written to atom_char_length etc at the end of the round.
77867 		 */
77868 		duk_int32_t new_atom_char_length;   /* char length of the atom parsed in this loop */
77869 		duk_int32_t new_atom_start_offset;  /* bytecode start offset of the atom parsed in this loop
77870 		                                     * (allows quantifiers to copy the atom bytecode)
77871 		                                     */
77872 		duk_uint32_t new_atom_start_captures;  /* re_ctx->captures at the start of the atom parsed in this loop */
77873 
77874 		duk_lexer_parse_re_token(&re_ctx->lex, &re_ctx->curr_token);
77875 
77876 		DUK_DD(DUK_DDPRINT("re token: %ld (num=%ld, char=%c)",
77877 		                   (long) re_ctx->curr_token.t,
77878 		                   (long) re_ctx->curr_token.num,
77879 		                   (re_ctx->curr_token.num >= 0x20 && re_ctx->curr_token.num <= 0x7e) ?
77880 		                   (int) re_ctx->curr_token.num : (int) '?'));
77881 
77882 		/* set by atom case clauses */
77883 		new_atom_start_offset = -1;
77884 		new_atom_char_length = -1;
77885 		new_atom_start_captures = re_ctx->captures;
77886 
77887 		switch (re_ctx->curr_token.t) {
77888 		case DUK_RETOK_DISJUNCTION: {
77889 			/*
77890 			 *  The handling here is a bit tricky.  If a previous '|' has been processed,
77891 			 *  we have a pending split1 and a pending jump (for a previous match).  These
77892 			 *  need to be back-patched carefully.  See docs for a detailed example.
77893 			 */
77894 
77895 			/* patch pending jump and split */
77896 			if (unpatched_disjunction_jump >= 0) {
77897 				duk_uint32_t offset;
77898 
77899 				DUK_ASSERT(unpatched_disjunction_split >= 0);
77900 				offset = unpatched_disjunction_jump;
77901 				offset += duk__insert_jump_offset(re_ctx,
77902 				                                  offset,
77903 				                                  (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - offset));
77904 				/* offset is now target of the pending split (right after jump) */
77905 				duk__insert_jump_offset(re_ctx,
77906 				                        unpatched_disjunction_split,
77907 				                        offset - unpatched_disjunction_split);
77908 			}
77909 
77910 			/* add a new pending split to the beginning of the entire disjunction */
77911 			(void) duk__insert_u32(re_ctx,
77912 			                       entry_offset,
77913 			                       DUK_REOP_SPLIT1);   /* prefer direct execution */
77914 			unpatched_disjunction_split = entry_offset + 1;   /* +1 for opcode */
77915 
77916 			/* add a new pending match jump for latest finished alternative */
77917 			duk__append_u32(re_ctx, DUK_REOP_JUMP);
77918 			unpatched_disjunction_jump = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
77919 
77920 			/* 'taint' result as complex */
77921 			res_charlen = -1;
77922 			break;
77923 		}
77924 		case DUK_RETOK_QUANTIFIER: {
77925 			if (atom_start_offset < 0) {
77926 				DUK_ERROR_SYNTAX(re_ctx->thr, DUK_STR_INVALID_QUANTIFIER_NO_ATOM);
77927 			}
77928 			if (re_ctx->curr_token.qmin > re_ctx->curr_token.qmax) {
77929 				DUK_ERROR_SYNTAX(re_ctx->thr, DUK_STR_INVALID_QUANTIFIER_VALUES);
77930 			}
77931 			if (atom_char_length >= 0) {
77932 				/*
77933 				 *  Simple atom
77934 				 *
77935 				 *  If atom_char_length is zero, we'll have unbounded execution time for e.g.
77936 				 *  /()*x/.exec('x').  We can't just skip the match because it might have some
77937 				 *  side effects (for instance, if we allowed captures in simple atoms, the
77938 				 *  capture needs to happen).  The simple solution below is to force the
77939 				 *  quantifier to match at most once, since the additional matches have no effect.
77940 				 *
77941 				 *  With a simple atom there can be no capture groups, so no captures need
77942 				 *  to be reset.
77943 				 */
77944 				duk_int32_t atom_code_length;
77945 				duk_uint32_t offset;
77946 				duk_uint32_t qmin, qmax;
77947 
77948 				qmin = re_ctx->curr_token.qmin;
77949 				qmax = re_ctx->curr_token.qmax;
77950 				if (atom_char_length == 0) {
77951 					/* qmin and qmax will be 0 or 1 */
77952 					if (qmin > 1) {
77953 						qmin = 1;
77954 					}
77955 					if (qmax > 1) {
77956 						qmax = 1;
77957 					}
77958 				}
77959 
77960 				duk__append_u32(re_ctx, DUK_REOP_MATCH);   /* complete 'sub atom' */
77961 				atom_code_length = (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - atom_start_offset);
77962 
77963 				offset = atom_start_offset;
77964 				if (re_ctx->curr_token.greedy) {
77965 					offset += duk__insert_u32(re_ctx, offset, DUK_REOP_SQGREEDY);
77966 					offset += duk__insert_u32(re_ctx, offset, qmin);
77967 					offset += duk__insert_u32(re_ctx, offset, qmax);
77968 					offset += duk__insert_u32(re_ctx, offset, atom_char_length);
77969 					offset += duk__insert_jump_offset(re_ctx, offset, atom_code_length);
77970 				} else {
77971 					offset += duk__insert_u32(re_ctx, offset, DUK_REOP_SQMINIMAL);
77972 					offset += duk__insert_u32(re_ctx, offset, qmin);
77973 					offset += duk__insert_u32(re_ctx, offset, qmax);
77974 					offset += duk__insert_jump_offset(re_ctx, offset, atom_code_length);
77975 				}
77976 				DUK_UNREF(offset);  /* silence scan-build warning */
77977 			} else {
77978 				/*
77979 				 *  Complex atom
77980 				 *
77981 				 *  The original code is used as a template, and removed at the end
77982 				 *  (this differs from the handling of simple quantifiers).
77983 				 *
77984 				 *  NOTE: there is no current solution for empty atoms in complex
77985 				 *  quantifiers.  This would need some sort of a 'progress' instruction.
77986 				 *
77987 				 *  XXX: impose limit on maximum result size, i.e. atom_code_len * atom_copies?
77988 				 */
77989 				duk_int32_t atom_code_length;
77990 				duk_uint32_t atom_copies;
77991 				duk_uint32_t tmp_qmin, tmp_qmax;
77992 
77993 				/* pre-check how many atom copies we're willing to make (atom_copies not needed below) */
77994 				atom_copies = (re_ctx->curr_token.qmax == DUK_RE_QUANTIFIER_INFINITE) ?
77995 				              re_ctx->curr_token.qmin : re_ctx->curr_token.qmax;
77996 				if (atom_copies > DUK_RE_MAX_ATOM_COPIES) {
77997 					DUK_ERROR_RANGE(re_ctx->thr, DUK_STR_QUANTIFIER_TOO_MANY_COPIES);
77998 				}
77999 
78000 				/* wipe the capture range made by the atom (if any) */
78001 				DUK_ASSERT(atom_start_captures <= re_ctx->captures);
78002 				if (atom_start_captures != re_ctx->captures) {
78003 					DUK_ASSERT(atom_start_captures < re_ctx->captures);
78004 					DUK_DDD(DUK_DDDPRINT("must wipe ]atom_start_captures,re_ctx->captures]: ]%ld,%ld]",
78005 					                     (long) atom_start_captures, (long) re_ctx->captures));
78006 
78007 					/* insert (DUK_REOP_WIPERANGE, start, count) in reverse order so the order ends up right */
78008 					duk__insert_u32(re_ctx, atom_start_offset, (re_ctx->captures - atom_start_captures) * 2);
78009 					duk__insert_u32(re_ctx, atom_start_offset, (atom_start_captures + 1) * 2);
78010 					duk__insert_u32(re_ctx, atom_start_offset, DUK_REOP_WIPERANGE);
78011 				} else {
78012 					DUK_DDD(DUK_DDDPRINT("no need to wipe captures: atom_start_captures == re_ctx->captures == %ld",
78013 					                     (long) atom_start_captures));
78014 				}
78015 
78016 				atom_code_length = (duk_int32_t) DUK__RE_BUFLEN(re_ctx) - atom_start_offset;
78017 
78018 				/* insert the required matches (qmin) by copying the atom */
78019 				tmp_qmin = re_ctx->curr_token.qmin;
78020 				tmp_qmax = re_ctx->curr_token.qmax;
78021 				while (tmp_qmin > 0) {
78022 					duk__append_slice(re_ctx, atom_start_offset, atom_code_length);
78023 					tmp_qmin--;
78024 					if (tmp_qmax != DUK_RE_QUANTIFIER_INFINITE) {
78025 						tmp_qmax--;
78026 					}
78027 				}
78028 				DUK_ASSERT(tmp_qmin == 0);
78029 
78030 				/* insert code for matching the remainder - infinite or finite */
78031 				if (tmp_qmax == DUK_RE_QUANTIFIER_INFINITE) {
78032 					/* reuse last emitted atom for remaining 'infinite' quantifier */
78033 
78034 					if (re_ctx->curr_token.qmin == 0) {
78035 						/* Special case: original qmin was zero so there is nothing
78036 						 * to repeat.  Emit an atom copy but jump over it here.
78037 						 */
78038 						duk__append_u32(re_ctx, DUK_REOP_JUMP);
78039 						duk__append_jump_offset(re_ctx, atom_code_length);
78040 						duk__append_slice(re_ctx, atom_start_offset, atom_code_length);
78041 					}
78042 					if (re_ctx->curr_token.greedy) {
78043 						duk__append_u32(re_ctx, DUK_REOP_SPLIT2);   /* prefer jump */
78044 					} else {
78045 						duk__append_u32(re_ctx, DUK_REOP_SPLIT1);   /* prefer direct */
78046 					}
78047 					duk__append_jump_offset(re_ctx, -atom_code_length - 1);  /* -1 for opcode */
78048 				} else {
78049 					/*
78050 					 *  The remaining matches are emitted as sequence of SPLITs and atom
78051 					 *  copies; the SPLITs skip the remaining copies and match the sequel.
78052 					 *  This sequence needs to be emitted starting from the last copy
78053 					 *  because the SPLITs are variable length due to the variable length
78054 					 *  skip offset.  This causes a lot of memory copying now.
78055 					 *
78056 					 *  Example structure (greedy, match maximum # atoms):
78057 					 *
78058 					 *      SPLIT1 LSEQ
78059 					 *      (atom)
78060 					 *      SPLIT1 LSEQ    ; <- the byte length of this instruction is needed
78061 					 *      (atom)         ; to encode the above SPLIT1 correctly
78062 					 *      ...
78063 					 *   LSEQ:
78064 					 */
78065 					duk_uint32_t offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx);
78066 					while (tmp_qmax > 0) {
78067 						duk__insert_slice(re_ctx, offset, atom_start_offset, atom_code_length);
78068 						if (re_ctx->curr_token.greedy) {
78069 							duk__insert_u32(re_ctx, offset, DUK_REOP_SPLIT1);   /* prefer direct */
78070 						} else {
78071 							duk__insert_u32(re_ctx, offset, DUK_REOP_SPLIT2);   /* prefer jump */
78072 						}
78073 						duk__insert_jump_offset(re_ctx,
78074 						                        offset + 1,   /* +1 for opcode */
78075 						                        (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - (offset + 1)));
78076 						tmp_qmax--;
78077 					}
78078 				}
78079 
78080 				/* remove the original 'template' atom */
78081 				duk__remove_slice(re_ctx, atom_start_offset, atom_code_length);
78082 			}
78083 
78084 			/* 'taint' result as complex */
78085 			res_charlen = -1;
78086 			break;
78087 		}
78088 		case DUK_RETOK_ASSERT_START: {
78089 			duk__append_u32(re_ctx, DUK_REOP_ASSERT_START);
78090 			break;
78091 		}
78092 		case DUK_RETOK_ASSERT_END: {
78093 			duk__append_u32(re_ctx, DUK_REOP_ASSERT_END);
78094 			break;
78095 		}
78096 		case DUK_RETOK_ASSERT_WORD_BOUNDARY: {
78097 			duk__append_u32(re_ctx, DUK_REOP_ASSERT_WORD_BOUNDARY);
78098 			break;
78099 		}
78100 		case DUK_RETOK_ASSERT_NOT_WORD_BOUNDARY: {
78101 			duk__append_u32(re_ctx, DUK_REOP_ASSERT_NOT_WORD_BOUNDARY);
78102 			break;
78103 		}
78104 		case DUK_RETOK_ASSERT_START_POS_LOOKAHEAD:
78105 		case DUK_RETOK_ASSERT_START_NEG_LOOKAHEAD: {
78106 			duk_uint32_t offset;
78107 			duk_uint32_t opcode = (re_ctx->curr_token.t == DUK_RETOK_ASSERT_START_POS_LOOKAHEAD) ?
78108 			                      DUK_REOP_LOOKPOS : DUK_REOP_LOOKNEG;
78109 
78110 			offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx);
78111 			duk__parse_disjunction(re_ctx, 0, &tmp_disj);
78112 			duk__append_u32(re_ctx, DUK_REOP_MATCH);
78113 
78114 			(void) duk__insert_u32(re_ctx, offset, opcode);
78115 			(void) duk__insert_jump_offset(re_ctx,
78116 			                               offset + 1,   /* +1 for opcode */
78117 			                               (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - (offset + 1)));
78118 
78119 			/* 'taint' result as complex -- this is conservative,
78120 			 * as lookaheads do not backtrack.
78121 			 */
78122 			res_charlen = -1;
78123 			break;
78124 		}
78125 		case DUK_RETOK_ATOM_PERIOD: {
78126 			new_atom_char_length = 1;
78127 			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
78128 			duk__append_u32(re_ctx, DUK_REOP_PERIOD);
78129 			break;
78130 		}
78131 		case DUK_RETOK_ATOM_CHAR: {
78132 			/* Note: successive characters could be joined into string matches
78133 			 * but this is not trivial (consider e.g. '/xyz+/); see docs for
78134 			 * more discussion.
78135 			 */
78136 			duk_uint32_t ch;
78137 
78138 			new_atom_char_length = 1;
78139 			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
78140 			duk__append_u32(re_ctx, DUK_REOP_CHAR);
78141 			ch = re_ctx->curr_token.num;
78142 			if (re_ctx->re_flags & DUK_RE_FLAG_IGNORE_CASE) {
78143 				ch = duk_unicode_re_canonicalize_char(re_ctx->thr, ch);
78144 			}
78145 			duk__append_u32(re_ctx, ch);
78146 			break;
78147 		}
78148 		case DUK_RETOK_ATOM_DIGIT:
78149 		case DUK_RETOK_ATOM_NOT_DIGIT: {
78150 			new_atom_char_length = 1;
78151 			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
78152 			duk__append_u32(re_ctx,
78153 			                (re_ctx->curr_token.t == DUK_RETOK_ATOM_DIGIT) ?
78154 			                DUK_REOP_RANGES : DUK_REOP_INVRANGES);
78155 			duk__append_u32(re_ctx, sizeof(duk_unicode_re_ranges_digit) / (2 * sizeof(duk_uint16_t)));
78156 			duk__append_u16_list(re_ctx, duk_unicode_re_ranges_digit, sizeof(duk_unicode_re_ranges_digit) / sizeof(duk_uint16_t));
78157 			break;
78158 		}
78159 		case DUK_RETOK_ATOM_WHITE:
78160 		case DUK_RETOK_ATOM_NOT_WHITE: {
78161 			new_atom_char_length = 1;
78162 			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
78163 			duk__append_u32(re_ctx,
78164 			                (re_ctx->curr_token.t == DUK_RETOK_ATOM_WHITE) ?
78165 			                DUK_REOP_RANGES : DUK_REOP_INVRANGES);
78166 			duk__append_u32(re_ctx, sizeof(duk_unicode_re_ranges_white) / (2 * sizeof(duk_uint16_t)));
78167 			duk__append_u16_list(re_ctx, duk_unicode_re_ranges_white, sizeof(duk_unicode_re_ranges_white) / sizeof(duk_uint16_t));
78168 			break;
78169 		}
78170 		case DUK_RETOK_ATOM_WORD_CHAR:
78171 		case DUK_RETOK_ATOM_NOT_WORD_CHAR: {
78172 			new_atom_char_length = 1;
78173 			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
78174 			duk__append_u32(re_ctx,
78175 			                (re_ctx->curr_token.t == DUK_RETOK_ATOM_WORD_CHAR) ?
78176 			                DUK_REOP_RANGES : DUK_REOP_INVRANGES);
78177 			duk__append_u32(re_ctx, sizeof(duk_unicode_re_ranges_wordchar) / (2 * sizeof(duk_uint16_t)));
78178 			duk__append_u16_list(re_ctx, duk_unicode_re_ranges_wordchar, sizeof(duk_unicode_re_ranges_wordchar) / sizeof(duk_uint16_t));
78179 			break;
78180 		}
78181 		case DUK_RETOK_ATOM_BACKREFERENCE: {
78182 			duk_uint32_t backref = (duk_uint32_t) re_ctx->curr_token.num;
78183 			if (backref > re_ctx->highest_backref) {
78184 				re_ctx->highest_backref = backref;
78185 			}
78186 			new_atom_char_length = -1;   /* mark as complex */
78187 			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
78188 			duk__append_u32(re_ctx, DUK_REOP_BACKREFERENCE);
78189 			duk__append_u32(re_ctx, backref);
78190 			break;
78191 		}
78192 		case DUK_RETOK_ATOM_START_CAPTURE_GROUP: {
78193 			duk_uint32_t cap;
78194 
78195 			new_atom_char_length = -1;   /* mark as complex (capture handling) */
78196 			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
78197 			cap = ++re_ctx->captures;
78198 			duk__append_u32(re_ctx, DUK_REOP_SAVE);
78199 			duk__append_u32(re_ctx, cap * 2);
78200 			duk__parse_disjunction(re_ctx, 0, &tmp_disj);  /* retval (sub-atom char length) unused, tainted as complex above */
78201 			duk__append_u32(re_ctx, DUK_REOP_SAVE);
78202 			duk__append_u32(re_ctx, cap * 2 + 1);
78203 			break;
78204 		}
78205 		case DUK_RETOK_ATOM_START_NONCAPTURE_GROUP: {
78206 			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
78207 			duk__parse_disjunction(re_ctx, 0, &tmp_disj);
78208 			new_atom_char_length = tmp_disj.charlen;
78209 			break;
78210 		}
78211 		case DUK_RETOK_ATOM_START_CHARCLASS:
78212 		case DUK_RETOK_ATOM_START_CHARCLASS_INVERTED: {
78213 			/*
78214 			 *  Range parsing is done with a special lexer function which calls
78215 			 *  us for every range parsed.  This is different from how rest of
78216 			 *  the parsing works, but avoids a heavy, arbitrary size intermediate
78217 			 *  value type to hold the ranges.
78218 			 *
78219 			 *  Another complication is the handling of character ranges when
78220 			 *  case insensitive matching is used (see docs for discussion).
78221 			 *  The range handler callback given to the lexer takes care of this
78222 			 *  as well.
78223 			 *
78224 			 *  Note that duplicate ranges are not eliminated when parsing character
78225 			 *  classes, so that canonicalization of
78226 			 *
78227 			 *    [0-9a-fA-Fx-{]
78228 			 *
78229 			 *  creates the result (note the duplicate ranges):
78230 			 *
78231 			 *    [0-9A-FA-FX-Z{-{]
78232 			 *
78233 			 *  where [x-{] is split as a result of canonicalization.  The duplicate
78234 			 *  ranges are not a semantics issue: they work correctly.
78235 			 */
78236 
78237 			duk_uint32_t offset;
78238 
78239 			DUK_DD(DUK_DDPRINT("character class"));
78240 
78241 			/* insert ranges instruction, range count patched in later */
78242 			new_atom_char_length = 1;
78243 			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
78244 			duk__append_u32(re_ctx,
78245 			                (re_ctx->curr_token.t == DUK_RETOK_ATOM_START_CHARCLASS) ?
78246 			                DUK_REOP_RANGES : DUK_REOP_INVRANGES);
78247 			offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx);    /* patch in range count later */
78248 
78249 			/* parse ranges until character class ends */
78250 			re_ctx->nranges = 0;    /* note: ctx-wide temporary */
78251 			duk_lexer_parse_re_ranges(&re_ctx->lex, duk__generate_ranges, (void *) re_ctx);
78252 
78253 			/* insert range count */
78254 			duk__insert_u32(re_ctx, offset, re_ctx->nranges);
78255 			break;
78256 		}
78257 		case DUK_RETOK_ATOM_END_GROUP: {
78258 			if (expect_eof) {
78259 				DUK_ERROR_SYNTAX(re_ctx->thr, DUK_STR_UNEXPECTED_CLOSING_PAREN);
78260 			}
78261 			goto done;
78262 		}
78263 		case DUK_RETOK_EOF: {
78264 			if (!expect_eof) {
78265 				DUK_ERROR_SYNTAX(re_ctx->thr, DUK_STR_UNEXPECTED_END_OF_PATTERN);
78266 			}
78267 			goto done;
78268 		}
78269 		default: {
78270 			DUK_ERROR_SYNTAX(re_ctx->thr, DUK_STR_UNEXPECTED_REGEXP_TOKEN);
78271 		}
78272 		}
78273 
78274 		/* a complex (new) atom taints the result */
78275 		if (new_atom_start_offset >= 0) {
78276 			if (new_atom_char_length < 0) {
78277 				res_charlen = -1;
78278 			} else if (res_charlen >= 0) {
78279 				/* only advance if not tainted */
78280 				res_charlen += new_atom_char_length;
78281 			}
78282 		}
78283 
78284 		/* record previous atom info in case next token is a quantifier */
78285 		atom_start_offset = new_atom_start_offset;
78286 		atom_char_length = new_atom_char_length;
78287 		atom_start_captures = new_atom_start_captures;
78288 	}
78289 
78290  done:
78291 
78292 	/* finish up pending jump and split for last alternative */
78293 	if (unpatched_disjunction_jump >= 0) {
78294 		duk_uint32_t offset;
78295 
78296 		DUK_ASSERT(unpatched_disjunction_split >= 0);
78297 		offset = unpatched_disjunction_jump;
78298 		offset += duk__insert_jump_offset(re_ctx,
78299 		                                  offset,
78300 		                                  (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - offset));
78301 		/* offset is now target of the pending split (right after jump) */
78302 		duk__insert_jump_offset(re_ctx,
78303 		                        unpatched_disjunction_split,
78304 		                        offset - unpatched_disjunction_split);
78305 	}
78306 
78307 #if 0
78308 	out_atom_info->end_captures = re_ctx->captures;
78309 #endif
78310 	out_atom_info->charlen = res_charlen;
78311 	DUK_DDD(DUK_DDDPRINT("parse disjunction finished: charlen=%ld",
78312 	                     (long) out_atom_info->charlen));
78313 
78314 	re_ctx->recursion_depth--;
78315 }
78316 
78317 /*
78318  *  Flags parsing (see E5 Section 15.10.4.1).
78319  */
78320 
78321 DUK_LOCAL duk_uint32_t duk__parse_regexp_flags(duk_hthread *thr, duk_hstring *h) {
78322 	const duk_uint8_t *p;
78323 	const duk_uint8_t *p_end;
78324 	duk_uint32_t flags = 0;
78325 
78326 	p = DUK_HSTRING_GET_DATA(h);
78327 	p_end = p + DUK_HSTRING_GET_BYTELEN(h);
78328 
78329 	/* Note: can be safely scanned as bytes (undecoded) */
78330 
78331 	while (p < p_end) {
78332 		duk_uint8_t c = *p++;
78333 		switch ((int) c) {
78334 		case (int) 'g': {
78335 			if (flags & DUK_RE_FLAG_GLOBAL) {
78336 				goto error;
78337 			}
78338 			flags |= DUK_RE_FLAG_GLOBAL;
78339 			break;
78340 		}
78341 		case (int) 'i': {
78342 			if (flags & DUK_RE_FLAG_IGNORE_CASE) {
78343 				goto error;
78344 			}
78345 			flags |= DUK_RE_FLAG_IGNORE_CASE;
78346 			break;
78347 		}
78348 		case (int) 'm': {
78349 			if (flags & DUK_RE_FLAG_MULTILINE) {
78350 				goto error;
78351 			}
78352 			flags |= DUK_RE_FLAG_MULTILINE;
78353 			break;
78354 		}
78355 		default: {
78356 			goto error;
78357 		}
78358 		}
78359 	}
78360 
78361 	return flags;
78362 
78363  error:
78364 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_REGEXP_FLAGS);
78365 	return 0;  /* never here */
78366 }
78367 
78368 /*
78369  *  Create escaped RegExp source (E5 Section 15.10.3).
78370  *
78371  *  The current approach is to special case the empty RegExp
78372  *  ('' -> '(?:)') and otherwise replace unescaped '/' characters
78373  *  with '\/' regardless of where they occur in the regexp.
78374  *
78375  *  Note that normalization does not seem to be necessary for
78376  *  RegExp literals (e.g. '/foo/') because to be acceptable as
78377  *  a RegExp literal, the text between forward slashes must
78378  *  already match the escaping requirements (e.g. must not contain
78379  *  unescaped forward slashes or be empty).  Escaping IS needed
78380  *  for expressions like 'new Regexp("...", "")' however.
78381  *  Currently, we re-escape in either case.
78382  *
78383  *  Also note that we process the source here in UTF-8 encoded
78384  *  form.  This is correct, because any non-ASCII characters are
78385  *  passed through without change.
78386  */
78387 
78388 DUK_LOCAL void duk__create_escaped_source(duk_hthread *thr, int idx_pattern) {
78389 	duk_context *ctx = (duk_context *) thr;
78390 	duk_hstring *h;
78391 	const duk_uint8_t *p;
78392 	duk_bufwriter_ctx bw_alloc;
78393 	duk_bufwriter_ctx *bw;
78394 	duk_uint8_t *q;
78395 	duk_size_t i, n;
78396 	duk_uint_fast8_t c_prev, c;
78397 
78398 	h = duk_get_hstring(ctx, idx_pattern);
78399 	DUK_ASSERT(h != NULL);
78400 	p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
78401 	n = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h);
78402 
78403 	if (n == 0) {
78404 		/* return '(?:)' */
78405 		duk_push_hstring_stridx(ctx, DUK_STRIDX_ESCAPED_EMPTY_REGEXP);
78406 		return;
78407 	}
78408 
78409 	bw = &bw_alloc;
78410 	DUK_BW_INIT_PUSHBUF(thr, bw, n);
78411 	q = DUK_BW_GET_PTR(thr, bw);
78412 
78413 	c_prev = (duk_uint_fast8_t) 0;
78414 
78415 	for (i = 0; i < n; i++) {
78416 		c = p[i];
78417 
78418 		q = DUK_BW_ENSURE_RAW(thr, bw, 2, q);
78419 
78420 		if (c == (duk_uint_fast8_t) '/' && c_prev != (duk_uint_fast8_t) '\\') {
78421 			/* Unescaped '/' ANYWHERE in the regexp (in disjunction,
78422 			 * inside a character class, ...) => same escape works.
78423 			 */
78424 			*q++ = DUK_ASC_BACKSLASH;
78425 		}
78426 		*q++ = (duk_uint8_t) c;
78427 
78428 		c_prev = c;
78429 	}
78430 
78431 	DUK_BW_SETPTR_AND_COMPACT(thr, bw, q);
78432 	duk_to_string(ctx, -1);  /* -> [ ... escaped_source ] */
78433 }
78434 
78435 /*
78436  *  Exposed regexp compilation primitive.
78437  *
78438  *  Sets up a regexp compilation context, and calls duk__parse_disjunction() to do the
78439  *  actual parsing.  Handles generation of the compiled regexp header and the
78440  *  "boilerplate" capture of the matching substring (save 0 and 1).  Also does some
78441  *  global level regexp checks after recursive compilation has finished.
78442  *
78443  *  An escaped version of the regexp source, suitable for use as a RegExp instance
78444  *  'source' property (see E5 Section 15.10.3), is also left on the stack.
78445  *
78446  *  Input stack:  [ pattern flags ]
78447  *  Output stack: [ bytecode escaped_source ]  (both as strings)
78448  */
78449 
78450 DUK_INTERNAL void duk_regexp_compile(duk_hthread *thr) {
78451 	duk_context *ctx = (duk_context *) thr;
78452 	duk_re_compiler_ctx re_ctx;
78453 	duk_lexer_point lex_point;
78454 	duk_hstring *h_pattern;
78455 	duk_hstring *h_flags;
78456 	duk__re_disjunction_info ign_disj;
78457 
78458 	DUK_ASSERT(thr != NULL);
78459 	DUK_ASSERT(ctx != NULL);
78460 
78461 	/*
78462 	 *  Args validation
78463 	 */
78464 
78465 	/* TypeError if fails */
78466 	h_pattern = duk_require_hstring(ctx, -2);
78467 	h_flags = duk_require_hstring(ctx, -1);
78468 
78469 	/*
78470 	 *  Create normalized 'source' property (E5 Section 15.10.3).
78471 	 */
78472 
78473 	/* [ ... pattern flags ] */
78474 
78475 	duk__create_escaped_source(thr, -2);
78476 
78477 	/* [ ... pattern flags escaped_source ] */
78478 
78479 	/*
78480 	 *  Init compilation context
78481 	 */
78482 
78483 	/* [ ... pattern flags escaped_source buffer ] */
78484 
78485 	DUK_MEMZERO(&re_ctx, sizeof(re_ctx));
78486 	DUK_LEXER_INITCTX(&re_ctx.lex);  /* duplicate zeroing, expect for (possible) NULL inits */
78487 	re_ctx.thr = thr;
78488 	re_ctx.lex.thr = thr;
78489 	re_ctx.lex.input = DUK_HSTRING_GET_DATA(h_pattern);
78490 	re_ctx.lex.input_length = DUK_HSTRING_GET_BYTELEN(h_pattern);
78491 	re_ctx.lex.token_limit = DUK_RE_COMPILE_TOKEN_LIMIT;
78492 	re_ctx.recursion_limit = DUK_USE_REGEXP_COMPILER_RECLIMIT;
78493 	re_ctx.re_flags = duk__parse_regexp_flags(thr, h_flags);
78494 
78495 	DUK_BW_INIT_PUSHBUF(thr, &re_ctx.bw, DUK__RE_INITIAL_BUFSIZE);
78496 
78497 	DUK_DD(DUK_DDPRINT("regexp compiler ctx initialized, flags=0x%08lx, recursion_limit=%ld",
78498 	                   (unsigned long) re_ctx.re_flags, (long) re_ctx.recursion_limit));
78499 
78500 	/*
78501 	 *  Init lexer
78502 	 */
78503 
78504 	lex_point.offset = 0;  /* expensive init, just want to fill window */
78505 	lex_point.line = 1;
78506 	DUK_LEXER_SETPOINT(&re_ctx.lex, &lex_point);
78507 
78508 	/*
78509 	 *  Compilation
78510 	 */
78511 
78512 	DUK_DD(DUK_DDPRINT("starting regexp compilation"));
78513 
78514 	duk__append_u32(&re_ctx, DUK_REOP_SAVE);
78515 	duk__append_u32(&re_ctx, 0);
78516 	duk__parse_disjunction(&re_ctx, 1 /*expect_eof*/, &ign_disj);
78517 	duk__append_u32(&re_ctx, DUK_REOP_SAVE);
78518 	duk__append_u32(&re_ctx, 1);
78519 	duk__append_u32(&re_ctx, DUK_REOP_MATCH);
78520 
78521 	/*
78522 	 *  Check for invalid backreferences; note that it is NOT an error
78523 	 *  to back-reference a capture group which has not yet been introduced
78524 	 *  in the pattern (as in /\1(foo)/); in fact, the backreference will
78525 	 *  always match!  It IS an error to back-reference a capture group
78526 	 *  which will never be introduced in the pattern.  Thus, we can check
78527 	 *  for such references only after parsing is complete.
78528 	 */
78529 
78530 	if (re_ctx.highest_backref > re_ctx.captures) {
78531 		DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_BACKREFS);
78532 	}
78533 
78534 	/*
78535 	 *  Emit compiled regexp header: flags, ncaptures
78536 	 *  (insertion order inverted on purpose)
78537 	 */
78538 
78539 	duk__insert_u32(&re_ctx, 0, (re_ctx.captures + 1) * 2);
78540 	duk__insert_u32(&re_ctx, 0, re_ctx.re_flags);
78541 
78542 	/* [ ... pattern flags escaped_source buffer ] */
78543 
78544 	DUK_BW_COMPACT(thr, &re_ctx.bw);
78545 	duk_to_string(ctx, -1);  /* coerce to string */
78546 
78547 	/* [ ... pattern flags escaped_source bytecode ] */
78548 
78549 	/*
78550 	 *  Finalize stack
78551 	 */
78552 
78553 	duk_remove(ctx, -4);     /* -> [ ... flags escaped_source bytecode ] */
78554 	duk_remove(ctx, -3);     /* -> [ ... escaped_source bytecode ] */
78555 
78556 	DUK_DD(DUK_DDPRINT("regexp compilation successful, bytecode: %!T, escaped source: %!T",
78557 	                   (duk_tval *) duk_get_tval(ctx, -1), (duk_tval *) duk_get_tval(ctx, -2)));
78558 }
78559 
78560 /*
78561  *  Create a RegExp instance (E5 Section 15.10.7).
78562  *
78563  *  Note: the output stack left by duk_regexp_compile() is directly compatible
78564  *  with the input here.
78565  *
78566  *  Input stack:  [ escaped_source bytecode ]  (both as strings)
78567  *  Output stack: [ RegExp ]
78568  */
78569 
78570 DUK_INTERNAL void duk_regexp_create_instance(duk_hthread *thr) {
78571 	duk_context *ctx = (duk_context *) thr;
78572 	duk_hobject *h;
78573 	duk_hstring *h_bc;
78574 	duk_small_int_t re_flags;
78575 
78576 	/* [ ... escape_source bytecode ] */
78577 
78578 	h_bc = duk_get_hstring(ctx, -1);
78579 	DUK_ASSERT(h_bc != NULL);
78580 	DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(h_bc) >= 1);          /* always at least the header */
78581 	DUK_ASSERT(DUK_HSTRING_GET_CHARLEN(h_bc) >= 1);
78582 	DUK_ASSERT((duk_small_int_t) DUK_HSTRING_GET_DATA(h_bc)[0] < 0x80);  /* flags always encodes to 1 byte */
78583 	re_flags = (duk_small_int_t) DUK_HSTRING_GET_DATA(h_bc)[0];
78584 
78585 	/* [ ... escaped_source bytecode ] */
78586 
78587 	duk_push_object(ctx);
78588 	h = duk_get_hobject(ctx, -1);
78589 	DUK_ASSERT(h != NULL);
78590 	duk_insert(ctx, -3);
78591 
78592 	/* [ ... regexp_object escaped_source bytecode ] */
78593 
78594 	DUK_HOBJECT_SET_CLASS_NUMBER(h, DUK_HOBJECT_CLASS_REGEXP);
78595 	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h, thr->builtins[DUK_BIDX_REGEXP_PROTOTYPE]);
78596 
78597 	duk_xdef_prop_stridx(ctx, -3, DUK_STRIDX_INT_BYTECODE, DUK_PROPDESC_FLAGS_NONE);
78598 
78599 	/* [ ... regexp_object escaped_source ] */
78600 
78601 	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_SOURCE, DUK_PROPDESC_FLAGS_NONE);
78602 
78603 	/* [ ... regexp_object ] */
78604 
78605 	duk_push_boolean(ctx, (re_flags & DUK_RE_FLAG_GLOBAL));
78606 	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_GLOBAL, DUK_PROPDESC_FLAGS_NONE);
78607 
78608 	duk_push_boolean(ctx, (re_flags & DUK_RE_FLAG_IGNORE_CASE));
78609 	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_IGNORE_CASE, DUK_PROPDESC_FLAGS_NONE);
78610 
78611 	duk_push_boolean(ctx, (re_flags & DUK_RE_FLAG_MULTILINE));
78612 	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_MULTILINE, DUK_PROPDESC_FLAGS_NONE);
78613 
78614 	duk_push_int(ctx, 0);
78615 	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LAST_INDEX, DUK_PROPDESC_FLAGS_W);
78616 
78617 	/* [ ... regexp_object ] */
78618 }
78619 
78620 #undef DUK__RE_BUFLEN
78621 
78622 #else  /* DUK_USE_REGEXP_SUPPORT */
78623 
78624 /* regexp support disabled */
78625 
78626 #endif  /* DUK_USE_REGEXP_SUPPORT */
78627 /*
78628  *  Regexp executor.
78629  *
78630  *  Safety: the Ecmascript executor should prevent user from reading and
78631  *  replacing regexp bytecode.  Even so, the executor must validate all
78632  *  memory accesses etc.  When an invalid access is detected (e.g. a 'save'
78633  *  opcode to invalid, unallocated index) it should fail with an internal
78634  *  error but not cause a segmentation fault.
78635  *
78636  *  Notes:
78637  *
78638  *    - Backtrack counts are limited to unsigned 32 bits but should
78639  *      technically be duk_size_t for strings longer than 4G chars.
78640  *      This also requires a regexp bytecode change.
78641  */
78642 
78643 /* include removed: duk_internal.h */
78644 
78645 #ifdef DUK_USE_REGEXP_SUPPORT
78646 
78647 /*
78648  *  Helpers for UTF-8 handling
78649  *
78650  *  For bytecode readers the duk_uint32_t and duk_int32_t types are correct
78651  *  because they're used for more than just codepoints.
78652  */
78653 
78654 DUK_LOCAL duk_uint32_t duk__bc_get_u32(duk_re_matcher_ctx *re_ctx, const duk_uint8_t **pc) {
78655 	return (duk_uint32_t) duk_unicode_decode_xutf8_checked(re_ctx->thr, pc, re_ctx->bytecode, re_ctx->bytecode_end);
78656 }
78657 
78658 DUK_LOCAL duk_int32_t duk__bc_get_i32(duk_re_matcher_ctx *re_ctx, const duk_uint8_t **pc) {
78659 	duk_uint32_t t;
78660 
78661 	/* signed integer encoding needed to work with UTF-8 */
78662 	t = (duk_uint32_t) duk_unicode_decode_xutf8_checked(re_ctx->thr, pc, re_ctx->bytecode, re_ctx->bytecode_end);
78663 	if (t & 1) {
78664 		return -((duk_int32_t) (t >> 1));
78665 	} else {
78666 		return (duk_int32_t) (t >> 1);
78667 	}
78668 }
78669 
78670 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) {
78671 	const duk_uint8_t *p;
78672 
78673 	/* Note: allow backtracking from p == ptr_end */
78674 	p = *ptr;
78675 	if (p < ptr_start || p > ptr_end) {
78676 		goto fail;
78677 	}
78678 
78679 	while (count > 0) {
78680 		for (;;) {
78681 			p--;
78682 			if (p < ptr_start) {
78683 				goto fail;
78684 			}
78685 			if ((*p & 0xc0) != 0x80) {
78686 				/* utf-8 continuation bytes have the form 10xx xxxx */
78687 				break;
78688 			}
78689 		}
78690 		count--;
78691 	}
78692 	*ptr = p;
78693 	return p;
78694 
78695  fail:
78696 	DUK_ERROR_INTERNAL_DEFMSG(thr);
78697 	return NULL;  /* never here */
78698 }
78699 
78700 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) {
78701 	const duk_uint8_t *p;
78702 
78703 	p = *ptr;
78704 	if (p < ptr_start || p >= ptr_end) {
78705 		goto fail;
78706 	}
78707 
78708 	while (count > 0) {
78709 		for (;;) {
78710 			p++;
78711 
78712 			/* Note: if encoding ends by hitting end of input, we don't check that
78713 			 * the encoding is valid, we just assume it is.
78714 			 */
78715 			if (p >= ptr_end || ((*p & 0xc0) != 0x80)) {
78716 				/* utf-8 continuation bytes have the form 10xx xxxx */
78717 				break;
78718 			}
78719 		}
78720 		count--;
78721 	}
78722 
78723 	*ptr = p;
78724 	return p;
78725 
78726  fail:
78727 	DUK_ERROR_INTERNAL_DEFMSG(thr);
78728 	return NULL;  /* never here */
78729 }
78730 
78731 /*
78732  *  Helpers for dealing with the input string
78733  */
78734 
78735 /* Get a (possibly canonicalized) input character from current sp.  The input
78736  * itself is never modified, and captures always record non-canonicalized
78737  * characters even in case-insensitive matching.
78738  */
78739 DUK_LOCAL duk_codepoint_t duk__inp_get_cp(duk_re_matcher_ctx *re_ctx, const duk_uint8_t **sp) {
78740 	duk_codepoint_t res = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(re_ctx->thr, sp, re_ctx->input, re_ctx->input_end);
78741 	if (re_ctx->re_flags & DUK_RE_FLAG_IGNORE_CASE) {
78742 		res = duk_unicode_re_canonicalize_char(re_ctx->thr, res);
78743 	}
78744 	return res;
78745 }
78746 
78747 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) {
78748 	return duk__utf8_backtrack(re_ctx->thr, sp, re_ctx->input, re_ctx->input_end, count);
78749 }
78750 
78751 /* Backtrack utf-8 input and return a (possibly canonicalized) input character. */
78752 DUK_LOCAL duk_codepoint_t duk__inp_get_prev_cp(duk_re_matcher_ctx *re_ctx, const duk_uint8_t *sp) {
78753 	/* note: caller 'sp' is intentionally not updated here */
78754 	(void) duk__inp_backtrack(re_ctx, &sp, (duk_uint_fast32_t) 1);
78755 	return duk__inp_get_cp(re_ctx, &sp);
78756 }
78757 
78758 /*
78759  *  Regexp recursive matching function.
78760  *
78761  *  Returns 'sp' on successful match (points to character after last matched one),
78762  *  NULL otherwise.
78763  *
78764  *  The C recursion depth limit check is only performed in this function, this
78765  *  suffices because the function is present in all true recursion required by
78766  *  regexp execution.
78767  */
78768 
78769 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) {
78770 	if (re_ctx->recursion_depth >= re_ctx->recursion_limit) {
78771 		DUK_ERROR_RANGE(re_ctx->thr, DUK_STR_REGEXP_EXECUTOR_RECURSION_LIMIT);
78772 	}
78773 	re_ctx->recursion_depth++;
78774 
78775 	for (;;) {
78776 		duk_small_int_t op;
78777 
78778 		if (re_ctx->steps_count >= re_ctx->steps_limit) {
78779 			DUK_ERROR_RANGE(re_ctx->thr, DUK_STR_REGEXP_EXECUTOR_STEP_LIMIT);
78780 		}
78781 		re_ctx->steps_count++;
78782 
78783 		op = (duk_small_int_t) duk__bc_get_u32(re_ctx, &pc);
78784 
78785 		DUK_DDD(DUK_DDDPRINT("match: rec=%ld, steps=%ld, pc (after op)=%ld, sp=%ld, op=%ld",
78786 		                     (long) re_ctx->recursion_depth,
78787 		                     (long) re_ctx->steps_count,
78788 		                     (long) (pc - re_ctx->bytecode),
78789 		                     (long) (sp - re_ctx->input),
78790 		                     (long) op));
78791 
78792 		switch (op) {
78793 		case DUK_REOP_MATCH: {
78794 			goto match;
78795 		}
78796 		case DUK_REOP_CHAR: {
78797 			/*
78798 			 *  Byte-based matching would be possible for case-sensitive
78799 			 *  matching but not for case-insensitive matching.  So, we
78800 			 *  match by decoding the input and bytecode character normally.
78801 			 *
78802 			 *  Bytecode characters are assumed to be already canonicalized.
78803 			 *  Input characters are canonicalized automatically by
78804 			 *  duk__inp_get_cp() if necessary.
78805 			 *
78806 			 *  There is no opcode for matching multiple characters.  The
78807 			 *  regexp compiler has trouble joining strings efficiently
78808 			 *  during compilation.  See doc/regexp.rst for more discussion.
78809 			 */
78810 			duk_codepoint_t c1, c2;
78811 
78812 			c1 = (duk_codepoint_t) duk__bc_get_u32(re_ctx, &pc);
78813 			DUK_ASSERT(!(re_ctx->re_flags & DUK_RE_FLAG_IGNORE_CASE) ||
78814 			           c1 == duk_unicode_re_canonicalize_char(re_ctx->thr, c1));  /* canonicalized by compiler */
78815 			if (sp >= re_ctx->input_end) {
78816 				goto fail;
78817 			}
78818 			c2 = duk__inp_get_cp(re_ctx, &sp);
78819 			DUK_DDD(DUK_DDDPRINT("char match, c1=%ld, c2=%ld", (long) c1, (long) c2));
78820 			if (c1 != c2) {
78821 				goto fail;
78822 			}
78823 			break;
78824 		}
78825 		case DUK_REOP_PERIOD: {
78826 			duk_codepoint_t c;
78827 
78828 			if (sp >= re_ctx->input_end) {
78829 				goto fail;
78830 			}
78831 			c = duk__inp_get_cp(re_ctx, &sp);
78832 			if (duk_unicode_is_line_terminator(c)) {
78833 				/* E5 Sections 15.10.2.8, 7.3 */
78834 				goto fail;
78835 			}
78836 			break;
78837 		}
78838 		case DUK_REOP_RANGES:
78839 		case DUK_REOP_INVRANGES: {
78840 			duk_uint32_t n;
78841 			duk_codepoint_t c;
78842 			duk_small_int_t match;
78843 
78844 			n = duk__bc_get_u32(re_ctx, &pc);
78845 			if (sp >= re_ctx->input_end) {
78846 				goto fail;
78847 			}
78848 			c = duk__inp_get_cp(re_ctx, &sp);
78849 
78850 			match = 0;
78851 			while (n) {
78852 				duk_codepoint_t r1, r2;
78853 				r1 = (duk_codepoint_t) duk__bc_get_u32(re_ctx, &pc);
78854 				r2 = (duk_codepoint_t) duk__bc_get_u32(re_ctx, &pc);
78855 				DUK_DDD(DUK_DDDPRINT("matching ranges/invranges, n=%ld, r1=%ld, r2=%ld, c=%ld",
78856 				                     (long) n, (long) r1, (long) r2, (long) c));
78857 				if (c >= r1 && c <= r2) {
78858 					/* Note: don't bail out early, we must read all the ranges from
78859 					 * bytecode.  Another option is to skip them efficiently after
78860 					 * breaking out of here.  Prefer smallest code.
78861 					 */
78862 					match = 1;
78863 				}
78864 				n--;
78865 			}
78866 
78867 			if (op == DUK_REOP_RANGES) {
78868 				if (!match) {
78869 					goto fail;
78870 				}
78871 			} else {
78872 				DUK_ASSERT(op == DUK_REOP_INVRANGES);
78873 				if (match) {
78874 					goto fail;
78875 				}
78876 			}
78877 			break;
78878 		}
78879 		case DUK_REOP_ASSERT_START: {
78880 			duk_codepoint_t c;
78881 
78882 			if (sp <= re_ctx->input) {
78883 				break;
78884 			}
78885 			if (!(re_ctx->re_flags & DUK_RE_FLAG_MULTILINE)) {
78886 				goto fail;
78887 			}
78888 			c = duk__inp_get_prev_cp(re_ctx, sp);
78889 			if (duk_unicode_is_line_terminator(c)) {
78890 				/* E5 Sections 15.10.2.8, 7.3 */
78891 				break;
78892 			}
78893 			goto fail;
78894 		}
78895 		case DUK_REOP_ASSERT_END: {
78896 			duk_codepoint_t c;
78897 			const duk_uint8_t *tmp_sp;
78898 
78899 			if (sp >= re_ctx->input_end) {
78900 				break;
78901 			}
78902 			if (!(re_ctx->re_flags & DUK_RE_FLAG_MULTILINE)) {
78903 				goto fail;
78904 			}
78905 			tmp_sp = sp;
78906 			c = duk__inp_get_cp(re_ctx, &tmp_sp);
78907 			if (duk_unicode_is_line_terminator(c)) {
78908 				/* E5 Sections 15.10.2.8, 7.3 */
78909 				break;
78910 			}
78911 			goto fail;
78912 		}
78913 		case DUK_REOP_ASSERT_WORD_BOUNDARY:
78914 		case DUK_REOP_ASSERT_NOT_WORD_BOUNDARY: {
78915 			/*
78916 			 *  E5 Section 15.10.2.6.  The previous and current character
78917 			 *  should -not- be canonicalized as they are now.  However,
78918 			 *  canonicalization does not affect the result of IsWordChar()
78919 			 *  (which depends on Unicode characters never canonicalizing
78920 			 *  into ASCII characters) so this does not matter.
78921 			 */
78922 			duk_small_int_t w1, w2;
78923 
78924 			if (sp <= re_ctx->input) {
78925 				w1 = 0;  /* not a wordchar */
78926 			} else {
78927 				duk_codepoint_t c;
78928 				c = duk__inp_get_prev_cp(re_ctx, sp);
78929 				w1 = duk_unicode_re_is_wordchar(c);
78930 			}
78931 			if (sp >= re_ctx->input_end) {
78932 				w2 = 0;  /* not a wordchar */
78933 			} else {
78934 				const duk_uint8_t *tmp_sp = sp;  /* dummy so sp won't get updated */
78935 				duk_codepoint_t c;
78936 				c = duk__inp_get_cp(re_ctx, &tmp_sp);
78937 				w2 = duk_unicode_re_is_wordchar(c);
78938 			}
78939 
78940 			if (op == DUK_REOP_ASSERT_WORD_BOUNDARY) {
78941 				if (w1 == w2) {
78942 					goto fail;
78943 				}
78944 			} else {
78945 				DUK_ASSERT(op == DUK_REOP_ASSERT_NOT_WORD_BOUNDARY);
78946 				if (w1 != w2) {
78947 					goto fail;
78948 				}
78949 			}
78950 			break;
78951 		}
78952 		case DUK_REOP_JUMP: {
78953 			duk_int32_t skip;
78954 
78955 			skip = duk__bc_get_i32(re_ctx, &pc);
78956 			pc += skip;
78957 			break;
78958 		}
78959 		case DUK_REOP_SPLIT1: {
78960 			/* split1: prefer direct execution (no jump) */
78961 			const duk_uint8_t *sub_sp;
78962 			duk_int32_t skip;
78963 
78964 			skip = duk__bc_get_i32(re_ctx, &pc);
78965 			sub_sp = duk__match_regexp(re_ctx, pc, sp);
78966 			if (sub_sp) {
78967 				sp = sub_sp;
78968 				goto match;
78969 			}
78970 			pc += skip;
78971 			break;
78972 		}
78973 		case DUK_REOP_SPLIT2: {
78974 			/* split2: prefer jump execution (not direct) */
78975 			const duk_uint8_t *sub_sp;
78976 			duk_int32_t skip;
78977 
78978 			skip = duk__bc_get_i32(re_ctx, &pc);
78979 			sub_sp = duk__match_regexp(re_ctx, pc + skip, sp);
78980 			if (sub_sp) {
78981 				sp = sub_sp;
78982 				goto match;
78983 			}
78984 			break;
78985 		}
78986 		case DUK_REOP_SQMINIMAL: {
78987 			duk_uint32_t q, qmin, qmax;
78988 			duk_int32_t skip;
78989 			const duk_uint8_t *sub_sp;
78990 
78991 			qmin = duk__bc_get_u32(re_ctx, &pc);
78992 			qmax = duk__bc_get_u32(re_ctx, &pc);
78993 			skip = duk__bc_get_i32(re_ctx, &pc);
78994 			DUK_DDD(DUK_DDDPRINT("minimal quantifier, qmin=%lu, qmax=%lu, skip=%ld",
78995 			                     (unsigned long) qmin, (unsigned long) qmax, (long) skip));
78996 
78997 			q = 0;
78998 			while (q <= qmax) {
78999 				if (q >= qmin) {
79000 					sub_sp = duk__match_regexp(re_ctx, pc + skip, sp);
79001 					if (sub_sp) {
79002 						sp = sub_sp;
79003 						goto match;
79004 					}
79005 				}
79006 				sub_sp = duk__match_regexp(re_ctx, pc, sp);
79007 				if (!sub_sp) {
79008 					break;
79009 				}
79010 				sp = sub_sp;
79011 				q++;
79012 			}
79013 			goto fail;
79014 		}
79015 		case DUK_REOP_SQGREEDY: {
79016 			duk_uint32_t q, qmin, qmax, atomlen;
79017 			duk_int32_t skip;
79018 			const duk_uint8_t *sub_sp;
79019 
79020 			qmin = duk__bc_get_u32(re_ctx, &pc);
79021 			qmax = duk__bc_get_u32(re_ctx, &pc);
79022 			atomlen = duk__bc_get_u32(re_ctx, &pc);
79023 			skip = duk__bc_get_i32(re_ctx, &pc);
79024 			DUK_DDD(DUK_DDDPRINT("greedy quantifier, qmin=%lu, qmax=%lu, atomlen=%lu, skip=%ld",
79025 			                     (unsigned long) qmin, (unsigned long) qmax, (unsigned long) atomlen, (long) skip));
79026 
79027 			q = 0;
79028 			while (q < qmax) {
79029 				sub_sp = duk__match_regexp(re_ctx, pc, sp);
79030 				if (!sub_sp) {
79031 					break;
79032 				}
79033 				sp = sub_sp;
79034 				q++;
79035 			}
79036 			while (q >= qmin) {
79037 				sub_sp = duk__match_regexp(re_ctx, pc + skip, sp);
79038 				if (sub_sp) {
79039 					sp = sub_sp;
79040 					goto match;
79041 				}
79042 				if (q == qmin) {
79043 					break;
79044 				}
79045 
79046 				/* Note: if atom were to contain e.g. captures, we would need to
79047 				 * re-match the atom to get correct captures.  Simply quantifiers
79048 				 * do not allow captures in their atom now, so this is not an issue.
79049 				 */
79050 
79051 				DUK_DDD(DUK_DDDPRINT("greedy quantifier, backtrack %ld characters (atomlen)",
79052 				                     (long) atomlen));
79053 				sp = duk__inp_backtrack(re_ctx, &sp, (duk_uint_fast32_t) atomlen);
79054 				q--;
79055 			}
79056 			goto fail;
79057 		}
79058 		case DUK_REOP_SAVE: {
79059 			duk_uint32_t idx;
79060 			const duk_uint8_t *old;
79061 			const duk_uint8_t *sub_sp;
79062 
79063 			idx = duk__bc_get_u32(re_ctx, &pc);
79064 			if (idx >= re_ctx->nsaved) {
79065 				/* idx is unsigned, < 0 check is not necessary */
79066 				DUK_D(DUK_DPRINT("internal error, regexp save index insane: idx=%ld", (long) idx));
79067 				goto internal_error;
79068 			}
79069 			old = re_ctx->saved[idx];
79070 			re_ctx->saved[idx] = sp;
79071 			sub_sp = duk__match_regexp(re_ctx, pc, sp);
79072 			if (sub_sp) {
79073 				sp = sub_sp;
79074 				goto match;
79075 			}
79076 			re_ctx->saved[idx] = old;
79077 			goto fail;
79078 		}
79079 		case DUK_REOP_WIPERANGE: {
79080 			/* Wipe capture range and save old values for backtracking.
79081 			 *
79082 			 * XXX: this typically happens with a relatively small idx_count.
79083 			 * It might be useful to handle cases where the count is small
79084 			 * (say <= 8) by saving the values in stack instead.  This would
79085 			 * reduce memory churn and improve performance, at the cost of a
79086 			 * slightly higher code footprint.
79087 			 */
79088 			duk_uint32_t idx_start, idx_count;
79089 #ifdef DUK_USE_EXPLICIT_NULL_INIT
79090 			duk_uint32_t idx_end, idx;
79091 #endif
79092 			duk_uint8_t **range_save;
79093 			const duk_uint8_t *sub_sp;
79094 
79095 			idx_start = duk__bc_get_u32(re_ctx, &pc);
79096 			idx_count = duk__bc_get_u32(re_ctx, &pc);
79097 			DUK_DDD(DUK_DDDPRINT("wipe saved range: start=%ld, count=%ld -> [%ld,%ld] (captures [%ld,%ld])",
79098 			                     (long) idx_start, (long) idx_count,
79099 			                     (long) idx_start, (long) (idx_start + idx_count - 1),
79100 			                     (long) (idx_start / 2), (long) ((idx_start + idx_count - 1) / 2)));
79101 			if (idx_start + idx_count > re_ctx->nsaved || idx_count == 0) {
79102 				/* idx is unsigned, < 0 check is not necessary */
79103 				DUK_D(DUK_DPRINT("internal error, regexp wipe indices insane: idx_start=%ld, idx_count=%ld",
79104 				                 (long) idx_start, (long) idx_count));
79105 				goto internal_error;
79106 			}
79107 			DUK_ASSERT(idx_count > 0);
79108 
79109 			duk_require_stack((duk_context *) re_ctx->thr, 1);
79110 			range_save = (duk_uint8_t **) duk_push_fixed_buffer((duk_context *) re_ctx->thr,
79111 			                                                    sizeof(duk_uint8_t *) * idx_count);
79112 			DUK_ASSERT(range_save != NULL);
79113 			DUK_MEMCPY(range_save, re_ctx->saved + idx_start, sizeof(duk_uint8_t *) * idx_count);
79114 #ifdef DUK_USE_EXPLICIT_NULL_INIT
79115 			idx_end = idx_start + idx_count;
79116 			for (idx = idx_start; idx < idx_end; idx++) {
79117 				re_ctx->saved[idx] = NULL;
79118 			}
79119 #else
79120 			DUK_MEMZERO((void *) (re_ctx->saved + idx_start), sizeof(duk_uint8_t *) * idx_count);
79121 #endif
79122 
79123 			sub_sp = duk__match_regexp(re_ctx, pc, sp);
79124 			if (sub_sp) {
79125 				/* match: keep wiped/resaved values */
79126 				DUK_DDD(DUK_DDDPRINT("match: keep wiped/resaved values [%ld,%ld] (captures [%ld,%ld])",
79127 				                     (long) idx_start, (long) (idx_start + idx_count - 1),
79128 			                             (long) (idx_start / 2), (long) ((idx_start + idx_count - 1) / 2)));
79129 				duk_pop((duk_context *) re_ctx->thr);
79130 				sp = sub_sp;
79131 				goto match;
79132 			}
79133 
79134 			/* fail: restore saves */
79135 			DUK_DDD(DUK_DDDPRINT("fail: restore wiped/resaved values [%ld,%ld] (captures [%ld,%ld])",
79136 			                     (long) idx_start, (long) (idx_start + idx_count - 1),
79137 			                     (long) (idx_start / 2), (long) ((idx_start + idx_count - 1) / 2)));
79138 			DUK_MEMCPY((void *) (re_ctx->saved + idx_start),
79139 			           (const void *) range_save,
79140 			           sizeof(duk_uint8_t *) * idx_count);
79141 			duk_pop((duk_context *) re_ctx->thr);
79142 			goto fail;
79143 		}
79144 		case DUK_REOP_LOOKPOS:
79145 		case DUK_REOP_LOOKNEG: {
79146 			/*
79147 			 *  Needs a save of multiple saved[] entries depending on what range
79148 			 *  may be overwritten.  Because the regexp parser does no such analysis,
79149 			 *  we currently save the entire saved array here.  Lookaheads are thus
79150 			 *  a bit expensive.  Note that the saved array is not needed for just
79151 			 *  the lookahead sub-match, but for the matching of the entire sequel.
79152 			 *
79153 			 *  The temporary save buffer is pushed on to the valstack to handle
79154 			 *  errors correctly.  Each lookahead causes a C recursion and pushes
79155 			 *  more stuff on the value stack.  If the C recursion limit is less
79156 			 *  than the value stack spare, there is no need to check the stack.
79157 			 *  We do so regardless, just in case.
79158 			 */
79159 
79160 			duk_int32_t skip;
79161 			duk_uint8_t **full_save;
79162 			const duk_uint8_t *sub_sp;
79163 
79164 			DUK_ASSERT(re_ctx->nsaved > 0);
79165 
79166 			duk_require_stack((duk_context *) re_ctx->thr, 1);
79167 			full_save = (duk_uint8_t **) duk_push_fixed_buffer((duk_context *) re_ctx->thr,
79168 			                                                   sizeof(duk_uint8_t *) * re_ctx->nsaved);
79169 			DUK_ASSERT(full_save != NULL);
79170 			DUK_MEMCPY(full_save, re_ctx->saved, sizeof(duk_uint8_t *) * re_ctx->nsaved);
79171 
79172 			skip = duk__bc_get_i32(re_ctx, &pc);
79173 			sub_sp = duk__match_regexp(re_ctx, pc, sp);
79174 			if (op == DUK_REOP_LOOKPOS) {
79175 				if (!sub_sp) {
79176 					goto lookahead_fail;
79177 				}
79178 			} else {
79179 				if (sub_sp) {
79180 					goto lookahead_fail;
79181 				}
79182 			}
79183 			sub_sp = duk__match_regexp(re_ctx, pc + skip, sp);
79184 			if (sub_sp) {
79185 				/* match: keep saves */
79186 				duk_pop((duk_context *) re_ctx->thr);
79187 				sp = sub_sp;
79188 				goto match;
79189 			}
79190 
79191 			/* fall through */
79192 
79193 		 lookahead_fail:
79194 			/* fail: restore saves */
79195 			DUK_MEMCPY((void *) re_ctx->saved,
79196 			           (const void *) full_save,
79197 			           sizeof(duk_uint8_t *) * re_ctx->nsaved);
79198 			duk_pop((duk_context *) re_ctx->thr);
79199 			goto fail;
79200 		}
79201 		case DUK_REOP_BACKREFERENCE: {
79202 			/*
79203 			 *  Byte matching for back-references would be OK in case-
79204 			 *  sensitive matching.  In case-insensitive matching we need
79205 			 *  to canonicalize characters, so back-reference matching needs
79206 			 *  to be done with codepoints instead.  So, we just decode
79207 			 *  everything normally here, too.
79208 			 *
79209 			 *  Note: back-reference index which is 0 or higher than
79210 			 *  NCapturingParens (= number of capturing parens in the
79211 			 *  -entire- regexp) is a compile time error.  However, a
79212 			 *  backreference referring to a valid capture which has
79213 			 *  not matched anything always succeeds!  See E5 Section
79214 			 *  15.10.2.9, step 5, sub-step 3.
79215 			 */
79216 			duk_uint32_t idx;
79217 			const duk_uint8_t *p;
79218 
79219 			idx = duk__bc_get_u32(re_ctx, &pc);
79220 			idx = idx << 1;  /* backref n -> saved indices [n*2, n*2+1] */
79221 			if (idx < 2 || idx + 1 >= re_ctx->nsaved) {
79222 				/* regexp compiler should catch these */
79223 				DUK_D(DUK_DPRINT("internal error, backreference index insane"));
79224 				goto internal_error;
79225 			}
79226 			if (!re_ctx->saved[idx] || !re_ctx->saved[idx+1]) {
79227 				/* capture is 'undefined', always matches! */
79228 				DUK_DDD(DUK_DDDPRINT("backreference: saved[%ld,%ld] not complete, always match",
79229 				                     (long) idx, (long) (idx + 1)));
79230 				break;
79231 			}
79232 			DUK_DDD(DUK_DDDPRINT("backreference: match saved[%ld,%ld]", (long) idx, (long) (idx + 1)));
79233 
79234 			p = re_ctx->saved[idx];
79235 			while (p < re_ctx->saved[idx+1]) {
79236 				duk_codepoint_t c1, c2;
79237 
79238 				/* Note: not necessary to check p against re_ctx->input_end:
79239 				 * the memory access is checked by duk__inp_get_cp(), while
79240 				 * valid compiled regexps cannot write a saved[] entry
79241 				 * which points to outside the string.
79242 				 */
79243 				if (sp >= re_ctx->input_end) {
79244 					goto fail;
79245 				}
79246 				c1 = duk__inp_get_cp(re_ctx, &p);
79247 				c2 = duk__inp_get_cp(re_ctx, &sp);
79248 				if (c1 != c2) {
79249 					goto fail;
79250 				}
79251 			}
79252 			break;
79253 		}
79254 		default: {
79255 			DUK_D(DUK_DPRINT("internal error, regexp opcode error: %ld", (long) op));
79256 			goto internal_error;
79257 		}
79258 		}
79259 	}
79260 
79261  match:
79262 	re_ctx->recursion_depth--;
79263 	return sp;
79264 
79265  fail:
79266 	re_ctx->recursion_depth--;
79267 	return NULL;
79268 
79269  internal_error:
79270 	DUK_ERROR_INTERNAL_DEFMSG(re_ctx->thr);
79271 	return NULL;  /* never here */
79272 }
79273 
79274 /*
79275  *  Exposed matcher function which provides the semantics of RegExp.prototype.exec().
79276  *
79277  *  RegExp.prototype.test() has the same semantics as exec() but does not return the
79278  *  result object (which contains the matching string and capture groups).  Currently
79279  *  there is no separate test() helper, so a temporary result object is created and
79280  *  discarded if test() is needed.  This is intentional, to save code space.
79281  *
79282  *  Input stack:  [ ... re_obj input ]
79283  *  Output stack: [ ... result ]
79284  */
79285 
79286 DUK_LOCAL void duk__regexp_match_helper(duk_hthread *thr, duk_small_int_t force_global) {
79287 	duk_context *ctx = (duk_context *) thr;
79288 	duk_re_matcher_ctx re_ctx;
79289 	duk_hobject *h_regexp;
79290 	duk_hstring *h_bytecode;
79291 	duk_hstring *h_input;
79292 	duk_uint8_t *p_buf;
79293 	const duk_uint8_t *pc;
79294 	const duk_uint8_t *sp;
79295 	duk_small_int_t match = 0;
79296 	duk_small_int_t global;
79297 	duk_uint_fast32_t i;
79298 	double d;
79299 	duk_uint32_t char_offset;
79300 
79301 	DUK_ASSERT(thr != NULL);
79302 	DUK_ASSERT(ctx != NULL);
79303 
79304 	DUK_DD(DUK_DDPRINT("regexp match: regexp=%!T, input=%!T",
79305 	                   (duk_tval *) duk_get_tval(ctx, -2),
79306 	                   (duk_tval *) duk_get_tval(ctx, -1)));
79307 
79308 	/*
79309 	 *  Regexp instance check, bytecode check, input coercion.
79310 	 *
79311 	 *  See E5 Section 15.10.6.
79312 	 */
79313 
79314 	/* TypeError if wrong; class check, see E5 Section 15.10.6 */
79315 	h_regexp = duk_require_hobject_with_class(ctx, -2, DUK_HOBJECT_CLASS_REGEXP);
79316 	DUK_ASSERT(h_regexp != NULL);
79317 	DUK_ASSERT(DUK_HOBJECT_GET_CLASS_NUMBER(h_regexp) == DUK_HOBJECT_CLASS_REGEXP);
79318 	DUK_UNREF(h_regexp);
79319 
79320 	duk_to_string(ctx, -1);
79321 	h_input = duk_get_hstring(ctx, -1);
79322 	DUK_ASSERT(h_input != NULL);
79323 
79324 	duk_get_prop_stridx(ctx, -2, DUK_STRIDX_INT_BYTECODE);  /* [ ... re_obj input ] -> [ ... re_obj input bc ] */
79325 	h_bytecode = duk_require_hstring(ctx, -1);  /* no regexp instance should exist without a non-configurable bytecode property */
79326 	DUK_ASSERT(h_bytecode != NULL);
79327 
79328 	/*
79329 	 *  Basic context initialization.
79330 	 *
79331 	 *  Some init values are read from the bytecode header
79332 	 *  whose format is (UTF-8 codepoints):
79333 	 *
79334 	 *    uint   flags
79335 	 *    uint   nsaved (even, 2n+2 where n = num captures)
79336 	 */
79337 
79338 	/* [ ... re_obj input bc ] */
79339 
79340 	DUK_MEMZERO(&re_ctx, sizeof(re_ctx));
79341 
79342 	re_ctx.thr = thr;
79343 	re_ctx.input = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
79344 	re_ctx.input_end = re_ctx.input + DUK_HSTRING_GET_BYTELEN(h_input);
79345 	re_ctx.bytecode = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_bytecode);
79346 	re_ctx.bytecode_end = re_ctx.bytecode + DUK_HSTRING_GET_BYTELEN(h_bytecode);
79347 	re_ctx.saved = NULL;
79348 	re_ctx.recursion_limit = DUK_USE_REGEXP_EXECUTOR_RECLIMIT;
79349 	re_ctx.steps_limit = DUK_RE_EXECUTE_STEPS_LIMIT;
79350 
79351 	/* read header */
79352 	pc = re_ctx.bytecode;
79353 	re_ctx.re_flags = duk__bc_get_u32(&re_ctx, &pc);
79354 	re_ctx.nsaved = duk__bc_get_u32(&re_ctx, &pc);
79355 	re_ctx.bytecode = pc;
79356 
79357 	DUK_ASSERT(DUK_RE_FLAG_GLOBAL < 0x10000UL);  /* must fit into duk_small_int_t */
79358 	global = (duk_small_int_t) (force_global | (re_ctx.re_flags & DUK_RE_FLAG_GLOBAL));
79359 
79360 	DUK_ASSERT(re_ctx.nsaved >= 2);
79361 	DUK_ASSERT((re_ctx.nsaved % 2) == 0);
79362 
79363 	p_buf = (duk_uint8_t *) duk_push_fixed_buffer(ctx, sizeof(duk_uint8_t *) * re_ctx.nsaved);
79364 	DUK_UNREF(p_buf);
79365 	re_ctx.saved = (const duk_uint8_t **) duk_get_buffer(ctx, -1, NULL);
79366 	DUK_ASSERT(re_ctx.saved != NULL);
79367 
79368 	/* [ ... re_obj input bc saved_buf ] */
79369 
79370 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
79371 	for (i = 0; i < re_ctx.nsaved; i++) {
79372 		re_ctx.saved[i] = (duk_uint8_t *) NULL;
79373 	}
79374 #elif defined(DUK_USE_ZERO_BUFFER_DATA)
79375 	/* buffer is automatically zeroed */
79376 #else
79377 	DUK_MEMZERO((void *) p_buf, sizeof(duk_uint8_t *) * re_ctx.nsaved);
79378 #endif
79379 
79380 	DUK_DDD(DUK_DDDPRINT("regexp ctx initialized, flags=0x%08lx, nsaved=%ld, recursion_limit=%ld, steps_limit=%ld",
79381 	                     (unsigned long) re_ctx.re_flags, (long) re_ctx.nsaved, (long) re_ctx.recursion_limit,
79382 	                     (long) re_ctx.steps_limit));
79383 
79384 	/*
79385 	 *  Get starting character offset for match, and initialize 'sp' based on it.
79386 	 *
79387 	 *  Note: lastIndex is non-configurable so it must be present (we check the
79388 	 *  internal class of the object above, so we know it is).  User code can set
79389 	 *  its value to an arbitrary (garbage) value though; E5 requires that lastIndex
79390 	 *  be coerced to a number before using.  The code below works even if the
79391 	 *  property is missing: the value will then be coerced to zero.
79392 	 *
79393 	 *  Note: lastIndex may be outside Uint32 range even after ToInteger() coercion.
79394 	 *  For instance, ToInteger(+Infinity) = +Infinity.  We track the match offset
79395 	 *  as an integer, but pre-check it to be inside the 32-bit range before the loop.
79396 	 *  If not, the check in E5 Section 15.10.6.2, step 9.a applies.
79397 	 */
79398 
79399 	/* XXX: lastIndex handling produces a lot of asm */
79400 
79401 	/* [ ... re_obj input bc saved_buf ] */
79402 
79403 	duk_get_prop_stridx(ctx, -4, DUK_STRIDX_LAST_INDEX);  /* -> [ ... re_obj input bc saved_buf lastIndex ] */
79404 	(void) duk_to_int(ctx, -1);  /* ToInteger(lastIndex) */
79405 	d = duk_get_number(ctx, -1);  /* integer, but may be +/- Infinite, +/- zero (not NaN, though) */
79406 	duk_pop(ctx);
79407 
79408 	if (global) {
79409 		if (d < 0.0 || d > (double) DUK_HSTRING_GET_CHARLEN(h_input)) {
79410 			/* match fail */
79411 			char_offset = 0;   /* not really necessary */
79412 			DUK_ASSERT(match == 0);
79413 			goto match_over;
79414 		}
79415 		char_offset = (duk_uint32_t) d;
79416 	} else {
79417 		/* lastIndex must be ignored for non-global regexps, but get the
79418 		 * value for (theoretical) side effects.  No side effects can
79419 		 * really occur, because lastIndex is a normal property and is
79420 		 * always non-configurable for RegExp instances.
79421 		 */
79422 		char_offset = (duk_uint32_t) 0;
79423 	}
79424 
79425 	sp = re_ctx.input + duk_heap_strcache_offset_char2byte(thr, h_input, char_offset);
79426 
79427 	/*
79428 	 *  Match loop.
79429 	 *
79430 	 *  Try matching at different offsets until match found or input exhausted.
79431 	 */
79432 
79433 	/* [ ... re_obj input bc saved_buf ] */
79434 
79435 	DUK_ASSERT(match == 0);
79436 
79437 	for (;;) {
79438 		/* char offset in [0, h_input->clen] (both ends inclusive), checked before entry */
79439 		DUK_ASSERT_DISABLE(char_offset >= 0);
79440 		DUK_ASSERT(char_offset <= DUK_HSTRING_GET_CHARLEN(h_input));
79441 
79442 		/* Note: ctx.steps is intentionally not reset, it applies to the entire unanchored match */
79443 		DUK_ASSERT(re_ctx.recursion_depth == 0);
79444 
79445 		DUK_DDD(DUK_DDDPRINT("attempt match at char offset %ld; %p [%p,%p]",
79446 		                     (long) char_offset, (const void *) sp,
79447 		                     (const void *) re_ctx.input, (const void *) re_ctx.input_end));
79448 
79449 		/*
79450 		 *  Note:
79451 		 *
79452 		 *    - duk__match_regexp() is required not to longjmp() in ordinary "non-match"
79453 		 *      conditions; a longjmp() will terminate the entire matching process.
79454 		 *
79455 		 *    - Clearing saved[] is not necessary because backtracking does it
79456 		 *
79457 		 *    - Backtracking also rewinds ctx.recursion back to zero, unless an
79458 		 *      internal/limit error occurs (which causes a longjmp())
79459 		 *
79460 		 *    - If we supported anchored matches, we would break out here
79461 		 *      unconditionally; however, Ecmascript regexps don't have anchored
79462 		 *      matches.  It might make sense to implement a fast bail-out if
79463 		 *      the regexp begins with '^' and sp is not 0: currently we'll just
79464 		 *      run through the entire input string, trivially failing the match
79465 		 *      at every non-zero offset.
79466 		 */
79467 
79468 		if (duk__match_regexp(&re_ctx, re_ctx.bytecode, sp) != NULL) {
79469 			DUK_DDD(DUK_DDDPRINT("match at offset %ld", (long) char_offset));
79470 			match = 1;
79471 			break;
79472 		}
79473 
79474 		/* advance by one character (code point) and one char_offset */
79475 		char_offset++;
79476 		if (char_offset > DUK_HSTRING_GET_CHARLEN(h_input)) {
79477 			/*
79478 			 *  Note:
79479 			 *
79480 			 *    - Intentionally attempt (empty) match at char_offset == k_input->clen
79481 			 *
79482 			 *    - Negative char_offsets have been eliminated and char_offset is duk_uint32_t
79483 			 *      -> no need or use for a negative check
79484 			 */
79485 
79486 			DUK_DDD(DUK_DDDPRINT("no match after trying all sp offsets"));
79487 			break;
79488 		}
79489 
79490 		/* avoid calling at end of input, will DUK_ERROR (above check suffices to avoid this) */
79491 		(void) duk__utf8_advance(thr, &sp, re_ctx.input, re_ctx.input_end, (duk_uint_fast32_t) 1);
79492 	}
79493 
79494  match_over:
79495 
79496 	/*
79497 	 *  Matching complete, create result array or return a 'null'.  Update lastIndex
79498 	 *  if necessary.  See E5 Section 15.10.6.2.
79499 	 *
79500 	 *  Because lastIndex is a character (not byte) offset, we need the character
79501 	 *  length of the match which we conveniently get as a side effect of interning
79502 	 *  the matching substring (0th index of result array).
79503 	 *
79504 	 *  saved[0]         start pointer (~ byte offset) of current match
79505 	 *  saved[1]         end pointer (~ byte offset) of current match (exclusive)
79506 	 *  char_offset      start character offset of current match (-> .index of result)
79507 	 *  char_end_offset  end character offset (computed below)
79508 	 */
79509 
79510 	/* [ ... re_obj input bc saved_buf ] */
79511 
79512 	if (match) {
79513 #ifdef DUK_USE_ASSERTIONS
79514 		duk_hobject *h_res;
79515 #endif
79516 		duk_uint32_t char_end_offset = 0;
79517 
79518 		DUK_DDD(DUK_DDDPRINT("regexp matches at char_offset %ld", (long) char_offset));
79519 
79520 		DUK_ASSERT(re_ctx.nsaved >= 2);        /* must have start and end */
79521 		DUK_ASSERT((re_ctx.nsaved % 2) == 0);  /* and even number */
79522 
79523 		/* XXX: Array size is known before and (2 * re_ctx.nsaved) but not taken
79524 		 * advantage of now.  The array is not compacted either, as regexp match
79525 		 * objects are usually short lived.
79526 		 */
79527 
79528 		duk_push_array(ctx);
79529 
79530 #ifdef DUK_USE_ASSERTIONS
79531 		h_res = duk_require_hobject(ctx, -1);
79532 		DUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE(h_res));
79533 		DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY(h_res));
79534 		DUK_ASSERT(DUK_HOBJECT_GET_CLASS_NUMBER(h_res) == DUK_HOBJECT_CLASS_ARRAY);
79535 #endif
79536 
79537 		/* [ ... re_obj input bc saved_buf res_obj ] */
79538 
79539 		duk_push_u32(ctx, char_offset);
79540 		duk_xdef_prop_stridx_wec(ctx, -2, DUK_STRIDX_INDEX);
79541 
79542 		duk_dup(ctx, -4);
79543 		duk_xdef_prop_stridx_wec(ctx, -2, DUK_STRIDX_INPUT);
79544 
79545 		for (i = 0; i < re_ctx.nsaved; i += 2) {
79546 			/* Captures which are undefined have NULL pointers and are returned
79547 			 * as 'undefined'.  The same is done when saved[] pointers are insane
79548 			 * (this should, of course, never happen in practice).
79549 			 */
79550 			if (re_ctx.saved[i] && re_ctx.saved[i+1] && re_ctx.saved[i+1] >= re_ctx.saved[i]) {
79551 				duk_hstring *h_saved;
79552 
79553 				duk_push_lstring(ctx,
79554 				                 (const char *) re_ctx.saved[i],
79555 				                 (duk_size_t) (re_ctx.saved[i+1] - re_ctx.saved[i]));
79556 				h_saved = duk_get_hstring(ctx, -1);
79557 				DUK_ASSERT(h_saved != NULL);
79558 
79559 				if (i == 0) {
79560 					/* Assumes that saved[0] and saved[1] are always
79561 					 * set by regexp bytecode (if not, char_end_offset
79562 					 * will be zero).  Also assumes clen reflects the
79563 					 * correct char length.
79564 					 */
79565 					char_end_offset = char_offset + DUK_HSTRING_GET_CHARLEN(h_saved);
79566 				}
79567 			} else {
79568 				duk_push_undefined(ctx);
79569 			}
79570 
79571 			/* [ ... re_obj input bc saved_buf res_obj val ] */
79572 			duk_put_prop_index(ctx, -2, i / 2);
79573 		}
79574 
79575 		/* [ ... re_obj input bc saved_buf res_obj ] */
79576 
79577 		/* NB: 'length' property is automatically updated by the array setup loop */
79578 
79579 		if (global) {
79580 			/* global regexp: lastIndex updated on match */
79581 			duk_push_u32(ctx, char_end_offset);
79582 			duk_put_prop_stridx(ctx, -6, DUK_STRIDX_LAST_INDEX);
79583 		} else {
79584 			/* non-global regexp: lastIndex never updated on match */
79585 			;
79586 		}
79587 	} else {
79588 		/*
79589 		 *  No match, E5 Section 15.10.6.2, step 9.a.i - 9.a.ii apply, regardless
79590 		 *  of 'global' flag of the RegExp.  In particular, if lastIndex is invalid
79591 		 *  initially, it is reset to zero.
79592 		 */
79593 
79594 		DUK_DDD(DUK_DDDPRINT("regexp does not match"));
79595 
79596 		duk_push_null(ctx);
79597 
79598 		/* [ ... re_obj input bc saved_buf res_obj ] */
79599 
79600 		duk_push_int(ctx, 0);
79601 		duk_put_prop_stridx(ctx, -6, DUK_STRIDX_LAST_INDEX);
79602 	}
79603 
79604 	/* [ ... re_obj input bc saved_buf res_obj ] */
79605 
79606 	duk_insert(ctx, -5);
79607 
79608 	/* [ ... res_obj re_obj input bc saved_buf ] */
79609 
79610 	duk_pop_n(ctx, 4);
79611 
79612 	/* [ ... res_obj ] */
79613 
79614 	/* XXX: these last tricks are unnecessary if the function is made
79615 	 * a genuine native function.
79616 	 */
79617 }
79618 
79619 DUK_INTERNAL void duk_regexp_match(duk_hthread *thr) {
79620 	duk__regexp_match_helper(thr, 0 /*force_global*/);
79621 }
79622 
79623 /* This variant is needed by String.prototype.split(); it needs to perform
79624  * global-style matching on a cloned RegExp which is potentially non-global.
79625  */
79626 DUK_INTERNAL void duk_regexp_match_force_global(duk_hthread *thr) {
79627 	duk__regexp_match_helper(thr, 1 /*force_global*/);
79628 }
79629 
79630 #else  /* DUK_USE_REGEXP_SUPPORT */
79631 
79632 /* regexp support disabled */
79633 
79634 #endif  /* DUK_USE_REGEXP_SUPPORT */
79635 /*
79636  *  Self tests to ensure execution environment is sane.  Intended to catch
79637  *  compiler/platform problems which cannot be detected at compile time.
79638  */
79639 
79640 /* include removed: duk_internal.h */
79641 
79642 #if defined(DUK_USE_SELF_TESTS)
79643 
79644 /*
79645  *  Unions and structs for self tests
79646  */
79647 
79648 typedef union {
79649 	double d;
79650 	duk_uint8_t c[8];
79651 } duk__test_double_union;
79652 
79653 #define DUK__DBLUNION_CMP_TRUE(a,b)  do { \
79654 		if (DUK_MEMCMP((const void *) (a), (const void *) (b), sizeof(duk__test_double_union)) != 0) { \
79655 			DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: double union compares false (expected true)"); \
79656 		} \
79657 	} while (0)
79658 
79659 #define DUK__DBLUNION_CMP_FALSE(a,b)  do { \
79660 		if (DUK_MEMCMP((const void *) (a), (const void *) (b), sizeof(duk__test_double_union)) == 0) { \
79661 			DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: double union compares true (expected false)"); \
79662 		} \
79663 	} while (0)
79664 
79665 typedef union {
79666 	duk_uint32_t i;
79667 	duk_uint8_t c[8];
79668 } duk__test_u32_union;
79669 
79670 /*
79671  *  Various sanity checks for typing
79672  */
79673 
79674 DUK_LOCAL void duk__selftest_types(void) {
79675 	if (!(sizeof(duk_int8_t) == 1 &&
79676 	      sizeof(duk_uint8_t) == 1 &&
79677 	      sizeof(duk_int16_t) == 2 &&
79678 	      sizeof(duk_uint16_t) == 2 &&
79679 	      sizeof(duk_int32_t) == 4 &&
79680 	      sizeof(duk_uint32_t) == 4)) {
79681 		DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: duk_(u)int{8,16,32}_t size");
79682 	}
79683 #if defined(DUK_USE_64BIT_OPS)
79684 	if (!(sizeof(duk_int64_t) == 8 &&
79685 	      sizeof(duk_uint64_t) == 8)) {
79686 		DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: duk_(u)int64_t size");
79687 	}
79688 #endif
79689 
79690 	if (!(sizeof(duk_size_t) >= sizeof(duk_uint_t))) {
79691 		/* Some internal code now assumes that all duk_uint_t values
79692 		 * can be expressed with a duk_size_t.
79693 		 */
79694 		DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: duk_size_t is smaller than duk_uint_t");
79695 	}
79696 	if (!(sizeof(duk_int_t) >= 4)) {
79697 		DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: duk_int_t is not 32 bits");
79698 	}
79699 }
79700 
79701 /*
79702  *  Packed tval sanity
79703  */
79704 
79705 DUK_LOCAL void duk__selftest_packed_tval(void) {
79706 #if defined(DUK_USE_PACKED_TVAL)
79707 	if (sizeof(void *) > 4) {
79708 		DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: packed duk_tval in use but sizeof(void *) > 4");
79709 	}
79710 #endif
79711 }
79712 
79713 /*
79714  *  Two's complement arithmetic.
79715  */
79716 
79717 DUK_LOCAL void duk__selftest_twos_complement(void) {
79718 	volatile int test;
79719 	test = -1;
79720 
79721 	/* Note that byte order doesn't affect this test: all bytes in
79722 	 * 'test' will be 0xFF for two's complement.
79723 	 */
79724 	if (((volatile duk_uint8_t *) &test)[0] != (duk_uint8_t) 0xff) {
79725 		DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: two's complement arithmetic");
79726 	}
79727 }
79728 
79729 /*
79730  *  Byte order.  Important to self check, because on some exotic platforms
79731  *  there is no actual detection but rather assumption based on platform
79732  *  defines.
79733  */
79734 
79735 DUK_LOCAL void duk__selftest_byte_order(void) {
79736 	duk__test_u32_union u1;
79737 	duk__test_double_union u2;
79738 
79739 	/*
79740 	 *  >>> struct.pack('>d', 102030405060).encode('hex')
79741 	 *  '4237c17c6dc40000'
79742 	 */
79743 #if defined(DUK_USE_INTEGER_LE)
79744 	u1.c[0] = 0xef; u1.c[1] = 0xbe; u1.c[2] = 0xad; u1.c[3] = 0xde;
79745 #elif defined(DUK_USE_INTEGER_ME)
79746 #error integer mixed endian not supported now
79747 #elif defined(DUK_USE_INTEGER_BE)
79748 	u1.c[0] = 0xde; u1.c[1] = 0xad; u1.c[2] = 0xbe; u1.c[3] = 0xef;
79749 #else
79750 #error unknown integer endianness
79751 #endif
79752 
79753 #if defined(DUK_USE_DOUBLE_LE)
79754 	u2.c[0] = 0x00; u2.c[1] = 0x00; u2.c[2] = 0xc4; u2.c[3] = 0x6d;
79755 	u2.c[4] = 0x7c; u2.c[5] = 0xc1; u2.c[6] = 0x37; u2.c[7] = 0x42;
79756 #elif defined(DUK_USE_DOUBLE_ME)
79757 	u2.c[0] = 0x7c; u2.c[1] = 0xc1; u2.c[2] = 0x37; u2.c[3] = 0x42;
79758 	u2.c[4] = 0x00; u2.c[5] = 0x00; u2.c[6] = 0xc4; u2.c[7] = 0x6d;
79759 #elif defined(DUK_USE_DOUBLE_BE)
79760 	u2.c[0] = 0x42; u2.c[1] = 0x37; u2.c[2] = 0xc1; u2.c[3] = 0x7c;
79761 	u2.c[4] = 0x6d; u2.c[5] = 0xc4; u2.c[6] = 0x00; u2.c[7] = 0x00;
79762 #else
79763 #error unknown double endianness
79764 #endif
79765 
79766 	if (u1.i != (duk_uint32_t) 0xdeadbeefUL) {
79767 		DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: duk_uint32_t byte order");
79768 	}
79769 
79770 	if (u2.d != (double) 102030405060.0) {
79771 		DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: double byte order");
79772 	}
79773 }
79774 
79775 /*
79776  *  DUK_BSWAP macros
79777  */
79778 
79779 DUK_LOCAL void duk__selftest_bswap_macros(void) {
79780 	duk_uint32_t x32;
79781 	duk_uint16_t x16;
79782 	duk_double_union du;
79783 	duk_double_t du_diff;
79784 
79785 	x16 = 0xbeefUL;
79786 	x16 = DUK_BSWAP16(x16);
79787 	if (x16 != (duk_uint16_t) 0xefbeUL) {
79788 		DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: DUK_BSWAP16");
79789 	}
79790 
79791 	x32 = 0xdeadbeefUL;
79792 	x32 = DUK_BSWAP32(x32);
79793 	if (x32 != (duk_uint32_t) 0xefbeaddeUL) {
79794 		DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: DUK_BSWAP32");
79795 	}
79796 
79797 	/* >>> struct.unpack('>d', '4000112233445566'.decode('hex'))
79798 	 * (2.008366013071895,)
79799 	 */
79800 
79801 	du.uc[0] = 0x40; du.uc[1] = 0x00; du.uc[2] = 0x11; du.uc[3] = 0x22;
79802 	du.uc[4] = 0x33; du.uc[5] = 0x44; du.uc[6] = 0x55; du.uc[7] = 0x66;
79803 	DUK_DBLUNION_DOUBLE_NTOH(&du);
79804 	du_diff = du.d - 2.008366013071895;
79805 #if 0
79806 	DUK_FPRINTF(DUK_STDERR, "du_diff: %lg\n", (double) du_diff);
79807 #endif
79808 	if (du_diff > 1e-15) {
79809 		/* Allow very small lenience because some compilers won't parse
79810 		 * exact IEEE double constants (happened in matrix testing with
79811 		 * Linux gcc-4.8 -m32 at least).
79812 		 */
79813 #if 0
79814 		DUK_FPRINTF(DUK_STDERR, "Result of DUK_DBLUNION_DOUBLE_NTOH: %02x %02x %02x %02x %02x %02x %02x %02x\n",
79815 		            (unsigned int) du.uc[0], (unsigned int) du.uc[1],
79816 		            (unsigned int) du.uc[2], (unsigned int) du.uc[3],
79817 		            (unsigned int) du.uc[4], (unsigned int) du.uc[5],
79818 		            (unsigned int) du.uc[6], (unsigned int) du.uc[7]);
79819 #endif
79820 		DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: DUK_DBLUNION_DOUBLE_NTOH");
79821 	}
79822 }
79823 
79824 /*
79825  *  Basic double / byte union memory layout.
79826  */
79827 
79828 DUK_LOCAL void duk__selftest_double_union_size(void) {
79829 	if (sizeof(duk__test_double_union) != 8) {
79830 		DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: invalid union size");
79831 	}
79832 }
79833 
79834 /*
79835  *  Union aliasing, see misc/clang_aliasing.c.
79836  */
79837 
79838 DUK_LOCAL void duk__selftest_double_aliasing(void) {
79839 	duk__test_double_union a, b;
79840 
79841 	/* This testcase fails when Emscripten-generated code runs on Firefox.
79842 	 * It's not an issue because the failure should only affect packed
79843 	 * duk_tval representation, which is not used with Emscripten.
79844 	 */
79845 #if !defined(DUK_USE_PACKED_TVAL)
79846 	DUK_D(DUK_DPRINT("skip double aliasing self test when duk_tval is not packed"));
79847 	return;
79848 #endif
79849 
79850 	/* Test signaling NaN and alias assignment in all endianness combinations.
79851 	 */
79852 
79853 	/* little endian */
79854 	a.c[0] = 0x11; a.c[1] = 0x22; a.c[2] = 0x33; a.c[3] = 0x44;
79855 	a.c[4] = 0x00; a.c[5] = 0x00; a.c[6] = 0xf1; a.c[7] = 0xff;
79856 	b = a;
79857 	DUK__DBLUNION_CMP_TRUE(&a, &b);
79858 
79859 	/* big endian */
79860 	a.c[0] = 0xff; a.c[1] = 0xf1; a.c[2] = 0x00; a.c[3] = 0x00;
79861 	a.c[4] = 0x44; a.c[5] = 0x33; a.c[6] = 0x22; a.c[7] = 0x11;
79862 	b = a;
79863 	DUK__DBLUNION_CMP_TRUE(&a, &b);
79864 
79865 	/* mixed endian */
79866 	a.c[0] = 0x00; a.c[1] = 0x00; a.c[2] = 0xf1; a.c[3] = 0xff;
79867 	a.c[4] = 0x11; a.c[5] = 0x22; a.c[6] = 0x33; a.c[7] = 0x44;
79868 	b = a;
79869 	DUK__DBLUNION_CMP_TRUE(&a, &b);
79870 }
79871 
79872 /*
79873  *  Zero sign, see misc/tcc_zerosign2.c.
79874  */
79875 
79876 DUK_LOCAL void duk__selftest_double_zero_sign(void) {
79877 	duk__test_double_union a, b;
79878 
79879 	a.d = 0.0;
79880 	b.d = -a.d;
79881 	DUK__DBLUNION_CMP_FALSE(&a, &b);
79882 }
79883 
79884 /*
79885  *  Struct size/alignment if platform requires it
79886  *
79887  *  There are some compiler specific struct padding pragmas etc in use, this
79888  *  selftest ensures they're correctly detected and used.
79889  */
79890 
79891 DUK_LOCAL void duk__selftest_struct_align(void) {
79892 #if (DUK_USE_ALIGN_BY == 4)
79893 	if ((sizeof(duk_hbuffer_fixed) % 4) != 0) {
79894 		DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: sizeof(duk_hbuffer_fixed) not aligned to 4");
79895 	}
79896 #elif (DUK_USE_ALIGN_BY == 8)
79897 	if ((sizeof(duk_hbuffer_fixed) % 8) != 0) {
79898 		DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: sizeof(duk_hbuffer_fixed) not aligned to 8");
79899 	}
79900 #elif (DUK_USE_ALIGN_BY == 1)
79901 	/* no check */
79902 #else
79903 #error invalid DUK_USE_ALIGN_BY
79904 #endif
79905 }
79906 
79907 /*
79908  *  64-bit arithmetic
79909  *
79910  *  There are some platforms/compilers where 64-bit types are available
79911  *  but don't work correctly.  Test for known cases.
79912  */
79913 
79914 DUK_LOCAL void duk__selftest_64bit_arithmetic(void) {
79915 #if defined(DUK_USE_64BIT_OPS)
79916 	volatile duk_int64_t i;
79917 	volatile duk_double_t d;
79918 
79919 	/* Catch a double-to-int64 cast issue encountered in practice. */
79920 	d = 2147483648.0;
79921 	i = (duk_int64_t) d;
79922 	if (i != 0x80000000LL) {
79923 		DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: casting 2147483648.0 to duk_int64_t failed");
79924 	}
79925 #else
79926 	/* nop */
79927 #endif
79928 }
79929 
79930 /*
79931  *  Casting
79932  */
79933 
79934 DUK_LOCAL void duk__selftest_cast_double_to_small_uint(void) {
79935 	/*
79936 	 *  https://github.com/svaarala/duktape/issues/127#issuecomment-77863473
79937 	 */
79938 
79939 	duk_double_t d1, d2;
79940 	duk_small_uint_t u;
79941 
79942 	duk_double_t d1v, d2v;
79943 	duk_small_uint_t uv;
79944 
79945 	/* Test without volatiles */
79946 
79947 	d1 = 1.0;
79948 	u = (duk_small_uint_t) d1;
79949 	d2 = (duk_double_t) u;
79950 
79951 	if (!(d1 == 1.0 && u == 1 && d2 == 1.0 && d1 == d2)) {
79952 		DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: double to duk_small_uint_t cast failed");
79953 	}
79954 
79955 	/* Same test with volatiles */
79956 
79957 	d1v = 1.0;
79958 	uv = (duk_small_uint_t) d1v;
79959 	d2v = (duk_double_t) uv;
79960 
79961 	if (!(d1v == 1.0 && uv == 1 && d2v == 1.0 && d1v == d2v)) {
79962 		DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: double to duk_small_uint_t cast failed");
79963 	}
79964 }
79965 
79966 DUK_LOCAL void duk__selftest_cast_double_to_uint32(void) {
79967 	/*
79968 	 *  This test fails on an exotic ARM target; double-to-uint
79969 	 *  cast is incorrectly clamped to -signed- int highest value.
79970 	 *
79971 	 *  https://github.com/svaarala/duktape/issues/336
79972 	 */
79973 
79974 	duk_double_t dv;
79975 	duk_uint32_t uv;
79976 
79977 	dv = 3735928559.0;  /* 0xdeadbeef in decimal */
79978 	uv = (duk_uint32_t) dv;
79979 
79980 	if (uv != 0xdeadbeefUL) {
79981 		DUK_PANIC(DUK_ERR_INTERNAL_ERROR, "self test failed: double to duk_uint32_t cast failed");
79982 	}
79983 }
79984 
79985 /*
79986  *  Self test main
79987  */
79988 
79989 DUK_INTERNAL void duk_selftest_run_tests(void) {
79990 	duk__selftest_types();
79991 	duk__selftest_packed_tval();
79992 	duk__selftest_twos_complement();
79993 	duk__selftest_byte_order();
79994 	duk__selftest_bswap_macros();
79995 	duk__selftest_double_union_size();
79996 	duk__selftest_double_aliasing();
79997 	duk__selftest_double_zero_sign();
79998 	duk__selftest_struct_align();
79999 	duk__selftest_64bit_arithmetic();
80000 	duk__selftest_cast_double_to_small_uint();
80001 	duk__selftest_cast_double_to_uint32();
80002 }
80003 
80004 #undef DUK__DBLUNION_CMP_TRUE
80005 #undef DUK__DBLUNION_CMP_FALSE
80006 
80007 #endif  /* DUK_USE_SELF_TESTS */
80008 /* include removed: duk_internal.h */
80009 
80010 #if defined(DUK_USE_FASTINT)
80011 
80012 /*
80013  *  Manually optimized double-to-fastint downgrade check.
80014  *
80015  *  This check has a large impact on performance, especially for fastint
80016  *  slow paths, so must be changed carefully.  The code should probably be
80017  *  optimized for the case where the result does not fit into a fastint,
80018  *  to minimize the penalty for "slow path code" dealing with fractions etc.
80019  *
80020  *  At least on one tested soft float ARM platform double-to-int64 coercion
80021  *  is very slow (and sometimes produces incorrect results, see self tests).
80022  *  This algorithm combines a fastint compatibility check and extracting the
80023  *  integer value from an IEEE double for setting the tagged fastint.  For
80024  *  other platforms a more naive approach might be better.
80025  *
80026  *  See doc/fastint.rst for details.
80027  */
80028 
80029 DUK_INTERNAL DUK_ALWAYS_INLINE void duk_tval_set_number_chkfast(duk_tval *tv, duk_double_t x) {
80030 	duk_double_union du;
80031 	duk_int64_t i;
80032 	duk_small_int_t expt;
80033 	duk_small_int_t shift;
80034 
80035 	/* XXX: optimize for packed duk_tval directly? */
80036 
80037 	du.d = x;
80038 	i = (duk_int64_t) DUK_DBLUNION_GET_INT64(&du);
80039 	expt = (duk_small_int_t) ((i >> 52) & 0x07ff);
80040 	shift = expt - 1023;
80041 
80042 	if (shift >= 0 && shift <= 46) {  /* exponents 1023 to 1069 */
80043 		duk_int64_t t;
80044 
80045 		if (((0x000fffffffffffffLL >> shift) & i) == 0) {
80046 			t = i | 0x0010000000000000LL;  /* implicit leading one */
80047 			t = t & 0x001fffffffffffffLL;
80048 			t = t >> (52 - shift);
80049 			if (i < 0) {
80050 				t = -t;
80051 			}
80052 			DUK_TVAL_SET_FASTINT(tv, t);
80053 			return;
80054 		}
80055 	} else if (shift == -1023) {  /* exponent 0 */
80056 		if (i >= 0 && (i & 0x000fffffffffffffLL) == 0) {
80057 			/* Note: reject negative zero. */
80058 			DUK_TVAL_SET_FASTINT(tv, (duk_int64_t) 0);
80059 			return;
80060 		}
80061 	} else if (shift == 47) {  /* exponent 1070 */
80062 		if (i < 0 && (i & 0x000fffffffffffffLL) == 0) {
80063 			DUK_TVAL_SET_FASTINT(tv, (duk_int64_t) DUK_FASTINT_MIN);
80064 			return;
80065 		}
80066 	}
80067 
80068 	DUK_TVAL_SET_DOUBLE(tv, x);
80069 	return;
80070 }
80071 
80072 /*
80073  *  Manually optimized number-to-double conversion
80074  */
80075 
80076 #if defined(DUK_USE_FASTINT) && defined(DUK_USE_PACKED_TVAL)
80077 DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_tval_get_number_packed(duk_tval *tv) {
80078 	duk_double_union du;
80079 	duk_uint64_t t;
80080 
80081 	t = (duk_uint64_t) DUK_DBLUNION_GET_UINT64(tv);
80082 	if ((t >> 48) != DUK_TAG_FASTINT) {
80083 		return tv->d;
80084 	} else if (t & 0x0000800000000000ULL) {
80085 		t = (duk_uint64_t) (-((duk_int64_t) t));  /* avoid unary minus on unsigned */
80086 		t = t & 0x0000ffffffffffffULL;  /* negative */
80087 		t |= 0xc330000000000000ULL;
80088 		DUK_DBLUNION_SET_UINT64(&du, t);
80089 		return du.d + 4503599627370496.0;  /* 1 << 52 */
80090 	} else if (t != 0) {
80091 		t &= 0x0000ffffffffffffULL;  /* positive */
80092 		t |= 0x4330000000000000ULL;
80093 		DUK_DBLUNION_SET_UINT64(&du, t);
80094 		return du.d - 4503599627370496.0;  /* 1 << 52 */
80095 	} else {
80096 		return 0.0;  /* zero */
80097 	}
80098 }
80099 #endif  /* DUK_USE_FASTINT && DUK_USE_PACKED_TVAL */
80100 
80101 #if 0  /* unused */
80102 #if defined(DUK_USE_FASTINT) && !defined(DUK_USE_PACKED_TVAL)
80103 DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_tval_get_number_unpacked(duk_tval *tv) {
80104 	duk_double_union du;
80105 	duk_uint64_t t;
80106 
80107 	DUK_ASSERT(tv->t == DUK__TAG_NUMBER || tv->t == DUK_TAG_FASTINT);
80108 
80109 	if (tv->t == DUK_TAG_FASTINT) {
80110 		if (tv->v.fi >= 0) {
80111 			t = 0x4330000000000000ULL | (duk_uint64_t) tv->v.fi;
80112 			DUK_DBLUNION_SET_UINT64(&du, t);
80113 			return du.d - 4503599627370496.0;  /* 1 << 52 */
80114 		} else {
80115 			t = 0xc330000000000000ULL | (duk_uint64_t) (-tv->v.fi);
80116 			DUK_DBLUNION_SET_UINT64(&du, t);
80117 			return du.d + 4503599627370496.0;  /* 1 << 52 */
80118 		}
80119 	} else {
80120 		return tv->v.d;
80121 	}
80122 }
80123 #endif  /* DUK_USE_FASTINT && DUK_USE_PACKED_TVAL */
80124 #endif  /* 0 */
80125 
80126 #if defined(DUK_USE_FASTINT) && !defined(DUK_USE_PACKED_TVAL)
80127 DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_tval_get_number_unpacked_fastint(duk_tval *tv) {
80128 	duk_double_union du;
80129 	duk_uint64_t t;
80130 
80131 	DUK_ASSERT(tv->t == DUK_TAG_FASTINT);
80132 
80133 	if (tv->v.fi >= 0) {
80134 		t = 0x4330000000000000ULL | (duk_uint64_t) tv->v.fi;
80135 		DUK_DBLUNION_SET_UINT64(&du, t);
80136 		return du.d - 4503599627370496.0;  /* 1 << 52 */
80137 	} else {
80138 		t = 0xc330000000000000ULL | (duk_uint64_t) (-tv->v.fi);
80139 		DUK_DBLUNION_SET_UINT64(&du, t);
80140 		return du.d + 4503599627370496.0;  /* 1 << 52 */
80141 	}
80142 }
80143 #endif  /* DUK_USE_FASTINT && DUK_USE_PACKED_TVAL */
80144 
80145 #endif  /* DUK_USE_FASTINT */
80146 /*
80147  *  Unicode support tables automatically generated during build.
80148  */
80149 
80150 /* include removed: duk_internal.h */
80151 
80152 /*
80153  *  Unicode tables containing ranges of Unicode characters in a
80154  *  packed format.  These tables are used to match non-ASCII
80155  *  characters of complex productions by resorting to a linear
80156  *  range-by-range comparison.  This is very slow, but is expected
80157  *  to be very rare in practical Ecmascript source code, and thus
80158  *  compactness is most important.
80159  *
80160  *  The tables are matched using uni_range_match() and the format
80161  *  is described in src/extract_chars.py.
80162  */
80163 
80164 #ifdef DUK_USE_SOURCE_NONBMP
80165 /* IdentifierStart production with ASCII excluded */
80166 /* duk_unicode_ids_noa[] */
80167 /*
80168  *  Automatically generated by extract_chars.py, do not edit!
80169  */
80170 
80171 const duk_uint8_t duk_unicode_ids_noa[791] = {
80172 249,176,176,80,111,7,47,15,47,254,11,197,191,0,72,2,15,115,66,19,57,2,34,2,
80173 240,66,244,50,247,185,248,234,241,99,8,241,127,58,240,182,47,31,241,191,21,
80174 18,245,50,15,1,24,27,35,15,2,2,240,239,15,244,156,15,10,241,26,21,6,240,
80175 101,10,4,15,9,240,159,157,242,100,15,4,8,159,1,98,102,115,19,240,98,98,4,
80176 52,15,2,14,18,47,0,31,5,85,19,240,98,98,18,18,31,17,50,15,5,47,2,130,34,
80177 240,98,98,18,68,15,4,15,1,31,21,115,19,240,98,98,18,68,15,16,18,47,1,15,3,
80178 2,84,34,52,18,2,20,20,36,191,8,15,38,114,34,240,114,146,68,15,12,23,31,21,
80179 114,34,240,114,146,68,15,18,2,31,1,31,4,114,34,241,147,15,2,15,3,31,10,86,
80180 240,36,240,130,130,3,111,44,242,2,29,111,44,18,3,18,3,7,50,98,34,2,3,18,50,
80181 26,3,66,15,7,31,20,15,49,114,241,79,13,79,101,241,191,6,15,2,85,52,4,24,37,
80182 205,15,3,241,107,241,178,4,255,224,59,35,54,32,35,63,25,35,63,17,35,54,32,
80183 35,62,47,41,35,63,51,241,127,0,240,47,69,223,254,21,227,240,18,240,166,243,
80184 180,47,1,194,63,0,240,47,0,240,47,0,194,47,1,242,79,21,5,15,53,244,137,241,
80185 146,6,243,107,240,223,37,240,227,76,241,207,7,111,42,240,122,242,95,68,15,
80186 79,241,255,3,111,41,240,238,31,2,241,111,12,241,79,27,43,241,79,93,50,63,0,
80187 251,15,50,255,224,8,53,63,22,53,55,32,32,32,47,15,63,37,38,32,66,38,67,53,
80188 92,98,38,246,96,224,240,44,245,112,80,57,32,68,112,32,32,35,42,51,100,80,
80189 240,63,25,255,233,107,241,242,241,242,247,87,63,3,241,107,242,106,15,2,240,
80190 122,98,98,98,98,98,98,98,111,66,15,254,12,146,240,184,132,52,95,70,114,47,
80191 74,35,111,25,79,78,240,63,11,242,127,0,255,224,244,255,240,0,138,143,60,
80192 255,240,4,11,239,38,255,227,127,243,95,30,63,253,79,0,177,240,111,31,240,
80193 47,9,159,64,241,152,63,87,51,33,240,9,244,39,34,35,47,7,240,255,36,240,15,
80194 34,243,5,64,240,15,12,191,7,240,191,13,143,31,240,224,242,47,25,240,146,39,
80195 240,111,7,64,111,32,32,65,52,48,32,240,162,241,85,53,53,166,38,248,63,19,
80196 240,255,255,0,26,150,223,7,95,33,255,240,0,255,143,254,2,3,242,227,245,175,
80197 24,109,70,2,146,194,66,2,18,18,245,207,19,255,224,93,240,79,48,63,38,241,
80198 171,246,100,47,119,241,111,10,127,10,207,73,69,53,53,50,241,91,47,10,47,3,
80199 33,46,61,241,79,107,243,127,37,255,223,13,79,33,242,31,15,240,63,11,242,
80200 127,14,63,20,87,36,241,207,142,255,226,86,83,2,241,194,20,3,240,127,156,
80201 240,107,240,175,184,15,1,50,34,240,191,30,240,223,117,242,107,240,107,240,
80202 63,127,243,159,254,42,239,37,243,223,29,255,238,68,255,226,97,248,63,83,
80203 255,234,145,255,227,33,255,240,2,44,95,254,18,191,255,0,52,187,31,255,0,18,
80204 242,244,82,243,114,19,3,19,50,178,2,98,243,18,51,114,98,240,194,50,66,4,98,
80205 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,
80206 240,1,114,143,255,0,149,201,241,191,254,242,124,252,239,255,0,46,214,255,
80207 225,16,0,
80208 };
80209 #else
80210 /* IdentifierStart production with ASCII and non-BMP excluded */
80211 /* duk_unicode_ids_noabmp[] */
80212 /*
80213  *  Automatically generated by extract_chars.py, do not edit!
80214  */
80215 
80216 const duk_uint8_t duk_unicode_ids_noabmp[611] = {
80217 249,176,176,80,111,7,47,15,47,254,11,197,191,0,72,2,15,115,66,19,57,2,34,2,
80218 240,66,244,50,247,185,248,234,241,99,8,241,127,58,240,182,47,31,241,191,21,
80219 18,245,50,15,1,24,27,35,15,2,2,240,239,15,244,156,15,10,241,26,21,6,240,
80220 101,10,4,15,9,240,159,157,242,100,15,4,8,159,1,98,102,115,19,240,98,98,4,
80221 52,15,2,14,18,47,0,31,5,85,19,240,98,98,18,18,31,17,50,15,5,47,2,130,34,
80222 240,98,98,18,68,15,4,15,1,31,21,115,19,240,98,98,18,68,15,16,18,47,1,15,3,
80223 2,84,34,52,18,2,20,20,36,191,8,15,38,114,34,240,114,146,68,15,12,23,31,21,
80224 114,34,240,114,146,68,15,18,2,31,1,31,4,114,34,241,147,15,2,15,3,31,10,86,
80225 240,36,240,130,130,3,111,44,242,2,29,111,44,18,3,18,3,7,50,98,34,2,3,18,50,
80226 26,3,66,15,7,31,20,15,49,114,241,79,13,79,101,241,191,6,15,2,85,52,4,24,37,
80227 205,15,3,241,107,241,178,4,255,224,59,35,54,32,35,63,25,35,63,17,35,54,32,
80228 35,62,47,41,35,63,51,241,127,0,240,47,69,223,254,21,227,240,18,240,166,243,
80229 180,47,1,194,63,0,240,47,0,240,47,0,194,47,1,242,79,21,5,15,53,244,137,241,
80230 146,6,243,107,240,223,37,240,227,76,241,207,7,111,42,240,122,242,95,68,15,
80231 79,241,255,3,111,41,240,238,31,2,241,111,12,241,79,27,43,241,79,93,50,63,0,
80232 251,15,50,255,224,8,53,63,22,53,55,32,32,32,47,15,63,37,38,32,66,38,67,53,
80233 92,98,38,246,96,224,240,44,245,112,80,57,32,68,112,32,32,35,42,51,100,80,
80234 240,63,25,255,233,107,241,242,241,242,247,87,63,3,241,107,242,106,15,2,240,
80235 122,98,98,98,98,98,98,98,111,66,15,254,12,146,240,184,132,52,95,70,114,47,
80236 74,35,111,25,79,78,240,63,11,242,127,0,255,224,244,255,240,0,138,143,60,
80237 255,240,4,11,239,38,255,227,127,243,95,30,63,253,79,0,177,240,111,31,240,
80238 47,9,159,64,241,152,63,87,51,33,240,9,244,39,34,35,47,7,240,255,36,240,15,
80239 34,243,5,64,240,15,12,191,7,240,191,13,143,31,240,224,242,47,25,240,146,39,
80240 240,111,7,64,111,32,32,65,52,48,32,240,162,241,85,53,53,166,38,248,63,19,
80241 240,255,255,0,26,150,223,7,95,33,255,240,0,255,143,254,2,3,242,227,245,175,
80242 24,109,70,2,146,194,66,2,18,18,245,207,19,255,224,93,240,79,48,63,38,241,
80243 171,246,100,47,119,241,111,10,127,10,207,73,69,53,53,50,0,
80244 };
80245 #endif
80246 
80247 #ifdef DUK_USE_SOURCE_NONBMP
80248 /* IdentifierStart production with Letter and ASCII excluded */
80249 /* duk_unicode_ids_m_let_noa[] */
80250 /*
80251  *  Automatically generated by extract_chars.py, do not edit!
80252  */
80253 
80254 const duk_uint8_t duk_unicode_ids_m_let_noa[42] = {
80255 255,240,0,94,18,255,233,99,241,51,63,254,215,32,240,184,240,2,255,240,6,89,
80256 249,255,240,4,148,79,37,255,224,192,9,15,120,79,255,0,15,30,245,48,
80257 };
80258 #else
80259 /* IdentifierStart production with Letter, ASCII, and non-BMP excluded */
80260 /* duk_unicode_ids_m_let_noabmp[] */
80261 /*
80262  *  Automatically generated by extract_chars.py, do not edit!
80263  */
80264 
80265 const duk_uint8_t duk_unicode_ids_m_let_noabmp[24] = {
80266 255,240,0,94,18,255,233,99,241,51,63,254,215,32,240,184,240,2,255,240,6,89,
80267 249,0,
80268 };
80269 #endif
80270 
80271 #ifdef DUK_USE_SOURCE_NONBMP
80272 /* IdentifierPart production with IdentifierStart and ASCII excluded */
80273 /* duk_unicode_idp_m_ids_noa[] */
80274 /*
80275  *  Automatically generated by extract_chars.py, do not edit!
80276  */
80277 
80278 const duk_uint8_t duk_unicode_idp_m_ids_noa[397] = {
80279 255,225,243,246,15,254,0,116,255,191,29,32,33,33,32,243,170,242,47,15,112,
80280 245,118,53,49,35,57,240,144,241,15,11,244,218,240,25,241,56,241,67,40,34,
80281 36,241,210,249,99,242,130,47,2,38,177,57,240,50,242,160,38,49,50,160,177,
80282 57,240,50,242,160,36,81,50,64,240,107,64,194,242,160,39,34,34,240,97,57,
80283 240,50,242,160,38,49,50,145,177,57,240,64,242,212,66,35,160,240,9,240,50,
80284 242,198,34,35,129,193,57,240,65,242,160,38,34,35,129,193,57,240,65,242,198,
80285 34,35,160,177,57,240,65,243,128,85,32,39,240,65,242,240,54,215,41,244,144,
80286 53,33,197,57,243,1,121,192,32,32,81,242,63,4,33,106,47,20,160,245,111,4,41,
80287 211,82,34,54,67,235,46,255,225,179,47,254,42,98,240,242,240,241,241,1,243,
80288 79,14,160,57,241,50,57,248,16,246,139,91,185,245,47,1,129,121,242,244,242,
80289 185,47,13,58,121,245,132,242,31,1,201,240,56,210,241,9,105,241,237,242,47,
80290 4,153,121,246,130,47,5,80,80,251,255,23,240,115,255,225,0,31,35,31,5,15,
80291 109,197,4,191,254,175,34,247,240,245,47,16,255,225,30,95,91,31,255,0,100,
80292 121,159,55,13,31,100,31,254,0,64,64,80,240,148,244,161,242,79,1,201,127,2,
80293 240,9,240,231,240,188,241,227,242,29,240,25,244,29,208,145,57,241,48,242,
80294 96,34,49,97,32,255,224,21,114,19,159,255,0,62,24,15,254,29,95,0,240,38,209,
80295 240,162,251,41,241,112,255,225,177,15,254,25,105,255,228,75,34,22,63,26,37,
80296 15,254,75,66,242,126,241,25,240,34,241,250,255,240,10,249,228,69,151,54,
80297 241,3,248,98,255,228,125,242,47,255,12,23,244,254,0,
80298 };
80299 #else
80300 /* IdentifierPart production with IdentifierStart, ASCII, and non-BMP excluded */
80301 /* duk_unicode_idp_m_ids_noabmp[] */
80302 /*
80303  *  Automatically generated by extract_chars.py, do not edit!
80304  */
80305 
80306 const duk_uint8_t duk_unicode_idp_m_ids_noabmp[348] = {
80307 255,225,243,246,15,254,0,116,255,191,29,32,33,33,32,243,170,242,47,15,112,
80308 245,118,53,49,35,57,240,144,241,15,11,244,218,240,25,241,56,241,67,40,34,
80309 36,241,210,249,99,242,130,47,2,38,177,57,240,50,242,160,38,49,50,160,177,
80310 57,240,50,242,160,36,81,50,64,240,107,64,194,242,160,39,34,34,240,97,57,
80311 240,50,242,160,38,49,50,145,177,57,240,64,242,212,66,35,160,240,9,240,50,
80312 242,198,34,35,129,193,57,240,65,242,160,38,34,35,129,193,57,240,65,242,198,
80313 34,35,160,177,57,240,65,243,128,85,32,39,240,65,242,240,54,215,41,244,144,
80314 53,33,197,57,243,1,121,192,32,32,81,242,63,4,33,106,47,20,160,245,111,4,41,
80315 211,82,34,54,67,235,46,255,225,179,47,254,42,98,240,242,240,241,241,1,243,
80316 79,14,160,57,241,50,57,248,16,246,139,91,185,245,47,1,129,121,242,244,242,
80317 185,47,13,58,121,245,132,242,31,1,201,240,56,210,241,9,105,241,237,242,47,
80318 4,153,121,246,130,47,5,80,80,251,255,23,240,115,255,225,0,31,35,31,5,15,
80319 109,197,4,191,254,175,34,247,240,245,47,16,255,225,30,95,91,31,255,0,100,
80320 121,159,55,13,31,100,31,254,0,64,64,80,240,148,244,161,242,79,1,201,127,2,
80321 240,9,240,231,240,188,241,227,242,29,240,25,244,29,208,145,57,241,48,242,
80322 96,34,49,97,32,255,224,21,114,19,159,255,0,62,24,15,254,29,95,0,240,38,209,
80323 240,162,251,41,241,112,0,
80324 };
80325 #endif
80326 
80327 /*
80328  *  Case conversion tables generated using src/extract_caseconv.py.
80329  */
80330 
80331 /* duk_unicode_caseconv_uc[] */
80332 /* duk_unicode_caseconv_lc[] */
80333 
80334 /*
80335  *  Automatically generated by extract_caseconv.py, do not edit!
80336  */
80337 
80338 const duk_uint8_t duk_unicode_caseconv_uc[1288] = {
80339 132,3,128,3,0,184,7,192,6,192,112,35,242,199,224,64,74,192,49,32,128,162,
80340 128,108,65,1,189,129,254,131,3,173,3,136,6,7,98,7,34,68,15,12,14,140,72,30,
80341 104,28,112,32,67,0,65,4,0,138,0,128,4,1,88,65,76,83,15,128,15,132,8,31,16,
80342 31,24,12,62,64,62,80,32,124,192,124,224,64,250,0,250,64,97,246,1,246,129,3,
80343 238,3,247,64,135,220,135,242,2,15,187,15,237,2,31,120,31,248,4,62,244,63,
80344 212,8,125,240,127,232,16,253,128,253,192,33,253,1,253,128,67,252,3,253,0,
80345 136,92,8,88,8,18,104,18,91,26,44,48,44,0,94,90,0,33,64,155,253,7,252,132,
80346 212,0,32,32,32,6,0,76,192,76,129,128,157,0,156,136,1,75,1,74,46,2,244,2,
80347 242,12,6,12,6,8,16,13,8,13,0,48,27,64,27,48,64,57,192,57,162,0,119,192,119,
80348 132,128,252,128,252,20,2,35,2,34,18,4,142,4,140,20,13,196,13,192,16,30,200,
80349 30,192,192,70,16,70,2,32,145,96,145,70,193,48,129,48,67,130,104,130,104,44,
80350 30,1,30,0,150,61,66,61,64,192,125,68,125,100,33,99,65,99,56,50,200,18,200,
80351 6,69,157,133,157,96,169,144,105,144,11,211,64,211,64,12,167,35,167,34,15,
80352 78,103,78,100,126,157,234,157,228,21,59,253,59,240,90,122,26,122,0,163,128,
80353 214,128,214,2,1,197,1,196,6,3,140,3,136,12,7,200,7,196,16,20,0,13,48,32,63,
80354 128,63,112,69,142,101,142,64,130,1,136,1,135,4,3,114,3,112,8,26,120,202,
80355 120,176,65,1,30,1,29,130,2,105,1,150,5,255,96,22,160,115,128,31,224,47,0,
80356 38,32,9,32,47,224,10,96,48,0,72,96,50,64,50,32,50,160,62,192,51,32,51,0,51,
80357 64,71,160,51,192,68,0,53,0,52,224,55,224,62,224,59,160,49,192,62,96,62,32,
80358 74,5,141,224,74,37,141,160,74,69,142,0,74,96,48,32,74,128,48,192,75,32,49,
80359 224,75,96,50,0,76,0,50,96,76,96,50,128,76,180,241,160,77,0,50,224,77,101,
80360 140,64,78,37,141,192,78,64,51,160,78,160,51,224,79,165,140,128,81,0,53,192,
80361 81,32,72,128,81,128,72,160,82,64,54,224,104,160,115,32,110,224,110,192,117,
80362 128,112,192,120,64,116,96,121,128,113,128,122,0,114,64,122,32,115,0,122,
80363 160,116,192,122,192,116,0,122,224,121,224,126,0,115,64,126,32,116,32,126,
80364 64,127,32,126,160,114,160,153,224,152,3,175,52,239,163,175,165,140,99,211,
80365 99,204,3,247,192,115,35,252,163,253,132,41,196,38,68,48,132,48,101,140,37,
80366 140,5,140,160,71,69,140,192,71,217,128,55,224,5,48,5,48,20,152,10,240,1,56,
80367 7,194,0,74,3,12,3,144,192,230,64,194,0,192,64,236,48,58,80,48,128,48,16,88,
80368 120,20,212,21,72,122,90,0,72,3,49,30,151,128,21,0,194,7,166,32,5,112,48,
80369 161,233,152,1,100,12,40,122,106,0,65,2,190,31,80,128,233,64,196,199,212,
80370 176,58,80,49,48,48,1,245,76,14,148,12,76,12,4,125,91,3,165,3,19,3,66,31,
80371 128,135,194,0,230,71,224,97,240,144,57,145,248,40,124,40,14,100,126,14,31,
80372 11,3,153,31,132,135,195,0,230,71,225,97,240,208,57,145,248,104,124,56,14,
80373 100,126,30,31,15,3,153,31,136,135,194,0,230,71,226,97,240,144,57,145,248,
80374 168,124,40,14,100,126,46,31,11,3,153,31,140,135,195,0,230,71,227,97,240,
80375 208,57,145,248,232,124,56,14,100,126,62,31,15,3,153,31,144,135,202,0,230,
80376 71,228,97,242,144,57,145,249,40,124,168,14,100,126,78,31,43,3,153,31,148,
80377 135,203,0,230,71,229,97,242,208,57,145,249,104,124,184,14,100,126,94,31,47,
80378 3,153,31,152,135,202,0,230,71,230,97,242,144,57,145,249,168,124,168,14,100,
80379 126,110,31,43,3,153,31,156,135,203,0,230,71,231,97,242,208,57,145,249,232,
80380 124,184,14,100,126,126,31,47,3,153,31,160,135,218,0,230,71,232,97,246,144,
80381 57,145,250,40,125,168,14,100,126,142,31,107,3,153,31,164,135,219,0,230,71,
80382 233,97,246,208,57,145,250,104,125,184,14,100,126,158,31,111,3,153,31,168,
80383 135,218,0,230,71,234,97,246,144,57,145,250,168,125,168,14,100,126,174,31,
80384 107,3,153,31,172,135,219,0,230,71,235,97,246,208,57,145,250,232,125,184,14,
80385 100,126,190,31,111,3,153,31,178,135,238,128,230,71,236,224,57,16,57,145,
80386 251,72,14,24,14,100,126,218,3,145,3,66,31,183,192,228,64,208,128,230,71,
80387 239,32,57,16,57,145,252,40,127,40,14,100,127,14,3,151,3,153,31,196,128,226,
80388 64,230,71,241,160,57,112,52,33,252,124,14,92,13,8,14,100,127,50,3,151,3,
80389 153,31,210,192,230,64,194,0,192,7,244,240,57,144,48,128,48,17,253,104,14,
80390 100,13,8,127,95,3,153,3,8,3,66,31,226,192,233,64,194,0,192,7,248,240,58,80,
80391 48,128,48,17,254,72,14,132,12,76,127,154,3,165,3,66,31,231,192,233,64,194,
80392 0,208,135,252,161,255,160,57,145,255,56,14,164,14,100,127,210,3,143,3,153,
80393 31,246,128,234,64,208,135,253,240,58,144,52,32,57,145,255,200,14,164,14,
80394 103,236,2,0,70,0,70,251,1,128,17,128,18,126,192,160,4,96,4,207,176,60,1,24,
80395 1,24,1,39,236,19,0,70,0,70,0,76,251,5,128,20,192,21,62,193,160,5,48,5,79,
80396 177,56,21,16,21,27,236,82,5,68,5,53,251,21,129,81,1,78,254,197,160,84,224,
80397 84,111,177,120,21,16,20,244,
80398 };
80399 const duk_uint8_t duk_unicode_caseconv_lc[616] = {
80400 144,3,0,3,128,184,6,192,7,192,112,24,144,37,96,64,54,32,81,64,128,226,0,
80401 235,65,129,199,1,230,130,3,145,3,177,34,7,70,7,134,36,15,244,13,236,24,32,
80402 0,34,129,0,65,0,67,4,0,166,32,172,41,132,40,11,64,19,15,132,15,128,8,31,24,
80403 31,16,12,62,80,62,64,32,124,224,124,192,64,250,64,250,0,97,246,129,246,1,3,
80404 241,3,240,2,7,230,7,228,4,15,212,15,208,8,31,184,31,176,4,63,116,62,224,8,
80405 127,32,125,200,32,254,192,254,128,33,253,161,247,96,67,253,3,252,0,135,250,
80406 135,222,129,15,252,15,188,2,31,250,31,124,4,66,192,66,224,64,146,216,147,
80407 64,209,96,1,97,130,242,199,224,35,240,95,228,63,232,38,161,1,0,1,1,48,2,
80408 100,2,102,12,4,228,4,232,64,10,80,10,89,112,23,144,23,160,96,48,64,48,96,
80409 128,104,0,104,65,128,217,128,218,2,1,203,1,204,18,3,188,3,190,36,7,200,7,
80410 204,16,15,192,15,201,64,34,32,34,49,32,72,192,72,225,64,220,0,220,65,1,236,
80411 1,236,140,4,96,4,97,34,9,20,9,22,108,19,4,19,8,56,38,128,38,138,193,224,1,
80412 224,25,99,212,3,212,44,7,214,71,212,66,22,51,150,52,3,44,128,44,129,100,89,
80413 214,89,216,10,153,2,153,4,189,52,5,52,8,202,114,42,114,48,244,230,84,230,
80414 103,233,222,105,222,129,83,191,83,191,133,167,160,167,161,10,48,13,48,20,0,
80415 32,26,192,26,208,64,56,128,56,192,192,113,64,113,129,1,251,129,252,2,44,
80416 114,44,115,4,16,12,56,12,64,32,27,128,27,144,64,211,197,211,198,2,8,6,88,9,
80417 164,16,17,216,17,224,47,245,1,120,0,255,1,129,2,83,1,134,2,84,1,142,1,221,
80418 1,143,2,89,1,144,2,91,1,145,1,146,1,147,2,96,1,148,2,99,1,151,2,104,1,152,
80419 1,153,1,157,2,114,1,159,2,117,1,167,1,168,1,174,2,136,1,183,2,146,1,241,1,
80420 243,1,246,1,149,1,247,1,191,2,32,1,158,2,58,44,101,2,61,1,154,2,62,44,102,
80421 2,67,1,128,2,68,2,137,2,69,2,140,3,118,3,119,3,134,3,172,3,140,3,204,3,207,
80422 3,215,3,244,3,184,3,249,3,242,4,192,4,207,30,158,0,223,31,188,31,179,31,
80423 204,31,195,31,236,31,229,31,252,31,243,33,38,3,201,33,42,0,107,33,43,0,229,
80424 33,50,33,78,33,131,33,132,44,96,44,97,44,98,2,107,44,99,29,125,44,100,2,
80425 125,44,109,2,81,44,110,2,113,44,111,2,80,44,112,2,82,167,125,29,121,167,
80426 141,2,101,2,2,97,0,52,129,131,128,
80427 };
80428 
80429 #if defined(DUK_USE_REGEXP_CANON_WORKAROUND)
80430 /*
80431  *  Automatically generated by extract_caseconv.py, do not edit!
80432  */
80433 
80434 const duk_uint16_t duk_unicode_re_canon_lookup[65536] = {
80435 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,
80436 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,
80437 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,
80438 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,
80439 71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,123,124,125,
80440 126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
80441 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,
80442 162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,
80443 180,924,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,
80444 198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,
80445 216,217,218,219,220,221,222,223,192,193,194,195,196,197,198,199,200,201,
80446 202,203,204,205,206,207,208,209,210,211,212,213,214,247,216,217,218,219,
80447 220,221,222,376,256,256,258,258,260,260,262,262,264,264,266,266,268,268,
80448 270,270,272,272,274,274,276,276,278,278,280,280,282,282,284,284,286,286,
80449 288,288,290,290,292,292,294,294,296,296,298,298,300,300,302,302,304,305,
80450 306,306,308,308,310,310,312,313,313,315,315,317,317,319,319,321,321,323,
80451 323,325,325,327,327,329,330,330,332,332,334,334,336,336,338,338,340,340,
80452 342,342,344,344,346,346,348,348,350,350,352,352,354,354,356,356,358,358,
80453 360,360,362,362,364,364,366,366,368,368,370,370,372,372,374,374,376,377,
80454 377,379,379,381,381,383,579,385,386,386,388,388,390,391,391,393,394,395,
80455 395,397,398,399,400,401,401,403,404,502,406,407,408,408,573,411,412,413,
80456 544,415,416,416,418,418,420,420,422,423,423,425,426,427,428,428,430,431,
80457 431,433,434,435,435,437,437,439,440,440,442,443,444,444,446,503,448,449,
80458 450,451,452,452,452,455,455,455,458,458,458,461,461,463,463,465,465,467,
80459 467,469,469,471,471,473,473,475,475,398,478,478,480,480,482,482,484,484,
80460 486,486,488,488,490,490,492,492,494,494,496,497,497,497,500,500,502,503,
80461 504,504,506,506,508,508,510,510,512,512,514,514,516,516,518,518,520,520,
80462 522,522,524,524,526,526,528,528,530,530,532,532,534,534,536,536,538,538,
80463 540,540,542,542,544,545,546,546,548,548,550,550,552,552,554,554,556,556,
80464 558,558,560,560,562,562,564,565,566,567,568,569,570,571,571,573,574,11390,
80465 11391,577,577,579,580,581,582,582,584,584,586,586,588,588,590,590,11375,
80466 11373,11376,385,390,597,393,394,600,399,602,400,604,605,606,607,403,609,
80467 610,404,612,42893L,614,615,407,406,618,11362,620,621,622,412,624,11374,413,
80468 627,628,415,630,631,632,633,634,635,636,11364,638,639,422,641,642,425,644,
80469 645,646,647,430,580,433,434,581,653,654,655,656,657,439,659,660,661,662,
80470 663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,
80471 681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,
80472 699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,
80473 717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,
80474 735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,
80475 753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,
80476 771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,
80477 789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,
80478 807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,
80479 825,826,827,828,829,830,831,832,833,834,835,836,921,838,839,840,841,842,
80480 843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,
80481 861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,
80482 879,880,880,882,882,884,885,886,886,888,889,890,1021,1022,1023,894,895,896,
80483 897,898,899,900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,
80484 915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,930,931,932,
80485 933,934,935,936,937,938,939,902,904,905,906,944,913,914,915,916,917,918,
80486 919,920,921,922,923,924,925,926,927,928,929,931,931,932,933,934,935,936,
80487 937,938,939,908,910,911,975,914,920,978,979,980,934,928,975,984,984,986,
80488 986,988,988,990,990,992,992,994,994,996,996,998,998,1000,1000,1002,1002,
80489 1004,1004,1006,1006,922,929,1017,1011,1012,917,1014,1015,1015,1017,1018,
80490 1018,1020,1021,1022,1023,1024,1025,1026,1027,1028,1029,1030,1031,1032,1033,
80491 1034,1035,1036,1037,1038,1039,1040,1041,1042,1043,1044,1045,1046,1047,1048,
80492 1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,
80493 1064,1065,1066,1067,1068,1069,1070,1071,1040,1041,1042,1043,1044,1045,1046,
80494 1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,
80495 1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1024,1025,1026,1027,1028,
80496 1029,1030,1031,1032,1033,1034,1035,1036,1037,1038,1039,1120,1120,1122,1122,
80497 1124,1124,1126,1126,1128,1128,1130,1130,1132,1132,1134,1134,1136,1136,1138,
80498 1138,1140,1140,1142,1142,1144,1144,1146,1146,1148,1148,1150,1150,1152,1152,
80499 1154,1155,1156,1157,1158,1159,1160,1161,1162,1162,1164,1164,1166,1166,1168,
80500 1168,1170,1170,1172,1172,1174,1174,1176,1176,1178,1178,1180,1180,1182,1182,
80501 1184,1184,1186,1186,1188,1188,1190,1190,1192,1192,1194,1194,1196,1196,1198,
80502 1198,1200,1200,1202,1202,1204,1204,1206,1206,1208,1208,1210,1210,1212,1212,
80503 1214,1214,1216,1217,1217,1219,1219,1221,1221,1223,1223,1225,1225,1227,1227,
80504 1229,1229,1216,1232,1232,1234,1234,1236,1236,1238,1238,1240,1240,1242,1242,
80505 1244,1244,1246,1246,1248,1248,1250,1250,1252,1252,1254,1254,1256,1256,1258,
80506 1258,1260,1260,1262,1262,1264,1264,1266,1266,1268,1268,1270,1270,1272,1272,
80507 1274,1274,1276,1276,1278,1278,1280,1280,1282,1282,1284,1284,1286,1286,1288,
80508 1288,1290,1290,1292,1292,1294,1294,1296,1296,1298,1298,1300,1300,1302,1302,
80509 1304,1304,1306,1306,1308,1308,1310,1310,1312,1312,1314,1314,1316,1316,1318,
80510 1318,1320,1321,1322,1323,1324,1325,1326,1327,1328,1329,1330,1331,1332,1333,
80511 1334,1335,1336,1337,1338,1339,1340,1341,1342,1343,1344,1345,1346,1347,1348,
80512 1349,1350,1351,1352,1353,1354,1355,1356,1357,1358,1359,1360,1361,1362,1363,
80513 1364,1365,1366,1367,1368,1369,1370,1371,1372,1373,1374,1375,1376,1329,1330,
80514 1331,1332,1333,1334,1335,1336,1337,1338,1339,1340,1341,1342,1343,1344,1345,
80515 1346,1347,1348,1349,1350,1351,1352,1353,1354,1355,1356,1357,1358,1359,1360,
80516 1361,1362,1363,1364,1365,1366,1415,1416,1417,1418,1419,1420,1421,1422,1423,
80517 1424,1425,1426,1427,1428,1429,1430,1431,1432,1433,1434,1435,1436,1437,1438,
80518 1439,1440,1441,1442,1443,1444,1445,1446,1447,1448,1449,1450,1451,1452,1453,
80519 1454,1455,1456,1457,1458,1459,1460,1461,1462,1463,1464,1465,1466,1467,1468,
80520 1469,1470,1471,1472,1473,1474,1475,1476,1477,1478,1479,1480,1481,1482,1483,
80521 1484,1485,1486,1487,1488,1489,1490,1491,1492,1493,1494,1495,1496,1497,1498,
80522 1499,1500,1501,1502,1503,1504,1505,1506,1507,1508,1509,1510,1511,1512,1513,
80523 1514,1515,1516,1517,1518,1519,1520,1521,1522,1523,1524,1525,1526,1527,1528,
80524 1529,1530,1531,1532,1533,1534,1535,1536,1537,1538,1539,1540,1541,1542,1543,
80525 1544,1545,1546,1547,1548,1549,1550,1551,1552,1553,1554,1555,1556,1557,1558,
80526 1559,1560,1561,1562,1563,1564,1565,1566,1567,1568,1569,1570,1571,1572,1573,
80527 1574,1575,1576,1577,1578,1579,1580,1581,1582,1583,1584,1585,1586,1587,1588,
80528 1589,1590,1591,1592,1593,1594,1595,1596,1597,1598,1599,1600,1601,1602,1603,
80529 1604,1605,1606,1607,1608,1609,1610,1611,1612,1613,1614,1615,1616,1617,1618,
80530 1619,1620,1621,1622,1623,1624,1625,1626,1627,1628,1629,1630,1631,1632,1633,
80531 1634,1635,1636,1637,1638,1639,1640,1641,1642,1643,1644,1645,1646,1647,1648,
80532 1649,1650,1651,1652,1653,1654,1655,1656,1657,1658,1659,1660,1661,1662,1663,
80533 1664,1665,1666,1667,1668,1669,1670,1671,1672,1673,1674,1675,1676,1677,1678,
80534 1679,1680,1681,1682,1683,1684,1685,1686,1687,1688,1689,1690,1691,1692,1693,
80535 1694,1695,1696,1697,1698,1699,1700,1701,1702,1703,1704,1705,1706,1707,1708,
80536 1709,1710,1711,1712,1713,1714,1715,1716,1717,1718,1719,1720,1721,1722,1723,
80537 1724,1725,1726,1727,1728,1729,1730,1731,1732,1733,1734,1735,1736,1737,1738,
80538 1739,1740,1741,1742,1743,1744,1745,1746,1747,1748,1749,1750,1751,1752,1753,
80539 1754,1755,1756,1757,1758,1759,1760,1761,1762,1763,1764,1765,1766,1767,1768,
80540 1769,1770,1771,1772,1773,1774,1775,1776,1777,1778,1779,1780,1781,1782,1783,
80541 1784,1785,1786,1787,1788,1789,1790,1791,1792,1793,1794,1795,1796,1797,1798,
80542 1799,1800,1801,1802,1803,1804,1805,1806,1807,1808,1809,1810,1811,1812,1813,
80543 1814,1815,1816,1817,1818,1819,1820,1821,1822,1823,1824,1825,1826,1827,1828,
80544 1829,1830,1831,1832,1833,1834,1835,1836,1837,1838,1839,1840,1841,1842,1843,
80545 1844,1845,1846,1847,1848,1849,1850,1851,1852,1853,1854,1855,1856,1857,1858,
80546 1859,1860,1861,1862,1863,1864,1865,1866,1867,1868,1869,1870,1871,1872,1873,
80547 1874,1875,1876,1877,1878,1879,1880,1881,1882,1883,1884,1885,1886,1887,1888,
80548 1889,1890,1891,1892,1893,1894,1895,1896,1897,1898,1899,1900,1901,1902,1903,
80549 1904,1905,1906,1907,1908,1909,1910,1911,1912,1913,1914,1915,1916,1917,1918,
80550 1919,1920,1921,1922,1923,1924,1925,1926,1927,1928,1929,1930,1931,1932,1933,
80551 1934,1935,1936,1937,1938,1939,1940,1941,1942,1943,1944,1945,1946,1947,1948,
80552 1949,1950,1951,1952,1953,1954,1955,1956,1957,1958,1959,1960,1961,1962,1963,
80553 1964,1965,1966,1967,1968,1969,1970,1971,1972,1973,1974,1975,1976,1977,1978,
80554 1979,1980,1981,1982,1983,1984,1985,1986,1987,1988,1989,1990,1991,1992,1993,
80555 1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,
80556 2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021,2022,2023,
80557 2024,2025,2026,2027,2028,2029,2030,2031,2032,2033,2034,2035,2036,2037,2038,
80558 2039,2040,2041,2042,2043,2044,2045,2046,2047,2048,2049,2050,2051,2052,2053,
80559 2054,2055,2056,2057,2058,2059,2060,2061,2062,2063,2064,2065,2066,2067,2068,
80560 2069,2070,2071,2072,2073,2074,2075,2076,2077,2078,2079,2080,2081,2082,2083,
80561 2084,2085,2086,2087,2088,2089,2090,2091,2092,2093,2094,2095,2096,2097,2098,
80562 2099,2100,2101,2102,2103,2104,2105,2106,2107,2108,2109,2110,2111,2112,2113,
80563 2114,2115,2116,2117,2118,2119,2120,2121,2122,2123,2124,2125,2126,2127,2128,
80564 2129,2130,2131,2132,2133,2134,2135,2136,2137,2138,2139,2140,2141,2142,2143,
80565 2144,2145,2146,2147,2148,2149,2150,2151,2152,2153,2154,2155,2156,2157,2158,
80566 2159,2160,2161,2162,2163,2164,2165,2166,2167,2168,2169,2170,2171,2172,2173,
80567 2174,2175,2176,2177,2178,2179,2180,2181,2182,2183,2184,2185,2186,2187,2188,
80568 2189,2190,2191,2192,2193,2194,2195,2196,2197,2198,2199,2200,2201,2202,2203,
80569 2204,2205,2206,2207,2208,2209,2210,2211,2212,2213,2214,2215,2216,2217,2218,
80570 2219,2220,2221,2222,2223,2224,2225,2226,2227,2228,2229,2230,2231,2232,2233,
80571 2234,2235,2236,2237,2238,2239,2240,2241,2242,2243,2244,2245,2246,2247,2248,
80572 2249,2250,2251,2252,2253,2254,2255,2256,2257,2258,2259,2260,2261,2262,2263,
80573 2264,2265,2266,2267,2268,2269,2270,2271,2272,2273,2274,2275,2276,2277,2278,
80574 2279,2280,2281,2282,2283,2284,2285,2286,2287,2288,2289,2290,2291,2292,2293,
80575 2294,2295,2296,2297,2298,2299,2300,2301,2302,2303,2304,2305,2306,2307,2308,
80576 2309,2310,2311,2312,2313,2314,2315,2316,2317,2318,2319,2320,2321,2322,2323,
80577 2324,2325,2326,2327,2328,2329,2330,2331,2332,2333,2334,2335,2336,2337,2338,
80578 2339,2340,2341,2342,2343,2344,2345,2346,2347,2348,2349,2350,2351,2352,2353,
80579 2354,2355,2356,2357,2358,2359,2360,2361,2362,2363,2364,2365,2366,2367,2368,
80580 2369,2370,2371,2372,2373,2374,2375,2376,2377,2378,2379,2380,2381,2382,2383,
80581 2384,2385,2386,2387,2388,2389,2390,2391,2392,2393,2394,2395,2396,2397,2398,
80582 2399,2400,2401,2402,2403,2404,2405,2406,2407,2408,2409,2410,2411,2412,2413,
80583 2414,2415,2416,2417,2418,2419,2420,2421,2422,2423,2424,2425,2426,2427,2428,
80584 2429,2430,2431,2432,2433,2434,2435,2436,2437,2438,2439,2440,2441,2442,2443,
80585 2444,2445,2446,2447,2448,2449,2450,2451,2452,2453,2454,2455,2456,2457,2458,
80586 2459,2460,2461,2462,2463,2464,2465,2466,2467,2468,2469,2470,2471,2472,2473,
80587 2474,2475,2476,2477,2478,2479,2480,2481,2482,2483,2484,2485,2486,2487,2488,
80588 2489,2490,2491,2492,2493,2494,2495,2496,2497,2498,2499,2500,2501,2502,2503,
80589 2504,2505,2506,2507,2508,2509,2510,2511,2512,2513,2514,2515,2516,2517,2518,
80590 2519,2520,2521,2522,2523,2524,2525,2526,2527,2528,2529,2530,2531,2532,2533,
80591 2534,2535,2536,2537,2538,2539,2540,2541,2542,2543,2544,2545,2546,2547,2548,
80592 2549,2550,2551,2552,2553,2554,2555,2556,2557,2558,2559,2560,2561,2562,2563,
80593 2564,2565,2566,2567,2568,2569,2570,2571,2572,2573,2574,2575,2576,2577,2578,
80594 2579,2580,2581,2582,2583,2584,2585,2586,2587,2588,2589,2590,2591,2592,2593,
80595 2594,2595,2596,2597,2598,2599,2600,2601,2602,2603,2604,2605,2606,2607,2608,
80596 2609,2610,2611,2612,2613,2614,2615,2616,2617,2618,2619,2620,2621,2622,2623,
80597 2624,2625,2626,2627,2628,2629,2630,2631,2632,2633,2634,2635,2636,2637,2638,
80598 2639,2640,2641,2642,2643,2644,2645,2646,2647,2648,2649,2650,2651,2652,2653,
80599 2654,2655,2656,2657,2658,2659,2660,2661,2662,2663,2664,2665,2666,2667,2668,
80600 2669,2670,2671,2672,2673,2674,2675,2676,2677,2678,2679,2680,2681,2682,2683,
80601 2684,2685,2686,2687,2688,2689,2690,2691,2692,2693,2694,2695,2696,2697,2698,
80602 2699,2700,2701,2702,2703,2704,2705,2706,2707,2708,2709,2710,2711,2712,2713,
80603 2714,2715,2716,2717,2718,2719,2720,2721,2722,2723,2724,2725,2726,2727,2728,
80604 2729,2730,2731,2732,2733,2734,2735,2736,2737,2738,2739,2740,2741,2742,2743,
80605 2744,2745,2746,2747,2748,2749,2750,2751,2752,2753,2754,2755,2756,2757,2758,
80606 2759,2760,2761,2762,2763,2764,2765,2766,2767,2768,2769,2770,2771,2772,2773,
80607 2774,2775,2776,2777,2778,2779,2780,2781,2782,2783,2784,2785,2786,2787,2788,
80608 2789,2790,2791,2792,2793,2794,2795,2796,2797,2798,2799,2800,2801,2802,2803,
80609 2804,2805,2806,2807,2808,2809,2810,2811,2812,2813,2814,2815,2816,2817,2818,
80610 2819,2820,2821,2822,2823,2824,2825,2826,2827,2828,2829,2830,2831,2832,2833,
80611 2834,2835,2836,2837,2838,2839,2840,2841,2842,2843,2844,2845,2846,2847,2848,
80612 2849,2850,2851,2852,2853,2854,2855,2856,2857,2858,2859,2860,2861,2862,2863,
80613 2864,2865,2866,2867,2868,2869,2870,2871,2872,2873,2874,2875,2876,2877,2878,
80614 2879,2880,2881,2882,2883,2884,2885,2886,2887,2888,2889,2890,2891,2892,2893,
80615 2894,2895,2896,2897,2898,2899,2900,2901,2902,2903,2904,2905,2906,2907,2908,
80616 2909,2910,2911,2912,2913,2914,2915,2916,2917,2918,2919,2920,2921,2922,2923,
80617 2924,2925,2926,2927,2928,2929,2930,2931,2932,2933,2934,2935,2936,2937,2938,
80618 2939,2940,2941,2942,2943,2944,2945,2946,2947,2948,2949,2950,2951,2952,2953,
80619 2954,2955,2956,2957,2958,2959,2960,2961,2962,2963,2964,2965,2966,2967,2968,
80620 2969,2970,2971,2972,2973,2974,2975,2976,2977,2978,2979,2980,2981,2982,2983,
80621 2984,2985,2986,2987,2988,2989,2990,2991,2992,2993,2994,2995,2996,2997,2998,
80622 2999,3000,3001,3002,3003,3004,3005,3006,3007,3008,3009,3010,3011,3012,3013,
80623 3014,3015,3016,3017,3018,3019,3020,3021,3022,3023,3024,3025,3026,3027,3028,
80624 3029,3030,3031,3032,3033,3034,3035,3036,3037,3038,3039,3040,3041,3042,3043,
80625 3044,3045,3046,3047,3048,3049,3050,3051,3052,3053,3054,3055,3056,3057,3058,
80626 3059,3060,3061,3062,3063,3064,3065,3066,3067,3068,3069,3070,3071,3072,3073,
80627 3074,3075,3076,3077,3078,3079,3080,3081,3082,3083,3084,3085,3086,3087,3088,
80628 3089,3090,3091,3092,3093,3094,3095,3096,3097,3098,3099,3100,3101,3102,3103,
80629 3104,3105,3106,3107,3108,3109,3110,3111,3112,3113,3114,3115,3116,3117,3118,
80630 3119,3120,3121,3122,3123,3124,3125,3126,3127,3128,3129,3130,3131,3132,3133,
80631 3134,3135,3136,3137,3138,3139,3140,3141,3142,3143,3144,3145,3146,3147,3148,
80632 3149,3150,3151,3152,3153,3154,3155,3156,3157,3158,3159,3160,3161,3162,3163,
80633 3164,3165,3166,3167,3168,3169,3170,3171,3172,3173,3174,3175,3176,3177,3178,
80634 3179,3180,3181,3182,3183,3184,3185,3186,3187,3188,3189,3190,3191,3192,3193,
80635 3194,3195,3196,3197,3198,3199,3200,3201,3202,3203,3204,3205,3206,3207,3208,
80636 3209,3210,3211,3212,3213,3214,3215,3216,3217,3218,3219,3220,3221,3222,3223,
80637 3224,3225,3226,3227,3228,3229,3230,3231,3232,3233,3234,3235,3236,3237,3238,
80638 3239,3240,3241,3242,3243,3244,3245,3246,3247,3248,3249,3250,3251,3252,3253,
80639 3254,3255,3256,3257,3258,3259,3260,3261,3262,3263,3264,3265,3266,3267,3268,
80640 3269,3270,3271,3272,3273,3274,3275,3276,3277,3278,3279,3280,3281,3282,3283,
80641 3284,3285,3286,3287,3288,3289,3290,3291,3292,3293,3294,3295,3296,3297,3298,
80642 3299,3300,3301,3302,3303,3304,3305,3306,3307,3308,3309,3310,3311,3312,3313,
80643 3314,3315,3316,3317,3318,3319,3320,3321,3322,3323,3324,3325,3326,3327,3328,
80644 3329,3330,3331,3332,3333,3334,3335,3336,3337,3338,3339,3340,3341,3342,3343,
80645 3344,3345,3346,3347,3348,3349,3350,3351,3352,3353,3354,3355,3356,3357,3358,
80646 3359,3360,3361,3362,3363,3364,3365,3366,3367,3368,3369,3370,3371,3372,3373,
80647 3374,3375,3376,3377,3378,3379,3380,3381,3382,3383,3384,3385,3386,3387,3388,
80648 3389,3390,3391,3392,3393,3394,3395,3396,3397,3398,3399,3400,3401,3402,3403,
80649 3404,3405,3406,3407,3408,3409,3410,3411,3412,3413,3414,3415,3416,3417,3418,
80650 3419,3420,3421,3422,3423,3424,3425,3426,3427,3428,3429,3430,3431,3432,3433,
80651 3434,3435,3436,3437,3438,3439,3440,3441,3442,3443,3444,3445,3446,3447,3448,
80652 3449,3450,3451,3452,3453,3454,3455,3456,3457,3458,3459,3460,3461,3462,3463,
80653 3464,3465,3466,3467,3468,3469,3470,3471,3472,3473,3474,3475,3476,3477,3478,
80654 3479,3480,3481,3482,3483,3484,3485,3486,3487,3488,3489,3490,3491,3492,3493,
80655 3494,3495,3496,3497,3498,3499,3500,3501,3502,3503,3504,3505,3506,3507,3508,
80656 3509,3510,3511,3512,3513,3514,3515,3516,3517,3518,3519,3520,3521,3522,3523,
80657 3524,3525,3526,3527,3528,3529,3530,3531,3532,3533,3534,3535,3536,3537,3538,
80658 3539,3540,3541,3542,3543,3544,3545,3546,3547,3548,3549,3550,3551,3552,3553,
80659 3554,3555,3556,3557,3558,3559,3560,3561,3562,3563,3564,3565,3566,3567,3568,
80660 3569,3570,3571,3572,3573,3574,3575,3576,3577,3578,3579,3580,3581,3582,3583,
80661 3584,3585,3586,3587,3588,3589,3590,3591,3592,3593,3594,3595,3596,3597,3598,
80662 3599,3600,3601,3602,3603,3604,3605,3606,3607,3608,3609,3610,3611,3612,3613,
80663 3614,3615,3616,3617,3618,3619,3620,3621,3622,3623,3624,3625,3626,3627,3628,
80664 3629,3630,3631,3632,3633,3634,3635,3636,3637,3638,3639,3640,3641,3642,3643,
80665 3644,3645,3646,3647,3648,3649,3650,3651,3652,3653,3654,3655,3656,3657,3658,
80666 3659,3660,3661,3662,3663,3664,3665,3666,3667,3668,3669,3670,3671,3672,3673,
80667 3674,3675,3676,3677,3678,3679,3680,3681,3682,3683,3684,3685,3686,3687,3688,
80668 3689,3690,3691,3692,3693,3694,3695,3696,3697,3698,3699,3700,3701,3702,3703,
80669 3704,3705,3706,3707,3708,3709,3710,3711,3712,3713,3714,3715,3716,3717,3718,
80670 3719,3720,3721,3722,3723,3724,3725,3726,3727,3728,3729,3730,3731,3732,3733,
80671 3734,3735,3736,3737,3738,3739,3740,3741,3742,3743,3744,3745,3746,3747,3748,
80672 3749,3750,3751,3752,3753,3754,3755,3756,3757,3758,3759,3760,3761,3762,3763,
80673 3764,3765,3766,3767,3768,3769,3770,3771,3772,3773,3774,3775,3776,3777,3778,
80674 3779,3780,3781,3782,3783,3784,3785,3786,3787,3788,3789,3790,3791,3792,3793,
80675 3794,3795,3796,3797,3798,3799,3800,3801,3802,3803,3804,3805,3806,3807,3808,
80676 3809,3810,3811,3812,3813,3814,3815,3816,3817,3818,3819,3820,3821,3822,3823,
80677 3824,3825,3826,3827,3828,3829,3830,3831,3832,3833,3834,3835,3836,3837,3838,
80678 3839,3840,3841,3842,3843,3844,3845,3846,3847,3848,3849,3850,3851,3852,3853,
80679 3854,3855,3856,3857,3858,3859,3860,3861,3862,3863,3864,3865,3866,3867,3868,
80680 3869,3870,3871,3872,3873,3874,3875,3876,3877,3878,3879,3880,3881,3882,3883,
80681 3884,3885,3886,3887,3888,3889,3890,3891,3892,3893,3894,3895,3896,3897,3898,
80682 3899,3900,3901,3902,3903,3904,3905,3906,3907,3908,3909,3910,3911,3912,3913,
80683 3914,3915,3916,3917,3918,3919,3920,3921,3922,3923,3924,3925,3926,3927,3928,
80684 3929,3930,3931,3932,3933,3934,3935,3936,3937,3938,3939,3940,3941,3942,3943,
80685 3944,3945,3946,3947,3948,3949,3950,3951,3952,3953,3954,3955,3956,3957,3958,
80686 3959,3960,3961,3962,3963,3964,3965,3966,3967,3968,3969,3970,3971,3972,3973,
80687 3974,3975,3976,3977,3978,3979,3980,3981,3982,3983,3984,3985,3986,3987,3988,
80688 3989,3990,3991,3992,3993,3994,3995,3996,3997,3998,3999,4000,4001,4002,4003,
80689 4004,4005,4006,4007,4008,4009,4010,4011,4012,4013,4014,4015,4016,4017,4018,
80690 4019,4020,4021,4022,4023,4024,4025,4026,4027,4028,4029,4030,4031,4032,4033,
80691 4034,4035,4036,4037,4038,4039,4040,4041,4042,4043,4044,4045,4046,4047,4048,
80692 4049,4050,4051,4052,4053,4054,4055,4056,4057,4058,4059,4060,4061,4062,4063,
80693 4064,4065,4066,4067,4068,4069,4070,4071,4072,4073,4074,4075,4076,4077,4078,
80694 4079,4080,4081,4082,4083,4084,4085,4086,4087,4088,4089,4090,4091,4092,4093,
80695 4094,4095,4096,4097,4098,4099,4100,4101,4102,4103,4104,4105,4106,4107,4108,
80696 4109,4110,4111,4112,4113,4114,4115,4116,4117,4118,4119,4120,4121,4122,4123,
80697 4124,4125,4126,4127,4128,4129,4130,4131,4132,4133,4134,4135,4136,4137,4138,
80698 4139,4140,4141,4142,4143,4144,4145,4146,4147,4148,4149,4150,4151,4152,4153,
80699 4154,4155,4156,4157,4158,4159,4160,4161,4162,4163,4164,4165,4166,4167,4168,
80700 4169,4170,4171,4172,4173,4174,4175,4176,4177,4178,4179,4180,4181,4182,4183,
80701 4184,4185,4186,4187,4188,4189,4190,4191,4192,4193,4194,4195,4196,4197,4198,
80702 4199,4200,4201,4202,4203,4204,4205,4206,4207,4208,4209,4210,4211,4212,4213,
80703 4214,4215,4216,4217,4218,4219,4220,4221,4222,4223,4224,4225,4226,4227,4228,
80704 4229,4230,4231,4232,4233,4234,4235,4236,4237,4238,4239,4240,4241,4242,4243,
80705 4244,4245,4246,4247,4248,4249,4250,4251,4252,4253,4254,4255,4256,4257,4258,
80706 4259,4260,4261,4262,4263,4264,4265,4266,4267,4268,4269,4270,4271,4272,4273,
80707 4274,4275,4276,4277,4278,4279,4280,4281,4282,4283,4284,4285,4286,4287,4288,
80708 4289,4290,4291,4292,4293,4294,4295,4296,4297,4298,4299,4300,4301,4302,4303,
80709 4304,4305,4306,4307,4308,4309,4310,4311,4312,4313,4314,4315,4316,4317,4318,
80710 4319,4320,4321,4322,4323,4324,4325,4326,4327,4328,4329,4330,4331,4332,4333,
80711 4334,4335,4336,4337,4338,4339,4340,4341,4342,4343,4344,4345,4346,4347,4348,
80712 4349,4350,4351,4352,4353,4354,4355,4356,4357,4358,4359,4360,4361,4362,4363,
80713 4364,4365,4366,4367,4368,4369,4370,4371,4372,4373,4374,4375,4376,4377,4378,
80714 4379,4380,4381,4382,4383,4384,4385,4386,4387,4388,4389,4390,4391,4392,4393,
80715 4394,4395,4396,4397,4398,4399,4400,4401,4402,4403,4404,4405,4406,4407,4408,
80716 4409,4410,4411,4412,4413,4414,4415,4416,4417,4418,4419,4420,4421,4422,4423,
80717 4424,4425,4426,4427,4428,4429,4430,4431,4432,4433,4434,4435,4436,4437,4438,
80718 4439,4440,4441,4442,4443,4444,4445,4446,4447,4448,4449,4450,4451,4452,4453,
80719 4454,4455,4456,4457,4458,4459,4460,4461,4462,4463,4464,4465,4466,4467,4468,
80720 4469,4470,4471,4472,4473,4474,4475,4476,4477,4478,4479,4480,4481,4482,4483,
80721 4484,4485,4486,4487,4488,4489,4490,4491,4492,4493,4494,4495,4496,4497,4498,
80722 4499,4500,4501,4502,4503,4504,4505,4506,4507,4508,4509,4510,4511,4512,4513,
80723 4514,4515,4516,4517,4518,4519,4520,4521,4522,4523,4524,4525,4526,4527,4528,
80724 4529,4530,4531,4532,4533,4534,4535,4536,4537,4538,4539,4540,4541,4542,4543,
80725 4544,4545,4546,4547,4548,4549,4550,4551,4552,4553,4554,4555,4556,4557,4558,
80726 4559,4560,4561,4562,4563,4564,4565,4566,4567,4568,4569,4570,4571,4572,4573,
80727 4574,4575,4576,4577,4578,4579,4580,4581,4582,4583,4584,4585,4586,4587,4588,
80728 4589,4590,4591,4592,4593,4594,4595,4596,4597,4598,4599,4600,4601,4602,4603,
80729 4604,4605,4606,4607,4608,4609,4610,4611,4612,4613,4614,4615,4616,4617,4618,
80730 4619,4620,4621,4622,4623,4624,4625,4626,4627,4628,4629,4630,4631,4632,4633,
80731 4634,4635,4636,4637,4638,4639,4640,4641,4642,4643,4644,4645,4646,4647,4648,
80732 4649,4650,4651,4652,4653,4654,4655,4656,4657,4658,4659,4660,4661,4662,4663,
80733 4664,4665,4666,4667,4668,4669,4670,4671,4672,4673,4674,4675,4676,4677,4678,
80734 4679,4680,4681,4682,4683,4684,4685,4686,4687,4688,4689,4690,4691,4692,4693,
80735 4694,4695,4696,4697,4698,4699,4700,4701,4702,4703,4704,4705,4706,4707,4708,
80736 4709,4710,4711,4712,4713,4714,4715,4716,4717,4718,4719,4720,4721,4722,4723,
80737 4724,4725,4726,4727,4728,4729,4730,4731,4732,4733,4734,4735,4736,4737,4738,
80738 4739,4740,4741,4742,4743,4744,4745,4746,4747,4748,4749,4750,4751,4752,4753,
80739 4754,4755,4756,4757,4758,4759,4760,4761,4762,4763,4764,4765,4766,4767,4768,
80740 4769,4770,4771,4772,4773,4774,4775,4776,4777,4778,4779,4780,4781,4782,4783,
80741 4784,4785,4786,4787,4788,4789,4790,4791,4792,4793,4794,4795,4796,4797,4798,
80742 4799,4800,4801,4802,4803,4804,4805,4806,4807,4808,4809,4810,4811,4812,4813,
80743 4814,4815,4816,4817,4818,4819,4820,4821,4822,4823,4824,4825,4826,4827,4828,
80744 4829,4830,4831,4832,4833,4834,4835,4836,4837,4838,4839,4840,4841,4842,4843,
80745 4844,4845,4846,4847,4848,4849,4850,4851,4852,4853,4854,4855,4856,4857,4858,
80746 4859,4860,4861,4862,4863,4864,4865,4866,4867,4868,4869,4870,4871,4872,4873,
80747 4874,4875,4876,4877,4878,4879,4880,4881,4882,4883,4884,4885,4886,4887,4888,
80748 4889,4890,4891,4892,4893,4894,4895,4896,4897,4898,4899,4900,4901,4902,4903,
80749 4904,4905,4906,4907,4908,4909,4910,4911,4912,4913,4914,4915,4916,4917,4918,
80750 4919,4920,4921,4922,4923,4924,4925,4926,4927,4928,4929,4930,4931,4932,4933,
80751 4934,4935,4936,4937,4938,4939,4940,4941,4942,4943,4944,4945,4946,4947,4948,
80752 4949,4950,4951,4952,4953,4954,4955,4956,4957,4958,4959,4960,4961,4962,4963,
80753 4964,4965,4966,4967,4968,4969,4970,4971,4972,4973,4974,4975,4976,4977,4978,
80754 4979,4980,4981,4982,4983,4984,4985,4986,4987,4988,4989,4990,4991,4992,4993,
80755 4994,4995,4996,4997,4998,4999,5000,5001,5002,5003,5004,5005,5006,5007,5008,
80756 5009,5010,5011,5012,5013,5014,5015,5016,5017,5018,5019,5020,5021,5022,5023,
80757 5024,5025,5026,5027,5028,5029,5030,5031,5032,5033,5034,5035,5036,5037,5038,
80758 5039,5040,5041,5042,5043,5044,5045,5046,5047,5048,5049,5050,5051,5052,5053,
80759 5054,5055,5056,5057,5058,5059,5060,5061,5062,5063,5064,5065,5066,5067,5068,
80760 5069,5070,5071,5072,5073,5074,5075,5076,5077,5078,5079,5080,5081,5082,5083,
80761 5084,5085,5086,5087,5088,5089,5090,5091,5092,5093,5094,5095,5096,5097,5098,
80762 5099,5100,5101,5102,5103,5104,5105,5106,5107,5108,5109,5110,5111,5112,5113,
80763 5114,5115,5116,5117,5118,5119,5120,5121,5122,5123,5124,5125,5126,5127,5128,
80764 5129,5130,5131,5132,5133,5134,5135,5136,5137,5138,5139,5140,5141,5142,5143,
80765 5144,5145,5146,5147,5148,5149,5150,5151,5152,5153,5154,5155,5156,5157,5158,
80766 5159,5160,5161,5162,5163,5164,5165,5166,5167,5168,5169,5170,5171,5172,5173,
80767 5174,5175,5176,5177,5178,5179,5180,5181,5182,5183,5184,5185,5186,5187,5188,
80768 5189,5190,5191,5192,5193,5194,5195,5196,5197,5198,5199,5200,5201,5202,5203,
80769 5204,5205,5206,5207,5208,5209,5210,5211,5212,5213,5214,5215,5216,5217,5218,
80770 5219,5220,5221,5222,5223,5224,5225,5226,5227,5228,5229,5230,5231,5232,5233,
80771 5234,5235,5236,5237,5238,5239,5240,5241,5242,5243,5244,5245,5246,5247,5248,
80772 5249,5250,5251,5252,5253,5254,5255,5256,5257,5258,5259,5260,5261,5262,5263,
80773 5264,5265,5266,5267,5268,5269,5270,5271,5272,5273,5274,5275,5276,5277,5278,
80774 5279,5280,5281,5282,5283,5284,5285,5286,5287,5288,5289,5290,5291,5292,5293,
80775 5294,5295,5296,5297,5298,5299,5300,5301,5302,5303,5304,5305,5306,5307,5308,
80776 5309,5310,5311,5312,5313,5314,5315,5316,5317,5318,5319,5320,5321,5322,5323,
80777 5324,5325,5326,5327,5328,5329,5330,5331,5332,5333,5334,5335,5336,5337,5338,
80778 5339,5340,5341,5342,5343,5344,5345,5346,5347,5348,5349,5350,5351,5352,5353,
80779 5354,5355,5356,5357,5358,5359,5360,5361,5362,5363,5364,5365,5366,5367,5368,
80780 5369,5370,5371,5372,5373,5374,5375,5376,5377,5378,5379,5380,5381,5382,5383,
80781 5384,5385,5386,5387,5388,5389,5390,5391,5392,5393,5394,5395,5396,5397,5398,
80782 5399,5400,5401,5402,5403,5404,5405,5406,5407,5408,5409,5410,5411,5412,5413,
80783 5414,5415,5416,5417,5418,5419,5420,5421,5422,5423,5424,5425,5426,5427,5428,
80784 5429,5430,5431,5432,5433,5434,5435,5436,5437,5438,5439,5440,5441,5442,5443,
80785 5444,5445,5446,5447,5448,5449,5450,5451,5452,5453,5454,5455,5456,5457,5458,
80786 5459,5460,5461,5462,5463,5464,5465,5466,5467,5468,5469,5470,5471,5472,5473,
80787 5474,5475,5476,5477,5478,5479,5480,5481,5482,5483,5484,5485,5486,5487,5488,
80788 5489,5490,5491,5492,5493,5494,5495,5496,5497,5498,5499,5500,5501,5502,5503,
80789 5504,5505,5506,5507,5508,5509,5510,5511,5512,5513,5514,5515,5516,5517,5518,
80790 5519,5520,5521,5522,5523,5524,5525,5526,5527,5528,5529,5530,5531,5532,5533,
80791 5534,5535,5536,5537,5538,5539,5540,5541,5542,5543,5544,5545,5546,5547,5548,
80792 5549,5550,5551,5552,5553,5554,5555,5556,5557,5558,5559,5560,5561,5562,5563,
80793 5564,5565,5566,5567,5568,5569,5570,5571,5572,5573,5574,5575,5576,5577,5578,
80794 5579,5580,5581,5582,5583,5584,5585,5586,5587,5588,5589,5590,5591,5592,5593,
80795 5594,5595,5596,5597,5598,5599,5600,5601,5602,5603,5604,5605,5606,5607,5608,
80796 5609,5610,5611,5612,5613,5614,5615,5616,5617,5618,5619,5620,5621,5622,5623,
80797 5624,5625,5626,5627,5628,5629,5630,5631,5632,5633,5634,5635,5636,5637,5638,
80798 5639,5640,5641,5642,5643,5644,5645,5646,5647,5648,5649,5650,5651,5652,5653,
80799 5654,5655,5656,5657,5658,5659,5660,5661,5662,5663,5664,5665,5666,5667,5668,
80800 5669,5670,5671,5672,5673,5674,5675,5676,5677,5678,5679,5680,5681,5682,5683,
80801 5684,5685,5686,5687,5688,5689,5690,5691,5692,5693,5694,5695,5696,5697,5698,
80802 5699,5700,5701,5702,5703,5704,5705,5706,5707,5708,5709,5710,5711,5712,5713,
80803 5714,5715,5716,5717,5718,5719,5720,5721,5722,5723,5724,5725,5726,5727,5728,
80804 5729,5730,5731,5732,5733,5734,5735,5736,5737,5738,5739,5740,5741,5742,5743,
80805 5744,5745,5746,5747,5748,5749,5750,5751,5752,5753,5754,5755,5756,5757,5758,
80806 5759,5760,5761,5762,5763,5764,5765,5766,5767,5768,5769,5770,5771,5772,5773,
80807 5774,5775,5776,5777,5778,5779,5780,5781,5782,5783,5784,5785,5786,5787,5788,
80808 5789,5790,5791,5792,5793,5794,5795,5796,5797,5798,5799,5800,5801,5802,5803,
80809 5804,5805,5806,5807,5808,5809,5810,5811,5812,5813,5814,5815,5816,5817,5818,
80810 5819,5820,5821,5822,5823,5824,5825,5826,5827,5828,5829,5830,5831,5832,5833,
80811 5834,5835,5836,5837,5838,5839,5840,5841,5842,5843,5844,5845,5846,5847,5848,
80812 5849,5850,5851,5852,5853,5854,5855,5856,5857,5858,5859,5860,5861,5862,5863,
80813 5864,5865,5866,5867,5868,5869,5870,5871,5872,5873,5874,5875,5876,5877,5878,
80814 5879,5880,5881,5882,5883,5884,5885,5886,5887,5888,5889,5890,5891,5892,5893,
80815 5894,5895,5896,5897,5898,5899,5900,5901,5902,5903,5904,5905,5906,5907,5908,
80816 5909,5910,5911,5912,5913,5914,5915,5916,5917,5918,5919,5920,5921,5922,5923,
80817 5924,5925,5926,5927,5928,5929,5930,5931,5932,5933,5934,5935,5936,5937,5938,
80818 5939,5940,5941,5942,5943,5944,5945,5946,5947,5948,5949,5950,5951,5952,5953,
80819 5954,5955,5956,5957,5958,5959,5960,5961,5962,5963,5964,5965,5966,5967,5968,
80820 5969,5970,5971,5972,5973,5974,5975,5976,5977,5978,5979,5980,5981,5982,5983,
80821 5984,5985,5986,5987,5988,5989,5990,5991,5992,5993,5994,5995,5996,5997,5998,
80822 5999,6000,6001,6002,6003,6004,6005,6006,6007,6008,6009,6010,6011,6012,6013,
80823 6014,6015,6016,6017,6018,6019,6020,6021,6022,6023,6024,6025,6026,6027,6028,
80824 6029,6030,6031,6032,6033,6034,6035,6036,6037,6038,6039,6040,6041,6042,6043,
80825 6044,6045,6046,6047,6048,6049,6050,6051,6052,6053,6054,6055,6056,6057,6058,
80826 6059,6060,6061,6062,6063,6064,6065,6066,6067,6068,6069,6070,6071,6072,6073,
80827 6074,6075,6076,6077,6078,6079,6080,6081,6082,6083,6084,6085,6086,6087,6088,
80828 6089,6090,6091,6092,6093,6094,6095,6096,6097,6098,6099,6100,6101,6102,6103,
80829 6104,6105,6106,6107,6108,6109,6110,6111,6112,6113,6114,6115,6116,6117,6118,
80830 6119,6120,6121,6122,6123,6124,6125,6126,6127,6128,6129,6130,6131,6132,6133,
80831 6134,6135,6136,6137,6138,6139,6140,6141,6142,6143,6144,6145,6146,6147,6148,
80832 6149,6150,6151,6152,6153,6154,6155,6156,6157,6158,6159,6160,6161,6162,6163,
80833 6164,6165,6166,6167,6168,6169,6170,6171,6172,6173,6174,6175,6176,6177,6178,
80834 6179,6180,6181,6182,6183,6184,6185,6186,6187,6188,6189,6190,6191,6192,6193,
80835 6194,6195,6196,6197,6198,6199,6200,6201,6202,6203,6204,6205,6206,6207,6208,
80836 6209,6210,6211,6212,6213,6214,6215,6216,6217,6218,6219,6220,6221,6222,6223,
80837 6224,6225,6226,6227,6228,6229,6230,6231,6232,6233,6234,6235,6236,6237,6238,
80838 6239,6240,6241,6242,6243,6244,6245,6246,6247,6248,6249,6250,6251,6252,6253,
80839 6254,6255,6256,6257,6258,6259,6260,6261,6262,6263,6264,6265,6266,6267,6268,
80840 6269,6270,6271,6272,6273,6274,6275,6276,6277,6278,6279,6280,6281,6282,6283,
80841 6284,6285,6286,6287,6288,6289,6290,6291,6292,6293,6294,6295,6296,6297,6298,
80842 6299,6300,6301,6302,6303,6304,6305,6306,6307,6308,6309,6310,6311,6312,6313,
80843 6314,6315,6316,6317,6318,6319,6320,6321,6322,6323,6324,6325,6326,6327,6328,
80844 6329,6330,6331,6332,6333,6334,6335,6336,6337,6338,6339,6340,6341,6342,6343,
80845 6344,6345,6346,6347,6348,6349,6350,6351,6352,6353,6354,6355,6356,6357,6358,
80846 6359,6360,6361,6362,6363,6364,6365,6366,6367,6368,6369,6370,6371,6372,6373,
80847 6374,6375,6376,6377,6378,6379,6380,6381,6382,6383,6384,6385,6386,6387,6388,
80848 6389,6390,6391,6392,6393,6394,6395,6396,6397,6398,6399,6400,6401,6402,6403,
80849 6404,6405,6406,6407,6408,6409,6410,6411,6412,6413,6414,6415,6416,6417,6418,
80850 6419,6420,6421,6422,6423,6424,6425,6426,6427,6428,6429,6430,6431,6432,6433,
80851 6434,6435,6436,6437,6438,6439,6440,6441,6442,6443,6444,6445,6446,6447,6448,
80852 6449,6450,6451,6452,6453,6454,6455,6456,6457,6458,6459,6460,6461,6462,6463,
80853 6464,6465,6466,6467,6468,6469,6470,6471,6472,6473,6474,6475,6476,6477,6478,
80854 6479,6480,6481,6482,6483,6484,6485,6486,6487,6488,6489,6490,6491,6492,6493,
80855 6494,6495,6496,6497,6498,6499,6500,6501,6502,6503,6504,6505,6506,6507,6508,
80856 6509,6510,6511,6512,6513,6514,6515,6516,6517,6518,6519,6520,6521,6522,6523,
80857 6524,6525,6526,6527,6528,6529,6530,6531,6532,6533,6534,6535,6536,6537,6538,
80858 6539,6540,6541,6542,6543,6544,6545,6546,6547,6548,6549,6550,6551,6552,6553,
80859 6554,6555,6556,6557,6558,6559,6560,6561,6562,6563,6564,6565,6566,6567,6568,
80860 6569,6570,6571,6572,6573,6574,6575,6576,6577,6578,6579,6580,6581,6582,6583,
80861 6584,6585,6586,6587,6588,6589,6590,6591,6592,6593,6594,6595,6596,6597,6598,
80862 6599,6600,6601,6602,6603,6604,6605,6606,6607,6608,6609,6610,6611,6612,6613,
80863 6614,6615,6616,6617,6618,6619,6620,6621,6622,6623,6624,6625,6626,6627,6628,
80864 6629,6630,6631,6632,6633,6634,6635,6636,6637,6638,6639,6640,6641,6642,6643,
80865 6644,6645,6646,6647,6648,6649,6650,6651,6652,6653,6654,6655,6656,6657,6658,
80866 6659,6660,6661,6662,6663,6664,6665,6666,6667,6668,6669,6670,6671,6672,6673,
80867 6674,6675,6676,6677,6678,6679,6680,6681,6682,6683,6684,6685,6686,6687,6688,
80868 6689,6690,6691,6692,6693,6694,6695,6696,6697,6698,6699,6700,6701,6702,6703,
80869 6704,6705,6706,6707,6708,6709,6710,6711,6712,6713,6714,6715,6716,6717,6718,
80870 6719,6720,6721,6722,6723,6724,6725,6726,6727,6728,6729,6730,6731,6732,6733,
80871 6734,6735,6736,6737,6738,6739,6740,6741,6742,6743,6744,6745,6746,6747,6748,
80872 6749,6750,6751,6752,6753,6754,6755,6756,6757,6758,6759,6760,6761,6762,6763,
80873 6764,6765,6766,6767,6768,6769,6770,6771,6772,6773,6774,6775,6776,6777,6778,
80874 6779,6780,6781,6782,6783,6784,6785,6786,6787,6788,6789,6790,6791,6792,6793,
80875 6794,6795,6796,6797,6798,6799,6800,6801,6802,6803,6804,6805,6806,6807,6808,
80876 6809,6810,6811,6812,6813,6814,6815,6816,6817,6818,6819,6820,6821,6822,6823,
80877 6824,6825,6826,6827,6828,6829,6830,6831,6832,6833,6834,6835,6836,6837,6838,
80878 6839,6840,6841,6842,6843,6844,6845,6846,6847,6848,6849,6850,6851,6852,6853,
80879 6854,6855,6856,6857,6858,6859,6860,6861,6862,6863,6864,6865,6866,6867,6868,
80880 6869,6870,6871,6872,6873,6874,6875,6876,6877,6878,6879,6880,6881,6882,6883,
80881 6884,6885,6886,6887,6888,6889,6890,6891,6892,6893,6894,6895,6896,6897,6898,
80882 6899,6900,6901,6902,6903,6904,6905,6906,6907,6908,6909,6910,6911,6912,6913,
80883 6914,6915,6916,6917,6918,6919,6920,6921,6922,6923,6924,6925,6926,6927,6928,
80884 6929,6930,6931,6932,6933,6934,6935,6936,6937,6938,6939,6940,6941,6942,6943,
80885 6944,6945,6946,6947,6948,6949,6950,6951,6952,6953,6954,6955,6956,6957,6958,
80886 6959,6960,6961,6962,6963,6964,6965,6966,6967,6968,6969,6970,6971,6972,6973,
80887 6974,6975,6976,6977,6978,6979,6980,6981,6982,6983,6984,6985,6986,6987,6988,
80888 6989,6990,6991,6992,6993,6994,6995,6996,6997,6998,6999,7000,7001,7002,7003,
80889 7004,7005,7006,7007,7008,7009,7010,7011,7012,7013,7014,7015,7016,7017,7018,
80890 7019,7020,7021,7022,7023,7024,7025,7026,7027,7028,7029,7030,7031,7032,7033,
80891 7034,7035,7036,7037,7038,7039,7040,7041,7042,7043,7044,7045,7046,7047,7048,
80892 7049,7050,7051,7052,7053,7054,7055,7056,7057,7058,7059,7060,7061,7062,7063,
80893 7064,7065,7066,7067,7068,7069,7070,7071,7072,7073,7074,7075,7076,7077,7078,
80894 7079,7080,7081,7082,7083,7084,7085,7086,7087,7088,7089,7090,7091,7092,7093,
80895 7094,7095,7096,7097,7098,7099,7100,7101,7102,7103,7104,7105,7106,7107,7108,
80896 7109,7110,7111,7112,7113,7114,7115,7116,7117,7118,7119,7120,7121,7122,7123,
80897 7124,7125,7126,7127,7128,7129,7130,7131,7132,7133,7134,7135,7136,7137,7138,
80898 7139,7140,7141,7142,7143,7144,7145,7146,7147,7148,7149,7150,7151,7152,7153,
80899 7154,7155,7156,7157,7158,7159,7160,7161,7162,7163,7164,7165,7166,7167,7168,
80900 7169,7170,7171,7172,7173,7174,7175,7176,7177,7178,7179,7180,7181,7182,7183,
80901 7184,7185,7186,7187,7188,7189,7190,7191,7192,7193,7194,7195,7196,7197,7198,
80902 7199,7200,7201,7202,7203,7204,7205,7206,7207,7208,7209,7210,7211,7212,7213,
80903 7214,7215,7216,7217,7218,7219,7220,7221,7222,7223,7224,7225,7226,7227,7228,
80904 7229,7230,7231,7232,7233,7234,7235,7236,7237,7238,7239,7240,7241,7242,7243,
80905 7244,7245,7246,7247,7248,7249,7250,7251,7252,7253,7254,7255,7256,7257,7258,
80906 7259,7260,7261,7262,7263,7264,7265,7266,7267,7268,7269,7270,7271,7272,7273,
80907 7274,7275,7276,7277,7278,7279,7280,7281,7282,7283,7284,7285,7286,7287,7288,
80908 7289,7290,7291,7292,7293,7294,7295,7296,7297,7298,7299,7300,7301,7302,7303,
80909 7304,7305,7306,7307,7308,7309,7310,7311,7312,7313,7314,7315,7316,7317,7318,
80910 7319,7320,7321,7322,7323,7324,7325,7326,7327,7328,7329,7330,7331,7332,7333,
80911 7334,7335,7336,7337,7338,7339,7340,7341,7342,7343,7344,7345,7346,7347,7348,
80912 7349,7350,7351,7352,7353,7354,7355,7356,7357,7358,7359,7360,7361,7362,7363,
80913 7364,7365,7366,7367,7368,7369,7370,7371,7372,7373,7374,7375,7376,7377,7378,
80914 7379,7380,7381,7382,7383,7384,7385,7386,7387,7388,7389,7390,7391,7392,7393,
80915 7394,7395,7396,7397,7398,7399,7400,7401,7402,7403,7404,7405,7406,7407,7408,
80916 7409,7410,7411,7412,7413,7414,7415,7416,7417,7418,7419,7420,7421,7422,7423,
80917 7424,7425,7426,7427,7428,7429,7430,7431,7432,7433,7434,7435,7436,7437,7438,
80918 7439,7440,7441,7442,7443,7444,7445,7446,7447,7448,7449,7450,7451,7452,7453,
80919 7454,7455,7456,7457,7458,7459,7460,7461,7462,7463,7464,7465,7466,7467,7468,
80920 7469,7470,7471,7472,7473,7474,7475,7476,7477,7478,7479,7480,7481,7482,7483,
80921 7484,7485,7486,7487,7488,7489,7490,7491,7492,7493,7494,7495,7496,7497,7498,
80922 7499,7500,7501,7502,7503,7504,7505,7506,7507,7508,7509,7510,7511,7512,7513,
80923 7514,7515,7516,7517,7518,7519,7520,7521,7522,7523,7524,7525,7526,7527,7528,
80924 7529,7530,7531,7532,7533,7534,7535,7536,7537,7538,7539,7540,7541,7542,7543,
80925 7544,42877L,7546,7547,7548,11363,7550,7551,7552,7553,7554,7555,7556,7557,
80926 7558,7559,7560,7561,7562,7563,7564,7565,7566,7567,7568,7569,7570,7571,7572,
80927 7573,7574,7575,7576,7577,7578,7579,7580,7581,7582,7583,7584,7585,7586,7587,
80928 7588,7589,7590,7591,7592,7593,7594,7595,7596,7597,7598,7599,7600,7601,7602,
80929 7603,7604,7605,7606,7607,7608,7609,7610,7611,7612,7613,7614,7615,7616,7617,
80930 7618,7619,7620,7621,7622,7623,7624,7625,7626,7627,7628,7629,7630,7631,7632,
80931 7633,7634,7635,7636,7637,7638,7639,7640,7641,7642,7643,7644,7645,7646,7647,
80932 7648,7649,7650,7651,7652,7653,7654,7655,7656,7657,7658,7659,7660,7661,7662,
80933 7663,7664,7665,7666,7667,7668,7669,7670,7671,7672,7673,7674,7675,7676,7677,
80934 7678,7679,7680,7680,7682,7682,7684,7684,7686,7686,7688,7688,7690,7690,7692,
80935 7692,7694,7694,7696,7696,7698,7698,7700,7700,7702,7702,7704,7704,7706,7706,
80936 7708,7708,7710,7710,7712,7712,7714,7714,7716,7716,7718,7718,7720,7720,7722,
80937 7722,7724,7724,7726,7726,7728,7728,7730,7730,7732,7732,7734,7734,7736,7736,
80938 7738,7738,7740,7740,7742,7742,7744,7744,7746,7746,7748,7748,7750,7750,7752,
80939 7752,7754,7754,7756,7756,7758,7758,7760,7760,7762,7762,7764,7764,7766,7766,
80940 7768,7768,7770,7770,7772,7772,7774,7774,7776,7776,7778,7778,7780,7780,7782,
80941 7782,7784,7784,7786,7786,7788,7788,7790,7790,7792,7792,7794,7794,7796,7796,
80942 7798,7798,7800,7800,7802,7802,7804,7804,7806,7806,7808,7808,7810,7810,7812,
80943 7812,7814,7814,7816,7816,7818,7818,7820,7820,7822,7822,7824,7824,7826,7826,
80944 7828,7828,7830,7831,7832,7833,7834,7776,7836,7837,7838,7839,7840,7840,7842,
80945 7842,7844,7844,7846,7846,7848,7848,7850,7850,7852,7852,7854,7854,7856,7856,
80946 7858,7858,7860,7860,7862,7862,7864,7864,7866,7866,7868,7868,7870,7870,7872,
80947 7872,7874,7874,7876,7876,7878,7878,7880,7880,7882,7882,7884,7884,7886,7886,
80948 7888,7888,7890,7890,7892,7892,7894,7894,7896,7896,7898,7898,7900,7900,7902,
80949 7902,7904,7904,7906,7906,7908,7908,7910,7910,7912,7912,7914,7914,7916,7916,
80950 7918,7918,7920,7920,7922,7922,7924,7924,7926,7926,7928,7928,7930,7930,7932,
80951 7932,7934,7934,7944,7945,7946,7947,7948,7949,7950,7951,7944,7945,7946,7947,
80952 7948,7949,7950,7951,7960,7961,7962,7963,7964,7965,7958,7959,7960,7961,7962,
80953 7963,7964,7965,7966,7967,7976,7977,7978,7979,7980,7981,7982,7983,7976,7977,
80954 7978,7979,7980,7981,7982,7983,7992,7993,7994,7995,7996,7997,7998,7999,7992,
80955 7993,7994,7995,7996,7997,7998,7999,8008,8009,8010,8011,8012,8013,8006,8007,
80956 8008,8009,8010,8011,8012,8013,8014,8015,8016,8025,8018,8027,8020,8029,8022,
80957 8031,8024,8025,8026,8027,8028,8029,8030,8031,8040,8041,8042,8043,8044,8045,
80958 8046,8047,8040,8041,8042,8043,8044,8045,8046,8047,8122,8123,8136,8137,8138,
80959 8139,8154,8155,8184,8185,8170,8171,8186,8187,8062,8063,8064,8065,8066,8067,
80960 8068,8069,8070,8071,8072,8073,8074,8075,8076,8077,8078,8079,8080,8081,8082,
80961 8083,8084,8085,8086,8087,8088,8089,8090,8091,8092,8093,8094,8095,8096,8097,
80962 8098,8099,8100,8101,8102,8103,8104,8105,8106,8107,8108,8109,8110,8111,8120,
80963 8121,8114,8115,8116,8117,8118,8119,8120,8121,8122,8123,8124,8125,921,8127,
80964 8128,8129,8130,8131,8132,8133,8134,8135,8136,8137,8138,8139,8140,8141,8142,
80965 8143,8152,8153,8146,8147,8148,8149,8150,8151,8152,8153,8154,8155,8156,8157,
80966 8158,8159,8168,8169,8162,8163,8164,8172,8166,8167,8168,8169,8170,8171,8172,
80967 8173,8174,8175,8176,8177,8178,8179,8180,8181,8182,8183,8184,8185,8186,8187,
80968 8188,8189,8190,8191,8192,8193,8194,8195,8196,8197,8198,8199,8200,8201,8202,
80969 8203,8204,8205,8206,8207,8208,8209,8210,8211,8212,8213,8214,8215,8216,8217,
80970 8218,8219,8220,8221,8222,8223,8224,8225,8226,8227,8228,8229,8230,8231,8232,
80971 8233,8234,8235,8236,8237,8238,8239,8240,8241,8242,8243,8244,8245,8246,8247,
80972 8248,8249,8250,8251,8252,8253,8254,8255,8256,8257,8258,8259,8260,8261,8262,
80973 8263,8264,8265,8266,8267,8268,8269,8270,8271,8272,8273,8274,8275,8276,8277,
80974 8278,8279,8280,8281,8282,8283,8284,8285,8286,8287,8288,8289,8290,8291,8292,
80975 8293,8294,8295,8296,8297,8298,8299,8300,8301,8302,8303,8304,8305,8306,8307,
80976 8308,8309,8310,8311,8312,8313,8314,8315,8316,8317,8318,8319,8320,8321,8322,
80977 8323,8324,8325,8326,8327,8328,8329,8330,8331,8332,8333,8334,8335,8336,8337,
80978 8338,8339,8340,8341,8342,8343,8344,8345,8346,8347,8348,8349,8350,8351,8352,
80979 8353,8354,8355,8356,8357,8358,8359,8360,8361,8362,8363,8364,8365,8366,8367,
80980 8368,8369,8370,8371,8372,8373,8374,8375,8376,8377,8378,8379,8380,8381,8382,
80981 8383,8384,8385,8386,8387,8388,8389,8390,8391,8392,8393,8394,8395,8396,8397,
80982 8398,8399,8400,8401,8402,8403,8404,8405,8406,8407,8408,8409,8410,8411,8412,
80983 8413,8414,8415,8416,8417,8418,8419,8420,8421,8422,8423,8424,8425,8426,8427,
80984 8428,8429,8430,8431,8432,8433,8434,8435,8436,8437,8438,8439,8440,8441,8442,
80985 8443,8444,8445,8446,8447,8448,8449,8450,8451,8452,8453,8454,8455,8456,8457,
80986 8458,8459,8460,8461,8462,8463,8464,8465,8466,8467,8468,8469,8470,8471,8472,
80987 8473,8474,8475,8476,8477,8478,8479,8480,8481,8482,8483,8484,8485,8486,8487,
80988 8488,8489,8490,8491,8492,8493,8494,8495,8496,8497,8498,8499,8500,8501,8502,
80989 8503,8504,8505,8506,8507,8508,8509,8510,8511,8512,8513,8514,8515,8516,8517,
80990 8518,8519,8520,8521,8522,8523,8524,8525,8498,8527,8528,8529,8530,8531,8532,
80991 8533,8534,8535,8536,8537,8538,8539,8540,8541,8542,8543,8544,8545,8546,8547,
80992 8548,8549,8550,8551,8552,8553,8554,8555,8556,8557,8558,8559,8544,8545,8546,
80993 8547,8548,8549,8550,8551,8552,8553,8554,8555,8556,8557,8558,8559,8576,8577,
80994 8578,8579,8579,8581,8582,8583,8584,8585,8586,8587,8588,8589,8590,8591,8592,
80995 8593,8594,8595,8596,8597,8598,8599,8600,8601,8602,8603,8604,8605,8606,8607,
80996 8608,8609,8610,8611,8612,8613,8614,8615,8616,8617,8618,8619,8620,8621,8622,
80997 8623,8624,8625,8626,8627,8628,8629,8630,8631,8632,8633,8634,8635,8636,8637,
80998 8638,8639,8640,8641,8642,8643,8644,8645,8646,8647,8648,8649,8650,8651,8652,
80999 8653,8654,8655,8656,8657,8658,8659,8660,8661,8662,8663,8664,8665,8666,8667,
81000 8668,8669,8670,8671,8672,8673,8674,8675,8676,8677,8678,8679,8680,8681,8682,
81001 8683,8684,8685,8686,8687,8688,8689,8690,8691,8692,8693,8694,8695,8696,8697,
81002 8698,8699,8700,8701,8702,8703,8704,8705,8706,8707,8708,8709,8710,8711,8712,
81003 8713,8714,8715,8716,8717,8718,8719,8720,8721,8722,8723,8724,8725,8726,8727,
81004 8728,8729,8730,8731,8732,8733,8734,8735,8736,8737,8738,8739,8740,8741,8742,
81005 8743,8744,8745,8746,8747,8748,8749,8750,8751,8752,8753,8754,8755,8756,8757,
81006 8758,8759,8760,8761,8762,8763,8764,8765,8766,8767,8768,8769,8770,8771,8772,
81007 8773,8774,8775,8776,8777,8778,8779,8780,8781,8782,8783,8784,8785,8786,8787,
81008 8788,8789,8790,8791,8792,8793,8794,8795,8796,8797,8798,8799,8800,8801,8802,
81009 8803,8804,8805,8806,8807,8808,8809,8810,8811,8812,8813,8814,8815,8816,8817,
81010 8818,8819,8820,8821,8822,8823,8824,8825,8826,8827,8828,8829,8830,8831,8832,
81011 8833,8834,8835,8836,8837,8838,8839,8840,8841,8842,8843,8844,8845,8846,8847,
81012 8848,8849,8850,8851,8852,8853,8854,8855,8856,8857,8858,8859,8860,8861,8862,
81013 8863,8864,8865,8866,8867,8868,8869,8870,8871,8872,8873,8874,8875,8876,8877,
81014 8878,8879,8880,8881,8882,8883,8884,8885,8886,8887,8888,8889,8890,8891,8892,
81015 8893,8894,8895,8896,8897,8898,8899,8900,8901,8902,8903,8904,8905,8906,8907,
81016 8908,8909,8910,8911,8912,8913,8914,8915,8916,8917,8918,8919,8920,8921,8922,
81017 8923,8924,8925,8926,8927,8928,8929,8930,8931,8932,8933,8934,8935,8936,8937,
81018 8938,8939,8940,8941,8942,8943,8944,8945,8946,8947,8948,8949,8950,8951,8952,
81019 8953,8954,8955,8956,8957,8958,8959,8960,8961,8962,8963,8964,8965,8966,8967,
81020 8968,8969,8970,8971,8972,8973,8974,8975,8976,8977,8978,8979,8980,8981,8982,
81021 8983,8984,8985,8986,8987,8988,8989,8990,8991,8992,8993,8994,8995,8996,8997,
81022 8998,8999,9000,9001,9002,9003,9004,9005,9006,9007,9008,9009,9010,9011,9012,
81023 9013,9014,9015,9016,9017,9018,9019,9020,9021,9022,9023,9024,9025,9026,9027,
81024 9028,9029,9030,9031,9032,9033,9034,9035,9036,9037,9038,9039,9040,9041,9042,
81025 9043,9044,9045,9046,9047,9048,9049,9050,9051,9052,9053,9054,9055,9056,9057,
81026 9058,9059,9060,9061,9062,9063,9064,9065,9066,9067,9068,9069,9070,9071,9072,
81027 9073,9074,9075,9076,9077,9078,9079,9080,9081,9082,9083,9084,9085,9086,9087,
81028 9088,9089,9090,9091,9092,9093,9094,9095,9096,9097,9098,9099,9100,9101,9102,
81029 9103,9104,9105,9106,9107,9108,9109,9110,9111,9112,9113,9114,9115,9116,9117,
81030 9118,9119,9120,9121,9122,9123,9124,9125,9126,9127,9128,9129,9130,9131,9132,
81031 9133,9134,9135,9136,9137,9138,9139,9140,9141,9142,9143,9144,9145,9146,9147,
81032 9148,9149,9150,9151,9152,9153,9154,9155,9156,9157,9158,9159,9160,9161,9162,
81033 9163,9164,9165,9166,9167,9168,9169,9170,9171,9172,9173,9174,9175,9176,9177,
81034 9178,9179,9180,9181,9182,9183,9184,9185,9186,9187,9188,9189,9190,9191,9192,
81035 9193,9194,9195,9196,9197,9198,9199,9200,9201,9202,9203,9204,9205,9206,9207,
81036 9208,9209,9210,9211,9212,9213,9214,9215,9216,9217,9218,9219,9220,9221,9222,
81037 9223,9224,9225,9226,9227,9228,9229,9230,9231,9232,9233,9234,9235,9236,9237,
81038 9238,9239,9240,9241,9242,9243,9244,9245,9246,9247,9248,9249,9250,9251,9252,
81039 9253,9254,9255,9256,9257,9258,9259,9260,9261,9262,9263,9264,9265,9266,9267,
81040 9268,9269,9270,9271,9272,9273,9274,9275,9276,9277,9278,9279,9280,9281,9282,
81041 9283,9284,9285,9286,9287,9288,9289,9290,9291,9292,9293,9294,9295,9296,9297,
81042 9298,9299,9300,9301,9302,9303,9304,9305,9306,9307,9308,9309,9310,9311,9312,
81043 9313,9314,9315,9316,9317,9318,9319,9320,9321,9322,9323,9324,9325,9326,9327,
81044 9328,9329,9330,9331,9332,9333,9334,9335,9336,9337,9338,9339,9340,9341,9342,
81045 9343,9344,9345,9346,9347,9348,9349,9350,9351,9352,9353,9354,9355,9356,9357,
81046 9358,9359,9360,9361,9362,9363,9364,9365,9366,9367,9368,9369,9370,9371,9372,
81047 9373,9374,9375,9376,9377,9378,9379,9380,9381,9382,9383,9384,9385,9386,9387,
81048 9388,9389,9390,9391,9392,9393,9394,9395,9396,9397,9398,9399,9400,9401,9402,
81049 9403,9404,9405,9406,9407,9408,9409,9410,9411,9412,9413,9414,9415,9416,9417,
81050 9418,9419,9420,9421,9422,9423,9398,9399,9400,9401,9402,9403,9404,9405,9406,
81051 9407,9408,9409,9410,9411,9412,9413,9414,9415,9416,9417,9418,9419,9420,9421,
81052 9422,9423,9450,9451,9452,9453,9454,9455,9456,9457,9458,9459,9460,9461,9462,
81053 9463,9464,9465,9466,9467,9468,9469,9470,9471,9472,9473,9474,9475,9476,9477,
81054 9478,9479,9480,9481,9482,9483,9484,9485,9486,9487,9488,9489,9490,9491,9492,
81055 9493,9494,9495,9496,9497,9498,9499,9500,9501,9502,9503,9504,9505,9506,9507,
81056 9508,9509,9510,9511,9512,9513,9514,9515,9516,9517,9518,9519,9520,9521,9522,
81057 9523,9524,9525,9526,9527,9528,9529,9530,9531,9532,9533,9534,9535,9536,9537,
81058 9538,9539,9540,9541,9542,9543,9544,9545,9546,9547,9548,9549,9550,9551,9552,
81059 9553,9554,9555,9556,9557,9558,9559,9560,9561,9562,9563,9564,9565,9566,9567,
81060 9568,9569,9570,9571,9572,9573,9574,9575,9576,9577,9578,9579,9580,9581,9582,
81061 9583,9584,9585,9586,9587,9588,9589,9590,9591,9592,9593,9594,9595,9596,9597,
81062 9598,9599,9600,9601,9602,9603,9604,9605,9606,9607,9608,9609,9610,9611,9612,
81063 9613,9614,9615,9616,9617,9618,9619,9620,9621,9622,9623,9624,9625,9626,9627,
81064 9628,9629,9630,9631,9632,9633,9634,9635,9636,9637,9638,9639,9640,9641,9642,
81065 9643,9644,9645,9646,9647,9648,9649,9650,9651,9652,9653,9654,9655,9656,9657,
81066 9658,9659,9660,9661,9662,9663,9664,9665,9666,9667,9668,9669,9670,9671,9672,
81067 9673,9674,9675,9676,9677,9678,9679,9680,9681,9682,9683,9684,9685,9686,9687,
81068 9688,9689,9690,9691,9692,9693,9694,9695,9696,9697,9698,9699,9700,9701,9702,
81069 9703,9704,9705,9706,9707,9708,9709,9710,9711,9712,9713,9714,9715,9716,9717,
81070 9718,9719,9720,9721,9722,9723,9724,9725,9726,9727,9728,9729,9730,9731,9732,
81071 9733,9734,9735,9736,9737,9738,9739,9740,9741,9742,9743,9744,9745,9746,9747,
81072 9748,9749,9750,9751,9752,9753,9754,9755,9756,9757,9758,9759,9760,9761,9762,
81073 9763,9764,9765,9766,9767,9768,9769,9770,9771,9772,9773,9774,9775,9776,9777,
81074 9778,9779,9780,9781,9782,9783,9784,9785,9786,9787,9788,9789,9790,9791,9792,
81075 9793,9794,9795,9796,9797,9798,9799,9800,9801,9802,9803,9804,9805,9806,9807,
81076 9808,9809,9810,9811,9812,9813,9814,9815,9816,9817,9818,9819,9820,9821,9822,
81077 9823,9824,9825,9826,9827,9828,9829,9830,9831,9832,9833,9834,9835,9836,9837,
81078 9838,9839,9840,9841,9842,9843,9844,9845,9846,9847,9848,9849,9850,9851,9852,
81079 9853,9854,9855,9856,9857,9858,9859,9860,9861,9862,9863,9864,9865,9866,9867,
81080 9868,9869,9870,9871,9872,9873,9874,9875,9876,9877,9878,9879,9880,9881,9882,
81081 9883,9884,9885,9886,9887,9888,9889,9890,9891,9892,9893,9894,9895,9896,9897,
81082 9898,9899,9900,9901,9902,9903,9904,9905,9906,9907,9908,9909,9910,9911,9912,
81083 9913,9914,9915,9916,9917,9918,9919,9920,9921,9922,9923,9924,9925,9926,9927,
81084 9928,9929,9930,9931,9932,9933,9934,9935,9936,9937,9938,9939,9940,9941,9942,
81085 9943,9944,9945,9946,9947,9948,9949,9950,9951,9952,9953,9954,9955,9956,9957,
81086 9958,9959,9960,9961,9962,9963,9964,9965,9966,9967,9968,9969,9970,9971,9972,
81087 9973,9974,9975,9976,9977,9978,9979,9980,9981,9982,9983,9984,9985,9986,9987,
81088 9988,9989,9990,9991,9992,9993,9994,9995,9996,9997,9998,9999,10000,10001,
81089 10002,10003,10004,10005,10006,10007,10008,10009,10010,10011,10012,10013,
81090 10014,10015,10016,10017,10018,10019,10020,10021,10022,10023,10024,10025,
81091 10026,10027,10028,10029,10030,10031,10032,10033,10034,10035,10036,10037,
81092 10038,10039,10040,10041,10042,10043,10044,10045,10046,10047,10048,10049,
81093 10050,10051,10052,10053,10054,10055,10056,10057,10058,10059,10060,10061,
81094 10062,10063,10064,10065,10066,10067,10068,10069,10070,10071,10072,10073,
81095 10074,10075,10076,10077,10078,10079,10080,10081,10082,10083,10084,10085,
81096 10086,10087,10088,10089,10090,10091,10092,10093,10094,10095,10096,10097,
81097 10098,10099,10100,10101,10102,10103,10104,10105,10106,10107,10108,10109,
81098 10110,10111,10112,10113,10114,10115,10116,10117,10118,10119,10120,10121,
81099 10122,10123,10124,10125,10126,10127,10128,10129,10130,10131,10132,10133,
81100 10134,10135,10136,10137,10138,10139,10140,10141,10142,10143,10144,10145,
81101 10146,10147,10148,10149,10150,10151,10152,10153,10154,10155,10156,10157,
81102 10158,10159,10160,10161,10162,10163,10164,10165,10166,10167,10168,10169,
81103 10170,10171,10172,10173,10174,10175,10176,10177,10178,10179,10180,10181,
81104 10182,10183,10184,10185,10186,10187,10188,10189,10190,10191,10192,10193,
81105 10194,10195,10196,10197,10198,10199,10200,10201,10202,10203,10204,10205,
81106 10206,10207,10208,10209,10210,10211,10212,10213,10214,10215,10216,10217,
81107 10218,10219,10220,10221,10222,10223,10224,10225,10226,10227,10228,10229,
81108 10230,10231,10232,10233,10234,10235,10236,10237,10238,10239,10240,10241,
81109 10242,10243,10244,10245,10246,10247,10248,10249,10250,10251,10252,10253,
81110 10254,10255,10256,10257,10258,10259,10260,10261,10262,10263,10264,10265,
81111 10266,10267,10268,10269,10270,10271,10272,10273,10274,10275,10276,10277,
81112 10278,10279,10280,10281,10282,10283,10284,10285,10286,10287,10288,10289,
81113 10290,10291,10292,10293,10294,10295,10296,10297,10298,10299,10300,10301,
81114 10302,10303,10304,10305,10306,10307,10308,10309,10310,10311,10312,10313,
81115 10314,10315,10316,10317,10318,10319,10320,10321,10322,10323,10324,10325,
81116 10326,10327,10328,10329,10330,10331,10332,10333,10334,10335,10336,10337,
81117 10338,10339,10340,10341,10342,10343,10344,10345,10346,10347,10348,10349,
81118 10350,10351,10352,10353,10354,10355,10356,10357,10358,10359,10360,10361,
81119 10362,10363,10364,10365,10366,10367,10368,10369,10370,10371,10372,10373,
81120 10374,10375,10376,10377,10378,10379,10380,10381,10382,10383,10384,10385,
81121 10386,10387,10388,10389,10390,10391,10392,10393,10394,10395,10396,10397,
81122 10398,10399,10400,10401,10402,10403,10404,10405,10406,10407,10408,10409,
81123 10410,10411,10412,10413,10414,10415,10416,10417,10418,10419,10420,10421,
81124 10422,10423,10424,10425,10426,10427,10428,10429,10430,10431,10432,10433,
81125 10434,10435,10436,10437,10438,10439,10440,10441,10442,10443,10444,10445,
81126 10446,10447,10448,10449,10450,10451,10452,10453,10454,10455,10456,10457,
81127 10458,10459,10460,10461,10462,10463,10464,10465,10466,10467,10468,10469,
81128 10470,10471,10472,10473,10474,10475,10476,10477,10478,10479,10480,10481,
81129 10482,10483,10484,10485,10486,10487,10488,10489,10490,10491,10492,10493,
81130 10494,10495,10496,10497,10498,10499,10500,10501,10502,10503,10504,10505,
81131 10506,10507,10508,10509,10510,10511,10512,10513,10514,10515,10516,10517,
81132 10518,10519,10520,10521,10522,10523,10524,10525,10526,10527,10528,10529,
81133 10530,10531,10532,10533,10534,10535,10536,10537,10538,10539,10540,10541,
81134 10542,10543,10544,10545,10546,10547,10548,10549,10550,10551,10552,10553,
81135 10554,10555,10556,10557,10558,10559,10560,10561,10562,10563,10564,10565,
81136 10566,10567,10568,10569,10570,10571,10572,10573,10574,10575,10576,10577,
81137 10578,10579,10580,10581,10582,10583,10584,10585,10586,10587,10588,10589,
81138 10590,10591,10592,10593,10594,10595,10596,10597,10598,10599,10600,10601,
81139 10602,10603,10604,10605,10606,10607,10608,10609,10610,10611,10612,10613,
81140 10614,10615,10616,10617,10618,10619,10620,10621,10622,10623,10624,10625,
81141 10626,10627,10628,10629,10630,10631,10632,10633,10634,10635,10636,10637,
81142 10638,10639,10640,10641,10642,10643,10644,10645,10646,10647,10648,10649,
81143 10650,10651,10652,10653,10654,10655,10656,10657,10658,10659,10660,10661,
81144 10662,10663,10664,10665,10666,10667,10668,10669,10670,10671,10672,10673,
81145 10674,10675,10676,10677,10678,10679,10680,10681,10682,10683,10684,10685,
81146 10686,10687,10688,10689,10690,10691,10692,10693,10694,10695,10696,10697,
81147 10698,10699,10700,10701,10702,10703,10704,10705,10706,10707,10708,10709,
81148 10710,10711,10712,10713,10714,10715,10716,10717,10718,10719,10720,10721,
81149 10722,10723,10724,10725,10726,10727,10728,10729,10730,10731,10732,10733,
81150 10734,10735,10736,10737,10738,10739,10740,10741,10742,10743,10744,10745,
81151 10746,10747,10748,10749,10750,10751,10752,10753,10754,10755,10756,10757,
81152 10758,10759,10760,10761,10762,10763,10764,10765,10766,10767,10768,10769,
81153 10770,10771,10772,10773,10774,10775,10776,10777,10778,10779,10780,10781,
81154 10782,10783,10784,10785,10786,10787,10788,10789,10790,10791,10792,10793,
81155 10794,10795,10796,10797,10798,10799,10800,10801,10802,10803,10804,10805,
81156 10806,10807,10808,10809,10810,10811,10812,10813,10814,10815,10816,10817,
81157 10818,10819,10820,10821,10822,10823,10824,10825,10826,10827,10828,10829,
81158 10830,10831,10832,10833,10834,10835,10836,10837,10838,10839,10840,10841,
81159 10842,10843,10844,10845,10846,10847,10848,10849,10850,10851,10852,10853,
81160 10854,10855,10856,10857,10858,10859,10860,10861,10862,10863,10864,10865,
81161 10866,10867,10868,10869,10870,10871,10872,10873,10874,10875,10876,10877,
81162 10878,10879,10880,10881,10882,10883,10884,10885,10886,10887,10888,10889,
81163 10890,10891,10892,10893,10894,10895,10896,10897,10898,10899,10900,10901,
81164 10902,10903,10904,10905,10906,10907,10908,10909,10910,10911,10912,10913,
81165 10914,10915,10916,10917,10918,10919,10920,10921,10922,10923,10924,10925,
81166 10926,10927,10928,10929,10930,10931,10932,10933,10934,10935,10936,10937,
81167 10938,10939,10940,10941,10942,10943,10944,10945,10946,10947,10948,10949,
81168 10950,10951,10952,10953,10954,10955,10956,10957,10958,10959,10960,10961,
81169 10962,10963,10964,10965,10966,10967,10968,10969,10970,10971,10972,10973,
81170 10974,10975,10976,10977,10978,10979,10980,10981,10982,10983,10984,10985,
81171 10986,10987,10988,10989,10990,10991,10992,10993,10994,10995,10996,10997,
81172 10998,10999,11000,11001,11002,11003,11004,11005,11006,11007,11008,11009,
81173 11010,11011,11012,11013,11014,11015,11016,11017,11018,11019,11020,11021,
81174 11022,11023,11024,11025,11026,11027,11028,11029,11030,11031,11032,11033,
81175 11034,11035,11036,11037,11038,11039,11040,11041,11042,11043,11044,11045,
81176 11046,11047,11048,11049,11050,11051,11052,11053,11054,11055,11056,11057,
81177 11058,11059,11060,11061,11062,11063,11064,11065,11066,11067,11068,11069,
81178 11070,11071,11072,11073,11074,11075,11076,11077,11078,11079,11080,11081,
81179 11082,11083,11084,11085,11086,11087,11088,11089,11090,11091,11092,11093,
81180 11094,11095,11096,11097,11098,11099,11100,11101,11102,11103,11104,11105,
81181 11106,11107,11108,11109,11110,11111,11112,11113,11114,11115,11116,11117,
81182 11118,11119,11120,11121,11122,11123,11124,11125,11126,11127,11128,11129,
81183 11130,11131,11132,11133,11134,11135,11136,11137,11138,11139,11140,11141,
81184 11142,11143,11144,11145,11146,11147,11148,11149,11150,11151,11152,11153,
81185 11154,11155,11156,11157,11158,11159,11160,11161,11162,11163,11164,11165,
81186 11166,11167,11168,11169,11170,11171,11172,11173,11174,11175,11176,11177,
81187 11178,11179,11180,11181,11182,11183,11184,11185,11186,11187,11188,11189,
81188 11190,11191,11192,11193,11194,11195,11196,11197,11198,11199,11200,11201,
81189 11202,11203,11204,11205,11206,11207,11208,11209,11210,11211,11212,11213,
81190 11214,11215,11216,11217,11218,11219,11220,11221,11222,11223,11224,11225,
81191 11226,11227,11228,11229,11230,11231,11232,11233,11234,11235,11236,11237,
81192 11238,11239,11240,11241,11242,11243,11244,11245,11246,11247,11248,11249,
81193 11250,11251,11252,11253,11254,11255,11256,11257,11258,11259,11260,11261,
81194 11262,11263,11264,11265,11266,11267,11268,11269,11270,11271,11272,11273,
81195 11274,11275,11276,11277,11278,11279,11280,11281,11282,11283,11284,11285,
81196 11286,11287,11288,11289,11290,11291,11292,11293,11294,11295,11296,11297,
81197 11298,11299,11300,11301,11302,11303,11304,11305,11306,11307,11308,11309,
81198 11310,11311,11264,11265,11266,11267,11268,11269,11270,11271,11272,11273,
81199 11274,11275,11276,11277,11278,11279,11280,11281,11282,11283,11284,11285,
81200 11286,11287,11288,11289,11290,11291,11292,11293,11294,11295,11296,11297,
81201 11298,11299,11300,11301,11302,11303,11304,11305,11306,11307,11308,11309,
81202 11310,11359,11360,11360,11362,11363,11364,570,574,11367,11367,11369,11369,
81203 11371,11371,11373,11374,11375,11376,11377,11378,11378,11380,11381,11381,
81204 11383,11384,11385,11386,11387,11388,11389,11390,11391,11392,11392,11394,
81205 11394,11396,11396,11398,11398,11400,11400,11402,11402,11404,11404,11406,
81206 11406,11408,11408,11410,11410,11412,11412,11414,11414,11416,11416,11418,
81207 11418,11420,11420,11422,11422,11424,11424,11426,11426,11428,11428,11430,
81208 11430,11432,11432,11434,11434,11436,11436,11438,11438,11440,11440,11442,
81209 11442,11444,11444,11446,11446,11448,11448,11450,11450,11452,11452,11454,
81210 11454,11456,11456,11458,11458,11460,11460,11462,11462,11464,11464,11466,
81211 11466,11468,11468,11470,11470,11472,11472,11474,11474,11476,11476,11478,
81212 11478,11480,11480,11482,11482,11484,11484,11486,11486,11488,11488,11490,
81213 11490,11492,11493,11494,11495,11496,11497,11498,11499,11499,11501,11501,
81214 11503,11504,11505,11506,11507,11508,11509,11510,11511,11512,11513,11514,
81215 11515,11516,11517,11518,11519,4256,4257,4258,4259,4260,4261,4262,4263,4264,
81216 4265,4266,4267,4268,4269,4270,4271,4272,4273,4274,4275,4276,4277,4278,4279,
81217 4280,4281,4282,4283,4284,4285,4286,4287,4288,4289,4290,4291,4292,4293,
81218 11558,11559,11560,11561,11562,11563,11564,11565,11566,11567,11568,11569,
81219 11570,11571,11572,11573,11574,11575,11576,11577,11578,11579,11580,11581,
81220 11582,11583,11584,11585,11586,11587,11588,11589,11590,11591,11592,11593,
81221 11594,11595,11596,11597,11598,11599,11600,11601,11602,11603,11604,11605,
81222 11606,11607,11608,11609,11610,11611,11612,11613,11614,11615,11616,11617,
81223 11618,11619,11620,11621,11622,11623,11624,11625,11626,11627,11628,11629,
81224 11630,11631,11632,11633,11634,11635,11636,11637,11638,11639,11640,11641,
81225 11642,11643,11644,11645,11646,11647,11648,11649,11650,11651,11652,11653,
81226 11654,11655,11656,11657,11658,11659,11660,11661,11662,11663,11664,11665,
81227 11666,11667,11668,11669,11670,11671,11672,11673,11674,11675,11676,11677,
81228 11678,11679,11680,11681,11682,11683,11684,11685,11686,11687,11688,11689,
81229 11690,11691,11692,11693,11694,11695,11696,11697,11698,11699,11700,11701,
81230 11702,11703,11704,11705,11706,11707,11708,11709,11710,11711,11712,11713,
81231 11714,11715,11716,11717,11718,11719,11720,11721,11722,11723,11724,11725,
81232 11726,11727,11728,11729,11730,11731,11732,11733,11734,11735,11736,11737,
81233 11738,11739,11740,11741,11742,11743,11744,11745,11746,11747,11748,11749,
81234 11750,11751,11752,11753,11754,11755,11756,11757,11758,11759,11760,11761,
81235 11762,11763,11764,11765,11766,11767,11768,11769,11770,11771,11772,11773,
81236 11774,11775,11776,11777,11778,11779,11780,11781,11782,11783,11784,11785,
81237 11786,11787,11788,11789,11790,11791,11792,11793,11794,11795,11796,11797,
81238 11798,11799,11800,11801,11802,11803,11804,11805,11806,11807,11808,11809,
81239 11810,11811,11812,11813,11814,11815,11816,11817,11818,11819,11820,11821,
81240 11822,11823,11824,11825,11826,11827,11828,11829,11830,11831,11832,11833,
81241 11834,11835,11836,11837,11838,11839,11840,11841,11842,11843,11844,11845,
81242 11846,11847,11848,11849,11850,11851,11852,11853,11854,11855,11856,11857,
81243 11858,11859,11860,11861,11862,11863,11864,11865,11866,11867,11868,11869,
81244 11870,11871,11872,11873,11874,11875,11876,11877,11878,11879,11880,11881,
81245 11882,11883,11884,11885,11886,11887,11888,11889,11890,11891,11892,11893,
81246 11894,11895,11896,11897,11898,11899,11900,11901,11902,11903,11904,11905,
81247 11906,11907,11908,11909,11910,11911,11912,11913,11914,11915,11916,11917,
81248 11918,11919,11920,11921,11922,11923,11924,11925,11926,11927,11928,11929,
81249 11930,11931,11932,11933,11934,11935,11936,11937,11938,11939,11940,11941,
81250 11942,11943,11944,11945,11946,11947,11948,11949,11950,11951,11952,11953,
81251 11954,11955,11956,11957,11958,11959,11960,11961,11962,11963,11964,11965,
81252 11966,11967,11968,11969,11970,11971,11972,11973,11974,11975,11976,11977,
81253 11978,11979,11980,11981,11982,11983,11984,11985,11986,11987,11988,11989,
81254 11990,11991,11992,11993,11994,11995,11996,11997,11998,11999,12000,12001,
81255 12002,12003,12004,12005,12006,12007,12008,12009,12010,12011,12012,12013,
81256 12014,12015,12016,12017,12018,12019,12020,12021,12022,12023,12024,12025,
81257 12026,12027,12028,12029,12030,12031,12032,12033,12034,12035,12036,12037,
81258 12038,12039,12040,12041,12042,12043,12044,12045,12046,12047,12048,12049,
81259 12050,12051,12052,12053,12054,12055,12056,12057,12058,12059,12060,12061,
81260 12062,12063,12064,12065,12066,12067,12068,12069,12070,12071,12072,12073,
81261 12074,12075,12076,12077,12078,12079,12080,12081,12082,12083,12084,12085,
81262 12086,12087,12088,12089,12090,12091,12092,12093,12094,12095,12096,12097,
81263 12098,12099,12100,12101,12102,12103,12104,12105,12106,12107,12108,12109,
81264 12110,12111,12112,12113,12114,12115,12116,12117,12118,12119,12120,12121,
81265 12122,12123,12124,12125,12126,12127,12128,12129,12130,12131,12132,12133,
81266 12134,12135,12136,12137,12138,12139,12140,12141,12142,12143,12144,12145,
81267 12146,12147,12148,12149,12150,12151,12152,12153,12154,12155,12156,12157,
81268 12158,12159,12160,12161,12162,12163,12164,12165,12166,12167,12168,12169,
81269 12170,12171,12172,12173,12174,12175,12176,12177,12178,12179,12180,12181,
81270 12182,12183,12184,12185,12186,12187,12188,12189,12190,12191,12192,12193,
81271 12194,12195,12196,12197,12198,12199,12200,12201,12202,12203,12204,12205,
81272 12206,12207,12208,12209,12210,12211,12212,12213,12214,12215,12216,12217,
81273 12218,12219,12220,12221,12222,12223,12224,12225,12226,12227,12228,12229,
81274 12230,12231,12232,12233,12234,12235,12236,12237,12238,12239,12240,12241,
81275 12242,12243,12244,12245,12246,12247,12248,12249,12250,12251,12252,12253,
81276 12254,12255,12256,12257,12258,12259,12260,12261,12262,12263,12264,12265,
81277 12266,12267,12268,12269,12270,12271,12272,12273,12274,12275,12276,12277,
81278 12278,12279,12280,12281,12282,12283,12284,12285,12286,12287,12288,12289,
81279 12290,12291,12292,12293,12294,12295,12296,12297,12298,12299,12300,12301,
81280 12302,12303,12304,12305,12306,12307,12308,12309,12310,12311,12312,12313,
81281 12314,12315,12316,12317,12318,12319,12320,12321,12322,12323,12324,12325,
81282 12326,12327,12328,12329,12330,12331,12332,12333,12334,12335,12336,12337,
81283 12338,12339,12340,12341,12342,12343,12344,12345,12346,12347,12348,12349,
81284 12350,12351,12352,12353,12354,12355,12356,12357,12358,12359,12360,12361,
81285 12362,12363,12364,12365,12366,12367,12368,12369,12370,12371,12372,12373,
81286 12374,12375,12376,12377,12378,12379,12380,12381,12382,12383,12384,12385,
81287 12386,12387,12388,12389,12390,12391,12392,12393,12394,12395,12396,12397,
81288 12398,12399,12400,12401,12402,12403,12404,12405,12406,12407,12408,12409,
81289 12410,12411,12412,12413,12414,12415,12416,12417,12418,12419,12420,12421,
81290 12422,12423,12424,12425,12426,12427,12428,12429,12430,12431,12432,12433,
81291 12434,12435,12436,12437,12438,12439,12440,12441,12442,12443,12444,12445,
81292 12446,12447,12448,12449,12450,12451,12452,12453,12454,12455,12456,12457,
81293 12458,12459,12460,12461,12462,12463,12464,12465,12466,12467,12468,12469,
81294 12470,12471,12472,12473,12474,12475,12476,12477,12478,12479,12480,12481,
81295 12482,12483,12484,12485,12486,12487,12488,12489,12490,12491,12492,12493,
81296 12494,12495,12496,12497,12498,12499,12500,12501,12502,12503,12504,12505,
81297 12506,12507,12508,12509,12510,12511,12512,12513,12514,12515,12516,12517,
81298 12518,12519,12520,12521,12522,12523,12524,12525,12526,12527,12528,12529,
81299 12530,12531,12532,12533,12534,12535,12536,12537,12538,12539,12540,12541,
81300 12542,12543,12544,12545,12546,12547,12548,12549,12550,12551,12552,12553,
81301 12554,12555,12556,12557,12558,12559,12560,12561,12562,12563,12564,12565,
81302 12566,12567,12568,12569,12570,12571,12572,12573,12574,12575,12576,12577,
81303 12578,12579,12580,12581,12582,12583,12584,12585,12586,12587,12588,12589,
81304 12590,12591,12592,12593,12594,12595,12596,12597,12598,12599,12600,12601,
81305 12602,12603,12604,12605,12606,12607,12608,12609,12610,12611,12612,12613,
81306 12614,12615,12616,12617,12618,12619,12620,12621,12622,12623,12624,12625,
81307 12626,12627,12628,12629,12630,12631,12632,12633,12634,12635,12636,12637,
81308 12638,12639,12640,12641,12642,12643,12644,12645,12646,12647,12648,12649,
81309 12650,12651,12652,12653,12654,12655,12656,12657,12658,12659,12660,12661,
81310 12662,12663,12664,12665,12666,12667,12668,12669,12670,12671,12672,12673,
81311 12674,12675,12676,12677,12678,12679,12680,12681,12682,12683,12684,12685,
81312 12686,12687,12688,12689,12690,12691,12692,12693,12694,12695,12696,12697,
81313 12698,12699,12700,12701,12702,12703,12704,12705,12706,12707,12708,12709,
81314 12710,12711,12712,12713,12714,12715,12716,12717,12718,12719,12720,12721,
81315 12722,12723,12724,12725,12726,12727,12728,12729,12730,12731,12732,12733,
81316 12734,12735,12736,12737,12738,12739,12740,12741,12742,12743,12744,12745,
81317 12746,12747,12748,12749,12750,12751,12752,12753,12754,12755,12756,12757,
81318 12758,12759,12760,12761,12762,12763,12764,12765,12766,12767,12768,12769,
81319 12770,12771,12772,12773,12774,12775,12776,12777,12778,12779,12780,12781,
81320 12782,12783,12784,12785,12786,12787,12788,12789,12790,12791,12792,12793,
81321 12794,12795,12796,12797,12798,12799,12800,12801,12802,12803,12804,12805,
81322 12806,12807,12808,12809,12810,12811,12812,12813,12814,12815,12816,12817,
81323 12818,12819,12820,12821,12822,12823,12824,12825,12826,12827,12828,12829,
81324 12830,12831,12832,12833,12834,12835,12836,12837,12838,12839,12840,12841,
81325 12842,12843,12844,12845,12846,12847,12848,12849,12850,12851,12852,12853,
81326 12854,12855,12856,12857,12858,12859,12860,12861,12862,12863,12864,12865,
81327 12866,12867,12868,12869,12870,12871,12872,12873,12874,12875,12876,12877,
81328 12878,12879,12880,12881,12882,12883,12884,12885,12886,12887,12888,12889,
81329 12890,12891,12892,12893,12894,12895,12896,12897,12898,12899,12900,12901,
81330 12902,12903,12904,12905,12906,12907,12908,12909,12910,12911,12912,12913,
81331 12914,12915,12916,12917,12918,12919,12920,12921,12922,12923,12924,12925,
81332 12926,12927,12928,12929,12930,12931,12932,12933,12934,12935,12936,12937,
81333 12938,12939,12940,12941,12942,12943,12944,12945,12946,12947,12948,12949,
81334 12950,12951,12952,12953,12954,12955,12956,12957,12958,12959,12960,12961,
81335 12962,12963,12964,12965,12966,12967,12968,12969,12970,12971,12972,12973,
81336 12974,12975,12976,12977,12978,12979,12980,12981,12982,12983,12984,12985,
81337 12986,12987,12988,12989,12990,12991,12992,12993,12994,12995,12996,12997,
81338 12998,12999,13000,13001,13002,13003,13004,13005,13006,13007,13008,13009,
81339 13010,13011,13012,13013,13014,13015,13016,13017,13018,13019,13020,13021,
81340 13022,13023,13024,13025,13026,13027,13028,13029,13030,13031,13032,13033,
81341 13034,13035,13036,13037,13038,13039,13040,13041,13042,13043,13044,13045,
81342 13046,13047,13048,13049,13050,13051,13052,13053,13054,13055,13056,13057,
81343 13058,13059,13060,13061,13062,13063,13064,13065,13066,13067,13068,13069,
81344 13070,13071,13072,13073,13074,13075,13076,13077,13078,13079,13080,13081,
81345 13082,13083,13084,13085,13086,13087,13088,13089,13090,13091,13092,13093,
81346 13094,13095,13096,13097,13098,13099,13100,13101,13102,13103,13104,13105,
81347 13106,13107,13108,13109,13110,13111,13112,13113,13114,13115,13116,13117,
81348 13118,13119,13120,13121,13122,13123,13124,13125,13126,13127,13128,13129,
81349 13130,13131,13132,13133,13134,13135,13136,13137,13138,13139,13140,13141,
81350 13142,13143,13144,13145,13146,13147,13148,13149,13150,13151,13152,13153,
81351 13154,13155,13156,13157,13158,13159,13160,13161,13162,13163,13164,13165,
81352 13166,13167,13168,13169,13170,13171,13172,13173,13174,13175,13176,13177,
81353 13178,13179,13180,13181,13182,13183,13184,13185,13186,13187,13188,13189,
81354 13190,13191,13192,13193,13194,13195,13196,13197,13198,13199,13200,13201,
81355 13202,13203,13204,13205,13206,13207,13208,13209,13210,13211,13212,13213,
81356 13214,13215,13216,13217,13218,13219,13220,13221,13222,13223,13224,13225,
81357 13226,13227,13228,13229,13230,13231,13232,13233,13234,13235,13236,13237,
81358 13238,13239,13240,13241,13242,13243,13244,13245,13246,13247,13248,13249,
81359 13250,13251,13252,13253,13254,13255,13256,13257,13258,13259,13260,13261,
81360 13262,13263,13264,13265,13266,13267,13268,13269,13270,13271,13272,13273,
81361 13274,13275,13276,13277,13278,13279,13280,13281,13282,13283,13284,13285,
81362 13286,13287,13288,13289,13290,13291,13292,13293,13294,13295,13296,13297,
81363 13298,13299,13300,13301,13302,13303,13304,13305,13306,13307,13308,13309,
81364 13310,13311,13312,13313,13314,13315,13316,13317,13318,13319,13320,13321,
81365 13322,13323,13324,13325,13326,13327,13328,13329,13330,13331,13332,13333,
81366 13334,13335,13336,13337,13338,13339,13340,13341,13342,13343,13344,13345,
81367 13346,13347,13348,13349,13350,13351,13352,13353,13354,13355,13356,13357,
81368 13358,13359,13360,13361,13362,13363,13364,13365,13366,13367,13368,13369,
81369 13370,13371,13372,13373,13374,13375,13376,13377,13378,13379,13380,13381,
81370 13382,13383,13384,13385,13386,13387,13388,13389,13390,13391,13392,13393,
81371 13394,13395,13396,13397,13398,13399,13400,13401,13402,13403,13404,13405,
81372 13406,13407,13408,13409,13410,13411,13412,13413,13414,13415,13416,13417,
81373 13418,13419,13420,13421,13422,13423,13424,13425,13426,13427,13428,13429,
81374 13430,13431,13432,13433,13434,13435,13436,13437,13438,13439,13440,13441,
81375 13442,13443,13444,13445,13446,13447,13448,13449,13450,13451,13452,13453,
81376 13454,13455,13456,13457,13458,13459,13460,13461,13462,13463,13464,13465,
81377 13466,13467,13468,13469,13470,13471,13472,13473,13474,13475,13476,13477,
81378 13478,13479,13480,13481,13482,13483,13484,13485,13486,13487,13488,13489,
81379 13490,13491,13492,13493,13494,13495,13496,13497,13498,13499,13500,13501,
81380 13502,13503,13504,13505,13506,13507,13508,13509,13510,13511,13512,13513,
81381 13514,13515,13516,13517,13518,13519,13520,13521,13522,13523,13524,13525,
81382 13526,13527,13528,13529,13530,13531,13532,13533,13534,13535,13536,13537,
81383 13538,13539,13540,13541,13542,13543,13544,13545,13546,13547,13548,13549,
81384 13550,13551,13552,13553,13554,13555,13556,13557,13558,13559,13560,13561,
81385 13562,13563,13564,13565,13566,13567,13568,13569,13570,13571,13572,13573,
81386 13574,13575,13576,13577,13578,13579,13580,13581,13582,13583,13584,13585,
81387 13586,13587,13588,13589,13590,13591,13592,13593,13594,13595,13596,13597,
81388 13598,13599,13600,13601,13602,13603,13604,13605,13606,13607,13608,13609,
81389 13610,13611,13612,13613,13614,13615,13616,13617,13618,13619,13620,13621,
81390 13622,13623,13624,13625,13626,13627,13628,13629,13630,13631,13632,13633,
81391 13634,13635,13636,13637,13638,13639,13640,13641,13642,13643,13644,13645,
81392 13646,13647,13648,13649,13650,13651,13652,13653,13654,13655,13656,13657,
81393 13658,13659,13660,13661,13662,13663,13664,13665,13666,13667,13668,13669,
81394 13670,13671,13672,13673,13674,13675,13676,13677,13678,13679,13680,13681,
81395 13682,13683,13684,13685,13686,13687,13688,13689,13690,13691,13692,13693,
81396 13694,13695,13696,13697,13698,13699,13700,13701,13702,13703,13704,13705,
81397 13706,13707,13708,13709,13710,13711,13712,13713,13714,13715,13716,13717,
81398 13718,13719,13720,13721,13722,13723,13724,13725,13726,13727,13728,13729,
81399 13730,13731,13732,13733,13734,13735,13736,13737,13738,13739,13740,13741,
81400 13742,13743,13744,13745,13746,13747,13748,13749,13750,13751,13752,13753,
81401 13754,13755,13756,13757,13758,13759,13760,13761,13762,13763,13764,13765,
81402 13766,13767,13768,13769,13770,13771,13772,13773,13774,13775,13776,13777,
81403 13778,13779,13780,13781,13782,13783,13784,13785,13786,13787,13788,13789,
81404 13790,13791,13792,13793,13794,13795,13796,13797,13798,13799,13800,13801,
81405 13802,13803,13804,13805,13806,13807,13808,13809,13810,13811,13812,13813,
81406 13814,13815,13816,13817,13818,13819,13820,13821,13822,13823,13824,13825,
81407 13826,13827,13828,13829,13830,13831,13832,13833,13834,13835,13836,13837,
81408 13838,13839,13840,13841,13842,13843,13844,13845,13846,13847,13848,13849,
81409 13850,13851,13852,13853,13854,13855,13856,13857,13858,13859,13860,13861,
81410 13862,13863,13864,13865,13866,13867,13868,13869,13870,13871,13872,13873,
81411 13874,13875,13876,13877,13878,13879,13880,13881,13882,13883,13884,13885,
81412 13886,13887,13888,13889,13890,13891,13892,13893,13894,13895,13896,13897,
81413 13898,13899,13900,13901,13902,13903,13904,13905,13906,13907,13908,13909,
81414 13910,13911,13912,13913,13914,13915,13916,13917,13918,13919,13920,13921,
81415 13922,13923,13924,13925,13926,13927,13928,13929,13930,13931,13932,13933,
81416 13934,13935,13936,13937,13938,13939,13940,13941,13942,13943,13944,13945,
81417 13946,13947,13948,13949,13950,13951,13952,13953,13954,13955,13956,13957,
81418 13958,13959,13960,13961,13962,13963,13964,13965,13966,13967,13968,13969,
81419 13970,13971,13972,13973,13974,13975,13976,13977,13978,13979,13980,13981,
81420 13982,13983,13984,13985,13986,13987,13988,13989,13990,13991,13992,13993,
81421 13994,13995,13996,13997,13998,13999,14000,14001,14002,14003,14004,14005,
81422 14006,14007,14008,14009,14010,14011,14012,14013,14014,14015,14016,14017,
81423 14018,14019,14020,14021,14022,14023,14024,14025,14026,14027,14028,14029,
81424 14030,14031,14032,14033,14034,14035,14036,14037,14038,14039,14040,14041,
81425 14042,14043,14044,14045,14046,14047,14048,14049,14050,14051,14052,14053,
81426 14054,14055,14056,14057,14058,14059,14060,14061,14062,14063,14064,14065,
81427 14066,14067,14068,14069,14070,14071,14072,14073,14074,14075,14076,14077,
81428 14078,14079,14080,14081,14082,14083,14084,14085,14086,14087,14088,14089,
81429 14090,14091,14092,14093,14094,14095,14096,14097,14098,14099,14100,14101,
81430 14102,14103,14104,14105,14106,14107,14108,14109,14110,14111,14112,14113,
81431 14114,14115,14116,14117,14118,14119,14120,14121,14122,14123,14124,14125,
81432 14126,14127,14128,14129,14130,14131,14132,14133,14134,14135,14136,14137,
81433 14138,14139,14140,14141,14142,14143,14144,14145,14146,14147,14148,14149,
81434 14150,14151,14152,14153,14154,14155,14156,14157,14158,14159,14160,14161,
81435 14162,14163,14164,14165,14166,14167,14168,14169,14170,14171,14172,14173,
81436 14174,14175,14176,14177,14178,14179,14180,14181,14182,14183,14184,14185,
81437 14186,14187,14188,14189,14190,14191,14192,14193,14194,14195,14196,14197,
81438 14198,14199,14200,14201,14202,14203,14204,14205,14206,14207,14208,14209,
81439 14210,14211,14212,14213,14214,14215,14216,14217,14218,14219,14220,14221,
81440 14222,14223,14224,14225,14226,14227,14228,14229,14230,14231,14232,14233,
81441 14234,14235,14236,14237,14238,14239,14240,14241,14242,14243,14244,14245,
81442 14246,14247,14248,14249,14250,14251,14252,14253,14254,14255,14256,14257,
81443 14258,14259,14260,14261,14262,14263,14264,14265,14266,14267,14268,14269,
81444 14270,14271,14272,14273,14274,14275,14276,14277,14278,14279,14280,14281,
81445 14282,14283,14284,14285,14286,14287,14288,14289,14290,14291,14292,14293,
81446 14294,14295,14296,14297,14298,14299,14300,14301,14302,14303,14304,14305,
81447 14306,14307,14308,14309,14310,14311,14312,14313,14314,14315,14316,14317,
81448 14318,14319,14320,14321,14322,14323,14324,14325,14326,14327,14328,14329,
81449 14330,14331,14332,14333,14334,14335,14336,14337,14338,14339,14340,14341,
81450 14342,14343,14344,14345,14346,14347,14348,14349,14350,14351,14352,14353,
81451 14354,14355,14356,14357,14358,14359,14360,14361,14362,14363,14364,14365,
81452 14366,14367,14368,14369,14370,14371,14372,14373,14374,14375,14376,14377,
81453 14378,14379,14380,14381,14382,14383,14384,14385,14386,14387,14388,14389,
81454 14390,14391,14392,14393,14394,14395,14396,14397,14398,14399,14400,14401,
81455 14402,14403,14404,14405,14406,14407,14408,14409,14410,14411,14412,14413,
81456 14414,14415,14416,14417,14418,14419,14420,14421,14422,14423,14424,14425,
81457 14426,14427,14428,14429,14430,14431,14432,14433,14434,14435,14436,14437,
81458 14438,14439,14440,14441,14442,14443,14444,14445,14446,14447,14448,14449,
81459 14450,14451,14452,14453,14454,14455,14456,14457,14458,14459,14460,14461,
81460 14462,14463,14464,14465,14466,14467,14468,14469,14470,14471,14472,14473,
81461 14474,14475,14476,14477,14478,14479,14480,14481,14482,14483,14484,14485,
81462 14486,14487,14488,14489,14490,14491,14492,14493,14494,14495,14496,14497,
81463 14498,14499,14500,14501,14502,14503,14504,14505,14506,14507,14508,14509,
81464 14510,14511,14512,14513,14514,14515,14516,14517,14518,14519,14520,14521,
81465 14522,14523,14524,14525,14526,14527,14528,14529,14530,14531,14532,14533,
81466 14534,14535,14536,14537,14538,14539,14540,14541,14542,14543,14544,14545,
81467 14546,14547,14548,14549,14550,14551,14552,14553,14554,14555,14556,14557,
81468 14558,14559,14560,14561,14562,14563,14564,14565,14566,14567,14568,14569,
81469 14570,14571,14572,14573,14574,14575,14576,14577,14578,14579,14580,14581,
81470 14582,14583,14584,14585,14586,14587,14588,14589,14590,14591,14592,14593,
81471 14594,14595,14596,14597,14598,14599,14600,14601,14602,14603,14604,14605,
81472 14606,14607,14608,14609,14610,14611,14612,14613,14614,14615,14616,14617,
81473 14618,14619,14620,14621,14622,14623,14624,14625,14626,14627,14628,14629,
81474 14630,14631,14632,14633,14634,14635,14636,14637,14638,14639,14640,14641,
81475 14642,14643,14644,14645,14646,14647,14648,14649,14650,14651,14652,14653,
81476 14654,14655,14656,14657,14658,14659,14660,14661,14662,14663,14664,14665,
81477 14666,14667,14668,14669,14670,14671,14672,14673,14674,14675,14676,14677,
81478 14678,14679,14680,14681,14682,14683,14684,14685,14686,14687,14688,14689,
81479 14690,14691,14692,14693,14694,14695,14696,14697,14698,14699,14700,14701,
81480 14702,14703,14704,14705,14706,14707,14708,14709,14710,14711,14712,14713,
81481 14714,14715,14716,14717,14718,14719,14720,14721,14722,14723,14724,14725,
81482 14726,14727,14728,14729,14730,14731,14732,14733,14734,14735,14736,14737,
81483 14738,14739,14740,14741,14742,14743,14744,14745,14746,14747,14748,14749,
81484 14750,14751,14752,14753,14754,14755,14756,14757,14758,14759,14760,14761,
81485 14762,14763,14764,14765,14766,14767,14768,14769,14770,14771,14772,14773,
81486 14774,14775,14776,14777,14778,14779,14780,14781,14782,14783,14784,14785,
81487 14786,14787,14788,14789,14790,14791,14792,14793,14794,14795,14796,14797,
81488 14798,14799,14800,14801,14802,14803,14804,14805,14806,14807,14808,14809,
81489 14810,14811,14812,14813,14814,14815,14816,14817,14818,14819,14820,14821,
81490 14822,14823,14824,14825,14826,14827,14828,14829,14830,14831,14832,14833,
81491 14834,14835,14836,14837,14838,14839,14840,14841,14842,14843,14844,14845,
81492 14846,14847,14848,14849,14850,14851,14852,14853,14854,14855,14856,14857,
81493 14858,14859,14860,14861,14862,14863,14864,14865,14866,14867,14868,14869,
81494 14870,14871,14872,14873,14874,14875,14876,14877,14878,14879,14880,14881,
81495 14882,14883,14884,14885,14886,14887,14888,14889,14890,14891,14892,14893,
81496 14894,14895,14896,14897,14898,14899,14900,14901,14902,14903,14904,14905,
81497 14906,14907,14908,14909,14910,14911,14912,14913,14914,14915,14916,14917,
81498 14918,14919,14920,14921,14922,14923,14924,14925,14926,14927,14928,14929,
81499 14930,14931,14932,14933,14934,14935,14936,14937,14938,14939,14940,14941,
81500 14942,14943,14944,14945,14946,14947,14948,14949,14950,14951,14952,14953,
81501 14954,14955,14956,14957,14958,14959,14960,14961,14962,14963,14964,14965,
81502 14966,14967,14968,14969,14970,14971,14972,14973,14974,14975,14976,14977,
81503 14978,14979,14980,14981,14982,14983,14984,14985,14986,14987,14988,14989,
81504 14990,14991,14992,14993,14994,14995,14996,14997,14998,14999,15000,15001,
81505 15002,15003,15004,15005,15006,15007,15008,15009,15010,15011,15012,15013,
81506 15014,15015,15016,15017,15018,15019,15020,15021,15022,15023,15024,15025,
81507 15026,15027,15028,15029,15030,15031,15032,15033,15034,15035,15036,15037,
81508 15038,15039,15040,15041,15042,15043,15044,15045,15046,15047,15048,15049,
81509 15050,15051,15052,15053,15054,15055,15056,15057,15058,15059,15060,15061,
81510 15062,15063,15064,15065,15066,15067,15068,15069,15070,15071,15072,15073,
81511 15074,15075,15076,15077,15078,15079,15080,15081,15082,15083,15084,15085,
81512 15086,15087,15088,15089,15090,15091,15092,15093,15094,15095,15096,15097,
81513 15098,15099,15100,15101,15102,15103,15104,15105,15106,15107,15108,15109,
81514 15110,15111,15112,15113,15114,15115,15116,15117,15118,15119,15120,15121,
81515 15122,15123,15124,15125,15126,15127,15128,15129,15130,15131,15132,15133,
81516 15134,15135,15136,15137,15138,15139,15140,15141,15142,15143,15144,15145,
81517 15146,15147,15148,15149,15150,15151,15152,15153,15154,15155,15156,15157,
81518 15158,15159,15160,15161,15162,15163,15164,15165,15166,15167,15168,15169,
81519 15170,15171,15172,15173,15174,15175,15176,15177,15178,15179,15180,15181,
81520 15182,15183,15184,15185,15186,15187,15188,15189,15190,15191,15192,15193,
81521 15194,15195,15196,15197,15198,15199,15200,15201,15202,15203,15204,15205,
81522 15206,15207,15208,15209,15210,15211,15212,15213,15214,15215,15216,15217,
81523 15218,15219,15220,15221,15222,15223,15224,15225,15226,15227,15228,15229,
81524 15230,15231,15232,15233,15234,15235,15236,15237,15238,15239,15240,15241,
81525 15242,15243,15244,15245,15246,15247,15248,15249,15250,15251,15252,15253,
81526 15254,15255,15256,15257,15258,15259,15260,15261,15262,15263,15264,15265,
81527 15266,15267,15268,15269,15270,15271,15272,15273,15274,15275,15276,15277,
81528 15278,15279,15280,15281,15282,15283,15284,15285,15286,15287,15288,15289,
81529 15290,15291,15292,15293,15294,15295,15296,15297,15298,15299,15300,15301,
81530 15302,15303,15304,15305,15306,15307,15308,15309,15310,15311,15312,15313,
81531 15314,15315,15316,15317,15318,15319,15320,15321,15322,15323,15324,15325,
81532 15326,15327,15328,15329,15330,15331,15332,15333,15334,15335,15336,15337,
81533 15338,15339,15340,15341,15342,15343,15344,15345,15346,15347,15348,15349,
81534 15350,15351,15352,15353,15354,15355,15356,15357,15358,15359,15360,15361,
81535 15362,15363,15364,15365,15366,15367,15368,15369,15370,15371,15372,15373,
81536 15374,15375,15376,15377,15378,15379,15380,15381,15382,15383,15384,15385,
81537 15386,15387,15388,15389,15390,15391,15392,15393,15394,15395,15396,15397,
81538 15398,15399,15400,15401,15402,15403,15404,15405,15406,15407,15408,15409,
81539 15410,15411,15412,15413,15414,15415,15416,15417,15418,15419,15420,15421,
81540 15422,15423,15424,15425,15426,15427,15428,15429,15430,15431,15432,15433,
81541 15434,15435,15436,15437,15438,15439,15440,15441,15442,15443,15444,15445,
81542 15446,15447,15448,15449,15450,15451,15452,15453,15454,15455,15456,15457,
81543 15458,15459,15460,15461,15462,15463,15464,15465,15466,15467,15468,15469,
81544 15470,15471,15472,15473,15474,15475,15476,15477,15478,15479,15480,15481,
81545 15482,15483,15484,15485,15486,15487,15488,15489,15490,15491,15492,15493,
81546 15494,15495,15496,15497,15498,15499,15500,15501,15502,15503,15504,15505,
81547 15506,15507,15508,15509,15510,15511,15512,15513,15514,15515,15516,15517,
81548 15518,15519,15520,15521,15522,15523,15524,15525,15526,15527,15528,15529,
81549 15530,15531,15532,15533,15534,15535,15536,15537,15538,15539,15540,15541,
81550 15542,15543,15544,15545,15546,15547,15548,15549,15550,15551,15552,15553,
81551 15554,15555,15556,15557,15558,15559,15560,15561,15562,15563,15564,15565,
81552 15566,15567,15568,15569,15570,15571,15572,15573,15574,15575,15576,15577,
81553 15578,15579,15580,15581,15582,15583,15584,15585,15586,15587,15588,15589,
81554 15590,15591,15592,15593,15594,15595,15596,15597,15598,15599,15600,15601,
81555 15602,15603,15604,15605,15606,15607,15608,15609,15610,15611,15612,15613,
81556 15614,15615,15616,15617,15618,15619,15620,15621,15622,15623,15624,15625,
81557 15626,15627,15628,15629,15630,15631,15632,15633,15634,15635,15636,15637,
81558 15638,15639,15640,15641,15642,15643,15644,15645,15646,15647,15648,15649,
81559 15650,15651,15652,15653,15654,15655,15656,15657,15658,15659,15660,15661,
81560 15662,15663,15664,15665,15666,15667,15668,15669,15670,15671,15672,15673,
81561 15674,15675,15676,15677,15678,15679,15680,15681,15682,15683,15684,15685,
81562 15686,15687,15688,15689,15690,15691,15692,15693,15694,15695,15696,15697,
81563 15698,15699,15700,15701,15702,15703,15704,15705,15706,15707,15708,15709,
81564 15710,15711,15712,15713,15714,15715,15716,15717,15718,15719,15720,15721,
81565 15722,15723,15724,15725,15726,15727,15728,15729,15730,15731,15732,15733,
81566 15734,15735,15736,15737,15738,15739,15740,15741,15742,15743,15744,15745,
81567 15746,15747,15748,15749,15750,15751,15752,15753,15754,15755,15756,15757,
81568 15758,15759,15760,15761,15762,15763,15764,15765,15766,15767,15768,15769,
81569 15770,15771,15772,15773,15774,15775,15776,15777,15778,15779,15780,15781,
81570 15782,15783,15784,15785,15786,15787,15788,15789,15790,15791,15792,15793,
81571 15794,15795,15796,15797,15798,15799,15800,15801,15802,15803,15804,15805,
81572 15806,15807,15808,15809,15810,15811,15812,15813,15814,15815,15816,15817,
81573 15818,15819,15820,15821,15822,15823,15824,15825,15826,15827,15828,15829,
81574 15830,15831,15832,15833,15834,15835,15836,15837,15838,15839,15840,15841,
81575 15842,15843,15844,15845,15846,15847,15848,15849,15850,15851,15852,15853,
81576 15854,15855,15856,15857,15858,15859,15860,15861,15862,15863,15864,15865,
81577 15866,15867,15868,15869,15870,15871,15872,15873,15874,15875,15876,15877,
81578 15878,15879,15880,15881,15882,15883,15884,15885,15886,15887,15888,15889,
81579 15890,15891,15892,15893,15894,15895,15896,15897,15898,15899,15900,15901,
81580 15902,15903,15904,15905,15906,15907,15908,15909,15910,15911,15912,15913,
81581 15914,15915,15916,15917,15918,15919,15920,15921,15922,15923,15924,15925,
81582 15926,15927,15928,15929,15930,15931,15932,15933,15934,15935,15936,15937,
81583 15938,15939,15940,15941,15942,15943,15944,15945,15946,15947,15948,15949,
81584 15950,15951,15952,15953,15954,15955,15956,15957,15958,15959,15960,15961,
81585 15962,15963,15964,15965,15966,15967,15968,15969,15970,15971,15972,15973,
81586 15974,15975,15976,15977,15978,15979,15980,15981,15982,15983,15984,15985,
81587 15986,15987,15988,15989,15990,15991,15992,15993,15994,15995,15996,15997,
81588 15998,15999,16000,16001,16002,16003,16004,16005,16006,16007,16008,16009,
81589 16010,16011,16012,16013,16014,16015,16016,16017,16018,16019,16020,16021,
81590 16022,16023,16024,16025,16026,16027,16028,16029,16030,16031,16032,16033,
81591 16034,16035,16036,16037,16038,16039,16040,16041,16042,16043,16044,16045,
81592 16046,16047,16048,16049,16050,16051,16052,16053,16054,16055,16056,16057,
81593 16058,16059,16060,16061,16062,16063,16064,16065,16066,16067,16068,16069,
81594 16070,16071,16072,16073,16074,16075,16076,16077,16078,16079,16080,16081,
81595 16082,16083,16084,16085,16086,16087,16088,16089,16090,16091,16092,16093,
81596 16094,16095,16096,16097,16098,16099,16100,16101,16102,16103,16104,16105,
81597 16106,16107,16108,16109,16110,16111,16112,16113,16114,16115,16116,16117,
81598 16118,16119,16120,16121,16122,16123,16124,16125,16126,16127,16128,16129,
81599 16130,16131,16132,16133,16134,16135,16136,16137,16138,16139,16140,16141,
81600 16142,16143,16144,16145,16146,16147,16148,16149,16150,16151,16152,16153,
81601 16154,16155,16156,16157,16158,16159,16160,16161,16162,16163,16164,16165,
81602 16166,16167,16168,16169,16170,16171,16172,16173,16174,16175,16176,16177,
81603 16178,16179,16180,16181,16182,16183,16184,16185,16186,16187,16188,16189,
81604 16190,16191,16192,16193,16194,16195,16196,16197,16198,16199,16200,16201,
81605 16202,16203,16204,16205,16206,16207,16208,16209,16210,16211,16212,16213,
81606 16214,16215,16216,16217,16218,16219,16220,16221,16222,16223,16224,16225,
81607 16226,16227,16228,16229,16230,16231,16232,16233,16234,16235,16236,16237,
81608 16238,16239,16240,16241,16242,16243,16244,16245,16246,16247,16248,16249,
81609 16250,16251,16252,16253,16254,16255,16256,16257,16258,16259,16260,16261,
81610 16262,16263,16264,16265,16266,16267,16268,16269,16270,16271,16272,16273,
81611 16274,16275,16276,16277,16278,16279,16280,16281,16282,16283,16284,16285,
81612 16286,16287,16288,16289,16290,16291,16292,16293,16294,16295,16296,16297,
81613 16298,16299,16300,16301,16302,16303,16304,16305,16306,16307,16308,16309,
81614 16310,16311,16312,16313,16314,16315,16316,16317,16318,16319,16320,16321,
81615 16322,16323,16324,16325,16326,16327,16328,16329,16330,16331,16332,16333,
81616 16334,16335,16336,16337,16338,16339,16340,16341,16342,16343,16344,16345,
81617 16346,16347,16348,16349,16350,16351,16352,16353,16354,16355,16356,16357,
81618 16358,16359,16360,16361,16362,16363,16364,16365,16366,16367,16368,16369,
81619 16370,16371,16372,16373,16374,16375,16376,16377,16378,16379,16380,16381,
81620 16382,16383,16384,16385,16386,16387,16388,16389,16390,16391,16392,16393,
81621 16394,16395,16396,16397,16398,16399,16400,16401,16402,16403,16404,16405,
81622 16406,16407,16408,16409,16410,16411,16412,16413,16414,16415,16416,16417,
81623 16418,16419,16420,16421,16422,16423,16424,16425,16426,16427,16428,16429,
81624 16430,16431,16432,16433,16434,16435,16436,16437,16438,16439,16440,16441,
81625 16442,16443,16444,16445,16446,16447,16448,16449,16450,16451,16452,16453,
81626 16454,16455,16456,16457,16458,16459,16460,16461,16462,16463,16464,16465,
81627 16466,16467,16468,16469,16470,16471,16472,16473,16474,16475,16476,16477,
81628 16478,16479,16480,16481,16482,16483,16484,16485,16486,16487,16488,16489,
81629 16490,16491,16492,16493,16494,16495,16496,16497,16498,16499,16500,16501,
81630 16502,16503,16504,16505,16506,16507,16508,16509,16510,16511,16512,16513,
81631 16514,16515,16516,16517,16518,16519,16520,16521,16522,16523,16524,16525,
81632 16526,16527,16528,16529,16530,16531,16532,16533,16534,16535,16536,16537,
81633 16538,16539,16540,16541,16542,16543,16544,16545,16546,16547,16548,16549,
81634 16550,16551,16552,16553,16554,16555,16556,16557,16558,16559,16560,16561,
81635 16562,16563,16564,16565,16566,16567,16568,16569,16570,16571,16572,16573,
81636 16574,16575,16576,16577,16578,16579,16580,16581,16582,16583,16584,16585,
81637 16586,16587,16588,16589,16590,16591,16592,16593,16594,16595,16596,16597,
81638 16598,16599,16600,16601,16602,16603,16604,16605,16606,16607,16608,16609,
81639 16610,16611,16612,16613,16614,16615,16616,16617,16618,16619,16620,16621,
81640 16622,16623,16624,16625,16626,16627,16628,16629,16630,16631,16632,16633,
81641 16634,16635,16636,16637,16638,16639,16640,16641,16642,16643,16644,16645,
81642 16646,16647,16648,16649,16650,16651,16652,16653,16654,16655,16656,16657,
81643 16658,16659,16660,16661,16662,16663,16664,16665,16666,16667,16668,16669,
81644 16670,16671,16672,16673,16674,16675,16676,16677,16678,16679,16680,16681,
81645 16682,16683,16684,16685,16686,16687,16688,16689,16690,16691,16692,16693,
81646 16694,16695,16696,16697,16698,16699,16700,16701,16702,16703,16704,16705,
81647 16706,16707,16708,16709,16710,16711,16712,16713,16714,16715,16716,16717,
81648 16718,16719,16720,16721,16722,16723,16724,16725,16726,16727,16728,16729,
81649 16730,16731,16732,16733,16734,16735,16736,16737,16738,16739,16740,16741,
81650 16742,16743,16744,16745,16746,16747,16748,16749,16750,16751,16752,16753,
81651 16754,16755,16756,16757,16758,16759,16760,16761,16762,16763,16764,16765,
81652 16766,16767,16768,16769,16770,16771,16772,16773,16774,16775,16776,16777,
81653 16778,16779,16780,16781,16782,16783,16784,16785,16786,16787,16788,16789,
81654 16790,16791,16792,16793,16794,16795,16796,16797,16798,16799,16800,16801,
81655 16802,16803,16804,16805,16806,16807,16808,16809,16810,16811,16812,16813,
81656 16814,16815,16816,16817,16818,16819,16820,16821,16822,16823,16824,16825,
81657 16826,16827,16828,16829,16830,16831,16832,16833,16834,16835,16836,16837,
81658 16838,16839,16840,16841,16842,16843,16844,16845,16846,16847,16848,16849,
81659 16850,16851,16852,16853,16854,16855,16856,16857,16858,16859,16860,16861,
81660 16862,16863,16864,16865,16866,16867,16868,16869,16870,16871,16872,16873,
81661 16874,16875,16876,16877,16878,16879,16880,16881,16882,16883,16884,16885,
81662 16886,16887,16888,16889,16890,16891,16892,16893,16894,16895,16896,16897,
81663 16898,16899,16900,16901,16902,16903,16904,16905,16906,16907,16908,16909,
81664 16910,16911,16912,16913,16914,16915,16916,16917,16918,16919,16920,16921,
81665 16922,16923,16924,16925,16926,16927,16928,16929,16930,16931,16932,16933,
81666 16934,16935,16936,16937,16938,16939,16940,16941,16942,16943,16944,16945,
81667 16946,16947,16948,16949,16950,16951,16952,16953,16954,16955,16956,16957,
81668 16958,16959,16960,16961,16962,16963,16964,16965,16966,16967,16968,16969,
81669 16970,16971,16972,16973,16974,16975,16976,16977,16978,16979,16980,16981,
81670 16982,16983,16984,16985,16986,16987,16988,16989,16990,16991,16992,16993,
81671 16994,16995,16996,16997,16998,16999,17000,17001,17002,17003,17004,17005,
81672 17006,17007,17008,17009,17010,17011,17012,17013,17014,17015,17016,17017,
81673 17018,17019,17020,17021,17022,17023,17024,17025,17026,17027,17028,17029,
81674 17030,17031,17032,17033,17034,17035,17036,17037,17038,17039,17040,17041,
81675 17042,17043,17044,17045,17046,17047,17048,17049,17050,17051,17052,17053,
81676 17054,17055,17056,17057,17058,17059,17060,17061,17062,17063,17064,17065,
81677 17066,17067,17068,17069,17070,17071,17072,17073,17074,17075,17076,17077,
81678 17078,17079,17080,17081,17082,17083,17084,17085,17086,17087,17088,17089,
81679 17090,17091,17092,17093,17094,17095,17096,17097,17098,17099,17100,17101,
81680 17102,17103,17104,17105,17106,17107,17108,17109,17110,17111,17112,17113,
81681 17114,17115,17116,17117,17118,17119,17120,17121,17122,17123,17124,17125,
81682 17126,17127,17128,17129,17130,17131,17132,17133,17134,17135,17136,17137,
81683 17138,17139,17140,17141,17142,17143,17144,17145,17146,17147,17148,17149,
81684 17150,17151,17152,17153,17154,17155,17156,17157,17158,17159,17160,17161,
81685 17162,17163,17164,17165,17166,17167,17168,17169,17170,17171,17172,17173,
81686 17174,17175,17176,17177,17178,17179,17180,17181,17182,17183,17184,17185,
81687 17186,17187,17188,17189,17190,17191,17192,17193,17194,17195,17196,17197,
81688 17198,17199,17200,17201,17202,17203,17204,17205,17206,17207,17208,17209,
81689 17210,17211,17212,17213,17214,17215,17216,17217,17218,17219,17220,17221,
81690 17222,17223,17224,17225,17226,17227,17228,17229,17230,17231,17232,17233,
81691 17234,17235,17236,17237,17238,17239,17240,17241,17242,17243,17244,17245,
81692 17246,17247,17248,17249,17250,17251,17252,17253,17254,17255,17256,17257,
81693 17258,17259,17260,17261,17262,17263,17264,17265,17266,17267,17268,17269,
81694 17270,17271,17272,17273,17274,17275,17276,17277,17278,17279,17280,17281,
81695 17282,17283,17284,17285,17286,17287,17288,17289,17290,17291,17292,17293,
81696 17294,17295,17296,17297,17298,17299,17300,17301,17302,17303,17304,17305,
81697 17306,17307,17308,17309,17310,17311,17312,17313,17314,17315,17316,17317,
81698 17318,17319,17320,17321,17322,17323,17324,17325,17326,17327,17328,17329,
81699 17330,17331,17332,17333,17334,17335,17336,17337,17338,17339,17340,17341,
81700 17342,17343,17344,17345,17346,17347,17348,17349,17350,17351,17352,17353,
81701 17354,17355,17356,17357,17358,17359,17360,17361,17362,17363,17364,17365,
81702 17366,17367,17368,17369,17370,17371,17372,17373,17374,17375,17376,17377,
81703 17378,17379,17380,17381,17382,17383,17384,17385,17386,17387,17388,17389,
81704 17390,17391,17392,17393,17394,17395,17396,17397,17398,17399,17400,17401,
81705 17402,17403,17404,17405,17406,17407,17408,17409,17410,17411,17412,17413,
81706 17414,17415,17416,17417,17418,17419,17420,17421,17422,17423,17424,17425,
81707 17426,17427,17428,17429,17430,17431,17432,17433,17434,17435,17436,17437,
81708 17438,17439,17440,17441,17442,17443,17444,17445,17446,17447,17448,17449,
81709 17450,17451,17452,17453,17454,17455,17456,17457,17458,17459,17460,17461,
81710 17462,17463,17464,17465,17466,17467,17468,17469,17470,17471,17472,17473,
81711 17474,17475,17476,17477,17478,17479,17480,17481,17482,17483,17484,17485,
81712 17486,17487,17488,17489,17490,17491,17492,17493,17494,17495,17496,17497,
81713 17498,17499,17500,17501,17502,17503,17504,17505,17506,17507,17508,17509,
81714 17510,17511,17512,17513,17514,17515,17516,17517,17518,17519,17520,17521,
81715 17522,17523,17524,17525,17526,17527,17528,17529,17530,17531,17532,17533,
81716 17534,17535,17536,17537,17538,17539,17540,17541,17542,17543,17544,17545,
81717 17546,17547,17548,17549,17550,17551,17552,17553,17554,17555,17556,17557,
81718 17558,17559,17560,17561,17562,17563,17564,17565,17566,17567,17568,17569,
81719 17570,17571,17572,17573,17574,17575,17576,17577,17578,17579,17580,17581,
81720 17582,17583,17584,17585,17586,17587,17588,17589,17590,17591,17592,17593,
81721 17594,17595,17596,17597,17598,17599,17600,17601,17602,17603,17604,17605,
81722 17606,17607,17608,17609,17610,17611,17612,17613,17614,17615,17616,17617,
81723 17618,17619,17620,17621,17622,17623,17624,17625,17626,17627,17628,17629,
81724 17630,17631,17632,17633,17634,17635,17636,17637,17638,17639,17640,17641,
81725 17642,17643,17644,17645,17646,17647,17648,17649,17650,17651,17652,17653,
81726 17654,17655,17656,17657,17658,17659,17660,17661,17662,17663,17664,17665,
81727 17666,17667,17668,17669,17670,17671,17672,17673,17674,17675,17676,17677,
81728 17678,17679,17680,17681,17682,17683,17684,17685,17686,17687,17688,17689,
81729 17690,17691,17692,17693,17694,17695,17696,17697,17698,17699,17700,17701,
81730 17702,17703,17704,17705,17706,17707,17708,17709,17710,17711,17712,17713,
81731 17714,17715,17716,17717,17718,17719,17720,17721,17722,17723,17724,17725,
81732 17726,17727,17728,17729,17730,17731,17732,17733,17734,17735,17736,17737,
81733 17738,17739,17740,17741,17742,17743,17744,17745,17746,17747,17748,17749,
81734 17750,17751,17752,17753,17754,17755,17756,17757,17758,17759,17760,17761,
81735 17762,17763,17764,17765,17766,17767,17768,17769,17770,17771,17772,17773,
81736 17774,17775,17776,17777,17778,17779,17780,17781,17782,17783,17784,17785,
81737 17786,17787,17788,17789,17790,17791,17792,17793,17794,17795,17796,17797,
81738 17798,17799,17800,17801,17802,17803,17804,17805,17806,17807,17808,17809,
81739 17810,17811,17812,17813,17814,17815,17816,17817,17818,17819,17820,17821,
81740 17822,17823,17824,17825,17826,17827,17828,17829,17830,17831,17832,17833,
81741 17834,17835,17836,17837,17838,17839,17840,17841,17842,17843,17844,17845,
81742 17846,17847,17848,17849,17850,17851,17852,17853,17854,17855,17856,17857,
81743 17858,17859,17860,17861,17862,17863,17864,17865,17866,17867,17868,17869,
81744 17870,17871,17872,17873,17874,17875,17876,17877,17878,17879,17880,17881,
81745 17882,17883,17884,17885,17886,17887,17888,17889,17890,17891,17892,17893,
81746 17894,17895,17896,17897,17898,17899,17900,17901,17902,17903,17904,17905,
81747 17906,17907,17908,17909,17910,17911,17912,17913,17914,17915,17916,17917,
81748 17918,17919,17920,17921,17922,17923,17924,17925,17926,17927,17928,17929,
81749 17930,17931,17932,17933,17934,17935,17936,17937,17938,17939,17940,17941,
81750 17942,17943,17944,17945,17946,17947,17948,17949,17950,17951,17952,17953,
81751 17954,17955,17956,17957,17958,17959,17960,17961,17962,17963,17964,17965,
81752 17966,17967,17968,17969,17970,17971,17972,17973,17974,17975,17976,17977,
81753 17978,17979,17980,17981,17982,17983,17984,17985,17986,17987,17988,17989,
81754 17990,17991,17992,17993,17994,17995,17996,17997,17998,17999,18000,18001,
81755 18002,18003,18004,18005,18006,18007,18008,18009,18010,18011,18012,18013,
81756 18014,18015,18016,18017,18018,18019,18020,18021,18022,18023,18024,18025,
81757 18026,18027,18028,18029,18030,18031,18032,18033,18034,18035,18036,18037,
81758 18038,18039,18040,18041,18042,18043,18044,18045,18046,18047,18048,18049,
81759 18050,18051,18052,18053,18054,18055,18056,18057,18058,18059,18060,18061,
81760 18062,18063,18064,18065,18066,18067,18068,18069,18070,18071,18072,18073,
81761 18074,18075,18076,18077,18078,18079,18080,18081,18082,18083,18084,18085,
81762 18086,18087,18088,18089,18090,18091,18092,18093,18094,18095,18096,18097,
81763 18098,18099,18100,18101,18102,18103,18104,18105,18106,18107,18108,18109,
81764 18110,18111,18112,18113,18114,18115,18116,18117,18118,18119,18120,18121,
81765 18122,18123,18124,18125,18126,18127,18128,18129,18130,18131,18132,18133,
81766 18134,18135,18136,18137,18138,18139,18140,18141,18142,18143,18144,18145,
81767 18146,18147,18148,18149,18150,18151,18152,18153,18154,18155,18156,18157,
81768 18158,18159,18160,18161,18162,18163,18164,18165,18166,18167,18168,18169,
81769 18170,18171,18172,18173,18174,18175,18176,18177,18178,18179,18180,18181,
81770 18182,18183,18184,18185,18186,18187,18188,18189,18190,18191,18192,18193,
81771 18194,18195,18196,18197,18198,18199,18200,18201,18202,18203,18204,18205,
81772 18206,18207,18208,18209,18210,18211,18212,18213,18214,18215,18216,18217,
81773 18218,18219,18220,18221,18222,18223,18224,18225,18226,18227,18228,18229,
81774 18230,18231,18232,18233,18234,18235,18236,18237,18238,18239,18240,18241,
81775 18242,18243,18244,18245,18246,18247,18248,18249,18250,18251,18252,18253,
81776 18254,18255,18256,18257,18258,18259,18260,18261,18262,18263,18264,18265,
81777 18266,18267,18268,18269,18270,18271,18272,18273,18274,18275,18276,18277,
81778 18278,18279,18280,18281,18282,18283,18284,18285,18286,18287,18288,18289,
81779 18290,18291,18292,18293,18294,18295,18296,18297,18298,18299,18300,18301,
81780 18302,18303,18304,18305,18306,18307,18308,18309,18310,18311,18312,18313,
81781 18314,18315,18316,18317,18318,18319,18320,18321,18322,18323,18324,18325,
81782 18326,18327,18328,18329,18330,18331,18332,18333,18334,18335,18336,18337,
81783 18338,18339,18340,18341,18342,18343,18344,18345,18346,18347,18348,18349,
81784 18350,18351,18352,18353,18354,18355,18356,18357,18358,18359,18360,18361,
81785 18362,18363,18364,18365,18366,18367,18368,18369,18370,18371,18372,18373,
81786 18374,18375,18376,18377,18378,18379,18380,18381,18382,18383,18384,18385,
81787 18386,18387,18388,18389,18390,18391,18392,18393,18394,18395,18396,18397,
81788 18398,18399,18400,18401,18402,18403,18404,18405,18406,18407,18408,18409,
81789 18410,18411,18412,18413,18414,18415,18416,18417,18418,18419,18420,18421,
81790 18422,18423,18424,18425,18426,18427,18428,18429,18430,18431,18432,18433,
81791 18434,18435,18436,18437,18438,18439,18440,18441,18442,18443,18444,18445,
81792 18446,18447,18448,18449,18450,18451,18452,18453,18454,18455,18456,18457,
81793 18458,18459,18460,18461,18462,18463,18464,18465,18466,18467,18468,18469,
81794 18470,18471,18472,18473,18474,18475,18476,18477,18478,18479,18480,18481,
81795 18482,18483,18484,18485,18486,18487,18488,18489,18490,18491,18492,18493,
81796 18494,18495,18496,18497,18498,18499,18500,18501,18502,18503,18504,18505,
81797 18506,18507,18508,18509,18510,18511,18512,18513,18514,18515,18516,18517,
81798 18518,18519,18520,18521,18522,18523,18524,18525,18526,18527,18528,18529,
81799 18530,18531,18532,18533,18534,18535,18536,18537,18538,18539,18540,18541,
81800 18542,18543,18544,18545,18546,18547,18548,18549,18550,18551,18552,18553,
81801 18554,18555,18556,18557,18558,18559,18560,18561,18562,18563,18564,18565,
81802 18566,18567,18568,18569,18570,18571,18572,18573,18574,18575,18576,18577,
81803 18578,18579,18580,18581,18582,18583,18584,18585,18586,18587,18588,18589,
81804 18590,18591,18592,18593,18594,18595,18596,18597,18598,18599,18600,18601,
81805 18602,18603,18604,18605,18606,18607,18608,18609,18610,18611,18612,18613,
81806 18614,18615,18616,18617,18618,18619,18620,18621,18622,18623,18624,18625,
81807 18626,18627,18628,18629,18630,18631,18632,18633,18634,18635,18636,18637,
81808 18638,18639,18640,18641,18642,18643,18644,18645,18646,18647,18648,18649,
81809 18650,18651,18652,18653,18654,18655,18656,18657,18658,18659,18660,18661,
81810 18662,18663,18664,18665,18666,18667,18668,18669,18670,18671,18672,18673,
81811 18674,18675,18676,18677,18678,18679,18680,18681,18682,18683,18684,18685,
81812 18686,18687,18688,18689,18690,18691,18692,18693,18694,18695,18696,18697,
81813 18698,18699,18700,18701,18702,18703,18704,18705,18706,18707,18708,18709,
81814 18710,18711,18712,18713,18714,18715,18716,18717,18718,18719,18720,18721,
81815 18722,18723,18724,18725,18726,18727,18728,18729,18730,18731,18732,18733,
81816 18734,18735,18736,18737,18738,18739,18740,18741,18742,18743,18744,18745,
81817 18746,18747,18748,18749,18750,18751,18752,18753,18754,18755,18756,18757,
81818 18758,18759,18760,18761,18762,18763,18764,18765,18766,18767,18768,18769,
81819 18770,18771,18772,18773,18774,18775,18776,18777,18778,18779,18780,18781,
81820 18782,18783,18784,18785,18786,18787,18788,18789,18790,18791,18792,18793,
81821 18794,18795,18796,18797,18798,18799,18800,18801,18802,18803,18804,18805,
81822 18806,18807,18808,18809,18810,18811,18812,18813,18814,18815,18816,18817,
81823 18818,18819,18820,18821,18822,18823,18824,18825,18826,18827,18828,18829,
81824 18830,18831,18832,18833,18834,18835,18836,18837,18838,18839,18840,18841,
81825 18842,18843,18844,18845,18846,18847,18848,18849,18850,18851,18852,18853,
81826 18854,18855,18856,18857,18858,18859,18860,18861,18862,18863,18864,18865,
81827 18866,18867,18868,18869,18870,18871,18872,18873,18874,18875,18876,18877,
81828 18878,18879,18880,18881,18882,18883,18884,18885,18886,18887,18888,18889,
81829 18890,18891,18892,18893,18894,18895,18896,18897,18898,18899,18900,18901,
81830 18902,18903,18904,18905,18906,18907,18908,18909,18910,18911,18912,18913,
81831 18914,18915,18916,18917,18918,18919,18920,18921,18922,18923,18924,18925,
81832 18926,18927,18928,18929,18930,18931,18932,18933,18934,18935,18936,18937,
81833 18938,18939,18940,18941,18942,18943,18944,18945,18946,18947,18948,18949,
81834 18950,18951,18952,18953,18954,18955,18956,18957,18958,18959,18960,18961,
81835 18962,18963,18964,18965,18966,18967,18968,18969,18970,18971,18972,18973,
81836 18974,18975,18976,18977,18978,18979,18980,18981,18982,18983,18984,18985,
81837 18986,18987,18988,18989,18990,18991,18992,18993,18994,18995,18996,18997,
81838 18998,18999,19000,19001,19002,19003,19004,19005,19006,19007,19008,19009,
81839 19010,19011,19012,19013,19014,19015,19016,19017,19018,19019,19020,19021,
81840 19022,19023,19024,19025,19026,19027,19028,19029,19030,19031,19032,19033,
81841 19034,19035,19036,19037,19038,19039,19040,19041,19042,19043,19044,19045,
81842 19046,19047,19048,19049,19050,19051,19052,19053,19054,19055,19056,19057,
81843 19058,19059,19060,19061,19062,19063,19064,19065,19066,19067,19068,19069,
81844 19070,19071,19072,19073,19074,19075,19076,19077,19078,19079,19080,19081,
81845 19082,19083,19084,19085,19086,19087,19088,19089,19090,19091,19092,19093,
81846 19094,19095,19096,19097,19098,19099,19100,19101,19102,19103,19104,19105,
81847 19106,19107,19108,19109,19110,19111,19112,19113,19114,19115,19116,19117,
81848 19118,19119,19120,19121,19122,19123,19124,19125,19126,19127,19128,19129,
81849 19130,19131,19132,19133,19134,19135,19136,19137,19138,19139,19140,19141,
81850 19142,19143,19144,19145,19146,19147,19148,19149,19150,19151,19152,19153,
81851 19154,19155,19156,19157,19158,19159,19160,19161,19162,19163,19164,19165,
81852 19166,19167,19168,19169,19170,19171,19172,19173,19174,19175,19176,19177,
81853 19178,19179,19180,19181,19182,19183,19184,19185,19186,19187,19188,19189,
81854 19190,19191,19192,19193,19194,19195,19196,19197,19198,19199,19200,19201,
81855 19202,19203,19204,19205,19206,19207,19208,19209,19210,19211,19212,19213,
81856 19214,19215,19216,19217,19218,19219,19220,19221,19222,19223,19224,19225,
81857 19226,19227,19228,19229,19230,19231,19232,19233,19234,19235,19236,19237,
81858 19238,19239,19240,19241,19242,19243,19244,19245,19246,19247,19248,19249,
81859 19250,19251,19252,19253,19254,19255,19256,19257,19258,19259,19260,19261,
81860 19262,19263,19264,19265,19266,19267,19268,19269,19270,19271,19272,19273,
81861 19274,19275,19276,19277,19278,19279,19280,19281,19282,19283,19284,19285,
81862 19286,19287,19288,19289,19290,19291,19292,19293,19294,19295,19296,19297,
81863 19298,19299,19300,19301,19302,19303,19304,19305,19306,19307,19308,19309,
81864 19310,19311,19312,19313,19314,19315,19316,19317,19318,19319,19320,19321,
81865 19322,19323,19324,19325,19326,19327,19328,19329,19330,19331,19332,19333,
81866 19334,19335,19336,19337,19338,19339,19340,19341,19342,19343,19344,19345,
81867 19346,19347,19348,19349,19350,19351,19352,19353,19354,19355,19356,19357,
81868 19358,19359,19360,19361,19362,19363,19364,19365,19366,19367,19368,19369,
81869 19370,19371,19372,19373,19374,19375,19376,19377,19378,19379,19380,19381,
81870 19382,19383,19384,19385,19386,19387,19388,19389,19390,19391,19392,19393,
81871 19394,19395,19396,19397,19398,19399,19400,19401,19402,19403,19404,19405,
81872 19406,19407,19408,19409,19410,19411,19412,19413,19414,19415,19416,19417,
81873 19418,19419,19420,19421,19422,19423,19424,19425,19426,19427,19428,19429,
81874 19430,19431,19432,19433,19434,19435,19436,19437,19438,19439,19440,19441,
81875 19442,19443,19444,19445,19446,19447,19448,19449,19450,19451,19452,19453,
81876 19454,19455,19456,19457,19458,19459,19460,19461,19462,19463,19464,19465,
81877 19466,19467,19468,19469,19470,19471,19472,19473,19474,19475,19476,19477,
81878 19478,19479,19480,19481,19482,19483,19484,19485,19486,19487,19488,19489,
81879 19490,19491,19492,19493,19494,19495,19496,19497,19498,19499,19500,19501,
81880 19502,19503,19504,19505,19506,19507,19508,19509,19510,19511,19512,19513,
81881 19514,19515,19516,19517,19518,19519,19520,19521,19522,19523,19524,19525,
81882 19526,19527,19528,19529,19530,19531,19532,19533,19534,19535,19536,19537,
81883 19538,19539,19540,19541,19542,19543,19544,19545,19546,19547,19548,19549,
81884 19550,19551,19552,19553,19554,19555,19556,19557,19558,19559,19560,19561,
81885 19562,19563,19564,19565,19566,19567,19568,19569,19570,19571,19572,19573,
81886 19574,19575,19576,19577,19578,19579,19580,19581,19582,19583,19584,19585,
81887 19586,19587,19588,19589,19590,19591,19592,19593,19594,19595,19596,19597,
81888 19598,19599,19600,19601,19602,19603,19604,19605,19606,19607,19608,19609,
81889 19610,19611,19612,19613,19614,19615,19616,19617,19618,19619,19620,19621,
81890 19622,19623,19624,19625,19626,19627,19628,19629,19630,19631,19632,19633,
81891 19634,19635,19636,19637,19638,19639,19640,19641,19642,19643,19644,19645,
81892 19646,19647,19648,19649,19650,19651,19652,19653,19654,19655,19656,19657,
81893 19658,19659,19660,19661,19662,19663,19664,19665,19666,19667,19668,19669,
81894 19670,19671,19672,19673,19674,19675,19676,19677,19678,19679,19680,19681,
81895 19682,19683,19684,19685,19686,19687,19688,19689,19690,19691,19692,19693,
81896 19694,19695,19696,19697,19698,19699,19700,19701,19702,19703,19704,19705,
81897 19706,19707,19708,19709,19710,19711,19712,19713,19714,19715,19716,19717,
81898 19718,19719,19720,19721,19722,19723,19724,19725,19726,19727,19728,19729,
81899 19730,19731,19732,19733,19734,19735,19736,19737,19738,19739,19740,19741,
81900 19742,19743,19744,19745,19746,19747,19748,19749,19750,19751,19752,19753,
81901 19754,19755,19756,19757,19758,19759,19760,19761,19762,19763,19764,19765,
81902 19766,19767,19768,19769,19770,19771,19772,19773,19774,19775,19776,19777,
81903 19778,19779,19780,19781,19782,19783,19784,19785,19786,19787,19788,19789,
81904 19790,19791,19792,19793,19794,19795,19796,19797,19798,19799,19800,19801,
81905 19802,19803,19804,19805,19806,19807,19808,19809,19810,19811,19812,19813,
81906 19814,19815,19816,19817,19818,19819,19820,19821,19822,19823,19824,19825,
81907 19826,19827,19828,19829,19830,19831,19832,19833,19834,19835,19836,19837,
81908 19838,19839,19840,19841,19842,19843,19844,19845,19846,19847,19848,19849,
81909 19850,19851,19852,19853,19854,19855,19856,19857,19858,19859,19860,19861,
81910 19862,19863,19864,19865,19866,19867,19868,19869,19870,19871,19872,19873,
81911 19874,19875,19876,19877,19878,19879,19880,19881,19882,19883,19884,19885,
81912 19886,19887,19888,19889,19890,19891,19892,19893,19894,19895,19896,19897,
81913 19898,19899,19900,19901,19902,19903,19904,19905,19906,19907,19908,19909,
81914 19910,19911,19912,19913,19914,19915,19916,19917,19918,19919,19920,19921,
81915 19922,19923,19924,19925,19926,19927,19928,19929,19930,19931,19932,19933,
81916 19934,19935,19936,19937,19938,19939,19940,19941,19942,19943,19944,19945,
81917 19946,19947,19948,19949,19950,19951,19952,19953,19954,19955,19956,19957,
81918 19958,19959,19960,19961,19962,19963,19964,19965,19966,19967,19968,19969,
81919 19970,19971,19972,19973,19974,19975,19976,19977,19978,19979,19980,19981,
81920 19982,19983,19984,19985,19986,19987,19988,19989,19990,19991,19992,19993,
81921 19994,19995,19996,19997,19998,19999,20000,20001,20002,20003,20004,20005,
81922 20006,20007,20008,20009,20010,20011,20012,20013,20014,20015,20016,20017,
81923 20018,20019,20020,20021,20022,20023,20024,20025,20026,20027,20028,20029,
81924 20030,20031,20032,20033,20034,20035,20036,20037,20038,20039,20040,20041,
81925 20042,20043,20044,20045,20046,20047,20048,20049,20050,20051,20052,20053,
81926 20054,20055,20056,20057,20058,20059,20060,20061,20062,20063,20064,20065,
81927 20066,20067,20068,20069,20070,20071,20072,20073,20074,20075,20076,20077,
81928 20078,20079,20080,20081,20082,20083,20084,20085,20086,20087,20088,20089,
81929 20090,20091,20092,20093,20094,20095,20096,20097,20098,20099,20100,20101,
81930 20102,20103,20104,20105,20106,20107,20108,20109,20110,20111,20112,20113,
81931 20114,20115,20116,20117,20118,20119,20120,20121,20122,20123,20124,20125,
81932 20126,20127,20128,20129,20130,20131,20132,20133,20134,20135,20136,20137,
81933 20138,20139,20140,20141,20142,20143,20144,20145,20146,20147,20148,20149,
81934 20150,20151,20152,20153,20154,20155,20156,20157,20158,20159,20160,20161,
81935 20162,20163,20164,20165,20166,20167,20168,20169,20170,20171,20172,20173,
81936 20174,20175,20176,20177,20178,20179,20180,20181,20182,20183,20184,20185,
81937 20186,20187,20188,20189,20190,20191,20192,20193,20194,20195,20196,20197,
81938 20198,20199,20200,20201,20202,20203,20204,20205,20206,20207,20208,20209,
81939 20210,20211,20212,20213,20214,20215,20216,20217,20218,20219,20220,20221,
81940 20222,20223,20224,20225,20226,20227,20228,20229,20230,20231,20232,20233,
81941 20234,20235,20236,20237,20238,20239,20240,20241,20242,20243,20244,20245,
81942 20246,20247,20248,20249,20250,20251,20252,20253,20254,20255,20256,20257,
81943 20258,20259,20260,20261,20262,20263,20264,20265,20266,20267,20268,20269,
81944 20270,20271,20272,20273,20274,20275,20276,20277,20278,20279,20280,20281,
81945 20282,20283,20284,20285,20286,20287,20288,20289,20290,20291,20292,20293,
81946 20294,20295,20296,20297,20298,20299,20300,20301,20302,20303,20304,20305,
81947 20306,20307,20308,20309,20310,20311,20312,20313,20314,20315,20316,20317,
81948 20318,20319,20320,20321,20322,20323,20324,20325,20326,20327,20328,20329,
81949 20330,20331,20332,20333,20334,20335,20336,20337,20338,20339,20340,20341,
81950 20342,20343,20344,20345,20346,20347,20348,20349,20350,20351,20352,20353,
81951 20354,20355,20356,20357,20358,20359,20360,20361,20362,20363,20364,20365,
81952 20366,20367,20368,20369,20370,20371,20372,20373,20374,20375,20376,20377,
81953 20378,20379,20380,20381,20382,20383,20384,20385,20386,20387,20388,20389,
81954 20390,20391,20392,20393,20394,20395,20396,20397,20398,20399,20400,20401,
81955 20402,20403,20404,20405,20406,20407,20408,20409,20410,20411,20412,20413,
81956 20414,20415,20416,20417,20418,20419,20420,20421,20422,20423,20424,20425,
81957 20426,20427,20428,20429,20430,20431,20432,20433,20434,20435,20436,20437,
81958 20438,20439,20440,20441,20442,20443,20444,20445,20446,20447,20448,20449,
81959 20450,20451,20452,20453,20454,20455,20456,20457,20458,20459,20460,20461,
81960 20462,20463,20464,20465,20466,20467,20468,20469,20470,20471,20472,20473,
81961 20474,20475,20476,20477,20478,20479,20480,20481,20482,20483,20484,20485,
81962 20486,20487,20488,20489,20490,20491,20492,20493,20494,20495,20496,20497,
81963 20498,20499,20500,20501,20502,20503,20504,20505,20506,20507,20508,20509,
81964 20510,20511,20512,20513,20514,20515,20516,20517,20518,20519,20520,20521,
81965 20522,20523,20524,20525,20526,20527,20528,20529,20530,20531,20532,20533,
81966 20534,20535,20536,20537,20538,20539,20540,20541,20542,20543,20544,20545,
81967 20546,20547,20548,20549,20550,20551,20552,20553,20554,20555,20556,20557,
81968 20558,20559,20560,20561,20562,20563,20564,20565,20566,20567,20568,20569,
81969 20570,20571,20572,20573,20574,20575,20576,20577,20578,20579,20580,20581,
81970 20582,20583,20584,20585,20586,20587,20588,20589,20590,20591,20592,20593,
81971 20594,20595,20596,20597,20598,20599,20600,20601,20602,20603,20604,20605,
81972 20606,20607,20608,20609,20610,20611,20612,20613,20614,20615,20616,20617,
81973 20618,20619,20620,20621,20622,20623,20624,20625,20626,20627,20628,20629,
81974 20630,20631,20632,20633,20634,20635,20636,20637,20638,20639,20640,20641,
81975 20642,20643,20644,20645,20646,20647,20648,20649,20650,20651,20652,20653,
81976 20654,20655,20656,20657,20658,20659,20660,20661,20662,20663,20664,20665,
81977 20666,20667,20668,20669,20670,20671,20672,20673,20674,20675,20676,20677,
81978 20678,20679,20680,20681,20682,20683,20684,20685,20686,20687,20688,20689,
81979 20690,20691,20692,20693,20694,20695,20696,20697,20698,20699,20700,20701,
81980 20702,20703,20704,20705,20706,20707,20708,20709,20710,20711,20712,20713,
81981 20714,20715,20716,20717,20718,20719,20720,20721,20722,20723,20724,20725,
81982 20726,20727,20728,20729,20730,20731,20732,20733,20734,20735,20736,20737,
81983 20738,20739,20740,20741,20742,20743,20744,20745,20746,20747,20748,20749,
81984 20750,20751,20752,20753,20754,20755,20756,20757,20758,20759,20760,20761,
81985 20762,20763,20764,20765,20766,20767,20768,20769,20770,20771,20772,20773,
81986 20774,20775,20776,20777,20778,20779,20780,20781,20782,20783,20784,20785,
81987 20786,20787,20788,20789,20790,20791,20792,20793,20794,20795,20796,20797,
81988 20798,20799,20800,20801,20802,20803,20804,20805,20806,20807,20808,20809,
81989 20810,20811,20812,20813,20814,20815,20816,20817,20818,20819,20820,20821,
81990 20822,20823,20824,20825,20826,20827,20828,20829,20830,20831,20832,20833,
81991 20834,20835,20836,20837,20838,20839,20840,20841,20842,20843,20844,20845,
81992 20846,20847,20848,20849,20850,20851,20852,20853,20854,20855,20856,20857,
81993 20858,20859,20860,20861,20862,20863,20864,20865,20866,20867,20868,20869,
81994 20870,20871,20872,20873,20874,20875,20876,20877,20878,20879,20880,20881,
81995 20882,20883,20884,20885,20886,20887,20888,20889,20890,20891,20892,20893,
81996 20894,20895,20896,20897,20898,20899,20900,20901,20902,20903,20904,20905,
81997 20906,20907,20908,20909,20910,20911,20912,20913,20914,20915,20916,20917,
81998 20918,20919,20920,20921,20922,20923,20924,20925,20926,20927,20928,20929,
81999 20930,20931,20932,20933,20934,20935,20936,20937,20938,20939,20940,20941,
82000 20942,20943,20944,20945,20946,20947,20948,20949,20950,20951,20952,20953,
82001 20954,20955,20956,20957,20958,20959,20960,20961,20962,20963,20964,20965,
82002 20966,20967,20968,20969,20970,20971,20972,20973,20974,20975,20976,20977,
82003 20978,20979,20980,20981,20982,20983,20984,20985,20986,20987,20988,20989,
82004 20990,20991,20992,20993,20994,20995,20996,20997,20998,20999,21000,21001,
82005 21002,21003,21004,21005,21006,21007,21008,21009,21010,21011,21012,21013,
82006 21014,21015,21016,21017,21018,21019,21020,21021,21022,21023,21024,21025,
82007 21026,21027,21028,21029,21030,21031,21032,21033,21034,21035,21036,21037,
82008 21038,21039,21040,21041,21042,21043,21044,21045,21046,21047,21048,21049,
82009 21050,21051,21052,21053,21054,21055,21056,21057,21058,21059,21060,21061,
82010 21062,21063,21064,21065,21066,21067,21068,21069,21070,21071,21072,21073,
82011 21074,21075,21076,21077,21078,21079,21080,21081,21082,21083,21084,21085,
82012 21086,21087,21088,21089,21090,21091,21092,21093,21094,21095,21096,21097,
82013 21098,21099,21100,21101,21102,21103,21104,21105,21106,21107,21108,21109,
82014 21110,21111,21112,21113,21114,21115,21116,21117,21118,21119,21120,21121,
82015 21122,21123,21124,21125,21126,21127,21128,21129,21130,21131,21132,21133,
82016 21134,21135,21136,21137,21138,21139,21140,21141,21142,21143,21144,21145,
82017 21146,21147,21148,21149,21150,21151,21152,21153,21154,21155,21156,21157,
82018 21158,21159,21160,21161,21162,21163,21164,21165,21166,21167,21168,21169,
82019 21170,21171,21172,21173,21174,21175,21176,21177,21178,21179,21180,21181,
82020 21182,21183,21184,21185,21186,21187,21188,21189,21190,21191,21192,21193,
82021 21194,21195,21196,21197,21198,21199,21200,21201,21202,21203,21204,21205,
82022 21206,21207,21208,21209,21210,21211,21212,21213,21214,21215,21216,21217,
82023 21218,21219,21220,21221,21222,21223,21224,21225,21226,21227,21228,21229,
82024 21230,21231,21232,21233,21234,21235,21236,21237,21238,21239,21240,21241,
82025 21242,21243,21244,21245,21246,21247,21248,21249,21250,21251,21252,21253,
82026 21254,21255,21256,21257,21258,21259,21260,21261,21262,21263,21264,21265,
82027 21266,21267,21268,21269,21270,21271,21272,21273,21274,21275,21276,21277,
82028 21278,21279,21280,21281,21282,21283,21284,21285,21286,21287,21288,21289,
82029 21290,21291,21292,21293,21294,21295,21296,21297,21298,21299,21300,21301,
82030 21302,21303,21304,21305,21306,21307,21308,21309,21310,21311,21312,21313,
82031 21314,21315,21316,21317,21318,21319,21320,21321,21322,21323,21324,21325,
82032 21326,21327,21328,21329,21330,21331,21332,21333,21334,21335,21336,21337,
82033 21338,21339,21340,21341,21342,21343,21344,21345,21346,21347,21348,21349,
82034 21350,21351,21352,21353,21354,21355,21356,21357,21358,21359,21360,21361,
82035 21362,21363,21364,21365,21366,21367,21368,21369,21370,21371,21372,21373,
82036 21374,21375,21376,21377,21378,21379,21380,21381,21382,21383,21384,21385,
82037 21386,21387,21388,21389,21390,21391,21392,21393,21394,21395,21396,21397,
82038 21398,21399,21400,21401,21402,21403,21404,21405,21406,21407,21408,21409,
82039 21410,21411,21412,21413,21414,21415,21416,21417,21418,21419,21420,21421,
82040 21422,21423,21424,21425,21426,21427,21428,21429,21430,21431,21432,21433,
82041 21434,21435,21436,21437,21438,21439,21440,21441,21442,21443,21444,21445,
82042 21446,21447,21448,21449,21450,21451,21452,21453,21454,21455,21456,21457,
82043 21458,21459,21460,21461,21462,21463,21464,21465,21466,21467,21468,21469,
82044 21470,21471,21472,21473,21474,21475,21476,21477,21478,21479,21480,21481,
82045 21482,21483,21484,21485,21486,21487,21488,21489,21490,21491,21492,21493,
82046 21494,21495,21496,21497,21498,21499,21500,21501,21502,21503,21504,21505,
82047 21506,21507,21508,21509,21510,21511,21512,21513,21514,21515,21516,21517,
82048 21518,21519,21520,21521,21522,21523,21524,21525,21526,21527,21528,21529,
82049 21530,21531,21532,21533,21534,21535,21536,21537,21538,21539,21540,21541,
82050 21542,21543,21544,21545,21546,21547,21548,21549,21550,21551,21552,21553,
82051 21554,21555,21556,21557,21558,21559,21560,21561,21562,21563,21564,21565,
82052 21566,21567,21568,21569,21570,21571,21572,21573,21574,21575,21576,21577,
82053 21578,21579,21580,21581,21582,21583,21584,21585,21586,21587,21588,21589,
82054 21590,21591,21592,21593,21594,21595,21596,21597,21598,21599,21600,21601,
82055 21602,21603,21604,21605,21606,21607,21608,21609,21610,21611,21612,21613,
82056 21614,21615,21616,21617,21618,21619,21620,21621,21622,21623,21624,21625,
82057 21626,21627,21628,21629,21630,21631,21632,21633,21634,21635,21636,21637,
82058 21638,21639,21640,21641,21642,21643,21644,21645,21646,21647,21648,21649,
82059 21650,21651,21652,21653,21654,21655,21656,21657,21658,21659,21660,21661,
82060 21662,21663,21664,21665,21666,21667,21668,21669,21670,21671,21672,21673,
82061 21674,21675,21676,21677,21678,21679,21680,21681,21682,21683,21684,21685,
82062 21686,21687,21688,21689,21690,21691,21692,21693,21694,21695,21696,21697,
82063 21698,21699,21700,21701,21702,21703,21704,21705,21706,21707,21708,21709,
82064 21710,21711,21712,21713,21714,21715,21716,21717,21718,21719,21720,21721,
82065 21722,21723,21724,21725,21726,21727,21728,21729,21730,21731,21732,21733,
82066 21734,21735,21736,21737,21738,21739,21740,21741,21742,21743,21744,21745,
82067 21746,21747,21748,21749,21750,21751,21752,21753,21754,21755,21756,21757,
82068 21758,21759,21760,21761,21762,21763,21764,21765,21766,21767,21768,21769,
82069 21770,21771,21772,21773,21774,21775,21776,21777,21778,21779,21780,21781,
82070 21782,21783,21784,21785,21786,21787,21788,21789,21790,21791,21792,21793,
82071 21794,21795,21796,21797,21798,21799,21800,21801,21802,21803,21804,21805,
82072 21806,21807,21808,21809,21810,21811,21812,21813,21814,21815,21816,21817,
82073 21818,21819,21820,21821,21822,21823,21824,21825,21826,21827,21828,21829,
82074 21830,21831,21832,21833,21834,21835,21836,21837,21838,21839,21840,21841,
82075 21842,21843,21844,21845,21846,21847,21848,21849,21850,21851,21852,21853,
82076 21854,21855,21856,21857,21858,21859,21860,21861,21862,21863,21864,21865,
82077 21866,21867,21868,21869,21870,21871,21872,21873,21874,21875,21876,21877,
82078 21878,21879,21880,21881,21882,21883,21884,21885,21886,21887,21888,21889,
82079 21890,21891,21892,21893,21894,21895,21896,21897,21898,21899,21900,21901,
82080 21902,21903,21904,21905,21906,21907,21908,21909,21910,21911,21912,21913,
82081 21914,21915,21916,21917,21918,21919,21920,21921,21922,21923,21924,21925,
82082 21926,21927,21928,21929,21930,21931,21932,21933,21934,21935,21936,21937,
82083 21938,21939,21940,21941,21942,21943,21944,21945,21946,21947,21948,21949,
82084 21950,21951,21952,21953,21954,21955,21956,21957,21958,21959,21960,21961,
82085 21962,21963,21964,21965,21966,21967,21968,21969,21970,21971,21972,21973,
82086 21974,21975,21976,21977,21978,21979,21980,21981,21982,21983,21984,21985,
82087 21986,21987,21988,21989,21990,21991,21992,21993,21994,21995,21996,21997,
82088 21998,21999,22000,22001,22002,22003,22004,22005,22006,22007,22008,22009,
82089 22010,22011,22012,22013,22014,22015,22016,22017,22018,22019,22020,22021,
82090 22022,22023,22024,22025,22026,22027,22028,22029,22030,22031,22032,22033,
82091 22034,22035,22036,22037,22038,22039,22040,22041,22042,22043,22044,22045,
82092 22046,22047,22048,22049,22050,22051,22052,22053,22054,22055,22056,22057,
82093 22058,22059,22060,22061,22062,22063,22064,22065,22066,22067,22068,22069,
82094 22070,22071,22072,22073,22074,22075,22076,22077,22078,22079,22080,22081,
82095 22082,22083,22084,22085,22086,22087,22088,22089,22090,22091,22092,22093,
82096 22094,22095,22096,22097,22098,22099,22100,22101,22102,22103,22104,22105,
82097 22106,22107,22108,22109,22110,22111,22112,22113,22114,22115,22116,22117,
82098 22118,22119,22120,22121,22122,22123,22124,22125,22126,22127,22128,22129,
82099 22130,22131,22132,22133,22134,22135,22136,22137,22138,22139,22140,22141,
82100 22142,22143,22144,22145,22146,22147,22148,22149,22150,22151,22152,22153,
82101 22154,22155,22156,22157,22158,22159,22160,22161,22162,22163,22164,22165,
82102 22166,22167,22168,22169,22170,22171,22172,22173,22174,22175,22176,22177,
82103 22178,22179,22180,22181,22182,22183,22184,22185,22186,22187,22188,22189,
82104 22190,22191,22192,22193,22194,22195,22196,22197,22198,22199,22200,22201,
82105 22202,22203,22204,22205,22206,22207,22208,22209,22210,22211,22212,22213,
82106 22214,22215,22216,22217,22218,22219,22220,22221,22222,22223,22224,22225,
82107 22226,22227,22228,22229,22230,22231,22232,22233,22234,22235,22236,22237,
82108 22238,22239,22240,22241,22242,22243,22244,22245,22246,22247,22248,22249,
82109 22250,22251,22252,22253,22254,22255,22256,22257,22258,22259,22260,22261,
82110 22262,22263,22264,22265,22266,22267,22268,22269,22270,22271,22272,22273,
82111 22274,22275,22276,22277,22278,22279,22280,22281,22282,22283,22284,22285,
82112 22286,22287,22288,22289,22290,22291,22292,22293,22294,22295,22296,22297,
82113 22298,22299,22300,22301,22302,22303,22304,22305,22306,22307,22308,22309,
82114 22310,22311,22312,22313,22314,22315,22316,22317,22318,22319,22320,22321,
82115 22322,22323,22324,22325,22326,22327,22328,22329,22330,22331,22332,22333,
82116 22334,22335,22336,22337,22338,22339,22340,22341,22342,22343,22344,22345,
82117 22346,22347,22348,22349,22350,22351,22352,22353,22354,22355,22356,22357,
82118 22358,22359,22360,22361,22362,22363,22364,22365,22366,22367,22368,22369,
82119 22370,22371,22372,22373,22374,22375,22376,22377,22378,22379,22380,22381,
82120 22382,22383,22384,22385,22386,22387,22388,22389,22390,22391,22392,22393,
82121 22394,22395,22396,22397,22398,22399,22400,22401,22402,22403,22404,22405,
82122 22406,22407,22408,22409,22410,22411,22412,22413,22414,22415,22416,22417,
82123 22418,22419,22420,22421,22422,22423,22424,22425,22426,22427,22428,22429,
82124 22430,22431,22432,22433,22434,22435,22436,22437,22438,22439,22440,22441,
82125 22442,22443,22444,22445,22446,22447,22448,22449,22450,22451,22452,22453,
82126 22454,22455,22456,22457,22458,22459,22460,22461,22462,22463,22464,22465,
82127 22466,22467,22468,22469,22470,22471,22472,22473,22474,22475,22476,22477,
82128 22478,22479,22480,22481,22482,22483,22484,22485,22486,22487,22488,22489,
82129 22490,22491,22492,22493,22494,22495,22496,22497,22498,22499,22500,22501,
82130 22502,22503,22504,22505,22506,22507,22508,22509,22510,22511,22512,22513,
82131 22514,22515,22516,22517,22518,22519,22520,22521,22522,22523,22524,22525,
82132 22526,22527,22528,22529,22530,22531,22532,22533,22534,22535,22536,22537,
82133 22538,22539,22540,22541,22542,22543,22544,22545,22546,22547,22548,22549,
82134 22550,22551,22552,22553,22554,22555,22556,22557,22558,22559,22560,22561,
82135 22562,22563,22564,22565,22566,22567,22568,22569,22570,22571,22572,22573,
82136 22574,22575,22576,22577,22578,22579,22580,22581,22582,22583,22584,22585,
82137 22586,22587,22588,22589,22590,22591,22592,22593,22594,22595,22596,22597,
82138 22598,22599,22600,22601,22602,22603,22604,22605,22606,22607,22608,22609,
82139 22610,22611,22612,22613,22614,22615,22616,22617,22618,22619,22620,22621,
82140 22622,22623,22624,22625,22626,22627,22628,22629,22630,22631,22632,22633,
82141 22634,22635,22636,22637,22638,22639,22640,22641,22642,22643,22644,22645,
82142 22646,22647,22648,22649,22650,22651,22652,22653,22654,22655,22656,22657,
82143 22658,22659,22660,22661,22662,22663,22664,22665,22666,22667,22668,22669,
82144 22670,22671,22672,22673,22674,22675,22676,22677,22678,22679,22680,22681,
82145 22682,22683,22684,22685,22686,22687,22688,22689,22690,22691,22692,22693,
82146 22694,22695,22696,22697,22698,22699,22700,22701,22702,22703,22704,22705,
82147 22706,22707,22708,22709,22710,22711,22712,22713,22714,22715,22716,22717,
82148 22718,22719,22720,22721,22722,22723,22724,22725,22726,22727,22728,22729,
82149 22730,22731,22732,22733,22734,22735,22736,22737,22738,22739,22740,22741,
82150 22742,22743,22744,22745,22746,22747,22748,22749,22750,22751,22752,22753,
82151 22754,22755,22756,22757,22758,22759,22760,22761,22762,22763,22764,22765,
82152 22766,22767,22768,22769,22770,22771,22772,22773,22774,22775,22776,22777,
82153 22778,22779,22780,22781,22782,22783,22784,22785,22786,22787,22788,22789,
82154 22790,22791,22792,22793,22794,22795,22796,22797,22798,22799,22800,22801,
82155 22802,22803,22804,22805,22806,22807,22808,22809,22810,22811,22812,22813,
82156 22814,22815,22816,22817,22818,22819,22820,22821,22822,22823,22824,22825,
82157 22826,22827,22828,22829,22830,22831,22832,22833,22834,22835,22836,22837,
82158 22838,22839,22840,22841,22842,22843,22844,22845,22846,22847,22848,22849,
82159 22850,22851,22852,22853,22854,22855,22856,22857,22858,22859,22860,22861,
82160 22862,22863,22864,22865,22866,22867,22868,22869,22870,22871,22872,22873,
82161 22874,22875,22876,22877,22878,22879,22880,22881,22882,22883,22884,22885,
82162 22886,22887,22888,22889,22890,22891,22892,22893,22894,22895,22896,22897,
82163 22898,22899,22900,22901,22902,22903,22904,22905,22906,22907,22908,22909,
82164 22910,22911,22912,22913,22914,22915,22916,22917,22918,22919,22920,22921,
82165 22922,22923,22924,22925,22926,22927,22928,22929,22930,22931,22932,22933,
82166 22934,22935,22936,22937,22938,22939,22940,22941,22942,22943,22944,22945,
82167 22946,22947,22948,22949,22950,22951,22952,22953,22954,22955,22956,22957,
82168 22958,22959,22960,22961,22962,22963,22964,22965,22966,22967,22968,22969,
82169 22970,22971,22972,22973,22974,22975,22976,22977,22978,22979,22980,22981,
82170 22982,22983,22984,22985,22986,22987,22988,22989,22990,22991,22992,22993,
82171 22994,22995,22996,22997,22998,22999,23000,23001,23002,23003,23004,23005,
82172 23006,23007,23008,23009,23010,23011,23012,23013,23014,23015,23016,23017,
82173 23018,23019,23020,23021,23022,23023,23024,23025,23026,23027,23028,23029,
82174 23030,23031,23032,23033,23034,23035,23036,23037,23038,23039,23040,23041,
82175 23042,23043,23044,23045,23046,23047,23048,23049,23050,23051,23052,23053,
82176 23054,23055,23056,23057,23058,23059,23060,23061,23062,23063,23064,23065,
82177 23066,23067,23068,23069,23070,23071,23072,23073,23074,23075,23076,23077,
82178 23078,23079,23080,23081,23082,23083,23084,23085,23086,23087,23088,23089,
82179 23090,23091,23092,23093,23094,23095,23096,23097,23098,23099,23100,23101,
82180 23102,23103,23104,23105,23106,23107,23108,23109,23110,23111,23112,23113,
82181 23114,23115,23116,23117,23118,23119,23120,23121,23122,23123,23124,23125,
82182 23126,23127,23128,23129,23130,23131,23132,23133,23134,23135,23136,23137,
82183 23138,23139,23140,23141,23142,23143,23144,23145,23146,23147,23148,23149,
82184 23150,23151,23152,23153,23154,23155,23156,23157,23158,23159,23160,23161,
82185 23162,23163,23164,23165,23166,23167,23168,23169,23170,23171,23172,23173,
82186 23174,23175,23176,23177,23178,23179,23180,23181,23182,23183,23184,23185,
82187 23186,23187,23188,23189,23190,23191,23192,23193,23194,23195,23196,23197,
82188 23198,23199,23200,23201,23202,23203,23204,23205,23206,23207,23208,23209,
82189 23210,23211,23212,23213,23214,23215,23216,23217,23218,23219,23220,23221,
82190 23222,23223,23224,23225,23226,23227,23228,23229,23230,23231,23232,23233,
82191 23234,23235,23236,23237,23238,23239,23240,23241,23242,23243,23244,23245,
82192 23246,23247,23248,23249,23250,23251,23252,23253,23254,23255,23256,23257,
82193 23258,23259,23260,23261,23262,23263,23264,23265,23266,23267,23268,23269,
82194 23270,23271,23272,23273,23274,23275,23276,23277,23278,23279,23280,23281,
82195 23282,23283,23284,23285,23286,23287,23288,23289,23290,23291,23292,23293,
82196 23294,23295,23296,23297,23298,23299,23300,23301,23302,23303,23304,23305,
82197 23306,23307,23308,23309,23310,23311,23312,23313,23314,23315,23316,23317,
82198 23318,23319,23320,23321,23322,23323,23324,23325,23326,23327,23328,23329,
82199 23330,23331,23332,23333,23334,23335,23336,23337,23338,23339,23340,23341,
82200 23342,23343,23344,23345,23346,23347,23348,23349,23350,23351,23352,23353,
82201 23354,23355,23356,23357,23358,23359,23360,23361,23362,23363,23364,23365,
82202 23366,23367,23368,23369,23370,23371,23372,23373,23374,23375,23376,23377,
82203 23378,23379,23380,23381,23382,23383,23384,23385,23386,23387,23388,23389,
82204 23390,23391,23392,23393,23394,23395,23396,23397,23398,23399,23400,23401,
82205 23402,23403,23404,23405,23406,23407,23408,23409,23410,23411,23412,23413,
82206 23414,23415,23416,23417,23418,23419,23420,23421,23422,23423,23424,23425,
82207 23426,23427,23428,23429,23430,23431,23432,23433,23434,23435,23436,23437,
82208 23438,23439,23440,23441,23442,23443,23444,23445,23446,23447,23448,23449,
82209 23450,23451,23452,23453,23454,23455,23456,23457,23458,23459,23460,23461,
82210 23462,23463,23464,23465,23466,23467,23468,23469,23470,23471,23472,23473,
82211 23474,23475,23476,23477,23478,23479,23480,23481,23482,23483,23484,23485,
82212 23486,23487,23488,23489,23490,23491,23492,23493,23494,23495,23496,23497,
82213 23498,23499,23500,23501,23502,23503,23504,23505,23506,23507,23508,23509,
82214 23510,23511,23512,23513,23514,23515,23516,23517,23518,23519,23520,23521,
82215 23522,23523,23524,23525,23526,23527,23528,23529,23530,23531,23532,23533,
82216 23534,23535,23536,23537,23538,23539,23540,23541,23542,23543,23544,23545,
82217 23546,23547,23548,23549,23550,23551,23552,23553,23554,23555,23556,23557,
82218 23558,23559,23560,23561,23562,23563,23564,23565,23566,23567,23568,23569,
82219 23570,23571,23572,23573,23574,23575,23576,23577,23578,23579,23580,23581,
82220 23582,23583,23584,23585,23586,23587,23588,23589,23590,23591,23592,23593,
82221 23594,23595,23596,23597,23598,23599,23600,23601,23602,23603,23604,23605,
82222 23606,23607,23608,23609,23610,23611,23612,23613,23614,23615,23616,23617,
82223 23618,23619,23620,23621,23622,23623,23624,23625,23626,23627,23628,23629,
82224 23630,23631,23632,23633,23634,23635,23636,23637,23638,23639,23640,23641,
82225 23642,23643,23644,23645,23646,23647,23648,23649,23650,23651,23652,23653,
82226 23654,23655,23656,23657,23658,23659,23660,23661,23662,23663,23664,23665,
82227 23666,23667,23668,23669,23670,23671,23672,23673,23674,23675,23676,23677,
82228 23678,23679,23680,23681,23682,23683,23684,23685,23686,23687,23688,23689,
82229 23690,23691,23692,23693,23694,23695,23696,23697,23698,23699,23700,23701,
82230 23702,23703,23704,23705,23706,23707,23708,23709,23710,23711,23712,23713,
82231 23714,23715,23716,23717,23718,23719,23720,23721,23722,23723,23724,23725,
82232 23726,23727,23728,23729,23730,23731,23732,23733,23734,23735,23736,23737,
82233 23738,23739,23740,23741,23742,23743,23744,23745,23746,23747,23748,23749,
82234 23750,23751,23752,23753,23754,23755,23756,23757,23758,23759,23760,23761,
82235 23762,23763,23764,23765,23766,23767,23768,23769,23770,23771,23772,23773,
82236 23774,23775,23776,23777,23778,23779,23780,23781,23782,23783,23784,23785,
82237 23786,23787,23788,23789,23790,23791,23792,23793,23794,23795,23796,23797,
82238 23798,23799,23800,23801,23802,23803,23804,23805,23806,23807,23808,23809,
82239 23810,23811,23812,23813,23814,23815,23816,23817,23818,23819,23820,23821,
82240 23822,23823,23824,23825,23826,23827,23828,23829,23830,23831,23832,23833,
82241 23834,23835,23836,23837,23838,23839,23840,23841,23842,23843,23844,23845,
82242 23846,23847,23848,23849,23850,23851,23852,23853,23854,23855,23856,23857,
82243 23858,23859,23860,23861,23862,23863,23864,23865,23866,23867,23868,23869,
82244 23870,23871,23872,23873,23874,23875,23876,23877,23878,23879,23880,23881,
82245 23882,23883,23884,23885,23886,23887,23888,23889,23890,23891,23892,23893,
82246 23894,23895,23896,23897,23898,23899,23900,23901,23902,23903,23904,23905,
82247 23906,23907,23908,23909,23910,23911,23912,23913,23914,23915,23916,23917,
82248 23918,23919,23920,23921,23922,23923,23924,23925,23926,23927,23928,23929,
82249 23930,23931,23932,23933,23934,23935,23936,23937,23938,23939,23940,23941,
82250 23942,23943,23944,23945,23946,23947,23948,23949,23950,23951,23952,23953,
82251 23954,23955,23956,23957,23958,23959,23960,23961,23962,23963,23964,23965,
82252 23966,23967,23968,23969,23970,23971,23972,23973,23974,23975,23976,23977,
82253 23978,23979,23980,23981,23982,23983,23984,23985,23986,23987,23988,23989,
82254 23990,23991,23992,23993,23994,23995,23996,23997,23998,23999,24000,24001,
82255 24002,24003,24004,24005,24006,24007,24008,24009,24010,24011,24012,24013,
82256 24014,24015,24016,24017,24018,24019,24020,24021,24022,24023,24024,24025,
82257 24026,24027,24028,24029,24030,24031,24032,24033,24034,24035,24036,24037,
82258 24038,24039,24040,24041,24042,24043,24044,24045,24046,24047,24048,24049,
82259 24050,24051,24052,24053,24054,24055,24056,24057,24058,24059,24060,24061,
82260 24062,24063,24064,24065,24066,24067,24068,24069,24070,24071,24072,24073,
82261 24074,24075,24076,24077,24078,24079,24080,24081,24082,24083,24084,24085,
82262 24086,24087,24088,24089,24090,24091,24092,24093,24094,24095,24096,24097,
82263 24098,24099,24100,24101,24102,24103,24104,24105,24106,24107,24108,24109,
82264 24110,24111,24112,24113,24114,24115,24116,24117,24118,24119,24120,24121,
82265 24122,24123,24124,24125,24126,24127,24128,24129,24130,24131,24132,24133,
82266 24134,24135,24136,24137,24138,24139,24140,24141,24142,24143,24144,24145,
82267 24146,24147,24148,24149,24150,24151,24152,24153,24154,24155,24156,24157,
82268 24158,24159,24160,24161,24162,24163,24164,24165,24166,24167,24168,24169,
82269 24170,24171,24172,24173,24174,24175,24176,24177,24178,24179,24180,24181,
82270 24182,24183,24184,24185,24186,24187,24188,24189,24190,24191,24192,24193,
82271 24194,24195,24196,24197,24198,24199,24200,24201,24202,24203,24204,24205,
82272 24206,24207,24208,24209,24210,24211,24212,24213,24214,24215,24216,24217,
82273 24218,24219,24220,24221,24222,24223,24224,24225,24226,24227,24228,24229,
82274 24230,24231,24232,24233,24234,24235,24236,24237,24238,24239,24240,24241,
82275 24242,24243,24244,24245,24246,24247,24248,24249,24250,24251,24252,24253,
82276 24254,24255,24256,24257,24258,24259,24260,24261,24262,24263,24264,24265,
82277 24266,24267,24268,24269,24270,24271,24272,24273,24274,24275,24276,24277,
82278 24278,24279,24280,24281,24282,24283,24284,24285,24286,24287,24288,24289,
82279 24290,24291,24292,24293,24294,24295,24296,24297,24298,24299,24300,24301,
82280 24302,24303,24304,24305,24306,24307,24308,24309,24310,24311,24312,24313,
82281 24314,24315,24316,24317,24318,24319,24320,24321,24322,24323,24324,24325,
82282 24326,24327,24328,24329,24330,24331,24332,24333,24334,24335,24336,24337,
82283 24338,24339,24340,24341,24342,24343,24344,24345,24346,24347,24348,24349,
82284 24350,24351,24352,24353,24354,24355,24356,24357,24358,24359,24360,24361,
82285 24362,24363,24364,24365,24366,24367,24368,24369,24370,24371,24372,24373,
82286 24374,24375,24376,24377,24378,24379,24380,24381,24382,24383,24384,24385,
82287 24386,24387,24388,24389,24390,24391,24392,24393,24394,24395,24396,24397,
82288 24398,24399,24400,24401,24402,24403,24404,24405,24406,24407,24408,24409,
82289 24410,24411,24412,24413,24414,24415,24416,24417,24418,24419,24420,24421,
82290 24422,24423,24424,24425,24426,24427,24428,24429,24430,24431,24432,24433,
82291 24434,24435,24436,24437,24438,24439,24440,24441,24442,24443,24444,24445,
82292 24446,24447,24448,24449,24450,24451,24452,24453,24454,24455,24456,24457,
82293 24458,24459,24460,24461,24462,24463,24464,24465,24466,24467,24468,24469,
82294 24470,24471,24472,24473,24474,24475,24476,24477,24478,24479,24480,24481,
82295 24482,24483,24484,24485,24486,24487,24488,24489,24490,24491,24492,24493,
82296 24494,24495,24496,24497,24498,24499,24500,24501,24502,24503,24504,24505,
82297 24506,24507,24508,24509,24510,24511,24512,24513,24514,24515,24516,24517,
82298 24518,24519,24520,24521,24522,24523,24524,24525,24526,24527,24528,24529,
82299 24530,24531,24532,24533,24534,24535,24536,24537,24538,24539,24540,24541,
82300 24542,24543,24544,24545,24546,24547,24548,24549,24550,24551,24552,24553,
82301 24554,24555,24556,24557,24558,24559,24560,24561,24562,24563,24564,24565,
82302 24566,24567,24568,24569,24570,24571,24572,24573,24574,24575,24576,24577,
82303 24578,24579,24580,24581,24582,24583,24584,24585,24586,24587,24588,24589,
82304 24590,24591,24592,24593,24594,24595,24596,24597,24598,24599,24600,24601,
82305 24602,24603,24604,24605,24606,24607,24608,24609,24610,24611,24612,24613,
82306 24614,24615,24616,24617,24618,24619,24620,24621,24622,24623,24624,24625,
82307 24626,24627,24628,24629,24630,24631,24632,24633,24634,24635,24636,24637,
82308 24638,24639,24640,24641,24642,24643,24644,24645,24646,24647,24648,24649,
82309 24650,24651,24652,24653,24654,24655,24656,24657,24658,24659,24660,24661,
82310 24662,24663,24664,24665,24666,24667,24668,24669,24670,24671,24672,24673,
82311 24674,24675,24676,24677,24678,24679,24680,24681,24682,24683,24684,24685,
82312 24686,24687,24688,24689,24690,24691,24692,24693,24694,24695,24696,24697,
82313 24698,24699,24700,24701,24702,24703,24704,24705,24706,24707,24708,24709,
82314 24710,24711,24712,24713,24714,24715,24716,24717,24718,24719,24720,24721,
82315 24722,24723,24724,24725,24726,24727,24728,24729,24730,24731,24732,24733,
82316 24734,24735,24736,24737,24738,24739,24740,24741,24742,24743,24744,24745,
82317 24746,24747,24748,24749,24750,24751,24752,24753,24754,24755,24756,24757,
82318 24758,24759,24760,24761,24762,24763,24764,24765,24766,24767,24768,24769,
82319 24770,24771,24772,24773,24774,24775,24776,24777,24778,24779,24780,24781,
82320 24782,24783,24784,24785,24786,24787,24788,24789,24790,24791,24792,24793,
82321 24794,24795,24796,24797,24798,24799,24800,24801,24802,24803,24804,24805,
82322 24806,24807,24808,24809,24810,24811,24812,24813,24814,24815,24816,24817,
82323 24818,24819,24820,24821,24822,24823,24824,24825,24826,24827,24828,24829,
82324 24830,24831,24832,24833,24834,24835,24836,24837,24838,24839,24840,24841,
82325 24842,24843,24844,24845,24846,24847,24848,24849,24850,24851,24852,24853,
82326 24854,24855,24856,24857,24858,24859,24860,24861,24862,24863,24864,24865,
82327 24866,24867,24868,24869,24870,24871,24872,24873,24874,24875,24876,24877,
82328 24878,24879,24880,24881,24882,24883,24884,24885,24886,24887,24888,24889,
82329 24890,24891,24892,24893,24894,24895,24896,24897,24898,24899,24900,24901,
82330 24902,24903,24904,24905,24906,24907,24908,24909,24910,24911,24912,24913,
82331 24914,24915,24916,24917,24918,24919,24920,24921,24922,24923,24924,24925,
82332 24926,24927,24928,24929,24930,24931,24932,24933,24934,24935,24936,24937,
82333 24938,24939,24940,24941,24942,24943,24944,24945,24946,24947,24948,24949,
82334 24950,24951,24952,24953,24954,24955,24956,24957,24958,24959,24960,24961,
82335 24962,24963,24964,24965,24966,24967,24968,24969,24970,24971,24972,24973,
82336 24974,24975,24976,24977,24978,24979,24980,24981,24982,24983,24984,24985,
82337 24986,24987,24988,24989,24990,24991,24992,24993,24994,24995,24996,24997,
82338 24998,24999,25000,25001,25002,25003,25004,25005,25006,25007,25008,25009,
82339 25010,25011,25012,25013,25014,25015,25016,25017,25018,25019,25020,25021,
82340 25022,25023,25024,25025,25026,25027,25028,25029,25030,25031,25032,25033,
82341 25034,25035,25036,25037,25038,25039,25040,25041,25042,25043,25044,25045,
82342 25046,25047,25048,25049,25050,25051,25052,25053,25054,25055,25056,25057,
82343 25058,25059,25060,25061,25062,25063,25064,25065,25066,25067,25068,25069,
82344 25070,25071,25072,25073,25074,25075,25076,25077,25078,25079,25080,25081,
82345 25082,25083,25084,25085,25086,25087,25088,25089,25090,25091,25092,25093,
82346 25094,25095,25096,25097,25098,25099,25100,25101,25102,25103,25104,25105,
82347 25106,25107,25108,25109,25110,25111,25112,25113,25114,25115,25116,25117,
82348 25118,25119,25120,25121,25122,25123,25124,25125,25126,25127,25128,25129,
82349 25130,25131,25132,25133,25134,25135,25136,25137,25138,25139,25140,25141,
82350 25142,25143,25144,25145,25146,25147,25148,25149,25150,25151,25152,25153,
82351 25154,25155,25156,25157,25158,25159,25160,25161,25162,25163,25164,25165,
82352 25166,25167,25168,25169,25170,25171,25172,25173,25174,25175,25176,25177,
82353 25178,25179,25180,25181,25182,25183,25184,25185,25186,25187,25188,25189,
82354 25190,25191,25192,25193,25194,25195,25196,25197,25198,25199,25200,25201,
82355 25202,25203,25204,25205,25206,25207,25208,25209,25210,25211,25212,25213,
82356 25214,25215,25216,25217,25218,25219,25220,25221,25222,25223,25224,25225,
82357 25226,25227,25228,25229,25230,25231,25232,25233,25234,25235,25236,25237,
82358 25238,25239,25240,25241,25242,25243,25244,25245,25246,25247,25248,25249,
82359 25250,25251,25252,25253,25254,25255,25256,25257,25258,25259,25260,25261,
82360 25262,25263,25264,25265,25266,25267,25268,25269,25270,25271,25272,25273,
82361 25274,25275,25276,25277,25278,25279,25280,25281,25282,25283,25284,25285,
82362 25286,25287,25288,25289,25290,25291,25292,25293,25294,25295,25296,25297,
82363 25298,25299,25300,25301,25302,25303,25304,25305,25306,25307,25308,25309,
82364 25310,25311,25312,25313,25314,25315,25316,25317,25318,25319,25320,25321,
82365 25322,25323,25324,25325,25326,25327,25328,25329,25330,25331,25332,25333,
82366 25334,25335,25336,25337,25338,25339,25340,25341,25342,25343,25344,25345,
82367 25346,25347,25348,25349,25350,25351,25352,25353,25354,25355,25356,25357,
82368 25358,25359,25360,25361,25362,25363,25364,25365,25366,25367,25368,25369,
82369 25370,25371,25372,25373,25374,25375,25376,25377,25378,25379,25380,25381,
82370 25382,25383,25384,25385,25386,25387,25388,25389,25390,25391,25392,25393,
82371 25394,25395,25396,25397,25398,25399,25400,25401,25402,25403,25404,25405,
82372 25406,25407,25408,25409,25410,25411,25412,25413,25414,25415,25416,25417,
82373 25418,25419,25420,25421,25422,25423,25424,25425,25426,25427,25428,25429,
82374 25430,25431,25432,25433,25434,25435,25436,25437,25438,25439,25440,25441,
82375 25442,25443,25444,25445,25446,25447,25448,25449,25450,25451,25452,25453,
82376 25454,25455,25456,25457,25458,25459,25460,25461,25462,25463,25464,25465,
82377 25466,25467,25468,25469,25470,25471,25472,25473,25474,25475,25476,25477,
82378 25478,25479,25480,25481,25482,25483,25484,25485,25486,25487,25488,25489,
82379 25490,25491,25492,25493,25494,25495,25496,25497,25498,25499,25500,25501,
82380 25502,25503,25504,25505,25506,25507,25508,25509,25510,25511,25512,25513,
82381 25514,25515,25516,25517,25518,25519,25520,25521,25522,25523,25524,25525,
82382 25526,25527,25528,25529,25530,25531,25532,25533,25534,25535,25536,25537,
82383 25538,25539,25540,25541,25542,25543,25544,25545,25546,25547,25548,25549,
82384 25550,25551,25552,25553,25554,25555,25556,25557,25558,25559,25560,25561,
82385 25562,25563,25564,25565,25566,25567,25568,25569,25570,25571,25572,25573,
82386 25574,25575,25576,25577,25578,25579,25580,25581,25582,25583,25584,25585,
82387 25586,25587,25588,25589,25590,25591,25592,25593,25594,25595,25596,25597,
82388 25598,25599,25600,25601,25602,25603,25604,25605,25606,25607,25608,25609,
82389 25610,25611,25612,25613,25614,25615,25616,25617,25618,25619,25620,25621,
82390 25622,25623,25624,25625,25626,25627,25628,25629,25630,25631,25632,25633,
82391 25634,25635,25636,25637,25638,25639,25640,25641,25642,25643,25644,25645,
82392 25646,25647,25648,25649,25650,25651,25652,25653,25654,25655,25656,25657,
82393 25658,25659,25660,25661,25662,25663,25664,25665,25666,25667,25668,25669,
82394 25670,25671,25672,25673,25674,25675,25676,25677,25678,25679,25680,25681,
82395 25682,25683,25684,25685,25686,25687,25688,25689,25690,25691,25692,25693,
82396 25694,25695,25696,25697,25698,25699,25700,25701,25702,25703,25704,25705,
82397 25706,25707,25708,25709,25710,25711,25712,25713,25714,25715,25716,25717,
82398 25718,25719,25720,25721,25722,25723,25724,25725,25726,25727,25728,25729,
82399 25730,25731,25732,25733,25734,25735,25736,25737,25738,25739,25740,25741,
82400 25742,25743,25744,25745,25746,25747,25748,25749,25750,25751,25752,25753,
82401 25754,25755,25756,25757,25758,25759,25760,25761,25762,25763,25764,25765,
82402 25766,25767,25768,25769,25770,25771,25772,25773,25774,25775,25776,25777,
82403 25778,25779,25780,25781,25782,25783,25784,25785,25786,25787,25788,25789,
82404 25790,25791,25792,25793,25794,25795,25796,25797,25798,25799,25800,25801,
82405 25802,25803,25804,25805,25806,25807,25808,25809,25810,25811,25812,25813,
82406 25814,25815,25816,25817,25818,25819,25820,25821,25822,25823,25824,25825,
82407 25826,25827,25828,25829,25830,25831,25832,25833,25834,25835,25836,25837,
82408 25838,25839,25840,25841,25842,25843,25844,25845,25846,25847,25848,25849,
82409 25850,25851,25852,25853,25854,25855,25856,25857,25858,25859,25860,25861,
82410 25862,25863,25864,25865,25866,25867,25868,25869,25870,25871,25872,25873,
82411 25874,25875,25876,25877,25878,25879,25880,25881,25882,25883,25884,25885,
82412 25886,25887,25888,25889,25890,25891,25892,25893,25894,25895,25896,25897,
82413 25898,25899,25900,25901,25902,25903,25904,25905,25906,25907,25908,25909,
82414 25910,25911,25912,25913,25914,25915,25916,25917,25918,25919,25920,25921,
82415 25922,25923,25924,25925,25926,25927,25928,25929,25930,25931,25932,25933,
82416 25934,25935,25936,25937,25938,25939,25940,25941,25942,25943,25944,25945,
82417 25946,25947,25948,25949,25950,25951,25952,25953,25954,25955,25956,25957,
82418 25958,25959,25960,25961,25962,25963,25964,25965,25966,25967,25968,25969,
82419 25970,25971,25972,25973,25974,25975,25976,25977,25978,25979,25980,25981,
82420 25982,25983,25984,25985,25986,25987,25988,25989,25990,25991,25992,25993,
82421 25994,25995,25996,25997,25998,25999,26000,26001,26002,26003,26004,26005,
82422 26006,26007,26008,26009,26010,26011,26012,26013,26014,26015,26016,26017,
82423 26018,26019,26020,26021,26022,26023,26024,26025,26026,26027,26028,26029,
82424 26030,26031,26032,26033,26034,26035,26036,26037,26038,26039,26040,26041,
82425 26042,26043,26044,26045,26046,26047,26048,26049,26050,26051,26052,26053,
82426 26054,26055,26056,26057,26058,26059,26060,26061,26062,26063,26064,26065,
82427 26066,26067,26068,26069,26070,26071,26072,26073,26074,26075,26076,26077,
82428 26078,26079,26080,26081,26082,26083,26084,26085,26086,26087,26088,26089,
82429 26090,26091,26092,26093,26094,26095,26096,26097,26098,26099,26100,26101,
82430 26102,26103,26104,26105,26106,26107,26108,26109,26110,26111,26112,26113,
82431 26114,26115,26116,26117,26118,26119,26120,26121,26122,26123,26124,26125,
82432 26126,26127,26128,26129,26130,26131,26132,26133,26134,26135,26136,26137,
82433 26138,26139,26140,26141,26142,26143,26144,26145,26146,26147,26148,26149,
82434 26150,26151,26152,26153,26154,26155,26156,26157,26158,26159,26160,26161,
82435 26162,26163,26164,26165,26166,26167,26168,26169,26170,26171,26172,26173,
82436 26174,26175,26176,26177,26178,26179,26180,26181,26182,26183,26184,26185,
82437 26186,26187,26188,26189,26190,26191,26192,26193,26194,26195,26196,26197,
82438 26198,26199,26200,26201,26202,26203,26204,26205,26206,26207,26208,26209,
82439 26210,26211,26212,26213,26214,26215,26216,26217,26218,26219,26220,26221,
82440 26222,26223,26224,26225,26226,26227,26228,26229,26230,26231,26232,26233,
82441 26234,26235,26236,26237,26238,26239,26240,26241,26242,26243,26244,26245,
82442 26246,26247,26248,26249,26250,26251,26252,26253,26254,26255,26256,26257,
82443 26258,26259,26260,26261,26262,26263,26264,26265,26266,26267,26268,26269,
82444 26270,26271,26272,26273,26274,26275,26276,26277,26278,26279,26280,26281,
82445 26282,26283,26284,26285,26286,26287,26288,26289,26290,26291,26292,26293,
82446 26294,26295,26296,26297,26298,26299,26300,26301,26302,26303,26304,26305,
82447 26306,26307,26308,26309,26310,26311,26312,26313,26314,26315,26316,26317,
82448 26318,26319,26320,26321,26322,26323,26324,26325,26326,26327,26328,26329,
82449 26330,26331,26332,26333,26334,26335,26336,26337,26338,26339,26340,26341,
82450 26342,26343,26344,26345,26346,26347,26348,26349,26350,26351,26352,26353,
82451 26354,26355,26356,26357,26358,26359,26360,26361,26362,26363,26364,26365,
82452 26366,26367,26368,26369,26370,26371,26372,26373,26374,26375,26376,26377,
82453 26378,26379,26380,26381,26382,26383,26384,26385,26386,26387,26388,26389,
82454 26390,26391,26392,26393,26394,26395,26396,26397,26398,26399,26400,26401,
82455 26402,26403,26404,26405,26406,26407,26408,26409,26410,26411,26412,26413,
82456 26414,26415,26416,26417,26418,26419,26420,26421,26422,26423,26424,26425,
82457 26426,26427,26428,26429,26430,26431,26432,26433,26434,26435,26436,26437,
82458 26438,26439,26440,26441,26442,26443,26444,26445,26446,26447,26448,26449,
82459 26450,26451,26452,26453,26454,26455,26456,26457,26458,26459,26460,26461,
82460 26462,26463,26464,26465,26466,26467,26468,26469,26470,26471,26472,26473,
82461 26474,26475,26476,26477,26478,26479,26480,26481,26482,26483,26484,26485,
82462 26486,26487,26488,26489,26490,26491,26492,26493,26494,26495,26496,26497,
82463 26498,26499,26500,26501,26502,26503,26504,26505,26506,26507,26508,26509,
82464 26510,26511,26512,26513,26514,26515,26516,26517,26518,26519,26520,26521,
82465 26522,26523,26524,26525,26526,26527,26528,26529,26530,26531,26532,26533,
82466 26534,26535,26536,26537,26538,26539,26540,26541,26542,26543,26544,26545,
82467 26546,26547,26548,26549,26550,26551,26552,26553,26554,26555,26556,26557,
82468 26558,26559,26560,26561,26562,26563,26564,26565,26566,26567,26568,26569,
82469 26570,26571,26572,26573,26574,26575,26576,26577,26578,26579,26580,26581,
82470 26582,26583,26584,26585,26586,26587,26588,26589,26590,26591,26592,26593,
82471 26594,26595,26596,26597,26598,26599,26600,26601,26602,26603,26604,26605,
82472 26606,26607,26608,26609,26610,26611,26612,26613,26614,26615,26616,26617,
82473 26618,26619,26620,26621,26622,26623,26624,26625,26626,26627,26628,26629,
82474 26630,26631,26632,26633,26634,26635,26636,26637,26638,26639,26640,26641,
82475 26642,26643,26644,26645,26646,26647,26648,26649,26650,26651,26652,26653,
82476 26654,26655,26656,26657,26658,26659,26660,26661,26662,26663,26664,26665,
82477 26666,26667,26668,26669,26670,26671,26672,26673,26674,26675,26676,26677,
82478 26678,26679,26680,26681,26682,26683,26684,26685,26686,26687,26688,26689,
82479 26690,26691,26692,26693,26694,26695,26696,26697,26698,26699,26700,26701,
82480 26702,26703,26704,26705,26706,26707,26708,26709,26710,26711,26712,26713,
82481 26714,26715,26716,26717,26718,26719,26720,26721,26722,26723,26724,26725,
82482 26726,26727,26728,26729,26730,26731,26732,26733,26734,26735,26736,26737,
82483 26738,26739,26740,26741,26742,26743,26744,26745,26746,26747,26748,26749,
82484 26750,26751,26752,26753,26754,26755,26756,26757,26758,26759,26760,26761,
82485 26762,26763,26764,26765,26766,26767,26768,26769,26770,26771,26772,26773,
82486 26774,26775,26776,26777,26778,26779,26780,26781,26782,26783,26784,26785,
82487 26786,26787,26788,26789,26790,26791,26792,26793,26794,26795,26796,26797,
82488 26798,26799,26800,26801,26802,26803,26804,26805,26806,26807,26808,26809,
82489 26810,26811,26812,26813,26814,26815,26816,26817,26818,26819,26820,26821,
82490 26822,26823,26824,26825,26826,26827,26828,26829,26830,26831,26832,26833,
82491 26834,26835,26836,26837,26838,26839,26840,26841,26842,26843,26844,26845,
82492 26846,26847,26848,26849,26850,26851,26852,26853,26854,26855,26856,26857,
82493 26858,26859,26860,26861,26862,26863,26864,26865,26866,26867,26868,26869,
82494 26870,26871,26872,26873,26874,26875,26876,26877,26878,26879,26880,26881,
82495 26882,26883,26884,26885,26886,26887,26888,26889,26890,26891,26892,26893,
82496 26894,26895,26896,26897,26898,26899,26900,26901,26902,26903,26904,26905,
82497 26906,26907,26908,26909,26910,26911,26912,26913,26914,26915,26916,26917,
82498 26918,26919,26920,26921,26922,26923,26924,26925,26926,26927,26928,26929,
82499 26930,26931,26932,26933,26934,26935,26936,26937,26938,26939,26940,26941,
82500 26942,26943,26944,26945,26946,26947,26948,26949,26950,26951,26952,26953,
82501 26954,26955,26956,26957,26958,26959,26960,26961,26962,26963,26964,26965,
82502 26966,26967,26968,26969,26970,26971,26972,26973,26974,26975,26976,26977,
82503 26978,26979,26980,26981,26982,26983,26984,26985,26986,26987,26988,26989,
82504 26990,26991,26992,26993,26994,26995,26996,26997,26998,26999,27000,27001,
82505 27002,27003,27004,27005,27006,27007,27008,27009,27010,27011,27012,27013,
82506 27014,27015,27016,27017,27018,27019,27020,27021,27022,27023,27024,27025,
82507 27026,27027,27028,27029,27030,27031,27032,27033,27034,27035,27036,27037,
82508 27038,27039,27040,27041,27042,27043,27044,27045,27046,27047,27048,27049,
82509 27050,27051,27052,27053,27054,27055,27056,27057,27058,27059,27060,27061,
82510 27062,27063,27064,27065,27066,27067,27068,27069,27070,27071,27072,27073,
82511 27074,27075,27076,27077,27078,27079,27080,27081,27082,27083,27084,27085,
82512 27086,27087,27088,27089,27090,27091,27092,27093,27094,27095,27096,27097,
82513 27098,27099,27100,27101,27102,27103,27104,27105,27106,27107,27108,27109,
82514 27110,27111,27112,27113,27114,27115,27116,27117,27118,27119,27120,27121,
82515 27122,27123,27124,27125,27126,27127,27128,27129,27130,27131,27132,27133,
82516 27134,27135,27136,27137,27138,27139,27140,27141,27142,27143,27144,27145,
82517 27146,27147,27148,27149,27150,27151,27152,27153,27154,27155,27156,27157,
82518 27158,27159,27160,27161,27162,27163,27164,27165,27166,27167,27168,27169,
82519 27170,27171,27172,27173,27174,27175,27176,27177,27178,27179,27180,27181,
82520 27182,27183,27184,27185,27186,27187,27188,27189,27190,27191,27192,27193,
82521 27194,27195,27196,27197,27198,27199,27200,27201,27202,27203,27204,27205,
82522 27206,27207,27208,27209,27210,27211,27212,27213,27214,27215,27216,27217,
82523 27218,27219,27220,27221,27222,27223,27224,27225,27226,27227,27228,27229,
82524 27230,27231,27232,27233,27234,27235,27236,27237,27238,27239,27240,27241,
82525 27242,27243,27244,27245,27246,27247,27248,27249,27250,27251,27252,27253,
82526 27254,27255,27256,27257,27258,27259,27260,27261,27262,27263,27264,27265,
82527 27266,27267,27268,27269,27270,27271,27272,27273,27274,27275,27276,27277,
82528 27278,27279,27280,27281,27282,27283,27284,27285,27286,27287,27288,27289,
82529 27290,27291,27292,27293,27294,27295,27296,27297,27298,27299,27300,27301,
82530 27302,27303,27304,27305,27306,27307,27308,27309,27310,27311,27312,27313,
82531 27314,27315,27316,27317,27318,27319,27320,27321,27322,27323,27324,27325,
82532 27326,27327,27328,27329,27330,27331,27332,27333,27334,27335,27336,27337,
82533 27338,27339,27340,27341,27342,27343,27344,27345,27346,27347,27348,27349,
82534 27350,27351,27352,27353,27354,27355,27356,27357,27358,27359,27360,27361,
82535 27362,27363,27364,27365,27366,27367,27368,27369,27370,27371,27372,27373,
82536 27374,27375,27376,27377,27378,27379,27380,27381,27382,27383,27384,27385,
82537 27386,27387,27388,27389,27390,27391,27392,27393,27394,27395,27396,27397,
82538 27398,27399,27400,27401,27402,27403,27404,27405,27406,27407,27408,27409,
82539 27410,27411,27412,27413,27414,27415,27416,27417,27418,27419,27420,27421,
82540 27422,27423,27424,27425,27426,27427,27428,27429,27430,27431,27432,27433,
82541 27434,27435,27436,27437,27438,27439,27440,27441,27442,27443,27444,27445,
82542 27446,27447,27448,27449,27450,27451,27452,27453,27454,27455,27456,27457,
82543 27458,27459,27460,27461,27462,27463,27464,27465,27466,27467,27468,27469,
82544 27470,27471,27472,27473,27474,27475,27476,27477,27478,27479,27480,27481,
82545 27482,27483,27484,27485,27486,27487,27488,27489,27490,27491,27492,27493,
82546 27494,27495,27496,27497,27498,27499,27500,27501,27502,27503,27504,27505,
82547 27506,27507,27508,27509,27510,27511,27512,27513,27514,27515,27516,27517,
82548 27518,27519,27520,27521,27522,27523,27524,27525,27526,27527,27528,27529,
82549 27530,27531,27532,27533,27534,27535,27536,27537,27538,27539,27540,27541,
82550 27542,27543,27544,27545,27546,27547,27548,27549,27550,27551,27552,27553,
82551 27554,27555,27556,27557,27558,27559,27560,27561,27562,27563,27564,27565,
82552 27566,27567,27568,27569,27570,27571,27572,27573,27574,27575,27576,27577,
82553 27578,27579,27580,27581,27582,27583,27584,27585,27586,27587,27588,27589,
82554 27590,27591,27592,27593,27594,27595,27596,27597,27598,27599,27600,27601,
82555 27602,27603,27604,27605,27606,27607,27608,27609,27610,27611,27612,27613,
82556 27614,27615,27616,27617,27618,27619,27620,27621,27622,27623,27624,27625,
82557 27626,27627,27628,27629,27630,27631,27632,27633,27634,27635,27636,27637,
82558 27638,27639,27640,27641,27642,27643,27644,27645,27646,27647,27648,27649,
82559 27650,27651,27652,27653,27654,27655,27656,27657,27658,27659,27660,27661,
82560 27662,27663,27664,27665,27666,27667,27668,27669,27670,27671,27672,27673,
82561 27674,27675,27676,27677,27678,27679,27680,27681,27682,27683,27684,27685,
82562 27686,27687,27688,27689,27690,27691,27692,27693,27694,27695,27696,27697,
82563 27698,27699,27700,27701,27702,27703,27704,27705,27706,27707,27708,27709,
82564 27710,27711,27712,27713,27714,27715,27716,27717,27718,27719,27720,27721,
82565 27722,27723,27724,27725,27726,27727,27728,27729,27730,27731,27732,27733,
82566 27734,27735,27736,27737,27738,27739,27740,27741,27742,27743,27744,27745,
82567 27746,27747,27748,27749,27750,27751,27752,27753,27754,27755,27756,27757,
82568 27758,27759,27760,27761,27762,27763,27764,27765,27766,27767,27768,27769,
82569 27770,27771,27772,27773,27774,27775,27776,27777,27778,27779,27780,27781,
82570 27782,27783,27784,27785,27786,27787,27788,27789,27790,27791,27792,27793,
82571 27794,27795,27796,27797,27798,27799,27800,27801,27802,27803,27804,27805,
82572 27806,27807,27808,27809,27810,27811,27812,27813,27814,27815,27816,27817,
82573 27818,27819,27820,27821,27822,27823,27824,27825,27826,27827,27828,27829,
82574 27830,27831,27832,27833,27834,27835,27836,27837,27838,27839,27840,27841,
82575 27842,27843,27844,27845,27846,27847,27848,27849,27850,27851,27852,27853,
82576 27854,27855,27856,27857,27858,27859,27860,27861,27862,27863,27864,27865,
82577 27866,27867,27868,27869,27870,27871,27872,27873,27874,27875,27876,27877,
82578 27878,27879,27880,27881,27882,27883,27884,27885,27886,27887,27888,27889,
82579 27890,27891,27892,27893,27894,27895,27896,27897,27898,27899,27900,27901,
82580 27902,27903,27904,27905,27906,27907,27908,27909,27910,27911,27912,27913,
82581 27914,27915,27916,27917,27918,27919,27920,27921,27922,27923,27924,27925,
82582 27926,27927,27928,27929,27930,27931,27932,27933,27934,27935,27936,27937,
82583 27938,27939,27940,27941,27942,27943,27944,27945,27946,27947,27948,27949,
82584 27950,27951,27952,27953,27954,27955,27956,27957,27958,27959,27960,27961,
82585 27962,27963,27964,27965,27966,27967,27968,27969,27970,27971,27972,27973,
82586 27974,27975,27976,27977,27978,27979,27980,27981,27982,27983,27984,27985,
82587 27986,27987,27988,27989,27990,27991,27992,27993,27994,27995,27996,27997,
82588 27998,27999,28000,28001,28002,28003,28004,28005,28006,28007,28008,28009,
82589 28010,28011,28012,28013,28014,28015,28016,28017,28018,28019,28020,28021,
82590 28022,28023,28024,28025,28026,28027,28028,28029,28030,28031,28032,28033,
82591 28034,28035,28036,28037,28038,28039,28040,28041,28042,28043,28044,28045,
82592 28046,28047,28048,28049,28050,28051,28052,28053,28054,28055,28056,28057,
82593 28058,28059,28060,28061,28062,28063,28064,28065,28066,28067,28068,28069,
82594 28070,28071,28072,28073,28074,28075,28076,28077,28078,28079,28080,28081,
82595 28082,28083,28084,28085,28086,28087,28088,28089,28090,28091,28092,28093,
82596 28094,28095,28096,28097,28098,28099,28100,28101,28102,28103,28104,28105,
82597 28106,28107,28108,28109,28110,28111,28112,28113,28114,28115,28116,28117,
82598 28118,28119,28120,28121,28122,28123,28124,28125,28126,28127,28128,28129,
82599 28130,28131,28132,28133,28134,28135,28136,28137,28138,28139,28140,28141,
82600 28142,28143,28144,28145,28146,28147,28148,28149,28150,28151,28152,28153,
82601 28154,28155,28156,28157,28158,28159,28160,28161,28162,28163,28164,28165,
82602 28166,28167,28168,28169,28170,28171,28172,28173,28174,28175,28176,28177,
82603 28178,28179,28180,28181,28182,28183,28184,28185,28186,28187,28188,28189,
82604 28190,28191,28192,28193,28194,28195,28196,28197,28198,28199,28200,28201,
82605 28202,28203,28204,28205,28206,28207,28208,28209,28210,28211,28212,28213,
82606 28214,28215,28216,28217,28218,28219,28220,28221,28222,28223,28224,28225,
82607 28226,28227,28228,28229,28230,28231,28232,28233,28234,28235,28236,28237,
82608 28238,28239,28240,28241,28242,28243,28244,28245,28246,28247,28248,28249,
82609 28250,28251,28252,28253,28254,28255,28256,28257,28258,28259,28260,28261,
82610 28262,28263,28264,28265,28266,28267,28268,28269,28270,28271,28272,28273,
82611 28274,28275,28276,28277,28278,28279,28280,28281,28282,28283,28284,28285,
82612 28286,28287,28288,28289,28290,28291,28292,28293,28294,28295,28296,28297,
82613 28298,28299,28300,28301,28302,28303,28304,28305,28306,28307,28308,28309,
82614 28310,28311,28312,28313,28314,28315,28316,28317,28318,28319,28320,28321,
82615 28322,28323,28324,28325,28326,28327,28328,28329,28330,28331,28332,28333,
82616 28334,28335,28336,28337,28338,28339,28340,28341,28342,28343,28344,28345,
82617 28346,28347,28348,28349,28350,28351,28352,28353,28354,28355,28356,28357,
82618 28358,28359,28360,28361,28362,28363,28364,28365,28366,28367,28368,28369,
82619 28370,28371,28372,28373,28374,28375,28376,28377,28378,28379,28380,28381,
82620 28382,28383,28384,28385,28386,28387,28388,28389,28390,28391,28392,28393,
82621 28394,28395,28396,28397,28398,28399,28400,28401,28402,28403,28404,28405,
82622 28406,28407,28408,28409,28410,28411,28412,28413,28414,28415,28416,28417,
82623 28418,28419,28420,28421,28422,28423,28424,28425,28426,28427,28428,28429,
82624 28430,28431,28432,28433,28434,28435,28436,28437,28438,28439,28440,28441,
82625 28442,28443,28444,28445,28446,28447,28448,28449,28450,28451,28452,28453,
82626 28454,28455,28456,28457,28458,28459,28460,28461,28462,28463,28464,28465,
82627 28466,28467,28468,28469,28470,28471,28472,28473,28474,28475,28476,28477,
82628 28478,28479,28480,28481,28482,28483,28484,28485,28486,28487,28488,28489,
82629 28490,28491,28492,28493,28494,28495,28496,28497,28498,28499,28500,28501,
82630 28502,28503,28504,28505,28506,28507,28508,28509,28510,28511,28512,28513,
82631 28514,28515,28516,28517,28518,28519,28520,28521,28522,28523,28524,28525,
82632 28526,28527,28528,28529,28530,28531,28532,28533,28534,28535,28536,28537,
82633 28538,28539,28540,28541,28542,28543,28544,28545,28546,28547,28548,28549,
82634 28550,28551,28552,28553,28554,28555,28556,28557,28558,28559,28560,28561,
82635 28562,28563,28564,28565,28566,28567,28568,28569,28570,28571,28572,28573,
82636 28574,28575,28576,28577,28578,28579,28580,28581,28582,28583,28584,28585,
82637 28586,28587,28588,28589,28590,28591,28592,28593,28594,28595,28596,28597,
82638 28598,28599,28600,28601,28602,28603,28604,28605,28606,28607,28608,28609,
82639 28610,28611,28612,28613,28614,28615,28616,28617,28618,28619,28620,28621,
82640 28622,28623,28624,28625,28626,28627,28628,28629,28630,28631,28632,28633,
82641 28634,28635,28636,28637,28638,28639,28640,28641,28642,28643,28644,28645,
82642 28646,28647,28648,28649,28650,28651,28652,28653,28654,28655,28656,28657,
82643 28658,28659,28660,28661,28662,28663,28664,28665,28666,28667,28668,28669,
82644 28670,28671,28672,28673,28674,28675,28676,28677,28678,28679,28680,28681,
82645 28682,28683,28684,28685,28686,28687,28688,28689,28690,28691,28692,28693,
82646 28694,28695,28696,28697,28698,28699,28700,28701,28702,28703,28704,28705,
82647 28706,28707,28708,28709,28710,28711,28712,28713,28714,28715,28716,28717,
82648 28718,28719,28720,28721,28722,28723,28724,28725,28726,28727,28728,28729,
82649 28730,28731,28732,28733,28734,28735,28736,28737,28738,28739,28740,28741,
82650 28742,28743,28744,28745,28746,28747,28748,28749,28750,28751,28752,28753,
82651 28754,28755,28756,28757,28758,28759,28760,28761,28762,28763,28764,28765,
82652 28766,28767,28768,28769,28770,28771,28772,28773,28774,28775,28776,28777,
82653 28778,28779,28780,28781,28782,28783,28784,28785,28786,28787,28788,28789,
82654 28790,28791,28792,28793,28794,28795,28796,28797,28798,28799,28800,28801,
82655 28802,28803,28804,28805,28806,28807,28808,28809,28810,28811,28812,28813,
82656 28814,28815,28816,28817,28818,28819,28820,28821,28822,28823,28824,28825,
82657 28826,28827,28828,28829,28830,28831,28832,28833,28834,28835,28836,28837,
82658 28838,28839,28840,28841,28842,28843,28844,28845,28846,28847,28848,28849,
82659 28850,28851,28852,28853,28854,28855,28856,28857,28858,28859,28860,28861,
82660 28862,28863,28864,28865,28866,28867,28868,28869,28870,28871,28872,28873,
82661 28874,28875,28876,28877,28878,28879,28880,28881,28882,28883,28884,28885,
82662 28886,28887,28888,28889,28890,28891,28892,28893,28894,28895,28896,28897,
82663 28898,28899,28900,28901,28902,28903,28904,28905,28906,28907,28908,28909,
82664 28910,28911,28912,28913,28914,28915,28916,28917,28918,28919,28920,28921,
82665 28922,28923,28924,28925,28926,28927,28928,28929,28930,28931,28932,28933,
82666 28934,28935,28936,28937,28938,28939,28940,28941,28942,28943,28944,28945,
82667 28946,28947,28948,28949,28950,28951,28952,28953,28954,28955,28956,28957,
82668 28958,28959,28960,28961,28962,28963,28964,28965,28966,28967,28968,28969,
82669 28970,28971,28972,28973,28974,28975,28976,28977,28978,28979,28980,28981,
82670 28982,28983,28984,28985,28986,28987,28988,28989,28990,28991,28992,28993,
82671 28994,28995,28996,28997,28998,28999,29000,29001,29002,29003,29004,29005,
82672 29006,29007,29008,29009,29010,29011,29012,29013,29014,29015,29016,29017,
82673 29018,29019,29020,29021,29022,29023,29024,29025,29026,29027,29028,29029,
82674 29030,29031,29032,29033,29034,29035,29036,29037,29038,29039,29040,29041,
82675 29042,29043,29044,29045,29046,29047,29048,29049,29050,29051,29052,29053,
82676 29054,29055,29056,29057,29058,29059,29060,29061,29062,29063,29064,29065,
82677 29066,29067,29068,29069,29070,29071,29072,29073,29074,29075,29076,29077,
82678 29078,29079,29080,29081,29082,29083,29084,29085,29086,29087,29088,29089,
82679 29090,29091,29092,29093,29094,29095,29096,29097,29098,29099,29100,29101,
82680 29102,29103,29104,29105,29106,29107,29108,29109,29110,29111,29112,29113,
82681 29114,29115,29116,29117,29118,29119,29120,29121,29122,29123,29124,29125,
82682 29126,29127,29128,29129,29130,29131,29132,29133,29134,29135,29136,29137,
82683 29138,29139,29140,29141,29142,29143,29144,29145,29146,29147,29148,29149,
82684 29150,29151,29152,29153,29154,29155,29156,29157,29158,29159,29160,29161,
82685 29162,29163,29164,29165,29166,29167,29168,29169,29170,29171,29172,29173,
82686 29174,29175,29176,29177,29178,29179,29180,29181,29182,29183,29184,29185,
82687 29186,29187,29188,29189,29190,29191,29192,29193,29194,29195,29196,29197,
82688 29198,29199,29200,29201,29202,29203,29204,29205,29206,29207,29208,29209,
82689 29210,29211,29212,29213,29214,29215,29216,29217,29218,29219,29220,29221,
82690 29222,29223,29224,29225,29226,29227,29228,29229,29230,29231,29232,29233,
82691 29234,29235,29236,29237,29238,29239,29240,29241,29242,29243,29244,29245,
82692 29246,29247,29248,29249,29250,29251,29252,29253,29254,29255,29256,29257,
82693 29258,29259,29260,29261,29262,29263,29264,29265,29266,29267,29268,29269,
82694 29270,29271,29272,29273,29274,29275,29276,29277,29278,29279,29280,29281,
82695 29282,29283,29284,29285,29286,29287,29288,29289,29290,29291,29292,29293,
82696 29294,29295,29296,29297,29298,29299,29300,29301,29302,29303,29304,29305,
82697 29306,29307,29308,29309,29310,29311,29312,29313,29314,29315,29316,29317,
82698 29318,29319,29320,29321,29322,29323,29324,29325,29326,29327,29328,29329,
82699 29330,29331,29332,29333,29334,29335,29336,29337,29338,29339,29340,29341,
82700 29342,29343,29344,29345,29346,29347,29348,29349,29350,29351,29352,29353,
82701 29354,29355,29356,29357,29358,29359,29360,29361,29362,29363,29364,29365,
82702 29366,29367,29368,29369,29370,29371,29372,29373,29374,29375,29376,29377,
82703 29378,29379,29380,29381,29382,29383,29384,29385,29386,29387,29388,29389,
82704 29390,29391,29392,29393,29394,29395,29396,29397,29398,29399,29400,29401,
82705 29402,29403,29404,29405,29406,29407,29408,29409,29410,29411,29412,29413,
82706 29414,29415,29416,29417,29418,29419,29420,29421,29422,29423,29424,29425,
82707 29426,29427,29428,29429,29430,29431,29432,29433,29434,29435,29436,29437,
82708 29438,29439,29440,29441,29442,29443,29444,29445,29446,29447,29448,29449,
82709 29450,29451,29452,29453,29454,29455,29456,29457,29458,29459,29460,29461,
82710 29462,29463,29464,29465,29466,29467,29468,29469,29470,29471,29472,29473,
82711 29474,29475,29476,29477,29478,29479,29480,29481,29482,29483,29484,29485,
82712 29486,29487,29488,29489,29490,29491,29492,29493,29494,29495,29496,29497,
82713 29498,29499,29500,29501,29502,29503,29504,29505,29506,29507,29508,29509,
82714 29510,29511,29512,29513,29514,29515,29516,29517,29518,29519,29520,29521,
82715 29522,29523,29524,29525,29526,29527,29528,29529,29530,29531,29532,29533,
82716 29534,29535,29536,29537,29538,29539,29540,29541,29542,29543,29544,29545,
82717 29546,29547,29548,29549,29550,29551,29552,29553,29554,29555,29556,29557,
82718 29558,29559,29560,29561,29562,29563,29564,29565,29566,29567,29568,29569,
82719 29570,29571,29572,29573,29574,29575,29576,29577,29578,29579,29580,29581,
82720 29582,29583,29584,29585,29586,29587,29588,29589,29590,29591,29592,29593,
82721 29594,29595,29596,29597,29598,29599,29600,29601,29602,29603,29604,29605,
82722 29606,29607,29608,29609,29610,29611,29612,29613,29614,29615,29616,29617,
82723 29618,29619,29620,29621,29622,29623,29624,29625,29626,29627,29628,29629,
82724 29630,29631,29632,29633,29634,29635,29636,29637,29638,29639,29640,29641,
82725 29642,29643,29644,29645,29646,29647,29648,29649,29650,29651,29652,29653,
82726 29654,29655,29656,29657,29658,29659,29660,29661,29662,29663,29664,29665,
82727 29666,29667,29668,29669,29670,29671,29672,29673,29674,29675,29676,29677,
82728 29678,29679,29680,29681,29682,29683,29684,29685,29686,29687,29688,29689,
82729 29690,29691,29692,29693,29694,29695,29696,29697,29698,29699,29700,29701,
82730 29702,29703,29704,29705,29706,29707,29708,29709,29710,29711,29712,29713,
82731 29714,29715,29716,29717,29718,29719,29720,29721,29722,29723,29724,29725,
82732 29726,29727,29728,29729,29730,29731,29732,29733,29734,29735,29736,29737,
82733 29738,29739,29740,29741,29742,29743,29744,29745,29746,29747,29748,29749,
82734 29750,29751,29752,29753,29754,29755,29756,29757,29758,29759,29760,29761,
82735 29762,29763,29764,29765,29766,29767,29768,29769,29770,29771,29772,29773,
82736 29774,29775,29776,29777,29778,29779,29780,29781,29782,29783,29784,29785,
82737 29786,29787,29788,29789,29790,29791,29792,29793,29794,29795,29796,29797,
82738 29798,29799,29800,29801,29802,29803,29804,29805,29806,29807,29808,29809,
82739 29810,29811,29812,29813,29814,29815,29816,29817,29818,29819,29820,29821,
82740 29822,29823,29824,29825,29826,29827,29828,29829,29830,29831,29832,29833,
82741 29834,29835,29836,29837,29838,29839,29840,29841,29842,29843,29844,29845,
82742 29846,29847,29848,29849,29850,29851,29852,29853,29854,29855,29856,29857,
82743 29858,29859,29860,29861,29862,29863,29864,29865,29866,29867,29868,29869,
82744 29870,29871,29872,29873,29874,29875,29876,29877,29878,29879,29880,29881,
82745 29882,29883,29884,29885,29886,29887,29888,29889,29890,29891,29892,29893,
82746 29894,29895,29896,29897,29898,29899,29900,29901,29902,29903,29904,29905,
82747 29906,29907,29908,29909,29910,29911,29912,29913,29914,29915,29916,29917,
82748 29918,29919,29920,29921,29922,29923,29924,29925,29926,29927,29928,29929,
82749 29930,29931,29932,29933,29934,29935,29936,29937,29938,29939,29940,29941,
82750 29942,29943,29944,29945,29946,29947,29948,29949,29950,29951,29952,29953,
82751 29954,29955,29956,29957,29958,29959,29960,29961,29962,29963,29964,29965,
82752 29966,29967,29968,29969,29970,29971,29972,29973,29974,29975,29976,29977,
82753 29978,29979,29980,29981,29982,29983,29984,29985,29986,29987,29988,29989,
82754 29990,29991,29992,29993,29994,29995,29996,29997,29998,29999,30000,30001,
82755 30002,30003,30004,30005,30006,30007,30008,30009,30010,30011,30012,30013,
82756 30014,30015,30016,30017,30018,30019,30020,30021,30022,30023,30024,30025,
82757 30026,30027,30028,30029,30030,30031,30032,30033,30034,30035,30036,30037,
82758 30038,30039,30040,30041,30042,30043,30044,30045,30046,30047,30048,30049,
82759 30050,30051,30052,30053,30054,30055,30056,30057,30058,30059,30060,30061,
82760 30062,30063,30064,30065,30066,30067,30068,30069,30070,30071,30072,30073,
82761 30074,30075,30076,30077,30078,30079,30080,30081,30082,30083,30084,30085,
82762 30086,30087,30088,30089,30090,30091,30092,30093,30094,30095,30096,30097,
82763 30098,30099,30100,30101,30102,30103,30104,30105,30106,30107,30108,30109,
82764 30110,30111,30112,30113,30114,30115,30116,30117,30118,30119,30120,30121,
82765 30122,30123,30124,30125,30126,30127,30128,30129,30130,30131,30132,30133,
82766 30134,30135,30136,30137,30138,30139,30140,30141,30142,30143,30144,30145,
82767 30146,30147,30148,30149,30150,30151,30152,30153,30154,30155,30156,30157,
82768 30158,30159,30160,30161,30162,30163,30164,30165,30166,30167,30168,30169,
82769 30170,30171,30172,30173,30174,30175,30176,30177,30178,30179,30180,30181,
82770 30182,30183,30184,30185,30186,30187,30188,30189,30190,30191,30192,30193,
82771 30194,30195,30196,30197,30198,30199,30200,30201,30202,30203,30204,30205,
82772 30206,30207,30208,30209,30210,30211,30212,30213,30214,30215,30216,30217,
82773 30218,30219,30220,30221,30222,30223,30224,30225,30226,30227,30228,30229,
82774 30230,30231,30232,30233,30234,30235,30236,30237,30238,30239,30240,30241,
82775 30242,30243,30244,30245,30246,30247,30248,30249,30250,30251,30252,30253,
82776 30254,30255,30256,30257,30258,30259,30260,30261,30262,30263,30264,30265,
82777 30266,30267,30268,30269,30270,30271,30272,30273,30274,30275,30276,30277,
82778 30278,30279,30280,30281,30282,30283,30284,30285,30286,30287,30288,30289,
82779 30290,30291,30292,30293,30294,30295,30296,30297,30298,30299,30300,30301,
82780 30302,30303,30304,30305,30306,30307,30308,30309,30310,30311,30312,30313,
82781 30314,30315,30316,30317,30318,30319,30320,30321,30322,30323,30324,30325,
82782 30326,30327,30328,30329,30330,30331,30332,30333,30334,30335,30336,30337,
82783 30338,30339,30340,30341,30342,30343,30344,30345,30346,30347,30348,30349,
82784 30350,30351,30352,30353,30354,30355,30356,30357,30358,30359,30360,30361,
82785 30362,30363,30364,30365,30366,30367,30368,30369,30370,30371,30372,30373,
82786 30374,30375,30376,30377,30378,30379,30380,30381,30382,30383,30384,30385,
82787 30386,30387,30388,30389,30390,30391,30392,30393,30394,30395,30396,30397,
82788 30398,30399,30400,30401,30402,30403,30404,30405,30406,30407,30408,30409,
82789 30410,30411,30412,30413,30414,30415,30416,30417,30418,30419,30420,30421,
82790 30422,30423,30424,30425,30426,30427,30428,30429,30430,30431,30432,30433,
82791 30434,30435,30436,30437,30438,30439,30440,30441,30442,30443,30444,30445,
82792 30446,30447,30448,30449,30450,30451,30452,30453,30454,30455,30456,30457,
82793 30458,30459,30460,30461,30462,30463,30464,30465,30466,30467,30468,30469,
82794 30470,30471,30472,30473,30474,30475,30476,30477,30478,30479,30480,30481,
82795 30482,30483,30484,30485,30486,30487,30488,30489,30490,30491,30492,30493,
82796 30494,30495,30496,30497,30498,30499,30500,30501,30502,30503,30504,30505,
82797 30506,30507,30508,30509,30510,30511,30512,30513,30514,30515,30516,30517,
82798 30518,30519,30520,30521,30522,30523,30524,30525,30526,30527,30528,30529,
82799 30530,30531,30532,30533,30534,30535,30536,30537,30538,30539,30540,30541,
82800 30542,30543,30544,30545,30546,30547,30548,30549,30550,30551,30552,30553,
82801 30554,30555,30556,30557,30558,30559,30560,30561,30562,30563,30564,30565,
82802 30566,30567,30568,30569,30570,30571,30572,30573,30574,30575,30576,30577,
82803 30578,30579,30580,30581,30582,30583,30584,30585,30586,30587,30588,30589,
82804 30590,30591,30592,30593,30594,30595,30596,30597,30598,30599,30600,30601,
82805 30602,30603,30604,30605,30606,30607,30608,30609,30610,30611,30612,30613,
82806 30614,30615,30616,30617,30618,30619,30620,30621,30622,30623,30624,30625,
82807 30626,30627,30628,30629,30630,30631,30632,30633,30634,30635,30636,30637,
82808 30638,30639,30640,30641,30642,30643,30644,30645,30646,30647,30648,30649,
82809 30650,30651,30652,30653,30654,30655,30656,30657,30658,30659,30660,30661,
82810 30662,30663,30664,30665,30666,30667,30668,30669,30670,30671,30672,30673,
82811 30674,30675,30676,30677,30678,30679,30680,30681,30682,30683,30684,30685,
82812 30686,30687,30688,30689,30690,30691,30692,30693,30694,30695,30696,30697,
82813 30698,30699,30700,30701,30702,30703,30704,30705,30706,30707,30708,30709,
82814 30710,30711,30712,30713,30714,30715,30716,30717,30718,30719,30720,30721,
82815 30722,30723,30724,30725,30726,30727,30728,30729,30730,30731,30732,30733,
82816 30734,30735,30736,30737,30738,30739,30740,30741,30742,30743,30744,30745,
82817 30746,30747,30748,30749,30750,30751,30752,30753,30754,30755,30756,30757,
82818 30758,30759,30760,30761,30762,30763,30764,30765,30766,30767,30768,30769,
82819 30770,30771,30772,30773,30774,30775,30776,30777,30778,30779,30780,30781,
82820 30782,30783,30784,30785,30786,30787,30788,30789,30790,30791,30792,30793,
82821 30794,30795,30796,30797,30798,30799,30800,30801,30802,30803,30804,30805,
82822 30806,30807,30808,30809,30810,30811,30812,30813,30814,30815,30816,30817,
82823 30818,30819,30820,30821,30822,30823,30824,30825,30826,30827,30828,30829,
82824 30830,30831,30832,30833,30834,30835,30836,30837,30838,30839,30840,30841,
82825 30842,30843,30844,30845,30846,30847,30848,30849,30850,30851,30852,30853,
82826 30854,30855,30856,30857,30858,30859,30860,30861,30862,30863,30864,30865,
82827 30866,30867,30868,30869,30870,30871,30872,30873,30874,30875,30876,30877,
82828 30878,30879,30880,30881,30882,30883,30884,30885,30886,30887,30888,30889,
82829 30890,30891,30892,30893,30894,30895,30896,30897,30898,30899,30900,30901,
82830 30902,30903,30904,30905,30906,30907,30908,30909,30910,30911,30912,30913,
82831 30914,30915,30916,30917,30918,30919,30920,30921,30922,30923,30924,30925,
82832 30926,30927,30928,30929,30930,30931,30932,30933,30934,30935,30936,30937,
82833 30938,30939,30940,30941,30942,30943,30944,30945,30946,30947,30948,30949,
82834 30950,30951,30952,30953,30954,30955,30956,30957,30958,30959,30960,30961,
82835 30962,30963,30964,30965,30966,30967,30968,30969,30970,30971,30972,30973,
82836 30974,30975,30976,30977,30978,30979,30980,30981,30982,30983,30984,30985,
82837 30986,30987,30988,30989,30990,30991,30992,30993,30994,30995,30996,30997,
82838 30998,30999,31000,31001,31002,31003,31004,31005,31006,31007,31008,31009,
82839 31010,31011,31012,31013,31014,31015,31016,31017,31018,31019,31020,31021,
82840 31022,31023,31024,31025,31026,31027,31028,31029,31030,31031,31032,31033,
82841 31034,31035,31036,31037,31038,31039,31040,31041,31042,31043,31044,31045,
82842 31046,31047,31048,31049,31050,31051,31052,31053,31054,31055,31056,31057,
82843 31058,31059,31060,31061,31062,31063,31064,31065,31066,31067,31068,31069,
82844 31070,31071,31072,31073,31074,31075,31076,31077,31078,31079,31080,31081,
82845 31082,31083,31084,31085,31086,31087,31088,31089,31090,31091,31092,31093,
82846 31094,31095,31096,31097,31098,31099,31100,31101,31102,31103,31104,31105,
82847 31106,31107,31108,31109,31110,31111,31112,31113,31114,31115,31116,31117,
82848 31118,31119,31120,31121,31122,31123,31124,31125,31126,31127,31128,31129,
82849 31130,31131,31132,31133,31134,31135,31136,31137,31138,31139,31140,31141,
82850 31142,31143,31144,31145,31146,31147,31148,31149,31150,31151,31152,31153,
82851 31154,31155,31156,31157,31158,31159,31160,31161,31162,31163,31164,31165,
82852 31166,31167,31168,31169,31170,31171,31172,31173,31174,31175,31176,31177,
82853 31178,31179,31180,31181,31182,31183,31184,31185,31186,31187,31188,31189,
82854 31190,31191,31192,31193,31194,31195,31196,31197,31198,31199,31200,31201,
82855 31202,31203,31204,31205,31206,31207,31208,31209,31210,31211,31212,31213,
82856 31214,31215,31216,31217,31218,31219,31220,31221,31222,31223,31224,31225,
82857 31226,31227,31228,31229,31230,31231,31232,31233,31234,31235,31236,31237,
82858 31238,31239,31240,31241,31242,31243,31244,31245,31246,31247,31248,31249,
82859 31250,31251,31252,31253,31254,31255,31256,31257,31258,31259,31260,31261,
82860 31262,31263,31264,31265,31266,31267,31268,31269,31270,31271,31272,31273,
82861 31274,31275,31276,31277,31278,31279,31280,31281,31282,31283,31284,31285,
82862 31286,31287,31288,31289,31290,31291,31292,31293,31294,31295,31296,31297,
82863 31298,31299,31300,31301,31302,31303,31304,31305,31306,31307,31308,31309,
82864 31310,31311,31312,31313,31314,31315,31316,31317,31318,31319,31320,31321,
82865 31322,31323,31324,31325,31326,31327,31328,31329,31330,31331,31332,31333,
82866 31334,31335,31336,31337,31338,31339,31340,31341,31342,31343,31344,31345,
82867 31346,31347,31348,31349,31350,31351,31352,31353,31354,31355,31356,31357,
82868 31358,31359,31360,31361,31362,31363,31364,31365,31366,31367,31368,31369,
82869 31370,31371,31372,31373,31374,31375,31376,31377,31378,31379,31380,31381,
82870 31382,31383,31384,31385,31386,31387,31388,31389,31390,31391,31392,31393,
82871 31394,31395,31396,31397,31398,31399,31400,31401,31402,31403,31404,31405,
82872 31406,31407,31408,31409,31410,31411,31412,31413,31414,31415,31416,31417,
82873 31418,31419,31420,31421,31422,31423,31424,31425,31426,31427,31428,31429,
82874 31430,31431,31432,31433,31434,31435,31436,31437,31438,31439,31440,31441,
82875 31442,31443,31444,31445,31446,31447,31448,31449,31450,31451,31452,31453,
82876 31454,31455,31456,31457,31458,31459,31460,31461,31462,31463,31464,31465,
82877 31466,31467,31468,31469,31470,31471,31472,31473,31474,31475,31476,31477,
82878 31478,31479,31480,31481,31482,31483,31484,31485,31486,31487,31488,31489,
82879 31490,31491,31492,31493,31494,31495,31496,31497,31498,31499,31500,31501,
82880 31502,31503,31504,31505,31506,31507,31508,31509,31510,31511,31512,31513,
82881 31514,31515,31516,31517,31518,31519,31520,31521,31522,31523,31524,31525,
82882 31526,31527,31528,31529,31530,31531,31532,31533,31534,31535,31536,31537,
82883 31538,31539,31540,31541,31542,31543,31544,31545,31546,31547,31548,31549,
82884 31550,31551,31552,31553,31554,31555,31556,31557,31558,31559,31560,31561,
82885 31562,31563,31564,31565,31566,31567,31568,31569,31570,31571,31572,31573,
82886 31574,31575,31576,31577,31578,31579,31580,31581,31582,31583,31584,31585,
82887 31586,31587,31588,31589,31590,31591,31592,31593,31594,31595,31596,31597,
82888 31598,31599,31600,31601,31602,31603,31604,31605,31606,31607,31608,31609,
82889 31610,31611,31612,31613,31614,31615,31616,31617,31618,31619,31620,31621,
82890 31622,31623,31624,31625,31626,31627,31628,31629,31630,31631,31632,31633,
82891 31634,31635,31636,31637,31638,31639,31640,31641,31642,31643,31644,31645,
82892 31646,31647,31648,31649,31650,31651,31652,31653,31654,31655,31656,31657,
82893 31658,31659,31660,31661,31662,31663,31664,31665,31666,31667,31668,31669,
82894 31670,31671,31672,31673,31674,31675,31676,31677,31678,31679,31680,31681,
82895 31682,31683,31684,31685,31686,31687,31688,31689,31690,31691,31692,31693,
82896 31694,31695,31696,31697,31698,31699,31700,31701,31702,31703,31704,31705,
82897 31706,31707,31708,31709,31710,31711,31712,31713,31714,31715,31716,31717,
82898 31718,31719,31720,31721,31722,31723,31724,31725,31726,31727,31728,31729,
82899 31730,31731,31732,31733,31734,31735,31736,31737,31738,31739,31740,31741,
82900 31742,31743,31744,31745,31746,31747,31748,31749,31750,31751,31752,31753,
82901 31754,31755,31756,31757,31758,31759,31760,31761,31762,31763,31764,31765,
82902 31766,31767,31768,31769,31770,31771,31772,31773,31774,31775,31776,31777,
82903 31778,31779,31780,31781,31782,31783,31784,31785,31786,31787,31788,31789,
82904 31790,31791,31792,31793,31794,31795,31796,31797,31798,31799,31800,31801,
82905 31802,31803,31804,31805,31806,31807,31808,31809,31810,31811,31812,31813,
82906 31814,31815,31816,31817,31818,31819,31820,31821,31822,31823,31824,31825,
82907 31826,31827,31828,31829,31830,31831,31832,31833,31834,31835,31836,31837,
82908 31838,31839,31840,31841,31842,31843,31844,31845,31846,31847,31848,31849,
82909 31850,31851,31852,31853,31854,31855,31856,31857,31858,31859,31860,31861,
82910 31862,31863,31864,31865,31866,31867,31868,31869,31870,31871,31872,31873,
82911 31874,31875,31876,31877,31878,31879,31880,31881,31882,31883,31884,31885,
82912 31886,31887,31888,31889,31890,31891,31892,31893,31894,31895,31896,31897,
82913 31898,31899,31900,31901,31902,31903,31904,31905,31906,31907,31908,31909,
82914 31910,31911,31912,31913,31914,31915,31916,31917,31918,31919,31920,31921,
82915 31922,31923,31924,31925,31926,31927,31928,31929,31930,31931,31932,31933,
82916 31934,31935,31936,31937,31938,31939,31940,31941,31942,31943,31944,31945,
82917 31946,31947,31948,31949,31950,31951,31952,31953,31954,31955,31956,31957,
82918 31958,31959,31960,31961,31962,31963,31964,31965,31966,31967,31968,31969,
82919 31970,31971,31972,31973,31974,31975,31976,31977,31978,31979,31980,31981,
82920 31982,31983,31984,31985,31986,31987,31988,31989,31990,31991,31992,31993,
82921 31994,31995,31996,31997,31998,31999,32000,32001,32002,32003,32004,32005,
82922 32006,32007,32008,32009,32010,32011,32012,32013,32014,32015,32016,32017,
82923 32018,32019,32020,32021,32022,32023,32024,32025,32026,32027,32028,32029,
82924 32030,32031,32032,32033,32034,32035,32036,32037,32038,32039,32040,32041,
82925 32042,32043,32044,32045,32046,32047,32048,32049,32050,32051,32052,32053,
82926 32054,32055,32056,32057,32058,32059,32060,32061,32062,32063,32064,32065,
82927 32066,32067,32068,32069,32070,32071,32072,32073,32074,32075,32076,32077,
82928 32078,32079,32080,32081,32082,32083,32084,32085,32086,32087,32088,32089,
82929 32090,32091,32092,32093,32094,32095,32096,32097,32098,32099,32100,32101,
82930 32102,32103,32104,32105,32106,32107,32108,32109,32110,32111,32112,32113,
82931 32114,32115,32116,32117,32118,32119,32120,32121,32122,32123,32124,32125,
82932 32126,32127,32128,32129,32130,32131,32132,32133,32134,32135,32136,32137,
82933 32138,32139,32140,32141,32142,32143,32144,32145,32146,32147,32148,32149,
82934 32150,32151,32152,32153,32154,32155,32156,32157,32158,32159,32160,32161,
82935 32162,32163,32164,32165,32166,32167,32168,32169,32170,32171,32172,32173,
82936 32174,32175,32176,32177,32178,32179,32180,32181,32182,32183,32184,32185,
82937 32186,32187,32188,32189,32190,32191,32192,32193,32194,32195,32196,32197,
82938 32198,32199,32200,32201,32202,32203,32204,32205,32206,32207,32208,32209,
82939 32210,32211,32212,32213,32214,32215,32216,32217,32218,32219,32220,32221,
82940 32222,32223,32224,32225,32226,32227,32228,32229,32230,32231,32232,32233,
82941 32234,32235,32236,32237,32238,32239,32240,32241,32242,32243,32244,32245,
82942 32246,32247,32248,32249,32250,32251,32252,32253,32254,32255,32256,32257,
82943 32258,32259,32260,32261,32262,32263,32264,32265,32266,32267,32268,32269,
82944 32270,32271,32272,32273,32274,32275,32276,32277,32278,32279,32280,32281,
82945 32282,32283,32284,32285,32286,32287,32288,32289,32290,32291,32292,32293,
82946 32294,32295,32296,32297,32298,32299,32300,32301,32302,32303,32304,32305,
82947 32306,32307,32308,32309,32310,32311,32312,32313,32314,32315,32316,32317,
82948 32318,32319,32320,32321,32322,32323,32324,32325,32326,32327,32328,32329,
82949 32330,32331,32332,32333,32334,32335,32336,32337,32338,32339,32340,32341,
82950 32342,32343,32344,32345,32346,32347,32348,32349,32350,32351,32352,32353,
82951 32354,32355,32356,32357,32358,32359,32360,32361,32362,32363,32364,32365,
82952 32366,32367,32368,32369,32370,32371,32372,32373,32374,32375,32376,32377,
82953 32378,32379,32380,32381,32382,32383,32384,32385,32386,32387,32388,32389,
82954 32390,32391,32392,32393,32394,32395,32396,32397,32398,32399,32400,32401,
82955 32402,32403,32404,32405,32406,32407,32408,32409,32410,32411,32412,32413,
82956 32414,32415,32416,32417,32418,32419,32420,32421,32422,32423,32424,32425,
82957 32426,32427,32428,32429,32430,32431,32432,32433,32434,32435,32436,32437,
82958 32438,32439,32440,32441,32442,32443,32444,32445,32446,32447,32448,32449,
82959 32450,32451,32452,32453,32454,32455,32456,32457,32458,32459,32460,32461,
82960 32462,32463,32464,32465,32466,32467,32468,32469,32470,32471,32472,32473,
82961 32474,32475,32476,32477,32478,32479,32480,32481,32482,32483,32484,32485,
82962 32486,32487,32488,32489,32490,32491,32492,32493,32494,32495,32496,32497,
82963 32498,32499,32500,32501,32502,32503,32504,32505,32506,32507,32508,32509,
82964 32510,32511,32512,32513,32514,32515,32516,32517,32518,32519,32520,32521,
82965 32522,32523,32524,32525,32526,32527,32528,32529,32530,32531,32532,32533,
82966 32534,32535,32536,32537,32538,32539,32540,32541,32542,32543,32544,32545,
82967 32546,32547,32548,32549,32550,32551,32552,32553,32554,32555,32556,32557,
82968 32558,32559,32560,32561,32562,32563,32564,32565,32566,32567,32568,32569,
82969 32570,32571,32572,32573,32574,32575,32576,32577,32578,32579,32580,32581,
82970 32582,32583,32584,32585,32586,32587,32588,32589,32590,32591,32592,32593,
82971 32594,32595,32596,32597,32598,32599,32600,32601,32602,32603,32604,32605,
82972 32606,32607,32608,32609,32610,32611,32612,32613,32614,32615,32616,32617,
82973 32618,32619,32620,32621,32622,32623,32624,32625,32626,32627,32628,32629,
82974 32630,32631,32632,32633,32634,32635,32636,32637,32638,32639,32640,32641,
82975 32642,32643,32644,32645,32646,32647,32648,32649,32650,32651,32652,32653,
82976 32654,32655,32656,32657,32658,32659,32660,32661,32662,32663,32664,32665,
82977 32666,32667,32668,32669,32670,32671,32672,32673,32674,32675,32676,32677,
82978 32678,32679,32680,32681,32682,32683,32684,32685,32686,32687,32688,32689,
82979 32690,32691,32692,32693,32694,32695,32696,32697,32698,32699,32700,32701,
82980 32702,32703,32704,32705,32706,32707,32708,32709,32710,32711,32712,32713,
82981 32714,32715,32716,32717,32718,32719,32720,32721,32722,32723,32724,32725,
82982 32726,32727,32728,32729,32730,32731,32732,32733,32734,32735,32736,32737,
82983 32738,32739,32740,32741,32742,32743,32744,32745,32746,32747,32748,32749,
82984 32750,32751,32752,32753,32754,32755,32756,32757,32758,32759,32760,32761,
82985 32762,32763,32764,32765,32766,32767,32768L,32769L,32770L,32771L,32772L,
82986 32773L,32774L,32775L,32776L,32777L,32778L,32779L,32780L,32781L,32782L,
82987 32783L,32784L,32785L,32786L,32787L,32788L,32789L,32790L,32791L,32792L,
82988 32793L,32794L,32795L,32796L,32797L,32798L,32799L,32800L,32801L,32802L,
82989 32803L,32804L,32805L,32806L,32807L,32808L,32809L,32810L,32811L,32812L,
82990 32813L,32814L,32815L,32816L,32817L,32818L,32819L,32820L,32821L,32822L,
82991 32823L,32824L,32825L,32826L,32827L,32828L,32829L,32830L,32831L,32832L,
82992 32833L,32834L,32835L,32836L,32837L,32838L,32839L,32840L,32841L,32842L,
82993 32843L,32844L,32845L,32846L,32847L,32848L,32849L,32850L,32851L,32852L,
82994 32853L,32854L,32855L,32856L,32857L,32858L,32859L,32860L,32861L,32862L,
82995 32863L,32864L,32865L,32866L,32867L,32868L,32869L,32870L,32871L,32872L,
82996 32873L,32874L,32875L,32876L,32877L,32878L,32879L,32880L,32881L,32882L,
82997 32883L,32884L,32885L,32886L,32887L,32888L,32889L,32890L,32891L,32892L,
82998 32893L,32894L,32895L,32896L,32897L,32898L,32899L,32900L,32901L,32902L,
82999 32903L,32904L,32905L,32906L,32907L,32908L,32909L,32910L,32911L,32912L,
83000 32913L,32914L,32915L,32916L,32917L,32918L,32919L,32920L,32921L,32922L,
83001 32923L,32924L,32925L,32926L,32927L,32928L,32929L,32930L,32931L,32932L,
83002 32933L,32934L,32935L,32936L,32937L,32938L,32939L,32940L,32941L,32942L,
83003 32943L,32944L,32945L,32946L,32947L,32948L,32949L,32950L,32951L,32952L,
83004 32953L,32954L,32955L,32956L,32957L,32958L,32959L,32960L,32961L,32962L,
83005 32963L,32964L,32965L,32966L,32967L,32968L,32969L,32970L,32971L,32972L,
83006 32973L,32974L,32975L,32976L,32977L,32978L,32979L,32980L,32981L,32982L,
83007 32983L,32984L,32985L,32986L,32987L,32988L,32989L,32990L,32991L,32992L,
83008 32993L,32994L,32995L,32996L,32997L,32998L,32999L,33000L,33001L,33002L,
83009 33003L,33004L,33005L,33006L,33007L,33008L,33009L,33010L,33011L,33012L,
83010 33013L,33014L,33015L,33016L,33017L,33018L,33019L,33020L,33021L,33022L,
83011 33023L,33024L,33025L,33026L,33027L,33028L,33029L,33030L,33031L,33032L,
83012 33033L,33034L,33035L,33036L,33037L,33038L,33039L,33040L,33041L,33042L,
83013 33043L,33044L,33045L,33046L,33047L,33048L,33049L,33050L,33051L,33052L,
83014 33053L,33054L,33055L,33056L,33057L,33058L,33059L,33060L,33061L,33062L,
83015 33063L,33064L,33065L,33066L,33067L,33068L,33069L,33070L,33071L,33072L,
83016 33073L,33074L,33075L,33076L,33077L,33078L,33079L,33080L,33081L,33082L,
83017 33083L,33084L,33085L,33086L,33087L,33088L,33089L,33090L,33091L,33092L,
83018 33093L,33094L,33095L,33096L,33097L,33098L,33099L,33100L,33101L,33102L,
83019 33103L,33104L,33105L,33106L,33107L,33108L,33109L,33110L,33111L,33112L,
83020 33113L,33114L,33115L,33116L,33117L,33118L,33119L,33120L,33121L,33122L,
83021 33123L,33124L,33125L,33126L,33127L,33128L,33129L,33130L,33131L,33132L,
83022 33133L,33134L,33135L,33136L,33137L,33138L,33139L,33140L,33141L,33142L,
83023 33143L,33144L,33145L,33146L,33147L,33148L,33149L,33150L,33151L,33152L,
83024 33153L,33154L,33155L,33156L,33157L,33158L,33159L,33160L,33161L,33162L,
83025 33163L,33164L,33165L,33166L,33167L,33168L,33169L,33170L,33171L,33172L,
83026 33173L,33174L,33175L,33176L,33177L,33178L,33179L,33180L,33181L,33182L,
83027 33183L,33184L,33185L,33186L,33187L,33188L,33189L,33190L,33191L,33192L,
83028 33193L,33194L,33195L,33196L,33197L,33198L,33199L,33200L,33201L,33202L,
83029 33203L,33204L,33205L,33206L,33207L,33208L,33209L,33210L,33211L,33212L,
83030 33213L,33214L,33215L,33216L,33217L,33218L,33219L,33220L,33221L,33222L,
83031 33223L,33224L,33225L,33226L,33227L,33228L,33229L,33230L,33231L,33232L,
83032 33233L,33234L,33235L,33236L,33237L,33238L,33239L,33240L,33241L,33242L,
83033 33243L,33244L,33245L,33246L,33247L,33248L,33249L,33250L,33251L,33252L,
83034 33253L,33254L,33255L,33256L,33257L,33258L,33259L,33260L,33261L,33262L,
83035 33263L,33264L,33265L,33266L,33267L,33268L,33269L,33270L,33271L,33272L,
83036 33273L,33274L,33275L,33276L,33277L,33278L,33279L,33280L,33281L,33282L,
83037 33283L,33284L,33285L,33286L,33287L,33288L,33289L,33290L,33291L,33292L,
83038 33293L,33294L,33295L,33296L,33297L,33298L,33299L,33300L,33301L,33302L,
83039 33303L,33304L,33305L,33306L,33307L,33308L,33309L,33310L,33311L,33312L,
83040 33313L,33314L,33315L,33316L,33317L,33318L,33319L,33320L,33321L,33322L,
83041 33323L,33324L,33325L,33326L,33327L,33328L,33329L,33330L,33331L,33332L,
83042 33333L,33334L,33335L,33336L,33337L,33338L,33339L,33340L,33341L,33342L,
83043 33343L,33344L,33345L,33346L,33347L,33348L,33349L,33350L,33351L,33352L,
83044 33353L,33354L,33355L,33356L,33357L,33358L,33359L,33360L,33361L,33362L,
83045 33363L,33364L,33365L,33366L,33367L,33368L,33369L,33370L,33371L,33372L,
83046 33373L,33374L,33375L,33376L,33377L,33378L,33379L,33380L,33381L,33382L,
83047 33383L,33384L,33385L,33386L,33387L,33388L,33389L,33390L,33391L,33392L,
83048 33393L,33394L,33395L,33396L,33397L,33398L,33399L,33400L,33401L,33402L,
83049 33403L,33404L,33405L,33406L,33407L,33408L,33409L,33410L,33411L,33412L,
83050 33413L,33414L,33415L,33416L,33417L,33418L,33419L,33420L,33421L,33422L,
83051 33423L,33424L,33425L,33426L,33427L,33428L,33429L,33430L,33431L,33432L,
83052 33433L,33434L,33435L,33436L,33437L,33438L,33439L,33440L,33441L,33442L,
83053 33443L,33444L,33445L,33446L,33447L,33448L,33449L,33450L,33451L,33452L,
83054 33453L,33454L,33455L,33456L,33457L,33458L,33459L,33460L,33461L,33462L,
83055 33463L,33464L,33465L,33466L,33467L,33468L,33469L,33470L,33471L,33472L,
83056 33473L,33474L,33475L,33476L,33477L,33478L,33479L,33480L,33481L,33482L,
83057 33483L,33484L,33485L,33486L,33487L,33488L,33489L,33490L,33491L,33492L,
83058 33493L,33494L,33495L,33496L,33497L,33498L,33499L,33500L,33501L,33502L,
83059 33503L,33504L,33505L,33506L,33507L,33508L,33509L,33510L,33511L,33512L,
83060 33513L,33514L,33515L,33516L,33517L,33518L,33519L,33520L,33521L,33522L,
83061 33523L,33524L,33525L,33526L,33527L,33528L,33529L,33530L,33531L,33532L,
83062 33533L,33534L,33535L,33536L,33537L,33538L,33539L,33540L,33541L,33542L,
83063 33543L,33544L,33545L,33546L,33547L,33548L,33549L,33550L,33551L,33552L,
83064 33553L,33554L,33555L,33556L,33557L,33558L,33559L,33560L,33561L,33562L,
83065 33563L,33564L,33565L,33566L,33567L,33568L,33569L,33570L,33571L,33572L,
83066 33573L,33574L,33575L,33576L,33577L,33578L,33579L,33580L,33581L,33582L,
83067 33583L,33584L,33585L,33586L,33587L,33588L,33589L,33590L,33591L,33592L,
83068 33593L,33594L,33595L,33596L,33597L,33598L,33599L,33600L,33601L,33602L,
83069 33603L,33604L,33605L,33606L,33607L,33608L,33609L,33610L,33611L,33612L,
83070 33613L,33614L,33615L,33616L,33617L,33618L,33619L,33620L,33621L,33622L,
83071 33623L,33624L,33625L,33626L,33627L,33628L,33629L,33630L,33631L,33632L,
83072 33633L,33634L,33635L,33636L,33637L,33638L,33639L,33640L,33641L,33642L,
83073 33643L,33644L,33645L,33646L,33647L,33648L,33649L,33650L,33651L,33652L,
83074 33653L,33654L,33655L,33656L,33657L,33658L,33659L,33660L,33661L,33662L,
83075 33663L,33664L,33665L,33666L,33667L,33668L,33669L,33670L,33671L,33672L,
83076 33673L,33674L,33675L,33676L,33677L,33678L,33679L,33680L,33681L,33682L,
83077 33683L,33684L,33685L,33686L,33687L,33688L,33689L,33690L,33691L,33692L,
83078 33693L,33694L,33695L,33696L,33697L,33698L,33699L,33700L,33701L,33702L,
83079 33703L,33704L,33705L,33706L,33707L,33708L,33709L,33710L,33711L,33712L,
83080 33713L,33714L,33715L,33716L,33717L,33718L,33719L,33720L,33721L,33722L,
83081 33723L,33724L,33725L,33726L,33727L,33728L,33729L,33730L,33731L,33732L,
83082 33733L,33734L,33735L,33736L,33737L,33738L,33739L,33740L,33741L,33742L,
83083 33743L,33744L,33745L,33746L,33747L,33748L,33749L,33750L,33751L,33752L,
83084 33753L,33754L,33755L,33756L,33757L,33758L,33759L,33760L,33761L,33762L,
83085 33763L,33764L,33765L,33766L,33767L,33768L,33769L,33770L,33771L,33772L,
83086 33773L,33774L,33775L,33776L,33777L,33778L,33779L,33780L,33781L,33782L,
83087 33783L,33784L,33785L,33786L,33787L,33788L,33789L,33790L,33791L,33792L,
83088 33793L,33794L,33795L,33796L,33797L,33798L,33799L,33800L,33801L,33802L,
83089 33803L,33804L,33805L,33806L,33807L,33808L,33809L,33810L,33811L,33812L,
83090 33813L,33814L,33815L,33816L,33817L,33818L,33819L,33820L,33821L,33822L,
83091 33823L,33824L,33825L,33826L,33827L,33828L,33829L,33830L,33831L,33832L,
83092 33833L,33834L,33835L,33836L,33837L,33838L,33839L,33840L,33841L,33842L,
83093 33843L,33844L,33845L,33846L,33847L,33848L,33849L,33850L,33851L,33852L,
83094 33853L,33854L,33855L,33856L,33857L,33858L,33859L,33860L,33861L,33862L,
83095 33863L,33864L,33865L,33866L,33867L,33868L,33869L,33870L,33871L,33872L,
83096 33873L,33874L,33875L,33876L,33877L,33878L,33879L,33880L,33881L,33882L,
83097 33883L,33884L,33885L,33886L,33887L,33888L,33889L,33890L,33891L,33892L,
83098 33893L,33894L,33895L,33896L,33897L,33898L,33899L,33900L,33901L,33902L,
83099 33903L,33904L,33905L,33906L,33907L,33908L,33909L,33910L,33911L,33912L,
83100 33913L,33914L,33915L,33916L,33917L,33918L,33919L,33920L,33921L,33922L,
83101 33923L,33924L,33925L,33926L,33927L,33928L,33929L,33930L,33931L,33932L,
83102 33933L,33934L,33935L,33936L,33937L,33938L,33939L,33940L,33941L,33942L,
83103 33943L,33944L,33945L,33946L,33947L,33948L,33949L,33950L,33951L,33952L,
83104 33953L,33954L,33955L,33956L,33957L,33958L,33959L,33960L,33961L,33962L,
83105 33963L,33964L,33965L,33966L,33967L,33968L,33969L,33970L,33971L,33972L,
83106 33973L,33974L,33975L,33976L,33977L,33978L,33979L,33980L,33981L,33982L,
83107 33983L,33984L,33985L,33986L,33987L,33988L,33989L,33990L,33991L,33992L,
83108 33993L,33994L,33995L,33996L,33997L,33998L,33999L,34000L,34001L,34002L,
83109 34003L,34004L,34005L,34006L,34007L,34008L,34009L,34010L,34011L,34012L,
83110 34013L,34014L,34015L,34016L,34017L,34018L,34019L,34020L,34021L,34022L,
83111 34023L,34024L,34025L,34026L,34027L,34028L,34029L,34030L,34031L,34032L,
83112 34033L,34034L,34035L,34036L,34037L,34038L,34039L,34040L,34041L,34042L,
83113 34043L,34044L,34045L,34046L,34047L,34048L,34049L,34050L,34051L,34052L,
83114 34053L,34054L,34055L,34056L,34057L,34058L,34059L,34060L,34061L,34062L,
83115 34063L,34064L,34065L,34066L,34067L,34068L,34069L,34070L,34071L,34072L,
83116 34073L,34074L,34075L,34076L,34077L,34078L,34079L,34080L,34081L,34082L,
83117 34083L,34084L,34085L,34086L,34087L,34088L,34089L,34090L,34091L,34092L,
83118 34093L,34094L,34095L,34096L,34097L,34098L,34099L,34100L,34101L,34102L,
83119 34103L,34104L,34105L,34106L,34107L,34108L,34109L,34110L,34111L,34112L,
83120 34113L,34114L,34115L,34116L,34117L,34118L,34119L,34120L,34121L,34122L,
83121 34123L,34124L,34125L,34126L,34127L,34128L,34129L,34130L,34131L,34132L,
83122 34133L,34134L,34135L,34136L,34137L,34138L,34139L,34140L,34141L,34142L,
83123 34143L,34144L,34145L,34146L,34147L,34148L,34149L,34150L,34151L,34152L,
83124 34153L,34154L,34155L,34156L,34157L,34158L,34159L,34160L,34161L,34162L,
83125 34163L,34164L,34165L,34166L,34167L,34168L,34169L,34170L,34171L,34172L,
83126 34173L,34174L,34175L,34176L,34177L,34178L,34179L,34180L,34181L,34182L,
83127 34183L,34184L,34185L,34186L,34187L,34188L,34189L,34190L,34191L,34192L,
83128 34193L,34194L,34195L,34196L,34197L,34198L,34199L,34200L,34201L,34202L,
83129 34203L,34204L,34205L,34206L,34207L,34208L,34209L,34210L,34211L,34212L,
83130 34213L,34214L,34215L,34216L,34217L,34218L,34219L,34220L,34221L,34222L,
83131 34223L,34224L,34225L,34226L,34227L,34228L,34229L,34230L,34231L,34232L,
83132 34233L,34234L,34235L,34236L,34237L,34238L,34239L,34240L,34241L,34242L,
83133 34243L,34244L,34245L,34246L,34247L,34248L,34249L,34250L,34251L,34252L,
83134 34253L,34254L,34255L,34256L,34257L,34258L,34259L,34260L,34261L,34262L,
83135 34263L,34264L,34265L,34266L,34267L,34268L,34269L,34270L,34271L,34272L,
83136 34273L,34274L,34275L,34276L,34277L,34278L,34279L,34280L,34281L,34282L,
83137 34283L,34284L,34285L,34286L,34287L,34288L,34289L,34290L,34291L,34292L,
83138 34293L,34294L,34295L,34296L,34297L,34298L,34299L,34300L,34301L,34302L,
83139 34303L,34304L,34305L,34306L,34307L,34308L,34309L,34310L,34311L,34312L,
83140 34313L,34314L,34315L,34316L,34317L,34318L,34319L,34320L,34321L,34322L,
83141 34323L,34324L,34325L,34326L,34327L,34328L,34329L,34330L,34331L,34332L,
83142 34333L,34334L,34335L,34336L,34337L,34338L,34339L,34340L,34341L,34342L,
83143 34343L,34344L,34345L,34346L,34347L,34348L,34349L,34350L,34351L,34352L,
83144 34353L,34354L,34355L,34356L,34357L,34358L,34359L,34360L,34361L,34362L,
83145 34363L,34364L,34365L,34366L,34367L,34368L,34369L,34370L,34371L,34372L,
83146 34373L,34374L,34375L,34376L,34377L,34378L,34379L,34380L,34381L,34382L,
83147 34383L,34384L,34385L,34386L,34387L,34388L,34389L,34390L,34391L,34392L,
83148 34393L,34394L,34395L,34396L,34397L,34398L,34399L,34400L,34401L,34402L,
83149 34403L,34404L,34405L,34406L,34407L,34408L,34409L,34410L,34411L,34412L,
83150 34413L,34414L,34415L,34416L,34417L,34418L,34419L,34420L,34421L,34422L,
83151 34423L,34424L,34425L,34426L,34427L,34428L,34429L,34430L,34431L,34432L,
83152 34433L,34434L,34435L,34436L,34437L,34438L,34439L,34440L,34441L,34442L,
83153 34443L,34444L,34445L,34446L,34447L,34448L,34449L,34450L,34451L,34452L,
83154 34453L,34454L,34455L,34456L,34457L,34458L,34459L,34460L,34461L,34462L,
83155 34463L,34464L,34465L,34466L,34467L,34468L,34469L,34470L,34471L,34472L,
83156 34473L,34474L,34475L,34476L,34477L,34478L,34479L,34480L,34481L,34482L,
83157 34483L,34484L,34485L,34486L,34487L,34488L,34489L,34490L,34491L,34492L,
83158 34493L,34494L,34495L,34496L,34497L,34498L,34499L,34500L,34501L,34502L,
83159 34503L,34504L,34505L,34506L,34507L,34508L,34509L,34510L,34511L,34512L,
83160 34513L,34514L,34515L,34516L,34517L,34518L,34519L,34520L,34521L,34522L,
83161 34523L,34524L,34525L,34526L,34527L,34528L,34529L,34530L,34531L,34532L,
83162 34533L,34534L,34535L,34536L,34537L,34538L,34539L,34540L,34541L,34542L,
83163 34543L,34544L,34545L,34546L,34547L,34548L,34549L,34550L,34551L,34552L,
83164 34553L,34554L,34555L,34556L,34557L,34558L,34559L,34560L,34561L,34562L,
83165 34563L,34564L,34565L,34566L,34567L,34568L,34569L,34570L,34571L,34572L,
83166 34573L,34574L,34575L,34576L,34577L,34578L,34579L,34580L,34581L,34582L,
83167 34583L,34584L,34585L,34586L,34587L,34588L,34589L,34590L,34591L,34592L,
83168 34593L,34594L,34595L,34596L,34597L,34598L,34599L,34600L,34601L,34602L,
83169 34603L,34604L,34605L,34606L,34607L,34608L,34609L,34610L,34611L,34612L,
83170 34613L,34614L,34615L,34616L,34617L,34618L,34619L,34620L,34621L,34622L,
83171 34623L,34624L,34625L,34626L,34627L,34628L,34629L,34630L,34631L,34632L,
83172 34633L,34634L,34635L,34636L,34637L,34638L,34639L,34640L,34641L,34642L,
83173 34643L,34644L,34645L,34646L,34647L,34648L,34649L,34650L,34651L,34652L,
83174 34653L,34654L,34655L,34656L,34657L,34658L,34659L,34660L,34661L,34662L,
83175 34663L,34664L,34665L,34666L,34667L,34668L,34669L,34670L,34671L,34672L,
83176 34673L,34674L,34675L,34676L,34677L,34678L,34679L,34680L,34681L,34682L,
83177 34683L,34684L,34685L,34686L,34687L,34688L,34689L,34690L,34691L,34692L,
83178 34693L,34694L,34695L,34696L,34697L,34698L,34699L,34700L,34701L,34702L,
83179 34703L,34704L,34705L,34706L,34707L,34708L,34709L,34710L,34711L,34712L,
83180 34713L,34714L,34715L,34716L,34717L,34718L,34719L,34720L,34721L,34722L,
83181 34723L,34724L,34725L,34726L,34727L,34728L,34729L,34730L,34731L,34732L,
83182 34733L,34734L,34735L,34736L,34737L,34738L,34739L,34740L,34741L,34742L,
83183 34743L,34744L,34745L,34746L,34747L,34748L,34749L,34750L,34751L,34752L,
83184 34753L,34754L,34755L,34756L,34757L,34758L,34759L,34760L,34761L,34762L,
83185 34763L,34764L,34765L,34766L,34767L,34768L,34769L,34770L,34771L,34772L,
83186 34773L,34774L,34775L,34776L,34777L,34778L,34779L,34780L,34781L,34782L,
83187 34783L,34784L,34785L,34786L,34787L,34788L,34789L,34790L,34791L,34792L,
83188 34793L,34794L,34795L,34796L,34797L,34798L,34799L,34800L,34801L,34802L,
83189 34803L,34804L,34805L,34806L,34807L,34808L,34809L,34810L,34811L,34812L,
83190 34813L,34814L,34815L,34816L,34817L,34818L,34819L,34820L,34821L,34822L,
83191 34823L,34824L,34825L,34826L,34827L,34828L,34829L,34830L,34831L,34832L,
83192 34833L,34834L,34835L,34836L,34837L,34838L,34839L,34840L,34841L,34842L,
83193 34843L,34844L,34845L,34846L,34847L,34848L,34849L,34850L,34851L,34852L,
83194 34853L,34854L,34855L,34856L,34857L,34858L,34859L,34860L,34861L,34862L,
83195 34863L,34864L,34865L,34866L,34867L,34868L,34869L,34870L,34871L,34872L,
83196 34873L,34874L,34875L,34876L,34877L,34878L,34879L,34880L,34881L,34882L,
83197 34883L,34884L,34885L,34886L,34887L,34888L,34889L,34890L,34891L,34892L,
83198 34893L,34894L,34895L,34896L,34897L,34898L,34899L,34900L,34901L,34902L,
83199 34903L,34904L,34905L,34906L,34907L,34908L,34909L,34910L,34911L,34912L,
83200 34913L,34914L,34915L,34916L,34917L,34918L,34919L,34920L,34921L,34922L,
83201 34923L,34924L,34925L,34926L,34927L,34928L,34929L,34930L,34931L,34932L,
83202 34933L,34934L,34935L,34936L,34937L,34938L,34939L,34940L,34941L,34942L,
83203 34943L,34944L,34945L,34946L,34947L,34948L,34949L,34950L,34951L,34952L,
83204 34953L,34954L,34955L,34956L,34957L,34958L,34959L,34960L,34961L,34962L,
83205 34963L,34964L,34965L,34966L,34967L,34968L,34969L,34970L,34971L,34972L,
83206 34973L,34974L,34975L,34976L,34977L,34978L,34979L,34980L,34981L,34982L,
83207 34983L,34984L,34985L,34986L,34987L,34988L,34989L,34990L,34991L,34992L,
83208 34993L,34994L,34995L,34996L,34997L,34998L,34999L,35000L,35001L,35002L,
83209 35003L,35004L,35005L,35006L,35007L,35008L,35009L,35010L,35011L,35012L,
83210 35013L,35014L,35015L,35016L,35017L,35018L,35019L,35020L,35021L,35022L,
83211 35023L,35024L,35025L,35026L,35027L,35028L,35029L,35030L,35031L,35032L,
83212 35033L,35034L,35035L,35036L,35037L,35038L,35039L,35040L,35041L,35042L,
83213 35043L,35044L,35045L,35046L,35047L,35048L,35049L,35050L,35051L,35052L,
83214 35053L,35054L,35055L,35056L,35057L,35058L,35059L,35060L,35061L,35062L,
83215 35063L,35064L,35065L,35066L,35067L,35068L,35069L,35070L,35071L,35072L,
83216 35073L,35074L,35075L,35076L,35077L,35078L,35079L,35080L,35081L,35082L,
83217 35083L,35084L,35085L,35086L,35087L,35088L,35089L,35090L,35091L,35092L,
83218 35093L,35094L,35095L,35096L,35097L,35098L,35099L,35100L,35101L,35102L,
83219 35103L,35104L,35105L,35106L,35107L,35108L,35109L,35110L,35111L,35112L,
83220 35113L,35114L,35115L,35116L,35117L,35118L,35119L,35120L,35121L,35122L,
83221 35123L,35124L,35125L,35126L,35127L,35128L,35129L,35130L,35131L,35132L,
83222 35133L,35134L,35135L,35136L,35137L,35138L,35139L,35140L,35141L,35142L,
83223 35143L,35144L,35145L,35146L,35147L,35148L,35149L,35150L,35151L,35152L,
83224 35153L,35154L,35155L,35156L,35157L,35158L,35159L,35160L,35161L,35162L,
83225 35163L,35164L,35165L,35166L,35167L,35168L,35169L,35170L,35171L,35172L,
83226 35173L,35174L,35175L,35176L,35177L,35178L,35179L,35180L,35181L,35182L,
83227 35183L,35184L,35185L,35186L,35187L,35188L,35189L,35190L,35191L,35192L,
83228 35193L,35194L,35195L,35196L,35197L,35198L,35199L,35200L,35201L,35202L,
83229 35203L,35204L,35205L,35206L,35207L,35208L,35209L,35210L,35211L,35212L,
83230 35213L,35214L,35215L,35216L,35217L,35218L,35219L,35220L,35221L,35222L,
83231 35223L,35224L,35225L,35226L,35227L,35228L,35229L,35230L,35231L,35232L,
83232 35233L,35234L,35235L,35236L,35237L,35238L,35239L,35240L,35241L,35242L,
83233 35243L,35244L,35245L,35246L,35247L,35248L,35249L,35250L,35251L,35252L,
83234 35253L,35254L,35255L,35256L,35257L,35258L,35259L,35260L,35261L,35262L,
83235 35263L,35264L,35265L,35266L,35267L,35268L,35269L,35270L,35271L,35272L,
83236 35273L,35274L,35275L,35276L,35277L,35278L,35279L,35280L,35281L,35282L,
83237 35283L,35284L,35285L,35286L,35287L,35288L,35289L,35290L,35291L,35292L,
83238 35293L,35294L,35295L,35296L,35297L,35298L,35299L,35300L,35301L,35302L,
83239 35303L,35304L,35305L,35306L,35307L,35308L,35309L,35310L,35311L,35312L,
83240 35313L,35314L,35315L,35316L,35317L,35318L,35319L,35320L,35321L,35322L,
83241 35323L,35324L,35325L,35326L,35327L,35328L,35329L,35330L,35331L,35332L,
83242 35333L,35334L,35335L,35336L,35337L,35338L,35339L,35340L,35341L,35342L,
83243 35343L,35344L,35345L,35346L,35347L,35348L,35349L,35350L,35351L,35352L,
83244 35353L,35354L,35355L,35356L,35357L,35358L,35359L,35360L,35361L,35362L,
83245 35363L,35364L,35365L,35366L,35367L,35368L,35369L,35370L,35371L,35372L,
83246 35373L,35374L,35375L,35376L,35377L,35378L,35379L,35380L,35381L,35382L,
83247 35383L,35384L,35385L,35386L,35387L,35388L,35389L,35390L,35391L,35392L,
83248 35393L,35394L,35395L,35396L,35397L,35398L,35399L,35400L,35401L,35402L,
83249 35403L,35404L,35405L,35406L,35407L,35408L,35409L,35410L,35411L,35412L,
83250 35413L,35414L,35415L,35416L,35417L,35418L,35419L,35420L,35421L,35422L,
83251 35423L,35424L,35425L,35426L,35427L,35428L,35429L,35430L,35431L,35432L,
83252 35433L,35434L,35435L,35436L,35437L,35438L,35439L,35440L,35441L,35442L,
83253 35443L,35444L,35445L,35446L,35447L,35448L,35449L,35450L,35451L,35452L,
83254 35453L,35454L,35455L,35456L,35457L,35458L,35459L,35460L,35461L,35462L,
83255 35463L,35464L,35465L,35466L,35467L,35468L,35469L,35470L,35471L,35472L,
83256 35473L,35474L,35475L,35476L,35477L,35478L,35479L,35480L,35481L,35482L,
83257 35483L,35484L,35485L,35486L,35487L,35488L,35489L,35490L,35491L,35492L,
83258 35493L,35494L,35495L,35496L,35497L,35498L,35499L,35500L,35501L,35502L,
83259 35503L,35504L,35505L,35506L,35507L,35508L,35509L,35510L,35511L,35512L,
83260 35513L,35514L,35515L,35516L,35517L,35518L,35519L,35520L,35521L,35522L,
83261 35523L,35524L,35525L,35526L,35527L,35528L,35529L,35530L,35531L,35532L,
83262 35533L,35534L,35535L,35536L,35537L,35538L,35539L,35540L,35541L,35542L,
83263 35543L,35544L,35545L,35546L,35547L,35548L,35549L,35550L,35551L,35552L,
83264 35553L,35554L,35555L,35556L,35557L,35558L,35559L,35560L,35561L,35562L,
83265 35563L,35564L,35565L,35566L,35567L,35568L,35569L,35570L,35571L,35572L,
83266 35573L,35574L,35575L,35576L,35577L,35578L,35579L,35580L,35581L,35582L,
83267 35583L,35584L,35585L,35586L,35587L,35588L,35589L,35590L,35591L,35592L,
83268 35593L,35594L,35595L,35596L,35597L,35598L,35599L,35600L,35601L,35602L,
83269 35603L,35604L,35605L,35606L,35607L,35608L,35609L,35610L,35611L,35612L,
83270 35613L,35614L,35615L,35616L,35617L,35618L,35619L,35620L,35621L,35622L,
83271 35623L,35624L,35625L,35626L,35627L,35628L,35629L,35630L,35631L,35632L,
83272 35633L,35634L,35635L,35636L,35637L,35638L,35639L,35640L,35641L,35642L,
83273 35643L,35644L,35645L,35646L,35647L,35648L,35649L,35650L,35651L,35652L,
83274 35653L,35654L,35655L,35656L,35657L,35658L,35659L,35660L,35661L,35662L,
83275 35663L,35664L,35665L,35666L,35667L,35668L,35669L,35670L,35671L,35672L,
83276 35673L,35674L,35675L,35676L,35677L,35678L,35679L,35680L,35681L,35682L,
83277 35683L,35684L,35685L,35686L,35687L,35688L,35689L,35690L,35691L,35692L,
83278 35693L,35694L,35695L,35696L,35697L,35698L,35699L,35700L,35701L,35702L,
83279 35703L,35704L,35705L,35706L,35707L,35708L,35709L,35710L,35711L,35712L,
83280 35713L,35714L,35715L,35716L,35717L,35718L,35719L,35720L,35721L,35722L,
83281 35723L,35724L,35725L,35726L,35727L,35728L,35729L,35730L,35731L,35732L,
83282 35733L,35734L,35735L,35736L,35737L,35738L,35739L,35740L,35741L,35742L,
83283 35743L,35744L,35745L,35746L,35747L,35748L,35749L,35750L,35751L,35752L,
83284 35753L,35754L,35755L,35756L,35757L,35758L,35759L,35760L,35761L,35762L,
83285 35763L,35764L,35765L,35766L,35767L,35768L,35769L,35770L,35771L,35772L,
83286 35773L,35774L,35775L,35776L,35777L,35778L,35779L,35780L,35781L,35782L,
83287 35783L,35784L,35785L,35786L,35787L,35788L,35789L,35790L,35791L,35792L,
83288 35793L,35794L,35795L,35796L,35797L,35798L,35799L,35800L,35801L,35802L,
83289 35803L,35804L,35805L,35806L,35807L,35808L,35809L,35810L,35811L,35812L,
83290 35813L,35814L,35815L,35816L,35817L,35818L,35819L,35820L,35821L,35822L,
83291 35823L,35824L,35825L,35826L,35827L,35828L,35829L,35830L,35831L,35832L,
83292 35833L,35834L,35835L,35836L,35837L,35838L,35839L,35840L,35841L,35842L,
83293 35843L,35844L,35845L,35846L,35847L,35848L,35849L,35850L,35851L,35852L,
83294 35853L,35854L,35855L,35856L,35857L,35858L,35859L,35860L,35861L,35862L,
83295 35863L,35864L,35865L,35866L,35867L,35868L,35869L,35870L,35871L,35872L,
83296 35873L,35874L,35875L,35876L,35877L,35878L,35879L,35880L,35881L,35882L,
83297 35883L,35884L,35885L,35886L,35887L,35888L,35889L,35890L,35891L,35892L,
83298 35893L,35894L,35895L,35896L,35897L,35898L,35899L,35900L,35901L,35902L,
83299 35903L,35904L,35905L,35906L,35907L,35908L,35909L,35910L,35911L,35912L,
83300 35913L,35914L,35915L,35916L,35917L,35918L,35919L,35920L,35921L,35922L,
83301 35923L,35924L,35925L,35926L,35927L,35928L,35929L,35930L,35931L,35932L,
83302 35933L,35934L,35935L,35936L,35937L,35938L,35939L,35940L,35941L,35942L,
83303 35943L,35944L,35945L,35946L,35947L,35948L,35949L,35950L,35951L,35952L,
83304 35953L,35954L,35955L,35956L,35957L,35958L,35959L,35960L,35961L,35962L,
83305 35963L,35964L,35965L,35966L,35967L,35968L,35969L,35970L,35971L,35972L,
83306 35973L,35974L,35975L,35976L,35977L,35978L,35979L,35980L,35981L,35982L,
83307 35983L,35984L,35985L,35986L,35987L,35988L,35989L,35990L,35991L,35992L,
83308 35993L,35994L,35995L,35996L,35997L,35998L,35999L,36000L,36001L,36002L,
83309 36003L,36004L,36005L,36006L,36007L,36008L,36009L,36010L,36011L,36012L,
83310 36013L,36014L,36015L,36016L,36017L,36018L,36019L,36020L,36021L,36022L,
83311 36023L,36024L,36025L,36026L,36027L,36028L,36029L,36030L,36031L,36032L,
83312 36033L,36034L,36035L,36036L,36037L,36038L,36039L,36040L,36041L,36042L,
83313 36043L,36044L,36045L,36046L,36047L,36048L,36049L,36050L,36051L,36052L,
83314 36053L,36054L,36055L,36056L,36057L,36058L,36059L,36060L,36061L,36062L,
83315 36063L,36064L,36065L,36066L,36067L,36068L,36069L,36070L,36071L,36072L,
83316 36073L,36074L,36075L,36076L,36077L,36078L,36079L,36080L,36081L,36082L,
83317 36083L,36084L,36085L,36086L,36087L,36088L,36089L,36090L,36091L,36092L,
83318 36093L,36094L,36095L,36096L,36097L,36098L,36099L,36100L,36101L,36102L,
83319 36103L,36104L,36105L,36106L,36107L,36108L,36109L,36110L,36111L,36112L,
83320 36113L,36114L,36115L,36116L,36117L,36118L,36119L,36120L,36121L,36122L,
83321 36123L,36124L,36125L,36126L,36127L,36128L,36129L,36130L,36131L,36132L,
83322 36133L,36134L,36135L,36136L,36137L,36138L,36139L,36140L,36141L,36142L,
83323 36143L,36144L,36145L,36146L,36147L,36148L,36149L,36150L,36151L,36152L,
83324 36153L,36154L,36155L,36156L,36157L,36158L,36159L,36160L,36161L,36162L,
83325 36163L,36164L,36165L,36166L,36167L,36168L,36169L,36170L,36171L,36172L,
83326 36173L,36174L,36175L,36176L,36177L,36178L,36179L,36180L,36181L,36182L,
83327 36183L,36184L,36185L,36186L,36187L,36188L,36189L,36190L,36191L,36192L,
83328 36193L,36194L,36195L,36196L,36197L,36198L,36199L,36200L,36201L,36202L,
83329 36203L,36204L,36205L,36206L,36207L,36208L,36209L,36210L,36211L,36212L,
83330 36213L,36214L,36215L,36216L,36217L,36218L,36219L,36220L,36221L,36222L,
83331 36223L,36224L,36225L,36226L,36227L,36228L,36229L,36230L,36231L,36232L,
83332 36233L,36234L,36235L,36236L,36237L,36238L,36239L,36240L,36241L,36242L,
83333 36243L,36244L,36245L,36246L,36247L,36248L,36249L,36250L,36251L,36252L,
83334 36253L,36254L,36255L,36256L,36257L,36258L,36259L,36260L,36261L,36262L,
83335 36263L,36264L,36265L,36266L,36267L,36268L,36269L,36270L,36271L,36272L,
83336 36273L,36274L,36275L,36276L,36277L,36278L,36279L,36280L,36281L,36282L,
83337 36283L,36284L,36285L,36286L,36287L,36288L,36289L,36290L,36291L,36292L,
83338 36293L,36294L,36295L,36296L,36297L,36298L,36299L,36300L,36301L,36302L,
83339 36303L,36304L,36305L,36306L,36307L,36308L,36309L,36310L,36311L,36312L,
83340 36313L,36314L,36315L,36316L,36317L,36318L,36319L,36320L,36321L,36322L,
83341 36323L,36324L,36325L,36326L,36327L,36328L,36329L,36330L,36331L,36332L,
83342 36333L,36334L,36335L,36336L,36337L,36338L,36339L,36340L,36341L,36342L,
83343 36343L,36344L,36345L,36346L,36347L,36348L,36349L,36350L,36351L,36352L,
83344 36353L,36354L,36355L,36356L,36357L,36358L,36359L,36360L,36361L,36362L,
83345 36363L,36364L,36365L,36366L,36367L,36368L,36369L,36370L,36371L,36372L,
83346 36373L,36374L,36375L,36376L,36377L,36378L,36379L,36380L,36381L,36382L,
83347 36383L,36384L,36385L,36386L,36387L,36388L,36389L,36390L,36391L,36392L,
83348 36393L,36394L,36395L,36396L,36397L,36398L,36399L,36400L,36401L,36402L,
83349 36403L,36404L,36405L,36406L,36407L,36408L,36409L,36410L,36411L,36412L,
83350 36413L,36414L,36415L,36416L,36417L,36418L,36419L,36420L,36421L,36422L,
83351 36423L,36424L,36425L,36426L,36427L,36428L,36429L,36430L,36431L,36432L,
83352 36433L,36434L,36435L,36436L,36437L,36438L,36439L,36440L,36441L,36442L,
83353 36443L,36444L,36445L,36446L,36447L,36448L,36449L,36450L,36451L,36452L,
83354 36453L,36454L,36455L,36456L,36457L,36458L,36459L,36460L,36461L,36462L,
83355 36463L,36464L,36465L,36466L,36467L,36468L,36469L,36470L,36471L,36472L,
83356 36473L,36474L,36475L,36476L,36477L,36478L,36479L,36480L,36481L,36482L,
83357 36483L,36484L,36485L,36486L,36487L,36488L,36489L,36490L,36491L,36492L,
83358 36493L,36494L,36495L,36496L,36497L,36498L,36499L,36500L,36501L,36502L,
83359 36503L,36504L,36505L,36506L,36507L,36508L,36509L,36510L,36511L,36512L,
83360 36513L,36514L,36515L,36516L,36517L,36518L,36519L,36520L,36521L,36522L,
83361 36523L,36524L,36525L,36526L,36527L,36528L,36529L,36530L,36531L,36532L,
83362 36533L,36534L,36535L,36536L,36537L,36538L,36539L,36540L,36541L,36542L,
83363 36543L,36544L,36545L,36546L,36547L,36548L,36549L,36550L,36551L,36552L,
83364 36553L,36554L,36555L,36556L,36557L,36558L,36559L,36560L,36561L,36562L,
83365 36563L,36564L,36565L,36566L,36567L,36568L,36569L,36570L,36571L,36572L,
83366 36573L,36574L,36575L,36576L,36577L,36578L,36579L,36580L,36581L,36582L,
83367 36583L,36584L,36585L,36586L,36587L,36588L,36589L,36590L,36591L,36592L,
83368 36593L,36594L,36595L,36596L,36597L,36598L,36599L,36600L,36601L,36602L,
83369 36603L,36604L,36605L,36606L,36607L,36608L,36609L,36610L,36611L,36612L,
83370 36613L,36614L,36615L,36616L,36617L,36618L,36619L,36620L,36621L,36622L,
83371 36623L,36624L,36625L,36626L,36627L,36628L,36629L,36630L,36631L,36632L,
83372 36633L,36634L,36635L,36636L,36637L,36638L,36639L,36640L,36641L,36642L,
83373 36643L,36644L,36645L,36646L,36647L,36648L,36649L,36650L,36651L,36652L,
83374 36653L,36654L,36655L,36656L,36657L,36658L,36659L,36660L,36661L,36662L,
83375 36663L,36664L,36665L,36666L,36667L,36668L,36669L,36670L,36671L,36672L,
83376 36673L,36674L,36675L,36676L,36677L,36678L,36679L,36680L,36681L,36682L,
83377 36683L,36684L,36685L,36686L,36687L,36688L,36689L,36690L,36691L,36692L,
83378 36693L,36694L,36695L,36696L,36697L,36698L,36699L,36700L,36701L,36702L,
83379 36703L,36704L,36705L,36706L,36707L,36708L,36709L,36710L,36711L,36712L,
83380 36713L,36714L,36715L,36716L,36717L,36718L,36719L,36720L,36721L,36722L,
83381 36723L,36724L,36725L,36726L,36727L,36728L,36729L,36730L,36731L,36732L,
83382 36733L,36734L,36735L,36736L,36737L,36738L,36739L,36740L,36741L,36742L,
83383 36743L,36744L,36745L,36746L,36747L,36748L,36749L,36750L,36751L,36752L,
83384 36753L,36754L,36755L,36756L,36757L,36758L,36759L,36760L,36761L,36762L,
83385 36763L,36764L,36765L,36766L,36767L,36768L,36769L,36770L,36771L,36772L,
83386 36773L,36774L,36775L,36776L,36777L,36778L,36779L,36780L,36781L,36782L,
83387 36783L,36784L,36785L,36786L,36787L,36788L,36789L,36790L,36791L,36792L,
83388 36793L,36794L,36795L,36796L,36797L,36798L,36799L,36800L,36801L,36802L,
83389 36803L,36804L,36805L,36806L,36807L,36808L,36809L,36810L,36811L,36812L,
83390 36813L,36814L,36815L,36816L,36817L,36818L,36819L,36820L,36821L,36822L,
83391 36823L,36824L,36825L,36826L,36827L,36828L,36829L,36830L,36831L,36832L,
83392 36833L,36834L,36835L,36836L,36837L,36838L,36839L,36840L,36841L,36842L,
83393 36843L,36844L,36845L,36846L,36847L,36848L,36849L,36850L,36851L,36852L,
83394 36853L,36854L,36855L,36856L,36857L,36858L,36859L,36860L,36861L,36862L,
83395 36863L,36864L,36865L,36866L,36867L,36868L,36869L,36870L,36871L,36872L,
83396 36873L,36874L,36875L,36876L,36877L,36878L,36879L,36880L,36881L,36882L,
83397 36883L,36884L,36885L,36886L,36887L,36888L,36889L,36890L,36891L,36892L,
83398 36893L,36894L,36895L,36896L,36897L,36898L,36899L,36900L,36901L,36902L,
83399 36903L,36904L,36905L,36906L,36907L,36908L,36909L,36910L,36911L,36912L,
83400 36913L,36914L,36915L,36916L,36917L,36918L,36919L,36920L,36921L,36922L,
83401 36923L,36924L,36925L,36926L,36927L,36928L,36929L,36930L,36931L,36932L,
83402 36933L,36934L,36935L,36936L,36937L,36938L,36939L,36940L,36941L,36942L,
83403 36943L,36944L,36945L,36946L,36947L,36948L,36949L,36950L,36951L,36952L,
83404 36953L,36954L,36955L,36956L,36957L,36958L,36959L,36960L,36961L,36962L,
83405 36963L,36964L,36965L,36966L,36967L,36968L,36969L,36970L,36971L,36972L,
83406 36973L,36974L,36975L,36976L,36977L,36978L,36979L,36980L,36981L,36982L,
83407 36983L,36984L,36985L,36986L,36987L,36988L,36989L,36990L,36991L,36992L,
83408 36993L,36994L,36995L,36996L,36997L,36998L,36999L,37000L,37001L,37002L,
83409 37003L,37004L,37005L,37006L,37007L,37008L,37009L,37010L,37011L,37012L,
83410 37013L,37014L,37015L,37016L,37017L,37018L,37019L,37020L,37021L,37022L,
83411 37023L,37024L,37025L,37026L,37027L,37028L,37029L,37030L,37031L,37032L,
83412 37033L,37034L,37035L,37036L,37037L,37038L,37039L,37040L,37041L,37042L,
83413 37043L,37044L,37045L,37046L,37047L,37048L,37049L,37050L,37051L,37052L,
83414 37053L,37054L,37055L,37056L,37057L,37058L,37059L,37060L,37061L,37062L,
83415 37063L,37064L,37065L,37066L,37067L,37068L,37069L,37070L,37071L,37072L,
83416 37073L,37074L,37075L,37076L,37077L,37078L,37079L,37080L,37081L,37082L,
83417 37083L,37084L,37085L,37086L,37087L,37088L,37089L,37090L,37091L,37092L,
83418 37093L,37094L,37095L,37096L,37097L,37098L,37099L,37100L,37101L,37102L,
83419 37103L,37104L,37105L,37106L,37107L,37108L,37109L,37110L,37111L,37112L,
83420 37113L,37114L,37115L,37116L,37117L,37118L,37119L,37120L,37121L,37122L,
83421 37123L,37124L,37125L,37126L,37127L,37128L,37129L,37130L,37131L,37132L,
83422 37133L,37134L,37135L,37136L,37137L,37138L,37139L,37140L,37141L,37142L,
83423 37143L,37144L,37145L,37146L,37147L,37148L,37149L,37150L,37151L,37152L,
83424 37153L,37154L,37155L,37156L,37157L,37158L,37159L,37160L,37161L,37162L,
83425 37163L,37164L,37165L,37166L,37167L,37168L,37169L,37170L,37171L,37172L,
83426 37173L,37174L,37175L,37176L,37177L,37178L,37179L,37180L,37181L,37182L,
83427 37183L,37184L,37185L,37186L,37187L,37188L,37189L,37190L,37191L,37192L,
83428 37193L,37194L,37195L,37196L,37197L,37198L,37199L,37200L,37201L,37202L,
83429 37203L,37204L,37205L,37206L,37207L,37208L,37209L,37210L,37211L,37212L,
83430 37213L,37214L,37215L,37216L,37217L,37218L,37219L,37220L,37221L,37222L,
83431 37223L,37224L,37225L,37226L,37227L,37228L,37229L,37230L,37231L,37232L,
83432 37233L,37234L,37235L,37236L,37237L,37238L,37239L,37240L,37241L,37242L,
83433 37243L,37244L,37245L,37246L,37247L,37248L,37249L,37250L,37251L,37252L,
83434 37253L,37254L,37255L,37256L,37257L,37258L,37259L,37260L,37261L,37262L,
83435 37263L,37264L,37265L,37266L,37267L,37268L,37269L,37270L,37271L,37272L,
83436 37273L,37274L,37275L,37276L,37277L,37278L,37279L,37280L,37281L,37282L,
83437 37283L,37284L,37285L,37286L,37287L,37288L,37289L,37290L,37291L,37292L,
83438 37293L,37294L,37295L,37296L,37297L,37298L,37299L,37300L,37301L,37302L,
83439 37303L,37304L,37305L,37306L,37307L,37308L,37309L,37310L,37311L,37312L,
83440 37313L,37314L,37315L,37316L,37317L,37318L,37319L,37320L,37321L,37322L,
83441 37323L,37324L,37325L,37326L,37327L,37328L,37329L,37330L,37331L,37332L,
83442 37333L,37334L,37335L,37336L,37337L,37338L,37339L,37340L,37341L,37342L,
83443 37343L,37344L,37345L,37346L,37347L,37348L,37349L,37350L,37351L,37352L,
83444 37353L,37354L,37355L,37356L,37357L,37358L,37359L,37360L,37361L,37362L,
83445 37363L,37364L,37365L,37366L,37367L,37368L,37369L,37370L,37371L,37372L,
83446 37373L,37374L,37375L,37376L,37377L,37378L,37379L,37380L,37381L,37382L,
83447 37383L,37384L,37385L,37386L,37387L,37388L,37389L,37390L,37391L,37392L,
83448 37393L,37394L,37395L,37396L,37397L,37398L,37399L,37400L,37401L,37402L,
83449 37403L,37404L,37405L,37406L,37407L,37408L,37409L,37410L,37411L,37412L,
83450 37413L,37414L,37415L,37416L,37417L,37418L,37419L,37420L,37421L,37422L,
83451 37423L,37424L,37425L,37426L,37427L,37428L,37429L,37430L,37431L,37432L,
83452 37433L,37434L,37435L,37436L,37437L,37438L,37439L,37440L,37441L,37442L,
83453 37443L,37444L,37445L,37446L,37447L,37448L,37449L,37450L,37451L,37452L,
83454 37453L,37454L,37455L,37456L,37457L,37458L,37459L,37460L,37461L,37462L,
83455 37463L,37464L,37465L,37466L,37467L,37468L,37469L,37470L,37471L,37472L,
83456 37473L,37474L,37475L,37476L,37477L,37478L,37479L,37480L,37481L,37482L,
83457 37483L,37484L,37485L,37486L,37487L,37488L,37489L,37490L,37491L,37492L,
83458 37493L,37494L,37495L,37496L,37497L,37498L,37499L,37500L,37501L,37502L,
83459 37503L,37504L,37505L,37506L,37507L,37508L,37509L,37510L,37511L,37512L,
83460 37513L,37514L,37515L,37516L,37517L,37518L,37519L,37520L,37521L,37522L,
83461 37523L,37524L,37525L,37526L,37527L,37528L,37529L,37530L,37531L,37532L,
83462 37533L,37534L,37535L,37536L,37537L,37538L,37539L,37540L,37541L,37542L,
83463 37543L,37544L,37545L,37546L,37547L,37548L,37549L,37550L,37551L,37552L,
83464 37553L,37554L,37555L,37556L,37557L,37558L,37559L,37560L,37561L,37562L,
83465 37563L,37564L,37565L,37566L,37567L,37568L,37569L,37570L,37571L,37572L,
83466 37573L,37574L,37575L,37576L,37577L,37578L,37579L,37580L,37581L,37582L,
83467 37583L,37584L,37585L,37586L,37587L,37588L,37589L,37590L,37591L,37592L,
83468 37593L,37594L,37595L,37596L,37597L,37598L,37599L,37600L,37601L,37602L,
83469 37603L,37604L,37605L,37606L,37607L,37608L,37609L,37610L,37611L,37612L,
83470 37613L,37614L,37615L,37616L,37617L,37618L,37619L,37620L,37621L,37622L,
83471 37623L,37624L,37625L,37626L,37627L,37628L,37629L,37630L,37631L,37632L,
83472 37633L,37634L,37635L,37636L,37637L,37638L,37639L,37640L,37641L,37642L,
83473 37643L,37644L,37645L,37646L,37647L,37648L,37649L,37650L,37651L,37652L,
83474 37653L,37654L,37655L,37656L,37657L,37658L,37659L,37660L,37661L,37662L,
83475 37663L,37664L,37665L,37666L,37667L,37668L,37669L,37670L,37671L,37672L,
83476 37673L,37674L,37675L,37676L,37677L,37678L,37679L,37680L,37681L,37682L,
83477 37683L,37684L,37685L,37686L,37687L,37688L,37689L,37690L,37691L,37692L,
83478 37693L,37694L,37695L,37696L,37697L,37698L,37699L,37700L,37701L,37702L,
83479 37703L,37704L,37705L,37706L,37707L,37708L,37709L,37710L,37711L,37712L,
83480 37713L,37714L,37715L,37716L,37717L,37718L,37719L,37720L,37721L,37722L,
83481 37723L,37724L,37725L,37726L,37727L,37728L,37729L,37730L,37731L,37732L,
83482 37733L,37734L,37735L,37736L,37737L,37738L,37739L,37740L,37741L,37742L,
83483 37743L,37744L,37745L,37746L,37747L,37748L,37749L,37750L,37751L,37752L,
83484 37753L,37754L,37755L,37756L,37757L,37758L,37759L,37760L,37761L,37762L,
83485 37763L,37764L,37765L,37766L,37767L,37768L,37769L,37770L,37771L,37772L,
83486 37773L,37774L,37775L,37776L,37777L,37778L,37779L,37780L,37781L,37782L,
83487 37783L,37784L,37785L,37786L,37787L,37788L,37789L,37790L,37791L,37792L,
83488 37793L,37794L,37795L,37796L,37797L,37798L,37799L,37800L,37801L,37802L,
83489 37803L,37804L,37805L,37806L,37807L,37808L,37809L,37810L,37811L,37812L,
83490 37813L,37814L,37815L,37816L,37817L,37818L,37819L,37820L,37821L,37822L,
83491 37823L,37824L,37825L,37826L,37827L,37828L,37829L,37830L,37831L,37832L,
83492 37833L,37834L,37835L,37836L,37837L,37838L,37839L,37840L,37841L,37842L,
83493 37843L,37844L,37845L,37846L,37847L,37848L,37849L,37850L,37851L,37852L,
83494 37853L,37854L,37855L,37856L,37857L,37858L,37859L,37860L,37861L,37862L,
83495 37863L,37864L,37865L,37866L,37867L,37868L,37869L,37870L,37871L,37872L,
83496 37873L,37874L,37875L,37876L,37877L,37878L,37879L,37880L,37881L,37882L,
83497 37883L,37884L,37885L,37886L,37887L,37888L,37889L,37890L,37891L,37892L,
83498 37893L,37894L,37895L,37896L,37897L,37898L,37899L,37900L,37901L,37902L,
83499 37903L,37904L,37905L,37906L,37907L,37908L,37909L,37910L,37911L,37912L,
83500 37913L,37914L,37915L,37916L,37917L,37918L,37919L,37920L,37921L,37922L,
83501 37923L,37924L,37925L,37926L,37927L,37928L,37929L,37930L,37931L,37932L,
83502 37933L,37934L,37935L,37936L,37937L,37938L,37939L,37940L,37941L,37942L,
83503 37943L,37944L,37945L,37946L,37947L,37948L,37949L,37950L,37951L,37952L,
83504 37953L,37954L,37955L,37956L,37957L,37958L,37959L,37960L,37961L,37962L,
83505 37963L,37964L,37965L,37966L,37967L,37968L,37969L,37970L,37971L,37972L,
83506 37973L,37974L,37975L,37976L,37977L,37978L,37979L,37980L,37981L,37982L,
83507 37983L,37984L,37985L,37986L,37987L,37988L,37989L,37990L,37991L,37992L,
83508 37993L,37994L,37995L,37996L,37997L,37998L,37999L,38000L,38001L,38002L,
83509 38003L,38004L,38005L,38006L,38007L,38008L,38009L,38010L,38011L,38012L,
83510 38013L,38014L,38015L,38016L,38017L,38018L,38019L,38020L,38021L,38022L,
83511 38023L,38024L,38025L,38026L,38027L,38028L,38029L,38030L,38031L,38032L,
83512 38033L,38034L,38035L,38036L,38037L,38038L,38039L,38040L,38041L,38042L,
83513 38043L,38044L,38045L,38046L,38047L,38048L,38049L,38050L,38051L,38052L,
83514 38053L,38054L,38055L,38056L,38057L,38058L,38059L,38060L,38061L,38062L,
83515 38063L,38064L,38065L,38066L,38067L,38068L,38069L,38070L,38071L,38072L,
83516 38073L,38074L,38075L,38076L,38077L,38078L,38079L,38080L,38081L,38082L,
83517 38083L,38084L,38085L,38086L,38087L,38088L,38089L,38090L,38091L,38092L,
83518 38093L,38094L,38095L,38096L,38097L,38098L,38099L,38100L,38101L,38102L,
83519 38103L,38104L,38105L,38106L,38107L,38108L,38109L,38110L,38111L,38112L,
83520 38113L,38114L,38115L,38116L,38117L,38118L,38119L,38120L,38121L,38122L,
83521 38123L,38124L,38125L,38126L,38127L,38128L,38129L,38130L,38131L,38132L,
83522 38133L,38134L,38135L,38136L,38137L,38138L,38139L,38140L,38141L,38142L,
83523 38143L,38144L,38145L,38146L,38147L,38148L,38149L,38150L,38151L,38152L,
83524 38153L,38154L,38155L,38156L,38157L,38158L,38159L,38160L,38161L,38162L,
83525 38163L,38164L,38165L,38166L,38167L,38168L,38169L,38170L,38171L,38172L,
83526 38173L,38174L,38175L,38176L,38177L,38178L,38179L,38180L,38181L,38182L,
83527 38183L,38184L,38185L,38186L,38187L,38188L,38189L,38190L,38191L,38192L,
83528 38193L,38194L,38195L,38196L,38197L,38198L,38199L,38200L,38201L,38202L,
83529 38203L,38204L,38205L,38206L,38207L,38208L,38209L,38210L,38211L,38212L,
83530 38213L,38214L,38215L,38216L,38217L,38218L,38219L,38220L,38221L,38222L,
83531 38223L,38224L,38225L,38226L,38227L,38228L,38229L,38230L,38231L,38232L,
83532 38233L,38234L,38235L,38236L,38237L,38238L,38239L,38240L,38241L,38242L,
83533 38243L,38244L,38245L,38246L,38247L,38248L,38249L,38250L,38251L,38252L,
83534 38253L,38254L,38255L,38256L,38257L,38258L,38259L,38260L,38261L,38262L,
83535 38263L,38264L,38265L,38266L,38267L,38268L,38269L,38270L,38271L,38272L,
83536 38273L,38274L,38275L,38276L,38277L,38278L,38279L,38280L,38281L,38282L,
83537 38283L,38284L,38285L,38286L,38287L,38288L,38289L,38290L,38291L,38292L,
83538 38293L,38294L,38295L,38296L,38297L,38298L,38299L,38300L,38301L,38302L,
83539 38303L,38304L,38305L,38306L,38307L,38308L,38309L,38310L,38311L,38312L,
83540 38313L,38314L,38315L,38316L,38317L,38318L,38319L,38320L,38321L,38322L,
83541 38323L,38324L,38325L,38326L,38327L,38328L,38329L,38330L,38331L,38332L,
83542 38333L,38334L,38335L,38336L,38337L,38338L,38339L,38340L,38341L,38342L,
83543 38343L,38344L,38345L,38346L,38347L,38348L,38349L,38350L,38351L,38352L,
83544 38353L,38354L,38355L,38356L,38357L,38358L,38359L,38360L,38361L,38362L,
83545 38363L,38364L,38365L,38366L,38367L,38368L,38369L,38370L,38371L,38372L,
83546 38373L,38374L,38375L,38376L,38377L,38378L,38379L,38380L,38381L,38382L,
83547 38383L,38384L,38385L,38386L,38387L,38388L,38389L,38390L,38391L,38392L,
83548 38393L,38394L,38395L,38396L,38397L,38398L,38399L,38400L,38401L,38402L,
83549 38403L,38404L,38405L,38406L,38407L,38408L,38409L,38410L,38411L,38412L,
83550 38413L,38414L,38415L,38416L,38417L,38418L,38419L,38420L,38421L,38422L,
83551 38423L,38424L,38425L,38426L,38427L,38428L,38429L,38430L,38431L,38432L,
83552 38433L,38434L,38435L,38436L,38437L,38438L,38439L,38440L,38441L,38442L,
83553 38443L,38444L,38445L,38446L,38447L,38448L,38449L,38450L,38451L,38452L,
83554 38453L,38454L,38455L,38456L,38457L,38458L,38459L,38460L,38461L,38462L,
83555 38463L,38464L,38465L,38466L,38467L,38468L,38469L,38470L,38471L,38472L,
83556 38473L,38474L,38475L,38476L,38477L,38478L,38479L,38480L,38481L,38482L,
83557 38483L,38484L,38485L,38486L,38487L,38488L,38489L,38490L,38491L,38492L,
83558 38493L,38494L,38495L,38496L,38497L,38498L,38499L,38500L,38501L,38502L,
83559 38503L,38504L,38505L,38506L,38507L,38508L,38509L,38510L,38511L,38512L,
83560 38513L,38514L,38515L,38516L,38517L,38518L,38519L,38520L,38521L,38522L,
83561 38523L,38524L,38525L,38526L,38527L,38528L,38529L,38530L,38531L,38532L,
83562 38533L,38534L,38535L,38536L,38537L,38538L,38539L,38540L,38541L,38542L,
83563 38543L,38544L,38545L,38546L,38547L,38548L,38549L,38550L,38551L,38552L,
83564 38553L,38554L,38555L,38556L,38557L,38558L,38559L,38560L,38561L,38562L,
83565 38563L,38564L,38565L,38566L,38567L,38568L,38569L,38570L,38571L,38572L,
83566 38573L,38574L,38575L,38576L,38577L,38578L,38579L,38580L,38581L,38582L,
83567 38583L,38584L,38585L,38586L,38587L,38588L,38589L,38590L,38591L,38592L,
83568 38593L,38594L,38595L,38596L,38597L,38598L,38599L,38600L,38601L,38602L,
83569 38603L,38604L,38605L,38606L,38607L,38608L,38609L,38610L,38611L,38612L,
83570 38613L,38614L,38615L,38616L,38617L,38618L,38619L,38620L,38621L,38622L,
83571 38623L,38624L,38625L,38626L,38627L,38628L,38629L,38630L,38631L,38632L,
83572 38633L,38634L,38635L,38636L,38637L,38638L,38639L,38640L,38641L,38642L,
83573 38643L,38644L,38645L,38646L,38647L,38648L,38649L,38650L,38651L,38652L,
83574 38653L,38654L,38655L,38656L,38657L,38658L,38659L,38660L,38661L,38662L,
83575 38663L,38664L,38665L,38666L,38667L,38668L,38669L,38670L,38671L,38672L,
83576 38673L,38674L,38675L,38676L,38677L,38678L,38679L,38680L,38681L,38682L,
83577 38683L,38684L,38685L,38686L,38687L,38688L,38689L,38690L,38691L,38692L,
83578 38693L,38694L,38695L,38696L,38697L,38698L,38699L,38700L,38701L,38702L,
83579 38703L,38704L,38705L,38706L,38707L,38708L,38709L,38710L,38711L,38712L,
83580 38713L,38714L,38715L,38716L,38717L,38718L,38719L,38720L,38721L,38722L,
83581 38723L,38724L,38725L,38726L,38727L,38728L,38729L,38730L,38731L,38732L,
83582 38733L,38734L,38735L,38736L,38737L,38738L,38739L,38740L,38741L,38742L,
83583 38743L,38744L,38745L,38746L,38747L,38748L,38749L,38750L,38751L,38752L,
83584 38753L,38754L,38755L,38756L,38757L,38758L,38759L,38760L,38761L,38762L,
83585 38763L,38764L,38765L,38766L,38767L,38768L,38769L,38770L,38771L,38772L,
83586 38773L,38774L,38775L,38776L,38777L,38778L,38779L,38780L,38781L,38782L,
83587 38783L,38784L,38785L,38786L,38787L,38788L,38789L,38790L,38791L,38792L,
83588 38793L,38794L,38795L,38796L,38797L,38798L,38799L,38800L,38801L,38802L,
83589 38803L,38804L,38805L,38806L,38807L,38808L,38809L,38810L,38811L,38812L,
83590 38813L,38814L,38815L,38816L,38817L,38818L,38819L,38820L,38821L,38822L,
83591 38823L,38824L,38825L,38826L,38827L,38828L,38829L,38830L,38831L,38832L,
83592 38833L,38834L,38835L,38836L,38837L,38838L,38839L,38840L,38841L,38842L,
83593 38843L,38844L,38845L,38846L,38847L,38848L,38849L,38850L,38851L,38852L,
83594 38853L,38854L,38855L,38856L,38857L,38858L,38859L,38860L,38861L,38862L,
83595 38863L,38864L,38865L,38866L,38867L,38868L,38869L,38870L,38871L,38872L,
83596 38873L,38874L,38875L,38876L,38877L,38878L,38879L,38880L,38881L,38882L,
83597 38883L,38884L,38885L,38886L,38887L,38888L,38889L,38890L,38891L,38892L,
83598 38893L,38894L,38895L,38896L,38897L,38898L,38899L,38900L,38901L,38902L,
83599 38903L,38904L,38905L,38906L,38907L,38908L,38909L,38910L,38911L,38912L,
83600 38913L,38914L,38915L,38916L,38917L,38918L,38919L,38920L,38921L,38922L,
83601 38923L,38924L,38925L,38926L,38927L,38928L,38929L,38930L,38931L,38932L,
83602 38933L,38934L,38935L,38936L,38937L,38938L,38939L,38940L,38941L,38942L,
83603 38943L,38944L,38945L,38946L,38947L,38948L,38949L,38950L,38951L,38952L,
83604 38953L,38954L,38955L,38956L,38957L,38958L,38959L,38960L,38961L,38962L,
83605 38963L,38964L,38965L,38966L,38967L,38968L,38969L,38970L,38971L,38972L,
83606 38973L,38974L,38975L,38976L,38977L,38978L,38979L,38980L,38981L,38982L,
83607 38983L,38984L,38985L,38986L,38987L,38988L,38989L,38990L,38991L,38992L,
83608 38993L,38994L,38995L,38996L,38997L,38998L,38999L,39000L,39001L,39002L,
83609 39003L,39004L,39005L,39006L,39007L,39008L,39009L,39010L,39011L,39012L,
83610 39013L,39014L,39015L,39016L,39017L,39018L,39019L,39020L,39021L,39022L,
83611 39023L,39024L,39025L,39026L,39027L,39028L,39029L,39030L,39031L,39032L,
83612 39033L,39034L,39035L,39036L,39037L,39038L,39039L,39040L,39041L,39042L,
83613 39043L,39044L,39045L,39046L,39047L,39048L,39049L,39050L,39051L,39052L,
83614 39053L,39054L,39055L,39056L,39057L,39058L,39059L,39060L,39061L,39062L,
83615 39063L,39064L,39065L,39066L,39067L,39068L,39069L,39070L,39071L,39072L,
83616 39073L,39074L,39075L,39076L,39077L,39078L,39079L,39080L,39081L,39082L,
83617 39083L,39084L,39085L,39086L,39087L,39088L,39089L,39090L,39091L,39092L,
83618 39093L,39094L,39095L,39096L,39097L,39098L,39099L,39100L,39101L,39102L,
83619 39103L,39104L,39105L,39106L,39107L,39108L,39109L,39110L,39111L,39112L,
83620 39113L,39114L,39115L,39116L,39117L,39118L,39119L,39120L,39121L,39122L,
83621 39123L,39124L,39125L,39126L,39127L,39128L,39129L,39130L,39131L,39132L,
83622 39133L,39134L,39135L,39136L,39137L,39138L,39139L,39140L,39141L,39142L,
83623 39143L,39144L,39145L,39146L,39147L,39148L,39149L,39150L,39151L,39152L,
83624 39153L,39154L,39155L,39156L,39157L,39158L,39159L,39160L,39161L,39162L,
83625 39163L,39164L,39165L,39166L,39167L,39168L,39169L,39170L,39171L,39172L,
83626 39173L,39174L,39175L,39176L,39177L,39178L,39179L,39180L,39181L,39182L,
83627 39183L,39184L,39185L,39186L,39187L,39188L,39189L,39190L,39191L,39192L,
83628 39193L,39194L,39195L,39196L,39197L,39198L,39199L,39200L,39201L,39202L,
83629 39203L,39204L,39205L,39206L,39207L,39208L,39209L,39210L,39211L,39212L,
83630 39213L,39214L,39215L,39216L,39217L,39218L,39219L,39220L,39221L,39222L,
83631 39223L,39224L,39225L,39226L,39227L,39228L,39229L,39230L,39231L,39232L,
83632 39233L,39234L,39235L,39236L,39237L,39238L,39239L,39240L,39241L,39242L,
83633 39243L,39244L,39245L,39246L,39247L,39248L,39249L,39250L,39251L,39252L,
83634 39253L,39254L,39255L,39256L,39257L,39258L,39259L,39260L,39261L,39262L,
83635 39263L,39264L,39265L,39266L,39267L,39268L,39269L,39270L,39271L,39272L,
83636 39273L,39274L,39275L,39276L,39277L,39278L,39279L,39280L,39281L,39282L,
83637 39283L,39284L,39285L,39286L,39287L,39288L,39289L,39290L,39291L,39292L,
83638 39293L,39294L,39295L,39296L,39297L,39298L,39299L,39300L,39301L,39302L,
83639 39303L,39304L,39305L,39306L,39307L,39308L,39309L,39310L,39311L,39312L,
83640 39313L,39314L,39315L,39316L,39317L,39318L,39319L,39320L,39321L,39322L,
83641 39323L,39324L,39325L,39326L,39327L,39328L,39329L,39330L,39331L,39332L,
83642 39333L,39334L,39335L,39336L,39337L,39338L,39339L,39340L,39341L,39342L,
83643 39343L,39344L,39345L,39346L,39347L,39348L,39349L,39350L,39351L,39352L,
83644 39353L,39354L,39355L,39356L,39357L,39358L,39359L,39360L,39361L,39362L,
83645 39363L,39364L,39365L,39366L,39367L,39368L,39369L,39370L,39371L,39372L,
83646 39373L,39374L,39375L,39376L,39377L,39378L,39379L,39380L,39381L,39382L,
83647 39383L,39384L,39385L,39386L,39387L,39388L,39389L,39390L,39391L,39392L,
83648 39393L,39394L,39395L,39396L,39397L,39398L,39399L,39400L,39401L,39402L,
83649 39403L,39404L,39405L,39406L,39407L,39408L,39409L,39410L,39411L,39412L,
83650 39413L,39414L,39415L,39416L,39417L,39418L,39419L,39420L,39421L,39422L,
83651 39423L,39424L,39425L,39426L,39427L,39428L,39429L,39430L,39431L,39432L,
83652 39433L,39434L,39435L,39436L,39437L,39438L,39439L,39440L,39441L,39442L,
83653 39443L,39444L,39445L,39446L,39447L,39448L,39449L,39450L,39451L,39452L,
83654 39453L,39454L,39455L,39456L,39457L,39458L,39459L,39460L,39461L,39462L,
83655 39463L,39464L,39465L,39466L,39467L,39468L,39469L,39470L,39471L,39472L,
83656 39473L,39474L,39475L,39476L,39477L,39478L,39479L,39480L,39481L,39482L,
83657 39483L,39484L,39485L,39486L,39487L,39488L,39489L,39490L,39491L,39492L,
83658 39493L,39494L,39495L,39496L,39497L,39498L,39499L,39500L,39501L,39502L,
83659 39503L,39504L,39505L,39506L,39507L,39508L,39509L,39510L,39511L,39512L,
83660 39513L,39514L,39515L,39516L,39517L,39518L,39519L,39520L,39521L,39522L,
83661 39523L,39524L,39525L,39526L,39527L,39528L,39529L,39530L,39531L,39532L,
83662 39533L,39534L,39535L,39536L,39537L,39538L,39539L,39540L,39541L,39542L,
83663 39543L,39544L,39545L,39546L,39547L,39548L,39549L,39550L,39551L,39552L,
83664 39553L,39554L,39555L,39556L,39557L,39558L,39559L,39560L,39561L,39562L,
83665 39563L,39564L,39565L,39566L,39567L,39568L,39569L,39570L,39571L,39572L,
83666 39573L,39574L,39575L,39576L,39577L,39578L,39579L,39580L,39581L,39582L,
83667 39583L,39584L,39585L,39586L,39587L,39588L,39589L,39590L,39591L,39592L,
83668 39593L,39594L,39595L,39596L,39597L,39598L,39599L,39600L,39601L,39602L,
83669 39603L,39604L,39605L,39606L,39607L,39608L,39609L,39610L,39611L,39612L,
83670 39613L,39614L,39615L,39616L,39617L,39618L,39619L,39620L,39621L,39622L,
83671 39623L,39624L,39625L,39626L,39627L,39628L,39629L,39630L,39631L,39632L,
83672 39633L,39634L,39635L,39636L,39637L,39638L,39639L,39640L,39641L,39642L,
83673 39643L,39644L,39645L,39646L,39647L,39648L,39649L,39650L,39651L,39652L,
83674 39653L,39654L,39655L,39656L,39657L,39658L,39659L,39660L,39661L,39662L,
83675 39663L,39664L,39665L,39666L,39667L,39668L,39669L,39670L,39671L,39672L,
83676 39673L,39674L,39675L,39676L,39677L,39678L,39679L,39680L,39681L,39682L,
83677 39683L,39684L,39685L,39686L,39687L,39688L,39689L,39690L,39691L,39692L,
83678 39693L,39694L,39695L,39696L,39697L,39698L,39699L,39700L,39701L,39702L,
83679 39703L,39704L,39705L,39706L,39707L,39708L,39709L,39710L,39711L,39712L,
83680 39713L,39714L,39715L,39716L,39717L,39718L,39719L,39720L,39721L,39722L,
83681 39723L,39724L,39725L,39726L,39727L,39728L,39729L,39730L,39731L,39732L,
83682 39733L,39734L,39735L,39736L,39737L,39738L,39739L,39740L,39741L,39742L,
83683 39743L,39744L,39745L,39746L,39747L,39748L,39749L,39750L,39751L,39752L,
83684 39753L,39754L,39755L,39756L,39757L,39758L,39759L,39760L,39761L,39762L,
83685 39763L,39764L,39765L,39766L,39767L,39768L,39769L,39770L,39771L,39772L,
83686 39773L,39774L,39775L,39776L,39777L,39778L,39779L,39780L,39781L,39782L,
83687 39783L,39784L,39785L,39786L,39787L,39788L,39789L,39790L,39791L,39792L,
83688 39793L,39794L,39795L,39796L,39797L,39798L,39799L,39800L,39801L,39802L,
83689 39803L,39804L,39805L,39806L,39807L,39808L,39809L,39810L,39811L,39812L,
83690 39813L,39814L,39815L,39816L,39817L,39818L,39819L,39820L,39821L,39822L,
83691 39823L,39824L,39825L,39826L,39827L,39828L,39829L,39830L,39831L,39832L,
83692 39833L,39834L,39835L,39836L,39837L,39838L,39839L,39840L,39841L,39842L,
83693 39843L,39844L,39845L,39846L,39847L,39848L,39849L,39850L,39851L,39852L,
83694 39853L,39854L,39855L,39856L,39857L,39858L,39859L,39860L,39861L,39862L,
83695 39863L,39864L,39865L,39866L,39867L,39868L,39869L,39870L,39871L,39872L,
83696 39873L,39874L,39875L,39876L,39877L,39878L,39879L,39880L,39881L,39882L,
83697 39883L,39884L,39885L,39886L,39887L,39888L,39889L,39890L,39891L,39892L,
83698 39893L,39894L,39895L,39896L,39897L,39898L,39899L,39900L,39901L,39902L,
83699 39903L,39904L,39905L,39906L,39907L,39908L,39909L,39910L,39911L,39912L,
83700 39913L,39914L,39915L,39916L,39917L,39918L,39919L,39920L,39921L,39922L,
83701 39923L,39924L,39925L,39926L,39927L,39928L,39929L,39930L,39931L,39932L,
83702 39933L,39934L,39935L,39936L,39937L,39938L,39939L,39940L,39941L,39942L,
83703 39943L,39944L,39945L,39946L,39947L,39948L,39949L,39950L,39951L,39952L,
83704 39953L,39954L,39955L,39956L,39957L,39958L,39959L,39960L,39961L,39962L,
83705 39963L,39964L,39965L,39966L,39967L,39968L,39969L,39970L,39971L,39972L,
83706 39973L,39974L,39975L,39976L,39977L,39978L,39979L,39980L,39981L,39982L,
83707 39983L,39984L,39985L,39986L,39987L,39988L,39989L,39990L,39991L,39992L,
83708 39993L,39994L,39995L,39996L,39997L,39998L,39999L,40000L,40001L,40002L,
83709 40003L,40004L,40005L,40006L,40007L,40008L,40009L,40010L,40011L,40012L,
83710 40013L,40014L,40015L,40016L,40017L,40018L,40019L,40020L,40021L,40022L,
83711 40023L,40024L,40025L,40026L,40027L,40028L,40029L,40030L,40031L,40032L,
83712 40033L,40034L,40035L,40036L,40037L,40038L,40039L,40040L,40041L,40042L,
83713 40043L,40044L,40045L,40046L,40047L,40048L,40049L,40050L,40051L,40052L,
83714 40053L,40054L,40055L,40056L,40057L,40058L,40059L,40060L,40061L,40062L,
83715 40063L,40064L,40065L,40066L,40067L,40068L,40069L,40070L,40071L,40072L,
83716 40073L,40074L,40075L,40076L,40077L,40078L,40079L,40080L,40081L,40082L,
83717 40083L,40084L,40085L,40086L,40087L,40088L,40089L,40090L,40091L,40092L,
83718 40093L,40094L,40095L,40096L,40097L,40098L,40099L,40100L,40101L,40102L,
83719 40103L,40104L,40105L,40106L,40107L,40108L,40109L,40110L,40111L,40112L,
83720 40113L,40114L,40115L,40116L,40117L,40118L,40119L,40120L,40121L,40122L,
83721 40123L,40124L,40125L,40126L,40127L,40128L,40129L,40130L,40131L,40132L,
83722 40133L,40134L,40135L,40136L,40137L,40138L,40139L,40140L,40141L,40142L,
83723 40143L,40144L,40145L,40146L,40147L,40148L,40149L,40150L,40151L,40152L,
83724 40153L,40154L,40155L,40156L,40157L,40158L,40159L,40160L,40161L,40162L,
83725 40163L,40164L,40165L,40166L,40167L,40168L,40169L,40170L,40171L,40172L,
83726 40173L,40174L,40175L,40176L,40177L,40178L,40179L,40180L,40181L,40182L,
83727 40183L,40184L,40185L,40186L,40187L,40188L,40189L,40190L,40191L,40192L,
83728 40193L,40194L,40195L,40196L,40197L,40198L,40199L,40200L,40201L,40202L,
83729 40203L,40204L,40205L,40206L,40207L,40208L,40209L,40210L,40211L,40212L,
83730 40213L,40214L,40215L,40216L,40217L,40218L,40219L,40220L,40221L,40222L,
83731 40223L,40224L,40225L,40226L,40227L,40228L,40229L,40230L,40231L,40232L,
83732 40233L,40234L,40235L,40236L,40237L,40238L,40239L,40240L,40241L,40242L,
83733 40243L,40244L,40245L,40246L,40247L,40248L,40249L,40250L,40251L,40252L,
83734 40253L,40254L,40255L,40256L,40257L,40258L,40259L,40260L,40261L,40262L,
83735 40263L,40264L,40265L,40266L,40267L,40268L,40269L,40270L,40271L,40272L,
83736 40273L,40274L,40275L,40276L,40277L,40278L,40279L,40280L,40281L,40282L,
83737 40283L,40284L,40285L,40286L,40287L,40288L,40289L,40290L,40291L,40292L,
83738 40293L,40294L,40295L,40296L,40297L,40298L,40299L,40300L,40301L,40302L,
83739 40303L,40304L,40305L,40306L,40307L,40308L,40309L,40310L,40311L,40312L,
83740 40313L,40314L,40315L,40316L,40317L,40318L,40319L,40320L,40321L,40322L,
83741 40323L,40324L,40325L,40326L,40327L,40328L,40329L,40330L,40331L,40332L,
83742 40333L,40334L,40335L,40336L,40337L,40338L,40339L,40340L,40341L,40342L,
83743 40343L,40344L,40345L,40346L,40347L,40348L,40349L,40350L,40351L,40352L,
83744 40353L,40354L,40355L,40356L,40357L,40358L,40359L,40360L,40361L,40362L,
83745 40363L,40364L,40365L,40366L,40367L,40368L,40369L,40370L,40371L,40372L,
83746 40373L,40374L,40375L,40376L,40377L,40378L,40379L,40380L,40381L,40382L,
83747 40383L,40384L,40385L,40386L,40387L,40388L,40389L,40390L,40391L,40392L,
83748 40393L,40394L,40395L,40396L,40397L,40398L,40399L,40400L,40401L,40402L,
83749 40403L,40404L,40405L,40406L,40407L,40408L,40409L,40410L,40411L,40412L,
83750 40413L,40414L,40415L,40416L,40417L,40418L,40419L,40420L,40421L,40422L,
83751 40423L,40424L,40425L,40426L,40427L,40428L,40429L,40430L,40431L,40432L,
83752 40433L,40434L,40435L,40436L,40437L,40438L,40439L,40440L,40441L,40442L,
83753 40443L,40444L,40445L,40446L,40447L,40448L,40449L,40450L,40451L,40452L,
83754 40453L,40454L,40455L,40456L,40457L,40458L,40459L,40460L,40461L,40462L,
83755 40463L,40464L,40465L,40466L,40467L,40468L,40469L,40470L,40471L,40472L,
83756 40473L,40474L,40475L,40476L,40477L,40478L,40479L,40480L,40481L,40482L,
83757 40483L,40484L,40485L,40486L,40487L,40488L,40489L,40490L,40491L,40492L,
83758 40493L,40494L,40495L,40496L,40497L,40498L,40499L,40500L,40501L,40502L,
83759 40503L,40504L,40505L,40506L,40507L,40508L,40509L,40510L,40511L,40512L,
83760 40513L,40514L,40515L,40516L,40517L,40518L,40519L,40520L,40521L,40522L,
83761 40523L,40524L,40525L,40526L,40527L,40528L,40529L,40530L,40531L,40532L,
83762 40533L,40534L,40535L,40536L,40537L,40538L,40539L,40540L,40541L,40542L,
83763 40543L,40544L,40545L,40546L,40547L,40548L,40549L,40550L,40551L,40552L,
83764 40553L,40554L,40555L,40556L,40557L,40558L,40559L,40560L,40561L,40562L,
83765 40563L,40564L,40565L,40566L,40567L,40568L,40569L,40570L,40571L,40572L,
83766 40573L,40574L,40575L,40576L,40577L,40578L,40579L,40580L,40581L,40582L,
83767 40583L,40584L,40585L,40586L,40587L,40588L,40589L,40590L,40591L,40592L,
83768 40593L,40594L,40595L,40596L,40597L,40598L,40599L,40600L,40601L,40602L,
83769 40603L,40604L,40605L,40606L,40607L,40608L,40609L,40610L,40611L,40612L,
83770 40613L,40614L,40615L,40616L,40617L,40618L,40619L,40620L,40621L,40622L,
83771 40623L,40624L,40625L,40626L,40627L,40628L,40629L,40630L,40631L,40632L,
83772 40633L,40634L,40635L,40636L,40637L,40638L,40639L,40640L,40641L,40642L,
83773 40643L,40644L,40645L,40646L,40647L,40648L,40649L,40650L,40651L,40652L,
83774 40653L,40654L,40655L,40656L,40657L,40658L,40659L,40660L,40661L,40662L,
83775 40663L,40664L,40665L,40666L,40667L,40668L,40669L,40670L,40671L,40672L,
83776 40673L,40674L,40675L,40676L,40677L,40678L,40679L,40680L,40681L,40682L,
83777 40683L,40684L,40685L,40686L,40687L,40688L,40689L,40690L,40691L,40692L,
83778 40693L,40694L,40695L,40696L,40697L,40698L,40699L,40700L,40701L,40702L,
83779 40703L,40704L,40705L,40706L,40707L,40708L,40709L,40710L,40711L,40712L,
83780 40713L,40714L,40715L,40716L,40717L,40718L,40719L,40720L,40721L,40722L,
83781 40723L,40724L,40725L,40726L,40727L,40728L,40729L,40730L,40731L,40732L,
83782 40733L,40734L,40735L,40736L,40737L,40738L,40739L,40740L,40741L,40742L,
83783 40743L,40744L,40745L,40746L,40747L,40748L,40749L,40750L,40751L,40752L,
83784 40753L,40754L,40755L,40756L,40757L,40758L,40759L,40760L,40761L,40762L,
83785 40763L,40764L,40765L,40766L,40767L,40768L,40769L,40770L,40771L,40772L,
83786 40773L,40774L,40775L,40776L,40777L,40778L,40779L,40780L,40781L,40782L,
83787 40783L,40784L,40785L,40786L,40787L,40788L,40789L,40790L,40791L,40792L,
83788 40793L,40794L,40795L,40796L,40797L,40798L,40799L,40800L,40801L,40802L,
83789 40803L,40804L,40805L,40806L,40807L,40808L,40809L,40810L,40811L,40812L,
83790 40813L,40814L,40815L,40816L,40817L,40818L,40819L,40820L,40821L,40822L,
83791 40823L,40824L,40825L,40826L,40827L,40828L,40829L,40830L,40831L,40832L,
83792 40833L,40834L,40835L,40836L,40837L,40838L,40839L,40840L,40841L,40842L,
83793 40843L,40844L,40845L,40846L,40847L,40848L,40849L,40850L,40851L,40852L,
83794 40853L,40854L,40855L,40856L,40857L,40858L,40859L,40860L,40861L,40862L,
83795 40863L,40864L,40865L,40866L,40867L,40868L,40869L,40870L,40871L,40872L,
83796 40873L,40874L,40875L,40876L,40877L,40878L,40879L,40880L,40881L,40882L,
83797 40883L,40884L,40885L,40886L,40887L,40888L,40889L,40890L,40891L,40892L,
83798 40893L,40894L,40895L,40896L,40897L,40898L,40899L,40900L,40901L,40902L,
83799 40903L,40904L,40905L,40906L,40907L,40908L,40909L,40910L,40911L,40912L,
83800 40913L,40914L,40915L,40916L,40917L,40918L,40919L,40920L,40921L,40922L,
83801 40923L,40924L,40925L,40926L,40927L,40928L,40929L,40930L,40931L,40932L,
83802 40933L,40934L,40935L,40936L,40937L,40938L,40939L,40940L,40941L,40942L,
83803 40943L,40944L,40945L,40946L,40947L,40948L,40949L,40950L,40951L,40952L,
83804 40953L,40954L,40955L,40956L,40957L,40958L,40959L,40960L,40961L,40962L,
83805 40963L,40964L,40965L,40966L,40967L,40968L,40969L,40970L,40971L,40972L,
83806 40973L,40974L,40975L,40976L,40977L,40978L,40979L,40980L,40981L,40982L,
83807 40983L,40984L,40985L,40986L,40987L,40988L,40989L,40990L,40991L,40992L,
83808 40993L,40994L,40995L,40996L,40997L,40998L,40999L,41000L,41001L,41002L,
83809 41003L,41004L,41005L,41006L,41007L,41008L,41009L,41010L,41011L,41012L,
83810 41013L,41014L,41015L,41016L,41017L,41018L,41019L,41020L,41021L,41022L,
83811 41023L,41024L,41025L,41026L,41027L,41028L,41029L,41030L,41031L,41032L,
83812 41033L,41034L,41035L,41036L,41037L,41038L,41039L,41040L,41041L,41042L,
83813 41043L,41044L,41045L,41046L,41047L,41048L,41049L,41050L,41051L,41052L,
83814 41053L,41054L,41055L,41056L,41057L,41058L,41059L,41060L,41061L,41062L,
83815 41063L,41064L,41065L,41066L,41067L,41068L,41069L,41070L,41071L,41072L,
83816 41073L,41074L,41075L,41076L,41077L,41078L,41079L,41080L,41081L,41082L,
83817 41083L,41084L,41085L,41086L,41087L,41088L,41089L,41090L,41091L,41092L,
83818 41093L,41094L,41095L,41096L,41097L,41098L,41099L,41100L,41101L,41102L,
83819 41103L,41104L,41105L,41106L,41107L,41108L,41109L,41110L,41111L,41112L,
83820 41113L,41114L,41115L,41116L,41117L,41118L,41119L,41120L,41121L,41122L,
83821 41123L,41124L,41125L,41126L,41127L,41128L,41129L,41130L,41131L,41132L,
83822 41133L,41134L,41135L,41136L,41137L,41138L,41139L,41140L,41141L,41142L,
83823 41143L,41144L,41145L,41146L,41147L,41148L,41149L,41150L,41151L,41152L,
83824 41153L,41154L,41155L,41156L,41157L,41158L,41159L,41160L,41161L,41162L,
83825 41163L,41164L,41165L,41166L,41167L,41168L,41169L,41170L,41171L,41172L,
83826 41173L,41174L,41175L,41176L,41177L,41178L,41179L,41180L,41181L,41182L,
83827 41183L,41184L,41185L,41186L,41187L,41188L,41189L,41190L,41191L,41192L,
83828 41193L,41194L,41195L,41196L,41197L,41198L,41199L,41200L,41201L,41202L,
83829 41203L,41204L,41205L,41206L,41207L,41208L,41209L,41210L,41211L,41212L,
83830 41213L,41214L,41215L,41216L,41217L,41218L,41219L,41220L,41221L,41222L,
83831 41223L,41224L,41225L,41226L,41227L,41228L,41229L,41230L,41231L,41232L,
83832 41233L,41234L,41235L,41236L,41237L,41238L,41239L,41240L,41241L,41242L,
83833 41243L,41244L,41245L,41246L,41247L,41248L,41249L,41250L,41251L,41252L,
83834 41253L,41254L,41255L,41256L,41257L,41258L,41259L,41260L,41261L,41262L,
83835 41263L,41264L,41265L,41266L,41267L,41268L,41269L,41270L,41271L,41272L,
83836 41273L,41274L,41275L,41276L,41277L,41278L,41279L,41280L,41281L,41282L,
83837 41283L,41284L,41285L,41286L,41287L,41288L,41289L,41290L,41291L,41292L,
83838 41293L,41294L,41295L,41296L,41297L,41298L,41299L,41300L,41301L,41302L,
83839 41303L,41304L,41305L,41306L,41307L,41308L,41309L,41310L,41311L,41312L,
83840 41313L,41314L,41315L,41316L,41317L,41318L,41319L,41320L,41321L,41322L,
83841 41323L,41324L,41325L,41326L,41327L,41328L,41329L,41330L,41331L,41332L,
83842 41333L,41334L,41335L,41336L,41337L,41338L,41339L,41340L,41341L,41342L,
83843 41343L,41344L,41345L,41346L,41347L,41348L,41349L,41350L,41351L,41352L,
83844 41353L,41354L,41355L,41356L,41357L,41358L,41359L,41360L,41361L,41362L,
83845 41363L,41364L,41365L,41366L,41367L,41368L,41369L,41370L,41371L,41372L,
83846 41373L,41374L,41375L,41376L,41377L,41378L,41379L,41380L,41381L,41382L,
83847 41383L,41384L,41385L,41386L,41387L,41388L,41389L,41390L,41391L,41392L,
83848 41393L,41394L,41395L,41396L,41397L,41398L,41399L,41400L,41401L,41402L,
83849 41403L,41404L,41405L,41406L,41407L,41408L,41409L,41410L,41411L,41412L,
83850 41413L,41414L,41415L,41416L,41417L,41418L,41419L,41420L,41421L,41422L,
83851 41423L,41424L,41425L,41426L,41427L,41428L,41429L,41430L,41431L,41432L,
83852 41433L,41434L,41435L,41436L,41437L,41438L,41439L,41440L,41441L,41442L,
83853 41443L,41444L,41445L,41446L,41447L,41448L,41449L,41450L,41451L,41452L,
83854 41453L,41454L,41455L,41456L,41457L,41458L,41459L,41460L,41461L,41462L,
83855 41463L,41464L,41465L,41466L,41467L,41468L,41469L,41470L,41471L,41472L,
83856 41473L,41474L,41475L,41476L,41477L,41478L,41479L,41480L,41481L,41482L,
83857 41483L,41484L,41485L,41486L,41487L,41488L,41489L,41490L,41491L,41492L,
83858 41493L,41494L,41495L,41496L,41497L,41498L,41499L,41500L,41501L,41502L,
83859 41503L,41504L,41505L,41506L,41507L,41508L,41509L,41510L,41511L,41512L,
83860 41513L,41514L,41515L,41516L,41517L,41518L,41519L,41520L,41521L,41522L,
83861 41523L,41524L,41525L,41526L,41527L,41528L,41529L,41530L,41531L,41532L,
83862 41533L,41534L,41535L,41536L,41537L,41538L,41539L,41540L,41541L,41542L,
83863 41543L,41544L,41545L,41546L,41547L,41548L,41549L,41550L,41551L,41552L,
83864 41553L,41554L,41555L,41556L,41557L,41558L,41559L,41560L,41561L,41562L,
83865 41563L,41564L,41565L,41566L,41567L,41568L,41569L,41570L,41571L,41572L,
83866 41573L,41574L,41575L,41576L,41577L,41578L,41579L,41580L,41581L,41582L,
83867 41583L,41584L,41585L,41586L,41587L,41588L,41589L,41590L,41591L,41592L,
83868 41593L,41594L,41595L,41596L,41597L,41598L,41599L,41600L,41601L,41602L,
83869 41603L,41604L,41605L,41606L,41607L,41608L,41609L,41610L,41611L,41612L,
83870 41613L,41614L,41615L,41616L,41617L,41618L,41619L,41620L,41621L,41622L,
83871 41623L,41624L,41625L,41626L,41627L,41628L,41629L,41630L,41631L,41632L,
83872 41633L,41634L,41635L,41636L,41637L,41638L,41639L,41640L,41641L,41642L,
83873 41643L,41644L,41645L,41646L,41647L,41648L,41649L,41650L,41651L,41652L,
83874 41653L,41654L,41655L,41656L,41657L,41658L,41659L,41660L,41661L,41662L,
83875 41663L,41664L,41665L,41666L,41667L,41668L,41669L,41670L,41671L,41672L,
83876 41673L,41674L,41675L,41676L,41677L,41678L,41679L,41680L,41681L,41682L,
83877 41683L,41684L,41685L,41686L,41687L,41688L,41689L,41690L,41691L,41692L,
83878 41693L,41694L,41695L,41696L,41697L,41698L,41699L,41700L,41701L,41702L,
83879 41703L,41704L,41705L,41706L,41707L,41708L,41709L,41710L,41711L,41712L,
83880 41713L,41714L,41715L,41716L,41717L,41718L,41719L,41720L,41721L,41722L,
83881 41723L,41724L,41725L,41726L,41727L,41728L,41729L,41730L,41731L,41732L,
83882 41733L,41734L,41735L,41736L,41737L,41738L,41739L,41740L,41741L,41742L,
83883 41743L,41744L,41745L,41746L,41747L,41748L,41749L,41750L,41751L,41752L,
83884 41753L,41754L,41755L,41756L,41757L,41758L,41759L,41760L,41761L,41762L,
83885 41763L,41764L,41765L,41766L,41767L,41768L,41769L,41770L,41771L,41772L,
83886 41773L,41774L,41775L,41776L,41777L,41778L,41779L,41780L,41781L,41782L,
83887 41783L,41784L,41785L,41786L,41787L,41788L,41789L,41790L,41791L,41792L,
83888 41793L,41794L,41795L,41796L,41797L,41798L,41799L,41800L,41801L,41802L,
83889 41803L,41804L,41805L,41806L,41807L,41808L,41809L,41810L,41811L,41812L,
83890 41813L,41814L,41815L,41816L,41817L,41818L,41819L,41820L,41821L,41822L,
83891 41823L,41824L,41825L,41826L,41827L,41828L,41829L,41830L,41831L,41832L,
83892 41833L,41834L,41835L,41836L,41837L,41838L,41839L,41840L,41841L,41842L,
83893 41843L,41844L,41845L,41846L,41847L,41848L,41849L,41850L,41851L,41852L,
83894 41853L,41854L,41855L,41856L,41857L,41858L,41859L,41860L,41861L,41862L,
83895 41863L,41864L,41865L,41866L,41867L,41868L,41869L,41870L,41871L,41872L,
83896 41873L,41874L,41875L,41876L,41877L,41878L,41879L,41880L,41881L,41882L,
83897 41883L,41884L,41885L,41886L,41887L,41888L,41889L,41890L,41891L,41892L,
83898 41893L,41894L,41895L,41896L,41897L,41898L,41899L,41900L,41901L,41902L,
83899 41903L,41904L,41905L,41906L,41907L,41908L,41909L,41910L,41911L,41912L,
83900 41913L,41914L,41915L,41916L,41917L,41918L,41919L,41920L,41921L,41922L,
83901 41923L,41924L,41925L,41926L,41927L,41928L,41929L,41930L,41931L,41932L,
83902 41933L,41934L,41935L,41936L,41937L,41938L,41939L,41940L,41941L,41942L,
83903 41943L,41944L,41945L,41946L,41947L,41948L,41949L,41950L,41951L,41952L,
83904 41953L,41954L,41955L,41956L,41957L,41958L,41959L,41960L,41961L,41962L,
83905 41963L,41964L,41965L,41966L,41967L,41968L,41969L,41970L,41971L,41972L,
83906 41973L,41974L,41975L,41976L,41977L,41978L,41979L,41980L,41981L,41982L,
83907 41983L,41984L,41985L,41986L,41987L,41988L,41989L,41990L,41991L,41992L,
83908 41993L,41994L,41995L,41996L,41997L,41998L,41999L,42000L,42001L,42002L,
83909 42003L,42004L,42005L,42006L,42007L,42008L,42009L,42010L,42011L,42012L,
83910 42013L,42014L,42015L,42016L,42017L,42018L,42019L,42020L,42021L,42022L,
83911 42023L,42024L,42025L,42026L,42027L,42028L,42029L,42030L,42031L,42032L,
83912 42033L,42034L,42035L,42036L,42037L,42038L,42039L,42040L,42041L,42042L,
83913 42043L,42044L,42045L,42046L,42047L,42048L,42049L,42050L,42051L,42052L,
83914 42053L,42054L,42055L,42056L,42057L,42058L,42059L,42060L,42061L,42062L,
83915 42063L,42064L,42065L,42066L,42067L,42068L,42069L,42070L,42071L,42072L,
83916 42073L,42074L,42075L,42076L,42077L,42078L,42079L,42080L,42081L,42082L,
83917 42083L,42084L,42085L,42086L,42087L,42088L,42089L,42090L,42091L,42092L,
83918 42093L,42094L,42095L,42096L,42097L,42098L,42099L,42100L,42101L,42102L,
83919 42103L,42104L,42105L,42106L,42107L,42108L,42109L,42110L,42111L,42112L,
83920 42113L,42114L,42115L,42116L,42117L,42118L,42119L,42120L,42121L,42122L,
83921 42123L,42124L,42125L,42126L,42127L,42128L,42129L,42130L,42131L,42132L,
83922 42133L,42134L,42135L,42136L,42137L,42138L,42139L,42140L,42141L,42142L,
83923 42143L,42144L,42145L,42146L,42147L,42148L,42149L,42150L,42151L,42152L,
83924 42153L,42154L,42155L,42156L,42157L,42158L,42159L,42160L,42161L,42162L,
83925 42163L,42164L,42165L,42166L,42167L,42168L,42169L,42170L,42171L,42172L,
83926 42173L,42174L,42175L,42176L,42177L,42178L,42179L,42180L,42181L,42182L,
83927 42183L,42184L,42185L,42186L,42187L,42188L,42189L,42190L,42191L,42192L,
83928 42193L,42194L,42195L,42196L,42197L,42198L,42199L,42200L,42201L,42202L,
83929 42203L,42204L,42205L,42206L,42207L,42208L,42209L,42210L,42211L,42212L,
83930 42213L,42214L,42215L,42216L,42217L,42218L,42219L,42220L,42221L,42222L,
83931 42223L,42224L,42225L,42226L,42227L,42228L,42229L,42230L,42231L,42232L,
83932 42233L,42234L,42235L,42236L,42237L,42238L,42239L,42240L,42241L,42242L,
83933 42243L,42244L,42245L,42246L,42247L,42248L,42249L,42250L,42251L,42252L,
83934 42253L,42254L,42255L,42256L,42257L,42258L,42259L,42260L,42261L,42262L,
83935 42263L,42264L,42265L,42266L,42267L,42268L,42269L,42270L,42271L,42272L,
83936 42273L,42274L,42275L,42276L,42277L,42278L,42279L,42280L,42281L,42282L,
83937 42283L,42284L,42285L,42286L,42287L,42288L,42289L,42290L,42291L,42292L,
83938 42293L,42294L,42295L,42296L,42297L,42298L,42299L,42300L,42301L,42302L,
83939 42303L,42304L,42305L,42306L,42307L,42308L,42309L,42310L,42311L,42312L,
83940 42313L,42314L,42315L,42316L,42317L,42318L,42319L,42320L,42321L,42322L,
83941 42323L,42324L,42325L,42326L,42327L,42328L,42329L,42330L,42331L,42332L,
83942 42333L,42334L,42335L,42336L,42337L,42338L,42339L,42340L,42341L,42342L,
83943 42343L,42344L,42345L,42346L,42347L,42348L,42349L,42350L,42351L,42352L,
83944 42353L,42354L,42355L,42356L,42357L,42358L,42359L,42360L,42361L,42362L,
83945 42363L,42364L,42365L,42366L,42367L,42368L,42369L,42370L,42371L,42372L,
83946 42373L,42374L,42375L,42376L,42377L,42378L,42379L,42380L,42381L,42382L,
83947 42383L,42384L,42385L,42386L,42387L,42388L,42389L,42390L,42391L,42392L,
83948 42393L,42394L,42395L,42396L,42397L,42398L,42399L,42400L,42401L,42402L,
83949 42403L,42404L,42405L,42406L,42407L,42408L,42409L,42410L,42411L,42412L,
83950 42413L,42414L,42415L,42416L,42417L,42418L,42419L,42420L,42421L,42422L,
83951 42423L,42424L,42425L,42426L,42427L,42428L,42429L,42430L,42431L,42432L,
83952 42433L,42434L,42435L,42436L,42437L,42438L,42439L,42440L,42441L,42442L,
83953 42443L,42444L,42445L,42446L,42447L,42448L,42449L,42450L,42451L,42452L,
83954 42453L,42454L,42455L,42456L,42457L,42458L,42459L,42460L,42461L,42462L,
83955 42463L,42464L,42465L,42466L,42467L,42468L,42469L,42470L,42471L,42472L,
83956 42473L,42474L,42475L,42476L,42477L,42478L,42479L,42480L,42481L,42482L,
83957 42483L,42484L,42485L,42486L,42487L,42488L,42489L,42490L,42491L,42492L,
83958 42493L,42494L,42495L,42496L,42497L,42498L,42499L,42500L,42501L,42502L,
83959 42503L,42504L,42505L,42506L,42507L,42508L,42509L,42510L,42511L,42512L,
83960 42513L,42514L,42515L,42516L,42517L,42518L,42519L,42520L,42521L,42522L,
83961 42523L,42524L,42525L,42526L,42527L,42528L,42529L,42530L,42531L,42532L,
83962 42533L,42534L,42535L,42536L,42537L,42538L,42539L,42540L,42541L,42542L,
83963 42543L,42544L,42545L,42546L,42547L,42548L,42549L,42550L,42551L,42552L,
83964 42553L,42554L,42555L,42556L,42557L,42558L,42559L,42560L,42560L,42562L,
83965 42562L,42564L,42564L,42566L,42566L,42568L,42568L,42570L,42570L,42572L,
83966 42572L,42574L,42574L,42576L,42576L,42578L,42578L,42580L,42580L,42582L,
83967 42582L,42584L,42584L,42586L,42586L,42588L,42588L,42590L,42590L,42592L,
83968 42592L,42594L,42594L,42596L,42596L,42598L,42598L,42600L,42600L,42602L,
83969 42602L,42604L,42604L,42606L,42607L,42608L,42609L,42610L,42611L,42612L,
83970 42613L,42614L,42615L,42616L,42617L,42618L,42619L,42620L,42621L,42622L,
83971 42623L,42624L,42624L,42626L,42626L,42628L,42628L,42630L,42630L,42632L,
83972 42632L,42634L,42634L,42636L,42636L,42638L,42638L,42640L,42640L,42642L,
83973 42642L,42644L,42644L,42646L,42646L,42648L,42649L,42650L,42651L,42652L,
83974 42653L,42654L,42655L,42656L,42657L,42658L,42659L,42660L,42661L,42662L,
83975 42663L,42664L,42665L,42666L,42667L,42668L,42669L,42670L,42671L,42672L,
83976 42673L,42674L,42675L,42676L,42677L,42678L,42679L,42680L,42681L,42682L,
83977 42683L,42684L,42685L,42686L,42687L,42688L,42689L,42690L,42691L,42692L,
83978 42693L,42694L,42695L,42696L,42697L,42698L,42699L,42700L,42701L,42702L,
83979 42703L,42704L,42705L,42706L,42707L,42708L,42709L,42710L,42711L,42712L,
83980 42713L,42714L,42715L,42716L,42717L,42718L,42719L,42720L,42721L,42722L,
83981 42723L,42724L,42725L,42726L,42727L,42728L,42729L,42730L,42731L,42732L,
83982 42733L,42734L,42735L,42736L,42737L,42738L,42739L,42740L,42741L,42742L,
83983 42743L,42744L,42745L,42746L,42747L,42748L,42749L,42750L,42751L,42752L,
83984 42753L,42754L,42755L,42756L,42757L,42758L,42759L,42760L,42761L,42762L,
83985 42763L,42764L,42765L,42766L,42767L,42768L,42769L,42770L,42771L,42772L,
83986 42773L,42774L,42775L,42776L,42777L,42778L,42779L,42780L,42781L,42782L,
83987 42783L,42784L,42785L,42786L,42786L,42788L,42788L,42790L,42790L,42792L,
83988 42792L,42794L,42794L,42796L,42796L,42798L,42798L,42800L,42801L,42802L,
83989 42802L,42804L,42804L,42806L,42806L,42808L,42808L,42810L,42810L,42812L,
83990 42812L,42814L,42814L,42816L,42816L,42818L,42818L,42820L,42820L,42822L,
83991 42822L,42824L,42824L,42826L,42826L,42828L,42828L,42830L,42830L,42832L,
83992 42832L,42834L,42834L,42836L,42836L,42838L,42838L,42840L,42840L,42842L,
83993 42842L,42844L,42844L,42846L,42846L,42848L,42848L,42850L,42850L,42852L,
83994 42852L,42854L,42854L,42856L,42856L,42858L,42858L,42860L,42860L,42862L,
83995 42862L,42864L,42865L,42866L,42867L,42868L,42869L,42870L,42871L,42872L,
83996 42873L,42873L,42875L,42875L,42877L,42878L,42878L,42880L,42880L,42882L,
83997 42882L,42884L,42884L,42886L,42886L,42888L,42889L,42890L,42891L,42891L,
83998 42893L,42894L,42895L,42896L,42896L,42898L,42899L,42900L,42901L,42902L,
83999 42903L,42904L,42905L,42906L,42907L,42908L,42909L,42910L,42911L,42912L,
84000 42912L,42914L,42914L,42916L,42916L,42918L,42918L,42920L,42920L,42922L,
84001 42923L,42924L,42925L,42926L,42927L,42928L,42929L,42930L,42931L,42932L,
84002 42933L,42934L,42935L,42936L,42937L,42938L,42939L,42940L,42941L,42942L,
84003 42943L,42944L,42945L,42946L,42947L,42948L,42949L,42950L,42951L,42952L,
84004 42953L,42954L,42955L,42956L,42957L,42958L,42959L,42960L,42961L,42962L,
84005 42963L,42964L,42965L,42966L,42967L,42968L,42969L,42970L,42971L,42972L,
84006 42973L,42974L,42975L,42976L,42977L,42978L,42979L,42980L,42981L,42982L,
84007 42983L,42984L,42985L,42986L,42987L,42988L,42989L,42990L,42991L,42992L,
84008 42993L,42994L,42995L,42996L,42997L,42998L,42999L,43000L,43001L,43002L,
84009 43003L,43004L,43005L,43006L,43007L,43008L,43009L,43010L,43011L,43012L,
84010 43013L,43014L,43015L,43016L,43017L,43018L,43019L,43020L,43021L,43022L,
84011 43023L,43024L,43025L,43026L,43027L,43028L,43029L,43030L,43031L,43032L,
84012 43033L,43034L,43035L,43036L,43037L,43038L,43039L,43040L,43041L,43042L,
84013 43043L,43044L,43045L,43046L,43047L,43048L,43049L,43050L,43051L,43052L,
84014 43053L,43054L,43055L,43056L,43057L,43058L,43059L,43060L,43061L,43062L,
84015 43063L,43064L,43065L,43066L,43067L,43068L,43069L,43070L,43071L,43072L,
84016 43073L,43074L,43075L,43076L,43077L,43078L,43079L,43080L,43081L,43082L,
84017 43083L,43084L,43085L,43086L,43087L,43088L,43089L,43090L,43091L,43092L,
84018 43093L,43094L,43095L,43096L,43097L,43098L,43099L,43100L,43101L,43102L,
84019 43103L,43104L,43105L,43106L,43107L,43108L,43109L,43110L,43111L,43112L,
84020 43113L,43114L,43115L,43116L,43117L,43118L,43119L,43120L,43121L,43122L,
84021 43123L,43124L,43125L,43126L,43127L,43128L,43129L,43130L,43131L,43132L,
84022 43133L,43134L,43135L,43136L,43137L,43138L,43139L,43140L,43141L,43142L,
84023 43143L,43144L,43145L,43146L,43147L,43148L,43149L,43150L,43151L,43152L,
84024 43153L,43154L,43155L,43156L,43157L,43158L,43159L,43160L,43161L,43162L,
84025 43163L,43164L,43165L,43166L,43167L,43168L,43169L,43170L,43171L,43172L,
84026 43173L,43174L,43175L,43176L,43177L,43178L,43179L,43180L,43181L,43182L,
84027 43183L,43184L,43185L,43186L,43187L,43188L,43189L,43190L,43191L,43192L,
84028 43193L,43194L,43195L,43196L,43197L,43198L,43199L,43200L,43201L,43202L,
84029 43203L,43204L,43205L,43206L,43207L,43208L,43209L,43210L,43211L,43212L,
84030 43213L,43214L,43215L,43216L,43217L,43218L,43219L,43220L,43221L,43222L,
84031 43223L,43224L,43225L,43226L,43227L,43228L,43229L,43230L,43231L,43232L,
84032 43233L,43234L,43235L,43236L,43237L,43238L,43239L,43240L,43241L,43242L,
84033 43243L,43244L,43245L,43246L,43247L,43248L,43249L,43250L,43251L,43252L,
84034 43253L,43254L,43255L,43256L,43257L,43258L,43259L,43260L,43261L,43262L,
84035 43263L,43264L,43265L,43266L,43267L,43268L,43269L,43270L,43271L,43272L,
84036 43273L,43274L,43275L,43276L,43277L,43278L,43279L,43280L,43281L,43282L,
84037 43283L,43284L,43285L,43286L,43287L,43288L,43289L,43290L,43291L,43292L,
84038 43293L,43294L,43295L,43296L,43297L,43298L,43299L,43300L,43301L,43302L,
84039 43303L,43304L,43305L,43306L,43307L,43308L,43309L,43310L,43311L,43312L,
84040 43313L,43314L,43315L,43316L,43317L,43318L,43319L,43320L,43321L,43322L,
84041 43323L,43324L,43325L,43326L,43327L,43328L,43329L,43330L,43331L,43332L,
84042 43333L,43334L,43335L,43336L,43337L,43338L,43339L,43340L,43341L,43342L,
84043 43343L,43344L,43345L,43346L,43347L,43348L,43349L,43350L,43351L,43352L,
84044 43353L,43354L,43355L,43356L,43357L,43358L,43359L,43360L,43361L,43362L,
84045 43363L,43364L,43365L,43366L,43367L,43368L,43369L,43370L,43371L,43372L,
84046 43373L,43374L,43375L,43376L,43377L,43378L,43379L,43380L,43381L,43382L,
84047 43383L,43384L,43385L,43386L,43387L,43388L,43389L,43390L,43391L,43392L,
84048 43393L,43394L,43395L,43396L,43397L,43398L,43399L,43400L,43401L,43402L,
84049 43403L,43404L,43405L,43406L,43407L,43408L,43409L,43410L,43411L,43412L,
84050 43413L,43414L,43415L,43416L,43417L,43418L,43419L,43420L,43421L,43422L,
84051 43423L,43424L,43425L,43426L,43427L,43428L,43429L,43430L,43431L,43432L,
84052 43433L,43434L,43435L,43436L,43437L,43438L,43439L,43440L,43441L,43442L,
84053 43443L,43444L,43445L,43446L,43447L,43448L,43449L,43450L,43451L,43452L,
84054 43453L,43454L,43455L,43456L,43457L,43458L,43459L,43460L,43461L,43462L,
84055 43463L,43464L,43465L,43466L,43467L,43468L,43469L,43470L,43471L,43472L,
84056 43473L,43474L,43475L,43476L,43477L,43478L,43479L,43480L,43481L,43482L,
84057 43483L,43484L,43485L,43486L,43487L,43488L,43489L,43490L,43491L,43492L,
84058 43493L,43494L,43495L,43496L,43497L,43498L,43499L,43500L,43501L,43502L,
84059 43503L,43504L,43505L,43506L,43507L,43508L,43509L,43510L,43511L,43512L,
84060 43513L,43514L,43515L,43516L,43517L,43518L,43519L,43520L,43521L,43522L,
84061 43523L,43524L,43525L,43526L,43527L,43528L,43529L,43530L,43531L,43532L,
84062 43533L,43534L,43535L,43536L,43537L,43538L,43539L,43540L,43541L,43542L,
84063 43543L,43544L,43545L,43546L,43547L,43548L,43549L,43550L,43551L,43552L,
84064 43553L,43554L,43555L,43556L,43557L,43558L,43559L,43560L,43561L,43562L,
84065 43563L,43564L,43565L,43566L,43567L,43568L,43569L,43570L,43571L,43572L,
84066 43573L,43574L,43575L,43576L,43577L,43578L,43579L,43580L,43581L,43582L,
84067 43583L,43584L,43585L,43586L,43587L,43588L,43589L,43590L,43591L,43592L,
84068 43593L,43594L,43595L,43596L,43597L,43598L,43599L,43600L,43601L,43602L,
84069 43603L,43604L,43605L,43606L,43607L,43608L,43609L,43610L,43611L,43612L,
84070 43613L,43614L,43615L,43616L,43617L,43618L,43619L,43620L,43621L,43622L,
84071 43623L,43624L,43625L,43626L,43627L,43628L,43629L,43630L,43631L,43632L,
84072 43633L,43634L,43635L,43636L,43637L,43638L,43639L,43640L,43641L,43642L,
84073 43643L,43644L,43645L,43646L,43647L,43648L,43649L,43650L,43651L,43652L,
84074 43653L,43654L,43655L,43656L,43657L,43658L,43659L,43660L,43661L,43662L,
84075 43663L,43664L,43665L,43666L,43667L,43668L,43669L,43670L,43671L,43672L,
84076 43673L,43674L,43675L,43676L,43677L,43678L,43679L,43680L,43681L,43682L,
84077 43683L,43684L,43685L,43686L,43687L,43688L,43689L,43690L,43691L,43692L,
84078 43693L,43694L,43695L,43696L,43697L,43698L,43699L,43700L,43701L,43702L,
84079 43703L,43704L,43705L,43706L,43707L,43708L,43709L,43710L,43711L,43712L,
84080 43713L,43714L,43715L,43716L,43717L,43718L,43719L,43720L,43721L,43722L,
84081 43723L,43724L,43725L,43726L,43727L,43728L,43729L,43730L,43731L,43732L,
84082 43733L,43734L,43735L,43736L,43737L,43738L,43739L,43740L,43741L,43742L,
84083 43743L,43744L,43745L,43746L,43747L,43748L,43749L,43750L,43751L,43752L,
84084 43753L,43754L,43755L,43756L,43757L,43758L,43759L,43760L,43761L,43762L,
84085 43763L,43764L,43765L,43766L,43767L,43768L,43769L,43770L,43771L,43772L,
84086 43773L,43774L,43775L,43776L,43777L,43778L,43779L,43780L,43781L,43782L,
84087 43783L,43784L,43785L,43786L,43787L,43788L,43789L,43790L,43791L,43792L,
84088 43793L,43794L,43795L,43796L,43797L,43798L,43799L,43800L,43801L,43802L,
84089 43803L,43804L,43805L,43806L,43807L,43808L,43809L,43810L,43811L,43812L,
84090 43813L,43814L,43815L,43816L,43817L,43818L,43819L,43820L,43821L,43822L,
84091 43823L,43824L,43825L,43826L,43827L,43828L,43829L,43830L,43831L,43832L,
84092 43833L,43834L,43835L,43836L,43837L,43838L,43839L,43840L,43841L,43842L,
84093 43843L,43844L,43845L,43846L,43847L,43848L,43849L,43850L,43851L,43852L,
84094 43853L,43854L,43855L,43856L,43857L,43858L,43859L,43860L,43861L,43862L,
84095 43863L,43864L,43865L,43866L,43867L,43868L,43869L,43870L,43871L,43872L,
84096 43873L,43874L,43875L,43876L,43877L,43878L,43879L,43880L,43881L,43882L,
84097 43883L,43884L,43885L,43886L,43887L,43888L,43889L,43890L,43891L,43892L,
84098 43893L,43894L,43895L,43896L,43897L,43898L,43899L,43900L,43901L,43902L,
84099 43903L,43904L,43905L,43906L,43907L,43908L,43909L,43910L,43911L,43912L,
84100 43913L,43914L,43915L,43916L,43917L,43918L,43919L,43920L,43921L,43922L,
84101 43923L,43924L,43925L,43926L,43927L,43928L,43929L,43930L,43931L,43932L,
84102 43933L,43934L,43935L,43936L,43937L,43938L,43939L,43940L,43941L,43942L,
84103 43943L,43944L,43945L,43946L,43947L,43948L,43949L,43950L,43951L,43952L,
84104 43953L,43954L,43955L,43956L,43957L,43958L,43959L,43960L,43961L,43962L,
84105 43963L,43964L,43965L,43966L,43967L,43968L,43969L,43970L,43971L,43972L,
84106 43973L,43974L,43975L,43976L,43977L,43978L,43979L,43980L,43981L,43982L,
84107 43983L,43984L,43985L,43986L,43987L,43988L,43989L,43990L,43991L,43992L,
84108 43993L,43994L,43995L,43996L,43997L,43998L,43999L,44000L,44001L,44002L,
84109 44003L,44004L,44005L,44006L,44007L,44008L,44009L,44010L,44011L,44012L,
84110 44013L,44014L,44015L,44016L,44017L,44018L,44019L,44020L,44021L,44022L,
84111 44023L,44024L,44025L,44026L,44027L,44028L,44029L,44030L,44031L,44032L,
84112 44033L,44034L,44035L,44036L,44037L,44038L,44039L,44040L,44041L,44042L,
84113 44043L,44044L,44045L,44046L,44047L,44048L,44049L,44050L,44051L,44052L,
84114 44053L,44054L,44055L,44056L,44057L,44058L,44059L,44060L,44061L,44062L,
84115 44063L,44064L,44065L,44066L,44067L,44068L,44069L,44070L,44071L,44072L,
84116 44073L,44074L,44075L,44076L,44077L,44078L,44079L,44080L,44081L,44082L,
84117 44083L,44084L,44085L,44086L,44087L,44088L,44089L,44090L,44091L,44092L,
84118 44093L,44094L,44095L,44096L,44097L,44098L,44099L,44100L,44101L,44102L,
84119 44103L,44104L,44105L,44106L,44107L,44108L,44109L,44110L,44111L,44112L,
84120 44113L,44114L,44115L,44116L,44117L,44118L,44119L,44120L,44121L,44122L,
84121 44123L,44124L,44125L,44126L,44127L,44128L,44129L,44130L,44131L,44132L,
84122 44133L,44134L,44135L,44136L,44137L,44138L,44139L,44140L,44141L,44142L,
84123 44143L,44144L,44145L,44146L,44147L,44148L,44149L,44150L,44151L,44152L,
84124 44153L,44154L,44155L,44156L,44157L,44158L,44159L,44160L,44161L,44162L,
84125 44163L,44164L,44165L,44166L,44167L,44168L,44169L,44170L,44171L,44172L,
84126 44173L,44174L,44175L,44176L,44177L,44178L,44179L,44180L,44181L,44182L,
84127 44183L,44184L,44185L,44186L,44187L,44188L,44189L,44190L,44191L,44192L,
84128 44193L,44194L,44195L,44196L,44197L,44198L,44199L,44200L,44201L,44202L,
84129 44203L,44204L,44205L,44206L,44207L,44208L,44209L,44210L,44211L,44212L,
84130 44213L,44214L,44215L,44216L,44217L,44218L,44219L,44220L,44221L,44222L,
84131 44223L,44224L,44225L,44226L,44227L,44228L,44229L,44230L,44231L,44232L,
84132 44233L,44234L,44235L,44236L,44237L,44238L,44239L,44240L,44241L,44242L,
84133 44243L,44244L,44245L,44246L,44247L,44248L,44249L,44250L,44251L,44252L,
84134 44253L,44254L,44255L,44256L,44257L,44258L,44259L,44260L,44261L,44262L,
84135 44263L,44264L,44265L,44266L,44267L,44268L,44269L,44270L,44271L,44272L,
84136 44273L,44274L,44275L,44276L,44277L,44278L,44279L,44280L,44281L,44282L,
84137 44283L,44284L,44285L,44286L,44287L,44288L,44289L,44290L,44291L,44292L,
84138 44293L,44294L,44295L,44296L,44297L,44298L,44299L,44300L,44301L,44302L,
84139 44303L,44304L,44305L,44306L,44307L,44308L,44309L,44310L,44311L,44312L,
84140 44313L,44314L,44315L,44316L,44317L,44318L,44319L,44320L,44321L,44322L,
84141 44323L,44324L,44325L,44326L,44327L,44328L,44329L,44330L,44331L,44332L,
84142 44333L,44334L,44335L,44336L,44337L,44338L,44339L,44340L,44341L,44342L,
84143 44343L,44344L,44345L,44346L,44347L,44348L,44349L,44350L,44351L,44352L,
84144 44353L,44354L,44355L,44356L,44357L,44358L,44359L,44360L,44361L,44362L,
84145 44363L,44364L,44365L,44366L,44367L,44368L,44369L,44370L,44371L,44372L,
84146 44373L,44374L,44375L,44376L,44377L,44378L,44379L,44380L,44381L,44382L,
84147 44383L,44384L,44385L,44386L,44387L,44388L,44389L,44390L,44391L,44392L,
84148 44393L,44394L,44395L,44396L,44397L,44398L,44399L,44400L,44401L,44402L,
84149 44403L,44404L,44405L,44406L,44407L,44408L,44409L,44410L,44411L,44412L,
84150 44413L,44414L,44415L,44416L,44417L,44418L,44419L,44420L,44421L,44422L,
84151 44423L,44424L,44425L,44426L,44427L,44428L,44429L,44430L,44431L,44432L,
84152 44433L,44434L,44435L,44436L,44437L,44438L,44439L,44440L,44441L,44442L,
84153 44443L,44444L,44445L,44446L,44447L,44448L,44449L,44450L,44451L,44452L,
84154 44453L,44454L,44455L,44456L,44457L,44458L,44459L,44460L,44461L,44462L,
84155 44463L,44464L,44465L,44466L,44467L,44468L,44469L,44470L,44471L,44472L,
84156 44473L,44474L,44475L,44476L,44477L,44478L,44479L,44480L,44481L,44482L,
84157 44483L,44484L,44485L,44486L,44487L,44488L,44489L,44490L,44491L,44492L,
84158 44493L,44494L,44495L,44496L,44497L,44498L,44499L,44500L,44501L,44502L,
84159 44503L,44504L,44505L,44506L,44507L,44508L,44509L,44510L,44511L,44512L,
84160 44513L,44514L,44515L,44516L,44517L,44518L,44519L,44520L,44521L,44522L,
84161 44523L,44524L,44525L,44526L,44527L,44528L,44529L,44530L,44531L,44532L,
84162 44533L,44534L,44535L,44536L,44537L,44538L,44539L,44540L,44541L,44542L,
84163 44543L,44544L,44545L,44546L,44547L,44548L,44549L,44550L,44551L,44552L,
84164 44553L,44554L,44555L,44556L,44557L,44558L,44559L,44560L,44561L,44562L,
84165 44563L,44564L,44565L,44566L,44567L,44568L,44569L,44570L,44571L,44572L,
84166 44573L,44574L,44575L,44576L,44577L,44578L,44579L,44580L,44581L,44582L,
84167 44583L,44584L,44585L,44586L,44587L,44588L,44589L,44590L,44591L,44592L,
84168 44593L,44594L,44595L,44596L,44597L,44598L,44599L,44600L,44601L,44602L,
84169 44603L,44604L,44605L,44606L,44607L,44608L,44609L,44610L,44611L,44612L,
84170 44613L,44614L,44615L,44616L,44617L,44618L,44619L,44620L,44621L,44622L,
84171 44623L,44624L,44625L,44626L,44627L,44628L,44629L,44630L,44631L,44632L,
84172 44633L,44634L,44635L,44636L,44637L,44638L,44639L,44640L,44641L,44642L,
84173 44643L,44644L,44645L,44646L,44647L,44648L,44649L,44650L,44651L,44652L,
84174 44653L,44654L,44655L,44656L,44657L,44658L,44659L,44660L,44661L,44662L,
84175 44663L,44664L,44665L,44666L,44667L,44668L,44669L,44670L,44671L,44672L,
84176 44673L,44674L,44675L,44676L,44677L,44678L,44679L,44680L,44681L,44682L,
84177 44683L,44684L,44685L,44686L,44687L,44688L,44689L,44690L,44691L,44692L,
84178 44693L,44694L,44695L,44696L,44697L,44698L,44699L,44700L,44701L,44702L,
84179 44703L,44704L,44705L,44706L,44707L,44708L,44709L,44710L,44711L,44712L,
84180 44713L,44714L,44715L,44716L,44717L,44718L,44719L,44720L,44721L,44722L,
84181 44723L,44724L,44725L,44726L,44727L,44728L,44729L,44730L,44731L,44732L,
84182 44733L,44734L,44735L,44736L,44737L,44738L,44739L,44740L,44741L,44742L,
84183 44743L,44744L,44745L,44746L,44747L,44748L,44749L,44750L,44751L,44752L,
84184 44753L,44754L,44755L,44756L,44757L,44758L,44759L,44760L,44761L,44762L,
84185 44763L,44764L,44765L,44766L,44767L,44768L,44769L,44770L,44771L,44772L,
84186 44773L,44774L,44775L,44776L,44777L,44778L,44779L,44780L,44781L,44782L,
84187 44783L,44784L,44785L,44786L,44787L,44788L,44789L,44790L,44791L,44792L,
84188 44793L,44794L,44795L,44796L,44797L,44798L,44799L,44800L,44801L,44802L,
84189 44803L,44804L,44805L,44806L,44807L,44808L,44809L,44810L,44811L,44812L,
84190 44813L,44814L,44815L,44816L,44817L,44818L,44819L,44820L,44821L,44822L,
84191 44823L,44824L,44825L,44826L,44827L,44828L,44829L,44830L,44831L,44832L,
84192 44833L,44834L,44835L,44836L,44837L,44838L,44839L,44840L,44841L,44842L,
84193 44843L,44844L,44845L,44846L,44847L,44848L,44849L,44850L,44851L,44852L,
84194 44853L,44854L,44855L,44856L,44857L,44858L,44859L,44860L,44861L,44862L,
84195 44863L,44864L,44865L,44866L,44867L,44868L,44869L,44870L,44871L,44872L,
84196 44873L,44874L,44875L,44876L,44877L,44878L,44879L,44880L,44881L,44882L,
84197 44883L,44884L,44885L,44886L,44887L,44888L,44889L,44890L,44891L,44892L,
84198 44893L,44894L,44895L,44896L,44897L,44898L,44899L,44900L,44901L,44902L,
84199 44903L,44904L,44905L,44906L,44907L,44908L,44909L,44910L,44911L,44912L,
84200 44913L,44914L,44915L,44916L,44917L,44918L,44919L,44920L,44921L,44922L,
84201 44923L,44924L,44925L,44926L,44927L,44928L,44929L,44930L,44931L,44932L,
84202 44933L,44934L,44935L,44936L,44937L,44938L,44939L,44940L,44941L,44942L,
84203 44943L,44944L,44945L,44946L,44947L,44948L,44949L,44950L,44951L,44952L,
84204 44953L,44954L,44955L,44956L,44957L,44958L,44959L,44960L,44961L,44962L,
84205 44963L,44964L,44965L,44966L,44967L,44968L,44969L,44970L,44971L,44972L,
84206 44973L,44974L,44975L,44976L,44977L,44978L,44979L,44980L,44981L,44982L,
84207 44983L,44984L,44985L,44986L,44987L,44988L,44989L,44990L,44991L,44992L,
84208 44993L,44994L,44995L,44996L,44997L,44998L,44999L,45000L,45001L,45002L,
84209 45003L,45004L,45005L,45006L,45007L,45008L,45009L,45010L,45011L,45012L,
84210 45013L,45014L,45015L,45016L,45017L,45018L,45019L,45020L,45021L,45022L,
84211 45023L,45024L,45025L,45026L,45027L,45028L,45029L,45030L,45031L,45032L,
84212 45033L,45034L,45035L,45036L,45037L,45038L,45039L,45040L,45041L,45042L,
84213 45043L,45044L,45045L,45046L,45047L,45048L,45049L,45050L,45051L,45052L,
84214 45053L,45054L,45055L,45056L,45057L,45058L,45059L,45060L,45061L,45062L,
84215 45063L,45064L,45065L,45066L,45067L,45068L,45069L,45070L,45071L,45072L,
84216 45073L,45074L,45075L,45076L,45077L,45078L,45079L,45080L,45081L,45082L,
84217 45083L,45084L,45085L,45086L,45087L,45088L,45089L,45090L,45091L,45092L,
84218 45093L,45094L,45095L,45096L,45097L,45098L,45099L,45100L,45101L,45102L,
84219 45103L,45104L,45105L,45106L,45107L,45108L,45109L,45110L,45111L,45112L,
84220 45113L,45114L,45115L,45116L,45117L,45118L,45119L,45120L,45121L,45122L,
84221 45123L,45124L,45125L,45126L,45127L,45128L,45129L,45130L,45131L,45132L,
84222 45133L,45134L,45135L,45136L,45137L,45138L,45139L,45140L,45141L,45142L,
84223 45143L,45144L,45145L,45146L,45147L,45148L,45149L,45150L,45151L,45152L,
84224 45153L,45154L,45155L,45156L,45157L,45158L,45159L,45160L,45161L,45162L,
84225 45163L,45164L,45165L,45166L,45167L,45168L,45169L,45170L,45171L,45172L,
84226 45173L,45174L,45175L,45176L,45177L,45178L,45179L,45180L,45181L,45182L,
84227 45183L,45184L,45185L,45186L,45187L,45188L,45189L,45190L,45191L,45192L,
84228 45193L,45194L,45195L,45196L,45197L,45198L,45199L,45200L,45201L,45202L,
84229 45203L,45204L,45205L,45206L,45207L,45208L,45209L,45210L,45211L,45212L,
84230 45213L,45214L,45215L,45216L,45217L,45218L,45219L,45220L,45221L,45222L,
84231 45223L,45224L,45225L,45226L,45227L,45228L,45229L,45230L,45231L,45232L,
84232 45233L,45234L,45235L,45236L,45237L,45238L,45239L,45240L,45241L,45242L,
84233 45243L,45244L,45245L,45246L,45247L,45248L,45249L,45250L,45251L,45252L,
84234 45253L,45254L,45255L,45256L,45257L,45258L,45259L,45260L,45261L,45262L,
84235 45263L,45264L,45265L,45266L,45267L,45268L,45269L,45270L,45271L,45272L,
84236 45273L,45274L,45275L,45276L,45277L,45278L,45279L,45280L,45281L,45282L,
84237 45283L,45284L,45285L,45286L,45287L,45288L,45289L,45290L,45291L,45292L,
84238 45293L,45294L,45295L,45296L,45297L,45298L,45299L,45300L,45301L,45302L,
84239 45303L,45304L,45305L,45306L,45307L,45308L,45309L,45310L,45311L,45312L,
84240 45313L,45314L,45315L,45316L,45317L,45318L,45319L,45320L,45321L,45322L,
84241 45323L,45324L,45325L,45326L,45327L,45328L,45329L,45330L,45331L,45332L,
84242 45333L,45334L,45335L,45336L,45337L,45338L,45339L,45340L,45341L,45342L,
84243 45343L,45344L,45345L,45346L,45347L,45348L,45349L,45350L,45351L,45352L,
84244 45353L,45354L,45355L,45356L,45357L,45358L,45359L,45360L,45361L,45362L,
84245 45363L,45364L,45365L,45366L,45367L,45368L,45369L,45370L,45371L,45372L,
84246 45373L,45374L,45375L,45376L,45377L,45378L,45379L,45380L,45381L,45382L,
84247 45383L,45384L,45385L,45386L,45387L,45388L,45389L,45390L,45391L,45392L,
84248 45393L,45394L,45395L,45396L,45397L,45398L,45399L,45400L,45401L,45402L,
84249 45403L,45404L,45405L,45406L,45407L,45408L,45409L,45410L,45411L,45412L,
84250 45413L,45414L,45415L,45416L,45417L,45418L,45419L,45420L,45421L,45422L,
84251 45423L,45424L,45425L,45426L,45427L,45428L,45429L,45430L,45431L,45432L,
84252 45433L,45434L,45435L,45436L,45437L,45438L,45439L,45440L,45441L,45442L,
84253 45443L,45444L,45445L,45446L,45447L,45448L,45449L,45450L,45451L,45452L,
84254 45453L,45454L,45455L,45456L,45457L,45458L,45459L,45460L,45461L,45462L,
84255 45463L,45464L,45465L,45466L,45467L,45468L,45469L,45470L,45471L,45472L,
84256 45473L,45474L,45475L,45476L,45477L,45478L,45479L,45480L,45481L,45482L,
84257 45483L,45484L,45485L,45486L,45487L,45488L,45489L,45490L,45491L,45492L,
84258 45493L,45494L,45495L,45496L,45497L,45498L,45499L,45500L,45501L,45502L,
84259 45503L,45504L,45505L,45506L,45507L,45508L,45509L,45510L,45511L,45512L,
84260 45513L,45514L,45515L,45516L,45517L,45518L,45519L,45520L,45521L,45522L,
84261 45523L,45524L,45525L,45526L,45527L,45528L,45529L,45530L,45531L,45532L,
84262 45533L,45534L,45535L,45536L,45537L,45538L,45539L,45540L,45541L,45542L,
84263 45543L,45544L,45545L,45546L,45547L,45548L,45549L,45550L,45551L,45552L,
84264 45553L,45554L,45555L,45556L,45557L,45558L,45559L,45560L,45561L,45562L,
84265 45563L,45564L,45565L,45566L,45567L,45568L,45569L,45570L,45571L,45572L,
84266 45573L,45574L,45575L,45576L,45577L,45578L,45579L,45580L,45581L,45582L,
84267 45583L,45584L,45585L,45586L,45587L,45588L,45589L,45590L,45591L,45592L,
84268 45593L,45594L,45595L,45596L,45597L,45598L,45599L,45600L,45601L,45602L,
84269 45603L,45604L,45605L,45606L,45607L,45608L,45609L,45610L,45611L,45612L,
84270 45613L,45614L,45615L,45616L,45617L,45618L,45619L,45620L,45621L,45622L,
84271 45623L,45624L,45625L,45626L,45627L,45628L,45629L,45630L,45631L,45632L,
84272 45633L,45634L,45635L,45636L,45637L,45638L,45639L,45640L,45641L,45642L,
84273 45643L,45644L,45645L,45646L,45647L,45648L,45649L,45650L,45651L,45652L,
84274 45653L,45654L,45655L,45656L,45657L,45658L,45659L,45660L,45661L,45662L,
84275 45663L,45664L,45665L,45666L,45667L,45668L,45669L,45670L,45671L,45672L,
84276 45673L,45674L,45675L,45676L,45677L,45678L,45679L,45680L,45681L,45682L,
84277 45683L,45684L,45685L,45686L,45687L,45688L,45689L,45690L,45691L,45692L,
84278 45693L,45694L,45695L,45696L,45697L,45698L,45699L,45700L,45701L,45702L,
84279 45703L,45704L,45705L,45706L,45707L,45708L,45709L,45710L,45711L,45712L,
84280 45713L,45714L,45715L,45716L,45717L,45718L,45719L,45720L,45721L,45722L,
84281 45723L,45724L,45725L,45726L,45727L,45728L,45729L,45730L,45731L,45732L,
84282 45733L,45734L,45735L,45736L,45737L,45738L,45739L,45740L,45741L,45742L,
84283 45743L,45744L,45745L,45746L,45747L,45748L,45749L,45750L,45751L,45752L,
84284 45753L,45754L,45755L,45756L,45757L,45758L,45759L,45760L,45761L,45762L,
84285 45763L,45764L,45765L,45766L,45767L,45768L,45769L,45770L,45771L,45772L,
84286 45773L,45774L,45775L,45776L,45777L,45778L,45779L,45780L,45781L,45782L,
84287 45783L,45784L,45785L,45786L,45787L,45788L,45789L,45790L,45791L,45792L,
84288 45793L,45794L,45795L,45796L,45797L,45798L,45799L,45800L,45801L,45802L,
84289 45803L,45804L,45805L,45806L,45807L,45808L,45809L,45810L,45811L,45812L,
84290 45813L,45814L,45815L,45816L,45817L,45818L,45819L,45820L,45821L,45822L,
84291 45823L,45824L,45825L,45826L,45827L,45828L,45829L,45830L,45831L,45832L,
84292 45833L,45834L,45835L,45836L,45837L,45838L,45839L,45840L,45841L,45842L,
84293 45843L,45844L,45845L,45846L,45847L,45848L,45849L,45850L,45851L,45852L,
84294 45853L,45854L,45855L,45856L,45857L,45858L,45859L,45860L,45861L,45862L,
84295 45863L,45864L,45865L,45866L,45867L,45868L,45869L,45870L,45871L,45872L,
84296 45873L,45874L,45875L,45876L,45877L,45878L,45879L,45880L,45881L,45882L,
84297 45883L,45884L,45885L,45886L,45887L,45888L,45889L,45890L,45891L,45892L,
84298 45893L,45894L,45895L,45896L,45897L,45898L,45899L,45900L,45901L,45902L,
84299 45903L,45904L,45905L,45906L,45907L,45908L,45909L,45910L,45911L,45912L,
84300 45913L,45914L,45915L,45916L,45917L,45918L,45919L,45920L,45921L,45922L,
84301 45923L,45924L,45925L,45926L,45927L,45928L,45929L,45930L,45931L,45932L,
84302 45933L,45934L,45935L,45936L,45937L,45938L,45939L,45940L,45941L,45942L,
84303 45943L,45944L,45945L,45946L,45947L,45948L,45949L,45950L,45951L,45952L,
84304 45953L,45954L,45955L,45956L,45957L,45958L,45959L,45960L,45961L,45962L,
84305 45963L,45964L,45965L,45966L,45967L,45968L,45969L,45970L,45971L,45972L,
84306 45973L,45974L,45975L,45976L,45977L,45978L,45979L,45980L,45981L,45982L,
84307 45983L,45984L,45985L,45986L,45987L,45988L,45989L,45990L,45991L,45992L,
84308 45993L,45994L,45995L,45996L,45997L,45998L,45999L,46000L,46001L,46002L,
84309 46003L,46004L,46005L,46006L,46007L,46008L,46009L,46010L,46011L,46012L,
84310 46013L,46014L,46015L,46016L,46017L,46018L,46019L,46020L,46021L,46022L,
84311 46023L,46024L,46025L,46026L,46027L,46028L,46029L,46030L,46031L,46032L,
84312 46033L,46034L,46035L,46036L,46037L,46038L,46039L,46040L,46041L,46042L,
84313 46043L,46044L,46045L,46046L,46047L,46048L,46049L,46050L,46051L,46052L,
84314 46053L,46054L,46055L,46056L,46057L,46058L,46059L,46060L,46061L,46062L,
84315 46063L,46064L,46065L,46066L,46067L,46068L,46069L,46070L,46071L,46072L,
84316 46073L,46074L,46075L,46076L,46077L,46078L,46079L,46080L,46081L,46082L,
84317 46083L,46084L,46085L,46086L,46087L,46088L,46089L,46090L,46091L,46092L,
84318 46093L,46094L,46095L,46096L,46097L,46098L,46099L,46100L,46101L,46102L,
84319 46103L,46104L,46105L,46106L,46107L,46108L,46109L,46110L,46111L,46112L,
84320 46113L,46114L,46115L,46116L,46117L,46118L,46119L,46120L,46121L,46122L,
84321 46123L,46124L,46125L,46126L,46127L,46128L,46129L,46130L,46131L,46132L,
84322 46133L,46134L,46135L,46136L,46137L,46138L,46139L,46140L,46141L,46142L,
84323 46143L,46144L,46145L,46146L,46147L,46148L,46149L,46150L,46151L,46152L,
84324 46153L,46154L,46155L,46156L,46157L,46158L,46159L,46160L,46161L,46162L,
84325 46163L,46164L,46165L,46166L,46167L,46168L,46169L,46170L,46171L,46172L,
84326 46173L,46174L,46175L,46176L,46177L,46178L,46179L,46180L,46181L,46182L,
84327 46183L,46184L,46185L,46186L,46187L,46188L,46189L,46190L,46191L,46192L,
84328 46193L,46194L,46195L,46196L,46197L,46198L,46199L,46200L,46201L,46202L,
84329 46203L,46204L,46205L,46206L,46207L,46208L,46209L,46210L,46211L,46212L,
84330 46213L,46214L,46215L,46216L,46217L,46218L,46219L,46220L,46221L,46222L,
84331 46223L,46224L,46225L,46226L,46227L,46228L,46229L,46230L,46231L,46232L,
84332 46233L,46234L,46235L,46236L,46237L,46238L,46239L,46240L,46241L,46242L,
84333 46243L,46244L,46245L,46246L,46247L,46248L,46249L,46250L,46251L,46252L,
84334 46253L,46254L,46255L,46256L,46257L,46258L,46259L,46260L,46261L,46262L,
84335 46263L,46264L,46265L,46266L,46267L,46268L,46269L,46270L,46271L,46272L,
84336 46273L,46274L,46275L,46276L,46277L,46278L,46279L,46280L,46281L,46282L,
84337 46283L,46284L,46285L,46286L,46287L,46288L,46289L,46290L,46291L,46292L,
84338 46293L,46294L,46295L,46296L,46297L,46298L,46299L,46300L,46301L,46302L,
84339 46303L,46304L,46305L,46306L,46307L,46308L,46309L,46310L,46311L,46312L,
84340 46313L,46314L,46315L,46316L,46317L,46318L,46319L,46320L,46321L,46322L,
84341 46323L,46324L,46325L,46326L,46327L,46328L,46329L,46330L,46331L,46332L,
84342 46333L,46334L,46335L,46336L,46337L,46338L,46339L,46340L,46341L,46342L,
84343 46343L,46344L,46345L,46346L,46347L,46348L,46349L,46350L,46351L,46352L,
84344 46353L,46354L,46355L,46356L,46357L,46358L,46359L,46360L,46361L,46362L,
84345 46363L,46364L,46365L,46366L,46367L,46368L,46369L,46370L,46371L,46372L,
84346 46373L,46374L,46375L,46376L,46377L,46378L,46379L,46380L,46381L,46382L,
84347 46383L,46384L,46385L,46386L,46387L,46388L,46389L,46390L,46391L,46392L,
84348 46393L,46394L,46395L,46396L,46397L,46398L,46399L,46400L,46401L,46402L,
84349 46403L,46404L,46405L,46406L,46407L,46408L,46409L,46410L,46411L,46412L,
84350 46413L,46414L,46415L,46416L,46417L,46418L,46419L,46420L,46421L,46422L,
84351 46423L,46424L,46425L,46426L,46427L,46428L,46429L,46430L,46431L,46432L,
84352 46433L,46434L,46435L,46436L,46437L,46438L,46439L,46440L,46441L,46442L,
84353 46443L,46444L,46445L,46446L,46447L,46448L,46449L,46450L,46451L,46452L,
84354 46453L,46454L,46455L,46456L,46457L,46458L,46459L,46460L,46461L,46462L,
84355 46463L,46464L,46465L,46466L,46467L,46468L,46469L,46470L,46471L,46472L,
84356 46473L,46474L,46475L,46476L,46477L,46478L,46479L,46480L,46481L,46482L,
84357 46483L,46484L,46485L,46486L,46487L,46488L,46489L,46490L,46491L,46492L,
84358 46493L,46494L,46495L,46496L,46497L,46498L,46499L,46500L,46501L,46502L,
84359 46503L,46504L,46505L,46506L,46507L,46508L,46509L,46510L,46511L,46512L,
84360 46513L,46514L,46515L,46516L,46517L,46518L,46519L,46520L,46521L,46522L,
84361 46523L,46524L,46525L,46526L,46527L,46528L,46529L,46530L,46531L,46532L,
84362 46533L,46534L,46535L,46536L,46537L,46538L,46539L,46540L,46541L,46542L,
84363 46543L,46544L,46545L,46546L,46547L,46548L,46549L,46550L,46551L,46552L,
84364 46553L,46554L,46555L,46556L,46557L,46558L,46559L,46560L,46561L,46562L,
84365 46563L,46564L,46565L,46566L,46567L,46568L,46569L,46570L,46571L,46572L,
84366 46573L,46574L,46575L,46576L,46577L,46578L,46579L,46580L,46581L,46582L,
84367 46583L,46584L,46585L,46586L,46587L,46588L,46589L,46590L,46591L,46592L,
84368 46593L,46594L,46595L,46596L,46597L,46598L,46599L,46600L,46601L,46602L,
84369 46603L,46604L,46605L,46606L,46607L,46608L,46609L,46610L,46611L,46612L,
84370 46613L,46614L,46615L,46616L,46617L,46618L,46619L,46620L,46621L,46622L,
84371 46623L,46624L,46625L,46626L,46627L,46628L,46629L,46630L,46631L,46632L,
84372 46633L,46634L,46635L,46636L,46637L,46638L,46639L,46640L,46641L,46642L,
84373 46643L,46644L,46645L,46646L,46647L,46648L,46649L,46650L,46651L,46652L,
84374 46653L,46654L,46655L,46656L,46657L,46658L,46659L,46660L,46661L,46662L,
84375 46663L,46664L,46665L,46666L,46667L,46668L,46669L,46670L,46671L,46672L,
84376 46673L,46674L,46675L,46676L,46677L,46678L,46679L,46680L,46681L,46682L,
84377 46683L,46684L,46685L,46686L,46687L,46688L,46689L,46690L,46691L,46692L,
84378 46693L,46694L,46695L,46696L,46697L,46698L,46699L,46700L,46701L,46702L,
84379 46703L,46704L,46705L,46706L,46707L,46708L,46709L,46710L,46711L,46712L,
84380 46713L,46714L,46715L,46716L,46717L,46718L,46719L,46720L,46721L,46722L,
84381 46723L,46724L,46725L,46726L,46727L,46728L,46729L,46730L,46731L,46732L,
84382 46733L,46734L,46735L,46736L,46737L,46738L,46739L,46740L,46741L,46742L,
84383 46743L,46744L,46745L,46746L,46747L,46748L,46749L,46750L,46751L,46752L,
84384 46753L,46754L,46755L,46756L,46757L,46758L,46759L,46760L,46761L,46762L,
84385 46763L,46764L,46765L,46766L,46767L,46768L,46769L,46770L,46771L,46772L,
84386 46773L,46774L,46775L,46776L,46777L,46778L,46779L,46780L,46781L,46782L,
84387 46783L,46784L,46785L,46786L,46787L,46788L,46789L,46790L,46791L,46792L,
84388 46793L,46794L,46795L,46796L,46797L,46798L,46799L,46800L,46801L,46802L,
84389 46803L,46804L,46805L,46806L,46807L,46808L,46809L,46810L,46811L,46812L,
84390 46813L,46814L,46815L,46816L,46817L,46818L,46819L,46820L,46821L,46822L,
84391 46823L,46824L,46825L,46826L,46827L,46828L,46829L,46830L,46831L,46832L,
84392 46833L,46834L,46835L,46836L,46837L,46838L,46839L,46840L,46841L,46842L,
84393 46843L,46844L,46845L,46846L,46847L,46848L,46849L,46850L,46851L,46852L,
84394 46853L,46854L,46855L,46856L,46857L,46858L,46859L,46860L,46861L,46862L,
84395 46863L,46864L,46865L,46866L,46867L,46868L,46869L,46870L,46871L,46872L,
84396 46873L,46874L,46875L,46876L,46877L,46878L,46879L,46880L,46881L,46882L,
84397 46883L,46884L,46885L,46886L,46887L,46888L,46889L,46890L,46891L,46892L,
84398 46893L,46894L,46895L,46896L,46897L,46898L,46899L,46900L,46901L,46902L,
84399 46903L,46904L,46905L,46906L,46907L,46908L,46909L,46910L,46911L,46912L,
84400 46913L,46914L,46915L,46916L,46917L,46918L,46919L,46920L,46921L,46922L,
84401 46923L,46924L,46925L,46926L,46927L,46928L,46929L,46930L,46931L,46932L,
84402 46933L,46934L,46935L,46936L,46937L,46938L,46939L,46940L,46941L,46942L,
84403 46943L,46944L,46945L,46946L,46947L,46948L,46949L,46950L,46951L,46952L,
84404 46953L,46954L,46955L,46956L,46957L,46958L,46959L,46960L,46961L,46962L,
84405 46963L,46964L,46965L,46966L,46967L,46968L,46969L,46970L,46971L,46972L,
84406 46973L,46974L,46975L,46976L,46977L,46978L,46979L,46980L,46981L,46982L,
84407 46983L,46984L,46985L,46986L,46987L,46988L,46989L,46990L,46991L,46992L,
84408 46993L,46994L,46995L,46996L,46997L,46998L,46999L,47000L,47001L,47002L,
84409 47003L,47004L,47005L,47006L,47007L,47008L,47009L,47010L,47011L,47012L,
84410 47013L,47014L,47015L,47016L,47017L,47018L,47019L,47020L,47021L,47022L,
84411 47023L,47024L,47025L,47026L,47027L,47028L,47029L,47030L,47031L,47032L,
84412 47033L,47034L,47035L,47036L,47037L,47038L,47039L,47040L,47041L,47042L,
84413 47043L,47044L,47045L,47046L,47047L,47048L,47049L,47050L,47051L,47052L,
84414 47053L,47054L,47055L,47056L,47057L,47058L,47059L,47060L,47061L,47062L,
84415 47063L,47064L,47065L,47066L,47067L,47068L,47069L,47070L,47071L,47072L,
84416 47073L,47074L,47075L,47076L,47077L,47078L,47079L,47080L,47081L,47082L,
84417 47083L,47084L,47085L,47086L,47087L,47088L,47089L,47090L,47091L,47092L,
84418 47093L,47094L,47095L,47096L,47097L,47098L,47099L,47100L,47101L,47102L,
84419 47103L,47104L,47105L,47106L,47107L,47108L,47109L,47110L,47111L,47112L,
84420 47113L,47114L,47115L,47116L,47117L,47118L,47119L,47120L,47121L,47122L,
84421 47123L,47124L,47125L,47126L,47127L,47128L,47129L,47130L,47131L,47132L,
84422 47133L,47134L,47135L,47136L,47137L,47138L,47139L,47140L,47141L,47142L,
84423 47143L,47144L,47145L,47146L,47147L,47148L,47149L,47150L,47151L,47152L,
84424 47153L,47154L,47155L,47156L,47157L,47158L,47159L,47160L,47161L,47162L,
84425 47163L,47164L,47165L,47166L,47167L,47168L,47169L,47170L,47171L,47172L,
84426 47173L,47174L,47175L,47176L,47177L,47178L,47179L,47180L,47181L,47182L,
84427 47183L,47184L,47185L,47186L,47187L,47188L,47189L,47190L,47191L,47192L,
84428 47193L,47194L,47195L,47196L,47197L,47198L,47199L,47200L,47201L,47202L,
84429 47203L,47204L,47205L,47206L,47207L,47208L,47209L,47210L,47211L,47212L,
84430 47213L,47214L,47215L,47216L,47217L,47218L,47219L,47220L,47221L,47222L,
84431 47223L,47224L,47225L,47226L,47227L,47228L,47229L,47230L,47231L,47232L,
84432 47233L,47234L,47235L,47236L,47237L,47238L,47239L,47240L,47241L,47242L,
84433 47243L,47244L,47245L,47246L,47247L,47248L,47249L,47250L,47251L,47252L,
84434 47253L,47254L,47255L,47256L,47257L,47258L,47259L,47260L,47261L,47262L,
84435 47263L,47264L,47265L,47266L,47267L,47268L,47269L,47270L,47271L,47272L,
84436 47273L,47274L,47275L,47276L,47277L,47278L,47279L,47280L,47281L,47282L,
84437 47283L,47284L,47285L,47286L,47287L,47288L,47289L,47290L,47291L,47292L,
84438 47293L,47294L,47295L,47296L,47297L,47298L,47299L,47300L,47301L,47302L,
84439 47303L,47304L,47305L,47306L,47307L,47308L,47309L,47310L,47311L,47312L,
84440 47313L,47314L,47315L,47316L,47317L,47318L,47319L,47320L,47321L,47322L,
84441 47323L,47324L,47325L,47326L,47327L,47328L,47329L,47330L,47331L,47332L,
84442 47333L,47334L,47335L,47336L,47337L,47338L,47339L,47340L,47341L,47342L,
84443 47343L,47344L,47345L,47346L,47347L,47348L,47349L,47350L,47351L,47352L,
84444 47353L,47354L,47355L,47356L,47357L,47358L,47359L,47360L,47361L,47362L,
84445 47363L,47364L,47365L,47366L,47367L,47368L,47369L,47370L,47371L,47372L,
84446 47373L,47374L,47375L,47376L,47377L,47378L,47379L,47380L,47381L,47382L,
84447 47383L,47384L,47385L,47386L,47387L,47388L,47389L,47390L,47391L,47392L,
84448 47393L,47394L,47395L,47396L,47397L,47398L,47399L,47400L,47401L,47402L,
84449 47403L,47404L,47405L,47406L,47407L,47408L,47409L,47410L,47411L,47412L,
84450 47413L,47414L,47415L,47416L,47417L,47418L,47419L,47420L,47421L,47422L,
84451 47423L,47424L,47425L,47426L,47427L,47428L,47429L,47430L,47431L,47432L,
84452 47433L,47434L,47435L,47436L,47437L,47438L,47439L,47440L,47441L,47442L,
84453 47443L,47444L,47445L,47446L,47447L,47448L,47449L,47450L,47451L,47452L,
84454 47453L,47454L,47455L,47456L,47457L,47458L,47459L,47460L,47461L,47462L,
84455 47463L,47464L,47465L,47466L,47467L,47468L,47469L,47470L,47471L,47472L,
84456 47473L,47474L,47475L,47476L,47477L,47478L,47479L,47480L,47481L,47482L,
84457 47483L,47484L,47485L,47486L,47487L,47488L,47489L,47490L,47491L,47492L,
84458 47493L,47494L,47495L,47496L,47497L,47498L,47499L,47500L,47501L,47502L,
84459 47503L,47504L,47505L,47506L,47507L,47508L,47509L,47510L,47511L,47512L,
84460 47513L,47514L,47515L,47516L,47517L,47518L,47519L,47520L,47521L,47522L,
84461 47523L,47524L,47525L,47526L,47527L,47528L,47529L,47530L,47531L,47532L,
84462 47533L,47534L,47535L,47536L,47537L,47538L,47539L,47540L,47541L,47542L,
84463 47543L,47544L,47545L,47546L,47547L,47548L,47549L,47550L,47551L,47552L,
84464 47553L,47554L,47555L,47556L,47557L,47558L,47559L,47560L,47561L,47562L,
84465 47563L,47564L,47565L,47566L,47567L,47568L,47569L,47570L,47571L,47572L,
84466 47573L,47574L,47575L,47576L,47577L,47578L,47579L,47580L,47581L,47582L,
84467 47583L,47584L,47585L,47586L,47587L,47588L,47589L,47590L,47591L,47592L,
84468 47593L,47594L,47595L,47596L,47597L,47598L,47599L,47600L,47601L,47602L,
84469 47603L,47604L,47605L,47606L,47607L,47608L,47609L,47610L,47611L,47612L,
84470 47613L,47614L,47615L,47616L,47617L,47618L,47619L,47620L,47621L,47622L,
84471 47623L,47624L,47625L,47626L,47627L,47628L,47629L,47630L,47631L,47632L,
84472 47633L,47634L,47635L,47636L,47637L,47638L,47639L,47640L,47641L,47642L,
84473 47643L,47644L,47645L,47646L,47647L,47648L,47649L,47650L,47651L,47652L,
84474 47653L,47654L,47655L,47656L,47657L,47658L,47659L,47660L,47661L,47662L,
84475 47663L,47664L,47665L,47666L,47667L,47668L,47669L,47670L,47671L,47672L,
84476 47673L,47674L,47675L,47676L,47677L,47678L,47679L,47680L,47681L,47682L,
84477 47683L,47684L,47685L,47686L,47687L,47688L,47689L,47690L,47691L,47692L,
84478 47693L,47694L,47695L,47696L,47697L,47698L,47699L,47700L,47701L,47702L,
84479 47703L,47704L,47705L,47706L,47707L,47708L,47709L,47710L,47711L,47712L,
84480 47713L,47714L,47715L,47716L,47717L,47718L,47719L,47720L,47721L,47722L,
84481 47723L,47724L,47725L,47726L,47727L,47728L,47729L,47730L,47731L,47732L,
84482 47733L,47734L,47735L,47736L,47737L,47738L,47739L,47740L,47741L,47742L,
84483 47743L,47744L,47745L,47746L,47747L,47748L,47749L,47750L,47751L,47752L,
84484 47753L,47754L,47755L,47756L,47757L,47758L,47759L,47760L,47761L,47762L,
84485 47763L,47764L,47765L,47766L,47767L,47768L,47769L,47770L,47771L,47772L,
84486 47773L,47774L,47775L,47776L,47777L,47778L,47779L,47780L,47781L,47782L,
84487 47783L,47784L,47785L,47786L,47787L,47788L,47789L,47790L,47791L,47792L,
84488 47793L,47794L,47795L,47796L,47797L,47798L,47799L,47800L,47801L,47802L,
84489 47803L,47804L,47805L,47806L,47807L,47808L,47809L,47810L,47811L,47812L,
84490 47813L,47814L,47815L,47816L,47817L,47818L,47819L,47820L,47821L,47822L,
84491 47823L,47824L,47825L,47826L,47827L,47828L,47829L,47830L,47831L,47832L,
84492 47833L,47834L,47835L,47836L,47837L,47838L,47839L,47840L,47841L,47842L,
84493 47843L,47844L,47845L,47846L,47847L,47848L,47849L,47850L,47851L,47852L,
84494 47853L,47854L,47855L,47856L,47857L,47858L,47859L,47860L,47861L,47862L,
84495 47863L,47864L,47865L,47866L,47867L,47868L,47869L,47870L,47871L,47872L,
84496 47873L,47874L,47875L,47876L,47877L,47878L,47879L,47880L,47881L,47882L,
84497 47883L,47884L,47885L,47886L,47887L,47888L,47889L,47890L,47891L,47892L,
84498 47893L,47894L,47895L,47896L,47897L,47898L,47899L,47900L,47901L,47902L,
84499 47903L,47904L,47905L,47906L,47907L,47908L,47909L,47910L,47911L,47912L,
84500 47913L,47914L,47915L,47916L,47917L,47918L,47919L,47920L,47921L,47922L,
84501 47923L,47924L,47925L,47926L,47927L,47928L,47929L,47930L,47931L,47932L,
84502 47933L,47934L,47935L,47936L,47937L,47938L,47939L,47940L,47941L,47942L,
84503 47943L,47944L,47945L,47946L,47947L,47948L,47949L,47950L,47951L,47952L,
84504 47953L,47954L,47955L,47956L,47957L,47958L,47959L,47960L,47961L,47962L,
84505 47963L,47964L,47965L,47966L,47967L,47968L,47969L,47970L,47971L,47972L,
84506 47973L,47974L,47975L,47976L,47977L,47978L,47979L,47980L,47981L,47982L,
84507 47983L,47984L,47985L,47986L,47987L,47988L,47989L,47990L,47991L,47992L,
84508 47993L,47994L,47995L,47996L,47997L,47998L,47999L,48000L,48001L,48002L,
84509 48003L,48004L,48005L,48006L,48007L,48008L,48009L,48010L,48011L,48012L,
84510 48013L,48014L,48015L,48016L,48017L,48018L,48019L,48020L,48021L,48022L,
84511 48023L,48024L,48025L,48026L,48027L,48028L,48029L,48030L,48031L,48032L,
84512 48033L,48034L,48035L,48036L,48037L,48038L,48039L,48040L,48041L,48042L,
84513 48043L,48044L,48045L,48046L,48047L,48048L,48049L,48050L,48051L,48052L,
84514 48053L,48054L,48055L,48056L,48057L,48058L,48059L,48060L,48061L,48062L,
84515 48063L,48064L,48065L,48066L,48067L,48068L,48069L,48070L,48071L,48072L,
84516 48073L,48074L,48075L,48076L,48077L,48078L,48079L,48080L,48081L,48082L,
84517 48083L,48084L,48085L,48086L,48087L,48088L,48089L,48090L,48091L,48092L,
84518 48093L,48094L,48095L,48096L,48097L,48098L,48099L,48100L,48101L,48102L,
84519 48103L,48104L,48105L,48106L,48107L,48108L,48109L,48110L,48111L,48112L,
84520 48113L,48114L,48115L,48116L,48117L,48118L,48119L,48120L,48121L,48122L,
84521 48123L,48124L,48125L,48126L,48127L,48128L,48129L,48130L,48131L,48132L,
84522 48133L,48134L,48135L,48136L,48137L,48138L,48139L,48140L,48141L,48142L,
84523 48143L,48144L,48145L,48146L,48147L,48148L,48149L,48150L,48151L,48152L,
84524 48153L,48154L,48155L,48156L,48157L,48158L,48159L,48160L,48161L,48162L,
84525 48163L,48164L,48165L,48166L,48167L,48168L,48169L,48170L,48171L,48172L,
84526 48173L,48174L,48175L,48176L,48177L,48178L,48179L,48180L,48181L,48182L,
84527 48183L,48184L,48185L,48186L,48187L,48188L,48189L,48190L,48191L,48192L,
84528 48193L,48194L,48195L,48196L,48197L,48198L,48199L,48200L,48201L,48202L,
84529 48203L,48204L,48205L,48206L,48207L,48208L,48209L,48210L,48211L,48212L,
84530 48213L,48214L,48215L,48216L,48217L,48218L,48219L,48220L,48221L,48222L,
84531 48223L,48224L,48225L,48226L,48227L,48228L,48229L,48230L,48231L,48232L,
84532 48233L,48234L,48235L,48236L,48237L,48238L,48239L,48240L,48241L,48242L,
84533 48243L,48244L,48245L,48246L,48247L,48248L,48249L,48250L,48251L,48252L,
84534 48253L,48254L,48255L,48256L,48257L,48258L,48259L,48260L,48261L,48262L,
84535 48263L,48264L,48265L,48266L,48267L,48268L,48269L,48270L,48271L,48272L,
84536 48273L,48274L,48275L,48276L,48277L,48278L,48279L,48280L,48281L,48282L,
84537 48283L,48284L,48285L,48286L,48287L,48288L,48289L,48290L,48291L,48292L,
84538 48293L,48294L,48295L,48296L,48297L,48298L,48299L,48300L,48301L,48302L,
84539 48303L,48304L,48305L,48306L,48307L,48308L,48309L,48310L,48311L,48312L,
84540 48313L,48314L,48315L,48316L,48317L,48318L,48319L,48320L,48321L,48322L,
84541 48323L,48324L,48325L,48326L,48327L,48328L,48329L,48330L,48331L,48332L,
84542 48333L,48334L,48335L,48336L,48337L,48338L,48339L,48340L,48341L,48342L,
84543 48343L,48344L,48345L,48346L,48347L,48348L,48349L,48350L,48351L,48352L,
84544 48353L,48354L,48355L,48356L,48357L,48358L,48359L,48360L,48361L,48362L,
84545 48363L,48364L,48365L,48366L,48367L,48368L,48369L,48370L,48371L,48372L,
84546 48373L,48374L,48375L,48376L,48377L,48378L,48379L,48380L,48381L,48382L,
84547 48383L,48384L,48385L,48386L,48387L,48388L,48389L,48390L,48391L,48392L,
84548 48393L,48394L,48395L,48396L,48397L,48398L,48399L,48400L,48401L,48402L,
84549 48403L,48404L,48405L,48406L,48407L,48408L,48409L,48410L,48411L,48412L,
84550 48413L,48414L,48415L,48416L,48417L,48418L,48419L,48420L,48421L,48422L,
84551 48423L,48424L,48425L,48426L,48427L,48428L,48429L,48430L,48431L,48432L,
84552 48433L,48434L,48435L,48436L,48437L,48438L,48439L,48440L,48441L,48442L,
84553 48443L,48444L,48445L,48446L,48447L,48448L,48449L,48450L,48451L,48452L,
84554 48453L,48454L,48455L,48456L,48457L,48458L,48459L,48460L,48461L,48462L,
84555 48463L,48464L,48465L,48466L,48467L,48468L,48469L,48470L,48471L,48472L,
84556 48473L,48474L,48475L,48476L,48477L,48478L,48479L,48480L,48481L,48482L,
84557 48483L,48484L,48485L,48486L,48487L,48488L,48489L,48490L,48491L,48492L,
84558 48493L,48494L,48495L,48496L,48497L,48498L,48499L,48500L,48501L,48502L,
84559 48503L,48504L,48505L,48506L,48507L,48508L,48509L,48510L,48511L,48512L,
84560 48513L,48514L,48515L,48516L,48517L,48518L,48519L,48520L,48521L,48522L,
84561 48523L,48524L,48525L,48526L,48527L,48528L,48529L,48530L,48531L,48532L,
84562 48533L,48534L,48535L,48536L,48537L,48538L,48539L,48540L,48541L,48542L,
84563 48543L,48544L,48545L,48546L,48547L,48548L,48549L,48550L,48551L,48552L,
84564 48553L,48554L,48555L,48556L,48557L,48558L,48559L,48560L,48561L,48562L,
84565 48563L,48564L,48565L,48566L,48567L,48568L,48569L,48570L,48571L,48572L,
84566 48573L,48574L,48575L,48576L,48577L,48578L,48579L,48580L,48581L,48582L,
84567 48583L,48584L,48585L,48586L,48587L,48588L,48589L,48590L,48591L,48592L,
84568 48593L,48594L,48595L,48596L,48597L,48598L,48599L,48600L,48601L,48602L,
84569 48603L,48604L,48605L,48606L,48607L,48608L,48609L,48610L,48611L,48612L,
84570 48613L,48614L,48615L,48616L,48617L,48618L,48619L,48620L,48621L,48622L,
84571 48623L,48624L,48625L,48626L,48627L,48628L,48629L,48630L,48631L,48632L,
84572 48633L,48634L,48635L,48636L,48637L,48638L,48639L,48640L,48641L,48642L,
84573 48643L,48644L,48645L,48646L,48647L,48648L,48649L,48650L,48651L,48652L,
84574 48653L,48654L,48655L,48656L,48657L,48658L,48659L,48660L,48661L,48662L,
84575 48663L,48664L,48665L,48666L,48667L,48668L,48669L,48670L,48671L,48672L,
84576 48673L,48674L,48675L,48676L,48677L,48678L,48679L,48680L,48681L,48682L,
84577 48683L,48684L,48685L,48686L,48687L,48688L,48689L,48690L,48691L,48692L,
84578 48693L,48694L,48695L,48696L,48697L,48698L,48699L,48700L,48701L,48702L,
84579 48703L,48704L,48705L,48706L,48707L,48708L,48709L,48710L,48711L,48712L,
84580 48713L,48714L,48715L,48716L,48717L,48718L,48719L,48720L,48721L,48722L,
84581 48723L,48724L,48725L,48726L,48727L,48728L,48729L,48730L,48731L,48732L,
84582 48733L,48734L,48735L,48736L,48737L,48738L,48739L,48740L,48741L,48742L,
84583 48743L,48744L,48745L,48746L,48747L,48748L,48749L,48750L,48751L,48752L,
84584 48753L,48754L,48755L,48756L,48757L,48758L,48759L,48760L,48761L,48762L,
84585 48763L,48764L,48765L,48766L,48767L,48768L,48769L,48770L,48771L,48772L,
84586 48773L,48774L,48775L,48776L,48777L,48778L,48779L,48780L,48781L,48782L,
84587 48783L,48784L,48785L,48786L,48787L,48788L,48789L,48790L,48791L,48792L,
84588 48793L,48794L,48795L,48796L,48797L,48798L,48799L,48800L,48801L,48802L,
84589 48803L,48804L,48805L,48806L,48807L,48808L,48809L,48810L,48811L,48812L,
84590 48813L,48814L,48815L,48816L,48817L,48818L,48819L,48820L,48821L,48822L,
84591 48823L,48824L,48825L,48826L,48827L,48828L,48829L,48830L,48831L,48832L,
84592 48833L,48834L,48835L,48836L,48837L,48838L,48839L,48840L,48841L,48842L,
84593 48843L,48844L,48845L,48846L,48847L,48848L,48849L,48850L,48851L,48852L,
84594 48853L,48854L,48855L,48856L,48857L,48858L,48859L,48860L,48861L,48862L,
84595 48863L,48864L,48865L,48866L,48867L,48868L,48869L,48870L,48871L,48872L,
84596 48873L,48874L,48875L,48876L,48877L,48878L,48879L,48880L,48881L,48882L,
84597 48883L,48884L,48885L,48886L,48887L,48888L,48889L,48890L,48891L,48892L,
84598 48893L,48894L,48895L,48896L,48897L,48898L,48899L,48900L,48901L,48902L,
84599 48903L,48904L,48905L,48906L,48907L,48908L,48909L,48910L,48911L,48912L,
84600 48913L,48914L,48915L,48916L,48917L,48918L,48919L,48920L,48921L,48922L,
84601 48923L,48924L,48925L,48926L,48927L,48928L,48929L,48930L,48931L,48932L,
84602 48933L,48934L,48935L,48936L,48937L,48938L,48939L,48940L,48941L,48942L,
84603 48943L,48944L,48945L,48946L,48947L,48948L,48949L,48950L,48951L,48952L,
84604 48953L,48954L,48955L,48956L,48957L,48958L,48959L,48960L,48961L,48962L,
84605 48963L,48964L,48965L,48966L,48967L,48968L,48969L,48970L,48971L,48972L,
84606 48973L,48974L,48975L,48976L,48977L,48978L,48979L,48980L,48981L,48982L,
84607 48983L,48984L,48985L,48986L,48987L,48988L,48989L,48990L,48991L,48992L,
84608 48993L,48994L,48995L,48996L,48997L,48998L,48999L,49000L,49001L,49002L,
84609 49003L,49004L,49005L,49006L,49007L,49008L,49009L,49010L,49011L,49012L,
84610 49013L,49014L,49015L,49016L,49017L,49018L,49019L,49020L,49021L,49022L,
84611 49023L,49024L,49025L,49026L,49027L,49028L,49029L,49030L,49031L,49032L,
84612 49033L,49034L,49035L,49036L,49037L,49038L,49039L,49040L,49041L,49042L,
84613 49043L,49044L,49045L,49046L,49047L,49048L,49049L,49050L,49051L,49052L,
84614 49053L,49054L,49055L,49056L,49057L,49058L,49059L,49060L,49061L,49062L,
84615 49063L,49064L,49065L,49066L,49067L,49068L,49069L,49070L,49071L,49072L,
84616 49073L,49074L,49075L,49076L,49077L,49078L,49079L,49080L,49081L,49082L,
84617 49083L,49084L,49085L,49086L,49087L,49088L,49089L,49090L,49091L,49092L,
84618 49093L,49094L,49095L,49096L,49097L,49098L,49099L,49100L,49101L,49102L,
84619 49103L,49104L,49105L,49106L,49107L,49108L,49109L,49110L,49111L,49112L,
84620 49113L,49114L,49115L,49116L,49117L,49118L,49119L,49120L,49121L,49122L,
84621 49123L,49124L,49125L,49126L,49127L,49128L,49129L,49130L,49131L,49132L,
84622 49133L,49134L,49135L,49136L,49137L,49138L,49139L,49140L,49141L,49142L,
84623 49143L,49144L,49145L,49146L,49147L,49148L,49149L,49150L,49151L,49152L,
84624 49153L,49154L,49155L,49156L,49157L,49158L,49159L,49160L,49161L,49162L,
84625 49163L,49164L,49165L,49166L,49167L,49168L,49169L,49170L,49171L,49172L,
84626 49173L,49174L,49175L,49176L,49177L,49178L,49179L,49180L,49181L,49182L,
84627 49183L,49184L,49185L,49186L,49187L,49188L,49189L,49190L,49191L,49192L,
84628 49193L,49194L,49195L,49196L,49197L,49198L,49199L,49200L,49201L,49202L,
84629 49203L,49204L,49205L,49206L,49207L,49208L,49209L,49210L,49211L,49212L,
84630 49213L,49214L,49215L,49216L,49217L,49218L,49219L,49220L,49221L,49222L,
84631 49223L,49224L,49225L,49226L,49227L,49228L,49229L,49230L,49231L,49232L,
84632 49233L,49234L,49235L,49236L,49237L,49238L,49239L,49240L,49241L,49242L,
84633 49243L,49244L,49245L,49246L,49247L,49248L,49249L,49250L,49251L,49252L,
84634 49253L,49254L,49255L,49256L,49257L,49258L,49259L,49260L,49261L,49262L,
84635 49263L,49264L,49265L,49266L,49267L,49268L,49269L,49270L,49271L,49272L,
84636 49273L,49274L,49275L,49276L,49277L,49278L,49279L,49280L,49281L,49282L,
84637 49283L,49284L,49285L,49286L,49287L,49288L,49289L,49290L,49291L,49292L,
84638 49293L,49294L,49295L,49296L,49297L,49298L,49299L,49300L,49301L,49302L,
84639 49303L,49304L,49305L,49306L,49307L,49308L,49309L,49310L,49311L,49312L,
84640 49313L,49314L,49315L,49316L,49317L,49318L,49319L,49320L,49321L,49322L,
84641 49323L,49324L,49325L,49326L,49327L,49328L,49329L,49330L,49331L,49332L,
84642 49333L,49334L,49335L,49336L,49337L,49338L,49339L,49340L,49341L,49342L,
84643 49343L,49344L,49345L,49346L,49347L,49348L,49349L,49350L,49351L,49352L,
84644 49353L,49354L,49355L,49356L,49357L,49358L,49359L,49360L,49361L,49362L,
84645 49363L,49364L,49365L,49366L,49367L,49368L,49369L,49370L,49371L,49372L,
84646 49373L,49374L,49375L,49376L,49377L,49378L,49379L,49380L,49381L,49382L,
84647 49383L,49384L,49385L,49386L,49387L,49388L,49389L,49390L,49391L,49392L,
84648 49393L,49394L,49395L,49396L,49397L,49398L,49399L,49400L,49401L,49402L,
84649 49403L,49404L,49405L,49406L,49407L,49408L,49409L,49410L,49411L,49412L,
84650 49413L,49414L,49415L,49416L,49417L,49418L,49419L,49420L,49421L,49422L,
84651 49423L,49424L,49425L,49426L,49427L,49428L,49429L,49430L,49431L,49432L,
84652 49433L,49434L,49435L,49436L,49437L,49438L,49439L,49440L,49441L,49442L,
84653 49443L,49444L,49445L,49446L,49447L,49448L,49449L,49450L,49451L,49452L,
84654 49453L,49454L,49455L,49456L,49457L,49458L,49459L,49460L,49461L,49462L,
84655 49463L,49464L,49465L,49466L,49467L,49468L,49469L,49470L,49471L,49472L,
84656 49473L,49474L,49475L,49476L,49477L,49478L,49479L,49480L,49481L,49482L,
84657 49483L,49484L,49485L,49486L,49487L,49488L,49489L,49490L,49491L,49492L,
84658 49493L,49494L,49495L,49496L,49497L,49498L,49499L,49500L,49501L,49502L,
84659 49503L,49504L,49505L,49506L,49507L,49508L,49509L,49510L,49511L,49512L,
84660 49513L,49514L,49515L,49516L,49517L,49518L,49519L,49520L,49521L,49522L,
84661 49523L,49524L,49525L,49526L,49527L,49528L,49529L,49530L,49531L,49532L,
84662 49533L,49534L,49535L,49536L,49537L,49538L,49539L,49540L,49541L,49542L,
84663 49543L,49544L,49545L,49546L,49547L,49548L,49549L,49550L,49551L,49552L,
84664 49553L,49554L,49555L,49556L,49557L,49558L,49559L,49560L,49561L,49562L,
84665 49563L,49564L,49565L,49566L,49567L,49568L,49569L,49570L,49571L,49572L,
84666 49573L,49574L,49575L,49576L,49577L,49578L,49579L,49580L,49581L,49582L,
84667 49583L,49584L,49585L,49586L,49587L,49588L,49589L,49590L,49591L,49592L,
84668 49593L,49594L,49595L,49596L,49597L,49598L,49599L,49600L,49601L,49602L,
84669 49603L,49604L,49605L,49606L,49607L,49608L,49609L,49610L,49611L,49612L,
84670 49613L,49614L,49615L,49616L,49617L,49618L,49619L,49620L,49621L,49622L,
84671 49623L,49624L,49625L,49626L,49627L,49628L,49629L,49630L,49631L,49632L,
84672 49633L,49634L,49635L,49636L,49637L,49638L,49639L,49640L,49641L,49642L,
84673 49643L,49644L,49645L,49646L,49647L,49648L,49649L,49650L,49651L,49652L,
84674 49653L,49654L,49655L,49656L,49657L,49658L,49659L,49660L,49661L,49662L,
84675 49663L,49664L,49665L,49666L,49667L,49668L,49669L,49670L,49671L,49672L,
84676 49673L,49674L,49675L,49676L,49677L,49678L,49679L,49680L,49681L,49682L,
84677 49683L,49684L,49685L,49686L,49687L,49688L,49689L,49690L,49691L,49692L,
84678 49693L,49694L,49695L,49696L,49697L,49698L,49699L,49700L,49701L,49702L,
84679 49703L,49704L,49705L,49706L,49707L,49708L,49709L,49710L,49711L,49712L,
84680 49713L,49714L,49715L,49716L,49717L,49718L,49719L,49720L,49721L,49722L,
84681 49723L,49724L,49725L,49726L,49727L,49728L,49729L,49730L,49731L,49732L,
84682 49733L,49734L,49735L,49736L,49737L,49738L,49739L,49740L,49741L,49742L,
84683 49743L,49744L,49745L,49746L,49747L,49748L,49749L,49750L,49751L,49752L,
84684 49753L,49754L,49755L,49756L,49757L,49758L,49759L,49760L,49761L,49762L,
84685 49763L,49764L,49765L,49766L,49767L,49768L,49769L,49770L,49771L,49772L,
84686 49773L,49774L,49775L,49776L,49777L,49778L,49779L,49780L,49781L,49782L,
84687 49783L,49784L,49785L,49786L,49787L,49788L,49789L,49790L,49791L,49792L,
84688 49793L,49794L,49795L,49796L,49797L,49798L,49799L,49800L,49801L,49802L,
84689 49803L,49804L,49805L,49806L,49807L,49808L,49809L,49810L,49811L,49812L,
84690 49813L,49814L,49815L,49816L,49817L,49818L,49819L,49820L,49821L,49822L,
84691 49823L,49824L,49825L,49826L,49827L,49828L,49829L,49830L,49831L,49832L,
84692 49833L,49834L,49835L,49836L,49837L,49838L,49839L,49840L,49841L,49842L,
84693 49843L,49844L,49845L,49846L,49847L,49848L,49849L,49850L,49851L,49852L,
84694 49853L,49854L,49855L,49856L,49857L,49858L,49859L,49860L,49861L,49862L,
84695 49863L,49864L,49865L,49866L,49867L,49868L,49869L,49870L,49871L,49872L,
84696 49873L,49874L,49875L,49876L,49877L,49878L,49879L,49880L,49881L,49882L,
84697 49883L,49884L,49885L,49886L,49887L,49888L,49889L,49890L,49891L,49892L,
84698 49893L,49894L,49895L,49896L,49897L,49898L,49899L,49900L,49901L,49902L,
84699 49903L,49904L,49905L,49906L,49907L,49908L,49909L,49910L,49911L,49912L,
84700 49913L,49914L,49915L,49916L,49917L,49918L,49919L,49920L,49921L,49922L,
84701 49923L,49924L,49925L,49926L,49927L,49928L,49929L,49930L,49931L,49932L,
84702 49933L,49934L,49935L,49936L,49937L,49938L,49939L,49940L,49941L,49942L,
84703 49943L,49944L,49945L,49946L,49947L,49948L,49949L,49950L,49951L,49952L,
84704 49953L,49954L,49955L,49956L,49957L,49958L,49959L,49960L,49961L,49962L,
84705 49963L,49964L,49965L,49966L,49967L,49968L,49969L,49970L,49971L,49972L,
84706 49973L,49974L,49975L,49976L,49977L,49978L,49979L,49980L,49981L,49982L,
84707 49983L,49984L,49985L,49986L,49987L,49988L,49989L,49990L,49991L,49992L,
84708 49993L,49994L,49995L,49996L,49997L,49998L,49999L,50000L,50001L,50002L,
84709 50003L,50004L,50005L,50006L,50007L,50008L,50009L,50010L,50011L,50012L,
84710 50013L,50014L,50015L,50016L,50017L,50018L,50019L,50020L,50021L,50022L,
84711 50023L,50024L,50025L,50026L,50027L,50028L,50029L,50030L,50031L,50032L,
84712 50033L,50034L,50035L,50036L,50037L,50038L,50039L,50040L,50041L,50042L,
84713 50043L,50044L,50045L,50046L,50047L,50048L,50049L,50050L,50051L,50052L,
84714 50053L,50054L,50055L,50056L,50057L,50058L,50059L,50060L,50061L,50062L,
84715 50063L,50064L,50065L,50066L,50067L,50068L,50069L,50070L,50071L,50072L,
84716 50073L,50074L,50075L,50076L,50077L,50078L,50079L,50080L,50081L,50082L,
84717 50083L,50084L,50085L,50086L,50087L,50088L,50089L,50090L,50091L,50092L,
84718 50093L,50094L,50095L,50096L,50097L,50098L,50099L,50100L,50101L,50102L,
84719 50103L,50104L,50105L,50106L,50107L,50108L,50109L,50110L,50111L,50112L,
84720 50113L,50114L,50115L,50116L,50117L,50118L,50119L,50120L,50121L,50122L,
84721 50123L,50124L,50125L,50126L,50127L,50128L,50129L,50130L,50131L,50132L,
84722 50133L,50134L,50135L,50136L,50137L,50138L,50139L,50140L,50141L,50142L,
84723 50143L,50144L,50145L,50146L,50147L,50148L,50149L,50150L,50151L,50152L,
84724 50153L,50154L,50155L,50156L,50157L,50158L,50159L,50160L,50161L,50162L,
84725 50163L,50164L,50165L,50166L,50167L,50168L,50169L,50170L,50171L,50172L,
84726 50173L,50174L,50175L,50176L,50177L,50178L,50179L,50180L,50181L,50182L,
84727 50183L,50184L,50185L,50186L,50187L,50188L,50189L,50190L,50191L,50192L,
84728 50193L,50194L,50195L,50196L,50197L,50198L,50199L,50200L,50201L,50202L,
84729 50203L,50204L,50205L,50206L,50207L,50208L,50209L,50210L,50211L,50212L,
84730 50213L,50214L,50215L,50216L,50217L,50218L,50219L,50220L,50221L,50222L,
84731 50223L,50224L,50225L,50226L,50227L,50228L,50229L,50230L,50231L,50232L,
84732 50233L,50234L,50235L,50236L,50237L,50238L,50239L,50240L,50241L,50242L,
84733 50243L,50244L,50245L,50246L,50247L,50248L,50249L,50250L,50251L,50252L,
84734 50253L,50254L,50255L,50256L,50257L,50258L,50259L,50260L,50261L,50262L,
84735 50263L,50264L,50265L,50266L,50267L,50268L,50269L,50270L,50271L,50272L,
84736 50273L,50274L,50275L,50276L,50277L,50278L,50279L,50280L,50281L,50282L,
84737 50283L,50284L,50285L,50286L,50287L,50288L,50289L,50290L,50291L,50292L,
84738 50293L,50294L,50295L,50296L,50297L,50298L,50299L,50300L,50301L,50302L,
84739 50303L,50304L,50305L,50306L,50307L,50308L,50309L,50310L,50311L,50312L,
84740 50313L,50314L,50315L,50316L,50317L,50318L,50319L,50320L,50321L,50322L,
84741 50323L,50324L,50325L,50326L,50327L,50328L,50329L,50330L,50331L,50332L,
84742 50333L,50334L,50335L,50336L,50337L,50338L,50339L,50340L,50341L,50342L,
84743 50343L,50344L,50345L,50346L,50347L,50348L,50349L,50350L,50351L,50352L,
84744 50353L,50354L,50355L,50356L,50357L,50358L,50359L,50360L,50361L,50362L,
84745 50363L,50364L,50365L,50366L,50367L,50368L,50369L,50370L,50371L,50372L,
84746 50373L,50374L,50375L,50376L,50377L,50378L,50379L,50380L,50381L,50382L,
84747 50383L,50384L,50385L,50386L,50387L,50388L,50389L,50390L,50391L,50392L,
84748 50393L,50394L,50395L,50396L,50397L,50398L,50399L,50400L,50401L,50402L,
84749 50403L,50404L,50405L,50406L,50407L,50408L,50409L,50410L,50411L,50412L,
84750 50413L,50414L,50415L,50416L,50417L,50418L,50419L,50420L,50421L,50422L,
84751 50423L,50424L,50425L,50426L,50427L,50428L,50429L,50430L,50431L,50432L,
84752 50433L,50434L,50435L,50436L,50437L,50438L,50439L,50440L,50441L,50442L,
84753 50443L,50444L,50445L,50446L,50447L,50448L,50449L,50450L,50451L,50452L,
84754 50453L,50454L,50455L,50456L,50457L,50458L,50459L,50460L,50461L,50462L,
84755 50463L,50464L,50465L,50466L,50467L,50468L,50469L,50470L,50471L,50472L,
84756 50473L,50474L,50475L,50476L,50477L,50478L,50479L,50480L,50481L,50482L,
84757 50483L,50484L,50485L,50486L,50487L,50488L,50489L,50490L,50491L,50492L,
84758 50493L,50494L,50495L,50496L,50497L,50498L,50499L,50500L,50501L,50502L,
84759 50503L,50504L,50505L,50506L,50507L,50508L,50509L,50510L,50511L,50512L,
84760 50513L,50514L,50515L,50516L,50517L,50518L,50519L,50520L,50521L,50522L,
84761 50523L,50524L,50525L,50526L,50527L,50528L,50529L,50530L,50531L,50532L,
84762 50533L,50534L,50535L,50536L,50537L,50538L,50539L,50540L,50541L,50542L,
84763 50543L,50544L,50545L,50546L,50547L,50548L,50549L,50550L,50551L,50552L,
84764 50553L,50554L,50555L,50556L,50557L,50558L,50559L,50560L,50561L,50562L,
84765 50563L,50564L,50565L,50566L,50567L,50568L,50569L,50570L,50571L,50572L,
84766 50573L,50574L,50575L,50576L,50577L,50578L,50579L,50580L,50581L,50582L,
84767 50583L,50584L,50585L,50586L,50587L,50588L,50589L,50590L,50591L,50592L,
84768 50593L,50594L,50595L,50596L,50597L,50598L,50599L,50600L,50601L,50602L,
84769 50603L,50604L,50605L,50606L,50607L,50608L,50609L,50610L,50611L,50612L,
84770 50613L,50614L,50615L,50616L,50617L,50618L,50619L,50620L,50621L,50622L,
84771 50623L,50624L,50625L,50626L,50627L,50628L,50629L,50630L,50631L,50632L,
84772 50633L,50634L,50635L,50636L,50637L,50638L,50639L,50640L,50641L,50642L,
84773 50643L,50644L,50645L,50646L,50647L,50648L,50649L,50650L,50651L,50652L,
84774 50653L,50654L,50655L,50656L,50657L,50658L,50659L,50660L,50661L,50662L,
84775 50663L,50664L,50665L,50666L,50667L,50668L,50669L,50670L,50671L,50672L,
84776 50673L,50674L,50675L,50676L,50677L,50678L,50679L,50680L,50681L,50682L,
84777 50683L,50684L,50685L,50686L,50687L,50688L,50689L,50690L,50691L,50692L,
84778 50693L,50694L,50695L,50696L,50697L,50698L,50699L,50700L,50701L,50702L,
84779 50703L,50704L,50705L,50706L,50707L,50708L,50709L,50710L,50711L,50712L,
84780 50713L,50714L,50715L,50716L,50717L,50718L,50719L,50720L,50721L,50722L,
84781 50723L,50724L,50725L,50726L,50727L,50728L,50729L,50730L,50731L,50732L,
84782 50733L,50734L,50735L,50736L,50737L,50738L,50739L,50740L,50741L,50742L,
84783 50743L,50744L,50745L,50746L,50747L,50748L,50749L,50750L,50751L,50752L,
84784 50753L,50754L,50755L,50756L,50757L,50758L,50759L,50760L,50761L,50762L,
84785 50763L,50764L,50765L,50766L,50767L,50768L,50769L,50770L,50771L,50772L,
84786 50773L,50774L,50775L,50776L,50777L,50778L,50779L,50780L,50781L,50782L,
84787 50783L,50784L,50785L,50786L,50787L,50788L,50789L,50790L,50791L,50792L,
84788 50793L,50794L,50795L,50796L,50797L,50798L,50799L,50800L,50801L,50802L,
84789 50803L,50804L,50805L,50806L,50807L,50808L,50809L,50810L,50811L,50812L,
84790 50813L,50814L,50815L,50816L,50817L,50818L,50819L,50820L,50821L,50822L,
84791 50823L,50824L,50825L,50826L,50827L,50828L,50829L,50830L,50831L,50832L,
84792 50833L,50834L,50835L,50836L,50837L,50838L,50839L,50840L,50841L,50842L,
84793 50843L,50844L,50845L,50846L,50847L,50848L,50849L,50850L,50851L,50852L,
84794 50853L,50854L,50855L,50856L,50857L,50858L,50859L,50860L,50861L,50862L,
84795 50863L,50864L,50865L,50866L,50867L,50868L,50869L,50870L,50871L,50872L,
84796 50873L,50874L,50875L,50876L,50877L,50878L,50879L,50880L,50881L,50882L,
84797 50883L,50884L,50885L,50886L,50887L,50888L,50889L,50890L,50891L,50892L,
84798 50893L,50894L,50895L,50896L,50897L,50898L,50899L,50900L,50901L,50902L,
84799 50903L,50904L,50905L,50906L,50907L,50908L,50909L,50910L,50911L,50912L,
84800 50913L,50914L,50915L,50916L,50917L,50918L,50919L,50920L,50921L,50922L,
84801 50923L,50924L,50925L,50926L,50927L,50928L,50929L,50930L,50931L,50932L,
84802 50933L,50934L,50935L,50936L,50937L,50938L,50939L,50940L,50941L,50942L,
84803 50943L,50944L,50945L,50946L,50947L,50948L,50949L,50950L,50951L,50952L,
84804 50953L,50954L,50955L,50956L,50957L,50958L,50959L,50960L,50961L,50962L,
84805 50963L,50964L,50965L,50966L,50967L,50968L,50969L,50970L,50971L,50972L,
84806 50973L,50974L,50975L,50976L,50977L,50978L,50979L,50980L,50981L,50982L,
84807 50983L,50984L,50985L,50986L,50987L,50988L,50989L,50990L,50991L,50992L,
84808 50993L,50994L,50995L,50996L,50997L,50998L,50999L,51000L,51001L,51002L,
84809 51003L,51004L,51005L,51006L,51007L,51008L,51009L,51010L,51011L,51012L,
84810 51013L,51014L,51015L,51016L,51017L,51018L,51019L,51020L,51021L,51022L,
84811 51023L,51024L,51025L,51026L,51027L,51028L,51029L,51030L,51031L,51032L,
84812 51033L,51034L,51035L,51036L,51037L,51038L,51039L,51040L,51041L,51042L,
84813 51043L,51044L,51045L,51046L,51047L,51048L,51049L,51050L,51051L,51052L,
84814 51053L,51054L,51055L,51056L,51057L,51058L,51059L,51060L,51061L,51062L,
84815 51063L,51064L,51065L,51066L,51067L,51068L,51069L,51070L,51071L,51072L,
84816 51073L,51074L,51075L,51076L,51077L,51078L,51079L,51080L,51081L,51082L,
84817 51083L,51084L,51085L,51086L,51087L,51088L,51089L,51090L,51091L,51092L,
84818 51093L,51094L,51095L,51096L,51097L,51098L,51099L,51100L,51101L,51102L,
84819 51103L,51104L,51105L,51106L,51107L,51108L,51109L,51110L,51111L,51112L,
84820 51113L,51114L,51115L,51116L,51117L,51118L,51119L,51120L,51121L,51122L,
84821 51123L,51124L,51125L,51126L,51127L,51128L,51129L,51130L,51131L,51132L,
84822 51133L,51134L,51135L,51136L,51137L,51138L,51139L,51140L,51141L,51142L,
84823 51143L,51144L,51145L,51146L,51147L,51148L,51149L,51150L,51151L,51152L,
84824 51153L,51154L,51155L,51156L,51157L,51158L,51159L,51160L,51161L,51162L,
84825 51163L,51164L,51165L,51166L,51167L,51168L,51169L,51170L,51171L,51172L,
84826 51173L,51174L,51175L,51176L,51177L,51178L,51179L,51180L,51181L,51182L,
84827 51183L,51184L,51185L,51186L,51187L,51188L,51189L,51190L,51191L,51192L,
84828 51193L,51194L,51195L,51196L,51197L,51198L,51199L,51200L,51201L,51202L,
84829 51203L,51204L,51205L,51206L,51207L,51208L,51209L,51210L,51211L,51212L,
84830 51213L,51214L,51215L,51216L,51217L,51218L,51219L,51220L,51221L,51222L,
84831 51223L,51224L,51225L,51226L,51227L,51228L,51229L,51230L,51231L,51232L,
84832 51233L,51234L,51235L,51236L,51237L,51238L,51239L,51240L,51241L,51242L,
84833 51243L,51244L,51245L,51246L,51247L,51248L,51249L,51250L,51251L,51252L,
84834 51253L,51254L,51255L,51256L,51257L,51258L,51259L,51260L,51261L,51262L,
84835 51263L,51264L,51265L,51266L,51267L,51268L,51269L,51270L,51271L,51272L,
84836 51273L,51274L,51275L,51276L,51277L,51278L,51279L,51280L,51281L,51282L,
84837 51283L,51284L,51285L,51286L,51287L,51288L,51289L,51290L,51291L,51292L,
84838 51293L,51294L,51295L,51296L,51297L,51298L,51299L,51300L,51301L,51302L,
84839 51303L,51304L,51305L,51306L,51307L,51308L,51309L,51310L,51311L,51312L,
84840 51313L,51314L,51315L,51316L,51317L,51318L,51319L,51320L,51321L,51322L,
84841 51323L,51324L,51325L,51326L,51327L,51328L,51329L,51330L,51331L,51332L,
84842 51333L,51334L,51335L,51336L,51337L,51338L,51339L,51340L,51341L,51342L,
84843 51343L,51344L,51345L,51346L,51347L,51348L,51349L,51350L,51351L,51352L,
84844 51353L,51354L,51355L,51356L,51357L,51358L,51359L,51360L,51361L,51362L,
84845 51363L,51364L,51365L,51366L,51367L,51368L,51369L,51370L,51371L,51372L,
84846 51373L,51374L,51375L,51376L,51377L,51378L,51379L,51380L,51381L,51382L,
84847 51383L,51384L,51385L,51386L,51387L,51388L,51389L,51390L,51391L,51392L,
84848 51393L,51394L,51395L,51396L,51397L,51398L,51399L,51400L,51401L,51402L,
84849 51403L,51404L,51405L,51406L,51407L,51408L,51409L,51410L,51411L,51412L,
84850 51413L,51414L,51415L,51416L,51417L,51418L,51419L,51420L,51421L,51422L,
84851 51423L,51424L,51425L,51426L,51427L,51428L,51429L,51430L,51431L,51432L,
84852 51433L,51434L,51435L,51436L,51437L,51438L,51439L,51440L,51441L,51442L,
84853 51443L,51444L,51445L,51446L,51447L,51448L,51449L,51450L,51451L,51452L,
84854 51453L,51454L,51455L,51456L,51457L,51458L,51459L,51460L,51461L,51462L,
84855 51463L,51464L,51465L,51466L,51467L,51468L,51469L,51470L,51471L,51472L,
84856 51473L,51474L,51475L,51476L,51477L,51478L,51479L,51480L,51481L,51482L,
84857 51483L,51484L,51485L,51486L,51487L,51488L,51489L,51490L,51491L,51492L,
84858 51493L,51494L,51495L,51496L,51497L,51498L,51499L,51500L,51501L,51502L,
84859 51503L,51504L,51505L,51506L,51507L,51508L,51509L,51510L,51511L,51512L,
84860 51513L,51514L,51515L,51516L,51517L,51518L,51519L,51520L,51521L,51522L,
84861 51523L,51524L,51525L,51526L,51527L,51528L,51529L,51530L,51531L,51532L,
84862 51533L,51534L,51535L,51536L,51537L,51538L,51539L,51540L,51541L,51542L,
84863 51543L,51544L,51545L,51546L,51547L,51548L,51549L,51550L,51551L,51552L,
84864 51553L,51554L,51555L,51556L,51557L,51558L,51559L,51560L,51561L,51562L,
84865 51563L,51564L,51565L,51566L,51567L,51568L,51569L,51570L,51571L,51572L,
84866 51573L,51574L,51575L,51576L,51577L,51578L,51579L,51580L,51581L,51582L,
84867 51583L,51584L,51585L,51586L,51587L,51588L,51589L,51590L,51591L,51592L,
84868 51593L,51594L,51595L,51596L,51597L,51598L,51599L,51600L,51601L,51602L,
84869 51603L,51604L,51605L,51606L,51607L,51608L,51609L,51610L,51611L,51612L,
84870 51613L,51614L,51615L,51616L,51617L,51618L,51619L,51620L,51621L,51622L,
84871 51623L,51624L,51625L,51626L,51627L,51628L,51629L,51630L,51631L,51632L,
84872 51633L,51634L,51635L,51636L,51637L,51638L,51639L,51640L,51641L,51642L,
84873 51643L,51644L,51645L,51646L,51647L,51648L,51649L,51650L,51651L,51652L,
84874 51653L,51654L,51655L,51656L,51657L,51658L,51659L,51660L,51661L,51662L,
84875 51663L,51664L,51665L,51666L,51667L,51668L,51669L,51670L,51671L,51672L,
84876 51673L,51674L,51675L,51676L,51677L,51678L,51679L,51680L,51681L,51682L,
84877 51683L,51684L,51685L,51686L,51687L,51688L,51689L,51690L,51691L,51692L,
84878 51693L,51694L,51695L,51696L,51697L,51698L,51699L,51700L,51701L,51702L,
84879 51703L,51704L,51705L,51706L,51707L,51708L,51709L,51710L,51711L,51712L,
84880 51713L,51714L,51715L,51716L,51717L,51718L,51719L,51720L,51721L,51722L,
84881 51723L,51724L,51725L,51726L,51727L,51728L,51729L,51730L,51731L,51732L,
84882 51733L,51734L,51735L,51736L,51737L,51738L,51739L,51740L,51741L,51742L,
84883 51743L,51744L,51745L,51746L,51747L,51748L,51749L,51750L,51751L,51752L,
84884 51753L,51754L,51755L,51756L,51757L,51758L,51759L,51760L,51761L,51762L,
84885 51763L,51764L,51765L,51766L,51767L,51768L,51769L,51770L,51771L,51772L,
84886 51773L,51774L,51775L,51776L,51777L,51778L,51779L,51780L,51781L,51782L,
84887 51783L,51784L,51785L,51786L,51787L,51788L,51789L,51790L,51791L,51792L,
84888 51793L,51794L,51795L,51796L,51797L,51798L,51799L,51800L,51801L,51802L,
84889 51803L,51804L,51805L,51806L,51807L,51808L,51809L,51810L,51811L,51812L,
84890 51813L,51814L,51815L,51816L,51817L,51818L,51819L,51820L,51821L,51822L,
84891 51823L,51824L,51825L,51826L,51827L,51828L,51829L,51830L,51831L,51832L,
84892 51833L,51834L,51835L,51836L,51837L,51838L,51839L,51840L,51841L,51842L,
84893 51843L,51844L,51845L,51846L,51847L,51848L,51849L,51850L,51851L,51852L,
84894 51853L,51854L,51855L,51856L,51857L,51858L,51859L,51860L,51861L,51862L,
84895 51863L,51864L,51865L,51866L,51867L,51868L,51869L,51870L,51871L,51872L,
84896 51873L,51874L,51875L,51876L,51877L,51878L,51879L,51880L,51881L,51882L,
84897 51883L,51884L,51885L,51886L,51887L,51888L,51889L,51890L,51891L,51892L,
84898 51893L,51894L,51895L,51896L,51897L,51898L,51899L,51900L,51901L,51902L,
84899 51903L,51904L,51905L,51906L,51907L,51908L,51909L,51910L,51911L,51912L,
84900 51913L,51914L,51915L,51916L,51917L,51918L,51919L,51920L,51921L,51922L,
84901 51923L,51924L,51925L,51926L,51927L,51928L,51929L,51930L,51931L,51932L,
84902 51933L,51934L,51935L,51936L,51937L,51938L,51939L,51940L,51941L,51942L,
84903 51943L,51944L,51945L,51946L,51947L,51948L,51949L,51950L,51951L,51952L,
84904 51953L,51954L,51955L,51956L,51957L,51958L,51959L,51960L,51961L,51962L,
84905 51963L,51964L,51965L,51966L,51967L,51968L,51969L,51970L,51971L,51972L,
84906 51973L,51974L,51975L,51976L,51977L,51978L,51979L,51980L,51981L,51982L,
84907 51983L,51984L,51985L,51986L,51987L,51988L,51989L,51990L,51991L,51992L,
84908 51993L,51994L,51995L,51996L,51997L,51998L,51999L,52000L,52001L,52002L,
84909 52003L,52004L,52005L,52006L,52007L,52008L,52009L,52010L,52011L,52012L,
84910 52013L,52014L,52015L,52016L,52017L,52018L,52019L,52020L,52021L,52022L,
84911 52023L,52024L,52025L,52026L,52027L,52028L,52029L,52030L,52031L,52032L,
84912 52033L,52034L,52035L,52036L,52037L,52038L,52039L,52040L,52041L,52042L,
84913 52043L,52044L,52045L,52046L,52047L,52048L,52049L,52050L,52051L,52052L,
84914 52053L,52054L,52055L,52056L,52057L,52058L,52059L,52060L,52061L,52062L,
84915 52063L,52064L,52065L,52066L,52067L,52068L,52069L,52070L,52071L,52072L,
84916 52073L,52074L,52075L,52076L,52077L,52078L,52079L,52080L,52081L,52082L,
84917 52083L,52084L,52085L,52086L,52087L,52088L,52089L,52090L,52091L,52092L,
84918 52093L,52094L,52095L,52096L,52097L,52098L,52099L,52100L,52101L,52102L,
84919 52103L,52104L,52105L,52106L,52107L,52108L,52109L,52110L,52111L,52112L,
84920 52113L,52114L,52115L,52116L,52117L,52118L,52119L,52120L,52121L,52122L,
84921 52123L,52124L,52125L,52126L,52127L,52128L,52129L,52130L,52131L,52132L,
84922 52133L,52134L,52135L,52136L,52137L,52138L,52139L,52140L,52141L,52142L,
84923 52143L,52144L,52145L,52146L,52147L,52148L,52149L,52150L,52151L,52152L,
84924 52153L,52154L,52155L,52156L,52157L,52158L,52159L,52160L,52161L,52162L,
84925 52163L,52164L,52165L,52166L,52167L,52168L,52169L,52170L,52171L,52172L,
84926 52173L,52174L,52175L,52176L,52177L,52178L,52179L,52180L,52181L,52182L,
84927 52183L,52184L,52185L,52186L,52187L,52188L,52189L,52190L,52191L,52192L,
84928 52193L,52194L,52195L,52196L,52197L,52198L,52199L,52200L,52201L,52202L,
84929 52203L,52204L,52205L,52206L,52207L,52208L,52209L,52210L,52211L,52212L,
84930 52213L,52214L,52215L,52216L,52217L,52218L,52219L,52220L,52221L,52222L,
84931 52223L,52224L,52225L,52226L,52227L,52228L,52229L,52230L,52231L,52232L,
84932 52233L,52234L,52235L,52236L,52237L,52238L,52239L,52240L,52241L,52242L,
84933 52243L,52244L,52245L,52246L,52247L,52248L,52249L,52250L,52251L,52252L,
84934 52253L,52254L,52255L,52256L,52257L,52258L,52259L,52260L,52261L,52262L,
84935 52263L,52264L,52265L,52266L,52267L,52268L,52269L,52270L,52271L,52272L,
84936 52273L,52274L,52275L,52276L,52277L,52278L,52279L,52280L,52281L,52282L,
84937 52283L,52284L,52285L,52286L,52287L,52288L,52289L,52290L,52291L,52292L,
84938 52293L,52294L,52295L,52296L,52297L,52298L,52299L,52300L,52301L,52302L,
84939 52303L,52304L,52305L,52306L,52307L,52308L,52309L,52310L,52311L,52312L,
84940 52313L,52314L,52315L,52316L,52317L,52318L,52319L,52320L,52321L,52322L,
84941 52323L,52324L,52325L,52326L,52327L,52328L,52329L,52330L,52331L,52332L,
84942 52333L,52334L,52335L,52336L,52337L,52338L,52339L,52340L,52341L,52342L,
84943 52343L,52344L,52345L,52346L,52347L,52348L,52349L,52350L,52351L,52352L,
84944 52353L,52354L,52355L,52356L,52357L,52358L,52359L,52360L,52361L,52362L,
84945 52363L,52364L,52365L,52366L,52367L,52368L,52369L,52370L,52371L,52372L,
84946 52373L,52374L,52375L,52376L,52377L,52378L,52379L,52380L,52381L,52382L,
84947 52383L,52384L,52385L,52386L,52387L,52388L,52389L,52390L,52391L,52392L,
84948 52393L,52394L,52395L,52396L,52397L,52398L,52399L,52400L,52401L,52402L,
84949 52403L,52404L,52405L,52406L,52407L,52408L,52409L,52410L,52411L,52412L,
84950 52413L,52414L,52415L,52416L,52417L,52418L,52419L,52420L,52421L,52422L,
84951 52423L,52424L,52425L,52426L,52427L,52428L,52429L,52430L,52431L,52432L,
84952 52433L,52434L,52435L,52436L,52437L,52438L,52439L,52440L,52441L,52442L,
84953 52443L,52444L,52445L,52446L,52447L,52448L,52449L,52450L,52451L,52452L,
84954 52453L,52454L,52455L,52456L,52457L,52458L,52459L,52460L,52461L,52462L,
84955 52463L,52464L,52465L,52466L,52467L,52468L,52469L,52470L,52471L,52472L,
84956 52473L,52474L,52475L,52476L,52477L,52478L,52479L,52480L,52481L,52482L,
84957 52483L,52484L,52485L,52486L,52487L,52488L,52489L,52490L,52491L,52492L,
84958 52493L,52494L,52495L,52496L,52497L,52498L,52499L,52500L,52501L,52502L,
84959 52503L,52504L,52505L,52506L,52507L,52508L,52509L,52510L,52511L,52512L,
84960 52513L,52514L,52515L,52516L,52517L,52518L,52519L,52520L,52521L,52522L,
84961 52523L,52524L,52525L,52526L,52527L,52528L,52529L,52530L,52531L,52532L,
84962 52533L,52534L,52535L,52536L,52537L,52538L,52539L,52540L,52541L,52542L,
84963 52543L,52544L,52545L,52546L,52547L,52548L,52549L,52550L,52551L,52552L,
84964 52553L,52554L,52555L,52556L,52557L,52558L,52559L,52560L,52561L,52562L,
84965 52563L,52564L,52565L,52566L,52567L,52568L,52569L,52570L,52571L,52572L,
84966 52573L,52574L,52575L,52576L,52577L,52578L,52579L,52580L,52581L,52582L,
84967 52583L,52584L,52585L,52586L,52587L,52588L,52589L,52590L,52591L,52592L,
84968 52593L,52594L,52595L,52596L,52597L,52598L,52599L,52600L,52601L,52602L,
84969 52603L,52604L,52605L,52606L,52607L,52608L,52609L,52610L,52611L,52612L,
84970 52613L,52614L,52615L,52616L,52617L,52618L,52619L,52620L,52621L,52622L,
84971 52623L,52624L,52625L,52626L,52627L,52628L,52629L,52630L,52631L,52632L,
84972 52633L,52634L,52635L,52636L,52637L,52638L,52639L,52640L,52641L,52642L,
84973 52643L,52644L,52645L,52646L,52647L,52648L,52649L,52650L,52651L,52652L,
84974 52653L,52654L,52655L,52656L,52657L,52658L,52659L,52660L,52661L,52662L,
84975 52663L,52664L,52665L,52666L,52667L,52668L,52669L,52670L,52671L,52672L,
84976 52673L,52674L,52675L,52676L,52677L,52678L,52679L,52680L,52681L,52682L,
84977 52683L,52684L,52685L,52686L,52687L,52688L,52689L,52690L,52691L,52692L,
84978 52693L,52694L,52695L,52696L,52697L,52698L,52699L,52700L,52701L,52702L,
84979 52703L,52704L,52705L,52706L,52707L,52708L,52709L,52710L,52711L,52712L,
84980 52713L,52714L,52715L,52716L,52717L,52718L,52719L,52720L,52721L,52722L,
84981 52723L,52724L,52725L,52726L,52727L,52728L,52729L,52730L,52731L,52732L,
84982 52733L,52734L,52735L,52736L,52737L,52738L,52739L,52740L,52741L,52742L,
84983 52743L,52744L,52745L,52746L,52747L,52748L,52749L,52750L,52751L,52752L,
84984 52753L,52754L,52755L,52756L,52757L,52758L,52759L,52760L,52761L,52762L,
84985 52763L,52764L,52765L,52766L,52767L,52768L,52769L,52770L,52771L,52772L,
84986 52773L,52774L,52775L,52776L,52777L,52778L,52779L,52780L,52781L,52782L,
84987 52783L,52784L,52785L,52786L,52787L,52788L,52789L,52790L,52791L,52792L,
84988 52793L,52794L,52795L,52796L,52797L,52798L,52799L,52800L,52801L,52802L,
84989 52803L,52804L,52805L,52806L,52807L,52808L,52809L,52810L,52811L,52812L,
84990 52813L,52814L,52815L,52816L,52817L,52818L,52819L,52820L,52821L,52822L,
84991 52823L,52824L,52825L,52826L,52827L,52828L,52829L,52830L,52831L,52832L,
84992 52833L,52834L,52835L,52836L,52837L,52838L,52839L,52840L,52841L,52842L,
84993 52843L,52844L,52845L,52846L,52847L,52848L,52849L,52850L,52851L,52852L,
84994 52853L,52854L,52855L,52856L,52857L,52858L,52859L,52860L,52861L,52862L,
84995 52863L,52864L,52865L,52866L,52867L,52868L,52869L,52870L,52871L,52872L,
84996 52873L,52874L,52875L,52876L,52877L,52878L,52879L,52880L,52881L,52882L,
84997 52883L,52884L,52885L,52886L,52887L,52888L,52889L,52890L,52891L,52892L,
84998 52893L,52894L,52895L,52896L,52897L,52898L,52899L,52900L,52901L,52902L,
84999 52903L,52904L,52905L,52906L,52907L,52908L,52909L,52910L,52911L,52912L,
85000 52913L,52914L,52915L,52916L,52917L,52918L,52919L,52920L,52921L,52922L,
85001 52923L,52924L,52925L,52926L,52927L,52928L,52929L,52930L,52931L,52932L,
85002 52933L,52934L,52935L,52936L,52937L,52938L,52939L,52940L,52941L,52942L,
85003 52943L,52944L,52945L,52946L,52947L,52948L,52949L,52950L,52951L,52952L,
85004 52953L,52954L,52955L,52956L,52957L,52958L,52959L,52960L,52961L,52962L,
85005 52963L,52964L,52965L,52966L,52967L,52968L,52969L,52970L,52971L,52972L,
85006 52973L,52974L,52975L,52976L,52977L,52978L,52979L,52980L,52981L,52982L,
85007 52983L,52984L,52985L,52986L,52987L,52988L,52989L,52990L,52991L,52992L,
85008 52993L,52994L,52995L,52996L,52997L,52998L,52999L,53000L,53001L,53002L,
85009 53003L,53004L,53005L,53006L,53007L,53008L,53009L,53010L,53011L,53012L,
85010 53013L,53014L,53015L,53016L,53017L,53018L,53019L,53020L,53021L,53022L,
85011 53023L,53024L,53025L,53026L,53027L,53028L,53029L,53030L,53031L,53032L,
85012 53033L,53034L,53035L,53036L,53037L,53038L,53039L,53040L,53041L,53042L,
85013 53043L,53044L,53045L,53046L,53047L,53048L,53049L,53050L,53051L,53052L,
85014 53053L,53054L,53055L,53056L,53057L,53058L,53059L,53060L,53061L,53062L,
85015 53063L,53064L,53065L,53066L,53067L,53068L,53069L,53070L,53071L,53072L,
85016 53073L,53074L,53075L,53076L,53077L,53078L,53079L,53080L,53081L,53082L,
85017 53083L,53084L,53085L,53086L,53087L,53088L,53089L,53090L,53091L,53092L,
85018 53093L,53094L,53095L,53096L,53097L,53098L,53099L,53100L,53101L,53102L,
85019 53103L,53104L,53105L,53106L,53107L,53108L,53109L,53110L,53111L,53112L,
85020 53113L,53114L,53115L,53116L,53117L,53118L,53119L,53120L,53121L,53122L,
85021 53123L,53124L,53125L,53126L,53127L,53128L,53129L,53130L,53131L,53132L,
85022 53133L,53134L,53135L,53136L,53137L,53138L,53139L,53140L,53141L,53142L,
85023 53143L,53144L,53145L,53146L,53147L,53148L,53149L,53150L,53151L,53152L,
85024 53153L,53154L,53155L,53156L,53157L,53158L,53159L,53160L,53161L,53162L,
85025 53163L,53164L,53165L,53166L,53167L,53168L,53169L,53170L,53171L,53172L,
85026 53173L,53174L,53175L,53176L,53177L,53178L,53179L,53180L,53181L,53182L,
85027 53183L,53184L,53185L,53186L,53187L,53188L,53189L,53190L,53191L,53192L,
85028 53193L,53194L,53195L,53196L,53197L,53198L,53199L,53200L,53201L,53202L,
85029 53203L,53204L,53205L,53206L,53207L,53208L,53209L,53210L,53211L,53212L,
85030 53213L,53214L,53215L,53216L,53217L,53218L,53219L,53220L,53221L,53222L,
85031 53223L,53224L,53225L,53226L,53227L,53228L,53229L,53230L,53231L,53232L,
85032 53233L,53234L,53235L,53236L,53237L,53238L,53239L,53240L,53241L,53242L,
85033 53243L,53244L,53245L,53246L,53247L,53248L,53249L,53250L,53251L,53252L,
85034 53253L,53254L,53255L,53256L,53257L,53258L,53259L,53260L,53261L,53262L,
85035 53263L,53264L,53265L,53266L,53267L,53268L,53269L,53270L,53271L,53272L,
85036 53273L,53274L,53275L,53276L,53277L,53278L,53279L,53280L,53281L,53282L,
85037 53283L,53284L,53285L,53286L,53287L,53288L,53289L,53290L,53291L,53292L,
85038 53293L,53294L,53295L,53296L,53297L,53298L,53299L,53300L,53301L,53302L,
85039 53303L,53304L,53305L,53306L,53307L,53308L,53309L,53310L,53311L,53312L,
85040 53313L,53314L,53315L,53316L,53317L,53318L,53319L,53320L,53321L,53322L,
85041 53323L,53324L,53325L,53326L,53327L,53328L,53329L,53330L,53331L,53332L,
85042 53333L,53334L,53335L,53336L,53337L,53338L,53339L,53340L,53341L,53342L,
85043 53343L,53344L,53345L,53346L,53347L,53348L,53349L,53350L,53351L,53352L,
85044 53353L,53354L,53355L,53356L,53357L,53358L,53359L,53360L,53361L,53362L,
85045 53363L,53364L,53365L,53366L,53367L,53368L,53369L,53370L,53371L,53372L,
85046 53373L,53374L,53375L,53376L,53377L,53378L,53379L,53380L,53381L,53382L,
85047 53383L,53384L,53385L,53386L,53387L,53388L,53389L,53390L,53391L,53392L,
85048 53393L,53394L,53395L,53396L,53397L,53398L,53399L,53400L,53401L,53402L,
85049 53403L,53404L,53405L,53406L,53407L,53408L,53409L,53410L,53411L,53412L,
85050 53413L,53414L,53415L,53416L,53417L,53418L,53419L,53420L,53421L,53422L,
85051 53423L,53424L,53425L,53426L,53427L,53428L,53429L,53430L,53431L,53432L,
85052 53433L,53434L,53435L,53436L,53437L,53438L,53439L,53440L,53441L,53442L,
85053 53443L,53444L,53445L,53446L,53447L,53448L,53449L,53450L,53451L,53452L,
85054 53453L,53454L,53455L,53456L,53457L,53458L,53459L,53460L,53461L,53462L,
85055 53463L,53464L,53465L,53466L,53467L,53468L,53469L,53470L,53471L,53472L,
85056 53473L,53474L,53475L,53476L,53477L,53478L,53479L,53480L,53481L,53482L,
85057 53483L,53484L,53485L,53486L,53487L,53488L,53489L,53490L,53491L,53492L,
85058 53493L,53494L,53495L,53496L,53497L,53498L,53499L,53500L,53501L,53502L,
85059 53503L,53504L,53505L,53506L,53507L,53508L,53509L,53510L,53511L,53512L,
85060 53513L,53514L,53515L,53516L,53517L,53518L,53519L,53520L,53521L,53522L,
85061 53523L,53524L,53525L,53526L,53527L,53528L,53529L,53530L,53531L,53532L,
85062 53533L,53534L,53535L,53536L,53537L,53538L,53539L,53540L,53541L,53542L,
85063 53543L,53544L,53545L,53546L,53547L,53548L,53549L,53550L,53551L,53552L,
85064 53553L,53554L,53555L,53556L,53557L,53558L,53559L,53560L,53561L,53562L,
85065 53563L,53564L,53565L,53566L,53567L,53568L,53569L,53570L,53571L,53572L,
85066 53573L,53574L,53575L,53576L,53577L,53578L,53579L,53580L,53581L,53582L,
85067 53583L,53584L,53585L,53586L,53587L,53588L,53589L,53590L,53591L,53592L,
85068 53593L,53594L,53595L,53596L,53597L,53598L,53599L,53600L,53601L,53602L,
85069 53603L,53604L,53605L,53606L,53607L,53608L,53609L,53610L,53611L,53612L,
85070 53613L,53614L,53615L,53616L,53617L,53618L,53619L,53620L,53621L,53622L,
85071 53623L,53624L,53625L,53626L,53627L,53628L,53629L,53630L,53631L,53632L,
85072 53633L,53634L,53635L,53636L,53637L,53638L,53639L,53640L,53641L,53642L,
85073 53643L,53644L,53645L,53646L,53647L,53648L,53649L,53650L,53651L,53652L,
85074 53653L,53654L,53655L,53656L,53657L,53658L,53659L,53660L,53661L,53662L,
85075 53663L,53664L,53665L,53666L,53667L,53668L,53669L,53670L,53671L,53672L,
85076 53673L,53674L,53675L,53676L,53677L,53678L,53679L,53680L,53681L,53682L,
85077 53683L,53684L,53685L,53686L,53687L,53688L,53689L,53690L,53691L,53692L,
85078 53693L,53694L,53695L,53696L,53697L,53698L,53699L,53700L,53701L,53702L,
85079 53703L,53704L,53705L,53706L,53707L,53708L,53709L,53710L,53711L,53712L,
85080 53713L,53714L,53715L,53716L,53717L,53718L,53719L,53720L,53721L,53722L,
85081 53723L,53724L,53725L,53726L,53727L,53728L,53729L,53730L,53731L,53732L,
85082 53733L,53734L,53735L,53736L,53737L,53738L,53739L,53740L,53741L,53742L,
85083 53743L,53744L,53745L,53746L,53747L,53748L,53749L,53750L,53751L,53752L,
85084 53753L,53754L,53755L,53756L,53757L,53758L,53759L,53760L,53761L,53762L,
85085 53763L,53764L,53765L,53766L,53767L,53768L,53769L,53770L,53771L,53772L,
85086 53773L,53774L,53775L,53776L,53777L,53778L,53779L,53780L,53781L,53782L,
85087 53783L,53784L,53785L,53786L,53787L,53788L,53789L,53790L,53791L,53792L,
85088 53793L,53794L,53795L,53796L,53797L,53798L,53799L,53800L,53801L,53802L,
85089 53803L,53804L,53805L,53806L,53807L,53808L,53809L,53810L,53811L,53812L,
85090 53813L,53814L,53815L,53816L,53817L,53818L,53819L,53820L,53821L,53822L,
85091 53823L,53824L,53825L,53826L,53827L,53828L,53829L,53830L,53831L,53832L,
85092 53833L,53834L,53835L,53836L,53837L,53838L,53839L,53840L,53841L,53842L,
85093 53843L,53844L,53845L,53846L,53847L,53848L,53849L,53850L,53851L,53852L,
85094 53853L,53854L,53855L,53856L,53857L,53858L,53859L,53860L,53861L,53862L,
85095 53863L,53864L,53865L,53866L,53867L,53868L,53869L,53870L,53871L,53872L,
85096 53873L,53874L,53875L,53876L,53877L,53878L,53879L,53880L,53881L,53882L,
85097 53883L,53884L,53885L,53886L,53887L,53888L,53889L,53890L,53891L,53892L,
85098 53893L,53894L,53895L,53896L,53897L,53898L,53899L,53900L,53901L,53902L,
85099 53903L,53904L,53905L,53906L,53907L,53908L,53909L,53910L,53911L,53912L,
85100 53913L,53914L,53915L,53916L,53917L,53918L,53919L,53920L,53921L,53922L,
85101 53923L,53924L,53925L,53926L,53927L,53928L,53929L,53930L,53931L,53932L,
85102 53933L,53934L,53935L,53936L,53937L,53938L,53939L,53940L,53941L,53942L,
85103 53943L,53944L,53945L,53946L,53947L,53948L,53949L,53950L,53951L,53952L,
85104 53953L,53954L,53955L,53956L,53957L,53958L,53959L,53960L,53961L,53962L,
85105 53963L,53964L,53965L,53966L,53967L,53968L,53969L,53970L,53971L,53972L,
85106 53973L,53974L,53975L,53976L,53977L,53978L,53979L,53980L,53981L,53982L,
85107 53983L,53984L,53985L,53986L,53987L,53988L,53989L,53990L,53991L,53992L,
85108 53993L,53994L,53995L,53996L,53997L,53998L,53999L,54000L,54001L,54002L,
85109 54003L,54004L,54005L,54006L,54007L,54008L,54009L,54010L,54011L,54012L,
85110 54013L,54014L,54015L,54016L,54017L,54018L,54019L,54020L,54021L,54022L,
85111 54023L,54024L,54025L,54026L,54027L,54028L,54029L,54030L,54031L,54032L,
85112 54033L,54034L,54035L,54036L,54037L,54038L,54039L,54040L,54041L,54042L,
85113 54043L,54044L,54045L,54046L,54047L,54048L,54049L,54050L,54051L,54052L,
85114 54053L,54054L,54055L,54056L,54057L,54058L,54059L,54060L,54061L,54062L,
85115 54063L,54064L,54065L,54066L,54067L,54068L,54069L,54070L,54071L,54072L,
85116 54073L,54074L,54075L,54076L,54077L,54078L,54079L,54080L,54081L,54082L,
85117 54083L,54084L,54085L,54086L,54087L,54088L,54089L,54090L,54091L,54092L,
85118 54093L,54094L,54095L,54096L,54097L,54098L,54099L,54100L,54101L,54102L,
85119 54103L,54104L,54105L,54106L,54107L,54108L,54109L,54110L,54111L,54112L,
85120 54113L,54114L,54115L,54116L,54117L,54118L,54119L,54120L,54121L,54122L,
85121 54123L,54124L,54125L,54126L,54127L,54128L,54129L,54130L,54131L,54132L,
85122 54133L,54134L,54135L,54136L,54137L,54138L,54139L,54140L,54141L,54142L,
85123 54143L,54144L,54145L,54146L,54147L,54148L,54149L,54150L,54151L,54152L,
85124 54153L,54154L,54155L,54156L,54157L,54158L,54159L,54160L,54161L,54162L,
85125 54163L,54164L,54165L,54166L,54167L,54168L,54169L,54170L,54171L,54172L,
85126 54173L,54174L,54175L,54176L,54177L,54178L,54179L,54180L,54181L,54182L,
85127 54183L,54184L,54185L,54186L,54187L,54188L,54189L,54190L,54191L,54192L,
85128 54193L,54194L,54195L,54196L,54197L,54198L,54199L,54200L,54201L,54202L,
85129 54203L,54204L,54205L,54206L,54207L,54208L,54209L,54210L,54211L,54212L,
85130 54213L,54214L,54215L,54216L,54217L,54218L,54219L,54220L,54221L,54222L,
85131 54223L,54224L,54225L,54226L,54227L,54228L,54229L,54230L,54231L,54232L,
85132 54233L,54234L,54235L,54236L,54237L,54238L,54239L,54240L,54241L,54242L,
85133 54243L,54244L,54245L,54246L,54247L,54248L,54249L,54250L,54251L,54252L,
85134 54253L,54254L,54255L,54256L,54257L,54258L,54259L,54260L,54261L,54262L,
85135 54263L,54264L,54265L,54266L,54267L,54268L,54269L,54270L,54271L,54272L,
85136 54273L,54274L,54275L,54276L,54277L,54278L,54279L,54280L,54281L,54282L,
85137 54283L,54284L,54285L,54286L,54287L,54288L,54289L,54290L,54291L,54292L,
85138 54293L,54294L,54295L,54296L,54297L,54298L,54299L,54300L,54301L,54302L,
85139 54303L,54304L,54305L,54306L,54307L,54308L,54309L,54310L,54311L,54312L,
85140 54313L,54314L,54315L,54316L,54317L,54318L,54319L,54320L,54321L,54322L,
85141 54323L,54324L,54325L,54326L,54327L,54328L,54329L,54330L,54331L,54332L,
85142 54333L,54334L,54335L,54336L,54337L,54338L,54339L,54340L,54341L,54342L,
85143 54343L,54344L,54345L,54346L,54347L,54348L,54349L,54350L,54351L,54352L,
85144 54353L,54354L,54355L,54356L,54357L,54358L,54359L,54360L,54361L,54362L,
85145 54363L,54364L,54365L,54366L,54367L,54368L,54369L,54370L,54371L,54372L,
85146 54373L,54374L,54375L,54376L,54377L,54378L,54379L,54380L,54381L,54382L,
85147 54383L,54384L,54385L,54386L,54387L,54388L,54389L,54390L,54391L,54392L,
85148 54393L,54394L,54395L,54396L,54397L,54398L,54399L,54400L,54401L,54402L,
85149 54403L,54404L,54405L,54406L,54407L,54408L,54409L,54410L,54411L,54412L,
85150 54413L,54414L,54415L,54416L,54417L,54418L,54419L,54420L,54421L,54422L,
85151 54423L,54424L,54425L,54426L,54427L,54428L,54429L,54430L,54431L,54432L,
85152 54433L,54434L,54435L,54436L,54437L,54438L,54439L,54440L,54441L,54442L,
85153 54443L,54444L,54445L,54446L,54447L,54448L,54449L,54450L,54451L,54452L,
85154 54453L,54454L,54455L,54456L,54457L,54458L,54459L,54460L,54461L,54462L,
85155 54463L,54464L,54465L,54466L,54467L,54468L,54469L,54470L,54471L,54472L,
85156 54473L,54474L,54475L,54476L,54477L,54478L,54479L,54480L,54481L,54482L,
85157 54483L,54484L,54485L,54486L,54487L,54488L,54489L,54490L,54491L,54492L,
85158 54493L,54494L,54495L,54496L,54497L,54498L,54499L,54500L,54501L,54502L,
85159 54503L,54504L,54505L,54506L,54507L,54508L,54509L,54510L,54511L,54512L,
85160 54513L,54514L,54515L,54516L,54517L,54518L,54519L,54520L,54521L,54522L,
85161 54523L,54524L,54525L,54526L,54527L,54528L,54529L,54530L,54531L,54532L,
85162 54533L,54534L,54535L,54536L,54537L,54538L,54539L,54540L,54541L,54542L,
85163 54543L,54544L,54545L,54546L,54547L,54548L,54549L,54550L,54551L,54552L,
85164 54553L,54554L,54555L,54556L,54557L,54558L,54559L,54560L,54561L,54562L,
85165 54563L,54564L,54565L,54566L,54567L,54568L,54569L,54570L,54571L,54572L,
85166 54573L,54574L,54575L,54576L,54577L,54578L,54579L,54580L,54581L,54582L,
85167 54583L,54584L,54585L,54586L,54587L,54588L,54589L,54590L,54591L,54592L,
85168 54593L,54594L,54595L,54596L,54597L,54598L,54599L,54600L,54601L,54602L,
85169 54603L,54604L,54605L,54606L,54607L,54608L,54609L,54610L,54611L,54612L,
85170 54613L,54614L,54615L,54616L,54617L,54618L,54619L,54620L,54621L,54622L,
85171 54623L,54624L,54625L,54626L,54627L,54628L,54629L,54630L,54631L,54632L,
85172 54633L,54634L,54635L,54636L,54637L,54638L,54639L,54640L,54641L,54642L,
85173 54643L,54644L,54645L,54646L,54647L,54648L,54649L,54650L,54651L,54652L,
85174 54653L,54654L,54655L,54656L,54657L,54658L,54659L,54660L,54661L,54662L,
85175 54663L,54664L,54665L,54666L,54667L,54668L,54669L,54670L,54671L,54672L,
85176 54673L,54674L,54675L,54676L,54677L,54678L,54679L,54680L,54681L,54682L,
85177 54683L,54684L,54685L,54686L,54687L,54688L,54689L,54690L,54691L,54692L,
85178 54693L,54694L,54695L,54696L,54697L,54698L,54699L,54700L,54701L,54702L,
85179 54703L,54704L,54705L,54706L,54707L,54708L,54709L,54710L,54711L,54712L,
85180 54713L,54714L,54715L,54716L,54717L,54718L,54719L,54720L,54721L,54722L,
85181 54723L,54724L,54725L,54726L,54727L,54728L,54729L,54730L,54731L,54732L,
85182 54733L,54734L,54735L,54736L,54737L,54738L,54739L,54740L,54741L,54742L,
85183 54743L,54744L,54745L,54746L,54747L,54748L,54749L,54750L,54751L,54752L,
85184 54753L,54754L,54755L,54756L,54757L,54758L,54759L,54760L,54761L,54762L,
85185 54763L,54764L,54765L,54766L,54767L,54768L,54769L,54770L,54771L,54772L,
85186 54773L,54774L,54775L,54776L,54777L,54778L,54779L,54780L,54781L,54782L,
85187 54783L,54784L,54785L,54786L,54787L,54788L,54789L,54790L,54791L,54792L,
85188 54793L,54794L,54795L,54796L,54797L,54798L,54799L,54800L,54801L,54802L,
85189 54803L,54804L,54805L,54806L,54807L,54808L,54809L,54810L,54811L,54812L,
85190 54813L,54814L,54815L,54816L,54817L,54818L,54819L,54820L,54821L,54822L,
85191 54823L,54824L,54825L,54826L,54827L,54828L,54829L,54830L,54831L,54832L,
85192 54833L,54834L,54835L,54836L,54837L,54838L,54839L,54840L,54841L,54842L,
85193 54843L,54844L,54845L,54846L,54847L,54848L,54849L,54850L,54851L,54852L,
85194 54853L,54854L,54855L,54856L,54857L,54858L,54859L,54860L,54861L,54862L,
85195 54863L,54864L,54865L,54866L,54867L,54868L,54869L,54870L,54871L,54872L,
85196 54873L,54874L,54875L,54876L,54877L,54878L,54879L,54880L,54881L,54882L,
85197 54883L,54884L,54885L,54886L,54887L,54888L,54889L,54890L,54891L,54892L,
85198 54893L,54894L,54895L,54896L,54897L,54898L,54899L,54900L,54901L,54902L,
85199 54903L,54904L,54905L,54906L,54907L,54908L,54909L,54910L,54911L,54912L,
85200 54913L,54914L,54915L,54916L,54917L,54918L,54919L,54920L,54921L,54922L,
85201 54923L,54924L,54925L,54926L,54927L,54928L,54929L,54930L,54931L,54932L,
85202 54933L,54934L,54935L,54936L,54937L,54938L,54939L,54940L,54941L,54942L,
85203 54943L,54944L,54945L,54946L,54947L,54948L,54949L,54950L,54951L,54952L,
85204 54953L,54954L,54955L,54956L,54957L,54958L,54959L,54960L,54961L,54962L,
85205 54963L,54964L,54965L,54966L,54967L,54968L,54969L,54970L,54971L,54972L,
85206 54973L,54974L,54975L,54976L,54977L,54978L,54979L,54980L,54981L,54982L,
85207 54983L,54984L,54985L,54986L,54987L,54988L,54989L,54990L,54991L,54992L,
85208 54993L,54994L,54995L,54996L,54997L,54998L,54999L,55000L,55001L,55002L,
85209 55003L,55004L,55005L,55006L,55007L,55008L,55009L,55010L,55011L,55012L,
85210 55013L,55014L,55015L,55016L,55017L,55018L,55019L,55020L,55021L,55022L,
85211 55023L,55024L,55025L,55026L,55027L,55028L,55029L,55030L,55031L,55032L,
85212 55033L,55034L,55035L,55036L,55037L,55038L,55039L,55040L,55041L,55042L,
85213 55043L,55044L,55045L,55046L,55047L,55048L,55049L,55050L,55051L,55052L,
85214 55053L,55054L,55055L,55056L,55057L,55058L,55059L,55060L,55061L,55062L,
85215 55063L,55064L,55065L,55066L,55067L,55068L,55069L,55070L,55071L,55072L,
85216 55073L,55074L,55075L,55076L,55077L,55078L,55079L,55080L,55081L,55082L,
85217 55083L,55084L,55085L,55086L,55087L,55088L,55089L,55090L,55091L,55092L,
85218 55093L,55094L,55095L,55096L,55097L,55098L,55099L,55100L,55101L,55102L,
85219 55103L,55104L,55105L,55106L,55107L,55108L,55109L,55110L,55111L,55112L,
85220 55113L,55114L,55115L,55116L,55117L,55118L,55119L,55120L,55121L,55122L,
85221 55123L,55124L,55125L,55126L,55127L,55128L,55129L,55130L,55131L,55132L,
85222 55133L,55134L,55135L,55136L,55137L,55138L,55139L,55140L,55141L,55142L,
85223 55143L,55144L,55145L,55146L,55147L,55148L,55149L,55150L,55151L,55152L,
85224 55153L,55154L,55155L,55156L,55157L,55158L,55159L,55160L,55161L,55162L,
85225 55163L,55164L,55165L,55166L,55167L,55168L,55169L,55170L,55171L,55172L,
85226 55173L,55174L,55175L,55176L,55177L,55178L,55179L,55180L,55181L,55182L,
85227 55183L,55184L,55185L,55186L,55187L,55188L,55189L,55190L,55191L,55192L,
85228 55193L,55194L,55195L,55196L,55197L,55198L,55199L,55200L,55201L,55202L,
85229 55203L,55204L,55205L,55206L,55207L,55208L,55209L,55210L,55211L,55212L,
85230 55213L,55214L,55215L,55216L,55217L,55218L,55219L,55220L,55221L,55222L,
85231 55223L,55224L,55225L,55226L,55227L,55228L,55229L,55230L,55231L,55232L,
85232 55233L,55234L,55235L,55236L,55237L,55238L,55239L,55240L,55241L,55242L,
85233 55243L,55244L,55245L,55246L,55247L,55248L,55249L,55250L,55251L,55252L,
85234 55253L,55254L,55255L,55256L,55257L,55258L,55259L,55260L,55261L,55262L,
85235 55263L,55264L,55265L,55266L,55267L,55268L,55269L,55270L,55271L,55272L,
85236 55273L,55274L,55275L,55276L,55277L,55278L,55279L,55280L,55281L,55282L,
85237 55283L,55284L,55285L,55286L,55287L,55288L,55289L,55290L,55291L,55292L,
85238 55293L,55294L,55295L,55296L,55297L,55298L,55299L,55300L,55301L,55302L,
85239 55303L,55304L,55305L,55306L,55307L,55308L,55309L,55310L,55311L,55312L,
85240 55313L,55314L,55315L,55316L,55317L,55318L,55319L,55320L,55321L,55322L,
85241 55323L,55324L,55325L,55326L,55327L,55328L,55329L,55330L,55331L,55332L,
85242 55333L,55334L,55335L,55336L,55337L,55338L,55339L,55340L,55341L,55342L,
85243 55343L,55344L,55345L,55346L,55347L,55348L,55349L,55350L,55351L,55352L,
85244 55353L,55354L,55355L,55356L,55357L,55358L,55359L,55360L,55361L,55362L,
85245 55363L,55364L,55365L,55366L,55367L,55368L,55369L,55370L,55371L,55372L,
85246 55373L,55374L,55375L,55376L,55377L,55378L,55379L,55380L,55381L,55382L,
85247 55383L,55384L,55385L,55386L,55387L,55388L,55389L,55390L,55391L,55392L,
85248 55393L,55394L,55395L,55396L,55397L,55398L,55399L,55400L,55401L,55402L,
85249 55403L,55404L,55405L,55406L,55407L,55408L,55409L,55410L,55411L,55412L,
85250 55413L,55414L,55415L,55416L,55417L,55418L,55419L,55420L,55421L,55422L,
85251 55423L,55424L,55425L,55426L,55427L,55428L,55429L,55430L,55431L,55432L,
85252 55433L,55434L,55435L,55436L,55437L,55438L,55439L,55440L,55441L,55442L,
85253 55443L,55444L,55445L,55446L,55447L,55448L,55449L,55450L,55451L,55452L,
85254 55453L,55454L,55455L,55456L,55457L,55458L,55459L,55460L,55461L,55462L,
85255 55463L,55464L,55465L,55466L,55467L,55468L,55469L,55470L,55471L,55472L,
85256 55473L,55474L,55475L,55476L,55477L,55478L,55479L,55480L,55481L,55482L,
85257 55483L,55484L,55485L,55486L,55487L,55488L,55489L,55490L,55491L,55492L,
85258 55493L,55494L,55495L,55496L,55497L,55498L,55499L,55500L,55501L,55502L,
85259 55503L,55504L,55505L,55506L,55507L,55508L,55509L,55510L,55511L,55512L,
85260 55513L,55514L,55515L,55516L,55517L,55518L,55519L,55520L,55521L,55522L,
85261 55523L,55524L,55525L,55526L,55527L,55528L,55529L,55530L,55531L,55532L,
85262 55533L,55534L,55535L,55536L,55537L,55538L,55539L,55540L,55541L,55542L,
85263 55543L,55544L,55545L,55546L,55547L,55548L,55549L,55550L,55551L,55552L,
85264 55553L,55554L,55555L,55556L,55557L,55558L,55559L,55560L,55561L,55562L,
85265 55563L,55564L,55565L,55566L,55567L,55568L,55569L,55570L,55571L,55572L,
85266 55573L,55574L,55575L,55576L,55577L,55578L,55579L,55580L,55581L,55582L,
85267 55583L,55584L,55585L,55586L,55587L,55588L,55589L,55590L,55591L,55592L,
85268 55593L,55594L,55595L,55596L,55597L,55598L,55599L,55600L,55601L,55602L,
85269 55603L,55604L,55605L,55606L,55607L,55608L,55609L,55610L,55611L,55612L,
85270 55613L,55614L,55615L,55616L,55617L,55618L,55619L,55620L,55621L,55622L,
85271 55623L,55624L,55625L,55626L,55627L,55628L,55629L,55630L,55631L,55632L,
85272 55633L,55634L,55635L,55636L,55637L,55638L,55639L,55640L,55641L,55642L,
85273 55643L,55644L,55645L,55646L,55647L,55648L,55649L,55650L,55651L,55652L,
85274 55653L,55654L,55655L,55656L,55657L,55658L,55659L,55660L,55661L,55662L,
85275 55663L,55664L,55665L,55666L,55667L,55668L,55669L,55670L,55671L,55672L,
85276 55673L,55674L,55675L,55676L,55677L,55678L,55679L,55680L,55681L,55682L,
85277 55683L,55684L,55685L,55686L,55687L,55688L,55689L,55690L,55691L,55692L,
85278 55693L,55694L,55695L,55696L,55697L,55698L,55699L,55700L,55701L,55702L,
85279 55703L,55704L,55705L,55706L,55707L,55708L,55709L,55710L,55711L,55712L,
85280 55713L,55714L,55715L,55716L,55717L,55718L,55719L,55720L,55721L,55722L,
85281 55723L,55724L,55725L,55726L,55727L,55728L,55729L,55730L,55731L,55732L,
85282 55733L,55734L,55735L,55736L,55737L,55738L,55739L,55740L,55741L,55742L,
85283 55743L,55744L,55745L,55746L,55747L,55748L,55749L,55750L,55751L,55752L,
85284 55753L,55754L,55755L,55756L,55757L,55758L,55759L,55760L,55761L,55762L,
85285 55763L,55764L,55765L,55766L,55767L,55768L,55769L,55770L,55771L,55772L,
85286 55773L,55774L,55775L,55776L,55777L,55778L,55779L,55780L,55781L,55782L,
85287 55783L,55784L,55785L,55786L,55787L,55788L,55789L,55790L,55791L,55792L,
85288 55793L,55794L,55795L,55796L,55797L,55798L,55799L,55800L,55801L,55802L,
85289 55803L,55804L,55805L,55806L,55807L,55808L,55809L,55810L,55811L,55812L,
85290 55813L,55814L,55815L,55816L,55817L,55818L,55819L,55820L,55821L,55822L,
85291 55823L,55824L,55825L,55826L,55827L,55828L,55829L,55830L,55831L,55832L,
85292 55833L,55834L,55835L,55836L,55837L,55838L,55839L,55840L,55841L,55842L,
85293 55843L,55844L,55845L,55846L,55847L,55848L,55849L,55850L,55851L,55852L,
85294 55853L,55854L,55855L,55856L,55857L,55858L,55859L,55860L,55861L,55862L,
85295 55863L,55864L,55865L,55866L,55867L,55868L,55869L,55870L,55871L,55872L,
85296 55873L,55874L,55875L,55876L,55877L,55878L,55879L,55880L,55881L,55882L,
85297 55883L,55884L,55885L,55886L,55887L,55888L,55889L,55890L,55891L,55892L,
85298 55893L,55894L,55895L,55896L,55897L,55898L,55899L,55900L,55901L,55902L,
85299 55903L,55904L,55905L,55906L,55907L,55908L,55909L,55910L,55911L,55912L,
85300 55913L,55914L,55915L,55916L,55917L,55918L,55919L,55920L,55921L,55922L,
85301 55923L,55924L,55925L,55926L,55927L,55928L,55929L,55930L,55931L,55932L,
85302 55933L,55934L,55935L,55936L,55937L,55938L,55939L,55940L,55941L,55942L,
85303 55943L,55944L,55945L,55946L,55947L,55948L,55949L,55950L,55951L,55952L,
85304 55953L,55954L,55955L,55956L,55957L,55958L,55959L,55960L,55961L,55962L,
85305 55963L,55964L,55965L,55966L,55967L,55968L,55969L,55970L,55971L,55972L,
85306 55973L,55974L,55975L,55976L,55977L,55978L,55979L,55980L,55981L,55982L,
85307 55983L,55984L,55985L,55986L,55987L,55988L,55989L,55990L,55991L,55992L,
85308 55993L,55994L,55995L,55996L,55997L,55998L,55999L,56000L,56001L,56002L,
85309 56003L,56004L,56005L,56006L,56007L,56008L,56009L,56010L,56011L,56012L,
85310 56013L,56014L,56015L,56016L,56017L,56018L,56019L,56020L,56021L,56022L,
85311 56023L,56024L,56025L,56026L,56027L,56028L,56029L,56030L,56031L,56032L,
85312 56033L,56034L,56035L,56036L,56037L,56038L,56039L,56040L,56041L,56042L,
85313 56043L,56044L,56045L,56046L,56047L,56048L,56049L,56050L,56051L,56052L,
85314 56053L,56054L,56055L,56056L,56057L,56058L,56059L,56060L,56061L,56062L,
85315 56063L,56064L,56065L,56066L,56067L,56068L,56069L,56070L,56071L,56072L,
85316 56073L,56074L,56075L,56076L,56077L,56078L,56079L,56080L,56081L,56082L,
85317 56083L,56084L,56085L,56086L,56087L,56088L,56089L,56090L,56091L,56092L,
85318 56093L,56094L,56095L,56096L,56097L,56098L,56099L,56100L,56101L,56102L,
85319 56103L,56104L,56105L,56106L,56107L,56108L,56109L,56110L,56111L,56112L,
85320 56113L,56114L,56115L,56116L,56117L,56118L,56119L,56120L,56121L,56122L,
85321 56123L,56124L,56125L,56126L,56127L,56128L,56129L,56130L,56131L,56132L,
85322 56133L,56134L,56135L,56136L,56137L,56138L,56139L,56140L,56141L,56142L,
85323 56143L,56144L,56145L,56146L,56147L,56148L,56149L,56150L,56151L,56152L,
85324 56153L,56154L,56155L,56156L,56157L,56158L,56159L,56160L,56161L,56162L,
85325 56163L,56164L,56165L,56166L,56167L,56168L,56169L,56170L,56171L,56172L,
85326 56173L,56174L,56175L,56176L,56177L,56178L,56179L,56180L,56181L,56182L,
85327 56183L,56184L,56185L,56186L,56187L,56188L,56189L,56190L,56191L,56192L,
85328 56193L,56194L,56195L,56196L,56197L,56198L,56199L,56200L,56201L,56202L,
85329 56203L,56204L,56205L,56206L,56207L,56208L,56209L,56210L,56211L,56212L,
85330 56213L,56214L,56215L,56216L,56217L,56218L,56219L,56220L,56221L,56222L,
85331 56223L,56224L,56225L,56226L,56227L,56228L,56229L,56230L,56231L,56232L,
85332 56233L,56234L,56235L,56236L,56237L,56238L,56239L,56240L,56241L,56242L,
85333 56243L,56244L,56245L,56246L,56247L,56248L,56249L,56250L,56251L,56252L,
85334 56253L,56254L,56255L,56256L,56257L,56258L,56259L,56260L,56261L,56262L,
85335 56263L,56264L,56265L,56266L,56267L,56268L,56269L,56270L,56271L,56272L,
85336 56273L,56274L,56275L,56276L,56277L,56278L,56279L,56280L,56281L,56282L,
85337 56283L,56284L,56285L,56286L,56287L,56288L,56289L,56290L,56291L,56292L,
85338 56293L,56294L,56295L,56296L,56297L,56298L,56299L,56300L,56301L,56302L,
85339 56303L,56304L,56305L,56306L,56307L,56308L,56309L,56310L,56311L,56312L,
85340 56313L,56314L,56315L,56316L,56317L,56318L,56319L,56320L,56321L,56322L,
85341 56323L,56324L,56325L,56326L,56327L,56328L,56329L,56330L,56331L,56332L,
85342 56333L,56334L,56335L,56336L,56337L,56338L,56339L,56340L,56341L,56342L,
85343 56343L,56344L,56345L,56346L,56347L,56348L,56349L,56350L,56351L,56352L,
85344 56353L,56354L,56355L,56356L,56357L,56358L,56359L,56360L,56361L,56362L,
85345 56363L,56364L,56365L,56366L,56367L,56368L,56369L,56370L,56371L,56372L,
85346 56373L,56374L,56375L,56376L,56377L,56378L,56379L,56380L,56381L,56382L,
85347 56383L,56384L,56385L,56386L,56387L,56388L,56389L,56390L,56391L,56392L,
85348 56393L,56394L,56395L,56396L,56397L,56398L,56399L,56400L,56401L,56402L,
85349 56403L,56404L,56405L,56406L,56407L,56408L,56409L,56410L,56411L,56412L,
85350 56413L,56414L,56415L,56416L,56417L,56418L,56419L,56420L,56421L,56422L,
85351 56423L,56424L,56425L,56426L,56427L,56428L,56429L,56430L,56431L,56432L,
85352 56433L,56434L,56435L,56436L,56437L,56438L,56439L,56440L,56441L,56442L,
85353 56443L,56444L,56445L,56446L,56447L,56448L,56449L,56450L,56451L,56452L,
85354 56453L,56454L,56455L,56456L,56457L,56458L,56459L,56460L,56461L,56462L,
85355 56463L,56464L,56465L,56466L,56467L,56468L,56469L,56470L,56471L,56472L,
85356 56473L,56474L,56475L,56476L,56477L,56478L,56479L,56480L,56481L,56482L,
85357 56483L,56484L,56485L,56486L,56487L,56488L,56489L,56490L,56491L,56492L,
85358 56493L,56494L,56495L,56496L,56497L,56498L,56499L,56500L,56501L,56502L,
85359 56503L,56504L,56505L,56506L,56507L,56508L,56509L,56510L,56511L,56512L,
85360 56513L,56514L,56515L,56516L,56517L,56518L,56519L,56520L,56521L,56522L,
85361 56523L,56524L,56525L,56526L,56527L,56528L,56529L,56530L,56531L,56532L,
85362 56533L,56534L,56535L,56536L,56537L,56538L,56539L,56540L,56541L,56542L,
85363 56543L,56544L,56545L,56546L,56547L,56548L,56549L,56550L,56551L,56552L,
85364 56553L,56554L,56555L,56556L,56557L,56558L,56559L,56560L,56561L,56562L,
85365 56563L,56564L,56565L,56566L,56567L,56568L,56569L,56570L,56571L,56572L,
85366 56573L,56574L,56575L,56576L,56577L,56578L,56579L,56580L,56581L,56582L,
85367 56583L,56584L,56585L,56586L,56587L,56588L,56589L,56590L,56591L,56592L,
85368 56593L,56594L,56595L,56596L,56597L,56598L,56599L,56600L,56601L,56602L,
85369 56603L,56604L,56605L,56606L,56607L,56608L,56609L,56610L,56611L,56612L,
85370 56613L,56614L,56615L,56616L,56617L,56618L,56619L,56620L,56621L,56622L,
85371 56623L,56624L,56625L,56626L,56627L,56628L,56629L,56630L,56631L,56632L,
85372 56633L,56634L,56635L,56636L,56637L,56638L,56639L,56640L,56641L,56642L,
85373 56643L,56644L,56645L,56646L,56647L,56648L,56649L,56650L,56651L,56652L,
85374 56653L,56654L,56655L,56656L,56657L,56658L,56659L,56660L,56661L,56662L,
85375 56663L,56664L,56665L,56666L,56667L,56668L,56669L,56670L,56671L,56672L,
85376 56673L,56674L,56675L,56676L,56677L,56678L,56679L,56680L,56681L,56682L,
85377 56683L,56684L,56685L,56686L,56687L,56688L,56689L,56690L,56691L,56692L,
85378 56693L,56694L,56695L,56696L,56697L,56698L,56699L,56700L,56701L,56702L,
85379 56703L,56704L,56705L,56706L,56707L,56708L,56709L,56710L,56711L,56712L,
85380 56713L,56714L,56715L,56716L,56717L,56718L,56719L,56720L,56721L,56722L,
85381 56723L,56724L,56725L,56726L,56727L,56728L,56729L,56730L,56731L,56732L,
85382 56733L,56734L,56735L,56736L,56737L,56738L,56739L,56740L,56741L,56742L,
85383 56743L,56744L,56745L,56746L,56747L,56748L,56749L,56750L,56751L,56752L,
85384 56753L,56754L,56755L,56756L,56757L,56758L,56759L,56760L,56761L,56762L,
85385 56763L,56764L,56765L,56766L,56767L,56768L,56769L,56770L,56771L,56772L,
85386 56773L,56774L,56775L,56776L,56777L,56778L,56779L,56780L,56781L,56782L,
85387 56783L,56784L,56785L,56786L,56787L,56788L,56789L,56790L,56791L,56792L,
85388 56793L,56794L,56795L,56796L,56797L,56798L,56799L,56800L,56801L,56802L,
85389 56803L,56804L,56805L,56806L,56807L,56808L,56809L,56810L,56811L,56812L,
85390 56813L,56814L,56815L,56816L,56817L,56818L,56819L,56820L,56821L,56822L,
85391 56823L,56824L,56825L,56826L,56827L,56828L,56829L,56830L,56831L,56832L,
85392 56833L,56834L,56835L,56836L,56837L,56838L,56839L,56840L,56841L,56842L,
85393 56843L,56844L,56845L,56846L,56847L,56848L,56849L,56850L,56851L,56852L,
85394 56853L,56854L,56855L,56856L,56857L,56858L,56859L,56860L,56861L,56862L,
85395 56863L,56864L,56865L,56866L,56867L,56868L,56869L,56870L,56871L,56872L,
85396 56873L,56874L,56875L,56876L,56877L,56878L,56879L,56880L,56881L,56882L,
85397 56883L,56884L,56885L,56886L,56887L,56888L,56889L,56890L,56891L,56892L,
85398 56893L,56894L,56895L,56896L,56897L,56898L,56899L,56900L,56901L,56902L,
85399 56903L,56904L,56905L,56906L,56907L,56908L,56909L,56910L,56911L,56912L,
85400 56913L,56914L,56915L,56916L,56917L,56918L,56919L,56920L,56921L,56922L,
85401 56923L,56924L,56925L,56926L,56927L,56928L,56929L,56930L,56931L,56932L,
85402 56933L,56934L,56935L,56936L,56937L,56938L,56939L,56940L,56941L,56942L,
85403 56943L,56944L,56945L,56946L,56947L,56948L,56949L,56950L,56951L,56952L,
85404 56953L,56954L,56955L,56956L,56957L,56958L,56959L,56960L,56961L,56962L,
85405 56963L,56964L,56965L,56966L,56967L,56968L,56969L,56970L,56971L,56972L,
85406 56973L,56974L,56975L,56976L,56977L,56978L,56979L,56980L,56981L,56982L,
85407 56983L,56984L,56985L,56986L,56987L,56988L,56989L,56990L,56991L,56992L,
85408 56993L,56994L,56995L,56996L,56997L,56998L,56999L,57000L,57001L,57002L,
85409 57003L,57004L,57005L,57006L,57007L,57008L,57009L,57010L,57011L,57012L,
85410 57013L,57014L,57015L,57016L,57017L,57018L,57019L,57020L,57021L,57022L,
85411 57023L,57024L,57025L,57026L,57027L,57028L,57029L,57030L,57031L,57032L,
85412 57033L,57034L,57035L,57036L,57037L,57038L,57039L,57040L,57041L,57042L,
85413 57043L,57044L,57045L,57046L,57047L,57048L,57049L,57050L,57051L,57052L,
85414 57053L,57054L,57055L,57056L,57057L,57058L,57059L,57060L,57061L,57062L,
85415 57063L,57064L,57065L,57066L,57067L,57068L,57069L,57070L,57071L,57072L,
85416 57073L,57074L,57075L,57076L,57077L,57078L,57079L,57080L,57081L,57082L,
85417 57083L,57084L,57085L,57086L,57087L,57088L,57089L,57090L,57091L,57092L,
85418 57093L,57094L,57095L,57096L,57097L,57098L,57099L,57100L,57101L,57102L,
85419 57103L,57104L,57105L,57106L,57107L,57108L,57109L,57110L,57111L,57112L,
85420 57113L,57114L,57115L,57116L,57117L,57118L,57119L,57120L,57121L,57122L,
85421 57123L,57124L,57125L,57126L,57127L,57128L,57129L,57130L,57131L,57132L,
85422 57133L,57134L,57135L,57136L,57137L,57138L,57139L,57140L,57141L,57142L,
85423 57143L,57144L,57145L,57146L,57147L,57148L,57149L,57150L,57151L,57152L,
85424 57153L,57154L,57155L,57156L,57157L,57158L,57159L,57160L,57161L,57162L,
85425 57163L,57164L,57165L,57166L,57167L,57168L,57169L,57170L,57171L,57172L,
85426 57173L,57174L,57175L,57176L,57177L,57178L,57179L,57180L,57181L,57182L,
85427 57183L,57184L,57185L,57186L,57187L,57188L,57189L,57190L,57191L,57192L,
85428 57193L,57194L,57195L,57196L,57197L,57198L,57199L,57200L,57201L,57202L,
85429 57203L,57204L,57205L,57206L,57207L,57208L,57209L,57210L,57211L,57212L,
85430 57213L,57214L,57215L,57216L,57217L,57218L,57219L,57220L,57221L,57222L,
85431 57223L,57224L,57225L,57226L,57227L,57228L,57229L,57230L,57231L,57232L,
85432 57233L,57234L,57235L,57236L,57237L,57238L,57239L,57240L,57241L,57242L,
85433 57243L,57244L,57245L,57246L,57247L,57248L,57249L,57250L,57251L,57252L,
85434 57253L,57254L,57255L,57256L,57257L,57258L,57259L,57260L,57261L,57262L,
85435 57263L,57264L,57265L,57266L,57267L,57268L,57269L,57270L,57271L,57272L,
85436 57273L,57274L,57275L,57276L,57277L,57278L,57279L,57280L,57281L,57282L,
85437 57283L,57284L,57285L,57286L,57287L,57288L,57289L,57290L,57291L,57292L,
85438 57293L,57294L,57295L,57296L,57297L,57298L,57299L,57300L,57301L,57302L,
85439 57303L,57304L,57305L,57306L,57307L,57308L,57309L,57310L,57311L,57312L,
85440 57313L,57314L,57315L,57316L,57317L,57318L,57319L,57320L,57321L,57322L,
85441 57323L,57324L,57325L,57326L,57327L,57328L,57329L,57330L,57331L,57332L,
85442 57333L,57334L,57335L,57336L,57337L,57338L,57339L,57340L,57341L,57342L,
85443 57343L,57344L,57345L,57346L,57347L,57348L,57349L,57350L,57351L,57352L,
85444 57353L,57354L,57355L,57356L,57357L,57358L,57359L,57360L,57361L,57362L,
85445 57363L,57364L,57365L,57366L,57367L,57368L,57369L,57370L,57371L,57372L,
85446 57373L,57374L,57375L,57376L,57377L,57378L,57379L,57380L,57381L,57382L,
85447 57383L,57384L,57385L,57386L,57387L,57388L,57389L,57390L,57391L,57392L,
85448 57393L,57394L,57395L,57396L,57397L,57398L,57399L,57400L,57401L,57402L,
85449 57403L,57404L,57405L,57406L,57407L,57408L,57409L,57410L,57411L,57412L,
85450 57413L,57414L,57415L,57416L,57417L,57418L,57419L,57420L,57421L,57422L,
85451 57423L,57424L,57425L,57426L,57427L,57428L,57429L,57430L,57431L,57432L,
85452 57433L,57434L,57435L,57436L,57437L,57438L,57439L,57440L,57441L,57442L,
85453 57443L,57444L,57445L,57446L,57447L,57448L,57449L,57450L,57451L,57452L,
85454 57453L,57454L,57455L,57456L,57457L,57458L,57459L,57460L,57461L,57462L,
85455 57463L,57464L,57465L,57466L,57467L,57468L,57469L,57470L,57471L,57472L,
85456 57473L,57474L,57475L,57476L,57477L,57478L,57479L,57480L,57481L,57482L,
85457 57483L,57484L,57485L,57486L,57487L,57488L,57489L,57490L,57491L,57492L,
85458 57493L,57494L,57495L,57496L,57497L,57498L,57499L,57500L,57501L,57502L,
85459 57503L,57504L,57505L,57506L,57507L,57508L,57509L,57510L,57511L,57512L,
85460 57513L,57514L,57515L,57516L,57517L,57518L,57519L,57520L,57521L,57522L,
85461 57523L,57524L,57525L,57526L,57527L,57528L,57529L,57530L,57531L,57532L,
85462 57533L,57534L,57535L,57536L,57537L,57538L,57539L,57540L,57541L,57542L,
85463 57543L,57544L,57545L,57546L,57547L,57548L,57549L,57550L,57551L,57552L,
85464 57553L,57554L,57555L,57556L,57557L,57558L,57559L,57560L,57561L,57562L,
85465 57563L,57564L,57565L,57566L,57567L,57568L,57569L,57570L,57571L,57572L,
85466 57573L,57574L,57575L,57576L,57577L,57578L,57579L,57580L,57581L,57582L,
85467 57583L,57584L,57585L,57586L,57587L,57588L,57589L,57590L,57591L,57592L,
85468 57593L,57594L,57595L,57596L,57597L,57598L,57599L,57600L,57601L,57602L,
85469 57603L,57604L,57605L,57606L,57607L,57608L,57609L,57610L,57611L,57612L,
85470 57613L,57614L,57615L,57616L,57617L,57618L,57619L,57620L,57621L,57622L,
85471 57623L,57624L,57625L,57626L,57627L,57628L,57629L,57630L,57631L,57632L,
85472 57633L,57634L,57635L,57636L,57637L,57638L,57639L,57640L,57641L,57642L,
85473 57643L,57644L,57645L,57646L,57647L,57648L,57649L,57650L,57651L,57652L,
85474 57653L,57654L,57655L,57656L,57657L,57658L,57659L,57660L,57661L,57662L,
85475 57663L,57664L,57665L,57666L,57667L,57668L,57669L,57670L,57671L,57672L,
85476 57673L,57674L,57675L,57676L,57677L,57678L,57679L,57680L,57681L,57682L,
85477 57683L,57684L,57685L,57686L,57687L,57688L,57689L,57690L,57691L,57692L,
85478 57693L,57694L,57695L,57696L,57697L,57698L,57699L,57700L,57701L,57702L,
85479 57703L,57704L,57705L,57706L,57707L,57708L,57709L,57710L,57711L,57712L,
85480 57713L,57714L,57715L,57716L,57717L,57718L,57719L,57720L,57721L,57722L,
85481 57723L,57724L,57725L,57726L,57727L,57728L,57729L,57730L,57731L,57732L,
85482 57733L,57734L,57735L,57736L,57737L,57738L,57739L,57740L,57741L,57742L,
85483 57743L,57744L,57745L,57746L,57747L,57748L,57749L,57750L,57751L,57752L,
85484 57753L,57754L,57755L,57756L,57757L,57758L,57759L,57760L,57761L,57762L,
85485 57763L,57764L,57765L,57766L,57767L,57768L,57769L,57770L,57771L,57772L,
85486 57773L,57774L,57775L,57776L,57777L,57778L,57779L,57780L,57781L,57782L,
85487 57783L,57784L,57785L,57786L,57787L,57788L,57789L,57790L,57791L,57792L,
85488 57793L,57794L,57795L,57796L,57797L,57798L,57799L,57800L,57801L,57802L,
85489 57803L,57804L,57805L,57806L,57807L,57808L,57809L,57810L,57811L,57812L,
85490 57813L,57814L,57815L,57816L,57817L,57818L,57819L,57820L,57821L,57822L,
85491 57823L,57824L,57825L,57826L,57827L,57828L,57829L,57830L,57831L,57832L,
85492 57833L,57834L,57835L,57836L,57837L,57838L,57839L,57840L,57841L,57842L,
85493 57843L,57844L,57845L,57846L,57847L,57848L,57849L,57850L,57851L,57852L,
85494 57853L,57854L,57855L,57856L,57857L,57858L,57859L,57860L,57861L,57862L,
85495 57863L,57864L,57865L,57866L,57867L,57868L,57869L,57870L,57871L,57872L,
85496 57873L,57874L,57875L,57876L,57877L,57878L,57879L,57880L,57881L,57882L,
85497 57883L,57884L,57885L,57886L,57887L,57888L,57889L,57890L,57891L,57892L,
85498 57893L,57894L,57895L,57896L,57897L,57898L,57899L,57900L,57901L,57902L,
85499 57903L,57904L,57905L,57906L,57907L,57908L,57909L,57910L,57911L,57912L,
85500 57913L,57914L,57915L,57916L,57917L,57918L,57919L,57920L,57921L,57922L,
85501 57923L,57924L,57925L,57926L,57927L,57928L,57929L,57930L,57931L,57932L,
85502 57933L,57934L,57935L,57936L,57937L,57938L,57939L,57940L,57941L,57942L,
85503 57943L,57944L,57945L,57946L,57947L,57948L,57949L,57950L,57951L,57952L,
85504 57953L,57954L,57955L,57956L,57957L,57958L,57959L,57960L,57961L,57962L,
85505 57963L,57964L,57965L,57966L,57967L,57968L,57969L,57970L,57971L,57972L,
85506 57973L,57974L,57975L,57976L,57977L,57978L,57979L,57980L,57981L,57982L,
85507 57983L,57984L,57985L,57986L,57987L,57988L,57989L,57990L,57991L,57992L,
85508 57993L,57994L,57995L,57996L,57997L,57998L,57999L,58000L,58001L,58002L,
85509 58003L,58004L,58005L,58006L,58007L,58008L,58009L,58010L,58011L,58012L,
85510 58013L,58014L,58015L,58016L,58017L,58018L,58019L,58020L,58021L,58022L,
85511 58023L,58024L,58025L,58026L,58027L,58028L,58029L,58030L,58031L,58032L,
85512 58033L,58034L,58035L,58036L,58037L,58038L,58039L,58040L,58041L,58042L,
85513 58043L,58044L,58045L,58046L,58047L,58048L,58049L,58050L,58051L,58052L,
85514 58053L,58054L,58055L,58056L,58057L,58058L,58059L,58060L,58061L,58062L,
85515 58063L,58064L,58065L,58066L,58067L,58068L,58069L,58070L,58071L,58072L,
85516 58073L,58074L,58075L,58076L,58077L,58078L,58079L,58080L,58081L,58082L,
85517 58083L,58084L,58085L,58086L,58087L,58088L,58089L,58090L,58091L,58092L,
85518 58093L,58094L,58095L,58096L,58097L,58098L,58099L,58100L,58101L,58102L,
85519 58103L,58104L,58105L,58106L,58107L,58108L,58109L,58110L,58111L,58112L,
85520 58113L,58114L,58115L,58116L,58117L,58118L,58119L,58120L,58121L,58122L,
85521 58123L,58124L,58125L,58126L,58127L,58128L,58129L,58130L,58131L,58132L,
85522 58133L,58134L,58135L,58136L,58137L,58138L,58139L,58140L,58141L,58142L,
85523 58143L,58144L,58145L,58146L,58147L,58148L,58149L,58150L,58151L,58152L,
85524 58153L,58154L,58155L,58156L,58157L,58158L,58159L,58160L,58161L,58162L,
85525 58163L,58164L,58165L,58166L,58167L,58168L,58169L,58170L,58171L,58172L,
85526 58173L,58174L,58175L,58176L,58177L,58178L,58179L,58180L,58181L,58182L,
85527 58183L,58184L,58185L,58186L,58187L,58188L,58189L,58190L,58191L,58192L,
85528 58193L,58194L,58195L,58196L,58197L,58198L,58199L,58200L,58201L,58202L,
85529 58203L,58204L,58205L,58206L,58207L,58208L,58209L,58210L,58211L,58212L,
85530 58213L,58214L,58215L,58216L,58217L,58218L,58219L,58220L,58221L,58222L,
85531 58223L,58224L,58225L,58226L,58227L,58228L,58229L,58230L,58231L,58232L,
85532 58233L,58234L,58235L,58236L,58237L,58238L,58239L,58240L,58241L,58242L,
85533 58243L,58244L,58245L,58246L,58247L,58248L,58249L,58250L,58251L,58252L,
85534 58253L,58254L,58255L,58256L,58257L,58258L,58259L,58260L,58261L,58262L,
85535 58263L,58264L,58265L,58266L,58267L,58268L,58269L,58270L,58271L,58272L,
85536 58273L,58274L,58275L,58276L,58277L,58278L,58279L,58280L,58281L,58282L,
85537 58283L,58284L,58285L,58286L,58287L,58288L,58289L,58290L,58291L,58292L,
85538 58293L,58294L,58295L,58296L,58297L,58298L,58299L,58300L,58301L,58302L,
85539 58303L,58304L,58305L,58306L,58307L,58308L,58309L,58310L,58311L,58312L,
85540 58313L,58314L,58315L,58316L,58317L,58318L,58319L,58320L,58321L,58322L,
85541 58323L,58324L,58325L,58326L,58327L,58328L,58329L,58330L,58331L,58332L,
85542 58333L,58334L,58335L,58336L,58337L,58338L,58339L,58340L,58341L,58342L,
85543 58343L,58344L,58345L,58346L,58347L,58348L,58349L,58350L,58351L,58352L,
85544 58353L,58354L,58355L,58356L,58357L,58358L,58359L,58360L,58361L,58362L,
85545 58363L,58364L,58365L,58366L,58367L,58368L,58369L,58370L,58371L,58372L,
85546 58373L,58374L,58375L,58376L,58377L,58378L,58379L,58380L,58381L,58382L,
85547 58383L,58384L,58385L,58386L,58387L,58388L,58389L,58390L,58391L,58392L,
85548 58393L,58394L,58395L,58396L,58397L,58398L,58399L,58400L,58401L,58402L,
85549 58403L,58404L,58405L,58406L,58407L,58408L,58409L,58410L,58411L,58412L,
85550 58413L,58414L,58415L,58416L,58417L,58418L,58419L,58420L,58421L,58422L,
85551 58423L,58424L,58425L,58426L,58427L,58428L,58429L,58430L,58431L,58432L,
85552 58433L,58434L,58435L,58436L,58437L,58438L,58439L,58440L,58441L,58442L,
85553 58443L,58444L,58445L,58446L,58447L,58448L,58449L,58450L,58451L,58452L,
85554 58453L,58454L,58455L,58456L,58457L,58458L,58459L,58460L,58461L,58462L,
85555 58463L,58464L,58465L,58466L,58467L,58468L,58469L,58470L,58471L,58472L,
85556 58473L,58474L,58475L,58476L,58477L,58478L,58479L,58480L,58481L,58482L,
85557 58483L,58484L,58485L,58486L,58487L,58488L,58489L,58490L,58491L,58492L,
85558 58493L,58494L,58495L,58496L,58497L,58498L,58499L,58500L,58501L,58502L,
85559 58503L,58504L,58505L,58506L,58507L,58508L,58509L,58510L,58511L,58512L,
85560 58513L,58514L,58515L,58516L,58517L,58518L,58519L,58520L,58521L,58522L,
85561 58523L,58524L,58525L,58526L,58527L,58528L,58529L,58530L,58531L,58532L,
85562 58533L,58534L,58535L,58536L,58537L,58538L,58539L,58540L,58541L,58542L,
85563 58543L,58544L,58545L,58546L,58547L,58548L,58549L,58550L,58551L,58552L,
85564 58553L,58554L,58555L,58556L,58557L,58558L,58559L,58560L,58561L,58562L,
85565 58563L,58564L,58565L,58566L,58567L,58568L,58569L,58570L,58571L,58572L,
85566 58573L,58574L,58575L,58576L,58577L,58578L,58579L,58580L,58581L,58582L,
85567 58583L,58584L,58585L,58586L,58587L,58588L,58589L,58590L,58591L,58592L,
85568 58593L,58594L,58595L,58596L,58597L,58598L,58599L,58600L,58601L,58602L,
85569 58603L,58604L,58605L,58606L,58607L,58608L,58609L,58610L,58611L,58612L,
85570 58613L,58614L,58615L,58616L,58617L,58618L,58619L,58620L,58621L,58622L,
85571 58623L,58624L,58625L,58626L,58627L,58628L,58629L,58630L,58631L,58632L,
85572 58633L,58634L,58635L,58636L,58637L,58638L,58639L,58640L,58641L,58642L,
85573 58643L,58644L,58645L,58646L,58647L,58648L,58649L,58650L,58651L,58652L,
85574 58653L,58654L,58655L,58656L,58657L,58658L,58659L,58660L,58661L,58662L,
85575 58663L,58664L,58665L,58666L,58667L,58668L,58669L,58670L,58671L,58672L,
85576 58673L,58674L,58675L,58676L,58677L,58678L,58679L,58680L,58681L,58682L,
85577 58683L,58684L,58685L,58686L,58687L,58688L,58689L,58690L,58691L,58692L,
85578 58693L,58694L,58695L,58696L,58697L,58698L,58699L,58700L,58701L,58702L,
85579 58703L,58704L,58705L,58706L,58707L,58708L,58709L,58710L,58711L,58712L,
85580 58713L,58714L,58715L,58716L,58717L,58718L,58719L,58720L,58721L,58722L,
85581 58723L,58724L,58725L,58726L,58727L,58728L,58729L,58730L,58731L,58732L,
85582 58733L,58734L,58735L,58736L,58737L,58738L,58739L,58740L,58741L,58742L,
85583 58743L,58744L,58745L,58746L,58747L,58748L,58749L,58750L,58751L,58752L,
85584 58753L,58754L,58755L,58756L,58757L,58758L,58759L,58760L,58761L,58762L,
85585 58763L,58764L,58765L,58766L,58767L,58768L,58769L,58770L,58771L,58772L,
85586 58773L,58774L,58775L,58776L,58777L,58778L,58779L,58780L,58781L,58782L,
85587 58783L,58784L,58785L,58786L,58787L,58788L,58789L,58790L,58791L,58792L,
85588 58793L,58794L,58795L,58796L,58797L,58798L,58799L,58800L,58801L,58802L,
85589 58803L,58804L,58805L,58806L,58807L,58808L,58809L,58810L,58811L,58812L,
85590 58813L,58814L,58815L,58816L,58817L,58818L,58819L,58820L,58821L,58822L,
85591 58823L,58824L,58825L,58826L,58827L,58828L,58829L,58830L,58831L,58832L,
85592 58833L,58834L,58835L,58836L,58837L,58838L,58839L,58840L,58841L,58842L,
85593 58843L,58844L,58845L,58846L,58847L,58848L,58849L,58850L,58851L,58852L,
85594 58853L,58854L,58855L,58856L,58857L,58858L,58859L,58860L,58861L,58862L,
85595 58863L,58864L,58865L,58866L,58867L,58868L,58869L,58870L,58871L,58872L,
85596 58873L,58874L,58875L,58876L,58877L,58878L,58879L,58880L,58881L,58882L,
85597 58883L,58884L,58885L,58886L,58887L,58888L,58889L,58890L,58891L,58892L,
85598 58893L,58894L,58895L,58896L,58897L,58898L,58899L,58900L,58901L,58902L,
85599 58903L,58904L,58905L,58906L,58907L,58908L,58909L,58910L,58911L,58912L,
85600 58913L,58914L,58915L,58916L,58917L,58918L,58919L,58920L,58921L,58922L,
85601 58923L,58924L,58925L,58926L,58927L,58928L,58929L,58930L,58931L,58932L,
85602 58933L,58934L,58935L,58936L,58937L,58938L,58939L,58940L,58941L,58942L,
85603 58943L,58944L,58945L,58946L,58947L,58948L,58949L,58950L,58951L,58952L,
85604 58953L,58954L,58955L,58956L,58957L,58958L,58959L,58960L,58961L,58962L,
85605 58963L,58964L,58965L,58966L,58967L,58968L,58969L,58970L,58971L,58972L,
85606 58973L,58974L,58975L,58976L,58977L,58978L,58979L,58980L,58981L,58982L,
85607 58983L,58984L,58985L,58986L,58987L,58988L,58989L,58990L,58991L,58992L,
85608 58993L,58994L,58995L,58996L,58997L,58998L,58999L,59000L,59001L,59002L,
85609 59003L,59004L,59005L,59006L,59007L,59008L,59009L,59010L,59011L,59012L,
85610 59013L,59014L,59015L,59016L,59017L,59018L,59019L,59020L,59021L,59022L,
85611 59023L,59024L,59025L,59026L,59027L,59028L,59029L,59030L,59031L,59032L,
85612 59033L,59034L,59035L,59036L,59037L,59038L,59039L,59040L,59041L,59042L,
85613 59043L,59044L,59045L,59046L,59047L,59048L,59049L,59050L,59051L,59052L,
85614 59053L,59054L,59055L,59056L,59057L,59058L,59059L,59060L,59061L,59062L,
85615 59063L,59064L,59065L,59066L,59067L,59068L,59069L,59070L,59071L,59072L,
85616 59073L,59074L,59075L,59076L,59077L,59078L,59079L,59080L,59081L,59082L,
85617 59083L,59084L,59085L,59086L,59087L,59088L,59089L,59090L,59091L,59092L,
85618 59093L,59094L,59095L,59096L,59097L,59098L,59099L,59100L,59101L,59102L,
85619 59103L,59104L,59105L,59106L,59107L,59108L,59109L,59110L,59111L,59112L,
85620 59113L,59114L,59115L,59116L,59117L,59118L,59119L,59120L,59121L,59122L,
85621 59123L,59124L,59125L,59126L,59127L,59128L,59129L,59130L,59131L,59132L,
85622 59133L,59134L,59135L,59136L,59137L,59138L,59139L,59140L,59141L,59142L,
85623 59143L,59144L,59145L,59146L,59147L,59148L,59149L,59150L,59151L,59152L,
85624 59153L,59154L,59155L,59156L,59157L,59158L,59159L,59160L,59161L,59162L,
85625 59163L,59164L,59165L,59166L,59167L,59168L,59169L,59170L,59171L,59172L,
85626 59173L,59174L,59175L,59176L,59177L,59178L,59179L,59180L,59181L,59182L,
85627 59183L,59184L,59185L,59186L,59187L,59188L,59189L,59190L,59191L,59192L,
85628 59193L,59194L,59195L,59196L,59197L,59198L,59199L,59200L,59201L,59202L,
85629 59203L,59204L,59205L,59206L,59207L,59208L,59209L,59210L,59211L,59212L,
85630 59213L,59214L,59215L,59216L,59217L,59218L,59219L,59220L,59221L,59222L,
85631 59223L,59224L,59225L,59226L,59227L,59228L,59229L,59230L,59231L,59232L,
85632 59233L,59234L,59235L,59236L,59237L,59238L,59239L,59240L,59241L,59242L,
85633 59243L,59244L,59245L,59246L,59247L,59248L,59249L,59250L,59251L,59252L,
85634 59253L,59254L,59255L,59256L,59257L,59258L,59259L,59260L,59261L,59262L,
85635 59263L,59264L,59265L,59266L,59267L,59268L,59269L,59270L,59271L,59272L,
85636 59273L,59274L,59275L,59276L,59277L,59278L,59279L,59280L,59281L,59282L,
85637 59283L,59284L,59285L,59286L,59287L,59288L,59289L,59290L,59291L,59292L,
85638 59293L,59294L,59295L,59296L,59297L,59298L,59299L,59300L,59301L,59302L,
85639 59303L,59304L,59305L,59306L,59307L,59308L,59309L,59310L,59311L,59312L,
85640 59313L,59314L,59315L,59316L,59317L,59318L,59319L,59320L,59321L,59322L,
85641 59323L,59324L,59325L,59326L,59327L,59328L,59329L,59330L,59331L,59332L,
85642 59333L,59334L,59335L,59336L,59337L,59338L,59339L,59340L,59341L,59342L,
85643 59343L,59344L,59345L,59346L,59347L,59348L,59349L,59350L,59351L,59352L,
85644 59353L,59354L,59355L,59356L,59357L,59358L,59359L,59360L,59361L,59362L,
85645 59363L,59364L,59365L,59366L,59367L,59368L,59369L,59370L,59371L,59372L,
85646 59373L,59374L,59375L,59376L,59377L,59378L,59379L,59380L,59381L,59382L,
85647 59383L,59384L,59385L,59386L,59387L,59388L,59389L,59390L,59391L,59392L,
85648 59393L,59394L,59395L,59396L,59397L,59398L,59399L,59400L,59401L,59402L,
85649 59403L,59404L,59405L,59406L,59407L,59408L,59409L,59410L,59411L,59412L,
85650 59413L,59414L,59415L,59416L,59417L,59418L,59419L,59420L,59421L,59422L,
85651 59423L,59424L,59425L,59426L,59427L,59428L,59429L,59430L,59431L,59432L,
85652 59433L,59434L,59435L,59436L,59437L,59438L,59439L,59440L,59441L,59442L,
85653 59443L,59444L,59445L,59446L,59447L,59448L,59449L,59450L,59451L,59452L,
85654 59453L,59454L,59455L,59456L,59457L,59458L,59459L,59460L,59461L,59462L,
85655 59463L,59464L,59465L,59466L,59467L,59468L,59469L,59470L,59471L,59472L,
85656 59473L,59474L,59475L,59476L,59477L,59478L,59479L,59480L,59481L,59482L,
85657 59483L,59484L,59485L,59486L,59487L,59488L,59489L,59490L,59491L,59492L,
85658 59493L,59494L,59495L,59496L,59497L,59498L,59499L,59500L,59501L,59502L,
85659 59503L,59504L,59505L,59506L,59507L,59508L,59509L,59510L,59511L,59512L,
85660 59513L,59514L,59515L,59516L,59517L,59518L,59519L,59520L,59521L,59522L,
85661 59523L,59524L,59525L,59526L,59527L,59528L,59529L,59530L,59531L,59532L,
85662 59533L,59534L,59535L,59536L,59537L,59538L,59539L,59540L,59541L,59542L,
85663 59543L,59544L,59545L,59546L,59547L,59548L,59549L,59550L,59551L,59552L,
85664 59553L,59554L,59555L,59556L,59557L,59558L,59559L,59560L,59561L,59562L,
85665 59563L,59564L,59565L,59566L,59567L,59568L,59569L,59570L,59571L,59572L,
85666 59573L,59574L,59575L,59576L,59577L,59578L,59579L,59580L,59581L,59582L,
85667 59583L,59584L,59585L,59586L,59587L,59588L,59589L,59590L,59591L,59592L,
85668 59593L,59594L,59595L,59596L,59597L,59598L,59599L,59600L,59601L,59602L,
85669 59603L,59604L,59605L,59606L,59607L,59608L,59609L,59610L,59611L,59612L,
85670 59613L,59614L,59615L,59616L,59617L,59618L,59619L,59620L,59621L,59622L,
85671 59623L,59624L,59625L,59626L,59627L,59628L,59629L,59630L,59631L,59632L,
85672 59633L,59634L,59635L,59636L,59637L,59638L,59639L,59640L,59641L,59642L,
85673 59643L,59644L,59645L,59646L,59647L,59648L,59649L,59650L,59651L,59652L,
85674 59653L,59654L,59655L,59656L,59657L,59658L,59659L,59660L,59661L,59662L,
85675 59663L,59664L,59665L,59666L,59667L,59668L,59669L,59670L,59671L,59672L,
85676 59673L,59674L,59675L,59676L,59677L,59678L,59679L,59680L,59681L,59682L,
85677 59683L,59684L,59685L,59686L,59687L,59688L,59689L,59690L,59691L,59692L,
85678 59693L,59694L,59695L,59696L,59697L,59698L,59699L,59700L,59701L,59702L,
85679 59703L,59704L,59705L,59706L,59707L,59708L,59709L,59710L,59711L,59712L,
85680 59713L,59714L,59715L,59716L,59717L,59718L,59719L,59720L,59721L,59722L,
85681 59723L,59724L,59725L,59726L,59727L,59728L,59729L,59730L,59731L,59732L,
85682 59733L,59734L,59735L,59736L,59737L,59738L,59739L,59740L,59741L,59742L,
85683 59743L,59744L,59745L,59746L,59747L,59748L,59749L,59750L,59751L,59752L,
85684 59753L,59754L,59755L,59756L,59757L,59758L,59759L,59760L,59761L,59762L,
85685 59763L,59764L,59765L,59766L,59767L,59768L,59769L,59770L,59771L,59772L,
85686 59773L,59774L,59775L,59776L,59777L,59778L,59779L,59780L,59781L,59782L,
85687 59783L,59784L,59785L,59786L,59787L,59788L,59789L,59790L,59791L,59792L,
85688 59793L,59794L,59795L,59796L,59797L,59798L,59799L,59800L,59801L,59802L,
85689 59803L,59804L,59805L,59806L,59807L,59808L,59809L,59810L,59811L,59812L,
85690 59813L,59814L,59815L,59816L,59817L,59818L,59819L,59820L,59821L,59822L,
85691 59823L,59824L,59825L,59826L,59827L,59828L,59829L,59830L,59831L,59832L,
85692 59833L,59834L,59835L,59836L,59837L,59838L,59839L,59840L,59841L,59842L,
85693 59843L,59844L,59845L,59846L,59847L,59848L,59849L,59850L,59851L,59852L,
85694 59853L,59854L,59855L,59856L,59857L,59858L,59859L,59860L,59861L,59862L,
85695 59863L,59864L,59865L,59866L,59867L,59868L,59869L,59870L,59871L,59872L,
85696 59873L,59874L,59875L,59876L,59877L,59878L,59879L,59880L,59881L,59882L,
85697 59883L,59884L,59885L,59886L,59887L,59888L,59889L,59890L,59891L,59892L,
85698 59893L,59894L,59895L,59896L,59897L,59898L,59899L,59900L,59901L,59902L,
85699 59903L,59904L,59905L,59906L,59907L,59908L,59909L,59910L,59911L,59912L,
85700 59913L,59914L,59915L,59916L,59917L,59918L,59919L,59920L,59921L,59922L,
85701 59923L,59924L,59925L,59926L,59927L,59928L,59929L,59930L,59931L,59932L,
85702 59933L,59934L,59935L,59936L,59937L,59938L,59939L,59940L,59941L,59942L,
85703 59943L,59944L,59945L,59946L,59947L,59948L,59949L,59950L,59951L,59952L,
85704 59953L,59954L,59955L,59956L,59957L,59958L,59959L,59960L,59961L,59962L,
85705 59963L,59964L,59965L,59966L,59967L,59968L,59969L,59970L,59971L,59972L,
85706 59973L,59974L,59975L,59976L,59977L,59978L,59979L,59980L,59981L,59982L,
85707 59983L,59984L,59985L,59986L,59987L,59988L,59989L,59990L,59991L,59992L,
85708 59993L,59994L,59995L,59996L,59997L,59998L,59999L,60000L,60001L,60002L,
85709 60003L,60004L,60005L,60006L,60007L,60008L,60009L,60010L,60011L,60012L,
85710 60013L,60014L,60015L,60016L,60017L,60018L,60019L,60020L,60021L,60022L,
85711 60023L,60024L,60025L,60026L,60027L,60028L,60029L,60030L,60031L,60032L,
85712 60033L,60034L,60035L,60036L,60037L,60038L,60039L,60040L,60041L,60042L,
85713 60043L,60044L,60045L,60046L,60047L,60048L,60049L,60050L,60051L,60052L,
85714 60053L,60054L,60055L,60056L,60057L,60058L,60059L,60060L,60061L,60062L,
85715 60063L,60064L,60065L,60066L,60067L,60068L,60069L,60070L,60071L,60072L,
85716 60073L,60074L,60075L,60076L,60077L,60078L,60079L,60080L,60081L,60082L,
85717 60083L,60084L,60085L,60086L,60087L,60088L,60089L,60090L,60091L,60092L,
85718 60093L,60094L,60095L,60096L,60097L,60098L,60099L,60100L,60101L,60102L,
85719 60103L,60104L,60105L,60106L,60107L,60108L,60109L,60110L,60111L,60112L,
85720 60113L,60114L,60115L,60116L,60117L,60118L,60119L,60120L,60121L,60122L,
85721 60123L,60124L,60125L,60126L,60127L,60128L,60129L,60130L,60131L,60132L,
85722 60133L,60134L,60135L,60136L,60137L,60138L,60139L,60140L,60141L,60142L,
85723 60143L,60144L,60145L,60146L,60147L,60148L,60149L,60150L,60151L,60152L,
85724 60153L,60154L,60155L,60156L,60157L,60158L,60159L,60160L,60161L,60162L,
85725 60163L,60164L,60165L,60166L,60167L,60168L,60169L,60170L,60171L,60172L,
85726 60173L,60174L,60175L,60176L,60177L,60178L,60179L,60180L,60181L,60182L,
85727 60183L,60184L,60185L,60186L,60187L,60188L,60189L,60190L,60191L,60192L,
85728 60193L,60194L,60195L,60196L,60197L,60198L,60199L,60200L,60201L,60202L,
85729 60203L,60204L,60205L,60206L,60207L,60208L,60209L,60210L,60211L,60212L,
85730 60213L,60214L,60215L,60216L,60217L,60218L,60219L,60220L,60221L,60222L,
85731 60223L,60224L,60225L,60226L,60227L,60228L,60229L,60230L,60231L,60232L,
85732 60233L,60234L,60235L,60236L,60237L,60238L,60239L,60240L,60241L,60242L,
85733 60243L,60244L,60245L,60246L,60247L,60248L,60249L,60250L,60251L,60252L,
85734 60253L,60254L,60255L,60256L,60257L,60258L,60259L,60260L,60261L,60262L,
85735 60263L,60264L,60265L,60266L,60267L,60268L,60269L,60270L,60271L,60272L,
85736 60273L,60274L,60275L,60276L,60277L,60278L,60279L,60280L,60281L,60282L,
85737 60283L,60284L,60285L,60286L,60287L,60288L,60289L,60290L,60291L,60292L,
85738 60293L,60294L,60295L,60296L,60297L,60298L,60299L,60300L,60301L,60302L,
85739 60303L,60304L,60305L,60306L,60307L,60308L,60309L,60310L,60311L,60312L,
85740 60313L,60314L,60315L,60316L,60317L,60318L,60319L,60320L,60321L,60322L,
85741 60323L,60324L,60325L,60326L,60327L,60328L,60329L,60330L,60331L,60332L,
85742 60333L,60334L,60335L,60336L,60337L,60338L,60339L,60340L,60341L,60342L,
85743 60343L,60344L,60345L,60346L,60347L,60348L,60349L,60350L,60351L,60352L,
85744 60353L,60354L,60355L,60356L,60357L,60358L,60359L,60360L,60361L,60362L,
85745 60363L,60364L,60365L,60366L,60367L,60368L,60369L,60370L,60371L,60372L,
85746 60373L,60374L,60375L,60376L,60377L,60378L,60379L,60380L,60381L,60382L,
85747 60383L,60384L,60385L,60386L,60387L,60388L,60389L,60390L,60391L,60392L,
85748 60393L,60394L,60395L,60396L,60397L,60398L,60399L,60400L,60401L,60402L,
85749 60403L,60404L,60405L,60406L,60407L,60408L,60409L,60410L,60411L,60412L,
85750 60413L,60414L,60415L,60416L,60417L,60418L,60419L,60420L,60421L,60422L,
85751 60423L,60424L,60425L,60426L,60427L,60428L,60429L,60430L,60431L,60432L,
85752 60433L,60434L,60435L,60436L,60437L,60438L,60439L,60440L,60441L,60442L,
85753 60443L,60444L,60445L,60446L,60447L,60448L,60449L,60450L,60451L,60452L,
85754 60453L,60454L,60455L,60456L,60457L,60458L,60459L,60460L,60461L,60462L,
85755 60463L,60464L,60465L,60466L,60467L,60468L,60469L,60470L,60471L,60472L,
85756 60473L,60474L,60475L,60476L,60477L,60478L,60479L,60480L,60481L,60482L,
85757 60483L,60484L,60485L,60486L,60487L,60488L,60489L,60490L,60491L,60492L,
85758 60493L,60494L,60495L,60496L,60497L,60498L,60499L,60500L,60501L,60502L,
85759 60503L,60504L,60505L,60506L,60507L,60508L,60509L,60510L,60511L,60512L,
85760 60513L,60514L,60515L,60516L,60517L,60518L,60519L,60520L,60521L,60522L,
85761 60523L,60524L,60525L,60526L,60527L,60528L,60529L,60530L,60531L,60532L,
85762 60533L,60534L,60535L,60536L,60537L,60538L,60539L,60540L,60541L,60542L,
85763 60543L,60544L,60545L,60546L,60547L,60548L,60549L,60550L,60551L,60552L,
85764 60553L,60554L,60555L,60556L,60557L,60558L,60559L,60560L,60561L,60562L,
85765 60563L,60564L,60565L,60566L,60567L,60568L,60569L,60570L,60571L,60572L,
85766 60573L,60574L,60575L,60576L,60577L,60578L,60579L,60580L,60581L,60582L,
85767 60583L,60584L,60585L,60586L,60587L,60588L,60589L,60590L,60591L,60592L,
85768 60593L,60594L,60595L,60596L,60597L,60598L,60599L,60600L,60601L,60602L,
85769 60603L,60604L,60605L,60606L,60607L,60608L,60609L,60610L,60611L,60612L,
85770 60613L,60614L,60615L,60616L,60617L,60618L,60619L,60620L,60621L,60622L,
85771 60623L,60624L,60625L,60626L,60627L,60628L,60629L,60630L,60631L,60632L,
85772 60633L,60634L,60635L,60636L,60637L,60638L,60639L,60640L,60641L,60642L,
85773 60643L,60644L,60645L,60646L,60647L,60648L,60649L,60650L,60651L,60652L,
85774 60653L,60654L,60655L,60656L,60657L,60658L,60659L,60660L,60661L,60662L,
85775 60663L,60664L,60665L,60666L,60667L,60668L,60669L,60670L,60671L,60672L,
85776 60673L,60674L,60675L,60676L,60677L,60678L,60679L,60680L,60681L,60682L,
85777 60683L,60684L,60685L,60686L,60687L,60688L,60689L,60690L,60691L,60692L,
85778 60693L,60694L,60695L,60696L,60697L,60698L,60699L,60700L,60701L,60702L,
85779 60703L,60704L,60705L,60706L,60707L,60708L,60709L,60710L,60711L,60712L,
85780 60713L,60714L,60715L,60716L,60717L,60718L,60719L,60720L,60721L,60722L,
85781 60723L,60724L,60725L,60726L,60727L,60728L,60729L,60730L,60731L,60732L,
85782 60733L,60734L,60735L,60736L,60737L,60738L,60739L,60740L,60741L,60742L,
85783 60743L,60744L,60745L,60746L,60747L,60748L,60749L,60750L,60751L,60752L,
85784 60753L,60754L,60755L,60756L,60757L,60758L,60759L,60760L,60761L,60762L,
85785 60763L,60764L,60765L,60766L,60767L,60768L,60769L,60770L,60771L,60772L,
85786 60773L,60774L,60775L,60776L,60777L,60778L,60779L,60780L,60781L,60782L,
85787 60783L,60784L,60785L,60786L,60787L,60788L,60789L,60790L,60791L,60792L,
85788 60793L,60794L,60795L,60796L,60797L,60798L,60799L,60800L,60801L,60802L,
85789 60803L,60804L,60805L,60806L,60807L,60808L,60809L,60810L,60811L,60812L,
85790 60813L,60814L,60815L,60816L,60817L,60818L,60819L,60820L,60821L,60822L,
85791 60823L,60824L,60825L,60826L,60827L,60828L,60829L,60830L,60831L,60832L,
85792 60833L,60834L,60835L,60836L,60837L,60838L,60839L,60840L,60841L,60842L,
85793 60843L,60844L,60845L,60846L,60847L,60848L,60849L,60850L,60851L,60852L,
85794 60853L,60854L,60855L,60856L,60857L,60858L,60859L,60860L,60861L,60862L,
85795 60863L,60864L,60865L,60866L,60867L,60868L,60869L,60870L,60871L,60872L,
85796 60873L,60874L,60875L,60876L,60877L,60878L,60879L,60880L,60881L,60882L,
85797 60883L,60884L,60885L,60886L,60887L,60888L,60889L,60890L,60891L,60892L,
85798 60893L,60894L,60895L,60896L,60897L,60898L,60899L,60900L,60901L,60902L,
85799 60903L,60904L,60905L,60906L,60907L,60908L,60909L,60910L,60911L,60912L,
85800 60913L,60914L,60915L,60916L,60917L,60918L,60919L,60920L,60921L,60922L,
85801 60923L,60924L,60925L,60926L,60927L,60928L,60929L,60930L,60931L,60932L,
85802 60933L,60934L,60935L,60936L,60937L,60938L,60939L,60940L,60941L,60942L,
85803 60943L,60944L,60945L,60946L,60947L,60948L,60949L,60950L,60951L,60952L,
85804 60953L,60954L,60955L,60956L,60957L,60958L,60959L,60960L,60961L,60962L,
85805 60963L,60964L,60965L,60966L,60967L,60968L,60969L,60970L,60971L,60972L,
85806 60973L,60974L,60975L,60976L,60977L,60978L,60979L,60980L,60981L,60982L,
85807 60983L,60984L,60985L,60986L,60987L,60988L,60989L,60990L,60991L,60992L,
85808 60993L,60994L,60995L,60996L,60997L,60998L,60999L,61000L,61001L,61002L,
85809 61003L,61004L,61005L,61006L,61007L,61008L,61009L,61010L,61011L,61012L,
85810 61013L,61014L,61015L,61016L,61017L,61018L,61019L,61020L,61021L,61022L,
85811 61023L,61024L,61025L,61026L,61027L,61028L,61029L,61030L,61031L,61032L,
85812 61033L,61034L,61035L,61036L,61037L,61038L,61039L,61040L,61041L,61042L,
85813 61043L,61044L,61045L,61046L,61047L,61048L,61049L,61050L,61051L,61052L,
85814 61053L,61054L,61055L,61056L,61057L,61058L,61059L,61060L,61061L,61062L,
85815 61063L,61064L,61065L,61066L,61067L,61068L,61069L,61070L,61071L,61072L,
85816 61073L,61074L,61075L,61076L,61077L,61078L,61079L,61080L,61081L,61082L,
85817 61083L,61084L,61085L,61086L,61087L,61088L,61089L,61090L,61091L,61092L,
85818 61093L,61094L,61095L,61096L,61097L,61098L,61099L,61100L,61101L,61102L,
85819 61103L,61104L,61105L,61106L,61107L,61108L,61109L,61110L,61111L,61112L,
85820 61113L,61114L,61115L,61116L,61117L,61118L,61119L,61120L,61121L,61122L,
85821 61123L,61124L,61125L,61126L,61127L,61128L,61129L,61130L,61131L,61132L,
85822 61133L,61134L,61135L,61136L,61137L,61138L,61139L,61140L,61141L,61142L,
85823 61143L,61144L,61145L,61146L,61147L,61148L,61149L,61150L,61151L,61152L,
85824 61153L,61154L,61155L,61156L,61157L,61158L,61159L,61160L,61161L,61162L,
85825 61163L,61164L,61165L,61166L,61167L,61168L,61169L,61170L,61171L,61172L,
85826 61173L,61174L,61175L,61176L,61177L,61178L,61179L,61180L,61181L,61182L,
85827 61183L,61184L,61185L,61186L,61187L,61188L,61189L,61190L,61191L,61192L,
85828 61193L,61194L,61195L,61196L,61197L,61198L,61199L,61200L,61201L,61202L,
85829 61203L,61204L,61205L,61206L,61207L,61208L,61209L,61210L,61211L,61212L,
85830 61213L,61214L,61215L,61216L,61217L,61218L,61219L,61220L,61221L,61222L,
85831 61223L,61224L,61225L,61226L,61227L,61228L,61229L,61230L,61231L,61232L,
85832 61233L,61234L,61235L,61236L,61237L,61238L,61239L,61240L,61241L,61242L,
85833 61243L,61244L,61245L,61246L,61247L,61248L,61249L,61250L,61251L,61252L,
85834 61253L,61254L,61255L,61256L,61257L,61258L,61259L,61260L,61261L,61262L,
85835 61263L,61264L,61265L,61266L,61267L,61268L,61269L,61270L,61271L,61272L,
85836 61273L,61274L,61275L,61276L,61277L,61278L,61279L,61280L,61281L,61282L,
85837 61283L,61284L,61285L,61286L,61287L,61288L,61289L,61290L,61291L,61292L,
85838 61293L,61294L,61295L,61296L,61297L,61298L,61299L,61300L,61301L,61302L,
85839 61303L,61304L,61305L,61306L,61307L,61308L,61309L,61310L,61311L,61312L,
85840 61313L,61314L,61315L,61316L,61317L,61318L,61319L,61320L,61321L,61322L,
85841 61323L,61324L,61325L,61326L,61327L,61328L,61329L,61330L,61331L,61332L,
85842 61333L,61334L,61335L,61336L,61337L,61338L,61339L,61340L,61341L,61342L,
85843 61343L,61344L,61345L,61346L,61347L,61348L,61349L,61350L,61351L,61352L,
85844 61353L,61354L,61355L,61356L,61357L,61358L,61359L,61360L,61361L,61362L,
85845 61363L,61364L,61365L,61366L,61367L,61368L,61369L,61370L,61371L,61372L,
85846 61373L,61374L,61375L,61376L,61377L,61378L,61379L,61380L,61381L,61382L,
85847 61383L,61384L,61385L,61386L,61387L,61388L,61389L,61390L,61391L,61392L,
85848 61393L,61394L,61395L,61396L,61397L,61398L,61399L,61400L,61401L,61402L,
85849 61403L,61404L,61405L,61406L,61407L,61408L,61409L,61410L,61411L,61412L,
85850 61413L,61414L,61415L,61416L,61417L,61418L,61419L,61420L,61421L,61422L,
85851 61423L,61424L,61425L,61426L,61427L,61428L,61429L,61430L,61431L,61432L,
85852 61433L,61434L,61435L,61436L,61437L,61438L,61439L,61440L,61441L,61442L,
85853 61443L,61444L,61445L,61446L,61447L,61448L,61449L,61450L,61451L,61452L,
85854 61453L,61454L,61455L,61456L,61457L,61458L,61459L,61460L,61461L,61462L,
85855 61463L,61464L,61465L,61466L,61467L,61468L,61469L,61470L,61471L,61472L,
85856 61473L,61474L,61475L,61476L,61477L,61478L,61479L,61480L,61481L,61482L,
85857 61483L,61484L,61485L,61486L,61487L,61488L,61489L,61490L,61491L,61492L,
85858 61493L,61494L,61495L,61496L,61497L,61498L,61499L,61500L,61501L,61502L,
85859 61503L,61504L,61505L,61506L,61507L,61508L,61509L,61510L,61511L,61512L,
85860 61513L,61514L,61515L,61516L,61517L,61518L,61519L,61520L,61521L,61522L,
85861 61523L,61524L,61525L,61526L,61527L,61528L,61529L,61530L,61531L,61532L,
85862 61533L,61534L,61535L,61536L,61537L,61538L,61539L,61540L,61541L,61542L,
85863 61543L,61544L,61545L,61546L,61547L,61548L,61549L,61550L,61551L,61552L,
85864 61553L,61554L,61555L,61556L,61557L,61558L,61559L,61560L,61561L,61562L,
85865 61563L,61564L,61565L,61566L,61567L,61568L,61569L,61570L,61571L,61572L,
85866 61573L,61574L,61575L,61576L,61577L,61578L,61579L,61580L,61581L,61582L,
85867 61583L,61584L,61585L,61586L,61587L,61588L,61589L,61590L,61591L,61592L,
85868 61593L,61594L,61595L,61596L,61597L,61598L,61599L,61600L,61601L,61602L,
85869 61603L,61604L,61605L,61606L,61607L,61608L,61609L,61610L,61611L,61612L,
85870 61613L,61614L,61615L,61616L,61617L,61618L,61619L,61620L,61621L,61622L,
85871 61623L,61624L,61625L,61626L,61627L,61628L,61629L,61630L,61631L,61632L,
85872 61633L,61634L,61635L,61636L,61637L,61638L,61639L,61640L,61641L,61642L,
85873 61643L,61644L,61645L,61646L,61647L,61648L,61649L,61650L,61651L,61652L,
85874 61653L,61654L,61655L,61656L,61657L,61658L,61659L,61660L,61661L,61662L,
85875 61663L,61664L,61665L,61666L,61667L,61668L,61669L,61670L,61671L,61672L,
85876 61673L,61674L,61675L,61676L,61677L,61678L,61679L,61680L,61681L,61682L,
85877 61683L,61684L,61685L,61686L,61687L,61688L,61689L,61690L,61691L,61692L,
85878 61693L,61694L,61695L,61696L,61697L,61698L,61699L,61700L,61701L,61702L,
85879 61703L,61704L,61705L,61706L,61707L,61708L,61709L,61710L,61711L,61712L,
85880 61713L,61714L,61715L,61716L,61717L,61718L,61719L,61720L,61721L,61722L,
85881 61723L,61724L,61725L,61726L,61727L,61728L,61729L,61730L,61731L,61732L,
85882 61733L,61734L,61735L,61736L,61737L,61738L,61739L,61740L,61741L,61742L,
85883 61743L,61744L,61745L,61746L,61747L,61748L,61749L,61750L,61751L,61752L,
85884 61753L,61754L,61755L,61756L,61757L,61758L,61759L,61760L,61761L,61762L,
85885 61763L,61764L,61765L,61766L,61767L,61768L,61769L,61770L,61771L,61772L,
85886 61773L,61774L,61775L,61776L,61777L,61778L,61779L,61780L,61781L,61782L,
85887 61783L,61784L,61785L,61786L,61787L,61788L,61789L,61790L,61791L,61792L,
85888 61793L,61794L,61795L,61796L,61797L,61798L,61799L,61800L,61801L,61802L,
85889 61803L,61804L,61805L,61806L,61807L,61808L,61809L,61810L,61811L,61812L,
85890 61813L,61814L,61815L,61816L,61817L,61818L,61819L,61820L,61821L,61822L,
85891 61823L,61824L,61825L,61826L,61827L,61828L,61829L,61830L,61831L,61832L,
85892 61833L,61834L,61835L,61836L,61837L,61838L,61839L,61840L,61841L,61842L,
85893 61843L,61844L,61845L,61846L,61847L,61848L,61849L,61850L,61851L,61852L,
85894 61853L,61854L,61855L,61856L,61857L,61858L,61859L,61860L,61861L,61862L,
85895 61863L,61864L,61865L,61866L,61867L,61868L,61869L,61870L,61871L,61872L,
85896 61873L,61874L,61875L,61876L,61877L,61878L,61879L,61880L,61881L,61882L,
85897 61883L,61884L,61885L,61886L,61887L,61888L,61889L,61890L,61891L,61892L,
85898 61893L,61894L,61895L,61896L,61897L,61898L,61899L,61900L,61901L,61902L,
85899 61903L,61904L,61905L,61906L,61907L,61908L,61909L,61910L,61911L,61912L,
85900 61913L,61914L,61915L,61916L,61917L,61918L,61919L,61920L,61921L,61922L,
85901 61923L,61924L,61925L,61926L,61927L,61928L,61929L,61930L,61931L,61932L,
85902 61933L,61934L,61935L,61936L,61937L,61938L,61939L,61940L,61941L,61942L,
85903 61943L,61944L,61945L,61946L,61947L,61948L,61949L,61950L,61951L,61952L,
85904 61953L,61954L,61955L,61956L,61957L,61958L,61959L,61960L,61961L,61962L,
85905 61963L,61964L,61965L,61966L,61967L,61968L,61969L,61970L,61971L,61972L,
85906 61973L,61974L,61975L,61976L,61977L,61978L,61979L,61980L,61981L,61982L,
85907 61983L,61984L,61985L,61986L,61987L,61988L,61989L,61990L,61991L,61992L,
85908 61993L,61994L,61995L,61996L,61997L,61998L,61999L,62000L,62001L,62002L,
85909 62003L,62004L,62005L,62006L,62007L,62008L,62009L,62010L,62011L,62012L,
85910 62013L,62014L,62015L,62016L,62017L,62018L,62019L,62020L,62021L,62022L,
85911 62023L,62024L,62025L,62026L,62027L,62028L,62029L,62030L,62031L,62032L,
85912 62033L,62034L,62035L,62036L,62037L,62038L,62039L,62040L,62041L,62042L,
85913 62043L,62044L,62045L,62046L,62047L,62048L,62049L,62050L,62051L,62052L,
85914 62053L,62054L,62055L,62056L,62057L,62058L,62059L,62060L,62061L,62062L,
85915 62063L,62064L,62065L,62066L,62067L,62068L,62069L,62070L,62071L,62072L,
85916 62073L,62074L,62075L,62076L,62077L,62078L,62079L,62080L,62081L,62082L,
85917 62083L,62084L,62085L,62086L,62087L,62088L,62089L,62090L,62091L,62092L,
85918 62093L,62094L,62095L,62096L,62097L,62098L,62099L,62100L,62101L,62102L,
85919 62103L,62104L,62105L,62106L,62107L,62108L,62109L,62110L,62111L,62112L,
85920 62113L,62114L,62115L,62116L,62117L,62118L,62119L,62120L,62121L,62122L,
85921 62123L,62124L,62125L,62126L,62127L,62128L,62129L,62130L,62131L,62132L,
85922 62133L,62134L,62135L,62136L,62137L,62138L,62139L,62140L,62141L,62142L,
85923 62143L,62144L,62145L,62146L,62147L,62148L,62149L,62150L,62151L,62152L,
85924 62153L,62154L,62155L,62156L,62157L,62158L,62159L,62160L,62161L,62162L,
85925 62163L,62164L,62165L,62166L,62167L,62168L,62169L,62170L,62171L,62172L,
85926 62173L,62174L,62175L,62176L,62177L,62178L,62179L,62180L,62181L,62182L,
85927 62183L,62184L,62185L,62186L,62187L,62188L,62189L,62190L,62191L,62192L,
85928 62193L,62194L,62195L,62196L,62197L,62198L,62199L,62200L,62201L,62202L,
85929 62203L,62204L,62205L,62206L,62207L,62208L,62209L,62210L,62211L,62212L,
85930 62213L,62214L,62215L,62216L,62217L,62218L,62219L,62220L,62221L,62222L,
85931 62223L,62224L,62225L,62226L,62227L,62228L,62229L,62230L,62231L,62232L,
85932 62233L,62234L,62235L,62236L,62237L,62238L,62239L,62240L,62241L,62242L,
85933 62243L,62244L,62245L,62246L,62247L,62248L,62249L,62250L,62251L,62252L,
85934 62253L,62254L,62255L,62256L,62257L,62258L,62259L,62260L,62261L,62262L,
85935 62263L,62264L,62265L,62266L,62267L,62268L,62269L,62270L,62271L,62272L,
85936 62273L,62274L,62275L,62276L,62277L,62278L,62279L,62280L,62281L,62282L,
85937 62283L,62284L,62285L,62286L,62287L,62288L,62289L,62290L,62291L,62292L,
85938 62293L,62294L,62295L,62296L,62297L,62298L,62299L,62300L,62301L,62302L,
85939 62303L,62304L,62305L,62306L,62307L,62308L,62309L,62310L,62311L,62312L,
85940 62313L,62314L,62315L,62316L,62317L,62318L,62319L,62320L,62321L,62322L,
85941 62323L,62324L,62325L,62326L,62327L,62328L,62329L,62330L,62331L,62332L,
85942 62333L,62334L,62335L,62336L,62337L,62338L,62339L,62340L,62341L,62342L,
85943 62343L,62344L,62345L,62346L,62347L,62348L,62349L,62350L,62351L,62352L,
85944 62353L,62354L,62355L,62356L,62357L,62358L,62359L,62360L,62361L,62362L,
85945 62363L,62364L,62365L,62366L,62367L,62368L,62369L,62370L,62371L,62372L,
85946 62373L,62374L,62375L,62376L,62377L,62378L,62379L,62380L,62381L,62382L,
85947 62383L,62384L,62385L,62386L,62387L,62388L,62389L,62390L,62391L,62392L,
85948 62393L,62394L,62395L,62396L,62397L,62398L,62399L,62400L,62401L,62402L,
85949 62403L,62404L,62405L,62406L,62407L,62408L,62409L,62410L,62411L,62412L,
85950 62413L,62414L,62415L,62416L,62417L,62418L,62419L,62420L,62421L,62422L,
85951 62423L,62424L,62425L,62426L,62427L,62428L,62429L,62430L,62431L,62432L,
85952 62433L,62434L,62435L,62436L,62437L,62438L,62439L,62440L,62441L,62442L,
85953 62443L,62444L,62445L,62446L,62447L,62448L,62449L,62450L,62451L,62452L,
85954 62453L,62454L,62455L,62456L,62457L,62458L,62459L,62460L,62461L,62462L,
85955 62463L,62464L,62465L,62466L,62467L,62468L,62469L,62470L,62471L,62472L,
85956 62473L,62474L,62475L,62476L,62477L,62478L,62479L,62480L,62481L,62482L,
85957 62483L,62484L,62485L,62486L,62487L,62488L,62489L,62490L,62491L,62492L,
85958 62493L,62494L,62495L,62496L,62497L,62498L,62499L,62500L,62501L,62502L,
85959 62503L,62504L,62505L,62506L,62507L,62508L,62509L,62510L,62511L,62512L,
85960 62513L,62514L,62515L,62516L,62517L,62518L,62519L,62520L,62521L,62522L,
85961 62523L,62524L,62525L,62526L,62527L,62528L,62529L,62530L,62531L,62532L,
85962 62533L,62534L,62535L,62536L,62537L,62538L,62539L,62540L,62541L,62542L,
85963 62543L,62544L,62545L,62546L,62547L,62548L,62549L,62550L,62551L,62552L,
85964 62553L,62554L,62555L,62556L,62557L,62558L,62559L,62560L,62561L,62562L,
85965 62563L,62564L,62565L,62566L,62567L,62568L,62569L,62570L,62571L,62572L,
85966 62573L,62574L,62575L,62576L,62577L,62578L,62579L,62580L,62581L,62582L,
85967 62583L,62584L,62585L,62586L,62587L,62588L,62589L,62590L,62591L,62592L,
85968 62593L,62594L,62595L,62596L,62597L,62598L,62599L,62600L,62601L,62602L,
85969 62603L,62604L,62605L,62606L,62607L,62608L,62609L,62610L,62611L,62612L,
85970 62613L,62614L,62615L,62616L,62617L,62618L,62619L,62620L,62621L,62622L,
85971 62623L,62624L,62625L,62626L,62627L,62628L,62629L,62630L,62631L,62632L,
85972 62633L,62634L,62635L,62636L,62637L,62638L,62639L,62640L,62641L,62642L,
85973 62643L,62644L,62645L,62646L,62647L,62648L,62649L,62650L,62651L,62652L,
85974 62653L,62654L,62655L,62656L,62657L,62658L,62659L,62660L,62661L,62662L,
85975 62663L,62664L,62665L,62666L,62667L,62668L,62669L,62670L,62671L,62672L,
85976 62673L,62674L,62675L,62676L,62677L,62678L,62679L,62680L,62681L,62682L,
85977 62683L,62684L,62685L,62686L,62687L,62688L,62689L,62690L,62691L,62692L,
85978 62693L,62694L,62695L,62696L,62697L,62698L,62699L,62700L,62701L,62702L,
85979 62703L,62704L,62705L,62706L,62707L,62708L,62709L,62710L,62711L,62712L,
85980 62713L,62714L,62715L,62716L,62717L,62718L,62719L,62720L,62721L,62722L,
85981 62723L,62724L,62725L,62726L,62727L,62728L,62729L,62730L,62731L,62732L,
85982 62733L,62734L,62735L,62736L,62737L,62738L,62739L,62740L,62741L,62742L,
85983 62743L,62744L,62745L,62746L,62747L,62748L,62749L,62750L,62751L,62752L,
85984 62753L,62754L,62755L,62756L,62757L,62758L,62759L,62760L,62761L,62762L,
85985 62763L,62764L,62765L,62766L,62767L,62768L,62769L,62770L,62771L,62772L,
85986 62773L,62774L,62775L,62776L,62777L,62778L,62779L,62780L,62781L,62782L,
85987 62783L,62784L,62785L,62786L,62787L,62788L,62789L,62790L,62791L,62792L,
85988 62793L,62794L,62795L,62796L,62797L,62798L,62799L,62800L,62801L,62802L,
85989 62803L,62804L,62805L,62806L,62807L,62808L,62809L,62810L,62811L,62812L,
85990 62813L,62814L,62815L,62816L,62817L,62818L,62819L,62820L,62821L,62822L,
85991 62823L,62824L,62825L,62826L,62827L,62828L,62829L,62830L,62831L,62832L,
85992 62833L,62834L,62835L,62836L,62837L,62838L,62839L,62840L,62841L,62842L,
85993 62843L,62844L,62845L,62846L,62847L,62848L,62849L,62850L,62851L,62852L,
85994 62853L,62854L,62855L,62856L,62857L,62858L,62859L,62860L,62861L,62862L,
85995 62863L,62864L,62865L,62866L,62867L,62868L,62869L,62870L,62871L,62872L,
85996 62873L,62874L,62875L,62876L,62877L,62878L,62879L,62880L,62881L,62882L,
85997 62883L,62884L,62885L,62886L,62887L,62888L,62889L,62890L,62891L,62892L,
85998 62893L,62894L,62895L,62896L,62897L,62898L,62899L,62900L,62901L,62902L,
85999 62903L,62904L,62905L,62906L,62907L,62908L,62909L,62910L,62911L,62912L,
86000 62913L,62914L,62915L,62916L,62917L,62918L,62919L,62920L,62921L,62922L,
86001 62923L,62924L,62925L,62926L,62927L,62928L,62929L,62930L,62931L,62932L,
86002 62933L,62934L,62935L,62936L,62937L,62938L,62939L,62940L,62941L,62942L,
86003 62943L,62944L,62945L,62946L,62947L,62948L,62949L,62950L,62951L,62952L,
86004 62953L,62954L,62955L,62956L,62957L,62958L,62959L,62960L,62961L,62962L,
86005 62963L,62964L,62965L,62966L,62967L,62968L,62969L,62970L,62971L,62972L,
86006 62973L,62974L,62975L,62976L,62977L,62978L,62979L,62980L,62981L,62982L,
86007 62983L,62984L,62985L,62986L,62987L,62988L,62989L,62990L,62991L,62992L,
86008 62993L,62994L,62995L,62996L,62997L,62998L,62999L,63000L,63001L,63002L,
86009 63003L,63004L,63005L,63006L,63007L,63008L,63009L,63010L,63011L,63012L,
86010 63013L,63014L,63015L,63016L,63017L,63018L,63019L,63020L,63021L,63022L,
86011 63023L,63024L,63025L,63026L,63027L,63028L,63029L,63030L,63031L,63032L,
86012 63033L,63034L,63035L,63036L,63037L,63038L,63039L,63040L,63041L,63042L,
86013 63043L,63044L,63045L,63046L,63047L,63048L,63049L,63050L,63051L,63052L,
86014 63053L,63054L,63055L,63056L,63057L,63058L,63059L,63060L,63061L,63062L,
86015 63063L,63064L,63065L,63066L,63067L,63068L,63069L,63070L,63071L,63072L,
86016 63073L,63074L,63075L,63076L,63077L,63078L,63079L,63080L,63081L,63082L,
86017 63083L,63084L,63085L,63086L,63087L,63088L,63089L,63090L,63091L,63092L,
86018 63093L,63094L,63095L,63096L,63097L,63098L,63099L,63100L,63101L,63102L,
86019 63103L,63104L,63105L,63106L,63107L,63108L,63109L,63110L,63111L,63112L,
86020 63113L,63114L,63115L,63116L,63117L,63118L,63119L,63120L,63121L,63122L,
86021 63123L,63124L,63125L,63126L,63127L,63128L,63129L,63130L,63131L,63132L,
86022 63133L,63134L,63135L,63136L,63137L,63138L,63139L,63140L,63141L,63142L,
86023 63143L,63144L,63145L,63146L,63147L,63148L,63149L,63150L,63151L,63152L,
86024 63153L,63154L,63155L,63156L,63157L,63158L,63159L,63160L,63161L,63162L,
86025 63163L,63164L,63165L,63166L,63167L,63168L,63169L,63170L,63171L,63172L,
86026 63173L,63174L,63175L,63176L,63177L,63178L,63179L,63180L,63181L,63182L,
86027 63183L,63184L,63185L,63186L,63187L,63188L,63189L,63190L,63191L,63192L,
86028 63193L,63194L,63195L,63196L,63197L,63198L,63199L,63200L,63201L,63202L,
86029 63203L,63204L,63205L,63206L,63207L,63208L,63209L,63210L,63211L,63212L,
86030 63213L,63214L,63215L,63216L,63217L,63218L,63219L,63220L,63221L,63222L,
86031 63223L,63224L,63225L,63226L,63227L,63228L,63229L,63230L,63231L,63232L,
86032 63233L,63234L,63235L,63236L,63237L,63238L,63239L,63240L,63241L,63242L,
86033 63243L,63244L,63245L,63246L,63247L,63248L,63249L,63250L,63251L,63252L,
86034 63253L,63254L,63255L,63256L,63257L,63258L,63259L,63260L,63261L,63262L,
86035 63263L,63264L,63265L,63266L,63267L,63268L,63269L,63270L,63271L,63272L,
86036 63273L,63274L,63275L,63276L,63277L,63278L,63279L,63280L,63281L,63282L,
86037 63283L,63284L,63285L,63286L,63287L,63288L,63289L,63290L,63291L,63292L,
86038 63293L,63294L,63295L,63296L,63297L,63298L,63299L,63300L,63301L,63302L,
86039 63303L,63304L,63305L,63306L,63307L,63308L,63309L,63310L,63311L,63312L,
86040 63313L,63314L,63315L,63316L,63317L,63318L,63319L,63320L,63321L,63322L,
86041 63323L,63324L,63325L,63326L,63327L,63328L,63329L,63330L,63331L,63332L,
86042 63333L,63334L,63335L,63336L,63337L,63338L,63339L,63340L,63341L,63342L,
86043 63343L,63344L,63345L,63346L,63347L,63348L,63349L,63350L,63351L,63352L,
86044 63353L,63354L,63355L,63356L,63357L,63358L,63359L,63360L,63361L,63362L,
86045 63363L,63364L,63365L,63366L,63367L,63368L,63369L,63370L,63371L,63372L,
86046 63373L,63374L,63375L,63376L,63377L,63378L,63379L,63380L,63381L,63382L,
86047 63383L,63384L,63385L,63386L,63387L,63388L,63389L,63390L,63391L,63392L,
86048 63393L,63394L,63395L,63396L,63397L,63398L,63399L,63400L,63401L,63402L,
86049 63403L,63404L,63405L,63406L,63407L,63408L,63409L,63410L,63411L,63412L,
86050 63413L,63414L,63415L,63416L,63417L,63418L,63419L,63420L,63421L,63422L,
86051 63423L,63424L,63425L,63426L,63427L,63428L,63429L,63430L,63431L,63432L,
86052 63433L,63434L,63435L,63436L,63437L,63438L,63439L,63440L,63441L,63442L,
86053 63443L,63444L,63445L,63446L,63447L,63448L,63449L,63450L,63451L,63452L,
86054 63453L,63454L,63455L,63456L,63457L,63458L,63459L,63460L,63461L,63462L,
86055 63463L,63464L,63465L,63466L,63467L,63468L,63469L,63470L,63471L,63472L,
86056 63473L,63474L,63475L,63476L,63477L,63478L,63479L,63480L,63481L,63482L,
86057 63483L,63484L,63485L,63486L,63487L,63488L,63489L,63490L,63491L,63492L,
86058 63493L,63494L,63495L,63496L,63497L,63498L,63499L,63500L,63501L,63502L,
86059 63503L,63504L,63505L,63506L,63507L,63508L,63509L,63510L,63511L,63512L,
86060 63513L,63514L,63515L,63516L,63517L,63518L,63519L,63520L,63521L,63522L,
86061 63523L,63524L,63525L,63526L,63527L,63528L,63529L,63530L,63531L,63532L,
86062 63533L,63534L,63535L,63536L,63537L,63538L,63539L,63540L,63541L,63542L,
86063 63543L,63544L,63545L,63546L,63547L,63548L,63549L,63550L,63551L,63552L,
86064 63553L,63554L,63555L,63556L,63557L,63558L,63559L,63560L,63561L,63562L,
86065 63563L,63564L,63565L,63566L,63567L,63568L,63569L,63570L,63571L,63572L,
86066 63573L,63574L,63575L,63576L,63577L,63578L,63579L,63580L,63581L,63582L,
86067 63583L,63584L,63585L,63586L,63587L,63588L,63589L,63590L,63591L,63592L,
86068 63593L,63594L,63595L,63596L,63597L,63598L,63599L,63600L,63601L,63602L,
86069 63603L,63604L,63605L,63606L,63607L,63608L,63609L,63610L,63611L,63612L,
86070 63613L,63614L,63615L,63616L,63617L,63618L,63619L,63620L,63621L,63622L,
86071 63623L,63624L,63625L,63626L,63627L,63628L,63629L,63630L,63631L,63632L,
86072 63633L,63634L,63635L,63636L,63637L,63638L,63639L,63640L,63641L,63642L,
86073 63643L,63644L,63645L,63646L,63647L,63648L,63649L,63650L,63651L,63652L,
86074 63653L,63654L,63655L,63656L,63657L,63658L,63659L,63660L,63661L,63662L,
86075 63663L,63664L,63665L,63666L,63667L,63668L,63669L,63670L,63671L,63672L,
86076 63673L,63674L,63675L,63676L,63677L,63678L,63679L,63680L,63681L,63682L,
86077 63683L,63684L,63685L,63686L,63687L,63688L,63689L,63690L,63691L,63692L,
86078 63693L,63694L,63695L,63696L,63697L,63698L,63699L,63700L,63701L,63702L,
86079 63703L,63704L,63705L,63706L,63707L,63708L,63709L,63710L,63711L,63712L,
86080 63713L,63714L,63715L,63716L,63717L,63718L,63719L,63720L,63721L,63722L,
86081 63723L,63724L,63725L,63726L,63727L,63728L,63729L,63730L,63731L,63732L,
86082 63733L,63734L,63735L,63736L,63737L,63738L,63739L,63740L,63741L,63742L,
86083 63743L,63744L,63745L,63746L,63747L,63748L,63749L,63750L,63751L,63752L,
86084 63753L,63754L,63755L,63756L,63757L,63758L,63759L,63760L,63761L,63762L,
86085 63763L,63764L,63765L,63766L,63767L,63768L,63769L,63770L,63771L,63772L,
86086 63773L,63774L,63775L,63776L,63777L,63778L,63779L,63780L,63781L,63782L,
86087 63783L,63784L,63785L,63786L,63787L,63788L,63789L,63790L,63791L,63792L,
86088 63793L,63794L,63795L,63796L,63797L,63798L,63799L,63800L,63801L,63802L,
86089 63803L,63804L,63805L,63806L,63807L,63808L,63809L,63810L,63811L,63812L,
86090 63813L,63814L,63815L,63816L,63817L,63818L,63819L,63820L,63821L,63822L,
86091 63823L,63824L,63825L,63826L,63827L,63828L,63829L,63830L,63831L,63832L,
86092 63833L,63834L,63835L,63836L,63837L,63838L,63839L,63840L,63841L,63842L,
86093 63843L,63844L,63845L,63846L,63847L,63848L,63849L,63850L,63851L,63852L,
86094 63853L,63854L,63855L,63856L,63857L,63858L,63859L,63860L,63861L,63862L,
86095 63863L,63864L,63865L,63866L,63867L,63868L,63869L,63870L,63871L,63872L,
86096 63873L,63874L,63875L,63876L,63877L,63878L,63879L,63880L,63881L,63882L,
86097 63883L,63884L,63885L,63886L,63887L,63888L,63889L,63890L,63891L,63892L,
86098 63893L,63894L,63895L,63896L,63897L,63898L,63899L,63900L,63901L,63902L,
86099 63903L,63904L,63905L,63906L,63907L,63908L,63909L,63910L,63911L,63912L,
86100 63913L,63914L,63915L,63916L,63917L,63918L,63919L,63920L,63921L,63922L,
86101 63923L,63924L,63925L,63926L,63927L,63928L,63929L,63930L,63931L,63932L,
86102 63933L,63934L,63935L,63936L,63937L,63938L,63939L,63940L,63941L,63942L,
86103 63943L,63944L,63945L,63946L,63947L,63948L,63949L,63950L,63951L,63952L,
86104 63953L,63954L,63955L,63956L,63957L,63958L,63959L,63960L,63961L,63962L,
86105 63963L,63964L,63965L,63966L,63967L,63968L,63969L,63970L,63971L,63972L,
86106 63973L,63974L,63975L,63976L,63977L,63978L,63979L,63980L,63981L,63982L,
86107 63983L,63984L,63985L,63986L,63987L,63988L,63989L,63990L,63991L,63992L,
86108 63993L,63994L,63995L,63996L,63997L,63998L,63999L,64000L,64001L,64002L,
86109 64003L,64004L,64005L,64006L,64007L,64008L,64009L,64010L,64011L,64012L,
86110 64013L,64014L,64015L,64016L,64017L,64018L,64019L,64020L,64021L,64022L,
86111 64023L,64024L,64025L,64026L,64027L,64028L,64029L,64030L,64031L,64032L,
86112 64033L,64034L,64035L,64036L,64037L,64038L,64039L,64040L,64041L,64042L,
86113 64043L,64044L,64045L,64046L,64047L,64048L,64049L,64050L,64051L,64052L,
86114 64053L,64054L,64055L,64056L,64057L,64058L,64059L,64060L,64061L,64062L,
86115 64063L,64064L,64065L,64066L,64067L,64068L,64069L,64070L,64071L,64072L,
86116 64073L,64074L,64075L,64076L,64077L,64078L,64079L,64080L,64081L,64082L,
86117 64083L,64084L,64085L,64086L,64087L,64088L,64089L,64090L,64091L,64092L,
86118 64093L,64094L,64095L,64096L,64097L,64098L,64099L,64100L,64101L,64102L,
86119 64103L,64104L,64105L,64106L,64107L,64108L,64109L,64110L,64111L,64112L,
86120 64113L,64114L,64115L,64116L,64117L,64118L,64119L,64120L,64121L,64122L,
86121 64123L,64124L,64125L,64126L,64127L,64128L,64129L,64130L,64131L,64132L,
86122 64133L,64134L,64135L,64136L,64137L,64138L,64139L,64140L,64141L,64142L,
86123 64143L,64144L,64145L,64146L,64147L,64148L,64149L,64150L,64151L,64152L,
86124 64153L,64154L,64155L,64156L,64157L,64158L,64159L,64160L,64161L,64162L,
86125 64163L,64164L,64165L,64166L,64167L,64168L,64169L,64170L,64171L,64172L,
86126 64173L,64174L,64175L,64176L,64177L,64178L,64179L,64180L,64181L,64182L,
86127 64183L,64184L,64185L,64186L,64187L,64188L,64189L,64190L,64191L,64192L,
86128 64193L,64194L,64195L,64196L,64197L,64198L,64199L,64200L,64201L,64202L,
86129 64203L,64204L,64205L,64206L,64207L,64208L,64209L,64210L,64211L,64212L,
86130 64213L,64214L,64215L,64216L,64217L,64218L,64219L,64220L,64221L,64222L,
86131 64223L,64224L,64225L,64226L,64227L,64228L,64229L,64230L,64231L,64232L,
86132 64233L,64234L,64235L,64236L,64237L,64238L,64239L,64240L,64241L,64242L,
86133 64243L,64244L,64245L,64246L,64247L,64248L,64249L,64250L,64251L,64252L,
86134 64253L,64254L,64255L,64256L,64257L,64258L,64259L,64260L,64261L,64262L,
86135 64263L,64264L,64265L,64266L,64267L,64268L,64269L,64270L,64271L,64272L,
86136 64273L,64274L,64275L,64276L,64277L,64278L,64279L,64280L,64281L,64282L,
86137 64283L,64284L,64285L,64286L,64287L,64288L,64289L,64290L,64291L,64292L,
86138 64293L,64294L,64295L,64296L,64297L,64298L,64299L,64300L,64301L,64302L,
86139 64303L,64304L,64305L,64306L,64307L,64308L,64309L,64310L,64311L,64312L,
86140 64313L,64314L,64315L,64316L,64317L,64318L,64319L,64320L,64321L,64322L,
86141 64323L,64324L,64325L,64326L,64327L,64328L,64329L,64330L,64331L,64332L,
86142 64333L,64334L,64335L,64336L,64337L,64338L,64339L,64340L,64341L,64342L,
86143 64343L,64344L,64345L,64346L,64347L,64348L,64349L,64350L,64351L,64352L,
86144 64353L,64354L,64355L,64356L,64357L,64358L,64359L,64360L,64361L,64362L,
86145 64363L,64364L,64365L,64366L,64367L,64368L,64369L,64370L,64371L,64372L,
86146 64373L,64374L,64375L,64376L,64377L,64378L,64379L,64380L,64381L,64382L,
86147 64383L,64384L,64385L,64386L,64387L,64388L,64389L,64390L,64391L,64392L,
86148 64393L,64394L,64395L,64396L,64397L,64398L,64399L,64400L,64401L,64402L,
86149 64403L,64404L,64405L,64406L,64407L,64408L,64409L,64410L,64411L,64412L,
86150 64413L,64414L,64415L,64416L,64417L,64418L,64419L,64420L,64421L,64422L,
86151 64423L,64424L,64425L,64426L,64427L,64428L,64429L,64430L,64431L,64432L,
86152 64433L,64434L,64435L,64436L,64437L,64438L,64439L,64440L,64441L,64442L,
86153 64443L,64444L,64445L,64446L,64447L,64448L,64449L,64450L,64451L,64452L,
86154 64453L,64454L,64455L,64456L,64457L,64458L,64459L,64460L,64461L,64462L,
86155 64463L,64464L,64465L,64466L,64467L,64468L,64469L,64470L,64471L,64472L,
86156 64473L,64474L,64475L,64476L,64477L,64478L,64479L,64480L,64481L,64482L,
86157 64483L,64484L,64485L,64486L,64487L,64488L,64489L,64490L,64491L,64492L,
86158 64493L,64494L,64495L,64496L,64497L,64498L,64499L,64500L,64501L,64502L,
86159 64503L,64504L,64505L,64506L,64507L,64508L,64509L,64510L,64511L,64512L,
86160 64513L,64514L,64515L,64516L,64517L,64518L,64519L,64520L,64521L,64522L,
86161 64523L,64524L,64525L,64526L,64527L,64528L,64529L,64530L,64531L,64532L,
86162 64533L,64534L,64535L,64536L,64537L,64538L,64539L,64540L,64541L,64542L,
86163 64543L,64544L,64545L,64546L,64547L,64548L,64549L,64550L,64551L,64552L,
86164 64553L,64554L,64555L,64556L,64557L,64558L,64559L,64560L,64561L,64562L,
86165 64563L,64564L,64565L,64566L,64567L,64568L,64569L,64570L,64571L,64572L,
86166 64573L,64574L,64575L,64576L,64577L,64578L,64579L,64580L,64581L,64582L,
86167 64583L,64584L,64585L,64586L,64587L,64588L,64589L,64590L,64591L,64592L,
86168 64593L,64594L,64595L,64596L,64597L,64598L,64599L,64600L,64601L,64602L,
86169 64603L,64604L,64605L,64606L,64607L,64608L,64609L,64610L,64611L,64612L,
86170 64613L,64614L,64615L,64616L,64617L,64618L,64619L,64620L,64621L,64622L,
86171 64623L,64624L,64625L,64626L,64627L,64628L,64629L,64630L,64631L,64632L,
86172 64633L,64634L,64635L,64636L,64637L,64638L,64639L,64640L,64641L,64642L,
86173 64643L,64644L,64645L,64646L,64647L,64648L,64649L,64650L,64651L,64652L,
86174 64653L,64654L,64655L,64656L,64657L,64658L,64659L,64660L,64661L,64662L,
86175 64663L,64664L,64665L,64666L,64667L,64668L,64669L,64670L,64671L,64672L,
86176 64673L,64674L,64675L,64676L,64677L,64678L,64679L,64680L,64681L,64682L,
86177 64683L,64684L,64685L,64686L,64687L,64688L,64689L,64690L,64691L,64692L,
86178 64693L,64694L,64695L,64696L,64697L,64698L,64699L,64700L,64701L,64702L,
86179 64703L,64704L,64705L,64706L,64707L,64708L,64709L,64710L,64711L,64712L,
86180 64713L,64714L,64715L,64716L,64717L,64718L,64719L,64720L,64721L,64722L,
86181 64723L,64724L,64725L,64726L,64727L,64728L,64729L,64730L,64731L,64732L,
86182 64733L,64734L,64735L,64736L,64737L,64738L,64739L,64740L,64741L,64742L,
86183 64743L,64744L,64745L,64746L,64747L,64748L,64749L,64750L,64751L,64752L,
86184 64753L,64754L,64755L,64756L,64757L,64758L,64759L,64760L,64761L,64762L,
86185 64763L,64764L,64765L,64766L,64767L,64768L,64769L,64770L,64771L,64772L,
86186 64773L,64774L,64775L,64776L,64777L,64778L,64779L,64780L,64781L,64782L,
86187 64783L,64784L,64785L,64786L,64787L,64788L,64789L,64790L,64791L,64792L,
86188 64793L,64794L,64795L,64796L,64797L,64798L,64799L,64800L,64801L,64802L,
86189 64803L,64804L,64805L,64806L,64807L,64808L,64809L,64810L,64811L,64812L,
86190 64813L,64814L,64815L,64816L,64817L,64818L,64819L,64820L,64821L,64822L,
86191 64823L,64824L,64825L,64826L,64827L,64828L,64829L,64830L,64831L,64832L,
86192 64833L,64834L,64835L,64836L,64837L,64838L,64839L,64840L,64841L,64842L,
86193 64843L,64844L,64845L,64846L,64847L,64848L,64849L,64850L,64851L,64852L,
86194 64853L,64854L,64855L,64856L,64857L,64858L,64859L,64860L,64861L,64862L,
86195 64863L,64864L,64865L,64866L,64867L,64868L,64869L,64870L,64871L,64872L,
86196 64873L,64874L,64875L,64876L,64877L,64878L,64879L,64880L,64881L,64882L,
86197 64883L,64884L,64885L,64886L,64887L,64888L,64889L,64890L,64891L,64892L,
86198 64893L,64894L,64895L,64896L,64897L,64898L,64899L,64900L,64901L,64902L,
86199 64903L,64904L,64905L,64906L,64907L,64908L,64909L,64910L,64911L,64912L,
86200 64913L,64914L,64915L,64916L,64917L,64918L,64919L,64920L,64921L,64922L,
86201 64923L,64924L,64925L,64926L,64927L,64928L,64929L,64930L,64931L,64932L,
86202 64933L,64934L,64935L,64936L,64937L,64938L,64939L,64940L,64941L,64942L,
86203 64943L,64944L,64945L,64946L,64947L,64948L,64949L,64950L,64951L,64952L,
86204 64953L,64954L,64955L,64956L,64957L,64958L,64959L,64960L,64961L,64962L,
86205 64963L,64964L,64965L,64966L,64967L,64968L,64969L,64970L,64971L,64972L,
86206 64973L,64974L,64975L,64976L,64977L,64978L,64979L,64980L,64981L,64982L,
86207 64983L,64984L,64985L,64986L,64987L,64988L,64989L,64990L,64991L,64992L,
86208 64993L,64994L,64995L,64996L,64997L,64998L,64999L,65000L,65001L,65002L,
86209 65003L,65004L,65005L,65006L,65007L,65008L,65009L,65010L,65011L,65012L,
86210 65013L,65014L,65015L,65016L,65017L,65018L,65019L,65020L,65021L,65022L,
86211 65023L,65024L,65025L,65026L,65027L,65028L,65029L,65030L,65031L,65032L,
86212 65033L,65034L,65035L,65036L,65037L,65038L,65039L,65040L,65041L,65042L,
86213 65043L,65044L,65045L,65046L,65047L,65048L,65049L,65050L,65051L,65052L,
86214 65053L,65054L,65055L,65056L,65057L,65058L,65059L,65060L,65061L,65062L,
86215 65063L,65064L,65065L,65066L,65067L,65068L,65069L,65070L,65071L,65072L,
86216 65073L,65074L,65075L,65076L,65077L,65078L,65079L,65080L,65081L,65082L,
86217 65083L,65084L,65085L,65086L,65087L,65088L,65089L,65090L,65091L,65092L,
86218 65093L,65094L,65095L,65096L,65097L,65098L,65099L,65100L,65101L,65102L,
86219 65103L,65104L,65105L,65106L,65107L,65108L,65109L,65110L,65111L,65112L,
86220 65113L,65114L,65115L,65116L,65117L,65118L,65119L,65120L,65121L,65122L,
86221 65123L,65124L,65125L,65126L,65127L,65128L,65129L,65130L,65131L,65132L,
86222 65133L,65134L,65135L,65136L,65137L,65138L,65139L,65140L,65141L,65142L,
86223 65143L,65144L,65145L,65146L,65147L,65148L,65149L,65150L,65151L,65152L,
86224 65153L,65154L,65155L,65156L,65157L,65158L,65159L,65160L,65161L,65162L,
86225 65163L,65164L,65165L,65166L,65167L,65168L,65169L,65170L,65171L,65172L,
86226 65173L,65174L,65175L,65176L,65177L,65178L,65179L,65180L,65181L,65182L,
86227 65183L,65184L,65185L,65186L,65187L,65188L,65189L,65190L,65191L,65192L,
86228 65193L,65194L,65195L,65196L,65197L,65198L,65199L,65200L,65201L,65202L,
86229 65203L,65204L,65205L,65206L,65207L,65208L,65209L,65210L,65211L,65212L,
86230 65213L,65214L,65215L,65216L,65217L,65218L,65219L,65220L,65221L,65222L,
86231 65223L,65224L,65225L,65226L,65227L,65228L,65229L,65230L,65231L,65232L,
86232 65233L,65234L,65235L,65236L,65237L,65238L,65239L,65240L,65241L,65242L,
86233 65243L,65244L,65245L,65246L,65247L,65248L,65249L,65250L,65251L,65252L,
86234 65253L,65254L,65255L,65256L,65257L,65258L,65259L,65260L,65261L,65262L,
86235 65263L,65264L,65265L,65266L,65267L,65268L,65269L,65270L,65271L,65272L,
86236 65273L,65274L,65275L,65276L,65277L,65278L,65279L,65280L,65281L,65282L,
86237 65283L,65284L,65285L,65286L,65287L,65288L,65289L,65290L,65291L,65292L,
86238 65293L,65294L,65295L,65296L,65297L,65298L,65299L,65300L,65301L,65302L,
86239 65303L,65304L,65305L,65306L,65307L,65308L,65309L,65310L,65311L,65312L,
86240 65313L,65314L,65315L,65316L,65317L,65318L,65319L,65320L,65321L,65322L,
86241 65323L,65324L,65325L,65326L,65327L,65328L,65329L,65330L,65331L,65332L,
86242 65333L,65334L,65335L,65336L,65337L,65338L,65339L,65340L,65341L,65342L,
86243 65343L,65344L,65313L,65314L,65315L,65316L,65317L,65318L,65319L,65320L,
86244 65321L,65322L,65323L,65324L,65325L,65326L,65327L,65328L,65329L,65330L,
86245 65331L,65332L,65333L,65334L,65335L,65336L,65337L,65338L,65371L,65372L,
86246 65373L,65374L,65375L,65376L,65377L,65378L,65379L,65380L,65381L,65382L,
86247 65383L,65384L,65385L,65386L,65387L,65388L,65389L,65390L,65391L,65392L,
86248 65393L,65394L,65395L,65396L,65397L,65398L,65399L,65400L,65401L,65402L,
86249 65403L,65404L,65405L,65406L,65407L,65408L,65409L,65410L,65411L,65412L,
86250 65413L,65414L,65415L,65416L,65417L,65418L,65419L,65420L,65421L,65422L,
86251 65423L,65424L,65425L,65426L,65427L,65428L,65429L,65430L,65431L,65432L,
86252 65433L,65434L,65435L,65436L,65437L,65438L,65439L,65440L,65441L,65442L,
86253 65443L,65444L,65445L,65446L,65447L,65448L,65449L,65450L,65451L,65452L,
86254 65453L,65454L,65455L,65456L,65457L,65458L,65459L,65460L,65461L,65462L,
86255 65463L,65464L,65465L,65466L,65467L,65468L,65469L,65470L,65471L,65472L,
86256 65473L,65474L,65475L,65476L,65477L,65478L,65479L,65480L,65481L,65482L,
86257 65483L,65484L,65485L,65486L,65487L,65488L,65489L,65490L,65491L,65492L,
86258 65493L,65494L,65495L,65496L,65497L,65498L,65499L,65500L,65501L,65502L,
86259 65503L,65504L,65505L,65506L,65507L,65508L,65509L,65510L,65511L,65512L,
86260 65513L,65514L,65515L,65516L,65517L,65518L,65519L,65520L,65521L,65522L,
86261 65523L,65524L,65525L,65526L,65527L,65528L,65529L,65530L,65531L,65532L,
86262 65533L,65534L,65535L,
86263 };
86264 #endif
86265 /*
86266  *  Bitstream decoder.
86267  */
86268 
86269 /* include removed: duk_internal.h */
86270 
86271 /* Decode 'bits' bits from the input stream (bits must be 1...24).
86272  * When reading past bitstream end, zeroes are shifted in.  The result
86273  * is signed to match duk_bd_decode_flagged.
86274  */
86275 DUK_INTERNAL duk_int32_t duk_bd_decode(duk_bitdecoder_ctx *ctx, duk_small_int_t bits) {
86276 	duk_small_int_t shift;
86277 	duk_uint32_t mask;
86278 	duk_uint32_t tmp;
86279 
86280 	/* Note: cannot read more than 24 bits without possibly shifting top bits out.
86281 	 * Fixable, but adds complexity.
86282 	 */
86283 	DUK_ASSERT(bits >= 1 && bits <= 24);
86284 
86285 	while (ctx->currbits < bits) {
86286 #if 0
86287 		DUK_DDD(DUK_DDDPRINT("decode_bits: shift more data (bits=%ld, currbits=%ld)",
86288 		                     (long) bits, (long) ctx->currbits));
86289 #endif
86290 		ctx->currval <<= 8;
86291 		if (ctx->offset < ctx->length) {
86292 			/* If ctx->offset >= ctx->length, we "shift zeroes in"
86293 			 * instead of croaking.
86294 			 */
86295 			ctx->currval |= ctx->data[ctx->offset++];
86296 		}
86297 		ctx->currbits += 8;
86298 	}
86299 #if 0
86300 	DUK_DDD(DUK_DDDPRINT("decode_bits: bits=%ld, currbits=%ld, currval=0x%08lx",
86301 	                     (long) bits, (long) ctx->currbits, (unsigned long) ctx->currval));
86302 #endif
86303 
86304 	/* Extract 'top' bits of currval; note that the extracted bits do not need
86305 	 * to be cleared, we just ignore them on next round.
86306 	 */
86307 	shift = ctx->currbits - bits;
86308 	mask = (1 << bits) - 1;
86309 	tmp = (ctx->currval >> shift) & mask;
86310 	ctx->currbits = shift;  /* remaining */
86311 
86312 #if 0
86313 	DUK_DDD(DUK_DDDPRINT("decode_bits: %ld bits -> 0x%08lx (%ld), currbits=%ld, currval=0x%08lx",
86314 	                     (long) bits, (unsigned long) tmp, (long) tmp, (long) ctx->currbits, (unsigned long) ctx->currval));
86315 #endif
86316 
86317 	return tmp;
86318 }
86319 
86320 DUK_INTERNAL duk_small_int_t duk_bd_decode_flag(duk_bitdecoder_ctx *ctx) {
86321 	return (duk_small_int_t) duk_bd_decode(ctx, 1);
86322 }
86323 
86324 /* Decode a one-bit flag, and if set, decode a value of 'bits', otherwise return
86325  * default value.  Return value is signed so that negative marker value can be
86326  * used by caller as a "not present" value.
86327  */
86328 DUK_INTERNAL duk_int32_t duk_bd_decode_flagged(duk_bitdecoder_ctx *ctx, duk_small_int_t bits, duk_int32_t def_value) {
86329 	if (duk_bd_decode_flag(ctx)) {
86330 		return (duk_int32_t) duk_bd_decode(ctx, bits);
86331 	} else {
86332 		return def_value;
86333 	}
86334 }
86335 /*
86336  *  Bitstream encoder.
86337  */
86338 
86339 /* include removed: duk_internal.h */
86340 
86341 DUK_INTERNAL void duk_be_encode(duk_bitencoder_ctx *ctx, duk_uint32_t data, duk_small_int_t bits) {
86342 	duk_uint8_t tmp;
86343 
86344 	DUK_ASSERT(ctx != NULL);
86345 	DUK_ASSERT(ctx->currbits < 8);
86346 
86347 	/* This limitation would be fixable but adds unnecessary complexity. */
86348 	DUK_ASSERT(bits >= 1 && bits <= 24);
86349 
86350 	ctx->currval = (ctx->currval << bits) | data;
86351 	ctx->currbits += bits;
86352 
86353 	while (ctx->currbits >= 8) {
86354 		if (ctx->offset < ctx->length) {
86355 			tmp = (duk_uint8_t) ((ctx->currval >> (ctx->currbits - 8)) & 0xff);
86356 			ctx->data[ctx->offset++] = tmp;
86357 		} else {
86358 			/* If buffer has been exhausted, truncate bitstream */
86359 			ctx->truncated = 1;
86360 		}
86361 
86362 		ctx->currbits -= 8;
86363 	}
86364 }
86365 
86366 DUK_INTERNAL void duk_be_finish(duk_bitencoder_ctx *ctx) {
86367 	duk_small_int_t npad;
86368 
86369 	DUK_ASSERT(ctx != NULL);
86370 	DUK_ASSERT(ctx->currbits < 8);
86371 
86372 	npad = (duk_small_int_t) (8 - ctx->currbits);
86373 	if (npad > 0) {
86374 		duk_be_encode(ctx, 0, npad);
86375 	}
86376 	DUK_ASSERT(ctx->currbits == 0);
86377 }
86378 /*
86379  *  Fast buffer writer with spare management.
86380  */
86381 
86382 /* include removed: duk_internal.h */
86383 
86384 /*
86385  *  Macro support functions (use only macros in calling code)
86386  */
86387 
86388 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) {
86389 	duk_uint8_t *p;
86390 
86391 	DUK_ASSERT(thr != NULL);
86392 	DUK_ASSERT(bw_ctx != NULL);
86393 	DUK_UNREF(thr);
86394 
86395 	p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, bw_ctx->buf);
86396 	DUK_ASSERT(p != NULL || (DUK_HBUFFER_DYNAMIC_GET_SIZE(bw_ctx->buf) == 0 && curr_offset == 0 && new_length == 0));
86397 	bw_ctx->p = p + curr_offset;
86398 	bw_ctx->p_base = p;
86399 	bw_ctx->p_limit = p + new_length;
86400 }
86401 
86402 DUK_INTERNAL void duk_bw_init(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_hbuffer_dynamic *h_buf) {
86403 
86404 	DUK_ASSERT(thr != NULL);
86405 	DUK_ASSERT(bw_ctx != NULL);
86406 	DUK_ASSERT(h_buf != NULL);
86407 	DUK_UNREF(thr);
86408 
86409 	bw_ctx->buf = h_buf;
86410 	duk__bw_update_ptrs(thr, bw_ctx, 0, DUK_HBUFFER_DYNAMIC_GET_SIZE(h_buf));
86411 }
86412 
86413 DUK_INTERNAL void duk_bw_init_pushbuf(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t buf_size) {
86414 	duk_context *ctx;
86415 
86416 	DUK_ASSERT(thr != NULL);
86417 	DUK_ASSERT(bw_ctx != NULL);
86418 	ctx = (duk_context *) thr;
86419 
86420 	(void) duk_push_dynamic_buffer(ctx, buf_size);
86421 	bw_ctx->buf = (duk_hbuffer_dynamic *) duk_get_hbuffer(ctx, -1);
86422 	duk__bw_update_ptrs(thr, bw_ctx, 0, buf_size);
86423 }
86424 
86425 /* Resize target buffer for requested size.  Called by the macro only when the
86426  * fast path test (= there is space) fails.
86427  */
86428 DUK_INTERNAL duk_uint8_t *duk_bw_resize(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t sz) {
86429 	duk_size_t curr_off;
86430 	duk_size_t add_sz;
86431 	duk_size_t new_sz;
86432 
86433 	DUK_ASSERT(thr != NULL);
86434 	DUK_ASSERT(bw_ctx != NULL);
86435 
86436 	/* We could do this operation without caller updating bw_ctx->ptr,
86437 	 * but by writing it back here we can share code better.
86438 	 */
86439 
86440 	curr_off = (duk_size_t) (bw_ctx->p - bw_ctx->p_base);
86441 	add_sz = (curr_off >> DUK_BW_SPARE_SHIFT) + DUK_BW_SPARE_ADD;
86442 	new_sz = curr_off + sz + add_sz;
86443 	if (new_sz < curr_off) {
86444 		/* overflow */
86445 		DUK_ERROR_RANGE(thr, DUK_STR_BUFFER_TOO_LONG);
86446 		return NULL;  /* not reachable */
86447 	}
86448 #if 0  /* for manual torture testing: tight allocation, useful with valgrind */
86449 	new_sz = curr_off + sz;
86450 #endif
86451 
86452 	/* This is important to ensure dynamic buffer data pointer is not
86453 	 * NULL (which is possible if buffer size is zero), which in turn
86454 	 * causes portability issues with e.g. memmove() and memcpy().
86455 	 */
86456 	DUK_ASSERT(new_sz >= 1);
86457 
86458 	DUK_DD(DUK_DDPRINT("resize bufferwriter from %ld to %ld (add_sz=%ld)", (long) curr_off, (long) new_sz, (long) add_sz));
86459 
86460 	duk_hbuffer_resize(thr, bw_ctx->buf, new_sz);
86461 	duk__bw_update_ptrs(thr, bw_ctx, curr_off, new_sz);
86462 	return bw_ctx->p;
86463 }
86464 
86465 /* Make buffer compact, matching current written size. */
86466 DUK_INTERNAL void duk_bw_compact(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx) {
86467 	duk_size_t len;
86468 
86469 	DUK_ASSERT(thr != NULL);
86470 	DUK_ASSERT(bw_ctx != NULL);
86471 	DUK_UNREF(thr);
86472 
86473 	len = (duk_size_t) (bw_ctx->p - bw_ctx->p_base);
86474 	duk_hbuffer_resize(thr, bw_ctx->buf, len);
86475 	duk__bw_update_ptrs(thr, bw_ctx, len, len);
86476 }
86477 
86478 DUK_INTERNAL void duk_bw_write_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t src_off, duk_size_t len) {
86479 	duk_uint8_t *p_base;
86480 
86481 	DUK_ASSERT(thr != NULL);
86482 	DUK_ASSERT(bw != NULL);
86483 	DUK_ASSERT(src_off <= DUK_BW_GET_SIZE(thr, bw));
86484 	DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
86485 	DUK_ASSERT(src_off + len <= DUK_BW_GET_SIZE(thr, bw));
86486 	DUK_UNREF(thr);
86487 
86488 	p_base = bw->p_base;
86489 	DUK_MEMCPY((void *) bw->p,
86490 	           (const void *) (p_base + src_off),
86491 	           (size_t) len);
86492 	bw->p += len;
86493 }
86494 
86495 DUK_INTERNAL void duk_bw_write_ensure_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t src_off, duk_size_t len) {
86496 	DUK_ASSERT(thr != NULL);
86497 	DUK_ASSERT(bw != NULL);
86498 	DUK_ASSERT(src_off <= DUK_BW_GET_SIZE(thr, bw));
86499 	DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
86500 	DUK_ASSERT(src_off + len <= DUK_BW_GET_SIZE(thr, bw));
86501 	DUK_UNREF(thr);
86502 
86503 	DUK_BW_ENSURE(thr, bw, len);
86504 	duk_bw_write_raw_slice(thr, bw, src_off, len);
86505 }
86506 
86507 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) {
86508 	duk_uint8_t *p_base;
86509 	duk_size_t buf_sz, move_sz;
86510 
86511 	DUK_ASSERT(thr != NULL);
86512 	DUK_ASSERT(bw != NULL);
86513 	DUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw));
86514 	DUK_ASSERT(buf != NULL);
86515 	DUK_UNREF(thr);
86516 
86517 	p_base = bw->p_base;
86518 	buf_sz = bw->p - p_base;
86519 	move_sz = buf_sz - dst_off;
86520 
86521 	DUK_ASSERT(p_base != NULL);  /* buffer size is >= 1 */
86522 	DUK_MEMMOVE((void *) (p_base + dst_off + len),
86523 	            (const void *) (p_base + dst_off),
86524 	            (size_t) move_sz);
86525 	DUK_MEMCPY((void *) (p_base + dst_off),
86526 	           (const void *) buf,
86527 	           (size_t) len);
86528 	bw->p += len;
86529 }
86530 
86531 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) {
86532 	DUK_ASSERT(thr != NULL);
86533 	DUK_ASSERT(bw != NULL);
86534 	DUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw));
86535 	DUK_ASSERT(buf != NULL);
86536 	DUK_UNREF(thr);
86537 
86538 	DUK_BW_ENSURE(thr, bw, len);
86539 	duk_bw_insert_raw_bytes(thr, bw, dst_off, buf, len);
86540 }
86541 
86542 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) {
86543 	duk_uint8_t *p_base;
86544 	duk_size_t buf_sz, move_sz;
86545 
86546 	DUK_ASSERT(thr != NULL);
86547 	DUK_ASSERT(bw != NULL);
86548 	DUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw));
86549 	DUK_ASSERT(src_off <= DUK_BW_GET_SIZE(thr, bw));
86550 	DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
86551 	DUK_ASSERT(src_off + len <= DUK_BW_GET_SIZE(thr, bw));
86552 	DUK_UNREF(thr);
86553 
86554 	p_base = bw->p_base;
86555 
86556 	/* Don't support "straddled" source now. */
86557 	DUK_ASSERT(dst_off <= src_off || dst_off >= src_off + len);
86558 
86559 	if (dst_off <= src_off) {
86560 		/* Target is before source.  Source offset is expressed as
86561 		 * a "before change" offset.  Account for the memmove.
86562 		 */
86563 		src_off += len;
86564 	}
86565 
86566 	buf_sz = bw->p - p_base;
86567 	move_sz = buf_sz - dst_off;
86568 
86569 	DUK_ASSERT(p_base != NULL);  /* buffer size is >= 1 */
86570 	DUK_MEMMOVE((void *) (p_base + dst_off + len),
86571 	            (const void *) (p_base + dst_off),
86572 	            (size_t) move_sz);
86573 	DUK_MEMCPY((void *) (p_base + dst_off),
86574 	           (const void *) (p_base + src_off),
86575 	           (size_t) len);
86576 	bw->p += len;
86577 }
86578 
86579 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) {
86580 	DUK_ASSERT(thr != NULL);
86581 	DUK_ASSERT(bw != NULL);
86582 	DUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw));
86583 	DUK_ASSERT(src_off <= DUK_BW_GET_SIZE(thr, bw));
86584 	DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
86585 	DUK_ASSERT(src_off + len <= DUK_BW_GET_SIZE(thr, bw));
86586 	DUK_UNREF(thr);
86587 
86588 	/* Don't support "straddled" source now. */
86589 	DUK_ASSERT(dst_off <= src_off || dst_off >= src_off + len);
86590 
86591 	DUK_BW_ENSURE(thr, bw, len);
86592 	duk_bw_insert_raw_slice(thr, bw, dst_off, src_off, len);
86593 }
86594 
86595 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) {
86596 	duk_uint8_t *p_base, *p_dst, *p_src;
86597 	duk_size_t buf_sz, move_sz;
86598 
86599 	DUK_ASSERT(thr != NULL);
86600 	DUK_ASSERT(bw != NULL);
86601 	DUK_ASSERT(off <= DUK_BW_GET_SIZE(thr, bw));
86602 	DUK_UNREF(thr);
86603 
86604 	p_base = bw->p_base;
86605 	buf_sz = bw->p - p_base;
86606 	move_sz = buf_sz - off;
86607 	p_dst = p_base + off + len;
86608 	p_src = p_base + off;
86609 	DUK_MEMMOVE((void *) p_dst, (const void *) p_src, (size_t) move_sz);
86610 	return p_src;  /* point to start of 'reserved area' */
86611 }
86612 
86613 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) {
86614 	DUK_ASSERT(thr != NULL);
86615 	DUK_ASSERT(bw != NULL);
86616 	DUK_ASSERT(off <= DUK_BW_GET_SIZE(thr, bw));
86617 	DUK_UNREF(thr);
86618 
86619 	DUK_BW_ENSURE(thr, bw, len);
86620 	return duk_bw_insert_raw_area(thr, bw, off, len);
86621 }
86622 
86623 DUK_INTERNAL void duk_bw_remove_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len) {
86624 	duk_size_t move_sz;
86625 
86626 	duk_uint8_t *p_base;
86627 	duk_uint8_t *p_src;
86628 	duk_uint8_t *p_dst;
86629 
86630 	DUK_ASSERT(thr != NULL);
86631 	DUK_ASSERT(bw != NULL);
86632 	DUK_ASSERT(off <= DUK_BW_GET_SIZE(thr, bw));
86633 	DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
86634 	DUK_ASSERT(off + len <= DUK_BW_GET_SIZE(thr, bw));
86635 	DUK_UNREF(thr);
86636 
86637 	p_base = bw->p_base;
86638 	p_dst = p_base + off;
86639 	p_src = p_dst + len;
86640 	move_sz = (duk_size_t) (bw->p - p_src);
86641 	DUK_MEMMOVE((void *) p_dst,
86642 	            (const void *) p_src,
86643 	            (size_t) move_sz);
86644 	bw->p -= len;
86645 }
86646 
86647 /*
86648  *  Macro support functions for reading/writing raw data.
86649  *
86650  *  These are done using mempcy to ensure they're valid even for unaligned
86651  *  reads/writes on platforms where alignment counts.  On x86 at least gcc
86652  *  is able to compile these into a bswap+mov.  "Always inline" is used to
86653  *  ensure these macros compile to minimal code.
86654  *
86655  *  Not really bufwriter related, but currently used together.
86656  */
86657 
86658 DUK_INTERNAL DUK_ALWAYS_INLINE duk_uint16_t duk_raw_read_u16_be(duk_uint8_t **p) {
86659 	union {
86660 		duk_uint8_t b[2];
86661 		duk_uint16_t x;
86662 	} u;
86663 
86664 	DUK_MEMCPY((void *) u.b, (const void *) (*p), (size_t) 2);
86665 	u.x = DUK_NTOH16(u.x);
86666 	*p += 2;
86667 	return u.x;
86668 }
86669 
86670 DUK_INTERNAL DUK_ALWAYS_INLINE duk_uint32_t duk_raw_read_u32_be(duk_uint8_t **p) {
86671 	union {
86672 		duk_uint8_t b[4];
86673 		duk_uint32_t x;
86674 	} u;
86675 
86676 	DUK_MEMCPY((void *) u.b, (const void *) (*p), (size_t) 4);
86677 	u.x = DUK_NTOH32(u.x);
86678 	*p += 4;
86679 	return u.x;
86680 }
86681 
86682 DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_raw_read_double_be(duk_uint8_t **p) {
86683 	duk_double_union du;
86684 	union {
86685 		duk_uint8_t b[4];
86686 		duk_uint32_t x;
86687 	} u;
86688 
86689 	DUK_MEMCPY((void *) u.b, (const void *) (*p), (size_t) 4);
86690 	u.x = DUK_NTOH32(u.x);
86691 	du.ui[DUK_DBL_IDX_UI0] = u.x;
86692 	DUK_MEMCPY((void *) u.b, (const void *) (*p + 4), (size_t) 4);
86693 	u.x = DUK_NTOH32(u.x);
86694 	du.ui[DUK_DBL_IDX_UI1] = u.x;
86695 	*p += 8;
86696 
86697 	return du.d;
86698 }
86699 
86700 DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_u16_be(duk_uint8_t **p, duk_uint16_t val) {
86701 	union {
86702 		duk_uint8_t b[2];
86703 		duk_uint16_t x;
86704 	} u;
86705 
86706 	u.x = DUK_HTON16(val);
86707 	DUK_MEMCPY((void *) (*p), (const void *) u.b, (size_t) 2);
86708 	*p += 2;
86709 }
86710 
86711 DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_u32_be(duk_uint8_t **p, duk_uint32_t val) {
86712 	union {
86713 		duk_uint8_t b[4];
86714 		duk_uint32_t x;
86715 	} u;
86716 
86717 	u.x = DUK_HTON32(val);
86718 	DUK_MEMCPY((void *) (*p), (const void *) u.b, (size_t) 4);
86719 	*p += 4;
86720 }
86721 
86722 DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_double_be(duk_uint8_t **p, duk_double_t val) {
86723 	duk_double_union du;
86724 	union {
86725 		duk_uint8_t b[4];
86726 		duk_uint32_t x;
86727 	} u;
86728 
86729 	du.d = val;
86730 	u.x = du.ui[DUK_DBL_IDX_UI0];
86731 	u.x = DUK_HTON32(u.x);
86732 	DUK_MEMCPY((void *) (*p), (const void *) u.b, (size_t) 4);
86733 	u.x = du.ui[DUK_DBL_IDX_UI1];
86734 	u.x = DUK_HTON32(u.x);
86735 	DUK_MEMCPY((void *) (*p + 4), (const void *) u.b, (size_t) 4);
86736 	*p += 8;
86737 }
86738 /*
86739  *  Hash function duk_util_hashbytes().
86740  *
86741  *  Currently, 32-bit MurmurHash2.
86742  *
86743  *  Don't rely on specific hash values; hash function may be endianness
86744  *  dependent, for instance.
86745  */
86746 
86747 /* include removed: duk_internal.h */
86748 
86749 #if defined(DUK_USE_STRHASH_DENSE)
86750 /* 'magic' constants for Murmurhash2 */
86751 #define DUK__MAGIC_M  ((duk_uint32_t) 0x5bd1e995UL)
86752 #define DUK__MAGIC_R  24
86753 
86754 DUK_INTERNAL duk_uint32_t duk_util_hashbytes(const duk_uint8_t *data, duk_size_t len, duk_uint32_t seed) {
86755 	duk_uint32_t h = seed ^ ((duk_uint32_t) len);
86756 
86757 	while (len >= 4) {
86758 		/* Portability workaround is required for platforms without
86759 		 * unaligned access.  The replacement code emulates little
86760 		 * endian access even on big endian architectures, which is
86761 		 * OK as long as it is consistent for a build.
86762 		 */
86763 #ifdef DUK_USE_HASHBYTES_UNALIGNED_U32_ACCESS
86764 		duk_uint32_t k = *((const duk_uint32_t *) (const void *) data);
86765 #else
86766 		duk_uint32_t k = ((duk_uint32_t) data[0]) |
86767 		                 (((duk_uint32_t) data[1]) << 8) |
86768 		                 (((duk_uint32_t) data[2]) << 16) |
86769 		                 (((duk_uint32_t) data[3]) << 24);
86770 #endif
86771 
86772 		k *= DUK__MAGIC_M;
86773 		k ^= k >> DUK__MAGIC_R;
86774 		k *= DUK__MAGIC_M;
86775 		h *= DUK__MAGIC_M;
86776 		h ^= k;
86777 		data += 4;
86778 		len -= 4;
86779 	}
86780 
86781 	switch (len) {
86782 	case 3: h ^= data[2] << 16;
86783 	case 2: h ^= data[1] << 8;
86784 	case 1: h ^= data[0];
86785 	        h *= DUK__MAGIC_M;
86786         }
86787 
86788 	h ^= h >> 13;
86789 	h *= DUK__MAGIC_M;
86790 	h ^= h >> 15;
86791 
86792 	return h;
86793 }
86794 #endif  /* DUK_USE_STRHASH_DENSE */
86795 /*
86796  *  A tiny random number generator.
86797  *
86798  *  Currently used for Math.random().
86799  *
86800  *  http://www.woodmann.com/forum/archive/index.php/t-3100.html
86801  */
86802 
86803 /* include removed: duk_internal.h */
86804 
86805 #define DUK__UPDATE_RND(rnd) do { \
86806 		(rnd) += ((rnd) * (rnd)) | 0x05; \
86807 		(rnd) = ((rnd) & 0xffffffffU);       /* if duk_uint32_t is exactly 32 bits, this is a NOP */ \
86808 	} while (0)
86809 
86810 #define DUK__RND_BIT(rnd)  ((rnd) >> 31)  /* only use the highest bit */
86811 
86812 DUK_INTERNAL duk_uint32_t duk_util_tinyrandom_get_bits(duk_hthread *thr, duk_small_int_t n) {
86813 	duk_small_int_t i;
86814 	duk_uint32_t res = 0;
86815 	duk_uint32_t rnd;
86816 
86817 	rnd = thr->heap->rnd_state;
86818 
86819 	for (i = 0; i < n; i++) {
86820 		DUK__UPDATE_RND(rnd);
86821 		res <<= 1;
86822 		res += DUK__RND_BIT(rnd);
86823 	}
86824 
86825 	thr->heap->rnd_state = rnd;
86826 
86827 	return res;
86828 }
86829 
86830 DUK_INTERNAL duk_double_t duk_util_tinyrandom_get_double(duk_hthread *thr) {
86831 	duk_double_t t;
86832 	duk_small_int_t n;
86833 	duk_uint32_t rnd;
86834 
86835 	/*
86836 	 *  XXX: could make this a lot faster if we create the double memory
86837 	 *  representation directly.  Feasible easily (must be uniform random).
86838 	 */
86839 
86840 	rnd = thr->heap->rnd_state;
86841 
86842 	n = 53;  /* enough to cover the whole mantissa */
86843 	t = 0.0;
86844 
86845 	do {
86846 		DUK__UPDATE_RND(rnd);
86847 		t += DUK__RND_BIT(rnd);
86848 		t /= 2.0;
86849 	} while (--n);
86850 
86851 	thr->heap->rnd_state = rnd;
86852 
86853 	DUK_ASSERT(t >= (duk_double_t) 0.0);
86854 	DUK_ASSERT(t < (duk_double_t) 1.0);
86855 
86856 	return t;
86857 }
86858