all repos — litestore @ 20f1efa1f29fed91d9cbd13872537fb50eae5892

A minimalist nosql document store.

src/litestorepkg/vendor/duktape/duktape.c

 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
 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
 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
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176
 177
 178
 179
 180
 181
 182
 183
 184
 185
 186
 187
 188
 189
 190
 191
 192
 193
 194
 195
 196
 197
 198
 199
 200
 201
 202
 203
 204
 205
 206
 207
 208
 209
 210
 211
 212
 213
 214
 215
 216
 217
 218
 219
 220
 221
 222
 223
 224
 225
 226
 227
 228
 229
 230
 231
 232
 233
 234
 235
 236
 237
 238
 239
 240
 241
 242
 243
 244
 245
 246
 247
 248
 249
 250
 251
 252
 253
 254
 255
 256
 257
 258
 259
 260
 261
 262
 263
 264
 265
 266
 267
 268
 269
 270
 271
 272
 273
 274
 275
 276
 277
 278
 279
 280
 281
 282
 283
 284
 285
 286
 287
 288
 289
 290
 291
 292
 293
 294
 295
 296
 297
 298
 299
 300
 301
 302
 303
 304
 305
 306
 307
 308
 309
 310
 311
 312
 313
 314
 315
 316
 317
 318
 319
 320
 321
 322
 323
 324
 325
 326
 327
 328
 329
 330
 331
 332
 333
 334
 335
 336
 337
 338
 339
 340
 341
 342
 343
 344
 345
 346
 347
 348
 349
 350
 351
 352
 353
 354
 355
 356
 357
 358
 359
 360
 361
 362
 363
 364
 365
 366
 367
 368
 369
 370
 371
 372
 373
 374
 375
 376
 377
 378
 379
 380
 381
 382
 383
 384
 385
 386
 387
 388
 389
 390
 391
 392
 393
 394
 395
 396
 397
 398
 399
 400
 401
 402
 403
 404
 405
 406
 407
 408
 409
 410
 411
 412
 413
 414
 415
 416
 417
 418
 419
 420
 421
 422
 423
 424
 425
 426
 427
 428
 429
 430
 431
 432
 433
 434
 435
 436
 437
 438
 439
 440
 441
 442
 443
 444
 445
 446
 447
 448
 449
 450
 451
 452
 453
 454
 455
 456
 457
 458
 459
 460
 461
 462
 463
 464
 465
 466
 467
 468
 469
 470
 471
 472
 473
 474
 475
 476
 477
 478
 479
 480
 481
 482
 483
 484
 485
 486
 487
 488
 489
 490
 491
 492
 493
 494
 495
 496
 497
 498
 499
 500
 501
 502
 503
 504
 505
 506
 507
 508
 509
 510
 511
 512
 513
 514
 515
 516
 517
 518
 519
 520
 521
 522
 523
 524
 525
 526
 527
 528
 529
 530
 531
 532
 533
 534
 535
 536
 537
 538
 539
 540
 541
 542
 543
 544
 545
 546
 547
 548
 549
 550
 551
 552
 553
 554
 555
 556
 557
 558
 559
 560
 561
 562
 563
 564
 565
 566
 567
 568
 569
 570
 571
 572
 573
 574
 575
 576
 577
 578
 579
 580
 581
 582
 583
 584
 585
 586
 587
 588
 589
 590
 591
 592
 593
 594
 595
 596
 597
 598
 599
 600
 601
 602
 603
 604
 605
 606
 607
 608
 609
 610
 611
 612
 613
 614
 615
 616
 617
 618
 619
 620
 621
 622
 623
 624
 625
 626
 627
 628
 629
 630
 631
 632
 633
 634
 635
 636
 637
 638
 639
 640
 641
 642
 643
 644
 645
 646
 647
 648
 649
 650
 651
 652
 653
 654
 655
 656
 657
 658
 659
 660
 661
 662
 663
 664
 665
 666
 667
 668
 669
 670
 671
 672
 673
 674
 675
 676
 677
 678
 679
 680
 681
 682
 683
 684
 685
 686
 687
 688
 689
 690
 691
 692
 693
 694
 695
 696
 697
 698
 699
 700
 701
 702
 703
 704
 705
 706
 707
 708
 709
 710
 711
 712
 713
 714
 715
 716
 717
 718
 719
 720
 721
 722
 723
 724
 725
 726
 727
 728
 729
 730
 731
 732
 733
 734
 735
 736
 737
 738
 739
 740
 741
 742
 743
 744
 745
 746
 747
 748
 749
 750
 751
 752
 753
 754
 755
 756
 757
 758
 759
 760
 761
 762
 763
 764
 765
 766
 767
 768
 769
 770
 771
 772
 773
 774
 775
 776
 777
 778
 779
 780
 781
 782
 783
 784
 785
 786
 787
 788
 789
 790
 791
 792
 793
 794
 795
 796
 797
 798
 799
 800
 801
 802
 803
 804
 805
 806
 807
 808
 809
 810
 811
 812
 813
 814
 815
 816
 817
 818
 819
 820
 821
 822
 823
 824
 825
 826
 827
 828
 829
 830
 831
 832
 833
 834
 835
 836
 837
 838
 839
 840
 841
 842
 843
 844
 845
 846
 847
 848
 849
 850
 851
 852
 853
 854
 855
 856
 857
 858
 859
 860
 861
 862
 863
 864
 865
 866
 867
 868
 869
 870
 871
 872
 873
 874
 875
 876
 877
 878
 879
 880
 881
 882
 883
 884
 885
 886
 887
 888
 889
 890
 891
 892
 893
 894
 895
 896
 897
 898
 899
 900
 901
 902
 903
 904
 905
 906
 907
 908
 909
 910
 911
 912
 913
 914
 915
 916
 917
 918
 919
 920
 921
 922
 923
 924
 925
 926
 927
 928
 929
 930
 931
 932
 933
 934
 935
 936
 937
 938
 939
 940
 941
 942
 943
 944
 945
 946
 947
 948
 949
 950
 951
 952
 953
 954
 955
 956
 957
 958
 959
 960
 961
 962
 963
 964
 965
 966
 967
 968
 969
 970
 971
 972
 973
 974
 975
 976
 977
 978
 979
 980
 981
 982
 983
 984
 985
 986
 987
 988
 989
 990
 991
 992
 993
 994
 995
 996
 997
 998
 999
 1000
 1001
 1002
 1003
 1004
 1005
 1006
 1007
 1008
 1009
 1010
 1011
 1012
 1013
 1014
 1015
 1016
 1017
 1018
 1019
 1020
 1021
 1022
 1023
 1024
 1025
 1026
 1027
 1028
 1029
 1030
 1031
 1032
 1033
 1034
 1035
 1036
 1037
 1038
 1039
 1040
 1041
 1042
 1043
 1044
 1045
 1046
 1047
 1048
 1049
 1050
 1051
 1052
 1053
 1054
 1055
 1056
 1057
 1058
 1059
 1060
 1061
 1062
 1063
 1064
 1065
 1066
 1067
 1068
 1069
 1070
 1071
 1072
 1073
 1074
 1075
 1076
 1077
 1078
 1079
 1080
 1081
 1082
 1083
 1084
 1085
 1086
 1087
 1088
 1089
 1090
 1091
 1092
 1093
 1094
 1095
 1096
 1097
 1098
 1099
 1100
 1101
 1102
 1103
 1104
 1105
 1106
 1107
 1108
 1109
 1110
 1111
 1112
 1113
 1114
 1115
 1116
 1117
 1118
 1119
 1120
 1121
 1122
 1123
 1124
 1125
 1126
 1127
 1128
 1129
 1130
 1131
 1132
 1133
 1134
 1135
 1136
 1137
 1138
 1139
 1140
 1141
 1142
 1143
 1144
 1145
 1146
 1147
 1148
 1149
 1150
 1151
 1152
 1153
 1154
 1155
 1156
 1157
 1158
 1159
 1160
 1161
 1162
 1163
 1164
 1165
 1166
 1167
 1168
 1169
 1170
 1171
 1172
 1173
 1174
 1175
 1176
 1177
 1178
 1179
 1180
 1181
 1182
 1183
 1184
 1185
 1186
 1187
 1188
 1189
 1190
 1191
 1192
 1193
 1194
 1195
 1196
 1197
 1198
 1199
 1200
 1201
 1202
 1203
 1204
 1205
 1206
 1207
 1208
 1209
 1210
 1211
 1212
 1213
 1214
 1215
 1216
 1217
 1218
 1219
 1220
 1221
 1222
 1223
 1224
 1225
 1226
 1227
 1228
 1229
 1230
 1231
 1232
 1233
 1234
 1235
 1236
 1237
 1238
 1239
 1240
 1241
 1242
 1243
 1244
 1245
 1246
 1247
 1248
 1249
 1250
 1251
 1252
 1253
 1254
 1255
 1256
 1257
 1258
 1259
 1260
 1261
 1262
 1263
 1264
 1265
 1266
 1267
 1268
 1269
 1270
 1271
 1272
 1273
 1274
 1275
 1276
 1277
 1278
 1279
 1280
 1281
 1282
 1283
 1284
 1285
 1286
 1287
 1288
 1289
 1290
 1291
 1292
 1293
 1294
 1295
 1296
 1297
 1298
 1299
 1300
 1301
 1302
 1303
 1304
 1305
 1306
 1307
 1308
 1309
 1310
 1311
 1312
 1313
 1314
 1315
 1316
 1317
 1318
 1319
 1320
 1321
 1322
 1323
 1324
 1325
 1326
 1327
 1328
 1329
 1330
 1331
 1332
 1333
 1334
 1335
 1336
 1337
 1338
 1339
 1340
 1341
 1342
 1343
 1344
 1345
 1346
 1347
 1348
 1349
 1350
 1351
 1352
 1353
 1354
 1355
 1356
 1357
 1358
 1359
 1360
 1361
 1362
 1363
 1364
 1365
 1366
 1367
 1368
 1369
 1370
 1371
 1372
 1373
 1374
 1375
 1376
 1377
 1378
 1379
 1380
 1381
 1382
 1383
 1384
 1385
 1386
 1387
 1388
 1389
 1390
 1391
 1392
 1393
 1394
 1395
 1396
 1397
 1398
 1399
 1400
 1401
 1402
 1403
 1404
 1405
 1406
 1407
 1408
 1409
 1410
 1411
 1412
 1413
 1414
 1415
 1416
 1417
 1418
 1419
 1420
 1421
 1422
 1423
 1424
 1425
 1426
 1427
 1428
 1429
 1430
 1431
 1432
 1433
 1434
 1435
 1436
 1437
 1438
 1439
 1440
 1441
 1442
 1443
 1444
 1445
 1446
 1447
 1448
 1449
 1450
 1451
 1452
 1453
 1454
 1455
 1456
 1457
 1458
 1459
 1460
 1461
 1462
 1463
 1464
 1465
 1466
 1467
 1468
 1469
 1470
 1471
 1472
 1473
 1474
 1475
 1476
 1477
 1478
 1479
 1480
 1481
 1482
 1483
 1484
 1485
 1486
 1487
 1488
 1489
 1490
 1491
 1492
 1493
 1494
 1495
 1496
 1497
 1498
 1499
 1500
 1501
 1502
 1503
 1504
 1505
 1506
 1507
 1508
 1509
 1510
 1511
 1512
 1513
 1514
 1515
 1516
 1517
 1518
 1519
 1520
 1521
 1522
 1523
 1524
 1525
 1526
 1527
 1528
 1529
 1530
 1531
 1532
 1533
 1534
 1535
 1536
 1537
 1538
 1539
 1540
 1541
 1542
 1543
 1544
 1545
 1546
 1547
 1548
 1549
 1550
 1551
 1552
 1553
 1554
 1555
 1556
 1557
 1558
 1559
 1560
 1561
 1562
 1563
 1564
 1565
 1566
 1567
 1568
 1569
 1570
 1571
 1572
 1573
 1574
 1575
 1576
 1577
 1578
 1579
 1580
 1581
 1582
 1583
 1584
 1585
 1586
 1587
 1588
 1589
 1590
 1591
 1592
 1593
 1594
 1595
 1596
 1597
 1598
 1599
 1600
 1601
 1602
 1603
 1604
 1605
 1606
 1607
 1608
 1609
 1610
 1611
 1612
 1613
 1614
 1615
 1616
 1617
 1618
 1619
 1620
 1621
 1622
 1623
 1624
 1625
 1626
 1627
 1628
 1629
 1630
 1631
 1632
 1633
 1634
 1635
 1636
 1637
 1638
 1639
 1640
 1641
 1642
 1643
 1644
 1645
 1646
 1647
 1648
 1649
 1650
 1651
 1652
 1653
 1654
 1655
 1656
 1657
 1658
 1659
 1660
 1661
 1662
 1663
 1664
 1665
 1666
 1667
 1668
 1669
 1670
 1671
 1672
 1673
 1674
 1675
 1676
 1677
 1678
 1679
 1680
 1681
 1682
 1683
 1684
 1685
 1686
 1687
 1688
 1689
 1690
 1691
 1692
 1693
 1694
 1695
 1696
 1697
 1698
 1699
 1700
 1701
 1702
 1703
 1704
 1705
 1706
 1707
 1708
 1709
 1710
 1711
 1712
 1713
 1714
 1715
 1716
 1717
 1718
 1719
 1720
 1721
 1722
 1723
 1724
 1725
 1726
 1727
 1728
 1729
 1730
 1731
 1732
 1733
 1734
 1735
 1736
 1737
 1738
 1739
 1740
 1741
 1742
 1743
 1744
 1745
 1746
 1747
 1748
 1749
 1750
 1751
 1752
 1753
 1754
 1755
 1756
 1757
 1758
 1759
 1760
 1761
 1762
 1763
 1764
 1765
 1766
 1767
 1768
 1769
 1770
 1771
 1772
 1773
 1774
 1775
 1776
 1777
 1778
 1779
 1780
 1781
 1782
 1783
 1784
 1785
 1786
 1787
 1788
 1789
 1790
 1791
 1792
 1793
 1794
 1795
 1796
 1797
 1798
 1799
 1800
 1801
 1802
 1803
 1804
 1805
 1806
 1807
 1808
 1809
 1810
 1811
 1812
 1813
 1814
 1815
 1816
 1817
 1818
 1819
 1820
 1821
 1822
 1823
 1824
 1825
 1826
 1827
 1828
 1829
 1830
 1831
 1832
 1833
 1834
 1835
 1836
 1837
 1838
 1839
 1840
 1841
 1842
 1843
 1844
 1845
 1846
 1847
 1848
 1849
 1850
 1851
 1852
 1853
 1854
 1855
 1856
 1857
 1858
 1859
 1860
 1861
 1862
 1863
 1864
 1865
 1866
 1867
 1868
 1869
 1870
 1871
 1872
 1873
 1874
 1875
 1876
 1877
 1878
 1879
 1880
 1881
 1882
 1883
 1884
 1885
 1886
 1887
 1888
 1889
 1890
 1891
 1892
 1893
 1894
 1895
 1896
 1897
 1898
 1899
 1900
 1901
 1902
 1903
 1904
 1905
 1906
 1907
 1908
 1909
 1910
 1911
 1912
 1913
 1914
 1915
 1916
 1917
 1918
 1919
 1920
 1921
 1922
 1923
 1924
 1925
 1926
 1927
 1928
 1929
 1930
 1931
 1932
 1933
 1934
 1935
 1936
 1937
 1938
 1939
 1940
 1941
 1942
 1943
 1944
 1945
 1946
 1947
 1948
 1949
 1950
 1951
 1952
 1953
 1954
 1955
 1956
 1957
 1958
 1959
 1960
 1961
 1962
 1963
 1964
 1965
 1966
 1967
 1968
 1969
 1970
 1971
 1972
 1973
 1974
 1975
 1976
 1977
 1978
 1979
 1980
 1981
 1982
 1983
 1984
 1985
 1986
 1987
 1988
 1989
 1990
 1991
 1992
 1993
 1994
 1995
 1996
 1997
 1998
 1999
 2000
 2001
 2002
 2003
 2004
 2005
 2006
 2007
 2008
 2009
 2010
 2011
 2012
 2013
 2014
 2015
 2016
 2017
 2018
 2019
 2020
 2021
 2022
 2023
 2024
 2025
 2026
 2027
 2028
 2029
 2030
 2031
 2032
 2033
 2034
 2035
 2036
 2037
 2038
 2039
 2040
 2041
 2042
 2043
 2044
 2045
 2046
 2047
 2048
 2049
 2050
 2051
 2052
 2053
 2054
 2055
 2056
 2057
 2058
 2059
 2060
 2061
 2062
 2063
 2064
 2065
 2066
 2067
 2068
 2069
 2070
 2071
 2072
 2073
 2074
 2075
 2076
 2077
 2078
 2079
 2080
 2081
 2082
 2083
 2084
 2085
 2086
 2087
 2088
 2089
 2090
 2091
 2092
 2093
 2094
 2095
 2096
 2097
 2098
 2099
 2100
 2101
 2102
 2103
 2104
 2105
 2106
 2107
 2108
 2109
 2110
 2111
 2112
 2113
 2114
 2115
 2116
 2117
 2118
 2119
 2120
 2121
 2122
 2123
 2124
 2125
 2126
 2127
 2128
 2129
 2130
 2131
 2132
 2133
 2134
 2135
 2136
 2137
 2138
 2139
 2140
 2141
 2142
 2143
 2144
 2145
 2146
 2147
 2148
 2149
 2150
 2151
 2152
 2153
 2154
 2155
 2156
 2157
 2158
 2159
 2160
 2161
 2162
 2163
 2164
 2165
 2166
 2167
 2168
 2169
 2170
 2171
 2172
 2173
 2174
 2175
 2176
 2177
 2178
 2179
 2180
 2181
 2182
 2183
 2184
 2185
 2186
 2187
 2188
 2189
 2190
 2191
 2192
 2193
 2194
 2195
 2196
 2197
 2198
 2199
 2200
 2201
 2202
 2203
 2204
 2205
 2206
 2207
 2208
 2209
 2210
 2211
 2212
 2213
 2214
 2215
 2216
 2217
 2218
 2219
 2220
 2221
 2222
 2223
 2224
 2225
 2226
 2227
 2228
 2229
 2230
 2231
 2232
 2233
 2234
 2235
 2236
 2237
 2238
 2239
 2240
 2241
 2242
 2243
 2244
 2245
 2246
 2247
 2248
 2249
 2250
 2251
 2252
 2253
 2254
 2255
 2256
 2257
 2258
 2259
 2260
 2261
 2262
 2263
 2264
 2265
 2266
 2267
 2268
 2269
 2270
 2271
 2272
 2273
 2274
 2275
 2276
 2277
 2278
 2279
 2280
 2281
 2282
 2283
 2284
 2285
 2286
 2287
 2288
 2289
 2290
 2291
 2292
 2293
 2294
 2295
 2296
 2297
 2298
 2299
 2300
 2301
 2302
 2303
 2304
 2305
 2306
 2307
 2308
 2309
 2310
 2311
 2312
 2313
 2314
 2315
 2316
 2317
 2318
 2319
 2320
 2321
 2322
 2323
 2324
 2325
 2326
 2327
 2328
 2329
 2330
 2331
 2332
 2333
 2334
 2335
 2336
 2337
 2338
 2339
 2340
 2341
 2342
 2343
 2344
 2345
 2346
 2347
 2348
 2349
 2350
 2351
 2352
 2353
 2354
 2355
 2356
 2357
 2358
 2359
 2360
 2361
 2362
 2363
 2364
 2365
 2366
 2367
 2368
 2369
 2370
 2371
 2372
 2373
 2374
 2375
 2376
 2377
 2378
 2379
 2380
 2381
 2382
 2383
 2384
 2385
 2386
 2387
 2388
 2389
 2390
 2391
 2392
 2393
 2394
 2395
 2396
 2397
 2398
 2399
 2400
 2401
 2402
 2403
 2404
 2405
 2406
 2407
 2408
 2409
 2410
 2411
 2412
 2413
 2414
 2415
 2416
 2417
 2418
 2419
 2420
 2421
 2422
 2423
 2424
 2425
 2426
 2427
 2428
 2429
 2430
 2431
 2432
 2433
 2434
 2435
 2436
 2437
 2438
 2439
 2440
 2441
 2442
 2443
 2444
 2445
 2446
 2447
 2448
 2449
 2450
 2451
 2452
 2453
 2454
 2455
 2456
 2457
 2458
 2459
 2460
 2461
 2462
 2463
 2464
 2465
 2466
 2467
 2468
 2469
 2470
 2471
 2472
 2473
 2474
 2475
 2476
 2477
 2478
 2479
 2480
 2481
 2482
 2483
 2484
 2485
 2486
 2487
 2488
 2489
 2490
 2491
 2492
 2493
 2494
 2495
 2496
 2497
 2498
 2499
 2500
 2501
 2502
 2503
 2504
 2505
 2506
 2507
 2508
 2509
 2510
 2511
 2512
 2513
 2514
 2515
 2516
 2517
 2518
 2519
 2520
 2521
 2522
 2523
 2524
 2525
 2526
 2527
 2528
 2529
 2530
 2531
 2532
 2533
 2534
 2535
 2536
 2537
 2538
 2539
 2540
 2541
 2542
 2543
 2544
 2545
 2546
 2547
 2548
 2549
 2550
 2551
 2552
 2553
 2554
 2555
 2556
 2557
 2558
 2559
 2560
 2561
 2562
 2563
 2564
 2565
 2566
 2567
 2568
 2569
 2570
 2571
 2572
 2573
 2574
 2575
 2576
 2577
 2578
 2579
 2580
 2581
 2582
 2583
 2584
 2585
 2586
 2587
 2588
 2589
 2590
 2591
 2592
 2593
 2594
 2595
 2596
 2597
 2598
 2599
 2600
 2601
 2602
 2603
 2604
 2605
 2606
 2607
 2608
 2609
 2610
 2611
 2612
 2613
 2614
 2615
 2616
 2617
 2618
 2619
 2620
 2621
 2622
 2623
 2624
 2625
 2626
 2627
 2628
 2629
 2630
 2631
 2632
 2633
 2634
 2635
 2636
 2637
 2638
 2639
 2640
 2641
 2642
 2643
 2644
 2645
 2646
 2647
 2648
 2649
 2650
 2651
 2652
 2653
 2654
 2655
 2656
 2657
 2658
 2659
 2660
 2661
 2662
 2663
 2664
 2665
 2666
 2667
 2668
 2669
 2670
 2671
 2672
 2673
 2674
 2675
 2676
 2677
 2678
 2679
 2680
 2681
 2682
 2683
 2684
 2685
 2686
 2687
 2688
 2689
 2690
 2691
 2692
 2693
 2694
 2695
 2696
 2697
 2698
 2699
 2700
 2701
 2702
 2703
 2704
 2705
 2706
 2707
 2708
 2709
 2710
 2711
 2712
 2713
 2714
 2715
 2716
 2717
 2718
 2719
 2720
 2721
 2722
 2723
 2724
 2725
 2726
 2727
 2728
 2729
 2730
 2731
 2732
 2733
 2734
 2735
 2736
 2737
 2738
 2739
 2740
 2741
 2742
 2743
 2744
 2745
 2746
 2747
 2748
 2749
 2750
 2751
 2752
 2753
 2754
 2755
 2756
 2757
 2758
 2759
 2760
 2761
 2762
 2763
 2764
 2765
 2766
 2767
 2768
 2769
 2770
 2771
 2772
 2773
 2774
 2775
 2776
 2777
 2778
 2779
 2780
 2781
 2782
 2783
 2784
 2785
 2786
 2787
 2788
 2789
 2790
 2791
 2792
 2793
 2794
 2795
 2796
 2797
 2798
 2799
 2800
 2801
 2802
 2803
 2804
 2805
 2806
 2807
 2808
 2809
 2810
 2811
 2812
 2813
 2814
 2815
 2816
 2817
 2818
 2819
 2820
 2821
 2822
 2823
 2824
 2825
 2826
 2827
 2828
 2829
 2830
 2831
 2832
 2833
 2834
 2835
 2836
 2837
 2838
 2839
 2840
 2841
 2842
 2843
 2844
 2845
 2846
 2847
 2848
 2849
 2850
 2851
 2852
 2853
 2854
 2855
 2856
 2857
 2858
 2859
 2860
 2861
 2862
 2863
 2864
 2865
 2866
 2867
 2868
 2869
 2870
 2871
 2872
 2873
 2874
 2875
 2876
 2877
 2878
 2879
 2880
 2881
 2882
 2883
 2884
 2885
 2886
 2887
 2888
 2889
 2890
 2891
 2892
 2893
 2894
 2895
 2896
 2897
 2898
 2899
 2900
 2901
 2902
 2903
 2904
 2905
 2906
 2907
 2908
 2909
 2910
 2911
 2912
 2913
 2914
 2915
 2916
 2917
 2918
 2919
 2920
 2921
 2922
 2923
 2924
 2925
 2926
 2927
 2928
 2929
 2930
 2931
 2932
 2933
 2934
 2935
 2936
 2937
 2938
 2939
 2940
 2941
 2942
 2943
 2944
 2945
 2946
 2947
 2948
 2949
 2950
 2951
 2952
 2953
 2954
 2955
 2956
 2957
 2958
 2959
 2960
 2961
 2962
 2963
 2964
 2965
 2966
 2967
 2968
 2969
 2970
 2971
 2972
 2973
 2974
 2975
 2976
 2977
 2978
 2979
 2980
 2981
 2982
 2983
 2984
 2985
 2986
 2987
 2988
 2989
 2990
 2991
 2992
 2993
 2994
 2995
 2996
 2997
 2998
 2999
 3000
 3001
 3002
 3003
 3004
 3005
 3006
 3007
 3008
 3009
 3010
 3011
 3012
 3013
 3014
 3015
 3016
 3017
 3018
 3019
 3020
 3021
 3022
 3023
 3024
 3025
 3026
 3027
 3028
 3029
 3030
 3031
 3032
 3033
 3034
 3035
 3036
 3037
 3038
 3039
 3040
 3041
 3042
 3043
 3044
 3045
 3046
 3047
 3048
 3049
 3050
 3051
 3052
 3053
 3054
 3055
 3056
 3057
 3058
 3059
 3060
 3061
 3062
 3063
 3064
 3065
 3066
 3067
 3068
 3069
 3070
 3071
 3072
 3073
 3074
 3075
 3076
 3077
 3078
 3079
 3080
 3081
 3082
 3083
 3084
 3085
 3086
 3087
 3088
 3089
 3090
 3091
 3092
 3093
 3094
 3095
 3096
 3097
 3098
 3099
 3100
 3101
 3102
 3103
 3104
 3105
 3106
 3107
 3108
 3109
 3110
 3111
 3112
 3113
 3114
 3115
 3116
 3117
 3118
 3119
 3120
 3121
 3122
 3123
 3124
 3125
 3126
 3127
 3128
 3129
 3130
 3131
 3132
 3133
 3134
 3135
 3136
 3137
 3138
 3139
 3140
 3141
 3142
 3143
 3144
 3145
 3146
 3147
 3148
 3149
 3150
 3151
 3152
 3153
 3154
 3155
 3156
 3157
 3158
 3159
 3160
 3161
 3162
 3163
 3164
 3165
 3166
 3167
 3168
 3169
 3170
 3171
 3172
 3173
 3174
 3175
 3176
 3177
 3178
 3179
 3180
 3181
 3182
 3183
 3184
 3185
 3186
 3187
 3188
 3189
 3190
 3191
 3192
 3193
 3194
 3195
 3196
 3197
 3198
 3199
 3200
 3201
 3202
 3203
 3204
 3205
 3206
 3207
 3208
 3209
 3210
 3211
 3212
 3213
 3214
 3215
 3216
 3217
 3218
 3219
 3220
 3221
 3222
 3223
 3224
 3225
 3226
 3227
 3228
 3229
 3230
 3231
 3232
 3233
 3234
 3235
 3236
 3237
 3238
 3239
 3240
 3241
 3242
 3243
 3244
 3245
 3246
 3247
 3248
 3249
 3250
 3251
 3252
 3253
 3254
 3255
 3256
 3257
 3258
 3259
 3260
 3261
 3262
 3263
 3264
 3265
 3266
 3267
 3268
 3269
 3270
 3271
 3272
 3273
 3274
 3275
 3276
 3277
 3278
 3279
 3280
 3281
 3282
 3283
 3284
 3285
 3286
 3287
 3288
 3289
 3290
 3291
 3292
 3293
 3294
 3295
 3296
 3297
 3298
 3299
 3300
 3301
 3302
 3303
 3304
 3305
 3306
 3307
 3308
 3309
 3310
 3311
 3312
 3313
 3314
 3315
 3316
 3317
 3318
 3319
 3320
 3321
 3322
 3323
 3324
 3325
 3326
 3327
 3328
 3329
 3330
 3331
 3332
 3333
 3334
 3335
 3336
 3337
 3338
 3339
 3340
 3341
 3342
 3343
 3344
 3345
 3346
 3347
 3348
 3349
 3350
 3351
 3352
 3353
 3354
 3355
 3356
 3357
 3358
 3359
 3360
 3361
 3362
 3363
 3364
 3365
 3366
 3367
 3368
 3369
 3370
 3371
 3372
 3373
 3374
 3375
 3376
 3377
 3378
 3379
 3380
 3381
 3382
 3383
 3384
 3385
 3386
 3387
 3388
 3389
 3390
 3391
 3392
 3393
 3394
 3395
 3396
 3397
 3398
 3399
 3400
 3401
 3402
 3403
 3404
 3405
 3406
 3407
 3408
 3409
 3410
 3411
 3412
 3413
 3414
 3415
 3416
 3417
 3418
 3419
 3420
 3421
 3422
 3423
 3424
 3425
 3426
 3427
 3428
 3429
 3430
 3431
 3432
 3433
 3434
 3435
 3436
 3437
 3438
 3439
 3440
 3441
 3442
 3443
 3444
 3445
 3446
 3447
 3448
 3449
 3450
 3451
 3452
 3453
 3454
 3455
 3456
 3457
 3458
 3459
 3460
 3461
 3462
 3463
 3464
 3465
 3466
 3467
 3468
 3469
 3470
 3471
 3472
 3473
 3474
 3475
 3476
 3477
 3478
 3479
 3480
 3481
 3482
 3483
 3484
 3485
 3486
 3487
 3488
 3489
 3490
 3491
 3492
 3493
 3494
 3495
 3496
 3497
 3498
 3499
 3500
 3501
 3502
 3503
 3504
 3505
 3506
 3507
 3508
 3509
 3510
 3511
 3512
 3513
 3514
 3515
 3516
 3517
 3518
 3519
 3520
 3521
 3522
 3523
 3524
 3525
 3526
 3527
 3528
 3529
 3530
 3531
 3532
 3533
 3534
 3535
 3536
 3537
 3538
 3539
 3540
 3541
 3542
 3543
 3544
 3545
 3546
 3547
 3548
 3549
 3550
 3551
 3552
 3553
 3554
 3555
 3556
 3557
 3558
 3559
 3560
 3561
 3562
 3563
 3564
 3565
 3566
 3567
 3568
 3569
 3570
 3571
 3572
 3573
 3574
 3575
 3576
 3577
 3578
 3579
 3580
 3581
 3582
 3583
 3584
 3585
 3586
 3587
 3588
 3589
 3590
 3591
 3592
 3593
 3594
 3595
 3596
 3597
 3598
 3599
 3600
 3601
 3602
 3603
 3604
 3605
 3606
 3607
 3608
 3609
 3610
 3611
 3612
 3613
 3614
 3615
 3616
 3617
 3618
 3619
 3620
 3621
 3622
 3623
 3624
 3625
 3626
 3627
 3628
 3629
 3630
 3631
 3632
 3633
 3634
 3635
 3636
 3637
 3638
 3639
 3640
 3641
 3642
 3643
 3644
 3645
 3646
 3647
 3648
 3649
 3650
 3651
 3652
 3653
 3654
 3655
 3656
 3657
 3658
 3659
 3660
 3661
 3662
 3663
 3664
 3665
 3666
 3667
 3668
 3669
 3670
 3671
 3672
 3673
 3674
 3675
 3676
 3677
 3678
 3679
 3680
 3681
 3682
 3683
 3684
 3685
 3686
 3687
 3688
 3689
 3690
 3691
 3692
 3693
 3694
 3695
 3696
 3697
 3698
 3699
 3700
 3701
 3702
 3703
 3704
 3705
 3706
 3707
 3708
 3709
 3710
 3711
 3712
 3713
 3714
 3715
 3716
 3717
 3718
 3719
 3720
 3721
 3722
 3723
 3724
 3725
 3726
 3727
 3728
 3729
 3730
 3731
 3732
 3733
 3734
 3735
 3736
 3737
 3738
 3739
 3740
 3741
 3742
 3743
 3744
 3745
 3746
 3747
 3748
 3749
 3750
 3751
 3752
 3753
 3754
 3755
 3756
 3757
 3758
 3759
 3760
 3761
 3762
 3763
 3764
 3765
 3766
 3767
 3768
 3769
 3770
 3771
 3772
 3773
 3774
 3775
 3776
 3777
 3778
 3779
 3780
 3781
 3782
 3783
 3784
 3785
 3786
 3787
 3788
 3789
 3790
 3791
 3792
 3793
 3794
 3795
 3796
 3797
 3798
 3799
 3800
 3801
 3802
 3803
 3804
 3805
 3806
 3807
 3808
 3809
 3810
 3811
 3812
 3813
 3814
 3815
 3816
 3817
 3818
 3819
 3820
 3821
 3822
 3823
 3824
 3825
 3826
 3827
 3828
 3829
 3830
 3831
 3832
 3833
 3834
 3835
 3836
 3837
 3838
 3839
 3840
 3841
 3842
 3843
 3844
 3845
 3846
 3847
 3848
 3849
 3850
 3851
 3852
 3853
 3854
 3855
 3856
 3857
 3858
 3859
 3860
 3861
 3862
 3863
 3864
 3865
 3866
 3867
 3868
 3869
 3870
 3871
 3872
 3873
 3874
 3875
 3876
 3877
 3878
 3879
 3880
 3881
 3882
 3883
 3884
 3885
 3886
 3887
 3888
 3889
 3890
 3891
 3892
 3893
 3894
 3895
 3896
 3897
 3898
 3899
 3900
 3901
 3902
 3903
 3904
 3905
 3906
 3907
 3908
 3909
 3910
 3911
 3912
 3913
 3914
 3915
 3916
 3917
 3918
 3919
 3920
 3921
 3922
 3923
 3924
 3925
 3926
 3927
 3928
 3929
 3930
 3931
 3932
 3933
 3934
 3935
 3936
 3937
 3938
 3939
 3940
 3941
 3942
 3943
 3944
 3945
 3946
 3947
 3948
 3949
 3950
 3951
 3952
 3953
 3954
 3955
 3956
 3957
 3958
 3959
 3960
 3961
 3962
 3963
 3964
 3965
 3966
 3967
 3968
 3969
 3970
 3971
 3972
 3973
 3974
 3975
 3976
 3977
 3978
 3979
 3980
 3981
 3982
 3983
 3984
 3985
 3986
 3987
 3988
 3989
 3990
 3991
 3992
 3993
 3994
 3995
 3996
 3997
 3998
 3999
 4000
 4001
 4002
 4003
 4004
 4005
 4006
 4007
 4008
 4009
 4010
 4011
 4012
 4013
 4014
 4015
 4016
 4017
 4018
 4019
 4020
 4021
 4022
 4023
 4024
 4025
 4026
 4027
 4028
 4029
 4030
 4031
 4032
 4033
 4034
 4035
 4036
 4037
 4038
 4039
 4040
 4041
 4042
 4043
 4044
 4045
 4046
 4047
 4048
 4049
 4050
 4051
 4052
 4053
 4054
 4055
 4056
 4057
 4058
 4059
 4060
 4061
 4062
 4063
 4064
 4065
 4066
 4067
 4068
 4069
 4070
 4071
 4072
 4073
 4074
 4075
 4076
 4077
 4078
 4079
 4080
 4081
 4082
 4083
 4084
 4085
 4086
 4087
 4088
 4089
 4090
 4091
 4092
 4093
 4094
 4095
 4096
 4097
 4098
 4099
 4100
 4101
 4102
 4103
 4104
 4105
 4106
 4107
 4108
 4109
 4110
 4111
 4112
 4113
 4114
 4115
 4116
 4117
 4118
 4119
 4120
 4121
 4122
 4123
 4124
 4125
 4126
 4127
 4128
 4129
 4130
 4131
 4132
 4133
 4134
 4135
 4136
 4137
 4138
 4139
 4140
 4141
 4142
 4143
 4144
 4145
 4146
 4147
 4148
 4149
 4150
 4151
 4152
 4153
 4154
 4155
 4156
 4157
 4158
 4159
 4160
 4161
 4162
 4163
 4164
 4165
 4166
 4167
 4168
 4169
 4170
 4171
 4172
 4173
 4174
 4175
 4176
 4177
 4178
 4179
 4180
 4181
 4182
 4183
 4184
 4185
 4186
 4187
 4188
 4189
 4190
 4191
 4192
 4193
 4194
 4195
 4196
 4197
 4198
 4199
 4200
 4201
 4202
 4203
 4204
 4205
 4206
 4207
 4208
 4209
 4210
 4211
 4212
 4213
 4214
 4215
 4216
 4217
 4218
 4219
 4220
 4221
 4222
 4223
 4224
 4225
 4226
 4227
 4228
 4229
 4230
 4231
 4232
 4233
 4234
 4235
 4236
 4237
 4238
 4239
 4240
 4241
 4242
 4243
 4244
 4245
 4246
 4247
 4248
 4249
 4250
 4251
 4252
 4253
 4254
 4255
 4256
 4257
 4258
 4259
 4260
 4261
 4262
 4263
 4264
 4265
 4266
 4267
 4268
 4269
 4270
 4271
 4272
 4273
 4274
 4275
 4276
 4277
 4278
 4279
 4280
 4281
 4282
 4283
 4284
 4285
 4286
 4287
 4288
 4289
 4290
 4291
 4292
 4293
 4294
 4295
 4296
 4297
 4298
 4299
 4300
 4301
 4302
 4303
 4304
 4305
 4306
 4307
 4308
 4309
 4310
 4311
 4312
 4313
 4314
 4315
 4316
 4317
 4318
 4319
 4320
 4321
 4322
 4323
 4324
 4325
 4326
 4327
 4328
 4329
 4330
 4331
 4332
 4333
 4334
 4335
 4336
 4337
 4338
 4339
 4340
 4341
 4342
 4343
 4344
 4345
 4346
 4347
 4348
 4349
 4350
 4351
 4352
 4353
 4354
 4355
 4356
 4357
 4358
 4359
 4360
 4361
 4362
 4363
 4364
 4365
 4366
 4367
 4368
 4369
 4370
 4371
 4372
 4373
 4374
 4375
 4376
 4377
 4378
 4379
 4380
 4381
 4382
 4383
 4384
 4385
 4386
 4387
 4388
 4389
 4390
 4391
 4392
 4393
 4394
 4395
 4396
 4397
 4398
 4399
 4400
 4401
 4402
 4403
 4404
 4405
 4406
 4407
 4408
 4409
 4410
 4411
 4412
 4413
 4414
 4415
 4416
 4417
 4418
 4419
 4420
 4421
 4422
 4423
 4424
 4425
 4426
 4427
 4428
 4429
 4430
 4431
 4432
 4433
 4434
 4435
 4436
 4437
 4438
 4439
 4440
 4441
 4442
 4443
 4444
 4445
 4446
 4447
 4448
 4449
 4450
 4451
 4452
 4453
 4454
 4455
 4456
 4457
 4458
 4459
 4460
 4461
 4462
 4463
 4464
 4465
 4466
 4467
 4468
 4469
 4470
 4471
 4472
 4473
 4474
 4475
 4476
 4477
 4478
 4479
 4480
 4481
 4482
 4483
 4484
 4485
 4486
 4487
 4488
 4489
 4490
 4491
 4492
 4493
 4494
 4495
 4496
 4497
 4498
 4499
 4500
 4501
 4502
 4503
 4504
 4505
 4506
 4507
 4508
 4509
 4510
 4511
 4512
 4513
 4514
 4515
 4516
 4517
 4518
 4519
 4520
 4521
 4522
 4523
 4524
 4525
 4526
 4527
 4528
 4529
 4530
 4531
 4532
 4533
 4534
 4535
 4536
 4537
 4538
 4539
 4540
 4541
 4542
 4543
 4544
 4545
 4546
 4547
 4548
 4549
 4550
 4551
 4552
 4553
 4554
 4555
 4556
 4557
 4558
 4559
 4560
 4561
 4562
 4563
 4564
 4565
 4566
 4567
 4568
 4569
 4570
 4571
 4572
 4573
 4574
 4575
 4576
 4577
 4578
 4579
 4580
 4581
 4582
 4583
 4584
 4585
 4586
 4587
 4588
 4589
 4590
 4591
 4592
 4593
 4594
 4595
 4596
 4597
 4598
 4599
 4600
 4601
 4602
 4603
 4604
 4605
 4606
 4607
 4608
 4609
 4610
 4611
 4612
 4613
 4614
 4615
 4616
 4617
 4618
 4619
 4620
 4621
 4622
 4623
 4624
 4625
 4626
 4627
 4628
 4629
 4630
 4631
 4632
 4633
 4634
 4635
 4636
 4637
 4638
 4639
 4640
 4641
 4642
 4643
 4644
 4645
 4646
 4647
 4648
 4649
 4650
 4651
 4652
 4653
 4654
 4655
 4656
 4657
 4658
 4659
 4660
 4661
 4662
 4663
 4664
 4665
 4666
 4667
 4668
 4669
 4670
 4671
 4672
 4673
 4674
 4675
 4676
 4677
 4678
 4679
 4680
 4681
 4682
 4683
 4684
 4685
 4686
 4687
 4688
 4689
 4690
 4691
 4692
 4693
 4694
 4695
 4696
 4697
 4698
 4699
 4700
 4701
 4702
 4703
 4704
 4705
 4706
 4707
 4708
 4709
 4710
 4711
 4712
 4713
 4714
 4715
 4716
 4717
 4718
 4719
 4720
 4721
 4722
 4723
 4724
 4725
 4726
 4727
 4728
 4729
 4730
 4731
 4732
 4733
 4734
 4735
 4736
 4737
 4738
 4739
 4740
 4741
 4742
 4743
 4744
 4745
 4746
 4747
 4748
 4749
 4750
 4751
 4752
 4753
 4754
 4755
 4756
 4757
 4758
 4759
 4760
 4761
 4762
 4763
 4764
 4765
 4766
 4767
 4768
 4769
 4770
 4771
 4772
 4773
 4774
 4775
 4776
 4777
 4778
 4779
 4780
 4781
 4782
 4783
 4784
 4785
 4786
 4787
 4788
 4789
 4790
 4791
 4792
 4793
 4794
 4795
 4796
 4797
 4798
 4799
 4800
 4801
 4802
 4803
 4804
 4805
 4806
 4807
 4808
 4809
 4810
 4811
 4812
 4813
 4814
 4815
 4816
 4817
 4818
 4819
 4820
 4821
 4822
 4823
 4824
 4825
 4826
 4827
 4828
 4829
 4830
 4831
 4832
 4833
 4834
 4835
 4836
 4837
 4838
 4839
 4840
 4841
 4842
 4843
 4844
 4845
 4846
 4847
 4848
 4849
 4850
 4851
 4852
 4853
 4854
 4855
 4856
 4857
 4858
 4859
 4860
 4861
 4862
 4863
 4864
 4865
 4866
 4867
 4868
 4869
 4870
 4871
 4872
 4873
 4874
 4875
 4876
 4877
 4878
 4879
 4880
 4881
 4882
 4883
 4884
 4885
 4886
 4887
 4888
 4889
 4890
 4891
 4892
 4893
 4894
 4895
 4896
 4897
 4898
 4899
 4900
 4901
 4902
 4903
 4904
 4905
 4906
 4907
 4908
 4909
 4910
 4911
 4912
 4913
 4914
 4915
 4916
 4917
 4918
 4919
 4920
 4921
 4922
 4923
 4924
 4925
 4926
 4927
 4928
 4929
 4930
 4931
 4932
 4933
 4934
 4935
 4936
 4937
 4938
 4939
 4940
 4941
 4942
 4943
 4944
 4945
 4946
 4947
 4948
 4949
 4950
 4951
 4952
 4953
 4954
 4955
 4956
 4957
 4958
 4959
 4960
 4961
 4962
 4963
 4964
 4965
 4966
 4967
 4968
 4969
 4970
 4971
 4972
 4973
 4974
 4975
 4976
 4977
 4978
 4979
 4980
 4981
 4982
 4983
 4984
 4985
 4986
 4987
 4988
 4989
 4990
 4991
 4992
 4993
 4994
 4995
 4996
 4997
 4998
 4999
 5000
 5001
 5002
 5003
 5004
 5005
 5006
 5007
 5008
 5009
 5010
 5011
 5012
 5013
 5014
 5015
 5016
 5017
 5018
 5019
 5020
 5021
 5022
 5023
 5024
 5025
 5026
 5027
 5028
 5029
 5030
 5031
 5032
 5033
 5034
 5035
 5036
 5037
 5038
 5039
 5040
 5041
 5042
 5043
 5044
 5045
 5046
 5047
 5048
 5049
 5050
 5051
 5052
 5053
 5054
 5055
 5056
 5057
 5058
 5059
 5060
 5061
 5062
 5063
 5064
 5065
 5066
 5067
 5068
 5069
 5070
 5071
 5072
 5073
 5074
 5075
 5076
 5077
 5078
 5079
 5080
 5081
 5082
 5083
 5084
 5085
 5086
 5087
 5088
 5089
 5090
 5091
 5092
 5093
 5094
 5095
 5096
 5097
 5098
 5099
 5100
 5101
 5102
 5103
 5104
 5105
 5106
 5107
 5108
 5109
 5110
 5111
 5112
 5113
 5114
 5115
 5116
 5117
 5118
 5119
 5120
 5121
 5122
 5123
 5124
 5125
 5126
 5127
 5128
 5129
 5130
 5131
 5132
 5133
 5134
 5135
 5136
 5137
 5138
 5139
 5140
 5141
 5142
 5143
 5144
 5145
 5146
 5147
 5148
 5149
 5150
 5151
 5152
 5153
 5154
 5155
 5156
 5157
 5158
 5159
 5160
 5161
 5162
 5163
 5164
 5165
 5166
 5167
 5168
 5169
 5170
 5171
 5172
 5173
 5174
 5175
 5176
 5177
 5178
 5179
 5180
 5181
 5182
 5183
 5184
 5185
 5186
 5187
 5188
 5189
 5190
 5191
 5192
 5193
 5194
 5195
 5196
 5197
 5198
 5199
 5200
 5201
 5202
 5203
 5204
 5205
 5206
 5207
 5208
 5209
 5210
 5211
 5212
 5213
 5214
 5215
 5216
 5217
 5218
 5219
 5220
 5221
 5222
 5223
 5224
 5225
 5226
 5227
 5228
 5229
 5230
 5231
 5232
 5233
 5234
 5235
 5236
 5237
 5238
 5239
 5240
 5241
 5242
 5243
 5244
 5245
 5246
 5247
 5248
 5249
 5250
 5251
 5252
 5253
 5254
 5255
 5256
 5257
 5258
 5259
 5260
 5261
 5262
 5263
 5264
 5265
 5266
 5267
 5268
 5269
 5270
 5271
 5272
 5273
 5274
 5275
 5276
 5277
 5278
 5279
 5280
 5281
 5282
 5283
 5284
 5285
 5286
 5287
 5288
 5289
 5290
 5291
 5292
 5293
 5294
 5295
 5296
 5297
 5298
 5299
 5300
 5301
 5302
 5303
 5304
 5305
 5306
 5307
 5308
 5309
 5310
 5311
 5312
 5313
 5314
 5315
 5316
 5317
 5318
 5319
 5320
 5321
 5322
 5323
 5324
 5325
 5326
 5327
 5328
 5329
 5330
 5331
 5332
 5333
 5334
 5335
 5336
 5337
 5338
 5339
 5340
 5341
 5342
 5343
 5344
 5345
 5346
 5347
 5348
 5349
 5350
 5351
 5352
 5353
 5354
 5355
 5356
 5357
 5358
 5359
 5360
 5361
 5362
 5363
 5364
 5365
 5366
 5367
 5368
 5369
 5370
 5371
 5372
 5373
 5374
 5375
 5376
 5377
 5378
 5379
 5380
 5381
 5382
 5383
 5384
 5385
 5386
 5387
 5388
 5389
 5390
 5391
 5392
 5393
 5394
 5395
 5396
 5397
 5398
 5399
 5400
 5401
 5402
 5403
 5404
 5405
 5406
 5407
 5408
 5409
 5410
 5411
 5412
 5413
 5414
 5415
 5416
 5417
 5418
 5419
 5420
 5421
 5422
 5423
 5424
 5425
 5426
 5427
 5428
 5429
 5430
 5431
 5432
 5433
 5434
 5435
 5436
 5437
 5438
 5439
 5440
 5441
 5442
 5443
 5444
 5445
 5446
 5447
 5448
 5449
 5450
 5451
 5452
 5453
 5454
 5455
 5456
 5457
 5458
 5459
 5460
 5461
 5462
 5463
 5464
 5465
 5466
 5467
 5468
 5469
 5470
 5471
 5472
 5473
 5474
 5475
 5476
 5477
 5478
 5479
 5480
 5481
 5482
 5483
 5484
 5485
 5486
 5487
 5488
 5489
 5490
 5491
 5492
 5493
 5494
 5495
 5496
 5497
 5498
 5499
 5500
 5501
 5502
 5503
 5504
 5505
 5506
 5507
 5508
 5509
 5510
 5511
 5512
 5513
 5514
 5515
 5516
 5517
 5518
 5519
 5520
 5521
 5522
 5523
 5524
 5525
 5526
 5527
 5528
 5529
 5530
 5531
 5532
 5533
 5534
 5535
 5536
 5537
 5538
 5539
 5540
 5541
 5542
 5543
 5544
 5545
 5546
 5547
 5548
 5549
 5550
 5551
 5552
 5553
 5554
 5555
 5556
 5557
 5558
 5559
 5560
 5561
 5562
 5563
 5564
 5565
 5566
 5567
 5568
 5569
 5570
 5571
 5572
 5573
 5574
 5575
 5576
 5577
 5578
 5579
 5580
 5581
 5582
 5583
 5584
 5585
 5586
 5587
 5588
 5589
 5590
 5591
 5592
 5593
 5594
 5595
 5596
 5597
 5598
 5599
 5600
 5601
 5602
 5603
 5604
 5605
 5606
 5607
 5608
 5609
 5610
 5611
 5612
 5613
 5614
 5615
 5616
 5617
 5618
 5619
 5620
 5621
 5622
 5623
 5624
 5625
 5626
 5627
 5628
 5629
 5630
 5631
 5632
 5633
 5634
 5635
 5636
 5637
 5638
 5639
 5640
 5641
 5642
 5643
 5644
 5645
 5646
 5647
 5648
 5649
 5650
 5651
 5652
 5653
 5654
 5655
 5656
 5657
 5658
 5659
 5660
 5661
 5662
 5663
 5664
 5665
 5666
 5667
 5668
 5669
 5670
 5671
 5672
 5673
 5674
 5675
 5676
 5677
 5678
 5679
 5680
 5681
 5682
 5683
 5684
 5685
 5686
 5687
 5688
 5689
 5690
 5691
 5692
 5693
 5694
 5695
 5696
 5697
 5698
 5699
 5700
 5701
 5702
 5703
 5704
 5705
 5706
 5707
 5708
 5709
 5710
 5711
 5712
 5713
 5714
 5715
 5716
 5717
 5718
 5719
 5720
 5721
 5722
 5723
 5724
 5725
 5726
 5727
 5728
 5729
 5730
 5731
 5732
 5733
 5734
 5735
 5736
 5737
 5738
 5739
 5740
 5741
 5742
 5743
 5744
 5745
 5746
 5747
 5748
 5749
 5750
 5751
 5752
 5753
 5754
 5755
 5756
 5757
 5758
 5759
 5760
 5761
 5762
 5763
 5764
 5765
 5766
 5767
 5768
 5769
 5770
 5771
 5772
 5773
 5774
 5775
 5776
 5777
 5778
 5779
 5780
 5781
 5782
 5783
 5784
 5785
 5786
 5787
 5788
 5789
 5790
 5791
 5792
 5793
 5794
 5795
 5796
 5797
 5798
 5799
 5800
 5801
 5802
 5803
 5804
 5805
 5806
 5807
 5808
 5809
 5810
 5811
 5812
 5813
 5814
 5815
 5816
 5817
 5818
 5819
 5820
 5821
 5822
 5823
 5824
 5825
 5826
 5827
 5828
 5829
 5830
 5831
 5832
 5833
 5834
 5835
 5836
 5837
 5838
 5839
 5840
 5841
 5842
 5843
 5844
 5845
 5846
 5847
 5848
 5849
 5850
 5851
 5852
 5853
 5854
 5855
 5856
 5857
 5858
 5859
 5860
 5861
 5862
 5863
 5864
 5865
 5866
 5867
 5868
 5869
 5870
 5871
 5872
 5873
 5874
 5875
 5876
 5877
 5878
 5879
 5880
 5881
 5882
 5883
 5884
 5885
 5886
 5887
 5888
 5889
 5890
 5891
 5892
 5893
 5894
 5895
 5896
 5897
 5898
 5899
 5900
 5901
 5902
 5903
 5904
 5905
 5906
 5907
 5908
 5909
 5910
 5911
 5912
 5913
 5914
 5915
 5916
 5917
 5918
 5919
 5920
 5921
 5922
 5923
 5924
 5925
 5926
 5927
 5928
 5929
 5930
 5931
 5932
 5933
 5934
 5935
 5936
 5937
 5938
 5939
 5940
 5941
 5942
 5943
 5944
 5945
 5946
 5947
 5948
 5949
 5950
 5951
 5952
 5953
 5954
 5955
 5956
 5957
 5958
 5959
 5960
 5961
 5962
 5963
 5964
 5965
 5966
 5967
 5968
 5969
 5970
 5971
 5972
 5973
 5974
 5975
 5976
 5977
 5978
 5979
 5980
 5981
 5982
 5983
 5984
 5985
 5986
 5987
 5988
 5989
 5990
 5991
 5992
 5993
 5994
 5995
 5996
 5997
 5998
 5999
 6000
 6001
 6002
 6003
 6004
 6005
 6006
 6007
 6008
 6009
 6010
 6011
 6012
 6013
 6014
 6015
 6016
 6017
 6018
 6019
 6020
 6021
 6022
 6023
 6024
 6025
 6026
 6027
 6028
 6029
 6030
 6031
 6032
 6033
 6034
 6035
 6036
 6037
 6038
 6039
 6040
 6041
 6042
 6043
 6044
 6045
 6046
 6047
 6048
 6049
 6050
 6051
 6052
 6053
 6054
 6055
 6056
 6057
 6058
 6059
 6060
 6061
 6062
 6063
 6064
 6065
 6066
 6067
 6068
 6069
 6070
 6071
 6072
 6073
 6074
 6075
 6076
 6077
 6078
 6079
 6080
 6081
 6082
 6083
 6084
 6085
 6086
 6087
 6088
 6089
 6090
 6091
 6092
 6093
 6094
 6095
 6096
 6097
 6098
 6099
 6100
 6101
 6102
 6103
 6104
 6105
 6106
 6107
 6108
 6109
 6110
 6111
 6112
 6113
 6114
 6115
 6116
 6117
 6118
 6119
 6120
 6121
 6122
 6123
 6124
 6125
 6126
 6127
 6128
 6129
 6130
 6131
 6132
 6133
 6134
 6135
 6136
 6137
 6138
 6139
 6140
 6141
 6142
 6143
 6144
 6145
 6146
 6147
 6148
 6149
 6150
 6151
 6152
 6153
 6154
 6155
 6156
 6157
 6158
 6159
 6160
 6161
 6162
 6163
 6164
 6165
 6166
 6167
 6168
 6169
 6170
 6171
 6172
 6173
 6174
 6175
 6176
 6177
 6178
 6179
 6180
 6181
 6182
 6183
 6184
 6185
 6186
 6187
 6188
 6189
 6190
 6191
 6192
 6193
 6194
 6195
 6196
 6197
 6198
 6199
 6200
 6201
 6202
 6203
 6204
 6205
 6206
 6207
 6208
 6209
 6210
 6211
 6212
 6213
 6214
 6215
 6216
 6217
 6218
 6219
 6220
 6221
 6222
 6223
 6224
 6225
 6226
 6227
 6228
 6229
 6230
 6231
 6232
 6233
 6234
 6235
 6236
 6237
 6238
 6239
 6240
 6241
 6242
 6243
 6244
 6245
 6246
 6247
 6248
 6249
 6250
 6251
 6252
 6253
 6254
 6255
 6256
 6257
 6258
 6259
 6260
 6261
 6262
 6263
 6264
 6265
 6266
 6267
 6268
 6269
 6270
 6271
 6272
 6273
 6274
 6275
 6276
 6277
 6278
 6279
 6280
 6281
 6282
 6283
 6284
 6285
 6286
 6287
 6288
 6289
 6290
 6291
 6292
 6293
 6294
 6295
 6296
 6297
 6298
 6299
 6300
 6301
 6302
 6303
 6304
 6305
 6306
 6307
 6308
 6309
 6310
 6311
 6312
 6313
 6314
 6315
 6316
 6317
 6318
 6319
 6320
 6321
 6322
 6323
 6324
 6325
 6326
 6327
 6328
 6329
 6330
 6331
 6332
 6333
 6334
 6335
 6336
 6337
 6338
 6339
 6340
 6341
 6342
 6343
 6344
 6345
 6346
 6347
 6348
 6349
 6350
 6351
 6352
 6353
 6354
 6355
 6356
 6357
 6358
 6359
 6360
 6361
 6362
 6363
 6364
 6365
 6366
 6367
 6368
 6369
 6370
 6371
 6372
 6373
 6374
 6375
 6376
 6377
 6378
 6379
 6380
 6381
 6382
 6383
 6384
 6385
 6386
 6387
 6388
 6389
 6390
 6391
 6392
 6393
 6394
 6395
 6396
 6397
 6398
 6399
 6400
 6401
 6402
 6403
 6404
 6405
 6406
 6407
 6408
 6409
 6410
 6411
 6412
 6413
 6414
 6415
 6416
 6417
 6418
 6419
 6420
 6421
 6422
 6423
 6424
 6425
 6426
 6427
 6428
 6429
 6430
 6431
 6432
 6433
 6434
 6435
 6436
 6437
 6438
 6439
 6440
 6441
 6442
 6443
 6444
 6445
 6446
 6447
 6448
 6449
 6450
 6451
 6452
 6453
 6454
 6455
 6456
 6457
 6458
 6459
 6460
 6461
 6462
 6463
 6464
 6465
 6466
 6467
 6468
 6469
 6470
 6471
 6472
 6473
 6474
 6475
 6476
 6477
 6478
 6479
 6480
 6481
 6482
 6483
 6484
 6485
 6486
 6487
 6488
 6489
 6490
 6491
 6492
 6493
 6494
 6495
 6496
 6497
 6498
 6499
 6500
 6501
 6502
 6503
 6504
 6505
 6506
 6507
 6508
 6509
 6510
 6511
 6512
 6513
 6514
 6515
 6516
 6517
 6518
 6519
 6520
 6521
 6522
 6523
 6524
 6525
 6526
 6527
 6528
 6529
 6530
 6531
 6532
 6533
 6534
 6535
 6536
 6537
 6538
 6539
 6540
 6541
 6542
 6543
 6544
 6545
 6546
 6547
 6548
 6549
 6550
 6551
 6552
 6553
 6554
 6555
 6556
 6557
 6558
 6559
 6560
 6561
 6562
 6563
 6564
 6565
 6566
 6567
 6568
 6569
 6570
 6571
 6572
 6573
 6574
 6575
 6576
 6577
 6578
 6579
 6580
 6581
 6582
 6583
 6584
 6585
 6586
 6587
 6588
 6589
 6590
 6591
 6592
 6593
 6594
 6595
 6596
 6597
 6598
 6599
 6600
 6601
 6602
 6603
 6604
 6605
 6606
 6607
 6608
 6609
 6610
 6611
 6612
 6613
 6614
 6615
 6616
 6617
 6618
 6619
 6620
 6621
 6622
 6623
 6624
 6625
 6626
 6627
 6628
 6629
 6630
 6631
 6632
 6633
 6634
 6635
 6636
 6637
 6638
 6639
 6640
 6641
 6642
 6643
 6644
 6645
 6646
 6647
 6648
 6649
 6650
 6651
 6652
 6653
 6654
 6655
 6656
 6657
 6658
 6659
 6660
 6661
 6662
 6663
 6664
 6665
 6666
 6667
 6668
 6669
 6670
 6671
 6672
 6673
 6674
 6675
 6676
 6677
 6678
 6679
 6680
 6681
 6682
 6683
 6684
 6685
 6686
 6687
 6688
 6689
 6690
 6691
 6692
 6693
 6694
 6695
 6696
 6697
 6698
 6699
 6700
 6701
 6702
 6703
 6704
 6705
 6706
 6707
 6708
 6709
 6710
 6711
 6712
 6713
 6714
 6715
 6716
 6717
 6718
 6719
 6720
 6721
 6722
 6723
 6724
 6725
 6726
 6727
 6728
 6729
 6730
 6731
 6732
 6733
 6734
 6735
 6736
 6737
 6738
 6739
 6740
 6741
 6742
 6743
 6744
 6745
 6746
 6747
 6748
 6749
 6750
 6751
 6752
 6753
 6754
 6755
 6756
 6757
 6758
 6759
 6760
 6761
 6762
 6763
 6764
 6765
 6766
 6767
 6768
 6769
 6770
 6771
 6772
 6773
 6774
 6775
 6776
 6777
 6778
 6779
 6780
 6781
 6782
 6783
 6784
 6785
 6786
 6787
 6788
 6789
 6790
 6791
 6792
 6793
 6794
 6795
 6796
 6797
 6798
 6799
 6800
 6801
 6802
 6803
 6804
 6805
 6806
 6807
 6808
 6809
 6810
 6811
 6812
 6813
 6814
 6815
 6816
 6817
 6818
 6819
 6820
 6821
 6822
 6823
 6824
 6825
 6826
 6827
 6828
 6829
 6830
 6831
 6832
 6833
 6834
 6835
 6836
 6837
 6838
 6839
 6840
 6841
 6842
 6843
 6844
 6845
 6846
 6847
 6848
 6849
 6850
 6851
 6852
 6853
 6854
 6855
 6856
 6857
 6858
 6859
 6860
 6861
 6862
 6863
 6864
 6865
 6866
 6867
 6868
 6869
 6870
 6871
 6872
 6873
 6874
 6875
 6876
 6877
 6878
 6879
 6880
 6881
 6882
 6883
 6884
 6885
 6886
 6887
 6888
 6889
 6890
 6891
 6892
 6893
 6894
 6895
 6896
 6897
 6898
 6899
 6900
 6901
 6902
 6903
 6904
 6905
 6906
 6907
 6908
 6909
 6910
 6911
 6912
 6913
 6914
 6915
 6916
 6917
 6918
 6919
 6920
 6921
 6922
 6923
 6924
 6925
 6926
 6927
 6928
 6929
 6930
 6931
 6932
 6933
 6934
 6935
 6936
 6937
 6938
 6939
 6940
 6941
 6942
 6943
 6944
 6945
 6946
 6947
 6948
 6949
 6950
 6951
 6952
 6953
 6954
 6955
 6956
 6957
 6958
 6959
 6960
 6961
 6962
 6963
 6964
 6965
 6966
 6967
 6968
 6969
 6970
 6971
 6972
 6973
 6974
 6975
 6976
 6977
 6978
 6979
 6980
 6981
 6982
 6983
 6984
 6985
 6986
 6987
 6988
 6989
 6990
 6991
 6992
 6993
 6994
 6995
 6996
 6997
 6998
 6999
 7000
 7001
 7002
 7003
 7004
 7005
 7006
 7007
 7008
 7009
 7010
 7011
 7012
 7013
 7014
 7015
 7016
 7017
 7018
 7019
 7020
 7021
 7022
 7023
 7024
 7025
 7026
 7027
 7028
 7029
 7030
 7031
 7032
 7033
 7034
 7035
 7036
 7037
 7038
 7039
 7040
 7041
 7042
 7043
 7044
 7045
 7046
 7047
 7048
 7049
 7050
 7051
 7052
 7053
 7054
 7055
 7056
 7057
 7058
 7059
 7060
 7061
 7062
 7063
 7064
 7065
 7066
 7067
 7068
 7069
 7070
 7071
 7072
 7073
 7074
 7075
 7076
 7077
 7078
 7079
 7080
 7081
 7082
 7083
 7084
 7085
 7086
 7087
 7088
 7089
 7090
 7091
 7092
 7093
 7094
 7095
 7096
 7097
 7098
 7099
 7100
 7101
 7102
 7103
 7104
 7105
 7106
 7107
 7108
 7109
 7110
 7111
 7112
 7113
 7114
 7115
 7116
 7117
 7118
 7119
 7120
 7121
 7122
 7123
 7124
 7125
 7126
 7127
 7128
 7129
 7130
 7131
 7132
 7133
 7134
 7135
 7136
 7137
 7138
 7139
 7140
 7141
 7142
 7143
 7144
 7145
 7146
 7147
 7148
 7149
 7150
 7151
 7152
 7153
 7154
 7155
 7156
 7157
 7158
 7159
 7160
 7161
 7162
 7163
 7164
 7165
 7166
 7167
 7168
 7169
 7170
 7171
 7172
 7173
 7174
 7175
 7176
 7177
 7178
 7179
 7180
 7181
 7182
 7183
 7184
 7185
 7186
 7187
 7188
 7189
 7190
 7191
 7192
 7193
 7194
 7195
 7196
 7197
 7198
 7199
 7200
 7201
 7202
 7203
 7204
 7205
 7206
 7207
 7208
 7209
 7210
 7211
 7212
 7213
 7214
 7215
 7216
 7217
 7218
 7219
 7220
 7221
 7222
 7223
 7224
 7225
 7226
 7227
 7228
 7229
 7230
 7231
 7232
 7233
 7234
 7235
 7236
 7237
 7238
 7239
 7240
 7241
 7242
 7243
 7244
 7245
 7246
 7247
 7248
 7249
 7250
 7251
 7252
 7253
 7254
 7255
 7256
 7257
 7258
 7259
 7260
 7261
 7262
 7263
 7264
 7265
 7266
 7267
 7268
 7269
 7270
 7271
 7272
 7273
 7274
 7275
 7276
 7277
 7278
 7279
 7280
 7281
 7282
 7283
 7284
 7285
 7286
 7287
 7288
 7289
 7290
 7291
 7292
 7293
 7294
 7295
 7296
 7297
 7298
 7299
 7300
 7301
 7302
 7303
 7304
 7305
 7306
 7307
 7308
 7309
 7310
 7311
 7312
 7313
 7314
 7315
 7316
 7317
 7318
 7319
 7320
 7321
 7322
 7323
 7324
 7325
 7326
 7327
 7328
 7329
 7330
 7331
 7332
 7333
 7334
 7335
 7336
 7337
 7338
 7339
 7340
 7341
 7342
 7343
 7344
 7345
 7346
 7347
 7348
 7349
 7350
 7351
 7352
 7353
 7354
 7355
 7356
 7357
 7358
 7359
 7360
 7361
 7362
 7363
 7364
 7365
 7366
 7367
 7368
 7369
 7370
 7371
 7372
 7373
 7374
 7375
 7376
 7377
 7378
 7379
 7380
 7381
 7382
 7383
 7384
 7385
 7386
 7387
 7388
 7389
 7390
 7391
 7392
 7393
 7394
 7395
 7396
 7397
 7398
 7399
 7400
 7401
 7402
 7403
 7404
 7405
 7406
 7407
 7408
 7409
 7410
 7411
 7412
 7413
 7414
 7415
 7416
 7417
 7418
 7419
 7420
 7421
 7422
 7423
 7424
 7425
 7426
 7427
 7428
 7429
 7430
 7431
 7432
 7433
 7434
 7435
 7436
 7437
 7438
 7439
 7440
 7441
 7442
 7443
 7444
 7445
 7446
 7447
 7448
 7449
 7450
 7451
 7452
 7453
 7454
 7455
 7456
 7457
 7458
 7459
 7460
 7461
 7462
 7463
 7464
 7465
 7466
 7467
 7468
 7469
 7470
 7471
 7472
 7473
 7474
 7475
 7476
 7477
 7478
 7479
 7480
 7481
 7482
 7483
 7484
 7485
 7486
 7487
 7488
 7489
 7490
 7491
 7492
 7493
 7494
 7495
 7496
 7497
 7498
 7499
 7500
 7501
 7502
 7503
 7504
 7505
 7506
 7507
 7508
 7509
 7510
 7511
 7512
 7513
 7514
 7515
 7516
 7517
 7518
 7519
 7520
 7521
 7522
 7523
 7524
 7525
 7526
 7527
 7528
 7529
 7530
 7531
 7532
 7533
 7534
 7535
 7536
 7537
 7538
 7539
 7540
 7541
 7542
 7543
 7544
 7545
 7546
 7547
 7548
 7549
 7550
 7551
 7552
 7553
 7554
 7555
 7556
 7557
 7558
 7559
 7560
 7561
 7562
 7563
 7564
 7565
 7566
 7567
 7568
 7569
 7570
 7571
 7572
 7573
 7574
 7575
 7576
 7577
 7578
 7579
 7580
 7581
 7582
 7583
 7584
 7585
 7586
 7587
 7588
 7589
 7590
 7591
 7592
 7593
 7594
 7595
 7596
 7597
 7598
 7599
 7600
 7601
 7602
 7603
 7604
 7605
 7606
 7607
 7608
 7609
 7610
 7611
 7612
 7613
 7614
 7615
 7616
 7617
 7618
 7619
 7620
 7621
 7622
 7623
 7624
 7625
 7626
 7627
 7628
 7629
 7630
 7631
 7632
 7633
 7634
 7635
 7636
 7637
 7638
 7639
 7640
 7641
 7642
 7643
 7644
 7645
 7646
 7647
 7648
 7649
 7650
 7651
 7652
 7653
 7654
 7655
 7656
 7657
 7658
 7659
 7660
 7661
 7662
 7663
 7664
 7665
 7666
 7667
 7668
 7669
 7670
 7671
 7672
 7673
 7674
 7675
 7676
 7677
 7678
 7679
 7680
 7681
 7682
 7683
 7684
 7685
 7686
 7687
 7688
 7689
 7690
 7691
 7692
 7693
 7694
 7695
 7696
 7697
 7698
 7699
 7700
 7701
 7702
 7703
 7704
 7705
 7706
 7707
 7708
 7709
 7710
 7711
 7712
 7713
 7714
 7715
 7716
 7717
 7718
 7719
 7720
 7721
 7722
 7723
 7724
 7725
 7726
 7727
 7728
 7729
 7730
 7731
 7732
 7733
 7734
 7735
 7736
 7737
 7738
 7739
 7740
 7741
 7742
 7743
 7744
 7745
 7746
 7747
 7748
 7749
 7750
 7751
 7752
 7753
 7754
 7755
 7756
 7757
 7758
 7759
 7760
 7761
 7762
 7763
 7764
 7765
 7766
 7767
 7768
 7769
 7770
 7771
 7772
 7773
 7774
 7775
 7776
 7777
 7778
 7779
 7780
 7781
 7782
 7783
 7784
 7785
 7786
 7787
 7788
 7789
 7790
 7791
 7792
 7793
 7794
 7795
 7796
 7797
 7798
 7799
 7800
 7801
 7802
 7803
 7804
 7805
 7806
 7807
 7808
 7809
 7810
 7811
 7812
 7813
 7814
 7815
 7816
 7817
 7818
 7819
 7820
 7821
 7822
 7823
 7824
 7825
 7826
 7827
 7828
 7829
 7830
 7831
 7832
 7833
 7834
 7835
 7836
 7837
 7838
 7839
 7840
 7841
 7842
 7843
 7844
 7845
 7846
 7847
 7848
 7849
 7850
 7851
 7852
 7853
 7854
 7855
 7856
 7857
 7858
 7859
 7860
 7861
 7862
 7863
 7864
 7865
 7866
 7867
 7868
 7869
 7870
 7871
 7872
 7873
 7874
 7875
 7876
 7877
 7878
 7879
 7880
 7881
 7882
 7883
 7884
 7885
 7886
 7887
 7888
 7889
 7890
 7891
 7892
 7893
 7894
 7895
 7896
 7897
 7898
 7899
 7900
 7901
 7902
 7903
 7904
 7905
 7906
 7907
 7908
 7909
 7910
 7911
 7912
 7913
 7914
 7915
 7916
 7917
 7918
 7919
 7920
 7921
 7922
 7923
 7924
 7925
 7926
 7927
 7928
 7929
 7930
 7931
 7932
 7933
 7934
 7935
 7936
 7937
 7938
 7939
 7940
 7941
 7942
 7943
 7944
 7945
 7946
 7947
 7948
 7949
 7950
 7951
 7952
 7953
 7954
 7955
 7956
 7957
 7958
 7959
 7960
 7961
 7962
 7963
 7964
 7965
 7966
 7967
 7968
 7969
 7970
 7971
 7972
 7973
 7974
 7975
 7976
 7977
 7978
 7979
 7980
 7981
 7982
 7983
 7984
 7985
 7986
 7987
 7988
 7989
 7990
 7991
 7992
 7993
 7994
 7995
 7996
 7997
 7998
 7999
 8000
 8001
 8002
 8003
 8004
 8005
 8006
 8007
 8008
 8009
 8010
 8011
 8012
 8013
 8014
 8015
 8016
 8017
 8018
 8019
 8020
 8021
 8022
 8023
 8024
 8025
 8026
 8027
 8028
 8029
 8030
 8031
 8032
 8033
 8034
 8035
 8036
 8037
 8038
 8039
 8040
 8041
 8042
 8043
 8044
 8045
 8046
 8047
 8048
 8049
 8050
 8051
 8052
 8053
 8054
 8055
 8056
 8057
 8058
 8059
 8060
 8061
 8062
 8063
 8064
 8065
 8066
 8067
 8068
 8069
 8070
 8071
 8072
 8073
 8074
 8075
 8076
 8077
 8078
 8079
 8080
 8081
 8082
 8083
 8084
 8085
 8086
 8087
 8088
 8089
 8090
 8091
 8092
 8093
 8094
 8095
 8096
 8097
 8098
 8099
 8100
 8101
 8102
 8103
 8104
 8105
 8106
 8107
 8108
 8109
 8110
 8111
 8112
 8113
 8114
 8115
 8116
 8117
 8118
 8119
 8120
 8121
 8122
 8123
 8124
 8125
 8126
 8127
 8128
 8129
 8130
 8131
 8132
 8133
 8134
 8135
 8136
 8137
 8138
 8139
 8140
 8141
 8142
 8143
 8144
 8145
 8146
 8147
 8148
 8149
 8150
 8151
 8152
 8153
 8154
 8155
 8156
 8157
 8158
 8159
 8160
 8161
 8162
 8163
 8164
 8165
 8166
 8167
 8168
 8169
 8170
 8171
 8172
 8173
 8174
 8175
 8176
 8177
 8178
 8179
 8180
 8181
 8182
 8183
 8184
 8185
 8186
 8187
 8188
 8189
 8190
 8191
 8192
 8193
 8194
 8195
 8196
 8197
 8198
 8199
 8200
 8201
 8202
 8203
 8204
 8205
 8206
 8207
 8208
 8209
 8210
 8211
 8212
 8213
 8214
 8215
 8216
 8217
 8218
 8219
 8220
 8221
 8222
 8223
 8224
 8225
 8226
 8227
 8228
 8229
 8230
 8231
 8232
 8233
 8234
 8235
 8236
 8237
 8238
 8239
 8240
 8241
 8242
 8243
 8244
 8245
 8246
 8247
 8248
 8249
 8250
 8251
 8252
 8253
 8254
 8255
 8256
 8257
 8258
 8259
 8260
 8261
 8262
 8263
 8264
 8265
 8266
 8267
 8268
 8269
 8270
 8271
 8272
 8273
 8274
 8275
 8276
 8277
 8278
 8279
 8280
 8281
 8282
 8283
 8284
 8285
 8286
 8287
 8288
 8289
 8290
 8291
 8292
 8293
 8294
 8295
 8296
 8297
 8298
 8299
 8300
 8301
 8302
 8303
 8304
 8305
 8306
 8307
 8308
 8309
 8310
 8311
 8312
 8313
 8314
 8315
 8316
 8317
 8318
 8319
 8320
 8321
 8322
 8323
 8324
 8325
 8326
 8327
 8328
 8329
 8330
 8331
 8332
 8333
 8334
 8335
 8336
 8337
 8338
 8339
 8340
 8341
 8342
 8343
 8344
 8345
 8346
 8347
 8348
 8349
 8350
 8351
 8352
 8353
 8354
 8355
 8356
 8357
 8358
 8359
 8360
 8361
 8362
 8363
 8364
 8365
 8366
 8367
 8368
 8369
 8370
 8371
 8372
 8373
 8374
 8375
 8376
 8377
 8378
 8379
 8380
 8381
 8382
 8383
 8384
 8385
 8386
 8387
 8388
 8389
 8390
 8391
 8392
 8393
 8394
 8395
 8396
 8397
 8398
 8399
 8400
 8401
 8402
 8403
 8404
 8405
 8406
 8407
 8408
 8409
 8410
 8411
 8412
 8413
 8414
 8415
 8416
 8417
 8418
 8419
 8420
 8421
 8422
 8423
 8424
 8425
 8426
 8427
 8428
 8429
 8430
 8431
 8432
 8433
 8434
 8435
 8436
 8437
 8438
 8439
 8440
 8441
 8442
 8443
 8444
 8445
 8446
 8447
 8448
 8449
 8450
 8451
 8452
 8453
 8454
 8455
 8456
 8457
 8458
 8459
 8460
 8461
 8462
 8463
 8464
 8465
 8466
 8467
 8468
 8469
 8470
 8471
 8472
 8473
 8474
 8475
 8476
 8477
 8478
 8479
 8480
 8481
 8482
 8483
 8484
 8485
 8486
 8487
 8488
 8489
 8490
 8491
 8492
 8493
 8494
 8495
 8496
 8497
 8498
 8499
 8500
 8501
 8502
 8503
 8504
 8505
 8506
 8507
 8508
 8509
 8510
 8511
 8512
 8513
 8514
 8515
 8516
 8517
 8518
 8519
 8520
 8521
 8522
 8523
 8524
 8525
 8526
 8527
 8528
 8529
 8530
 8531
 8532
 8533
 8534
 8535
 8536
 8537
 8538
 8539
 8540
 8541
 8542
 8543
 8544
 8545
 8546
 8547
 8548
 8549
 8550
 8551
 8552
 8553
 8554
 8555
 8556
 8557
 8558
 8559
 8560
 8561
 8562
 8563
 8564
 8565
 8566
 8567
 8568
 8569
 8570
 8571
 8572
 8573
 8574
 8575
 8576
 8577
 8578
 8579
 8580
 8581
 8582
 8583
 8584
 8585
 8586
 8587
 8588
 8589
 8590
 8591
 8592
 8593
 8594
 8595
 8596
 8597
 8598
 8599
 8600
 8601
 8602
 8603
 8604
 8605
 8606
 8607
 8608
 8609
 8610
 8611
 8612
 8613
 8614
 8615
 8616
 8617
 8618
 8619
 8620
 8621
 8622
 8623
 8624
 8625
 8626
 8627
 8628
 8629
 8630
 8631
 8632
 8633
 8634
 8635
 8636
 8637
 8638
 8639
 8640
 8641
 8642
 8643
 8644
 8645
 8646
 8647
 8648
 8649
 8650
 8651
 8652
 8653
 8654
 8655
 8656
 8657
 8658
 8659
 8660
 8661
 8662
 8663
 8664
 8665
 8666
 8667
 8668
 8669
 8670
 8671
 8672
 8673
 8674
 8675
 8676
 8677
 8678
 8679
 8680
 8681
 8682
 8683
 8684
 8685
 8686
 8687
 8688
 8689
 8690
 8691
 8692
 8693
 8694
 8695
 8696
 8697
 8698
 8699
 8700
 8701
 8702
 8703
 8704
 8705
 8706
 8707
 8708
 8709
 8710
 8711
 8712
 8713
 8714
 8715
 8716
 8717
 8718
 8719
 8720
 8721
 8722
 8723
 8724
 8725
 8726
 8727
 8728
 8729
 8730
 8731
 8732
 8733
 8734
 8735
 8736
 8737
 8738
 8739
 8740
 8741
 8742
 8743
 8744
 8745
 8746
 8747
 8748
 8749
 8750
 8751
 8752
 8753
 8754
 8755
 8756
 8757
 8758
 8759
 8760
 8761
 8762
 8763
 8764
 8765
 8766
 8767
 8768
 8769
 8770
 8771
 8772
 8773
 8774
 8775
 8776
 8777
 8778
 8779
 8780
 8781
 8782
 8783
 8784
 8785
 8786
 8787
 8788
 8789
 8790
 8791
 8792
 8793
 8794
 8795
 8796
 8797
 8798
 8799
 8800
 8801
 8802
 8803
 8804
 8805
 8806
 8807
 8808
 8809
 8810
 8811
 8812
 8813
 8814
 8815
 8816
 8817
 8818
 8819
 8820
 8821
 8822
 8823
 8824
 8825
 8826
 8827
 8828
 8829
 8830
 8831
 8832
 8833
 8834
 8835
 8836
 8837
 8838
 8839
 8840
 8841
 8842
 8843
 8844
 8845
 8846
 8847
 8848
 8849
 8850
 8851
 8852
 8853
 8854
 8855
 8856
 8857
 8858
 8859
 8860
 8861
 8862
 8863
 8864
 8865
 8866
 8867
 8868
 8869
 8870
 8871
 8872
 8873
 8874
 8875
 8876
 8877
 8878
 8879
 8880
 8881
 8882
 8883
 8884
 8885
 8886
 8887
 8888
 8889
 8890
 8891
 8892
 8893
 8894
 8895
 8896
 8897
 8898
 8899
 8900
 8901
 8902
 8903
 8904
 8905
 8906
 8907
 8908
 8909
 8910
 8911
 8912
 8913
 8914
 8915
 8916
 8917
 8918
 8919
 8920
 8921
 8922
 8923
 8924
 8925
 8926
 8927
 8928
 8929
 8930
 8931
 8932
 8933
 8934
 8935
 8936
 8937
 8938
 8939
 8940
 8941
 8942
 8943
 8944
 8945
 8946
 8947
 8948
 8949
 8950
 8951
 8952
 8953
 8954
 8955
 8956
 8957
 8958
 8959
 8960
 8961
 8962
 8963
 8964
 8965
 8966
 8967
 8968
 8969
 8970
 8971
 8972
 8973
 8974
 8975
 8976
 8977
 8978
 8979
 8980
 8981
 8982
 8983
 8984
 8985
 8986
 8987
 8988
 8989
 8990
 8991
 8992
 8993
 8994
 8995
 8996
 8997
 8998
 8999
 9000
 9001
 9002
 9003
 9004
 9005
 9006
 9007
 9008
 9009
 9010
 9011
 9012
 9013
 9014
 9015
 9016
 9017
 9018
 9019
 9020
 9021
 9022
 9023
 9024
 9025
 9026
 9027
 9028
 9029
 9030
 9031
 9032
 9033
 9034
 9035
 9036
 9037
 9038
 9039
 9040
 9041
 9042
 9043
 9044
 9045
 9046
 9047
 9048
 9049
 9050
 9051
 9052
 9053
 9054
 9055
 9056
 9057
 9058
 9059
 9060
 9061
 9062
 9063
 9064
 9065
 9066
 9067
 9068
 9069
 9070
 9071
 9072
 9073
 9074
 9075
 9076
 9077
 9078
 9079
 9080
 9081
 9082
 9083
 9084
 9085
 9086
 9087
 9088
 9089
 9090
 9091
 9092
 9093
 9094
 9095
 9096
 9097
 9098
 9099
 9100
 9101
 9102
 9103
 9104
 9105
 9106
 9107
 9108
 9109
 9110
 9111
 9112
 9113
 9114
 9115
 9116
 9117
 9118
 9119
 9120
 9121
 9122
 9123
 9124
 9125
 9126
 9127
 9128
 9129
 9130
 9131
 9132
 9133
 9134
 9135
 9136
 9137
 9138
 9139
 9140
 9141
 9142
 9143
 9144
 9145
 9146
 9147
 9148
 9149
 9150
 9151
 9152
 9153
 9154
 9155
 9156
 9157
 9158
 9159
 9160
 9161
 9162
 9163
 9164
 9165
 9166
 9167
 9168
 9169
 9170
 9171
 9172
 9173
 9174
 9175
 9176
 9177
 9178
 9179
 9180
 9181
 9182
 9183
 9184
 9185
 9186
 9187
 9188
 9189
 9190
 9191
 9192
 9193
 9194
 9195
 9196
 9197
 9198
 9199
 9200
 9201
 9202
 9203
 9204
 9205
 9206
 9207
 9208
 9209
 9210
 9211
 9212
 9213
 9214
 9215
 9216
 9217
 9218
 9219
 9220
 9221
 9222
 9223
 9224
 9225
 9226
 9227
 9228
 9229
 9230
 9231
 9232
 9233
 9234
 9235
 9236
 9237
 9238
 9239
 9240
 9241
 9242
 9243
 9244
 9245
 9246
 9247
 9248
 9249
 9250
 9251
 9252
 9253
 9254
 9255
 9256
 9257
 9258
 9259
 9260
 9261
 9262
 9263
 9264
 9265
 9266
 9267
 9268
 9269
 9270
 9271
 9272
 9273
 9274
 9275
 9276
 9277
 9278
 9279
 9280
 9281
 9282
 9283
 9284
 9285
 9286
 9287
 9288
 9289
 9290
 9291
 9292
 9293
 9294
 9295
 9296
 9297
 9298
 9299
 9300
 9301
 9302
 9303
 9304
 9305
 9306
 9307
 9308
 9309
 9310
 9311
 9312
 9313
 9314
 9315
 9316
 9317
 9318
 9319
 9320
 9321
 9322
 9323
 9324
 9325
 9326
 9327
 9328
 9329
 9330
 9331
 9332
 9333
 9334
 9335
 9336
 9337
 9338
 9339
 9340
 9341
 9342
 9343
 9344
 9345
 9346
 9347
 9348
 9349
 9350
 9351
 9352
 9353
 9354
 9355
 9356
 9357
 9358
 9359
 9360
 9361
 9362
 9363
 9364
 9365
 9366
 9367
 9368
 9369
 9370
 9371
 9372
 9373
 9374
 9375
 9376
 9377
 9378
 9379
 9380
 9381
 9382
 9383
 9384
 9385
 9386
 9387
 9388
 9389
 9390
 9391
 9392
 9393
 9394
 9395
 9396
 9397
 9398
 9399
 9400
 9401
 9402
 9403
 9404
 9405
 9406
 9407
 9408
 9409
 9410
 9411
 9412
 9413
 9414
 9415
 9416
 9417
 9418
 9419
 9420
 9421
 9422
 9423
 9424
 9425
 9426
 9427
 9428
 9429
 9430
 9431
 9432
 9433
 9434
 9435
 9436
 9437
 9438
 9439
 9440
 9441
 9442
 9443
 9444
 9445
 9446
 9447
 9448
 9449
 9450
 9451
 9452
 9453
 9454
 9455
 9456
 9457
 9458
 9459
 9460
 9461
 9462
 9463
 9464
 9465
 9466
 9467
 9468
 9469
 9470
 9471
 9472
 9473
 9474
 9475
 9476
 9477
 9478
 9479
 9480
 9481
 9482
 9483
 9484
 9485
 9486
 9487
 9488
 9489
 9490
 9491
 9492
 9493
 9494
 9495
 9496
 9497
 9498
 9499
 9500
 9501
 9502
 9503
 9504
 9505
 9506
 9507
 9508
 9509
 9510
 9511
 9512
 9513
 9514
 9515
 9516
 9517
 9518
 9519
 9520
 9521
 9522
 9523
 9524
 9525
 9526
 9527
 9528
 9529
 9530
 9531
 9532
 9533
 9534
 9535
 9536
 9537
 9538
 9539
 9540
 9541
 9542
 9543
 9544
 9545
 9546
 9547
 9548
 9549
 9550
 9551
 9552
 9553
 9554
 9555
 9556
 9557
 9558
 9559
 9560
 9561
 9562
 9563
 9564
 9565
 9566
 9567
 9568
 9569
 9570
 9571
 9572
 9573
 9574
 9575
 9576
 9577
 9578
 9579
 9580
 9581
 9582
 9583
 9584
 9585
 9586
 9587
 9588
 9589
 9590
 9591
 9592
 9593
 9594
 9595
 9596
 9597
 9598
 9599
 9600
 9601
 9602
 9603
 9604
 9605
 9606
 9607
 9608
 9609
 9610
 9611
 9612
 9613
 9614
 9615
 9616
 9617
 9618
 9619
 9620
 9621
 9622
 9623
 9624
 9625
 9626
 9627
 9628
 9629
 9630
 9631
 9632
 9633
 9634
 9635
 9636
 9637
 9638
 9639
 9640
 9641
 9642
 9643
 9644
 9645
 9646
 9647
 9648
 9649
 9650
 9651
 9652
 9653
 9654
 9655
 9656
 9657
 9658
 9659
 9660
 9661
 9662
 9663
 9664
 9665
 9666
 9667
 9668
 9669
 9670
 9671
 9672
 9673
 9674
 9675
 9676
 9677
 9678
 9679
 9680
 9681
 9682
 9683
 9684
 9685
 9686
 9687
 9688
 9689
 9690
 9691
 9692
 9693
 9694
 9695
 9696
 9697
 9698
 9699
 9700
 9701
 9702
 9703
 9704
 9705
 9706
 9707
 9708
 9709
 9710
 9711
 9712
 9713
 9714
 9715
 9716
 9717
 9718
 9719
 9720
 9721
 9722
 9723
 9724
 9725
 9726
 9727
 9728
 9729
 9730
 9731
 9732
 9733
 9734
 9735
 9736
 9737
 9738
 9739
 9740
 9741
 9742
 9743
 9744
 9745
 9746
 9747
 9748
 9749
 9750
 9751
 9752
 9753
 9754
 9755
 9756
 9757
 9758
 9759
 9760
 9761
 9762
 9763
 9764
 9765
 9766
 9767
 9768
 9769
 9770
 9771
 9772
 9773
 9774
 9775
 9776
 9777
 9778
 9779
 9780
 9781
 9782
 9783
 9784
 9785
 9786
 9787
 9788
 9789
 9790
 9791
 9792
 9793
 9794
 9795
 9796
 9797
 9798
 9799
 9800
 9801
 9802
 9803
 9804
 9805
 9806
 9807
 9808
 9809
 9810
 9811
 9812
 9813
 9814
 9815
 9816
 9817
 9818
 9819
 9820
 9821
 9822
 9823
 9824
 9825
 9826
 9827
 9828
 9829
 9830
 9831
 9832
 9833
 9834
 9835
 9836
 9837
 9838
 9839
 9840
 9841
 9842
 9843
 9844
 9845
 9846
 9847
 9848
 9849
 9850
 9851
 9852
 9853
 9854
 9855
 9856
 9857
 9858
 9859
 9860
 9861
 9862
 9863
 9864
 9865
 9866
 9867
 9868
 9869
 9870
 9871
 9872
 9873
 9874
 9875
 9876
 9877
 9878
 9879
 9880
 9881
 9882
 9883
 9884
 9885
 9886
 9887
 9888
 9889
 9890
 9891
 9892
 9893
 9894
 9895
 9896
 9897
 9898
 9899
 9900
 9901
 9902
 9903
 9904
 9905
 9906
 9907
 9908
 9909
 9910
 9911
 9912
 9913
 9914
 9915
 9916
 9917
 9918
 9919
 9920
 9921
 9922
 9923
 9924
 9925
 9926
 9927
 9928
 9929
 9930
 9931
 9932
 9933
 9934
 9935
 9936
 9937
 9938
 9939
 9940
 9941
 9942
 9943
 9944
 9945
 9946
 9947
 9948
 9949
 9950
 9951
 9952
 9953
 9954
 9955
 9956
 9957
 9958
 9959
 9960
 9961
 9962
 9963
 9964
 9965
 9966
 9967
 9968
 9969
 9970
 9971
 9972
 9973
 9974
 9975
 9976
 9977
 9978
 9979
 9980
 9981
 9982
 9983
 9984
 9985
 9986
 9987
 9988
 9989
 9990
 9991
 9992
 9993
 9994
 9995
 9996
 9997
 9998
 9999
 10000
 10001
 10002
 10003
 10004
 10005
 10006
 10007
 10008
 10009
 10010
 10011
 10012
 10013
 10014
 10015
 10016
 10017
 10018
 10019
 10020
 10021
 10022
 10023
 10024
 10025
 10026
 10027
 10028
 10029
 10030
 10031
 10032
 10033
 10034
 10035
 10036
 10037
 10038
 10039
 10040
 10041
 10042
 10043
 10044
 10045
 10046
 10047
 10048
 10049
 10050
 10051
 10052
 10053
 10054
 10055
 10056
 10057
 10058
 10059
 10060
 10061
 10062
 10063
 10064
 10065
 10066
 10067
 10068
 10069
 10070
 10071
 10072
 10073
 10074
 10075
 10076
 10077
 10078
 10079
 10080
 10081
 10082
 10083
 10084
 10085
 10086
 10087
 10088
 10089
 10090
 10091
 10092
 10093
 10094
 10095
 10096
 10097
 10098
 10099
 10100
 10101
 10102
 10103
 10104
 10105
 10106
 10107
 10108
 10109
 10110
 10111
 10112
 10113
 10114
 10115
 10116
 10117
 10118
 10119
 10120
 10121
 10122
 10123
 10124
 10125
 10126
 10127
 10128
 10129
 10130
 10131
 10132
 10133
 10134
 10135
 10136
 10137
 10138
 10139
 10140
 10141
 10142
 10143
 10144
 10145
 10146
 10147
 10148
 10149
 10150
 10151
 10152
 10153
 10154
 10155
 10156
 10157
 10158
 10159
 10160
 10161
 10162
 10163
 10164
 10165
 10166
 10167
 10168
 10169
 10170
 10171
 10172
 10173
 10174
 10175
 10176
 10177
 10178
 10179
 10180
 10181
 10182
 10183
 10184
 10185
 10186
 10187
 10188
 10189
 10190
 10191
 10192
 10193
 10194
 10195
 10196
 10197
 10198
 10199
 10200
 10201
 10202
 10203
 10204
 10205
 10206
 10207
 10208
 10209
 10210
 10211
 10212
 10213
 10214
 10215
 10216
 10217
 10218
 10219
 10220
 10221
 10222
 10223
 10224
 10225
 10226
 10227
 10228
 10229
 10230
 10231
 10232
 10233
 10234
 10235
 10236
 10237
 10238
 10239
 10240
 10241
 10242
 10243
 10244
 10245
 10246
 10247
 10248
 10249
 10250
 10251
 10252
 10253
 10254
 10255
 10256
 10257
 10258
 10259
 10260
 10261
 10262
 10263
 10264
 10265
 10266
 10267
 10268
 10269
 10270
 10271
 10272
 10273
 10274
 10275
 10276
 10277
 10278
 10279
 10280
 10281
 10282
 10283
 10284
 10285
 10286
 10287
 10288
 10289
 10290
 10291
 10292
 10293
 10294
 10295
 10296
 10297
 10298
 10299
 10300
 10301
 10302
 10303
 10304
 10305
 10306
 10307
 10308
 10309
 10310
 10311
 10312
 10313
 10314
 10315
 10316
 10317
 10318
 10319
 10320
 10321
 10322
 10323
 10324
 10325
 10326
 10327
 10328
 10329
 10330
 10331
 10332
 10333
 10334
 10335
 10336
 10337
 10338
 10339
 10340
 10341
 10342
 10343
 10344
 10345
 10346
 10347
 10348
 10349
 10350
 10351
 10352
 10353
 10354
 10355
 10356
 10357
 10358
 10359
 10360
 10361
 10362
 10363
 10364
 10365
 10366
 10367
 10368
 10369
 10370
 10371
 10372
 10373
 10374
 10375
 10376
 10377
 10378
 10379
 10380
 10381
 10382
 10383
 10384
 10385
 10386
 10387
 10388
 10389
 10390
 10391
 10392
 10393
 10394
 10395
 10396
 10397
 10398
 10399
 10400
 10401
 10402
 10403
 10404
 10405
 10406
 10407
 10408
 10409
 10410
 10411
 10412
 10413
 10414
 10415
 10416
 10417
 10418
 10419
 10420
 10421
 10422
 10423
 10424
 10425
 10426
 10427
 10428
 10429
 10430
 10431
 10432
 10433
 10434
 10435
 10436
 10437
 10438
 10439
 10440
 10441
 10442
 10443
 10444
 10445
 10446
 10447
 10448
 10449
 10450
 10451
 10452
 10453
 10454
 10455
 10456
 10457
 10458
 10459
 10460
 10461
 10462
 10463
 10464
 10465
 10466
 10467
 10468
 10469
 10470
 10471
 10472
 10473
 10474
 10475
 10476
 10477
 10478
 10479
 10480
 10481
 10482
 10483
 10484
 10485
 10486
 10487
 10488
 10489
 10490
 10491
 10492
 10493
 10494
 10495
 10496
 10497
 10498
 10499
 10500
 10501
 10502
 10503
 10504
 10505
 10506
 10507
 10508
 10509
 10510
 10511
 10512
 10513
 10514
 10515
 10516
 10517
 10518
 10519
 10520
 10521
 10522
 10523
 10524
 10525
 10526
 10527
 10528
 10529
 10530
 10531
 10532
 10533
 10534
 10535
 10536
 10537
 10538
 10539
 10540
 10541
 10542
 10543
 10544
 10545
 10546
 10547
 10548
 10549
 10550
 10551
 10552
 10553
 10554
 10555
 10556
 10557
 10558
 10559
 10560
 10561
 10562
 10563
 10564
 10565
 10566
 10567
 10568
 10569
 10570
 10571
 10572
 10573
 10574
 10575
 10576
 10577
 10578
 10579
 10580
 10581
 10582
 10583
 10584
 10585
 10586
 10587
 10588
 10589
 10590
 10591
 10592
 10593
 10594
 10595
 10596
 10597
 10598
 10599
 10600
 10601
 10602
 10603
 10604
 10605
 10606
 10607
 10608
 10609
 10610
 10611
 10612
 10613
 10614
 10615
 10616
 10617
 10618
 10619
 10620
 10621
 10622
 10623
 10624
 10625
 10626
 10627
 10628
 10629
 10630
 10631
 10632
 10633
 10634
 10635
 10636
 10637
 10638
 10639
 10640
 10641
 10642
 10643
 10644
 10645
 10646
 10647
 10648
 10649
 10650
 10651
 10652
 10653
 10654
 10655
 10656
 10657
 10658
 10659
 10660
 10661
 10662
 10663
 10664
 10665
 10666
 10667
 10668
 10669
 10670
 10671
 10672
 10673
 10674
 10675
 10676
 10677
 10678
 10679
 10680
 10681
 10682
 10683
 10684
 10685
 10686
 10687
 10688
 10689
 10690
 10691
 10692
 10693
 10694
 10695
 10696
 10697
 10698
 10699
 10700
 10701
 10702
 10703
 10704
 10705
 10706
 10707
 10708
 10709
 10710
 10711
 10712
 10713
 10714
 10715
 10716
 10717
 10718
 10719
 10720
 10721
 10722
 10723
 10724
 10725
 10726
 10727
 10728
 10729
 10730
 10731
 10732
 10733
 10734
 10735
 10736
 10737
 10738
 10739
 10740
 10741
 10742
 10743
 10744
 10745
 10746
 10747
 10748
 10749
 10750
 10751
 10752
 10753
 10754
 10755
 10756
 10757
 10758
 10759
 10760
 10761
 10762
 10763
 10764
 10765
 10766
 10767
 10768
 10769
 10770
 10771
 10772
 10773
 10774
 10775
 10776
 10777
 10778
 10779
 10780
 10781
 10782
 10783
 10784
 10785
 10786
 10787
 10788
 10789
 10790
 10791
 10792
 10793
 10794
 10795
 10796
 10797
 10798
 10799
 10800
 10801
 10802
 10803
 10804
 10805
 10806
 10807
 10808
 10809
 10810
 10811
 10812
 10813
 10814
 10815
 10816
 10817
 10818
 10819
 10820
 10821
 10822
 10823
 10824
 10825
 10826
 10827
 10828
 10829
 10830
 10831
 10832
 10833
 10834
 10835
 10836
 10837
 10838
 10839
 10840
 10841
 10842
 10843
 10844
 10845
 10846
 10847
 10848
 10849
 10850
 10851
 10852
 10853
 10854
 10855
 10856
 10857
 10858
 10859
 10860
 10861
 10862
 10863
 10864
 10865
 10866
 10867
 10868
 10869
 10870
 10871
 10872
 10873
 10874
 10875
 10876
 10877
 10878
 10879
 10880
 10881
 10882
 10883
 10884
 10885
 10886
 10887
 10888
 10889
 10890
 10891
 10892
 10893
 10894
 10895
 10896
 10897
 10898
 10899
 10900
 10901
 10902
 10903
 10904
 10905
 10906
 10907
 10908
 10909
 10910
 10911
 10912
 10913
 10914
 10915
 10916
 10917
 10918
 10919
 10920
 10921
 10922
 10923
 10924
 10925
 10926
 10927
 10928
 10929
 10930
 10931
 10932
 10933
 10934
 10935
 10936
 10937
 10938
 10939
 10940
 10941
 10942
 10943
 10944
 10945
 10946
 10947
 10948
 10949
 10950
 10951
 10952
 10953
 10954
 10955
 10956
 10957
 10958
 10959
 10960
 10961
 10962
 10963
 10964
 10965
 10966
 10967
 10968
 10969
 10970
 10971
 10972
 10973
 10974
 10975
 10976
 10977
 10978
 10979
 10980
 10981
 10982
 10983
 10984
 10985
 10986
 10987
 10988
 10989
 10990
 10991
 10992
 10993
 10994
 10995
 10996
 10997
 10998
 10999
 11000
 11001
 11002
 11003
 11004
 11005
 11006
 11007
 11008
 11009
 11010
 11011
 11012
 11013
 11014
 11015
 11016
 11017
 11018
 11019
 11020
 11021
 11022
 11023
 11024
 11025
 11026
 11027
 11028
 11029
 11030
 11031
 11032
 11033
 11034
 11035
 11036
 11037
 11038
 11039
 11040
 11041
 11042
 11043
 11044
 11045
 11046
 11047
 11048
 11049
 11050
 11051
 11052
 11053
 11054
 11055
 11056
 11057
 11058
 11059
 11060
 11061
 11062
 11063
 11064
 11065
 11066
 11067
 11068
 11069
 11070
 11071
 11072
 11073
 11074
 11075
 11076
 11077
 11078
 11079
 11080
 11081
 11082
 11083
 11084
 11085
 11086
 11087
 11088
 11089
 11090
 11091
 11092
 11093
 11094
 11095
 11096
 11097
 11098
 11099
 11100
 11101
 11102
 11103
 11104
 11105
 11106
 11107
 11108
 11109
 11110
 11111
 11112
 11113
 11114
 11115
 11116
 11117
 11118
 11119
 11120
 11121
 11122
 11123
 11124
 11125
 11126
 11127
 11128
 11129
 11130
 11131
 11132
 11133
 11134
 11135
 11136
 11137
 11138
 11139
 11140
 11141
 11142
 11143
 11144
 11145
 11146
 11147
 11148
 11149
 11150
 11151
 11152
 11153
 11154
 11155
 11156
 11157
 11158
 11159
 11160
 11161
 11162
 11163
 11164
 11165
 11166
 11167
 11168
 11169
 11170
 11171
 11172
 11173
 11174
 11175
 11176
 11177
 11178
 11179
 11180
 11181
 11182
 11183
 11184
 11185
 11186
 11187
 11188
 11189
 11190
 11191
 11192
 11193
 11194
 11195
 11196
 11197
 11198
 11199
 11200
 11201
 11202
 11203
 11204
 11205
 11206
 11207
 11208
 11209
 11210
 11211
 11212
 11213
 11214
 11215
 11216
 11217
 11218
 11219
 11220
 11221
 11222
 11223
 11224
 11225
 11226
 11227
 11228
 11229
 11230
 11231
 11232
 11233
 11234
 11235
 11236
 11237
 11238
 11239
 11240
 11241
 11242
 11243
 11244
 11245
 11246
 11247
 11248
 11249
 11250
 11251
 11252
 11253
 11254
 11255
 11256
 11257
 11258
 11259
 11260
 11261
 11262
 11263
 11264
 11265
 11266
 11267
 11268
 11269
 11270
 11271
 11272
 11273
 11274
 11275
 11276
 11277
 11278
 11279
 11280
 11281
 11282
 11283
 11284
 11285
 11286
 11287
 11288
 11289
 11290
 11291
 11292
 11293
 11294
 11295
 11296
 11297
 11298
 11299
 11300
 11301
 11302
 11303
 11304
 11305
 11306
 11307
 11308
 11309
 11310
 11311
 11312
 11313
 11314
 11315
 11316
 11317
 11318
 11319
 11320
 11321
 11322
 11323
 11324
 11325
 11326
 11327
 11328
 11329
 11330
 11331
 11332
 11333
 11334
 11335
 11336
 11337
 11338
 11339
 11340
 11341
 11342
 11343
 11344
 11345
 11346
 11347
 11348
 11349
 11350
 11351
 11352
 11353
 11354
 11355
 11356
 11357
 11358
 11359
 11360
 11361
 11362
 11363
 11364
 11365
 11366
 11367
 11368
 11369
 11370
 11371
 11372
 11373
 11374
 11375
 11376
 11377
 11378
 11379
 11380
 11381
 11382
 11383
 11384
 11385
 11386
 11387
 11388
 11389
 11390
 11391
 11392
 11393
 11394
 11395
 11396
 11397
 11398
 11399
 11400
 11401
 11402
 11403
 11404
 11405
 11406
 11407
 11408
 11409
 11410
 11411
 11412
 11413
 11414
 11415
 11416
 11417
 11418
 11419
 11420
 11421
 11422
 11423
 11424
 11425
 11426
 11427
 11428
 11429
 11430
 11431
 11432
 11433
 11434
 11435
 11436
 11437
 11438
 11439
 11440
 11441
 11442
 11443
 11444
 11445
 11446
 11447
 11448
 11449
 11450
 11451
 11452
 11453
 11454
 11455
 11456
 11457
 11458
 11459
 11460
 11461
 11462
 11463
 11464
 11465
 11466
 11467
 11468
 11469
 11470
 11471
 11472
 11473
 11474
 11475
 11476
 11477
 11478
 11479
 11480
 11481
 11482
 11483
 11484
 11485
 11486
 11487
 11488
 11489
 11490
 11491
 11492
 11493
 11494
 11495
 11496
 11497
 11498
 11499
 11500
 11501
 11502
 11503
 11504
 11505
 11506
 11507
 11508
 11509
 11510
 11511
 11512
 11513
 11514
 11515
 11516
 11517
 11518
 11519
 11520
 11521
 11522
 11523
 11524
 11525
 11526
 11527
 11528
 11529
 11530
 11531
 11532
 11533
 11534
 11535
 11536
 11537
 11538
 11539
 11540
 11541
 11542
 11543
 11544
 11545
 11546
 11547
 11548
 11549
 11550
 11551
 11552
 11553
 11554
 11555
 11556
 11557
 11558
 11559
 11560
 11561
 11562
 11563
 11564
 11565
 11566
 11567
 11568
 11569
 11570
 11571
 11572
 11573
 11574
 11575
 11576
 11577
 11578
 11579
 11580
 11581
 11582
 11583
 11584
 11585
 11586
 11587
 11588
 11589
 11590
 11591
 11592
 11593
 11594
 11595
 11596
 11597
 11598
 11599
 11600
 11601
 11602
 11603
 11604
 11605
 11606
 11607
 11608
 11609
 11610
 11611
 11612
 11613
 11614
 11615
 11616
 11617
 11618
 11619
 11620
 11621
 11622
 11623
 11624
 11625
 11626
 11627
 11628
 11629
 11630
 11631
 11632
 11633
 11634
 11635
 11636
 11637
 11638
 11639
 11640
 11641
 11642
 11643
 11644
 11645
 11646
 11647
 11648
 11649
 11650
 11651
 11652
 11653
 11654
 11655
 11656
 11657
 11658
 11659
 11660
 11661
 11662
 11663
 11664
 11665
 11666
 11667
 11668
 11669
 11670
 11671
 11672
 11673
 11674
 11675
 11676
 11677
 11678
 11679
 11680
 11681
 11682
 11683
 11684
 11685
 11686
 11687
 11688
 11689
 11690
 11691
 11692
 11693
 11694
 11695
 11696
 11697
 11698
 11699
 11700
 11701
 11702
 11703
 11704
 11705
 11706
 11707
 11708
 11709
 11710
 11711
 11712
 11713
 11714
 11715
 11716
 11717
 11718
 11719
 11720
 11721
 11722
 11723
 11724
 11725
 11726
 11727
 11728
 11729
 11730
 11731
 11732
 11733
 11734
 11735
 11736
 11737
 11738
 11739
 11740
 11741
 11742
 11743
 11744
 11745
 11746
 11747
 11748
 11749
 11750
 11751
 11752
 11753
 11754
 11755
 11756
 11757
 11758
 11759
 11760
 11761
 11762
 11763
 11764
 11765
 11766
 11767
 11768
 11769
 11770
 11771
 11772
 11773
 11774
 11775
 11776
 11777
 11778
 11779
 11780
 11781
 11782
 11783
 11784
 11785
 11786
 11787
 11788
 11789
 11790
 11791
 11792
 11793
 11794
 11795
 11796
 11797
 11798
 11799
 11800
 11801
 11802
 11803
 11804
 11805
 11806
 11807
 11808
 11809
 11810
 11811
 11812
 11813
 11814
 11815
 11816
 11817
 11818
 11819
 11820
 11821
 11822
 11823
 11824
 11825
 11826
 11827
 11828
 11829
 11830
 11831
 11832
 11833
 11834
 11835
 11836
 11837
 11838
 11839
 11840
 11841
 11842
 11843
 11844
 11845
 11846
 11847
 11848
 11849
 11850
 11851
 11852
 11853
 11854
 11855
 11856
 11857
 11858
 11859
 11860
 11861
 11862
 11863
 11864
 11865
 11866
 11867
 11868
 11869
 11870
 11871
 11872
 11873
 11874
 11875
 11876
 11877
 11878
 11879
 11880
 11881
 11882
 11883
 11884
 11885
 11886
 11887
 11888
 11889
 11890
 11891
 11892
 11893
 11894
 11895
 11896
 11897
 11898
 11899
 11900
 11901
 11902
 11903
 11904
 11905
 11906
 11907
 11908
 11909
 11910
 11911
 11912
 11913
 11914
 11915
 11916
 11917
 11918
 11919
 11920
 11921
 11922
 11923
 11924
 11925
 11926
 11927
 11928
 11929
 11930
 11931
 11932
 11933
 11934
 11935
 11936
 11937
 11938
 11939
 11940
 11941
 11942
 11943
 11944
 11945
 11946
 11947
 11948
 11949
 11950
 11951
 11952
 11953
 11954
 11955
 11956
 11957
 11958
 11959
 11960
 11961
 11962
 11963
 11964
 11965
 11966
 11967
 11968
 11969
 11970
 11971
 11972
 11973
 11974
 11975
 11976
 11977
 11978
 11979
 11980
 11981
 11982
 11983
 11984
 11985
 11986
 11987
 11988
 11989
 11990
 11991
 11992
 11993
 11994
 11995
 11996
 11997
 11998
 11999
 12000
 12001
 12002
 12003
 12004
 12005
 12006
 12007
 12008
 12009
 12010
 12011
 12012
 12013
 12014
 12015
 12016
 12017
 12018
 12019
 12020
 12021
 12022
 12023
 12024
 12025
 12026
 12027
 12028
 12029
 12030
 12031
 12032
 12033
 12034
 12035
 12036
 12037
 12038
 12039
 12040
 12041
 12042
 12043
 12044
 12045
 12046
 12047
 12048
 12049
 12050
 12051
 12052
 12053
 12054
 12055
 12056
 12057
 12058
 12059
 12060
 12061
 12062
 12063
 12064
 12065
 12066
 12067
 12068
 12069
 12070
 12071
 12072
 12073
 12074
 12075
 12076
 12077
 12078
 12079
 12080
 12081
 12082
 12083
 12084
 12085
 12086
 12087
 12088
 12089
 12090
 12091
 12092
 12093
 12094
 12095
 12096
 12097
 12098
 12099
 12100
 12101
 12102
 12103
 12104
 12105
 12106
 12107
 12108
 12109
 12110
 12111
 12112
 12113
 12114
 12115
 12116
 12117
 12118
 12119
 12120
 12121
 12122
 12123
 12124
 12125
 12126
 12127
 12128
 12129
 12130
 12131
 12132
 12133
 12134
 12135
 12136
 12137
 12138
 12139
 12140
 12141
 12142
 12143
 12144
 12145
 12146
 12147
 12148
 12149
 12150
 12151
 12152
 12153
 12154
 12155
 12156
 12157
 12158
 12159
 12160
 12161
 12162
 12163
 12164
 12165
 12166
 12167
 12168
 12169
 12170
 12171
 12172
 12173
 12174
 12175
 12176
 12177
 12178
 12179
 12180
 12181
 12182
 12183
 12184
 12185
 12186
 12187
 12188
 12189
 12190
 12191
 12192
 12193
 12194
 12195
 12196
 12197
 12198
 12199
 12200
 12201
 12202
 12203
 12204
 12205
 12206
 12207
 12208
 12209
 12210
 12211
 12212
 12213
 12214
 12215
 12216
 12217
 12218
 12219
 12220
 12221
 12222
 12223
 12224
 12225
 12226
 12227
 12228
 12229
 12230
 12231
 12232
 12233
 12234
 12235
 12236
 12237
 12238
 12239
 12240
 12241
 12242
 12243
 12244
 12245
 12246
 12247
 12248
 12249
 12250
 12251
 12252
 12253
 12254
 12255
 12256
 12257
 12258
 12259
 12260
 12261
 12262
 12263
 12264
 12265
 12266
 12267
 12268
 12269
 12270
 12271
 12272
 12273
 12274
 12275
 12276
 12277
 12278
 12279
 12280
 12281
 12282
 12283
 12284
 12285
 12286
 12287
 12288
 12289
 12290
 12291
 12292
 12293
 12294
 12295
 12296
 12297
 12298
 12299
 12300
 12301
 12302
 12303
 12304
 12305
 12306
 12307
 12308
 12309
 12310
 12311
 12312
 12313
 12314
 12315
 12316
 12317
 12318
 12319
 12320
 12321
 12322
 12323
 12324
 12325
 12326
 12327
 12328
 12329
 12330
 12331
 12332
 12333
 12334
 12335
 12336
 12337
 12338
 12339
 12340
 12341
 12342
 12343
 12344
 12345
 12346
 12347
 12348
 12349
 12350
 12351
 12352
 12353
 12354
 12355
 12356
 12357
 12358
 12359
 12360
 12361
 12362
 12363
 12364
 12365
 12366
 12367
 12368
 12369
 12370
 12371
 12372
 12373
 12374
 12375
 12376
 12377
 12378
 12379
 12380
 12381
 12382
 12383
 12384
 12385
 12386
 12387
 12388
 12389
 12390
 12391
 12392
 12393
 12394
 12395
 12396
 12397
 12398
 12399
 12400
 12401
 12402
 12403
 12404
 12405
 12406
 12407
 12408
 12409
 12410
 12411
 12412
 12413
 12414
 12415
 12416
 12417
 12418
 12419
 12420
 12421
 12422
 12423
 12424
 12425
 12426
 12427
 12428
 12429
 12430
 12431
 12432
 12433
 12434
 12435
 12436
 12437
 12438
 12439
 12440
 12441
 12442
 12443
 12444
 12445
 12446
 12447
 12448
 12449
 12450
 12451
 12452
 12453
 12454
 12455
 12456
 12457
 12458
 12459
 12460
 12461
 12462
 12463
 12464
 12465
 12466
 12467
 12468
 12469
 12470
 12471
 12472
 12473
 12474
 12475
 12476
 12477
 12478
 12479
 12480
 12481
 12482
 12483
 12484
 12485
 12486
 12487
 12488
 12489
 12490
 12491
 12492
 12493
 12494
 12495
 12496
 12497
 12498
 12499
 12500
 12501
 12502
 12503
 12504
 12505
 12506
 12507
 12508
 12509
 12510
 12511
 12512
 12513
 12514
 12515
 12516
 12517
 12518
 12519
 12520
 12521
 12522
 12523
 12524
 12525
 12526
 12527
 12528
 12529
 12530
 12531
 12532
 12533
 12534
 12535
 12536
 12537
 12538
 12539
 12540
 12541
 12542
 12543
 12544
 12545
 12546
 12547
 12548
 12549
 12550
 12551
 12552
 12553
 12554
 12555
 12556
 12557
 12558
 12559
 12560
 12561
 12562
 12563
 12564
 12565
 12566
 12567
 12568
 12569
 12570
 12571
 12572
 12573
 12574
 12575
 12576
 12577
 12578
 12579
 12580
 12581
 12582
 12583
 12584
 12585
 12586
 12587
 12588
 12589
 12590
 12591
 12592
 12593
 12594
 12595
 12596
 12597
 12598
 12599
 12600
 12601
 12602
 12603
 12604
 12605
 12606
 12607
 12608
 12609
 12610
 12611
 12612
 12613
 12614
 12615
 12616
 12617
 12618
 12619
 12620
 12621
 12622
 12623
 12624
 12625
 12626
 12627
 12628
 12629
 12630
 12631
 12632
 12633
 12634
 12635
 12636
 12637
 12638
 12639
 12640
 12641
 12642
 12643
 12644
 12645
 12646
 12647
 12648
 12649
 12650
 12651
 12652
 12653
 12654
 12655
 12656
 12657
 12658
 12659
 12660
 12661
 12662
 12663
 12664
 12665
 12666
 12667
 12668
 12669
 12670
 12671
 12672
 12673
 12674
 12675
 12676
 12677
 12678
 12679
 12680
 12681
 12682
 12683
 12684
 12685
 12686
 12687
 12688
 12689
 12690
 12691
 12692
 12693
 12694
 12695
 12696
 12697
 12698
 12699
 12700
 12701
 12702
 12703
 12704
 12705
 12706
 12707
 12708
 12709
 12710
 12711
 12712
 12713
 12714
 12715
 12716
 12717
 12718
 12719
 12720
 12721
 12722
 12723
 12724
 12725
 12726
 12727
 12728
 12729
 12730
 12731
 12732
 12733
 12734
 12735
 12736
 12737
 12738
 12739
 12740
 12741
 12742
 12743
 12744
 12745
 12746
 12747
 12748
 12749
 12750
 12751
 12752
 12753
 12754
 12755
 12756
 12757
 12758
 12759
 12760
 12761
 12762
 12763
 12764
 12765
 12766
 12767
 12768
 12769
 12770
 12771
 12772
 12773
 12774
 12775
 12776
 12777
 12778
 12779
 12780
 12781
 12782
 12783
 12784
 12785
 12786
 12787
 12788
 12789
 12790
 12791
 12792
 12793
 12794
 12795
 12796
 12797
 12798
 12799
 12800
 12801
 12802
 12803
 12804
 12805
 12806
 12807
 12808
 12809
 12810
 12811
 12812
 12813
 12814
 12815
 12816
 12817
 12818
 12819
 12820
 12821
 12822
 12823
 12824
 12825
 12826
 12827
 12828
 12829
 12830
 12831
 12832
 12833
 12834
 12835
 12836
 12837
 12838
 12839
 12840
 12841
 12842
 12843
 12844
 12845
 12846
 12847
 12848
 12849
 12850
 12851
 12852
 12853
 12854
 12855
 12856
 12857
 12858
 12859
 12860
 12861
 12862
 12863
 12864
 12865
 12866
 12867
 12868
 12869
 12870
 12871
 12872
 12873
 12874
 12875
 12876
 12877
 12878
 12879
 12880
 12881
 12882
 12883
 12884
 12885
 12886
 12887
 12888
 12889
 12890
 12891
 12892
 12893
 12894
 12895
 12896
 12897
 12898
 12899
 12900
 12901
 12902
 12903
 12904
 12905
 12906
 12907
 12908
 12909
 12910
 12911
 12912
 12913
 12914
 12915
 12916
 12917
 12918
 12919
 12920
 12921
 12922
 12923
 12924
 12925
 12926
 12927
 12928
 12929
 12930
 12931
 12932
 12933
 12934
 12935
 12936
 12937
 12938
 12939
 12940
 12941
 12942
 12943
 12944
 12945
 12946
 12947
 12948
 12949
 12950
 12951
 12952
 12953
 12954
 12955
 12956
 12957
 12958
 12959
 12960
 12961
 12962
 12963
 12964
 12965
 12966
 12967
 12968
 12969
 12970
 12971
 12972
 12973
 12974
 12975
 12976
 12977
 12978
 12979
 12980
 12981
 12982
 12983
 12984
 12985
 12986
 12987
 12988
 12989
 12990
 12991
 12992
 12993
 12994
 12995
 12996
 12997
 12998
 12999
 13000
 13001
 13002
 13003
 13004
 13005
 13006
 13007
 13008
 13009
 13010
 13011
 13012
 13013
 13014
 13015
 13016
 13017
 13018
 13019
 13020
 13021
 13022
 13023
 13024
 13025
 13026
 13027
 13028
 13029
 13030
 13031
 13032
 13033
 13034
 13035
 13036
 13037
 13038
 13039
 13040
 13041
 13042
 13043
 13044
 13045
 13046
 13047
 13048
 13049
 13050
 13051
 13052
 13053
 13054
 13055
 13056
 13057
 13058
 13059
 13060
 13061
 13062
 13063
 13064
 13065
 13066
 13067
 13068
 13069
 13070
 13071
 13072
 13073
 13074
 13075
 13076
 13077
 13078
 13079
 13080
 13081
 13082
 13083
 13084
 13085
 13086
 13087
 13088
 13089
 13090
 13091
 13092
 13093
 13094
 13095
 13096
 13097
 13098
 13099
 13100
 13101
 13102
 13103
 13104
 13105
 13106
 13107
 13108
 13109
 13110
 13111
 13112
 13113
 13114
 13115
 13116
 13117
 13118
 13119
 13120
 13121
 13122
 13123
 13124
 13125
 13126
 13127
 13128
 13129
 13130
 13131
 13132
 13133
 13134
 13135
 13136
 13137
 13138
 13139
 13140
 13141
 13142
 13143
 13144
 13145
 13146
 13147
 13148
 13149
 13150
 13151
 13152
 13153
 13154
 13155
 13156
 13157
 13158
 13159
 13160
 13161
 13162
 13163
 13164
 13165
 13166
 13167
 13168
 13169
 13170
 13171
 13172
 13173
 13174
 13175
 13176
 13177
 13178
 13179
 13180
 13181
 13182
 13183
 13184
 13185
 13186
 13187
 13188
 13189
 13190
 13191
 13192
 13193
 13194
 13195
 13196
 13197
 13198
 13199
 13200
 13201
 13202
 13203
 13204
 13205
 13206
 13207
 13208
 13209
 13210
 13211
 13212
 13213
 13214
 13215
 13216
 13217
 13218
 13219
 13220
 13221
 13222
 13223
 13224
 13225
 13226
 13227
 13228
 13229
 13230
 13231
 13232
 13233
 13234
 13235
 13236
 13237
 13238
 13239
 13240
 13241
 13242
 13243
 13244
 13245
 13246
 13247
 13248
 13249
 13250
 13251
 13252
 13253
 13254
 13255
 13256
 13257
 13258
 13259
 13260
 13261
 13262
 13263
 13264
 13265
 13266
 13267
 13268
 13269
 13270
 13271
 13272
 13273
 13274
 13275
 13276
 13277
 13278
 13279
 13280
 13281
 13282
 13283
 13284
 13285
 13286
 13287
 13288
 13289
 13290
 13291
 13292
 13293
 13294
 13295
 13296
 13297
 13298
 13299
 13300
 13301
 13302
 13303
 13304
 13305
 13306
 13307
 13308
 13309
 13310
 13311
 13312
 13313
 13314
 13315
 13316
 13317
 13318
 13319
 13320
 13321
 13322
 13323
 13324
 13325
 13326
 13327
 13328
 13329
 13330
 13331
 13332
 13333
 13334
 13335
 13336
 13337
 13338
 13339
 13340
 13341
 13342
 13343
 13344
 13345
 13346
 13347
 13348
 13349
 13350
 13351
 13352
 13353
 13354
 13355
 13356
 13357
 13358
 13359
 13360
 13361
 13362
 13363
 13364
 13365
 13366
 13367
 13368
 13369
 13370
 13371
 13372
 13373
 13374
 13375
 13376
 13377
 13378
 13379
 13380
 13381
 13382
 13383
 13384
 13385
 13386
 13387
 13388
 13389
 13390
 13391
 13392
 13393
 13394
 13395
 13396
 13397
 13398
 13399
 13400
 13401
 13402
 13403
 13404
 13405
 13406
 13407
 13408
 13409
 13410
 13411
 13412
 13413
 13414
 13415
 13416
 13417
 13418
 13419
 13420
 13421
 13422
 13423
 13424
 13425
 13426
 13427
 13428
 13429
 13430
 13431
 13432
 13433
 13434
 13435
 13436
 13437
 13438
 13439
 13440
 13441
 13442
 13443
 13444
 13445
 13446
 13447
 13448
 13449
 13450
 13451
 13452
 13453
 13454
 13455
 13456
 13457
 13458
 13459
 13460
 13461
 13462
 13463
 13464
 13465
 13466
 13467
 13468
 13469
 13470
 13471
 13472
 13473
 13474
 13475
 13476
 13477
 13478
 13479
 13480
 13481
 13482
 13483
 13484
 13485
 13486
 13487
 13488
 13489
 13490
 13491
 13492
 13493
 13494
 13495
 13496
 13497
 13498
 13499
 13500
 13501
 13502
 13503
 13504
 13505
 13506
 13507
 13508
 13509
 13510
 13511
 13512
 13513
 13514
 13515
 13516
 13517
 13518
 13519
 13520
 13521
 13522
 13523
 13524
 13525
 13526
 13527
 13528
 13529
 13530
 13531
 13532
 13533
 13534
 13535
 13536
 13537
 13538
 13539
 13540
 13541
 13542
 13543
 13544
 13545
 13546
 13547
 13548
 13549
 13550
 13551
 13552
 13553
 13554
 13555
 13556
 13557
 13558
 13559
 13560
 13561
 13562
 13563
 13564
 13565
 13566
 13567
 13568
 13569
 13570
 13571
 13572
 13573
 13574
 13575
 13576
 13577
 13578
 13579
 13580
 13581
 13582
 13583
 13584
 13585
 13586
 13587
 13588
 13589
 13590
 13591
 13592
 13593
 13594
 13595
 13596
 13597
 13598
 13599
 13600
 13601
 13602
 13603
 13604
 13605
 13606
 13607
 13608
 13609
 13610
 13611
 13612
 13613
 13614
 13615
 13616
 13617
 13618
 13619
 13620
 13621
 13622
 13623
 13624
 13625
 13626
 13627
 13628
 13629
 13630
 13631
 13632
 13633
 13634
 13635
 13636
 13637
 13638
 13639
 13640
 13641
 13642
 13643
 13644
 13645
 13646
 13647
 13648
 13649
 13650
 13651
 13652
 13653
 13654
 13655
 13656
 13657
 13658
 13659
 13660
 13661
 13662
 13663
 13664
 13665
 13666
 13667
 13668
 13669
 13670
 13671
 13672
 13673
 13674
 13675
 13676
 13677
 13678
 13679
 13680
 13681
 13682
 13683
 13684
 13685
 13686
 13687
 13688
 13689
 13690
 13691
 13692
 13693
 13694
 13695
 13696
 13697
 13698
 13699
 13700
 13701
 13702
 13703
 13704
 13705
 13706
 13707
 13708
 13709
 13710
 13711
 13712
 13713
 13714
 13715
 13716
 13717
 13718
 13719
 13720
 13721
 13722
 13723
 13724
 13725
 13726
 13727
 13728
 13729
 13730
 13731
 13732
 13733
 13734
 13735
 13736
 13737
 13738
 13739
 13740
 13741
 13742
 13743
 13744
 13745
 13746
 13747
 13748
 13749
 13750
 13751
 13752
 13753
 13754
 13755
 13756
 13757
 13758
 13759
 13760
 13761
 13762
 13763
 13764
 13765
 13766
 13767
 13768
 13769
 13770
 13771
 13772
 13773
 13774
 13775
 13776
 13777
 13778
 13779
 13780
 13781
 13782
 13783
 13784
 13785
 13786
 13787
 13788
 13789
 13790
 13791
 13792
 13793
 13794
 13795
 13796
 13797
 13798
 13799
 13800
 13801
 13802
 13803
 13804
 13805
 13806
 13807
 13808
 13809
 13810
 13811
 13812
 13813
 13814
 13815
 13816
 13817
 13818
 13819
 13820
 13821
 13822
 13823
 13824
 13825
 13826
 13827
 13828
 13829
 13830
 13831
 13832
 13833
 13834
 13835
 13836
 13837
 13838
 13839
 13840
 13841
 13842
 13843
 13844
 13845
 13846
 13847
 13848
 13849
 13850
 13851
 13852
 13853
 13854
 13855
 13856
 13857
 13858
 13859
 13860
 13861
 13862
 13863
 13864
 13865
 13866
 13867
 13868
 13869
 13870
 13871
 13872
 13873
 13874
 13875
 13876
 13877
 13878
 13879
 13880
 13881
 13882
 13883
 13884
 13885
 13886
 13887
 13888
 13889
 13890
 13891
 13892
 13893
 13894
 13895
 13896
 13897
 13898
 13899
 13900
 13901
 13902
 13903
 13904
 13905
 13906
 13907
 13908
 13909
 13910
 13911
 13912
 13913
 13914
 13915
 13916
 13917
 13918
 13919
 13920
 13921
 13922
 13923
 13924
 13925
 13926
 13927
 13928
 13929
 13930
 13931
 13932
 13933
 13934
 13935
 13936
 13937
 13938
 13939
 13940
 13941
 13942
 13943
 13944
 13945
 13946
 13947
 13948
 13949
 13950
 13951
 13952
 13953
 13954
 13955
 13956
 13957
 13958
 13959
 13960
 13961
 13962
 13963
 13964
 13965
 13966
 13967
 13968
 13969
 13970
 13971
 13972
 13973
 13974
 13975
 13976
 13977
 13978
 13979
 13980
 13981
 13982
 13983
 13984
 13985
 13986
 13987
 13988
 13989
 13990
 13991
 13992
 13993
 13994
 13995
 13996
 13997
 13998
 13999
 14000
 14001
 14002
 14003
 14004
 14005
 14006
 14007
 14008
 14009
 14010
 14011
 14012
 14013
 14014
 14015
 14016
 14017
 14018
 14019
 14020
 14021
 14022
 14023
 14024
 14025
 14026
 14027
 14028
 14029
 14030
 14031
 14032
 14033
 14034
 14035
 14036
 14037
 14038
 14039
 14040
 14041
 14042
 14043
 14044
 14045
 14046
 14047
 14048
 14049
 14050
 14051
 14052
 14053
 14054
 14055
 14056
 14057
 14058
 14059
 14060
 14061
 14062
 14063
 14064
 14065
 14066
 14067
 14068
 14069
 14070
 14071
 14072
 14073
 14074
 14075
 14076
 14077
 14078
 14079
 14080
 14081
 14082
 14083
 14084
 14085
 14086
 14087
 14088
 14089
 14090
 14091
 14092
 14093
 14094
 14095
 14096
 14097
 14098
 14099
 14100
 14101
 14102
 14103
 14104
 14105
 14106
 14107
 14108
 14109
 14110
 14111
 14112
 14113
 14114
 14115
 14116
 14117
 14118
 14119
 14120
 14121
 14122
 14123
 14124
 14125
 14126
 14127
 14128
 14129
 14130
 14131
 14132
 14133
 14134
 14135
 14136
 14137
 14138
 14139
 14140
 14141
 14142
 14143
 14144
 14145
 14146
 14147
 14148
 14149
 14150
 14151
 14152
 14153
 14154
 14155
 14156
 14157
 14158
 14159
 14160
 14161
 14162
 14163
 14164
 14165
 14166
 14167
 14168
 14169
 14170
 14171
 14172
 14173
 14174
 14175
 14176
 14177
 14178
 14179
 14180
 14181
 14182
 14183
 14184
 14185
 14186
 14187
 14188
 14189
 14190
 14191
 14192
 14193
 14194
 14195
 14196
 14197
 14198
 14199
 14200
 14201
 14202
 14203
 14204
 14205
 14206
 14207
 14208
 14209
 14210
 14211
 14212
 14213
 14214
 14215
 14216
 14217
 14218
 14219
 14220
 14221
 14222
 14223
 14224
 14225
 14226
 14227
 14228
 14229
 14230
 14231
 14232
 14233
 14234
 14235
 14236
 14237
 14238
 14239
 14240
 14241
 14242
 14243
 14244
 14245
 14246
 14247
 14248
 14249
 14250
 14251
 14252
 14253
 14254
 14255
 14256
 14257
 14258
 14259
 14260
 14261
 14262
 14263
 14264
 14265
 14266
 14267
 14268
 14269
 14270
 14271
 14272
 14273
 14274
 14275
 14276
 14277
 14278
 14279
 14280
 14281
 14282
 14283
 14284
 14285
 14286
 14287
 14288
 14289
 14290
 14291
 14292
 14293
 14294
 14295
 14296
 14297
 14298
 14299
 14300
 14301
 14302
 14303
 14304
 14305
 14306
 14307
 14308
 14309
 14310
 14311
 14312
 14313
 14314
 14315
 14316
 14317
 14318
 14319
 14320
 14321
 14322
 14323
 14324
 14325
 14326
 14327
 14328
 14329
 14330
 14331
 14332
 14333
 14334
 14335
 14336
 14337
 14338
 14339
 14340
 14341
 14342
 14343
 14344
 14345
 14346
 14347
 14348
 14349
 14350
 14351
 14352
 14353
 14354
 14355
 14356
 14357
 14358
 14359
 14360
 14361
 14362
 14363
 14364
 14365
 14366
 14367
 14368
 14369
 14370
 14371
 14372
 14373
 14374
 14375
 14376
 14377
 14378
 14379
 14380
 14381
 14382
 14383
 14384
 14385
 14386
 14387
 14388
 14389
 14390
 14391
 14392
 14393
 14394
 14395
 14396
 14397
 14398
 14399
 14400
 14401
 14402
 14403
 14404
 14405
 14406
 14407
 14408
 14409
 14410
 14411
 14412
 14413
 14414
 14415
 14416
 14417
 14418
 14419
 14420
 14421
 14422
 14423
 14424
 14425
 14426
 14427
 14428
 14429
 14430
 14431
 14432
 14433
 14434
 14435
 14436
 14437
 14438
 14439
 14440
 14441
 14442
 14443
 14444
 14445
 14446
 14447
 14448
 14449
 14450
 14451
 14452
 14453
 14454
 14455
 14456
 14457
 14458
 14459
 14460
 14461
 14462
 14463
 14464
 14465
 14466
 14467
 14468
 14469
 14470
 14471
 14472
 14473
 14474
 14475
 14476
 14477
 14478
 14479
 14480
 14481
 14482
 14483
 14484
 14485
 14486
 14487
 14488
 14489
 14490
 14491
 14492
 14493
 14494
 14495
 14496
 14497
 14498
 14499
 14500
 14501
 14502
 14503
 14504
 14505
 14506
 14507
 14508
 14509
 14510
 14511
 14512
 14513
 14514
 14515
 14516
 14517
 14518
 14519
 14520
 14521
 14522
 14523
 14524
 14525
 14526
 14527
 14528
 14529
 14530
 14531
 14532
 14533
 14534
 14535
 14536
 14537
 14538
 14539
 14540
 14541
 14542
 14543
 14544
 14545
 14546
 14547
 14548
 14549
 14550
 14551
 14552
 14553
 14554
 14555
 14556
 14557
 14558
 14559
 14560
 14561
 14562
 14563
 14564
 14565
 14566
 14567
 14568
 14569
 14570
 14571
 14572
 14573
 14574
 14575
 14576
 14577
 14578
 14579
 14580
 14581
 14582
 14583
 14584
 14585
 14586
 14587
 14588
 14589
 14590
 14591
 14592
 14593
 14594
 14595
 14596
 14597
 14598
 14599
 14600
 14601
 14602
 14603
 14604
 14605
 14606
 14607
 14608
 14609
 14610
 14611
 14612
 14613
 14614
 14615
 14616
 14617
 14618
 14619
 14620
 14621
 14622
 14623
 14624
 14625
 14626
 14627
 14628
 14629
 14630
 14631
 14632
 14633
 14634
 14635
 14636
 14637
 14638
 14639
 14640
 14641
 14642
 14643
 14644
 14645
 14646
 14647
 14648
 14649
 14650
 14651
 14652
 14653
 14654
 14655
 14656
 14657
 14658
 14659
 14660
 14661
 14662
 14663
 14664
 14665
 14666
 14667
 14668
 14669
 14670
 14671
 14672
 14673
 14674
 14675
 14676
 14677
 14678
 14679
 14680
 14681
 14682
 14683
 14684
 14685
 14686
 14687
 14688
 14689
 14690
 14691
 14692
 14693
 14694
 14695
 14696
 14697
 14698
 14699
 14700
 14701
 14702
 14703
 14704
 14705
 14706
 14707
 14708
 14709
 14710
 14711
 14712
 14713
 14714
 14715
 14716
 14717
 14718
 14719
 14720
 14721
 14722
 14723
 14724
 14725
 14726
 14727
 14728
 14729
 14730
 14731
 14732
 14733
 14734
 14735
 14736
 14737
 14738
 14739
 14740
 14741
 14742
 14743
 14744
 14745
 14746
 14747
 14748
 14749
 14750
 14751
 14752
 14753
 14754
 14755
 14756
 14757
 14758
 14759
 14760
 14761
 14762
 14763
 14764
 14765
 14766
 14767
 14768
 14769
 14770
 14771
 14772
 14773
 14774
 14775
 14776
 14777
 14778
 14779
 14780
 14781
 14782
 14783
 14784
 14785
 14786
 14787
 14788
 14789
 14790
 14791
 14792
 14793
 14794
 14795
 14796
 14797
 14798
 14799
 14800
 14801
 14802
 14803
 14804
 14805
 14806
 14807
 14808
 14809
 14810
 14811
 14812
 14813
 14814
 14815
 14816
 14817
 14818
 14819
 14820
 14821
 14822
 14823
 14824
 14825
 14826
 14827
 14828
 14829
 14830
 14831
 14832
 14833
 14834
 14835
 14836
 14837
 14838
 14839
 14840
 14841
 14842
 14843
 14844
 14845
 14846
 14847
 14848
 14849
 14850
 14851
 14852
 14853
 14854
 14855
 14856
 14857
 14858
 14859
 14860
 14861
 14862
 14863
 14864
 14865
 14866
 14867
 14868
 14869
 14870
 14871
 14872
 14873
 14874
 14875
 14876
 14877
 14878
 14879
 14880
 14881
 14882
 14883
 14884
 14885
 14886
 14887
 14888
 14889
 14890
 14891
 14892
 14893
 14894
 14895
 14896
 14897
 14898
 14899
 14900
 14901
 14902
 14903
 14904
 14905
 14906
 14907
 14908
 14909
 14910
 14911
 14912
 14913
 14914
 14915
 14916
 14917
 14918
 14919
 14920
 14921
 14922
 14923
 14924
 14925
 14926
 14927
 14928
 14929
 14930
 14931
 14932
 14933
 14934
 14935
 14936
 14937
 14938
 14939
 14940
 14941
 14942
 14943
 14944
 14945
 14946
 14947
 14948
 14949
 14950
 14951
 14952
 14953
 14954
 14955
 14956
 14957
 14958
 14959
 14960
 14961
 14962
 14963
 14964
 14965
 14966
 14967
 14968
 14969
 14970
 14971
 14972
 14973
 14974
 14975
 14976
 14977
 14978
 14979
 14980
 14981
 14982
 14983
 14984
 14985
 14986
 14987
 14988
 14989
 14990
 14991
 14992
 14993
 14994
 14995
 14996
 14997
 14998
 14999
 15000
 15001
 15002
 15003
 15004
 15005
 15006
 15007
 15008
 15009
 15010
 15011
 15012
 15013
 15014
 15015
 15016
 15017
 15018
 15019
 15020
 15021
 15022
 15023
 15024
 15025
 15026
 15027
 15028
 15029
 15030
 15031
 15032
 15033
 15034
 15035
 15036
 15037
 15038
 15039
 15040
 15041
 15042
 15043
 15044
 15045
 15046
 15047
 15048
 15049
 15050
 15051
 15052
 15053
 15054
 15055
 15056
 15057
 15058
 15059
 15060
 15061
 15062
 15063
 15064
 15065
 15066
 15067
 15068
 15069
 15070
 15071
 15072
 15073
 15074
 15075
 15076
 15077
 15078
 15079
 15080
 15081
 15082
 15083
 15084
 15085
 15086
 15087
 15088
 15089
 15090
 15091
 15092
 15093
 15094
 15095
 15096
 15097
 15098
 15099
 15100
 15101
 15102
 15103
 15104
 15105
 15106
 15107
 15108
 15109
 15110
 15111
 15112
 15113
 15114
 15115
 15116
 15117
 15118
 15119
 15120
 15121
 15122
 15123
 15124
 15125
 15126
 15127
 15128
 15129
 15130
 15131
 15132
 15133
 15134
 15135
 15136
 15137
 15138
 15139
 15140
 15141
 15142
 15143
 15144
 15145
 15146
 15147
 15148
 15149
 15150
 15151
 15152
 15153
 15154
 15155
 15156
 15157
 15158
 15159
 15160
 15161
 15162
 15163
 15164
 15165
 15166
 15167
 15168
 15169
 15170
 15171
 15172
 15173
 15174
 15175
 15176
 15177
 15178
 15179
 15180
 15181
 15182
 15183
 15184
 15185
 15186
 15187
 15188
 15189
 15190
 15191
 15192
 15193
 15194
 15195
 15196
 15197
 15198
 15199
 15200
 15201
 15202
 15203
 15204
 15205
 15206
 15207
 15208
 15209
 15210
 15211
 15212
 15213
 15214
 15215
 15216
 15217
 15218
 15219
 15220
 15221
 15222
 15223
 15224
 15225
 15226
 15227
 15228
 15229
 15230
 15231
 15232
 15233
 15234
 15235
 15236
 15237
 15238
 15239
 15240
 15241
 15242
 15243
 15244
 15245
 15246
 15247
 15248
 15249
 15250
 15251
 15252
 15253
 15254
 15255
 15256
 15257
 15258
 15259
 15260
 15261
 15262
 15263
 15264
 15265
 15266
 15267
 15268
 15269
 15270
 15271
 15272
 15273
 15274
 15275
 15276
 15277
 15278
 15279
 15280
 15281
 15282
 15283
 15284
 15285
 15286
 15287
 15288
 15289
 15290
 15291
 15292
 15293
 15294
 15295
 15296
 15297
 15298
 15299
 15300
 15301
 15302
 15303
 15304
 15305
 15306
 15307
 15308
 15309
 15310
 15311
 15312
 15313
 15314
 15315
 15316
 15317
 15318
 15319
 15320
 15321
 15322
 15323
 15324
 15325
 15326
 15327
 15328
 15329
 15330
 15331
 15332
 15333
 15334
 15335
 15336
 15337
 15338
 15339
 15340
 15341
 15342
 15343
 15344
 15345
 15346
 15347
 15348
 15349
 15350
 15351
 15352
 15353
 15354
 15355
 15356
 15357
 15358
 15359
 15360
 15361
 15362
 15363
 15364
 15365
 15366
 15367
 15368
 15369
 15370
 15371
 15372
 15373
 15374
 15375
 15376
 15377
 15378
 15379
 15380
 15381
 15382
 15383
 15384
 15385
 15386
 15387
 15388
 15389
 15390
 15391
 15392
 15393
 15394
 15395
 15396
 15397
 15398
 15399
 15400
 15401
 15402
 15403
 15404
 15405
 15406
 15407
 15408
 15409
 15410
 15411
 15412
 15413
 15414
 15415
 15416
 15417
 15418
 15419
 15420
 15421
 15422
 15423
 15424
 15425
 15426
 15427
 15428
 15429
 15430
 15431
 15432
 15433
 15434
 15435
 15436
 15437
 15438
 15439
 15440
 15441
 15442
 15443
 15444
 15445
 15446
 15447
 15448
 15449
 15450
 15451
 15452
 15453
 15454
 15455
 15456
 15457
 15458
 15459
 15460
 15461
 15462
 15463
 15464
 15465
 15466
 15467
 15468
 15469
 15470
 15471
 15472
 15473
 15474
 15475
 15476
 15477
 15478
 15479
 15480
 15481
 15482
 15483
 15484
 15485
 15486
 15487
 15488
 15489
 15490
 15491
 15492
 15493
 15494
 15495
 15496
 15497
 15498
 15499
 15500
 15501
 15502
 15503
 15504
 15505
 15506
 15507
 15508
 15509
 15510
 15511
 15512
 15513
 15514
 15515
 15516
 15517
 15518
 15519
 15520
 15521
 15522
 15523
 15524
 15525
 15526
 15527
 15528
 15529
 15530
 15531
 15532
 15533
 15534
 15535
 15536
 15537
 15538
 15539
 15540
 15541
 15542
 15543
 15544
 15545
 15546
 15547
 15548
 15549
 15550
 15551
 15552
 15553
 15554
 15555
 15556
 15557
 15558
 15559
 15560
 15561
 15562
 15563
 15564
 15565
 15566
 15567
 15568
 15569
 15570
 15571
 15572
 15573
 15574
 15575
 15576
 15577
 15578
 15579
 15580
 15581
 15582
 15583
 15584
 15585
 15586
 15587
 15588
 15589
 15590
 15591
 15592
 15593
 15594
 15595
 15596
 15597
 15598
 15599
 15600
 15601
 15602
 15603
 15604
 15605
 15606
 15607
 15608
 15609
 15610
 15611
 15612
 15613
 15614
 15615
 15616
 15617
 15618
 15619
 15620
 15621
 15622
 15623
 15624
 15625
 15626
 15627
 15628
 15629
 15630
 15631
 15632
 15633
 15634
 15635
 15636
 15637
 15638
 15639
 15640
 15641
 15642
 15643
 15644
 15645
 15646
 15647
 15648
 15649
 15650
 15651
 15652
 15653
 15654
 15655
 15656
 15657
 15658
 15659
 15660
 15661
 15662
 15663
 15664
 15665
 15666
 15667
 15668
 15669
 15670
 15671
 15672
 15673
 15674
 15675
 15676
 15677
 15678
 15679
 15680
 15681
 15682
 15683
 15684
 15685
 15686
 15687
 15688
 15689
 15690
 15691
 15692
 15693
 15694
 15695
 15696
 15697
 15698
 15699
 15700
 15701
 15702
 15703
 15704
 15705
 15706
 15707
 15708
 15709
 15710
 15711
 15712
 15713
 15714
 15715
 15716
 15717
 15718
 15719
 15720
 15721
 15722
 15723
 15724
 15725
 15726
 15727
 15728
 15729
 15730
 15731
 15732
 15733
 15734
 15735
 15736
 15737
 15738
 15739
 15740
 15741
 15742
 15743
 15744
 15745
 15746
 15747
 15748
 15749
 15750
 15751
 15752
 15753
 15754
 15755
 15756
 15757
 15758
 15759
 15760
 15761
 15762
 15763
 15764
 15765
 15766
 15767
 15768
 15769
 15770
 15771
 15772
 15773
 15774
 15775
 15776
 15777
 15778
 15779
 15780
 15781
 15782
 15783
 15784
 15785
 15786
 15787
 15788
 15789
 15790
 15791
 15792
 15793
 15794
 15795
 15796
 15797
 15798
 15799
 15800
 15801
 15802
 15803
 15804
 15805
 15806
 15807
 15808
 15809
 15810
 15811
 15812
 15813
 15814
 15815
 15816
 15817
 15818
 15819
 15820
 15821
 15822
 15823
 15824
 15825
 15826
 15827
 15828
 15829
 15830
 15831
 15832
 15833
 15834
 15835
 15836
 15837
 15838
 15839
 15840
 15841
 15842
 15843
 15844
 15845
 15846
 15847
 15848
 15849
 15850
 15851
 15852
 15853
 15854
 15855
 15856
 15857
 15858
 15859
 15860
 15861
 15862
 15863
 15864
 15865
 15866
 15867
 15868
 15869
 15870
 15871
 15872
 15873
 15874
 15875
 15876
 15877
 15878
 15879
 15880
 15881
 15882
 15883
 15884
 15885
 15886
 15887
 15888
 15889
 15890
 15891
 15892
 15893
 15894
 15895
 15896
 15897
 15898
 15899
 15900
 15901
 15902
 15903
 15904
 15905
 15906
 15907
 15908
 15909
 15910
 15911
 15912
 15913
 15914
 15915
 15916
 15917
 15918
 15919
 15920
 15921
 15922
 15923
 15924
 15925
 15926
 15927
 15928
 15929
 15930
 15931
 15932
 15933
 15934
 15935
 15936
 15937
 15938
 15939
 15940
 15941
 15942
 15943
 15944
 15945
 15946
 15947
 15948
 15949
 15950
 15951
 15952
 15953
 15954
 15955
 15956
 15957
 15958
 15959
 15960
 15961
 15962
 15963
 15964
 15965
 15966
 15967
 15968
 15969
 15970
 15971
 15972
 15973
 15974
 15975
 15976
 15977
 15978
 15979
 15980
 15981
 15982
 15983
 15984
 15985
 15986
 15987
 15988
 15989
 15990
 15991
 15992
 15993
 15994
 15995
 15996
 15997
 15998
 15999
 16000
 16001
 16002
 16003
 16004
 16005
 16006
 16007
 16008
 16009
 16010
 16011
 16012
 16013
 16014
 16015
 16016
 16017
 16018
 16019
 16020
 16021
 16022
 16023
 16024
 16025
 16026
 16027
 16028
 16029
 16030
 16031
 16032
 16033
 16034
 16035
 16036
 16037
 16038
 16039
 16040
 16041
 16042
 16043
 16044
 16045
 16046
 16047
 16048
 16049
 16050
 16051
 16052
 16053
 16054
 16055
 16056
 16057
 16058
 16059
 16060
 16061
 16062
 16063
 16064
 16065
 16066
 16067
 16068
 16069
 16070
 16071
 16072
 16073
 16074
 16075
 16076
 16077
 16078
 16079
 16080
 16081
 16082
 16083
 16084
 16085
 16086
 16087
 16088
 16089
 16090
 16091
 16092
 16093
 16094
 16095
 16096
 16097
 16098
 16099
 16100
 16101
 16102
 16103
 16104
 16105
 16106
 16107
 16108
 16109
 16110
 16111
 16112
 16113
 16114
 16115
 16116
 16117
 16118
 16119
 16120
 16121
 16122
 16123
 16124
 16125
 16126
 16127
 16128
 16129
 16130
 16131
 16132
 16133
 16134
 16135
 16136
 16137
 16138
 16139
 16140
 16141
 16142
 16143
 16144
 16145
 16146
 16147
 16148
 16149
 16150
 16151
 16152
 16153
 16154
 16155
 16156
 16157
 16158
 16159
 16160
 16161
 16162
 16163
 16164
 16165
 16166
 16167
 16168
 16169
 16170
 16171
 16172
 16173
 16174
 16175
 16176
 16177
 16178
 16179
 16180
 16181
 16182
 16183
 16184
 16185
 16186
 16187
 16188
 16189
 16190
 16191
 16192
 16193
 16194
 16195
 16196
 16197
 16198
 16199
 16200
 16201
 16202
 16203
 16204
 16205
 16206
 16207
 16208
 16209
 16210
 16211
 16212
 16213
 16214
 16215
 16216
 16217
 16218
 16219
 16220
 16221
 16222
 16223
 16224
 16225
 16226
 16227
 16228
 16229
 16230
 16231
 16232
 16233
 16234
 16235
 16236
 16237
 16238
 16239
 16240
 16241
 16242
 16243
 16244
 16245
 16246
 16247
 16248
 16249
 16250
 16251
 16252
 16253
 16254
 16255
 16256
 16257
 16258
 16259
 16260
 16261
 16262
 16263
 16264
 16265
 16266
 16267
 16268
 16269
 16270
 16271
 16272
 16273
 16274
 16275
 16276
 16277
 16278
 16279
 16280
 16281
 16282
 16283
 16284
 16285
 16286
 16287
 16288
 16289
 16290
 16291
 16292
 16293
 16294
 16295
 16296
 16297
 16298
 16299
 16300
 16301
 16302
 16303
 16304
 16305
 16306
 16307
 16308
 16309
 16310
 16311
 16312
 16313
 16314
 16315
 16316
 16317
 16318
 16319
 16320
 16321
 16322
 16323
 16324
 16325
 16326
 16327
 16328
 16329
 16330
 16331
 16332
 16333
 16334
 16335
 16336
 16337
 16338
 16339
 16340
 16341
 16342
 16343
 16344
 16345
 16346
 16347
 16348
 16349
 16350
 16351
 16352
 16353
 16354
 16355
 16356
 16357
 16358
 16359
 16360
 16361
 16362
 16363
 16364
 16365
 16366
 16367
 16368
 16369
 16370
 16371
 16372
 16373
 16374
 16375
 16376
 16377
 16378
 16379
 16380
 16381
 16382
 16383
 16384
 16385
 16386
 16387
 16388
 16389
 16390
 16391
 16392
 16393
 16394
 16395
 16396
 16397
 16398
 16399
 16400
 16401
 16402
 16403
 16404
 16405
 16406
 16407
 16408
 16409
 16410
 16411
 16412
 16413
 16414
 16415
 16416
 16417
 16418
 16419
 16420
 16421
 16422
 16423
 16424
 16425
 16426
 16427
 16428
 16429
 16430
 16431
 16432
 16433
 16434
 16435
 16436
 16437
 16438
 16439
 16440
 16441
 16442
 16443
 16444
 16445
 16446
 16447
 16448
 16449
 16450
 16451
 16452
 16453
 16454
 16455
 16456
 16457
 16458
 16459
 16460
 16461
 16462
 16463
 16464
 16465
 16466
 16467
 16468
 16469
 16470
 16471
 16472
 16473
 16474
 16475
 16476
 16477
 16478
 16479
 16480
 16481
 16482
 16483
 16484
 16485
 16486
 16487
 16488
 16489
 16490
 16491
 16492
 16493
 16494
 16495
 16496
 16497
 16498
 16499
 16500
 16501
 16502
 16503
 16504
 16505
 16506
 16507
 16508
 16509
 16510
 16511
 16512
 16513
 16514
 16515
 16516
 16517
 16518
 16519
 16520
 16521
 16522
 16523
 16524
 16525
 16526
 16527
 16528
 16529
 16530
 16531
 16532
 16533
 16534
 16535
 16536
 16537
 16538
 16539
 16540
 16541
 16542
 16543
 16544
 16545
 16546
 16547
 16548
 16549
 16550
 16551
 16552
 16553
 16554
 16555
 16556
 16557
 16558
 16559
 16560
 16561
 16562
 16563
 16564
 16565
 16566
 16567
 16568
 16569
 16570
 16571
 16572
 16573
 16574
 16575
 16576
 16577
 16578
 16579
 16580
 16581
 16582
 16583
 16584
 16585
 16586
 16587
 16588
 16589
 16590
 16591
 16592
 16593
 16594
 16595
 16596
 16597
 16598
 16599
 16600
 16601
 16602
 16603
 16604
 16605
 16606
 16607
 16608
 16609
 16610
 16611
 16612
 16613
 16614
 16615
 16616
 16617
 16618
 16619
 16620
 16621
 16622
 16623
 16624
 16625
 16626
 16627
 16628
 16629
 16630
 16631
 16632
 16633
 16634
 16635
 16636
 16637
 16638
 16639
 16640
 16641
 16642
 16643
 16644
 16645
 16646
 16647
 16648
 16649
 16650
 16651
 16652
 16653
 16654
 16655
 16656
 16657
 16658
 16659
 16660
 16661
 16662
 16663
 16664
 16665
 16666
 16667
 16668
 16669
 16670
 16671
 16672
 16673
 16674
 16675
 16676
 16677
 16678
 16679
 16680
 16681
 16682
 16683
 16684
 16685
 16686
 16687
 16688
 16689
 16690
 16691
 16692
 16693
 16694
 16695
 16696
 16697
 16698
 16699
 16700
 16701
 16702
 16703
 16704
 16705
 16706
 16707
 16708
 16709
 16710
 16711
 16712
 16713
 16714
 16715
 16716
 16717
 16718
 16719
 16720
 16721
 16722
 16723
 16724
 16725
 16726
 16727
 16728
 16729
 16730
 16731
 16732
 16733
 16734
 16735
 16736
 16737
 16738
 16739
 16740
 16741
 16742
 16743
 16744
 16745
 16746
 16747
 16748
 16749
 16750
 16751
 16752
 16753
 16754
 16755
 16756
 16757
 16758
 16759
 16760
 16761
 16762
 16763
 16764
 16765
 16766
 16767
 16768
 16769
 16770
 16771
 16772
 16773
 16774
 16775
 16776
 16777
 16778
 16779
 16780
 16781
 16782
 16783
 16784
 16785
 16786
 16787
 16788
 16789
 16790
 16791
 16792
 16793
 16794
 16795
 16796
 16797
 16798
 16799
 16800
 16801
 16802
 16803
 16804
 16805
 16806
 16807
 16808
 16809
 16810
 16811
 16812
 16813
 16814
 16815
 16816
 16817
 16818
 16819
 16820
 16821
 16822
 16823
 16824
 16825
 16826
 16827
 16828
 16829
 16830
 16831
 16832
 16833
 16834
 16835
 16836
 16837
 16838
 16839
 16840
 16841
 16842
 16843
 16844
 16845
 16846
 16847
 16848
 16849
 16850
 16851
 16852
 16853
 16854
 16855
 16856
 16857
 16858
 16859
 16860
 16861
 16862
 16863
 16864
 16865
 16866
 16867
 16868
 16869
 16870
 16871
 16872
 16873
 16874
 16875
 16876
 16877
 16878
 16879
 16880
 16881
 16882
 16883
 16884
 16885
 16886
 16887
 16888
 16889
 16890
 16891
 16892
 16893
 16894
 16895
 16896
 16897
 16898
 16899
 16900
 16901
 16902
 16903
 16904
 16905
 16906
 16907
 16908
 16909
 16910
 16911
 16912
 16913
 16914
 16915
 16916
 16917
 16918
 16919
 16920
 16921
 16922
 16923
 16924
 16925
 16926
 16927
 16928
 16929
 16930
 16931
 16932
 16933
 16934
 16935
 16936
 16937
 16938
 16939
 16940
 16941
 16942
 16943
 16944
 16945
 16946
 16947
 16948
 16949
 16950
 16951
 16952
 16953
 16954
 16955
 16956
 16957
 16958
 16959
 16960
 16961
 16962
 16963
 16964
 16965
 16966
 16967
 16968
 16969
 16970
 16971
 16972
 16973
 16974
 16975
 16976
 16977
 16978
 16979
 16980
 16981
 16982
 16983
 16984
 16985
 16986
 16987
 16988
 16989
 16990
 16991
 16992
 16993
 16994
 16995
 16996
 16997
 16998
 16999
 17000
 17001
 17002
 17003
 17004
 17005
 17006
 17007
 17008
 17009
 17010
 17011
 17012
 17013
 17014
 17015
 17016
 17017
 17018
 17019
 17020
 17021
 17022
 17023
 17024
 17025
 17026
 17027
 17028
 17029
 17030
 17031
 17032
 17033
 17034
 17035
 17036
 17037
 17038
 17039
 17040
 17041
 17042
 17043
 17044
 17045
 17046
 17047
 17048
 17049
 17050
 17051
 17052
 17053
 17054
 17055
 17056
 17057
 17058
 17059
 17060
 17061
 17062
 17063
 17064
 17065
 17066
 17067
 17068
 17069
 17070
 17071
 17072
 17073
 17074
 17075
 17076
 17077
 17078
 17079
 17080
 17081
 17082
 17083
 17084
 17085
 17086
 17087
 17088
 17089
 17090
 17091
 17092
 17093
 17094
 17095
 17096
 17097
 17098
 17099
 17100
 17101
 17102
 17103
 17104
 17105
 17106
 17107
 17108
 17109
 17110
 17111
 17112
 17113
 17114
 17115
 17116
 17117
 17118
 17119
 17120
 17121
 17122
 17123
 17124
 17125
 17126
 17127
 17128
 17129
 17130
 17131
 17132
 17133
 17134
 17135
 17136
 17137
 17138
 17139
 17140
 17141
 17142
 17143
 17144
 17145
 17146
 17147
 17148
 17149
 17150
 17151
 17152
 17153
 17154
 17155
 17156
 17157
 17158
 17159
 17160
 17161
 17162
 17163
 17164
 17165
 17166
 17167
 17168
 17169
 17170
 17171
 17172
 17173
 17174
 17175
 17176
 17177
 17178
 17179
 17180
 17181
 17182
 17183
 17184
 17185
 17186
 17187
 17188
 17189
 17190
 17191
 17192
 17193
 17194
 17195
 17196
 17197
 17198
 17199
 17200
 17201
 17202
 17203
 17204
 17205
 17206
 17207
 17208
 17209
 17210
 17211
 17212
 17213
 17214
 17215
 17216
 17217
 17218
 17219
 17220
 17221
 17222
 17223
 17224
 17225
 17226
 17227
 17228
 17229
 17230
 17231
 17232
 17233
 17234
 17235
 17236
 17237
 17238
 17239
 17240
 17241
 17242
 17243
 17244
 17245
 17246
 17247
 17248
 17249
 17250
 17251
 17252
 17253
 17254
 17255
 17256
 17257
 17258
 17259
 17260
 17261
 17262
 17263
 17264
 17265
 17266
 17267
 17268
 17269
 17270
 17271
 17272
 17273
 17274
 17275
 17276
 17277
 17278
 17279
 17280
 17281
 17282
 17283
 17284
 17285
 17286
 17287
 17288
 17289
 17290
 17291
 17292
 17293
 17294
 17295
 17296
 17297
 17298
 17299
 17300
 17301
 17302
 17303
 17304
 17305
 17306
 17307
 17308
 17309
 17310
 17311
 17312
 17313
 17314
 17315
 17316
 17317
 17318
 17319
 17320
 17321
 17322
 17323
 17324
 17325
 17326
 17327
 17328
 17329
 17330
 17331
 17332
 17333
 17334
 17335
 17336
 17337
 17338
 17339
 17340
 17341
 17342
 17343
 17344
 17345
 17346
 17347
 17348
 17349
 17350
 17351
 17352
 17353
 17354
 17355
 17356
 17357
 17358
 17359
 17360
 17361
 17362
 17363
 17364
 17365
 17366
 17367
 17368
 17369
 17370
 17371
 17372
 17373
 17374
 17375
 17376
 17377
 17378
 17379
 17380
 17381
 17382
 17383
 17384
 17385
 17386
 17387
 17388
 17389
 17390
 17391
 17392
 17393
 17394
 17395
 17396
 17397
 17398
 17399
 17400
 17401
 17402
 17403
 17404
 17405
 17406
 17407
 17408
 17409
 17410
 17411
 17412
 17413
 17414
 17415
 17416
 17417
 17418
 17419
 17420
 17421
 17422
 17423
 17424
 17425
 17426
 17427
 17428
 17429
 17430
 17431
 17432
 17433
 17434
 17435
 17436
 17437
 17438
 17439
 17440
 17441
 17442
 17443
 17444
 17445
 17446
 17447
 17448
 17449
 17450
 17451
 17452
 17453
 17454
 17455
 17456
 17457
 17458
 17459
 17460
 17461
 17462
 17463
 17464
 17465
 17466
 17467
 17468
 17469
 17470
 17471
 17472
 17473
 17474
 17475
 17476
 17477
 17478
 17479
 17480
 17481
 17482
 17483
 17484
 17485
 17486
 17487
 17488
 17489
 17490
 17491
 17492
 17493
 17494
 17495
 17496
 17497
 17498
 17499
 17500
 17501
 17502
 17503
 17504
 17505
 17506
 17507
 17508
 17509
 17510
 17511
 17512
 17513
 17514
 17515
 17516
 17517
 17518
 17519
 17520
 17521
 17522
 17523
 17524
 17525
 17526
 17527
 17528
 17529
 17530
 17531
 17532
 17533
 17534
 17535
 17536
 17537
 17538
 17539
 17540
 17541
 17542
 17543
 17544
 17545
 17546
 17547
 17548
 17549
 17550
 17551
 17552
 17553
 17554
 17555
 17556
 17557
 17558
 17559
 17560
 17561
 17562
 17563
 17564
 17565
 17566
 17567
 17568
 17569
 17570
 17571
 17572
 17573
 17574
 17575
 17576
 17577
 17578
 17579
 17580
 17581
 17582
 17583
 17584
 17585
 17586
 17587
 17588
 17589
 17590
 17591
 17592
 17593
 17594
 17595
 17596
 17597
 17598
 17599
 17600
 17601
 17602
 17603
 17604
 17605
 17606
 17607
 17608
 17609
 17610
 17611
 17612
 17613
 17614
 17615
 17616
 17617
 17618
 17619
 17620
 17621
 17622
 17623
 17624
 17625
 17626
 17627
 17628
 17629
 17630
 17631
 17632
 17633
 17634
 17635
 17636
 17637
 17638
 17639
 17640
 17641
 17642
 17643
 17644
 17645
 17646
 17647
 17648
 17649
 17650
 17651
 17652
 17653
 17654
 17655
 17656
 17657
 17658
 17659
 17660
 17661
 17662
 17663
 17664
 17665
 17666
 17667
 17668
 17669
 17670
 17671
 17672
 17673
 17674
 17675
 17676
 17677
 17678
 17679
 17680
 17681
 17682
 17683
 17684
 17685
 17686
 17687
 17688
 17689
 17690
 17691
 17692
 17693
 17694
 17695
 17696
 17697
 17698
 17699
 17700
 17701
 17702
 17703
 17704
 17705
 17706
 17707
 17708
 17709
 17710
 17711
 17712
 17713
 17714
 17715
 17716
 17717
 17718
 17719
 17720
 17721
 17722
 17723
 17724
 17725
 17726
 17727
 17728
 17729
 17730
 17731
 17732
 17733
 17734
 17735
 17736
 17737
 17738
 17739
 17740
 17741
 17742
 17743
 17744
 17745
 17746
 17747
 17748
 17749
 17750
 17751
 17752
 17753
 17754
 17755
 17756
 17757
 17758
 17759
 17760
 17761
 17762
 17763
 17764
 17765
 17766
 17767
 17768
 17769
 17770
 17771
 17772
 17773
 17774
 17775
 17776
 17777
 17778
 17779
 17780
 17781
 17782
 17783
 17784
 17785
 17786
 17787
 17788
 17789
 17790
 17791
 17792
 17793
 17794
 17795
 17796
 17797
 17798
 17799
 17800
 17801
 17802
 17803
 17804
 17805
 17806
 17807
 17808
 17809
 17810
 17811
 17812
 17813
 17814
 17815
 17816
 17817
 17818
 17819
 17820
 17821
 17822
 17823
 17824
 17825
 17826
 17827
 17828
 17829
 17830
 17831
 17832
 17833
 17834
 17835
 17836
 17837
 17838
 17839
 17840
 17841
 17842
 17843
 17844
 17845
 17846
 17847
 17848
 17849
 17850
 17851
 17852
 17853
 17854
 17855
 17856
 17857
 17858
 17859
 17860
 17861
 17862
 17863
 17864
 17865
 17866
 17867
 17868
 17869
 17870
 17871
 17872
 17873
 17874
 17875
 17876
 17877
 17878
 17879
 17880
 17881
 17882
 17883
 17884
 17885
 17886
 17887
 17888
 17889
 17890
 17891
 17892
 17893
 17894
 17895
 17896
 17897
 17898
 17899
 17900
 17901
 17902
 17903
 17904
 17905
 17906
 17907
 17908
 17909
 17910
 17911
 17912
 17913
 17914
 17915
 17916
 17917
 17918
 17919
 17920
 17921
 17922
 17923
 17924
 17925
 17926
 17927
 17928
 17929
 17930
 17931
 17932
 17933
 17934
 17935
 17936
 17937
 17938
 17939
 17940
 17941
 17942
 17943
 17944
 17945
 17946
 17947
 17948
 17949
 17950
 17951
 17952
 17953
 17954
 17955
 17956
 17957
 17958
 17959
 17960
 17961
 17962
 17963
 17964
 17965
 17966
 17967
 17968
 17969
 17970
 17971
 17972
 17973
 17974
 17975
 17976
 17977
 17978
 17979
 17980
 17981
 17982
 17983
 17984
 17985
 17986
 17987
 17988
 17989
 17990
 17991
 17992
 17993
 17994
 17995
 17996
 17997
 17998
 17999
 18000
 18001
 18002
 18003
 18004
 18005
 18006
 18007
 18008
 18009
 18010
 18011
 18012
 18013
 18014
 18015
 18016
 18017
 18018
 18019
 18020
 18021
 18022
 18023
 18024
 18025
 18026
 18027
 18028
 18029
 18030
 18031
 18032
 18033
 18034
 18035
 18036
 18037
 18038
 18039
 18040
 18041
 18042
 18043
 18044
 18045
 18046
 18047
 18048
 18049
 18050
 18051
 18052
 18053
 18054
 18055
 18056
 18057
 18058
 18059
 18060
 18061
 18062
 18063
 18064
 18065
 18066
 18067
 18068
 18069
 18070
 18071
 18072
 18073
 18074
 18075
 18076
 18077
 18078
 18079
 18080
 18081
 18082
 18083
 18084
 18085
 18086
 18087
 18088
 18089
 18090
 18091
 18092
 18093
 18094
 18095
 18096
 18097
 18098
 18099
 18100
 18101
 18102
 18103
 18104
 18105
 18106
 18107
 18108
 18109
 18110
 18111
 18112
 18113
 18114
 18115
 18116
 18117
 18118
 18119
 18120
 18121
 18122
 18123
 18124
 18125
 18126
 18127
 18128
 18129
 18130
 18131
 18132
 18133
 18134
 18135
 18136
 18137
 18138
 18139
 18140
 18141
 18142
 18143
 18144
 18145
 18146
 18147
 18148
 18149
 18150
 18151
 18152
 18153
 18154
 18155
 18156
 18157
 18158
 18159
 18160
 18161
 18162
 18163
 18164
 18165
 18166
 18167
 18168
 18169
 18170
 18171
 18172
 18173
 18174
 18175
 18176
 18177
 18178
 18179
 18180
 18181
 18182
 18183
 18184
 18185
 18186
 18187
 18188
 18189
 18190
 18191
 18192
 18193
 18194
 18195
 18196
 18197
 18198
 18199
 18200
 18201
 18202
 18203
 18204
 18205
 18206
 18207
 18208
 18209
 18210
 18211
 18212
 18213
 18214
 18215
 18216
 18217
 18218
 18219
 18220
 18221
 18222
 18223
 18224
 18225
 18226
 18227
 18228
 18229
 18230
 18231
 18232
 18233
 18234
 18235
 18236
 18237
 18238
 18239
 18240
 18241
 18242
 18243
 18244
 18245
 18246
 18247
 18248
 18249
 18250
 18251
 18252
 18253
 18254
 18255
 18256
 18257
 18258
 18259
 18260
 18261
 18262
 18263
 18264
 18265
 18266
 18267
 18268
 18269
 18270
 18271
 18272
 18273
 18274
 18275
 18276
 18277
 18278
 18279
 18280
 18281
 18282
 18283
 18284
 18285
 18286
 18287
 18288
 18289
 18290
 18291
 18292
 18293
 18294
 18295
 18296
 18297
 18298
 18299
 18300
 18301
 18302
 18303
 18304
 18305
 18306
 18307
 18308
 18309
 18310
 18311
 18312
 18313
 18314
 18315
 18316
 18317
 18318
 18319
 18320
 18321
 18322
 18323
 18324
 18325
 18326
 18327
 18328
 18329
 18330
 18331
 18332
 18333
 18334
 18335
 18336
 18337
 18338
 18339
 18340
 18341
 18342
 18343
 18344
 18345
 18346
 18347
 18348
 18349
 18350
 18351
 18352
 18353
 18354
 18355
 18356
 18357
 18358
 18359
 18360
 18361
 18362
 18363
 18364
 18365
 18366
 18367
 18368
 18369
 18370
 18371
 18372
 18373
 18374
 18375
 18376
 18377
 18378
 18379
 18380
 18381
 18382
 18383
 18384
 18385
 18386
 18387
 18388
 18389
 18390
 18391
 18392
 18393
 18394
 18395
 18396
 18397
 18398
 18399
 18400
 18401
 18402
 18403
 18404
 18405
 18406
 18407
 18408
 18409
 18410
 18411
 18412
 18413
 18414
 18415
 18416
 18417
 18418
 18419
 18420
 18421
 18422
 18423
 18424
 18425
 18426
 18427
 18428
 18429
 18430
 18431
 18432
 18433
 18434
 18435
 18436
 18437
 18438
 18439
 18440
 18441
 18442
 18443
 18444
 18445
 18446
 18447
 18448
 18449
 18450
 18451
 18452
 18453
 18454
 18455
 18456
 18457
 18458
 18459
 18460
 18461
 18462
 18463
 18464
 18465
 18466
 18467
 18468
 18469
 18470
 18471
 18472
 18473
 18474
 18475
 18476
 18477
 18478
 18479
 18480
 18481
 18482
 18483
 18484
 18485
 18486
 18487
 18488
 18489
 18490
 18491
 18492
 18493
 18494
 18495
 18496
 18497
 18498
 18499
 18500
 18501
 18502
 18503
 18504
 18505
 18506
 18507
 18508
 18509
 18510
 18511
 18512
 18513
 18514
 18515
 18516
 18517
 18518
 18519
 18520
 18521
 18522
 18523
 18524
 18525
 18526
 18527
 18528
 18529
 18530
 18531
 18532
 18533
 18534
 18535
 18536
 18537
 18538
 18539
 18540
 18541
 18542
 18543
 18544
 18545
 18546
 18547
 18548
 18549
 18550
 18551
 18552
 18553
 18554
 18555
 18556
 18557
 18558
 18559
 18560
 18561
 18562
 18563
 18564
 18565
 18566
 18567
 18568
 18569
 18570
 18571
 18572
 18573
 18574
 18575
 18576
 18577
 18578
 18579
 18580
 18581
 18582
 18583
 18584
 18585
 18586
 18587
 18588
 18589
 18590
 18591
 18592
 18593
 18594
 18595
 18596
 18597
 18598
 18599
 18600
 18601
 18602
 18603
 18604
 18605
 18606
 18607
 18608
 18609
 18610
 18611
 18612
 18613
 18614
 18615
 18616
 18617
 18618
 18619
 18620
 18621
 18622
 18623
 18624
 18625
 18626
 18627
 18628
 18629
 18630
 18631
 18632
 18633
 18634
 18635
 18636
 18637
 18638
 18639
 18640
 18641
 18642
 18643
 18644
 18645
 18646
 18647
 18648
 18649
 18650
 18651
 18652
 18653
 18654
 18655
 18656
 18657
 18658
 18659
 18660
 18661
 18662
 18663
 18664
 18665
 18666
 18667
 18668
 18669
 18670
 18671
 18672
 18673
 18674
 18675
 18676
 18677
 18678
 18679
 18680
 18681
 18682
 18683
 18684
 18685
 18686
 18687
 18688
 18689
 18690
 18691
 18692
 18693
 18694
 18695
 18696
 18697
 18698
 18699
 18700
 18701
 18702
 18703
 18704
 18705
 18706
 18707
 18708
 18709
 18710
 18711
 18712
 18713
 18714
 18715
 18716
 18717
 18718
 18719
 18720
 18721
 18722
 18723
 18724
 18725
 18726
 18727
 18728
 18729
 18730
 18731
 18732
 18733
 18734
 18735
 18736
 18737
 18738
 18739
 18740
 18741
 18742
 18743
 18744
 18745
 18746
 18747
 18748
 18749
 18750
 18751
 18752
 18753
 18754
 18755
 18756
 18757
 18758
 18759
 18760
 18761
 18762
 18763
 18764
 18765
 18766
 18767
 18768
 18769
 18770
 18771
 18772
 18773
 18774
 18775
 18776
 18777
 18778
 18779
 18780
 18781
 18782
 18783
 18784
 18785
 18786
 18787
 18788
 18789
 18790
 18791
 18792
 18793
 18794
 18795
 18796
 18797
 18798
 18799
 18800
 18801
 18802
 18803
 18804
 18805
 18806
 18807
 18808
 18809
 18810
 18811
 18812
 18813
 18814
 18815
 18816
 18817
 18818
 18819
 18820
 18821
 18822
 18823
 18824
 18825
 18826
 18827
 18828
 18829
 18830
 18831
 18832
 18833
 18834
 18835
 18836
 18837
 18838
 18839
 18840
 18841
 18842
 18843
 18844
 18845
 18846
 18847
 18848
 18849
 18850
 18851
 18852
 18853
 18854
 18855
 18856
 18857
 18858
 18859
 18860
 18861
 18862
 18863
 18864
 18865
 18866
 18867
 18868
 18869
 18870
 18871
 18872
 18873
 18874
 18875
 18876
 18877
 18878
 18879
 18880
 18881
 18882
 18883
 18884
 18885
 18886
 18887
 18888
 18889
 18890
 18891
 18892
 18893
 18894
 18895
 18896
 18897
 18898
 18899
 18900
 18901
 18902
 18903
 18904
 18905
 18906
 18907
 18908
 18909
 18910
 18911
 18912
 18913
 18914
 18915
 18916
 18917
 18918
 18919
 18920
 18921
 18922
 18923
 18924
 18925
 18926
 18927
 18928
 18929
 18930
 18931
 18932
 18933
 18934
 18935
 18936
 18937
 18938
 18939
 18940
 18941
 18942
 18943
 18944
 18945
 18946
 18947
 18948
 18949
 18950
 18951
 18952
 18953
 18954
 18955
 18956
 18957
 18958
 18959
 18960
 18961
 18962
 18963
 18964
 18965
 18966
 18967
 18968
 18969
 18970
 18971
 18972
 18973
 18974
 18975
 18976
 18977
 18978
 18979
 18980
 18981
 18982
 18983
 18984
 18985
 18986
 18987
 18988
 18989
 18990
 18991
 18992
 18993
 18994
 18995
 18996
 18997
 18998
 18999
 19000
 19001
 19002
 19003
 19004
 19005
 19006
 19007
 19008
 19009
 19010
 19011
 19012
 19013
 19014
 19015
 19016
 19017
 19018
 19019
 19020
 19021
 19022
 19023
 19024
 19025
 19026
 19027
 19028
 19029
 19030
 19031
 19032
 19033
 19034
 19035
 19036
 19037
 19038
 19039
 19040
 19041
 19042
 19043
 19044
 19045
 19046
 19047
 19048
 19049
 19050
 19051
 19052
 19053
 19054
 19055
 19056
 19057
 19058
 19059
 19060
 19061
 19062
 19063
 19064
 19065
 19066
 19067
 19068
 19069
 19070
 19071
 19072
 19073
 19074
 19075
 19076
 19077
 19078
 19079
 19080
 19081
 19082
 19083
 19084
 19085
 19086
 19087
 19088
 19089
 19090
 19091
 19092
 19093
 19094
 19095
 19096
 19097
 19098
 19099
 19100
 19101
 19102
 19103
 19104
 19105
 19106
 19107
 19108
 19109
 19110
 19111
 19112
 19113
 19114
 19115
 19116
 19117
 19118
 19119
 19120
 19121
 19122
 19123
 19124
 19125
 19126
 19127
 19128
 19129
 19130
 19131
 19132
 19133
 19134
 19135
 19136
 19137
 19138
 19139
 19140
 19141
 19142
 19143
 19144
 19145
 19146
 19147
 19148
 19149
 19150
 19151
 19152
 19153
 19154
 19155
 19156
 19157
 19158
 19159
 19160
 19161
 19162
 19163
 19164
 19165
 19166
 19167
 19168
 19169
 19170
 19171
 19172
 19173
 19174
 19175
 19176
 19177
 19178
 19179
 19180
 19181
 19182
 19183
 19184
 19185
 19186
 19187
 19188
 19189
 19190
 19191
 19192
 19193
 19194
 19195
 19196
 19197
 19198
 19199
 19200
 19201
 19202
 19203
 19204
 19205
 19206
 19207
 19208
 19209
 19210
 19211
 19212
 19213
 19214
 19215
 19216
 19217
 19218
 19219
 19220
 19221
 19222
 19223
 19224
 19225
 19226
 19227
 19228
 19229
 19230
 19231
 19232
 19233
 19234
 19235
 19236
 19237
 19238
 19239
 19240
 19241
 19242
 19243
 19244
 19245
 19246
 19247
 19248
 19249
 19250
 19251
 19252
 19253
 19254
 19255
 19256
 19257
 19258
 19259
 19260
 19261
 19262
 19263
 19264
 19265
 19266
 19267
 19268
 19269
 19270
 19271
 19272
 19273
 19274
 19275
 19276
 19277
 19278
 19279
 19280
 19281
 19282
 19283
 19284
 19285
 19286
 19287
 19288
 19289
 19290
 19291
 19292
 19293
 19294
 19295
 19296
 19297
 19298
 19299
 19300
 19301
 19302
 19303
 19304
 19305
 19306
 19307
 19308
 19309
 19310
 19311
 19312
 19313
 19314
 19315
 19316
 19317
 19318
 19319
 19320
 19321
 19322
 19323
 19324
 19325
 19326
 19327
 19328
 19329
 19330
 19331
 19332
 19333
 19334
 19335
 19336
 19337
 19338
 19339
 19340
 19341
 19342
 19343
 19344
 19345
 19346
 19347
 19348
 19349
 19350
 19351
 19352
 19353
 19354
 19355
 19356
 19357
 19358
 19359
 19360
 19361
 19362
 19363
 19364
 19365
 19366
 19367
 19368
 19369
 19370
 19371
 19372
 19373
 19374
 19375
 19376
 19377
 19378
 19379
 19380
 19381
 19382
 19383
 19384
 19385
 19386
 19387
 19388
 19389
 19390
 19391
 19392
 19393
 19394
 19395
 19396
 19397
 19398
 19399
 19400
 19401
 19402
 19403
 19404
 19405
 19406
 19407
 19408
 19409
 19410
 19411
 19412
 19413
 19414
 19415
 19416
 19417
 19418
 19419
 19420
 19421
 19422
 19423
 19424
 19425
 19426
 19427
 19428
 19429
 19430
 19431
 19432
 19433
 19434
 19435
 19436
 19437
 19438
 19439
 19440
 19441
 19442
 19443
 19444
 19445
 19446
 19447
 19448
 19449
 19450
 19451
 19452
 19453
 19454
 19455
 19456
 19457
 19458
 19459
 19460
 19461
 19462
 19463
 19464
 19465
 19466
 19467
 19468
 19469
 19470
 19471
 19472
 19473
 19474
 19475
 19476
 19477
 19478
 19479
 19480
 19481
 19482
 19483
 19484
 19485
 19486
 19487
 19488
 19489
 19490
 19491
 19492
 19493
 19494
 19495
 19496
 19497
 19498
 19499
 19500
 19501
 19502
 19503
 19504
 19505
 19506
 19507
 19508
 19509
 19510
 19511
 19512
 19513
 19514
 19515
 19516
 19517
 19518
 19519
 19520
 19521
 19522
 19523
 19524
 19525
 19526
 19527
 19528
 19529
 19530
 19531
 19532
 19533
 19534
 19535
 19536
 19537
 19538
 19539
 19540
 19541
 19542
 19543
 19544
 19545
 19546
 19547
 19548
 19549
 19550
 19551
 19552
 19553
 19554
 19555
 19556
 19557
 19558
 19559
 19560
 19561
 19562
 19563
 19564
 19565
 19566
 19567
 19568
 19569
 19570
 19571
 19572
 19573
 19574
 19575
 19576
 19577
 19578
 19579
 19580
 19581
 19582
 19583
 19584
 19585
 19586
 19587
 19588
 19589
 19590
 19591
 19592
 19593
 19594
 19595
 19596
 19597
 19598
 19599
 19600
 19601
 19602
 19603
 19604
 19605
 19606
 19607
 19608
 19609
 19610
 19611
 19612
 19613
 19614
 19615
 19616
 19617
 19618
 19619
 19620
 19621
 19622
 19623
 19624
 19625
 19626
 19627
 19628
 19629
 19630
 19631
 19632
 19633
 19634
 19635
 19636
 19637
 19638
 19639
 19640
 19641
 19642
 19643
 19644
 19645
 19646
 19647
 19648
 19649
 19650
 19651
 19652
 19653
 19654
 19655
 19656
 19657
 19658
 19659
 19660
 19661
 19662
 19663
 19664
 19665
 19666
 19667
 19668
 19669
 19670
 19671
 19672
 19673
 19674
 19675
 19676
 19677
 19678
 19679
 19680
 19681
 19682
 19683
 19684
 19685
 19686
 19687
 19688
 19689
 19690
 19691
 19692
 19693
 19694
 19695
 19696
 19697
 19698
 19699
 19700
 19701
 19702
 19703
 19704
 19705
 19706
 19707
 19708
 19709
 19710
 19711
 19712
 19713
 19714
 19715
 19716
 19717
 19718
 19719
 19720
 19721
 19722
 19723
 19724
 19725
 19726
 19727
 19728
 19729
 19730
 19731
 19732
 19733
 19734
 19735
 19736
 19737
 19738
 19739
 19740
 19741
 19742
 19743
 19744
 19745
 19746
 19747
 19748
 19749
 19750
 19751
 19752
 19753
 19754
 19755
 19756
 19757
 19758
 19759
 19760
 19761
 19762
 19763
 19764
 19765
 19766
 19767
 19768
 19769
 19770
 19771
 19772
 19773
 19774
 19775
 19776
 19777
 19778
 19779
 19780
 19781
 19782
 19783
 19784
 19785
 19786
 19787
 19788
 19789
 19790
 19791
 19792
 19793
 19794
 19795
 19796
 19797
 19798
 19799
 19800
 19801
 19802
 19803
 19804
 19805
 19806
 19807
 19808
 19809
 19810
 19811
 19812
 19813
 19814
 19815
 19816
 19817
 19818
 19819
 19820
 19821
 19822
 19823
 19824
 19825
 19826
 19827
 19828
 19829
 19830
 19831
 19832
 19833
 19834
 19835
 19836
 19837
 19838
 19839
 19840
 19841
 19842
 19843
 19844
 19845
 19846
 19847
 19848
 19849
 19850
 19851
 19852
 19853
 19854
 19855
 19856
 19857
 19858
 19859
 19860
 19861
 19862
 19863
 19864
 19865
 19866
 19867
 19868
 19869
 19870
 19871
 19872
 19873
 19874
 19875
 19876
 19877
 19878
 19879
 19880
 19881
 19882
 19883
 19884
 19885
 19886
 19887
 19888
 19889
 19890
 19891
 19892
 19893
 19894
 19895
 19896
 19897
 19898
 19899
 19900
 19901
 19902
 19903
 19904
 19905
 19906
 19907
 19908
 19909
 19910
 19911
 19912
 19913
 19914
 19915
 19916
 19917
 19918
 19919
 19920
 19921
 19922
 19923
 19924
 19925
 19926
 19927
 19928
 19929
 19930
 19931
 19932
 19933
 19934
 19935
 19936
 19937
 19938
 19939
 19940
 19941
 19942
 19943
 19944
 19945
 19946
 19947
 19948
 19949
 19950
 19951
 19952
 19953
 19954
 19955
 19956
 19957
 19958
 19959
 19960
 19961
 19962
 19963
 19964
 19965
 19966
 19967
 19968
 19969
 19970
 19971
 19972
 19973
 19974
 19975
 19976
 19977
 19978
 19979
 19980
 19981
 19982
 19983
 19984
 19985
 19986
 19987
 19988
 19989
 19990
 19991
 19992
 19993
 19994
 19995
 19996
 19997
 19998
 19999
 20000
 20001
 20002
 20003
 20004
 20005
 20006
 20007
 20008
 20009
 20010
 20011
 20012
 20013
 20014
 20015
 20016
 20017
 20018
 20019
 20020
 20021
 20022
 20023
 20024
 20025
 20026
 20027
 20028
 20029
 20030
 20031
 20032
 20033
 20034
 20035
 20036
 20037
 20038
 20039
 20040
 20041
 20042
 20043
 20044
 20045
 20046
 20047
 20048
 20049
 20050
 20051
 20052
 20053
 20054
 20055
 20056
 20057
 20058
 20059
 20060
 20061
 20062
 20063
 20064
 20065
 20066
 20067
 20068
 20069
 20070
 20071
 20072
 20073
 20074
 20075
 20076
 20077
 20078
 20079
 20080
 20081
 20082
 20083
 20084
 20085
 20086
 20087
 20088
 20089
 20090
 20091
 20092
 20093
 20094
 20095
 20096
 20097
 20098
 20099
 20100
 20101
 20102
 20103
 20104
 20105
 20106
 20107
 20108
 20109
 20110
 20111
 20112
 20113
 20114
 20115
 20116
 20117
 20118
 20119
 20120
 20121
 20122
 20123
 20124
 20125
 20126
 20127
 20128
 20129
 20130
 20131
 20132
 20133
 20134
 20135
 20136
 20137
 20138
 20139
 20140
 20141
 20142
 20143
 20144
 20145
 20146
 20147
 20148
 20149
 20150
 20151
 20152
 20153
 20154
 20155
 20156
 20157
 20158
 20159
 20160
 20161
 20162
 20163
 20164
 20165
 20166
 20167
 20168
 20169
 20170
 20171
 20172
 20173
 20174
 20175
 20176
 20177
 20178
 20179
 20180
 20181
 20182
 20183
 20184
 20185
 20186
 20187
 20188
 20189
 20190
 20191
 20192
 20193
 20194
 20195
 20196
 20197
 20198
 20199
 20200
 20201
 20202
 20203
 20204
 20205
 20206
 20207
 20208
 20209
 20210
 20211
 20212
 20213
 20214
 20215
 20216
 20217
 20218
 20219
 20220
 20221
 20222
 20223
 20224
 20225
 20226
 20227
 20228
 20229
 20230
 20231
 20232
 20233
 20234
 20235
 20236
 20237
 20238
 20239
 20240
 20241
 20242
 20243
 20244
 20245
 20246
 20247
 20248
 20249
 20250
 20251
 20252
 20253
 20254
 20255
 20256
 20257
 20258
 20259
 20260
 20261
 20262
 20263
 20264
 20265
 20266
 20267
 20268
 20269
 20270
 20271
 20272
 20273
 20274
 20275
 20276
 20277
 20278
 20279
 20280
 20281
 20282
 20283
 20284
 20285
 20286
 20287
 20288
 20289
 20290
 20291
 20292
 20293
 20294
 20295
 20296
 20297
 20298
 20299
 20300
 20301
 20302
 20303
 20304
 20305
 20306
 20307
 20308
 20309
 20310
 20311
 20312
 20313
 20314
 20315
 20316
 20317
 20318
 20319
 20320
 20321
 20322
 20323
 20324
 20325
 20326
 20327
 20328
 20329
 20330
 20331
 20332
 20333
 20334
 20335
 20336
 20337
 20338
 20339
 20340
 20341
 20342
 20343
 20344
 20345
 20346
 20347
 20348
 20349
 20350
 20351
 20352
 20353
 20354
 20355
 20356
 20357
 20358
 20359
 20360
 20361
 20362
 20363
 20364
 20365
 20366
 20367
 20368
 20369
 20370
 20371
 20372
 20373
 20374
 20375
 20376
 20377
 20378
 20379
 20380
 20381
 20382
 20383
 20384
 20385
 20386
 20387
 20388
 20389
 20390
 20391
 20392
 20393
 20394
 20395
 20396
 20397
 20398
 20399
 20400
 20401
 20402
 20403
 20404
 20405
 20406
 20407
 20408
 20409
 20410
 20411
 20412
 20413
 20414
 20415
 20416
 20417
 20418
 20419
 20420
 20421
 20422
 20423
 20424
 20425
 20426
 20427
 20428
 20429
 20430
 20431
 20432
 20433
 20434
 20435
 20436
 20437
 20438
 20439
 20440
 20441
 20442
 20443
 20444
 20445
 20446
 20447
 20448
 20449
 20450
 20451
 20452
 20453
 20454
 20455
 20456
 20457
 20458
 20459
 20460
 20461
 20462
 20463
 20464
 20465
 20466
 20467
 20468
 20469
 20470
 20471
 20472
 20473
 20474
 20475
 20476
 20477
 20478
 20479
 20480
 20481
 20482
 20483
 20484
 20485
 20486
 20487
 20488
 20489
 20490
 20491
 20492
 20493
 20494
 20495
 20496
 20497
 20498
 20499
 20500
 20501
 20502
 20503
 20504
 20505
 20506
 20507
 20508
 20509
 20510
 20511
 20512
 20513
 20514
 20515
 20516
 20517
 20518
 20519
 20520
 20521
 20522
 20523
 20524
 20525
 20526
 20527
 20528
 20529
 20530
 20531
 20532
 20533
 20534
 20535
 20536
 20537
 20538
 20539
 20540
 20541
 20542
 20543
 20544
 20545
 20546
 20547
 20548
 20549
 20550
 20551
 20552
 20553
 20554
 20555
 20556
 20557
 20558
 20559
 20560
 20561
 20562
 20563
 20564
 20565
 20566
 20567
 20568
 20569
 20570
 20571
 20572
 20573
 20574
 20575
 20576
 20577
 20578
 20579
 20580
 20581
 20582
 20583
 20584
 20585
 20586
 20587
 20588
 20589
 20590
 20591
 20592
 20593
 20594
 20595
 20596
 20597
 20598
 20599
 20600
 20601
 20602
 20603
 20604
 20605
 20606
 20607
 20608
 20609
 20610
 20611
 20612
 20613
 20614
 20615
 20616
 20617
 20618
 20619
 20620
 20621
 20622
 20623
 20624
 20625
 20626
 20627
 20628
 20629
 20630
 20631
 20632
 20633
 20634
 20635
 20636
 20637
 20638
 20639
 20640
 20641
 20642
 20643
 20644
 20645
 20646
 20647
 20648
 20649
 20650
 20651
 20652
 20653
 20654
 20655
 20656
 20657
 20658
 20659
 20660
 20661
 20662
 20663
 20664
 20665
 20666
 20667
 20668
 20669
 20670
 20671
 20672
 20673
 20674
 20675
 20676
 20677
 20678
 20679
 20680
 20681
 20682
 20683
 20684
 20685
 20686
 20687
 20688
 20689
 20690
 20691
 20692
 20693
 20694
 20695
 20696
 20697
 20698
 20699
 20700
 20701
 20702
 20703
 20704
 20705
 20706
 20707
 20708
 20709
 20710
 20711
 20712
 20713
 20714
 20715
 20716
 20717
 20718
 20719
 20720
 20721
 20722
 20723
 20724
 20725
 20726
 20727
 20728
 20729
 20730
 20731
 20732
 20733
 20734
 20735
 20736
 20737
 20738
 20739
 20740
 20741
 20742
 20743
 20744
 20745
 20746
 20747
 20748
 20749
 20750
 20751
 20752
 20753
 20754
 20755
 20756
 20757
 20758
 20759
 20760
 20761
 20762
 20763
 20764
 20765
 20766
 20767
 20768
 20769
 20770
 20771
 20772
 20773
 20774
 20775
 20776
 20777
 20778
 20779
 20780
 20781
 20782
 20783
 20784
 20785
 20786
 20787
 20788
 20789
 20790
 20791
 20792
 20793
 20794
 20795
 20796
 20797
 20798
 20799
 20800
 20801
 20802
 20803
 20804
 20805
 20806
 20807
 20808
 20809
 20810
 20811
 20812
 20813
 20814
 20815
 20816
 20817
 20818
 20819
 20820
 20821
 20822
 20823
 20824
 20825
 20826
 20827
 20828
 20829
 20830
 20831
 20832
 20833
 20834
 20835
 20836
 20837
 20838
 20839
 20840
 20841
 20842
 20843
 20844
 20845
 20846
 20847
 20848
 20849
 20850
 20851
 20852
 20853
 20854
 20855
 20856
 20857
 20858
 20859
 20860
 20861
 20862
 20863
 20864
 20865
 20866
 20867
 20868
 20869
 20870
 20871
 20872
 20873
 20874
 20875
 20876
 20877
 20878
 20879
 20880
 20881
 20882
 20883
 20884
 20885
 20886
 20887
 20888
 20889
 20890
 20891
 20892
 20893
 20894
 20895
 20896
 20897
 20898
 20899
 20900
 20901
 20902
 20903
 20904
 20905
 20906
 20907
 20908
 20909
 20910
 20911
 20912
 20913
 20914
 20915
 20916
 20917
 20918
 20919
 20920
 20921
 20922
 20923
 20924
 20925
 20926
 20927
 20928
 20929
 20930
 20931
 20932
 20933
 20934
 20935
 20936
 20937
 20938
 20939
 20940
 20941
 20942
 20943
 20944
 20945
 20946
 20947
 20948
 20949
 20950
 20951
 20952
 20953
 20954
 20955
 20956
 20957
 20958
 20959
 20960
 20961
 20962
 20963
 20964
 20965
 20966
 20967
 20968
 20969
 20970
 20971
 20972
 20973
 20974
 20975
 20976
 20977
 20978
 20979
 20980
 20981
 20982
 20983
 20984
 20985
 20986
 20987
 20988
 20989
 20990
 20991
 20992
 20993
 20994
 20995
 20996
 20997
 20998
 20999
 21000
 21001
 21002
 21003
 21004
 21005
 21006
 21007
 21008
 21009
 21010
 21011
 21012
 21013
 21014
 21015
 21016
 21017
 21018
 21019
 21020
 21021
 21022
 21023
 21024
 21025
 21026
 21027
 21028
 21029
 21030
 21031
 21032
 21033
 21034
 21035
 21036
 21037
 21038
 21039
 21040
 21041
 21042
 21043
 21044
 21045
 21046
 21047
 21048
 21049
 21050
 21051
 21052
 21053
 21054
 21055
 21056
 21057
 21058
 21059
 21060
 21061
 21062
 21063
 21064
 21065
 21066
 21067
 21068
 21069
 21070
 21071
 21072
 21073
 21074
 21075
 21076
 21077
 21078
 21079
 21080
 21081
 21082
 21083
 21084
 21085
 21086
 21087
 21088
 21089
 21090
 21091
 21092
 21093
 21094
 21095
 21096
 21097
 21098
 21099
 21100
 21101
 21102
 21103
 21104
 21105
 21106
 21107
 21108
 21109
 21110
 21111
 21112
 21113
 21114
 21115
 21116
 21117
 21118
 21119
 21120
 21121
 21122
 21123
 21124
 21125
 21126
 21127
 21128
 21129
 21130
 21131
 21132
 21133
 21134
 21135
 21136
 21137
 21138
 21139
 21140
 21141
 21142
 21143
 21144
 21145
 21146
 21147
 21148
 21149
 21150
 21151
 21152
 21153
 21154
 21155
 21156
 21157
 21158
 21159
 21160
 21161
 21162
 21163
 21164
 21165
 21166
 21167
 21168
 21169
 21170
 21171
 21172
 21173
 21174
 21175
 21176
 21177
 21178
 21179
 21180
 21181
 21182
 21183
 21184
 21185
 21186
 21187
 21188
 21189
 21190
 21191
 21192
 21193
 21194
 21195
 21196
 21197
 21198
 21199
 21200
 21201
 21202
 21203
 21204
 21205
 21206
 21207
 21208
 21209
 21210
 21211
 21212
 21213
 21214
 21215
 21216
 21217
 21218
 21219
 21220
 21221
 21222
 21223
 21224
 21225
 21226
 21227
 21228
 21229
 21230
 21231
 21232
 21233
 21234
 21235
 21236
 21237
 21238
 21239
 21240
 21241
 21242
 21243
 21244
 21245
 21246
 21247
 21248
 21249
 21250
 21251
 21252
 21253
 21254
 21255
 21256
 21257
 21258
 21259
 21260
 21261
 21262
 21263
 21264
 21265
 21266
 21267
 21268
 21269
 21270
 21271
 21272
 21273
 21274
 21275
 21276
 21277
 21278
 21279
 21280
 21281
 21282
 21283
 21284
 21285
 21286
 21287
 21288
 21289
 21290
 21291
 21292
 21293
 21294
 21295
 21296
 21297
 21298
 21299
 21300
 21301
 21302
 21303
 21304
 21305
 21306
 21307
 21308
 21309
 21310
 21311
 21312
 21313
 21314
 21315
 21316
 21317
 21318
 21319
 21320
 21321
 21322
 21323
 21324
 21325
 21326
 21327
 21328
 21329
 21330
 21331
 21332
 21333
 21334
 21335
 21336
 21337
 21338
 21339
 21340
 21341
 21342
 21343
 21344
 21345
 21346
 21347
 21348
 21349
 21350
 21351
 21352
 21353
 21354
 21355
 21356
 21357
 21358
 21359
 21360
 21361
 21362
 21363
 21364
 21365
 21366
 21367
 21368
 21369
 21370
 21371
 21372
 21373
 21374
 21375
 21376
 21377
 21378
 21379
 21380
 21381
 21382
 21383
 21384
 21385
 21386
 21387
 21388
 21389
 21390
 21391
 21392
 21393
 21394
 21395
 21396
 21397
 21398
 21399
 21400
 21401
 21402
 21403
 21404
 21405
 21406
 21407
 21408
 21409
 21410
 21411
 21412
 21413
 21414
 21415
 21416
 21417
 21418
 21419
 21420
 21421
 21422
 21423
 21424
 21425
 21426
 21427
 21428
 21429
 21430
 21431
 21432
 21433
 21434
 21435
 21436
 21437
 21438
 21439
 21440
 21441
 21442
 21443
 21444
 21445
 21446
 21447
 21448
 21449
 21450
 21451
 21452
 21453
 21454
 21455
 21456
 21457
 21458
 21459
 21460
 21461
 21462
 21463
 21464
 21465
 21466
 21467
 21468
 21469
 21470
 21471
 21472
 21473
 21474
 21475
 21476
 21477
 21478
 21479
 21480
 21481
 21482
 21483
 21484
 21485
 21486
 21487
 21488
 21489
 21490
 21491
 21492
 21493
 21494
 21495
 21496
 21497
 21498
 21499
 21500
 21501
 21502
 21503
 21504
 21505
 21506
 21507
 21508
 21509
 21510
 21511
 21512
 21513
 21514
 21515
 21516
 21517
 21518
 21519
 21520
 21521
 21522
 21523
 21524
 21525
 21526
 21527
 21528
 21529
 21530
 21531
 21532
 21533
 21534
 21535
 21536
 21537
 21538
 21539
 21540
 21541
 21542
 21543
 21544
 21545
 21546
 21547
 21548
 21549
 21550
 21551
 21552
 21553
 21554
 21555
 21556
 21557
 21558
 21559
 21560
 21561
 21562
 21563
 21564
 21565
 21566
 21567
 21568
 21569
 21570
 21571
 21572
 21573
 21574
 21575
 21576
 21577
 21578
 21579
 21580
 21581
 21582
 21583
 21584
 21585
 21586
 21587
 21588
 21589
 21590
 21591
 21592
 21593
 21594
 21595
 21596
 21597
 21598
 21599
 21600
 21601
 21602
 21603
 21604
 21605
 21606
 21607
 21608
 21609
 21610
 21611
 21612
 21613
 21614
 21615
 21616
 21617
 21618
 21619
 21620
 21621
 21622
 21623
 21624
 21625
 21626
 21627
 21628
 21629
 21630
 21631
 21632
 21633
 21634
 21635
 21636
 21637
 21638
 21639
 21640
 21641
 21642
 21643
 21644
 21645
 21646
 21647
 21648
 21649
 21650
 21651
 21652
 21653
 21654
 21655
 21656
 21657
 21658
 21659
 21660
 21661
 21662
 21663
 21664
 21665
 21666
 21667
 21668
 21669
 21670
 21671
 21672
 21673
 21674
 21675
 21676
 21677
 21678
 21679
 21680
 21681
 21682
 21683
 21684
 21685
 21686
 21687
 21688
 21689
 21690
 21691
 21692
 21693
 21694
 21695
 21696
 21697
 21698
 21699
 21700
 21701
 21702
 21703
 21704
 21705
 21706
 21707
 21708
 21709
 21710
 21711
 21712
 21713
 21714
 21715
 21716
 21717
 21718
 21719
 21720
 21721
 21722
 21723
 21724
 21725
 21726
 21727
 21728
 21729
 21730
 21731
 21732
 21733
 21734
 21735
 21736
 21737
 21738
 21739
 21740
 21741
 21742
 21743
 21744
 21745
 21746
 21747
 21748
 21749
 21750
 21751
 21752
 21753
 21754
 21755
 21756
 21757
 21758
 21759
 21760
 21761
 21762
 21763
 21764
 21765
 21766
 21767
 21768
 21769
 21770
 21771
 21772
 21773
 21774
 21775
 21776
 21777
 21778
 21779
 21780
 21781
 21782
 21783
 21784
 21785
 21786
 21787
 21788
 21789
 21790
 21791
 21792
 21793
 21794
 21795
 21796
 21797
 21798
 21799
 21800
 21801
 21802
 21803
 21804
 21805
 21806
 21807
 21808
 21809
 21810
 21811
 21812
 21813
 21814
 21815
 21816
 21817
 21818
 21819
 21820
 21821
 21822
 21823
 21824
 21825
 21826
 21827
 21828
 21829
 21830
 21831
 21832
 21833
 21834
 21835
 21836
 21837
 21838
 21839
 21840
 21841
 21842
 21843
 21844
 21845
 21846
 21847
 21848
 21849
 21850
 21851
 21852
 21853
 21854
 21855
 21856
 21857
 21858
 21859
 21860
 21861
 21862
 21863
 21864
 21865
 21866
 21867
 21868
 21869
 21870
 21871
 21872
 21873
 21874
 21875
 21876
 21877
 21878
 21879
 21880
 21881
 21882
 21883
 21884
 21885
 21886
 21887
 21888
 21889
 21890
 21891
 21892
 21893
 21894
 21895
 21896
 21897
 21898
 21899
 21900
 21901
 21902
 21903
 21904
 21905
 21906
 21907
 21908
 21909
 21910
 21911
 21912
 21913
 21914
 21915
 21916
 21917
 21918
 21919
 21920
 21921
 21922
 21923
 21924
 21925
 21926
 21927
 21928
 21929
 21930
 21931
 21932
 21933
 21934
 21935
 21936
 21937
 21938
 21939
 21940
 21941
 21942
 21943
 21944
 21945
 21946
 21947
 21948
 21949
 21950
 21951
 21952
 21953
 21954
 21955
 21956
 21957
 21958
 21959
 21960
 21961
 21962
 21963
 21964
 21965
 21966
 21967
 21968
 21969
 21970
 21971
 21972
 21973
 21974
 21975
 21976
 21977
 21978
 21979
 21980
 21981
 21982
 21983
 21984
 21985
 21986
 21987
 21988
 21989
 21990
 21991
 21992
 21993
 21994
 21995
 21996
 21997
 21998
 21999
 22000
 22001
 22002
 22003
 22004
 22005
 22006
 22007
 22008
 22009
 22010
 22011
 22012
 22013
 22014
 22015
 22016
 22017
 22018
 22019
 22020
 22021
 22022
 22023
 22024
 22025
 22026
 22027
 22028
 22029
 22030
 22031
 22032
 22033
 22034
 22035
 22036
 22037
 22038
 22039
 22040
 22041
 22042
 22043
 22044
 22045
 22046
 22047
 22048
 22049
 22050
 22051
 22052
 22053
 22054
 22055
 22056
 22057
 22058
 22059
 22060
 22061
 22062
 22063
 22064
 22065
 22066
 22067
 22068
 22069
 22070
 22071
 22072
 22073
 22074
 22075
 22076
 22077
 22078
 22079
 22080
 22081
 22082
 22083
 22084
 22085
 22086
 22087
 22088
 22089
 22090
 22091
 22092
 22093
 22094
 22095
 22096
 22097
 22098
 22099
 22100
 22101
 22102
 22103
 22104
 22105
 22106
 22107
 22108
 22109
 22110
 22111
 22112
 22113
 22114
 22115
 22116
 22117
 22118
 22119
 22120
 22121
 22122
 22123
 22124
 22125
 22126
 22127
 22128
 22129
 22130
 22131
 22132
 22133
 22134
 22135
 22136
 22137
 22138
 22139
 22140
 22141
 22142
 22143
 22144
 22145
 22146
 22147
 22148
 22149
 22150
 22151
 22152
 22153
 22154
 22155
 22156
 22157
 22158
 22159
 22160
 22161
 22162
 22163
 22164
 22165
 22166
 22167
 22168
 22169
 22170
 22171
 22172
 22173
 22174
 22175
 22176
 22177
 22178
 22179
 22180
 22181
 22182
 22183
 22184
 22185
 22186
 22187
 22188
 22189
 22190
 22191
 22192
 22193
 22194
 22195
 22196
 22197
 22198
 22199
 22200
 22201
 22202
 22203
 22204
 22205
 22206
 22207
 22208
 22209
 22210
 22211
 22212
 22213
 22214
 22215
 22216
 22217
 22218
 22219
 22220
 22221
 22222
 22223
 22224
 22225
 22226
 22227
 22228
 22229
 22230
 22231
 22232
 22233
 22234
 22235
 22236
 22237
 22238
 22239
 22240
 22241
 22242
 22243
 22244
 22245
 22246
 22247
 22248
 22249
 22250
 22251
 22252
 22253
 22254
 22255
 22256
 22257
 22258
 22259
 22260
 22261
 22262
 22263
 22264
 22265
 22266
 22267
 22268
 22269
 22270
 22271
 22272
 22273
 22274
 22275
 22276
 22277
 22278
 22279
 22280
 22281
 22282
 22283
 22284
 22285
 22286
 22287
 22288
 22289
 22290
 22291
 22292
 22293
 22294
 22295
 22296
 22297
 22298
 22299
 22300
 22301
 22302
 22303
 22304
 22305
 22306
 22307
 22308
 22309
 22310
 22311
 22312
 22313
 22314
 22315
 22316
 22317
 22318
 22319
 22320
 22321
 22322
 22323
 22324
 22325
 22326
 22327
 22328
 22329
 22330
 22331
 22332
 22333
 22334
 22335
 22336
 22337
 22338
 22339
 22340
 22341
 22342
 22343
 22344
 22345
 22346
 22347
 22348
 22349
 22350
 22351
 22352
 22353
 22354
 22355
 22356
 22357
 22358
 22359
 22360
 22361
 22362
 22363
 22364
 22365
 22366
 22367
 22368
 22369
 22370
 22371
 22372
 22373
 22374
 22375
 22376
 22377
 22378
 22379
 22380
 22381
 22382
 22383
 22384
 22385
 22386
 22387
 22388
 22389
 22390
 22391
 22392
 22393
 22394
 22395
 22396
 22397
 22398
 22399
 22400
 22401
 22402
 22403
 22404
 22405
 22406
 22407
 22408
 22409
 22410
 22411
 22412
 22413
 22414
 22415
 22416
 22417
 22418
 22419
 22420
 22421
 22422
 22423
 22424
 22425
 22426
 22427
 22428
 22429
 22430
 22431
 22432
 22433
 22434
 22435
 22436
 22437
 22438
 22439
 22440
 22441
 22442
 22443
 22444
 22445
 22446
 22447
 22448
 22449
 22450
 22451
 22452
 22453
 22454
 22455
 22456
 22457
 22458
 22459
 22460
 22461
 22462
 22463
 22464
 22465
 22466
 22467
 22468
 22469
 22470
 22471
 22472
 22473
 22474
 22475
 22476
 22477
 22478
 22479
 22480
 22481
 22482
 22483
 22484
 22485
 22486
 22487
 22488
 22489
 22490
 22491
 22492
 22493
 22494
 22495
 22496
 22497
 22498
 22499
 22500
 22501
 22502
 22503
 22504
 22505
 22506
 22507
 22508
 22509
 22510
 22511
 22512
 22513
 22514
 22515
 22516
 22517
 22518
 22519
 22520
 22521
 22522
 22523
 22524
 22525
 22526
 22527
 22528
 22529
 22530
 22531
 22532
 22533
 22534
 22535
 22536
 22537
 22538
 22539
 22540
 22541
 22542
 22543
 22544
 22545
 22546
 22547
 22548
 22549
 22550
 22551
 22552
 22553
 22554
 22555
 22556
 22557
 22558
 22559
 22560
 22561
 22562
 22563
 22564
 22565
 22566
 22567
 22568
 22569
 22570
 22571
 22572
 22573
 22574
 22575
 22576
 22577
 22578
 22579
 22580
 22581
 22582
 22583
 22584
 22585
 22586
 22587
 22588
 22589
 22590
 22591
 22592
 22593
 22594
 22595
 22596
 22597
 22598
 22599
 22600
 22601
 22602
 22603
 22604
 22605
 22606
 22607
 22608
 22609
 22610
 22611
 22612
 22613
 22614
 22615
 22616
 22617
 22618
 22619
 22620
 22621
 22622
 22623
 22624
 22625
 22626
 22627
 22628
 22629
 22630
 22631
 22632
 22633
 22634
 22635
 22636
 22637
 22638
 22639
 22640
 22641
 22642
 22643
 22644
 22645
 22646
 22647
 22648
 22649
 22650
 22651
 22652
 22653
 22654
 22655
 22656
 22657
 22658
 22659
 22660
 22661
 22662
 22663
 22664
 22665
 22666
 22667
 22668
 22669
 22670
 22671
 22672
 22673
 22674
 22675
 22676
 22677
 22678
 22679
 22680
 22681
 22682
 22683
 22684
 22685
 22686
 22687
 22688
 22689
 22690
 22691
 22692
 22693
 22694
 22695
 22696
 22697
 22698
 22699
 22700
 22701
 22702
 22703
 22704
 22705
 22706
 22707
 22708
 22709
 22710
 22711
 22712
 22713
 22714
 22715
 22716
 22717
 22718
 22719
 22720
 22721
 22722
 22723
 22724
 22725
 22726
 22727
 22728
 22729
 22730
 22731
 22732
 22733
 22734
 22735
 22736
 22737
 22738
 22739
 22740
 22741
 22742
 22743
 22744
 22745
 22746
 22747
 22748
 22749
 22750
 22751
 22752
 22753
 22754
 22755
 22756
 22757
 22758
 22759
 22760
 22761
 22762
 22763
 22764
 22765
 22766
 22767
 22768
 22769
 22770
 22771
 22772
 22773
 22774
 22775
 22776
 22777
 22778
 22779
 22780
 22781
 22782
 22783
 22784
 22785
 22786
 22787
 22788
 22789
 22790
 22791
 22792
 22793
 22794
 22795
 22796
 22797
 22798
 22799
 22800
 22801
 22802
 22803
 22804
 22805
 22806
 22807
 22808
 22809
 22810
 22811
 22812
 22813
 22814
 22815
 22816
 22817
 22818
 22819
 22820
 22821
 22822
 22823
 22824
 22825
 22826
 22827
 22828
 22829
 22830
 22831
 22832
 22833
 22834
 22835
 22836
 22837
 22838
 22839
 22840
 22841
 22842
 22843
 22844
 22845
 22846
 22847
 22848
 22849
 22850
 22851
 22852
 22853
 22854
 22855
 22856
 22857
 22858
 22859
 22860
 22861
 22862
 22863
 22864
 22865
 22866
 22867
 22868
 22869
 22870
 22871
 22872
 22873
 22874
 22875
 22876
 22877
 22878
 22879
 22880
 22881
 22882
 22883
 22884
 22885
 22886
 22887
 22888
 22889
 22890
 22891
 22892
 22893
 22894
 22895
 22896
 22897
 22898
 22899
 22900
 22901
 22902
 22903
 22904
 22905
 22906
 22907
 22908
 22909
 22910
 22911
 22912
 22913
 22914
 22915
 22916
 22917
 22918
 22919
 22920
 22921
 22922
 22923
 22924
 22925
 22926
 22927
 22928
 22929
 22930
 22931
 22932
 22933
 22934
 22935
 22936
 22937
 22938
 22939
 22940
 22941
 22942
 22943
 22944
 22945
 22946
 22947
 22948
 22949
 22950
 22951
 22952
 22953
 22954
 22955
 22956
 22957
 22958
 22959
 22960
 22961
 22962
 22963
 22964
 22965
 22966
 22967
 22968
 22969
 22970
 22971
 22972
 22973
 22974
 22975
 22976
 22977
 22978
 22979
 22980
 22981
 22982
 22983
 22984
 22985
 22986
 22987
 22988
 22989
 22990
 22991
 22992
 22993
 22994
 22995
 22996
 22997
 22998
 22999
 23000
 23001
 23002
 23003
 23004
 23005
 23006
 23007
 23008
 23009
 23010
 23011
 23012
 23013
 23014
 23015
 23016
 23017
 23018
 23019
 23020
 23021
 23022
 23023
 23024
 23025
 23026
 23027
 23028
 23029
 23030
 23031
 23032
 23033
 23034
 23035
 23036
 23037
 23038
 23039
 23040
 23041
 23042
 23043
 23044
 23045
 23046
 23047
 23048
 23049
 23050
 23051
 23052
 23053
 23054
 23055
 23056
 23057
 23058
 23059
 23060
 23061
 23062
 23063
 23064
 23065
 23066
 23067
 23068
 23069
 23070
 23071
 23072
 23073
 23074
 23075
 23076
 23077
 23078
 23079
 23080
 23081
 23082
 23083
 23084
 23085
 23086
 23087
 23088
 23089
 23090
 23091
 23092
 23093
 23094
 23095
 23096
 23097
 23098
 23099
 23100
 23101
 23102
 23103
 23104
 23105
 23106
 23107
 23108
 23109
 23110
 23111
 23112
 23113
 23114
 23115
 23116
 23117
 23118
 23119
 23120
 23121
 23122
 23123
 23124
 23125
 23126
 23127
 23128
 23129
 23130
 23131
 23132
 23133
 23134
 23135
 23136
 23137
 23138
 23139
 23140
 23141
 23142
 23143
 23144
 23145
 23146
 23147
 23148
 23149
 23150
 23151
 23152
 23153
 23154
 23155
 23156
 23157
 23158
 23159
 23160
 23161
 23162
 23163
 23164
 23165
 23166
 23167
 23168
 23169
 23170
 23171
 23172
 23173
 23174
 23175
 23176
 23177
 23178
 23179
 23180
 23181
 23182
 23183
 23184
 23185
 23186
 23187
 23188
 23189
 23190
 23191
 23192
 23193
 23194
 23195
 23196
 23197
 23198
 23199
 23200
 23201
 23202
 23203
 23204
 23205
 23206
 23207
 23208
 23209
 23210
 23211
 23212
 23213
 23214
 23215
 23216
 23217
 23218
 23219
 23220
 23221
 23222
 23223
 23224
 23225
 23226
 23227
 23228
 23229
 23230
 23231
 23232
 23233
 23234
 23235
 23236
 23237
 23238
 23239
 23240
 23241
 23242
 23243
 23244
 23245
 23246
 23247
 23248
 23249
 23250
 23251
 23252
 23253
 23254
 23255
 23256
 23257
 23258
 23259
 23260
 23261
 23262
 23263
 23264
 23265
 23266
 23267
 23268
 23269
 23270
 23271
 23272
 23273
 23274
 23275
 23276
 23277
 23278
 23279
 23280
 23281
 23282
 23283
 23284
 23285
 23286
 23287
 23288
 23289
 23290
 23291
 23292
 23293
 23294
 23295
 23296
 23297
 23298
 23299
 23300
 23301
 23302
 23303
 23304
 23305
 23306
 23307
 23308
 23309
 23310
 23311
 23312
 23313
 23314
 23315
 23316
 23317
 23318
 23319
 23320
 23321
 23322
 23323
 23324
 23325
 23326
 23327
 23328
 23329
 23330
 23331
 23332
 23333
 23334
 23335
 23336
 23337
 23338
 23339
 23340
 23341
 23342
 23343
 23344
 23345
 23346
 23347
 23348
 23349
 23350
 23351
 23352
 23353
 23354
 23355
 23356
 23357
 23358
 23359
 23360
 23361
 23362
 23363
 23364
 23365
 23366
 23367
 23368
 23369
 23370
 23371
 23372
 23373
 23374
 23375
 23376
 23377
 23378
 23379
 23380
 23381
 23382
 23383
 23384
 23385
 23386
 23387
 23388
 23389
 23390
 23391
 23392
 23393
 23394
 23395
 23396
 23397
 23398
 23399
 23400
 23401
 23402
 23403
 23404
 23405
 23406
 23407
 23408
 23409
 23410
 23411
 23412
 23413
 23414
 23415
 23416
 23417
 23418
 23419
 23420
 23421
 23422
 23423
 23424
 23425
 23426
 23427
 23428
 23429
 23430
 23431
 23432
 23433
 23434
 23435
 23436
 23437
 23438
 23439
 23440
 23441
 23442
 23443
 23444
 23445
 23446
 23447
 23448
 23449
 23450
 23451
 23452
 23453
 23454
 23455
 23456
 23457
 23458
 23459
 23460
 23461
 23462
 23463
 23464
 23465
 23466
 23467
 23468
 23469
 23470
 23471
 23472
 23473
 23474
 23475
 23476
 23477
 23478
 23479
 23480
 23481
 23482
 23483
 23484
 23485
 23486
 23487
 23488
 23489
 23490
 23491
 23492
 23493
 23494
 23495
 23496
 23497
 23498
 23499
 23500
 23501
 23502
 23503
 23504
 23505
 23506
 23507
 23508
 23509
 23510
 23511
 23512
 23513
 23514
 23515
 23516
 23517
 23518
 23519
 23520
 23521
 23522
 23523
 23524
 23525
 23526
 23527
 23528
 23529
 23530
 23531
 23532
 23533
 23534
 23535
 23536
 23537
 23538
 23539
 23540
 23541
 23542
 23543
 23544
 23545
 23546
 23547
 23548
 23549
 23550
 23551
 23552
 23553
 23554
 23555
 23556
 23557
 23558
 23559
 23560
 23561
 23562
 23563
 23564
 23565
 23566
 23567
 23568
 23569
 23570
 23571
 23572
 23573
 23574
 23575
 23576
 23577
 23578
 23579
 23580
 23581
 23582
 23583
 23584
 23585
 23586
 23587
 23588
 23589
 23590
 23591
 23592
 23593
 23594
 23595
 23596
 23597
 23598
 23599
 23600
 23601
 23602
 23603
 23604
 23605
 23606
 23607
 23608
 23609
 23610
 23611
 23612
 23613
 23614
 23615
 23616
 23617
 23618
 23619
 23620
 23621
 23622
 23623
 23624
 23625
 23626
 23627
 23628
 23629
 23630
 23631
 23632
 23633
 23634
 23635
 23636
 23637
 23638
 23639
 23640
 23641
 23642
 23643
 23644
 23645
 23646
 23647
 23648
 23649
 23650
 23651
 23652
 23653
 23654
 23655
 23656
 23657
 23658
 23659
 23660
 23661
 23662
 23663
 23664
 23665
 23666
 23667
 23668
 23669
 23670
 23671
 23672
 23673
 23674
 23675
 23676
 23677
 23678
 23679
 23680
 23681
 23682
 23683
 23684
 23685
 23686
 23687
 23688
 23689
 23690
 23691
 23692
 23693
 23694
 23695
 23696
 23697
 23698
 23699
 23700
 23701
 23702
 23703
 23704
 23705
 23706
 23707
 23708
 23709
 23710
 23711
 23712
 23713
 23714
 23715
 23716
 23717
 23718
 23719
 23720
 23721
 23722
 23723
 23724
 23725
 23726
 23727
 23728
 23729
 23730
 23731
 23732
 23733
 23734
 23735
 23736
 23737
 23738
 23739
 23740
 23741
 23742
 23743
 23744
 23745
 23746
 23747
 23748
 23749
 23750
 23751
 23752
 23753
 23754
 23755
 23756
 23757
 23758
 23759
 23760
 23761
 23762
 23763
 23764
 23765
 23766
 23767
 23768
 23769
 23770
 23771
 23772
 23773
 23774
 23775
 23776
 23777
 23778
 23779
 23780
 23781
 23782
 23783
 23784
 23785
 23786
 23787
 23788
 23789
 23790
 23791
 23792
 23793
 23794
 23795
 23796
 23797
 23798
 23799
 23800
 23801
 23802
 23803
 23804
 23805
 23806
 23807
 23808
 23809
 23810
 23811
 23812
 23813
 23814
 23815
 23816
 23817
 23818
 23819
 23820
 23821
 23822
 23823
 23824
 23825
 23826
 23827
 23828
 23829
 23830
 23831
 23832
 23833
 23834
 23835
 23836
 23837
 23838
 23839
 23840
 23841
 23842
 23843
 23844
 23845
 23846
 23847
 23848
 23849
 23850
 23851
 23852
 23853
 23854
 23855
 23856
 23857
 23858
 23859
 23860
 23861
 23862
 23863
 23864
 23865
 23866
 23867
 23868
 23869
 23870
 23871
 23872
 23873
 23874
 23875
 23876
 23877
 23878
 23879
 23880
 23881
 23882
 23883
 23884
 23885
 23886
 23887
 23888
 23889
 23890
 23891
 23892
 23893
 23894
 23895
 23896
 23897
 23898
 23899
 23900
 23901
 23902
 23903
 23904
 23905
 23906
 23907
 23908
 23909
 23910
 23911
 23912
 23913
 23914
 23915
 23916
 23917
 23918
 23919
 23920
 23921
 23922
 23923
 23924
 23925
 23926
 23927
 23928
 23929
 23930
 23931
 23932
 23933
 23934
 23935
 23936
 23937
 23938
 23939
 23940
 23941
 23942
 23943
 23944
 23945
 23946
 23947
 23948
 23949
 23950
 23951
 23952
 23953
 23954
 23955
 23956
 23957
 23958
 23959
 23960
 23961
 23962
 23963
 23964
 23965
 23966
 23967
 23968
 23969
 23970
 23971
 23972
 23973
 23974
 23975
 23976
 23977
 23978
 23979
 23980
 23981
 23982
 23983
 23984
 23985
 23986
 23987
 23988
 23989
 23990
 23991
 23992
 23993
 23994
 23995
 23996
 23997
 23998
 23999
 24000
 24001
 24002
 24003
 24004
 24005
 24006
 24007
 24008
 24009
 24010
 24011
 24012
 24013
 24014
 24015
 24016
 24017
 24018
 24019
 24020
 24021
 24022
 24023
 24024
 24025
 24026
 24027
 24028
 24029
 24030
 24031
 24032
 24033
 24034
 24035
 24036
 24037
 24038
 24039
 24040
 24041
 24042
 24043
 24044
 24045
 24046
 24047
 24048
 24049
 24050
 24051
 24052
 24053
 24054
 24055
 24056
 24057
 24058
 24059
 24060
 24061
 24062
 24063
 24064
 24065
 24066
 24067
 24068
 24069
 24070
 24071
 24072
 24073
 24074
 24075
 24076
 24077
 24078
 24079
 24080
 24081
 24082
 24083
 24084
 24085
 24086
 24087
 24088
 24089
 24090
 24091
 24092
 24093
 24094
 24095
 24096
 24097
 24098
 24099
 24100
 24101
 24102
 24103
 24104
 24105
 24106
 24107
 24108
 24109
 24110
 24111
 24112
 24113
 24114
 24115
 24116
 24117
 24118
 24119
 24120
 24121
 24122
 24123
 24124
 24125
 24126
 24127
 24128
 24129
 24130
 24131
 24132
 24133
 24134
 24135
 24136
 24137
 24138
 24139
 24140
 24141
 24142
 24143
 24144
 24145
 24146
 24147
 24148
 24149
 24150
 24151
 24152
 24153
 24154
 24155
 24156
 24157
 24158
 24159
 24160
 24161
 24162
 24163
 24164
 24165
 24166
 24167
 24168
 24169
 24170
 24171
 24172
 24173
 24174
 24175
 24176
 24177
 24178
 24179
 24180
 24181
 24182
 24183
 24184
 24185
 24186
 24187
 24188
 24189
 24190
 24191
 24192
 24193
 24194
 24195
 24196
 24197
 24198
 24199
 24200
 24201
 24202
 24203
 24204
 24205
 24206
 24207
 24208
 24209
 24210
 24211
 24212
 24213
 24214
 24215
 24216
 24217
 24218
 24219
 24220
 24221
 24222
 24223
 24224
 24225
 24226
 24227
 24228
 24229
 24230
 24231
 24232
 24233
 24234
 24235
 24236
 24237
 24238
 24239
 24240
 24241
 24242
 24243
 24244
 24245
 24246
 24247
 24248
 24249
 24250
 24251
 24252
 24253
 24254
 24255
 24256
 24257
 24258
 24259
 24260
 24261
 24262
 24263
 24264
 24265
 24266
 24267
 24268
 24269
 24270
 24271
 24272
 24273
 24274
 24275
 24276
 24277
 24278
 24279
 24280
 24281
 24282
 24283
 24284
 24285
 24286
 24287
 24288
 24289
 24290
 24291
 24292
 24293
 24294
 24295
 24296
 24297
 24298
 24299
 24300
 24301
 24302
 24303
 24304
 24305
 24306
 24307
 24308
 24309
 24310
 24311
 24312
 24313
 24314
 24315
 24316
 24317
 24318
 24319
 24320
 24321
 24322
 24323
 24324
 24325
 24326
 24327
 24328
 24329
 24330
 24331
 24332
 24333
 24334
 24335
 24336
 24337
 24338
 24339
 24340
 24341
 24342
 24343
 24344
 24345
 24346
 24347
 24348
 24349
 24350
 24351
 24352
 24353
 24354
 24355
 24356
 24357
 24358
 24359
 24360
 24361
 24362
 24363
 24364
 24365
 24366
 24367
 24368
 24369
 24370
 24371
 24372
 24373
 24374
 24375
 24376
 24377
 24378
 24379
 24380
 24381
 24382
 24383
 24384
 24385
 24386
 24387
 24388
 24389
 24390
 24391
 24392
 24393
 24394
 24395
 24396
 24397
 24398
 24399
 24400
 24401
 24402
 24403
 24404
 24405
 24406
 24407
 24408
 24409
 24410
 24411
 24412
 24413
 24414
 24415
 24416
 24417
 24418
 24419
 24420
 24421
 24422
 24423
 24424
 24425
 24426
 24427
 24428
 24429
 24430
 24431
 24432
 24433
 24434
 24435
 24436
 24437
 24438
 24439
 24440
 24441
 24442
 24443
 24444
 24445
 24446
 24447
 24448
 24449
 24450
 24451
 24452
 24453
 24454
 24455
 24456
 24457
 24458
 24459
 24460
 24461
 24462
 24463
 24464
 24465
 24466
 24467
 24468
 24469
 24470
 24471
 24472
 24473
 24474
 24475
 24476
 24477
 24478
 24479
 24480
 24481
 24482
 24483
 24484
 24485
 24486
 24487
 24488
 24489
 24490
 24491
 24492
 24493
 24494
 24495
 24496
 24497
 24498
 24499
 24500
 24501
 24502
 24503
 24504
 24505
 24506
 24507
 24508
 24509
 24510
 24511
 24512
 24513
 24514
 24515
 24516
 24517
 24518
 24519
 24520
 24521
 24522
 24523
 24524
 24525
 24526
 24527
 24528
 24529
 24530
 24531
 24532
 24533
 24534
 24535
 24536
 24537
 24538
 24539
 24540
 24541
 24542
 24543
 24544
 24545
 24546
 24547
 24548
 24549
 24550
 24551
 24552
 24553
 24554
 24555
 24556
 24557
 24558
 24559
 24560
 24561
 24562
 24563
 24564
 24565
 24566
 24567
 24568
 24569
 24570
 24571
 24572
 24573
 24574
 24575
 24576
 24577
 24578
 24579
 24580
 24581
 24582
 24583
 24584
 24585
 24586
 24587
 24588
 24589
 24590
 24591
 24592
 24593
 24594
 24595
 24596
 24597
 24598
 24599
 24600
 24601
 24602
 24603
 24604
 24605
 24606
 24607
 24608
 24609
 24610
 24611
 24612
 24613
 24614
 24615
 24616
 24617
 24618
 24619
 24620
 24621
 24622
 24623
 24624
 24625
 24626
 24627
 24628
 24629
 24630
 24631
 24632
 24633
 24634
 24635
 24636
 24637
 24638
 24639
 24640
 24641
 24642
 24643
 24644
 24645
 24646
 24647
 24648
 24649
 24650
 24651
 24652
 24653
 24654
 24655
 24656
 24657
 24658
 24659
 24660
 24661
 24662
 24663
 24664
 24665
 24666
 24667
 24668
 24669
 24670
 24671
 24672
 24673
 24674
 24675
 24676
 24677
 24678
 24679
 24680
 24681
 24682
 24683
 24684
 24685
 24686
 24687
 24688
 24689
 24690
 24691
 24692
 24693
 24694
 24695
 24696
 24697
 24698
 24699
 24700
 24701
 24702
 24703
 24704
 24705
 24706
 24707
 24708
 24709
 24710
 24711
 24712
 24713
 24714
 24715
 24716
 24717
 24718
 24719
 24720
 24721
 24722
 24723
 24724
 24725
 24726
 24727
 24728
 24729
 24730
 24731
 24732
 24733
 24734
 24735
 24736
 24737
 24738
 24739
 24740
 24741
 24742
 24743
 24744
 24745
 24746
 24747
 24748
 24749
 24750
 24751
 24752
 24753
 24754
 24755
 24756
 24757
 24758
 24759
 24760
 24761
 24762
 24763
 24764
 24765
 24766
 24767
 24768
 24769
 24770
 24771
 24772
 24773
 24774
 24775
 24776
 24777
 24778
 24779
 24780
 24781
 24782
 24783
 24784
 24785
 24786
 24787
 24788
 24789
 24790
 24791
 24792
 24793
 24794
 24795
 24796
 24797
 24798
 24799
 24800
 24801
 24802
 24803
 24804
 24805
 24806
 24807
 24808
 24809
 24810
 24811
 24812
 24813
 24814
 24815
 24816
 24817
 24818
 24819
 24820
 24821
 24822
 24823
 24824
 24825
 24826
 24827
 24828
 24829
 24830
 24831
 24832
 24833
 24834
 24835
 24836
 24837
 24838
 24839
 24840
 24841
 24842
 24843
 24844
 24845
 24846
 24847
 24848
 24849
 24850
 24851
 24852
 24853
 24854
 24855
 24856
 24857
 24858
 24859
 24860
 24861
 24862
 24863
 24864
 24865
 24866
 24867
 24868
 24869
 24870
 24871
 24872
 24873
 24874
 24875
 24876
 24877
 24878
 24879
 24880
 24881
 24882
 24883
 24884
 24885
 24886
 24887
 24888
 24889
 24890
 24891
 24892
 24893
 24894
 24895
 24896
 24897
 24898
 24899
 24900
 24901
 24902
 24903
 24904
 24905
 24906
 24907
 24908
 24909
 24910
 24911
 24912
 24913
 24914
 24915
 24916
 24917
 24918
 24919
 24920
 24921
 24922
 24923
 24924
 24925
 24926
 24927
 24928
 24929
 24930
 24931
 24932
 24933
 24934
 24935
 24936
 24937
 24938
 24939
 24940
 24941
 24942
 24943
 24944
 24945
 24946
 24947
 24948
 24949
 24950
 24951
 24952
 24953
 24954
 24955
 24956
 24957
 24958
 24959
 24960
 24961
 24962
 24963
 24964
 24965
 24966
 24967
 24968
 24969
 24970
 24971
 24972
 24973
 24974
 24975
 24976
 24977
 24978
 24979
 24980
 24981
 24982
 24983
 24984
 24985
 24986
 24987
 24988
 24989
 24990
 24991
 24992
 24993
 24994
 24995
 24996
 24997
 24998
 24999
 25000
 25001
 25002
 25003
 25004
 25005
 25006
 25007
 25008
 25009
 25010
 25011
 25012
 25013
 25014
 25015
 25016
 25017
 25018
 25019
 25020
 25021
 25022
 25023
 25024
 25025
 25026
 25027
 25028
 25029
 25030
 25031
 25032
 25033
 25034
 25035
 25036
 25037
 25038
 25039
 25040
 25041
 25042
 25043
 25044
 25045
 25046
 25047
 25048
 25049
 25050
 25051
 25052
 25053
 25054
 25055
 25056
 25057
 25058
 25059
 25060
 25061
 25062
 25063
 25064
 25065
 25066
 25067
 25068
 25069
 25070
 25071
 25072
 25073
 25074
 25075
 25076
 25077
 25078
 25079
 25080
 25081
 25082
 25083
 25084
 25085
 25086
 25087
 25088
 25089
 25090
 25091
 25092
 25093
 25094
 25095
 25096
 25097
 25098
 25099
 25100
 25101
 25102
 25103
 25104
 25105
 25106
 25107
 25108
 25109
 25110
 25111
 25112
 25113
 25114
 25115
 25116
 25117
 25118
 25119
 25120
 25121
 25122
 25123
 25124
 25125
 25126
 25127
 25128
 25129
 25130
 25131
 25132
 25133
 25134
 25135
 25136
 25137
 25138
 25139
 25140
 25141
 25142
 25143
 25144
 25145
 25146
 25147
 25148
 25149
 25150
 25151
 25152
 25153
 25154
 25155
 25156
 25157
 25158
 25159
 25160
 25161
 25162
 25163
 25164
 25165
 25166
 25167
 25168
 25169
 25170
 25171
 25172
 25173
 25174
 25175
 25176
 25177
 25178
 25179
 25180
 25181
 25182
 25183
 25184
 25185
 25186
 25187
 25188
 25189
 25190
 25191
 25192
 25193
 25194
 25195
 25196
 25197
 25198
 25199
 25200
 25201
 25202
 25203
 25204
 25205
 25206
 25207
 25208
 25209
 25210
 25211
 25212
 25213
 25214
 25215
 25216
 25217
 25218
 25219
 25220
 25221
 25222
 25223
 25224
 25225
 25226
 25227
 25228
 25229
 25230
 25231
 25232
 25233
 25234
 25235
 25236
 25237
 25238
 25239
 25240
 25241
 25242
 25243
 25244
 25245
 25246
 25247
 25248
 25249
 25250
 25251
 25252
 25253
 25254
 25255
 25256
 25257
 25258
 25259
 25260
 25261
 25262
 25263
 25264
 25265
 25266
 25267
 25268
 25269
 25270
 25271
 25272
 25273
 25274
 25275
 25276
 25277
 25278
 25279
 25280
 25281
 25282
 25283
 25284
 25285
 25286
 25287
 25288
 25289
 25290
 25291
 25292
 25293
 25294
 25295
 25296
 25297
 25298
 25299
 25300
 25301
 25302
 25303
 25304
 25305
 25306
 25307
 25308
 25309
 25310
 25311
 25312
 25313
 25314
 25315
 25316
 25317
 25318
 25319
 25320
 25321
 25322
 25323
 25324
 25325
 25326
 25327
 25328
 25329
 25330
 25331
 25332
 25333
 25334
 25335
 25336
 25337
 25338
 25339
 25340
 25341
 25342
 25343
 25344
 25345
 25346
 25347
 25348
 25349
 25350
 25351
 25352
 25353
 25354
 25355
 25356
 25357
 25358
 25359
 25360
 25361
 25362
 25363
 25364
 25365
 25366
 25367
 25368
 25369
 25370
 25371
 25372
 25373
 25374
 25375
 25376
 25377
 25378
 25379
 25380
 25381
 25382
 25383
 25384
 25385
 25386
 25387
 25388
 25389
 25390
 25391
 25392
 25393
 25394
 25395
 25396
 25397
 25398
 25399
 25400
 25401
 25402
 25403
 25404
 25405
 25406
 25407
 25408
 25409
 25410
 25411
 25412
 25413
 25414
 25415
 25416
 25417
 25418
 25419
 25420
 25421
 25422
 25423
 25424
 25425
 25426
 25427
 25428
 25429
 25430
 25431
 25432
 25433
 25434
 25435
 25436
 25437
 25438
 25439
 25440
 25441
 25442
 25443
 25444
 25445
 25446
 25447
 25448
 25449
 25450
 25451
 25452
 25453
 25454
 25455
 25456
 25457
 25458
 25459
 25460
 25461
 25462
 25463
 25464
 25465
 25466
 25467
 25468
 25469
 25470
 25471
 25472
 25473
 25474
 25475
 25476
 25477
 25478
 25479
 25480
 25481
 25482
 25483
 25484
 25485
 25486
 25487
 25488
 25489
 25490
 25491
 25492
 25493
 25494
 25495
 25496
 25497
 25498
 25499
 25500
 25501
 25502
 25503
 25504
 25505
 25506
 25507
 25508
 25509
 25510
 25511
 25512
 25513
 25514
 25515
 25516
 25517
 25518
 25519
 25520
 25521
 25522
 25523
 25524
 25525
 25526
 25527
 25528
 25529
 25530
 25531
 25532
 25533
 25534
 25535
 25536
 25537
 25538
 25539
 25540
 25541
 25542
 25543
 25544
 25545
 25546
 25547
 25548
 25549
 25550
 25551
 25552
 25553
 25554
 25555
 25556
 25557
 25558
 25559
 25560
 25561
 25562
 25563
 25564
 25565
 25566
 25567
 25568
 25569
 25570
 25571
 25572
 25573
 25574
 25575
 25576
 25577
 25578
 25579
 25580
 25581
 25582
 25583
 25584
 25585
 25586
 25587
 25588
 25589
 25590
 25591
 25592
 25593
 25594
 25595
 25596
 25597
 25598
 25599
 25600
 25601
 25602
 25603
 25604
 25605
 25606
 25607
 25608
 25609
 25610
 25611
 25612
 25613
 25614
 25615
 25616
 25617
 25618
 25619
 25620
 25621
 25622
 25623
 25624
 25625
 25626
 25627
 25628
 25629
 25630
 25631
 25632
 25633
 25634
 25635
 25636
 25637
 25638
 25639
 25640
 25641
 25642
 25643
 25644
 25645
 25646
 25647
 25648
 25649
 25650
 25651
 25652
 25653
 25654
 25655
 25656
 25657
 25658
 25659
 25660
 25661
 25662
 25663
 25664
 25665
 25666
 25667
 25668
 25669
 25670
 25671
 25672
 25673
 25674
 25675
 25676
 25677
 25678
 25679
 25680
 25681
 25682
 25683
 25684
 25685
 25686
 25687
 25688
 25689
 25690
 25691
 25692
 25693
 25694
 25695
 25696
 25697
 25698
 25699
 25700
 25701
 25702
 25703
 25704
 25705
 25706
 25707
 25708
 25709
 25710
 25711
 25712
 25713
 25714
 25715
 25716
 25717
 25718
 25719
 25720
 25721
 25722
 25723
 25724
 25725
 25726
 25727
 25728
 25729
 25730
 25731
 25732
 25733
 25734
 25735
 25736
 25737
 25738
 25739
 25740
 25741
 25742
 25743
 25744
 25745
 25746
 25747
 25748
 25749
 25750
 25751
 25752
 25753
 25754
 25755
 25756
 25757
 25758
 25759
 25760
 25761
 25762
 25763
 25764
 25765
 25766
 25767
 25768
 25769
 25770
 25771
 25772
 25773
 25774
 25775
 25776
 25777
 25778
 25779
 25780
 25781
 25782
 25783
 25784
 25785
 25786
 25787
 25788
 25789
 25790
 25791
 25792
 25793
 25794
 25795
 25796
 25797
 25798
 25799
 25800
 25801
 25802
 25803
 25804
 25805
 25806
 25807
 25808
 25809
 25810
 25811
 25812
 25813
 25814
 25815
 25816
 25817
 25818
 25819
 25820
 25821
 25822
 25823
 25824
 25825
 25826
 25827
 25828
 25829
 25830
 25831
 25832
 25833
 25834
 25835
 25836
 25837
 25838
 25839
 25840
 25841
 25842
 25843
 25844
 25845
 25846
 25847
 25848
 25849
 25850
 25851
 25852
 25853
 25854
 25855
 25856
 25857
 25858
 25859
 25860
 25861
 25862
 25863
 25864
 25865
 25866
 25867
 25868
 25869
 25870
 25871
 25872
 25873
 25874
 25875
 25876
 25877
 25878
 25879
 25880
 25881
 25882
 25883
 25884
 25885
 25886
 25887
 25888
 25889
 25890
 25891
 25892
 25893
 25894
 25895
 25896
 25897
 25898
 25899
 25900
 25901
 25902
 25903
 25904
 25905
 25906
 25907
 25908
 25909
 25910
 25911
 25912
 25913
 25914
 25915
 25916
 25917
 25918
 25919
 25920
 25921
 25922
 25923
 25924
 25925
 25926
 25927
 25928
 25929
 25930
 25931
 25932
 25933
 25934
 25935
 25936
 25937
 25938
 25939
 25940
 25941
 25942
 25943
 25944
 25945
 25946
 25947
 25948
 25949
 25950
 25951
 25952
 25953
 25954
 25955
 25956
 25957
 25958
 25959
 25960
 25961
 25962
 25963
 25964
 25965
 25966
 25967
 25968
 25969
 25970
 25971
 25972
 25973
 25974
 25975
 25976
 25977
 25978
 25979
 25980
 25981
 25982
 25983
 25984
 25985
 25986
 25987
 25988
 25989
 25990
 25991
 25992
 25993
 25994
 25995
 25996
 25997
 25998
 25999
 26000
 26001
 26002
 26003
 26004
 26005
 26006
 26007
 26008
 26009
 26010
 26011
 26012
 26013
 26014
 26015
 26016
 26017
 26018
 26019
 26020
 26021
 26022
 26023
 26024
 26025
 26026
 26027
 26028
 26029
 26030
 26031
 26032
 26033
 26034
 26035
 26036
 26037
 26038
 26039
 26040
 26041
 26042
 26043
 26044
 26045
 26046
 26047
 26048
 26049
 26050
 26051
 26052
 26053
 26054
 26055
 26056
 26057
 26058
 26059
 26060
 26061
 26062
 26063
 26064
 26065
 26066
 26067
 26068
 26069
 26070
 26071
 26072
 26073
 26074
 26075
 26076
 26077
 26078
 26079
 26080
 26081
 26082
 26083
 26084
 26085
 26086
 26087
 26088
 26089
 26090
 26091
 26092
 26093
 26094
 26095
 26096
 26097
 26098
 26099
 26100
 26101
 26102
 26103
 26104
 26105
 26106
 26107
 26108
 26109
 26110
 26111
 26112
 26113
 26114
 26115
 26116
 26117
 26118
 26119
 26120
 26121
 26122
 26123
 26124
 26125
 26126
 26127
 26128
 26129
 26130
 26131
 26132
 26133
 26134
 26135
 26136
 26137
 26138
 26139
 26140
 26141
 26142
 26143
 26144
 26145
 26146
 26147
 26148
 26149
 26150
 26151
 26152
 26153
 26154
 26155
 26156
 26157
 26158
 26159
 26160
 26161
 26162
 26163
 26164
 26165
 26166
 26167
 26168
 26169
 26170
 26171
 26172
 26173
 26174
 26175
 26176
 26177
 26178
 26179
 26180
 26181
 26182
 26183
 26184
 26185
 26186
 26187
 26188
 26189
 26190
 26191
 26192
 26193
 26194
 26195
 26196
 26197
 26198
 26199
 26200
 26201
 26202
 26203
 26204
 26205
 26206
 26207
 26208
 26209
 26210
 26211
 26212
 26213
 26214
 26215
 26216
 26217
 26218
 26219
 26220
 26221
 26222
 26223
 26224
 26225
 26226
 26227
 26228
 26229
 26230
 26231
 26232
 26233
 26234
 26235
 26236
 26237
 26238
 26239
 26240
 26241
 26242
 26243
 26244
 26245
 26246
 26247
 26248
 26249
 26250
 26251
 26252
 26253
 26254
 26255
 26256
 26257
 26258
 26259
 26260
 26261
 26262
 26263
 26264
 26265
 26266
 26267
 26268
 26269
 26270
 26271
 26272
 26273
 26274
 26275
 26276
 26277
 26278
 26279
 26280
 26281
 26282
 26283
 26284
 26285
 26286
 26287
 26288
 26289
 26290
 26291
 26292
 26293
 26294
 26295
 26296
 26297
 26298
 26299
 26300
 26301
 26302
 26303
 26304
 26305
 26306
 26307
 26308
 26309
 26310
 26311
 26312
 26313
 26314
 26315
 26316
 26317
 26318
 26319
 26320
 26321
 26322
 26323
 26324
 26325
 26326
 26327
 26328
 26329
 26330
 26331
 26332
 26333
 26334
 26335
 26336
 26337
 26338
 26339
 26340
 26341
 26342
 26343
 26344
 26345
 26346
 26347
 26348
 26349
 26350
 26351
 26352
 26353
 26354
 26355
 26356
 26357
 26358
 26359
 26360
 26361
 26362
 26363
 26364
 26365
 26366
 26367
 26368
 26369
 26370
 26371
 26372
 26373
 26374
 26375
 26376
 26377
 26378
 26379
 26380
 26381
 26382
 26383
 26384
 26385
 26386
 26387
 26388
 26389
 26390
 26391
 26392
 26393
 26394
 26395
 26396
 26397
 26398
 26399
 26400
 26401
 26402
 26403
 26404
 26405
 26406
 26407
 26408
 26409
 26410
 26411
 26412
 26413
 26414
 26415
 26416
 26417
 26418
 26419
 26420
 26421
 26422
 26423
 26424
 26425
 26426
 26427
 26428
 26429
 26430
 26431
 26432
 26433
 26434
 26435
 26436
 26437
 26438
 26439
 26440
 26441
 26442
 26443
 26444
 26445
 26446
 26447
 26448
 26449
 26450
 26451
 26452
 26453
 26454
 26455
 26456
 26457
 26458
 26459
 26460
 26461
 26462
 26463
 26464
 26465
 26466
 26467
 26468
 26469
 26470
 26471
 26472
 26473
 26474
 26475
 26476
 26477
 26478
 26479
 26480
 26481
 26482
 26483
 26484
 26485
 26486
 26487
 26488
 26489
 26490
 26491
 26492
 26493
 26494
 26495
 26496
 26497
 26498
 26499
 26500
 26501
 26502
 26503
 26504
 26505
 26506
 26507
 26508
 26509
 26510
 26511
 26512
 26513
 26514
 26515
 26516
 26517
 26518
 26519
 26520
 26521
 26522
 26523
 26524
 26525
 26526
 26527
 26528
 26529
 26530
 26531
 26532
 26533
 26534
 26535
 26536
 26537
 26538
 26539
 26540
 26541
 26542
 26543
 26544
 26545
 26546
 26547
 26548
 26549
 26550
 26551
 26552
 26553
 26554
 26555
 26556
 26557
 26558
 26559
 26560
 26561
 26562
 26563
 26564
 26565
 26566
 26567
 26568
 26569
 26570
 26571
 26572
 26573
 26574
 26575
 26576
 26577
 26578
 26579
 26580
 26581
 26582
 26583
 26584
 26585
 26586
 26587
 26588
 26589
 26590
 26591
 26592
 26593
 26594
 26595
 26596
 26597
 26598
 26599
 26600
 26601
 26602
 26603
 26604
 26605
 26606
 26607
 26608
 26609
 26610
 26611
 26612
 26613
 26614
 26615
 26616
 26617
 26618
 26619
 26620
 26621
 26622
 26623
 26624
 26625
 26626
 26627
 26628
 26629
 26630
 26631
 26632
 26633
 26634
 26635
 26636
 26637
 26638
 26639
 26640
 26641
 26642
 26643
 26644
 26645
 26646
 26647
 26648
 26649
 26650
 26651
 26652
 26653
 26654
 26655
 26656
 26657
 26658
 26659
 26660
 26661
 26662
 26663
 26664
 26665
 26666
 26667
 26668
 26669
 26670
 26671
 26672
 26673
 26674
 26675
 26676
 26677
 26678
 26679
 26680
 26681
 26682
 26683
 26684
 26685
 26686
 26687
 26688
 26689
 26690
 26691
 26692
 26693
 26694
 26695
 26696
 26697
 26698
 26699
 26700
 26701
 26702
 26703
 26704
 26705
 26706
 26707
 26708
 26709
 26710
 26711
 26712
 26713
 26714
 26715
 26716
 26717
 26718
 26719
 26720
 26721
 26722
 26723
 26724
 26725
 26726
 26727
 26728
 26729
 26730
 26731
 26732
 26733
 26734
 26735
 26736
 26737
 26738
 26739
 26740
 26741
 26742
 26743
 26744
 26745
 26746
 26747
 26748
 26749
 26750
 26751
 26752
 26753
 26754
 26755
 26756
 26757
 26758
 26759
 26760
 26761
 26762
 26763
 26764
 26765
 26766
 26767
 26768
 26769
 26770
 26771
 26772
 26773
 26774
 26775
 26776
 26777
 26778
 26779
 26780
 26781
 26782
 26783
 26784
 26785
 26786
 26787
 26788
 26789
 26790
 26791
 26792
 26793
 26794
 26795
 26796
 26797
 26798
 26799
 26800
 26801
 26802
 26803
 26804
 26805
 26806
 26807
 26808
 26809
 26810
 26811
 26812
 26813
 26814
 26815
 26816
 26817
 26818
 26819
 26820
 26821
 26822
 26823
 26824
 26825
 26826
 26827
 26828
 26829
 26830
 26831
 26832
 26833
 26834
 26835
 26836
 26837
 26838
 26839
 26840
 26841
 26842
 26843
 26844
 26845
 26846
 26847
 26848
 26849
 26850
 26851
 26852
 26853
 26854
 26855
 26856
 26857
 26858
 26859
 26860
 26861
 26862
 26863
 26864
 26865
 26866
 26867
 26868
 26869
 26870
 26871
 26872
 26873
 26874
 26875
 26876
 26877
 26878
 26879
 26880
 26881
 26882
 26883
 26884
 26885
 26886
 26887
 26888
 26889
 26890
 26891
 26892
 26893
 26894
 26895
 26896
 26897
 26898
 26899
 26900
 26901
 26902
 26903
 26904
 26905
 26906
 26907
 26908
 26909
 26910
 26911
 26912
 26913
 26914
 26915
 26916
 26917
 26918
 26919
 26920
 26921
 26922
 26923
 26924
 26925
 26926
 26927
 26928
 26929
 26930
 26931
 26932
 26933
 26934
 26935
 26936
 26937
 26938
 26939
 26940
 26941
 26942
 26943
 26944
 26945
 26946
 26947
 26948
 26949
 26950
 26951
 26952
 26953
 26954
 26955
 26956
 26957
 26958
 26959
 26960
 26961
 26962
 26963
 26964
 26965
 26966
 26967
 26968
 26969
 26970
 26971
 26972
 26973
 26974
 26975
 26976
 26977
 26978
 26979
 26980
 26981
 26982
 26983
 26984
 26985
 26986
 26987
 26988
 26989
 26990
 26991
 26992
 26993
 26994
 26995
 26996
 26997
 26998
 26999
 27000
 27001
 27002
 27003
 27004
 27005
 27006
 27007
 27008
 27009
 27010
 27011
 27012
 27013
 27014
 27015
 27016
 27017
 27018
 27019
 27020
 27021
 27022
 27023
 27024
 27025
 27026
 27027
 27028
 27029
 27030
 27031
 27032
 27033
 27034
 27035
 27036
 27037
 27038
 27039
 27040
 27041
 27042
 27043
 27044
 27045
 27046
 27047
 27048
 27049
 27050
 27051
 27052
 27053
 27054
 27055
 27056
 27057
 27058
 27059
 27060
 27061
 27062
 27063
 27064
 27065
 27066
 27067
 27068
 27069
 27070
 27071
 27072
 27073
 27074
 27075
 27076
 27077
 27078
 27079
 27080
 27081
 27082
 27083
 27084
 27085
 27086
 27087
 27088
 27089
 27090
 27091
 27092
 27093
 27094
 27095
 27096
 27097
 27098
 27099
 27100
 27101
 27102
 27103
 27104
 27105
 27106
 27107
 27108
 27109
 27110
 27111
 27112
 27113
 27114
 27115
 27116
 27117
 27118
 27119
 27120
 27121
 27122
 27123
 27124
 27125
 27126
 27127
 27128
 27129
 27130
 27131
 27132
 27133
 27134
 27135
 27136
 27137
 27138
 27139
 27140
 27141
 27142
 27143
 27144
 27145
 27146
 27147
 27148
 27149
 27150
 27151
 27152
 27153
 27154
 27155
 27156
 27157
 27158
 27159
 27160
 27161
 27162
 27163
 27164
 27165
 27166
 27167
 27168
 27169
 27170
 27171
 27172
 27173
 27174
 27175
 27176
 27177
 27178
 27179
 27180
 27181
 27182
 27183
 27184
 27185
 27186
 27187
 27188
 27189
 27190
 27191
 27192
 27193
 27194
 27195
 27196
 27197
 27198
 27199
 27200
 27201
 27202
 27203
 27204
 27205
 27206
 27207
 27208
 27209
 27210
 27211
 27212
 27213
 27214
 27215
 27216
 27217
 27218
 27219
 27220
 27221
 27222
 27223
 27224
 27225
 27226
 27227
 27228
 27229
 27230
 27231
 27232
 27233
 27234
 27235
 27236
 27237
 27238
 27239
 27240
 27241
 27242
 27243
 27244
 27245
 27246
 27247
 27248
 27249
 27250
 27251
 27252
 27253
 27254
 27255
 27256
 27257
 27258
 27259
 27260
 27261
 27262
 27263
 27264
 27265
 27266
 27267
 27268
 27269
 27270
 27271
 27272
 27273
 27274
 27275
 27276
 27277
 27278
 27279
 27280
 27281
 27282
 27283
 27284
 27285
 27286
 27287
 27288
 27289
 27290
 27291
 27292
 27293
 27294
 27295
 27296
 27297
 27298
 27299
 27300
 27301
 27302
 27303
 27304
 27305
 27306
 27307
 27308
 27309
 27310
 27311
 27312
 27313
 27314
 27315
 27316
 27317
 27318
 27319
 27320
 27321
 27322
 27323
 27324
 27325
 27326
 27327
 27328
 27329
 27330
 27331
 27332
 27333
 27334
 27335
 27336
 27337
 27338
 27339
 27340
 27341
 27342
 27343
 27344
 27345
 27346
 27347
 27348
 27349
 27350
 27351
 27352
 27353
 27354
 27355
 27356
 27357
 27358
 27359
 27360
 27361
 27362
 27363
 27364
 27365
 27366
 27367
 27368
 27369
 27370
 27371
 27372
 27373
 27374
 27375
 27376
 27377
 27378
 27379
 27380
 27381
 27382
 27383
 27384
 27385
 27386
 27387
 27388
 27389
 27390
 27391
 27392
 27393
 27394
 27395
 27396
 27397
 27398
 27399
 27400
 27401
 27402
 27403
 27404
 27405
 27406
 27407
 27408
 27409
 27410
 27411
 27412
 27413
 27414
 27415
 27416
 27417
 27418
 27419
 27420
 27421
 27422
 27423
 27424
 27425
 27426
 27427
 27428
 27429
 27430
 27431
 27432
 27433
 27434
 27435
 27436
 27437
 27438
 27439
 27440
 27441
 27442
 27443
 27444
 27445
 27446
 27447
 27448
 27449
 27450
 27451
 27452
 27453
 27454
 27455
 27456
 27457
 27458
 27459
 27460
 27461
 27462
 27463
 27464
 27465
 27466
 27467
 27468
 27469
 27470
 27471
 27472
 27473
 27474
 27475
 27476
 27477
 27478
 27479
 27480
 27481
 27482
 27483
 27484
 27485
 27486
 27487
 27488
 27489
 27490
 27491
 27492
 27493
 27494
 27495
 27496
 27497
 27498
 27499
 27500
 27501
 27502
 27503
 27504
 27505
 27506
 27507
 27508
 27509
 27510
 27511
 27512
 27513
 27514
 27515
 27516
 27517
 27518
 27519
 27520
 27521
 27522
 27523
 27524
 27525
 27526
 27527
 27528
 27529
 27530
 27531
 27532
 27533
 27534
 27535
 27536
 27537
 27538
 27539
 27540
 27541
 27542
 27543
 27544
 27545
 27546
 27547
 27548
 27549
 27550
 27551
 27552
 27553
 27554
 27555
 27556
 27557
 27558
 27559
 27560
 27561
 27562
 27563
 27564
 27565
 27566
 27567
 27568
 27569
 27570
 27571
 27572
 27573
 27574
 27575
 27576
 27577
 27578
 27579
 27580
 27581
 27582
 27583
 27584
 27585
 27586
 27587
 27588
 27589
 27590
 27591
 27592
 27593
 27594
 27595
 27596
 27597
 27598
 27599
 27600
 27601
 27602
 27603
 27604
 27605
 27606
 27607
 27608
 27609
 27610
 27611
 27612
 27613
 27614
 27615
 27616
 27617
 27618
 27619
 27620
 27621
 27622
 27623
 27624
 27625
 27626
 27627
 27628
 27629
 27630
 27631
 27632
 27633
 27634
 27635
 27636
 27637
 27638
 27639
 27640
 27641
 27642
 27643
 27644
 27645
 27646
 27647
 27648
 27649
 27650
 27651
 27652
 27653
 27654
 27655
 27656
 27657
 27658
 27659
 27660
 27661
 27662
 27663
 27664
 27665
 27666
 27667
 27668
 27669
 27670
 27671
 27672
 27673
 27674
 27675
 27676
 27677
 27678
 27679
 27680
 27681
 27682
 27683
 27684
 27685
 27686
 27687
 27688
 27689
 27690
 27691
 27692
 27693
 27694
 27695
 27696
 27697
 27698
 27699
 27700
 27701
 27702
 27703
 27704
 27705
 27706
 27707
 27708
 27709
 27710
 27711
 27712
 27713
 27714
 27715
 27716
 27717
 27718
 27719
 27720
 27721
 27722
 27723
 27724
 27725
 27726
 27727
 27728
 27729
 27730
 27731
 27732
 27733
 27734
 27735
 27736
 27737
 27738
 27739
 27740
 27741
 27742
 27743
 27744
 27745
 27746
 27747
 27748
 27749
 27750
 27751
 27752
 27753
 27754
 27755
 27756
 27757
 27758
 27759
 27760
 27761
 27762
 27763
 27764
 27765
 27766
 27767
 27768
 27769
 27770
 27771
 27772
 27773
 27774
 27775
 27776
 27777
 27778
 27779
 27780
 27781
 27782
 27783
 27784
 27785
 27786
 27787
 27788
 27789
 27790
 27791
 27792
 27793
 27794
 27795
 27796
 27797
 27798
 27799
 27800
 27801
 27802
 27803
 27804
 27805
 27806
 27807
 27808
 27809
 27810
 27811
 27812
 27813
 27814
 27815
 27816
 27817
 27818
 27819
 27820
 27821
 27822
 27823
 27824
 27825
 27826
 27827
 27828
 27829
 27830
 27831
 27832
 27833
 27834
 27835
 27836
 27837
 27838
 27839
 27840
 27841
 27842
 27843
 27844
 27845
 27846
 27847
 27848
 27849
 27850
 27851
 27852
 27853
 27854
 27855
 27856
 27857
 27858
 27859
 27860
 27861
 27862
 27863
 27864
 27865
 27866
 27867
 27868
 27869
 27870
 27871
 27872
 27873
 27874
 27875
 27876
 27877
 27878
 27879
 27880
 27881
 27882
 27883
 27884
 27885
 27886
 27887
 27888
 27889
 27890
 27891
 27892
 27893
 27894
 27895
 27896
 27897
 27898
 27899
 27900
 27901
 27902
 27903
 27904
 27905
 27906
 27907
 27908
 27909
 27910
 27911
 27912
 27913
 27914
 27915
 27916
 27917
 27918
 27919
 27920
 27921
 27922
 27923
 27924
 27925
 27926
 27927
 27928
 27929
 27930
 27931
 27932
 27933
 27934
 27935
 27936
 27937
 27938
 27939
 27940
 27941
 27942
 27943
 27944
 27945
 27946
 27947
 27948
 27949
 27950
 27951
 27952
 27953
 27954
 27955
 27956
 27957
 27958
 27959
 27960
 27961
 27962
 27963
 27964
 27965
 27966
 27967
 27968
 27969
 27970
 27971
 27972
 27973
 27974
 27975
 27976
 27977
 27978
 27979
 27980
 27981
 27982
 27983
 27984
 27985
 27986
 27987
 27988
 27989
 27990
 27991
 27992
 27993
 27994
 27995
 27996
 27997
 27998
 27999
 28000
 28001
 28002
 28003
 28004
 28005
 28006
 28007
 28008
 28009
 28010
 28011
 28012
 28013
 28014
 28015
 28016
 28017
 28018
 28019
 28020
 28021
 28022
 28023
 28024
 28025
 28026
 28027
 28028
 28029
 28030
 28031
 28032
 28033
 28034
 28035
 28036
 28037
 28038
 28039
 28040
 28041
 28042
 28043
 28044
 28045
 28046
 28047
 28048
 28049
 28050
 28051
 28052
 28053
 28054
 28055
 28056
 28057
 28058
 28059
 28060
 28061
 28062
 28063
 28064
 28065
 28066
 28067
 28068
 28069
 28070
 28071
 28072
 28073
 28074
 28075
 28076
 28077
 28078
 28079
 28080
 28081
 28082
 28083
 28084
 28085
 28086
 28087
 28088
 28089
 28090
 28091
 28092
 28093
 28094
 28095
 28096
 28097
 28098
 28099
 28100
 28101
 28102
 28103
 28104
 28105
 28106
 28107
 28108
 28109
 28110
 28111
 28112
 28113
 28114
 28115
 28116
 28117
 28118
 28119
 28120
 28121
 28122
 28123
 28124
 28125
 28126
 28127
 28128
 28129
 28130
 28131
 28132
 28133
 28134
 28135
 28136
 28137
 28138
 28139
 28140
 28141
 28142
 28143
 28144
 28145
 28146
 28147
 28148
 28149
 28150
 28151
 28152
 28153
 28154
 28155
 28156
 28157
 28158
 28159
 28160
 28161
 28162
 28163
 28164
 28165
 28166
 28167
 28168
 28169
 28170
 28171
 28172
 28173
 28174
 28175
 28176
 28177
 28178
 28179
 28180
 28181
 28182
 28183
 28184
 28185
 28186
 28187
 28188
 28189
 28190
 28191
 28192
 28193
 28194
 28195
 28196
 28197
 28198
 28199
 28200
 28201
 28202
 28203
 28204
 28205
 28206
 28207
 28208
 28209
 28210
 28211
 28212
 28213
 28214
 28215
 28216
 28217
 28218
 28219
 28220
 28221
 28222
 28223
 28224
 28225
 28226
 28227
 28228
 28229
 28230
 28231
 28232
 28233
 28234
 28235
 28236
 28237
 28238
 28239
 28240
 28241
 28242
 28243
 28244
 28245
 28246
 28247
 28248
 28249
 28250
 28251
 28252
 28253
 28254
 28255
 28256
 28257
 28258
 28259
 28260
 28261
 28262
 28263
 28264
 28265
 28266
 28267
 28268
 28269
 28270
 28271
 28272
 28273
 28274
 28275
 28276
 28277
 28278
 28279
 28280
 28281
 28282
 28283
 28284
 28285
 28286
 28287
 28288
 28289
 28290
 28291
 28292
 28293
 28294
 28295
 28296
 28297
 28298
 28299
 28300
 28301
 28302
 28303
 28304
 28305
 28306
 28307
 28308
 28309
 28310
 28311
 28312
 28313
 28314
 28315
 28316
 28317
 28318
 28319
 28320
 28321
 28322
 28323
 28324
 28325
 28326
 28327
 28328
 28329
 28330
 28331
 28332
 28333
 28334
 28335
 28336
 28337
 28338
 28339
 28340
 28341
 28342
 28343
 28344
 28345
 28346
 28347
 28348
 28349
 28350
 28351
 28352
 28353
 28354
 28355
 28356
 28357
 28358
 28359
 28360
 28361
 28362
 28363
 28364
 28365
 28366
 28367
 28368
 28369
 28370
 28371
 28372
 28373
 28374
 28375
 28376
 28377
 28378
 28379
 28380
 28381
 28382
 28383
 28384
 28385
 28386
 28387
 28388
 28389
 28390
 28391
 28392
 28393
 28394
 28395
 28396
 28397
 28398
 28399
 28400
 28401
 28402
 28403
 28404
 28405
 28406
 28407
 28408
 28409
 28410
 28411
 28412
 28413
 28414
 28415
 28416
 28417
 28418
 28419
 28420
 28421
 28422
 28423
 28424
 28425
 28426
 28427
 28428
 28429
 28430
 28431
 28432
 28433
 28434
 28435
 28436
 28437
 28438
 28439
 28440
 28441
 28442
 28443
 28444
 28445
 28446
 28447
 28448
 28449
 28450
 28451
 28452
 28453
 28454
 28455
 28456
 28457
 28458
 28459
 28460
 28461
 28462
 28463
 28464
 28465
 28466
 28467
 28468
 28469
 28470
 28471
 28472
 28473
 28474
 28475
 28476
 28477
 28478
 28479
 28480
 28481
 28482
 28483
 28484
 28485
 28486
 28487
 28488
 28489
 28490
 28491
 28492
 28493
 28494
 28495
 28496
 28497
 28498
 28499
 28500
 28501
 28502
 28503
 28504
 28505
 28506
 28507
 28508
 28509
 28510
 28511
 28512
 28513
 28514
 28515
 28516
 28517
 28518
 28519
 28520
 28521
 28522
 28523
 28524
 28525
 28526
 28527
 28528
 28529
 28530
 28531
 28532
 28533
 28534
 28535
 28536
 28537
 28538
 28539
 28540
 28541
 28542
 28543
 28544
 28545
 28546
 28547
 28548
 28549
 28550
 28551
 28552
 28553
 28554
 28555
 28556
 28557
 28558
 28559
 28560
 28561
 28562
 28563
 28564
 28565
 28566
 28567
 28568
 28569
 28570
 28571
 28572
 28573
 28574
 28575
 28576
 28577
 28578
 28579
 28580
 28581
 28582
 28583
 28584
 28585
 28586
 28587
 28588
 28589
 28590
 28591
 28592
 28593
 28594
 28595
 28596
 28597
 28598
 28599
 28600
 28601
 28602
 28603
 28604
 28605
 28606
 28607
 28608
 28609
 28610
 28611
 28612
 28613
 28614
 28615
 28616
 28617
 28618
 28619
 28620
 28621
 28622
 28623
 28624
 28625
 28626
 28627
 28628
 28629
 28630
 28631
 28632
 28633
 28634
 28635
 28636
 28637
 28638
 28639
 28640
 28641
 28642
 28643
 28644
 28645
 28646
 28647
 28648
 28649
 28650
 28651
 28652
 28653
 28654
 28655
 28656
 28657
 28658
 28659
 28660
 28661
 28662
 28663
 28664
 28665
 28666
 28667
 28668
 28669
 28670
 28671
 28672
 28673
 28674
 28675
 28676
 28677
 28678
 28679
 28680
 28681
 28682
 28683
 28684
 28685
 28686
 28687
 28688
 28689
 28690
 28691
 28692
 28693
 28694
 28695
 28696
 28697
 28698
 28699
 28700
 28701
 28702
 28703
 28704
 28705
 28706
 28707
 28708
 28709
 28710
 28711
 28712
 28713
 28714
 28715
 28716
 28717
 28718
 28719
 28720
 28721
 28722
 28723
 28724
 28725
 28726
 28727
 28728
 28729
 28730
 28731
 28732
 28733
 28734
 28735
 28736
 28737
 28738
 28739
 28740
 28741
 28742
 28743
 28744
 28745
 28746
 28747
 28748
 28749
 28750
 28751
 28752
 28753
 28754
 28755
 28756
 28757
 28758
 28759
 28760
 28761
 28762
 28763
 28764
 28765
 28766
 28767
 28768
 28769
 28770
 28771
 28772
 28773
 28774
 28775
 28776
 28777
 28778
 28779
 28780
 28781
 28782
 28783
 28784
 28785
 28786
 28787
 28788
 28789
 28790
 28791
 28792
 28793
 28794
 28795
 28796
 28797
 28798
 28799
 28800
 28801
 28802
 28803
 28804
 28805
 28806
 28807
 28808
 28809
 28810
 28811
 28812
 28813
 28814
 28815
 28816
 28817
 28818
 28819
 28820
 28821
 28822
 28823
 28824
 28825
 28826
 28827
 28828
 28829
 28830
 28831
 28832
 28833
 28834
 28835
 28836
 28837
 28838
 28839
 28840
 28841
 28842
 28843
 28844
 28845
 28846
 28847
 28848
 28849
 28850
 28851
 28852
 28853
 28854
 28855
 28856
 28857
 28858
 28859
 28860
 28861
 28862
 28863
 28864
 28865
 28866
 28867
 28868
 28869
 28870
 28871
 28872
 28873
 28874
 28875
 28876
 28877
 28878
 28879
 28880
 28881
 28882
 28883
 28884
 28885
 28886
 28887
 28888
 28889
 28890
 28891
 28892
 28893
 28894
 28895
 28896
 28897
 28898
 28899
 28900
 28901
 28902
 28903
 28904
 28905
 28906
 28907
 28908
 28909
 28910
 28911
 28912
 28913
 28914
 28915
 28916
 28917
 28918
 28919
 28920
 28921
 28922
 28923
 28924
 28925
 28926
 28927
 28928
 28929
 28930
 28931
 28932
 28933
 28934
 28935
 28936
 28937
 28938
 28939
 28940
 28941
 28942
 28943
 28944
 28945
 28946
 28947
 28948
 28949
 28950
 28951
 28952
 28953
 28954
 28955
 28956
 28957
 28958
 28959
 28960
 28961
 28962
 28963
 28964
 28965
 28966
 28967
 28968
 28969
 28970
 28971
 28972
 28973
 28974
 28975
 28976
 28977
 28978
 28979
 28980
 28981
 28982
 28983
 28984
 28985
 28986
 28987
 28988
 28989
 28990
 28991
 28992
 28993
 28994
 28995
 28996
 28997
 28998
 28999
 29000
 29001
 29002
 29003
 29004
 29005
 29006
 29007
 29008
 29009
 29010
 29011
 29012
 29013
 29014
 29015
 29016
 29017
 29018
 29019
 29020
 29021
 29022
 29023
 29024
 29025
 29026
 29027
 29028
 29029
 29030
 29031
 29032
 29033
 29034
 29035
 29036
 29037
 29038
 29039
 29040
 29041
 29042
 29043
 29044
 29045
 29046
 29047
 29048
 29049
 29050
 29051
 29052
 29053
 29054
 29055
 29056
 29057
 29058
 29059
 29060
 29061
 29062
 29063
 29064
 29065
 29066
 29067
 29068
 29069
 29070
 29071
 29072
 29073
 29074
 29075
 29076
 29077
 29078
 29079
 29080
 29081
 29082
 29083
 29084
 29085
 29086
 29087
 29088
 29089
 29090
 29091
 29092
 29093
 29094
 29095
 29096
 29097
 29098
 29099
 29100
 29101
 29102
 29103
 29104
 29105
 29106
 29107
 29108
 29109
 29110
 29111
 29112
 29113
 29114
 29115
 29116
 29117
 29118
 29119
 29120
 29121
 29122
 29123
 29124
 29125
 29126
 29127
 29128
 29129
 29130
 29131
 29132
 29133
 29134
 29135
 29136
 29137
 29138
 29139
 29140
 29141
 29142
 29143
 29144
 29145
 29146
 29147
 29148
 29149
 29150
 29151
 29152
 29153
 29154
 29155
 29156
 29157
 29158
 29159
 29160
 29161
 29162
 29163
 29164
 29165
 29166
 29167
 29168
 29169
 29170
 29171
 29172
 29173
 29174
 29175
 29176
 29177
 29178
 29179
 29180
 29181
 29182
 29183
 29184
 29185
 29186
 29187
 29188
 29189
 29190
 29191
 29192
 29193
 29194
 29195
 29196
 29197
 29198
 29199
 29200
 29201
 29202
 29203
 29204
 29205
 29206
 29207
 29208
 29209
 29210
 29211
 29212
 29213
 29214
 29215
 29216
 29217
 29218
 29219
 29220
 29221
 29222
 29223
 29224
 29225
 29226
 29227
 29228
 29229
 29230
 29231
 29232
 29233
 29234
 29235
 29236
 29237
 29238
 29239
 29240
 29241
 29242
 29243
 29244
 29245
 29246
 29247
 29248
 29249
 29250
 29251
 29252
 29253
 29254
 29255
 29256
 29257
 29258
 29259
 29260
 29261
 29262
 29263
 29264
 29265
 29266
 29267
 29268
 29269
 29270
 29271
 29272
 29273
 29274
 29275
 29276
 29277
 29278
 29279
 29280
 29281
 29282
 29283
 29284
 29285
 29286
 29287
 29288
 29289
 29290
 29291
 29292
 29293
 29294
 29295
 29296
 29297
 29298
 29299
 29300
 29301
 29302
 29303
 29304
 29305
 29306
 29307
 29308
 29309
 29310
 29311
 29312
 29313
 29314
 29315
 29316
 29317
 29318
 29319
 29320
 29321
 29322
 29323
 29324
 29325
 29326
 29327
 29328
 29329
 29330
 29331
 29332
 29333
 29334
 29335
 29336
 29337
 29338
 29339
 29340
 29341
 29342
 29343
 29344
 29345
 29346
 29347
 29348
 29349
 29350
 29351
 29352
 29353
 29354
 29355
 29356
 29357
 29358
 29359
 29360
 29361
 29362
 29363
 29364
 29365
 29366
 29367
 29368
 29369
 29370
 29371
 29372
 29373
 29374
 29375
 29376
 29377
 29378
 29379
 29380
 29381
 29382
 29383
 29384
 29385
 29386
 29387
 29388
 29389
 29390
 29391
 29392
 29393
 29394
 29395
 29396
 29397
 29398
 29399
 29400
 29401
 29402
 29403
 29404
 29405
 29406
 29407
 29408
 29409
 29410
 29411
 29412
 29413
 29414
 29415
 29416
 29417
 29418
 29419
 29420
 29421
 29422
 29423
 29424
 29425
 29426
 29427
 29428
 29429
 29430
 29431
 29432
 29433
 29434
 29435
 29436
 29437
 29438
 29439
 29440
 29441
 29442
 29443
 29444
 29445
 29446
 29447
 29448
 29449
 29450
 29451
 29452
 29453
 29454
 29455
 29456
 29457
 29458
 29459
 29460
 29461
 29462
 29463
 29464
 29465
 29466
 29467
 29468
 29469
 29470
 29471
 29472
 29473
 29474
 29475
 29476
 29477
 29478
 29479
 29480
 29481
 29482
 29483
 29484
 29485
 29486
 29487
 29488
 29489
 29490
 29491
 29492
 29493
 29494
 29495
 29496
 29497
 29498
 29499
 29500
 29501
 29502
 29503
 29504
 29505
 29506
 29507
 29508
 29509
 29510
 29511
 29512
 29513
 29514
 29515
 29516
 29517
 29518
 29519
 29520
 29521
 29522
 29523
 29524
 29525
 29526
 29527
 29528
 29529
 29530
 29531
 29532
 29533
 29534
 29535
 29536
 29537
 29538
 29539
 29540
 29541
 29542
 29543
 29544
 29545
 29546
 29547
 29548
 29549
 29550
 29551
 29552
 29553
 29554
 29555
 29556
 29557
 29558
 29559
 29560
 29561
 29562
 29563
 29564
 29565
 29566
 29567
 29568
 29569
 29570
 29571
 29572
 29573
 29574
 29575
 29576
 29577
 29578
 29579
 29580
 29581
 29582
 29583
 29584
 29585
 29586
 29587
 29588
 29589
 29590
 29591
 29592
 29593
 29594
 29595
 29596
 29597
 29598
 29599
 29600
 29601
 29602
 29603
 29604
 29605
 29606
 29607
 29608
 29609
 29610
 29611
 29612
 29613
 29614
 29615
 29616
 29617
 29618
 29619
 29620
 29621
 29622
 29623
 29624
 29625
 29626
 29627
 29628
 29629
 29630
 29631
 29632
 29633
 29634
 29635
 29636
 29637
 29638
 29639
 29640
 29641
 29642
 29643
 29644
 29645
 29646
 29647
 29648
 29649
 29650
 29651
 29652
 29653
 29654
 29655
 29656
 29657
 29658
 29659
 29660
 29661
 29662
 29663
 29664
 29665
 29666
 29667
 29668
 29669
 29670
 29671
 29672
 29673
 29674
 29675
 29676
 29677
 29678
 29679
 29680
 29681
 29682
 29683
 29684
 29685
 29686
 29687
 29688
 29689
 29690
 29691
 29692
 29693
 29694
 29695
 29696
 29697
 29698
 29699
 29700
 29701
 29702
 29703
 29704
 29705
 29706
 29707
 29708
 29709
 29710
 29711
 29712
 29713
 29714
 29715
 29716
 29717
 29718
 29719
 29720
 29721
 29722
 29723
 29724
 29725
 29726
 29727
 29728
 29729
 29730
 29731
 29732
 29733
 29734
 29735
 29736
 29737
 29738
 29739
 29740
 29741
 29742
 29743
 29744
 29745
 29746
 29747
 29748
 29749
 29750
 29751
 29752
 29753
 29754
 29755
 29756
 29757
 29758
 29759
 29760
 29761
 29762
 29763
 29764
 29765
 29766
 29767
 29768
 29769
 29770
 29771
 29772
 29773
 29774
 29775
 29776
 29777
 29778
 29779
 29780
 29781
 29782
 29783
 29784
 29785
 29786
 29787
 29788
 29789
 29790
 29791
 29792
 29793
 29794
 29795
 29796
 29797
 29798
 29799
 29800
 29801
 29802
 29803
 29804
 29805
 29806
 29807
 29808
 29809
 29810
 29811
 29812
 29813
 29814
 29815
 29816
 29817
 29818
 29819
 29820
 29821
 29822
 29823
 29824
 29825
 29826
 29827
 29828
 29829
 29830
 29831
 29832
 29833
 29834
 29835
 29836
 29837
 29838
 29839
 29840
 29841
 29842
 29843
 29844
 29845
 29846
 29847
 29848
 29849
 29850
 29851
 29852
 29853
 29854
 29855
 29856
 29857
 29858
 29859
 29860
 29861
 29862
 29863
 29864
 29865
 29866
 29867
 29868
 29869
 29870
 29871
 29872
 29873
 29874
 29875
 29876
 29877
 29878
 29879
 29880
 29881
 29882
 29883
 29884
 29885
 29886
 29887
 29888
 29889
 29890
 29891
 29892
 29893
 29894
 29895
 29896
 29897
 29898
 29899
 29900
 29901
 29902
 29903
 29904
 29905
 29906
 29907
 29908
 29909
 29910
 29911
 29912
 29913
 29914
 29915
 29916
 29917
 29918
 29919
 29920
 29921
 29922
 29923
 29924
 29925
 29926
 29927
 29928
 29929
 29930
 29931
 29932
 29933
 29934
 29935
 29936
 29937
 29938
 29939
 29940
 29941
 29942
 29943
 29944
 29945
 29946
 29947
 29948
 29949
 29950
 29951
 29952
 29953
 29954
 29955
 29956
 29957
 29958
 29959
 29960
 29961
 29962
 29963
 29964
 29965
 29966
 29967
 29968
 29969
 29970
 29971
 29972
 29973
 29974
 29975
 29976
 29977
 29978
 29979
 29980
 29981
 29982
 29983
 29984
 29985
 29986
 29987
 29988
 29989
 29990
 29991
 29992
 29993
 29994
 29995
 29996
 29997
 29998
 29999
 30000
 30001
 30002
 30003
 30004
 30005
 30006
 30007
 30008
 30009
 30010
 30011
 30012
 30013
 30014
 30015
 30016
 30017
 30018
 30019
 30020
 30021
 30022
 30023
 30024
 30025
 30026
 30027
 30028
 30029
 30030
 30031
 30032
 30033
 30034
 30035
 30036
 30037
 30038
 30039
 30040
 30041
 30042
 30043
 30044
 30045
 30046
 30047
 30048
 30049
 30050
 30051
 30052
 30053
 30054
 30055
 30056
 30057
 30058
 30059
 30060
 30061
 30062
 30063
 30064
 30065
 30066
 30067
 30068
 30069
 30070
 30071
 30072
 30073
 30074
 30075
 30076
 30077
 30078
 30079
 30080
 30081
 30082
 30083
 30084
 30085
 30086
 30087
 30088
 30089
 30090
 30091
 30092
 30093
 30094
 30095
 30096
 30097
 30098
 30099
 30100
 30101
 30102
 30103
 30104
 30105
 30106
 30107
 30108
 30109
 30110
 30111
 30112
 30113
 30114
 30115
 30116
 30117
 30118
 30119
 30120
 30121
 30122
 30123
 30124
 30125
 30126
 30127
 30128
 30129
 30130
 30131
 30132
 30133
 30134
 30135
 30136
 30137
 30138
 30139
 30140
 30141
 30142
 30143
 30144
 30145
 30146
 30147
 30148
 30149
 30150
 30151
 30152
 30153
 30154
 30155
 30156
 30157
 30158
 30159
 30160
 30161
 30162
 30163
 30164
 30165
 30166
 30167
 30168
 30169
 30170
 30171
 30172
 30173
 30174
 30175
 30176
 30177
 30178
 30179
 30180
 30181
 30182
 30183
 30184
 30185
 30186
 30187
 30188
 30189
 30190
 30191
 30192
 30193
 30194
 30195
 30196
 30197
 30198
 30199
 30200
 30201
 30202
 30203
 30204
 30205
 30206
 30207
 30208
 30209
 30210
 30211
 30212
 30213
 30214
 30215
 30216
 30217
 30218
 30219
 30220
 30221
 30222
 30223
 30224
 30225
 30226
 30227
 30228
 30229
 30230
 30231
 30232
 30233
 30234
 30235
 30236
 30237
 30238
 30239
 30240
 30241
 30242
 30243
 30244
 30245
 30246
 30247
 30248
 30249
 30250
 30251
 30252
 30253
 30254
 30255
 30256
 30257
 30258
 30259
 30260
 30261
 30262
 30263
 30264
 30265
 30266
 30267
 30268
 30269
 30270
 30271
 30272
 30273
 30274
 30275
 30276
 30277
 30278
 30279
 30280
 30281
 30282
 30283
 30284
 30285
 30286
 30287
 30288
 30289
 30290
 30291
 30292
 30293
 30294
 30295
 30296
 30297
 30298
 30299
 30300
 30301
 30302
 30303
 30304
 30305
 30306
 30307
 30308
 30309
 30310
 30311
 30312
 30313
 30314
 30315
 30316
 30317
 30318
 30319
 30320
 30321
 30322
 30323
 30324
 30325
 30326
 30327
 30328
 30329
 30330
 30331
 30332
 30333
 30334
 30335
 30336
 30337
 30338
 30339
 30340
 30341
 30342
 30343
 30344
 30345
 30346
 30347
 30348
 30349
 30350
 30351
 30352
 30353
 30354
 30355
 30356
 30357
 30358
 30359
 30360
 30361
 30362
 30363
 30364
 30365
 30366
 30367
 30368
 30369
 30370
 30371
 30372
 30373
 30374
 30375
 30376
 30377
 30378
 30379
 30380
 30381
 30382
 30383
 30384
 30385
 30386
 30387
 30388
 30389
 30390
 30391
 30392
 30393
 30394
 30395
 30396
 30397
 30398
 30399
 30400
 30401
 30402
 30403
 30404
 30405
 30406
 30407
 30408
 30409
 30410
 30411
 30412
 30413
 30414
 30415
 30416
 30417
 30418
 30419
 30420
 30421
 30422
 30423
 30424
 30425
 30426
 30427
 30428
 30429
 30430
 30431
 30432
 30433
 30434
 30435
 30436
 30437
 30438
 30439
 30440
 30441
 30442
 30443
 30444
 30445
 30446
 30447
 30448
 30449
 30450
 30451
 30452
 30453
 30454
 30455
 30456
 30457
 30458
 30459
 30460
 30461
 30462
 30463
 30464
 30465
 30466
 30467
 30468
 30469
 30470
 30471
 30472
 30473
 30474
 30475
 30476
 30477
 30478
 30479
 30480
 30481
 30482
 30483
 30484
 30485
 30486
 30487
 30488
 30489
 30490
 30491
 30492
 30493
 30494
 30495
 30496
 30497
 30498
 30499
 30500
 30501
 30502
 30503
 30504
 30505
 30506
 30507
 30508
 30509
 30510
 30511
 30512
 30513
 30514
 30515
 30516
 30517
 30518
 30519
 30520
 30521
 30522
 30523
 30524
 30525
 30526
 30527
 30528
 30529
 30530
 30531
 30532
 30533
 30534
 30535
 30536
 30537
 30538
 30539
 30540
 30541
 30542
 30543
 30544
 30545
 30546
 30547
 30548
 30549
 30550
 30551
 30552
 30553
 30554
 30555
 30556
 30557
 30558
 30559
 30560
 30561
 30562
 30563
 30564
 30565
 30566
 30567
 30568
 30569
 30570
 30571
 30572
 30573
 30574
 30575
 30576
 30577
 30578
 30579
 30580
 30581
 30582
 30583
 30584
 30585
 30586
 30587
 30588
 30589
 30590
 30591
 30592
 30593
 30594
 30595
 30596
 30597
 30598
 30599
 30600
 30601
 30602
 30603
 30604
 30605
 30606
 30607
 30608
 30609
 30610
 30611
 30612
 30613
 30614
 30615
 30616
 30617
 30618
 30619
 30620
 30621
 30622
 30623
 30624
 30625
 30626
 30627
 30628
 30629
 30630
 30631
 30632
 30633
 30634
 30635
 30636
 30637
 30638
 30639
 30640
 30641
 30642
 30643
 30644
 30645
 30646
 30647
 30648
 30649
 30650
 30651
 30652
 30653
 30654
 30655
 30656
 30657
 30658
 30659
 30660
 30661
 30662
 30663
 30664
 30665
 30666
 30667
 30668
 30669
 30670
 30671
 30672
 30673
 30674
 30675
 30676
 30677
 30678
 30679
 30680
 30681
 30682
 30683
 30684
 30685
 30686
 30687
 30688
 30689
 30690
 30691
 30692
 30693
 30694
 30695
 30696
 30697
 30698
 30699
 30700
 30701
 30702
 30703
 30704
 30705
 30706
 30707
 30708
 30709
 30710
 30711
 30712
 30713
 30714
 30715
 30716
 30717
 30718
 30719
 30720
 30721
 30722
 30723
 30724
 30725
 30726
 30727
 30728
 30729
 30730
 30731
 30732
 30733
 30734
 30735
 30736
 30737
 30738
 30739
 30740
 30741
 30742
 30743
 30744
 30745
 30746
 30747
 30748
 30749
 30750
 30751
 30752
 30753
 30754
 30755
 30756
 30757
 30758
 30759
 30760
 30761
 30762
 30763
 30764
 30765
 30766
 30767
 30768
 30769
 30770
 30771
 30772
 30773
 30774
 30775
 30776
 30777
 30778
 30779
 30780
 30781
 30782
 30783
 30784
 30785
 30786
 30787
 30788
 30789
 30790
 30791
 30792
 30793
 30794
 30795
 30796
 30797
 30798
 30799
 30800
 30801
 30802
 30803
 30804
 30805
 30806
 30807
 30808
 30809
 30810
 30811
 30812
 30813
 30814
 30815
 30816
 30817
 30818
 30819
 30820
 30821
 30822
 30823
 30824
 30825
 30826
 30827
 30828
 30829
 30830
 30831
 30832
 30833
 30834
 30835
 30836
 30837
 30838
 30839
 30840
 30841
 30842
 30843
 30844
 30845
 30846
 30847
 30848
 30849
 30850
 30851
 30852
 30853
 30854
 30855
 30856
 30857
 30858
 30859
 30860
 30861
 30862
 30863
 30864
 30865
 30866
 30867
 30868
 30869
 30870
 30871
 30872
 30873
 30874
 30875
 30876
 30877
 30878
 30879
 30880
 30881
 30882
 30883
 30884
 30885
 30886
 30887
 30888
 30889
 30890
 30891
 30892
 30893
 30894
 30895
 30896
 30897
 30898
 30899
 30900
 30901
 30902
 30903
 30904
 30905
 30906
 30907
 30908
 30909
 30910
 30911
 30912
 30913
 30914
 30915
 30916
 30917
 30918
 30919
 30920
 30921
 30922
 30923
 30924
 30925
 30926
 30927
 30928
 30929
 30930
 30931
 30932
 30933
 30934
 30935
 30936
 30937
 30938
 30939
 30940
 30941
 30942
 30943
 30944
 30945
 30946
 30947
 30948
 30949
 30950
 30951
 30952
 30953
 30954
 30955
 30956
 30957
 30958
 30959
 30960
 30961
 30962
 30963
 30964
 30965
 30966
 30967
 30968
 30969
 30970
 30971
 30972
 30973
 30974
 30975
 30976
 30977
 30978
 30979
 30980
 30981
 30982
 30983
 30984
 30985
 30986
 30987
 30988
 30989
 30990
 30991
 30992
 30993
 30994
 30995
 30996
 30997
 30998
 30999
 31000
 31001
 31002
 31003
 31004
 31005
 31006
 31007
 31008
 31009
 31010
 31011
 31012
 31013
 31014
 31015
 31016
 31017
 31018
 31019
 31020
 31021
 31022
 31023
 31024
 31025
 31026
 31027
 31028
 31029
 31030
 31031
 31032
 31033
 31034
 31035
 31036
 31037
 31038
 31039
 31040
 31041
 31042
 31043
 31044
 31045
 31046
 31047
 31048
 31049
 31050
 31051
 31052
 31053
 31054
 31055
 31056
 31057
 31058
 31059
 31060
 31061
 31062
 31063
 31064
 31065
 31066
 31067
 31068
 31069
 31070
 31071
 31072
 31073
 31074
 31075
 31076
 31077
 31078
 31079
 31080
 31081
 31082
 31083
 31084
 31085
 31086
 31087
 31088
 31089
 31090
 31091
 31092
 31093
 31094
 31095
 31096
 31097
 31098
 31099
 31100
 31101
 31102
 31103
 31104
 31105
 31106
 31107
 31108
 31109
 31110
 31111
 31112
 31113
 31114
 31115
 31116
 31117
 31118
 31119
 31120
 31121
 31122
 31123
 31124
 31125
 31126
 31127
 31128
 31129
 31130
 31131
 31132
 31133
 31134
 31135
 31136
 31137
 31138
 31139
 31140
 31141
 31142
 31143
 31144
 31145
 31146
 31147
 31148
 31149
 31150
 31151
 31152
 31153
 31154
 31155
 31156
 31157
 31158
 31159
 31160
 31161
 31162
 31163
 31164
 31165
 31166
 31167
 31168
 31169
 31170
 31171
 31172
 31173
 31174
 31175
 31176
 31177
 31178
 31179
 31180
 31181
 31182
 31183
 31184
 31185
 31186
 31187
 31188
 31189
 31190
 31191
 31192
 31193
 31194
 31195
 31196
 31197
 31198
 31199
 31200
 31201
 31202
 31203
 31204
 31205
 31206
 31207
 31208
 31209
 31210
 31211
 31212
 31213
 31214
 31215
 31216
 31217
 31218
 31219
 31220
 31221
 31222
 31223
 31224
 31225
 31226
 31227
 31228
 31229
 31230
 31231
 31232
 31233
 31234
 31235
 31236
 31237
 31238
 31239
 31240
 31241
 31242
 31243
 31244
 31245
 31246
 31247
 31248
 31249
 31250
 31251
 31252
 31253
 31254
 31255
 31256
 31257
 31258
 31259
 31260
 31261
 31262
 31263
 31264
 31265
 31266
 31267
 31268
 31269
 31270
 31271
 31272
 31273
 31274
 31275
 31276
 31277
 31278
 31279
 31280
 31281
 31282
 31283
 31284
 31285
 31286
 31287
 31288
 31289
 31290
 31291
 31292
 31293
 31294
 31295
 31296
 31297
 31298
 31299
 31300
 31301
 31302
 31303
 31304
 31305
 31306
 31307
 31308
 31309
 31310
 31311
 31312
 31313
 31314
 31315
 31316
 31317
 31318
 31319
 31320
 31321
 31322
 31323
 31324
 31325
 31326
 31327
 31328
 31329
 31330
 31331
 31332
 31333
 31334
 31335
 31336
 31337
 31338
 31339
 31340
 31341
 31342
 31343
 31344
 31345
 31346
 31347
 31348
 31349
 31350
 31351
 31352
 31353
 31354
 31355
 31356
 31357
 31358
 31359
 31360
 31361
 31362
 31363
 31364
 31365
 31366
 31367
 31368
 31369
 31370
 31371
 31372
 31373
 31374
 31375
 31376
 31377
 31378
 31379
 31380
 31381
 31382
 31383
 31384
 31385
 31386
 31387
 31388
 31389
 31390
 31391
 31392
 31393
 31394
 31395
 31396
 31397
 31398
 31399
 31400
 31401
 31402
 31403
 31404
 31405
 31406
 31407
 31408
 31409
 31410
 31411
 31412
 31413
 31414
 31415
 31416
 31417
 31418
 31419
 31420
 31421
 31422
 31423
 31424
 31425
 31426
 31427
 31428
 31429
 31430
 31431
 31432
 31433
 31434
 31435
 31436
 31437
 31438
 31439
 31440
 31441
 31442
 31443
 31444
 31445
 31446
 31447
 31448
 31449
 31450
 31451
 31452
 31453
 31454
 31455
 31456
 31457
 31458
 31459
 31460
 31461
 31462
 31463
 31464
 31465
 31466
 31467
 31468
 31469
 31470
 31471
 31472
 31473
 31474
 31475
 31476
 31477
 31478
 31479
 31480
 31481
 31482
 31483
 31484
 31485
 31486
 31487
 31488
 31489
 31490
 31491
 31492
 31493
 31494
 31495
 31496
 31497
 31498
 31499
 31500
 31501
 31502
 31503
 31504
 31505
 31506
 31507
 31508
 31509
 31510
 31511
 31512
 31513
 31514
 31515
 31516
 31517
 31518
 31519
 31520
 31521
 31522
 31523
 31524
 31525
 31526
 31527
 31528
 31529
 31530
 31531
 31532
 31533
 31534
 31535
 31536
 31537
 31538
 31539
 31540
 31541
 31542
 31543
 31544
 31545
 31546
 31547
 31548
 31549
 31550
 31551
 31552
 31553
 31554
 31555
 31556
 31557
 31558
 31559
 31560
 31561
 31562
 31563
 31564
 31565
 31566
 31567
 31568
 31569
 31570
 31571
 31572
 31573
 31574
 31575
 31576
 31577
 31578
 31579
 31580
 31581
 31582
 31583
 31584
 31585
 31586
 31587
 31588
 31589
 31590
 31591
 31592
 31593
 31594
 31595
 31596
 31597
 31598
 31599
 31600
 31601
 31602
 31603
 31604
 31605
 31606
 31607
 31608
 31609
 31610
 31611
 31612
 31613
 31614
 31615
 31616
 31617
 31618
 31619
 31620
 31621
 31622
 31623
 31624
 31625
 31626
 31627
 31628
 31629
 31630
 31631
 31632
 31633
 31634
 31635
 31636
 31637
 31638
 31639
 31640
 31641
 31642
 31643
 31644
 31645
 31646
 31647
 31648
 31649
 31650
 31651
 31652
 31653
 31654
 31655
 31656
 31657
 31658
 31659
 31660
 31661
 31662
 31663
 31664
 31665
 31666
 31667
 31668
 31669
 31670
 31671
 31672
 31673
 31674
 31675
 31676
 31677
 31678
 31679
 31680
 31681
 31682
 31683
 31684
 31685
 31686
 31687
 31688
 31689
 31690
 31691
 31692
 31693
 31694
 31695
 31696
 31697
 31698
 31699
 31700
 31701
 31702
 31703
 31704
 31705
 31706
 31707
 31708
 31709
 31710
 31711
 31712
 31713
 31714
 31715
 31716
 31717
 31718
 31719
 31720
 31721
 31722
 31723
 31724
 31725
 31726
 31727
 31728
 31729
 31730
 31731
 31732
 31733
 31734
 31735
 31736
 31737
 31738
 31739
 31740
 31741
 31742
 31743
 31744
 31745
 31746
 31747
 31748
 31749
 31750
 31751
 31752
 31753
 31754
 31755
 31756
 31757
 31758
 31759
 31760
 31761
 31762
 31763
 31764
 31765
 31766
 31767
 31768
 31769
 31770
 31771
 31772
 31773
 31774
 31775
 31776
 31777
 31778
 31779
 31780
 31781
 31782
 31783
 31784
 31785
 31786
 31787
 31788
 31789
 31790
 31791
 31792
 31793
 31794
 31795
 31796
 31797
 31798
 31799
 31800
 31801
 31802
 31803
 31804
 31805
 31806
 31807
 31808
 31809
 31810
 31811
 31812
 31813
 31814
 31815
 31816
 31817
 31818
 31819
 31820
 31821
 31822
 31823
 31824
 31825
 31826
 31827
 31828
 31829
 31830
 31831
 31832
 31833
 31834
 31835
 31836
 31837
 31838
 31839
 31840
 31841
 31842
 31843
 31844
 31845
 31846
 31847
 31848
 31849
 31850
 31851
 31852
 31853
 31854
 31855
 31856
 31857
 31858
 31859
 31860
 31861
 31862
 31863
 31864
 31865
 31866
 31867
 31868
 31869
 31870
 31871
 31872
 31873
 31874
 31875
 31876
 31877
 31878
 31879
 31880
 31881
 31882
 31883
 31884
 31885
 31886
 31887
 31888
 31889
 31890
 31891
 31892
 31893
 31894
 31895
 31896
 31897
 31898
 31899
 31900
 31901
 31902
 31903
 31904
 31905
 31906
 31907
 31908
 31909
 31910
 31911
 31912
 31913
 31914
 31915
 31916
 31917
 31918
 31919
 31920
 31921
 31922
 31923
 31924
 31925
 31926
 31927
 31928
 31929
 31930
 31931
 31932
 31933
 31934
 31935
 31936
 31937
 31938
 31939
 31940
 31941
 31942
 31943
 31944
 31945
 31946
 31947
 31948
 31949
 31950
 31951
 31952
 31953
 31954
 31955
 31956
 31957
 31958
 31959
 31960
 31961
 31962
 31963
 31964
 31965
 31966
 31967
 31968
 31969
 31970
 31971
 31972
 31973
 31974
 31975
 31976
 31977
 31978
 31979
 31980
 31981
 31982
 31983
 31984
 31985
 31986
 31987
 31988
 31989
 31990
 31991
 31992
 31993
 31994
 31995
 31996
 31997
 31998
 31999
 32000
 32001
 32002
 32003
 32004
 32005
 32006
 32007
 32008
 32009
 32010
 32011
 32012
 32013
 32014
 32015
 32016
 32017
 32018
 32019
 32020
 32021
 32022
 32023
 32024
 32025
 32026
 32027
 32028
 32029
 32030
 32031
 32032
 32033
 32034
 32035
 32036
 32037
 32038
 32039
 32040
 32041
 32042
 32043
 32044
 32045
 32046
 32047
 32048
 32049
 32050
 32051
 32052
 32053
 32054
 32055
 32056
 32057
 32058
 32059
 32060
 32061
 32062
 32063
 32064
 32065
 32066
 32067
 32068
 32069
 32070
 32071
 32072
 32073
 32074
 32075
 32076
 32077
 32078
 32079
 32080
 32081
 32082
 32083
 32084
 32085
 32086
 32087
 32088
 32089
 32090
 32091
 32092
 32093
 32094
 32095
 32096
 32097
 32098
 32099
 32100
 32101
 32102
 32103
 32104
 32105
 32106
 32107
 32108
 32109
 32110
 32111
 32112
 32113
 32114
 32115
 32116
 32117
 32118
 32119
 32120
 32121
 32122
 32123
 32124
 32125
 32126
 32127
 32128
 32129
 32130
 32131
 32132
 32133
 32134
 32135
 32136
 32137
 32138
 32139
 32140
 32141
 32142
 32143
 32144
 32145
 32146
 32147
 32148
 32149
 32150
 32151
 32152
 32153
 32154
 32155
 32156
 32157
 32158
 32159
 32160
 32161
 32162
 32163
 32164
 32165
 32166
 32167
 32168
 32169
 32170
 32171
 32172
 32173
 32174
 32175
 32176
 32177
 32178
 32179
 32180
 32181
 32182
 32183
 32184
 32185
 32186
 32187
 32188
 32189
 32190
 32191
 32192
 32193
 32194
 32195
 32196
 32197
 32198
 32199
 32200
 32201
 32202
 32203
 32204
 32205
 32206
 32207
 32208
 32209
 32210
 32211
 32212
 32213
 32214
 32215
 32216
 32217
 32218
 32219
 32220
 32221
 32222
 32223
 32224
 32225
 32226
 32227
 32228
 32229
 32230
 32231
 32232
 32233
 32234
 32235
 32236
 32237
 32238
 32239
 32240
 32241
 32242
 32243
 32244
 32245
 32246
 32247
 32248
 32249
 32250
 32251
 32252
 32253
 32254
 32255
 32256
 32257
 32258
 32259
 32260
 32261
 32262
 32263
 32264
 32265
 32266
 32267
 32268
 32269
 32270
 32271
 32272
 32273
 32274
 32275
 32276
 32277
 32278
 32279
 32280
 32281
 32282
 32283
 32284
 32285
 32286
 32287
 32288
 32289
 32290
 32291
 32292
 32293
 32294
 32295
 32296
 32297
 32298
 32299
 32300
 32301
 32302
 32303
 32304
 32305
 32306
 32307
 32308
 32309
 32310
 32311
 32312
 32313
 32314
 32315
 32316
 32317
 32318
 32319
 32320
 32321
 32322
 32323
 32324
 32325
 32326
 32327
 32328
 32329
 32330
 32331
 32332
 32333
 32334
 32335
 32336
 32337
 32338
 32339
 32340
 32341
 32342
 32343
 32344
 32345
 32346
 32347
 32348
 32349
 32350
 32351
 32352
 32353
 32354
 32355
 32356
 32357
 32358
 32359
 32360
 32361
 32362
 32363
 32364
 32365
 32366
 32367
 32368
 32369
 32370
 32371
 32372
 32373
 32374
 32375
 32376
 32377
 32378
 32379
 32380
 32381
 32382
 32383
 32384
 32385
 32386
 32387
 32388
 32389
 32390
 32391
 32392
 32393
 32394
 32395
 32396
 32397
 32398
 32399
 32400
 32401
 32402
 32403
 32404
 32405
 32406
 32407
 32408
 32409
 32410
 32411
 32412
 32413
 32414
 32415
 32416
 32417
 32418
 32419
 32420
 32421
 32422
 32423
 32424
 32425
 32426
 32427
 32428
 32429
 32430
 32431
 32432
 32433
 32434
 32435
 32436
 32437
 32438
 32439
 32440
 32441
 32442
 32443
 32444
 32445
 32446
 32447
 32448
 32449
 32450
 32451
 32452
 32453
 32454
 32455
 32456
 32457
 32458
 32459
 32460
 32461
 32462
 32463
 32464
 32465
 32466
 32467
 32468
 32469
 32470
 32471
 32472
 32473
 32474
 32475
 32476
 32477
 32478
 32479
 32480
 32481
 32482
 32483
 32484
 32485
 32486
 32487
 32488
 32489
 32490
 32491
 32492
 32493
 32494
 32495
 32496
 32497
 32498
 32499
 32500
 32501
 32502
 32503
 32504
 32505
 32506
 32507
 32508
 32509
 32510
 32511
 32512
 32513
 32514
 32515
 32516
 32517
 32518
 32519
 32520
 32521
 32522
 32523
 32524
 32525
 32526
 32527
 32528
 32529
 32530
 32531
 32532
 32533
 32534
 32535
 32536
 32537
 32538
 32539
 32540
 32541
 32542
 32543
 32544
 32545
 32546
 32547
 32548
 32549
 32550
 32551
 32552
 32553
 32554
 32555
 32556
 32557
 32558
 32559
 32560
 32561
 32562
 32563
 32564
 32565
 32566
 32567
 32568
 32569
 32570
 32571
 32572
 32573
 32574
 32575
 32576
 32577
 32578
 32579
 32580
 32581
 32582
 32583
 32584
 32585
 32586
 32587
 32588
 32589
 32590
 32591
 32592
 32593
 32594
 32595
 32596
 32597
 32598
 32599
 32600
 32601
 32602
 32603
 32604
 32605
 32606
 32607
 32608
 32609
 32610
 32611
 32612
 32613
 32614
 32615
 32616
 32617
 32618
 32619
 32620
 32621
 32622
 32623
 32624
 32625
 32626
 32627
 32628
 32629
 32630
 32631
 32632
 32633
 32634
 32635
 32636
 32637
 32638
 32639
 32640
 32641
 32642
 32643
 32644
 32645
 32646
 32647
 32648
 32649
 32650
 32651
 32652
 32653
 32654
 32655
 32656
 32657
 32658
 32659
 32660
 32661
 32662
 32663
 32664
 32665
 32666
 32667
 32668
 32669
 32670
 32671
 32672
 32673
 32674
 32675
 32676
 32677
 32678
 32679
 32680
 32681
 32682
 32683
 32684
 32685
 32686
 32687
 32688
 32689
 32690
 32691
 32692
 32693
 32694
 32695
 32696
 32697
 32698
 32699
 32700
 32701
 32702
 32703
 32704
 32705
 32706
 32707
 32708
 32709
 32710
 32711
 32712
 32713
 32714
 32715
 32716
 32717
 32718
 32719
 32720
 32721
 32722
 32723
 32724
 32725
 32726
 32727
 32728
 32729
 32730
 32731
 32732
 32733
 32734
 32735
 32736
 32737
 32738
 32739
 32740
 32741
 32742
 32743
 32744
 32745
 32746
 32747
 32748
 32749
 32750
 32751
 32752
 32753
 32754
 32755
 32756
 32757
 32758
 32759
 32760
 32761
 32762
 32763
 32764
 32765
 32766
 32767
 32768
 32769
 32770
 32771
 32772
 32773
 32774
 32775
 32776
 32777
 32778
 32779
 32780
 32781
 32782
 32783
 32784
 32785
 32786
 32787
 32788
 32789
 32790
 32791
 32792
 32793
 32794
 32795
 32796
 32797
 32798
 32799
 32800
 32801
 32802
 32803
 32804
 32805
 32806
 32807
 32808
 32809
 32810
 32811
 32812
 32813
 32814
 32815
 32816
 32817
 32818
 32819
 32820
 32821
 32822
 32823
 32824
 32825
 32826
 32827
 32828
 32829
 32830
 32831
 32832
 32833
 32834
 32835
 32836
 32837
 32838
 32839
 32840
 32841
 32842
 32843
 32844
 32845
 32846
 32847
 32848
 32849
 32850
 32851
 32852
 32853
 32854
 32855
 32856
 32857
 32858
 32859
 32860
 32861
 32862
 32863
 32864
 32865
 32866
 32867
 32868
 32869
 32870
 32871
 32872
 32873
 32874
 32875
 32876
 32877
 32878
 32879
 32880
 32881
 32882
 32883
 32884
 32885
 32886
 32887
 32888
 32889
 32890
 32891
 32892
 32893
 32894
 32895
 32896
 32897
 32898
 32899
 32900
 32901
 32902
 32903
 32904
 32905
 32906
 32907
 32908
 32909
 32910
 32911
 32912
 32913
 32914
 32915
 32916
 32917
 32918
 32919
 32920
 32921
 32922
 32923
 32924
 32925
 32926
 32927
 32928
 32929
 32930
 32931
 32932
 32933
 32934
 32935
 32936
 32937
 32938
 32939
 32940
 32941
 32942
 32943
 32944
 32945
 32946
 32947
 32948
 32949
 32950
 32951
 32952
 32953
 32954
 32955
 32956
 32957
 32958
 32959
 32960
 32961
 32962
 32963
 32964
 32965
 32966
 32967
 32968
 32969
 32970
 32971
 32972
 32973
 32974
 32975
 32976
 32977
 32978
 32979
 32980
 32981
 32982
 32983
 32984
 32985
 32986
 32987
 32988
 32989
 32990
 32991
 32992
 32993
 32994
 32995
 32996
 32997
 32998
 32999
 33000
 33001
 33002
 33003
 33004
 33005
 33006
 33007
 33008
 33009
 33010
 33011
 33012
 33013
 33014
 33015
 33016
 33017
 33018
 33019
 33020
 33021
 33022
 33023
 33024
 33025
 33026
 33027
 33028
 33029
 33030
 33031
 33032
 33033
 33034
 33035
 33036
 33037
 33038
 33039
 33040
 33041
 33042
 33043
 33044
 33045
 33046
 33047
 33048
 33049
 33050
 33051
 33052
 33053
 33054
 33055
 33056
 33057
 33058
 33059
 33060
 33061
 33062
 33063
 33064
 33065
 33066
 33067
 33068
 33069
 33070
 33071
 33072
 33073
 33074
 33075
 33076
 33077
 33078
 33079
 33080
 33081
 33082
 33083
 33084
 33085
 33086
 33087
 33088
 33089
 33090
 33091
 33092
 33093
 33094
 33095
 33096
 33097
 33098
 33099
 33100
 33101
 33102
 33103
 33104
 33105
 33106
 33107
 33108
 33109
 33110
 33111
 33112
 33113
 33114
 33115
 33116
 33117
 33118
 33119
 33120
 33121
 33122
 33123
 33124
 33125
 33126
 33127
 33128
 33129
 33130
 33131
 33132
 33133
 33134
 33135
 33136
 33137
 33138
 33139
 33140
 33141
 33142
 33143
 33144
 33145
 33146
 33147
 33148
 33149
 33150
 33151
 33152
 33153
 33154
 33155
 33156
 33157
 33158
 33159
 33160
 33161
 33162
 33163
 33164
 33165
 33166
 33167
 33168
 33169
 33170
 33171
 33172
 33173
 33174
 33175
 33176
 33177
 33178
 33179
 33180
 33181
 33182
 33183
 33184
 33185
 33186
 33187
 33188
 33189
 33190
 33191
 33192
 33193
 33194
 33195
 33196
 33197
 33198
 33199
 33200
 33201
 33202
 33203
 33204
 33205
 33206
 33207
 33208
 33209
 33210
 33211
 33212
 33213
 33214
 33215
 33216
 33217
 33218
 33219
 33220
 33221
 33222
 33223
 33224
 33225
 33226
 33227
 33228
 33229
 33230
 33231
 33232
 33233
 33234
 33235
 33236
 33237
 33238
 33239
 33240
 33241
 33242
 33243
 33244
 33245
 33246
 33247
 33248
 33249
 33250
 33251
 33252
 33253
 33254
 33255
 33256
 33257
 33258
 33259
 33260
 33261
 33262
 33263
 33264
 33265
 33266
 33267
 33268
 33269
 33270
 33271
 33272
 33273
 33274
 33275
 33276
 33277
 33278
 33279
 33280
 33281
 33282
 33283
 33284
 33285
 33286
 33287
 33288
 33289
 33290
 33291
 33292
 33293
 33294
 33295
 33296
 33297
 33298
 33299
 33300
 33301
 33302
 33303
 33304
 33305
 33306
 33307
 33308
 33309
 33310
 33311
 33312
 33313
 33314
 33315
 33316
 33317
 33318
 33319
 33320
 33321
 33322
 33323
 33324
 33325
 33326
 33327
 33328
 33329
 33330
 33331
 33332
 33333
 33334
 33335
 33336
 33337
 33338
 33339
 33340
 33341
 33342
 33343
 33344
 33345
 33346
 33347
 33348
 33349
 33350
 33351
 33352
 33353
 33354
 33355
 33356
 33357
 33358
 33359
 33360
 33361
 33362
 33363
 33364
 33365
 33366
 33367
 33368
 33369
 33370
 33371
 33372
 33373
 33374
 33375
 33376
 33377
 33378
 33379
 33380
 33381
 33382
 33383
 33384
 33385
 33386
 33387
 33388
 33389
 33390
 33391
 33392
 33393
 33394
 33395
 33396
 33397
 33398
 33399
 33400
 33401
 33402
 33403
 33404
 33405
 33406
 33407
 33408
 33409
 33410
 33411
 33412
 33413
 33414
 33415
 33416
 33417
 33418
 33419
 33420
 33421
 33422
 33423
 33424
 33425
 33426
 33427
 33428
 33429
 33430
 33431
 33432
 33433
 33434
 33435
 33436
 33437
 33438
 33439
 33440
 33441
 33442
 33443
 33444
 33445
 33446
 33447
 33448
 33449
 33450
 33451
 33452
 33453
 33454
 33455
 33456
 33457
 33458
 33459
 33460
 33461
 33462
 33463
 33464
 33465
 33466
 33467
 33468
 33469
 33470
 33471
 33472
 33473
 33474
 33475
 33476
 33477
 33478
 33479
 33480
 33481
 33482
 33483
 33484
 33485
 33486
 33487
 33488
 33489
 33490
 33491
 33492
 33493
 33494
 33495
 33496
 33497
 33498
 33499
 33500
 33501
 33502
 33503
 33504
 33505
 33506
 33507
 33508
 33509
 33510
 33511
 33512
 33513
 33514
 33515
 33516
 33517
 33518
 33519
 33520
 33521
 33522
 33523
 33524
 33525
 33526
 33527
 33528
 33529
 33530
 33531
 33532
 33533
 33534
 33535
 33536
 33537
 33538
 33539
 33540
 33541
 33542
 33543
 33544
 33545
 33546
 33547
 33548
 33549
 33550
 33551
 33552
 33553
 33554
 33555
 33556
 33557
 33558
 33559
 33560
 33561
 33562
 33563
 33564
 33565
 33566
 33567
 33568
 33569
 33570
 33571
 33572
 33573
 33574
 33575
 33576
 33577
 33578
 33579
 33580
 33581
 33582
 33583
 33584
 33585
 33586
 33587
 33588
 33589
 33590
 33591
 33592
 33593
 33594
 33595
 33596
 33597
 33598
 33599
 33600
 33601
 33602
 33603
 33604
 33605
 33606
 33607
 33608
 33609
 33610
 33611
 33612
 33613
 33614
 33615
 33616
 33617
 33618
 33619
 33620
 33621
 33622
 33623
 33624
 33625
 33626
 33627
 33628
 33629
 33630
 33631
 33632
 33633
 33634
 33635
 33636
 33637
 33638
 33639
 33640
 33641
 33642
 33643
 33644
 33645
 33646
 33647
 33648
 33649
 33650
 33651
 33652
 33653
 33654
 33655
 33656
 33657
 33658
 33659
 33660
 33661
 33662
 33663
 33664
 33665
 33666
 33667
 33668
 33669
 33670
 33671
 33672
 33673
 33674
 33675
 33676
 33677
 33678
 33679
 33680
 33681
 33682
 33683
 33684
 33685
 33686
 33687
 33688
 33689
 33690
 33691
 33692
 33693
 33694
 33695
 33696
 33697
 33698
 33699
 33700
 33701
 33702
 33703
 33704
 33705
 33706
 33707
 33708
 33709
 33710
 33711
 33712
 33713
 33714
 33715
 33716
 33717
 33718
 33719
 33720
 33721
 33722
 33723
 33724
 33725
 33726
 33727
 33728
 33729
 33730
 33731
 33732
 33733
 33734
 33735
 33736
 33737
 33738
 33739
 33740
 33741
 33742
 33743
 33744
 33745
 33746
 33747
 33748
 33749
 33750
 33751
 33752
 33753
 33754
 33755
 33756
 33757
 33758
 33759
 33760
 33761
 33762
 33763
 33764
 33765
 33766
 33767
 33768
 33769
 33770
 33771
 33772
 33773
 33774
 33775
 33776
 33777
 33778
 33779
 33780
 33781
 33782
 33783
 33784
 33785
 33786
 33787
 33788
 33789
 33790
 33791
 33792
 33793
 33794
 33795
 33796
 33797
 33798
 33799
 33800
 33801
 33802
 33803
 33804
 33805
 33806
 33807
 33808
 33809
 33810
 33811
 33812
 33813
 33814
 33815
 33816
 33817
 33818
 33819
 33820
 33821
 33822
 33823
 33824
 33825
 33826
 33827
 33828
 33829
 33830
 33831
 33832
 33833
 33834
 33835
 33836
 33837
 33838
 33839
 33840
 33841
 33842
 33843
 33844
 33845
 33846
 33847
 33848
 33849
 33850
 33851
 33852
 33853
 33854
 33855
 33856
 33857
 33858
 33859
 33860
 33861
 33862
 33863
 33864
 33865
 33866
 33867
 33868
 33869
 33870
 33871
 33872
 33873
 33874
 33875
 33876
 33877
 33878
 33879
 33880
 33881
 33882
 33883
 33884
 33885
 33886
 33887
 33888
 33889
 33890
 33891
 33892
 33893
 33894
 33895
 33896
 33897
 33898
 33899
 33900
 33901
 33902
 33903
 33904
 33905
 33906
 33907
 33908
 33909
 33910
 33911
 33912
 33913
 33914
 33915
 33916
 33917
 33918
 33919
 33920
 33921
 33922
 33923
 33924
 33925
 33926
 33927
 33928
 33929
 33930
 33931
 33932
 33933
 33934
 33935
 33936
 33937
 33938
 33939
 33940
 33941
 33942
 33943
 33944
 33945
 33946
 33947
 33948
 33949
 33950
 33951
 33952
 33953
 33954
 33955
 33956
 33957
 33958
 33959
 33960
 33961
 33962
 33963
 33964
 33965
 33966
 33967
 33968
 33969
 33970
 33971
 33972
 33973
 33974
 33975
 33976
 33977
 33978
 33979
 33980
 33981
 33982
 33983
 33984
 33985
 33986
 33987
 33988
 33989
 33990
 33991
 33992
 33993
 33994
 33995
 33996
 33997
 33998
 33999
 34000
 34001
 34002
 34003
 34004
 34005
 34006
 34007
 34008
 34009
 34010
 34011
 34012
 34013
 34014
 34015
 34016
 34017
 34018
 34019
 34020
 34021
 34022
 34023
 34024
 34025
 34026
 34027
 34028
 34029
 34030
 34031
 34032
 34033
 34034
 34035
 34036
 34037
 34038
 34039
 34040
 34041
 34042
 34043
 34044
 34045
 34046
 34047
 34048
 34049
 34050
 34051
 34052
 34053
 34054
 34055
 34056
 34057
 34058
 34059
 34060
 34061
 34062
 34063
 34064
 34065
 34066
 34067
 34068
 34069
 34070
 34071
 34072
 34073
 34074
 34075
 34076
 34077
 34078
 34079
 34080
 34081
 34082
 34083
 34084
 34085
 34086
 34087
 34088
 34089
 34090
 34091
 34092
 34093
 34094
 34095
 34096
 34097
 34098
 34099
 34100
 34101
 34102
 34103
 34104
 34105
 34106
 34107
 34108
 34109
 34110
 34111
 34112
 34113
 34114
 34115
 34116
 34117
 34118
 34119
 34120
 34121
 34122
 34123
 34124
 34125
 34126
 34127
 34128
 34129
 34130
 34131
 34132
 34133
 34134
 34135
 34136
 34137
 34138
 34139
 34140
 34141
 34142
 34143
 34144
 34145
 34146
 34147
 34148
 34149
 34150
 34151
 34152
 34153
 34154
 34155
 34156
 34157
 34158
 34159
 34160
 34161
 34162
 34163
 34164
 34165
 34166
 34167
 34168
 34169
 34170
 34171
 34172
 34173
 34174
 34175
 34176
 34177
 34178
 34179
 34180
 34181
 34182
 34183
 34184
 34185
 34186
 34187
 34188
 34189
 34190
 34191
 34192
 34193
 34194
 34195
 34196
 34197
 34198
 34199
 34200
 34201
 34202
 34203
 34204
 34205
 34206
 34207
 34208
 34209
 34210
 34211
 34212
 34213
 34214
 34215
 34216
 34217
 34218
 34219
 34220
 34221
 34222
 34223
 34224
 34225
 34226
 34227
 34228
 34229
 34230
 34231
 34232
 34233
 34234
 34235
 34236
 34237
 34238
 34239
 34240
 34241
 34242
 34243
 34244
 34245
 34246
 34247
 34248
 34249
 34250
 34251
 34252
 34253
 34254
 34255
 34256
 34257
 34258
 34259
 34260
 34261
 34262
 34263
 34264
 34265
 34266
 34267
 34268
 34269
 34270
 34271
 34272
 34273
 34274
 34275
 34276
 34277
 34278
 34279
 34280
 34281
 34282
 34283
 34284
 34285
 34286
 34287
 34288
 34289
 34290
 34291
 34292
 34293
 34294
 34295
 34296
 34297
 34298
 34299
 34300
 34301
 34302
 34303
 34304
 34305
 34306
 34307
 34308
 34309
 34310
 34311
 34312
 34313
 34314
 34315
 34316
 34317
 34318
 34319
 34320
 34321
 34322
 34323
 34324
 34325
 34326
 34327
 34328
 34329
 34330
 34331
 34332
 34333
 34334
 34335
 34336
 34337
 34338
 34339
 34340
 34341
 34342
 34343
 34344
 34345
 34346
 34347
 34348
 34349
 34350
 34351
 34352
 34353
 34354
 34355
 34356
 34357
 34358
 34359
 34360
 34361
 34362
 34363
 34364
 34365
 34366
 34367
 34368
 34369
 34370
 34371
 34372
 34373
 34374
 34375
 34376
 34377
 34378
 34379
 34380
 34381
 34382
 34383
 34384
 34385
 34386
 34387
 34388
 34389
 34390
 34391
 34392
 34393
 34394
 34395
 34396
 34397
 34398
 34399
 34400
 34401
 34402
 34403
 34404
 34405
 34406
 34407
 34408
 34409
 34410
 34411
 34412
 34413
 34414
 34415
 34416
 34417
 34418
 34419
 34420
 34421
 34422
 34423
 34424
 34425
 34426
 34427
 34428
 34429
 34430
 34431
 34432
 34433
 34434
 34435
 34436
 34437
 34438
 34439
 34440
 34441
 34442
 34443
 34444
 34445
 34446
 34447
 34448
 34449
 34450
 34451
 34452
 34453
 34454
 34455
 34456
 34457
 34458
 34459
 34460
 34461
 34462
 34463
 34464
 34465
 34466
 34467
 34468
 34469
 34470
 34471
 34472
 34473
 34474
 34475
 34476
 34477
 34478
 34479
 34480
 34481
 34482
 34483
 34484
 34485
 34486
 34487
 34488
 34489
 34490
 34491
 34492
 34493
 34494
 34495
 34496
 34497
 34498
 34499
 34500
 34501
 34502
 34503
 34504
 34505
 34506
 34507
 34508
 34509
 34510
 34511
 34512
 34513
 34514
 34515
 34516
 34517
 34518
 34519
 34520
 34521
 34522
 34523
 34524
 34525
 34526
 34527
 34528
 34529
 34530
 34531
 34532
 34533
 34534
 34535
 34536
 34537
 34538
 34539
 34540
 34541
 34542
 34543
 34544
 34545
 34546
 34547
 34548
 34549
 34550
 34551
 34552
 34553
 34554
 34555
 34556
 34557
 34558
 34559
 34560
 34561
 34562
 34563
 34564
 34565
 34566
 34567
 34568
 34569
 34570
 34571
 34572
 34573
 34574
 34575
 34576
 34577
 34578
 34579
 34580
 34581
 34582
 34583
 34584
 34585
 34586
 34587
 34588
 34589
 34590
 34591
 34592
 34593
 34594
 34595
 34596
 34597
 34598
 34599
 34600
 34601
 34602
 34603
 34604
 34605
 34606
 34607
 34608
 34609
 34610
 34611
 34612
 34613
 34614
 34615
 34616
 34617
 34618
 34619
 34620
 34621
 34622
 34623
 34624
 34625
 34626
 34627
 34628
 34629
 34630
 34631
 34632
 34633
 34634
 34635
 34636
 34637
 34638
 34639
 34640
 34641
 34642
 34643
 34644
 34645
 34646
 34647
 34648
 34649
 34650
 34651
 34652
 34653
 34654
 34655
 34656
 34657
 34658
 34659
 34660
 34661
 34662
 34663
 34664
 34665
 34666
 34667
 34668
 34669
 34670
 34671
 34672
 34673
 34674
 34675
 34676
 34677
 34678
 34679
 34680
 34681
 34682
 34683
 34684
 34685
 34686
 34687
 34688
 34689
 34690
 34691
 34692
 34693
 34694
 34695
 34696
 34697
 34698
 34699
 34700
 34701
 34702
 34703
 34704
 34705
 34706
 34707
 34708
 34709
 34710
 34711
 34712
 34713
 34714
 34715
 34716
 34717
 34718
 34719
 34720
 34721
 34722
 34723
 34724
 34725
 34726
 34727
 34728
 34729
 34730
 34731
 34732
 34733
 34734
 34735
 34736
 34737
 34738
 34739
 34740
 34741
 34742
 34743
 34744
 34745
 34746
 34747
 34748
 34749
 34750
 34751
 34752
 34753
 34754
 34755
 34756
 34757
 34758
 34759
 34760
 34761
 34762
 34763
 34764
 34765
 34766
 34767
 34768
 34769
 34770
 34771
 34772
 34773
 34774
 34775
 34776
 34777
 34778
 34779
 34780
 34781
 34782
 34783
 34784
 34785
 34786
 34787
 34788
 34789
 34790
 34791
 34792
 34793
 34794
 34795
 34796
 34797
 34798
 34799
 34800
 34801
 34802
 34803
 34804
 34805
 34806
 34807
 34808
 34809
 34810
 34811
 34812
 34813
 34814
 34815
 34816
 34817
 34818
 34819
 34820
 34821
 34822
 34823
 34824
 34825
 34826
 34827
 34828
 34829
 34830
 34831
 34832
 34833
 34834
 34835
 34836
 34837
 34838
 34839
 34840
 34841
 34842
 34843
 34844
 34845
 34846
 34847
 34848
 34849
 34850
 34851
 34852
 34853
 34854
 34855
 34856
 34857
 34858
 34859
 34860
 34861
 34862
 34863
 34864
 34865
 34866
 34867
 34868
 34869
 34870
 34871
 34872
 34873
 34874
 34875
 34876
 34877
 34878
 34879
 34880
 34881
 34882
 34883
 34884
 34885
 34886
 34887
 34888
 34889
 34890
 34891
 34892
 34893
 34894
 34895
 34896
 34897
 34898
 34899
 34900
 34901
 34902
 34903
 34904
 34905
 34906
 34907
 34908
 34909
 34910
 34911
 34912
 34913
 34914
 34915
 34916
 34917
 34918
 34919
 34920
 34921
 34922
 34923
 34924
 34925
 34926
 34927
 34928
 34929
 34930
 34931
 34932
 34933
 34934
 34935
 34936
 34937
 34938
 34939
 34940
 34941
 34942
 34943
 34944
 34945
 34946
 34947
 34948
 34949
 34950
 34951
 34952
 34953
 34954
 34955
 34956
 34957
 34958
 34959
 34960
 34961
 34962
 34963
 34964
 34965
 34966
 34967
 34968
 34969
 34970
 34971
 34972
 34973
 34974
 34975
 34976
 34977
 34978
 34979
 34980
 34981
 34982
 34983
 34984
 34985
 34986
 34987
 34988
 34989
 34990
 34991
 34992
 34993
 34994
 34995
 34996
 34997
 34998
 34999
 35000
 35001
 35002
 35003
 35004
 35005
 35006
 35007
 35008
 35009
 35010
 35011
 35012
 35013
 35014
 35015
 35016
 35017
 35018
 35019
 35020
 35021
 35022
 35023
 35024
 35025
 35026
 35027
 35028
 35029
 35030
 35031
 35032
 35033
 35034
 35035
 35036
 35037
 35038
 35039
 35040
 35041
 35042
 35043
 35044
 35045
 35046
 35047
 35048
 35049
 35050
 35051
 35052
 35053
 35054
 35055
 35056
 35057
 35058
 35059
 35060
 35061
 35062
 35063
 35064
 35065
 35066
 35067
 35068
 35069
 35070
 35071
 35072
 35073
 35074
 35075
 35076
 35077
 35078
 35079
 35080
 35081
 35082
 35083
 35084
 35085
 35086
 35087
 35088
 35089
 35090
 35091
 35092
 35093
 35094
 35095
 35096
 35097
 35098
 35099
 35100
 35101
 35102
 35103
 35104
 35105
 35106
 35107
 35108
 35109
 35110
 35111
 35112
 35113
 35114
 35115
 35116
 35117
 35118
 35119
 35120
 35121
 35122
 35123
 35124
 35125
 35126
 35127
 35128
 35129
 35130
 35131
 35132
 35133
 35134
 35135
 35136
 35137
 35138
 35139
 35140
 35141
 35142
 35143
 35144
 35145
 35146
 35147
 35148
 35149
 35150
 35151
 35152
 35153
 35154
 35155
 35156
 35157
 35158
 35159
 35160
 35161
 35162
 35163
 35164
 35165
 35166
 35167
 35168
 35169
 35170
 35171
 35172
 35173
 35174
 35175
 35176
 35177
 35178
 35179
 35180
 35181
 35182
 35183
 35184
 35185
 35186
 35187
 35188
 35189
 35190
 35191
 35192
 35193
 35194
 35195
 35196
 35197
 35198
 35199
 35200
 35201
 35202
 35203
 35204
 35205
 35206
 35207
 35208
 35209
 35210
 35211
 35212
 35213
 35214
 35215
 35216
 35217
 35218
 35219
 35220
 35221
 35222
 35223
 35224
 35225
 35226
 35227
 35228
 35229
 35230
 35231
 35232
 35233
 35234
 35235
 35236
 35237
 35238
 35239
 35240
 35241
 35242
 35243
 35244
 35245
 35246
 35247
 35248
 35249
 35250
 35251
 35252
 35253
 35254
 35255
 35256
 35257
 35258
 35259
 35260
 35261
 35262
 35263
 35264
 35265
 35266
 35267
 35268
 35269
 35270
 35271
 35272
 35273
 35274
 35275
 35276
 35277
 35278
 35279
 35280
 35281
 35282
 35283
 35284
 35285
 35286
 35287
 35288
 35289
 35290
 35291
 35292
 35293
 35294
 35295
 35296
 35297
 35298
 35299
 35300
 35301
 35302
 35303
 35304
 35305
 35306
 35307
 35308
 35309
 35310
 35311
 35312
 35313
 35314
 35315
 35316
 35317
 35318
 35319
 35320
 35321
 35322
 35323
 35324
 35325
 35326
 35327
 35328
 35329
 35330
 35331
 35332
 35333
 35334
 35335
 35336
 35337
 35338
 35339
 35340
 35341
 35342
 35343
 35344
 35345
 35346
 35347
 35348
 35349
 35350
 35351
 35352
 35353
 35354
 35355
 35356
 35357
 35358
 35359
 35360
 35361
 35362
 35363
 35364
 35365
 35366
 35367
 35368
 35369
 35370
 35371
 35372
 35373
 35374
 35375
 35376
 35377
 35378
 35379
 35380
 35381
 35382
 35383
 35384
 35385
 35386
 35387
 35388
 35389
 35390
 35391
 35392
 35393
 35394
 35395
 35396
 35397
 35398
 35399
 35400
 35401
 35402
 35403
 35404
 35405
 35406
 35407
 35408
 35409
 35410
 35411
 35412
 35413
 35414
 35415
 35416
 35417
 35418
 35419
 35420
 35421
 35422
 35423
 35424
 35425
 35426
 35427
 35428
 35429
 35430
 35431
 35432
 35433
 35434
 35435
 35436
 35437
 35438
 35439
 35440
 35441
 35442
 35443
 35444
 35445
 35446
 35447
 35448
 35449
 35450
 35451
 35452
 35453
 35454
 35455
 35456
 35457
 35458
 35459
 35460
 35461
 35462
 35463
 35464
 35465
 35466
 35467
 35468
 35469
 35470
 35471
 35472
 35473
 35474
 35475
 35476
 35477
 35478
 35479
 35480
 35481
 35482
 35483
 35484
 35485
 35486
 35487
 35488
 35489
 35490
 35491
 35492
 35493
 35494
 35495
 35496
 35497
 35498
 35499
 35500
 35501
 35502
 35503
 35504
 35505
 35506
 35507
 35508
 35509
 35510
 35511
 35512
 35513
 35514
 35515
 35516
 35517
 35518
 35519
 35520
 35521
 35522
 35523
 35524
 35525
 35526
 35527
 35528
 35529
 35530
 35531
 35532
 35533
 35534
 35535
 35536
 35537
 35538
 35539
 35540
 35541
 35542
 35543
 35544
 35545
 35546
 35547
 35548
 35549
 35550
 35551
 35552
 35553
 35554
 35555
 35556
 35557
 35558
 35559
 35560
 35561
 35562
 35563
 35564
 35565
 35566
 35567
 35568
 35569
 35570
 35571
 35572
 35573
 35574
 35575
 35576
 35577
 35578
 35579
 35580
 35581
 35582
 35583
 35584
 35585
 35586
 35587
 35588
 35589
 35590
 35591
 35592
 35593
 35594
 35595
 35596
 35597
 35598
 35599
 35600
 35601
 35602
 35603
 35604
 35605
 35606
 35607
 35608
 35609
 35610
 35611
 35612
 35613
 35614
 35615
 35616
 35617
 35618
 35619
 35620
 35621
 35622
 35623
 35624
 35625
 35626
 35627
 35628
 35629
 35630
 35631
 35632
 35633
 35634
 35635
 35636
 35637
 35638
 35639
 35640
 35641
 35642
 35643
 35644
 35645
 35646
 35647
 35648
 35649
 35650
 35651
 35652
 35653
 35654
 35655
 35656
 35657
 35658
 35659
 35660
 35661
 35662
 35663
 35664
 35665
 35666
 35667
 35668
 35669
 35670
 35671
 35672
 35673
 35674
 35675
 35676
 35677
 35678
 35679
 35680
 35681
 35682
 35683
 35684
 35685
 35686
 35687
 35688
 35689
 35690
 35691
 35692
 35693
 35694
 35695
 35696
 35697
 35698
 35699
 35700
 35701
 35702
 35703
 35704
 35705
 35706
 35707
 35708
 35709
 35710
 35711
 35712
 35713
 35714
 35715
 35716
 35717
 35718
 35719
 35720
 35721
 35722
 35723
 35724
 35725
 35726
 35727
 35728
 35729
 35730
 35731
 35732
 35733
 35734
 35735
 35736
 35737
 35738
 35739
 35740
 35741
 35742
 35743
 35744
 35745
 35746
 35747
 35748
 35749
 35750
 35751
 35752
 35753
 35754
 35755
 35756
 35757
 35758
 35759
 35760
 35761
 35762
 35763
 35764
 35765
 35766
 35767
 35768
 35769
 35770
 35771
 35772
 35773
 35774
 35775
 35776
 35777
 35778
 35779
 35780
 35781
 35782
 35783
 35784
 35785
 35786
 35787
 35788
 35789
 35790
 35791
 35792
 35793
 35794
 35795
 35796
 35797
 35798
 35799
 35800
 35801
 35802
 35803
 35804
 35805
 35806
 35807
 35808
 35809
 35810
 35811
 35812
 35813
 35814
 35815
 35816
 35817
 35818
 35819
 35820
 35821
 35822
 35823
 35824
 35825
 35826
 35827
 35828
 35829
 35830
 35831
 35832
 35833
 35834
 35835
 35836
 35837
 35838
 35839
 35840
 35841
 35842
 35843
 35844
 35845
 35846
 35847
 35848
 35849
 35850
 35851
 35852
 35853
 35854
 35855
 35856
 35857
 35858
 35859
 35860
 35861
 35862
 35863
 35864
 35865
 35866
 35867
 35868
 35869
 35870
 35871
 35872
 35873
 35874
 35875
 35876
 35877
 35878
 35879
 35880
 35881
 35882
 35883
 35884
 35885
 35886
 35887
 35888
 35889
 35890
 35891
 35892
 35893
 35894
 35895
 35896
 35897
 35898
 35899
 35900
 35901
 35902
 35903
 35904
 35905
 35906
 35907
 35908
 35909
 35910
 35911
 35912
 35913
 35914
 35915
 35916
 35917
 35918
 35919
 35920
 35921
 35922
 35923
 35924
 35925
 35926
 35927
 35928
 35929
 35930
 35931
 35932
 35933
 35934
 35935
 35936
 35937
 35938
 35939
 35940
 35941
 35942
 35943
 35944
 35945
 35946
 35947
 35948
 35949
 35950
 35951
 35952
 35953
 35954
 35955
 35956
 35957
 35958
 35959
 35960
 35961
 35962
 35963
 35964
 35965
 35966
 35967
 35968
 35969
 35970
 35971
 35972
 35973
 35974
 35975
 35976
 35977
 35978
 35979
 35980
 35981
 35982
 35983
 35984
 35985
 35986
 35987
 35988
 35989
 35990
 35991
 35992
 35993
 35994
 35995
 35996
 35997
 35998
 35999
 36000
 36001
 36002
 36003
 36004
 36005
 36006
 36007
 36008
 36009
 36010
 36011
 36012
 36013
 36014
 36015
 36016
 36017
 36018
 36019
 36020
 36021
 36022
 36023
 36024
 36025
 36026
 36027
 36028
 36029
 36030
 36031
 36032
 36033
 36034
 36035
 36036
 36037
 36038
 36039
 36040
 36041
 36042
 36043
 36044
 36045
 36046
 36047
 36048
 36049
 36050
 36051
 36052
 36053
 36054
 36055
 36056
 36057
 36058
 36059
 36060
 36061
 36062
 36063
 36064
 36065
 36066
 36067
 36068
 36069
 36070
 36071
 36072
 36073
 36074
 36075
 36076
 36077
 36078
 36079
 36080
 36081
 36082
 36083
 36084
 36085
 36086
 36087
 36088
 36089
 36090
 36091
 36092
 36093
 36094
 36095
 36096
 36097
 36098
 36099
 36100
 36101
 36102
 36103
 36104
 36105
 36106
 36107
 36108
 36109
 36110
 36111
 36112
 36113
 36114
 36115
 36116
 36117
 36118
 36119
 36120
 36121
 36122
 36123
 36124
 36125
 36126
 36127
 36128
 36129
 36130
 36131
 36132
 36133
 36134
 36135
 36136
 36137
 36138
 36139
 36140
 36141
 36142
 36143
 36144
 36145
 36146
 36147
 36148
 36149
 36150
 36151
 36152
 36153
 36154
 36155
 36156
 36157
 36158
 36159
 36160
 36161
 36162
 36163
 36164
 36165
 36166
 36167
 36168
 36169
 36170
 36171
 36172
 36173
 36174
 36175
 36176
 36177
 36178
 36179
 36180
 36181
 36182
 36183
 36184
 36185
 36186
 36187
 36188
 36189
 36190
 36191
 36192
 36193
 36194
 36195
 36196
 36197
 36198
 36199
 36200
 36201
 36202
 36203
 36204
 36205
 36206
 36207
 36208
 36209
 36210
 36211
 36212
 36213
 36214
 36215
 36216
 36217
 36218
 36219
 36220
 36221
 36222
 36223
 36224
 36225
 36226
 36227
 36228
 36229
 36230
 36231
 36232
 36233
 36234
 36235
 36236
 36237
 36238
 36239
 36240
 36241
 36242
 36243
 36244
 36245
 36246
 36247
 36248
 36249
 36250
 36251
 36252
 36253
 36254
 36255
 36256
 36257
 36258
 36259
 36260
 36261
 36262
 36263
 36264
 36265
 36266
 36267
 36268
 36269
 36270
 36271
 36272
 36273
 36274
 36275
 36276
 36277
 36278
 36279
 36280
 36281
 36282
 36283
 36284
 36285
 36286
 36287
 36288
 36289
 36290
 36291
 36292
 36293
 36294
 36295
 36296
 36297
 36298
 36299
 36300
 36301
 36302
 36303
 36304
 36305
 36306
 36307
 36308
 36309
 36310
 36311
 36312
 36313
 36314
 36315
 36316
 36317
 36318
 36319
 36320
 36321
 36322
 36323
 36324
 36325
 36326
 36327
 36328
 36329
 36330
 36331
 36332
 36333
 36334
 36335
 36336
 36337
 36338
 36339
 36340
 36341
 36342
 36343
 36344
 36345
 36346
 36347
 36348
 36349
 36350
 36351
 36352
 36353
 36354
 36355
 36356
 36357
 36358
 36359
 36360
 36361
 36362
 36363
 36364
 36365
 36366
 36367
 36368
 36369
 36370
 36371
 36372
 36373
 36374
 36375
 36376
 36377
 36378
 36379
 36380
 36381
 36382
 36383
 36384
 36385
 36386
 36387
 36388
 36389
 36390
 36391
 36392
 36393
 36394
 36395
 36396
 36397
 36398
 36399
 36400
 36401
 36402
 36403
 36404
 36405
 36406
 36407
 36408
 36409
 36410
 36411
 36412
 36413
 36414
 36415
 36416
 36417
 36418
 36419
 36420
 36421
 36422
 36423
 36424
 36425
 36426
 36427
 36428
 36429
 36430
 36431
 36432
 36433
 36434
 36435
 36436
 36437
 36438
 36439
 36440
 36441
 36442
 36443
 36444
 36445
 36446
 36447
 36448
 36449
 36450
 36451
 36452
 36453
 36454
 36455
 36456
 36457
 36458
 36459
 36460
 36461
 36462
 36463
 36464
 36465
 36466
 36467
 36468
 36469
 36470
 36471
 36472
 36473
 36474
 36475
 36476
 36477
 36478
 36479
 36480
 36481
 36482
 36483
 36484
 36485
 36486
 36487
 36488
 36489
 36490
 36491
 36492
 36493
 36494
 36495
 36496
 36497
 36498
 36499
 36500
 36501
 36502
 36503
 36504
 36505
 36506
 36507
 36508
 36509
 36510
 36511
 36512
 36513
 36514
 36515
 36516
 36517
 36518
 36519
 36520
 36521
 36522
 36523
 36524
 36525
 36526
 36527
 36528
 36529
 36530
 36531
 36532
 36533
 36534
 36535
 36536
 36537
 36538
 36539
 36540
 36541
 36542
 36543
 36544
 36545
 36546
 36547
 36548
 36549
 36550
 36551
 36552
 36553
 36554
 36555
 36556
 36557
 36558
 36559
 36560
 36561
 36562
 36563
 36564
 36565
 36566
 36567
 36568
 36569
 36570
 36571
 36572
 36573
 36574
 36575
 36576
 36577
 36578
 36579
 36580
 36581
 36582
 36583
 36584
 36585
 36586
 36587
 36588
 36589
 36590
 36591
 36592
 36593
 36594
 36595
 36596
 36597
 36598
 36599
 36600
 36601
 36602
 36603
 36604
 36605
 36606
 36607
 36608
 36609
 36610
 36611
 36612
 36613
 36614
 36615
 36616
 36617
 36618
 36619
 36620
 36621
 36622
 36623
 36624
 36625
 36626
 36627
 36628
 36629
 36630
 36631
 36632
 36633
 36634
 36635
 36636
 36637
 36638
 36639
 36640
 36641
 36642
 36643
 36644
 36645
 36646
 36647
 36648
 36649
 36650
 36651
 36652
 36653
 36654
 36655
 36656
 36657
 36658
 36659
 36660
 36661
 36662
 36663
 36664
 36665
 36666
 36667
 36668
 36669
 36670
 36671
 36672
 36673
 36674
 36675
 36676
 36677
 36678
 36679
 36680
 36681
 36682
 36683
 36684
 36685
 36686
 36687
 36688
 36689
 36690
 36691
 36692
 36693
 36694
 36695
 36696
 36697
 36698
 36699
 36700
 36701
 36702
 36703
 36704
 36705
 36706
 36707
 36708
 36709
 36710
 36711
 36712
 36713
 36714
 36715
 36716
 36717
 36718
 36719
 36720
 36721
 36722
 36723
 36724
 36725
 36726
 36727
 36728
 36729
 36730
 36731
 36732
 36733
 36734
 36735
 36736
 36737
 36738
 36739
 36740
 36741
 36742
 36743
 36744
 36745
 36746
 36747
 36748
 36749
 36750
 36751
 36752
 36753
 36754
 36755
 36756
 36757
 36758
 36759
 36760
 36761
 36762
 36763
 36764
 36765
 36766
 36767
 36768
 36769
 36770
 36771
 36772
 36773
 36774
 36775
 36776
 36777
 36778
 36779
 36780
 36781
 36782
 36783
 36784
 36785
 36786
 36787
 36788
 36789
 36790
 36791
 36792
 36793
 36794
 36795
 36796
 36797
 36798
 36799
 36800
 36801
 36802
 36803
 36804
 36805
 36806
 36807
 36808
 36809
 36810
 36811
 36812
 36813
 36814
 36815
 36816
 36817
 36818
 36819
 36820
 36821
 36822
 36823
 36824
 36825
 36826
 36827
 36828
 36829
 36830
 36831
 36832
 36833
 36834
 36835
 36836
 36837
 36838
 36839
 36840
 36841
 36842
 36843
 36844
 36845
 36846
 36847
 36848
 36849
 36850
 36851
 36852
 36853
 36854
 36855
 36856
 36857
 36858
 36859
 36860
 36861
 36862
 36863
 36864
 36865
 36866
 36867
 36868
 36869
 36870
 36871
 36872
 36873
 36874
 36875
 36876
 36877
 36878
 36879
 36880
 36881
 36882
 36883
 36884
 36885
 36886
 36887
 36888
 36889
 36890
 36891
 36892
 36893
 36894
 36895
 36896
 36897
 36898
 36899
 36900
 36901
 36902
 36903
 36904
 36905
 36906
 36907
 36908
 36909
 36910
 36911
 36912
 36913
 36914
 36915
 36916
 36917
 36918
 36919
 36920
 36921
 36922
 36923
 36924
 36925
 36926
 36927
 36928
 36929
 36930
 36931
 36932
 36933
 36934
 36935
 36936
 36937
 36938
 36939
 36940
 36941
 36942
 36943
 36944
 36945
 36946
 36947
 36948
 36949
 36950
 36951
 36952
 36953
 36954
 36955
 36956
 36957
 36958
 36959
 36960
 36961
 36962
 36963
 36964
 36965
 36966
 36967
 36968
 36969
 36970
 36971
 36972
 36973
 36974
 36975
 36976
 36977
 36978
 36979
 36980
 36981
 36982
 36983
 36984
 36985
 36986
 36987
 36988
 36989
 36990
 36991
 36992
 36993
 36994
 36995
 36996
 36997
 36998
 36999
 37000
 37001
 37002
 37003
 37004
 37005
 37006
 37007
 37008
 37009
 37010
 37011
 37012
 37013
 37014
 37015
 37016
 37017
 37018
 37019
 37020
 37021
 37022
 37023
 37024
 37025
 37026
 37027
 37028
 37029
 37030
 37031
 37032
 37033
 37034
 37035
 37036
 37037
 37038
 37039
 37040
 37041
 37042
 37043
 37044
 37045
 37046
 37047
 37048
 37049
 37050
 37051
 37052
 37053
 37054
 37055
 37056
 37057
 37058
 37059
 37060
 37061
 37062
 37063
 37064
 37065
 37066
 37067
 37068
 37069
 37070
 37071
 37072
 37073
 37074
 37075
 37076
 37077
 37078
 37079
 37080
 37081
 37082
 37083
 37084
 37085
 37086
 37087
 37088
 37089
 37090
 37091
 37092
 37093
 37094
 37095
 37096
 37097
 37098
 37099
 37100
 37101
 37102
 37103
 37104
 37105
 37106
 37107
 37108
 37109
 37110
 37111
 37112
 37113
 37114
 37115
 37116
 37117
 37118
 37119
 37120
 37121
 37122
 37123
 37124
 37125
 37126
 37127
 37128
 37129
 37130
 37131
 37132
 37133
 37134
 37135
 37136
 37137
 37138
 37139
 37140
 37141
 37142
 37143
 37144
 37145
 37146
 37147
 37148
 37149
 37150
 37151
 37152
 37153
 37154
 37155
 37156
 37157
 37158
 37159
 37160
 37161
 37162
 37163
 37164
 37165
 37166
 37167
 37168
 37169
 37170
 37171
 37172
 37173
 37174
 37175
 37176
 37177
 37178
 37179
 37180
 37181
 37182
 37183
 37184
 37185
 37186
 37187
 37188
 37189
 37190
 37191
 37192
 37193
 37194
 37195
 37196
 37197
 37198
 37199
 37200
 37201
 37202
 37203
 37204
 37205
 37206
 37207
 37208
 37209
 37210
 37211
 37212
 37213
 37214
 37215
 37216
 37217
 37218
 37219
 37220
 37221
 37222
 37223
 37224
 37225
 37226
 37227
 37228
 37229
 37230
 37231
 37232
 37233
 37234
 37235
 37236
 37237
 37238
 37239
 37240
 37241
 37242
 37243
 37244
 37245
 37246
 37247
 37248
 37249
 37250
 37251
 37252
 37253
 37254
 37255
 37256
 37257
 37258
 37259
 37260
 37261
 37262
 37263
 37264
 37265
 37266
 37267
 37268
 37269
 37270
 37271
 37272
 37273
 37274
 37275
 37276
 37277
 37278
 37279
 37280
 37281
 37282
 37283
 37284
 37285
 37286
 37287
 37288
 37289
 37290
 37291
 37292
 37293
 37294
 37295
 37296
 37297
 37298
 37299
 37300
 37301
 37302
 37303
 37304
 37305
 37306
 37307
 37308
 37309
 37310
 37311
 37312
 37313
 37314
 37315
 37316
 37317
 37318
 37319
 37320
 37321
 37322
 37323
 37324
 37325
 37326
 37327
 37328
 37329
 37330
 37331
 37332
 37333
 37334
 37335
 37336
 37337
 37338
 37339
 37340
 37341
 37342
 37343
 37344
 37345
 37346
 37347
 37348
 37349
 37350
 37351
 37352
 37353
 37354
 37355
 37356
 37357
 37358
 37359
 37360
 37361
 37362
 37363
 37364
 37365
 37366
 37367
 37368
 37369
 37370
 37371
 37372
 37373
 37374
 37375
 37376
 37377
 37378
 37379
 37380
 37381
 37382
 37383
 37384
 37385
 37386
 37387
 37388
 37389
 37390
 37391
 37392
 37393
 37394
 37395
 37396
 37397
 37398
 37399
 37400
 37401
 37402
 37403
 37404
 37405
 37406
 37407
 37408
 37409
 37410
 37411
 37412
 37413
 37414
 37415
 37416
 37417
 37418
 37419
 37420
 37421
 37422
 37423
 37424
 37425
 37426
 37427
 37428
 37429
 37430
 37431
 37432
 37433
 37434
 37435
 37436
 37437
 37438
 37439
 37440
 37441
 37442
 37443
 37444
 37445
 37446
 37447
 37448
 37449
 37450
 37451
 37452
 37453
 37454
 37455
 37456
 37457
 37458
 37459
 37460
 37461
 37462
 37463
 37464
 37465
 37466
 37467
 37468
 37469
 37470
 37471
 37472
 37473
 37474
 37475
 37476
 37477
 37478
 37479
 37480
 37481
 37482
 37483
 37484
 37485
 37486
 37487
 37488
 37489
 37490
 37491
 37492
 37493
 37494
 37495
 37496
 37497
 37498
 37499
 37500
 37501
 37502
 37503
 37504
 37505
 37506
 37507
 37508
 37509
 37510
 37511
 37512
 37513
 37514
 37515
 37516
 37517
 37518
 37519
 37520
 37521
 37522
 37523
 37524
 37525
 37526
 37527
 37528
 37529
 37530
 37531
 37532
 37533
 37534
 37535
 37536
 37537
 37538
 37539
 37540
 37541
 37542
 37543
 37544
 37545
 37546
 37547
 37548
 37549
 37550
 37551
 37552
 37553
 37554
 37555
 37556
 37557
 37558
 37559
 37560
 37561
 37562
 37563
 37564
 37565
 37566
 37567
 37568
 37569
 37570
 37571
 37572
 37573
 37574
 37575
 37576
 37577
 37578
 37579
 37580
 37581
 37582
 37583
 37584
 37585
 37586
 37587
 37588
 37589
 37590
 37591
 37592
 37593
 37594
 37595
 37596
 37597
 37598
 37599
 37600
 37601
 37602
 37603
 37604
 37605
 37606
 37607
 37608
 37609
 37610
 37611
 37612
 37613
 37614
 37615
 37616
 37617
 37618
 37619
 37620
 37621
 37622
 37623
 37624
 37625
 37626
 37627
 37628
 37629
 37630
 37631
 37632
 37633
 37634
 37635
 37636
 37637
 37638
 37639
 37640
 37641
 37642
 37643
 37644
 37645
 37646
 37647
 37648
 37649
 37650
 37651
 37652
 37653
 37654
 37655
 37656
 37657
 37658
 37659
 37660
 37661
 37662
 37663
 37664
 37665
 37666
 37667
 37668
 37669
 37670
 37671
 37672
 37673
 37674
 37675
 37676
 37677
 37678
 37679
 37680
 37681
 37682
 37683
 37684
 37685
 37686
 37687
 37688
 37689
 37690
 37691
 37692
 37693
 37694
 37695
 37696
 37697
 37698
 37699
 37700
 37701
 37702
 37703
 37704
 37705
 37706
 37707
 37708
 37709
 37710
 37711
 37712
 37713
 37714
 37715
 37716
 37717
 37718
 37719
 37720
 37721
 37722
 37723
 37724
 37725
 37726
 37727
 37728
 37729
 37730
 37731
 37732
 37733
 37734
 37735
 37736
 37737
 37738
 37739
 37740
 37741
 37742
 37743
 37744
 37745
 37746
 37747
 37748
 37749
 37750
 37751
 37752
 37753
 37754
 37755
 37756
 37757
 37758
 37759
 37760
 37761
 37762
 37763
 37764
 37765
 37766
 37767
 37768
 37769
 37770
 37771
 37772
 37773
 37774
 37775
 37776
 37777
 37778
 37779
 37780
 37781
 37782
 37783
 37784
 37785
 37786
 37787
 37788
 37789
 37790
 37791
 37792
 37793
 37794
 37795
 37796
 37797
 37798
 37799
 37800
 37801
 37802
 37803
 37804
 37805
 37806
 37807
 37808
 37809
 37810
 37811
 37812
 37813
 37814
 37815
 37816
 37817
 37818
 37819
 37820
 37821
 37822
 37823
 37824
 37825
 37826
 37827
 37828
 37829
 37830
 37831
 37832
 37833
 37834
 37835
 37836
 37837
 37838
 37839
 37840
 37841
 37842
 37843
 37844
 37845
 37846
 37847
 37848
 37849
 37850
 37851
 37852
 37853
 37854
 37855
 37856
 37857
 37858
 37859
 37860
 37861
 37862
 37863
 37864
 37865
 37866
 37867
 37868
 37869
 37870
 37871
 37872
 37873
 37874
 37875
 37876
 37877
 37878
 37879
 37880
 37881
 37882
 37883
 37884
 37885
 37886
 37887
 37888
 37889
 37890
 37891
 37892
 37893
 37894
 37895
 37896
 37897
 37898
 37899
 37900
 37901
 37902
 37903
 37904
 37905
 37906
 37907
 37908
 37909
 37910
 37911
 37912
 37913
 37914
 37915
 37916
 37917
 37918
 37919
 37920
 37921
 37922
 37923
 37924
 37925
 37926
 37927
 37928
 37929
 37930
 37931
 37932
 37933
 37934
 37935
 37936
 37937
 37938
 37939
 37940
 37941
 37942
 37943
 37944
 37945
 37946
 37947
 37948
 37949
 37950
 37951
 37952
 37953
 37954
 37955
 37956
 37957
 37958
 37959
 37960
 37961
 37962
 37963
 37964
 37965
 37966
 37967
 37968
 37969
 37970
 37971
 37972
 37973
 37974
 37975
 37976
 37977
 37978
 37979
 37980
 37981
 37982
 37983
 37984
 37985
 37986
 37987
 37988
 37989
 37990
 37991
 37992
 37993
 37994
 37995
 37996
 37997
 37998
 37999
 38000
 38001
 38002
 38003
 38004
 38005
 38006
 38007
 38008
 38009
 38010
 38011
 38012
 38013
 38014
 38015
 38016
 38017
 38018
 38019
 38020
 38021
 38022
 38023
 38024
 38025
 38026
 38027
 38028
 38029
 38030
 38031
 38032
 38033
 38034
 38035
 38036
 38037
 38038
 38039
 38040
 38041
 38042
 38043
 38044
 38045
 38046
 38047
 38048
 38049
 38050
 38051
 38052
 38053
 38054
 38055
 38056
 38057
 38058
 38059
 38060
 38061
 38062
 38063
 38064
 38065
 38066
 38067
 38068
 38069
 38070
 38071
 38072
 38073
 38074
 38075
 38076
 38077
 38078
 38079
 38080
 38081
 38082
 38083
 38084
 38085
 38086
 38087
 38088
 38089
 38090
 38091
 38092
 38093
 38094
 38095
 38096
 38097
 38098
 38099
 38100
 38101
 38102
 38103
 38104
 38105
 38106
 38107
 38108
 38109
 38110
 38111
 38112
 38113
 38114
 38115
 38116
 38117
 38118
 38119
 38120
 38121
 38122
 38123
 38124
 38125
 38126
 38127
 38128
 38129
 38130
 38131
 38132
 38133
 38134
 38135
 38136
 38137
 38138
 38139
 38140
 38141
 38142
 38143
 38144
 38145
 38146
 38147
 38148
 38149
 38150
 38151
 38152
 38153
 38154
 38155
 38156
 38157
 38158
 38159
 38160
 38161
 38162
 38163
 38164
 38165
 38166
 38167
 38168
 38169
 38170
 38171
 38172
 38173
 38174
 38175
 38176
 38177
 38178
 38179
 38180
 38181
 38182
 38183
 38184
 38185
 38186
 38187
 38188
 38189
 38190
 38191
 38192
 38193
 38194
 38195
 38196
 38197
 38198
 38199
 38200
 38201
 38202
 38203
 38204
 38205
 38206
 38207
 38208
 38209
 38210
 38211
 38212
 38213
 38214
 38215
 38216
 38217
 38218
 38219
 38220
 38221
 38222
 38223
 38224
 38225
 38226
 38227
 38228
 38229
 38230
 38231
 38232
 38233
 38234
 38235
 38236
 38237
 38238
 38239
 38240
 38241
 38242
 38243
 38244
 38245
 38246
 38247
 38248
 38249
 38250
 38251
 38252
 38253
 38254
 38255
 38256
 38257
 38258
 38259
 38260
 38261
 38262
 38263
 38264
 38265
 38266
 38267
 38268
 38269
 38270
 38271
 38272
 38273
 38274
 38275
 38276
 38277
 38278
 38279
 38280
 38281
 38282
 38283
 38284
 38285
 38286
 38287
 38288
 38289
 38290
 38291
 38292
 38293
 38294
 38295
 38296
 38297
 38298
 38299
 38300
 38301
 38302
 38303
 38304
 38305
 38306
 38307
 38308
 38309
 38310
 38311
 38312
 38313
 38314
 38315
 38316
 38317
 38318
 38319
 38320
 38321
 38322
 38323
 38324
 38325
 38326
 38327
 38328
 38329
 38330
 38331
 38332
 38333
 38334
 38335
 38336
 38337
 38338
 38339
 38340
 38341
 38342
 38343
 38344
 38345
 38346
 38347
 38348
 38349
 38350
 38351
 38352
 38353
 38354
 38355
 38356
 38357
 38358
 38359
 38360
 38361
 38362
 38363
 38364
 38365
 38366
 38367
 38368
 38369
 38370
 38371
 38372
 38373
 38374
 38375
 38376
 38377
 38378
 38379
 38380
 38381
 38382
 38383
 38384
 38385
 38386
 38387
 38388
 38389
 38390
 38391
 38392
 38393
 38394
 38395
 38396
 38397
 38398
 38399
 38400
 38401
 38402
 38403
 38404
 38405
 38406
 38407
 38408
 38409
 38410
 38411
 38412
 38413
 38414
 38415
 38416
 38417
 38418
 38419
 38420
 38421
 38422
 38423
 38424
 38425
 38426
 38427
 38428
 38429
 38430
 38431
 38432
 38433
 38434
 38435
 38436
 38437
 38438
 38439
 38440
 38441
 38442
 38443
 38444
 38445
 38446
 38447
 38448
 38449
 38450
 38451
 38452
 38453
 38454
 38455
 38456
 38457
 38458
 38459
 38460
 38461
 38462
 38463
 38464
 38465
 38466
 38467
 38468
 38469
 38470
 38471
 38472
 38473
 38474
 38475
 38476
 38477
 38478
 38479
 38480
 38481
 38482
 38483
 38484
 38485
 38486
 38487
 38488
 38489
 38490
 38491
 38492
 38493
 38494
 38495
 38496
 38497
 38498
 38499
 38500
 38501
 38502
 38503
 38504
 38505
 38506
 38507
 38508
 38509
 38510
 38511
 38512
 38513
 38514
 38515
 38516
 38517
 38518
 38519
 38520
 38521
 38522
 38523
 38524
 38525
 38526
 38527
 38528
 38529
 38530
 38531
 38532
 38533
 38534
 38535
 38536
 38537
 38538
 38539
 38540
 38541
 38542
 38543
 38544
 38545
 38546
 38547
 38548
 38549
 38550
 38551
 38552
 38553
 38554
 38555
 38556
 38557
 38558
 38559
 38560
 38561
 38562
 38563
 38564
 38565
 38566
 38567
 38568
 38569
 38570
 38571
 38572
 38573
 38574
 38575
 38576
 38577
 38578
 38579
 38580
 38581
 38582
 38583
 38584
 38585
 38586
 38587
 38588
 38589
 38590
 38591
 38592
 38593
 38594
 38595
 38596
 38597
 38598
 38599
 38600
 38601
 38602
 38603
 38604
 38605
 38606
 38607
 38608
 38609
 38610
 38611
 38612
 38613
 38614
 38615
 38616
 38617
 38618
 38619
 38620
 38621
 38622
 38623
 38624
 38625
 38626
 38627
 38628
 38629
 38630
 38631
 38632
 38633
 38634
 38635
 38636
 38637
 38638
 38639
 38640
 38641
 38642
 38643
 38644
 38645
 38646
 38647
 38648
 38649
 38650
 38651
 38652
 38653
 38654
 38655
 38656
 38657
 38658
 38659
 38660
 38661
 38662
 38663
 38664
 38665
 38666
 38667
 38668
 38669
 38670
 38671
 38672
 38673
 38674
 38675
 38676
 38677
 38678
 38679
 38680
 38681
 38682
 38683
 38684
 38685
 38686
 38687
 38688
 38689
 38690
 38691
 38692
 38693
 38694
 38695
 38696
 38697
 38698
 38699
 38700
 38701
 38702
 38703
 38704
 38705
 38706
 38707
 38708
 38709
 38710
 38711
 38712
 38713
 38714
 38715
 38716
 38717
 38718
 38719
 38720
 38721
 38722
 38723
 38724
 38725
 38726
 38727
 38728
 38729
 38730
 38731
 38732
 38733
 38734
 38735
 38736
 38737
 38738
 38739
 38740
 38741
 38742
 38743
 38744
 38745
 38746
 38747
 38748
 38749
 38750
 38751
 38752
 38753
 38754
 38755
 38756
 38757
 38758
 38759
 38760
 38761
 38762
 38763
 38764
 38765
 38766
 38767
 38768
 38769
 38770
 38771
 38772
 38773
 38774
 38775
 38776
 38777
 38778
 38779
 38780
 38781
 38782
 38783
 38784
 38785
 38786
 38787
 38788
 38789
 38790
 38791
 38792
 38793
 38794
 38795
 38796
 38797
 38798
 38799
 38800
 38801
 38802
 38803
 38804
 38805
 38806
 38807
 38808
 38809
 38810
 38811
 38812
 38813
 38814
 38815
 38816
 38817
 38818
 38819
 38820
 38821
 38822
 38823
 38824
 38825
 38826
 38827
 38828
 38829
 38830
 38831
 38832
 38833
 38834
 38835
 38836
 38837
 38838
 38839
 38840
 38841
 38842
 38843
 38844
 38845
 38846
 38847
 38848
 38849
 38850
 38851
 38852
 38853
 38854
 38855
 38856
 38857
 38858
 38859
 38860
 38861
 38862
 38863
 38864
 38865
 38866
 38867
 38868
 38869
 38870
 38871
 38872
 38873
 38874
 38875
 38876
 38877
 38878
 38879
 38880
 38881
 38882
 38883
 38884
 38885
 38886
 38887
 38888
 38889
 38890
 38891
 38892
 38893
 38894
 38895
 38896
 38897
 38898
 38899
 38900
 38901
 38902
 38903
 38904
 38905
 38906
 38907
 38908
 38909
 38910
 38911
 38912
 38913
 38914
 38915
 38916
 38917
 38918
 38919
 38920
 38921
 38922
 38923
 38924
 38925
 38926
 38927
 38928
 38929
 38930
 38931
 38932
 38933
 38934
 38935
 38936
 38937
 38938
 38939
 38940
 38941
 38942
 38943
 38944
 38945
 38946
 38947
 38948
 38949
 38950
 38951
 38952
 38953
 38954
 38955
 38956
 38957
 38958
 38959
 38960
 38961
 38962
 38963
 38964
 38965
 38966
 38967
 38968
 38969
 38970
 38971
 38972
 38973
 38974
 38975
 38976
 38977
 38978
 38979
 38980
 38981
 38982
 38983
 38984
 38985
 38986
 38987
 38988
 38989
 38990
 38991
 38992
 38993
 38994
 38995
 38996
 38997
 38998
 38999
 39000
 39001
 39002
 39003
 39004
 39005
 39006
 39007
 39008
 39009
 39010
 39011
 39012
 39013
 39014
 39015
 39016
 39017
 39018
 39019
 39020
 39021
 39022
 39023
 39024
 39025
 39026
 39027
 39028
 39029
 39030
 39031
 39032
 39033
 39034
 39035
 39036
 39037
 39038
 39039
 39040
 39041
 39042
 39043
 39044
 39045
 39046
 39047
 39048
 39049
 39050
 39051
 39052
 39053
 39054
 39055
 39056
 39057
 39058
 39059
 39060
 39061
 39062
 39063
 39064
 39065
 39066
 39067
 39068
 39069
 39070
 39071
 39072
 39073
 39074
 39075
 39076
 39077
 39078
 39079
 39080
 39081
 39082
 39083
 39084
 39085
 39086
 39087
 39088
 39089
 39090
 39091
 39092
 39093
 39094
 39095
 39096
 39097
 39098
 39099
 39100
 39101
 39102
 39103
 39104
 39105
 39106
 39107
 39108
 39109
 39110
 39111
 39112
 39113
 39114
 39115
 39116
 39117
 39118
 39119
 39120
 39121
 39122
 39123
 39124
 39125
 39126
 39127
 39128
 39129
 39130
 39131
 39132
 39133
 39134
 39135
 39136
 39137
 39138
 39139
 39140
 39141
 39142
 39143
 39144
 39145
 39146
 39147
 39148
 39149
 39150
 39151
 39152
 39153
 39154
 39155
 39156
 39157
 39158
 39159
 39160
 39161
 39162
 39163
 39164
 39165
 39166
 39167
 39168
 39169
 39170
 39171
 39172
 39173
 39174
 39175
 39176
 39177
 39178
 39179
 39180
 39181
 39182
 39183
 39184
 39185
 39186
 39187
 39188
 39189
 39190
 39191
 39192
 39193
 39194
 39195
 39196
 39197
 39198
 39199
 39200
 39201
 39202
 39203
 39204
 39205
 39206
 39207
 39208
 39209
 39210
 39211
 39212
 39213
 39214
 39215
 39216
 39217
 39218
 39219
 39220
 39221
 39222
 39223
 39224
 39225
 39226
 39227
 39228
 39229
 39230
 39231
 39232
 39233
 39234
 39235
 39236
 39237
 39238
 39239
 39240
 39241
 39242
 39243
 39244
 39245
 39246
 39247
 39248
 39249
 39250
 39251
 39252
 39253
 39254
 39255
 39256
 39257
 39258
 39259
 39260
 39261
 39262
 39263
 39264
 39265
 39266
 39267
 39268
 39269
 39270
 39271
 39272
 39273
 39274
 39275
 39276
 39277
 39278
 39279
 39280
 39281
 39282
 39283
 39284
 39285
 39286
 39287
 39288
 39289
 39290
 39291
 39292
 39293
 39294
 39295
 39296
 39297
 39298
 39299
 39300
 39301
 39302
 39303
 39304
 39305
 39306
 39307
 39308
 39309
 39310
 39311
 39312
 39313
 39314
 39315
 39316
 39317
 39318
 39319
 39320
 39321
 39322
 39323
 39324
 39325
 39326
 39327
 39328
 39329
 39330
 39331
 39332
 39333
 39334
 39335
 39336
 39337
 39338
 39339
 39340
 39341
 39342
 39343
 39344
 39345
 39346
 39347
 39348
 39349
 39350
 39351
 39352
 39353
 39354
 39355
 39356
 39357
 39358
 39359
 39360
 39361
 39362
 39363
 39364
 39365
 39366
 39367
 39368
 39369
 39370
 39371
 39372
 39373
 39374
 39375
 39376
 39377
 39378
 39379
 39380
 39381
 39382
 39383
 39384
 39385
 39386
 39387
 39388
 39389
 39390
 39391
 39392
 39393
 39394
 39395
 39396
 39397
 39398
 39399
 39400
 39401
 39402
 39403
 39404
 39405
 39406
 39407
 39408
 39409
 39410
 39411
 39412
 39413
 39414
 39415
 39416
 39417
 39418
 39419
 39420
 39421
 39422
 39423
 39424
 39425
 39426
 39427
 39428
 39429
 39430
 39431
 39432
 39433
 39434
 39435
 39436
 39437
 39438
 39439
 39440
 39441
 39442
 39443
 39444
 39445
 39446
 39447
 39448
 39449
 39450
 39451
 39452
 39453
 39454
 39455
 39456
 39457
 39458
 39459
 39460
 39461
 39462
 39463
 39464
 39465
 39466
 39467
 39468
 39469
 39470
 39471
 39472
 39473
 39474
 39475
 39476
 39477
 39478
 39479
 39480
 39481
 39482
 39483
 39484
 39485
 39486
 39487
 39488
 39489
 39490
 39491
 39492
 39493
 39494
 39495
 39496
 39497
 39498
 39499
 39500
 39501
 39502
 39503
 39504
 39505
 39506
 39507
 39508
 39509
 39510
 39511
 39512
 39513
 39514
 39515
 39516
 39517
 39518
 39519
 39520
 39521
 39522
 39523
 39524
 39525
 39526
 39527
 39528
 39529
 39530
 39531
 39532
 39533
 39534
 39535
 39536
 39537
 39538
 39539
 39540
 39541
 39542
 39543
 39544
 39545
 39546
 39547
 39548
 39549
 39550
 39551
 39552
 39553
 39554
 39555
 39556
 39557
 39558
 39559
 39560
 39561
 39562
 39563
 39564
 39565
 39566
 39567
 39568
 39569
 39570
 39571
 39572
 39573
 39574
 39575
 39576
 39577
 39578
 39579
 39580
 39581
 39582
 39583
 39584
 39585
 39586
 39587
 39588
 39589
 39590
 39591
 39592
 39593
 39594
 39595
 39596
 39597
 39598
 39599
 39600
 39601
 39602
 39603
 39604
 39605
 39606
 39607
 39608
 39609
 39610
 39611
 39612
 39613
 39614
 39615
 39616
 39617
 39618
 39619
 39620
 39621
 39622
 39623
 39624
 39625
 39626
 39627
 39628
 39629
 39630
 39631
 39632
 39633
 39634
 39635
 39636
 39637
 39638
 39639
 39640
 39641
 39642
 39643
 39644
 39645
 39646
 39647
 39648
 39649
 39650
 39651
 39652
 39653
 39654
 39655
 39656
 39657
 39658
 39659
 39660
 39661
 39662
 39663
 39664
 39665
 39666
 39667
 39668
 39669
 39670
 39671
 39672
 39673
 39674
 39675
 39676
 39677
 39678
 39679
 39680
 39681
 39682
 39683
 39684
 39685
 39686
 39687
 39688
 39689
 39690
 39691
 39692
 39693
 39694
 39695
 39696
 39697
 39698
 39699
 39700
 39701
 39702
 39703
 39704
 39705
 39706
 39707
 39708
 39709
 39710
 39711
 39712
 39713
 39714
 39715
 39716
 39717
 39718
 39719
 39720
 39721
 39722
 39723
 39724
 39725
 39726
 39727
 39728
 39729
 39730
 39731
 39732
 39733
 39734
 39735
 39736
 39737
 39738
 39739
 39740
 39741
 39742
 39743
 39744
 39745
 39746
 39747
 39748
 39749
 39750
 39751
 39752
 39753
 39754
 39755
 39756
 39757
 39758
 39759
 39760
 39761
 39762
 39763
 39764
 39765
 39766
 39767
 39768
 39769
 39770
 39771
 39772
 39773
 39774
 39775
 39776
 39777
 39778
 39779
 39780
 39781
 39782
 39783
 39784
 39785
 39786
 39787
 39788
 39789
 39790
 39791
 39792
 39793
 39794
 39795
 39796
 39797
 39798
 39799
 39800
 39801
 39802
 39803
 39804
 39805
 39806
 39807
 39808
 39809
 39810
 39811
 39812
 39813
 39814
 39815
 39816
 39817
 39818
 39819
 39820
 39821
 39822
 39823
 39824
 39825
 39826
 39827
 39828
 39829
 39830
 39831
 39832
 39833
 39834
 39835
 39836
 39837
 39838
 39839
 39840
 39841
 39842
 39843
 39844
 39845
 39846
 39847
 39848
 39849
 39850
 39851
 39852
 39853
 39854
 39855
 39856
 39857
 39858
 39859
 39860
 39861
 39862
 39863
 39864
 39865
 39866
 39867
 39868
 39869
 39870
 39871
 39872
 39873
 39874
 39875
 39876
 39877
 39878
 39879
 39880
 39881
 39882
 39883
 39884
 39885
 39886
 39887
 39888
 39889
 39890
 39891
 39892
 39893
 39894
 39895
 39896
 39897
 39898
 39899
 39900
 39901
 39902
 39903
 39904
 39905
 39906
 39907
 39908
 39909
 39910
 39911
 39912
 39913
 39914
 39915
 39916
 39917
 39918
 39919
 39920
 39921
 39922
 39923
 39924
 39925
 39926
 39927
 39928
 39929
 39930
 39931
 39932
 39933
 39934
 39935
 39936
 39937
 39938
 39939
 39940
 39941
 39942
 39943
 39944
 39945
 39946
 39947
 39948
 39949
 39950
 39951
 39952
 39953
 39954
 39955
 39956
 39957
 39958
 39959
 39960
 39961
 39962
 39963
 39964
 39965
 39966
 39967
 39968
 39969
 39970
 39971
 39972
 39973
 39974
 39975
 39976
 39977
 39978
 39979
 39980
 39981
 39982
 39983
 39984
 39985
 39986
 39987
 39988
 39989
 39990
 39991
 39992
 39993
 39994
 39995
 39996
 39997
 39998
 39999
 40000
 40001
 40002
 40003
 40004
 40005
 40006
 40007
 40008
 40009
 40010
 40011
 40012
 40013
 40014
 40015
 40016
 40017
 40018
 40019
 40020
 40021
 40022
 40023
 40024
 40025
 40026
 40027
 40028
 40029
 40030
 40031
 40032
 40033
 40034
 40035
 40036
 40037
 40038
 40039
 40040
 40041
 40042
 40043
 40044
 40045
 40046
 40047
 40048
 40049
 40050
 40051
 40052
 40053
 40054
 40055
 40056
 40057
 40058
 40059
 40060
 40061
 40062
 40063
 40064
 40065
 40066
 40067
 40068
 40069
 40070
 40071
 40072
 40073
 40074
 40075
 40076
 40077
 40078
 40079
 40080
 40081
 40082
 40083
 40084
 40085
 40086
 40087
 40088
 40089
 40090
 40091
 40092
 40093
 40094
 40095
 40096
 40097
 40098
 40099
 40100
 40101
 40102
 40103
 40104
 40105
 40106
 40107
 40108
 40109
 40110
 40111
 40112
 40113
 40114
 40115
 40116
 40117
 40118
 40119
 40120
 40121
 40122
 40123
 40124
 40125
 40126
 40127
 40128
 40129
 40130
 40131
 40132
 40133
 40134
 40135
 40136
 40137
 40138
 40139
 40140
 40141
 40142
 40143
 40144
 40145
 40146
 40147
 40148
 40149
 40150
 40151
 40152
 40153
 40154
 40155
 40156
 40157
 40158
 40159
 40160
 40161
 40162
 40163
 40164
 40165
 40166
 40167
 40168
 40169
 40170
 40171
 40172
 40173
 40174
 40175
 40176
 40177
 40178
 40179
 40180
 40181
 40182
 40183
 40184
 40185
 40186
 40187
 40188
 40189
 40190
 40191
 40192
 40193
 40194
 40195
 40196
 40197
 40198
 40199
 40200
 40201
 40202
 40203
 40204
 40205
 40206
 40207
 40208
 40209
 40210
 40211
 40212
 40213
 40214
 40215
 40216
 40217
 40218
 40219
 40220
 40221
 40222
 40223
 40224
 40225
 40226
 40227
 40228
 40229
 40230
 40231
 40232
 40233
 40234
 40235
 40236
 40237
 40238
 40239
 40240
 40241
 40242
 40243
 40244
 40245
 40246
 40247
 40248
 40249
 40250
 40251
 40252
 40253
 40254
 40255
 40256
 40257
 40258
 40259
 40260
 40261
 40262
 40263
 40264
 40265
 40266
 40267
 40268
 40269
 40270
 40271
 40272
 40273
 40274
 40275
 40276
 40277
 40278
 40279
 40280
 40281
 40282
 40283
 40284
 40285
 40286
 40287
 40288
 40289
 40290
 40291
 40292
 40293
 40294
 40295
 40296
 40297
 40298
 40299
 40300
 40301
 40302
 40303
 40304
 40305
 40306
 40307
 40308
 40309
 40310
 40311
 40312
 40313
 40314
 40315
 40316
 40317
 40318
 40319
 40320
 40321
 40322
 40323
 40324
 40325
 40326
 40327
 40328
 40329
 40330
 40331
 40332
 40333
 40334
 40335
 40336
 40337
 40338
 40339
 40340
 40341
 40342
 40343
 40344
 40345
 40346
 40347
 40348
 40349
 40350
 40351
 40352
 40353
 40354
 40355
 40356
 40357
 40358
 40359
 40360
 40361
 40362
 40363
 40364
 40365
 40366
 40367
 40368
 40369
 40370
 40371
 40372
 40373
 40374
 40375
 40376
 40377
 40378
 40379
 40380
 40381
 40382
 40383
 40384
 40385
 40386
 40387
 40388
 40389
 40390
 40391
 40392
 40393
 40394
 40395
 40396
 40397
 40398
 40399
 40400
 40401
 40402
 40403
 40404
 40405
 40406
 40407
 40408
 40409
 40410
 40411
 40412
 40413
 40414
 40415
 40416
 40417
 40418
 40419
 40420
 40421
 40422
 40423
 40424
 40425
 40426
 40427
 40428
 40429
 40430
 40431
 40432
 40433
 40434
 40435
 40436
 40437
 40438
 40439
 40440
 40441
 40442
 40443
 40444
 40445
 40446
 40447
 40448
 40449
 40450
 40451
 40452
 40453
 40454
 40455
 40456
 40457
 40458
 40459
 40460
 40461
 40462
 40463
 40464
 40465
 40466
 40467
 40468
 40469
 40470
 40471
 40472
 40473
 40474
 40475
 40476
 40477
 40478
 40479
 40480
 40481
 40482
 40483
 40484
 40485
 40486
 40487
 40488
 40489
 40490
 40491
 40492
 40493
 40494
 40495
 40496
 40497
 40498
 40499
 40500
 40501
 40502
 40503
 40504
 40505
 40506
 40507
 40508
 40509
 40510
 40511
 40512
 40513
 40514
 40515
 40516
 40517
 40518
 40519
 40520
 40521
 40522
 40523
 40524
 40525
 40526
 40527
 40528
 40529
 40530
 40531
 40532
 40533
 40534
 40535
 40536
 40537
 40538
 40539
 40540
 40541
 40542
 40543
 40544
 40545
 40546
 40547
 40548
 40549
 40550
 40551
 40552
 40553
 40554
 40555
 40556
 40557
 40558
 40559
 40560
 40561
 40562
 40563
 40564
 40565
 40566
 40567
 40568
 40569
 40570
 40571
 40572
 40573
 40574
 40575
 40576
 40577
 40578
 40579
 40580
 40581
 40582
 40583
 40584
 40585
 40586
 40587
 40588
 40589
 40590
 40591
 40592
 40593
 40594
 40595
 40596
 40597
 40598
 40599
 40600
 40601
 40602
 40603
 40604
 40605
 40606
 40607
 40608
 40609
 40610
 40611
 40612
 40613
 40614
 40615
 40616
 40617
 40618
 40619
 40620
 40621
 40622
 40623
 40624
 40625
 40626
 40627
 40628
 40629
 40630
 40631
 40632
 40633
 40634
 40635
 40636
 40637
 40638
 40639
 40640
 40641
 40642
 40643
 40644
 40645
 40646
 40647
 40648
 40649
 40650
 40651
 40652
 40653
 40654
 40655
 40656
 40657
 40658
 40659
 40660
 40661
 40662
 40663
 40664
 40665
 40666
 40667
 40668
 40669
 40670
 40671
 40672
 40673
 40674
 40675
 40676
 40677
 40678
 40679
 40680
 40681
 40682
 40683
 40684
 40685
 40686
 40687
 40688
 40689
 40690
 40691
 40692
 40693
 40694
 40695
 40696
 40697
 40698
 40699
 40700
 40701
 40702
 40703
 40704
 40705
 40706
 40707
 40708
 40709
 40710
 40711
 40712
 40713
 40714
 40715
 40716
 40717
 40718
 40719
 40720
 40721
 40722
 40723
 40724
 40725
 40726
 40727
 40728
 40729
 40730
 40731
 40732
 40733
 40734
 40735
 40736
 40737
 40738
 40739
 40740
 40741
 40742
 40743
 40744
 40745
 40746
 40747
 40748
 40749
 40750
 40751
 40752
 40753
 40754
 40755
 40756
 40757
 40758
 40759
 40760
 40761
 40762
 40763
 40764
 40765
 40766
 40767
 40768
 40769
 40770
 40771
 40772
 40773
 40774
 40775
 40776
 40777
 40778
 40779
 40780
 40781
 40782
 40783
 40784
 40785
 40786
 40787
 40788
 40789
 40790
 40791
 40792
 40793
 40794
 40795
 40796
 40797
 40798
 40799
 40800
 40801
 40802
 40803
 40804
 40805
 40806
 40807
 40808
 40809
 40810
 40811
 40812
 40813
 40814
 40815
 40816
 40817
 40818
 40819
 40820
 40821
 40822
 40823
 40824
 40825
 40826
 40827
 40828
 40829
 40830
 40831
 40832
 40833
 40834
 40835
 40836
 40837
 40838
 40839
 40840
 40841
 40842
 40843
 40844
 40845
 40846
 40847
 40848
 40849
 40850
 40851
 40852
 40853
 40854
 40855
 40856
 40857
 40858
 40859
 40860
 40861
 40862
 40863
 40864
 40865
 40866
 40867
 40868
 40869
 40870
 40871
 40872
 40873
 40874
 40875
 40876
 40877
 40878
 40879
 40880
 40881
 40882
 40883
 40884
 40885
 40886
 40887
 40888
 40889
 40890
 40891
 40892
 40893
 40894
 40895
 40896
 40897
 40898
 40899
 40900
 40901
 40902
 40903
 40904
 40905
 40906
 40907
 40908
 40909
 40910
 40911
 40912
 40913
 40914
 40915
 40916
 40917
 40918
 40919
 40920
 40921
 40922
 40923
 40924
 40925
 40926
 40927
 40928
 40929
 40930
 40931
 40932
 40933
 40934
 40935
 40936
 40937
 40938
 40939
 40940
 40941
 40942
 40943
 40944
 40945
 40946
 40947
 40948
 40949
 40950
 40951
 40952
 40953
 40954
 40955
 40956
 40957
 40958
 40959
 40960
 40961
 40962
 40963
 40964
 40965
 40966
 40967
 40968
 40969
 40970
 40971
 40972
 40973
 40974
 40975
 40976
 40977
 40978
 40979
 40980
 40981
 40982
 40983
 40984
 40985
 40986
 40987
 40988
 40989
 40990
 40991
 40992
 40993
 40994
 40995
 40996
 40997
 40998
 40999
 41000
 41001
 41002
 41003
 41004
 41005
 41006
 41007
 41008
 41009
 41010
 41011
 41012
 41013
 41014
 41015
 41016
 41017
 41018
 41019
 41020
 41021
 41022
 41023
 41024
 41025
 41026
 41027
 41028
 41029
 41030
 41031
 41032
 41033
 41034
 41035
 41036
 41037
 41038
 41039
 41040
 41041
 41042
 41043
 41044
 41045
 41046
 41047
 41048
 41049
 41050
 41051
 41052
 41053
 41054
 41055
 41056
 41057
 41058
 41059
 41060
 41061
 41062
 41063
 41064
 41065
 41066
 41067
 41068
 41069
 41070
 41071
 41072
 41073
 41074
 41075
 41076
 41077
 41078
 41079
 41080
 41081
 41082
 41083
 41084
 41085
 41086
 41087
 41088
 41089
 41090
 41091
 41092
 41093
 41094
 41095
 41096
 41097
 41098
 41099
 41100
 41101
 41102
 41103
 41104
 41105
 41106
 41107
 41108
 41109
 41110
 41111
 41112
 41113
 41114
 41115
 41116
 41117
 41118
 41119
 41120
 41121
 41122
 41123
 41124
 41125
 41126
 41127
 41128
 41129
 41130
 41131
 41132
 41133
 41134
 41135
 41136
 41137
 41138
 41139
 41140
 41141
 41142
 41143
 41144
 41145
 41146
 41147
 41148
 41149
 41150
 41151
 41152
 41153
 41154
 41155
 41156
 41157
 41158
 41159
 41160
 41161
 41162
 41163
 41164
 41165
 41166
 41167
 41168
 41169
 41170
 41171
 41172
 41173
 41174
 41175
 41176
 41177
 41178
 41179
 41180
 41181
 41182
 41183
 41184
 41185
 41186
 41187
 41188
 41189
 41190
 41191
 41192
 41193
 41194
 41195
 41196
 41197
 41198
 41199
 41200
 41201
 41202
 41203
 41204
 41205
 41206
 41207
 41208
 41209
 41210
 41211
 41212
 41213
 41214
 41215
 41216
 41217
 41218
 41219
 41220
 41221
 41222
 41223
 41224
 41225
 41226
 41227
 41228
 41229
 41230
 41231
 41232
 41233
 41234
 41235
 41236
 41237
 41238
 41239
 41240
 41241
 41242
 41243
 41244
 41245
 41246
 41247
 41248
 41249
 41250
 41251
 41252
 41253
 41254
 41255
 41256
 41257
 41258
 41259
 41260
 41261
 41262
 41263
 41264
 41265
 41266
 41267
 41268
 41269
 41270
 41271
 41272
 41273
 41274
 41275
 41276
 41277
 41278
 41279
 41280
 41281
 41282
 41283
 41284
 41285
 41286
 41287
 41288
 41289
 41290
 41291
 41292
 41293
 41294
 41295
 41296
 41297
 41298
 41299
 41300
 41301
 41302
 41303
 41304
 41305
 41306
 41307
 41308
 41309
 41310
 41311
 41312
 41313
 41314
 41315
 41316
 41317
 41318
 41319
 41320
 41321
 41322
 41323
 41324
 41325
 41326
 41327
 41328
 41329
 41330
 41331
 41332
 41333
 41334
 41335
 41336
 41337
 41338
 41339
 41340
 41341
 41342
 41343
 41344
 41345
 41346
 41347
 41348
 41349
 41350
 41351
 41352
 41353
 41354
 41355
 41356
 41357
 41358
 41359
 41360
 41361
 41362
 41363
 41364
 41365
 41366
 41367
 41368
 41369
 41370
 41371
 41372
 41373
 41374
 41375
 41376
 41377
 41378
 41379
 41380
 41381
 41382
 41383
 41384
 41385
 41386
 41387
 41388
 41389
 41390
 41391
 41392
 41393
 41394
 41395
 41396
 41397
 41398
 41399
 41400
 41401
 41402
 41403
 41404
 41405
 41406
 41407
 41408
 41409
 41410
 41411
 41412
 41413
 41414
 41415
 41416
 41417
 41418
 41419
 41420
 41421
 41422
 41423
 41424
 41425
 41426
 41427
 41428
 41429
 41430
 41431
 41432
 41433
 41434
 41435
 41436
 41437
 41438
 41439
 41440
 41441
 41442
 41443
 41444
 41445
 41446
 41447
 41448
 41449
 41450
 41451
 41452
 41453
 41454
 41455
 41456
 41457
 41458
 41459
 41460
 41461
 41462
 41463
 41464
 41465
 41466
 41467
 41468
 41469
 41470
 41471
 41472
 41473
 41474
 41475
 41476
 41477
 41478
 41479
 41480
 41481
 41482
 41483
 41484
 41485
 41486
 41487
 41488
 41489
 41490
 41491
 41492
 41493
 41494
 41495
 41496
 41497
 41498
 41499
 41500
 41501
 41502
 41503
 41504
 41505
 41506
 41507
 41508
 41509
 41510
 41511
 41512
 41513
 41514
 41515
 41516
 41517
 41518
 41519
 41520
 41521
 41522
 41523
 41524
 41525
 41526
 41527
 41528
 41529
 41530
 41531
 41532
 41533
 41534
 41535
 41536
 41537
 41538
 41539
 41540
 41541
 41542
 41543
 41544
 41545
 41546
 41547
 41548
 41549
 41550
 41551
 41552
 41553
 41554
 41555
 41556
 41557
 41558
 41559
 41560
 41561
 41562
 41563
 41564
 41565
 41566
 41567
 41568
 41569
 41570
 41571
 41572
 41573
 41574
 41575
 41576
 41577
 41578
 41579
 41580
 41581
 41582
 41583
 41584
 41585
 41586
 41587
 41588
 41589
 41590
 41591
 41592
 41593
 41594
 41595
 41596
 41597
 41598
 41599
 41600
 41601
 41602
 41603
 41604
 41605
 41606
 41607
 41608
 41609
 41610
 41611
 41612
 41613
 41614
 41615
 41616
 41617
 41618
 41619
 41620
 41621
 41622
 41623
 41624
 41625
 41626
 41627
 41628
 41629
 41630
 41631
 41632
 41633
 41634
 41635
 41636
 41637
 41638
 41639
 41640
 41641
 41642
 41643
 41644
 41645
 41646
 41647
 41648
 41649
 41650
 41651
 41652
 41653
 41654
 41655
 41656
 41657
 41658
 41659
 41660
 41661
 41662
 41663
 41664
 41665
 41666
 41667
 41668
 41669
 41670
 41671
 41672
 41673
 41674
 41675
 41676
 41677
 41678
 41679
 41680
 41681
 41682
 41683
 41684
 41685
 41686
 41687
 41688
 41689
 41690
 41691
 41692
 41693
 41694
 41695
 41696
 41697
 41698
 41699
 41700
 41701
 41702
 41703
 41704
 41705
 41706
 41707
 41708
 41709
 41710
 41711
 41712
 41713
 41714
 41715
 41716
 41717
 41718
 41719
 41720
 41721
 41722
 41723
 41724
 41725
 41726
 41727
 41728
 41729
 41730
 41731
 41732
 41733
 41734
 41735
 41736
 41737
 41738
 41739
 41740
 41741
 41742
 41743
 41744
 41745
 41746
 41747
 41748
 41749
 41750
 41751
 41752
 41753
 41754
 41755
 41756
 41757
 41758
 41759
 41760
 41761
 41762
 41763
 41764
 41765
 41766
 41767
 41768
 41769
 41770
 41771
 41772
 41773
 41774
 41775
 41776
 41777
 41778
 41779
 41780
 41781
 41782
 41783
 41784
 41785
 41786
 41787
 41788
 41789
 41790
 41791
 41792
 41793
 41794
 41795
 41796
 41797
 41798
 41799
 41800
 41801
 41802
 41803
 41804
 41805
 41806
 41807
 41808
 41809
 41810
 41811
 41812
 41813
 41814
 41815
 41816
 41817
 41818
 41819
 41820
 41821
 41822
 41823
 41824
 41825
 41826
 41827
 41828
 41829
 41830
 41831
 41832
 41833
 41834
 41835
 41836
 41837
 41838
 41839
 41840
 41841
 41842
 41843
 41844
 41845
 41846
 41847
 41848
 41849
 41850
 41851
 41852
 41853
 41854
 41855
 41856
 41857
 41858
 41859
 41860
 41861
 41862
 41863
 41864
 41865
 41866
 41867
 41868
 41869
 41870
 41871
 41872
 41873
 41874
 41875
 41876
 41877
 41878
 41879
 41880
 41881
 41882
 41883
 41884
 41885
 41886
 41887
 41888
 41889
 41890
 41891
 41892
 41893
 41894
 41895
 41896
 41897
 41898
 41899
 41900
 41901
 41902
 41903
 41904
 41905
 41906
 41907
 41908
 41909
 41910
 41911
 41912
 41913
 41914
 41915
 41916
 41917
 41918
 41919
 41920
 41921
 41922
 41923
 41924
 41925
 41926
 41927
 41928
 41929
 41930
 41931
 41932
 41933
 41934
 41935
 41936
 41937
 41938
 41939
 41940
 41941
 41942
 41943
 41944
 41945
 41946
 41947
 41948
 41949
 41950
 41951
 41952
 41953
 41954
 41955
 41956
 41957
 41958
 41959
 41960
 41961
 41962
 41963
 41964
 41965
 41966
 41967
 41968
 41969
 41970
 41971
 41972
 41973
 41974
 41975
 41976
 41977
 41978
 41979
 41980
 41981
 41982
 41983
 41984
 41985
 41986
 41987
 41988
 41989
 41990
 41991
 41992
 41993
 41994
 41995
 41996
 41997
 41998
 41999
 42000
 42001
 42002
 42003
 42004
 42005
 42006
 42007
 42008
 42009
 42010
 42011
 42012
 42013
 42014
 42015
 42016
 42017
 42018
 42019
 42020
 42021
 42022
 42023
 42024
 42025
 42026
 42027
 42028
 42029
 42030
 42031
 42032
 42033
 42034
 42035
 42036
 42037
 42038
 42039
 42040
 42041
 42042
 42043
 42044
 42045
 42046
 42047
 42048
 42049
 42050
 42051
 42052
 42053
 42054
 42055
 42056
 42057
 42058
 42059
 42060
 42061
 42062
 42063
 42064
 42065
 42066
 42067
 42068
 42069
 42070
 42071
 42072
 42073
 42074
 42075
 42076
 42077
 42078
 42079
 42080
 42081
 42082
 42083
 42084
 42085
 42086
 42087
 42088
 42089
 42090
 42091
 42092
 42093
 42094
 42095
 42096
 42097
 42098
 42099
 42100
 42101
 42102
 42103
 42104
 42105
 42106
 42107
 42108
 42109
 42110
 42111
 42112
 42113
 42114
 42115
 42116
 42117
 42118
 42119
 42120
 42121
 42122
 42123
 42124
 42125
 42126
 42127
 42128
 42129
 42130
 42131
 42132
 42133
 42134
 42135
 42136
 42137
 42138
 42139
 42140
 42141
 42142
 42143
 42144
 42145
 42146
 42147
 42148
 42149
 42150
 42151
 42152
 42153
 42154
 42155
 42156
 42157
 42158
 42159
 42160
 42161
 42162
 42163
 42164
 42165
 42166
 42167
 42168
 42169
 42170
 42171
 42172
 42173
 42174
 42175
 42176
 42177
 42178
 42179
 42180
 42181
 42182
 42183
 42184
 42185
 42186
 42187
 42188
 42189
 42190
 42191
 42192
 42193
 42194
 42195
 42196
 42197
 42198
 42199
 42200
 42201
 42202
 42203
 42204
 42205
 42206
 42207
 42208
 42209
 42210
 42211
 42212
 42213
 42214
 42215
 42216
 42217
 42218
 42219
 42220
 42221
 42222
 42223
 42224
 42225
 42226
 42227
 42228
 42229
 42230
 42231
 42232
 42233
 42234
 42235
 42236
 42237
 42238
 42239
 42240
 42241
 42242
 42243
 42244
 42245
 42246
 42247
 42248
 42249
 42250
 42251
 42252
 42253
 42254
 42255
 42256
 42257
 42258
 42259
 42260
 42261
 42262
 42263
 42264
 42265
 42266
 42267
 42268
 42269
 42270
 42271
 42272
 42273
 42274
 42275
 42276
 42277
 42278
 42279
 42280
 42281
 42282
 42283
 42284
 42285
 42286
 42287
 42288
 42289
 42290
 42291
 42292
 42293
 42294
 42295
 42296
 42297
 42298
 42299
 42300
 42301
 42302
 42303
 42304
 42305
 42306
 42307
 42308
 42309
 42310
 42311
 42312
 42313
 42314
 42315
 42316
 42317
 42318
 42319
 42320
 42321
 42322
 42323
 42324
 42325
 42326
 42327
 42328
 42329
 42330
 42331
 42332
 42333
 42334
 42335
 42336
 42337
 42338
 42339
 42340
 42341
 42342
 42343
 42344
 42345
 42346
 42347
 42348
 42349
 42350
 42351
 42352
 42353
 42354
 42355
 42356
 42357
 42358
 42359
 42360
 42361
 42362
 42363
 42364
 42365
 42366
 42367
 42368
 42369
 42370
 42371
 42372
 42373
 42374
 42375
 42376
 42377
 42378
 42379
 42380
 42381
 42382
 42383
 42384
 42385
 42386
 42387
 42388
 42389
 42390
 42391
 42392
 42393
 42394
 42395
 42396
 42397
 42398
 42399
 42400
 42401
 42402
 42403
 42404
 42405
 42406
 42407
 42408
 42409
 42410
 42411
 42412
 42413
 42414
 42415
 42416
 42417
 42418
 42419
 42420
 42421
 42422
 42423
 42424
 42425
 42426
 42427
 42428
 42429
 42430
 42431
 42432
 42433
 42434
 42435
 42436
 42437
 42438
 42439
 42440
 42441
 42442
 42443
 42444
 42445
 42446
 42447
 42448
 42449
 42450
 42451
 42452
 42453
 42454
 42455
 42456
 42457
 42458
 42459
 42460
 42461
 42462
 42463
 42464
 42465
 42466
 42467
 42468
 42469
 42470
 42471
 42472
 42473
 42474
 42475
 42476
 42477
 42478
 42479
 42480
 42481
 42482
 42483
 42484
 42485
 42486
 42487
 42488
 42489
 42490
 42491
 42492
 42493
 42494
 42495
 42496
 42497
 42498
 42499
 42500
 42501
 42502
 42503
 42504
 42505
 42506
 42507
 42508
 42509
 42510
 42511
 42512
 42513
 42514
 42515
 42516
 42517
 42518
 42519
 42520
 42521
 42522
 42523
 42524
 42525
 42526
 42527
 42528
 42529
 42530
 42531
 42532
 42533
 42534
 42535
 42536
 42537
 42538
 42539
 42540
 42541
 42542
 42543
 42544
 42545
 42546
 42547
 42548
 42549
 42550
 42551
 42552
 42553
 42554
 42555
 42556
 42557
 42558
 42559
 42560
 42561
 42562
 42563
 42564
 42565
 42566
 42567
 42568
 42569
 42570
 42571
 42572
 42573
 42574
 42575
 42576
 42577
 42578
 42579
 42580
 42581
 42582
 42583
 42584
 42585
 42586
 42587
 42588
 42589
 42590
 42591
 42592
 42593
 42594
 42595
 42596
 42597
 42598
 42599
 42600
 42601
 42602
 42603
 42604
 42605
 42606
 42607
 42608
 42609
 42610
 42611
 42612
 42613
 42614
 42615
 42616
 42617
 42618
 42619
 42620
 42621
 42622
 42623
 42624
 42625
 42626
 42627
 42628
 42629
 42630
 42631
 42632
 42633
 42634
 42635
 42636
 42637
 42638
 42639
 42640
 42641
 42642
 42643
 42644
 42645
 42646
 42647
 42648
 42649
 42650
 42651
 42652
 42653
 42654
 42655
 42656
 42657
 42658
 42659
 42660
 42661
 42662
 42663
 42664
 42665
 42666
 42667
 42668
 42669
 42670
 42671
 42672
 42673
 42674
 42675
 42676
 42677
 42678
 42679
 42680
 42681
 42682
 42683
 42684
 42685
 42686
 42687
 42688
 42689
 42690
 42691
 42692
 42693
 42694
 42695
 42696
 42697
 42698
 42699
 42700
 42701
 42702
 42703
 42704
 42705
 42706
 42707
 42708
 42709
 42710
 42711
 42712
 42713
 42714
 42715
 42716
 42717
 42718
 42719
 42720
 42721
 42722
 42723
 42724
 42725
 42726
 42727
 42728
 42729
 42730
 42731
 42732
 42733
 42734
 42735
 42736
 42737
 42738
 42739
 42740
 42741
 42742
 42743
 42744
 42745
 42746
 42747
 42748
 42749
 42750
 42751
 42752
 42753
 42754
 42755
 42756
 42757
 42758
 42759
 42760
 42761
 42762
 42763
 42764
 42765
 42766
 42767
 42768
 42769
 42770
 42771
 42772
 42773
 42774
 42775
 42776
 42777
 42778
 42779
 42780
 42781
 42782
 42783
 42784
 42785
 42786
 42787
 42788
 42789
 42790
 42791
 42792
 42793
 42794
 42795
 42796
 42797
 42798
 42799
 42800
 42801
 42802
 42803
 42804
 42805
 42806
 42807
 42808
 42809
 42810
 42811
 42812
 42813
 42814
 42815
 42816
 42817
 42818
 42819
 42820
 42821
 42822
 42823
 42824
 42825
 42826
 42827
 42828
 42829
 42830
 42831
 42832
 42833
 42834
 42835
 42836
 42837
 42838
 42839
 42840
 42841
 42842
 42843
 42844
 42845
 42846
 42847
 42848
 42849
 42850
 42851
 42852
 42853
 42854
 42855
 42856
 42857
 42858
 42859
 42860
 42861
 42862
 42863
 42864
 42865
 42866
 42867
 42868
 42869
 42870
 42871
 42872
 42873
 42874
 42875
 42876
 42877
 42878
 42879
 42880
 42881
 42882
 42883
 42884
 42885
 42886
 42887
 42888
 42889
 42890
 42891
 42892
 42893
 42894
 42895
 42896
 42897
 42898
 42899
 42900
 42901
 42902
 42903
 42904
 42905
 42906
 42907
 42908
 42909
 42910
 42911
 42912
 42913
 42914
 42915
 42916
 42917
 42918
 42919
 42920
 42921
 42922
 42923
 42924
 42925
 42926
 42927
 42928
 42929
 42930
 42931
 42932
 42933
 42934
 42935
 42936
 42937
 42938
 42939
 42940
 42941
 42942
 42943
 42944
 42945
 42946
 42947
 42948
 42949
 42950
 42951
 42952
 42953
 42954
 42955
 42956
 42957
 42958
 42959
 42960
 42961
 42962
 42963
 42964
 42965
 42966
 42967
 42968
 42969
 42970
 42971
 42972
 42973
 42974
 42975
 42976
 42977
 42978
 42979
 42980
 42981
 42982
 42983
 42984
 42985
 42986
 42987
 42988
 42989
 42990
 42991
 42992
 42993
 42994
 42995
 42996
 42997
 42998
 42999
 43000
 43001
 43002
 43003
 43004
 43005
 43006
 43007
 43008
 43009
 43010
 43011
 43012
 43013
 43014
 43015
 43016
 43017
 43018
 43019
 43020
 43021
 43022
 43023
 43024
 43025
 43026
 43027
 43028
 43029
 43030
 43031
 43032
 43033
 43034
 43035
 43036
 43037
 43038
 43039
 43040
 43041
 43042
 43043
 43044
 43045
 43046
 43047
 43048
 43049
 43050
 43051
 43052
 43053
 43054
 43055
 43056
 43057
 43058
 43059
 43060
 43061
 43062
 43063
 43064
 43065
 43066
 43067
 43068
 43069
 43070
 43071
 43072
 43073
 43074
 43075
 43076
 43077
 43078
 43079
 43080
 43081
 43082
 43083
 43084
 43085
 43086
 43087
 43088
 43089
 43090
 43091
 43092
 43093
 43094
 43095
 43096
 43097
 43098
 43099
 43100
 43101
 43102
 43103
 43104
 43105
 43106
 43107
 43108
 43109
 43110
 43111
 43112
 43113
 43114
 43115
 43116
 43117
 43118
 43119
 43120
 43121
 43122
 43123
 43124
 43125
 43126
 43127
 43128
 43129
 43130
 43131
 43132
 43133
 43134
 43135
 43136
 43137
 43138
 43139
 43140
 43141
 43142
 43143
 43144
 43145
 43146
 43147
 43148
 43149
 43150
 43151
 43152
 43153
 43154
 43155
 43156
 43157
 43158
 43159
 43160
 43161
 43162
 43163
 43164
 43165
 43166
 43167
 43168
 43169
 43170
 43171
 43172
 43173
 43174
 43175
 43176
 43177
 43178
 43179
 43180
 43181
 43182
 43183
 43184
 43185
 43186
 43187
 43188
 43189
 43190
 43191
 43192
 43193
 43194
 43195
 43196
 43197
 43198
 43199
 43200
 43201
 43202
 43203
 43204
 43205
 43206
 43207
 43208
 43209
 43210
 43211
 43212
 43213
 43214
 43215
 43216
 43217
 43218
 43219
 43220
 43221
 43222
 43223
 43224
 43225
 43226
 43227
 43228
 43229
 43230
 43231
 43232
 43233
 43234
 43235
 43236
 43237
 43238
 43239
 43240
 43241
 43242
 43243
 43244
 43245
 43246
 43247
 43248
 43249
 43250
 43251
 43252
 43253
 43254
 43255
 43256
 43257
 43258
 43259
 43260
 43261
 43262
 43263
 43264
 43265
 43266
 43267
 43268
 43269
 43270
 43271
 43272
 43273
 43274
 43275
 43276
 43277
 43278
 43279
 43280
 43281
 43282
 43283
 43284
 43285
 43286
 43287
 43288
 43289
 43290
 43291
 43292
 43293
 43294
 43295
 43296
 43297
 43298
 43299
 43300
 43301
 43302
 43303
 43304
 43305
 43306
 43307
 43308
 43309
 43310
 43311
 43312
 43313
 43314
 43315
 43316
 43317
 43318
 43319
 43320
 43321
 43322
 43323
 43324
 43325
 43326
 43327
 43328
 43329
 43330
 43331
 43332
 43333
 43334
 43335
 43336
 43337
 43338
 43339
 43340
 43341
 43342
 43343
 43344
 43345
 43346
 43347
 43348
 43349
 43350
 43351
 43352
 43353
 43354
 43355
 43356
 43357
 43358
 43359
 43360
 43361
 43362
 43363
 43364
 43365
 43366
 43367
 43368
 43369
 43370
 43371
 43372
 43373
 43374
 43375
 43376
 43377
 43378
 43379
 43380
 43381
 43382
 43383
 43384
 43385
 43386
 43387
 43388
 43389
 43390
 43391
 43392
 43393
 43394
 43395
 43396
 43397
 43398
 43399
 43400
 43401
 43402
 43403
 43404
 43405
 43406
 43407
 43408
 43409
 43410
 43411
 43412
 43413
 43414
 43415
 43416
 43417
 43418
 43419
 43420
 43421
 43422
 43423
 43424
 43425
 43426
 43427
 43428
 43429
 43430
 43431
 43432
 43433
 43434
 43435
 43436
 43437
 43438
 43439
 43440
 43441
 43442
 43443
 43444
 43445
 43446
 43447
 43448
 43449
 43450
 43451
 43452
 43453
 43454
 43455
 43456
 43457
 43458
 43459
 43460
 43461
 43462
 43463
 43464
 43465
 43466
 43467
 43468
 43469
 43470
 43471
 43472
 43473
 43474
 43475
 43476
 43477
 43478
 43479
 43480
 43481
 43482
 43483
 43484
 43485
 43486
 43487
 43488
 43489
 43490
 43491
 43492
 43493
 43494
 43495
 43496
 43497
 43498
 43499
 43500
 43501
 43502
 43503
 43504
 43505
 43506
 43507
 43508
 43509
 43510
 43511
 43512
 43513
 43514
 43515
 43516
 43517
 43518
 43519
 43520
 43521
 43522
 43523
 43524
 43525
 43526
 43527
 43528
 43529
 43530
 43531
 43532
 43533
 43534
 43535
 43536
 43537
 43538
 43539
 43540
 43541
 43542
 43543
 43544
 43545
 43546
 43547
 43548
 43549
 43550
 43551
 43552
 43553
 43554
 43555
 43556
 43557
 43558
 43559
 43560
 43561
 43562
 43563
 43564
 43565
 43566
 43567
 43568
 43569
 43570
 43571
 43572
 43573
 43574
 43575
 43576
 43577
 43578
 43579
 43580
 43581
 43582
 43583
 43584
 43585
 43586
 43587
 43588
 43589
 43590
 43591
 43592
 43593
 43594
 43595
 43596
 43597
 43598
 43599
 43600
 43601
 43602
 43603
 43604
 43605
 43606
 43607
 43608
 43609
 43610
 43611
 43612
 43613
 43614
 43615
 43616
 43617
 43618
 43619
 43620
 43621
 43622
 43623
 43624
 43625
 43626
 43627
 43628
 43629
 43630
 43631
 43632
 43633
 43634
 43635
 43636
 43637
 43638
 43639
 43640
 43641
 43642
 43643
 43644
 43645
 43646
 43647
 43648
 43649
 43650
 43651
 43652
 43653
 43654
 43655
 43656
 43657
 43658
 43659
 43660
 43661
 43662
 43663
 43664
 43665
 43666
 43667
 43668
 43669
 43670
 43671
 43672
 43673
 43674
 43675
 43676
 43677
 43678
 43679
 43680
 43681
 43682
 43683
 43684
 43685
 43686
 43687
 43688
 43689
 43690
 43691
 43692
 43693
 43694
 43695
 43696
 43697
 43698
 43699
 43700
 43701
 43702
 43703
 43704
 43705
 43706
 43707
 43708
 43709
 43710
 43711
 43712
 43713
 43714
 43715
 43716
 43717
 43718
 43719
 43720
 43721
 43722
 43723
 43724
 43725
 43726
 43727
 43728
 43729
 43730
 43731
 43732
 43733
 43734
 43735
 43736
 43737
 43738
 43739
 43740
 43741
 43742
 43743
 43744
 43745
 43746
 43747
 43748
 43749
 43750
 43751
 43752
 43753
 43754
 43755
 43756
 43757
 43758
 43759
 43760
 43761
 43762
 43763
 43764
 43765
 43766
 43767
 43768
 43769
 43770
 43771
 43772
 43773
 43774
 43775
 43776
 43777
 43778
 43779
 43780
 43781
 43782
 43783
 43784
 43785
 43786
 43787
 43788
 43789
 43790
 43791
 43792
 43793
 43794
 43795
 43796
 43797
 43798
 43799
 43800
 43801
 43802
 43803
 43804
 43805
 43806
 43807
 43808
 43809
 43810
 43811
 43812
 43813
 43814
 43815
 43816
 43817
 43818
 43819
 43820
 43821
 43822
 43823
 43824
 43825
 43826
 43827
 43828
 43829
 43830
 43831
 43832
 43833
 43834
 43835
 43836
 43837
 43838
 43839
 43840
 43841
 43842
 43843
 43844
 43845
 43846
 43847
 43848
 43849
 43850
 43851
 43852
 43853
 43854
 43855
 43856
 43857
 43858
 43859
 43860
 43861
 43862
 43863
 43864
 43865
 43866
 43867
 43868
 43869
 43870
 43871
 43872
 43873
 43874
 43875
 43876
 43877
 43878
 43879
 43880
 43881
 43882
 43883
 43884
 43885
 43886
 43887
 43888
 43889
 43890
 43891
 43892
 43893
 43894
 43895
 43896
 43897
 43898
 43899
 43900
 43901
 43902
 43903
 43904
 43905
 43906
 43907
 43908
 43909
 43910
 43911
 43912
 43913
 43914
 43915
 43916
 43917
 43918
 43919
 43920
 43921
 43922
 43923
 43924
 43925
 43926
 43927
 43928
 43929
 43930
 43931
 43932
 43933
 43934
 43935
 43936
 43937
 43938
 43939
 43940
 43941
 43942
 43943
 43944
 43945
 43946
 43947
 43948
 43949
 43950
 43951
 43952
 43953
 43954
 43955
 43956
 43957
 43958
 43959
 43960
 43961
 43962
 43963
 43964
 43965
 43966
 43967
 43968
 43969
 43970
 43971
 43972
 43973
 43974
 43975
 43976
 43977
 43978
 43979
 43980
 43981
 43982
 43983
 43984
 43985
 43986
 43987
 43988
 43989
 43990
 43991
 43992
 43993
 43994
 43995
 43996
 43997
 43998
 43999
 44000
 44001
 44002
 44003
 44004
 44005
 44006
 44007
 44008
 44009
 44010
 44011
 44012
 44013
 44014
 44015
 44016
 44017
 44018
 44019
 44020
 44021
 44022
 44023
 44024
 44025
 44026
 44027
 44028
 44029
 44030
 44031
 44032
 44033
 44034
 44035
 44036
 44037
 44038
 44039
 44040
 44041
 44042
 44043
 44044
 44045
 44046
 44047
 44048
 44049
 44050
 44051
 44052
 44053
 44054
 44055
 44056
 44057
 44058
 44059
 44060
 44061
 44062
 44063
 44064
 44065
 44066
 44067
 44068
 44069
 44070
 44071
 44072
 44073
 44074
 44075
 44076
 44077
 44078
 44079
 44080
 44081
 44082
 44083
 44084
 44085
 44086
 44087
 44088
 44089
 44090
 44091
 44092
 44093
 44094
 44095
 44096
 44097
 44098
 44099
 44100
 44101
 44102
 44103
 44104
 44105
 44106
 44107
 44108
 44109
 44110
 44111
 44112
 44113
 44114
 44115
 44116
 44117
 44118
 44119
 44120
 44121
 44122
 44123
 44124
 44125
 44126
 44127
 44128
 44129
 44130
 44131
 44132
 44133
 44134
 44135
 44136
 44137
 44138
 44139
 44140
 44141
 44142
 44143
 44144
 44145
 44146
 44147
 44148
 44149
 44150
 44151
 44152
 44153
 44154
 44155
 44156
 44157
 44158
 44159
 44160
 44161
 44162
 44163
 44164
 44165
 44166
 44167
 44168
 44169
 44170
 44171
 44172
 44173
 44174
 44175
 44176
 44177
 44178
 44179
 44180
 44181
 44182
 44183
 44184
 44185
 44186
 44187
 44188
 44189
 44190
 44191
 44192
 44193
 44194
 44195
 44196
 44197
 44198
 44199
 44200
 44201
 44202
 44203
 44204
 44205
 44206
 44207
 44208
 44209
 44210
 44211
 44212
 44213
 44214
 44215
 44216
 44217
 44218
 44219
 44220
 44221
 44222
 44223
 44224
 44225
 44226
 44227
 44228
 44229
 44230
 44231
 44232
 44233
 44234
 44235
 44236
 44237
 44238
 44239
 44240
 44241
 44242
 44243
 44244
 44245
 44246
 44247
 44248
 44249
 44250
 44251
 44252
 44253
 44254
 44255
 44256
 44257
 44258
 44259
 44260
 44261
 44262
 44263
 44264
 44265
 44266
 44267
 44268
 44269
 44270
 44271
 44272
 44273
 44274
 44275
 44276
 44277
 44278
 44279
 44280
 44281
 44282
 44283
 44284
 44285
 44286
 44287
 44288
 44289
 44290
 44291
 44292
 44293
 44294
 44295
 44296
 44297
 44298
 44299
 44300
 44301
 44302
 44303
 44304
 44305
 44306
 44307
 44308
 44309
 44310
 44311
 44312
 44313
 44314
 44315
 44316
 44317
 44318
 44319
 44320
 44321
 44322
 44323
 44324
 44325
 44326
 44327
 44328
 44329
 44330
 44331
 44332
 44333
 44334
 44335
 44336
 44337
 44338
 44339
 44340
 44341
 44342
 44343
 44344
 44345
 44346
 44347
 44348
 44349
 44350
 44351
 44352
 44353
 44354
 44355
 44356
 44357
 44358
 44359
 44360
 44361
 44362
 44363
 44364
 44365
 44366
 44367
 44368
 44369
 44370
 44371
 44372
 44373
 44374
 44375
 44376
 44377
 44378
 44379
 44380
 44381
 44382
 44383
 44384
 44385
 44386
 44387
 44388
 44389
 44390
 44391
 44392
 44393
 44394
 44395
 44396
 44397
 44398
 44399
 44400
 44401
 44402
 44403
 44404
 44405
 44406
 44407
 44408
 44409
 44410
 44411
 44412
 44413
 44414
 44415
 44416
 44417
 44418
 44419
 44420
 44421
 44422
 44423
 44424
 44425
 44426
 44427
 44428
 44429
 44430
 44431
 44432
 44433
 44434
 44435
 44436
 44437
 44438
 44439
 44440
 44441
 44442
 44443
 44444
 44445
 44446
 44447
 44448
 44449
 44450
 44451
 44452
 44453
 44454
 44455
 44456
 44457
 44458
 44459
 44460
 44461
 44462
 44463
 44464
 44465
 44466
 44467
 44468
 44469
 44470
 44471
 44472
 44473
 44474
 44475
 44476
 44477
 44478
 44479
 44480
 44481
 44482
 44483
 44484
 44485
 44486
 44487
 44488
 44489
 44490
 44491
 44492
 44493
 44494
 44495
 44496
 44497
 44498
 44499
 44500
 44501
 44502
 44503
 44504
 44505
 44506
 44507
 44508
 44509
 44510
 44511
 44512
 44513
 44514
 44515
 44516
 44517
 44518
 44519
 44520
 44521
 44522
 44523
 44524
 44525
 44526
 44527
 44528
 44529
 44530
 44531
 44532
 44533
 44534
 44535
 44536
 44537
 44538
 44539
 44540
 44541
 44542
 44543
 44544
 44545
 44546
 44547
 44548
 44549
 44550
 44551
 44552
 44553
 44554
 44555
 44556
 44557
 44558
 44559
 44560
 44561
 44562
 44563
 44564
 44565
 44566
 44567
 44568
 44569
 44570
 44571
 44572
 44573
 44574
 44575
 44576
 44577
 44578
 44579
 44580
 44581
 44582
 44583
 44584
 44585
 44586
 44587
 44588
 44589
 44590
 44591
 44592
 44593
 44594
 44595
 44596
 44597
 44598
 44599
 44600
 44601
 44602
 44603
 44604
 44605
 44606
 44607
 44608
 44609
 44610
 44611
 44612
 44613
 44614
 44615
 44616
 44617
 44618
 44619
 44620
 44621
 44622
 44623
 44624
 44625
 44626
 44627
 44628
 44629
 44630
 44631
 44632
 44633
 44634
 44635
 44636
 44637
 44638
 44639
 44640
 44641
 44642
 44643
 44644
 44645
 44646
 44647
 44648
 44649
 44650
 44651
 44652
 44653
 44654
 44655
 44656
 44657
 44658
 44659
 44660
 44661
 44662
 44663
 44664
 44665
 44666
 44667
 44668
 44669
 44670
 44671
 44672
 44673
 44674
 44675
 44676
 44677
 44678
 44679
 44680
 44681
 44682
 44683
 44684
 44685
 44686
 44687
 44688
 44689
 44690
 44691
 44692
 44693
 44694
 44695
 44696
 44697
 44698
 44699
 44700
 44701
 44702
 44703
 44704
 44705
 44706
 44707
 44708
 44709
 44710
 44711
 44712
 44713
 44714
 44715
 44716
 44717
 44718
 44719
 44720
 44721
 44722
 44723
 44724
 44725
 44726
 44727
 44728
 44729
 44730
 44731
 44732
 44733
 44734
 44735
 44736
 44737
 44738
 44739
 44740
 44741
 44742
 44743
 44744
 44745
 44746
 44747
 44748
 44749
 44750
 44751
 44752
 44753
 44754
 44755
 44756
 44757
 44758
 44759
 44760
 44761
 44762
 44763
 44764
 44765
 44766
 44767
 44768
 44769
 44770
 44771
 44772
 44773
 44774
 44775
 44776
 44777
 44778
 44779
 44780
 44781
 44782
 44783
 44784
 44785
 44786
 44787
 44788
 44789
 44790
 44791
 44792
 44793
 44794
 44795
 44796
 44797
 44798
 44799
 44800
 44801
 44802
 44803
 44804
 44805
 44806
 44807
 44808
 44809
 44810
 44811
 44812
 44813
 44814
 44815
 44816
 44817
 44818
 44819
 44820
 44821
 44822
 44823
 44824
 44825
 44826
 44827
 44828
 44829
 44830
 44831
 44832
 44833
 44834
 44835
 44836
 44837
 44838
 44839
 44840
 44841
 44842
 44843
 44844
 44845
 44846
 44847
 44848
 44849
 44850
 44851
 44852
 44853
 44854
 44855
 44856
 44857
 44858
 44859
 44860
 44861
 44862
 44863
 44864
 44865
 44866
 44867
 44868
 44869
 44870
 44871
 44872
 44873
 44874
 44875
 44876
 44877
 44878
 44879
 44880
 44881
 44882
 44883
 44884
 44885
 44886
 44887
 44888
 44889
 44890
 44891
 44892
 44893
 44894
 44895
 44896
 44897
 44898
 44899
 44900
 44901
 44902
 44903
 44904
 44905
 44906
 44907
 44908
 44909
 44910
 44911
 44912
 44913
 44914
 44915
 44916
 44917
 44918
 44919
 44920
 44921
 44922
 44923
 44924
 44925
 44926
 44927
 44928
 44929
 44930
 44931
 44932
 44933
 44934
 44935
 44936
 44937
 44938
 44939
 44940
 44941
 44942
 44943
 44944
 44945
 44946
 44947
 44948
 44949
 44950
 44951
 44952
 44953
 44954
 44955
 44956
 44957
 44958
 44959
 44960
 44961
 44962
 44963
 44964
 44965
 44966
 44967
 44968
 44969
 44970
 44971
 44972
 44973
 44974
 44975
 44976
 44977
 44978
 44979
 44980
 44981
 44982
 44983
 44984
 44985
 44986
 44987
 44988
 44989
 44990
 44991
 44992
 44993
 44994
 44995
 44996
 44997
 44998
 44999
 45000
 45001
 45002
 45003
 45004
 45005
 45006
 45007
 45008
 45009
 45010
 45011
 45012
 45013
 45014
 45015
 45016
 45017
 45018
 45019
 45020
 45021
 45022
 45023
 45024
 45025
 45026
 45027
 45028
 45029
 45030
 45031
 45032
 45033
 45034
 45035
 45036
 45037
 45038
 45039
 45040
 45041
 45042
 45043
 45044
 45045
 45046
 45047
 45048
 45049
 45050
 45051
 45052
 45053
 45054
 45055
 45056
 45057
 45058
 45059
 45060
 45061
 45062
 45063
 45064
 45065
 45066
 45067
 45068
 45069
 45070
 45071
 45072
 45073
 45074
 45075
 45076
 45077
 45078
 45079
 45080
 45081
 45082
 45083
 45084
 45085
 45086
 45087
 45088
 45089
 45090
 45091
 45092
 45093
 45094
 45095
 45096
 45097
 45098
 45099
 45100
 45101
 45102
 45103
 45104
 45105
 45106
 45107
 45108
 45109
 45110
 45111
 45112
 45113
 45114
 45115
 45116
 45117
 45118
 45119
 45120
 45121
 45122
 45123
 45124
 45125
 45126
 45127
 45128
 45129
 45130
 45131
 45132
 45133
 45134
 45135
 45136
 45137
 45138
 45139
 45140
 45141
 45142
 45143
 45144
 45145
 45146
 45147
 45148
 45149
 45150
 45151
 45152
 45153
 45154
 45155
 45156
 45157
 45158
 45159
 45160
 45161
 45162
 45163
 45164
 45165
 45166
 45167
 45168
 45169
 45170
 45171
 45172
 45173
 45174
 45175
 45176
 45177
 45178
 45179
 45180
 45181
 45182
 45183
 45184
 45185
 45186
 45187
 45188
 45189
 45190
 45191
 45192
 45193
 45194
 45195
 45196
 45197
 45198
 45199
 45200
 45201
 45202
 45203
 45204
 45205
 45206
 45207
 45208
 45209
 45210
 45211
 45212
 45213
 45214
 45215
 45216
 45217
 45218
 45219
 45220
 45221
 45222
 45223
 45224
 45225
 45226
 45227
 45228
 45229
 45230
 45231
 45232
 45233
 45234
 45235
 45236
 45237
 45238
 45239
 45240
 45241
 45242
 45243
 45244
 45245
 45246
 45247
 45248
 45249
 45250
 45251
 45252
 45253
 45254
 45255
 45256
 45257
 45258
 45259
 45260
 45261
 45262
 45263
 45264
 45265
 45266
 45267
 45268
 45269
 45270
 45271
 45272
 45273
 45274
 45275
 45276
 45277
 45278
 45279
 45280
 45281
 45282
 45283
 45284
 45285
 45286
 45287
 45288
 45289
 45290
 45291
 45292
 45293
 45294
 45295
 45296
 45297
 45298
 45299
 45300
 45301
 45302
 45303
 45304
 45305
 45306
 45307
 45308
 45309
 45310
 45311
 45312
 45313
 45314
 45315
 45316
 45317
 45318
 45319
 45320
 45321
 45322
 45323
 45324
 45325
 45326
 45327
 45328
 45329
 45330
 45331
 45332
 45333
 45334
 45335
 45336
 45337
 45338
 45339
 45340
 45341
 45342
 45343
 45344
 45345
 45346
 45347
 45348
 45349
 45350
 45351
 45352
 45353
 45354
 45355
 45356
 45357
 45358
 45359
 45360
 45361
 45362
 45363
 45364
 45365
 45366
 45367
 45368
 45369
 45370
 45371
 45372
 45373
 45374
 45375
 45376
 45377
 45378
 45379
 45380
 45381
 45382
 45383
 45384
 45385
 45386
 45387
 45388
 45389
 45390
 45391
 45392
 45393
 45394
 45395
 45396
 45397
 45398
 45399
 45400
 45401
 45402
 45403
 45404
 45405
 45406
 45407
 45408
 45409
 45410
 45411
 45412
 45413
 45414
 45415
 45416
 45417
 45418
 45419
 45420
 45421
 45422
 45423
 45424
 45425
 45426
 45427
 45428
 45429
 45430
 45431
 45432
 45433
 45434
 45435
 45436
 45437
 45438
 45439
 45440
 45441
 45442
 45443
 45444
 45445
 45446
 45447
 45448
 45449
 45450
 45451
 45452
 45453
 45454
 45455
 45456
 45457
 45458
 45459
 45460
 45461
 45462
 45463
 45464
 45465
 45466
 45467
 45468
 45469
 45470
 45471
 45472
 45473
 45474
 45475
 45476
 45477
 45478
 45479
 45480
 45481
 45482
 45483
 45484
 45485
 45486
 45487
 45488
 45489
 45490
 45491
 45492
 45493
 45494
 45495
 45496
 45497
 45498
 45499
 45500
 45501
 45502
 45503
 45504
 45505
 45506
 45507
 45508
 45509
 45510
 45511
 45512
 45513
 45514
 45515
 45516
 45517
 45518
 45519
 45520
 45521
 45522
 45523
 45524
 45525
 45526
 45527
 45528
 45529
 45530
 45531
 45532
 45533
 45534
 45535
 45536
 45537
 45538
 45539
 45540
 45541
 45542
 45543
 45544
 45545
 45546
 45547
 45548
 45549
 45550
 45551
 45552
 45553
 45554
 45555
 45556
 45557
 45558
 45559
 45560
 45561
 45562
 45563
 45564
 45565
 45566
 45567
 45568
 45569
 45570
 45571
 45572
 45573
 45574
 45575
 45576
 45577
 45578
 45579
 45580
 45581
 45582
 45583
 45584
 45585
 45586
 45587
 45588
 45589
 45590
 45591
 45592
 45593
 45594
 45595
 45596
 45597
 45598
 45599
 45600
 45601
 45602
 45603
 45604
 45605
 45606
 45607
 45608
 45609
 45610
 45611
 45612
 45613
 45614
 45615
 45616
 45617
 45618
 45619
 45620
 45621
 45622
 45623
 45624
 45625
 45626
 45627
 45628
 45629
 45630
 45631
 45632
 45633
 45634
 45635
 45636
 45637
 45638
 45639
 45640
 45641
 45642
 45643
 45644
 45645
 45646
 45647
 45648
 45649
 45650
 45651
 45652
 45653
 45654
 45655
 45656
 45657
 45658
 45659
 45660
 45661
 45662
 45663
 45664
 45665
 45666
 45667
 45668
 45669
 45670
 45671
 45672
 45673
 45674
 45675
 45676
 45677
 45678
 45679
 45680
 45681
 45682
 45683
 45684
 45685
 45686
 45687
 45688
 45689
 45690
 45691
 45692
 45693
 45694
 45695
 45696
 45697
 45698
 45699
 45700
 45701
 45702
 45703
 45704
 45705
 45706
 45707
 45708
 45709
 45710
 45711
 45712
 45713
 45714
 45715
 45716
 45717
 45718
 45719
 45720
 45721
 45722
 45723
 45724
 45725
 45726
 45727
 45728
 45729
 45730
 45731
 45732
 45733
 45734
 45735
 45736
 45737
 45738
 45739
 45740
 45741
 45742
 45743
 45744
 45745
 45746
 45747
 45748
 45749
 45750
 45751
 45752
 45753
 45754
 45755
 45756
 45757
 45758
 45759
 45760
 45761
 45762
 45763
 45764
 45765
 45766
 45767
 45768
 45769
 45770
 45771
 45772
 45773
 45774
 45775
 45776
 45777
 45778
 45779
 45780
 45781
 45782
 45783
 45784
 45785
 45786
 45787
 45788
 45789
 45790
 45791
 45792
 45793
 45794
 45795
 45796
 45797
 45798
 45799
 45800
 45801
 45802
 45803
 45804
 45805
 45806
 45807
 45808
 45809
 45810
 45811
 45812
 45813
 45814
 45815
 45816
 45817
 45818
 45819
 45820
 45821
 45822
 45823
 45824
 45825
 45826
 45827
 45828
 45829
 45830
 45831
 45832
 45833
 45834
 45835
 45836
 45837
 45838
 45839
 45840
 45841
 45842
 45843
 45844
 45845
 45846
 45847
 45848
 45849
 45850
 45851
 45852
 45853
 45854
 45855
 45856
 45857
 45858
 45859
 45860
 45861
 45862
 45863
 45864
 45865
 45866
 45867
 45868
 45869
 45870
 45871
 45872
 45873
 45874
 45875
 45876
 45877
 45878
 45879
 45880
 45881
 45882
 45883
 45884
 45885
 45886
 45887
 45888
 45889
 45890
 45891
 45892
 45893
 45894
 45895
 45896
 45897
 45898
 45899
 45900
 45901
 45902
 45903
 45904
 45905
 45906
 45907
 45908
 45909
 45910
 45911
 45912
 45913
 45914
 45915
 45916
 45917
 45918
 45919
 45920
 45921
 45922
 45923
 45924
 45925
 45926
 45927
 45928
 45929
 45930
 45931
 45932
 45933
 45934
 45935
 45936
 45937
 45938
 45939
 45940
 45941
 45942
 45943
 45944
 45945
 45946
 45947
 45948
 45949
 45950
 45951
 45952
 45953
 45954
 45955
 45956
 45957
 45958
 45959
 45960
 45961
 45962
 45963
 45964
 45965
 45966
 45967
 45968
 45969
 45970
 45971
 45972
 45973
 45974
 45975
 45976
 45977
 45978
 45979
 45980
 45981
 45982
 45983
 45984
 45985
 45986
 45987
 45988
 45989
 45990
 45991
 45992
 45993
 45994
 45995
 45996
 45997
 45998
 45999
 46000
 46001
 46002
 46003
 46004
 46005
 46006
 46007
 46008
 46009
 46010
 46011
 46012
 46013
 46014
 46015
 46016
 46017
 46018
 46019
 46020
 46021
 46022
 46023
 46024
 46025
 46026
 46027
 46028
 46029
 46030
 46031
 46032
 46033
 46034
 46035
 46036
 46037
 46038
 46039
 46040
 46041
 46042
 46043
 46044
 46045
 46046
 46047
 46048
 46049
 46050
 46051
 46052
 46053
 46054
 46055
 46056
 46057
 46058
 46059
 46060
 46061
 46062
 46063
 46064
 46065
 46066
 46067
 46068
 46069
 46070
 46071
 46072
 46073
 46074
 46075
 46076
 46077
 46078
 46079
 46080
 46081
 46082
 46083
 46084
 46085
 46086
 46087
 46088
 46089
 46090
 46091
 46092
 46093
 46094
 46095
 46096
 46097
 46098
 46099
 46100
 46101
 46102
 46103
 46104
 46105
 46106
 46107
 46108
 46109
 46110
 46111
 46112
 46113
 46114
 46115
 46116
 46117
 46118
 46119
 46120
 46121
 46122
 46123
 46124
 46125
 46126
 46127
 46128
 46129
 46130
 46131
 46132
 46133
 46134
 46135
 46136
 46137
 46138
 46139
 46140
 46141
 46142
 46143
 46144
 46145
 46146
 46147
 46148
 46149
 46150
 46151
 46152
 46153
 46154
 46155
 46156
 46157
 46158
 46159
 46160
 46161
 46162
 46163
 46164
 46165
 46166
 46167
 46168
 46169
 46170
 46171
 46172
 46173
 46174
 46175
 46176
 46177
 46178
 46179
 46180
 46181
 46182
 46183
 46184
 46185
 46186
 46187
 46188
 46189
 46190
 46191
 46192
 46193
 46194
 46195
 46196
 46197
 46198
 46199
 46200
 46201
 46202
 46203
 46204
 46205
 46206
 46207
 46208
 46209
 46210
 46211
 46212
 46213
 46214
 46215
 46216
 46217
 46218
 46219
 46220
 46221
 46222
 46223
 46224
 46225
 46226
 46227
 46228
 46229
 46230
 46231
 46232
 46233
 46234
 46235
 46236
 46237
 46238
 46239
 46240
 46241
 46242
 46243
 46244
 46245
 46246
 46247
 46248
 46249
 46250
 46251
 46252
 46253
 46254
 46255
 46256
 46257
 46258
 46259
 46260
 46261
 46262
 46263
 46264
 46265
 46266
 46267
 46268
 46269
 46270
 46271
 46272
 46273
 46274
 46275
 46276
 46277
 46278
 46279
 46280
 46281
 46282
 46283
 46284
 46285
 46286
 46287
 46288
 46289
 46290
 46291
 46292
 46293
 46294
 46295
 46296
 46297
 46298
 46299
 46300
 46301
 46302
 46303
 46304
 46305
 46306
 46307
 46308
 46309
 46310
 46311
 46312
 46313
 46314
 46315
 46316
 46317
 46318
 46319
 46320
 46321
 46322
 46323
 46324
 46325
 46326
 46327
 46328
 46329
 46330
 46331
 46332
 46333
 46334
 46335
 46336
 46337
 46338
 46339
 46340
 46341
 46342
 46343
 46344
 46345
 46346
 46347
 46348
 46349
 46350
 46351
 46352
 46353
 46354
 46355
 46356
 46357
 46358
 46359
 46360
 46361
 46362
 46363
 46364
 46365
 46366
 46367
 46368
 46369
 46370
 46371
 46372
 46373
 46374
 46375
 46376
 46377
 46378
 46379
 46380
 46381
 46382
 46383
 46384
 46385
 46386
 46387
 46388
 46389
 46390
 46391
 46392
 46393
 46394
 46395
 46396
 46397
 46398
 46399
 46400
 46401
 46402
 46403
 46404
 46405
 46406
 46407
 46408
 46409
 46410
 46411
 46412
 46413
 46414
 46415
 46416
 46417
 46418
 46419
 46420
 46421
 46422
 46423
 46424
 46425
 46426
 46427
 46428
 46429
 46430
 46431
 46432
 46433
 46434
 46435
 46436
 46437
 46438
 46439
 46440
 46441
 46442
 46443
 46444
 46445
 46446
 46447
 46448
 46449
 46450
 46451
 46452
 46453
 46454
 46455
 46456
 46457
 46458
 46459
 46460
 46461
 46462
 46463
 46464
 46465
 46466
 46467
 46468
 46469
 46470
 46471
 46472
 46473
 46474
 46475
 46476
 46477
 46478
 46479
 46480
 46481
 46482
 46483
 46484
 46485
 46486
 46487
 46488
 46489
 46490
 46491
 46492
 46493
 46494
 46495
 46496
 46497
 46498
 46499
 46500
 46501
 46502
 46503
 46504
 46505
 46506
 46507
 46508
 46509
 46510
 46511
 46512
 46513
 46514
 46515
 46516
 46517
 46518
 46519
 46520
 46521
 46522
 46523
 46524
 46525
 46526
 46527
 46528
 46529
 46530
 46531
 46532
 46533
 46534
 46535
 46536
 46537
 46538
 46539
 46540
 46541
 46542
 46543
 46544
 46545
 46546
 46547
 46548
 46549
 46550
 46551
 46552
 46553
 46554
 46555
 46556
 46557
 46558
 46559
 46560
 46561
 46562
 46563
 46564
 46565
 46566
 46567
 46568
 46569
 46570
 46571
 46572
 46573
 46574
 46575
 46576
 46577
 46578
 46579
 46580
 46581
 46582
 46583
 46584
 46585
 46586
 46587
 46588
 46589
 46590
 46591
 46592
 46593
 46594
 46595
 46596
 46597
 46598
 46599
 46600
 46601
 46602
 46603
 46604
 46605
 46606
 46607
 46608
 46609
 46610
 46611
 46612
 46613
 46614
 46615
 46616
 46617
 46618
 46619
 46620
 46621
 46622
 46623
 46624
 46625
 46626
 46627
 46628
 46629
 46630
 46631
 46632
 46633
 46634
 46635
 46636
 46637
 46638
 46639
 46640
 46641
 46642
 46643
 46644
 46645
 46646
 46647
 46648
 46649
 46650
 46651
 46652
 46653
 46654
 46655
 46656
 46657
 46658
 46659
 46660
 46661
 46662
 46663
 46664
 46665
 46666
 46667
 46668
 46669
 46670
 46671
 46672
 46673
 46674
 46675
 46676
 46677
 46678
 46679
 46680
 46681
 46682
 46683
 46684
 46685
 46686
 46687
 46688
 46689
 46690
 46691
 46692
 46693
 46694
 46695
 46696
 46697
 46698
 46699
 46700
 46701
 46702
 46703
 46704
 46705
 46706
 46707
 46708
 46709
 46710
 46711
 46712
 46713
 46714
 46715
 46716
 46717
 46718
 46719
 46720
 46721
 46722
 46723
 46724
 46725
 46726
 46727
 46728
 46729
 46730
 46731
 46732
 46733
 46734
 46735
 46736
 46737
 46738
 46739
 46740
 46741
 46742
 46743
 46744
 46745
 46746
 46747
 46748
 46749
 46750
 46751
 46752
 46753
 46754
 46755
 46756
 46757
 46758
 46759
 46760
 46761
 46762
 46763
 46764
 46765
 46766
 46767
 46768
 46769
 46770
 46771
 46772
 46773
 46774
 46775
 46776
 46777
 46778
 46779
 46780
 46781
 46782
 46783
 46784
 46785
 46786
 46787
 46788
 46789
 46790
 46791
 46792
 46793
 46794
 46795
 46796
 46797
 46798
 46799
 46800
 46801
 46802
 46803
 46804
 46805
 46806
 46807
 46808
 46809
 46810
 46811
 46812
 46813
 46814
 46815
 46816
 46817
 46818
 46819
 46820
 46821
 46822
 46823
 46824
 46825
 46826
 46827
 46828
 46829
 46830
 46831
 46832
 46833
 46834
 46835
 46836
 46837
 46838
 46839
 46840
 46841
 46842
 46843
 46844
 46845
 46846
 46847
 46848
 46849
 46850
 46851
 46852
 46853
 46854
 46855
 46856
 46857
 46858
 46859
 46860
 46861
 46862
 46863
 46864
 46865
 46866
 46867
 46868
 46869
 46870
 46871
 46872
 46873
 46874
 46875
 46876
 46877
 46878
 46879
 46880
 46881
 46882
 46883
 46884
 46885
 46886
 46887
 46888
 46889
 46890
 46891
 46892
 46893
 46894
 46895
 46896
 46897
 46898
 46899
 46900
 46901
 46902
 46903
 46904
 46905
 46906
 46907
 46908
 46909
 46910
 46911
 46912
 46913
 46914
 46915
 46916
 46917
 46918
 46919
 46920
 46921
 46922
 46923
 46924
 46925
 46926
 46927
 46928
 46929
 46930
 46931
 46932
 46933
 46934
 46935
 46936
 46937
 46938
 46939
 46940
 46941
 46942
 46943
 46944
 46945
 46946
 46947
 46948
 46949
 46950
 46951
 46952
 46953
 46954
 46955
 46956
 46957
 46958
 46959
 46960
 46961
 46962
 46963
 46964
 46965
 46966
 46967
 46968
 46969
 46970
 46971
 46972
 46973
 46974
 46975
 46976
 46977
 46978
 46979
 46980
 46981
 46982
 46983
 46984
 46985
 46986
 46987
 46988
 46989
 46990
 46991
 46992
 46993
 46994
 46995
 46996
 46997
 46998
 46999
 47000
 47001
 47002
 47003
 47004
 47005
 47006
 47007
 47008
 47009
 47010
 47011
 47012
 47013
 47014
 47015
 47016
 47017
 47018
 47019
 47020
 47021
 47022
 47023
 47024
 47025
 47026
 47027
 47028
 47029
 47030
 47031
 47032
 47033
 47034
 47035
 47036
 47037
 47038
 47039
 47040
 47041
 47042
 47043
 47044
 47045
 47046
 47047
 47048
 47049
 47050
 47051
 47052
 47053
 47054
 47055
 47056
 47057
 47058
 47059
 47060
 47061
 47062
 47063
 47064
 47065
 47066
 47067
 47068
 47069
 47070
 47071
 47072
 47073
 47074
 47075
 47076
 47077
 47078
 47079
 47080
 47081
 47082
 47083
 47084
 47085
 47086
 47087
 47088
 47089
 47090
 47091
 47092
 47093
 47094
 47095
 47096
 47097
 47098
 47099
 47100
 47101
 47102
 47103
 47104
 47105
 47106
 47107
 47108
 47109
 47110
 47111
 47112
 47113
 47114
 47115
 47116
 47117
 47118
 47119
 47120
 47121
 47122
 47123
 47124
 47125
 47126
 47127
 47128
 47129
 47130
 47131
 47132
 47133
 47134
 47135
 47136
 47137
 47138
 47139
 47140
 47141
 47142
 47143
 47144
 47145
 47146
 47147
 47148
 47149
 47150
 47151
 47152
 47153
 47154
 47155
 47156
 47157
 47158
 47159
 47160
 47161
 47162
 47163
 47164
 47165
 47166
 47167
 47168
 47169
 47170
 47171
 47172
 47173
 47174
 47175
 47176
 47177
 47178
 47179
 47180
 47181
 47182
 47183
 47184
 47185
 47186
 47187
 47188
 47189
 47190
 47191
 47192
 47193
 47194
 47195
 47196
 47197
 47198
 47199
 47200
 47201
 47202
 47203
 47204
 47205
 47206
 47207
 47208
 47209
 47210
 47211
 47212
 47213
 47214
 47215
 47216
 47217
 47218
 47219
 47220
 47221
 47222
 47223
 47224
 47225
 47226
 47227
 47228
 47229
 47230
 47231
 47232
 47233
 47234
 47235
 47236
 47237
 47238
 47239
 47240
 47241
 47242
 47243
 47244
 47245
 47246
 47247
 47248
 47249
 47250
 47251
 47252
 47253
 47254
 47255
 47256
 47257
 47258
 47259
 47260
 47261
 47262
 47263
 47264
 47265
 47266
 47267
 47268
 47269
 47270
 47271
 47272
 47273
 47274
 47275
 47276
 47277
 47278
 47279
 47280
 47281
 47282
 47283
 47284
 47285
 47286
 47287
 47288
 47289
 47290
 47291
 47292
 47293
 47294
 47295
 47296
 47297
 47298
 47299
 47300
 47301
 47302
 47303
 47304
 47305
 47306
 47307
 47308
 47309
 47310
 47311
 47312
 47313
 47314
 47315
 47316
 47317
 47318
 47319
 47320
 47321
 47322
 47323
 47324
 47325
 47326
 47327
 47328
 47329
 47330
 47331
 47332
 47333
 47334
 47335
 47336
 47337
 47338
 47339
 47340
 47341
 47342
 47343
 47344
 47345
 47346
 47347
 47348
 47349
 47350
 47351
 47352
 47353
 47354
 47355
 47356
 47357
 47358
 47359
 47360
 47361
 47362
 47363
 47364
 47365
 47366
 47367
 47368
 47369
 47370
 47371
 47372
 47373
 47374
 47375
 47376
 47377
 47378
 47379
 47380
 47381
 47382
 47383
 47384
 47385
 47386
 47387
 47388
 47389
 47390
 47391
 47392
 47393
 47394
 47395
 47396
 47397
 47398
 47399
 47400
 47401
 47402
 47403
 47404
 47405
 47406
 47407
 47408
 47409
 47410
 47411
 47412
 47413
 47414
 47415
 47416
 47417
 47418
 47419
 47420
 47421
 47422
 47423
 47424
 47425
 47426
 47427
 47428
 47429
 47430
 47431
 47432
 47433
 47434
 47435
 47436
 47437
 47438
 47439
 47440
 47441
 47442
 47443
 47444
 47445
 47446
 47447
 47448
 47449
 47450
 47451
 47452
 47453
 47454
 47455
 47456
 47457
 47458
 47459
 47460
 47461
 47462
 47463
 47464
 47465
 47466
 47467
 47468
 47469
 47470
 47471
 47472
 47473
 47474
 47475
 47476
 47477
 47478
 47479
 47480
 47481
 47482
 47483
 47484
 47485
 47486
 47487
 47488
 47489
 47490
 47491
 47492
 47493
 47494
 47495
 47496
 47497
 47498
 47499
 47500
 47501
 47502
 47503
 47504
 47505
 47506
 47507
 47508
 47509
 47510
 47511
 47512
 47513
 47514
 47515
 47516
 47517
 47518
 47519
 47520
 47521
 47522
 47523
 47524
 47525
 47526
 47527
 47528
 47529
 47530
 47531
 47532
 47533
 47534
 47535
 47536
 47537
 47538
 47539
 47540
 47541
 47542
 47543
 47544
 47545
 47546
 47547
 47548
 47549
 47550
 47551
 47552
 47553
 47554
 47555
 47556
 47557
 47558
 47559
 47560
 47561
 47562
 47563
 47564
 47565
 47566
 47567
 47568
 47569
 47570
 47571
 47572
 47573
 47574
 47575
 47576
 47577
 47578
 47579
 47580
 47581
 47582
 47583
 47584
 47585
 47586
 47587
 47588
 47589
 47590
 47591
 47592
 47593
 47594
 47595
 47596
 47597
 47598
 47599
 47600
 47601
 47602
 47603
 47604
 47605
 47606
 47607
 47608
 47609
 47610
 47611
 47612
 47613
 47614
 47615
 47616
 47617
 47618
 47619
 47620
 47621
 47622
 47623
 47624
 47625
 47626
 47627
 47628
 47629
 47630
 47631
 47632
 47633
 47634
 47635
 47636
 47637
 47638
 47639
 47640
 47641
 47642
 47643
 47644
 47645
 47646
 47647
 47648
 47649
 47650
 47651
 47652
 47653
 47654
 47655
 47656
 47657
 47658
 47659
 47660
 47661
 47662
 47663
 47664
 47665
 47666
 47667
 47668
 47669
 47670
 47671
 47672
 47673
 47674
 47675
 47676
 47677
 47678
 47679
 47680
 47681
 47682
 47683
 47684
 47685
 47686
 47687
 47688
 47689
 47690
 47691
 47692
 47693
 47694
 47695
 47696
 47697
 47698
 47699
 47700
 47701
 47702
 47703
 47704
 47705
 47706
 47707
 47708
 47709
 47710
 47711
 47712
 47713
 47714
 47715
 47716
 47717
 47718
 47719
 47720
 47721
 47722
 47723
 47724
 47725
 47726
 47727
 47728
 47729
 47730
 47731
 47732
 47733
 47734
 47735
 47736
 47737
 47738
 47739
 47740
 47741
 47742
 47743
 47744
 47745
 47746
 47747
 47748
 47749
 47750
 47751
 47752
 47753
 47754
 47755
 47756
 47757
 47758
 47759
 47760
 47761
 47762
 47763
 47764
 47765
 47766
 47767
 47768
 47769
 47770
 47771
 47772
 47773
 47774
 47775
 47776
 47777
 47778
 47779
 47780
 47781
 47782
 47783
 47784
 47785
 47786
 47787
 47788
 47789
 47790
 47791
 47792
 47793
 47794
 47795
 47796
 47797
 47798
 47799
 47800
 47801
 47802
 47803
 47804
 47805
 47806
 47807
 47808
 47809
 47810
 47811
 47812
 47813
 47814
 47815
 47816
 47817
 47818
 47819
 47820
 47821
 47822
 47823
 47824
 47825
 47826
 47827
 47828
 47829
 47830
 47831
 47832
 47833
 47834
 47835
 47836
 47837
 47838
 47839
 47840
 47841
 47842
 47843
 47844
 47845
 47846
 47847
 47848
 47849
 47850
 47851
 47852
 47853
 47854
 47855
 47856
 47857
 47858
 47859
 47860
 47861
 47862
 47863
 47864
 47865
 47866
 47867
 47868
 47869
 47870
 47871
 47872
 47873
 47874
 47875
 47876
 47877
 47878
 47879
 47880
 47881
 47882
 47883
 47884
 47885
 47886
 47887
 47888
 47889
 47890
 47891
 47892
 47893
 47894
 47895
 47896
 47897
 47898
 47899
 47900
 47901
 47902
 47903
 47904
 47905
 47906
 47907
 47908
 47909
 47910
 47911
 47912
 47913
 47914
 47915
 47916
 47917
 47918
 47919
 47920
 47921
 47922
 47923
 47924
 47925
 47926
 47927
 47928
 47929
 47930
 47931
 47932
 47933
 47934
 47935
 47936
 47937
 47938
 47939
 47940
 47941
 47942
 47943
 47944
 47945
 47946
 47947
 47948
 47949
 47950
 47951
 47952
 47953
 47954
 47955
 47956
 47957
 47958
 47959
 47960
 47961
 47962
 47963
 47964
 47965
 47966
 47967
 47968
 47969
 47970
 47971
 47972
 47973
 47974
 47975
 47976
 47977
 47978
 47979
 47980
 47981
 47982
 47983
 47984
 47985
 47986
 47987
 47988
 47989
 47990
 47991
 47992
 47993
 47994
 47995
 47996
 47997
 47998
 47999
 48000
 48001
 48002
 48003
 48004
 48005
 48006
 48007
 48008
 48009
 48010
 48011
 48012
 48013
 48014
 48015
 48016
 48017
 48018
 48019
 48020
 48021
 48022
 48023
 48024
 48025
 48026
 48027
 48028
 48029
 48030
 48031
 48032
 48033
 48034
 48035
 48036
 48037
 48038
 48039
 48040
 48041
 48042
 48043
 48044
 48045
 48046
 48047
 48048
 48049
 48050
 48051
 48052
 48053
 48054
 48055
 48056
 48057
 48058
 48059
 48060
 48061
 48062
 48063
 48064
 48065
 48066
 48067
 48068
 48069
 48070
 48071
 48072
 48073
 48074
 48075
 48076
 48077
 48078
 48079
 48080
 48081
 48082
 48083
 48084
 48085
 48086
 48087
 48088
 48089
 48090
 48091
 48092
 48093
 48094
 48095
 48096
 48097
 48098
 48099
 48100
 48101
 48102
 48103
 48104
 48105
 48106
 48107
 48108
 48109
 48110
 48111
 48112
 48113
 48114
 48115
 48116
 48117
 48118
 48119
 48120
 48121
 48122
 48123
 48124
 48125
 48126
 48127
 48128
 48129
 48130
 48131
 48132
 48133
 48134
 48135
 48136
 48137
 48138
 48139
 48140
 48141
 48142
 48143
 48144
 48145
 48146
 48147
 48148
 48149
 48150
 48151
 48152
 48153
 48154
 48155
 48156
 48157
 48158
 48159
 48160
 48161
 48162
 48163
 48164
 48165
 48166
 48167
 48168
 48169
 48170
 48171
 48172
 48173
 48174
 48175
 48176
 48177
 48178
 48179
 48180
 48181
 48182
 48183
 48184
 48185
 48186
 48187
 48188
 48189
 48190
 48191
 48192
 48193
 48194
 48195
 48196
 48197
 48198
 48199
 48200
 48201
 48202
 48203
 48204
 48205
 48206
 48207
 48208
 48209
 48210
 48211
 48212
 48213
 48214
 48215
 48216
 48217
 48218
 48219
 48220
 48221
 48222
 48223
 48224
 48225
 48226
 48227
 48228
 48229
 48230
 48231
 48232
 48233
 48234
 48235
 48236
 48237
 48238
 48239
 48240
 48241
 48242
 48243
 48244
 48245
 48246
 48247
 48248
 48249
 48250
 48251
 48252
 48253
 48254
 48255
 48256
 48257
 48258
 48259
 48260
 48261
 48262
 48263
 48264
 48265
 48266
 48267
 48268
 48269
 48270
 48271
 48272
 48273
 48274
 48275
 48276
 48277
 48278
 48279
 48280
 48281
 48282
 48283
 48284
 48285
 48286
 48287
 48288
 48289
 48290
 48291
 48292
 48293
 48294
 48295
 48296
 48297
 48298
 48299
 48300
 48301
 48302
 48303
 48304
 48305
 48306
 48307
 48308
 48309
 48310
 48311
 48312
 48313
 48314
 48315
 48316
 48317
 48318
 48319
 48320
 48321
 48322
 48323
 48324
 48325
 48326
 48327
 48328
 48329
 48330
 48331
 48332
 48333
 48334
 48335
 48336
 48337
 48338
 48339
 48340
 48341
 48342
 48343
 48344
 48345
 48346
 48347
 48348
 48349
 48350
 48351
 48352
 48353
 48354
 48355
 48356
 48357
 48358
 48359
 48360
 48361
 48362
 48363
 48364
 48365
 48366
 48367
 48368
 48369
 48370
 48371
 48372
 48373
 48374
 48375
 48376
 48377
 48378
 48379
 48380
 48381
 48382
 48383
 48384
 48385
 48386
 48387
 48388
 48389
 48390
 48391
 48392
 48393
 48394
 48395
 48396
 48397
 48398
 48399
 48400
 48401
 48402
 48403
 48404
 48405
 48406
 48407
 48408
 48409
 48410
 48411
 48412
 48413
 48414
 48415
 48416
 48417
 48418
 48419
 48420
 48421
 48422
 48423
 48424
 48425
 48426
 48427
 48428
 48429
 48430
 48431
 48432
 48433
 48434
 48435
 48436
 48437
 48438
 48439
 48440
 48441
 48442
 48443
 48444
 48445
 48446
 48447
 48448
 48449
 48450
 48451
 48452
 48453
 48454
 48455
 48456
 48457
 48458
 48459
 48460
 48461
 48462
 48463
 48464
 48465
 48466
 48467
 48468
 48469
 48470
 48471
 48472
 48473
 48474
 48475
 48476
 48477
 48478
 48479
 48480
 48481
 48482
 48483
 48484
 48485
 48486
 48487
 48488
 48489
 48490
 48491
 48492
 48493
 48494
 48495
 48496
 48497
 48498
 48499
 48500
 48501
 48502
 48503
 48504
 48505
 48506
 48507
 48508
 48509
 48510
 48511
 48512
 48513
 48514
 48515
 48516
 48517
 48518
 48519
 48520
 48521
 48522
 48523
 48524
 48525
 48526
 48527
 48528
 48529
 48530
 48531
 48532
 48533
 48534
 48535
 48536
 48537
 48538
 48539
 48540
 48541
 48542
 48543
 48544
 48545
 48546
 48547
 48548
 48549
 48550
 48551
 48552
 48553
 48554
 48555
 48556
 48557
 48558
 48559
 48560
 48561
 48562
 48563
 48564
 48565
 48566
 48567
 48568
 48569
 48570
 48571
 48572
 48573
 48574
 48575
 48576
 48577
 48578
 48579
 48580
 48581
 48582
 48583
 48584
 48585
 48586
 48587
 48588
 48589
 48590
 48591
 48592
 48593
 48594
 48595
 48596
 48597
 48598
 48599
 48600
 48601
 48602
 48603
 48604
 48605
 48606
 48607
 48608
 48609
 48610
 48611
 48612
 48613
 48614
 48615
 48616
 48617
 48618
 48619
 48620
 48621
 48622
 48623
 48624
 48625
 48626
 48627
 48628
 48629
 48630
 48631
 48632
 48633
 48634
 48635
 48636
 48637
 48638
 48639
 48640
 48641
 48642
 48643
 48644
 48645
 48646
 48647
 48648
 48649
 48650
 48651
 48652
 48653
 48654
 48655
 48656
 48657
 48658
 48659
 48660
 48661
 48662
 48663
 48664
 48665
 48666
 48667
 48668
 48669
 48670
 48671
 48672
 48673
 48674
 48675
 48676
 48677
 48678
 48679
 48680
 48681
 48682
 48683
 48684
 48685
 48686
 48687
 48688
 48689
 48690
 48691
 48692
 48693
 48694
 48695
 48696
 48697
 48698
 48699
 48700
 48701
 48702
 48703
 48704
 48705
 48706
 48707
 48708
 48709
 48710
 48711
 48712
 48713
 48714
 48715
 48716
 48717
 48718
 48719
 48720
 48721
 48722
 48723
 48724
 48725
 48726
 48727
 48728
 48729
 48730
 48731
 48732
 48733
 48734
 48735
 48736
 48737
 48738
 48739
 48740
 48741
 48742
 48743
 48744
 48745
 48746
 48747
 48748
 48749
 48750
 48751
 48752
 48753
 48754
 48755
 48756
 48757
 48758
 48759
 48760
 48761
 48762
 48763
 48764
 48765
 48766
 48767
 48768
 48769
 48770
 48771
 48772
 48773
 48774
 48775
 48776
 48777
 48778
 48779
 48780
 48781
 48782
 48783
 48784
 48785
 48786
 48787
 48788
 48789
 48790
 48791
 48792
 48793
 48794
 48795
 48796
 48797
 48798
 48799
 48800
 48801
 48802
 48803
 48804
 48805
 48806
 48807
 48808
 48809
 48810
 48811
 48812
 48813
 48814
 48815
 48816
 48817
 48818
 48819
 48820
 48821
 48822
 48823
 48824
 48825
 48826
 48827
 48828
 48829
 48830
 48831
 48832
 48833
 48834
 48835
 48836
 48837
 48838
 48839
 48840
 48841
 48842
 48843
 48844
 48845
 48846
 48847
 48848
 48849
 48850
 48851
 48852
 48853
 48854
 48855
 48856
 48857
 48858
 48859
 48860
 48861
 48862
 48863
 48864
 48865
 48866
 48867
 48868
 48869
 48870
 48871
 48872
 48873
 48874
 48875
 48876
 48877
 48878
 48879
 48880
 48881
 48882
 48883
 48884
 48885
 48886
 48887
 48888
 48889
 48890
 48891
 48892
 48893
 48894
 48895
 48896
 48897
 48898
 48899
 48900
 48901
 48902
 48903
 48904
 48905
 48906
 48907
 48908
 48909
 48910
 48911
 48912
 48913
 48914
 48915
 48916
 48917
 48918
 48919
 48920
 48921
 48922
 48923
 48924
 48925
 48926
 48927
 48928
 48929
 48930
 48931
 48932
 48933
 48934
 48935
 48936
 48937
 48938
 48939
 48940
 48941
 48942
 48943
 48944
 48945
 48946
 48947
 48948
 48949
 48950
 48951
 48952
 48953
 48954
 48955
 48956
 48957
 48958
 48959
 48960
 48961
 48962
 48963
 48964
 48965
 48966
 48967
 48968
 48969
 48970
 48971
 48972
 48973
 48974
 48975
 48976
 48977
 48978
 48979
 48980
 48981
 48982
 48983
 48984
 48985
 48986
 48987
 48988
 48989
 48990
 48991
 48992
 48993
 48994
 48995
 48996
 48997
 48998
 48999
 49000
 49001
 49002
 49003
 49004
 49005
 49006
 49007
 49008
 49009
 49010
 49011
 49012
 49013
 49014
 49015
 49016
 49017
 49018
 49019
 49020
 49021
 49022
 49023
 49024
 49025
 49026
 49027
 49028
 49029
 49030
 49031
 49032
 49033
 49034
 49035
 49036
 49037
 49038
 49039
 49040
 49041
 49042
 49043
 49044
 49045
 49046
 49047
 49048
 49049
 49050
 49051
 49052
 49053
 49054
 49055
 49056
 49057
 49058
 49059
 49060
 49061
 49062
 49063
 49064
 49065
 49066
 49067
 49068
 49069
 49070
 49071
 49072
 49073
 49074
 49075
 49076
 49077
 49078
 49079
 49080
 49081
 49082
 49083
 49084
 49085
 49086
 49087
 49088
 49089
 49090
 49091
 49092
 49093
 49094
 49095
 49096
 49097
 49098
 49099
 49100
 49101
 49102
 49103
 49104
 49105
 49106
 49107
 49108
 49109
 49110
 49111
 49112
 49113
 49114
 49115
 49116
 49117
 49118
 49119
 49120
 49121
 49122
 49123
 49124
 49125
 49126
 49127
 49128
 49129
 49130
 49131
 49132
 49133
 49134
 49135
 49136
 49137
 49138
 49139
 49140
 49141
 49142
 49143
 49144
 49145
 49146
 49147
 49148
 49149
 49150
 49151
 49152
 49153
 49154
 49155
 49156
 49157
 49158
 49159
 49160
 49161
 49162
 49163
 49164
 49165
 49166
 49167
 49168
 49169
 49170
 49171
 49172
 49173
 49174
 49175
 49176
 49177
 49178
 49179
 49180
 49181
 49182
 49183
 49184
 49185
 49186
 49187
 49188
 49189
 49190
 49191
 49192
 49193
 49194
 49195
 49196
 49197
 49198
 49199
 49200
 49201
 49202
 49203
 49204
 49205
 49206
 49207
 49208
 49209
 49210
 49211
 49212
 49213
 49214
 49215
 49216
 49217
 49218
 49219
 49220
 49221
 49222
 49223
 49224
 49225
 49226
 49227
 49228
 49229
 49230
 49231
 49232
 49233
 49234
 49235
 49236
 49237
 49238
 49239
 49240
 49241
 49242
 49243
 49244
 49245
 49246
 49247
 49248
 49249
 49250
 49251
 49252
 49253
 49254
 49255
 49256
 49257
 49258
 49259
 49260
 49261
 49262
 49263
 49264
 49265
 49266
 49267
 49268
 49269
 49270
 49271
 49272
 49273
 49274
 49275
 49276
 49277
 49278
 49279
 49280
 49281
 49282
 49283
 49284
 49285
 49286
 49287
 49288
 49289
 49290
 49291
 49292
 49293
 49294
 49295
 49296
 49297
 49298
 49299
 49300
 49301
 49302
 49303
 49304
 49305
 49306
 49307
 49308
 49309
 49310
 49311
 49312
 49313
 49314
 49315
 49316
 49317
 49318
 49319
 49320
 49321
 49322
 49323
 49324
 49325
 49326
 49327
 49328
 49329
 49330
 49331
 49332
 49333
 49334
 49335
 49336
 49337
 49338
 49339
 49340
 49341
 49342
 49343
 49344
 49345
 49346
 49347
 49348
 49349
 49350
 49351
 49352
 49353
 49354
 49355
 49356
 49357
 49358
 49359
 49360
 49361
 49362
 49363
 49364
 49365
 49366
 49367
 49368
 49369
 49370
 49371
 49372
 49373
 49374
 49375
 49376
 49377
 49378
 49379
 49380
 49381
 49382
 49383
 49384
 49385
 49386
 49387
 49388
 49389
 49390
 49391
 49392
 49393
 49394
 49395
 49396
 49397
 49398
 49399
 49400
 49401
 49402
 49403
 49404
 49405
 49406
 49407
 49408
 49409
 49410
 49411
 49412
 49413
 49414
 49415
 49416
 49417
 49418
 49419
 49420
 49421
 49422
 49423
 49424
 49425
 49426
 49427
 49428
 49429
 49430
 49431
 49432
 49433
 49434
 49435
 49436
 49437
 49438
 49439
 49440
 49441
 49442
 49443
 49444
 49445
 49446
 49447
 49448
 49449
 49450
 49451
 49452
 49453
 49454
 49455
 49456
 49457
 49458
 49459
 49460
 49461
 49462
 49463
 49464
 49465
 49466
 49467
 49468
 49469
 49470
 49471
 49472
 49473
 49474
 49475
 49476
 49477
 49478
 49479
 49480
 49481
 49482
 49483
 49484
 49485
 49486
 49487
 49488
 49489
 49490
 49491
 49492
 49493
 49494
 49495
 49496
 49497
 49498
 49499
 49500
 49501
 49502
 49503
 49504
 49505
 49506
 49507
 49508
 49509
 49510
 49511
 49512
 49513
 49514
 49515
 49516
 49517
 49518
 49519
 49520
 49521
 49522
 49523
 49524
 49525
 49526
 49527
 49528
 49529
 49530
 49531
 49532
 49533
 49534
 49535
 49536
 49537
 49538
 49539
 49540
 49541
 49542
 49543
 49544
 49545
 49546
 49547
 49548
 49549
 49550
 49551
 49552
 49553
 49554
 49555
 49556
 49557
 49558
 49559
 49560
 49561
 49562
 49563
 49564
 49565
 49566
 49567
 49568
 49569
 49570
 49571
 49572
 49573
 49574
 49575
 49576
 49577
 49578
 49579
 49580
 49581
 49582
 49583
 49584
 49585
 49586
 49587
 49588
 49589
 49590
 49591
 49592
 49593
 49594
 49595
 49596
 49597
 49598
 49599
 49600
 49601
 49602
 49603
 49604
 49605
 49606
 49607
 49608
 49609
 49610
 49611
 49612
 49613
 49614
 49615
 49616
 49617
 49618
 49619
 49620
 49621
 49622
 49623
 49624
 49625
 49626
 49627
 49628
 49629
 49630
 49631
 49632
 49633
 49634
 49635
 49636
 49637
 49638
 49639
 49640
 49641
 49642
 49643
 49644
 49645
 49646
 49647
 49648
 49649
 49650
 49651
 49652
 49653
 49654
 49655
 49656
 49657
 49658
 49659
 49660
 49661
 49662
 49663
 49664
 49665
 49666
 49667
 49668
 49669
 49670
 49671
 49672
 49673
 49674
 49675
 49676
 49677
 49678
 49679
 49680
 49681
 49682
 49683
 49684
 49685
 49686
 49687
 49688
 49689
 49690
 49691
 49692
 49693
 49694
 49695
 49696
 49697
 49698
 49699
 49700
 49701
 49702
 49703
 49704
 49705
 49706
 49707
 49708
 49709
 49710
 49711
 49712
 49713
 49714
 49715
 49716
 49717
 49718
 49719
 49720
 49721
 49722
 49723
 49724
 49725
 49726
 49727
 49728
 49729
 49730
 49731
 49732
 49733
 49734
 49735
 49736
 49737
 49738
 49739
 49740
 49741
 49742
 49743
 49744
 49745
 49746
 49747
 49748
 49749
 49750
 49751
 49752
 49753
 49754
 49755
 49756
 49757
 49758
 49759
 49760
 49761
 49762
 49763
 49764
 49765
 49766
 49767
 49768
 49769
 49770
 49771
 49772
 49773
 49774
 49775
 49776
 49777
 49778
 49779
 49780
 49781
 49782
 49783
 49784
 49785
 49786
 49787
 49788
 49789
 49790
 49791
 49792
 49793
 49794
 49795
 49796
 49797
 49798
 49799
 49800
 49801
 49802
 49803
 49804
 49805
 49806
 49807
 49808
 49809
 49810
 49811
 49812
 49813
 49814
 49815
 49816
 49817
 49818
 49819
 49820
 49821
 49822
 49823
 49824
 49825
 49826
 49827
 49828
 49829
 49830
 49831
 49832
 49833
 49834
 49835
 49836
 49837
 49838
 49839
 49840
 49841
 49842
 49843
 49844
 49845
 49846
 49847
 49848
 49849
 49850
 49851
 49852
 49853
 49854
 49855
 49856
 49857
 49858
 49859
 49860
 49861
 49862
 49863
 49864
 49865
 49866
 49867
 49868
 49869
 49870
 49871
 49872
 49873
 49874
 49875
 49876
 49877
 49878
 49879
 49880
 49881
 49882
 49883
 49884
 49885
 49886
 49887
 49888
 49889
 49890
 49891
 49892
 49893
 49894
 49895
 49896
 49897
 49898
 49899
 49900
 49901
 49902
 49903
 49904
 49905
 49906
 49907
 49908
 49909
 49910
 49911
 49912
 49913
 49914
 49915
 49916
 49917
 49918
 49919
 49920
 49921
 49922
 49923
 49924
 49925
 49926
 49927
 49928
 49929
 49930
 49931
 49932
 49933
 49934
 49935
 49936
 49937
 49938
 49939
 49940
 49941
 49942
 49943
 49944
 49945
 49946
 49947
 49948
 49949
 49950
 49951
 49952
 49953
 49954
 49955
 49956
 49957
 49958
 49959
 49960
 49961
 49962
 49963
 49964
 49965
 49966
 49967
 49968
 49969
 49970
 49971
 49972
 49973
 49974
 49975
 49976
 49977
 49978
 49979
 49980
 49981
 49982
 49983
 49984
 49985
 49986
 49987
 49988
 49989
 49990
 49991
 49992
 49993
 49994
 49995
 49996
 49997
 49998
 49999
 50000
 50001
 50002
 50003
 50004
 50005
 50006
 50007
 50008
 50009
 50010
 50011
 50012
 50013
 50014
 50015
 50016
 50017
 50018
 50019
 50020
 50021
 50022
 50023
 50024
 50025
 50026
 50027
 50028
 50029
 50030
 50031
 50032
 50033
 50034
 50035
 50036
 50037
 50038
 50039
 50040
 50041
 50042
 50043
 50044
 50045
 50046
 50047
 50048
 50049
 50050
 50051
 50052
 50053
 50054
 50055
 50056
 50057
 50058
 50059
 50060
 50061
 50062
 50063
 50064
 50065
 50066
 50067
 50068
 50069
 50070
 50071
 50072
 50073
 50074
 50075
 50076
 50077
 50078
 50079
 50080
 50081
 50082
 50083
 50084
 50085
 50086
 50087
 50088
 50089
 50090
 50091
 50092
 50093
 50094
 50095
 50096
 50097
 50098
 50099
 50100
 50101
 50102
 50103
 50104
 50105
 50106
 50107
 50108
 50109
 50110
 50111
 50112
 50113
 50114
 50115
 50116
 50117
 50118
 50119
 50120
 50121
 50122
 50123
 50124
 50125
 50126
 50127
 50128
 50129
 50130
 50131
 50132
 50133
 50134
 50135
 50136
 50137
 50138
 50139
 50140
 50141
 50142
 50143
 50144
 50145
 50146
 50147
 50148
 50149
 50150
 50151
 50152
 50153
 50154
 50155
 50156
 50157
 50158
 50159
 50160
 50161
 50162
 50163
 50164
 50165
 50166
 50167
 50168
 50169
 50170
 50171
 50172
 50173
 50174
 50175
 50176
 50177
 50178
 50179
 50180
 50181
 50182
 50183
 50184
 50185
 50186
 50187
 50188
 50189
 50190
 50191
 50192
 50193
 50194
 50195
 50196
 50197
 50198
 50199
 50200
 50201
 50202
 50203
 50204
 50205
 50206
 50207
 50208
 50209
 50210
 50211
 50212
 50213
 50214
 50215
 50216
 50217
 50218
 50219
 50220
 50221
 50222
 50223
 50224
 50225
 50226
 50227
 50228
 50229
 50230
 50231
 50232
 50233
 50234
 50235
 50236
 50237
 50238
 50239
 50240
 50241
 50242
 50243
 50244
 50245
 50246
 50247
 50248
 50249
 50250
 50251
 50252
 50253
 50254
 50255
 50256
 50257
 50258
 50259
 50260
 50261
 50262
 50263
 50264
 50265
 50266
 50267
 50268
 50269
 50270
 50271
 50272
 50273
 50274
 50275
 50276
 50277
 50278
 50279
 50280
 50281
 50282
 50283
 50284
 50285
 50286
 50287
 50288
 50289
 50290
 50291
 50292
 50293
 50294
 50295
 50296
 50297
 50298
 50299
 50300
 50301
 50302
 50303
 50304
 50305
 50306
 50307
 50308
 50309
 50310
 50311
 50312
 50313
 50314
 50315
 50316
 50317
 50318
 50319
 50320
 50321
 50322
 50323
 50324
 50325
 50326
 50327
 50328
 50329
 50330
 50331
 50332
 50333
 50334
 50335
 50336
 50337
 50338
 50339
 50340
 50341
 50342
 50343
 50344
 50345
 50346
 50347
 50348
 50349
 50350
 50351
 50352
 50353
 50354
 50355
 50356
 50357
 50358
 50359
 50360
 50361
 50362
 50363
 50364
 50365
 50366
 50367
 50368
 50369
 50370
 50371
 50372
 50373
 50374
 50375
 50376
 50377
 50378
 50379
 50380
 50381
 50382
 50383
 50384
 50385
 50386
 50387
 50388
 50389
 50390
 50391
 50392
 50393
 50394
 50395
 50396
 50397
 50398
 50399
 50400
 50401
 50402
 50403
 50404
 50405
 50406
 50407
 50408
 50409
 50410
 50411
 50412
 50413
 50414
 50415
 50416
 50417
 50418
 50419
 50420
 50421
 50422
 50423
 50424
 50425
 50426
 50427
 50428
 50429
 50430
 50431
 50432
 50433
 50434
 50435
 50436
 50437
 50438
 50439
 50440
 50441
 50442
 50443
 50444
 50445
 50446
 50447
 50448
 50449
 50450
 50451
 50452
 50453
 50454
 50455
 50456
 50457
 50458
 50459
 50460
 50461
 50462
 50463
 50464
 50465
 50466
 50467
 50468
 50469
 50470
 50471
 50472
 50473
 50474
 50475
 50476
 50477
 50478
 50479
 50480
 50481
 50482
 50483
 50484
 50485
 50486
 50487
 50488
 50489
 50490
 50491
 50492
 50493
 50494
 50495
 50496
 50497
 50498
 50499
 50500
 50501
 50502
 50503
 50504
 50505
 50506
 50507
 50508
 50509
 50510
 50511
 50512
 50513
 50514
 50515
 50516
 50517
 50518
 50519
 50520
 50521
 50522
 50523
 50524
 50525
 50526
 50527
 50528
 50529
 50530
 50531
 50532
 50533
 50534
 50535
 50536
 50537
 50538
 50539
 50540
 50541
 50542
 50543
 50544
 50545
 50546
 50547
 50548
 50549
 50550
 50551
 50552
 50553
 50554
 50555
 50556
 50557
 50558
 50559
 50560
 50561
 50562
 50563
 50564
 50565
 50566
 50567
 50568
 50569
 50570
 50571
 50572
 50573
 50574
 50575
 50576
 50577
 50578
 50579
 50580
 50581
 50582
 50583
 50584
 50585
 50586
 50587
 50588
 50589
 50590
 50591
 50592
 50593
 50594
 50595
 50596
 50597
 50598
 50599
 50600
 50601
 50602
 50603
 50604
 50605
 50606
 50607
 50608
 50609
 50610
 50611
 50612
 50613
 50614
 50615
 50616
 50617
 50618
 50619
 50620
 50621
 50622
 50623
 50624
 50625
 50626
 50627
 50628
 50629
 50630
 50631
 50632
 50633
 50634
 50635
 50636
 50637
 50638
 50639
 50640
 50641
 50642
 50643
 50644
 50645
 50646
 50647
 50648
 50649
 50650
 50651
 50652
 50653
 50654
 50655
 50656
 50657
 50658
 50659
 50660
 50661
 50662
 50663
 50664
 50665
 50666
 50667
 50668
 50669
 50670
 50671
 50672
 50673
 50674
 50675
 50676
 50677
 50678
 50679
 50680
 50681
 50682
 50683
 50684
 50685
 50686
 50687
 50688
 50689
 50690
 50691
 50692
 50693
 50694
 50695
 50696
 50697
 50698
 50699
 50700
 50701
 50702
 50703
 50704
 50705
 50706
 50707
 50708
 50709
 50710
 50711
 50712
 50713
 50714
 50715
 50716
 50717
 50718
 50719
 50720
 50721
 50722
 50723
 50724
 50725
 50726
 50727
 50728
 50729
 50730
 50731
 50732
 50733
 50734
 50735
 50736
 50737
 50738
 50739
 50740
 50741
 50742
 50743
 50744
 50745
 50746
 50747
 50748
 50749
 50750
 50751
 50752
 50753
 50754
 50755
 50756
 50757
 50758
 50759
 50760
 50761
 50762
 50763
 50764
 50765
 50766
 50767
 50768
 50769
 50770
 50771
 50772
 50773
 50774
 50775
 50776
 50777
 50778
 50779
 50780
 50781
 50782
 50783
 50784
 50785
 50786
 50787
 50788
 50789
 50790
 50791
 50792
 50793
 50794
 50795
 50796
 50797
 50798
 50799
 50800
 50801
 50802
 50803
 50804
 50805
 50806
 50807
 50808
 50809
 50810
 50811
 50812
 50813
 50814
 50815
 50816
 50817
 50818
 50819
 50820
 50821
 50822
 50823
 50824
 50825
 50826
 50827
 50828
 50829
 50830
 50831
 50832
 50833
 50834
 50835
 50836
 50837
 50838
 50839
 50840
 50841
 50842
 50843
 50844
 50845
 50846
 50847
 50848
 50849
 50850
 50851
 50852
 50853
 50854
 50855
 50856
 50857
 50858
 50859
 50860
 50861
 50862
 50863
 50864
 50865
 50866
 50867
 50868
 50869
 50870
 50871
 50872
 50873
 50874
 50875
 50876
 50877
 50878
 50879
 50880
 50881
 50882
 50883
 50884
 50885
 50886
 50887
 50888
 50889
 50890
 50891
 50892
 50893
 50894
 50895
 50896
 50897
 50898
 50899
 50900
 50901
 50902
 50903
 50904
 50905
 50906
 50907
 50908
 50909
 50910
 50911
 50912
 50913
 50914
 50915
 50916
 50917
 50918
 50919
 50920
 50921
 50922
 50923
 50924
 50925
 50926
 50927
 50928
 50929
 50930
 50931
 50932
 50933
 50934
 50935
 50936
 50937
 50938
 50939
 50940
 50941
 50942
 50943
 50944
 50945
 50946
 50947
 50948
 50949
 50950
 50951
 50952
 50953
 50954
 50955
 50956
 50957
 50958
 50959
 50960
 50961
 50962
 50963
 50964
 50965
 50966
 50967
 50968
 50969
 50970
 50971
 50972
 50973
 50974
 50975
 50976
 50977
 50978
 50979
 50980
 50981
 50982
 50983
 50984
 50985
 50986
 50987
 50988
 50989
 50990
 50991
 50992
 50993
 50994
 50995
 50996
 50997
 50998
 50999
 51000
 51001
 51002
 51003
 51004
 51005
 51006
 51007
 51008
 51009
 51010
 51011
 51012
 51013
 51014
 51015
 51016
 51017
 51018
 51019
 51020
 51021
 51022
 51023
 51024
 51025
 51026
 51027
 51028
 51029
 51030
 51031
 51032
 51033
 51034
 51035
 51036
 51037
 51038
 51039
 51040
 51041
 51042
 51043
 51044
 51045
 51046
 51047
 51048
 51049
 51050
 51051
 51052
 51053
 51054
 51055
 51056
 51057
 51058
 51059
 51060
 51061
 51062
 51063
 51064
 51065
 51066
 51067
 51068
 51069
 51070
 51071
 51072
 51073
 51074
 51075
 51076
 51077
 51078
 51079
 51080
 51081
 51082
 51083
 51084
 51085
 51086
 51087
 51088
 51089
 51090
 51091
 51092
 51093
 51094
 51095
 51096
 51097
 51098
 51099
 51100
 51101
 51102
 51103
 51104
 51105
 51106
 51107
 51108
 51109
 51110
 51111
 51112
 51113
 51114
 51115
 51116
 51117
 51118
 51119
 51120
 51121
 51122
 51123
 51124
 51125
 51126
 51127
 51128
 51129
 51130
 51131
 51132
 51133
 51134
 51135
 51136
 51137
 51138
 51139
 51140
 51141
 51142
 51143
 51144
 51145
 51146
 51147
 51148
 51149
 51150
 51151
 51152
 51153
 51154
 51155
 51156
 51157
 51158
 51159
 51160
 51161
 51162
 51163
 51164
 51165
 51166
 51167
 51168
 51169
 51170
 51171
 51172
 51173
 51174
 51175
 51176
 51177
 51178
 51179
 51180
 51181
 51182
 51183
 51184
 51185
 51186
 51187
 51188
 51189
 51190
 51191
 51192
 51193
 51194
 51195
 51196
 51197
 51198
 51199
 51200
 51201
 51202
 51203
 51204
 51205
 51206
 51207
 51208
 51209
 51210
 51211
 51212
 51213
 51214
 51215
 51216
 51217
 51218
 51219
 51220
 51221
 51222
 51223
 51224
 51225
 51226
 51227
 51228
 51229
 51230
 51231
 51232
 51233
 51234
 51235
 51236
 51237
 51238
 51239
 51240
 51241
 51242
 51243
 51244
 51245
 51246
 51247
 51248
 51249
 51250
 51251
 51252
 51253
 51254
 51255
 51256
 51257
 51258
 51259
 51260
 51261
 51262
 51263
 51264
 51265
 51266
 51267
 51268
 51269
 51270
 51271
 51272
 51273
 51274
 51275
 51276
 51277
 51278
 51279
 51280
 51281
 51282
 51283
 51284
 51285
 51286
 51287
 51288
 51289
 51290
 51291
 51292
 51293
 51294
 51295
 51296
 51297
 51298
 51299
 51300
 51301
 51302
 51303
 51304
 51305
 51306
 51307
 51308
 51309
 51310
 51311
 51312
 51313
 51314
 51315
 51316
 51317
 51318
 51319
 51320
 51321
 51322
 51323
 51324
 51325
 51326
 51327
 51328
 51329
 51330
 51331
 51332
 51333
 51334
 51335
 51336
 51337
 51338
 51339
 51340
 51341
 51342
 51343
 51344
 51345
 51346
 51347
 51348
 51349
 51350
 51351
 51352
 51353
 51354
 51355
 51356
 51357
 51358
 51359
 51360
 51361
 51362
 51363
 51364
 51365
 51366
 51367
 51368
 51369
 51370
 51371
 51372
 51373
 51374
 51375
 51376
 51377
 51378
 51379
 51380
 51381
 51382
 51383
 51384
 51385
 51386
 51387
 51388
 51389
 51390
 51391
 51392
 51393
 51394
 51395
 51396
 51397
 51398
 51399
 51400
 51401
 51402
 51403
 51404
 51405
 51406
 51407
 51408
 51409
 51410
 51411
 51412
 51413
 51414
 51415
 51416
 51417
 51418
 51419
 51420
 51421
 51422
 51423
 51424
 51425
 51426
 51427
 51428
 51429
 51430
 51431
 51432
 51433
 51434
 51435
 51436
 51437
 51438
 51439
 51440
 51441
 51442
 51443
 51444
 51445
 51446
 51447
 51448
 51449
 51450
 51451
 51452
 51453
 51454
 51455
 51456
 51457
 51458
 51459
 51460
 51461
 51462
 51463
 51464
 51465
 51466
 51467
 51468
 51469
 51470
 51471
 51472
 51473
 51474
 51475
 51476
 51477
 51478
 51479
 51480
 51481
 51482
 51483
 51484
 51485
 51486
 51487
 51488
 51489
 51490
 51491
 51492
 51493
 51494
 51495
 51496
 51497
 51498
 51499
 51500
 51501
 51502
 51503
 51504
 51505
 51506
 51507
 51508
 51509
 51510
 51511
 51512
 51513
 51514
 51515
 51516
 51517
 51518
 51519
 51520
 51521
 51522
 51523
 51524
 51525
 51526
 51527
 51528
 51529
 51530
 51531
 51532
 51533
 51534
 51535
 51536
 51537
 51538
 51539
 51540
 51541
 51542
 51543
 51544
 51545
 51546
 51547
 51548
 51549
 51550
 51551
 51552
 51553
 51554
 51555
 51556
 51557
 51558
 51559
 51560
 51561
 51562
 51563
 51564
 51565
 51566
 51567
 51568
 51569
 51570
 51571
 51572
 51573
 51574
 51575
 51576
 51577
 51578
 51579
 51580
 51581
 51582
 51583
 51584
 51585
 51586
 51587
 51588
 51589
 51590
 51591
 51592
 51593
 51594
 51595
 51596
 51597
 51598
 51599
 51600
 51601
 51602
 51603
 51604
 51605
 51606
 51607
 51608
 51609
 51610
 51611
 51612
 51613
 51614
 51615
 51616
 51617
 51618
 51619
 51620
 51621
 51622
 51623
 51624
 51625
 51626
 51627
 51628
 51629
 51630
 51631
 51632
 51633
 51634
 51635
 51636
 51637
 51638
 51639
 51640
 51641
 51642
 51643
 51644
 51645
 51646
 51647
 51648
 51649
 51650
 51651
 51652
 51653
 51654
 51655
 51656
 51657
 51658
 51659
 51660
 51661
 51662
 51663
 51664
 51665
 51666
 51667
 51668
 51669
 51670
 51671
 51672
 51673
 51674
 51675
 51676
 51677
 51678
 51679
 51680
 51681
 51682
 51683
 51684
 51685
 51686
 51687
 51688
 51689
 51690
 51691
 51692
 51693
 51694
 51695
 51696
 51697
 51698
 51699
 51700
 51701
 51702
 51703
 51704
 51705
 51706
 51707
 51708
 51709
 51710
 51711
 51712
 51713
 51714
 51715
 51716
 51717
 51718
 51719
 51720
 51721
 51722
 51723
 51724
 51725
 51726
 51727
 51728
 51729
 51730
 51731
 51732
 51733
 51734
 51735
 51736
 51737
 51738
 51739
 51740
 51741
 51742
 51743
 51744
 51745
 51746
 51747
 51748
 51749
 51750
 51751
 51752
 51753
 51754
 51755
 51756
 51757
 51758
 51759
 51760
 51761
 51762
 51763
 51764
 51765
 51766
 51767
 51768
 51769
 51770
 51771
 51772
 51773
 51774
 51775
 51776
 51777
 51778
 51779
 51780
 51781
 51782
 51783
 51784
 51785
 51786
 51787
 51788
 51789
 51790
 51791
 51792
 51793
 51794
 51795
 51796
 51797
 51798
 51799
 51800
 51801
 51802
 51803
 51804
 51805
 51806
 51807
 51808
 51809
 51810
 51811
 51812
 51813
 51814
 51815
 51816
 51817
 51818
 51819
 51820
 51821
 51822
 51823
 51824
 51825
 51826
 51827
 51828
 51829
 51830
 51831
 51832
 51833
 51834
 51835
 51836
 51837
 51838
 51839
 51840
 51841
 51842
 51843
 51844
 51845
 51846
 51847
 51848
 51849
 51850
 51851
 51852
 51853
 51854
 51855
 51856
 51857
 51858
 51859
 51860
 51861
 51862
 51863
 51864
 51865
 51866
 51867
 51868
 51869
 51870
 51871
 51872
 51873
 51874
 51875
 51876
 51877
 51878
 51879
 51880
 51881
 51882
 51883
 51884
 51885
 51886
 51887
 51888
 51889
 51890
 51891
 51892
 51893
 51894
 51895
 51896
 51897
 51898
 51899
 51900
 51901
 51902
 51903
 51904
 51905
 51906
 51907
 51908
 51909
 51910
 51911
 51912
 51913
 51914
 51915
 51916
 51917
 51918
 51919
 51920
 51921
 51922
 51923
 51924
 51925
 51926
 51927
 51928
 51929
 51930
 51931
 51932
 51933
 51934
 51935
 51936
 51937
 51938
 51939
 51940
 51941
 51942
 51943
 51944
 51945
 51946
 51947
 51948
 51949
 51950
 51951
 51952
 51953
 51954
 51955
 51956
 51957
 51958
 51959
 51960
 51961
 51962
 51963
 51964
 51965
 51966
 51967
 51968
 51969
 51970
 51971
 51972
 51973
 51974
 51975
 51976
 51977
 51978
 51979
 51980
 51981
 51982
 51983
 51984
 51985
 51986
 51987
 51988
 51989
 51990
 51991
 51992
 51993
 51994
 51995
 51996
 51997
 51998
 51999
 52000
 52001
 52002
 52003
 52004
 52005
 52006
 52007
 52008
 52009
 52010
 52011
 52012
 52013
 52014
 52015
 52016
 52017
 52018
 52019
 52020
 52021
 52022
 52023
 52024
 52025
 52026
 52027
 52028
 52029
 52030
 52031
 52032
 52033
 52034
 52035
 52036
 52037
 52038
 52039
 52040
 52041
 52042
 52043
 52044
 52045
 52046
 52047
 52048
 52049
 52050
 52051
 52052
 52053
 52054
 52055
 52056
 52057
 52058
 52059
 52060
 52061
 52062
 52063
 52064
 52065
 52066
 52067
 52068
 52069
 52070
 52071
 52072
 52073
 52074
 52075
 52076
 52077
 52078
 52079
 52080
 52081
 52082
 52083
 52084
 52085
 52086
 52087
 52088
 52089
 52090
 52091
 52092
 52093
 52094
 52095
 52096
 52097
 52098
 52099
 52100
 52101
 52102
 52103
 52104
 52105
 52106
 52107
 52108
 52109
 52110
 52111
 52112
 52113
 52114
 52115
 52116
 52117
 52118
 52119
 52120
 52121
 52122
 52123
 52124
 52125
 52126
 52127
 52128
 52129
 52130
 52131
 52132
 52133
 52134
 52135
 52136
 52137
 52138
 52139
 52140
 52141
 52142
 52143
 52144
 52145
 52146
 52147
 52148
 52149
 52150
 52151
 52152
 52153
 52154
 52155
 52156
 52157
 52158
 52159
 52160
 52161
 52162
 52163
 52164
 52165
 52166
 52167
 52168
 52169
 52170
 52171
 52172
 52173
 52174
 52175
 52176
 52177
 52178
 52179
 52180
 52181
 52182
 52183
 52184
 52185
 52186
 52187
 52188
 52189
 52190
 52191
 52192
 52193
 52194
 52195
 52196
 52197
 52198
 52199
 52200
 52201
 52202
 52203
 52204
 52205
 52206
 52207
 52208
 52209
 52210
 52211
 52212
 52213
 52214
 52215
 52216
 52217
 52218
 52219
 52220
 52221
 52222
 52223
 52224
 52225
 52226
 52227
 52228
 52229
 52230
 52231
 52232
 52233
 52234
 52235
 52236
 52237
 52238
 52239
 52240
 52241
 52242
 52243
 52244
 52245
 52246
 52247
 52248
 52249
 52250
 52251
 52252
 52253
 52254
 52255
 52256
 52257
 52258
 52259
 52260
 52261
 52262
 52263
 52264
 52265
 52266
 52267
 52268
 52269
 52270
 52271
 52272
 52273
 52274
 52275
 52276
 52277
 52278
 52279
 52280
 52281
 52282
 52283
 52284
 52285
 52286
 52287
 52288
 52289
 52290
 52291
 52292
 52293
 52294
 52295
 52296
 52297
 52298
 52299
 52300
 52301
 52302
 52303
 52304
 52305
 52306
 52307
 52308
 52309
 52310
 52311
 52312
 52313
 52314
 52315
 52316
 52317
 52318
 52319
 52320
 52321
 52322
 52323
 52324
 52325
 52326
 52327
 52328
 52329
 52330
 52331
 52332
 52333
 52334
 52335
 52336
 52337
 52338
 52339
 52340
 52341
 52342
 52343
 52344
 52345
 52346
 52347
 52348
 52349
 52350
 52351
 52352
 52353
 52354
 52355
 52356
 52357
 52358
 52359
 52360
 52361
 52362
 52363
 52364
 52365
 52366
 52367
 52368
 52369
 52370
 52371
 52372
 52373
 52374
 52375
 52376
 52377
 52378
 52379
 52380
 52381
 52382
 52383
 52384
 52385
 52386
 52387
 52388
 52389
 52390
 52391
 52392
 52393
 52394
 52395
 52396
 52397
 52398
 52399
 52400
 52401
 52402
 52403
 52404
 52405
 52406
 52407
 52408
 52409
 52410
 52411
 52412
 52413
 52414
 52415
 52416
 52417
 52418
 52419
 52420
 52421
 52422
 52423
 52424
 52425
 52426
 52427
 52428
 52429
 52430
 52431
 52432
 52433
 52434
 52435
 52436
 52437
 52438
 52439
 52440
 52441
 52442
 52443
 52444
 52445
 52446
 52447
 52448
 52449
 52450
 52451
 52452
 52453
 52454
 52455
 52456
 52457
 52458
 52459
 52460
 52461
 52462
 52463
 52464
 52465
 52466
 52467
 52468
 52469
 52470
 52471
 52472
 52473
 52474
 52475
 52476
 52477
 52478
 52479
 52480
 52481
 52482
 52483
 52484
 52485
 52486
 52487
 52488
 52489
 52490
 52491
 52492
 52493
 52494
 52495
 52496
 52497
 52498
 52499
 52500
 52501
 52502
 52503
 52504
 52505
 52506
 52507
 52508
 52509
 52510
 52511
 52512
 52513
 52514
 52515
 52516
 52517
 52518
 52519
 52520
 52521
 52522
 52523
 52524
 52525
 52526
 52527
 52528
 52529
 52530
 52531
 52532
 52533
 52534
 52535
 52536
 52537
 52538
 52539
 52540
 52541
 52542
 52543
 52544
 52545
 52546
 52547
 52548
 52549
 52550
 52551
 52552
 52553
 52554
 52555
 52556
 52557
 52558
 52559
 52560
 52561
 52562
 52563
 52564
 52565
 52566
 52567
 52568
 52569
 52570
 52571
 52572
 52573
 52574
 52575
 52576
 52577
 52578
 52579
 52580
 52581
 52582
 52583
 52584
 52585
 52586
 52587
 52588
 52589
 52590
 52591
 52592
 52593
 52594
 52595
 52596
 52597
 52598
 52599
 52600
 52601
 52602
 52603
 52604
 52605
 52606
 52607
 52608
 52609
 52610
 52611
 52612
 52613
 52614
 52615
 52616
 52617
 52618
 52619
 52620
 52621
 52622
 52623
 52624
 52625
 52626
 52627
 52628
 52629
 52630
 52631
 52632
 52633
 52634
 52635
 52636
 52637
 52638
 52639
 52640
 52641
 52642
 52643
 52644
 52645
 52646
 52647
 52648
 52649
 52650
 52651
 52652
 52653
 52654
 52655
 52656
 52657
 52658
 52659
 52660
 52661
 52662
 52663
 52664
 52665
 52666
 52667
 52668
 52669
 52670
 52671
 52672
 52673
 52674
 52675
 52676
 52677
 52678
 52679
 52680
 52681
 52682
 52683
 52684
 52685
 52686
 52687
 52688
 52689
 52690
 52691
 52692
 52693
 52694
 52695
 52696
 52697
 52698
 52699
 52700
 52701
 52702
 52703
 52704
 52705
 52706
 52707
 52708
 52709
 52710
 52711
 52712
 52713
 52714
 52715
 52716
 52717
 52718
 52719
 52720
 52721
 52722
 52723
 52724
 52725
 52726
 52727
 52728
 52729
 52730
 52731
 52732
 52733
 52734
 52735
 52736
 52737
 52738
 52739
 52740
 52741
 52742
 52743
 52744
 52745
 52746
 52747
 52748
 52749
 52750
 52751
 52752
 52753
 52754
 52755
 52756
 52757
 52758
 52759
 52760
 52761
 52762
 52763
 52764
 52765
 52766
 52767
 52768
 52769
 52770
 52771
 52772
 52773
 52774
 52775
 52776
 52777
 52778
 52779
 52780
 52781
 52782
 52783
 52784
 52785
 52786
 52787
 52788
 52789
 52790
 52791
 52792
 52793
 52794
 52795
 52796
 52797
 52798
 52799
 52800
 52801
 52802
 52803
 52804
 52805
 52806
 52807
 52808
 52809
 52810
 52811
 52812
 52813
 52814
 52815
 52816
 52817
 52818
 52819
 52820
 52821
 52822
 52823
 52824
 52825
 52826
 52827
 52828
 52829
 52830
 52831
 52832
 52833
 52834
 52835
 52836
 52837
 52838
 52839
 52840
 52841
 52842
 52843
 52844
 52845
 52846
 52847
 52848
 52849
 52850
 52851
 52852
 52853
 52854
 52855
 52856
 52857
 52858
 52859
 52860
 52861
 52862
 52863
 52864
 52865
 52866
 52867
 52868
 52869
 52870
 52871
 52872
 52873
 52874
 52875
 52876
 52877
 52878
 52879
 52880
 52881
 52882
 52883
 52884
 52885
 52886
 52887
 52888
 52889
 52890
 52891
 52892
 52893
 52894
 52895
 52896
 52897
 52898
 52899
 52900
 52901
 52902
 52903
 52904
 52905
 52906
 52907
 52908
 52909
 52910
 52911
 52912
 52913
 52914
 52915
 52916
 52917
 52918
 52919
 52920
 52921
 52922
 52923
 52924
 52925
 52926
 52927
 52928
 52929
 52930
 52931
 52932
 52933
 52934
 52935
 52936
 52937
 52938
 52939
 52940
 52941
 52942
 52943
 52944
 52945
 52946
 52947
 52948
 52949
 52950
 52951
 52952
 52953
 52954
 52955
 52956
 52957
 52958
 52959
 52960
 52961
 52962
 52963
 52964
 52965
 52966
 52967
 52968
 52969
 52970
 52971
 52972
 52973
 52974
 52975
 52976
 52977
 52978
 52979
 52980
 52981
 52982
 52983
 52984
 52985
 52986
 52987
 52988
 52989
 52990
 52991
 52992
 52993
 52994
 52995
 52996
 52997
 52998
 52999
 53000
 53001
 53002
 53003
 53004
 53005
 53006
 53007
 53008
 53009
 53010
 53011
 53012
 53013
 53014
 53015
 53016
 53017
 53018
 53019
 53020
 53021
 53022
 53023
 53024
 53025
 53026
 53027
 53028
 53029
 53030
 53031
 53032
 53033
 53034
 53035
 53036
 53037
 53038
 53039
 53040
 53041
 53042
 53043
 53044
 53045
 53046
 53047
 53048
 53049
 53050
 53051
 53052
 53053
 53054
 53055
 53056
 53057
 53058
 53059
 53060
 53061
 53062
 53063
 53064
 53065
 53066
 53067
 53068
 53069
 53070
 53071
 53072
 53073
 53074
 53075
 53076
 53077
 53078
 53079
 53080
 53081
 53082
 53083
 53084
 53085
 53086
 53087
 53088
 53089
 53090
 53091
 53092
 53093
 53094
 53095
 53096
 53097
 53098
 53099
 53100
 53101
 53102
 53103
 53104
 53105
 53106
 53107
 53108
 53109
 53110
 53111
 53112
 53113
 53114
 53115
 53116
 53117
 53118
 53119
 53120
 53121
 53122
 53123
 53124
 53125
 53126
 53127
 53128
 53129
 53130
 53131
 53132
 53133
 53134
 53135
 53136
 53137
 53138
 53139
 53140
 53141
 53142
 53143
 53144
 53145
 53146
 53147
 53148
 53149
 53150
 53151
 53152
 53153
 53154
 53155
 53156
 53157
 53158
 53159
 53160
 53161
 53162
 53163
 53164
 53165
 53166
 53167
 53168
 53169
 53170
 53171
 53172
 53173
 53174
 53175
 53176
 53177
 53178
 53179
 53180
 53181
 53182
 53183
 53184
 53185
 53186
 53187
 53188
 53189
 53190
 53191
 53192
 53193
 53194
 53195
 53196
 53197
 53198
 53199
 53200
 53201
 53202
 53203
 53204
 53205
 53206
 53207
 53208
 53209
 53210
 53211
 53212
 53213
 53214
 53215
 53216
 53217
 53218
 53219
 53220
 53221
 53222
 53223
 53224
 53225
 53226
 53227
 53228
 53229
 53230
 53231
 53232
 53233
 53234
 53235
 53236
 53237
 53238
 53239
 53240
 53241
 53242
 53243
 53244
 53245
 53246
 53247
 53248
 53249
 53250
 53251
 53252
 53253
 53254
 53255
 53256
 53257
 53258
 53259
 53260
 53261
 53262
 53263
 53264
 53265
 53266
 53267
 53268
 53269
 53270
 53271
 53272
 53273
 53274
 53275
 53276
 53277
 53278
 53279
 53280
 53281
 53282
 53283
 53284
 53285
 53286
 53287
 53288
 53289
 53290
 53291
 53292
 53293
 53294
 53295
 53296
 53297
 53298
 53299
 53300
 53301
 53302
 53303
 53304
 53305
 53306
 53307
 53308
 53309
 53310
 53311
 53312
 53313
 53314
 53315
 53316
 53317
 53318
 53319
 53320
 53321
 53322
 53323
 53324
 53325
 53326
 53327
 53328
 53329
 53330
 53331
 53332
 53333
 53334
 53335
 53336
 53337
 53338
 53339
 53340
 53341
 53342
 53343
 53344
 53345
 53346
 53347
 53348
 53349
 53350
 53351
 53352
 53353
 53354
 53355
 53356
 53357
 53358
 53359
 53360
 53361
 53362
 53363
 53364
 53365
 53366
 53367
 53368
 53369
 53370
 53371
 53372
 53373
 53374
 53375
 53376
 53377
 53378
 53379
 53380
 53381
 53382
 53383
 53384
 53385
 53386
 53387
 53388
 53389
 53390
 53391
 53392
 53393
 53394
 53395
 53396
 53397
 53398
 53399
 53400
 53401
 53402
 53403
 53404
 53405
 53406
 53407
 53408
 53409
 53410
 53411
 53412
 53413
 53414
 53415
 53416
 53417
 53418
 53419
 53420
 53421
 53422
 53423
 53424
 53425
 53426
 53427
 53428
 53429
 53430
 53431
 53432
 53433
 53434
 53435
 53436
 53437
 53438
 53439
 53440
 53441
 53442
 53443
 53444
 53445
 53446
 53447
 53448
 53449
 53450
 53451
 53452
 53453
 53454
 53455
 53456
 53457
 53458
 53459
 53460
 53461
 53462
 53463
 53464
 53465
 53466
 53467
 53468
 53469
 53470
 53471
 53472
 53473
 53474
 53475
 53476
 53477
 53478
 53479
 53480
 53481
 53482
 53483
 53484
 53485
 53486
 53487
 53488
 53489
 53490
 53491
 53492
 53493
 53494
 53495
 53496
 53497
 53498
 53499
 53500
 53501
 53502
 53503
 53504
 53505
 53506
 53507
 53508
 53509
 53510
 53511
 53512
 53513
 53514
 53515
 53516
 53517
 53518
 53519
 53520
 53521
 53522
 53523
 53524
 53525
 53526
 53527
 53528
 53529
 53530
 53531
 53532
 53533
 53534
 53535
 53536
 53537
 53538
 53539
 53540
 53541
 53542
 53543
 53544
 53545
 53546
 53547
 53548
 53549
 53550
 53551
 53552
 53553
 53554
 53555
 53556
 53557
 53558
 53559
 53560
 53561
 53562
 53563
 53564
 53565
 53566
 53567
 53568
 53569
 53570
 53571
 53572
 53573
 53574
 53575
 53576
 53577
 53578
 53579
 53580
 53581
 53582
 53583
 53584
 53585
 53586
 53587
 53588
 53589
 53590
 53591
 53592
 53593
 53594
 53595
 53596
 53597
 53598
 53599
 53600
 53601
 53602
 53603
 53604
 53605
 53606
 53607
 53608
 53609
 53610
 53611
 53612
 53613
 53614
 53615
 53616
 53617
 53618
 53619
 53620
 53621
 53622
 53623
 53624
 53625
 53626
 53627
 53628
 53629
 53630
 53631
 53632
 53633
 53634
 53635
 53636
 53637
 53638
 53639
 53640
 53641
 53642
 53643
 53644
 53645
 53646
 53647
 53648
 53649
 53650
 53651
 53652
 53653
 53654
 53655
 53656
 53657
 53658
 53659
 53660
 53661
 53662
 53663
 53664
 53665
 53666
 53667
 53668
 53669
 53670
 53671
 53672
 53673
 53674
 53675
 53676
 53677
 53678
 53679
 53680
 53681
 53682
 53683
 53684
 53685
 53686
 53687
 53688
 53689
 53690
 53691
 53692
 53693
 53694
 53695
 53696
 53697
 53698
 53699
 53700
 53701
 53702
 53703
 53704
 53705
 53706
 53707
 53708
 53709
 53710
 53711
 53712
 53713
 53714
 53715
 53716
 53717
 53718
 53719
 53720
 53721
 53722
 53723
 53724
 53725
 53726
 53727
 53728
 53729
 53730
 53731
 53732
 53733
 53734
 53735
 53736
 53737
 53738
 53739
 53740
 53741
 53742
 53743
 53744
 53745
 53746
 53747
 53748
 53749
 53750
 53751
 53752
 53753
 53754
 53755
 53756
 53757
 53758
 53759
 53760
 53761
 53762
 53763
 53764
 53765
 53766
 53767
 53768
 53769
 53770
 53771
 53772
 53773
 53774
 53775
 53776
 53777
 53778
 53779
 53780
 53781
 53782
 53783
 53784
 53785
 53786
 53787
 53788
 53789
 53790
 53791
 53792
 53793
 53794
 53795
 53796
 53797
 53798
 53799
 53800
 53801
 53802
 53803
 53804
 53805
 53806
 53807
 53808
 53809
 53810
 53811
 53812
 53813
 53814
 53815
 53816
 53817
 53818
 53819
 53820
 53821
 53822
 53823
 53824
 53825
 53826
 53827
 53828
 53829
 53830
 53831
 53832
 53833
 53834
 53835
 53836
 53837
 53838
 53839
 53840
 53841
 53842
 53843
 53844
 53845
 53846
 53847
 53848
 53849
 53850
 53851
 53852
 53853
 53854
 53855
 53856
 53857
 53858
 53859
 53860
 53861
 53862
 53863
 53864
 53865
 53866
 53867
 53868
 53869
 53870
 53871
 53872
 53873
 53874
 53875
 53876
 53877
 53878
 53879
 53880
 53881
 53882
 53883
 53884
 53885
 53886
 53887
 53888
 53889
 53890
 53891
 53892
 53893
 53894
 53895
 53896
 53897
 53898
 53899
 53900
 53901
 53902
 53903
 53904
 53905
 53906
 53907
 53908
 53909
 53910
 53911
 53912
 53913
 53914
 53915
 53916
 53917
 53918
 53919
 53920
 53921
 53922
 53923
 53924
 53925
 53926
 53927
 53928
 53929
 53930
 53931
 53932
 53933
 53934
 53935
 53936
 53937
 53938
 53939
 53940
 53941
 53942
 53943
 53944
 53945
 53946
 53947
 53948
 53949
 53950
 53951
 53952
 53953
 53954
 53955
 53956
 53957
 53958
 53959
 53960
 53961
 53962
 53963
 53964
 53965
 53966
 53967
 53968
 53969
 53970
 53971
 53972
 53973
 53974
 53975
 53976
 53977
 53978
 53979
 53980
 53981
 53982
 53983
 53984
 53985
 53986
 53987
 53988
 53989
 53990
 53991
 53992
 53993
 53994
 53995
 53996
 53997
 53998
 53999
 54000
 54001
 54002
 54003
 54004
 54005
 54006
 54007
 54008
 54009
 54010
 54011
 54012
 54013
 54014
 54015
 54016
 54017
 54018
 54019
 54020
 54021
 54022
 54023
 54024
 54025
 54026
 54027
 54028
 54029
 54030
 54031
 54032
 54033
 54034
 54035
 54036
 54037
 54038
 54039
 54040
 54041
 54042
 54043
 54044
 54045
 54046
 54047
 54048
 54049
 54050
 54051
 54052
 54053
 54054
 54055
 54056
 54057
 54058
 54059
 54060
 54061
 54062
 54063
 54064
 54065
 54066
 54067
 54068
 54069
 54070
 54071
 54072
 54073
 54074
 54075
 54076
 54077
 54078
 54079
 54080
 54081
 54082
 54083
 54084
 54085
 54086
 54087
 54088
 54089
 54090
 54091
 54092
 54093
 54094
 54095
 54096
 54097
 54098
 54099
 54100
 54101
 54102
 54103
 54104
 54105
 54106
 54107
 54108
 54109
 54110
 54111
 54112
 54113
 54114
 54115
 54116
 54117
 54118
 54119
 54120
 54121
 54122
 54123
 54124
 54125
 54126
 54127
 54128
 54129
 54130
 54131
 54132
 54133
 54134
 54135
 54136
 54137
 54138
 54139
 54140
 54141
 54142
 54143
 54144
 54145
 54146
 54147
 54148
 54149
 54150
 54151
 54152
 54153
 54154
 54155
 54156
 54157
 54158
 54159
 54160
 54161
 54162
 54163
 54164
 54165
 54166
 54167
 54168
 54169
 54170
 54171
 54172
 54173
 54174
 54175
 54176
 54177
 54178
 54179
 54180
 54181
 54182
 54183
 54184
 54185
 54186
 54187
 54188
 54189
 54190
 54191
 54192
 54193
 54194
 54195
 54196
 54197
 54198
 54199
 54200
 54201
 54202
 54203
 54204
 54205
 54206
 54207
 54208
 54209
 54210
 54211
 54212
 54213
 54214
 54215
 54216
 54217
 54218
 54219
 54220
 54221
 54222
 54223
 54224
 54225
 54226
 54227
 54228
 54229
 54230
 54231
 54232
 54233
 54234
 54235
 54236
 54237
 54238
 54239
 54240
 54241
 54242
 54243
 54244
 54245
 54246
 54247
 54248
 54249
 54250
 54251
 54252
 54253
 54254
 54255
 54256
 54257
 54258
 54259
 54260
 54261
 54262
 54263
 54264
 54265
 54266
 54267
 54268
 54269
 54270
 54271
 54272
 54273
 54274
 54275
 54276
 54277
 54278
 54279
 54280
 54281
 54282
 54283
 54284
 54285
 54286
 54287
 54288
 54289
 54290
 54291
 54292
 54293
 54294
 54295
 54296
 54297
 54298
 54299
 54300
 54301
 54302
 54303
 54304
 54305
 54306
 54307
 54308
 54309
 54310
 54311
 54312
 54313
 54314
 54315
 54316
 54317
 54318
 54319
 54320
 54321
 54322
 54323
 54324
 54325
 54326
 54327
 54328
 54329
 54330
 54331
 54332
 54333
 54334
 54335
 54336
 54337
 54338
 54339
 54340
 54341
 54342
 54343
 54344
 54345
 54346
 54347
 54348
 54349
 54350
 54351
 54352
 54353
 54354
 54355
 54356
 54357
 54358
 54359
 54360
 54361
 54362
 54363
 54364
 54365
 54366
 54367
 54368
 54369
 54370
 54371
 54372
 54373
 54374
 54375
 54376
 54377
 54378
 54379
 54380
 54381
 54382
 54383
 54384
 54385
 54386
 54387
 54388
 54389
 54390
 54391
 54392
 54393
 54394
 54395
 54396
 54397
 54398
 54399
 54400
 54401
 54402
 54403
 54404
 54405
 54406
 54407
 54408
 54409
 54410
 54411
 54412
 54413
 54414
 54415
 54416
 54417
 54418
 54419
 54420
 54421
 54422
 54423
 54424
 54425
 54426
 54427
 54428
 54429
 54430
 54431
 54432
 54433
 54434
 54435
 54436
 54437
 54438
 54439
 54440
 54441
 54442
 54443
 54444
 54445
 54446
 54447
 54448
 54449
 54450
 54451
 54452
 54453
 54454
 54455
 54456
 54457
 54458
 54459
 54460
 54461
 54462
 54463
 54464
 54465
 54466
 54467
 54468
 54469
 54470
 54471
 54472
 54473
 54474
 54475
 54476
 54477
 54478
 54479
 54480
 54481
 54482
 54483
 54484
 54485
 54486
 54487
 54488
 54489
 54490
 54491
 54492
 54493
 54494
 54495
 54496
 54497
 54498
 54499
 54500
 54501
 54502
 54503
 54504
 54505
 54506
 54507
 54508
 54509
 54510
 54511
 54512
 54513
 54514
 54515
 54516
 54517
 54518
 54519
 54520
 54521
 54522
 54523
 54524
 54525
 54526
 54527
 54528
 54529
 54530
 54531
 54532
 54533
 54534
 54535
 54536
 54537
 54538
 54539
 54540
 54541
 54542
 54543
 54544
 54545
 54546
 54547
 54548
 54549
 54550
 54551
 54552
 54553
 54554
 54555
 54556
 54557
 54558
 54559
 54560
 54561
 54562
 54563
 54564
 54565
 54566
 54567
 54568
 54569
 54570
 54571
 54572
 54573
 54574
 54575
 54576
 54577
 54578
 54579
 54580
 54581
 54582
 54583
 54584
 54585
 54586
 54587
 54588
 54589
 54590
 54591
 54592
 54593
 54594
 54595
 54596
 54597
 54598
 54599
 54600
 54601
 54602
 54603
 54604
 54605
 54606
 54607
 54608
 54609
 54610
 54611
 54612
 54613
 54614
 54615
 54616
 54617
 54618
 54619
 54620
 54621
 54622
 54623
 54624
 54625
 54626
 54627
 54628
 54629
 54630
 54631
 54632
 54633
 54634
 54635
 54636
 54637
 54638
 54639
 54640
 54641
 54642
 54643
 54644
 54645
 54646
 54647
 54648
 54649
 54650
 54651
 54652
 54653
 54654
 54655
 54656
 54657
 54658
 54659
 54660
 54661
 54662
 54663
 54664
 54665
 54666
 54667
 54668
 54669
 54670
 54671
 54672
 54673
 54674
 54675
 54676
 54677
 54678
 54679
 54680
 54681
 54682
 54683
 54684
 54685
 54686
 54687
 54688
 54689
 54690
 54691
 54692
 54693
 54694
 54695
 54696
 54697
 54698
 54699
 54700
 54701
 54702
 54703
 54704
 54705
 54706
 54707
 54708
 54709
 54710
 54711
 54712
 54713
 54714
 54715
 54716
 54717
 54718
 54719
 54720
 54721
 54722
 54723
 54724
 54725
 54726
 54727
 54728
 54729
 54730
 54731
 54732
 54733
 54734
 54735
 54736
 54737
 54738
 54739
 54740
 54741
 54742
 54743
 54744
 54745
 54746
 54747
 54748
 54749
 54750
 54751
 54752
 54753
 54754
 54755
 54756
 54757
 54758
 54759
 54760
 54761
 54762
 54763
 54764
 54765
 54766
 54767
 54768
 54769
 54770
 54771
 54772
 54773
 54774
 54775
 54776
 54777
 54778
 54779
 54780
 54781
 54782
 54783
 54784
 54785
 54786
 54787
 54788
 54789
 54790
 54791
 54792
 54793
 54794
 54795
 54796
 54797
 54798
 54799
 54800
 54801
 54802
 54803
 54804
 54805
 54806
 54807
 54808
 54809
 54810
 54811
 54812
 54813
 54814
 54815
 54816
 54817
 54818
 54819
 54820
 54821
 54822
 54823
 54824
 54825
 54826
 54827
 54828
 54829
 54830
 54831
 54832
 54833
 54834
 54835
 54836
 54837
 54838
 54839
 54840
 54841
 54842
 54843
 54844
 54845
 54846
 54847
 54848
 54849
 54850
 54851
 54852
 54853
 54854
 54855
 54856
 54857
 54858
 54859
 54860
 54861
 54862
 54863
 54864
 54865
 54866
 54867
 54868
 54869
 54870
 54871
 54872
 54873
 54874
 54875
 54876
 54877
 54878
 54879
 54880
 54881
 54882
 54883
 54884
 54885
 54886
 54887
 54888
 54889
 54890
 54891
 54892
 54893
 54894
 54895
 54896
 54897
 54898
 54899
 54900
 54901
 54902
 54903
 54904
 54905
 54906
 54907
 54908
 54909
 54910
 54911
 54912
 54913
 54914
 54915
 54916
 54917
 54918
 54919
 54920
 54921
 54922
 54923
 54924
 54925
 54926
 54927
 54928
 54929
 54930
 54931
 54932
 54933
 54934
 54935
 54936
 54937
 54938
 54939
 54940
 54941
 54942
 54943
 54944
 54945
 54946
 54947
 54948
 54949
 54950
 54951
 54952
 54953
 54954
 54955
 54956
 54957
 54958
 54959
 54960
 54961
 54962
 54963
 54964
 54965
 54966
 54967
 54968
 54969
 54970
 54971
 54972
 54973
 54974
 54975
 54976
 54977
 54978
 54979
 54980
 54981
 54982
 54983
 54984
 54985
 54986
 54987
 54988
 54989
 54990
 54991
 54992
 54993
 54994
 54995
 54996
 54997
 54998
 54999
 55000
 55001
 55002
 55003
 55004
 55005
 55006
 55007
 55008
 55009
 55010
 55011
 55012
 55013
 55014
 55015
 55016
 55017
 55018
 55019
 55020
 55021
 55022
 55023
 55024
 55025
 55026
 55027
 55028
 55029
 55030
 55031
 55032
 55033
 55034
 55035
 55036
 55037
 55038
 55039
 55040
 55041
 55042
 55043
 55044
 55045
 55046
 55047
 55048
 55049
 55050
 55051
 55052
 55053
 55054
 55055
 55056
 55057
 55058
 55059
 55060
 55061
 55062
 55063
 55064
 55065
 55066
 55067
 55068
 55069
 55070
 55071
 55072
 55073
 55074
 55075
 55076
 55077
 55078
 55079
 55080
 55081
 55082
 55083
 55084
 55085
 55086
 55087
 55088
 55089
 55090
 55091
 55092
 55093
 55094
 55095
 55096
 55097
 55098
 55099
 55100
 55101
 55102
 55103
 55104
 55105
 55106
 55107
 55108
 55109
 55110
 55111
 55112
 55113
 55114
 55115
 55116
 55117
 55118
 55119
 55120
 55121
 55122
 55123
 55124
 55125
 55126
 55127
 55128
 55129
 55130
 55131
 55132
 55133
 55134
 55135
 55136
 55137
 55138
 55139
 55140
 55141
 55142
 55143
 55144
 55145
 55146
 55147
 55148
 55149
 55150
 55151
 55152
 55153
 55154
 55155
 55156
 55157
 55158
 55159
 55160
 55161
 55162
 55163
 55164
 55165
 55166
 55167
 55168
 55169
 55170
 55171
 55172
 55173
 55174
 55175
 55176
 55177
 55178
 55179
 55180
 55181
 55182
 55183
 55184
 55185
 55186
 55187
 55188
 55189
 55190
 55191
 55192
 55193
 55194
 55195
 55196
 55197
 55198
 55199
 55200
 55201
 55202
 55203
 55204
 55205
 55206
 55207
 55208
 55209
 55210
 55211
 55212
 55213
 55214
 55215
 55216
 55217
 55218
 55219
 55220
 55221
 55222
 55223
 55224
 55225
 55226
 55227
 55228
 55229
 55230
 55231
 55232
 55233
 55234
 55235
 55236
 55237
 55238
 55239
 55240
 55241
 55242
 55243
 55244
 55245
 55246
 55247
 55248
 55249
 55250
 55251
 55252
 55253
 55254
 55255
 55256
 55257
 55258
 55259
 55260
 55261
 55262
 55263
 55264
 55265
 55266
 55267
 55268
 55269
 55270
 55271
 55272
 55273
 55274
 55275
 55276
 55277
 55278
 55279
 55280
 55281
 55282
 55283
 55284
 55285
 55286
 55287
 55288
 55289
 55290
 55291
 55292
 55293
 55294
 55295
 55296
 55297
 55298
 55299
 55300
 55301
 55302
 55303
 55304
 55305
 55306
 55307
 55308
 55309
 55310
 55311
 55312
 55313
 55314
 55315
 55316
 55317
 55318
 55319
 55320
 55321
 55322
 55323
 55324
 55325
 55326
 55327
 55328
 55329
 55330
 55331
 55332
 55333
 55334
 55335
 55336
 55337
 55338
 55339
 55340
 55341
 55342
 55343
 55344
 55345
 55346
 55347
 55348
 55349
 55350
 55351
 55352
 55353
 55354
 55355
 55356
 55357
 55358
 55359
 55360
 55361
 55362
 55363
 55364
 55365
 55366
 55367
 55368
 55369
 55370
 55371
 55372
 55373
 55374
 55375
 55376
 55377
 55378
 55379
 55380
 55381
 55382
 55383
 55384
 55385
 55386
 55387
 55388
 55389
 55390
 55391
 55392
 55393
 55394
 55395
 55396
 55397
 55398
 55399
 55400
 55401
 55402
 55403
 55404
 55405
 55406
 55407
 55408
 55409
 55410
 55411
 55412
 55413
 55414
 55415
 55416
 55417
 55418
 55419
 55420
 55421
 55422
 55423
 55424
 55425
 55426
 55427
 55428
 55429
 55430
 55431
 55432
 55433
 55434
 55435
 55436
 55437
 55438
 55439
 55440
 55441
 55442
 55443
 55444
 55445
 55446
 55447
 55448
 55449
 55450
 55451
 55452
 55453
 55454
 55455
 55456
 55457
 55458
 55459
 55460
 55461
 55462
 55463
 55464
 55465
 55466
 55467
 55468
 55469
 55470
 55471
 55472
 55473
 55474
 55475
 55476
 55477
 55478
 55479
 55480
 55481
 55482
 55483
 55484
 55485
 55486
 55487
 55488
 55489
 55490
 55491
 55492
 55493
 55494
 55495
 55496
 55497
 55498
 55499
 55500
 55501
 55502
 55503
 55504
 55505
 55506
 55507
 55508
 55509
 55510
 55511
 55512
 55513
 55514
 55515
 55516
 55517
 55518
 55519
 55520
 55521
 55522
 55523
 55524
 55525
 55526
 55527
 55528
 55529
 55530
 55531
 55532
 55533
 55534
 55535
 55536
 55537
 55538
 55539
 55540
 55541
 55542
 55543
 55544
 55545
 55546
 55547
 55548
 55549
 55550
 55551
 55552
 55553
 55554
 55555
 55556
 55557
 55558
 55559
 55560
 55561
 55562
 55563
 55564
 55565
 55566
 55567
 55568
 55569
 55570
 55571
 55572
 55573
 55574
 55575
 55576
 55577
 55578
 55579
 55580
 55581
 55582
 55583
 55584
 55585
 55586
 55587
 55588
 55589
 55590
 55591
 55592
 55593
 55594
 55595
 55596
 55597
 55598
 55599
 55600
 55601
 55602
 55603
 55604
 55605
 55606
 55607
 55608
 55609
 55610
 55611
 55612
 55613
 55614
 55615
 55616
 55617
 55618
 55619
 55620
 55621
 55622
 55623
 55624
 55625
 55626
 55627
 55628
 55629
 55630
 55631
 55632
 55633
 55634
 55635
 55636
 55637
 55638
 55639
 55640
 55641
 55642
 55643
 55644
 55645
 55646
 55647
 55648
 55649
 55650
 55651
 55652
 55653
 55654
 55655
 55656
 55657
 55658
 55659
 55660
 55661
 55662
 55663
 55664
 55665
 55666
 55667
 55668
 55669
 55670
 55671
 55672
 55673
 55674
 55675
 55676
 55677
 55678
 55679
 55680
 55681
 55682
 55683
 55684
 55685
 55686
 55687
 55688
 55689
 55690
 55691
 55692
 55693
 55694
 55695
 55696
 55697
 55698
 55699
 55700
 55701
 55702
 55703
 55704
 55705
 55706
 55707
 55708
 55709
 55710
 55711
 55712
 55713
 55714
 55715
 55716
 55717
 55718
 55719
 55720
 55721
 55722
 55723
 55724
 55725
 55726
 55727
 55728
 55729
 55730
 55731
 55732
 55733
 55734
 55735
 55736
 55737
 55738
 55739
 55740
 55741
 55742
 55743
 55744
 55745
 55746
 55747
 55748
 55749
 55750
 55751
 55752
 55753
 55754
 55755
 55756
 55757
 55758
 55759
 55760
 55761
 55762
 55763
 55764
 55765
 55766
 55767
 55768
 55769
 55770
 55771
 55772
 55773
 55774
 55775
 55776
 55777
 55778
 55779
 55780
 55781
 55782
 55783
 55784
 55785
 55786
 55787
 55788
 55789
 55790
 55791
 55792
 55793
 55794
 55795
 55796
 55797
 55798
 55799
 55800
 55801
 55802
 55803
 55804
 55805
 55806
 55807
 55808
 55809
 55810
 55811
 55812
 55813
 55814
 55815
 55816
 55817
 55818
 55819
 55820
 55821
 55822
 55823
 55824
 55825
 55826
 55827
 55828
 55829
 55830
 55831
 55832
 55833
 55834
 55835
 55836
 55837
 55838
 55839
 55840
 55841
 55842
 55843
 55844
 55845
 55846
 55847
 55848
 55849
 55850
 55851
 55852
 55853
 55854
 55855
 55856
 55857
 55858
 55859
 55860
 55861
 55862
 55863
 55864
 55865
 55866
 55867
 55868
 55869
 55870
 55871
 55872
 55873
 55874
 55875
 55876
 55877
 55878
 55879
 55880
 55881
 55882
 55883
 55884
 55885
 55886
 55887
 55888
 55889
 55890
 55891
 55892
 55893
 55894
 55895
 55896
 55897
 55898
 55899
 55900
 55901
 55902
 55903
 55904
 55905
 55906
 55907
 55908
 55909
 55910
 55911
 55912
 55913
 55914
 55915
 55916
 55917
 55918
 55919
 55920
 55921
 55922
 55923
 55924
 55925
 55926
 55927
 55928
 55929
 55930
 55931
 55932
 55933
 55934
 55935
 55936
 55937
 55938
 55939
 55940
 55941
 55942
 55943
 55944
 55945
 55946
 55947
 55948
 55949
 55950
 55951
 55952
 55953
 55954
 55955
 55956
 55957
 55958
 55959
 55960
 55961
 55962
 55963
 55964
 55965
 55966
 55967
 55968
 55969
 55970
 55971
 55972
 55973
 55974
 55975
 55976
 55977
 55978
 55979
 55980
 55981
 55982
 55983
 55984
 55985
 55986
 55987
 55988
 55989
 55990
 55991
 55992
 55993
 55994
 55995
 55996
 55997
 55998
 55999
 56000
 56001
 56002
 56003
 56004
 56005
 56006
 56007
 56008
 56009
 56010
 56011
 56012
 56013
 56014
 56015
 56016
 56017
 56018
 56019
 56020
 56021
 56022
 56023
 56024
 56025
 56026
 56027
 56028
 56029
 56030
 56031
 56032
 56033
 56034
 56035
 56036
 56037
 56038
 56039
 56040
 56041
 56042
 56043
 56044
 56045
 56046
 56047
 56048
 56049
 56050
 56051
 56052
 56053
 56054
 56055
 56056
 56057
 56058
 56059
 56060
 56061
 56062
 56063
 56064
 56065
 56066
 56067
 56068
 56069
 56070
 56071
 56072
 56073
 56074
 56075
 56076
 56077
 56078
 56079
 56080
 56081
 56082
 56083
 56084
 56085
 56086
 56087
 56088
 56089
 56090
 56091
 56092
 56093
 56094
 56095
 56096
 56097
 56098
 56099
 56100
 56101
 56102
 56103
 56104
 56105
 56106
 56107
 56108
 56109
 56110
 56111
 56112
 56113
 56114
 56115
 56116
 56117
 56118
 56119
 56120
 56121
 56122
 56123
 56124
 56125
 56126
 56127
 56128
 56129
 56130
 56131
 56132
 56133
 56134
 56135
 56136
 56137
 56138
 56139
 56140
 56141
 56142
 56143
 56144
 56145
 56146
 56147
 56148
 56149
 56150
 56151
 56152
 56153
 56154
 56155
 56156
 56157
 56158
 56159
 56160
 56161
 56162
 56163
 56164
 56165
 56166
 56167
 56168
 56169
 56170
 56171
 56172
 56173
 56174
 56175
 56176
 56177
 56178
 56179
 56180
 56181
 56182
 56183
 56184
 56185
 56186
 56187
 56188
 56189
 56190
 56191
 56192
 56193
 56194
 56195
 56196
 56197
 56198
 56199
 56200
 56201
 56202
 56203
 56204
 56205
 56206
 56207
 56208
 56209
 56210
 56211
 56212
 56213
 56214
 56215
 56216
 56217
 56218
 56219
 56220
 56221
 56222
 56223
 56224
 56225
 56226
 56227
 56228
 56229
 56230
 56231
 56232
 56233
 56234
 56235
 56236
 56237
 56238
 56239
 56240
 56241
 56242
 56243
 56244
 56245
 56246
 56247
 56248
 56249
 56250
 56251
 56252
 56253
 56254
 56255
 56256
 56257
 56258
 56259
 56260
 56261
 56262
 56263
 56264
 56265
 56266
 56267
 56268
 56269
 56270
 56271
 56272
 56273
 56274
 56275
 56276
 56277
 56278
 56279
 56280
 56281
 56282
 56283
 56284
 56285
 56286
 56287
 56288
 56289
 56290
 56291
 56292
 56293
 56294
 56295
 56296
 56297
 56298
 56299
 56300
 56301
 56302
 56303
 56304
 56305
 56306
 56307
 56308
 56309
 56310
 56311
 56312
 56313
 56314
 56315
 56316
 56317
 56318
 56319
 56320
 56321
 56322
 56323
 56324
 56325
 56326
 56327
 56328
 56329
 56330
 56331
 56332
 56333
 56334
 56335
 56336
 56337
 56338
 56339
 56340
 56341
 56342
 56343
 56344
 56345
 56346
 56347
 56348
 56349
 56350
 56351
 56352
 56353
 56354
 56355
 56356
 56357
 56358
 56359
 56360
 56361
 56362
 56363
 56364
 56365
 56366
 56367
 56368
 56369
 56370
 56371
 56372
 56373
 56374
 56375
 56376
 56377
 56378
 56379
 56380
 56381
 56382
 56383
 56384
 56385
 56386
 56387
 56388
 56389
 56390
 56391
 56392
 56393
 56394
 56395
 56396
 56397
 56398
 56399
 56400
 56401
 56402
 56403
 56404
 56405
 56406
 56407
 56408
 56409
 56410
 56411
 56412
 56413
 56414
 56415
 56416
 56417
 56418
 56419
 56420
 56421
 56422
 56423
 56424
 56425
 56426
 56427
 56428
 56429
 56430
 56431
 56432
 56433
 56434
 56435
 56436
 56437
 56438
 56439
 56440
 56441
 56442
 56443
 56444
 56445
 56446
 56447
 56448
 56449
 56450
 56451
 56452
 56453
 56454
 56455
 56456
 56457
 56458
 56459
 56460
 56461
 56462
 56463
 56464
 56465
 56466
 56467
 56468
 56469
 56470
 56471
 56472
 56473
 56474
 56475
 56476
 56477
 56478
 56479
 56480
 56481
 56482
 56483
 56484
 56485
 56486
 56487
 56488
 56489
 56490
 56491
 56492
 56493
 56494
 56495
 56496
 56497
 56498
 56499
 56500
 56501
 56502
 56503
 56504
 56505
 56506
 56507
 56508
 56509
 56510
 56511
 56512
 56513
 56514
 56515
 56516
 56517
 56518
 56519
 56520
 56521
 56522
 56523
 56524
 56525
 56526
 56527
 56528
 56529
 56530
 56531
 56532
 56533
 56534
 56535
 56536
 56537
 56538
 56539
 56540
 56541
 56542
 56543
 56544
 56545
 56546
 56547
 56548
 56549
 56550
 56551
 56552
 56553
 56554
 56555
 56556
 56557
 56558
 56559
 56560
 56561
 56562
 56563
 56564
 56565
 56566
 56567
 56568
 56569
 56570
 56571
 56572
 56573
 56574
 56575
 56576
 56577
 56578
 56579
 56580
 56581
 56582
 56583
 56584
 56585
 56586
 56587
 56588
 56589
 56590
 56591
 56592
 56593
 56594
 56595
 56596
 56597
 56598
 56599
 56600
 56601
 56602
 56603
 56604
 56605
 56606
 56607
 56608
 56609
 56610
 56611
 56612
 56613
 56614
 56615
 56616
 56617
 56618
 56619
 56620
 56621
 56622
 56623
 56624
 56625
 56626
 56627
 56628
 56629
 56630
 56631
 56632
 56633
 56634
 56635
 56636
 56637
 56638
 56639
 56640
 56641
 56642
 56643
 56644
 56645
 56646
 56647
 56648
 56649
 56650
 56651
 56652
 56653
 56654
 56655
 56656
 56657
 56658
 56659
 56660
 56661
 56662
 56663
 56664
 56665
 56666
 56667
 56668
 56669
 56670
 56671
 56672
 56673
 56674
 56675
 56676
 56677
 56678
 56679
 56680
 56681
 56682
 56683
 56684
 56685
 56686
 56687
 56688
 56689
 56690
 56691
 56692
 56693
 56694
 56695
 56696
 56697
 56698
 56699
 56700
 56701
 56702
 56703
 56704
 56705
 56706
 56707
 56708
 56709
 56710
 56711
 56712
 56713
 56714
 56715
 56716
 56717
 56718
 56719
 56720
 56721
 56722
 56723
 56724
 56725
 56726
 56727
 56728
 56729
 56730
 56731
 56732
 56733
 56734
 56735
 56736
 56737
 56738
 56739
 56740
 56741
 56742
 56743
 56744
 56745
 56746
 56747
 56748
 56749
 56750
 56751
 56752
 56753
 56754
 56755
 56756
 56757
 56758
 56759
 56760
 56761
 56762
 56763
 56764
 56765
 56766
 56767
 56768
 56769
 56770
 56771
 56772
 56773
 56774
 56775
 56776
 56777
 56778
 56779
 56780
 56781
 56782
 56783
 56784
 56785
 56786
 56787
 56788
 56789
 56790
 56791
 56792
 56793
 56794
 56795
 56796
 56797
 56798
 56799
 56800
 56801
 56802
 56803
 56804
 56805
 56806
 56807
 56808
 56809
 56810
 56811
 56812
 56813
 56814
 56815
 56816
 56817
 56818
 56819
 56820
 56821
 56822
 56823
 56824
 56825
 56826
 56827
 56828
 56829
 56830
 56831
 56832
 56833
 56834
 56835
 56836
 56837
 56838
 56839
 56840
 56841
 56842
 56843
 56844
 56845
 56846
 56847
 56848
 56849
 56850
 56851
 56852
 56853
 56854
 56855
 56856
 56857
 56858
 56859
 56860
 56861
 56862
 56863
 56864
 56865
 56866
 56867
 56868
 56869
 56870
 56871
 56872
 56873
 56874
 56875
 56876
 56877
 56878
 56879
 56880
 56881
 56882
 56883
 56884
 56885
 56886
 56887
 56888
 56889
 56890
 56891
 56892
 56893
 56894
 56895
 56896
 56897
 56898
 56899
 56900
 56901
 56902
 56903
 56904
 56905
 56906
 56907
 56908
 56909
 56910
 56911
 56912
 56913
 56914
 56915
 56916
 56917
 56918
 56919
 56920
 56921
 56922
 56923
 56924
 56925
 56926
 56927
 56928
 56929
 56930
 56931
 56932
 56933
 56934
 56935
 56936
 56937
 56938
 56939
 56940
 56941
 56942
 56943
 56944
 56945
 56946
 56947
 56948
 56949
 56950
 56951
 56952
 56953
 56954
 56955
 56956
 56957
 56958
 56959
 56960
 56961
 56962
 56963
 56964
 56965
 56966
 56967
 56968
 56969
 56970
 56971
 56972
 56973
 56974
 56975
 56976
 56977
 56978
 56979
 56980
 56981
 56982
 56983
 56984
 56985
 56986
 56987
 56988
 56989
 56990
 56991
 56992
 56993
 56994
 56995
 56996
 56997
 56998
 56999
 57000
 57001
 57002
 57003
 57004
 57005
 57006
 57007
 57008
 57009
 57010
 57011
 57012
 57013
 57014
 57015
 57016
 57017
 57018
 57019
 57020
 57021
 57022
 57023
 57024
 57025
 57026
 57027
 57028
 57029
 57030
 57031
 57032
 57033
 57034
 57035
 57036
 57037
 57038
 57039
 57040
 57041
 57042
 57043
 57044
 57045
 57046
 57047
 57048
 57049
 57050
 57051
 57052
 57053
 57054
 57055
 57056
 57057
 57058
 57059
 57060
 57061
 57062
 57063
 57064
 57065
 57066
 57067
 57068
 57069
 57070
 57071
 57072
 57073
 57074
 57075
 57076
 57077
 57078
 57079
 57080
 57081
 57082
 57083
 57084
 57085
 57086
 57087
 57088
 57089
 57090
 57091
 57092
 57093
 57094
 57095
 57096
 57097
 57098
 57099
 57100
 57101
 57102
 57103
 57104
 57105
 57106
 57107
 57108
 57109
 57110
 57111
 57112
 57113
 57114
 57115
 57116
 57117
 57118
 57119
 57120
 57121
 57122
 57123
 57124
 57125
 57126
 57127
 57128
 57129
 57130
 57131
 57132
 57133
 57134
 57135
 57136
 57137
 57138
 57139
 57140
 57141
 57142
 57143
 57144
 57145
 57146
 57147
 57148
 57149
 57150
 57151
 57152
 57153
 57154
 57155
 57156
 57157
 57158
 57159
 57160
 57161
 57162
 57163
 57164
 57165
 57166
 57167
 57168
 57169
 57170
 57171
 57172
 57173
 57174
 57175
 57176
 57177
 57178
 57179
 57180
 57181
 57182
 57183
 57184
 57185
 57186
 57187
 57188
 57189
 57190
 57191
 57192
 57193
 57194
 57195
 57196
 57197
 57198
 57199
 57200
 57201
 57202
 57203
 57204
 57205
 57206
 57207
 57208
 57209
 57210
 57211
 57212
 57213
 57214
 57215
 57216
 57217
 57218
 57219
 57220
 57221
 57222
 57223
 57224
 57225
 57226
 57227
 57228
 57229
 57230
 57231
 57232
 57233
 57234
 57235
 57236
 57237
 57238
 57239
 57240
 57241
 57242
 57243
 57244
 57245
 57246
 57247
 57248
 57249
 57250
 57251
 57252
 57253
 57254
 57255
 57256
 57257
 57258
 57259
 57260
 57261
 57262
 57263
 57264
 57265
 57266
 57267
 57268
 57269
 57270
 57271
 57272
 57273
 57274
 57275
 57276
 57277
 57278
 57279
 57280
 57281
 57282
 57283
 57284
 57285
 57286
 57287
 57288
 57289
 57290
 57291
 57292
 57293
 57294
 57295
 57296
 57297
 57298
 57299
 57300
 57301
 57302
 57303
 57304
 57305
 57306
 57307
 57308
 57309
 57310
 57311
 57312
 57313
 57314
 57315
 57316
 57317
 57318
 57319
 57320
 57321
 57322
 57323
 57324
 57325
 57326
 57327
 57328
 57329
 57330
 57331
 57332
 57333
 57334
 57335
 57336
 57337
 57338
 57339
 57340
 57341
 57342
 57343
 57344
 57345
 57346
 57347
 57348
 57349
 57350
 57351
 57352
 57353
 57354
 57355
 57356
 57357
 57358
 57359
 57360
 57361
 57362
 57363
 57364
 57365
 57366
 57367
 57368
 57369
 57370
 57371
 57372
 57373
 57374
 57375
 57376
 57377
 57378
 57379
 57380
 57381
 57382
 57383
 57384
 57385
 57386
 57387
 57388
 57389
 57390
 57391
 57392
 57393
 57394
 57395
 57396
 57397
 57398
 57399
 57400
 57401
 57402
 57403
 57404
 57405
 57406
 57407
 57408
 57409
 57410
 57411
 57412
 57413
 57414
 57415
 57416
 57417
 57418
 57419
 57420
 57421
 57422
 57423
 57424
 57425
 57426
 57427
 57428
 57429
 57430
 57431
 57432
 57433
 57434
 57435
 57436
 57437
 57438
 57439
 57440
 57441
 57442
 57443
 57444
 57445
 57446
 57447
 57448
 57449
 57450
 57451
 57452
 57453
 57454
 57455
 57456
 57457
 57458
 57459
 57460
 57461
 57462
 57463
 57464
 57465
 57466
 57467
 57468
 57469
 57470
 57471
 57472
 57473
 57474
 57475
 57476
 57477
 57478
 57479
 57480
 57481
 57482
 57483
 57484
 57485
 57486
 57487
 57488
 57489
 57490
 57491
 57492
 57493
 57494
 57495
 57496
 57497
 57498
 57499
 57500
 57501
 57502
 57503
 57504
 57505
 57506
 57507
 57508
 57509
 57510
 57511
 57512
 57513
 57514
 57515
 57516
 57517
 57518
 57519
 57520
 57521
 57522
 57523
 57524
 57525
 57526
 57527
 57528
 57529
 57530
 57531
 57532
 57533
 57534
 57535
 57536
 57537
 57538
 57539
 57540
 57541
 57542
 57543
 57544
 57545
 57546
 57547
 57548
 57549
 57550
 57551
 57552
 57553
 57554
 57555
 57556
 57557
 57558
 57559
 57560
 57561
 57562
 57563
 57564
 57565
 57566
 57567
 57568
 57569
 57570
 57571
 57572
 57573
 57574
 57575
 57576
 57577
 57578
 57579
 57580
 57581
 57582
 57583
 57584
 57585
 57586
 57587
 57588
 57589
 57590
 57591
 57592
 57593
 57594
 57595
 57596
 57597
 57598
 57599
 57600
 57601
 57602
 57603
 57604
 57605
 57606
 57607
 57608
 57609
 57610
 57611
 57612
 57613
 57614
 57615
 57616
 57617
 57618
 57619
 57620
 57621
 57622
 57623
 57624
 57625
 57626
 57627
 57628
 57629
 57630
 57631
 57632
 57633
 57634
 57635
 57636
 57637
 57638
 57639
 57640
 57641
 57642
 57643
 57644
 57645
 57646
 57647
 57648
 57649
 57650
 57651
 57652
 57653
 57654
 57655
 57656
 57657
 57658
 57659
 57660
 57661
 57662
 57663
 57664
 57665
 57666
 57667
 57668
 57669
 57670
 57671
 57672
 57673
 57674
 57675
 57676
 57677
 57678
 57679
 57680
 57681
 57682
 57683
 57684
 57685
 57686
 57687
 57688
 57689
 57690
 57691
 57692
 57693
 57694
 57695
 57696
 57697
 57698
 57699
 57700
 57701
 57702
 57703
 57704
 57705
 57706
 57707
 57708
 57709
 57710
 57711
 57712
 57713
 57714
 57715
 57716
 57717
 57718
 57719
 57720
 57721
 57722
 57723
 57724
 57725
 57726
 57727
 57728
 57729
 57730
 57731
 57732
 57733
 57734
 57735
 57736
 57737
 57738
 57739
 57740
 57741
 57742
 57743
 57744
 57745
 57746
 57747
 57748
 57749
 57750
 57751
 57752
 57753
 57754
 57755
 57756
 57757
 57758
 57759
 57760
 57761
 57762
 57763
 57764
 57765
 57766
 57767
 57768
 57769
 57770
 57771
 57772
 57773
 57774
 57775
 57776
 57777
 57778
 57779
 57780
 57781
 57782
 57783
 57784
 57785
 57786
 57787
 57788
 57789
 57790
 57791
 57792
 57793
 57794
 57795
 57796
 57797
 57798
 57799
 57800
 57801
 57802
 57803
 57804
 57805
 57806
 57807
 57808
 57809
 57810
 57811
 57812
 57813
 57814
 57815
 57816
 57817
 57818
 57819
 57820
 57821
 57822
 57823
 57824
 57825
 57826
 57827
 57828
 57829
 57830
 57831
 57832
 57833
 57834
 57835
 57836
 57837
 57838
 57839
 57840
 57841
 57842
 57843
 57844
 57845
 57846
 57847
 57848
 57849
 57850
 57851
 57852
 57853
 57854
 57855
 57856
 57857
 57858
 57859
 57860
 57861
 57862
 57863
 57864
 57865
 57866
 57867
 57868
 57869
 57870
 57871
 57872
 57873
 57874
 57875
 57876
 57877
 57878
 57879
 57880
 57881
 57882
 57883
 57884
 57885
 57886
 57887
 57888
 57889
 57890
 57891
 57892
 57893
 57894
 57895
 57896
 57897
 57898
 57899
 57900
 57901
 57902
 57903
 57904
 57905
 57906
 57907
 57908
 57909
 57910
 57911
 57912
 57913
 57914
 57915
 57916
 57917
 57918
 57919
 57920
 57921
 57922
 57923
 57924
 57925
 57926
 57927
 57928
 57929
 57930
 57931
 57932
 57933
 57934
 57935
 57936
 57937
 57938
 57939
 57940
 57941
 57942
 57943
 57944
 57945
 57946
 57947
 57948
 57949
 57950
 57951
 57952
 57953
 57954
 57955
 57956
 57957
 57958
 57959
 57960
 57961
 57962
 57963
 57964
 57965
 57966
 57967
 57968
 57969
 57970
 57971
 57972
 57973
 57974
 57975
 57976
 57977
 57978
 57979
 57980
 57981
 57982
 57983
 57984
 57985
 57986
 57987
 57988
 57989
 57990
 57991
 57992
 57993
 57994
 57995
 57996
 57997
 57998
 57999
 58000
 58001
 58002
 58003
 58004
 58005
 58006
 58007
 58008
 58009
 58010
 58011
 58012
 58013
 58014
 58015
 58016
 58017
 58018
 58019
 58020
 58021
 58022
 58023
 58024
 58025
 58026
 58027
 58028
 58029
 58030
 58031
 58032
 58033
 58034
 58035
 58036
 58037
 58038
 58039
 58040
 58041
 58042
 58043
 58044
 58045
 58046
 58047
 58048
 58049
 58050
 58051
 58052
 58053
 58054
 58055
 58056
 58057
 58058
 58059
 58060
 58061
 58062
 58063
 58064
 58065
 58066
 58067
 58068
 58069
 58070
 58071
 58072
 58073
 58074
 58075
 58076
 58077
 58078
 58079
 58080
 58081
 58082
 58083
 58084
 58085
 58086
 58087
 58088
 58089
 58090
 58091
 58092
 58093
 58094
 58095
 58096
 58097
 58098
 58099
 58100
 58101
 58102
 58103
 58104
 58105
 58106
 58107
 58108
 58109
 58110
 58111
 58112
 58113
 58114
 58115
 58116
 58117
 58118
 58119
 58120
 58121
 58122
 58123
 58124
 58125
 58126
 58127
 58128
 58129
 58130
 58131
 58132
 58133
 58134
 58135
 58136
 58137
 58138
 58139
 58140
 58141
 58142
 58143
 58144
 58145
 58146
 58147
 58148
 58149
 58150
 58151
 58152
 58153
 58154
 58155
 58156
 58157
 58158
 58159
 58160
 58161
 58162
 58163
 58164
 58165
 58166
 58167
 58168
 58169
 58170
 58171
 58172
 58173
 58174
 58175
 58176
 58177
 58178
 58179
 58180
 58181
 58182
 58183
 58184
 58185
 58186
 58187
 58188
 58189
 58190
 58191
 58192
 58193
 58194
 58195
 58196
 58197
 58198
 58199
 58200
 58201
 58202
 58203
 58204
 58205
 58206
 58207
 58208
 58209
 58210
 58211
 58212
 58213
 58214
 58215
 58216
 58217
 58218
 58219
 58220
 58221
 58222
 58223
 58224
 58225
 58226
 58227
 58228
 58229
 58230
 58231
 58232
 58233
 58234
 58235
 58236
 58237
 58238
 58239
 58240
 58241
 58242
 58243
 58244
 58245
 58246
 58247
 58248
 58249
 58250
 58251
 58252
 58253
 58254
 58255
 58256
 58257
 58258
 58259
 58260
 58261
 58262
 58263
 58264
 58265
 58266
 58267
 58268
 58269
 58270
 58271
 58272
 58273
 58274
 58275
 58276
 58277
 58278
 58279
 58280
 58281
 58282
 58283
 58284
 58285
 58286
 58287
 58288
 58289
 58290
 58291
 58292
 58293
 58294
 58295
 58296
 58297
 58298
 58299
 58300
 58301
 58302
 58303
 58304
 58305
 58306
 58307
 58308
 58309
 58310
 58311
 58312
 58313
 58314
 58315
 58316
 58317
 58318
 58319
 58320
 58321
 58322
 58323
 58324
 58325
 58326
 58327
 58328
 58329
 58330
 58331
 58332
 58333
 58334
 58335
 58336
 58337
 58338
 58339
 58340
 58341
 58342
 58343
 58344
 58345
 58346
 58347
 58348
 58349
 58350
 58351
 58352
 58353
 58354
 58355
 58356
 58357
 58358
 58359
 58360
 58361
 58362
 58363
 58364
 58365
 58366
 58367
 58368
 58369
 58370
 58371
 58372
 58373
 58374
 58375
 58376
 58377
 58378
 58379
 58380
 58381
 58382
 58383
 58384
 58385
 58386
 58387
 58388
 58389
 58390
 58391
 58392
 58393
 58394
 58395
 58396
 58397
 58398
 58399
 58400
 58401
 58402
 58403
 58404
 58405
 58406
 58407
 58408
 58409
 58410
 58411
 58412
 58413
 58414
 58415
 58416
 58417
 58418
 58419
 58420
 58421
 58422
 58423
 58424
 58425
 58426
 58427
 58428
 58429
 58430
 58431
 58432
 58433
 58434
 58435
 58436
 58437
 58438
 58439
 58440
 58441
 58442
 58443
 58444
 58445
 58446
 58447
 58448
 58449
 58450
 58451
 58452
 58453
 58454
 58455
 58456
 58457
 58458
 58459
 58460
 58461
 58462
 58463
 58464
 58465
 58466
 58467
 58468
 58469
 58470
 58471
 58472
 58473
 58474
 58475
 58476
 58477
 58478
 58479
 58480
 58481
 58482
 58483
 58484
 58485
 58486
 58487
 58488
 58489
 58490
 58491
 58492
 58493
 58494
 58495
 58496
 58497
 58498
 58499
 58500
 58501
 58502
 58503
 58504
 58505
 58506
 58507
 58508
 58509
 58510
 58511
 58512
 58513
 58514
 58515
 58516
 58517
 58518
 58519
 58520
 58521
 58522
 58523
 58524
 58525
 58526
 58527
 58528
 58529
 58530
 58531
 58532
 58533
 58534
 58535
 58536
 58537
 58538
 58539
 58540
 58541
 58542
 58543
 58544
 58545
 58546
 58547
 58548
 58549
 58550
 58551
 58552
 58553
 58554
 58555
 58556
 58557
 58558
 58559
 58560
 58561
 58562
 58563
 58564
 58565
 58566
 58567
 58568
 58569
 58570
 58571
 58572
 58573
 58574
 58575
 58576
 58577
 58578
 58579
 58580
 58581
 58582
 58583
 58584
 58585
 58586
 58587
 58588
 58589
 58590
 58591
 58592
 58593
 58594
 58595
 58596
 58597
 58598
 58599
 58600
 58601
 58602
 58603
 58604
 58605
 58606
 58607
 58608
 58609
 58610
 58611
 58612
 58613
 58614
 58615
 58616
 58617
 58618
 58619
 58620
 58621
 58622
 58623
 58624
 58625
 58626
 58627
 58628
 58629
 58630
 58631
 58632
 58633
 58634
 58635
 58636
 58637
 58638
 58639
 58640
 58641
 58642
 58643
 58644
 58645
 58646
 58647
 58648
 58649
 58650
 58651
 58652
 58653
 58654
 58655
 58656
 58657
 58658
 58659
 58660
 58661
 58662
 58663
 58664
 58665
 58666
 58667
 58668
 58669
 58670
 58671
 58672
 58673
 58674
 58675
 58676
 58677
 58678
 58679
 58680
 58681
 58682
 58683
 58684
 58685
 58686
 58687
 58688
 58689
 58690
 58691
 58692
 58693
 58694
 58695
 58696
 58697
 58698
 58699
 58700
 58701
 58702
 58703
 58704
 58705
 58706
 58707
 58708
 58709
 58710
 58711
 58712
 58713
 58714
 58715
 58716
 58717
 58718
 58719
 58720
 58721
 58722
 58723
 58724
 58725
 58726
 58727
 58728
 58729
 58730
 58731
 58732
 58733
 58734
 58735
 58736
 58737
 58738
 58739
 58740
 58741
 58742
 58743
 58744
 58745
 58746
 58747
 58748
 58749
 58750
 58751
 58752
 58753
 58754
 58755
 58756
 58757
 58758
 58759
 58760
 58761
 58762
 58763
 58764
 58765
 58766
 58767
 58768
 58769
 58770
 58771
 58772
 58773
 58774
 58775
 58776
 58777
 58778
 58779
 58780
 58781
 58782
 58783
 58784
 58785
 58786
 58787
 58788
 58789
 58790
 58791
 58792
 58793
 58794
 58795
 58796
 58797
 58798
 58799
 58800
 58801
 58802
 58803
 58804
 58805
 58806
 58807
 58808
 58809
 58810
 58811
 58812
 58813
 58814
 58815
 58816
 58817
 58818
 58819
 58820
 58821
 58822
 58823
 58824
 58825
 58826
 58827
 58828
 58829
 58830
 58831
 58832
 58833
 58834
 58835
 58836
 58837
 58838
 58839
 58840
 58841
 58842
 58843
 58844
 58845
 58846
 58847
 58848
 58849
 58850
 58851
 58852
 58853
 58854
 58855
 58856
 58857
 58858
 58859
 58860
 58861
 58862
 58863
 58864
 58865
 58866
 58867
 58868
 58869
 58870
 58871
 58872
 58873
 58874
 58875
 58876
 58877
 58878
 58879
 58880
 58881
 58882
 58883
 58884
 58885
 58886
 58887
 58888
 58889
 58890
 58891
 58892
 58893
 58894
 58895
 58896
 58897
 58898
 58899
 58900
 58901
 58902
 58903
 58904
 58905
 58906
 58907
 58908
 58909
 58910
 58911
 58912
 58913
 58914
 58915
 58916
 58917
 58918
 58919
 58920
 58921
 58922
 58923
 58924
 58925
 58926
 58927
 58928
 58929
 58930
 58931
 58932
 58933
 58934
 58935
 58936
 58937
 58938
 58939
 58940
 58941
 58942
 58943
 58944
 58945
 58946
 58947
 58948
 58949
 58950
 58951
 58952
 58953
 58954
 58955
 58956
 58957
 58958
 58959
 58960
 58961
 58962
 58963
 58964
 58965
 58966
 58967
 58968
 58969
 58970
 58971
 58972
 58973
 58974
 58975
 58976
 58977
 58978
 58979
 58980
 58981
 58982
 58983
 58984
 58985
 58986
 58987
 58988
 58989
 58990
 58991
 58992
 58993
 58994
 58995
 58996
 58997
 58998
 58999
 59000
 59001
 59002
 59003
 59004
 59005
 59006
 59007
 59008
 59009
 59010
 59011
 59012
 59013
 59014
 59015
 59016
 59017
 59018
 59019
 59020
 59021
 59022
 59023
 59024
 59025
 59026
 59027
 59028
 59029
 59030
 59031
 59032
 59033
 59034
 59035
 59036
 59037
 59038
 59039
 59040
 59041
 59042
 59043
 59044
 59045
 59046
 59047
 59048
 59049
 59050
 59051
 59052
 59053
 59054
 59055
 59056
 59057
 59058
 59059
 59060
 59061
 59062
 59063
 59064
 59065
 59066
 59067
 59068
 59069
 59070
 59071
 59072
 59073
 59074
 59075
 59076
 59077
 59078
 59079
 59080
 59081
 59082
 59083
 59084
 59085
 59086
 59087
 59088
 59089
 59090
 59091
 59092
 59093
 59094
 59095
 59096
 59097
 59098
 59099
 59100
 59101
 59102
 59103
 59104
 59105
 59106
 59107
 59108
 59109
 59110
 59111
 59112
 59113
 59114
 59115
 59116
 59117
 59118
 59119
 59120
 59121
 59122
 59123
 59124
 59125
 59126
 59127
 59128
 59129
 59130
 59131
 59132
 59133
 59134
 59135
 59136
 59137
 59138
 59139
 59140
 59141
 59142
 59143
 59144
 59145
 59146
 59147
 59148
 59149
 59150
 59151
 59152
 59153
 59154
 59155
 59156
 59157
 59158
 59159
 59160
 59161
 59162
 59163
 59164
 59165
 59166
 59167
 59168
 59169
 59170
 59171
 59172
 59173
 59174
 59175
 59176
 59177
 59178
 59179
 59180
 59181
 59182
 59183
 59184
 59185
 59186
 59187
 59188
 59189
 59190
 59191
 59192
 59193
 59194
 59195
 59196
 59197
 59198
 59199
 59200
 59201
 59202
 59203
 59204
 59205
 59206
 59207
 59208
 59209
 59210
 59211
 59212
 59213
 59214
 59215
 59216
 59217
 59218
 59219
 59220
 59221
 59222
 59223
 59224
 59225
 59226
 59227
 59228
 59229
 59230
 59231
 59232
 59233
 59234
 59235
 59236
 59237
 59238
 59239
 59240
 59241
 59242
 59243
 59244
 59245
 59246
 59247
 59248
 59249
 59250
 59251
 59252
 59253
 59254
 59255
 59256
 59257
 59258
 59259
 59260
 59261
 59262
 59263
 59264
 59265
 59266
 59267
 59268
 59269
 59270
 59271
 59272
 59273
 59274
 59275
 59276
 59277
 59278
 59279
 59280
 59281
 59282
 59283
 59284
 59285
 59286
 59287
 59288
 59289
 59290
 59291
 59292
 59293
 59294
 59295
 59296
 59297
 59298
 59299
 59300
 59301
 59302
 59303
 59304
 59305
 59306
 59307
 59308
 59309
 59310
 59311
 59312
 59313
 59314
 59315
 59316
 59317
 59318
 59319
 59320
 59321
 59322
 59323
 59324
 59325
 59326
 59327
 59328
 59329
 59330
 59331
 59332
 59333
 59334
 59335
 59336
 59337
 59338
 59339
 59340
 59341
 59342
 59343
 59344
 59345
 59346
 59347
 59348
 59349
 59350
 59351
 59352
 59353
 59354
 59355
 59356
 59357
 59358
 59359
 59360
 59361
 59362
 59363
 59364
 59365
 59366
 59367
 59368
 59369
 59370
 59371
 59372
 59373
 59374
 59375
 59376
 59377
 59378
 59379
 59380
 59381
 59382
 59383
 59384
 59385
 59386
 59387
 59388
 59389
 59390
 59391
 59392
 59393
 59394
 59395
 59396
 59397
 59398
 59399
 59400
 59401
 59402
 59403
 59404
 59405
 59406
 59407
 59408
 59409
 59410
 59411
 59412
 59413
 59414
 59415
 59416
 59417
 59418
 59419
 59420
 59421
 59422
 59423
 59424
 59425
 59426
 59427
 59428
 59429
 59430
 59431
 59432
 59433
 59434
 59435
 59436
 59437
 59438
 59439
 59440
 59441
 59442
 59443
 59444
 59445
 59446
 59447
 59448
 59449
 59450
 59451
 59452
 59453
 59454
 59455
 59456
 59457
 59458
 59459
 59460
 59461
 59462
 59463
 59464
 59465
 59466
 59467
 59468
 59469
 59470
 59471
 59472
 59473
 59474
 59475
 59476
 59477
 59478
 59479
 59480
 59481
 59482
 59483
 59484
 59485
 59486
 59487
 59488
 59489
 59490
 59491
 59492
 59493
 59494
 59495
 59496
 59497
 59498
 59499
 59500
 59501
 59502
 59503
 59504
 59505
 59506
 59507
 59508
 59509
 59510
 59511
 59512
 59513
 59514
 59515
 59516
 59517
 59518
 59519
 59520
 59521
 59522
 59523
 59524
 59525
 59526
 59527
 59528
 59529
 59530
 59531
 59532
 59533
 59534
 59535
 59536
 59537
 59538
 59539
 59540
 59541
 59542
 59543
 59544
 59545
 59546
 59547
 59548
 59549
 59550
 59551
 59552
 59553
 59554
 59555
 59556
 59557
 59558
 59559
 59560
 59561
 59562
 59563
 59564
 59565
 59566
 59567
 59568
 59569
 59570
 59571
 59572
 59573
 59574
 59575
 59576
 59577
 59578
 59579
 59580
 59581
 59582
 59583
 59584
 59585
 59586
 59587
 59588
 59589
 59590
 59591
 59592
 59593
 59594
 59595
 59596
 59597
 59598
 59599
 59600
 59601
 59602
 59603
 59604
 59605
 59606
 59607
 59608
 59609
 59610
 59611
 59612
 59613
 59614
 59615
 59616
 59617
 59618
 59619
 59620
 59621
 59622
 59623
 59624
 59625
 59626
 59627
 59628
 59629
 59630
 59631
 59632
 59633
 59634
 59635
 59636
 59637
 59638
 59639
 59640
 59641
 59642
 59643
 59644
 59645
 59646
 59647
 59648
 59649
 59650
 59651
 59652
 59653
 59654
 59655
 59656
 59657
 59658
 59659
 59660
 59661
 59662
 59663
 59664
 59665
 59666
 59667
 59668
 59669
 59670
 59671
 59672
 59673
 59674
 59675
 59676
 59677
 59678
 59679
 59680
 59681
 59682
 59683
 59684
 59685
 59686
 59687
 59688
 59689
 59690
 59691
 59692
 59693
 59694
 59695
 59696
 59697
 59698
 59699
 59700
 59701
 59702
 59703
 59704
 59705
 59706
 59707
 59708
 59709
 59710
 59711
 59712
 59713
 59714
 59715
 59716
 59717
 59718
 59719
 59720
 59721
 59722
 59723
 59724
 59725
 59726
 59727
 59728
 59729
 59730
 59731
 59732
 59733
 59734
 59735
 59736
 59737
 59738
 59739
 59740
 59741
 59742
 59743
 59744
 59745
 59746
 59747
 59748
 59749
 59750
 59751
 59752
 59753
 59754
 59755
 59756
 59757
 59758
 59759
 59760
 59761
 59762
 59763
 59764
 59765
 59766
 59767
 59768
 59769
 59770
 59771
 59772
 59773
 59774
 59775
 59776
 59777
 59778
 59779
 59780
 59781
 59782
 59783
 59784
 59785
 59786
 59787
 59788
 59789
 59790
 59791
 59792
 59793
 59794
 59795
 59796
 59797
 59798
 59799
 59800
 59801
 59802
 59803
 59804
 59805
 59806
 59807
 59808
 59809
 59810
 59811
 59812
 59813
 59814
 59815
 59816
 59817
 59818
 59819
 59820
 59821
 59822
 59823
 59824
 59825
 59826
 59827
 59828
 59829
 59830
 59831
 59832
 59833
 59834
 59835
 59836
 59837
 59838
 59839
 59840
 59841
 59842
 59843
 59844
 59845
 59846
 59847
 59848
 59849
 59850
 59851
 59852
 59853
 59854
 59855
 59856
 59857
 59858
 59859
 59860
 59861
 59862
 59863
 59864
 59865
 59866
 59867
 59868
 59869
 59870
 59871
 59872
 59873
 59874
 59875
 59876
 59877
 59878
 59879
 59880
 59881
 59882
 59883
 59884
 59885
 59886
 59887
 59888
 59889
 59890
 59891
 59892
 59893
 59894
 59895
 59896
 59897
 59898
 59899
 59900
 59901
 59902
 59903
 59904
 59905
 59906
 59907
 59908
 59909
 59910
 59911
 59912
 59913
 59914
 59915
 59916
 59917
 59918
 59919
 59920
 59921
 59922
 59923
 59924
 59925
 59926
 59927
 59928
 59929
 59930
 59931
 59932
 59933
 59934
 59935
 59936
 59937
 59938
 59939
 59940
 59941
 59942
 59943
 59944
 59945
 59946
 59947
 59948
 59949
 59950
 59951
 59952
 59953
 59954
 59955
 59956
 59957
 59958
 59959
 59960
 59961
 59962
 59963
 59964
 59965
 59966
 59967
 59968
 59969
 59970
 59971
 59972
 59973
 59974
 59975
 59976
 59977
 59978
 59979
 59980
 59981
 59982
 59983
 59984
 59985
 59986
 59987
 59988
 59989
 59990
 59991
 59992
 59993
 59994
 59995
 59996
 59997
 59998
 59999
 60000
 60001
 60002
 60003
 60004
 60005
 60006
 60007
 60008
 60009
 60010
 60011
 60012
 60013
 60014
 60015
 60016
 60017
 60018
 60019
 60020
 60021
 60022
 60023
 60024
 60025
 60026
 60027
 60028
 60029
 60030
 60031
 60032
 60033
 60034
 60035
 60036
 60037
 60038
 60039
 60040
 60041
 60042
 60043
 60044
 60045
 60046
 60047
 60048
 60049
 60050
 60051
 60052
 60053
 60054
 60055
 60056
 60057
 60058
 60059
 60060
 60061
 60062
 60063
 60064
 60065
 60066
 60067
 60068
 60069
 60070
 60071
 60072
 60073
 60074
 60075
 60076
 60077
 60078
 60079
 60080
 60081
 60082
 60083
 60084
 60085
 60086
 60087
 60088
 60089
 60090
 60091
 60092
 60093
 60094
 60095
 60096
 60097
 60098
 60099
 60100
 60101
 60102
 60103
 60104
 60105
 60106
 60107
 60108
 60109
 60110
 60111
 60112
 60113
 60114
 60115
 60116
 60117
 60118
 60119
 60120
 60121
 60122
 60123
 60124
 60125
 60126
 60127
 60128
 60129
 60130
 60131
 60132
 60133
 60134
 60135
 60136
 60137
 60138
 60139
 60140
 60141
 60142
 60143
 60144
 60145
 60146
 60147
 60148
 60149
 60150
 60151
 60152
 60153
 60154
 60155
 60156
 60157
 60158
 60159
 60160
 60161
 60162
 60163
 60164
 60165
 60166
 60167
 60168
 60169
 60170
 60171
 60172
 60173
 60174
 60175
 60176
 60177
 60178
 60179
 60180
 60181
 60182
 60183
 60184
 60185
 60186
 60187
 60188
 60189
 60190
 60191
 60192
 60193
 60194
 60195
 60196
 60197
 60198
 60199
 60200
 60201
 60202
 60203
 60204
 60205
 60206
 60207
 60208
 60209
 60210
 60211
 60212
 60213
 60214
 60215
 60216
 60217
 60218
 60219
 60220
 60221
 60222
 60223
 60224
 60225
 60226
 60227
 60228
 60229
 60230
 60231
 60232
 60233
 60234
 60235
 60236
 60237
 60238
 60239
 60240
 60241
 60242
 60243
 60244
 60245
 60246
 60247
 60248
 60249
 60250
 60251
 60252
 60253
 60254
 60255
 60256
 60257
 60258
 60259
 60260
 60261
 60262
 60263
 60264
 60265
 60266
 60267
 60268
 60269
 60270
 60271
 60272
 60273
 60274
 60275
 60276
 60277
 60278
 60279
 60280
 60281
 60282
 60283
 60284
 60285
 60286
 60287
 60288
 60289
 60290
 60291
 60292
 60293
 60294
 60295
 60296
 60297
 60298
 60299
 60300
 60301
 60302
 60303
 60304
 60305
 60306
 60307
 60308
 60309
 60310
 60311
 60312
 60313
 60314
 60315
 60316
 60317
 60318
 60319
 60320
 60321
 60322
 60323
 60324
 60325
 60326
 60327
 60328
 60329
 60330
 60331
 60332
 60333
 60334
 60335
 60336
 60337
 60338
 60339
 60340
 60341
 60342
 60343
 60344
 60345
 60346
 60347
 60348
 60349
 60350
 60351
 60352
 60353
 60354
 60355
 60356
 60357
 60358
 60359
 60360
 60361
 60362
 60363
 60364
 60365
 60366
 60367
 60368
 60369
 60370
 60371
 60372
 60373
 60374
 60375
 60376
 60377
 60378
 60379
 60380
 60381
 60382
 60383
 60384
 60385
 60386
 60387
 60388
 60389
 60390
 60391
 60392
 60393
 60394
 60395
 60396
 60397
 60398
 60399
 60400
 60401
 60402
 60403
 60404
 60405
 60406
 60407
 60408
 60409
 60410
 60411
 60412
 60413
 60414
 60415
 60416
 60417
 60418
 60419
 60420
 60421
 60422
 60423
 60424
 60425
 60426
 60427
 60428
 60429
 60430
 60431
 60432
 60433
 60434
 60435
 60436
 60437
 60438
 60439
 60440
 60441
 60442
 60443
 60444
 60445
 60446
 60447
 60448
 60449
 60450
 60451
 60452
 60453
 60454
 60455
 60456
 60457
 60458
 60459
 60460
 60461
 60462
 60463
 60464
 60465
 60466
 60467
 60468
 60469
 60470
 60471
 60472
 60473
 60474
 60475
 60476
 60477
 60478
 60479
 60480
 60481
 60482
 60483
 60484
 60485
 60486
 60487
 60488
 60489
 60490
 60491
 60492
 60493
 60494
 60495
 60496
 60497
 60498
 60499
 60500
 60501
 60502
 60503
 60504
 60505
 60506
 60507
 60508
 60509
 60510
 60511
 60512
 60513
 60514
 60515
 60516
 60517
 60518
 60519
 60520
 60521
 60522
 60523
 60524
 60525
 60526
 60527
 60528
 60529
 60530
 60531
 60532
 60533
 60534
 60535
 60536
 60537
 60538
 60539
 60540
 60541
 60542
 60543
 60544
 60545
 60546
 60547
 60548
 60549
 60550
 60551
 60552
 60553
 60554
 60555
 60556
 60557
 60558
 60559
 60560
 60561
 60562
 60563
 60564
 60565
 60566
 60567
 60568
 60569
 60570
 60571
 60572
 60573
 60574
 60575
 60576
 60577
 60578
 60579
 60580
 60581
 60582
 60583
 60584
 60585
 60586
 60587
 60588
 60589
 60590
 60591
 60592
 60593
 60594
 60595
 60596
 60597
 60598
 60599
 60600
 60601
 60602
 60603
 60604
 60605
 60606
 60607
 60608
 60609
 60610
 60611
 60612
 60613
 60614
 60615
 60616
 60617
 60618
 60619
 60620
 60621
 60622
 60623
 60624
 60625
 60626
 60627
 60628
 60629
 60630
 60631
 60632
 60633
 60634
 60635
 60636
 60637
 60638
 60639
 60640
 60641
 60642
 60643
 60644
 60645
 60646
 60647
 60648
 60649
 60650
 60651
 60652
 60653
 60654
 60655
 60656
 60657
 60658
 60659
 60660
 60661
 60662
 60663
 60664
 60665
 60666
 60667
 60668
 60669
 60670
 60671
 60672
 60673
 60674
 60675
 60676
 60677
 60678
 60679
 60680
 60681
 60682
 60683
 60684
 60685
 60686
 60687
 60688
 60689
 60690
 60691
 60692
 60693
 60694
 60695
 60696
 60697
 60698
 60699
 60700
 60701
 60702
 60703
 60704
 60705
 60706
 60707
 60708
 60709
 60710
 60711
 60712
 60713
 60714
 60715
 60716
 60717
 60718
 60719
 60720
 60721
 60722
 60723
 60724
 60725
 60726
 60727
 60728
 60729
 60730
 60731
 60732
 60733
 60734
 60735
 60736
 60737
 60738
 60739
 60740
 60741
 60742
 60743
 60744
 60745
 60746
 60747
 60748
 60749
 60750
 60751
 60752
 60753
 60754
 60755
 60756
 60757
 60758
 60759
 60760
 60761
 60762
 60763
 60764
 60765
 60766
 60767
 60768
 60769
 60770
 60771
 60772
 60773
 60774
 60775
 60776
 60777
 60778
 60779
 60780
 60781
 60782
 60783
 60784
 60785
 60786
 60787
 60788
 60789
 60790
 60791
 60792
 60793
 60794
 60795
 60796
 60797
 60798
 60799
 60800
 60801
 60802
 60803
 60804
 60805
 60806
 60807
 60808
 60809
 60810
 60811
 60812
 60813
 60814
 60815
 60816
 60817
 60818
 60819
 60820
 60821
 60822
 60823
 60824
 60825
 60826
 60827
 60828
 60829
 60830
 60831
 60832
 60833
 60834
 60835
 60836
 60837
 60838
 60839
 60840
 60841
 60842
 60843
 60844
 60845
 60846
 60847
 60848
 60849
 60850
 60851
 60852
 60853
 60854
 60855
 60856
 60857
 60858
 60859
 60860
 60861
 60862
 60863
 60864
 60865
 60866
 60867
 60868
 60869
 60870
 60871
 60872
 60873
 60874
 60875
 60876
 60877
 60878
 60879
 60880
 60881
 60882
 60883
 60884
 60885
 60886
 60887
 60888
 60889
 60890
 60891
 60892
 60893
 60894
 60895
 60896
 60897
 60898
 60899
 60900
 60901
 60902
 60903
 60904
 60905
 60906
 60907
 60908
 60909
 60910
 60911
 60912
 60913
 60914
 60915
 60916
 60917
 60918
 60919
 60920
 60921
 60922
 60923
 60924
 60925
 60926
 60927
 60928
 60929
 60930
 60931
 60932
 60933
 60934
 60935
 60936
 60937
 60938
 60939
 60940
 60941
 60942
 60943
 60944
 60945
 60946
 60947
 60948
 60949
 60950
 60951
 60952
 60953
 60954
 60955
 60956
 60957
 60958
 60959
 60960
 60961
 60962
 60963
 60964
 60965
 60966
 60967
 60968
 60969
 60970
 60971
 60972
 60973
 60974
 60975
 60976
 60977
 60978
 60979
 60980
 60981
 60982
 60983
 60984
 60985
 60986
 60987
 60988
 60989
 60990
 60991
 60992
 60993
 60994
 60995
 60996
 60997
 60998
 60999
 61000
 61001
 61002
 61003
 61004
 61005
 61006
 61007
 61008
 61009
 61010
 61011
 61012
 61013
 61014
 61015
 61016
 61017
 61018
 61019
 61020
 61021
 61022
 61023
 61024
 61025
 61026
 61027
 61028
 61029
 61030
 61031
 61032
 61033
 61034
 61035
 61036
 61037
 61038
 61039
 61040
 61041
 61042
 61043
 61044
 61045
 61046
 61047
 61048
 61049
 61050
 61051
 61052
 61053
 61054
 61055
 61056
 61057
 61058
 61059
 61060
 61061
 61062
 61063
 61064
 61065
 61066
 61067
 61068
 61069
 61070
 61071
 61072
 61073
 61074
 61075
 61076
 61077
 61078
 61079
 61080
 61081
 61082
 61083
 61084
 61085
 61086
 61087
 61088
 61089
 61090
 61091
 61092
 61093
 61094
 61095
 61096
 61097
 61098
 61099
 61100
 61101
 61102
 61103
 61104
 61105
 61106
 61107
 61108
 61109
 61110
 61111
 61112
 61113
 61114
 61115
 61116
 61117
 61118
 61119
 61120
 61121
 61122
 61123
 61124
 61125
 61126
 61127
 61128
 61129
 61130
 61131
 61132
 61133
 61134
 61135
 61136
 61137
 61138
 61139
 61140
 61141
 61142
 61143
 61144
 61145
 61146
 61147
 61148
 61149
 61150
 61151
 61152
 61153
 61154
 61155
 61156
 61157
 61158
 61159
 61160
 61161
 61162
 61163
 61164
 61165
 61166
 61167
 61168
 61169
 61170
 61171
 61172
 61173
 61174
 61175
 61176
 61177
 61178
 61179
 61180
 61181
 61182
 61183
 61184
 61185
 61186
 61187
 61188
 61189
 61190
 61191
 61192
 61193
 61194
 61195
 61196
 61197
 61198
 61199
 61200
 61201
 61202
 61203
 61204
 61205
 61206
 61207
 61208
 61209
 61210
 61211
 61212
 61213
 61214
 61215
 61216
 61217
 61218
 61219
 61220
 61221
 61222
 61223
 61224
 61225
 61226
 61227
 61228
 61229
 61230
 61231
 61232
 61233
 61234
 61235
 61236
 61237
 61238
 61239
 61240
 61241
 61242
 61243
 61244
 61245
 61246
 61247
 61248
 61249
 61250
 61251
 61252
 61253
 61254
 61255
 61256
 61257
 61258
 61259
 61260
 61261
 61262
 61263
 61264
 61265
 61266
 61267
 61268
 61269
 61270
 61271
 61272
 61273
 61274
 61275
 61276
 61277
 61278
 61279
 61280
 61281
 61282
 61283
 61284
 61285
 61286
 61287
 61288
 61289
 61290
 61291
 61292
 61293
 61294
 61295
 61296
 61297
 61298
 61299
 61300
 61301
 61302
 61303
 61304
 61305
 61306
 61307
 61308
 61309
 61310
 61311
 61312
 61313
 61314
 61315
 61316
 61317
 61318
 61319
 61320
 61321
 61322
 61323
 61324
 61325
 61326
 61327
 61328
 61329
 61330
 61331
 61332
 61333
 61334
 61335
 61336
 61337
 61338
 61339
 61340
 61341
 61342
 61343
 61344
 61345
 61346
 61347
 61348
 61349
 61350
 61351
 61352
 61353
 61354
 61355
 61356
 61357
 61358
 61359
 61360
 61361
 61362
 61363
 61364
 61365
 61366
 61367
 61368
 61369
 61370
 61371
 61372
 61373
 61374
 61375
 61376
 61377
 61378
 61379
 61380
 61381
 61382
 61383
 61384
 61385
 61386
 61387
 61388
 61389
 61390
 61391
 61392
 61393
 61394
 61395
 61396
 61397
 61398
 61399
 61400
 61401
 61402
 61403
 61404
 61405
 61406
 61407
 61408
 61409
 61410
 61411
 61412
 61413
 61414
 61415
 61416
 61417
 61418
 61419
 61420
 61421
 61422
 61423
 61424
 61425
 61426
 61427
 61428
 61429
 61430
 61431
 61432
 61433
 61434
 61435
 61436
 61437
 61438
 61439
 61440
 61441
 61442
 61443
 61444
 61445
 61446
 61447
 61448
 61449
 61450
 61451
 61452
 61453
 61454
 61455
 61456
 61457
 61458
 61459
 61460
 61461
 61462
 61463
 61464
 61465
 61466
 61467
 61468
 61469
 61470
 61471
 61472
 61473
 61474
 61475
 61476
 61477
 61478
 61479
 61480
 61481
 61482
 61483
 61484
 61485
 61486
 61487
 61488
 61489
 61490
 61491
 61492
 61493
 61494
 61495
 61496
 61497
 61498
 61499
 61500
 61501
 61502
 61503
 61504
 61505
 61506
 61507
 61508
 61509
 61510
 61511
 61512
 61513
 61514
 61515
 61516
 61517
 61518
 61519
 61520
 61521
 61522
 61523
 61524
 61525
 61526
 61527
 61528
 61529
 61530
 61531
 61532
 61533
 61534
 61535
 61536
 61537
 61538
 61539
 61540
 61541
 61542
 61543
 61544
 61545
 61546
 61547
 61548
 61549
 61550
 61551
 61552
 61553
 61554
 61555
 61556
 61557
 61558
 61559
 61560
 61561
 61562
 61563
 61564
 61565
 61566
 61567
 61568
 61569
 61570
 61571
 61572
 61573
 61574
 61575
 61576
 61577
 61578
 61579
 61580
 61581
 61582
 61583
 61584
 61585
 61586
 61587
 61588
 61589
 61590
 61591
 61592
 61593
 61594
 61595
 61596
 61597
 61598
 61599
 61600
 61601
 61602
 61603
 61604
 61605
 61606
 61607
 61608
 61609
 61610
 61611
 61612
 61613
 61614
 61615
 61616
 61617
 61618
 61619
 61620
 61621
 61622
 61623
 61624
 61625
 61626
 61627
 61628
 61629
 61630
 61631
 61632
 61633
 61634
 61635
 61636
 61637
 61638
 61639
 61640
 61641
 61642
 61643
 61644
 61645
 61646
 61647
 61648
 61649
 61650
 61651
 61652
 61653
 61654
 61655
 61656
 61657
 61658
 61659
 61660
 61661
 61662
 61663
 61664
 61665
 61666
 61667
 61668
 61669
 61670
 61671
 61672
 61673
 61674
 61675
 61676
 61677
 61678
 61679
 61680
 61681
 61682
 61683
 61684
 61685
 61686
 61687
 61688
 61689
 61690
 61691
 61692
 61693
 61694
 61695
 61696
 61697
 61698
 61699
 61700
 61701
 61702
 61703
 61704
 61705
 61706
 61707
 61708
 61709
 61710
 61711
 61712
 61713
 61714
 61715
 61716
 61717
 61718
 61719
 61720
 61721
 61722
 61723
 61724
 61725
 61726
 61727
 61728
 61729
 61730
 61731
 61732
 61733
 61734
 61735
 61736
 61737
 61738
 61739
 61740
 61741
 61742
 61743
 61744
 61745
 61746
 61747
 61748
 61749
 61750
 61751
 61752
 61753
 61754
 61755
 61756
 61757
 61758
 61759
 61760
 61761
 61762
 61763
 61764
 61765
 61766
 61767
 61768
 61769
 61770
 61771
 61772
 61773
 61774
 61775
 61776
 61777
 61778
 61779
 61780
 61781
 61782
 61783
 61784
 61785
 61786
 61787
 61788
 61789
 61790
 61791
 61792
 61793
 61794
 61795
 61796
 61797
 61798
 61799
 61800
 61801
 61802
 61803
 61804
 61805
 61806
 61807
 61808
 61809
 61810
 61811
 61812
 61813
 61814
 61815
 61816
 61817
 61818
 61819
 61820
 61821
 61822
 61823
 61824
 61825
 61826
 61827
 61828
 61829
 61830
 61831
 61832
 61833
 61834
 61835
 61836
 61837
 61838
 61839
 61840
 61841
 61842
 61843
 61844
 61845
 61846
 61847
 61848
 61849
 61850
 61851
 61852
 61853
 61854
 61855
 61856
 61857
 61858
 61859
 61860
 61861
 61862
 61863
 61864
 61865
 61866
 61867
 61868
 61869
 61870
 61871
 61872
 61873
 61874
 61875
 61876
 61877
 61878
 61879
 61880
 61881
 61882
 61883
 61884
 61885
 61886
 61887
 61888
 61889
 61890
 61891
 61892
 61893
 61894
 61895
 61896
 61897
 61898
 61899
 61900
 61901
 61902
 61903
 61904
 61905
 61906
 61907
 61908
 61909
 61910
 61911
 61912
 61913
 61914
 61915
 61916
 61917
 61918
 61919
 61920
 61921
 61922
 61923
 61924
 61925
 61926
 61927
 61928
 61929
 61930
 61931
 61932
 61933
 61934
 61935
 61936
 61937
 61938
 61939
 61940
 61941
 61942
 61943
 61944
 61945
 61946
 61947
 61948
 61949
 61950
 61951
 61952
 61953
 61954
 61955
 61956
 61957
 61958
 61959
 61960
 61961
 61962
 61963
 61964
 61965
 61966
 61967
 61968
 61969
 61970
 61971
 61972
 61973
 61974
 61975
 61976
 61977
 61978
 61979
 61980
 61981
 61982
 61983
 61984
 61985
 61986
 61987
 61988
 61989
 61990
 61991
 61992
 61993
 61994
 61995
 61996
 61997
 61998
 61999
 62000
 62001
 62002
 62003
 62004
 62005
 62006
 62007
 62008
 62009
 62010
 62011
 62012
 62013
 62014
 62015
 62016
 62017
 62018
 62019
 62020
 62021
 62022
 62023
 62024
 62025
 62026
 62027
 62028
 62029
 62030
 62031
 62032
 62033
 62034
 62035
 62036
 62037
 62038
 62039
 62040
 62041
 62042
 62043
 62044
 62045
 62046
 62047
 62048
 62049
 62050
 62051
 62052
 62053
 62054
 62055
 62056
 62057
 62058
 62059
 62060
 62061
 62062
 62063
 62064
 62065
 62066
 62067
 62068
 62069
 62070
 62071
 62072
 62073
 62074
 62075
 62076
 62077
 62078
 62079
 62080
 62081
 62082
 62083
 62084
 62085
 62086
 62087
 62088
 62089
 62090
 62091
 62092
 62093
 62094
 62095
 62096
 62097
 62098
 62099
 62100
 62101
 62102
 62103
 62104
 62105
 62106
 62107
 62108
 62109
 62110
 62111
 62112
 62113
 62114
 62115
 62116
 62117
 62118
 62119
 62120
 62121
 62122
 62123
 62124
 62125
 62126
 62127
 62128
 62129
 62130
 62131
 62132
 62133
 62134
 62135
 62136
 62137
 62138
 62139
 62140
 62141
 62142
 62143
 62144
 62145
 62146
 62147
 62148
 62149
 62150
 62151
 62152
 62153
 62154
 62155
 62156
 62157
 62158
 62159
 62160
 62161
 62162
 62163
 62164
 62165
 62166
 62167
 62168
 62169
 62170
 62171
 62172
 62173
 62174
 62175
 62176
 62177
 62178
 62179
 62180
 62181
 62182
 62183
 62184
 62185
 62186
 62187
 62188
 62189
 62190
 62191
 62192
 62193
 62194
 62195
 62196
 62197
 62198
 62199
 62200
 62201
 62202
 62203
 62204
 62205
 62206
 62207
 62208
 62209
 62210
 62211
 62212
 62213
 62214
 62215
 62216
 62217
 62218
 62219
 62220
 62221
 62222
 62223
 62224
 62225
 62226
 62227
 62228
 62229
 62230
 62231
 62232
 62233
 62234
 62235
 62236
 62237
 62238
 62239
 62240
 62241
 62242
 62243
 62244
 62245
 62246
 62247
 62248
 62249
 62250
 62251
 62252
 62253
 62254
 62255
 62256
 62257
 62258
 62259
 62260
 62261
 62262
 62263
 62264
 62265
 62266
 62267
 62268
 62269
 62270
 62271
 62272
 62273
 62274
 62275
 62276
 62277
 62278
 62279
 62280
 62281
 62282
 62283
 62284
 62285
 62286
 62287
 62288
 62289
 62290
 62291
 62292
 62293
 62294
 62295
 62296
 62297
 62298
 62299
 62300
 62301
 62302
 62303
 62304
 62305
 62306
 62307
 62308
 62309
 62310
 62311
 62312
 62313
 62314
 62315
 62316
 62317
 62318
 62319
 62320
 62321
 62322
 62323
 62324
 62325
 62326
 62327
 62328
 62329
 62330
 62331
 62332
 62333
 62334
 62335
 62336
 62337
 62338
 62339
 62340
 62341
 62342
 62343
 62344
 62345
 62346
 62347
 62348
 62349
 62350
 62351
 62352
 62353
 62354
 62355
 62356
 62357
 62358
 62359
 62360
 62361
 62362
 62363
 62364
 62365
 62366
 62367
 62368
 62369
 62370
 62371
 62372
 62373
 62374
 62375
 62376
 62377
 62378
 62379
 62380
 62381
 62382
 62383
 62384
 62385
 62386
 62387
 62388
 62389
 62390
 62391
 62392
 62393
 62394
 62395
 62396
 62397
 62398
 62399
 62400
 62401
 62402
 62403
 62404
 62405
 62406
 62407
 62408
 62409
 62410
 62411
 62412
 62413
 62414
 62415
 62416
 62417
 62418
 62419
 62420
 62421
 62422
 62423
 62424
 62425
 62426
 62427
 62428
 62429
 62430
 62431
 62432
 62433
 62434
 62435
 62436
 62437
 62438
 62439
 62440
 62441
 62442
 62443
 62444
 62445
 62446
 62447
 62448
 62449
 62450
 62451
 62452
 62453
 62454
 62455
 62456
 62457
 62458
 62459
 62460
 62461
 62462
 62463
 62464
 62465
 62466
 62467
 62468
 62469
 62470
 62471
 62472
 62473
 62474
 62475
 62476
 62477
 62478
 62479
 62480
 62481
 62482
 62483
 62484
 62485
 62486
 62487
 62488
 62489
 62490
 62491
 62492
 62493
 62494
 62495
 62496
 62497
 62498
 62499
 62500
 62501
 62502
 62503
 62504
 62505
 62506
 62507
 62508
 62509
 62510
 62511
 62512
 62513
 62514
 62515
 62516
 62517
 62518
 62519
 62520
 62521
 62522
 62523
 62524
 62525
 62526
 62527
 62528
 62529
 62530
 62531
 62532
 62533
 62534
 62535
 62536
 62537
 62538
 62539
 62540
 62541
 62542
 62543
 62544
 62545
 62546
 62547
 62548
 62549
 62550
 62551
 62552
 62553
 62554
 62555
 62556
 62557
 62558
 62559
 62560
 62561
 62562
 62563
 62564
 62565
 62566
 62567
 62568
 62569
 62570
 62571
 62572
 62573
 62574
 62575
 62576
 62577
 62578
 62579
 62580
 62581
 62582
 62583
 62584
 62585
 62586
 62587
 62588
 62589
 62590
 62591
 62592
 62593
 62594
 62595
 62596
 62597
 62598
 62599
 62600
 62601
 62602
 62603
 62604
 62605
 62606
 62607
 62608
 62609
 62610
 62611
 62612
 62613
 62614
 62615
 62616
 62617
 62618
 62619
 62620
 62621
 62622
 62623
 62624
 62625
 62626
 62627
 62628
 62629
 62630
 62631
 62632
 62633
 62634
 62635
 62636
 62637
 62638
 62639
 62640
 62641
 62642
 62643
 62644
 62645
 62646
 62647
 62648
 62649
 62650
 62651
 62652
 62653
 62654
 62655
 62656
 62657
 62658
 62659
 62660
 62661
 62662
 62663
 62664
 62665
 62666
 62667
 62668
 62669
 62670
 62671
 62672
 62673
 62674
 62675
 62676
 62677
 62678
 62679
 62680
 62681
 62682
 62683
 62684
 62685
 62686
 62687
 62688
 62689
 62690
 62691
 62692
 62693
 62694
 62695
 62696
 62697
 62698
 62699
 62700
 62701
 62702
 62703
 62704
 62705
 62706
 62707
 62708
 62709
 62710
 62711
 62712
 62713
 62714
 62715
 62716
 62717
 62718
 62719
 62720
 62721
 62722
 62723
 62724
 62725
 62726
 62727
 62728
 62729
 62730
 62731
 62732
 62733
 62734
 62735
 62736
 62737
 62738
 62739
 62740
 62741
 62742
 62743
 62744
 62745
 62746
 62747
 62748
 62749
 62750
 62751
 62752
 62753
 62754
 62755
 62756
 62757
 62758
 62759
 62760
 62761
 62762
 62763
 62764
 62765
 62766
 62767
 62768
 62769
 62770
 62771
 62772
 62773
 62774
 62775
 62776
 62777
 62778
 62779
 62780
 62781
 62782
 62783
 62784
 62785
 62786
 62787
 62788
 62789
 62790
 62791
 62792
 62793
 62794
 62795
 62796
 62797
 62798
 62799
 62800
 62801
 62802
 62803
 62804
 62805
 62806
 62807
 62808
 62809
 62810
 62811
 62812
 62813
 62814
 62815
 62816
 62817
 62818
 62819
 62820
 62821
 62822
 62823
 62824
 62825
 62826
 62827
 62828
 62829
 62830
 62831
 62832
 62833
 62834
 62835
 62836
 62837
 62838
 62839
 62840
 62841
 62842
 62843
 62844
 62845
 62846
 62847
 62848
 62849
 62850
 62851
 62852
 62853
 62854
 62855
 62856
 62857
 62858
 62859
 62860
 62861
 62862
 62863
 62864
 62865
 62866
 62867
 62868
 62869
 62870
 62871
 62872
 62873
 62874
 62875
 62876
 62877
 62878
 62879
 62880
 62881
 62882
 62883
 62884
 62885
 62886
 62887
 62888
 62889
 62890
 62891
 62892
 62893
 62894
 62895
 62896
 62897
 62898
 62899
 62900
 62901
 62902
 62903
 62904
 62905
 62906
 62907
 62908
 62909
 62910
 62911
 62912
 62913
 62914
 62915
 62916
 62917
 62918
 62919
 62920
 62921
 62922
 62923
 62924
 62925
 62926
 62927
 62928
 62929
 62930
 62931
 62932
 62933
 62934
 62935
 62936
 62937
 62938
 62939
 62940
 62941
 62942
 62943
 62944
 62945
 62946
 62947
 62948
 62949
 62950
 62951
 62952
 62953
 62954
 62955
 62956
 62957
 62958
 62959
 62960
 62961
 62962
 62963
 62964
 62965
 62966
 62967
 62968
 62969
 62970
 62971
 62972
 62973
 62974
 62975
 62976
 62977
 62978
 62979
 62980
 62981
 62982
 62983
 62984
 62985
 62986
 62987
 62988
 62989
 62990
 62991
 62992
 62993
 62994
 62995
 62996
 62997
 62998
 62999
 63000
 63001
 63002
 63003
 63004
 63005
 63006
 63007
 63008
 63009
 63010
 63011
 63012
 63013
 63014
 63015
 63016
 63017
 63018
 63019
 63020
 63021
 63022
 63023
 63024
 63025
 63026
 63027
 63028
 63029
 63030
 63031
 63032
 63033
 63034
 63035
 63036
 63037
 63038
 63039
 63040
 63041
 63042
 63043
 63044
 63045
 63046
 63047
 63048
 63049
 63050
 63051
 63052
 63053
 63054
 63055
 63056
 63057
 63058
 63059
 63060
 63061
 63062
 63063
 63064
 63065
 63066
 63067
 63068
 63069
 63070
 63071
 63072
 63073
 63074
 63075
 63076
 63077
 63078
 63079
 63080
 63081
 63082
 63083
 63084
 63085
 63086
 63087
 63088
 63089
 63090
 63091
 63092
 63093
 63094
 63095
 63096
 63097
 63098
 63099
 63100
 63101
 63102
 63103
 63104
 63105
 63106
 63107
 63108
 63109
 63110
 63111
 63112
 63113
 63114
 63115
 63116
 63117
 63118
 63119
 63120
 63121
 63122
 63123
 63124
 63125
 63126
 63127
 63128
 63129
 63130
 63131
 63132
 63133
 63134
 63135
 63136
 63137
 63138
 63139
 63140
 63141
 63142
 63143
 63144
 63145
 63146
 63147
 63148
 63149
 63150
 63151
 63152
 63153
 63154
 63155
 63156
 63157
 63158
 63159
 63160
 63161
 63162
 63163
 63164
 63165
 63166
 63167
 63168
 63169
 63170
 63171
 63172
 63173
 63174
 63175
 63176
 63177
 63178
 63179
 63180
 63181
 63182
 63183
 63184
 63185
 63186
 63187
 63188
 63189
 63190
 63191
 63192
 63193
 63194
 63195
 63196
 63197
 63198
 63199
 63200
 63201
 63202
 63203
 63204
 63205
 63206
 63207
 63208
 63209
 63210
 63211
 63212
 63213
 63214
 63215
 63216
 63217
 63218
 63219
 63220
 63221
 63222
 63223
 63224
 63225
 63226
 63227
 63228
 63229
 63230
 63231
 63232
 63233
 63234
 63235
 63236
 63237
 63238
 63239
 63240
 63241
 63242
 63243
 63244
 63245
 63246
 63247
 63248
 63249
 63250
 63251
 63252
 63253
 63254
 63255
 63256
 63257
 63258
 63259
 63260
 63261
 63262
 63263
 63264
 63265
 63266
 63267
 63268
 63269
 63270
 63271
 63272
 63273
 63274
 63275
 63276
 63277
 63278
 63279
 63280
 63281
 63282
 63283
 63284
 63285
 63286
 63287
 63288
 63289
 63290
 63291
 63292
 63293
 63294
 63295
 63296
 63297
 63298
 63299
 63300
 63301
 63302
 63303
 63304
 63305
 63306
 63307
 63308
 63309
 63310
 63311
 63312
 63313
 63314
 63315
 63316
 63317
 63318
 63319
 63320
 63321
 63322
 63323
 63324
 63325
 63326
 63327
 63328
 63329
 63330
 63331
 63332
 63333
 63334
 63335
 63336
 63337
 63338
 63339
 63340
 63341
 63342
 63343
 63344
 63345
 63346
 63347
 63348
 63349
 63350
 63351
 63352
 63353
 63354
 63355
 63356
 63357
 63358
 63359
 63360
 63361
 63362
 63363
 63364
 63365
 63366
 63367
 63368
 63369
 63370
 63371
 63372
 63373
 63374
 63375
 63376
 63377
 63378
 63379
 63380
 63381
 63382
 63383
 63384
 63385
 63386
 63387
 63388
 63389
 63390
 63391
 63392
 63393
 63394
 63395
 63396
 63397
 63398
 63399
 63400
 63401
 63402
 63403
 63404
 63405
 63406
 63407
 63408
 63409
 63410
 63411
 63412
 63413
 63414
 63415
 63416
 63417
 63418
 63419
 63420
 63421
 63422
 63423
 63424
 63425
 63426
 63427
 63428
 63429
 63430
 63431
 63432
 63433
 63434
 63435
 63436
 63437
 63438
 63439
 63440
 63441
 63442
 63443
 63444
 63445
 63446
 63447
 63448
 63449
 63450
 63451
 63452
 63453
 63454
 63455
 63456
 63457
 63458
 63459
 63460
 63461
 63462
 63463
 63464
 63465
 63466
 63467
 63468
 63469
 63470
 63471
 63472
 63473
 63474
 63475
 63476
 63477
 63478
 63479
 63480
 63481
 63482
 63483
 63484
 63485
 63486
 63487
 63488
 63489
 63490
 63491
 63492
 63493
 63494
 63495
 63496
 63497
 63498
 63499
 63500
 63501
 63502
 63503
 63504
 63505
 63506
 63507
 63508
 63509
 63510
 63511
 63512
 63513
 63514
 63515
 63516
 63517
 63518
 63519
 63520
 63521
 63522
 63523
 63524
 63525
 63526
 63527
 63528
 63529
 63530
 63531
 63532
 63533
 63534
 63535
 63536
 63537
 63538
 63539
 63540
 63541
 63542
 63543
 63544
 63545
 63546
 63547
 63548
 63549
 63550
 63551
 63552
 63553
 63554
 63555
 63556
 63557
 63558
 63559
 63560
 63561
 63562
 63563
 63564
 63565
 63566
 63567
 63568
 63569
 63570
 63571
 63572
 63573
 63574
 63575
 63576
 63577
 63578
 63579
 63580
 63581
 63582
 63583
 63584
 63585
 63586
 63587
 63588
 63589
 63590
 63591
 63592
 63593
 63594
 63595
 63596
 63597
 63598
 63599
 63600
 63601
 63602
 63603
 63604
 63605
 63606
 63607
 63608
 63609
 63610
 63611
 63612
 63613
 63614
 63615
 63616
 63617
 63618
 63619
 63620
 63621
 63622
 63623
 63624
 63625
 63626
 63627
 63628
 63629
 63630
 63631
 63632
 63633
 63634
 63635
 63636
 63637
 63638
 63639
 63640
 63641
 63642
 63643
 63644
 63645
 63646
 63647
 63648
 63649
 63650
 63651
 63652
 63653
 63654
 63655
 63656
 63657
 63658
 63659
 63660
 63661
 63662
 63663
 63664
 63665
 63666
 63667
 63668
 63669
 63670
 63671
 63672
 63673
 63674
 63675
 63676
 63677
 63678
 63679
 63680
 63681
 63682
 63683
 63684
 63685
 63686
 63687
 63688
 63689
 63690
 63691
 63692
 63693
 63694
 63695
 63696
 63697
 63698
 63699
 63700
 63701
 63702
 63703
 63704
 63705
 63706
 63707
 63708
 63709
 63710
 63711
 63712
 63713
 63714
 63715
 63716
 63717
 63718
 63719
 63720
 63721
 63722
 63723
 63724
 63725
 63726
 63727
 63728
 63729
 63730
 63731
 63732
 63733
 63734
 63735
 63736
 63737
 63738
 63739
 63740
 63741
 63742
 63743
 63744
 63745
 63746
 63747
 63748
 63749
 63750
 63751
 63752
 63753
 63754
 63755
 63756
 63757
 63758
 63759
 63760
 63761
 63762
 63763
 63764
 63765
 63766
 63767
 63768
 63769
 63770
 63771
 63772
 63773
 63774
 63775
 63776
 63777
 63778
 63779
 63780
 63781
 63782
 63783
 63784
 63785
 63786
 63787
 63788
 63789
 63790
 63791
 63792
 63793
 63794
 63795
 63796
 63797
 63798
 63799
 63800
 63801
 63802
 63803
 63804
 63805
 63806
 63807
 63808
 63809
 63810
 63811
 63812
 63813
 63814
 63815
 63816
 63817
 63818
 63819
 63820
 63821
 63822
 63823
 63824
 63825
 63826
 63827
 63828
 63829
 63830
 63831
 63832
 63833
 63834
 63835
 63836
 63837
 63838
 63839
 63840
 63841
 63842
 63843
 63844
 63845
 63846
 63847
 63848
 63849
 63850
 63851
 63852
 63853
 63854
 63855
 63856
 63857
 63858
 63859
 63860
 63861
 63862
 63863
 63864
 63865
 63866
 63867
 63868
 63869
 63870
 63871
 63872
 63873
 63874
 63875
 63876
 63877
 63878
 63879
 63880
 63881
 63882
 63883
 63884
 63885
 63886
 63887
 63888
 63889
 63890
 63891
 63892
 63893
 63894
 63895
 63896
 63897
 63898
 63899
 63900
 63901
 63902
 63903
 63904
 63905
 63906
 63907
 63908
 63909
 63910
 63911
 63912
 63913
 63914
 63915
 63916
 63917
 63918
 63919
 63920
 63921
 63922
 63923
 63924
 63925
 63926
 63927
 63928
 63929
 63930
 63931
 63932
 63933
 63934
 63935
 63936
 63937
 63938
 63939
 63940
 63941
 63942
 63943
 63944
 63945
 63946
 63947
 63948
 63949
 63950
 63951
 63952
 63953
 63954
 63955
 63956
 63957
 63958
 63959
 63960
 63961
 63962
 63963
 63964
 63965
 63966
 63967
 63968
 63969
 63970
 63971
 63972
 63973
 63974
 63975
 63976
 63977
 63978
 63979
 63980
 63981
 63982
 63983
 63984
 63985
 63986
 63987
 63988
 63989
 63990
 63991
 63992
 63993
 63994
 63995
 63996
 63997
 63998
 63999
 64000
 64001
 64002
 64003
 64004
 64005
 64006
 64007
 64008
 64009
 64010
 64011
 64012
 64013
 64014
 64015
 64016
 64017
 64018
 64019
 64020
 64021
 64022
 64023
 64024
 64025
 64026
 64027
 64028
 64029
 64030
 64031
 64032
 64033
 64034
 64035
 64036
 64037
 64038
 64039
 64040
 64041
 64042
 64043
 64044
 64045
 64046
 64047
 64048
 64049
 64050
 64051
 64052
 64053
 64054
 64055
 64056
 64057
 64058
 64059
 64060
 64061
 64062
 64063
 64064
 64065
 64066
 64067
 64068
 64069
 64070
 64071
 64072
 64073
 64074
 64075
 64076
 64077
 64078
 64079
 64080
 64081
 64082
 64083
 64084
 64085
 64086
 64087
 64088
 64089
 64090
 64091
 64092
 64093
 64094
 64095
 64096
 64097
 64098
 64099
 64100
 64101
 64102
 64103
 64104
 64105
 64106
 64107
 64108
 64109
 64110
 64111
 64112
 64113
 64114
 64115
 64116
 64117
 64118
 64119
 64120
 64121
 64122
 64123
 64124
 64125
 64126
 64127
 64128
 64129
 64130
 64131
 64132
 64133
 64134
 64135
 64136
 64137
 64138
 64139
 64140
 64141
 64142
 64143
 64144
 64145
 64146
 64147
 64148
 64149
 64150
 64151
 64152
 64153
 64154
 64155
 64156
 64157
 64158
 64159
 64160
 64161
 64162
 64163
 64164
 64165
 64166
 64167
 64168
 64169
 64170
 64171
 64172
 64173
 64174
 64175
 64176
 64177
 64178
 64179
 64180
 64181
 64182
 64183
 64184
 64185
 64186
 64187
 64188
 64189
 64190
 64191
 64192
 64193
 64194
 64195
 64196
 64197
 64198
 64199
 64200
 64201
 64202
 64203
 64204
 64205
 64206
 64207
 64208
 64209
 64210
 64211
 64212
 64213
 64214
 64215
 64216
 64217
 64218
 64219
 64220
 64221
 64222
 64223
 64224
 64225
 64226
 64227
 64228
 64229
 64230
 64231
 64232
 64233
 64234
 64235
 64236
 64237
 64238
 64239
 64240
 64241
 64242
 64243
 64244
 64245
 64246
 64247
 64248
 64249
 64250
 64251
 64252
 64253
 64254
 64255
 64256
 64257
 64258
 64259
 64260
 64261
 64262
 64263
 64264
 64265
 64266
 64267
 64268
 64269
 64270
 64271
 64272
 64273
 64274
 64275
 64276
 64277
 64278
 64279
 64280
 64281
 64282
 64283
 64284
 64285
 64286
 64287
 64288
 64289
 64290
 64291
 64292
 64293
 64294
 64295
 64296
 64297
 64298
 64299
 64300
 64301
 64302
 64303
 64304
 64305
 64306
 64307
 64308
 64309
 64310
 64311
 64312
 64313
 64314
 64315
 64316
 64317
 64318
 64319
 64320
 64321
 64322
 64323
 64324
 64325
 64326
 64327
 64328
 64329
 64330
 64331
 64332
 64333
 64334
 64335
 64336
 64337
 64338
 64339
 64340
 64341
 64342
 64343
 64344
 64345
 64346
 64347
 64348
 64349
 64350
 64351
 64352
 64353
 64354
 64355
 64356
 64357
 64358
 64359
 64360
 64361
 64362
 64363
 64364
 64365
 64366
 64367
 64368
 64369
 64370
 64371
 64372
 64373
 64374
 64375
 64376
 64377
 64378
 64379
 64380
 64381
 64382
 64383
 64384
 64385
 64386
 64387
 64388
 64389
 64390
 64391
 64392
 64393
 64394
 64395
 64396
 64397
 64398
 64399
 64400
 64401
 64402
 64403
 64404
 64405
 64406
 64407
 64408
 64409
 64410
 64411
 64412
 64413
 64414
 64415
 64416
 64417
 64418
 64419
 64420
 64421
 64422
 64423
 64424
 64425
 64426
 64427
 64428
 64429
 64430
 64431
 64432
 64433
 64434
 64435
 64436
 64437
 64438
 64439
 64440
 64441
 64442
 64443
 64444
 64445
 64446
 64447
 64448
 64449
 64450
 64451
 64452
 64453
 64454
 64455
 64456
 64457
 64458
 64459
 64460
 64461
 64462
 64463
 64464
 64465
 64466
 64467
 64468
 64469
 64470
 64471
 64472
 64473
 64474
 64475
 64476
 64477
 64478
 64479
 64480
 64481
 64482
 64483
 64484
 64485
 64486
 64487
 64488
 64489
 64490
 64491
 64492
 64493
 64494
 64495
 64496
 64497
 64498
 64499
 64500
 64501
 64502
 64503
 64504
 64505
 64506
 64507
 64508
 64509
 64510
 64511
 64512
 64513
 64514
 64515
 64516
 64517
 64518
 64519
 64520
 64521
 64522
 64523
 64524
 64525
 64526
 64527
 64528
 64529
 64530
 64531
 64532
 64533
 64534
 64535
 64536
 64537
 64538
 64539
 64540
 64541
 64542
 64543
 64544
 64545
 64546
 64547
 64548
 64549
 64550
 64551
 64552
 64553
 64554
 64555
 64556
 64557
 64558
 64559
 64560
 64561
 64562
 64563
 64564
 64565
 64566
 64567
 64568
 64569
 64570
 64571
 64572
 64573
 64574
 64575
 64576
 64577
 64578
 64579
 64580
 64581
 64582
 64583
 64584
 64585
 64586
 64587
 64588
 64589
 64590
 64591
 64592
 64593
 64594
 64595
 64596
 64597
 64598
 64599
 64600
 64601
 64602
 64603
 64604
 64605
 64606
 64607
 64608
 64609
 64610
 64611
 64612
 64613
 64614
 64615
 64616
 64617
 64618
 64619
 64620
 64621
 64622
 64623
 64624
 64625
 64626
 64627
 64628
 64629
 64630
 64631
 64632
 64633
 64634
 64635
 64636
 64637
 64638
 64639
 64640
 64641
 64642
 64643
 64644
 64645
 64646
 64647
 64648
 64649
 64650
 64651
 64652
 64653
 64654
 64655
 64656
 64657
 64658
 64659
 64660
 64661
 64662
 64663
 64664
 64665
 64666
 64667
 64668
 64669
 64670
 64671
 64672
 64673
 64674
 64675
 64676
 64677
 64678
 64679
 64680
 64681
 64682
 64683
 64684
 64685
 64686
 64687
 64688
 64689
 64690
 64691
 64692
 64693
 64694
 64695
 64696
 64697
 64698
 64699
 64700
 64701
 64702
 64703
 64704
 64705
 64706
 64707
 64708
 64709
 64710
 64711
 64712
 64713
 64714
 64715
 64716
 64717
 64718
 64719
 64720
 64721
 64722
 64723
 64724
 64725
 64726
 64727
 64728
 64729
 64730
 64731
 64732
 64733
 64734
 64735
 64736
 64737
 64738
 64739
 64740
 64741
 64742
 64743
 64744
 64745
 64746
 64747
 64748
 64749
 64750
 64751
 64752
 64753
 64754
 64755
 64756
 64757
 64758
 64759
 64760
 64761
 64762
 64763
 64764
 64765
 64766
 64767
 64768
 64769
 64770
 64771
 64772
 64773
 64774
 64775
 64776
 64777
 64778
 64779
 64780
 64781
 64782
 64783
 64784
 64785
 64786
 64787
 64788
 64789
 64790
 64791
 64792
 64793
 64794
 64795
 64796
 64797
 64798
 64799
 64800
 64801
 64802
 64803
 64804
 64805
 64806
 64807
 64808
 64809
 64810
 64811
 64812
 64813
 64814
 64815
 64816
 64817
 64818
 64819
 64820
 64821
 64822
 64823
 64824
 64825
 64826
 64827
 64828
 64829
 64830
 64831
 64832
 64833
 64834
 64835
 64836
 64837
 64838
 64839
 64840
 64841
 64842
 64843
 64844
 64845
 64846
 64847
 64848
 64849
 64850
 64851
 64852
 64853
 64854
 64855
 64856
 64857
 64858
 64859
 64860
 64861
 64862
 64863
 64864
 64865
 64866
 64867
 64868
 64869
 64870
 64871
 64872
 64873
 64874
 64875
 64876
 64877
 64878
 64879
 64880
 64881
 64882
 64883
 64884
 64885
 64886
 64887
 64888
 64889
 64890
 64891
 64892
 64893
 64894
 64895
 64896
 64897
 64898
 64899
 64900
 64901
 64902
 64903
 64904
 64905
 64906
 64907
 64908
 64909
 64910
 64911
 64912
 64913
 64914
 64915
 64916
 64917
 64918
 64919
 64920
 64921
 64922
 64923
 64924
 64925
 64926
 64927
 64928
 64929
 64930
 64931
 64932
 64933
 64934
 64935
 64936
 64937
 64938
 64939
 64940
 64941
 64942
 64943
 64944
 64945
 64946
 64947
 64948
 64949
 64950
 64951
 64952
 64953
 64954
 64955
 64956
 64957
 64958
 64959
 64960
 64961
 64962
 64963
 64964
 64965
 64966
 64967
 64968
 64969
 64970
 64971
 64972
 64973
 64974
 64975
 64976
 64977
 64978
 64979
 64980
 64981
 64982
 64983
 64984
 64985
 64986
 64987
 64988
 64989
 64990
 64991
 64992
 64993
 64994
 64995
 64996
 64997
 64998
 64999
 65000
 65001
 65002
 65003
 65004
 65005
 65006
 65007
 65008
 65009
 65010
 65011
 65012
 65013
 65014
 65015
 65016
 65017
 65018
 65019
 65020
 65021
 65022
 65023
 65024
 65025
 65026
 65027
 65028
 65029
 65030
 65031
 65032
 65033
 65034
 65035
 65036
 65037
 65038
 65039
 65040
 65041
 65042
 65043
 65044
 65045
 65046
 65047
 65048
 65049
 65050
 65051
 65052
 65053
 65054
 65055
 65056
 65057
 65058
 65059
 65060
 65061
 65062
 65063
 65064
 65065
 65066
 65067
 65068
 65069
 65070
 65071
 65072
 65073
 65074
 65075
 65076
 65077
 65078
 65079
 65080
 65081
 65082
 65083
 65084
 65085
 65086
 65087
 65088
 65089
 65090
 65091
 65092
 65093
 65094
 65095
 65096
 65097
 65098
 65099
 65100
 65101
 65102
 65103
 65104
 65105
 65106
 65107
 65108
 65109
 65110
 65111
 65112
 65113
 65114
 65115
 65116
 65117
 65118
 65119
 65120
 65121
 65122
 65123
 65124
 65125
 65126
 65127
 65128
 65129
 65130
 65131
 65132
 65133
 65134
 65135
 65136
 65137
 65138
 65139
 65140
 65141
 65142
 65143
 65144
 65145
 65146
 65147
 65148
 65149
 65150
 65151
 65152
 65153
 65154
 65155
 65156
 65157
 65158
 65159
 65160
 65161
 65162
 65163
 65164
 65165
 65166
 65167
 65168
 65169
 65170
 65171
 65172
 65173
 65174
 65175
 65176
 65177
 65178
 65179
 65180
 65181
 65182
 65183
 65184
 65185
 65186
 65187
 65188
 65189
 65190
 65191
 65192
 65193
 65194
 65195
 65196
 65197
 65198
 65199
 65200
 65201
 65202
 65203
 65204
 65205
 65206
 65207
 65208
 65209
 65210
 65211
 65212
 65213
 65214
 65215
 65216
 65217
 65218
 65219
 65220
 65221
 65222
 65223
 65224
 65225
 65226
 65227
 65228
 65229
 65230
 65231
 65232
 65233
 65234
 65235
 65236
 65237
 65238
 65239
 65240
 65241
 65242
 65243
 65244
 65245
 65246
 65247
 65248
 65249
 65250
 65251
 65252
 65253
 65254
 65255
 65256
 65257
 65258
 65259
 65260
 65261
 65262
 65263
 65264
 65265
 65266
 65267
 65268
 65269
 65270
 65271
 65272
 65273
 65274
 65275
 65276
 65277
 65278
 65279
 65280
 65281
 65282
 65283
 65284
 65285
 65286
 65287
 65288
 65289
 65290
 65291
 65292
 65293
 65294
 65295
 65296
 65297
 65298
 65299
 65300
 65301
 65302
 65303
 65304
 65305
 65306
 65307
 65308
 65309
 65310
 65311
 65312
 65313
 65314
 65315
 65316
 65317
 65318
 65319
 65320
 65321
 65322
 65323
 65324
 65325
 65326
 65327
 65328
 65329
 65330
 65331
 65332
 65333
 65334
 65335
 65336
 65337
 65338
 65339
 65340
 65341
 65342
 65343
 65344
 65345
 65346
 65347
 65348
 65349
 65350
 65351
 65352
 65353
 65354
 65355
 65356
 65357
 65358
 65359
 65360
 65361
 65362
 65363
 65364
 65365
 65366
 65367
 65368
 65369
 65370
 65371
 65372
 65373
 65374
 65375
 65376
 65377
 65378
 65379
 65380
 65381
 65382
 65383
 65384
 65385
 65386
 65387
 65388
 65389
 65390
 65391
 65392
 65393
 65394
 65395
 65396
 65397
 65398
 65399
 65400
 65401
 65402
 65403
 65404
 65405
 65406
 65407
 65408
 65409
 65410
 65411
 65412
 65413
 65414
 65415
 65416
 65417
 65418
 65419
 65420
 65421
 65422
 65423
 65424
 65425
 65426
 65427
 65428
 65429
 65430
 65431
 65432
 65433
 65434
 65435
 65436
 65437
 65438
 65439
 65440
 65441
 65442
 65443
 65444
 65445
 65446
 65447
 65448
 65449
 65450
 65451
 65452
 65453
 65454
 65455
 65456
 65457
 65458
 65459
 65460
 65461
 65462
 65463
 65464
 65465
 65466
 65467
 65468
 65469
 65470
 65471
 65472
 65473
 65474
 65475
 65476
 65477
 65478
 65479
 65480
 65481
 65482
 65483
 65484
 65485
 65486
 65487
 65488
 65489
 65490
 65491
 65492
 65493
 65494
 65495
 65496
 65497
 65498
 65499
 65500
 65501
 65502
 65503
 65504
 65505
 65506
 65507
 65508
 65509
 65510
 65511
 65512
 65513
 65514
 65515
 65516
 65517
 65518
 65519
 65520
 65521
 65522
 65523
 65524
 65525
 65526
 65527
 65528
 65529
 65530
 65531
 65532
 65533
 65534
 65535
 65536
 65537
 65538
 65539
 65540
 65541
 65542
 65543
 65544
 65545
 65546
 65547
 65548
 65549
 65550
 65551
 65552
 65553
 65554
 65555
 65556
 65557
 65558
 65559
 65560
 65561
 65562
 65563
 65564
 65565
 65566
 65567
 65568
 65569
 65570
 65571
 65572
 65573
 65574
 65575
 65576
 65577
 65578
 65579
 65580
 65581
 65582
 65583
 65584
 65585
 65586
 65587
 65588
 65589
 65590
 65591
 65592
 65593
 65594
 65595
 65596
 65597
 65598
 65599
 65600
 65601
 65602
 65603
 65604
 65605
 65606
 65607
 65608
 65609
 65610
 65611
 65612
 65613
 65614
 65615
 65616
 65617
 65618
 65619
 65620
 65621
 65622
 65623
 65624
 65625
 65626
 65627
 65628
 65629
 65630
 65631
 65632
 65633
 65634
 65635
 65636
 65637
 65638
 65639
 65640
 65641
 65642
 65643
 65644
 65645
 65646
 65647
 65648
 65649
 65650
 65651
 65652
 65653
 65654
 65655
 65656
 65657
 65658
 65659
 65660
 65661
 65662
 65663
 65664
 65665
 65666
 65667
 65668
 65669
 65670
 65671
 65672
 65673
 65674
 65675
 65676
 65677
 65678
 65679
 65680
 65681
 65682
 65683
 65684
 65685
 65686
 65687
 65688
 65689
 65690
 65691
 65692
 65693
 65694
 65695
 65696
 65697
 65698
 65699
 65700
 65701
 65702
 65703
 65704
 65705
 65706
 65707
 65708
 65709
 65710
 65711
 65712
 65713
 65714
 65715
 65716
 65717
 65718
 65719
 65720
 65721
 65722
 65723
 65724
 65725
 65726
 65727
 65728
 65729
 65730
 65731
 65732
 65733
 65734
 65735
 65736
 65737
 65738
 65739
 65740
 65741
 65742
 65743
 65744
 65745
 65746
 65747
 65748
 65749
 65750
 65751
 65752
 65753
 65754
 65755
 65756
 65757
 65758
 65759
 65760
 65761
 65762
 65763
 65764
 65765
 65766
 65767
 65768
 65769
 65770
 65771
 65772
 65773
 65774
 65775
 65776
 65777
 65778
 65779
 65780
 65781
 65782
 65783
 65784
 65785
 65786
 65787
 65788
 65789
 65790
 65791
 65792
 65793
 65794
 65795
 65796
 65797
 65798
 65799
 65800
 65801
 65802
 65803
 65804
 65805
 65806
 65807
 65808
 65809
 65810
 65811
 65812
 65813
 65814
 65815
 65816
 65817
 65818
 65819
 65820
 65821
 65822
 65823
 65824
 65825
 65826
 65827
 65828
 65829
 65830
 65831
 65832
 65833
 65834
 65835
 65836
 65837
 65838
 65839
 65840
 65841
 65842
 65843
 65844
 65845
 65846
 65847
 65848
 65849
 65850
 65851
 65852
 65853
 65854
 65855
 65856
 65857
 65858
 65859
 65860
 65861
 65862
 65863
 65864
 65865
 65866
 65867
 65868
 65869
 65870
 65871
 65872
 65873
 65874
 65875
 65876
 65877
 65878
 65879
 65880
 65881
 65882
 65883
 65884
 65885
 65886
 65887
 65888
 65889
 65890
 65891
 65892
 65893
 65894
 65895
 65896
 65897
 65898
 65899
 65900
 65901
 65902
 65903
 65904
 65905
 65906
 65907
 65908
 65909
 65910
 65911
 65912
 65913
 65914
 65915
 65916
 65917
 65918
 65919
 65920
 65921
 65922
 65923
 65924
 65925
 65926
 65927
 65928
 65929
 65930
 65931
 65932
 65933
 65934
 65935
 65936
 65937
 65938
 65939
 65940
 65941
 65942
 65943
 65944
 65945
 65946
 65947
 65948
 65949
 65950
 65951
 65952
 65953
 65954
 65955
 65956
 65957
 65958
 65959
 65960
 65961
 65962
 65963
 65964
 65965
 65966
 65967
 65968
 65969
 65970
 65971
 65972
 65973
 65974
 65975
 65976
 65977
 65978
 65979
 65980
 65981
 65982
 65983
 65984
 65985
 65986
 65987
 65988
 65989
 65990
 65991
 65992
 65993
 65994
 65995
 65996
 65997
 65998
 65999
 66000
 66001
 66002
 66003
 66004
 66005
 66006
 66007
 66008
 66009
 66010
 66011
 66012
 66013
 66014
 66015
 66016
 66017
 66018
 66019
 66020
 66021
 66022
 66023
 66024
 66025
 66026
 66027
 66028
 66029
 66030
 66031
 66032
 66033
 66034
 66035
 66036
 66037
 66038
 66039
 66040
 66041
 66042
 66043
 66044
 66045
 66046
 66047
 66048
 66049
 66050
 66051
 66052
 66053
 66054
 66055
 66056
 66057
 66058
 66059
 66060
 66061
 66062
 66063
 66064
 66065
 66066
 66067
 66068
 66069
 66070
 66071
 66072
 66073
 66074
 66075
 66076
 66077
 66078
 66079
 66080
 66081
 66082
 66083
 66084
 66085
 66086
 66087
 66088
 66089
 66090
 66091
 66092
 66093
 66094
 66095
 66096
 66097
 66098
 66099
 66100
 66101
 66102
 66103
 66104
 66105
 66106
 66107
 66108
 66109
 66110
 66111
 66112
 66113
 66114
 66115
 66116
 66117
 66118
 66119
 66120
 66121
 66122
 66123
 66124
 66125
 66126
 66127
 66128
 66129
 66130
 66131
 66132
 66133
 66134
 66135
 66136
 66137
 66138
 66139
 66140
 66141
 66142
 66143
 66144
 66145
 66146
 66147
 66148
 66149
 66150
 66151
 66152
 66153
 66154
 66155
 66156
 66157
 66158
 66159
 66160
 66161
 66162
 66163
 66164
 66165
 66166
 66167
 66168
 66169
 66170
 66171
 66172
 66173
 66174
 66175
 66176
 66177
 66178
 66179
 66180
 66181
 66182
 66183
 66184
 66185
 66186
 66187
 66188
 66189
 66190
 66191
 66192
 66193
 66194
 66195
 66196
 66197
 66198
 66199
 66200
 66201
 66202
 66203
 66204
 66205
 66206
 66207
 66208
 66209
 66210
 66211
 66212
 66213
 66214
 66215
 66216
 66217
 66218
 66219
 66220
 66221
 66222
 66223
 66224
 66225
 66226
 66227
 66228
 66229
 66230
 66231
 66232
 66233
 66234
 66235
 66236
 66237
 66238
 66239
 66240
 66241
 66242
 66243
 66244
 66245
 66246
 66247
 66248
 66249
 66250
 66251
 66252
 66253
 66254
 66255
 66256
 66257
 66258
 66259
 66260
 66261
 66262
 66263
 66264
 66265
 66266
 66267
 66268
 66269
 66270
 66271
 66272
 66273
 66274
 66275
 66276
 66277
 66278
 66279
 66280
 66281
 66282
 66283
 66284
 66285
 66286
 66287
 66288
 66289
 66290
 66291
 66292
 66293
 66294
 66295
 66296
 66297
 66298
 66299
 66300
 66301
 66302
 66303
 66304
 66305
 66306
 66307
 66308
 66309
 66310
 66311
 66312
 66313
 66314
 66315
 66316
 66317
 66318
 66319
 66320
 66321
 66322
 66323
 66324
 66325
 66326
 66327
 66328
 66329
 66330
 66331
 66332
 66333
 66334
 66335
 66336
 66337
 66338
 66339
 66340
 66341
 66342
 66343
 66344
 66345
 66346
 66347
 66348
 66349
 66350
 66351
 66352
 66353
 66354
 66355
 66356
 66357
 66358
 66359
 66360
 66361
 66362
 66363
 66364
 66365
 66366
 66367
 66368
 66369
 66370
 66371
 66372
 66373
 66374
 66375
 66376
 66377
 66378
 66379
 66380
 66381
 66382
 66383
 66384
 66385
 66386
 66387
 66388
 66389
 66390
 66391
 66392
 66393
 66394
 66395
 66396
 66397
 66398
 66399
 66400
 66401
 66402
 66403
 66404
 66405
 66406
 66407
 66408
 66409
 66410
 66411
 66412
 66413
 66414
 66415
 66416
 66417
 66418
 66419
 66420
 66421
 66422
 66423
 66424
 66425
 66426
 66427
 66428
 66429
 66430
 66431
 66432
 66433
 66434
 66435
 66436
 66437
 66438
 66439
 66440
 66441
 66442
 66443
 66444
 66445
 66446
 66447
 66448
 66449
 66450
 66451
 66452
 66453
 66454
 66455
 66456
 66457
 66458
 66459
 66460
 66461
 66462
 66463
 66464
 66465
 66466
 66467
 66468
 66469
 66470
 66471
 66472
 66473
 66474
 66475
 66476
 66477
 66478
 66479
 66480
 66481
 66482
 66483
 66484
 66485
 66486
 66487
 66488
 66489
 66490
 66491
 66492
 66493
 66494
 66495
 66496
 66497
 66498
 66499
 66500
 66501
 66502
 66503
 66504
 66505
 66506
 66507
 66508
 66509
 66510
 66511
 66512
 66513
 66514
 66515
 66516
 66517
 66518
 66519
 66520
 66521
 66522
 66523
 66524
 66525
 66526
 66527
 66528
 66529
 66530
 66531
 66532
 66533
 66534
 66535
 66536
 66537
 66538
 66539
 66540
 66541
 66542
 66543
 66544
 66545
 66546
 66547
 66548
 66549
 66550
 66551
 66552
 66553
 66554
 66555
 66556
 66557
 66558
 66559
 66560
 66561
 66562
 66563
 66564
 66565
 66566
 66567
 66568
 66569
 66570
 66571
 66572
 66573
 66574
 66575
 66576
 66577
 66578
 66579
 66580
 66581
 66582
 66583
 66584
 66585
 66586
 66587
 66588
 66589
 66590
 66591
 66592
 66593
 66594
 66595
 66596
 66597
 66598
 66599
 66600
 66601
 66602
 66603
 66604
 66605
 66606
 66607
 66608
 66609
 66610
 66611
 66612
 66613
 66614
 66615
 66616
 66617
 66618
 66619
 66620
 66621
 66622
 66623
 66624
 66625
 66626
 66627
 66628
 66629
 66630
 66631
 66632
 66633
 66634
 66635
 66636
 66637
 66638
 66639
 66640
 66641
 66642
 66643
 66644
 66645
 66646
 66647
 66648
 66649
 66650
 66651
 66652
 66653
 66654
 66655
 66656
 66657
 66658
 66659
 66660
 66661
 66662
 66663
 66664
 66665
 66666
 66667
 66668
 66669
 66670
 66671
 66672
 66673
 66674
 66675
 66676
 66677
 66678
 66679
 66680
 66681
 66682
 66683
 66684
 66685
 66686
 66687
 66688
 66689
 66690
 66691
 66692
 66693
 66694
 66695
 66696
 66697
 66698
 66699
 66700
 66701
 66702
 66703
 66704
 66705
 66706
 66707
 66708
 66709
 66710
 66711
 66712
 66713
 66714
 66715
 66716
 66717
 66718
 66719
 66720
 66721
 66722
 66723
 66724
 66725
 66726
 66727
 66728
 66729
 66730
 66731
 66732
 66733
 66734
 66735
 66736
 66737
 66738
 66739
 66740
 66741
 66742
 66743
 66744
 66745
 66746
 66747
 66748
 66749
 66750
 66751
 66752
 66753
 66754
 66755
 66756
 66757
 66758
 66759
 66760
 66761
 66762
 66763
 66764
 66765
 66766
 66767
 66768
 66769
 66770
 66771
 66772
 66773
 66774
 66775
 66776
 66777
 66778
 66779
 66780
 66781
 66782
 66783
 66784
 66785
 66786
 66787
 66788
 66789
 66790
 66791
 66792
 66793
 66794
 66795
 66796
 66797
 66798
 66799
 66800
 66801
 66802
 66803
 66804
 66805
 66806
 66807
 66808
 66809
 66810
 66811
 66812
 66813
 66814
 66815
 66816
 66817
 66818
 66819
 66820
 66821
 66822
 66823
 66824
 66825
 66826
 66827
 66828
 66829
 66830
 66831
 66832
 66833
 66834
 66835
 66836
 66837
 66838
 66839
 66840
 66841
 66842
 66843
 66844
 66845
 66846
 66847
 66848
 66849
 66850
 66851
 66852
 66853
 66854
 66855
 66856
 66857
 66858
 66859
 66860
 66861
 66862
 66863
 66864
 66865
 66866
 66867
 66868
 66869
 66870
 66871
 66872
 66873
 66874
 66875
 66876
 66877
 66878
 66879
 66880
 66881
 66882
 66883
 66884
 66885
 66886
 66887
 66888
 66889
 66890
 66891
 66892
 66893
 66894
 66895
 66896
 66897
 66898
 66899
 66900
 66901
 66902
 66903
 66904
 66905
 66906
 66907
 66908
 66909
 66910
 66911
 66912
 66913
 66914
 66915
 66916
 66917
 66918
 66919
 66920
 66921
 66922
 66923
 66924
 66925
 66926
 66927
 66928
 66929
 66930
 66931
 66932
 66933
 66934
 66935
 66936
 66937
 66938
 66939
 66940
 66941
 66942
 66943
 66944
 66945
 66946
 66947
 66948
 66949
 66950
 66951
 66952
 66953
 66954
 66955
 66956
 66957
 66958
 66959
 66960
 66961
 66962
 66963
 66964
 66965
 66966
 66967
 66968
 66969
 66970
 66971
 66972
 66973
 66974
 66975
 66976
 66977
 66978
 66979
 66980
 66981
 66982
 66983
 66984
 66985
 66986
 66987
 66988
 66989
 66990
 66991
 66992
 66993
 66994
 66995
 66996
 66997
 66998
 66999
 67000
 67001
 67002
 67003
 67004
 67005
 67006
 67007
 67008
 67009
 67010
 67011
 67012
 67013
 67014
 67015
 67016
 67017
 67018
 67019
 67020
 67021
 67022
 67023
 67024
 67025
 67026
 67027
 67028
 67029
 67030
 67031
 67032
 67033
 67034
 67035
 67036
 67037
 67038
 67039
 67040
 67041
 67042
 67043
 67044
 67045
 67046
 67047
 67048
 67049
 67050
 67051
 67052
 67053
 67054
 67055
 67056
 67057
 67058
 67059
 67060
 67061
 67062
 67063
 67064
 67065
 67066
 67067
 67068
 67069
 67070
 67071
 67072
 67073
 67074
 67075
 67076
 67077
 67078
 67079
 67080
 67081
 67082
 67083
 67084
 67085
 67086
 67087
 67088
 67089
 67090
 67091
 67092
 67093
 67094
 67095
 67096
 67097
 67098
 67099
 67100
 67101
 67102
 67103
 67104
 67105
 67106
 67107
 67108
 67109
 67110
 67111
 67112
 67113
 67114
 67115
 67116
 67117
 67118
 67119
 67120
 67121
 67122
 67123
 67124
 67125
 67126
 67127
 67128
 67129
 67130
 67131
 67132
 67133
 67134
 67135
 67136
 67137
 67138
 67139
 67140
 67141
 67142
 67143
 67144
 67145
 67146
 67147
 67148
 67149
 67150
 67151
 67152
 67153
 67154
 67155
 67156
 67157
 67158
 67159
 67160
 67161
 67162
 67163
 67164
 67165
 67166
 67167
 67168
 67169
 67170
 67171
 67172
 67173
 67174
 67175
 67176
 67177
 67178
 67179
 67180
 67181
 67182
 67183
 67184
 67185
 67186
 67187
 67188
 67189
 67190
 67191
 67192
 67193
 67194
 67195
 67196
 67197
 67198
 67199
 67200
 67201
 67202
 67203
 67204
 67205
 67206
 67207
 67208
 67209
 67210
 67211
 67212
 67213
 67214
 67215
 67216
 67217
 67218
 67219
 67220
 67221
 67222
 67223
 67224
 67225
 67226
 67227
 67228
 67229
 67230
 67231
 67232
 67233
 67234
 67235
 67236
 67237
 67238
 67239
 67240
 67241
 67242
 67243
 67244
 67245
 67246
 67247
 67248
 67249
 67250
 67251
 67252
 67253
 67254
 67255
 67256
 67257
 67258
 67259
 67260
 67261
 67262
 67263
 67264
 67265
 67266
 67267
 67268
 67269
 67270
 67271
 67272
 67273
 67274
 67275
 67276
 67277
 67278
 67279
 67280
 67281
 67282
 67283
 67284
 67285
 67286
 67287
 67288
 67289
 67290
 67291
 67292
 67293
 67294
 67295
 67296
 67297
 67298
 67299
 67300
 67301
 67302
 67303
 67304
 67305
 67306
 67307
 67308
 67309
 67310
 67311
 67312
 67313
 67314
 67315
 67316
 67317
 67318
 67319
 67320
 67321
 67322
 67323
 67324
 67325
 67326
 67327
 67328
 67329
 67330
 67331
 67332
 67333
 67334
 67335
 67336
 67337
 67338
 67339
 67340
 67341
 67342
 67343
 67344
 67345
 67346
 67347
 67348
 67349
 67350
 67351
 67352
 67353
 67354
 67355
 67356
 67357
 67358
 67359
 67360
 67361
 67362
 67363
 67364
 67365
 67366
 67367
 67368
 67369
 67370
 67371
 67372
 67373
 67374
 67375
 67376
 67377
 67378
 67379
 67380
 67381
 67382
 67383
 67384
 67385
 67386
 67387
 67388
 67389
 67390
 67391
 67392
 67393
 67394
 67395
 67396
 67397
 67398
 67399
 67400
 67401
 67402
 67403
 67404
 67405
 67406
 67407
 67408
 67409
 67410
 67411
 67412
 67413
 67414
 67415
 67416
 67417
 67418
 67419
 67420
 67421
 67422
 67423
 67424
 67425
 67426
 67427
 67428
 67429
 67430
 67431
 67432
 67433
 67434
 67435
 67436
 67437
 67438
 67439
 67440
 67441
 67442
 67443
 67444
 67445
 67446
 67447
 67448
 67449
 67450
 67451
 67452
 67453
 67454
 67455
 67456
 67457
 67458
 67459
 67460
 67461
 67462
 67463
 67464
 67465
 67466
 67467
 67468
 67469
 67470
 67471
 67472
 67473
 67474
 67475
 67476
 67477
 67478
 67479
 67480
 67481
 67482
 67483
 67484
 67485
 67486
 67487
 67488
 67489
 67490
 67491
 67492
 67493
 67494
 67495
 67496
 67497
 67498
 67499
 67500
 67501
 67502
 67503
 67504
 67505
 67506
 67507
 67508
 67509
 67510
 67511
 67512
 67513
 67514
 67515
 67516
 67517
 67518
 67519
 67520
 67521
 67522
 67523
 67524
 67525
 67526
 67527
 67528
 67529
 67530
 67531
 67532
 67533
 67534
 67535
 67536
 67537
 67538
 67539
 67540
 67541
 67542
 67543
 67544
 67545
 67546
 67547
 67548
 67549
 67550
 67551
 67552
 67553
 67554
 67555
 67556
 67557
 67558
 67559
 67560
 67561
 67562
 67563
 67564
 67565
 67566
 67567
 67568
 67569
 67570
 67571
 67572
 67573
 67574
 67575
 67576
 67577
 67578
 67579
 67580
 67581
 67582
 67583
 67584
 67585
 67586
 67587
 67588
 67589
 67590
 67591
 67592
 67593
 67594
 67595
 67596
 67597
 67598
 67599
 67600
 67601
 67602
 67603
 67604
 67605
 67606
 67607
 67608
 67609
 67610
 67611
 67612
 67613
 67614
 67615
 67616
 67617
 67618
 67619
 67620
 67621
 67622
 67623
 67624
 67625
 67626
 67627
 67628
 67629
 67630
 67631
 67632
 67633
 67634
 67635
 67636
 67637
 67638
 67639
 67640
 67641
 67642
 67643
 67644
 67645
 67646
 67647
 67648
 67649
 67650
 67651
 67652
 67653
 67654
 67655
 67656
 67657
 67658
 67659
 67660
 67661
 67662
 67663
 67664
 67665
 67666
 67667
 67668
 67669
 67670
 67671
 67672
 67673
 67674
 67675
 67676
 67677
 67678
 67679
 67680
 67681
 67682
 67683
 67684
 67685
 67686
 67687
 67688
 67689
 67690
 67691
 67692
 67693
 67694
 67695
 67696
 67697
 67698
 67699
 67700
 67701
 67702
 67703
 67704
 67705
 67706
 67707
 67708
 67709
 67710
 67711
 67712
 67713
 67714
 67715
 67716
 67717
 67718
 67719
 67720
 67721
 67722
 67723
 67724
 67725
 67726
 67727
 67728
 67729
 67730
 67731
 67732
 67733
 67734
 67735
 67736
 67737
 67738
 67739
 67740
 67741
 67742
 67743
 67744
 67745
 67746
 67747
 67748
 67749
 67750
 67751
 67752
 67753
 67754
 67755
 67756
 67757
 67758
 67759
 67760
 67761
 67762
 67763
 67764
 67765
 67766
 67767
 67768
 67769
 67770
 67771
 67772
 67773
 67774
 67775
 67776
 67777
 67778
 67779
 67780
 67781
 67782
 67783
 67784
 67785
 67786
 67787
 67788
 67789
 67790
 67791
 67792
 67793
 67794
 67795
 67796
 67797
 67798
 67799
 67800
 67801
 67802
 67803
 67804
 67805
 67806
 67807
 67808
 67809
 67810
 67811
 67812
 67813
 67814
 67815
 67816
 67817
 67818
 67819
 67820
 67821
 67822
 67823
 67824
 67825
 67826
 67827
 67828
 67829
 67830
 67831
 67832
 67833
 67834
 67835
 67836
 67837
 67838
 67839
 67840
 67841
 67842
 67843
 67844
 67845
 67846
 67847
 67848
 67849
 67850
 67851
 67852
 67853
 67854
 67855
 67856
 67857
 67858
 67859
 67860
 67861
 67862
 67863
 67864
 67865
 67866
 67867
 67868
 67869
 67870
 67871
 67872
 67873
 67874
 67875
 67876
 67877
 67878
 67879
 67880
 67881
 67882
 67883
 67884
 67885
 67886
 67887
 67888
 67889
 67890
 67891
 67892
 67893
 67894
 67895
 67896
 67897
 67898
 67899
 67900
 67901
 67902
 67903
 67904
 67905
 67906
 67907
 67908
 67909
 67910
 67911
 67912
 67913
 67914
 67915
 67916
 67917
 67918
 67919
 67920
 67921
 67922
 67923
 67924
 67925
 67926
 67927
 67928
 67929
 67930
 67931
 67932
 67933
 67934
 67935
 67936
 67937
 67938
 67939
 67940
 67941
 67942
 67943
 67944
 67945
 67946
 67947
 67948
 67949
 67950
 67951
 67952
 67953
 67954
 67955
 67956
 67957
 67958
 67959
 67960
 67961
 67962
 67963
 67964
 67965
 67966
 67967
 67968
 67969
 67970
 67971
 67972
 67973
 67974
 67975
 67976
 67977
 67978
 67979
 67980
 67981
 67982
 67983
 67984
 67985
 67986
 67987
 67988
 67989
 67990
 67991
 67992
 67993
 67994
 67995
 67996
 67997
 67998
 67999
 68000
 68001
 68002
 68003
 68004
 68005
 68006
 68007
 68008
 68009
 68010
 68011
 68012
 68013
 68014
 68015
 68016
 68017
 68018
 68019
 68020
 68021
 68022
 68023
 68024
 68025
 68026
 68027
 68028
 68029
 68030
 68031
 68032
 68033
 68034
 68035
 68036
 68037
 68038
 68039
 68040
 68041
 68042
 68043
 68044
 68045
 68046
 68047
 68048
 68049
 68050
 68051
 68052
 68053
 68054
 68055
 68056
 68057
 68058
 68059
 68060
 68061
 68062
 68063
 68064
 68065
 68066
 68067
 68068
 68069
 68070
 68071
 68072
 68073
 68074
 68075
 68076
 68077
 68078
 68079
 68080
 68081
 68082
 68083
 68084
 68085
 68086
 68087
 68088
 68089
 68090
 68091
 68092
 68093
 68094
 68095
 68096
 68097
 68098
 68099
 68100
 68101
 68102
 68103
 68104
 68105
 68106
 68107
 68108
 68109
 68110
 68111
 68112
 68113
 68114
 68115
 68116
 68117
 68118
 68119
 68120
 68121
 68122
 68123
 68124
 68125
 68126
 68127
 68128
 68129
 68130
 68131
 68132
 68133
 68134
 68135
 68136
 68137
 68138
 68139
 68140
 68141
 68142
 68143
 68144
 68145
 68146
 68147
 68148
 68149
 68150
 68151
 68152
 68153
 68154
 68155
 68156
 68157
 68158
 68159
 68160
 68161
 68162
 68163
 68164
 68165
 68166
 68167
 68168
 68169
 68170
 68171
 68172
 68173
 68174
 68175
 68176
 68177
 68178
 68179
 68180
 68181
 68182
 68183
 68184
 68185
 68186
 68187
 68188
 68189
 68190
 68191
 68192
 68193
 68194
 68195
 68196
 68197
 68198
 68199
 68200
 68201
 68202
 68203
 68204
 68205
 68206
 68207
 68208
 68209
 68210
 68211
 68212
 68213
 68214
 68215
 68216
 68217
 68218
 68219
 68220
 68221
 68222
 68223
 68224
 68225
 68226
 68227
 68228
 68229
 68230
 68231
 68232
 68233
 68234
 68235
 68236
 68237
 68238
 68239
 68240
 68241
 68242
 68243
 68244
 68245
 68246
 68247
 68248
 68249
 68250
 68251
 68252
 68253
 68254
 68255
 68256
 68257
 68258
 68259
 68260
 68261
 68262
 68263
 68264
 68265
 68266
 68267
 68268
 68269
 68270
 68271
 68272
 68273
 68274
 68275
 68276
 68277
 68278
 68279
 68280
 68281
 68282
 68283
 68284
 68285
 68286
 68287
 68288
 68289
 68290
 68291
 68292
 68293
 68294
 68295
 68296
 68297
 68298
 68299
 68300
 68301
 68302
 68303
 68304
 68305
 68306
 68307
 68308
 68309
 68310
 68311
 68312
 68313
 68314
 68315
 68316
 68317
 68318
 68319
 68320
 68321
 68322
 68323
 68324
 68325
 68326
 68327
 68328
 68329
 68330
 68331
 68332
 68333
 68334
 68335
 68336
 68337
 68338
 68339
 68340
 68341
 68342
 68343
 68344
 68345
 68346
 68347
 68348
 68349
 68350
 68351
 68352
 68353
 68354
 68355
 68356
 68357
 68358
 68359
 68360
 68361
 68362
 68363
 68364
 68365
 68366
 68367
 68368
 68369
 68370
 68371
 68372
 68373
 68374
 68375
 68376
 68377
 68378
 68379
 68380
 68381
 68382
 68383
 68384
 68385
 68386
 68387
 68388
 68389
 68390
 68391
 68392
 68393
 68394
 68395
 68396
 68397
 68398
 68399
 68400
 68401
 68402
 68403
 68404
 68405
 68406
 68407
 68408
 68409
 68410
 68411
 68412
 68413
 68414
 68415
 68416
 68417
 68418
 68419
 68420
 68421
 68422
 68423
 68424
 68425
 68426
 68427
 68428
 68429
 68430
 68431
 68432
 68433
 68434
 68435
 68436
 68437
 68438
 68439
 68440
 68441
 68442
 68443
 68444
 68445
 68446
 68447
 68448
 68449
 68450
 68451
 68452
 68453
 68454
 68455
 68456
 68457
 68458
 68459
 68460
 68461
 68462
 68463
 68464
 68465
 68466
 68467
 68468
 68469
 68470
 68471
 68472
 68473
 68474
 68475
 68476
 68477
 68478
 68479
 68480
 68481
 68482
 68483
 68484
 68485
 68486
 68487
 68488
 68489
 68490
 68491
 68492
 68493
 68494
 68495
 68496
 68497
 68498
 68499
 68500
 68501
 68502
 68503
 68504
 68505
 68506
 68507
 68508
 68509
 68510
 68511
 68512
 68513
 68514
 68515
 68516
 68517
 68518
 68519
 68520
 68521
 68522
 68523
 68524
 68525
 68526
 68527
 68528
 68529
 68530
 68531
 68532
 68533
 68534
 68535
 68536
 68537
 68538
 68539
 68540
 68541
 68542
 68543
 68544
 68545
 68546
 68547
 68548
 68549
 68550
 68551
 68552
 68553
 68554
 68555
 68556
 68557
 68558
 68559
 68560
 68561
 68562
 68563
 68564
 68565
 68566
 68567
 68568
 68569
 68570
 68571
 68572
 68573
 68574
 68575
 68576
 68577
 68578
 68579
 68580
 68581
 68582
 68583
 68584
 68585
 68586
 68587
 68588
 68589
 68590
 68591
 68592
 68593
 68594
 68595
 68596
 68597
 68598
 68599
 68600
 68601
 68602
 68603
 68604
 68605
 68606
 68607
 68608
 68609
 68610
 68611
 68612
 68613
 68614
 68615
 68616
 68617
 68618
 68619
 68620
 68621
 68622
 68623
 68624
 68625
 68626
 68627
 68628
 68629
 68630
 68631
 68632
 68633
 68634
 68635
 68636
 68637
 68638
 68639
 68640
 68641
 68642
 68643
 68644
 68645
 68646
 68647
 68648
 68649
 68650
 68651
 68652
 68653
 68654
 68655
 68656
 68657
 68658
 68659
 68660
 68661
 68662
 68663
 68664
 68665
 68666
 68667
 68668
 68669
 68670
 68671
 68672
 68673
 68674
 68675
 68676
 68677
 68678
 68679
 68680
 68681
 68682
 68683
 68684
 68685
 68686
 68687
 68688
 68689
 68690
 68691
 68692
 68693
 68694
 68695
 68696
 68697
 68698
 68699
 68700
 68701
 68702
 68703
 68704
 68705
 68706
 68707
 68708
 68709
 68710
 68711
 68712
 68713
 68714
 68715
 68716
 68717
 68718
 68719
 68720
 68721
 68722
 68723
 68724
 68725
 68726
 68727
 68728
 68729
 68730
 68731
 68732
 68733
 68734
 68735
 68736
 68737
 68738
 68739
 68740
 68741
 68742
 68743
 68744
 68745
 68746
 68747
 68748
 68749
 68750
 68751
 68752
 68753
 68754
 68755
 68756
 68757
 68758
 68759
 68760
 68761
 68762
 68763
 68764
 68765
 68766
 68767
 68768
 68769
 68770
 68771
 68772
 68773
 68774
 68775
 68776
 68777
 68778
 68779
 68780
 68781
 68782
 68783
 68784
 68785
 68786
 68787
 68788
 68789
 68790
 68791
 68792
 68793
 68794
 68795
 68796
 68797
 68798
 68799
 68800
 68801
 68802
 68803
 68804
 68805
 68806
 68807
 68808
 68809
 68810
 68811
 68812
 68813
 68814
 68815
 68816
 68817
 68818
 68819
 68820
 68821
 68822
 68823
 68824
 68825
 68826
 68827
 68828
 68829
 68830
 68831
 68832
 68833
 68834
 68835
 68836
 68837
 68838
 68839
 68840
 68841
 68842
 68843
 68844
 68845
 68846
 68847
 68848
 68849
 68850
 68851
 68852
 68853
 68854
 68855
 68856
 68857
 68858
 68859
 68860
 68861
 68862
 68863
 68864
 68865
 68866
 68867
 68868
 68869
 68870
 68871
 68872
 68873
 68874
 68875
 68876
 68877
 68878
 68879
 68880
 68881
 68882
 68883
 68884
 68885
 68886
 68887
 68888
 68889
 68890
 68891
 68892
 68893
 68894
 68895
 68896
 68897
 68898
 68899
 68900
 68901
 68902
 68903
 68904
 68905
 68906
 68907
 68908
 68909
 68910
 68911
 68912
 68913
 68914
 68915
 68916
 68917
 68918
 68919
 68920
 68921
 68922
 68923
 68924
 68925
 68926
 68927
 68928
 68929
 68930
 68931
 68932
 68933
 68934
 68935
 68936
 68937
 68938
 68939
 68940
 68941
 68942
 68943
 68944
 68945
 68946
 68947
 68948
 68949
 68950
 68951
 68952
 68953
 68954
 68955
 68956
 68957
 68958
 68959
 68960
 68961
 68962
 68963
 68964
 68965
 68966
 68967
 68968
 68969
 68970
 68971
 68972
 68973
 68974
 68975
 68976
 68977
 68978
 68979
 68980
 68981
 68982
 68983
 68984
 68985
 68986
 68987
 68988
 68989
 68990
 68991
 68992
 68993
 68994
 68995
 68996
 68997
 68998
 68999
 69000
 69001
 69002
 69003
 69004
 69005
 69006
 69007
 69008
 69009
 69010
 69011
 69012
 69013
 69014
 69015
 69016
 69017
 69018
 69019
 69020
 69021
 69022
 69023
 69024
 69025
 69026
 69027
 69028
 69029
 69030
 69031
 69032
 69033
 69034
 69035
 69036
 69037
 69038
 69039
 69040
 69041
 69042
 69043
 69044
 69045
 69046
 69047
 69048
 69049
 69050
 69051
 69052
 69053
 69054
 69055
 69056
 69057
 69058
 69059
 69060
 69061
 69062
 69063
 69064
 69065
 69066
 69067
 69068
 69069
 69070
 69071
 69072
 69073
 69074
 69075
 69076
 69077
 69078
 69079
 69080
 69081
 69082
 69083
 69084
 69085
 69086
 69087
 69088
 69089
 69090
 69091
 69092
 69093
 69094
 69095
 69096
 69097
 69098
 69099
 69100
 69101
 69102
 69103
 69104
 69105
 69106
 69107
 69108
 69109
 69110
 69111
 69112
 69113
 69114
 69115
 69116
 69117
 69118
 69119
 69120
 69121
 69122
 69123
 69124
 69125
 69126
 69127
 69128
 69129
 69130
 69131
 69132
 69133
 69134
 69135
 69136
 69137
 69138
 69139
 69140
 69141
 69142
 69143
 69144
 69145
 69146
 69147
 69148
 69149
 69150
 69151
 69152
 69153
 69154
 69155
 69156
 69157
 69158
 69159
 69160
 69161
 69162
 69163
 69164
 69165
 69166
 69167
 69168
 69169
 69170
 69171
 69172
 69173
 69174
 69175
 69176
 69177
 69178
 69179
 69180
 69181
 69182
 69183
 69184
 69185
 69186
 69187
 69188
 69189
 69190
 69191
 69192
 69193
 69194
 69195
 69196
 69197
 69198
 69199
 69200
 69201
 69202
 69203
 69204
 69205
 69206
 69207
 69208
 69209
 69210
 69211
 69212
 69213
 69214
 69215
 69216
 69217
 69218
 69219
 69220
 69221
 69222
 69223
 69224
 69225
 69226
 69227
 69228
 69229
 69230
 69231
 69232
 69233
 69234
 69235
 69236
 69237
 69238
 69239
 69240
 69241
 69242
 69243
 69244
 69245
 69246
 69247
 69248
 69249
 69250
 69251
 69252
 69253
 69254
 69255
 69256
 69257
 69258
 69259
 69260
 69261
 69262
 69263
 69264
 69265
 69266
 69267
 69268
 69269
 69270
 69271
 69272
 69273
 69274
 69275
 69276
 69277
 69278
 69279
 69280
 69281
 69282
 69283
 69284
 69285
 69286
 69287
 69288
 69289
 69290
 69291
 69292
 69293
 69294
 69295
 69296
 69297
 69298
 69299
 69300
 69301
 69302
 69303
 69304
 69305
 69306
 69307
 69308
 69309
 69310
 69311
 69312
 69313
 69314
 69315
 69316
 69317
 69318
 69319
 69320
 69321
 69322
 69323
 69324
 69325
 69326
 69327
 69328
 69329
 69330
 69331
 69332
 69333
 69334
 69335
 69336
 69337
 69338
 69339
 69340
 69341
 69342
 69343
 69344
 69345
 69346
 69347
 69348
 69349
 69350
 69351
 69352
 69353
 69354
 69355
 69356
 69357
 69358
 69359
 69360
 69361
 69362
 69363
 69364
 69365
 69366
 69367
 69368
 69369
 69370
 69371
 69372
 69373
 69374
 69375
 69376
 69377
 69378
 69379
 69380
 69381
 69382
 69383
 69384
 69385
 69386
 69387
 69388
 69389
 69390
 69391
 69392
 69393
 69394
 69395
 69396
 69397
 69398
 69399
 69400
 69401
 69402
 69403
 69404
 69405
 69406
 69407
 69408
 69409
 69410
 69411
 69412
 69413
 69414
 69415
 69416
 69417
 69418
 69419
 69420
 69421
 69422
 69423
 69424
 69425
 69426
 69427
 69428
 69429
 69430
 69431
 69432
 69433
 69434
 69435
 69436
 69437
 69438
 69439
 69440
 69441
 69442
 69443
 69444
 69445
 69446
 69447
 69448
 69449
 69450
 69451
 69452
 69453
 69454
 69455
 69456
 69457
 69458
 69459
 69460
 69461
 69462
 69463
 69464
 69465
 69466
 69467
 69468
 69469
 69470
 69471
 69472
 69473
 69474
 69475
 69476
 69477
 69478
 69479
 69480
 69481
 69482
 69483
 69484
 69485
 69486
 69487
 69488
 69489
 69490
 69491
 69492
 69493
 69494
 69495
 69496
 69497
 69498
 69499
 69500
 69501
 69502
 69503
 69504
 69505
 69506
 69507
 69508
 69509
 69510
 69511
 69512
 69513
 69514
 69515
 69516
 69517
 69518
 69519
 69520
 69521
 69522
 69523
 69524
 69525
 69526
 69527
 69528
 69529
 69530
 69531
 69532
 69533
 69534
 69535
 69536
 69537
 69538
 69539
 69540
 69541
 69542
 69543
 69544
 69545
 69546
 69547
 69548
 69549
 69550
 69551
 69552
 69553
 69554
 69555
 69556
 69557
 69558
 69559
 69560
 69561
 69562
 69563
 69564
 69565
 69566
 69567
 69568
 69569
 69570
 69571
 69572
 69573
 69574
 69575
 69576
 69577
 69578
 69579
 69580
 69581
 69582
 69583
 69584
 69585
 69586
 69587
 69588
 69589
 69590
 69591
 69592
 69593
 69594
 69595
 69596
 69597
 69598
 69599
 69600
 69601
 69602
 69603
 69604
 69605
 69606
 69607
 69608
 69609
 69610
 69611
 69612
 69613
 69614
 69615
 69616
 69617
 69618
 69619
 69620
 69621
 69622
 69623
 69624
 69625
 69626
 69627
 69628
 69629
 69630
 69631
 69632
 69633
 69634
 69635
 69636
 69637
 69638
 69639
 69640
 69641
 69642
 69643
 69644
 69645
 69646
 69647
 69648
 69649
 69650
 69651
 69652
 69653
 69654
 69655
 69656
 69657
 69658
 69659
 69660
 69661
 69662
 69663
 69664
 69665
 69666
 69667
 69668
 69669
 69670
 69671
 69672
 69673
 69674
 69675
 69676
 69677
 69678
 69679
 69680
 69681
 69682
 69683
 69684
 69685
 69686
 69687
 69688
 69689
 69690
 69691
 69692
 69693
 69694
 69695
 69696
 69697
 69698
 69699
 69700
 69701
 69702
 69703
 69704
 69705
 69706
 69707
 69708
 69709
 69710
 69711
 69712
 69713
 69714
 69715
 69716
 69717
 69718
 69719
 69720
 69721
 69722
 69723
 69724
 69725
 69726
 69727
 69728
 69729
 69730
 69731
 69732
 69733
 69734
 69735
 69736
 69737
 69738
 69739
 69740
 69741
 69742
 69743
 69744
 69745
 69746
 69747
 69748
 69749
 69750
 69751
 69752
 69753
 69754
 69755
 69756
 69757
 69758
 69759
 69760
 69761
 69762
 69763
 69764
 69765
 69766
 69767
 69768
 69769
 69770
 69771
 69772
 69773
 69774
 69775
 69776
 69777
 69778
 69779
 69780
 69781
 69782
 69783
 69784
 69785
 69786
 69787
 69788
 69789
 69790
 69791
 69792
 69793
 69794
 69795
 69796
 69797
 69798
 69799
 69800
 69801
 69802
 69803
 69804
 69805
 69806
 69807
 69808
 69809
 69810
 69811
 69812
 69813
 69814
 69815
 69816
 69817
 69818
 69819
 69820
 69821
 69822
 69823
 69824
 69825
 69826
 69827
 69828
 69829
 69830
 69831
 69832
 69833
 69834
 69835
 69836
 69837
 69838
 69839
 69840
 69841
 69842
 69843
 69844
 69845
 69846
 69847
 69848
 69849
 69850
 69851
 69852
 69853
 69854
 69855
 69856
 69857
 69858
 69859
 69860
 69861
 69862
 69863
 69864
 69865
 69866
 69867
 69868
 69869
 69870
 69871
 69872
 69873
 69874
 69875
 69876
 69877
 69878
 69879
 69880
 69881
 69882
 69883
 69884
 69885
 69886
 69887
 69888
 69889
 69890
 69891
 69892
 69893
 69894
 69895
 69896
 69897
 69898
 69899
 69900
 69901
 69902
 69903
 69904
 69905
 69906
 69907
 69908
 69909
 69910
 69911
 69912
 69913
 69914
 69915
 69916
 69917
 69918
 69919
 69920
 69921
 69922
 69923
 69924
 69925
 69926
 69927
 69928
 69929
 69930
 69931
 69932
 69933
 69934
 69935
 69936
 69937
 69938
 69939
 69940
 69941
 69942
 69943
 69944
 69945
 69946
 69947
 69948
 69949
 69950
 69951
 69952
 69953
 69954
 69955
 69956
 69957
 69958
 69959
 69960
 69961
 69962
 69963
 69964
 69965
 69966
 69967
 69968
 69969
 69970
 69971
 69972
 69973
 69974
 69975
 69976
 69977
 69978
 69979
 69980
 69981
 69982
 69983
 69984
 69985
 69986
 69987
 69988
 69989
 69990
 69991
 69992
 69993
 69994
 69995
 69996
 69997
 69998
 69999
 70000
 70001
 70002
 70003
 70004
 70005
 70006
 70007
 70008
 70009
 70010
 70011
 70012
 70013
 70014
 70015
 70016
 70017
 70018
 70019
 70020
 70021
 70022
 70023
 70024
 70025
 70026
 70027
 70028
 70029
 70030
 70031
 70032
 70033
 70034
 70035
 70036
 70037
 70038
 70039
 70040
 70041
 70042
 70043
 70044
 70045
 70046
 70047
 70048
 70049
 70050
 70051
 70052
 70053
 70054
 70055
 70056
 70057
 70058
 70059
 70060
 70061
 70062
 70063
 70064
 70065
 70066
 70067
 70068
 70069
 70070
 70071
 70072
 70073
 70074
 70075
 70076
 70077
 70078
 70079
 70080
 70081
 70082
 70083
 70084
 70085
 70086
 70087
 70088
 70089
 70090
 70091
 70092
 70093
 70094
 70095
 70096
 70097
 70098
 70099
 70100
 70101
 70102
 70103
 70104
 70105
 70106
 70107
 70108
 70109
 70110
 70111
 70112
 70113
 70114
 70115
 70116
 70117
 70118
 70119
 70120
 70121
 70122
 70123
 70124
 70125
 70126
 70127
 70128
 70129
 70130
 70131
 70132
 70133
 70134
 70135
 70136
 70137
 70138
 70139
 70140
 70141
 70142
 70143
 70144
 70145
 70146
 70147
 70148
 70149
 70150
 70151
 70152
 70153
 70154
 70155
 70156
 70157
 70158
 70159
 70160
 70161
 70162
 70163
 70164
 70165
 70166
 70167
 70168
 70169
 70170
 70171
 70172
 70173
 70174
 70175
 70176
 70177
 70178
 70179
 70180
 70181
 70182
 70183
 70184
 70185
 70186
 70187
 70188
 70189
 70190
 70191
 70192
 70193
 70194
 70195
 70196
 70197
 70198
 70199
 70200
 70201
 70202
 70203
 70204
 70205
 70206
 70207
 70208
 70209
 70210
 70211
 70212
 70213
 70214
 70215
 70216
 70217
 70218
 70219
 70220
 70221
 70222
 70223
 70224
 70225
 70226
 70227
 70228
 70229
 70230
 70231
 70232
 70233
 70234
 70235
 70236
 70237
 70238
 70239
 70240
 70241
 70242
 70243
 70244
 70245
 70246
 70247
 70248
 70249
 70250
 70251
 70252
 70253
 70254
 70255
 70256
 70257
 70258
 70259
 70260
 70261
 70262
 70263
 70264
 70265
 70266
 70267
 70268
 70269
 70270
 70271
 70272
 70273
 70274
 70275
 70276
 70277
 70278
 70279
 70280
 70281
 70282
 70283
 70284
 70285
 70286
 70287
 70288
 70289
 70290
 70291
 70292
 70293
 70294
 70295
 70296
 70297
 70298
 70299
 70300
 70301
 70302
 70303
 70304
 70305
 70306
 70307
 70308
 70309
 70310
 70311
 70312
 70313
 70314
 70315
 70316
 70317
 70318
 70319
 70320
 70321
 70322
 70323
 70324
 70325
 70326
 70327
 70328
 70329
 70330
 70331
 70332
 70333
 70334
 70335
 70336
 70337
 70338
 70339
 70340
 70341
 70342
 70343
 70344
 70345
 70346
 70347
 70348
 70349
 70350
 70351
 70352
 70353
 70354
 70355
 70356
 70357
 70358
 70359
 70360
 70361
 70362
 70363
 70364
 70365
 70366
 70367
 70368
 70369
 70370
 70371
 70372
 70373
 70374
 70375
 70376
 70377
 70378
 70379
 70380
 70381
 70382
 70383
 70384
 70385
 70386
 70387
 70388
 70389
 70390
 70391
 70392
 70393
 70394
 70395
 70396
 70397
 70398
 70399
 70400
 70401
 70402
 70403
 70404
 70405
 70406
 70407
 70408
 70409
 70410
 70411
 70412
 70413
 70414
 70415
 70416
 70417
 70418
 70419
 70420
 70421
 70422
 70423
 70424
 70425
 70426
 70427
 70428
 70429
 70430
 70431
 70432
 70433
 70434
 70435
 70436
 70437
 70438
 70439
 70440
 70441
 70442
 70443
 70444
 70445
 70446
 70447
 70448
 70449
 70450
 70451
 70452
 70453
 70454
 70455
 70456
 70457
 70458
 70459
 70460
 70461
 70462
 70463
 70464
 70465
 70466
 70467
 70468
 70469
 70470
 70471
 70472
 70473
 70474
 70475
 70476
 70477
 70478
 70479
 70480
 70481
 70482
 70483
 70484
 70485
 70486
 70487
 70488
 70489
 70490
 70491
 70492
 70493
 70494
 70495
 70496
 70497
 70498
 70499
 70500
 70501
 70502
 70503
 70504
 70505
 70506
 70507
 70508
 70509
 70510
 70511
 70512
 70513
 70514
 70515
 70516
 70517
 70518
 70519
 70520
 70521
 70522
 70523
 70524
 70525
 70526
 70527
 70528
 70529
 70530
 70531
 70532
 70533
 70534
 70535
 70536
 70537
 70538
 70539
 70540
 70541
 70542
 70543
 70544
 70545
 70546
 70547
 70548
 70549
 70550
 70551
 70552
 70553
 70554
 70555
 70556
 70557
 70558
 70559
 70560
 70561
 70562
 70563
 70564
 70565
 70566
 70567
 70568
 70569
 70570
 70571
 70572
 70573
 70574
 70575
 70576
 70577
 70578
 70579
 70580
 70581
 70582
 70583
 70584
 70585
 70586
 70587
 70588
 70589
 70590
 70591
 70592
 70593
 70594
 70595
 70596
 70597
 70598
 70599
 70600
 70601
 70602
 70603
 70604
 70605
 70606
 70607
 70608
 70609
 70610
 70611
 70612
 70613
 70614
 70615
 70616
 70617
 70618
 70619
 70620
 70621
 70622
 70623
 70624
 70625
 70626
 70627
 70628
 70629
 70630
 70631
 70632
 70633
 70634
 70635
 70636
 70637
 70638
 70639
 70640
 70641
 70642
 70643
 70644
 70645
 70646
 70647
 70648
 70649
 70650
 70651
 70652
 70653
 70654
 70655
 70656
 70657
 70658
 70659
 70660
 70661
 70662
 70663
 70664
 70665
 70666
 70667
 70668
 70669
 70670
 70671
 70672
 70673
 70674
 70675
 70676
 70677
 70678
 70679
 70680
 70681
 70682
 70683
 70684
 70685
 70686
 70687
 70688
 70689
 70690
 70691
 70692
 70693
 70694
 70695
 70696
 70697
 70698
 70699
 70700
 70701
 70702
 70703
 70704
 70705
 70706
 70707
 70708
 70709
 70710
 70711
 70712
 70713
 70714
 70715
 70716
 70717
 70718
 70719
 70720
 70721
 70722
 70723
 70724
 70725
 70726
 70727
 70728
 70729
 70730
 70731
 70732
 70733
 70734
 70735
 70736
 70737
 70738
 70739
 70740
 70741
 70742
 70743
 70744
 70745
 70746
 70747
 70748
 70749
 70750
 70751
 70752
 70753
 70754
 70755
 70756
 70757
 70758
 70759
 70760
 70761
 70762
 70763
 70764
 70765
 70766
 70767
 70768
 70769
 70770
 70771
 70772
 70773
 70774
 70775
 70776
 70777
 70778
 70779
 70780
 70781
 70782
 70783
 70784
 70785
 70786
 70787
 70788
 70789
 70790
 70791
 70792
 70793
 70794
 70795
 70796
 70797
 70798
 70799
 70800
 70801
 70802
 70803
 70804
 70805
 70806
 70807
 70808
 70809
 70810
 70811
 70812
 70813
 70814
 70815
 70816
 70817
 70818
 70819
 70820
 70821
 70822
 70823
 70824
 70825
 70826
 70827
 70828
 70829
 70830
 70831
 70832
 70833
 70834
 70835
 70836
 70837
 70838
 70839
 70840
 70841
 70842
 70843
 70844
 70845
 70846
 70847
 70848
 70849
 70850
 70851
 70852
 70853
 70854
 70855
 70856
 70857
 70858
 70859
 70860
 70861
 70862
 70863
 70864
 70865
 70866
 70867
 70868
 70869
 70870
 70871
 70872
 70873
 70874
 70875
 70876
 70877
 70878
 70879
 70880
 70881
 70882
 70883
 70884
 70885
 70886
 70887
 70888
 70889
 70890
 70891
 70892
 70893
 70894
 70895
 70896
 70897
 70898
 70899
 70900
 70901
 70902
 70903
 70904
 70905
 70906
 70907
 70908
 70909
 70910
 70911
 70912
 70913
 70914
 70915
 70916
 70917
 70918
 70919
 70920
 70921
 70922
 70923
 70924
 70925
 70926
 70927
 70928
 70929
 70930
 70931
 70932
 70933
 70934
 70935
 70936
 70937
 70938
 70939
 70940
 70941
 70942
 70943
 70944
 70945
 70946
 70947
 70948
 70949
 70950
 70951
 70952
 70953
 70954
 70955
 70956
 70957
 70958
 70959
 70960
 70961
 70962
 70963
 70964
 70965
 70966
 70967
 70968
 70969
 70970
 70971
 70972
 70973
 70974
 70975
 70976
 70977
 70978
 70979
 70980
 70981
 70982
 70983
 70984
 70985
 70986
 70987
 70988
 70989
 70990
 70991
 70992
 70993
 70994
 70995
 70996
 70997
 70998
 70999
 71000
 71001
 71002
 71003
 71004
 71005
 71006
 71007
 71008
 71009
 71010
 71011
 71012
 71013
 71014
 71015
 71016
 71017
 71018
 71019
 71020
 71021
 71022
 71023
 71024
 71025
 71026
 71027
 71028
 71029
 71030
 71031
 71032
 71033
 71034
 71035
 71036
 71037
 71038
 71039
 71040
 71041
 71042
 71043
 71044
 71045
 71046
 71047
 71048
 71049
 71050
 71051
 71052
 71053
 71054
 71055
 71056
 71057
 71058
 71059
 71060
 71061
 71062
 71063
 71064
 71065
 71066
 71067
 71068
 71069
 71070
 71071
 71072
 71073
 71074
 71075
 71076
 71077
 71078
 71079
 71080
 71081
 71082
 71083
 71084
 71085
 71086
 71087
 71088
 71089
 71090
 71091
 71092
 71093
 71094
 71095
 71096
 71097
 71098
 71099
 71100
 71101
 71102
 71103
 71104
 71105
 71106
 71107
 71108
 71109
 71110
 71111
 71112
 71113
 71114
 71115
 71116
 71117
 71118
 71119
 71120
 71121
 71122
 71123
 71124
 71125
 71126
 71127
 71128
 71129
 71130
 71131
 71132
 71133
 71134
 71135
 71136
 71137
 71138
 71139
 71140
 71141
 71142
 71143
 71144
 71145
 71146
 71147
 71148
 71149
 71150
 71151
 71152
 71153
 71154
 71155
 71156
 71157
 71158
 71159
 71160
 71161
 71162
 71163
 71164
 71165
 71166
 71167
 71168
 71169
 71170
 71171
 71172
 71173
 71174
 71175
 71176
 71177
 71178
 71179
 71180
 71181
 71182
 71183
 71184
 71185
 71186
 71187
 71188
 71189
 71190
 71191
 71192
 71193
 71194
 71195
 71196
 71197
 71198
 71199
 71200
 71201
 71202
 71203
 71204
 71205
 71206
 71207
 71208
 71209
 71210
 71211
 71212
 71213
 71214
 71215
 71216
 71217
 71218
 71219
 71220
 71221
 71222
 71223
 71224
 71225
 71226
 71227
 71228
 71229
 71230
 71231
 71232
 71233
 71234
 71235
 71236
 71237
 71238
 71239
 71240
 71241
 71242
 71243
 71244
 71245
 71246
 71247
 71248
 71249
 71250
 71251
 71252
 71253
 71254
 71255
 71256
 71257
 71258
 71259
 71260
 71261
 71262
 71263
 71264
 71265
 71266
 71267
 71268
 71269
 71270
 71271
 71272
 71273
 71274
 71275
 71276
 71277
 71278
 71279
 71280
 71281
 71282
 71283
 71284
 71285
 71286
 71287
 71288
 71289
 71290
 71291
 71292
 71293
 71294
 71295
 71296
 71297
 71298
 71299
 71300
 71301
 71302
 71303
 71304
 71305
 71306
 71307
 71308
 71309
 71310
 71311
 71312
 71313
 71314
 71315
 71316
 71317
 71318
 71319
 71320
 71321
 71322
 71323
 71324
 71325
 71326
 71327
 71328
 71329
 71330
 71331
 71332
 71333
 71334
 71335
 71336
 71337
 71338
 71339
 71340
 71341
 71342
 71343
 71344
 71345
 71346
 71347
 71348
 71349
 71350
 71351
 71352
 71353
 71354
 71355
 71356
 71357
 71358
 71359
 71360
 71361
 71362
 71363
 71364
 71365
 71366
 71367
 71368
 71369
 71370
 71371
 71372
 71373
 71374
 71375
 71376
 71377
 71378
 71379
 71380
 71381
 71382
 71383
 71384
 71385
 71386
 71387
 71388
 71389
 71390
 71391
 71392
 71393
 71394
 71395
 71396
 71397
 71398
 71399
 71400
 71401
 71402
 71403
 71404
 71405
 71406
 71407
 71408
 71409
 71410
 71411
 71412
 71413
 71414
 71415
 71416
 71417
 71418
 71419
 71420
 71421
 71422
 71423
 71424
 71425
 71426
 71427
 71428
 71429
 71430
 71431
 71432
 71433
 71434
 71435
 71436
 71437
 71438
 71439
 71440
 71441
 71442
 71443
 71444
 71445
 71446
 71447
 71448
 71449
 71450
 71451
 71452
 71453
 71454
 71455
 71456
 71457
 71458
 71459
 71460
 71461
 71462
 71463
 71464
 71465
 71466
 71467
 71468
 71469
 71470
 71471
 71472
 71473
 71474
 71475
 71476
 71477
 71478
 71479
 71480
 71481
 71482
 71483
 71484
 71485
 71486
 71487
 71488
 71489
 71490
 71491
 71492
 71493
 71494
 71495
 71496
 71497
 71498
 71499
 71500
 71501
 71502
 71503
 71504
 71505
 71506
 71507
 71508
 71509
 71510
 71511
 71512
 71513
 71514
 71515
 71516
 71517
 71518
 71519
 71520
 71521
 71522
 71523
 71524
 71525
 71526
 71527
 71528
 71529
 71530
 71531
 71532
 71533
 71534
 71535
 71536
 71537
 71538
 71539
 71540
 71541
 71542
 71543
 71544
 71545
 71546
 71547
 71548
 71549
 71550
 71551
 71552
 71553
 71554
 71555
 71556
 71557
 71558
 71559
 71560
 71561
 71562
 71563
 71564
 71565
 71566
 71567
 71568
 71569
 71570
 71571
 71572
 71573
 71574
 71575
 71576
 71577
 71578
 71579
 71580
 71581
 71582
 71583
 71584
 71585
 71586
 71587
 71588
 71589
 71590
 71591
 71592
 71593
 71594
 71595
 71596
 71597
 71598
 71599
 71600
 71601
 71602
 71603
 71604
 71605
 71606
 71607
 71608
 71609
 71610
 71611
 71612
 71613
 71614
 71615
 71616
 71617
 71618
 71619
 71620
 71621
 71622
 71623
 71624
 71625
 71626
 71627
 71628
 71629
 71630
 71631
 71632
 71633
 71634
 71635
 71636
 71637
 71638
 71639
 71640
 71641
 71642
 71643
 71644
 71645
 71646
 71647
 71648
 71649
 71650
 71651
 71652
 71653
 71654
 71655
 71656
 71657
 71658
 71659
 71660
 71661
 71662
 71663
 71664
 71665
 71666
 71667
 71668
 71669
 71670
 71671
 71672
 71673
 71674
 71675
 71676
 71677
 71678
 71679
 71680
 71681
 71682
 71683
 71684
 71685
 71686
 71687
 71688
 71689
 71690
 71691
 71692
 71693
 71694
 71695
 71696
 71697
 71698
 71699
 71700
 71701
 71702
 71703
 71704
 71705
 71706
 71707
 71708
 71709
 71710
 71711
 71712
 71713
 71714
 71715
 71716
 71717
 71718
 71719
 71720
 71721
 71722
 71723
 71724
 71725
 71726
 71727
 71728
 71729
 71730
 71731
 71732
 71733
 71734
 71735
 71736
 71737
 71738
 71739
 71740
 71741
 71742
 71743
 71744
 71745
 71746
 71747
 71748
 71749
 71750
 71751
 71752
 71753
 71754
 71755
 71756
 71757
 71758
 71759
 71760
 71761
 71762
 71763
 71764
 71765
 71766
 71767
 71768
 71769
 71770
 71771
 71772
 71773
 71774
 71775
 71776
 71777
 71778
 71779
 71780
 71781
 71782
 71783
 71784
 71785
 71786
 71787
 71788
 71789
 71790
 71791
 71792
 71793
 71794
 71795
 71796
 71797
 71798
 71799
 71800
 71801
 71802
 71803
 71804
 71805
 71806
 71807
 71808
 71809
 71810
 71811
 71812
 71813
 71814
 71815
 71816
 71817
 71818
 71819
 71820
 71821
 71822
 71823
 71824
 71825
 71826
 71827
 71828
 71829
 71830
 71831
 71832
 71833
 71834
 71835
 71836
 71837
 71838
 71839
 71840
 71841
 71842
 71843
 71844
 71845
 71846
 71847
 71848
 71849
 71850
 71851
 71852
 71853
 71854
 71855
 71856
 71857
 71858
 71859
 71860
 71861
 71862
 71863
 71864
 71865
 71866
 71867
 71868
 71869
 71870
 71871
 71872
 71873
 71874
 71875
 71876
 71877
 71878
 71879
 71880
 71881
 71882
 71883
 71884
 71885
 71886
 71887
 71888
 71889
 71890
 71891
 71892
 71893
 71894
 71895
 71896
 71897
 71898
 71899
 71900
 71901
 71902
 71903
 71904
 71905
 71906
 71907
 71908
 71909
 71910
 71911
 71912
 71913
 71914
 71915
 71916
 71917
 71918
 71919
 71920
 71921
 71922
 71923
 71924
 71925
 71926
 71927
 71928
 71929
 71930
 71931
 71932
 71933
 71934
 71935
 71936
 71937
 71938
 71939
 71940
 71941
 71942
 71943
 71944
 71945
 71946
 71947
 71948
 71949
 71950
 71951
 71952
 71953
 71954
 71955
 71956
 71957
 71958
 71959
 71960
 71961
 71962
 71963
 71964
 71965
 71966
 71967
 71968
 71969
 71970
 71971
 71972
 71973
 71974
 71975
 71976
 71977
 71978
 71979
 71980
 71981
 71982
 71983
 71984
 71985
 71986
 71987
 71988
 71989
 71990
 71991
 71992
 71993
 71994
 71995
 71996
 71997
 71998
 71999
 72000
 72001
 72002
 72003
 72004
 72005
 72006
 72007
 72008
 72009
 72010
 72011
 72012
 72013
 72014
 72015
 72016
 72017
 72018
 72019
 72020
 72021
 72022
 72023
 72024
 72025
 72026
 72027
 72028
 72029
 72030
 72031
 72032
 72033
 72034
 72035
 72036
 72037
 72038
 72039
 72040
 72041
 72042
 72043
 72044
 72045
 72046
 72047
 72048
 72049
 72050
 72051
 72052
 72053
 72054
 72055
 72056
 72057
 72058
 72059
 72060
 72061
 72062
 72063
 72064
 72065
 72066
 72067
 72068
 72069
 72070
 72071
 72072
 72073
 72074
 72075
 72076
 72077
 72078
 72079
 72080
 72081
 72082
 72083
 72084
 72085
 72086
 72087
 72088
 72089
 72090
 72091
 72092
 72093
 72094
 72095
 72096
 72097
 72098
 72099
 72100
 72101
 72102
 72103
 72104
 72105
 72106
 72107
 72108
 72109
 72110
 72111
 72112
 72113
 72114
 72115
 72116
 72117
 72118
 72119
 72120
 72121
 72122
 72123
 72124
 72125
 72126
 72127
 72128
 72129
 72130
 72131
 72132
 72133
 72134
 72135
 72136
 72137
 72138
 72139
 72140
 72141
 72142
 72143
 72144
 72145
 72146
 72147
 72148
 72149
 72150
 72151
 72152
 72153
 72154
 72155
 72156
 72157
 72158
 72159
 72160
 72161
 72162
 72163
 72164
 72165
 72166
 72167
 72168
 72169
 72170
 72171
 72172
 72173
 72174
 72175
 72176
 72177
 72178
 72179
 72180
 72181
 72182
 72183
 72184
 72185
 72186
 72187
 72188
 72189
 72190
 72191
 72192
 72193
 72194
 72195
 72196
 72197
 72198
 72199
 72200
 72201
 72202
 72203
 72204
 72205
 72206
 72207
 72208
 72209
 72210
 72211
 72212
 72213
 72214
 72215
 72216
 72217
 72218
 72219
 72220
 72221
 72222
 72223
 72224
 72225
 72226
 72227
 72228
 72229
 72230
 72231
 72232
 72233
 72234
 72235
 72236
 72237
 72238
 72239
 72240
 72241
 72242
 72243
 72244
 72245
 72246
 72247
 72248
 72249
 72250
 72251
 72252
 72253
 72254
 72255
 72256
 72257
 72258
 72259
 72260
 72261
 72262
 72263
 72264
 72265
 72266
 72267
 72268
 72269
 72270
 72271
 72272
 72273
 72274
 72275
 72276
 72277
 72278
 72279
 72280
 72281
 72282
 72283
 72284
 72285
 72286
 72287
 72288
 72289
 72290
 72291
 72292
 72293
 72294
 72295
 72296
 72297
 72298
 72299
 72300
 72301
 72302
 72303
 72304
 72305
 72306
 72307
 72308
 72309
 72310
 72311
 72312
 72313
 72314
 72315
 72316
 72317
 72318
 72319
 72320
 72321
 72322
 72323
 72324
 72325
 72326
 72327
 72328
 72329
 72330
 72331
 72332
 72333
 72334
 72335
 72336
 72337
 72338
 72339
 72340
 72341
 72342
 72343
 72344
 72345
 72346
 72347
 72348
 72349
 72350
 72351
 72352
 72353
 72354
 72355
 72356
 72357
 72358
 72359
 72360
 72361
 72362
 72363
 72364
 72365
 72366
 72367
 72368
 72369
 72370
 72371
 72372
 72373
 72374
 72375
 72376
 72377
 72378
 72379
 72380
 72381
 72382
 72383
 72384
 72385
 72386
 72387
 72388
 72389
 72390
 72391
 72392
 72393
 72394
 72395
 72396
 72397
 72398
 72399
 72400
 72401
 72402
 72403
 72404
 72405
 72406
 72407
 72408
 72409
 72410
 72411
 72412
 72413
 72414
 72415
 72416
 72417
 72418
 72419
 72420
 72421
 72422
 72423
 72424
 72425
 72426
 72427
 72428
 72429
 72430
 72431
 72432
 72433
 72434
 72435
 72436
 72437
 72438
 72439
 72440
 72441
 72442
 72443
 72444
 72445
 72446
 72447
 72448
 72449
 72450
 72451
 72452
 72453
 72454
 72455
 72456
 72457
 72458
 72459
 72460
 72461
 72462
 72463
 72464
 72465
 72466
 72467
 72468
 72469
 72470
 72471
 72472
 72473
 72474
 72475
 72476
 72477
 72478
 72479
 72480
 72481
 72482
 72483
 72484
 72485
 72486
 72487
 72488
 72489
 72490
 72491
 72492
 72493
 72494
 72495
 72496
 72497
 72498
 72499
 72500
 72501
 72502
 72503
 72504
 72505
 72506
 72507
 72508
 72509
 72510
 72511
 72512
 72513
 72514
 72515
 72516
 72517
 72518
 72519
 72520
 72521
 72522
 72523
 72524
 72525
 72526
 72527
 72528
 72529
 72530
 72531
 72532
 72533
 72534
 72535
 72536
 72537
 72538
 72539
 72540
 72541
 72542
 72543
 72544
 72545
 72546
 72547
 72548
 72549
 72550
 72551
 72552
 72553
 72554
 72555
 72556
 72557
 72558
 72559
 72560
 72561
 72562
 72563
 72564
 72565
 72566
 72567
 72568
 72569
 72570
 72571
 72572
 72573
 72574
 72575
 72576
 72577
 72578
 72579
 72580
 72581
 72582
 72583
 72584
 72585
 72586
 72587
 72588
 72589
 72590
 72591
 72592
 72593
 72594
 72595
 72596
 72597
 72598
 72599
 72600
 72601
 72602
 72603
 72604
 72605
 72606
 72607
 72608
 72609
 72610
 72611
 72612
 72613
 72614
 72615
 72616
 72617
 72618
 72619
 72620
 72621
 72622
 72623
 72624
 72625
 72626
 72627
 72628
 72629
 72630
 72631
 72632
 72633
 72634
 72635
 72636
 72637
 72638
 72639
 72640
 72641
 72642
 72643
 72644
 72645
 72646
 72647
 72648
 72649
 72650
 72651
 72652
 72653
 72654
 72655
 72656
 72657
 72658
 72659
 72660
 72661
 72662
 72663
 72664
 72665
 72666
 72667
 72668
 72669
 72670
 72671
 72672
 72673
 72674
 72675
 72676
 72677
 72678
 72679
 72680
 72681
 72682
 72683
 72684
 72685
 72686
 72687
 72688
 72689
 72690
 72691
 72692
 72693
 72694
 72695
 72696
 72697
 72698
 72699
 72700
 72701
 72702
 72703
 72704
 72705
 72706
 72707
 72708
 72709
 72710
 72711
 72712
 72713
 72714
 72715
 72716
 72717
 72718
 72719
 72720
 72721
 72722
 72723
 72724
 72725
 72726
 72727
 72728
 72729
 72730
 72731
 72732
 72733
 72734
 72735
 72736
 72737
 72738
 72739
 72740
 72741
 72742
 72743
 72744
 72745
 72746
 72747
 72748
 72749
 72750
 72751
 72752
 72753
 72754
 72755
 72756
 72757
 72758
 72759
 72760
 72761
 72762
 72763
 72764
 72765
 72766
 72767
 72768
 72769
 72770
 72771
 72772
 72773
 72774
 72775
 72776
 72777
 72778
 72779
 72780
 72781
 72782
 72783
 72784
 72785
 72786
 72787
 72788
 72789
 72790
 72791
 72792
 72793
 72794
 72795
 72796
 72797
 72798
 72799
 72800
 72801
 72802
 72803
 72804
 72805
 72806
 72807
 72808
 72809
 72810
 72811
 72812
 72813
 72814
 72815
 72816
 72817
 72818
 72819
 72820
 72821
 72822
 72823
 72824
 72825
 72826
 72827
 72828
 72829
 72830
 72831
 72832
 72833
 72834
 72835
 72836
 72837
 72838
 72839
 72840
 72841
 72842
 72843
 72844
 72845
 72846
 72847
 72848
 72849
 72850
 72851
 72852
 72853
 72854
 72855
 72856
 72857
 72858
 72859
 72860
 72861
 72862
 72863
 72864
 72865
 72866
 72867
 72868
 72869
 72870
 72871
 72872
 72873
 72874
 72875
 72876
 72877
 72878
 72879
 72880
 72881
 72882
 72883
 72884
 72885
 72886
 72887
 72888
 72889
 72890
 72891
 72892
 72893
 72894
 72895
 72896
 72897
 72898
 72899
 72900
 72901
 72902
 72903
 72904
 72905
 72906
 72907
 72908
 72909
 72910
 72911
 72912
 72913
 72914
 72915
 72916
 72917
 72918
 72919
 72920
 72921
 72922
 72923
 72924
 72925
 72926
 72927
 72928
 72929
 72930
 72931
 72932
 72933
 72934
 72935
 72936
 72937
 72938
 72939
 72940
 72941
 72942
 72943
 72944
 72945
 72946
 72947
 72948
 72949
 72950
 72951
 72952
 72953
 72954
 72955
 72956
 72957
 72958
 72959
 72960
 72961
 72962
 72963
 72964
 72965
 72966
 72967
 72968
 72969
 72970
 72971
 72972
 72973
 72974
 72975
 72976
 72977
 72978
 72979
 72980
 72981
 72982
 72983
 72984
 72985
 72986
 72987
 72988
 72989
 72990
 72991
 72992
 72993
 72994
 72995
 72996
 72997
 72998
 72999
 73000
 73001
 73002
 73003
 73004
 73005
 73006
 73007
 73008
 73009
 73010
 73011
 73012
 73013
 73014
 73015
 73016
 73017
 73018
 73019
 73020
 73021
 73022
 73023
 73024
 73025
 73026
 73027
 73028
 73029
 73030
 73031
 73032
 73033
 73034
 73035
 73036
 73037
 73038
 73039
 73040
 73041
 73042
 73043
 73044
 73045
 73046
 73047
 73048
 73049
 73050
 73051
 73052
 73053
 73054
 73055
 73056
 73057
 73058
 73059
 73060
 73061
 73062
 73063
 73064
 73065
 73066
 73067
 73068
 73069
 73070
 73071
 73072
 73073
 73074
 73075
 73076
 73077
 73078
 73079
 73080
 73081
 73082
 73083
 73084
 73085
 73086
 73087
 73088
 73089
 73090
 73091
 73092
 73093
 73094
 73095
 73096
 73097
 73098
 73099
 73100
 73101
 73102
 73103
 73104
 73105
 73106
 73107
 73108
 73109
 73110
 73111
 73112
 73113
 73114
 73115
 73116
 73117
 73118
 73119
 73120
 73121
 73122
 73123
 73124
 73125
 73126
 73127
 73128
 73129
 73130
 73131
 73132
 73133
 73134
 73135
 73136
 73137
 73138
 73139
 73140
 73141
 73142
 73143
 73144
 73145
 73146
 73147
 73148
 73149
 73150
 73151
 73152
 73153
 73154
 73155
 73156
 73157
 73158
 73159
 73160
 73161
 73162
 73163
 73164
 73165
 73166
 73167
 73168
 73169
 73170
 73171
 73172
 73173
 73174
 73175
 73176
 73177
 73178
 73179
 73180
 73181
 73182
 73183
 73184
 73185
 73186
 73187
 73188
 73189
 73190
 73191
 73192
 73193
 73194
 73195
 73196
 73197
 73198
 73199
 73200
 73201
 73202
 73203
 73204
 73205
 73206
 73207
 73208
 73209
 73210
 73211
 73212
 73213
 73214
 73215
 73216
 73217
 73218
 73219
 73220
 73221
 73222
 73223
 73224
 73225
 73226
 73227
 73228
 73229
 73230
 73231
 73232
 73233
 73234
 73235
 73236
 73237
 73238
 73239
 73240
 73241
 73242
 73243
 73244
 73245
 73246
 73247
 73248
 73249
 73250
 73251
 73252
 73253
 73254
 73255
 73256
 73257
 73258
 73259
 73260
 73261
 73262
 73263
 73264
 73265
 73266
 73267
 73268
 73269
 73270
 73271
 73272
 73273
 73274
 73275
 73276
 73277
 73278
 73279
 73280
 73281
 73282
 73283
 73284
 73285
 73286
 73287
 73288
 73289
 73290
 73291
 73292
 73293
 73294
 73295
 73296
 73297
 73298
 73299
 73300
 73301
 73302
 73303
 73304
 73305
 73306
 73307
 73308
 73309
 73310
 73311
 73312
 73313
 73314
 73315
 73316
 73317
 73318
 73319
 73320
 73321
 73322
 73323
 73324
 73325
 73326
 73327
 73328
 73329
 73330
 73331
 73332
 73333
 73334
 73335
 73336
 73337
 73338
 73339
 73340
 73341
 73342
 73343
 73344
 73345
 73346
 73347
 73348
 73349
 73350
 73351
 73352
 73353
 73354
 73355
 73356
 73357
 73358
 73359
 73360
 73361
 73362
 73363
 73364
 73365
 73366
 73367
 73368
 73369
 73370
 73371
 73372
 73373
 73374
 73375
 73376
 73377
 73378
 73379
 73380
 73381
 73382
 73383
 73384
 73385
 73386
 73387
 73388
 73389
 73390
 73391
 73392
 73393
 73394
 73395
 73396
 73397
 73398
 73399
 73400
 73401
 73402
 73403
 73404
 73405
 73406
 73407
 73408
 73409
 73410
 73411
 73412
 73413
 73414
 73415
 73416
 73417
 73418
 73419
 73420
 73421
 73422
 73423
 73424
 73425
 73426
 73427
 73428
 73429
 73430
 73431
 73432
 73433
 73434
 73435
 73436
 73437
 73438
 73439
 73440
 73441
 73442
 73443
 73444
 73445
 73446
 73447
 73448
 73449
 73450
 73451
 73452
 73453
 73454
 73455
 73456
 73457
 73458
 73459
 73460
 73461
 73462
 73463
 73464
 73465
 73466
 73467
 73468
 73469
 73470
 73471
 73472
 73473
 73474
 73475
 73476
 73477
 73478
 73479
 73480
 73481
 73482
 73483
 73484
 73485
 73486
 73487
 73488
 73489
 73490
 73491
 73492
 73493
 73494
 73495
 73496
 73497
 73498
 73499
 73500
 73501
 73502
 73503
 73504
 73505
 73506
 73507
 73508
 73509
 73510
 73511
 73512
 73513
 73514
 73515
 73516
 73517
 73518
 73519
 73520
 73521
 73522
 73523
 73524
 73525
 73526
 73527
 73528
 73529
 73530
 73531
 73532
 73533
 73534
 73535
 73536
 73537
 73538
 73539
 73540
 73541
 73542
 73543
 73544
 73545
 73546
 73547
 73548
 73549
 73550
 73551
 73552
 73553
 73554
 73555
 73556
 73557
 73558
 73559
 73560
 73561
 73562
 73563
 73564
 73565
 73566
 73567
 73568
 73569
 73570
 73571
 73572
 73573
 73574
 73575
 73576
 73577
 73578
 73579
 73580
 73581
 73582
 73583
 73584
 73585
 73586
 73587
 73588
 73589
 73590
 73591
 73592
 73593
 73594
 73595
 73596
 73597
 73598
 73599
 73600
 73601
 73602
 73603
 73604
 73605
 73606
 73607
 73608
 73609
 73610
 73611
 73612
 73613
 73614
 73615
 73616
 73617
 73618
 73619
 73620
 73621
 73622
 73623
 73624
 73625
 73626
 73627
 73628
 73629
 73630
 73631
 73632
 73633
 73634
 73635
 73636
 73637
 73638
 73639
 73640
 73641
 73642
 73643
 73644
 73645
 73646
 73647
 73648
 73649
 73650
 73651
 73652
 73653
 73654
 73655
 73656
 73657
 73658
 73659
 73660
 73661
 73662
 73663
 73664
 73665
 73666
 73667
 73668
 73669
 73670
 73671
 73672
 73673
 73674
 73675
 73676
 73677
 73678
 73679
 73680
 73681
 73682
 73683
 73684
 73685
 73686
 73687
 73688
 73689
 73690
 73691
 73692
 73693
 73694
 73695
 73696
 73697
 73698
 73699
 73700
 73701
 73702
 73703
 73704
 73705
 73706
 73707
 73708
 73709
 73710
 73711
 73712
 73713
 73714
 73715
 73716
 73717
 73718
 73719
 73720
 73721
 73722
 73723
 73724
 73725
 73726
 73727
 73728
 73729
 73730
 73731
 73732
 73733
 73734
 73735
 73736
 73737
 73738
 73739
 73740
 73741
 73742
 73743
 73744
 73745
 73746
 73747
 73748
 73749
 73750
 73751
 73752
 73753
 73754
 73755
 73756
 73757
 73758
 73759
 73760
 73761
 73762
 73763
 73764
 73765
 73766
 73767
 73768
 73769
 73770
 73771
 73772
 73773
 73774
 73775
 73776
 73777
 73778
 73779
 73780
 73781
 73782
 73783
 73784
 73785
 73786
 73787
 73788
 73789
 73790
 73791
 73792
 73793
 73794
 73795
 73796
 73797
 73798
 73799
 73800
 73801
 73802
 73803
 73804
 73805
 73806
 73807
 73808
 73809
 73810
 73811
 73812
 73813
 73814
 73815
 73816
 73817
 73818
 73819
 73820
 73821
 73822
 73823
 73824
 73825
 73826
 73827
 73828
 73829
 73830
 73831
 73832
 73833
 73834
 73835
 73836
 73837
 73838
 73839
 73840
 73841
 73842
 73843
 73844
 73845
 73846
 73847
 73848
 73849
 73850
 73851
 73852
 73853
 73854
 73855
 73856
 73857
 73858
 73859
 73860
 73861
 73862
 73863
 73864
 73865
 73866
 73867
 73868
 73869
 73870
 73871
 73872
 73873
 73874
 73875
 73876
 73877
 73878
 73879
 73880
 73881
 73882
 73883
 73884
 73885
 73886
 73887
 73888
 73889
 73890
 73891
 73892
 73893
 73894
 73895
 73896
 73897
 73898
 73899
 73900
 73901
 73902
 73903
 73904
 73905
 73906
 73907
 73908
 73909
 73910
 73911
 73912
 73913
 73914
 73915
 73916
 73917
 73918
 73919
 73920
 73921
 73922
 73923
 73924
 73925
 73926
 73927
 73928
 73929
 73930
 73931
 73932
 73933
 73934
 73935
 73936
 73937
 73938
 73939
 73940
 73941
 73942
 73943
 73944
 73945
 73946
 73947
 73948
 73949
 73950
 73951
 73952
 73953
 73954
 73955
 73956
 73957
 73958
 73959
 73960
 73961
 73962
 73963
 73964
 73965
 73966
 73967
 73968
 73969
 73970
 73971
 73972
 73973
 73974
 73975
 73976
 73977
 73978
 73979
 73980
 73981
 73982
 73983
 73984
 73985
 73986
 73987
 73988
 73989
 73990
 73991
 73992
 73993
 73994
 73995
 73996
 73997
 73998
 73999
 74000
 74001
 74002
 74003
 74004
 74005
 74006
 74007
 74008
 74009
 74010
 74011
 74012
 74013
 74014
 74015
 74016
 74017
 74018
 74019
 74020
 74021
 74022
 74023
 74024
 74025
 74026
 74027
 74028
 74029
 74030
 74031
 74032
 74033
 74034
 74035
 74036
 74037
 74038
 74039
 74040
 74041
 74042
 74043
 74044
 74045
 74046
 74047
 74048
 74049
 74050
 74051
 74052
 74053
 74054
 74055
 74056
 74057
 74058
 74059
 74060
 74061
 74062
 74063
 74064
 74065
 74066
 74067
 74068
 74069
 74070
 74071
 74072
 74073
 74074
 74075
 74076
 74077
 74078
 74079
 74080
 74081
 74082
 74083
 74084
 74085
 74086
 74087
 74088
 74089
 74090
 74091
 74092
 74093
 74094
 74095
 74096
 74097
 74098
 74099
 74100
 74101
 74102
 74103
 74104
 74105
 74106
 74107
 74108
 74109
 74110
 74111
 74112
 74113
 74114
 74115
 74116
 74117
 74118
 74119
 74120
 74121
 74122
 74123
 74124
 74125
 74126
 74127
 74128
 74129
 74130
 74131
 74132
 74133
 74134
 74135
 74136
 74137
 74138
 74139
 74140
 74141
 74142
 74143
 74144
 74145
 74146
 74147
 74148
 74149
 74150
 74151
 74152
 74153
 74154
 74155
 74156
 74157
 74158
 74159
 74160
 74161
 74162
 74163
 74164
 74165
 74166
 74167
 74168
 74169
 74170
 74171
 74172
 74173
 74174
 74175
 74176
 74177
 74178
 74179
 74180
 74181
 74182
 74183
 74184
 74185
 74186
 74187
 74188
 74189
 74190
 74191
 74192
 74193
 74194
 74195
 74196
 74197
 74198
 74199
 74200
 74201
 74202
 74203
 74204
 74205
 74206
 74207
 74208
 74209
 74210
 74211
 74212
 74213
 74214
 74215
 74216
 74217
 74218
 74219
 74220
 74221
 74222
 74223
 74224
 74225
 74226
 74227
 74228
 74229
 74230
 74231
 74232
 74233
 74234
 74235
 74236
 74237
 74238
 74239
 74240
 74241
 74242
 74243
 74244
 74245
 74246
 74247
 74248
 74249
 74250
 74251
 74252
 74253
 74254
 74255
 74256
 74257
 74258
 74259
 74260
 74261
 74262
 74263
 74264
 74265
 74266
 74267
 74268
 74269
 74270
 74271
 74272
 74273
 74274
 74275
 74276
 74277
 74278
 74279
 74280
 74281
 74282
 74283
 74284
 74285
 74286
 74287
 74288
 74289
 74290
 74291
 74292
 74293
 74294
 74295
 74296
 74297
 74298
 74299
 74300
 74301
 74302
 74303
 74304
 74305
 74306
 74307
 74308
 74309
 74310
 74311
 74312
 74313
 74314
 74315
 74316
 74317
 74318
 74319
 74320
 74321
 74322
 74323
 74324
 74325
 74326
 74327
 74328
 74329
 74330
 74331
 74332
 74333
 74334
 74335
 74336
 74337
 74338
 74339
 74340
 74341
 74342
 74343
 74344
 74345
 74346
 74347
 74348
 74349
 74350
 74351
 74352
 74353
 74354
 74355
 74356
 74357
 74358
 74359
 74360
 74361
 74362
 74363
 74364
 74365
 74366
 74367
 74368
 74369
 74370
 74371
 74372
 74373
 74374
 74375
 74376
 74377
 74378
 74379
 74380
 74381
 74382
 74383
 74384
 74385
 74386
 74387
 74388
 74389
 74390
 74391
 74392
 74393
 74394
 74395
 74396
 74397
 74398
 74399
 74400
 74401
 74402
 74403
 74404
 74405
 74406
 74407
 74408
 74409
 74410
 74411
 74412
 74413
 74414
 74415
 74416
 74417
 74418
 74419
 74420
 74421
 74422
 74423
 74424
 74425
 74426
 74427
 74428
 74429
 74430
 74431
 74432
 74433
 74434
 74435
 74436
 74437
 74438
 74439
 74440
 74441
 74442
 74443
 74444
 74445
 74446
 74447
 74448
 74449
 74450
 74451
 74452
 74453
 74454
 74455
 74456
 74457
 74458
 74459
 74460
 74461
 74462
 74463
 74464
 74465
 74466
 74467
 74468
 74469
 74470
 74471
 74472
 74473
 74474
 74475
 74476
 74477
 74478
 74479
 74480
 74481
 74482
 74483
 74484
 74485
 74486
 74487
 74488
 74489
 74490
 74491
 74492
 74493
 74494
 74495
 74496
 74497
 74498
 74499
 74500
 74501
 74502
 74503
 74504
 74505
 74506
 74507
 74508
 74509
 74510
 74511
 74512
 74513
 74514
 74515
 74516
 74517
 74518
 74519
 74520
 74521
 74522
 74523
 74524
 74525
 74526
 74527
 74528
 74529
 74530
 74531
 74532
 74533
 74534
 74535
 74536
 74537
 74538
 74539
 74540
 74541
 74542
 74543
 74544
 74545
 74546
 74547
 74548
 74549
 74550
 74551
 74552
 74553
 74554
 74555
 74556
 74557
 74558
 74559
 74560
 74561
 74562
 74563
 74564
 74565
 74566
 74567
 74568
 74569
 74570
 74571
 74572
 74573
 74574
 74575
 74576
 74577
 74578
 74579
 74580
 74581
 74582
 74583
 74584
 74585
 74586
 74587
 74588
 74589
 74590
 74591
 74592
 74593
 74594
 74595
 74596
 74597
 74598
 74599
 74600
 74601
 74602
 74603
 74604
 74605
 74606
 74607
 74608
 74609
 74610
 74611
 74612
 74613
 74614
 74615
 74616
 74617
 74618
 74619
 74620
 74621
 74622
 74623
 74624
 74625
 74626
 74627
 74628
 74629
 74630
 74631
 74632
 74633
 74634
 74635
 74636
 74637
 74638
 74639
 74640
 74641
 74642
 74643
 74644
 74645
 74646
 74647
 74648
 74649
 74650
 74651
 74652
 74653
 74654
 74655
 74656
 74657
 74658
 74659
 74660
 74661
 74662
 74663
 74664
 74665
 74666
 74667
 74668
 74669
 74670
 74671
 74672
 74673
 74674
 74675
 74676
 74677
 74678
 74679
 74680
 74681
 74682
 74683
 74684
 74685
 74686
 74687
 74688
 74689
 74690
 74691
 74692
 74693
 74694
 74695
 74696
 74697
 74698
 74699
 74700
 74701
 74702
 74703
 74704
 74705
 74706
 74707
 74708
 74709
 74710
 74711
 74712
 74713
 74714
 74715
 74716
 74717
 74718
 74719
 74720
 74721
 74722
 74723
 74724
 74725
 74726
 74727
 74728
 74729
 74730
 74731
 74732
 74733
 74734
 74735
 74736
 74737
 74738
 74739
 74740
 74741
 74742
 74743
 74744
 74745
 74746
 74747
 74748
 74749
 74750
 74751
 74752
 74753
 74754
 74755
 74756
 74757
 74758
 74759
 74760
 74761
 74762
 74763
 74764
 74765
 74766
 74767
 74768
 74769
 74770
 74771
 74772
 74773
 74774
 74775
 74776
 74777
 74778
 74779
 74780
 74781
 74782
 74783
 74784
 74785
 74786
 74787
 74788
 74789
 74790
 74791
 74792
 74793
 74794
 74795
 74796
 74797
 74798
 74799
 74800
 74801
 74802
 74803
 74804
 74805
 74806
 74807
 74808
 74809
 74810
 74811
 74812
 74813
 74814
 74815
 74816
 74817
 74818
 74819
 74820
 74821
 74822
 74823
 74824
 74825
 74826
 74827
 74828
 74829
 74830
 74831
 74832
 74833
 74834
 74835
 74836
 74837
 74838
 74839
 74840
 74841
 74842
 74843
 74844
 74845
 74846
 74847
 74848
 74849
 74850
 74851
 74852
 74853
 74854
 74855
 74856
 74857
 74858
 74859
 74860
 74861
 74862
 74863
 74864
 74865
 74866
 74867
 74868
 74869
 74870
 74871
 74872
 74873
 74874
 74875
 74876
 74877
 74878
 74879
 74880
 74881
 74882
 74883
 74884
 74885
 74886
 74887
 74888
 74889
 74890
 74891
 74892
 74893
 74894
 74895
 74896
 74897
 74898
 74899
 74900
 74901
 74902
 74903
 74904
 74905
 74906
 74907
 74908
 74909
 74910
 74911
 74912
 74913
 74914
 74915
 74916
 74917
 74918
 74919
 74920
 74921
 74922
 74923
 74924
 74925
 74926
 74927
 74928
 74929
 74930
 74931
 74932
 74933
 74934
 74935
 74936
 74937
 74938
 74939
 74940
 74941
 74942
 74943
 74944
 74945
 74946
 74947
 74948
 74949
 74950
 74951
 74952
 74953
 74954
 74955
 74956
 74957
 74958
 74959
 74960
 74961
 74962
 74963
 74964
 74965
 74966
 74967
 74968
 74969
 74970
 74971
 74972
 74973
 74974
 74975
 74976
 74977
 74978
 74979
 74980
 74981
 74982
 74983
 74984
 74985
 74986
 74987
 74988
 74989
 74990
 74991
 74992
 74993
 74994
 74995
 74996
 74997
 74998
 74999
 75000
 75001
 75002
 75003
 75004
 75005
 75006
 75007
 75008
 75009
 75010
 75011
 75012
 75013
 75014
 75015
 75016
 75017
 75018
 75019
 75020
 75021
 75022
 75023
 75024
 75025
 75026
 75027
 75028
 75029
 75030
 75031
 75032
 75033
 75034
 75035
 75036
 75037
 75038
 75039
 75040
 75041
 75042
 75043
 75044
 75045
 75046
 75047
 75048
 75049
 75050
 75051
 75052
 75053
 75054
 75055
 75056
 75057
 75058
 75059
 75060
 75061
 75062
 75063
 75064
 75065
 75066
 75067
 75068
 75069
 75070
 75071
 75072
 75073
 75074
 75075
 75076
 75077
 75078
 75079
 75080
 75081
 75082
 75083
 75084
 75085
 75086
 75087
 75088
 75089
 75090
 75091
 75092
 75093
 75094
 75095
 75096
 75097
 75098
 75099
 75100
 75101
 75102
 75103
 75104
 75105
 75106
 75107
 75108
 75109
 75110
 75111
 75112
 75113
 75114
 75115
 75116
 75117
 75118
 75119
 75120
 75121
 75122
 75123
 75124
 75125
 75126
 75127
 75128
 75129
 75130
 75131
 75132
 75133
 75134
 75135
 75136
 75137
 75138
 75139
 75140
 75141
 75142
 75143
 75144
 75145
 75146
 75147
 75148
 75149
 75150
 75151
 75152
 75153
 75154
 75155
 75156
 75157
 75158
 75159
 75160
 75161
 75162
 75163
 75164
 75165
 75166
 75167
 75168
 75169
 75170
 75171
 75172
 75173
 75174
 75175
 75176
 75177
 75178
 75179
 75180
 75181
 75182
 75183
 75184
 75185
 75186
 75187
 75188
 75189
 75190
 75191
 75192
 75193
 75194
 75195
 75196
 75197
 75198
 75199
 75200
 75201
 75202
 75203
 75204
 75205
 75206
 75207
 75208
 75209
 75210
 75211
 75212
 75213
 75214
 75215
 75216
 75217
 75218
 75219
 75220
 75221
 75222
 75223
 75224
 75225
 75226
 75227
 75228
 75229
 75230
 75231
 75232
 75233
 75234
 75235
 75236
 75237
 75238
 75239
 75240
 75241
 75242
 75243
 75244
 75245
 75246
 75247
 75248
 75249
 75250
 75251
 75252
 75253
 75254
 75255
 75256
 75257
 75258
 75259
 75260
 75261
 75262
 75263
 75264
 75265
 75266
 75267
 75268
 75269
 75270
 75271
 75272
 75273
 75274
 75275
 75276
 75277
 75278
 75279
 75280
 75281
 75282
 75283
 75284
 75285
 75286
 75287
 75288
 75289
 75290
 75291
 75292
 75293
 75294
 75295
 75296
 75297
 75298
 75299
 75300
 75301
 75302
 75303
 75304
 75305
 75306
 75307
 75308
 75309
 75310
 75311
 75312
 75313
 75314
 75315
 75316
 75317
 75318
 75319
 75320
 75321
 75322
 75323
 75324
 75325
 75326
 75327
 75328
 75329
 75330
 75331
 75332
 75333
 75334
 75335
 75336
 75337
 75338
 75339
 75340
 75341
 75342
 75343
 75344
 75345
 75346
 75347
 75348
 75349
 75350
 75351
 75352
 75353
 75354
 75355
 75356
 75357
 75358
 75359
 75360
 75361
 75362
 75363
 75364
 75365
 75366
 75367
 75368
 75369
 75370
 75371
 75372
 75373
 75374
 75375
 75376
 75377
 75378
 75379
 75380
 75381
 75382
 75383
 75384
 75385
 75386
 75387
 75388
 75389
 75390
 75391
 75392
 75393
 75394
 75395
 75396
 75397
 75398
 75399
 75400
 75401
 75402
 75403
 75404
 75405
 75406
 75407
 75408
 75409
 75410
 75411
 75412
 75413
 75414
 75415
 75416
 75417
 75418
 75419
 75420
 75421
 75422
 75423
 75424
 75425
 75426
 75427
 75428
 75429
 75430
 75431
 75432
 75433
 75434
 75435
 75436
 75437
 75438
 75439
 75440
 75441
 75442
 75443
 75444
 75445
 75446
 75447
 75448
 75449
 75450
 75451
 75452
 75453
 75454
 75455
 75456
 75457
 75458
 75459
 75460
 75461
 75462
 75463
 75464
 75465
 75466
 75467
 75468
 75469
 75470
 75471
 75472
 75473
 75474
 75475
 75476
 75477
 75478
 75479
 75480
 75481
 75482
 75483
 75484
 75485
 75486
 75487
 75488
 75489
 75490
 75491
 75492
 75493
 75494
 75495
 75496
 75497
 75498
 75499
 75500
 75501
 75502
 75503
 75504
 75505
 75506
 75507
 75508
 75509
 75510
 75511
 75512
 75513
 75514
 75515
 75516
 75517
 75518
 75519
 75520
 75521
 75522
 75523
 75524
 75525
 75526
 75527
 75528
 75529
 75530
 75531
 75532
 75533
 75534
 75535
 75536
 75537
 75538
 75539
 75540
 75541
 75542
 75543
 75544
 75545
 75546
 75547
 75548
 75549
 75550
 75551
 75552
 75553
 75554
 75555
 75556
 75557
 75558
 75559
 75560
 75561
 75562
 75563
 75564
 75565
 75566
 75567
 75568
 75569
 75570
 75571
 75572
 75573
 75574
 75575
 75576
 75577
 75578
 75579
 75580
 75581
 75582
 75583
 75584
 75585
 75586
 75587
 75588
 75589
 75590
 75591
 75592
 75593
 75594
 75595
 75596
 75597
 75598
 75599
 75600
 75601
 75602
 75603
 75604
 75605
 75606
 75607
 75608
 75609
 75610
 75611
 75612
 75613
 75614
 75615
 75616
 75617
 75618
 75619
 75620
 75621
 75622
 75623
 75624
 75625
 75626
 75627
 75628
 75629
 75630
 75631
 75632
 75633
 75634
 75635
 75636
 75637
 75638
 75639
 75640
 75641
 75642
 75643
 75644
 75645
 75646
 75647
 75648
 75649
 75650
 75651
 75652
 75653
 75654
 75655
 75656
 75657
 75658
 75659
 75660
 75661
 75662
 75663
 75664
 75665
 75666
 75667
 75668
 75669
 75670
 75671
 75672
 75673
 75674
 75675
 75676
 75677
 75678
 75679
 75680
 75681
 75682
 75683
 75684
 75685
 75686
 75687
 75688
 75689
 75690
 75691
 75692
 75693
 75694
 75695
 75696
 75697
 75698
 75699
 75700
 75701
 75702
 75703
 75704
 75705
 75706
 75707
 75708
 75709
 75710
 75711
 75712
 75713
 75714
 75715
 75716
 75717
 75718
 75719
 75720
 75721
 75722
 75723
 75724
 75725
 75726
 75727
 75728
 75729
 75730
 75731
 75732
 75733
 75734
 75735
 75736
 75737
 75738
 75739
 75740
 75741
 75742
 75743
 75744
 75745
 75746
 75747
 75748
 75749
 75750
 75751
 75752
 75753
 75754
 75755
 75756
 75757
 75758
 75759
 75760
 75761
 75762
 75763
 75764
 75765
 75766
 75767
 75768
 75769
 75770
 75771
 75772
 75773
 75774
 75775
 75776
 75777
 75778
 75779
 75780
 75781
 75782
 75783
 75784
 75785
 75786
 75787
 75788
 75789
 75790
 75791
 75792
 75793
 75794
 75795
 75796
 75797
 75798
 75799
 75800
 75801
 75802
 75803
 75804
 75805
 75806
 75807
 75808
 75809
 75810
 75811
 75812
 75813
 75814
 75815
 75816
 75817
 75818
 75819
 75820
 75821
 75822
 75823
 75824
 75825
 75826
 75827
 75828
 75829
 75830
 75831
 75832
 75833
 75834
 75835
 75836
 75837
 75838
 75839
 75840
 75841
 75842
 75843
 75844
 75845
 75846
 75847
 75848
 75849
 75850
 75851
 75852
 75853
 75854
 75855
 75856
 75857
 75858
 75859
 75860
 75861
 75862
 75863
 75864
 75865
 75866
 75867
 75868
 75869
 75870
 75871
 75872
 75873
 75874
 75875
 75876
 75877
 75878
 75879
 75880
 75881
 75882
 75883
 75884
 75885
 75886
 75887
 75888
 75889
 75890
 75891
 75892
 75893
 75894
 75895
 75896
 75897
 75898
 75899
 75900
 75901
 75902
 75903
 75904
 75905
 75906
 75907
 75908
 75909
 75910
 75911
 75912
 75913
 75914
 75915
 75916
 75917
 75918
 75919
 75920
 75921
 75922
 75923
 75924
 75925
 75926
 75927
 75928
 75929
 75930
 75931
 75932
 75933
 75934
 75935
 75936
 75937
 75938
 75939
 75940
 75941
 75942
 75943
 75944
 75945
 75946
 75947
 75948
 75949
 75950
 75951
 75952
 75953
 75954
 75955
 75956
 75957
 75958
 75959
 75960
 75961
 75962
 75963
 75964
 75965
 75966
 75967
 75968
 75969
 75970
 75971
 75972
 75973
 75974
 75975
 75976
 75977
 75978
 75979
 75980
 75981
 75982
 75983
 75984
 75985
 75986
 75987
 75988
 75989
 75990
 75991
 75992
 75993
 75994
 75995
 75996
 75997
 75998
 75999
 76000
 76001
 76002
 76003
 76004
 76005
 76006
 76007
 76008
 76009
 76010
 76011
 76012
 76013
 76014
 76015
 76016
 76017
 76018
 76019
 76020
 76021
 76022
 76023
 76024
 76025
 76026
 76027
 76028
 76029
 76030
 76031
 76032
 76033
 76034
 76035
 76036
 76037
 76038
 76039
 76040
 76041
 76042
 76043
 76044
 76045
 76046
 76047
 76048
 76049
 76050
 76051
 76052
 76053
 76054
 76055
 76056
 76057
 76058
 76059
 76060
 76061
 76062
 76063
 76064
 76065
 76066
 76067
 76068
 76069
 76070
 76071
 76072
 76073
 76074
 76075
 76076
 76077
 76078
 76079
 76080
 76081
 76082
 76083
 76084
 76085
 76086
 76087
 76088
 76089
 76090
 76091
 76092
 76093
 76094
 76095
 76096
 76097
 76098
 76099
 76100
 76101
 76102
 76103
 76104
 76105
 76106
 76107
 76108
 76109
 76110
 76111
 76112
 76113
 76114
 76115
 76116
 76117
 76118
 76119
 76120
 76121
 76122
 76123
 76124
 76125
 76126
 76127
 76128
 76129
 76130
 76131
 76132
 76133
 76134
 76135
 76136
 76137
 76138
 76139
 76140
 76141
 76142
 76143
 76144
 76145
 76146
 76147
 76148
 76149
 76150
 76151
 76152
 76153
 76154
 76155
 76156
 76157
 76158
 76159
 76160
 76161
 76162
 76163
 76164
 76165
 76166
 76167
 76168
 76169
 76170
 76171
 76172
 76173
 76174
 76175
 76176
 76177
 76178
 76179
 76180
 76181
 76182
 76183
 76184
 76185
 76186
 76187
 76188
 76189
 76190
 76191
 76192
 76193
 76194
 76195
 76196
 76197
 76198
 76199
 76200
 76201
 76202
 76203
 76204
 76205
 76206
 76207
 76208
 76209
 76210
 76211
 76212
 76213
 76214
 76215
 76216
 76217
 76218
 76219
 76220
 76221
 76222
 76223
 76224
 76225
 76226
 76227
 76228
 76229
 76230
 76231
 76232
 76233
 76234
 76235
 76236
 76237
 76238
 76239
 76240
 76241
 76242
 76243
 76244
 76245
 76246
 76247
 76248
 76249
 76250
 76251
 76252
 76253
 76254
 76255
 76256
 76257
 76258
 76259
 76260
 76261
 76262
 76263
 76264
 76265
 76266
 76267
 76268
 76269
 76270
 76271
 76272
 76273
 76274
 76275
 76276
 76277
 76278
 76279
 76280
 76281
 76282
 76283
 76284
 76285
 76286
 76287
 76288
 76289
 76290
 76291
 76292
 76293
 76294
 76295
 76296
 76297
 76298
 76299
 76300
 76301
 76302
 76303
 76304
 76305
 76306
 76307
 76308
 76309
 76310
 76311
 76312
 76313
 76314
 76315
 76316
 76317
 76318
 76319
 76320
 76321
 76322
 76323
 76324
 76325
 76326
 76327
 76328
 76329
 76330
 76331
 76332
 76333
 76334
 76335
 76336
 76337
 76338
 76339
 76340
 76341
 76342
 76343
 76344
 76345
 76346
 76347
 76348
 76349
 76350
 76351
 76352
 76353
 76354
 76355
 76356
 76357
 76358
 76359
 76360
 76361
 76362
 76363
 76364
 76365
 76366
 76367
 76368
 76369
 76370
 76371
 76372
 76373
 76374
 76375
 76376
 76377
 76378
 76379
 76380
 76381
 76382
 76383
 76384
 76385
 76386
 76387
 76388
 76389
 76390
 76391
 76392
 76393
 76394
 76395
 76396
 76397
 76398
 76399
 76400
 76401
 76402
 76403
 76404
 76405
 76406
 76407
 76408
 76409
 76410
 76411
 76412
 76413
 76414
 76415
 76416
 76417
 76418
 76419
 76420
 76421
 76422
 76423
 76424
 76425
 76426
 76427
 76428
 76429
 76430
 76431
 76432
 76433
 76434
 76435
 76436
 76437
 76438
 76439
 76440
 76441
 76442
 76443
 76444
 76445
 76446
 76447
 76448
 76449
 76450
 76451
 76452
 76453
 76454
 76455
 76456
 76457
 76458
 76459
 76460
 76461
 76462
 76463
 76464
 76465
 76466
 76467
 76468
 76469
 76470
 76471
 76472
 76473
 76474
 76475
 76476
 76477
 76478
 76479
 76480
 76481
 76482
 76483
 76484
 76485
 76486
 76487
 76488
 76489
 76490
 76491
 76492
 76493
 76494
 76495
 76496
 76497
 76498
 76499
 76500
 76501
 76502
 76503
 76504
 76505
 76506
 76507
 76508
 76509
 76510
 76511
 76512
 76513
 76514
 76515
 76516
 76517
 76518
 76519
 76520
 76521
 76522
 76523
 76524
 76525
 76526
 76527
 76528
 76529
 76530
 76531
 76532
 76533
 76534
 76535
 76536
 76537
 76538
 76539
 76540
 76541
 76542
 76543
 76544
 76545
 76546
 76547
 76548
 76549
 76550
 76551
 76552
 76553
 76554
 76555
 76556
 76557
 76558
 76559
 76560
 76561
 76562
 76563
 76564
 76565
 76566
 76567
 76568
 76569
 76570
 76571
 76572
 76573
 76574
 76575
 76576
 76577
 76578
 76579
 76580
 76581
 76582
 76583
 76584
 76585
 76586
 76587
 76588
 76589
 76590
 76591
 76592
 76593
 76594
 76595
 76596
 76597
 76598
 76599
 76600
 76601
 76602
 76603
 76604
 76605
 76606
 76607
 76608
 76609
 76610
 76611
 76612
 76613
 76614
 76615
 76616
 76617
 76618
 76619
 76620
 76621
 76622
 76623
 76624
 76625
 76626
 76627
 76628
 76629
 76630
 76631
 76632
 76633
 76634
 76635
 76636
 76637
 76638
 76639
 76640
 76641
 76642
 76643
 76644
 76645
 76646
 76647
 76648
 76649
 76650
 76651
 76652
 76653
 76654
 76655
 76656
 76657
 76658
 76659
 76660
 76661
 76662
 76663
 76664
 76665
 76666
 76667
 76668
 76669
 76670
 76671
 76672
 76673
 76674
 76675
 76676
 76677
 76678
 76679
 76680
 76681
 76682
 76683
 76684
 76685
 76686
 76687
 76688
 76689
 76690
 76691
 76692
 76693
 76694
 76695
 76696
 76697
 76698
 76699
 76700
 76701
 76702
 76703
 76704
 76705
 76706
 76707
 76708
 76709
 76710
 76711
 76712
 76713
 76714
 76715
 76716
 76717
 76718
 76719
 76720
 76721
 76722
 76723
 76724
 76725
 76726
 76727
 76728
 76729
 76730
 76731
 76732
 76733
 76734
 76735
 76736
 76737
 76738
 76739
 76740
 76741
 76742
 76743
 76744
 76745
 76746
 76747
 76748
 76749
 76750
 76751
 76752
 76753
 76754
 76755
 76756
 76757
 76758
 76759
 76760
 76761
 76762
 76763
 76764
 76765
 76766
 76767
 76768
 76769
 76770
 76771
 76772
 76773
 76774
 76775
 76776
 76777
 76778
 76779
 76780
 76781
 76782
 76783
 76784
 76785
 76786
 76787
 76788
 76789
 76790
 76791
 76792
 76793
 76794
 76795
 76796
 76797
 76798
 76799
 76800
 76801
 76802
 76803
 76804
 76805
 76806
 76807
 76808
 76809
 76810
 76811
 76812
 76813
 76814
 76815
 76816
 76817
 76818
 76819
 76820
 76821
 76822
 76823
 76824
 76825
 76826
 76827
 76828
 76829
 76830
 76831
 76832
 76833
 76834
 76835
 76836
 76837
 76838
 76839
 76840
 76841
 76842
 76843
 76844
 76845
 76846
 76847
 76848
 76849
 76850
 76851
 76852
 76853
 76854
 76855
 76856
 76857
 76858
 76859
 76860
 76861
 76862
 76863
 76864
 76865
 76866
 76867
 76868
 76869
 76870
 76871
 76872
 76873
 76874
 76875
 76876
 76877
 76878
 76879
 76880
 76881
 76882
 76883
 76884
 76885
 76886
 76887
 76888
 76889
 76890
 76891
 76892
 76893
 76894
 76895
 76896
 76897
 76898
 76899
 76900
 76901
 76902
 76903
 76904
 76905
 76906
 76907
 76908
 76909
 76910
 76911
 76912
 76913
 76914
 76915
 76916
 76917
 76918
 76919
 76920
 76921
 76922
 76923
 76924
 76925
 76926
 76927
 76928
 76929
 76930
 76931
 76932
 76933
 76934
 76935
 76936
 76937
 76938
 76939
 76940
 76941
 76942
 76943
 76944
 76945
 76946
 76947
 76948
 76949
 76950
 76951
 76952
 76953
 76954
 76955
 76956
 76957
 76958
 76959
 76960
 76961
 76962
 76963
 76964
 76965
 76966
 76967
 76968
 76969
 76970
 76971
 76972
 76973
 76974
 76975
 76976
 76977
 76978
 76979
 76980
 76981
 76982
 76983
 76984
 76985
 76986
 76987
 76988
 76989
 76990
 76991
 76992
 76993
 76994
 76995
 76996
 76997
 76998
 76999
 77000
 77001
 77002
 77003
 77004
 77005
 77006
 77007
 77008
 77009
 77010
 77011
 77012
 77013
 77014
 77015
 77016
 77017
 77018
 77019
 77020
 77021
 77022
 77023
 77024
 77025
 77026
 77027
 77028
 77029
 77030
 77031
 77032
 77033
 77034
 77035
 77036
 77037
 77038
 77039
 77040
 77041
 77042
 77043
 77044
 77045
 77046
 77047
 77048
 77049
 77050
 77051
 77052
 77053
 77054
 77055
 77056
 77057
 77058
 77059
 77060
 77061
 77062
 77063
 77064
 77065
 77066
 77067
 77068
 77069
 77070
 77071
 77072
 77073
 77074
 77075
 77076
 77077
 77078
 77079
 77080
 77081
 77082
 77083
 77084
 77085
 77086
 77087
 77088
 77089
 77090
 77091
 77092
 77093
 77094
 77095
 77096
 77097
 77098
 77099
 77100
 77101
 77102
 77103
 77104
 77105
 77106
 77107
 77108
 77109
 77110
 77111
 77112
 77113
 77114
 77115
 77116
 77117
 77118
 77119
 77120
 77121
 77122
 77123
 77124
 77125
 77126
 77127
 77128
 77129
 77130
 77131
 77132
 77133
 77134
 77135
 77136
 77137
 77138
 77139
 77140
 77141
 77142
 77143
 77144
 77145
 77146
 77147
 77148
 77149
 77150
 77151
 77152
 77153
 77154
 77155
 77156
 77157
 77158
 77159
 77160
 77161
 77162
 77163
 77164
 77165
 77166
 77167
 77168
 77169
 77170
 77171
 77172
 77173
 77174
 77175
 77176
 77177
 77178
 77179
 77180
 77181
 77182
 77183
 77184
 77185
 77186
 77187
 77188
 77189
 77190
 77191
 77192
 77193
 77194
 77195
 77196
 77197
 77198
 77199
 77200
 77201
 77202
 77203
 77204
 77205
 77206
 77207
 77208
 77209
 77210
 77211
 77212
 77213
 77214
 77215
 77216
 77217
 77218
 77219
 77220
 77221
 77222
 77223
 77224
 77225
 77226
 77227
 77228
 77229
 77230
 77231
 77232
 77233
 77234
 77235
 77236
 77237
 77238
 77239
 77240
 77241
 77242
 77243
 77244
 77245
 77246
 77247
 77248
 77249
 77250
 77251
 77252
 77253
 77254
 77255
 77256
 77257
 77258
 77259
 77260
 77261
 77262
 77263
 77264
 77265
 77266
 77267
 77268
 77269
 77270
 77271
 77272
 77273
 77274
 77275
 77276
 77277
 77278
 77279
 77280
 77281
 77282
 77283
 77284
 77285
 77286
 77287
 77288
 77289
 77290
 77291
 77292
 77293
 77294
 77295
 77296
 77297
 77298
 77299
 77300
 77301
 77302
 77303
 77304
 77305
 77306
 77307
 77308
 77309
 77310
 77311
 77312
 77313
 77314
 77315
 77316
 77317
 77318
 77319
 77320
 77321
 77322
 77323
 77324
 77325
 77326
 77327
 77328
 77329
 77330
 77331
 77332
 77333
 77334
 77335
 77336
 77337
 77338
 77339
 77340
 77341
 77342
 77343
 77344
 77345
 77346
 77347
 77348
 77349
 77350
 77351
 77352
 77353
 77354
 77355
 77356
 77357
 77358
 77359
 77360
 77361
 77362
 77363
 77364
 77365
 77366
 77367
 77368
 77369
 77370
 77371
 77372
 77373
 77374
 77375
 77376
 77377
 77378
 77379
 77380
 77381
 77382
 77383
 77384
 77385
 77386
 77387
 77388
 77389
 77390
 77391
 77392
 77393
 77394
 77395
 77396
 77397
 77398
 77399
 77400
 77401
 77402
 77403
 77404
 77405
 77406
 77407
 77408
 77409
 77410
 77411
 77412
 77413
 77414
 77415
 77416
 77417
 77418
 77419
 77420
 77421
 77422
 77423
 77424
 77425
 77426
 77427
 77428
 77429
 77430
 77431
 77432
 77433
 77434
 77435
 77436
 77437
 77438
 77439
 77440
 77441
 77442
 77443
 77444
 77445
 77446
 77447
 77448
 77449
 77450
 77451
 77452
 77453
 77454
 77455
 77456
 77457
 77458
 77459
 77460
 77461
 77462
 77463
 77464
 77465
 77466
 77467
 77468
 77469
 77470
 77471
 77472
 77473
 77474
 77475
 77476
 77477
 77478
 77479
 77480
 77481
 77482
 77483
 77484
 77485
 77486
 77487
 77488
 77489
 77490
 77491
 77492
 77493
 77494
 77495
 77496
 77497
 77498
 77499
 77500
 77501
 77502
 77503
 77504
 77505
 77506
 77507
 77508
 77509
 77510
 77511
 77512
 77513
 77514
 77515
 77516
 77517
 77518
 77519
 77520
 77521
 77522
 77523
 77524
 77525
 77526
 77527
 77528
 77529
 77530
 77531
 77532
 77533
 77534
 77535
 77536
 77537
 77538
 77539
 77540
 77541
 77542
 77543
 77544
 77545
 77546
 77547
 77548
 77549
 77550
 77551
 77552
 77553
 77554
 77555
 77556
 77557
 77558
 77559
 77560
 77561
 77562
 77563
 77564
 77565
 77566
 77567
 77568
 77569
 77570
 77571
 77572
 77573
 77574
 77575
 77576
 77577
 77578
 77579
 77580
 77581
 77582
 77583
 77584
 77585
 77586
 77587
 77588
 77589
 77590
 77591
 77592
 77593
 77594
 77595
 77596
 77597
 77598
 77599
 77600
 77601
 77602
 77603
 77604
 77605
 77606
 77607
 77608
 77609
 77610
 77611
 77612
 77613
 77614
 77615
 77616
 77617
 77618
 77619
 77620
 77621
 77622
 77623
 77624
 77625
 77626
 77627
 77628
 77629
 77630
 77631
 77632
 77633
 77634
 77635
 77636
 77637
 77638
 77639
 77640
 77641
 77642
 77643
 77644
 77645
 77646
 77647
 77648
 77649
 77650
 77651
 77652
 77653
 77654
 77655
 77656
 77657
 77658
 77659
 77660
 77661
 77662
 77663
 77664
 77665
 77666
 77667
 77668
 77669
 77670
 77671
 77672
 77673
 77674
 77675
 77676
 77677
 77678
 77679
 77680
 77681
 77682
 77683
 77684
 77685
 77686
 77687
 77688
 77689
 77690
 77691
 77692
 77693
 77694
 77695
 77696
 77697
 77698
 77699
 77700
 77701
 77702
 77703
 77704
 77705
 77706
 77707
 77708
 77709
 77710
 77711
 77712
 77713
 77714
 77715
 77716
 77717
 77718
 77719
 77720
 77721
 77722
 77723
 77724
 77725
 77726
 77727
 77728
 77729
 77730
 77731
 77732
 77733
 77734
 77735
 77736
 77737
 77738
 77739
 77740
 77741
 77742
 77743
 77744
 77745
 77746
 77747
 77748
 77749
 77750
 77751
 77752
 77753
 77754
 77755
 77756
 77757
 77758
 77759
 77760
 77761
 77762
 77763
 77764
 77765
 77766
 77767
 77768
 77769
 77770
 77771
 77772
 77773
 77774
 77775
 77776
 77777
 77778
 77779
 77780
 77781
 77782
 77783
 77784
 77785
 77786
 77787
 77788
 77789
 77790
 77791
 77792
 77793
 77794
 77795
 77796
 77797
 77798
 77799
 77800
 77801
 77802
 77803
 77804
 77805
 77806
 77807
 77808
 77809
 77810
 77811
 77812
 77813
 77814
 77815
 77816
 77817
 77818
 77819
 77820
 77821
 77822
 77823
 77824
 77825
 77826
 77827
 77828
 77829
 77830
 77831
 77832
 77833
 77834
 77835
 77836
 77837
 77838
 77839
 77840
 77841
 77842
 77843
 77844
 77845
 77846
 77847
 77848
 77849
 77850
 77851
 77852
 77853
 77854
 77855
 77856
 77857
 77858
 77859
 77860
 77861
 77862
 77863
 77864
 77865
 77866
 77867
 77868
 77869
 77870
 77871
 77872
 77873
 77874
 77875
 77876
 77877
 77878
 77879
 77880
 77881
 77882
 77883
 77884
 77885
 77886
 77887
 77888
 77889
 77890
 77891
 77892
 77893
 77894
 77895
 77896
 77897
 77898
 77899
 77900
 77901
 77902
 77903
 77904
 77905
 77906
 77907
 77908
 77909
 77910
 77911
 77912
 77913
 77914
 77915
 77916
 77917
 77918
 77919
 77920
 77921
 77922
 77923
 77924
 77925
 77926
 77927
 77928
 77929
 77930
 77931
 77932
 77933
 77934
 77935
 77936
 77937
 77938
 77939
 77940
 77941
 77942
 77943
 77944
 77945
 77946
 77947
 77948
 77949
 77950
 77951
 77952
 77953
 77954
 77955
 77956
 77957
 77958
 77959
 77960
 77961
 77962
 77963
 77964
 77965
 77966
 77967
 77968
 77969
 77970
 77971
 77972
 77973
 77974
 77975
 77976
 77977
 77978
 77979
 77980
 77981
 77982
 77983
 77984
 77985
 77986
 77987
 77988
 77989
 77990
 77991
 77992
 77993
 77994
 77995
 77996
 77997
 77998
 77999
 78000
 78001
 78002
 78003
 78004
 78005
 78006
 78007
 78008
 78009
 78010
 78011
 78012
 78013
 78014
 78015
 78016
 78017
 78018
 78019
 78020
 78021
 78022
 78023
 78024
 78025
 78026
 78027
 78028
 78029
 78030
 78031
 78032
 78033
 78034
 78035
 78036
 78037
 78038
 78039
 78040
 78041
 78042
 78043
 78044
 78045
 78046
 78047
 78048
 78049
 78050
 78051
 78052
 78053
 78054
 78055
 78056
 78057
 78058
 78059
 78060
 78061
 78062
 78063
 78064
 78065
 78066
 78067
 78068
 78069
 78070
 78071
 78072
 78073
 78074
 78075
 78076
 78077
 78078
 78079
 78080
 78081
 78082
 78083
 78084
 78085
 78086
 78087
 78088
 78089
 78090
 78091
 78092
 78093
 78094
 78095
 78096
 78097
 78098
 78099
 78100
 78101
 78102
 78103
 78104
 78105
 78106
 78107
 78108
 78109
 78110
 78111
 78112
 78113
 78114
 78115
 78116
 78117
 78118
 78119
 78120
 78121
 78122
 78123
 78124
 78125
 78126
 78127
 78128
 78129
 78130
 78131
 78132
 78133
 78134
 78135
 78136
 78137
 78138
 78139
 78140
 78141
 78142
 78143
 78144
 78145
 78146
 78147
 78148
 78149
 78150
 78151
 78152
 78153
 78154
 78155
 78156
 78157
 78158
 78159
 78160
 78161
 78162
 78163
 78164
 78165
 78166
 78167
 78168
 78169
 78170
 78171
 78172
 78173
 78174
 78175
 78176
 78177
 78178
 78179
 78180
 78181
 78182
 78183
 78184
 78185
 78186
 78187
 78188
 78189
 78190
 78191
 78192
 78193
 78194
 78195
 78196
 78197
 78198
 78199
 78200
 78201
 78202
 78203
 78204
 78205
 78206
 78207
 78208
 78209
 78210
 78211
 78212
 78213
 78214
 78215
 78216
 78217
 78218
 78219
 78220
 78221
 78222
 78223
 78224
 78225
 78226
 78227
 78228
 78229
 78230
 78231
 78232
 78233
 78234
 78235
 78236
 78237
 78238
 78239
 78240
 78241
 78242
 78243
 78244
 78245
 78246
 78247
 78248
 78249
 78250
 78251
 78252
 78253
 78254
 78255
 78256
 78257
 78258
 78259
 78260
 78261
 78262
 78263
 78264
 78265
 78266
 78267
 78268
 78269
 78270
 78271
 78272
 78273
 78274
 78275
 78276
 78277
 78278
 78279
 78280
 78281
 78282
 78283
 78284
 78285
 78286
 78287
 78288
 78289
 78290
 78291
 78292
 78293
 78294
 78295
 78296
 78297
 78298
 78299
 78300
 78301
 78302
 78303
 78304
 78305
 78306
 78307
 78308
 78309
 78310
 78311
 78312
 78313
 78314
 78315
 78316
 78317
 78318
 78319
 78320
 78321
 78322
 78323
 78324
 78325
 78326
 78327
 78328
 78329
 78330
 78331
 78332
 78333
 78334
 78335
 78336
 78337
 78338
 78339
 78340
 78341
 78342
 78343
 78344
 78345
 78346
 78347
 78348
 78349
 78350
 78351
 78352
 78353
 78354
 78355
 78356
 78357
 78358
 78359
 78360
 78361
 78362
 78363
 78364
 78365
 78366
 78367
 78368
 78369
 78370
 78371
 78372
 78373
 78374
 78375
 78376
 78377
 78378
 78379
 78380
 78381
 78382
 78383
 78384
 78385
 78386
 78387
 78388
 78389
 78390
 78391
 78392
 78393
 78394
 78395
 78396
 78397
 78398
 78399
 78400
 78401
 78402
 78403
 78404
 78405
 78406
 78407
 78408
 78409
 78410
 78411
 78412
 78413
 78414
 78415
 78416
 78417
 78418
 78419
 78420
 78421
 78422
 78423
 78424
 78425
 78426
 78427
 78428
 78429
 78430
 78431
 78432
 78433
 78434
 78435
 78436
 78437
 78438
 78439
 78440
 78441
 78442
 78443
 78444
 78445
 78446
 78447
 78448
 78449
 78450
 78451
 78452
 78453
 78454
 78455
 78456
 78457
 78458
 78459
 78460
 78461
 78462
 78463
 78464
 78465
 78466
 78467
 78468
 78469
 78470
 78471
 78472
 78473
 78474
 78475
 78476
 78477
 78478
 78479
 78480
 78481
 78482
 78483
 78484
 78485
 78486
 78487
 78488
 78489
 78490
 78491
 78492
 78493
 78494
 78495
 78496
 78497
 78498
 78499
 78500
 78501
 78502
 78503
 78504
 78505
 78506
 78507
 78508
 78509
 78510
 78511
 78512
 78513
 78514
 78515
 78516
 78517
 78518
 78519
 78520
 78521
 78522
 78523
 78524
 78525
 78526
 78527
 78528
 78529
 78530
 78531
 78532
 78533
 78534
 78535
 78536
 78537
 78538
 78539
 78540
 78541
 78542
 78543
 78544
 78545
 78546
 78547
 78548
 78549
 78550
 78551
 78552
 78553
 78554
 78555
 78556
 78557
 78558
 78559
 78560
 78561
 78562
 78563
 78564
 78565
 78566
 78567
 78568
 78569
 78570
 78571
 78572
 78573
 78574
 78575
 78576
 78577
 78578
 78579
 78580
 78581
 78582
 78583
 78584
 78585
 78586
 78587
 78588
 78589
 78590
 78591
 78592
 78593
 78594
 78595
 78596
 78597
 78598
 78599
 78600
 78601
 78602
 78603
 78604
 78605
 78606
 78607
 78608
 78609
 78610
 78611
 78612
 78613
 78614
 78615
 78616
 78617
 78618
 78619
 78620
 78621
 78622
 78623
 78624
 78625
 78626
 78627
 78628
 78629
 78630
 78631
 78632
 78633
 78634
 78635
 78636
 78637
 78638
 78639
 78640
 78641
 78642
 78643
 78644
 78645
 78646
 78647
 78648
 78649
 78650
 78651
 78652
 78653
 78654
 78655
 78656
 78657
 78658
 78659
 78660
 78661
 78662
 78663
 78664
 78665
 78666
 78667
 78668
 78669
 78670
 78671
 78672
 78673
 78674
 78675
 78676
 78677
 78678
 78679
 78680
 78681
 78682
 78683
 78684
 78685
 78686
 78687
 78688
 78689
 78690
 78691
 78692
 78693
 78694
 78695
 78696
 78697
 78698
 78699
 78700
 78701
 78702
 78703
 78704
 78705
 78706
 78707
 78708
 78709
 78710
 78711
 78712
 78713
 78714
 78715
 78716
 78717
 78718
 78719
 78720
 78721
 78722
 78723
 78724
 78725
 78726
 78727
 78728
 78729
 78730
 78731
 78732
 78733
 78734
 78735
 78736
 78737
 78738
 78739
 78740
 78741
 78742
 78743
 78744
 78745
 78746
 78747
 78748
 78749
 78750
 78751
 78752
 78753
 78754
 78755
 78756
 78757
 78758
 78759
 78760
 78761
 78762
 78763
 78764
 78765
 78766
 78767
 78768
 78769
 78770
 78771
 78772
 78773
 78774
 78775
 78776
 78777
 78778
 78779
 78780
 78781
 78782
 78783
 78784
 78785
 78786
 78787
 78788
 78789
 78790
 78791
 78792
 78793
 78794
 78795
 78796
 78797
 78798
 78799
 78800
 78801
 78802
 78803
 78804
 78805
 78806
 78807
 78808
 78809
 78810
 78811
 78812
 78813
 78814
 78815
 78816
 78817
 78818
 78819
 78820
 78821
 78822
 78823
 78824
 78825
 78826
 78827
 78828
 78829
 78830
 78831
 78832
 78833
 78834
 78835
 78836
 78837
 78838
 78839
 78840
 78841
 78842
 78843
 78844
 78845
 78846
 78847
 78848
 78849
 78850
 78851
 78852
 78853
 78854
 78855
 78856
 78857
 78858
 78859
 78860
 78861
 78862
 78863
 78864
 78865
 78866
 78867
 78868
 78869
 78870
 78871
 78872
 78873
 78874
 78875
 78876
 78877
 78878
 78879
 78880
 78881
 78882
 78883
 78884
 78885
 78886
 78887
 78888
 78889
 78890
 78891
 78892
 78893
 78894
 78895
 78896
 78897
 78898
 78899
 78900
 78901
 78902
 78903
 78904
 78905
 78906
 78907
 78908
 78909
 78910
 78911
 78912
 78913
 78914
 78915
 78916
 78917
 78918
 78919
 78920
 78921
 78922
 78923
 78924
 78925
 78926
 78927
 78928
 78929
 78930
 78931
 78932
 78933
 78934
 78935
 78936
 78937
 78938
 78939
 78940
 78941
 78942
 78943
 78944
 78945
 78946
 78947
 78948
 78949
 78950
 78951
 78952
 78953
 78954
 78955
 78956
 78957
 78958
 78959
 78960
 78961
 78962
 78963
 78964
 78965
 78966
 78967
 78968
 78969
 78970
 78971
 78972
 78973
 78974
 78975
 78976
 78977
 78978
 78979
 78980
 78981
 78982
 78983
 78984
 78985
 78986
 78987
 78988
 78989
 78990
 78991
 78992
 78993
 78994
 78995
 78996
 78997
 78998
 78999
 79000
 79001
 79002
 79003
 79004
 79005
 79006
 79007
 79008
 79009
 79010
 79011
 79012
 79013
 79014
 79015
 79016
 79017
 79018
 79019
 79020
 79021
 79022
 79023
 79024
 79025
 79026
 79027
 79028
 79029
 79030
 79031
 79032
 79033
 79034
 79035
 79036
 79037
 79038
 79039
 79040
 79041
 79042
 79043
 79044
 79045
 79046
 79047
 79048
 79049
 79050
 79051
 79052
 79053
 79054
 79055
 79056
 79057
 79058
 79059
 79060
 79061
 79062
 79063
 79064
 79065
 79066
 79067
 79068
 79069
 79070
 79071
 79072
 79073
 79074
 79075
 79076
 79077
 79078
 79079
 79080
 79081
 79082
 79083
 79084
 79085
 79086
 79087
 79088
 79089
 79090
 79091
 79092
 79093
 79094
 79095
 79096
 79097
 79098
 79099
 79100
 79101
 79102
 79103
 79104
 79105
 79106
 79107
 79108
 79109
 79110
 79111
 79112
 79113
 79114
 79115
 79116
 79117
 79118
 79119
 79120
 79121
 79122
 79123
 79124
 79125
 79126
 79127
 79128
 79129
 79130
 79131
 79132
 79133
 79134
 79135
 79136
 79137
 79138
 79139
 79140
 79141
 79142
 79143
 79144
 79145
 79146
 79147
 79148
 79149
 79150
 79151
 79152
 79153
 79154
 79155
 79156
 79157
 79158
 79159
 79160
 79161
 79162
 79163
 79164
 79165
 79166
 79167
 79168
 79169
 79170
 79171
 79172
 79173
 79174
 79175
 79176
 79177
 79178
 79179
 79180
 79181
 79182
 79183
 79184
 79185
 79186
 79187
 79188
 79189
 79190
 79191
 79192
 79193
 79194
 79195
 79196
 79197
 79198
 79199
 79200
 79201
 79202
 79203
 79204
 79205
 79206
 79207
 79208
 79209
 79210
 79211
 79212
 79213
 79214
 79215
 79216
 79217
 79218
 79219
 79220
 79221
 79222
 79223
 79224
 79225
 79226
 79227
 79228
 79229
 79230
 79231
 79232
 79233
 79234
 79235
 79236
 79237
 79238
 79239
 79240
 79241
 79242
 79243
 79244
 79245
 79246
 79247
 79248
 79249
 79250
 79251
 79252
 79253
 79254
 79255
 79256
 79257
 79258
 79259
 79260
 79261
 79262
 79263
 79264
 79265
 79266
 79267
 79268
 79269
 79270
 79271
 79272
 79273
 79274
 79275
 79276
 79277
 79278
 79279
 79280
 79281
 79282
 79283
 79284
 79285
 79286
 79287
 79288
 79289
 79290
 79291
 79292
 79293
 79294
 79295
 79296
 79297
 79298
 79299
 79300
 79301
 79302
 79303
 79304
 79305
 79306
 79307
 79308
 79309
 79310
 79311
 79312
 79313
 79314
 79315
 79316
 79317
 79318
 79319
 79320
 79321
 79322
 79323
 79324
 79325
 79326
 79327
 79328
 79329
 79330
 79331
 79332
 79333
 79334
 79335
 79336
 79337
 79338
 79339
 79340
 79341
 79342
 79343
 79344
 79345
 79346
 79347
 79348
 79349
 79350
 79351
 79352
 79353
 79354
 79355
 79356
 79357
 79358
 79359
 79360
 79361
 79362
 79363
 79364
 79365
 79366
 79367
 79368
 79369
 79370
 79371
 79372
 79373
 79374
 79375
 79376
 79377
 79378
 79379
 79380
 79381
 79382
 79383
 79384
 79385
 79386
 79387
 79388
 79389
 79390
 79391
 79392
 79393
 79394
 79395
 79396
 79397
 79398
 79399
 79400
 79401
 79402
 79403
 79404
 79405
 79406
 79407
 79408
 79409
 79410
 79411
 79412
 79413
 79414
 79415
 79416
 79417
 79418
 79419
 79420
 79421
 79422
 79423
 79424
 79425
 79426
 79427
 79428
 79429
 79430
 79431
 79432
 79433
 79434
 79435
 79436
 79437
 79438
 79439
 79440
 79441
 79442
 79443
 79444
 79445
 79446
 79447
 79448
 79449
 79450
 79451
 79452
 79453
 79454
 79455
 79456
 79457
 79458
 79459
 79460
 79461
 79462
 79463
 79464
 79465
 79466
 79467
 79468
 79469
 79470
 79471
 79472
 79473
 79474
 79475
 79476
 79477
 79478
 79479
 79480
 79481
 79482
 79483
 79484
 79485
 79486
 79487
 79488
 79489
 79490
 79491
 79492
 79493
 79494
 79495
 79496
 79497
 79498
 79499
 79500
 79501
 79502
 79503
 79504
 79505
 79506
 79507
 79508
 79509
 79510
 79511
 79512
 79513
 79514
 79515
 79516
 79517
 79518
 79519
 79520
 79521
 79522
 79523
 79524
 79525
 79526
 79527
 79528
 79529
 79530
 79531
 79532
 79533
 79534
 79535
 79536
 79537
 79538
 79539
 79540
 79541
 79542
 79543
 79544
 79545
 79546
 79547
 79548
 79549
 79550
 79551
 79552
 79553
 79554
 79555
 79556
 79557
 79558
 79559
 79560
 79561
 79562
 79563
 79564
 79565
 79566
 79567
 79568
 79569
 79570
 79571
 79572
 79573
 79574
 79575
 79576
 79577
 79578
 79579
 79580
 79581
 79582
 79583
 79584
 79585
 79586
 79587
 79588
 79589
 79590
 79591
 79592
 79593
 79594
 79595
 79596
 79597
 79598
 79599
 79600
 79601
 79602
 79603
 79604
 79605
 79606
 79607
 79608
 79609
 79610
 79611
 79612
 79613
 79614
 79615
 79616
 79617
 79618
 79619
 79620
 79621
 79622
 79623
 79624
 79625
 79626
 79627
 79628
 79629
 79630
 79631
 79632
 79633
 79634
 79635
 79636
 79637
 79638
 79639
 79640
 79641
 79642
 79643
 79644
 79645
 79646
 79647
 79648
 79649
 79650
 79651
 79652
 79653
 79654
 79655
 79656
 79657
 79658
 79659
 79660
 79661
 79662
 79663
 79664
 79665
 79666
 79667
 79668
 79669
 79670
 79671
 79672
 79673
 79674
 79675
 79676
 79677
 79678
 79679
 79680
 79681
 79682
 79683
 79684
 79685
 79686
 79687
 79688
 79689
 79690
 79691
 79692
 79693
 79694
 79695
 79696
 79697
 79698
 79699
 79700
 79701
 79702
 79703
 79704
 79705
 79706
 79707
 79708
 79709
 79710
 79711
 79712
 79713
 79714
 79715
 79716
 79717
 79718
 79719
 79720
 79721
 79722
 79723
 79724
 79725
 79726
 79727
 79728
 79729
 79730
 79731
 79732
 79733
 79734
 79735
 79736
 79737
 79738
 79739
 79740
 79741
 79742
 79743
 79744
 79745
 79746
 79747
 79748
 79749
 79750
 79751
 79752
 79753
 79754
 79755
 79756
 79757
 79758
 79759
 79760
 79761
 79762
 79763
 79764
 79765
 79766
 79767
 79768
 79769
 79770
 79771
 79772
 79773
 79774
 79775
 79776
 79777
 79778
 79779
 79780
 79781
 79782
 79783
 79784
 79785
 79786
 79787
 79788
 79789
 79790
 79791
 79792
 79793
 79794
 79795
 79796
 79797
 79798
 79799
 79800
 79801
 79802
 79803
 79804
 79805
 79806
 79807
 79808
 79809
 79810
 79811
 79812
 79813
 79814
 79815
 79816
 79817
 79818
 79819
 79820
 79821
 79822
 79823
 79824
 79825
 79826
 79827
 79828
 79829
 79830
 79831
 79832
 79833
 79834
 79835
 79836
 79837
 79838
 79839
 79840
 79841
 79842
 79843
 79844
 79845
 79846
 79847
 79848
 79849
 79850
 79851
 79852
 79853
 79854
 79855
 79856
 79857
 79858
 79859
 79860
 79861
 79862
 79863
 79864
 79865
 79866
 79867
 79868
 79869
 79870
 79871
 79872
 79873
 79874
 79875
 79876
 79877
 79878
 79879
 79880
 79881
 79882
 79883
 79884
 79885
 79886
 79887
 79888
 79889
 79890
 79891
 79892
 79893
 79894
 79895
 79896
 79897
 79898
 79899
 79900
 79901
 79902
 79903
 79904
 79905
 79906
 79907
 79908
 79909
 79910
 79911
 79912
 79913
 79914
 79915
 79916
 79917
 79918
 79919
 79920
 79921
 79922
 79923
 79924
 79925
 79926
 79927
 79928
 79929
 79930
 79931
 79932
 79933
 79934
 79935
 79936
 79937
 79938
 79939
 79940
 79941
 79942
 79943
 79944
 79945
 79946
 79947
 79948
 79949
 79950
 79951
 79952
 79953
 79954
 79955
 79956
 79957
 79958
 79959
 79960
 79961
 79962
 79963
 79964
 79965
 79966
 79967
 79968
 79969
 79970
 79971
 79972
 79973
 79974
 79975
 79976
 79977
 79978
 79979
 79980
 79981
 79982
 79983
 79984
 79985
 79986
 79987
 79988
 79989
 79990
 79991
 79992
 79993
 79994
 79995
 79996
 79997
 79998
 79999
 80000
 80001
 80002
 80003
 80004
 80005
 80006
 80007
 80008
 80009
 80010
 80011
 80012
 80013
 80014
 80015
 80016
 80017
 80018
 80019
 80020
 80021
 80022
 80023
 80024
 80025
 80026
 80027
 80028
 80029
 80030
 80031
 80032
 80033
 80034
 80035
 80036
 80037
 80038
 80039
 80040
 80041
 80042
 80043
 80044
 80045
 80046
 80047
 80048
 80049
 80050
 80051
 80052
 80053
 80054
 80055
 80056
 80057
 80058
 80059
 80060
 80061
 80062
 80063
 80064
 80065
 80066
 80067
 80068
 80069
 80070
 80071
 80072
 80073
 80074
 80075
 80076
 80077
 80078
 80079
 80080
 80081
 80082
 80083
 80084
 80085
 80086
 80087
 80088
 80089
 80090
 80091
 80092
 80093
 80094
 80095
 80096
 80097
 80098
 80099
 80100
 80101
 80102
 80103
 80104
 80105
 80106
 80107
 80108
 80109
 80110
 80111
 80112
 80113
 80114
 80115
 80116
 80117
 80118
 80119
 80120
 80121
 80122
 80123
 80124
 80125
 80126
 80127
 80128
 80129
 80130
 80131
 80132
 80133
 80134
 80135
 80136
 80137
 80138
 80139
 80140
 80141
 80142
 80143
 80144
 80145
 80146
 80147
 80148
 80149
 80150
 80151
 80152
 80153
 80154
 80155
 80156
 80157
 80158
 80159
 80160
 80161
 80162
 80163
 80164
 80165
 80166
 80167
 80168
 80169
 80170
 80171
 80172
 80173
 80174
 80175
 80176
 80177
 80178
 80179
 80180
 80181
 80182
 80183
 80184
 80185
 80186
 80187
 80188
 80189
 80190
 80191
 80192
 80193
 80194
 80195
 80196
 80197
 80198
 80199
 80200
 80201
 80202
 80203
 80204
 80205
 80206
 80207
 80208
 80209
 80210
 80211
 80212
 80213
 80214
 80215
 80216
 80217
 80218
 80219
 80220
 80221
 80222
 80223
 80224
 80225
 80226
 80227
 80228
 80229
 80230
 80231
 80232
 80233
 80234
 80235
 80236
 80237
 80238
 80239
 80240
 80241
 80242
 80243
 80244
 80245
 80246
 80247
 80248
 80249
 80250
 80251
 80252
 80253
 80254
 80255
 80256
 80257
 80258
 80259
 80260
 80261
 80262
 80263
 80264
 80265
 80266
 80267
 80268
 80269
 80270
 80271
 80272
 80273
 80274
 80275
 80276
 80277
 80278
 80279
 80280
 80281
 80282
 80283
 80284
 80285
 80286
 80287
 80288
 80289
 80290
 80291
 80292
 80293
 80294
 80295
 80296
 80297
 80298
 80299
 80300
 80301
 80302
 80303
 80304
 80305
 80306
 80307
 80308
 80309
 80310
 80311
 80312
 80313
 80314
 80315
 80316
 80317
 80318
 80319
 80320
 80321
 80322
 80323
 80324
 80325
 80326
 80327
 80328
 80329
 80330
 80331
 80332
 80333
 80334
 80335
 80336
 80337
 80338
 80339
 80340
 80341
 80342
 80343
 80344
 80345
 80346
 80347
 80348
 80349
 80350
 80351
 80352
 80353
 80354
 80355
 80356
 80357
 80358
 80359
 80360
 80361
 80362
 80363
 80364
 80365
 80366
 80367
 80368
 80369
 80370
 80371
 80372
 80373
 80374
 80375
 80376
 80377
 80378
 80379
 80380
 80381
 80382
 80383
 80384
 80385
 80386
 80387
 80388
 80389
 80390
 80391
 80392
 80393
 80394
 80395
 80396
 80397
 80398
 80399
 80400
 80401
 80402
 80403
 80404
 80405
 80406
 80407
 80408
 80409
 80410
 80411
 80412
 80413
 80414
 80415
 80416
 80417
 80418
 80419
 80420
 80421
 80422
 80423
 80424
 80425
 80426
 80427
 80428
 80429
 80430
 80431
 80432
 80433
 80434
 80435
 80436
 80437
 80438
 80439
 80440
 80441
 80442
 80443
 80444
 80445
 80446
 80447
 80448
 80449
 80450
 80451
 80452
 80453
 80454
 80455
 80456
 80457
 80458
 80459
 80460
 80461
 80462
 80463
 80464
 80465
 80466
 80467
 80468
 80469
 80470
 80471
 80472
 80473
 80474
 80475
 80476
 80477
 80478
 80479
 80480
 80481
 80482
 80483
 80484
 80485
 80486
 80487
 80488
 80489
 80490
 80491
 80492
 80493
 80494
 80495
 80496
 80497
 80498
 80499
 80500
 80501
 80502
 80503
 80504
 80505
 80506
 80507
 80508
 80509
 80510
 80511
 80512
 80513
 80514
 80515
 80516
 80517
 80518
 80519
 80520
 80521
 80522
 80523
 80524
 80525
 80526
 80527
 80528
 80529
 80530
 80531
 80532
 80533
 80534
 80535
 80536
 80537
 80538
 80539
 80540
 80541
 80542
 80543
 80544
 80545
 80546
 80547
 80548
 80549
 80550
 80551
 80552
 80553
 80554
 80555
 80556
 80557
 80558
 80559
 80560
 80561
 80562
 80563
 80564
 80565
 80566
 80567
 80568
 80569
 80570
 80571
 80572
 80573
 80574
 80575
 80576
 80577
 80578
 80579
 80580
 80581
 80582
 80583
 80584
 80585
 80586
 80587
 80588
 80589
 80590
 80591
 80592
 80593
 80594
 80595
 80596
 80597
 80598
 80599
 80600
 80601
 80602
 80603
 80604
 80605
 80606
 80607
 80608
 80609
 80610
 80611
 80612
 80613
 80614
 80615
 80616
 80617
 80618
 80619
 80620
 80621
 80622
 80623
 80624
 80625
 80626
 80627
 80628
 80629
 80630
 80631
 80632
 80633
 80634
 80635
 80636
 80637
 80638
 80639
 80640
 80641
 80642
 80643
 80644
 80645
 80646
 80647
 80648
 80649
 80650
 80651
 80652
 80653
 80654
 80655
 80656
 80657
 80658
 80659
 80660
 80661
 80662
 80663
 80664
 80665
 80666
 80667
 80668
 80669
 80670
 80671
 80672
 80673
 80674
 80675
 80676
 80677
 80678
 80679
 80680
 80681
 80682
 80683
 80684
 80685
 80686
 80687
 80688
 80689
 80690
 80691
 80692
 80693
 80694
 80695
 80696
 80697
 80698
 80699
 80700
 80701
 80702
 80703
 80704
 80705
 80706
 80707
 80708
 80709
 80710
 80711
 80712
 80713
 80714
 80715
 80716
 80717
 80718
 80719
 80720
 80721
 80722
 80723
 80724
 80725
 80726
 80727
 80728
 80729
 80730
 80731
 80732
 80733
 80734
 80735
 80736
 80737
 80738
 80739
 80740
 80741
 80742
 80743
 80744
 80745
 80746
 80747
 80748
 80749
 80750
 80751
 80752
 80753
 80754
 80755
 80756
 80757
 80758
 80759
 80760
 80761
 80762
 80763
 80764
 80765
 80766
 80767
 80768
 80769
 80770
 80771
 80772
 80773
 80774
 80775
 80776
 80777
 80778
 80779
 80780
 80781
 80782
 80783
 80784
 80785
 80786
 80787
 80788
 80789
 80790
 80791
 80792
 80793
 80794
 80795
 80796
 80797
 80798
 80799
 80800
 80801
 80802
 80803
 80804
 80805
 80806
 80807
 80808
 80809
 80810
 80811
 80812
 80813
 80814
 80815
 80816
 80817
 80818
 80819
 80820
 80821
 80822
 80823
 80824
 80825
 80826
 80827
 80828
 80829
 80830
 80831
 80832
 80833
 80834
 80835
 80836
 80837
 80838
 80839
 80840
 80841
 80842
 80843
 80844
 80845
 80846
 80847
 80848
 80849
 80850
 80851
 80852
 80853
 80854
 80855
 80856
 80857
 80858
 80859
 80860
 80861
 80862
 80863
 80864
 80865
 80866
 80867
 80868
 80869
 80870
 80871
 80872
 80873
 80874
 80875
 80876
 80877
 80878
 80879
 80880
 80881
 80882
 80883
 80884
 80885
 80886
 80887
 80888
 80889
 80890
 80891
 80892
 80893
 80894
 80895
 80896
 80897
 80898
 80899
 80900
 80901
 80902
 80903
 80904
 80905
 80906
 80907
 80908
 80909
 80910
 80911
 80912
 80913
 80914
 80915
 80916
 80917
 80918
 80919
 80920
 80921
 80922
 80923
 80924
 80925
 80926
 80927
 80928
 80929
 80930
 80931
 80932
 80933
 80934
 80935
 80936
 80937
 80938
 80939
 80940
 80941
 80942
 80943
 80944
 80945
 80946
 80947
 80948
 80949
 80950
 80951
 80952
 80953
 80954
 80955
 80956
 80957
 80958
 80959
 80960
 80961
 80962
 80963
 80964
 80965
 80966
 80967
 80968
 80969
 80970
 80971
 80972
 80973
 80974
 80975
 80976
 80977
 80978
 80979
 80980
 80981
 80982
 80983
 80984
 80985
 80986
 80987
 80988
 80989
 80990
 80991
 80992
 80993
 80994
 80995
 80996
 80997
 80998
 80999
 81000
 81001
 81002
 81003
 81004
 81005
 81006
 81007
 81008
 81009
 81010
 81011
 81012
 81013
 81014
 81015
 81016
 81017
 81018
 81019
 81020
 81021
 81022
 81023
 81024
 81025
 81026
 81027
 81028
 81029
 81030
 81031
 81032
 81033
 81034
 81035
 81036
 81037
 81038
 81039
 81040
 81041
 81042
 81043
 81044
 81045
 81046
 81047
 81048
 81049
 81050
 81051
 81052
 81053
 81054
 81055
 81056
 81057
 81058
 81059
 81060
 81061
 81062
 81063
 81064
 81065
 81066
 81067
 81068
 81069
 81070
 81071
 81072
 81073
 81074
 81075
 81076
 81077
 81078
 81079
 81080
 81081
 81082
 81083
 81084
 81085
 81086
 81087
 81088
 81089
 81090
 81091
 81092
 81093
 81094
 81095
 81096
 81097
 81098
 81099
 81100
 81101
 81102
 81103
 81104
 81105
 81106
 81107
 81108
 81109
 81110
 81111
 81112
 81113
 81114
 81115
 81116
 81117
 81118
 81119
 81120
 81121
 81122
 81123
 81124
 81125
 81126
 81127
 81128
 81129
 81130
 81131
 81132
 81133
 81134
 81135
 81136
 81137
 81138
 81139
 81140
 81141
 81142
 81143
 81144
 81145
 81146
 81147
 81148
 81149
 81150
 81151
 81152
 81153
 81154
 81155
 81156
 81157
 81158
 81159
 81160
 81161
 81162
 81163
 81164
 81165
 81166
 81167
 81168
 81169
 81170
 81171
 81172
 81173
 81174
 81175
 81176
 81177
 81178
 81179
 81180
 81181
 81182
 81183
 81184
 81185
 81186
 81187
 81188
 81189
 81190
 81191
 81192
 81193
 81194
 81195
 81196
 81197
 81198
 81199
 81200
 81201
 81202
 81203
 81204
 81205
 81206
 81207
 81208
 81209
 81210
 81211
 81212
 81213
 81214
 81215
 81216
 81217
 81218
 81219
 81220
 81221
 81222
 81223
 81224
 81225
 81226
 81227
 81228
 81229
 81230
 81231
 81232
 81233
 81234
 81235
 81236
 81237
 81238
 81239
 81240
 81241
 81242
 81243
 81244
 81245
 81246
 81247
 81248
 81249
 81250
 81251
 81252
 81253
 81254
 81255
 81256
 81257
 81258
 81259
 81260
 81261
 81262
 81263
 81264
 81265
 81266
 81267
 81268
 81269
 81270
 81271
 81272
 81273
 81274
 81275
 81276
 81277
 81278
 81279
 81280
 81281
 81282
 81283
 81284
 81285
 81286
 81287
 81288
 81289
 81290
 81291
 81292
 81293
 81294
 81295
 81296
 81297
 81298
 81299
 81300
 81301
 81302
 81303
 81304
 81305
 81306
 81307
 81308
 81309
 81310
 81311
 81312
 81313
 81314
 81315
 81316
 81317
 81318
 81319
 81320
 81321
 81322
 81323
 81324
 81325
 81326
 81327
 81328
 81329
 81330
 81331
 81332
 81333
 81334
 81335
 81336
 81337
 81338
 81339
 81340
 81341
 81342
 81343
 81344
 81345
 81346
 81347
 81348
 81349
 81350
 81351
 81352
 81353
 81354
 81355
 81356
 81357
 81358
 81359
 81360
 81361
 81362
 81363
 81364
 81365
 81366
 81367
 81368
 81369
 81370
 81371
 81372
 81373
 81374
 81375
 81376
 81377
 81378
 81379
 81380
 81381
 81382
 81383
 81384
 81385
 81386
 81387
 81388
 81389
 81390
 81391
 81392
 81393
 81394
 81395
 81396
 81397
 81398
 81399
 81400
 81401
 81402
 81403
 81404
 81405
 81406
 81407
 81408
 81409
 81410
 81411
 81412
 81413
 81414
 81415
 81416
 81417
 81418
 81419
 81420
 81421
 81422
 81423
 81424
 81425
 81426
 81427
 81428
 81429
 81430
 81431
 81432
 81433
 81434
 81435
 81436
 81437
 81438
 81439
 81440
 81441
 81442
 81443
 81444
 81445
 81446
 81447
 81448
 81449
 81450
 81451
 81452
 81453
 81454
 81455
 81456
 81457
 81458
 81459
 81460
 81461
 81462
 81463
 81464
 81465
 81466
 81467
 81468
 81469
 81470
 81471
 81472
 81473
 81474
 81475
 81476
 81477
 81478
 81479
 81480
 81481
 81482
 81483
 81484
 81485
 81486
 81487
 81488
 81489
 81490
 81491
 81492
 81493
 81494
 81495
 81496
 81497
 81498
 81499
 81500
 81501
 81502
 81503
 81504
 81505
 81506
 81507
 81508
 81509
 81510
 81511
 81512
 81513
 81514
 81515
 81516
 81517
 81518
 81519
 81520
 81521
 81522
 81523
 81524
 81525
 81526
 81527
 81528
 81529
 81530
 81531
 81532
 81533
 81534
 81535
 81536
 81537
 81538
 81539
 81540
 81541
 81542
 81543
 81544
 81545
 81546
 81547
 81548
 81549
 81550
 81551
 81552
 81553
 81554
 81555
 81556
 81557
 81558
 81559
 81560
 81561
 81562
 81563
 81564
 81565
 81566
 81567
 81568
 81569
 81570
 81571
 81572
 81573
 81574
 81575
 81576
 81577
 81578
 81579
 81580
 81581
 81582
 81583
 81584
 81585
 81586
 81587
 81588
 81589
 81590
 81591
 81592
 81593
 81594
 81595
 81596
 81597
 81598
 81599
 81600
 81601
 81602
 81603
 81604
 81605
 81606
 81607
 81608
 81609
 81610
 81611
 81612
 81613
 81614
 81615
 81616
 81617
 81618
 81619
 81620
 81621
 81622
 81623
 81624
 81625
 81626
 81627
 81628
 81629
 81630
 81631
 81632
 81633
 81634
 81635
 81636
 81637
 81638
 81639
 81640
 81641
 81642
 81643
 81644
 81645
 81646
 81647
 81648
 81649
 81650
 81651
 81652
 81653
 81654
 81655
 81656
 81657
 81658
 81659
 81660
 81661
 81662
 81663
 81664
 81665
 81666
 81667
 81668
 81669
 81670
 81671
 81672
 81673
 81674
 81675
 81676
 81677
 81678
 81679
 81680
 81681
 81682
 81683
 81684
 81685
 81686
 81687
 81688
 81689
 81690
 81691
 81692
 81693
 81694
 81695
 81696
 81697
 81698
 81699
 81700
 81701
 81702
 81703
 81704
 81705
 81706
 81707
 81708
 81709
 81710
 81711
 81712
 81713
 81714
 81715
 81716
 81717
 81718
 81719
 81720
 81721
 81722
 81723
 81724
 81725
 81726
 81727
 81728
 81729
 81730
 81731
 81732
 81733
 81734
 81735
 81736
 81737
 81738
 81739
 81740
 81741
 81742
 81743
 81744
 81745
 81746
 81747
 81748
 81749
 81750
 81751
 81752
 81753
 81754
 81755
 81756
 81757
 81758
 81759
 81760
 81761
 81762
 81763
 81764
 81765
 81766
 81767
 81768
 81769
 81770
 81771
 81772
 81773
 81774
 81775
 81776
 81777
 81778
 81779
 81780
 81781
 81782
 81783
 81784
 81785
 81786
 81787
 81788
 81789
 81790
 81791
 81792
 81793
 81794
 81795
 81796
 81797
 81798
 81799
 81800
 81801
 81802
 81803
 81804
 81805
 81806
 81807
 81808
 81809
 81810
 81811
 81812
 81813
 81814
 81815
 81816
 81817
 81818
 81819
 81820
 81821
 81822
 81823
 81824
 81825
 81826
 81827
 81828
 81829
 81830
 81831
 81832
 81833
 81834
 81835
 81836
 81837
 81838
 81839
 81840
 81841
 81842
 81843
 81844
 81845
 81846
 81847
 81848
 81849
 81850
 81851
 81852
 81853
 81854
 81855
 81856
 81857
 81858
 81859
 81860
 81861
 81862
 81863
 81864
 81865
 81866
 81867
 81868
 81869
 81870
 81871
 81872
 81873
 81874
 81875
 81876
 81877
 81878
 81879
 81880
 81881
 81882
 81883
 81884
 81885
 81886
 81887
 81888
 81889
 81890
 81891
 81892
 81893
 81894
 81895
 81896
 81897
 81898
 81899
 81900
 81901
 81902
 81903
 81904
 81905
 81906
 81907
 81908
 81909
 81910
 81911
 81912
 81913
 81914
 81915
 81916
 81917
 81918
 81919
 81920
 81921
 81922
 81923
 81924
 81925
 81926
 81927
 81928
 81929
 81930
 81931
 81932
 81933
 81934
 81935
 81936
 81937
 81938
 81939
 81940
 81941
 81942
 81943
 81944
 81945
 81946
 81947
 81948
 81949
 81950
 81951
 81952
 81953
 81954
 81955
 81956
 81957
 81958
 81959
 81960
 81961
 81962
 81963
 81964
 81965
 81966
 81967
 81968
 81969
 81970
 81971
 81972
 81973
 81974
 81975
 81976
 81977
 81978
 81979
 81980
 81981
 81982
 81983
 81984
 81985
 81986
 81987
 81988
 81989
 81990
 81991
 81992
 81993
 81994
 81995
 81996
 81997
 81998
 81999
 82000
 82001
 82002
 82003
 82004
 82005
 82006
 82007
 82008
 82009
 82010
 82011
 82012
 82013
 82014
 82015
 82016
 82017
 82018
 82019
 82020
 82021
 82022
 82023
 82024
 82025
 82026
 82027
 82028
 82029
 82030
 82031
 82032
 82033
 82034
 82035
 82036
 82037
 82038
 82039
 82040
 82041
 82042
 82043
 82044
 82045
 82046
 82047
 82048
 82049
 82050
 82051
 82052
 82053
 82054
 82055
 82056
 82057
 82058
 82059
 82060
 82061
 82062
 82063
 82064
 82065
 82066
 82067
 82068
 82069
 82070
 82071
 82072
 82073
 82074
 82075
 82076
 82077
 82078
 82079
 82080
 82081
 82082
 82083
 82084
 82085
 82086
 82087
 82088
 82089
 82090
 82091
 82092
 82093
 82094
 82095
 82096
 82097
 82098
 82099
 82100
 82101
 82102
 82103
 82104
 82105
 82106
 82107
 82108
 82109
 82110
 82111
 82112
 82113
 82114
 82115
 82116
 82117
 82118
 82119
 82120
 82121
 82122
 82123
 82124
 82125
 82126
 82127
 82128
 82129
 82130
 82131
 82132
 82133
 82134
 82135
 82136
 82137
 82138
 82139
 82140
 82141
 82142
 82143
 82144
 82145
 82146
 82147
 82148
 82149
 82150
 82151
 82152
 82153
 82154
 82155
 82156
 82157
 82158
 82159
 82160
 82161
 82162
 82163
 82164
 82165
 82166
 82167
 82168
 82169
 82170
 82171
 82172
 82173
 82174
 82175
 82176
 82177
 82178
 82179
 82180
 82181
 82182
 82183
 82184
 82185
 82186
 82187
 82188
 82189
 82190
 82191
 82192
 82193
 82194
 82195
 82196
 82197
 82198
 82199
 82200
 82201
 82202
 82203
 82204
 82205
 82206
 82207
 82208
 82209
 82210
 82211
 82212
 82213
 82214
 82215
 82216
 82217
 82218
 82219
 82220
 82221
 82222
 82223
 82224
 82225
 82226
 82227
 82228
 82229
 82230
 82231
 82232
 82233
 82234
 82235
 82236
 82237
 82238
 82239
 82240
 82241
 82242
 82243
 82244
 82245
 82246
 82247
 82248
 82249
 82250
 82251
 82252
 82253
 82254
 82255
 82256
 82257
 82258
 82259
 82260
 82261
 82262
 82263
 82264
 82265
 82266
 82267
 82268
 82269
 82270
 82271
 82272
 82273
 82274
 82275
 82276
 82277
 82278
 82279
 82280
 82281
 82282
 82283
 82284
 82285
 82286
 82287
 82288
 82289
 82290
 82291
 82292
 82293
 82294
 82295
 82296
 82297
 82298
 82299
 82300
 82301
 82302
 82303
 82304
 82305
 82306
 82307
 82308
 82309
 82310
 82311
 82312
 82313
 82314
 82315
 82316
 82317
 82318
 82319
 82320
 82321
 82322
 82323
 82324
 82325
 82326
 82327
 82328
 82329
 82330
 82331
 82332
 82333
 82334
 82335
 82336
 82337
 82338
 82339
 82340
 82341
 82342
 82343
 82344
 82345
 82346
 82347
 82348
 82349
 82350
 82351
 82352
 82353
 82354
 82355
 82356
 82357
 82358
 82359
 82360
 82361
 82362
 82363
 82364
 82365
 82366
 82367
 82368
 82369
 82370
 82371
 82372
 82373
 82374
 82375
 82376
 82377
 82378
 82379
 82380
 82381
 82382
 82383
 82384
 82385
 82386
 82387
 82388
 82389
 82390
 82391
 82392
 82393
 82394
 82395
 82396
 82397
 82398
 82399
 82400
 82401
 82402
 82403
 82404
 82405
 82406
 82407
 82408
 82409
 82410
 82411
 82412
 82413
 82414
 82415
 82416
 82417
 82418
 82419
 82420
 82421
 82422
 82423
 82424
 82425
 82426
 82427
 82428
 82429
 82430
 82431
 82432
 82433
 82434
 82435
 82436
 82437
 82438
 82439
 82440
 82441
 82442
 82443
 82444
 82445
 82446
 82447
 82448
 82449
 82450
 82451
 82452
 82453
 82454
 82455
 82456
 82457
 82458
 82459
 82460
 82461
 82462
 82463
 82464
 82465
 82466
 82467
 82468
 82469
 82470
 82471
 82472
 82473
 82474
 82475
 82476
 82477
 82478
 82479
 82480
 82481
 82482
 82483
 82484
 82485
 82486
 82487
 82488
 82489
 82490
 82491
 82492
 82493
 82494
 82495
 82496
 82497
 82498
 82499
 82500
 82501
 82502
 82503
 82504
 82505
 82506
 82507
 82508
 82509
 82510
 82511
 82512
 82513
 82514
 82515
 82516
 82517
 82518
 82519
 82520
 82521
 82522
 82523
 82524
 82525
 82526
 82527
 82528
 82529
 82530
 82531
 82532
 82533
 82534
 82535
 82536
 82537
 82538
 82539
 82540
 82541
 82542
 82543
 82544
 82545
 82546
 82547
 82548
 82549
 82550
 82551
 82552
 82553
 82554
 82555
 82556
 82557
 82558
 82559
 82560
 82561
 82562
 82563
 82564
 82565
 82566
 82567
 82568
 82569
 82570
 82571
 82572
 82573
 82574
 82575
 82576
 82577
 82578
 82579
 82580
 82581
 82582
 82583
 82584
 82585
 82586
 82587
 82588
 82589
 82590
 82591
 82592
 82593
 82594
 82595
 82596
 82597
 82598
 82599
 82600
 82601
 82602
 82603
 82604
 82605
 82606
 82607
 82608
 82609
 82610
 82611
 82612
 82613
 82614
 82615
 82616
 82617
 82618
 82619
 82620
 82621
 82622
 82623
 82624
 82625
 82626
 82627
 82628
 82629
 82630
 82631
 82632
 82633
 82634
 82635
 82636
 82637
 82638
 82639
 82640
 82641
 82642
 82643
 82644
 82645
 82646
 82647
 82648
 82649
 82650
 82651
 82652
 82653
 82654
 82655
 82656
 82657
 82658
 82659
 82660
 82661
 82662
 82663
 82664
 82665
 82666
 82667
 82668
 82669
 82670
 82671
 82672
 82673
 82674
 82675
 82676
 82677
 82678
 82679
 82680
 82681
 82682
 82683
 82684
 82685
 82686
 82687
 82688
 82689
 82690
 82691
 82692
 82693
 82694
 82695
 82696
 82697
 82698
 82699
 82700
 82701
 82702
 82703
 82704
 82705
 82706
 82707
 82708
 82709
 82710
 82711
 82712
 82713
 82714
 82715
 82716
 82717
 82718
 82719
 82720
 82721
 82722
 82723
 82724
 82725
 82726
 82727
 82728
 82729
 82730
 82731
 82732
 82733
 82734
 82735
 82736
 82737
 82738
 82739
 82740
 82741
 82742
 82743
 82744
 82745
 82746
 82747
 82748
 82749
 82750
 82751
 82752
 82753
 82754
 82755
 82756
 82757
 82758
 82759
 82760
 82761
 82762
 82763
 82764
 82765
 82766
 82767
 82768
 82769
 82770
 82771
 82772
 82773
 82774
 82775
 82776
 82777
 82778
 82779
 82780
 82781
 82782
 82783
 82784
 82785
 82786
 82787
 82788
 82789
 82790
 82791
 82792
 82793
 82794
 82795
 82796
 82797
 82798
 82799
 82800
 82801
 82802
 82803
 82804
 82805
 82806
 82807
 82808
 82809
 82810
 82811
 82812
 82813
 82814
 82815
 82816
 82817
 82818
 82819
 82820
 82821
 82822
 82823
 82824
 82825
 82826
 82827
 82828
 82829
 82830
 82831
 82832
 82833
 82834
 82835
 82836
 82837
 82838
 82839
 82840
 82841
 82842
 82843
 82844
 82845
 82846
 82847
 82848
 82849
 82850
 82851
 82852
 82853
 82854
 82855
 82856
 82857
 82858
 82859
 82860
 82861
 82862
 82863
 82864
 82865
 82866
 82867
 82868
 82869
 82870
 82871
 82872
 82873
 82874
 82875
 82876
 82877
 82878
 82879
 82880
 82881
 82882
 82883
 82884
 82885
 82886
 82887
 82888
 82889
 82890
 82891
 82892
 82893
 82894
 82895
 82896
 82897
 82898
 82899
 82900
 82901
 82902
 82903
 82904
 82905
 82906
 82907
 82908
 82909
 82910
 82911
 82912
 82913
 82914
 82915
 82916
 82917
 82918
 82919
 82920
 82921
 82922
 82923
 82924
 82925
 82926
 82927
 82928
 82929
 82930
 82931
 82932
 82933
 82934
 82935
 82936
 82937
 82938
 82939
 82940
 82941
 82942
 82943
 82944
 82945
 82946
 82947
 82948
 82949
 82950
 82951
 82952
 82953
 82954
 82955
 82956
 82957
 82958
 82959
 82960
 82961
 82962
 82963
 82964
 82965
 82966
 82967
 82968
 82969
 82970
 82971
 82972
 82973
 82974
 82975
 82976
 82977
 82978
 82979
 82980
 82981
 82982
 82983
 82984
 82985
 82986
 82987
 82988
 82989
 82990
 82991
 82992
 82993
 82994
 82995
 82996
 82997
 82998
 82999
 83000
 83001
 83002
 83003
 83004
 83005
 83006
 83007
 83008
 83009
 83010
 83011
 83012
 83013
 83014
 83015
 83016
 83017
 83018
 83019
 83020
 83021
 83022
 83023
 83024
 83025
 83026
 83027
 83028
 83029
 83030
 83031
 83032
 83033
 83034
 83035
 83036
 83037
 83038
 83039
 83040
 83041
 83042
 83043
 83044
 83045
 83046
 83047
 83048
 83049
 83050
 83051
 83052
 83053
 83054
 83055
 83056
 83057
 83058
 83059
 83060
 83061
 83062
 83063
 83064
 83065
 83066
 83067
 83068
 83069
 83070
 83071
 83072
 83073
 83074
 83075
 83076
 83077
 83078
 83079
 83080
 83081
 83082
 83083
 83084
 83085
 83086
 83087
 83088
 83089
 83090
 83091
 83092
 83093
 83094
 83095
 83096
 83097
 83098
 83099
 83100
 83101
 83102
 83103
 83104
 83105
 83106
 83107
 83108
 83109
 83110
 83111
 83112
 83113
 83114
 83115
 83116
 83117
 83118
 83119
 83120
 83121
 83122
 83123
 83124
 83125
 83126
 83127
 83128
 83129
 83130
 83131
 83132
 83133
 83134
 83135
 83136
 83137
 83138
 83139
 83140
 83141
 83142
 83143
 83144
 83145
 83146
 83147
 83148
 83149
 83150
 83151
 83152
 83153
 83154
 83155
 83156
 83157
 83158
 83159
 83160
 83161
 83162
 83163
 83164
 83165
 83166
 83167
 83168
 83169
 83170
 83171
 83172
 83173
 83174
 83175
 83176
 83177
 83178
 83179
 83180
 83181
 83182
 83183
 83184
 83185
 83186
 83187
 83188
 83189
 83190
 83191
 83192
 83193
 83194
 83195
 83196
 83197
 83198
 83199
 83200
 83201
 83202
 83203
 83204
 83205
 83206
 83207
 83208
 83209
 83210
 83211
 83212
 83213
 83214
 83215
 83216
 83217
 83218
 83219
 83220
 83221
 83222
 83223
 83224
 83225
 83226
 83227
 83228
 83229
 83230
 83231
 83232
 83233
 83234
 83235
 83236
 83237
 83238
 83239
 83240
 83241
 83242
 83243
 83244
 83245
 83246
 83247
 83248
 83249
 83250
 83251
 83252
 83253
 83254
 83255
 83256
 83257
 83258
 83259
 83260
 83261
 83262
 83263
 83264
 83265
 83266
 83267
 83268
 83269
 83270
 83271
 83272
 83273
 83274
 83275
 83276
 83277
 83278
 83279
 83280
 83281
 83282
 83283
 83284
 83285
 83286
 83287
 83288
 83289
 83290
 83291
 83292
 83293
 83294
 83295
 83296
 83297
 83298
 83299
 83300
 83301
 83302
 83303
 83304
 83305
 83306
 83307
 83308
 83309
 83310
 83311
 83312
 83313
 83314
 83315
 83316
 83317
 83318
 83319
 83320
 83321
 83322
 83323
 83324
 83325
 83326
 83327
 83328
 83329
 83330
 83331
 83332
 83333
 83334
 83335
 83336
 83337
 83338
 83339
 83340
 83341
 83342
 83343
 83344
 83345
 83346
 83347
 83348
 83349
 83350
 83351
 83352
 83353
 83354
 83355
 83356
 83357
 83358
 83359
 83360
 83361
 83362
 83363
 83364
 83365
 83366
 83367
 83368
 83369
 83370
 83371
 83372
 83373
 83374
 83375
 83376
 83377
 83378
 83379
 83380
 83381
 83382
 83383
 83384
 83385
 83386
 83387
 83388
 83389
 83390
 83391
 83392
 83393
 83394
 83395
 83396
 83397
 83398
 83399
 83400
 83401
 83402
 83403
 83404
 83405
 83406
 83407
 83408
 83409
 83410
 83411
 83412
 83413
 83414
 83415
 83416
 83417
 83418
 83419
 83420
 83421
 83422
 83423
 83424
 83425
 83426
 83427
 83428
 83429
 83430
 83431
 83432
 83433
 83434
 83435
 83436
 83437
 83438
 83439
 83440
 83441
 83442
 83443
 83444
 83445
 83446
 83447
 83448
 83449
 83450
 83451
 83452
 83453
 83454
 83455
 83456
 83457
 83458
 83459
 83460
 83461
 83462
 83463
 83464
 83465
 83466
 83467
 83468
 83469
 83470
 83471
 83472
 83473
 83474
 83475
 83476
 83477
 83478
 83479
 83480
 83481
 83482
 83483
 83484
 83485
 83486
 83487
 83488
 83489
 83490
 83491
 83492
 83493
 83494
 83495
 83496
 83497
 83498
 83499
 83500
 83501
 83502
 83503
 83504
 83505
 83506
 83507
 83508
 83509
 83510
 83511
 83512
 83513
 83514
 83515
 83516
 83517
 83518
 83519
 83520
 83521
 83522
 83523
 83524
 83525
 83526
 83527
 83528
 83529
 83530
 83531
 83532
 83533
 83534
 83535
 83536
 83537
 83538
 83539
 83540
 83541
 83542
 83543
 83544
 83545
 83546
 83547
 83548
 83549
 83550
 83551
 83552
 83553
 83554
 83555
 83556
 83557
 83558
 83559
 83560
 83561
 83562
 83563
 83564
 83565
 83566
 83567
 83568
 83569
 83570
 83571
 83572
 83573
 83574
 83575
 83576
 83577
 83578
 83579
 83580
 83581
 83582
 83583
 83584
 83585
 83586
 83587
 83588
 83589
 83590
 83591
 83592
 83593
 83594
 83595
 83596
 83597
 83598
 83599
 83600
 83601
 83602
 83603
 83604
 83605
 83606
 83607
 83608
 83609
 83610
 83611
 83612
 83613
 83614
 83615
 83616
 83617
 83618
 83619
 83620
 83621
 83622
 83623
 83624
 83625
 83626
 83627
 83628
 83629
 83630
 83631
 83632
 83633
 83634
 83635
 83636
 83637
 83638
 83639
 83640
 83641
 83642
 83643
 83644
 83645
 83646
 83647
 83648
 83649
 83650
 83651
 83652
 83653
 83654
 83655
 83656
 83657
 83658
 83659
 83660
 83661
 83662
 83663
 83664
 83665
 83666
 83667
 83668
 83669
 83670
 83671
 83672
 83673
 83674
 83675
 83676
 83677
 83678
 83679
 83680
 83681
 83682
 83683
 83684
 83685
 83686
 83687
 83688
 83689
 83690
 83691
 83692
 83693
 83694
 83695
 83696
 83697
 83698
 83699
 83700
 83701
 83702
 83703
 83704
 83705
 83706
 83707
 83708
 83709
 83710
 83711
 83712
 83713
 83714
 83715
 83716
 83717
 83718
 83719
 83720
 83721
 83722
 83723
 83724
 83725
 83726
 83727
 83728
 83729
 83730
 83731
 83732
 83733
 83734
 83735
 83736
 83737
 83738
 83739
 83740
 83741
 83742
 83743
 83744
 83745
 83746
 83747
 83748
 83749
 83750
 83751
 83752
 83753
 83754
 83755
 83756
 83757
 83758
 83759
 83760
 83761
 83762
 83763
 83764
 83765
 83766
 83767
 83768
 83769
 83770
 83771
 83772
 83773
 83774
 83775
 83776
 83777
 83778
 83779
 83780
 83781
 83782
 83783
 83784
 83785
 83786
 83787
 83788
 83789
 83790
 83791
 83792
 83793
 83794
 83795
 83796
 83797
 83798
 83799
 83800
 83801
 83802
 83803
 83804
 83805
 83806
 83807
 83808
 83809
 83810
 83811
 83812
 83813
 83814
 83815
 83816
 83817
 83818
 83819
 83820
 83821
 83822
 83823
 83824
 83825
 83826
 83827
 83828
 83829
 83830
 83831
 83832
 83833
 83834
 83835
 83836
 83837
 83838
 83839
 83840
 83841
 83842
 83843
 83844
 83845
 83846
 83847
 83848
 83849
 83850
 83851
 83852
 83853
 83854
 83855
 83856
 83857
 83858
 83859
 83860
 83861
 83862
 83863
 83864
 83865
 83866
 83867
 83868
 83869
 83870
 83871
 83872
 83873
 83874
 83875
 83876
 83877
 83878
 83879
 83880
 83881
 83882
 83883
 83884
 83885
 83886
 83887
 83888
 83889
 83890
 83891
 83892
 83893
 83894
 83895
 83896
 83897
 83898
 83899
 83900
 83901
 83902
 83903
 83904
 83905
 83906
 83907
 83908
 83909
 83910
 83911
 83912
 83913
 83914
 83915
 83916
 83917
 83918
 83919
 83920
 83921
 83922
 83923
 83924
 83925
 83926
 83927
 83928
 83929
 83930
 83931
 83932
 83933
 83934
 83935
 83936
 83937
 83938
 83939
 83940
 83941
 83942
 83943
 83944
 83945
 83946
 83947
 83948
 83949
 83950
 83951
 83952
 83953
 83954
 83955
 83956
 83957
 83958
 83959
 83960
 83961
 83962
 83963
 83964
 83965
 83966
 83967
 83968
 83969
 83970
 83971
 83972
 83973
 83974
 83975
 83976
 83977
 83978
 83979
 83980
 83981
 83982
 83983
 83984
 83985
 83986
 83987
 83988
 83989
 83990
 83991
 83992
 83993
 83994
 83995
 83996
 83997
 83998
 83999
 84000
 84001
 84002
 84003
 84004
 84005
 84006
 84007
 84008
 84009
 84010
 84011
 84012
 84013
 84014
 84015
 84016
 84017
 84018
 84019
 84020
 84021
 84022
 84023
 84024
 84025
 84026
 84027
 84028
 84029
 84030
 84031
 84032
 84033
 84034
 84035
 84036
 84037
 84038
 84039
 84040
 84041
 84042
 84043
 84044
 84045
 84046
 84047
 84048
 84049
 84050
 84051
 84052
 84053
 84054
 84055
 84056
 84057
 84058
 84059
 84060
 84061
 84062
 84063
 84064
 84065
 84066
 84067
 84068
 84069
 84070
 84071
 84072
 84073
 84074
 84075
 84076
 84077
 84078
 84079
 84080
 84081
 84082
 84083
 84084
 84085
 84086
 84087
 84088
 84089
 84090
 84091
 84092
 84093
 84094
 84095
 84096
 84097
 84098
 84099
 84100
 84101
 84102
 84103
 84104
 84105
 84106
 84107
 84108
 84109
 84110
 84111
 84112
 84113
 84114
 84115
 84116
 84117
 84118
 84119
 84120
 84121
 84122
 84123
 84124
 84125
 84126
 84127
 84128
 84129
 84130
 84131
 84132
 84133
 84134
 84135
 84136
 84137
 84138
 84139
 84140
 84141
 84142
 84143
 84144
 84145
 84146
 84147
 84148
 84149
 84150
 84151
 84152
 84153
 84154
 84155
 84156
 84157
 84158
 84159
 84160
 84161
 84162
 84163
 84164
 84165
 84166
 84167
 84168
 84169
 84170
 84171
 84172
 84173
 84174
 84175
 84176
 84177
 84178
 84179
 84180
 84181
 84182
 84183
 84184
 84185
 84186
 84187
 84188
 84189
 84190
 84191
 84192
 84193
 84194
 84195
 84196
 84197
 84198
 84199
 84200
 84201
 84202
 84203
 84204
 84205
 84206
 84207
 84208
 84209
 84210
 84211
 84212
 84213
 84214
 84215
 84216
 84217
 84218
 84219
 84220
 84221
 84222
 84223
 84224
 84225
 84226
 84227
 84228
 84229
 84230
 84231
 84232
 84233
 84234
 84235
 84236
 84237
 84238
 84239
 84240
 84241
 84242
 84243
 84244
 84245
 84246
 84247
 84248
 84249
 84250
 84251
 84252
 84253
 84254
 84255
 84256
 84257
 84258
 84259
 84260
 84261
 84262
 84263
 84264
 84265
 84266
 84267
 84268
 84269
 84270
 84271
 84272
 84273
 84274
 84275
 84276
 84277
 84278
 84279
 84280
 84281
 84282
 84283
 84284
 84285
 84286
 84287
 84288
 84289
 84290
 84291
 84292
 84293
 84294
 84295
 84296
 84297
 84298
 84299
 84300
 84301
 84302
 84303
 84304
 84305
 84306
 84307
 84308
 84309
 84310
 84311
 84312
 84313
 84314
 84315
 84316
 84317
 84318
 84319
 84320
 84321
 84322
 84323
 84324
 84325
 84326
 84327
 84328
 84329
 84330
 84331
 84332
 84333
 84334
 84335
 84336
 84337
 84338
 84339
 84340
 84341
 84342
 84343
 84344
 84345
 84346
 84347
 84348
 84349
 84350
 84351
 84352
 84353
 84354
 84355
 84356
 84357
 84358
 84359
 84360
 84361
 84362
 84363
 84364
 84365
 84366
 84367
 84368
 84369
 84370
 84371
 84372
 84373
 84374
 84375
 84376
 84377
 84378
 84379
 84380
 84381
 84382
 84383
 84384
 84385
 84386
 84387
 84388
 84389
 84390
 84391
 84392
 84393
 84394
 84395
 84396
 84397
 84398
 84399
 84400
 84401
 84402
 84403
 84404
 84405
 84406
 84407
 84408
 84409
 84410
 84411
 84412
 84413
 84414
 84415
 84416
 84417
 84418
 84419
 84420
 84421
 84422
 84423
 84424
 84425
 84426
 84427
 84428
 84429
 84430
 84431
 84432
 84433
 84434
 84435
 84436
 84437
 84438
 84439
 84440
 84441
 84442
 84443
 84444
 84445
 84446
 84447
 84448
 84449
 84450
 84451
 84452
 84453
 84454
 84455
 84456
 84457
 84458
 84459
 84460
 84461
 84462
 84463
 84464
 84465
 84466
 84467
 84468
 84469
 84470
 84471
 84472
 84473
 84474
 84475
 84476
 84477
 84478
 84479
 84480
 84481
 84482
 84483
 84484
 84485
 84486
 84487
 84488
 84489
 84490
 84491
 84492
 84493
 84494
 84495
 84496
 84497
 84498
 84499
 84500
 84501
 84502
 84503
 84504
 84505
 84506
 84507
 84508
 84509
 84510
 84511
 84512
 84513
 84514
 84515
 84516
 84517
 84518
 84519
 84520
 84521
 84522
 84523
 84524
 84525
 84526
 84527
 84528
 84529
 84530
 84531
 84532
 84533
 84534
 84535
 84536
 84537
 84538
 84539
 84540
 84541
 84542
 84543
 84544
 84545
 84546
 84547
 84548
 84549
 84550
 84551
 84552
 84553
 84554
 84555
 84556
 84557
 84558
 84559
 84560
 84561
 84562
 84563
 84564
 84565
 84566
 84567
 84568
 84569
 84570
 84571
 84572
 84573
 84574
 84575
 84576
 84577
 84578
 84579
 84580
 84581
 84582
 84583
 84584
 84585
 84586
 84587
 84588
 84589
 84590
 84591
 84592
 84593
 84594
 84595
 84596
 84597
 84598
 84599
 84600
 84601
 84602
 84603
 84604
 84605
 84606
 84607
 84608
 84609
 84610
 84611
 84612
 84613
 84614
 84615
 84616
 84617
 84618
 84619
 84620
 84621
 84622
 84623
 84624
 84625
 84626
 84627
 84628
 84629
 84630
 84631
 84632
 84633
 84634
 84635
 84636
 84637
 84638
 84639
 84640
 84641
 84642
 84643
 84644
 84645
 84646
 84647
 84648
 84649
 84650
 84651
 84652
 84653
 84654
 84655
 84656
 84657
 84658
 84659
 84660
 84661
 84662
 84663
 84664
 84665
 84666
 84667
 84668
 84669
 84670
 84671
 84672
 84673
 84674
 84675
 84676
 84677
 84678
 84679
 84680
 84681
 84682
 84683
 84684
 84685
 84686
 84687
 84688
 84689
 84690
 84691
 84692
 84693
 84694
 84695
 84696
 84697
 84698
 84699
 84700
 84701
 84702
 84703
 84704
 84705
 84706
 84707
 84708
 84709
 84710
 84711
 84712
 84713
 84714
 84715
 84716
 84717
 84718
 84719
 84720
 84721
 84722
 84723
 84724
 84725
 84726
 84727
 84728
 84729
 84730
 84731
 84732
 84733
 84734
 84735
 84736
 84737
 84738
 84739
 84740
 84741
 84742
 84743
 84744
 84745
 84746
 84747
 84748
 84749
 84750
 84751
 84752
 84753
 84754
 84755
 84756
 84757
 84758
 84759
 84760
 84761
 84762
 84763
 84764
 84765
 84766
 84767
 84768
 84769
 84770
 84771
 84772
 84773
 84774
 84775
 84776
 84777
 84778
 84779
 84780
 84781
 84782
 84783
 84784
 84785
 84786
 84787
 84788
 84789
 84790
 84791
 84792
 84793
 84794
 84795
 84796
 84797
 84798
 84799
 84800
 84801
 84802
 84803
 84804
 84805
 84806
 84807
 84808
 84809
 84810
 84811
 84812
 84813
 84814
 84815
 84816
 84817
 84818
 84819
 84820
 84821
 84822
 84823
 84824
 84825
 84826
 84827
 84828
 84829
 84830
 84831
 84832
 84833
 84834
 84835
 84836
 84837
 84838
 84839
 84840
 84841
 84842
 84843
 84844
 84845
 84846
 84847
 84848
 84849
 84850
 84851
 84852
 84853
 84854
 84855
 84856
 84857
 84858
 84859
 84860
 84861
 84862
 84863
 84864
 84865
 84866
 84867
 84868
 84869
 84870
 84871
 84872
 84873
 84874
 84875
 84876
 84877
 84878
 84879
 84880
 84881
 84882
 84883
 84884
 84885
 84886
 84887
 84888
 84889
 84890
 84891
 84892
 84893
 84894
 84895
 84896
 84897
 84898
 84899
 84900
 84901
 84902
 84903
 84904
 84905
 84906
 84907
 84908
 84909
 84910
 84911
 84912
 84913
 84914
 84915
 84916
 84917
 84918
 84919
 84920
 84921
 84922
 84923
 84924
 84925
 84926
 84927
 84928
 84929
 84930
 84931
 84932
 84933
 84934
 84935
 84936
 84937
 84938
 84939
 84940
 84941
 84942
 84943
 84944
 84945
 84946
 84947
 84948
 84949
 84950
 84951
 84952
 84953
 84954
 84955
 84956
 84957
 84958
 84959
 84960
 84961
 84962
 84963
 84964
 84965
 84966
 84967
 84968
 84969
 84970
 84971
 84972
 84973
 84974
 84975
 84976
 84977
 84978
 84979
 84980
 84981
 84982
 84983
 84984
 84985
 84986
 84987
 84988
 84989
 84990
 84991
 84992
 84993
 84994
 84995
 84996
 84997
 84998
 84999
 85000
 85001
 85002
 85003
 85004
 85005
 85006
 85007
 85008
 85009
 85010
 85011
 85012
 85013
 85014
 85015
 85016
 85017
 85018
 85019
 85020
 85021
 85022
 85023
 85024
 85025
 85026
 85027
 85028
 85029
 85030
 85031
 85032
 85033
 85034
 85035
 85036
 85037
 85038
 85039
 85040
 85041
 85042
 85043
 85044
 85045
 85046
 85047
 85048
 85049
 85050
 85051
 85052
 85053
 85054
 85055
 85056
 85057
 85058
 85059
 85060
 85061
 85062
 85063
 85064
 85065
 85066
 85067
 85068
 85069
 85070
 85071
 85072
 85073
 85074
 85075
 85076
 85077
 85078
 85079
 85080
 85081
 85082
 85083
 85084
 85085
 85086
 85087
 85088
 85089
 85090
 85091
 85092
 85093
 85094
 85095
 85096
 85097
 85098
 85099
 85100
 85101
 85102
 85103
 85104
 85105
 85106
 85107
 85108
 85109
 85110
 85111
 85112
 85113
 85114
 85115
 85116
 85117
 85118
 85119
 85120
 85121
 85122
 85123
 85124
 85125
 85126
 85127
 85128
 85129
 85130
 85131
 85132
 85133
 85134
 85135
 85136
 85137
 85138
 85139
 85140
 85141
 85142
 85143
 85144
 85145
 85146
 85147
 85148
 85149
 85150
 85151
 85152
 85153
 85154
 85155
 85156
 85157
 85158
 85159
 85160
 85161
 85162
 85163
 85164
 85165
 85166
 85167
 85168
 85169
 85170
 85171
 85172
 85173
 85174
 85175
 85176
 85177
 85178
 85179
 85180
 85181
 85182
 85183
 85184
 85185
 85186
 85187
 85188
 85189
 85190
 85191
 85192
 85193
 85194
 85195
 85196
 85197
 85198
 85199
 85200
 85201
 85202
 85203
 85204
 85205
 85206
 85207
 85208
 85209
 85210
 85211
 85212
 85213
 85214
 85215
 85216
 85217
 85218
 85219
 85220
 85221
 85222
 85223
 85224
 85225
 85226
 85227
 85228
 85229
 85230
 85231
 85232
 85233
 85234
 85235
 85236
 85237
 85238
 85239
 85240
 85241
 85242
 85243
 85244
 85245
 85246
 85247
 85248
 85249
 85250
 85251
 85252
 85253
 85254
 85255
 85256
 85257
 85258
 85259
 85260
 85261
 85262
 85263
 85264
 85265
 85266
 85267
 85268
 85269
 85270
 85271
 85272
 85273
 85274
 85275
 85276
 85277
 85278
 85279
 85280
 85281
 85282
 85283
 85284
 85285
 85286
 85287
 85288
 85289
 85290
 85291
 85292
 85293
 85294
 85295
 85296
 85297
 85298
 85299
 85300
 85301
 85302
 85303
 85304
 85305
 85306
 85307
 85308
 85309
 85310
 85311
 85312
 85313
 85314
 85315
 85316
 85317
 85318
 85319
 85320
 85321
 85322
 85323
 85324
 85325
 85326
 85327
 85328
 85329
 85330
 85331
 85332
 85333
 85334
 85335
 85336
 85337
 85338
 85339
 85340
 85341
 85342
 85343
 85344
 85345
 85346
 85347
 85348
 85349
 85350
 85351
 85352
 85353
 85354
 85355
 85356
 85357
 85358
 85359
 85360
 85361
 85362
 85363
 85364
 85365
 85366
 85367
 85368
 85369
 85370
 85371
 85372
 85373
 85374
 85375
 85376
 85377
 85378
 85379
 85380
 85381
 85382
 85383
 85384
 85385
 85386
 85387
 85388
 85389
 85390
 85391
 85392
 85393
 85394
 85395
 85396
 85397
 85398
 85399
 85400
 85401
 85402
 85403
 85404
 85405
 85406
 85407
 85408
 85409
 85410
 85411
 85412
 85413
 85414
 85415
 85416
 85417
 85418
 85419
 85420
 85421
 85422
 85423
 85424
 85425
 85426
 85427
 85428
 85429
 85430
 85431
 85432
 85433
 85434
 85435
 85436
 85437
 85438
 85439
 85440
 85441
 85442
 85443
 85444
 85445
 85446
 85447
 85448
 85449
 85450
 85451
 85452
 85453
 85454
 85455
 85456
 85457
 85458
 85459
 85460
 85461
 85462
 85463
 85464
 85465
 85466
 85467
 85468
 85469
 85470
 85471
 85472
 85473
 85474
 85475
 85476
 85477
 85478
 85479
 85480
 85481
 85482
 85483
 85484
 85485
 85486
 85487
 85488
 85489
 85490
 85491
 85492
 85493
 85494
 85495
 85496
 85497
 85498
 85499
 85500
 85501
 85502
 85503
 85504
 85505
 85506
 85507
 85508
 85509
 85510
 85511
 85512
 85513
 85514
 85515
 85516
 85517
 85518
 85519
 85520
 85521
 85522
 85523
 85524
 85525
 85526
 85527
 85528
 85529
 85530
 85531
 85532
 85533
 85534
 85535
 85536
 85537
 85538
 85539
 85540
 85541
 85542
 85543
 85544
 85545
 85546
 85547
 85548
 85549
 85550
 85551
 85552
 85553
 85554
 85555
 85556
 85557
 85558
 85559
 85560
 85561
 85562
 85563
 85564
 85565
 85566
 85567
 85568
 85569
 85570
 85571
 85572
 85573
 85574
 85575
 85576
 85577
 85578
 85579
 85580
 85581
 85582
 85583
 85584
 85585
 85586
 85587
 85588
 85589
 85590
 85591
 85592
 85593
 85594
 85595
 85596
 85597
 85598
 85599
 85600
 85601
 85602
 85603
 85604
 85605
 85606
 85607
 85608
 85609
 85610
 85611
 85612
 85613
 85614
 85615
 85616
 85617
 85618
 85619
 85620
 85621
 85622
 85623
 85624
 85625
 85626
 85627
 85628
 85629
 85630
 85631
 85632
 85633
 85634
 85635
 85636
 85637
 85638
 85639
 85640
 85641
 85642
 85643
 85644
 85645
 85646
 85647
 85648
 85649
 85650
 85651
 85652
 85653
 85654
 85655
 85656
 85657
 85658
 85659
 85660
 85661
 85662
 85663
 85664
 85665
 85666
 85667
 85668
 85669
 85670
 85671
 85672
 85673
 85674
 85675
 85676
 85677
 85678
 85679
 85680
 85681
 85682
 85683
 85684
 85685
 85686
 85687
 85688
 85689
 85690
 85691
 85692
 85693
 85694
 85695
 85696
 85697
 85698
 85699
 85700
 85701
 85702
 85703
 85704
 85705
 85706
 85707
 85708
 85709
 85710
 85711
 85712
 85713
 85714
 85715
 85716
 85717
 85718
 85719
 85720
 85721
 85722
 85723
 85724
 85725
 85726
 85727
 85728
 85729
 85730
 85731
 85732
 85733
 85734
 85735
 85736
 85737
 85738
 85739
 85740
 85741
 85742
 85743
 85744
 85745
 85746
 85747
 85748
 85749
 85750
 85751
 85752
 85753
 85754
 85755
 85756
 85757
 85758
 85759
 85760
 85761
 85762
 85763
 85764
 85765
 85766
 85767
 85768
 85769
 85770
 85771
 85772
 85773
 85774
 85775
 85776
 85777
 85778
 85779
 85780
 85781
 85782
 85783
 85784
 85785
 85786
 85787
 85788
 85789
 85790
 85791
 85792
 85793
 85794
 85795
 85796
 85797
 85798
 85799
 85800
 85801
 85802
 85803
 85804
 85805
 85806
 85807
 85808
 85809
 85810
 85811
 85812
 85813
 85814
 85815
 85816
 85817
 85818
 85819
 85820
 85821
 85822
 85823
 85824
 85825
 85826
 85827
 85828
 85829
 85830
 85831
 85832
 85833
 85834
 85835
 85836
 85837
 85838
 85839
 85840
 85841
 85842
 85843
 85844
 85845
 85846
 85847
 85848
 85849
 85850
 85851
 85852
 85853
 85854
 85855
 85856
 85857
 85858
 85859
 85860
 85861
 85862
 85863
 85864
 85865
 85866
 85867
 85868
 85869
 85870
 85871
 85872
 85873
 85874
 85875
 85876
 85877
 85878
 85879
 85880
 85881
 85882
 85883
 85884
 85885
 85886
 85887
 85888
 85889
 85890
 85891
 85892
 85893
 85894
 85895
 85896
 85897
 85898
 85899
 85900
 85901
 85902
 85903
 85904
 85905
 85906
 85907
 85908
 85909
 85910
 85911
 85912
 85913
 85914
 85915
 85916
 85917
 85918
 85919
 85920
 85921
 85922
 85923
 85924
 85925
 85926
 85927
 85928
 85929
 85930
 85931
 85932
 85933
 85934
 85935
 85936
 85937
 85938
 85939
 85940
 85941
 85942
 85943
 85944
 85945
 85946
 85947
 85948
 85949
 85950
 85951
 85952
 85953
 85954
 85955
 85956
 85957
 85958
 85959
 85960
 85961
 85962
 85963
 85964
 85965
 85966
 85967
 85968
 85969
 85970
 85971
 85972
 85973
 85974
 85975
 85976
 85977
 85978
 85979
 85980
 85981
 85982
 85983
 85984
 85985
 85986
 85987
 85988
 85989
 85990
 85991
 85992
 85993
 85994
 85995
 85996
 85997
 85998
 85999
 86000
 86001
 86002
 86003
 86004
 86005
 86006
 86007
 86008
 86009
 86010
 86011
 86012
 86013
 86014
 86015
 86016
 86017
 86018
 86019
 86020
 86021
 86022
 86023
 86024
 86025
 86026
 86027
 86028
 86029
 86030
 86031
 86032
 86033
 86034
 86035
 86036
 86037
 86038
 86039
 86040
 86041
 86042
 86043
 86044
 86045
 86046
 86047
 86048
 86049
 86050
 86051
 86052
 86053
 86054
 86055
 86056
 86057
 86058
 86059
 86060
 86061
 86062
 86063
 86064
 86065
 86066
 86067
 86068
 86069
 86070
 86071
 86072
 86073
 86074
 86075
 86076
 86077
 86078
 86079
 86080
 86081
 86082
 86083
 86084
 86085
 86086
 86087
 86088
 86089
 86090
 86091
 86092
 86093
 86094
 86095
 86096
 86097
 86098
 86099
 86100
 86101
 86102
 86103
 86104
 86105
 86106
 86107
 86108
 86109
 86110
 86111
 86112
 86113
 86114
 86115
 86116
 86117
 86118
 86119
 86120
 86121
 86122
 86123
 86124
 86125
 86126
 86127
 86128
 86129
 86130
 86131
 86132
 86133
 86134
 86135
 86136
 86137
 86138
 86139
 86140
 86141
 86142
 86143
 86144
 86145
 86146
 86147
 86148
 86149
 86150
 86151
 86152
 86153
 86154
 86155
 86156
 86157
 86158
 86159
 86160
 86161
 86162
 86163
 86164
 86165
 86166
 86167
 86168
 86169
 86170
 86171
 86172
 86173
 86174
 86175
 86176
 86177
 86178
 86179
 86180
 86181
 86182
 86183
 86184
 86185
 86186
 86187
 86188
 86189
 86190
 86191
 86192
 86193
 86194
 86195
 86196
 86197
 86198
 86199
 86200
 86201
 86202
 86203
 86204
 86205
 86206
 86207
 86208
 86209
 86210
 86211
 86212
 86213
 86214
 86215
 86216
 86217
 86218
 86219
 86220
 86221
 86222
 86223
 86224
 86225
 86226
 86227
 86228
 86229
 86230
 86231
 86232
 86233
 86234
 86235
 86236
 86237
 86238
 86239
 86240
 86241
 86242
 86243
 86244
 86245
 86246
 86247
 86248
 86249
 86250
 86251
 86252
 86253
 86254
 86255
 86256
 86257
 86258
 86259
 86260
 86261
 86262
 86263
 86264
 86265
 86266
 86267
 86268
 86269
 86270
 86271
 86272
 86273
 86274
 86275
 86276
 86277
 86278
 86279
 86280
 86281
 86282
 86283
 86284
 86285
 86286
 86287
 86288
 86289
 86290
 86291
 86292
 86293
 86294
 86295
 86296
 86297
 86298
 86299
 86300
 86301
 86302
 86303
 86304
 86305
 86306
 86307
 86308
 86309
 86310
 86311
 86312
 86313
 86314
 86315
 86316
 86317
 86318
 86319
 86320
 86321
 86322
 86323
 86324
 86325
 86326
 86327
 86328
 86329
 86330
 86331
 86332
 86333
 86334
 86335
 86336
 86337
 86338
 86339
 86340
 86341
 86342
 86343
 86344
 86345
 86346
 86347
 86348
 86349
 86350
 86351
 86352
 86353
 86354
 86355
 86356
 86357
 86358
 86359
 86360
 86361
 86362
 86363
 86364
 86365
 86366
 86367
 86368
 86369
 86370
 86371
 86372
 86373
 86374
 86375
 86376
 86377
 86378
 86379
 86380
 86381
 86382
 86383
 86384
 86385
 86386
 86387
 86388
 86389
 86390
 86391
 86392
 86393
 86394
 86395
 86396
 86397
 86398
 86399
 86400
 86401
 86402
 86403
 86404
 86405
 86406
 86407
 86408
 86409
 86410
 86411
 86412
 86413
 86414
 86415
 86416
 86417
 86418
 86419
 86420
 86421
 86422
 86423
 86424
 86425
 86426
 86427
 86428
 86429
 86430
 86431
 86432
 86433
 86434
 86435
 86436
 86437
 86438
 86439
 86440
 86441
 86442
 86443
 86444
 86445
 86446
 86447
 86448
 86449
 86450
 86451
 86452
 86453
 86454
 86455
 86456
 86457
 86458
 86459
 86460
 86461
 86462
 86463
 86464
 86465
 86466
 86467
 86468
 86469
 86470
 86471
 86472
 86473
 86474
 86475
 86476
 86477
 86478
 86479
 86480
 86481
 86482
 86483
 86484
 86485
 86486
 86487
 86488
 86489
 86490
 86491
 86492
 86493
 86494
 86495
 86496
 86497
 86498
 86499
 86500
 86501
 86502
 86503
 86504
 86505
 86506
 86507
 86508
 86509
 86510
 86511
 86512
 86513
 86514
 86515
 86516
 86517
 86518
 86519
 86520
 86521
 86522
 86523
 86524
 86525
 86526
 86527
 86528
 86529
 86530
 86531
 86532
 86533
 86534
 86535
 86536
 86537
 86538
 86539
 86540
 86541
 86542
 86543
 86544
 86545
 86546
 86547
 86548
 86549
 86550
 86551
 86552
 86553
 86554
 86555
 86556
 86557
 86558
 86559
 86560
 86561
 86562
 86563
 86564
 86565
 86566
 86567
 86568
 86569
 86570
 86571
 86572
 86573
 86574
 86575
 86576
 86577
 86578
 86579
 86580
 86581
 86582
 86583
 86584
 86585
 86586
 86587
 86588
 86589
 86590
 86591
 86592
 86593
 86594
 86595
 86596
 86597
 86598
 86599
 86600
 86601
 86602
 86603
 86604
 86605
 86606
 86607
 86608
 86609
 86610
 86611
 86612
 86613
 86614
 86615
 86616
 86617
 86618
 86619
 86620
 86621
 86622
 86623
 86624
 86625
 86626
 86627
 86628
 86629
 86630
 86631
 86632
 86633
 86634
 86635
 86636
 86637
 86638
 86639
 86640
 86641
 86642
 86643
 86644
 86645
 86646
 86647
 86648
 86649
 86650
 86651
 86652
 86653
 86654
 86655
 86656
 86657
 86658
 86659
 86660
 86661
 86662
 86663
 86664
 86665
 86666
 86667
 86668
 86669
 86670
 86671
 86672
 86673
 86674
 86675
 86676
 86677
 86678
 86679
 86680
 86681
 86682
 86683
 86684
 86685
 86686
 86687
 86688
 86689
 86690
 86691
 86692
 86693
 86694
 86695
 86696
 86697
 86698
 86699
 86700
 86701
 86702
 86703
 86704
 86705
 86706
 86707
 86708
 86709
 86710
 86711
 86712
 86713
 86714
 86715
 86716
 86717
 86718
 86719
 86720
 86721
 86722
 86723
 86724
 86725
 86726
 86727
 86728
 86729
 86730
 86731
 86732
 86733
 86734
 86735
 86736
 86737
 86738
 86739
 86740
 86741
 86742
 86743
 86744
 86745
 86746
 86747
 86748
 86749
 86750
 86751
 86752
 86753
 86754
 86755
 86756
 86757
 86758
 86759
 86760
 86761
 86762
 86763
 86764
 86765
 86766
 86767
 86768
 86769
 86770
 86771
 86772
 86773
 86774
 86775
 86776
 86777
 86778
 86779
 86780
 86781
 86782
 86783
 86784
 86785
 86786
 86787
 86788
 86789
 86790
 86791
 86792
 86793
 86794
 86795
 86796
 86797
 86798
 86799
 86800
 86801
 86802
 86803
 86804
 86805
 86806
 86807
 86808
 86809
 86810
 86811
 86812
 86813
 86814
 86815
 86816
 86817
 86818
 86819
 86820
 86821
 86822
 86823
 86824
 86825
 86826
 86827
 86828
 86829
 86830
 86831
 86832
 86833
 86834
 86835
 86836
 86837
 86838
 86839
 86840
 86841
 86842
 86843
 86844
 86845
 86846
 86847
 86848
 86849
 86850
 86851
 86852
 86853
 86854
 86855
 86856
 86857
 86858
 86859
 86860
 86861
 86862
 86863
 86864
 86865
 86866
 86867
 86868
 86869
 86870
 86871
 86872
 86873
 86874
 86875
 86876
 86877
 86878
 86879
 86880
 86881
 86882
 86883
 86884
 86885
 86886
 86887
 86888
 86889
 86890
 86891
 86892
 86893
 86894
 86895
 86896
 86897
 86898
 86899
 86900
 86901
 86902
 86903
 86904
 86905
 86906
 86907
 86908
 86909
 86910
 86911
 86912
 86913
 86914
 86915
 86916
 86917
 86918
 86919
 86920
 86921
 86922
 86923
 86924
 86925
 86926
 86927
 86928
 86929
 86930
 86931
 86932
 86933
 86934
 86935
 86936
 86937
 86938
 86939
 86940
 86941
 86942
 86943
 86944
 86945
 86946
 86947
 86948
 86949
 86950
 86951
 86952
 86953
 86954
 86955
 86956
 86957
 86958
 86959
 86960
 86961
 86962
 86963
 86964
 86965
 86966
 86967
 86968
 86969
 86970
 86971
 86972
 86973
 86974
 86975
 86976
 86977
 86978
 86979
 86980
 86981
 86982
 86983
 86984
 86985
 86986
 86987
 86988
 86989
 86990
 86991
 86992
 86993
 86994
 86995
 86996
 86997
 86998
 86999
 87000
 87001
 87002
 87003
 87004
 87005
 87006
 87007
 87008
 87009
 87010
 87011
 87012
 87013
 87014
 87015
 87016
 87017
 87018
 87019
 87020
 87021
 87022
 87023
 87024
 87025
 87026
 87027
 87028
 87029
 87030
 87031
 87032
 87033
 87034
 87035
 87036
 87037
 87038
 87039
 87040
 87041
 87042
 87043
 87044
 87045
 87046
 87047
 87048
 87049
 87050
 87051
 87052
 87053
 87054
 87055
 87056
 87057
 87058
 87059
 87060
 87061
 87062
 87063
 87064
 87065
 87066
 87067
 87068
 87069
 87070
 87071
 87072
 87073
 87074
 87075
 87076
 87077
 87078
 87079
 87080
 87081
 87082
 87083
 87084
 87085
 87086
 87087
 87088
 87089
 87090
 87091
 87092
 87093
 87094
 87095
 87096
 87097
 87098
 87099
 87100
 87101
 87102
 87103
 87104
 87105
 87106
 87107
 87108
 87109
 87110
 87111
 87112
 87113
 87114
 87115
 87116
 87117
 87118
 87119
 87120
 87121
 87122
 87123
 87124
 87125
 87126
 87127
 87128
 87129
 87130
 87131
 87132
 87133
 87134
 87135
 87136
 87137
 87138
 87139
 87140
 87141
 87142
 87143
 87144
 87145
 87146
 87147
 87148
 87149
 87150
 87151
 87152
 87153
 87154
 87155
 87156
 87157
 87158
 87159
 87160
 87161
 87162
 87163
 87164
 87165
 87166
 87167
 87168
 87169
 87170
 87171
 87172
 87173
 87174
 87175
 87176
 87177
 87178
 87179
 87180
 87181
 87182
 87183
 87184
 87185
 87186
 87187
 87188
 87189
 87190
 87191
 87192
 87193
 87194
 87195
 87196
 87197
 87198
 87199
 87200
 87201
 87202
 87203
 87204
 87205
 87206
 87207
 87208
 87209
 87210
 87211
 87212
 87213
 87214
 87215
 87216
 87217
 87218
 87219
 87220
 87221
 87222
 87223
 87224
 87225
 87226
 87227
 87228
 87229
 87230
 87231
 87232
 87233
 87234
 87235
 87236
 87237
 87238
 87239
 87240
 87241
 87242
 87243
 87244
 87245
 87246
 87247
 87248
 87249
 87250
 87251
 87252
 87253
 87254
 87255
 87256
 87257
 87258
 87259
 87260
 87261
 87262
 87263
 87264
 87265
 87266
 87267
 87268
 87269
 87270
 87271
 87272
 87273
 87274
 87275
 87276
 87277
 87278
 87279
 87280
 87281
 87282
 87283
 87284
 87285
 87286
 87287
 87288
 87289
 87290
 87291
 87292
 87293
 87294
 87295
 87296
 87297
 87298
 87299
 87300
 87301
 87302
 87303
 87304
 87305
 87306
 87307
 87308
 87309
 87310
 87311
 87312
 87313
 87314
 87315
 87316
 87317
 87318
 87319
 87320
 87321
 87322
 87323
 87324
 87325
 87326
 87327
 87328
 87329
 87330
 87331
 87332
 87333
 87334
 87335
 87336
 87337
 87338
 87339
 87340
 87341
 87342
 87343
 87344
 87345
 87346
 87347
 87348
 87349
 87350
 87351
 87352
 87353
 87354
 87355
 87356
 87357
 87358
 87359
 87360
 87361
 87362
 87363
 87364
 87365
 87366
 87367
 87368
 87369
 87370
 87371
 87372
 87373
 87374
 87375
 87376
 87377
 87378
 87379
 87380
 87381
 87382
 87383
 87384
 87385
 87386
 87387
 87388
 87389
 87390
 87391
 87392
 87393
 87394
 87395
 87396
 87397
 87398
 87399
 87400
 87401
 87402
 87403
 87404
 87405
 87406
 87407
 87408
 87409
 87410
 87411
 87412
 87413
 87414
 87415
 87416
 87417
 87418
 87419
 87420
 87421
 87422
 87423
 87424
 87425
 87426
 87427
 87428
 87429
 87430
 87431
 87432
 87433
 87434
 87435
 87436
 87437
 87438
 87439
 87440
 87441
 87442
 87443
 87444
 87445
 87446
 87447
 87448
 87449
 87450
 87451
 87452
 87453
 87454
 87455
 87456
 87457
 87458
 87459
 87460
 87461
 87462
 87463
 87464
 87465
 87466
 87467
 87468
 87469
 87470
 87471
 87472
 87473
 87474
 87475
 87476
 87477
 87478
 87479
 87480
 87481
 87482
 87483
 87484
 87485
 87486
 87487
 87488
 87489
 87490
 87491
 87492
 87493
 87494
 87495
 87496
 87497
 87498
 87499
 87500
 87501
 87502
 87503
 87504
 87505
 87506
 87507
 87508
 87509
 87510
 87511
 87512
 87513
 87514
 87515
 87516
 87517
 87518
 87519
 87520
 87521
 87522
 87523
 87524
 87525
 87526
 87527
 87528
 87529
 87530
 87531
 87532
 87533
 87534
 87535
 87536
 87537
 87538
 87539
 87540
 87541
 87542
 87543
 87544
 87545
 87546
 87547
 87548
 87549
 87550
 87551
 87552
 87553
 87554
 87555
 87556
 87557
 87558
 87559
 87560
 87561
 87562
 87563
 87564
 87565
 87566
 87567
 87568
 87569
 87570
 87571
 87572
 87573
 87574
 87575
 87576
 87577
 87578
 87579
 87580
 87581
 87582
 87583
 87584
 87585
 87586
 87587
 87588
 87589
 87590
 87591
 87592
 87593
 87594
 87595
 87596
 87597
 87598
 87599
 87600
 87601
 87602
 87603
 87604
 87605
 87606
 87607
 87608
 87609
 87610
 87611
 87612
 87613
 87614
 87615
 87616
 87617
 87618
 87619
 87620
 87621
 87622
 87623
 87624
 87625
 87626
 87627
 87628
 87629
 87630
 87631
 87632
 87633
 87634
 87635
 87636
 87637
 87638
 87639
 87640
 87641
 87642
 87643
 87644
 87645
 87646
 87647
 87648
 87649
 87650
 87651
 87652
 87653
 87654
 87655
 87656
 87657
 87658
 87659
 87660
 87661
 87662
 87663
 87664
 87665
 87666
 87667
 87668
 87669
 87670
 87671
 87672
 87673
 87674
 87675
 87676
 87677
 87678
 87679
 87680
 87681
 87682
 87683
 87684
 87685
 87686
 87687
 87688
 87689
 87690
 87691
 87692
 87693
 87694
 87695
 87696
 87697
 87698
 87699
 87700
 87701
 87702
 87703
 87704
 87705
 87706
 87707
 87708
 87709
 87710
 87711
 87712
 87713
 87714
 87715
 87716
 87717
 87718
 87719
 87720
 87721
 87722
 87723
 87724
 87725
 87726
 87727
 87728
 87729
 87730
 87731
 87732
 87733
 87734
 87735
 87736
 87737
 87738
 87739
 87740
 87741
 87742
 87743
 87744
 87745
 87746
 87747
 87748
 87749
 87750
 87751
 87752
 87753
 87754
 87755
 87756
 87757
 87758
 87759
 87760
 87761
 87762
 87763
 87764
 87765
 87766
 87767
 87768
 87769
 87770
 87771
 87772
 87773
 87774
 87775
 87776
 87777
 87778
 87779
 87780
 87781
 87782
 87783
 87784
 87785
 87786
 87787
 87788
 87789
 87790
 87791
 87792
 87793
 87794
 87795
 87796
 87797
 87798
 87799
 87800
 87801
 87802
 87803
 87804
 87805
 87806
 87807
 87808
 87809
 87810
 87811
 87812
 87813
 87814
 87815
 87816
 87817
 87818
 87819
 87820
 87821
 87822
 87823
 87824
 87825
 87826
 87827
 87828
 87829
 87830
 87831
 87832
 87833
 87834
 87835
 87836
 87837
 87838
 87839
 87840
 87841
 87842
 87843
 87844
 87845
 87846
 87847
 87848
 87849
 87850
 87851
 87852
 87853
 87854
 87855
 87856
 87857
 87858
 87859
 87860
 87861
 87862
 87863
 87864
 87865
 87866
 87867
 87868
 87869
 87870
 87871
 87872
 87873
 87874
 87875
 87876
 87877
 87878
 87879
 87880
 87881
 87882
 87883
 87884
 87885
 87886
 87887
 87888
 87889
 87890
 87891
 87892
 87893
 87894
 87895
 87896
 87897
 87898
 87899
 87900
 87901
 87902
 87903
 87904
 87905
 87906
 87907
 87908
 87909
 87910
 87911
 87912
 87913
 87914
 87915
 87916
 87917
 87918
 87919
 87920
 87921
 87922
 87923
 87924
 87925
 87926
 87927
 87928
 87929
 87930
 87931
 87932
 87933
 87934
 87935
 87936
 87937
 87938
 87939
 87940
 87941
 87942
 87943
 87944
 87945
 87946
 87947
 87948
 87949
 87950
 87951
 87952
 87953
 87954
 87955
 87956
 87957
 87958
 87959
 87960
 87961
 87962
 87963
 87964
 87965
 87966
 87967
 87968
 87969
 87970
 87971
 87972
 87973
 87974
 87975
 87976
 87977
 87978
 87979
 87980
 87981
 87982
 87983
 87984
 87985
 87986
 87987
 87988
 87989
 87990
 87991
 87992
 87993
 87994
 87995
 87996
 87997
 87998
 87999
 88000
 88001
 88002
 88003
 88004
 88005
 88006
 88007
 88008
 88009
 88010
 88011
 88012
 88013
 88014
 88015
 88016
 88017
 88018
 88019
 88020
 88021
 88022
 88023
 88024
 88025
 88026
 88027
 88028
 88029
 88030
 88031
 88032
 88033
 88034
 88035
 88036
 88037
 88038
 88039
 88040
 88041
 88042
 88043
 88044
 88045
 88046
 88047
 88048
 88049
 88050
 88051
 88052
 88053
 88054
 88055
 88056
 88057
 88058
 88059
 88060
 88061
 88062
 88063
 88064
 88065
 88066
 88067
 88068
 88069
 88070
 88071
 88072
 88073
 88074
 88075
 88076
 88077
 88078
 88079
 88080
 88081
 88082
 88083
 88084
 88085
 88086
 88087
 88088
 88089
 88090
 88091
 88092
 88093
 88094
 88095
 88096
 88097
 88098
 88099
 88100
 88101
 88102
 88103
 88104
 88105
 88106
 88107
 88108
 88109
 88110
 88111
 88112
 88113
 88114
 88115
 88116
 88117
 88118
 88119
 88120
 88121
 88122
 88123
 88124
 88125
 88126
 88127
 88128
 88129
 88130
 88131
 88132
 88133
 88134
 88135
 88136
 88137
 88138
 88139
 88140
 88141
 88142
 88143
 88144
 88145
 88146
 88147
 88148
 88149
 88150
 88151
 88152
 88153
 88154
 88155
 88156
 88157
 88158
 88159
 88160
 88161
 88162
 88163
 88164
 88165
 88166
 88167
 88168
 88169
 88170
 88171
 88172
 88173
 88174
 88175
 88176
 88177
 88178
 88179
 88180
 88181
 88182
 88183
 88184
 88185
 88186
 88187
 88188
 88189
 88190
 88191
 88192
 88193
 88194
 88195
 88196
 88197
 88198
 88199
 88200
 88201
 88202
 88203
 88204
 88205
 88206
 88207
 88208
 88209
 88210
 88211
 88212
 88213
 88214
 88215
 88216
 88217
 88218
 88219
 88220
 88221
 88222
 88223
 88224
 88225
 88226
 88227
 88228
 88229
 88230
 88231
 88232
 88233
 88234
 88235
 88236
 88237
 88238
 88239
 88240
 88241
 88242
 88243
 88244
 88245
 88246
 88247
 88248
 88249
 88250
 88251
 88252
 88253
 88254
 88255
 88256
 88257
 88258
 88259
 88260
 88261
 88262
 88263
 88264
 88265
 88266
 88267
 88268
 88269
 88270
 88271
 88272
 88273
 88274
 88275
 88276
 88277
 88278
 88279
 88280
 88281
 88282
 88283
 88284
 88285
 88286
 88287
 88288
 88289
 88290
 88291
 88292
 88293
 88294
 88295
 88296
 88297
 88298
 88299
 88300
 88301
 88302
 88303
 88304
 88305
 88306
 88307
 88308
 88309
 88310
 88311
 88312
 88313
 88314
 88315
 88316
 88317
 88318
 88319
 88320
 88321
 88322
 88323
 88324
 88325
 88326
 88327
 88328
 88329
 88330
 88331
 88332
 88333
 88334
 88335
 88336
 88337
 88338
 88339
 88340
 88341
 88342
 88343
 88344
 88345
 88346
 88347
 88348
 88349
 88350
 88351
 88352
 88353
 88354
 88355
 88356
 88357
 88358
 88359
 88360
 88361
 88362
 88363
 88364
 88365
 88366
 88367
 88368
 88369
 88370
 88371
 88372
 88373
 88374
 88375
 88376
 88377
 88378
 88379
 88380
 88381
 88382
 88383
 88384
 88385
 88386
 88387
 88388
 88389
 88390
 88391
 88392
 88393
 88394
 88395
 88396
 88397
 88398
 88399
 88400
 88401
 88402
 88403
 88404
 88405
 88406
 88407
 88408
 88409
 88410
 88411
 88412
 88413
 88414
 88415
 88416
 88417
 88418
 88419
 88420
 88421
 88422
 88423
 88424
 88425
 88426
 88427
 88428
 88429
 88430
 88431
 88432
 88433
 88434
 88435
 88436
 88437
 88438
 88439
 88440
 88441
 88442
 88443
 88444
 88445
 88446
 88447
 88448
 88449
 88450
 88451
 88452
 88453
 88454
 88455
 88456
 88457
 88458
 88459
 88460
 88461
 88462
 88463
 88464
 88465
 88466
 88467
 88468
 88469
 88470
 88471
 88472
 88473
 88474
 88475
 88476
 88477
 88478
 88479
 88480
 88481
 88482
 88483
 88484
 88485
 88486
 88487
 88488
 88489
 88490
 88491
 88492
 88493
 88494
 88495
 88496
 88497
 88498
 88499
 88500
 88501
 88502
 88503
 88504
 88505
 88506
 88507
 88508
 88509
 88510
 88511
 88512
 88513
 88514
 88515
 88516
 88517
 88518
 88519
 88520
 88521
 88522
 88523
 88524
 88525
 88526
 88527
 88528
 88529
 88530
 88531
 88532
 88533
 88534
 88535
 88536
 88537
 88538
 88539
 88540
 88541
 88542
 88543
 88544
 88545
 88546
 88547
 88548
 88549
 88550
 88551
 88552
 88553
 88554
 88555
 88556
 88557
 88558
 88559
 88560
 88561
 88562
 88563
 88564
 88565
 88566
 88567
 88568
 88569
 88570
 88571
 88572
 88573
 88574
 88575
 88576
 88577
 88578
 88579
 88580
 88581
 88582
 88583
 88584
 88585
 88586
 88587
 88588
 88589
 88590
 88591
 88592
 88593
 88594
 88595
 88596
 88597
 88598
 88599
 88600
 88601
 88602
 88603
 88604
 88605
 88606
 88607
 88608
 88609
 88610
 88611
 88612
 88613
 88614
 88615
 88616
 88617
 88618
 88619
 88620
 88621
 88622
 88623
 88624
 88625
 88626
 88627
 88628
 88629
 88630
 88631
 88632
 88633
 88634
 88635
 88636
 88637
 88638
 88639
 88640
 88641
 88642
 88643
 88644
 88645
 88646
 88647
 88648
 88649
 88650
 88651
 88652
 88653
 88654
 88655
 88656
 88657
 88658
 88659
 88660
 88661
 88662
 88663
 88664
 88665
 88666
 88667
 88668
 88669
 88670
 88671
 88672
 88673
 88674
 88675
 88676
 88677
 88678
 88679
 88680
 88681
 88682
 88683
 88684
 88685
 88686
 88687
 88688
 88689
 88690
 88691
 88692
 88693
 88694
 88695
 88696
 88697
 88698
 88699
 88700
 88701
 88702
 88703
 88704
 88705
 88706
 88707
 88708
 88709
 88710
 88711
 88712
 88713
 88714
 88715
 88716
 88717
 88718
 88719
 88720
 88721
 88722
 88723
 88724
 88725
 88726
 88727
 88728
 88729
 88730
 88731
 88732
 88733
 88734
 88735
 88736
 88737
 88738
 88739
 88740
 88741
 88742
 88743
 88744
 88745
 88746
 88747
 88748
 88749
 88750
 88751
 88752
 88753
 88754
 88755
 88756
 88757
 88758
 88759
 88760
 88761
 88762
 88763
 88764
 88765
 88766
 88767
 88768
 88769
 88770
 88771
 88772
 88773
 88774
 88775
 88776
 88777
 88778
 88779
 88780
 88781
 88782
 88783
 88784
 88785
 88786
 88787
 88788
 88789
 88790
 88791
 88792
 88793
 88794
 88795
 88796
 88797
 88798
 88799
 88800
 88801
 88802
 88803
 88804
 88805
 88806
 88807
 88808
 88809
 88810
 88811
 88812
 88813
 88814
 88815
 88816
 88817
 88818
 88819
 88820
 88821
 88822
 88823
 88824
 88825
 88826
 88827
 88828
 88829
 88830
 88831
 88832
 88833
 88834
 88835
 88836
 88837
 88838
 88839
 88840
 88841
 88842
 88843
 88844
 88845
 88846
 88847
 88848
 88849
 88850
 88851
 88852
 88853
 88854
 88855
 88856
 88857
 88858
 88859
 88860
 88861
 88862
 88863
 88864
 88865
 88866
 88867
 88868
 88869
 88870
 88871
 88872
 88873
 88874
 88875
 88876
 88877
 88878
 88879
 88880
 88881
 88882
 88883
 88884
 88885
 88886
 88887
 88888
 88889
 88890
 88891
 88892
 88893
 88894
 88895
 88896
 88897
 88898
 88899
 88900
 88901
 88902
 88903
 88904
 88905
 88906
 88907
 88908
 88909
 88910
 88911
 88912
 88913
 88914
 88915
 88916
 88917
 88918
 88919
 88920
 88921
 88922
 88923
 88924
 88925
 88926
 88927
 88928
 88929
 88930
 88931
 88932
 88933
 88934
 88935
 88936
 88937
 88938
 88939
 88940
 88941
 88942
 88943
 88944
 88945
 88946
 88947
 88948
 88949
 88950
 88951
 88952
 88953
 88954
 88955
 88956
 88957
 88958
 88959
 88960
 88961
 88962
 88963
 88964
 88965
 88966
 88967
 88968
 88969
 88970
 88971
 88972
 88973
 88974
 88975
 88976
 88977
 88978
 88979
 88980
 88981
 88982
 88983
 88984
 88985
 88986
 88987
 88988
 88989
 88990
 88991
 88992
 88993
 88994
 88995
 88996
 88997
 88998
 88999
 89000
 89001
 89002
 89003
 89004
 89005
 89006
 89007
 89008
 89009
 89010
 89011
 89012
 89013
 89014
 89015
 89016
 89017
 89018
 89019
 89020
 89021
 89022
 89023
 89024
 89025
 89026
 89027
 89028
 89029
 89030
 89031
 89032
 89033
 89034
 89035
 89036
 89037
 89038
 89039
 89040
 89041
 89042
 89043
 89044
 89045
 89046
 89047
 89048
 89049
 89050
 89051
 89052
 89053
 89054
 89055
 89056
 89057
 89058
 89059
 89060
 89061
 89062
 89063
 89064
 89065
 89066
 89067
 89068
 89069
 89070
 89071
 89072
 89073
 89074
 89075
 89076
 89077
 89078
 89079
 89080
 89081
 89082
 89083
 89084
 89085
 89086
 89087
 89088
 89089
 89090
 89091
 89092
 89093
 89094
 89095
 89096
 89097
 89098
 89099
 89100
 89101
 89102
 89103
 89104
 89105
 89106
 89107
 89108
 89109
 89110
 89111
 89112
 89113
 89114
 89115
 89116
 89117
 89118
 89119
 89120
 89121
 89122
 89123
 89124
 89125
 89126
 89127
 89128
 89129
 89130
 89131
 89132
 89133
 89134
 89135
 89136
 89137
 89138
 89139
 89140
 89141
 89142
 89143
 89144
 89145
 89146
 89147
 89148
 89149
 89150
 89151
 89152
 89153
 89154
 89155
 89156
 89157
 89158
 89159
 89160
 89161
 89162
 89163
 89164
 89165
 89166
 89167
 89168
 89169
 89170
 89171
 89172
 89173
 89174
 89175
 89176
 89177
 89178
 89179
 89180
 89181
 89182
 89183
 89184
 89185
 89186
 89187
 89188
 89189
 89190
 89191
 89192
 89193
 89194
 89195
 89196
 89197
 89198
 89199
 89200
 89201
 89202
 89203
 89204
 89205
 89206
 89207
 89208
 89209
 89210
 89211
 89212
 89213
 89214
 89215
 89216
 89217
 89218
 89219
 89220
 89221
 89222
 89223
 89224
 89225
 89226
 89227
 89228
 89229
 89230
 89231
 89232
 89233
 89234
 89235
 89236
 89237
 89238
 89239
 89240
 89241
 89242
 89243
 89244
 89245
 89246
 89247
 89248
 89249
 89250
 89251
 89252
 89253
 89254
 89255
 89256
 89257
 89258
 89259
 89260
 89261
 89262
 89263
 89264
 89265
 89266
 89267
 89268
 89269
 89270
 89271
 89272
 89273
 89274
 89275
 89276
 89277
 89278
 89279
 89280
 89281
 89282
 89283
 89284
 89285
 89286
 89287
 89288
 89289
 89290
 89291
 89292
 89293
 89294
 89295
 89296
 89297
 89298
 89299
 89300
 89301
 89302
 89303
 89304
 89305
 89306
 89307
 89308
 89309
 89310
 89311
 89312
 89313
 89314
 89315
 89316
 89317
 89318
 89319
 89320
 89321
 89322
 89323
 89324
 89325
 89326
 89327
 89328
 89329
 89330
 89331
 89332
 89333
 89334
 89335
 89336
 89337
 89338
 89339
 89340
 89341
 89342
 89343
 89344
 89345
 89346
 89347
 89348
 89349
 89350
 89351
 89352
 89353
 89354
 89355
 89356
 89357
 89358
 89359
 89360
 89361
 89362
 89363
 89364
 89365
 89366
 89367
 89368
 89369
 89370
 89371
 89372
 89373
 89374
 89375
 89376
 89377
 89378
 89379
 89380
 89381
 89382
 89383
 89384
 89385
 89386
 89387
 89388
 89389
 89390
 89391
 89392
 89393
 89394
 89395
 89396
 89397
 89398
 89399
 89400
 89401
 89402
 89403
 89404
 89405
 89406
 89407
 89408
 89409
 89410
 89411
 89412
 89413
 89414
 89415
 89416
 89417
 89418
 89419
 89420
 89421
 89422
 89423
 89424
 89425
 89426
 89427
 89428
 89429
 89430
 89431
 89432
 89433
 89434
 89435
 89436
 89437
 89438
 89439
 89440
 89441
 89442
 89443
 89444
 89445
 89446
 89447
 89448
 89449
 89450
 89451
 89452
 89453
 89454
 89455
 89456
 89457
 89458
 89459
 89460
 89461
 89462
 89463
 89464
 89465
 89466
 89467
 89468
 89469
 89470
 89471
 89472
 89473
 89474
 89475
 89476
 89477
 89478
 89479
 89480
 89481
 89482
 89483
 89484
 89485
 89486
 89487
 89488
 89489
 89490
 89491
 89492
 89493
 89494
 89495
 89496
 89497
 89498
 89499
 89500
 89501
 89502
 89503
 89504
 89505
 89506
 89507
 89508
 89509
 89510
 89511
 89512
 89513
 89514
 89515
 89516
 89517
 89518
 89519
 89520
 89521
 89522
 89523
 89524
 89525
 89526
 89527
 89528
 89529
 89530
 89531
 89532
 89533
 89534
 89535
 89536
 89537
 89538
 89539
 89540
 89541
 89542
 89543
 89544
 89545
 89546
 89547
 89548
 89549
 89550
 89551
 89552
 89553
 89554
 89555
 89556
 89557
 89558
 89559
 89560
 89561
 89562
 89563
 89564
 89565
 89566
 89567
 89568
 89569
 89570
 89571
 89572
 89573
 89574
 89575
 89576
 89577
 89578
 89579
 89580
 89581
 89582
 89583
 89584
 89585
 89586
 89587
 89588
 89589
 89590
 89591
 89592
 89593
 89594
 89595
 89596
 89597
 89598
 89599
 89600
 89601
 89602
 89603
 89604
 89605
 89606
 89607
 89608
 89609
 89610
 89611
 89612
 89613
 89614
 89615
 89616
 89617
 89618
 89619
 89620
 89621
 89622
 89623
 89624
 89625
 89626
 89627
 89628
 89629
 89630
 89631
 89632
 89633
 89634
 89635
 89636
 89637
 89638
 89639
 89640
 89641
 89642
 89643
 89644
 89645
 89646
 89647
 89648
 89649
 89650
 89651
 89652
 89653
 89654
 89655
 89656
 89657
 89658
 89659
 89660
 89661
 89662
 89663
 89664
 89665
 89666
 89667
 89668
 89669
 89670
 89671
 89672
 89673
 89674
 89675
 89676
 89677
 89678
 89679
 89680
 89681
 89682
 89683
 89684
 89685
 89686
 89687
 89688
 89689
 89690
 89691
 89692
 89693
 89694
 89695
 89696
 89697
 89698
 89699
 89700
 89701
 89702
 89703
 89704
 89705
 89706
 89707
 89708
 89709
 89710
 89711
 89712
 89713
 89714
 89715
 89716
 89717
 89718
 89719
 89720
 89721
 89722
 89723
 89724
 89725
 89726
 89727
 89728
 89729
 89730
 89731
 89732
 89733
 89734
 89735
 89736
 89737
 89738
 89739
 89740
 89741
 89742
 89743
 89744
 89745
 89746
 89747
 89748
 89749
 89750
 89751
 89752
 89753
 89754
 89755
 89756
 89757
 89758
 89759
 89760
 89761
 89762
 89763
 89764
 89765
 89766
 89767
 89768
 89769
 89770
 89771
 89772
 89773
 89774
 89775
 89776
 89777
 89778
 89779
 89780
 89781
 89782
 89783
 89784
 89785
 89786
 89787
 89788
 89789
 89790
 89791
 89792
 89793
 89794
 89795
 89796
 89797
 89798
 89799
 89800
 89801
 89802
 89803
 89804
 89805
 89806
 89807
 89808
 89809
 89810
 89811
 89812
 89813
 89814
 89815
 89816
 89817
 89818
 89819
 89820
 89821
 89822
 89823
 89824
 89825
 89826
 89827
 89828
 89829
 89830
 89831
 89832
 89833
 89834
 89835
 89836
 89837
 89838
 89839
 89840
 89841
 89842
 89843
 89844
 89845
 89846
 89847
 89848
 89849
 89850
 89851
 89852
 89853
 89854
 89855
 89856
 89857
 89858
 89859
 89860
 89861
 89862
 89863
 89864
 89865
 89866
 89867
 89868
 89869
 89870
 89871
 89872
 89873
 89874
 89875
 89876
 89877
 89878
 89879
 89880
 89881
 89882
 89883
 89884
 89885
 89886
 89887
 89888
 89889
 89890
 89891
 89892
 89893
 89894
 89895
 89896
 89897
 89898
 89899
 89900
 89901
 89902
 89903
 89904
 89905
 89906
 89907
 89908
 89909
 89910
 89911
 89912
 89913
 89914
 89915
 89916
 89917
 89918
 89919
 89920
 89921
 89922
 89923
 89924
 89925
 89926
 89927
 89928
 89929
 89930
 89931
 89932
 89933
 89934
 89935
 89936
 89937
 89938
 89939
 89940
 89941
 89942
 89943
 89944
 89945
 89946
 89947
 89948
 89949
 89950
 89951
 89952
 89953
 89954
 89955
 89956
 89957
 89958
 89959
 89960
 89961
 89962
 89963
 89964
 89965
 89966
 89967
 89968
 89969
 89970
 89971
 89972
 89973
 89974
 89975
 89976
 89977
 89978
 89979
 89980
 89981
 89982
 89983
 89984
 89985
 89986
 89987
 89988
 89989
 89990
 89991
 89992
 89993
 89994
 89995
 89996
 89997
 89998
 89999
 90000
 90001
 90002
 90003
 90004
 90005
 90006
 90007
 90008
 90009
 90010
 90011
 90012
 90013
 90014
 90015
 90016
 90017
 90018
 90019
 90020
 90021
 90022
 90023
 90024
 90025
 90026
 90027
 90028
 90029
 90030
 90031
 90032
 90033
 90034
 90035
 90036
 90037
 90038
 90039
 90040
 90041
 90042
 90043
 90044
 90045
 90046
 90047
 90048
 90049
 90050
 90051
 90052
 90053
 90054
 90055
 90056
 90057
 90058
 90059
 90060
 90061
 90062
 90063
 90064
 90065
 90066
 90067
 90068
 90069
 90070
 90071
 90072
 90073
 90074
 90075
 90076
 90077
 90078
 90079
 90080
 90081
 90082
 90083
 90084
 90085
 90086
 90087
 90088
 90089
 90090
 90091
 90092
 90093
 90094
 90095
 90096
 90097
 90098
 90099
 90100
 90101
 90102
 90103
 90104
 90105
 90106
 90107
 90108
 90109
 90110
 90111
 90112
 90113
 90114
 90115
 90116
 90117
 90118
 90119
 90120
 90121
 90122
 90123
 90124
 90125
 90126
 90127
 90128
 90129
 90130
 90131
 90132
 90133
 90134
 90135
 90136
 90137
 90138
 90139
 90140
 90141
 90142
 90143
 90144
 90145
 90146
 90147
 90148
 90149
 90150
 90151
 90152
 90153
 90154
 90155
 90156
 90157
 90158
 90159
 90160
 90161
 90162
 90163
 90164
 90165
 90166
 90167
 90168
 90169
 90170
 90171
 90172
 90173
 90174
 90175
 90176
 90177
 90178
 90179
 90180
 90181
 90182
 90183
 90184
 90185
 90186
 90187
 90188
 90189
 90190
 90191
 90192
 90193
 90194
 90195
 90196
 90197
 90198
 90199
 90200
 90201
 90202
 90203
 90204
 90205
 90206
 90207
 90208
 90209
 90210
 90211
 90212
 90213
 90214
 90215
 90216
 90217
 90218
 90219
 90220
 90221
 90222
 90223
 90224
 90225
 90226
 90227
 90228
 90229
 90230
 90231
 90232
 90233
 90234
 90235
 90236
 90237
 90238
 90239
 90240
 90241
 90242
 90243
 90244
 90245
 90246
 90247
 90248
 90249
 90250
 90251
 90252
 90253
 90254
 90255
 90256
 90257
 90258
 90259
 90260
 90261
 90262
 90263
 90264
 90265
 90266
 90267
 90268
 90269
 90270
 90271
 90272
 90273
 90274
 90275
 90276
 90277
 90278
 90279
 90280
 90281
 90282
 90283
 90284
 90285
 90286
 90287
 90288
 90289
 90290
 90291
 90292
 90293
 90294
 90295
 90296
 90297
 90298
 90299
 90300
 90301
 90302
 90303
 90304
 90305
 90306
 90307
 90308
 90309
 90310
 90311
 90312
 90313
 90314
 90315
 90316
 90317
 90318
 90319
 90320
 90321
 90322
 90323
 90324
 90325
 90326
 90327
 90328
 90329
 90330
 90331
 90332
 90333
 90334
 90335
 90336
 90337
 90338
 90339
 90340
 90341
 90342
 90343
 90344
 90345
 90346
 90347
 90348
 90349
 90350
 90351
 90352
 90353
 90354
 90355
 90356
 90357
 90358
 90359
 90360
 90361
 90362
 90363
 90364
 90365
 90366
 90367
 90368
 90369
 90370
 90371
 90372
 90373
 90374
 90375
 90376
 90377
 90378
 90379
 90380
 90381
 90382
 90383
 90384
 90385
 90386
 90387
 90388
 90389
 90390
 90391
 90392
 90393
 90394
 90395
 90396
 90397
 90398
 90399
 90400
 90401
 90402
 90403
 90404
 90405
 90406
 90407
 90408
 90409
 90410
 90411
 90412
 90413
 90414
 90415
 90416
 90417
 90418
 90419
 90420
 90421
 90422
 90423
 90424
 90425
 90426
 90427
 90428
 90429
 90430
 90431
 90432
 90433
 90434
 90435
 90436
 90437
 90438
 90439
 90440
 90441
 90442
 90443
 90444
 90445
 90446
 90447
 90448
 90449
 90450
 90451
 90452
 90453
 90454
 90455
 90456
 90457
 90458
 90459
 90460
 90461
 90462
 90463
 90464
 90465
 90466
 90467
 90468
 90469
 90470
 90471
 90472
 90473
 90474
 90475
 90476
 90477
 90478
 90479
 90480
 90481
 90482
 90483
 90484
 90485
 90486
 90487
 90488
 90489
 90490
 90491
 90492
 90493
 90494
 90495
 90496
 90497
 90498
 90499
 90500
 90501
 90502
 90503
 90504
 90505
 90506
 90507
 90508
 90509
 90510
 90511
 90512
 90513
 90514
 90515
 90516
 90517
 90518
 90519
 90520
 90521
 90522
 90523
 90524
 90525
 90526
 90527
 90528
 90529
 90530
 90531
 90532
 90533
 90534
 90535
 90536
 90537
 90538
 90539
 90540
 90541
 90542
 90543
 90544
 90545
 90546
 90547
 90548
 90549
 90550
 90551
 90552
 90553
 90554
 90555
 90556
 90557
 90558
 90559
 90560
 90561
 90562
 90563
 90564
 90565
 90566
 90567
 90568
 90569
 90570
 90571
 90572
 90573
 90574
 90575
 90576
 90577
 90578
 90579
 90580
 90581
 90582
 90583
 90584
 90585
 90586
 90587
 90588
 90589
 90590
 90591
 90592
 90593
 90594
 90595
 90596
 90597
 90598
 90599
 90600
 90601
 90602
 90603
 90604
 90605
 90606
 90607
 90608
 90609
 90610
 90611
 90612
 90613
 90614
 90615
 90616
 90617
 90618
 90619
 90620
 90621
 90622
 90623
 90624
 90625
 90626
 90627
 90628
 90629
 90630
 90631
 90632
 90633
 90634
 90635
 90636
 90637
 90638
 90639
 90640
 90641
 90642
 90643
 90644
 90645
 90646
 90647
 90648
 90649
 90650
 90651
 90652
 90653
 90654
 90655
 90656
 90657
 90658
 90659
 90660
 90661
 90662
 90663
 90664
 90665
 90666
 90667
 90668
 90669
 90670
 90671
 90672
 90673
 90674
 90675
 90676
 90677
 90678
 90679
 90680
 90681
 90682
 90683
 90684
 90685
 90686
 90687
 90688
 90689
 90690
 90691
 90692
 90693
 90694
 90695
 90696
 90697
 90698
 90699
 90700
 90701
 90702
 90703
 90704
 90705
 90706
 90707
 90708
 90709
 90710
 90711
 90712
 90713
 90714
 90715
 90716
 90717
 90718
 90719
 90720
 90721
 90722
 90723
 90724
 90725
 90726
 90727
 90728
 90729
 90730
 90731
 90732
 90733
 90734
 90735
 90736
 90737
 90738
 90739
 90740
 90741
 90742
 90743
 90744
 90745
 90746
 90747
 90748
 90749
 90750
 90751
 90752
 90753
 90754
 90755
 90756
 90757
 90758
 90759
 90760
 90761
 90762
 90763
 90764
 90765
 90766
 90767
 90768
 90769
 90770
 90771
 90772
 90773
 90774
 90775
 90776
 90777
 90778
 90779
 90780
 90781
 90782
 90783
 90784
 90785
 90786
 90787
 90788
 90789
 90790
 90791
 90792
 90793
 90794
 90795
 90796
 90797
 90798
 90799
 90800
 90801
 90802
 90803
 90804
 90805
 90806
 90807
 90808
 90809
 90810
 90811
 90812
 90813
 90814
 90815
 90816
 90817
 90818
 90819
 90820
 90821
 90822
 90823
 90824
 90825
 90826
 90827
 90828
 90829
 90830
 90831
 90832
 90833
 90834
 90835
 90836
 90837
 90838
 90839
 90840
 90841
 90842
 90843
 90844
 90845
 90846
 90847
 90848
 90849
 90850
 90851
 90852
 90853
 90854
 90855
 90856
 90857
 90858
 90859
 90860
 90861
 90862
 90863
 90864
 90865
 90866
 90867
 90868
 90869
 90870
 90871
 90872
 90873
 90874
 90875
 90876
 90877
 90878
 90879
 90880
 90881
 90882
 90883
 90884
 90885
 90886
 90887
 90888
 90889
 90890
 90891
 90892
 90893
 90894
 90895
 90896
 90897
 90898
 90899
 90900
 90901
 90902
 90903
 90904
 90905
 90906
 90907
 90908
 90909
 90910
 90911
 90912
 90913
 90914
 90915
 90916
 90917
 90918
 90919
 90920
 90921
 90922
 90923
 90924
 90925
 90926
 90927
 90928
 90929
 90930
 90931
 90932
 90933
 90934
 90935
 90936
 90937
 90938
 90939
 90940
 90941
 90942
 90943
 90944
 90945
 90946
 90947
 90948
 90949
 90950
 90951
 90952
 90953
 90954
 90955
 90956
 90957
 90958
 90959
 90960
 90961
 90962
 90963
 90964
 90965
 90966
 90967
 90968
 90969
 90970
 90971
 90972
 90973
 90974
 90975
 90976
 90977
 90978
 90979
 90980
 90981
 90982
 90983
 90984
 90985
 90986
 90987
 90988
 90989
 90990
 90991
 90992
 90993
 90994
 90995
 90996
 90997
 90998
 90999
 91000
 91001
 91002
 91003
 91004
 91005
 91006
 91007
 91008
 91009
 91010
 91011
 91012
 91013
 91014
 91015
 91016
 91017
 91018
 91019
 91020
 91021
 91022
 91023
 91024
 91025
 91026
 91027
 91028
 91029
 91030
 91031
 91032
 91033
 91034
 91035
 91036
 91037
 91038
 91039
 91040
 91041
 91042
 91043
 91044
 91045
 91046
 91047
 91048
 91049
 91050
 91051
 91052
 91053
 91054
 91055
 91056
 91057
 91058
 91059
 91060
 91061
 91062
 91063
 91064
 91065
 91066
 91067
 91068
 91069
 91070
 91071
 91072
 91073
 91074
 91075
 91076
 91077
 91078
 91079
 91080
 91081
 91082
 91083
 91084
 91085
 91086
 91087
 91088
 91089
 91090
 91091
 91092
 91093
 91094
 91095
 91096
 91097
 91098
 91099
 91100
 91101
 91102
 91103
 91104
 91105
 91106
 91107
 91108
 91109
 91110
 91111
 91112
 91113
 91114
 91115
 91116
 91117
 91118
 91119
 91120
 91121
 91122
 91123
 91124
 91125
 91126
 91127
 91128
 91129
 91130
 91131
 91132
 91133
 91134
 91135
 91136
 91137
 91138
 91139
 91140
 91141
 91142
 91143
 91144
 91145
 91146
 91147
 91148
 91149
 91150
 91151
 91152
 91153
 91154
 91155
 91156
 91157
 91158
 91159
 91160
 91161
 91162
 91163
 91164
 91165
 91166
 91167
 91168
 91169
 91170
 91171
 91172
 91173
 91174
 91175
 91176
 91177
 91178
 91179
 91180
 91181
 91182
 91183
 91184
 91185
 91186
 91187
 91188
 91189
 91190
 91191
 91192
 91193
 91194
 91195
 91196
 91197
 91198
 91199
 91200
 91201
 91202
 91203
 91204
 91205
 91206
 91207
 91208
 91209
 91210
 91211
 91212
 91213
 91214
 91215
 91216
 91217
 91218
 91219
 91220
 91221
 91222
 91223
 91224
 91225
 91226
 91227
 91228
 91229
 91230
 91231
 91232
 91233
 91234
 91235
 91236
 91237
 91238
 91239
 91240
 91241
 91242
 91243
 91244
 91245
 91246
 91247
 91248
 91249
 91250
 91251
 91252
 91253
 91254
 91255
 91256
 91257
 91258
 91259
 91260
 91261
 91262
 91263
 91264
 91265
 91266
 91267
 91268
 91269
 91270
 91271
 91272
 91273
 91274
 91275
 91276
 91277
 91278
 91279
 91280
 91281
 91282
 91283
 91284
 91285
 91286
 91287
 91288
 91289
 91290
 91291
 91292
 91293
 91294
 91295
 91296
 91297
 91298
 91299
 91300
 91301
 91302
 91303
 91304
 91305
 91306
 91307
 91308
 91309
 91310
 91311
 91312
 91313
 91314
 91315
 91316
 91317
 91318
 91319
 91320
 91321
 91322
 91323
 91324
 91325
 91326
 91327
 91328
 91329
 91330
 91331
 91332
 91333
 91334
 91335
 91336
 91337
 91338
 91339
 91340
 91341
 91342
 91343
 91344
 91345
 91346
 91347
 91348
 91349
 91350
 91351
 91352
 91353
 91354
 91355
 91356
 91357
 91358
 91359
 91360
 91361
 91362
 91363
 91364
 91365
 91366
 91367
 91368
 91369
 91370
 91371
 91372
 91373
 91374
 91375
 91376
 91377
 91378
 91379
 91380
 91381
 91382
 91383
 91384
 91385
 91386
 91387
 91388
 91389
 91390
 91391
 91392
 91393
 91394
 91395
 91396
 91397
 91398
 91399
 91400
 91401
 91402
 91403
 91404
 91405
 91406
 91407
 91408
 91409
 91410
 91411
 91412
 91413
 91414
 91415
 91416
 91417
 91418
 91419
 91420
 91421
 91422
 91423
 91424
 91425
 91426
 91427
 91428
 91429
 91430
 91431
 91432
 91433
 91434
 91435
 91436
 91437
 91438
 91439
 91440
 91441
 91442
 91443
 91444
 91445
 91446
 91447
 91448
 91449
 91450
 91451
 91452
 91453
 91454
 91455
 91456
 91457
 91458
 91459
 91460
 91461
 91462
 91463
 91464
 91465
 91466
 91467
 91468
 91469
 91470
 91471
 91472
 91473
 91474
 91475
 91476
 91477
 91478
 91479
 91480
 91481
 91482
 91483
 91484
 91485
 91486
 91487
 91488
 91489
 91490
 91491
 91492
 91493
 91494
 91495
 91496
 91497
 91498
 91499
 91500
 91501
 91502
 91503
 91504
 91505
 91506
 91507
 91508
 91509
 91510
 91511
 91512
 91513
 91514
 91515
 91516
 91517
 91518
 91519
 91520
 91521
 91522
 91523
 91524
 91525
 91526
 91527
 91528
 91529
 91530
 91531
 91532
 91533
 91534
 91535
 91536
 91537
 91538
 91539
 91540
 91541
 91542
 91543
 91544
 91545
 91546
 91547
 91548
 91549
 91550
 91551
 91552
 91553
 91554
 91555
 91556
 91557
 91558
 91559
 91560
 91561
 91562
 91563
 91564
 91565
 91566
 91567
 91568
 91569
 91570
 91571
 91572
 91573
 91574
 91575
 91576
 91577
 91578
 91579
 91580
 91581
 91582
 91583
 91584
 91585
 91586
 91587
 91588
 91589
 91590
 91591
 91592
 91593
 91594
 91595
 91596
 91597
 91598
 91599
 91600
 91601
 91602
 91603
 91604
 91605
 91606
 91607
 91608
 91609
 91610
 91611
 91612
 91613
 91614
 91615
 91616
 91617
 91618
 91619
 91620
 91621
 91622
 91623
 91624
 91625
 91626
 91627
 91628
 91629
 91630
 91631
 91632
 91633
 91634
 91635
 91636
 91637
 91638
 91639
 91640
 91641
 91642
 91643
 91644
 91645
 91646
 91647
 91648
 91649
 91650
 91651
 91652
 91653
 91654
 91655
 91656
 91657
 91658
 91659
 91660
 91661
 91662
 91663
 91664
 91665
 91666
 91667
 91668
 91669
 91670
 91671
 91672
 91673
 91674
 91675
 91676
 91677
 91678
 91679
 91680
 91681
 91682
 91683
 91684
 91685
 91686
 91687
 91688
 91689
 91690
 91691
 91692
 91693
 91694
 91695
 91696
 91697
 91698
 91699
 91700
 91701
 91702
 91703
 91704
 91705
 91706
 91707
 91708
 91709
 91710
 91711
 91712
 91713
 91714
 91715
 91716
 91717
 91718
 91719
 91720
 91721
 91722
 91723
 91724
 91725
 91726
 91727
 91728
 91729
 91730
 91731
 91732
 91733
 91734
 91735
 91736
 91737
 91738
 91739
 91740
 91741
 91742
 91743
 91744
 91745
 91746
 91747
 91748
 91749
 91750
 91751
 91752
 91753
 91754
 91755
 91756
 91757
 91758
 91759
 91760
 91761
 91762
 91763
 91764
 91765
 91766
 91767
 91768
 91769
 91770
 91771
 91772
 91773
 91774
 91775
 91776
 91777
 91778
 91779
 91780
 91781
 91782
 91783
 91784
 91785
 91786
 91787
 91788
 91789
 91790
 91791
 91792
 91793
 91794
 91795
 91796
 91797
 91798
 91799
 91800
 91801
 91802
 91803
 91804
 91805
 91806
 91807
 91808
 91809
 91810
 91811
 91812
 91813
 91814
 91815
 91816
 91817
 91818
 91819
 91820
 91821
 91822
 91823
 91824
 91825
 91826
 91827
 91828
 91829
 91830
 91831
 91832
 91833
 91834
 91835
 91836
 91837
 91838
 91839
 91840
 91841
 91842
 91843
 91844
 91845
 91846
 91847
 91848
 91849
 91850
 91851
 91852
 91853
 91854
 91855
 91856
 91857
 91858
 91859
 91860
 91861
 91862
 91863
 91864
 91865
 91866
 91867
 91868
 91869
 91870
 91871
 91872
 91873
 91874
 91875
 91876
 91877
 91878
 91879
 91880
 91881
 91882
 91883
 91884
 91885
 91886
 91887
 91888
 91889
 91890
 91891
 91892
 91893
 91894
 91895
 91896
 91897
 91898
 91899
 91900
 91901
 91902
 91903
 91904
 91905
 91906
 91907
 91908
 91909
 91910
 91911
 91912
 91913
 91914
 91915
 91916
 91917
 91918
 91919
 91920
 91921
 91922
 91923
 91924
 91925
 91926
 91927
 91928
 91929
 91930
 91931
 91932
 91933
 91934
 91935
 91936
 91937
 91938
 91939
 91940
 91941
 91942
 91943
 91944
 91945
 91946
 91947
 91948
 91949
 91950
 91951
 91952
 91953
 91954
 91955
 91956
 91957
 91958
 91959
 91960
 91961
 91962
 91963
 91964
 91965
 91966
 91967
 91968
 91969
 91970
 91971
 91972
 91973
 91974
 91975
 91976
 91977
 91978
 91979
 91980
 91981
 91982
 91983
 91984
 91985
 91986
 91987
 91988
 91989
 91990
 91991
 91992
 91993
 91994
 91995
 91996
 91997
 91998
 91999
 92000
 92001
 92002
 92003
 92004
 92005
 92006
 92007
 92008
 92009
 92010
 92011
 92012
 92013
 92014
 92015
 92016
 92017
 92018
 92019
 92020
 92021
 92022
 92023
 92024
 92025
 92026
 92027
 92028
 92029
 92030
 92031
 92032
 92033
 92034
 92035
 92036
 92037
 92038
 92039
 92040
 92041
 92042
 92043
 92044
 92045
 92046
 92047
 92048
 92049
 92050
 92051
 92052
 92053
 92054
 92055
 92056
 92057
 92058
 92059
 92060
 92061
 92062
 92063
 92064
 92065
 92066
 92067
 92068
 92069
 92070
 92071
 92072
 92073
 92074
 92075
 92076
 92077
 92078
 92079
 92080
 92081
 92082
 92083
 92084
 92085
 92086
 92087
 92088
 92089
 92090
 92091
 92092
 92093
 92094
 92095
 92096
 92097
 92098
 92099
 92100
 92101
 92102
 92103
 92104
 92105
 92106
 92107
 92108
 92109
 92110
 92111
 92112
 92113
 92114
 92115
 92116
 92117
 92118
 92119
 92120
 92121
 92122
 92123
 92124
 92125
 92126
 92127
 92128
 92129
 92130
 92131
 92132
 92133
 92134
 92135
 92136
 92137
 92138
 92139
 92140
 92141
 92142
 92143
 92144
 92145
 92146
 92147
 92148
 92149
 92150
 92151
 92152
 92153
 92154
 92155
 92156
 92157
 92158
 92159
 92160
 92161
 92162
 92163
 92164
 92165
 92166
 92167
 92168
 92169
 92170
 92171
 92172
 92173
 92174
 92175
 92176
 92177
 92178
 92179
 92180
 92181
 92182
 92183
 92184
 92185
 92186
 92187
 92188
 92189
 92190
 92191
 92192
 92193
 92194
 92195
 92196
 92197
 92198
 92199
 92200
 92201
 92202
 92203
 92204
 92205
 92206
 92207
 92208
 92209
 92210
 92211
 92212
 92213
 92214
 92215
 92216
 92217
 92218
 92219
 92220
 92221
 92222
 92223
 92224
 92225
 92226
 92227
 92228
 92229
 92230
 92231
 92232
 92233
 92234
 92235
 92236
 92237
 92238
 92239
 92240
 92241
 92242
 92243
 92244
 92245
 92246
 92247
 92248
 92249
 92250
 92251
 92252
 92253
 92254
 92255
 92256
 92257
 92258
 92259
 92260
 92261
 92262
 92263
 92264
 92265
 92266
 92267
 92268
 92269
 92270
 92271
 92272
 92273
 92274
 92275
 92276
 92277
 92278
 92279
 92280
 92281
 92282
 92283
 92284
 92285
 92286
 92287
 92288
 92289
 92290
 92291
 92292
 92293
 92294
 92295
 92296
 92297
 92298
 92299
 92300
 92301
 92302
 92303
 92304
 92305
 92306
 92307
 92308
 92309
 92310
 92311
 92312
 92313
 92314
 92315
 92316
 92317
 92318
 92319
 92320
 92321
 92322
 92323
 92324
 92325
 92326
 92327
 92328
 92329
 92330
 92331
 92332
 92333
 92334
 92335
 92336
 92337
 92338
 92339
 92340
 92341
 92342
 92343
 92344
 92345
 92346
 92347
 92348
 92349
 92350
 92351
 92352
 92353
 92354
 92355
 92356
 92357
 92358
 92359
 92360
 92361
 92362
 92363
 92364
 92365
 92366
 92367
 92368
 92369
 92370
 92371
 92372
 92373
 92374
 92375
 92376
 92377
 92378
 92379
 92380
 92381
 92382
 92383
 92384
 92385
 92386
 92387
 92388
 92389
 92390
 92391
 92392
 92393
 92394
 92395
 92396
 92397
 92398
 92399
 92400
 92401
 92402
 92403
 92404
 92405
 92406
 92407
 92408
 92409
 92410
 92411
 92412
 92413
 92414
 92415
 92416
 92417
 92418
 92419
 92420
 92421
 92422
 92423
 92424
 92425
 92426
 92427
 92428
 92429
 92430
 92431
 92432
 92433
 92434
 92435
 92436
 92437
 92438
 92439
 92440
 92441
 92442
 92443
 92444
 92445
 92446
 92447
 92448
 92449
 92450
 92451
 92452
 92453
 92454
 92455
 92456
 92457
 92458
 92459
 92460
 92461
 92462
 92463
 92464
 92465
 92466
 92467
 92468
 92469
 92470
 92471
 92472
 92473
 92474
 92475
 92476
 92477
 92478
 92479
 92480
 92481
 92482
 92483
 92484
 92485
 92486
 92487
 92488
 92489
 92490
 92491
 92492
 92493
 92494
 92495
 92496
 92497
 92498
 92499
 92500
 92501
 92502
 92503
 92504
 92505
 92506
 92507
 92508
 92509
 92510
 92511
 92512
 92513
 92514
 92515
 92516
 92517
 92518
 92519
 92520
 92521
 92522
 92523
 92524
 92525
 92526
 92527
 92528
 92529
 92530
 92531
 92532
 92533
 92534
 92535
 92536
 92537
 92538
 92539
 92540
 92541
 92542
 92543
 92544
 92545
 92546
 92547
 92548
 92549
 92550
 92551
 92552
 92553
 92554
 92555
 92556
 92557
 92558
 92559
 92560
 92561
 92562
 92563
 92564
 92565
 92566
 92567
 92568
 92569
 92570
 92571
 92572
 92573
 92574
 92575
 92576
 92577
 92578
 92579
 92580
 92581
 92582
 92583
 92584
 92585
 92586
 92587
 92588
 92589
 92590
 92591
 92592
 92593
 92594
 92595
 92596
 92597
 92598
 92599
 92600
 92601
 92602
 92603
 92604
 92605
 92606
 92607
 92608
 92609
 92610
 92611
 92612
 92613
 92614
 92615
 92616
 92617
 92618
 92619
 92620
 92621
 92622
 92623
 92624
 92625
 92626
 92627
 92628
 92629
 92630
 92631
 92632
 92633
 92634
 92635
 92636
 92637
 92638
 92639
 92640
 92641
 92642
 92643
 92644
 92645
 92646
 92647
 92648
 92649
 92650
 92651
 92652
 92653
 92654
 92655
 92656
 92657
 92658
 92659
 92660
 92661
 92662
 92663
 92664
 92665
 92666
 92667
 92668
 92669
 92670
 92671
 92672
 92673
 92674
 92675
 92676
 92677
 92678
 92679
 92680
 92681
 92682
 92683
 92684
 92685
 92686
 92687
 92688
 92689
 92690
 92691
 92692
 92693
 92694
 92695
 92696
 92697
 92698
 92699
 92700
 92701
 92702
 92703
 92704
 92705
 92706
 92707
 92708
 92709
 92710
 92711
 92712
 92713
 92714
 92715
 92716
 92717
 92718
 92719
 92720
 92721
 92722
 92723
 92724
 92725
 92726
 92727
 92728
 92729
 92730
 92731
 92732
 92733
 92734
 92735
 92736
 92737
 92738
 92739
 92740
 92741
 92742
 92743
 92744
 92745
 92746
 92747
 92748
 92749
 92750
 92751
 92752
 92753
 92754
 92755
 92756
 92757
 92758
 92759
 92760
 92761
 92762
 92763
 92764
 92765
 92766
 92767
 92768
 92769
 92770
 92771
 92772
 92773
 92774
 92775
 92776
 92777
 92778
 92779
 92780
 92781
 92782
 92783
 92784
 92785
 92786
 92787
 92788
 92789
 92790
 92791
 92792
 92793
 92794
 92795
 92796
 92797
 92798
 92799
 92800
 92801
 92802
 92803
 92804
 92805
 92806
 92807
 92808
 92809
 92810
 92811
 92812
 92813
 92814
 92815
 92816
 92817
 92818
 92819
 92820
 92821
 92822
 92823
 92824
 92825
 92826
 92827
 92828
 92829
 92830
 92831
 92832
 92833
 92834
 92835
 92836
 92837
 92838
 92839
 92840
 92841
 92842
 92843
 92844
 92845
 92846
 92847
 92848
 92849
 92850
 92851
 92852
 92853
 92854
 92855
 92856
 92857
 92858
 92859
 92860
 92861
 92862
 92863
 92864
 92865
 92866
 92867
 92868
 92869
 92870
 92871
 92872
 92873
 92874
 92875
 92876
 92877
 92878
 92879
 92880
 92881
 92882
 92883
 92884
 92885
 92886
 92887
 92888
 92889
 92890
 92891
 92892
 92893
 92894
 92895
 92896
 92897
 92898
 92899
 92900
 92901
 92902
 92903
 92904
 92905
 92906
 92907
 92908
 92909
 92910
 92911
 92912
 92913
 92914
 92915
 92916
 92917
 92918
 92919
 92920
 92921
 92922
 92923
 92924
 92925
 92926
 92927
 92928
 92929
 92930
 92931
 92932
 92933
 92934
 92935
 92936
 92937
 92938
 92939
 92940
 92941
 92942
 92943
 92944
 92945
 92946
 92947
 92948
 92949
 92950
 92951
 92952
 92953
 92954
 92955
 92956
 92957
 92958
 92959
 92960
 92961
 92962
 92963
 92964
 92965
 92966
 92967
 92968
 92969
 92970
 92971
 92972
 92973
 92974
 92975
 92976
 92977
 92978
 92979
 92980
 92981
 92982
 92983
 92984
 92985
 92986
 92987
 92988
 92989
 92990
 92991
 92992
 92993
 92994
 92995
 92996
 92997
 92998
 92999
 93000
 93001
 93002
 93003
 93004
 93005
 93006
 93007
 93008
 93009
 93010
 93011
 93012
 93013
 93014
 93015
 93016
 93017
 93018
 93019
 93020
 93021
 93022
 93023
 93024
 93025
 93026
 93027
 93028
 93029
 93030
 93031
 93032
 93033
 93034
 93035
 93036
 93037
 93038
 93039
 93040
 93041
 93042
 93043
 93044
 93045
 93046
 93047
 93048
 93049
 93050
 93051
 93052
 93053
 93054
 93055
 93056
 93057
 93058
 93059
 93060
 93061
 93062
 93063
 93064
 93065
 93066
 93067
 93068
 93069
 93070
 93071
 93072
 93073
 93074
 93075
 93076
 93077
 93078
 93079
 93080
 93081
 93082
 93083
 93084
 93085
 93086
 93087
 93088
 93089
 93090
 93091
 93092
 93093
 93094
 93095
 93096
 93097
 93098
 93099
 93100
 93101
 93102
 93103
 93104
 93105
 93106
 93107
 93108
 93109
 93110
 93111
 93112
 93113
 93114
 93115
 93116
 93117
 93118
 93119
 93120
 93121
 93122
 93123
 93124
 93125
 93126
 93127
 93128
 93129
 93130
 93131
 93132
 93133
 93134
 93135
 93136
 93137
 93138
 93139
 93140
 93141
 93142
 93143
 93144
 93145
 93146
 93147
 93148
 93149
 93150
 93151
 93152
 93153
 93154
 93155
 93156
 93157
 93158
 93159
 93160
 93161
 93162
 93163
 93164
 93165
 93166
 93167
 93168
 93169
 93170
 93171
 93172
 93173
 93174
 93175
 93176
 93177
 93178
 93179
 93180
 93181
 93182
 93183
 93184
 93185
 93186
 93187
 93188
 93189
 93190
 93191
 93192
 93193
 93194
 93195
 93196
 93197
 93198
 93199
 93200
 93201
 93202
 93203
 93204
 93205
 93206
 93207
 93208
 93209
 93210
 93211
 93212
 93213
 93214
 93215
 93216
 93217
 93218
 93219
 93220
 93221
 93222
 93223
 93224
 93225
 93226
 93227
 93228
 93229
 93230
 93231
 93232
 93233
 93234
 93235
 93236
 93237
 93238
 93239
 93240
 93241
 93242
 93243
 93244
 93245
 93246
 93247
 93248
 93249
 93250
 93251
 93252
 93253
 93254
 93255
 93256
 93257
 93258
 93259
 93260
 93261
 93262
 93263
 93264
 93265
 93266
 93267
 93268
 93269
 93270
 93271
 93272
 93273
 93274
 93275
 93276
 93277
 93278
 93279
 93280
 93281
 93282
 93283
 93284
 93285
 93286
 93287
 93288
 93289
 93290
 93291
 93292
 93293
 93294
 93295
 93296
 93297
 93298
 93299
 93300
 93301
 93302
 93303
 93304
 93305
 93306
 93307
 93308
 93309
 93310
 93311
 93312
 93313
 93314
 93315
 93316
 93317
 93318
 93319
 93320
 93321
 93322
 93323
 93324
 93325
 93326
 93327
 93328
 93329
 93330
 93331
 93332
 93333
 93334
 93335
 93336
 93337
 93338
 93339
 93340
 93341
 93342
 93343
 93344
 93345
 93346
 93347
 93348
 93349
 93350
 93351
 93352
 93353
 93354
 93355
 93356
 93357
 93358
 93359
 93360
 93361
 93362
 93363
 93364
 93365
 93366
 93367
 93368
 93369
 93370
 93371
 93372
 93373
 93374
 93375
 93376
 93377
 93378
 93379
 93380
 93381
 93382
 93383
 93384
 93385
 93386
 93387
 93388
 93389
 93390
 93391
 93392
 93393
 93394
 93395
 93396
 93397
 93398
 93399
 93400
 93401
 93402
 93403
 93404
 93405
 93406
 93407
 93408
 93409
 93410
 93411
 93412
 93413
 93414
 93415
 93416
 93417
 93418
 93419
 93420
 93421
 93422
 93423
 93424
 93425
 93426
 93427
 93428
 93429
 93430
 93431
 93432
 93433
 93434
 93435
 93436
 93437
 93438
 93439
 93440
 93441
 93442
 93443
 93444
 93445
 93446
 93447
 93448
 93449
 93450
 93451
 93452
 93453
 93454
 93455
 93456
 93457
 93458
 93459
 93460
 93461
 93462
 93463
 93464
 93465
 93466
 93467
 93468
 93469
 93470
 93471
 93472
 93473
 93474
 93475
 93476
 93477
 93478
 93479
 93480
 93481
 93482
 93483
 93484
 93485
 93486
 93487
 93488
 93489
 93490
 93491
 93492
 93493
 93494
 93495
 93496
 93497
 93498
 93499
 93500
 93501
 93502
 93503
 93504
 93505
 93506
 93507
 93508
 93509
 93510
 93511
 93512
 93513
 93514
 93515
 93516
 93517
 93518
 93519
 93520
 93521
 93522
 93523
 93524
 93525
 93526
 93527
 93528
 93529
 93530
 93531
 93532
 93533
 93534
 93535
 93536
 93537
 93538
 93539
 93540
 93541
 93542
 93543
 93544
 93545
 93546
 93547
 93548
 93549
 93550
 93551
 93552
 93553
 93554
 93555
 93556
 93557
 93558
 93559
 93560
 93561
 93562
 93563
 93564
 93565
 93566
 93567
 93568
 93569
 93570
 93571
 93572
 93573
 93574
 93575
 93576
 93577
 93578
 93579
 93580
 93581
 93582
 93583
 93584
 93585
 93586
 93587
 93588
 93589
 93590
 93591
 93592
 93593
 93594
 93595
 93596
 93597
 93598
 93599
 93600
 93601
 93602
 93603
 93604
 93605
 93606
 93607
 93608
 93609
 93610
 93611
 93612
 93613
 93614
 93615
 93616
 93617
 93618
 93619
 93620
 93621
 93622
 93623
 93624
 93625
 93626
 93627
 93628
 93629
 93630
 93631
 93632
 93633
 93634
 93635
 93636
 93637
 93638
 93639
 93640
 93641
 93642
 93643
 93644
 93645
 93646
 93647
 93648
 93649
 93650
 93651
 93652
 93653
 93654
 93655
 93656
 93657
 93658
 93659
 93660
 93661
 93662
 93663
 93664
 93665
 93666
 93667
 93668
 93669
 93670
 93671
 93672
 93673
 93674
 93675
 93676
 93677
 93678
 93679
 93680
 93681
 93682
 93683
 93684
 93685
 93686
 93687
 93688
 93689
 93690
 93691
 93692
 93693
 93694
 93695
 93696
 93697
 93698
 93699
 93700
 93701
 93702
 93703
 93704
 93705
 93706
 93707
 93708
 93709
 93710
 93711
 93712
 93713
 93714
 93715
 93716
 93717
 93718
 93719
 93720
 93721
 93722
 93723
 93724
 93725
 93726
 93727
 93728
 93729
 93730
 93731
 93732
 93733
 93734
 93735
 93736
 93737
 93738
 93739
 93740
 93741
 93742
 93743
 93744
 93745
 93746
 93747
 93748
 93749
 93750
 93751
 93752
 93753
 93754
 93755
 93756
 93757
 93758
 93759
 93760
 93761
 93762
 93763
 93764
 93765
 93766
 93767
 93768
 93769
 93770
 93771
 93772
 93773
 93774
 93775
 93776
 93777
 93778
 93779
 93780
 93781
 93782
 93783
 93784
 93785
 93786
 93787
 93788
 93789
 93790
 93791
 93792
 93793
 93794
 93795
 93796
 93797
 93798
 93799
 93800
 93801
 93802
 93803
 93804
 93805
 93806
 93807
 93808
 93809
 93810
 93811
 93812
 93813
 93814
 93815
 93816
 93817
 93818
 93819
 93820
 93821
 93822
 93823
 93824
 93825
 93826
 93827
 93828
 93829
 93830
 93831
 93832
 93833
 93834
 93835
 93836
 93837
 93838
 93839
 93840
 93841
 93842
 93843
 93844
 93845
 93846
 93847
 93848
 93849
 93850
 93851
 93852
 93853
 93854
 93855
 93856
 93857
 93858
 93859
 93860
 93861
 93862
 93863
 93864
 93865
 93866
 93867
 93868
 93869
 93870
 93871
 93872
 93873
 93874
 93875
 93876
 93877
 93878
 93879
 93880
 93881
 93882
 93883
 93884
 93885
 93886
 93887
 93888
 93889
 93890
 93891
 93892
 93893
 93894
 93895
 93896
 93897
 93898
 93899
 93900
 93901
 93902
 93903
 93904
 93905
 93906
 93907
 93908
 93909
 93910
 93911
 93912
 93913
 93914
 93915
 93916
 93917
 93918
 93919
 93920
 93921
 93922
 93923
 93924
 93925
 93926
 93927
 93928
 93929
 93930
 93931
 93932
 93933
 93934
 93935
 93936
 93937
 93938
 93939
 93940
 93941
 93942
 93943
 93944
 93945
 93946
 93947
 93948
 93949
 93950
 93951
 93952
 93953
 93954
 93955
 93956
 93957
 93958
 93959
 93960
 93961
 93962
 93963
 93964
 93965
 93966
 93967
 93968
 93969
 93970
 93971
 93972
 93973
 93974
 93975
 93976
 93977
 93978
 93979
 93980
 93981
 93982
 93983
 93984
 93985
 93986
 93987
 93988
 93989
 93990
 93991
 93992
 93993
 93994
 93995
 93996
 93997
 93998
 93999
 94000
 94001
 94002
 94003
 94004
 94005
 94006
 94007
 94008
 94009
 94010
 94011
 94012
 94013
 94014
 94015
 94016
 94017
 94018
 94019
 94020
 94021
 94022
 94023
 94024
 94025
 94026
 94027
 94028
 94029
 94030
 94031
 94032
 94033
 94034
 94035
 94036
 94037
 94038
 94039
 94040
 94041
 94042
 94043
 94044
 94045
 94046
 94047
 94048
 94049
 94050
 94051
 94052
 94053
 94054
 94055
 94056
 94057
 94058
 94059
 94060
 94061
 94062
 94063
 94064
 94065
 94066
 94067
 94068
 94069
 94070
 94071
 94072
 94073
 94074
 94075
 94076
 94077
 94078
 94079
 94080
 94081
 94082
 94083
 94084
 94085
 94086
 94087
 94088
 94089
 94090
 94091
 94092
 94093
 94094
 94095
 94096
 94097
 94098
 94099
 94100
 94101
 94102
 94103
 94104
 94105
 94106
 94107
 94108
 94109
 94110
 94111
 94112
 94113
 94114
 94115
 94116
 94117
 94118
 94119
 94120
 94121
 94122
 94123
 94124
 94125
 94126
 94127
 94128
 94129
 94130
 94131
 94132
 94133
 94134
 94135
 94136
 94137
 94138
 94139
 94140
 94141
 94142
 94143
 94144
 94145
 94146
 94147
 94148
 94149
 94150
 94151
 94152
 94153
 94154
 94155
 94156
 94157
 94158
 94159
 94160
 94161
 94162
 94163
 94164
 94165
 94166
 94167
 94168
 94169
 94170
 94171
 94172
 94173
 94174
 94175
 94176
 94177
 94178
 94179
 94180
 94181
 94182
 94183
 94184
 94185
 94186
 94187
 94188
 94189
 94190
 94191
 94192
 94193
 94194
 94195
 94196
 94197
 94198
 94199
 94200
 94201
 94202
 94203
 94204
 94205
 94206
 94207
 94208
 94209
 94210
 94211
 94212
 94213
 94214
 94215
 94216
 94217
 94218
 94219
 94220
 94221
 94222
 94223
 94224
 94225
 94226
 94227
 94228
 94229
 94230
 94231
 94232
 94233
 94234
 94235
 94236
 94237
 94238
 94239
 94240
 94241
 94242
 94243
 94244
 94245
 94246
 94247
 94248
 94249
 94250
 94251
 94252
 94253
 94254
 94255
 94256
 94257
 94258
 94259
 94260
 94261
 94262
 94263
 94264
 94265
 94266
 94267
 94268
 94269
 94270
 94271
 94272
 94273
 94274
 94275
 94276
 94277
 94278
 94279
 94280
 94281
 94282
 94283
 94284
 94285
 94286
 94287
 94288
 94289
 94290
 94291
 94292
 94293
 94294
 94295
 94296
 94297
 94298
 94299
 94300
 94301
 94302
 94303
 94304
 94305
 94306
 94307
 94308
 94309
 94310
 94311
 94312
 94313
 94314
 94315
 94316
 94317
 94318
 94319
 94320
 94321
 94322
 94323
 94324
 94325
 94326
 94327
 94328
 94329
 94330
 94331
 94332
 94333
 94334
 94335
 94336
 94337
 94338
 94339
 94340
 94341
 94342
 94343
 94344
 94345
 94346
 94347
 94348
 94349
 94350
 94351
 94352
 94353
 94354
 94355
 94356
 94357
 94358
 94359
 94360
 94361
 94362
 94363
 94364
 94365
 94366
 94367
 94368
 94369
 94370
 94371
 94372
 94373
 94374
 94375
 94376
 94377
 94378
 94379
 94380
 94381
 94382
 94383
 94384
 94385
 94386
 94387
 94388
 94389
 94390
 94391
 94392
 94393
 94394
 94395
 94396
 94397
 94398
 94399
 94400
 94401
 94402
 94403
 94404
 94405
 94406
 94407
 94408
 94409
 94410
 94411
 94412
 94413
 94414
 94415
 94416
 94417
 94418
 94419
 94420
 94421
 94422
 94423
 94424
 94425
 94426
 94427
 94428
 94429
 94430
 94431
 94432
 94433
 94434
 94435
 94436
 94437
 94438
 94439
 94440
 94441
 94442
 94443
 94444
 94445
 94446
 94447
 94448
 94449
 94450
 94451
 94452
 94453
 94454
 94455
 94456
 94457
 94458
 94459
 94460
 94461
 94462
 94463
 94464
 94465
 94466
 94467
 94468
 94469
 94470
 94471
 94472
 94473
 94474
 94475
 94476
 94477
 94478
 94479
 94480
 94481
 94482
 94483
 94484
 94485
 94486
 94487
 94488
 94489
 94490
 94491
 94492
 94493
 94494
 94495
 94496
 94497
 94498
 94499
 94500
 94501
 94502
 94503
 94504
 94505
 94506
 94507
 94508
 94509
 94510
 94511
 94512
 94513
 94514
 94515
 94516
 94517
 94518
 94519
 94520
 94521
 94522
 94523
 94524
 94525
 94526
 94527
 94528
 94529
 94530
 94531
 94532
 94533
 94534
 94535
 94536
 94537
 94538
 94539
 94540
 94541
 94542
 94543
 94544
 94545
 94546
 94547
 94548
 94549
 94550
 94551
 94552
 94553
 94554
 94555
 94556
 94557
 94558
 94559
 94560
 94561
 94562
 94563
 94564
 94565
 94566
 94567
 94568
 94569
 94570
 94571
 94572
 94573
 94574
 94575
 94576
 94577
 94578
 94579
 94580
 94581
 94582
 94583
 94584
 94585
 94586
 94587
 94588
 94589
 94590
 94591
 94592
 94593
 94594
 94595
 94596
 94597
 94598
 94599
 94600
 94601
 94602
 94603
 94604
 94605
 94606
 94607
 94608
 94609
 94610
 94611
 94612
 94613
 94614
 94615
 94616
 94617
 94618
 94619
 94620
 94621
 94622
 94623
 94624
 94625
 94626
 94627
 94628
 94629
 94630
 94631
 94632
 94633
 94634
 94635
 94636
 94637
 94638
 94639
 94640
 94641
 94642
 94643
 94644
 94645
 94646
 94647
 94648
 94649
 94650
 94651
 94652
 94653
 94654
 94655
 94656
 94657
 94658
 94659
 94660
 94661
 94662
 94663
 94664
 94665
 94666
 94667
 94668
 94669
 94670
 94671
 94672
 94673
 94674
 94675
 94676
 94677
 94678
 94679
 94680
 94681
 94682
 94683
 94684
 94685
 94686
 94687
 94688
 94689
 94690
 94691
 94692
 94693
 94694
 94695
 94696
 94697
 94698
 94699
 94700
 94701
 94702
 94703
 94704
 94705
 94706
 94707
 94708
 94709
 94710
 94711
 94712
 94713
 94714
 94715
 94716
 94717
 94718
 94719
 94720
 94721
 94722
 94723
 94724
 94725
 94726
 94727
 94728
 94729
 94730
 94731
 94732
 94733
 94734
 94735
 94736
 94737
 94738
 94739
 94740
 94741
 94742
 94743
 94744
 94745
 94746
 94747
 94748
 94749
 94750
 94751
 94752
 94753
 94754
 94755
 94756
 94757
 94758
 94759
 94760
 94761
 94762
 94763
 94764
 94765
 94766
 94767
 94768
 94769
 94770
 94771
 94772
 94773
 94774
 94775
 94776
 94777
 94778
 94779
 94780
 94781
 94782
 94783
 94784
 94785
 94786
 94787
 94788
 94789
 94790
 94791
 94792
 94793
 94794
 94795
 94796
 94797
 94798
 94799
 94800
 94801
 94802
 94803
 94804
 94805
 94806
 94807
 94808
 94809
 94810
 94811
 94812
 94813
 94814
 94815
 94816
 94817
 94818
 94819
 94820
 94821
 94822
 94823
 94824
 94825
 94826
 94827
 94828
 94829
 94830
 94831
 94832
 94833
 94834
 94835
 94836
 94837
 94838
 94839
 94840
 94841
 94842
 94843
 94844
 94845
 94846
 94847
 94848
 94849
 94850
 94851
 94852
 94853
 94854
 94855
 94856
 94857
 94858
 94859
 94860
 94861
 94862
 94863
 94864
 94865
 94866
 94867
 94868
 94869
 94870
 94871
 94872
 94873
 94874
 94875
 94876
 94877
 94878
 94879
 94880
 94881
 94882
 94883
 94884
 94885
 94886
 94887
 94888
 94889
 94890
 94891
 94892
 94893
 94894
 94895
 94896
 94897
 94898
 94899
 94900
 94901
 94902
 94903
 94904
 94905
 94906
 94907
 94908
 94909
 94910
 94911
 94912
 94913
 94914
 94915
 94916
 94917
 94918
 94919
 94920
 94921
 94922
 94923
 94924
 94925
 94926
 94927
 94928
 94929
 94930
 94931
 94932
 94933
 94934
 94935
 94936
 94937
 94938
 94939
 94940
 94941
 94942
 94943
 94944
 94945
 94946
 94947
 94948
 94949
 94950
 94951
 94952
 94953
 94954
 94955
 94956
 94957
 94958
 94959
 94960
 94961
 94962
 94963
 94964
 94965
 94966
 94967
 94968
 94969
 94970
 94971
 94972
 94973
 94974
 94975
 94976
 94977
 94978
 94979
 94980
 94981
 94982
 94983
 94984
 94985
 94986
 94987
 94988
 94989
 94990
 94991
 94992
 94993
 94994
 94995
 94996
 94997
 94998
 94999
 95000
 95001
 95002
 95003
 95004
 95005
 95006
 95007
 95008
 95009
 95010
 95011
 95012
 95013
 95014
 95015
 95016
 95017
 95018
 95019
 95020
 95021
 95022
 95023
 95024
 95025
 95026
 95027
 95028
 95029
 95030
 95031
 95032
 95033
 95034
 95035
 95036
 95037
 95038
 95039
 95040
 95041
 95042
 95043
 95044
 95045
 95046
 95047
 95048
 95049
 95050
 95051
 95052
 95053
 95054
 95055
 95056
 95057
 95058
 95059
 95060
 95061
 95062
 95063
 95064
 95065
 95066
 95067
 95068
 95069
 95070
 95071
 95072
 95073
 95074
 95075
 95076
 95077
 95078
 95079
 95080
 95081
 95082
 95083
 95084
 95085
 95086
 95087
 95088
 95089
 95090
 95091
 95092
 95093
 95094
 95095
 95096
 95097
 95098
 95099
 95100
 95101
 95102
 95103
 95104
 95105
 95106
 95107
 95108
 95109
 95110
 95111
 95112
 95113
 95114
 95115
 95116
 95117
 95118
 95119
 95120
 95121
 95122
 95123
 95124
 95125
 95126
 95127
 95128
 95129
 95130
 95131
 95132
 95133
 95134
 95135
 95136
 95137
 95138
 95139
 95140
 95141
 95142
 95143
 95144
 95145
 95146
 95147
 95148
 95149
 95150
 95151
 95152
 95153
 95154
 95155
 95156
 95157
 95158
 95159
 95160
 95161
 95162
 95163
 95164
 95165
 95166
 95167
 95168
 95169
 95170
 95171
 95172
 95173
 95174
 95175
 95176
 95177
 95178
 95179
 95180
 95181
 95182
 95183
 95184
 95185
 95186
 95187
 95188
 95189
 95190
 95191
 95192
 95193
 95194
 95195
 95196
 95197
 95198
 95199
 95200
 95201
 95202
 95203
 95204
 95205
 95206
 95207
 95208
 95209
 95210
 95211
 95212
 95213
 95214
 95215
 95216
 95217
 95218
 95219
 95220
 95221
 95222
 95223
 95224
 95225
 95226
 95227
 95228
 95229
 95230
 95231
 95232
 95233
 95234
 95235
 95236
 95237
 95238
 95239
 95240
 95241
 95242
 95243
 95244
 95245
 95246
 95247
 95248
 95249
 95250
 95251
 95252
 95253
 95254
 95255
 95256
 95257
 95258
 95259
 95260
 95261
 95262
 95263
 95264
 95265
 95266
 95267
 95268
 95269
 95270
 95271
 95272
 95273
 95274
 95275
 95276
 95277
 95278
 95279
 95280
 95281
 95282
 95283
 95284
 95285
 95286
 95287
 95288
 95289
 95290
 95291
 95292
 95293
 95294
 95295
 95296
 95297
 95298
 95299
 95300
 95301
 95302
 95303
 95304
 95305
 95306
 95307
 95308
 95309
 95310
 95311
 95312
 95313
 95314
 95315
 95316
 95317
 95318
 95319
 95320
 95321
 95322
 95323
 95324
 95325
 95326
 95327
 95328
 95329
 95330
 95331
 95332
 95333
 95334
 95335
 95336
 95337
 95338
 95339
 95340
 95341
 95342
 95343
 95344
 95345
 95346
 95347
 95348
 95349
 95350
 95351
 95352
 95353
 95354
 95355
 95356
 95357
 95358
 95359
 95360
 95361
 95362
 95363
 95364
 95365
 95366
 95367
 95368
 95369
 95370
 95371
 95372
 95373
 95374
 95375
 95376
 95377
 95378
 95379
 95380
 95381
 95382
 95383
 95384
 95385
 95386
 95387
 95388
 95389
 95390
 95391
 95392
 95393
 95394
 95395
 95396
 95397
 95398
 95399
 95400
 95401
 95402
 95403
 95404
 95405
 95406
 95407
 95408
 95409
 95410
 95411
 95412
 95413
 95414
 95415
 95416
 95417
 95418
 95419
 95420
 95421
 95422
 95423
 95424
 95425
 95426
 95427
 95428
 95429
 95430
 95431
 95432
 95433
 95434
 95435
 95436
 95437
 95438
 95439
 95440
 95441
 95442
 95443
 95444
 95445
 95446
 95447
 95448
 95449
 95450
 95451
 95452
 95453
 95454
 95455
 95456
 95457
 95458
 95459
 95460
 95461
 95462
 95463
 95464
 95465
 95466
 95467
 95468
 95469
 95470
 95471
 95472
 95473
 95474
 95475
 95476
 95477
 95478
 95479
 95480
 95481
 95482
 95483
 95484
 95485
 95486
 95487
 95488
 95489
 95490
 95491
 95492
 95493
 95494
 95495
 95496
 95497
 95498
 95499
 95500
 95501
 95502
 95503
 95504
 95505
 95506
 95507
 95508
 95509
 95510
 95511
 95512
 95513
 95514
 95515
 95516
 95517
 95518
 95519
 95520
 95521
 95522
 95523
 95524
 95525
 95526
 95527
 95528
 95529
 95530
 95531
 95532
 95533
 95534
 95535
 95536
 95537
 95538
 95539
 95540
 95541
 95542
 95543
 95544
 95545
 95546
 95547
 95548
 95549
 95550
 95551
 95552
 95553
 95554
 95555
 95556
 95557
 95558
 95559
 95560
 95561
 95562
 95563
 95564
 95565
 95566
 95567
 95568
 95569
 95570
 95571
 95572
 95573
 95574
 95575
 95576
 95577
 95578
 95579
 95580
 95581
 95582
 95583
 95584
 95585
 95586
 95587
 95588
 95589
 95590
 95591
 95592
 95593
 95594
 95595
 95596
 95597
 95598
 95599
 95600
 95601
 95602
 95603
 95604
 95605
 95606
 95607
 95608
 95609
 95610
 95611
 95612
 95613
 95614
 95615
 95616
 95617
 95618
 95619
 95620
 95621
 95622
 95623
 95624
 95625
 95626
 95627
 95628
 95629
 95630
 95631
 95632
 95633
 95634
 95635
 95636
 95637
 95638
 95639
 95640
 95641
 95642
 95643
 95644
 95645
 95646
 95647
 95648
 95649
 95650
 95651
 95652
 95653
 95654
 95655
 95656
 95657
 95658
 95659
 95660
 95661
 95662
 95663
 95664
 95665
 95666
 95667
 95668
 95669
 95670
 95671
 95672
 95673
 95674
 95675
 95676
 95677
 95678
 95679
 95680
 95681
 95682
 95683
 95684
 95685
 95686
 95687
 95688
 95689
 95690
 95691
 95692
 95693
 95694
 95695
 95696
 95697
 95698
 95699
 95700
 95701
 95702
 95703
 95704
 95705
 95706
 95707
 95708
 95709
 95710
 95711
 95712
 95713
 95714
 95715
 95716
 95717
 95718
 95719
 95720
 95721
 95722
 95723
 95724
 95725
 95726
 95727
 95728
 95729
 95730
 95731
 95732
 95733
 95734
 95735
 95736
 95737
 95738
 95739
 95740
 95741
 95742
 95743
 95744
 95745
 95746
 95747
 95748
 95749
 95750
 95751
 95752
 95753
 95754
 95755
 95756
 95757
 95758
 95759
 95760
 95761
 95762
 95763
 95764
 95765
 95766
 95767
 95768
 95769
 95770
 95771
 95772
 95773
 95774
 95775
 95776
 95777
 95778
 95779
 95780
 95781
 95782
 95783
 95784
 95785
 95786
 95787
 95788
 95789
 95790
 95791
 95792
 95793
 95794
 95795
 95796
 95797
 95798
 95799
 95800
 95801
 95802
 95803
 95804
 95805
 95806
 95807
 95808
 95809
 95810
 95811
 95812
 95813
 95814
 95815
 95816
 95817
 95818
 95819
 95820
 95821
 95822
 95823
 95824
 95825
 95826
 95827
 95828
 95829
 95830
 95831
 95832
 95833
 95834
 95835
 95836
 95837
 95838
 95839
 95840
 95841
 95842
 95843
 95844
 95845
 95846
 95847
 95848
 95849
 95850
 95851
 95852
 95853
 95854
 95855
 95856
 95857
 95858
 95859
 95860
 95861
 95862
 95863
 95864
 95865
 95866
 95867
 95868
 95869
 95870
 95871
 95872
 95873
 95874
 95875
 95876
 95877
 95878
 95879
 95880
 95881
 95882
 95883
 95884
 95885
 95886
 95887
 95888
 95889
 95890
 95891
 95892
 95893
 95894
 95895
 95896
 95897
 95898
 95899
 95900
 95901
 95902
 95903
 95904
 95905
 95906
 95907
 95908
 95909
 95910
 95911
 95912
 95913
 95914
 95915
 95916
 95917
 95918
 95919
 95920
 95921
 95922
 95923
 95924
 95925
 95926
 95927
 95928
 95929
 95930
 95931
 95932
 95933
 95934
 95935
 95936
 95937
 95938
 95939
 95940
 95941
 95942
 95943
 95944
 95945
 95946
 95947
 95948
 95949
 95950
 95951
 95952
 95953
 95954
 95955
 95956
 95957
 95958
 95959
 95960
 95961
 95962
 95963
 95964
 95965
 95966
 95967
 95968
 95969
 95970
 95971
 95972
 95973
 95974
 95975
 95976
 95977
 95978
 95979
 95980
 95981
 95982
 95983
 95984
 95985
 95986
 95987
 95988
 95989
 95990
 95991
 95992
 95993
 95994
 95995
 95996
 95997
 95998
 95999
 96000
 96001
 96002
 96003
 96004
 96005
 96006
 96007
 96008
 96009
 96010
 96011
 96012
 96013
 96014
 96015
 96016
 96017
 96018
 96019
 96020
 96021
 96022
 96023
 96024
 96025
 96026
 96027
 96028
 96029
 96030
 96031
 96032
 96033
 96034
 96035
 96036
 96037
 96038
 96039
 96040
 96041
 96042
 96043
 96044
 96045
 96046
 96047
 96048
 96049
 96050
 96051
 96052
 96053
 96054
 96055
 96056
 96057
 96058
 96059
 96060
 96061
 96062
 96063
 96064
 96065
 96066
 96067
 96068
 96069
 96070
 96071
 96072
 96073
 96074
 96075
 96076
 96077
 96078
 96079
 96080
 96081
 96082
 96083
 96084
 96085
 96086
 96087
 96088
 96089
 96090
 96091
 96092
 96093
 96094
 96095
 96096
 96097
 96098
 96099
 96100
 96101
 96102
 96103
 96104
 96105
 96106
 96107
 96108
 96109
 96110
 96111
 96112
 96113
 96114
 96115
 96116
 96117
 96118
 96119
 96120
 96121
 96122
 96123
 96124
 96125
 96126
 96127
 96128
 96129
 96130
 96131
 96132
 96133
 96134
 96135
 96136
 96137
 96138
 96139
 96140
 96141
 96142
 96143
 96144
 96145
 96146
 96147
 96148
 96149
 96150
 96151
 96152
 96153
 96154
 96155
 96156
 96157
 96158
 96159
 96160
 96161
 96162
 96163
 96164
 96165
 96166
 96167
 96168
 96169
 96170
 96171
 96172
 96173
 96174
 96175
 96176
 96177
 96178
 96179
 96180
 96181
 96182
 96183
 96184
 96185
 96186
 96187
 96188
 96189
 96190
 96191
 96192
 96193
 96194
 96195
 96196
 96197
 96198
 96199
 96200
 96201
 96202
 96203
 96204
 96205
 96206
 96207
 96208
 96209
 96210
 96211
 96212
 96213
 96214
 96215
 96216
 96217
 96218
 96219
 96220
 96221
 96222
 96223
 96224
 96225
 96226
 96227
 96228
 96229
 96230
 96231
 96232
 96233
 96234
 96235
 96236
 96237
 96238
 96239
 96240
 96241
 96242
 96243
 96244
 96245
 96246
 96247
 96248
 96249
 96250
 96251
 96252
 96253
 96254
 96255
 96256
 96257
 96258
 96259
 96260
 96261
 96262
 96263
 96264
 96265
 96266
 96267
 96268
 96269
 96270
 96271
 96272
 96273
 96274
 96275
 96276
 96277
 96278
 96279
 96280
 96281
 96282
 96283
 96284
 96285
 96286
 96287
 96288
 96289
 96290
 96291
 96292
 96293
 96294
 96295
 96296
 96297
 96298
 96299
 96300
 96301
 96302
 96303
 96304
 96305
 96306
 96307
 96308
 96309
 96310
 96311
 96312
 96313
 96314
 96315
 96316
 96317
 96318
 96319
 96320
 96321
 96322
 96323
 96324
 96325
 96326
 96327
 96328
 96329
 96330
 96331
 96332
 96333
 96334
 96335
 96336
 96337
 96338
 96339
 96340
 96341
 96342
 96343
 96344
 96345
 96346
 96347
 96348
 96349
 96350
 96351
 96352
 96353
 96354
 96355
 96356
 96357
 96358
 96359
 96360
 96361
 96362
 96363
 96364
 96365
 96366
 96367
 96368
 96369
 96370
 96371
 96372
 96373
 96374
 96375
 96376
 96377
 96378
 96379
 96380
 96381
 96382
 96383
 96384
 96385
 96386
 96387
 96388
 96389
 96390
 96391
 96392
 96393
 96394
 96395
 96396
 96397
 96398
 96399
 96400
 96401
 96402
 96403
 96404
 96405
 96406
 96407
 96408
 96409
 96410
 96411
 96412
 96413
 96414
 96415
 96416
 96417
 96418
 96419
 96420
 96421
 96422
 96423
 96424
 96425
 96426
 96427
 96428
 96429
 96430
 96431
 96432
 96433
 96434
 96435
 96436
 96437
 96438
 96439
 96440
 96441
 96442
 96443
 96444
 96445
 96446
 96447
 96448
 96449
 96450
 96451
 96452
 96453
 96454
 96455
 96456
 96457
 96458
 96459
 96460
 96461
 96462
 96463
 96464
 96465
 96466
 96467
 96468
 96469
 96470
 96471
 96472
 96473
 96474
 96475
 96476
 96477
 96478
 96479
 96480
 96481
 96482
 96483
 96484
 96485
 96486
 96487
 96488
 96489
 96490
 96491
 96492
 96493
 96494
 96495
 96496
 96497
 96498
 96499
 96500
 96501
 96502
 96503
 96504
 96505
 96506
 96507
 96508
 96509
 96510
 96511
 96512
 96513
 96514
 96515
 96516
 96517
 96518
 96519
 96520
 96521
 96522
 96523
 96524
 96525
 96526
 96527
 96528
 96529
 96530
 96531
 96532
 96533
 96534
 96535
 96536
 96537
 96538
 96539
 96540
 96541
 96542
 96543
 96544
 96545
 96546
 96547
 96548
 96549
 96550
 96551
 96552
 96553
 96554
 96555
 96556
 96557
 96558
 96559
 96560
 96561
 96562
 96563
 96564
 96565
 96566
 96567
 96568
 96569
 96570
 96571
 96572
 96573
 96574
 96575
 96576
 96577
 96578
 96579
 96580
 96581
 96582
 96583
 96584
 96585
 96586
 96587
 96588
 96589
 96590
 96591
 96592
 96593
 96594
 96595
 96596
 96597
 96598
 96599
 96600
 96601
 96602
 96603
 96604
 96605
 96606
 96607
 96608
 96609
 96610
 96611
 96612
 96613
 96614
 96615
 96616
 96617
 96618
 96619
 96620
 96621
 96622
 96623
 96624
 96625
 96626
 96627
 96628
 96629
 96630
 96631
 96632
 96633
 96634
 96635
 96636
 96637
 96638
 96639
 96640
 96641
 96642
 96643
 96644
 96645
 96646
 96647
 96648
 96649
 96650
 96651
 96652
 96653
 96654
 96655
 96656
 96657
 96658
 96659
 96660
 96661
 96662
 96663
 96664
 96665
 96666
 96667
 96668
 96669
 96670
 96671
 96672
 96673
 96674
 96675
 96676
 96677
 96678
 96679
 96680
 96681
 96682
 96683
 96684
 96685
 96686
 96687
 96688
 96689
 96690
 96691
 96692
 96693
 96694
 96695
 96696
 96697
 96698
 96699
 96700
 96701
 96702
 96703
 96704
 96705
 96706
 96707
 96708
 96709
 96710
 96711
 96712
 96713
 96714
 96715
 96716
 96717
 96718
 96719
 96720
 96721
 96722
 96723
 96724
 96725
 96726
 96727
 96728
 96729
 96730
 96731
 96732
 96733
 96734
 96735
 96736
 96737
 96738
 96739
 96740
 96741
 96742
 96743
 96744
 96745
 96746
 96747
 96748
 96749
 96750
 96751
 96752
 96753
 96754
 96755
 96756
 96757
 96758
 96759
 96760
 96761
 96762
 96763
 96764
 96765
 96766
 96767
 96768
 96769
 96770
 96771
 96772
 96773
 96774
 96775
 96776
 96777
 96778
 96779
 96780
 96781
 96782
 96783
 96784
 96785
 96786
 96787
 96788
 96789
 96790
 96791
 96792
 96793
 96794
 96795
 96796
 96797
 96798
 96799
 96800
 96801
 96802
 96803
 96804
 96805
 96806
 96807
 96808
 96809
 96810
 96811
 96812
 96813
 96814
 96815
 96816
 96817
 96818
 96819
 96820
 96821
 96822
 96823
 96824
 96825
 96826
 96827
 96828
 96829
 96830
 96831
 96832
 96833
 96834
 96835
 96836
 96837
 96838
 96839
 96840
 96841
 96842
 96843
 96844
 96845
 96846
 96847
 96848
 96849
 96850
 96851
 96852
 96853
 96854
 96855
 96856
 96857
 96858
 96859
 96860
 96861
 96862
 96863
 96864
 96865
 96866
 96867
 96868
 96869
 96870
 96871
 96872
 96873
 96874
 96875
 96876
 96877
 96878
 96879
 96880
 96881
 96882
 96883
 96884
 96885
 96886
 96887
 96888
 96889
 96890
 96891
 96892
 96893
 96894
 96895
 96896
 96897
 96898
 96899
 96900
 96901
 96902
 96903
 96904
 96905
 96906
 96907
 96908
 96909
 96910
 96911
 96912
 96913
 96914
 96915
 96916
 96917
 96918
 96919
 96920
 96921
 96922
 96923
 96924
 96925
 96926
 96927
 96928
 96929
 96930
 96931
 96932
 96933
 96934
 96935
 96936
 96937
 96938
 96939
 96940
 96941
 96942
 96943
 96944
 96945
 96946
 96947
 96948
 96949
 96950
 96951
 96952
 96953
 96954
 96955
 96956
 96957
 96958
 96959
 96960
 96961
 96962
 96963
 96964
 96965
 96966
 96967
 96968
 96969
 96970
 96971
 96972
 96973
 96974
 96975
 96976
 96977
 96978
 96979
 96980
 96981
 96982
 96983
 96984
 96985
 96986
 96987
 96988
 96989
 96990
 96991
 96992
 96993
 96994
 96995
 96996
 96997
 96998
 96999
 97000
 97001
 97002
 97003
 97004
 97005
 97006
 97007
 97008
 97009
 97010
 97011
 97012
 97013
 97014
 97015
 97016
 97017
 97018
 97019
 97020
 97021
 97022
 97023
 97024
 97025
 97026
 97027
 97028
 97029
 97030
 97031
 97032
 97033
 97034
 97035
 97036
 97037
 97038
 97039
 97040
 97041
 97042
 97043
 97044
 97045
 97046
 97047
 97048
 97049
 97050
 97051
 97052
 97053
 97054
 97055
 97056
 97057
 97058
 97059
 97060
 97061
 97062
 97063
 97064
 97065
 97066
 97067
 97068
 97069
 97070
 97071
 97072
 97073
 97074
 97075
 97076
 97077
 97078
 97079
 97080
 97081
 97082
 97083
 97084
 97085
 97086
 97087
 97088
 97089
 97090
 97091
 97092
 97093
 97094
 97095
 97096
 97097
 97098
 97099
 97100
 97101
 97102
 97103
 97104
 97105
 97106
 97107
 97108
 97109
 97110
 97111
 97112
 97113
 97114
 97115
 97116
 97117
 97118
 97119
 97120
 97121
 97122
 97123
 97124
 97125
 97126
 97127
 97128
 97129
 97130
 97131
 97132
 97133
 97134
 97135
 97136
 97137
 97138
 97139
 97140
 97141
 97142
 97143
 97144
 97145
 97146
 97147
 97148
 97149
 97150
 97151
 97152
 97153
 97154
 97155
 97156
 97157
 97158
 97159
 97160
 97161
 97162
 97163
 97164
 97165
 97166
 97167
 97168
 97169
 97170
 97171
 97172
 97173
 97174
 97175
 97176
 97177
 97178
 97179
 97180
 97181
 97182
 97183
 97184
 97185
 97186
 97187
 97188
 97189
 97190
 97191
 97192
 97193
 97194
 97195
 97196
 97197
 97198
 97199
 97200
 97201
 97202
 97203
 97204
 97205
 97206
 97207
 97208
 97209
 97210
 97211
 97212
 97213
 97214
 97215
 97216
 97217
 97218
 97219
 97220
 97221
 97222
 97223
 97224
 97225
 97226
 97227
 97228
 97229
 97230
 97231
 97232
 97233
 97234
 97235
 97236
 97237
 97238
 97239
 97240
 97241
 97242
 97243
 97244
 97245
 97246
 97247
 97248
 97249
 97250
 97251
 97252
 97253
 97254
 97255
 97256
 97257
 97258
 97259
 97260
 97261
 97262
 97263
 97264
 97265
 97266
 97267
 97268
 97269
 97270
 97271
 97272
 97273
 97274
 97275
 97276
 97277
 97278
 97279
 97280
 97281
 97282
 97283
 97284
 97285
 97286
 97287
 97288
 97289
 97290
 97291
 97292
 97293
 97294
 97295
 97296
 97297
 97298
 97299
 97300
 97301
 97302
 97303
 97304
 97305
 97306
 97307
 97308
 97309
 97310
 97311
 97312
 97313
 97314
 97315
 97316
 97317
 97318
 97319
 97320
 97321
 97322
 97323
 97324
 97325
 97326
 97327
 97328
 97329
 97330
 97331
 97332
 97333
 97334
 97335
 97336
 97337
 97338
 97339
 97340
 97341
 97342
 97343
 97344
 97345
 97346
 97347
 97348
 97349
 97350
 97351
 97352
 97353
 97354
 97355
 97356
 97357
 97358
 97359
 97360
 97361
 97362
 97363
 97364
 97365
 97366
 97367
 97368
 97369
 97370
 97371
 97372
 97373
 97374
 97375
 97376
 97377
 97378
 97379
 97380
 97381
 97382
 97383
 97384
 97385
 97386
 97387
 97388
 97389
 97390
 97391
 97392
 97393
 97394
 97395
 97396
 97397
 97398
 97399
 97400
 97401
 97402
 97403
 97404
 97405
 97406
 97407
 97408
 97409
 97410
 97411
 97412
 97413
 97414
 97415
 97416
 97417
 97418
 97419
 97420
 97421
 97422
 97423
 97424
 97425
 97426
 97427
 97428
 97429
 97430
 97431
 97432
 97433
 97434
 97435
 97436
 97437
 97438
 97439
 97440
 97441
 97442
 97443
 97444
 97445
 97446
 97447
 97448
 97449
 97450
 97451
 97452
 97453
 97454
 97455
 97456
 97457
 97458
 97459
 97460
 97461
 97462
 97463
 97464
 97465
 97466
 97467
 97468
 97469
 97470
 97471
 97472
 97473
 97474
 97475
 97476
 97477
 97478
 97479
 97480
 97481
 97482
 97483
 97484
 97485
 97486
 97487
 97488
 97489
 97490
 97491
 97492
 97493
 97494
 97495
 97496
 97497
 97498
 97499
 97500
 97501
 97502
 97503
 97504
 97505
 97506
 97507
 97508
 97509
 97510
 97511
 97512
 97513
 97514
 97515
 97516
 97517
 97518
 97519
 97520
 97521
 97522
 97523
 97524
 97525
 97526
 97527
 97528
 97529
 97530
 97531
 97532
 97533
 97534
 97535
 97536
 97537
 97538
 97539
 97540
 97541
 97542
 97543
 97544
 97545
 97546
 97547
 97548
 97549
 97550
 97551
 97552
 97553
 97554
 97555
 97556
 97557
 97558
 97559
 97560
 97561
 97562
 97563
 97564
 97565
 97566
 97567
 97568
 97569
 97570
 97571
 97572
 97573
 97574
 97575
 97576
 97577
 97578
 97579
 97580
 97581
 97582
 97583
 97584
 97585
 97586
 97587
 97588
 97589
 97590
 97591
 97592
 97593
 97594
 97595
 97596
 97597
 97598
 97599
 97600
 97601
 97602
 97603
 97604
 97605
 97606
 97607
 97608
 97609
 97610
 97611
 97612
 97613
 97614
 97615
 97616
 97617
 97618
 97619
 97620
 97621
 97622
 97623
 97624
 97625
 97626
 97627
 97628
 97629
 97630
 97631
 97632
 97633
 97634
 97635
 97636
 97637
 97638
 97639
 97640
 97641
 97642
 97643
 97644
 97645
 97646
 97647
 97648
 97649
 97650
 97651
 97652
 97653
 97654
 97655
 97656
 97657
 97658
 97659
 97660
 97661
 97662
 97663
 97664
 97665
 97666
 97667
 97668
 97669
 97670
 97671
 97672
 97673
 97674
 97675
 97676
 97677
 97678
 97679
 97680
 97681
 97682
 97683
 97684
 97685
 97686
 97687
 97688
 97689
 97690
 97691
 97692
 97693
 97694
 97695
 97696
 97697
 97698
 97699
 97700
 97701
 97702
 97703
 97704
 97705
 97706
 97707
 97708
 97709
 97710
 97711
 97712
 97713
 97714
 97715
 97716
 97717
 97718
 97719
 97720
 97721
 97722
 97723
 97724
 97725
 97726
 97727
 97728
 97729
 97730
 97731
 97732
 97733
 97734
 97735
 97736
 97737
 97738
 97739
 97740
 97741
 97742
 97743
 97744
 97745
 97746
 97747
 97748
 97749
 97750
 97751
 97752
 97753
 97754
 97755
 97756
 97757
 97758
 97759
 97760
 97761
 97762
 97763
 97764
 97765
 97766
 97767
 97768
 97769
 97770
 97771
 97772
 97773
 97774
 97775
 97776
 97777
 97778
 97779
 97780
 97781
 97782
 97783
 97784
 97785
 97786
 97787
 97788
 97789
 97790
 97791
 97792
 97793
 97794
 97795
 97796
 97797
 97798
 97799
 97800
 97801
 97802
 97803
 97804
 97805
 97806
 97807
 97808
 97809
 97810
 97811
 97812
 97813
 97814
 97815
 97816
 97817
 97818
 97819
 97820
 97821
 97822
 97823
 97824
 97825
 97826
 97827
 97828
 97829
 97830
 97831
 97832
 97833
 97834
 97835
 97836
 97837
 97838
 97839
 97840
 97841
 97842
 97843
 97844
 97845
 97846
 97847
 97848
 97849
 97850
 97851
 97852
 97853
 97854
 97855
 97856
 97857
 97858
 97859
 97860
 97861
 97862
 97863
 97864
 97865
 97866
 97867
 97868
 97869
 97870
 97871
 97872
 97873
 97874
 97875
 97876
 97877
 97878
 97879
 97880
 97881
 97882
 97883
 97884
 97885
 97886
 97887
 97888
 97889
 97890
 97891
 97892
 97893
 97894
 97895
 97896
 97897
 97898
 97899
 97900
 97901
 97902
 97903
 97904
 97905
 97906
 97907
 97908
 97909
 97910
 97911
 97912
 97913
 97914
 97915
 97916
 97917
 97918
 97919
 97920
 97921
 97922
 97923
 97924
 97925
 97926
 97927
 97928
 97929
 97930
 97931
 97932
 97933
 97934
 97935
 97936
 97937
 97938
 97939
 97940
 97941
 97942
 97943
 97944
 97945
 97946
 97947
 97948
 97949
 97950
 97951
 97952
 97953
 97954
 97955
 97956
 97957
 97958
 97959
 97960
 97961
 97962
 97963
 97964
 97965
 97966
 97967
 97968
 97969
 97970
 97971
 97972
 97973
 97974
 97975
 97976
 97977
 97978
 97979
 97980
 97981
 97982
 97983
 97984
 97985
 97986
 97987
 97988
 97989
 97990
 97991
 97992
 97993
 97994
 97995
 97996
 97997
 97998
 97999
 98000
 98001
 98002
 98003
 98004
 98005
 98006
 98007
 98008
 98009
 98010
 98011
 98012
 98013
 98014
 98015
 98016
 98017
 98018
 98019
 98020
 98021
 98022
 98023
 98024
 98025
 98026
 98027
 98028
 98029
 98030
 98031
 98032
 98033
 98034
 98035
 98036
 98037
 98038
 98039
 98040
 98041
 98042
 98043
 98044
 98045
 98046
 98047
 98048
 98049
 98050
 98051
 98052
 98053
 98054
 98055
 98056
 98057
 98058
 98059
 98060
 98061
 98062
 98063
 98064
 98065
 98066
 98067
 98068
 98069
 98070
 98071
 98072
 98073
 98074
 98075
 98076
 98077
 98078
 98079
 98080
 98081
 98082
 98083
 98084
 98085
 98086
 98087
 98088
 98089
 98090
 98091
 98092
 98093
 98094
 98095
 98096
 98097
 98098
 98099
 98100
 98101
 98102
 98103
 98104
 98105
 98106
 98107
 98108
 98109
 98110
 98111
 98112
 98113
 98114
 98115
 98116
 98117
 98118
 98119
 98120
 98121
 98122
 98123
 98124
 98125
 98126
 98127
 98128
 98129
 98130
 98131
 98132
 98133
 98134
 98135
 98136
 98137
 98138
 98139
 98140
 98141
 98142
 98143
 98144
 98145
 98146
 98147
 98148
 98149
 98150
 98151
 98152
 98153
 98154
 98155
 98156
 98157
 98158
 98159
 98160
 98161
 98162
 98163
 98164
 98165
 98166
 98167
 98168
 98169
 98170
 98171
 98172
 98173
 98174
 98175
 98176
 98177
 98178
 98179
 98180
 98181
 98182
 98183
 98184
 98185
 98186
 98187
 98188
 98189
 98190
 98191
 98192
 98193
 98194
 98195
 98196
 98197
 98198
 98199
 98200
 98201
 98202
 98203
 98204
 98205
 98206
 98207
 98208
 98209
 98210
 98211
 98212
 98213
 98214
 98215
 98216
 98217
 98218
 98219
 98220
 98221
 98222
 98223
 98224
 98225
 98226
 98227
 98228
 98229
 98230
 98231
 98232
 98233
 98234
 98235
 98236
 98237
 98238
 98239
 98240
 98241
 98242
 98243
 98244
 98245
 98246
 98247
 98248
 98249
 98250
 98251
 98252
 98253
 98254
 98255
 98256
 98257
 98258
 98259
 98260
 98261
 98262
 98263
 98264
 98265
 98266
 98267
 98268
 98269
 98270
 98271
 98272
 98273
 98274
 98275
 98276
 98277
 98278
 98279
 98280
 98281
 98282
 98283
 98284
 98285
 98286
 98287
 98288
 98289
 98290
 98291
 98292
 98293
 98294
 98295
 98296
 98297
 98298
 98299
 98300
 98301
 98302
 98303
 98304
 98305
 98306
 98307
 98308
 98309
 98310
 98311
 98312
 98313
 98314
 98315
 98316
 98317
 98318
 98319
 98320
 98321
 98322
 98323
 98324
 98325
 98326
 98327
 98328
 98329
 98330
 98331
 98332
 98333
 98334
 98335
 98336
 98337
 98338
 98339
 98340
 98341
 98342
 98343
 98344
 98345
 98346
 98347
 98348
 98349
 98350
 98351
 98352
 98353
 98354
 98355
 98356
 98357
 98358
 98359
 98360
 98361
 98362
 98363
 98364
 98365
 98366
 98367
 98368
 98369
 98370
 98371
 98372
 98373
 98374
 98375
 98376
 98377
 98378
 98379
 98380
 98381
 98382
 98383
 98384
 98385
 98386
 98387
 98388
 98389
 98390
 98391
 98392
 98393
 98394
 98395
 98396
 98397
 98398
 98399
 98400
 98401
 98402
 98403
 98404
 98405
 98406
 98407
 98408
 98409
 98410
 98411
 98412
 98413
 98414
 98415
 98416
 98417
 98418
 98419
 98420
 98421
 98422
 98423
 98424
 98425
 98426
 98427
 98428
 98429
 98430
 98431
 98432
 98433
 98434
 98435
 98436
 98437
 98438
 98439
 98440
 98441
 98442
 98443
 98444
 98445
 98446
 98447
 98448
 98449
 98450
 98451
 98452
 98453
 98454
 98455
 98456
 98457
 98458
 98459
 98460
 98461
 98462
 98463
 98464
 98465
 98466
 98467
 98468
 98469
 98470
 98471
 98472
 98473
 98474
 98475
 98476
 98477
 98478
 98479
 98480
 98481
 98482
 98483
 98484
 98485
 98486
 98487
 98488
 98489
 98490
 98491
 98492
 98493
 98494
 98495
 98496
 98497
 98498
 98499
 98500
 98501
 98502
 98503
 98504
 98505
 98506
 98507
 98508
 98509
 98510
 98511
 98512
 98513
 98514
 98515
 98516
 98517
 98518
 98519
 98520
 98521
 98522
 98523
 98524
 98525
 98526
 98527
 98528
 98529
 98530
 98531
 98532
 98533
 98534
 98535
 98536
 98537
 98538
 98539
 98540
 98541
 98542
 98543
 98544
 98545
 98546
 98547
 98548
 98549
 98550
 98551
 98552
 98553
 98554
 98555
 98556
 98557
 98558
 98559
 98560
 98561
 98562
 98563
 98564
 98565
 98566
 98567
 98568
 98569
 98570
 98571
 98572
 98573
 98574
 98575
 98576
 98577
 98578
 98579
 98580
 98581
 98582
 98583
 98584
 98585
 98586
 98587
 98588
 98589
 98590
 98591
 98592
 98593
 98594
 98595
 98596
 98597
 98598
 98599
 98600
 98601
 98602
 98603
 98604
 98605
 98606
 98607
 98608
 98609
 98610
 98611
 98612
 98613
 98614
 98615
 98616
 98617
 98618
 98619
 98620
 98621
 98622
 98623
 98624
 98625
 98626
 98627
 98628
 98629
 98630
 98631
 98632
 98633
 98634
 98635
 98636
 98637
 98638
 98639
 98640
 98641
 98642
 98643
 98644
 98645
 98646
 98647
 98648
 98649
 98650
 98651
 98652
 98653
 98654
 98655
 98656
 98657
 98658
 98659
 98660
 98661
 98662
 98663
 98664
 98665
 98666
 98667
 98668
 98669
 98670
 98671
 98672
 98673
 98674
 98675
 98676
 98677
 98678
 98679
 98680
 98681
 98682
 98683
 98684
 98685
 98686
 98687
 98688
 98689
 98690
 98691
 98692
 98693
 98694
 98695
 98696
 98697
 98698
 98699
 98700
 98701
 98702
 98703
 98704
 98705
 98706
 98707
 98708
 98709
 98710
 98711
 98712
 98713
 98714
 98715
 98716
 98717
 98718
 98719
 98720
 98721
 98722
 98723
 98724
 98725
 98726
 98727
 98728
 98729
 98730
 98731
 98732
 98733
 98734
 98735
 98736
 98737
 98738
 98739
 98740
 98741
 98742
 98743
 98744
 98745
 98746
 98747
 98748
 98749
 98750
 98751
 98752
 98753
 98754
 98755
 98756
 98757
 98758
 98759
 98760
 98761
 98762
 98763
 98764
 98765
 98766
 98767
 98768
 98769
 98770
 98771
 98772
 98773
 98774
 98775
 98776
 98777
 98778
 98779
 98780
 98781
 98782
 98783
 98784
 98785
 98786
 98787
 98788
 98789
 98790
 98791
 98792
 98793
 98794
 98795
 98796
 98797
 98798
 98799
 98800
 98801
 98802
 98803
 98804
 98805
 98806
 98807
 98808
 98809
 98810
 98811
 98812
 98813
 98814
 98815
 98816
 98817
 98818
 98819
 98820
 98821
 98822
 98823
 98824
 98825
 98826
 98827
 98828
 98829
 98830
 98831
 98832
 98833
 98834
 98835
 98836
 98837
 98838
 98839
 98840
 98841
 98842
 98843
 98844
 98845
 98846
 98847
 98848
 98849
 98850
 98851
 98852
 98853
 98854
 98855
 98856
 98857
 98858
 98859
 98860
 98861
 98862
 98863
 98864
 98865
 98866
 98867
 98868
 98869
 98870
 98871
 98872
 98873
 98874
 98875
 98876
 98877
 98878
 98879
 98880
 98881
 98882
 98883
 98884
 98885
 98886
 98887
 98888
 98889
 98890
 98891
 98892
 98893
 98894
 98895
 98896
 98897
 98898
 98899
 98900
 98901
 98902
 98903
 98904
 98905
 98906
 98907
 98908
 98909
 98910
 98911
 98912
 98913
 98914
 98915
 98916
 98917
 98918
 98919
 98920
 98921
 98922
 98923
 98924
 98925
 98926
 98927
 98928
 98929
 98930
 98931
 98932
 98933
 98934
 98935
 98936
 98937
 98938
 98939
 98940
 98941
 98942
 98943
 98944
 98945
 98946
 98947
 98948
 98949
 98950
 98951
 98952
 98953
 98954
 98955
 98956
 98957
 98958
 98959
 98960
 98961
 98962
 98963
 98964
 98965
 98966
 98967
 98968
 98969
 98970
 98971
 98972
 98973
 98974
 98975
 98976
 98977
 98978
 98979
 98980
 98981
 98982
 98983
 98984
 98985
 98986
 98987
 98988
 98989
 98990
 98991
 98992
 98993
 98994
 98995
 98996
 98997
 98998
 98999
 99000
 99001
 99002
 99003
 99004
 99005
 99006
 99007
 99008
 99009
 99010
 99011
 99012
 99013
 99014
 99015
 99016
 99017
 99018
 99019
 99020
 99021
 99022
 99023
 99024
 99025
 99026
 99027
 99028
 99029
 99030
 99031
 99032
 99033
 99034
 99035
 99036
 99037
 99038
 99039
 99040
 99041
 99042
 99043
 99044
 99045
 99046
 99047
 99048
 99049
 99050
 99051
 99052
 99053
 99054
 99055
 99056
 99057
 99058
 99059
 99060
 99061
 99062
 99063
 99064
 99065
 99066
 99067
 99068
 99069
 99070
 99071
 99072
 99073
 99074
 99075
 99076
 99077
 99078
 99079
 99080
 99081
 99082
 99083
 99084
 99085
 99086
 99087
 99088
 99089
 99090
 99091
 99092
 99093
 99094
 99095
 99096
 99097
 99098
 99099
 99100
 99101
 99102
 99103
 99104
 99105
 99106
 99107
 99108
 99109
 99110
 99111
 99112
 99113
 99114
 99115
 99116
 99117
 99118
 99119
 99120
 99121
 99122
 99123
 99124
 99125
 99126
 99127
 99128
 99129
 99130
 99131
 99132
 99133
 99134
 99135
 99136
 99137
 99138
 99139
 99140
 99141
 99142
 99143
 99144
 99145
 99146
 99147
 99148
 99149
 99150
 99151
 99152
 99153
 99154
 99155
 99156
 99157
 99158
 99159
 99160
 99161
 99162
 99163
 99164
 99165
 99166
 99167
 99168
 99169
 99170
 99171
 99172
 99173
 99174
 99175
 99176
 99177
 99178
 99179
 99180
 99181
 99182
 99183
 99184
 99185
 99186
 99187
 99188
 99189
 99190
 99191
 99192
 99193
 99194
 99195
 99196
 99197
 99198
 99199
 99200
 99201
 99202
 99203
 99204
 99205
 99206
 99207
 99208
 99209
 99210
 99211
 99212
 99213
 99214
 99215
 99216
 99217
 99218
 99219
 99220
 99221
 99222
 99223
 99224
 99225
 99226
 99227
 99228
 99229
 99230
 99231
 99232
 99233
 99234
 99235
 99236
 99237
 99238
 99239
 99240
 99241
 99242
 99243
 99244
 99245
 99246
 99247
 99248
 99249
 99250
 99251
 99252
 99253
 99254
 99255
 99256
 99257
 99258
 99259
 99260
 99261
 99262
 99263
 99264
 99265
 99266
 99267
 99268
 99269
 99270
 99271
 99272
 99273
 99274
 99275
 99276
 99277
 99278
 99279
 99280
 99281
 99282
 99283
 99284
 99285
 99286
 99287
 99288
 99289
 99290
 99291
 99292
 99293
 99294
 99295
 99296
 99297
 99298
 99299
 99300
 99301
 99302
 99303
 99304
 99305
 99306
 99307
 99308
 99309
 99310
 99311
 99312
 99313
 99314
 99315
 99316
 99317
 99318
 99319
 99320
 99321
 99322
 99323
 99324
 99325
 99326
 99327
 99328
 99329
 99330
 99331
 99332
 99333
 99334
 99335
 99336
 99337
 99338
 99339
 99340
 99341
 99342
 99343
 99344
 99345
 99346
 99347
 99348
 99349
 99350
 99351
 99352
 99353
 99354
 99355
 99356
 99357
 99358
 99359
 99360
 99361
 99362
 99363
 99364
 99365
 99366
 99367
 99368
 99369
 99370
 99371
 99372
 99373
 99374
 99375
 99376
 99377
 99378
 99379
 99380
 99381
 99382
 99383
 99384
 99385
 99386
 99387
 99388
 99389
 99390
 99391
 99392
 99393
 99394
 99395
 99396
 99397
 99398
 99399
 99400
 99401
 99402
 99403
 99404
 99405
 99406
 99407
 99408
 99409
 99410
 99411
 99412
 99413
 99414
 99415
 99416
 99417
 99418
 99419
 99420
 99421
 99422
 99423
 99424
 99425
 99426
 99427
 99428
 99429
 99430
 99431
 99432
 99433
 99434
 99435
 99436
 99437
 99438
 99439
 99440
 99441
 99442
 99443
 99444
 99445
 99446
 99447
 99448
 99449
 99450
 99451
 99452
 99453
 99454
 99455
 99456
 99457
 99458
 99459
 99460
 99461
 99462
 99463
 99464
 99465
 99466
 99467
 99468
 99469
 99470
 99471
 99472
 99473
 99474
 99475
 99476
 99477
 99478
 99479
 99480
 99481
 99482
 99483
 99484
 99485
 99486
 99487
 99488
 99489
 99490
 99491
 99492
 99493
 99494
 99495
 99496
 99497
 99498
 99499
 99500
 99501
 99502
 99503
 99504
 99505
 99506
 99507
 99508
 99509
 99510
 99511
 99512
 99513
 99514
 99515
 99516
 99517
 99518
 99519
 99520
 99521
 99522
 99523
 99524
 99525
 99526
 99527
 99528
 99529
 99530
 99531
 99532
 99533
 99534
 99535
 99536
 99537
 99538
 99539
 99540
 99541
 99542
 99543
 99544
 99545
 99546
 99547
 99548
 99549
 99550
 99551
 99552
 99553
 99554
 99555
 99556
 99557
 99558
 99559
 99560
 99561
 99562
 99563
 99564
 99565
 99566
 99567
 99568
 99569
 99570
 99571
 99572
 99573
 99574
 99575
 99576
 99577
 99578
 99579
 99580
 99581
 99582
 99583
 99584
 99585
 99586
 99587
 99588
 99589
 99590
 99591
 99592
 99593
 99594
 99595
 99596
 99597
 99598
 99599
 99600
 99601
 99602
 99603
 99604
 99605
 99606
 99607
 99608
 99609
 99610
 99611
 99612
 99613
 99614
 99615
 99616
 99617
 99618
 99619
 99620
 99621
 99622
 99623
 99624
 99625
 99626
 99627
 99628
 99629
 99630
 99631
 99632
 99633
 99634
 99635
 99636
 99637
 99638
 99639
 99640
 99641
 99642
 99643
 99644
 99645
 99646
 99647
 99648
 99649
 99650
 99651
 99652
 99653
 99654
 99655
 99656
 99657
 99658
 99659
 99660
 99661
 99662
 99663
 99664
 99665
 99666
 99667
 99668
 99669
 99670
 99671
 99672
 99673
 99674
 99675
 99676
 99677
 99678
 99679
 99680
 99681
 99682
 99683
 99684
 99685
 99686
 99687
 99688
 99689
 99690
 99691
 99692
 99693
 99694
 99695
 99696
 99697
 99698
 99699
 99700
 99701
 99702
 99703
 99704
 99705
 99706
 99707
 99708
 99709
 99710
 99711
 99712
 99713
 99714
 99715
 99716
 99717
 99718
 99719
 99720
 99721
 99722
 99723
 99724
 99725
 99726
 99727
 99728
 99729
 99730
 99731
 99732
 99733
 99734
 99735
 99736
 99737
 99738
 99739
 99740
 99741
 99742
 99743
 99744
 99745
 99746
 99747
 99748
 99749
 99750
 99751
 99752
 99753
 99754
 99755
/*
 *  Single source autogenerated distributable for Duktape 2.5.0.
 *
 *  Git commit 6001888049cb42656f8649db020e804bcdeca6a7 (v2.5.0).
 *  Git branch master.
 *
 *  See Duktape AUTHORS.rst and LICENSE.txt for copyright and
 *  licensing information.
 */

/* LICENSE.txt */
/*
*  ===============
*  Duktape license
*  ===============
*
*  (http://opensource.org/licenses/MIT)
*
*  Copyright (c) 2013-2019 by Duktape authors (see AUTHORS.rst)
*
*  Permission is hereby granted, free of charge, to any person obtaining a copy
*  of this software and associated documentation files (the "Software"), to deal
*  in the Software without restriction, including without limitation the rights
*  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
*  copies of the Software, and to permit persons to whom the Software is
*  furnished to do so, subject to the following conditions:
*
*  The above copyright notice and this permission notice shall be included in
*  all copies or substantial portions of the Software.
*
*  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
*  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
*  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
*  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
*  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
*  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
*  THE SOFTWARE.
*/

/* AUTHORS.rst */
/*
*  ===============
*  Duktape authors
*  ===============
*
*  Copyright
*  =========
*
*  Duktape copyrights are held by its authors.  Each author has a copyright
*  to their contribution, and agrees to irrevocably license the contribution
*  under the Duktape ``LICENSE.txt``.
*
*  Authors
*  =======
*
*  Please include an e-mail address, a link to your GitHub profile, or something
*  similar to allow your contribution to be identified accurately.
*
*  The following people have contributed code, website contents, or Wiki contents,
*  and agreed to irrevocably license their contributions under the Duktape
*  ``LICENSE.txt`` (in order of appearance):
*
*  * Sami Vaarala <sami.vaarala@iki.fi>
*  * Niki Dobrev
*  * Andreas \u00d6man <andreas@lonelycoder.com>
*  * L\u00e1szl\u00f3 Lang\u00f3 <llango.u-szeged@partner.samsung.com>
*  * Legimet <legimet.calc@gmail.com>
*  * Karl Skomski <karl@skomski.com>
*  * Bruce Pascoe <fatcerberus1@gmail.com>
*  * Ren\u00e9 Hollander <rene@rene8888.at>
*  * Julien Hamaide (https://github.com/crazyjul)
*  * Sebastian G\u00f6tte (https://github.com/jaseg)
*  * Tomasz Magulski (https://github.com/magul)
*  * \D. Bohdan (https://github.com/dbohdan)
*  * Ond\u0159ej Jirman (https://github.com/megous)
*  * Sa\u00fal Ibarra Corretg\u00e9 <saghul@gmail.com>
*  * Jeremy HU <huxingyi@msn.com>
*  * Ole Andr\u00e9 Vadla Ravn\u00e5s (https://github.com/oleavr)
*  * Harold Brenes (https://github.com/harold-b)
*  * Oliver Crow (https://github.com/ocrow)
*  * Jakub Ch\u0142api\u0144ski (https://github.com/jchlapinski)
*  * Brett Vickers (https://github.com/beevik)
*  * Dominik Okwieka (https://github.com/okitec)
*  * Remko Tron\u00e7on (https://el-tramo.be)
*  * Romero Malaquias (rbsm@ic.ufal.br)
*  * Michael Drake <michael.drake@codethink.co.uk>
*  * Steven Don (https://github.com/shdon)
*  * Simon Stone (https://github.com/sstone1)
*  * \J. McC. (https://github.com/jmhmccr)
*  * Jakub Nowakowski (https://github.com/jimvonmoon)
*  * Tommy Nguyen (https://github.com/tn0502)
*  * Fabrice Fontaine (https://github.com/ffontaine)
*  * Christopher Hiller (https://github.com/boneskull)
*  * Gonzalo Diethelm (https://github.com/gonzus)
*  * Michal Kasperek (https://github.com/michalkas)
*  * Andrew Janke (https://github.com/apjanke)
*  * Steve Fan (https://github.com/stevefan1999)
*  * Edward Betts (https://github.com/edwardbetts)
*  * Ozhan Duz (https://github.com/webfolderio)
*  * Akos Kiss (https://github.com/akosthekiss)
*  * TheBrokenRail (https://github.com/TheBrokenRail)
*  * Jesse Doyle (https://github.com/jessedoyle)
*  * Gero Kuehn (https://github.com/dc6jgk)
*  * James Swift (https://github.com/phraemer)
*  * Luis de Bethencourt (https://github.com/luisbg)
*  * Ian Whyman (https://github.com/v00d00)
*  * Rick Sayre (https://github.com/whorfin)
*
*  Other contributions
*  ===================
*
*  The following people have contributed something other than code (e.g. reported
*  bugs, provided ideas, etc; roughly in order of appearance):
*
*  * Greg Burns
*  * Anthony Rabine
*  * Carlos Costa
*  * Aur\u00e9lien Bouilland
*  * Preet Desai (Pris Matic)
*  * judofyr (http://www.reddit.com/user/judofyr)
*  * Jason Woofenden
*  * Micha\u0142 Przyby\u015b
*  * Anthony Howe
*  * Conrad Pankoff
*  * Jim Schimpf
*  * Rajaran Gaunker (https://github.com/zimbabao)
*  * Andreas \u00d6man
*  * Doug Sanden
*  * Josh Engebretson (https://github.com/JoshEngebretson)
*  * Remo Eichenberger (https://github.com/remoe)
*  * Mamod Mehyar (https://github.com/mamod)
*  * David Demelier (https://github.com/markand)
*  * Tim Caswell (https://github.com/creationix)
*  * Mitchell Blank Jr (https://github.com/mitchblank)
*  * https://github.com/yushli
*  * Seo Sanghyeon (https://github.com/sanxiyn)
*  * Han ChoongWoo (https://github.com/tunz)
*  * Joshua Peek (https://github.com/josh)
*  * Bruce E. Pascoe (https://github.com/fatcerberus)
*  * https://github.com/Kelledin
*  * https://github.com/sstruchtrup
*  * Michael Drake (https://github.com/tlsa)
*  * https://github.com/chris-y
*  * Laurent Zubiaur (https://github.com/lzubiaur)
*  * Neil Kolban (https://github.com/nkolban)
*  * Wilhelm Wanecek (https://github.com/wanecek)
*  * Andrew Janke (https://github.com/apjanke)
*  * Unamer (https://github.com/unamer)
*  * Karl Dahlke (eklhad@gmail.com)
*
*  If you are accidentally missing from this list, send me an e-mail
*  (``sami.vaarala@iki.fi``) and I'll fix the omission.
*/

#line 1 "duk_replacements.c"
/*
 *  Replacements for missing platform functions.
 *
 *  Unlike the originals, fpclassify() and signbit() replacements don't
 *  work on any floating point types, only doubles.  The C typing here
 *  mimics the standard prototypes.
 */

/* #include duk_internal.h */
#line 1 "duk_internal.h"
/*
 *  Top-level include file to be used for all (internal) source files.
 *
 *  Source files should not include individual header files, as they
 *  have not been designed to be individually included.
 */

#if !defined(DUK_INTERNAL_H_INCLUDED)
#define DUK_INTERNAL_H_INCLUDED

/*
 *  The 'duktape.h' header provides the public API, but also handles all
 *  compiler and platform specific feature detection, Duktape feature
 *  resolution, inclusion of system headers, etc.  These have been merged
 *  because the public API is also dependent on e.g. detecting appropriate
 *  C types which is quite platform/compiler specific especially for a non-C99
 *  build.  The public API is also dependent on the resolved feature set.
 *
 *  Some actions taken by the merged header (such as including system headers)
 *  are not appropriate for building a user application.  The define
 *  DUK_COMPILING_DUKTAPE allows the merged header to skip/include some
 *  sections depending on what is being built.
 */

#define DUK_COMPILING_DUKTAPE
#include "duktape.h"

/*
 *  Duktape includes (other than duk_features.h)
 *
 *  The header files expect to be included in an order which satisfies header
 *  dependencies correctly (the headers themselves don't include any other
 *  includes).  Forward declarations are used to break circular struct/typedef
 *  dependencies.
 */

/* #include duk_dblunion.h */
#line 1 "duk_dblunion.h"
/*
 *  Union to access IEEE double memory representation, indexes for double
 *  memory representation, and some macros for double manipulation.
 *
 *  Also used by packed duk_tval.  Use a union for bit manipulation to
 *  minimize aliasing issues in practice.  The C99 standard does not
 *  guarantee that this should work, but it's a very widely supported
 *  practice for low level manipulation.
 *
 *  IEEE double format summary:
 *
 *    seeeeeee eeeeffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff
 *       A        B        C        D        E        F        G        H
 *
 *    s       sign bit
 *    eee...  exponent field
 *    fff...  fraction
 *
 *  See http://en.wikipedia.org/wiki/Double_precision_floating-point_format.
 *
 *  NaNs are represented as exponent 0x7ff and mantissa != 0.  The NaN is a
 *  signaling NaN when the highest bit of the mantissa is zero, and a quiet
 *  NaN when the highest bit is set.
 *
 *  At least three memory layouts are relevant here:
 *
 *    A B C D E F G H    Big endian (e.g. 68k)           DUK_USE_DOUBLE_BE
 *    H G F E D C B A    Little endian (e.g. x86)        DUK_USE_DOUBLE_LE
 *    D C B A H G F E    Mixed endian (e.g. ARM FPA)     DUK_USE_DOUBLE_ME
 *
 *  Legacy ARM (FPA) is a special case: ARM double values are in mixed
 *  endian format while ARM duk_uint64_t values are in standard little endian
 *  format (H G F E D C B A).  When a double is read as a duk_uint64_t
 *  from memory, the register will contain the (logical) value
 *  E F G H A B C D.  This requires some special handling below.
 *  See http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0056d/Bcfhgcgd.html.
 *
 *  Indexes of various types (8-bit, 16-bit, 32-bit) in memory relative to
 *  the logical (big endian) order:
 *
 *  byte order      duk_uint8_t    duk_uint16_t     duk_uint32_t
 *    BE             01234567         0123               01
 *    LE             76543210         3210               10
 *    ME (ARM)       32107654         1032               01
 *
 *  Some processors may alter NaN values in a floating point load+store.
 *  For instance, on X86 a FLD + FSTP may convert a signaling NaN to a
 *  quiet one.  This is catastrophic when NaN space is used in packed
 *  duk_tval values.  See: misc/clang_aliasing.c.
 */

#if !defined(DUK_DBLUNION_H_INCLUDED)
#define DUK_DBLUNION_H_INCLUDED

/*
 *  Union for accessing double parts, also serves as packed duk_tval
 */

union duk_double_union {
	double d;
	float f[2];
#if defined(DUK_USE_64BIT_OPS)
	duk_uint64_t ull[1];
#endif
	duk_uint32_t ui[2];
	duk_uint16_t us[4];
	duk_uint8_t uc[8];
#if defined(DUK_USE_PACKED_TVAL)
	void *vp[2];  /* used by packed duk_tval, assumes sizeof(void *) == 4 */
#endif
};

typedef union duk_double_union duk_double_union;

/*
 *  Indexes of various types with respect to big endian (logical) layout
 */

#if defined(DUK_USE_DOUBLE_LE)
#if defined(DUK_USE_64BIT_OPS)
#define DUK_DBL_IDX_ULL0   0
#endif
#define DUK_DBL_IDX_UI0    1
#define DUK_DBL_IDX_UI1    0
#define DUK_DBL_IDX_US0    3
#define DUK_DBL_IDX_US1    2
#define DUK_DBL_IDX_US2    1
#define DUK_DBL_IDX_US3    0
#define DUK_DBL_IDX_UC0    7
#define DUK_DBL_IDX_UC1    6
#define DUK_DBL_IDX_UC2    5
#define DUK_DBL_IDX_UC3    4
#define DUK_DBL_IDX_UC4    3
#define DUK_DBL_IDX_UC5    2
#define DUK_DBL_IDX_UC6    1
#define DUK_DBL_IDX_UC7    0
#define DUK_DBL_IDX_VP0    DUK_DBL_IDX_UI0  /* packed tval */
#define DUK_DBL_IDX_VP1    DUK_DBL_IDX_UI1  /* packed tval */
#elif defined(DUK_USE_DOUBLE_BE)
#if defined(DUK_USE_64BIT_OPS)
#define DUK_DBL_IDX_ULL0   0
#endif
#define DUK_DBL_IDX_UI0    0
#define DUK_DBL_IDX_UI1    1
#define DUK_DBL_IDX_US0    0
#define DUK_DBL_IDX_US1    1
#define DUK_DBL_IDX_US2    2
#define DUK_DBL_IDX_US3    3
#define DUK_DBL_IDX_UC0    0
#define DUK_DBL_IDX_UC1    1
#define DUK_DBL_IDX_UC2    2
#define DUK_DBL_IDX_UC3    3
#define DUK_DBL_IDX_UC4    4
#define DUK_DBL_IDX_UC5    5
#define DUK_DBL_IDX_UC6    6
#define DUK_DBL_IDX_UC7    7
#define DUK_DBL_IDX_VP0    DUK_DBL_IDX_UI0  /* packed tval */
#define DUK_DBL_IDX_VP1    DUK_DBL_IDX_UI1  /* packed tval */
#elif defined(DUK_USE_DOUBLE_ME)
#if defined(DUK_USE_64BIT_OPS)
#define DUK_DBL_IDX_ULL0   0  /* not directly applicable, byte order differs from a double */
#endif
#define DUK_DBL_IDX_UI0    0
#define DUK_DBL_IDX_UI1    1
#define DUK_DBL_IDX_US0    1
#define DUK_DBL_IDX_US1    0
#define DUK_DBL_IDX_US2    3
#define DUK_DBL_IDX_US3    2
#define DUK_DBL_IDX_UC0    3
#define DUK_DBL_IDX_UC1    2
#define DUK_DBL_IDX_UC2    1
#define DUK_DBL_IDX_UC3    0
#define DUK_DBL_IDX_UC4    7
#define DUK_DBL_IDX_UC5    6
#define DUK_DBL_IDX_UC6    5
#define DUK_DBL_IDX_UC7    4
#define DUK_DBL_IDX_VP0    DUK_DBL_IDX_UI0  /* packed tval */
#define DUK_DBL_IDX_VP1    DUK_DBL_IDX_UI1  /* packed tval */
#else
#error internal error
#endif

/*
 *  Helper macros for reading/writing memory representation parts, used
 *  by duk_numconv.c and duk_tval.h.
 */

#define DUK_DBLUNION_SET_DOUBLE(u,v)  do {  \
		(u)->d = (v); \
	} while (0)

#define DUK_DBLUNION_SET_HIGH32(u,v)  do {  \
		(u)->ui[DUK_DBL_IDX_UI0] = (duk_uint32_t) (v); \
	} while (0)

#if defined(DUK_USE_64BIT_OPS)
#if defined(DUK_USE_DOUBLE_ME)
#define DUK_DBLUNION_SET_HIGH32_ZERO_LOW32(u,v)  do { \
		(u)->ull[DUK_DBL_IDX_ULL0] = (duk_uint64_t) (v); \
	} while (0)
#else
#define DUK_DBLUNION_SET_HIGH32_ZERO_LOW32(u,v)  do { \
		(u)->ull[DUK_DBL_IDX_ULL0] = ((duk_uint64_t) (v)) << 32; \
	} while (0)
#endif
#else  /* DUK_USE_64BIT_OPS */
#define DUK_DBLUNION_SET_HIGH32_ZERO_LOW32(u,v)  do { \
		(u)->ui[DUK_DBL_IDX_UI0] = (duk_uint32_t) (v); \
		(u)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) 0; \
	} while (0)
#endif  /* DUK_USE_64BIT_OPS */

#define DUK_DBLUNION_SET_LOW32(u,v)  do {  \
		(u)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (v); \
	} while (0)

#define DUK_DBLUNION_GET_DOUBLE(u)  ((u)->d)
#define DUK_DBLUNION_GET_HIGH32(u)  ((u)->ui[DUK_DBL_IDX_UI0])
#define DUK_DBLUNION_GET_LOW32(u)   ((u)->ui[DUK_DBL_IDX_UI1])

#if defined(DUK_USE_64BIT_OPS)
#if defined(DUK_USE_DOUBLE_ME)
#define DUK_DBLUNION_SET_UINT64(u,v)  do { \
		(u)->ui[DUK_DBL_IDX_UI0] = (duk_uint32_t) ((v) >> 32); \
		(u)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (v); \
	} while (0)
#define DUK_DBLUNION_GET_UINT64(u) \
	((((duk_uint64_t) (u)->ui[DUK_DBL_IDX_UI0]) << 32) | \
	 ((duk_uint64_t) (u)->ui[DUK_DBL_IDX_UI1]))
#else
#define DUK_DBLUNION_SET_UINT64(u,v)  do { \
		(u)->ull[DUK_DBL_IDX_ULL0] = (duk_uint64_t) (v); \
	} while (0)
#define DUK_DBLUNION_GET_UINT64(u)  ((u)->ull[DUK_DBL_IDX_ULL0])
#endif
#define DUK_DBLUNION_SET_INT64(u,v) DUK_DBLUNION_SET_UINT64((u), (duk_uint64_t) (v))
#define DUK_DBLUNION_GET_INT64(u)   ((duk_int64_t) DUK_DBLUNION_GET_UINT64((u)))
#endif  /* DUK_USE_64BIT_OPS */

/*
 *  Double NaN manipulation macros related to NaN normalization needed when
 *  using the packed duk_tval representation.  NaN normalization is necessary
 *  to keep double values compatible with the duk_tval format.
 *
 *  When packed duk_tval is used, the NaN space is used to store pointers
 *  and other tagged values in addition to NaNs.  Actual NaNs are normalized
 *  to a specific quiet NaN.  The macros below are used by the implementation
 *  to check and normalize NaN values when they might be created.  The macros
 *  are essentially NOPs when the non-packed duk_tval representation is used.
 *
 *  A FULL check is exact and checks all bits.  A NOTFULL check is used by
 *  the packed duk_tval and works correctly for all NaNs except those that
 *  begin with 0x7ff0.  Since the 'normalized NaN' values used with packed
 *  duk_tval begin with 0x7ff8, the partial check is reliable when packed
 *  duk_tval is used.  The 0x7ff8 prefix means the normalized NaN will be a
 *  quiet NaN regardless of its remaining lower bits.
 *
 *  The ME variant below is specifically for ARM byte order, which has the
 *  feature that while doubles have a mixed byte order (32107654), unsigned
 *  long long values has a little endian byte order (76543210).  When writing
 *  a logical double value through a ULL pointer, the 32-bit words need to be
 *  swapped; hence the #if defined()s below for ULL writes with DUK_USE_DOUBLE_ME.
 *  This is not full ARM support but suffices for some environments.
 */

#if defined(DUK_USE_64BIT_OPS)
#if defined(DUK_USE_DOUBLE_ME)
/* Macros for 64-bit ops + mixed endian doubles. */
#define DUK__DBLUNION_SET_NAN_FULL(u)  do { \
		(u)->ull[DUK_DBL_IDX_ULL0] = DUK_U64_CONSTANT(0x000000007ff80000); \
	} while (0)
#define DUK__DBLUNION_IS_NAN_FULL(u) \
	((((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x000000007ff00000)) == DUK_U64_CONSTANT(0x000000007ff00000)) && \
	 ((((u)->ull[DUK_DBL_IDX_ULL0]) & DUK_U64_CONSTANT(0xffffffff000fffff)) != 0))
#define DUK__DBLUNION_IS_NORMALIZED_NAN_FULL(u) \
	((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x000000007ff80000))
#define DUK__DBLUNION_IS_ANYINF(u) \
	(((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0xffffffff7fffffff)) == DUK_U64_CONSTANT(0x000000007ff00000))
#define DUK__DBLUNION_IS_POSINF(u) \
	((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x000000007ff00000))
#define DUK__DBLUNION_IS_NEGINF(u) \
	((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x00000000fff00000))
#define DUK__DBLUNION_IS_ANYZERO(u) \
	(((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0xffffffff7fffffff)) == DUK_U64_CONSTANT(0x0000000000000000))
#define DUK__DBLUNION_IS_POSZERO(u) \
	((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x0000000000000000))
#define DUK__DBLUNION_IS_NEGZERO(u) \
	((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x0000000080000000))
#else
/* Macros for 64-bit ops + big/little endian doubles. */
#define DUK__DBLUNION_SET_NAN_FULL(u)  do { \
		(u)->ull[DUK_DBL_IDX_ULL0] = DUK_U64_CONSTANT(0x7ff8000000000000); \
	} while (0)
#define DUK__DBLUNION_IS_NAN_FULL(u) \
	((((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x7ff0000000000000)) == DUK_U64_CONSTANT(0x7ff0000000000000)) && \
	 ((((u)->ull[DUK_DBL_IDX_ULL0]) & DUK_U64_CONSTANT(0x000fffffffffffff)) != 0))
#define DUK__DBLUNION_IS_NORMALIZED_NAN_FULL(u) \
	((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x7ff8000000000000))
#define DUK__DBLUNION_IS_ANYINF(u) \
	(((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x7fffffffffffffff)) == DUK_U64_CONSTANT(0x7ff0000000000000))
#define DUK__DBLUNION_IS_POSINF(u) \
	((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x7ff0000000000000))
#define DUK__DBLUNION_IS_NEGINF(u) \
	((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0xfff0000000000000))
#define DUK__DBLUNION_IS_ANYZERO(u) \
	(((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x7fffffffffffffff)) == DUK_U64_CONSTANT(0x0000000000000000))
#define DUK__DBLUNION_IS_POSZERO(u) \
	((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x0000000000000000))
#define DUK__DBLUNION_IS_NEGZERO(u) \
	((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x8000000000000000))
#endif
#else  /* DUK_USE_64BIT_OPS */
/* Macros for no 64-bit ops, any endianness. */
#define DUK__DBLUNION_SET_NAN_FULL(u)  do { \
		(u)->ui[DUK_DBL_IDX_UI0] = (duk_uint32_t) 0x7ff80000UL; \
		(u)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) 0x00000000UL; \
	} while (0)
#define DUK__DBLUNION_IS_NAN_FULL(u) \
	((((u)->ui[DUK_DBL_IDX_UI0] & 0x7ff00000UL) == 0x7ff00000UL) && \
	 (((u)->ui[DUK_DBL_IDX_UI0] & 0x000fffffUL) != 0 || \
          (u)->ui[DUK_DBL_IDX_UI1] != 0))
#define DUK__DBLUNION_IS_NORMALIZED_NAN_FULL(u) \
	(((u)->ui[DUK_DBL_IDX_UI0] == 0x7ff80000UL) && \
	 ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))
#define DUK__DBLUNION_IS_ANYINF(u) \
	((((u)->ui[DUK_DBL_IDX_UI0] & 0x7fffffffUL) == 0x7ff00000UL) && \
	 ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))
#define DUK__DBLUNION_IS_POSINF(u) \
	(((u)->ui[DUK_DBL_IDX_UI0] == 0x7ff00000UL) && \
	 ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))
#define DUK__DBLUNION_IS_NEGINF(u) \
	(((u)->ui[DUK_DBL_IDX_UI0] == 0xfff00000UL) && \
	 ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))
#define DUK__DBLUNION_IS_ANYZERO(u) \
	((((u)->ui[DUK_DBL_IDX_UI0] & 0x7fffffffUL) == 0x00000000UL) && \
	 ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))
#define DUK__DBLUNION_IS_POSZERO(u) \
	(((u)->ui[DUK_DBL_IDX_UI0] == 0x00000000UL) && \
	 ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))
#define DUK__DBLUNION_IS_NEGZERO(u) \
	(((u)->ui[DUK_DBL_IDX_UI0] == 0x80000000UL) && \
	 ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))
#endif  /* DUK_USE_64BIT_OPS */

#define DUK__DBLUNION_SET_NAN_NOTFULL(u)  do { \
		(u)->us[DUK_DBL_IDX_US0] = 0x7ff8UL; \
	} while (0)

#define DUK__DBLUNION_IS_NAN_NOTFULL(u) \
	/* E == 0x7ff, topmost four bits of F != 0 => assume NaN */ \
	((((u)->us[DUK_DBL_IDX_US0] & 0x7ff0UL) == 0x7ff0UL) && \
	 (((u)->us[DUK_DBL_IDX_US0] & 0x000fUL) != 0x0000UL))

#define DUK__DBLUNION_IS_NORMALIZED_NAN_NOTFULL(u) \
	/* E == 0x7ff, F == 8 => normalized NaN */ \
	((u)->us[DUK_DBL_IDX_US0] == 0x7ff8UL)

#define DUK__DBLUNION_NORMALIZE_NAN_CHECK_FULL(u)  do { \
		if (DUK__DBLUNION_IS_NAN_FULL((u))) { \
			DUK__DBLUNION_SET_NAN_FULL((u)); \
		} \
	} while (0)

#define DUK__DBLUNION_NORMALIZE_NAN_CHECK_NOTFULL(u)  do { \
		if (DUK__DBLUNION_IS_NAN_NOTFULL((u))) { \
			DUK__DBLUNION_SET_NAN_NOTFULL((u)); \
		} \
	} while (0)

/* Concrete macros for NaN handling used by the implementation internals.
 * Chosen so that they match the duk_tval representation: with a packed
 * duk_tval, ensure NaNs are properly normalized; with a non-packed duk_tval
 * these are essentially NOPs.
 */

#if defined(DUK_USE_PACKED_TVAL)
#if defined(DUK_USE_FULL_TVAL)
#define DUK_DBLUNION_NORMALIZE_NAN_CHECK(u)  DUK__DBLUNION_NORMALIZE_NAN_CHECK_FULL((u))
#define DUK_DBLUNION_IS_NAN(u)               DUK__DBLUNION_IS_NAN_FULL((u))
#define DUK_DBLUNION_IS_NORMALIZED_NAN(u)    DUK__DBLUNION_IS_NORMALIZED_NAN_FULL((u))
#define DUK_DBLUNION_SET_NAN(d)              DUK__DBLUNION_SET_NAN_FULL((d))
#else
#define DUK_DBLUNION_NORMALIZE_NAN_CHECK(u)  DUK__DBLUNION_NORMALIZE_NAN_CHECK_NOTFULL((u))
#define DUK_DBLUNION_IS_NAN(u)               DUK__DBLUNION_IS_NAN_NOTFULL((u))
#define DUK_DBLUNION_IS_NORMALIZED_NAN(u)    DUK__DBLUNION_IS_NORMALIZED_NAN_NOTFULL((u))
#define DUK_DBLUNION_SET_NAN(d)              DUK__DBLUNION_SET_NAN_NOTFULL((d))
#endif
#define DUK_DBLUNION_IS_NORMALIZED(u) \
	(!DUK_DBLUNION_IS_NAN((u)) ||  /* either not a NaN */ \
	 DUK_DBLUNION_IS_NORMALIZED_NAN((u)))  /* or is a normalized NaN */
#else  /* DUK_USE_PACKED_TVAL */
#define DUK_DBLUNION_NORMALIZE_NAN_CHECK(u)  /* nop: no need to normalize */
#define DUK_DBLUNION_IS_NAN(u)               DUK__DBLUNION_IS_NAN_FULL((u))  /* (DUK_ISNAN((u)->d)) */
#define DUK_DBLUNION_IS_NORMALIZED_NAN(u)    DUK__DBLUNION_IS_NAN_FULL((u))  /* (DUK_ISNAN((u)->d)) */
#define DUK_DBLUNION_IS_NORMALIZED(u)        1  /* all doubles are considered normalized */
#define DUK_DBLUNION_SET_NAN(u)  do { \
		/* in non-packed representation we don't care about which NaN is used */ \
		(u)->d = DUK_DOUBLE_NAN; \
	} while (0)
#endif  /* DUK_USE_PACKED_TVAL */

#define DUK_DBLUNION_IS_ANYINF(u) DUK__DBLUNION_IS_ANYINF((u))
#define DUK_DBLUNION_IS_POSINF(u) DUK__DBLUNION_IS_POSINF((u))
#define DUK_DBLUNION_IS_NEGINF(u) DUK__DBLUNION_IS_NEGINF((u))

#define DUK_DBLUNION_IS_ANYZERO(u) DUK__DBLUNION_IS_ANYZERO((u))
#define DUK_DBLUNION_IS_POSZERO(u) DUK__DBLUNION_IS_POSZERO((u))
#define DUK_DBLUNION_IS_NEGZERO(u) DUK__DBLUNION_IS_NEGZERO((u))

/* XXX: native 64-bit byteswaps when available */

/* 64-bit byteswap, same operation independent of target endianness. */
#define DUK_DBLUNION_BSWAP64(u) do { \
		duk_uint32_t duk__bswaptmp1, duk__bswaptmp2; \
		duk__bswaptmp1 = (u)->ui[0]; \
		duk__bswaptmp2 = (u)->ui[1]; \
		duk__bswaptmp1 = DUK_BSWAP32(duk__bswaptmp1); \
		duk__bswaptmp2 = DUK_BSWAP32(duk__bswaptmp2); \
		(u)->ui[0] = duk__bswaptmp2; \
		(u)->ui[1] = duk__bswaptmp1; \
	} while (0)

/* Byteswap an IEEE double in the duk_double_union from host to network
 * order.  For a big endian target this is a no-op.
 */
#if defined(DUK_USE_DOUBLE_LE)
#define DUK_DBLUNION_DOUBLE_HTON(u) do { \
		duk_uint32_t duk__bswaptmp1, duk__bswaptmp2; \
		duk__bswaptmp1 = (u)->ui[0]; \
		duk__bswaptmp2 = (u)->ui[1]; \
		duk__bswaptmp1 = DUK_BSWAP32(duk__bswaptmp1); \
		duk__bswaptmp2 = DUK_BSWAP32(duk__bswaptmp2); \
		(u)->ui[0] = duk__bswaptmp2; \
		(u)->ui[1] = duk__bswaptmp1; \
	} while (0)
#elif defined(DUK_USE_DOUBLE_ME)
#define DUK_DBLUNION_DOUBLE_HTON(u) do { \
		duk_uint32_t duk__bswaptmp1, duk__bswaptmp2; \
		duk__bswaptmp1 = (u)->ui[0]; \
		duk__bswaptmp2 = (u)->ui[1]; \
		duk__bswaptmp1 = DUK_BSWAP32(duk__bswaptmp1); \
		duk__bswaptmp2 = DUK_BSWAP32(duk__bswaptmp2); \
		(u)->ui[0] = duk__bswaptmp1; \
		(u)->ui[1] = duk__bswaptmp2; \
	} while (0)
#elif defined(DUK_USE_DOUBLE_BE)
#define DUK_DBLUNION_DOUBLE_HTON(u) do { } while (0)
#else
#error internal error, double endianness insane
#endif

/* Reverse operation is the same. */
#define DUK_DBLUNION_DOUBLE_NTOH(u) DUK_DBLUNION_DOUBLE_HTON((u))

/* Some sign bit helpers. */
#if defined(DUK_USE_64BIT_OPS)
#define DUK_DBLUNION_HAS_SIGNBIT(u) (((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x8000000000000000)) != 0)
#define DUK_DBLUNION_GET_SIGNBIT(u) (((u)->ull[DUK_DBL_IDX_ULL0] >> 63U))
#else
#define DUK_DBLUNION_HAS_SIGNBIT(u) (((u)->ui[DUK_DBL_IDX_UI0] & 0x80000000UL) != 0)
#define DUK_DBLUNION_GET_SIGNBIT(u) (((u)->ui[DUK_DBL_IDX_UI0] >> 31U))
#endif

#endif  /* DUK_DBLUNION_H_INCLUDED */
/* #include duk_fltunion.h */
#line 1 "duk_fltunion.h"
/*
 *  Union to access IEEE float memory representation.
 */

#if !defined(DUK_FLTUNION_H_INCLUDED)
#define DUK_FLTUNION_H_INCLUDED

/* #include duk_internal.h -> already included */

union duk_float_union {
	float f;
	duk_uint32_t ui[1];
	duk_uint16_t us[2];
	duk_uint8_t uc[4];
};

typedef union duk_float_union duk_float_union;

#if defined(DUK_USE_DOUBLE_LE) || defined(DUK_USE_DOUBLE_ME)
#define DUK_FLT_IDX_UI0    0
#define DUK_FLT_IDX_US0    1
#define DUK_FLT_IDX_US1    0
#define DUK_FLT_IDX_UC0    3
#define DUK_FLT_IDX_UC1    2
#define DUK_FLT_IDX_UC2    1
#define DUK_FLT_IDX_UC3    0
#elif defined(DUK_USE_DOUBLE_BE)
#define DUK_FLT_IDX_UI0    0
#define DUK_FLT_IDX_US0    0
#define DUK_FLT_IDX_US1    1
#define DUK_FLT_IDX_UC0    0
#define DUK_FLT_IDX_UC1    1
#define DUK_FLT_IDX_UC2    2
#define DUK_FLT_IDX_UC3    3
#else
#error internal error
#endif

#endif  /* DUK_FLTUNION_H_INCLUDED */
/* #include duk_replacements.h */
#line 1 "duk_replacements.h"
#if !defined(DUK_REPLACEMENTS_H_INCLUDED)
#define DUK_REPLACEMENTS_H_INCLUDED

#if !defined(DUK_SINGLE_FILE)
#if defined(DUK_USE_COMPUTED_INFINITY)
DUK_INTERNAL_DECL double duk_computed_infinity;
#endif
#if defined(DUK_USE_COMPUTED_NAN)
DUK_INTERNAL_DECL double duk_computed_nan;
#endif
#endif  /* !DUK_SINGLE_FILE */

#if defined(DUK_USE_REPL_FPCLASSIFY)
DUK_INTERNAL_DECL int duk_repl_fpclassify(double x);
#endif
#if defined(DUK_USE_REPL_SIGNBIT)
DUK_INTERNAL_DECL int duk_repl_signbit(double x);
#endif
#if defined(DUK_USE_REPL_ISFINITE)
DUK_INTERNAL_DECL int duk_repl_isfinite(double x);
#endif
#if defined(DUK_USE_REPL_ISNAN)
DUK_INTERNAL_DECL int duk_repl_isnan(double x);
#endif
#if defined(DUK_USE_REPL_ISINF)
DUK_INTERNAL_DECL int duk_repl_isinf(double x);
#endif

#endif  /* DUK_REPLACEMENTS_H_INCLUDED */
/* #include duk_jmpbuf.h */
#line 1 "duk_jmpbuf.h"
/*
 *  Wrapper for jmp_buf.
 *
 *  This is used because jmp_buf is an array type for backward compatibility.
 *  Wrapping jmp_buf in a struct makes pointer references, sizeof, etc,
 *  behave more intuitively.
 *
 *  http://en.wikipedia.org/wiki/Setjmp.h#Member_types
 */

#if !defined(DUK_JMPBUF_H_INCLUDED)
#define DUK_JMPBUF_H_INCLUDED

#if defined(DUK_USE_CPP_EXCEPTIONS)
struct duk_jmpbuf {
	duk_small_int_t dummy;  /* unused */
};
#else
struct duk_jmpbuf {
	DUK_JMPBUF_TYPE jb;
};
#endif

#endif  /* DUK_JMPBUF_H_INCLUDED */
/* #include duk_exception.h */
#line 1 "duk_exception.h"
/*
 *  Exceptions for Duktape internal throws when C++ exceptions are used
 *  for long control transfers.
 */

#if !defined(DUK_EXCEPTION_H_INCLUDED)
#define DUK_EXCEPTION_H_INCLUDED

#if defined(DUK_USE_CPP_EXCEPTIONS)
/* Internal exception used as a setjmp-longjmp replacement.  User code should
 * NEVER see or catch this exception, so it doesn't inherit from any base
 * class which should minimize the chance of user code accidentally catching
 * the exception.
 */
class duk_internal_exception {
	/* intentionally empty */
};

/* Fatal error, thrown as a specific C++ exception with C++ exceptions
 * enabled.  It is unsafe to continue; doing so may cause crashes or memory
 * leaks.  This is intended to be either uncaught, or caught by user code
 * aware of the "unsafe to continue" semantics.
 */
class duk_fatal_exception : public virtual std::runtime_error {
 public:
	duk_fatal_exception(const char *message) : std::runtime_error(message) {}
};
#endif

#endif  /* DUK_EXCEPTION_H_INCLUDED */
/* #include duk_forwdecl.h */
#line 1 "duk_forwdecl.h"
/*
 *  Forward declarations for all Duktape structures.
 */

#if !defined(DUK_FORWDECL_H_INCLUDED)
#define DUK_FORWDECL_H_INCLUDED

/*
 *  Forward declarations
 */

#if defined(DUK_USE_CPP_EXCEPTIONS)
class duk_internal_exception;
#else
struct duk_jmpbuf;
#endif

/* duk_tval intentionally skipped */
struct duk_heaphdr;
struct duk_heaphdr_string;
struct duk_harray;
struct duk_hstring;
struct duk_hstring_external;
struct duk_hobject;
struct duk_hcompfunc;
struct duk_hnatfunc;
struct duk_hboundfunc;
struct duk_hthread;
struct duk_hbufobj;
struct duk_hdecenv;
struct duk_hobjenv;
struct duk_hproxy;
struct duk_hbuffer;
struct duk_hbuffer_fixed;
struct duk_hbuffer_dynamic;
struct duk_hbuffer_external;

struct duk_propaccessor;
union duk_propvalue;
struct duk_propdesc;

struct duk_heap;
struct duk_breakpoint;

struct duk_activation;
struct duk_catcher;
struct duk_ljstate;
struct duk_strcache_entry;
struct duk_litcache_entry;
struct duk_strtab_entry;

#if defined(DUK_USE_DEBUG)
struct duk_fixedbuffer;
#endif

struct duk_bitdecoder_ctx;
struct duk_bitencoder_ctx;
struct duk_bufwriter_ctx;

struct duk_token;
struct duk_re_token;
struct duk_lexer_point;
struct duk_lexer_ctx;
struct duk_lexer_codepoint;

struct duk_compiler_instr;
struct duk_compiler_func;
struct duk_compiler_ctx;

struct duk_re_matcher_ctx;
struct duk_re_compiler_ctx;

#if defined(DUK_USE_CPP_EXCEPTIONS)
/* no typedef */
#else
typedef struct duk_jmpbuf duk_jmpbuf;
#endif

/* duk_tval intentionally skipped */
typedef struct duk_heaphdr duk_heaphdr;
typedef struct duk_heaphdr_string duk_heaphdr_string;
typedef struct duk_harray duk_harray;
typedef struct duk_hstring duk_hstring;
typedef struct duk_hstring_external duk_hstring_external;
typedef struct duk_hobject duk_hobject;
typedef struct duk_hcompfunc duk_hcompfunc;
typedef struct duk_hnatfunc duk_hnatfunc;
typedef struct duk_hboundfunc duk_hboundfunc;
typedef struct duk_hthread duk_hthread;
typedef struct duk_hbufobj duk_hbufobj;
typedef struct duk_hdecenv duk_hdecenv;
typedef struct duk_hobjenv duk_hobjenv;
typedef struct duk_hproxy duk_hproxy;
typedef struct duk_hbuffer duk_hbuffer;
typedef struct duk_hbuffer_fixed duk_hbuffer_fixed;
typedef struct duk_hbuffer_dynamic duk_hbuffer_dynamic;
typedef struct duk_hbuffer_external duk_hbuffer_external;

typedef struct duk_propaccessor duk_propaccessor;
typedef union duk_propvalue duk_propvalue;
typedef struct duk_propdesc duk_propdesc;

typedef struct duk_heap duk_heap;
typedef struct duk_breakpoint duk_breakpoint;

typedef struct duk_activation duk_activation;
typedef struct duk_catcher duk_catcher;
typedef struct duk_ljstate duk_ljstate;
typedef struct duk_strcache_entry duk_strcache_entry;
typedef struct duk_litcache_entry duk_litcache_entry;
typedef struct duk_strtab_entry duk_strtab_entry;

#if defined(DUK_USE_DEBUG)
typedef struct duk_fixedbuffer duk_fixedbuffer;
#endif

typedef struct duk_bitdecoder_ctx duk_bitdecoder_ctx;
typedef struct duk_bitencoder_ctx duk_bitencoder_ctx;
typedef struct duk_bufwriter_ctx duk_bufwriter_ctx;

typedef struct duk_token duk_token;
typedef struct duk_re_token duk_re_token;
typedef struct duk_lexer_point duk_lexer_point;
typedef struct duk_lexer_ctx duk_lexer_ctx;
typedef struct duk_lexer_codepoint duk_lexer_codepoint;

typedef struct duk_compiler_instr duk_compiler_instr;
typedef struct duk_compiler_func duk_compiler_func;
typedef struct duk_compiler_ctx duk_compiler_ctx;

typedef struct duk_re_matcher_ctx duk_re_matcher_ctx;
typedef struct duk_re_compiler_ctx duk_re_compiler_ctx;

#endif  /* DUK_FORWDECL_H_INCLUDED */
/* #include duk_tval.h */
#line 1 "duk_tval.h"
/*
 *  Tagged type definition (duk_tval) and accessor macros.
 *
 *  Access all fields through the accessor macros, as the representation
 *  is quite tricky.
 *
 *  There are two packed type alternatives: an 8-byte representation
 *  based on an IEEE double (preferred for compactness), and a 12-byte
 *  representation (portability).  The latter is needed also in e.g.
 *  64-bit environments (it usually pads to 16 bytes per value).
 *
 *  Selecting the tagged type format involves many trade-offs (memory
 *  use, size and performance of generated code, portability, etc).
 *
 *  NB: because macro arguments are often expressions, macros should
 *  avoid evaluating their argument more than once.
 */

#if !defined(DUK_TVAL_H_INCLUDED)
#define DUK_TVAL_H_INCLUDED

/* sanity */
#if !defined(DUK_USE_DOUBLE_LE) && !defined(DUK_USE_DOUBLE_ME) && !defined(DUK_USE_DOUBLE_BE)
#error unsupported: cannot determine byte order variant
#endif

#if defined(DUK_USE_PACKED_TVAL)
/* ======================================================================== */

/*
 *  Packed 8-byte representation
 */

/* use duk_double_union as duk_tval directly */
typedef union duk_double_union duk_tval;
typedef struct {
	duk_uint16_t a;
	duk_uint16_t b;
	duk_uint16_t c;
	duk_uint16_t d;
} duk_tval_unused;

/* tags */
#define DUK_TAG_NORMALIZED_NAN    0x7ff8UL   /* the NaN variant we use */
/* avoid tag 0xfff0, no risk of confusion with negative infinity */
#define DUK_TAG_MIN               0xfff1UL
#if defined(DUK_USE_FASTINT)
#define DUK_TAG_FASTINT           0xfff1UL   /* embed: integer value */
#endif
#define DUK_TAG_UNUSED            0xfff2UL   /* marker; not actual tagged value */
#define DUK_TAG_UNDEFINED         0xfff3UL   /* embed: nothing */
#define DUK_TAG_NULL              0xfff4UL   /* embed: nothing */
#define DUK_TAG_BOOLEAN           0xfff5UL   /* embed: 0 or 1 (false or true) */
/* DUK_TAG_NUMBER would logically go here, but it has multiple 'tags' */
#define DUK_TAG_POINTER           0xfff6UL   /* embed: void ptr */
#define DUK_TAG_LIGHTFUNC         0xfff7UL   /* embed: func ptr */
#define DUK_TAG_STRING            0xfff8UL   /* embed: duk_hstring ptr */
#define DUK_TAG_OBJECT            0xfff9UL   /* embed: duk_hobject ptr */
#define DUK_TAG_BUFFER            0xfffaUL   /* embed: duk_hbuffer ptr */
#define DUK_TAG_MAX               0xfffaUL

/* for convenience */
#define DUK_XTAG_BOOLEAN_FALSE    0xfff50000UL
#define DUK_XTAG_BOOLEAN_TRUE     0xfff50001UL

#define DUK_TVAL_IS_VALID_TAG(tv) \
	(DUK_TVAL_GET_TAG((tv)) - DUK_TAG_MIN <= DUK_TAG_MAX - DUK_TAG_MIN)

/* DUK_TVAL_UNUSED initializer for duk_tval_unused, works for any endianness. */
#define DUK_TVAL_UNUSED_INITIALIZER() \
	{ DUK_TAG_UNUSED, DUK_TAG_UNUSED, DUK_TAG_UNUSED, DUK_TAG_UNUSED }

/* two casts to avoid gcc warning: "warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]" */
#if defined(DUK_USE_64BIT_OPS)
#if defined(DUK_USE_DOUBLE_ME)
#define DUK__TVAL_SET_TAGGEDPOINTER(tv,h,tag)  do { \
		(tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) (tag)) << 16) | (((duk_uint64_t) (duk_uint32_t) (h)) << 32); \
	} while (0)
#else
#define DUK__TVAL_SET_TAGGEDPOINTER(tv,h,tag)  do { \
		(tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) (tag)) << 48) | ((duk_uint64_t) (duk_uint32_t) (h)); \
	} while (0)
#endif
#else  /* DUK_USE_64BIT_OPS */
#define DUK__TVAL_SET_TAGGEDPOINTER(tv,h,tag)  do { \
		duk_tval *duk__tv; \
		duk__tv = (tv); \
		duk__tv->ui[DUK_DBL_IDX_UI0] = ((duk_uint32_t) (tag)) << 16; \
		duk__tv->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (h); \
	} while (0)
#endif  /* DUK_USE_64BIT_OPS */

#if defined(DUK_USE_64BIT_OPS)
/* Double casting for pointer to avoid gcc warning (cast from pointer to integer of different size) */
#if defined(DUK_USE_DOUBLE_ME)
#define DUK__TVAL_SET_LIGHTFUNC(tv,fp,flags)  do { \
		(tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_LIGHTFUNC) << 16) | \
		                              ((duk_uint64_t) (flags)) | \
		                              (((duk_uint64_t) (duk_uint32_t) (fp)) << 32); \
	} while (0)
#else
#define DUK__TVAL_SET_LIGHTFUNC(tv,fp,flags)  do { \
		(tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_LIGHTFUNC) << 48) | \
		                              (((duk_uint64_t) (flags)) << 32) | \
		                              ((duk_uint64_t) (duk_uint32_t) (fp)); \
	} while (0)
#endif
#else  /* DUK_USE_64BIT_OPS */
#define DUK__TVAL_SET_LIGHTFUNC(tv,fp,flags)  do { \
		duk_tval *duk__tv; \
		duk__tv = (tv); \
		duk__tv->ui[DUK_DBL_IDX_UI0] = (((duk_uint32_t) DUK_TAG_LIGHTFUNC) << 16) | ((duk_uint32_t) (flags)); \
		duk__tv->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (fp); \
	} while (0)
#endif  /* DUK_USE_64BIT_OPS */

#if defined(DUK_USE_FASTINT)
/* Note: masking is done for 'i' to deal with negative numbers correctly */
#if defined(DUK_USE_DOUBLE_ME)
#define DUK__TVAL_SET_I48(tv,i)  do { \
		duk_tval *duk__tv; \
		duk__tv = (tv); \
		duk__tv->ui[DUK_DBL_IDX_UI0] = ((duk_uint32_t) DUK_TAG_FASTINT) << 16 | (((duk_uint32_t) ((i) >> 32)) & 0x0000ffffUL); \
		duk__tv->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (i); \
	} while (0)
#define DUK__TVAL_SET_U32(tv,i)  do { \
		duk_tval *duk__tv; \
		duk__tv = (tv); \
		duk__tv->ui[DUK_DBL_IDX_UI0] = ((duk_uint32_t) DUK_TAG_FASTINT) << 16; \
		duk__tv->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (i); \
	} while (0)
#else
#define DUK__TVAL_SET_I48(tv,i)  do { \
		(tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_FASTINT) << 48) | (((duk_uint64_t) (i)) & DUK_U64_CONSTANT(0x0000ffffffffffff)); \
	} while (0)
#define DUK__TVAL_SET_U32(tv,i)  do { \
		(tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_FASTINT) << 48) | (duk_uint64_t) (i); \
	} while (0)
#endif

/* This needs to go through a cast because sign extension is needed. */
#define DUK__TVAL_SET_I32(tv,i)  do { \
		duk_int64_t duk__tmp = (duk_int64_t) (i); \
		DUK_TVAL_SET_I48((tv), duk__tmp); \
	} while (0)

/* XXX: Clumsy sign extend and masking of 16 topmost bits. */
#if defined(DUK_USE_DOUBLE_ME)
#define DUK__TVAL_GET_FASTINT(tv)      (((duk_int64_t) ((((duk_uint64_t) (tv)->ui[DUK_DBL_IDX_UI0]) << 32) | ((duk_uint64_t) (tv)->ui[DUK_DBL_IDX_UI1]))) << 16 >> 16)
#else
#define DUK__TVAL_GET_FASTINT(tv)      ((((duk_int64_t) (tv)->ull[DUK_DBL_IDX_ULL0]) << 16) >> 16)
#endif
#define DUK__TVAL_GET_FASTINT_U32(tv)  ((tv)->ui[DUK_DBL_IDX_UI1])
#define DUK__TVAL_GET_FASTINT_I32(tv)  ((duk_int32_t) (tv)->ui[DUK_DBL_IDX_UI1])
#endif  /* DUK_USE_FASTINT */

#define DUK_TVAL_SET_UNDEFINED(tv)  do { \
		(tv)->us[DUK_DBL_IDX_US0] = (duk_uint16_t) DUK_TAG_UNDEFINED; \
	} while (0)
#define DUK_TVAL_SET_UNUSED(tv)  do { \
		(tv)->us[DUK_DBL_IDX_US0] = (duk_uint16_t) DUK_TAG_UNUSED; \
	} while (0)
#define DUK_TVAL_SET_NULL(tv)  do { \
		(tv)->us[DUK_DBL_IDX_US0] = (duk_uint16_t) DUK_TAG_NULL; \
	} while (0)

#define DUK_TVAL_SET_BOOLEAN(tv,val)         DUK_DBLUNION_SET_HIGH32((tv), (((duk_uint32_t) DUK_TAG_BOOLEAN) << 16) | ((duk_uint32_t) (val)))

#define DUK_TVAL_SET_NAN(tv)                 DUK_DBLUNION_SET_NAN_FULL((tv))

/* Assumes that caller has normalized NaNs, otherwise trouble ahead. */
#if defined(DUK_USE_FASTINT)
#define DUK_TVAL_SET_DOUBLE(tv,d)  do { \
		duk_double_t duk__dblval; \
		duk__dblval = (d); \
		DUK_ASSERT_DOUBLE_IS_NORMALIZED(duk__dblval); \
		DUK_DBLUNION_SET_DOUBLE((tv), duk__dblval); \
	} while (0)
#define DUK_TVAL_SET_I48(tv,i)               DUK__TVAL_SET_I48((tv), (i))
#define DUK_TVAL_SET_I32(tv,i)               DUK__TVAL_SET_I32((tv), (i))
#define DUK_TVAL_SET_U32(tv,i)               DUK__TVAL_SET_U32((tv), (i))
#define DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv,d)  duk_tval_set_number_chkfast_fast((tv), (d))
#define DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv,d)  duk_tval_set_number_chkfast_slow((tv), (d))
#define DUK_TVAL_SET_NUMBER(tv,d)            DUK_TVAL_SET_DOUBLE((tv), (d))
#define DUK_TVAL_CHKFAST_INPLACE_FAST(tv)  do { \
		duk_tval *duk__tv; \
		duk_double_t duk__d; \
		duk__tv = (tv); \
		if (DUK_TVAL_IS_DOUBLE(duk__tv)) { \
			duk__d = DUK_TVAL_GET_DOUBLE(duk__tv); \
			DUK_TVAL_SET_NUMBER_CHKFAST_FAST(duk__tv, duk__d); \
		} \
	} while (0)
#define DUK_TVAL_CHKFAST_INPLACE_SLOW(tv)  do { \
		duk_tval *duk__tv; \
		duk_double_t duk__d; \
		duk__tv = (tv); \
		if (DUK_TVAL_IS_DOUBLE(duk__tv)) { \
			duk__d = DUK_TVAL_GET_DOUBLE(duk__tv); \
			DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(duk__tv, duk__d); \
		} \
	} while (0)
#else  /* DUK_USE_FASTINT */
#define DUK_TVAL_SET_DOUBLE(tv,d)  do { \
		duk_double_t duk__dblval; \
		duk__dblval = (d); \
		DUK_ASSERT_DOUBLE_IS_NORMALIZED(duk__dblval); \
		DUK_DBLUNION_SET_DOUBLE((tv), duk__dblval); \
	} while (0)
#define DUK_TVAL_SET_I48(tv,i)               DUK_TVAL_SET_DOUBLE((tv), (duk_double_t) (i))  /* XXX: fast int-to-double */
#define DUK_TVAL_SET_I32(tv,i)               DUK_TVAL_SET_DOUBLE((tv), (duk_double_t) (i))
#define DUK_TVAL_SET_U32(tv,i)               DUK_TVAL_SET_DOUBLE((tv), (duk_double_t) (i))
#define DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv,d)    DUK_TVAL_SET_DOUBLE((tv), (d))
#define DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv,d)    DUK_TVAL_SET_DOUBLE((tv), (d))
#define DUK_TVAL_SET_NUMBER(tv,d)            DUK_TVAL_SET_DOUBLE((tv), (d))
#define DUK_TVAL_CHKFAST_INPLACE_FAST(tv)  do { } while (0)
#define DUK_TVAL_CHKFAST_INPLACE_SLOW(tv)  do { } while (0)
#endif  /* DUK_USE_FASTINT */

#define DUK_TVAL_SET_FASTINT(tv,i)           DUK_TVAL_SET_I48((tv), (i))  /* alias */

#define DUK_TVAL_SET_LIGHTFUNC(tv,fp,flags)  DUK__TVAL_SET_LIGHTFUNC((tv), (fp), (flags))
#define DUK_TVAL_SET_STRING(tv,h)            DUK__TVAL_SET_TAGGEDPOINTER((tv), (h), DUK_TAG_STRING)
#define DUK_TVAL_SET_OBJECT(tv,h)            DUK__TVAL_SET_TAGGEDPOINTER((tv), (h), DUK_TAG_OBJECT)
#define DUK_TVAL_SET_BUFFER(tv,h)            DUK__TVAL_SET_TAGGEDPOINTER((tv), (h), DUK_TAG_BUFFER)
#define DUK_TVAL_SET_POINTER(tv,p)           DUK__TVAL_SET_TAGGEDPOINTER((tv), (p), DUK_TAG_POINTER)

#define DUK_TVAL_SET_TVAL(tv,x)              do { *(tv) = *(x); } while (0)

/* getters */
#define DUK_TVAL_GET_BOOLEAN(tv)             ((duk_small_uint_t) (tv)->us[DUK_DBL_IDX_US1])
#if defined(DUK_USE_FASTINT)
#define DUK_TVAL_GET_DOUBLE(tv)              ((tv)->d)
#define DUK_TVAL_GET_FASTINT(tv)             DUK__TVAL_GET_FASTINT((tv))
#define DUK_TVAL_GET_FASTINT_U32(tv)         DUK__TVAL_GET_FASTINT_U32((tv))
#define DUK_TVAL_GET_FASTINT_I32(tv)         DUK__TVAL_GET_FASTINT_I32((tv))
#define DUK_TVAL_GET_NUMBER(tv)              duk_tval_get_number_packed((tv))
#else
#define DUK_TVAL_GET_NUMBER(tv)              ((tv)->d)
#define DUK_TVAL_GET_DOUBLE(tv)              ((tv)->d)
#endif
#define DUK_TVAL_GET_LIGHTFUNC(tv,out_fp,out_flags)  do { \
		(out_flags) = (tv)->ui[DUK_DBL_IDX_UI0] & 0xffffUL; \
		(out_fp) = (duk_c_function) (tv)->ui[DUK_DBL_IDX_UI1]; \
	} while (0)
#define DUK_TVAL_GET_LIGHTFUNC_FUNCPTR(tv)   ((duk_c_function) ((tv)->ui[DUK_DBL_IDX_UI1]))
#define DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv)     (((duk_small_uint_t) (tv)->ui[DUK_DBL_IDX_UI0]) & 0xffffUL)
#define DUK_TVAL_GET_STRING(tv)              ((duk_hstring *) (tv)->vp[DUK_DBL_IDX_VP1])
#define DUK_TVAL_GET_OBJECT(tv)              ((duk_hobject *) (tv)->vp[DUK_DBL_IDX_VP1])
#define DUK_TVAL_GET_BUFFER(tv)              ((duk_hbuffer *) (tv)->vp[DUK_DBL_IDX_VP1])
#define DUK_TVAL_GET_POINTER(tv)             ((void *) (tv)->vp[DUK_DBL_IDX_VP1])
#define DUK_TVAL_GET_HEAPHDR(tv)             ((duk_heaphdr *) (tv)->vp[DUK_DBL_IDX_VP1])

/* decoding */
#define DUK_TVAL_GET_TAG(tv)                 ((duk_small_uint_t) (tv)->us[DUK_DBL_IDX_US0])

#define DUK_TVAL_IS_UNDEFINED(tv)            (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_UNDEFINED)
#define DUK_TVAL_IS_UNUSED(tv)               (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_UNUSED)
#define DUK_TVAL_IS_NULL(tv)                 (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_NULL)
#define DUK_TVAL_IS_BOOLEAN(tv)              (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_BOOLEAN)
#define DUK_TVAL_IS_BOOLEAN_TRUE(tv)         ((tv)->ui[DUK_DBL_IDX_UI0] == DUK_XTAG_BOOLEAN_TRUE)
#define DUK_TVAL_IS_BOOLEAN_FALSE(tv)        ((tv)->ui[DUK_DBL_IDX_UI0] == DUK_XTAG_BOOLEAN_FALSE)
#define DUK_TVAL_IS_LIGHTFUNC(tv)            (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_LIGHTFUNC)
#define DUK_TVAL_IS_STRING(tv)               (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_STRING)
#define DUK_TVAL_IS_OBJECT(tv)               (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_OBJECT)
#define DUK_TVAL_IS_BUFFER(tv)               (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_BUFFER)
#define DUK_TVAL_IS_POINTER(tv)              (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_POINTER)
#if defined(DUK_USE_FASTINT)
/* 0xfff0 is -Infinity */
#define DUK_TVAL_IS_DOUBLE(tv)               (DUK_TVAL_GET_TAG((tv)) <= 0xfff0UL)
#define DUK_TVAL_IS_FASTINT(tv)              (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_FASTINT)
#define DUK_TVAL_IS_NUMBER(tv)               (DUK_TVAL_GET_TAG((tv)) <= 0xfff1UL)
#else
#define DUK_TVAL_IS_NUMBER(tv)               (DUK_TVAL_GET_TAG((tv)) <= 0xfff0UL)
#define DUK_TVAL_IS_DOUBLE(tv)               DUK_TVAL_IS_NUMBER((tv))
#endif

/* This is performance critical because it appears in every DECREF. */
#define DUK_TVAL_IS_HEAP_ALLOCATED(tv)       (DUK_TVAL_GET_TAG((tv)) >= DUK_TAG_STRING)

#if defined(DUK_USE_FASTINT)
DUK_INTERNAL_DECL duk_double_t duk_tval_get_number_packed(duk_tval *tv);
#endif

#else  /* DUK_USE_PACKED_TVAL */
/* ======================================================================== */

/*
 *  Portable 12-byte representation
 */

/* Note: not initializing all bytes is normally not an issue: Duktape won't
 * read or use the uninitialized bytes so valgrind won't issue warnings.
 * In some special cases a harmless valgrind warning may be issued though.
 * For example, the DumpHeap debugger command writes out a compiled function's
 * 'data' area as is, including any uninitialized bytes, which causes a
 * valgrind warning.
 */

typedef struct duk_tval_struct duk_tval;

struct duk_tval_struct {
	duk_small_uint_t t;
	duk_small_uint_t v_extra;
	union {
		duk_double_t d;
		duk_small_int_t i;
#if defined(DUK_USE_FASTINT)
		duk_int64_t fi;  /* if present, forces 16-byte duk_tval */
#endif
		void *voidptr;
		duk_hstring *hstring;
		duk_hobject *hobject;
		duk_hcompfunc *hcompfunc;
		duk_hnatfunc *hnatfunc;
		duk_hthread *hthread;
		duk_hbuffer *hbuffer;
		duk_heaphdr *heaphdr;
		duk_c_function lightfunc;
	} v;
};

typedef struct {
	duk_small_uint_t t;
	duk_small_uint_t v_extra;
	/* The rest of the fields don't matter except for debug dumps and such
	 * for which a partial initializer may trigger out-ot-bounds memory
	 * reads.  Include a double field which is usually as large or larger
	 * than pointers (not always however).
	 */
	duk_double_t d;
} duk_tval_unused;

#define DUK_TVAL_UNUSED_INITIALIZER() \
	{ DUK_TAG_UNUSED, 0, 0.0 }

#define DUK_TAG_MIN                   0
#define DUK_TAG_NUMBER                0  /* DUK_TAG_NUMBER only defined for non-packed duk_tval */
#if defined(DUK_USE_FASTINT)
#define DUK_TAG_FASTINT               1
#endif
#define DUK_TAG_UNDEFINED             2
#define DUK_TAG_NULL                  3
#define DUK_TAG_BOOLEAN               4
#define DUK_TAG_POINTER               5
#define DUK_TAG_LIGHTFUNC             6
#define DUK_TAG_UNUSED                7  /* marker; not actual tagged type */
#define DUK_TAG_STRING                8  /* first heap allocated, match bit boundary */
#define DUK_TAG_OBJECT                9
#define DUK_TAG_BUFFER                10
#define DUK_TAG_MAX                   10

#define DUK_TVAL_IS_VALID_TAG(tv) \
	(DUK_TVAL_GET_TAG((tv)) - DUK_TAG_MIN <= DUK_TAG_MAX - DUK_TAG_MIN)

/* DUK_TAG_NUMBER is intentionally first, as it is the default clause in code
 * to support the 8-byte representation.  Further, it is a non-heap-allocated
 * type so it should come before DUK_TAG_STRING.  Finally, it should not break
 * the tag value ranges covered by case-clauses in a switch-case.
 */

/* setters */
#define DUK_TVAL_SET_UNDEFINED(tv)  do { \
		duk_tval *duk__tv; \
		duk__tv = (tv); \
		duk__tv->t = DUK_TAG_UNDEFINED; \
	} while (0)

#define DUK_TVAL_SET_UNUSED(tv)  do { \
		duk_tval *duk__tv; \
		duk__tv = (tv); \
		duk__tv->t = DUK_TAG_UNUSED; \
	} while (0)

#define DUK_TVAL_SET_NULL(tv)  do { \
		duk_tval *duk__tv; \
		duk__tv = (tv); \
		duk__tv->t = DUK_TAG_NULL; \
	} while (0)

#define DUK_TVAL_SET_BOOLEAN(tv,val)  do { \
		duk_tval *duk__tv; \
		duk__tv = (tv); \
		duk__tv->t = DUK_TAG_BOOLEAN; \
		duk__tv->v.i = (duk_small_int_t) (val); \
	} while (0)

#if defined(DUK_USE_FASTINT)
#define DUK_TVAL_SET_DOUBLE(tv,val)  do { \
		duk_tval *duk__tv; \
		duk_double_t duk__dblval; \
		duk__dblval = (val); \
		DUK_ASSERT_DOUBLE_IS_NORMALIZED(duk__dblval); /* nop for unpacked duk_tval */ \
		duk__tv = (tv); \
		duk__tv->t = DUK_TAG_NUMBER; \
		duk__tv->v.d = duk__dblval; \
	} while (0)
#define DUK_TVAL_SET_I48(tv,val)  do { \
		duk_tval *duk__tv; \
		duk__tv = (tv); \
		duk__tv->t = DUK_TAG_FASTINT; \
		duk__tv->v.fi = (val); \
	} while (0)
#define DUK_TVAL_SET_U32(tv,val)  do { \
		duk_tval *duk__tv; \
		duk__tv = (tv); \
		duk__tv->t = DUK_TAG_FASTINT; \
		duk__tv->v.fi = (duk_int64_t) (val); \
	} while (0)
#define DUK_TVAL_SET_I32(tv,val)  do { \
		duk_tval *duk__tv; \
		duk__tv = (tv); \
		duk__tv->t = DUK_TAG_FASTINT; \
		duk__tv->v.fi = (duk_int64_t) (val); \
	} while (0)
#define DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv,d) \
	duk_tval_set_number_chkfast_fast((tv), (d))
#define DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv,d) \
	duk_tval_set_number_chkfast_slow((tv), (d))
#define DUK_TVAL_SET_NUMBER(tv,val) \
	DUK_TVAL_SET_DOUBLE((tv), (val))
#define DUK_TVAL_CHKFAST_INPLACE_FAST(tv)  do { \
		duk_tval *duk__tv; \
		duk_double_t duk__d; \
		duk__tv = (tv); \
		if (DUK_TVAL_IS_DOUBLE(duk__tv)) { \
			duk__d = DUK_TVAL_GET_DOUBLE(duk__tv); \
			DUK_TVAL_SET_NUMBER_CHKFAST_FAST(duk__tv, duk__d); \
		} \
	} while (0)
#define DUK_TVAL_CHKFAST_INPLACE_SLOW(tv)  do { \
		duk_tval *duk__tv; \
		duk_double_t duk__d; \
		duk__tv = (tv); \
		if (DUK_TVAL_IS_DOUBLE(duk__tv)) { \
			duk__d = DUK_TVAL_GET_DOUBLE(duk__tv); \
			DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(duk__tv, duk__d); \
		} \
	} while (0)
#else  /* DUK_USE_FASTINT */
#define DUK_TVAL_SET_DOUBLE(tv,d) \
	DUK_TVAL_SET_NUMBER((tv), (d))
#define DUK_TVAL_SET_I48(tv,val) \
	DUK_TVAL_SET_NUMBER((tv), (duk_double_t) (val))  /* XXX: fast int-to-double */
#define DUK_TVAL_SET_U32(tv,val) \
	DUK_TVAL_SET_NUMBER((tv), (duk_double_t) (val))
#define DUK_TVAL_SET_I32(tv,val) \
	DUK_TVAL_SET_NUMBER((tv), (duk_double_t) (val))
#define DUK_TVAL_SET_NUMBER(tv,val)  do { \
		duk_tval *duk__tv; \
		duk_double_t duk__dblval; \
		duk__dblval = (val); \
		DUK_ASSERT_DOUBLE_IS_NORMALIZED(duk__dblval); /* nop for unpacked duk_tval */ \
		duk__tv = (tv); \
		duk__tv->t = DUK_TAG_NUMBER; \
		duk__tv->v.d = duk__dblval; \
	} while (0)
#define DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv,d) \
	DUK_TVAL_SET_NUMBER((tv), (d))
#define DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv,d) \
	DUK_TVAL_SET_NUMBER((tv), (d))
#define DUK_TVAL_CHKFAST_INPLACE_FAST(tv)  do { } while (0)
#define DUK_TVAL_CHKFAST_INPLACE_SLOW(tv)  do { } while (0)
#endif  /* DUK_USE_FASTINT */

#define DUK_TVAL_SET_FASTINT(tv,i) \
	DUK_TVAL_SET_I48((tv), (i))  /* alias */

#define DUK_TVAL_SET_POINTER(tv,hptr)  do { \
		duk_tval *duk__tv; \
		duk__tv = (tv); \
		duk__tv->t = DUK_TAG_POINTER; \
		duk__tv->v.voidptr = (hptr); \
	} while (0)

#define DUK_TVAL_SET_LIGHTFUNC(tv,fp,flags)  do { \
		duk_tval *duk__tv; \
		duk__tv = (tv); \
		duk__tv->t = DUK_TAG_LIGHTFUNC; \
		duk__tv->v_extra = (flags); \
		duk__tv->v.lightfunc = (duk_c_function) (fp); \
	} while (0)

#define DUK_TVAL_SET_STRING(tv,hptr)  do { \
		duk_tval *duk__tv; \
		duk__tv = (tv); \
		duk__tv->t = DUK_TAG_STRING; \
		duk__tv->v.hstring = (hptr); \
	} while (0)

#define DUK_TVAL_SET_OBJECT(tv,hptr)  do { \
		duk_tval *duk__tv; \
		duk__tv = (tv); \
		duk__tv->t = DUK_TAG_OBJECT; \
		duk__tv->v.hobject = (hptr); \
	} while (0)

#define DUK_TVAL_SET_BUFFER(tv,hptr)  do { \
		duk_tval *duk__tv; \
		duk__tv = (tv); \
		duk__tv->t = DUK_TAG_BUFFER; \
		duk__tv->v.hbuffer = (hptr); \
	} while (0)

#define DUK_TVAL_SET_NAN(tv)  do { \
		/* in non-packed representation we don't care about which NaN is used */ \
		duk_tval *duk__tv; \
		duk__tv = (tv); \
		duk__tv->t = DUK_TAG_NUMBER; \
		duk__tv->v.d = DUK_DOUBLE_NAN; \
	} while (0)

#define DUK_TVAL_SET_TVAL(tv,x)            do { *(tv) = *(x); } while (0)

/* getters */
#define DUK_TVAL_GET_BOOLEAN(tv)           ((duk_small_uint_t) (tv)->v.i)
#if defined(DUK_USE_FASTINT)
#define DUK_TVAL_GET_DOUBLE(tv)            ((tv)->v.d)
#define DUK_TVAL_GET_FASTINT(tv)           ((tv)->v.fi)
#define DUK_TVAL_GET_FASTINT_U32(tv)       ((duk_uint32_t) ((tv)->v.fi))
#define DUK_TVAL_GET_FASTINT_I32(tv)       ((duk_int32_t) ((tv)->v.fi))
#if 0
#define DUK_TVAL_GET_NUMBER(tv)            (DUK_TVAL_IS_FASTINT((tv)) ? \
                                               (duk_double_t) DUK_TVAL_GET_FASTINT((tv)) : \
                                               DUK_TVAL_GET_DOUBLE((tv)))
#define DUK_TVAL_GET_NUMBER(tv)            duk_tval_get_number_unpacked((tv))
#else
/* This seems reasonable overall. */
#define DUK_TVAL_GET_NUMBER(tv)            (DUK_TVAL_IS_FASTINT((tv)) ? \
                                               duk_tval_get_number_unpacked_fastint((tv)) : \
                                               DUK_TVAL_GET_DOUBLE((tv)))
#endif
#else
#define DUK_TVAL_GET_NUMBER(tv)            ((tv)->v.d)
#define DUK_TVAL_GET_DOUBLE(tv)            ((tv)->v.d)
#endif  /* DUK_USE_FASTINT */
#define DUK_TVAL_GET_POINTER(tv)           ((tv)->v.voidptr)
#define DUK_TVAL_GET_LIGHTFUNC(tv,out_fp,out_flags)  do { \
		(out_flags) = (duk_uint32_t) (tv)->v_extra; \
		(out_fp) = (tv)->v.lightfunc; \
	} while (0)
#define DUK_TVAL_GET_LIGHTFUNC_FUNCPTR(tv) ((tv)->v.lightfunc)
#define DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv)   ((duk_small_uint_t) ((tv)->v_extra))
#define DUK_TVAL_GET_STRING(tv)            ((tv)->v.hstring)
#define DUK_TVAL_GET_OBJECT(tv)            ((tv)->v.hobject)
#define DUK_TVAL_GET_BUFFER(tv)            ((tv)->v.hbuffer)
#define DUK_TVAL_GET_HEAPHDR(tv)           ((tv)->v.heaphdr)

/* decoding */
#define DUK_TVAL_GET_TAG(tv)               ((tv)->t)
#define DUK_TVAL_IS_UNDEFINED(tv)          ((tv)->t == DUK_TAG_UNDEFINED)
#define DUK_TVAL_IS_UNUSED(tv)             ((tv)->t == DUK_TAG_UNUSED)
#define DUK_TVAL_IS_NULL(tv)               ((tv)->t == DUK_TAG_NULL)
#define DUK_TVAL_IS_BOOLEAN(tv)            ((tv)->t == DUK_TAG_BOOLEAN)
#define DUK_TVAL_IS_BOOLEAN_TRUE(tv)       (((tv)->t == DUK_TAG_BOOLEAN) && ((tv)->v.i != 0))
#define DUK_TVAL_IS_BOOLEAN_FALSE(tv)      (((tv)->t == DUK_TAG_BOOLEAN) && ((tv)->v.i == 0))
#if defined(DUK_USE_FASTINT)
#define DUK_TVAL_IS_DOUBLE(tv)             ((tv)->t == DUK_TAG_NUMBER)
#define DUK_TVAL_IS_FASTINT(tv)            ((tv)->t == DUK_TAG_FASTINT)
#define DUK_TVAL_IS_NUMBER(tv)             ((tv)->t == DUK_TAG_NUMBER || \
                                            (tv)->t == DUK_TAG_FASTINT)
#else
#define DUK_TVAL_IS_NUMBER(tv)             ((tv)->t == DUK_TAG_NUMBER)
#define DUK_TVAL_IS_DOUBLE(tv)             DUK_TVAL_IS_NUMBER((tv))
#endif  /* DUK_USE_FASTINT */
#define DUK_TVAL_IS_POINTER(tv)            ((tv)->t == DUK_TAG_POINTER)
#define DUK_TVAL_IS_LIGHTFUNC(tv)          ((tv)->t == DUK_TAG_LIGHTFUNC)
#define DUK_TVAL_IS_STRING(tv)             ((tv)->t == DUK_TAG_STRING)
#define DUK_TVAL_IS_OBJECT(tv)             ((tv)->t == DUK_TAG_OBJECT)
#define DUK_TVAL_IS_BUFFER(tv)             ((tv)->t == DUK_TAG_BUFFER)

/* This is performance critical because it's needed for every DECREF.
 * Take advantage of the fact that the first heap allocated tag is 8,
 * so that bit 3 is set for all heap allocated tags (and never set for
 * non-heap-allocated tags).
 */
#if 0
#define DUK_TVAL_IS_HEAP_ALLOCATED(tv)     ((tv)->t >= DUK_TAG_STRING)
#endif
#define DUK_TVAL_IS_HEAP_ALLOCATED(tv)     ((tv)->t & 0x08)

#if defined(DUK_USE_FASTINT)
#if 0
DUK_INTERNAL_DECL duk_double_t duk_tval_get_number_unpacked(duk_tval *tv);
#endif
DUK_INTERNAL_DECL duk_double_t duk_tval_get_number_unpacked_fastint(duk_tval *tv);
#endif

#endif  /* DUK_USE_PACKED_TVAL */

/*
 *  Convenience (independent of representation)
 */

#define DUK_TVAL_SET_BOOLEAN_TRUE(tv)        DUK_TVAL_SET_BOOLEAN((tv), 1)
#define DUK_TVAL_SET_BOOLEAN_FALSE(tv)       DUK_TVAL_SET_BOOLEAN((tv), 0)

#define DUK_TVAL_STRING_IS_SYMBOL(tv) \
	DUK_HSTRING_HAS_SYMBOL(DUK_TVAL_GET_STRING((tv)))

/* Lightfunc flags packing and unpacking. */
/* Sign extend: 0x0000##00 -> 0x##000000 -> sign extend to 0xssssss##.
 * Avoid signed shifts due to portability limitations.
 */
#define DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags) \
	((duk_int32_t) (duk_int8_t) (((duk_uint16_t) (lf_flags)) >> 8))
#define DUK_LFUNC_FLAGS_GET_LENGTH(lf_flags) \
	(((lf_flags) >> 4) & 0x0fU)
#define DUK_LFUNC_FLAGS_GET_NARGS(lf_flags) \
	((lf_flags) & 0x0fU)
#define DUK_LFUNC_FLAGS_PACK(magic,length,nargs) \
	((((duk_small_uint_t) (magic)) & 0xffU) << 8) | ((length) << 4) | (nargs)

#define DUK_LFUNC_NARGS_VARARGS             0x0f   /* varargs marker */
#define DUK_LFUNC_NARGS_MIN                 0x00
#define DUK_LFUNC_NARGS_MAX                 0x0e   /* max, excl. varargs marker */
#define DUK_LFUNC_LENGTH_MIN                0x00
#define DUK_LFUNC_LENGTH_MAX                0x0f
#define DUK_LFUNC_MAGIC_MIN                 (-0x80)
#define DUK_LFUNC_MAGIC_MAX                 0x7f

/* fastint constants etc */
#if defined(DUK_USE_FASTINT)
#define DUK_FASTINT_MIN           (DUK_I64_CONSTANT(-0x800000000000))
#define DUK_FASTINT_MAX           (DUK_I64_CONSTANT(0x7fffffffffff))
#define DUK_FASTINT_BITS          48

DUK_INTERNAL_DECL void duk_tval_set_number_chkfast_fast(duk_tval *tv, duk_double_t x);
DUK_INTERNAL_DECL void duk_tval_set_number_chkfast_slow(duk_tval *tv, duk_double_t x);
#endif

#if defined(DUK_USE_ASSERTIONS)
DUK_INTERNAL_DECL void duk_tval_assert_valid(duk_tval *tv);
#define DUK_TVAL_ASSERT_VALID(tv)  do { duk_tval_assert_valid((tv)); } while (0)
#else
#define DUK_TVAL_ASSERT_VALID(tv)  do {} while (0)
#endif

#endif  /* DUK_TVAL_H_INCLUDED */
/* #include duk_builtins.h */
#line 1 "duk_builtins.h"
/*
 *  Automatically generated by genbuiltins.py, do not edit!
 */

#if !defined(DUK_BUILTINS_H_INCLUDED)
#define DUK_BUILTINS_H_INCLUDED

#if defined(DUK_USE_ROM_STRINGS)
#error ROM support not enabled, rerun configure.py with --rom-support
#else  /* DUK_USE_ROM_STRINGS */
#define DUK_STRIDX_UC_UNDEFINED                                       0                              /* 'Undefined' */
#define DUK_HEAP_STRING_UC_UNDEFINED(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_UNDEFINED)
#define DUK_HTHREAD_STRING_UC_UNDEFINED(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_UNDEFINED)
#define DUK_STRIDX_UC_NULL                                            1                              /* 'Null' */
#define DUK_HEAP_STRING_UC_NULL(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_NULL)
#define DUK_HTHREAD_STRING_UC_NULL(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_NULL)
#define DUK_STRIDX_UC_SYMBOL                                          2                              /* 'Symbol' */
#define DUK_HEAP_STRING_UC_SYMBOL(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_SYMBOL)
#define DUK_HTHREAD_STRING_UC_SYMBOL(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_SYMBOL)
#define DUK_STRIDX_UC_ARGUMENTS                                       3                              /* 'Arguments' */
#define DUK_HEAP_STRING_UC_ARGUMENTS(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_ARGUMENTS)
#define DUK_HTHREAD_STRING_UC_ARGUMENTS(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_ARGUMENTS)
#define DUK_STRIDX_UC_OBJECT                                          4                              /* 'Object' */
#define DUK_HEAP_STRING_UC_OBJECT(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_OBJECT)
#define DUK_HTHREAD_STRING_UC_OBJECT(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_OBJECT)
#define DUK_STRIDX_UC_FUNCTION                                        5                              /* 'Function' */
#define DUK_HEAP_STRING_UC_FUNCTION(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_FUNCTION)
#define DUK_HTHREAD_STRING_UC_FUNCTION(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_FUNCTION)
#define DUK_STRIDX_UC_ARRAY                                           6                              /* 'Array' */
#define DUK_HEAP_STRING_UC_ARRAY(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_ARRAY)
#define DUK_HTHREAD_STRING_UC_ARRAY(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_ARRAY)
#define DUK_STRIDX_UC_STRING                                          7                              /* 'String' */
#define DUK_HEAP_STRING_UC_STRING(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_STRING)
#define DUK_HTHREAD_STRING_UC_STRING(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_STRING)
#define DUK_STRIDX_UC_BOOLEAN                                         8                              /* 'Boolean' */
#define DUK_HEAP_STRING_UC_BOOLEAN(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_BOOLEAN)
#define DUK_HTHREAD_STRING_UC_BOOLEAN(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_BOOLEAN)
#define DUK_STRIDX_UC_NUMBER                                          9                              /* 'Number' */
#define DUK_HEAP_STRING_UC_NUMBER(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_NUMBER)
#define DUK_HTHREAD_STRING_UC_NUMBER(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_NUMBER)
#define DUK_STRIDX_UC_DATE                                            10                             /* 'Date' */
#define DUK_HEAP_STRING_UC_DATE(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_DATE)
#define DUK_HTHREAD_STRING_UC_DATE(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_DATE)
#define DUK_STRIDX_REG_EXP                                            11                             /* 'RegExp' */
#define DUK_HEAP_STRING_REG_EXP(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_REG_EXP)
#define DUK_HTHREAD_STRING_REG_EXP(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_REG_EXP)
#define DUK_STRIDX_UC_ERROR                                           12                             /* 'Error' */
#define DUK_HEAP_STRING_UC_ERROR(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_ERROR)
#define DUK_HTHREAD_STRING_UC_ERROR(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_ERROR)
#define DUK_STRIDX_MATH                                               13                             /* 'Math' */
#define DUK_HEAP_STRING_MATH(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MATH)
#define DUK_HTHREAD_STRING_MATH(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MATH)
#define DUK_STRIDX_JSON                                               14                             /* 'JSON' */
#define DUK_HEAP_STRING_JSON(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON)
#define DUK_HTHREAD_STRING_JSON(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON)
#define DUK_STRIDX_EMPTY_STRING                                       15                             /* '' */
#define DUK_HEAP_STRING_EMPTY_STRING(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EMPTY_STRING)
#define DUK_HTHREAD_STRING_EMPTY_STRING(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EMPTY_STRING)
#define DUK_STRIDX_ARRAY_BUFFER                                       16                             /* 'ArrayBuffer' */
#define DUK_HEAP_STRING_ARRAY_BUFFER(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ARRAY_BUFFER)
#define DUK_HTHREAD_STRING_ARRAY_BUFFER(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ARRAY_BUFFER)
#define DUK_STRIDX_DATA_VIEW                                          17                             /* 'DataView' */
#define DUK_HEAP_STRING_DATA_VIEW(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DATA_VIEW)
#define DUK_HTHREAD_STRING_DATA_VIEW(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DATA_VIEW)
#define DUK_STRIDX_INT8_ARRAY                                         18                             /* 'Int8Array' */
#define DUK_HEAP_STRING_INT8_ARRAY(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT8_ARRAY)
#define DUK_HTHREAD_STRING_INT8_ARRAY(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT8_ARRAY)
#define DUK_STRIDX_UINT8_ARRAY                                        19                             /* 'Uint8Array' */
#define DUK_HEAP_STRING_UINT8_ARRAY(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT8_ARRAY)
#define DUK_HTHREAD_STRING_UINT8_ARRAY(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT8_ARRAY)
#define DUK_STRIDX_UINT8_CLAMPED_ARRAY                                20                             /* 'Uint8ClampedArray' */
#define DUK_HEAP_STRING_UINT8_CLAMPED_ARRAY(heap)                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT8_CLAMPED_ARRAY)
#define DUK_HTHREAD_STRING_UINT8_CLAMPED_ARRAY(thr)                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT8_CLAMPED_ARRAY)
#define DUK_STRIDX_INT16_ARRAY                                        21                             /* 'Int16Array' */
#define DUK_HEAP_STRING_INT16_ARRAY(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT16_ARRAY)
#define DUK_HTHREAD_STRING_INT16_ARRAY(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT16_ARRAY)
#define DUK_STRIDX_UINT16_ARRAY                                       22                             /* 'Uint16Array' */
#define DUK_HEAP_STRING_UINT16_ARRAY(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT16_ARRAY)
#define DUK_HTHREAD_STRING_UINT16_ARRAY(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT16_ARRAY)
#define DUK_STRIDX_INT32_ARRAY                                        23                             /* 'Int32Array' */
#define DUK_HEAP_STRING_INT32_ARRAY(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT32_ARRAY)
#define DUK_HTHREAD_STRING_INT32_ARRAY(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT32_ARRAY)
#define DUK_STRIDX_UINT32_ARRAY                                       24                             /* 'Uint32Array' */
#define DUK_HEAP_STRING_UINT32_ARRAY(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT32_ARRAY)
#define DUK_HTHREAD_STRING_UINT32_ARRAY(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT32_ARRAY)
#define DUK_STRIDX_FLOAT32_ARRAY                                      25                             /* 'Float32Array' */
#define DUK_HEAP_STRING_FLOAT32_ARRAY(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FLOAT32_ARRAY)
#define DUK_HTHREAD_STRING_FLOAT32_ARRAY(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FLOAT32_ARRAY)
#define DUK_STRIDX_FLOAT64_ARRAY                                      26                             /* 'Float64Array' */
#define DUK_HEAP_STRING_FLOAT64_ARRAY(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FLOAT64_ARRAY)
#define DUK_HTHREAD_STRING_FLOAT64_ARRAY(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FLOAT64_ARRAY)
#define DUK_STRIDX_GLOBAL                                             27                             /* 'global' */
#define DUK_HEAP_STRING_GLOBAL(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GLOBAL)
#define DUK_HTHREAD_STRING_GLOBAL(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GLOBAL)
#define DUK_STRIDX_OBJ_ENV                                            28                             /* 'ObjEnv' */
#define DUK_HEAP_STRING_OBJ_ENV(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_OBJ_ENV)
#define DUK_HTHREAD_STRING_OBJ_ENV(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_OBJ_ENV)
#define DUK_STRIDX_DEC_ENV                                            29                             /* 'DecEnv' */
#define DUK_HEAP_STRING_DEC_ENV(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DEC_ENV)
#define DUK_HTHREAD_STRING_DEC_ENV(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DEC_ENV)
#define DUK_STRIDX_UC_BUFFER                                          30                             /* 'Buffer' */
#define DUK_HEAP_STRING_UC_BUFFER(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_BUFFER)
#define DUK_HTHREAD_STRING_UC_BUFFER(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_BUFFER)
#define DUK_STRIDX_UC_POINTER                                         31                             /* 'Pointer' */
#define DUK_HEAP_STRING_UC_POINTER(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_POINTER)
#define DUK_HTHREAD_STRING_UC_POINTER(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_POINTER)
#define DUK_STRIDX_UC_THREAD                                          32                             /* 'Thread' */
#define DUK_HEAP_STRING_UC_THREAD(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_THREAD)
#define DUK_HTHREAD_STRING_UC_THREAD(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_THREAD)
#define DUK_STRIDX_EVAL                                               33                             /* 'eval' */
#define DUK_HEAP_STRING_EVAL(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EVAL)
#define DUK_HTHREAD_STRING_EVAL(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EVAL)
#define DUK_STRIDX_VALUE                                              34                             /* 'value' */
#define DUK_HEAP_STRING_VALUE(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VALUE)
#define DUK_HTHREAD_STRING_VALUE(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VALUE)
#define DUK_STRIDX_WRITABLE                                           35                             /* 'writable' */
#define DUK_HEAP_STRING_WRITABLE(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITABLE)
#define DUK_HTHREAD_STRING_WRITABLE(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITABLE)
#define DUK_STRIDX_CONFIGURABLE                                       36                             /* 'configurable' */
#define DUK_HEAP_STRING_CONFIGURABLE(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONFIGURABLE)
#define DUK_HTHREAD_STRING_CONFIGURABLE(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONFIGURABLE)
#define DUK_STRIDX_ENUMERABLE                                         37                             /* 'enumerable' */
#define DUK_HEAP_STRING_ENUMERABLE(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ENUMERABLE)
#define DUK_HTHREAD_STRING_ENUMERABLE(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ENUMERABLE)
#define DUK_STRIDX_JOIN                                               38                             /* 'join' */
#define DUK_HEAP_STRING_JOIN(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JOIN)
#define DUK_HTHREAD_STRING_JOIN(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JOIN)
#define DUK_STRIDX_TO_LOCALE_STRING                                   39                             /* 'toLocaleString' */
#define DUK_HEAP_STRING_TO_LOCALE_STRING(heap)                        DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_LOCALE_STRING)
#define DUK_HTHREAD_STRING_TO_LOCALE_STRING(thr)                      DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_LOCALE_STRING)
#define DUK_STRIDX_VALUE_OF                                           40                             /* 'valueOf' */
#define DUK_HEAP_STRING_VALUE_OF(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VALUE_OF)
#define DUK_HTHREAD_STRING_VALUE_OF(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VALUE_OF)
#define DUK_STRIDX_TO_UTC_STRING                                      41                             /* 'toUTCString' */
#define DUK_HEAP_STRING_TO_UTC_STRING(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_UTC_STRING)
#define DUK_HTHREAD_STRING_TO_UTC_STRING(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_UTC_STRING)
#define DUK_STRIDX_TO_ISO_STRING                                      42                             /* 'toISOString' */
#define DUK_HEAP_STRING_TO_ISO_STRING(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_ISO_STRING)
#define DUK_HTHREAD_STRING_TO_ISO_STRING(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_ISO_STRING)
#define DUK_STRIDX_TO_GMT_STRING                                      43                             /* 'toGMTString' */
#define DUK_HEAP_STRING_TO_GMT_STRING(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_GMT_STRING)
#define DUK_HTHREAD_STRING_TO_GMT_STRING(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_GMT_STRING)
#define DUK_STRIDX_SOURCE                                             44                             /* 'source' */
#define DUK_HEAP_STRING_SOURCE(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SOURCE)
#define DUK_HTHREAD_STRING_SOURCE(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SOURCE)
#define DUK_STRIDX_IGNORE_CASE                                        45                             /* 'ignoreCase' */
#define DUK_HEAP_STRING_IGNORE_CASE(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IGNORE_CASE)
#define DUK_HTHREAD_STRING_IGNORE_CASE(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IGNORE_CASE)
#define DUK_STRIDX_MULTILINE                                          46                             /* 'multiline' */
#define DUK_HEAP_STRING_MULTILINE(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MULTILINE)
#define DUK_HTHREAD_STRING_MULTILINE(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MULTILINE)
#define DUK_STRIDX_LAST_INDEX                                         47                             /* 'lastIndex' */
#define DUK_HEAP_STRING_LAST_INDEX(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LAST_INDEX)
#define DUK_HTHREAD_STRING_LAST_INDEX(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LAST_INDEX)
#define DUK_STRIDX_FLAGS                                              48                             /* 'flags' */
#define DUK_HEAP_STRING_FLAGS(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FLAGS)
#define DUK_HTHREAD_STRING_FLAGS(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FLAGS)
#define DUK_STRIDX_INDEX                                              49                             /* 'index' */
#define DUK_HEAP_STRING_INDEX(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INDEX)
#define DUK_HTHREAD_STRING_INDEX(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INDEX)
#define DUK_STRIDX_PROTOTYPE                                          50                             /* 'prototype' */
#define DUK_HEAP_STRING_PROTOTYPE(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PROTOTYPE)
#define DUK_HTHREAD_STRING_PROTOTYPE(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PROTOTYPE)
#define DUK_STRIDX_CONSTRUCTOR                                        51                             /* 'constructor' */
#define DUK_HEAP_STRING_CONSTRUCTOR(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONSTRUCTOR)
#define DUK_HTHREAD_STRING_CONSTRUCTOR(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONSTRUCTOR)
#define DUK_STRIDX_MESSAGE                                            52                             /* 'message' */
#define DUK_HEAP_STRING_MESSAGE(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MESSAGE)
#define DUK_HTHREAD_STRING_MESSAGE(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MESSAGE)
#define DUK_STRIDX_LC_BOOLEAN                                         53                             /* 'boolean' */
#define DUK_HEAP_STRING_LC_BOOLEAN(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_BOOLEAN)
#define DUK_HTHREAD_STRING_LC_BOOLEAN(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_BOOLEAN)
#define DUK_STRIDX_LC_NUMBER                                          54                             /* 'number' */
#define DUK_HEAP_STRING_LC_NUMBER(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_NUMBER)
#define DUK_HTHREAD_STRING_LC_NUMBER(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_NUMBER)
#define DUK_STRIDX_LC_STRING                                          55                             /* 'string' */
#define DUK_HEAP_STRING_LC_STRING(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_STRING)
#define DUK_HTHREAD_STRING_LC_STRING(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_STRING)
#define DUK_STRIDX_LC_SYMBOL                                          56                             /* 'symbol' */
#define DUK_HEAP_STRING_LC_SYMBOL(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_SYMBOL)
#define DUK_HTHREAD_STRING_LC_SYMBOL(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_SYMBOL)
#define DUK_STRIDX_LC_OBJECT                                          57                             /* 'object' */
#define DUK_HEAP_STRING_LC_OBJECT(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_OBJECT)
#define DUK_HTHREAD_STRING_LC_OBJECT(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_OBJECT)
#define DUK_STRIDX_LC_UNDEFINED                                       58                             /* 'undefined' */
#define DUK_HEAP_STRING_LC_UNDEFINED(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_UNDEFINED)
#define DUK_HTHREAD_STRING_LC_UNDEFINED(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_UNDEFINED)
#define DUK_STRIDX_NAN                                                59                             /* 'NaN' */
#define DUK_HEAP_STRING_NAN(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NAN)
#define DUK_HTHREAD_STRING_NAN(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NAN)
#define DUK_STRIDX_INFINITY                                           60                             /* 'Infinity' */
#define DUK_HEAP_STRING_INFINITY(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INFINITY)
#define DUK_HTHREAD_STRING_INFINITY(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INFINITY)
#define DUK_STRIDX_MINUS_INFINITY                                     61                             /* '-Infinity' */
#define DUK_HEAP_STRING_MINUS_INFINITY(heap)                          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MINUS_INFINITY)
#define DUK_HTHREAD_STRING_MINUS_INFINITY(thr)                        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MINUS_INFINITY)
#define DUK_STRIDX_MINUS_ZERO                                         62                             /* '-0' */
#define DUK_HEAP_STRING_MINUS_ZERO(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MINUS_ZERO)
#define DUK_HTHREAD_STRING_MINUS_ZERO(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MINUS_ZERO)
#define DUK_STRIDX_COMMA                                              63                             /* ',' */
#define DUK_HEAP_STRING_COMMA(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_COMMA)
#define DUK_HTHREAD_STRING_COMMA(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_COMMA)
#define DUK_STRIDX_NEWLINE_4SPACE                                     64                             /* '\n    ' */
#define DUK_HEAP_STRING_NEWLINE_4SPACE(heap)                          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NEWLINE_4SPACE)
#define DUK_HTHREAD_STRING_NEWLINE_4SPACE(thr)                        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NEWLINE_4SPACE)
#define DUK_STRIDX_BRACKETED_ELLIPSIS                                 65                             /* '[...]' */
#define DUK_HEAP_STRING_BRACKETED_ELLIPSIS(heap)                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BRACKETED_ELLIPSIS)
#define DUK_HTHREAD_STRING_BRACKETED_ELLIPSIS(thr)                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BRACKETED_ELLIPSIS)
#define DUK_STRIDX_INVALID_DATE                                       66                             /* 'Invalid Date' */
#define DUK_HEAP_STRING_INVALID_DATE(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INVALID_DATE)
#define DUK_HTHREAD_STRING_INVALID_DATE(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INVALID_DATE)
#define DUK_STRIDX_LC_ARGUMENTS                                       67                             /* 'arguments' */
#define DUK_HEAP_STRING_LC_ARGUMENTS(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_ARGUMENTS)
#define DUK_HTHREAD_STRING_LC_ARGUMENTS(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_ARGUMENTS)
#define DUK_STRIDX_CALLEE                                             68                             /* 'callee' */
#define DUK_HEAP_STRING_CALLEE(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CALLEE)
#define DUK_HTHREAD_STRING_CALLEE(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CALLEE)
#define DUK_STRIDX_CALLER                                             69                             /* 'caller' */
#define DUK_HEAP_STRING_CALLER(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CALLER)
#define DUK_HTHREAD_STRING_CALLER(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CALLER)
#define DUK_STRIDX_APPLY                                              70                             /* 'apply' */
#define DUK_HEAP_STRING_APPLY(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_APPLY)
#define DUK_HTHREAD_STRING_APPLY(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_APPLY)
#define DUK_STRIDX_CONSTRUCT                                          71                             /* 'construct' */
#define DUK_HEAP_STRING_CONSTRUCT(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONSTRUCT)
#define DUK_HTHREAD_STRING_CONSTRUCT(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONSTRUCT)
#define DUK_STRIDX_DELETE_PROPERTY                                    72                             /* 'deleteProperty' */
#define DUK_HEAP_STRING_DELETE_PROPERTY(heap)                         DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DELETE_PROPERTY)
#define DUK_HTHREAD_STRING_DELETE_PROPERTY(thr)                       DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DELETE_PROPERTY)
#define DUK_STRIDX_GET                                                73                             /* 'get' */
#define DUK_HEAP_STRING_GET(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET)
#define DUK_HTHREAD_STRING_GET(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET)
#define DUK_STRIDX_HAS                                                74                             /* 'has' */
#define DUK_HEAP_STRING_HAS(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_HAS)
#define DUK_HTHREAD_STRING_HAS(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_HAS)
#define DUK_STRIDX_OWN_KEYS                                           75                             /* 'ownKeys' */
#define DUK_HEAP_STRING_OWN_KEYS(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_OWN_KEYS)
#define DUK_HTHREAD_STRING_OWN_KEYS(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_OWN_KEYS)
#define DUK_STRIDX_WELLKNOWN_SYMBOL_TO_PRIMITIVE                      76                             /* '\x81Symbol.toPrimitive\xff' */
#define DUK_HEAP_STRING_WELLKNOWN_SYMBOL_TO_PRIMITIVE(heap)           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WELLKNOWN_SYMBOL_TO_PRIMITIVE)
#define DUK_HTHREAD_STRING_WELLKNOWN_SYMBOL_TO_PRIMITIVE(thr)         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WELLKNOWN_SYMBOL_TO_PRIMITIVE)
#define DUK_STRIDX_WELLKNOWN_SYMBOL_HAS_INSTANCE                      77                             /* '\x81Symbol.hasInstance\xff' */
#define DUK_HEAP_STRING_WELLKNOWN_SYMBOL_HAS_INSTANCE(heap)           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WELLKNOWN_SYMBOL_HAS_INSTANCE)
#define DUK_HTHREAD_STRING_WELLKNOWN_SYMBOL_HAS_INSTANCE(thr)         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WELLKNOWN_SYMBOL_HAS_INSTANCE)
#define DUK_STRIDX_WELLKNOWN_SYMBOL_TO_STRING_TAG                     78                             /* '\x81Symbol.toStringTag\xff' */
#define DUK_HEAP_STRING_WELLKNOWN_SYMBOL_TO_STRING_TAG(heap)          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WELLKNOWN_SYMBOL_TO_STRING_TAG)
#define DUK_HTHREAD_STRING_WELLKNOWN_SYMBOL_TO_STRING_TAG(thr)        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WELLKNOWN_SYMBOL_TO_STRING_TAG)
#define DUK_STRIDX_WELLKNOWN_SYMBOL_IS_CONCAT_SPREADABLE              79                             /* '\x81Symbol.isConcatSpreadable\xff' */
#define DUK_HEAP_STRING_WELLKNOWN_SYMBOL_IS_CONCAT_SPREADABLE(heap)   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WELLKNOWN_SYMBOL_IS_CONCAT_SPREADABLE)
#define DUK_HTHREAD_STRING_WELLKNOWN_SYMBOL_IS_CONCAT_SPREADABLE(thr)  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WELLKNOWN_SYMBOL_IS_CONCAT_SPREADABLE)
#define DUK_STRIDX_SET_PROTOTYPE_OF                                   80                             /* 'setPrototypeOf' */
#define DUK_HEAP_STRING_SET_PROTOTYPE_OF(heap)                        DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_PROTOTYPE_OF)
#define DUK_HTHREAD_STRING_SET_PROTOTYPE_OF(thr)                      DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_PROTOTYPE_OF)
#define DUK_STRIDX___PROTO__                                          81                             /* '__proto__' */
#define DUK_HEAP_STRING___PROTO__(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX___PROTO__)
#define DUK_HTHREAD_STRING___PROTO__(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX___PROTO__)
#define DUK_STRIDX_TO_STRING                                          82                             /* 'toString' */
#define DUK_HEAP_STRING_TO_STRING(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_STRING)
#define DUK_HTHREAD_STRING_TO_STRING(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_STRING)
#define DUK_STRIDX_TO_JSON                                            83                             /* 'toJSON' */
#define DUK_HEAP_STRING_TO_JSON(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_JSON)
#define DUK_HTHREAD_STRING_TO_JSON(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_JSON)
#define DUK_STRIDX_TYPE                                               84                             /* 'type' */
#define DUK_HEAP_STRING_TYPE(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TYPE)
#define DUK_HTHREAD_STRING_TYPE(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TYPE)
#define DUK_STRIDX_DATA                                               85                             /* 'data' */
#define DUK_HEAP_STRING_DATA(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DATA)
#define DUK_HTHREAD_STRING_DATA(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DATA)
#define DUK_STRIDX_LC_BUFFER                                          86                             /* 'buffer' */
#define DUK_HEAP_STRING_LC_BUFFER(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_BUFFER)
#define DUK_HTHREAD_STRING_LC_BUFFER(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_BUFFER)
#define DUK_STRIDX_LENGTH                                             87                             /* 'length' */
#define DUK_HEAP_STRING_LENGTH(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LENGTH)
#define DUK_HTHREAD_STRING_LENGTH(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LENGTH)
#define DUK_STRIDX_SET                                                88                             /* 'set' */
#define DUK_HEAP_STRING_SET(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET)
#define DUK_HTHREAD_STRING_SET(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET)
#define DUK_STRIDX_STACK                                              89                             /* 'stack' */
#define DUK_HEAP_STRING_STACK(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_STACK)
#define DUK_HTHREAD_STRING_STACK(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_STACK)
#define DUK_STRIDX_PC                                                 90                             /* 'pc' */
#define DUK_HEAP_STRING_PC(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PC)
#define DUK_HTHREAD_STRING_PC(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PC)
#define DUK_STRIDX_LINE_NUMBER                                        91                             /* 'lineNumber' */
#define DUK_HEAP_STRING_LINE_NUMBER(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LINE_NUMBER)
#define DUK_HTHREAD_STRING_LINE_NUMBER(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LINE_NUMBER)
#define DUK_STRIDX_INT_TRACEDATA                                      92                             /* '\x82Tracedata' */
#define DUK_HEAP_STRING_INT_TRACEDATA(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_TRACEDATA)
#define DUK_HTHREAD_STRING_INT_TRACEDATA(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_TRACEDATA)
#define DUK_STRIDX_NAME                                               93                             /* 'name' */
#define DUK_HEAP_STRING_NAME(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NAME)
#define DUK_HTHREAD_STRING_NAME(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NAME)
#define DUK_STRIDX_FILE_NAME                                          94                             /* 'fileName' */
#define DUK_HEAP_STRING_FILE_NAME(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FILE_NAME)
#define DUK_HTHREAD_STRING_FILE_NAME(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FILE_NAME)
#define DUK_STRIDX_LC_POINTER                                         95                             /* 'pointer' */
#define DUK_HEAP_STRING_LC_POINTER(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_POINTER)
#define DUK_HTHREAD_STRING_LC_POINTER(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_POINTER)
#define DUK_STRIDX_INT_TARGET                                         96                             /* '\x82Target' */
#define DUK_HEAP_STRING_INT_TARGET(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_TARGET)
#define DUK_HTHREAD_STRING_INT_TARGET(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_TARGET)
#define DUK_STRIDX_INT_NEXT                                           97                             /* '\x82Next' */
#define DUK_HEAP_STRING_INT_NEXT(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_NEXT)
#define DUK_HTHREAD_STRING_INT_NEXT(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_NEXT)
#define DUK_STRIDX_INT_BYTECODE                                       98                             /* '\x82Bytecode' */
#define DUK_HEAP_STRING_INT_BYTECODE(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_BYTECODE)
#define DUK_HTHREAD_STRING_INT_BYTECODE(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_BYTECODE)
#define DUK_STRIDX_INT_FORMALS                                        99                             /* '\x82Formals' */
#define DUK_HEAP_STRING_INT_FORMALS(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_FORMALS)
#define DUK_HTHREAD_STRING_INT_FORMALS(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_FORMALS)
#define DUK_STRIDX_INT_VARMAP                                         100                            /* '\x82Varmap' */
#define DUK_HEAP_STRING_INT_VARMAP(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_VARMAP)
#define DUK_HTHREAD_STRING_INT_VARMAP(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_VARMAP)
#define DUK_STRIDX_INT_SOURCE                                         101                            /* '\x82Source' */
#define DUK_HEAP_STRING_INT_SOURCE(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_SOURCE)
#define DUK_HTHREAD_STRING_INT_SOURCE(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_SOURCE)
#define DUK_STRIDX_INT_PC2LINE                                        102                            /* '\x82Pc2line' */
#define DUK_HEAP_STRING_INT_PC2LINE(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_PC2LINE)
#define DUK_HTHREAD_STRING_INT_PC2LINE(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_PC2LINE)
#define DUK_STRIDX_INT_MAP                                            103                            /* '\x82Map' */
#define DUK_HEAP_STRING_INT_MAP(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_MAP)
#define DUK_HTHREAD_STRING_INT_MAP(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_MAP)
#define DUK_STRIDX_INT_VARENV                                         104                            /* '\x82Varenv' */
#define DUK_HEAP_STRING_INT_VARENV(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_VARENV)
#define DUK_HTHREAD_STRING_INT_VARENV(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_VARENV)
#define DUK_STRIDX_INT_FINALIZER                                      105                            /* '\x82Finalizer' */
#define DUK_HEAP_STRING_INT_FINALIZER(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_FINALIZER)
#define DUK_HTHREAD_STRING_INT_FINALIZER(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_FINALIZER)
#define DUK_STRIDX_INT_VALUE                                          106                            /* '\x82Value' */
#define DUK_HEAP_STRING_INT_VALUE(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_VALUE)
#define DUK_HTHREAD_STRING_INT_VALUE(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_VALUE)
#define DUK_STRIDX_COMPILE                                            107                            /* 'compile' */
#define DUK_HEAP_STRING_COMPILE(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_COMPILE)
#define DUK_HTHREAD_STRING_COMPILE(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_COMPILE)
#define DUK_STRIDX_INPUT                                              108                            /* 'input' */
#define DUK_HEAP_STRING_INPUT(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INPUT)
#define DUK_HTHREAD_STRING_INPUT(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INPUT)
#define DUK_STRIDX_ERR_CREATE                                         109                            /* 'errCreate' */
#define DUK_HEAP_STRING_ERR_CREATE(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ERR_CREATE)
#define DUK_HTHREAD_STRING_ERR_CREATE(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ERR_CREATE)
#define DUK_STRIDX_ERR_THROW                                          110                            /* 'errThrow' */
#define DUK_HEAP_STRING_ERR_THROW(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ERR_THROW)
#define DUK_HTHREAD_STRING_ERR_THROW(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ERR_THROW)
#define DUK_STRIDX_ENV                                                111                            /* 'env' */
#define DUK_HEAP_STRING_ENV(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ENV)
#define DUK_HTHREAD_STRING_ENV(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ENV)
#define DUK_STRIDX_HEX                                                112                            /* 'hex' */
#define DUK_HEAP_STRING_HEX(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_HEX)
#define DUK_HTHREAD_STRING_HEX(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_HEX)
#define DUK_STRIDX_BASE64                                             113                            /* 'base64' */
#define DUK_HEAP_STRING_BASE64(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BASE64)
#define DUK_HTHREAD_STRING_BASE64(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BASE64)
#define DUK_STRIDX_JX                                                 114                            /* 'jx' */
#define DUK_HEAP_STRING_JX(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JX)
#define DUK_HTHREAD_STRING_JX(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JX)
#define DUK_STRIDX_JC                                                 115                            /* 'jc' */
#define DUK_HEAP_STRING_JC(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JC)
#define DUK_HTHREAD_STRING_JC(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JC)
#define DUK_STRIDX_JSON_EXT_UNDEFINED                                 116                            /* '{"_undef":true}' */
#define DUK_HEAP_STRING_JSON_EXT_UNDEFINED(heap)                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_UNDEFINED)
#define DUK_HTHREAD_STRING_JSON_EXT_UNDEFINED(thr)                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_UNDEFINED)
#define DUK_STRIDX_JSON_EXT_NAN                                       117                            /* '{"_nan":true}' */
#define DUK_HEAP_STRING_JSON_EXT_NAN(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_NAN)
#define DUK_HTHREAD_STRING_JSON_EXT_NAN(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_NAN)
#define DUK_STRIDX_JSON_EXT_POSINF                                    118                            /* '{"_inf":true}' */
#define DUK_HEAP_STRING_JSON_EXT_POSINF(heap)                         DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_POSINF)
#define DUK_HTHREAD_STRING_JSON_EXT_POSINF(thr)                       DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_POSINF)
#define DUK_STRIDX_JSON_EXT_NEGINF                                    119                            /* '{"_ninf":true}' */
#define DUK_HEAP_STRING_JSON_EXT_NEGINF(heap)                         DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_NEGINF)
#define DUK_HTHREAD_STRING_JSON_EXT_NEGINF(thr)                       DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_NEGINF)
#define DUK_STRIDX_JSON_EXT_FUNCTION1                                 120                            /* '{"_func":true}' */
#define DUK_HEAP_STRING_JSON_EXT_FUNCTION1(heap)                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_FUNCTION1)
#define DUK_HTHREAD_STRING_JSON_EXT_FUNCTION1(thr)                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_FUNCTION1)
#define DUK_STRIDX_JSON_EXT_FUNCTION2                                 121                            /* '{_func:true}' */
#define DUK_HEAP_STRING_JSON_EXT_FUNCTION2(heap)                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_FUNCTION2)
#define DUK_HTHREAD_STRING_JSON_EXT_FUNCTION2(thr)                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_FUNCTION2)
#define DUK_STRIDX_BREAK                                              122                            /* 'break' */
#define DUK_HEAP_STRING_BREAK(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BREAK)
#define DUK_HTHREAD_STRING_BREAK(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BREAK)
#define DUK_STRIDX_CASE                                               123                            /* 'case' */
#define DUK_HEAP_STRING_CASE(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CASE)
#define DUK_HTHREAD_STRING_CASE(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CASE)
#define DUK_STRIDX_CATCH                                              124                            /* 'catch' */
#define DUK_HEAP_STRING_CATCH(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CATCH)
#define DUK_HTHREAD_STRING_CATCH(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CATCH)
#define DUK_STRIDX_CONTINUE                                           125                            /* 'continue' */
#define DUK_HEAP_STRING_CONTINUE(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONTINUE)
#define DUK_HTHREAD_STRING_CONTINUE(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONTINUE)
#define DUK_STRIDX_DEBUGGER                                           126                            /* 'debugger' */
#define DUK_HEAP_STRING_DEBUGGER(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DEBUGGER)
#define DUK_HTHREAD_STRING_DEBUGGER(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DEBUGGER)
#define DUK_STRIDX_DEFAULT                                            127                            /* 'default' */
#define DUK_HEAP_STRING_DEFAULT(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DEFAULT)
#define DUK_HTHREAD_STRING_DEFAULT(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DEFAULT)
#define DUK_STRIDX_DELETE                                             128                            /* 'delete' */
#define DUK_HEAP_STRING_DELETE(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DELETE)
#define DUK_HTHREAD_STRING_DELETE(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DELETE)
#define DUK_STRIDX_DO                                                 129                            /* 'do' */
#define DUK_HEAP_STRING_DO(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DO)
#define DUK_HTHREAD_STRING_DO(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DO)
#define DUK_STRIDX_ELSE                                               130                            /* 'else' */
#define DUK_HEAP_STRING_ELSE(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ELSE)
#define DUK_HTHREAD_STRING_ELSE(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ELSE)
#define DUK_STRIDX_FINALLY                                            131                            /* 'finally' */
#define DUK_HEAP_STRING_FINALLY(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FINALLY)
#define DUK_HTHREAD_STRING_FINALLY(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FINALLY)
#define DUK_STRIDX_FOR                                                132                            /* 'for' */
#define DUK_HEAP_STRING_FOR(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FOR)
#define DUK_HTHREAD_STRING_FOR(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FOR)
#define DUK_STRIDX_LC_FUNCTION                                        133                            /* 'function' */
#define DUK_HEAP_STRING_LC_FUNCTION(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_FUNCTION)
#define DUK_HTHREAD_STRING_LC_FUNCTION(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_FUNCTION)
#define DUK_STRIDX_IF                                                 134                            /* 'if' */
#define DUK_HEAP_STRING_IF(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IF)
#define DUK_HTHREAD_STRING_IF(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IF)
#define DUK_STRIDX_IN                                                 135                            /* 'in' */
#define DUK_HEAP_STRING_IN(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IN)
#define DUK_HTHREAD_STRING_IN(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IN)
#define DUK_STRIDX_INSTANCEOF                                         136                            /* 'instanceof' */
#define DUK_HEAP_STRING_INSTANCEOF(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INSTANCEOF)
#define DUK_HTHREAD_STRING_INSTANCEOF(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INSTANCEOF)
#define DUK_STRIDX_NEW                                                137                            /* 'new' */
#define DUK_HEAP_STRING_NEW(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NEW)
#define DUK_HTHREAD_STRING_NEW(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NEW)
#define DUK_STRIDX_RETURN                                             138                            /* 'return' */
#define DUK_HEAP_STRING_RETURN(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_RETURN)
#define DUK_HTHREAD_STRING_RETURN(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_RETURN)
#define DUK_STRIDX_SWITCH                                             139                            /* 'switch' */
#define DUK_HEAP_STRING_SWITCH(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SWITCH)
#define DUK_HTHREAD_STRING_SWITCH(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SWITCH)
#define DUK_STRIDX_THIS                                               140                            /* 'this' */
#define DUK_HEAP_STRING_THIS(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_THIS)
#define DUK_HTHREAD_STRING_THIS(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_THIS)
#define DUK_STRIDX_THROW                                              141                            /* 'throw' */
#define DUK_HEAP_STRING_THROW(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_THROW)
#define DUK_HTHREAD_STRING_THROW(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_THROW)
#define DUK_STRIDX_TRY                                                142                            /* 'try' */
#define DUK_HEAP_STRING_TRY(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TRY)
#define DUK_HTHREAD_STRING_TRY(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TRY)
#define DUK_STRIDX_TYPEOF                                             143                            /* 'typeof' */
#define DUK_HEAP_STRING_TYPEOF(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TYPEOF)
#define DUK_HTHREAD_STRING_TYPEOF(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TYPEOF)
#define DUK_STRIDX_VAR                                                144                            /* 'var' */
#define DUK_HEAP_STRING_VAR(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VAR)
#define DUK_HTHREAD_STRING_VAR(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VAR)
#define DUK_STRIDX_CONST                                              145                            /* 'const' */
#define DUK_HEAP_STRING_CONST(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONST)
#define DUK_HTHREAD_STRING_CONST(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONST)
#define DUK_STRIDX_VOID                                               146                            /* 'void' */
#define DUK_HEAP_STRING_VOID(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VOID)
#define DUK_HTHREAD_STRING_VOID(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VOID)
#define DUK_STRIDX_WHILE                                              147                            /* 'while' */
#define DUK_HEAP_STRING_WHILE(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WHILE)
#define DUK_HTHREAD_STRING_WHILE(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WHILE)
#define DUK_STRIDX_WITH                                               148                            /* 'with' */
#define DUK_HEAP_STRING_WITH(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WITH)
#define DUK_HTHREAD_STRING_WITH(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WITH)
#define DUK_STRIDX_CLASS                                              149                            /* 'class' */
#define DUK_HEAP_STRING_CLASS(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CLASS)
#define DUK_HTHREAD_STRING_CLASS(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CLASS)
#define DUK_STRIDX_ENUM                                               150                            /* 'enum' */
#define DUK_HEAP_STRING_ENUM(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ENUM)
#define DUK_HTHREAD_STRING_ENUM(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ENUM)
#define DUK_STRIDX_EXPORT                                             151                            /* 'export' */
#define DUK_HEAP_STRING_EXPORT(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EXPORT)
#define DUK_HTHREAD_STRING_EXPORT(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EXPORT)
#define DUK_STRIDX_EXTENDS                                            152                            /* 'extends' */
#define DUK_HEAP_STRING_EXTENDS(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EXTENDS)
#define DUK_HTHREAD_STRING_EXTENDS(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EXTENDS)
#define DUK_STRIDX_IMPORT                                             153                            /* 'import' */
#define DUK_HEAP_STRING_IMPORT(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IMPORT)
#define DUK_HTHREAD_STRING_IMPORT(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IMPORT)
#define DUK_STRIDX_SUPER                                              154                            /* 'super' */
#define DUK_HEAP_STRING_SUPER(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SUPER)
#define DUK_HTHREAD_STRING_SUPER(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SUPER)
#define DUK_STRIDX_LC_NULL                                            155                            /* 'null' */
#define DUK_HEAP_STRING_LC_NULL(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_NULL)
#define DUK_HTHREAD_STRING_LC_NULL(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_NULL)
#define DUK_STRIDX_TRUE                                               156                            /* 'true' */
#define DUK_HEAP_STRING_TRUE(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TRUE)
#define DUK_HTHREAD_STRING_TRUE(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TRUE)
#define DUK_STRIDX_FALSE                                              157                            /* 'false' */
#define DUK_HEAP_STRING_FALSE(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FALSE)
#define DUK_HTHREAD_STRING_FALSE(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FALSE)
#define DUK_STRIDX_IMPLEMENTS                                         158                            /* 'implements' */
#define DUK_HEAP_STRING_IMPLEMENTS(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IMPLEMENTS)
#define DUK_HTHREAD_STRING_IMPLEMENTS(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IMPLEMENTS)
#define DUK_STRIDX_INTERFACE                                          159                            /* 'interface' */
#define DUK_HEAP_STRING_INTERFACE(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INTERFACE)
#define DUK_HTHREAD_STRING_INTERFACE(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INTERFACE)
#define DUK_STRIDX_LET                                                160                            /* 'let' */
#define DUK_HEAP_STRING_LET(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LET)
#define DUK_HTHREAD_STRING_LET(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LET)
#define DUK_STRIDX_PACKAGE                                            161                            /* 'package' */
#define DUK_HEAP_STRING_PACKAGE(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PACKAGE)
#define DUK_HTHREAD_STRING_PACKAGE(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PACKAGE)
#define DUK_STRIDX_PRIVATE                                            162                            /* 'private' */
#define DUK_HEAP_STRING_PRIVATE(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PRIVATE)
#define DUK_HTHREAD_STRING_PRIVATE(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PRIVATE)
#define DUK_STRIDX_PROTECTED                                          163                            /* 'protected' */
#define DUK_HEAP_STRING_PROTECTED(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PROTECTED)
#define DUK_HTHREAD_STRING_PROTECTED(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PROTECTED)
#define DUK_STRIDX_PUBLIC                                             164                            /* 'public' */
#define DUK_HEAP_STRING_PUBLIC(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PUBLIC)
#define DUK_HTHREAD_STRING_PUBLIC(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PUBLIC)
#define DUK_STRIDX_STATIC                                             165                            /* 'static' */
#define DUK_HEAP_STRING_STATIC(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_STATIC)
#define DUK_HTHREAD_STRING_STATIC(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_STATIC)
#define DUK_STRIDX_YIELD                                              166                            /* 'yield' */
#define DUK_HEAP_STRING_YIELD(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_YIELD)
#define DUK_HTHREAD_STRING_YIELD(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_YIELD)

#define DUK_HEAP_NUM_STRINGS                                          167
#define DUK_STRIDX_START_RESERVED                                     122
#define DUK_STRIDX_START_STRICT_RESERVED                              158
#define DUK_STRIDX_END_RESERVED                                       167                            /* exclusive endpoint */

/* To convert a heap stridx to a token number, subtract
 * DUK_STRIDX_START_RESERVED and add DUK_TOK_START_RESERVED.
 */
#if !defined(DUK_SINGLE_FILE)
DUK_INTERNAL_DECL const duk_uint8_t duk_strings_data[972];
#endif  /* !DUK_SINGLE_FILE */
#define DUK_STRDATA_MAX_STRLEN                                        27
#define DUK_STRDATA_DATA_LENGTH                                       972
#endif  /* DUK_USE_ROM_STRINGS */

#if defined(DUK_USE_ROM_OBJECTS)
#error RAM support not enabled, rerun configure.py with --ram-support
#else  /* DUK_USE_ROM_OBJECTS */
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_function_constructor(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_constructor(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_constructor(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_boolean_constructor(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_number_constructor(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_constructor(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_error_constructor_shared(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_type_error_thrower(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_parse_int(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_parse_float(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_thread_constructor(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_pointer_constructor(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_proxy_constructor(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_symbol_constructor_shared(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_arraybuffer_constructor(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_dataview_constructor(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_constructor(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_constructor(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_textencoder_constructor(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_textdecoder_constructor(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_eval(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_is_nan(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_is_finite(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_decode_uri(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_decode_uri_component(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_encode_uri(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_encode_uri_component(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_escape(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_unescape(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_getprototype_shared(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_setprototype_shared(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_get_own_property_descriptor(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_keys_shared(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_assign(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_create(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_define_property(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_define_properties(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_seal_freeze_shared(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_prevent_extensions(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_is_sealed_frozen_shared(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_is_extensible(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_is(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_to_string(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_to_locale_string(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_value_of(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_has_own_property(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_is_prototype_of(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_property_is_enumerable(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_defineaccessor(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_lookupaccessor(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_to_string(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_apply(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_call(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_bind(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_hasinstance(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_native_function_length(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_native_function_name(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_constructor_is_array(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_to_string(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_join_shared(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_concat(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_pop(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_push(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_reverse(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_shift(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_slice(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_sort(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_splice(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_unshift(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_indexof_shared(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_iter_shared(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_reduce_shared(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_constructor_from_char_code(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_constructor_from_code_point(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_to_string(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_char_at(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_char_code_at(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_concat(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_indexof_shared(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_locale_compare(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_match(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_replace(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_search(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_slice(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_split(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_substring(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_caseconv_shared(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_trim(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_repeat(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_startswith_endswith(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_includes(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_substr(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_boolean_prototype_tostring_shared(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_number_check_shared(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_string(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_locale_string(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_value_of(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_fixed(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_exponential(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_precision(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor_parse(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor_utc(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor_now(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_tostring_shared(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_to_json(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_value_of(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_get_shared(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_get_timezone_offset(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_set_time(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_set_shared(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_toprimitive(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_exec(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_test(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_tostring(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_flags(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_shared_getter(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_stack_getter(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_stack_setter(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_filename_getter(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_filename_setter(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_linenumber_getter(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_linenumber_setter(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_to_string(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_onearg_shared(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_twoarg_shared(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_clz32(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_hypot(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_imul(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_max(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_min(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_random(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_sign(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_json_object_parse(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_json_object_stringify(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_info(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_act(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_gc(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_fin(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_enc(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_dec(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_compact(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_thread_yield(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_thread_resume(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_thread_current(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_pointer_prototype_tostring_shared(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_apply(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_construct(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_object_delete_property(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_object_get(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_object_has(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_object_set(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_symbol_key_for(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_symbol_tostring_shared(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_symbol_toprimitive(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_arraybuffer_isview(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_bytelength_getter(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_slice_shared(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_byteoffset_getter(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_buffer_getter(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_readfield(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_writefield(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_set(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_uint8array_allocplain(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_uint8array_plainof(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_concat(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_is_encoding(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_is_buffer(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_byte_length(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_compare_shared(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_tostring(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_tojson(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_fill(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_copy(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_write(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_cbor_encode(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_cbor_decode(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_textencoder_prototype_encoding_getter(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_textencoder_prototype_encode(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_textdecoder_prototype_shared_getter(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_textdecoder_prototype_decode(duk_context *ctx);
DUK_INTERNAL_DECL duk_ret_t duk_bi_performance_now(duk_context *ctx);
#if !defined(DUK_SINGLE_FILE)
DUK_INTERNAL_DECL const duk_c_function duk_bi_native_functions[185];
#endif  /* !DUK_SINGLE_FILE */
#define DUK_BIDX_GLOBAL                                               0
#define DUK_BIDX_GLOBAL_ENV                                           1
#define DUK_BIDX_OBJECT_CONSTRUCTOR                                   2
#define DUK_BIDX_OBJECT_PROTOTYPE                                     3
#define DUK_BIDX_FUNCTION_CONSTRUCTOR                                 4
#define DUK_BIDX_FUNCTION_PROTOTYPE                                   5
#define DUK_BIDX_NATIVE_FUNCTION_PROTOTYPE                            6
#define DUK_BIDX_ARRAY_CONSTRUCTOR                                    7
#define DUK_BIDX_ARRAY_PROTOTYPE                                      8
#define DUK_BIDX_STRING_CONSTRUCTOR                                   9
#define DUK_BIDX_STRING_PROTOTYPE                                     10
#define DUK_BIDX_BOOLEAN_CONSTRUCTOR                                  11
#define DUK_BIDX_BOOLEAN_PROTOTYPE                                    12
#define DUK_BIDX_NUMBER_CONSTRUCTOR                                   13
#define DUK_BIDX_NUMBER_PROTOTYPE                                     14
#define DUK_BIDX_DATE_CONSTRUCTOR                                     15
#define DUK_BIDX_DATE_PROTOTYPE                                       16
#define DUK_BIDX_REGEXP_CONSTRUCTOR                                   17
#define DUK_BIDX_REGEXP_PROTOTYPE                                     18
#define DUK_BIDX_ERROR_CONSTRUCTOR                                    19
#define DUK_BIDX_ERROR_PROTOTYPE                                      20
#define DUK_BIDX_EVAL_ERROR_CONSTRUCTOR                               21
#define DUK_BIDX_EVAL_ERROR_PROTOTYPE                                 22
#define DUK_BIDX_RANGE_ERROR_CONSTRUCTOR                              23
#define DUK_BIDX_RANGE_ERROR_PROTOTYPE                                24
#define DUK_BIDX_REFERENCE_ERROR_CONSTRUCTOR                          25
#define DUK_BIDX_REFERENCE_ERROR_PROTOTYPE                            26
#define DUK_BIDX_SYNTAX_ERROR_CONSTRUCTOR                             27
#define DUK_BIDX_SYNTAX_ERROR_PROTOTYPE                               28
#define DUK_BIDX_TYPE_ERROR_CONSTRUCTOR                               29
#define DUK_BIDX_TYPE_ERROR_PROTOTYPE                                 30
#define DUK_BIDX_URI_ERROR_CONSTRUCTOR                                31
#define DUK_BIDX_URI_ERROR_PROTOTYPE                                  32
#define DUK_BIDX_TYPE_ERROR_THROWER                                   33
#define DUK_BIDX_DUKTAPE                                              34
#define DUK_BIDX_THREAD_PROTOTYPE                                     35
#define DUK_BIDX_POINTER_PROTOTYPE                                    36
#define DUK_BIDX_DOUBLE_ERROR                                         37
#define DUK_BIDX_SYMBOL_PROTOTYPE                                     38
#define DUK_BIDX_ARRAYBUFFER_PROTOTYPE                                39
#define DUK_BIDX_DATAVIEW_PROTOTYPE                                   40
#define DUK_BIDX_INT8ARRAY_PROTOTYPE                                  41
#define DUK_BIDX_UINT8ARRAY_PROTOTYPE                                 42
#define DUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE                          43
#define DUK_BIDX_INT16ARRAY_PROTOTYPE                                 44
#define DUK_BIDX_UINT16ARRAY_PROTOTYPE                                45
#define DUK_BIDX_INT32ARRAY_PROTOTYPE                                 46
#define DUK_BIDX_UINT32ARRAY_PROTOTYPE                                47
#define DUK_BIDX_FLOAT32ARRAY_PROTOTYPE                               48
#define DUK_BIDX_FLOAT64ARRAY_PROTOTYPE                               49
#define DUK_BIDX_NODEJS_BUFFER_PROTOTYPE                              50
#define DUK_NUM_BUILTINS                                              51
#define DUK_NUM_BIDX_BUILTINS                                         51
#define DUK_NUM_ALL_BUILTINS                                          80
#if defined(DUK_USE_DOUBLE_LE)
#if !defined(DUK_SINGLE_FILE)
DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[4281];
#endif  /* !DUK_SINGLE_FILE */
#define DUK_BUILTINS_DATA_LENGTH                                      4281
#elif defined(DUK_USE_DOUBLE_BE)
#if !defined(DUK_SINGLE_FILE)
DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[4281];
#endif  /* !DUK_SINGLE_FILE */
#define DUK_BUILTINS_DATA_LENGTH                                      4281
#elif defined(DUK_USE_DOUBLE_ME)
#if !defined(DUK_SINGLE_FILE)
DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[4281];
#endif  /* !DUK_SINGLE_FILE */
#define DUK_BUILTINS_DATA_LENGTH                                      4281
#else
#error invalid endianness defines
#endif
#endif  /* DUK_USE_ROM_OBJECTS */
#endif  /* DUK_BUILTINS_H_INCLUDED */
#line 45 "duk_internal.h"

/* #include duk_util.h */
#line 1 "duk_util.h"
/*
 *  Utilities
 */

#if !defined(DUK_UTIL_H_INCLUDED)
#define DUK_UTIL_H_INCLUDED

#if defined(DUK_USE_GET_RANDOM_DOUBLE)
#define DUK_UTIL_GET_RANDOM_DOUBLE(thr) DUK_USE_GET_RANDOM_DOUBLE((thr)->heap_udata)
#else
#define DUK_UTIL_GET_RANDOM_DOUBLE(thr) duk_util_tinyrandom_get_double(thr)
#endif

/*
 *  Some useful constants
 */

#define DUK_DOUBLE_2TO32     4294967296.0
#define DUK_DOUBLE_2TO31     2147483648.0
#define DUK_DOUBLE_LOG2E     1.4426950408889634
#define DUK_DOUBLE_LOG10E    0.4342944819032518

/*
 *  Endian conversion
 */

#if defined(DUK_USE_INTEGER_LE)
#define DUK_HTON32(x) DUK_BSWAP32((x))
#define DUK_NTOH32(x) DUK_BSWAP32((x))
#define DUK_HTON16(x) DUK_BSWAP16((x))
#define DUK_NTOH16(x) DUK_BSWAP16((x))
#elif defined(DUK_USE_INTEGER_BE)
#define DUK_HTON32(x) (x)
#define DUK_NTOH32(x) (x)
#define DUK_HTON16(x) (x)
#define DUK_NTOH16(x) (x)
#else
#error internal error, endianness defines broken
#endif

/*
 *  Bitstream decoder
 */

struct duk_bitdecoder_ctx {
	const duk_uint8_t *data;
	duk_size_t offset;
	duk_size_t length;
	duk_uint32_t currval;
	duk_small_int_t currbits;
};

#define DUK_BD_BITPACKED_STRING_MAXLEN 256

/*
 *  Bitstream encoder
 */

struct duk_bitencoder_ctx {
	duk_uint8_t *data;
	duk_size_t offset;
	duk_size_t length;
	duk_uint32_t currval;
	duk_small_int_t currbits;
	duk_small_int_t truncated;
};

/*
 *  Raw write/read macros for big endian, unaligned basic values.
 *  Caller ensures there's enough space.  The INC macro variants
 *  update the pointer argument automatically.
 */

#define DUK_RAW_WRITE_U8(ptr,val)  do { \
		*(ptr) = (duk_uint8_t) (val); \
	} while (0)
#define DUK_RAW_WRITE_U16_BE(ptr,val) duk_raw_write_u16_be((ptr), (duk_uint16_t) (val))
#define DUK_RAW_WRITE_U32_BE(ptr,val) duk_raw_write_u32_be((ptr), (duk_uint32_t) (val))
#define DUK_RAW_WRITE_FLOAT_BE(ptr,val) duk_raw_write_float_be((ptr), (duk_float_t) (val))
#define DUK_RAW_WRITE_DOUBLE_BE(ptr,val) duk_raw_write_double_be((ptr), (duk_double_t) (val))
#define DUK_RAW_WRITE_XUTF8(ptr,val) duk_raw_write_xutf8((ptr), (duk_ucodepoint_t) (val))

#define DUK_RAW_WRITEINC_U8(ptr,val)  do { \
		*(ptr)++ = (duk_uint8_t) (val); \
	} while (0)
#define DUK_RAW_WRITEINC_U16_BE(ptr,val) duk_raw_writeinc_u16_be(&(ptr), (duk_uint16_t) (val))
#define DUK_RAW_WRITEINC_U32_BE(ptr,val) duk_raw_writeinc_u32_be(&(ptr), (duk_uint32_t) (val))
#define DUK_RAW_WRITEINC_FLOAT_BE(ptr,val) duk_raw_writeinc_float_be(&(ptr), (duk_float_t) (val))
#define DUK_RAW_WRITEINC_DOUBLE_BE(ptr,val) duk_raw_writeinc_double_be(&(ptr), (duk_double_t) (val))
#define DUK_RAW_WRITEINC_XUTF8(ptr,val) duk_raw_writeinc_xutf8(&(ptr), (duk_ucodepoint_t) (val))
#define DUK_RAW_WRITEINC_CESU8(ptr,val) duk_raw_writeinc_cesu8(&(ptr), (duk_ucodepoint_t) (val))

#define DUK_RAW_READ_U8(ptr) ((duk_uint8_t) (*(ptr)))
#define DUK_RAW_READ_U16_BE(ptr) duk_raw_read_u16_be((ptr));
#define DUK_RAW_READ_U32_BE(ptr) duk_raw_read_u32_be((ptr));
#define DUK_RAW_READ_DOUBLE_BE(ptr) duk_raw_read_double_be((ptr));

#define DUK_RAW_READINC_U8(ptr) ((duk_uint8_t) (*(ptr)++))
#define DUK_RAW_READINC_U16_BE(ptr) duk_raw_readinc_u16_be(&(ptr));
#define DUK_RAW_READINC_U32_BE(ptr) duk_raw_readinc_u32_be(&(ptr));
#define DUK_RAW_READINC_DOUBLE_BE(ptr) duk_raw_readinc_double_be(&(ptr));

/*
 *  Double and float byte order operations.
 */

DUK_INTERNAL_DECL void duk_dblunion_host_to_little(duk_double_union *u);
DUK_INTERNAL_DECL void duk_dblunion_little_to_host(duk_double_union *u);
DUK_INTERNAL_DECL void duk_dblunion_host_to_big(duk_double_union *u);
DUK_INTERNAL_DECL void duk_dblunion_big_to_host(duk_double_union *u);
DUK_INTERNAL_DECL void duk_fltunion_host_to_big(duk_float_union *u);
DUK_INTERNAL_DECL void duk_fltunion_big_to_host(duk_float_union *u);

/*
 *  Buffer writer (dynamic buffer only)
 *
 *  Helper for writing to a dynamic buffer with a concept of a "slack" area
 *  to reduce resizes.  You can ensure there is enough space beforehand and
 *  then write for a while without further checks, relying on a stable data
 *  pointer.  Slack handling is automatic so call sites only indicate how
 *  much data they need right now.
 *
 *  There are several ways to write using bufwriter.  The best approach
 *  depends mainly on how much performance matters over code footprint.
 *  The key issues are (1) ensuring there is space and (2) keeping the
 *  pointers consistent.  Fast code should ensure space for multiple writes
 *  with one ensure call.  Fastest inner loop code can temporarily borrow
 *  the 'p' pointer but must write it back eventually.
 *
 *  Be careful to ensure all macro arguments (other than static pointers like
 *  'thr' and 'bw_ctx') are evaluated exactly once, using temporaries if
 *  necessary (if that's not possible, there should be a note near the macro).
 *  Buffer write arguments often contain arithmetic etc so this is
 *  particularly important here.
 */

/* XXX: Migrate bufwriter and other read/write helpers to its own header? */

struct duk_bufwriter_ctx {
	duk_uint8_t *p;
	duk_uint8_t *p_base;
	duk_uint8_t *p_limit;
	duk_hbuffer_dynamic *buf;
};

#if defined(DUK_USE_PREFER_SIZE)
#define DUK_BW_SLACK_ADD           64
#define DUK_BW_SLACK_SHIFT         4    /* 2^4 -> 1/16 = 6.25% slack */
#else
#define DUK_BW_SLACK_ADD           64
#define DUK_BW_SLACK_SHIFT         2    /* 2^2 -> 1/4 = 25% slack */
#endif

/* Initialization and finalization (compaction), converting to other types. */

#define DUK_BW_INIT_PUSHBUF(thr,bw_ctx,sz) do { \
		duk_bw_init_pushbuf((thr), (bw_ctx), (sz)); \
	} while (0)
#define DUK_BW_INIT_WITHBUF(thr,bw_ctx,buf) do { \
		duk_bw_init((thr), (bw_ctx), (buf)); \
	} while (0)
#define DUK_BW_COMPACT(thr,bw_ctx) do { \
		/* Make underlying buffer compact to match DUK_BW_GET_SIZE(). */ \
		duk_bw_compact((thr), (bw_ctx)); \
	} while (0)
#define DUK_BW_PUSH_AS_STRING(thr,bw_ctx) do { \
		duk_push_lstring((thr), \
		                 (const char *) (bw_ctx)->p_base, \
		                 (duk_size_t) ((bw_ctx)->p - (bw_ctx)->p_base)); \
	} while (0)

/* Pointers may be NULL for a while when 'buf' size is zero and before any
 * ENSURE calls have been made.  Once an ENSURE has been made, the pointers
 * are required to be non-NULL so that it's always valid to use memcpy() and
 * memmove(), even for zero size.
 */
#if defined(DUK_USE_ASSERTIONS)
DUK_INTERNAL_DECL void duk_bw_assert_valid(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx);
#define DUK_BW_ASSERT_VALID_EXPR(thr,bw_ctx)  (duk_bw_assert_valid((thr), (bw_ctx)))
#define DUK_BW_ASSERT_VALID(thr,bw_ctx)  do { duk_bw_assert_valid((thr), (bw_ctx)); } while (0)
#else
#define DUK_BW_ASSERT_VALID_EXPR(thr,bw_ctx)  DUK_ASSERT_EXPR(1)
#define DUK_BW_ASSERT_VALID(thr,bw_ctx)  do {} while (0)
#endif

/* Working with the pointer and current size. */

#define DUK_BW_GET_PTR(thr,bw_ctx) \
	((bw_ctx)->p)
#define DUK_BW_SET_PTR(thr,bw_ctx,ptr) do { \
		(bw_ctx)->p = (ptr); \
	} while (0)
#define DUK_BW_ADD_PTR(thr,bw_ctx,delta) do { \
		(bw_ctx)->p += (delta); \
	} while (0)
#define DUK_BW_GET_BASEPTR(thr,bw_ctx) \
	((bw_ctx)->p_base)
#define DUK_BW_GET_LIMITPTR(thr,bw_ctx) \
	((bw_ctx)->p_limit)
#define DUK_BW_GET_SIZE(thr,bw_ctx) \
	((duk_size_t) ((bw_ctx)->p - (bw_ctx)->p_base))
#define DUK_BW_SET_SIZE(thr,bw_ctx,sz) do { \
		DUK_ASSERT((duk_size_t) (sz) <= (duk_size_t) ((bw_ctx)->p - (bw_ctx)->p_base)); \
		(bw_ctx)->p = (bw_ctx)->p_base + (sz); \
	} while (0)
#define DUK_BW_RESET_SIZE(thr,bw_ctx) do { \
		/* Reset to zero size, keep current limit. */ \
		(bw_ctx)->p = (bw_ctx)->p_base; \
	} while (0)
#define DUK_BW_GET_BUFFER(thr,bw_ctx) \
	((bw_ctx)->buf)

/* Ensuring (reserving) space. */

#define DUK_BW_ENSURE(thr,bw_ctx,sz) do { \
		duk_size_t duk__sz, duk__space; \
		DUK_BW_ASSERT_VALID((thr), (bw_ctx)); \
		duk__sz = (sz); \
		duk__space = (duk_size_t) ((bw_ctx)->p_limit - (bw_ctx)->p); \
		if (duk__space < duk__sz) { \
			(void) duk_bw_resize((thr), (bw_ctx), duk__sz); \
		} \
	} while (0)
/* NOTE: Multiple evaluation of 'ptr' in this macro. */
/* XXX: Rework to use an always-inline function? */
#define DUK_BW_ENSURE_RAW(thr,bw_ctx,sz,ptr) \
	(((duk_size_t) ((bw_ctx)->p_limit - (ptr)) >= (sz)) ? \
	 (ptr) : \
	 ((bw_ctx)->p = (ptr), duk_bw_resize((thr),(bw_ctx),(sz))))
#define DUK_BW_ENSURE_GETPTR(thr,bw_ctx,sz) \
	DUK_BW_ENSURE_RAW((thr), (bw_ctx), (sz), (bw_ctx)->p)
#define DUK_BW_ASSERT_SPACE_EXPR(thr,bw_ctx,sz) \
	(DUK_BW_ASSERT_VALID_EXPR((thr), (bw_ctx)), \
	 DUK_ASSERT_EXPR((duk_size_t) ((bw_ctx)->p_limit - (bw_ctx)->p) >= (duk_size_t) (sz)))
#define DUK_BW_ASSERT_SPACE(thr,bw_ctx,sz) do { \
		DUK_BW_ASSERT_SPACE_EXPR((thr), (bw_ctx), (sz)); \
	} while (0)

/* Miscellaneous. */

#define DUK_BW_SETPTR_AND_COMPACT(thr,bw_ctx,ptr) do { \
		(bw_ctx)->p = (ptr); \
		duk_bw_compact((thr), (bw_ctx)); \
	} while (0)

/* Fast write calls which assume you control the slack beforehand.
 * Multibyte write variants exist and use a temporary write pointer
 * because byte writes alias with anything: with a stored pointer
 * explicit pointer load/stores get generated (e.g. gcc -Os).
 */

#define DUK_BW_WRITE_RAW_U8(thr,bw_ctx,val) do { \
		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 1); \
		*(bw_ctx)->p++ = (duk_uint8_t) (val); \
	} while (0)
#define DUK_BW_WRITE_RAW_U8_2(thr,bw_ctx,val1,val2) do { \
		duk_uint8_t *duk__p; \
		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 2); \
		duk__p = (bw_ctx)->p; \
		*duk__p++ = (duk_uint8_t) (val1); \
		*duk__p++ = (duk_uint8_t) (val2); \
		(bw_ctx)->p = duk__p; \
	} while (0)
#define DUK_BW_WRITE_RAW_U8_3(thr,bw_ctx,val1,val2,val3) do { \
		duk_uint8_t *duk__p; \
		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 3); \
		duk__p = (bw_ctx)->p; \
		*duk__p++ = (duk_uint8_t) (val1); \
		*duk__p++ = (duk_uint8_t) (val2); \
		*duk__p++ = (duk_uint8_t) (val3); \
		(bw_ctx)->p = duk__p; \
	} while (0)
#define DUK_BW_WRITE_RAW_U8_4(thr,bw_ctx,val1,val2,val3,val4) do { \
		duk_uint8_t *duk__p; \
		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 4); \
		duk__p = (bw_ctx)->p; \
		*duk__p++ = (duk_uint8_t) (val1); \
		*duk__p++ = (duk_uint8_t) (val2); \
		*duk__p++ = (duk_uint8_t) (val3); \
		*duk__p++ = (duk_uint8_t) (val4); \
		(bw_ctx)->p = duk__p; \
	} while (0)
#define DUK_BW_WRITE_RAW_U8_5(thr,bw_ctx,val1,val2,val3,val4,val5) do { \
		duk_uint8_t *duk__p; \
		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 5); \
		duk__p = (bw_ctx)->p; \
		*duk__p++ = (duk_uint8_t) (val1); \
		*duk__p++ = (duk_uint8_t) (val2); \
		*duk__p++ = (duk_uint8_t) (val3); \
		*duk__p++ = (duk_uint8_t) (val4); \
		*duk__p++ = (duk_uint8_t) (val5); \
		(bw_ctx)->p = duk__p; \
	} while (0)
#define DUK_BW_WRITE_RAW_U8_6(thr,bw_ctx,val1,val2,val3,val4,val5,val6) do { \
		duk_uint8_t *duk__p; \
		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 6); \
		duk__p = (bw_ctx)->p; \
		*duk__p++ = (duk_uint8_t) (val1); \
		*duk__p++ = (duk_uint8_t) (val2); \
		*duk__p++ = (duk_uint8_t) (val3); \
		*duk__p++ = (duk_uint8_t) (val4); \
		*duk__p++ = (duk_uint8_t) (val5); \
		*duk__p++ = (duk_uint8_t) (val6); \
		(bw_ctx)->p = duk__p; \
	} while (0)
#define DUK_BW_WRITE_RAW_XUTF8(thr,bw_ctx,cp) do { \
		duk_ucodepoint_t duk__cp; \
		duk_small_int_t duk__enc_len; \
		duk__cp = (duk_ucodepoint_t) (cp); \
		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), duk_unicode_get_xutf8_length(duk__cp)); \
		duk__enc_len = duk_unicode_encode_xutf8(duk__cp, (bw_ctx)->p); \
		(bw_ctx)->p += duk__enc_len; \
	} while (0)
#define DUK_BW_WRITE_RAW_CESU8(thr,bw_ctx,cp) do { \
		duk_ucodepoint_t duk__cp; \
		duk_small_int_t duk__enc_len; \
		duk__cp = (duk_ucodepoint_t) (cp); \
		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), duk_unicode_get_cesu8_length(duk__cp)); \
		duk__enc_len = duk_unicode_encode_cesu8(duk__cp, (bw_ctx)->p); \
		(bw_ctx)->p += duk__enc_len; \
	} while (0)
/* XXX: add temporary duk__p pointer here too; sharing */
/* XXX: avoid unsafe variants */
#define DUK_BW_WRITE_RAW_BYTES(thr,bw_ctx,valptr,valsz) do { \
		const void *duk__valptr; \
		duk_size_t duk__valsz; \
		duk__valptr = (const void *) (valptr); \
		duk__valsz = (duk_size_t) (valsz); \
		duk_memcpy_unsafe((void *) ((bw_ctx)->p), duk__valptr, duk__valsz); \
		(bw_ctx)->p += duk__valsz; \
	} while (0)
#define DUK_BW_WRITE_RAW_CSTRING(thr,bw_ctx,val) do { \
		const duk_uint8_t *duk__val; \
		duk_size_t duk__val_len; \
		duk__val = (const duk_uint8_t *) (val); \
		duk__val_len = DUK_STRLEN((const char *) duk__val); \
		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) duk__val, duk__val_len); \
		(bw_ctx)->p += duk__val_len; \
	} while (0)
#define DUK_BW_WRITE_RAW_HSTRING(thr,bw_ctx,val) do { \
		duk_size_t duk__val_len; \
		duk__val_len = DUK_HSTRING_GET_BYTELEN((val)); \
		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HSTRING_GET_DATA((val)), duk__val_len); \
		(bw_ctx)->p += duk__val_len; \
	} while (0)
#define DUK_BW_WRITE_RAW_HBUFFER(thr,bw_ctx,val) do { \
		duk_size_t duk__val_len; \
		duk__val_len = DUK_HBUFFER_GET_SIZE((val)); \
		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
		(bw_ctx)->p += duk__val_len; \
	} while (0)
#define DUK_BW_WRITE_RAW_HBUFFER_FIXED(thr,bw_ctx,val) do { \
		duk_size_t duk__val_len; \
		duk__val_len = DUK_HBUFFER_FIXED_GET_SIZE((val)); \
		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_FIXED_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
		(bw_ctx)->p += duk__val_len; \
	} while (0)
#define DUK_BW_WRITE_RAW_HBUFFER_DYNAMIC(thr,bw_ctx,val) do { \
		duk_size_t duk__val_len; \
		duk__val_len = DUK_HBUFFER_DYNAMIC_GET_SIZE((val)); \
		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
		(bw_ctx)->p += duk__val_len; \
	} while (0)

/* Append bytes from a slice already in the buffer. */
#define DUK_BW_WRITE_RAW_SLICE(thr,bw,dst_off,dst_len) \
	duk_bw_write_raw_slice((thr), (bw), (dst_off), (dst_len))

/* Insert bytes in the middle of the buffer from an external buffer. */
#define DUK_BW_INSERT_RAW_BYTES(thr,bw,dst_off,buf,len) \
	duk_bw_insert_raw_bytes((thr), (bw), (dst_off), (buf), (len))

/* Insert bytes in the middle of the buffer from a slice already
 * in the buffer.  Source offset is interpreted "before" the operation.
 */
#define DUK_BW_INSERT_RAW_SLICE(thr,bw,dst_off,src_off,len) \
	duk_bw_insert_raw_slice((thr), (bw), (dst_off), (src_off), (len))

/* Insert a reserved area somewhere in the buffer; caller fills it.
 * Evaluates to a (duk_uint_t *) pointing to the start of the reserved
 * area for convenience.
 */
#define DUK_BW_INSERT_RAW_AREA(thr,bw,off,len) \
	duk_bw_insert_raw_area((thr), (bw), (off), (len))

/* Remove a slice from inside buffer. */
#define DUK_BW_REMOVE_RAW_SLICE(thr,bw,off,len) \
	duk_bw_remove_raw_slice((thr), (bw), (off), (len))

/* Safe write calls which will ensure space first. */

#define DUK_BW_WRITE_ENSURE_U8(thr,bw_ctx,val) do { \
		DUK_BW_ENSURE((thr), (bw_ctx), 1); \
		DUK_BW_WRITE_RAW_U8((thr), (bw_ctx), (val)); \
	} while (0)
#define DUK_BW_WRITE_ENSURE_U8_2(thr,bw_ctx,val1,val2) do { \
		DUK_BW_ENSURE((thr), (bw_ctx), 2); \
		DUK_BW_WRITE_RAW_U8_2((thr), (bw_ctx), (val1), (val2)); \
	} while (0)
#define DUK_BW_WRITE_ENSURE_U8_3(thr,bw_ctx,val1,val2,val3) do { \
		DUK_BW_ENSURE((thr), (bw_ctx), 3); \
		DUK_BW_WRITE_RAW_U8_3((thr), (bw_ctx), (val1), (val2), (val3)); \
	} while (0)
#define DUK_BW_WRITE_ENSURE_U8_4(thr,bw_ctx,val1,val2,val3,val4) do { \
		DUK_BW_ENSURE((thr), (bw_ctx), 4); \
		DUK_BW_WRITE_RAW_U8_4((thr), (bw_ctx), (val1), (val2), (val3), (val4)); \
	} while (0)
#define DUK_BW_WRITE_ENSURE_U8_5(thr,bw_ctx,val1,val2,val3,val4,val5) do { \
		DUK_BW_ENSURE((thr), (bw_ctx), 5); \
		DUK_BW_WRITE_RAW_U8_5((thr), (bw_ctx), (val1), (val2), (val3), (val4), (val5)); \
	} while (0)
#define DUK_BW_WRITE_ENSURE_U8_6(thr,bw_ctx,val1,val2,val3,val4,val5,val6) do { \
		DUK_BW_ENSURE((thr), (bw_ctx), 6); \
		DUK_BW_WRITE_RAW_U8_6((thr), (bw_ctx), (val1), (val2), (val3), (val4), (val5), (val6)); \
	} while (0)
#define DUK_BW_WRITE_ENSURE_XUTF8(thr,bw_ctx,cp) do { \
		DUK_BW_ENSURE((thr), (bw_ctx), DUK_UNICODE_MAX_XUTF8_LENGTH); \
		DUK_BW_WRITE_RAW_XUTF8((thr), (bw_ctx), (cp)); \
	} while (0)
#define DUK_BW_WRITE_ENSURE_CESU8(thr,bw_ctx,cp) do { \
		DUK_BW_ENSURE((thr), (bw_ctx), DUK_UNICODE_MAX_CESU8_LENGTH); \
		DUK_BW_WRITE_RAW_CESU8((thr), (bw_ctx), (cp)); \
	} while (0)
/* XXX: add temporary duk__p pointer here too; sharing */
/* XXX: avoid unsafe */
#define DUK_BW_WRITE_ENSURE_BYTES(thr,bw_ctx,valptr,valsz) do { \
		const void *duk__valptr; \
		duk_size_t duk__valsz; \
		duk__valptr = (const void *) (valptr); \
		duk__valsz = (duk_size_t) (valsz); \
		DUK_BW_ENSURE((thr), (bw_ctx), duk__valsz); \
		duk_memcpy_unsafe((void *) ((bw_ctx)->p), duk__valptr, duk__valsz); \
		(bw_ctx)->p += duk__valsz; \
	} while (0)
#define DUK_BW_WRITE_ENSURE_CSTRING(thr,bw_ctx,val) do { \
		const duk_uint8_t *duk__val; \
		duk_size_t duk__val_len; \
		duk__val = (const duk_uint8_t *) (val); \
		duk__val_len = DUK_STRLEN((const char *) duk__val); \
		DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) duk__val, duk__val_len); \
		(bw_ctx)->p += duk__val_len; \
	} while (0)
#define DUK_BW_WRITE_ENSURE_HSTRING(thr,bw_ctx,val) do { \
		duk_size_t duk__val_len; \
		duk__val_len = DUK_HSTRING_GET_BYTELEN((val)); \
		DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HSTRING_GET_DATA((val)), duk__val_len); \
		(bw_ctx)->p += duk__val_len; \
	} while (0)
#define DUK_BW_WRITE_ENSURE_HBUFFER(thr,bw_ctx,val) do { \
		duk_size_t duk__val_len; \
		duk__val_len = DUK_HBUFFER_GET_SIZE((val)); \
		DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
		(bw_ctx)->p += duk__val_len; \
	} while (0)
#define DUK_BW_WRITE_ENSURE_HBUFFER_FIXED(thr,bw_ctx,val) do { \
		duk_size_t duk__val_len; \
		duk__val_len = DUK_HBUFFER_FIXED_GET_SIZE((val)); \
		DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_FIXED_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
		(bw_ctx)->p += duk__val_len; \
	} while (0)
#define DUK_BW_WRITE_ENSURE_HBUFFER_DYNAMIC(thr,bw_ctx,val) do { \
		duk_size_t duk__val_len; \
		duk__val_len = DUK_HBUFFER_DYNAMIC_GET_SIZE((val)); \
		DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
		(bw_ctx)->p += duk__val_len; \
	} while (0)

#define DUK_BW_WRITE_ENSURE_SLICE(thr,bw,dst_off,dst_len) \
	duk_bw_write_ensure_slice((thr), (bw), (dst_off), (dst_len))
#define DUK_BW_INSERT_ENSURE_BYTES(thr,bw,dst_off,buf,len) \
	duk_bw_insert_ensure_bytes((thr), (bw), (dst_off), (buf), (len))
#define DUK_BW_INSERT_ENSURE_SLICE(thr,bw,dst_off,src_off,len) \
	duk_bw_insert_ensure_slice((thr), (bw), (dst_off), (src_off), (len))
#define DUK_BW_INSERT_ENSURE_AREA(thr,bw,off,len) \
	/* Evaluates to (duk_uint8_t *) pointing to start of area. */ \
	duk_bw_insert_ensure_area((thr), (bw), (off), (len))
#define DUK_BW_REMOVE_ENSURE_SLICE(thr,bw,off,len) \
	/* No difference between raw/ensure because the buffer shrinks. */ \
	DUK_BW_REMOVE_RAW_SLICE((thr), (bw), (off), (len))

/*
 *  Externs and prototypes
 */

#if !defined(DUK_SINGLE_FILE)
DUK_INTERNAL_DECL const duk_uint8_t duk_lc_digits[36];
DUK_INTERNAL_DECL const duk_uint8_t duk_uc_nybbles[16];
DUK_INTERNAL_DECL const duk_int8_t duk_hex_dectab[256];
#if defined(DUK_USE_HEX_FASTPATH)
DUK_INTERNAL_DECL const duk_int16_t duk_hex_dectab_shift4[256];
DUK_INTERNAL_DECL const duk_uint16_t duk_hex_enctab[256];
#endif
#endif  /* !DUK_SINGLE_FILE */

/* Note: assumes that duk_util_probe_steps size is 32 */
#if defined(DUK_USE_HOBJECT_HASH_PART)
#if !defined(DUK_SINGLE_FILE)
DUK_INTERNAL_DECL duk_uint8_t duk_util_probe_steps[32];
#endif  /* !DUK_SINGLE_FILE */
#endif

#if defined(DUK_USE_STRHASH_DENSE)
DUK_INTERNAL_DECL duk_uint32_t duk_util_hashbytes(const duk_uint8_t *data, duk_size_t len, duk_uint32_t seed);
#endif

DUK_INTERNAL_DECL duk_uint32_t duk_bd_decode(duk_bitdecoder_ctx *ctx, duk_small_int_t bits);
DUK_INTERNAL_DECL duk_small_uint_t duk_bd_decode_flag(duk_bitdecoder_ctx *ctx);
DUK_INTERNAL_DECL duk_uint32_t duk_bd_decode_flagged(duk_bitdecoder_ctx *ctx, duk_small_int_t bits, duk_uint32_t def_value);
DUK_INTERNAL_DECL duk_int32_t duk_bd_decode_flagged_signed(duk_bitdecoder_ctx *ctx, duk_small_int_t bits, duk_int32_t def_value);
DUK_INTERNAL_DECL duk_uint32_t duk_bd_decode_varuint(duk_bitdecoder_ctx *ctx);
DUK_INTERNAL_DECL duk_small_uint_t duk_bd_decode_bitpacked_string(duk_bitdecoder_ctx *bd, duk_uint8_t *out);

DUK_INTERNAL_DECL void duk_be_encode(duk_bitencoder_ctx *ctx, duk_uint32_t data, duk_small_int_t bits);
DUK_INTERNAL_DECL void duk_be_finish(duk_bitencoder_ctx *ctx);

#if !defined(DUK_USE_GET_RANDOM_DOUBLE)
DUK_INTERNAL_DECL duk_double_t duk_util_tinyrandom_get_double(duk_hthread *thr);
DUK_INTERNAL_DECL void duk_util_tinyrandom_prepare_seed(duk_hthread *thr);
#endif

DUK_INTERNAL_DECL void duk_bw_init(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_hbuffer_dynamic *h_buf);
DUK_INTERNAL_DECL void duk_bw_init_pushbuf(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t buf_size);
DUK_INTERNAL_DECL duk_uint8_t *duk_bw_resize(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t sz);
DUK_INTERNAL_DECL void duk_bw_compact(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx);
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);
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);
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);
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);
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);
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);
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);
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);
DUK_INTERNAL_DECL void duk_bw_remove_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len);
/* No duk_bw_remove_ensure_slice(), functionality would be identical. */

DUK_INTERNAL_DECL duk_uint16_t duk_raw_read_u16_be(const duk_uint8_t *p);
DUK_INTERNAL_DECL duk_uint32_t duk_raw_read_u32_be(const duk_uint8_t *p);
DUK_INTERNAL_DECL duk_float_t duk_raw_read_float_be(const duk_uint8_t *p);
DUK_INTERNAL_DECL duk_double_t duk_raw_read_double_be(const duk_uint8_t *p);
DUK_INTERNAL_DECL duk_uint16_t duk_raw_readinc_u16_be(const duk_uint8_t **p);
DUK_INTERNAL_DECL duk_uint32_t duk_raw_readinc_u32_be(const duk_uint8_t **p);
DUK_INTERNAL_DECL duk_float_t duk_raw_readinc_float_be(const duk_uint8_t **p);
DUK_INTERNAL_DECL duk_double_t duk_raw_readinc_double_be(const duk_uint8_t **p);
DUK_INTERNAL_DECL void duk_raw_write_u16_be(duk_uint8_t *p, duk_uint16_t val);
DUK_INTERNAL_DECL void duk_raw_write_u32_be(duk_uint8_t *p, duk_uint32_t val);
DUK_INTERNAL_DECL void duk_raw_write_float_be(duk_uint8_t *p, duk_float_t val);
DUK_INTERNAL_DECL void duk_raw_write_double_be(duk_uint8_t *p, duk_double_t val);
DUK_INTERNAL_DECL duk_small_int_t duk_raw_write_xutf8(duk_uint8_t *p, duk_ucodepoint_t val);
DUK_INTERNAL_DECL duk_small_int_t duk_raw_write_cesu8(duk_uint8_t *p, duk_ucodepoint_t val);
DUK_INTERNAL_DECL void duk_raw_writeinc_u16_be(duk_uint8_t **p, duk_uint16_t val);
DUK_INTERNAL_DECL void duk_raw_writeinc_u32_be(duk_uint8_t **p, duk_uint32_t val);
DUK_INTERNAL_DECL void duk_raw_writeinc_float_be(duk_uint8_t **p, duk_float_t val);
DUK_INTERNAL_DECL void duk_raw_writeinc_double_be(duk_uint8_t **p, duk_double_t val);
DUK_INTERNAL_DECL void duk_raw_writeinc_xutf8(duk_uint8_t **p, duk_ucodepoint_t val);
DUK_INTERNAL_DECL void duk_raw_writeinc_cesu8(duk_uint8_t **p, duk_ucodepoint_t val);

#if defined(DUK_USE_DEBUGGER_SUPPORT)  /* For now only needed by the debugger. */
DUK_INTERNAL_DECL void duk_byteswap_bytes(duk_uint8_t *p, duk_small_uint_t len);
#endif

/* memcpy(), memmove() etc wrappers.  The plain variants like duk_memcpy()
 * assume C99+ and 'src' and 'dst' pointers must be non-NULL even when the
 * operation size is zero.  The unsafe variants like duk_memcpy_safe() deal
 * with the zero size case explicitly, and allow NULL pointers in that case
 * (which is undefined behavior in C99+).  For the majority of actual targets
 * a NULL pointer with a zero length is fine in practice.  These wrappers are
 * macros to force inlining; because there are hundreds of call sites, even a
 * few extra bytes per call site adds up to ~1kB footprint.
 */
#if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
#define duk_memcpy(dst,src,len)  do { \
		void *duk__dst = (dst); \
		const void *duk__src = (src); \
		duk_size_t duk__len = (len); \
		DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
		DUK_ASSERT(duk__src != NULL || duk__len == 0U); \
		(void) DUK_MEMCPY(duk__dst, duk__src, (size_t) duk__len); \
	} while (0)
#define duk_memcpy_unsafe(dst,src,len)  duk_memcpy((dst), (src), (len))
#define duk_memmove(dst,src,len)  do { \
		void *duk__dst = (dst); \
		const void *duk__src = (src); \
		duk_size_t duk__len = (len); \
		DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
		DUK_ASSERT(duk__src != NULL || duk__len == 0U); \
		(void) DUK_MEMMOVE(duk__dst, duk__src, (size_t) duk__len); \
	} while (0)
#define duk_memmove_unsafe(dst,src,len)  duk_memmove((dst), (src), (len))
#define duk_memset(dst,val,len)  do { \
		void *duk__dst = (dst); \
		duk_small_int_t duk__val = (val); \
		duk_size_t duk__len = (len); \
		DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
		(void) DUK_MEMSET(duk__dst, duk__val, (size_t) duk__len); \
	} while (0)
#define duk_memset_unsafe(dst,val,len)  duk_memset((dst), (val), (len))
#define duk_memzero(dst,len)  do { \
		void *duk__dst = (dst); \
		duk_size_t duk__len = (len); \
		DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
		(void) DUK_MEMZERO(duk__dst, (size_t) duk__len); \
	} while (0)
#define duk_memzero_unsafe(dst,len)  duk_memzero((dst), (len))
#else  /* DUK_USE_ALLOW_UNDEFINED_BEHAVIOR */
#define duk_memcpy(dst,src,len)  do { \
		void *duk__dst = (dst); \
		const void *duk__src = (src); \
		duk_size_t duk__len = (len); \
		DUK_ASSERT(duk__dst != NULL); \
		DUK_ASSERT(duk__src != NULL); \
		(void) DUK_MEMCPY(duk__dst, duk__src, (size_t) duk__len); \
	} while (0)
#define duk_memcpy_unsafe(dst,src,len)  do { \
		void *duk__dst = (dst); \
		const void *duk__src = (src); \
		duk_size_t duk__len = (len); \
		DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
		DUK_ASSERT(duk__src != NULL || duk__len == 0U); \
		if (DUK_LIKELY(duk__len > 0U)) { \
			DUK_ASSERT(duk__dst != NULL); \
			DUK_ASSERT(duk__src != NULL); \
			(void) DUK_MEMCPY(duk__dst, duk__src, (size_t) duk__len); \
		} \
	} while (0)
#define duk_memmove(dst,src,len)  do { \
		void *duk__dst = (dst); \
		const void *duk__src = (src); \
		duk_size_t duk__len = (len); \
		DUK_ASSERT(duk__dst != NULL); \
		DUK_ASSERT(duk__src != NULL); \
		(void) DUK_MEMMOVE(duk__dst, duk__src, (size_t) duk__len); \
	} while (0)
#define duk_memmove_unsafe(dst,src,len)  do { \
		void *duk__dst = (dst); \
		const void *duk__src = (src); \
		duk_size_t duk__len = (len); \
		DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
		DUK_ASSERT(duk__src != NULL || duk__len == 0U); \
		if (DUK_LIKELY(duk__len > 0U)) { \
			DUK_ASSERT(duk__dst != NULL); \
			DUK_ASSERT(duk__src != NULL); \
			(void) DUK_MEMMOVE(duk__dst, duk__src, (size_t) duk__len); \
		} \
	} while (0)
#define duk_memset(dst,val,len)  do { \
		void *duk__dst = (dst); \
		duk_small_int_t duk__val = (val); \
		duk_size_t duk__len = (len); \
		DUK_ASSERT(duk__dst != NULL); \
		(void) DUK_MEMSET(duk__dst, duk__val, (size_t) duk__len); \
	} while (0)
#define duk_memset_unsafe(dst,val,len)  do { \
		void *duk__dst = (dst); \
		duk_small_int_t duk__val = (val); \
		duk_size_t duk__len = (len); \
		DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
		if (DUK_LIKELY(duk__len > 0U)) { \
			DUK_ASSERT(duk__dst != NULL); \
			(void) DUK_MEMSET(duk__dst, duk__val, (size_t) duk__len); \
		} \
	} while (0)
#define duk_memzero(dst,len)  do { \
		void *duk__dst = (dst); \
		duk_size_t duk__len = (len); \
		DUK_ASSERT(duk__dst != NULL); \
		(void) DUK_MEMZERO(duk__dst, (size_t) duk__len); \
	} while (0)
#define duk_memzero_unsafe(dst,len)  do { \
		void *duk__dst = (dst); \
		duk_size_t duk__len = (len); \
		DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
		if (DUK_LIKELY(duk__len > 0U)) { \
			DUK_ASSERT(duk__dst != NULL); \
			(void) DUK_MEMZERO(duk__dst, (size_t) duk__len); \
		} \
	} while (0)
#endif  /* DUK_USE_ALLOW_UNDEFINED_BEHAVIOR */

DUK_INTERNAL_DECL duk_small_int_t duk_memcmp(const void *s1, const void *s2, duk_size_t len);
DUK_INTERNAL_DECL duk_small_int_t duk_memcmp_unsafe(const void *s1, const void *s2, duk_size_t len);

DUK_INTERNAL_DECL duk_bool_t duk_is_whole_get_int32_nonegzero(duk_double_t x, duk_int32_t *ival);
DUK_INTERNAL_DECL duk_bool_t duk_is_whole_get_int32(duk_double_t x, duk_int32_t *ival);
DUK_INTERNAL_DECL duk_bool_t duk_double_is_anyinf(duk_double_t x);
DUK_INTERNAL_DECL duk_bool_t duk_double_is_posinf(duk_double_t x);
DUK_INTERNAL_DECL duk_bool_t duk_double_is_neginf(duk_double_t x);
DUK_INTERNAL_DECL duk_bool_t duk_double_is_nan(duk_double_t x);
DUK_INTERNAL_DECL duk_bool_t duk_double_is_nan_or_zero(duk_double_t x);
DUK_INTERNAL_DECL duk_bool_t duk_double_is_nan_or_inf(duk_double_t x);
DUK_INTERNAL_DECL duk_bool_t duk_double_is_nan_zero_inf(duk_double_t x);
DUK_INTERNAL_DECL duk_small_uint_t duk_double_signbit(duk_double_t x);
DUK_INTERNAL_DECL duk_double_t duk_double_trunc_towards_zero(duk_double_t x);
DUK_INTERNAL_DECL duk_bool_t duk_double_same_sign(duk_double_t x, duk_double_t y);
DUK_INTERNAL_DECL duk_double_t duk_double_fmin(duk_double_t x, duk_double_t y);
DUK_INTERNAL_DECL duk_double_t duk_double_fmax(duk_double_t x, duk_double_t y);
DUK_INTERNAL_DECL duk_bool_t duk_double_is_finite(duk_double_t x);
DUK_INTERNAL_DECL duk_bool_t duk_double_is_integer(duk_double_t x);
DUK_INTERNAL_DECL duk_bool_t duk_double_is_safe_integer(duk_double_t x);

DUK_INTERNAL_DECL duk_double_t duk_double_div(duk_double_t x, duk_double_t y);
DUK_INTERNAL_DECL duk_int_t duk_double_to_int_t(duk_double_t x);
DUK_INTERNAL_DECL duk_uint_t duk_double_to_uint_t(duk_double_t x);
DUK_INTERNAL_DECL duk_int32_t duk_double_to_int32_t(duk_double_t x);
DUK_INTERNAL_DECL duk_uint32_t duk_double_to_uint32_t(duk_double_t x);
DUK_INTERNAL_DECL duk_float_t duk_double_to_float_t(duk_double_t x);
DUK_INTERNAL_DECL duk_bool_t duk_double_equals(duk_double_t x, duk_double_t y);
DUK_INTERNAL_DECL duk_bool_t duk_float_equals(duk_float_t x, duk_float_t y);

/*
 *  Miscellaneous
 */

/* Example: x     = 0x10 = 0b00010000
 *          x - 1 = 0x0f = 0b00001111
 *          x & (x - 1) == 0
 *
 *          x     = 0x07 = 0b00000111
 *          x - 1 = 0x06 = 0b00000110
 *          x & (x - 1) != 0
 *
 * However, incorrectly true for x == 0 so check for that explicitly.
 */
#define DUK_IS_POWER_OF_TWO(x) \
	((x) != 0U && ((x) & ((x) - 1U)) == 0U)

#endif  /* DUK_UTIL_H_INCLUDED */
/* #include duk_strings.h */
#line 1 "duk_strings.h"
/*
 *  Shared string macros.
 *
 *  Using shared macros helps minimize strings data size because it's easy
 *  to check if an existing string could be used.  String constants don't
 *  need to be all defined here; defining a string here makes sense if there's
 *  a high chance the string could be reused.  Also, using macros allows
 *  a call site express the exact string needed, but the macro may map to an
 *  approximate string to reduce unique string count.  Macros can also be
 *  more easily tuned for low memory targets than #if defined()s throughout
 *  the code base.
 *
 *  Because format strings behave differently in the call site (they need to
 *  be followed by format arguments), they use a special prefix DUK_STR_FMT_.
 *
 *  On some compilers using explicit shared strings is preferable; on others
 *  it may be better to use straight literals because the compiler will combine
 *  them anyway, and such strings won't end up unnecessarily in a symbol table.
 */

#if !defined(DUK_ERRMSG_H_INCLUDED)
#define DUK_ERRMSG_H_INCLUDED

/* Mostly API and built-in method related */
#define DUK_STR_INTERNAL_ERROR                   "internal error"
#define DUK_STR_UNSUPPORTED                      "unsupported"
#define DUK_STR_INVALID_COUNT                    "invalid count"
#define DUK_STR_INVALID_ARGS                     "invalid args"
#define DUK_STR_INVALID_STATE                    "invalid state"
#define DUK_STR_INVALID_INPUT                    "invalid input"
#define DUK_STR_INVALID_LENGTH                   "invalid length"
#define DUK_STR_NOT_CONSTRUCTABLE                "not constructable"
#define DUK_STR_CONSTRUCT_ONLY                   "constructor requires 'new'"
#define DUK_STR_NOT_CALLABLE                     "not callable"
#define DUK_STR_NOT_EXTENSIBLE                   "not extensible"
#define DUK_STR_NOT_WRITABLE                     "not writable"
#define DUK_STR_NOT_CONFIGURABLE                 "not configurable"
#define DUK_STR_INVALID_CONTEXT                  "invalid context"
#define DUK_STR_INVALID_INDEX                    "invalid args"
#define DUK_STR_PUSH_BEYOND_ALLOC_STACK          "cannot push beyond allocated stack"
#define DUK_STR_NOT_UNDEFINED                    "unexpected type"
#define DUK_STR_NOT_NULL                         "unexpected type"
#define DUK_STR_NOT_BOOLEAN                      "unexpected type"
#define DUK_STR_NOT_NUMBER                       "unexpected type"
#define DUK_STR_NOT_STRING                       "unexpected type"
#define DUK_STR_NOT_OBJECT                       "unexpected type"
#define DUK_STR_NOT_POINTER                      "unexpected type"
#define DUK_STR_NOT_BUFFER                       "not buffer"  /* still in use with verbose messages */
#define DUK_STR_UNEXPECTED_TYPE                  "unexpected type"
#define DUK_STR_NOT_THREAD                       "unexpected type"
#define DUK_STR_NOT_COMPFUNC                     "unexpected type"
#define DUK_STR_NOT_NATFUNC                      "unexpected type"
#define DUK_STR_NOT_C_FUNCTION                   "unexpected type"
#define DUK_STR_NOT_FUNCTION                     "unexpected type"
#define DUK_STR_NOT_REGEXP                       "unexpected type"
#define DUK_STR_TOPRIMITIVE_FAILED               "coercion to primitive failed"
#define DUK_STR_NUMBER_OUTSIDE_RANGE             "number outside range"
#define DUK_STR_NOT_OBJECT_COERCIBLE             "not object coercible"
#define DUK_STR_CANNOT_NUMBER_COERCE_SYMBOL      "cannot number coerce Symbol"
#define DUK_STR_CANNOT_STRING_COERCE_SYMBOL      "cannot string coerce Symbol"
#define DUK_STR_STRING_TOO_LONG                  "string too long"
#define DUK_STR_BUFFER_TOO_LONG                  "buffer too long"
#define DUK_STR_ALLOC_FAILED                     "alloc failed"
#define DUK_STR_WRONG_BUFFER_TYPE                "wrong buffer type"
#define DUK_STR_BASE64_ENCODE_FAILED             "base64 encode failed"
#define DUK_STR_SOURCE_DECODE_FAILED             "source decode failed"
#define DUK_STR_UTF8_DECODE_FAILED               "utf-8 decode failed"
#define DUK_STR_BASE64_DECODE_FAILED             "base64 decode failed"
#define DUK_STR_HEX_DECODE_FAILED                "hex decode failed"
#define DUK_STR_INVALID_BYTECODE                 "invalid bytecode"
#define DUK_STR_NO_SOURCECODE                    "no sourcecode"
#define DUK_STR_RESULT_TOO_LONG                  "result too long"
#define DUK_STR_INVALID_CFUNC_RC                 "invalid C function rc"
#define DUK_STR_INVALID_INSTANCEOF_RVAL          "invalid instanceof rval"
#define DUK_STR_INVALID_INSTANCEOF_RVAL_NOPROTO  "instanceof rval has no .prototype"

/* JSON */
#define DUK_STR_FMT_PTR                          "%p"
#define DUK_STR_FMT_INVALID_JSON                 "invalid json (at offset %ld)"
#define DUK_STR_JSONDEC_RECLIMIT                 "json decode recursion limit"
#define DUK_STR_JSONENC_RECLIMIT                 "json encode recursion limit"
#define DUK_STR_CYCLIC_INPUT                     "cyclic input"

/* Object property access */
#define DUK_STR_INVALID_BASE                     "invalid base value"
#define DUK_STR_STRICT_CALLER_READ               "cannot read strict 'caller'"
#define DUK_STR_PROXY_REJECTED                   "proxy rejected"
#define DUK_STR_INVALID_ARRAY_LENGTH             "invalid array length"
#define DUK_STR_SETTER_UNDEFINED                 "setter undefined"
#define DUK_STR_INVALID_DESCRIPTOR               "invalid descriptor"

/* Proxy */
#define DUK_STR_PROXY_REVOKED                    "proxy revoked"
#define DUK_STR_INVALID_TRAP_RESULT              "invalid trap result"

/* Variables */

/* Lexer */
#define DUK_STR_INVALID_ESCAPE                   "invalid escape"
#define DUK_STR_UNTERMINATED_STRING              "unterminated string"
#define DUK_STR_UNTERMINATED_COMMENT             "unterminated comment"
#define DUK_STR_UNTERMINATED_REGEXP              "unterminated regexp"
#define DUK_STR_TOKEN_LIMIT                      "token limit"
#define DUK_STR_REGEXP_SUPPORT_DISABLED          "regexp support disabled"
#define DUK_STR_INVALID_NUMBER_LITERAL           "invalid number literal"
#define DUK_STR_INVALID_TOKEN                    "invalid token"

/* Compiler */
#define DUK_STR_PARSE_ERROR                      "parse error"
#define DUK_STR_DUPLICATE_LABEL                  "duplicate label"
#define DUK_STR_INVALID_LABEL                    "invalid label"
#define DUK_STR_INVALID_ARRAY_LITERAL            "invalid array literal"
#define DUK_STR_INVALID_OBJECT_LITERAL           "invalid object literal"
#define DUK_STR_INVALID_VAR_DECLARATION          "invalid variable declaration"
#define DUK_STR_CANNOT_DELETE_IDENTIFIER         "cannot delete identifier"
#define DUK_STR_INVALID_EXPRESSION               "invalid expression"
#define DUK_STR_INVALID_LVALUE                   "invalid lvalue"
#define DUK_STR_INVALID_NEWTARGET                "invalid new.target"
#define DUK_STR_EXPECTED_IDENTIFIER              "expected identifier"
#define DUK_STR_EMPTY_EXPR_NOT_ALLOWED           "empty expression not allowed"
#define DUK_STR_INVALID_FOR                      "invalid for statement"
#define DUK_STR_INVALID_SWITCH                   "invalid switch statement"
#define DUK_STR_INVALID_BREAK_CONT_LABEL         "invalid break/continue label"
#define DUK_STR_INVALID_RETURN                   "invalid return"
#define DUK_STR_INVALID_TRY                      "invalid try"
#define DUK_STR_INVALID_THROW                    "invalid throw"
#define DUK_STR_WITH_IN_STRICT_MODE              "with in strict mode"
#define DUK_STR_FUNC_STMT_NOT_ALLOWED            "function statement not allowed"
#define DUK_STR_UNTERMINATED_STMT                "unterminated statement"
#define DUK_STR_INVALID_ARG_NAME                 "invalid argument name"
#define DUK_STR_INVALID_FUNC_NAME                "invalid function name"
#define DUK_STR_INVALID_GETSET_NAME              "invalid getter/setter name"
#define DUK_STR_FUNC_NAME_REQUIRED               "function name required"

/* RegExp */
#define DUK_STR_INVALID_QUANTIFIER               "invalid regexp quantifier"
#define DUK_STR_INVALID_QUANTIFIER_NO_ATOM       "quantifier without preceding atom"
#define DUK_STR_INVALID_QUANTIFIER_VALUES        "quantifier values invalid (qmin > qmax)"
#define DUK_STR_QUANTIFIER_TOO_MANY_COPIES       "quantifier requires too many atom copies"
#define DUK_STR_UNEXPECTED_CLOSING_PAREN         "unexpected closing parenthesis"
#define DUK_STR_UNEXPECTED_END_OF_PATTERN        "unexpected end of pattern"
#define DUK_STR_UNEXPECTED_REGEXP_TOKEN          "unexpected token in regexp"
#define DUK_STR_INVALID_REGEXP_FLAGS             "invalid regexp flags"
#define DUK_STR_INVALID_REGEXP_ESCAPE            "invalid regexp escape"
#define DUK_STR_INVALID_BACKREFS                 "invalid backreference(s)"
#define DUK_STR_INVALID_REGEXP_CHARACTER         "invalid regexp character"
#define DUK_STR_INVALID_REGEXP_GROUP             "invalid regexp group"
#define DUK_STR_UNTERMINATED_CHARCLASS           "unterminated character class"
#define DUK_STR_INVALID_RANGE                    "invalid range"

/* Limits */
#define DUK_STR_VALSTACK_LIMIT                   "valstack limit"
#define DUK_STR_CALLSTACK_LIMIT                  "callstack limit"
#define DUK_STR_PROTOTYPE_CHAIN_LIMIT            "prototype chain limit"
#define DUK_STR_BOUND_CHAIN_LIMIT                "function call bound chain limit"
#define DUK_STR_NATIVE_STACK_LIMIT               "C stack depth limit"
#define DUK_STR_COMPILER_RECURSION_LIMIT         "compiler recursion limit"
#define DUK_STR_BYTECODE_LIMIT                   "bytecode limit"
#define DUK_STR_REG_LIMIT                        "register limit"
#define DUK_STR_TEMP_LIMIT                       "temp limit"
#define DUK_STR_CONST_LIMIT                      "const limit"
#define DUK_STR_FUNC_LIMIT                       "function limit"
#define DUK_STR_REGEXP_COMPILER_RECURSION_LIMIT  "regexp compiler recursion limit"
#define DUK_STR_REGEXP_EXECUTOR_RECURSION_LIMIT  "regexp executor recursion limit"
#define DUK_STR_REGEXP_EXECUTOR_STEP_LIMIT       "regexp step limit"

#endif  /* DUK_ERRMSG_H_INCLUDED */
/* #include duk_js_bytecode.h */
#line 1 "duk_js_bytecode.h"
/*
 *  ECMAScript bytecode
 */

#if !defined(DUK_JS_BYTECODE_H_INCLUDED)
#define DUK_JS_BYTECODE_H_INCLUDED

/*
 *  Bytecode instruction layout
 *  ===========================
 *
 *  Instructions are unsigned 32-bit integers divided as follows:
 *
 *  !3!3!2!2!2!2!2!2!2!2!2!2!1!1!1!1!1!1!1!1!1!1! ! ! ! ! ! ! ! ! ! !
 *  !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!
 *  +-----------------------------------------------+---------------+
 *  !       C       !       B       !       A       !       OP      !
 *  +-----------------------------------------------+---------------+
 *
 *  OP (8 bits):  opcode (DUK_OP_*), access should be fastest
 *                consecutive opcodes allocated when opcode needs flags
 *   A (8 bits):  typically a target register number
 *   B (8 bits):  typically first source register/constant number
 *   C (8 bits):  typically second source register/constant number
 *
 *  Some instructions combine BC or ABC together for larger parameter values.
 *  Signed integers (e.g. jump offsets) are encoded as unsigned, with an
 *  opcode specific bias.
 *
 *  Some opcodes have flags which are handled by allocating consecutive
 *  opcodes to make space for 1-N flags.  Flags can also be e.g. in the 'A'
 *  field when there's room for the specific opcode.
 *
 *  For example, if three flags were needed, they could be allocated from
 *  the opcode field as follows:
 *
 *  !3!3!2!2!2!2!2!2!2!2!2!2!1!1!1!1!1!1!1!1!1!1! ! ! ! ! ! ! ! ! ! !
 *  !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!
 *  +-----------------------------------------------+---------------+
 *  !       C       !       B       !       A       !    OP   !Z!Y!X!
 *  +-----------------------------------------------+---------------+
 *
 *  Some opcodes accept a reg/const argument which is handled by allocating
 *  flags in the OP field, see DUK_BC_ISREG() and DUK_BC_ISCONST().  The
 *  following convention is shared by most opcodes, so that the compiler
 *  can handle reg/const flagging without opcode specific code paths:
 *
 *  !3!3!2!2!2!2!2!2!2!2!2!2!1!1!1!1!1!1!1!1!1!1! ! ! ! ! ! ! ! ! ! !
 *  !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!
 *  +-----------------------------------------------+---------------+
 *  !       C       !       B       !       A       !     OP    !Y!X!
 *  +-----------------------------------------------+---------------+
 *
 *    X  1=B is const, 0=B is reg
 *    Y  1=C is const, 0=C is reg
 *
 *    In effect OP, OP + 1, OP + 2, and OP + 3 are allocated from the
 *    8-bit opcode space for a single logical opcode.  The base opcode
 *    number should be divisible by 4.  If the opcode is called 'FOO'
 *    the following opcode constants would be defined:
 *
 *      DUK_OP_FOO     100       // base opcode number
 *      DUK_OP_FOO_RR  100       // FOO, B=reg, C=reg
 *      DUK_OP_FOO_CR  101       // FOO, B=const, C=reg
 *      DUK_OP_FOO_RC  102       // FOO, B=reg, C=const
 *      DUK_OP_FOO_CC  103       // FOO, B=const, C=const
 *
 *  If only B or C is a reg/const, the unused opcode combinations can be
 *  used for other opcodes (which take no reg/const argument).  However,
 *  such opcode values are initially reserved, at least while opcode space
 *  is available.  For example, if 'BAR' uses B for a register field and
 *  C is a reg/const:
 *
 *      DUK_OP_BAR            116    // base opcode number
 *      DUK_OP_BAR_RR         116    // BAR, B=reg, C=reg
 *      DUK_OP_BAR_CR_UNUSED  117    // unused, could be repurposed
 *      DUK_OP_BAR_RC         118    // BAR, B=reg, C=const
 *      DUK_OP_BAR_CC_UNUSED  119    // unused, could be repurposed
 *
 *  Macro naming is a bit misleading, e.g. "ABC" in macro name but the
 *  field layout is concretely "CBA" in the register.
 */

typedef duk_uint32_t duk_instr_t;

#define DUK_BC_SHIFT_OP             0
#define DUK_BC_SHIFT_A              8
#define DUK_BC_SHIFT_B              16
#define DUK_BC_SHIFT_C              24
#define DUK_BC_SHIFT_BC             DUK_BC_SHIFT_B
#define DUK_BC_SHIFT_ABC            DUK_BC_SHIFT_A

#define DUK_BC_UNSHIFTED_MASK_OP    0xffUL
#define DUK_BC_UNSHIFTED_MASK_A     0xffUL
#define DUK_BC_UNSHIFTED_MASK_B     0xffUL
#define DUK_BC_UNSHIFTED_MASK_C     0xffUL
#define DUK_BC_UNSHIFTED_MASK_BC    0xffffUL
#define DUK_BC_UNSHIFTED_MASK_ABC   0xffffffUL

#define DUK_BC_SHIFTED_MASK_OP      (DUK_BC_UNSHIFTED_MASK_OP << DUK_BC_SHIFT_OP)
#define DUK_BC_SHIFTED_MASK_A       (DUK_BC_UNSHIFTED_MASK_A << DUK_BC_SHIFT_A)
#define DUK_BC_SHIFTED_MASK_B       (DUK_BC_UNSHIFTED_MASK_B << DUK_BC_SHIFT_B)
#define DUK_BC_SHIFTED_MASK_C       (DUK_BC_UNSHIFTED_MASK_C << DUK_BC_SHIFT_C)
#define DUK_BC_SHIFTED_MASK_BC      (DUK_BC_UNSHIFTED_MASK_BC << DUK_BC_SHIFT_BC)
#define DUK_BC_SHIFTED_MASK_ABC     (DUK_BC_UNSHIFTED_MASK_ABC << DUK_BC_SHIFT_ABC)

#define DUK_DEC_OP(x)               ((x) & 0xffUL)
#define DUK_DEC_A(x)                (((x) >> 8) & 0xffUL)
#define DUK_DEC_B(x)                (((x) >> 16) & 0xffUL)
#define DUK_DEC_C(x)                (((x) >> 24) & 0xffUL)
#define DUK_DEC_BC(x)               (((x) >> 16) & 0xffffUL)
#define DUK_DEC_ABC(x)              (((x) >> 8) & 0xffffffUL)

#define DUK_ENC_OP(op)              ((duk_instr_t) (op))
#define DUK_ENC_OP_ABC(op,abc)      ((duk_instr_t) ( \
                                        (((duk_instr_t) (abc)) << 8) | \
                                        ((duk_instr_t) (op)) \
                                    ))
#define DUK_ENC_OP_A_BC(op,a,bc)    ((duk_instr_t) ( \
                                        (((duk_instr_t) (bc)) << 16) | \
                                        (((duk_instr_t) (a)) << 8) | \
                                        ((duk_instr_t) (op)) \
                                    ))
#define DUK_ENC_OP_A_B_C(op,a,b,c)  ((duk_instr_t) ( \
                                        (((duk_instr_t) (c)) << 24) | \
                                        (((duk_instr_t) (b)) << 16) | \
                                        (((duk_instr_t) (a)) << 8) | \
                                        ((duk_instr_t) (op)) \
                                    ))
#define DUK_ENC_OP_A_B(op,a,b)      DUK_ENC_OP_A_B_C((op),(a),(b),0)
#define DUK_ENC_OP_A(op,a)          DUK_ENC_OP_A_B_C((op),(a),0,0)
#define DUK_ENC_OP_BC(op,bc)        DUK_ENC_OP_A_BC((op),0,(bc))

/* Get opcode base value with B/C reg/const flags cleared. */
#define DUK_BC_NOREGCONST_OP(op)    ((op) & 0xfc)

/* Constants should be signed so that signed arithmetic involving them
 * won't cause values to be coerced accidentally to unsigned.
 */
#define DUK_BC_OP_MIN               0
#define DUK_BC_OP_MAX               0xffL
#define DUK_BC_A_MIN                0
#define DUK_BC_A_MAX                0xffL
#define DUK_BC_B_MIN                0
#define DUK_BC_B_MAX                0xffL
#define DUK_BC_C_MIN                0
#define DUK_BC_C_MAX                0xffL
#define DUK_BC_BC_MIN               0
#define DUK_BC_BC_MAX               0xffffL
#define DUK_BC_ABC_MIN              0
#define DUK_BC_ABC_MAX              0xffffffL

/* Masks for B/C reg/const indicator in opcode field. */
#define DUK_BC_REGCONST_B           (0x01UL)
#define DUK_BC_REGCONST_C           (0x02UL)

/* Misc. masks for opcode field. */
#define DUK_BC_INCDECP_FLAG_DEC     (0x04UL)
#define DUK_BC_INCDECP_FLAG_POST    (0x08UL)

/* Opcodes. */
#define DUK_OP_LDREG                0
#define DUK_OP_STREG                1
#define DUK_OP_JUMP                 2
#define DUK_OP_LDCONST              3
#define DUK_OP_LDINT                4
#define DUK_OP_LDINTX               5
#define DUK_OP_LDTHIS               6
#define DUK_OP_LDUNDEF              7
#define DUK_OP_LDNULL               8
#define DUK_OP_LDTRUE               9
#define DUK_OP_LDFALSE              10
#define DUK_OP_GETVAR               11
#define DUK_OP_BNOT                 12
#define DUK_OP_LNOT                 13
#define DUK_OP_UNM                  14
#define DUK_OP_UNP                  15
#define DUK_OP_EQ                   16
#define DUK_OP_EQ_RR                16
#define DUK_OP_EQ_CR                17
#define DUK_OP_EQ_RC                18
#define DUK_OP_EQ_CC                19
#define DUK_OP_NEQ                  20
#define DUK_OP_NEQ_RR               20
#define DUK_OP_NEQ_CR               21
#define DUK_OP_NEQ_RC               22
#define DUK_OP_NEQ_CC               23
#define DUK_OP_SEQ                  24
#define DUK_OP_SEQ_RR               24
#define DUK_OP_SEQ_CR               25
#define DUK_OP_SEQ_RC               26
#define DUK_OP_SEQ_CC               27
#define DUK_OP_SNEQ                 28
#define DUK_OP_SNEQ_RR              28
#define DUK_OP_SNEQ_CR              29
#define DUK_OP_SNEQ_RC              30
#define DUK_OP_SNEQ_CC              31
#define DUK_OP_GT                   32
#define DUK_OP_GT_RR                32
#define DUK_OP_GT_CR                33
#define DUK_OP_GT_RC                34
#define DUK_OP_GT_CC                35
#define DUK_OP_GE                   36
#define DUK_OP_GE_RR                36
#define DUK_OP_GE_CR                37
#define DUK_OP_GE_RC                38
#define DUK_OP_GE_CC                39
#define DUK_OP_LT                   40
#define DUK_OP_LT_RR                40
#define DUK_OP_LT_CR                41
#define DUK_OP_LT_RC                42
#define DUK_OP_LT_CC                43
#define DUK_OP_LE                   44
#define DUK_OP_LE_RR                44
#define DUK_OP_LE_CR                45
#define DUK_OP_LE_RC                46
#define DUK_OP_LE_CC                47
#define DUK_OP_IFTRUE               48
#define DUK_OP_IFTRUE_R             48
#define DUK_OP_IFTRUE_C             49
#define DUK_OP_IFFALSE              50
#define DUK_OP_IFFALSE_R            50
#define DUK_OP_IFFALSE_C            51
#define DUK_OP_ADD                  52
#define DUK_OP_ADD_RR               52
#define DUK_OP_ADD_CR               53
#define DUK_OP_ADD_RC               54
#define DUK_OP_ADD_CC               55
#define DUK_OP_SUB                  56
#define DUK_OP_SUB_RR               56
#define DUK_OP_SUB_CR               57
#define DUK_OP_SUB_RC               58
#define DUK_OP_SUB_CC               59
#define DUK_OP_MUL                  60
#define DUK_OP_MUL_RR               60
#define DUK_OP_MUL_CR               61
#define DUK_OP_MUL_RC               62
#define DUK_OP_MUL_CC               63
#define DUK_OP_DIV                  64
#define DUK_OP_DIV_RR               64
#define DUK_OP_DIV_CR               65
#define DUK_OP_DIV_RC               66
#define DUK_OP_DIV_CC               67
#define DUK_OP_MOD                  68
#define DUK_OP_MOD_RR               68
#define DUK_OP_MOD_CR               69
#define DUK_OP_MOD_RC               70
#define DUK_OP_MOD_CC               71
#define DUK_OP_EXP                  72
#define DUK_OP_EXP_RR               72
#define DUK_OP_EXP_CR               73
#define DUK_OP_EXP_RC               74
#define DUK_OP_EXP_CC               75
#define DUK_OP_BAND                 76
#define DUK_OP_BAND_RR              76
#define DUK_OP_BAND_CR              77
#define DUK_OP_BAND_RC              78
#define DUK_OP_BAND_CC              79
#define DUK_OP_BOR                  80
#define DUK_OP_BOR_RR               80
#define DUK_OP_BOR_CR               81
#define DUK_OP_BOR_RC               82
#define DUK_OP_BOR_CC               83
#define DUK_OP_BXOR                 84
#define DUK_OP_BXOR_RR              84
#define DUK_OP_BXOR_CR              85
#define DUK_OP_BXOR_RC              86
#define DUK_OP_BXOR_CC              87
#define DUK_OP_BASL                 88
#define DUK_OP_BASL_RR              88
#define DUK_OP_BASL_CR              89
#define DUK_OP_BASL_RC              90
#define DUK_OP_BASL_CC              91
#define DUK_OP_BLSR                 92
#define DUK_OP_BLSR_RR              92
#define DUK_OP_BLSR_CR              93
#define DUK_OP_BLSR_RC              94
#define DUK_OP_BLSR_CC              95
#define DUK_OP_BASR                 96
#define DUK_OP_BASR_RR              96
#define DUK_OP_BASR_CR              97
#define DUK_OP_BASR_RC              98
#define DUK_OP_BASR_CC              99
#define DUK_OP_INSTOF               100
#define DUK_OP_INSTOF_RR            100
#define DUK_OP_INSTOF_CR            101
#define DUK_OP_INSTOF_RC            102
#define DUK_OP_INSTOF_CC            103
#define DUK_OP_IN                   104
#define DUK_OP_IN_RR                104
#define DUK_OP_IN_CR                105
#define DUK_OP_IN_RC                106
#define DUK_OP_IN_CC                107
#define DUK_OP_GETPROP              108
#define DUK_OP_GETPROP_RR           108
#define DUK_OP_GETPROP_CR           109
#define DUK_OP_GETPROP_RC           110
#define DUK_OP_GETPROP_CC           111
#define DUK_OP_PUTPROP              112
#define DUK_OP_PUTPROP_RR           112
#define DUK_OP_PUTPROP_CR           113
#define DUK_OP_PUTPROP_RC           114
#define DUK_OP_PUTPROP_CC           115
#define DUK_OP_DELPROP              116
#define DUK_OP_DELPROP_RR           116
#define DUK_OP_DELPROP_CR_UNUSED    117  /* unused now */
#define DUK_OP_DELPROP_RC           118
#define DUK_OP_DELPROP_CC_UNUSED    119  /* unused now */
#define DUK_OP_PREINCR              120  /* pre/post opcode values have constraints, */
#define DUK_OP_PREDECR              121  /* see duk_js_executor.c and duk_js_compiler.c. */
#define DUK_OP_POSTINCR             122
#define DUK_OP_POSTDECR             123
#define DUK_OP_PREINCV              124
#define DUK_OP_PREDECV              125
#define DUK_OP_POSTINCV             126
#define DUK_OP_POSTDECV             127
#define DUK_OP_PREINCP              128  /* pre/post inc/dec prop opcodes have constraints */
#define DUK_OP_PREINCP_RR           128
#define DUK_OP_PREINCP_CR           129
#define DUK_OP_PREINCP_RC           130
#define DUK_OP_PREINCP_CC           131
#define DUK_OP_PREDECP              132
#define DUK_OP_PREDECP_RR           132
#define DUK_OP_PREDECP_CR           133
#define DUK_OP_PREDECP_RC           134
#define DUK_OP_PREDECP_CC           135
#define DUK_OP_POSTINCP             136
#define DUK_OP_POSTINCP_RR          136
#define DUK_OP_POSTINCP_CR          137
#define DUK_OP_POSTINCP_RC          138
#define DUK_OP_POSTINCP_CC          139
#define DUK_OP_POSTDECP             140
#define DUK_OP_POSTDECP_RR          140
#define DUK_OP_POSTDECP_CR          141
#define DUK_OP_POSTDECP_RC          142
#define DUK_OP_POSTDECP_CC          143
#define DUK_OP_DECLVAR              144
#define DUK_OP_DECLVAR_RR           144
#define DUK_OP_DECLVAR_CR           145
#define DUK_OP_DECLVAR_RC           146
#define DUK_OP_DECLVAR_CC           147
#define DUK_OP_REGEXP               148
#define DUK_OP_REGEXP_RR            148
#define DUK_OP_REGEXP_CR            149
#define DUK_OP_REGEXP_RC            150
#define DUK_OP_REGEXP_CC            151
#define DUK_OP_CLOSURE              152
#define DUK_OP_TYPEOF               153
#define DUK_OP_TYPEOFID             154
#define DUK_OP_PUTVAR               155
#define DUK_OP_DELVAR               156
#define DUK_OP_RETREG               157
#define DUK_OP_RETUNDEF             158
#define DUK_OP_RETCONST             159
#define DUK_OP_RETCONSTN            160  /* return const without incref (e.g. number) */
#define DUK_OP_LABEL                161
#define DUK_OP_ENDLABEL             162
#define DUK_OP_BREAK                163
#define DUK_OP_CONTINUE             164
#define DUK_OP_TRYCATCH             165
#define DUK_OP_ENDTRY               166
#define DUK_OP_ENDCATCH             167
#define DUK_OP_ENDFIN               168
#define DUK_OP_THROW                169
#define DUK_OP_INVLHS               170
#define DUK_OP_CSREG                171
#define DUK_OP_CSVAR                172
#define DUK_OP_CSVAR_RR             172
#define DUK_OP_CSVAR_CR             173
#define DUK_OP_CSVAR_RC             174
#define DUK_OP_CSVAR_CC             175
#define DUK_OP_CALL0                176  /* DUK_OP_CALL0 & 0x0F must be zero. */
#define DUK_OP_CALL1                177
#define DUK_OP_CALL2                178
#define DUK_OP_CALL3                179
#define DUK_OP_CALL4                180
#define DUK_OP_CALL5                181
#define DUK_OP_CALL6                182
#define DUK_OP_CALL7                183
#define DUK_OP_CALL8                184
#define DUK_OP_CALL9                185
#define DUK_OP_CALL10               186
#define DUK_OP_CALL11               187
#define DUK_OP_CALL12               188
#define DUK_OP_CALL13               189
#define DUK_OP_CALL14               190
#define DUK_OP_CALL15               191
#define DUK_OP_NEWOBJ               192
#define DUK_OP_NEWARR               193
#define DUK_OP_MPUTOBJ              194
#define DUK_OP_MPUTOBJI             195
#define DUK_OP_INITSET              196
#define DUK_OP_INITGET              197
#define DUK_OP_MPUTARR              198
#define DUK_OP_MPUTARRI             199
#define DUK_OP_SETALEN              200
#define DUK_OP_INITENUM             201
#define DUK_OP_NEXTENUM             202
#define DUK_OP_NEWTARGET            203
#define DUK_OP_DEBUGGER             204
#define DUK_OP_NOP                  205
#define DUK_OP_INVALID              206
#define DUK_OP_UNUSED207            207
#define DUK_OP_GETPROPC             208
#define DUK_OP_GETPROPC_RR          208
#define DUK_OP_GETPROPC_CR          209
#define DUK_OP_GETPROPC_RC          210
#define DUK_OP_GETPROPC_CC          211
#define DUK_OP_UNUSED212            212
#define DUK_OP_UNUSED213            213
#define DUK_OP_UNUSED214            214
#define DUK_OP_UNUSED215            215
#define DUK_OP_UNUSED216            216
#define DUK_OP_UNUSED217            217
#define DUK_OP_UNUSED218            218
#define DUK_OP_UNUSED219            219
#define DUK_OP_UNUSED220            220
#define DUK_OP_UNUSED221            221
#define DUK_OP_UNUSED222            222
#define DUK_OP_UNUSED223            223
#define DUK_OP_UNUSED224            224
#define DUK_OP_UNUSED225            225
#define DUK_OP_UNUSED226            226
#define DUK_OP_UNUSED227            227
#define DUK_OP_UNUSED228            228
#define DUK_OP_UNUSED229            229
#define DUK_OP_UNUSED230            230
#define DUK_OP_UNUSED231            231
#define DUK_OP_UNUSED232            232
#define DUK_OP_UNUSED233            233
#define DUK_OP_UNUSED234            234
#define DUK_OP_UNUSED235            235
#define DUK_OP_UNUSED236            236
#define DUK_OP_UNUSED237            237
#define DUK_OP_UNUSED238            238
#define DUK_OP_UNUSED239            239
#define DUK_OP_UNUSED240            240
#define DUK_OP_UNUSED241            241
#define DUK_OP_UNUSED242            242
#define DUK_OP_UNUSED243            243
#define DUK_OP_UNUSED244            244
#define DUK_OP_UNUSED245            245
#define DUK_OP_UNUSED246            246
#define DUK_OP_UNUSED247            247
#define DUK_OP_UNUSED248            248
#define DUK_OP_UNUSED249            249
#define DUK_OP_UNUSED250            250
#define DUK_OP_UNUSED251            251
#define DUK_OP_UNUSED252            252
#define DUK_OP_UNUSED253            253
#define DUK_OP_UNUSED254            254
#define DUK_OP_UNUSED255            255
#define DUK_OP_NONE                 256  /* dummy value used as marker (doesn't fit in 8-bit field) */

/* XXX: Allocate flags from opcode field?  Would take 16 opcode slots
 * but avoids shuffling in more cases.  Maybe not worth it.
 */
/* DUK_OP_TRYCATCH flags in A. */
#define DUK_BC_TRYCATCH_FLAG_HAVE_CATCH     (1U << 0)
#define DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY   (1U << 1)
#define DUK_BC_TRYCATCH_FLAG_CATCH_BINDING  (1U << 2)
#define DUK_BC_TRYCATCH_FLAG_WITH_BINDING   (1U << 3)

/* DUK_OP_DECLVAR flags in A; bottom bits are reserved for propdesc flags
 * (DUK_PROPDESC_FLAG_XXX).
 */
#define DUK_BC_DECLVAR_FLAG_FUNC_DECL       (1U << 4)  /* function declaration */

/* DUK_OP_CALLn flags, part of opcode field.  Three lowest bits must match
 * DUK_CALL_FLAG_xxx directly.
 */
#define DUK_BC_CALL_FLAG_TAILCALL           (1U << 0)
#define DUK_BC_CALL_FLAG_CONSTRUCT          (1U << 1)
#define DUK_BC_CALL_FLAG_CALLED_AS_EVAL     (1U << 2)
#define DUK_BC_CALL_FLAG_INDIRECT           (1U << 3)

/* Misc constants and helper macros. */
#define DUK_BC_LDINT_BIAS           (1L << 15)
#define DUK_BC_LDINTX_SHIFT         16
#define DUK_BC_JUMP_BIAS            (1L << 23)

#endif  /* DUK_JS_BYTECODE_H_INCLUDED */
/* #include duk_lexer.h */
#line 1 "duk_lexer.h"
/*
 *  Lexer defines.
 */

#if !defined(DUK_LEXER_H_INCLUDED)
#define DUK_LEXER_H_INCLUDED

typedef void (*duk_re_range_callback)(void *user, duk_codepoint_t r1, duk_codepoint_t r2, duk_bool_t direct);

/*
 *  A token is interpreted as any possible production of InputElementDiv
 *  and InputElementRegExp, see E5 Section 7 in its entirety.  Note that
 *  the E5 "Token" production does not cover all actual tokens of the
 *  language (which is explicitly stated in the specification, Section 7.5).
 *  Null and boolean literals are defined as part of both ReservedWord
 *  (E5 Section 7.6.1) and Literal (E5 Section 7.8) productions.  Here,
 *  null and boolean values have literal tokens, and are not reserved
 *  words.
 *
 *  Decimal literal negative/positive sign is -not- part of DUK_TOK_NUMBER.
 *  The number tokens always have a non-negative value.  The unary minus
 *  operator in "-1.0" is optimized during compilation to yield a single
 *  negative constant.
 *
 *  Token numbering is free except that reserved words are required to be
 *  in a continuous range and in a particular order.  See genstrings.py.
 */

#define DUK_LEXER_INITCTX(ctx)        duk_lexer_initctx((ctx))

#define DUK_LEXER_SETPOINT(ctx,pt)    duk_lexer_setpoint((ctx), (pt))

#define DUK_LEXER_GETPOINT(ctx,pt)    duk_lexer_getpoint((ctx), (pt))

/* Currently 6 characters of lookup are actually needed (duk_lexer.c). */
#define DUK_LEXER_WINDOW_SIZE                     6
#if defined(DUK_USE_LEXER_SLIDING_WINDOW)
#define DUK_LEXER_BUFFER_SIZE                     64
#endif

#define DUK_TOK_MINVAL                            0

/* returned after EOF (infinite amount) */
#define DUK_TOK_EOF                               0

/* identifier names (E5 Section 7.6) */
#define DUK_TOK_IDENTIFIER                        1

/* reserved words: keywords */
#define DUK_TOK_START_RESERVED                    2
#define DUK_TOK_BREAK                             2
#define DUK_TOK_CASE                              3
#define DUK_TOK_CATCH                             4
#define DUK_TOK_CONTINUE                          5
#define DUK_TOK_DEBUGGER                          6
#define DUK_TOK_DEFAULT                           7
#define DUK_TOK_DELETE                            8
#define DUK_TOK_DO                                9
#define DUK_TOK_ELSE                              10
#define DUK_TOK_FINALLY                           11
#define DUK_TOK_FOR                               12
#define DUK_TOK_FUNCTION                          13
#define DUK_TOK_IF                                14
#define DUK_TOK_IN                                15
#define DUK_TOK_INSTANCEOF                        16
#define DUK_TOK_NEW                               17
#define DUK_TOK_RETURN                            18
#define DUK_TOK_SWITCH                            19
#define DUK_TOK_THIS                              20
#define DUK_TOK_THROW                             21
#define DUK_TOK_TRY                               22
#define DUK_TOK_TYPEOF                            23
#define DUK_TOK_VAR                               24
#define DUK_TOK_CONST                             25
#define DUK_TOK_VOID                              26
#define DUK_TOK_WHILE                             27
#define DUK_TOK_WITH                              28

/* reserved words: future reserved words */
#define DUK_TOK_CLASS                             29
#define DUK_TOK_ENUM                              30
#define DUK_TOK_EXPORT                            31
#define DUK_TOK_EXTENDS                           32
#define DUK_TOK_IMPORT                            33
#define DUK_TOK_SUPER                             34

/* "null", "true", and "false" are always reserved words.
 * Note that "get" and "set" are not!
 */
#define DUK_TOK_NULL                              35
#define DUK_TOK_TRUE                              36
#define DUK_TOK_FALSE                             37

/* reserved words: additional future reserved words in strict mode */
#define DUK_TOK_START_STRICT_RESERVED             38  /* inclusive */
#define DUK_TOK_IMPLEMENTS                        38
#define DUK_TOK_INTERFACE                         39
#define DUK_TOK_LET                               40
#define DUK_TOK_PACKAGE                           41
#define DUK_TOK_PRIVATE                           42
#define DUK_TOK_PROTECTED                         43
#define DUK_TOK_PUBLIC                            44
#define DUK_TOK_STATIC                            45
#define DUK_TOK_YIELD                             46

#define DUK_TOK_END_RESERVED                      47  /* exclusive */

/* "get" and "set" are tokens but NOT ReservedWords.  They are currently
 * parsed and identifiers and these defines are actually now unused.
 */
#define DUK_TOK_GET                               47
#define DUK_TOK_SET                               48

/* punctuators (unlike the spec, also includes "/" and "/=") */
#define DUK_TOK_LCURLY                            49
#define DUK_TOK_RCURLY                            50
#define DUK_TOK_LBRACKET                          51
#define DUK_TOK_RBRACKET                          52
#define DUK_TOK_LPAREN                            53
#define DUK_TOK_RPAREN                            54
#define DUK_TOK_PERIOD                            55
#define DUK_TOK_SEMICOLON                         56
#define DUK_TOK_COMMA                             57
#define DUK_TOK_LT                                58
#define DUK_TOK_GT                                59
#define DUK_TOK_LE                                60
#define DUK_TOK_GE                                61
#define DUK_TOK_EQ                                62
#define DUK_TOK_NEQ                               63
#define DUK_TOK_SEQ                               64
#define DUK_TOK_SNEQ                              65
#define DUK_TOK_ADD                               66
#define DUK_TOK_SUB                               67
#define DUK_TOK_MUL                               68
#define DUK_TOK_DIV                               69
#define DUK_TOK_MOD                               70
#define DUK_TOK_EXP                               71
#define DUK_TOK_INCREMENT                         72
#define DUK_TOK_DECREMENT                         73
#define DUK_TOK_ALSHIFT                           74   /* named "arithmetic" because result is signed */
#define DUK_TOK_ARSHIFT                           75
#define DUK_TOK_RSHIFT                            76
#define DUK_TOK_BAND                              77
#define DUK_TOK_BOR                               78
#define DUK_TOK_BXOR                              79
#define DUK_TOK_LNOT                              80
#define DUK_TOK_BNOT                              81
#define DUK_TOK_LAND                              82
#define DUK_TOK_LOR                               83
#define DUK_TOK_QUESTION                          84
#define DUK_TOK_COLON                             85
#define DUK_TOK_EQUALSIGN                         86
#define DUK_TOK_ADD_EQ                            87
#define DUK_TOK_SUB_EQ                            88
#define DUK_TOK_MUL_EQ                            89
#define DUK_TOK_DIV_EQ                            90
#define DUK_TOK_MOD_EQ                            91
#define DUK_TOK_EXP_EQ                            92
#define DUK_TOK_ALSHIFT_EQ                        93
#define DUK_TOK_ARSHIFT_EQ                        94
#define DUK_TOK_RSHIFT_EQ                         95
#define DUK_TOK_BAND_EQ                           96
#define DUK_TOK_BOR_EQ                            97
#define DUK_TOK_BXOR_EQ                           98

/* literals (E5 Section 7.8), except null, true, false, which are treated
 * like reserved words (above).
 */
#define DUK_TOK_NUMBER                            99
#define DUK_TOK_STRING                            100
#define DUK_TOK_REGEXP                            101

#define DUK_TOK_MAXVAL                            101  /* inclusive */

#define DUK_TOK_INVALID                           DUK_SMALL_UINT_MAX

/* Convert heap string index to a token (reserved words) */
#define DUK_STRIDX_TO_TOK(x)                        ((x) - DUK_STRIDX_START_RESERVED + DUK_TOK_START_RESERVED)

/* Sanity check */
#if (DUK_TOK_MAXVAL > 255)
#error DUK_TOK_MAXVAL too large, code assumes it fits into 8 bits
#endif

/* Sanity checks for string and token defines */
#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_BREAK) != DUK_TOK_BREAK)
#error mismatch in token defines
#endif
#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CASE) != DUK_TOK_CASE)
#error mismatch in token defines
#endif
#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CATCH) != DUK_TOK_CATCH)
#error mismatch in token defines
#endif
#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CONTINUE) != DUK_TOK_CONTINUE)
#error mismatch in token defines
#endif
#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_DEBUGGER) != DUK_TOK_DEBUGGER)
#error mismatch in token defines
#endif
#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_DEFAULT) != DUK_TOK_DEFAULT)
#error mismatch in token defines
#endif
#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_DELETE) != DUK_TOK_DELETE)
#error mismatch in token defines
#endif
#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_DO) != DUK_TOK_DO)
#error mismatch in token defines
#endif
#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_ELSE) != DUK_TOK_ELSE)
#error mismatch in token defines
#endif
#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_FINALLY) != DUK_TOK_FINALLY)
#error mismatch in token defines
#endif
#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_FOR) != DUK_TOK_FOR)
#error mismatch in token defines
#endif
#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_LC_FUNCTION) != DUK_TOK_FUNCTION)
#error mismatch in token defines
#endif
#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_IF) != DUK_TOK_IF)
#error mismatch in token defines
#endif
#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_IN) != DUK_TOK_IN)
#error mismatch in token defines
#endif
#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_INSTANCEOF) != DUK_TOK_INSTANCEOF)
#error mismatch in token defines
#endif
#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_NEW) != DUK_TOK_NEW)
#error mismatch in token defines
#endif
#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_RETURN) != DUK_TOK_RETURN)
#error mismatch in token defines
#endif
#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_SWITCH) != DUK_TOK_SWITCH)
#error mismatch in token defines
#endif
#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_THIS) != DUK_TOK_THIS)
#error mismatch in token defines
#endif
#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_THROW) != DUK_TOK_THROW)
#error mismatch in token defines
#endif
#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_TRY) != DUK_TOK_TRY)
#error mismatch in token defines
#endif
#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_TYPEOF) != DUK_TOK_TYPEOF)
#error mismatch in token defines
#endif
#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_VAR) != DUK_TOK_VAR)
#error mismatch in token defines
#endif
#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_VOID) != DUK_TOK_VOID)
#error mismatch in token defines
#endif
#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_WHILE) != DUK_TOK_WHILE)
#error mismatch in token defines
#endif
#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_WITH) != DUK_TOK_WITH)
#error mismatch in token defines
#endif
#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CLASS) != DUK_TOK_CLASS)
#error mismatch in token defines
#endif
#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CONST) != DUK_TOK_CONST)
#error mismatch in token defines
#endif
#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_ENUM) != DUK_TOK_ENUM)
#error mismatch in token defines
#endif
#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_EXPORT) != DUK_TOK_EXPORT)
#error mismatch in token defines
#endif
#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_EXTENDS) != DUK_TOK_EXTENDS)
#error mismatch in token defines
#endif
#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_IMPORT) != DUK_TOK_IMPORT)
#error mismatch in token defines
#endif
#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_SUPER) != DUK_TOK_SUPER)
#error mismatch in token defines
#endif
#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_LC_NULL) != DUK_TOK_NULL)
#error mismatch in token defines
#endif
#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_TRUE) != DUK_TOK_TRUE)
#error mismatch in token defines
#endif
#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_FALSE) != DUK_TOK_FALSE)
#error mismatch in token defines
#endif
#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_IMPLEMENTS) != DUK_TOK_IMPLEMENTS)
#error mismatch in token defines
#endif
#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_INTERFACE) != DUK_TOK_INTERFACE)
#error mismatch in token defines
#endif
#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_LET) != DUK_TOK_LET)
#error mismatch in token defines
#endif
#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_PACKAGE) != DUK_TOK_PACKAGE)
#error mismatch in token defines
#endif
#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_PRIVATE) != DUK_TOK_PRIVATE)
#error mismatch in token defines
#endif
#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_PROTECTED) != DUK_TOK_PROTECTED)
#error mismatch in token defines
#endif
#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_PUBLIC) != DUK_TOK_PUBLIC)
#error mismatch in token defines
#endif
#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_STATIC) != DUK_TOK_STATIC)
#error mismatch in token defines
#endif
#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_YIELD) != DUK_TOK_YIELD)
#error mismatch in token defines
#endif

/* Regexp tokens */
#define DUK_RETOK_EOF                              0
#define DUK_RETOK_DISJUNCTION                      1
#define DUK_RETOK_QUANTIFIER                       2
#define DUK_RETOK_ASSERT_START                     3
#define DUK_RETOK_ASSERT_END                       4
#define DUK_RETOK_ASSERT_WORD_BOUNDARY             5
#define DUK_RETOK_ASSERT_NOT_WORD_BOUNDARY         6
#define DUK_RETOK_ASSERT_START_POS_LOOKAHEAD       7
#define DUK_RETOK_ASSERT_START_NEG_LOOKAHEAD       8
#define DUK_RETOK_ATOM_PERIOD                      9
#define DUK_RETOK_ATOM_CHAR                        10
#define DUK_RETOK_ATOM_DIGIT                       11  /* assumptions in regexp compiler */
#define DUK_RETOK_ATOM_NOT_DIGIT                   12  /* -""- */
#define DUK_RETOK_ATOM_WHITE                       13  /* -""- */
#define DUK_RETOK_ATOM_NOT_WHITE                   14  /* -""- */
#define DUK_RETOK_ATOM_WORD_CHAR                   15  /* -""- */
#define DUK_RETOK_ATOM_NOT_WORD_CHAR               16  /* -""- */
#define DUK_RETOK_ATOM_BACKREFERENCE               17
#define DUK_RETOK_ATOM_START_CAPTURE_GROUP         18
#define DUK_RETOK_ATOM_START_NONCAPTURE_GROUP      19
#define DUK_RETOK_ATOM_START_CHARCLASS             20
#define DUK_RETOK_ATOM_START_CHARCLASS_INVERTED    21
#define DUK_RETOK_ATOM_END_GROUP                   22

/* Constants for duk_lexer_ctx.buf. */
#define DUK_LEXER_TEMP_BUF_LIMIT                   256

/* A token value.  Can be memcpy()'d, but note that slot1/slot2 values are on the valstack.
 * Some fields (like num, str1, str2) are only valid for specific token types and may have
 * stale values otherwise.
 */
struct duk_token {
	duk_small_uint_t t;           /* token type (with reserved word identification) */
	duk_small_uint_t t_nores;     /* token type (with reserved words as DUK_TOK_IDENTIFER) */
	duk_double_t num;             /* numeric value of token */
	duk_hstring *str1;            /* string 1 of token (borrowed, stored to ctx->slot1_idx) */
	duk_hstring *str2;            /* string 2 of token (borrowed, stored to ctx->slot2_idx) */
	duk_size_t start_offset;      /* start byte offset of token in lexer input */
	duk_int_t start_line;         /* start line of token (first char) */
	duk_int_t num_escapes;        /* number of escapes and line continuations (for directive prologue) */
	duk_bool_t lineterm;          /* token was preceded by a lineterm */
	duk_bool_t allow_auto_semi;   /* token allows automatic semicolon insertion (eof or preceded by newline) */
};

#define DUK_RE_QUANTIFIER_INFINITE         ((duk_uint32_t) 0xffffffffUL)

/* A regexp token value. */
struct duk_re_token {
	duk_small_uint_t t;          /* token type */
	duk_small_uint_t greedy;
	duk_uint32_t num;            /* numeric value (character, count) */
	duk_uint32_t qmin;
	duk_uint32_t qmax;
};

/* A structure for 'snapshotting' a point for rewinding */
struct duk_lexer_point {
	duk_size_t offset;
	duk_int_t line;
};

/* Lexer codepoint with additional info like offset/line number */
struct duk_lexer_codepoint {
	duk_codepoint_t codepoint;
	duk_size_t offset;
	duk_int_t line;
};

/* Lexer context.  Same context is used for ECMAScript and Regexp parsing. */
struct duk_lexer_ctx {
#if defined(DUK_USE_LEXER_SLIDING_WINDOW)
	duk_lexer_codepoint *window; /* unicode code points, window[0] is always next, points to 'buffer' */
	duk_lexer_codepoint buffer[DUK_LEXER_BUFFER_SIZE];
#else
	duk_lexer_codepoint window[DUK_LEXER_WINDOW_SIZE]; /* unicode code points, window[0] is always next */
#endif

	duk_hthread *thr;                              /* thread; minimizes argument passing */

	const duk_uint8_t *input;                      /* input string (may be a user pointer) */
	duk_size_t input_length;                       /* input byte length */
	duk_size_t input_offset;                       /* input offset for window leading edge (not window[0]) */
	duk_int_t input_line;                          /* input linenumber at input_offset (not window[0]), init to 1 */

	duk_idx_t slot1_idx;                           /* valstack slot for 1st token value */
	duk_idx_t slot2_idx;                           /* valstack slot for 2nd token value */
	duk_idx_t buf_idx;                             /* valstack slot for temp buffer */
	duk_hbuffer_dynamic *buf;                      /* temp accumulation buffer */
	duk_bufwriter_ctx bw;                          /* bufwriter for temp accumulation */

	duk_int_t token_count;                         /* number of tokens parsed */
	duk_int_t token_limit;                         /* maximum token count before error (sanity backstop) */

	duk_small_uint_t flags;                        /* lexer flags, use compiler flag defines for now */
};

/*
 *  Prototypes
 */

DUK_INTERNAL_DECL void duk_lexer_initctx(duk_lexer_ctx *lex_ctx);

DUK_INTERNAL_DECL void duk_lexer_getpoint(duk_lexer_ctx *lex_ctx, duk_lexer_point *pt);
DUK_INTERNAL_DECL void duk_lexer_setpoint(duk_lexer_ctx *lex_ctx, duk_lexer_point *pt);

DUK_INTERNAL_DECL
void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx,
                                      duk_token *out_token,
                                      duk_bool_t strict_mode,
                                      duk_bool_t regexp_mode);
#if defined(DUK_USE_REGEXP_SUPPORT)
DUK_INTERNAL_DECL void duk_lexer_parse_re_token(duk_lexer_ctx *lex_ctx, duk_re_token *out_token);
DUK_INTERNAL_DECL void duk_lexer_parse_re_ranges(duk_lexer_ctx *lex_ctx, duk_re_range_callback gen_range, void *userdata);
#endif  /* DUK_USE_REGEXP_SUPPORT */

#endif  /* DUK_LEXER_H_INCLUDED */
/* #include duk_js_compiler.h */
#line 1 "duk_js_compiler.h"
/*
 *  ECMAScript compiler.
 */

#if !defined(DUK_JS_COMPILER_H_INCLUDED)
#define DUK_JS_COMPILER_H_INCLUDED

/* ECMAScript compiler limits */
#define DUK_COMPILER_TOKEN_LIMIT           100000000L  /* 1e8: protects against deeply nested inner functions */

/* maximum loopcount for peephole optimization */
#define DUK_COMPILER_PEEPHOLE_MAXITER      3

/* maximum bytecode length in instructions */
#define DUK_COMPILER_MAX_BYTECODE_LENGTH   (256L * 1024L * 1024L)  /* 1 GB */

/*
 *  Compiler intermediate values
 *
 *  Intermediate values describe either plain values (e.g. strings or
 *  numbers) or binary operations which have not yet been coerced into
 *  either a left-hand-side or right-hand-side role (e.g. object property).
 */

#define DUK_IVAL_NONE          0   /* no value */
#define DUK_IVAL_PLAIN         1   /* register, constant, or value */
#define DUK_IVAL_ARITH         2   /* binary arithmetic; DUK_OP_ADD, DUK_OP_EQ, other binary ops */
#define DUK_IVAL_PROP          3   /* property access */
#define DUK_IVAL_VAR           4   /* variable access */

#define DUK_ISPEC_NONE         0   /* no value */
#define DUK_ISPEC_VALUE        1   /* value resides in 'valstack_idx' */
#define DUK_ISPEC_REGCONST     2   /* value resides in a register or constant */

/* Bit mask which indicates that a regconst is a constant instead of a register.
 * Chosen so that when a regconst is cast to duk_int32_t, all consts are
 * negative values.
 */
#define DUK_REGCONST_CONST_MARKER    DUK_INT32_MIN  /* = -0x80000000 */

/* Type to represent a reg/const reference during compilation, with <0
 * indicating a constant.  Some call sites also use -1 to indicate 'none'.
 */
typedef duk_int32_t duk_regconst_t;

typedef struct {
	duk_small_uint_t t;          /* DUK_ISPEC_XXX */
	duk_regconst_t regconst;
	duk_idx_t valstack_idx;      /* always set; points to a reserved valstack slot */
} duk_ispec;

typedef struct {
	/*
	 *  PLAIN: x1
	 *  ARITH: x1 <op> x2
	 *  PROP: x1.x2
	 *  VAR: x1 (name)
	 */

	/* XXX: can be optimized for smaller footprint esp. on 32-bit environments */
	duk_small_uint_t t;          /* DUK_IVAL_XXX */
	duk_small_uint_t op;         /* bytecode opcode for binary ops */
	duk_ispec x1;
	duk_ispec x2;
} duk_ivalue;

/*
 *  Bytecode instruction representation during compilation
 *
 *  Contains the actual instruction and (optionally) debug info.
 */

struct duk_compiler_instr {
	duk_instr_t ins;
#if defined(DUK_USE_PC2LINE)
	duk_uint32_t line;
#endif
};

/*
 *  Compiler state
 */

#define DUK_LABEL_FLAG_ALLOW_BREAK       (1U << 0)
#define DUK_LABEL_FLAG_ALLOW_CONTINUE    (1U << 1)

#define DUK_DECL_TYPE_VAR                0
#define DUK_DECL_TYPE_FUNC               1

/* XXX: optimize to 16 bytes */
typedef struct {
	duk_small_uint_t flags;
	duk_int_t label_id;          /* numeric label_id (-1 reserved as marker) */
	duk_hstring *h_label;        /* borrowed label name */
	duk_int_t catch_depth;       /* catch depth at point of definition */
	duk_int_t pc_label;          /* pc of label statement:
	                              * pc+1: break jump site
	                              * pc+2: continue jump site
	                              */

	/* Fast jumps (which avoid longjmp) jump directly to the jump sites
	 * which are always known even while the iteration/switch statement
	 * is still being parsed.  A final peephole pass "straightens out"
	 * the jumps.
	 */
} duk_labelinfo;

/* Compiling state of one function, eventually converted to duk_hcompfunc */
struct duk_compiler_func {
	/* These pointers are at the start of the struct so that they pack
	 * nicely.  Mixing pointers and integer values is bad on some
	 * platforms (e.g. if int is 32 bits and pointers are 64 bits).
	 */

	duk_bufwriter_ctx bw_code;          /* bufwriter for code */

	duk_hstring *h_name;                /* function name (borrowed reference), ends up in _name */
	/* h_code: held in bw_code */
	duk_hobject *h_consts;              /* array */
	duk_hobject *h_funcs;               /* array of function templates: [func1, offset1, line1, func2, offset2, line2]
	                                     * offset/line points to closing brace to allow skipping on pass 2
	                                     */
	duk_hobject *h_decls;               /* array of declarations: [ name1, val1, name2, val2, ... ]
	                                     * valN = (typeN) | (fnum << 8), where fnum is inner func number (0 for vars)
	                                     * record function and variable declarations in pass 1
	                                     */
	duk_hobject *h_labelnames;          /* array of active label names */
	duk_hbuffer_dynamic *h_labelinfos;  /* C array of duk_labelinfo */
	duk_hobject *h_argnames;            /* array of formal argument names (-> _Formals) */
	duk_hobject *h_varmap;              /* variable map for pass 2 (identifier -> register number or null (unmapped)) */

	/* Value stack indices for tracking objects. */
	/* code_idx: not needed */
	duk_idx_t consts_idx;
	duk_idx_t funcs_idx;
	duk_idx_t decls_idx;
	duk_idx_t labelnames_idx;
	duk_idx_t labelinfos_idx;
	duk_idx_t argnames_idx;
	duk_idx_t varmap_idx;

	/* Temp reg handling. */
	duk_regconst_t temp_first;           /* first register that is a temporary (below: variables) */
	duk_regconst_t temp_next;            /* next temporary register to allocate */
	duk_regconst_t temp_max;             /* highest value of temp_reg (temp_max - 1 is highest used reg) */

	/* Shuffle registers if large number of regs/consts. */
	duk_regconst_t shuffle1;
	duk_regconst_t shuffle2;
	duk_regconst_t shuffle3;

	/* Stats for current expression being parsed. */
	duk_int_t nud_count;
	duk_int_t led_count;
	duk_int_t paren_level;              /* parenthesis count, 0 = top level */
	duk_bool_t expr_lhs;                /* expression is left-hand-side compatible */
	duk_bool_t allow_in;                /* current paren level allows 'in' token */

	/* Misc. */
	duk_int_t stmt_next;                /* statement id allocation (running counter) */
	duk_int_t label_next;               /* label id allocation (running counter) */
	duk_int_t catch_depth;              /* catch stack depth */
	duk_int_t with_depth;               /* with stack depth (affects identifier lookups) */
	duk_int_t fnum_next;                /* inner function numbering */
	duk_int_t num_formals;              /* number of formal arguments */
	duk_regconst_t reg_stmt_value;      /* register for writing value of 'non-empty' statements (global or eval code), -1 is marker */
#if defined(DUK_USE_DEBUGGER_SUPPORT)
	duk_int_t min_line;                 /* XXX: typing (duk_hcompfunc has duk_uint32_t) */
	duk_int_t max_line;
#endif

	/* Status booleans. */
	duk_uint8_t is_function;             /* is an actual function (not global/eval code) */
	duk_uint8_t is_eval;                 /* is eval code */
	duk_uint8_t is_global;               /* is global code */
	duk_uint8_t is_namebinding;          /* needs a name binding */
	duk_uint8_t is_constructable;        /* result is constructable */
	duk_uint8_t is_setget;               /* is a setter/getter */
	duk_uint8_t is_strict;               /* function is strict */
	duk_uint8_t is_notail;               /* function must not be tail called */
	duk_uint8_t in_directive_prologue;   /* parsing in "directive prologue", recognize directives */
	duk_uint8_t in_scanning;             /* parsing in "scanning" phase (first pass) */
	duk_uint8_t may_direct_eval;         /* function may call direct eval */
	duk_uint8_t id_access_arguments;     /* function refers to 'arguments' identifier */
	duk_uint8_t id_access_slow;          /* function makes one or more slow path accesses that won't match own static variables */
	duk_uint8_t id_access_slow_own;      /* function makes one or more slow path accesses that may match own static variables */
	duk_uint8_t is_arguments_shadowed;   /* argument/function declaration shadows 'arguments' */
	duk_uint8_t needs_shuffle;           /* function needs shuffle registers */
	duk_uint8_t reject_regexp_in_adv;    /* reject RegExp literal on next advance() call; needed for handling IdentifierName productions */
	duk_uint8_t allow_regexp_in_adv;     /* allow RegExp literal on next advance() call */
};

struct duk_compiler_ctx {
	duk_hthread *thr;

	/* filename being compiled (ends up in functions' '_filename' property) */
	duk_hstring *h_filename;            /* borrowed reference */

	/* lexing (tokenization) state (contains two valstack slot indices) */
	duk_lexer_ctx lex;

	/* current and previous token for parsing */
	duk_token prev_token;
	duk_token curr_token;
	duk_idx_t tok11_idx;                /* curr_token slot1 (matches 'lex' slot1_idx) */
	duk_idx_t tok12_idx;                /* curr_token slot2 (matches 'lex' slot2_idx) */
	duk_idx_t tok21_idx;                /* prev_token slot1 */
	duk_idx_t tok22_idx;                /* prev_token slot2 */

	/* recursion limit */
	duk_int_t recursion_depth;
	duk_int_t recursion_limit;

	/* code emission temporary */
	duk_int_t emit_jumpslot_pc;

	/* current function being compiled (embedded instead of pointer for more compact access) */
	duk_compiler_func curr_func;
};

/*
 *  Prototypes
 */

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);

#endif  /* DUK_JS_COMPILER_H_INCLUDED */
/* #include duk_regexp.h */
#line 1 "duk_regexp.h"
/*
 *  Regular expression structs, constants, and bytecode defines.
 */

#if !defined(DUK_REGEXP_H_INCLUDED)
#define DUK_REGEXP_H_INCLUDED

/* maximum bytecode copies for {n,m} quantifiers */
#define DUK_RE_MAX_ATOM_COPIES             1000

/* regexp compilation limits */
#define DUK_RE_COMPILE_TOKEN_LIMIT         100000000L   /* 1e8 */

/* regexp execution limits */
#define DUK_RE_EXECUTE_STEPS_LIMIT         1000000000L  /* 1e9 */

/* regexp opcodes */
#define DUK_REOP_MATCH                     1
#define DUK_REOP_CHAR                      2
#define DUK_REOP_PERIOD                    3
#define DUK_REOP_RANGES                    4
#define DUK_REOP_INVRANGES                 5
#define DUK_REOP_JUMP                      6
#define DUK_REOP_SPLIT1                    7
#define DUK_REOP_SPLIT2                    8
#define DUK_REOP_SQMINIMAL                 9
#define DUK_REOP_SQGREEDY                  10
#define DUK_REOP_SAVE                      11
#define DUK_REOP_WIPERANGE                 12
#define DUK_REOP_LOOKPOS                   13
#define DUK_REOP_LOOKNEG                   14
#define DUK_REOP_BACKREFERENCE             15
#define DUK_REOP_ASSERT_START              16
#define DUK_REOP_ASSERT_END                17
#define DUK_REOP_ASSERT_WORD_BOUNDARY      18
#define DUK_REOP_ASSERT_NOT_WORD_BOUNDARY  19

/* flags */
#define DUK_RE_FLAG_GLOBAL                 (1U << 0)
#define DUK_RE_FLAG_IGNORE_CASE            (1U << 1)
#define DUK_RE_FLAG_MULTILINE              (1U << 2)

struct duk_re_matcher_ctx {
	duk_hthread *thr;

	duk_uint32_t re_flags;
	const duk_uint8_t *input;
	const duk_uint8_t *input_end;
	const duk_uint8_t *bytecode;
	const duk_uint8_t *bytecode_end;
	const duk_uint8_t **saved;  /* allocated from valstack (fixed buffer) */
	duk_uint32_t nsaved;
	duk_uint32_t recursion_depth;
	duk_uint32_t recursion_limit;
	duk_uint32_t steps_count;
	duk_uint32_t steps_limit;
};

struct duk_re_compiler_ctx {
	duk_hthread *thr;

	duk_uint32_t re_flags;
	duk_lexer_ctx lex;
	duk_re_token curr_token;
	duk_bufwriter_ctx bw;
	duk_uint32_t captures;  /* highest capture number emitted so far (used as: ++captures) */
	duk_uint32_t highest_backref;
	duk_uint32_t recursion_depth;
	duk_uint32_t recursion_limit;
	duk_uint32_t nranges;  /* internal temporary value, used for char classes */
};

/*
 *  Prototypes
 */

#if defined(DUK_USE_REGEXP_SUPPORT)
DUK_INTERNAL_DECL void duk_regexp_compile(duk_hthread *thr);
DUK_INTERNAL_DECL void duk_regexp_create_instance(duk_hthread *thr);
DUK_INTERNAL_DECL void duk_regexp_match(duk_hthread *thr);
DUK_INTERNAL_DECL void duk_regexp_match_force_global(duk_hthread *thr);  /* hacky helper for String.prototype.split() */
#endif

#endif  /* DUK_REGEXP_H_INCLUDED */
/* #include duk_heaphdr.h */
#line 1 "duk_heaphdr.h"
/*
 *  Heap header definition and assorted macros, including ref counting.
 *  Access all fields through the accessor macros.
 */

#if !defined(DUK_HEAPHDR_H_INCLUDED)
#define DUK_HEAPHDR_H_INCLUDED

/*
 *  Common heap header
 *
 *  All heap objects share the same flags and refcount fields.  Objects other
 *  than strings also need to have a single or double linked list pointers
 *  for insertion into the "heap allocated" list.  Strings have single linked
 *  list pointers for string table chaining.
 *
 *  Technically, 'h_refcount' must be wide enough to guarantee that it cannot
 *  wrap; otherwise objects might be freed incorrectly after wrapping.  The
 *  default refcount field is 32 bits even on 64-bit systems: while that's in
 *  theory incorrect, the Duktape heap needs to be larger than 64GB for the
 *  count to actually wrap (assuming 16-byte duk_tvals).  This is very unlikely
 *  to ever be an issue, but if it is, disabling DUK_USE_REFCOUNT32 causes
 *  Duktape to use size_t for refcounts which should always be safe.
 *
 *  Heap header size on 32-bit platforms: 8 bytes without reference counting,
 *  16 bytes with reference counting.
 *
 *  Note that 'raw' macros such as DUK_HEAPHDR_GET_REFCOUNT() are not
 *  defined without DUK_USE_REFERENCE_COUNTING, so caller must #if defined()
 *  around them.
 */

/* XXX: macro for shared header fields (avoids some padding issues) */

struct duk_heaphdr {
	duk_uint32_t h_flags;

#if defined(DUK_USE_REFERENCE_COUNTING)
#if defined(DUK_USE_ASSERTIONS)
	/* When assertions enabled, used by mark-and-sweep for refcount
	 * validation.  Largest reasonable type; also detects overflows.
	 */
	duk_size_t h_assert_refcount;
#endif
#if defined(DUK_USE_REFCOUNT16)
	duk_uint16_t h_refcount;
#elif defined(DUK_USE_REFCOUNT32)
	duk_uint32_t h_refcount;
#else
	duk_size_t h_refcount;
#endif
#endif  /* DUK_USE_REFERENCE_COUNTING */

#if defined(DUK_USE_HEAPPTR16)
	duk_uint16_t h_next16;
#else
	duk_heaphdr *h_next;
#endif

#if defined(DUK_USE_DOUBLE_LINKED_HEAP)
	/* refcounting requires direct heap frees, which in turn requires a dual linked heap */
#if defined(DUK_USE_HEAPPTR16)
	duk_uint16_t h_prev16;
#else
	duk_heaphdr *h_prev;
#endif
#endif

	/* When DUK_USE_HEAPPTR16 (and DUK_USE_REFCOUNT16) is in use, the
	 * struct won't align nicely to 4 bytes.  This 16-bit extra field
	 * is added to make the alignment clean; the field can be used by
	 * heap objects when 16-bit packing is used.  This field is now
	 * conditional to DUK_USE_HEAPPTR16 only, but it is intended to be
	 * used with DUK_USE_REFCOUNT16 and DUK_USE_DOUBLE_LINKED_HEAP;
	 * this only matter to low memory environments anyway.
	 */
#if defined(DUK_USE_HEAPPTR16)
	duk_uint16_t h_extra16;
#endif
};

struct duk_heaphdr_string {
	/* 16 bits would be enough for shared heaphdr flags and duk_hstring
	 * flags.  The initial parts of duk_heaphdr_string and duk_heaphdr
	 * must match so changing the flags field size here would be quite
	 * awkward.  However, to minimize struct size, we can pack at least
	 * 16 bits of duk_hstring data into the flags field.
	 */
	duk_uint32_t h_flags;

#if defined(DUK_USE_REFERENCE_COUNTING)
#if defined(DUK_USE_ASSERTIONS)
	/* When assertions enabled, used by mark-and-sweep for refcount
	 * validation.  Largest reasonable type; also detects overflows.
	 */
	duk_size_t h_assert_refcount;
#endif
#if defined(DUK_USE_REFCOUNT16)
	duk_uint16_t h_refcount;
	duk_uint16_t h_strextra16;  /* round out to 8 bytes */
#elif defined(DUK_USE_REFCOUNT32)
	duk_uint32_t h_refcount;
#else
	duk_size_t h_refcount;
#endif
#else
	duk_uint16_t h_strextra16;
#endif  /* DUK_USE_REFERENCE_COUNTING */

	duk_hstring *h_next;
	/* No 'h_prev' pointer for strings. */
};

#define DUK_HEAPHDR_FLAGS_TYPE_MASK      0x00000003UL
#define DUK_HEAPHDR_FLAGS_FLAG_MASK      (~DUK_HEAPHDR_FLAGS_TYPE_MASK)

                                             /* 2 bits for heap type */
#define DUK_HEAPHDR_FLAGS_HEAP_START     2   /* 5 heap flags */
#define DUK_HEAPHDR_FLAGS_USER_START     7   /* 25 user flags */

#define DUK_HEAPHDR_HEAP_FLAG_NUMBER(n)  (DUK_HEAPHDR_FLAGS_HEAP_START + (n))
#define DUK_HEAPHDR_USER_FLAG_NUMBER(n)  (DUK_HEAPHDR_FLAGS_USER_START + (n))
#define DUK_HEAPHDR_HEAP_FLAG(n)         (1UL << (DUK_HEAPHDR_FLAGS_HEAP_START + (n)))
#define DUK_HEAPHDR_USER_FLAG(n)         (1UL << (DUK_HEAPHDR_FLAGS_USER_START + (n)))

#define DUK_HEAPHDR_FLAG_REACHABLE       DUK_HEAPHDR_HEAP_FLAG(0)  /* mark-and-sweep: reachable */
#define DUK_HEAPHDR_FLAG_TEMPROOT        DUK_HEAPHDR_HEAP_FLAG(1)  /* mark-and-sweep: children not processed */
#define DUK_HEAPHDR_FLAG_FINALIZABLE     DUK_HEAPHDR_HEAP_FLAG(2)  /* mark-and-sweep: finalizable (on current pass) */
#define DUK_HEAPHDR_FLAG_FINALIZED       DUK_HEAPHDR_HEAP_FLAG(3)  /* mark-and-sweep: finalized (on previous pass) */
#define DUK_HEAPHDR_FLAG_READONLY        DUK_HEAPHDR_HEAP_FLAG(4)  /* read-only object, in code section */

#define DUK_HTYPE_MIN                    0
#define DUK_HTYPE_STRING                 0
#define DUK_HTYPE_OBJECT                 1
#define DUK_HTYPE_BUFFER                 2
#define DUK_HTYPE_MAX                    2

#if defined(DUK_USE_HEAPPTR16)
#define DUK_HEAPHDR_GET_NEXT(heap,h) \
	((duk_heaphdr *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->h_next16))
#define DUK_HEAPHDR_SET_NEXT(heap,h,val)   do { \
		(h)->h_next16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) val); \
	} while (0)
#else
#define DUK_HEAPHDR_GET_NEXT(heap,h)  ((h)->h_next)
#define DUK_HEAPHDR_SET_NEXT(heap,h,val)   do { \
		(h)->h_next = (val); \
	} while (0)
#endif

#if defined(DUK_USE_DOUBLE_LINKED_HEAP)
#if defined(DUK_USE_HEAPPTR16)
#define DUK_HEAPHDR_GET_PREV(heap,h) \
	((duk_heaphdr *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->h_prev16))
#define DUK_HEAPHDR_SET_PREV(heap,h,val)   do { \
		(h)->h_prev16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (val)); \
	} while (0)
#else
#define DUK_HEAPHDR_GET_PREV(heap,h)       ((h)->h_prev)
#define DUK_HEAPHDR_SET_PREV(heap,h,val)   do { \
		(h)->h_prev = (val); \
	} while (0)
#endif
#endif

#if defined(DUK_USE_REFERENCE_COUNTING)
#define DUK_HEAPHDR_GET_REFCOUNT(h)   ((h)->h_refcount)
#define DUK_HEAPHDR_SET_REFCOUNT(h,val)  do { \
		(h)->h_refcount = (val); \
		DUK_ASSERT((h)->h_refcount == (val));  /* No truncation. */ \
	} while (0)
#define DUK_HEAPHDR_PREINC_REFCOUNT(h)  (++(h)->h_refcount)  /* result: updated refcount */
#define DUK_HEAPHDR_PREDEC_REFCOUNT(h)  (--(h)->h_refcount)  /* result: updated refcount */
#else
/* refcount macros not defined without refcounting, caller must #if defined() now */
#endif  /* DUK_USE_REFERENCE_COUNTING */

/*
 *  Note: type is treated as a field separate from flags, so some masking is
 *  involved in the macros below.
 */

#define DUK_HEAPHDR_GET_FLAGS_RAW(h)  ((h)->h_flags)
#define DUK_HEAPHDR_SET_FLAGS_RAW(h,val)  do { \
		(h)->h_flags = (val); } \
	}
#define DUK_HEAPHDR_GET_FLAGS(h)      ((h)->h_flags & DUK_HEAPHDR_FLAGS_FLAG_MASK)
#define DUK_HEAPHDR_SET_FLAGS(h,val)  do { \
		(h)->h_flags = ((h)->h_flags & ~(DUK_HEAPHDR_FLAGS_FLAG_MASK)) | (val); \
	} while (0)
#define DUK_HEAPHDR_GET_TYPE(h)       ((h)->h_flags & DUK_HEAPHDR_FLAGS_TYPE_MASK)
#define DUK_HEAPHDR_SET_TYPE(h,val)   do { \
		(h)->h_flags = ((h)->h_flags & ~(DUK_HEAPHDR_FLAGS_TYPE_MASK)) | (val); \
	} while (0)

/* Comparison for type >= DUK_HTYPE_MIN skipped; because DUK_HTYPE_MIN is zero
 * and the comparison is unsigned, it's always true and generates warnings.
 */
#define DUK_HEAPHDR_HTYPE_VALID(h)    ( \
	DUK_HEAPHDR_GET_TYPE((h)) <= DUK_HTYPE_MAX \
	)

#define DUK_HEAPHDR_SET_TYPE_AND_FLAGS(h,tval,fval)  do { \
		(h)->h_flags = ((tval) & DUK_HEAPHDR_FLAGS_TYPE_MASK) | \
		               ((fval) & DUK_HEAPHDR_FLAGS_FLAG_MASK); \
	} while (0)

#define DUK_HEAPHDR_SET_FLAG_BITS(h,bits)  do { \
		DUK_ASSERT(((bits) & ~(DUK_HEAPHDR_FLAGS_FLAG_MASK)) == 0); \
		(h)->h_flags |= (bits); \
	} while (0)

#define DUK_HEAPHDR_CLEAR_FLAG_BITS(h,bits)  do { \
		DUK_ASSERT(((bits) & ~(DUK_HEAPHDR_FLAGS_FLAG_MASK)) == 0); \
		(h)->h_flags &= ~((bits)); \
	} while (0)

#define DUK_HEAPHDR_CHECK_FLAG_BITS(h,bits)  (((h)->h_flags & (bits)) != 0)

#define DUK_HEAPHDR_SET_REACHABLE(h)      DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_REACHABLE)
#define DUK_HEAPHDR_CLEAR_REACHABLE(h)    DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_REACHABLE)
#define DUK_HEAPHDR_HAS_REACHABLE(h)      DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_REACHABLE)

#define DUK_HEAPHDR_SET_TEMPROOT(h)       DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_TEMPROOT)
#define DUK_HEAPHDR_CLEAR_TEMPROOT(h)     DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_TEMPROOT)
#define DUK_HEAPHDR_HAS_TEMPROOT(h)       DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_TEMPROOT)

#define DUK_HEAPHDR_SET_FINALIZABLE(h)    DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZABLE)
#define DUK_HEAPHDR_CLEAR_FINALIZABLE(h)  DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZABLE)
#define DUK_HEAPHDR_HAS_FINALIZABLE(h)    DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZABLE)

#define DUK_HEAPHDR_SET_FINALIZED(h)      DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZED)
#define DUK_HEAPHDR_CLEAR_FINALIZED(h)    DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZED)
#define DUK_HEAPHDR_HAS_FINALIZED(h)      DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZED)

#define DUK_HEAPHDR_SET_READONLY(h)       DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_READONLY)
#define DUK_HEAPHDR_CLEAR_READONLY(h)     DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_READONLY)
#define DUK_HEAPHDR_HAS_READONLY(h)       DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_READONLY)

/* get or set a range of flags; m=first bit number, n=number of bits */
#define DUK_HEAPHDR_GET_FLAG_RANGE(h,m,n)  (((h)->h_flags >> (m)) & ((1UL << (n)) - 1UL))

#define DUK_HEAPHDR_SET_FLAG_RANGE(h,m,n,v)  do { \
		(h)->h_flags = \
			((h)->h_flags & (~(((1UL << (n)) - 1UL) << (m)))) \
			| ((v) << (m)); \
	} while (0)

/* init pointer fields to null */
#if defined(DUK_USE_DOUBLE_LINKED_HEAP)
#define DUK_HEAPHDR_INIT_NULLS(h)       do { \
		DUK_HEAPHDR_SET_NEXT((h), (void *) NULL); \
		DUK_HEAPHDR_SET_PREV((h), (void *) NULL); \
	} while (0)
#else
#define DUK_HEAPHDR_INIT_NULLS(h)       do { \
		DUK_HEAPHDR_SET_NEXT((h), (void *) NULL); \
	} while (0)
#endif

#define DUK_HEAPHDR_STRING_INIT_NULLS(h)  do { \
		(h)->h_next = NULL; \
	} while (0)

/*
 *  Type tests
 */

/* Take advantage of the fact that for DUK_HTYPE_xxx numbers the lowest bit
 * is only set for DUK_HTYPE_OBJECT (= 1).
 */
#if 0
#define DUK_HEAPHDR_IS_OBJECT(h) (DUK_HEAPHDR_GET_TYPE((h)) == DUK_HTYPE_OBJECT)
#endif
#define DUK_HEAPHDR_IS_OBJECT(h) ((h)->h_flags & 0x01UL)
#define DUK_HEAPHDR_IS_STRING(h) (DUK_HEAPHDR_GET_TYPE((h)) == DUK_HTYPE_STRING)
#define DUK_HEAPHDR_IS_BUFFER(h) (DUK_HEAPHDR_GET_TYPE((h)) == DUK_HTYPE_BUFFER)

/*
 *  Assert helpers
 */

/* Check that prev/next links are consistent: if e.g. h->prev is != NULL,
 * h->prev->next should point back to h.
 */
#if defined(DUK_USE_ASSERTIONS)
DUK_INTERNAL_DECL void duk_heaphdr_assert_valid_subclassed(duk_heaphdr *h);
DUK_INTERNAL_DECL void duk_heaphdr_assert_links(duk_heap *heap, duk_heaphdr *h);
DUK_INTERNAL_DECL void duk_heaphdr_assert_valid(duk_heaphdr *h);
#define DUK_HEAPHDR_ASSERT_LINKS(heap,h)  do { duk_heaphdr_assert_links((heap), (h)); } while (0)
#define DUK_HEAPHDR_ASSERT_VALID(h)  do { duk_heaphdr_assert_valid((h)); } while (0)
#else
#define DUK_HEAPHDR_ASSERT_LINKS(heap,h)  do {} while (0)
#define DUK_HEAPHDR_ASSERT_VALID(h)  do {} while (0)
#endif

#endif  /* DUK_HEAPHDR_H_INCLUDED */
/* #include duk_refcount.h */
#line 1 "duk_refcount.h"
/*
 *  Reference counting helper macros.  The macros take a thread argument
 *  and must thus always be executed in a specific thread context.  The
 *  thread argument is not really needed anymore: DECREF can operate with
 *  a heap pointer only, and INCREF needs neither.
 */

#if !defined(DUK_REFCOUNT_H_INCLUDED)
#define DUK_REFCOUNT_H_INCLUDED

#if defined(DUK_USE_REFERENCE_COUNTING)

#if defined(DUK_USE_ROM_OBJECTS)
/* With ROM objects "needs refcount update" is true when the value is
 * heap allocated and is not a ROM object.
 */
/* XXX: double evaluation for 'tv' argument. */
#define DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv) \
	(DUK_TVAL_IS_HEAP_ALLOCATED((tv)) && !DUK_HEAPHDR_HAS_READONLY(DUK_TVAL_GET_HEAPHDR((tv))))
#define DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(h)  (!DUK_HEAPHDR_HAS_READONLY((h)))
#else  /* DUK_USE_ROM_OBJECTS */
/* Without ROM objects "needs refcount update" == is heap allocated. */
#define DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv)    DUK_TVAL_IS_HEAP_ALLOCATED((tv))
#define DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(h)  1
#endif  /* DUK_USE_ROM_OBJECTS */

/* Fast variants, inline refcount operations except for refzero handling.
 * Can be used explicitly when speed is always more important than size.
 * For a good compiler and a single file build, these are basically the
 * same as a forced inline.
 */
#define DUK_TVAL_INCREF_FAST(thr,tv) do { \
		duk_tval *duk__tv = (tv); \
		DUK_ASSERT(duk__tv != NULL); \
		if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(duk__tv)) { \
			duk_heaphdr *duk__h = DUK_TVAL_GET_HEAPHDR(duk__tv); \
			DUK_ASSERT(duk__h != NULL); \
			DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
			DUK_HEAPHDR_PREINC_REFCOUNT(duk__h); \
			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) != 0);  /* No wrapping. */ \
		} \
	} while (0)
#define DUK_TVAL_DECREF_FAST(thr,tv) do { \
		duk_tval *duk__tv = (tv); \
		DUK_ASSERT(duk__tv != NULL); \
		if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(duk__tv)) { \
			duk_heaphdr *duk__h = DUK_TVAL_GET_HEAPHDR(duk__tv); \
			DUK_ASSERT(duk__h != NULL); \
			DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) > 0); \
			if (DUK_HEAPHDR_PREDEC_REFCOUNT(duk__h) == 0) { \
				duk_heaphdr_refzero((thr), duk__h); \
			} \
		} \
	} while (0)
#define DUK_TVAL_DECREF_NORZ_FAST(thr,tv) do { \
		duk_tval *duk__tv = (tv); \
		DUK_ASSERT(duk__tv != NULL); \
		if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(duk__tv)) { \
			duk_heaphdr *duk__h = DUK_TVAL_GET_HEAPHDR(duk__tv); \
			DUK_ASSERT(duk__h != NULL); \
			DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) > 0); \
			if (DUK_HEAPHDR_PREDEC_REFCOUNT(duk__h) == 0) { \
				duk_heaphdr_refzero_norz((thr), duk__h); \
			} \
		} \
	} while (0)
#define DUK_HEAPHDR_INCREF_FAST(thr,h) do { \
		duk_heaphdr *duk__h = (duk_heaphdr *) (h); \
		DUK_ASSERT(duk__h != NULL); \
		DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
		if (DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(duk__h)) { \
			DUK_HEAPHDR_PREINC_REFCOUNT(duk__h); \
			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) != 0);  /* No wrapping. */ \
		} \
	} while (0)
#define DUK_HEAPHDR_DECREF_FAST_RAW(thr,h,rzcall,rzcast) do { \
		duk_heaphdr *duk__h = (duk_heaphdr *) (h); \
		DUK_ASSERT(duk__h != NULL); \
		DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) > 0); \
		if (DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(duk__h)) { \
			if (DUK_HEAPHDR_PREDEC_REFCOUNT(duk__h) == 0) { \
				(rzcall)((thr), (rzcast) duk__h); \
			} \
		} \
	} while (0)
#define DUK_HEAPHDR_DECREF_FAST(thr,h) \
	DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_heaphdr_refzero,duk_heaphdr *)
#define DUK_HEAPHDR_DECREF_NORZ_FAST(thr,h) \
	DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_heaphdr_refzero_norz,duk_heaphdr *)

/* Slow variants, call to a helper to reduce code size.
 * Can be used explicitly when size is always more important than speed.
 */
#define DUK_TVAL_INCREF_SLOW(thr,tv)         do { duk_tval_incref((tv)); } while (0)
#define DUK_TVAL_DECREF_SLOW(thr,tv)         do { duk_tval_decref((thr), (tv)); } while (0)
#define DUK_TVAL_DECREF_NORZ_SLOW(thr,tv)    do { duk_tval_decref_norz((thr), (tv)); } while (0)
#define DUK_HEAPHDR_INCREF_SLOW(thr,h)       do { duk_heaphdr_incref((duk_heaphdr *) (h)); } while (0)
#define DUK_HEAPHDR_DECREF_SLOW(thr,h)       do { duk_heaphdr_decref((thr), (duk_heaphdr *) (h)); } while (0)
#define DUK_HEAPHDR_DECREF_NORZ_SLOW(thr,h)  do { duk_heaphdr_decref_norz((thr), (duk_heaphdr *) (h)); } while (0)
#define DUK_HSTRING_INCREF_SLOW(thr,h)       do { duk_heaphdr_incref((duk_heaphdr *) (h)); } while (0)
#define DUK_HSTRING_DECREF_SLOW(thr,h)       do { duk_heaphdr_decref((thr), (duk_heaphdr *) (h)); } while (0)
#define DUK_HSTRING_DECREF_NORZ_SLOW(thr,h)  do { duk_heaphdr_decref_norz((thr), (duk_heaphdr *) (h)); } while (0)
#define DUK_HBUFFER_INCREF_SLOW(thr,h)       do { duk_heaphdr_incref((duk_heaphdr *) (h)); } while (0)
#define DUK_HBUFFER_DECREF_SLOW(thr,h)       do { duk_heaphdr_decref((thr), (duk_heaphdr *) (h)); } while (0)
#define DUK_HBUFFER_DECREF_NORZ_SLOW(thr,h)  do { duk_heaphdr_decref_norz((thr), (duk_heaphdr *) (h)); } while (0)
#define DUK_HOBJECT_INCREF_SLOW(thr,h)       do { duk_heaphdr_incref((duk_heaphdr *) (h)); } while (0)
#define DUK_HOBJECT_DECREF_SLOW(thr,h)       do { duk_heaphdr_decref((thr), (duk_heaphdr *) (h)); } while (0)
#define DUK_HOBJECT_DECREF_NORZ_SLOW(thr,h)  do { duk_heaphdr_decref_norz((thr), (duk_heaphdr *) (h)); } while (0)

/* Default variants.  Selection depends on speed/size preference.
 * Concretely: with gcc 4.8.1 -Os x64 the difference in final binary
 * is about +1kB for _FAST variants.
 */
#if defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
/* XXX: It would be nice to specialize for specific duk_hobject subtypes
 * but current refzero queue handling prevents that.
 */
#define DUK_TVAL_INCREF(thr,tv)                DUK_TVAL_INCREF_FAST((thr),(tv))
#define DUK_TVAL_DECREF(thr,tv)                DUK_TVAL_DECREF_FAST((thr),(tv))
#define DUK_TVAL_DECREF_NORZ(thr,tv)           DUK_TVAL_DECREF_NORZ_FAST((thr),(tv))
#define DUK_HEAPHDR_INCREF(thr,h)              DUK_HEAPHDR_INCREF_FAST((thr),(h))
#define DUK_HEAPHDR_DECREF(thr,h)              DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_heaphdr_refzero,duk_heaphdr *)
#define DUK_HEAPHDR_DECREF_NORZ(thr,h)         DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_heaphdr_refzero_norz,duk_heaphdr *)
#define DUK_HSTRING_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
#define DUK_HSTRING_DECREF(thr,h)              DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hstring_refzero,duk_hstring *)
#define DUK_HSTRING_DECREF_NORZ(thr,h)         DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hstring_refzero,duk_hstring *)  /* no 'norz' variant */
#define DUK_HOBJECT_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
#define DUK_HOBJECT_DECREF(thr,h)              DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero,duk_hobject *)
#define DUK_HOBJECT_DECREF_NORZ(thr,h)         DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero_norz,duk_hobject *)
#define DUK_HBUFFER_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
#define DUK_HBUFFER_DECREF(thr,h)              DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hbuffer_refzero,duk_hbuffer *)
#define DUK_HBUFFER_DECREF_NORZ(thr,h)         DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hbuffer_refzero,duk_hbuffer *)  /* no 'norz' variant */
#define DUK_HCOMPFUNC_INCREF(thr,h)            DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
#define DUK_HCOMPFUNC_DECREF(thr,h)            DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero,duk_hobject *)
#define DUK_HCOMPFUNC_DECREF_NORZ(thr,h)       DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero_norz,duk_hobject *)
#define DUK_HNATFUNC_INCREF(thr,h)             DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
#define DUK_HNATFUNC_DECREF(thr,h)             DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero,duk_hobject *)
#define DUK_HNATFUNC_DECREF_NORZ(thr,h)        DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero_norz,duk_hobject *)
#define DUK_HBUFOBJ_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
#define DUK_HBUFOBJ_DECREF(thr,h)              DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero,duk_hobject *)
#define DUK_HBUFOBJ_DECREF_NORZ(thr,h)         DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero_norz,duk_hobject *)
#define DUK_HTHREAD_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
#define DUK_HTHREAD_DECREF(thr,h)              DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero,duk_hobject *)
#define DUK_HTHREAD_DECREF_NORZ(thr,h)         DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero_norz,duk_hobject *)
#else
#define DUK_TVAL_INCREF(thr,tv)                DUK_TVAL_INCREF_SLOW((thr),(tv))
#define DUK_TVAL_DECREF(thr,tv)                DUK_TVAL_DECREF_SLOW((thr),(tv))
#define DUK_TVAL_DECREF_NORZ(thr,tv)           DUK_TVAL_DECREF_NORZ_SLOW((thr),(tv))
#define DUK_HEAPHDR_INCREF(thr,h)              DUK_HEAPHDR_INCREF_SLOW((thr),(h))
#define DUK_HEAPHDR_DECREF(thr,h)              DUK_HEAPHDR_DECREF_SLOW((thr),(h))
#define DUK_HEAPHDR_DECREF_NORZ(thr,h)         DUK_HEAPHDR_DECREF_NORZ_SLOW((thr),(h))
#define DUK_HSTRING_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
#define DUK_HSTRING_DECREF(thr,h)              DUK_HSTRING_DECREF_SLOW((thr),(h))
#define DUK_HSTRING_DECREF_NORZ(thr,h)         DUK_HSTRING_DECREF_NORZ_SLOW((thr),(h))
#define DUK_HOBJECT_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
#define DUK_HOBJECT_DECREF(thr,h)              DUK_HOBJECT_DECREF_SLOW((thr),(h))
#define DUK_HOBJECT_DECREF_NORZ(thr,h)         DUK_HOBJECT_DECREF_NORZ_SLOW((thr),(h))
#define DUK_HBUFFER_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
#define DUK_HBUFFER_DECREF(thr,h)              DUK_HBUFFER_DECREF_SLOW((thr),(h))
#define DUK_HBUFFER_DECREF_NORZ(thr,h)         DUK_HBUFFER_DECREF_NORZ_SLOW((thr),(h))
#define DUK_HCOMPFUNC_INCREF(thr,h)            DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
#define DUK_HCOMPFUNC_DECREF(thr,h)            DUK_HOBJECT_DECREF_SLOW((thr),(duk_hobject *) &(h)->obj)
#define DUK_HCOMPFUNC_DECREF_NORZ(thr,h)       DUK_HOBJECT_DECREF_NORZ_SLOW((thr),(duk_hobject *) &(h)->obj)
#define DUK_HNATFUNC_INCREF(thr,h)             DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
#define DUK_HNATFUNC_DECREF(thr,h)             DUK_HOBJECT_DECREF_SLOW((thr),(duk_hobject *) &(h)->obj)
#define DUK_HNATFUNC_DECREF_NORZ(thr,h)        DUK_HOBJECT_DECREF_NORZ_SLOW((thr),(duk_hobject *) &(h)->obj)
#define DUK_HBUFOBJ_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
#define DUK_HBUFOBJ_DECREF(thr,h)              DUK_HOBJECT_DECREF_SLOW((thr),(duk_hobject *) &(h)->obj)
#define DUK_HBUFOB_DECREF_NORZ(thr,h)          DUK_HOBJECT_DECREF_NORZ_SLOW((thr),(duk_hobject *) &(h)->obj)
#define DUK_HTHREAD_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
#define DUK_HTHREAD_DECREF(thr,h)              DUK_HOBJECT_DECREF_SLOW((thr),(duk_hobject *) &(h)->obj)
#define DUK_HTHREAD_DECREF_NORZ(thr,h)         DUK_HOBJECT_DECREF_NORZ_SLOW((thr),(duk_hobject *) &(h)->obj)
#endif

/* Convenience for some situations; the above macros don't allow NULLs
 * for performance reasons.  Macros cover only actually needed cases.
 */
#define DUK_HEAPHDR_INCREF_ALLOWNULL(thr,h) do { \
		if ((h) != NULL) { \
			DUK_HEAPHDR_INCREF((thr), (duk_heaphdr *) (h)); \
		} \
	} while (0)
#define DUK_HEAPHDR_DECREF_ALLOWNULL(thr,h) do { \
		if ((h) != NULL) { \
			DUK_HEAPHDR_DECREF((thr), (duk_heaphdr *) (h)); \
		} \
	} while (0)
#define DUK_HEAPHDR_DECREF_NORZ_ALLOWNULL(thr,h) do { \
		if ((h) != NULL) { \
			DUK_HEAPHDR_DECREF_NORZ((thr), (duk_heaphdr *) (h)); \
		} \
	} while (0)
#define DUK_HOBJECT_INCREF_ALLOWNULL(thr,h) do { \
		if ((h) != NULL) { \
			DUK_HOBJECT_INCREF((thr), (h)); \
		} \
	} while (0)
#define DUK_HOBJECT_DECREF_ALLOWNULL(thr,h) do { \
		if ((h) != NULL) { \
			DUK_HOBJECT_DECREF((thr), (h)); \
		} \
	} while (0)
#define DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr,h) do { \
		if ((h) != NULL) { \
			DUK_HOBJECT_DECREF_NORZ((thr), (h)); \
		} \
	} while (0)
#define DUK_HBUFFER_INCREF_ALLOWNULL(thr,h) do { \
		if ((h) != NULL) { \
			DUK_HBUFFER_INCREF((thr), (h)); \
		} \
	} while (0)
#define DUK_HBUFFER_DECREF_ALLOWNULL(thr,h) do { \
		if ((h) != NULL) { \
			DUK_HBUFFER_DECREF((thr), (h)); \
		} \
	} while (0)
#define DUK_HBUFFER_DECREF_NORZ_ALLOWNULL(thr,h) do { \
		if ((h) != NULL) { \
			DUK_HBUFFER_DECREF_NORZ((thr), (h)); \
		} \
	} while (0)
#define DUK_HTHREAD_INCREF_ALLOWNULL(thr,h) do { \
		if ((h) != NULL) { \
			DUK_HTHREAD_INCREF((thr), (h)); \
		} \
	} while (0)
#define DUK_HTHREAD_DECREF_ALLOWNULL(thr,h) do { \
		if ((h) != NULL) { \
			DUK_HTHREAD_DECREF((thr), (h)); \
		} \
	} while (0)
#define DUK_HTHREAD_DECREF_NORZ_ALLOWNULL(thr,h) do { \
		if ((h) != NULL) { \
			DUK_HTHREAD_DECREF_NORZ((thr), (h)); \
		} \
	} while (0)

/* Called after one or more DECREF NORZ calls to handle pending side effects.
 * At present DECREF NORZ does freeing inline but doesn't execute finalizers,
 * so these macros check for pending finalizers and execute them.  The FAST
 * variant is performance critical.
 */
#if defined(DUK_USE_FINALIZER_SUPPORT)
#define DUK_REFZERO_CHECK_FAST(thr) do { \
		duk_refzero_check_fast((thr)); \
	} while (0)
#define DUK_REFZERO_CHECK_SLOW(thr) do { \
		duk_refzero_check_slow((thr)); \
	} while (0)
#else  /* DUK_USE_FINALIZER_SUPPORT */
#define DUK_REFZERO_CHECK_FAST(thr) do { } while (0)
#define DUK_REFZERO_CHECK_SLOW(thr) do { } while (0)
#endif  /* DUK_USE_FINALIZER_SUPPORT */

/*
 *  Macros to set a duk_tval and update refcount of the target (decref the
 *  old value and incref the new value if necessary).  This is both performance
 *  and footprint critical; any changes made should be measured for size/speed.
 */

#define DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0(thr,tvptr_dst) do { \
		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
		DUK_TVAL_SET_UNDEFINED(tv__dst); \
		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
	} while (0)

#define DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ_ALT0(thr,tvptr_dst) do { \
		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
		DUK_TVAL_SET_UNDEFINED(tv__dst); \
		DUK_TVAL_DECREF_NORZ((thr), &tv__tmp); \
	} while (0)

#define DUK_TVAL_SET_UNUSED_UPDREF_ALT0(thr,tvptr_dst) do { \
		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
		DUK_TVAL_SET_UNUSED(tv__dst); \
		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
	} while (0)

#define DUK_TVAL_SET_NULL_UPDREF_ALT0(thr,tvptr_dst) do { \
		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
		DUK_TVAL_SET_NULL(tv__dst); \
		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
	} while (0)

#define DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
		DUK_TVAL_SET_BOOLEAN(tv__dst, (newval)); \
		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
	} while (0)

#define DUK_TVAL_SET_NUMBER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
		DUK_TVAL_SET_NUMBER(tv__dst, (newval)); \
		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
	} while (0)
#define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
		DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv__dst, (newval)); \
		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
	} while (0)
#define DUK_TVAL_SET_DOUBLE_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
		DUK_TVAL_SET_DOUBLE(tv__dst, (newval)); \
		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
	} while (0)
#define DUK_TVAL_SET_NAN_UPDREF_ALT0(thr,tvptr_dst) do { \
		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
		DUK_TVAL_SET_NAN(tv__dst); \
		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
	} while (0)
#if defined(DUK_USE_FASTINT)
#define DUK_TVAL_SET_I48_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
		DUK_TVAL_SET_I48(tv__dst, (newval)); \
		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
	} while (0)
#define DUK_TVAL_SET_I32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
		DUK_TVAL_SET_I32(tv__dst, (newval)); \
		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
	} while (0)
#define DUK_TVAL_SET_U32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
		DUK_TVAL_SET_U32(tv__dst, (newval)); \
		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
	} while (0)
#else
#define DUK_TVAL_SET_DOUBLE_CAST_UPDREF(thr,tvptr_dst,newval) \
	DUK_TVAL_SET_DOUBLE_UPDREF((thr), (tvptr_dst), (duk_double_t) (newval))
#endif  /* DUK_USE_FASTINT */

#define DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0(thr,tvptr_dst,lf_v,lf_fp,lf_flags) do { \
		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
		DUK_TVAL_SET_LIGHTFUNC(tv__dst, (lf_v), (lf_fp), (lf_flags)); \
		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
	} while (0)

#define DUK_TVAL_SET_STRING_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
		DUK_TVAL_SET_STRING(tv__dst, (newval)); \
		DUK_HSTRING_INCREF((thr), (newval)); \
		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
	} while (0)

#define DUK_TVAL_SET_OBJECT_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
		DUK_TVAL_SET_OBJECT(tv__dst, (newval)); \
		DUK_HOBJECT_INCREF((thr), (newval)); \
		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
	} while (0)

#define DUK_TVAL_SET_BUFFER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
		DUK_TVAL_SET_BUFFER(tv__dst, (newval)); \
		DUK_HBUFFER_INCREF((thr), (newval)); \
		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
	} while (0)

#define DUK_TVAL_SET_POINTER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
		DUK_TVAL_SET_POINTER(tv__dst, (newval)); \
		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
	} while (0)

/* DUK_TVAL_SET_TVAL_UPDREF() is used a lot in executor, property lookups,
 * etc, so it's very important for performance.  Measure when changing.
 *
 * NOTE: the source and destination duk_tval pointers may be the same, and
 * the macros MUST deal with that correctly.
 */

/* Original idiom used, minimal code size. */
#define DUK_TVAL_SET_TVAL_UPDREF_ALT0(thr,tvptr_dst,tvptr_src) do { \
		duk_tval *tv__dst, *tv__src; duk_tval tv__tmp; \
		tv__dst = (tvptr_dst); tv__src = (tvptr_src); \
		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
		DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
		DUK_TVAL_INCREF((thr), tv__src); \
		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
	} while (0)

/* Faster alternative: avoid making a temporary copy of tvptr_dst and use
 * fast incref/decref macros.
 */
#define DUK_TVAL_SET_TVAL_UPDREF_ALT1(thr,tvptr_dst,tvptr_src) do { \
		duk_tval *tv__dst, *tv__src; duk_heaphdr *h__obj; \
		tv__dst = (tvptr_dst); tv__src = (tvptr_src); \
		DUK_TVAL_INCREF_FAST((thr), tv__src); \
		if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv__dst)) { \
			h__obj = DUK_TVAL_GET_HEAPHDR(tv__dst); \
			DUK_ASSERT(h__obj != NULL); \
			DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
			DUK_HEAPHDR_DECREF_FAST((thr), h__obj);  /* side effects */ \
		} else { \
			DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
		} \
	} while (0)

/* XXX: no optimized variants yet */
#define DUK_TVAL_SET_UNDEFINED_UPDREF         DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0
#define DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ    DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ_ALT0
#define DUK_TVAL_SET_UNUSED_UPDREF            DUK_TVAL_SET_UNUSED_UPDREF_ALT0
#define DUK_TVAL_SET_NULL_UPDREF              DUK_TVAL_SET_NULL_UPDREF_ALT0
#define DUK_TVAL_SET_BOOLEAN_UPDREF           DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0
#define DUK_TVAL_SET_NUMBER_UPDREF            DUK_TVAL_SET_NUMBER_UPDREF_ALT0
#define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF    DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0
#define DUK_TVAL_SET_DOUBLE_UPDREF            DUK_TVAL_SET_DOUBLE_UPDREF_ALT0
#define DUK_TVAL_SET_NAN_UPDREF               DUK_TVAL_SET_NAN_UPDREF_ALT0
#if defined(DUK_USE_FASTINT)
#define DUK_TVAL_SET_I48_UPDREF               DUK_TVAL_SET_I48_UPDREF_ALT0
#define DUK_TVAL_SET_I32_UPDREF               DUK_TVAL_SET_I32_UPDREF_ALT0
#define DUK_TVAL_SET_U32_UPDREF               DUK_TVAL_SET_U32_UPDREF_ALT0
#else
#define DUK_TVAL_SET_I48_UPDREF               DUK_TVAL_SET_DOUBLE_CAST_UPDREF  /* XXX: fast int-to-double */
#define DUK_TVAL_SET_I32_UPDREF               DUK_TVAL_SET_DOUBLE_CAST_UPDREF
#define DUK_TVAL_SET_U32_UPDREF               DUK_TVAL_SET_DOUBLE_CAST_UPDREF
#endif  /* DUK_USE_FASTINT */
#define DUK_TVAL_SET_FASTINT_UPDREF           DUK_TVAL_SET_I48_UPDREF  /* convenience */
#define DUK_TVAL_SET_LIGHTFUNC_UPDREF         DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0
#define DUK_TVAL_SET_STRING_UPDREF            DUK_TVAL_SET_STRING_UPDREF_ALT0
#define DUK_TVAL_SET_OBJECT_UPDREF            DUK_TVAL_SET_OBJECT_UPDREF_ALT0
#define DUK_TVAL_SET_BUFFER_UPDREF            DUK_TVAL_SET_BUFFER_UPDREF_ALT0
#define DUK_TVAL_SET_POINTER_UPDREF           DUK_TVAL_SET_POINTER_UPDREF_ALT0

#if defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
/* Optimized for speed. */
#define DUK_TVAL_SET_TVAL_UPDREF              DUK_TVAL_SET_TVAL_UPDREF_ALT1
#define DUK_TVAL_SET_TVAL_UPDREF_FAST         DUK_TVAL_SET_TVAL_UPDREF_ALT1
#define DUK_TVAL_SET_TVAL_UPDREF_SLOW         DUK_TVAL_SET_TVAL_UPDREF_ALT0
#else
/* Optimized for size. */
#define DUK_TVAL_SET_TVAL_UPDREF              DUK_TVAL_SET_TVAL_UPDREF_ALT0
#define DUK_TVAL_SET_TVAL_UPDREF_FAST         DUK_TVAL_SET_TVAL_UPDREF_ALT0
#define DUK_TVAL_SET_TVAL_UPDREF_SLOW         DUK_TVAL_SET_TVAL_UPDREF_ALT0
#endif

#else  /* DUK_USE_REFERENCE_COUNTING */

#define DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv)     0
#define DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(h)   0

#define DUK_TVAL_INCREF_FAST(thr,v)            do {} while (0) /* nop */
#define DUK_TVAL_DECREF_FAST(thr,v)            do {} while (0) /* nop */
#define DUK_TVAL_DECREF_NORZ_FAST(thr,v)       do {} while (0) /* nop */
#define DUK_TVAL_INCREF_SLOW(thr,v)            do {} while (0) /* nop */
#define DUK_TVAL_DECREF_SLOW(thr,v)            do {} while (0) /* nop */
#define DUK_TVAL_DECREF_NORZ_SLOW(thr,v)       do {} while (0) /* nop */
#define DUK_TVAL_INCREF(thr,v)                 do {} while (0) /* nop */
#define DUK_TVAL_DECREF(thr,v)                 do {} while (0) /* nop */
#define DUK_TVAL_DECREF_NORZ(thr,v)            do {} while (0) /* nop */
#define DUK_HEAPHDR_INCREF_FAST(thr,h)         do {} while (0) /* nop */
#define DUK_HEAPHDR_DECREF_FAST(thr,h)         do {} while (0) /* nop */
#define DUK_HEAPHDR_DECREF_NORZ_FAST(thr,h)    do {} while (0) /* nop */
#define DUK_HEAPHDR_INCREF_SLOW(thr,h)         do {} while (0) /* nop */
#define DUK_HEAPHDR_DECREF_SLOW(thr,h)         do {} while (0) /* nop */
#define DUK_HEAPHDR_DECREF_NORZ_SLOW(thr,h)    do {} while (0) /* nop */
#define DUK_HEAPHDR_INCREF(thr,h)              do {} while (0) /* nop */
#define DUK_HEAPHDR_DECREF(thr,h)              do {} while (0) /* nop */
#define DUK_HEAPHDR_DECREF_NORZ(thr,h)         do {} while (0) /* nop */
#define DUK_HSTRING_INCREF_FAST(thr,h)         do {} while (0) /* nop */
#define DUK_HSTRING_DECREF_FAST(thr,h)         do {} while (0) /* nop */
#define DUK_HSTRING_DECREF_NORZ_FAST(thr,h)    do {} while (0) /* nop */
#define DUK_HSTRING_INCREF_SLOW(thr,h)         do {} while (0) /* nop */
#define DUK_HSTRING_DECREF_SLOW(thr,h)         do {} while (0) /* nop */
#define DUK_HSTRING_DECREF_NORZ_SLOW(thr,h)    do {} while (0) /* nop */
#define DUK_HSTRING_INCREF(thr,h)              do {} while (0) /* nop */
#define DUK_HSTRING_DECREF(thr,h)              do {} while (0) /* nop */
#define DUK_HSTRING_DECREF_NORZ(thr,h)         do {} while (0) /* nop */
#define DUK_HOBJECT_INCREF_FAST(thr,h)         do {} while (0) /* nop */
#define DUK_HOBJECT_DECREF_FAST(thr,h)         do {} while (0) /* nop */
#define DUK_HOBJECT_DECREF_NORZ_FAST(thr,h)    do {} while (0) /* nop */
#define DUK_HOBJECT_INCREF_SLOW(thr,h)         do {} while (0) /* nop */
#define DUK_HOBJECT_DECREF_SLOW(thr,h)         do {} while (0) /* nop */
#define DUK_HOBJECT_DECREF_NORZ_SLOW(thr,h)    do {} while (0) /* nop */
#define DUK_HOBJECT_INCREF(thr,h)              do {} while (0) /* nop */
#define DUK_HOBJECT_DECREF(thr,h)              do {} while (0) /* nop */
#define DUK_HOBJECT_DECREF_NORZ(thr,h)         do {} while (0) /* nop */
#define DUK_HBUFFER_INCREF_FAST(thr,h)         do {} while (0) /* nop */
#define DUK_HBUFFER_DECREF_FAST(thr,h)         do {} while (0) /* nop */
#define DUK_HBUFFER_DECREF_NORZ_FAST(thr,h)    do {} while (0) /* nop */
#define DUK_HBUFFER_INCREF_SLOW(thr,h)         do {} while (0) /* nop */
#define DUK_HBUFFER_DECREF_SLOW(thr,h)         do {} while (0) /* nop */
#define DUK_HBUFFER_DECREF_NORZ_SLOW(thr,h)    do {} while (0) /* nop */
#define DUK_HBUFFER_INCREF(thr,h)              do {} while (0) /* nop */
#define DUK_HBUFFER_DECREF(thr,h)              do {} while (0) /* nop */
#define DUK_HBUFFER_DECREF_NORZ(thr,h)         do {} while (0) /* nop */

#define DUK_HCOMPFUNC_INCREF(thr,h)            do {} while (0) /* nop */
#define DUK_HCOMPFUNC_DECREF(thr,h)            do {} while (0) /* nop */
#define DUK_HCOMPFUNC_DECREF_NORZ(thr,h)       do {} while (0) /* nop */
#define DUK_HNATFUNC_INCREF(thr,h)             do {} while (0) /* nop */
#define DUK_HNATFUNC_DECREF(thr,h)             do {} while (0) /* nop */
#define DUK_HNATFUNC_DECREF_NORZ(thr,h)        do {} while (0) /* nop */
#define DUK_HBUFOBJ_INCREF(thr,h)              do {} while (0) /* nop */
#define DUK_HBUFOBJ_DECREF(thr,h)              do {} while (0) /* nop */
#define DUK_HBUFOBJ_DECREF_NORZ(thr,h)         do {} while (0) /* nop */
#define DUK_HTHREAD_INCREF(thr,h)              do {} while (0) /* nop */
#define DUK_HTHREAD_DECREF(thr,h)              do {} while (0) /* nop */
#define DUK_HTHREAD_DECREF_NORZ(thr,h)         do {} while (0) /* nop */
#define DUK_HOBJECT_INCREF_ALLOWNULL(thr,h)    do {} while (0) /* nop */
#define DUK_HOBJECT_DECREF_ALLOWNULL(thr,h)    do {} while (0) /* nop */
#define DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr,h)  do {} while (0) /* nop */
#define DUK_HBUFFER_INCREF_ALLOWNULL(thr,h)    do {} while (0) /* nop */
#define DUK_HBUFFER_DECREF_ALLOWNULL(thr,h)    do {} while (0) /* nop */
#define DUK_HBUFFER_DECREF_NORZ_ALLOWNULL(thr,h)  do {} while (0) /* nop */

#define DUK_REFZERO_CHECK_FAST(thr)            do {} while (0) /* nop */
#define DUK_REFZERO_CHECK_SLOW(thr)            do {} while (0) /* nop */

#define DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0(thr,tvptr_dst) do { \
		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
		DUK_TVAL_SET_UNDEFINED(tv__dst); \
		DUK_UNREF((thr)); \
	} while (0)

#define DUK_TVAL_SET_UNUSED_UPDREF_ALT0(thr,tvptr_dst) do { \
		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
		DUK_TVAL_SET_UNUSED(tv__dst); \
		DUK_UNREF((thr)); \
	} while (0)

#define DUK_TVAL_SET_NULL_UPDREF_ALT0(thr,tvptr_dst) do { \
		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
		DUK_TVAL_SET_NULL(tv__dst); \
		DUK_UNREF((thr)); \
	} while (0)

#define DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
		DUK_TVAL_SET_BOOLEAN(tv__dst, (newval)); \
		DUK_UNREF((thr)); \
	} while (0)

#define DUK_TVAL_SET_NUMBER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
		DUK_TVAL_SET_NUMBER(tv__dst, (newval)); \
		DUK_UNREF((thr)); \
	} while (0)
#define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
		DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv__dst, (newval)); \
		DUK_UNREF((thr)); \
	} while (0)
#define DUK_TVAL_SET_DOUBLE_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
		DUK_TVAL_SET_DOUBLE(tv__dst, (newval)); \
		DUK_UNREF((thr)); \
	} while (0)
#define DUK_TVAL_SET_NAN_UPDREF_ALT0(thr,tvptr_dst) do { \
		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
		DUK_TVAL_SET_NAN(tv__dst); \
		DUK_UNREF((thr)); \
	} while (0)
#if defined(DUK_USE_FASTINT)
#define DUK_TVAL_SET_I48_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
		DUK_TVAL_SET_I48(tv__dst, (newval)); \
		DUK_UNREF((thr)); \
	} while (0)
#define DUK_TVAL_SET_I32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
		DUK_TVAL_SET_I32(tv__dst, (newval)); \
		DUK_UNREF((thr)); \
	} while (0)
#define DUK_TVAL_SET_U32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
		DUK_TVAL_SET_U32(tv__dst, (newval)); \
		DUK_UNREF((thr)); \
	} while (0)
#else
#define DUK_TVAL_SET_DOUBLE_CAST_UPDREF(thr,tvptr_dst,newval) \
	DUK_TVAL_SET_DOUBLE_UPDREF((thr), (tvptr_dst), (duk_double_t) (newval))
#endif  /* DUK_USE_FASTINT */

#define DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0(thr,tvptr_dst,lf_v,lf_fp,lf_flags) do { \
		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
		DUK_TVAL_SET_LIGHTFUNC(tv__dst, (lf_v), (lf_fp), (lf_flags)); \
		DUK_UNREF((thr)); \
	} while (0)

#define DUK_TVAL_SET_STRING_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
		DUK_TVAL_SET_STRING(tv__dst, (newval)); \
		DUK_UNREF((thr)); \
	} while (0)

#define DUK_TVAL_SET_OBJECT_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
		DUK_TVAL_SET_OBJECT(tv__dst, (newval)); \
		DUK_UNREF((thr)); \
	} while (0)

#define DUK_TVAL_SET_BUFFER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
		DUK_TVAL_SET_BUFFER(tv__dst, (newval)); \
		DUK_UNREF((thr)); \
	} while (0)

#define DUK_TVAL_SET_POINTER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
		DUK_TVAL_SET_POINTER(tv__dst, (newval)); \
		DUK_UNREF((thr)); \
	} while (0)

#define DUK_TVAL_SET_TVAL_UPDREF_ALT0(thr,tvptr_dst,tvptr_src) do { \
		duk_tval *tv__dst, *tv__src; \
		tv__dst = (tvptr_dst); tv__src = (tvptr_src); \
		DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
		DUK_UNREF((thr)); \
	} while (0)

#define DUK_TVAL_SET_UNDEFINED_UPDREF         DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0
#define DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ    DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0
#define DUK_TVAL_SET_UNUSED_UPDREF            DUK_TVAL_SET_UNUSED_UPDREF_ALT0
#define DUK_TVAL_SET_NULL_UPDREF              DUK_TVAL_SET_NULL_UPDREF_ALT0
#define DUK_TVAL_SET_BOOLEAN_UPDREF           DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0
#define DUK_TVAL_SET_NUMBER_UPDREF            DUK_TVAL_SET_NUMBER_UPDREF_ALT0
#define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF    DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0
#define DUK_TVAL_SET_DOUBLE_UPDREF            DUK_TVAL_SET_DOUBLE_UPDREF_ALT0
#define DUK_TVAL_SET_NAN_UPDREF               DUK_TVAL_SET_NAN_UPDREF_ALT0
#if defined(DUK_USE_FASTINT)
#define DUK_TVAL_SET_I48_UPDREF               DUK_TVAL_SET_I48_UPDREF_ALT0
#define DUK_TVAL_SET_I32_UPDREF               DUK_TVAL_SET_I32_UPDREF_ALT0
#define DUK_TVAL_SET_U32_UPDREF               DUK_TVAL_SET_U32_UPDREF_ALT0
#else
#define DUK_TVAL_SET_I48_UPDREF               DUK_TVAL_SET_DOUBLE_CAST_UPDREF  /* XXX: fast-int-to-double */
#define DUK_TVAL_SET_I32_UPDREF               DUK_TVAL_SET_DOUBLE_CAST_UPDREF
#define DUK_TVAL_SET_U32_UPDREF               DUK_TVAL_SET_DOUBLE_CAST_UPDREF
#endif  /* DUK_USE_FASTINT */
#define DUK_TVAL_SET_FASTINT_UPDREF           DUK_TVAL_SET_I48_UPDREF  /* convenience */
#define DUK_TVAL_SET_LIGHTFUNC_UPDREF         DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0
#define DUK_TVAL_SET_STRING_UPDREF            DUK_TVAL_SET_STRING_UPDREF_ALT0
#define DUK_TVAL_SET_OBJECT_UPDREF            DUK_TVAL_SET_OBJECT_UPDREF_ALT0
#define DUK_TVAL_SET_BUFFER_UPDREF            DUK_TVAL_SET_BUFFER_UPDREF_ALT0
#define DUK_TVAL_SET_POINTER_UPDREF           DUK_TVAL_SET_POINTER_UPDREF_ALT0

#define DUK_TVAL_SET_TVAL_UPDREF              DUK_TVAL_SET_TVAL_UPDREF_ALT0
#define DUK_TVAL_SET_TVAL_UPDREF_FAST         DUK_TVAL_SET_TVAL_UPDREF_ALT0
#define DUK_TVAL_SET_TVAL_UPDREF_SLOW         DUK_TVAL_SET_TVAL_UPDREF_ALT0

#endif  /* DUK_USE_REFERENCE_COUNTING */

/*
 *  Some convenience macros that don't have optimized implementations now.
 */

#define DUK_TVAL_SET_TVAL_UPDREF_NORZ(thr,tv_dst,tv_src) do { \
		duk_hthread *duk__thr = (thr); \
		duk_tval *duk__dst = (tv_dst); \
		duk_tval *duk__src = (tv_src); \
		DUK_UNREF(duk__thr); \
		DUK_TVAL_DECREF_NORZ(thr, duk__dst); \
		DUK_TVAL_SET_TVAL(duk__dst, duk__src); \
		DUK_TVAL_INCREF(thr, duk__dst); \
	} while (0)

#define DUK_TVAL_SET_U32_UPDREF_NORZ(thr,tv_dst,val) do { \
		duk_hthread *duk__thr = (thr); \
		duk_tval *duk__dst = (tv_dst); \
		duk_uint32_t duk__val = (duk_uint32_t) (val); \
		DUK_UNREF(duk__thr); \
		DUK_TVAL_DECREF_NORZ(thr, duk__dst); \
		DUK_TVAL_SET_U32(duk__dst, duk__val); \
	} while (0)

/*
 *  Prototypes
 */

#if defined(DUK_USE_REFERENCE_COUNTING)
#if defined(DUK_USE_FINALIZER_SUPPORT)
DUK_INTERNAL_DECL void duk_refzero_check_slow(duk_hthread *thr);
DUK_INTERNAL_DECL void duk_refzero_check_fast(duk_hthread *thr);
#endif
DUK_INTERNAL_DECL void duk_heaphdr_refcount_finalize_norz(duk_heap *heap, duk_heaphdr *hdr);
DUK_INTERNAL_DECL void duk_hobject_refcount_finalize_norz(duk_heap *heap, duk_hobject *h);
#if 0  /* Not needed: fast path handles inline; slow path uses duk_heaphdr_decref() which is needed anyway. */
DUK_INTERNAL_DECL void duk_hstring_decref(duk_hthread *thr, duk_hstring *h);
DUK_INTERNAL_DECL void duk_hstring_decref_norz(duk_hthread *thr, duk_hstring *h);
DUK_INTERNAL_DECL void duk_hbuffer_decref(duk_hthread *thr, duk_hbuffer *h);
DUK_INTERNAL_DECL void duk_hbuffer_decref_norz(duk_hthread *thr, duk_hbuffer *h);
DUK_INTERNAL_DECL void duk_hobject_decref(duk_hthread *thr, duk_hobject *h);
DUK_INTERNAL_DECL void duk_hobject_decref_norz(duk_hthread *thr, duk_hobject *h);
#endif
DUK_INTERNAL_DECL void duk_heaphdr_refzero(duk_hthread *thr, duk_heaphdr *h);
DUK_INTERNAL_DECL void duk_heaphdr_refzero_norz(duk_hthread *thr, duk_heaphdr *h);
#if defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
DUK_INTERNAL_DECL void duk_hstring_refzero(duk_hthread *thr, duk_hstring *h);  /* no 'norz' variant */
DUK_INTERNAL_DECL void duk_hbuffer_refzero(duk_hthread *thr, duk_hbuffer *h);  /* no 'norz' variant */
DUK_INTERNAL_DECL void duk_hobject_refzero(duk_hthread *thr, duk_hobject *h);
DUK_INTERNAL_DECL void duk_hobject_refzero_norz(duk_hthread *thr, duk_hobject *h);
#else
DUK_INTERNAL_DECL void duk_tval_incref(duk_tval *tv);
DUK_INTERNAL_DECL void duk_tval_decref(duk_hthread *thr, duk_tval *tv);
DUK_INTERNAL_DECL void duk_tval_decref_norz(duk_hthread *thr, duk_tval *tv);
DUK_INTERNAL_DECL void duk_heaphdr_incref(duk_heaphdr *h);
DUK_INTERNAL_DECL void duk_heaphdr_decref(duk_hthread *thr, duk_heaphdr *h);
DUK_INTERNAL_DECL void duk_heaphdr_decref_norz(duk_hthread *thr, duk_heaphdr *h);
#endif
#else  /* DUK_USE_REFERENCE_COUNTING */
/* no refcounting */
#endif  /* DUK_USE_REFERENCE_COUNTING */

#endif  /* DUK_REFCOUNT_H_INCLUDED */
/* #include duk_api_internal.h */
#line 1 "duk_api_internal.h"
/*
 *  Internal API calls which have (stack and other) semantics similar
 *  to the public API.
 */

#if !defined(DUK_API_INTERNAL_H_INCLUDED)
#define DUK_API_INTERNAL_H_INCLUDED

/* Inline macro helpers. */
#if defined(DUK_USE_PREFER_SIZE)
#define DUK_INLINE_PERF
#define DUK_ALWAYS_INLINE_PERF
#define DUK_NOINLINE_PERF
#else
#define DUK_INLINE_PERF DUK_INLINE
#define DUK_ALWAYS_INLINE_PERF DUK_ALWAYS_INLINE
#define DUK_NOINLINE_PERF DUK_NOINLINE
#endif

/* Inline macro helpers, for bytecode executor. */
#if defined(DUK_USE_EXEC_PREFER_SIZE)
#define DUK_EXEC_INLINE_PERF
#define DUK_EXEC_ALWAYS_INLINE_PERF
#define DUK_EXEC_NOINLINE_PERF
#else
#define DUK_EXEC_INLINE_PERF DUK_INLINE
#define DUK_EXEC_ALWAYS_INLINE_PERF DUK_ALWAYS_INLINE
#define DUK_EXEC_NOINLINE_PERF DUK_NOINLINE
#endif

/* duk_push_sprintf constants */
#define DUK_PUSH_SPRINTF_INITIAL_SIZE  256L
#define DUK_PUSH_SPRINTF_SANITY_LIMIT  (1L * 1024L * 1024L * 1024L)

/* Flag ORed to err_code to indicate __FILE__ / __LINE__ is not
 * blamed as source of error for error fileName / lineNumber.
 */
#define DUK_ERRCODE_FLAG_NOBLAME_FILELINE  (1L << 24)

/* Current convention is to use duk_size_t for value stack sizes and global indices,
 * and duk_idx_t for local frame indices.
 */
DUK_INTERNAL_DECL void duk_valstack_grow_check_throw(duk_hthread *thr, duk_size_t min_bytes);
DUK_INTERNAL_DECL duk_bool_t duk_valstack_grow_check_nothrow(duk_hthread *thr, duk_size_t min_bytes);
DUK_INTERNAL_DECL void duk_valstack_shrink_check_nothrow(duk_hthread *thr, duk_bool_t snug);

DUK_INTERNAL_DECL void duk_copy_tvals_incref(duk_hthread *thr, duk_tval *tv_dst, duk_tval *tv_src, duk_size_t count);

DUK_INTERNAL_DECL duk_tval *duk_reserve_gap(duk_hthread *thr, duk_idx_t idx_base, duk_idx_t count);

DUK_INTERNAL_DECL void duk_set_top_unsafe(duk_hthread *thr, duk_idx_t idx);
DUK_INTERNAL_DECL void duk_set_top_and_wipe(duk_hthread *thr, duk_idx_t top, duk_idx_t idx_wipe_start);

DUK_INTERNAL_DECL void duk_dup_0(duk_hthread *thr);
DUK_INTERNAL_DECL void duk_dup_1(duk_hthread *thr);
DUK_INTERNAL_DECL void duk_dup_2(duk_hthread *thr);
/* duk_dup_m1() would be same as duk_dup_top() */
DUK_INTERNAL_DECL void duk_dup_m2(duk_hthread *thr);
DUK_INTERNAL_DECL void duk_dup_m3(duk_hthread *thr);
DUK_INTERNAL_DECL void duk_dup_m4(duk_hthread *thr);

DUK_INTERNAL_DECL void duk_remove_unsafe(duk_hthread *thr, duk_idx_t idx);
DUK_INTERNAL_DECL void duk_remove_m2(duk_hthread *thr);
DUK_INTERNAL_DECL void duk_remove_n(duk_hthread *thr, duk_idx_t idx, duk_idx_t count);
DUK_INTERNAL_DECL void duk_remove_n_unsafe(duk_hthread *thr, duk_idx_t idx, duk_idx_t count);

DUK_INTERNAL_DECL duk_int_t duk_get_type_tval(duk_tval *tv);
DUK_INTERNAL_DECL duk_uint_t duk_get_type_mask_tval(duk_tval *tv);

#if defined(DUK_USE_VERBOSE_ERRORS) && defined(DUK_USE_PARANOID_ERRORS)
DUK_INTERNAL_DECL const char *duk_get_type_name(duk_hthread *thr, duk_idx_t idx);
#endif
DUK_INTERNAL_DECL duk_small_uint_t duk_get_class_number(duk_hthread *thr, duk_idx_t idx);

DUK_INTERNAL_DECL duk_tval *duk_get_tval(duk_hthread *thr, duk_idx_t idx);
DUK_INTERNAL_DECL duk_tval *duk_get_tval_or_unused(duk_hthread *thr, duk_idx_t idx);
DUK_INTERNAL_DECL duk_tval *duk_require_tval(duk_hthread *thr, duk_idx_t idx);
DUK_INTERNAL_DECL void duk_push_tval(duk_hthread *thr, duk_tval *tv);

/* Push the current 'this' binding; throw TypeError if binding is not object
 * coercible (CheckObjectCoercible).
 */
DUK_INTERNAL_DECL void duk_push_this_check_object_coercible(duk_hthread *thr);

/* duk_push_this() + CheckObjectCoercible() + duk_to_object() */
DUK_INTERNAL_DECL duk_hobject *duk_push_this_coercible_to_object(duk_hthread *thr);

/* duk_push_this() + CheckObjectCoercible() + duk_to_string() */
DUK_INTERNAL_DECL duk_hstring *duk_push_this_coercible_to_string(duk_hthread *thr);

DUK_INTERNAL_DECL duk_hstring *duk_push_uint_to_hstring(duk_hthread *thr, duk_uint_t i);

/* Get a borrowed duk_tval pointer to the current 'this' binding.  Caller must
 * make sure there's an active callstack entry.  Note that the returned pointer
 * is unstable with regards to side effects.
 */
DUK_INTERNAL_DECL duk_tval *duk_get_borrowed_this_tval(duk_hthread *thr);

/* XXX: add fastint support? */
#define duk_push_u64(thr,val) \
	duk_push_number((thr), (duk_double_t) (val))
#define duk_push_i64(thr,val) \
	duk_push_number((thr), (duk_double_t) (val))

/* duk_push_(u)int() is guaranteed to support at least (un)signed 32-bit range */
#define duk_push_u32(thr,val) \
	duk_push_uint((thr), (duk_uint_t) (val))
#define duk_push_i32(thr,val) \
	duk_push_int((thr), (duk_int_t) (val))

/* sometimes stack and array indices need to go on the stack */
#define duk_push_idx(thr,val) \
	duk_push_int((thr), (duk_int_t) (val))
#define duk_push_uarridx(thr,val) \
	duk_push_uint((thr), (duk_uint_t) (val))
#define duk_push_size_t(thr,val) \
	duk_push_uint((thr), (duk_uint_t) (val))  /* XXX: assumed to fit for now */

DUK_INTERNAL_DECL duk_bool_t duk_is_string_notsymbol(duk_hthread *thr, duk_idx_t idx);

DUK_INTERNAL_DECL duk_bool_t duk_is_callable_tval(duk_hthread *thr, duk_tval *tv);

DUK_INTERNAL_DECL duk_bool_t duk_is_bare_object(duk_hthread *thr, duk_idx_t idx);

DUK_INTERNAL_DECL duk_hstring *duk_get_hstring(duk_hthread *thr, duk_idx_t idx);
DUK_INTERNAL_DECL duk_hstring *duk_get_hstring_notsymbol(duk_hthread *thr, duk_idx_t idx);
DUK_INTERNAL_DECL const char *duk_get_string_notsymbol(duk_hthread *thr, duk_idx_t idx);
DUK_INTERNAL_DECL duk_hobject *duk_get_hobject(duk_hthread *thr, duk_idx_t idx);
DUK_INTERNAL_DECL duk_hbuffer *duk_get_hbuffer(duk_hthread *thr, duk_idx_t idx);
DUK_INTERNAL_DECL duk_hthread *duk_get_hthread(duk_hthread *thr, duk_idx_t idx);
DUK_INTERNAL_DECL duk_hcompfunc *duk_get_hcompfunc(duk_hthread *thr, duk_idx_t idx);
DUK_INTERNAL_DECL duk_hnatfunc *duk_get_hnatfunc(duk_hthread *thr, duk_idx_t idx);

DUK_INTERNAL_DECL void *duk_get_buffer_data_raw(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size, void *def_ptr, duk_size_t def_len, duk_bool_t throw_flag, duk_bool_t *out_isbuffer);

DUK_INTERNAL_DECL duk_hobject *duk_get_hobject_with_class(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t classnum);

DUK_INTERNAL_DECL duk_hobject *duk_get_hobject_promote_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask);
DUK_INTERNAL_DECL duk_hobject *duk_require_hobject_promote_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask);
DUK_INTERNAL_DECL duk_hobject *duk_require_hobject_accept_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask);
#define duk_require_hobject_promote_lfunc(thr,idx) \
	duk_require_hobject_promote_mask((thr), (idx), DUK_TYPE_MASK_LIGHTFUNC)
#define duk_get_hobject_promote_lfunc(thr,idx) \
	duk_get_hobject_promote_mask((thr), (idx), DUK_TYPE_MASK_LIGHTFUNC)

#if 0  /*unused*/
DUK_INTERNAL_DECL void *duk_get_voidptr(duk_hthread *thr, duk_idx_t idx);
#endif

DUK_INTERNAL_DECL duk_hstring *duk_known_hstring(duk_hthread *thr, duk_idx_t idx);
DUK_INTERNAL_DECL duk_hobject *duk_known_hobject(duk_hthread *thr, duk_idx_t idx);
DUK_INTERNAL_DECL duk_hbuffer *duk_known_hbuffer(duk_hthread *thr, duk_idx_t idx);
DUK_INTERNAL_DECL duk_hcompfunc *duk_known_hcompfunc(duk_hthread *thr, duk_idx_t idx);
DUK_INTERNAL_DECL duk_hnatfunc *duk_known_hnatfunc(duk_hthread *thr, duk_idx_t idx);

DUK_INTERNAL_DECL duk_double_t duk_to_number_tval(duk_hthread *thr, duk_tval *tv);

DUK_INTERNAL_DECL duk_hstring *duk_to_hstring(duk_hthread *thr, duk_idx_t idx);
DUK_INTERNAL_DECL duk_hstring *duk_to_hstring_m1(duk_hthread *thr);
DUK_INTERNAL_DECL duk_hstring *duk_to_hstring_acceptsymbol(duk_hthread *thr, duk_idx_t idx);

DUK_INTERNAL_DECL duk_hobject *duk_to_hobject(duk_hthread *thr, duk_idx_t idx);

DUK_INTERNAL_DECL duk_double_t duk_to_number_m1(duk_hthread *thr);
DUK_INTERNAL_DECL duk_double_t duk_to_number_m2(duk_hthread *thr);

DUK_INTERNAL_DECL duk_bool_t duk_to_boolean_top_pop(duk_hthread *thr);

#if defined(DUK_USE_DEBUGGER_SUPPORT)  /* only needed by debugger for now */
DUK_INTERNAL_DECL duk_hstring *duk_safe_to_hstring(duk_hthread *thr, duk_idx_t idx);
#endif
DUK_INTERNAL_DECL void duk_push_class_string_tval(duk_hthread *thr, duk_tval *tv, duk_bool_t avoid_side_effects);

DUK_INTERNAL_DECL duk_int_t duk_to_int_clamped_raw(duk_hthread *thr, duk_idx_t idx, duk_int_t minval, duk_int_t maxval, duk_bool_t *out_clamped);  /* out_clamped=NULL, RangeError if outside range */
DUK_INTERNAL_DECL duk_int_t duk_to_int_clamped(duk_hthread *thr, duk_idx_t idx, duk_int_t minval, duk_int_t maxval);
DUK_INTERNAL_DECL duk_int_t duk_to_int_check_range(duk_hthread *thr, duk_idx_t idx, duk_int_t minval, duk_int_t maxval);
#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
DUK_INTERNAL_DECL duk_uint8_t duk_to_uint8clamped(duk_hthread *thr, duk_idx_t idx);
#endif
DUK_INTERNAL_DECL duk_hstring *duk_to_property_key_hstring(duk_hthread *thr, duk_idx_t idx);

DUK_INTERNAL_DECL duk_hstring *duk_require_hstring(duk_hthread *thr, duk_idx_t idx);
DUK_INTERNAL_DECL duk_hstring *duk_require_hstring_notsymbol(duk_hthread *thr, duk_idx_t idx);
DUK_INTERNAL_DECL const char *duk_require_lstring_notsymbol(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len);
DUK_INTERNAL_DECL const char *duk_require_string_notsymbol(duk_hthread *thr, duk_idx_t idx);
DUK_INTERNAL_DECL duk_hobject *duk_require_hobject(duk_hthread *thr, duk_idx_t idx);
DUK_INTERNAL_DECL duk_hbuffer *duk_require_hbuffer(duk_hthread *thr, duk_idx_t idx);
DUK_INTERNAL_DECL duk_hthread *duk_require_hthread(duk_hthread *thr, duk_idx_t idx);
DUK_INTERNAL_DECL duk_hcompfunc *duk_require_hcompfunc(duk_hthread *thr, duk_idx_t idx);
DUK_INTERNAL_DECL duk_hnatfunc *duk_require_hnatfunc(duk_hthread *thr, duk_idx_t idx);

DUK_INTERNAL_DECL duk_hobject *duk_require_hobject_with_class(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t classnum);

DUK_INTERNAL_DECL void duk_push_hstring(duk_hthread *thr, duk_hstring *h);
DUK_INTERNAL_DECL void duk_push_hstring_stridx(duk_hthread *thr, duk_small_uint_t stridx);
DUK_INTERNAL_DECL void duk_push_hstring_empty(duk_hthread *thr);
DUK_INTERNAL_DECL void duk_push_hobject(duk_hthread *thr, duk_hobject *h);
DUK_INTERNAL_DECL void duk_push_hbuffer(duk_hthread *thr, duk_hbuffer *h);
#define duk_push_hthread(thr,h) \
	duk_push_hobject((thr), (duk_hobject *) (h))
#define duk_push_hnatfunc(thr,h) \
	duk_push_hobject((thr), (duk_hobject *) (h))
DUK_INTERNAL_DECL void duk_push_hobject_bidx(duk_hthread *thr, duk_small_int_t builtin_idx);
DUK_INTERNAL_DECL duk_hobject *duk_push_object_helper(duk_hthread *thr, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx);
DUK_INTERNAL_DECL duk_hobject *duk_push_object_helper_proto(duk_hthread *thr, duk_uint_t hobject_flags_and_class, duk_hobject *proto);
DUK_INTERNAL_DECL duk_hcompfunc *duk_push_hcompfunc(duk_hthread *thr);
DUK_INTERNAL_DECL duk_hboundfunc *duk_push_hboundfunc(duk_hthread *thr);
DUK_INTERNAL_DECL void duk_push_c_function_builtin(duk_hthread *thr, duk_c_function func, duk_int_t nargs);
DUK_INTERNAL_DECL void duk_push_c_function_builtin_noconstruct(duk_hthread *thr, duk_c_function func, duk_int_t nargs);

/* XXX: duk_push_harray() and duk_push_hcompfunc() are inconsistent with
 * duk_push_hobject() etc which don't create a new value.
 */
DUK_INTERNAL_DECL duk_harray *duk_push_harray(duk_hthread *thr);
DUK_INTERNAL_DECL duk_harray *duk_push_harray_with_size(duk_hthread *thr, duk_uint32_t size);
DUK_INTERNAL_DECL duk_tval *duk_push_harray_with_size_outptr(duk_hthread *thr, duk_uint32_t size);

DUK_INTERNAL_DECL void duk_push_string_funcptr(duk_hthread *thr, duk_uint8_t *ptr, duk_size_t sz);
DUK_INTERNAL_DECL void duk_push_lightfunc_name_raw(duk_hthread *thr, duk_c_function func, duk_small_uint_t lf_flags);
DUK_INTERNAL_DECL void duk_push_lightfunc_name(duk_hthread *thr, duk_tval *tv);
DUK_INTERNAL_DECL void duk_push_lightfunc_tostring(duk_hthread *thr, duk_tval *tv);
#if 0  /* not used yet */
DUK_INTERNAL_DECL void duk_push_hnatfunc_name(duk_hthread *thr, duk_hnatfunc *h);
#endif
#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
DUK_INTERNAL_DECL duk_hbufobj *duk_push_bufobj_raw(duk_hthread *thr, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx);
#endif

DUK_INTERNAL_DECL void *duk_push_fixed_buffer_nozero(duk_hthread *thr, duk_size_t len);
DUK_INTERNAL_DECL void *duk_push_fixed_buffer_zero(duk_hthread *thr, duk_size_t len);

DUK_INTERNAL_DECL const char *duk_push_string_readable(duk_hthread *thr, duk_idx_t idx);
DUK_INTERNAL_DECL const char *duk_push_string_tval_readable(duk_hthread *thr, duk_tval *tv);
DUK_INTERNAL_DECL const char *duk_push_string_tval_readable_error(duk_hthread *thr, duk_tval *tv);

/* The duk_xxx_prop_stridx_short() variants expect their arguments to be short
 * enough to be packed into a single 32-bit integer argument.  Argument limits
 * vary per call; typically 16 bits are assigned to the signed value stack index
 * and the stridx.  In practice these work well for footprint with constant
 * arguments and such call sites are also easiest to verify to be correct.
 */

DUK_INTERNAL_DECL duk_bool_t duk_get_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx);     /* [] -> [val] */
DUK_INTERNAL_DECL duk_bool_t duk_get_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args);
#define duk_get_prop_stridx_short(thr,obj_idx,stridx) \
	(DUK_ASSERT_EXPR((duk_int_t) (obj_idx) >= -0x8000L && (duk_int_t) (obj_idx) <= 0x7fffL), \
	 DUK_ASSERT_EXPR((duk_int_t) (stridx) >= 0 && (duk_int_t) (stridx) <= 0xffffL), \
	 duk_get_prop_stridx_short_raw((thr), (((duk_uint_t) (obj_idx)) << 16) + ((duk_uint_t) (stridx))))
DUK_INTERNAL_DECL duk_bool_t duk_get_prop_stridx_boolean(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx, duk_bool_t *out_has_prop);  /* [] -> [] */

DUK_INTERNAL_DECL duk_bool_t duk_xget_owndataprop(duk_hthread *thr, duk_idx_t obj_idx);
DUK_INTERNAL_DECL duk_bool_t duk_xget_owndataprop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx);
DUK_INTERNAL_DECL duk_bool_t duk_xget_owndataprop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args);
#define duk_xget_owndataprop_stridx_short(thr,obj_idx,stridx) \
	(DUK_ASSERT_EXPR((duk_int_t) (obj_idx) >= -0x8000L && (duk_int_t) (obj_idx) <= 0x7fffL), \
	 DUK_ASSERT_EXPR((duk_int_t) (stridx) >= 0 && (duk_int_t) (stridx) <= 0xffffL), \
	 duk_xget_owndataprop_stridx_short_raw((thr), (((duk_uint_t) (obj_idx)) << 16) + ((duk_uint_t) (stridx))))

DUK_INTERNAL_DECL duk_bool_t duk_put_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx);     /* [val] -> [] */
DUK_INTERNAL_DECL duk_bool_t duk_put_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args);
#define duk_put_prop_stridx_short(thr,obj_idx,stridx) \
	(DUK_ASSERT_EXPR((duk_int_t) (obj_idx) >= -0x8000L && (duk_int_t) (obj_idx) <= 0x7fffL), \
	 DUK_ASSERT_EXPR((duk_int_t) (stridx) >= 0 && (duk_int_t) (stridx) <= 0xffffL), \
	 duk_put_prop_stridx_short_raw((thr), (((duk_uint_t) (obj_idx)) << 16) + ((duk_uint_t) (stridx))))

DUK_INTERNAL_DECL duk_bool_t duk_del_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx);     /* [] -> [] */
#if 0  /* Too few call sites to be useful. */
DUK_INTERNAL_DECL duk_bool_t duk_del_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args);
#define duk_del_prop_stridx_short(thr,obj_idx,stridx) \
	(DUK_ASSERT_EXPR((obj_idx) >= -0x8000L && (obj_idx) <= 0x7fffL), \
	 DUK_ASSERT_EXPR((stridx) >= 0 && (stridx) <= 0xffffL), \
	 duk_del_prop_stridx_short_raw((thr), (((duk_uint_t) (obj_idx)) << 16) + ((duk_uint_t) (stridx))))
#endif
#define duk_del_prop_stridx_short(thr,obj_idx,stridx) \
	duk_del_prop_stridx((thr), (obj_idx), (stridx))

DUK_INTERNAL_DECL duk_bool_t duk_has_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx);     /* [] -> [] */
#if 0  /* Too few call sites to be useful. */
DUK_INTERNAL_DECL duk_bool_t duk_has_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args);
#define duk_has_prop_stridx_short(thr,obj_idx,stridx) \
	(DUK_ASSERT_EXPR((obj_idx) >= -0x8000L && (obj_idx) <= 0x7fffL), \
	 DUK_ASSERT_EXPR((stridx) >= 0 && (stridx) <= 0xffffL), \
	 duk_has_prop_stridx_short_raw((thr), (((duk_uint_t) (obj_idx)) << 16) + ((duk_uint_t) (stridx))))
#endif
#define duk_has_prop_stridx_short(thr,obj_idx,stridx) \
	duk_has_prop_stridx((thr), (obj_idx), (stridx))

DUK_INTERNAL_DECL void duk_xdef_prop(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t desc_flags);  /* [key val] -> [] */

DUK_INTERNAL_DECL void duk_xdef_prop_index(duk_hthread *thr, duk_idx_t obj_idx, duk_uarridx_t arr_idx, duk_small_uint_t desc_flags);  /* [val] -> [] */

/* XXX: Because stridx and desc_flags have a limited range, this call could
 * always pack stridx and desc_flags into a single argument.
 */
DUK_INTERNAL_DECL void duk_xdef_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx, duk_small_uint_t desc_flags);  /* [val] -> [] */
DUK_INTERNAL_DECL void duk_xdef_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args);
#define duk_xdef_prop_stridx_short(thr,obj_idx,stridx,desc_flags) \
	(DUK_ASSERT_EXPR((duk_int_t) (obj_idx) >= -0x80L && (duk_int_t) (obj_idx) <= 0x7fL), \
	 DUK_ASSERT_EXPR((duk_int_t) (stridx) >= 0 && (duk_int_t) (stridx) <= 0xffffL), \
	 DUK_ASSERT_EXPR((duk_int_t) (desc_flags) >= 0 && (duk_int_t) (desc_flags) <= 0xffL), \
	 duk_xdef_prop_stridx_short_raw((thr), (((duk_uint_t) (obj_idx)) << 24) + (((duk_uint_t) (stridx)) << 8) + (duk_uint_t) (desc_flags)))

#define duk_xdef_prop_wec(thr,obj_idx) \
	duk_xdef_prop((thr), (obj_idx), DUK_PROPDESC_FLAGS_WEC)
#define duk_xdef_prop_index_wec(thr,obj_idx,arr_idx) \
	duk_xdef_prop_index((thr), (obj_idx), (arr_idx), DUK_PROPDESC_FLAGS_WEC)
#define duk_xdef_prop_stridx_wec(thr,obj_idx,stridx) \
	duk_xdef_prop_stridx((thr), (obj_idx), (stridx), DUK_PROPDESC_FLAGS_WEC)
#define duk_xdef_prop_stridx_short_wec(thr,obj_idx,stridx) \
	duk_xdef_prop_stridx_short((thr), (obj_idx), (stridx), DUK_PROPDESC_FLAGS_WEC)

#if 0  /*unused*/
DUK_INTERNAL_DECL void duk_xdef_prop_stridx_builtin(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx, duk_small_int_t builtin_idx, duk_small_uint_t desc_flags);  /* [] -> [] */
#endif

DUK_INTERNAL_DECL void duk_xdef_prop_stridx_thrower(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx);  /* [] -> [] */

DUK_INTERNAL_DECL duk_bool_t duk_get_method_stridx(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t stridx);

DUK_INTERNAL_DECL void duk_pack(duk_hthread *thr, duk_idx_t count);
DUK_INTERNAL_DECL duk_idx_t duk_unpack_array_like(duk_hthread *thr, duk_idx_t idx);
#if 0
DUK_INTERNAL_DECL void duk_unpack(duk_hthread *thr);
#endif

DUK_INTERNAL_DECL void duk_push_symbol_descriptive_string(duk_hthread *thr, duk_hstring *h);

DUK_INTERNAL_DECL void duk_resolve_nonbound_function(duk_hthread *thr);

DUK_INTERNAL_DECL duk_idx_t duk_get_top_require_min(duk_hthread *thr, duk_idx_t min_top);
DUK_INTERNAL_DECL duk_idx_t duk_get_top_index_unsafe(duk_hthread *thr);

DUK_INTERNAL_DECL void duk_pop_n_unsafe(duk_hthread *thr, duk_idx_t count);
DUK_INTERNAL_DECL void duk_pop_unsafe(duk_hthread *thr);
DUK_INTERNAL_DECL void duk_pop_2_unsafe(duk_hthread *thr);
DUK_INTERNAL_DECL void duk_pop_3_unsafe(duk_hthread *thr);
DUK_INTERNAL_DECL void duk_pop_n_nodecref_unsafe(duk_hthread *thr, duk_idx_t count);
DUK_INTERNAL_DECL void duk_pop_nodecref_unsafe(duk_hthread *thr);
DUK_INTERNAL_DECL void duk_pop_2_nodecref_unsafe(duk_hthread *thr);
DUK_INTERNAL_DECL void duk_pop_3_nodecref_unsafe(duk_hthread *thr);
DUK_INTERNAL_DECL void duk_pop_undefined(duk_hthread *thr);

DUK_INTERNAL_DECL void duk_compact_m1(duk_hthread *thr);

DUK_INTERNAL_DECL void duk_seal_freeze_raw(duk_hthread *thr, duk_idx_t obj_idx, duk_bool_t is_freeze);

DUK_INTERNAL_DECL void duk_insert_undefined(duk_hthread *thr, duk_idx_t idx);
DUK_INTERNAL_DECL void duk_insert_undefined_n(duk_hthread *thr, duk_idx_t idx, duk_idx_t count);

DUK_INTERNAL_DECL void duk_concat_2(duk_hthread *thr);

DUK_INTERNAL_DECL duk_int_t duk_pcall_method_flags(duk_hthread *thr, duk_idx_t nargs, duk_small_uint_t call_flags);

#if defined(DUK_USE_SYMBOL_BUILTIN)
DUK_INTERNAL_DECL void duk_to_primitive_ordinary(duk_hthread *thr, duk_idx_t idx, duk_int_t hint);
#endif

DUK_INTERNAL_DECL void duk_clear_prototype(duk_hthread *thr, duk_idx_t idx);

/* Raw internal valstack access macros: access is unsafe so call site
 * must have a guarantee that the index is valid.  When that is the case,
 * using these macro results in faster and smaller code than duk_get_tval().
 * Both 'ctx' and 'idx' are evaluted multiple times, but only for asserts.
 */
#define DUK_ASSERT_VALID_NEGIDX(thr,idx) \
	(DUK_ASSERT_EXPR((duk_int_t) (idx) < 0), DUK_ASSERT_EXPR(duk_is_valid_index((thr), (idx))))
#define DUK_ASSERT_VALID_POSIDX(thr,idx) \
	(DUK_ASSERT_EXPR((duk_int_t) (idx) >= 0), DUK_ASSERT_EXPR(duk_is_valid_index((thr), (idx))))
#define DUK_GET_TVAL_NEGIDX(thr,idx) \
	(DUK_ASSERT_VALID_NEGIDX((thr),(idx)), ((duk_hthread *) (thr))->valstack_top + (idx))
#define DUK_GET_TVAL_POSIDX(thr,idx) \
	(DUK_ASSERT_VALID_POSIDX((thr),(idx)), ((duk_hthread *) (thr))->valstack_bottom + (idx))
#define DUK_GET_HOBJECT_NEGIDX(thr,idx) \
	(DUK_ASSERT_VALID_NEGIDX((thr),(idx)), DUK_TVAL_GET_OBJECT(((duk_hthread *) (thr))->valstack_top + (idx)))
#define DUK_GET_HOBJECT_POSIDX(thr,idx) \
	(DUK_ASSERT_VALID_POSIDX((thr),(idx)), DUK_TVAL_GET_OBJECT(((duk_hthread *) (thr))->valstack_bottom + (idx)))

#define DUK_GET_THIS_TVAL_PTR(thr) \
	(DUK_ASSERT_EXPR((thr)->valstack_bottom > (thr)->valstack), \
	 (thr)->valstack_bottom - 1)

DUK_INTERNAL_DECL duk_double_t duk_time_get_ecmascript_time(duk_hthread *thr);
DUK_INTERNAL_DECL duk_double_t duk_time_get_ecmascript_time_nofrac(duk_hthread *thr);
DUK_INTERNAL_DECL duk_double_t duk_time_get_monotonic_time(duk_hthread *thr);

#endif  /* DUK_API_INTERNAL_H_INCLUDED */
/* #include duk_hstring.h */
#line 1 "duk_hstring.h"
/*
 *  Heap string representation.
 *
 *  Strings are byte sequences ordinarily stored in extended UTF-8 format,
 *  allowing values larger than the official UTF-8 range (used internally)
 *  and also allowing UTF-8 encoding of surrogate pairs (CESU-8 format).
 *  Strings may also be invalid UTF-8 altogether which is the case e.g. with
 *  strings used as internal property names and raw buffers converted to
 *  strings.  In such cases the 'clen' field contains an inaccurate value.
 *
 *  ECMAScript requires support for 32-bit long strings.  However, since each
 *  16-bit codepoint can take 3 bytes in CESU-8, this representation can only
 *  support about 1.4G codepoint long strings in extreme cases.  This is not
 *  really a practical issue.
 */

#if !defined(DUK_HSTRING_H_INCLUDED)
#define DUK_HSTRING_H_INCLUDED

/* Impose a maximum string length for now.  Restricted artificially to
 * ensure adding a heap header length won't overflow size_t.  The limit
 * should be synchronized with DUK_HBUFFER_MAX_BYTELEN.
 *
 * E5.1 makes provisions to support strings longer than 4G characters.
 * This limit should be eliminated on 64-bit platforms (and increased
 * closer to maximum support on 32-bit platforms).
 */

#if defined(DUK_USE_STRLEN16)
#define DUK_HSTRING_MAX_BYTELEN                     (0x0000ffffUL)
#else
#define DUK_HSTRING_MAX_BYTELEN                     (0x7fffffffUL)
#endif

/* XXX: could add flags for "is valid CESU-8" (ECMAScript compatible strings),
 * "is valid UTF-8", "is valid extended UTF-8" (internal strings are not,
 * regexp bytecode is), and "contains non-BMP characters".  These are not
 * needed right now.
 */

/* With lowmem builds the high 16 bits of duk_heaphdr are used for other
 * purposes, so this leaves 7 duk_heaphdr flags and 9 duk_hstring flags.
 */
#define DUK_HSTRING_FLAG_ASCII                      DUK_HEAPHDR_USER_FLAG(0)  /* string is ASCII, clen == blen */
#define DUK_HSTRING_FLAG_ARRIDX                     DUK_HEAPHDR_USER_FLAG(1)  /* string is a valid array index */
#define DUK_HSTRING_FLAG_SYMBOL                     DUK_HEAPHDR_USER_FLAG(2)  /* string is a symbol (invalid utf-8) */
#define DUK_HSTRING_FLAG_HIDDEN                     DUK_HEAPHDR_USER_FLAG(3)  /* string is a hidden symbol (implies symbol, Duktape 1.x internal string) */
#define DUK_HSTRING_FLAG_RESERVED_WORD              DUK_HEAPHDR_USER_FLAG(4)  /* string is a reserved word (non-strict) */
#define DUK_HSTRING_FLAG_STRICT_RESERVED_WORD       DUK_HEAPHDR_USER_FLAG(5)  /* string is a reserved word (strict) */
#define DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS          DUK_HEAPHDR_USER_FLAG(6)  /* string is 'eval' or 'arguments' */
#define DUK_HSTRING_FLAG_EXTDATA                    DUK_HEAPHDR_USER_FLAG(7)  /* string data is external (duk_hstring_external) */
#define DUK_HSTRING_FLAG_PINNED_LITERAL             DUK_HEAPHDR_USER_FLAG(8)  /* string is a literal, and pinned */

#define DUK_HSTRING_HAS_ASCII(x)                    DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ASCII)
#define DUK_HSTRING_HAS_ARRIDX(x)                   DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ARRIDX)
#define DUK_HSTRING_HAS_SYMBOL(x)                   DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_SYMBOL)
#define DUK_HSTRING_HAS_HIDDEN(x)                   DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_HIDDEN)
#define DUK_HSTRING_HAS_RESERVED_WORD(x)            DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_RESERVED_WORD)
#define DUK_HSTRING_HAS_STRICT_RESERVED_WORD(x)     DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_STRICT_RESERVED_WORD)
#define DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(x)        DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS)
#define DUK_HSTRING_HAS_EXTDATA(x)                  DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EXTDATA)
#define DUK_HSTRING_HAS_PINNED_LITERAL(x)           DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_PINNED_LITERAL)

#define DUK_HSTRING_SET_ASCII(x)                    DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ASCII)
#define DUK_HSTRING_SET_ARRIDX(x)                   DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ARRIDX)
#define DUK_HSTRING_SET_SYMBOL(x)                   DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_SYMBOL)
#define DUK_HSTRING_SET_HIDDEN(x)                   DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_HIDDEN)
#define DUK_HSTRING_SET_RESERVED_WORD(x)            DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_RESERVED_WORD)
#define DUK_HSTRING_SET_STRICT_RESERVED_WORD(x)     DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_STRICT_RESERVED_WORD)
#define DUK_HSTRING_SET_EVAL_OR_ARGUMENTS(x)        DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS)
#define DUK_HSTRING_SET_EXTDATA(x)                  DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EXTDATA)
#define DUK_HSTRING_SET_PINNED_LITERAL(x)           DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_PINNED_LITERAL)

#define DUK_HSTRING_CLEAR_ASCII(x)                  DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ASCII)
#define DUK_HSTRING_CLEAR_ARRIDX(x)                 DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ARRIDX)
#define DUK_HSTRING_CLEAR_SYMBOL(x)                 DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_SYMBOL)
#define DUK_HSTRING_CLEAR_HIDDEN(x)                 DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_HIDDEN)
#define DUK_HSTRING_CLEAR_RESERVED_WORD(x)          DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_RESERVED_WORD)
#define DUK_HSTRING_CLEAR_STRICT_RESERVED_WORD(x)   DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_STRICT_RESERVED_WORD)
#define DUK_HSTRING_CLEAR_EVAL_OR_ARGUMENTS(x)      DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS)
#define DUK_HSTRING_CLEAR_EXTDATA(x)                DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EXTDATA)
#define DUK_HSTRING_CLEAR_PINNED_LITERAL(x)         DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_PINNED_LITERAL)

#if 0  /* Slightly smaller code without explicit flag, but explicit flag
        * is very useful when 'clen' is dropped.
        */
#define DUK_HSTRING_IS_ASCII(x)                     (DUK_HSTRING_GET_BYTELEN((x)) == DUK_HSTRING_GET_CHARLEN((x)))
#endif
#define DUK_HSTRING_IS_ASCII(x)                     DUK_HSTRING_HAS_ASCII((x))  /* lazily set! */
#define DUK_HSTRING_IS_EMPTY(x)                     (DUK_HSTRING_GET_BYTELEN((x)) == 0)

#if defined(DUK_USE_STRHASH16)
#define DUK_HSTRING_GET_HASH(x)                     ((x)->hdr.h_flags >> 16)
#define DUK_HSTRING_SET_HASH(x,v) do { \
		(x)->hdr.h_flags = ((x)->hdr.h_flags & 0x0000ffffUL) | ((v) << 16); \
	} while (0)
#else
#define DUK_HSTRING_GET_HASH(x)                     ((x)->hash)
#define DUK_HSTRING_SET_HASH(x,v) do { \
		(x)->hash = (v); \
	} while (0)
#endif

#if defined(DUK_USE_STRLEN16)
#define DUK_HSTRING_GET_BYTELEN(x)                  ((x)->hdr.h_strextra16)
#define DUK_HSTRING_SET_BYTELEN(x,v) do { \
		(x)->hdr.h_strextra16 = (v); \
	} while (0)
#if defined(DUK_USE_HSTRING_CLEN)
#define DUK_HSTRING_GET_CHARLEN(x)                  duk_hstring_get_charlen((x))
#define DUK_HSTRING_SET_CHARLEN(x,v) do { \
		(x)->clen16 = (v); \
	} while (0)
#else
#define DUK_HSTRING_GET_CHARLEN(x)                  duk_hstring_get_charlen((x))
#define DUK_HSTRING_SET_CHARLEN(x,v) do { \
		DUK_ASSERT(0);  /* should never be called */ \
	} while (0)
#endif
#else
#define DUK_HSTRING_GET_BYTELEN(x)                  ((x)->blen)
#define DUK_HSTRING_SET_BYTELEN(x,v) do { \
		(x)->blen = (v); \
	} while (0)
#define DUK_HSTRING_GET_CHARLEN(x)                  duk_hstring_get_charlen((x))
#define DUK_HSTRING_SET_CHARLEN(x,v) do { \
		(x)->clen = (v); \
	} while (0)
#endif

#if defined(DUK_USE_HSTRING_EXTDATA)
#define DUK_HSTRING_GET_EXTDATA(x) \
	((x)->extdata)
#define DUK_HSTRING_GET_DATA(x) \
	(DUK_HSTRING_HAS_EXTDATA((x)) ? \
		DUK_HSTRING_GET_EXTDATA((const duk_hstring_external *) (x)) : ((const duk_uint8_t *) ((x) + 1)))
#else
#define DUK_HSTRING_GET_DATA(x) \
	((const duk_uint8_t *) ((x) + 1))
#endif

#define DUK_HSTRING_GET_DATA_END(x) \
	(DUK_HSTRING_GET_DATA((x)) + (x)->blen)

/* Marker value; in E5 2^32-1 is not a valid array index (2^32-2 is highest
 * valid).
 */
#define DUK_HSTRING_NO_ARRAY_INDEX  (0xffffffffUL)

#if defined(DUK_USE_HSTRING_ARRIDX)
#define DUK_HSTRING_GET_ARRIDX_FAST(h)  ((h)->arridx)
#define DUK_HSTRING_GET_ARRIDX_SLOW(h)  ((h)->arridx)
#else
/* Get array index related to string (or return DUK_HSTRING_NO_ARRAY_INDEX);
 * avoids helper call if string has no array index value.
 */
#define DUK_HSTRING_GET_ARRIDX_FAST(h)  \
	(DUK_HSTRING_HAS_ARRIDX((h)) ? duk_js_to_arrayindex_hstring_fast_known((h)) : DUK_HSTRING_NO_ARRAY_INDEX)

/* Slower but more compact variant. */
#define DUK_HSTRING_GET_ARRIDX_SLOW(h)  \
	(duk_js_to_arrayindex_hstring_fast((h)))
#endif

/* XXX: these actually fit into duk_hstring */
#define DUK_SYMBOL_TYPE_HIDDEN 0
#define DUK_SYMBOL_TYPE_GLOBAL 1
#define DUK_SYMBOL_TYPE_LOCAL 2
#define DUK_SYMBOL_TYPE_WELLKNOWN 3

/* Assertion for duk_hstring validity. */
#if defined(DUK_USE_ASSERTIONS)
DUK_INTERNAL_DECL void duk_hstring_assert_valid(duk_hstring *h);
#define DUK_HSTRING_ASSERT_VALID(h)  do { duk_hstring_assert_valid((h)); } while (0)
#else
#define DUK_HSTRING_ASSERT_VALID(h)  do {} while (0)
#endif

/*
 *  Misc
 */

struct duk_hstring {
	/* Smaller heaphdr than for other objects, because strings are held
	 * in string intern table which requires no link pointers.  Much of
	 * the 32-bit flags field is unused by flags, so we can stuff a 16-bit
	 * field in there.
	 */
	duk_heaphdr_string hdr;

	/* String hash. */
#if defined(DUK_USE_STRHASH16)
	/* If 16-bit hash is in use, stuff it into duk_heaphdr_string flags. */
#else
	duk_uint32_t hash;
#endif

	/* Precomputed array index (or DUK_HSTRING_NO_ARRAY_INDEX). */
#if defined(DUK_USE_HSTRING_ARRIDX)
	duk_uarridx_t arridx;
#endif

	/* Length in bytes (not counting NUL term). */
#if defined(DUK_USE_STRLEN16)
	/* placed in duk_heaphdr_string */
#else
	duk_uint32_t blen;
#endif

	/* Length in codepoints (must be E5 compatible). */
#if defined(DUK_USE_STRLEN16)
#if defined(DUK_USE_HSTRING_CLEN)
	duk_uint16_t clen16;
#else
	/* computed live */
#endif
#else
	duk_uint32_t clen;
#endif

	/*
	 *  String data of 'blen+1' bytes follows (+1 for NUL termination
	 *  convenience for C API).  No alignment needs to be guaranteed
	 *  for strings, but fields above should guarantee alignment-by-4
	 *  (but not alignment-by-8).
	 */
};

/* The external string struct is defined even when the feature is inactive. */
struct duk_hstring_external {
	duk_hstring str;

	/*
	 *  For an external string, the NUL-terminated string data is stored
	 *  externally.  The user must guarantee that data behind this pointer
	 *  doesn't change while it's used.
	 */

	const duk_uint8_t *extdata;
};

/*
 *  Prototypes
 */

DUK_INTERNAL_DECL duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr, duk_hstring *h, duk_uint_t pos, duk_bool_t surrogate_aware);
DUK_INTERNAL_DECL duk_bool_t duk_hstring_equals_ascii_cstring(duk_hstring *h, const char *cstr);
DUK_INTERNAL_DECL duk_size_t duk_hstring_get_charlen(duk_hstring *h);
#if !defined(DUK_USE_HSTRING_LAZY_CLEN)
DUK_INTERNAL_DECL void duk_hstring_init_charlen(duk_hstring *h);
#endif

#endif  /* DUK_HSTRING_H_INCLUDED */
/* #include duk_hobject.h */
#line 1 "duk_hobject.h"
/*
 *  Heap object representation.
 *
 *  Heap objects are used for ECMAScript objects, arrays, and functions,
 *  but also for internal control like declarative and object environment
 *  records.  Compiled functions, native functions, and threads are also
 *  objects but with an extended C struct.
 *
 *  Objects provide the required ECMAScript semantics and exotic behaviors
 *  especially for property access.
 *
 *  Properties are stored in three conceptual parts:
 *
 *    1. A linear 'entry part' contains ordered key-value-attributes triples
 *       and is the main method of string properties.
 *
 *    2. An optional linear 'array part' is used for array objects to store a
 *       (dense) range of [0,N[ array indexed entries with default attributes
 *       (writable, enumerable, configurable).  If the array part would become
 *       sparse or non-default attributes are required, the array part is
 *       abandoned and moved to the 'entry part'.
 *
 *    3. An optional 'hash part' is used to optimize lookups of the entry
 *       part; it is used only for objects with sufficiently many properties
 *       and can be abandoned without loss of information.
 *
 *  These three conceptual parts are stored in a single memory allocated area.
 *  This minimizes memory allocation overhead but also means that all three
 *  parts are resized together, and makes property access a bit complicated.
 */

#if !defined(DUK_HOBJECT_H_INCLUDED)
#define DUK_HOBJECT_H_INCLUDED

/* Object flags.  Make sure this stays in sync with debugger object
 * inspection code.
 */

/* XXX: some flags are object subtype specific (e.g. common to all function
 * subtypes, duk_harray, etc) and could be reused for different subtypes.
 */
#define DUK_HOBJECT_FLAG_EXTENSIBLE            DUK_HEAPHDR_USER_FLAG(0)   /* object is extensible */
#define DUK_HOBJECT_FLAG_CONSTRUCTABLE         DUK_HEAPHDR_USER_FLAG(1)   /* object is constructable */
#define DUK_HOBJECT_FLAG_CALLABLE              DUK_HEAPHDR_USER_FLAG(2)   /* object is callable */
#define DUK_HOBJECT_FLAG_BOUNDFUNC             DUK_HEAPHDR_USER_FLAG(3)   /* object established using Function.prototype.bind() */
#define DUK_HOBJECT_FLAG_COMPFUNC              DUK_HEAPHDR_USER_FLAG(4)   /* object is a compiled function (duk_hcompfunc) */
#define DUK_HOBJECT_FLAG_NATFUNC               DUK_HEAPHDR_USER_FLAG(5)   /* object is a native function (duk_hnatfunc) */
#define DUK_HOBJECT_FLAG_BUFOBJ                DUK_HEAPHDR_USER_FLAG(6)   /* object is a buffer object (duk_hbufobj) (always exotic) */
#define DUK_HOBJECT_FLAG_FASTREFS              DUK_HEAPHDR_USER_FLAG(7)   /* object has no fields needing DECREF/marking beyond base duk_hobject header */
#define DUK_HOBJECT_FLAG_ARRAY_PART            DUK_HEAPHDR_USER_FLAG(8)   /* object has an array part (a_size may still be 0) */
#define DUK_HOBJECT_FLAG_STRICT                DUK_HEAPHDR_USER_FLAG(9)   /* function: function object is strict */
#define DUK_HOBJECT_FLAG_NOTAIL                DUK_HEAPHDR_USER_FLAG(10)  /* function: function must not be tail called */
#define DUK_HOBJECT_FLAG_NEWENV                DUK_HEAPHDR_USER_FLAG(11)  /* function: create new environment when called (see duk_hcompfunc) */
#define DUK_HOBJECT_FLAG_NAMEBINDING           DUK_HEAPHDR_USER_FLAG(12)  /* function: create binding for func name (function templates only, used for named function expressions) */
#define DUK_HOBJECT_FLAG_CREATEARGS            DUK_HEAPHDR_USER_FLAG(13)  /* function: create an arguments object on function call */
#define DUK_HOBJECT_FLAG_HAVE_FINALIZER        DUK_HEAPHDR_USER_FLAG(14)  /* object has a callable (own) finalizer property */
#define DUK_HOBJECT_FLAG_EXOTIC_ARRAY          DUK_HEAPHDR_USER_FLAG(15)  /* 'Array' object, array length and index exotic behavior */
#define DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ      DUK_HEAPHDR_USER_FLAG(16)  /* 'String' object, array index exotic behavior */
#define DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS      DUK_HEAPHDR_USER_FLAG(17)  /* 'Arguments' object and has arguments exotic behavior (non-strict callee) */
#define DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ       DUK_HEAPHDR_USER_FLAG(18)  /* 'Proxy' object */
#define DUK_HOBJECT_FLAG_SPECIAL_CALL          DUK_HEAPHDR_USER_FLAG(19)  /* special casing in call behavior, for .call(), .apply(), etc. */

#define DUK_HOBJECT_FLAG_CLASS_BASE            DUK_HEAPHDR_USER_FLAG_NUMBER(20)
#define DUK_HOBJECT_FLAG_CLASS_BITS            5

#define DUK_HOBJECT_GET_CLASS_NUMBER(h)        \
	DUK_HEAPHDR_GET_FLAG_RANGE(&(h)->hdr, DUK_HOBJECT_FLAG_CLASS_BASE, DUK_HOBJECT_FLAG_CLASS_BITS)
#define DUK_HOBJECT_SET_CLASS_NUMBER(h,v)      \
	DUK_HEAPHDR_SET_FLAG_RANGE(&(h)->hdr, DUK_HOBJECT_FLAG_CLASS_BASE, DUK_HOBJECT_FLAG_CLASS_BITS, (v))

#define DUK_HOBJECT_GET_CLASS_MASK(h)          \
	(1UL << DUK_HEAPHDR_GET_FLAG_RANGE(&(h)->hdr, DUK_HOBJECT_FLAG_CLASS_BASE, DUK_HOBJECT_FLAG_CLASS_BITS))

/* Macro for creating flag initializer from a class number.
 * Unsigned type cast is needed to avoid warnings about coercing
 * a signed integer to an unsigned one; the largest class values
 * have the highest bit (bit 31) set which causes this.
 */
#define DUK_HOBJECT_CLASS_AS_FLAGS(v)          (((duk_uint_t) (v)) << DUK_HOBJECT_FLAG_CLASS_BASE)

/* E5 Section 8.6.2 + custom classes */
#define DUK_HOBJECT_CLASS_NONE                 0
#define DUK_HOBJECT_CLASS_OBJECT               1
#define DUK_HOBJECT_CLASS_ARRAY                2
#define DUK_HOBJECT_CLASS_FUNCTION             3
#define DUK_HOBJECT_CLASS_ARGUMENTS            4
#define DUK_HOBJECT_CLASS_BOOLEAN              5
#define DUK_HOBJECT_CLASS_DATE                 6
#define DUK_HOBJECT_CLASS_ERROR                7
#define DUK_HOBJECT_CLASS_JSON                 8
#define DUK_HOBJECT_CLASS_MATH                 9
#define DUK_HOBJECT_CLASS_NUMBER               10
#define DUK_HOBJECT_CLASS_REGEXP               11
#define DUK_HOBJECT_CLASS_STRING               12
#define DUK_HOBJECT_CLASS_GLOBAL               13
#define DUK_HOBJECT_CLASS_SYMBOL               14
#define DUK_HOBJECT_CLASS_OBJENV               15  /* custom */
#define DUK_HOBJECT_CLASS_DECENV               16  /* custom */
#define DUK_HOBJECT_CLASS_POINTER              17  /* custom */
#define DUK_HOBJECT_CLASS_THREAD               18  /* custom; implies DUK_HOBJECT_IS_THREAD */
#define DUK_HOBJECT_CLASS_BUFOBJ_MIN           19
#define DUK_HOBJECT_CLASS_ARRAYBUFFER          19  /* implies DUK_HOBJECT_IS_BUFOBJ */
#define DUK_HOBJECT_CLASS_DATAVIEW             20
#define DUK_HOBJECT_CLASS_INT8ARRAY            21
#define DUK_HOBJECT_CLASS_UINT8ARRAY           22
#define DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY    23
#define DUK_HOBJECT_CLASS_INT16ARRAY           24
#define DUK_HOBJECT_CLASS_UINT16ARRAY          25
#define DUK_HOBJECT_CLASS_INT32ARRAY           26
#define DUK_HOBJECT_CLASS_UINT32ARRAY          27
#define DUK_HOBJECT_CLASS_FLOAT32ARRAY         28
#define DUK_HOBJECT_CLASS_FLOAT64ARRAY         29
#define DUK_HOBJECT_CLASS_BUFOBJ_MAX           29
#define DUK_HOBJECT_CLASS_MAX                  29

/* Class masks. */
#define DUK_HOBJECT_CMASK_ALL                  ((1UL << (DUK_HOBJECT_CLASS_MAX + 1)) - 1UL)
#define DUK_HOBJECT_CMASK_NONE                 (1UL << DUK_HOBJECT_CLASS_NONE)
#define DUK_HOBJECT_CMASK_ARGUMENTS            (1UL << DUK_HOBJECT_CLASS_ARGUMENTS)
#define DUK_HOBJECT_CMASK_ARRAY                (1UL << DUK_HOBJECT_CLASS_ARRAY)
#define DUK_HOBJECT_CMASK_BOOLEAN              (1UL << DUK_HOBJECT_CLASS_BOOLEAN)
#define DUK_HOBJECT_CMASK_DATE                 (1UL << DUK_HOBJECT_CLASS_DATE)
#define DUK_HOBJECT_CMASK_ERROR                (1UL << DUK_HOBJECT_CLASS_ERROR)
#define DUK_HOBJECT_CMASK_FUNCTION             (1UL << DUK_HOBJECT_CLASS_FUNCTION)
#define DUK_HOBJECT_CMASK_JSON                 (1UL << DUK_HOBJECT_CLASS_JSON)
#define DUK_HOBJECT_CMASK_MATH                 (1UL << DUK_HOBJECT_CLASS_MATH)
#define DUK_HOBJECT_CMASK_NUMBER               (1UL << DUK_HOBJECT_CLASS_NUMBER)
#define DUK_HOBJECT_CMASK_OBJECT               (1UL << DUK_HOBJECT_CLASS_OBJECT)
#define DUK_HOBJECT_CMASK_REGEXP               (1UL << DUK_HOBJECT_CLASS_REGEXP)
#define DUK_HOBJECT_CMASK_STRING               (1UL << DUK_HOBJECT_CLASS_STRING)
#define DUK_HOBJECT_CMASK_GLOBAL               (1UL << DUK_HOBJECT_CLASS_GLOBAL)
#define DUK_HOBJECT_CMASK_SYMBOL               (1UL << DUK_HOBJECT_CLASS_SYMBOL)
#define DUK_HOBJECT_CMASK_OBJENV               (1UL << DUK_HOBJECT_CLASS_OBJENV)
#define DUK_HOBJECT_CMASK_DECENV               (1UL << DUK_HOBJECT_CLASS_DECENV)
#define DUK_HOBJECT_CMASK_POINTER              (1UL << DUK_HOBJECT_CLASS_POINTER)
#define DUK_HOBJECT_CMASK_ARRAYBUFFER          (1UL << DUK_HOBJECT_CLASS_ARRAYBUFFER)
#define DUK_HOBJECT_CMASK_DATAVIEW             (1UL << DUK_HOBJECT_CLASS_DATAVIEW)
#define DUK_HOBJECT_CMASK_INT8ARRAY            (1UL << DUK_HOBJECT_CLASS_INT8ARRAY)
#define DUK_HOBJECT_CMASK_UINT8ARRAY           (1UL << DUK_HOBJECT_CLASS_UINT8ARRAY)
#define DUK_HOBJECT_CMASK_UINT8CLAMPEDARRAY    (1UL << DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY)
#define DUK_HOBJECT_CMASK_INT16ARRAY           (1UL << DUK_HOBJECT_CLASS_INT16ARRAY)
#define DUK_HOBJECT_CMASK_UINT16ARRAY          (1UL << DUK_HOBJECT_CLASS_UINT16ARRAY)
#define DUK_HOBJECT_CMASK_INT32ARRAY           (1UL << DUK_HOBJECT_CLASS_INT32ARRAY)
#define DUK_HOBJECT_CMASK_UINT32ARRAY          (1UL << DUK_HOBJECT_CLASS_UINT32ARRAY)
#define DUK_HOBJECT_CMASK_FLOAT32ARRAY         (1UL << DUK_HOBJECT_CLASS_FLOAT32ARRAY)
#define DUK_HOBJECT_CMASK_FLOAT64ARRAY         (1UL << DUK_HOBJECT_CLASS_FLOAT64ARRAY)

#define DUK_HOBJECT_CMASK_ALL_BUFOBJS \
	(DUK_HOBJECT_CMASK_ARRAYBUFFER | \
	 DUK_HOBJECT_CMASK_DATAVIEW | \
	 DUK_HOBJECT_CMASK_INT8ARRAY | \
	 DUK_HOBJECT_CMASK_UINT8ARRAY | \
	 DUK_HOBJECT_CMASK_UINT8CLAMPEDARRAY | \
	 DUK_HOBJECT_CMASK_INT16ARRAY | \
	 DUK_HOBJECT_CMASK_UINT16ARRAY | \
	 DUK_HOBJECT_CMASK_INT32ARRAY | \
	 DUK_HOBJECT_CMASK_UINT32ARRAY | \
	 DUK_HOBJECT_CMASK_FLOAT32ARRAY | \
	 DUK_HOBJECT_CMASK_FLOAT64ARRAY)

#define DUK_HOBJECT_IS_OBJENV(h)               (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_OBJENV)
#define DUK_HOBJECT_IS_DECENV(h)               (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_DECENV)
#define DUK_HOBJECT_IS_ENV(h)                  (DUK_HOBJECT_IS_OBJENV((h)) || DUK_HOBJECT_IS_DECENV((h)))
#define DUK_HOBJECT_IS_ARRAY(h)                DUK_HOBJECT_HAS_EXOTIC_ARRAY((h))  /* Rely on class Array <=> exotic Array */
#define DUK_HOBJECT_IS_BOUNDFUNC(h)            DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUNDFUNC)
#define DUK_HOBJECT_IS_COMPFUNC(h)             DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPFUNC)
#define DUK_HOBJECT_IS_NATFUNC(h)              DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATFUNC)
#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
#define DUK_HOBJECT_IS_BUFOBJ(h)               DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFOBJ)
#else
#define DUK_HOBJECT_IS_BUFOBJ(h)               0
#endif
#define DUK_HOBJECT_IS_THREAD(h)               (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_THREAD)
#if defined(DUK_USE_ES6_PROXY)
#define DUK_HOBJECT_IS_PROXY(h)                DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ((h))
#else
#define DUK_HOBJECT_IS_PROXY(h)                0
#endif

#define DUK_HOBJECT_IS_NONBOUND_FUNCTION(h)    DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, \
                                                        DUK_HOBJECT_FLAG_COMPFUNC | \
                                                        DUK_HOBJECT_FLAG_NATFUNC)

#define DUK_HOBJECT_IS_FUNCTION(h)             DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, \
                                                        DUK_HOBJECT_FLAG_BOUNDFUNC | \
                                                        DUK_HOBJECT_FLAG_COMPFUNC | \
                                                        DUK_HOBJECT_FLAG_NATFUNC)

#define DUK_HOBJECT_IS_CALLABLE(h)             DUK_HOBJECT_HAS_CALLABLE((h))

/* Object has any exotic behavior(s). */
#define DUK_HOBJECT_EXOTIC_BEHAVIOR_FLAGS      (DUK_HOBJECT_FLAG_EXOTIC_ARRAY | \
                                                DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS | \
                                                DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ | \
                                                DUK_HOBJECT_FLAG_BUFOBJ | \
                                                DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
#define DUK_HOBJECT_HAS_EXOTIC_BEHAVIOR(h)     DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_EXOTIC_BEHAVIOR_FLAGS)

/* Object has any virtual properties (not counting Proxy behavior). */
#define DUK_HOBJECT_VIRTUAL_PROPERTY_FLAGS     (DUK_HOBJECT_FLAG_EXOTIC_ARRAY | \
                                                DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ | \
                                                DUK_HOBJECT_FLAG_BUFOBJ)
#define DUK_HOBJECT_HAS_VIRTUAL_PROPERTIES(h)  DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_VIRTUAL_PROPERTY_FLAGS)

#define DUK_HOBJECT_HAS_EXTENSIBLE(h)          DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXTENSIBLE)
#define DUK_HOBJECT_HAS_CONSTRUCTABLE(h)       DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CONSTRUCTABLE)
#define DUK_HOBJECT_HAS_CALLABLE(h)            DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CALLABLE)
#define DUK_HOBJECT_HAS_BOUNDFUNC(h)           DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUNDFUNC)
#define DUK_HOBJECT_HAS_COMPFUNC(h)            DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPFUNC)
#define DUK_HOBJECT_HAS_NATFUNC(h)             DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATFUNC)
#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
#define DUK_HOBJECT_HAS_BUFOBJ(h)              DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFOBJ)
#else
#define DUK_HOBJECT_HAS_BUFOBJ(h)              0
#endif
#define DUK_HOBJECT_HAS_FASTREFS(h)            DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_FASTREFS)
#define DUK_HOBJECT_HAS_ARRAY_PART(h)          DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ARRAY_PART)
#define DUK_HOBJECT_HAS_STRICT(h)              DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_STRICT)
#define DUK_HOBJECT_HAS_NOTAIL(h)              DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NOTAIL)
#define DUK_HOBJECT_HAS_NEWENV(h)              DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NEWENV)
#define DUK_HOBJECT_HAS_NAMEBINDING(h)         DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NAMEBINDING)
#define DUK_HOBJECT_HAS_CREATEARGS(h)          DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CREATEARGS)
#define DUK_HOBJECT_HAS_HAVE_FINALIZER(h)      DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_HAVE_FINALIZER)
#define DUK_HOBJECT_HAS_EXOTIC_ARRAY(h)        DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARRAY)
#define DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(h)    DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ)
#define DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(h)    DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS)
#if defined(DUK_USE_ES6_PROXY)
#define DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h)     DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
#else
#define DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h)     0
#endif
#define DUK_HOBJECT_HAS_SPECIAL_CALL(h)        DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_SPECIAL_CALL)

#define DUK_HOBJECT_SET_EXTENSIBLE(h)          DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXTENSIBLE)
#define DUK_HOBJECT_SET_CONSTRUCTABLE(h)       DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CONSTRUCTABLE)
#define DUK_HOBJECT_SET_CALLABLE(h)            DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CALLABLE)
#define DUK_HOBJECT_SET_BOUNDFUNC(h)           DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUNDFUNC)
#define DUK_HOBJECT_SET_COMPFUNC(h)            DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPFUNC)
#define DUK_HOBJECT_SET_NATFUNC(h)             DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATFUNC)
#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
#define DUK_HOBJECT_SET_BUFOBJ(h)              DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFOBJ)
#endif
#define DUK_HOBJECT_SET_FASTREFS(h)            DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_FASTREFS)
#define DUK_HOBJECT_SET_ARRAY_PART(h)          DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ARRAY_PART)
#define DUK_HOBJECT_SET_STRICT(h)              DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_STRICT)
#define DUK_HOBJECT_SET_NOTAIL(h)              DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NOTAIL)
#define DUK_HOBJECT_SET_NEWENV(h)              DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NEWENV)
#define DUK_HOBJECT_SET_NAMEBINDING(h)         DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NAMEBINDING)
#define DUK_HOBJECT_SET_CREATEARGS(h)          DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CREATEARGS)
#define DUK_HOBJECT_SET_HAVE_FINALIZER(h)      DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_HAVE_FINALIZER)
#define DUK_HOBJECT_SET_EXOTIC_ARRAY(h)        DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARRAY)
#define DUK_HOBJECT_SET_EXOTIC_STRINGOBJ(h)    DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ)
#define DUK_HOBJECT_SET_EXOTIC_ARGUMENTS(h)    DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS)
#if defined(DUK_USE_ES6_PROXY)
#define DUK_HOBJECT_SET_EXOTIC_PROXYOBJ(h)     DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
#endif
#define DUK_HOBJECT_SET_SPECIAL_CALL(h)        DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_SPECIAL_CALL)

#define DUK_HOBJECT_CLEAR_EXTENSIBLE(h)        DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXTENSIBLE)
#define DUK_HOBJECT_CLEAR_CONSTRUCTABLE(h)     DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CONSTRUCTABLE)
#define DUK_HOBJECT_CLEAR_CALLABLE(h)          DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CALLABLE)
#define DUK_HOBJECT_CLEAR_BOUNDFUNC(h)         DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUNDFUNC)
#define DUK_HOBJECT_CLEAR_COMPFUNC(h)          DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPFUNC)
#define DUK_HOBJECT_CLEAR_NATFUNC(h)           DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATFUNC)
#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
#define DUK_HOBJECT_CLEAR_BUFOBJ(h)            DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFOBJ)
#endif
#define DUK_HOBJECT_CLEAR_FASTREFS(h)          DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_FASTREFS)
#define DUK_HOBJECT_CLEAR_ARRAY_PART(h)        DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ARRAY_PART)
#define DUK_HOBJECT_CLEAR_STRICT(h)            DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_STRICT)
#define DUK_HOBJECT_CLEAR_NOTAIL(h)            DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NOTAIL)
#define DUK_HOBJECT_CLEAR_NEWENV(h)            DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NEWENV)
#define DUK_HOBJECT_CLEAR_NAMEBINDING(h)       DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NAMEBINDING)
#define DUK_HOBJECT_CLEAR_CREATEARGS(h)        DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CREATEARGS)
#define DUK_HOBJECT_CLEAR_HAVE_FINALIZER(h)    DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_HAVE_FINALIZER)
#define DUK_HOBJECT_CLEAR_EXOTIC_ARRAY(h)      DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARRAY)
#define DUK_HOBJECT_CLEAR_EXOTIC_STRINGOBJ(h)  DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ)
#define DUK_HOBJECT_CLEAR_EXOTIC_ARGUMENTS(h)  DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS)
#if defined(DUK_USE_ES6_PROXY)
#define DUK_HOBJECT_CLEAR_EXOTIC_PROXYOBJ(h)   DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
#endif
#define DUK_HOBJECT_CLEAR_SPECIAL_CALL(h)      DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_SPECIAL_CALL)

/* Object can/cannot use FASTREFS, i.e. has no strong reference fields beyond
 * duk_hobject base header.  This is used just for asserts so doesn't need to
 * be optimized.
 */
#define DUK_HOBJECT_PROHIBITS_FASTREFS(h) \
	(DUK_HOBJECT_IS_COMPFUNC((h)) || DUK_HOBJECT_IS_DECENV((h)) || DUK_HOBJECT_IS_OBJENV((h)) || \
	 DUK_HOBJECT_IS_BUFOBJ((h)) || DUK_HOBJECT_IS_THREAD((h)) || DUK_HOBJECT_IS_PROXY((h)) || \
	 DUK_HOBJECT_IS_BOUNDFUNC((h)))
#define DUK_HOBJECT_ALLOWS_FASTREFS(h) (!DUK_HOBJECT_PROHIBITS_FASTREFS((h)))

/* Flags used for property attributes in duk_propdesc and packed flags.
 * Must fit into 8 bits.
 */
#define DUK_PROPDESC_FLAG_WRITABLE              (1U << 0)    /* E5 Section 8.6.1 */
#define DUK_PROPDESC_FLAG_ENUMERABLE            (1U << 1)    /* E5 Section 8.6.1 */
#define DUK_PROPDESC_FLAG_CONFIGURABLE          (1U << 2)    /* E5 Section 8.6.1 */
#define DUK_PROPDESC_FLAG_ACCESSOR              (1U << 3)    /* accessor */
#define DUK_PROPDESC_FLAG_VIRTUAL               (1U << 4)    /* property is virtual: used in duk_propdesc, never stored
                                                             * (used by e.g. buffer virtual properties)
                                                             */
#define DUK_PROPDESC_FLAGS_MASK                 (DUK_PROPDESC_FLAG_WRITABLE | \
                                                 DUK_PROPDESC_FLAG_ENUMERABLE | \
                                                 DUK_PROPDESC_FLAG_CONFIGURABLE | \
                                                 DUK_PROPDESC_FLAG_ACCESSOR)

/* Additional flags which are passed in the same flags argument as property
 * flags but are not stored in object properties.
 */
#define DUK_PROPDESC_FLAG_NO_OVERWRITE          (1U << 4)    /* internal define property: skip write silently if exists */

/* Convenience defines for property attributes. */
#define DUK_PROPDESC_FLAGS_NONE                 0
#define DUK_PROPDESC_FLAGS_W                    (DUK_PROPDESC_FLAG_WRITABLE)
#define DUK_PROPDESC_FLAGS_E                    (DUK_PROPDESC_FLAG_ENUMERABLE)
#define DUK_PROPDESC_FLAGS_C                    (DUK_PROPDESC_FLAG_CONFIGURABLE)
#define DUK_PROPDESC_FLAGS_WE                   (DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_ENUMERABLE)
#define DUK_PROPDESC_FLAGS_WC                   (DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_CONFIGURABLE)
#define DUK_PROPDESC_FLAGS_EC                   (DUK_PROPDESC_FLAG_ENUMERABLE | DUK_PROPDESC_FLAG_CONFIGURABLE)
#define DUK_PROPDESC_FLAGS_WEC                  (DUK_PROPDESC_FLAG_WRITABLE | \
                                                 DUK_PROPDESC_FLAG_ENUMERABLE | \
                                                 DUK_PROPDESC_FLAG_CONFIGURABLE)

/* Flags for duk_hobject_get_own_propdesc() and variants. */
#define DUK_GETDESC_FLAG_PUSH_VALUE          (1U << 0)  /* push value to stack */
#define DUK_GETDESC_FLAG_IGNORE_PROTOLOOP    (1U << 1)  /* don't throw for prototype loop */

/*
 *  Macro for object validity check
 *
 *  Assert for currently guaranteed relations between flags, for instance.
 */

#if defined(DUK_USE_ASSERTIONS)
DUK_INTERNAL_DECL void duk_hobject_assert_valid(duk_hobject *h);
#define DUK_HOBJECT_ASSERT_VALID(h)  do { duk_hobject_assert_valid((h)); } while (0)
#else
#define DUK_HOBJECT_ASSERT_VALID(h)  do {} while (0)
#endif

/*
 *  Macros to access the 'props' allocation.
 */

#if defined(DUK_USE_HEAPPTR16)
#define DUK_HOBJECT_GET_PROPS(heap,h) \
	((duk_uint8_t *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, ((duk_heaphdr *) (h))->h_extra16))
#define DUK_HOBJECT_SET_PROPS(heap,h,x) do { \
		((duk_heaphdr *) (h))->h_extra16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (x)); \
	} while (0)
#else
#define DUK_HOBJECT_GET_PROPS(heap,h) \
	((h)->props)
#define DUK_HOBJECT_SET_PROPS(heap,h,x) do { \
		(h)->props = (duk_uint8_t *) (x); \
	} while (0)
#endif

#if defined(DUK_USE_HOBJECT_LAYOUT_1)
/* LAYOUT 1 */
#define DUK_HOBJECT_E_GET_KEY_BASE(heap,h) \
	((duk_hstring **) (void *) ( \
		DUK_HOBJECT_GET_PROPS((heap), (h)) \
	))
#define DUK_HOBJECT_E_GET_VALUE_BASE(heap,h) \
	((duk_propvalue *) (void *) ( \
		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
			DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_hstring *) \
	))
#define DUK_HOBJECT_E_GET_FLAGS_BASE(heap,h) \
	((duk_uint8_t *) (void *) ( \
		DUK_HOBJECT_GET_PROPS((heap), (h)) + DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue)) \
	))
#define DUK_HOBJECT_A_GET_BASE(heap,h) \
	((duk_tval *) (void *) ( \
		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
			DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) \
	))
#define DUK_HOBJECT_H_GET_BASE(heap,h) \
	((duk_uint32_t *) (void *) ( \
		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
			DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
			DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \
	))
#define DUK_HOBJECT_P_COMPUTE_SIZE(n_ent,n_arr,n_hash) \
	( \
		(n_ent) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
		(n_arr) * sizeof(duk_tval) + \
		(n_hash) * sizeof(duk_uint32_t) \
	)
#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 { \
		(set_e_k) = (duk_hstring **) (void *) (p_base); \
		(set_e_pv) = (duk_propvalue *) (void *) ((set_e_k) + (n_ent)); \
		(set_e_f) = (duk_uint8_t *) (void *) ((set_e_pv) + (n_ent)); \
		(set_a) = (duk_tval *) (void *) ((set_e_f) + (n_ent)); \
		(set_h) = (duk_uint32_t *) (void *) ((set_a) + (n_arr)); \
	} while (0)
#elif defined(DUK_USE_HOBJECT_LAYOUT_2)
/* LAYOUT 2 */
#if (DUK_USE_ALIGN_BY == 4)
#define DUK_HOBJECT_E_FLAG_PADDING(e_sz) ((4 - (e_sz)) & 0x03)
#elif (DUK_USE_ALIGN_BY == 8)
#define DUK_HOBJECT_E_FLAG_PADDING(e_sz) ((8 - (e_sz)) & 0x07)
#elif (DUK_USE_ALIGN_BY == 1)
#define DUK_HOBJECT_E_FLAG_PADDING(e_sz) 0
#else
#error invalid DUK_USE_ALIGN_BY
#endif
#define DUK_HOBJECT_E_GET_KEY_BASE(heap,h) \
	((duk_hstring **) (void *) ( \
		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
			DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_propvalue) \
	))
#define DUK_HOBJECT_E_GET_VALUE_BASE(heap,h) \
	((duk_propvalue *) (void *) ( \
		DUK_HOBJECT_GET_PROPS((heap), (h)) \
	))
#define DUK_HOBJECT_E_GET_FLAGS_BASE(heap,h) \
	((duk_uint8_t *) (void *) ( \
		DUK_HOBJECT_GET_PROPS((heap), (h)) + DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue)) \
	))
#define DUK_HOBJECT_A_GET_BASE(heap,h) \
	((duk_tval *) (void *) ( \
		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
			DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
			DUK_HOBJECT_E_FLAG_PADDING(DUK_HOBJECT_GET_ESIZE((h))) \
	))
#define DUK_HOBJECT_H_GET_BASE(heap,h) \
	((duk_uint32_t *) (void *) ( \
		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
			DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
			DUK_HOBJECT_E_FLAG_PADDING(DUK_HOBJECT_GET_ESIZE((h))) + \
			DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \
	))
#define DUK_HOBJECT_P_COMPUTE_SIZE(n_ent,n_arr,n_hash) \
	( \
		(n_ent) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
		DUK_HOBJECT_E_FLAG_PADDING((n_ent)) + \
		(n_arr) * sizeof(duk_tval) + \
		(n_hash) * sizeof(duk_uint32_t) \
	)
#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 { \
		(set_e_pv) = (duk_propvalue *) (void *) (p_base); \
		(set_e_k) = (duk_hstring **) (void *) ((set_e_pv) + (n_ent)); \
		(set_e_f) = (duk_uint8_t *) (void *) ((set_e_k) + (n_ent)); \
		(set_a) = (duk_tval *) (void *) (((duk_uint8_t *) (set_e_f)) + \
		                                 sizeof(duk_uint8_t) * (n_ent) + \
		                                 DUK_HOBJECT_E_FLAG_PADDING((n_ent))); \
		(set_h) = (duk_uint32_t *) (void *) ((set_a) + (n_arr)); \
	} while (0)
#elif defined(DUK_USE_HOBJECT_LAYOUT_3)
/* LAYOUT 3 */
#define DUK_HOBJECT_E_GET_KEY_BASE(heap,h) \
	((duk_hstring **) (void *) ( \
		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
			DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_propvalue) + \
			DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \
	))
#define DUK_HOBJECT_E_GET_VALUE_BASE(heap,h) \
	((duk_propvalue *) (void *) ( \
		DUK_HOBJECT_GET_PROPS((heap), (h)) \
	))
#define DUK_HOBJECT_E_GET_FLAGS_BASE(heap,h) \
	((duk_uint8_t *) (void *) ( \
		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
			DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_propvalue) + sizeof(duk_hstring *)) + \
			DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) + \
			DUK_HOBJECT_GET_HSIZE((h)) * sizeof(duk_uint32_t) \
	))
#define DUK_HOBJECT_A_GET_BASE(heap,h) \
	((duk_tval *) (void *) ( \
		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
			DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_propvalue) \
	))
#define DUK_HOBJECT_H_GET_BASE(heap,h) \
	((duk_uint32_t *) (void *) ( \
		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
			DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_propvalue) + sizeof(duk_hstring *)) + \
			DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \
	))
#define DUK_HOBJECT_P_COMPUTE_SIZE(n_ent,n_arr,n_hash) \
	( \
		(n_ent) * (sizeof(duk_propvalue) + sizeof(duk_hstring *) + sizeof(duk_uint8_t)) + \
		(n_arr) * sizeof(duk_tval) + \
		(n_hash) * sizeof(duk_uint32_t) \
	)
#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 { \
		(set_e_pv) = (duk_propvalue *) (void *) (p_base); \
		(set_a) = (duk_tval *) (void *) ((set_e_pv) + (n_ent)); \
		(set_e_k) = (duk_hstring **) (void *) ((set_a) + (n_arr)); \
		(set_h) = (duk_uint32_t *) (void *) ((set_e_k) + (n_ent)); \
		(set_e_f) = (duk_uint8_t *) (void *) ((set_h) + (n_hash)); \
	} while (0)
#else
#error invalid hobject layout defines
#endif  /* hobject property layout */

#define DUK_HOBJECT_P_ALLOC_SIZE(h) \
	DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE((h)), DUK_HOBJECT_GET_ASIZE((h)), DUK_HOBJECT_GET_HSIZE((h)))

#define DUK_HOBJECT_E_GET_KEY(heap,h,i)              (DUK_HOBJECT_E_GET_KEY_BASE((heap), (h))[(i)])
#define DUK_HOBJECT_E_GET_KEY_PTR(heap,h,i)          (&DUK_HOBJECT_E_GET_KEY_BASE((heap), (h))[(i)])
#define DUK_HOBJECT_E_GET_VALUE(heap,h,i)            (DUK_HOBJECT_E_GET_VALUE_BASE((heap), (h))[(i)])
#define DUK_HOBJECT_E_GET_VALUE_PTR(heap,h,i)        (&DUK_HOBJECT_E_GET_VALUE_BASE((heap), (h))[(i)])
#define DUK_HOBJECT_E_GET_VALUE_TVAL(heap,h,i)       (DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).v)
#define DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap,h,i)   (&DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).v)
#define DUK_HOBJECT_E_GET_VALUE_GETTER(heap,h,i)     (DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.get)
#define DUK_HOBJECT_E_GET_VALUE_GETTER_PTR(heap,h,i) (&DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.get)
#define DUK_HOBJECT_E_GET_VALUE_SETTER(heap,h,i)     (DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.set)
#define DUK_HOBJECT_E_GET_VALUE_SETTER_PTR(heap,h,i) (&DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.set)
#define DUK_HOBJECT_E_GET_FLAGS(heap,h,i)            (DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)])
#define DUK_HOBJECT_E_GET_FLAGS_PTR(heap,h,i)        (&DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)])
#define DUK_HOBJECT_A_GET_VALUE(heap,h,i)            (DUK_HOBJECT_A_GET_BASE((heap), (h))[(i)])
#define DUK_HOBJECT_A_GET_VALUE_PTR(heap,h,i)        (&DUK_HOBJECT_A_GET_BASE((heap), (h))[(i)])
#define DUK_HOBJECT_H_GET_INDEX(heap,h,i)            (DUK_HOBJECT_H_GET_BASE((heap), (h))[(i)])
#define DUK_HOBJECT_H_GET_INDEX_PTR(heap,h,i)        (&DUK_HOBJECT_H_GET_BASE((heap), (h))[(i)])

#define DUK_HOBJECT_E_SET_KEY(heap,h,i,k)  do { \
		DUK_HOBJECT_E_GET_KEY((heap), (h), (i)) = (k); \
	} while (0)
#define DUK_HOBJECT_E_SET_VALUE(heap,h,i,v)  do { \
		DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)) = (v); \
	} while (0)
#define DUK_HOBJECT_E_SET_VALUE_TVAL(heap,h,i,v)  do { \
		DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).v = (v); \
	} while (0)
#define DUK_HOBJECT_E_SET_VALUE_GETTER(heap,h,i,v)  do { \
		DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.get = (v); \
	} while (0)
#define DUK_HOBJECT_E_SET_VALUE_SETTER(heap,h,i,v)  do { \
		DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.set = (v); \
	} while (0)
#define DUK_HOBJECT_E_SET_FLAGS(heap,h,i,f)  do { \
		DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) = (duk_uint8_t) (f); \
	} while (0)
#define DUK_HOBJECT_A_SET_VALUE(heap,h,i,v)  do { \
		DUK_HOBJECT_A_GET_VALUE((heap), (h), (i)) = (v); \
	} while (0)
#define DUK_HOBJECT_A_SET_VALUE_TVAL(heap,h,i,v) \
	DUK_HOBJECT_A_SET_VALUE((heap), (h), (i), (v))  /* alias for above */
#define DUK_HOBJECT_H_SET_INDEX(heap,h,i,v)  do { \
		DUK_HOBJECT_H_GET_INDEX((heap), (h), (i)) = (v); \
	} while (0)

#define DUK_HOBJECT_E_SET_FLAG_BITS(heap,h,i,mask)  do { \
		DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)] |= (mask); \
	} while (0)

#define DUK_HOBJECT_E_CLEAR_FLAG_BITS(heap,h,i,mask)  do { \
		DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)] &= ~(mask); \
	} while (0)

#define DUK_HOBJECT_E_SLOT_IS_WRITABLE(heap,h,i)     ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_WRITABLE) != 0)
#define DUK_HOBJECT_E_SLOT_IS_ENUMERABLE(heap,h,i)   ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_ENUMERABLE) != 0)
#define DUK_HOBJECT_E_SLOT_IS_CONFIGURABLE(heap,h,i) ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_CONFIGURABLE) != 0)
#define DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap,h,i)     ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_ACCESSOR) != 0)

#define DUK_HOBJECT_E_SLOT_SET_WRITABLE(heap,h,i)        DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_WRITABLE)
#define DUK_HOBJECT_E_SLOT_SET_ENUMERABLE(heap,h,i)      DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ENUMERABLE)
#define DUK_HOBJECT_E_SLOT_SET_CONFIGURABLE(heap,h,i)    DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_CONFIGURABLE)
#define DUK_HOBJECT_E_SLOT_SET_ACCESSOR(heap,h,i)        DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ACCESSOR)

#define DUK_HOBJECT_E_SLOT_CLEAR_WRITABLE(heap,h,i)      DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_WRITABLE)
#define DUK_HOBJECT_E_SLOT_CLEAR_ENUMERABLE(heap,h,i)    DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ENUMERABLE)
#define DUK_HOBJECT_E_SLOT_CLEAR_CONFIGURABLE(heap,h,i)  DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_CONFIGURABLE)
#define DUK_HOBJECT_E_SLOT_CLEAR_ACCESSOR(heap,h,i)      DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ACCESSOR)

#define DUK_PROPDESC_IS_WRITABLE(p)             (((p)->flags & DUK_PROPDESC_FLAG_WRITABLE) != 0)
#define DUK_PROPDESC_IS_ENUMERABLE(p)           (((p)->flags & DUK_PROPDESC_FLAG_ENUMERABLE) != 0)
#define DUK_PROPDESC_IS_CONFIGURABLE(p)         (((p)->flags & DUK_PROPDESC_FLAG_CONFIGURABLE) != 0)
#define DUK_PROPDESC_IS_ACCESSOR(p)             (((p)->flags & DUK_PROPDESC_FLAG_ACCESSOR) != 0)

#define DUK_HOBJECT_HASHIDX_UNUSED              0xffffffffUL
#define DUK_HOBJECT_HASHIDX_DELETED             0xfffffffeUL

/*
 *  Macros for accessing size fields
 */

#if defined(DUK_USE_OBJSIZES16)
#define DUK_HOBJECT_GET_ESIZE(h) ((h)->e_size16)
#define DUK_HOBJECT_SET_ESIZE(h,v) do { (h)->e_size16 = (v); } while (0)
#define DUK_HOBJECT_GET_ENEXT(h) ((h)->e_next16)
#define DUK_HOBJECT_SET_ENEXT(h,v) do { (h)->e_next16 = (v); } while (0)
#define DUK_HOBJECT_POSTINC_ENEXT(h) ((h)->e_next16++)
#define DUK_HOBJECT_GET_ASIZE(h) ((h)->a_size16)
#define DUK_HOBJECT_SET_ASIZE(h,v) do { (h)->a_size16 = (v); } while (0)
#if defined(DUK_USE_HOBJECT_HASH_PART)
#define DUK_HOBJECT_GET_HSIZE(h) ((h)->h_size16)
#define DUK_HOBJECT_SET_HSIZE(h,v) do { (h)->h_size16 = (v); } while (0)
#else
#define DUK_HOBJECT_GET_HSIZE(h) 0
#define DUK_HOBJECT_SET_HSIZE(h,v) do { DUK_ASSERT((v) == 0); } while (0)
#endif
#else
#define DUK_HOBJECT_GET_ESIZE(h) ((h)->e_size)
#define DUK_HOBJECT_SET_ESIZE(h,v) do { (h)->e_size = (v); } while (0)
#define DUK_HOBJECT_GET_ENEXT(h) ((h)->e_next)
#define DUK_HOBJECT_SET_ENEXT(h,v) do { (h)->e_next = (v); } while (0)
#define DUK_HOBJECT_POSTINC_ENEXT(h) ((h)->e_next++)
#define DUK_HOBJECT_GET_ASIZE(h) ((h)->a_size)
#define DUK_HOBJECT_SET_ASIZE(h,v) do { (h)->a_size = (v); } while (0)
#if defined(DUK_USE_HOBJECT_HASH_PART)
#define DUK_HOBJECT_GET_HSIZE(h) ((h)->h_size)
#define DUK_HOBJECT_SET_HSIZE(h,v) do { (h)->h_size = (v); } while (0)
#else
#define DUK_HOBJECT_GET_HSIZE(h) 0
#define DUK_HOBJECT_SET_HSIZE(h,v) do { DUK_ASSERT((v) == 0); } while (0)
#endif
#endif

/*
 *  Misc
 */

/* Maximum prototype traversal depth.  Sanity limit which handles e.g.
 * prototype loops (even complex ones like 1->2->3->4->2->3->4->2->3->4).
 */
#define DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY      10000L

/*
 *  ECMAScript [[Class]]
 */

/* range check not necessary because all 4-bit values are mapped */
#define DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(n)  duk_class_number_to_stridx[(n)]

#define DUK_HOBJECT_GET_CLASS_STRING(heap,h)          \
	DUK_HEAP_GET_STRING( \
		(heap), \
		DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(DUK_HOBJECT_GET_CLASS_NUMBER((h))) \
	)

/*
 *  Macros for property handling
 */

#if defined(DUK_USE_HEAPPTR16)
#define DUK_HOBJECT_GET_PROTOTYPE(heap,h) \
	((duk_hobject *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->prototype16))
#define DUK_HOBJECT_SET_PROTOTYPE(heap,h,x) do { \
		(h)->prototype16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (x)); \
	} while (0)
#else
#define DUK_HOBJECT_GET_PROTOTYPE(heap,h) \
	((h)->prototype)
#define DUK_HOBJECT_SET_PROTOTYPE(heap,h,x) do { \
		(h)->prototype = (x); \
	} while (0)
#endif

/* Set prototype, DECREF earlier value, INCREF new value (tolerating NULLs). */
#define DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr,h,p)       duk_hobject_set_prototype_updref((thr), (h), (p))

/* Set initial prototype, assume NULL previous prototype, INCREF new value,
 * tolerate NULL.
 */
#define DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr,h,proto) do { \
		duk_hthread *duk__thr = (thr); \
		duk_hobject *duk__obj = (h); \
		duk_hobject *duk__proto = (proto); \
		DUK_UNREF(duk__thr); \
		DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(duk__thr->heap, duk__obj) == NULL); \
		DUK_HOBJECT_SET_PROTOTYPE(duk__thr->heap, duk__obj, duk__proto); \
		DUK_HOBJECT_INCREF_ALLOWNULL(duk__thr, duk__proto); \
	} while (0)

/*
 *  Finalizer check
 */

#if defined(DUK_USE_HEAPPTR16)
#define DUK_HOBJECT_HAS_FINALIZER_FAST(heap,h) duk_hobject_has_finalizer_fast_raw((heap), (h))
#else
#define DUK_HOBJECT_HAS_FINALIZER_FAST(heap,h) duk_hobject_has_finalizer_fast_raw((h))
#endif

/*
 *  Resizing and hash behavior
 */

/* Sanity limit on max number of properties (allocated, not necessarily used).
 * This is somewhat arbitrary, but if we're close to 2**32 properties some
 * algorithms will fail (e.g. hash size selection, next prime selection).
 * Also, we use negative array/entry table indices to indicate 'not found',
 * so anything above 0x80000000 will cause trouble now.
 */
#if defined(DUK_USE_OBJSIZES16)
#define DUK_HOBJECT_MAX_PROPERTIES       0x0000ffffUL
#else
#define DUK_HOBJECT_MAX_PROPERTIES       0x3fffffffUL   /* 2**30-1 ~= 1G properties */
#endif

/* internal align target for props allocation, must be 2*n for some n */
#if (DUK_USE_ALIGN_BY == 4)
#define DUK_HOBJECT_ALIGN_TARGET         4
#elif (DUK_USE_ALIGN_BY == 8)
#define DUK_HOBJECT_ALIGN_TARGET         8
#elif (DUK_USE_ALIGN_BY == 1)
#define DUK_HOBJECT_ALIGN_TARGET         1
#else
#error invalid DUK_USE_ALIGN_BY
#endif

/*
 *  PC-to-line constants
 */

#define DUK_PC2LINE_SKIP    64

/* maximum length for a SKIP-1 diffstream: 35 bits per entry, rounded up to bytes */
#define DUK_PC2LINE_MAX_DIFF_LENGTH    (((DUK_PC2LINE_SKIP - 1) * 35 + 7) / 8)

/*
 *  Struct defs
 */

struct duk_propaccessor {
	duk_hobject *get;
	duk_hobject *set;
};

union duk_propvalue {
	/* The get/set pointers could be 16-bit pointer compressed but it
	 * would make no difference on 32-bit platforms because duk_tval is
	 * 8 bytes or more anyway.
	 */
	duk_tval v;
	duk_propaccessor a;
};

struct duk_propdesc {
	/* read-only values 'lifted' for ease of use */
	duk_small_uint_t flags;
	duk_hobject *get;
	duk_hobject *set;

	/* for updating (all are set to < 0 for virtual properties) */
	duk_int_t e_idx;  /* prop index in 'entry part', < 0 if not there */
	duk_int_t h_idx;  /* prop index in 'hash part', < 0 if not there */
	duk_int_t a_idx;  /* prop index in 'array part', < 0 if not there */
};

struct duk_hobject {
	duk_heaphdr hdr;

	/*
	 *  'props' contains {key,value,flags} entries, optional array entries, and
	 *  an optional hash lookup table for non-array entries in a single 'sliced'
	 *  allocation.  There are several layout options, which differ slightly in
	 *  generated code size/speed and alignment/padding; duk_features.h selects
	 *  the layout used.
	 *
	 *  Layout 1 (DUK_USE_HOBJECT_LAYOUT_1):
	 *
	 *    e_size * sizeof(duk_hstring *)         bytes of   entry keys (e_next gc reachable)
	 *    e_size * sizeof(duk_propvalue)         bytes of   entry values (e_next gc reachable)
	 *    e_size * sizeof(duk_uint8_t)           bytes of   entry flags (e_next gc reachable)
	 *    a_size * sizeof(duk_tval)              bytes of   (opt) array values (plain only) (all gc reachable)
	 *    h_size * sizeof(duk_uint32_t)          bytes of   (opt) hash indexes to entries (e_size),
	 *                                                      0xffffffffUL = unused, 0xfffffffeUL = deleted
	 *
	 *  Layout 2 (DUK_USE_HOBJECT_LAYOUT_2):
	 *
	 *    e_size * sizeof(duk_propvalue)         bytes of   entry values (e_next gc reachable)
	 *    e_size * sizeof(duk_hstring *)         bytes of   entry keys (e_next gc reachable)
	 *    e_size * sizeof(duk_uint8_t) + pad     bytes of   entry flags (e_next gc reachable)
	 *    a_size * sizeof(duk_tval)              bytes of   (opt) array values (plain only) (all gc reachable)
	 *    h_size * sizeof(duk_uint32_t)          bytes of   (opt) hash indexes to entries (e_size),
	 *                                                      0xffffffffUL = unused, 0xfffffffeUL = deleted
	 *
	 *  Layout 3 (DUK_USE_HOBJECT_LAYOUT_3):
	 *
	 *    e_size * sizeof(duk_propvalue)         bytes of   entry values (e_next gc reachable)
	 *    a_size * sizeof(duk_tval)              bytes of   (opt) array values (plain only) (all gc reachable)
	 *    e_size * sizeof(duk_hstring *)         bytes of   entry keys (e_next gc reachable)
	 *    h_size * sizeof(duk_uint32_t)          bytes of   (opt) hash indexes to entries (e_size),
	 *                                                      0xffffffffUL = unused, 0xfffffffeUL = deleted
	 *    e_size * sizeof(duk_uint8_t)           bytes of   entry flags (e_next gc reachable)
	 *
	 *  In layout 1, the 'e_next' count is rounded to 4 or 8 on platforms
	 *  requiring 4 or 8 byte alignment.  This ensures proper alignment
	 *  for the entries, at the cost of memory footprint.  However, it's
	 *  probably preferable to use another layout on such platforms instead.
	 *
	 *  In layout 2, the key and value parts are swapped to avoid padding
	 *  the key array on platforms requiring alignment by 8.  The flags part
	 *  is padded to get alignment for array entries.  The 'e_next' count does
	 *  not need to be rounded as in layout 1.
	 *
	 *  In layout 3, entry values and array values are always aligned properly,
	 *  and assuming pointers are at most 8 bytes, so are the entry keys.  Hash
	 *  indices will be properly aligned (assuming pointers are at least 4 bytes).
	 *  Finally, flags don't need additional alignment.  This layout provides
	 *  compact allocations without padding (even on platforms with alignment
	 *  requirements) at the cost of a bit slower lookups.
	 *
	 *  Objects with few keys don't have a hash index; keys are looked up linearly,
	 *  which is cache efficient because the keys are consecutive.  Larger objects
	 *  have a hash index part which contains integer indexes to the entries part.
	 *
	 *  A single allocation reduces memory allocation overhead but requires more
	 *  work when any part needs to be resized.  A sliced allocation for entries
	 *  makes linear key matching faster on most platforms (more locality) and
	 *  skimps on flags size (which would be followed by 3 bytes of padding in
	 *  most architectures if entries were placed in a struct).
	 *
	 *  'props' also contains internal properties distinguished with a non-BMP
	 *  prefix.  Often used properties should be placed early in 'props' whenever
	 *  possible to make accessing them as fast a possible.
	 */

#if defined(DUK_USE_HEAPPTR16)
	/* Located in duk_heaphdr h_extra16.  Subclasses of duk_hobject (like
	 * duk_hcompfunc) are not free to use h_extra16 for this reason.
	 */
#else
	duk_uint8_t *props;
#endif

	/* prototype: the only internal property lifted outside 'e' as it is so central */
#if defined(DUK_USE_HEAPPTR16)
	duk_uint16_t prototype16;
#else
	duk_hobject *prototype;
#endif

#if defined(DUK_USE_OBJSIZES16)
	duk_uint16_t e_size16;
	duk_uint16_t e_next16;
	duk_uint16_t a_size16;
#if defined(DUK_USE_HOBJECT_HASH_PART)
	duk_uint16_t h_size16;
#endif
#else
	duk_uint32_t e_size;  /* entry part size */
	duk_uint32_t e_next;  /* index for next new key ([0,e_next[ are gc reachable) */
	duk_uint32_t a_size;  /* array part size (entirely gc reachable) */
#if defined(DUK_USE_HOBJECT_HASH_PART)
	duk_uint32_t h_size;  /* hash part size or 0 if unused */
#endif
#endif
};

/*
 *  Exposed data
 */

#if !defined(DUK_SINGLE_FILE)
DUK_INTERNAL_DECL duk_uint8_t duk_class_number_to_stridx[32];
#endif  /* !DUK_SINGLE_FILE */

/*
 *  Prototypes
 */

/* alloc and init */
DUK_INTERNAL_DECL duk_hobject *duk_hobject_alloc_unchecked(duk_heap *heap, duk_uint_t hobject_flags);
DUK_INTERNAL_DECL duk_hobject *duk_hobject_alloc(duk_hthread *thr, duk_uint_t hobject_flags);
DUK_INTERNAL_DECL duk_harray *duk_harray_alloc(duk_hthread *thr, duk_uint_t hobject_flags);
DUK_INTERNAL_DECL duk_hcompfunc *duk_hcompfunc_alloc(duk_hthread *thr, duk_uint_t hobject_flags);
DUK_INTERNAL_DECL duk_hnatfunc *duk_hnatfunc_alloc(duk_hthread *thr, duk_uint_t hobject_flags);
DUK_INTERNAL_DECL duk_hboundfunc *duk_hboundfunc_alloc(duk_heap *heap, duk_uint_t hobject_flags);
#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
DUK_INTERNAL_DECL duk_hbufobj *duk_hbufobj_alloc(duk_hthread *thr, duk_uint_t hobject_flags);
#endif
DUK_INTERNAL_DECL duk_hthread *duk_hthread_alloc_unchecked(duk_heap *heap, duk_uint_t hobject_flags);
DUK_INTERNAL_DECL duk_hthread *duk_hthread_alloc(duk_hthread *thr, duk_uint_t hobject_flags);
DUK_INTERNAL_DECL duk_hdecenv *duk_hdecenv_alloc(duk_hthread *thr, duk_uint_t hobject_flags);
DUK_INTERNAL_DECL duk_hobjenv *duk_hobjenv_alloc(duk_hthread *thr, duk_uint_t hobject_flags);
DUK_INTERNAL_DECL duk_hproxy *duk_hproxy_alloc(duk_hthread *thr, duk_uint_t hobject_flags);

/* resize */
DUK_INTERNAL_DECL void duk_hobject_realloc_props(duk_hthread *thr,
                                                 duk_hobject *obj,
                                                 duk_uint32_t new_e_size,
                                                 duk_uint32_t new_a_size,
                                                 duk_uint32_t new_h_size,
                                                 duk_bool_t abandon_array);
DUK_INTERNAL_DECL void duk_hobject_resize_entrypart(duk_hthread *thr,
                                                    duk_hobject *obj,
                                                    duk_uint32_t new_e_size);
#if 0  /*unused*/
DUK_INTERNAL_DECL void duk_hobject_resize_arraypart(duk_hthread *thr,
                                                    duk_hobject *obj,
                                                    duk_uint32_t new_a_size);
#endif

/* low-level property functions */
DUK_INTERNAL_DECL duk_bool_t duk_hobject_find_entry(duk_heap *heap, duk_hobject *obj, duk_hstring *key, duk_int_t *e_idx, duk_int_t *h_idx);
DUK_INTERNAL_DECL duk_tval *duk_hobject_find_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_hstring *key);
DUK_INTERNAL_DECL duk_tval *duk_hobject_find_entry_tval_ptr_stridx(duk_heap *heap, duk_hobject *obj, duk_small_uint_t stridx);
DUK_INTERNAL_DECL duk_tval *duk_hobject_find_entry_tval_ptr_and_attrs(duk_heap *heap, duk_hobject *obj, duk_hstring *key, duk_uint_t *out_attrs);
DUK_INTERNAL_DECL duk_tval *duk_hobject_find_array_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_uarridx_t i);
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);

/* core property functions */
DUK_INTERNAL_DECL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key);
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);
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);
DUK_INTERNAL_DECL duk_bool_t duk_hobject_hasprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key);

/* internal property functions */
#define DUK_DELPROP_FLAG_THROW  (1U << 0)
#define DUK_DELPROP_FLAG_FORCE  (1U << 1)
DUK_INTERNAL_DECL duk_bool_t duk_hobject_delprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags);
DUK_INTERNAL_DECL duk_bool_t duk_hobject_hasprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key);
DUK_INTERNAL_DECL void duk_hobject_define_property_internal(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags);
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);
DUK_INTERNAL_DECL duk_size_t duk_hobject_get_length(duk_hthread *thr, duk_hobject *obj);
#if defined(DUK_USE_HEAPPTR16)
DUK_INTERNAL_DECL duk_bool_t duk_hobject_has_finalizer_fast_raw(duk_heap *heap, duk_hobject *obj);
#else
DUK_INTERNAL_DECL duk_bool_t duk_hobject_has_finalizer_fast_raw(duk_hobject *obj);
#endif

/* helpers for defineProperty() and defineProperties() */
DUK_INTERNAL_DECL void duk_hobject_prepare_property_descriptor(duk_hthread *thr,
                                                               duk_idx_t idx_in,
                                                               duk_uint_t *out_defprop_flags,
                                                               duk_idx_t *out_idx_value,
                                                               duk_hobject **out_getter,
                                                               duk_hobject **out_setter);
DUK_INTERNAL_DECL duk_bool_t duk_hobject_define_property_helper(duk_hthread *thr,
                                                                duk_uint_t defprop_flags,
                                                                duk_hobject *obj,
                                                                duk_hstring *key,
                                                                duk_idx_t idx_value,
                                                                duk_hobject *get,
                                                                duk_hobject *set,
                                                                duk_bool_t throw_flag);

/* Object built-in methods */
DUK_INTERNAL_DECL void duk_hobject_object_get_own_property_descriptor(duk_hthread *thr, duk_idx_t obj_idx);
DUK_INTERNAL_DECL void duk_hobject_object_seal_freeze_helper(duk_hthread *thr, duk_hobject *obj, duk_bool_t is_freeze);
DUK_INTERNAL_DECL duk_bool_t duk_hobject_object_is_sealed_frozen_helper(duk_hthread *thr, duk_hobject *obj, duk_bool_t is_frozen);
DUK_INTERNAL_DECL duk_bool_t duk_hobject_object_ownprop_helper(duk_hthread *thr, duk_small_uint_t required_desc_flags);

/* internal properties */
DUK_INTERNAL_DECL duk_tval *duk_hobject_get_internal_value_tval_ptr(duk_heap *heap, duk_hobject *obj);
DUK_INTERNAL_DECL duk_hstring *duk_hobject_get_internal_value_string(duk_heap *heap, duk_hobject *obj);
DUK_INTERNAL_DECL duk_harray *duk_hobject_get_formals(duk_hthread *thr, duk_hobject *obj);
DUK_INTERNAL_DECL duk_hobject *duk_hobject_get_varmap(duk_hthread *thr, duk_hobject *obj);

/* hobject management functions */
DUK_INTERNAL_DECL void duk_hobject_compact_props(duk_hthread *thr, duk_hobject *obj);

/* ES2015 proxy */
#if defined(DUK_USE_ES6_PROXY)
DUK_INTERNAL_DECL duk_bool_t duk_hobject_proxy_check(duk_hobject *obj, duk_hobject **out_target, duk_hobject **out_handler);
DUK_INTERNAL_DECL duk_hobject *duk_hobject_resolve_proxy_target(duk_hobject *obj);
#endif

/* enumeration */
DUK_INTERNAL_DECL void duk_hobject_enumerator_create(duk_hthread *thr, duk_small_uint_t enum_flags);
DUK_INTERNAL_DECL duk_ret_t duk_hobject_get_enumerated_keys(duk_hthread *thr, duk_small_uint_t enum_flags);
DUK_INTERNAL_DECL duk_bool_t duk_hobject_enumerator_next(duk_hthread *thr, duk_bool_t get_value);

/* macros */
DUK_INTERNAL_DECL void duk_hobject_set_prototype_updref(duk_hthread *thr, duk_hobject *h, duk_hobject *p);

/* pc2line */
#if defined(DUK_USE_PC2LINE)
DUK_INTERNAL_DECL void duk_hobject_pc2line_pack(duk_hthread *thr, duk_compiler_instr *instrs, duk_uint_fast32_t length);
DUK_INTERNAL_DECL duk_uint_fast32_t duk_hobject_pc2line_query(duk_hthread *thr, duk_idx_t idx_func, duk_uint_fast32_t pc);
#endif

/* misc */
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);

#if !defined(DUK_USE_OBJECT_BUILTIN)
/* These declarations are needed when related built-in is disabled and
 * genbuiltins.py won't automatically emit the declerations.
 */
DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_to_string(duk_hthread *thr);
DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype(duk_hthread *thr);
#endif

#endif  /* DUK_HOBJECT_H_INCLUDED */
/* #include duk_hcompfunc.h */
#line 1 "duk_hcompfunc.h"
/*
 *  Heap compiled function (ECMAScript function) representation.
 *
 *  There is a single data buffer containing the ECMAScript function's
 *  bytecode, constants, and inner functions.
 */

#if !defined(DUK_HCOMPFUNC_H_INCLUDED)
#define DUK_HCOMPFUNC_H_INCLUDED

/*
 *  Field accessor macros
 */

/* XXX: casts could be improved, especially for GET/SET DATA */

#if defined(DUK_USE_HEAPPTR16)
#define DUK_HCOMPFUNC_GET_DATA(heap,h) \
	((duk_hbuffer_fixed *) (void *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->data16))
#define DUK_HCOMPFUNC_SET_DATA(heap,h,v) do { \
		(h)->data16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
	} while (0)
#define DUK_HCOMPFUNC_GET_FUNCS(heap,h)  \
	((duk_hobject **) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->funcs16)))
#define DUK_HCOMPFUNC_SET_FUNCS(heap,h,v)  do { \
		(h)->funcs16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
	} while (0)
#define DUK_HCOMPFUNC_GET_BYTECODE(heap,h)  \
	((duk_instr_t *) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->bytecode16)))
#define DUK_HCOMPFUNC_SET_BYTECODE(heap,h,v)  do { \
		(h)->bytecode16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
	} while (0)
#define DUK_HCOMPFUNC_GET_LEXENV(heap,h)  \
	((duk_hobject *) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->lex_env16)))
#define DUK_HCOMPFUNC_SET_LEXENV(heap,h,v)  do { \
		(h)->lex_env16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
	} while (0)
#define DUK_HCOMPFUNC_GET_VARENV(heap,h)  \
	((duk_hobject *) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->var_env16)))
#define DUK_HCOMPFUNC_SET_VARENV(heap,h,v)  do { \
		(h)->var_env16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
	} while (0)
#else
#define DUK_HCOMPFUNC_GET_DATA(heap,h)  ((duk_hbuffer_fixed *) (void *) (h)->data)
#define DUK_HCOMPFUNC_SET_DATA(heap,h,v) do { \
		(h)->data = (duk_hbuffer *) (v); \
	} while (0)
#define DUK_HCOMPFUNC_GET_FUNCS(heap,h)  ((h)->funcs)
#define DUK_HCOMPFUNC_SET_FUNCS(heap,h,v)  do { \
		(h)->funcs = (v); \
	} while (0)
#define DUK_HCOMPFUNC_GET_BYTECODE(heap,h)  ((h)->bytecode)
#define DUK_HCOMPFUNC_SET_BYTECODE(heap,h,v)  do { \
		(h)->bytecode = (v); \
	} while (0)
#define DUK_HCOMPFUNC_GET_LEXENV(heap,h)  ((h)->lex_env)
#define DUK_HCOMPFUNC_SET_LEXENV(heap,h,v)  do { \
		(h)->lex_env = (v); \
	} while (0)
#define DUK_HCOMPFUNC_GET_VARENV(heap,h)  ((h)->var_env)
#define DUK_HCOMPFUNC_SET_VARENV(heap,h,v)  do { \
		(h)->var_env = (v); \
	} while (0)
#endif

/*
 *  Accessor macros for function specific data areas
 */

/* Note: assumes 'data' is always a fixed buffer */
#define DUK_HCOMPFUNC_GET_BUFFER_BASE(heap,h)  \
	DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), DUK_HCOMPFUNC_GET_DATA((heap), (h)))

#define DUK_HCOMPFUNC_GET_CONSTS_BASE(heap,h)  \
	((duk_tval *) (void *) DUK_HCOMPFUNC_GET_BUFFER_BASE((heap), (h)))

#define DUK_HCOMPFUNC_GET_FUNCS_BASE(heap,h)  \
	DUK_HCOMPFUNC_GET_FUNCS((heap), (h))

#define DUK_HCOMPFUNC_GET_CODE_BASE(heap,h)  \
	DUK_HCOMPFUNC_GET_BYTECODE((heap), (h))

#define DUK_HCOMPFUNC_GET_CONSTS_END(heap,h)  \
	((duk_tval *) (void *) DUK_HCOMPFUNC_GET_FUNCS((heap), (h)))

#define DUK_HCOMPFUNC_GET_FUNCS_END(heap,h)  \
	((duk_hobject **) (void *) DUK_HCOMPFUNC_GET_BYTECODE((heap), (h)))

/* XXX: double evaluation of DUK_HCOMPFUNC_GET_DATA() */
#define DUK_HCOMPFUNC_GET_CODE_END(heap,h)  \
	((duk_instr_t *) (void *) (DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), DUK_HCOMPFUNC_GET_DATA((heap), (h))) + \
	                DUK_HBUFFER_GET_SIZE((duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA((heap), h))))

#define DUK_HCOMPFUNC_GET_CONSTS_SIZE(heap,h)  \
	( \
	 (duk_size_t) \
	 ( \
	   ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_CONSTS_END((heap), (h))) - \
	   ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_CONSTS_BASE((heap), (h))) \
	 ) \
	)

#define DUK_HCOMPFUNC_GET_FUNCS_SIZE(heap,h)  \
	( \
	 (duk_size_t) \
	 ( \
	   ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_FUNCS_END((heap), (h))) - \
	   ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_FUNCS_BASE((heap), (h))) \
	 ) \
	)

#define DUK_HCOMPFUNC_GET_CODE_SIZE(heap,h)  \
	( \
	 (duk_size_t) \
	 ( \
	   ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_CODE_END((heap),(h))) - \
	   ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_CODE_BASE((heap),(h))) \
	 ) \
	)

#define DUK_HCOMPFUNC_GET_CONSTS_COUNT(heap,h)  \
	((duk_size_t) (DUK_HCOMPFUNC_GET_CONSTS_SIZE((heap), (h)) / sizeof(duk_tval)))

#define DUK_HCOMPFUNC_GET_FUNCS_COUNT(heap,h)  \
	((duk_size_t) (DUK_HCOMPFUNC_GET_FUNCS_SIZE((heap), (h)) / sizeof(duk_hobject *)))

#define DUK_HCOMPFUNC_GET_CODE_COUNT(heap,h)  \
	((duk_size_t) (DUK_HCOMPFUNC_GET_CODE_SIZE((heap), (h)) / sizeof(duk_instr_t)))

/*
 *  Validity assert
 */

#if defined(DUK_USE_ASSERTIONS)
DUK_INTERNAL_DECL void duk_hcompfunc_assert_valid(duk_hcompfunc *h);
#define DUK_HCOMPFUNC_ASSERT_VALID(h)  do { duk_hcompfunc_assert_valid((h)); } while (0)
#else
#define DUK_HCOMPFUNC_ASSERT_VALID(h)  do {} while (0)
#endif

/*
 *  Main struct
 */

struct duk_hcompfunc {
	/* shared object part */
	duk_hobject obj;

	/*
	 *  Pointers to function data area for faster access.  Function
	 *  data is a buffer shared between all closures of the same
	 *  "template" function.  The data buffer is always fixed (non-
	 *  dynamic, hence stable), with a layout as follows:
	 *
	 *    constants (duk_tval)
	 *    inner functions (duk_hobject *)
	 *    bytecode (duk_instr_t)
	 *
	 *  Note: bytecode end address can be computed from 'data' buffer
	 *  size.  It is not strictly necessary functionally, assuming
	 *  bytecode never jumps outside its allocated area.  However,
	 *  it's a safety/robustness feature for avoiding the chance of
	 *  executing random data as bytecode due to a compiler error.
	 *
	 *  Note: values in the data buffer must be incref'd (they will
	 *  be decref'd on release) for every compiledfunction referring
	 *  to the 'data' element.
	 */

	/* Data area, fixed allocation, stable data ptrs. */
#if defined(DUK_USE_HEAPPTR16)
	duk_uint16_t data16;
#else
	duk_hbuffer *data;
#endif

	/* No need for constants pointer (= same as data).
	 *
	 * When using 16-bit packing alignment to 4 is nice.  'funcs' will be
	 * 4-byte aligned because 'constants' are duk_tvals.  For now the
	 * inner function pointers are not compressed, so that 'bytecode' will
	 * also be 4-byte aligned.
	 */
#if defined(DUK_USE_HEAPPTR16)
	duk_uint16_t funcs16;
	duk_uint16_t bytecode16;
#else
	duk_hobject **funcs;
	duk_instr_t *bytecode;
#endif

	/* Lexenv: lexical environment of closure, NULL for templates.
	 * Varenv: variable environment of closure, NULL for templates.
	 */
#if defined(DUK_USE_HEAPPTR16)
	duk_uint16_t lex_env16;
	duk_uint16_t var_env16;
#else
	duk_hobject *lex_env;
	duk_hobject *var_env;
#endif

	/*
	 *  'nregs' registers are allocated on function entry, at most 'nargs'
	 *  are initialized to arguments, and the rest to undefined.  Arguments
	 *  above 'nregs' are not mapped to registers.  All registers in the
	 *  active stack range must be initialized because they are GC reachable.
	 *  'nargs' is needed so that if the function is given more than 'nargs'
	 *  arguments, the additional arguments do not 'clobber' registers
	 *  beyond 'nregs' which must be consistently initialized to undefined.
	 *
	 *  Usually there is no need to know which registers are mapped to
	 *  local variables.  Registers may be allocated to variable in any
	 *  way (even including gaps).  However, a register-variable mapping
	 *  must be the same for the duration of the function execution and
	 *  the register cannot be used for anything else.
	 *
	 *  When looking up variables by name, the '_Varmap' map is used.
	 *  When an activation closes, registers mapped to arguments are
	 *  copied into the environment record based on the same map.  The
	 *  reverse map (from register to variable) is not currently needed
	 *  at run time, except for debugging, so it is not maintained.
	 */

	duk_uint16_t nregs;                /* regs to allocate */
	duk_uint16_t nargs;                /* number of arguments allocated to regs */

	/*
	 *  Additional control information is placed into the object itself
	 *  as internal properties to avoid unnecessary fields for the
	 *  majority of functions.  The compiler tries to omit internal
	 *  control fields when possible.
	 *
	 *  Function templates:
	 *
	 *    {
	 *      name: "func",    // declaration, named function expressions
	 *      fileName: <debug info for creating nice errors>
	 *      _Varmap: { "arg1": 0, "arg2": 1, "varname": 2 },
	 *      _Formals: [ "arg1", "arg2" ],
	 *      _Source: "function func(arg1, arg2) { ... }",
	 *      _Pc2line: <debug info for pc-to-line mapping>,
	 *    }
	 *
	 *  Function instances:
	 *
	 *    {
	 *      length: 2,
	 *      prototype: { constructor: <func> },
	 *      caller: <thrower>,
	 *      arguments: <thrower>,
	 *      name: "func",    // declaration, named function expressions
	 *      fileName: <debug info for creating nice errors>
	 *      _Varmap: { "arg1": 0, "arg2": 1, "varname": 2 },
	 *      _Formals: [ "arg1", "arg2" ],
	 *      _Source: "function func(arg1, arg2) { ... }",
	 *      _Pc2line: <debug info for pc-to-line mapping>,
	 *    }
	 *
	 *  More detailed description of these properties can be found
	 *  in the documentation.
	 */

#if defined(DUK_USE_DEBUGGER_SUPPORT)
	/* Line number range for function.  Needed during debugging to
	 * determine active breakpoints.
	 */
	duk_uint32_t start_line;
	duk_uint32_t end_line;
#endif
};

#endif  /* DUK_HCOMPFUNC_H_INCLUDED */
/* #include duk_hnatfunc.h */
#line 1 "duk_hnatfunc.h"
/*
 *  Heap native function representation.
 */

#if !defined(DUK_HNATFUNC_H_INCLUDED)
#define DUK_HNATFUNC_H_INCLUDED

#if defined(DUK_USE_ASSERTIONS)
DUK_INTERNAL_DECL void duk_hnatfunc_assert_valid(duk_hnatfunc *h);
#define DUK_HNATFUNC_ASSERT_VALID(h)  do { duk_hnatfunc_assert_valid((h)); } while (0)
#else
#define DUK_HNATFUNC_ASSERT_VALID(h)  do {} while (0)
#endif

#define DUK_HNATFUNC_NARGS_VARARGS  ((duk_int16_t) -1)
#define DUK_HNATFUNC_NARGS_MAX      ((duk_int16_t) 0x7fff)

struct duk_hnatfunc {
	/* shared object part */
	duk_hobject obj;

	duk_c_function func;
	duk_int16_t nargs;
	duk_int16_t magic;

	/* The 'magic' field allows an opaque 16-bit field to be accessed by the
	 * Duktape/C function.  This allows, for instance, the same native function
	 * to be used for a set of very similar functions, with the 'magic' field
	 * providing the necessary non-argument flags / values to guide the behavior
	 * of the native function.  The value is signed on purpose: it is easier to
	 * convert a signed value to unsigned (simply AND with 0xffff) than vice
	 * versa.
	 *
	 * Note: cannot place nargs/magic into the heaphdr flags, because
	 * duk_hobject takes almost all flags already.
	 */
};

#endif  /* DUK_HNATFUNC_H_INCLUDED */
/* #include duk_hboundfunc.h */
#line 1 "duk_hboundfunc.h"
/*
 *  Bound function representation.
 */

#if !defined(DUK_HBOUNDFUNC_H_INCLUDED)
#define DUK_HBOUNDFUNC_H_INCLUDED

/* Artificial limit for args length.  Ensures arithmetic won't overflow
 * 32 bits when combining bound functions.
 */
#define DUK_HBOUNDFUNC_MAX_ARGS 0x20000000UL

#if defined(DUK_USE_ASSERTIONS)
DUK_INTERNAL_DECL void duk_hboundfunc_assert_valid(duk_hboundfunc *h);
#define DUK_HBOUNDFUNC_ASSERT_VALID(h)  do { duk_hboundfunc_assert_valid((h)); } while (0)
#else
#define DUK_HBOUNDFUNC_ASSERT_VALID(h)  do {} while (0)
#endif

struct duk_hboundfunc {
	/* Shared object part. */
	duk_hobject obj;

	/* Final target function, stored as duk_tval so that lightfunc can be
	 * represented too.
	 */
	duk_tval target;

	/* This binding. */
	duk_tval this_binding;

	/* Arguments to prepend. */
	duk_tval *args;  /* Separate allocation. */
	duk_idx_t nargs;
};

#endif  /* DUK_HBOUNDFUNC_H_INCLUDED */
/* #include duk_hbufobj.h */
#line 1 "duk_hbufobj.h"
/*
 *  Heap Buffer object representation.  Used for all Buffer variants.
 */

#if !defined(DUK_HBUFOBJ_H_INCLUDED)
#define DUK_HBUFOBJ_H_INCLUDED

#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)

/* All element accessors are host endian now (driven by TypedArray spec). */
#define DUK_HBUFOBJ_ELEM_UINT8           0
#define DUK_HBUFOBJ_ELEM_UINT8CLAMPED    1
#define DUK_HBUFOBJ_ELEM_INT8            2
#define DUK_HBUFOBJ_ELEM_UINT16          3
#define DUK_HBUFOBJ_ELEM_INT16           4
#define DUK_HBUFOBJ_ELEM_UINT32          5
#define DUK_HBUFOBJ_ELEM_INT32           6
#define DUK_HBUFOBJ_ELEM_FLOAT32         7
#define DUK_HBUFOBJ_ELEM_FLOAT64         8
#define DUK_HBUFOBJ_ELEM_MAX             8

#if defined(DUK_USE_ASSERTIONS)
DUK_INTERNAL_DECL void duk_hbufobj_assert_valid(duk_hbufobj *h);
#define DUK_HBUFOBJ_ASSERT_VALID(h)  do { duk_hbufobj_assert_valid((h)); } while (0)
#else
#define DUK_HBUFOBJ_ASSERT_VALID(h)  do {} while (0)
#endif

/* Get the current data pointer (caller must ensure buf != NULL) as a
 * duk_uint8_t ptr.  Note that the result may be NULL if the underlying
 * buffer has zero size and is not a fixed buffer.
 */
#define DUK_HBUFOBJ_GET_SLICE_BASE(heap,h) \
	(DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
	(((duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR((heap), (h)->buf)) + (h)->offset))

/* True if slice is full, i.e. offset is zero and length covers the entire
 * buffer.  This status may change independently of the duk_hbufobj if
 * the underlying buffer is dynamic and changes without the hbufobj
 * being changed.
 */
#define DUK_HBUFOBJ_FULL_SLICE(h) \
	(DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
	((h)->offset == 0 && (h)->length == DUK_HBUFFER_GET_SIZE((h)->buf)))

/* Validate that the whole slice [0,length[ is contained in the underlying
 * buffer.  Caller must ensure 'buf' != NULL.
 */
#define DUK_HBUFOBJ_VALID_SLICE(h) \
	(DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
	((h)->offset + (h)->length <= DUK_HBUFFER_GET_SIZE((h)->buf)))

/* Validate byte read/write for virtual 'offset', i.e. check that the
 * offset, taking into account h->offset, is within the underlying
 * buffer size.  This is a safety check which is needed to ensure
 * that even a misconfigured duk_hbufobj never causes memory unsafe
 * behavior (e.g. if an underlying dynamic buffer changes after being
 * setup).  Caller must ensure 'buf' != NULL.
 */
#define DUK_HBUFOBJ_VALID_BYTEOFFSET_INCL(h,off) \
	(DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
	((h)->offset + (off) < DUK_HBUFFER_GET_SIZE((h)->buf)))

#define DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h,off) \
	(DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
	((h)->offset + (off) <= DUK_HBUFFER_GET_SIZE((h)->buf)))

/* Clamp an input byte length (already assumed to be within the nominal
 * duk_hbufobj 'length') to the current dynamic buffer limits to yield
 * a byte length limit that's safe for memory accesses.  This value can
 * be invalidated by any side effect because it may trigger a user
 * callback that resizes the underlying buffer.
 */
#define DUK_HBUFOBJ_CLAMP_BYTELENGTH(h,len) \
	(DUK_ASSERT_EXPR((h) != NULL), \
	duk_hbufobj_clamp_bytelength((h), (len)))

/* Typed arrays have virtual indices, ArrayBuffer and DataView do not. */
#define DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h)  ((h)->is_typedarray)

struct duk_hbufobj {
	/* Shared object part. */
	duk_hobject obj;

	/* Underlying buffer (refcounted), may be NULL. */
	duk_hbuffer *buf;

	/* .buffer reference to an ArrayBuffer, may be NULL. */
	duk_hobject *buf_prop;

	/* Slice and accessor information.
	 *
	 * Because the underlying buffer may be dynamic, these may be
	 * invalidated by the buffer being modified so that both offset
	 * and length should be validated before every access.  Behavior
	 * when the underlying buffer has changed doesn't need to be clean:
	 * virtual 'length' doesn't need to be affected, reads can return
	 * zero/NaN, and writes can be ignored.
	 *
	 * Note that a data pointer cannot be precomputed because 'buf' may
	 * be dynamic and its pointer unstable.
	 */

	duk_uint_t offset;       /* byte offset to buf */
	duk_uint_t length;       /* byte index limit for element access, exclusive */
	duk_uint8_t shift;       /* element size shift:
	                          *   0 = u8/i8
	                          *   1 = u16/i16
	                          *   2 = u32/i32/float
	                          *   3 = double
	                          */
	duk_uint8_t elem_type;   /* element type */
	duk_uint8_t is_typedarray;
};

DUK_INTERNAL_DECL duk_uint_t duk_hbufobj_clamp_bytelength(duk_hbufobj *h_bufobj, duk_uint_t len);
DUK_INTERNAL_DECL void duk_hbufobj_push_uint8array_from_plain(duk_hthread *thr, duk_hbuffer *h_buf);
DUK_INTERNAL_DECL void duk_hbufobj_push_validated_read(duk_hthread *thr, duk_hbufobj *h_bufobj, duk_uint8_t *p, duk_small_uint_t elem_size);
DUK_INTERNAL_DECL void duk_hbufobj_validated_write(duk_hthread *thr, duk_hbufobj *h_bufobj, duk_uint8_t *p, duk_small_uint_t elem_size);
DUK_INTERNAL_DECL void duk_hbufobj_promote_plain(duk_hthread *thr, duk_idx_t idx);

#else  /* DUK_USE_BUFFEROBJECT_SUPPORT */

/* nothing */

#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
#endif  /* DUK_HBUFOBJ_H_INCLUDED */
/* #include duk_hthread.h */
#line 1 "duk_hthread.h"
/*
 *  Heap thread object representation.
 *
 *  duk_hthread is also the 'context' for public API functions via a
 *  different typedef.  Most API calls operate on the topmost frame
 *  of the value stack only.
 */

#if !defined(DUK_HTHREAD_H_INCLUDED)
#define DUK_HTHREAD_H_INCLUDED

/*
 *  Stack constants
 */

/* Initial valstack size, roughly 0.7kiB. */
#define DUK_VALSTACK_INITIAL_SIZE       96U

/* Internal extra elements assumed on function entry, always added to
 * user-defined 'extra' for e.g. the duk_check_stack() call.
 */
#define DUK_VALSTACK_INTERNAL_EXTRA     32U

/* Number of elements guaranteed to be user accessible (in addition to call
 * arguments) on Duktape/C function entry.  This is the major public API
 * commitment.
 */
#define DUK_VALSTACK_API_ENTRY_MINIMUM  DUK_API_ENTRY_STACK

/*
 *  Activation defines
 */

#define DUK_ACT_FLAG_STRICT             (1U << 0)  /* function executes in strict mode */
#define DUK_ACT_FLAG_TAILCALLED         (1U << 1)  /* activation has tail called one or more times */
#define DUK_ACT_FLAG_CONSTRUCT          (1U << 2)  /* function executes as a constructor (called via "new") */
#define DUK_ACT_FLAG_PREVENT_YIELD      (1U << 3)  /* activation prevents yield (native call or "new") */
#define DUK_ACT_FLAG_DIRECT_EVAL        (1U << 4)  /* activation is a direct eval call */
#define DUK_ACT_FLAG_CONSTRUCT_PROXY    (1U << 5)  /* activation is for Proxy 'construct' call, special return value handling */
#define DUK_ACT_FLAG_BREAKPOINT_ACTIVE  (1U << 6)  /* activation has active breakpoint(s) */

#define DUK_ACT_GET_FUNC(act)           ((act)->func)

/*
 *  Flags for __FILE__ / __LINE__ registered into tracedata
 */

#define DUK_TB_FLAG_NOBLAME_FILELINE    (1U << 0)  /* don't report __FILE__ / __LINE__ as fileName/lineNumber */

/*
 *  Catcher defines
 */

/* XXX: remove catcher type entirely */

/* flags field: LLLLLLFT, L = label (24 bits), F = flags (4 bits), T = type (4 bits) */
#define DUK_CAT_TYPE_MASK            0x0000000fUL
#define DUK_CAT_TYPE_BITS            4
#define DUK_CAT_LABEL_MASK           0xffffff00UL
#define DUK_CAT_LABEL_BITS           24
#define DUK_CAT_LABEL_SHIFT          8

#define DUK_CAT_FLAG_CATCH_ENABLED          (1U << 4)   /* catch part will catch */
#define DUK_CAT_FLAG_FINALLY_ENABLED        (1U << 5)   /* finally part will catch */
#define DUK_CAT_FLAG_CATCH_BINDING_ENABLED  (1U << 6)   /* request to create catch binding */
#define DUK_CAT_FLAG_LEXENV_ACTIVE          (1U << 7)   /* catch or with binding is currently active */

#define DUK_CAT_TYPE_UNKNOWN         0
#define DUK_CAT_TYPE_TCF             1
#define DUK_CAT_TYPE_LABEL           2

#define DUK_CAT_GET_TYPE(c)          ((c)->flags & DUK_CAT_TYPE_MASK)
#define DUK_CAT_GET_LABEL(c)         (((c)->flags & DUK_CAT_LABEL_MASK) >> DUK_CAT_LABEL_SHIFT)

#define DUK_CAT_HAS_CATCH_ENABLED(c)           ((c)->flags & DUK_CAT_FLAG_CATCH_ENABLED)
#define DUK_CAT_HAS_FINALLY_ENABLED(c)         ((c)->flags & DUK_CAT_FLAG_FINALLY_ENABLED)
#define DUK_CAT_HAS_CATCH_BINDING_ENABLED(c)   ((c)->flags & DUK_CAT_FLAG_CATCH_BINDING_ENABLED)
#define DUK_CAT_HAS_LEXENV_ACTIVE(c)           ((c)->flags & DUK_CAT_FLAG_LEXENV_ACTIVE)

#define DUK_CAT_SET_CATCH_ENABLED(c)    do { \
		(c)->flags |= DUK_CAT_FLAG_CATCH_ENABLED; \
	} while (0)
#define DUK_CAT_SET_FINALLY_ENABLED(c)  do { \
		(c)->flags |= DUK_CAT_FLAG_FINALLY_ENABLED; \
	} while (0)
#define DUK_CAT_SET_CATCH_BINDING_ENABLED(c)    do { \
		(c)->flags |= DUK_CAT_FLAG_CATCH_BINDING_ENABLED; \
	} while (0)
#define DUK_CAT_SET_LEXENV_ACTIVE(c)    do { \
		(c)->flags |= DUK_CAT_FLAG_LEXENV_ACTIVE; \
	} while (0)

#define DUK_CAT_CLEAR_CATCH_ENABLED(c)    do { \
		(c)->flags &= ~DUK_CAT_FLAG_CATCH_ENABLED; \
	} while (0)
#define DUK_CAT_CLEAR_FINALLY_ENABLED(c)  do { \
		(c)->flags &= ~DUK_CAT_FLAG_FINALLY_ENABLED; \
	} while (0)
#define DUK_CAT_CLEAR_CATCH_BINDING_ENABLED(c)    do { \
		(c)->flags &= ~DUK_CAT_FLAG_CATCH_BINDING_ENABLED; \
	} while (0)
#define DUK_CAT_CLEAR_LEXENV_ACTIVE(c)    do { \
		(c)->flags &= ~DUK_CAT_FLAG_LEXENV_ACTIVE; \
	} while (0)

/*
 *  Thread defines
 */

#if defined(DUK_USE_ROM_STRINGS)
#define DUK_HTHREAD_GET_STRING(thr,idx) \
	((duk_hstring *) DUK_LOSE_CONST(duk_rom_strings_stridx[(idx)]))
#else  /* DUK_USE_ROM_STRINGS */
#if defined(DUK_USE_HEAPPTR16)
#define DUK_HTHREAD_GET_STRING(thr,idx) \
	((duk_hstring *) DUK_USE_HEAPPTR_DEC16((thr)->heap->heap_udata, (thr)->strs16[(idx)]))
#else
#define DUK_HTHREAD_GET_STRING(thr,idx) \
	((thr)->strs[(idx)])
#endif
#endif  /* DUK_USE_ROM_STRINGS */

/* values for the state field */
#define DUK_HTHREAD_STATE_INACTIVE     1   /* thread not currently running */
#define DUK_HTHREAD_STATE_RUNNING      2   /* thread currently running (only one at a time) */
#define DUK_HTHREAD_STATE_RESUMED      3   /* thread resumed another thread (active but not running) */
#define DUK_HTHREAD_STATE_YIELDED      4   /* thread has yielded */
#define DUK_HTHREAD_STATE_TERMINATED   5   /* thread has terminated */

/* Executor interrupt default interval when nothing else requires a
 * smaller value.  The default interval must be small enough to allow
 * for reasonable execution timeout checking but large enough to keep
 * impact on execution performance low.
 */
#if defined(DUK_USE_INTERRUPT_COUNTER)
#define DUK_HTHREAD_INTCTR_DEFAULT     (256L * 1024L)
#endif

/*
 *  Assert context is valid: non-NULL pointer, fields look sane.
 *
 *  This is used by public API call entrypoints to catch invalid 'ctx' pointers
 *  as early as possible; invalid 'ctx' pointers cause very odd and difficult to
 *  diagnose behavior so it's worth checking even when the check is not 100%.
 */

#if defined(DUK_USE_ASSERTIONS)
/* Assertions for internals. */
DUK_INTERNAL_DECL void duk_hthread_assert_valid(duk_hthread *thr);
#define DUK_HTHREAD_ASSERT_VALID(thr)  do { duk_hthread_assert_valid((thr)); } while (0)

/* Assertions for public API calls; a bit stronger. */
DUK_INTERNAL_DECL void duk_ctx_assert_valid(duk_hthread *thr);
#define DUK_CTX_ASSERT_VALID(thr)  do { duk_ctx_assert_valid((thr)); } while (0)
#else
#define DUK_HTHREAD_ASSERT_VALID(thr)  do {} while (0)
#define DUK_CTX_ASSERT_VALID(thr)  do {} while (0)
#endif

/* Assertions for API call entry specifically.  Checks 'ctx' but also may
 * check internal state (e.g. not in a debugger transport callback).
 */
#define DUK_ASSERT_API_ENTRY(thr) do { \
		DUK_CTX_ASSERT_VALID((thr)); \
		DUK_ASSERT((thr)->heap != NULL); \
		DUK_ASSERT((thr)->heap->dbg_calling_transport == 0); \
	} while (0)

/*
 *  Assertion helpers.
 */

#define DUK_ASSERT_STRIDX_VALID(val) \
	DUK_ASSERT((duk_uint_t) (val) < DUK_HEAP_NUM_STRINGS)

#define DUK_ASSERT_BIDX_VALID(val) \
	DUK_ASSERT((duk_uint_t) (val) < DUK_NUM_BUILTINS)

/*
 *  Misc
 */

/* Fast access to 'this' binding.  Assumes there's a call in progress. */
#define DUK_HTHREAD_THIS_PTR(thr) \
	(DUK_ASSERT_EXPR((thr) != NULL), \
	 DUK_ASSERT_EXPR((thr)->valstack_bottom > (thr)->valstack), \
	 (thr)->valstack_bottom - 1)

/*
 *  Struct defines
 */

/* Fields are ordered for alignment/packing. */
struct duk_activation {
	duk_tval tv_func;       /* borrowed: full duk_tval for function being executed; for lightfuncs */
	duk_hobject *func;      /* borrowed: function being executed; for bound function calls, this is the final, real function, NULL for lightfuncs */
	duk_activation *parent; /* previous (parent) activation (or NULL if none) */
	duk_hobject *var_env;   /* current variable environment (may be NULL if delayed) */
	duk_hobject *lex_env;   /* current lexical environment (may be NULL if delayed) */
	duk_catcher *cat;       /* current catcher (or NULL) */

#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
	/* Previous value of 'func' caller, restored when unwound.  Only in use
	 * when 'func' is non-strict.
	 */
	duk_hobject *prev_caller;
#endif

	duk_instr_t *curr_pc;   /* next instruction to execute (points to 'func' bytecode, stable pointer), NULL for native calls */

	/* bottom_byteoff and retval_byteoff are only used for book-keeping
	 * of ECMAScript-initiated calls, to allow returning to an ECMAScript
	 * function properly.
	 */

	/* Bottom of valstack for this activation, used to reset
	 * valstack_bottom on return; offset is absolute.  There's
	 * no need to track 'top' because native call handling deals
	 * with that using locals, and for ECMAScript returns 'nregs'
	 * indicates the necessary top.
	 */
	duk_size_t bottom_byteoff;

	/* Return value when returning to this activation (points to caller
	 * reg, not callee reg); offset is absolute (only set if activation is
	 * not topmost).
	 *
	 * Note: bottom_byteoff is always set, while retval_byteoff is only
	 * applicable for activations below the topmost one.  Currently
	 * retval_byteoff for the topmost activation is considered garbage
	 * (and it not initialized on entry or cleared on return; may contain
	 * previous or garbage values).
	 */
	duk_size_t retval_byteoff;

	/* Current 'this' binding is the value just below bottom.
	 * Previously, 'this' binding was handled with an index to the
	 * (calling) valstack.  This works for everything except tail
	 * calls, which must not "accumulate" valstack temps.
	 */

	/* Value stack reserve (valstack_end) byte offset to be restored
	 * when returning to this activation.  Only used by the bytecode
	 * executor.
	 */
	duk_size_t reserve_byteoff;

#if defined(DUK_USE_DEBUGGER_SUPPORT)
	duk_uint32_t prev_line; /* needed for stepping */
#endif

	duk_small_uint_t flags;
};

struct duk_catcher {
	duk_catcher *parent;            /* previous (parent) catcher (or NULL if none) */
	duk_hstring *h_varname;         /* borrowed reference to catch variable name (or NULL if none) */
	                                /* (reference is valid as long activation exists) */
	duk_instr_t *pc_base;           /* resume execution from pc_base or pc_base+1 (points to 'func' bytecode, stable pointer) */
	duk_size_t idx_base;            /* idx_base and idx_base+1 get completion value and type */
	duk_uint32_t flags;             /* type and control flags, label number */
	/* XXX: could pack 'flags' and 'idx_base' to same value in practice,
	 * on 32-bit targets this would make duk_catcher 16 bytes.
	 */
};

struct duk_hthread {
	/* Shared object part */
	duk_hobject obj;

	/* Pointer to bytecode executor's 'curr_pc' variable.  Used to copy
	 * the current PC back into the topmost activation when activation
	 * state is about to change (or "syncing" is otherwise needed).  This
	 * is rather awkward but important for performance, see execution.rst.
	 */
	duk_instr_t **ptr_curr_pc;

	/* Backpointers. */
	duk_heap *heap;

	/* Current strictness flag: affects API calls. */
	duk_uint8_t strict;

	/* Thread state. */
	duk_uint8_t state;
	duk_uint8_t unused1;
	duk_uint8_t unused2;

	/* XXX: Valstack and callstack are currently assumed to have non-NULL
	 * pointers.  Relaxing this would not lead to big benefits (except
	 * perhaps for terminated threads).
	 */

	/* Value stack: these are expressed as pointers for faster stack
	 * manipulation.  [valstack,valstack_top[ is GC-reachable,
	 * [valstack_top,valstack_alloc_end[ is not GC-reachable but kept
	 * initialized as 'undefined'.  [valstack,valstack_end[ is the
	 * guaranteed/reserved space and the valstack cannot be resized to
	 * a smaller size.  [valstack_end,valstack_alloc_end[ is currently
	 * allocated slack that can be used to grow the current guaranteed
	 * space but may be shrunk away without notice.
	 *
	 *
	 * <----------------------- guaranteed --->
	 *                                        <---- slack --->
	 *               <--- frame --->
	 * .-------------+=============+----------+--------------.
	 * |xxxxxxxxxxxxx|yyyyyyyyyyyyy|uuuuuuuuuu|uuuuuuuuuuuuuu|
	 * `-------------+=============+----------+--------------'
	 *
	 * ^             ^             ^          ^              ^
	 * |             |             |          |              |
	 * valstack      bottom        top        end            alloc_end
	 *
	 *     xxx = arbitrary values, below current frame
	 *     yyy = arbitrary values, inside current frame
	 *     uuu = outside active value stack, initialized to 'undefined'
	 */
	duk_tval *valstack;                     /* start of valstack allocation */
	duk_tval *valstack_end;                 /* end of valstack reservation/guarantee (exclusive) */
	duk_tval *valstack_alloc_end;           /* end of valstack allocation */
	duk_tval *valstack_bottom;              /* bottom of current frame */
	duk_tval *valstack_top;                 /* top of current frame (exclusive) */

	/* Call stack, represented as a linked list starting from the current
	 * activation (or NULL if nothing is active).
	 */
	duk_activation *callstack_curr;         /* current activation (or NULL if none) */
	duk_size_t callstack_top;               /* number of activation records in callstack (0 if none) */
	duk_size_t callstack_preventcount;      /* number of activation records in callstack preventing a yield */

	/* Yield/resume book-keeping. */
	duk_hthread *resumer;                   /* who resumed us (if any) */

	/* Current compiler state (if any), used for augmenting SyntaxErrors. */
	duk_compiler_ctx *compile_ctx;

#if defined(DUK_USE_INTERRUPT_COUNTER)
	/* Interrupt counter for triggering a slow path check for execution
	 * timeout, debugger interaction such as breakpoints, etc.  The value
	 * is valid for the current running thread, and both the init and
	 * counter values are copied whenever a thread switch occurs.  It's
	 * important for the counter to be conveniently accessible for the
	 * bytecode executor inner loop for performance reasons.
	 */
	duk_int_t interrupt_counter;    /* countdown state */
	duk_int_t interrupt_init;       /* start value for current countdown */
#endif

	/* Builtin-objects; may or may not be shared with other threads,
	 * threads existing in different "compartments" will have different
	 * built-ins.  Must be stored on a per-thread basis because there
	 * is no intermediate structure for a thread group / compartment.
	 * This takes quite a lot of space, currently 43x4 = 172 bytes on
	 * 32-bit platforms.
	 *
	 * In some cases the builtins array could be ROM based, but it's
	 * sometimes edited (e.g. for sandboxing) so it's better to keep
	 * this array in RAM.
	 */
	duk_hobject *builtins[DUK_NUM_BUILTINS];

	/* Convenience copies from heap/vm for faster access. */
#if defined(DUK_USE_ROM_STRINGS)
	/* No field needed when strings are in ROM. */
#else
#if defined(DUK_USE_HEAPPTR16)
	duk_uint16_t *strs16;
#else
	duk_hstring **strs;
#endif
#endif
};

/*
 *  Prototypes
 */

DUK_INTERNAL_DECL void duk_hthread_copy_builtin_objects(duk_hthread *thr_from, duk_hthread *thr_to);
DUK_INTERNAL_DECL void duk_hthread_create_builtin_objects(duk_hthread *thr);
DUK_INTERNAL_DECL duk_bool_t duk_hthread_init_stacks(duk_heap *heap, duk_hthread *thr);
DUK_INTERNAL_DECL void duk_hthread_terminate(duk_hthread *thr);

DUK_INTERNAL_DECL duk_activation *duk_hthread_activation_alloc(duk_hthread *thr);
DUK_INTERNAL_DECL void duk_hthread_activation_free(duk_hthread *thr, duk_activation *act);
DUK_INTERNAL_DECL void duk_hthread_activation_unwind_norz(duk_hthread *thr);
DUK_INTERNAL_DECL void duk_hthread_activation_unwind_reuse_norz(duk_hthread *thr);
DUK_INTERNAL_DECL duk_activation *duk_hthread_get_activation_for_level(duk_hthread *thr, duk_int_t level);

DUK_INTERNAL_DECL duk_catcher *duk_hthread_catcher_alloc(duk_hthread *thr);
DUK_INTERNAL_DECL void duk_hthread_catcher_free(duk_hthread *thr, duk_catcher *cat);
DUK_INTERNAL_DECL void duk_hthread_catcher_unwind_norz(duk_hthread *thr, duk_activation *act);
DUK_INTERNAL_DECL void duk_hthread_catcher_unwind_nolexenv_norz(duk_hthread *thr, duk_activation *act);

#if defined(DUK_USE_FINALIZER_TORTURE)
DUK_INTERNAL_DECL void duk_hthread_valstack_torture_realloc(duk_hthread *thr);
#endif

DUK_INTERNAL_DECL void *duk_hthread_get_valstack_ptr(duk_heap *heap, void *ud);  /* indirect allocs */

#if defined(DUK_USE_DEBUGGER_SUPPORT)
DUK_INTERNAL_DECL duk_uint_fast32_t duk_hthread_get_act_curr_pc(duk_hthread *thr, duk_activation *act);
#endif
DUK_INTERNAL_DECL duk_uint_fast32_t duk_hthread_get_act_prev_pc(duk_hthread *thr, duk_activation *act);
DUK_INTERNAL_DECL void duk_hthread_sync_currpc(duk_hthread *thr);
DUK_INTERNAL_DECL void duk_hthread_sync_and_null_currpc(duk_hthread *thr);

#endif  /* DUK_HTHREAD_H_INCLUDED */
/* #include duk_harray.h */
#line 1 "duk_harray.h"
/*
 *  Array object representation, used for actual Array instances.
 *
 *  All objects with the exotic array behavior (which must coincide with having
 *  internal class array) MUST be duk_harrays.  No other object can be a
 *  duk_harray.  However, duk_harrays may not always have an array part.
 */

#if !defined(DUK_HARRAY_H_INCLUDED)
#define DUK_HARRAY_H_INCLUDED

#if defined(DUK_USE_ASSERTIONS)
DUK_INTERNAL_DECL void duk_harray_assert_valid(duk_harray *h);
#define DUK_HARRAY_ASSERT_VALID(h)  do { duk_harray_assert_valid((h)); } while (0)
#else
#define DUK_HARRAY_ASSERT_VALID(h)  do {} while (0)
#endif

#define DUK_HARRAY_LENGTH_WRITABLE(h)         (!(h)->length_nonwritable)
#define DUK_HARRAY_LENGTH_NONWRITABLE(h)      ((h)->length_nonwritable)
#define DUK_HARRAY_SET_LENGTH_WRITABLE(h)     do { (h)->length_nonwritable = 0; } while (0)
#define DUK_HARRAY_SET_LENGTH_NONWRITABLE(h)  do { (h)->length_nonwritable = 1; } while (0)

struct duk_harray {
	/* Shared object part. */
	duk_hobject obj;

	/* Array .length.
	 *
	 * At present Array .length may be smaller, equal, or even larger
	 * than the allocated underlying array part.  Fast path code must
	 * always take this into account carefully.
	 */
	duk_uint32_t length;

	/* Array .length property attributes.  The property is always
	 * non-enumerable and non-configurable.  It's initially writable
	 * but per Object.defineProperty() rules it can be made non-writable
	 * even if it is non-configurable.  Thus we need to track the
	 * writability explicitly.
	 *
	 * XXX: this field to be eliminated and moved into duk_hobject
	 * flags field to save space.
	 */
	duk_bool_t length_nonwritable;
};

#endif  /* DUK_HARRAY_H_INCLUDED */
/* #include duk_henv.h */
#line 1 "duk_henv.h"
/*
 *  Environment object representation.
 */

#if !defined(DUK_HENV_H_INCLUDED)
#define DUK_HENV_H_INCLUDED

#if defined(DUK_USE_ASSERTIONS)
DUK_INTERNAL_DECL void duk_hdecenv_assert_valid(duk_hdecenv *h);
DUK_INTERNAL_DECL void duk_hobjenv_assert_valid(duk_hobjenv *h);
#define DUK_HDECENV_ASSERT_VALID(h)  do { duk_hdecenv_assert_valid((h)); } while (0)
#define DUK_HOBJENV_ASSERT_VALID(h)  do { duk_hobjenv_assert_valid((h)); } while (0)
#else
#define DUK_HDECENV_ASSERT_VALID(h)  do {} while (0)
#define DUK_HOBJENV_ASSERT_VALID(h)  do {} while (0)
#endif

struct duk_hdecenv {
	/* Shared object part. */
	duk_hobject obj;

	/* These control variables provide enough information to access live
	 * variables for a closure that is still open.  If thread == NULL,
	 * the record is closed and the identifiers are in the property table.
	 */
	duk_hthread *thread;
	duk_hobject *varmap;
	duk_size_t regbase_byteoff;
};

struct duk_hobjenv {
	/* Shared object part. */
	duk_hobject obj;

	/* Target object and 'this' binding for object binding. */
	duk_hobject *target;

	/* The 'target' object is used as a this binding in only some object
	 * environments.  For example, the global environment does not provide
	 * a this binding, but a with statement does.
	 */
	duk_bool_t has_this;
};

#endif  /* DUK_HENV_H_INCLUDED */
/* #include duk_hbuffer.h */
#line 1 "duk_hbuffer.h"
/*
 *  Heap buffer representation.
 *
 *  Heap allocated user data buffer which is either:
 *
 *    1. A fixed size buffer (data follows header statically)
 *    2. A dynamic size buffer (data pointer follows header)
 *
 *  The data pointer for a variable size buffer of zero size may be NULL.
 */

#if !defined(DUK_HBUFFER_H_INCLUDED)
#define DUK_HBUFFER_H_INCLUDED

/*
 *  Flags
 *
 *  Fixed buffer:     0
 *  Dynamic buffer:   DUK_HBUFFER_FLAG_DYNAMIC
 *  External buffer:  DUK_HBUFFER_FLAG_DYNAMIC | DUK_HBUFFER_FLAG_EXTERNAL
 */

#define DUK_HBUFFER_FLAG_DYNAMIC                  DUK_HEAPHDR_USER_FLAG(0)    /* buffer is behind a pointer, dynamic or external */
#define DUK_HBUFFER_FLAG_EXTERNAL                 DUK_HEAPHDR_USER_FLAG(1)    /* buffer pointer is to an externally allocated buffer */

#define DUK_HBUFFER_HAS_DYNAMIC(x)                DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_DYNAMIC)
#define DUK_HBUFFER_HAS_EXTERNAL(x)               DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_EXTERNAL)

#define DUK_HBUFFER_SET_DYNAMIC(x)                DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_DYNAMIC)
#define DUK_HBUFFER_SET_EXTERNAL(x)               DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_EXTERNAL)

#define DUK_HBUFFER_CLEAR_DYNAMIC(x)              DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_DYNAMIC)
#define DUK_HBUFFER_CLEAR_EXTERNAL(x)             DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_EXTERNAL)

/*
 *  Misc defines
 */

/* Impose a maximum buffer length for now.  Restricted artificially to
 * ensure resize computations or adding a heap header length won't
 * overflow size_t and that a signed duk_int_t can hold a buffer
 * length.  The limit should be synchronized with DUK_HSTRING_MAX_BYTELEN.
 */

#if defined(DUK_USE_BUFLEN16)
#define DUK_HBUFFER_MAX_BYTELEN                   (0x0000ffffUL)
#else
/* Intentionally not 0x7fffffffUL; at least JSON code expects that
 * 2*len + 2 fits in 32 bits.
 */
#define DUK_HBUFFER_MAX_BYTELEN                   (0x7ffffffeUL)
#endif

/*
 *  Field access
 */

#if defined(DUK_USE_BUFLEN16)
/* size stored in duk_heaphdr unused flag bits */
#define DUK_HBUFFER_GET_SIZE(x)     ((x)->hdr.h_flags >> 16)
#define DUK_HBUFFER_SET_SIZE(x,v)   do { \
		duk_size_t duk__v; \
		duk__v = (v); \
		DUK_ASSERT(duk__v <= 0xffffUL); \
		(x)->hdr.h_flags = ((x)->hdr.h_flags & 0x0000ffffUL) | (((duk_uint32_t) duk__v) << 16); \
	} while (0)
#define DUK_HBUFFER_ADD_SIZE(x,dv)  do { \
		(x)->hdr.h_flags += ((dv) << 16); \
	} while (0)
#define DUK_HBUFFER_SUB_SIZE(x,dv)  do { \
		(x)->hdr.h_flags -= ((dv) << 16); \
	} while (0)
#else
#define DUK_HBUFFER_GET_SIZE(x)     (((duk_hbuffer *) (x))->size)
#define DUK_HBUFFER_SET_SIZE(x,v)   do { \
		((duk_hbuffer *) (x))->size = (v); \
	} while (0)
#define DUK_HBUFFER_ADD_SIZE(x,dv)  do { \
		(x)->size += (dv); \
	} while (0)
#define DUK_HBUFFER_SUB_SIZE(x,dv)  do { \
		(x)->size -= (dv); \
	} while (0)
#endif

#define DUK_HBUFFER_FIXED_GET_SIZE(x)       DUK_HBUFFER_GET_SIZE((duk_hbuffer *) (x))
#define DUK_HBUFFER_FIXED_SET_SIZE(x,v)     DUK_HBUFFER_SET_SIZE((duk_hbuffer *) (x))

#define DUK_HBUFFER_DYNAMIC_GET_SIZE(x)     DUK_HBUFFER_GET_SIZE((duk_hbuffer *) (x))
#define DUK_HBUFFER_DYNAMIC_SET_SIZE(x,v)   DUK_HBUFFER_SET_SIZE((duk_hbuffer *) (x), (v))
#define DUK_HBUFFER_DYNAMIC_ADD_SIZE(x,dv)  DUK_HBUFFER_ADD_SIZE((duk_hbuffer *) (x), (dv))
#define DUK_HBUFFER_DYNAMIC_SUB_SIZE(x,dv)  DUK_HBUFFER_SUB_SIZE((duk_hbuffer *) (x), (dv))

#define DUK_HBUFFER_EXTERNAL_GET_SIZE(x)    DUK_HBUFFER_GET_SIZE((duk_hbuffer *) (x))
#define DUK_HBUFFER_EXTERNAL_SET_SIZE(x,v)  DUK_HBUFFER_SET_SIZE((duk_hbuffer *) (x), (v))

#define DUK_HBUFFER_FIXED_GET_DATA_PTR(heap,x)    ((duk_uint8_t *) (((duk_hbuffer_fixed *) (void *) (x)) + 1))

#if defined(DUK_USE_HEAPPTR16)
#define DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap,x) \
	((void *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, ((duk_heaphdr *) (x))->h_extra16))
#define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap,x,v)     do { \
		((duk_heaphdr *) (x))->h_extra16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
	} while (0)
#define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR_NULL(heap,x)  do { \
		((duk_heaphdr *) (x))->h_extra16 = 0;  /* assume 0 <=> NULL */ \
	} while (0)
#else
#define DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap,x)       ((x)->curr_alloc)
#define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap,x,v)     do { \
		(x)->curr_alloc = (void *) (v); \
	} while (0)
#define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR_NULL(heap,x)  do { \
		(x)->curr_alloc = (void *) NULL; \
	} while (0)
#endif

/* No pointer compression because pointer is potentially outside of
 * Duktape heap.
 */
#if defined(DUK_USE_HEAPPTR16)
#define DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(heap,x) \
	((void *) (x)->curr_alloc)
#define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(heap,x,v)     do { \
		(x)->curr_alloc = (void *) (v); \
	} while (0)
#define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR_NULL(heap,x)  do { \
		(x)->curr_alloc = (void *) NULL; \
	} while (0)
#else
#define DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(heap,x) \
	((void *) (x)->curr_alloc)
#define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(heap,x,v)     do { \
		(x)->curr_alloc = (void *) (v); \
	} while (0)
#define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR_NULL(heap,x)  do { \
		(x)->curr_alloc = (void *) NULL; \
	} while (0)
#endif

/* Get a pointer to the current buffer contents (matching current allocation
 * size).  May be NULL for zero size dynamic/external buffer.
 */
#if defined(DUK_USE_HEAPPTR16)
#define DUK_HBUFFER_GET_DATA_PTR(heap,x)  ( \
	DUK_HBUFFER_HAS_DYNAMIC((x)) ? \
		( \
			DUK_HBUFFER_HAS_EXTERNAL((x)) ? \
				DUK_HBUFFER_EXTERNAL_GET_DATA_PTR((heap), (duk_hbuffer_external *) (x)) : \
				DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((heap), (duk_hbuffer_dynamic *) (x)) \
		) : \
		DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), (duk_hbuffer_fixed *) (void *) (x)) \
	)
#else
/* Without heap pointer compression duk_hbuffer_dynamic and duk_hbuffer_external
 * have the same layout so checking for fixed vs. dynamic (or external) is enough.
 */
#define DUK_HBUFFER_GET_DATA_PTR(heap,x)  ( \
	DUK_HBUFFER_HAS_DYNAMIC((x)) ? \
		DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((heap), (duk_hbuffer_dynamic *) (x)) : \
		DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), (duk_hbuffer_fixed *) (void *) (x)) \
	)
#endif

/* Validity assert. */
#if defined(DUK_USE_ASSERTIONS)
DUK_INTERNAL_DECL void duk_hbuffer_assert_valid(duk_hbuffer *h);
#define DUK_HBUFFER_ASSERT_VALID(h)  do { duk_hbuffer_assert_valid((h)); } while (0)
#else
#define DUK_HBUFFER_ASSERT_VALID(h)  do {} while (0)
#endif

/*
 *  Structs
 */

/* Shared prefix for all buffer types. */
struct duk_hbuffer {
	duk_heaphdr hdr;

	/* It's not strictly necessary to track the current size, but
	 * it is useful for writing robust native code.
	 */

	/* Current size. */
#if defined(DUK_USE_BUFLEN16)
	/* Stored in duk_heaphdr unused flags. */
#else
	duk_size_t size;
#endif

	/*
	 *  Data following the header depends on the DUK_HBUFFER_FLAG_DYNAMIC
	 *  flag.
	 *
	 *  If the flag is clear (the buffer is a fixed size one), the buffer
	 *  data follows the header directly, consisting of 'size' bytes.
	 *
	 *  If the flag is set, the actual buffer is allocated separately, and
	 *  a few control fields follow the header.  Specifically:
	 *
	 *    - a "void *" pointing to the current allocation
	 *    - a duk_size_t indicating the full allocated size (always >= 'size')
	 *
	 *  If DUK_HBUFFER_FLAG_EXTERNAL is set, the buffer has been allocated
	 *  by user code, so that Duktape won't be able to resize it and won't
	 *  free it.  This allows buffers to point to e.g. an externally
	 *  allocated structure such as a frame buffer.
	 *
	 *  Unlike strings, no terminator byte (NUL) is guaranteed after the
	 *  data.  This would be convenient, but would pad aligned user buffers
	 *  unnecessarily upwards in size.  For instance, if user code requested
	 *  a 64-byte dynamic buffer, 65 bytes would actually be allocated which
	 *  would then potentially round upwards to perhaps 68 or 72 bytes.
	 */
};

/* Fixed buffer; data follows struct, with proper alignment guaranteed by
 * struct size.
 */
#if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_MSVC_PRAGMA)
#pragma pack(push, 8)
#endif
struct duk_hbuffer_fixed {
	/* A union is used here as a portable struct size / alignment trick:
	 * by adding a 32-bit or a 64-bit (unused) union member, the size of
	 * the struct is effectively forced to be a multiple of 4 or 8 bytes
	 * (respectively) without increasing the size of the struct unless
	 * necessary.
	 */
	union {
		struct {
			duk_heaphdr hdr;
#if defined(DUK_USE_BUFLEN16)
			/* Stored in duk_heaphdr unused flags. */
#else
			duk_size_t size;
#endif
		} s;
#if (DUK_USE_ALIGN_BY == 4)
		duk_uint32_t dummy_for_align4;
#elif (DUK_USE_ALIGN_BY == 8)
		duk_double_t dummy_for_align8_1;
#if defined(DUK_USE_64BIT_OPS)
		duk_uint64_t dummy_for_align8_2;
#endif
#elif (DUK_USE_ALIGN_BY == 1)
		/* no extra padding */
#else
#error invalid DUK_USE_ALIGN_BY
#endif
	} u;

	/*
	 *  Data follows the struct header.  The struct size is padded by the
	 *  compiler based on the struct members.  This guarantees that the
	 *  buffer data will be aligned-by-4 but not necessarily aligned-by-8.
	 *
	 *  On platforms where alignment does not matter, the struct padding
	 *  could be removed (if there is any).  On platforms where alignment
	 *  by 8 is required, the struct size must be forced to be a multiple
	 *  of 8 by some means.  Without it, some user code may break, and also
	 *  Duktape itself breaks (e.g. the compiler stores duk_tvals in a
	 *  dynamic buffer).
	 */
}
#if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_GCC_ATTR)
__attribute__ ((aligned (8)))
#elif (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_CLANG_ATTR)
__attribute__ ((aligned (8)))
#endif
;
#if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_MSVC_PRAGMA)
#pragma pack(pop)
#endif

/* Dynamic buffer with 'curr_alloc' pointing to a dynamic area allocated using
 * heap allocation primitives.  Also used for external buffers when low memory
 * options are not used.
 */
struct duk_hbuffer_dynamic {
	duk_heaphdr hdr;

#if defined(DUK_USE_BUFLEN16)
	/* Stored in duk_heaphdr unused flags. */
#else
	duk_size_t size;
#endif

#if defined(DUK_USE_HEAPPTR16)
	/* Stored in duk_heaphdr h_extra16. */
#else
	void *curr_alloc;  /* may be NULL if alloc_size == 0 */
#endif

	/*
	 *  Allocation size for 'curr_alloc' is alloc_size.  There is no
	 *  automatic NUL terminator for buffers (see above for rationale).
	 *
	 *  'curr_alloc' is explicitly allocated with heap allocation
	 *  primitives and will thus always have alignment suitable for
	 *  e.g. duk_tval and an IEEE double.
	 */
};

/* External buffer with 'curr_alloc' managed by user code and pointing to an
 * arbitrary address.  When heap pointer compression is not used, this struct
 * has the same layout as duk_hbuffer_dynamic.
 */
struct duk_hbuffer_external {
	duk_heaphdr hdr;

#if defined(DUK_USE_BUFLEN16)
	/* Stored in duk_heaphdr unused flags. */
#else
	duk_size_t size;
#endif

	/* Cannot be compressed as a heap pointer because may point to
	 * an arbitrary address.
	 */
	void *curr_alloc;  /* may be NULL if alloc_size == 0 */
};

/*
 *  Prototypes
 */

DUK_INTERNAL_DECL duk_hbuffer *duk_hbuffer_alloc(duk_heap *heap, duk_size_t size, duk_small_uint_t flags, void **out_bufdata);
DUK_INTERNAL_DECL void *duk_hbuffer_get_dynalloc_ptr(duk_heap *heap, void *ud);  /* indirect allocs */

/* dynamic buffer ops */
DUK_INTERNAL_DECL void duk_hbuffer_resize(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t new_size);
DUK_INTERNAL_DECL void duk_hbuffer_reset(duk_hthread *thr, duk_hbuffer_dynamic *buf);

#endif  /* DUK_HBUFFER_H_INCLUDED */
/* #include duk_hproxy.h */
#line 1 "duk_hproxy.h"
/*
 *  Proxy object representation.
 */

#if !defined(DUK_HPROXY_H_INCLUDED)
#define DUK_HPROXY_H_INCLUDED

#if defined(DUK_USE_ASSERTIONS)
DUK_INTERNAL_DECL void duk_hproxy_assert_valid(duk_hproxy *h);
#define DUK_HPROXY_ASSERT_VALID(h)  do { duk_hproxy_assert_valid((h)); } while (0)
#else
#define DUK_HPROXY_ASSERT_VALID(h)  do {} while (0)
#endif

struct duk_hproxy {
	/* Shared object part. */
	duk_hobject obj;

	/* Proxy target object. */
	duk_hobject *target;

	/* Proxy handlers (traps). */
	duk_hobject *handler;
};

#endif  /* DUK_HPROXY_H_INCLUDED */
/* #include duk_heap.h */
#line 1 "duk_heap.h"
/*
 *  Heap structure.
 *
 *  Heap contains allocated heap objects, interned strings, and built-in
 *  strings for one or more threads.
 */

#if !defined(DUK_HEAP_H_INCLUDED)
#define DUK_HEAP_H_INCLUDED

/* alloc function typedefs in duktape.h */

/*
 *  Heap flags
 */

#define DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED            (1U << 0)  /* mark-and-sweep marking reached a recursion limit and must use multi-pass marking */
#define DUK_HEAP_FLAG_INTERRUPT_RUNNING                        (1U << 1)  /* executor interrupt running (used to avoid nested interrupts) */
#define DUK_HEAP_FLAG_FINALIZER_NORESCUE                       (1U << 2)  /* heap destruction ongoing, finalizer rescue no longer possible */
#define DUK_HEAP_FLAG_DEBUGGER_PAUSED                          (1U << 3)  /* debugger is paused: talk with debug client until step/resume */

#define DUK__HEAP_HAS_FLAGS(heap,bits)               ((heap)->flags & (bits))
#define DUK__HEAP_SET_FLAGS(heap,bits)  do { \
		(heap)->flags |= (bits); \
	} while (0)
#define DUK__HEAP_CLEAR_FLAGS(heap,bits)  do { \
		(heap)->flags &= ~(bits); \
	} while (0)

#define DUK_HEAP_HAS_MARKANDSWEEP_RECLIMIT_REACHED(heap)   DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED)
#define DUK_HEAP_HAS_INTERRUPT_RUNNING(heap)               DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING)
#define DUK_HEAP_HAS_FINALIZER_NORESCUE(heap)              DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE)
#define DUK_HEAP_HAS_DEBUGGER_PAUSED(heap)                 DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_DEBUGGER_PAUSED)

#define DUK_HEAP_SET_MARKANDSWEEP_RECLIMIT_REACHED(heap)   DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED)
#define DUK_HEAP_SET_INTERRUPT_RUNNING(heap)               DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING)
#define DUK_HEAP_SET_FINALIZER_NORESCUE(heap)              DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE)
#define DUK_HEAP_SET_DEBUGGER_PAUSED(heap)                 DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_DEBUGGER_PAUSED)

#define DUK_HEAP_CLEAR_MARKANDSWEEP_RECLIMIT_REACHED(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED)
#define DUK_HEAP_CLEAR_INTERRUPT_RUNNING(heap)             DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING)
#define DUK_HEAP_CLEAR_FINALIZER_NORESCUE(heap)            DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE)
#define DUK_HEAP_CLEAR_DEBUGGER_PAUSED(heap)               DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_DEBUGGER_PAUSED)

/*
 *  Longjmp types, also double as identifying continuation type for a rethrow (in 'finally')
 */

#define DUK_LJ_TYPE_UNKNOWN      0    /* unused */
#define DUK_LJ_TYPE_THROW        1    /* value1 -> error object */
#define DUK_LJ_TYPE_YIELD        2    /* value1 -> yield value, iserror -> error / normal */
#define DUK_LJ_TYPE_RESUME       3    /* value1 -> resume value, value2 -> resumee thread, iserror -> error/normal */
#define DUK_LJ_TYPE_BREAK        4    /* value1 -> label number, pseudo-type to indicate a break continuation (for ENDFIN) */
#define DUK_LJ_TYPE_CONTINUE     5    /* value1 -> label number, pseudo-type to indicate a continue continuation (for ENDFIN) */
#define DUK_LJ_TYPE_RETURN       6    /* value1 -> return value, pseudo-type to indicate a return continuation (for ENDFIN) */
#define DUK_LJ_TYPE_NORMAL       7    /* no value, pseudo-type to indicate a normal continuation (for ENDFIN) */

/*
 *  Mark-and-sweep flags
 *
 *  These are separate from heap level flags now but could be merged.
 *  The heap structure only contains a 'base mark-and-sweep flags'
 *  field and the GC caller can impose further flags.
 */

/* Emergency mark-and-sweep: try extra hard, even at the cost of
 * performance.
 */
#define DUK_MS_FLAG_EMERGENCY                (1U << 0)

/* Postpone rescue decisions for reachable objects with FINALIZED set.
 * Used during finalize_list processing to avoid incorrect rescue
 * decisions due to finalize_list being a reachability root.
 */
#define DUK_MS_FLAG_POSTPONE_RESCUE          (1U << 1)

/* Don't compact objects; needed during object property table resize
 * to prevent a recursive resize.  It would suffice to protect only the
 * current object being resized, but this is not yet implemented.
 */
#define DUK_MS_FLAG_NO_OBJECT_COMPACTION     (1U << 2)

/*
 *  Thread switching
 *
 *  To switch heap->curr_thread, use the macro below so that interrupt counters
 *  get updated correctly.  The macro allows a NULL target thread because that
 *  happens e.g. in call handling.
 */

#if defined(DUK_USE_INTERRUPT_COUNTER)
#define DUK_HEAP_SWITCH_THREAD(heap,newthr)  duk_heap_switch_thread((heap), (newthr))
#else
#define DUK_HEAP_SWITCH_THREAD(heap,newthr)  do { \
		(heap)->curr_thread = (newthr); \
	} while (0)
#endif

/*
 *  Stats
 */

#if defined(DUK_USE_DEBUG)
#define DUK_STATS_INC(heap,fieldname) do { \
		(heap)->fieldname += 1; \
	} while (0)
#else
#define DUK_STATS_INC(heap,fieldname) do {} while (0)
#endif

/*
 *  Other heap related defines
 */

/* Mark-and-sweep interval is relative to combined count of objects and
 * strings kept in the heap during the latest mark-and-sweep pass.
 * Fixed point .8 multiplier and .0 adder.  Trigger count (interval) is
 * decreased by each (re)allocation attempt (regardless of size), and each
 * refzero processed object.
 *
 * 'SKIP' indicates how many (re)allocations to wait until a retry if
 * GC is skipped because there is no thread do it with yet (happens
 * only during init phases).
 */
#if defined(DUK_USE_REFERENCE_COUNTING)
#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_MULT              12800L  /* 50x heap size */
#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_ADD               1024L
#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_SKIP              256L
#else
#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_MULT              256L    /* 1x heap size */
#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_ADD               1024L
#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_SKIP              256L
#endif

/* GC torture. */
#if defined(DUK_USE_GC_TORTURE)
#define DUK_GC_TORTURE(heap) do { duk_heap_mark_and_sweep((heap), 0); } while (0)
#else
#define DUK_GC_TORTURE(heap) do { } while (0)
#endif

/* Stringcache is used for speeding up char-offset-to-byte-offset
 * translations for non-ASCII strings.
 */
#define DUK_HEAP_STRCACHE_SIZE                            4
#define DUK_HEAP_STRINGCACHE_NOCACHE_LIMIT                16  /* strings up to the this length are not cached */

/* Some list management macros. */
#define DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap,hdr)     duk_heap_insert_into_heap_allocated((heap), (hdr))
#if defined(DUK_USE_REFERENCE_COUNTING)
#define DUK_HEAP_REMOVE_FROM_HEAP_ALLOCATED(heap,hdr)     duk_heap_remove_from_heap_allocated((heap), (hdr))
#endif
#if defined(DUK_USE_FINALIZER_SUPPORT)
#define DUK_HEAP_INSERT_INTO_FINALIZE_LIST(heap,hdr)      duk_heap_insert_into_finalize_list((heap), (hdr))
#define DUK_HEAP_REMOVE_FROM_FINALIZE_LIST(heap,hdr)      duk_heap_remove_from_finalize_list((heap), (hdr))
#endif

/*
 *  Built-in strings
 */

/* heap string indices are autogenerated in duk_strings.h */
#if defined(DUK_USE_ROM_STRINGS)
#define DUK_HEAP_GET_STRING(heap,idx) \
	((duk_hstring *) DUK_LOSE_CONST(duk_rom_strings_stridx[(idx)]))
#else  /* DUK_USE_ROM_STRINGS */
#if defined(DUK_USE_HEAPPTR16)
#define DUK_HEAP_GET_STRING(heap,idx) \
	((duk_hstring *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (heap)->strs16[(idx)]))
#else
#define DUK_HEAP_GET_STRING(heap,idx) \
	((heap)->strs[(idx)])
#endif
#endif  /* DUK_USE_ROM_STRINGS */

/*
 *  Raw memory calls: relative to heap, but no GC interaction
 */

#define DUK_ALLOC_RAW(heap,size) \
	((heap)->alloc_func((heap)->heap_udata, (size)))

#define DUK_REALLOC_RAW(heap,ptr,newsize) \
	((heap)->realloc_func((heap)->heap_udata, (void *) (ptr), (newsize)))

#define DUK_FREE_RAW(heap,ptr) \
	((heap)->free_func((heap)->heap_udata, (void *) (ptr)))

/*
 *  Memory calls: relative to heap, GC interaction, but no error throwing.
 *
 *  XXX: Currently a mark-and-sweep triggered by memory allocation will run
 *  using the heap->heap_thread.  This thread is also used for running
 *  mark-and-sweep finalization; this is not ideal because it breaks the
 *  isolation between multiple global environments.
 *
 *  Notes:
 *
 *    - DUK_FREE() is required to ignore NULL and any other possible return
 *      value of a zero-sized alloc/realloc (same as ANSI C free()).
 *
 *    - There is no DUK_REALLOC_ZEROED because we don't assume to know the
 *      old size.  Caller must zero the reallocated memory.
 *
 *    - DUK_REALLOC_INDIRECT() must be used when a mark-and-sweep triggered
 *      by an allocation failure might invalidate the original 'ptr', thus
 *      causing a realloc retry to use an invalid pointer.  Example: we're
 *      reallocating the value stack and a finalizer resizes the same value
 *      stack during mark-and-sweep.  The indirect variant requests for the
 *      current location of the pointer being reallocated using a callback
 *      right before every realloc attempt; this circuitous approach is used
 *      to avoid strict aliasing issues in a more straightforward indirect
 *      pointer (void **) approach.  Note: the pointer in the storage
 *      location is read but is NOT updated; the caller must do that.
 */

/* callback for indirect reallocs, request for current pointer */
typedef void *(*duk_mem_getptr)(duk_heap *heap, void *ud);

#define DUK_ALLOC(heap,size)                            duk_heap_mem_alloc((heap), (size))
#define DUK_ALLOC_ZEROED(heap,size)                     duk_heap_mem_alloc_zeroed((heap), (size))
#define DUK_REALLOC(heap,ptr,newsize)                   duk_heap_mem_realloc((heap), (ptr), (newsize))
#define DUK_REALLOC_INDIRECT(heap,cb,ud,newsize)        duk_heap_mem_realloc_indirect((heap), (cb), (ud), (newsize))
#define DUK_FREE(heap,ptr)                              duk_heap_mem_free((heap), (ptr))

/*
 *  Checked allocation, relative to a thread
 *
 *  DUK_FREE_CHECKED() doesn't actually throw, but accepts a 'thr' argument
 *  for convenience.
 */

#define DUK_ALLOC_CHECKED(thr,size)                     duk_heap_mem_alloc_checked((thr), (size))
#define DUK_ALLOC_CHECKED_ZEROED(thr,size)              duk_heap_mem_alloc_checked_zeroed((thr), (size))
#define DUK_FREE_CHECKED(thr,ptr)                       duk_heap_mem_free((thr)->heap, (ptr))

/*
 *  Memory constants
 */

#define DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT           10  /* Retry allocation after mark-and-sweep for this
                                                              * many times.  A single mark-and-sweep round is
                                                              * not guaranteed to free all unreferenced memory
                                                              * because of finalization (in fact, ANY number of
                                                              * rounds is strictly not enough).
                                                              */

#define DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_EMERGENCY_LIMIT  3  /* Starting from this round, use emergency mode
                                                              * for mark-and-sweep.
                                                              */

/*
 *  Debugger support
 */

/* Maximum number of breakpoints.  Only breakpoints that are set are
 * consulted so increasing this has no performance impact.
 */
#define DUK_HEAP_MAX_BREAKPOINTS          16

/* Opcode interval for a Date-based status/peek rate limit check.  Only
 * relevant when debugger is attached.  Requesting a timestamp may be a
 * slow operation on some platforms so this shouldn't be too low.  On the
 * other hand a high value makes Duktape react to a pause request slowly.
 */
#define DUK_HEAP_DBG_RATELIMIT_OPCODES    4000

/* Milliseconds between status notify and transport peeks. */
#define DUK_HEAP_DBG_RATELIMIT_MILLISECS  200

/* Debugger pause flags. */
#define DUK_PAUSE_FLAG_ONE_OPCODE        (1U << 0)   /* pause when a single opcode has been executed */
#define DUK_PAUSE_FLAG_ONE_OPCODE_ACTIVE (1U << 1)   /* one opcode pause actually active; artifact of current implementation */
#define DUK_PAUSE_FLAG_LINE_CHANGE       (1U << 2)   /* pause when current line number changes */
#define DUK_PAUSE_FLAG_FUNC_ENTRY        (1U << 3)   /* pause when entering a function */
#define DUK_PAUSE_FLAG_FUNC_EXIT         (1U << 4)   /* pause when exiting current function */
#define DUK_PAUSE_FLAG_CAUGHT_ERROR      (1U << 5)   /* pause when about to throw an error that is caught */
#define DUK_PAUSE_FLAG_UNCAUGHT_ERROR    (1U << 6)   /* pause when about to throw an error that won't be caught */

struct duk_breakpoint {
	duk_hstring *filename;
	duk_uint32_t line;
};

/*
 *  String cache should ideally be at duk_hthread level, but that would
 *  cause string finalization to slow down relative to the number of
 *  threads; string finalization must check the string cache for "weak"
 *  references to the string being finalized to avoid dead pointers.
 *
 *  Thus, string caches are now at the heap level now.
 */

struct duk_strcache_entry {
	duk_hstring *h;
	duk_uint32_t bidx;
	duk_uint32_t cidx;
};

/*
 *  Longjmp state, contains the information needed to perform a longjmp.
 *  Longjmp related values are written to value1, value2, and iserror.
 */

struct duk_ljstate {
	duk_jmpbuf *jmpbuf_ptr;   /* current setjmp() catchpoint */
	duk_small_uint_t type;    /* longjmp type */
	duk_bool_t iserror;       /* isError flag for yield */
	duk_tval value1;          /* 1st related value (type specific) */
	duk_tval value2;          /* 2nd related value (type specific) */
};

#define DUK_ASSERT_LJSTATE_UNSET(heap) do { \
		DUK_ASSERT(heap != NULL); \
		DUK_ASSERT(heap->lj.type == DUK_LJ_TYPE_UNKNOWN); \
		DUK_ASSERT(heap->lj.iserror == 0); \
		DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&heap->lj.value1)); \
		DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&heap->lj.value2)); \
	} while (0)
#define DUK_ASSERT_LJSTATE_SET(heap) do { \
		DUK_ASSERT(heap != NULL); \
		DUK_ASSERT(heap->lj.type != DUK_LJ_TYPE_UNKNOWN); \
	} while (0)

/*
 *  Literal intern cache
 */

struct duk_litcache_entry {
	const duk_uint8_t *addr;
	duk_hstring *h;
};

/*
 *  Main heap structure
 */

#if defined(DUK_USE_ASSERTIONS)
DUK_INTERNAL_DECL void duk_heap_assert_valid(duk_heap *heap);
#define DUK_HEAP_ASSERT_VALID(heap)  do { duk_heap_assert_valid((heap)); } while (0)
#else
#define DUK_HEAP_ASSERT_VALID(heap)  do {} while (0)
#endif

struct duk_heap {
	duk_small_uint_t flags;

	/* Allocator functions. */
	duk_alloc_function alloc_func;
	duk_realloc_function realloc_func;
	duk_free_function free_func;

	/* Heap udata, used for allocator functions but also for other heap
	 * level callbacks like fatal function, pointer compression, etc.
	 */
	void *heap_udata;

	/* Fatal error handling, called e.g. when a longjmp() is needed but
	 * lj.jmpbuf_ptr is NULL.  fatal_func must never return; it's not
	 * declared as "noreturn" because doing that for typedefs is a bit
	 * challenging portability-wise.
	 */
	duk_fatal_function fatal_func;

	/* Main list of allocated heap objects.  Objects are either here,
	 * in finalize_list waiting for processing, or in refzero_list
	 * temporarily while a DECREF refzero cascade finishes.
	 */
	duk_heaphdr *heap_allocated;

	/* Temporary work list for freeing a cascade of objects when a DECREF
	 * (or DECREF_NORZ) encounters a zero refcount.  Using a work list
	 * allows fixed C stack size when refcounts go to zero for a chain of
	 * objects.  Outside of DECREF this is always a NULL because DECREF is
	 * processed without side effects (only memory free calls).
	 */
#if defined(DUK_USE_REFERENCE_COUNTING)
	duk_heaphdr *refzero_list;
#endif

#if defined(DUK_USE_FINALIZER_SUPPORT)
	/* Work list for objects to be finalized. */
	duk_heaphdr *finalize_list;
#if defined(DUK_USE_ASSERTIONS)
	/* Object whose finalizer is executing right now (no nesting). */
	duk_heaphdr *currently_finalizing;
#endif
#endif

	/* Freelist for duk_activations and duk_catchers. */
#if defined(DUK_USE_CACHE_ACTIVATION)
	duk_activation *activation_free;
#endif
#if defined(DUK_USE_CACHE_CATCHER)
	duk_catcher *catcher_free;
#endif

	/* Voluntary mark-and-sweep trigger counter.  Intentionally signed
	 * because we continue decreasing the value when voluntary GC cannot
	 * run.
	 */
#if defined(DUK_USE_VOLUNTARY_GC)
	duk_int_t ms_trigger_counter;
#endif

	/* Mark-and-sweep recursion control: too deep recursion causes
	 * multi-pass processing to avoid growing C stack without bound.
	 */
	duk_uint_t ms_recursion_depth;

	/* Mark-and-sweep flags automatically active (used for critical sections). */
	duk_small_uint_t ms_base_flags;

	/* Mark-and-sweep running flag.  Prevents re-entry, and also causes
	 * refzero events to be ignored (= objects won't be queued to refzero_list).
	 *
	 * 0: mark-and-sweep not running
	 * 1: mark-and-sweep is running
	 * 2: heap destruction active or debugger active, prevent mark-and-sweep
	 *    and refzero processing (but mark-and-sweep not itself running)
	 */
	duk_uint_t ms_running;

	/* Mark-and-sweep prevent count, stacking.  Used to avoid M&S side
	 * effects (besides finalizers which are controlled separately) such
	 * as compacting the string table or object property tables.  This
	 * is also bumped when ms_running is set to prevent recursive re-entry.
	 * Can also be bumped when mark-and-sweep is not running.
	 */
	duk_uint_t ms_prevent_count;

	/* Finalizer processing prevent count, stacking.  Bumped when finalizers
	 * are processed to prevent recursive finalizer processing (first call site
	 * processing finalizers handles all finalizers until the list is empty).
	 * Can also be bumped explicitly to prevent finalizer execution.
	 */
	duk_uint_t pf_prevent_count;

	/* When processing finalize_list, don't actually run finalizers but
	 * queue finalizable objects back to heap_allocated as is.  This is
	 * used during heap destruction to deal with finalizers that keep
	 * on creating more finalizable garbage.
	 */
	duk_uint_t pf_skip_finalizers;

#if defined(DUK_USE_ASSERTIONS)
	/* Set when we're in a critical path where an error throw would cause
	 * e.g. sandboxing/protected call violations or state corruption.  This
	 * is just used for asserts.
	 */
	duk_bool_t error_not_allowed;
#endif

#if defined(DUK_USE_ASSERTIONS)
	/* Set when heap is still being initialized, helps with writing
	 * some assertions.
	 */
	duk_bool_t heap_initializing;
#endif

	/* Marker for detecting internal "double faults", errors thrown when
	 * we're trying to create an error object, see duk_error_throw.c.
	 */
	duk_bool_t creating_error;

	/* Marker for indicating we're calling a user error augmentation
	 * (errCreate/errThrow) function.  Errors created/thrown during
	 * such a call are not augmented.
	 */
#if defined(DUK_USE_AUGMENT_ERROR_THROW) || defined(DUK_USE_AUGMENT_ERROR_CREATE)
	duk_bool_t augmenting_error;
#endif

	/* Longjmp state. */
	duk_ljstate lj;

	/* Heap thread, used internally and for finalization. */
	duk_hthread *heap_thread;

	/* Current running thread. */
	duk_hthread *curr_thread;

	/* Heap level "stash" object (e.g., various reachability roots). */
	duk_hobject *heap_object;

	/* duk_handle_call / duk_handle_safe_call recursion depth limiting */
	duk_int_t call_recursion_depth;
	duk_int_t call_recursion_limit;

	/* Mix-in value for computing string hashes; should be reasonably unpredictable. */
	duk_uint32_t hash_seed;

	/* Random number state for duk_util_tinyrandom.c. */
#if !defined(DUK_USE_GET_RANDOM_DOUBLE)
#if defined(DUK_USE_PREFER_SIZE) || !defined(DUK_USE_64BIT_OPS)
	duk_uint32_t rnd_state;  /* State for Shamir's three-op algorithm */
#else
	duk_uint64_t rnd_state[2];  /* State for xoroshiro128+ */
#endif
#endif

	/* Counter for unique local symbol creation. */
	/* XXX: When 64-bit types are available, it would be more efficient to
	 * use a duk_uint64_t at least for incrementing but maybe also for
	 * string formatting in the Symbol constructor.
	 */
	duk_uint32_t sym_counter[2];

	/* For manual debugging: instruction count based on executor and
	 * interrupt counter book-keeping.  Inspect debug logs to see how
	 * they match up.
	 */
#if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
	duk_int_t inst_count_exec;
	duk_int_t inst_count_interrupt;
#endif

	/* Debugger state. */
#if defined(DUK_USE_DEBUGGER_SUPPORT)
	/* Callbacks and udata; dbg_read_cb != NULL is used to indicate attached state. */
	duk_debug_read_function dbg_read_cb;                /* required, NULL implies detached */
	duk_debug_write_function dbg_write_cb;              /* required */
	duk_debug_peek_function dbg_peek_cb;
	duk_debug_read_flush_function dbg_read_flush_cb;
	duk_debug_write_flush_function dbg_write_flush_cb;
	duk_debug_request_function dbg_request_cb;
	duk_debug_detached_function dbg_detached_cb;
	void *dbg_udata;

	/* The following are only relevant when debugger is attached. */
	duk_bool_t dbg_processing;              /* currently processing messages or breakpoints: don't enter message processing recursively (e.g. no breakpoints when processing debugger eval) */
	duk_bool_t dbg_state_dirty;             /* resend state next time executor is about to run */
	duk_bool_t dbg_force_restart;           /* force executor restart to recheck breakpoints; used to handle function returns (see GH-303) */
	duk_bool_t dbg_detaching;               /* debugger detaching; used to avoid calling detach handler recursively */
	duk_small_uint_t dbg_pause_flags;       /* flags for automatic pause behavior */
	duk_activation *dbg_pause_act;          /* activation related to pause behavior (pause on line change, function entry/exit) */
	duk_uint32_t dbg_pause_startline;       /* starting line number for line change related pause behavior */
	duk_breakpoint dbg_breakpoints[DUK_HEAP_MAX_BREAKPOINTS];  /* breakpoints: [0,breakpoint_count[ gc reachable */
	duk_small_uint_t dbg_breakpoint_count;
	duk_breakpoint *dbg_breakpoints_active[DUK_HEAP_MAX_BREAKPOINTS + 1];  /* currently active breakpoints: NULL term, borrowed pointers */
	/* XXX: make active breakpoints actual copies instead of pointers? */

	/* These are for rate limiting Status notifications and transport peeking. */
	duk_uint_t dbg_exec_counter;            /* cumulative opcode execution count (overflows are OK) */
	duk_uint_t dbg_last_counter;            /* value of dbg_exec_counter when we last did a Date-based check */
	duk_double_t dbg_last_time;             /* time when status/peek was last done (Date-based rate limit) */

	/* Used to support single-byte stream lookahead. */
	duk_bool_t dbg_have_next_byte;
	duk_uint8_t dbg_next_byte;
#endif  /* DUK_USE_DEBUGGER_SUPPORT */
#if defined(DUK_USE_ASSERTIONS)
	duk_bool_t dbg_calling_transport;       /* transport call in progress, calling into Duktape forbidden */
#endif

	/* String intern table (weak refs). */
#if defined(DUK_USE_STRTAB_PTRCOMP)
	duk_uint16_t *strtable16;
#else
	duk_hstring **strtable;
#endif
	duk_uint32_t st_mask;    /* mask for lookup, st_size - 1 */
	duk_uint32_t st_size;    /* stringtable size */
#if (DUK_USE_STRTAB_MINSIZE != DUK_USE_STRTAB_MAXSIZE)
	duk_uint32_t st_count;   /* string count for resize load factor checks */
#endif
	duk_bool_t st_resizing;  /* string table is being resized; avoid recursive resize */

	/* String access cache (codepoint offset -> byte offset) for fast string
	 * character looping; 'weak' reference which needs special handling in GC.
	 */
	duk_strcache_entry strcache[DUK_HEAP_STRCACHE_SIZE];

#if defined(DUK_USE_LITCACHE_SIZE)
	/* Literal intern cache.  When enabled, strings interned as literals
	 * (e.g. duk_push_literal()) will be pinned and cached for the lifetime
	 * of the heap.
	 */
	duk_litcache_entry litcache[DUK_USE_LITCACHE_SIZE];
#endif

	/* Built-in strings. */
#if defined(DUK_USE_ROM_STRINGS)
	/* No field needed when strings are in ROM. */
#else
#if defined(DUK_USE_HEAPPTR16)
	duk_uint16_t strs16[DUK_HEAP_NUM_STRINGS];
#else
	duk_hstring *strs[DUK_HEAP_NUM_STRINGS];
#endif
#endif

	/* Stats. */
#if defined(DUK_USE_DEBUG)
	duk_int_t stats_exec_opcodes;
	duk_int_t stats_exec_interrupt;
	duk_int_t stats_exec_throw;
	duk_int_t stats_call_all;
	duk_int_t stats_call_tailcall;
	duk_int_t stats_call_ecmatoecma;
	duk_int_t stats_safecall_all;
	duk_int_t stats_safecall_nothrow;
	duk_int_t stats_safecall_throw;
	duk_int_t stats_ms_try_count;
	duk_int_t stats_ms_skip_count;
	duk_int_t stats_ms_emergency_count;
	duk_int_t stats_strtab_intern_hit;
	duk_int_t stats_strtab_intern_miss;
	duk_int_t stats_strtab_resize_check;
	duk_int_t stats_strtab_resize_grow;
	duk_int_t stats_strtab_resize_shrink;
	duk_int_t stats_strtab_litcache_hit;
	duk_int_t stats_strtab_litcache_miss;
	duk_int_t stats_strtab_litcache_pin;
	duk_int_t stats_object_realloc_props;
	duk_int_t stats_object_abandon_array;
	duk_int_t stats_getownpropdesc_count;
	duk_int_t stats_getownpropdesc_hit;
	duk_int_t stats_getownpropdesc_miss;
	duk_int_t stats_getpropdesc_count;
	duk_int_t stats_getpropdesc_hit;
	duk_int_t stats_getpropdesc_miss;
	duk_int_t stats_getprop_all;
	duk_int_t stats_getprop_arrayidx;
	duk_int_t stats_getprop_bufobjidx;
	duk_int_t stats_getprop_bufferidx;
	duk_int_t stats_getprop_bufferlen;
	duk_int_t stats_getprop_stringidx;
	duk_int_t stats_getprop_stringlen;
	duk_int_t stats_getprop_proxy;
	duk_int_t stats_getprop_arguments;
	duk_int_t stats_putprop_all;
	duk_int_t stats_putprop_arrayidx;
	duk_int_t stats_putprop_bufobjidx;
	duk_int_t stats_putprop_bufferidx;
	duk_int_t stats_putprop_proxy;
	duk_int_t stats_getvar_all;
	duk_int_t stats_putvar_all;
	duk_int_t stats_envrec_delayedcreate;
	duk_int_t stats_envrec_create;
	duk_int_t stats_envrec_newenv;
	duk_int_t stats_envrec_oldenv;
	duk_int_t stats_envrec_pushclosure;
#endif
};

/*
 *  Prototypes
 */

DUK_INTERNAL_DECL
duk_heap *duk_heap_alloc(duk_alloc_function alloc_func,
                         duk_realloc_function realloc_func,
                         duk_free_function free_func,
                         void *heap_udata,
                         duk_fatal_function fatal_func);
DUK_INTERNAL_DECL void duk_heap_free(duk_heap *heap);
DUK_INTERNAL_DECL void duk_free_hobject(duk_heap *heap, duk_hobject *h);
DUK_INTERNAL_DECL void duk_free_hbuffer(duk_heap *heap, duk_hbuffer *h);
DUK_INTERNAL_DECL void duk_free_hstring(duk_heap *heap, duk_hstring *h);
DUK_INTERNAL_DECL void duk_heap_free_heaphdr_raw(duk_heap *heap, duk_heaphdr *hdr);

DUK_INTERNAL_DECL void duk_heap_insert_into_heap_allocated(duk_heap *heap, duk_heaphdr *hdr);
#if defined(DUK_USE_REFERENCE_COUNTING)
DUK_INTERNAL_DECL void duk_heap_remove_from_heap_allocated(duk_heap *heap, duk_heaphdr *hdr);
#endif
#if defined(DUK_USE_FINALIZER_SUPPORT)
DUK_INTERNAL_DECL void duk_heap_insert_into_finalize_list(duk_heap *heap, duk_heaphdr *hdr);
DUK_INTERNAL_DECL void duk_heap_remove_from_finalize_list(duk_heap *heap, duk_heaphdr *hdr);
#endif
#if defined(DUK_USE_ASSERTIONS)
DUK_INTERNAL_DECL duk_bool_t duk_heap_in_heap_allocated(duk_heap *heap, duk_heaphdr *ptr);
#endif
#if defined(DUK_USE_INTERRUPT_COUNTER)
DUK_INTERNAL_DECL void duk_heap_switch_thread(duk_heap *heap, duk_hthread *new_thr);
#endif

DUK_INTERNAL_DECL duk_hstring *duk_heap_strtable_intern(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen);
DUK_INTERNAL_DECL duk_hstring *duk_heap_strtable_intern_checked(duk_hthread *thr, const duk_uint8_t *str, duk_uint32_t len);
#if defined(DUK_USE_LITCACHE_SIZE)
DUK_INTERNAL_DECL duk_hstring *duk_heap_strtable_intern_literal_checked(duk_hthread *thr, const duk_uint8_t *str, duk_uint32_t blen);
#endif
DUK_INTERNAL_DECL duk_hstring *duk_heap_strtable_intern_u32(duk_heap *heap, duk_uint32_t val);
DUK_INTERNAL_DECL duk_hstring *duk_heap_strtable_intern_u32_checked(duk_hthread *thr, duk_uint32_t val);
#if defined(DUK_USE_REFERENCE_COUNTING)
DUK_INTERNAL_DECL void duk_heap_strtable_unlink(duk_heap *heap, duk_hstring *h);
#endif
DUK_INTERNAL_DECL void duk_heap_strtable_unlink_prev(duk_heap *heap, duk_hstring *h, duk_hstring *prev);
DUK_INTERNAL_DECL void duk_heap_strtable_force_resize(duk_heap *heap);
DUK_INTERNAL void duk_heap_strtable_free(duk_heap *heap);
#if defined(DUK_USE_DEBUG)
DUK_INTERNAL void duk_heap_strtable_dump(duk_heap *heap);
#endif

DUK_INTERNAL_DECL void duk_heap_strcache_string_remove(duk_heap *heap, duk_hstring *h);
DUK_INTERNAL_DECL duk_uint_fast32_t duk_heap_strcache_offset_char2byte(duk_hthread *thr, duk_hstring *h, duk_uint_fast32_t char_offset);

#if defined(DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS)
DUK_INTERNAL_DECL void *duk_default_alloc_function(void *udata, duk_size_t size);
DUK_INTERNAL_DECL void *duk_default_realloc_function(void *udata, void *ptr, duk_size_t newsize);
DUK_INTERNAL_DECL void duk_default_free_function(void *udata, void *ptr);
#endif

DUK_INTERNAL_DECL void *duk_heap_mem_alloc(duk_heap *heap, duk_size_t size);
DUK_INTERNAL_DECL void *duk_heap_mem_alloc_zeroed(duk_heap *heap, duk_size_t size);
DUK_INTERNAL_DECL void *duk_heap_mem_alloc_checked(duk_hthread *thr, duk_size_t size);
DUK_INTERNAL_DECL void *duk_heap_mem_alloc_checked_zeroed(duk_hthread *thr, duk_size_t size);
DUK_INTERNAL_DECL void *duk_heap_mem_realloc(duk_heap *heap, void *ptr, duk_size_t newsize);
DUK_INTERNAL_DECL void *duk_heap_mem_realloc_indirect(duk_heap *heap, duk_mem_getptr cb, void *ud, duk_size_t newsize);
DUK_INTERNAL_DECL void duk_heap_mem_free(duk_heap *heap, void *ptr);

DUK_INTERNAL_DECL void duk_heap_free_freelists(duk_heap *heap);

#if defined(DUK_USE_FINALIZER_SUPPORT)
DUK_INTERNAL_DECL void duk_heap_run_finalizer(duk_heap *heap, duk_hobject *obj);
DUK_INTERNAL_DECL void duk_heap_process_finalize_list(duk_heap *heap);
#endif  /* DUK_USE_FINALIZER_SUPPORT */

DUK_INTERNAL_DECL void duk_heap_mark_and_sweep(duk_heap *heap, duk_small_uint_t flags);

DUK_INTERNAL_DECL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const duk_uint8_t *str, duk_size_t len);

#endif  /* DUK_HEAP_H_INCLUDED */
/* #include duk_debugger.h */
#line 1 "duk_debugger.h"
#if !defined(DUK_DEBUGGER_H_INCLUDED)
#define DUK_DEBUGGER_H_INCLUDED

/* Debugger protocol version is defined in the public API header. */

/* Initial bytes for markers. */
#define DUK_DBG_IB_EOM                   0x00
#define DUK_DBG_IB_REQUEST               0x01
#define DUK_DBG_IB_REPLY                 0x02
#define DUK_DBG_IB_ERROR                 0x03
#define DUK_DBG_IB_NOTIFY                0x04

/* Other initial bytes. */
#define DUK_DBG_IB_INT4                  0x10
#define DUK_DBG_IB_STR4                  0x11
#define DUK_DBG_IB_STR2                  0x12
#define DUK_DBG_IB_BUF4                  0x13
#define DUK_DBG_IB_BUF2                  0x14
#define DUK_DBG_IB_UNUSED                0x15
#define DUK_DBG_IB_UNDEFINED             0x16
#define DUK_DBG_IB_NULL                  0x17
#define DUK_DBG_IB_TRUE                  0x18
#define DUK_DBG_IB_FALSE                 0x19
#define DUK_DBG_IB_NUMBER                0x1a
#define DUK_DBG_IB_OBJECT                0x1b
#define DUK_DBG_IB_POINTER               0x1c
#define DUK_DBG_IB_LIGHTFUNC             0x1d
#define DUK_DBG_IB_HEAPPTR               0x1e
/* The short string/integer initial bytes starting from 0x60 don't have
 * defines now.
 */

/* Error codes. */
#define DUK_DBG_ERR_UNKNOWN              0x00
#define DUK_DBG_ERR_UNSUPPORTED          0x01
#define DUK_DBG_ERR_TOOMANY              0x02
#define DUK_DBG_ERR_NOTFOUND             0x03
#define DUK_DBG_ERR_APPLICATION          0x04

/* Commands and notifys initiated by Duktape. */
#define DUK_DBG_CMD_STATUS               0x01
#define DUK_DBG_CMD_UNUSED_2             0x02  /* Duktape 1.x: print notify */
#define DUK_DBG_CMD_UNUSED_3             0x03  /* Duktape 1.x: alert notify */
#define DUK_DBG_CMD_UNUSED_4             0x04  /* Duktape 1.x: log notify */
#define DUK_DBG_CMD_THROW                0x05
#define DUK_DBG_CMD_DETACHING            0x06
#define DUK_DBG_CMD_APPNOTIFY            0x07

/* Commands initiated by debug client. */
#define DUK_DBG_CMD_BASICINFO            0x10
#define DUK_DBG_CMD_TRIGGERSTATUS        0x11
#define DUK_DBG_CMD_PAUSE                0x12
#define DUK_DBG_CMD_RESUME               0x13
#define DUK_DBG_CMD_STEPINTO             0x14
#define DUK_DBG_CMD_STEPOVER             0x15
#define DUK_DBG_CMD_STEPOUT              0x16
#define DUK_DBG_CMD_LISTBREAK            0x17
#define DUK_DBG_CMD_ADDBREAK             0x18
#define DUK_DBG_CMD_DELBREAK             0x19
#define DUK_DBG_CMD_GETVAR               0x1a
#define DUK_DBG_CMD_PUTVAR               0x1b
#define DUK_DBG_CMD_GETCALLSTACK         0x1c
#define DUK_DBG_CMD_GETLOCALS            0x1d
#define DUK_DBG_CMD_EVAL                 0x1e
#define DUK_DBG_CMD_DETACH               0x1f
#define DUK_DBG_CMD_DUMPHEAP             0x20
#define DUK_DBG_CMD_GETBYTECODE          0x21
#define DUK_DBG_CMD_APPREQUEST           0x22
#define DUK_DBG_CMD_GETHEAPOBJINFO       0x23
#define DUK_DBG_CMD_GETOBJPROPDESC       0x24
#define DUK_DBG_CMD_GETOBJPROPDESCRANGE  0x25

/* The low 8 bits map directly to duk_hobject.h DUK_PROPDESC_FLAG_xxx.
 * The remaining flags are specific to the debugger.
 */
#define DUK_DBG_PROPFLAG_SYMBOL          (1U << 8)
#define DUK_DBG_PROPFLAG_HIDDEN          (1U << 9)

#if defined(DUK_USE_DEBUGGER_SUPPORT)
DUK_INTERNAL_DECL void duk_debug_do_detach(duk_heap *heap);

DUK_INTERNAL_DECL duk_bool_t duk_debug_read_peek(duk_hthread *thr);
DUK_INTERNAL_DECL void duk_debug_write_flush(duk_hthread *thr);

DUK_INTERNAL_DECL void duk_debug_skip_bytes(duk_hthread *thr, duk_size_t length);
DUK_INTERNAL_DECL void duk_debug_skip_byte(duk_hthread *thr);

DUK_INTERNAL_DECL void duk_debug_read_bytes(duk_hthread *thr, duk_uint8_t *data, duk_size_t length);
DUK_INTERNAL_DECL duk_uint8_t duk_debug_read_byte(duk_hthread *thr);
DUK_INTERNAL_DECL duk_int32_t duk_debug_read_int(duk_hthread *thr);
DUK_INTERNAL_DECL duk_hstring *duk_debug_read_hstring(duk_hthread *thr);
/* XXX: exposed duk_debug_read_pointer */
/* XXX: exposed duk_debug_read_buffer */
/* XXX: exposed duk_debug_read_hbuffer */
#if 0
DUK_INTERNAL_DECL duk_heaphdr *duk_debug_read_heapptr(duk_hthread *thr);
#endif
#if defined(DUK_USE_DEBUGGER_INSPECT)
DUK_INTERNAL_DECL duk_heaphdr *duk_debug_read_any_ptr(duk_hthread *thr);
#endif
DUK_INTERNAL_DECL duk_tval *duk_debug_read_tval(duk_hthread *thr);

DUK_INTERNAL_DECL void duk_debug_write_bytes(duk_hthread *thr, const duk_uint8_t *data, duk_size_t length);
DUK_INTERNAL_DECL void duk_debug_write_byte(duk_hthread *thr, duk_uint8_t x);
DUK_INTERNAL_DECL void duk_debug_write_unused(duk_hthread *thr);
DUK_INTERNAL_DECL void duk_debug_write_undefined(duk_hthread *thr);
#if defined(DUK_USE_DEBUGGER_INSPECT)
DUK_INTERNAL_DECL void duk_debug_write_null(duk_hthread *thr);
#endif
DUK_INTERNAL_DECL void duk_debug_write_boolean(duk_hthread *thr, duk_uint_t val);
DUK_INTERNAL_DECL void duk_debug_write_int(duk_hthread *thr, duk_int32_t x);
DUK_INTERNAL_DECL void duk_debug_write_uint(duk_hthread *thr, duk_uint32_t x);
DUK_INTERNAL_DECL void duk_debug_write_string(duk_hthread *thr, const char *data, duk_size_t length);
DUK_INTERNAL_DECL void duk_debug_write_cstring(duk_hthread *thr, const char *data);
DUK_INTERNAL_DECL void duk_debug_write_hstring(duk_hthread *thr, duk_hstring *h);
DUK_INTERNAL_DECL void duk_debug_write_buffer(duk_hthread *thr, const char *data, duk_size_t length);
DUK_INTERNAL_DECL void duk_debug_write_hbuffer(duk_hthread *thr, duk_hbuffer *h);
DUK_INTERNAL_DECL void duk_debug_write_pointer(duk_hthread *thr, void *ptr);
#if defined(DUK_USE_DEBUGGER_DUMPHEAP) || defined(DUK_USE_DEBUGGER_INSPECT)
DUK_INTERNAL_DECL void duk_debug_write_heapptr(duk_hthread *thr, duk_heaphdr *h);
#endif
DUK_INTERNAL_DECL void duk_debug_write_hobject(duk_hthread *thr, duk_hobject *obj);
DUK_INTERNAL_DECL void duk_debug_write_tval(duk_hthread *thr, duk_tval *tv);
#if 0  /* unused */
DUK_INTERNAL_DECL void duk_debug_write_request(duk_hthread *thr, duk_small_uint_t command);
#endif
DUK_INTERNAL_DECL void duk_debug_write_reply(duk_hthread *thr);
DUK_INTERNAL_DECL void duk_debug_write_error_eom(duk_hthread *thr, duk_small_uint_t err_code, const char *msg);
DUK_INTERNAL_DECL void duk_debug_write_notify(duk_hthread *thr, duk_small_uint_t command);
DUK_INTERNAL_DECL void duk_debug_write_eom(duk_hthread *thr);

DUK_INTERNAL_DECL duk_uint_fast32_t duk_debug_curr_line(duk_hthread *thr);
DUK_INTERNAL_DECL void duk_debug_send_status(duk_hthread *thr);
#if defined(DUK_USE_DEBUGGER_THROW_NOTIFY)
DUK_INTERNAL_DECL void duk_debug_send_throw(duk_hthread *thr, duk_bool_t fatal);
#endif

DUK_INTERNAL_DECL void duk_debug_halt_execution(duk_hthread *thr, duk_bool_t use_prev_pc);
DUK_INTERNAL_DECL duk_bool_t duk_debug_process_messages(duk_hthread *thr, duk_bool_t no_block);

DUK_INTERNAL_DECL duk_small_int_t duk_debug_add_breakpoint(duk_hthread *thr, duk_hstring *filename, duk_uint32_t line);
DUK_INTERNAL_DECL duk_bool_t duk_debug_remove_breakpoint(duk_hthread *thr, duk_small_uint_t breakpoint_index);

DUK_INTERNAL_DECL duk_bool_t duk_debug_is_attached(duk_heap *heap);
DUK_INTERNAL_DECL duk_bool_t duk_debug_is_paused(duk_heap *heap);
DUK_INTERNAL_DECL void duk_debug_set_paused(duk_heap *heap);
DUK_INTERNAL_DECL void duk_debug_clear_paused(duk_heap *heap);
DUK_INTERNAL_DECL void duk_debug_clear_pause_state(duk_heap *heap);
#endif  /* DUK_USE_DEBUGGER_SUPPORT */

#endif  /* DUK_DEBUGGER_H_INCLUDED */
/* #include duk_debug.h */
#line 1 "duk_debug.h"
/*
 *  Debugging macros, DUK_DPRINT() and its variants in particular.
 *
 *  DUK_DPRINT() allows formatted debug prints, and supports standard
 *  and Duktape specific formatters.  See duk_debug_vsnprintf.c for details.
 *
 *  DUK_D(x), DUK_DD(x), and DUK_DDD(x) are used together with log macros
 *  for technical reasons.  They are concretely used to hide 'x' from the
 *  compiler when the corresponding log level is disabled.  This allows
 *  clean builds on non-C99 compilers, at the cost of more verbose code.
 *  Examples:
 *
 *    DUK_D(DUK_DPRINT("foo"));
 *    DUK_DD(DUK_DDPRINT("foo"));
 *    DUK_DDD(DUK_DDDPRINT("foo"));
 *
 *  This approach is preferable to the old "double parentheses" hack because
 *  double parentheses make the C99 solution worse: __FILE__ and __LINE__ can
 *  no longer be added transparently without going through globals, which
 *  works poorly with threading.
 */

#if !defined(DUK_DEBUG_H_INCLUDED)
#define DUK_DEBUG_H_INCLUDED

#if defined(DUK_USE_DEBUG)

#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 0)
#define DUK_D(x) x
#else
#define DUK_D(x) do { } while (0) /* omit */
#endif

#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 1)
#define DUK_DD(x) x
#else
#define DUK_DD(x) do { } while (0) /* omit */
#endif

#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
#define DUK_DDD(x) x
#else
#define DUK_DDD(x) do { } while (0) /* omit */
#endif

/*
 *  Exposed debug macros: debugging enabled
 */

#if defined(DUK_USE_VARIADIC_MACROS)

/* Note: combining __FILE__, __LINE__, and __func__ into fmt would be
 * possible compile time, but waste some space with shared function names.
 */
#define DUK__DEBUG_LOG(lev,...)  duk_debug_log((duk_int_t) (lev), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, DUK_FUNC_MACRO, __VA_ARGS__);

#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 0)
#define DUK_DPRINT(...)          DUK__DEBUG_LOG(DUK_LEVEL_DEBUG, __VA_ARGS__)
#else
#define DUK_DPRINT(...)
#endif

#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 1)
#define DUK_DDPRINT(...)         DUK__DEBUG_LOG(DUK_LEVEL_DDEBUG, __VA_ARGS__)
#else
#define DUK_DDPRINT(...)
#endif

#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
#define DUK_DDDPRINT(...)        DUK__DEBUG_LOG(DUK_LEVEL_DDDEBUG, __VA_ARGS__)
#else
#define DUK_DDDPRINT(...)
#endif

#else  /* DUK_USE_VARIADIC_MACROS */

#define DUK__DEBUG_STASH(lev)    \
	(void) DUK_SNPRINTF(duk_debug_file_stash, DUK_DEBUG_STASH_SIZE, "%s", (const char *) DUK_FILE_MACRO), \
	(void) (duk_debug_file_stash[DUK_DEBUG_STASH_SIZE - 1] = (char) 0), \
	(void) (duk_debug_line_stash = (duk_int_t) DUK_LINE_MACRO), \
	(void) DUK_SNPRINTF(duk_debug_func_stash, DUK_DEBUG_STASH_SIZE, "%s", (const char *) DUK_FUNC_MACRO), \
	(void) (duk_debug_func_stash[DUK_DEBUG_STASH_SIZE - 1] = (char) 0), \
	(void) (duk_debug_level_stash = (lev))

/* Without variadic macros resort to comma expression trickery to handle debug
 * prints.  This generates a lot of harmless warnings.  These hacks are not
 * needed normally because DUK_D() and friends will hide the entire debug log
 * statement from the compiler.
 */

#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 0)
#define DUK_DPRINT  DUK__DEBUG_STASH(DUK_LEVEL_DEBUG), (void) duk_debug_log  /* args go here in parens */
#else
#define DUK_DPRINT  0 && /* args go here as a comma expression in parens */
#endif

#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 1)
#define DUK_DDPRINT  DUK__DEBUG_STASH(DUK_LEVEL_DDEBUG), (void) duk_debug_log  /* args go here in parens */
#else
#define DUK_DDPRINT  0 && /* args */
#endif

#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
#define DUK_DDDPRINT  DUK__DEBUG_STASH(DUK_LEVEL_DDDEBUG), (void) duk_debug_log  /* args go here in parens */
#else
#define DUK_DDDPRINT  0 && /* args */
#endif

#endif  /* DUK_USE_VARIADIC_MACROS */

#else  /* DUK_USE_DEBUG */

/*
 *  Exposed debug macros: debugging disabled
 */

#define DUK_D(x) do { } while (0) /* omit */
#define DUK_DD(x) do { } while (0) /* omit */
#define DUK_DDD(x) do { } while (0) /* omit */

#if defined(DUK_USE_VARIADIC_MACROS)

#define DUK_DPRINT(...)
#define DUK_DDPRINT(...)
#define DUK_DDDPRINT(...)

#else  /* DUK_USE_VARIADIC_MACROS */

#define DUK_DPRINT    0 && /* args go here as a comma expression in parens */
#define DUK_DDPRINT   0 && /* args */
#define DUK_DDDPRINT  0 && /* args */

#endif  /* DUK_USE_VARIADIC_MACROS */

#endif  /* DUK_USE_DEBUG */

/*
 *  Structs
 */

#if defined(DUK_USE_DEBUG)
struct duk_fixedbuffer {
	duk_uint8_t *buffer;
	duk_size_t length;
	duk_size_t offset;
	duk_bool_t truncated;
};
#endif

/*
 *  Prototypes
 */

#if defined(DUK_USE_DEBUG)
DUK_INTERNAL_DECL duk_int_t duk_debug_vsnprintf(char *str, duk_size_t size, const char *format, va_list ap);
#if 0  /*unused*/
DUK_INTERNAL_DECL duk_int_t duk_debug_snprintf(char *str, duk_size_t size, const char *format, ...);
#endif
DUK_INTERNAL_DECL void duk_debug_format_funcptr(char *buf, duk_size_t buf_size, duk_uint8_t *fptr, duk_size_t fptr_size);

#if defined(DUK_USE_VARIADIC_MACROS)
DUK_INTERNAL_DECL void duk_debug_log(duk_int_t level, const char *file, duk_int_t line, const char *func, const char *fmt, ...);
#else  /* DUK_USE_VARIADIC_MACROS */
/* parameter passing, not thread safe */
#define DUK_DEBUG_STASH_SIZE  128
#if !defined(DUK_SINGLE_FILE)
DUK_INTERNAL_DECL char duk_debug_file_stash[DUK_DEBUG_STASH_SIZE];
DUK_INTERNAL_DECL duk_int_t duk_debug_line_stash;
DUK_INTERNAL_DECL char duk_debug_func_stash[DUK_DEBUG_STASH_SIZE];
DUK_INTERNAL_DECL duk_int_t duk_debug_level_stash;
#endif
DUK_INTERNAL_DECL void duk_debug_log(const char *fmt, ...);
#endif  /* DUK_USE_VARIADIC_MACROS */

DUK_INTERNAL_DECL void duk_fb_put_bytes(duk_fixedbuffer *fb, const duk_uint8_t *buffer, duk_size_t length);
DUK_INTERNAL_DECL void duk_fb_put_byte(duk_fixedbuffer *fb, duk_uint8_t x);
DUK_INTERNAL_DECL void duk_fb_put_cstring(duk_fixedbuffer *fb, const char *x);
DUK_INTERNAL_DECL void duk_fb_sprintf(duk_fixedbuffer *fb, const char *fmt, ...);
DUK_INTERNAL_DECL void duk_fb_put_funcptr(duk_fixedbuffer *fb, duk_uint8_t *fptr, duk_size_t fptr_size);
DUK_INTERNAL_DECL duk_bool_t duk_fb_is_full(duk_fixedbuffer *fb);

#endif  /* DUK_USE_DEBUG */

#endif  /* DUK_DEBUG_H_INCLUDED */
/* #include duk_error.h */
#line 1 "duk_error.h"
/*
 *  Error handling macros, assertion macro, error codes.
 *
 *  There are three types of 'errors':
 *
 *    1. Ordinary errors relative to a thread, cause a longjmp, catchable.
 *    2. Fatal errors relative to a heap, cause fatal handler to be called.
 *    3. Fatal errors without context, cause the default (not heap specific)
 *       fatal handler to be called.
 *
 *  Fatal errors without context are used by debug code such as assertions.
 *  By providing a fatal error handler for a Duktape heap, user code can
 *  avoid fatal errors without context in non-debug builds.
 */

#if !defined(DUK_ERROR_H_INCLUDED)
#define DUK_ERROR_H_INCLUDED

/*
 *  Error codes: defined in duktape.h
 *
 *  Error codes are used as a shorthand to throw exceptions from inside
 *  the implementation.  The appropriate ECMAScript object is constructed
 *  based on the code.  ECMAScript code throws objects directly.  The error
 *  codes are defined in the public API header because they are also used
 *  by calling code.
 */

/*
 *  Normal error
 *
 *  Normal error is thrown with a longjmp() through the current setjmp()
 *  catchpoint record in the duk_heap.  The 'curr_thread' of the duk_heap
 *  identifies the throwing thread.
 *
 *  Error formatting is usually unnecessary.  The error macros provide a
 *  zero argument version (no formatting) and separate macros for small
 *  argument counts.  Variadic macros are not used to avoid portability
 *  issues and avoid the need for stash-based workarounds when they're not
 *  available.  Vararg calls are avoided for non-formatted error calls
 *  because vararg call sites are larger than normal, and there are a lot
 *  of call sites with no formatting.
 *
 *  Note that special formatting provided by debug macros is NOT available.
 *
 *  The _RAW variants allow the caller to specify file and line.  This makes
 *  it easier to write checked calls which want to use the call site of the
 *  checked function, not the error macro call inside the checked function.
 */

#if defined(DUK_USE_VERBOSE_ERRORS)

/* Because there are quite many call sites, pack error code (require at most
 * 8-bit) into a single argument.
 */
#define DUK_ERROR(thr,err,msg) do { \
		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
		duk_err_handle_error((thr), DUK_FILE_MACRO, (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (msg)); \
	} while (0)
#define DUK_ERROR_RAW(thr,file,line,err,msg) do { \
		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \
		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
		duk_err_handle_error((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (msg)); \
	} while (0)

#define DUK_ERROR_FMT1(thr,err,fmt,arg1) do { \
		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
		duk_err_handle_error_fmt((thr), DUK_FILE_MACRO, (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1)); \
	} while (0)
#define DUK_ERROR_RAW_FMT1(thr,file,line,err,fmt,arg1) do { \
		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \
		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
		duk_err_handle_error_fmt((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1)); \
	} while (0)

#define DUK_ERROR_FMT2(thr,err,fmt,arg1,arg2) do { \
		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
		duk_err_handle_error_fmt((thr), DUK_FILE_MACRO, (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2)); \
	} while (0)
#define DUK_ERROR_RAW_FMT2(thr,file,line,err,fmt,arg1,arg2) do { \
		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \
		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
		duk_err_handle_error_fmt((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2)); \
	} while (0)

#define DUK_ERROR_FMT3(thr,err,fmt,arg1,arg2,arg3) do { \
		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
		duk_err_handle_error_fmt((thr), DUK_FILE_MACRO, (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2), (arg3)); \
	} while (0)
#define DUK_ERROR_RAW_FMT3(thr,file,line,err,fmt,arg1,arg2,arg3) do { \
		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \
		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
		duk_err_handle_error_fmt((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2), (arg3)); \
	} while (0)

#define DUK_ERROR_FMT4(thr,err,fmt,arg1,arg2,arg3,arg4) do { \
		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
		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)); \
	} while (0)
#define DUK_ERROR_RAW_FMT4(thr,file,line,err,fmt,arg1,arg2,arg3,arg4) do { \
		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \
		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
		duk_err_handle_error_fmt((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2), (arg3), (arg4)); \
	} while (0)

#else  /* DUK_USE_VERBOSE_ERRORS */

#define DUK_ERROR(thr,err,msg)                    duk_err_handle_error((thr), (err))
#define DUK_ERROR_RAW(thr,file,line,err,msg)      duk_err_handle_error((thr), (err))

#define DUK_ERROR_FMT1(thr,err,fmt,arg1) DUK_ERROR((thr),(err),(fmt))
#define DUK_ERROR_RAW_FMT1(thr,file,line,err,fmt,arg1) DUK_ERROR_RAW((thr),(file),(line),(err),(fmt))

#define DUK_ERROR_FMT2(thr,err,fmt,arg1,arg2) DUK_ERROR((thr),(err),(fmt))
#define DUK_ERROR_RAW_FMT2(thr,file,line,err,fmt,arg1,arg2) DUK_ERROR_RAW((thr),(file),(line),(err),(fmt))

#define DUK_ERROR_FMT3(thr,err,fmt,arg1,arg2,arg3) DUK_ERROR((thr),(err),(fmt))
#define DUK_ERROR_RAW_FMT3(thr,file,line,err,fmt,arg1,arg2,arg3) DUK_ERROR_RAW((thr),(file),(line),(err),(fmt))

#define DUK_ERROR_FMT4(thr,err,fmt,arg1,arg2,arg3,arg4) DUK_ERROR((thr),(err),(fmt))
#define DUK_ERROR_RAW_FMT4(thr,file,line,err,fmt,arg1,arg2,arg3,arg4) DUK_ERROR_RAW((thr),(file),(line),(err),(fmt))

#endif  /* DUK_USE_VERBOSE_ERRORS */

/*
 *  Fatal error without context
 *
 *  The macro is an expression to make it compatible with DUK_ASSERT_EXPR().
 */

#define DUK_FATAL_WITHOUT_CONTEXT(msg) \
	duk_default_fatal_handler(NULL, (msg))

/*
 *  Error throwing helpers
 *
 *  The goal is to provide verbose and configurable error messages.  Call
 *  sites should be clean in source code and compile to a small footprint.
 *  Small footprint is also useful for performance because small cold paths
 *  reduce code cache pressure.  Adding macros here only makes sense if there
 *  are enough call sites to get concrete benefits.
 *
 *  DUK_ERROR_xxx() macros are generic and can be used anywhere.
 *
 *  DUK_DCERROR_xxx() macros can only be used in Duktape/C functions where
 *  the "return DUK_RET_xxx;" shorthand is available for low memory targets.
 *  The DUK_DCERROR_xxx() macros always either throw or perform a
 *  'return DUK_RET_xxx' from the calling function.
 */

#if defined(DUK_USE_VERBOSE_ERRORS)
/* Verbose errors with key/value summaries (non-paranoid) or without key/value
 * summaries (paranoid, for some security sensitive environments), the paranoid
 * vs. non-paranoid distinction affects only a few specific errors.
 */
#if defined(DUK_USE_PARANOID_ERRORS)
#define DUK_ERROR_REQUIRE_TYPE_INDEX(thr,idx,expectname,lowmemstr) do { \
		duk_err_require_type_index((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (idx), (expectname)); \
	} while (0)
#else  /* DUK_USE_PARANOID_ERRORS */
#define DUK_ERROR_REQUIRE_TYPE_INDEX(thr,idx,expectname,lowmemstr) do { \
		duk_err_require_type_index((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (idx), (expectname)); \
	} while (0)
#endif  /* DUK_USE_PARANOID_ERRORS */

#define DUK_ERROR_INTERNAL(thr) do { \
		duk_err_error_internal((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
	} while (0)
#define DUK_DCERROR_INTERNAL(thr) do { \
		DUK_ERROR_INTERNAL((thr)); \
		return 0; \
	} while (0)
#define DUK_ERROR_ALLOC_FAILED(thr) do { \
		duk_err_error_alloc_failed((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
	} while (0)
#define DUK_ERROR_UNSUPPORTED(thr) do { \
		DUK_ERROR((thr), DUK_ERR_ERROR, DUK_STR_UNSUPPORTED); \
	} while (0)
#define DUK_DCERROR_UNSUPPORTED(thr) do { \
		DUK_ERROR_UNSUPPORTED((thr)); \
		return 0; \
	} while (0)
#define DUK_ERROR_ERROR(thr,msg) do { \
		duk_err_error((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (msg)); \
	} while (0)
#define DUK_ERROR_RANGE_INDEX(thr,idx) do { \
		duk_err_range_index((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (idx)); \
	} while (0)
#define DUK_ERROR_RANGE_PUSH_BEYOND(thr) do { \
		duk_err_range_push_beyond((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
	} while (0)
#define DUK_ERROR_RANGE_INVALID_ARGS(thr) do { \
		DUK_ERROR_RANGE((thr), DUK_STR_INVALID_ARGS); \
	} while (0)
#define DUK_DCERROR_RANGE_INVALID_ARGS(thr) do { \
		DUK_ERROR_RANGE_INVALID_ARGS((thr)); \
		return 0; \
	} while (0)
#define DUK_ERROR_RANGE_INVALID_COUNT(thr) do { \
		DUK_ERROR_RANGE((thr), DUK_STR_INVALID_COUNT); \
	} while (0)
#define DUK_DCERROR_RANGE_INVALID_COUNT(thr) do { \
		DUK_ERROR_RANGE_INVALID_COUNT((thr)); \
		return 0; \
	} while (0)
#define DUK_ERROR_RANGE_INVALID_LENGTH(thr) do { \
		DUK_ERROR_RANGE((thr), DUK_STR_INVALID_LENGTH); \
	} while (0)
#define DUK_DCERROR_RANGE_INVALID_LENGTH(thr) do { \
		DUK_ERROR_RANGE_INVALID_LENGTH((thr)); \
		return 0; \
	} while (0)
#define DUK_ERROR_RANGE(thr,msg) do { \
		duk_err_range((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (msg)); \
	} while (0)
#define DUK_ERROR_EVAL(thr,msg) do { \
		DUK_ERROR((thr), DUK_ERR_EVAL_ERROR, (msg)); \
	} while (0)
#define DUK_ERROR_REFERENCE(thr,msg) do { \
		DUK_ERROR((thr), DUK_ERR_REFERENCE_ERROR, (msg)); \
	} while (0)
#define DUK_ERROR_SYNTAX(thr,msg) do { \
		DUK_ERROR((thr), DUK_ERR_SYNTAX_ERROR, (msg)); \
	} while (0)
#define DUK_ERROR_TYPE_INVALID_ARGS(thr) do { \
		duk_err_type_invalid_args((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
	} while (0)
#define DUK_DCERROR_TYPE_INVALID_ARGS(thr) do { \
		DUK_ERROR_TYPE_INVALID_ARGS((thr)); \
		return 0; \
	} while (0)
#define DUK_ERROR_TYPE_INVALID_STATE(thr) do { \
		duk_err_type_invalid_state((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
	} while (0)
#define DUK_DCERROR_TYPE_INVALID_STATE(thr) do { \
		DUK_ERROR_TYPE_INVALID_STATE((thr)); \
		return 0; \
	} while (0)
#define DUK_ERROR_TYPE_INVALID_TRAP_RESULT(thr) do { \
		duk_err_type_invalid_trap_result((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
	} while (0)
#define DUK_DCERROR_TYPE_INVALID_TRAP_RESULT(thr) do { \
		DUK_ERROR_TYPE((thr), DUK_STR_INVALID_TRAP_RESULT); \
	} while (0)
#define DUK_ERROR_TYPE(thr,msg) do { \
		DUK_ERROR((thr), DUK_ERR_TYPE_ERROR, (msg)); \
	} while (0)
#define DUK_ERROR_URI(thr,msg) do { \
		DUK_ERROR((thr), DUK_ERR_URI_ERROR, (msg)); \
	} while (0)
#else  /* DUK_USE_VERBOSE_ERRORS */
/* Non-verbose errors for low memory targets: no file, line, or message. */

#define DUK_ERROR_REQUIRE_TYPE_INDEX(thr,idx,expectname,lowmemstr) do { \
		duk_err_type((thr)); \
	} while (0)

#define DUK_ERROR_INTERNAL(thr) do { \
		duk_err_error((thr)); \
	} while (0)
#define DUK_DCERROR_INTERNAL(thr) do { \
		DUK_UNREF((thr)); \
		return DUK_RET_ERROR; \
	} while (0)
#define DUK_ERROR_ALLOC_FAILED(thr) do { \
		duk_err_error((thr)); \
	} while (0)
#define DUK_ERROR_UNSUPPORTED(thr) do { \
		duk_err_error((thr)); \
	} while (0)
#define DUK_DCERROR_UNSUPPORTED(thr) do { \
		DUK_UNREF((thr)); \
		return DUK_RET_ERROR; \
	} while (0)
#define DUK_ERROR_ERROR(thr,msg) do { \
		duk_err_error((thr)); \
	} while (0)
#define DUK_ERROR_RANGE_INDEX(thr,idx) do { \
		duk_err_range((thr)); \
	} while (0)
#define DUK_ERROR_RANGE_PUSH_BEYOND(thr) do { \
		duk_err_range((thr)); \
	} while (0)
#define DUK_ERROR_RANGE_INVALID_ARGS(thr) do { \
		duk_err_range((thr)); \
	} while (0)
#define DUK_DCERROR_RANGE_INVALID_ARGS(thr) do { \
		DUK_UNREF((thr)); \
		return DUK_RET_RANGE_ERROR; \
	} while (0)
#define DUK_ERROR_RANGE_INVALID_COUNT(thr) do { \
		duk_err_range((thr)); \
	} while (0)
#define DUK_DCERROR_RANGE_INVALID_COUNT(thr) do { \
		DUK_UNREF((thr)); \
		return DUK_RET_RANGE_ERROR; \
	} while (0)
#define DUK_ERROR_RANGE_INVALID_LENGTH(thr) do { \
		duk_err_range((thr)); \
	} while (0)
#define DUK_DCERROR_RANGE_INVALID_LENGTH(thr) do { \
		DUK_UNREF((thr)); \
		return DUK_RET_RANGE_ERROR; \
	} while (0)
#define DUK_ERROR_RANGE(thr,msg) do { \
		duk_err_range((thr)); \
	} while (0)
#define DUK_ERROR_EVAL(thr,msg) do { \
		duk_err_eval((thr)); \
	} while (0)
#define DUK_ERROR_REFERENCE(thr,msg) do { \
		duk_err_reference((thr)); \
	} while (0)
#define DUK_ERROR_SYNTAX(thr,msg) do { \
		duk_err_syntax((thr)); \
	} while (0)
#define DUK_ERROR_TYPE_INVALID_ARGS(thr) do { \
		duk_err_type((thr)); \
	} while (0)
#define DUK_DCERROR_TYPE_INVALID_ARGS(thr) do { \
		DUK_UNREF((thr)); \
		return DUK_RET_TYPE_ERROR; \
	} while (0)
#define DUK_ERROR_TYPE_INVALID_STATE(thr) do { \
		duk_err_type((thr)); \
	} while (0)
#define DUK_DCERROR_TYPE_INVALID_STATE(thr) do { \
		duk_err_type((thr)); \
	} while (0)
#define DUK_ERROR_TYPE_INVALID_TRAP_RESULT(thr) do { \
		duk_err_type((thr)); \
	} while (0)
#define DUK_DCERROR_TYPE_INVALID_TRAP_RESULT(thr) do { \
		DUK_UNREF((thr)); \
		return DUK_RET_TYPE_ERROR; \
	} while (0)
#define DUK_ERROR_TYPE_INVALID_TRAP_RESULT(thr) do { \
		duk_err_type((thr)); \
	} while (0)
#define DUK_ERROR_TYPE(thr,msg) do { \
		duk_err_type((thr)); \
	} while (0)
#define DUK_ERROR_URI(thr,msg) do { \
		duk_err_uri((thr)); \
	} while (0)
#endif  /* DUK_USE_VERBOSE_ERRORS */

/*
 *  Assert macro: failure causes a fatal error.
 *
 *  NOTE: since the assert macro doesn't take a heap/context argument, there's
 *  no way to look up a heap/context specific fatal error handler which may have
 *  been given by the application.  Instead, assertion failures always use the
 *  internal default fatal error handler; it can be replaced via duk_config.h
 *  and then applies to all Duktape heaps.
 */

#if defined(DUK_USE_ASSERTIONS)

/* The message should be a compile time constant without formatting (less risk);
 * we don't care about assertion text size because they're not used in production
 * builds.
 */
#define DUK_ASSERT(x)  do { \
	if (!(x)) { \
		DUK_FATAL_WITHOUT_CONTEXT("assertion failed: " #x \
			" (" DUK_FILE_MACRO ":" DUK_MACRO_STRINGIFY(DUK_LINE_MACRO) ")"); \
	} \
	} while (0)

/* Assertion compatible inside a comma expression, evaluates to void. */
#define DUK_ASSERT_EXPR(x) \
	((void) ((x) ? 0 : (DUK_FATAL_WITHOUT_CONTEXT("assertion failed: " #x \
				" (" DUK_FILE_MACRO ":" DUK_MACRO_STRINGIFY(DUK_LINE_MACRO) ")"), 0)))

#else  /* DUK_USE_ASSERTIONS */

#define DUK_ASSERT(x)  do { /* assertion omitted */ } while (0)

#define DUK_ASSERT_EXPR(x)  ((void) 0)

#endif  /* DUK_USE_ASSERTIONS */

/* this variant is used when an assert would generate a compile warning by
 * being always true (e.g. >= 0 comparison for an unsigned value
 */
#define DUK_ASSERT_DISABLE(x)  do { /* assertion disabled */ } while (0)

/*
 *  Assertion helpers
 */

#if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_REFERENCE_COUNTING)
#define DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(h)  do { \
		DUK_ASSERT((h) == NULL || DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) (h)) > 0); \
	} while (0)
#define DUK_ASSERT_REFCOUNT_NONZERO_TVAL(tv)  do { \
		if ((tv) != NULL && DUK_TVAL_IS_HEAP_ALLOCATED((tv))) { \
			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(DUK_TVAL_GET_HEAPHDR((tv))) > 0); \
		} \
	} while (0)
#else
#define DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(h)  /* no refcount check */
#define DUK_ASSERT_REFCOUNT_NONZERO_TVAL(tv)    /* no refcount check */
#endif

#define DUK_ASSERT_TOP(ctx,n)  DUK_ASSERT((duk_idx_t) duk_get_top((ctx)) == (duk_idx_t) (n))

#if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_PACKED_TVAL)
#define DUK_ASSERT_DOUBLE_IS_NORMALIZED(dval)  do { \
		duk_double_union duk__assert_tmp_du; \
		duk__assert_tmp_du.d = (dval); \
		DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&duk__assert_tmp_du)); \
	} while (0)
#else
#define DUK_ASSERT_DOUBLE_IS_NORMALIZED(dval)  /* nop */
#endif

#define DUK_ASSERT_VS_SPACE(thr) \
	DUK_ASSERT(thr->valstack_top < thr->valstack_end)

/*
 *  Helper to initialize a memory area (e.g. struct) with garbage when
 *  assertions enabled.
 */

#if defined(DUK_USE_ASSERTIONS)
#define DUK_ASSERT_SET_GARBAGE(ptr,size) do { \
		duk_memset_unsafe((void *) (ptr), 0x5a, size); \
	} while (0)
#else
#define DUK_ASSERT_SET_GARBAGE(ptr,size) do {} while (0)
#endif

/*
 *  Helper for valstack space
 *
 *  Caller of DUK_ASSERT_VALSTACK_SPACE() estimates the number of free stack entries
 *  required for its own use, and any child calls which are not (a) Duktape API calls
 *  or (b) Duktape calls which involve extending the valstack (e.g. getter call).
 */

#define DUK_VALSTACK_ASSERT_EXTRA  5  /* this is added to checks to allow for Duktape
                                       * API calls in addition to function's own use
                                       */
#if defined(DUK_USE_ASSERTIONS)
#define DUK_ASSERT_VALSTACK_SPACE(thr,n)   do { \
		DUK_ASSERT((thr) != NULL); \
		DUK_ASSERT((thr)->valstack_end - (thr)->valstack_top >= (n) + DUK_VALSTACK_ASSERT_EXTRA); \
	} while (0)
#else
#define DUK_ASSERT_VALSTACK_SPACE(thr,n)   /* no valstack space check */
#endif

/*
 *  Prototypes
 */

#if defined(DUK_USE_VERBOSE_ERRORS)
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));
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, ...));
#else  /* DUK_USE_VERBOSE_ERRORS */
DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_handle_error(duk_hthread *thr, duk_errcode_t code));
#endif  /* DUK_USE_VERBOSE_ERRORS */

#if defined(DUK_USE_VERBOSE_ERRORS)
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));
#else
DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_create_and_throw(duk_hthread *thr, duk_errcode_t code));
#endif

DUK_NORETURN(DUK_INTERNAL_DECL void duk_error_throw_from_negative_rc(duk_hthread *thr, duk_ret_t rc));

#define DUK_AUGMENT_FLAG_NOBLAME_FILELINE  (1U << 0)  /* if set, don't blame C file/line for .fileName and .lineNumber */
#define DUK_AUGMENT_FLAG_SKIP_ONE          (1U << 1)  /* if set, skip topmost activation in traceback construction */

#if defined(DUK_USE_AUGMENT_ERROR_CREATE)
DUK_INTERNAL_DECL void duk_err_augment_error_create(duk_hthread *thr, duk_hthread *thr_callstack, const char *filename, duk_int_t line, duk_small_uint_t flags);
#endif
#if defined(DUK_USE_AUGMENT_ERROR_THROW)
DUK_INTERNAL_DECL void duk_err_augment_error_throw(duk_hthread *thr);
#endif

#if defined(DUK_USE_VERBOSE_ERRORS)
#if defined(DUK_USE_PARANOID_ERRORS)
DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_require_type_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t idx, const char *expect_name));
#else
DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_require_type_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t idx, const char *expect_name));
#endif
DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_error_internal(duk_hthread *thr, const char *filename, duk_int_t linenumber));
DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_error_alloc_failed(duk_hthread *thr, const char *filename, duk_int_t linenumber));
DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_error(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message));
DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_range_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t idx));
DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_range_push_beyond(duk_hthread *thr, const char *filename, duk_int_t linenumber));
DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_range(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message));
DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_type_invalid_args(duk_hthread *thr, const char *filename, duk_int_t linenumber));
DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_type_invalid_state(duk_hthread *thr, const char *filename, duk_int_t linenumber));
DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_type_invalid_trap_result(duk_hthread *thr, const char *filename, duk_int_t linenumber));
#else  /* DUK_VERBOSE_ERRORS */
DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_error(duk_hthread *thr));
DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_range(duk_hthread *thr));
DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_eval(duk_hthread *thr));
DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_reference(duk_hthread *thr));
DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_syntax(duk_hthread *thr));
DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_type(duk_hthread *thr));
DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_uri(duk_hthread *thr));
#endif /* DUK_VERBOSE_ERRORS */

DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_longjmp(duk_hthread *thr));

DUK_NORETURN(DUK_INTERNAL_DECL void duk_default_fatal_handler(void *udata, const char *msg));

DUK_INTERNAL_DECL void duk_err_setup_ljstate1(duk_hthread *thr, duk_small_uint_t lj_type, duk_tval *tv_val);
#if defined(DUK_USE_DEBUGGER_SUPPORT)
DUK_INTERNAL_DECL void duk_err_check_debugger_integration(duk_hthread *thr);
#endif

DUK_INTERNAL_DECL duk_hobject *duk_error_prototype_from_code(duk_hthread *thr, duk_errcode_t err_code);

#endif  /* DUK_ERROR_H_INCLUDED */
/* #include duk_unicode.h */
#line 1 "duk_unicode.h"
/*
 *  Unicode helpers
 */

#if !defined(DUK_UNICODE_H_INCLUDED)
#define DUK_UNICODE_H_INCLUDED

/*
 *  UTF-8 / XUTF-8 / CESU-8 constants
 */

#define DUK_UNICODE_MAX_XUTF8_LENGTH      7   /* up to 36 bit codepoints */
#define DUK_UNICODE_MAX_XUTF8_BMP_LENGTH  3   /* all codepoints up to U+FFFF */
#define DUK_UNICODE_MAX_CESU8_LENGTH      6   /* all codepoints up to U+10FFFF */
#define DUK_UNICODE_MAX_CESU8_BMP_LENGTH  3   /* all codepoints up to U+FFFF */

/*
 *  Useful Unicode codepoints
 *
 *  Integer constants must be signed to avoid unexpected coercions
 *  in comparisons.
 */

#define DUK_UNICODE_CP_ZWNJ                   0x200cL  /* zero-width non-joiner */
#define DUK_UNICODE_CP_ZWJ                    0x200dL  /* zero-width joiner */
#define DUK_UNICODE_CP_REPLACEMENT_CHARACTER  0xfffdL  /* http://en.wikipedia.org/wiki/Replacement_character#Replacement_character */

/*
 *  ASCII character constants
 *
 *  C character literals like 'x' have a platform specific value and do
 *  not match ASCII (UTF-8) values on e.g. EBCDIC platforms.  So, use
 *  these (admittedly awkward) constants instead.  These constants must
 *  also have signed values to avoid unexpected coercions in comparisons.
 *
 *  http://en.wikipedia.org/wiki/ASCII
 */

#define DUK_ASC_NUL              0x00
#define DUK_ASC_SOH              0x01
#define DUK_ASC_STX              0x02
#define DUK_ASC_ETX              0x03
#define DUK_ASC_EOT              0x04
#define DUK_ASC_ENQ              0x05
#define DUK_ASC_ACK              0x06
#define DUK_ASC_BEL              0x07
#define DUK_ASC_BS               0x08
#define DUK_ASC_HT               0x09
#define DUK_ASC_LF               0x0a
#define DUK_ASC_VT               0x0b
#define DUK_ASC_FF               0x0c
#define DUK_ASC_CR               0x0d
#define DUK_ASC_SO               0x0e
#define DUK_ASC_SI               0x0f
#define DUK_ASC_DLE              0x10
#define DUK_ASC_DC1              0x11
#define DUK_ASC_DC2              0x12
#define DUK_ASC_DC3              0x13
#define DUK_ASC_DC4              0x14
#define DUK_ASC_NAK              0x15
#define DUK_ASC_SYN              0x16
#define DUK_ASC_ETB              0x17
#define DUK_ASC_CAN              0x18
#define DUK_ASC_EM               0x19
#define DUK_ASC_SUB              0x1a
#define DUK_ASC_ESC              0x1b
#define DUK_ASC_FS               0x1c
#define DUK_ASC_GS               0x1d
#define DUK_ASC_RS               0x1e
#define DUK_ASC_US               0x1f
#define DUK_ASC_SPACE            0x20
#define DUK_ASC_EXCLAMATION      0x21
#define DUK_ASC_DOUBLEQUOTE      0x22
#define DUK_ASC_HASH             0x23
#define DUK_ASC_DOLLAR           0x24
#define DUK_ASC_PERCENT          0x25
#define DUK_ASC_AMP              0x26
#define DUK_ASC_SINGLEQUOTE      0x27
#define DUK_ASC_LPAREN           0x28
#define DUK_ASC_RPAREN           0x29
#define DUK_ASC_STAR             0x2a
#define DUK_ASC_PLUS             0x2b
#define DUK_ASC_COMMA            0x2c
#define DUK_ASC_MINUS            0x2d
#define DUK_ASC_PERIOD           0x2e
#define DUK_ASC_SLASH            0x2f
#define DUK_ASC_0                0x30
#define DUK_ASC_1                0x31
#define DUK_ASC_2                0x32
#define DUK_ASC_3                0x33
#define DUK_ASC_4                0x34
#define DUK_ASC_5                0x35
#define DUK_ASC_6                0x36
#define DUK_ASC_7                0x37
#define DUK_ASC_8                0x38
#define DUK_ASC_9                0x39
#define DUK_ASC_COLON            0x3a
#define DUK_ASC_SEMICOLON        0x3b
#define DUK_ASC_LANGLE           0x3c
#define DUK_ASC_EQUALS           0x3d
#define DUK_ASC_RANGLE           0x3e
#define DUK_ASC_QUESTION         0x3f
#define DUK_ASC_ATSIGN           0x40
#define DUK_ASC_UC_A             0x41
#define DUK_ASC_UC_B             0x42
#define DUK_ASC_UC_C             0x43
#define DUK_ASC_UC_D             0x44
#define DUK_ASC_UC_E             0x45
#define DUK_ASC_UC_F             0x46
#define DUK_ASC_UC_G             0x47
#define DUK_ASC_UC_H             0x48
#define DUK_ASC_UC_I             0x49
#define DUK_ASC_UC_J             0x4a
#define DUK_ASC_UC_K             0x4b
#define DUK_ASC_UC_L             0x4c
#define DUK_ASC_UC_M             0x4d
#define DUK_ASC_UC_N             0x4e
#define DUK_ASC_UC_O             0x4f
#define DUK_ASC_UC_P             0x50
#define DUK_ASC_UC_Q             0x51
#define DUK_ASC_UC_R             0x52
#define DUK_ASC_UC_S             0x53
#define DUK_ASC_UC_T             0x54
#define DUK_ASC_UC_U             0x55
#define DUK_ASC_UC_V             0x56
#define DUK_ASC_UC_W             0x57
#define DUK_ASC_UC_X             0x58
#define DUK_ASC_UC_Y             0x59
#define DUK_ASC_UC_Z             0x5a
#define DUK_ASC_LBRACKET         0x5b
#define DUK_ASC_BACKSLASH        0x5c
#define DUK_ASC_RBRACKET         0x5d
#define DUK_ASC_CARET            0x5e
#define DUK_ASC_UNDERSCORE       0x5f
#define DUK_ASC_GRAVE            0x60
#define DUK_ASC_LC_A             0x61
#define DUK_ASC_LC_B             0x62
#define DUK_ASC_LC_C             0x63
#define DUK_ASC_LC_D             0x64
#define DUK_ASC_LC_E             0x65
#define DUK_ASC_LC_F             0x66
#define DUK_ASC_LC_G             0x67
#define DUK_ASC_LC_H             0x68
#define DUK_ASC_LC_I             0x69
#define DUK_ASC_LC_J             0x6a
#define DUK_ASC_LC_K             0x6b
#define DUK_ASC_LC_L             0x6c
#define DUK_ASC_LC_M             0x6d
#define DUK_ASC_LC_N             0x6e
#define DUK_ASC_LC_O             0x6f
#define DUK_ASC_LC_P             0x70
#define DUK_ASC_LC_Q             0x71
#define DUK_ASC_LC_R             0x72
#define DUK_ASC_LC_S             0x73
#define DUK_ASC_LC_T             0x74
#define DUK_ASC_LC_U             0x75
#define DUK_ASC_LC_V             0x76
#define DUK_ASC_LC_W             0x77
#define DUK_ASC_LC_X             0x78
#define DUK_ASC_LC_Y             0x79
#define DUK_ASC_LC_Z             0x7a
#define DUK_ASC_LCURLY           0x7b
#define DUK_ASC_PIPE             0x7c
#define DUK_ASC_RCURLY           0x7d
#define DUK_ASC_TILDE            0x7e
#define DUK_ASC_DEL              0x7f

/*
 *  Miscellaneous
 */

/* Uppercase A is 0x41, lowercase a is 0x61; OR 0x20 to convert uppercase
 * to lowercase.
 */
#define DUK_LOWERCASE_CHAR_ASCII(x)  ((x) | 0x20)

/*
 *  Unicode tables
 */

#if defined(DUK_USE_SOURCE_NONBMP)
/*
 *  Automatically generated by extract_chars.py, do not edit!
 */

extern const duk_uint8_t duk_unicode_ids_noa[1116];
#else
/*
 *  Automatically generated by extract_chars.py, do not edit!
 */

extern const duk_uint8_t duk_unicode_ids_noabmp[625];
#endif

#if defined(DUK_USE_SOURCE_NONBMP)
/*
 *  Automatically generated by extract_chars.py, do not edit!
 */

extern const duk_uint8_t duk_unicode_ids_m_let_noa[42];
#else
/*
 *  Automatically generated by extract_chars.py, do not edit!
 */

extern const duk_uint8_t duk_unicode_ids_m_let_noabmp[24];
#endif

#if defined(DUK_USE_SOURCE_NONBMP)
/*
 *  Automatically generated by extract_chars.py, do not edit!
 */

extern const duk_uint8_t duk_unicode_idp_m_ids_noa[576];
#else
/*
 *  Automatically generated by extract_chars.py, do not edit!
 */

extern const duk_uint8_t duk_unicode_idp_m_ids_noabmp[358];
#endif

/*
 *  Automatically generated by extract_caseconv.py, do not edit!
 */

extern const duk_uint8_t duk_unicode_caseconv_uc[1411];
extern const duk_uint8_t duk_unicode_caseconv_lc[706];

#if defined(DUK_USE_REGEXP_CANON_WORKAROUND)
/*
 *  Automatically generated by extract_caseconv.py, do not edit!
 */

extern const duk_uint16_t duk_unicode_re_canon_lookup[65536];
#endif

#if defined(DUK_USE_REGEXP_CANON_BITMAP)
/*
 *  Automatically generated by extract_caseconv.py, do not edit!
 */

#define DUK_CANON_BITMAP_BLKSIZE                                      32
#define DUK_CANON_BITMAP_BLKSHIFT                                     5
#define DUK_CANON_BITMAP_BLKMASK                                      31
extern const duk_uint8_t duk_unicode_re_canon_bitmap[256];
#endif

/*
 *  Extern
 */

/* duk_unicode_support.c */
#if !defined(DUK_SINGLE_FILE)
DUK_INTERNAL_DECL const duk_uint8_t duk_unicode_xutf8_markers[7];
DUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_digit[2];
DUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_white[22];
DUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_wordchar[8];
DUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_not_digit[4];
DUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_not_white[24];
DUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_not_wordchar[10];
DUK_INTERNAL_DECL const duk_int8_t duk_is_idchar_tab[128];
#endif  /* !DUK_SINGLE_FILE */

/*
 *  Prototypes
 */

DUK_INTERNAL_DECL duk_small_int_t duk_unicode_get_xutf8_length(duk_ucodepoint_t cp);
#if defined(DUK_USE_ASSERTIONS)
DUK_INTERNAL_DECL duk_small_int_t duk_unicode_get_cesu8_length(duk_ucodepoint_t cp);
#endif
DUK_INTERNAL_DECL duk_small_int_t duk_unicode_encode_xutf8(duk_ucodepoint_t cp, duk_uint8_t *out);
DUK_INTERNAL_DECL duk_small_int_t duk_unicode_encode_cesu8(duk_ucodepoint_t cp, duk_uint8_t *out);
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);
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);
DUK_INTERNAL_DECL duk_size_t duk_unicode_unvalidated_utf8_length(const duk_uint8_t *data, duk_size_t blen);
DUK_INTERNAL_DECL duk_bool_t duk_unicode_is_utf8_compatible(const duk_uint8_t *buf, duk_size_t len);
DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_whitespace(duk_codepoint_t cp);
DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_line_terminator(duk_codepoint_t cp);
DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_identifier_start(duk_codepoint_t cp);
DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_identifier_part(duk_codepoint_t cp);
DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_letter(duk_codepoint_t cp);
DUK_INTERNAL_DECL void duk_unicode_case_convert_string(duk_hthread *thr, duk_bool_t uppercase);
#if defined(DUK_USE_REGEXP_SUPPORT)
DUK_INTERNAL_DECL duk_codepoint_t duk_unicode_re_canonicalize_char(duk_hthread *thr, duk_codepoint_t cp);
DUK_INTERNAL_DECL duk_small_int_t duk_unicode_re_is_wordchar(duk_codepoint_t cp);
#endif

#endif  /* DUK_UNICODE_H_INCLUDED */
/* #include duk_json.h */
#line 1 "duk_json.h"
/*
 *  Defines for JSON, especially duk_bi_json.c.
 */

#if !defined(DUK_JSON_H_INCLUDED)
#define DUK_JSON_H_INCLUDED

/* Encoding/decoding flags */
#define DUK_JSON_FLAG_ASCII_ONLY              (1U << 0)  /* escape any non-ASCII characters */
#define DUK_JSON_FLAG_AVOID_KEY_QUOTES        (1U << 1)  /* avoid key quotes when key is an ASCII Identifier */
#define DUK_JSON_FLAG_EXT_CUSTOM              (1U << 2)  /* extended types: custom encoding */
#define DUK_JSON_FLAG_EXT_COMPATIBLE          (1U << 3)  /* extended types: compatible encoding */

/* How much stack to require on entry to object/array encode */
#define DUK_JSON_ENC_REQSTACK                 32

/* How much stack to require on entry to object/array decode */
#define DUK_JSON_DEC_REQSTACK                 32

/* How large a loop detection stack to use */
#define DUK_JSON_ENC_LOOPARRAY                64

/* Encoding state.  Heap object references are all borrowed. */
typedef struct {
	duk_hthread *thr;
	duk_bufwriter_ctx bw;        /* output bufwriter */
	duk_hobject *h_replacer;     /* replacer function */
	duk_hstring *h_gap;          /* gap (if empty string, NULL) */
	duk_idx_t idx_proplist;      /* explicit PropertyList */
	duk_idx_t idx_loop;          /* valstack index of loop detection object */
	duk_small_uint_t flags;
	duk_small_uint_t flag_ascii_only;
	duk_small_uint_t flag_avoid_key_quotes;
#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
	duk_small_uint_t flag_ext_custom;
	duk_small_uint_t flag_ext_compatible;
	duk_small_uint_t flag_ext_custom_or_compatible;
#endif
	duk_uint_t recursion_depth;
	duk_uint_t recursion_limit;
	duk_uint_t mask_for_undefined;      /* type bit mask: types which certainly produce 'undefined' */
#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
	duk_small_uint_t stridx_custom_undefined;
	duk_small_uint_t stridx_custom_nan;
	duk_small_uint_t stridx_custom_neginf;
	duk_small_uint_t stridx_custom_posinf;
	duk_small_uint_t stridx_custom_function;
#endif
	duk_hobject *visiting[DUK_JSON_ENC_LOOPARRAY];  /* indexed by recursion_depth */
} duk_json_enc_ctx;

typedef struct {
	duk_hthread *thr;
	const duk_uint8_t *p;
	const duk_uint8_t *p_start;
	const duk_uint8_t *p_end;
	duk_idx_t idx_reviver;
	duk_small_uint_t flags;
#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
	duk_small_uint_t flag_ext_custom;
	duk_small_uint_t flag_ext_compatible;
	duk_small_uint_t flag_ext_custom_or_compatible;
#endif
	duk_int_t recursion_depth;
	duk_int_t recursion_limit;
} duk_json_dec_ctx;

#endif  /* DUK_JSON_H_INCLUDED */
/* #include duk_js.h */
#line 1 "duk_js.h"
/*
 *  ECMAScript execution, support primitives.
 */

#if !defined(DUK_JS_H_INCLUDED)
#define DUK_JS_H_INCLUDED

/* Flags for call handling.  Lowest flags must match bytecode DUK_BC_CALL_FLAG_xxx 1:1. */
#define DUK_CALL_FLAG_TAILCALL                 (1U << 0)  /* setup for a tail call */
#define DUK_CALL_FLAG_CONSTRUCT                (1U << 1)  /* constructor call (i.e. called as 'new Foo()') */
#define DUK_CALL_FLAG_CALLED_AS_EVAL           (1U << 2)  /* call was made using the identifier 'eval' */
#define DUK_CALL_FLAG_ALLOW_ECMATOECMA         (1U << 3)  /* ecma-to-ecma call with executor reuse is possible */
#define DUK_CALL_FLAG_DIRECT_EVAL              (1U << 4)  /* call is a direct eval call */
#define DUK_CALL_FLAG_CONSTRUCT_PROXY          (1U << 5)  /* handled via 'construct' proxy trap, check return value invariant(s) */
#define DUK_CALL_FLAG_DEFAULT_INSTANCE_UPDATED (1U << 6)  /* prototype of 'default instance' updated, temporary flag in call handling */

/* Flags for duk_js_equals_helper(). */
#define DUK_EQUALS_FLAG_SAMEVALUE            (1U << 0)  /* use SameValue instead of non-strict equality */
#define DUK_EQUALS_FLAG_STRICT               (1U << 1)  /* use strict equality instead of non-strict equality */

/* Flags for duk_js_compare_helper(). */
#define DUK_COMPARE_FLAG_NEGATE              (1U << 0)  /* negate result */
#define DUK_COMPARE_FLAG_EVAL_LEFT_FIRST     (1U << 1)  /* eval left argument first */

/* conversions, coercions, comparison, etc */
DUK_INTERNAL_DECL duk_bool_t duk_js_toboolean(duk_tval *tv);
DUK_INTERNAL_DECL duk_double_t duk_js_tonumber(duk_hthread *thr, duk_tval *tv);
DUK_INTERNAL_DECL duk_double_t duk_js_tointeger_number(duk_double_t x);
DUK_INTERNAL_DECL duk_double_t duk_js_tointeger(duk_hthread *thr, duk_tval *tv);
DUK_INTERNAL_DECL duk_uint32_t duk_js_touint32(duk_hthread *thr, duk_tval *tv);
DUK_INTERNAL_DECL duk_int32_t duk_js_toint32(duk_hthread *thr, duk_tval *tv);
DUK_INTERNAL_DECL duk_uint16_t duk_js_touint16(duk_hthread *thr, duk_tval *tv);
DUK_INTERNAL_DECL duk_uarridx_t duk_js_to_arrayindex_string(const duk_uint8_t *str, duk_uint32_t blen);
#if !defined(DUK_USE_HSTRING_ARRIDX)
DUK_INTERNAL_DECL duk_uarridx_t duk_js_to_arrayindex_hstring_fast_known(duk_hstring *h);
DUK_INTERNAL_DECL duk_uarridx_t duk_js_to_arrayindex_hstring_fast(duk_hstring *h);
#endif
DUK_INTERNAL_DECL duk_bool_t duk_js_equals_helper(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_uint_t flags);
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);
DUK_INTERNAL_DECL duk_small_int_t duk_js_string_compare(duk_hstring *h1, duk_hstring *h2);
#if 0  /* unused */
DUK_INTERNAL_DECL duk_small_int_t duk_js_buffer_compare(duk_heap *heap, duk_hbuffer *h1, duk_hbuffer *h2);
#endif
DUK_INTERNAL_DECL duk_bool_t duk_js_compare_helper(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_uint_t flags);
DUK_INTERNAL_DECL duk_bool_t duk_js_instanceof(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y);
#if defined(DUK_USE_SYMBOL_BUILTIN)
DUK_INTERNAL_DECL duk_bool_t duk_js_instanceof_ordinary(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y);
#endif
DUK_INTERNAL_DECL duk_bool_t duk_js_in(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y);
DUK_INTERNAL_DECL duk_small_uint_t duk_js_typeof_stridx(duk_tval *tv_x);
DUK_INTERNAL_DECL duk_bool_t duk_js_isarray_hobject(duk_hobject *h);
DUK_INTERNAL_DECL duk_bool_t duk_js_isarray(duk_tval *tv);

/* arithmetic */
DUK_INTERNAL_DECL double duk_js_arith_pow(double x, double y);
DUK_INTERNAL_DECL double duk_js_arith_mod(double x, double y);

#define duk_js_equals(thr,tv_x,tv_y) \
	duk_js_equals_helper((thr), (tv_x), (tv_y), 0)
#define duk_js_strict_equals(tv_x,tv_y) \
	duk_js_equals_helper(NULL, (tv_x), (tv_y), DUK_EQUALS_FLAG_STRICT)
#define duk_js_samevalue(tv_x,tv_y) \
	duk_js_equals_helper(NULL, (tv_x), (tv_y), DUK_EQUALS_FLAG_SAMEVALUE)

/* E5 Sections 11.8.1, 11.8.5; x < y */
#define duk_js_lessthan(thr,tv_x,tv_y) \
	duk_js_compare_helper((thr), (tv_x), (tv_Y), DUK_COMPARE_FLAG_EVAL_LEFT_FIRST)

/* E5 Sections 11.8.2, 11.8.5; x > y  -->  y < x */
#define duk_js_greaterthan(thr,tv_x,tv_y) \
	duk_js_compare_helper((thr), (tv_y), (tv_x), 0)

/* E5 Sections 11.8.3, 11.8.5; x <= y  -->  not (x > y)  -->  not (y < x) */
#define duk_js_lessthanorequal(thr,tv_x,tv_y) \
	duk_js_compare_helper((thr), (tv_y), (tv_x), DUK_COMPARE_FLAG_NEGATE)

/* E5 Sections 11.8.4, 11.8.5; x >= y  -->  not (x < y) */
#define duk_js_greaterthanorequal(thr,tv_x,tv_y) \
	duk_js_compare_helper((thr), (tv_x), (tv_y), DUK_COMPARE_FLAG_EVAL_LEFT_FIRST | DUK_COMPARE_FLAG_NEGATE)

/* identifiers and environment handling */
#if 0  /*unused*/
DUK_INTERNAL duk_bool_t duk_js_hasvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name);
#endif
DUK_INTERNAL_DECL duk_bool_t duk_js_getvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name, duk_bool_t throw_flag);
DUK_INTERNAL_DECL duk_bool_t duk_js_getvar_activation(duk_hthread *thr, duk_activation *act, duk_hstring *name, duk_bool_t throw_flag);
DUK_INTERNAL_DECL void duk_js_putvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name, duk_tval *val, duk_bool_t strict);
DUK_INTERNAL_DECL void duk_js_putvar_activation(duk_hthread *thr, duk_activation *act, duk_hstring *name, duk_tval *val, duk_bool_t strict);
#if 0  /*unused*/
DUK_INTERNAL_DECL duk_bool_t duk_js_delvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name);
#endif
DUK_INTERNAL_DECL duk_bool_t duk_js_delvar_activation(duk_hthread *thr, duk_activation *act, duk_hstring *name);
DUK_INTERNAL_DECL duk_bool_t duk_js_declvar_activation(duk_hthread *thr, duk_activation *act, duk_hstring *name, duk_tval *val, duk_small_uint_t prop_flags, duk_bool_t is_func_decl);
DUK_INTERNAL_DECL void duk_js_init_activation_environment_records_delayed(duk_hthread *thr, duk_activation *act);
DUK_INTERNAL_DECL void duk_js_close_environment_record(duk_hthread *thr, duk_hobject *env);
DUK_INTERNAL_DECL duk_hobject *duk_create_activation_environment_record(duk_hthread *thr, duk_hobject *func, duk_size_t bottom_byteoff);
DUK_INTERNAL_DECL void duk_js_push_closure(duk_hthread *thr,
                                           duk_hcompfunc *fun_temp,
                                           duk_hobject *outer_var_env,
                                           duk_hobject *outer_lex_env,
                                           duk_bool_t add_auto_proto);

/* call handling */
DUK_INTERNAL_DECL void duk_native_stack_check(duk_hthread *thr);
DUK_INTERNAL_DECL duk_int_t duk_handle_call_unprotected(duk_hthread *thr, duk_idx_t idx_func, duk_small_uint_t call_flags);
DUK_INTERNAL_DECL duk_int_t duk_handle_call_unprotected_nargs(duk_hthread *thr, duk_idx_t nargs, duk_small_uint_t call_flags);
DUK_INTERNAL_DECL duk_int_t duk_handle_safe_call(duk_hthread *thr, duk_safe_call_function func, void *udata, duk_idx_t num_stack_args, duk_idx_t num_stack_res);
DUK_INTERNAL_DECL void duk_call_construct_postprocess(duk_hthread *thr, duk_small_uint_t proxy_invariant);
#if defined(DUK_USE_VERBOSE_ERRORS)
DUK_INTERNAL_DECL void duk_call_setup_propcall_error(duk_hthread *thr, duk_tval *tv_base, duk_tval *tv_key);
#endif

/* bytecode execution */
DUK_INTERNAL_DECL void duk_js_execute_bytecode(duk_hthread *exec_thr);

#endif  /* DUK_JS_H_INCLUDED */
/* #include duk_numconv.h */
#line 1 "duk_numconv.h"
/*
 *  Number-to-string conversion.  The semantics of these is very tightly
 *  bound with the ECMAScript semantics required for call sites.
 */

#if !defined(DUK_NUMCONV_H_INCLUDED)
#define DUK_NUMCONV_H_INCLUDED

/* Output a specified number of digits instead of using the shortest
 * form.  Used for toPrecision() and toFixed().
 */
#define DUK_N2S_FLAG_FIXED_FORMAT         (1U << 0)

/* Force exponential format.  Used for toExponential(). */
#define DUK_N2S_FLAG_FORCE_EXP            (1U << 1)

/* If number would need zero padding (for whole number part), use
 * exponential format instead.  E.g. if input number is 12300, 3
 * digits are generated ("123"), output "1.23e+4" instead of "12300".
 * Used for toPrecision().
 */
#define DUK_N2S_FLAG_NO_ZERO_PAD          (1U << 2)

/* Digit count indicates number of fractions (i.e. an absolute
 * digit index instead of a relative one).  Used together with
 * DUK_N2S_FLAG_FIXED_FORMAT for toFixed().
 */
#define DUK_N2S_FLAG_FRACTION_DIGITS      (1U << 3)

/*
 *  String-to-number conversion
 */

/* Maximum exponent value when parsing numbers.  This is not strictly
 * compliant as there should be no upper limit, but as we parse the
 * exponent without a bigint, impose some limit.  The limit should be
 * small enough that multiplying it (or limit-1 to be precise) won't
 * overflow signed 32-bit integer range.  Exponent is only parsed with
 * radix 10, but with maximum radix (36) a safe limit is:
 * (10000000*36).toString(16) -> '15752a00'
 */
#define DUK_S2N_MAX_EXPONENT              10000000L

/* Trim white space (= allow leading and trailing whitespace) */
#define DUK_S2N_FLAG_TRIM_WHITE           (1U << 0)

/* Allow exponent */
#define DUK_S2N_FLAG_ALLOW_EXP            (1U << 1)

/* Allow trailing garbage (e.g. treat "123foo" as "123) */
#define DUK_S2N_FLAG_ALLOW_GARBAGE        (1U << 2)

/* Allow leading plus sign */
#define DUK_S2N_FLAG_ALLOW_PLUS           (1U << 3)

/* Allow leading minus sign */
#define DUK_S2N_FLAG_ALLOW_MINUS          (1U << 4)

/* Allow 'Infinity' */
#define DUK_S2N_FLAG_ALLOW_INF            (1U << 5)

/* Allow fraction part */
#define DUK_S2N_FLAG_ALLOW_FRAC           (1U << 6)

/* Allow naked fraction (e.g. ".123") */
#define DUK_S2N_FLAG_ALLOW_NAKED_FRAC     (1U << 7)

/* Allow empty fraction (e.g. "123.") */
#define DUK_S2N_FLAG_ALLOW_EMPTY_FRAC     (1U << 8)

/* Allow empty string to be interpreted as 0 */
#define DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO  (1U << 9)

/* Allow leading zeroes (e.g. "0123" -> "123") */
#define DUK_S2N_FLAG_ALLOW_LEADING_ZERO   (1U << 10)

/* Allow automatic detection of hex base ("0x" or "0X" prefix),
 * overrides radix argument and forces integer mode.
 */
#define DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT   (1U << 11)

/* Allow automatic detection of legacy octal base ("0n"),
 * overrides radix argument and forces integer mode.
 */
#define DUK_S2N_FLAG_ALLOW_AUTO_LEGACY_OCT_INT   (1U << 12)

/* Allow automatic detection of ES2015 octal base ("0o123"),
 * overrides radix argument and forces integer mode.
 */
#define DUK_S2N_FLAG_ALLOW_AUTO_OCT_INT   (1U << 13)

/* Allow automatic detection of ES2015 binary base ("0b10001"),
 * overrides radix argument and forces integer mode.
 */
#define DUK_S2N_FLAG_ALLOW_AUTO_BIN_INT   (1U << 14)

/*
 *  Prototypes
 */

DUK_INTERNAL_DECL void duk_numconv_stringify(duk_hthread *thr, duk_small_int_t radix, duk_small_int_t digits, duk_small_uint_t flags);
DUK_INTERNAL_DECL void duk_numconv_parse(duk_hthread *thr, duk_small_int_t radix, duk_small_uint_t flags);

#endif  /* DUK_NUMCONV_H_INCLUDED */
/* #include duk_bi_protos.h */
#line 1 "duk_bi_protos.h"
/*
 *  Prototypes for built-in functions not automatically covered by the
 *  header declarations emitted by genbuiltins.py.
 */

#if !defined(DUK_BUILTIN_PROTOS_H_INCLUDED)
#define DUK_BUILTIN_PROTOS_H_INCLUDED

/* Buffer size needed for ISO 8601 formatting.
 * Accurate value is 32 + 1 for NUL termination:
 *   >>> len('+123456-01-23T12:34:56.123+12:34')
 *   32
 * Include additional space to be safe.
 */
#define  DUK_BI_DATE_ISO8601_BUFSIZE  40

/* Helpers exposed for internal use */
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);
DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_timeval_from_dparts(duk_double_t *dparts, duk_small_uint_t flags);
DUK_INTERNAL_DECL duk_bool_t duk_bi_date_is_leap_year(duk_int_t year);
DUK_INTERNAL_DECL duk_bool_t duk_bi_date_timeval_in_valid_range(duk_double_t x);
DUK_INTERNAL_DECL duk_bool_t duk_bi_date_year_in_valid_range(duk_double_t year);
DUK_INTERNAL_DECL duk_bool_t duk_bi_date_timeval_in_leeway_range(duk_double_t x);
/* Built-in providers */
#if defined(DUK_USE_DATE_NOW_GETTIMEOFDAY)
DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_now_gettimeofday(void);
#endif
#if defined(DUK_USE_DATE_NOW_TIME)
DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_now_time(void);
#endif
#if defined(DUK_USE_DATE_NOW_WINDOWS)
DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_now_windows(void);
#endif
#if defined(DUK_USE_DATE_NOW_WINDOWS_SUBMS)
DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_now_windows_subms(void);
#endif
#if defined(DUK_USE_DATE_TZO_GMTIME_R) || defined(DUK_USE_DATE_TZO_GMTIME_S) || defined(DUK_USE_DATE_TZO_GMTIME)
DUK_INTERNAL_DECL duk_int_t duk_bi_date_get_local_tzoffset_gmtime(duk_double_t d);
#endif
#if defined(DUK_USE_DATE_TZO_WINDOWS)
DUK_INTERNAL_DECL duk_int_t duk_bi_date_get_local_tzoffset_windows(duk_double_t d);
#endif
#if defined(DUK_USE_DATE_TZO_WINDOWS_NO_DST)
DUK_INTERNAL_DECL duk_int_t duk_bi_date_get_local_tzoffset_windows_no_dst(duk_double_t d);
#endif
#if defined(DUK_USE_DATE_PRS_STRPTIME)
DUK_INTERNAL_DECL duk_bool_t duk_bi_date_parse_string_strptime(duk_hthread *thr, const char *str);
#endif
#if defined(DUK_USE_DATE_PRS_GETDATE)
DUK_INTERNAL_DECL duk_bool_t duk_bi_date_parse_string_getdate(duk_hthread *thr, const char *str);
#endif
#if defined(DUK_USE_DATE_FMT_STRFTIME)
DUK_INTERNAL_DECL duk_bool_t duk_bi_date_format_parts_strftime(duk_hthread *thr, duk_int_t *parts, duk_int_t tzoffset, duk_small_uint_t flags);
#endif

#if defined(DUK_USE_GET_MONOTONIC_TIME_CLOCK_GETTIME)
DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_monotonic_time_clock_gettime(void);
#endif
#if defined(DUK_USE_GET_MONOTONIC_TIME_WINDOWS_QPC)
DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_monotonic_time_windows_qpc(void);
#endif

DUK_INTERNAL_DECL
void duk_bi_json_parse_helper(duk_hthread *thr,
                              duk_idx_t idx_value,
                              duk_idx_t idx_reviver,
                              duk_small_uint_t flags);
DUK_INTERNAL_DECL
void duk_bi_json_stringify_helper(duk_hthread *thr,
                                  duk_idx_t idx_value,
                                  duk_idx_t idx_replacer,
                                  duk_idx_t idx_space,
                                  duk_small_uint_t flags);

DUK_INTERNAL_DECL duk_ret_t duk_textdecoder_decode_utf8_nodejs(duk_hthread *thr);

#if defined(DUK_USE_ES6_PROXY)
DUK_INTERNAL_DECL void duk_proxy_ownkeys_postprocess(duk_hthread *thr, duk_hobject *h_proxy_target, duk_uint_t flags);
#endif

#endif  /* DUK_BUILTIN_PROTOS_H_INCLUDED */
/* #include duk_selftest.h */
#line 1 "duk_selftest.h"
/*
 *  Selftest code
 */

#if !defined(DUK_SELFTEST_H_INCLUDED)
#define DUK_SELFTEST_H_INCLUDED

#if defined(DUK_USE_SELF_TESTS)
DUK_INTERNAL_DECL duk_uint_t duk_selftest_run_tests(duk_alloc_function alloc_func,
                                                    duk_realloc_function realloc_func,
                                                    duk_free_function free_func,
                                                    void *udata);
#endif

#endif  /* DUK_SELFTEST_H_INCLUDED */
#line 76 "duk_internal.h"

#endif  /* DUK_INTERNAL_H_INCLUDED */
#line 10 "duk_replacements.c"

#if defined(DUK_USE_COMPUTED_NAN)
DUK_INTERNAL double duk_computed_nan;
#endif

#if defined(DUK_USE_COMPUTED_INFINITY)
DUK_INTERNAL double duk_computed_infinity;
#endif

#if defined(DUK_USE_REPL_FPCLASSIFY)
DUK_INTERNAL int duk_repl_fpclassify(double x) {
	duk_double_union u;
	duk_uint_fast16_t expt;
	duk_small_int_t mzero;

	u.d = x;
	expt = (duk_uint_fast16_t) (u.us[DUK_DBL_IDX_US0] & 0x7ff0UL);
	if (expt > 0x0000UL && expt < 0x7ff0UL) {
		/* expt values [0x001,0x7fe] = normal */
		return DUK_FP_NORMAL;
	}

	mzero = (u.ui[DUK_DBL_IDX_UI1] == 0 && (u.ui[DUK_DBL_IDX_UI0] & 0x000fffffUL) == 0);
	if (expt == 0x0000UL) {
		/* expt 0x000 is zero/subnormal */
		if (mzero) {
			return DUK_FP_ZERO;
		} else {
			return DUK_FP_SUBNORMAL;
		}
	} else {
		/* expt 0xfff is infinite/nan */
		if (mzero) {
			return DUK_FP_INFINITE;
		} else {
			return DUK_FP_NAN;
		}
	}
}
#endif

#if defined(DUK_USE_REPL_SIGNBIT)
DUK_INTERNAL int duk_repl_signbit(double x) {
	duk_double_union u;
	u.d = x;
	return (int) (u.uc[DUK_DBL_IDX_UC0] & 0x80UL);
}
#endif

#if defined(DUK_USE_REPL_ISFINITE)
DUK_INTERNAL int duk_repl_isfinite(double x) {
	int c = DUK_FPCLASSIFY(x);
	if (c == DUK_FP_NAN || c == DUK_FP_INFINITE) {
		return 0;
	} else {
		return 1;
	}
}
#endif

#if defined(DUK_USE_REPL_ISNAN)
DUK_INTERNAL int duk_repl_isnan(double x) {
	int c = DUK_FPCLASSIFY(x);
	return (c == DUK_FP_NAN);
}
#endif

#if defined(DUK_USE_REPL_ISINF)
DUK_INTERNAL int duk_repl_isinf(double x) {
	int c = DUK_FPCLASSIFY(x);
	return (c == DUK_FP_INFINITE);
}
#endif
#line 1 "duk_debug_macros.c"
/*
 *  Debugging macro calls.
 */

/* #include duk_internal.h -> already included */

#if defined(DUK_USE_DEBUG)

/*
 *  Debugging enabled
 */

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>

#if !defined(DUK_USE_DEBUG_WRITE)
#error debugging enabled (DUK_USE_DEBUG) but DUK_USE_DEBUG_WRITE not defined
#endif

#define DUK__DEBUG_BUFSIZE  DUK_USE_DEBUG_BUFSIZE

#if defined(DUK_USE_VARIADIC_MACROS)

DUK_INTERNAL void duk_debug_log(duk_int_t level, const char *file, duk_int_t line, const char *func, const char *fmt, ...) {
	va_list ap;
	long arg_level;
	const char *arg_file;
	long arg_line;
	const char *arg_func;
	const char *arg_msg;
	char buf[DUK__DEBUG_BUFSIZE];

	va_start(ap, fmt);

	duk_memzero((void *) buf, (size_t) DUK__DEBUG_BUFSIZE);
	duk_debug_vsnprintf(buf, DUK__DEBUG_BUFSIZE - 1, fmt, ap);

	arg_level = (long) level;
	arg_file = (const char *) file;
	arg_line = (long) line;
	arg_func = (const char *) func;
	arg_msg = (const char *) buf;
	DUK_USE_DEBUG_WRITE(arg_level, arg_file, arg_line, arg_func, arg_msg);

	va_end(ap);
}

#else  /* DUK_USE_VARIADIC_MACROS */

DUK_INTERNAL char duk_debug_file_stash[DUK_DEBUG_STASH_SIZE];
DUK_INTERNAL duk_int_t duk_debug_line_stash;
DUK_INTERNAL char duk_debug_func_stash[DUK_DEBUG_STASH_SIZE];
DUK_INTERNAL duk_int_t duk_debug_level_stash;

DUK_INTERNAL void duk_debug_log(const char *fmt, ...) {
	va_list ap;
	long arg_level;
	const char *arg_file;
	long arg_line;
	const char *arg_func;
	const char *arg_msg;
	char buf[DUK__DEBUG_BUFSIZE];

	va_start(ap, fmt);

	duk_memzero((void *) buf, (size_t) DUK__DEBUG_BUFSIZE);
	duk_debug_vsnprintf(buf, DUK__DEBUG_BUFSIZE - 1, fmt, ap);

	arg_level = (long) duk_debug_level_stash;
	arg_file = (const char *) duk_debug_file_stash;
	arg_line = (long) duk_debug_line_stash;
	arg_func = (const char *) duk_debug_func_stash;
	arg_msg = (const char *) buf;
	DUK_USE_DEBUG_WRITE(arg_level, arg_file, arg_line, arg_func, arg_msg);

	va_end(ap);
}

#endif  /* DUK_USE_VARIADIC_MACROS */

#else  /* DUK_USE_DEBUG */

/*
 *  Debugging disabled
 */

#endif  /* DUK_USE_DEBUG */

/* automatic undefs */
#undef DUK__DEBUG_BUFSIZE
#line 1 "duk_builtins.c"
/*
 *  Automatically generated by genbuiltins.py, do not edit!
 */

/* #include duk_internal.h -> already included */

#if defined(DUK_USE_ASSERTIONS)
#define DUK__REFCINIT(refc) 0 /*h_assert_refcount*/, (refc) /*actual*/
#else
#define DUK__REFCINIT(refc) (refc) /*actual*/
#endif

#if defined(DUK_USE_ROM_STRINGS)
#error ROM support not enabled, rerun configure.py with --rom-support
#else  /* DUK_USE_ROM_STRINGS */
DUK_INTERNAL const duk_uint8_t duk_strings_data[972] = {
79,40,209,144,168,105,6,78,54,139,89,185,44,48,46,90,120,8,154,140,35,103,
35,113,193,73,5,52,112,180,104,166,135,52,188,4,98,12,27,146,156,80,211,31,
129,115,150,64,52,220,109,24,18,68,156,24,38,67,114,36,55,9,119,151,132,
140,93,18,113,128,153,201,212,201,205,2,248,8,196,24,224,104,82,146,40,224,
193,48,114,168,37,147,196,54,123,28,4,98,12,43,148,67,103,177,192,70,32,
196,121,68,54,123,28,18,192,199,144,124,4,98,12,43,136,108,244,117,184,8,
196,24,95,40,134,207,71,91,128,140,65,133,113,13,158,158,151,1,24,131,11,
229,16,217,233,233,112,17,136,48,206,21,110,4,244,244,184,8,196,24,103,10,
183,2,122,218,156,4,98,12,24,203,112,64,179,113,193,79,8,218,155,131,32,
184,70,212,220,13,10,82,68,252,123,144,217,146,38,228,207,18,0,100,37,64,
178,212,11,161,17,104,162,96,10,200,193,57,165,65,169,16,5,100,81,27,70,18,
32,10,200,68,185,13,116,221,197,184,64,89,57,41,197,13,49,234,5,208,156,
113,87,55,118,147,20,187,56,161,166,92,221,212,73,210,236,226,134,153,115,
119,76,201,203,179,138,26,99,73,212,136,136,164,25,174,137,56,32,72,137,
101,23,52,45,13,34,86,9,79,136,104,201,114,149,96,52,138,134,140,151,75,
226,233,186,120,121,22,39,54,83,141,5,55,68,236,36,164,3,16,225,115,150,64,
52,205,163,2,72,154,83,138,26,99,75,12,11,150,103,5,36,20,211,70,140,133,
67,72,49,241,160,227,81,196,52,168,106,39,132,252,183,136,105,80,212,79,2,
249,110,128,126,88,95,133,109,237,237,237,151,235,127,46,249,119,203,190,
186,206,33,181,2,208,61,190,12,19,34,65,19,81,132,108,228,97,1,107,33,12,
32,45,100,137,64,247,175,9,19,155,41,198,130,155,134,69,146,100,227,226,
231,146,51,192,204,73,140,224,145,221,102,241,68,196,169,248,30,75,12,11,
151,242,233,187,143,138,24,137,162,164,255,253,63,3,201,97,129,114,254,92,
112,75,136,108,166,6,136,159,255,167,224,121,44,48,46,95,203,166,238,74,
113,67,77,201,128,223,255,223,224,121,44,48,46,95,203,145,46,9,205,16,39,
201,62,36,0,192,21,147,255,238,145,39,199,197,211,116,240,242,113,197,78,
214,211,226,233,187,107,105,19,119,37,56,161,166,52,221,212,201,205,36,240,
242,16,96,152,12,26,20,164,137,150,70,154,103,28,137,50,202,96,18,132,241,
41,104,105,56,218,48,36,138,183,57,56,128,68,24,38,2,52,12,34,10,133,147,
141,3,8,119,185,13,153,34,125,206,76,17,49,38,93,206,52,151,154,119,56,28,
76,130,112,200,141,206,21,209,96,23,35,238,114,160,139,0,243,238,114,78,
164,68,68,110,113,226,210,90,26,66,110,113,128,121,247,57,80,68,141,170,
183,56,84,52,11,70,73,19,110,114,160,93,8,113,57,143,66,200,84,53,244,154,
73,24,240,81,32,38,68,18,49,228,207,23,88,100,109,70,114,92,193,4,137,173,
168,36,220,73,19,247,247,182,168,209,144,187,223,58,156,104,79,190,183,127,
123,105,160,110,247,206,167,26,19,239,173,223,222,218,67,75,189,243,169,
198,132,251,235,183,247,182,154,134,151,123,231,83,141,9,247,215,111,239,
109,22,141,22,247,206,167,26,19,239,172,223,218,45,26,47,157,78,52,39,223,
74,24,144,10,32,129,34,20,64,152,142,129,57,179,67,104,68,12,129,161,140,
72,156,100,40,40,185,152,100,89,38,65,13,196,34,228,67,149,13,2,215,129,
149,209,65,104,209,77,14,104,144,81,33,170,67,101,48,52,68,113,70,210,88,
209,36,233,22,154,86,68,196,114,76,232,145,102,120,186,195,156,112,105,225,
228,113,71,80,68,162,115,101,50,85,200,25,108,116,44,132,178,38,114,137,96,
148,136,70,209,134,37,222,232,204,228,188,200,209,200,200,99,221,25,150,84,
121,34,70,209,107,36,227,66,20,160,92,136,164,49,235,35,8,217,201,40,108,
201,18,128,68,26,201,51,188,2,80,12,67,190,40,168,38,68,190,46,153,5,50,12,
207,160,86,129,26,83,4,208,34,225,4,88,192,
};
#endif  /* DUK_USE_ROM_STRINGS */

#if defined(DUK_USE_ROM_OBJECTS)
#error ROM support not enabled, rerun configure.py with --rom-support
#else  /* DUK_USE_ROM_OBJECTS */
/* native functions: 185 */
DUK_INTERNAL const duk_c_function duk_bi_native_functions[185] = {
	NULL,
	duk_bi_array_constructor,
	duk_bi_array_constructor_is_array,
	duk_bi_array_prototype_concat,
	duk_bi_array_prototype_indexof_shared,
	duk_bi_array_prototype_iter_shared,
	duk_bi_array_prototype_join_shared,
	duk_bi_array_prototype_pop,
	duk_bi_array_prototype_push,
	duk_bi_array_prototype_reduce_shared,
	duk_bi_array_prototype_reverse,
	duk_bi_array_prototype_shift,
	duk_bi_array_prototype_slice,
	duk_bi_array_prototype_sort,
	duk_bi_array_prototype_splice,
	duk_bi_array_prototype_to_string,
	duk_bi_array_prototype_unshift,
	duk_bi_arraybuffer_constructor,
	duk_bi_arraybuffer_isview,
	duk_bi_boolean_constructor,
	duk_bi_boolean_prototype_tostring_shared,
	duk_bi_buffer_compare_shared,
	duk_bi_buffer_readfield,
	duk_bi_buffer_slice_shared,
	duk_bi_buffer_writefield,
	duk_bi_cbor_decode,
	duk_bi_cbor_encode,
	duk_bi_dataview_constructor,
	duk_bi_date_constructor,
	duk_bi_date_constructor_now,
	duk_bi_date_constructor_parse,
	duk_bi_date_constructor_utc,
	duk_bi_date_prototype_get_shared,
	duk_bi_date_prototype_get_timezone_offset,
	duk_bi_date_prototype_set_shared,
	duk_bi_date_prototype_set_time,
	duk_bi_date_prototype_to_json,
	duk_bi_date_prototype_toprimitive,
	duk_bi_date_prototype_tostring_shared,
	duk_bi_date_prototype_value_of,
	duk_bi_duktape_object_act,
	duk_bi_duktape_object_compact,
	duk_bi_duktape_object_dec,
	duk_bi_duktape_object_enc,
	duk_bi_duktape_object_fin,
	duk_bi_duktape_object_gc,
	duk_bi_duktape_object_info,
	duk_bi_error_constructor_shared,
	duk_bi_error_prototype_filename_getter,
	duk_bi_error_prototype_filename_setter,
	duk_bi_error_prototype_linenumber_getter,
	duk_bi_error_prototype_linenumber_setter,
	duk_bi_error_prototype_stack_getter,
	duk_bi_error_prototype_stack_setter,
	duk_bi_error_prototype_to_string,
	duk_bi_function_constructor,
	duk_bi_function_prototype,
	duk_bi_function_prototype_apply,
	duk_bi_function_prototype_bind,
	duk_bi_function_prototype_call,
	duk_bi_function_prototype_hasinstance,
	duk_bi_function_prototype_to_string,
	duk_bi_global_object_decode_uri,
	duk_bi_global_object_decode_uri_component,
	duk_bi_global_object_encode_uri,
	duk_bi_global_object_encode_uri_component,
	duk_bi_global_object_escape,
	duk_bi_global_object_eval,
	duk_bi_global_object_is_finite,
	duk_bi_global_object_is_nan,
	duk_bi_global_object_parse_float,
	duk_bi_global_object_parse_int,
	duk_bi_global_object_unescape,
	duk_bi_json_object_parse,
	duk_bi_json_object_stringify,
	duk_bi_math_object_clz32,
	duk_bi_math_object_hypot,
	duk_bi_math_object_imul,
	duk_bi_math_object_max,
	duk_bi_math_object_min,
	duk_bi_math_object_onearg_shared,
	duk_bi_math_object_random,
	duk_bi_math_object_sign,
	duk_bi_math_object_twoarg_shared,
	duk_bi_native_function_length,
	duk_bi_native_function_name,
	duk_bi_nodejs_buffer_byte_length,
	duk_bi_nodejs_buffer_concat,
	duk_bi_nodejs_buffer_constructor,
	duk_bi_nodejs_buffer_copy,
	duk_bi_nodejs_buffer_fill,
	duk_bi_nodejs_buffer_is_buffer,
	duk_bi_nodejs_buffer_is_encoding,
	duk_bi_nodejs_buffer_tojson,
	duk_bi_nodejs_buffer_tostring,
	duk_bi_nodejs_buffer_write,
	duk_bi_number_check_shared,
	duk_bi_number_constructor,
	duk_bi_number_prototype_to_exponential,
	duk_bi_number_prototype_to_fixed,
	duk_bi_number_prototype_to_locale_string,
	duk_bi_number_prototype_to_precision,
	duk_bi_number_prototype_to_string,
	duk_bi_number_prototype_value_of,
	duk_bi_object_constructor,
	duk_bi_object_constructor_assign,
	duk_bi_object_constructor_create,
	duk_bi_object_constructor_define_properties,
	duk_bi_object_constructor_define_property,
	duk_bi_object_constructor_get_own_property_descriptor,
	duk_bi_object_constructor_is,
	duk_bi_object_constructor_is_extensible,
	duk_bi_object_constructor_is_sealed_frozen_shared,
	duk_bi_object_constructor_keys_shared,
	duk_bi_object_constructor_prevent_extensions,
	duk_bi_object_constructor_seal_freeze_shared,
	duk_bi_object_getprototype_shared,
	duk_bi_object_prototype_defineaccessor,
	duk_bi_object_prototype_has_own_property,
	duk_bi_object_prototype_is_prototype_of,
	duk_bi_object_prototype_lookupaccessor,
	duk_bi_object_prototype_property_is_enumerable,
	duk_bi_object_prototype_to_locale_string,
	duk_bi_object_prototype_to_string,
	duk_bi_object_prototype_value_of,
	duk_bi_object_setprototype_shared,
	duk_bi_performance_now,
	duk_bi_pointer_constructor,
	duk_bi_pointer_prototype_tostring_shared,
	duk_bi_proxy_constructor,
	duk_bi_reflect_apply,
	duk_bi_reflect_construct,
	duk_bi_reflect_object_delete_property,
	duk_bi_reflect_object_get,
	duk_bi_reflect_object_has,
	duk_bi_reflect_object_set,
	duk_bi_regexp_constructor,
	duk_bi_regexp_prototype_exec,
	duk_bi_regexp_prototype_flags,
	duk_bi_regexp_prototype_shared_getter,
	duk_bi_regexp_prototype_test,
	duk_bi_regexp_prototype_tostring,
	duk_bi_string_constructor,
	duk_bi_string_constructor_from_char_code,
	duk_bi_string_constructor_from_code_point,
	duk_bi_string_prototype_caseconv_shared,
	duk_bi_string_prototype_char_at,
	duk_bi_string_prototype_char_code_at,
	duk_bi_string_prototype_concat,
	duk_bi_string_prototype_includes,
	duk_bi_string_prototype_indexof_shared,
	duk_bi_string_prototype_locale_compare,
	duk_bi_string_prototype_match,
	duk_bi_string_prototype_repeat,
	duk_bi_string_prototype_replace,
	duk_bi_string_prototype_search,
	duk_bi_string_prototype_slice,
	duk_bi_string_prototype_split,
	duk_bi_string_prototype_startswith_endswith,
	duk_bi_string_prototype_substr,
	duk_bi_string_prototype_substring,
	duk_bi_string_prototype_to_string,
	duk_bi_string_prototype_trim,
	duk_bi_symbol_constructor_shared,
	duk_bi_symbol_key_for,
	duk_bi_symbol_toprimitive,
	duk_bi_symbol_tostring_shared,
	duk_bi_textdecoder_constructor,
	duk_bi_textdecoder_prototype_decode,
	duk_bi_textdecoder_prototype_shared_getter,
	duk_bi_textencoder_constructor,
	duk_bi_textencoder_prototype_encode,
	duk_bi_textencoder_prototype_encoding_getter,
	duk_bi_thread_constructor,
	duk_bi_thread_current,
	duk_bi_thread_resume,
	duk_bi_thread_yield,
	duk_bi_type_error_thrower,
	duk_bi_typedarray_buffer_getter,
	duk_bi_typedarray_bytelength_getter,
	duk_bi_typedarray_byteoffset_getter,
	duk_bi_typedarray_constructor,
	duk_bi_typedarray_set,
	duk_bi_uint8array_allocplain,
	duk_bi_uint8array_plainof,
};
#if defined(DUK_USE_DOUBLE_LE)
DUK_INTERNAL const duk_uint8_t duk_builtins_data[4281] = {
144,148,105,226,32,68,52,228,254,12,104,202,37,132,52,167,194,138,105,245,
124,57,28,211,57,18,64,52,239,126,44,138,111,175,241,164,19,87,145,30,33,
167,22,145,159,8,211,139,9,225,42,5,240,145,139,163,163,8,211,139,10,228,
64,211,19,132,140,93,29,56,70,156,88,119,34,66,146,36,104,137,194,70,46,
142,172,35,78,44,47,146,195,102,11,240,145,139,163,175,8,211,139,9,228,240,
242,112,145,139,163,179,8,211,139,8,237,34,130,118,49,116,118,225,26,48,0,
1,98,29,201,158,46,183,39,135,147,132,140,93,16,132,76,66,33,8,66,16,132,
33,8,66,26,180,105,97,167,68,150,34,33,154,112,0,1,91,247,35,79,111,237,
198,174,232,47,31,23,95,17,13,31,249,96,211,49,50,53,214,77,141,24,0,0,181,
10,228,240,242,15,128,140,65,128,134,188,0,0,90,167,97,181,224,0,2,213,62,
53,224,0,2,213,66,237,120,0,0,181,81,204,107,192,0,5,170,150,67,94,0,0,45,
84,245,90,240,0,1,106,169,162,215,128,0,11,85,93,150,188,0,0,90,171,111,53,
109,22,162,26,48,0,1,84,23,201,146,243,225,26,39,12,145,136,104,192,0,5,61,
11,228,201,121,240,100,19,134,72,196,33,195,14,40,203,112,64,190,76,232,
145,153,136,0,0,0,0,0,0,31,15,249,152,0,0,0,0,0,0,30,15,249,120,144,13,96,
155,194,56,80,206,36,67,141,20,228,70,57,81,206,100,131,156,39,132,168,23,
194,70,46,137,208,21,200,129,166,39,9,24,186,39,72,119,34,66,146,36,104,
137,194,70,46,137,212,23,201,97,179,5,248,72,197,209,58,194,121,60,60,156,
36,98,232,157,129,29,164,80,78,198,46,137,218,146,121,25,71,146,9,209,5,
209,61,48,126,14,138,152,30,67,186,23,143,139,175,131,202,135,228,72,85,
144,83,60,179,30,94,209,233,102,30,98,105,230,103,30,114,121,231,104,30,
122,137,231,233,30,130,153,232,106,30,138,169,232,235,30,144,67,193,25,19,
136,108,207,30,41,224,140,137,194,173,192,153,228,5,242,100,188,248,70,137,
195,36,79,78,47,147,37,231,193,144,78,25,34,122,145,111,36,74,232,176,13,
17,61,234,226,93,207,148,160,84,75,141,7,27,161,32,33,18,225,80,212,76,154,
2,2,70,65,56,100,237,34,140,209,2,67,32,156,50,118,145,64,186,230,61,205,
35,103,155,32,36,141,19,134,78,210,40,206,16,36,70,137,195,39,105,20,11,
174,99,220,210,54,121,210,1,137,33,1,228,207,16,17,70,146,66,3,201,164,32,
0,65,112,152,56,196,159,31,23,77,211,195,201,199,23,160,72,214,246,81,6,12,
73,241,214,111,31,23,60,145,158,56,50,72,81,67,230,232,242,80,19,49,39,199,
89,188,124,92,242,70,120,227,64,194,75,154,72,12,9,73,6,111,21,120,12,40,
144,19,39,25,0,225,144,168,105,56,248,185,228,140,241,200,96,64,100,42,26,
78,62,46,121,35,52,18,92,116,1,36,64,47,158,64,49,98,66,100,156,242,65,23,
196,149,35,103,194,94,100,108,144,230,203,156,64,66,37,201,16,11,32,249,
132,4,34,92,44,93,146,55,152,72,24,137,112,151,153,27,36,5,100,229,144,8,
162,98,92,210,5,76,73,241,214,111,31,23,60,145,158,57,44,48,46,92,185,164,
160,72,151,41,0,50,107,179,244,59,36,93,127,92,6,19,172,3,11,216,0,56,224,
151,29,102,241,241,115,201,25,227,164,64,106,37,199,197,211,116,240,242,
113,197,233,144,40,248,185,228,140,241,196,75,132,109,24,72,128,43,39,84,
129,13,173,161,144,168,105,56,98,78,100,142,214,215,69,1,13,173,161,144,
168,105,57,34,78,100,142,214,215,69,16,67,107,105,110,114,168,254,24,147,
153,35,181,181,212,32,67,107,105,110,114,168,254,72,147,153,35,181,181,212,
36,65,130,3,144,8,26,252,200,13,30,85,16,16,64,90,242,231,192,64,161,163,
203,31,26,172,193,17,4,23,105,159,96,27,172,251,16,32,196,4,14,137,112,17,
136,48,164,28,134,80,215,202,1,132,130,8,12,39,52,64,155,31,24,56,36,1,189,
207,132,0,35,233,35,195,62,3,196,149,36,100,72,160,2,200,232,44,227,0,11,
37,160,68,142,128,36,157,25,200,32,26,79,90,4,73,43,192,122,54,71,65,103,
44,248,14,134,140,151,227,138,231,208,45,96,148,248,134,140,151,227,138,
231,240,1,255,254,10,74,146,56,128,104,4,147,152,72,6,144,28,174,143,8,1,
30,1,165,3,96,31,0,211,3,21,11,153,35,0,211,131,68,131,160,137,16,250,5,
196,131,160,137,200,160,199,156,67,248,0,255,255,65,140,10,48,177,115,56,
35,130,60,19,134,79,89,240,52,177,115,56,39,12,156,123,144,217,251,15,135,
34,167,30,20,170,154,255,232,12,47,244,0,97,28,17,224,39,238,32,40,71,4,
120,39,12,156,4,253,228,5,137,195,39,30,228,54,124,4,253,228,128,194,115,
68,9,252,15,128,232,104,201,126,56,191,35,64,90,193,41,241,13,25,47,199,23,
228,105,3,86,225,1,100,224,156,199,130,36,249,144,10,192,76,71,250,16,15,
18,61,96,17,62,200,3,72,128,136,143,247,32,22,75,64,137,248,64,22,79,90,39,
249,64,38,84,12,167,20,52,223,196,2,230,238,45,214,36,120,32,72,158,208,4,
102,238,45,194,2,201,197,186,196,143,4,9,19,218,0,92,221,202,61,228,143,4,
9,19,218,8,35,55,113,110,16,22,78,81,239,36,120,32,72,158,208,64,73,197,12,
255,0,13,18,60,128,159,212,128,169,76,17,156,185,100,76,255,163,64,65,26,
57,114,200,153,255,70,144,33,13,18,232,50,75,226,104,6,149,3,41,199,246,
130,12,128,28,142,156,120,203,175,158,8,194,207,1,6,81,20,79,88,11,237,84,
11,161,32,127,255,255,255,255,255,247,191,137,235,16,221,170,129,116,36,0,
16,0,0,0,0,0,0,12,196,0,0,0,0,0,0,15,135,242,61,123,164,137,162,164,218,67,
74,134,162,120,128,0,0,0,0,0,1,224,254,71,173,33,129,52,84,155,72,105,80,
212,79,16,0,0,0,0,0,0,60,63,195,244,143,146,22,230,192,0,0,0,0,0,0,176,60,
33,214,2,251,82,1,73,180,134,204,134,36,96,127,255,255,255,255,255,159,161,
144,235,16,221,169,0,164,218,67,102,67,18,48,63,255,255,255,255,255,207,
240,196,60,17,145,56,134,204,241,226,158,8,200,156,42,220,9,158,65,196,34,
92,42,26,137,147,120,64,74,37,196,54,100,49,35,188,36,5,68,184,208,113,187,
194,80,212,75,146,1,73,196,54,100,49,35,188,38,57,37,56,240,0,0,0,0,0,0,0,
0,32,235,248,68,48,156,2,24,94,24,0,243,119,10,139,144,123,242,3,102,238,
18,239,115,72,217,160,11,223,16,23,55,113,241,32,145,36,57,188,18,16,102,3,
5,120,35,34,89,32,15,180,152,173,127,0,218,235,88,0,228,180,227,200,0,0,0,
0,0,0,248,127,197,107,240,64,6,77,220,24,38,78,74,113,67,77,130,4,12,155,
185,52,48,156,148,226,134,155,4,10,194,96,129,132,166,238,45,194,2,201,193,
130,100,228,167,20,52,216,32,113,41,187,139,112,128,178,114,104,97,57,41,
197,13,54,8,32,48,216,32,130,195,224,130,19,97,124,134,23,6,0,57,137,62,77,
12,38,12,0,179,18,124,45,22,190,96,128,141,176,134,28,98,79,180,152,139,
218,45,124,193,1,27,97,16,32,196,159,24,230,204,246,194,40,89,137,62,210,
98,103,92,217,158,216,70,7,49,39,193,130,100,182,17,194,140,73,246,147,16,
250,9,146,216,72,6,49,39,193,131,22,194,72,73,137,62,210,98,31,65,139,97,
40,32,196,159,14,234,70,86,194,88,89,137,62,210,98,63,93,72,202,216,76,10,
49,39,198,33,180,153,37,108,38,134,152,147,237,38,38,117,13,164,201,43,97,
56,40,196,159,36,65,57,163,149,176,158,26,98,79,180,152,165,210,9,205,28,
173,133,0,243,18,124,98,22,180,72,130,115,71,43,97,68,72,196,159,105,49,51,
168,90,209,34,9,205,28,173,133,33,19,18,124,154,24,76,185,164,227,138,89,
18,119,0,7,145,39,201,161,132,188,64,124,137,62,49,11,90,36,65,57,163,149,
210,166,37,34,79,180,152,153,212,45,104,145,4,230,142,87,74,160,84,137,62,
72,130,115,71,43,171,234,134,200,147,237,38,41,116,130,115,71,43,171,235,5,
72,147,227,16,218,76,146,186,254,184,108,137,62,210,98,103,80,218,76,146,
186,254,192,68,137,62,29,212,140,174,207,178,23,34,79,180,152,143,215,82,
50,187,62,208,60,137,62,12,19,37,210,182,21,34,79,180,152,135,208,76,151,
74,224,68,137,62,49,205,153,238,175,186,23,34,79,180,152,153,215,54,103,
186,190,240,92,137,62,22,139,95,48,64,70,235,251,225,210,36,251,73,136,189,
162,215,204,16,17,186,255,2,14,98,79,152,32,35,108,48,64,242,36,249,130,2,
55,75,6,212,224,72,200,51,128,114,108,28,100,128,0,0,0,0,0,0,0,12,110,127,
48,98,115,249,201,117,243,249,195,21,159,206,38,47,63,156,86,8,75,144,94,
82,1,38,73,79,208,67,95,233,1,6,128,14,79,129,186,40,249,18,149,182,207,
144,200,155,188,248,204,105,184,207,142,199,137,175,201,0,159,72,10,5,21,
221,10,120,74,129,124,36,98,232,228,74,81,62,160,20,10,107,186,21,114,32,
105,137,194,70,46,142,68,165,19,235,1,64,170,187,161,119,34,66,146,36,104,
137,194,70,46,142,68,165,19,236,1,64,174,187,161,95,37,134,204,23,225,35,
23,71,34,82,137,246,128,160,89,93,208,167,147,195,201,194,70,46,142,68,165,
19,238,1,64,182,187,161,71,105,20,19,177,139,163,145,41,68,16,7,6,15,82,70,
72,115,96,0,0,0,0,0,2,234,32,91,60,165,195,201,194,8,134,149,216,162,0,192,
41,225,8,2,48,177,36,1,149,13,196,15,0,200,209,97,199,128,99,32,176,195,
192,113,57,143,0,167,133,32,230,80,28,202,139,175,238,2,48,189,192,20,1,
119,80,87,193,186,129,89,56,72,197,209,200,193,185,35,23,71,109,13,219,36,
98,232,237,156,13,26,208,211,14,102,19,87,137,91,95,128,0,10,96,24,92,0,0,
83,2,53,56,0,0,165,3,28,204,160,160,226,100,226,200,211,76,241,240,0,1,102,
8,22,75,64,137,73,20,230,105,133,7,19,39,22,70,154,103,143,128,0,11,48,20,
28,76,156,113,75,34,78,62,0,0,45,3,103,31,0,0,22,65,44,57,137,62,33,179,
216,162,152,192,131,18,124,162,27,61,138,41,108,32,196,159,16,217,232,235,
81,76,104,73,137,62,81,13,158,142,181,20,184,16,98,79,136,108,244,244,168,
166,56,36,196,159,40,134,207,79,74,138,93,10,49,39,194,173,192,158,158,149,
20,188,20,98,79,133,91,129,61,109,74,41,124,30,68,159,16,217,236,83,108,96,
68,137,62,81,13,158,197,54,182,17,34,79,136,108,244,117,169,182,52,38,68,
159,40,134,207,71,90,155,92,8,145,39,196,54,122,122,84,219,28,19,34,79,148,
67,103,167,165,77,174,133,72,147,225,86,224,79,79,74,155,94,10,145,39,194,
173,192,158,182,165,54,190,206,25,212,35,208,226,100,150,211,201,29,162,44,
140,35,103,0,0,0,0,0,0,3,192,252,206,25,228,35,208,226,100,150,211,201,29,
162,44,140,35,103,0,0,0,0,0,0,3,192,252,206,25,244,35,208,226,100,150,211,
201,29,162,44,140,35,103,0,0,0,0,0,0,3,192,252,206,26,4,35,208,226,100,150,
211,201,29,162,44,140,35,103,0,0,0,0,0,0,0,1,0,206,26,20,35,208,226,100,
150,211,201,29,162,44,140,35,103,0,0,0,0,0,0,0,1,0,206,26,36,35,208,226,
100,150,211,201,29,162,44,140,35,103,0,0,0,0,0,0,0,65,0,206,26,52,35,208,
226,100,150,211,201,29,162,44,140,35,103,0,0,0,0,0,0,0,65,0,206,26,68,35,
208,226,100,150,211,201,29,162,44,140,35,103,0,0,0,0,0,0,0,65,0,206,26,84,
35,208,226,100,150,211,201,29,162,44,140,35,103,0,0,0,0,0,0,0,129,0,195,
154,99,16,38,36,0,251,68,117,179,216,162,128,68,72,1,241,13,158,197,20,150,
25,18,0,125,162,58,217,232,235,117,100,162,136,25,18,0,125,162,58,217,232,
235,116,36,162,145,2,226,64,15,136,108,244,117,186,178,81,73,129,113,32,7,
196,54,122,58,221,9,40,165,64,200,144,3,237,17,214,207,79,75,171,37,20,80,
200,144,3,237,17,214,207,79,75,161,37,20,138,23,18,0,124,67,103,167,165,
213,146,138,77,11,137,0,62,33,179,211,210,232,73,69,42,133,196,128,31,10,
183,2,125,89,40,163,5,196,128,31,10,183,2,125,9,40,164,96,200,144,3,224,
221,64,172,157,89,40,163,134,68,128,31,6,234,5,100,232,73,69,35,133,68,128,
31,104,142,182,125,89,40,180,0,168,144,3,237,17,214,207,161,37,22,144,19,
18,0,124,67,103,213,146,139,80,9,137,0,62,33,179,232,73,69,172,5,90,40,153,
59,68,117,179,216,166,192,77,162,137,147,136,108,246,41,180,176,219,69,19,
39,104,142,182,122,58,221,89,41,178,6,218,40,153,59,68,117,179,209,214,232,
73,77,162,6,90,40,153,56,134,207,71,91,171,37,54,152,25,104,162,100,226,27,
61,29,110,132,148,218,160,109,162,137,147,180,71,91,61,61,46,172,148,217,
67,109,20,76,157,162,58,217,233,233,116,36,166,209,67,45,20,76,156,67,103,
167,165,213,146,155,77,12,180,81,50,113,13,158,158,151,66,74,109,84,50,209,
68,201,194,173,192,159,86,74,108,193,150,138,38,78,21,110,4,250,18,83,104,
193,182,138,38,78,13,212,10,201,213,146,155,56,109,162,137,147,131,117,2,
178,116,36,166,209,194,237,20,76,157,162,58,217,245,100,167,16,2,237,20,76,
157,162,58,217,244,36,167,18,2,173,20,76,156,67,103,213,146,156,80,10,180,
81,50,113,13,159,66,74,113,97,175,221,48,216,110,64,4,42,22,189,179,0,196,
133,0,185,80,32,28,78,99,193,18,80,36,4,19,159,141,172,0,178,90,4,74,73,0,
22,209,68,201,187,129,4,2,8,3,132,64,60,36,6,149,113,72,176,171,240,84,0,
157,91,116,116,32,11,42,218,221,216,181,129,32,3,234,219,165,3,188,231,235,
249,8,187,152,252,47,86,227,105,18,7,244,17,91,42,56,175,185,248,110,173,
198,209,208,36,0,238,82,97,87,188,189,179,240,93,122,32,12,22,162,42,125,
144,132,160,7,236,161,25,232,237,105,64,205,59,127,102,158,160,230,63,11,
217,66,51,210,129,154,118,254,205,61,65,236,127,171,197,34,168,48,6,90,194,
1,0,39,75,88,72,8,9,33,186,194,80,64,76,13,214,19,2,130,96,110,150,189,0,
65,6,51,214,20,128,65,17,11,214,19,130,137,121,211,210,211,144,6,39,75,88,
80,0,201,119,235,10,8,41,86,231,71,88,80,129,79,135,186,122,133,224,34,25,
69,234,80,3,91,141,172,40,96,139,113,180,181,133,36,21,110,54,142,134,176,
165,1,176,23,213,47,0,216,134,234,215,128,111,117,181,232,128,209,3,70,230,
107,64,5,139,168,209,235,10,32,36,144,102,235,136,3,146,27,172,40,160,146,
132,103,172,40,192,115,3,117,133,28,22,113,163,69,172,41,103,1,66,188,17,
145,52,168,4,202,113,67,76,130,227,76,194,13,240,108,0,0,83,224,0,2,193,0,
104,146,84,97,48,0,1,94,192,56,169,24,145,179,192,0,5,112,8,56,16,32,128,
56,18,52,125,230,86,147,190,140,28,50,21,13,39,31,23,60,145,158,57,12,141,
47,129,6,155,194,188,24,49,39,199,89,188,124,92,242,70,120,224,201,33,69,
15,155,163,201,68,14,49,39,199,197,211,116,240,242,113,197,232,18,180,254,
36,3,17,46,18,243,35,100,128,172,156,178,70,163,154,76,34,248,146,164,108,
248,75,204,141,146,28,217,115,137,27,95,27,241,173,236,162,160,224,200,2,
206,9,113,13,148,192,209,18,22,164,146,37,193,57,162,4,249,39,196,128,24,2,
178,66,213,136,68,201,16,77,209,131,31,192,242,88,96,92,191,151,34,100,136,
38,232,255,252,92,221,199,197,12,68,209,82,66,212,11,155,185,41,197,13,55,
38,3,66,213,47,135,254,72,12,162,99,133,116,112,0,1,72,66,14,16,16,50,37,
202,160,150,154,66,14,20,8,57,192,28,24,80,113,50,113,100,105,166,120,248,
0,0,179,1,65,196,201,199,20,178,36,227,224,0,2,208,54,113,240,0,1,100,11,
181,192,0,5,178,1,18,160,65,24,131,20,145,25,188,48,132,122,28,76,146,218,
121,35,180,69,145,132,108,224,0,0,0,0,0,0,120,31,153,188,56,132,122,28,76,
146,218,121,35,180,69,145,132,108,224,0,0,0,0,0,0,120,31,168,160,45,110,23,
30,176,33,184,0,0,183,32,29,235,2,27,199,23,0,0,23,4,51,120,129,8,244,56,
153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,240,63,51,120,145,8,244,
56,153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,0,64,51,120,161,8,
244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,0,64,51,120,177,
8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,16,64,51,120,
193,8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,16,64,51,
120,209,8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,16,64,
51,120,225,8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,32,
64,32,227,194,0,97,57,162,4,246,104,5,34,92,35,68,225,161,166,220,16,16,
137,112,52,41,73,29,185,1,65,196,201,197,145,166,153,246,72,3,137,204,120,
34,74,8,199,1,67,17,162,112,201,84,128,97,144,78,25,42,16,131,169,1,205,66,
8,35,68,225,161,166,239,128,0,10,192,64,196,104,156,50,96,0,2,172,73,240,
117,96,57,170,97,4,104,156,52,52,221,240,0,1,82,1,74,9,129,125,240,0,1,82,
32,148,25,174,137,58,23,51,190,0,0,42,69,64,195,32,156,50,96,0,2,160,81,
238,2,3,107,173,218,3,192,
};
#elif defined(DUK_USE_DOUBLE_BE)
DUK_INTERNAL const duk_uint8_t duk_builtins_data[4281] = {
144,148,105,226,32,68,52,228,254,12,104,202,37,132,52,167,194,138,105,245,
124,57,28,211,57,18,64,52,239,126,44,138,111,175,241,164,19,87,145,30,33,
167,22,145,159,8,211,139,9,225,42,5,240,145,139,163,163,8,211,139,10,228,
64,211,19,132,140,93,29,56,70,156,88,119,34,66,146,36,104,137,194,70,46,
142,172,35,78,44,47,146,195,102,11,240,145,139,163,175,8,211,139,9,228,240,
242,112,145,139,163,179,8,211,139,8,237,34,130,118,49,116,118,225,26,48,0,
1,98,29,201,158,46,183,39,135,147,132,140,93,16,132,76,66,33,8,66,16,132,
33,8,66,26,180,105,97,167,68,150,34,33,154,112,0,1,91,247,35,79,111,237,
198,174,232,47,31,23,95,17,13,31,249,96,211,49,50,53,214,77,141,24,0,0,181,
10,228,240,242,15,128,140,65,128,134,188,0,0,90,167,97,181,224,0,2,213,62,
53,224,0,2,213,66,237,120,0,0,181,81,204,107,192,0,5,170,150,67,94,0,0,45,
84,245,90,240,0,1,106,169,162,215,128,0,11,85,93,150,188,0,0,90,171,111,53,
109,22,162,26,48,0,1,84,23,201,146,243,225,26,39,12,145,136,104,192,0,5,61,
11,228,201,121,240,100,19,134,72,196,33,195,14,40,203,112,64,190,76,232,
145,153,136,15,255,0,0,0,0,0,0,25,152,15,254,0,0,0,0,0,0,25,120,144,13,96,
155,194,56,80,206,36,67,141,20,228,70,57,81,206,100,131,156,39,132,168,23,
194,70,46,137,208,21,200,129,166,39,9,24,186,39,72,119,34,66,146,36,104,
137,194,70,46,137,212,23,201,97,179,5,248,72,197,209,58,194,121,60,60,156,
36,98,232,157,129,29,164,80,78,198,46,137,218,146,121,25,71,146,9,209,5,
209,61,48,126,14,138,152,30,67,186,23,143,139,175,131,202,135,228,72,85,
144,83,60,179,30,94,209,233,102,30,98,105,230,103,30,114,121,231,104,30,
122,137,231,233,30,130,153,232,106,30,138,169,232,235,30,144,67,193,25,19,
136,108,207,30,41,224,140,137,194,173,192,153,228,5,242,100,188,248,70,137,
195,36,79,78,47,147,37,231,193,144,78,25,34,122,145,111,36,74,232,176,13,
17,61,234,226,93,207,148,160,84,75,141,7,27,161,32,33,18,225,80,212,76,154,
2,2,70,65,56,100,237,34,140,209,2,67,32,156,50,118,145,64,186,230,61,205,
35,103,155,32,36,141,19,134,78,210,40,206,16,36,70,137,195,39,105,20,11,
174,99,220,210,54,121,210,1,137,33,1,228,207,16,17,70,146,66,3,201,164,32,
0,65,112,152,56,196,159,31,23,77,211,195,201,199,23,160,72,214,246,81,6,12,
73,241,214,111,31,23,60,145,158,56,50,72,81,67,230,232,242,80,19,49,39,199,
89,188,124,92,242,70,120,227,64,194,75,154,72,12,9,73,6,111,21,120,12,40,
144,19,39,25,0,225,144,168,105,56,248,185,228,140,241,200,96,64,100,42,26,
78,62,46,121,35,52,18,92,116,1,36,64,47,158,64,49,98,66,100,156,242,65,23,
196,149,35,103,194,94,100,108,144,230,203,156,64,66,37,201,16,11,32,249,
132,4,34,92,44,93,146,55,152,72,24,137,112,151,153,27,36,5,100,229,144,8,
162,98,92,210,5,76,73,241,214,111,31,23,60,145,158,57,44,48,46,92,185,164,
160,72,151,41,0,50,107,179,244,59,36,93,127,92,6,19,172,3,11,216,0,56,224,
151,29,102,241,241,115,201,25,227,164,64,106,37,199,197,211,116,240,242,
113,197,233,144,40,248,185,228,140,241,196,75,132,109,24,72,128,43,39,84,
129,13,173,161,144,168,105,56,98,78,100,142,214,215,69,1,13,173,161,144,
168,105,57,34,78,100,142,214,215,69,16,67,107,105,110,114,168,254,24,147,
153,35,181,181,212,32,67,107,105,110,114,168,254,72,147,153,35,181,181,212,
36,65,130,3,144,8,26,252,200,13,30,85,16,16,64,90,242,231,192,64,161,163,
203,31,26,172,193,17,4,23,105,159,96,27,172,251,16,32,196,4,14,137,112,17,
136,48,164,28,134,80,215,202,1,132,130,8,12,39,52,64,155,31,24,56,36,1,189,
207,132,0,35,233,35,195,62,3,196,149,36,100,72,160,2,200,232,44,227,0,11,
37,160,68,142,128,36,157,25,200,32,26,79,90,4,73,43,192,122,54,71,65,103,
44,248,14,134,140,151,227,138,231,208,45,96,148,248,134,140,151,227,138,
231,240,1,255,254,10,74,146,56,128,104,4,147,152,72,6,144,28,174,143,8,1,
30,1,165,3,96,31,0,211,3,21,11,153,35,0,211,131,68,131,160,137,16,250,5,
196,131,160,137,200,160,199,156,67,248,0,255,255,65,140,10,48,177,115,56,
35,130,60,19,134,79,89,240,52,177,115,56,39,12,156,123,144,217,251,15,135,
34,167,30,20,170,154,255,232,12,47,244,0,97,28,17,224,39,238,32,40,71,4,
120,39,12,156,4,253,228,5,137,195,39,30,228,54,124,4,253,228,128,194,115,
68,9,252,15,128,232,104,201,126,56,191,35,64,90,193,41,241,13,25,47,199,23,
228,105,3,86,225,1,100,224,156,199,130,36,249,144,10,192,76,71,250,16,15,
18,61,96,17,62,200,3,72,128,136,143,247,32,22,75,64,137,248,64,22,79,90,39,
249,64,38,84,12,167,20,52,223,196,2,230,238,45,214,36,120,32,72,158,208,4,
102,238,45,194,2,201,197,186,196,143,4,9,19,218,0,92,221,202,61,228,143,4,
9,19,218,8,35,55,113,110,16,22,78,81,239,36,120,32,72,158,208,64,73,197,12,
255,0,13,18,60,128,159,212,128,169,76,17,156,185,100,76,255,163,64,65,26,
57,114,200,153,255,70,144,33,13,18,232,50,75,226,104,6,149,3,41,199,246,
130,12,128,28,142,156,120,203,175,158,8,194,207,1,6,81,20,79,88,11,237,84,
11,161,32,63,247,255,255,255,255,255,255,137,235,16,221,170,129,116,36,0,0,
0,0,0,0,0,0,28,196,7,255,128,0,0,0,0,0,2,61,123,164,137,162,164,218,67,74,
134,162,120,128,255,224,0,0,0,0,0,0,71,173,33,129,52,84,155,72,105,80,212,
79,16,63,252,0,0,0,0,0,0,3,244,143,146,22,230,192,60,176,0,0,0,0,0,0,33,
214,2,251,82,1,73,180,134,204,134,36,96,33,159,255,255,255,255,255,255,144,
235,16,221,169,0,164,218,67,102,67,18,48,48,207,255,255,255,255,255,255,
196,60,17,145,56,134,204,241,226,158,8,200,156,42,220,9,158,65,196,34,92,
42,26,137,147,120,64,74,37,196,54,100,49,35,188,36,5,68,184,208,113,187,
194,80,212,75,146,1,73,196,54,100,49,35,188,38,57,37,56,240,0,0,0,0,0,0,0,
0,32,235,248,68,48,156,2,24,94,24,0,243,119,10,139,144,123,242,3,102,238,
18,239,115,72,217,160,11,223,16,23,55,113,241,32,145,36,57,188,18,16,102,3,
5,120,35,34,89,32,15,180,152,173,127,0,218,235,88,0,228,180,227,200,127,
248,0,0,0,0,0,0,197,107,240,64,6,77,220,24,38,78,74,113,67,77,130,4,12,155,
185,52,48,156,148,226,134,155,4,10,194,96,129,132,166,238,45,194,2,201,193,
130,100,228,167,20,52,216,32,113,41,187,139,112,128,178,114,104,97,57,41,
197,13,54,8,32,48,216,32,130,195,224,130,19,97,124,134,23,6,0,57,137,62,77,
12,38,12,0,179,18,124,45,22,190,96,128,141,176,134,28,98,79,180,152,139,
218,45,124,193,1,27,97,16,32,196,159,24,230,204,246,194,40,89,137,62,210,
98,103,92,217,158,216,70,7,49,39,193,130,100,182,17,194,140,73,246,147,16,
250,9,146,216,72,6,49,39,193,131,22,194,72,73,137,62,210,98,31,65,139,97,
40,32,196,159,14,234,70,86,194,88,89,137,62,210,98,63,93,72,202,216,76,10,
49,39,198,33,180,153,37,108,38,134,152,147,237,38,38,117,13,164,201,43,97,
56,40,196,159,36,65,57,163,149,176,158,26,98,79,180,152,165,210,9,205,28,
173,133,0,243,18,124,98,22,180,72,130,115,71,43,97,68,72,196,159,105,49,51,
168,90,209,34,9,205,28,173,133,33,19,18,124,154,24,76,185,164,227,138,89,
18,119,0,7,145,39,201,161,132,188,64,124,137,62,49,11,90,36,65,57,163,149,
210,166,37,34,79,180,152,153,212,45,104,145,4,230,142,87,74,160,84,137,62,
72,130,115,71,43,171,234,134,200,147,237,38,41,116,130,115,71,43,171,235,5,
72,147,227,16,218,76,146,186,254,184,108,137,62,210,98,103,80,218,76,146,
186,254,192,68,137,62,29,212,140,174,207,178,23,34,79,180,152,143,215,82,
50,187,62,208,60,137,62,12,19,37,210,182,21,34,79,180,152,135,208,76,151,
74,224,68,137,62,49,205,153,238,175,186,23,34,79,180,152,153,215,54,103,
186,190,240,92,137,62,22,139,95,48,64,70,235,251,225,210,36,251,73,136,189,
162,215,204,16,17,186,255,2,14,98,79,152,32,35,108,48,64,242,36,249,130,2,
55,75,6,212,224,72,200,51,128,114,108,28,100,128,0,0,0,0,0,0,0,12,110,127,
48,98,115,249,201,117,243,249,195,21,159,206,38,47,63,156,86,8,75,144,94,
82,1,38,73,79,208,67,95,233,1,6,128,14,79,129,186,40,249,18,149,182,207,
144,200,155,188,248,204,105,184,207,142,199,137,175,201,0,159,72,10,5,21,
221,10,120,74,129,124,36,98,232,228,74,81,62,160,20,10,107,186,21,114,32,
105,137,194,70,46,142,68,165,19,235,1,64,170,187,161,119,34,66,146,36,104,
137,194,70,46,142,68,165,19,236,1,64,174,187,161,95,37,134,204,23,225,35,
23,71,34,82,137,246,128,160,89,93,208,167,147,195,201,194,70,46,142,68,165,
19,238,1,64,182,187,161,71,105,20,19,177,139,163,145,41,68,16,7,6,15,82,70,
72,115,96,32,106,2,128,0,0,0,0,91,60,165,195,201,194,8,134,149,216,162,0,
192,41,225,8,2,48,177,36,1,149,13,196,15,0,200,209,97,199,128,99,32,176,
195,192,113,57,143,0,167,133,32,230,80,28,202,139,175,238,2,48,189,192,20,
1,119,80,87,193,186,129,89,56,72,197,209,200,193,185,35,23,71,109,13,219,
36,98,232,237,156,13,26,208,211,14,102,19,87,137,91,95,128,0,10,96,24,92,0,
0,83,2,53,56,0,0,165,3,28,204,160,160,226,100,226,200,211,76,241,240,0,1,
102,8,22,75,64,137,73,20,230,105,133,7,19,39,22,70,154,103,143,128,0,11,48,
20,28,76,156,113,75,34,78,62,0,0,45,3,103,31,0,0,22,65,44,57,137,62,33,179,
216,162,152,192,131,18,124,162,27,61,138,41,108,32,196,159,16,217,232,235,
81,76,104,73,137,62,81,13,158,142,181,20,184,16,98,79,136,108,244,244,168,
166,56,36,196,159,40,134,207,79,74,138,93,10,49,39,194,173,192,158,158,149,
20,188,20,98,79,133,91,129,61,109,74,41,124,30,68,159,16,217,236,83,108,96,
68,137,62,81,13,158,197,54,182,17,34,79,136,108,244,117,169,182,52,38,68,
159,40,134,207,71,90,155,92,8,145,39,196,54,122,122,84,219,28,19,34,79,148,
67,103,167,165,77,174,133,72,147,225,86,224,79,79,74,155,94,10,145,39,194,
173,192,158,182,165,54,190,206,25,212,35,208,226,100,150,211,201,29,162,44,
140,35,103,0,255,192,0,0,0,0,0,0,206,25,228,35,208,226,100,150,211,201,29,
162,44,140,35,103,0,255,192,0,0,0,0,0,0,206,25,244,35,208,226,100,150,211,
201,29,162,44,140,35,103,0,255,192,0,0,0,0,0,0,206,26,4,35,208,226,100,150,
211,201,29,162,44,140,35,103,1,0,0,0,0,0,0,0,0,206,26,20,35,208,226,100,
150,211,201,29,162,44,140,35,103,1,0,0,0,0,0,0,0,0,206,26,36,35,208,226,
100,150,211,201,29,162,44,140,35,103,1,0,64,0,0,0,0,0,0,206,26,52,35,208,
226,100,150,211,201,29,162,44,140,35,103,1,0,64,0,0,0,0,0,0,206,26,68,35,
208,226,100,150,211,201,29,162,44,140,35,103,1,0,64,0,0,0,0,0,0,206,26,84,
35,208,226,100,150,211,201,29,162,44,140,35,103,1,0,128,0,0,0,0,0,0,195,
154,99,16,38,36,0,251,68,117,179,216,162,128,68,72,1,241,13,158,197,20,150,
25,18,0,125,162,58,217,232,235,117,100,162,136,25,18,0,125,162,58,217,232,
235,116,36,162,145,2,226,64,15,136,108,244,117,186,178,81,73,129,113,32,7,
196,54,122,58,221,9,40,165,64,200,144,3,237,17,214,207,79,75,171,37,20,80,
200,144,3,237,17,214,207,79,75,161,37,20,138,23,18,0,124,67,103,167,165,
213,146,138,77,11,137,0,62,33,179,211,210,232,73,69,42,133,196,128,31,10,
183,2,125,89,40,163,5,196,128,31,10,183,2,125,9,40,164,96,200,144,3,224,
221,64,172,157,89,40,163,134,68,128,31,6,234,5,100,232,73,69,35,133,68,128,
31,104,142,182,125,89,40,180,0,168,144,3,237,17,214,207,161,37,22,144,19,
18,0,124,67,103,213,146,139,80,9,137,0,62,33,179,232,73,69,172,5,90,40,153,
59,68,117,179,216,166,192,77,162,137,147,136,108,246,41,180,176,219,69,19,
39,104,142,182,122,58,221,89,41,178,6,218,40,153,59,68,117,179,209,214,232,
73,77,162,6,90,40,153,56,134,207,71,91,171,37,54,152,25,104,162,100,226,27,
61,29,110,132,148,218,160,109,162,137,147,180,71,91,61,61,46,172,148,217,
67,109,20,76,157,162,58,217,233,233,116,36,166,209,67,45,20,76,156,67,103,
167,165,213,146,155,77,12,180,81,50,113,13,158,158,151,66,74,109,84,50,209,
68,201,194,173,192,159,86,74,108,193,150,138,38,78,21,110,4,250,18,83,104,
193,182,138,38,78,13,212,10,201,213,146,155,56,109,162,137,147,131,117,2,
178,116,36,166,209,194,237,20,76,157,162,58,217,245,100,167,16,2,237,20,76,
157,162,58,217,244,36,167,18,2,173,20,76,156,67,103,213,146,156,80,10,180,
81,50,113,13,159,66,74,113,97,175,221,48,216,110,64,4,42,22,189,179,0,196,
133,0,185,80,32,28,78,99,193,18,80,36,4,19,159,141,172,0,178,90,4,74,73,0,
22,209,68,201,187,129,4,2,8,3,132,64,60,36,4,0,91,240,168,177,69,118,144,
157,91,116,116,32,32,1,53,216,221,218,170,139,3,234,219,165,0,255,152,185,
11,251,232,231,188,47,86,227,105,18,1,255,184,170,59,41,92,23,240,110,173,
198,209,208,36,3,253,188,183,177,82,110,80,224,93,122,32,32,4,144,253,170,
34,22,140,7,236,161,25,232,237,105,64,63,230,160,158,102,127,59,205,11,217,
66,51,210,128,127,237,65,60,204,254,119,155,171,197,34,168,48,6,90,194,1,0,
39,75,88,72,8,9,33,186,194,80,64,76,13,214,19,2,130,96,110,150,189,0,65,6,
51,214,20,128,65,17,11,214,19,130,137,121,211,210,211,144,6,39,75,88,80,0,
201,119,235,10,8,41,86,231,71,88,80,129,79,135,186,122,133,224,34,25,69,
234,80,3,91,141,172,40,96,139,113,180,181,133,36,21,110,54,142,134,176,165,
1,176,23,213,47,0,216,134,234,215,128,111,117,181,232,128,209,3,70,230,107,
64,5,139,168,209,235,10,32,36,144,102,235,136,3,146,27,172,40,160,146,132,
103,172,40,192,115,3,117,133,28,22,113,163,69,172,41,103,1,66,188,17,145,
52,168,4,202,113,67,76,130,227,76,194,13,240,108,0,0,83,224,0,2,193,0,104,
146,84,97,48,0,1,94,192,56,169,24,145,179,192,0,5,112,8,56,16,32,128,56,18,
52,125,230,86,147,190,140,28,50,21,13,39,31,23,60,145,158,57,12,141,47,129,
6,155,194,188,24,49,39,199,89,188,124,92,242,70,120,224,201,33,69,15,155,
163,201,68,14,49,39,199,197,211,116,240,242,113,197,232,18,180,254,36,3,17,
46,18,243,35,100,128,172,156,178,70,163,154,76,34,248,146,164,108,248,75,
204,141,146,28,217,115,137,27,95,27,241,173,236,162,160,224,200,2,206,9,
113,13,148,192,209,18,22,164,146,37,193,57,162,4,249,39,196,128,24,2,178,
66,213,136,68,201,16,77,209,131,31,192,242,88,96,92,191,151,34,100,136,38,
232,255,252,92,221,199,197,12,68,209,82,66,212,11,155,185,41,197,13,55,38,
3,66,213,47,135,254,72,12,162,99,133,116,112,0,1,72,66,14,16,16,50,37,202,
160,150,154,66,14,20,8,57,192,28,24,80,113,50,113,100,105,166,120,248,0,0,
179,1,65,196,201,199,20,178,36,227,224,0,2,208,54,113,240,0,1,100,11,181,
192,0,5,178,1,18,160,65,24,131,20,145,25,188,48,132,122,28,76,146,218,121,
35,180,69,145,132,108,224,31,248,0,0,0,0,0,0,25,188,56,132,122,28,76,146,
218,121,35,180,69,145,132,108,224,31,248,0,0,0,0,0,0,40,160,45,110,23,30,
176,33,184,0,0,183,32,29,235,2,27,199,23,0,0,23,4,51,120,129,8,244,56,153,
37,180,242,71,104,139,35,8,217,192,63,240,0,0,0,0,0,0,51,120,145,8,244,56,
153,37,180,242,71,104,139,35,8,217,192,64,0,0,0,0,0,0,0,51,120,161,8,244,
56,153,37,180,242,71,104,139,35,8,217,192,64,0,0,0,0,0,0,0,51,120,177,8,
244,56,153,37,180,242,71,104,139,35,8,217,192,64,16,0,0,0,0,0,0,51,120,193,
8,244,56,153,37,180,242,71,104,139,35,8,217,192,64,16,0,0,0,0,0,0,51,120,
209,8,244,56,153,37,180,242,71,104,139,35,8,217,192,64,16,0,0,0,0,0,0,51,
120,225,8,244,56,153,37,180,242,71,104,139,35,8,217,192,64,32,0,0,0,0,0,0,
32,227,194,0,97,57,162,4,246,104,5,34,92,35,68,225,161,166,220,16,16,137,
112,52,41,73,29,185,1,65,196,201,197,145,166,153,246,72,3,137,204,120,34,
74,8,199,1,67,17,162,112,201,84,128,97,144,78,25,42,16,131,169,1,205,66,8,
35,68,225,161,166,239,128,0,10,192,64,196,104,156,50,96,0,2,172,73,240,117,
96,57,170,97,4,104,156,52,52,221,240,0,1,82,1,74,9,129,125,240,0,1,82,32,
148,25,174,137,58,23,51,190,0,0,42,69,64,195,32,156,50,96,0,2,160,81,238,2,
3,107,173,218,3,192,
};
#elif defined(DUK_USE_DOUBLE_ME)
DUK_INTERNAL const duk_uint8_t duk_builtins_data[4281] = {
144,148,105,226,32,68,52,228,254,12,104,202,37,132,52,167,194,138,105,245,
124,57,28,211,57,18,64,52,239,126,44,138,111,175,241,164,19,87,145,30,33,
167,22,145,159,8,211,139,9,225,42,5,240,145,139,163,163,8,211,139,10,228,
64,211,19,132,140,93,29,56,70,156,88,119,34,66,146,36,104,137,194,70,46,
142,172,35,78,44,47,146,195,102,11,240,145,139,163,175,8,211,139,9,228,240,
242,112,145,139,163,179,8,211,139,8,237,34,130,118,49,116,118,225,26,48,0,
1,98,29,201,158,46,183,39,135,147,132,140,93,16,132,76,66,33,8,66,16,132,
33,8,66,26,180,105,97,167,68,150,34,33,154,112,0,1,91,247,35,79,111,237,
198,174,232,47,31,23,95,17,13,31,249,96,211,49,50,53,214,77,141,24,0,0,181,
10,228,240,242,15,128,140,65,128,134,188,0,0,90,167,97,181,224,0,2,213,62,
53,224,0,2,213,66,237,120,0,0,181,81,204,107,192,0,5,170,150,67,94,0,0,45,
84,245,90,240,0,1,106,169,162,215,128,0,11,85,93,150,188,0,0,90,171,111,53,
109,22,162,26,48,0,1,84,23,201,146,243,225,26,39,12,145,136,104,192,0,5,61,
11,228,201,121,240,100,19,134,72,196,33,195,14,40,203,112,64,190,76,232,
145,153,136,0,0,31,15,224,0,0,0,25,152,0,0,30,15,224,0,0,0,25,120,144,13,
96,155,194,56,80,206,36,67,141,20,228,70,57,81,206,100,131,156,39,132,168,
23,194,70,46,137,208,21,200,129,166,39,9,24,186,39,72,119,34,66,146,36,104,
137,194,70,46,137,212,23,201,97,179,5,248,72,197,209,58,194,121,60,60,156,
36,98,232,157,129,29,164,80,78,198,46,137,218,146,121,25,71,146,9,209,5,
209,61,48,126,14,138,152,30,67,186,23,143,139,175,131,202,135,228,72,85,
144,83,60,179,30,94,209,233,102,30,98,105,230,103,30,114,121,231,104,30,
122,137,231,233,30,130,153,232,106,30,138,169,232,235,30,144,67,193,25,19,
136,108,207,30,41,224,140,137,194,173,192,153,228,5,242,100,188,248,70,137,
195,36,79,78,47,147,37,231,193,144,78,25,34,122,145,111,36,74,232,176,13,
17,61,234,226,93,207,148,160,84,75,141,7,27,161,32,33,18,225,80,212,76,154,
2,2,70,65,56,100,237,34,140,209,2,67,32,156,50,118,145,64,186,230,61,205,
35,103,155,32,36,141,19,134,78,210,40,206,16,36,70,137,195,39,105,20,11,
174,99,220,210,54,121,210,1,137,33,1,228,207,16,17,70,146,66,3,201,164,32,
0,65,112,152,56,196,159,31,23,77,211,195,201,199,23,160,72,214,246,81,6,12,
73,241,214,111,31,23,60,145,158,56,50,72,81,67,230,232,242,80,19,49,39,199,
89,188,124,92,242,70,120,227,64,194,75,154,72,12,9,73,6,111,21,120,12,40,
144,19,39,25,0,225,144,168,105,56,248,185,228,140,241,200,96,64,100,42,26,
78,62,46,121,35,52,18,92,116,1,36,64,47,158,64,49,98,66,100,156,242,65,23,
196,149,35,103,194,94,100,108,144,230,203,156,64,66,37,201,16,11,32,249,
132,4,34,92,44,93,146,55,152,72,24,137,112,151,153,27,36,5,100,229,144,8,
162,98,92,210,5,76,73,241,214,111,31,23,60,145,158,57,44,48,46,92,185,164,
160,72,151,41,0,50,107,179,244,59,36,93,127,92,6,19,172,3,11,216,0,56,224,
151,29,102,241,241,115,201,25,227,164,64,106,37,199,197,211,116,240,242,
113,197,233,144,40,248,185,228,140,241,196,75,132,109,24,72,128,43,39,84,
129,13,173,161,144,168,105,56,98,78,100,142,214,215,69,1,13,173,161,144,
168,105,57,34,78,100,142,214,215,69,16,67,107,105,110,114,168,254,24,147,
153,35,181,181,212,32,67,107,105,110,114,168,254,72,147,153,35,181,181,212,
36,65,130,3,144,8,26,252,200,13,30,85,16,16,64,90,242,231,192,64,161,163,
203,31,26,172,193,17,4,23,105,159,96,27,172,251,16,32,196,4,14,137,112,17,
136,48,164,28,134,80,215,202,1,132,130,8,12,39,52,64,155,31,24,56,36,1,189,
207,132,0,35,233,35,195,62,3,196,149,36,100,72,160,2,200,232,44,227,0,11,
37,160,68,142,128,36,157,25,200,32,26,79,90,4,73,43,192,122,54,71,65,103,
44,248,14,134,140,151,227,138,231,208,45,96,148,248,134,140,151,227,138,
231,240,1,255,254,10,74,146,56,128,104,4,147,152,72,6,144,28,174,143,8,1,
30,1,165,3,96,31,0,211,3,21,11,153,35,0,211,131,68,131,160,137,16,250,5,
196,131,160,137,200,160,199,156,67,248,0,255,255,65,140,10,48,177,115,56,
35,130,60,19,134,79,89,240,52,177,115,56,39,12,156,123,144,217,251,15,135,
34,167,30,20,170,154,255,232,12,47,244,0,97,28,17,224,39,238,32,40,71,4,
120,39,12,156,4,253,228,5,137,195,39,30,228,54,124,4,253,228,128,194,115,
68,9,252,15,128,232,104,201,126,56,191,35,64,90,193,41,241,13,25,47,199,23,
228,105,3,86,225,1,100,224,156,199,130,36,249,144,10,192,76,71,250,16,15,
18,61,96,17,62,200,3,72,128,136,143,247,32,22,75,64,137,248,64,22,79,90,39,
249,64,38,84,12,167,20,52,223,196,2,230,238,45,214,36,120,32,72,158,208,4,
102,238,45,194,2,201,197,186,196,143,4,9,19,218,0,92,221,202,61,228,143,4,
9,19,218,8,35,55,113,110,16,22,78,81,239,36,120,32,72,158,208,64,73,197,12,
255,0,13,18,60,128,159,212,128,169,76,17,156,185,100,76,255,163,64,65,26,
57,114,200,153,255,70,144,33,13,18,232,50,75,226,104,6,149,3,41,199,246,
130,12,128,28,142,156,120,203,175,158,8,194,207,1,6,81,20,79,88,11,237,84,
11,161,32,127,255,247,191,255,255,255,255,137,235,16,221,170,129,116,36,0,
0,0,0,0,16,0,0,12,196,0,0,15,135,240,0,0,0,2,61,123,164,137,162,164,218,67,
74,134,162,120,128,0,1,224,254,0,0,0,0,71,173,33,129,52,84,155,72,105,80,
212,79,16,0,0,60,63,192,0,0,0,3,244,143,146,22,230,192,0,0,176,60,0,0,0,0,
33,214,2,251,82,1,73,180,134,204,134,36,96,127,255,159,161,255,255,255,255,
144,235,16,221,169,0,164,218,67,102,67,18,48,63,255,207,240,255,255,255,
255,196,60,17,145,56,134,204,241,226,158,8,200,156,42,220,9,158,65,196,34,
92,42,26,137,147,120,64,74,37,196,54,100,49,35,188,36,5,68,184,208,113,187,
194,80,212,75,146,1,73,196,54,100,49,35,188,38,57,37,56,240,0,0,0,0,0,0,0,
0,32,235,248,68,48,156,2,24,94,24,0,243,119,10,139,144,123,242,3,102,238,
18,239,115,72,217,160,11,223,16,23,55,113,241,32,145,36,57,188,18,16,102,3,
5,120,35,34,89,32,15,180,152,173,127,0,218,235,88,0,228,180,227,200,0,0,
248,127,0,0,0,0,197,107,240,64,6,77,220,24,38,78,74,113,67,77,130,4,12,155,
185,52,48,156,148,226,134,155,4,10,194,96,129,132,166,238,45,194,2,201,193,
130,100,228,167,20,52,216,32,113,41,187,139,112,128,178,114,104,97,57,41,
197,13,54,8,32,48,216,32,130,195,224,130,19,97,124,134,23,6,0,57,137,62,77,
12,38,12,0,179,18,124,45,22,190,96,128,141,176,134,28,98,79,180,152,139,
218,45,124,193,1,27,97,16,32,196,159,24,230,204,246,194,40,89,137,62,210,
98,103,92,217,158,216,70,7,49,39,193,130,100,182,17,194,140,73,246,147,16,
250,9,146,216,72,6,49,39,193,131,22,194,72,73,137,62,210,98,31,65,139,97,
40,32,196,159,14,234,70,86,194,88,89,137,62,210,98,63,93,72,202,216,76,10,
49,39,198,33,180,153,37,108,38,134,152,147,237,38,38,117,13,164,201,43,97,
56,40,196,159,36,65,57,163,149,176,158,26,98,79,180,152,165,210,9,205,28,
173,133,0,243,18,124,98,22,180,72,130,115,71,43,97,68,72,196,159,105,49,51,
168,90,209,34,9,205,28,173,133,33,19,18,124,154,24,76,185,164,227,138,89,
18,119,0,7,145,39,201,161,132,188,64,124,137,62,49,11,90,36,65,57,163,149,
210,166,37,34,79,180,152,153,212,45,104,145,4,230,142,87,74,160,84,137,62,
72,130,115,71,43,171,234,134,200,147,237,38,41,116,130,115,71,43,171,235,5,
72,147,227,16,218,76,146,186,254,184,108,137,62,210,98,103,80,218,76,146,
186,254,192,68,137,62,29,212,140,174,207,178,23,34,79,180,152,143,215,82,
50,187,62,208,60,137,62,12,19,37,210,182,21,34,79,180,152,135,208,76,151,
74,224,68,137,62,49,205,153,238,175,186,23,34,79,180,152,153,215,54,103,
186,190,240,92,137,62,22,139,95,48,64,70,235,251,225,210,36,251,73,136,189,
162,215,204,16,17,186,255,2,14,98,79,152,32,35,108,48,64,242,36,249,130,2,
55,75,6,212,224,72,200,51,128,114,108,28,100,128,0,0,0,0,0,0,0,12,110,127,
48,98,115,249,201,117,243,249,195,21,159,206,38,47,63,156,86,8,75,144,94,
82,1,38,73,79,208,67,95,233,1,6,128,14,79,129,186,40,249,18,149,182,207,
144,200,155,188,248,204,105,184,207,142,199,137,175,201,0,159,72,10,5,21,
221,10,120,74,129,124,36,98,232,228,74,81,62,160,20,10,107,186,21,114,32,
105,137,194,70,46,142,68,165,19,235,1,64,170,187,161,119,34,66,146,36,104,
137,194,70,46,142,68,165,19,236,1,64,174,187,161,95,37,134,204,23,225,35,
23,71,34,82,137,246,128,160,89,93,208,167,147,195,201,194,70,46,142,68,165,
19,238,1,64,182,187,161,71,105,20,19,177,139,163,145,41,68,16,7,6,15,82,70,
72,115,96,0,2,234,32,0,0,0,0,91,60,165,195,201,194,8,134,149,216,162,0,192,
41,225,8,2,48,177,36,1,149,13,196,15,0,200,209,97,199,128,99,32,176,195,
192,113,57,143,0,167,133,32,230,80,28,202,139,175,238,2,48,189,192,20,1,
119,80,87,193,186,129,89,56,72,197,209,200,193,185,35,23,71,109,13,219,36,
98,232,237,156,13,26,208,211,14,102,19,87,137,91,95,128,0,10,96,24,92,0,0,
83,2,53,56,0,0,165,3,28,204,160,160,226,100,226,200,211,76,241,240,0,1,102,
8,22,75,64,137,73,20,230,105,133,7,19,39,22,70,154,103,143,128,0,11,48,20,
28,76,156,113,75,34,78,62,0,0,45,3,103,31,0,0,22,65,44,57,137,62,33,179,
216,162,152,192,131,18,124,162,27,61,138,41,108,32,196,159,16,217,232,235,
81,76,104,73,137,62,81,13,158,142,181,20,184,16,98,79,136,108,244,244,168,
166,56,36,196,159,40,134,207,79,74,138,93,10,49,39,194,173,192,158,158,149,
20,188,20,98,79,133,91,129,61,109,74,41,124,30,68,159,16,217,236,83,108,96,
68,137,62,81,13,158,197,54,182,17,34,79,136,108,244,117,169,182,52,38,68,
159,40,134,207,71,90,155,92,8,145,39,196,54,122,122,84,219,28,19,34,79,148,
67,103,167,165,77,174,133,72,147,225,86,224,79,79,74,155,94,10,145,39,194,
173,192,158,182,165,54,190,206,25,212,35,208,226,100,150,211,201,29,162,44,
140,35,103,0,0,3,192,252,0,0,0,0,206,25,228,35,208,226,100,150,211,201,29,
162,44,140,35,103,0,0,3,192,252,0,0,0,0,206,25,244,35,208,226,100,150,211,
201,29,162,44,140,35,103,0,0,3,192,252,0,0,0,0,206,26,4,35,208,226,100,150,
211,201,29,162,44,140,35,103,0,0,0,1,0,0,0,0,0,206,26,20,35,208,226,100,
150,211,201,29,162,44,140,35,103,0,0,0,1,0,0,0,0,0,206,26,36,35,208,226,
100,150,211,201,29,162,44,140,35,103,0,0,0,65,0,0,0,0,0,206,26,52,35,208,
226,100,150,211,201,29,162,44,140,35,103,0,0,0,65,0,0,0,0,0,206,26,68,35,
208,226,100,150,211,201,29,162,44,140,35,103,0,0,0,65,0,0,0,0,0,206,26,84,
35,208,226,100,150,211,201,29,162,44,140,35,103,0,0,0,129,0,0,0,0,0,195,
154,99,16,38,36,0,251,68,117,179,216,162,128,68,72,1,241,13,158,197,20,150,
25,18,0,125,162,58,217,232,235,117,100,162,136,25,18,0,125,162,58,217,232,
235,116,36,162,145,2,226,64,15,136,108,244,117,186,178,81,73,129,113,32,7,
196,54,122,58,221,9,40,165,64,200,144,3,237,17,214,207,79,75,171,37,20,80,
200,144,3,237,17,214,207,79,75,161,37,20,138,23,18,0,124,67,103,167,165,
213,146,138,77,11,137,0,62,33,179,211,210,232,73,69,42,133,196,128,31,10,
183,2,125,89,40,163,5,196,128,31,10,183,2,125,9,40,164,96,200,144,3,224,
221,64,172,157,89,40,163,134,68,128,31,6,234,5,100,232,73,69,35,133,68,128,
31,104,142,182,125,89,40,180,0,168,144,3,237,17,214,207,161,37,22,144,19,
18,0,124,67,103,213,146,139,80,9,137,0,62,33,179,232,73,69,172,5,90,40,153,
59,68,117,179,216,166,192,77,162,137,147,136,108,246,41,180,176,219,69,19,
39,104,142,182,122,58,221,89,41,178,6,218,40,153,59,68,117,179,209,214,232,
73,77,162,6,90,40,153,56,134,207,71,91,171,37,54,152,25,104,162,100,226,27,
61,29,110,132,148,218,160,109,162,137,147,180,71,91,61,61,46,172,148,217,
67,109,20,76,157,162,58,217,233,233,116,36,166,209,67,45,20,76,156,67,103,
167,165,213,146,155,77,12,180,81,50,113,13,158,158,151,66,74,109,84,50,209,
68,201,194,173,192,159,86,74,108,193,150,138,38,78,21,110,4,250,18,83,104,
193,182,138,38,78,13,212,10,201,213,146,155,56,109,162,137,147,131,117,2,
178,116,36,166,209,194,237,20,76,157,162,58,217,245,100,167,16,2,237,20,76,
157,162,58,217,244,36,167,18,2,173,20,76,156,67,103,213,146,156,80,10,180,
81,50,113,13,159,66,74,113,97,175,221,48,216,110,64,4,42,22,189,179,0,196,
133,0,185,80,32,28,78,99,193,18,80,36,4,19,159,141,172,0,178,90,4,74,73,0,
22,209,68,201,187,129,4,2,8,3,132,64,60,36,0,171,240,84,6,149,113,72,176,
157,91,116,116,32,88,181,129,32,11,42,218,221,131,234,219,165,1,8,187,152,
255,188,231,235,248,47,86,227,105,18,2,56,175,185,255,244,17,91,40,110,173,
198,209,208,36,7,188,189,179,240,238,82,97,80,93,122,32,125,144,132,160,12,
22,162,42,7,236,161,25,232,237,105,64,158,160,230,63,205,59,127,102,11,217,
66,51,210,129,61,65,236,127,154,118,254,205,171,197,34,168,48,6,90,194,1,0,
39,75,88,72,8,9,33,186,194,80,64,76,13,214,19,2,130,96,110,150,189,0,65,6,
51,214,20,128,65,17,11,214,19,130,137,121,211,210,211,144,6,39,75,88,80,0,
201,119,235,10,8,41,86,231,71,88,80,129,79,135,186,122,133,224,34,25,69,
234,80,3,91,141,172,40,96,139,113,180,181,133,36,21,110,54,142,134,176,165,
1,176,23,213,47,0,216,134,234,215,128,111,117,181,232,128,209,3,70,230,107,
64,5,139,168,209,235,10,32,36,144,102,235,136,3,146,27,172,40,160,146,132,
103,172,40,192,115,3,117,133,28,22,113,163,69,172,41,103,1,66,188,17,145,
52,168,4,202,113,67,76,130,227,76,194,13,240,108,0,0,83,224,0,2,193,0,104,
146,84,97,48,0,1,94,192,56,169,24,145,179,192,0,5,112,8,56,16,32,128,56,18,
52,125,230,86,147,190,140,28,50,21,13,39,31,23,60,145,158,57,12,141,47,129,
6,155,194,188,24,49,39,199,89,188,124,92,242,70,120,224,201,33,69,15,155,
163,201,68,14,49,39,199,197,211,116,240,242,113,197,232,18,180,254,36,3,17,
46,18,243,35,100,128,172,156,178,70,163,154,76,34,248,146,164,108,248,75,
204,141,146,28,217,115,137,27,95,27,241,173,236,162,160,224,200,2,206,9,
113,13,148,192,209,18,22,164,146,37,193,57,162,4,249,39,196,128,24,2,178,
66,213,136,68,201,16,77,209,131,31,192,242,88,96,92,191,151,34,100,136,38,
232,255,252,92,221,199,197,12,68,209,82,66,212,11,155,185,41,197,13,55,38,
3,66,213,47,135,254,72,12,162,99,133,116,112,0,1,72,66,14,16,16,50,37,202,
160,150,154,66,14,20,8,57,192,28,24,80,113,50,113,100,105,166,120,248,0,0,
179,1,65,196,201,199,20,178,36,227,224,0,2,208,54,113,240,0,1,100,11,181,
192,0,5,178,1,18,160,65,24,131,20,145,25,188,48,132,122,28,76,146,218,121,
35,180,69,145,132,108,224,0,0,120,31,128,0,0,0,25,188,56,132,122,28,76,146,
218,121,35,180,69,145,132,108,224,0,0,120,31,128,0,0,0,40,160,45,110,23,30,
176,33,184,0,0,183,32,29,235,2,27,199,23,0,0,23,4,51,120,129,8,244,56,153,
37,180,242,71,104,139,35,8,217,192,0,0,240,63,0,0,0,0,51,120,145,8,244,56,
153,37,180,242,71,104,139,35,8,217,192,0,0,0,64,0,0,0,0,51,120,161,8,244,
56,153,37,180,242,71,104,139,35,8,217,192,0,0,0,64,0,0,0,0,51,120,177,8,
244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,16,64,0,0,0,0,51,120,193,
8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,16,64,0,0,0,0,51,120,
209,8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,16,64,0,0,0,0,51,
120,225,8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,32,64,0,0,0,0,
32,227,194,0,97,57,162,4,246,104,5,34,92,35,68,225,161,166,220,16,16,137,
112,52,41,73,29,185,1,65,196,201,197,145,166,153,246,72,3,137,204,120,34,
74,8,199,1,67,17,162,112,201,84,128,97,144,78,25,42,16,131,169,1,205,66,8,
35,68,225,161,166,239,128,0,10,192,64,196,104,156,50,96,0,2,172,73,240,117,
96,57,170,97,4,104,156,52,52,221,240,0,1,82,1,74,9,129,125,240,0,1,82,32,
148,25,174,137,58,23,51,190,0,0,42,69,64,195,32,156,50,96,0,2,160,81,238,2,
3,107,173,218,3,192,
};
#else
#error invalid endianness defines
#endif
#endif  /* DUK_USE_ROM_OBJECTS */

/* automatic undefs */
#undef DUK__REFCINIT
#line 1 "duk_error_macros.c"
/*
 *  Error and fatal handling.
 */

/* #include duk_internal.h -> already included */

#define DUK__ERRFMT_BUFSIZE  256  /* size for formatting buffers */

#if defined(DUK_USE_VERBOSE_ERRORS)

DUK_INTERNAL DUK_COLD void duk_err_handle_error_fmt(duk_hthread *thr, const char *filename, duk_uint_t line_and_code, const char *fmt, ...) {
	va_list ap;
	char msg[DUK__ERRFMT_BUFSIZE];
	va_start(ap, fmt);
	(void) DUK_VSNPRINTF(msg, sizeof(msg), fmt, ap);
	msg[sizeof(msg) - 1] = (char) 0;
	duk_err_create_and_throw(thr, (duk_errcode_t) (line_and_code >> 24), msg, filename, (duk_int_t) (line_and_code & 0x00ffffffL));
	va_end(ap);  /* dead code, but ensures portability (see Linux man page notes) */
}

DUK_INTERNAL DUK_COLD void duk_err_handle_error(duk_hthread *thr, const char *filename, duk_uint_t line_and_code, const char *msg) {
	duk_err_create_and_throw(thr, (duk_errcode_t) (line_and_code >> 24), msg, filename, (duk_int_t) (line_and_code & 0x00ffffffL));
}

#else  /* DUK_USE_VERBOSE_ERRORS */

DUK_INTERNAL DUK_COLD void duk_err_handle_error(duk_hthread *thr, duk_errcode_t code) {
	duk_err_create_and_throw(thr, code);
}

#endif  /* DUK_USE_VERBOSE_ERRORS */

/*
 *  Error throwing helpers
 */

#if defined(DUK_USE_VERBOSE_ERRORS)
#if defined(DUK_USE_PARANOID_ERRORS)
DUK_INTERNAL DUK_COLD void duk_err_require_type_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t idx, const char *expect_name) {
	DUK_ERROR_RAW_FMT3(thr, filename, linenumber, DUK_ERR_TYPE_ERROR, "%s required, found %s (stack index %ld)",
	                   expect_name, duk_get_type_name(thr, idx), (long) idx);
}
#else
DUK_INTERNAL DUK_COLD void duk_err_require_type_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t idx, const char *expect_name) {
	DUK_ERROR_RAW_FMT3(thr, filename, linenumber, DUK_ERR_TYPE_ERROR, "%s required, found %s (stack index %ld)",
	                   expect_name, duk_push_string_readable(thr, idx), (long) idx);
}
#endif
DUK_INTERNAL DUK_COLD void duk_err_error_internal(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_ERROR, DUK_STR_INTERNAL_ERROR);
}
DUK_INTERNAL DUK_COLD void duk_err_error_alloc_failed(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_ERROR, DUK_STR_ALLOC_FAILED);
}
DUK_INTERNAL DUK_COLD void duk_err_error(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message) {
	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_ERROR, message);
}
DUK_INTERNAL DUK_COLD void duk_err_range(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message) {
	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_RANGE_ERROR, message);
}
DUK_INTERNAL DUK_COLD void duk_err_range_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t idx) {
	DUK_ERROR_RAW_FMT1(thr, filename, linenumber, DUK_ERR_RANGE_ERROR, "invalid stack index %ld", (long) (idx));
}
DUK_INTERNAL DUK_COLD void duk_err_range_push_beyond(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_RANGE_ERROR, DUK_STR_PUSH_BEYOND_ALLOC_STACK);
}
DUK_INTERNAL DUK_COLD void duk_err_type_invalid_args(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_TYPE_ERROR, DUK_STR_INVALID_ARGS);
}
DUK_INTERNAL DUK_COLD void duk_err_type_invalid_state(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_TYPE_ERROR, DUK_STR_INVALID_STATE);
}
DUK_INTERNAL DUK_COLD void duk_err_type_invalid_trap_result(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_TYPE_ERROR, DUK_STR_INVALID_TRAP_RESULT);
}
#else
/* The file/line arguments are NULL and 0, they're ignored by DUK_ERROR_RAW()
 * when non-verbose errors are used.
 */

DUK_NORETURN(DUK_LOCAL_DECL void duk__err_shared(duk_hthread *thr, duk_errcode_t code));
DUK_LOCAL void duk__err_shared(duk_hthread *thr, duk_errcode_t code) {
	DUK_ERROR_RAW(thr, NULL, 0, code, NULL);
}
DUK_INTERNAL DUK_COLD void duk_err_error(duk_hthread *thr) {
	duk__err_shared(thr, DUK_ERR_ERROR);
}
DUK_INTERNAL DUK_COLD void duk_err_range(duk_hthread *thr) {
	duk__err_shared(thr, DUK_ERR_RANGE_ERROR);
}
DUK_INTERNAL DUK_COLD void duk_err_eval(duk_hthread *thr) {
	duk__err_shared(thr, DUK_ERR_EVAL_ERROR);
}
DUK_INTERNAL DUK_COLD void duk_err_reference(duk_hthread *thr) {
	duk__err_shared(thr, DUK_ERR_REFERENCE_ERROR);
}
DUK_INTERNAL DUK_COLD void duk_err_syntax(duk_hthread *thr) {
	duk__err_shared(thr, DUK_ERR_SYNTAX_ERROR);
}
DUK_INTERNAL DUK_COLD void duk_err_type(duk_hthread *thr) {
	duk__err_shared(thr, DUK_ERR_TYPE_ERROR);
}
DUK_INTERNAL DUK_COLD void duk_err_uri(duk_hthread *thr) {
	duk__err_shared(thr, DUK_ERR_URI_ERROR);
}
#endif

/*
 *  Default fatal error handler
 */

DUK_INTERNAL DUK_COLD void duk_default_fatal_handler(void *udata, const char *msg) {
	DUK_UNREF(udata);
	DUK_UNREF(msg);

	msg = msg ? msg : "NULL";

#if defined(DUK_USE_FATAL_HANDLER)
	/* duk_config.h provided a custom default fatal handler. */
	DUK_D(DUK_DPRINT("custom default fatal error handler called: %s", msg));
	DUK_USE_FATAL_HANDLER(udata, msg);
#elif defined(DUK_USE_CPP_EXCEPTIONS)
	/* With C++ use a duk_fatal_exception which user code can catch in
	 * a natural way.
	 */
	DUK_D(DUK_DPRINT("built-in default C++ fatal error handler called: %s", msg));
	throw duk_fatal_exception(msg);
#else
	/* Default behavior is to abort() on error.  There's no printout
	 * which makes this awkward, so it's always recommended to use an
	 * explicit fatal error handler.
	 *
	 * ====================================================================
	 * NOTE: If you are seeing this, you are most likely dealing with an
	 * uncaught error.  You should provide a fatal error handler in Duktape
	 * heap creation, and should consider using a protected call as your
	 * first call into an empty Duktape context to properly handle errors.
	 * See:
	 *   - http://duktape.org/guide.html#error-handling
	 *   - http://wiki.duktape.org/HowtoFatalErrors.html
	 *   - http://duktape.org/api.html#taglist-protected
	 * ====================================================================
	 */
	DUK_D(DUK_DPRINT("built-in default fatal error handler called: %s", msg));
	DUK_ABORT();
#endif

	DUK_D(DUK_DPRINT("fatal error handler returned, enter forever loop"));
	for (;;) {
		/* Loop forever to ensure we don't return. */
	}
}

/* automatic undefs */
#undef DUK__ERRFMT_BUFSIZE
#line 1 "duk_unicode_support.c"
/*
 *  Various Unicode help functions for character classification predicates,
 *  case conversion, decoding, etc.
 */

/* #include duk_internal.h -> already included */

/*
 *  Fast path tables
 */

#if defined(DUK_USE_IDCHAR_FASTPATH)
DUK_INTERNAL const duk_int8_t duk_is_idchar_tab[128] = {
	/* 0: not IdentifierStart or IdentifierPart
	 * 1: IdentifierStart and IdentifierPart
	 * -1: IdentifierPart only
	 */
	0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   /* 0x00...0x0f */
	0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   /* 0x10...0x1f */
	0,  0,  0,  0,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   /* 0x20...0x2f */
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0,  0,  0,  0,  0,  0,   /* 0x30...0x3f */
	0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,   /* 0x40...0x4f */
	1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  1,   /* 0x50...0x5f */
	0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,   /* 0x60...0x6f */
	1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0    /* 0x70...0x7f */
};
#endif

/*
 *  XUTF-8 and CESU-8 encoding/decoding
 */

DUK_INTERNAL duk_small_int_t duk_unicode_get_xutf8_length(duk_ucodepoint_t cp) {
	duk_uint_fast32_t x = (duk_uint_fast32_t) cp;
	if (x < 0x80UL) {
		/* 7 bits */
		return 1;
	} else if (x < 0x800UL) {
		/* 11 bits */
		return 2;
	} else if (x < 0x10000UL) {
		/* 16 bits */
		return 3;
	} else if (x < 0x200000UL) {
		/* 21 bits */
		return 4;
	} else if (x < 0x4000000UL) {
		/* 26 bits */
		return 5;
	} else if (x < (duk_ucodepoint_t) 0x80000000UL) {
		/* 31 bits */
		return 6;
	} else {
		/* 36 bits */
		return 7;
	}
}

#if defined(DUK_USE_ASSERTIONS)
DUK_INTERNAL duk_small_int_t duk_unicode_get_cesu8_length(duk_ucodepoint_t cp) {
	duk_uint_fast32_t x = (duk_uint_fast32_t) cp;
	if (x < 0x80UL) {
		/* 7 bits */
		return 1;
	} else if (x < 0x800UL) {
		/* 11 bits */
		return 2;
	} else if (x < 0x10000UL) {
		/* 16 bits */
		return 3;
	} else {
		/* Encoded as surrogate pair, each encoding to 3 bytes for
		 * 6 bytes total.  Codepoints above U+10FFFF encode as 6 bytes
		 * too, see duk_unicode_encode_cesu8().
		  */
		return 3 + 3;
	}
}
#endif  /* DUK_USE_ASSERTIONS */

DUK_INTERNAL const duk_uint8_t duk_unicode_xutf8_markers[7] = {
	0x00, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe
};

/* Encode to extended UTF-8; 'out' must have space for at least
 * DUK_UNICODE_MAX_XUTF8_LENGTH bytes.  Allows encoding of any
 * 32-bit (unsigned) codepoint.
 */
DUK_INTERNAL duk_small_int_t duk_unicode_encode_xutf8(duk_ucodepoint_t cp, duk_uint8_t *out) {
	duk_uint_fast32_t x = (duk_uint_fast32_t) cp;
	duk_small_int_t len;
	duk_uint8_t marker;
	duk_small_int_t i;

	len = duk_unicode_get_xutf8_length(cp);
	DUK_ASSERT(len > 0);

	marker = duk_unicode_xutf8_markers[len - 1];  /* 64-bit OK because always >= 0 */

	i = len;
	DUK_ASSERT(i > 0);
	do {
		i--;
		if (i > 0) {
			out[i] = (duk_uint8_t) (0x80 + (x & 0x3f));
			x >>= 6;
		} else {
			/* Note: masking of 'x' is not necessary because of
			 * range check and shifting -> no bits overlapping
			 * the marker should be set.
			 */
			out[0] = (duk_uint8_t) (marker + x);
		}
	} while (i > 0);

	return len;
}

/* Encode to CESU-8; 'out' must have space for at least
 * DUK_UNICODE_MAX_CESU8_LENGTH bytes; codepoints above U+10FFFF
 * will encode to garbage but won't overwrite the output buffer.
 */
DUK_INTERNAL duk_small_int_t duk_unicode_encode_cesu8(duk_ucodepoint_t cp, duk_uint8_t *out) {
	duk_uint_fast32_t x = (duk_uint_fast32_t) cp;
	duk_small_int_t len;

	if (x < 0x80UL) {
		out[0] = (duk_uint8_t) x;
		len = 1;
	} else if (x < 0x800UL) {
		out[0] = (duk_uint8_t) (0xc0 + ((x >> 6) & 0x1f));
		out[1] = (duk_uint8_t) (0x80 + (x & 0x3f));
		len = 2;
	} else if (x < 0x10000UL) {
		/* surrogate pairs get encoded here */
		out[0] = (duk_uint8_t) (0xe0 + ((x >> 12) & 0x0f));
		out[1] = (duk_uint8_t) (0x80 + ((x >> 6) & 0x3f));
		out[2] = (duk_uint8_t) (0x80 + (x & 0x3f));
		len = 3;
	} else {
		/*
		 *  Unicode codepoints above U+FFFF are encoded as surrogate
		 *  pairs here.  This ensures that all CESU-8 codepoints are
		 *  16-bit values as expected in ECMAScript.  The surrogate
		 *  pairs always get a 3-byte encoding (each) in CESU-8.
		 *  See: http://en.wikipedia.org/wiki/Surrogate_pair
		 *
		 *  20-bit codepoint, 10 bits (A and B) per surrogate pair:
		 *
		 *    x = 0b00000000 0000AAAA AAAAAABB BBBBBBBB
		 *  sp1 = 0b110110AA AAAAAAAA  (0xd800 + ((x >> 10) & 0x3ff))
		 *  sp2 = 0b110111BB BBBBBBBB  (0xdc00 + (x & 0x3ff))
		 *
		 *  Encoded into CESU-8:
		 *
		 *  sp1 -> 0b11101101  (0xe0 + ((sp1 >> 12) & 0x0f))
		 *      -> 0b1010AAAA  (0x80 + ((sp1 >> 6) & 0x3f))
		 *      -> 0b10AAAAAA  (0x80 + (sp1 & 0x3f))
		 *  sp2 -> 0b11101101  (0xe0 + ((sp2 >> 12) & 0x0f))
		 *      -> 0b1011BBBB  (0x80 + ((sp2 >> 6) & 0x3f))
		 *      -> 0b10BBBBBB  (0x80 + (sp2 & 0x3f))
		 *
		 *  Note that 0x10000 must be subtracted first.  The code below
		 *  avoids the sp1, sp2 temporaries which saves around 20 bytes
		 *  of code.
		 */

		x -= 0x10000UL;

		out[0] = (duk_uint8_t) (0xed);
		out[1] = (duk_uint8_t) (0xa0 + ((x >> 16) & 0x0f));
		out[2] = (duk_uint8_t) (0x80 + ((x >> 10) & 0x3f));
		out[3] = (duk_uint8_t) (0xed);
		out[4] = (duk_uint8_t) (0xb0 + ((x >> 6) & 0x0f));
		out[5] = (duk_uint8_t) (0x80 + (x & 0x3f));
		len = 6;
	}

	return len;
}

/* Decode helper.  Return zero on error. */
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) {
	const duk_uint8_t *p;
	duk_uint32_t res;
	duk_uint_fast8_t ch;
	duk_small_int_t n;

	DUK_UNREF(thr);

	p = *ptr;
	if (p < ptr_start || p >= ptr_end) {
		goto fail;
	}

	/*
	 *  UTF-8 decoder which accepts longer than standard byte sequences.
	 *  This allows full 32-bit code points to be used.
	 */

	ch = (duk_uint_fast8_t) (*p++);
	if (ch < 0x80) {
		/* 0xxx xxxx   [7 bits] */
		res = (duk_uint32_t) (ch & 0x7f);
		n = 0;
	} else if (ch < 0xc0) {
		/* 10xx xxxx -> invalid */
		goto fail;
	} else if (ch < 0xe0) {
		/* 110x xxxx   10xx xxxx   [11 bits] */
		res = (duk_uint32_t) (ch & 0x1f);
		n = 1;
	} else if (ch < 0xf0) {
		/* 1110 xxxx   10xx xxxx   10xx xxxx   [16 bits] */
		res = (duk_uint32_t) (ch & 0x0f);
		n = 2;
	} else if (ch < 0xf8) {
		/* 1111 0xxx   10xx xxxx   10xx xxxx   10xx xxxx   [21 bits] */
		res = (duk_uint32_t) (ch & 0x07);
		n = 3;
	} else if (ch < 0xfc) {
		/* 1111 10xx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   [26 bits] */
		res = (duk_uint32_t) (ch & 0x03);
		n = 4;
	} else if (ch < 0xfe) {
		/* 1111 110x   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   [31 bits] */
		res = (duk_uint32_t) (ch & 0x01);
		n = 5;
	} else if (ch < 0xff) {
		/* 1111 1110   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   [36 bits] */
		res = (duk_uint32_t) (0);
		n = 6;
	} else {
		/* 8-byte format could be:
		 * 1111 1111   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   [41 bits]
		 *
		 * However, this format would not have a zero bit following the
		 * leading one bits and would not allow 0xFF to be used as an
		 * "invalid xutf-8" marker for internal keys.  Further, 8-byte
		 * encodings (up to 41 bit code points) are not currently needed.
		 */
		goto fail;
	}

	DUK_ASSERT(p >= ptr_start);  /* verified at beginning */
	if (p + n > ptr_end) {
		/* check pointer at end */
		goto fail;
	}

	while (n > 0) {
		DUK_ASSERT(p >= ptr_start && p < ptr_end);
		ch = (duk_uint_fast8_t) (*p++);
#if 0
		if (ch & 0xc0 != 0x80) {
			/* not a continuation byte */
			p--;
			*ptr = p;
			*out_cp = DUK_UNICODE_CP_REPLACEMENT_CHARACTER;
			return 1;
		}
#endif
		res = (res << 6) + (duk_uint32_t) (ch & 0x3f);
		n--;
	}

	*ptr = p;
	*out_cp = res;
	return 1;

 fail:
	return 0;
}

/* used by e.g. duk_regexp_executor.c, string built-ins */
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) {
	duk_ucodepoint_t cp;

	if (duk_unicode_decode_xutf8(thr, ptr, ptr_start, ptr_end, &cp)) {
		return cp;
	}
	DUK_ERROR_INTERNAL(thr);
	DUK_WO_NORETURN(return 0;);
}

/* Compute (extended) utf-8 length without codepoint encoding validation,
 * used for string interning.
 *
 * NOTE: This algorithm is performance critical, more so than string hashing
 * in some cases.  It is needed when interning a string and needs to scan
 * every byte of the string with no skipping.  Having an ASCII fast path
 * is useful if possible in the algorithm.  The current algorithms were
 * chosen from several variants, based on x64 gcc -O2 testing.  See:
 * https://github.com/svaarala/duktape/pull/422
 *
 * NOTE: must match tools/dukutil.py:duk_unicode_unvalidated_utf8_length().
 */

#if defined(DUK_USE_PREFER_SIZE)
/* Small variant; roughly 150 bytes smaller than the fast variant. */
DUK_INTERNAL duk_size_t duk_unicode_unvalidated_utf8_length(const duk_uint8_t *data, duk_size_t blen) {
	const duk_uint8_t *p;
	const duk_uint8_t *p_end;
	duk_size_t ncont;
	duk_size_t clen;

	p = data;
	p_end = data + blen;
	ncont = 0;
	while (p != p_end) {
		duk_uint8_t x;
		x = *p++;
		if (DUK_UNLIKELY(x >= 0x80 && x <= 0xbf)) {
			ncont++;
		}
	}

	DUK_ASSERT(ncont <= blen);
	clen = blen - ncont;
	DUK_ASSERT(clen <= blen);
	return clen;
}
#else  /* DUK_USE_PREFER_SIZE */
/* This seems like a good overall approach.  Fast path for ASCII in 4 byte
 * blocks.
 */
DUK_INTERNAL duk_size_t duk_unicode_unvalidated_utf8_length(const duk_uint8_t *data, duk_size_t blen) {
	const duk_uint8_t *p;
	const duk_uint8_t *p_end;
	const duk_uint32_t *p32_end;
	const duk_uint32_t *p32;
	duk_size_t ncont;
	duk_size_t clen;

	ncont = 0;  /* number of continuation (non-initial) bytes in [0x80,0xbf] */
	p = data;
	p_end = data + blen;
	if (blen < 16) {
		goto skip_fastpath;
	}

	/* Align 'p' to 4; the input data may have arbitrary alignment.
	 * End of string check not needed because blen >= 16.
	 */
	while (((duk_size_t) (const void *) p) & 0x03U) {
		duk_uint8_t x;
		x = *p++;
		if (DUK_UNLIKELY(x >= 0x80 && x <= 0xbf)) {
			ncont++;
		}
	}

	/* Full, aligned 4-byte reads. */
	p32_end = (const duk_uint32_t *) (const void *) (p + ((duk_size_t) (p_end - p) & (duk_size_t) (~0x03)));
	p32 = (const duk_uint32_t *) (const void *) p;
	while (p32 != (const duk_uint32_t *) p32_end) {
		duk_uint32_t x;
		x = *p32++;
		if (DUK_LIKELY((x & 0x80808080UL) == 0)) {
			;  /* ASCII fast path */
		} else {
			/* Flip highest bit of each byte which changes
			 * the bit pattern 10xxxxxx into 00xxxxxx which
			 * allows an easy bit mask test.
			 */
			x ^= 0x80808080UL;
			if (DUK_UNLIKELY(!(x & 0xc0000000UL))) {
				ncont++;
			}
			if (DUK_UNLIKELY(!(x & 0x00c00000UL))) {
				ncont++;
			}
			if (DUK_UNLIKELY(!(x & 0x0000c000UL))) {
				ncont++;
			}
			if (DUK_UNLIKELY(!(x & 0x000000c0UL))) {
				ncont++;
			}
		}
	}
	p = (const duk_uint8_t *) p32;
	/* Fall through to handle the rest. */

 skip_fastpath:
	while (p != p_end) {
		duk_uint8_t x;
		x = *p++;
		if (DUK_UNLIKELY(x >= 0x80 && x <= 0xbf)) {
			ncont++;
		}
	}

	DUK_ASSERT(ncont <= blen);
	clen = blen - ncont;
	DUK_ASSERT(clen <= blen);
	return clen;
}
#endif  /* DUK_USE_PREFER_SIZE */

/* Check whether a string is UTF-8 compatible or not. */
DUK_INTERNAL duk_bool_t duk_unicode_is_utf8_compatible(const duk_uint8_t *buf, duk_size_t len) {
	duk_size_t i = 0;
#if !defined(DUK_USE_PREFER_SIZE)
	duk_size_t len_safe;
#endif

	/* Many practical strings are ASCII only, so use a fast path check
	 * to check chunks of bytes at once with minimal branch cost.
	 */
#if !defined(DUK_USE_PREFER_SIZE)
	len_safe = len & ~0x03UL;
	for (; i < len_safe; i += 4) {
		duk_uint8_t t = buf[i] | buf[i + 1] | buf[i + 2] | buf[i + 3];
		if (DUK_UNLIKELY((t & 0x80U) != 0U)) {
			/* At least one byte was outside 0x00-0x7f, break
			 * out to slow path (and remain there).
			 *
			 * XXX: We could also deal with the problem character
			 * and resume fast path later.
			 */
			break;
		}
	}
#endif

	for (; i < len;) {
		duk_uint8_t t;
		duk_size_t left;
		duk_size_t ncont;
		duk_uint32_t cp;
		duk_uint32_t mincp;

		t = buf[i++];
		if (DUK_LIKELY((t & 0x80U) == 0U)) {
			/* Fast path, ASCII. */
			continue;
		}

		/* Non-ASCII start byte, slow path.
		 *
		 * 10xx xxxx          -> continuation byte
		 * 110x xxxx + 1*CONT -> [0x80, 0x7ff]
		 * 1110 xxxx + 2*CONT -> [0x800, 0xffff], must reject [0xd800,0xdfff]
		 * 1111 0xxx + 3*CONT -> [0x10000, 0x10ffff]
		 */
		left = len - i;
		if (t <= 0xdfU) {  /* 1101 1111 = 0xdf */
			if (t <= 0xbfU) {  /* 1011 1111 = 0xbf */
				return 0;
			}
			ncont = 1;
			mincp = 0x80UL;
			cp = t & 0x1fU;
		} else if (t <= 0xefU) {  /* 1110 1111 = 0xef */
			ncont = 2;
			mincp = 0x800UL;
			cp = t & 0x0fU;
		} else if (t <= 0xf7U) {  /* 1111 0111 = 0xf7 */
			ncont = 3;
			mincp = 0x10000UL;
			cp = t & 0x07U;
		} else {
			return 0;
		}
		if (left < ncont) {
			return 0;
		}
		while (ncont > 0U) {
			t = buf[i++];
			if ((t & 0xc0U) != 0x80U) {  /* 10xx xxxx */
				return 0;
			}
			cp = (cp << 6) + (t & 0x3fU);
			ncont--;
		}
		if (cp < mincp || cp > 0x10ffffUL || (cp >= 0xd800UL && cp <= 0xdfffUL)) {
			return 0;
		}
	}

	return 1;
}

/*
 *  Unicode range matcher
 *
 *  Matches a codepoint against a packed bitstream of character ranges.
 *  Used for slow path Unicode matching.
 */

/* Must match tools/extract_chars.py, generate_match_table3(). */
DUK_LOCAL duk_uint32_t duk__uni_decode_value(duk_bitdecoder_ctx *bd_ctx) {
	duk_uint32_t t;

	t = (duk_uint32_t) duk_bd_decode(bd_ctx, 4);
	if (t <= 0x0eU) {
		return t;
	}
	t = (duk_uint32_t) duk_bd_decode(bd_ctx, 8);
	if (t <= 0xfdU) {
		return t + 0x0f;
	}
	if (t == 0xfeU) {
		t = (duk_uint32_t) duk_bd_decode(bd_ctx, 12);
		return t + 0x0fU + 0xfeU;
	} else {
		t = (duk_uint32_t) duk_bd_decode(bd_ctx, 24);
		return t + 0x0fU + 0xfeU + 0x1000UL;
	}
}

DUK_LOCAL duk_small_int_t duk__uni_range_match(const duk_uint8_t *unitab, duk_size_t unilen, duk_codepoint_t cp) {
	duk_bitdecoder_ctx bd_ctx;
	duk_codepoint_t prev_re;

	duk_memzero(&bd_ctx, sizeof(bd_ctx));
	bd_ctx.data = (const duk_uint8_t *) unitab;
	bd_ctx.length = (duk_size_t) unilen;

	prev_re = 0;
	for (;;) {
		duk_codepoint_t r1, r2;
		r1 = (duk_codepoint_t) duk__uni_decode_value(&bd_ctx);
		if (r1 == 0) {
			break;
		}
		r2 = (duk_codepoint_t) duk__uni_decode_value(&bd_ctx);

		r1 = prev_re + r1;
		r2 = r1 + r2;
		prev_re = r2;

		/* [r1,r2] is the range */

		DUK_DDD(DUK_DDDPRINT("duk__uni_range_match: cp=%06lx range=[0x%06lx,0x%06lx]",
		                     (unsigned long) cp, (unsigned long) r1, (unsigned long) r2));
		if (cp >= r1 && cp <= r2) {
			return 1;
		}
	}

	return 0;
}

/*
 *  "WhiteSpace" production check.
 */

DUK_INTERNAL duk_small_int_t duk_unicode_is_whitespace(duk_codepoint_t cp) {
	/*
	 *  E5 Section 7.2 specifies six characters specifically as
	 *  white space:
	 *
	 *    0009;<control>;Cc;0;S;;;;;N;CHARACTER TABULATION;;;;
	 *    000B;<control>;Cc;0;S;;;;;N;LINE TABULATION;;;;
	 *    000C;<control>;Cc;0;WS;;;;;N;FORM FEED (FF);;;;
	 *    0020;SPACE;Zs;0;WS;;;;;N;;;;;
	 *    00A0;NO-BREAK SPACE;Zs;0;CS;<noBreak> 0020;;;;N;NON-BREAKING SPACE;;;;
	 *    FEFF;ZERO WIDTH NO-BREAK SPACE;Cf;0;BN;;;;;N;BYTE ORDER MARK;;;;
	 *
	 *  It also specifies any Unicode category 'Zs' characters as white
	 *  space.  These can be extracted with the "tools/extract_chars.py" script.
	 *  Current result:
	 *
	 *    RAW OUTPUT:
	 *    ===========
	 *    0020;SPACE;Zs;0;WS;;;;;N;;;;;
	 *    00A0;NO-BREAK SPACE;Zs;0;CS;<noBreak> 0020;;;;N;NON-BREAKING SPACE;;;;
	 *    1680;OGHAM SPACE MARK;Zs;0;WS;;;;;N;;;;;
	 *    180E;MONGOLIAN VOWEL SEPARATOR;Zs;0;WS;;;;;N;;;;;
	 *    2000;EN QUAD;Zs;0;WS;2002;;;;N;;;;;
	 *    2001;EM QUAD;Zs;0;WS;2003;;;;N;;;;;
	 *    2002;EN SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
	 *    2003;EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
	 *    2004;THREE-PER-EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
	 *    2005;FOUR-PER-EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
	 *    2006;SIX-PER-EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
	 *    2007;FIGURE SPACE;Zs;0;WS;<noBreak> 0020;;;;N;;;;;
	 *    2008;PUNCTUATION SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
	 *    2009;THIN SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
	 *    200A;HAIR SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
	 *    202F;NARROW NO-BREAK SPACE;Zs;0;CS;<noBreak> 0020;;;;N;;;;;
	 *    205F;MEDIUM MATHEMATICAL SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
	 *    3000;IDEOGRAPHIC SPACE;Zs;0;WS;<wide> 0020;;;;N;;;;;
	 *
	 *    RANGES:
	 *    =======
	 *    0x0020
	 *    0x00a0
	 *    0x1680
	 *    0x180e
	 *    0x2000 ... 0x200a
	 *    0x202f
	 *    0x205f
	 *    0x3000
	 *
	 *  A manual decoder (below) is probably most compact for this.
	 */

	duk_uint_fast8_t lo;
	duk_uint_fast32_t hi;

	/* cp == -1 (EOF) never matches and causes return value 0 */

	lo = (duk_uint_fast8_t) (cp & 0xff);
	hi = (duk_uint_fast32_t) (cp >> 8);  /* does not fit into an uchar */

	if (hi == 0x0000UL) {
		if (lo == 0x09U || lo == 0x0bU || lo == 0x0cU ||
		    lo == 0x20U || lo == 0xa0U) {
			return 1;
		}
	} else if (hi == 0x0020UL) {
		if (lo <= 0x0aU || lo == 0x2fU || lo == 0x5fU) {
			return 1;
		}
	} else if (cp == 0x1680L || cp == 0x180eL || cp == 0x3000L ||
	           cp == 0xfeffL) {
		return 1;
	}

	return 0;
}

/*
 *  "LineTerminator" production check.
 */

DUK_INTERNAL duk_small_int_t duk_unicode_is_line_terminator(duk_codepoint_t cp) {
	/*
	 *  E5 Section 7.3
	 *
	 *  A LineTerminatorSequence essentially merges <CR> <LF> sequences
	 *  into a single line terminator.  This must be handled by the caller.
	 */

	if (cp == 0x000aL || cp == 0x000dL || cp == 0x2028L ||
	    cp == 0x2029L) {
		return 1;
	}

	return 0;
}

/*
 *  "IdentifierStart" production check.
 */

DUK_INTERNAL duk_small_int_t duk_unicode_is_identifier_start(duk_codepoint_t cp) {
	/*
	 *  E5 Section 7.6:
	 *
	 *    IdentifierStart:
	 *      UnicodeLetter
	 *      $
	 *      _
	 *      \ UnicodeEscapeSequence
	 *
	 *  IdentifierStart production has one multi-character production:
	 *
	 *    \ UnicodeEscapeSequence
	 *
	 *  The '\' character is -not- matched by this function.  Rather, the caller
	 *  should decode the escape and then call this function to check whether the
	 *  decoded character is acceptable (see discussion in E5 Section 7.6).
	 *
	 *  The "UnicodeLetter" alternative of the production allows letters
	 *  from various Unicode categories.  These can be extracted with the
	 *  "tools/extract_chars.py" script.
	 *
	 *  Because the result has hundreds of Unicode codepoint ranges, matching
	 *  for any values >= 0x80 are done using a very slow range-by-range scan
	 *  and a packed range format.
	 *
	 *  The ASCII portion (codepoints 0x00 ... 0x7f) is fast-pathed below because
	 *  it matters the most.  The ASCII related ranges of IdentifierStart are:
	 *
	 *    0x0041 ... 0x005a     ['A' ... 'Z']
	 *    0x0061 ... 0x007a     ['a' ... 'z']
	 *    0x0024                ['$']
	 *    0x005f                ['_']
	 */

	/* ASCII (and EOF) fast path -- quick accept and reject */
	if (cp <= 0x7fL) {
#if defined(DUK_USE_IDCHAR_FASTPATH)
		return (cp >= 0) && (duk_is_idchar_tab[cp] > 0);
#else
		if ((cp >= 'a' && cp <= 'z') ||
		    (cp >= 'A' && cp <= 'Z') ||
		    cp == '_' || cp == '$') {
			return 1;
		}
		return 0;
#endif
	}

	/* Non-ASCII slow path (range-by-range linear comparison), very slow */

#if defined(DUK_USE_SOURCE_NONBMP)
	if (duk__uni_range_match(duk_unicode_ids_noa,
	                         (duk_size_t) sizeof(duk_unicode_ids_noa),
	                         (duk_codepoint_t) cp)) {
		return 1;
	}
	return 0;
#else
	if (cp < 0x10000L) {
		if (duk__uni_range_match(duk_unicode_ids_noabmp,
		                         sizeof(duk_unicode_ids_noabmp),
		                         (duk_codepoint_t) cp)) {
			return 1;
		}
		return 0;
	} else {
		/* without explicit non-BMP support, assume non-BMP characters
		 * are always accepted as identifier characters.
		 */
		return 1;
	}
#endif
}

/*
 *  "IdentifierPart" production check.
 */

DUK_INTERNAL duk_small_int_t duk_unicode_is_identifier_part(duk_codepoint_t cp) {
	/*
	 *  E5 Section 7.6:
	 *
	 *    IdentifierPart:
	 *      IdentifierStart
	 *      UnicodeCombiningMark
	 *      UnicodeDigit
	 *      UnicodeConnectorPunctuation
	 *      <ZWNJ>  [U+200C]
	 *      <ZWJ>   [U+200D]
	 *
	 *  IdentifierPart production has one multi-character production
	 *  as part of its IdentifierStart alternative.  The '\' character
	 *  of an escape sequence is not matched here, see discussion in
	 *  duk_unicode_is_identifier_start().
	 *
	 *  To match non-ASCII characters (codepoints >= 0x80), a very slow
	 *  linear range-by-range scan is used.  The codepoint is first compared
	 *  to the IdentifierStart ranges, and if it doesn't match, then to a
	 *  set consisting of code points in IdentifierPart but not in
	 *  IdentifierStart.  This is done to keep the unicode range data small,
	 *  at the expense of speed.
	 *
	 *  The ASCII fast path consists of:
	 *
	 *    0x0030 ... 0x0039     ['0' ... '9', UnicodeDigit]
	 *    0x0041 ... 0x005a     ['A' ... 'Z', IdentifierStart]
	 *    0x0061 ... 0x007a     ['a' ... 'z', IdentifierStart]
	 *    0x0024                ['$', IdentifierStart]
	 *    0x005f                ['_', IdentifierStart and
	 *                                UnicodeConnectorPunctuation]
	 *
	 *  UnicodeCombiningMark has no code points <= 0x7f.
	 *
	 *  The matching code reuses the "identifier start" tables, and then
	 *  consults a separate range set for characters in "identifier part"
	 *  but not in "identifier start".  These can be extracted with the
	 *  "tools/extract_chars.py" script.
	 *
	 *  UnicodeCombiningMark -> categories Mn, Mc
	 *  UnicodeDigit -> categories Nd
	 *  UnicodeConnectorPunctuation -> categories Pc
	 */

	/* ASCII (and EOF) fast path -- quick accept and reject */
	if (cp <= 0x7fL) {
#if defined(DUK_USE_IDCHAR_FASTPATH)
		return (cp >= 0) && (duk_is_idchar_tab[cp] != 0);
#else
		if ((cp >= 'a' && cp <= 'z') ||
		    (cp >= 'A' && cp <= 'Z') ||
		    (cp >= '0' && cp <= '9') ||
		    cp == '_' || cp == '$') {
			return 1;
		}
		return 0;
#endif
	}

	/* Non-ASCII slow path (range-by-range linear comparison), very slow */

#if defined(DUK_USE_SOURCE_NONBMP)
	if (duk__uni_range_match(duk_unicode_ids_noa,
	                         sizeof(duk_unicode_ids_noa),
	                         (duk_codepoint_t) cp) ||
	    duk__uni_range_match(duk_unicode_idp_m_ids_noa,
	                         sizeof(duk_unicode_idp_m_ids_noa),
	                         (duk_codepoint_t) cp)) {
		return 1;
	}
	return 0;
#else
	if (cp < 0x10000L) {
		if (duk__uni_range_match(duk_unicode_ids_noabmp,
		                         sizeof(duk_unicode_ids_noabmp),
		                         (duk_codepoint_t) cp) ||
		    duk__uni_range_match(duk_unicode_idp_m_ids_noabmp,
		                         sizeof(duk_unicode_idp_m_ids_noabmp),
		                         (duk_codepoint_t) cp)) {
			return 1;
		}
		return 0;
	} else {
		/* without explicit non-BMP support, assume non-BMP characters
		 * are always accepted as identifier characters.
		 */
		return 1;
	}
#endif
}

/*
 *  Unicode letter check.
 */

DUK_INTERNAL duk_small_int_t duk_unicode_is_letter(duk_codepoint_t cp) {
	/*
	 *  Unicode letter is now taken to be the categories:
	 *
	 *    Lu, Ll, Lt, Lm, Lo
	 *
	 *  (Not sure if this is exactly correct.)
	 *
	 *  The ASCII fast path consists of:
	 *
	 *    0x0041 ... 0x005a     ['A' ... 'Z']
	 *    0x0061 ... 0x007a     ['a' ... 'z']
	 */

	/* ASCII (and EOF) fast path -- quick accept and reject */
	if (cp <= 0x7fL) {
		if ((cp >= 'a' && cp <= 'z') ||
		    (cp >= 'A' && cp <= 'Z')) {
			return 1;
		}
		return 0;
	}

	/* Non-ASCII slow path (range-by-range linear comparison), very slow */

#if defined(DUK_USE_SOURCE_NONBMP)
	if (duk__uni_range_match(duk_unicode_ids_noa,
	                         sizeof(duk_unicode_ids_noa),
	                         (duk_codepoint_t) cp) &&
	    !duk__uni_range_match(duk_unicode_ids_m_let_noa,
	                          sizeof(duk_unicode_ids_m_let_noa),
	                          (duk_codepoint_t) cp)) {
		return 1;
	}
	return 0;
#else
	if (cp < 0x10000L) {
		if (duk__uni_range_match(duk_unicode_ids_noabmp,
		                         sizeof(duk_unicode_ids_noabmp),
		                         (duk_codepoint_t) cp) &&
		    !duk__uni_range_match(duk_unicode_ids_m_let_noabmp,
		                          sizeof(duk_unicode_ids_m_let_noabmp),
		                          (duk_codepoint_t) cp)) {
			return 1;
		}
		return 0;
	} else {
		/* without explicit non-BMP support, assume non-BMP characters
		 * are always accepted as letters.
		 */
		return 1;
	}
#endif
}

/*
 *  Complex case conversion helper which decodes a bit-packed conversion
 *  control stream generated by tools/extract_caseconv.py.  The conversion
 *  is very slow because it runs through the conversion data in a linear
 *  fashion to save space (which is why ASCII characters have a special
 *  fast path before arriving here).
 *
 *  The particular bit counts etc have been determined experimentally to
 *  be small but still sufficient, and must match the Python script
 *  (tools/extract_caseconv.py).
 *
 *  The return value is the case converted codepoint or -1 if the conversion
 *  results in multiple characters (this is useful for regexp Canonicalization
 *  operation).  If 'buf' is not NULL, the result codepoint(s) are also
 *  appended to the hbuffer.
 *
 *  Context and locale specific rules must be checked before consulting
 *  this function.
 */

DUK_LOCAL
duk_codepoint_t duk__slow_case_conversion(duk_hthread *thr,
                                          duk_bufwriter_ctx *bw,
                                          duk_codepoint_t cp,
                                          duk_bitdecoder_ctx *bd_ctx) {
	duk_small_int_t skip = 0;
	duk_small_int_t n;
	duk_small_int_t t;
	duk_small_int_t count;
	duk_codepoint_t tmp_cp;
	duk_codepoint_t start_i;
	duk_codepoint_t start_o;

	DUK_ASSERT(bd_ctx != NULL);
	DUK_UNREF(thr);

	DUK_DDD(DUK_DDDPRINT("slow case conversion for codepoint: %ld", (long) cp));

	/* range conversion with a "skip" */
	DUK_DDD(DUK_DDDPRINT("checking ranges"));
	for (;;) {
		skip++;
		n = (duk_small_int_t) duk_bd_decode(bd_ctx, 6);
		if (n == 0x3f) {
			/* end marker */
			break;
		}
		DUK_DDD(DUK_DDDPRINT("skip=%ld, n=%ld", (long) skip, (long) n));

		while (n--) {
			start_i = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
			start_o = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
			count = (duk_small_int_t) duk_bd_decode(bd_ctx, 7);
			DUK_DDD(DUK_DDDPRINT("range: start_i=%ld, start_o=%ld, count=%ld, skip=%ld",
			                     (long) start_i, (long) start_o, (long) count, (long) skip));

			if (cp >= start_i) {
				tmp_cp = cp - start_i;  /* always >= 0 */
				if (tmp_cp < (duk_codepoint_t) count * (duk_codepoint_t) skip &&
				    (tmp_cp % (duk_codepoint_t) skip) == 0) {
					DUK_DDD(DUK_DDDPRINT("range matches input codepoint"));
					cp = start_o + tmp_cp;
					goto single;
				}
			}
		}
	}

	/* 1:1 conversion */
	n = (duk_small_int_t) duk_bd_decode(bd_ctx, 7);
	DUK_DDD(DUK_DDDPRINT("checking 1:1 conversions (count %ld)", (long) n));
	while (n--) {
		start_i = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
		start_o = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
		DUK_DDD(DUK_DDDPRINT("1:1 conversion %ld -> %ld", (long) start_i, (long) start_o));
		if (cp == start_i) {
			DUK_DDD(DUK_DDDPRINT("1:1 matches input codepoint"));
			cp = start_o;
			goto single;
		}
	}

	/* complex, multicharacter conversion */
	n = (duk_small_int_t) duk_bd_decode(bd_ctx, 7);
	DUK_DDD(DUK_DDDPRINT("checking 1:n conversions (count %ld)", (long) n));
	while (n--) {
		start_i = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
		t = (duk_small_int_t) duk_bd_decode(bd_ctx, 2);
		DUK_DDD(DUK_DDDPRINT("1:n conversion %ld -> %ld chars", (long) start_i, (long) t));
		if (cp == start_i) {
			DUK_DDD(DUK_DDDPRINT("1:n matches input codepoint"));
			if (bw != NULL) {
				while (t--) {
					tmp_cp = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
					DUK_BW_WRITE_RAW_XUTF8(thr, bw, (duk_ucodepoint_t) tmp_cp);
				}
			}
			return -1;
		} else {
			while (t--) {
				(void) duk_bd_decode(bd_ctx, 16);
			}
		}
	}

	/* default: no change */
	DUK_DDD(DUK_DDDPRINT("no rule matches, output is same as input"));
	/* fall through */

 single:
	if (bw != NULL) {
		DUK_BW_WRITE_RAW_XUTF8(thr, bw, (duk_ucodepoint_t) cp);
	}
	return cp;
}

/*
 *  Case conversion helper, with context/local sensitivity.
 *  For proper case conversion, one needs to know the character
 *  and the preceding and following characters, as well as
 *  locale/language.
 */

/* XXX: add 'language' argument when locale/language sensitive rule
 * support added.
 */
DUK_LOCAL
duk_codepoint_t 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) {
	duk_bitdecoder_ctx bd_ctx;

	/* fast path for ASCII */
	if (cp < 0x80L) {
		/* XXX: there are language sensitive rules for the ASCII range.
		 * If/when language/locale support is implemented, they need to
		 * be implemented here for the fast path.  There are no context
		 * sensitive rules for ASCII range.
		 */

		if (uppercase) {
			if (cp >= 'a' && cp <= 'z') {
				cp = cp - 'a' + 'A';
			}
		} else {
			if (cp >= 'A' && cp <= 'Z') {
				cp = cp - 'A' + 'a';
			}
		}

		if (bw != NULL) {
			DUK_BW_WRITE_RAW_U8(thr, bw, (duk_uint8_t) cp);
		}
		return cp;
	}

	/* context and locale specific rules which cannot currently be represented
	 * in the caseconv bitstream: hardcoded rules in C
	 */
	if (uppercase) {
		/* XXX: turkish / azeri */
	} else {
		/*
		 *  Final sigma context specific rule.  This is a rather tricky
		 *  rule and this handling is probably not 100% correct now.
		 *  The rule is not locale/language specific so it is supported.
		 */

		if (cp == 0x03a3L &&    /* U+03A3 = GREEK CAPITAL LETTER SIGMA */
		    duk_unicode_is_letter(prev) &&        /* prev exists and is not a letter */
		    !duk_unicode_is_letter(next)) {       /* next does not exist or next is not a letter */
			/* Capital sigma occurred at "end of word", lowercase to
			 * U+03C2 = GREEK SMALL LETTER FINAL SIGMA.  Otherwise
			 * fall through and let the normal rules lowercase it to
			 * U+03C3 = GREEK SMALL LETTER SIGMA.
			 */
			cp = 0x03c2L;
			goto singlechar;
		}

		/* XXX: lithuanian not implemented */
		/* XXX: lithuanian, explicit dot rules */
		/* XXX: turkish / azeri, lowercase rules */
	}

	/* 1:1 or special conversions, but not locale/context specific: script generated rules */
	duk_memzero(&bd_ctx, sizeof(bd_ctx));
	if (uppercase) {
		bd_ctx.data = (const duk_uint8_t *) duk_unicode_caseconv_uc;
		bd_ctx.length = (duk_size_t) sizeof(duk_unicode_caseconv_uc);
	} else {
		bd_ctx.data = (const duk_uint8_t *) duk_unicode_caseconv_lc;
		bd_ctx.length = (duk_size_t) sizeof(duk_unicode_caseconv_lc);
	}
	return duk__slow_case_conversion(thr, bw, cp, &bd_ctx);

 singlechar:
	if (bw != NULL) {
		DUK_BW_WRITE_RAW_XUTF8(thr, bw, (duk_ucodepoint_t) cp);
	}
	return cp;

 /* unused now, not needed until Turkish/Azeri */
#if 0
 nochar:
	return -1;
#endif
}

/*
 *  Replace valstack top with case converted version.
 */

DUK_INTERNAL void duk_unicode_case_convert_string(duk_hthread *thr, duk_bool_t uppercase) {
	duk_hstring *h_input;
	duk_bufwriter_ctx bw_alloc;
	duk_bufwriter_ctx *bw;
	const duk_uint8_t *p, *p_start, *p_end;
	duk_codepoint_t prev, curr, next;

	h_input = duk_require_hstring(thr, -1);  /* Accept symbols. */
	DUK_ASSERT(h_input != NULL);

	bw = &bw_alloc;
	DUK_BW_INIT_PUSHBUF(thr, bw, DUK_HSTRING_GET_BYTELEN(h_input));

	/* [ ... input buffer ] */

	p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
	p = p_start;

	prev = -1; DUK_UNREF(prev);
	curr = -1;
	next = -1;
	for (;;) {
		prev = curr;
		curr = next;
		next = -1;
		if (p < p_end) {
			next = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p, p_start, p_end);
		} else {
			/* end of input and last char has been processed */
			if (curr < 0) {
				break;
			}
		}

		/* on first round, skip */
		if (curr >= 0) {
			/* XXX: could add a fast path to process chunks of input codepoints,
			 * but relative benefit would be quite small.
			 */

			/* Ensure space for maximum multi-character result; estimate is overkill. */
			DUK_BW_ENSURE(thr, bw, 8 * DUK_UNICODE_MAX_XUTF8_LENGTH);

			duk__case_transform_helper(thr,
			                           bw,
			                           (duk_codepoint_t) curr,
			                           prev,
			                           next,
			                           uppercase);
		}
	}

	DUK_BW_COMPACT(thr, bw);
	(void) duk_buffer_to_string(thr, -1);  /* Safe, output is encoded. */
	/* invalidates h_buf pointer */
	duk_remove_m2(thr);
}

#if defined(DUK_USE_REGEXP_SUPPORT)

/*
 *  Canonicalize() abstract operation needed for canonicalization of individual
 *  codepoints during regexp compilation and execution, see E5 Section 15.10.2.8.
 *  Note that codepoints are canonicalized one character at a time, so no context
 *  specific rules can apply.  Locale specific rules can apply, though.
 */

DUK_INTERNAL duk_codepoint_t duk_unicode_re_canonicalize_char(duk_hthread *thr, duk_codepoint_t cp) {
#if defined(DUK_USE_REGEXP_CANON_WORKAROUND)
	/* Fast canonicalization lookup at the cost of 128kB footprint. */
	DUK_ASSERT(cp >= 0);
	DUK_UNREF(thr);
	if (DUK_LIKELY(cp < 0x10000L)) {
		return (duk_codepoint_t) duk_unicode_re_canon_lookup[cp];
	}
	return cp;
#else  /* DUK_USE_REGEXP_CANON_WORKAROUND */
	duk_codepoint_t y;

	y = duk__case_transform_helper(thr,
	                               NULL,    /* NULL is allowed, no output */
	                               cp,      /* curr char */
	                               -1,      /* prev char */
	                               -1,      /* next char */
	                               1);      /* uppercase */

	if ((y < 0) || (cp >= 0x80 && y < 0x80)) {
		/* multiple codepoint conversion or non-ASCII mapped to ASCII
		 * --> leave as is.
		 */
		return cp;
	}

	return y;
#endif  /* DUK_USE_REGEXP_CANON_WORKAROUND */
}

/*
 *  E5 Section 15.10.2.6 "IsWordChar" abstract operation.  Assume
 *  x < 0 for characters read outside the string.
 */

DUK_INTERNAL duk_small_int_t duk_unicode_re_is_wordchar(duk_codepoint_t x) {
	/*
	 *  Note: the description in E5 Section 15.10.2.6 has a typo, it
	 *  contains 'A' twice and lacks 'a'; the intent is [0-9a-zA-Z_].
	 */
	if ((x >= '0' && x <= '9') ||
	    (x >= 'a' && x <= 'z') ||
	    (x >= 'A' && x <= 'Z') ||
	    (x == '_')) {
		return 1;
	}
	return 0;
}

/*
 *  Regexp range tables
 */

/* exposed because lexer needs these too */
DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_digit[2] = {
	(duk_uint16_t) 0x0030UL, (duk_uint16_t) 0x0039UL,
};
DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_white[22] = {
	(duk_uint16_t) 0x0009UL, (duk_uint16_t) 0x000DUL,
	(duk_uint16_t) 0x0020UL, (duk_uint16_t) 0x0020UL,
	(duk_uint16_t) 0x00A0UL, (duk_uint16_t) 0x00A0UL,
	(duk_uint16_t) 0x1680UL, (duk_uint16_t) 0x1680UL,
	(duk_uint16_t) 0x180EUL, (duk_uint16_t) 0x180EUL,
	(duk_uint16_t) 0x2000UL, (duk_uint16_t) 0x200AUL,
	(duk_uint16_t) 0x2028UL, (duk_uint16_t) 0x2029UL,
	(duk_uint16_t) 0x202FUL, (duk_uint16_t) 0x202FUL,
	(duk_uint16_t) 0x205FUL, (duk_uint16_t) 0x205FUL,
	(duk_uint16_t) 0x3000UL, (duk_uint16_t) 0x3000UL,
	(duk_uint16_t) 0xFEFFUL, (duk_uint16_t) 0xFEFFUL,
};
DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_wordchar[8] = {
	(duk_uint16_t) 0x0030UL, (duk_uint16_t) 0x0039UL,
	(duk_uint16_t) 0x0041UL, (duk_uint16_t) 0x005AUL,
	(duk_uint16_t) 0x005FUL, (duk_uint16_t) 0x005FUL,
	(duk_uint16_t) 0x0061UL, (duk_uint16_t) 0x007AUL,
};
DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_not_digit[4] = {
	(duk_uint16_t) 0x0000UL, (duk_uint16_t) 0x002FUL,
	(duk_uint16_t) 0x003AUL, (duk_uint16_t) 0xFFFFUL,
};
DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_not_white[24] = {
	(duk_uint16_t) 0x0000UL, (duk_uint16_t) 0x0008UL,
	(duk_uint16_t) 0x000EUL, (duk_uint16_t) 0x001FUL,
	(duk_uint16_t) 0x0021UL, (duk_uint16_t) 0x009FUL,
	(duk_uint16_t) 0x00A1UL, (duk_uint16_t) 0x167FUL,
	(duk_uint16_t) 0x1681UL, (duk_uint16_t) 0x180DUL,
	(duk_uint16_t) 0x180FUL, (duk_uint16_t) 0x1FFFUL,
	(duk_uint16_t) 0x200BUL, (duk_uint16_t) 0x2027UL,
	(duk_uint16_t) 0x202AUL, (duk_uint16_t) 0x202EUL,
	(duk_uint16_t) 0x2030UL, (duk_uint16_t) 0x205EUL,
	(duk_uint16_t) 0x2060UL, (duk_uint16_t) 0x2FFFUL,
	(duk_uint16_t) 0x3001UL, (duk_uint16_t) 0xFEFEUL,
	(duk_uint16_t) 0xFF00UL, (duk_uint16_t) 0xFFFFUL,
};
DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_not_wordchar[10] = {
	(duk_uint16_t) 0x0000UL, (duk_uint16_t) 0x002FUL,
	(duk_uint16_t) 0x003AUL, (duk_uint16_t) 0x0040UL,
	(duk_uint16_t) 0x005BUL, (duk_uint16_t) 0x005EUL,
	(duk_uint16_t) 0x0060UL, (duk_uint16_t) 0x0060UL,
	(duk_uint16_t) 0x007BUL, (duk_uint16_t) 0xFFFFUL,
};

#endif  /* DUK_USE_REGEXP_SUPPORT */
#line 1 "duk_util_memrw.c"
/*
 *  Macro support functions for reading/writing raw data.
 *
 *  These are done using memcpy to ensure they're valid even for unaligned
 *  reads/writes on platforms where alignment counts.  On x86 at least gcc
 *  is able to compile these into a bswap+mov.  "Always inline" is used to
 *  ensure these macros compile to minimal code.
 */

/* #include duk_internal.h -> already included */

union duk__u16_union {
	duk_uint8_t b[2];
	duk_uint16_t x;
};
typedef union duk__u16_union duk__u16_union;

union duk__u32_union {
	duk_uint8_t b[4];
	duk_uint32_t x;
};
typedef union duk__u32_union duk__u32_union;

#if defined(DUK_USE_64BIT_OPS)
union duk__u64_union {
	duk_uint8_t b[8];
	duk_uint64_t x;
};
typedef union duk__u64_union duk__u64_union;
#endif

DUK_INTERNAL DUK_ALWAYS_INLINE duk_uint16_t duk_raw_read_u16_be(const duk_uint8_t *p) {
	duk__u16_union u;
	duk_memcpy((void *) u.b, (const void *) p, (size_t) 2);
	u.x = DUK_NTOH16(u.x);
	return u.x;
}

DUK_INTERNAL DUK_ALWAYS_INLINE duk_uint32_t duk_raw_read_u32_be(const duk_uint8_t *p) {
	duk__u32_union u;
	duk_memcpy((void *) u.b, (const void *) p, (size_t) 4);
	u.x = DUK_NTOH32(u.x);
	return u.x;
}

DUK_INTERNAL DUK_ALWAYS_INLINE duk_float_t duk_raw_read_float_be(const duk_uint8_t *p) {
	duk_float_union fu;
	duk_memcpy((void *) fu.uc, (const void *) p, (size_t) 4);
	duk_fltunion_big_to_host(&fu);
	return fu.f;
}

DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_raw_read_double_be(const duk_uint8_t *p) {
	duk_double_union du;
	duk_memcpy((void *) du.uc, (const void *) p, (size_t) 8);
	duk_dblunion_big_to_host(&du);
	return du.d;
}

DUK_INTERNAL DUK_ALWAYS_INLINE duk_uint16_t duk_raw_readinc_u16_be(const duk_uint8_t **p) {
	duk_uint16_t res = duk_raw_read_u16_be(*p);
	*p += 2;
	return res;
}

DUK_INTERNAL DUK_ALWAYS_INLINE duk_uint32_t duk_raw_readinc_u32_be(const duk_uint8_t **p) {
	duk_uint32_t res = duk_raw_read_u32_be(*p);
	*p += 4;
	return res;
}

DUK_INTERNAL DUK_ALWAYS_INLINE duk_float_t duk_raw_readinc_float_be(const duk_uint8_t **p) {
	duk_float_t res = duk_raw_read_float_be(*p);
	*p += 4;
	return res;
}

DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_raw_readinc_double_be(const duk_uint8_t **p) {
	duk_double_t res = duk_raw_read_double_be(*p);
	*p += 8;
	return res;
}

DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_u16_be(duk_uint8_t *p, duk_uint16_t val) {
	duk__u16_union u;
	u.x = DUK_HTON16(val);
	duk_memcpy((void *) p, (const void *) u.b, (size_t) 2);
}

DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_u32_be(duk_uint8_t *p, duk_uint32_t val) {
	duk__u32_union u;
	u.x = DUK_HTON32(val);
	duk_memcpy((void *) p, (const void *) u.b, (size_t) 4);
}

DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_float_be(duk_uint8_t *p, duk_float_t val) {
	duk_float_union fu;
	fu.f = val;
	duk_fltunion_host_to_big(&fu);
	duk_memcpy((void *) p, (const void *) fu.uc, (size_t) 4);
}

DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_double_be(duk_uint8_t *p, duk_double_t val) {
	duk_double_union du;
	du.d = val;
	duk_dblunion_host_to_big(&du);
	duk_memcpy((void *) p, (const void *) du.uc, (size_t) 8);
}

DUK_INTERNAL duk_small_int_t duk_raw_write_xutf8(duk_uint8_t *p, duk_ucodepoint_t val) {
	duk_small_int_t len = duk_unicode_encode_xutf8(val, p);
	return len;
}

DUK_INTERNAL duk_small_int_t duk_raw_write_cesu8(duk_uint8_t *p, duk_ucodepoint_t val) {
	duk_small_int_t len = duk_unicode_encode_cesu8(val, p);
	return len;
}

DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_writeinc_u16_be(duk_uint8_t **p, duk_uint16_t val) {
	duk_raw_write_u16_be(*p, val);
	*p += 2;
}

DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_writeinc_u32_be(duk_uint8_t **p, duk_uint32_t val) {
	duk_raw_write_u32_be(*p, val);
	*p += 4;
}

DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_writeinc_float_be(duk_uint8_t **p, duk_float_t val) {
	duk_raw_write_float_be(*p, val);
	*p += 4;
}

DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_writeinc_double_be(duk_uint8_t **p, duk_double_t val) {
	duk_raw_write_double_be(*p, val);
	*p += 8;
}

DUK_INTERNAL void duk_raw_writeinc_xutf8(duk_uint8_t **p, duk_ucodepoint_t val) {
	duk_small_int_t len = duk_unicode_encode_xutf8(val, *p);
	*p += len;
}

DUK_INTERNAL void duk_raw_writeinc_cesu8(duk_uint8_t **p, duk_ucodepoint_t val) {
	duk_small_int_t len = duk_unicode_encode_cesu8(val, *p);
	*p += len;
}
#line 1 "duk_util_misc.c"
/*
 *  Misc util stuff.
 */

/* #include duk_internal.h -> already included */

/*
 *  Lowercase digits for radix values 2 to 36.  Also doubles as lowercase
 *  hex nybble table.
 */

DUK_INTERNAL const duk_uint8_t duk_lc_digits[36] = {
	DUK_ASC_0, DUK_ASC_1, DUK_ASC_2, DUK_ASC_3,
	DUK_ASC_4, DUK_ASC_5, DUK_ASC_6, DUK_ASC_7,
	DUK_ASC_8, DUK_ASC_9, DUK_ASC_LC_A, DUK_ASC_LC_B,
	DUK_ASC_LC_C, DUK_ASC_LC_D, DUK_ASC_LC_E, DUK_ASC_LC_F,
	DUK_ASC_LC_G, DUK_ASC_LC_H, DUK_ASC_LC_I, DUK_ASC_LC_J,
	DUK_ASC_LC_K, DUK_ASC_LC_L, DUK_ASC_LC_M, DUK_ASC_LC_N,
	DUK_ASC_LC_O, DUK_ASC_LC_P, DUK_ASC_LC_Q, DUK_ASC_LC_R,
	DUK_ASC_LC_S, DUK_ASC_LC_T, DUK_ASC_LC_U, DUK_ASC_LC_V,
	DUK_ASC_LC_W, DUK_ASC_LC_X, DUK_ASC_LC_Y, DUK_ASC_LC_Z
};

DUK_INTERNAL const duk_uint8_t duk_uc_nybbles[16] = {
	DUK_ASC_0, DUK_ASC_1, DUK_ASC_2, DUK_ASC_3,
	DUK_ASC_4, DUK_ASC_5, DUK_ASC_6, DUK_ASC_7,
	DUK_ASC_8, DUK_ASC_9, DUK_ASC_UC_A, DUK_ASC_UC_B,
	DUK_ASC_UC_C, DUK_ASC_UC_D, DUK_ASC_UC_E, DUK_ASC_UC_F
};

/*
 *  Table for hex decoding ASCII hex digits
 */

DUK_INTERNAL const duk_int8_t duk_hex_dectab[256] = {
	/* -1 if invalid */
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x00-0x0f */
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x10-0x1f */
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x20-0x2f */
	 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1,  /* 0x30-0x3f */
	-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x40-0x4f */
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x50-0x5f */
	-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x60-0x6f */
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x70-0x7f */
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x80-0x8f */
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x90-0x9f */
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xa0-0xaf */
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xb0-0xbf */
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xc0-0xcf */
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xd0-0xdf */
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xe0-0xef */
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1   /* 0xf0-0xff */
};

#if defined(DUK_USE_HEX_FASTPATH)
/* Preshifted << 4.  Must use 16-bit entry to allow negative value signaling. */
DUK_INTERNAL const duk_int16_t duk_hex_dectab_shift4[256] = {
	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x00-0x0f */
	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x10-0x1f */
	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x20-0x2f */
	0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x30-0x3f */
	  -1, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x40-0x4f */
	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x50-0x5f */
	  -1, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x60-0x6f */
	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x70-0x7f */
	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x80-0x8f */
	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x90-0x9f */
	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0xa0-0xaf */
	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0xb0-0xbf */
	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0xc0-0xcf */
	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0xd0-0xdf */
	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0xe0-0xef */
	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1   /* 0xf0-0xff */
};
#endif

/*
 *  Table for hex encoding bytes
 */

#if defined(DUK_USE_HEX_FASTPATH)
/* Lookup to encode one byte directly into 2 characters:
 *
 *   def genhextab(bswap):
 *       for i in xrange(256):
 *           t = chr(i).encode('hex')
 *           if bswap:
 *               t = t[1] + t[0]
 *           print('0x' + t.encode('hex') + 'U')
 *   print('big endian'); genhextab(False)
 *   print('little endian'); genhextab(True)
*/
DUK_INTERNAL const duk_uint16_t duk_hex_enctab[256] = {
#if defined(DUK_USE_INTEGER_BE)
	0x3030U, 0x3031U, 0x3032U, 0x3033U, 0x3034U, 0x3035U, 0x3036U, 0x3037U,
	0x3038U, 0x3039U, 0x3061U, 0x3062U, 0x3063U, 0x3064U, 0x3065U, 0x3066U,
	0x3130U, 0x3131U, 0x3132U, 0x3133U, 0x3134U, 0x3135U, 0x3136U, 0x3137U,
	0x3138U, 0x3139U, 0x3161U, 0x3162U, 0x3163U, 0x3164U, 0x3165U, 0x3166U,
	0x3230U, 0x3231U, 0x3232U, 0x3233U, 0x3234U, 0x3235U, 0x3236U, 0x3237U,
	0x3238U, 0x3239U, 0x3261U, 0x3262U, 0x3263U, 0x3264U, 0x3265U, 0x3266U,
	0x3330U, 0x3331U, 0x3332U, 0x3333U, 0x3334U, 0x3335U, 0x3336U, 0x3337U,
	0x3338U, 0x3339U, 0x3361U, 0x3362U, 0x3363U, 0x3364U, 0x3365U, 0x3366U,
	0x3430U, 0x3431U, 0x3432U, 0x3433U, 0x3434U, 0x3435U, 0x3436U, 0x3437U,
	0x3438U, 0x3439U, 0x3461U, 0x3462U, 0x3463U, 0x3464U, 0x3465U, 0x3466U,
	0x3530U, 0x3531U, 0x3532U, 0x3533U, 0x3534U, 0x3535U, 0x3536U, 0x3537U,
	0x3538U, 0x3539U, 0x3561U, 0x3562U, 0x3563U, 0x3564U, 0x3565U, 0x3566U,
	0x3630U, 0x3631U, 0x3632U, 0x3633U, 0x3634U, 0x3635U, 0x3636U, 0x3637U,
	0x3638U, 0x3639U, 0x3661U, 0x3662U, 0x3663U, 0x3664U, 0x3665U, 0x3666U,
	0x3730U, 0x3731U, 0x3732U, 0x3733U, 0x3734U, 0x3735U, 0x3736U, 0x3737U,
	0x3738U, 0x3739U, 0x3761U, 0x3762U, 0x3763U, 0x3764U, 0x3765U, 0x3766U,
	0x3830U, 0x3831U, 0x3832U, 0x3833U, 0x3834U, 0x3835U, 0x3836U, 0x3837U,
	0x3838U, 0x3839U, 0x3861U, 0x3862U, 0x3863U, 0x3864U, 0x3865U, 0x3866U,
	0x3930U, 0x3931U, 0x3932U, 0x3933U, 0x3934U, 0x3935U, 0x3936U, 0x3937U,
	0x3938U, 0x3939U, 0x3961U, 0x3962U, 0x3963U, 0x3964U, 0x3965U, 0x3966U,
	0x6130U, 0x6131U, 0x6132U, 0x6133U, 0x6134U, 0x6135U, 0x6136U, 0x6137U,
	0x6138U, 0x6139U, 0x6161U, 0x6162U, 0x6163U, 0x6164U, 0x6165U, 0x6166U,
	0x6230U, 0x6231U, 0x6232U, 0x6233U, 0x6234U, 0x6235U, 0x6236U, 0x6237U,
	0x6238U, 0x6239U, 0x6261U, 0x6262U, 0x6263U, 0x6264U, 0x6265U, 0x6266U,
	0x6330U, 0x6331U, 0x6332U, 0x6333U, 0x6334U, 0x6335U, 0x6336U, 0x6337U,
	0x6338U, 0x6339U, 0x6361U, 0x6362U, 0x6363U, 0x6364U, 0x6365U, 0x6366U,
	0x6430U, 0x6431U, 0x6432U, 0x6433U, 0x6434U, 0x6435U, 0x6436U, 0x6437U,
	0x6438U, 0x6439U, 0x6461U, 0x6462U, 0x6463U, 0x6464U, 0x6465U, 0x6466U,
	0x6530U, 0x6531U, 0x6532U, 0x6533U, 0x6534U, 0x6535U, 0x6536U, 0x6537U,
	0x6538U, 0x6539U, 0x6561U, 0x6562U, 0x6563U, 0x6564U, 0x6565U, 0x6566U,
	0x6630U, 0x6631U, 0x6632U, 0x6633U, 0x6634U, 0x6635U, 0x6636U, 0x6637U,
	0x6638U, 0x6639U, 0x6661U, 0x6662U, 0x6663U, 0x6664U, 0x6665U, 0x6666U
#else  /* DUK_USE_INTEGER_BE */
	0x3030U, 0x3130U, 0x3230U, 0x3330U, 0x3430U, 0x3530U, 0x3630U, 0x3730U,
	0x3830U, 0x3930U, 0x6130U, 0x6230U, 0x6330U, 0x6430U, 0x6530U, 0x6630U,
	0x3031U, 0x3131U, 0x3231U, 0x3331U, 0x3431U, 0x3531U, 0x3631U, 0x3731U,
	0x3831U, 0x3931U, 0x6131U, 0x6231U, 0x6331U, 0x6431U, 0x6531U, 0x6631U,
	0x3032U, 0x3132U, 0x3232U, 0x3332U, 0x3432U, 0x3532U, 0x3632U, 0x3732U,
	0x3832U, 0x3932U, 0x6132U, 0x6232U, 0x6332U, 0x6432U, 0x6532U, 0x6632U,
	0x3033U, 0x3133U, 0x3233U, 0x3333U, 0x3433U, 0x3533U, 0x3633U, 0x3733U,
	0x3833U, 0x3933U, 0x6133U, 0x6233U, 0x6333U, 0x6433U, 0x6533U, 0x6633U,
	0x3034U, 0x3134U, 0x3234U, 0x3334U, 0x3434U, 0x3534U, 0x3634U, 0x3734U,
	0x3834U, 0x3934U, 0x6134U, 0x6234U, 0x6334U, 0x6434U, 0x6534U, 0x6634U,
	0x3035U, 0x3135U, 0x3235U, 0x3335U, 0x3435U, 0x3535U, 0x3635U, 0x3735U,
	0x3835U, 0x3935U, 0x6135U, 0x6235U, 0x6335U, 0x6435U, 0x6535U, 0x6635U,
	0x3036U, 0x3136U, 0x3236U, 0x3336U, 0x3436U, 0x3536U, 0x3636U, 0x3736U,
	0x3836U, 0x3936U, 0x6136U, 0x6236U, 0x6336U, 0x6436U, 0x6536U, 0x6636U,
	0x3037U, 0x3137U, 0x3237U, 0x3337U, 0x3437U, 0x3537U, 0x3637U, 0x3737U,
	0x3837U, 0x3937U, 0x6137U, 0x6237U, 0x6337U, 0x6437U, 0x6537U, 0x6637U,
	0x3038U, 0x3138U, 0x3238U, 0x3338U, 0x3438U, 0x3538U, 0x3638U, 0x3738U,
	0x3838U, 0x3938U, 0x6138U, 0x6238U, 0x6338U, 0x6438U, 0x6538U, 0x6638U,
	0x3039U, 0x3139U, 0x3239U, 0x3339U, 0x3439U, 0x3539U, 0x3639U, 0x3739U,
	0x3839U, 0x3939U, 0x6139U, 0x6239U, 0x6339U, 0x6439U, 0x6539U, 0x6639U,
	0x3061U, 0x3161U, 0x3261U, 0x3361U, 0x3461U, 0x3561U, 0x3661U, 0x3761U,
	0x3861U, 0x3961U, 0x6161U, 0x6261U, 0x6361U, 0x6461U, 0x6561U, 0x6661U,
	0x3062U, 0x3162U, 0x3262U, 0x3362U, 0x3462U, 0x3562U, 0x3662U, 0x3762U,
	0x3862U, 0x3962U, 0x6162U, 0x6262U, 0x6362U, 0x6462U, 0x6562U, 0x6662U,
	0x3063U, 0x3163U, 0x3263U, 0x3363U, 0x3463U, 0x3563U, 0x3663U, 0x3763U,
	0x3863U, 0x3963U, 0x6163U, 0x6263U, 0x6363U, 0x6463U, 0x6563U, 0x6663U,
	0x3064U, 0x3164U, 0x3264U, 0x3364U, 0x3464U, 0x3564U, 0x3664U, 0x3764U,
	0x3864U, 0x3964U, 0x6164U, 0x6264U, 0x6364U, 0x6464U, 0x6564U, 0x6664U,
	0x3065U, 0x3165U, 0x3265U, 0x3365U, 0x3465U, 0x3565U, 0x3665U, 0x3765U,
	0x3865U, 0x3965U, 0x6165U, 0x6265U, 0x6365U, 0x6465U, 0x6565U, 0x6665U,
	0x3066U, 0x3166U, 0x3266U, 0x3366U, 0x3466U, 0x3566U, 0x3666U, 0x3766U,
	0x3866U, 0x3966U, 0x6166U, 0x6266U, 0x6366U, 0x6466U, 0x6566U, 0x6666U
#endif  /* DUK_USE_INTEGER_BE */
};
#endif  /* DUK_USE_HEX_FASTPATH */

/*
 *  Arbitrary byteswap for potentially unaligned values
 *
 *  Used to byteswap pointers e.g. in debugger code.
 */

#if defined(DUK_USE_DEBUGGER_SUPPORT)  /* For now only needed by the debugger. */
DUK_INTERNAL void duk_byteswap_bytes(duk_uint8_t *p, duk_small_uint_t len) {
	duk_uint8_t tmp;
	duk_uint8_t *q = p + len - 1;

	while (p - q < 0) {
		tmp = *p;
		*p = *q;
		*q = tmp;
		p++;
		q--;
	}
}
#endif
#line 1 "duk_hobject_class.c"
/*
 *  Hobject ECMAScript [[Class]].
 */

/* #include duk_internal.h -> already included */

#if (DUK_STRIDX_UC_ARGUMENTS > 255)
#error constant too large
#endif
#if (DUK_STRIDX_UC_ARRAY > 255)
#error constant too large
#endif
#if (DUK_STRIDX_UC_BOOLEAN > 255)
#error constant too large
#endif
#if (DUK_STRIDX_UC_DATE > 255)
#error constant too large
#endif
#if (DUK_STRIDX_UC_ERROR > 255)
#error constant too large
#endif
#if (DUK_STRIDX_UC_FUNCTION > 255)
#error constant too large
#endif
#if (DUK_STRIDX_JSON > 255)
#error constant too large
#endif
#if (DUK_STRIDX_MATH > 255)
#error constant too large
#endif
#if (DUK_STRIDX_UC_NUMBER > 255)
#error constant too large
#endif
#if (DUK_STRIDX_UC_OBJECT > 255)
#error constant too large
#endif
#if (DUK_STRIDX_REG_EXP > 255)
#error constant too large
#endif
#if (DUK_STRIDX_UC_STRING > 255)
#error constant too large
#endif
#if (DUK_STRIDX_GLOBAL > 255)
#error constant too large
#endif
#if (DUK_STRIDX_OBJ_ENV > 255)
#error constant too large
#endif
#if (DUK_STRIDX_DEC_ENV > 255)
#error constant too large
#endif
#if (DUK_STRIDX_UC_POINTER > 255)
#error constant too large
#endif
#if (DUK_STRIDX_UC_THREAD > 255)
#error constant too large
#endif
#if (DUK_STRIDX_ARRAY_BUFFER > 255)
#error constant too large
#endif
#if (DUK_STRIDX_DATA_VIEW > 255)
#error constant too large
#endif
#if (DUK_STRIDX_INT8_ARRAY > 255)
#error constant too large
#endif
#if (DUK_STRIDX_UINT8_ARRAY > 255)
#error constant too large
#endif
#if (DUK_STRIDX_UINT8_CLAMPED_ARRAY > 255)
#error constant too large
#endif
#if (DUK_STRIDX_INT16_ARRAY > 255)
#error constant too large
#endif
#if (DUK_STRIDX_UINT16_ARRAY > 255)
#error constant too large
#endif
#if (DUK_STRIDX_INT32_ARRAY > 255)
#error constant too large
#endif
#if (DUK_STRIDX_UINT32_ARRAY > 255)
#error constant too large
#endif
#if (DUK_STRIDX_FLOAT32_ARRAY > 255)
#error constant too large
#endif
#if (DUK_STRIDX_FLOAT64_ARRAY > 255)
#error constant too large
#endif
#if (DUK_STRIDX_EMPTY_STRING > 255)
#error constant too large
#endif

/* Note: assumes that these string indexes are 8-bit, genstrings.py must ensure that */
DUK_INTERNAL duk_uint8_t duk_class_number_to_stridx[32] = {
	DUK_STRIDX_EMPTY_STRING,  /* NONE, intentionally empty */
	DUK_STRIDX_UC_OBJECT,
	DUK_STRIDX_UC_ARRAY,
	DUK_STRIDX_UC_FUNCTION,
	DUK_STRIDX_UC_ARGUMENTS,
	DUK_STRIDX_UC_BOOLEAN,
	DUK_STRIDX_UC_DATE,
	DUK_STRIDX_UC_ERROR,
	DUK_STRIDX_JSON,
	DUK_STRIDX_MATH,
	DUK_STRIDX_UC_NUMBER,
	DUK_STRIDX_REG_EXP,
	DUK_STRIDX_UC_STRING,
	DUK_STRIDX_GLOBAL,
	DUK_STRIDX_UC_SYMBOL,
	DUK_STRIDX_OBJ_ENV,
	DUK_STRIDX_DEC_ENV,
	DUK_STRIDX_UC_POINTER,
	DUK_STRIDX_UC_THREAD,
	DUK_STRIDX_ARRAY_BUFFER,
	DUK_STRIDX_DATA_VIEW,
	DUK_STRIDX_INT8_ARRAY,
	DUK_STRIDX_UINT8_ARRAY,
	DUK_STRIDX_UINT8_CLAMPED_ARRAY,
	DUK_STRIDX_INT16_ARRAY,
	DUK_STRIDX_UINT16_ARRAY,
	DUK_STRIDX_INT32_ARRAY,
	DUK_STRIDX_UINT32_ARRAY,
	DUK_STRIDX_FLOAT32_ARRAY,
	DUK_STRIDX_FLOAT64_ARRAY,
	DUK_STRIDX_EMPTY_STRING,  /* UNUSED, intentionally empty */
	DUK_STRIDX_EMPTY_STRING,  /* UNUSED, intentionally empty */
};
#line 1 "duk_alloc_default.c"
/*
 *  Default allocation functions.
 *
 *  Assumes behavior such as malloc allowing zero size, yielding
 *  a NULL or a unique pointer which is a no-op for free.
 */

/* #include duk_internal.h -> already included */

#if defined(DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS)
DUK_INTERNAL void *duk_default_alloc_function(void *udata, duk_size_t size) {
	void *res;
	DUK_UNREF(udata);
	res = DUK_ANSI_MALLOC(size);
	DUK_DDD(DUK_DDDPRINT("default alloc function: %lu -> %p",
	                     (unsigned long) size, (void *) res));
	return res;
}

DUK_INTERNAL void *duk_default_realloc_function(void *udata, void *ptr, duk_size_t newsize) {
	void *res;
	DUK_UNREF(udata);
	res = DUK_ANSI_REALLOC(ptr, newsize);
	DUK_DDD(DUK_DDDPRINT("default realloc function: %p %lu -> %p",
	                     (void *) ptr, (unsigned long) newsize, (void *) res));
	return res;
}

DUK_INTERNAL void duk_default_free_function(void *udata, void *ptr) {
	DUK_DDD(DUK_DDDPRINT("default free function: %p", (void *) ptr));
	DUK_UNREF(udata);
	DUK_ANSI_FREE(ptr);
}
#endif  /* DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS */
#line 1 "duk_api_buffer.c"
/*
 *  Buffer
 */

/* #include duk_internal.h -> already included */

DUK_EXTERNAL void *duk_resize_buffer(duk_hthread *thr, duk_idx_t idx, duk_size_t new_size) {
	duk_hbuffer_dynamic *h;

	DUK_ASSERT_API_ENTRY(thr);

	h = (duk_hbuffer_dynamic *) duk_require_hbuffer(thr, idx);
	DUK_ASSERT(h != NULL);

	if (!(DUK_HBUFFER_HAS_DYNAMIC(h) && !DUK_HBUFFER_HAS_EXTERNAL(h))) {
		DUK_ERROR_TYPE(thr, DUK_STR_WRONG_BUFFER_TYPE);
		DUK_WO_NORETURN(return NULL;);
	}

	/* Maximum size check is handled by callee. */
	duk_hbuffer_resize(thr, h, new_size);

	return DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h);
}

DUK_EXTERNAL void *duk_steal_buffer(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size) {
	duk_hbuffer_dynamic *h;
	void *ptr;
	duk_size_t sz;

	DUK_ASSERT_API_ENTRY(thr);

	h = (duk_hbuffer_dynamic *) duk_require_hbuffer(thr, idx);
	DUK_ASSERT(h != NULL);

	if (!(DUK_HBUFFER_HAS_DYNAMIC(h) && !DUK_HBUFFER_HAS_EXTERNAL(h))) {
		DUK_ERROR_TYPE(thr, DUK_STR_WRONG_BUFFER_TYPE);
		DUK_WO_NORETURN(return NULL;);
	}

	/* Forget the previous allocation, setting size to 0 and alloc to
	 * NULL.  Caller is responsible for freeing the previous allocation.
	 * Getting the allocation and clearing it is done in the same API
	 * call to avoid any chance of a realloc.
	 */
	ptr = DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h);
	sz = DUK_HBUFFER_DYNAMIC_GET_SIZE(h);
	if (out_size) {
		*out_size = sz;
	}
	DUK_HBUFFER_DYNAMIC_SET_DATA_PTR_NULL(thr->heap, h);
	DUK_HBUFFER_DYNAMIC_SET_SIZE(h, 0);

	return ptr;
}

DUK_EXTERNAL void duk_config_buffer(duk_hthread *thr, duk_idx_t idx, void *ptr, duk_size_t len) {
	duk_hbuffer_external *h;

	DUK_ASSERT_API_ENTRY(thr);

	h = (duk_hbuffer_external *) duk_require_hbuffer(thr, idx);
	DUK_ASSERT(h != NULL);

	if (!DUK_HBUFFER_HAS_EXTERNAL(h)) {
		DUK_ERROR_TYPE(thr, DUK_STR_WRONG_BUFFER_TYPE);
		DUK_WO_NORETURN(return;);
	}
	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(h));

	DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(thr->heap, h, ptr);
	DUK_HBUFFER_EXTERNAL_SET_SIZE(h, len);
}
#line 1 "duk_api_bytecode.c"
/*
 *  Bytecode dump/load
 *
 *  The bytecode load primitive is more important performance-wise than the
 *  dump primitive.
 *
 *  Unlike most Duktape API calls, bytecode dump/load is not guaranteed to be
 *  memory safe for invalid arguments - caller beware!  There's little point
 *  in trying to achieve memory safety unless bytecode instructions are also
 *  validated which is not easy to do with indirect register references etc.
 */

/* #include duk_internal.h -> already included */

#if defined(DUK_USE_BYTECODE_DUMP_SUPPORT)

#define DUK__SER_MARKER  0xbf
#define DUK__SER_STRING  0x00
#define DUK__SER_NUMBER  0x01
#define DUK__BYTECODE_INITIAL_ALLOC 256
#define DUK__NO_FORMALS  0xffffffffUL

/*
 *  Dump/load helpers, xxx_raw() helpers do no buffer checks
 */

DUK_LOCAL const duk_uint8_t *duk__load_string_raw(duk_hthread *thr, const duk_uint8_t *p) {
	duk_uint32_t len;

	len = DUK_RAW_READINC_U32_BE(p);
	duk_push_lstring(thr, (const char *) p, len);
	p += len;
	return p;
}

DUK_LOCAL const duk_uint8_t *duk__load_buffer_raw(duk_hthread *thr, const duk_uint8_t *p) {
	duk_uint32_t len;
	duk_uint8_t *buf;

	len = DUK_RAW_READINC_U32_BE(p);
	buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, (duk_size_t) len);
	DUK_ASSERT(buf != NULL);
	duk_memcpy((void *) buf, (const void *) p, (size_t) len);
	p += len;
	return p;
}

DUK_LOCAL duk_uint8_t *duk__dump_hstring_raw(duk_uint8_t *p, duk_hstring *h) {
	duk_size_t len;
	duk_uint32_t tmp32;

	DUK_ASSERT(h != NULL);

	len = DUK_HSTRING_GET_BYTELEN(h);
	DUK_ASSERT(len <= 0xffffffffUL);  /* string limits */
	tmp32 = (duk_uint32_t) len;
	DUK_RAW_WRITEINC_U32_BE(p, tmp32);
	duk_memcpy((void *) p,
	           (const void *) DUK_HSTRING_GET_DATA(h),
	           len);
	p += len;
	return p;
}

DUK_LOCAL duk_uint8_t *duk__dump_hbuffer_raw(duk_hthread *thr, duk_uint8_t *p, duk_hbuffer *h) {
	duk_size_t len;
	duk_uint32_t tmp32;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(h != NULL);
	DUK_UNREF(thr);

	len = DUK_HBUFFER_GET_SIZE(h);
	DUK_ASSERT(len <= 0xffffffffUL);  /* buffer limits */
	tmp32 = (duk_uint32_t) len;
	DUK_RAW_WRITEINC_U32_BE(p, tmp32);
	/* When len == 0, buffer data pointer may be NULL. */
	duk_memcpy_unsafe((void *) p,
	                  (const void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h),
	                  len);
	p += len;
	return p;
}

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) {
	duk_hstring *h_str;
	duk_tval *tv;

	tv = duk_hobject_find_entry_tval_ptr_stridx(thr->heap, (duk_hobject *) func, stridx);
	if (tv != NULL && DUK_TVAL_IS_STRING(tv)) {
		h_str = DUK_TVAL_GET_STRING(tv);
		DUK_ASSERT(h_str != NULL);
	} else {
		h_str = DUK_HTHREAD_STRING_EMPTY_STRING(thr);
		DUK_ASSERT(h_str != NULL);
	}
	DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL);  /* ensures no overflow */
	p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U + DUK_HSTRING_GET_BYTELEN(h_str), p);
	p = duk__dump_hstring_raw(p, h_str);
	return p;
}

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) {
	duk_tval *tv;

	tv = duk_hobject_find_entry_tval_ptr_stridx(thr->heap, (duk_hobject *) func, stridx);
	if (tv != NULL && DUK_TVAL_IS_BUFFER(tv)) {
		duk_hbuffer *h_buf;
		h_buf = DUK_TVAL_GET_BUFFER(tv);
		DUK_ASSERT(h_buf != NULL);
		DUK_ASSERT(DUK_HBUFFER_MAX_BYTELEN <= 0x7fffffffUL);  /* ensures no overflow */
		p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U + DUK_HBUFFER_GET_SIZE(h_buf), p);
		p = duk__dump_hbuffer_raw(thr, p, h_buf);
	} else {
		p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U, p);
		DUK_RAW_WRITEINC_U32_BE(p, 0);
	}
	return p;
}

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) {
	duk_tval *tv;
	duk_uint32_t val;

	tv = duk_hobject_find_entry_tval_ptr_stridx(thr->heap, (duk_hobject *) func, stridx);
	if (tv != NULL && DUK_TVAL_IS_NUMBER(tv)) {
		val = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv);
	} else {
		val = def_value;
	}
	p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U, p);
	DUK_RAW_WRITEINC_U32_BE(p, val);
	return p;
}

DUK_LOCAL duk_uint8_t *duk__dump_varmap(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func) {
	duk_hobject *h;

	h = duk_hobject_get_varmap(thr, (duk_hobject *) func);
	if (h != NULL) {
		duk_uint_fast32_t i;

		/* We know _Varmap only has own properties so walk property
		 * table directly.  We also know _Varmap is dense and all
		 * values are numbers; assert for these.  GC and finalizers
		 * shouldn't affect _Varmap so side effects should be fine.
		 */
		for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h); i++) {
			duk_hstring *key;
			duk_tval *tv_val;
			duk_uint32_t val;

			key = DUK_HOBJECT_E_GET_KEY(thr->heap, h, i);
			DUK_ASSERT(key != NULL);  /* _Varmap is dense */
			DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, h, i));
			tv_val = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, h, i);
			DUK_ASSERT(tv_val != NULL);
			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_val));  /* known to be number; in fact an integer */
#if defined(DUK_USE_FASTINT)
			DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv_val));
			DUK_ASSERT(DUK_TVAL_GET_FASTINT(tv_val) == (duk_int64_t) DUK_TVAL_GET_FASTINT_U32(tv_val));  /* known to be 32-bit */
			val = DUK_TVAL_GET_FASTINT_U32(tv_val);
#else
			val = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv_val);
#endif

			DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL);  /* ensures no overflow */
			p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U + DUK_HSTRING_GET_BYTELEN(key) + 4U, p);
			p = duk__dump_hstring_raw(p, key);
			DUK_RAW_WRITEINC_U32_BE(p, val);
		}
	}
	p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U, p);
	DUK_RAW_WRITEINC_U32_BE(p, 0);  /* end of _Varmap */
	return p;
}

DUK_LOCAL duk_uint8_t *duk__dump_formals(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func) {
	duk_harray *h;

	h = duk_hobject_get_formals(thr, (duk_hobject *) func);
	if (h != NULL) {
		duk_uint32_t i;

		/* Here we rely on _Formals being a dense array containing
		 * strings.  This should be the case unless _Formals has been
		 * tweaked by the application (which we don't support right
		 * now).
		 */

		p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U, p);
		DUK_ASSERT(h->length != DUK__NO_FORMALS);  /* limits */
		DUK_RAW_WRITEINC_U32_BE(p, h->length);

		for (i = 0; i < h->length; i++) {
			duk_tval *tv_val;
			duk_hstring *varname;

			tv_val = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, (duk_hobject *) h, i);
			DUK_ASSERT(tv_val != NULL);
			DUK_ASSERT(DUK_TVAL_IS_STRING(tv_val));

			varname = DUK_TVAL_GET_STRING(tv_val);
			DUK_ASSERT(varname != NULL);
			DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(varname) >= 1);

			DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL);  /* ensures no overflow */
			p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U + DUK_HSTRING_GET_BYTELEN(varname), p);
			p = duk__dump_hstring_raw(p, varname);
		}
	} else {
		DUK_DD(DUK_DDPRINT("dumping function without _Formals, emit marker to indicate missing _Formals"));
		p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U, p);
		DUK_RAW_WRITEINC_U32_BE(p, DUK__NO_FORMALS);  /* marker: no formals */
	}
	return p;
}

static duk_uint8_t *duk__dump_func(duk_hthread *thr, duk_hcompfunc *func, duk_bufwriter_ctx *bw_ctx, duk_uint8_t *p) {
	duk_tval *tv, *tv_end;
	duk_instr_t *ins, *ins_end;
	duk_hobject **fn, **fn_end;
	duk_hstring *h_str;
	duk_uint32_t count_instr;
	duk_uint32_t tmp32;
	duk_uint16_t tmp16;
	duk_double_t d;

	DUK_DD(DUK_DDPRINT("dumping function %p to %p: "
	                   "consts=[%p,%p[ (%ld bytes, %ld items), "
	                   "funcs=[%p,%p[ (%ld bytes, %ld items), "
	                   "code=[%p,%p[ (%ld bytes, %ld items)",
	                   (void *) func,
	                   (void *) p,
	                   (void *) DUK_HCOMPFUNC_GET_CONSTS_BASE(thr->heap, func),
	                   (void *) DUK_HCOMPFUNC_GET_CONSTS_END(thr->heap, func),
	                   (long) DUK_HCOMPFUNC_GET_CONSTS_SIZE(thr->heap, func),
	                   (long) DUK_HCOMPFUNC_GET_CONSTS_COUNT(thr->heap, func),
	                   (void *) DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, func),
	                   (void *) DUK_HCOMPFUNC_GET_FUNCS_END(thr->heap, func),
	                   (long) DUK_HCOMPFUNC_GET_FUNCS_SIZE(thr->heap, func),
	                   (long) DUK_HCOMPFUNC_GET_FUNCS_COUNT(thr->heap, func),
	                   (void *) DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, func),
	                   (void *) DUK_HCOMPFUNC_GET_CODE_END(thr->heap, func),
	                   (long) DUK_HCOMPFUNC_GET_CODE_SIZE(thr->heap, func),
	                   (long) DUK_HCOMPFUNC_GET_CODE_COUNT(thr->heap, func)));

	DUK_ASSERT(DUK_USE_ESBC_MAX_BYTES <= 0x7fffffffUL);  /* ensures no overflow */
	count_instr = (duk_uint32_t) DUK_HCOMPFUNC_GET_CODE_COUNT(thr->heap, func);
	p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 3U * 4U + 2U * 2U + 3U * 4U + count_instr * 4U, p);

	/* Fixed header info. */
	tmp32 = count_instr;
	DUK_RAW_WRITEINC_U32_BE(p, tmp32);
	tmp32 = (duk_uint32_t) DUK_HCOMPFUNC_GET_CONSTS_COUNT(thr->heap, func);
	DUK_RAW_WRITEINC_U32_BE(p, tmp32);
	tmp32 = (duk_uint32_t) DUK_HCOMPFUNC_GET_FUNCS_COUNT(thr->heap, func);
	DUK_RAW_WRITEINC_U32_BE(p, tmp32);
	tmp16 = func->nregs;
	DUK_RAW_WRITEINC_U16_BE(p, tmp16);
	tmp16 = func->nargs;
	DUK_RAW_WRITEINC_U16_BE(p, tmp16);
#if defined(DUK_USE_DEBUGGER_SUPPORT)
	tmp32 = func->start_line;
	DUK_RAW_WRITEINC_U32_BE(p, tmp32);
	tmp32 = func->end_line;
	DUK_RAW_WRITEINC_U32_BE(p, tmp32);
#else
	DUK_RAW_WRITEINC_U32_BE(p, 0);
	DUK_RAW_WRITEINC_U32_BE(p, 0);
#endif
	tmp32 = DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) func);  /* masks flags, only duk_hobject flags */
	tmp32 &= ~(DUK_HOBJECT_FLAG_HAVE_FINALIZER);  /* finalizer flag is lost */
	DUK_RAW_WRITEINC_U32_BE(p, tmp32);

	/* Bytecode instructions: endian conversion needed unless
	 * platform is big endian.
	 */
	ins = DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, func);
	ins_end = DUK_HCOMPFUNC_GET_CODE_END(thr->heap, func);
	DUK_ASSERT((duk_size_t) (ins_end - ins) == (duk_size_t) count_instr);
#if defined(DUK_USE_INTEGER_BE)
	duk_memcpy_unsafe((void *) p, (const void *) ins, (size_t) (ins_end - ins));
	p += (size_t) (ins_end - ins);
#else
	while (ins != ins_end) {
		tmp32 = (duk_uint32_t) (*ins);
		DUK_RAW_WRITEINC_U32_BE(p, tmp32);
		ins++;
	}
#endif

	/* Constants: variable size encoding. */
	tv = DUK_HCOMPFUNC_GET_CONSTS_BASE(thr->heap, func);
	tv_end = DUK_HCOMPFUNC_GET_CONSTS_END(thr->heap, func);
	while (tv != tv_end) {
		/* constants are strings or numbers now */
		DUK_ASSERT(DUK_TVAL_IS_STRING(tv) ||
		           DUK_TVAL_IS_NUMBER(tv));

		if (DUK_TVAL_IS_STRING(tv)) {
			h_str = DUK_TVAL_GET_STRING(tv);
			DUK_ASSERT(h_str != NULL);
			DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL);  /* ensures no overflow */
			p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 1U + 4U + DUK_HSTRING_GET_BYTELEN(h_str), p);
			*p++ = DUK__SER_STRING;
			p = duk__dump_hstring_raw(p, h_str);
		} else {
			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
			p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 1U + 8U, p);
			*p++ = DUK__SER_NUMBER;
			d = DUK_TVAL_GET_NUMBER(tv);
			DUK_RAW_WRITEINC_DOUBLE_BE(p, d);
		}
		tv++;
	}

	/* Inner functions recursively. */
	fn = (duk_hobject **) DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, func);
	fn_end = (duk_hobject **) DUK_HCOMPFUNC_GET_FUNCS_END(thr->heap, func);
	while (fn != fn_end) {
		/* XXX: This causes recursion up to inner function depth
		 * which is normally not an issue, e.g. mark-and-sweep uses
		 * a recursion limiter to avoid C stack issues.  Avoiding
		 * this would mean some sort of a work list or just refusing
		 * to serialize deep functions.
		 */
		DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(*fn));
		p = duk__dump_func(thr, (duk_hcompfunc *) *fn, bw_ctx, p);
		fn++;
	}

	/* Lexenv and varenv are not dumped. */

	/* Object extra properties.
	 *
	 * There are some difference between function templates and functions.
	 * For example, function templates don't have .length and nargs is
	 * normally used to instantiate the functions.
	 */

	p = duk__dump_uint32_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_LENGTH, (duk_uint32_t) func->nargs);
#if defined(DUK_USE_FUNC_NAME_PROPERTY)
	p = duk__dump_string_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_NAME);
#endif
#if defined(DUK_USE_FUNC_FILENAME_PROPERTY)
	p = duk__dump_string_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_FILE_NAME);
#endif
#if defined(DUK_USE_PC2LINE)
	p = duk__dump_buffer_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_INT_PC2LINE);
#endif
	p = duk__dump_varmap(thr, p, bw_ctx, (duk_hobject *) func);
	p = duk__dump_formals(thr, p, bw_ctx, (duk_hobject *) func);

	DUK_DD(DUK_DDPRINT("serialized function %p -> final pointer %p", (void *) func, (void *) p));

	return p;
}

/* Load a function from bytecode.  The function object returned here must
 * match what is created by duk_js_push_closure() with respect to its flags,
 * properties, etc.
 *
 * NOTE: there are intentionally no input buffer length / bound checks.
 * Adding them would be easy but wouldn't ensure memory safety as untrusted
 * or broken bytecode is unsafe during execution unless the opcodes themselves
 * are validated (which is quite complex, especially for indirect opcodes).
 */

#define DUK__ASSERT_LEFT(n) do { \
		DUK_ASSERT((duk_size_t) (p_end - p) >= (duk_size_t) (n)); \
	} while (0)

static const duk_uint8_t *duk__load_func(duk_hthread *thr, const duk_uint8_t *p, const duk_uint8_t *p_end) {
	duk_hcompfunc *h_fun;
	duk_hbuffer *h_data;
	duk_size_t data_size;
	duk_uint32_t count_instr, count_const, count_funcs;
	duk_uint32_t n;
	duk_uint32_t tmp32;
	duk_small_uint_t const_type;
	duk_uint8_t *fun_data;
	duk_uint8_t *q;
	duk_idx_t idx_base;
	duk_tval *tv1;
	duk_uarridx_t arr_idx;
	duk_uarridx_t arr_limit;
	duk_hobject *func_env;
	duk_bool_t need_pop;

	/* XXX: There's some overlap with duk_js_closure() here, but
	 * seems difficult to share code.  Ensure that the final function
	 * looks the same as created by duk_js_closure().
	 */

	DUK_ASSERT(thr != NULL);

	DUK_DD(DUK_DDPRINT("loading function, p=%p, p_end=%p", (const void *) p, (const void *) p_end));

	DUK__ASSERT_LEFT(3 * 4);
	count_instr = DUK_RAW_READINC_U32_BE(p);
	count_const = DUK_RAW_READINC_U32_BE(p);
	count_funcs = DUK_RAW_READINC_U32_BE(p);

	data_size = sizeof(duk_tval) * count_const +
	            sizeof(duk_hobject *) * count_funcs +
	            sizeof(duk_instr_t) * count_instr;

	DUK_DD(DUK_DDPRINT("instr=%ld, const=%ld, funcs=%ld, data_size=%ld",
	                   (long) count_instr, (long) count_const,
	                   (long) count_const, (long) data_size));

	/* Value stack is used to ensure reachability of constants and
	 * inner functions being loaded.  Require enough space to handle
	 * large functions correctly.
	 */
	duk_require_stack(thr, (duk_idx_t) (2 + count_const + count_funcs));
	idx_base = duk_get_top(thr);

	/* Push function object, init flags etc.  This must match
	 * duk_js_push_closure() quite carefully.
	 */
	h_fun = duk_push_hcompfunc(thr);
	DUK_ASSERT(h_fun != NULL);
	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) h_fun));
	DUK_ASSERT(DUK_HCOMPFUNC_GET_DATA(thr->heap, h_fun) == NULL);
	DUK_ASSERT(DUK_HCOMPFUNC_GET_FUNCS(thr->heap, h_fun) == NULL);
	DUK_ASSERT(DUK_HCOMPFUNC_GET_BYTECODE(thr->heap, h_fun) == NULL);
	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_fun) == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);

	h_fun->nregs = DUK_RAW_READINC_U16_BE(p);
	h_fun->nargs = DUK_RAW_READINC_U16_BE(p);
#if defined(DUK_USE_DEBUGGER_SUPPORT)
	h_fun->start_line = DUK_RAW_READINC_U32_BE(p);
	h_fun->end_line = DUK_RAW_READINC_U32_BE(p);
#else
	p += 8;  /* skip line info */
#endif

	/* duk_hcompfunc flags; quite version specific */
	tmp32 = DUK_RAW_READINC_U32_BE(p);
	DUK_HEAPHDR_SET_FLAGS((duk_heaphdr *) h_fun, tmp32);  /* masks flags to only change duk_hobject flags */

	/* standard prototype (no need to set here, already set) */
	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_fun) == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
#if 0
	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, &h_fun->obj, thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
#endif

	/* assert just a few critical flags */
	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) h_fun) == DUK_HTYPE_OBJECT);
	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(&h_fun->obj));
	DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(&h_fun->obj));
	DUK_ASSERT(!DUK_HOBJECT_HAS_NATFUNC(&h_fun->obj));
	DUK_ASSERT(!DUK_HOBJECT_IS_THREAD(&h_fun->obj));
	DUK_ASSERT(!DUK_HOBJECT_IS_PROXY(&h_fun->obj));
	DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARRAY(&h_fun->obj));
	DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(&h_fun->obj));
	DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(&h_fun->obj));

	/* Create function 'data' buffer but don't attach it yet. */
	fun_data = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, data_size);
	DUK_ASSERT(fun_data != NULL);

	/* Load bytecode instructions. */
	DUK_ASSERT(sizeof(duk_instr_t) == 4);
	DUK__ASSERT_LEFT(count_instr * sizeof(duk_instr_t));
#if defined(DUK_USE_INTEGER_BE)
	q = fun_data + sizeof(duk_tval) * count_const + sizeof(duk_hobject *) * count_funcs;
	duk_memcpy((void *) q,
	           (const void *) p,
	           sizeof(duk_instr_t) * count_instr);
	p += sizeof(duk_instr_t) * count_instr;
#else
	q = fun_data + sizeof(duk_tval) * count_const + sizeof(duk_hobject *) * count_funcs;
	for (n = count_instr; n > 0; n--) {
		*((duk_instr_t *) (void *) q) = DUK_RAW_READINC_U32_BE(p);
		q += sizeof(duk_instr_t);
	}
#endif

	/* Load constants onto value stack but don't yet copy to buffer. */
	for (n = count_const; n > 0; n--) {
		DUK__ASSERT_LEFT(1);
		const_type = DUK_RAW_READINC_U8(p);
		switch (const_type) {
		case DUK__SER_STRING: {
			p = duk__load_string_raw(thr, p);
			break;
		}
		case DUK__SER_NUMBER: {
			/* Important to do a fastint check so that constants are
			 * properly read back as fastints.
			 */
			duk_tval tv_tmp;
			duk_double_t val;
			DUK__ASSERT_LEFT(8);
			val = DUK_RAW_READINC_DOUBLE_BE(p);
			DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(&tv_tmp, val);
			duk_push_tval(thr, &tv_tmp);
			break;
		}
		default: {
			goto format_error;
		}
		}
	}

	/* Load inner functions to value stack, but don't yet copy to buffer. */
	for (n = count_funcs; n > 0; n--) {
		p = duk__load_func(thr, p, p_end);
		if (p == NULL) {
			goto format_error;
		}
	}

	/* With constants and inner functions on value stack, we can now
	 * atomically finish the function 'data' buffer, bump refcounts,
	 * etc.
	 *
	 * Here we take advantage of the value stack being just a duk_tval
	 * array: we can just memcpy() the constants as long as we incref
	 * them afterwards.
	 */

	h_data = (duk_hbuffer *) duk_known_hbuffer(thr, idx_base + 1);
	DUK_ASSERT(!DUK_HBUFFER_HAS_DYNAMIC(h_data));
	DUK_HCOMPFUNC_SET_DATA(thr->heap, h_fun, h_data);
	DUK_HBUFFER_INCREF(thr, h_data);

	tv1 = duk_get_tval(thr, idx_base + 2);  /* may be NULL if no constants or inner funcs */
	DUK_ASSERT((count_const == 0 && count_funcs == 0) || tv1 != NULL);

	q = fun_data;
	duk_memcpy_unsafe((void *) q, (const void *) tv1, sizeof(duk_tval) * count_const);
	for (n = count_const; n > 0; n--) {
		DUK_TVAL_INCREF_FAST(thr, (duk_tval *) (void *) q);  /* no side effects */
		q += sizeof(duk_tval);
	}
	tv1 += count_const;

	DUK_HCOMPFUNC_SET_FUNCS(thr->heap, h_fun, (duk_hobject **) (void *) q);
	for (n = count_funcs; n > 0; n--) {
		duk_hobject *h_obj;

		DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv1));
		h_obj = DUK_TVAL_GET_OBJECT(tv1);
		DUK_ASSERT(h_obj != NULL);
		tv1++;
		DUK_HOBJECT_INCREF(thr, h_obj);

		*((duk_hobject **) (void *) q) = h_obj;
		q += sizeof(duk_hobject *);
	}

	DUK_HCOMPFUNC_SET_BYTECODE(thr->heap, h_fun, (duk_instr_t *) (void *) q);

	/* The function object is now reachable and refcounts are fine,
	 * so we can pop off all the temporaries.
	 */
	DUK_DDD(DUK_DDDPRINT("function is reachable, reset top; func: %!iT", duk_get_tval(thr, idx_base)));
	duk_set_top(thr, idx_base + 1);

	/* Setup function properties. */
	tmp32 = DUK_RAW_READINC_U32_BE(p);
	duk_push_u32(thr, tmp32);
	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_C);

#if defined(DUK_USE_FUNC_NAME_PROPERTY)
	p = duk__load_string_raw(thr, p);  /* -> [ func funcname ] */
	func_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
	DUK_ASSERT(func_env != NULL);
	need_pop = 0;
	if (DUK_HOBJECT_HAS_NAMEBINDING((duk_hobject *) h_fun)) {
		/* Original function instance/template had NAMEBINDING.
		 * Must create a lexical environment on loading to allow
		 * recursive functions like 'function foo() { foo(); }'.
		 */
		duk_hdecenv *new_env;

		new_env = duk_hdecenv_alloc(thr,
		                            DUK_HOBJECT_FLAG_EXTENSIBLE |
		                            DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV));
		DUK_ASSERT(new_env != NULL);
		DUK_ASSERT(new_env->thread == NULL);  /* Closed. */
		DUK_ASSERT(new_env->varmap == NULL);
		DUK_ASSERT(new_env->regbase_byteoff == 0);
		DUK_HDECENV_ASSERT_VALID(new_env);
		DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) new_env) == NULL);
		DUK_HOBJECT_SET_PROTOTYPE(thr->heap, (duk_hobject *) new_env, func_env);
		DUK_HOBJECT_INCREF(thr, func_env);

		func_env = (duk_hobject *) new_env;

		duk_push_hobject(thr, (duk_hobject *) new_env);

		duk_dup_m2(thr);                                  /* -> [ func funcname env funcname ] */
		duk_dup(thr, idx_base);                           /* -> [ func funcname env funcname func ] */
		duk_xdef_prop(thr, -3, DUK_PROPDESC_FLAGS_NONE);  /* -> [ func funcname env ] */

		need_pop = 1;  /* Need to pop env, but -after- updating h_fun and increfs. */
	}
	DUK_ASSERT(func_env != NULL);
	DUK_HCOMPFUNC_SET_LEXENV(thr->heap, h_fun, func_env);
	DUK_HCOMPFUNC_SET_VARENV(thr->heap, h_fun, func_env);
	DUK_HOBJECT_INCREF(thr, func_env);
	DUK_HOBJECT_INCREF(thr, func_env);
	if (need_pop) {
		duk_pop(thr);
	}
	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_C);
#endif  /* DUK_USE_FUNC_NAME_PROPERTY */

#if defined(DUK_USE_FUNC_FILENAME_PROPERTY)
	p = duk__load_string_raw(thr, p);
	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_FILE_NAME, DUK_PROPDESC_FLAGS_C);
#endif  /* DUK_USE_FUNC_FILENAME_PROPERTY */

	if (DUK_HOBJECT_HAS_CONSTRUCTABLE((duk_hobject *) h_fun)) {
		/* Restore empty external .prototype only for constructable
		 * functions.  The prototype object should inherit from
		 * Object.prototype.
		 */
		duk_push_object(thr);
		DUK_ASSERT(!duk_is_bare_object(thr, -1));
		duk_dup_m2(thr);
		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_CONSTRUCTOR, DUK_PROPDESC_FLAGS_WC);  /* func.prototype.constructor = func */
		duk_compact_m1(thr);
		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_PROTOTYPE, DUK_PROPDESC_FLAGS_W);
	}

#if defined(DUK_USE_PC2LINE)
	p = duk__load_buffer_raw(thr, p);
	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_PC2LINE, DUK_PROPDESC_FLAGS_WC);
#endif  /* DUK_USE_PC2LINE */

	duk_push_bare_object(thr);  /* _Varmap */
	for (;;) {
		/* XXX: awkward */
		p = duk__load_string_raw(thr, p);
		if (duk_get_length(thr, -1) == 0) {
			duk_pop(thr);
			break;
		}
		tmp32 = DUK_RAW_READINC_U32_BE(p);
		duk_push_u32(thr, tmp32);
		duk_put_prop(thr, -3);
	}
	duk_compact_m1(thr);
	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VARMAP, DUK_PROPDESC_FLAGS_NONE);

	/* _Formals may have been missing in the original function, which is
	 * handled using a marker length.
	 */
	arr_limit = DUK_RAW_READINC_U32_BE(p);
	if (arr_limit != DUK__NO_FORMALS) {
		duk_push_bare_array(thr);  /* _Formals */
		for (arr_idx = 0; arr_idx < arr_limit; arr_idx++) {
			p = duk__load_string_raw(thr, p);
			duk_put_prop_index(thr, -2, arr_idx);
		}
		duk_compact_m1(thr);
		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_FORMALS, DUK_PROPDESC_FLAGS_NONE);
	} else {
		DUK_DD(DUK_DDPRINT("no _Formals in dumped function"));
	}

	/* Return with final function pushed on stack top. */
	DUK_DD(DUK_DDPRINT("final loaded function: %!iT", duk_get_tval(thr, -1)));
	DUK_ASSERT_TOP(thr, idx_base + 1);
	return p;

 format_error:
	return NULL;
}

DUK_EXTERNAL void duk_dump_function(duk_hthread *thr) {
	duk_hcompfunc *func;
	duk_bufwriter_ctx bw_ctx_alloc;
	duk_bufwriter_ctx *bw_ctx = &bw_ctx_alloc;
	duk_uint8_t *p;

	DUK_ASSERT_API_ENTRY(thr);

	/* Bound functions don't have all properties so we'd either need to
	 * lookup the non-bound target function or reject bound functions.
	 * For now, bound functions are rejected with TypeError.
	 */
	func = duk_require_hcompfunc(thr, -1);
	DUK_ASSERT(func != NULL);
	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(&func->obj));

	/* Estimating the result size beforehand would be costly, so
	 * start with a reasonable size and extend as needed.
	 */
	DUK_BW_INIT_PUSHBUF(thr, bw_ctx, DUK__BYTECODE_INITIAL_ALLOC);
	p = DUK_BW_GET_PTR(thr, bw_ctx);
	*p++ = DUK__SER_MARKER;
	p = duk__dump_func(thr, func, bw_ctx, p);
	DUK_BW_SET_PTR(thr, bw_ctx, p);
	DUK_BW_COMPACT(thr, bw_ctx);

	DUK_DD(DUK_DDPRINT("serialized result: %!T", duk_get_tval(thr, -1)));

	duk_remove_m2(thr);  /* [ ... func buf ] -> [ ... buf ] */
}

DUK_EXTERNAL void duk_load_function(duk_hthread *thr) {
	const duk_uint8_t *p_buf, *p, *p_end;
	duk_size_t sz;

	DUK_ASSERT_API_ENTRY(thr);

	p_buf = (duk_uint8_t *) duk_require_buffer(thr, -1, &sz);
	DUK_ASSERT(p_buf != NULL);

	/* The caller is responsible for being sure that bytecode being loaded
	 * is valid and trusted.  Invalid bytecode can cause memory unsafe
	 * behavior directly during loading or later during bytecode execution
	 * (instruction validation would be quite complex to implement).
	 *
	 * This signature check is the only sanity check for detecting
	 * accidental invalid inputs.  The initial byte ensures no ordinary
	 * string or Symbol will be accepted by accident.
	 */
	p = p_buf;
	p_end = p_buf + sz;
	if (sz < 1 || p[0] != DUK__SER_MARKER) {
		goto format_error;
	}
	p++;

	p = duk__load_func(thr, p, p_end);
	if (p == NULL) {
		goto format_error;
	}

	duk_remove_m2(thr);  /* [ ... buf func ] -> [ ... func ] */
	return;

 format_error:
	DUK_ERROR_TYPE(thr, DUK_STR_INVALID_BYTECODE);
	DUK_WO_NORETURN(return;);
}

#else  /* DUK_USE_BYTECODE_DUMP_SUPPORT */

DUK_EXTERNAL void duk_dump_function(duk_hthread *thr) {
	DUK_ASSERT_API_ENTRY(thr);
	DUK_ERROR_UNSUPPORTED(thr);
	DUK_WO_NORETURN(return;);
}

DUK_EXTERNAL void duk_load_function(duk_hthread *thr) {
	DUK_ASSERT_API_ENTRY(thr);
	DUK_ERROR_UNSUPPORTED(thr);
	DUK_WO_NORETURN(return;);
}

#endif  /* DUK_USE_BYTECODE_DUMP_SUPPORT */

/* automatic undefs */
#undef DUK__ASSERT_LEFT
#undef DUK__BYTECODE_INITIAL_ALLOC
#undef DUK__NO_FORMALS
#undef DUK__SER_MARKER
#undef DUK__SER_NUMBER
#undef DUK__SER_STRING
#line 1 "duk_api_call.c"
/*
 *  Calls.
 *
 *  Protected variants should avoid ever throwing an error.  Must be careful
 *  to catch errors related to value stack manipulation and property lookup,
 *  not just the call itself.
 *
 *  The only exception is when arguments are insane, e.g. nargs/nrets are out
 *  of bounds; in such cases an error is thrown for two reasons.  First, we
 *  can't always respect the value stack input/output guarantees in such cases
 *  so the caller would end up with the value stack in an unexpected state.
 *  Second, an attempt to create an error might itself fail (although this
 *  could be avoided by pushing a preallocated object/string or a primitive
 *  value).
 */

/* #include duk_internal.h -> already included */

/*
 *  Helpers
 */

struct duk__pcall_prop_args {
	duk_idx_t obj_idx;
	duk_idx_t nargs;
	duk_small_uint_t call_flags;
};
typedef struct duk__pcall_prop_args duk__pcall_prop_args;

struct duk__pcall_method_args {
	duk_idx_t nargs;
	duk_small_uint_t call_flags;
};
typedef struct duk__pcall_method_args duk__pcall_method_args;

struct duk__pcall_args {
	duk_idx_t nargs;
	duk_small_uint_t call_flags;
};
typedef struct duk__pcall_args duk__pcall_args;

/* Compute and validate idx_func for a certain 'nargs' and 'other'
 * parameter count (1 or 2, depending on whether 'this' binding is
 * present).
 */
DUK_LOCAL duk_idx_t duk__call_get_idx_func(duk_hthread *thr, duk_idx_t nargs, duk_idx_t other) {
	duk_idx_t idx_func;

	/* XXX: byte arithmetic? */

	DUK_ASSERT(other >= 0);

	idx_func = duk_get_top(thr) - nargs - other;
	if (DUK_UNLIKELY((idx_func | nargs) < 0)) {  /* idx_func < 0 || nargs < 0; OR sign bits */
		DUK_ERROR_TYPE_INVALID_ARGS(thr);
		DUK_WO_NORETURN(return 0;);
	}
	DUK_ASSERT(duk_is_valid_index(thr, idx_func));
	return idx_func;
}

/* Compute idx_func, assume index will be valid.  This is a valid assumption
 * for protected calls: nargs < 0 is checked explicitly and duk_safe_call()
 * validates the argument count.
 */
DUK_LOCAL duk_idx_t duk__call_get_idx_func_unvalidated(duk_hthread *thr, duk_idx_t nargs, duk_idx_t other) {
	duk_idx_t idx_func;

	/* XXX: byte arithmetic? */

	DUK_ASSERT(nargs >= 0);
	DUK_ASSERT(other >= 0);

	idx_func = duk_get_top(thr) - nargs - other;
	DUK_ASSERT(idx_func >= 0);
	DUK_ASSERT(duk_is_valid_index(thr, idx_func));
	return idx_func;
}

/* Prepare value stack for a method call through an object property.
 * May currently throw an error e.g. when getting the property.
 */
DUK_LOCAL void duk__call_prop_prep_stack(duk_hthread *thr, duk_idx_t normalized_obj_idx, duk_idx_t nargs) {
	DUK_CTX_ASSERT_VALID(thr);
	DUK_ASSERT(nargs >= 0);

	DUK_DDD(DUK_DDDPRINT("duk__call_prop_prep_stack, normalized_obj_idx=%ld, nargs=%ld, stacktop=%ld",
	                     (long) normalized_obj_idx, (long) nargs, (long) duk_get_top(thr)));

	/* [... key arg1 ... argN] */

	/* duplicate key */
	duk_dup(thr, -nargs - 1);  /* Note: -nargs alone would fail for nargs == 0, this is OK */
	(void) duk_get_prop(thr, normalized_obj_idx);

	DUK_DDD(DUK_DDDPRINT("func: %!T", (duk_tval *) duk_get_tval(thr, -1)));

#if defined(DUK_USE_VERBOSE_ERRORS)
	if (DUK_UNLIKELY(!duk_is_callable(thr, -1))) {
		duk_tval *tv_base;
		duk_tval *tv_key;

		/* tv_targ is passed on stack top (at index -1). */
		tv_base = DUK_GET_TVAL_POSIDX(thr, normalized_obj_idx);
		tv_key = DUK_GET_TVAL_NEGIDX(thr, -nargs - 2);
		DUK_ASSERT(tv_base >= thr->valstack_bottom && tv_base < thr->valstack_top);
		DUK_ASSERT(tv_key >= thr->valstack_bottom && tv_key < thr->valstack_top);

		duk_call_setup_propcall_error(thr, tv_base, tv_key);
	}
#endif

	/* [... key arg1 ... argN func] */

	duk_replace(thr, -nargs - 2);

	/* [... func arg1 ... argN] */

	duk_dup(thr, normalized_obj_idx);
	duk_insert(thr, -nargs - 1);

	/* [... func this arg1 ... argN] */
}

DUK_EXTERNAL void duk_call(duk_hthread *thr, duk_idx_t nargs) {
	duk_small_uint_t call_flags;
	duk_idx_t idx_func;

	DUK_ASSERT_API_ENTRY(thr);

	idx_func = duk__call_get_idx_func(thr, nargs, 1);
	DUK_ASSERT(duk_is_valid_index(thr, idx_func));

	duk_insert_undefined(thr, idx_func + 1);

	call_flags = 0;  /* not protected, respect reclimit, not constructor */
	duk_handle_call_unprotected(thr, idx_func, call_flags);
}

DUK_EXTERNAL void duk_call_method(duk_hthread *thr, duk_idx_t nargs) {
	duk_small_uint_t call_flags;
	duk_idx_t idx_func;

	DUK_ASSERT_API_ENTRY(thr);

	idx_func = duk__call_get_idx_func(thr, nargs, 2);
	DUK_ASSERT(duk_is_valid_index(thr, idx_func));

	call_flags = 0;  /* not protected, respect reclimit, not constructor */
	duk_handle_call_unprotected(thr, idx_func, call_flags);
}

DUK_EXTERNAL void duk_call_prop(duk_hthread *thr, duk_idx_t obj_idx, duk_idx_t nargs) {
	/*
	 *  XXX: if duk_handle_call() took values through indices, this could be
	 *  made much more sensible.  However, duk_handle_call() needs to fudge
	 *  the 'this' and 'func' values to handle bound functions, which is now
	 *  done "in-place", so this is not a trivial change.
	 */

	DUK_ASSERT_API_ENTRY(thr);

	obj_idx = duk_require_normalize_index(thr, obj_idx);  /* make absolute */
	if (DUK_UNLIKELY(nargs < 0)) {
		DUK_ERROR_TYPE_INVALID_ARGS(thr);
		DUK_WO_NORETURN(return;);
	}

	duk__call_prop_prep_stack(thr, obj_idx, nargs);

	duk_call_method(thr, nargs);
}

DUK_LOCAL duk_ret_t duk__pcall_raw(duk_hthread *thr, void *udata) {
	duk__pcall_args *args;
	duk_idx_t idx_func;
	duk_int_t ret;

	DUK_CTX_ASSERT_VALID(thr);
	DUK_ASSERT(udata != NULL);

	args = (duk__pcall_args *) udata;
	idx_func = duk__call_get_idx_func_unvalidated(thr, args->nargs, 1);
	DUK_ASSERT(duk_is_valid_index(thr, idx_func));

	duk_insert_undefined(thr, idx_func + 1);

	ret = duk_handle_call_unprotected(thr, idx_func, args->call_flags);
	DUK_ASSERT(ret == 0);
	DUK_UNREF(ret);

	return 1;
}

DUK_EXTERNAL duk_int_t duk_pcall(duk_hthread *thr, duk_idx_t nargs) {
	duk__pcall_args args;

	DUK_ASSERT_API_ENTRY(thr);

	args.nargs = nargs;
	if (DUK_UNLIKELY(nargs < 0)) {
		DUK_ERROR_TYPE_INVALID_ARGS(thr);
		DUK_WO_NORETURN(return DUK_EXEC_ERROR;);
	}
	args.call_flags = 0;

	return duk_safe_call(thr, duk__pcall_raw, (void *) &args /*udata*/, nargs + 1 /*nargs*/, 1 /*nrets*/);
}

DUK_LOCAL duk_ret_t duk__pcall_method_raw(duk_hthread *thr, void *udata) {
	duk__pcall_method_args *args;
	duk_idx_t idx_func;
	duk_int_t ret;

	DUK_CTX_ASSERT_VALID(thr);
	DUK_ASSERT(udata != NULL);

	args = (duk__pcall_method_args *) udata;

	idx_func = duk__call_get_idx_func_unvalidated(thr, args->nargs, 2);
	DUK_ASSERT(duk_is_valid_index(thr, idx_func));

	ret = duk_handle_call_unprotected(thr, idx_func, args->call_flags);
	DUK_ASSERT(ret == 0);
	DUK_UNREF(ret);

	return 1;
}

DUK_INTERNAL duk_int_t duk_pcall_method_flags(duk_hthread *thr, duk_idx_t nargs, duk_small_uint_t call_flags) {
	duk__pcall_method_args args;

	DUK_ASSERT_API_ENTRY(thr);

	args.nargs = nargs;
	if (DUK_UNLIKELY(nargs < 0)) {
		DUK_ERROR_TYPE_INVALID_ARGS(thr);
		DUK_WO_NORETURN(return DUK_EXEC_ERROR;);
	}
	args.call_flags = call_flags;

	return duk_safe_call(thr, duk__pcall_method_raw, (void *) &args /*udata*/, nargs + 2 /*nargs*/, 1 /*nrets*/);
}

DUK_EXTERNAL duk_int_t duk_pcall_method(duk_hthread *thr, duk_idx_t nargs) {
	DUK_ASSERT_API_ENTRY(thr);

	return duk_pcall_method_flags(thr, nargs, 0);
}

DUK_LOCAL duk_ret_t duk__pcall_prop_raw(duk_hthread *thr, void *udata) {
	duk__pcall_prop_args *args;
	duk_idx_t obj_idx;
	duk_int_t ret;

	DUK_CTX_ASSERT_VALID(thr);
	DUK_ASSERT(udata != NULL);

	args = (duk__pcall_prop_args *) udata;

	obj_idx = duk_require_normalize_index(thr, args->obj_idx);  /* make absolute */
	duk__call_prop_prep_stack(thr, obj_idx, args->nargs);

	ret = duk_handle_call_unprotected_nargs(thr, args->nargs, args->call_flags);
	DUK_ASSERT(ret == 0);
	DUK_UNREF(ret);
	return 1;
}

DUK_EXTERNAL duk_int_t duk_pcall_prop(duk_hthread *thr, duk_idx_t obj_idx, duk_idx_t nargs) {
	duk__pcall_prop_args args;

	DUK_ASSERT_API_ENTRY(thr);

	args.obj_idx = obj_idx;
	args.nargs = nargs;
	if (DUK_UNLIKELY(nargs < 0)) {
		DUK_ERROR_TYPE_INVALID_ARGS(thr);
		DUK_WO_NORETURN(return DUK_EXEC_ERROR;);
	}
	args.call_flags = 0;

	return duk_safe_call(thr, duk__pcall_prop_raw, (void *) &args /*udata*/, nargs + 1 /*nargs*/, 1 /*nrets*/);
}

DUK_EXTERNAL duk_int_t duk_safe_call(duk_hthread *thr, duk_safe_call_function func, void *udata, duk_idx_t nargs, duk_idx_t nrets) {
	duk_int_t rc;

	DUK_ASSERT_API_ENTRY(thr);

	/* nargs condition; fail if: top - bottom < nargs
	 *                      <=>  top < bottom + nargs
	 * nrets condition; fail if: end - (top - nargs) < nrets
	 *                      <=>  end - top + nargs < nrets
	 *                      <=>  end + nargs < top + nrets
	 */
	/* XXX: check for any reserve? */

	if (DUK_UNLIKELY((nargs | nrets) < 0 ||  /* nargs < 0 || nrets < 0; OR sign bits */
	                 thr->valstack_top < thr->valstack_bottom + nargs ||        /* nargs too large compared to top */
	                 thr->valstack_end + nargs < thr->valstack_top + nrets)) {  /* nrets too large compared to reserve */
		DUK_D(DUK_DPRINT("not enough stack reserve for safe call or invalid arguments: "
		                 "nargs=%ld < 0 (?), nrets=%ld < 0 (?), top=%ld < bottom=%ld + nargs=%ld (?), "
		                 "end=%ld + nargs=%ld < top=%ld + nrets=%ld (?)",
		                  (long) nargs,
		                  (long) nrets,
		                  (long) (thr->valstack_top - thr->valstack),
		                  (long) (thr->valstack_bottom - thr->valstack),
		                  (long) nargs,
		                  (long) (thr->valstack_end - thr->valstack),
		                  (long) nargs,
		                  (long) (thr->valstack_top - thr->valstack),
		                  (long) nrets));
		DUK_ERROR_TYPE_INVALID_ARGS(thr);
		DUK_WO_NORETURN(return DUK_EXEC_ERROR;);
	}

	rc = duk_handle_safe_call(thr,           /* thread */
	                          func,          /* func */
	                          udata,         /* udata */
	                          nargs,         /* num_stack_args */
	                          nrets);        /* num_stack_res */

	return rc;
}

DUK_EXTERNAL void duk_new(duk_hthread *thr, duk_idx_t nargs) {
	duk_idx_t idx_func;

	DUK_ASSERT_API_ENTRY(thr);

	idx_func = duk__call_get_idx_func(thr, nargs, 1);
	DUK_ASSERT(duk_is_valid_index(thr, idx_func));

	duk_push_object(thr);  /* default instance; internal proto updated by call handling */
	duk_insert(thr, idx_func + 1);

	duk_handle_call_unprotected(thr, idx_func, DUK_CALL_FLAG_CONSTRUCT);
}

DUK_LOCAL duk_ret_t duk__pnew_helper(duk_hthread *thr, void *udata) {
	duk_idx_t nargs;

	DUK_ASSERT(udata != NULL);
	nargs = *((duk_idx_t *) udata);

	duk_new(thr, nargs);
	return 1;
}

DUK_EXTERNAL duk_int_t duk_pnew(duk_hthread *thr, duk_idx_t nargs) {
	duk_int_t rc;

	DUK_ASSERT_API_ENTRY(thr);

	/* For now, just use duk_safe_call() to wrap duk_new().  We can't
	 * simply use a protected duk_handle_call() because pushing the
	 * default instance might throw.
	 */

	if (DUK_UNLIKELY(nargs < 0)) {
		DUK_ERROR_TYPE_INVALID_ARGS(thr);
		DUK_WO_NORETURN(return DUK_EXEC_ERROR;);
	}

	rc = duk_safe_call(thr, duk__pnew_helper, (void *) &nargs /*udata*/, nargs + 1 /*nargs*/, 1 /*nrets*/);
	return rc;
}

DUK_EXTERNAL duk_bool_t duk_is_constructor_call(duk_hthread *thr) {
	duk_activation *act;

	DUK_ASSERT_API_ENTRY(thr);

	act = thr->callstack_curr;
	if (act != NULL) {
		return ((act->flags & DUK_ACT_FLAG_CONSTRUCT) != 0 ? 1 : 0);
	}
	return 0;
}

DUK_EXTERNAL void duk_require_constructor_call(duk_hthread *thr) {
	DUK_ASSERT_API_ENTRY(thr);

	if (!duk_is_constructor_call(thr)) {
		DUK_ERROR_TYPE(thr, DUK_STR_CONSTRUCT_ONLY);
		DUK_WO_NORETURN(return;);
	}
}

DUK_EXTERNAL duk_bool_t duk_is_strict_call(duk_hthread *thr) {
	duk_activation *act;

	/* For user code this could just return 1 (strict) always
	 * because all Duktape/C functions are considered strict,
	 * and strict is also the default when nothing is running.
	 * However, Duktape may call this function internally when
	 * the current activation is an ECMAScript function, so
	 * this cannot be replaced by a 'return 1' without fixing
	 * the internal call sites.
	 */

	DUK_ASSERT_API_ENTRY(thr);

	act = thr->callstack_curr;
	if (act != NULL) {
		return ((act->flags & DUK_ACT_FLAG_STRICT) != 0 ? 1 : 0);
	} else {
		/* Strict by default. */
		return 1;
	}
}

/*
 *  Duktape/C function magic
 */

DUK_EXTERNAL duk_int_t duk_get_current_magic(duk_hthread *thr) {
	duk_activation *act;
	duk_hobject *func;

	DUK_ASSERT_API_ENTRY(thr);

	act = thr->callstack_curr;
	if (act) {
		func = DUK_ACT_GET_FUNC(act);
		if (!func) {
			duk_tval *tv = &act->tv_func;
			duk_small_uint_t lf_flags;
			lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv);
			return (duk_int_t) DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags);
		}
		DUK_ASSERT(func != NULL);

		if (DUK_HOBJECT_IS_NATFUNC(func)) {
			duk_hnatfunc *nf = (duk_hnatfunc *) func;
			return (duk_int_t) nf->magic;
		}
	}
	return 0;
}

DUK_EXTERNAL duk_int_t duk_get_magic(duk_hthread *thr, duk_idx_t idx) {
	duk_tval *tv;
	duk_hobject *h;

	DUK_ASSERT_API_ENTRY(thr);

	tv = duk_require_tval(thr, idx);
	if (DUK_TVAL_IS_OBJECT(tv)) {
		h = DUK_TVAL_GET_OBJECT(tv);
		DUK_ASSERT(h != NULL);
		if (!DUK_HOBJECT_HAS_NATFUNC(h)) {
			goto type_error;
		}
		return (duk_int_t) ((duk_hnatfunc *) h)->magic;
	} else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
		duk_small_uint_t lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv);
		return (duk_int_t) DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags);
	}

	/* fall through */
 type_error:
	DUK_ERROR_TYPE(thr, DUK_STR_UNEXPECTED_TYPE);
	DUK_WO_NORETURN(return 0;);
}

DUK_EXTERNAL void duk_set_magic(duk_hthread *thr, duk_idx_t idx, duk_int_t magic) {
	duk_hnatfunc *nf;

	DUK_ASSERT_API_ENTRY(thr);

	nf = duk_require_hnatfunc(thr, idx);
	DUK_ASSERT(nf != NULL);
	nf->magic = (duk_int16_t) magic;
}

/*
 *  Misc helpers
 */

/* Resolve a bound function on value stack top to a non-bound target
 * (leave other values as is).
 */
DUK_INTERNAL void duk_resolve_nonbound_function(duk_hthread *thr) {
	duk_tval *tv;

	DUK_HTHREAD_ASSERT_VALID(thr);

	tv = DUK_GET_TVAL_NEGIDX(thr, -1);
	if (DUK_TVAL_IS_OBJECT(tv)) {
		duk_hobject *h;

		h = DUK_TVAL_GET_OBJECT(tv);
		DUK_ASSERT(h != NULL);
		if (DUK_HOBJECT_HAS_BOUNDFUNC(h)) {
			duk_push_tval(thr, &((duk_hboundfunc *) (void *) h)->target);
			duk_replace(thr, -2);
#if 0
			DUK_TVAL_SET_TVAL(tv, &((duk_hboundfunc *) h)->target);
			DUK_TVAL_INCREF(thr, tv);
			DUK_HOBJECT_DECREF_NORZ(thr, h);
#endif
			/* Rely on Function.prototype.bind() on never creating a bound
			 * function whose target is not proper.  This is now safe
			 * because the target is not even an internal property but a
			 * struct member.
			 */
			DUK_ASSERT(duk_is_lightfunc(thr, -1) || duk_is_callable(thr, -1));
		}
	}

	/* Lightfuncs cannot be bound but are always callable and
	 * constructable.
	 */
}
#line 1 "duk_api_codec.c"
/*
 *  Encoding and decoding basic formats: hex, base64.
 *
 *  These are in-place operations which may allow an optimized implementation.
 *
 *  Base-64: https://tools.ietf.org/html/rfc4648#section-4
 */

/* #include duk_internal.h -> already included */

/*
 *  Misc helpers
 */

/* Shared handling for encode/decode argument.  Fast path handling for
 * buffer and string values because they're the most common.  In particular,
 * avoid creating a temporary string or buffer when possible.  Return value
 * is guaranteed to be non-NULL, even for zero length input.
 */
DUK_LOCAL const duk_uint8_t *duk__prep_codec_arg(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len) {
	const void *def_ptr = (const void *) out_len;  /* Any non-NULL pointer will do. */
	const void *ptr;
	duk_bool_t isbuffer;

	DUK_ASSERT(out_len != NULL);
	DUK_ASSERT(def_ptr != NULL);
	DUK_ASSERT(duk_is_valid_index(thr, idx));  /* checked by caller */

	ptr = (const void *) duk_get_buffer_data_raw(thr, idx, out_len, NULL /*def_ptr*/, 0 /*def_size*/, 0 /*throw_flag*/, &isbuffer);
	if (isbuffer) {
		DUK_ASSERT(ptr != NULL || *out_len == 0U);
		if (DUK_UNLIKELY(ptr == NULL)) {
			ptr = def_ptr;
		}
		DUK_ASSERT(ptr != NULL);
	} else {
		/* For strings a non-NULL pointer is always guaranteed because
		 * at least a NUL will be present.
		 */
		ptr = (const void *) duk_to_lstring(thr, idx, out_len);
		DUK_ASSERT(ptr != NULL);
	}
	DUK_ASSERT(ptr != NULL);
	return (const duk_uint8_t *) ptr;
}

/*
 *  Base64
 */

#if defined(DUK_USE_BASE64_SUPPORT)
/* Bytes emitted for number of padding characters in range [0,4]. */
DUK_LOCAL const duk_int8_t duk__base64_decode_nequal_step[5] = {
	3,   /* #### -> 24 bits, emit 3 bytes */
	2,   /* ###= -> 18 bits, emit 2 bytes */
	1,   /* ##== -> 12 bits, emit 1 byte */
	-1,  /* #=== -> 6 bits, error */
	0,   /* ==== -> 0 bits, emit 0 bytes */
};

#if defined(DUK_USE_BASE64_FASTPATH)
DUK_LOCAL const duk_uint8_t duk__base64_enctab_fast[64] = {
	0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U, 0x48U, 0x49U, 0x4aU, 0x4bU, 0x4cU, 0x4dU, 0x4eU, 0x4fU, 0x50U,  /* A...P */
	0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U, 0x58U, 0x59U, 0x5aU, 0x61U, 0x62U, 0x63U, 0x64U, 0x65U, 0x66U,  /* Q...f */
	0x67U, 0x68U, 0x69U, 0x6aU, 0x6bU, 0x6cU, 0x6dU, 0x6eU, 0x6fU, 0x70U, 0x71U, 0x72U, 0x73U, 0x74U, 0x75U, 0x76U,  /* g...v */
	0x77U, 0x78U, 0x79U, 0x7aU, 0x30U, 0x31U, 0x32U, 0x33U, 0x34U, 0x35U, 0x36U, 0x37U, 0x38U, 0x39U, 0x2bU, 0x2fU   /* w.../ */
};
#endif  /* DUK_USE_BASE64_FASTPATH */

#if defined(DUK_USE_BASE64_FASTPATH)
/* Decode table for one byte of input:
 *   -1 = allowed whitespace
 *   -2 = padding
 *   -3 = error
 *    0...63 decoded bytes
 */
DUK_LOCAL const duk_int8_t duk__base64_dectab_fast[256] = {
	-3, -3, -3, -3, -3, -3, -3, -3, -3, -1, -1, -3, -3, -1, -3, -3,  /* 0x00...0x0f */
	-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,  /* 0x10...0x1f */
	-1, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, 62, -3, -3, -3, 63,  /* 0x20...0x2f */
	52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -3, -3, -3, -2, -3, -3,  /* 0x30...0x3f */
	-3,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,  /* 0x40...0x4f */
	15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -3, -3, -3, -3, -3,  /* 0x50...0x5f */
	-3, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,  /* 0x60...0x6f */
	41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -3, -3, -3, -3, -3,  /* 0x70...0x7f */
	-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,  /* 0x80...0x8f */
	-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,  /* 0x90...0x9f */
	-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,  /* 0xa0...0xaf */
	-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,  /* 0xb0...0xbf */
	-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,  /* 0xc0...0xcf */
	-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,  /* 0xd0...0xdf */
	-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,  /* 0xe0...0xef */
	-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3   /* 0xf0...0xff */
};
#endif  /* DUK_USE_BASE64_FASTPATH */

#if defined(DUK_USE_BASE64_FASTPATH)
DUK_LOCAL DUK_ALWAYS_INLINE void duk__base64_encode_fast_3(const duk_uint8_t *src, duk_uint8_t *dst) {
	duk_uint_t t;

	t = (duk_uint_t) src[0];
	t = (t << 8) + (duk_uint_t) src[1];
	t = (t << 8) + (duk_uint_t) src[2];

	dst[0] = duk__base64_enctab_fast[t >> 18];
	dst[1] = duk__base64_enctab_fast[(t >> 12) & 0x3fU];
	dst[2] = duk__base64_enctab_fast[(t >> 6) & 0x3fU];
	dst[3] = duk__base64_enctab_fast[t & 0x3fU];

#if 0
	/* Tested: not faster on x64, most likely due to aliasing between
	 * output and input index computation.
	 */
	/* aaaaaabb bbbbcccc ccdddddd */
	dst[0] = duk__base64_enctab_fast[(src[0] >> 2) & 0x3fU];
	dst[1] = duk__base64_enctab_fast[((src[0] << 4) & 0x30U) | ((src[1] >> 4) & 0x0fU)];
	dst[2] = duk__base64_enctab_fast[((src[1] << 2) & 0x3fU) | ((src[2] >> 6) & 0x03U)];
	dst[3] = duk__base64_enctab_fast[src[2] & 0x3fU];
#endif
}

DUK_LOCAL DUK_ALWAYS_INLINE void duk__base64_encode_fast_2(const duk_uint8_t *src, duk_uint8_t *dst) {
	duk_uint_t t;

	t = (duk_uint_t) src[0];
	t = (t << 8) + (duk_uint_t) src[1];
	dst[0] = duk__base64_enctab_fast[t >> 10];           /* XXXXXX-- -------- */
	dst[1] = duk__base64_enctab_fast[(t >> 4) & 0x3fU];  /* ------XX XXXX---- */
	dst[2] = duk__base64_enctab_fast[(t << 2) & 0x3fU];  /* -------- ----XXXX */
	dst[3] = DUK_ASC_EQUALS;
}

DUK_LOCAL DUK_ALWAYS_INLINE void duk__base64_encode_fast_1(const duk_uint8_t *src, duk_uint8_t *dst) {
	duk_uint_t t;

	t = (duk_uint_t) src[0];
	dst[0] = duk__base64_enctab_fast[t >> 2];            /* XXXXXX-- */
	dst[1] = duk__base64_enctab_fast[(t << 4) & 0x3fU];  /* ------XX */
	dst[2] = DUK_ASC_EQUALS;
	dst[3] = DUK_ASC_EQUALS;
}

DUK_LOCAL void duk__base64_encode_helper(const duk_uint8_t *src, duk_size_t srclen, duk_uint8_t *dst) {
	duk_size_t n;
	const duk_uint8_t *p;
	duk_uint8_t *q;

	n = srclen;
	p = src;
	q = dst;

	if (n >= 16U) {
		/* Fast path, unrolled by 4, allows interleaving.  Process
		 * 12-byte input chunks which encode to 16-char output chunks.
		 * Only enter when at least one block is emitted (avoids div+mul
		 * for short inputs too).
		 */
		const duk_uint8_t *p_end_fast;

		p_end_fast = p + ((n / 12U) * 12U);
		DUK_ASSERT(p_end_fast >= p + 12);
		do {
			duk__base64_encode_fast_3(p, q);
			duk__base64_encode_fast_3(p + 3, q + 4);
			duk__base64_encode_fast_3(p + 6, q + 8);
			duk__base64_encode_fast_3(p + 9, q + 12);
			p += 12;
			q += 16;
		} while (DUK_LIKELY(p != p_end_fast));

		DUK_ASSERT(src + srclen >= p);
		n = (duk_size_t) (src + srclen - p);
		DUK_ASSERT(n < 12U);
	}

	/* Remainder. */
	while (n >= 3U) {
		duk__base64_encode_fast_3(p, q);
		p += 3;
		q += 4;
		n -= 3U;
	}
	DUK_ASSERT(n == 0U || n == 1U || n == 2U);
	if (n == 1U) {
		duk__base64_encode_fast_1(p, q);
#if 0  /* Unnecessary. */
		p += 1;
		q += 4;
		n -= 1U;
#endif
	} else if (n == 2U) {
		duk__base64_encode_fast_2(p, q);
#if 0  /* Unnecessary. */
		p += 2;
		q += 4;
		n -= 2U;
#endif
	} else {
		DUK_ASSERT(n == 0U);  /* nothing to do */
		;
	}
}
#else  /* DUK_USE_BASE64_FASTPATH */
DUK_LOCAL void duk__base64_encode_helper(const duk_uint8_t *src, duk_size_t srclen, duk_uint8_t *dst) {
	duk_small_uint_t i, npad;
	duk_uint_t t, x, y;
	const duk_uint8_t *p;
	const duk_uint8_t *p_end;
	duk_uint8_t *q;

	p = src;
	p_end = src + srclen;
	q = dst;
	npad = 0U;

	while (p < p_end) {
		/* Read 3 bytes into 't', padded by zero. */
		t = 0;
		for (i = 0; i < 3; i++) {
			t = t << 8;
			if (p < p_end) {
				t += (duk_uint_t) (*p++);
			} else {
				/* This only happens on the last loop and we're
				 * guaranteed to exit on the next loop.
				 */
				npad++;
			}
		}
		DUK_ASSERT(npad <= 2U);

		/* Emit 4 encoded characters.  If npad > 0, some of the
		 * chars will be incorrect (zero bits) but we fix up the
		 * padding after the loop.  A straightforward 64-byte
		 * lookup would be faster and cleaner, but this is shorter.
		 */
		for (i = 0; i < 4; i++) {
			x = ((t >> 18) & 0x3fU);
			t = t << 6;

			if (x <= 51U) {
				if (x <= 25) {
					y = x + DUK_ASC_UC_A;
				} else {
					y = x - 26 + DUK_ASC_LC_A;
				}
			} else {
				if (x <= 61U) {
					y = x - 52 + DUK_ASC_0;
				} else if (x == 62) {
					y = DUK_ASC_PLUS;
				} else {
					DUK_ASSERT(x == 63);
					y = DUK_ASC_SLASH;
				}
			}

			*q++ = (duk_uint8_t) y;
		}
	}

	/* Handle padding by rewriting 0-2 bogus characters at the end.
	 *
	 *  Missing bytes    npad     base64 example
	 *    0               0         ####
	 *    1               1         ###=
	 *    2               2         ##==
	 */
	DUK_ASSERT(npad <= 2U);
	while (npad > 0U) {
		*(q - npad) = DUK_ASC_EQUALS;
		npad--;
	}
}
#endif  /* DUK_USE_BASE64_FASTPATH */

#if defined(DUK_USE_BASE64_FASTPATH)
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) {
	duk_int_t x;
	duk_uint_t t;
	duk_small_uint_t n_equal;
	duk_int8_t step;
	const duk_uint8_t *p;
	const duk_uint8_t *p_end;
	const duk_uint8_t *p_end_safe;
	duk_uint8_t *q;

	DUK_ASSERT(src != NULL);  /* Required by pointer arithmetic below, which fails for NULL. */

	p = src;
	p_end = src + srclen;
	p_end_safe = p_end - 8;  /* If 'src <= src_end_safe', safe to read 8 bytes. */
	q = dst;

	/* Alternate between a fast path which processes clean groups with no
	 * padding or whitespace, and a slow path which processes one arbitrary
	 * group and then re-enters the fast path.  This handles e.g. base64
	 * with newlines reasonably well because the majority of a line is in
	 * the fast path.
	 */
	for (;;) {
		/* Fast path, on each loop handle two 4-char input groups.
		 * If both are clean, emit 6 bytes and continue.  If first
		 * is clean, emit 3 bytes and drop out; otherwise emit
		 * nothing and drop out.  This approach could be extended to
		 * more groups per loop, but for inputs with e.g. periodic
		 * newlines (which are common) it might not be an improvement.
		 */
		while (DUK_LIKELY(p <= p_end_safe)) {
			duk_int_t t1, t2;

			/* The lookup byte is intentionally sign extended to
			 * (at least) 32 bits and then ORed.  This ensures
			 * that is at least 1 byte is negative, the highest
			 * bit of the accumulator will be set at the end and
			 * we don't need to check every byte.
			 *
			 * Read all input bytes first before writing output
			 * bytes to minimize aliasing.
			 */
			DUK_DDD(DUK_DDDPRINT("fast loop: p=%p, p_end_safe=%p, p_end=%p",
			                     (const void *) p, (const void *) p_end_safe, (const void *) p_end));

			t1 = (duk_int_t) duk__base64_dectab_fast[p[0]];
			t1 = (duk_int_t) ((duk_uint_t) t1 << 6) | (duk_int_t) duk__base64_dectab_fast[p[1]];
			t1 = (duk_int_t) ((duk_uint_t) t1 << 6) | (duk_int_t) duk__base64_dectab_fast[p[2]];
			t1 = (duk_int_t) ((duk_uint_t) t1 << 6) | (duk_int_t) duk__base64_dectab_fast[p[3]];

			t2 = (duk_int_t) duk__base64_dectab_fast[p[4]];
			t2 = (duk_int_t) ((duk_uint_t) t2 << 6) | (duk_int_t) duk__base64_dectab_fast[p[5]];
			t2 = (duk_int_t) ((duk_uint_t) t2 << 6) | (duk_int_t) duk__base64_dectab_fast[p[6]];
			t2 = (duk_int_t) ((duk_uint_t) t2 << 6) | (duk_int_t) duk__base64_dectab_fast[p[7]];

			q[0] = (duk_uint8_t) (((duk_uint_t) t1 >> 16) & 0xffU);
			q[1] = (duk_uint8_t) (((duk_uint_t) t1 >> 8) & 0xffU);
			q[2] = (duk_uint8_t) ((duk_uint_t) t1 & 0xffU);

			q[3] = (duk_uint8_t) (((duk_uint_t) t2 >> 16) & 0xffU);
			q[4] = (duk_uint8_t) (((duk_uint_t) t2 >> 8) & 0xffU);
			q[5] = (duk_uint8_t) ((duk_uint_t) t2 & 0xffU);

			/* Optimistic check using one branch. */
			if (DUK_LIKELY((t1 | t2) >= 0)) {
				p += 8;
				q += 6;
			} else if (t1 >= 0) {
				DUK_DDD(DUK_DDDPRINT("fast loop first group was clean, second was not, process one slow path group"));
				DUK_ASSERT(t2 < 0);
				p += 4;
				q += 3;
				break;
			} else {
				DUK_DDD(DUK_DDDPRINT("fast loop first group was not clean, second does not matter, process one slow path group"));
				DUK_ASSERT(t1 < 0);
				break;
			}
		}  /* fast path */

		/* Slow path step 1: try to scan a 4-character encoded group,
		 * end-of-input, or start-of-padding.  We exit with:
		 *   1. n_chars == 4: full group, no padding, no end-of-input.
		 *   2. n_chars < 4: partial group (may also be 0), encountered
		 *      padding or end of input.
		 *
		 * The accumulator is initialized to 1; this allows us to detect
		 * a full group by comparing >= 0x1000000 without an extra
		 * counter variable.
		 */
		t = 1UL;
		for (;;) {
			DUK_DDD(DUK_DDDPRINT("slow loop: p=%p, p_end=%p, t=%lu",
			                     (const void *) p, (const void *) p_end, (unsigned long) t));

			if (DUK_LIKELY(p < p_end)) {
				x = duk__base64_dectab_fast[*p++];
				if (DUK_LIKELY(x >= 0)) {
					DUK_ASSERT(x >= 0 && x <= 63);
					t = (t << 6) + (duk_uint_t) x;
					if (t >= 0x1000000UL) {
						break;
					}
				} else if (x == -1) {
					continue;  /* allowed ascii whitespace */
				} else if (x == -2) {
					p--;
					break;  /* start of padding */
				} else {
					DUK_ASSERT(x == -3);
					goto decode_error;
				}
			} else {
				break;  /* end of input */
			}
		}  /* slow path step 1 */

		/* Complete the padding by simulating pad characters,
		 * regardless of actual input padding chars.
		 */
		n_equal = 0;
		while (t < 0x1000000UL) {
			t = (t << 6) + 0U;
			n_equal++;
		}

		/* Slow path step 2: deal with full/partial group, padding,
		 * etc.  Note that for num chars in [0,3] we intentionally emit
		 * 3 bytes but don't step forward that much, buffer space is
		 * guaranteed in setup.
		 *
		 *  num chars:
		 *   0      ####   no output (= step 0)
		 *   1      #===   reject, 6 bits of data
		 *   2      ##==   12 bits of data, output 1 byte (= step 1)
		 *   3      ###=   18 bits of data, output 2 bytes (= step 2)
		 *   4      ####   24 bits of data, output 3 bytes (= step 3)
		 */
		q[0] = (duk_uint8_t) ((t >> 16) & 0xffU);
		q[1] = (duk_uint8_t) ((t >> 8) & 0xffU);
		q[2] = (duk_uint8_t) (t & 0xffU);

		DUK_ASSERT(n_equal <= 4);
		step = duk__base64_decode_nequal_step[n_equal];
		if (DUK_UNLIKELY(step < 0)) {
			goto decode_error;
		}
		q += step;

		/* Slow path step 3: read and ignore padding and whitespace
		 * until (a) next non-padding and non-whitespace character
		 * after which we resume the fast path, or (b) end of input.
		 * This allows us to accept missing, partial, full, and extra
		 * padding cases uniformly.  We also support concatenated
		 * base-64 documents because we resume scanning afterwards.
		 *
		 * Note that to support concatenated documents well, the '='
		 * padding found inside the input must also allow for 'extra'
		 * padding.  For example, 'Zm===' decodes to 'f' and has one
		 * extra padding char.  So, 'Zm===Zm' should decode 'ff', even
		 * though the standard break-up would be 'Zm==' + '=Zm' which
		 * doesn't make sense.
		 *
		 * We also accept prepended padding like '==Zm9', because it
		 * is equivalent to an empty document with extra padding ('==')
		 * followed by a valid document.
		 */

		for (;;) {
			if (DUK_UNLIKELY(p >= p_end)) {
				goto done;
			}
			x = duk__base64_dectab_fast[*p++];
			if (x == -1 || x == -2) {
				;  /* padding or whitespace, keep eating */
			} else {
				p--;
				break;  /* backtrack and go back to fast path, even for -1 */
			}
		}  /* slow path step 3 */
	}  /* outer fast+slow path loop */

 done:
	DUK_DDD(DUK_DDDPRINT("done; p=%p, p_end=%p",
	                     (const void *) p, (const void *) p_end));

	DUK_ASSERT(p == p_end);

	*out_dst_final = q;
	return 1;

 decode_error:
	return 0;
}
#else  /* DUK_USE_BASE64_FASTPATH */
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) {
	duk_uint_t t, x;
	duk_int_t y;
	duk_int8_t step;
	const duk_uint8_t *p;
	const duk_uint8_t *p_end;
	duk_uint8_t *q;
	/* 0x09, 0x0a, or 0x0d */
	duk_uint32_t mask_white = (1U << 9) | (1U << 10) | (1U << 13);

	/* 't' tracks progress of the decoded group:
	 *
	 *  t == 1             no valid chars yet
	 *  t >= 0x40          1x6 = 6 bits shifted in
	 *  t >= 0x1000        2x6 = 12 bits shifted in
	 *  t >= 0x40000       3x6 = 18 bits shifted in
	 *  t >= 0x1000000     4x6 = 24 bits shifted in
	 *
	 * By initializing t=1 there's no need for a separate counter for
	 * the number of characters found so far.
	 */
	p = src;
	p_end = src + srclen;
	q = dst;
	t = 1UL;

	for (;;) {
		duk_small_uint_t n_equal;

		DUK_ASSERT(t >= 1U);
		if (p >= p_end) {
			/* End of input: if input exists, treat like
			 * start of padding, finish the block, then
			 * re-enter here to see we're done.
			 */
			if (t == 1U) {
				break;
			} else {
				goto simulate_padding;
			}
		}

		x = *p++;

		if (x >= 0x41U) {
			/* Valid: a-z and A-Z. */
			DUK_ASSERT(x >= 0x41U && x <= 0xffU);
			if (x >= 0x61U && x <= 0x7aU) {
				y = (duk_int_t) x - 0x61 + 26;
			} else if (x <= 0x5aU) {
				y = (duk_int_t) x - 0x41;
			} else {
				goto decode_error;
			}
		} else if (x >= 0x30U) {
			/* Valid: 0-9 and =. */
			DUK_ASSERT(x >= 0x30U && x <= 0x40U);
			if (x <= 0x39U) {
				y = (duk_int_t) x - 0x30 + 52;
			} else if (x == 0x3dU) {
				/* Skip padding and whitespace unless we're in the
				 * middle of a block.  Otherwise complete group by
				 * simulating shifting in the correct padding.
				 */
				if (t == 1U) {
					continue;
				}
				goto simulate_padding;
			} else {
				goto decode_error;
			}
		} else if (x >= 0x20U) {
			/* Valid: +, /, and 0x20 whitespace. */
			DUK_ASSERT(x >= 0x20U && x <= 0x2fU);
			if (x == 0x2bU) {
				y = 62;
			} else if (x == 0x2fU) {
				y = 63;
			} else if (x == 0x20U) {
				continue;
			} else {
				goto decode_error;
			}
		} else {
			/* Valid: whitespace. */
			duk_uint32_t m;
			DUK_ASSERT(x < 0x20U);  /* 0x00 to 0x1f */
			m = (1U << x);
			if (mask_white & m) {
				/* Allow basic ASCII whitespace. */
				continue;
			} else {
				goto decode_error;
			}
		}

		DUK_ASSERT(y >= 0 && y <= 63);
		t = (t << 6) + (duk_uint_t) y;
		if (t < 0x1000000UL) {
			continue;
		}
		/* fall through; no padding will be added */

	 simulate_padding:
		n_equal = 0;
		while (t < 0x1000000UL) {
			t = (t << 6) + 0U;
			n_equal++;
		}

		/* Output 3 bytes from 't' and advance as needed. */
		q[0] = (duk_uint8_t) ((t >> 16) & 0xffU);
		q[1] = (duk_uint8_t) ((t >> 8) & 0xffU);
		q[2] = (duk_uint8_t) (t & 0xffU);

		DUK_ASSERT(n_equal <= 4U);
		step = duk__base64_decode_nequal_step[n_equal];
		if (step < 0) {
			goto decode_error;
		}
		q += step;

		/* Re-enter loop.  The actual padding characters are skipped
		 * by the main loop.  This handles cases like missing, partial,
		 * full, and extra padding, and allows parsing of concatenated
		 * documents (with extra padding) like: Zm===Zm.  Also extra
		 * prepended padding is accepted: ===Zm9v.
		 */
		t = 1U;
	}
	DUK_ASSERT(t == 1UL);

	*out_dst_final = q;
	return 1;

 decode_error:
	return 0;
}
#endif  /* DUK_USE_BASE64_FASTPATH */

DUK_EXTERNAL const char *duk_base64_encode(duk_hthread *thr, duk_idx_t idx) {
	const duk_uint8_t *src;
	duk_size_t srclen;
	duk_size_t dstlen;
	duk_uint8_t *dst;
	const char *ret;

	DUK_ASSERT_API_ENTRY(thr);

	idx = duk_require_normalize_index(thr, idx);
	src = duk__prep_codec_arg(thr, idx, &srclen);
	DUK_ASSERT(src != NULL);

	/* Compute exact output length.  Computation must not wrap; this
	 * limit works for 32-bit size_t:
	 * >>> srclen = 3221225469
	 * >>> '%x' % ((srclen + 2) / 3 * 4)
	 * 'fffffffc'
	 */
	if (srclen > 3221225469UL) {
		goto type_error;
	}
	dstlen = (srclen + 2U) / 3U * 4U;
	dst = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, dstlen);

	duk__base64_encode_helper((const duk_uint8_t *) src, srclen, dst);

	ret = duk_buffer_to_string(thr, -1);  /* Safe, result is ASCII. */
	duk_replace(thr, idx);
	return ret;

 type_error:
	DUK_ERROR_TYPE(thr, DUK_STR_BASE64_ENCODE_FAILED);
	DUK_WO_NORETURN(return NULL;);
}

DUK_EXTERNAL void duk_base64_decode(duk_hthread *thr, duk_idx_t idx) {
	const duk_uint8_t *src;
	duk_size_t srclen;
	duk_size_t dstlen;
	duk_uint8_t *dst;
	duk_uint8_t *dst_final;

	DUK_ASSERT_API_ENTRY(thr);

	idx = duk_require_normalize_index(thr, idx);
	src = duk__prep_codec_arg(thr, idx, &srclen);
	DUK_ASSERT(src != NULL);

	/* Round up and add safety margin.  Avoid addition before division to
	 * avoid possibility of wrapping.  Margin includes +3 for rounding up,
	 * and +3 for one extra group: the decoder may emit and then backtrack
	 * a full group (3 bytes) from zero-sized input for technical reasons.
	 * Similarly, 'xx' may ecause 1+3 = bytes to be emitted and then
	 * backtracked.
	 */
	dstlen = (srclen / 4) * 3 + 6;  /* upper limit, assuming no whitespace etc */
	dst = (duk_uint8_t *) duk_push_dynamic_buffer(thr, dstlen);
	/* Note: for dstlen=0, dst may be NULL */

	if (!duk__base64_decode_helper((const duk_uint8_t *) src, srclen, dst, &dst_final)) {
		goto type_error;
	}

	/* XXX: convert to fixed buffer? */
	(void) duk_resize_buffer(thr, -1, (duk_size_t) (dst_final - dst));
	duk_replace(thr, idx);
	return;

 type_error:
	DUK_ERROR_TYPE(thr, DUK_STR_BASE64_DECODE_FAILED);
	DUK_WO_NORETURN(return;);
}
#else  /* DUK_USE_BASE64_SUPPORT */
DUK_EXTERNAL const char *duk_base64_encode(duk_hthread *thr, duk_idx_t idx) {
	DUK_UNREF(idx);
	DUK_ERROR_UNSUPPORTED(thr);
	DUK_WO_NORETURN(return NULL;);
}

DUK_EXTERNAL void duk_base64_decode(duk_hthread *thr, duk_idx_t idx) {
	DUK_UNREF(idx);
	DUK_ERROR_UNSUPPORTED(thr);
	DUK_WO_NORETURN(return;);
}
#endif  /* DUK_USE_BASE64_SUPPORT */

/*
 *  Hex
 */

#if defined(DUK_USE_HEX_SUPPORT)
DUK_EXTERNAL const char *duk_hex_encode(duk_hthread *thr, duk_idx_t idx) {
	const duk_uint8_t *inp;
	duk_size_t len;
	duk_size_t i;
	duk_uint8_t *buf;
	const char *ret;
#if defined(DUK_USE_HEX_FASTPATH)
	duk_size_t len_safe;
	duk_uint16_t *p16;
#endif

	DUK_ASSERT_API_ENTRY(thr);

	idx = duk_require_normalize_index(thr, idx);
	inp = duk__prep_codec_arg(thr, idx, &len);
	DUK_ASSERT(inp != NULL);

	/* Fixed buffer, no zeroing because we'll fill all the data. */
	buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, len * 2);
	DUK_ASSERT(buf != NULL);

#if defined(DUK_USE_HEX_FASTPATH)
	DUK_ASSERT((((duk_size_t) buf) & 0x01U) == 0);   /* pointer is aligned, guaranteed for fixed buffer */
	p16 = (duk_uint16_t *) (void *) buf;
	len_safe = len & ~0x03U;
	for (i = 0; i < len_safe; i += 4) {
		p16[0] = duk_hex_enctab[inp[i]];
		p16[1] = duk_hex_enctab[inp[i + 1]];
		p16[2] = duk_hex_enctab[inp[i + 2]];
		p16[3] = duk_hex_enctab[inp[i + 3]];
		p16 += 4;
	}
	for (; i < len; i++) {
		*p16++ = duk_hex_enctab[inp[i]];
	}
#else  /* DUK_USE_HEX_FASTPATH */
	for (i = 0; i < len; i++) {
		duk_small_uint_t t;
		t = (duk_small_uint_t) inp[i];
		buf[i*2 + 0] = duk_lc_digits[t >> 4];
		buf[i*2 + 1] = duk_lc_digits[t & 0x0f];
	}
#endif  /* DUK_USE_HEX_FASTPATH */

	/* XXX: Using a string return value forces a string intern which is
	 * not always necessary.  As a rough performance measure, hex encode
	 * time for tests/perf/test-hex-encode.js dropped from ~35s to ~15s
	 * without string coercion.  Change to returning a buffer and let the
	 * caller coerce to string if necessary?
	 */

	ret = duk_buffer_to_string(thr, -1);  /* Safe, result is ASCII. */
	duk_replace(thr, idx);
	return ret;
}

DUK_EXTERNAL void duk_hex_decode(duk_hthread *thr, duk_idx_t idx) {
	const duk_uint8_t *inp;
	duk_size_t len;
	duk_size_t i;
	duk_int_t t;
	duk_uint8_t *buf;
#if defined(DUK_USE_HEX_FASTPATH)
	duk_int_t chk;
	duk_uint8_t *p;
	duk_size_t len_safe;
#endif

	DUK_ASSERT_API_ENTRY(thr);

	idx = duk_require_normalize_index(thr, idx);
	inp = duk__prep_codec_arg(thr, idx, &len);
	DUK_ASSERT(inp != NULL);

	if (len & 0x01) {
		goto type_error;
	}

	/* Fixed buffer, no zeroing because we'll fill all the data. */
	buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, len / 2);
	DUK_ASSERT(buf != NULL);

#if defined(DUK_USE_HEX_FASTPATH)
	p = buf;
	len_safe = len & ~0x07U;
	for (i = 0; i < len_safe; i += 8) {
		t = ((duk_int_t) duk_hex_dectab_shift4[inp[i]]) |
		    ((duk_int_t) duk_hex_dectab[inp[i + 1]]);
		chk = t;
		p[0] = (duk_uint8_t) t;
		t = ((duk_int_t) duk_hex_dectab_shift4[inp[i + 2]]) |
		    ((duk_int_t) duk_hex_dectab[inp[i + 3]]);
		chk |= t;
		p[1] = (duk_uint8_t) t;
		t = ((duk_int_t) duk_hex_dectab_shift4[inp[i + 4]]) |
		    ((duk_int_t) duk_hex_dectab[inp[i + 5]]);
		chk |= t;
		p[2] = (duk_uint8_t) t;
		t = ((duk_int_t) duk_hex_dectab_shift4[inp[i + 6]]) |
		    ((duk_int_t) duk_hex_dectab[inp[i + 7]]);
		chk |= t;
		p[3] = (duk_uint8_t) t;
		p += 4;

		/* Check if any lookup above had a negative result. */
		if (DUK_UNLIKELY(chk < 0)) {
			goto type_error;
		}
	}
	for (; i < len; i += 2) {
		/* First cast to duk_int_t to sign extend, second cast to
		 * duk_uint_t to avoid signed left shift, and final cast to
		 * duk_int_t result type.
		 */
		t = (duk_int_t) ((((duk_uint_t) (duk_int_t) duk_hex_dectab[inp[i]]) << 4U) |
		                 ((duk_uint_t) (duk_int_t) duk_hex_dectab[inp[i + 1]]));
		if (DUK_UNLIKELY(t < 0)) {
			goto type_error;
		}
		*p++ = (duk_uint8_t) t;
	}
#else  /* DUK_USE_HEX_FASTPATH */
	for (i = 0; i < len; i += 2) {
		/* For invalid characters the value -1 gets extended to
		 * at least 16 bits.  If either nybble is invalid, the
		 * resulting 't' will be < 0.
		 */
		t = (duk_int_t) ((((duk_uint_t) (duk_int_t) duk_hex_dectab[inp[i]]) << 4U) |
		                 ((duk_uint_t) (duk_int_t) duk_hex_dectab[inp[i + 1]]));
		if (DUK_UNLIKELY(t < 0)) {
			goto type_error;
		}
		buf[i >> 1] = (duk_uint8_t) t;
	}
#endif  /* DUK_USE_HEX_FASTPATH */

	duk_replace(thr, idx);
	return;

 type_error:
	DUK_ERROR_TYPE(thr, DUK_STR_HEX_DECODE_FAILED);
	DUK_WO_NORETURN(return;);
}
#else  /* DUK_USE_HEX_SUPPORT */
DUK_EXTERNAL const char *duk_hex_encode(duk_hthread *thr, duk_idx_t idx) {
	DUK_UNREF(idx);
	DUK_ERROR_UNSUPPORTED(thr);
	DUK_WO_NORETURN(return NULL;);
}
DUK_EXTERNAL void duk_hex_decode(duk_hthread *thr, duk_idx_t idx) {
	DUK_UNREF(idx);
	DUK_ERROR_UNSUPPORTED(thr);
	DUK_WO_NORETURN(return;);
}
#endif  /* DUK_USE_HEX_SUPPORT */

/*
 *  JSON
 */

#if defined(DUK_USE_JSON_SUPPORT)
DUK_EXTERNAL const char *duk_json_encode(duk_hthread *thr, duk_idx_t idx) {
#if defined(DUK_USE_ASSERTIONS)
	duk_idx_t top_at_entry;
#endif
	const char *ret;

	DUK_ASSERT_API_ENTRY(thr);
#if defined(DUK_USE_ASSERTIONS)
	top_at_entry = duk_get_top(thr);
#endif

	idx = duk_require_normalize_index(thr, idx);
	duk_bi_json_stringify_helper(thr,
	                             idx /*idx_value*/,
	                             DUK_INVALID_INDEX /*idx_replacer*/,
	                             DUK_INVALID_INDEX /*idx_space*/,
	                             0 /*flags*/);
	DUK_ASSERT(duk_is_string(thr, -1));
	duk_replace(thr, idx);
	ret = duk_get_string(thr, idx);

	DUK_ASSERT(duk_get_top(thr) == top_at_entry);

	return ret;
}

DUK_EXTERNAL void duk_json_decode(duk_hthread *thr, duk_idx_t idx) {
#if defined(DUK_USE_ASSERTIONS)
	duk_idx_t top_at_entry;
#endif

	DUK_ASSERT_API_ENTRY(thr);
#if defined(DUK_USE_ASSERTIONS)
	top_at_entry = duk_get_top(thr);
#endif

	idx = duk_require_normalize_index(thr, idx);
	duk_bi_json_parse_helper(thr,
	                         idx /*idx_value*/,
	                         DUK_INVALID_INDEX /*idx_reviver*/,
	                         0 /*flags*/);
	duk_replace(thr, idx);

	DUK_ASSERT(duk_get_top(thr) == top_at_entry);
}
#else  /* DUK_USE_JSON_SUPPORT */
DUK_EXTERNAL const char *duk_json_encode(duk_hthread *thr, duk_idx_t idx) {
	DUK_ASSERT_API_ENTRY(thr);
	DUK_UNREF(idx);
	DUK_ERROR_UNSUPPORTED(thr);
	DUK_WO_NORETURN(return NULL;);
}

DUK_EXTERNAL void duk_json_decode(duk_hthread *thr, duk_idx_t idx) {
	DUK_ASSERT_API_ENTRY(thr);
	DUK_UNREF(idx);
	DUK_ERROR_UNSUPPORTED(thr);
	DUK_WO_NORETURN(return;);
}
#endif  /* DUK_USE_JSON_SUPPORT */
#line 1 "duk_api_compile.c"
/*
 *  Compilation and evaluation
 */

/* #include duk_internal.h -> already included */

typedef struct duk__compile_raw_args duk__compile_raw_args;
struct duk__compile_raw_args {
	duk_size_t src_length;  /* should be first on 64-bit platforms */
	const duk_uint8_t *src_buffer;
	duk_uint_t flags;
};

/* Eval is just a wrapper now. */
DUK_EXTERNAL duk_int_t duk_eval_raw(duk_hthread *thr, const char *src_buffer, duk_size_t src_length, duk_uint_t flags) {
	duk_int_t rc;

	DUK_ASSERT_API_ENTRY(thr);

	/* Note: strictness is *not* inherited from the current Duktape/C.
	 * This would be confusing because the current strictness state
	 * depends on whether we're running inside a Duktape/C activation
	 * (= strict mode) or outside of any activation (= non-strict mode).
	 * See tests/api/test-eval-strictness.c for more discussion.
	 */

	/* [ ... source? filename? ] (depends on flags) */

	rc = duk_compile_raw(thr, src_buffer, src_length, flags | DUK_COMPILE_EVAL);  /* may be safe, or non-safe depending on flags */

	/* [ ... closure/error ] */

	if (rc != DUK_EXEC_SUCCESS) {
		rc = DUK_EXEC_ERROR;
		goto got_rc;
	}

	duk_push_global_object(thr);  /* explicit 'this' binding, see GH-164 */

	if (flags & DUK_COMPILE_SAFE) {
		rc = duk_pcall_method(thr, 0);
	} else {
		duk_call_method(thr, 0);
		rc = DUK_EXEC_SUCCESS;
	}

	/* [ ... result/error ] */

 got_rc:
	if (flags & DUK_COMPILE_NORESULT) {
		duk_pop(thr);
	}

	return rc;
}

/* Helper which can be called both directly and with duk_safe_call(). */
DUK_LOCAL duk_ret_t duk__do_compile(duk_hthread *thr, void *udata) {
	duk__compile_raw_args *comp_args;
	duk_uint_t flags;
	duk_hcompfunc *h_templ;

	DUK_CTX_ASSERT_VALID(thr);
	DUK_ASSERT(udata != NULL);

	/* Note: strictness is not inherited from the current Duktape/C
	 * context.  Otherwise it would not be possible to compile
	 * non-strict code inside a Duktape/C activation (which is
	 * always strict now).  See tests/api/test-eval-strictness.c
	 * for discussion.
	 */

	/* [ ... source? filename? ] (depends on flags) */

	comp_args = (duk__compile_raw_args *) udata;
	flags = comp_args->flags;

	if (flags & DUK_COMPILE_NOFILENAME) {
		/* Automatic filename: 'eval' or 'input'. */
		duk_push_hstring_stridx(thr, (flags & DUK_COMPILE_EVAL) ? DUK_STRIDX_EVAL : DUK_STRIDX_INPUT);
	}

	/* [ ... source? filename ] */

	if (!comp_args->src_buffer) {
		duk_hstring *h_sourcecode;

		h_sourcecode = duk_get_hstring(thr, -2);
		if ((flags & DUK_COMPILE_NOSOURCE) ||  /* args incorrect */
		    (h_sourcecode == NULL)) {          /* e.g. duk_push_string_file_raw() pushed undefined */
			DUK_ERROR_TYPE(thr, DUK_STR_NO_SOURCECODE);
			DUK_WO_NORETURN(return 0;);
		}
		DUK_ASSERT(h_sourcecode != NULL);
		comp_args->src_buffer = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_sourcecode);
		comp_args->src_length = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_sourcecode);
	}
	DUK_ASSERT(comp_args->src_buffer != NULL);

	if (flags & DUK_COMPILE_FUNCTION) {
		flags |= DUK_COMPILE_EVAL | DUK_COMPILE_FUNCEXPR;
	}

	/* [ ... source? filename ] */

	duk_js_compile(thr, comp_args->src_buffer, comp_args->src_length, flags);

	/* [ ... source? func_template ] */

	if (flags & DUK_COMPILE_NOSOURCE) {
		;
	} else {
		duk_remove_m2(thr);
	}

	/* [ ... func_template ] */

	h_templ = (duk_hcompfunc *) duk_known_hobject(thr, -1);
	duk_js_push_closure(thr,
	                   h_templ,
	                   thr->builtins[DUK_BIDX_GLOBAL_ENV],
	                   thr->builtins[DUK_BIDX_GLOBAL_ENV],
	                   1 /*add_auto_proto*/);
	duk_remove_m2(thr);   /* -> [ ... closure ] */

	/* [ ... closure ] */

	return 1;
}

DUK_EXTERNAL duk_int_t duk_compile_raw(duk_hthread *thr, const char *src_buffer, duk_size_t src_length, duk_uint_t flags) {
	duk__compile_raw_args comp_args_alloc;
	duk__compile_raw_args *comp_args = &comp_args_alloc;

	DUK_ASSERT_API_ENTRY(thr);

	if ((flags & DUK_COMPILE_STRLEN) && (src_buffer != NULL)) {
		/* String length is computed here to avoid multiple evaluation
		 * of a macro argument in the calling side.
		 */
		src_length = DUK_STRLEN(src_buffer);
	}

	comp_args->src_buffer = (const duk_uint8_t *) src_buffer;
	comp_args->src_length = src_length;
	comp_args->flags = flags;

	/* [ ... source? filename? ] (depends on flags) */

	if (flags & DUK_COMPILE_SAFE) {
		duk_int_t rc;
		duk_int_t nargs;
		duk_int_t nrets = 1;

		/* Arguments can be: [ source? filename? &comp_args] so that
		 * nargs is 1 to 3.  Call site encodes the correct nargs count
		 * directly into flags.
		 */
		nargs = flags & 0x07;
		DUK_ASSERT(nargs == ((flags & DUK_COMPILE_NOSOURCE) ? 0 : 1) +
		                    ((flags & DUK_COMPILE_NOFILENAME) ? 0 : 1));
		rc = duk_safe_call(thr, duk__do_compile, (void *) comp_args, nargs, nrets);

		/* [ ... closure ] */
		return rc;
	}

	(void) duk__do_compile(thr, (void *) comp_args);

	/* [ ... closure ] */
	return DUK_EXEC_SUCCESS;
}
#line 1 "duk_api_debug.c"
/*
 *  Debugging related API calls
 */

/* #include duk_internal.h -> already included */

#if defined(DUK_USE_JSON_SUPPORT)
DUK_EXTERNAL void duk_push_context_dump(duk_hthread *thr) {
	duk_idx_t idx;
	duk_idx_t top;

	DUK_ASSERT_API_ENTRY(thr);

	/* We don't duk_require_stack() here now, but rely on the caller having
	 * enough space.
	 */

	top = duk_get_top(thr);
	duk_push_bare_array(thr);
	for (idx = 0; idx < top; idx++) {
		duk_dup(thr, idx);
		duk_put_prop_index(thr, -2, (duk_uarridx_t) idx);
	}

	/* XXX: conversion errors should not propagate outwards.
	 * Perhaps values need to be coerced individually?
	 */
	duk_bi_json_stringify_helper(thr,
	                             duk_get_top_index(thr),  /*idx_value*/
	                             DUK_INVALID_INDEX,  /*idx_replacer*/
	                             DUK_INVALID_INDEX,  /*idx_space*/
	                             DUK_JSON_FLAG_EXT_CUSTOM |
	                             DUK_JSON_FLAG_ASCII_ONLY |
	                             DUK_JSON_FLAG_AVOID_KEY_QUOTES /*flags*/);

	duk_push_sprintf(thr, "ctx: top=%ld, stack=%s", (long) top, (const char *) duk_safe_to_string(thr, -1));
	duk_replace(thr, -3);  /* [ ... arr jsonx(arr) res ] -> [ ... res jsonx(arr) ] */
	duk_pop(thr);
	DUK_ASSERT(duk_is_string(thr, -1));
}
#else  /* DUK_USE_JSON_SUPPORT */
DUK_EXTERNAL void duk_push_context_dump(duk_hthread *thr) {
	DUK_ASSERT_API_ENTRY(thr);
	DUK_ERROR_UNSUPPORTED(thr);
	DUK_WO_NORETURN(return;);
}
#endif  /* DUK_USE_JSON_SUPPORT */

#if defined(DUK_USE_DEBUGGER_SUPPORT)

DUK_EXTERNAL void duk_debugger_attach(duk_hthread *thr,
                                      duk_debug_read_function read_cb,
                                      duk_debug_write_function write_cb,
                                      duk_debug_peek_function peek_cb,
                                      duk_debug_read_flush_function read_flush_cb,
                                      duk_debug_write_flush_function write_flush_cb,
                                      duk_debug_request_function request_cb,
                                      duk_debug_detached_function detached_cb,
                                      void *udata) {
	duk_heap *heap;
	const char *str;
	duk_size_t len;

	/* XXX: should there be an error or an automatic detach if
	 * already attached?
	 */

	DUK_D(DUK_DPRINT("application called duk_debugger_attach()"));

	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(read_cb != NULL);
	DUK_ASSERT(write_cb != NULL);
	/* Other callbacks are optional. */

	heap = thr->heap;
	heap->dbg_read_cb = read_cb;
	heap->dbg_write_cb = write_cb;
	heap->dbg_peek_cb = peek_cb;
	heap->dbg_read_flush_cb = read_flush_cb;
	heap->dbg_write_flush_cb = write_flush_cb;
	heap->dbg_request_cb = request_cb;
	heap->dbg_detached_cb = detached_cb;
	heap->dbg_udata = udata;
	heap->dbg_have_next_byte = 0;

	/* Start in paused state. */
	heap->dbg_processing = 0;
	heap->dbg_state_dirty = 0;
	heap->dbg_force_restart = 0;
	heap->dbg_pause_flags = 0;
	heap->dbg_pause_act = NULL;
	heap->dbg_pause_startline = 0;
	heap->dbg_exec_counter = 0;
	heap->dbg_last_counter = 0;
	heap->dbg_last_time = 0.0;
	duk_debug_set_paused(heap);  /* XXX: overlap with fields above */

	/* Send version identification and flush right afterwards.  Note that
	 * we must write raw, unframed bytes here.
	 */
	duk_push_sprintf(thr, "%ld %ld %s %s\n",
	                 (long) DUK_DEBUG_PROTOCOL_VERSION,
	                 (long) DUK_VERSION,
	                 (const char *) DUK_GIT_DESCRIBE,
	                 (const char *) DUK_USE_TARGET_INFO);
	str = duk_get_lstring(thr, -1, &len);
	DUK_ASSERT(str != NULL);
	duk_debug_write_bytes(thr, (const duk_uint8_t *) str, len);
	duk_debug_write_flush(thr);
	duk_pop(thr);
}

DUK_EXTERNAL void duk_debugger_detach(duk_hthread *thr) {
	DUK_D(DUK_DPRINT("application called duk_debugger_detach()"));

	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(thr->heap != NULL);

	/* Can be called multiple times with no harm. */
	duk_debug_do_detach(thr->heap);
}

DUK_EXTERNAL void duk_debugger_cooperate(duk_hthread *thr) {
	duk_bool_t processed_messages;

	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(thr->heap != NULL);

	if (!duk_debug_is_attached(thr->heap)) {
		return;
	}
	if (thr->callstack_curr != NULL || thr->heap->dbg_processing) {
		/* Calling duk_debugger_cooperate() while Duktape is being
		 * called into is not supported.  This is not a 100% check
		 * but prevents any damage in most cases.
		 */
		return;
	}

	processed_messages = duk_debug_process_messages(thr, 1 /*no_block*/);
	DUK_UNREF(processed_messages);
}

DUK_EXTERNAL duk_bool_t duk_debugger_notify(duk_hthread *thr, duk_idx_t nvalues) {
	duk_idx_t top;
	duk_idx_t idx;
	duk_bool_t ret = 0;

	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(thr->heap != NULL);

	DUK_D(DUK_DPRINT("application called duk_debugger_notify() with nvalues=%ld", (long) nvalues));

	top = duk_get_top(thr);
	if (top < nvalues) {
		DUK_ERROR_RANGE(thr, "not enough stack values for notify");
		DUK_WO_NORETURN(return 0;);
	}
	if (duk_debug_is_attached(thr->heap)) {
		duk_debug_write_notify(thr, DUK_DBG_CMD_APPNOTIFY);
		for (idx = top - nvalues; idx < top; idx++) {
			duk_tval *tv = DUK_GET_TVAL_POSIDX(thr, idx);
			duk_debug_write_tval(thr, tv);
		}
		duk_debug_write_eom(thr);

		/* Return non-zero (true) if we have a good reason to believe
		 * the notify was delivered; if we're still attached at least
		 * a transport error was not indicated by the transport write
		 * callback.  This is not a 100% guarantee of course.
		 */
		if (duk_debug_is_attached(thr->heap)) {
			ret = 1;
		}
	}
	duk_pop_n(thr, nvalues);
	return ret;
}

DUK_EXTERNAL void duk_debugger_pause(duk_hthread *thr) {
	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(thr->heap != NULL);

	DUK_D(DUK_DPRINT("application called duk_debugger_pause()"));

	/* Treat like a debugger statement: ignore when not attached. */
	if (duk_debug_is_attached(thr->heap)) {
		if (duk_debug_is_paused(thr->heap)) {
			DUK_D(DUK_DPRINT("duk_debugger_pause() called when already paused; ignoring"));
		} else {
			duk_debug_set_paused(thr->heap);

			/* Pause on the next opcode executed.  This is always safe to do even
			 * inside the debugger message loop: the interrupt counter will be reset
			 * to its proper value when the message loop exits.
			 */
			thr->interrupt_init = 1;
			thr->interrupt_counter = 0;
		}
	}
}

#else  /* DUK_USE_DEBUGGER_SUPPORT */

DUK_EXTERNAL void duk_debugger_attach(duk_hthread *thr,
                                      duk_debug_read_function read_cb,
                                      duk_debug_write_function write_cb,
                                      duk_debug_peek_function peek_cb,
                                      duk_debug_read_flush_function read_flush_cb,
                                      duk_debug_write_flush_function write_flush_cb,
                                      duk_debug_request_function request_cb,
                                      duk_debug_detached_function detached_cb,
                                      void *udata) {
	DUK_ASSERT_API_ENTRY(thr);
	DUK_UNREF(read_cb);
	DUK_UNREF(write_cb);
	DUK_UNREF(peek_cb);
	DUK_UNREF(read_flush_cb);
	DUK_UNREF(write_flush_cb);
	DUK_UNREF(request_cb);
	DUK_UNREF(detached_cb);
	DUK_UNREF(udata);
	DUK_ERROR_TYPE(thr, "no debugger support");
	DUK_WO_NORETURN(return;);
}

DUK_EXTERNAL void duk_debugger_detach(duk_hthread *thr) {
	DUK_ASSERT_API_ENTRY(thr);
	DUK_ERROR_TYPE(thr, "no debugger support");
	DUK_WO_NORETURN(return;);
}

DUK_EXTERNAL void duk_debugger_cooperate(duk_hthread *thr) {
	/* nop */
	DUK_ASSERT_API_ENTRY(thr);
	DUK_UNREF(thr);
}

DUK_EXTERNAL duk_bool_t duk_debugger_notify(duk_hthread *thr, duk_idx_t nvalues) {
	duk_idx_t top;

	DUK_ASSERT_API_ENTRY(thr);

	top = duk_get_top(thr);
	if (top < nvalues) {
		DUK_ERROR_RANGE_INVALID_COUNT(thr);
		DUK_WO_NORETURN(return 0;);
	}

	/* No debugger support, just pop values. */
	duk_pop_n(thr, nvalues);
	return 0;
}

DUK_EXTERNAL void duk_debugger_pause(duk_hthread *thr) {
	/* Treat like debugger statement: nop */
	DUK_ASSERT_API_ENTRY(thr);
	DUK_UNREF(thr);
}

#endif  /* DUK_USE_DEBUGGER_SUPPORT */
#line 1 "duk_api_heap.c"
/*
 *  Heap creation and destruction
 */

/* #include duk_internal.h -> already included */

typedef struct duk_internal_thread_state duk_internal_thread_state;

struct duk_internal_thread_state {
	duk_ljstate lj;
	duk_bool_t creating_error;
	duk_hthread *curr_thread;
	duk_int_t call_recursion_depth;
};

DUK_EXTERNAL duk_hthread *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) {
	duk_heap *heap = NULL;
	duk_hthread *thr;

	/* Assume that either all memory funcs are NULL or non-NULL, mixed
	 * cases will now be unsafe.
	 */

	/* XXX: just assert non-NULL values here and make caller arguments
	 * do the defaulting to the default implementations (smaller code)?
	 */

	if (!alloc_func) {
		DUK_ASSERT(realloc_func == NULL);
		DUK_ASSERT(free_func == NULL);
#if defined(DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS)
		alloc_func = duk_default_alloc_function;
		realloc_func = duk_default_realloc_function;
		free_func = duk_default_free_function;
#else
		DUK_D(DUK_DPRINT("no allocation functions given and no default providers"));
		return NULL;
#endif
	} else {
		DUK_ASSERT(realloc_func != NULL);
		DUK_ASSERT(free_func != NULL);
	}

	if (!fatal_handler) {
		fatal_handler = duk_default_fatal_handler;
	}

	DUK_ASSERT(alloc_func != NULL);
	DUK_ASSERT(realloc_func != NULL);
	DUK_ASSERT(free_func != NULL);
	DUK_ASSERT(fatal_handler != NULL);

	heap = duk_heap_alloc(alloc_func, realloc_func, free_func, heap_udata, fatal_handler);
	if (!heap) {
		return NULL;
	}
	thr = heap->heap_thread;
	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(thr->heap != NULL);
	return thr;
}

DUK_EXTERNAL void duk_destroy_heap(duk_hthread *thr) {
	duk_heap *heap;

	if (!thr) {
		return;
	}
	DUK_ASSERT_API_ENTRY(thr);
	heap = thr->heap;
	DUK_ASSERT(heap != NULL);

	duk_heap_free(heap);
}

DUK_EXTERNAL void duk_suspend(duk_hthread *thr, duk_thread_state *state) {
	duk_internal_thread_state *snapshot = (duk_internal_thread_state *) (void *) state;
	duk_heap *heap;
	duk_ljstate *lj;

	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(thr->heap != NULL);
	DUK_ASSERT(state != NULL);  /* unvalidated */

	/* Currently not supported when called from within a finalizer.
	 * If that is done, the finalizer will remain running indefinitely,
	 * preventing other finalizers from executing.  The assert is a bit
	 * wider, checking that it would be OK to run pending finalizers.
	 */
	DUK_ASSERT(thr->heap->pf_prevent_count == 0);

	/* Currently not supported to duk_suspend() from an errCreate()
	 * call.
	 */
	DUK_ASSERT(thr->heap->creating_error == 0);

	heap = thr->heap;
	lj = &heap->lj;

	duk_push_tval(thr, &lj->value1);
	duk_push_tval(thr, &lj->value2);

	/* XXX: creating_error == 0 is asserted above, so no need to store. */
	duk_memcpy((void *) &snapshot->lj, (const void *) lj, sizeof(duk_ljstate));
	snapshot->creating_error = heap->creating_error;
	snapshot->curr_thread = heap->curr_thread;
	snapshot->call_recursion_depth = heap->call_recursion_depth;

	lj->jmpbuf_ptr = NULL;
	lj->type = DUK_LJ_TYPE_UNKNOWN;
	DUK_TVAL_SET_UNDEFINED(&lj->value1);
	DUK_TVAL_SET_UNDEFINED(&lj->value2);
	heap->creating_error = 0;
	heap->curr_thread = NULL;
	heap->call_recursion_depth = 0;
}

DUK_EXTERNAL void duk_resume(duk_hthread *thr, const duk_thread_state *state) {
	const duk_internal_thread_state *snapshot = (const duk_internal_thread_state *) (const void *) state;
	duk_heap *heap;

	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(thr->heap != NULL);
	DUK_ASSERT(state != NULL);  /* unvalidated */

	/* Shouldn't be necessary if duk_suspend() is called before
	 * duk_resume(), but assert in case API sequence is incorrect.
	 */
	DUK_ASSERT(thr->heap->pf_prevent_count == 0);
	DUK_ASSERT(thr->heap->creating_error == 0);

	heap = thr->heap;

	duk_memcpy((void *) &heap->lj, (const void *) &snapshot->lj, sizeof(duk_ljstate));
	heap->creating_error = snapshot->creating_error;
	heap->curr_thread = snapshot->curr_thread;
	heap->call_recursion_depth = snapshot->call_recursion_depth;

	duk_pop_2(thr);
}

/* XXX: better place for this */
DUK_EXTERNAL void duk_set_global_object(duk_hthread *thr) {
	duk_hobject *h_glob;
	duk_hobject *h_prev_glob;
	duk_hobjenv *h_env;
	duk_hobject *h_prev_env;

	DUK_ASSERT_API_ENTRY(thr);

	DUK_D(DUK_DPRINT("replace global object with: %!T", duk_get_tval(thr, -1)));

	h_glob = duk_require_hobject(thr, -1);
	DUK_ASSERT(h_glob != NULL);

	/*
	 *  Replace global object.
	 */

	h_prev_glob = thr->builtins[DUK_BIDX_GLOBAL];
	DUK_UNREF(h_prev_glob);
	thr->builtins[DUK_BIDX_GLOBAL] = h_glob;
	DUK_HOBJECT_INCREF(thr, h_glob);
	DUK_HOBJECT_DECREF_ALLOWNULL(thr, h_prev_glob);  /* side effects, in theory (referenced by global env) */

	/*
	 *  Replace lexical environment for global scope
	 *
	 *  Create a new object environment for the global lexical scope.
	 *  We can't just reset the _Target property of the current one,
	 *  because the lexical scope is shared by other threads with the
	 *  same (initial) built-ins.
	 */

	h_env = duk_hobjenv_alloc(thr,
	                          DUK_HOBJECT_FLAG_EXTENSIBLE |
	                          DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJENV));
	DUK_ASSERT(h_env != NULL);
	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_env) == NULL);

	DUK_ASSERT(h_env->target == NULL);
	DUK_ASSERT(h_glob != NULL);
	h_env->target = h_glob;
	DUK_HOBJECT_INCREF(thr, h_glob);
	DUK_ASSERT(h_env->has_this == 0);

	/* [ ... new_glob ] */

	h_prev_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
	thr->builtins[DUK_BIDX_GLOBAL_ENV] = (duk_hobject *) h_env;
	DUK_HOBJECT_INCREF(thr, (duk_hobject *) h_env);
	DUK_HOBJECT_DECREF_ALLOWNULL(thr, h_prev_env);  /* side effects */
	DUK_UNREF(h_env);  /* without refcounts */
	DUK_UNREF(h_prev_env);

	/* [ ... new_glob ] */

	duk_pop(thr);

	/* [ ... ] */
}
#line 1 "duk_api_inspect.c"
/*
 *  Inspection
 */

/* #include duk_internal.h -> already included */

/* For footprint efficient multiple value setting: arrays are much better than
 * varargs, format string with parsing is often better than string pointer arrays.
 */
DUK_LOCAL void duk__inspect_multiple_uint(duk_hthread *thr, const char *fmt, duk_int_t *vals) {
	duk_int_t val;
	const char *p;
	const char *p_curr;
	duk_size_t len;

	for (p = fmt;;) {
		len = DUK_STRLEN(p);
		p_curr = p;
		p += len + 1;
		if (len == 0) {
			/* Double NUL (= empty key) terminates. */
			break;
		}
		val = *vals++;
		if (val >= 0) {
			/* Negative values are markers to skip key. */
			duk_push_string(thr, p_curr);
			duk_push_int(thr, val);
			duk_put_prop(thr, -3);
		}
	}
}

/* Raw helper to extract internal information / statistics about a value.
 * The return value is an object with properties that are version specific.
 * The properties must not expose anything that would lead to security
 * issues (e.g. exposing compiled function 'data' buffer might be an issue).
 * Currently only counts and sizes and such are given so there shouldn't
 * be security implications.
 */

#define DUK__IDX_TYPE     0
#define DUK__IDX_ITAG     1
#define DUK__IDX_REFC     2
#define DUK__IDX_HBYTES   3
#define DUK__IDX_CLASS    4
#define DUK__IDX_PBYTES   5
#define DUK__IDX_ESIZE    6
#define DUK__IDX_ENEXT    7
#define DUK__IDX_ASIZE    8
#define DUK__IDX_HSIZE    9
#define DUK__IDX_BCBYTES  10
#define DUK__IDX_DBYTES   11
#define DUK__IDX_TSTATE   12
#define DUK__IDX_VARIANT  13

DUK_EXTERNAL void duk_inspect_value(duk_hthread *thr, duk_idx_t idx) {
	duk_tval *tv;
	duk_heaphdr *h;
	/* The temporary values should be in an array rather than individual
	 * variables which (in practice) ensures that the compiler won't map
	 * them to registers and emit a lot of unnecessary shuffling code.
	 */
	duk_int_t vals[14];

	DUK_ASSERT_API_ENTRY(thr);

	/* Assume two's complement and set everything to -1. */
	duk_memset((void *) &vals, (int) 0xff, sizeof(vals));
	DUK_ASSERT(vals[DUK__IDX_TYPE] == -1);  /* spot check one */

	tv = duk_get_tval_or_unused(thr, idx);
	h = (DUK_TVAL_IS_HEAP_ALLOCATED(tv) ? DUK_TVAL_GET_HEAPHDR(tv) : NULL);

	vals[DUK__IDX_TYPE] = duk_get_type_tval(tv);
	vals[DUK__IDX_ITAG] = (duk_int_t) DUK_TVAL_GET_TAG(tv);

	duk_push_bare_object(thr);  /* Invalidates 'tv'. */
	tv = NULL;

	if (h == NULL) {
		goto finish;
	}
	duk_push_pointer(thr, (void *) h);
	duk_put_prop_literal(thr, -2, "hptr");

#if 0
	/* Covers a lot of information, e.g. buffer and string variants. */
	duk_push_uint(thr, (duk_uint_t) DUK_HEAPHDR_GET_FLAGS(h));
	duk_put_prop_literal(thr, -2, "hflags");
#endif

#if defined(DUK_USE_REFERENCE_COUNTING)
	vals[DUK__IDX_REFC] = (duk_int_t) DUK_HEAPHDR_GET_REFCOUNT(h);
#endif
	vals[DUK__IDX_VARIANT] = 0;

	/* Heaphdr size and additional allocation size, followed by
	 * type specific stuff (with varying value count).
	 */
	switch ((duk_small_int_t) DUK_HEAPHDR_GET_TYPE(h)) {
	case DUK_HTYPE_STRING: {
		duk_hstring *h_str = (duk_hstring *) h;
		vals[DUK__IDX_HBYTES] = (duk_int_t) (sizeof(duk_hstring) + DUK_HSTRING_GET_BYTELEN(h_str) + 1);
#if defined(DUK_USE_HSTRING_EXTDATA)
		if (DUK_HSTRING_HAS_EXTDATA(h_str)) {
			vals[DUK__IDX_VARIANT] = 1;
		}
#endif
		break;
	}
	case DUK_HTYPE_OBJECT: {
		duk_hobject *h_obj = (duk_hobject *) h;

		/* XXX: variants here are maybe pointless; class is enough? */
		if (DUK_HOBJECT_IS_ARRAY(h_obj)) {
			vals[DUK__IDX_HBYTES] = sizeof(duk_harray);
		} else if (DUK_HOBJECT_IS_COMPFUNC(h_obj)) {
			vals[DUK__IDX_HBYTES] = sizeof(duk_hcompfunc);
		} else if (DUK_HOBJECT_IS_NATFUNC(h_obj)) {
			vals[DUK__IDX_HBYTES] = sizeof(duk_hnatfunc);
		} else if (DUK_HOBJECT_IS_THREAD(h_obj)) {
			vals[DUK__IDX_HBYTES] = sizeof(duk_hthread);
			vals[DUK__IDX_TSTATE] = ((duk_hthread *) h_obj)->state;
#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
		} else if (DUK_HOBJECT_IS_BUFOBJ(h_obj)) {
			vals[DUK__IDX_HBYTES] = sizeof(duk_hbufobj);
			/* XXX: some size information */
#endif
		} else {
			vals[DUK__IDX_HBYTES] = (duk_small_uint_t) sizeof(duk_hobject);
		}

		vals[DUK__IDX_CLASS] = (duk_int_t) DUK_HOBJECT_GET_CLASS_NUMBER(h_obj);
		vals[DUK__IDX_PBYTES] = (duk_int_t) DUK_HOBJECT_P_ALLOC_SIZE(h_obj);
		vals[DUK__IDX_ESIZE] = (duk_int_t) DUK_HOBJECT_GET_ESIZE(h_obj);
		vals[DUK__IDX_ENEXT] = (duk_int_t) DUK_HOBJECT_GET_ENEXT(h_obj);
		vals[DUK__IDX_ASIZE] = (duk_int_t) DUK_HOBJECT_GET_ASIZE(h_obj);
		vals[DUK__IDX_HSIZE] = (duk_int_t) DUK_HOBJECT_GET_HSIZE(h_obj);

		/* Note: e_next indicates the number of gc-reachable entries
		 * in the entry part, and also indicates the index where the
		 * next new property would be inserted.  It does *not* indicate
		 * the number of non-NULL keys present in the object.  That
		 * value could be counted separately but requires a pass through
		 * the key list.
		 */

		if (DUK_HOBJECT_IS_COMPFUNC(h_obj)) {
			duk_hbuffer *h_data = (duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA(thr->heap, (duk_hcompfunc *) h_obj);
			vals[DUK__IDX_BCBYTES] = (duk_int_t) (h_data ? DUK_HBUFFER_GET_SIZE(h_data) : 0);
		}
		break;
	}
	case DUK_HTYPE_BUFFER: {
		duk_hbuffer *h_buf = (duk_hbuffer *) h;

		if (DUK_HBUFFER_HAS_DYNAMIC(h_buf)) {
			if (DUK_HBUFFER_HAS_EXTERNAL(h_buf)) {
				vals[DUK__IDX_VARIANT] = 2;  /* buffer variant 2: external */
				vals[DUK__IDX_HBYTES] = (duk_uint_t) (sizeof(duk_hbuffer_external));
			} else {
				/* When alloc_size == 0 the second allocation may not
				 * actually exist.
				 */
				vals[DUK__IDX_VARIANT] = 1;  /* buffer variant 1: dynamic */
				vals[DUK__IDX_HBYTES] = (duk_uint_t) (sizeof(duk_hbuffer_dynamic));
			}
			vals[DUK__IDX_DBYTES] = (duk_int_t) (DUK_HBUFFER_GET_SIZE(h_buf));
		} else {
			DUK_ASSERT(vals[DUK__IDX_VARIANT] == 0);  /* buffer variant 0: fixed */
			vals[DUK__IDX_HBYTES] = (duk_int_t) (sizeof(duk_hbuffer_fixed) + DUK_HBUFFER_GET_SIZE(h_buf));
		}
		break;
	}
	}

 finish:
	duk__inspect_multiple_uint(thr,
	    "type" "\x00" "itag" "\x00" "refc" "\x00" "hbytes" "\x00" "class" "\x00"
	    "pbytes" "\x00" "esize" "\x00" "enext" "\x00" "asize" "\x00" "hsize" "\x00"
	    "bcbytes" "\x00" "dbytes" "\x00" "tstate" "\x00" "variant" "\x00" "\x00",
	    (duk_int_t *) &vals);
}

DUK_EXTERNAL void duk_inspect_callstack_entry(duk_hthread *thr, duk_int_t level) {
	duk_activation *act;
	duk_uint_fast32_t pc;
	duk_uint_fast32_t line;

	DUK_ASSERT_API_ENTRY(thr);

	/* -1   = top callstack entry
	 * -2   = caller of level -1
	 * etc
	 */
	act = duk_hthread_get_activation_for_level(thr, level);
	if (act == NULL) {
		duk_push_undefined(thr);
		return;
	}
	duk_push_bare_object(thr);

	/* Relevant PC is just before current one because PC is
	 * post-incremented.  This should match what error augment
	 * code does.
	 */
	pc = duk_hthread_get_act_prev_pc(thr, act);

	duk_push_tval(thr, &act->tv_func);

	duk_push_uint(thr, (duk_uint_t) pc);
	duk_put_prop_stridx_short(thr, -3, DUK_STRIDX_PC);

#if defined(DUK_USE_PC2LINE)
	line = duk_hobject_pc2line_query(thr, -1, pc);
#else
	line = 0;
#endif
	duk_push_uint(thr, (duk_uint_t) line);
	duk_put_prop_stridx_short(thr, -3, DUK_STRIDX_LINE_NUMBER);

	duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_LC_FUNCTION);
	/* Providing access to e.g. act->lex_env would be dangerous: these
	 * internal structures must never be accessible to the application.
	 * Duktape relies on them having consistent data, and this consistency
	 * is only asserted for, not checked for.
	 */
}

/* automatic undefs */
#undef DUK__IDX_ASIZE
#undef DUK__IDX_BCBYTES
#undef DUK__IDX_CLASS
#undef DUK__IDX_DBYTES
#undef DUK__IDX_ENEXT
#undef DUK__IDX_ESIZE
#undef DUK__IDX_HBYTES
#undef DUK__IDX_HSIZE
#undef DUK__IDX_ITAG
#undef DUK__IDX_PBYTES
#undef DUK__IDX_REFC
#undef DUK__IDX_TSTATE
#undef DUK__IDX_TYPE
#undef DUK__IDX_VARIANT
#line 1 "duk_api_memory.c"
/*
 *  Memory calls.
 */

/* #include duk_internal.h -> already included */

DUK_EXTERNAL void *duk_alloc_raw(duk_hthread *thr, duk_size_t size) {
	DUK_ASSERT_API_ENTRY(thr);

	return DUK_ALLOC_RAW(thr->heap, size);
}

DUK_EXTERNAL void duk_free_raw(duk_hthread *thr, void *ptr) {
	DUK_ASSERT_API_ENTRY(thr);

	DUK_FREE_RAW(thr->heap, ptr);
}

DUK_EXTERNAL void *duk_realloc_raw(duk_hthread *thr, void *ptr, duk_size_t size) {
	DUK_ASSERT_API_ENTRY(thr);

	return DUK_REALLOC_RAW(thr->heap, ptr, size);
}

DUK_EXTERNAL void *duk_alloc(duk_hthread *thr, duk_size_t size) {
	DUK_ASSERT_API_ENTRY(thr);

	return DUK_ALLOC(thr->heap, size);
}

DUK_EXTERNAL void duk_free(duk_hthread *thr, void *ptr) {
	DUK_ASSERT_API_ENTRY(thr);

	DUK_FREE_CHECKED(thr, ptr);
}

DUK_EXTERNAL void *duk_realloc(duk_hthread *thr, void *ptr, duk_size_t size) {
	DUK_ASSERT_API_ENTRY(thr);

	/*
	 *  Note: since this is an exposed API call, there should be
	 *  no way a mark-and-sweep could have a side effect on the
	 *  memory allocation behind 'ptr'; the pointer should never
	 *  be something that Duktape wants to change.
	 *
	 *  Thus, no need to use DUK_REALLOC_INDIRECT (and we don't
	 *  have the storage location here anyway).
	 */

	return DUK_REALLOC(thr->heap, ptr, size);
}

DUK_EXTERNAL void duk_get_memory_functions(duk_hthread *thr, duk_memory_functions *out_funcs) {
	duk_heap *heap;

	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(out_funcs != NULL);
	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(thr->heap != NULL);

	heap = thr->heap;
	out_funcs->alloc_func = heap->alloc_func;
	out_funcs->realloc_func = heap->realloc_func;
	out_funcs->free_func = heap->free_func;
	out_funcs->udata = heap->heap_udata;
}

DUK_EXTERNAL void duk_gc(duk_hthread *thr, duk_uint_t flags) {
	duk_heap *heap;
	duk_small_uint_t ms_flags;

	DUK_ASSERT_API_ENTRY(thr);
	heap = thr->heap;
	DUK_ASSERT(heap != NULL);

	DUK_D(DUK_DPRINT("mark-and-sweep requested by application"));
	DUK_ASSERT(DUK_GC_COMPACT == DUK_MS_FLAG_EMERGENCY);  /* Compact flag is 1:1 with emergency flag which forces compaction. */
	ms_flags = (duk_small_uint_t) flags;
	duk_heap_mark_and_sweep(heap, ms_flags);
}
#line 1 "duk_api_object.c"
/*
 *  Object handling: property access and other support functions.
 */

/* #include duk_internal.h -> already included */

/*
 *  Property handling
 *
 *  The API exposes only the most common property handling functions.
 *  The caller can invoke ECMAScript built-ins for full control (e.g.
 *  defineProperty, getOwnPropertyDescriptor).
 */

DUK_EXTERNAL duk_bool_t duk_get_prop(duk_hthread *thr, duk_idx_t obj_idx) {
	duk_tval *tv_obj;
	duk_tval *tv_key;
	duk_bool_t rc;

	DUK_ASSERT_API_ENTRY(thr);

	/* Note: copying tv_obj and tv_key to locals to shield against a valstack
	 * resize is not necessary for a property get right now.
	 */

	tv_obj = duk_require_tval(thr, obj_idx);
	tv_key = duk_require_tval(thr, -1);

	rc = duk_hobject_getprop(thr, tv_obj, tv_key);
	DUK_ASSERT(rc == 0 || rc == 1);
	/* a value is left on stack regardless of rc */

	duk_remove_m2(thr);  /* remove key */
	DUK_ASSERT(duk_is_undefined(thr, -1) || rc == 1);
	return rc;  /* 1 if property found, 0 otherwise */
}

DUK_EXTERNAL duk_bool_t duk_get_prop_string(duk_hthread *thr, duk_idx_t obj_idx, const char *key) {
	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(key != NULL);

	obj_idx = duk_require_normalize_index(thr, obj_idx);
	(void) duk_push_string(thr, key);
	return duk_get_prop(thr, obj_idx);
}

DUK_EXTERNAL duk_bool_t duk_get_prop_lstring(duk_hthread *thr, duk_idx_t obj_idx, const char *key, duk_size_t key_len) {
	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(key != NULL);

	obj_idx = duk_require_normalize_index(thr, obj_idx);
	(void) duk_push_lstring(thr, key, key_len);
	return duk_get_prop(thr, obj_idx);
}

#if !defined(DUK_USE_PREFER_SIZE)
DUK_EXTERNAL duk_bool_t duk_get_prop_literal_raw(duk_hthread *thr, duk_idx_t obj_idx, const char *key, duk_size_t key_len) {
	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(key != NULL);
	DUK_ASSERT(key[key_len] == (char) 0);

	obj_idx = duk_require_normalize_index(thr, obj_idx);
	(void) duk_push_literal_raw(thr, key, key_len);
	return duk_get_prop(thr, obj_idx);
}
#endif

DUK_EXTERNAL duk_bool_t duk_get_prop_index(duk_hthread *thr, duk_idx_t obj_idx, duk_uarridx_t arr_idx) {
	DUK_ASSERT_API_ENTRY(thr);

	obj_idx = duk_require_normalize_index(thr, obj_idx);
	duk_push_uarridx(thr, arr_idx);
	return duk_get_prop(thr, obj_idx);
}

DUK_EXTERNAL duk_bool_t duk_get_prop_heapptr(duk_hthread *thr, duk_idx_t obj_idx, void *ptr) {
	DUK_ASSERT_API_ENTRY(thr);

	obj_idx = duk_require_normalize_index(thr, obj_idx);
	(void) duk_push_heapptr(thr, ptr);  /* NULL -> 'undefined' */
	return duk_get_prop(thr, obj_idx);
}

DUK_INTERNAL duk_bool_t duk_get_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx) {
	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT_STRIDX_VALID(stridx);

	obj_idx = duk_require_normalize_index(thr, obj_idx);
	(void) duk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, stridx));
	return duk_get_prop(thr, obj_idx);
}

DUK_INTERNAL duk_bool_t duk_get_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args) {
	return duk_get_prop_stridx(thr, (duk_idx_t) (duk_int16_t) (packed_args >> 16),
	                                (duk_small_uint_t) (packed_args & 0xffffUL));
}

DUK_INTERNAL duk_bool_t duk_get_prop_stridx_boolean(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx, duk_bool_t *out_has_prop) {
	duk_bool_t rc;

	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT_STRIDX_VALID(stridx);

	rc = duk_get_prop_stridx(thr, obj_idx, stridx);
	if (out_has_prop) {
		*out_has_prop = rc;
	}
	return duk_to_boolean_top_pop(thr);
}

/* This get variant is for internal use, it differs from standard
 * duk_get_prop() in that:
 *   - Object argument must be an object (primitive values not supported).
 *   - Key argument must be a string (no coercion).
 *   - Only own properties are checked (no inheritance).  Only "entry part"
 *     properties are checked (not array index properties).
 *   - Property must be a plain data property, not a getter.
 *   - Proxy traps are not triggered.
 */
DUK_INTERNAL duk_bool_t duk_xget_owndataprop(duk_hthread *thr, duk_idx_t obj_idx) {
	duk_hobject *h_obj;
	duk_hstring *h_key;
	duk_tval *tv_val;

	DUK_ASSERT_API_ENTRY(thr);

	/* Note: copying tv_obj and tv_key to locals to shield against a valstack
	 * resize is not necessary for a property get right now.
	 */

	h_obj = duk_get_hobject(thr, obj_idx);
	if (h_obj == NULL) {
		return 0;
	}
	h_key = duk_require_hstring(thr, -1);

	tv_val = duk_hobject_find_entry_tval_ptr(thr->heap, h_obj, h_key);
	if (tv_val == NULL) {
		return 0;
	}

	duk_push_tval(thr, tv_val);
	duk_remove_m2(thr);  /* remove key */

	return 1;
}

DUK_INTERNAL duk_bool_t duk_xget_owndataprop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx) {
	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT_STRIDX_VALID(stridx);

	obj_idx = duk_require_normalize_index(thr, obj_idx);
	(void) duk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, stridx));
	return duk_xget_owndataprop(thr, obj_idx);
}

DUK_INTERNAL duk_bool_t duk_xget_owndataprop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args) {
	return duk_xget_owndataprop_stridx(thr, (duk_idx_t) (duk_int16_t) (packed_args >> 16),
	                                   (duk_small_uint_t) (packed_args & 0xffffUL));
}

DUK_LOCAL duk_bool_t duk__put_prop_shared(duk_hthread *thr, duk_idx_t obj_idx, duk_idx_t idx_key) {
	duk_tval *tv_obj;
	duk_tval *tv_key;
	duk_tval *tv_val;
	duk_bool_t throw_flag;
	duk_bool_t rc;

	/* Note: copying tv_obj and tv_key to locals to shield against a valstack
	 * resize is not necessary for a property put right now (putprop protects
	 * against it internally).
	 */

	/* Key and value indices are either (-2, -1) or (-1, -2).  Given idx_key,
	 * idx_val is always (idx_key ^ 0x01).
	 */
	DUK_ASSERT((idx_key == -2 && (idx_key ^ 1) == -1) ||
	           (idx_key == -1 && (idx_key ^ 1) == -2));
	/* XXX: Direct access; faster validation. */
	tv_obj = duk_require_tval(thr, obj_idx);
	tv_key = duk_require_tval(thr, idx_key);
	tv_val = duk_require_tval(thr, idx_key ^ 1);
	throw_flag = duk_is_strict_call(thr);

	rc = duk_hobject_putprop(thr, tv_obj, tv_key, tv_val, throw_flag);
	DUK_ASSERT(rc == 0 || rc == 1);

	duk_pop_2(thr);  /* remove key and value */
	return rc;  /* 1 if property found, 0 otherwise */
}

DUK_EXTERNAL duk_bool_t duk_put_prop(duk_hthread *thr, duk_idx_t obj_idx) {
	DUK_ASSERT_API_ENTRY(thr);
	return duk__put_prop_shared(thr, obj_idx, -2);
}

DUK_EXTERNAL duk_bool_t duk_put_prop_string(duk_hthread *thr, duk_idx_t obj_idx, const char *key) {
	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(key != NULL);

	/* Careful here and with other duk_put_prop_xxx() helpers: the
	 * target object and the property value may be in the same value
	 * stack slot (unusual, but still conceptually clear).
	 */
	obj_idx = duk_normalize_index(thr, obj_idx);
	(void) duk_push_string(thr, key);
	return duk__put_prop_shared(thr, obj_idx, -1);
}

DUK_EXTERNAL duk_bool_t duk_put_prop_lstring(duk_hthread *thr, duk_idx_t obj_idx, const char *key, duk_size_t key_len) {
	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(key != NULL);

	obj_idx = duk_normalize_index(thr, obj_idx);
	(void) duk_push_lstring(thr, key, key_len);
	return duk__put_prop_shared(thr, obj_idx, -1);
}

#if !defined(DUK_USE_PREFER_SIZE)
DUK_EXTERNAL duk_bool_t duk_put_prop_literal_raw(duk_hthread *thr, duk_idx_t obj_idx, const char *key, duk_size_t key_len) {
	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(key != NULL);
	DUK_ASSERT(key[key_len] == (char) 0);

	obj_idx = duk_normalize_index(thr, obj_idx);
	(void) duk_push_literal_raw(thr, key, key_len);
	return duk__put_prop_shared(thr, obj_idx, -1);
}
#endif

DUK_EXTERNAL duk_bool_t duk_put_prop_index(duk_hthread *thr, duk_idx_t obj_idx, duk_uarridx_t arr_idx) {
	DUK_ASSERT_API_ENTRY(thr);

	obj_idx = duk_require_normalize_index(thr, obj_idx);
	duk_push_uarridx(thr, arr_idx);
	return duk__put_prop_shared(thr, obj_idx, -1);
}

DUK_EXTERNAL duk_bool_t duk_put_prop_heapptr(duk_hthread *thr, duk_idx_t obj_idx, void *ptr) {
	DUK_ASSERT_API_ENTRY(thr);

	obj_idx = duk_require_normalize_index(thr, obj_idx);
	(void) duk_push_heapptr(thr, ptr);  /* NULL -> 'undefined' */
	return duk__put_prop_shared(thr, obj_idx, -1);
}


DUK_INTERNAL duk_bool_t duk_put_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx) {
	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT_STRIDX_VALID(stridx);

	obj_idx = duk_require_normalize_index(thr, obj_idx);
	duk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, stridx));
	return duk__put_prop_shared(thr, obj_idx, -1);
}

DUK_INTERNAL duk_bool_t duk_put_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args) {
	return duk_put_prop_stridx(thr, (duk_idx_t) (duk_int16_t) (packed_args >> 16),
	                                (duk_small_uint_t) (packed_args & 0xffffUL));
}

DUK_EXTERNAL duk_bool_t duk_del_prop(duk_hthread *thr, duk_idx_t obj_idx) {
	duk_tval *tv_obj;
	duk_tval *tv_key;
	duk_bool_t throw_flag;
	duk_bool_t rc;

	DUK_ASSERT_API_ENTRY(thr);

	/* Note: copying tv_obj and tv_key to locals to shield against a valstack
	 * resize is not necessary for a property delete right now.
	 */

	tv_obj = duk_require_tval(thr, obj_idx);
	tv_key = duk_require_tval(thr, -1);
	throw_flag = duk_is_strict_call(thr);

	rc = duk_hobject_delprop(thr, tv_obj, tv_key, throw_flag);
	DUK_ASSERT(rc == 0 || rc == 1);

	duk_pop(thr);  /* remove key */
	return rc;
}

DUK_EXTERNAL duk_bool_t duk_del_prop_string(duk_hthread *thr, duk_idx_t obj_idx, const char *key) {
	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(key != NULL);

	obj_idx = duk_require_normalize_index(thr, obj_idx);
	(void) duk_push_string(thr, key);
	return duk_del_prop(thr, obj_idx);
}

DUK_EXTERNAL duk_bool_t duk_del_prop_lstring(duk_hthread *thr, duk_idx_t obj_idx, const char *key, duk_size_t key_len) {
	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(key != NULL);

	obj_idx = duk_require_normalize_index(thr, obj_idx);
	(void) duk_push_lstring(thr, key, key_len);
	return duk_del_prop(thr, obj_idx);
}

#if !defined(DUK_USE_PREFER_SIZE)
DUK_EXTERNAL duk_bool_t duk_del_prop_literal_raw(duk_hthread *thr, duk_idx_t obj_idx, const char *key, duk_size_t key_len) {
	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(key != NULL);
	DUK_ASSERT(key[key_len] == (char) 0);

	obj_idx = duk_require_normalize_index(thr, obj_idx);
	(void) duk_push_literal_raw(thr, key, key_len);
	return duk_del_prop(thr, obj_idx);
}
#endif

DUK_EXTERNAL duk_bool_t duk_del_prop_index(duk_hthread *thr, duk_idx_t obj_idx, duk_uarridx_t arr_idx) {
	DUK_ASSERT_API_ENTRY(thr);

	obj_idx = duk_require_normalize_index(thr, obj_idx);
	duk_push_uarridx(thr, arr_idx);
	return duk_del_prop(thr, obj_idx);
}

DUK_EXTERNAL duk_bool_t duk_del_prop_heapptr(duk_hthread *thr, duk_idx_t obj_idx, void *ptr) {
	DUK_ASSERT_API_ENTRY(thr);

	obj_idx = duk_require_normalize_index(thr, obj_idx);
	(void) duk_push_heapptr(thr, ptr);  /* NULL -> 'undefined' */
	return duk_del_prop(thr, obj_idx);
}

DUK_INTERNAL duk_bool_t duk_del_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx) {
	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT_STRIDX_VALID(stridx);

	obj_idx = duk_require_normalize_index(thr, obj_idx);
	duk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, stridx));
	return duk_del_prop(thr, obj_idx);
}

#if 0
DUK_INTERNAL duk_bool_t duk_del_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args) {
	return duk_del_prop_stridx(thr, (duk_idx_t) (duk_int16_t) (packed_args >> 16),
	                                (duk_small_uint_t) (packed_args & 0xffffUL));
}
#endif

DUK_EXTERNAL duk_bool_t duk_has_prop(duk_hthread *thr, duk_idx_t obj_idx) {
	duk_tval *tv_obj;
	duk_tval *tv_key;
	duk_bool_t rc;

	DUK_ASSERT_API_ENTRY(thr);

	/* Note: copying tv_obj and tv_key to locals to shield against a valstack
	 * resize is not necessary for a property existence check right now.
	 */

	tv_obj = duk_require_tval(thr, obj_idx);
	tv_key = duk_require_tval(thr, -1);

	rc = duk_hobject_hasprop(thr, tv_obj, tv_key);
	DUK_ASSERT(rc == 0 || rc == 1);

	duk_pop(thr);  /* remove key */
	return rc;  /* 1 if property found, 0 otherwise */
}

DUK_EXTERNAL duk_bool_t duk_has_prop_string(duk_hthread *thr, duk_idx_t obj_idx, const char *key) {
	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(key != NULL);

	obj_idx = duk_require_normalize_index(thr, obj_idx);
	(void) duk_push_string(thr, key);
	return duk_has_prop(thr, obj_idx);
}

DUK_EXTERNAL duk_bool_t duk_has_prop_lstring(duk_hthread *thr, duk_idx_t obj_idx, const char *key, duk_size_t key_len) {
	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(key != NULL);

	obj_idx = duk_require_normalize_index(thr, obj_idx);
	(void) duk_push_lstring(thr, key, key_len);
	return duk_has_prop(thr, obj_idx);
}

#if !defined(DUK_USE_PREFER_SIZE)
DUK_EXTERNAL duk_bool_t duk_has_prop_literal_raw(duk_hthread *thr, duk_idx_t obj_idx, const char *key, duk_size_t key_len) {
	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(key != NULL);
	DUK_ASSERT(key[key_len] == (char) 0);

	obj_idx = duk_require_normalize_index(thr, obj_idx);
	(void) duk_push_literal_raw(thr, key, key_len);
	return duk_has_prop(thr, obj_idx);
}
#endif

DUK_EXTERNAL duk_bool_t duk_has_prop_index(duk_hthread *thr, duk_idx_t obj_idx, duk_uarridx_t arr_idx) {
	DUK_ASSERT_API_ENTRY(thr);

	obj_idx = duk_require_normalize_index(thr, obj_idx);
	duk_push_uarridx(thr, arr_idx);
	return duk_has_prop(thr, obj_idx);
}

DUK_EXTERNAL duk_bool_t duk_has_prop_heapptr(duk_hthread *thr, duk_idx_t obj_idx, void *ptr) {
	DUK_ASSERT_API_ENTRY(thr);

	obj_idx = duk_require_normalize_index(thr, obj_idx);
	(void) duk_push_heapptr(thr, ptr);  /* NULL -> 'undefined' */
	return duk_has_prop(thr, obj_idx);
}

DUK_INTERNAL duk_bool_t duk_has_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx) {
	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT_STRIDX_VALID(stridx);

	obj_idx = duk_require_normalize_index(thr, obj_idx);
	duk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, stridx));
	return duk_has_prop(thr, obj_idx);
}

#if 0
DUK_INTERNAL duk_bool_t duk_has_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args) {
	return duk_has_prop_stridx(thr, (duk_idx_t) (duk_int16_t) (packed_args >> 16),
	                                (duk_small_uint_t) (packed_args & 0xffffUL));
}
#endif

/* Define own property without inheritance lookups and such.  This differs from
 * [[DefineOwnProperty]] because special behaviors (like Array 'length') are
 * not invoked by this method.  The caller must be careful to invoke any such
 * behaviors if necessary.
 */
DUK_INTERNAL void duk_xdef_prop(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t desc_flags) {
	duk_hobject *obj;
	duk_hstring *key;

	DUK_ASSERT_API_ENTRY(thr);

	obj = duk_require_hobject(thr, obj_idx);
	DUK_ASSERT(obj != NULL);
	key = duk_to_property_key_hstring(thr, -2);
	DUK_ASSERT(key != NULL);
	DUK_ASSERT(duk_require_tval(thr, -1) != NULL);

	duk_hobject_define_property_internal(thr, obj, key, desc_flags);

	duk_pop(thr);  /* pop key */
}

DUK_INTERNAL void duk_xdef_prop_index(duk_hthread *thr, duk_idx_t obj_idx, duk_uarridx_t arr_idx, duk_small_uint_t desc_flags) {
	duk_hobject *obj;

	DUK_ASSERT_API_ENTRY(thr);

	obj = duk_require_hobject(thr, obj_idx);
	DUK_ASSERT(obj != NULL);

	duk_hobject_define_property_internal_arridx(thr, obj, arr_idx, desc_flags);
	/* value popped by call */
}

DUK_INTERNAL void duk_xdef_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx, duk_small_uint_t desc_flags) {
	duk_hobject *obj;
	duk_hstring *key;

	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT_STRIDX_VALID(stridx);

	obj = duk_require_hobject(thr, obj_idx);
	DUK_ASSERT(obj != NULL);
	key = DUK_HTHREAD_GET_STRING(thr, stridx);
	DUK_ASSERT(key != NULL);
	DUK_ASSERT(duk_require_tval(thr, -1) != NULL);

	duk_hobject_define_property_internal(thr, obj, key, desc_flags);
	/* value popped by call */
}

DUK_INTERNAL void duk_xdef_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args) {
	duk_xdef_prop_stridx(thr, (duk_idx_t) (duk_int8_t) (packed_args >> 24),
	                          (duk_small_uint_t) (packed_args >> 8) & 0xffffUL,
	                          (duk_small_uint_t) (packed_args & 0xffL));
}

#if 0  /*unused*/
DUK_INTERNAL void duk_xdef_prop_stridx_builtin(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx, duk_small_int_t builtin_idx, duk_small_uint_t desc_flags) {
	duk_hobject *obj;
	duk_hstring *key;

	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT_STRIDX_VALID(stridx);
	DUK_ASSERT_BIDX_VALID(builtin_idx);

	obj = duk_require_hobject(thr, obj_idx);
	DUK_ASSERT(obj != NULL);
	key = DUK_HTHREAD_GET_STRING(thr, stridx);
	DUK_ASSERT(key != NULL);

	duk_push_hobject(thr, thr->builtins[builtin_idx]);
	duk_hobject_define_property_internal(thr, obj, key, desc_flags);
	/* value popped by call */
}
#endif

/* This is a rare property helper; it sets the global thrower (E5 Section 13.2.3)
 * setter/getter into an object property.  This is needed by the 'arguments'
 * object creation code, function instance creation code, and Function.prototype.bind().
 */

DUK_INTERNAL void duk_xdef_prop_stridx_thrower(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx) {
	DUK_ASSERT_API_ENTRY(thr);

	obj_idx = duk_require_normalize_index(thr, obj_idx);
	duk_push_hstring_stridx(thr, stridx);
	duk_push_hobject_bidx(thr, DUK_BIDX_TYPE_ERROR_THROWER);
	duk_dup_top(thr);
	duk_def_prop(thr, obj_idx, DUK_DEFPROP_HAVE_SETTER | DUK_DEFPROP_HAVE_GETTER | DUK_DEFPROP_FORCE);  /* attributes always 0 */
}

/* Object.getOwnPropertyDescriptor() equivalent C binding. */
DUK_EXTERNAL void duk_get_prop_desc(duk_hthread *thr, duk_idx_t obj_idx, duk_uint_t flags) {
	DUK_ASSERT_API_ENTRY(thr);
	DUK_UNREF(flags);  /* no flags defined yet */

	duk_hobject_object_get_own_property_descriptor(thr, obj_idx);  /* [ ... key ] -> [ ... desc ] */
}

/* Object.defineProperty() equivalent C binding. */
DUK_EXTERNAL void duk_def_prop(duk_hthread *thr, duk_idx_t obj_idx, duk_uint_t flags) {
	duk_idx_t idx_base;
	duk_hobject *obj;
	duk_hstring *key;
	duk_idx_t idx_value;
	duk_hobject *get;
	duk_hobject *set;
	duk_uint_t is_data_desc;
	duk_uint_t is_acc_desc;

	DUK_ASSERT_API_ENTRY(thr);

	obj = duk_require_hobject(thr, obj_idx);

	is_data_desc = flags & (DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_HAVE_WRITABLE);
	is_acc_desc = flags & (DUK_DEFPROP_HAVE_GETTER | DUK_DEFPROP_HAVE_SETTER);
	if (is_data_desc && is_acc_desc) {
		/* "Have" flags must not be conflicting so that they would
		 * apply to both a plain property and an accessor at the same
		 * time.
		 */
		goto fail_invalid_desc;
	}

	idx_base = duk_get_top_index(thr);
	if (flags & DUK_DEFPROP_HAVE_SETTER) {
		duk_require_type_mask(thr, idx_base, DUK_TYPE_MASK_UNDEFINED |
		                                     DUK_TYPE_MASK_OBJECT |
		                                     DUK_TYPE_MASK_LIGHTFUNC);
		set = duk_get_hobject_promote_lfunc(thr, idx_base);
		if (set != NULL && !DUK_HOBJECT_IS_CALLABLE(set)) {
			goto fail_not_callable;
		}
		idx_base--;
	} else {
		set = NULL;
	}
	if (flags & DUK_DEFPROP_HAVE_GETTER) {
		duk_require_type_mask(thr, idx_base, DUK_TYPE_MASK_UNDEFINED |
		                                     DUK_TYPE_MASK_OBJECT |
		                                     DUK_TYPE_MASK_LIGHTFUNC);
		get = duk_get_hobject_promote_lfunc(thr, idx_base);
		if (get != NULL && !DUK_HOBJECT_IS_CALLABLE(get)) {
			goto fail_not_callable;
		}
		idx_base--;
	} else {
		get = NULL;
	}
	if (flags & DUK_DEFPROP_HAVE_VALUE) {
		idx_value = idx_base;
		idx_base--;
	} else {
		idx_value = (duk_idx_t) -1;
	}
	key = duk_to_property_key_hstring(thr, idx_base);
	DUK_ASSERT(key != NULL);

	duk_require_valid_index(thr, idx_base);

	duk_hobject_define_property_helper(thr,
	                                   flags /*defprop_flags*/,
	                                   obj,
	                                   key,
	                                   idx_value,
	                                   get,
	                                   set,
	                                   1 /*throw_flag*/);

	/* Clean up stack */

	duk_set_top(thr, idx_base);

	/* [ ... obj ... ] */

	return;

 fail_invalid_desc:
	DUK_ERROR_TYPE(thr, DUK_STR_INVALID_DESCRIPTOR);
	DUK_WO_NORETURN(return;);

 fail_not_callable:
	DUK_ERROR_TYPE(thr, DUK_STR_NOT_CALLABLE);
	DUK_WO_NORETURN(return;);
}

/*
 *  Object related
 */

DUK_EXTERNAL void duk_compact(duk_hthread *thr, duk_idx_t obj_idx) {
	duk_hobject *obj;

	DUK_ASSERT_API_ENTRY(thr);

	obj = duk_get_hobject(thr, obj_idx);
	if (obj) {
		/* Note: this may fail, caller should protect the call if necessary */
		duk_hobject_compact_props(thr, obj);
	}
}

DUK_INTERNAL void duk_compact_m1(duk_hthread *thr) {
	DUK_ASSERT_API_ENTRY(thr);

	duk_compact(thr, -1);
}

/* XXX: the duk_hobject_enum.c stack APIs should be reworked */

DUK_EXTERNAL void duk_enum(duk_hthread *thr, duk_idx_t obj_idx, duk_uint_t enum_flags) {
	DUK_ASSERT_API_ENTRY(thr);

	duk_dup(thr, obj_idx);
	duk_require_hobject_promote_mask(thr, -1, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
	duk_hobject_enumerator_create(thr, enum_flags);   /* [target] -> [enum] */
}

DUK_EXTERNAL duk_bool_t duk_next(duk_hthread *thr, duk_idx_t enum_index, duk_bool_t get_value) {
	DUK_ASSERT_API_ENTRY(thr);

	duk_require_hobject(thr, enum_index);
	duk_dup(thr, enum_index);
	return duk_hobject_enumerator_next(thr, get_value);
}

DUK_INTERNAL void duk_seal_freeze_raw(duk_hthread *thr, duk_idx_t obj_idx, duk_bool_t is_freeze) {
	duk_tval *tv;
	duk_hobject *h;

	DUK_ASSERT_API_ENTRY(thr);

	tv = duk_require_tval(thr, obj_idx);
	DUK_ASSERT(tv != NULL);

	/* Seal/freeze are quite rare in practice so it'd be nice to get the
	 * correct behavior simply via automatic promotion (at the cost of some
	 * memory churn).  However, the promoted objects don't behave the same,
	 * e.g. promoted lightfuncs are extensible.
	 */

	switch (DUK_TVAL_GET_TAG(tv)) {
	case DUK_TAG_BUFFER:
		/* Plain buffer: already sealed, but not frozen (and can't be frozen
		 * because index properties can't be made non-writable.
		 */
		if (is_freeze) {
			goto fail_cannot_freeze;
		}
		break;
	case DUK_TAG_LIGHTFUNC:
		/* Lightfunc: already sealed and frozen, success. */
		break;
	case DUK_TAG_OBJECT:
		h = DUK_TVAL_GET_OBJECT(tv);
		DUK_ASSERT(h != NULL);
		if (is_freeze && DUK_HOBJECT_IS_BUFOBJ(h)) {
			/* Buffer objects cannot be frozen because there's no internal
			 * support for making virtual array indices non-writable.
			 */
			DUK_DD(DUK_DDPRINT("cannot freeze a buffer object"));
			goto fail_cannot_freeze;
		}
		duk_hobject_object_seal_freeze_helper(thr, h, is_freeze);

		/* Sealed and frozen objects cannot gain any more properties,
		 * so this is a good time to compact them.
		 */
		duk_hobject_compact_props(thr, h);
		break;
	default:
		/* ES2015 Sections 19.1.2.5, 19.1.2.17 */
		break;
	}
	return;

 fail_cannot_freeze:
	DUK_ERROR_TYPE_INVALID_ARGS(thr);  /* XXX: proper error message */
	DUK_WO_NORETURN(return;);
}

DUK_EXTERNAL void duk_seal(duk_hthread *thr, duk_idx_t obj_idx) {
	DUK_ASSERT_API_ENTRY(thr);

	duk_seal_freeze_raw(thr, obj_idx, 0 /*is_freeze*/);
}

DUK_EXTERNAL void duk_freeze(duk_hthread *thr, duk_idx_t obj_idx) {
	DUK_ASSERT_API_ENTRY(thr);

	duk_seal_freeze_raw(thr, obj_idx, 1 /*is_freeze*/);
}

/*
 *  Helpers for writing multiple properties
 */

DUK_EXTERNAL void duk_put_function_list(duk_hthread *thr, duk_idx_t obj_idx, const duk_function_list_entry *funcs) {
	const duk_function_list_entry *ent = funcs;

	DUK_ASSERT_API_ENTRY(thr);

	obj_idx = duk_require_normalize_index(thr, obj_idx);
	if (ent != NULL) {
		while (ent->key != NULL) {
			duk_push_c_function(thr, ent->value, ent->nargs);
			duk_put_prop_string(thr, obj_idx, ent->key);
			ent++;
		}
	}
}

DUK_EXTERNAL void duk_put_number_list(duk_hthread *thr, duk_idx_t obj_idx, const duk_number_list_entry *numbers) {
	const duk_number_list_entry *ent = numbers;
	duk_tval *tv;

	DUK_ASSERT_API_ENTRY(thr);

	obj_idx = duk_require_normalize_index(thr, obj_idx);
	if (ent != NULL) {
		while (ent->key != NULL) {
			tv = thr->valstack_top++;
			DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv));  /* value stack init policy */
			DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv, ent->value);  /* no need for decref/incref */
			duk_put_prop_string(thr, obj_idx, ent->key);
			ent++;
		}
	}
}

/*
 *  Shortcut for accessing global object properties
 */

DUK_EXTERNAL duk_bool_t duk_get_global_string(duk_hthread *thr, const char *key) {
	duk_bool_t ret;

	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);

	/* XXX: direct implementation */

	duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);
	ret = duk_get_prop_string(thr, -1, key);
	duk_remove_m2(thr);
	return ret;
}

DUK_EXTERNAL duk_bool_t duk_get_global_lstring(duk_hthread *thr, const char *key, duk_size_t key_len) {
	duk_bool_t ret;

	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);

	/* XXX: direct implementation */

	duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);
	ret = duk_get_prop_lstring(thr, -1, key, key_len);
	duk_remove_m2(thr);
	return ret;
}

#if !defined(DUK_USE_PREFER_SIZE)
DUK_EXTERNAL duk_bool_t duk_get_global_literal_raw(duk_hthread *thr, const char *key, duk_size_t key_len) {
	duk_bool_t ret;

	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
	DUK_ASSERT(key[key_len] == (char) 0);

	/* XXX: direct implementation */

	duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);
	ret = duk_get_prop_literal_raw(thr, -1, key, key_len);
	duk_remove_m2(thr);
	return ret;
}
#endif

DUK_EXTERNAL duk_bool_t duk_get_global_heapptr(duk_hthread *thr, void *ptr) {
	duk_bool_t ret;

	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);

	/* XXX: direct implementation */

	duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);
	ret = duk_get_prop_heapptr(thr, -1, ptr);
	duk_remove_m2(thr);
	return ret;
}


DUK_EXTERNAL duk_bool_t duk_put_global_string(duk_hthread *thr, const char *key) {
	duk_bool_t ret;

	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);

	/* XXX: direct implementation */

	duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);
	duk_insert(thr, -2);
	ret = duk_put_prop_string(thr, -2, key);  /* [ ... global val ] -> [ ... global ] */
	duk_pop(thr);
	return ret;
}

DUK_EXTERNAL duk_bool_t duk_put_global_lstring(duk_hthread *thr, const char *key, duk_size_t key_len) {
	duk_bool_t ret;

	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);

	/* XXX: direct implementation */

	duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);
	duk_insert(thr, -2);
	ret = duk_put_prop_lstring(thr, -2, key, key_len);  /* [ ... global val ] -> [ ... global ] */
	duk_pop(thr);
	return ret;
}

#if !defined(DUK_USE_PREFER_SIZE)
DUK_EXTERNAL duk_bool_t duk_put_global_literal_raw(duk_hthread *thr, const char *key, duk_size_t key_len) {
	duk_bool_t ret;

	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
	DUK_ASSERT(key[key_len] == (char) 0);

	/* XXX: direct implementation */

	duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);
	duk_insert(thr, -2);
	ret = duk_put_prop_literal_raw(thr, -2, key, key_len);  /* [ ... global val ] -> [ ... global ] */
	duk_pop(thr);
	return ret;
}
#endif

DUK_EXTERNAL duk_bool_t duk_put_global_heapptr(duk_hthread *thr, void *ptr) {
	duk_bool_t ret;

	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);

	/* XXX: direct implementation */

	duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);
	duk_insert(thr, -2);
	ret = duk_put_prop_heapptr(thr, -2, ptr);  /* [ ... global val ] -> [ ... global ] */
	duk_pop(thr);
	return ret;
}

/*
 *  ES2015 GetMethod()
 */

DUK_INTERNAL duk_bool_t duk_get_method_stridx(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t stridx) {
	(void) duk_get_prop_stridx(thr, idx, stridx);
	if (duk_is_null_or_undefined(thr, -1)) {
		duk_pop_nodecref_unsafe(thr);
		return 0;
	}
	if (!duk_is_callable(thr, -1)) {
		DUK_ERROR_TYPE(thr, DUK_STR_NOT_CALLABLE);
		DUK_WO_NORETURN(return 0;);
	}
	return 1;
}

/*
 *  Object prototype
 */

DUK_EXTERNAL void duk_get_prototype(duk_hthread *thr, duk_idx_t idx) {
	duk_hobject *obj;
	duk_hobject *proto;

	DUK_ASSERT_API_ENTRY(thr);

	obj = duk_require_hobject(thr, idx);
	DUK_ASSERT(obj != NULL);

	/* XXX: shared helper for duk_push_hobject_or_undefined()? */
	proto = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, obj);
	if (proto) {
		duk_push_hobject(thr, proto);
	} else {
		duk_push_undefined(thr);
	}
}

DUK_EXTERNAL void duk_set_prototype(duk_hthread *thr, duk_idx_t idx) {
	duk_hobject *obj;
	duk_hobject *proto;

	DUK_ASSERT_API_ENTRY(thr);

	obj = duk_require_hobject(thr, idx);
	DUK_ASSERT(obj != NULL);
	duk_require_type_mask(thr, -1, DUK_TYPE_MASK_UNDEFINED |
	                               DUK_TYPE_MASK_OBJECT);
	proto = duk_get_hobject(thr, -1);
	/* proto can also be NULL here (allowed explicitly) */

#if defined(DUK_USE_ROM_OBJECTS)
	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {
		DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);  /* XXX: "read only object"? */
		DUK_WO_NORETURN(return;);
	}
#endif

	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, obj, proto);

	duk_pop(thr);
}

DUK_INTERNAL void duk_clear_prototype(duk_hthread *thr, duk_idx_t idx) {
	duk_hobject *obj;

	DUK_ASSERT_API_ENTRY(thr);

	obj = duk_require_hobject(thr, idx);
	DUK_ASSERT(obj != NULL);

#if defined(DUK_USE_ROM_OBJECTS)
	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {
		DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);  /* XXX: "read only object"? */
		DUK_WO_NORETURN(return;);
	}
#endif

	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, obj, NULL);
}

DUK_INTERNAL duk_bool_t duk_is_bare_object(duk_hthread *thr, duk_idx_t idx) {
	duk_hobject *obj;
	duk_hobject *proto;

	DUK_ASSERT_API_ENTRY(thr);

	obj = duk_require_hobject(thr, idx);
	DUK_ASSERT(obj != NULL);

	proto = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, obj);
	return (proto == NULL);
}

/*
 *  Object finalizer
 */

#if defined(DUK_USE_FINALIZER_SUPPORT)
/* XXX: these could be implemented as macros calling an internal function
 * directly.
 * XXX: same issue as with Duktape.fin: there's no way to delete the property
 * now (just set it to undefined).
 */
DUK_EXTERNAL void duk_get_finalizer(duk_hthread *thr, duk_idx_t idx) {
	DUK_ASSERT_API_ENTRY(thr);

	/* This get intentionally walks the inheritance chain at present,
	 * which matches how the effective finalizer property is also
	 * looked up in GC.
	 */
	duk_get_prop_stridx(thr, idx, DUK_STRIDX_INT_FINALIZER);
}

DUK_EXTERNAL void duk_set_finalizer(duk_hthread *thr, duk_idx_t idx) {
	duk_hobject *h;
	duk_bool_t callable;

	DUK_ASSERT_API_ENTRY(thr);

	h = duk_require_hobject(thr, idx);  /* Get before 'put' so that 'idx' is correct. */
	callable = duk_is_callable(thr, -1);

	/* At present finalizer is stored as a hidden Symbol, with normal
	 * inheritance and access control.  As a result, finalizer cannot
	 * currently be set on a non-extensible (sealed or frozen) object.
	 * It might be useful to allow it.
	 */
	duk_put_prop_stridx(thr, idx, DUK_STRIDX_INT_FINALIZER);

	/* In addition to setting the finalizer property, keep a "have
	 * finalizer" flag in duk_hobject in sync so that refzero can do
	 * a very quick finalizer check by walking the prototype chain
	 * and checking the flag alone.  (Note that this means that just
	 * setting _Finalizer on an object won't affect finalizer checks.)
	 *
	 * NOTE: if the argument is a Proxy object, this flag will be set
	 * on the Proxy, not the target.  As a result, the target won't get
	 * a finalizer flag and the Proxy also won't be finalized as there's
	 * an explicit Proxy check in finalization now.
	 */
	if (callable) {
		DUK_HOBJECT_SET_HAVE_FINALIZER(h);
	} else {
		DUK_HOBJECT_CLEAR_HAVE_FINALIZER(h);
	}
}
#else  /* DUK_USE_FINALIZER_SUPPORT */
DUK_EXTERNAL void duk_get_finalizer(duk_hthread *thr, duk_idx_t idx) {
	DUK_ASSERT_API_ENTRY(thr);
	DUK_UNREF(idx);
	DUK_ERROR_UNSUPPORTED(thr);
	DUK_WO_NORETURN(return;);
}

DUK_EXTERNAL void duk_set_finalizer(duk_hthread *thr, duk_idx_t idx) {
	DUK_ASSERT_API_ENTRY(thr);
	DUK_UNREF(idx);
	DUK_ERROR_UNSUPPORTED(thr);
	DUK_WO_NORETURN(return;);
}
#endif  /* DUK_USE_FINALIZER_SUPPORT */
#line 1 "duk_api_random.c"
/*
 *  Random numbers
 */

/* #include duk_internal.h -> already included */

DUK_EXTERNAL duk_double_t duk_random(duk_hthread *thr) {
	return (duk_double_t) DUK_UTIL_GET_RANDOM_DOUBLE(thr);
}
#line 1 "duk_api_stack.c"
/*
 *  API calls related to general value stack manipulation: resizing the value
 *  stack, pushing and popping values, type checking and reading values,
 *  coercing values, etc.
 *
 *  Also contains internal functions (such as duk_get_tval()), defined
 *  in duk_api_internal.h, with semantics similar to the public API.
 */

/* XXX: repetition of stack pre-checks -> helper or macro or inline */
/* XXX: shared api error strings, and perhaps even throw code for rare cases? */

/* #include duk_internal.h -> already included */

/*
 *  Forward declarations
 */

DUK_LOCAL_DECL duk_idx_t duk__push_c_function_raw(duk_hthread *thr, duk_c_function func, duk_idx_t nargs, duk_uint_t flags, duk_small_uint_t proto_bidx);

/*
 *  Global state for working around missing variadic macros
 */

#if !defined(DUK_USE_VARIADIC_MACROS)
DUK_EXTERNAL const char *duk_api_global_filename = NULL;
DUK_EXTERNAL duk_int_t duk_api_global_line = 0;
#endif

/*
 *  Misc helpers
 */

DUK_LOCAL const char * const duk__symbol_type_strings[4] = {
	"hidden", "global", "local", "wellknown"
};

#if !defined(DUK_USE_PACKED_TVAL)
DUK_LOCAL const duk_uint_t duk__type_from_tag[] = {
	DUK_TYPE_NUMBER,
	DUK_TYPE_NUMBER,  /* fastint */
	DUK_TYPE_UNDEFINED,
	DUK_TYPE_NULL,
	DUK_TYPE_BOOLEAN,
	DUK_TYPE_POINTER,
	DUK_TYPE_LIGHTFUNC,
	DUK_TYPE_NONE,
	DUK_TYPE_STRING,
	DUK_TYPE_OBJECT,
	DUK_TYPE_BUFFER,
};
DUK_LOCAL const duk_uint_t duk__type_mask_from_tag[] = {
	DUK_TYPE_MASK_NUMBER,
	DUK_TYPE_MASK_NUMBER,  /* fastint */
	DUK_TYPE_MASK_UNDEFINED,
	DUK_TYPE_MASK_NULL,
	DUK_TYPE_MASK_BOOLEAN,
	DUK_TYPE_MASK_POINTER,
	DUK_TYPE_MASK_LIGHTFUNC,
	DUK_TYPE_MASK_NONE,
	DUK_TYPE_MASK_STRING,
	DUK_TYPE_MASK_OBJECT,
	DUK_TYPE_MASK_BUFFER,
};
#endif  /* !DUK_USE_PACKED_TVAL */

/* Assert that there's room for one value. */
#define DUK__ASSERT_SPACE() do { \
		DUK_ASSERT(!(thr->valstack_top >= thr->valstack_end)); \
	} while (0)

/* Check that there's room to push one value. */
#if defined(DUK_USE_VALSTACK_UNSAFE)
/* Faster but value stack overruns are memory unsafe. */
#define DUK__CHECK_SPACE() DUK__ASSERT_SPACE()
#else
#define DUK__CHECK_SPACE() do { \
		if (DUK_UNLIKELY(thr->valstack_top >= thr->valstack_end)) { \
			DUK_ERROR_RANGE_PUSH_BEYOND(thr); \
		} \
	} while (0)
#endif

DUK_LOCAL duk_small_uint_t duk__get_symbol_type(duk_hstring *h) {
	const duk_uint8_t *data;
	duk_size_t len;

	DUK_ASSERT(h != NULL);
	DUK_ASSERT(DUK_HSTRING_HAS_SYMBOL(h));
	DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(h) >= 1);  /* always true, symbol prefix */

	data = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
	len = DUK_HSTRING_GET_BYTELEN(h);
	DUK_ASSERT(len >= 1);

	/* XXX: differentiate between 0x82 and 0xff (hidden vs. internal?)? */

	if (data[0] == 0xffU) {
		return DUK_SYMBOL_TYPE_HIDDEN;
	} else if (data[0] == 0x82U) {
		return DUK_SYMBOL_TYPE_HIDDEN;
	} else if (data[0] == 0x80U) {
		return DUK_SYMBOL_TYPE_GLOBAL;
	} else if (data[len - 1] != 0xffU) {
		return DUK_SYMBOL_TYPE_LOCAL;
	} else {
		return DUK_SYMBOL_TYPE_WELLKNOWN;
	}
}

DUK_LOCAL const char *duk__get_symbol_type_string(duk_hstring *h) {
	duk_small_uint_t idx;
	idx = duk__get_symbol_type(h);
	DUK_ASSERT(idx < sizeof(duk__symbol_type_strings));
	return duk__symbol_type_strings[idx];
}

DUK_LOCAL_DECL duk_heaphdr *duk__get_tagged_heaphdr_raw(duk_hthread *thr, duk_idx_t idx, duk_uint_t tag);

DUK_LOCAL duk_int_t duk__api_coerce_d2i(duk_hthread *thr, duk_idx_t idx, duk_int_t def_value, duk_bool_t require) {
	duk_tval *tv;
	duk_small_int_t c;
	duk_double_t d;

	tv = duk_get_tval_or_unused(thr, idx);
	DUK_ASSERT(tv != NULL);

	/*
	 *  Special cases like NaN and +/- Infinity are handled explicitly
	 *  because a plain C coercion from double to int handles these cases
	 *  in undesirable ways.  For instance, NaN may coerce to INT_MIN
	 *  (not zero), and INT_MAX + 1 may coerce to INT_MIN (not INT_MAX).
	 *
	 *  This double-to-int coercion differs from ToInteger() because it
	 *  has a finite range (ToInteger() allows e.g. +/- Infinity).  It
	 *  also differs from ToInt32() because the INT_MIN/INT_MAX clamping
	 *  depends on the size of the int type on the platform.  In particular,
	 *  on platforms with a 64-bit int type, the full range is allowed.
	 */

#if defined(DUK_USE_FASTINT)
	if (DUK_TVAL_IS_FASTINT(tv)) {
		duk_int64_t t = DUK_TVAL_GET_FASTINT(tv);
#if (DUK_INT_MAX <= 0x7fffffffL)
		/* Clamping only necessary for 32-bit ints. */
		if (t < DUK_INT_MIN) {
			t = DUK_INT_MIN;
		} else if (t > DUK_INT_MAX) {
			t = DUK_INT_MAX;
		}
#endif
		return (duk_int_t) t;
	}
#endif

	if (DUK_TVAL_IS_NUMBER(tv)) {
		d = DUK_TVAL_GET_NUMBER(tv);
		c = (duk_small_int_t) DUK_FPCLASSIFY(d);
		if (c == DUK_FP_NAN) {
			return 0;
		} else if (d < (duk_double_t) DUK_INT_MIN) {
			/* covers -Infinity */
			return DUK_INT_MIN;
		} else if (d > (duk_double_t) DUK_INT_MAX) {
			/* covers +Infinity */
			return DUK_INT_MAX;
		} else {
			/* coerce towards zero */
			return (duk_int_t) d;
		}
	}

	if (require) {
		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "number", DUK_STR_NOT_NUMBER);
		DUK_WO_NORETURN(return 0;);
	}

	return def_value;
}

DUK_LOCAL duk_uint_t duk__api_coerce_d2ui(duk_hthread *thr, duk_idx_t idx, duk_uint_t def_value, duk_bool_t require) {
	duk_tval *tv;
	duk_small_int_t c;
	duk_double_t d;

	/* Same as above but for unsigned int range. */

	tv = duk_get_tval_or_unused(thr, idx);
	DUK_ASSERT(tv != NULL);

#if defined(DUK_USE_FASTINT)
	if (DUK_TVAL_IS_FASTINT(tv)) {
		duk_int64_t t = DUK_TVAL_GET_FASTINT(tv);
		if (t < 0) {
			t = 0;
		}
#if (DUK_UINT_MAX <= 0xffffffffUL)
		/* Clamping only necessary for 32-bit ints. */
		else if (t > DUK_UINT_MAX) {
			t = DUK_UINT_MAX;
		}
#endif
		return (duk_uint_t) t;
	}
#endif

	if (DUK_TVAL_IS_NUMBER(tv)) {
		d = DUK_TVAL_GET_NUMBER(tv);
		c = (duk_small_int_t) DUK_FPCLASSIFY(d);
		if (c == DUK_FP_NAN) {
			return 0;
		} else if (d < 0.0) {
			/* covers -Infinity */
			return (duk_uint_t) 0;
		} else if (d > (duk_double_t) DUK_UINT_MAX) {
			/* covers +Infinity */
			return (duk_uint_t) DUK_UINT_MAX;
		} else {
			/* coerce towards zero */
			return (duk_uint_t) d;
		}
	}

	if (require) {
		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "number", DUK_STR_NOT_NUMBER);
		DUK_WO_NORETURN(return 0;);
	}

	return def_value;
}

/*
 *  Stack index validation/normalization and getting a stack duk_tval ptr.
 *
 *  These are called by many API entrypoints so the implementations must be
 *  fast and "inlined".
 *
 *  There's some repetition because of this; keep the functions in sync.
 */

DUK_EXTERNAL duk_idx_t duk_normalize_index(duk_hthread *thr, duk_idx_t idx) {
	duk_uidx_t vs_size;
	duk_uidx_t uidx;

	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(DUK_INVALID_INDEX < 0);

	/* Care must be taken to avoid pointer wrapping in the index
	 * validation.  For instance, on a 32-bit platform with 8-byte
	 * duk_tval the index 0x20000000UL would wrap the memory space
	 * once.
	 */

	/* Assume value stack sizes (in elements) fits into duk_idx_t. */
	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
	vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
	DUK_ASSERT_DISABLE(vs_size >= 0);  /* unsigned */

	if (idx < 0) {
		uidx = vs_size + (duk_uidx_t) idx;
	} else {
		/* since index non-negative */
		DUK_ASSERT(idx != DUK_INVALID_INDEX);
		uidx = (duk_uidx_t) idx;
	}

	/* DUK_INVALID_INDEX won't be accepted as a valid index. */
	DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);

	if (DUK_LIKELY(uidx < vs_size)) {
		return (duk_idx_t) uidx;
	}
	return DUK_INVALID_INDEX;
}

DUK_EXTERNAL duk_idx_t duk_require_normalize_index(duk_hthread *thr, duk_idx_t idx) {
	duk_uidx_t vs_size;
	duk_uidx_t uidx;

	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(DUK_INVALID_INDEX < 0);

	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
	vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
	DUK_ASSERT_DISABLE(vs_size >= 0);  /* unsigned */

	if (idx < 0) {
		uidx = vs_size + (duk_uidx_t) idx;
	} else {
		DUK_ASSERT(idx != DUK_INVALID_INDEX);
		uidx = (duk_uidx_t) idx;
	}

	/* DUK_INVALID_INDEX won't be accepted as a valid index. */
	DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);

	if (DUK_LIKELY(uidx < vs_size)) {
		return (duk_idx_t) uidx;
	}
	DUK_ERROR_RANGE_INDEX(thr, idx);
	DUK_WO_NORETURN(return 0;);
}

DUK_INTERNAL duk_tval *duk_get_tval(duk_hthread *thr, duk_idx_t idx) {
	duk_uidx_t vs_size;
	duk_uidx_t uidx;

	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(DUK_INVALID_INDEX < 0);

	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
	vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
	DUK_ASSERT_DISABLE(vs_size >= 0);  /* unsigned */

	if (idx < 0) {
		uidx = vs_size + (duk_uidx_t) idx;
	} else {
		DUK_ASSERT(idx != DUK_INVALID_INDEX);
		uidx = (duk_uidx_t) idx;
	}

	/* DUK_INVALID_INDEX won't be accepted as a valid index. */
	DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);

	if (DUK_LIKELY(uidx < vs_size)) {
		return thr->valstack_bottom + uidx;
	}
	return NULL;
}

/* Variant of duk_get_tval() which is guaranteed to return a valid duk_tval
 * pointer.  When duk_get_tval() would return NULL, this variant returns a
 * pointer to a duk_tval with tag DUK_TAG_UNUSED.  This allows the call site
 * to avoid an unnecessary NULL check which sometimes leads to better code.
 * The return duk_tval is read only (at least for the UNUSED value).
 */
DUK_LOCAL const duk_tval_unused duk__const_tval_unused = DUK_TVAL_UNUSED_INITIALIZER();

DUK_INTERNAL duk_tval *duk_get_tval_or_unused(duk_hthread *thr, duk_idx_t idx) {
	duk_tval *tv;

	DUK_ASSERT_API_ENTRY(thr);

	tv = duk_get_tval(thr, idx);
	if (tv != NULL) {
		return tv;
	}
	return (duk_tval *) DUK_LOSE_CONST(&duk__const_tval_unused);
}

DUK_INTERNAL duk_tval *duk_require_tval(duk_hthread *thr, duk_idx_t idx) {
	duk_uidx_t vs_size;
	duk_uidx_t uidx;

	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(DUK_INVALID_INDEX < 0);

	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
	vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
	DUK_ASSERT_DISABLE(vs_size >= 0);  /* unsigned */

	/* Use unsigned arithmetic to optimize comparison. */
	if (idx < 0) {
		uidx = vs_size + (duk_uidx_t) idx;
	} else {
		DUK_ASSERT(idx != DUK_INVALID_INDEX);
		uidx = (duk_uidx_t) idx;
	}

	/* DUK_INVALID_INDEX won't be accepted as a valid index. */
	DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);

	if (DUK_LIKELY(uidx < vs_size)) {
		return thr->valstack_bottom + uidx;
	}
	DUK_ERROR_RANGE_INDEX(thr, idx);
	DUK_WO_NORETURN(return NULL;);
}

/* Non-critical. */
DUK_EXTERNAL duk_bool_t duk_is_valid_index(duk_hthread *thr, duk_idx_t idx) {
	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(DUK_INVALID_INDEX < 0);

	return (duk_normalize_index(thr, idx) >= 0);
}

/* Non-critical. */
DUK_EXTERNAL void duk_require_valid_index(duk_hthread *thr, duk_idx_t idx) {
	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(DUK_INVALID_INDEX < 0);

	if (DUK_UNLIKELY(duk_normalize_index(thr, idx) < 0)) {
		DUK_ERROR_RANGE_INDEX(thr, idx);
		DUK_WO_NORETURN(return;);
	}
}

/*
 *  Value stack top handling
 */

DUK_EXTERNAL duk_idx_t duk_get_top(duk_hthread *thr) {
	DUK_ASSERT_API_ENTRY(thr);

	return (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
}

/* Internal helper to get current top but to require a minimum top value
 * (TypeError if not met).
 */
DUK_INTERNAL duk_idx_t duk_get_top_require_min(duk_hthread *thr, duk_idx_t min_top) {
	duk_idx_t ret;

	DUK_ASSERT_API_ENTRY(thr);

	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
	if (DUK_UNLIKELY(ret < min_top)) {
		DUK_ERROR_TYPE_INVALID_ARGS(thr);
		DUK_WO_NORETURN(return 0;);
	}
	return ret;
}

/* Set stack top within currently allocated range, but don't reallocate.
 * This is performance critical especially for call handling, so whenever
 * changing, profile and look at generated code.
 */
DUK_EXTERNAL void duk_set_top(duk_hthread *thr, duk_idx_t idx) {
	duk_uidx_t vs_size;
	duk_uidx_t vs_limit;
	duk_uidx_t uidx;
	duk_tval *tv;

	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(DUK_INVALID_INDEX < 0);

	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
	DUK_ASSERT(thr->valstack_end >= thr->valstack_bottom);
	vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
	vs_limit = (duk_uidx_t) (thr->valstack_end - thr->valstack_bottom);

	if (idx < 0) {
		/* Negative indices are always within allocated stack but
		 * must not go below zero index.
		 */
		uidx = vs_size + (duk_uidx_t) idx;
	} else {
		/* Positive index can be higher than valstack top but must
		 * not go above allocated stack (equality is OK).
		 */
		uidx = (duk_uidx_t) idx;
	}

	/* DUK_INVALID_INDEX won't be accepted as a valid index. */
	DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);
	DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_limit);

#if defined(DUK_USE_VALSTACK_UNSAFE)
	DUK_ASSERT(uidx <= vs_limit);
	DUK_UNREF(vs_limit);
#else
	if (DUK_UNLIKELY(uidx > vs_limit)) {
		DUK_ERROR_RANGE_INDEX(thr, idx);
		DUK_WO_NORETURN(return;);
	}
#endif
	DUK_ASSERT(uidx <= vs_limit);

	/* Handle change in value stack top.  Respect value stack
	 * initialization policy: 'undefined' above top.  Note that
	 * DECREF may cause a side effect that reallocates valstack,
	 * so must relookup after DECREF.
	 */

	if (uidx >= vs_size) {
		/* Stack size increases or stays the same. */
#if defined(DUK_USE_ASSERTIONS)
		duk_uidx_t count;

		count = uidx - vs_size;
		while (count != 0) {
			count--;
			tv = thr->valstack_top + count;
			DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv));
		}
#endif
		thr->valstack_top = thr->valstack_bottom + uidx;
	} else {
		/* Stack size decreases. */
#if defined(DUK_USE_REFERENCE_COUNTING)
		duk_uidx_t count;
		duk_tval *tv_end;

		count = vs_size - uidx;
		DUK_ASSERT(count > 0);
		tv = thr->valstack_top;
		tv_end = tv - count;
		DUK_ASSERT(tv > tv_end);  /* Because count > 0. */
		do {
			tv--;
			DUK_ASSERT(tv >= thr->valstack_bottom);
			DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ(thr, tv);
		} while (tv != tv_end);
		thr->valstack_top = tv_end;
		DUK_REFZERO_CHECK_FAST(thr);
#else  /* DUK_USE_REFERENCE_COUNTING */
		duk_uidx_t count;
		duk_tval *tv_end;

		count = vs_size - uidx;
		tv = thr->valstack_top;
		tv_end = tv - count;
		DUK_ASSERT(tv > tv_end);
		do {
			tv--;
			DUK_TVAL_SET_UNDEFINED(tv);
		} while (tv != tv_end);
		thr->valstack_top = tv_end;
#endif  /* DUK_USE_REFERENCE_COUNTING */
	}
}

/* Internal variant with a non-negative index and no runtime size checks. */
#if defined(DUK_USE_PREFER_SIZE)
DUK_INTERNAL void duk_set_top_unsafe(duk_hthread *thr, duk_idx_t idx) {
	DUK_ASSERT_API_ENTRY(thr);

	duk_set_top(thr, idx);
}
#else  /* DUK_USE_PREFER_SIZE */
DUK_INTERNAL void duk_set_top_unsafe(duk_hthread *thr, duk_idx_t idx) {
	duk_uidx_t uidx;
	duk_uidx_t vs_size;
	duk_tval *tv;

	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
	DUK_ASSERT(thr->valstack_end >= thr->valstack_bottom);
	DUK_ASSERT(idx >= 0);
	DUK_ASSERT(idx <= (duk_idx_t) (thr->valstack_end - thr->valstack_bottom));

	/* XXX: byte arithmetic */
	uidx = (duk_uidx_t) idx;
	vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);

	if (uidx >= vs_size) {
		/* Stack size increases or stays the same. */
#if defined(DUK_USE_ASSERTIONS)
		duk_uidx_t count;

		count = uidx - vs_size;
		while (count != 0) {
			count--;
			tv = thr->valstack_top + count;
			DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv));
		}
#endif
		thr->valstack_top = thr->valstack_bottom + uidx;
	} else {
		/* Stack size decreases. */
#if defined(DUK_USE_REFERENCE_COUNTING)
		duk_uidx_t count;
		duk_tval *tv_end;

		count = vs_size - uidx;
		DUK_ASSERT(count > 0);
		tv = thr->valstack_top;
		tv_end = tv - count;
		DUK_ASSERT(tv > tv_end);  /* Because count > 0. */
		do {
			tv--;
			DUK_ASSERT(tv >= thr->valstack_bottom);
			DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ(thr, tv);
		} while (tv != tv_end);
		thr->valstack_top = tv_end;
		DUK_REFZERO_CHECK_FAST(thr);
#else  /* DUK_USE_REFERENCE_COUNTING */
		duk_uidx_t count;
		duk_tval *tv_end;

		count = vs_size - uidx;
		tv = thr->valstack_top;
		tv_end = tv - count;
		DUK_ASSERT(tv > tv_end);
		do {
			tv--;
			DUK_TVAL_SET_UNDEFINED(tv);
		} while (tv != tv_end);
		thr->valstack_top = tv_end;
#endif  /* DUK_USE_REFERENCE_COUNTING */
	}
}
#endif  /* DUK_USE_PREFER_SIZE */

/* Internal helper: set top to 'top', and set [idx_wipe_start,top[ to
 * 'undefined' (doing nothing if idx_wipe_start == top).  Indices are
 * positive and within value stack reserve.  This is used by call handling.
 */
DUK_INTERNAL void duk_set_top_and_wipe(duk_hthread *thr, duk_idx_t top, duk_idx_t idx_wipe_start) {
	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(top >= 0);
	DUK_ASSERT(idx_wipe_start >= 0);
	DUK_ASSERT(idx_wipe_start <= top);
	DUK_ASSERT(thr->valstack_bottom + top <= thr->valstack_end);
	DUK_ASSERT(thr->valstack_bottom + idx_wipe_start <= thr->valstack_end);

	duk_set_top_unsafe(thr, idx_wipe_start);
	duk_set_top_unsafe(thr, top);
}

DUK_EXTERNAL duk_idx_t duk_get_top_index(duk_hthread *thr) {
	duk_idx_t ret;

	DUK_ASSERT_API_ENTRY(thr);

	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom) - 1;
	if (DUK_UNLIKELY(ret < 0)) {
		/* Return invalid index; if caller uses this without checking
		 * in another API call, the index won't map to a valid stack
		 * entry.
		 */
		return DUK_INVALID_INDEX;
	}
	return ret;
}

/* Internal variant: call assumes there is at least one element on the value
 * stack frame; this is only asserted for.
 */
DUK_INTERNAL duk_idx_t duk_get_top_index_unsafe(duk_hthread *thr) {
	duk_idx_t ret;

	DUK_ASSERT_API_ENTRY(thr);

	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom) - 1;
	return ret;
}

DUK_EXTERNAL duk_idx_t duk_require_top_index(duk_hthread *thr) {
	duk_idx_t ret;

	DUK_ASSERT_API_ENTRY(thr);

	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom) - 1;
	if (DUK_UNLIKELY(ret < 0)) {
		DUK_ERROR_RANGE_INDEX(thr, -1);
		DUK_WO_NORETURN(return 0;);
	}
	return ret;
}

/*
 *  Value stack resizing.
 *
 *  This resizing happens above the current "top": the value stack can be
 *  grown or shrunk, but the "top" is not affected.  The value stack cannot
 *  be resized to a size below the current reserve.
 *
 *  The low level reallocation primitive must carefully recompute all value
 *  stack pointers, and must also work if ALL pointers are NULL.  The resize
 *  is quite tricky because the valstack realloc may cause a mark-and-sweep,
 *  which may run finalizers.  Running finalizers may resize the valstack
 *  recursively (the same value stack we're working on).  So, after realloc
 *  returns, we know that the valstack bottom, top, and reserve should still
 *  be the same (there should not be live values above the "top"), but its
 *  underlying size, alloc_end, and base pointer may have changed.
 *
 *  'new_size' is known to be <= DUK_USE_VALSTACK_LIMIT, which ensures that
 *  size_t and pointer arithmetic won't wrap in duk__resize_valstack().
 */

/* Low level valstack resize primitive, used for both grow and shrink.  All
 * adjustments for slack etc have already been done.  Doesn't throw but does
 * have allocation side effects.
 */
DUK_LOCAL DUK_COLD DUK_NOINLINE duk_bool_t duk__resize_valstack(duk_hthread *thr, duk_size_t new_size) {
	duk_tval *pre_valstack;
	duk_tval *pre_bottom;
	duk_tval *pre_top;
	duk_tval *pre_end;
	duk_tval *pre_alloc_end;
	duk_ptrdiff_t ptr_diff;
	duk_tval *new_valstack;
	duk_size_t new_alloc_size;
	duk_tval *tv_prev_alloc_end;
	duk_tval *p;

	DUK_HTHREAD_ASSERT_VALID(thr);
	DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
	DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
	DUK_ASSERT(thr->valstack_alloc_end >= thr->valstack_end);
	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack) <= new_size);  /* can't resize below 'top' */
	DUK_ASSERT(new_size <= DUK_USE_VALSTACK_LIMIT);  /* valstack limit caller has check, prevents wrapping */
	DUK_ASSERT(new_size <= DUK_SIZE_MAX / sizeof(duk_tval));  /* specific assert for wrapping */

	/* Pre-realloc pointer copies for asserts and debug logs. */
	pre_valstack = thr->valstack;
	pre_bottom = thr->valstack_bottom;
	pre_top = thr->valstack_top;
	pre_end = thr->valstack_end;
	pre_alloc_end = thr->valstack_alloc_end;

	DUK_UNREF(pre_valstack);
	DUK_UNREF(pre_bottom);
	DUK_UNREF(pre_top);
	DUK_UNREF(pre_end);
	DUK_UNREF(pre_alloc_end);

	/* If finalizer torture enabled, force base pointer change every time
	 * when it would be allowed.
	 */
#if defined(DUK_USE_FINALIZER_TORTURE)
	if (thr->heap->pf_prevent_count == 0) {
		duk_hthread_valstack_torture_realloc(thr);
	}
#endif

	/* Allocate a new valstack using DUK_REALLOC_DIRECT() to deal with
	 * a side effect changing the base pointer.
	 */
	new_alloc_size = sizeof(duk_tval) * new_size;
	new_valstack = (duk_tval *) DUK_REALLOC_INDIRECT(thr->heap, duk_hthread_get_valstack_ptr, (void *) thr, new_alloc_size);
	if (DUK_UNLIKELY(new_valstack == NULL)) {
		/* Because new_size != 0, if condition doesn't need to be
		 * (new_valstack != NULL || new_size == 0).
		 */
		DUK_ASSERT(new_size != 0);
		DUK_D(DUK_DPRINT("failed to resize valstack to %lu entries (%lu bytes)",
		                 (unsigned long) new_size, (unsigned long) new_alloc_size));
		return 0;
	}

	/* Debug log any changes in pointer(s) by side effects.  These don't
	 * necessarily imply any incorrect behavior, but should be rare in
	 * practice.
	 */
#if defined(DUK_USE_DEBUG)
	if (thr->valstack != pre_valstack) {
		DUK_D(DUK_DPRINT("valstack base pointer changed during valstack resize: %p -> %p",
		                 (void *) pre_valstack, (void *) thr->valstack));
	}
	if (thr->valstack_bottom != pre_bottom) {
		DUK_D(DUK_DPRINT("valstack bottom pointer changed during valstack resize: %p -> %p",
		                 (void *) pre_bottom, (void *) thr->valstack_bottom));
	}
	if (thr->valstack_top != pre_top) {
		DUK_D(DUK_DPRINT("valstack top pointer changed during valstack resize: %p -> %p",
		                 (void *) pre_top, (void *) thr->valstack_top));
	}
	if (thr->valstack_end != pre_end) {
		DUK_D(DUK_DPRINT("valstack end pointer changed during valstack resize: %p -> %p",
		                 (void *) pre_end, (void *) thr->valstack_end));
	}
	if (thr->valstack_alloc_end != pre_alloc_end) {
		DUK_D(DUK_DPRINT("valstack alloc_end pointer changed during valstack resize: %p -> %p",
		                 (void *) pre_alloc_end, (void *) thr->valstack_alloc_end));
	}
#endif

	/* Assertions: offsets for bottom, top, and end (reserve) must not
	 * have changed even with side effects because they are always
	 * restored in unwind.  For alloc_end there's no guarantee: it may
	 * have grown or shrunk (but remain above 'end').
	 */
	DUK_ASSERT(thr->valstack_bottom - thr->valstack == pre_bottom - pre_valstack);
	DUK_ASSERT(thr->valstack_top - thr->valstack == pre_top - pre_valstack);
	DUK_ASSERT(thr->valstack_end - thr->valstack == pre_end - pre_valstack);
	DUK_ASSERT(thr->valstack_alloc_end >= thr->valstack_end);

	/* Write new pointers.  Most pointers can be handled as a pointer
	 * difference.
	 */
	ptr_diff = (duk_ptrdiff_t) ((duk_uint8_t *) new_valstack - (duk_uint8_t *) thr->valstack);
	tv_prev_alloc_end = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_alloc_end + ptr_diff);
	thr->valstack = new_valstack;
	thr->valstack_bottom = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_bottom + ptr_diff);
	thr->valstack_top = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_top + ptr_diff);
	thr->valstack_end = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_end + ptr_diff);
	thr->valstack_alloc_end = (duk_tval *) (void *) ((duk_uint8_t *) new_valstack + new_alloc_size);

	/* Assertions: pointer sanity after pointer updates. */
	DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
	DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
	DUK_ASSERT(thr->valstack_alloc_end >= thr->valstack_end);

	DUK_D(DUK_DPRINT("resized valstack %lu -> %lu elements (%lu -> %lu bytes): "
	                 "base=%p -> %p, bottom=%p -> %p (%ld), top=%p -> %p (%ld), "
	                 "end=%p -> %p (%ld), alloc_end=%p -> %p (%ld);"
	                 " tv_prev_alloc_end=%p (-> %ld inits; <0 means shrink)",
	                 (unsigned long) (pre_alloc_end - pre_valstack),
	                 (unsigned long) new_size,
	                 (unsigned long) ((duk_uint8_t *) pre_alloc_end - (duk_uint8_t *) pre_valstack),
	                 (unsigned long) new_alloc_size,
	                 (void *) pre_valstack, (void *) thr->valstack,
	                 (void *) pre_bottom, (void *) thr->valstack_bottom, (long) (thr->valstack_bottom - thr->valstack),
	                 (void *) pre_top, (void *) thr->valstack_top, (long) (thr->valstack_top - thr->valstack),
	                 (void *) pre_end, (void *) thr->valstack_end, (long) (thr->valstack_end - thr->valstack),
	                 (void *) pre_alloc_end, (void *) thr->valstack_alloc_end, (long) (thr->valstack_alloc_end - thr->valstack),
	                 (void *) tv_prev_alloc_end, (long) (thr->valstack_alloc_end - tv_prev_alloc_end)));

	/* If allocation grew, init any new slots to 'undefined'. */
	p = tv_prev_alloc_end;
	while (p < thr->valstack_alloc_end) {
		/* Never executed if new size is smaller. */
		DUK_TVAL_SET_UNDEFINED(p);
		p++;
	}

	/* Assert for value stack initialization policy. */
#if defined(DUK_USE_ASSERTIONS)
	p = thr->valstack_top;
	while (p < thr->valstack_alloc_end) {
		DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(p));
		p++;
	}
#endif

	return 1;
}

DUK_LOCAL DUK_COLD DUK_NOINLINE duk_bool_t duk__valstack_grow(duk_hthread *thr, duk_size_t min_bytes, duk_bool_t throw_on_error) {
	duk_size_t min_size;
	duk_size_t new_size;

	DUK_ASSERT(min_bytes / sizeof(duk_tval) * sizeof(duk_tval) == min_bytes);
	min_size = min_bytes / sizeof(duk_tval);  /* from bytes to slots */

#if defined(DUK_USE_VALSTACK_GROW_SHIFT)
	/* New size is minimum size plus a proportional slack, e.g. shift of
	 * 2 means a 25% slack.
	 */
	new_size = min_size + (min_size >> DUK_USE_VALSTACK_GROW_SHIFT);
#else
	/* New size is tight with no slack.  This is sometimes preferred in
	 * low memory environments.
	 */
	new_size = min_size;
#endif

	if (DUK_UNLIKELY(new_size > DUK_USE_VALSTACK_LIMIT || new_size < min_size /*wrap*/)) {
		/* Note: may be triggered even if minimal new_size would not reach the limit,
		 * plan limit accordingly.
		 */
		if (throw_on_error) {
			DUK_ERROR_RANGE(thr, DUK_STR_VALSTACK_LIMIT);
			DUK_WO_NORETURN(return 0;);
		}
		return 0;
	}

	if (duk__resize_valstack(thr, new_size) == 0) {
		if (throw_on_error) {
			DUK_ERROR_ALLOC_FAILED(thr);
			DUK_WO_NORETURN(return 0;);
		}
		return 0;
	}

	thr->valstack_end = thr->valstack + min_size;
	DUK_ASSERT(thr->valstack_alloc_end >= thr->valstack_end);

	return 1;
}

/* Hot, inlined value stack grow check.  Because value stack almost never
 * grows, the actual resize call is in a NOINLINE helper.
 */
DUK_INTERNAL DUK_INLINE void duk_valstack_grow_check_throw(duk_hthread *thr, duk_size_t min_bytes) {
	duk_tval *tv;

	tv = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + min_bytes);
	if (DUK_LIKELY(thr->valstack_end >= tv)) {
		return;
	}
	if (DUK_LIKELY(thr->valstack_alloc_end >= tv)) {
		/* Values in [valstack_top,valstack_alloc_end[ are initialized
		 * to 'undefined' so we can just move the end pointer.
		 */
		thr->valstack_end = tv;
		return;
	}
	(void) duk__valstack_grow(thr, min_bytes, 1 /*throw_on_error*/);
}

/* Hot, inlined value stack grow check which doesn't throw. */
DUK_INTERNAL DUK_INLINE duk_bool_t duk_valstack_grow_check_nothrow(duk_hthread *thr, duk_size_t min_bytes) {
	duk_tval *tv;

	tv = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + min_bytes);
	if (DUK_LIKELY(thr->valstack_end >= tv)) {
		return 1;
	}
	if (DUK_LIKELY(thr->valstack_alloc_end >= tv)) {
		thr->valstack_end = tv;
		return 1;
	}
	return duk__valstack_grow(thr, min_bytes, 0 /*throw_on_error*/);
}

/* Value stack shrink check, called from mark-and-sweep. */
DUK_INTERNAL void duk_valstack_shrink_check_nothrow(duk_hthread *thr, duk_bool_t snug) {
	duk_size_t alloc_bytes;
	duk_size_t reserve_bytes;
	duk_size_t shrink_bytes;

	alloc_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_alloc_end - (duk_uint8_t *) thr->valstack);
	reserve_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack);
	DUK_ASSERT(alloc_bytes >= reserve_bytes);

	/* We're free to shrink the value stack allocation down to
	 * reserve_bytes but not more.  If 'snug' (emergency GC)
	 * shrink whatever we can.  Otherwise only shrink if the new
	 * size would be considerably smaller.
	 */

#if defined(DUK_USE_VALSTACK_SHRINK_CHECK_SHIFT)
	if (snug) {
		shrink_bytes = reserve_bytes;
	} else {
		duk_size_t proportion, slack;

		/* Require that value stack shrinks by at least X% of its
		 * current size.  For example, shift of 2 means at least
		 * 25%.  The proportion is computed as bytes and may not
		 * be a multiple of sizeof(duk_tval); that's OK here.
		 */
		proportion = alloc_bytes >> DUK_USE_VALSTACK_SHRINK_CHECK_SHIFT;
		if (alloc_bytes - reserve_bytes < proportion) {
			/* Too little would be freed, do nothing. */
			return;
		}

		/* Keep a slack after shrinking.  The slack is again a
		 * proportion of the current size (the proportion should
		 * of course be smaller than the check proportion above).
		 */
#if defined(DUK_USE_VALSTACK_SHRINK_SLACK_SHIFT)
		DUK_ASSERT(DUK_USE_VALSTACK_SHRINK_SLACK_SHIFT > DUK_USE_VALSTACK_SHRINK_CHECK_SHIFT);
		slack = alloc_bytes >> DUK_USE_VALSTACK_SHRINK_SLACK_SHIFT;
#else
		slack = 0;
#endif
		shrink_bytes = reserve_bytes +
		               slack / sizeof(duk_tval) * sizeof(duk_tval);  /* multiple of duk_tval */
	}
#else  /* DUK_USE_VALSTACK_SHRINK_CHECK_SHIFT */
	/* Always snug, useful in some low memory environments. */
	DUK_UNREF(snug);
	shrink_bytes = reserve_bytes;
#endif  /* DUK_USE_VALSTACK_SHRINK_CHECK_SHIFT */

	DUK_D(DUK_DPRINT("valstack shrink check: alloc_bytes=%ld, reserve_bytes=%ld, shrink_bytes=%ld (unvalidated)",
	                 (long) alloc_bytes, (long) reserve_bytes, (long) shrink_bytes));
	DUK_ASSERT(shrink_bytes >= reserve_bytes);
	if (shrink_bytes >= alloc_bytes) {
		/* Skip if shrink target is same as current one (or higher,
		 * though that shouldn't happen in practice).
		 */
		return;
	}
	DUK_ASSERT(shrink_bytes / sizeof(duk_tval) * sizeof(duk_tval) == shrink_bytes);

	DUK_D(DUK_DPRINT("valstack shrink check: decided to shrink, snug: %ld", (long) snug));

	duk__resize_valstack(thr, shrink_bytes / sizeof(duk_tval));
}

DUK_EXTERNAL duk_bool_t duk_check_stack(duk_hthread *thr, duk_idx_t extra) {
	duk_size_t min_new_bytes;

	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(thr != NULL);

	if (DUK_UNLIKELY(extra < 0 || extra > DUK_USE_VALSTACK_LIMIT)) {
		if (extra < 0) {
			/* Clamping to zero makes the API more robust to calling code
			 * calculation errors.
			 */
			extra = 0;
		} else {
			/* Cause grow check to fail without wrapping arithmetic. */
			extra = DUK_USE_VALSTACK_LIMIT;
		}
	}

	min_new_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_top - (duk_uint8_t *) thr->valstack) +
	                sizeof(duk_tval) * ((duk_size_t) extra + DUK_VALSTACK_INTERNAL_EXTRA);
	return duk_valstack_grow_check_nothrow(thr, min_new_bytes);
}

DUK_EXTERNAL void duk_require_stack(duk_hthread *thr, duk_idx_t extra) {
	duk_size_t min_new_bytes;

	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(thr != NULL);

	if (DUK_UNLIKELY(extra < 0 || extra > DUK_USE_VALSTACK_LIMIT)) {
		if (extra < 0) {
			/* Clamping to zero makes the API more robust to calling code
			 * calculation errors.
			 */
			extra = 0;
		} else {
			/* Cause grow check to fail without wrapping arithmetic. */
			extra = DUK_USE_VALSTACK_LIMIT;
		}
	}

	min_new_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_top - (duk_uint8_t *) thr->valstack) +
	                sizeof(duk_tval) * ((duk_size_t) extra + DUK_VALSTACK_INTERNAL_EXTRA);
	duk_valstack_grow_check_throw(thr, min_new_bytes);
}

DUK_EXTERNAL duk_bool_t duk_check_stack_top(duk_hthread *thr, duk_idx_t top) {
	duk_size_t min_new_bytes;

	DUK_ASSERT_API_ENTRY(thr);

	if (DUK_UNLIKELY(top < 0 || top > DUK_USE_VALSTACK_LIMIT)) {
		if (top < 0) {
			/* Clamping to zero makes the API more robust to calling code
			 * calculation errors.
			 */
			top = 0;
		} else {
			/* Cause grow check to fail without wrapping arithmetic. */
			top = DUK_USE_VALSTACK_LIMIT;
		}
	}

	DUK_ASSERT(top >= 0);
	min_new_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack) +
	                sizeof(duk_tval) * ((duk_size_t) top + DUK_VALSTACK_INTERNAL_EXTRA);
	return duk_valstack_grow_check_nothrow(thr, min_new_bytes);
}

DUK_EXTERNAL void duk_require_stack_top(duk_hthread *thr, duk_idx_t top) {
	duk_size_t min_new_bytes;

	DUK_ASSERT_API_ENTRY(thr);

	if (DUK_UNLIKELY(top < 0 || top > DUK_USE_VALSTACK_LIMIT)) {
		if (top < 0) {
			/* Clamping to zero makes the API more robust to calling code
			 * calculation errors.
			 */
			top = 0;
		} else {
			/* Cause grow check to fail without wrapping arithmetic. */
			top = DUK_USE_VALSTACK_LIMIT;
		}
	}

	DUK_ASSERT(top >= 0);
	min_new_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack) +
	                sizeof(duk_tval) * ((duk_size_t) top + DUK_VALSTACK_INTERNAL_EXTRA);
	duk_valstack_grow_check_throw(thr, min_new_bytes);
}

/*
 *  Basic stack manipulation: swap, dup, insert, replace, etc
 */

DUK_EXTERNAL void duk_swap(duk_hthread *thr, duk_idx_t idx1, duk_idx_t idx2) {
	duk_tval *tv1;
	duk_tval *tv2;
	duk_tval tv_tmp;

	DUK_ASSERT_API_ENTRY(thr);

	tv1 = duk_require_tval(thr, idx1);
	DUK_ASSERT(tv1 != NULL);
	tv2 = duk_require_tval(thr, idx2);
	DUK_ASSERT(tv2 != NULL);

	/* If tv1==tv2 this is a NOP, no check is needed */
	DUK_TVAL_SET_TVAL(&tv_tmp, tv1);
	DUK_TVAL_SET_TVAL(tv1, tv2);
	DUK_TVAL_SET_TVAL(tv2, &tv_tmp);
}

DUK_EXTERNAL void duk_swap_top(duk_hthread *thr, duk_idx_t idx) {
	DUK_ASSERT_API_ENTRY(thr);

	duk_swap(thr, idx, -1);
}

DUK_EXTERNAL void duk_dup(duk_hthread *thr, duk_idx_t from_idx) {
	duk_tval *tv_from;
	duk_tval *tv_to;

	DUK_ASSERT_API_ENTRY(thr);
	DUK__CHECK_SPACE();

	tv_from = duk_require_tval(thr, from_idx);
	tv_to = thr->valstack_top++;
	DUK_ASSERT(tv_from != NULL);
	DUK_ASSERT(tv_to != NULL);
	DUK_TVAL_SET_TVAL(tv_to, tv_from);
	DUK_TVAL_INCREF(thr, tv_to);  /* no side effects */
}

DUK_EXTERNAL void duk_dup_top(duk_hthread *thr) {
#if defined(DUK_USE_PREFER_SIZE)
	duk_dup(thr, -1);
#else
	duk_tval *tv_from;
	duk_tval *tv_to;

	DUK_ASSERT_API_ENTRY(thr);
	DUK__CHECK_SPACE();

	if (DUK_UNLIKELY(thr->valstack_top - thr->valstack_bottom <= 0)) {
		DUK_ERROR_RANGE_INDEX(thr, -1);
		DUK_WO_NORETURN(return;);
	}
	tv_from = thr->valstack_top - 1;
	tv_to = thr->valstack_top++;
	DUK_ASSERT(tv_from != NULL);
	DUK_ASSERT(tv_to != NULL);
	DUK_TVAL_SET_TVAL(tv_to, tv_from);
	DUK_TVAL_INCREF(thr, tv_to);  /* no side effects */
#endif
}

DUK_INTERNAL void duk_dup_0(duk_hthread *thr) {
	DUK_ASSERT_API_ENTRY(thr);
	duk_dup(thr, 0);
}
DUK_INTERNAL void duk_dup_1(duk_hthread *thr) {
	DUK_ASSERT_API_ENTRY(thr);
	duk_dup(thr, 1);
}
DUK_INTERNAL void duk_dup_2(duk_hthread *thr) {
	DUK_ASSERT_API_ENTRY(thr);
	duk_dup(thr, 2);
}
DUK_INTERNAL void duk_dup_m2(duk_hthread *thr) {
	DUK_ASSERT_API_ENTRY(thr);
	duk_dup(thr, -2);
}
DUK_INTERNAL void duk_dup_m3(duk_hthread *thr) {
	DUK_ASSERT_API_ENTRY(thr);
	duk_dup(thr, -3);
}
DUK_INTERNAL void duk_dup_m4(duk_hthread *thr) {
	DUK_ASSERT_API_ENTRY(thr);
	duk_dup(thr, -4);
}

DUK_EXTERNAL void duk_insert(duk_hthread *thr, duk_idx_t to_idx) {
	duk_tval *p;
	duk_tval *q;
	duk_tval tv_tmp;
	duk_size_t nbytes;

	DUK_ASSERT_API_ENTRY(thr);

	p = duk_require_tval(thr, to_idx);
	DUK_ASSERT(p != NULL);
	q = duk_require_tval(thr, -1);
	DUK_ASSERT(q != NULL);

	DUK_ASSERT(q >= p);

	/*              nbytes
	 *           <--------->
	 *    [ ... | p | x | x | q ]
	 * => [ ... | q | p | x | x ]
	 */

	nbytes = (duk_size_t) (((duk_uint8_t *) q) - ((duk_uint8_t *) p));

	DUK_DDD(DUK_DDDPRINT("duk_insert: to_idx=%ld, p=%p, q=%p, nbytes=%lu",
	                     (long) to_idx, (void *) p, (void *) q, (unsigned long) nbytes));

	/* No net refcount changes.  No need to special case nbytes == 0
	 * (p == q).
	 */
	DUK_TVAL_SET_TVAL(&tv_tmp, q);
	duk_memmove((void *) (p + 1), (const void *) p, (size_t) nbytes);
	DUK_TVAL_SET_TVAL(p, &tv_tmp);
}

DUK_INTERNAL void duk_insert_undefined(duk_hthread *thr, duk_idx_t idx) {
	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(idx >= 0);  /* Doesn't support negative indices. */

	duk_push_undefined(thr);
	duk_insert(thr, idx);
}

DUK_INTERNAL void duk_insert_undefined_n(duk_hthread *thr, duk_idx_t idx, duk_idx_t count) {
	duk_tval *tv, *tv_end;

	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(idx >= 0);  /* Doesn't support negative indices or count. */
	DUK_ASSERT(count >= 0);

	tv = duk_reserve_gap(thr, idx, count);
	tv_end = tv + count;
	while (tv != tv_end) {
		DUK_TVAL_SET_UNDEFINED(tv);
		tv++;
	}
}

DUK_EXTERNAL void duk_pull(duk_hthread *thr, duk_idx_t from_idx) {
	duk_tval *p;
	duk_tval *q;
	duk_tval tv_tmp;
	duk_size_t nbytes;

	DUK_ASSERT_API_ENTRY(thr);

	/*                         nbytes
	 *                       <--------->
	 *    [ ... | x | x | p | y | y | q ]
	 * => [ ... | x | x | y | y | q | p ]
	 */

	p = duk_require_tval(thr, from_idx);
	DUK_ASSERT(p != NULL);
	q = duk_require_tval(thr, -1);
	DUK_ASSERT(q != NULL);

	DUK_ASSERT(q >= p);

	nbytes = (duk_size_t) (((duk_uint8_t *) q) - ((duk_uint8_t *) p));

	DUK_DDD(DUK_DDDPRINT("duk_pull: from_idx=%ld, p=%p, q=%p, nbytes=%lu",
	                     (long) from_idx, (void *) p, (void *) q, (unsigned long) nbytes));

	/* No net refcount changes.  No need to special case nbytes == 0
	 * (p == q).
	 */
	DUK_TVAL_SET_TVAL(&tv_tmp, p);
	duk_memmove((void *) p, (const void *) (p + 1), (size_t) nbytes);
	DUK_TVAL_SET_TVAL(q, &tv_tmp);
}

DUK_EXTERNAL void duk_replace(duk_hthread *thr, duk_idx_t to_idx) {
	duk_tval *tv1;
	duk_tval *tv2;
	duk_tval tv_tmp;

	DUK_ASSERT_API_ENTRY(thr);

	tv1 = duk_require_tval(thr, -1);
	DUK_ASSERT(tv1 != NULL);
	tv2 = duk_require_tval(thr, to_idx);
	DUK_ASSERT(tv2 != NULL);

	/* For tv1 == tv2, both pointing to stack top, the end result
	 * is same as duk_pop(thr).
	 */
	DUK_TVAL_SET_TVAL(&tv_tmp, tv2);
	DUK_TVAL_SET_TVAL(tv2, tv1);
	DUK_TVAL_SET_UNDEFINED(tv1);
	thr->valstack_top--;
	DUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */
}

DUK_EXTERNAL void duk_copy(duk_hthread *thr, duk_idx_t from_idx, duk_idx_t to_idx) {
	duk_tval *tv1;
	duk_tval *tv2;

	DUK_ASSERT_API_ENTRY(thr);

	tv1 = duk_require_tval(thr, from_idx);
	DUK_ASSERT(tv1 != NULL);
	tv2 = duk_require_tval(thr, to_idx);
	DUK_ASSERT(tv2 != NULL);

	/* For tv1 == tv2, this is a no-op (no explicit check needed). */
	DUK_TVAL_SET_TVAL_UPDREF(thr, tv2, tv1);  /* side effects */
}

DUK_EXTERNAL void duk_remove(duk_hthread *thr, duk_idx_t idx) {
	duk_tval *p;
	duk_tval *q;
#if defined(DUK_USE_REFERENCE_COUNTING)
	duk_tval tv_tmp;
#endif
	duk_size_t nbytes;

	DUK_ASSERT_API_ENTRY(thr);

	p = duk_require_tval(thr, idx);
	DUK_ASSERT(p != NULL);
	q = duk_require_tval(thr, -1);
	DUK_ASSERT(q != NULL);

	DUK_ASSERT(q >= p);

	/*              nbytes            zero size case
	 *           <--------->
	 *    [ ... | p | x | x | q ]     [ ... | p==q ]
	 * => [ ... | x | x | q ]         [ ... ]
	 */

#if defined(DUK_USE_REFERENCE_COUNTING)
	/* use a temp: decref only when valstack reachable values are correct */
	DUK_TVAL_SET_TVAL(&tv_tmp, p);
#endif

	nbytes = (duk_size_t) (((duk_uint8_t *) q) - ((duk_uint8_t *) p));  /* Note: 'q' is top-1 */
	duk_memmove((void *) p, (const void *) (p + 1), (size_t) nbytes);

	DUK_TVAL_SET_UNDEFINED(q);
	thr->valstack_top--;

#if defined(DUK_USE_REFERENCE_COUNTING)
	DUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */
#endif
}

DUK_INTERNAL void duk_remove_unsafe(duk_hthread *thr, duk_idx_t idx) {
	DUK_ASSERT_API_ENTRY(thr);

	duk_remove(thr, idx);  /* XXX: no optimization for now */
}

DUK_INTERNAL void duk_remove_m2(duk_hthread *thr) {
	DUK_ASSERT_API_ENTRY(thr);

	duk_remove(thr, -2);
}

DUK_INTERNAL void duk_remove_n(duk_hthread *thr, duk_idx_t idx, duk_idx_t count) {
#if defined(DUK_USE_PREFER_SIZE)
	/* XXX: maybe too slow even when preferring size? */
	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(count >= 0);
	DUK_ASSERT(idx >= 0);

	while (count-- > 0) {
		duk_remove(thr, idx);
	}
#else  /* DUK_USE_PREFER_SIZE */
	duk_tval *tv_src;
	duk_tval *tv_dst;
	duk_tval *tv_newtop;
	duk_tval *tv;
	duk_size_t bytes;

	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(count >= 0);
	DUK_ASSERT(idx >= 0);

	tv_dst = thr->valstack_bottom + idx;
	DUK_ASSERT(tv_dst <= thr->valstack_top);
	tv_src = tv_dst + count;
	DUK_ASSERT(tv_src <= thr->valstack_top);
	bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_top - (duk_uint8_t *) tv_src);

	for (tv = tv_dst; tv < tv_src; tv++) {
		DUK_TVAL_DECREF_NORZ(thr, tv);
	}

	duk_memmove((void *) tv_dst, (const void *) tv_src, bytes);

	tv_newtop = thr->valstack_top - count;
	for (tv = tv_newtop; tv < thr->valstack_top; tv++) {
		DUK_TVAL_SET_UNDEFINED(tv);
	}
	thr->valstack_top = tv_newtop;

	/* When not preferring size, only NORZ macros are used; caller
	 * is expected to DUK_REFZERO_CHECK().
	 */
#endif  /* DUK_USE_PREFER_SIZE */
}

DUK_INTERNAL void duk_remove_n_unsafe(duk_hthread *thr, duk_idx_t idx, duk_idx_t count) {
	DUK_ASSERT_API_ENTRY(thr);

	duk_remove_n(thr, idx, count);  /* XXX: no optimization for now */
}

/*
 *  Stack slice primitives
 */

DUK_EXTERNAL void duk_xcopymove_raw(duk_hthread *to_thr, duk_hthread *from_thr, duk_idx_t count, duk_bool_t is_copy) {
	void *src;
	duk_size_t nbytes;
	duk_tval *p;
	duk_tval *q;

	/* XXX: several pointer comparison issues here */

	DUK_ASSERT_API_ENTRY(to_thr);
	DUK_CTX_ASSERT_VALID(to_thr);
	DUK_CTX_ASSERT_VALID(from_thr);
	DUK_ASSERT(to_thr->heap == from_thr->heap);

	if (DUK_UNLIKELY(to_thr == from_thr)) {
		DUK_ERROR_TYPE(to_thr, DUK_STR_INVALID_CONTEXT);
		DUK_WO_NORETURN(return;);
	}
	if (DUK_UNLIKELY((duk_uidx_t) count > (duk_uidx_t) DUK_USE_VALSTACK_LIMIT)) {
		/* Maximum value check ensures 'nbytes' won't wrap below.
		 * Also handles negative count.
		 */
		DUK_ERROR_RANGE_INVALID_COUNT(to_thr);
		DUK_WO_NORETURN(return;);
	}
	DUK_ASSERT(count >= 0);

	nbytes = sizeof(duk_tval) * (duk_size_t) count;
	if (DUK_UNLIKELY(nbytes == 0)) {
		return;
	}
	DUK_ASSERT(to_thr->valstack_top <= to_thr->valstack_end);
	if (DUK_UNLIKELY((duk_size_t) ((duk_uint8_t *) to_thr->valstack_end - (duk_uint8_t *) to_thr->valstack_top) < nbytes)) {
		DUK_ERROR_RANGE_PUSH_BEYOND(to_thr);
		DUK_WO_NORETURN(return;);
	}
	src = (void *) ((duk_uint8_t *) from_thr->valstack_top - nbytes);
	if (DUK_UNLIKELY(src < (void *) from_thr->valstack_bottom)) {
		DUK_ERROR_RANGE_INVALID_COUNT(to_thr);
		DUK_WO_NORETURN(return;);
	}

	/* Copy values (no overlap even if to_thr == from_thr; that's not
	 * allowed now anyway).
	 */
	DUK_ASSERT(nbytes > 0);
	duk_memcpy((void *) to_thr->valstack_top, (const void *) src, (size_t) nbytes);

	p = to_thr->valstack_top;
	to_thr->valstack_top = (duk_tval *) (void *) (((duk_uint8_t *) p) + nbytes);

	if (is_copy) {
		/* Incref copies, keep originals. */
		q = to_thr->valstack_top;
		while (p < q) {
			DUK_TVAL_INCREF(to_thr, p);  /* no side effects */
			p++;
		}
	} else {
		/* No net refcount change. */
		p = from_thr->valstack_top;
		q = (duk_tval *) (void *) (((duk_uint8_t *) p) - nbytes);
		from_thr->valstack_top = q;

		while (p > q) {
			p--;
			DUK_TVAL_SET_UNDEFINED(p);
			/* XXX: fast primitive to set a bunch of values to UNDEFINED */
		}
	}
}

/* Internal helper: reserve a gap of 'count' elements at 'idx_base' and return a
 * pointer to the gap.  Values in the gap are garbage and MUST be initialized by
 * the caller before any side effects may occur.  The caller must ensure there's
 * enough stack reserve for 'count' values.
 */
DUK_INTERNAL duk_tval *duk_reserve_gap(duk_hthread *thr, duk_idx_t idx_base, duk_idx_t count) {
	duk_tval *tv_src;
	duk_tval *tv_dst;
	duk_size_t gap_bytes;
	duk_size_t copy_bytes;

	/* Caller is responsible for ensuring there's enough preallocated
	 * value stack.
	 */
	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(count >= 0);
	DUK_ASSERT((duk_size_t) (thr->valstack_end - thr->valstack_top) >= (duk_size_t) count);

	tv_src = thr->valstack_bottom + idx_base;
	gap_bytes = (duk_size_t) count * sizeof(duk_tval);
	tv_dst = (duk_tval *) (void *) ((duk_uint8_t *) tv_src + gap_bytes);
	copy_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_top - (duk_uint8_t *) tv_src);
	thr->valstack_top = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_top + gap_bytes);
	duk_memmove((void *) tv_dst, (const void *) tv_src, copy_bytes);

	/* Values in the gap are left as garbage: caller must fill them in
	 * and INCREF them before any side effects.
	 */
	return tv_src;
}

/*
 *  Get/opt/require
 */

DUK_EXTERNAL void duk_require_undefined(duk_hthread *thr, duk_idx_t idx) {
	duk_tval *tv;

	DUK_ASSERT_API_ENTRY(thr);

	tv = duk_get_tval_or_unused(thr, idx);
	DUK_ASSERT(tv != NULL);
	if (DUK_UNLIKELY(!DUK_TVAL_IS_UNDEFINED(tv))) {
		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "undefined", DUK_STR_NOT_UNDEFINED);
		DUK_WO_NORETURN(return;);
	}
}

DUK_EXTERNAL void duk_require_null(duk_hthread *thr, duk_idx_t idx) {
	duk_tval *tv;

	DUK_ASSERT_API_ENTRY(thr);

	tv = duk_get_tval_or_unused(thr, idx);
	DUK_ASSERT(tv != NULL);
	if (DUK_UNLIKELY(!DUK_TVAL_IS_NULL(tv))) {
		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "null", DUK_STR_NOT_NULL);
		DUK_WO_NORETURN(return;);
	}
}

DUK_LOCAL DUK_ALWAYS_INLINE duk_bool_t duk__get_boolean_raw(duk_hthread *thr, duk_idx_t idx, duk_bool_t def_value) {
	duk_bool_t ret;
	duk_tval *tv;

	DUK_CTX_ASSERT_VALID(thr);

	tv = duk_get_tval_or_unused(thr, idx);
	DUK_ASSERT(tv != NULL);
	if (DUK_TVAL_IS_BOOLEAN(tv)) {
		ret = DUK_TVAL_GET_BOOLEAN(tv);
		DUK_ASSERT(ret == 0 || ret == 1);
	} else {
		ret = def_value;
		/* Not guaranteed to be 0 or 1. */
	}

	return ret;
}

DUK_EXTERNAL duk_bool_t duk_get_boolean(duk_hthread *thr, duk_idx_t idx) {
	DUK_ASSERT_API_ENTRY(thr);

	return duk__get_boolean_raw(thr, idx, 0);  /* default: false */
}

DUK_EXTERNAL duk_bool_t duk_get_boolean_default(duk_hthread *thr, duk_idx_t idx, duk_bool_t def_value) {
	DUK_ASSERT_API_ENTRY(thr);

	return duk__get_boolean_raw(thr, idx, def_value);
}

DUK_EXTERNAL duk_bool_t duk_require_boolean(duk_hthread *thr, duk_idx_t idx) {
	duk_tval *tv;
	duk_bool_t ret;

	DUK_ASSERT_API_ENTRY(thr);

	tv = duk_get_tval_or_unused(thr, idx);
	DUK_ASSERT(tv != NULL);
	if (DUK_LIKELY(DUK_TVAL_IS_BOOLEAN(tv))) {
		ret = DUK_TVAL_GET_BOOLEAN(tv);
		DUK_ASSERT(ret == 0 || ret == 1);
		return ret;
	} else {
		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "boolean", DUK_STR_NOT_BOOLEAN);
		DUK_WO_NORETURN(return 0;);
	}
}

DUK_EXTERNAL duk_bool_t duk_opt_boolean(duk_hthread *thr, duk_idx_t idx, duk_bool_t def_value) {
	DUK_ASSERT_API_ENTRY(thr);

	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
		return def_value;
	}
	return duk_require_boolean(thr, idx);
}

DUK_LOCAL DUK_ALWAYS_INLINE duk_double_t duk__get_number_raw(duk_hthread *thr, duk_idx_t idx, duk_double_t def_value) {
	duk_double_union ret;
	duk_tval *tv;

	DUK_CTX_ASSERT_VALID(thr);

	tv = duk_get_tval_or_unused(thr, idx);
	DUK_ASSERT(tv != NULL);
#if defined(DUK_USE_FASTINT)
	if (DUK_TVAL_IS_FASTINT(tv)) {
		ret.d = (duk_double_t) DUK_TVAL_GET_FASTINT(tv);  /* XXX: cast trick */
	}
	else
#endif
	if (DUK_TVAL_IS_DOUBLE(tv)) {
		/* When using packed duk_tval, number must be in NaN-normalized form
		 * for it to be a duk_tval, so no need to normalize.  NOP for unpacked
		 * duk_tval.
		 */
		ret.d = DUK_TVAL_GET_DOUBLE(tv);
		DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&ret));
	} else {
		ret.d = def_value;
		/* Default value (including NaN) may not be normalized. */
	}

	return ret.d;
}

DUK_EXTERNAL duk_double_t duk_get_number(duk_hthread *thr, duk_idx_t idx) {
	DUK_ASSERT_API_ENTRY(thr);
	return duk__get_number_raw(thr, idx, DUK_DOUBLE_NAN);  /* default: NaN */
}

DUK_EXTERNAL duk_double_t duk_get_number_default(duk_hthread *thr, duk_idx_t idx, duk_double_t def_value) {
	DUK_ASSERT_API_ENTRY(thr);
	return duk__get_number_raw(thr, idx, def_value);
}

DUK_EXTERNAL duk_double_t duk_require_number(duk_hthread *thr, duk_idx_t idx) {
	duk_tval *tv;
	duk_double_union ret;

	DUK_ASSERT_API_ENTRY(thr);

	tv = duk_get_tval_or_unused(thr, idx);
	DUK_ASSERT(tv != NULL);
	if (DUK_UNLIKELY(!DUK_TVAL_IS_NUMBER(tv))) {
		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "number", DUK_STR_NOT_NUMBER);
		DUK_WO_NORETURN(return 0.0;);
	}

	ret.d = DUK_TVAL_GET_NUMBER(tv);

	/* When using packed duk_tval, number must be in NaN-normalized form
	 * for it to be a duk_tval, so no need to normalize.  NOP for unpacked
	 * duk_tval.
	 */
	DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&ret));
	return ret.d;
}

DUK_EXTERNAL duk_double_t duk_opt_number(duk_hthread *thr, duk_idx_t idx, duk_double_t def_value) {
	DUK_ASSERT_API_ENTRY(thr);

	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
		/* User provided default is not NaN normalized. */
		return def_value;
	}
	return duk_require_number(thr, idx);
}

DUK_EXTERNAL duk_int_t duk_get_int(duk_hthread *thr, duk_idx_t idx) {
	DUK_ASSERT_API_ENTRY(thr);

	return (duk_int_t) duk__api_coerce_d2i(thr, idx, 0 /*def_value*/, 0 /*require*/);
}

DUK_EXTERNAL duk_uint_t duk_get_uint(duk_hthread *thr, duk_idx_t idx) {
	DUK_ASSERT_API_ENTRY(thr);

	return (duk_uint_t) duk__api_coerce_d2ui(thr, idx, 0 /*def_value*/, 0 /*require*/);
}

DUK_EXTERNAL duk_int_t duk_get_int_default(duk_hthread *thr, duk_idx_t idx, duk_int_t def_value) {
	DUK_ASSERT_API_ENTRY(thr);

	return (duk_int_t) duk__api_coerce_d2i(thr, idx, def_value, 0 /*require*/);
}

DUK_EXTERNAL duk_uint_t duk_get_uint_default(duk_hthread *thr, duk_idx_t idx, duk_uint_t def_value) {
	DUK_ASSERT_API_ENTRY(thr);

	return (duk_uint_t) duk__api_coerce_d2ui(thr, idx, def_value, 0 /*require*/);
}

DUK_EXTERNAL duk_int_t duk_require_int(duk_hthread *thr, duk_idx_t idx) {
	DUK_ASSERT_API_ENTRY(thr);

	return (duk_int_t) duk__api_coerce_d2i(thr, idx, 0 /*def_value*/, 1 /*require*/);
}

DUK_EXTERNAL duk_uint_t duk_require_uint(duk_hthread *thr, duk_idx_t idx) {
	DUK_ASSERT_API_ENTRY(thr);

	return (duk_uint_t) duk__api_coerce_d2ui(thr, idx, 0 /*def_value*/, 1 /*require*/);
}

DUK_EXTERNAL duk_int_t duk_opt_int(duk_hthread *thr, duk_idx_t idx, duk_int_t def_value) {
	DUK_ASSERT_API_ENTRY(thr);

	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
		return def_value;
	}
	return duk_require_int(thr, idx);
}

DUK_EXTERNAL duk_uint_t duk_opt_uint(duk_hthread *thr, duk_idx_t idx, duk_uint_t def_value) {
	DUK_ASSERT_API_ENTRY(thr);

	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
		return def_value;
	}
	return duk_require_uint(thr, idx);
}

DUK_EXTERNAL const char *duk_get_lstring(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len) {
	duk_hstring *h;
	const char *ret;
	duk_size_t len;

	DUK_ASSERT_API_ENTRY(thr);

	h = duk_get_hstring(thr, idx);
	if (h != NULL) {
		len = DUK_HSTRING_GET_BYTELEN(h);
		ret = (const char *) DUK_HSTRING_GET_DATA(h);
	} else {
		len = 0;
		ret = NULL;
	}

	if (out_len != NULL) {
		*out_len = len;
	}
	return ret;
}

DUK_EXTERNAL const char *duk_require_lstring(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len) {
	duk_hstring *h;

	DUK_ASSERT_API_ENTRY(thr);

	h = duk_require_hstring(thr, idx);
	DUK_ASSERT(h != NULL);
	if (out_len) {
		*out_len = DUK_HSTRING_GET_BYTELEN(h);
	}
	return (const char *) DUK_HSTRING_GET_DATA(h);
}

DUK_INTERNAL const char *duk_require_lstring_notsymbol(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len) {
	duk_hstring *h;

	DUK_ASSERT_API_ENTRY(thr);

	h = duk_require_hstring_notsymbol(thr, idx);
	DUK_ASSERT(h != NULL);
	if (out_len) {
		*out_len = DUK_HSTRING_GET_BYTELEN(h);
	}
	return (const char *) DUK_HSTRING_GET_DATA(h);
}

DUK_EXTERNAL const char *duk_get_string(duk_hthread *thr, duk_idx_t idx) {
	duk_hstring *h;

	DUK_ASSERT_API_ENTRY(thr);

	h = duk_get_hstring(thr, idx);
	if (h != NULL) {
		return (const char *) DUK_HSTRING_GET_DATA(h);
	} else {
		return NULL;
	}
}

DUK_EXTERNAL const char *duk_opt_lstring(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len, const char *def_ptr, duk_size_t def_len) {
	DUK_ASSERT_API_ENTRY(thr);

	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
		if (out_len != NULL) {
			*out_len = def_len;
		}
		return def_ptr;
	}
	return duk_require_lstring(thr, idx, out_len);
}

DUK_EXTERNAL const char *duk_opt_string(duk_hthread *thr, duk_idx_t idx, const char *def_ptr) {
	DUK_ASSERT_API_ENTRY(thr);

	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
		return def_ptr;
	}
	return duk_require_string(thr, idx);
}

DUK_EXTERNAL const char *duk_get_lstring_default(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len, const char *def_ptr, duk_size_t def_len) {
	duk_hstring *h;
	const char *ret;
	duk_size_t len;

	DUK_ASSERT_API_ENTRY(thr);

	h = duk_get_hstring(thr, idx);
	if (h != NULL) {
		len = DUK_HSTRING_GET_BYTELEN(h);
		ret = (const char *) DUK_HSTRING_GET_DATA(h);
	} else {
		len = def_len;
		ret = def_ptr;
	}

	if (out_len != NULL) {
		*out_len = len;
	}
	return ret;
}

DUK_EXTERNAL const char *duk_get_string_default(duk_hthread *thr, duk_idx_t idx, const char *def_value) {
	duk_hstring *h;

	DUK_ASSERT_API_ENTRY(thr);

	h = duk_get_hstring(thr, idx);
	if (h != NULL) {
		return (const char *) DUK_HSTRING_GET_DATA(h);
	} else {
		return def_value;
	}
}

DUK_INTERNAL const char *duk_get_string_notsymbol(duk_hthread *thr, duk_idx_t idx) {
	duk_hstring *h;

	DUK_ASSERT_API_ENTRY(thr);

	h = duk_get_hstring_notsymbol(thr, idx);
	if (h) {
		return (const char *) DUK_HSTRING_GET_DATA(h);
	} else {
		return NULL;
	}
}

DUK_EXTERNAL const char *duk_require_string(duk_hthread *thr, duk_idx_t idx) {
	DUK_ASSERT_API_ENTRY(thr);

	return duk_require_lstring(thr, idx, NULL);
}

DUK_INTERNAL const char *duk_require_string_notsymbol(duk_hthread *thr, duk_idx_t idx) {
	duk_hstring *h;

	DUK_ASSERT_API_ENTRY(thr);

	h = duk_require_hstring_notsymbol(thr, idx);
	DUK_ASSERT(h != NULL);
	return (const char *) DUK_HSTRING_GET_DATA(h);
}

DUK_EXTERNAL void duk_require_object(duk_hthread *thr, duk_idx_t idx) {
	duk_tval *tv;

	DUK_ASSERT_API_ENTRY(thr);

	tv = duk_get_tval_or_unused(thr, idx);
	DUK_ASSERT(tv != NULL);
	if (DUK_UNLIKELY(!DUK_TVAL_IS_OBJECT(tv))) {
		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "object", DUK_STR_NOT_OBJECT);
		DUK_WO_NORETURN(return;);
	}
}

DUK_LOCAL void *duk__get_pointer_raw(duk_hthread *thr, duk_idx_t idx, void *def_value) {
	duk_tval *tv;
	void *p;

	DUK_CTX_ASSERT_VALID(thr);

	tv = duk_get_tval_or_unused(thr, idx);
	DUK_ASSERT(tv != NULL);
	if (!DUK_TVAL_IS_POINTER(tv)) {
		return def_value;
	}

	p = DUK_TVAL_GET_POINTER(tv);  /* may be NULL */
	return p;
}

DUK_EXTERNAL void *duk_get_pointer(duk_hthread *thr, duk_idx_t idx) {
	DUK_ASSERT_API_ENTRY(thr);
	return duk__get_pointer_raw(thr, idx, NULL /*def_value*/);
}

DUK_EXTERNAL void *duk_opt_pointer(duk_hthread *thr, duk_idx_t idx, void *def_value) {
	DUK_ASSERT_API_ENTRY(thr);

	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
		return def_value;
	}
	return duk_require_pointer(thr, idx);
}

DUK_EXTERNAL void *duk_get_pointer_default(duk_hthread *thr, duk_idx_t idx, void *def_value) {
	DUK_ASSERT_API_ENTRY(thr);
	return duk__get_pointer_raw(thr, idx, def_value);
}

DUK_EXTERNAL void *duk_require_pointer(duk_hthread *thr, duk_idx_t idx) {
	duk_tval *tv;
	void *p;

	DUK_ASSERT_API_ENTRY(thr);

	/* Note: here we must be wary of the fact that a pointer may be
	 * valid and be a NULL.
	 */
	tv = duk_get_tval_or_unused(thr, idx);
	DUK_ASSERT(tv != NULL);
	if (DUK_UNLIKELY(!DUK_TVAL_IS_POINTER(tv))) {
		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "pointer", DUK_STR_NOT_POINTER);
		DUK_WO_NORETURN(return NULL;);
	}
	p = DUK_TVAL_GET_POINTER(tv);  /* may be NULL */
	return p;
}

#if 0  /*unused*/
DUK_INTERNAL void *duk_get_voidptr(duk_hthread *thr, duk_idx_t idx) {
	duk_tval *tv;
	duk_heaphdr *h;

	DUK_ASSERT_API_ENTRY(thr);

	tv = duk_get_tval_or_unused(thr, idx);
	DUK_ASSERT(tv != NULL);
	if (!DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
		return NULL;
	}

	h = DUK_TVAL_GET_HEAPHDR(tv);
	DUK_ASSERT(h != NULL);
	return (void *) h;
}
#endif

DUK_LOCAL void *duk__get_buffer_helper(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size, void *def_ptr, duk_size_t def_size, duk_bool_t throw_flag) {
	duk_hbuffer *h;
	void *ret;
	duk_size_t len;
	duk_tval *tv;

	DUK_CTX_ASSERT_VALID(thr);

	if (out_size != NULL) {
		*out_size = 0;
	}

	tv = duk_get_tval_or_unused(thr, idx);
	DUK_ASSERT(tv != NULL);
	if (DUK_LIKELY(DUK_TVAL_IS_BUFFER(tv))) {
		h = DUK_TVAL_GET_BUFFER(tv);
		DUK_ASSERT(h != NULL);

		len = DUK_HBUFFER_GET_SIZE(h);
		ret = DUK_HBUFFER_GET_DATA_PTR(thr->heap, h);
	} else {
		if (throw_flag) {
			DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "buffer", DUK_STR_NOT_BUFFER);
			DUK_WO_NORETURN(return NULL;);
		}
		len = def_size;
		ret = def_ptr;
	}

	if (out_size != NULL) {
		*out_size = len;
	}
	return ret;
}

DUK_EXTERNAL void *duk_get_buffer(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size) {
	DUK_ASSERT_API_ENTRY(thr);

	return duk__get_buffer_helper(thr, idx, out_size, NULL /*def_ptr*/, 0 /*def_size*/, 0 /*throw_flag*/);
}

DUK_EXTERNAL void *duk_opt_buffer(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size, void *def_ptr, duk_size_t def_size) {
	DUK_ASSERT_API_ENTRY(thr);

	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
		if (out_size != NULL) {
			*out_size = def_size;
		}
		return def_ptr;
	}
	return duk_require_buffer(thr, idx, out_size);
}

DUK_EXTERNAL void *duk_get_buffer_default(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size, void *def_ptr, duk_size_t def_len) {
	DUK_ASSERT_API_ENTRY(thr);

	return duk__get_buffer_helper(thr, idx, out_size, def_ptr, def_len, 0 /*throw_flag*/);
}

DUK_EXTERNAL void *duk_require_buffer(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size) {
	DUK_ASSERT_API_ENTRY(thr);

	return duk__get_buffer_helper(thr, idx, out_size, NULL /*def_ptr*/, 0 /*def_size*/, 1 /*throw_flag*/);
}

/* Get the active buffer data area for a plain buffer or a buffer object.
 * Return NULL if the the value is not a buffer.  Note that a buffer may
 * have a NULL data pointer when its size is zero, the optional 'out_isbuffer'
 * argument allows caller to detect this reliably.
 */
DUK_INTERNAL void *duk_get_buffer_data_raw(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size, void *def_ptr, duk_size_t def_size, duk_bool_t throw_flag, duk_bool_t *out_isbuffer) {
	duk_tval *tv;

	DUK_ASSERT_API_ENTRY(thr);

	if (out_isbuffer != NULL) {
		*out_isbuffer = 0;
	}
	if (out_size != NULL) {
		*out_size = def_size;
	}

	tv = duk_get_tval_or_unused(thr, idx);
	DUK_ASSERT(tv != NULL);

	if (DUK_TVAL_IS_BUFFER(tv)) {
		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
		DUK_ASSERT(h != NULL);
		if (out_size != NULL) {
			*out_size = DUK_HBUFFER_GET_SIZE(h);
		}
		if (out_isbuffer != NULL) {
			*out_isbuffer = 1;
		}
		return (void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h);  /* may be NULL (but only if size is 0) */
	}
#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
	else if (DUK_TVAL_IS_OBJECT(tv)) {
		duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
		DUK_ASSERT(h != NULL);
		if (DUK_HOBJECT_IS_BUFOBJ(h)) {
			/* XXX: this is probably a useful shared helper: for a
			 * duk_hbufobj, get a validated buffer pointer/length.
			 */
			duk_hbufobj *h_bufobj = (duk_hbufobj *) h;
			DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);

			if (h_bufobj->buf != NULL &&
			    DUK_HBUFOBJ_VALID_SLICE(h_bufobj)) {
				duk_uint8_t *p;

				p = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf);
				if (out_size != NULL) {
					*out_size = (duk_size_t) h_bufobj->length;
				}
				if (out_isbuffer != NULL) {
					*out_isbuffer = 1;
				}
				return (void *) (p + h_bufobj->offset);
			}
			/* if slice not fully valid, treat as error */
		}
	}
#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */

	if (throw_flag) {
		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "buffer", DUK_STR_NOT_BUFFER);
		DUK_WO_NORETURN(return NULL;);
	}
	return def_ptr;
}

DUK_EXTERNAL void *duk_get_buffer_data(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size) {
	DUK_ASSERT_API_ENTRY(thr);
	return duk_get_buffer_data_raw(thr, idx, out_size, NULL /*def_ptr*/, 0 /*def_size*/, 0 /*throw_flag*/, NULL);
}

DUK_EXTERNAL void *duk_get_buffer_data_default(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size, void *def_ptr, duk_size_t def_size) {
	DUK_ASSERT_API_ENTRY(thr);
	return duk_get_buffer_data_raw(thr, idx, out_size, def_ptr, def_size, 0 /*throw_flag*/, NULL);
}

DUK_EXTERNAL void *duk_opt_buffer_data(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size, void *def_ptr, duk_size_t def_size) {
	DUK_ASSERT_API_ENTRY(thr);

	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
		if (out_size != NULL) {
			*out_size = def_size;
		}
		return def_ptr;
	}
	return duk_require_buffer_data(thr, idx, out_size);
}

DUK_EXTERNAL void *duk_require_buffer_data(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size) {
	DUK_ASSERT_API_ENTRY(thr);
	return duk_get_buffer_data_raw(thr, idx, out_size, NULL /*def_ptr*/, 0 /*def_size*/, 1 /*throw_flag*/, NULL);
}

/* Raw helper for getting a value from the stack, checking its tag.
 * The tag cannot be a number because numbers don't have an internal
 * tag in the packed representation.
 */

DUK_LOCAL duk_heaphdr *duk__get_tagged_heaphdr_raw(duk_hthread *thr, duk_idx_t idx, duk_uint_t tag) {
	duk_tval *tv;
	duk_heaphdr *ret;

	DUK_CTX_ASSERT_VALID(thr);

	tv = duk_get_tval_or_unused(thr, idx);
	DUK_ASSERT(tv != NULL);
	if (DUK_TVAL_GET_TAG(tv) != tag) {
		return (duk_heaphdr *) NULL;
	}

	ret = DUK_TVAL_GET_HEAPHDR(tv);
	DUK_ASSERT(ret != NULL);  /* tagged null pointers should never occur */
	return ret;

}

DUK_INTERNAL duk_hstring *duk_get_hstring(duk_hthread *thr, duk_idx_t idx) {
	DUK_ASSERT_API_ENTRY(thr);
	return (duk_hstring *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_STRING);
}

DUK_INTERNAL duk_hstring *duk_get_hstring_notsymbol(duk_hthread *thr, duk_idx_t idx) {
	duk_hstring *h;

	DUK_ASSERT_API_ENTRY(thr);

	h = (duk_hstring *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_STRING);
	if (DUK_UNLIKELY(h && DUK_HSTRING_HAS_SYMBOL(h))) {
		return NULL;
	}
	return h;
}

DUK_INTERNAL duk_hstring *duk_require_hstring(duk_hthread *thr, duk_idx_t idx) {
	duk_hstring *h;

	DUK_ASSERT_API_ENTRY(thr);

	h = (duk_hstring *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_STRING);
	if (DUK_UNLIKELY(h == NULL)) {
		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "string", DUK_STR_NOT_STRING);
		DUK_WO_NORETURN(return NULL;);
	}
	return h;
}

DUK_INTERNAL duk_hstring *duk_require_hstring_notsymbol(duk_hthread *thr, duk_idx_t idx) {
	duk_hstring *h;

	DUK_ASSERT_API_ENTRY(thr);

	h = (duk_hstring *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_STRING);
	if (DUK_UNLIKELY(h == NULL || DUK_HSTRING_HAS_SYMBOL(h))) {
		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "string", DUK_STR_NOT_STRING);
		DUK_WO_NORETURN(return NULL;);
	}
	return h;
}

DUK_INTERNAL duk_hobject *duk_get_hobject(duk_hthread *thr, duk_idx_t idx) {
	DUK_ASSERT_API_ENTRY(thr);
	return (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
}

DUK_INTERNAL duk_hobject *duk_require_hobject(duk_hthread *thr, duk_idx_t idx) {
	duk_hobject *h;

	DUK_ASSERT_API_ENTRY(thr);

	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
	if (DUK_UNLIKELY(h == NULL)) {
		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "object", DUK_STR_NOT_OBJECT);
		DUK_WO_NORETURN(return NULL;);
	}
	return h;
}

DUK_INTERNAL duk_hbuffer *duk_get_hbuffer(duk_hthread *thr, duk_idx_t idx) {
	DUK_ASSERT_API_ENTRY(thr);
	return (duk_hbuffer *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_BUFFER);
}

DUK_INTERNAL duk_hbuffer *duk_require_hbuffer(duk_hthread *thr, duk_idx_t idx) {
	duk_hbuffer *h;

	DUK_ASSERT_API_ENTRY(thr);

	h = (duk_hbuffer *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_BUFFER);
	if (DUK_UNLIKELY(h == NULL)) {
		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "buffer", DUK_STR_NOT_BUFFER);
		DUK_WO_NORETURN(return NULL;);
	}
	return h;
}

DUK_INTERNAL duk_hthread *duk_get_hthread(duk_hthread *thr, duk_idx_t idx) {
	duk_hobject *h;

	DUK_ASSERT_API_ENTRY(thr);

	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
	if (DUK_UNLIKELY(h != NULL && !DUK_HOBJECT_IS_THREAD(h))) {
		h = NULL;
	}
	return (duk_hthread *) h;
}

DUK_INTERNAL duk_hthread *duk_require_hthread(duk_hthread *thr, duk_idx_t idx) {
	duk_hobject *h;

	DUK_ASSERT_API_ENTRY(thr);

	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
	if (DUK_UNLIKELY(!(h != NULL && DUK_HOBJECT_IS_THREAD(h)))) {
		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "thread", DUK_STR_NOT_THREAD);
		DUK_WO_NORETURN(return NULL;);
	}
	return (duk_hthread *) h;
}

DUK_INTERNAL duk_hcompfunc *duk_get_hcompfunc(duk_hthread *thr, duk_idx_t idx) {
	duk_hobject *h;

	DUK_ASSERT_API_ENTRY(thr);

	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
	if (DUK_UNLIKELY(h != NULL && !DUK_HOBJECT_IS_COMPFUNC(h))) {
		h = NULL;
	}
	return (duk_hcompfunc *) h;
}

DUK_INTERNAL duk_hcompfunc *duk_require_hcompfunc(duk_hthread *thr, duk_idx_t idx) {
	duk_hobject *h;

	DUK_ASSERT_API_ENTRY(thr);

	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
	if (DUK_UNLIKELY(!(h != NULL && DUK_HOBJECT_IS_COMPFUNC(h)))) {
		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "compiledfunction", DUK_STR_NOT_COMPFUNC);
		DUK_WO_NORETURN(return NULL;);
	}
	return (duk_hcompfunc *) h;
}

DUK_INTERNAL duk_hnatfunc *duk_get_hnatfunc(duk_hthread *thr, duk_idx_t idx) {
	duk_hobject *h;

	DUK_ASSERT_API_ENTRY(thr);

	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
	if (DUK_UNLIKELY(h != NULL && !DUK_HOBJECT_IS_NATFUNC(h))) {
		h = NULL;
	}
	return (duk_hnatfunc *) h;
}

DUK_INTERNAL duk_hnatfunc *duk_require_hnatfunc(duk_hthread *thr, duk_idx_t idx) {
	duk_hobject *h;

	DUK_ASSERT_API_ENTRY(thr);

	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
	if (DUK_UNLIKELY(!(h != NULL && DUK_HOBJECT_IS_NATFUNC(h)))) {
		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "nativefunction", DUK_STR_NOT_NATFUNC);
		DUK_WO_NORETURN(return NULL;);
	}
	return (duk_hnatfunc *) h;
}

DUK_EXTERNAL duk_c_function duk_get_c_function(duk_hthread *thr, duk_idx_t idx) {
	duk_tval *tv;
	duk_hobject *h;
	duk_hnatfunc *f;

	DUK_ASSERT_API_ENTRY(thr);

	tv = duk_get_tval_or_unused(thr, idx);
	DUK_ASSERT(tv != NULL);
	if (DUK_UNLIKELY(!DUK_TVAL_IS_OBJECT(tv))) {
		return NULL;
	}
	h = DUK_TVAL_GET_OBJECT(tv);
	DUK_ASSERT(h != NULL);

	if (DUK_UNLIKELY(!DUK_HOBJECT_IS_NATFUNC(h))) {
		return NULL;
	}
	DUK_ASSERT(DUK_HOBJECT_HAS_NATFUNC(h));
	f = (duk_hnatfunc *) h;

	return f->func;
}

DUK_EXTERNAL duk_c_function duk_opt_c_function(duk_hthread *thr, duk_idx_t idx, duk_c_function def_value) {
	DUK_ASSERT_API_ENTRY(thr);

	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
		return def_value;
	}
	return duk_require_c_function(thr, idx);
}

DUK_EXTERNAL duk_c_function duk_get_c_function_default(duk_hthread *thr, duk_idx_t idx, duk_c_function def_value) {
	duk_c_function ret;

	DUK_ASSERT_API_ENTRY(thr);

	ret = duk_get_c_function(thr, idx);
	if (ret != NULL) {
		return ret;
	}

	return def_value;
}

DUK_EXTERNAL duk_c_function duk_require_c_function(duk_hthread *thr, duk_idx_t idx) {
	duk_c_function ret;

	DUK_ASSERT_API_ENTRY(thr);

	ret = duk_get_c_function(thr, idx);
	if (DUK_UNLIKELY(!ret)) {
		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "nativefunction", DUK_STR_NOT_NATFUNC);
		DUK_WO_NORETURN(return ret;);
	}
	return ret;
}

DUK_EXTERNAL void duk_require_function(duk_hthread *thr, duk_idx_t idx) {
	DUK_ASSERT_API_ENTRY(thr);
	if (DUK_UNLIKELY(!duk_is_function(thr, idx))) {
		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "function", DUK_STR_NOT_FUNCTION);
		DUK_WO_NORETURN(return;);
	}
}

DUK_EXTERNAL void duk_require_constructable(duk_hthread *thr, duk_idx_t idx) {
	duk_hobject *h;

	DUK_ASSERT_API_ENTRY(thr);

	h = duk_require_hobject_accept_mask(thr, idx, DUK_TYPE_MASK_LIGHTFUNC);
	if (DUK_UNLIKELY(h != NULL && !DUK_HOBJECT_HAS_CONSTRUCTABLE(h))) {
		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "constructable", DUK_STR_NOT_CONSTRUCTABLE);
		DUK_WO_NORETURN(return;);
	}
	/* Lightfuncs (h == NULL) are constructable. */
}

DUK_EXTERNAL duk_hthread *duk_get_context(duk_hthread *thr, duk_idx_t idx) {
	DUK_ASSERT_API_ENTRY(thr);

	return duk_get_hthread(thr, idx);
}

DUK_EXTERNAL duk_hthread *duk_require_context(duk_hthread *thr, duk_idx_t idx) {
	DUK_ASSERT_API_ENTRY(thr);

	return duk_require_hthread(thr, idx);
}

DUK_EXTERNAL duk_hthread *duk_opt_context(duk_hthread *thr, duk_idx_t idx, duk_hthread *def_value) {
	DUK_ASSERT_API_ENTRY(thr);

	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
		return def_value;
	}
	return duk_require_context(thr, idx);
}

DUK_EXTERNAL duk_hthread *duk_get_context_default(duk_hthread *thr, duk_idx_t idx, duk_hthread *def_value) {
	duk_hthread *ret;

	DUK_ASSERT_API_ENTRY(thr);

	ret = duk_get_context(thr, idx);
	if (ret != NULL) {
		return ret;
	}

	return def_value;
}

DUK_EXTERNAL void *duk_get_heapptr(duk_hthread *thr, duk_idx_t idx) {
	duk_tval *tv;
	void *ret;

	DUK_ASSERT_API_ENTRY(thr);

	tv = duk_get_tval_or_unused(thr, idx);
	DUK_ASSERT(tv != NULL);
	if (DUK_UNLIKELY(!DUK_TVAL_IS_HEAP_ALLOCATED(tv))) {
		return (void *) NULL;
	}

	ret = (void *) DUK_TVAL_GET_HEAPHDR(tv);
	DUK_ASSERT(ret != NULL);
	return ret;
}

DUK_EXTERNAL void *duk_opt_heapptr(duk_hthread *thr, duk_idx_t idx, void *def_value) {
	DUK_ASSERT_API_ENTRY(thr);

	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
		return def_value;
	}
	return duk_require_heapptr(thr, idx);
}

DUK_EXTERNAL void *duk_get_heapptr_default(duk_hthread *thr, duk_idx_t idx, void *def_value) {
	void *ret;

	DUK_ASSERT_API_ENTRY(thr);

	ret = duk_get_heapptr(thr, idx);
	if (ret != NULL) {
		return ret;
	}

	return def_value;
}

DUK_EXTERNAL void *duk_require_heapptr(duk_hthread *thr, duk_idx_t idx) {
	duk_tval *tv;
	void *ret;

	DUK_ASSERT_API_ENTRY(thr);

	tv = duk_get_tval_or_unused(thr, idx);
	DUK_ASSERT(tv != NULL);
	if (DUK_UNLIKELY(!DUK_TVAL_IS_HEAP_ALLOCATED(tv))) {
		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "heapobject", DUK_STR_UNEXPECTED_TYPE);
		DUK_WO_NORETURN(return NULL;);
	}

	ret = (void *) DUK_TVAL_GET_HEAPHDR(tv);
	DUK_ASSERT(ret != NULL);
	return ret;
}

/* Internal helper for getting/requiring a duk_hobject with possible promotion. */
DUK_LOCAL duk_hobject *duk__get_hobject_promote_mask_raw(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask) {
	duk_uint_t val_mask;
	duk_hobject *res;

	DUK_CTX_ASSERT_VALID(thr);

	res = duk_get_hobject(thr, idx);  /* common case, not promoted */
	if (DUK_LIKELY(res != NULL)) {
		DUK_ASSERT(res != NULL);
		return res;
	}

	val_mask = duk_get_type_mask(thr, idx);
	if (val_mask & type_mask) {
		if (type_mask & DUK_TYPE_MASK_PROMOTE) {
			res = duk_to_hobject(thr, idx);
			DUK_ASSERT(res != NULL);
			return res;
		} else {
			return NULL;  /* accept without promoting */
		}
	}

	if (type_mask & DUK_TYPE_MASK_THROW) {
		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "object", DUK_STR_NOT_OBJECT);
		DUK_WO_NORETURN(return NULL;);
	}
	return NULL;
}

/* Get a duk_hobject * at 'idx'; if the value is not an object but matches the
 * supplied 'type_mask', promote it to an object and return the duk_hobject *.
 * This is useful for call sites which want an object but also accept a plain
 * buffer and/or a lightfunc which gets automatically promoted to an object.
 * Return value is NULL if value is neither an object nor a plain type allowed
 * by the mask.
 */
DUK_INTERNAL duk_hobject *duk_get_hobject_promote_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask) {
	DUK_ASSERT_API_ENTRY(thr);
	return duk__get_hobject_promote_mask_raw(thr, idx, type_mask | DUK_TYPE_MASK_PROMOTE);
}

/* Like duk_get_hobject_promote_mask() but throw a TypeError instead of
 * returning a NULL.
 */
DUK_INTERNAL duk_hobject *duk_require_hobject_promote_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask) {
	DUK_ASSERT_API_ENTRY(thr);
	return duk__get_hobject_promote_mask_raw(thr, idx, type_mask | DUK_TYPE_MASK_THROW | DUK_TYPE_MASK_PROMOTE);
}

/* Require a duk_hobject * at 'idx'; if the value is not an object but matches the
 * supplied 'type_mask', return a NULL instead.  Otherwise throw a TypeError.
 */
DUK_INTERNAL duk_hobject *duk_require_hobject_accept_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask) {
	DUK_ASSERT_API_ENTRY(thr);
	return duk__get_hobject_promote_mask_raw(thr, idx, type_mask | DUK_TYPE_MASK_THROW);
}

DUK_INTERNAL duk_hobject *duk_get_hobject_with_class(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t classnum) {
	duk_hobject *h;

	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT_DISABLE(classnum >= 0);  /* unsigned */
	DUK_ASSERT(classnum <= DUK_HOBJECT_CLASS_MAX);

	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
	if (DUK_UNLIKELY(h != NULL && DUK_HOBJECT_GET_CLASS_NUMBER(h) != classnum)) {
		h = NULL;
	}
	return h;
}

DUK_INTERNAL duk_hobject *duk_require_hobject_with_class(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t classnum) {
	duk_hobject *h;

	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT_DISABLE(classnum >= 0);  /* unsigned */
	DUK_ASSERT(classnum <= DUK_HOBJECT_CLASS_MAX);

	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
	if (DUK_UNLIKELY(!(h != NULL && DUK_HOBJECT_GET_CLASS_NUMBER(h) == classnum))) {
		duk_hstring *h_class;
		h_class = DUK_HTHREAD_GET_STRING(thr, DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(classnum));
		DUK_UNREF(h_class);

		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, (const char *) DUK_HSTRING_GET_DATA(h_class), DUK_STR_UNEXPECTED_TYPE);
		DUK_WO_NORETURN(return NULL;);
	}
	return h;
}

DUK_EXTERNAL duk_size_t duk_get_length(duk_hthread *thr, duk_idx_t idx) {
	duk_tval *tv;

	DUK_ASSERT_API_ENTRY(thr);

	tv = duk_get_tval_or_unused(thr, idx);
	DUK_ASSERT(tv != NULL);

	switch (DUK_TVAL_GET_TAG(tv)) {
	case DUK_TAG_UNDEFINED:
	case DUK_TAG_NULL:
	case DUK_TAG_BOOLEAN:
	case DUK_TAG_POINTER:
		return 0;
#if defined(DUK_USE_PREFER_SIZE)
	/* String and buffer have a virtual non-configurable .length property
	 * which is within size_t range so it can be looked up without specific
	 * type checks.  Lightfuncs inherit from %NativeFunctionPrototype%
	 * which provides an inherited .length accessor; it could be overwritten
	 * to produce unexpected types or values, but just number convert and
	 * duk_size_t cast for now.
	 */
	case DUK_TAG_STRING:
	case DUK_TAG_BUFFER:
	case DUK_TAG_LIGHTFUNC: {
		duk_size_t ret;
		duk_get_prop_stridx(thr, idx, DUK_STRIDX_LENGTH);
		ret = (duk_size_t) duk_to_number_m1(thr);
		duk_pop_unsafe(thr);
		return ret;
	}
#else  /* DUK_USE_PREFER_SIZE */
	case DUK_TAG_STRING: {
		duk_hstring *h = DUK_TVAL_GET_STRING(tv);
		DUK_ASSERT(h != NULL);
		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
			return 0;
		}
		return (duk_size_t) DUK_HSTRING_GET_CHARLEN(h);
	}
	case DUK_TAG_BUFFER: {
		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
		DUK_ASSERT(h != NULL);
		return (duk_size_t) DUK_HBUFFER_GET_SIZE(h);
	}
	case DUK_TAG_LIGHTFUNC: {
		/* We could look up the length from the lightfunc duk_tval,
		 * but since Duktape 2.2 lightfunc .length comes from
		 * %NativeFunctionPrototype% which can be overridden, so
		 * look up the property explicitly.
		 */
		duk_size_t ret;
		duk_get_prop_stridx(thr, idx, DUK_STRIDX_LENGTH);
		ret = (duk_size_t) duk_to_number_m1(thr);
		duk_pop_unsafe(thr);
		return ret;
	}
#endif  /* DUK_USE_PREFER_SIZE */
	case DUK_TAG_OBJECT: {
		duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
		DUK_ASSERT(h != NULL);
		return (duk_size_t) duk_hobject_get_length(thr, h);
	}
#if defined(DUK_USE_FASTINT)
	case DUK_TAG_FASTINT:
#endif
	default:
		/* number or 'unused' */
		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv) || DUK_TVAL_IS_UNUSED(tv));
		return 0;
	}

	DUK_UNREACHABLE();
}

/*
 *  duk_known_xxx() helpers
 *
 *  Used internally when we're 100% sure that a certain index is valid and
 *  contains an object of a certain type.  For example, if we duk_push_object()
 *  we can then safely duk_known_hobject(thr, -1).  These helpers just assert
 *  for the index and type, and if the assumptions are not valid, memory unsafe
 *  behavior happens.
 */

DUK_LOCAL duk_heaphdr *duk__known_heaphdr(duk_hthread *thr, duk_idx_t idx) {
	duk_tval *tv;
	duk_heaphdr *h;

	DUK_CTX_ASSERT_VALID(thr);
	if (idx < 0) {
		tv = thr->valstack_top + idx;
	} else {
		tv = thr->valstack_bottom + idx;
	}
	DUK_ASSERT(tv >= thr->valstack_bottom);
	DUK_ASSERT(tv < thr->valstack_top);
	h = DUK_TVAL_GET_HEAPHDR(tv);
	DUK_ASSERT(h != NULL);
	return h;
}

DUK_INTERNAL duk_hstring *duk_known_hstring(duk_hthread *thr, duk_idx_t idx) {
	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(duk_get_hstring(thr, idx) != NULL);
	return (duk_hstring *) duk__known_heaphdr(thr, idx);
}

DUK_INTERNAL duk_hobject *duk_known_hobject(duk_hthread *thr, duk_idx_t idx) {
	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(duk_get_hobject(thr, idx) != NULL);
	return (duk_hobject *) duk__known_heaphdr(thr, idx);
}

DUK_INTERNAL duk_hbuffer *duk_known_hbuffer(duk_hthread *thr, duk_idx_t idx) {
	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(duk_get_hbuffer(thr, idx) != NULL);
	return (duk_hbuffer *) duk__known_heaphdr(thr, idx);
}

DUK_INTERNAL duk_hcompfunc *duk_known_hcompfunc(duk_hthread *thr, duk_idx_t idx) {
	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(duk_get_hcompfunc(thr, idx) != NULL);
	return (duk_hcompfunc *) duk__known_heaphdr(thr, idx);
}

DUK_INTERNAL duk_hnatfunc *duk_known_hnatfunc(duk_hthread *thr, duk_idx_t idx) {
	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(duk_get_hnatfunc(thr, idx) != NULL);
	return (duk_hnatfunc *) duk__known_heaphdr(thr, idx);
}

DUK_EXTERNAL void duk_set_length(duk_hthread *thr, duk_idx_t idx, duk_size_t len) {
	DUK_ASSERT_API_ENTRY(thr);

	idx = duk_normalize_index(thr, idx);
	duk_push_uint(thr, (duk_uint_t) len);
	duk_put_prop_stridx(thr, idx, DUK_STRIDX_LENGTH);
}

/*
 *  Conversions and coercions
 *
 *  The conversion/coercions are in-place operations on the value stack.
 *  Some operations are implemented here directly, while others call a
 *  helper in duk_js_ops.c after validating arguments.
 */

/* E5 Section 8.12.8 */

DUK_LOCAL duk_bool_t duk__defaultvalue_coerce_attempt(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t func_stridx) {
	if (duk_get_prop_stridx(thr, idx, func_stridx)) {
		/* [ ... func ] */
		if (duk_is_callable(thr, -1)) {
			duk_dup(thr, idx);         /* -> [ ... func this ] */
			duk_call_method(thr, 0);     /* -> [ ... retval ] */
			if (duk_is_primitive(thr, -1)) {
				duk_replace(thr, idx);
				return 1;
			}
			/* [ ... retval ]; popped below */
		}
	}
	duk_pop_unsafe(thr);  /* [ ... func/retval ] -> [ ... ] */
	return 0;
}

DUK_EXTERNAL void duk_to_undefined(duk_hthread *thr, duk_idx_t idx) {
	duk_tval *tv;

	DUK_ASSERT_API_ENTRY(thr);

	tv = duk_require_tval(thr, idx);
	DUK_ASSERT(tv != NULL);
	DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv);  /* side effects */
}

DUK_EXTERNAL void duk_to_null(duk_hthread *thr, duk_idx_t idx) {
	duk_tval *tv;

	DUK_ASSERT_API_ENTRY(thr);

	tv = duk_require_tval(thr, idx);
	DUK_ASSERT(tv != NULL);
	DUK_TVAL_SET_NULL_UPDREF(thr, tv);  /* side effects */
}

/* E5 Section 9.1 */
DUK_LOCAL const char * const duk__toprim_hint_strings[3] = {
	"default", "string", "number"
};
DUK_LOCAL void duk__to_primitive_helper(duk_hthread *thr, duk_idx_t idx, duk_int_t hint, duk_bool_t check_symbol) {
	/* Inline initializer for coercers[] is not allowed by old compilers like BCC. */
	duk_small_uint_t coercers[2];

	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(hint == DUK_HINT_NONE || hint == DUK_HINT_NUMBER || hint == DUK_HINT_STRING);

	idx = duk_require_normalize_index(thr, idx);

	/* If already primitive, return as is. */
	if (!duk_check_type_mask(thr, idx, DUK_TYPE_MASK_OBJECT |
	                                   DUK_TYPE_MASK_LIGHTFUNC |
	                                   DUK_TYPE_MASK_BUFFER)) {
		DUK_ASSERT(!duk_is_buffer(thr, idx));  /* duk_to_string() relies on this behavior */
		return;
	}

	/* @@toPrimitive lookup.  Also do for plain buffers and lightfuncs
	 * which mimic objects.
	 */
	if (check_symbol && duk_get_method_stridx(thr, idx, DUK_STRIDX_WELLKNOWN_SYMBOL_TO_PRIMITIVE)) {
		DUK_ASSERT(hint >= 0 && (duk_size_t) hint < sizeof(duk__toprim_hint_strings) / sizeof(const char *));
		duk_dup(thr, idx);
		duk_push_string(thr, duk__toprim_hint_strings[hint]);
		duk_call_method(thr, 1);  /* [ ... method value hint ] -> [ ... res] */
		if (duk_check_type_mask(thr, -1, DUK_TYPE_MASK_OBJECT |
	                                         DUK_TYPE_MASK_LIGHTFUNC |
		                                 DUK_TYPE_MASK_BUFFER)) {
			goto fail;
		}
		duk_replace(thr, idx);
		return;
	}

	/* Objects are coerced based on E5 specification.
	 * Lightfuncs are coerced because they behave like
	 * objects even if they're internally a primitive
	 * type.  Same applies to plain buffers, which behave
	 * like ArrayBuffer objects since Duktape 2.x.
	 */

	/* Hint magic for Date is unnecessary in ES2015 because of
	 * Date.prototype[@@toPrimitive].  However, it is needed if
	 * symbol support is not enabled.
	 */
#if defined(DUK_USE_SYMBOL_BUILTIN)
	if (hint == DUK_HINT_NONE) {
		hint = DUK_HINT_NUMBER;
	}
#else  /* DUK_USE_SYMBOL_BUILTIN */
	if (hint == DUK_HINT_NONE) {
		duk_small_uint_t class_number;

		class_number = duk_get_class_number(thr, idx);
		if (class_number == DUK_HOBJECT_CLASS_DATE) {
			hint = DUK_HINT_STRING;
		} else {
			hint = DUK_HINT_NUMBER;
		}
	}
#endif  /* DUK_USE_SYMBOL_BUILTIN */

	coercers[0] = DUK_STRIDX_VALUE_OF;
	coercers[1] = DUK_STRIDX_TO_STRING;
	if (hint == DUK_HINT_STRING) {
		coercers[0] = DUK_STRIDX_TO_STRING;
		coercers[1] = DUK_STRIDX_VALUE_OF;
	}

	if (duk__defaultvalue_coerce_attempt(thr, idx, coercers[0])) {
		DUK_ASSERT(!duk_is_buffer(thr, idx));  /* duk_to_string() relies on this behavior */
		return;
	}

	if (duk__defaultvalue_coerce_attempt(thr, idx, coercers[1])) {
		DUK_ASSERT(!duk_is_buffer(thr, idx));  /* duk_to_string() relies on this behavior */
		return;
	}

 fail:
	DUK_ERROR_TYPE(thr, DUK_STR_TOPRIMITIVE_FAILED);
	DUK_WO_NORETURN(return;);
}

DUK_EXTERNAL void duk_to_primitive(duk_hthread *thr, duk_idx_t idx, duk_int_t hint) {
	duk__to_primitive_helper(thr, idx, hint, 1 /*check_symbol*/);
}

#if defined(DUK_USE_SYMBOL_BUILTIN)
DUK_INTERNAL void duk_to_primitive_ordinary(duk_hthread *thr, duk_idx_t idx, duk_int_t hint) {
	duk__to_primitive_helper(thr, idx, hint, 0 /*check_symbol*/);
}
#endif

/* E5 Section 9.2 */
DUK_EXTERNAL duk_bool_t duk_to_boolean(duk_hthread *thr, duk_idx_t idx) {
	duk_tval *tv;
	duk_bool_t val;

	DUK_ASSERT_API_ENTRY(thr);

	idx = duk_require_normalize_index(thr, idx);
	tv = DUK_GET_TVAL_POSIDX(thr, idx);
	DUK_ASSERT(tv != NULL);

	val = duk_js_toboolean(tv);
	DUK_ASSERT(val == 0 || val == 1);

	/* Note: no need to re-lookup tv, conversion is side effect free. */
	DUK_ASSERT(tv != NULL);
	DUK_TVAL_SET_BOOLEAN_UPDREF(thr, tv, val);  /* side effects */
	return val;
}

DUK_INTERNAL duk_bool_t duk_to_boolean_top_pop(duk_hthread *thr) {
	duk_tval *tv;
	duk_bool_t val;

	DUK_ASSERT_API_ENTRY(thr);

	tv = duk_require_tval(thr, -1);
	DUK_ASSERT(tv != NULL);

	val = duk_js_toboolean(tv);
	DUK_ASSERT(val == 0 || val == 1);

	duk_pop_unsafe(thr);
	return val;
}

DUK_EXTERNAL duk_double_t duk_to_number(duk_hthread *thr, duk_idx_t idx) {
	duk_tval *tv;
	duk_double_t d;

	DUK_ASSERT_API_ENTRY(thr);

	/* XXX: No need to normalize; the whole operation could be inlined here to
	 * avoid 'tv' re-lookup.
	 */
	idx = duk_require_normalize_index(thr, idx);
	tv = DUK_GET_TVAL_POSIDX(thr, idx);
	DUK_ASSERT(tv != NULL);
	d = duk_js_tonumber(thr, tv);  /* XXX: fastint coercion? now result will always be a non-fastint */

	/* ToNumber() may have side effects so must relookup 'tv'. */
	tv = DUK_GET_TVAL_POSIDX(thr, idx);
	DUK_TVAL_SET_NUMBER_UPDREF(thr, tv, d);  /* side effects */
	return d;
}

DUK_INTERNAL duk_double_t duk_to_number_m1(duk_hthread *thr) {
	DUK_ASSERT_API_ENTRY(thr);
	return duk_to_number(thr, -1);
}
DUK_INTERNAL duk_double_t duk_to_number_m2(duk_hthread *thr) {
	DUK_ASSERT_API_ENTRY(thr);
	return duk_to_number(thr, -2);
}

DUK_INTERNAL duk_double_t duk_to_number_tval(duk_hthread *thr, duk_tval *tv) {
#if defined(DUK_USE_PREFER_SIZE)
	duk_double_t res;

	DUK_ASSERT_API_ENTRY(thr);

	duk_push_tval(thr, tv);
	res = duk_to_number_m1(thr);
	duk_pop_unsafe(thr);
	return res;
#else
	duk_double_t res;
	duk_tval *tv_dst;

	DUK_ASSERT_API_ENTRY(thr);
	DUK__ASSERT_SPACE();

	tv_dst = thr->valstack_top++;
	DUK_TVAL_SET_TVAL(tv_dst, tv);
	DUK_TVAL_INCREF(thr, tv_dst);  /* decref not necessary */
	res = duk_to_number_m1(thr);  /* invalidates tv_dst */

	tv_dst = --thr->valstack_top;
	DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_dst));
	DUK_ASSERT(!DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv_dst));  /* plain number */
	DUK_TVAL_SET_UNDEFINED(tv_dst);  /* valstack init policy */

	return res;
#endif
}

/* XXX: combine all the integer conversions: they share everything
 * but the helper function for coercion.
 */

typedef duk_double_t (*duk__toint_coercer)(duk_hthread *thr, duk_tval *tv);

DUK_LOCAL duk_double_t duk__to_int_uint_helper(duk_hthread *thr, duk_idx_t idx, duk__toint_coercer coerce_func) {
	duk_tval *tv;
	duk_double_t d;

	DUK_CTX_ASSERT_VALID(thr);

	tv = duk_require_tval(thr, idx);
	DUK_ASSERT(tv != NULL);

#if defined(DUK_USE_FASTINT)
	/* If argument is a fastint, guarantee that it remains one.
	 * There's no downgrade check for other cases.
	 */
	if (DUK_TVAL_IS_FASTINT(tv)) {
		/* XXX: Unnecessary conversion back and forth. */
		return (duk_double_t) DUK_TVAL_GET_FASTINT(tv);
	}
#endif
	d = coerce_func(thr, tv);

	/* XXX: fastint? */

	/* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */
	tv = duk_require_tval(thr, idx);
	DUK_TVAL_SET_NUMBER_UPDREF(thr, tv, d);  /* side effects */
	return d;
}

DUK_EXTERNAL duk_int_t duk_to_int(duk_hthread *thr, duk_idx_t idx) {
	/* Value coercion (in stack): ToInteger(), E5 Section 9.4,
	 * API return value coercion: custom.
	 */
	DUK_ASSERT_API_ENTRY(thr);
	(void) duk__to_int_uint_helper(thr, idx, duk_js_tointeger);
	return (duk_int_t) duk__api_coerce_d2i(thr, idx, 0 /*def_value*/, 0 /*require*/);
}

DUK_EXTERNAL duk_uint_t duk_to_uint(duk_hthread *thr, duk_idx_t idx) {
	/* Value coercion (in stack): ToInteger(), E5 Section 9.4,
	 * API return value coercion: custom.
	 */
	DUK_ASSERT_API_ENTRY(thr);
	(void) duk__to_int_uint_helper(thr, idx, duk_js_tointeger);
	return (duk_uint_t) duk__api_coerce_d2ui(thr, idx, 0 /*def_value*/, 0 /*require*/);
}

DUK_EXTERNAL duk_int32_t duk_to_int32(duk_hthread *thr, duk_idx_t idx) {
	duk_tval *tv;
	duk_int32_t ret;

	DUK_ASSERT_API_ENTRY(thr);

	tv = duk_require_tval(thr, idx);
	DUK_ASSERT(tv != NULL);
	ret = duk_js_toint32(thr, tv);

	/* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */
	tv = duk_require_tval(thr, idx);
	DUK_TVAL_SET_I32_UPDREF(thr, tv, ret);  /* side effects */
	return ret;
}

DUK_EXTERNAL duk_uint32_t duk_to_uint32(duk_hthread *thr, duk_idx_t idx) {
	duk_tval *tv;
	duk_uint32_t ret;

	DUK_ASSERT_API_ENTRY(thr);

	tv = duk_require_tval(thr, idx);
	DUK_ASSERT(tv != NULL);
	ret = duk_js_touint32(thr, tv);

	/* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */
	tv = duk_require_tval(thr, idx);
	DUK_TVAL_SET_U32_UPDREF(thr, tv, ret);  /* side effects */
	return ret;
}

DUK_EXTERNAL duk_uint16_t duk_to_uint16(duk_hthread *thr, duk_idx_t idx) {
	duk_tval *tv;
	duk_uint16_t ret;

	DUK_ASSERT_API_ENTRY(thr);

	tv = duk_require_tval(thr, idx);
	DUK_ASSERT(tv != NULL);
	ret = duk_js_touint16(thr, tv);

	/* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */
	tv = duk_require_tval(thr, idx);
	DUK_TVAL_SET_U32_UPDREF(thr, tv, ret);  /* side effects */
	return ret;
}

#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
/* Special coercion for Uint8ClampedArray. */
DUK_INTERNAL duk_uint8_t duk_to_uint8clamped(duk_hthread *thr, duk_idx_t idx) {
	duk_double_t d;
	duk_double_t t;
	duk_uint8_t ret;

	DUK_ASSERT_API_ENTRY(thr);

	/* XXX: Simplify this algorithm, should be possible to come up with
	 * a shorter and faster algorithm by inspecting IEEE representation
	 * directly.
	 */

	d = duk_to_number(thr, idx);
	if (d <= 0.0) {
		return 0;
	} else if (d >= 255) {
		return 255;
	} else if (DUK_ISNAN(d)) {
		/* Avoid NaN-to-integer coercion as it is compiler specific. */
		return 0;
	}

	t = d - DUK_FLOOR(d);
	if (duk_double_equals(t, 0.5)) {
		/* Exact halfway, round to even. */
		ret = (duk_uint8_t) d;
		ret = (ret + 1) & 0xfe;  /* Example: d=3.5, t=0.5 -> ret = (3 + 1) & 0xfe = 4 & 0xfe = 4
		                          * Example: d=4.5, t=0.5 -> ret = (4 + 1) & 0xfe = 5 & 0xfe = 4
		                          */
	} else {
		/* Not halfway, round to nearest. */
		ret = (duk_uint8_t) (d + 0.5);
	}
	return ret;
}
#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */

DUK_EXTERNAL const char *duk_to_lstring(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len) {
	DUK_ASSERT_API_ENTRY(thr);

	(void) duk_to_string(thr, idx);
	DUK_ASSERT(duk_is_string(thr, idx));
	return duk_require_lstring(thr, idx, out_len);
}

DUK_LOCAL duk_ret_t duk__safe_to_string_raw(duk_hthread *thr, void *udata) {
	DUK_CTX_ASSERT_VALID(thr);
	DUK_UNREF(udata);

	(void) duk_to_string(thr, -1);
	return 1;
}

DUK_EXTERNAL const char *duk_safe_to_lstring(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len) {
	DUK_ASSERT_API_ENTRY(thr);

	idx = duk_require_normalize_index(thr, idx);

	/* We intentionally ignore the duk_safe_call() return value and only
	 * check the output type.  This way we don't also need to check that
	 * the returned value is indeed a string in the success case.
	 */

	duk_dup(thr, idx);
	(void) duk_safe_call(thr, duk__safe_to_string_raw, NULL /*udata*/, 1 /*nargs*/, 1 /*nrets*/);
	if (!duk_is_string(thr, -1)) {
		/* Error: try coercing error to string once. */
		(void) duk_safe_call(thr, duk__safe_to_string_raw, NULL /*udata*/, 1 /*nargs*/, 1 /*nrets*/);
		if (!duk_is_string(thr, -1)) {
			/* Double error */
			duk_pop_unsafe(thr);
			duk_push_hstring_stridx(thr, DUK_STRIDX_UC_ERROR);
		} else {
			;
		}
	} else {
		/* String; may be a symbol, accepted. */
		;
	}
	DUK_ASSERT(duk_is_string(thr, -1));

	duk_replace(thr, idx);
	DUK_ASSERT(duk_get_string(thr, idx) != NULL);
	return duk_get_lstring(thr, idx, out_len);
}

DUK_EXTERNAL const char *duk_to_stacktrace(duk_hthread *thr, duk_idx_t idx) {
	DUK_ASSERT_API_ENTRY(thr);
	idx = duk_require_normalize_index(thr, idx);

	/* The expected argument to the call is an Error object.  The stack
	 * trace is extracted without an inheritance-based instanceof check
	 * so that one can also extract the stack trace of a foreign error
	 * created in another Realm.  Accept only a string .stack property.
	 */
	if (duk_is_object(thr, idx)) {
		(void) duk_get_prop_string(thr, idx, "stack");
		if (duk_is_string(thr, -1)) {
			duk_replace(thr, idx);
		} else {
			duk_pop(thr);
		}
	}

	return duk_to_string(thr, idx);
}

DUK_LOCAL duk_ret_t duk__safe_to_stacktrace_raw(duk_hthread *thr, void *udata) {
	DUK_CTX_ASSERT_VALID(thr);
	DUK_UNREF(udata);

	(void) duk_to_stacktrace(thr, -1);

	return 1;
}

DUK_EXTERNAL const char *duk_safe_to_stacktrace(duk_hthread *thr, duk_idx_t idx) {
	duk_int_t rc;

	DUK_ASSERT_API_ENTRY(thr);
	idx = duk_require_normalize_index(thr, idx);

	duk_dup(thr, idx);
	rc = duk_safe_call(thr, duk__safe_to_stacktrace_raw, NULL /*udata*/, 1 /*nargs*/, 1 /*nrets*/);
	if (rc != 0) {
		/* Coercion failed.  Try to coerce the coercion itself error
		 * to a stack trace once.  If that also fails, return a fixed,
		 * preallocated 'Error' string to avoid potential infinite loop.
		 */
		rc = duk_safe_call(thr, duk__safe_to_stacktrace_raw, NULL /*udata*/, 1 /*nargs*/, 1 /*nrets*/);
		if (rc != 0) {
			duk_pop_unsafe(thr);
			duk_push_hstring_stridx(thr, DUK_STRIDX_UC_ERROR);
		}
	}
	duk_replace(thr, idx);

	return duk_get_string(thr, idx);
}

DUK_INTERNAL duk_hstring *duk_to_property_key_hstring(duk_hthread *thr, duk_idx_t idx) {
	duk_hstring *h;

	DUK_ASSERT_API_ENTRY(thr);

	duk_to_primitive(thr, idx, DUK_HINT_STRING);  /* needed for e.g. Symbol objects */
	h = duk_get_hstring(thr, idx);
	if (h == NULL) {
		/* The "is string?" check may seem unnecessary, but as things
		 * are duk_to_hstring() invokes ToString() which fails for
		 * symbols.  But since symbols are already strings for Duktape
		 * C API, we check for that before doing the coercion.
		 */
		h = duk_to_hstring(thr, idx);
	}
	DUK_ASSERT(h != NULL);
	return h;
}

#if defined(DUK_USE_DEBUGGER_SUPPORT)  /* only needed by debugger for now */
DUK_INTERNAL duk_hstring *duk_safe_to_hstring(duk_hthread *thr, duk_idx_t idx) {
	DUK_ASSERT_API_ENTRY(thr);

	(void) duk_safe_to_string(thr, idx);
	DUK_ASSERT(duk_is_string(thr, idx));
	DUK_ASSERT(duk_get_hstring(thr, idx) != NULL);
	return duk_known_hstring(thr, idx);
}
#endif

/* Push Object.prototype.toString() output for 'tv'. */
DUK_INTERNAL void duk_push_class_string_tval(duk_hthread *thr, duk_tval *tv, duk_bool_t avoid_side_effects) {
	duk_hobject *h_obj;
	duk_small_uint_t classnum;
	duk_small_uint_t stridx;
	duk_tval tv_tmp;

	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(tv != NULL);

	/* Stabilize 'tv', duk_push_literal() may trigger side effects. */
	DUK_TVAL_SET_TVAL(&tv_tmp, tv);
	tv = &tv_tmp;

	/* Conceptually for any non-undefined/null value we should do a
	 * ToObject() coercion and look up @@toStringTag (from the object
	 * prototype) to see if a custom result should be used, with the
	 * exception of Arrays which are handled specially first.
	 *
	 * We'd like to avoid the actual conversion, but even for primitive
	 * types the prototype may have @@toStringTag.  What's worse, the
	 * @@toStringTag property may be a getter that must get the object
	 * coerced value (not the prototype) as its 'this' binding.
	 *
	 * For now, do an actual object coercion.  This could be avoided by
	 * doing a side effect free lookup to see if a getter would be invoked.
	 * If not, the value can be read directly and the object coercion could
	 * be avoided.  This may not be worth it in practice, because
	 * Object.prototype.toString() is usually not performance critical.
	 */

	duk_push_literal(thr, "[object ");  /* -> [ ... "[object" ] */

	switch (DUK_TVAL_GET_TAG(tv)) {
	case DUK_TAG_UNUSED:  /* Treat like 'undefined', shouldn't happen. */
	case DUK_TAG_UNDEFINED: {
		duk_push_hstring_stridx(thr, DUK_STRIDX_UC_UNDEFINED);
		goto finish;
	}
	case DUK_TAG_NULL: {
		duk_push_hstring_stridx(thr, DUK_STRIDX_UC_NULL);
		goto finish;
	}
	}

	duk_push_tval(thr, tv);
	tv = NULL;  /* Invalidated by ToObject(). */
	h_obj = duk_to_hobject(thr, -1);
	DUK_ASSERT(h_obj != NULL);
	if (duk_js_isarray_hobject(h_obj)) {
		stridx = DUK_STRIDX_UC_ARRAY;
	} else {
		/* [ ... "[object" obj ] */

#if defined(DUK_USE_SYMBOL_BUILTIN)
		/* XXX: better handling with avoid_side_effects == 1; lookup tval
		 * without Proxy or getter side effects, and use it in sanitized
		 * form if it's a string.
		 */
		if (!avoid_side_effects) {
			(void) duk_get_prop_stridx(thr, -1, DUK_STRIDX_WELLKNOWN_SYMBOL_TO_STRING_TAG);
			if (duk_is_string_notsymbol(thr, -1)) {
				duk_remove_m2(thr);
				goto finish;
			}
			duk_pop_unsafe(thr);
		}
#else
		DUK_UNREF(avoid_side_effects);
#endif

		classnum = DUK_HOBJECT_GET_CLASS_NUMBER(h_obj);
		stridx = DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(classnum);
	}
	duk_pop_unsafe(thr);
	duk_push_hstring_stridx(thr, stridx);

 finish:
	/* [ ... "[object" tag ] */
	duk_push_literal(thr, "]");
	duk_concat(thr, 3);  /* [ ... "[object" tag "]" ] -> [ ... res ] */
}

/* XXX: other variants like uint, u32 etc */
DUK_INTERNAL duk_int_t duk_to_int_clamped_raw(duk_hthread *thr, duk_idx_t idx, duk_int_t minval, duk_int_t maxval, duk_bool_t *out_clamped) {
	duk_tval *tv;
	duk_tval tv_tmp;
	duk_double_t d, dmin, dmax;
	duk_int_t res;
	duk_bool_t clamped = 0;

	DUK_ASSERT_API_ENTRY(thr);

	tv = duk_require_tval(thr, idx);
	DUK_ASSERT(tv != NULL);
	d = duk_js_tointeger(thr, tv);  /* E5 Section 9.4, ToInteger() */

	dmin = (duk_double_t) minval;
	dmax = (duk_double_t) maxval;

	if (d < dmin) {
		clamped = 1;
		res = minval;
		d = dmin;
	} else if (d > dmax) {
		clamped = 1;
		res = maxval;
		d = dmax;
	} else {
		res = (duk_int_t) d;
	}
	DUK_UNREF(d);  /* SCANBUILD: with suitable dmin/dmax limits 'd' is unused */
	/* 'd' and 'res' agree here */

	/* Relookup in case duk_js_tointeger() ends up e.g. coercing an object. */
	tv = duk_get_tval(thr, idx);
	DUK_ASSERT(tv != NULL);  /* not popped by side effect */
	DUK_TVAL_SET_TVAL(&tv_tmp, tv);
#if defined(DUK_USE_FASTINT)
#if (DUK_INT_MAX <= 0x7fffffffL)
	DUK_TVAL_SET_I32(tv, res);
#else
	/* Clamping needed if duk_int_t is 64 bits. */
	if (res >= DUK_FASTINT_MIN && res <= DUK_FASTINT_MAX) {
		DUK_TVAL_SET_FASTINT(tv, res);
	} else {
		DUK_TVAL_SET_NUMBER(tv, d);
	}
#endif
#else
	DUK_TVAL_SET_NUMBER(tv, d);  /* no need to incref */
#endif
	DUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */

	if (out_clamped) {
		*out_clamped = clamped;
	} else {
		/* coerced value is updated to value stack even when RangeError thrown */
		if (clamped) {
			DUK_ERROR_RANGE(thr, DUK_STR_NUMBER_OUTSIDE_RANGE);
			DUK_WO_NORETURN(return 0;);
		}
	}

	return res;
}

DUK_INTERNAL duk_int_t duk_to_int_clamped(duk_hthread *thr, duk_idx_t idx, duk_idx_t minval, duk_idx_t maxval) {
	duk_bool_t dummy;

	DUK_ASSERT_API_ENTRY(thr);

	return duk_to_int_clamped_raw(thr, idx, minval, maxval, &dummy);
}

DUK_INTERNAL duk_int_t duk_to_int_check_range(duk_hthread *thr, duk_idx_t idx, duk_int_t minval, duk_int_t maxval) {
	DUK_ASSERT_API_ENTRY(thr);
	return duk_to_int_clamped_raw(thr, idx, minval, maxval, NULL);  /* out_clamped==NULL -> RangeError if outside range */
}

DUK_EXTERNAL const char *duk_to_string(duk_hthread *thr, duk_idx_t idx) {
	duk_tval *tv;

	DUK_ASSERT_API_ENTRY(thr);

	idx = duk_require_normalize_index(thr, idx);
	tv = DUK_GET_TVAL_POSIDX(thr, idx);
	DUK_ASSERT(tv != NULL);

	switch (DUK_TVAL_GET_TAG(tv)) {
	case DUK_TAG_UNDEFINED: {
		duk_push_hstring_stridx(thr, DUK_STRIDX_LC_UNDEFINED);
		break;
	}
	case DUK_TAG_NULL: {
		duk_push_hstring_stridx(thr, DUK_STRIDX_LC_NULL);
		break;
	}
	case DUK_TAG_BOOLEAN: {
		if (DUK_TVAL_GET_BOOLEAN(tv)) {
			duk_push_hstring_stridx(thr, DUK_STRIDX_TRUE);
		} else {
			duk_push_hstring_stridx(thr, DUK_STRIDX_FALSE);
		}
		break;
	}
	case DUK_TAG_STRING: {
		/* Nop for actual strings, TypeError for Symbols.
		 * Because various internals rely on ToString() coercion of
		 * internal strings, -allow- (NOP) string coercion for hidden
		 * symbols.
		 */
#if 1
		duk_hstring *h;
		h = DUK_TVAL_GET_STRING(tv);
		DUK_ASSERT(h != NULL);
		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
			DUK_ERROR_TYPE(thr, DUK_STR_CANNOT_STRING_COERCE_SYMBOL);
			DUK_WO_NORETURN(goto skip_replace;);
		} else {
			goto skip_replace;
		}
#else
		goto skip_replace;
#endif
		break;
	}
	case DUK_TAG_BUFFER: /* Go through Uint8Array.prototype.toString() for coercion. */
	case DUK_TAG_OBJECT: {
		/* Plain buffers: go through ArrayBuffer.prototype.toString()
		 * for coercion.
		 *
		 * Symbol objects: duk_to_primitive() results in a plain symbol
		 * value, and duk_to_string() then causes a TypeError.
		 */
		duk_to_primitive(thr, idx, DUK_HINT_STRING);
		DUK_ASSERT(!duk_is_buffer(thr, idx));  /* ToPrimitive() must guarantee */
		DUK_ASSERT(!duk_is_object(thr, idx));
		return duk_to_string(thr, idx);  /* Note: recursive call */
	}
	case DUK_TAG_POINTER: {
		void *ptr = DUK_TVAL_GET_POINTER(tv);
		if (ptr != NULL) {
			duk_push_sprintf(thr, DUK_STR_FMT_PTR, (void *) ptr);
		} else {
			/* Represent a null pointer as 'null' to be consistent with
			 * the JX format variant.  Native '%p' format for a NULL
			 * pointer may be e.g. '(nil)'.
			 */
			duk_push_hstring_stridx(thr, DUK_STRIDX_LC_NULL);
		}
		break;
	}
	case DUK_TAG_LIGHTFUNC: {
		/* Should match Function.prototype.toString() */
		duk_push_lightfunc_tostring(thr, tv);
		break;
	}
#if defined(DUK_USE_FASTINT)
	case DUK_TAG_FASTINT:
#endif
	default: {
		/* number */
		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
		duk_push_tval(thr, tv);
		duk_numconv_stringify(thr,
		                      10 /*radix*/,
		                      0 /*precision:shortest*/,
		                      0 /*force_exponential*/);
		break;
	}
	}

	duk_replace(thr, idx);

 skip_replace:
	DUK_ASSERT(duk_is_string(thr, idx));
	return duk_require_string(thr, idx);
}

DUK_INTERNAL duk_hstring *duk_to_hstring(duk_hthread *thr, duk_idx_t idx) {
	duk_hstring *ret;

	DUK_ASSERT_API_ENTRY(thr);

	duk_to_string(thr, idx);
	ret = duk_get_hstring(thr, idx);
	DUK_ASSERT(ret != NULL);
	return ret;
}

DUK_INTERNAL duk_hstring *duk_to_hstring_m1(duk_hthread *thr) {
	DUK_ASSERT_API_ENTRY(thr);
	return duk_to_hstring(thr, -1);
}

DUK_INTERNAL duk_hstring *duk_to_hstring_acceptsymbol(duk_hthread *thr, duk_idx_t idx) {
	duk_hstring *ret;

	DUK_ASSERT_API_ENTRY(thr);

	ret = duk_get_hstring(thr, idx);
	if (DUK_UNLIKELY(ret && DUK_HSTRING_HAS_SYMBOL(ret))) {
		return ret;
	}
	return duk_to_hstring(thr, idx);
}

/* Convert a plain buffer or any buffer object into a string, using the buffer
 * bytes 1:1 in the internal string representation.  For views the active byte
 * slice (not element slice interpreted as an initializer) is used.  This is
 * necessary in Duktape 2.x because ToString(plainBuffer) no longer creates a
 * string with the same bytes as in the buffer but rather (usually)
 * '[object ArrayBuffer]'.
 */
DUK_EXTERNAL const char *duk_buffer_to_string(duk_hthread *thr, duk_idx_t idx) {
	void *ptr_src;
	duk_size_t len;
	const char *res;

	DUK_ASSERT_API_ENTRY(thr);

	idx = duk_require_normalize_index(thr, idx);

	ptr_src = duk_require_buffer_data(thr, idx, &len);
	DUK_ASSERT(ptr_src != NULL || len == 0);

	res = duk_push_lstring(thr, (const char *) ptr_src, len);
	duk_replace(thr, idx);
	return res;
}

DUK_EXTERNAL void *duk_to_buffer_raw(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size, duk_uint_t mode) {
	duk_hbuffer *h_buf;
	const duk_uint8_t *src_data;
	duk_size_t src_size;
	duk_uint8_t *dst_data;

	DUK_ASSERT_API_ENTRY(thr);

	idx = duk_require_normalize_index(thr, idx);

	h_buf = duk_get_hbuffer(thr, idx);
	if (h_buf != NULL) {
		/* Buffer is kept as is, with the fixed/dynamic nature of the
		 * buffer only changed if requested.  An external buffer
		 * is converted into a non-external dynamic buffer in a
		 * duk_to_dynamic_buffer() call.
		 */
		duk_uint_t tmp;
		duk_uint8_t *tmp_ptr;

		tmp_ptr = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_buf);
		src_data = (const duk_uint8_t *) tmp_ptr;
		src_size = DUK_HBUFFER_GET_SIZE(h_buf);

		tmp = (DUK_HBUFFER_HAS_DYNAMIC(h_buf) ? DUK_BUF_MODE_DYNAMIC : DUK_BUF_MODE_FIXED);
		if ((tmp == mode && !DUK_HBUFFER_HAS_EXTERNAL(h_buf)) ||
		    mode == DUK_BUF_MODE_DONTCARE) {
			/* Note: src_data may be NULL if input is a zero-size
			 * dynamic buffer.
			 */
			dst_data = tmp_ptr;
			goto skip_copy;
		}
	} else {
		/* Non-buffer value is first ToString() coerced, then converted
		 * to a buffer (fixed buffer is used unless a dynamic buffer is
		 * explicitly requested).  Symbols are rejected with a TypeError.
		 * XXX: C API could maybe allow symbol-to-buffer coercion?
		 */
		src_data = (const duk_uint8_t *) duk_to_lstring(thr, idx, &src_size);
	}

	dst_data = (duk_uint8_t *) duk_push_buffer(thr, src_size, (mode == DUK_BUF_MODE_DYNAMIC) /*dynamic*/);
	/* dst_data may be NULL if size is zero. */
	duk_memcpy_unsafe((void *) dst_data, (const void *) src_data, (size_t) src_size);

	duk_replace(thr, idx);
 skip_copy:

	if (out_size) {
		*out_size = src_size;
	}
	return dst_data;
}

DUK_EXTERNAL void *duk_to_pointer(duk_hthread *thr, duk_idx_t idx) {
	duk_tval *tv;
	void *res;

	DUK_ASSERT_API_ENTRY(thr);

	idx = duk_require_normalize_index(thr, idx);
	tv = DUK_GET_TVAL_POSIDX(thr, idx);
	DUK_ASSERT(tv != NULL);

	switch (DUK_TVAL_GET_TAG(tv)) {
	case DUK_TAG_UNDEFINED:
	case DUK_TAG_NULL:
	case DUK_TAG_BOOLEAN:
		res = NULL;
		break;
	case DUK_TAG_POINTER:
		res = DUK_TVAL_GET_POINTER(tv);
		break;
	case DUK_TAG_STRING:
	case DUK_TAG_OBJECT:
	case DUK_TAG_BUFFER:
		/* Heap allocated: return heap pointer which is NOT useful
		 * for the caller, except for debugging.
		 */
		res = (void *) DUK_TVAL_GET_HEAPHDR(tv);
		break;
	case DUK_TAG_LIGHTFUNC:
		/* Function pointers do not always cast correctly to void *
		 * (depends on memory and segmentation model for instance),
		 * so they coerce to NULL.
		 */
		res = NULL;
		break;
#if defined(DUK_USE_FASTINT)
	case DUK_TAG_FASTINT:
#endif
	default:
		/* number */
		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
		res = NULL;
		break;
	}

	duk_push_pointer(thr, res);
	duk_replace(thr, idx);
	return res;
}

DUK_LOCAL void duk__push_func_from_lightfunc(duk_hthread *thr, duk_c_function func, duk_small_uint_t lf_flags) {
	duk_idx_t nargs;
	duk_uint_t flags = 0;   /* shared flags for a subset of types */
	duk_small_uint_t lf_len;
	duk_hnatfunc *nf;

	nargs = (duk_idx_t) DUK_LFUNC_FLAGS_GET_NARGS(lf_flags);
	if (nargs == DUK_LFUNC_NARGS_VARARGS) {
		nargs = (duk_idx_t) DUK_VARARGS;
	}

	flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
	        DUK_HOBJECT_FLAG_CONSTRUCTABLE |
	        DUK_HOBJECT_FLAG_CALLABLE |
	        DUK_HOBJECT_FLAG_FASTREFS |
	        DUK_HOBJECT_FLAG_NATFUNC |
	        DUK_HOBJECT_FLAG_NEWENV |
	        DUK_HOBJECT_FLAG_STRICT |
	        DUK_HOBJECT_FLAG_NOTAIL |
	        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION);
	(void) duk__push_c_function_raw(thr, func, nargs, flags, DUK_BIDX_NATIVE_FUNCTION_PROTOTYPE);

	lf_len = DUK_LFUNC_FLAGS_GET_LENGTH(lf_flags);
	if ((duk_idx_t) lf_len != nargs) {
		/* Explicit length is only needed if it differs from 'nargs'. */
		duk_push_int(thr, (duk_int_t) lf_len);
		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_NONE);
	}

#if defined(DUK_USE_FUNC_NAME_PROPERTY)
	duk_push_lightfunc_name_raw(thr, func, lf_flags);
	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_C);
#endif

	nf = duk_known_hnatfunc(thr, -1);
	nf->magic = (duk_int16_t) DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags);
}

DUK_EXTERNAL void duk_to_object(duk_hthread *thr, duk_idx_t idx) {
	duk_tval *tv;
	duk_uint_t flags = 0;   /* shared flags for a subset of types */
	duk_small_int_t proto = 0;

	DUK_ASSERT_API_ENTRY(thr);

	idx = duk_require_normalize_index(thr, idx);
	tv = DUK_GET_TVAL_POSIDX(thr, idx);
	DUK_ASSERT(tv != NULL);

	switch (DUK_TVAL_GET_TAG(tv)) {
#if !defined(DUK_USE_BUFFEROBJECT_SUPPORT)
	case DUK_TAG_BUFFER:  /* With no bufferobject support, don't object coerce. */
#endif
	case DUK_TAG_UNDEFINED:
	case DUK_TAG_NULL: {
		DUK_ERROR_TYPE(thr, DUK_STR_NOT_OBJECT_COERCIBLE);
		DUK_WO_NORETURN(return;);
		break;
	}
	case DUK_TAG_BOOLEAN: {
		flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
		        DUK_HOBJECT_FLAG_FASTREFS |
		        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_BOOLEAN);
		proto = DUK_BIDX_BOOLEAN_PROTOTYPE;
		goto create_object;
	}
	case DUK_TAG_STRING: {
		duk_hstring *h;
		h = DUK_TVAL_GET_STRING(tv);
		DUK_ASSERT(h != NULL);
		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
			flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
			        DUK_HOBJECT_FLAG_FASTREFS |
			        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_SYMBOL);
			proto = DUK_BIDX_SYMBOL_PROTOTYPE;
		} else {
			flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
			        DUK_HOBJECT_FLAG_FASTREFS |
			        DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ |
			        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_STRING);
			proto = DUK_BIDX_STRING_PROTOTYPE;
		}
		goto create_object;
	}
	case DUK_TAG_OBJECT: {
		/* nop */
		break;
	}
#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
	case DUK_TAG_BUFFER: {
		/* A plain buffer object coerces to a full ArrayBuffer which
		 * is not fully transparent behavior (ToObject() should be a
		 * nop for an object).  This behavior matches lightfuncs which
		 * also coerce to an equivalent Function object.  There are
		 * also downsides to defining ToObject(plainBuffer) as a no-op;
		 * for example duk_to_hobject() could result in a NULL pointer.
		 */
		duk_hbuffer *h_buf;

		h_buf = DUK_TVAL_GET_BUFFER(tv);
		DUK_ASSERT(h_buf != NULL);
		duk_hbufobj_push_uint8array_from_plain(thr, h_buf);
		goto replace_value;
	}
#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
	case DUK_TAG_POINTER: {
		flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
		        DUK_HOBJECT_FLAG_FASTREFS |
		        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_POINTER);
		proto = DUK_BIDX_POINTER_PROTOTYPE;
		goto create_object;
	}
	case DUK_TAG_LIGHTFUNC: {
		/* Lightfunc coerces to a Function instance with concrete
		 * properties.  Since 'length' is virtual for Duktape/C
		 * functions, don't need to define that.  The result is made
		 * extensible to mimic what happens to strings in object
		 * coercion:
		 *
		 *   > Object.isExtensible(Object('foo'))
		 *   true
		 */
		duk_small_uint_t lf_flags;
		duk_c_function func;

		DUK_TVAL_GET_LIGHTFUNC(tv, func, lf_flags);
		duk__push_func_from_lightfunc(thr, func, lf_flags);
		goto replace_value;
	}
#if defined(DUK_USE_FASTINT)
	case DUK_TAG_FASTINT:
#endif
	default: {
		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
		flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
		        DUK_HOBJECT_FLAG_FASTREFS |
		        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_NUMBER);
		proto = DUK_BIDX_NUMBER_PROTOTYPE;
		goto create_object;
	}
	}
	DUK_ASSERT(duk_is_object(thr, idx));
	return;

 create_object:
	(void) duk_push_object_helper(thr, flags, proto);

	/* Note: Boolean prototype's internal value property is not writable,
	 * but duk_xdef_prop_stridx() disregards the write protection.  Boolean
	 * instances are immutable.
	 *
	 * String and buffer special behaviors are already enabled which is not
	 * ideal, but a write to the internal value is not affected by them.
	 */
	duk_dup(thr, idx);
	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);

 replace_value:
	duk_replace(thr, idx);
	DUK_ASSERT(duk_is_object(thr, idx));
}

DUK_INTERNAL duk_hobject *duk_to_hobject(duk_hthread *thr, duk_idx_t idx) {
	duk_hobject *ret;

	DUK_ASSERT_API_ENTRY(thr);

	duk_to_object(thr, idx);
	ret = duk_known_hobject(thr, idx);
	return ret;
}

/*
 *  Type checking
 */

DUK_LOCAL duk_bool_t duk__tag_check(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t tag) {
	duk_tval *tv;

	tv = duk_get_tval_or_unused(thr, idx);
	DUK_ASSERT(tv != NULL);
	return (DUK_TVAL_GET_TAG(tv) == tag);
}

DUK_LOCAL duk_bool_t duk__obj_flag_any_default_false(duk_hthread *thr, duk_idx_t idx, duk_uint_t flag_mask) {
	duk_hobject *obj;

	DUK_ASSERT_API_ENTRY(thr);

	obj = duk_get_hobject(thr, idx);
	if (obj) {
		return (DUK_HEAPHDR_CHECK_FLAG_BITS((duk_heaphdr *) obj, flag_mask) ? 1 : 0);
	}
	return 0;
}

DUK_INTERNAL duk_int_t duk_get_type_tval(duk_tval *tv) {
	DUK_ASSERT(tv != NULL);

#if defined(DUK_USE_PACKED_TVAL)
	switch (DUK_TVAL_GET_TAG(tv)) {
	case DUK_TAG_UNUSED:
		return DUK_TYPE_NONE;
	case DUK_TAG_UNDEFINED:
		return DUK_TYPE_UNDEFINED;
	case DUK_TAG_NULL:
		return DUK_TYPE_NULL;
	case DUK_TAG_BOOLEAN:
		return DUK_TYPE_BOOLEAN;
	case DUK_TAG_STRING:
		return DUK_TYPE_STRING;
	case DUK_TAG_OBJECT:
		return DUK_TYPE_OBJECT;
	case DUK_TAG_BUFFER:
		return DUK_TYPE_BUFFER;
	case DUK_TAG_POINTER:
		return DUK_TYPE_POINTER;
	case DUK_TAG_LIGHTFUNC:
		return DUK_TYPE_LIGHTFUNC;
#if defined(DUK_USE_FASTINT)
	case DUK_TAG_FASTINT:
#endif
	default:
		/* Note: number has no explicit tag (in 8-byte representation) */
		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
		return DUK_TYPE_NUMBER;
	}
#else  /* DUK_USE_PACKED_TVAL */
	DUK_ASSERT(DUK_TVAL_IS_VALID_TAG(tv));
	DUK_ASSERT(sizeof(duk__type_from_tag) / sizeof(duk_uint_t) == DUK_TAG_MAX - DUK_TAG_MIN + 1);
	return (duk_int_t) duk__type_from_tag[DUK_TVAL_GET_TAG(tv) - DUK_TAG_MIN];
#endif  /* DUK_USE_PACKED_TVAL */
}

DUK_EXTERNAL duk_int_t duk_get_type(duk_hthread *thr, duk_idx_t idx) {
	duk_tval *tv;

	DUK_ASSERT_API_ENTRY(thr);

	tv = duk_get_tval_or_unused(thr, idx);
	DUK_ASSERT(tv != NULL);

	return duk_get_type_tval(tv);
}

#if defined(DUK_USE_VERBOSE_ERRORS) && defined(DUK_USE_PARANOID_ERRORS)
DUK_LOCAL const char * const duk__type_names[] = {
	"none",
	"undefined",
	"null",
	"boolean",
	"number",
	"string",
	"object",
	"buffer",
	"pointer",
	"lightfunc"
};

DUK_INTERNAL const char *duk_get_type_name(duk_hthread *thr, duk_idx_t idx) {
	duk_int_t type_tag;

	DUK_ASSERT_API_ENTRY(thr);

	type_tag = duk_get_type(thr, idx);
	DUK_ASSERT(type_tag >= DUK_TYPE_MIN && type_tag <= DUK_TYPE_MAX);
	DUK_ASSERT(DUK_TYPE_MIN == 0 && sizeof(duk__type_names) / sizeof(const char *) == DUK_TYPE_MAX + 1);

	return duk__type_names[type_tag];
}
#endif  /* DUK_USE_VERBOSE_ERRORS && DUK_USE_PARANOID_ERRORS */

DUK_INTERNAL duk_small_uint_t duk_get_class_number(duk_hthread *thr, duk_idx_t idx) {
	duk_tval *tv;
	duk_hobject *obj;

	DUK_ASSERT_API_ENTRY(thr);

	tv = duk_get_tval_or_unused(thr, idx);
	DUK_ASSERT(tv != NULL);

	switch (DUK_TVAL_GET_TAG(tv)) {
	case DUK_TAG_OBJECT:
		obj = DUK_TVAL_GET_OBJECT(tv);
		DUK_ASSERT(obj != NULL);
		return DUK_HOBJECT_GET_CLASS_NUMBER(obj);
	case DUK_TAG_BUFFER:
		/* Buffers behave like Uint8Array objects. */
		return DUK_HOBJECT_CLASS_UINT8ARRAY;
	case DUK_TAG_LIGHTFUNC:
		/* Lightfuncs behave like Function objects. */
		return DUK_HOBJECT_CLASS_FUNCTION;
	default:
		/* Primitive or UNUSED, no class number. */
		return DUK_HOBJECT_CLASS_NONE;
	}
}

DUK_EXTERNAL duk_bool_t duk_check_type(duk_hthread *thr, duk_idx_t idx, duk_int_t type) {
	DUK_ASSERT_API_ENTRY(thr);

	return (duk_get_type(thr, idx) == type) ? 1 : 0;
}

DUK_INTERNAL duk_uint_t duk_get_type_mask_tval(duk_tval *tv) {
	DUK_ASSERT(tv != NULL);

#if defined(DUK_USE_PACKED_TVAL)
	switch (DUK_TVAL_GET_TAG(tv)) {
	case DUK_TAG_UNUSED:
		return DUK_TYPE_MASK_NONE;
	case DUK_TAG_UNDEFINED:
		return DUK_TYPE_MASK_UNDEFINED;
	case DUK_TAG_NULL:
		return DUK_TYPE_MASK_NULL;
	case DUK_TAG_BOOLEAN:
		return DUK_TYPE_MASK_BOOLEAN;
	case DUK_TAG_STRING:
		return DUK_TYPE_MASK_STRING;
	case DUK_TAG_OBJECT:
		return DUK_TYPE_MASK_OBJECT;
	case DUK_TAG_BUFFER:
		return DUK_TYPE_MASK_BUFFER;
	case DUK_TAG_POINTER:
		return DUK_TYPE_MASK_POINTER;
	case DUK_TAG_LIGHTFUNC:
		return DUK_TYPE_MASK_LIGHTFUNC;
#if defined(DUK_USE_FASTINT)
	case DUK_TAG_FASTINT:
#endif
	default:
		/* Note: number has no explicit tag (in 8-byte representation) */
		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
		return DUK_TYPE_MASK_NUMBER;
	}
#else  /* DUK_USE_PACKED_TVAL */
	DUK_ASSERT(DUK_TVAL_IS_VALID_TAG(tv));
	DUK_ASSERT(sizeof(duk__type_mask_from_tag) / sizeof(duk_uint_t) == DUK_TAG_MAX - DUK_TAG_MIN + 1);
	return duk__type_mask_from_tag[DUK_TVAL_GET_TAG(tv) - DUK_TAG_MIN];
#endif  /* DUK_USE_PACKED_TVAL */
}

DUK_EXTERNAL duk_uint_t duk_get_type_mask(duk_hthread *thr, duk_idx_t idx) {
	duk_tval *tv;

	DUK_ASSERT_API_ENTRY(thr);

	tv = duk_get_tval_or_unused(thr, idx);
	DUK_ASSERT(tv != NULL);

	return duk_get_type_mask_tval(tv);
}

DUK_EXTERNAL duk_bool_t duk_check_type_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t mask) {
	DUK_ASSERT_API_ENTRY(thr);

	if (DUK_LIKELY((duk_get_type_mask(thr, idx) & mask) != 0U)) {
		return 1;
	}
	if (mask & DUK_TYPE_MASK_THROW) {
		DUK_ERROR_TYPE(thr, DUK_STR_UNEXPECTED_TYPE);
		DUK_WO_NORETURN(return 0;);
	}
	return 0;
}

DUK_EXTERNAL duk_bool_t duk_is_undefined(duk_hthread *thr, duk_idx_t idx) {
	DUK_ASSERT_API_ENTRY(thr);
	return duk__tag_check(thr, idx, DUK_TAG_UNDEFINED);
}

DUK_EXTERNAL duk_bool_t duk_is_null(duk_hthread *thr, duk_idx_t idx) {
	DUK_ASSERT_API_ENTRY(thr);
	return duk__tag_check(thr, idx, DUK_TAG_NULL);
}

DUK_EXTERNAL duk_bool_t duk_is_boolean(duk_hthread *thr, duk_idx_t idx) {
	DUK_ASSERT_API_ENTRY(thr);
	return duk__tag_check(thr, idx, DUK_TAG_BOOLEAN);
}

DUK_EXTERNAL duk_bool_t duk_is_number(duk_hthread *thr, duk_idx_t idx) {
	duk_tval *tv;

	DUK_ASSERT_API_ENTRY(thr);

	/*
	 *  Number is special because it doesn't have a specific
	 *  tag in the 8-byte representation.
	 */

	/* XXX: shorter version for unpacked representation? */

	tv = duk_get_tval_or_unused(thr, idx);
	DUK_ASSERT(tv != NULL);
	return DUK_TVAL_IS_NUMBER(tv);
}

DUK_EXTERNAL duk_bool_t duk_is_nan(duk_hthread *thr, duk_idx_t idx) {
	/* XXX: This will now return false for non-numbers, even though they would
	 * coerce to NaN (as a general rule).  In particular, duk_get_number()
	 * returns a NaN for non-numbers, so should this function also return
	 * true for non-numbers?
	 */

	duk_tval *tv;

	DUK_ASSERT_API_ENTRY(thr);

	tv = duk_get_tval_or_unused(thr, idx);
	DUK_ASSERT(tv != NULL);

	/* XXX: for packed duk_tval an explicit "is number" check is unnecessary */
	if (!DUK_TVAL_IS_NUMBER(tv)) {
		return 0;
	}
	return (duk_bool_t) DUK_ISNAN(DUK_TVAL_GET_NUMBER(tv));
}

DUK_EXTERNAL duk_bool_t duk_is_string(duk_hthread *thr, duk_idx_t idx) {
	DUK_ASSERT_API_ENTRY(thr);
	return duk__tag_check(thr, idx, DUK_TAG_STRING);
}

DUK_INTERNAL duk_bool_t duk_is_string_notsymbol(duk_hthread *thr, duk_idx_t idx) {
	DUK_ASSERT_API_ENTRY(thr);
	return duk_get_hstring_notsymbol(thr, idx) != NULL;
}

DUK_EXTERNAL duk_bool_t duk_is_object(duk_hthread *thr, duk_idx_t idx) {
	DUK_ASSERT_API_ENTRY(thr);
	return duk__tag_check(thr, idx, DUK_TAG_OBJECT);
}

DUK_EXTERNAL duk_bool_t duk_is_buffer(duk_hthread *thr, duk_idx_t idx) {
	DUK_ASSERT_API_ENTRY(thr);
	return duk__tag_check(thr, idx, DUK_TAG_BUFFER);
}

#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
DUK_EXTERNAL duk_bool_t duk_is_buffer_data(duk_hthread *thr, duk_idx_t idx) {
	duk_tval *tv;

	DUK_ASSERT_API_ENTRY(thr);

	tv = duk_get_tval_or_unused(thr, idx);
	DUK_ASSERT(tv != NULL);
	if (DUK_TVAL_IS_BUFFER(tv)) {
		return 1;
	} else if (DUK_TVAL_IS_OBJECT(tv)) {
		duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
		DUK_ASSERT(h != NULL);
		if (DUK_HOBJECT_IS_BUFOBJ(h)) {
			return 1;
		}
	}
	return 0;
}
#else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
DUK_EXTERNAL duk_bool_t duk_is_buffer_data(duk_hthread *thr, duk_idx_t idx) {
	DUK_ASSERT_API_ENTRY(thr);

	return duk_is_buffer(thr, idx);
}

#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */

DUK_EXTERNAL duk_bool_t duk_is_pointer(duk_hthread *thr, duk_idx_t idx) {
	DUK_ASSERT_API_ENTRY(thr);
	return duk__tag_check(thr, idx, DUK_TAG_POINTER);
}

DUK_EXTERNAL duk_bool_t duk_is_lightfunc(duk_hthread *thr, duk_idx_t idx) {
	DUK_ASSERT_API_ENTRY(thr);
	return duk__tag_check(thr, idx, DUK_TAG_LIGHTFUNC);
}

DUK_EXTERNAL duk_bool_t duk_is_symbol(duk_hthread *thr, duk_idx_t idx) {
	duk_hstring *h;

	DUK_ASSERT_API_ENTRY(thr);
	h = duk_get_hstring(thr, idx);
	/* Use DUK_LIKELY() here because caller may be more likely to type
	 * check an expected symbol than not.
	 */
	if (DUK_LIKELY(h != NULL && DUK_HSTRING_HAS_SYMBOL(h))) {
		return 1;
	}
	return 0;
}

/* IsArray(), returns true for Array instance or Proxy of Array instance. */
DUK_EXTERNAL duk_bool_t duk_is_array(duk_hthread *thr, duk_idx_t idx) {
	duk_tval *tv;

	DUK_ASSERT_API_ENTRY(thr);

	tv = duk_get_tval(thr, idx);
	if (tv) {
		return duk_js_isarray(tv);
	}
	return 0;
}

DUK_EXTERNAL duk_bool_t duk_is_function(duk_hthread *thr, duk_idx_t idx) {
	duk_tval *tv;

	DUK_ASSERT_API_ENTRY(thr);

	tv = duk_get_tval_or_unused(thr, idx);
	if (DUK_TVAL_IS_OBJECT(tv)) {
		duk_hobject *h;
		h = DUK_TVAL_GET_OBJECT(tv);
		DUK_ASSERT(h != NULL);
		return DUK_HOBJECT_HAS_CALLABLE(h) ? 1 : 0;
	}
	if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
		return 1;
	}
	return 0;
}

DUK_INTERNAL duk_bool_t duk_is_callable_tval(duk_hthread *thr, duk_tval *tv) {
	DUK_ASSERT_API_ENTRY(thr);

	DUK_UNREF(thr);

	if (DUK_TVAL_IS_OBJECT(tv)) {
		duk_hobject *h;
		h = DUK_TVAL_GET_OBJECT(tv);
		DUK_ASSERT(h != NULL);
		return DUK_HOBJECT_HAS_CALLABLE(h) ? 1 : 0;
	}
	if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
		return 1;
	}
	return 0;
}

DUK_EXTERNAL duk_bool_t duk_is_constructable(duk_hthread *thr, duk_idx_t idx) {
	duk_tval *tv;

	DUK_ASSERT_API_ENTRY(thr);

	tv = duk_get_tval_or_unused(thr, idx);
	if (DUK_TVAL_IS_OBJECT(tv)) {
		duk_hobject *h;
		h = DUK_TVAL_GET_OBJECT(tv);
		DUK_ASSERT(h != NULL);
		return DUK_HOBJECT_HAS_CONSTRUCTABLE(h) ? 1 : 0;
	}
	if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
		return 1;
	}
	return 0;
}

DUK_EXTERNAL duk_bool_t duk_is_c_function(duk_hthread *thr, duk_idx_t idx) {
	DUK_ASSERT_API_ENTRY(thr);
	return duk__obj_flag_any_default_false(thr,
	                                       idx,
	                                       DUK_HOBJECT_FLAG_NATFUNC);
}

DUK_EXTERNAL duk_bool_t duk_is_ecmascript_function(duk_hthread *thr, duk_idx_t idx) {
	DUK_ASSERT_API_ENTRY(thr);
	return duk__obj_flag_any_default_false(thr,
	                                       idx,
	                                       DUK_HOBJECT_FLAG_COMPFUNC);
}

DUK_EXTERNAL duk_bool_t duk_is_bound_function(duk_hthread *thr, duk_idx_t idx) {
	DUK_ASSERT_API_ENTRY(thr);
	return duk__obj_flag_any_default_false(thr,
	                                       idx,
	                                       DUK_HOBJECT_FLAG_BOUNDFUNC);
}

DUK_EXTERNAL duk_bool_t duk_is_thread(duk_hthread *thr, duk_idx_t idx) {
	duk_hobject *obj;

	DUK_ASSERT_API_ENTRY(thr);

	obj = duk_get_hobject(thr, idx);
	if (obj) {
		return (DUK_HOBJECT_GET_CLASS_NUMBER(obj) == DUK_HOBJECT_CLASS_THREAD ? 1 : 0);
	}
	return 0;
}

DUK_EXTERNAL duk_bool_t duk_is_fixed_buffer(duk_hthread *thr, duk_idx_t idx) {
	duk_tval *tv;

	DUK_ASSERT_API_ENTRY(thr);

	tv = duk_get_tval_or_unused(thr, idx);
	DUK_ASSERT(tv != NULL);
	if (DUK_TVAL_IS_BUFFER(tv)) {
		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
		DUK_ASSERT(h != NULL);
		return (DUK_HBUFFER_HAS_DYNAMIC(h) ? 0 : 1);
	}
	return 0;
}

DUK_EXTERNAL duk_bool_t duk_is_dynamic_buffer(duk_hthread *thr, duk_idx_t idx) {
	duk_tval *tv;

	DUK_ASSERT_API_ENTRY(thr);

	tv = duk_get_tval_or_unused(thr, idx);
	DUK_ASSERT(tv != NULL);
	if (DUK_TVAL_IS_BUFFER(tv)) {
		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
		DUK_ASSERT(h != NULL);
		return (DUK_HBUFFER_HAS_DYNAMIC(h) && !DUK_HBUFFER_HAS_EXTERNAL(h) ? 1 : 0);
	}
	return 0;
}

DUK_EXTERNAL duk_bool_t duk_is_external_buffer(duk_hthread *thr, duk_idx_t idx) {
	duk_tval *tv;

	DUK_ASSERT_API_ENTRY(thr);

	tv = duk_get_tval_or_unused(thr, idx);
	DUK_ASSERT(tv != NULL);
	if (DUK_TVAL_IS_BUFFER(tv)) {
		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
		DUK_ASSERT(h != NULL);
		return (DUK_HBUFFER_HAS_DYNAMIC(h) && DUK_HBUFFER_HAS_EXTERNAL(h) ? 1 : 0);
	}
	return 0;
}

DUK_EXTERNAL duk_errcode_t duk_get_error_code(duk_hthread *thr, duk_idx_t idx) {
	duk_hobject *h;
	duk_uint_t sanity;

	DUK_ASSERT_API_ENTRY(thr);

	h = duk_get_hobject(thr, idx);

	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
	do {
		if (!h) {
			return DUK_ERR_NONE;
		}

		/* XXX: something more convenient? */

		if (h == thr->builtins[DUK_BIDX_EVAL_ERROR_PROTOTYPE]) {
			return DUK_ERR_EVAL_ERROR;
		}
		if (h == thr->builtins[DUK_BIDX_RANGE_ERROR_PROTOTYPE]) {
			return DUK_ERR_RANGE_ERROR;
		}
		if (h == thr->builtins[DUK_BIDX_REFERENCE_ERROR_PROTOTYPE]) {
			return DUK_ERR_REFERENCE_ERROR;
		}
		if (h == thr->builtins[DUK_BIDX_SYNTAX_ERROR_PROTOTYPE]) {
			return DUK_ERR_SYNTAX_ERROR;
		}
		if (h == thr->builtins[DUK_BIDX_TYPE_ERROR_PROTOTYPE]) {
			return DUK_ERR_TYPE_ERROR;
		}
		if (h == thr->builtins[DUK_BIDX_URI_ERROR_PROTOTYPE]) {
			return DUK_ERR_URI_ERROR;
		}
		if (h == thr->builtins[DUK_BIDX_ERROR_PROTOTYPE]) {
			return DUK_ERR_ERROR;
		}

		h = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
	} while (--sanity > 0);

	return DUK_ERR_NONE;
}

/*
 *  Pushers
 */

DUK_INTERNAL void duk_push_tval(duk_hthread *thr, duk_tval *tv) {
	duk_tval *tv_slot;

	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(tv != NULL);

	DUK__CHECK_SPACE();
	tv_slot = thr->valstack_top++;
	DUK_TVAL_SET_TVAL(tv_slot, tv);
	DUK_TVAL_INCREF(thr, tv);  /* no side effects */
}

DUK_EXTERNAL void duk_push_undefined(duk_hthread *thr) {
	DUK_ASSERT_API_ENTRY(thr);

	DUK__CHECK_SPACE();

	/* Because value stack init policy is 'undefined above top',
	 * we don't need to write, just assert.
	 */
	thr->valstack_top++;
	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top - 1));
}

DUK_EXTERNAL void duk_push_null(duk_hthread *thr) {
	duk_tval *tv_slot;

	DUK_ASSERT_API_ENTRY(thr);
	DUK__CHECK_SPACE();
	tv_slot = thr->valstack_top++;
	DUK_TVAL_SET_NULL(tv_slot);
}

DUK_EXTERNAL void duk_push_boolean(duk_hthread *thr, duk_bool_t val) {
	duk_tval *tv_slot;
	duk_small_int_t b;

	DUK_ASSERT_API_ENTRY(thr);
	DUK__CHECK_SPACE();
	b = (val ? 1 : 0);  /* ensure value is 1 or 0 (not other non-zero) */
	tv_slot = thr->valstack_top++;
	DUK_TVAL_SET_BOOLEAN(tv_slot, b);
}

DUK_EXTERNAL void duk_push_true(duk_hthread *thr) {
	duk_tval *tv_slot;

	DUK_ASSERT_API_ENTRY(thr);
	DUK__CHECK_SPACE();
	tv_slot = thr->valstack_top++;
	DUK_TVAL_SET_BOOLEAN_TRUE(tv_slot);
}

DUK_EXTERNAL void duk_push_false(duk_hthread *thr) {
	duk_tval *tv_slot;

	DUK_ASSERT_API_ENTRY(thr);
	DUK__CHECK_SPACE();
	tv_slot = thr->valstack_top++;
	DUK_TVAL_SET_BOOLEAN_FALSE(tv_slot);
}

/* normalize NaN which may not match our canonical internal NaN */
DUK_EXTERNAL void duk_push_number(duk_hthread *thr, duk_double_t val) {
	duk_tval *tv_slot;
	duk_double_union du;

	DUK_ASSERT_API_ENTRY(thr);
	DUK__CHECK_SPACE();
	du.d = val;
	DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);
	tv_slot = thr->valstack_top++;
	DUK_TVAL_SET_NUMBER(tv_slot, du.d);
}

DUK_EXTERNAL void duk_push_int(duk_hthread *thr, duk_int_t val) {
#if defined(DUK_USE_FASTINT)
	duk_tval *tv_slot;

	DUK_ASSERT_API_ENTRY(thr);
	DUK__CHECK_SPACE();
	tv_slot = thr->valstack_top++;
#if DUK_INT_MAX <= 0x7fffffffL
	DUK_TVAL_SET_I32(tv_slot, (duk_int32_t) val);
#else
	if (val >= DUK_FASTINT_MIN && val <= DUK_FASTINT_MAX) {
		DUK_TVAL_SET_FASTINT(tv_slot, (duk_int64_t) val);
	} else {
		duk_double_t = (duk_double_t) val;
		DUK_TVAL_SET_NUMBER(tv_slot, d);
	}
#endif
#else  /* DUK_USE_FASTINT */
	duk_tval *tv_slot;
	duk_double_t d;

	DUK_ASSERT_API_ENTRY(thr);
	DUK__CHECK_SPACE();
	d = (duk_double_t) val;
	tv_slot = thr->valstack_top++;
	DUK_TVAL_SET_NUMBER(tv_slot, d);
#endif  /* DUK_USE_FASTINT */
}

DUK_EXTERNAL void duk_push_uint(duk_hthread *thr, duk_uint_t val) {
#if defined(DUK_USE_FASTINT)
	duk_tval *tv_slot;

	DUK_ASSERT_API_ENTRY(thr);
	DUK__CHECK_SPACE();
	tv_slot = thr->valstack_top++;
#if DUK_UINT_MAX <= 0xffffffffUL
	DUK_TVAL_SET_U32(tv_slot, (duk_uint32_t) val);
#else
	if (val <= DUK_FASTINT_MAX) {  /* val is unsigned so >= 0 */
		/* XXX: take advantage of val being unsigned, no need to mask */
		DUK_TVAL_SET_FASTINT(tv_slot, (duk_int64_t) val);
	} else {
		duk_double_t = (duk_double_t) val;
		DUK_TVAL_SET_NUMBER(tv_slot, d);
	}
#endif
#else  /* DUK_USE_FASTINT */
	duk_tval *tv_slot;
	duk_double_t d;

	DUK_ASSERT_API_ENTRY(thr);
	DUK__CHECK_SPACE();
	d = (duk_double_t) val;
	tv_slot = thr->valstack_top++;
	DUK_TVAL_SET_NUMBER(tv_slot, d);
#endif  /* DUK_USE_FASTINT */
}

DUK_EXTERNAL void duk_push_nan(duk_hthread *thr) {
	duk_tval *tv_slot;
	duk_double_union du;

	DUK_ASSERT_API_ENTRY(thr);
	DUK__CHECK_SPACE();
	DUK_DBLUNION_SET_NAN(&du);
	DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
	tv_slot = thr->valstack_top++;
	DUK_TVAL_SET_NUMBER(tv_slot, du.d);
}

DUK_EXTERNAL const char *duk_push_lstring(duk_hthread *thr, const char *str, duk_size_t len) {
	duk_hstring *h;
	duk_tval *tv_slot;

	DUK_ASSERT_API_ENTRY(thr);

	/* Check stack before interning (avoid hanging temp). */
	DUK__CHECK_SPACE();

	/* NULL with zero length represents an empty string; NULL with higher
	 * length is also now treated like an empty string although it is
	 * a bit dubious.  This is unlike duk_push_string() which pushes a
	 * 'null' if the input string is a NULL.
	 */
	if (DUK_UNLIKELY(str == NULL)) {
		len = 0U;
	}

	/* Check for maximum string length. */
	if (DUK_UNLIKELY(len > DUK_HSTRING_MAX_BYTELEN)) {
		DUK_ERROR_RANGE(thr, DUK_STR_STRING_TOO_LONG);
		DUK_WO_NORETURN(return NULL;);
	}

	h = duk_heap_strtable_intern_checked(thr, (const duk_uint8_t *) str, (duk_uint32_t) len);
	DUK_ASSERT(h != NULL);

	tv_slot = thr->valstack_top++;
	DUK_TVAL_SET_STRING(tv_slot, h);
	DUK_HSTRING_INCREF(thr, h);  /* no side effects */

	return (const char *) DUK_HSTRING_GET_DATA(h);
}

DUK_EXTERNAL const char *duk_push_string(duk_hthread *thr, const char *str) {
	DUK_ASSERT_API_ENTRY(thr);

	if (str) {
		return duk_push_lstring(thr, str, DUK_STRLEN(str));
	} else {
		duk_push_null(thr);
		return NULL;
	}
}

#if !defined(DUK_USE_PREFER_SIZE)
#if defined(DUK_USE_LITCACHE_SIZE)
DUK_EXTERNAL const char *duk_push_literal_raw(duk_hthread *thr, const char *str, duk_size_t len) {
	duk_hstring *h;
	duk_tval *tv_slot;

	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(str != NULL);
	DUK_ASSERT(str[len] == (char) 0);

	/* Check for maximum string length. */
	if (DUK_UNLIKELY(len > DUK_HSTRING_MAX_BYTELEN)) {
		DUK_ERROR_RANGE(thr, DUK_STR_STRING_TOO_LONG);
		DUK_WO_NORETURN(return NULL;);
	}

	h = duk_heap_strtable_intern_literal_checked(thr, (const duk_uint8_t *) str, (duk_uint32_t) len);
	DUK_ASSERT(h != NULL);

	tv_slot = thr->valstack_top++;
	DUK_TVAL_SET_STRING(tv_slot, h);
	DUK_HSTRING_INCREF(thr, h);  /* no side effects */

	return (const char *) DUK_HSTRING_GET_DATA(h);
}
#else  /* DUK_USE_LITCACHE_SIZE */
DUK_EXTERNAL const char *duk_push_literal_raw(duk_hthread *thr, const char *str, duk_size_t len) {
	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(str != NULL);
	DUK_ASSERT(str[len] == (char) 0);

	return duk_push_lstring(thr, str, len);
}
#endif  /* DUK_USE_LITCACHE_SIZE */
#endif  /* !DUK_USE_PREFER_SIZE */

DUK_EXTERNAL void duk_push_pointer(duk_hthread *thr, void *val) {
	duk_tval *tv_slot;

	DUK_ASSERT_API_ENTRY(thr);
	DUK__CHECK_SPACE();
	tv_slot = thr->valstack_top++;
	DUK_TVAL_SET_POINTER(tv_slot, val);
}

DUK_INTERNAL duk_hstring *duk_push_uint_to_hstring(duk_hthread *thr, duk_uint_t i) {
	duk_hstring *h_tmp;

	DUK_ASSERT_API_ENTRY(thr);

	/* XXX: this could be a direct DUK_SPRINTF to a buffer followed by duk_push_string() */
	duk_push_uint(thr, (duk_uint_t) i);
	h_tmp = duk_to_hstring_m1(thr);
	DUK_ASSERT(h_tmp != NULL);
	return h_tmp;
}

DUK_LOCAL void duk__push_this_helper(duk_hthread *thr, duk_small_uint_t check_object_coercible) {
	duk_tval *tv_slot;

	DUK__CHECK_SPACE();

	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top));  /* because of valstack init policy */
	tv_slot = thr->valstack_top++;

	if (DUK_UNLIKELY(thr->callstack_curr == NULL)) {
		if (check_object_coercible) {
			goto type_error;
		}
		/* 'undefined' already on stack top */
	} else {
		duk_tval *tv;

		/* 'this' binding is just before current activation's bottom */
		DUK_ASSERT(thr->valstack_bottom > thr->valstack);
		tv = thr->valstack_bottom - 1;
		if (check_object_coercible &&
		    (DUK_TVAL_IS_UNDEFINED(tv) || DUK_TVAL_IS_NULL(tv))) {
			/* XXX: better macro for DUK_TVAL_IS_UNDEFINED_OR_NULL(tv) */
			goto type_error;
		}

		DUK_TVAL_SET_TVAL(tv_slot, tv);
		DUK_TVAL_INCREF(thr, tv);
	}
	return;

 type_error:
	DUK_ERROR_TYPE(thr, DUK_STR_NOT_OBJECT_COERCIBLE);
	DUK_WO_NORETURN(return;);
}

DUK_EXTERNAL void duk_push_this(duk_hthread *thr) {
	DUK_ASSERT_API_ENTRY(thr);

	duk__push_this_helper(thr, 0 /*check_object_coercible*/);
}

DUK_INTERNAL void duk_push_this_check_object_coercible(duk_hthread *thr) {
	DUK_ASSERT_API_ENTRY(thr);

	duk__push_this_helper(thr, 1 /*check_object_coercible*/);
}

DUK_INTERNAL duk_hobject *duk_push_this_coercible_to_object(duk_hthread *thr) {
	duk_hobject *h;

	DUK_ASSERT_API_ENTRY(thr);

	duk__push_this_helper(thr, 1 /*check_object_coercible*/);
	h = duk_to_hobject(thr, -1);
	DUK_ASSERT(h != NULL);
	return h;
}

DUK_INTERNAL duk_hstring *duk_push_this_coercible_to_string(duk_hthread *thr) {
	DUK_ASSERT_API_ENTRY(thr);

	duk__push_this_helper(thr, 1 /*check_object_coercible*/);
	return duk_to_hstring_m1(thr);  /* This will reject all Symbol values; accepts Symbol objects. */
}

DUK_INTERNAL duk_tval *duk_get_borrowed_this_tval(duk_hthread *thr) {
	DUK_ASSERT_API_ENTRY(thr);

	DUK_ASSERT(thr->callstack_top > 0);  /* caller required to know */
	DUK_ASSERT(thr->callstack_curr != NULL);  /* caller required to know */
	DUK_ASSERT(thr->valstack_bottom > thr->valstack);  /* consequence of above */
	DUK_ASSERT(thr->valstack_bottom - 1 >= thr->valstack);  /* 'this' binding exists */

	return thr->valstack_bottom - 1;
}

DUK_EXTERNAL void duk_push_new_target(duk_hthread *thr) {
	duk_activation *act;

	DUK_ASSERT_API_ENTRY(thr);

	/* https://www.ecma-international.org/ecma-262/6.0/#sec-meta-properties-runtime-semantics-evaluation
	 * https://www.ecma-international.org/ecma-262/6.0/#sec-getnewtarget
	 *
	 * No newTarget support now, so as a first approximation
	 * use the resolved (non-bound) target function.
	 *
	 * Check CONSTRUCT flag from current function, or if running
	 * direct eval, from a non-direct-eval parent (with possibly
	 * more than one nested direct eval).  An alternative to this
	 * would be to store [[NewTarget]] as a hidden symbol of the
	 * lexical scope, and then just look up that variable.
	 *
	 * Calls from the application will either be for an empty
	 * call stack, or a Duktape/C function as the top activation.
	 */

	act = thr->callstack_curr;
	for (;;) {
		if (act == NULL) {
			break;
		}

		if (act->flags & DUK_ACT_FLAG_CONSTRUCT) {
			duk_push_tval(thr, &act->tv_func);
			return;
		} else if (act->flags & DUK_ACT_FLAG_DIRECT_EVAL) {
			act = act->parent;
		} else {
			break;
		}
	}

	duk_push_undefined(thr);
}

DUK_EXTERNAL void duk_push_current_function(duk_hthread *thr) {
	duk_activation *act;

	DUK_ASSERT_API_ENTRY(thr);

	act = thr->callstack_curr;
	if (act != NULL) {
		duk_push_tval(thr, &act->tv_func);
	} else {
		duk_push_undefined(thr);
	}
}

DUK_EXTERNAL void duk_push_current_thread(duk_hthread *thr) {
	DUK_ASSERT_API_ENTRY(thr);

	if (thr->heap->curr_thread) {
		duk_push_hobject(thr, (duk_hobject *) thr->heap->curr_thread);
	} else {
		duk_push_undefined(thr);
	}
}

DUK_EXTERNAL void duk_push_global_object(duk_hthread *thr) {
	DUK_ASSERT_API_ENTRY(thr);

	duk_push_hobject_bidx(thr, DUK_BIDX_GLOBAL);
}

/* XXX: size optimize */
DUK_LOCAL void duk__push_stash(duk_hthread *thr) {
	if (!duk_xget_owndataprop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE)) {
		DUK_DDD(DUK_DDDPRINT("creating heap/global/thread stash on first use"));
		duk_pop_unsafe(thr);
		duk_push_bare_object(thr);
		duk_dup_top(thr);
		duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_C);  /* [ ... parent stash stash ] -> [ ... parent stash ] */
	}
	duk_remove_m2(thr);
}

DUK_EXTERNAL void duk_push_heap_stash(duk_hthread *thr) {
	duk_heap *heap;
	DUK_ASSERT_API_ENTRY(thr);
	heap = thr->heap;
	DUK_ASSERT(heap->heap_object != NULL);
	duk_push_hobject(thr, heap->heap_object);
	duk__push_stash(thr);
}

DUK_EXTERNAL void duk_push_global_stash(duk_hthread *thr) {
	DUK_ASSERT_API_ENTRY(thr);
	duk_push_global_object(thr);
	duk__push_stash(thr);
}

DUK_EXTERNAL void duk_push_thread_stash(duk_hthread *thr, duk_hthread *target_thr) {
	DUK_ASSERT_API_ENTRY(thr);
	if (DUK_UNLIKELY(target_thr == NULL)) {
		DUK_ERROR_TYPE_INVALID_ARGS(thr);
		DUK_WO_NORETURN(return;);
	}
	duk_push_hobject(thr, (duk_hobject *) target_thr);
	duk__push_stash(thr);
}

/* XXX: duk_ssize_t would be useful here */
DUK_LOCAL duk_int_t duk__try_push_vsprintf(duk_hthread *thr, void *buf, duk_size_t sz, const char *fmt, va_list ap) {
	duk_int_t len;

	DUK_CTX_ASSERT_VALID(thr);
	DUK_UNREF(thr);

	/* NUL terminator handling doesn't matter here */
	len = DUK_VSNPRINTF((char *) buf, sz, fmt, ap);
	if (len < (duk_int_t) sz) {
		/* Return value of 'sz' or more indicates output was (potentially)
		 * truncated.
		 */
		return (duk_int_t) len;
	}
	return -1;
}

DUK_EXTERNAL const char *duk_push_vsprintf(duk_hthread *thr, const char *fmt, va_list ap) {
	duk_uint8_t stack_buf[DUK_PUSH_SPRINTF_INITIAL_SIZE];
	duk_size_t sz = DUK_PUSH_SPRINTF_INITIAL_SIZE;
	duk_bool_t pushed_buf = 0;
	void *buf;
	duk_int_t len;  /* XXX: duk_ssize_t */
	const char *res;

	DUK_ASSERT_API_ENTRY(thr);

	/* special handling of fmt==NULL */
	if (!fmt) {
		duk_hstring *h_str;
		duk_push_hstring_empty(thr);
		h_str = duk_known_hstring(thr, -1);
		return (const char *) DUK_HSTRING_GET_DATA(h_str);
	}

	/* initial estimate based on format string */
	sz = DUK_STRLEN(fmt) + 16;  /* format plus something to avoid just missing */
	if (sz < DUK_PUSH_SPRINTF_INITIAL_SIZE) {
		sz = DUK_PUSH_SPRINTF_INITIAL_SIZE;
	}
	DUK_ASSERT(sz > 0);

	/* Try to make do with a stack buffer to avoid allocating a temporary buffer.
	 * This works 99% of the time which is quite nice.
	 */
	for (;;) {
		va_list ap_copy;  /* copied so that 'ap' can be reused */

		if (sz <= sizeof(stack_buf)) {
			buf = stack_buf;
		} else if (!pushed_buf) {
			pushed_buf = 1;
			buf = duk_push_dynamic_buffer(thr, sz);
		} else {
			buf = duk_resize_buffer(thr, -1, sz);
		}
		DUK_ASSERT(buf != NULL);

		DUK_VA_COPY(ap_copy, ap);
		len = duk__try_push_vsprintf(thr, buf, sz, fmt, ap_copy);
		va_end(ap_copy);
		if (len >= 0) {
			break;
		}

		/* failed, resize and try again */
		sz = sz * 2;
		if (DUK_UNLIKELY(sz >= DUK_PUSH_SPRINTF_SANITY_LIMIT)) {
			DUK_ERROR_RANGE(thr, DUK_STR_RESULT_TOO_LONG);
			DUK_WO_NORETURN(return NULL;);
		}
	}

	/* Cannot use duk_buffer_to_string() on the buffer because it is
	 * usually larger than 'len'; 'buf' is also usually a stack buffer.
	 */
	res = duk_push_lstring(thr, (const char *) buf, (duk_size_t) len);  /* [ buf? res ] */
	if (pushed_buf) {
		duk_remove_m2(thr);
	}
	return res;
}

DUK_EXTERNAL const char *duk_push_sprintf(duk_hthread *thr, const char *fmt, ...) {
	va_list ap;
	const char *ret;

	DUK_ASSERT_API_ENTRY(thr);

	/* allow fmt==NULL */
	va_start(ap, fmt);
	ret = duk_push_vsprintf(thr, fmt, ap);
	va_end(ap);

	return ret;
}

DUK_INTERNAL duk_hobject *duk_push_object_helper(duk_hthread *thr, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx) {
	duk_tval *tv_slot;
	duk_hobject *h;

	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(prototype_bidx == -1 ||
	           (prototype_bidx >= 0 && prototype_bidx < DUK_NUM_BUILTINS));

	DUK__CHECK_SPACE();

	h = duk_hobject_alloc(thr, hobject_flags_and_class);
	DUK_ASSERT(h != NULL);

	DUK_DDD(DUK_DDDPRINT("created object with flags: 0x%08lx", (unsigned long) h->hdr.h_flags));

	tv_slot = thr->valstack_top;
	DUK_TVAL_SET_OBJECT(tv_slot, h);
	DUK_HOBJECT_INCREF(thr, h);  /* no side effects */
	thr->valstack_top++;

	/* object is now reachable */

	if (prototype_bidx >= 0) {
		DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, h, thr->builtins[prototype_bidx]);
	} else {
		DUK_ASSERT(prototype_bidx == -1);
		DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h) == NULL);
	}

	return h;
}

DUK_INTERNAL duk_hobject *duk_push_object_helper_proto(duk_hthread *thr, duk_uint_t hobject_flags_and_class, duk_hobject *proto) {
	duk_hobject *h;

	DUK_ASSERT_API_ENTRY(thr);

	h = duk_push_object_helper(thr, hobject_flags_and_class, -1);
	DUK_ASSERT(h != NULL);
	DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, h, proto);
	return h;
}

DUK_EXTERNAL duk_idx_t duk_push_object(duk_hthread *thr) {
	DUK_ASSERT_API_ENTRY(thr);

	(void) duk_push_object_helper(thr,
	                              DUK_HOBJECT_FLAG_EXTENSIBLE |
	                              DUK_HOBJECT_FLAG_FASTREFS |
	                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
	                              DUK_BIDX_OBJECT_PROTOTYPE);
	return duk_get_top_index_unsafe(thr);
}

DUK_EXTERNAL duk_idx_t duk_push_array(duk_hthread *thr) {
	duk_uint_t flags;
	duk_harray *obj;
	duk_idx_t ret;
	duk_tval *tv_slot;

	DUK_ASSERT_API_ENTRY(thr);

	flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
	        DUK_HOBJECT_FLAG_FASTREFS |
	        DUK_HOBJECT_FLAG_ARRAY_PART |
	        DUK_HOBJECT_FLAG_EXOTIC_ARRAY |
	        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAY);

	obj = duk_harray_alloc(thr, flags);
	DUK_ASSERT(obj != NULL);

	DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) obj, thr->builtins[DUK_BIDX_ARRAY_PROTOTYPE]);

	tv_slot = thr->valstack_top;
	DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
	DUK_HOBJECT_INCREF(thr, obj);  /* XXX: could preallocate with refcount = 1 */
	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
	thr->valstack_top++;

	DUK_ASSERT(obj->length == 0);  /* Array .length starts at zero. */
	return ret;
}

DUK_EXTERNAL duk_idx_t duk_push_bare_array(duk_hthread *thr) {
	duk_uint_t flags;
	duk_harray *obj;
	duk_idx_t ret;
	duk_tval *tv_slot;

	DUK_ASSERT_API_ENTRY(thr);

	flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
	        DUK_HOBJECT_FLAG_FASTREFS |
	        DUK_HOBJECT_FLAG_ARRAY_PART |
	        DUK_HOBJECT_FLAG_EXOTIC_ARRAY |
	        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAY);

	obj = duk_harray_alloc(thr, flags);
	DUK_ASSERT(obj != NULL);

	tv_slot = thr->valstack_top;
	DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
	DUK_HOBJECT_INCREF(thr, obj);  /* XXX: could preallocate with refcount = 1 */
	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
	thr->valstack_top++;

	DUK_ASSERT(obj->length == 0);  /* Array .length starts at zero. */
	return ret;
}

DUK_INTERNAL duk_harray *duk_push_harray(duk_hthread *thr) {
	/* XXX: API call could do this directly, cast to void in API macro. */
	duk_harray *a;

	DUK_ASSERT_API_ENTRY(thr);

	(void) duk_push_array(thr);
	DUK_ASSERT(DUK_TVAL_IS_OBJECT(thr->valstack_top - 1));
	a = (duk_harray *) DUK_TVAL_GET_OBJECT(thr->valstack_top - 1);
	DUK_ASSERT(a != NULL);
	return a;
}

/* Push a duk_harray with preallocated size (.length also set to match size).
 * Caller may then populate array part of the duk_harray directly.
 */
DUK_INTERNAL duk_harray *duk_push_harray_with_size(duk_hthread *thr, duk_uint32_t size) {
	duk_harray *a;

	DUK_ASSERT_API_ENTRY(thr);

	a = duk_push_harray(thr);

	duk_hobject_realloc_props(thr,
	                          (duk_hobject *) a,
	                          0,
	                          size,
	                          0,
	                          0);
	a->length = size;
	return a;
}

DUK_INTERNAL duk_tval *duk_push_harray_with_size_outptr(duk_hthread *thr, duk_uint32_t size) {
	duk_harray *a;

	DUK_ASSERT_API_ENTRY(thr);

	a = duk_push_harray_with_size(thr, size);
	DUK_ASSERT(a != NULL);
	return DUK_HOBJECT_A_GET_BASE(thr->heap, (duk_hobject *) a);
}

DUK_EXTERNAL duk_idx_t duk_push_thread_raw(duk_hthread *thr, duk_uint_t flags) {
	duk_hthread *obj;
	duk_idx_t ret;
	duk_tval *tv_slot;

	DUK_ASSERT_API_ENTRY(thr);

	DUK__CHECK_SPACE();

	obj = duk_hthread_alloc(thr,
	                        DUK_HOBJECT_FLAG_EXTENSIBLE |
	                        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_THREAD));
	DUK_ASSERT(obj != NULL);
	obj->state = DUK_HTHREAD_STATE_INACTIVE;
#if defined(DUK_USE_ROM_STRINGS)
	/* Nothing to initialize, strs[] is in ROM. */
#else
#if defined(DUK_USE_HEAPPTR16)
	obj->strs16 = thr->strs16;
#else
	obj->strs = thr->strs;
#endif
#endif
	DUK_DDD(DUK_DDDPRINT("created thread object with flags: 0x%08lx", (unsigned long) obj->obj.hdr.h_flags));

	/* make the new thread reachable */
	tv_slot = thr->valstack_top;
	DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
	DUK_HTHREAD_INCREF(thr, obj);
	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
	thr->valstack_top++;

	/* important to do this *after* pushing, to make the thread reachable for gc */
	if (DUK_UNLIKELY(!duk_hthread_init_stacks(thr->heap, obj))) {
		DUK_ERROR_ALLOC_FAILED(thr);
		DUK_WO_NORETURN(return 0;);
	}

	/* initialize built-ins - either by copying or creating new ones */
	if (flags & DUK_THREAD_NEW_GLOBAL_ENV) {
		duk_hthread_create_builtin_objects(obj);
	} else {
		duk_hthread_copy_builtin_objects(thr, obj);
	}

	/* default prototype */
	DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) obj, obj->builtins[DUK_BIDX_THREAD_PROTOTYPE]);

	/* Initial stack size satisfies the stack slack constraints so there
	 * is no need to require stack here.
	 */
	DUK_ASSERT(DUK_VALSTACK_INITIAL_SIZE >=
	           DUK_VALSTACK_API_ENTRY_MINIMUM + DUK_VALSTACK_INTERNAL_EXTRA);

	return ret;
}

DUK_INTERNAL duk_hcompfunc *duk_push_hcompfunc(duk_hthread *thr) {
	duk_hcompfunc *obj;
	duk_tval *tv_slot;

	DUK_ASSERT_API_ENTRY(thr);

	DUK__CHECK_SPACE();

	/* Template functions are not strictly constructable (they don't
	 * have a "prototype" property for instance), so leave the
	 * DUK_HOBJECT_FLAG_CONSRUCTABLE flag cleared here.
	 */

	obj = duk_hcompfunc_alloc(thr,
	                          DUK_HOBJECT_FLAG_EXTENSIBLE |
	                          DUK_HOBJECT_FLAG_CALLABLE |
	                          DUK_HOBJECT_FLAG_COMPFUNC |
	                          DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION));
	if (DUK_UNLIKELY(obj == NULL)) {
		DUK_ERROR_ALLOC_FAILED(thr);
		DUK_WO_NORETURN(return NULL;);
	}

	DUK_DDD(DUK_DDDPRINT("created compiled function object with flags: 0x%08lx", (unsigned long) obj->obj.hdr.h_flags));

	tv_slot = thr->valstack_top;
	DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
	DUK_HOBJECT_INCREF(thr, obj);
	thr->valstack_top++;

	/* default prototype */
	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) obj) == NULL);
	DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) obj, thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);

	return obj;
}

DUK_INTERNAL duk_hboundfunc *duk_push_hboundfunc(duk_hthread *thr) {
	duk_hboundfunc *obj;
	duk_tval *tv_slot;

	DUK_ASSERT_API_ENTRY(thr);

	DUK__CHECK_SPACE();
	obj = duk_hboundfunc_alloc(thr->heap,
	                           DUK_HOBJECT_FLAG_EXTENSIBLE |
	                           DUK_HOBJECT_FLAG_BOUNDFUNC |
	                           DUK_HOBJECT_FLAG_CONSTRUCTABLE |
	                           DUK_HOBJECT_FLAG_CALLABLE |
	                           DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION));
	if (!obj) {
		DUK_ERROR_ALLOC_FAILED(thr);
		DUK_WO_NORETURN(return NULL;);
	}

	tv_slot = thr->valstack_top++;
	DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
	DUK_HOBJECT_INCREF(thr, obj);

	/* Prototype is left as NULL because the caller always sets it (and
	 * it depends on the target function).
	 */
	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) obj) == NULL);

	return obj;
}

DUK_LOCAL duk_idx_t duk__push_c_function_raw(duk_hthread *thr, duk_c_function func, duk_idx_t nargs, duk_uint_t flags, duk_small_uint_t proto_bidx) {
	duk_hnatfunc *obj;
	duk_idx_t ret;
	duk_tval *tv_slot;
	duk_int16_t func_nargs;

	DUK_CTX_ASSERT_VALID(thr);

	DUK__CHECK_SPACE();

	if (DUK_UNLIKELY(func == NULL)) {
		goto api_error;
	}
	if (nargs >= 0 && nargs < DUK_HNATFUNC_NARGS_MAX) {
		func_nargs = (duk_int16_t) nargs;
	} else if (nargs == DUK_VARARGS) {
		func_nargs = DUK_HNATFUNC_NARGS_VARARGS;
	} else {
		goto api_error;
	}

	obj = duk_hnatfunc_alloc(thr, flags);
	DUK_ASSERT(obj != NULL);

	obj->func = func;
	obj->nargs = func_nargs;

	DUK_DDD(DUK_DDDPRINT("created native function object with flags: 0x%08lx, nargs=%ld",
	                     (unsigned long) obj->obj.hdr.h_flags, (long) obj->nargs));

	tv_slot = thr->valstack_top;
	DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
	DUK_HOBJECT_INCREF(thr, obj);
	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
	thr->valstack_top++;

	DUK_ASSERT_BIDX_VALID(proto_bidx);
	DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) obj, thr->builtins[proto_bidx]);
	return ret;

 api_error:
	DUK_ERROR_TYPE_INVALID_ARGS(thr);
	DUK_WO_NORETURN(return 0;);
}

DUK_EXTERNAL duk_idx_t duk_push_c_function(duk_hthread *thr, duk_c_function func, duk_int_t nargs) {
	duk_uint_t flags;

	DUK_ASSERT_API_ENTRY(thr);

	flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
	        DUK_HOBJECT_FLAG_CONSTRUCTABLE |
	        DUK_HOBJECT_FLAG_CALLABLE |
	        DUK_HOBJECT_FLAG_FASTREFS |
	        DUK_HOBJECT_FLAG_NATFUNC |
	        DUK_HOBJECT_FLAG_NEWENV |
	        DUK_HOBJECT_FLAG_STRICT |
	        DUK_HOBJECT_FLAG_NOTAIL |
	        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION);

	/* Default prototype is a Duktape specific %NativeFunctionPrototype%
	 * which provides .length and .name getters.
	 */
	return duk__push_c_function_raw(thr, func, nargs, flags, DUK_BIDX_NATIVE_FUNCTION_PROTOTYPE);
}

DUK_INTERNAL void duk_push_c_function_builtin(duk_hthread *thr, duk_c_function func, duk_int_t nargs) {
	duk_uint_t flags;

	DUK_ASSERT_API_ENTRY(thr);

	flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
	        DUK_HOBJECT_FLAG_CONSTRUCTABLE |
	        DUK_HOBJECT_FLAG_CALLABLE |
	        DUK_HOBJECT_FLAG_FASTREFS |
	        DUK_HOBJECT_FLAG_NATFUNC |
	        DUK_HOBJECT_FLAG_NEWENV |
	        DUK_HOBJECT_FLAG_STRICT |
	        DUK_HOBJECT_FLAG_NOTAIL |
	        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION);

	/* Must use Function.prototype for standard built-in functions. */
	(void) duk__push_c_function_raw(thr, func, nargs, flags, DUK_BIDX_FUNCTION_PROTOTYPE);
}

DUK_INTERNAL void duk_push_c_function_builtin_noconstruct(duk_hthread *thr, duk_c_function func, duk_int_t nargs) {
	duk_uint_t flags;

	DUK_ASSERT_API_ENTRY(thr);

	flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
	        DUK_HOBJECT_FLAG_CALLABLE |
	        DUK_HOBJECT_FLAG_FASTREFS |
	        DUK_HOBJECT_FLAG_NATFUNC |
	        DUK_HOBJECT_FLAG_NEWENV |
	        DUK_HOBJECT_FLAG_STRICT |
	        DUK_HOBJECT_FLAG_NOTAIL |
	        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION);

	/* Must use Function.prototype for standard built-in functions. */
	(void) duk__push_c_function_raw(thr, func, nargs, flags, DUK_BIDX_FUNCTION_PROTOTYPE);
}

DUK_EXTERNAL duk_idx_t duk_push_c_lightfunc(duk_hthread *thr, duk_c_function func, duk_idx_t nargs, duk_idx_t length, duk_int_t magic) {
	duk_small_uint_t lf_flags;
	duk_tval *tv_slot;

	DUK_ASSERT_API_ENTRY(thr);

	DUK__CHECK_SPACE();

	if (nargs >= DUK_LFUNC_NARGS_MIN && nargs <= DUK_LFUNC_NARGS_MAX) {
		/* as is */
	} else if (nargs == DUK_VARARGS) {
		nargs = DUK_LFUNC_NARGS_VARARGS;
	} else {
		goto api_error;
	}
	if (DUK_UNLIKELY(!(length >= DUK_LFUNC_LENGTH_MIN && length <= DUK_LFUNC_LENGTH_MAX))) {
		goto api_error;
	}
	if (DUK_UNLIKELY(!(magic >= DUK_LFUNC_MAGIC_MIN && magic <= DUK_LFUNC_MAGIC_MAX))) {
		goto api_error;
	}

	lf_flags = DUK_LFUNC_FLAGS_PACK((duk_small_int_t) magic, (duk_small_uint_t) length, (duk_small_uint_t) nargs);
	tv_slot = thr->valstack_top++;
	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv_slot));
	DUK_TVAL_SET_LIGHTFUNC(tv_slot, func, lf_flags);
	DUK_ASSERT(tv_slot >= thr->valstack_bottom);
	return (duk_idx_t) (tv_slot - thr->valstack_bottom);

 api_error:
	DUK_ERROR_TYPE_INVALID_ARGS(thr);
	DUK_WO_NORETURN(return 0;);
}

#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
DUK_INTERNAL duk_hbufobj *duk_push_bufobj_raw(duk_hthread *thr, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx) {
	duk_hbufobj *obj;
	duk_tval *tv_slot;

	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(prototype_bidx >= 0);

	DUK__CHECK_SPACE();

	obj = duk_hbufobj_alloc(thr, hobject_flags_and_class);
	DUK_ASSERT(obj != NULL);

	DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) obj, thr->builtins[prototype_bidx]);
	DUK_HBUFOBJ_ASSERT_VALID(obj);

	tv_slot = thr->valstack_top;
	DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
	DUK_HOBJECT_INCREF(thr, obj);
	thr->valstack_top++;

	return obj;
}
#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */

/* XXX: There's quite a bit of overlap with buffer creation handling in
 * duk_bi_buffer.c.  Look for overlap and refactor.
 */
#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
#define DUK__PACK_ARGS(classnum,protobidx,elemtype,elemshift,istypedarray) \
	(((classnum) << 24) | ((protobidx) << 16) | ((elemtype) << 8) | ((elemshift) << 4) | (istypedarray))

static const duk_uint32_t duk__bufobj_flags_lookup[] = {
	/* Node.js Buffers are Uint8Array instances which inherit from Buffer.prototype. */
	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_ARRAYBUFFER,       DUK_BIDX_ARRAYBUFFER_PROTOTYPE,       DUK_HBUFOBJ_ELEM_UINT8,        0, 0),  /* DUK_BUFOBJ_ARRAYBUFFER */
	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT8ARRAY,        DUK_BIDX_NODEJS_BUFFER_PROTOTYPE,     DUK_HBUFOBJ_ELEM_UINT8,        0, 1),  /* DUK_BUFOBJ_NODEJS_BUFFER */
	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_DATAVIEW,          DUK_BIDX_DATAVIEW_PROTOTYPE,          DUK_HBUFOBJ_ELEM_UINT8,        0, 0),  /* DUK_BUFOBJ_DATAVIEW */
	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_INT8ARRAY,         DUK_BIDX_INT8ARRAY_PROTOTYPE,         DUK_HBUFOBJ_ELEM_INT8,         0, 1),  /* DUK_BUFOBJ_INT8ARRAY */
	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT8ARRAY,        DUK_BIDX_UINT8ARRAY_PROTOTYPE,        DUK_HBUFOBJ_ELEM_UINT8,        0, 1),  /* DUK_BUFOBJ_UINT8ARRAY */
	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY, DUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE, DUK_HBUFOBJ_ELEM_UINT8CLAMPED, 0, 1),  /* DUK_BUFOBJ_UINT8CLAMPEDARRAY */
	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_INT16ARRAY,        DUK_BIDX_INT16ARRAY_PROTOTYPE,        DUK_HBUFOBJ_ELEM_INT16,        1, 1),  /* DUK_BUFOBJ_INT16ARRAY */
	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT16ARRAY,       DUK_BIDX_UINT16ARRAY_PROTOTYPE,       DUK_HBUFOBJ_ELEM_UINT16,       1, 1),  /* DUK_BUFOBJ_UINT16ARRAY */
	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_INT32ARRAY,        DUK_BIDX_INT32ARRAY_PROTOTYPE,        DUK_HBUFOBJ_ELEM_INT32,        2, 1),  /* DUK_BUFOBJ_INT32ARRAY */
	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT32ARRAY,       DUK_BIDX_UINT32ARRAY_PROTOTYPE,       DUK_HBUFOBJ_ELEM_UINT32,       2, 1),  /* DUK_BUFOBJ_UINT32ARRAY */
	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_FLOAT32ARRAY,      DUK_BIDX_FLOAT32ARRAY_PROTOTYPE,      DUK_HBUFOBJ_ELEM_FLOAT32,      2, 1),  /* DUK_BUFOBJ_FLOAT32ARRAY */
	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_FLOAT64ARRAY,      DUK_BIDX_FLOAT64ARRAY_PROTOTYPE,      DUK_HBUFOBJ_ELEM_FLOAT64,      3, 1)   /* DUK_BUFOBJ_FLOAT64ARRAY */
};
#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */

#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
DUK_EXTERNAL void duk_push_buffer_object(duk_hthread *thr, duk_idx_t idx_buffer, duk_size_t byte_offset, duk_size_t byte_length, duk_uint_t flags) {
	duk_hbufobj *h_bufobj;
	duk_hbuffer *h_val;
	duk_hobject *h_arraybuf;
	duk_uint32_t tmp;
	duk_uint_t classnum;
	duk_uint_t protobidx;
	duk_uint_t lookupidx;
	duk_uint_t uint_offset, uint_length, uint_added;

	DUK_ASSERT_API_ENTRY(thr);

	/* The underlying types for offset/length in duk_hbufobj is
	 * duk_uint_t; make sure argument values fit.
	 */
	uint_offset = (duk_uint_t) byte_offset;
	uint_length = (duk_uint_t) byte_length;
	if (sizeof(duk_size_t) != sizeof(duk_uint_t)) {
		if (DUK_UNLIKELY((duk_size_t) uint_offset != byte_offset || (duk_size_t) uint_length != byte_length)) {
			goto range_error;
		}
	}

	DUK_ASSERT_DISABLE(flags >= 0);  /* flags is unsigned */
	lookupidx = flags;
	if (DUK_UNLIKELY(lookupidx >= sizeof(duk__bufobj_flags_lookup) / sizeof(duk_uint32_t))) {
		goto arg_error;
	}
	tmp = duk__bufobj_flags_lookup[lookupidx];
	classnum = tmp >> 24;
	protobidx = (tmp >> 16) & 0xff;

	h_arraybuf = duk_get_hobject(thr, idx_buffer);
	if (h_arraybuf != NULL &&  /* argument is an object */
	    flags != DUK_BUFOBJ_ARRAYBUFFER &&  /* creating a view */
	    DUK_HOBJECT_GET_CLASS_NUMBER(h_arraybuf) == DUK_HOBJECT_CLASS_ARRAYBUFFER  /* argument is ArrayBuffer */) {
		duk_uint_t tmp_offset;

		DUK_HBUFOBJ_ASSERT_VALID((duk_hbufobj *) h_arraybuf);
		h_val = ((duk_hbufobj *) h_arraybuf)->buf;
		if (DUK_UNLIKELY(h_val == NULL)) {
			goto arg_error;
		}

		tmp_offset = uint_offset + ((duk_hbufobj *) h_arraybuf)->offset;
		if (DUK_UNLIKELY(tmp_offset < uint_offset)) {
			goto range_error;
		}
		uint_offset = tmp_offset;

		/* Note intentional difference to new TypedArray(): we allow
		 * caller to create an uncovered typed array (which is memory
		 * safe); new TypedArray() rejects it.
		 */
	} else {
		/* Handle unexpected object arguments here too, for nice error
		 * messages.
		 */
		h_arraybuf = NULL;
		h_val = duk_require_hbuffer(thr, idx_buffer);
	}

	/* Wrap check for offset+length. */
	uint_added = uint_offset + uint_length;
	if (DUK_UNLIKELY(uint_added < uint_offset)) {
		goto range_error;
	}
	DUK_ASSERT(uint_added >= uint_offset && uint_added >= uint_length);

	DUK_ASSERT(h_val != NULL);

	h_bufobj = duk_push_bufobj_raw(thr,
	                               DUK_HOBJECT_FLAG_EXTENSIBLE |
	                               DUK_HOBJECT_FLAG_BUFOBJ |
	                               DUK_HOBJECT_CLASS_AS_FLAGS(classnum),
	                               (duk_small_int_t) protobidx);
	DUK_ASSERT(h_bufobj != NULL);

	h_bufobj->buf = h_val;
	DUK_HBUFFER_INCREF(thr, h_val);
	h_bufobj->buf_prop = h_arraybuf;
	DUK_HOBJECT_INCREF_ALLOWNULL(thr, h_arraybuf);
	h_bufobj->offset = uint_offset;
	h_bufobj->length = uint_length;
	h_bufobj->shift = (tmp >> 4) & 0x0f;
	h_bufobj->elem_type = (tmp >> 8) & 0xff;
	h_bufobj->is_typedarray = tmp & 0x0f;
	DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);

	/* TypedArray views need an automatic ArrayBuffer which must be
	 * provided as .buffer property of the view.  The ArrayBuffer is
	 * referenced via duk_hbufobj->buf_prop and an inherited .buffer
	 * accessor returns it.  The ArrayBuffer is created lazily on first
	 * access if necessary so we don't need to do anything more here.
	 */
	return;

 range_error:
	DUK_ERROR_RANGE(thr, DUK_STR_INVALID_ARGS);
	DUK_WO_NORETURN(return;);

 arg_error:
	DUK_ERROR_TYPE(thr, DUK_STR_INVALID_ARGS);
	DUK_WO_NORETURN(return;);
}
#else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
DUK_EXTERNAL void duk_push_buffer_object(duk_hthread *thr, duk_idx_t idx_buffer, duk_size_t byte_offset, duk_size_t byte_length, duk_uint_t flags) {
	DUK_ASSERT_API_ENTRY(thr);
	DUK_UNREF(idx_buffer);
	DUK_UNREF(byte_offset);
	DUK_UNREF(byte_length);
	DUK_UNREF(flags);
	DUK_ERROR_UNSUPPORTED(thr);
	DUK_WO_NORETURN(return;);
}
#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */

DUK_EXTERNAL duk_idx_t duk_push_error_object_va_raw(duk_hthread *thr, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, va_list ap) {
	duk_hobject *proto;
#if defined(DUK_USE_AUGMENT_ERROR_CREATE)
	duk_small_uint_t augment_flags;
#endif

	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(thr != NULL);
	DUK_UNREF(filename);
	DUK_UNREF(line);

	/* Error code also packs a tracedata related flag. */
#if defined(DUK_USE_AUGMENT_ERROR_CREATE)
	augment_flags = 0;
	if (err_code & DUK_ERRCODE_FLAG_NOBLAME_FILELINE) {
		augment_flags = DUK_AUGMENT_FLAG_NOBLAME_FILELINE;
	}
#endif
	err_code = err_code & (~DUK_ERRCODE_FLAG_NOBLAME_FILELINE);

	/* error gets its 'name' from the prototype */
	proto = duk_error_prototype_from_code(thr, err_code);
	(void) duk_push_object_helper_proto(thr,
	                                    DUK_HOBJECT_FLAG_EXTENSIBLE |
	                                    DUK_HOBJECT_FLAG_FASTREFS |
	                                    DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ERROR),
	                                    proto);

	/* ... and its 'message' from an instance property */
	if (fmt) {
		duk_push_vsprintf(thr, fmt, ap);
		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_MESSAGE, DUK_PROPDESC_FLAGS_WC);
	} else {
		/* If no explicit message given, put error code into message field
		 * (as a number).  This is not fully in keeping with the ECMAScript
		 * error model because messages are supposed to be strings (Error
		 * constructors use ToString() on their argument).  However, it's
		 * probably more useful than having a separate 'code' property.
		 */
		duk_push_int(thr, err_code);
		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_MESSAGE, DUK_PROPDESC_FLAGS_WC);
	}

	/* XXX: .code = err_code disabled, not sure if useful */

	/* Creation time error augmentation */
#if defined(DUK_USE_AUGMENT_ERROR_CREATE)
	/* filename may be NULL in which case file/line is not recorded */
	duk_err_augment_error_create(thr, thr, filename, line, augment_flags);  /* may throw an error */
#endif

	return duk_get_top_index_unsafe(thr);
}

DUK_EXTERNAL duk_idx_t duk_push_error_object_raw(duk_hthread *thr, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, ...) {
	va_list ap;
	duk_idx_t ret;

	DUK_ASSERT_API_ENTRY(thr);

	va_start(ap, fmt);
	ret = duk_push_error_object_va_raw(thr, err_code, filename, line, fmt, ap);
	va_end(ap);
	return ret;
}

#if !defined(DUK_USE_VARIADIC_MACROS)
DUK_EXTERNAL duk_idx_t duk_push_error_object_stash(duk_hthread *thr, duk_errcode_t err_code, const char *fmt, ...) {
	const char *filename = duk_api_global_filename;
	duk_int_t line = duk_api_global_line;
	va_list ap;
	duk_idx_t ret;

	DUK_ASSERT_API_ENTRY(thr);

	duk_api_global_filename = NULL;
	duk_api_global_line = 0;
	va_start(ap, fmt);
	ret = duk_push_error_object_va_raw(thr, err_code, filename, line, fmt, ap);
	va_end(ap);
	return ret;
}
#endif  /* DUK_USE_VARIADIC_MACROS */

DUK_EXTERNAL void *duk_push_buffer_raw(duk_hthread *thr, duk_size_t size, duk_small_uint_t flags) {
	duk_tval *tv_slot;
	duk_hbuffer *h;
	void *buf_data;

	DUK_ASSERT_API_ENTRY(thr);

	DUK__CHECK_SPACE();

	/* Check for maximum buffer length. */
	if (DUK_UNLIKELY(size > DUK_HBUFFER_MAX_BYTELEN)) {
		DUK_ERROR_RANGE(thr, DUK_STR_BUFFER_TOO_LONG);
		DUK_WO_NORETURN(return NULL;);
	}

	h = duk_hbuffer_alloc(thr->heap, size, flags, &buf_data);
	if (DUK_UNLIKELY(h == NULL)) {
		DUK_ERROR_ALLOC_FAILED(thr);
		DUK_WO_NORETURN(return NULL;);
	}

	tv_slot = thr->valstack_top;
	DUK_TVAL_SET_BUFFER(tv_slot, h);
	DUK_HBUFFER_INCREF(thr, h);
	thr->valstack_top++;

	return (void *) buf_data;
}

DUK_INTERNAL void *duk_push_fixed_buffer_nozero(duk_hthread *thr, duk_size_t len) {
	DUK_ASSERT_API_ENTRY(thr);
	return duk_push_buffer_raw(thr, len, DUK_BUF_FLAG_NOZERO);
}

DUK_INTERNAL void *duk_push_fixed_buffer_zero(duk_hthread *thr, duk_size_t len) {
	void *ptr;

	DUK_ASSERT_API_ENTRY(thr);

	ptr = duk_push_buffer_raw(thr, len, 0);
	DUK_ASSERT(ptr != NULL);
#if !defined(DUK_USE_ZERO_BUFFER_DATA)
	/* ES2015 requires zeroing even when DUK_USE_ZERO_BUFFER_DATA
	 * is not set.
	 */
	duk_memzero((void *) ptr, (size_t) len);
#endif
	return ptr;
}

#if defined(DUK_USE_ES6_PROXY)
DUK_EXTERNAL duk_idx_t duk_push_proxy(duk_hthread *thr, duk_uint_t proxy_flags) {
	duk_hobject *h_target;
	duk_hobject *h_handler;
	duk_hproxy *h_proxy;
	duk_tval *tv_slot;
	duk_uint_t flags;

	DUK_ASSERT_API_ENTRY(thr);
	DUK_UNREF(proxy_flags);

	/* DUK__CHECK_SPACE() unnecessary because the Proxy is written to
	 * value stack in-place.
	 */
#if 0
	DUK__CHECK_SPACE();
#endif

	/* Reject a proxy object as the target because it would need
	 * special handling in property lookups.  (ES2015 has no such
	 * restriction.)
	 */
	h_target = duk_require_hobject_promote_mask(thr, -2, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
	DUK_ASSERT(h_target != NULL);
	if (DUK_HOBJECT_IS_PROXY(h_target)) {
		goto fail_args;
	}

	/* Reject a proxy object as the handler because it would cause
	 * potentially unbounded recursion.  (ES2015 has no such
	 * restriction.)
	 *
	 * There's little practical reason to use a lightfunc or a plain
	 * buffer as the handler table: one could only provide traps via
	 * their prototype objects (Function.prototype and ArrayBuffer.prototype).
	 * Even so, as lightfuncs and plain buffers mimic their object
	 * counterparts, they're promoted and accepted here.
	 */
	h_handler = duk_require_hobject_promote_mask(thr, -1, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
	DUK_ASSERT(h_handler != NULL);
	if (DUK_HOBJECT_IS_PROXY(h_handler)) {
		goto fail_args;
	}

	/* XXX: Proxy object currently has no prototype, so ToPrimitive()
	 * coercion fails which is a bit confusing.
	 */

	/* CALLABLE and CONSTRUCTABLE flags are copied from the (initial)
	 * target, see ES2015 Sections 9.5.15 and 9.5.13.
	 */
	flags = DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) h_target) &
	        (DUK_HOBJECT_FLAG_CALLABLE | DUK_HOBJECT_FLAG_CONSTRUCTABLE);
	flags |= DUK_HOBJECT_FLAG_EXTENSIBLE |
	         DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ;
	if (flags & DUK_HOBJECT_FLAG_CALLABLE) {
		flags |= DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION) |
		         DUK_HOBJECT_FLAG_SPECIAL_CALL;
	} else {
		flags |= DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT);
	}

	h_proxy = duk_hproxy_alloc(thr, flags);
	DUK_ASSERT(h_proxy != NULL);
	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_proxy) == NULL);

	/* Initialize Proxy target and handler references; avoid INCREF
	 * by stealing the value stack refcounts via direct value stack
	 * manipulation.  INCREF is needed for the Proxy itself however.
	 */
	DUK_ASSERT(h_target != NULL);
	h_proxy->target = h_target;
	DUK_ASSERT(h_handler != NULL);
	h_proxy->handler = h_handler;
	DUK_HPROXY_ASSERT_VALID(h_proxy);

	DUK_ASSERT(duk_get_hobject(thr, -2) == h_target);
	DUK_ASSERT(duk_get_hobject(thr, -1) == h_handler);
	tv_slot = thr->valstack_top - 2;
	DUK_ASSERT(tv_slot >= thr->valstack_bottom);
	DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) h_proxy);
	DUK_HOBJECT_INCREF(thr, (duk_hobject *) h_proxy);
	tv_slot++;
	DUK_TVAL_SET_UNDEFINED(tv_slot);  /* [ ... target handler ] -> [ ... proxy undefined ] */
	thr->valstack_top = tv_slot;      /* -> [ ... proxy ] */

	DUK_DD(DUK_DDPRINT("created Proxy: %!iT", duk_get_tval(thr, -1)));

	return (duk_idx_t) (thr->valstack_top - thr->valstack_bottom - 1);

 fail_args:
	DUK_ERROR_TYPE_INVALID_ARGS(thr);
	DUK_WO_NORETURN(return 0;);
}
#else  /* DUK_USE_ES6_PROXY */
DUK_EXTERNAL duk_idx_t duk_push_proxy(duk_hthread *thr, duk_uint_t proxy_flags) {
	DUK_ASSERT_API_ENTRY(thr);
	DUK_UNREF(proxy_flags);
	DUK_ERROR_UNSUPPORTED(thr);
	DUK_WO_NORETURN(return 0;);
}
#endif  /* DUK_USE_ES6_PROXY */

#if defined(DUK_USE_ASSERTIONS)
DUK_LOCAL void duk__validate_push_heapptr(duk_hthread *thr, void *ptr) {
	duk_heaphdr *h;
	duk_heaphdr *curr;
	duk_bool_t found = 0;

	h = (duk_heaphdr *) ptr;
	if (h == NULL) {
		/* Allowed. */
		return;
	}
	DUK_ASSERT(h != NULL);
	DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));

	/* One particular problem case is where an object has been
	 * queued for finalization but the finalizer hasn't yet been
	 * executed.
	 *
	 * Corner case: we're running in a finalizer for object X, and
	 * user code calls duk_push_heapptr() for X itself.  In this
	 * case X will be in finalize_list, and we can detect the case
	 * by seeing that X's FINALIZED flag is set (which is done before
	 * the finalizer starts executing).
	 */
#if defined(DUK_USE_FINALIZER_SUPPORT)
	for (curr = thr->heap->finalize_list;
	     curr != NULL;
	     curr = DUK_HEAPHDR_GET_NEXT(thr->heap, curr)) {
		/* FINALIZABLE is set for all objects on finalize_list
		 * except for an object being finalized right now.  So
		 * can't assert here.
		 */
#if 0
		DUK_ASSERT(DUK_HEAPHDR_HAS_FINALIZABLE(curr));
#endif

		if (curr == h) {
			if (DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) h)) {
				/* Object is currently being finalized. */
				DUK_ASSERT(found == 0);  /* Would indicate corrupted lists. */
				found = 1;
			} else {
				/* Not being finalized but on finalize_list,
				 * allowed since Duktape 2.1.
				 */
				DUK_ASSERT(found == 0);  /* Would indicate corrupted lists. */
				found = 1;
			}
		}
	}
#endif  /* DUK_USE_FINALIZER_SUPPORT */

#if defined(DUK_USE_REFERENCE_COUNTING)
	/* Because refzero_list is now processed to completion inline with
	 * no side effects, it's always empty here.
	 */
	DUK_ASSERT(thr->heap->refzero_list == NULL);
#endif

	/* If not present in finalize_list (or refzero_list), it
	 * must be either in heap_allocated or the string table.
	 */
	if (DUK_HEAPHDR_IS_STRING(h)) {
		duk_uint32_t i;
		duk_hstring *str;
		duk_heap *heap = thr->heap;

		DUK_ASSERT(found == 0);
		for (i = 0; i < heap->st_size; i++) {
#if defined(DUK_USE_STRTAB_PTRCOMP)
			str = DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, heap->strtable16[i]);
#else
			str = heap->strtable[i];
#endif
			while (str != NULL) {
				if (str == (duk_hstring *) h) {
					DUK_ASSERT(found == 0);  /* Would indicate corrupted lists. */
					found = 1;
					break;
				}
				str = str->hdr.h_next;
			}
		}
		DUK_ASSERT(found != 0);
	} else {
		for (curr = thr->heap->heap_allocated;
		     curr != NULL;
		     curr = DUK_HEAPHDR_GET_NEXT(thr->heap, curr)) {
			if (curr == h) {
				DUK_ASSERT(found == 0);  /* Would indicate corrupted lists. */
				found = 1;
			}
		}
		DUK_ASSERT(found != 0);
	}
}
#endif  /* DUK_USE_ASSERTIONS */

DUK_EXTERNAL duk_idx_t duk_push_heapptr(duk_hthread *thr, void *ptr) {
	duk_idx_t ret;
	duk_tval *tv;

	DUK_ASSERT_API_ENTRY(thr);

	/* Reviving an object using a heap pointer is a dangerous API
	 * operation: if the application doesn't guarantee that the
	 * pointer target is always reachable, difficult-to-diagnose
	 * problems may ensue.  Try to validate the 'ptr' argument to
	 * the extent possible.
	 */

#if defined(DUK_USE_ASSERTIONS)
	duk__validate_push_heapptr(thr, ptr);
#endif

	DUK__CHECK_SPACE();

	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
	tv = thr->valstack_top++;

	if (ptr == NULL) {
		DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv));
		return ret;
	}

	DUK_HEAPHDR_ASSERT_VALID((duk_heaphdr *) ptr);

	/* If the argument is on finalize_list it has technically been
	 * unreachable before duk_push_heapptr() but it's still safe to
	 * push it.  Starting from Duktape 2.1 allow application code to
	 * do so.  There are two main cases:
	 *
	 *   (1) The object is on the finalize_list and we're called by
	 *       the finalizer for the object being finalized.  In this
	 *       case do nothing: finalize_list handling will deal with
	 *       the object queueing.  This is detected by the object not
	 *       having a FINALIZABLE flag despite being on the finalize_list;
	 *       the flag is cleared for the object being finalized only.
	 *
	 *   (2) The object is on the finalize_list but is not currently
	 *       being processed.  In this case the object can be queued
	 *       back to heap_allocated with a few flags cleared, in effect
	 *       cancelling the finalizer.
	 */
	if (DUK_UNLIKELY(DUK_HEAPHDR_HAS_FINALIZABLE((duk_heaphdr *) ptr))) {
		duk_heaphdr *curr;

		DUK_D(DUK_DPRINT("duk_push_heapptr() with a pointer on finalize_list, autorescue"));

		curr = (duk_heaphdr *) ptr;
		DUK_HEAPHDR_CLEAR_FINALIZABLE(curr);

		/* Because FINALIZED is set prior to finalizer call, it will
		 * be set for the object being currently finalized, but not
		 * for other objects on finalize_list.
		 */
		DUK_HEAPHDR_CLEAR_FINALIZED(curr);

		/* Dequeue object from finalize_list and queue it back to
		 * heap_allocated.
		 */
#if defined(DUK_USE_REFERENCE_COUNTING)
		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(curr) >= 1);  /* Preincremented on finalize_list insert. */
		DUK_HEAPHDR_PREDEC_REFCOUNT(curr);
#endif
		DUK_HEAP_REMOVE_FROM_FINALIZE_LIST(thr->heap, curr);
		DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(thr->heap, curr);

		/* Continue with the rest. */
	}

	switch (DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) ptr)) {
	case DUK_HTYPE_STRING:
		DUK_TVAL_SET_STRING(tv, (duk_hstring *) ptr);
		break;
	case DUK_HTYPE_OBJECT:
		DUK_TVAL_SET_OBJECT(tv, (duk_hobject *) ptr);
		break;
	default:
		DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) ptr) == DUK_HTYPE_BUFFER);
		DUK_TVAL_SET_BUFFER(tv, (duk_hbuffer *) ptr);
		break;
	}

	DUK_HEAPHDR_INCREF(thr, (duk_heaphdr *) ptr);

	return ret;
}

/* Push object with no prototype, i.e. a "bare" object. */
DUK_EXTERNAL duk_idx_t duk_push_bare_object(duk_hthread *thr) {
	DUK_ASSERT_API_ENTRY(thr);

	(void) duk_push_object_helper(thr,
	                              DUK_HOBJECT_FLAG_EXTENSIBLE |
	                              DUK_HOBJECT_FLAG_FASTREFS |
	                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
	                              -1);  /* no prototype */
	return duk_get_top_index_unsafe(thr);
}

DUK_INTERNAL void duk_push_hstring(duk_hthread *thr, duk_hstring *h) {
	duk_tval tv;

	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(h != NULL);

	DUK_TVAL_SET_STRING(&tv, h);
	duk_push_tval(thr, &tv);
}

DUK_INTERNAL void duk_push_hstring_stridx(duk_hthread *thr, duk_small_uint_t stridx) {
	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT_STRIDX_VALID(stridx);
	duk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, stridx));
}

DUK_INTERNAL void duk_push_hstring_empty(duk_hthread *thr) {
	DUK_ASSERT_API_ENTRY(thr);
	duk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, DUK_STRIDX_EMPTY_STRING));
}

DUK_INTERNAL void duk_push_hobject(duk_hthread *thr, duk_hobject *h) {
	duk_tval tv;

	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(h != NULL);

	DUK_TVAL_SET_OBJECT(&tv, h);
	duk_push_tval(thr, &tv);
}

DUK_INTERNAL void duk_push_hbuffer(duk_hthread *thr, duk_hbuffer *h) {
	duk_tval tv;

	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(h != NULL);

	DUK_TVAL_SET_BUFFER(&tv, h);
	duk_push_tval(thr, &tv);
}

DUK_INTERNAL void duk_push_hobject_bidx(duk_hthread *thr, duk_small_int_t builtin_idx) {
	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(builtin_idx >= 0 && builtin_idx < DUK_NUM_BUILTINS);
	DUK_ASSERT(thr->builtins[builtin_idx] != NULL);

	duk_push_hobject(thr, thr->builtins[builtin_idx]);
}

/*
 *  Poppers
 */

DUK_LOCAL DUK_ALWAYS_INLINE void duk__pop_n_unsafe_raw(duk_hthread *thr, duk_idx_t count) {
	duk_tval *tv;
#if defined(DUK_USE_REFERENCE_COUNTING)
	duk_tval *tv_end;
#endif

	DUK_CTX_ASSERT_VALID(thr);
	DUK_ASSERT(count >= 0);
	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) >= (duk_size_t) count);

#if defined(DUK_USE_REFERENCE_COUNTING)
	tv = thr->valstack_top;
	tv_end = tv - count;
	while (tv != tv_end) {
		tv--;
		DUK_ASSERT(tv >= thr->valstack_bottom);
		DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ(thr, tv);
	}
	thr->valstack_top = tv;
	DUK_REFZERO_CHECK_FAST(thr);
#else
	tv = thr->valstack_top;
	while (count > 0) {
		count--;
		tv--;
		DUK_ASSERT(tv >= thr->valstack_bottom);
		DUK_TVAL_SET_UNDEFINED(tv);
	}
	thr->valstack_top = tv;
#endif

	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
}

DUK_EXTERNAL void duk_pop_n(duk_hthread *thr, duk_idx_t count) {
	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);

	if (DUK_UNLIKELY((duk_uidx_t) (thr->valstack_top - thr->valstack_bottom) < (duk_uidx_t) count)) {
		DUK_ERROR_RANGE_INVALID_COUNT(thr);
		DUK_WO_NORETURN(return;);
	}
	DUK_ASSERT(count >= 0);

	duk__pop_n_unsafe_raw(thr, count);
}

#if defined(DUK_USE_PREFER_SIZE)
DUK_INTERNAL void duk_pop_n_unsafe(duk_hthread *thr, duk_idx_t count) {
	DUK_ASSERT_API_ENTRY(thr);
	duk_pop_n(thr, count);
}
#else  /* DUK_USE_PREFER_SIZE */
DUK_INTERNAL void duk_pop_n_unsafe(duk_hthread *thr, duk_idx_t count) {
	DUK_ASSERT_API_ENTRY(thr);
	duk__pop_n_unsafe_raw(thr, count);
}
#endif  /* DUK_USE_PREFER_SIZE */

/* Pop N elements without DECREF (in effect "stealing" any actual refcounts). */
#if defined(DUK_USE_REFERENCE_COUNTING)
DUK_INTERNAL void duk_pop_n_nodecref_unsafe(duk_hthread *thr, duk_idx_t count) {
	duk_tval *tv;

	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(count >= 0);
	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) >= (duk_size_t) count);

	tv = thr->valstack_top;
	while (count > 0) {
		count--;
		tv--;
		DUK_ASSERT(tv >= thr->valstack_bottom);
		DUK_TVAL_SET_UNDEFINED(tv);
	}
	thr->valstack_top = tv;

	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
}
#else  /* DUK_USE_REFERENCE_COUNTING */
DUK_INTERNAL void duk_pop_n_nodecref_unsafe(duk_hthread *thr, duk_idx_t count) {
	DUK_ASSERT_API_ENTRY(thr);
	duk_pop_n_unsafe(thr, count);
}
#endif  /* DUK_USE_REFERENCE_COUNTING */

/* Popping one element is called so often that when footprint is not an issue,
 * compile a specialized function for it.
 */
#if defined(DUK_USE_PREFER_SIZE)
DUK_EXTERNAL void duk_pop(duk_hthread *thr) {
	DUK_ASSERT_API_ENTRY(thr);
	duk_pop_n(thr, 1);
}
DUK_INTERNAL void duk_pop_unsafe(duk_hthread *thr) {
	DUK_ASSERT_API_ENTRY(thr);
	duk_pop_n_unsafe(thr, 1);
}
DUK_INTERNAL void duk_pop_nodecref_unsafe(duk_hthread *thr) {
	DUK_ASSERT_API_ENTRY(thr);
	duk_pop_n_nodecref_unsafe(thr, 1);
}
#else  /* DUK_USE_PREFER_SIZE */
DUK_LOCAL DUK_ALWAYS_INLINE void duk__pop_unsafe_raw(duk_hthread *thr) {
	duk_tval *tv;

	DUK_CTX_ASSERT_VALID(thr);
	DUK_ASSERT(thr->valstack_top != thr->valstack_bottom);
	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) >= (duk_size_t) 1);

	tv = --thr->valstack_top;
	DUK_ASSERT(tv >= thr->valstack_bottom);
#if defined(DUK_USE_REFERENCE_COUNTING)
	DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv);  /* side effects */
#else
	DUK_TVAL_SET_UNDEFINED(tv);
#endif

	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
}
DUK_EXTERNAL void duk_pop(duk_hthread *thr) {
	DUK_ASSERT_API_ENTRY(thr);

	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
	if (DUK_UNLIKELY(thr->valstack_top == thr->valstack_bottom)) {
		DUK_ERROR_RANGE_INVALID_COUNT(thr);
		DUK_WO_NORETURN(return;);
	}

	duk__pop_unsafe_raw(thr);
}
DUK_INTERNAL void duk_pop_unsafe(duk_hthread *thr) {
	DUK_ASSERT_API_ENTRY(thr);
	duk__pop_unsafe_raw(thr);
}
DUK_INTERNAL void duk_pop_nodecref_unsafe(duk_hthread *thr) {
	duk_tval *tv;

	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(thr->valstack_top != thr->valstack_bottom);
	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) >= (duk_size_t) 1);

	tv = --thr->valstack_top;
	DUK_ASSERT(tv >= thr->valstack_bottom);
	DUK_TVAL_SET_UNDEFINED(tv);

	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
}
#endif  /* !DUK_USE_PREFER_SIZE */

#if defined(DUK_USE_PREFER_SIZE)
DUK_INTERNAL void duk_pop_undefined(duk_hthread *thr) {
	DUK_ASSERT_API_ENTRY(thr);
	duk_pop_nodecref_unsafe(thr);
}
#else  /* DUK_USE_PREFER_SIZE */
DUK_INTERNAL void duk_pop_undefined(duk_hthread *thr) {
	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(thr->valstack_top != thr->valstack_bottom);
	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) >= (duk_size_t) 1);

	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top - 1));
	thr->valstack_top--;

	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
}
#endif  /* !DUK_USE_PREFER_SIZE */

#if defined(DUK_USE_PREFER_SIZE)
DUK_EXTERNAL void duk_pop_2(duk_hthread *thr) {
	DUK_ASSERT_API_ENTRY(thr);
	duk_pop_n(thr, 2);
}
DUK_INTERNAL void duk_pop_2_unsafe(duk_hthread *thr) {
	DUK_ASSERT_API_ENTRY(thr);
	duk_pop_n_unsafe(thr, 2);
}
DUK_INTERNAL void duk_pop_2_nodecref_unsafe(duk_hthread *thr) {
	DUK_ASSERT_API_ENTRY(thr);
	duk_pop_n_nodecref_unsafe(thr, 2);
}
#else
DUK_LOCAL DUK_ALWAYS_INLINE void duk__pop_2_unsafe_raw(duk_hthread *thr) {
	duk_tval *tv;

	DUK_CTX_ASSERT_VALID(thr);
	DUK_ASSERT(thr->valstack_top != thr->valstack_bottom);
	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) >= (duk_size_t) 2);

	tv = --thr->valstack_top;
	DUK_ASSERT(tv >= thr->valstack_bottom);
#if defined(DUK_USE_REFERENCE_COUNTING)
	DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv);  /* side effects */
#else
	DUK_TVAL_SET_UNDEFINED(tv);
#endif
	tv = --thr->valstack_top;
	DUK_ASSERT(tv >= thr->valstack_bottom);
#if defined(DUK_USE_REFERENCE_COUNTING)
	DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv);  /* side effects */
#else
	DUK_TVAL_SET_UNDEFINED(tv);
#endif

	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
}
DUK_EXTERNAL void duk_pop_2(duk_hthread *thr) {
	DUK_ASSERT_API_ENTRY(thr);

	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
	if (DUK_UNLIKELY(thr->valstack_top - 2 < thr->valstack_bottom)) {
		DUK_ERROR_RANGE_INVALID_COUNT(thr);
		DUK_WO_NORETURN(return;);
	}

	duk__pop_2_unsafe_raw(thr);
}
DUK_INTERNAL void duk_pop_2_unsafe(duk_hthread *thr) {
	DUK_ASSERT_API_ENTRY(thr);
	duk__pop_2_unsafe_raw(thr);
}
DUK_INTERNAL void duk_pop_2_nodecref_unsafe(duk_hthread *thr) {
	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(thr->valstack_top != thr->valstack_bottom);
	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) >= (duk_size_t) 2);

	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top - 1));
	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top - 2));
	thr->valstack_top -= 2;

	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
}
#endif  /* !DUK_USE_PREFER_SIZE */

DUK_EXTERNAL void duk_pop_3(duk_hthread *thr) {
	DUK_ASSERT_API_ENTRY(thr);
	duk_pop_n(thr, 3);
}

DUK_INTERNAL void duk_pop_3_unsafe(duk_hthread *thr) {
	DUK_ASSERT_API_ENTRY(thr);
	duk_pop_n_unsafe(thr, 3);
}

DUK_INTERNAL void duk_pop_3_nodecref_unsafe(duk_hthread *thr) {
	DUK_ASSERT_API_ENTRY(thr);
	duk_pop_n_nodecref_unsafe(thr, 3);
}

/*
 *  Pack and unpack (pack value stack entries into an array and vice versa)
 */

/* XXX: pack index range? array index offset? */
/* XXX: need ability to pack into a bare array? */
DUK_INTERNAL void duk_pack(duk_hthread *thr, duk_idx_t count) {
	duk_tval *tv_src;
	duk_tval *tv_dst;
	duk_tval *tv_curr;
	duk_tval *tv_limit;
	duk_idx_t top;

	DUK_ASSERT_API_ENTRY(thr);

	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
	top = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
	DUK_ASSERT(top >= 0);
	if (DUK_UNLIKELY((duk_uidx_t) count > (duk_uidx_t) top)) {
		/* Also handles negative count. */
		DUK_ERROR_RANGE_INVALID_COUNT(thr);
		DUK_WO_NORETURN(return;);
	}
	DUK_ASSERT(count >= 0);

	/* Wrapping is controlled by the check above: value stack top can be
	 * at most DUK_USE_VALSTACK_LIMIT which is low enough so that
	 * multiplying with sizeof(duk_tval) won't wrap.
	 */
	DUK_ASSERT(count >= 0 && count <= (duk_idx_t) DUK_USE_VALSTACK_LIMIT);
	DUK_ASSERT((duk_size_t) count <= DUK_SIZE_MAX / sizeof(duk_tval));  /* no wrapping */

	tv_dst = duk_push_harray_with_size_outptr(thr, (duk_uint32_t) count);  /* XXX: uninitialized would be OK */
	DUK_ASSERT(count == 0 || tv_dst != NULL);
	DUK_ASSERT(!duk_is_bare_object(thr, -1));

	/* Copy value stack values directly to the array part without
	 * any refcount updates: net refcount changes are zero.
	 */
	tv_src = thr->valstack_top - count - 1;
	duk_memcpy_unsafe((void *) tv_dst, (const void *) tv_src, (size_t) count * sizeof(duk_tval));

	/* Overwrite result array to final value stack location and wipe
	 * the rest; no refcount operations needed.
	 */

	tv_dst = tv_src;  /* when count == 0, same as tv_src (OK) */
	tv_src = thr->valstack_top - 1;
	DUK_TVAL_SET_TVAL(tv_dst, tv_src);

	/* XXX: internal helper to wipe a value stack segment? */
	tv_curr = tv_dst + 1;
	tv_limit = thr->valstack_top;
	while (tv_curr != tv_limit) {
		/* Wipe policy: keep as 'undefined'. */
		DUK_TVAL_SET_UNDEFINED(tv_curr);
		tv_curr++;
	}
	thr->valstack_top = tv_dst + 1;
}

DUK_INTERNAL duk_idx_t duk_unpack_array_like(duk_hthread *thr, duk_idx_t idx) {
	duk_tval *tv;

	DUK_ASSERT_API_ENTRY(thr);

	tv = duk_require_tval(thr, idx);
	if (DUK_LIKELY(DUK_TVAL_IS_OBJECT(tv))) {
		duk_hobject *h;
		duk_uint32_t len;
		duk_uint32_t i;

		h = DUK_TVAL_GET_OBJECT(tv);
		DUK_ASSERT(h != NULL);
		DUK_UNREF(h);

#if defined(DUK_USE_ARRAY_FASTPATH)  /* close enough */
		if (DUK_LIKELY(DUK_HOBJECT_IS_ARRAY(h) &&
		               ((duk_harray *) h)->length <= DUK_HOBJECT_GET_ASIZE(h))) {
			duk_harray *h_arr;
			duk_tval *tv_src;
			duk_tval *tv_dst;

			h_arr = (duk_harray *) h;
			len = h_arr->length;
			if (DUK_UNLIKELY(len >= 0x80000000UL)) {
				goto fail_over_2g;
			}
			duk_require_stack(thr, (duk_idx_t) len);

			/* The potential allocation in duk_require_stack() may
			 * run a finalizer which modifies the argArray so that
			 * e.g. becomes sparse.  So, we need to recheck that the
			 * array didn't change size and that there's still a
			 * valid backing array part.
			 *
			 * XXX: alternatively, could prevent finalizers for the
			 * duration.
			 */
			if (DUK_UNLIKELY(len != h_arr->length ||
			                 h_arr->length > DUK_HOBJECT_GET_ASIZE((duk_hobject *) h_arr))) {
				goto skip_fast;
			}

			/* Main fast path: arguments array is almost always
			 * an actual array (though it might also be an arguments
			 * object).
			 */

			DUK_DDD(DUK_DDDPRINT("fast path for %ld elements", (long) h_arr->length));
			tv_src = DUK_HOBJECT_A_GET_BASE(thr->heap, h);
			tv_dst = thr->valstack_top;
			while (len-- > 0) {
				DUK_ASSERT(tv_dst < thr->valstack_end);
				if (DUK_UNLIKELY(DUK_TVAL_IS_UNUSED(tv_src))) {
					/* Gaps are very unlikely.  Skip over them,
					 * without an ancestor lookup (technically
					 * not compliant).
					 */
					DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv_dst));  /* valstack policy */
				} else {
					DUK_TVAL_SET_TVAL(tv_dst, tv_src);
					DUK_TVAL_INCREF(thr, tv_dst);
				}
				tv_src++;
				tv_dst++;
			}
			DUK_ASSERT(tv_dst <= thr->valstack_end);
			thr->valstack_top = tv_dst;
			return (duk_idx_t) h_arr->length;
		}
	 skip_fast:
#endif  /* DUK_USE_ARRAY_FASTPATH */

		/* Slow path: actual lookups.  The initial 'length' lookup
		 * decides the output length, regardless of side effects that
		 * may resize or change the argArray while we read the
		 * indices.
		 */
		idx = duk_normalize_index(thr, idx);
		duk_get_prop_stridx(thr, idx, DUK_STRIDX_LENGTH);
		len = duk_to_uint32(thr, -1);  /* ToUint32() coercion required */
		if (DUK_UNLIKELY(len >= 0x80000000UL)) {
			goto fail_over_2g;
		}
		duk_pop_unsafe(thr);
		DUK_DDD(DUK_DDDPRINT("slow path for %ld elements", (long) len));

		duk_require_stack(thr, (duk_idx_t) len);
		for (i = 0; i < len; i++) {
			duk_get_prop_index(thr, idx, (duk_uarridx_t) i);
		}
		return (duk_idx_t) len;
	} else if (DUK_TVAL_IS_UNDEFINED(tv) || DUK_TVAL_IS_NULL(tv)) {
		return 0;
	}

	DUK_ERROR_TYPE_INVALID_ARGS(thr);
	DUK_WO_NORETURN(return 0;);

 fail_over_2g:
	DUK_ERROR_RANGE_INVALID_LENGTH(thr);
	DUK_WO_NORETURN(return 0;);
}

/*
 *  Error throwing
 */

#if defined(DUK_USE_GCC_PRAGMAS)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsuggest-attribute=noreturn"
#elif defined(DUK_USE_CLANG_PRAGMAS)
#pragma clang diagnostic push
#endif

DUK_EXTERNAL void duk_throw_raw(duk_hthread *thr) {
	duk_tval *tv_val;

	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
	DUK_ASSERT(thr->valstack_end >= thr->valstack_top);

	if (DUK_UNLIKELY(thr->valstack_top == thr->valstack_bottom)) {
		DUK_ERROR_TYPE_INVALID_ARGS(thr);
		DUK_WO_NORETURN(return;);
	}

	/* Errors are augmented when they are created, not when they are
	 * thrown or re-thrown.  The current error handler, however, runs
	 * just before an error is thrown.
	 */

	/* Sync so that augmentation sees up-to-date activations, NULL
	 * thr->ptr_curr_pc so that it's not used if side effects occur
	 * in augmentation or longjmp handling.
	 */
	duk_hthread_sync_and_null_currpc(thr);

#if defined(DUK_USE_AUGMENT_ERROR_THROW)
	DUK_DDD(DUK_DDDPRINT("THROW ERROR (API): %!dT (before throw augment)", (duk_tval *) duk_get_tval(thr, -1)));
	duk_err_augment_error_throw(thr);
#endif
	DUK_DDD(DUK_DDDPRINT("THROW ERROR (API): %!dT (after throw augment)", (duk_tval *) duk_get_tval(thr, -1)));

	tv_val = DUK_GET_TVAL_NEGIDX(thr, -1);
	duk_err_setup_ljstate1(thr, DUK_LJ_TYPE_THROW, tv_val);
#if defined(DUK_USE_DEBUGGER_SUPPORT)
	duk_err_check_debugger_integration(thr);
#endif

	/* thr->heap->lj.jmpbuf_ptr is checked by duk_err_longjmp() so we don't
	 * need to check that here.  If the value is NULL, a fatal error occurs
	 * because we can't return.
	 */

	duk_err_longjmp(thr);
	DUK_UNREACHABLE();
}

DUK_EXTERNAL void duk_fatal_raw(duk_hthread *thr, const char *err_msg) {
	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(thr->heap != NULL);
	DUK_ASSERT(thr->heap->fatal_func != NULL);

	DUK_D(DUK_DPRINT("fatal error occurred: %s", err_msg ? err_msg : "NULL"));

	/* fatal_func should be noreturn, but noreturn declarations on function
	 * pointers has a very spotty support apparently so it's not currently
	 * done.
	 */
	thr->heap->fatal_func(thr->heap->heap_udata, err_msg);

	/* If the fatal handler returns, all bets are off.  It'd be nice to
	 * print something here but since we don't want to depend on stdio,
	 * there's no way to do so portably.
	 */
	DUK_D(DUK_DPRINT("fatal error handler returned, all bets are off!"));
	for (;;) {
		/* loop forever, don't return (function marked noreturn) */
	}
}

DUK_EXTERNAL void duk_error_va_raw(duk_hthread *thr, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, va_list ap) {
	DUK_ASSERT_API_ENTRY(thr);

	duk_push_error_object_va_raw(thr, err_code, filename, line, fmt, ap);
	(void) duk_throw(thr);
	DUK_WO_NORETURN(return;);
}

DUK_EXTERNAL void duk_error_raw(duk_hthread *thr, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, ...) {
	va_list ap;

	DUK_ASSERT_API_ENTRY(thr);

	va_start(ap, fmt);
	duk_push_error_object_va_raw(thr, err_code, filename, line, fmt, ap);
	va_end(ap);
	(void) duk_throw(thr);
	DUK_WO_NORETURN(return;);
}

#if defined(DUK_USE_GCC_PRAGMAS)
#pragma GCC diagnostic pop
#elif defined(DUK_USE_CLANG_PRAGMAS)
#pragma clang diagnostic pop
#endif

#if !defined(DUK_USE_VARIADIC_MACROS)
DUK_NORETURN(DUK_LOCAL_DECL void duk__throw_error_from_stash(duk_hthread *thr, duk_errcode_t err_code, const char *fmt, va_list ap));

DUK_LOCAL void duk__throw_error_from_stash(duk_hthread *thr, duk_errcode_t err_code, const char *fmt, va_list ap) {
	const char *filename;
	duk_int_t line;

	DUK_CTX_ASSERT_VALID(thr);

	filename = duk_api_global_filename;
	line = duk_api_global_line;
	duk_api_global_filename = NULL;
	duk_api_global_line = 0;

	duk_push_error_object_va_raw(thr, err_code, filename, line, fmt, ap);
	(void) duk_throw(thr);
	DUK_WO_NORETURN(return;);
}

#define DUK__ERROR_STASH_SHARED(code) do { \
		va_list ap; \
		va_start(ap, fmt); \
		duk__throw_error_from_stash(thr, (code), fmt, ap); \
		va_end(ap); \
		DUK_WO_NORETURN(return 0;); \
	} while (0)

DUK_EXTERNAL duk_ret_t duk_error_stash(duk_hthread *thr, duk_errcode_t err_code, const char *fmt, ...) {
	DUK_ASSERT_API_ENTRY(thr);
	DUK__ERROR_STASH_SHARED(err_code);
}
DUK_EXTERNAL duk_ret_t duk_generic_error_stash(duk_hthread *thr, const char *fmt, ...) {
	DUK_ASSERT_API_ENTRY(thr);
	DUK__ERROR_STASH_SHARED(DUK_ERR_ERROR);
}
DUK_EXTERNAL duk_ret_t duk_eval_error_stash(duk_hthread *thr, const char *fmt, ...) {
	DUK_ASSERT_API_ENTRY(thr);
	DUK__ERROR_STASH_SHARED(DUK_ERR_EVAL_ERROR);
}
DUK_EXTERNAL duk_ret_t duk_range_error_stash(duk_hthread *thr, const char *fmt, ...) {
	DUK_ASSERT_API_ENTRY(thr);
	DUK__ERROR_STASH_SHARED(DUK_ERR_RANGE_ERROR);
}
DUK_EXTERNAL duk_ret_t duk_reference_error_stash(duk_hthread *thr, const char *fmt, ...) {
	DUK_ASSERT_API_ENTRY(thr);
	DUK__ERROR_STASH_SHARED(DUK_ERR_REFERENCE_ERROR);
}
DUK_EXTERNAL duk_ret_t duk_syntax_error_stash(duk_hthread *thr, const char *fmt, ...) {
	DUK_ASSERT_API_ENTRY(thr);
	DUK__ERROR_STASH_SHARED(DUK_ERR_SYNTAX_ERROR);
}
DUK_EXTERNAL duk_ret_t duk_type_error_stash(duk_hthread *thr, const char *fmt, ...) {
	DUK_ASSERT_API_ENTRY(thr);
	DUK__ERROR_STASH_SHARED(DUK_ERR_TYPE_ERROR);
}
DUK_EXTERNAL duk_ret_t duk_uri_error_stash(duk_hthread *thr, const char *fmt, ...) {
	DUK_ASSERT_API_ENTRY(thr);
	DUK__ERROR_STASH_SHARED(DUK_ERR_URI_ERROR);
}
#endif  /* DUK_USE_VARIADIC_MACROS */

/*
 *  Comparison
 */

DUK_EXTERNAL duk_bool_t duk_equals(duk_hthread *thr, duk_idx_t idx1, duk_idx_t idx2) {
	duk_tval *tv1, *tv2;

	DUK_ASSERT_API_ENTRY(thr);

	tv1 = duk_get_tval(thr, idx1);
	tv2 = duk_get_tval(thr, idx2);
	if ((tv1 == NULL) || (tv2 == NULL)) {
		return 0;
	}

	/* Coercion may be needed, the helper handles that by pushing the
	 * tagged values to the stack.
	 */
	return duk_js_equals(thr, tv1, tv2);
}

DUK_EXTERNAL duk_bool_t duk_strict_equals(duk_hthread *thr, duk_idx_t idx1, duk_idx_t idx2) {
	duk_tval *tv1, *tv2;

	DUK_ASSERT_API_ENTRY(thr);

	tv1 = duk_get_tval(thr, idx1);
	tv2 = duk_get_tval(thr, idx2);
	if ((tv1 == NULL) || (tv2 == NULL)) {
		return 0;
	}

	/* No coercions or other side effects, so safe */
	return duk_js_strict_equals(tv1, tv2);
}

DUK_EXTERNAL duk_bool_t duk_samevalue(duk_hthread *thr, duk_idx_t idx1, duk_idx_t idx2) {
	duk_tval *tv1, *tv2;

	DUK_ASSERT_API_ENTRY(thr);

	tv1 = duk_get_tval(thr, idx1);
	tv2 = duk_get_tval(thr, idx2);
	if ((tv1 == NULL) || (tv2 == NULL)) {
		return 0;
	}

	/* No coercions or other side effects, so safe */
	return duk_js_samevalue(tv1, tv2);
}

/*
 *  instanceof
 */

DUK_EXTERNAL duk_bool_t duk_instanceof(duk_hthread *thr, duk_idx_t idx1, duk_idx_t idx2) {
	duk_tval *tv1, *tv2;

	DUK_ASSERT_API_ENTRY(thr);

	/* Index validation is strict, which differs from duk_equals().
	 * The strict behavior mimics how instanceof itself works, e.g.
	 * it is a TypeError if rval is not a -callable- object.  It would
	 * be somewhat inconsistent if rval would be allowed to be
	 * non-existent without a TypeError.
	 */
	tv1 = duk_require_tval(thr, idx1);
	DUK_ASSERT(tv1 != NULL);
	tv2 = duk_require_tval(thr, idx2);
	DUK_ASSERT(tv2 != NULL);

	return duk_js_instanceof(thr, tv1, tv2);
}

/*
 *  Lightfunc
 */

DUK_INTERNAL void duk_push_lightfunc_name_raw(duk_hthread *thr, duk_c_function func, duk_small_uint_t lf_flags) {
	/* Lightfunc name, includes Duktape/C native function pointer, which
	 * can often be used to locate the function from a symbol table.
	 * The name also includes the 16-bit duk_tval flags field because it
	 * includes the magic value.  Because a single native function often
	 * provides different functionality depending on the magic value, it
	 * seems reasonably to include it in the name.
	 *
	 * On the other hand, a complicated name increases string table
	 * pressure in low memory environments (but only when function name
	 * is accessed).
	 */

	DUK_ASSERT_API_ENTRY(thr);

	duk_push_literal(thr, "light_");
	duk_push_string_funcptr(thr, (duk_uint8_t *) &func, sizeof(func));
	duk_push_sprintf(thr, "_%04x", (unsigned int) lf_flags);
	duk_concat(thr, 3);
}

DUK_INTERNAL void duk_push_lightfunc_name(duk_hthread *thr, duk_tval *tv) {
	duk_c_function func;
	duk_small_uint_t lf_flags;

	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv));

	DUK_TVAL_GET_LIGHTFUNC(tv, func, lf_flags);
	duk_push_lightfunc_name_raw(thr, func, lf_flags);
}

DUK_INTERNAL void duk_push_lightfunc_tostring(duk_hthread *thr, duk_tval *tv) {
	duk_c_function func;
	duk_small_uint_t lf_flags;

	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv));

	DUK_TVAL_GET_LIGHTFUNC(tv, func, lf_flags);  /* read before 'tv' potentially invalidated */
	duk_push_literal(thr, "function ");
	duk_push_lightfunc_name_raw(thr, func, lf_flags);
	duk_push_literal(thr, "() { [lightfunc code] }");
	duk_concat(thr, 3);
}

/*
 *  Function pointers
 *
 *  Printing function pointers is non-portable, so we do that by hex printing
 *  bytes from memory.
 */

DUK_INTERNAL void duk_push_string_funcptr(duk_hthread *thr, duk_uint8_t *ptr, duk_size_t sz) {
	duk_uint8_t buf[32 * 2];
	duk_uint8_t *p, *q;
	duk_small_uint_t i;
	duk_small_uint_t t;

	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(sz <= 32);  /* sanity limit for function pointer size */

	p = buf;
#if defined(DUK_USE_INTEGER_LE)
	q = ptr + sz;
#else
	q = ptr;
#endif
	for (i = 0; i < sz; i++) {
#if defined(DUK_USE_INTEGER_LE)
		t = *(--q);
#else
		t = *(q++);
#endif
		*p++ = duk_lc_digits[t >> 4];
		*p++ = duk_lc_digits[t & 0x0f];
	}

	duk_push_lstring(thr, (const char *) buf, sz * 2);
}

/*
 *  Push readable string summarizing duk_tval.  The operation is side effect
 *  free and will only throw from internal errors (e.g. out of memory).
 *  This is used by e.g. property access code to summarize a key/base safely,
 *  and is not intended to be fast (but small and safe).
 */

/* String limits for summary strings. */
#define DUK__READABLE_SUMMARY_MAXCHARS 96  /* maximum supported by helper */
#define DUK__READABLE_STRING_MAXCHARS  32  /* for strings/symbols */
#define DUK__READABLE_ERRMSG_MAXCHARS  96  /* for error messages */

/* String sanitizer which escapes ASCII control characters and a few other
 * ASCII characters, passes Unicode as is, and replaces invalid UTF-8 with
 * question marks.  No errors are thrown for any input string, except in out
 * of memory situations.
 */
DUK_LOCAL void duk__push_hstring_readable_unicode(duk_hthread *thr, duk_hstring *h_input, duk_small_uint_t maxchars) {
	const duk_uint8_t *p, *p_start, *p_end;
	duk_uint8_t buf[DUK_UNICODE_MAX_XUTF8_LENGTH * DUK__READABLE_SUMMARY_MAXCHARS +
	                2 /*quotes*/ + 3 /*periods*/];
	duk_uint8_t *q;
	duk_ucodepoint_t cp;
	duk_small_uint_t nchars;

	DUK_CTX_ASSERT_VALID(thr);
	DUK_ASSERT(h_input != NULL);
	DUK_ASSERT(maxchars <= DUK__READABLE_SUMMARY_MAXCHARS);

	p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
	p = p_start;
	q = buf;

	nchars = 0;
	*q++ = (duk_uint8_t) DUK_ASC_SINGLEQUOTE;
	for (;;) {
		if (p >= p_end) {
			break;
		}
		if (nchars == maxchars) {
			*q++ = (duk_uint8_t) DUK_ASC_PERIOD;
			*q++ = (duk_uint8_t) DUK_ASC_PERIOD;
			*q++ = (duk_uint8_t) DUK_ASC_PERIOD;
			break;
		}
		if (duk_unicode_decode_xutf8(thr, &p, p_start, p_end, &cp)) {
			if (cp < 0x20 || cp == 0x7f || cp == DUK_ASC_SINGLEQUOTE || cp == DUK_ASC_BACKSLASH) {
				DUK_ASSERT(DUK_UNICODE_MAX_XUTF8_LENGTH >= 4);  /* estimate is valid */
				DUK_ASSERT((cp >> 4) <= 0x0f);
				*q++ = (duk_uint8_t) DUK_ASC_BACKSLASH;
				*q++ = (duk_uint8_t) DUK_ASC_LC_X;
				*q++ = (duk_uint8_t) duk_lc_digits[cp >> 4];
				*q++ = (duk_uint8_t) duk_lc_digits[cp & 0x0f];
			} else {
				q += duk_unicode_encode_xutf8(cp, q);
			}
		} else {
			p++;  /* advance manually */
			*q++ = (duk_uint8_t) DUK_ASC_QUESTION;
		}
		nchars++;
	}
	*q++ = (duk_uint8_t) DUK_ASC_SINGLEQUOTE;

	duk_push_lstring(thr, (const char *) buf, (duk_size_t) (q - buf));
}

DUK_LOCAL const char *duk__push_string_tval_readable(duk_hthread *thr, duk_tval *tv, duk_bool_t error_aware) {
	DUK_CTX_ASSERT_VALID(thr);
	/* 'tv' may be NULL */

	if (tv == NULL) {
		duk_push_literal(thr, "none");
	} else {
		switch (DUK_TVAL_GET_TAG(tv)) {
		case DUK_TAG_STRING: {
			duk_hstring *h = DUK_TVAL_GET_STRING(tv);
			if (DUK_HSTRING_HAS_SYMBOL(h)) {
				/* XXX: string summary produces question marks
				 * so this is not very ideal.
				 */
				duk_push_literal(thr, "[Symbol ");
				duk_push_string(thr, duk__get_symbol_type_string(h));
				duk_push_literal(thr, " ");
				duk__push_hstring_readable_unicode(thr, h, DUK__READABLE_STRING_MAXCHARS);
				duk_push_literal(thr, "]");
				duk_concat(thr, 5);
				break;
			}
			duk__push_hstring_readable_unicode(thr, h, DUK__READABLE_STRING_MAXCHARS);
			break;
		}
		case DUK_TAG_OBJECT: {
			duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
			DUK_ASSERT(h != NULL);

			if (error_aware &&
			    duk_hobject_prototype_chain_contains(thr, h, thr->builtins[DUK_BIDX_ERROR_PROTOTYPE], 1 /*ignore_loop*/)) {
				/* Get error message in a side effect free way if
				 * possible; if not, summarize as a generic object.
				 * Error message currently gets quoted.
				 */
				/* XXX: better internal getprop call; get without side effects
				 * but traverse inheritance chain.
				 */
				duk_tval *tv_msg;
				tv_msg = duk_hobject_find_entry_tval_ptr_stridx(thr->heap, h, DUK_STRIDX_MESSAGE);
				if (tv_msg != NULL && DUK_TVAL_IS_STRING(tv_msg)) {
					/* It's critical to avoid recursion so
					 * only summarize a string .message.
					 */
					duk__push_hstring_readable_unicode(thr, DUK_TVAL_GET_STRING(tv_msg), DUK__READABLE_ERRMSG_MAXCHARS);
					break;
				}
			}
			duk_push_class_string_tval(thr, tv, 1 /*avoid_side_effects*/);
			break;
		}
		case DUK_TAG_BUFFER: {
			/* While plain buffers mimic Uint8Arrays, they summarize differently.
			 * This is useful so that the summarized string accurately reflects the
			 * internal type which may matter for figuring out bugs etc.
			 */
			/* XXX: Hex encoded, length limited buffer summary here? */
			duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
			DUK_ASSERT(h != NULL);
			duk_push_sprintf(thr, "[buffer:%ld]", (long) DUK_HBUFFER_GET_SIZE(h));
			break;
		}
		case DUK_TAG_POINTER: {
			/* Surround with parentheses like in JX, ensures NULL pointer
			 * is distinguishable from null value ("(null)" vs "null").
			 */
			duk_push_tval(thr, tv);
			duk_push_sprintf(thr, "(%s)", duk_to_string(thr, -1));
			duk_remove_m2(thr);
			break;
		}
		default: {
			duk_push_tval(thr, tv);
			break;
		}
		}
	}

	return duk_to_string(thr, -1);
}
DUK_INTERNAL const char *duk_push_string_tval_readable(duk_hthread *thr, duk_tval *tv) {
	DUK_ASSERT_API_ENTRY(thr);
	return duk__push_string_tval_readable(thr, tv, 0 /*error_aware*/);
}

DUK_INTERNAL const char *duk_push_string_readable(duk_hthread *thr, duk_idx_t idx) {
	DUK_ASSERT_API_ENTRY(thr);
	return duk_push_string_tval_readable(thr, duk_get_tval(thr, idx));
}

DUK_INTERNAL const char *duk_push_string_tval_readable_error(duk_hthread *thr, duk_tval *tv) {
	DUK_ASSERT_API_ENTRY(thr);
	return duk__push_string_tval_readable(thr, tv, 1 /*error_aware*/);
}

DUK_INTERNAL void duk_push_symbol_descriptive_string(duk_hthread *thr, duk_hstring *h) {
	const duk_uint8_t *p;
	const duk_uint8_t *p_end;
	const duk_uint8_t *q;

	DUK_ASSERT_API_ENTRY(thr);

	/* .toString() */
	duk_push_literal(thr, "Symbol(");
	p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
	p_end = p + DUK_HSTRING_GET_BYTELEN(h);
	DUK_ASSERT(p[0] == 0xff || (p[0] & 0xc0) == 0x80);
	p++;
	for (q = p; q < p_end; q++) {
		if (*q == 0xffU) {
			/* Terminate either at end-of-string (but NUL MUST
			 * be accepted without terminating description) or
			 * 0xFF, which is used to mark start of unique trailer
			 * (and cannot occur in CESU-8 / extended UTF-8).
			 */
			break;
		}
	}
	duk_push_lstring(thr, (const char *) p, (duk_size_t) (q - p));
	duk_push_literal(thr, ")");
	duk_concat(thr, 3);
}

/*
 *  Functions
 */

#if 0  /* not used yet */
DUK_INTERNAL void duk_push_hnatfunc_name(duk_hthread *thr, duk_hnatfunc *h) {
	duk_c_function func;

	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(h != NULL);
	DUK_ASSERT(DUK_HOBJECT_IS_NATFUNC((duk_hobject *) h));

	duk_push_sprintf(thr, "native_");
	func = h->func;
	duk_push_string_funcptr(thr, (duk_uint8_t *) &func, sizeof(func));
	duk_push_sprintf(thr, "_%04x_%04x",
	                 (unsigned int) (duk_uint16_t) h->nargs,
	                 (unsigned int) (duk_uint16_t) h->magic);
	duk_concat(thr, 3);
}
#endif

/*
 *  duk_tval slice copy
 */

DUK_INTERNAL void duk_copy_tvals_incref(duk_hthread *thr, duk_tval *tv_dst, duk_tval *tv_src, duk_size_t count) {
	duk_tval *tv;

	DUK_ASSERT_API_ENTRY(thr);
	DUK_UNREF(thr);
	DUK_ASSERT(count * sizeof(duk_tval) >= count);  /* no wrap */

	duk_memcpy_unsafe((void *) tv_dst, (const void *) tv_src, count * sizeof(duk_tval));

	tv = tv_dst;
	while (count-- > 0) {
		DUK_TVAL_INCREF(thr, tv);
		tv++;
	}
}

/* automatic undefs */
#undef DUK__ASSERT_SPACE
#undef DUK__CHECK_SPACE
#undef DUK__ERROR_STASH_SHARED
#undef DUK__PACK_ARGS
#undef DUK__READABLE_ERRMSG_MAXCHARS
#undef DUK__READABLE_STRING_MAXCHARS
#undef DUK__READABLE_SUMMARY_MAXCHARS
#line 1 "duk_api_string.c"
/*
 *  String manipulation
 */

/* #include duk_internal.h -> already included */

DUK_LOCAL void duk__concat_and_join_helper(duk_hthread *thr, duk_idx_t count_in, duk_bool_t is_join) {
	duk_uint_t count;
	duk_uint_t i;
	duk_size_t idx;
	duk_size_t len;
	duk_hstring *h;
	duk_uint8_t *buf;

	DUK_CTX_ASSERT_VALID(thr);

	if (DUK_UNLIKELY(count_in <= 0)) {
		if (count_in < 0) {
			DUK_ERROR_RANGE_INVALID_COUNT(thr);
			DUK_WO_NORETURN(return;);
		}
		DUK_ASSERT(count_in == 0);
		duk_push_hstring_empty(thr);
		return;
	}
	count = (duk_uint_t) count_in;

	if (is_join) {
		duk_size_t t1, t2, limit;
		h = duk_to_hstring(thr, -((duk_idx_t) count) - 1);
		DUK_ASSERT(h != NULL);

		/* A bit tricky overflow test, see doc/code-issues.rst. */
		t1 = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h);
		t2 = (duk_size_t) (count - 1);
		limit = (duk_size_t) DUK_HSTRING_MAX_BYTELEN;
		if (DUK_UNLIKELY(t2 != 0 && t1 > limit / t2)) {
			/* Combined size of separators already overflows. */
			goto error_overflow;
		}
		len = (duk_size_t) (t1 * t2);
	} else {
		len = (duk_size_t) 0;
	}

	for (i = count; i >= 1; i--) {
		duk_size_t new_len;
		h = duk_to_hstring(thr, -((duk_idx_t) i));
		new_len = len + (duk_size_t) DUK_HSTRING_GET_BYTELEN(h);

		/* Impose a string maximum length, need to handle overflow
		 * correctly.
		 */
		if (new_len < len ||  /* wrapped */
		    new_len > (duk_size_t) DUK_HSTRING_MAX_BYTELEN) {
			goto error_overflow;
		}
		len = new_len;
	}

	DUK_DDD(DUK_DDDPRINT("join/concat %lu strings, total length %lu bytes",
	                     (unsigned long) count, (unsigned long) len));

	/* Use stack allocated buffer to ensure reachability in errors
	 * (e.g. intern error).
	 */
	buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, len);
	DUK_ASSERT(buf != NULL);

	/* [ ... (sep) str1 str2 ... strN buf ] */

	idx = 0;
	for (i = count; i >= 1; i--) {
		if (is_join && i != count) {
			h = duk_require_hstring(thr, -((duk_idx_t) count) - 2);  /* extra -1 for buffer */
			duk_memcpy(buf + idx, DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
			idx += DUK_HSTRING_GET_BYTELEN(h);
		}
		h = duk_require_hstring(thr, -((duk_idx_t) i) - 1);  /* extra -1 for buffer */
		duk_memcpy(buf + idx, DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
		idx += DUK_HSTRING_GET_BYTELEN(h);
	}

	DUK_ASSERT(idx == len);

	/* [ ... (sep) str1 str2 ... strN buf ] */

	/* Get rid of the strings early to minimize memory use before intern. */

	if (is_join) {
		duk_replace(thr, -((duk_idx_t) count) - 2);  /* overwrite sep */
		duk_pop_n(thr, (duk_idx_t) count);
	} else {
		duk_replace(thr, -((duk_idx_t) count) - 1);  /* overwrite str1 */
		duk_pop_n(thr, (duk_idx_t) (count - 1));
	}

	/* [ ... buf ] */

	(void) duk_buffer_to_string(thr, -1);  /* Safe if inputs are safe. */

	/* [ ... res ] */
	return;

 error_overflow:
	DUK_ERROR_RANGE(thr, DUK_STR_RESULT_TOO_LONG);
	DUK_WO_NORETURN(return;);
}

DUK_EXTERNAL void duk_concat(duk_hthread *thr, duk_idx_t count) {
	DUK_ASSERT_API_ENTRY(thr);

	duk__concat_and_join_helper(thr, count, 0 /*is_join*/);
}

#if defined(DUK_USE_PREFER_SIZE)
DUK_INTERNAL void duk_concat_2(duk_hthread *thr) {
	DUK_ASSERT_API_ENTRY(thr);
	duk_concat(thr, 2);
}
#else  /* DUK_USE_PREFER_SIZE */
DUK_INTERNAL void duk_concat_2(duk_hthread *thr) {
	duk_hstring *h1;
	duk_hstring *h2;
	duk_uint8_t *buf;
	duk_size_t len1;
	duk_size_t len2;
	duk_size_t len;

	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(duk_get_top(thr) >= 2);  /* Trusted caller. */

	h1 = duk_to_hstring(thr, -2);
	h2 = duk_to_hstring(thr, -1);
	len1 = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h1);
	len2 = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h2);
	len = len1 + len2;
	if (DUK_UNLIKELY(len < len1 ||  /* wrapped */
	                 len > (duk_size_t) DUK_HSTRING_MAX_BYTELEN)) {
		goto error_overflow;
	}
	buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, len);
	DUK_ASSERT(buf != NULL);

	duk_memcpy((void *) buf, (const void *) DUK_HSTRING_GET_DATA(h1), (size_t) len1);
	duk_memcpy((void *) (buf + len1), (const void *) DUK_HSTRING_GET_DATA(h2), (size_t) len2);
	(void) duk_buffer_to_string(thr, -1);  /* Safe if inputs are safe. */

	/* [ ... str1 str2 buf ] */

	duk_replace(thr, -3);
	duk_pop_unsafe(thr);
	return;

 error_overflow:
	DUK_ERROR_RANGE(thr, DUK_STR_RESULT_TOO_LONG);
	DUK_WO_NORETURN(return;);
}
#endif  /* DUK_USE_PREFER_SIZE */

DUK_EXTERNAL void duk_join(duk_hthread *thr, duk_idx_t count) {
	DUK_ASSERT_API_ENTRY(thr);

	duk__concat_and_join_helper(thr, count, 1 /*is_join*/);
}

/* XXX: could map/decode be unified with duk_unicode_support.c code?
 * Case conversion needs also the character surroundings though.
 */

DUK_EXTERNAL void duk_decode_string(duk_hthread *thr, duk_idx_t idx, duk_decode_char_function callback, void *udata) {
	duk_hstring *h_input;
	const duk_uint8_t *p, *p_start, *p_end;
	duk_codepoint_t cp;

	DUK_ASSERT_API_ENTRY(thr);

	h_input = duk_require_hstring(thr, idx);  /* Accept symbols. */
	DUK_ASSERT(h_input != NULL);

	p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
	p = p_start;

	for (;;) {
		if (p >= p_end) {
			break;
		}
		cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p, p_start, p_end);
		callback(udata, cp);
	}
}

DUK_EXTERNAL void duk_map_string(duk_hthread *thr, duk_idx_t idx, duk_map_char_function callback, void *udata) {
	duk_hstring *h_input;
	duk_bufwriter_ctx bw_alloc;
	duk_bufwriter_ctx *bw;
	const duk_uint8_t *p, *p_start, *p_end;
	duk_codepoint_t cp;

	DUK_ASSERT_API_ENTRY(thr);

	idx = duk_normalize_index(thr, idx);

	h_input = duk_require_hstring(thr, idx);  /* Accept symbols. */
	DUK_ASSERT(h_input != NULL);

	bw = &bw_alloc;
	DUK_BW_INIT_PUSHBUF(thr, bw, DUK_HSTRING_GET_BYTELEN(h_input));  /* Reasonable output estimate. */

	p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
	p = p_start;

	for (;;) {
		/* XXX: could write output in chunks with fewer ensure calls,
		 * but relative benefit would be small here.
		 */

		if (p >= p_end) {
			break;
		}
		cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p, p_start, p_end);
		cp = callback(udata, cp);

		DUK_BW_WRITE_ENSURE_XUTF8(thr, bw, cp);
	}

	DUK_BW_COMPACT(thr, bw);
	(void) duk_buffer_to_string(thr, -1);  /* Safe, extended UTF-8 encoded. */
	duk_replace(thr, idx);
}

DUK_EXTERNAL void duk_substring(duk_hthread *thr, duk_idx_t idx, duk_size_t start_offset, duk_size_t end_offset) {
	duk_hstring *h;
	duk_hstring *res;
	duk_size_t start_byte_offset;
	duk_size_t end_byte_offset;
	duk_size_t charlen;

	DUK_ASSERT_API_ENTRY(thr);

	idx = duk_require_normalize_index(thr, idx);  /* Accept symbols. */
	h = duk_require_hstring(thr, idx);
	DUK_ASSERT(h != NULL);

	charlen = DUK_HSTRING_GET_CHARLEN(h);
	if (end_offset >= charlen) {
		end_offset = charlen;
	}
	if (start_offset > end_offset) {
		start_offset = end_offset;
	}

	DUK_ASSERT_DISABLE(start_offset >= 0);
	DUK_ASSERT(start_offset <= end_offset && start_offset <= DUK_HSTRING_GET_CHARLEN(h));
	DUK_ASSERT_DISABLE(end_offset >= 0);
	DUK_ASSERT(end_offset >= start_offset && end_offset <= DUK_HSTRING_GET_CHARLEN(h));

	/* Guaranteed by string limits. */
	DUK_ASSERT(start_offset <= DUK_UINT32_MAX);
	DUK_ASSERT(end_offset <= DUK_UINT32_MAX);

	start_byte_offset = (duk_size_t) duk_heap_strcache_offset_char2byte(thr, h, (duk_uint_fast32_t) start_offset);
	end_byte_offset = (duk_size_t) duk_heap_strcache_offset_char2byte(thr, h, (duk_uint_fast32_t) end_offset);

	DUK_ASSERT(end_byte_offset >= start_byte_offset);
	DUK_ASSERT(end_byte_offset - start_byte_offset <= DUK_UINT32_MAX);  /* Guaranteed by string limits. */

	/* No size check is necessary. */
	res = duk_heap_strtable_intern_checked(thr,
	                                       DUK_HSTRING_GET_DATA(h) + start_byte_offset,
	                                       (duk_uint32_t) (end_byte_offset - start_byte_offset));

	duk_push_hstring(thr, res);
	duk_replace(thr, idx);
}

/* XXX: this is quite clunky.  Add Unicode helpers to scan backwards and
 * forwards with a callback to process codepoints?
 */
DUK_EXTERNAL void duk_trim(duk_hthread *thr, duk_idx_t idx) {
	duk_hstring *h;
	const duk_uint8_t *p, *p_start, *p_end, *p_tmp1, *p_tmp2;  /* pointers for scanning */
	const duk_uint8_t *q_start, *q_end;  /* start (incl) and end (excl) of trimmed part */
	duk_codepoint_t cp;

	DUK_ASSERT_API_ENTRY(thr);

	idx = duk_require_normalize_index(thr, idx);  /* Accept symbols. */
	h = duk_require_hstring(thr, idx);
	DUK_ASSERT(h != NULL);

	p_start = DUK_HSTRING_GET_DATA(h);
	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h);

	p = p_start;
	while (p < p_end) {
		p_tmp1 = p;
		cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p_tmp1, p_start, p_end);
		if (!(duk_unicode_is_whitespace(cp) || duk_unicode_is_line_terminator(cp))) {
			break;
		}
		p = p_tmp1;
	}
	q_start = p;
	if (p == p_end) {
		/* Entire string is whitespace. */
		q_end = p;
		goto scan_done;
	}

	p = p_end;
	while (p > p_start) {
		p_tmp1 = p;
		while (p > p_start) {
			p--;
			if (((*p) & 0xc0) != 0x80) {
				break;
			}
		}
		p_tmp2 = p;

		cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p_tmp2, p_start, p_end);
		if (!(duk_unicode_is_whitespace(cp) || duk_unicode_is_line_terminator(cp))) {
			p = p_tmp1;
			break;
		}
	}
	q_end = p;

 scan_done:
	/* This may happen when forward and backward scanning disagree
	 * (possible for non-extended-UTF-8 strings).
	 */
	if (q_end < q_start) {
		q_end = q_start;
	}

	DUK_ASSERT(q_start >= p_start && q_start <= p_end);
	DUK_ASSERT(q_end >= p_start && q_end <= p_end);
	DUK_ASSERT(q_end >= q_start);

	DUK_DDD(DUK_DDDPRINT("trim: p_start=%p, p_end=%p, q_start=%p, q_end=%p",
	                     (const void *) p_start, (const void *) p_end,
	                     (const void *) q_start, (const void *) q_end));

	if (q_start == p_start && q_end == p_end) {
		DUK_DDD(DUK_DDDPRINT("nothing was trimmed: avoid interning (hashing etc)"));
		return;
	}

	duk_push_lstring(thr, (const char *) q_start, (duk_size_t) (q_end - q_start));
	duk_replace(thr, idx);
}

DUK_EXTERNAL duk_codepoint_t duk_char_code_at(duk_hthread *thr, duk_idx_t idx, duk_size_t char_offset) {
	duk_hstring *h;
	duk_ucodepoint_t cp;

	DUK_ASSERT_API_ENTRY(thr);

	/* XXX: Share code with String.prototype.charCodeAt?  Main difference
	 * is handling of clamped offsets.
	 */

	h = duk_require_hstring(thr, idx);  /* Accept symbols. */
	DUK_ASSERT(h != NULL);

	DUK_ASSERT_DISABLE(char_offset >= 0);  /* Always true, arg is unsigned. */
	if (char_offset >= DUK_HSTRING_GET_CHARLEN(h)) {
		return 0;
	}

	DUK_ASSERT(char_offset <= DUK_UINT_MAX);  /* Guaranteed by string limits. */
	cp = duk_hstring_char_code_at_raw(thr, h, (duk_uint_t) char_offset, 0 /*surrogate_aware*/);
	return (duk_codepoint_t) cp;
}
#line 1 "duk_api_time.c"
/*
 *  Date/time.
 */

/* #include duk_internal.h -> already included */

DUK_INTERNAL duk_double_t duk_time_get_ecmascript_time(duk_hthread *thr) {
	/* ECMAScript time, with millisecond fractions.  Exposed via
	 * duk_get_now() for example.
	 */
	DUK_UNREF(thr);
	return (duk_double_t) DUK_USE_DATE_GET_NOW(thr);
}

DUK_INTERNAL duk_double_t duk_time_get_ecmascript_time_nofrac(duk_hthread *thr) {
	/* ECMAScript time without millisecond fractions.  Exposed via
	 * the Date built-in which doesn't allow fractions.
	 */
	DUK_UNREF(thr);
	return (duk_double_t) DUK_FLOOR(DUK_USE_DATE_GET_NOW(thr));
}

DUK_INTERNAL duk_double_t duk_time_get_monotonic_time(duk_hthread *thr) {
	DUK_UNREF(thr);
#if defined(DUK_USE_GET_MONOTONIC_TIME)
	return (duk_double_t) DUK_USE_GET_MONOTONIC_TIME(thr);
#else
	return (duk_double_t) DUK_USE_DATE_GET_NOW(thr);
#endif
}

DUK_EXTERNAL duk_double_t duk_get_now(duk_hthread *thr) {
	DUK_ASSERT_API_ENTRY(thr);
	DUK_UNREF(thr);

	/* This API intentionally allows millisecond fractions. */
	return duk_time_get_ecmascript_time(thr);
}

#if 0  /* XXX: worth exposing? */
DUK_EXTERNAL duk_double_t duk_get_monotonic_time(duk_hthread *thr) {
	DUK_ASSERT_API_ENTRY(thr);
	DUK_UNREF(thr);

	return duk_time_get_monotonic_time(thr);
}
#endif

DUK_EXTERNAL void duk_time_to_components(duk_hthread *thr, duk_double_t timeval, duk_time_components *comp) {
	duk_int_t parts[DUK_DATE_IDX_NUM_PARTS];
	duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
	duk_uint_t flags;

	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(comp != NULL);  /* XXX: or check? */
	DUK_UNREF(thr);

	/* Convert as one-based, but change month to zero-based to match the
	 * ECMAScript Date built-in behavior 1:1.
	 */
	flags = DUK_DATE_FLAG_ONEBASED | DUK_DATE_FLAG_NAN_TO_ZERO;

	duk_bi_date_timeval_to_parts(timeval, parts, dparts, flags);

	/* XXX: sub-millisecond accuracy for the API */

	DUK_ASSERT(dparts[DUK_DATE_IDX_MONTH] >= 1.0 && dparts[DUK_DATE_IDX_MONTH] <= 12.0);
	comp->year = dparts[DUK_DATE_IDX_YEAR];
	comp->month = dparts[DUK_DATE_IDX_MONTH] - 1.0;
	comp->day = dparts[DUK_DATE_IDX_DAY];
	comp->hours = dparts[DUK_DATE_IDX_HOUR];
	comp->minutes = dparts[DUK_DATE_IDX_MINUTE];
	comp->seconds = dparts[DUK_DATE_IDX_SECOND];
	comp->milliseconds = dparts[DUK_DATE_IDX_MILLISECOND];
	comp->weekday = dparts[DUK_DATE_IDX_WEEKDAY];
}

DUK_EXTERNAL duk_double_t duk_components_to_time(duk_hthread *thr, duk_time_components *comp) {
	duk_double_t d;
	duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
	duk_uint_t flags;

	DUK_ASSERT_API_ENTRY(thr);
	DUK_ASSERT(comp != NULL);  /* XXX: or check? */
	DUK_UNREF(thr);

	/* Match Date constructor behavior (with UTC time).  Month is given
	 * as zero-based.  Day-of-month is given as one-based so normalize
	 * it to zero-based as the internal conversion helpers expects all
	 * components to be zero-based.
	 */
	flags = 0;

	/* XXX: expensive conversion; use array format in API instead, or unify
	 * time provider and time API to use same struct?
	 */

	dparts[DUK_DATE_IDX_YEAR] = comp->year;
	dparts[DUK_DATE_IDX_MONTH] = comp->month;
	dparts[DUK_DATE_IDX_DAY] = comp->day - 1.0;
	dparts[DUK_DATE_IDX_HOUR] = comp->hours;
	dparts[DUK_DATE_IDX_MINUTE] = comp->minutes;
	dparts[DUK_DATE_IDX_SECOND] = comp->seconds;
	dparts[DUK_DATE_IDX_MILLISECOND] = comp->milliseconds;
	dparts[DUK_DATE_IDX_WEEKDAY] = 0;  /* ignored */

	d = duk_bi_date_get_timeval_from_dparts(dparts, flags);

	return d;
}
#line 1 "duk_bi_array.c"
/*
 *  Array built-ins
 *
 *  Most Array built-ins are intentionally generic in ECMAScript, and are
 *  intended to work even when the 'this' binding is not an Array instance.
 *  This ECMAScript feature is also used by much real world code.  For this
 *  reason the implementations here don't assume exotic Array behavior or
 *  e.g. presence of a .length property.  However, some algorithms have a
 *  fast path for duk_harray backed actual Array instances, enabled when
 *  footprint is not a concern.
 *
 *  XXX: the "Throw" flag should be set for (almost?) all [[Put]] and
 *  [[Delete]] operations, but it's currently false throughout.  Go through
 *  all put/delete cases and check throw flag use.  Need a new API primitive
 *  which allows throws flag to be specified.
 *
 *  XXX: array lengths above 2G won't work reliably.  There are many places
 *  where one needs a full signed 32-bit range ([-0xffffffff, 0xffffffff],
 *  i.e. -33- bits).  Although array 'length' cannot be written to be outside
 *  the unsigned 32-bit range (E5.1 Section 15.4.5.1 throws a RangeError if so)
 *  some intermediate values may be above 0xffffffff and this may not be always
 *  correctly handled now (duk_uint32_t is not enough for all algorithms).
 *  For instance, push() can legitimately write entries beyond length 0xffffffff
 *  and cause a RangeError only at the end.  To do this properly, the current
 *  push() implementation tracks the array index using a 'double' instead of a
 *  duk_uint32_t (which is somewhat awkward).  See test-bi-array-push-maxlen.js.
 *
 *  On using "put" vs. "def" prop
 *  =============================
 *
 *  Code below must be careful to use the appropriate primitive as it matters
 *  for compliance.  When using "put" there may be inherited properties in
 *  Array.prototype which cause side effects when values are written.  When
 *  using "define" there are no such side effects, and many test262 test cases
 *  check for this (for real world code, such side effects are very rare).
 *  Both "put" and "define" are used in the E5.1 specification; as a rule,
 *  "put" is used when modifying an existing array (or a non-array 'this'
 *  binding) and "define" for setting values into a fresh result array.
 */

/* #include duk_internal.h -> already included */

/* Perform an intermediate join when this many elements have been pushed
 * on the value stack.
 */
#define  DUK__ARRAY_MID_JOIN_LIMIT  4096

#if defined(DUK_USE_ARRAY_BUILTIN)

/*
 *  Shared helpers.
 */

/* Shared entry code for many Array built-ins: the 'this' binding is pushed
 * on the value stack and object coerced, and the current .length is returned.
 * Note that length is left on stack (it could be popped, but that's not
 * usually necessary because call handling will clean it up automatically).
 */
DUK_LOCAL duk_uint32_t duk__push_this_obj_len_u32(duk_hthread *thr) {
	duk_uint32_t len;

	/* XXX: push more directly? */
	(void) duk_push_this_coercible_to_object(thr);
	DUK_HOBJECT_ASSERT_VALID(duk_get_hobject(thr, -1));
	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_LENGTH);
	len = duk_to_uint32(thr, -1);

	/* -> [ ... ToObject(this) ToUint32(length) ] */
	return len;
}

DUK_LOCAL duk_uint32_t duk__push_this_obj_len_u32_limited(duk_hthread *thr) {
	/* Range limited to [0, 0x7fffffff] range, i.e. range that can be
	 * represented with duk_int32_t.  Use this when the method doesn't
	 * handle the full 32-bit unsigned range correctly.
	 */
	duk_uint32_t ret = duk__push_this_obj_len_u32(thr);
	if (DUK_UNLIKELY(ret >= 0x80000000UL)) {
		DUK_ERROR_RANGE_INVALID_LENGTH(thr);
		DUK_WO_NORETURN(return 0U;);
	}
	return ret;
}

#if defined(DUK_USE_ARRAY_FASTPATH)
/* Check if 'this' binding is an Array instance (duk_harray) which satisfies
 * a few other guarantees for fast path operation.  The fast path doesn't
 * need to handle all operations, even for duk_harrays, but must handle a
 * significant fraction to improve performance.  Return a non-NULL duk_harray
 * pointer when all fast path criteria are met, NULL otherwise.
 */
DUK_LOCAL duk_harray *duk__arraypart_fastpath_this(duk_hthread *thr) {
	duk_tval *tv;
	duk_hobject *h;
	duk_uint_t flags_mask, flags_bits, flags_value;

	DUK_ASSERT(thr->valstack_bottom > thr->valstack);  /* because call in progress */
	tv = DUK_GET_THIS_TVAL_PTR(thr);

	/* Fast path requires that 'this' is a duk_harray.  Read only arrays
	 * (ROM backed) are also rejected for simplicity.
	 */
	if (!DUK_TVAL_IS_OBJECT(tv)) {
		DUK_DD(DUK_DDPRINT("reject array fast path: not an object"));
		return NULL;
	}
	h = DUK_TVAL_GET_OBJECT(tv);
	DUK_ASSERT(h != NULL);
	flags_mask = DUK_HOBJECT_FLAG_ARRAY_PART | \
	             DUK_HOBJECT_FLAG_EXOTIC_ARRAY | \
	             DUK_HEAPHDR_FLAG_READONLY;
	flags_bits = DUK_HOBJECT_FLAG_ARRAY_PART | \
	             DUK_HOBJECT_FLAG_EXOTIC_ARRAY;
	flags_value = DUK_HEAPHDR_GET_FLAGS_RAW((duk_heaphdr *) h);
	if ((flags_value & flags_mask) != flags_bits) {
		DUK_DD(DUK_DDPRINT("reject array fast path: object flag check failed"));
		return NULL;
	}

	/* In some cases a duk_harray's 'length' may be larger than the
	 * current array part allocation.  Avoid the fast path in these
	 * cases, so that all fast path code can safely assume that all
	 * items in the range [0,length[ are backed by the current array
	 * part allocation.
	 */
	if (((duk_harray *) h)->length > DUK_HOBJECT_GET_ASIZE(h)) {
		DUK_DD(DUK_DDPRINT("reject array fast path: length > array part size"));
		return NULL;
	}

	/* Guarantees for fast path. */
	DUK_ASSERT(h != NULL);
	DUK_ASSERT(DUK_HOBJECT_GET_ASIZE(h) == 0 || DUK_HOBJECT_A_GET_BASE(thr->heap, h) != NULL);
	DUK_ASSERT(((duk_harray *) h)->length <= DUK_HOBJECT_GET_ASIZE(h));

	DUK_DD(DUK_DDPRINT("array fast path allowed for: %!O", (duk_heaphdr *) h));
	return (duk_harray *) h;
}
#endif  /* DUK_USE_ARRAY_FASTPATH */

/*
 *  Constructor
 */

DUK_INTERNAL duk_ret_t duk_bi_array_constructor(duk_hthread *thr) {
	duk_idx_t nargs;
	duk_harray *a;
	duk_double_t d;
	duk_uint32_t len;
	duk_uint32_t len_prealloc;

	nargs = duk_get_top(thr);

	if (nargs == 1 && duk_is_number(thr, 0)) {
		/* XXX: expensive check (also shared elsewhere - so add a shared internal API call?) */
		d = duk_get_number(thr, 0);
		len = duk_to_uint32(thr, 0);
		if (!duk_double_equals((duk_double_t) len, d)) {
			DUK_DCERROR_RANGE_INVALID_LENGTH(thr);
		}

		/* For small lengths create a dense preallocated array.
		 * For large arrays preallocate an initial part.
		 */
		len_prealloc = len < 64 ? len : 64;
		a = duk_push_harray_with_size(thr, len_prealloc);
		DUK_ASSERT(a != NULL);
		DUK_ASSERT(!duk_is_bare_object(thr, -1));
		a->length = len;
		return 1;
	}

	duk_pack(thr, nargs);
	return 1;
}

/*
 *  isArray()
 */

DUK_INTERNAL duk_ret_t duk_bi_array_constructor_is_array(duk_hthread *thr) {
	DUK_ASSERT_TOP(thr, 1);
	duk_push_boolean(thr, duk_js_isarray(DUK_GET_TVAL_POSIDX(thr, 0)));
	return 1;
}

/*
 *  toString()
 */

DUK_INTERNAL duk_ret_t duk_bi_array_prototype_to_string(duk_hthread *thr) {
	(void) duk_push_this_coercible_to_object(thr);
	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_JOIN);

	/* [ ... this func ] */
	if (!duk_is_callable(thr, -1)) {
		/* Fall back to the initial (original) Object.toString().  We don't
		 * currently have pointers to the built-in functions, only the top
		 * level global objects (like "Array") so this is now done in a bit
		 * of a hacky manner.  It would be cleaner to push the (original)
		 * function and use duk_call_method().
		 */

		/* XXX: 'this' will be ToObject() coerced twice, which is incorrect
		 * but should have no visible side effects.
		 */
		DUK_DDD(DUK_DDDPRINT("this.join is not callable, fall back to (original) Object.toString"));
		duk_set_top(thr, 0);
		return duk_bi_object_prototype_to_string(thr);  /* has access to 'this' binding */
	}

	/* [ ... this func ] */

	duk_insert(thr, -2);

	/* [ ... func this ] */

	DUK_DDD(DUK_DDDPRINT("calling: func=%!iT, this=%!iT",
	                     (duk_tval *) duk_get_tval(thr, -2),
	                     (duk_tval *) duk_get_tval(thr, -1)));
	duk_call_method(thr, 0);

	return 1;
}

/*
 *  concat()
 */

DUK_INTERNAL duk_ret_t duk_bi_array_prototype_concat(duk_hthread *thr) {
	duk_idx_t i, n;
	duk_uint32_t j, idx, len;
	duk_hobject *h;
	duk_size_t tmp_len;

	/* XXX: In ES2015 Array .length can be up to 2^53-1.  The current
	 * implementation is limited to 2^32-1.
	 */

	/* XXX: Fast path for array 'this' and array element. */

	/* XXX: The insert here is a bit expensive if there are a lot of items.
	 * It could also be special cased in the outermost for loop quite easily
	 * (as the element is dup()'d anyway).
	 */

	(void) duk_push_this_coercible_to_object(thr);
	duk_insert(thr, 0);
	n = duk_get_top(thr);
	duk_push_array(thr);  /* -> [ ToObject(this) item1 ... itemN arr ] */

	/* NOTE: The Array special behaviors are NOT invoked by duk_xdef_prop_index()
	 * (which differs from the official algorithm).  If no error is thrown, this
	 * doesn't matter as the length is updated at the end.  However, if an error
	 * is thrown, the length will be unset.  That shouldn't matter because the
	 * caller won't get a reference to the intermediate value.
	 */

	idx = 0;
	for (i = 0; i < n; i++) {
		duk_bool_t spreadable;
		duk_bool_t need_has_check;

		DUK_ASSERT_TOP(thr, n + 1);

		/* [ ToObject(this) item1 ... itemN arr ] */

		h = duk_get_hobject(thr, i);

		if (h == NULL) {
			spreadable = 0;
		} else {
#if defined(DUK_USE_SYMBOL_BUILTIN)
			duk_get_prop_stridx(thr, i, DUK_STRIDX_WELLKNOWN_SYMBOL_IS_CONCAT_SPREADABLE);
			if (duk_is_undefined(thr, -1)) {
				spreadable = duk_js_isarray_hobject(h);
			} else {
				spreadable = duk_to_boolean(thr, -1);
			}
			duk_pop_nodecref_unsafe(thr);
#else
			spreadable = duk_js_isarray_hobject(h);
#endif
		}

		if (!spreadable) {
			duk_dup(thr, i);
			duk_xdef_prop_index_wec(thr, -2, idx);
			idx++;
			if (DUK_UNLIKELY(idx == 0U)) {
				/* Index after update is 0, and index written
				 * was 0xffffffffUL which is no longer a valid
				 * array index.
				 */
				goto fail_wrap;
			}
			continue;
		}

		DUK_ASSERT(duk_is_object(thr, i));
		need_has_check = (DUK_HOBJECT_IS_PROXY(h) != 0);  /* Always 0 w/o Proxy support. */

		/* [ ToObject(this) item1 ... itemN arr ] */

		tmp_len = duk_get_length(thr, i);
		len = (duk_uint32_t) tmp_len;
		if (DUK_UNLIKELY(tmp_len != (duk_size_t) len)) {
			goto fail_wrap;
		}
		if (DUK_UNLIKELY(idx + len < idx)) {
			/* Result length must be at most 0xffffffffUL to be
			 * a valid 32-bit array index.
			 */
			goto fail_wrap;
		}
		for (j = 0; j < len; j++) {
			/* For a Proxy element, an explicit 'has' check is
			 * needed to allow the Proxy to present gaps.
			 */
			if (need_has_check) {
				if (duk_has_prop_index(thr, i, j)) {
					duk_get_prop_index(thr, i, j);
					duk_xdef_prop_index_wec(thr, -2, idx);
				}
			} else {
				if (duk_get_prop_index(thr, i, j)) {
					duk_xdef_prop_index_wec(thr, -2, idx);
				} else {
					duk_pop_undefined(thr);
				}
			}
			idx++;
			DUK_ASSERT(idx != 0U);  /* Wrap check above. */
		}
	}

	/* ES5.1 has a specification "bug" in that nonexistent trailing
	 * elements don't affect the result .length.  Test262 and other
	 * engines disagree, and the specification bug was fixed in ES2015
	 * (see NOTE 1 in https://www.ecma-international.org/ecma-262/6.0/#sec-array.prototype.concat).
	 */
	duk_push_uarridx(thr, idx);
	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W);

	DUK_ASSERT_TOP(thr, n + 1);
	return 1;

 fail_wrap:
	DUK_ERROR_RANGE_INVALID_LENGTH(thr);
	DUK_WO_NORETURN(return 0;);
}

/*
 *  join(), toLocaleString()
 *
 *  Note: checking valstack is necessary, but only in the per-element loop.
 *
 *  Note: the trivial approach of pushing all the elements on the value stack
 *  and then calling duk_join() fails when the array contains a large number
 *  of elements.  This problem can't be offloaded to duk_join() because the
 *  elements to join must be handled here and have special handling.  Current
 *  approach is to do intermediate joins with very large number of elements.
 *  There is no fancy handling; the prefix gets re-joined multiple times.
 */

DUK_INTERNAL duk_ret_t duk_bi_array_prototype_join_shared(duk_hthread *thr) {
	duk_uint32_t len, count;
	duk_uint32_t idx;
	duk_small_int_t to_locale_string = duk_get_current_magic(thr);
	duk_idx_t valstack_required;

	/* For join(), nargs is 1.  For toLocaleString(), nargs is 0 and
	 * setting the top essentially pushes an undefined to the stack,
	 * thus defaulting to a comma separator.
	 */
	duk_set_top(thr, 1);
	if (duk_is_undefined(thr, 0)) {
		duk_pop_undefined(thr);
		duk_push_hstring_stridx(thr, DUK_STRIDX_COMMA);
	} else {
		duk_to_string(thr, 0);
	}

	len = duk__push_this_obj_len_u32(thr);

	/* [ sep ToObject(this) len ] */

	DUK_DDD(DUK_DDDPRINT("sep=%!T, this=%!T, len=%lu",
	                     (duk_tval *) duk_get_tval(thr, 0),
	                     (duk_tval *) duk_get_tval(thr, 1),
	                     (unsigned long) len));

	/* The extra (+4) is tight. */
	valstack_required = (duk_idx_t) ((len >= DUK__ARRAY_MID_JOIN_LIMIT ?
	                                  DUK__ARRAY_MID_JOIN_LIMIT : len) + 4);
	duk_require_stack(thr, valstack_required);

	duk_dup_0(thr);

	/* [ sep ToObject(this) len sep ] */

	count = 0;
	idx = 0;
	for (;;) {
		DUK_DDD(DUK_DDDPRINT("join idx=%ld", (long) idx));
		if (count >= DUK__ARRAY_MID_JOIN_LIMIT ||   /* intermediate join to avoid valstack overflow */
		    idx >= len) { /* end of loop (careful with len==0) */
			/* [ sep ToObject(this) len sep str0 ... str(count-1) ] */
			DUK_DDD(DUK_DDDPRINT("mid/final join, count=%ld, idx=%ld, len=%ld",
			                     (long) count, (long) idx, (long) len));
			duk_join(thr, (duk_idx_t) count);  /* -> [ sep ToObject(this) len str ] */
			duk_dup_0(thr);                    /* -> [ sep ToObject(this) len str sep ] */
			duk_insert(thr, -2);               /* -> [ sep ToObject(this) len sep str ] */
			count = 1;
		}
		if (idx >= len) {
			/* if true, the stack already contains the final result */
			break;
		}

		duk_get_prop_index(thr, 1, (duk_uarridx_t) idx);
		if (duk_is_null_or_undefined(thr, -1)) {
			duk_pop_nodecref_unsafe(thr);
			duk_push_hstring_empty(thr);
		} else {
			if (to_locale_string) {
				duk_to_object(thr, -1);
				duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_TO_LOCALE_STRING);
				duk_insert(thr, -2);  /* -> [ ... toLocaleString ToObject(val) ] */
				duk_call_method(thr, 0);
			}
			duk_to_string(thr, -1);
		}

		count++;
		idx++;
	}

	/* [ sep ToObject(this) len sep result ] */

	return 1;
}

/*
 *  pop(), push()
 */

#if defined(DUK_USE_ARRAY_FASTPATH)
DUK_LOCAL duk_ret_t duk__array_pop_fastpath(duk_hthread *thr, duk_harray *h_arr) {
	duk_tval *tv_arraypart;
	duk_tval *tv_val;
	duk_uint32_t len;

	tv_arraypart = DUK_HOBJECT_A_GET_BASE(thr->heap, (duk_hobject *) h_arr);
	len = h_arr->length;
	if (len <= 0) {
		/* nop, return undefined */
		return 0;
	}

	len--;
	h_arr->length = len;

	/* Fast path doesn't check for an index property inherited from
	 * Array.prototype.  This is quite often acceptable; if not,
	 * disable fast path.
	 */
	DUK_ASSERT_VS_SPACE(thr);
	tv_val = tv_arraypart + len;
	if (DUK_TVAL_IS_UNUSED(tv_val)) {
		/* No net refcount change.  Value stack already has
		 * 'undefined' based on value stack init policy.
		 */
		DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top));
		DUK_ASSERT(DUK_TVAL_IS_UNUSED(tv_val));
	} else {
		/* No net refcount change. */
		DUK_TVAL_SET_TVAL(thr->valstack_top, tv_val);
		DUK_TVAL_SET_UNUSED(tv_val);
	}
	thr->valstack_top++;

	/* XXX: there's no shrink check in the fast path now */

	return 1;
}
#endif  /* DUK_USE_ARRAY_FASTPATH */

DUK_INTERNAL duk_ret_t duk_bi_array_prototype_pop(duk_hthread *thr) {
	duk_uint32_t len;
	duk_uint32_t idx;
#if defined(DUK_USE_ARRAY_FASTPATH)
	duk_harray *h_arr;
#endif

	DUK_ASSERT_TOP(thr, 0);

#if defined(DUK_USE_ARRAY_FASTPATH)
	h_arr = duk__arraypart_fastpath_this(thr);
	if (h_arr) {
		return duk__array_pop_fastpath(thr, h_arr);
	}
#endif

	/* XXX: Merge fastpath check into a related call (push this, coerce length, etc)? */

	len = duk__push_this_obj_len_u32(thr);
	if (len == 0) {
		duk_push_int(thr, 0);
		duk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LENGTH);
		return 0;
	}
	idx = len - 1;

	duk_get_prop_index(thr, 0, (duk_uarridx_t) idx);
	duk_del_prop_index(thr, 0, (duk_uarridx_t) idx);
	duk_push_u32(thr, idx);
	duk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LENGTH);
	return 1;
}

#if defined(DUK_USE_ARRAY_FASTPATH)
DUK_LOCAL duk_ret_t duk__array_push_fastpath(duk_hthread *thr, duk_harray *h_arr) {
	duk_tval *tv_arraypart;
	duk_tval *tv_src;
	duk_tval *tv_dst;
	duk_uint32_t len;
	duk_idx_t i, n;

	len = h_arr->length;
	tv_arraypart = DUK_HOBJECT_A_GET_BASE(thr->heap, (duk_hobject *) h_arr);

	n = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
	DUK_ASSERT(n >= 0);
	DUK_ASSERT((duk_uint32_t) n <= DUK_UINT32_MAX);
	if (DUK_UNLIKELY(len + (duk_uint32_t) n < len)) {
		DUK_D(DUK_DPRINT("Array.prototype.push() would go beyond 32-bit length, throw"));
		DUK_DCERROR_RANGE_INVALID_LENGTH(thr);  /* != 0 return value returned as is by caller */
	}
	if (len + (duk_uint32_t) n > DUK_HOBJECT_GET_ASIZE((duk_hobject *) h_arr)) {
		/* Array part would need to be extended.  Rely on slow path
		 * for now.
		 *
		 * XXX: Rework hobject code a bit and add extend support.
		 */
		return 0;
	}

	tv_src = thr->valstack_bottom;
	tv_dst = tv_arraypart + len;
	for (i = 0; i < n; i++) {
		/* No net refcount change; reset value stack values to
		 * undefined to satisfy value stack init policy.
		 */
		DUK_TVAL_SET_TVAL(tv_dst, tv_src);
		DUK_TVAL_SET_UNDEFINED(tv_src);
		tv_src++;
		tv_dst++;
	}
	thr->valstack_top = thr->valstack_bottom;
	len += (duk_uint32_t) n;
	h_arr->length = len;

	DUK_ASSERT((duk_uint_t) len == len);
	duk_push_uint(thr, (duk_uint_t) len);
	return 1;
}
#endif  /* DUK_USE_ARRAY_FASTPATH */

DUK_INTERNAL duk_ret_t duk_bi_array_prototype_push(duk_hthread *thr) {
	/* Note: 'this' is not necessarily an Array object.  The push()
	 * algorithm is supposed to work for other kinds of objects too,
	 * so the algorithm has e.g. an explicit update for the 'length'
	 * property which is normally "magical" in arrays.
	 */

	duk_uint32_t len;
	duk_idx_t i, n;
#if defined(DUK_USE_ARRAY_FASTPATH)
	duk_harray *h_arr;
#endif

#if defined(DUK_USE_ARRAY_FASTPATH)
	h_arr = duk__arraypart_fastpath_this(thr);
	if (h_arr) {
		duk_ret_t rc;
		rc = duk__array_push_fastpath(thr, h_arr);
		if (rc != 0) {
			return rc;
		}
		DUK_DD(DUK_DDPRINT("array push() fast path exited, resize case"));
	}
#endif

	n = duk_get_top(thr);
	len = duk__push_this_obj_len_u32(thr);

	/* [ arg1 ... argN obj length ] */

	/* Technically Array.prototype.push() can create an Array with length
	 * longer than 2^32-1, i.e. outside the 32-bit range.  The final length
	 * is *not* wrapped to 32 bits in the specification.
	 *
	 * This implementation tracks length with a uint32 because it's much
	 * more practical.
	 *
	 * See: test-bi-array-push-maxlen.js.
	 */

	if (len + (duk_uint32_t) n < len) {
		DUK_D(DUK_DPRINT("Array.prototype.push() would go beyond 32-bit length, throw"));
		DUK_DCERROR_RANGE_INVALID_LENGTH(thr);
	}

	for (i = 0; i < n; i++) {
		duk_dup(thr, i);
		duk_put_prop_index(thr, -3, (duk_uarridx_t) (len + (duk_uint32_t) i));
	}
	len += (duk_uint32_t) n;

	duk_push_u32(thr, len);
	duk_dup_top(thr);
	duk_put_prop_stridx_short(thr, -4, DUK_STRIDX_LENGTH);

	/* [ arg1 ... argN obj length new_length ] */
	return 1;
}

/*
 *  sort()
 *
 *  Currently qsort with random pivot.  This is now really, really slow,
 *  because there is no fast path for array parts.
 *
 *  Signed indices are used because qsort() leaves and degenerate cases
 *  may use a negative offset.
 */

DUK_LOCAL duk_small_int_t duk__array_sort_compare(duk_hthread *thr, duk_int_t idx1, duk_int_t idx2) {
	duk_bool_t have1, have2;
	duk_bool_t undef1, undef2;
	duk_small_int_t ret;
	duk_idx_t idx_obj = 1;  /* fixed offsets in valstack */
	duk_idx_t idx_fn = 0;
	duk_hstring *h1, *h2;

	/* Fast exit if indices are identical.  This is valid for a non-existent property,
	 * for an undefined value, and almost always for ToString() coerced comparison of
	 * arbitrary values (corner cases where this is not the case include e.g. a an
	 * object with varying ToString() coercion).
	 *
	 * The specification does not prohibit "caching" of values read from the array, so
	 * assuming equality for comparing an index with itself falls into the category of
	 * "caching".
	 *
	 * Also, compareFn may be inconsistent, so skipping a call to compareFn here may
	 * have an effect on the final result.  The specification does not require any
	 * specific behavior for inconsistent compare functions, so again, this fast path
	 * is OK.
	 */

	if (idx1 == idx2) {
		DUK_DDD(DUK_DDDPRINT("duk__array_sort_compare: idx1=%ld, idx2=%ld -> indices identical, quick exit",
		                     (long) idx1, (long) idx2));
		return 0;
	}

	have1 = duk_get_prop_index(thr, idx_obj, (duk_uarridx_t) idx1);
	have2 = duk_get_prop_index(thr, idx_obj, (duk_uarridx_t) idx2);

	DUK_DDD(DUK_DDDPRINT("duk__array_sort_compare: idx1=%ld, idx2=%ld, have1=%ld, have2=%ld, val1=%!T, val2=%!T",
	                     (long) idx1, (long) idx2, (long) have1, (long) have2,
	                     (duk_tval *) duk_get_tval(thr, -2), (duk_tval *) duk_get_tval(thr, -1)));

	if (have1) {
		if (have2) {
			;
		} else {
			ret = -1;
			goto pop_ret;
		}
	} else {
		if (have2) {
			ret = 1;
			goto pop_ret;
		} else {
			ret = 0;
			goto pop_ret;
		}
	}

	undef1 = duk_is_undefined(thr, -2);
	undef2 = duk_is_undefined(thr, -1);
	if (undef1) {
		if (undef2) {
			ret = 0;
			goto pop_ret;
		} else {
			ret = 1;
			goto pop_ret;
		}
	} else {
		if (undef2) {
			ret = -1;
			goto pop_ret;
		} else {
			;
		}
	}

	if (!duk_is_undefined(thr, idx_fn)) {
		duk_double_t d;

		/* No need to check callable; duk_call() will do that. */
		duk_dup(thr, idx_fn);    /* -> [ ... x y fn ] */
		duk_insert(thr, -3);     /* -> [ ... fn x y ] */
		duk_call(thr, 2);        /* -> [ ... res ] */

		/* ES5 is a bit vague about what to do if the return value is
		 * not a number.  ES2015 provides a concrete description:
		 * http://www.ecma-international.org/ecma-262/6.0/#sec-sortcompare.
		 */

		d = duk_to_number_m1(thr);
		if (d < 0.0) {
			ret = -1;
		} else if (d > 0.0) {
			ret = 1;
		} else {
			/* Because NaN compares to false, NaN is handled here
			 * without an explicit check above.
			 */
			ret = 0;
		}

		duk_pop_nodecref_unsafe(thr);
		DUK_DDD(DUK_DDDPRINT("-> result %ld (from comparefn, after coercion)", (long) ret));
		return ret;
	}

	/* string compare is the default (a bit oddly) */

	/* XXX: any special handling for plain array; causes repeated coercion now? */
	h1 = duk_to_hstring(thr, -2);
	h2 = duk_to_hstring_m1(thr);
	DUK_ASSERT(h1 != NULL);
	DUK_ASSERT(h2 != NULL);

	ret = duk_js_string_compare(h1, h2);  /* retval is directly usable */
	goto pop_ret;

 pop_ret:
	duk_pop_2_unsafe(thr);
	DUK_DDD(DUK_DDDPRINT("-> result %ld", (long) ret));
	return ret;
}

DUK_LOCAL void duk__array_sort_swap(duk_hthread *thr, duk_int_t l, duk_int_t r) {
	duk_bool_t have_l, have_r;
	duk_idx_t idx_obj = 1;  /* fixed offset in valstack */

	if (l == r) {
		return;
	}

	/* swap elements; deal with non-existent elements correctly */
	have_l = duk_get_prop_index(thr, idx_obj, (duk_uarridx_t) l);
	have_r = duk_get_prop_index(thr, idx_obj, (duk_uarridx_t) r);

	if (have_r) {
		/* right exists, [[Put]] regardless whether or not left exists */
		duk_put_prop_index(thr, idx_obj, (duk_uarridx_t) l);
	} else {
		duk_del_prop_index(thr, idx_obj, (duk_uarridx_t) l);
		duk_pop_undefined(thr);
	}

	if (have_l) {
		duk_put_prop_index(thr, idx_obj, (duk_uarridx_t) r);
	} else {
		duk_del_prop_index(thr, idx_obj, (duk_uarridx_t) r);
		duk_pop_undefined(thr);
	}
}

#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
/* Debug print which visualizes the qsort partitioning process. */
DUK_LOCAL void duk__debuglog_qsort_state(duk_hthread *thr, duk_int_t lo, duk_int_t hi, duk_int_t pivot) {
	char buf[4096];
	char *ptr = buf;
	duk_int_t i, n;
	n = (duk_int_t) duk_get_length(thr, 1);
	if (n > 4000) {
		n = 4000;
	}
	*ptr++ = '[';
	for (i = 0; i < n; i++) {
		if (i == pivot) {
			*ptr++ = '|';
		} else if (i == lo) {
			*ptr++ = '<';
		} else if (i == hi) {
			*ptr++ = '>';
		} else if (i >= lo && i <= hi) {
			*ptr++ = '-';
		} else {
			*ptr++ = ' ';
		}
	}
	*ptr++ = ']';
	*ptr++ = '\0';

	DUK_DDD(DUK_DDDPRINT("%s   (lo=%ld, hi=%ld, pivot=%ld)",
	                     (const char *) buf, (long) lo, (long) hi, (long) pivot));
}
#endif

DUK_LOCAL void duk__array_qsort(duk_hthread *thr, duk_int_t lo, duk_int_t hi) {
	duk_int_t p, l, r;

	/* The lo/hi indices may be crossed and hi < 0 is possible at entry. */

	DUK_DDD(DUK_DDDPRINT("duk__array_qsort: lo=%ld, hi=%ld, obj=%!T",
	                     (long) lo, (long) hi, (duk_tval *) duk_get_tval(thr, 1)));

	DUK_ASSERT_TOP(thr, 3);

	/* In some cases it may be that lo > hi, or hi < 0; these
	 * degenerate cases happen e.g. for empty arrays, and in
	 * recursion leaves.
	 */

	/* trivial cases */
	if (hi - lo < 1) {
		DUK_DDD(DUK_DDDPRINT("degenerate case, return immediately"));
		return;
	}
	DUK_ASSERT(hi > lo);
	DUK_ASSERT(hi - lo + 1 >= 2);

	/* randomized pivot selection */
	p = lo + (duk_int_t) (DUK_UTIL_GET_RANDOM_DOUBLE(thr) * (duk_double_t) (hi - lo + 1));
	DUK_ASSERT(p >= lo && p <= hi);
	DUK_DDD(DUK_DDDPRINT("lo=%ld, hi=%ld, chose pivot p=%ld", (long) lo, (long) hi, (long) p));

	/* move pivot out of the way */
	duk__array_sort_swap(thr, p, lo);
	p = lo;
	DUK_DDD(DUK_DDDPRINT("pivot moved out of the way: %!T", (duk_tval *) duk_get_tval(thr, 1)));

	l = lo + 1;
	r = hi;
	for (;;) {
		/* find elements to swap */
		for (;;) {
			DUK_DDD(DUK_DDDPRINT("left scan: l=%ld, r=%ld, p=%ld",
			                     (long) l, (long) r, (long) p));
			if (l >= hi) {
				break;
			}
			if (duk__array_sort_compare(thr, l, p) >= 0) {  /* !(l < p) */
				break;
			}
			l++;
		}
		for (;;) {
			DUK_DDD(DUK_DDDPRINT("right scan: l=%ld, r=%ld, p=%ld",
			                     (long) l, (long) r, (long) p));
			if (r <= lo) {
				break;
			}
			if (duk__array_sort_compare(thr, p, r) >= 0) {  /* !(p < r) */
				break;
			}
			r--;
		}
		if (l >= r) {
			goto done;
		}
		DUK_ASSERT(l < r);

		DUK_DDD(DUK_DDDPRINT("swap %ld and %ld", (long) l, (long) r));

		duk__array_sort_swap(thr, l, r);

		DUK_DDD(DUK_DDDPRINT("after swap: %!T", (duk_tval *) duk_get_tval(thr, 1)));
		l++;
		r--;
	}
 done:
	/* Note that 'l' and 'r' may cross, i.e. r < l */
	DUK_ASSERT(l >= lo && l <= hi);
	DUK_ASSERT(r >= lo && r <= hi);

	/* XXX: there's no explicit recursion bound here now.  For the average
	 * qsort recursion depth O(log n) that's not really necessary: e.g. for
	 * 2**32 recursion depth would be about 32 which is OK.  However, qsort
	 * worst case recursion depth is O(n) which may be a problem.
	 */

	/* move pivot to its final place */
	DUK_DDD(DUK_DDDPRINT("before final pivot swap: %!T", (duk_tval *) duk_get_tval(thr, 1)));
	duk__array_sort_swap(thr, lo, r);

#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
	duk__debuglog_qsort_state(thr, lo, hi, r);
#endif

	DUK_DDD(DUK_DDDPRINT("recurse: pivot=%ld, obj=%!T", (long) r, (duk_tval *) duk_get_tval(thr, 1)));
	duk__array_qsort(thr, lo, r - 1);
	duk__array_qsort(thr, r + 1, hi);
}

DUK_INTERNAL duk_ret_t duk_bi_array_prototype_sort(duk_hthread *thr) {
	duk_uint32_t len;

	/* XXX: len >= 0x80000000 won't work below because a signed type
	 * is needed by qsort.
	 */
	len = duk__push_this_obj_len_u32_limited(thr);

	/* stack[0] = compareFn
	 * stack[1] = ToObject(this)
	 * stack[2] = ToUint32(length)
	 */

	if (len > 0) {
		/* avoid degenerate cases, so that (len - 1) won't underflow */
		duk__array_qsort(thr, (duk_int_t) 0, (duk_int_t) (len - 1));
	}

	DUK_ASSERT_TOP(thr, 3);
	duk_pop_nodecref_unsafe(thr);
	return 1;  /* return ToObject(this) */
}

/*
 *  splice()
 */

/* XXX: this compiles to over 500 bytes now, even without special handling
 * for an array part.  Uses signed ints so does not handle full array range correctly.
 */

/* XXX: can shift() / unshift() use the same helper?
 *   shift() is (close to?) <--> splice(0, 1)
 *   unshift is (close to?) <--> splice(0, 0, [items])?
 */

DUK_INTERNAL duk_ret_t duk_bi_array_prototype_splice(duk_hthread *thr) {
	duk_idx_t nargs;
	duk_uint32_t len_u32;
	duk_int_t len;
	duk_bool_t have_delcount;
	duk_int_t item_count;
	duk_int_t act_start;
	duk_int_t del_count;
	duk_int_t i, n;

	DUK_UNREF(have_delcount);

	nargs = duk_get_top(thr);
	if (nargs < 2) {
		duk_set_top(thr, 2);
		nargs = 2;
		have_delcount = 0;
	} else {
		have_delcount = 1;
	}

	/* XXX: len >= 0x80000000 won't work below because we need to be
	 * able to represent -len.
	 */
	len_u32 = duk__push_this_obj_len_u32_limited(thr);
	len = (duk_int_t) len_u32;
	DUK_ASSERT(len >= 0);

	act_start = duk_to_int_clamped(thr, 0, -len, len);
	if (act_start < 0) {
		act_start = len + act_start;
	}
	DUK_ASSERT(act_start >= 0 && act_start <= len);

#if defined(DUK_USE_NONSTD_ARRAY_SPLICE_DELCOUNT)
	if (have_delcount) {
#endif
		del_count = duk_to_int_clamped(thr, 1, 0, len - act_start);
#if defined(DUK_USE_NONSTD_ARRAY_SPLICE_DELCOUNT)
	} else {
		/* E5.1 standard behavior when deleteCount is not given would be
		 * to treat it just like if 'undefined' was given, which coerces
		 * ultimately to 0.  Real world behavior is to splice to the end
		 * of array, see test-bi-array-proto-splice-no-delcount.js.
		 */
		del_count = len - act_start;
	}
#endif

	DUK_ASSERT(nargs >= 2);
	item_count = (duk_int_t) (nargs - 2);

	DUK_ASSERT(del_count >= 0 && del_count <= len - act_start);
	DUK_ASSERT(del_count + act_start <= len);

	/* For now, restrict result array into 32-bit length range. */
	if (((duk_double_t) len) - ((duk_double_t) del_count) + ((duk_double_t) item_count) > (duk_double_t) DUK_UINT32_MAX) {
		DUK_D(DUK_DPRINT("Array.prototype.splice() would go beyond 32-bit length, throw"));
		DUK_DCERROR_RANGE_INVALID_LENGTH(thr);
	}

	duk_push_array(thr);

	/* stack[0] = start
	 * stack[1] = deleteCount
	 * stack[2...nargs-1] = items
	 * stack[nargs] = ToObject(this)               -3
	 * stack[nargs+1] = ToUint32(length)           -2
	 * stack[nargs+2] = result array               -1
	 */

	DUK_ASSERT_TOP(thr, nargs + 3);

	/* Step 9: copy elements-to-be-deleted into the result array */

	for (i = 0; i < del_count; i++) {
		if (duk_get_prop_index(thr, -3, (duk_uarridx_t) (act_start + i))) {
			duk_xdef_prop_index_wec(thr, -2, (duk_uarridx_t) i);  /* throw flag irrelevant (false in std alg) */
		} else {
			duk_pop_undefined(thr);
		}
	}
	duk_push_u32(thr, (duk_uint32_t) del_count);
	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W);

	/* Steps 12 and 13: reorganize elements to make room for itemCount elements */

	if (item_count < del_count) {
		/*    [ A B C D E F G H ]    rel_index = 2, del_count 3, item count 1
		 * -> [ A B F G H ]          (conceptual intermediate step)
		 * -> [ A B . F G H ]        (placeholder marked)
		 *    [ A B C F G H ]        (actual result at this point, C will be replaced)
		 */

		DUK_ASSERT_TOP(thr, nargs + 3);

		n = len - del_count;
		for (i = act_start; i < n; i++) {
			if (duk_get_prop_index(thr, -3, (duk_uarridx_t) (i + del_count))) {
				duk_put_prop_index(thr, -4, (duk_uarridx_t) (i + item_count));
			} else {
				duk_pop_undefined(thr);
				duk_del_prop_index(thr, -3, (duk_uarridx_t) (i + item_count));
			}
		}

		DUK_ASSERT_TOP(thr, nargs + 3);

		/* loop iterator init and limit changed from standard algorithm */
		n = len - del_count + item_count;
		for (i = len - 1; i >= n; i--) {
			duk_del_prop_index(thr, -3, (duk_uarridx_t) i);
		}

		DUK_ASSERT_TOP(thr, nargs + 3);
	} else if (item_count > del_count) {
		/*    [ A B C D E F G H ]    rel_index = 2, del_count 3, item count 4
		 * -> [ A B F G H ]          (conceptual intermediate step)
		 * -> [ A B . . . . F G H ]  (placeholder marked)
		 *    [ A B C D E F F G H ]  (actual result at this point)
		 */

		DUK_ASSERT_TOP(thr, nargs + 3);

		/* loop iterator init and limit changed from standard algorithm */
		for (i = len - del_count - 1; i >= act_start; i--) {
			if (duk_get_prop_index(thr, -3, (duk_uarridx_t) (i + del_count))) {
				duk_put_prop_index(thr, -4, (duk_uarridx_t) (i + item_count));
			} else {
				duk_pop_undefined(thr);
				duk_del_prop_index(thr, -3, (duk_uarridx_t) (i + item_count));
			}
		}

		DUK_ASSERT_TOP(thr, nargs + 3);
	} else {
		/*    [ A B C D E F G H ]    rel_index = 2, del_count 3, item count 3
		 * -> [ A B F G H ]          (conceptual intermediate step)
		 * -> [ A B . . . F G H ]    (placeholder marked)
		 *    [ A B C D E F G H ]    (actual result at this point)
		 */
	}
	DUK_ASSERT_TOP(thr, nargs + 3);

	/* Step 15: insert itemCount elements into the hole made above */

	for (i = 0; i < item_count; i++) {
		duk_dup(thr, i + 2);  /* args start at index 2 */
		duk_put_prop_index(thr, -4, (duk_uarridx_t) (act_start + i));
	}

	/* Step 16: update length; note that the final length may be above 32 bit range
	 * (but we checked above that this isn't the case here)
	 */

	duk_push_u32(thr, (duk_uint32_t) (len - del_count + item_count));
	duk_put_prop_stridx_short(thr, -4, DUK_STRIDX_LENGTH);

	/* result array is already at the top of stack */
	DUK_ASSERT_TOP(thr, nargs + 3);
	return 1;
}

/*
 *  reverse()
 */

DUK_INTERNAL duk_ret_t duk_bi_array_prototype_reverse(duk_hthread *thr) {
	duk_uint32_t len;
	duk_uint32_t middle;
	duk_uint32_t lower, upper;
	duk_bool_t have_lower, have_upper;

	len = duk__push_this_obj_len_u32(thr);
	middle = len / 2;

	/* If len <= 1, middle will be 0 and for-loop bails out
	 * immediately (0 < 0 -> false).
	 */

	for (lower = 0; lower < middle; lower++) {
		DUK_ASSERT(len >= 2);
		DUK_ASSERT_TOP(thr, 2);

		DUK_ASSERT(len >= lower + 1);
		upper = len - lower - 1;

		have_lower = duk_get_prop_index(thr, -2, (duk_uarridx_t) lower);
		have_upper = duk_get_prop_index(thr, -3, (duk_uarridx_t) upper);

		/* [ ToObject(this) ToUint32(length) lowerValue upperValue ] */

		if (have_upper) {
			duk_put_prop_index(thr, -4, (duk_uarridx_t) lower);
		} else {
			duk_del_prop_index(thr, -4, (duk_uarridx_t) lower);
			duk_pop_undefined(thr);
		}

		if (have_lower) {
			duk_put_prop_index(thr, -3, (duk_uarridx_t) upper);
		} else {
			duk_del_prop_index(thr, -3, (duk_uarridx_t) upper);
			duk_pop_undefined(thr);
		}

		DUK_ASSERT_TOP(thr, 2);
	}

	DUK_ASSERT_TOP(thr, 2);
	duk_pop_unsafe(thr);  /* -> [ ToObject(this) ] */
	return 1;
}

/*
 *  slice()
 */

DUK_INTERNAL duk_ret_t duk_bi_array_prototype_slice(duk_hthread *thr) {
	duk_uint32_t len_u32;
	duk_int_t len;
	duk_int_t start, end;
	duk_int_t i;
	duk_uarridx_t idx;
	duk_uint32_t res_length = 0;

	/* XXX: len >= 0x80000000 won't work below because we need to be
	 * able to represent -len.
	 */
	len_u32 = duk__push_this_obj_len_u32_limited(thr);
	len = (duk_int_t) len_u32;
	DUK_ASSERT(len >= 0);

	duk_push_array(thr);

	/* stack[0] = start
	 * stack[1] = end
	 * stack[2] = ToObject(this)
	 * stack[3] = ToUint32(length)
	 * stack[4] = result array
	 */

	start = duk_to_int_clamped(thr, 0, -len, len);
	if (start < 0) {
		start = len + start;
	}
	/* XXX: could duk_is_undefined() provide defaulting undefined to 'len'
	 * (the upper limit)?
	 */
	if (duk_is_undefined(thr, 1)) {
		end = len;
	} else {
		end = duk_to_int_clamped(thr, 1, -len, len);
		if (end < 0) {
			end = len + end;
		}
	}
	DUK_ASSERT(start >= 0 && start <= len);
	DUK_ASSERT(end >= 0 && end <= len);

	idx = 0;
	for (i = start; i < end; i++) {
		DUK_ASSERT_TOP(thr, 5);
		if (duk_get_prop_index(thr, 2, (duk_uarridx_t) i)) {
			duk_xdef_prop_index_wec(thr, 4, idx);
			res_length = idx + 1;
		} else {
			duk_pop_undefined(thr);
		}
		idx++;
		DUK_ASSERT_TOP(thr, 5);
	}

	duk_push_u32(thr, res_length);
	duk_xdef_prop_stridx_short(thr, 4, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W);

	DUK_ASSERT_TOP(thr, 5);
	return 1;
}

/*
 *  shift()
 */

DUK_INTERNAL duk_ret_t duk_bi_array_prototype_shift(duk_hthread *thr) {
	duk_uint32_t len;
	duk_uint32_t i;

	len = duk__push_this_obj_len_u32(thr);
	if (len == 0) {
		duk_push_int(thr, 0);
		duk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LENGTH);
		return 0;
	}

	duk_get_prop_index(thr, 0, 0);

	/* stack[0] = object (this)
	 * stack[1] = ToUint32(length)
	 * stack[2] = elem at index 0 (retval)
	 */

	for (i = 1; i < len; i++) {
		DUK_ASSERT_TOP(thr, 3);
		if (duk_get_prop_index(thr, 0, (duk_uarridx_t) i)) {
			/* fromPresent = true */
			duk_put_prop_index(thr, 0, (duk_uarridx_t) (i - 1));
		} else {
			/* fromPresent = false */
			duk_del_prop_index(thr, 0, (duk_uarridx_t) (i - 1));
			duk_pop_undefined(thr);
		}
	}
	duk_del_prop_index(thr, 0, (duk_uarridx_t) (len - 1));

	duk_push_u32(thr, (duk_uint32_t) (len - 1));
	duk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LENGTH);

	DUK_ASSERT_TOP(thr, 3);
	return 1;
}

/*
 *  unshift()
 */

DUK_INTERNAL duk_ret_t duk_bi_array_prototype_unshift(duk_hthread *thr) {
	duk_idx_t nargs;
	duk_uint32_t len;
	duk_uint32_t i;

	nargs = duk_get_top(thr);
	len = duk__push_this_obj_len_u32(thr);

	/* stack[0...nargs-1] = unshift args (vararg)
	 * stack[nargs] = ToObject(this)
	 * stack[nargs+1] = ToUint32(length)
	 */

	DUK_ASSERT_TOP(thr, nargs + 2);

	/* Note: unshift() may operate on indices above unsigned 32-bit range
	 * and the final length may be >= 2**32.  However, we restrict the
	 * final result to 32-bit range for practicality.
	 */

	if (len + (duk_uint32_t) nargs < len) {
		DUK_D(DUK_DPRINT("Array.prototype.unshift() would go beyond 32-bit length, throw"));
		DUK_DCERROR_RANGE_INVALID_LENGTH(thr);
	}

	i = len;
	while (i > 0) {
		DUK_ASSERT_TOP(thr, nargs + 2);
		i--;
		/* k+argCount-1; note that may be above 32-bit range */

		if (duk_get_prop_index(thr, -2, (duk_uarridx_t) i)) {
			/* fromPresent = true */
			/* [ ... ToObject(this) ToUint32(length) val ] */
			duk_put_prop_index(thr, -3, (duk_uarridx_t) (i + (duk_uint32_t) nargs));  /* -> [ ... ToObject(this) ToUint32(length) ] */
		} else {
			/* fromPresent = false */
			/* [ ... ToObject(this) ToUint32(length) val ] */
			duk_pop_undefined(thr);
			duk_del_prop_index(thr, -2, (duk_uarridx_t) (i + (duk_uint32_t) nargs));  /* -> [ ... ToObject(this) ToUint32(length) ] */
		}
		DUK_ASSERT_TOP(thr, nargs + 2);
	}

	for (i = 0; i < (duk_uint32_t) nargs; i++) {
		DUK_ASSERT_TOP(thr, nargs + 2);
		duk_dup(thr, (duk_idx_t) i);  /* -> [ ... ToObject(this) ToUint32(length) arg[i] ] */
		duk_put_prop_index(thr, -3, (duk_uarridx_t) i);
		DUK_ASSERT_TOP(thr, nargs + 2);
	}

	DUK_ASSERT_TOP(thr, nargs + 2);
	duk_push_u32(thr, len + (duk_uint32_t) nargs);
	duk_dup_top(thr);  /* -> [ ... ToObject(this) ToUint32(length) final_len final_len ] */
	duk_put_prop_stridx_short(thr, -4, DUK_STRIDX_LENGTH);
	return 1;
}

/*
 *  indexOf(), lastIndexOf()
 */

DUK_INTERNAL duk_ret_t duk_bi_array_prototype_indexof_shared(duk_hthread *thr) {
	duk_idx_t nargs;
	duk_int_t i, len;
	duk_int_t from_idx;
	duk_small_int_t idx_step = duk_get_current_magic(thr);  /* idx_step is +1 for indexOf, -1 for lastIndexOf */

	/* lastIndexOf() needs to be a vararg function because we must distinguish
	 * between an undefined fromIndex and a "not given" fromIndex; indexOf() is
	 * made vararg for symmetry although it doesn't strictly need to be.
	 */

	nargs = duk_get_top(thr);
	duk_set_top(thr, 2);

	/* XXX: must be able to represent -len */
	len = (duk_int_t) duk__push_this_obj_len_u32_limited(thr);
	if (len == 0) {
		goto not_found;
	}

	/* Index clamping is a bit tricky, we must ensure that we'll only iterate
	 * through elements that exist and that the specific requirements from E5.1
	 * Sections 15.4.4.14 and 15.4.4.15 are fulfilled; especially:
	 *
	 *   - indexOf: clamp to [-len,len], negative handling -> [0,len],
	 *     if clamped result is len, for-loop bails out immediately
	 *
	 *   - lastIndexOf: clamp to [-len-1, len-1], negative handling -> [-1, len-1],
	 *     if clamped result is -1, for-loop bails out immediately
	 *
	 * If fromIndex is not given, ToInteger(undefined) = 0, which is correct
	 * for indexOf() but incorrect for lastIndexOf().  Hence special handling,
	 * and why lastIndexOf() needs to be a vararg function.
	 */

	if (nargs >= 2) {
		/* indexOf: clamp fromIndex to [-len, len]
		 * (if fromIndex == len, for-loop terminates directly)
		 *
		 * lastIndexOf: clamp fromIndex to [-len - 1, len - 1]
		 * (if clamped to -len-1 -> fromIndex becomes -1, terminates for-loop directly)
		 */
		from_idx = duk_to_int_clamped(thr,
		                              1,
		                              (idx_step > 0 ? -len : -len - 1),
		                              (idx_step > 0 ? len : len - 1));
		if (from_idx < 0) {
			/* for lastIndexOf, result may be -1 (mark immediate termination) */
			from_idx = len + from_idx;
		}
	} else {
		/* for indexOf, ToInteger(undefined) would be 0, i.e. correct, but
		 * handle both indexOf and lastIndexOf specially here.
		 */
		if (idx_step > 0) {
			from_idx = 0;
		} else {
			from_idx = len - 1;
		}
	}

	/* stack[0] = searchElement
	 * stack[1] = fromIndex
	 * stack[2] = object
	 * stack[3] = length (not needed, but not popped above)
	 */

	for (i = from_idx; i >= 0 && i < len; i += idx_step) {
		DUK_ASSERT_TOP(thr, 4);

		if (duk_get_prop_index(thr, 2, (duk_uarridx_t) i)) {
			DUK_ASSERT_TOP(thr, 5);
			if (duk_strict_equals(thr, 0, 4)) {
				duk_push_int(thr, i);
				return 1;
			}
		}

		duk_pop_unsafe(thr);
	}

 not_found:
	duk_push_int(thr, -1);
	return 1;
}

/*
 *  every(), some(), forEach(), map(), filter()
 */

#define DUK__ITER_EVERY    0
#define DUK__ITER_SOME     1
#define DUK__ITER_FOREACH  2
#define DUK__ITER_MAP      3
#define DUK__ITER_FILTER   4

/* XXX: This helper is a bit awkward because the handling for the different iteration
 * callers is quite different.  This now compiles to a bit less than 500 bytes, so with
 * 5 callers the net result is about 100 bytes / caller.
 */

DUK_INTERNAL duk_ret_t duk_bi_array_prototype_iter_shared(duk_hthread *thr) {
	duk_uint32_t len;
	duk_uint32_t i;
	duk_uarridx_t k;
	duk_bool_t bval;
	duk_small_int_t iter_type = duk_get_current_magic(thr);
	duk_uint32_t res_length = 0;

	/* each call this helper serves has nargs==2 */
	DUK_ASSERT_TOP(thr, 2);

	len = duk__push_this_obj_len_u32(thr);
	duk_require_callable(thr, 0);
	/* if thisArg not supplied, behave as if undefined was supplied */

	if (iter_type == DUK__ITER_MAP || iter_type == DUK__ITER_FILTER) {
		duk_push_array(thr);
	} else {
		duk_push_undefined(thr);
	}

	/* stack[0] = callback
	 * stack[1] = thisArg
	 * stack[2] = object
	 * stack[3] = ToUint32(length)  (unused, but avoid unnecessary pop)
	 * stack[4] = result array (or undefined)
	 */

	k = 0;  /* result index for filter() */
	for (i = 0; i < len; i++) {
		DUK_ASSERT_TOP(thr, 5);

		if (!duk_get_prop_index(thr, 2, (duk_uarridx_t) i)) {
			/* For 'map' trailing missing elements don't invoke the
			 * callback but count towards the result length.
			 */
			if (iter_type == DUK__ITER_MAP) {
				res_length = i + 1;
			}
			duk_pop_undefined(thr);
			continue;
		}

		/* The original value needs to be preserved for filter(), hence
		 * this funny order.  We can't re-get the value because of side
		 * effects.
		 */

		duk_dup_0(thr);
		duk_dup_1(thr);
		duk_dup_m3(thr);
		duk_push_u32(thr, i);
		duk_dup_2(thr);  /* [ ... val callback thisArg val i obj ] */
		duk_call_method(thr, 3); /* -> [ ... val retval ] */

		switch (iter_type) {
		case DUK__ITER_EVERY:
			bval = duk_to_boolean(thr, -1);
			if (!bval) {
				/* stack top contains 'false' */
				return 1;
			}
			break;
		case DUK__ITER_SOME:
			bval = duk_to_boolean(thr, -1);
			if (bval) {
				/* stack top contains 'true' */
				return 1;
			}
			break;
		case DUK__ITER_FOREACH:
			/* nop */
			break;
		case DUK__ITER_MAP:
			duk_dup_top(thr);
			duk_xdef_prop_index_wec(thr, 4, (duk_uarridx_t) i);  /* retval to result[i] */
			res_length = i + 1;
			break;
		case DUK__ITER_FILTER:
			bval = duk_to_boolean(thr, -1);
			if (bval) {
				duk_dup_m2(thr);  /* orig value */
				duk_xdef_prop_index_wec(thr, 4, (duk_uarridx_t) k);
				k++;
				res_length = k;
			}
			break;
		default:
			DUK_UNREACHABLE();
			break;
		}
		duk_pop_2_unsafe(thr);

		DUK_ASSERT_TOP(thr, 5);
	}

	switch (iter_type) {
	case DUK__ITER_EVERY:
		duk_push_true(thr);
		break;
	case DUK__ITER_SOME:
		duk_push_false(thr);
		break;
	case DUK__ITER_FOREACH:
		duk_push_undefined(thr);
		break;
	case DUK__ITER_MAP:
	case DUK__ITER_FILTER:
		DUK_ASSERT_TOP(thr, 5);
		DUK_ASSERT(duk_is_array(thr, -1));  /* topmost element is the result array already */
		duk_push_u32(thr, res_length);
		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W);
		break;
	default:
		DUK_UNREACHABLE();
		break;
	}

	return 1;
}

/*
 *  reduce(), reduceRight()
 */

DUK_INTERNAL duk_ret_t duk_bi_array_prototype_reduce_shared(duk_hthread *thr) {
	duk_idx_t nargs;
	duk_bool_t have_acc;
	duk_uint32_t i, len;
	duk_small_int_t idx_step = duk_get_current_magic(thr);  /* idx_step is +1 for reduce, -1 for reduceRight */

	/* We're a varargs function because we need to detect whether
	 * initialValue was given or not.
	 */
	nargs = duk_get_top(thr);
	DUK_DDD(DUK_DDDPRINT("nargs=%ld", (long) nargs));

	duk_set_top(thr, 2);
	len = duk__push_this_obj_len_u32(thr);
	duk_require_callable(thr, 0);

	/* stack[0] = callback fn
	 * stack[1] = initialValue
	 * stack[2] = object (coerced this)
	 * stack[3] = length (not needed, but not popped above)
	 * stack[4] = accumulator
	 */

	have_acc = 0;
	if (nargs >= 2) {
		duk_dup_1(thr);
		have_acc = 1;
	}
	DUK_DDD(DUK_DDDPRINT("have_acc=%ld, acc=%!T",
	                     (long) have_acc, (duk_tval *) duk_get_tval(thr, 3)));

	/* For len == 0, i is initialized to len - 1 which underflows.
	 * The condition (i < len) will then exit the for-loop on the
	 * first round which is correct.  Similarly, loop termination
	 * happens by i underflowing.
	 */

	for (i = (idx_step >= 0 ? 0 : len - 1);
	     i < len;  /* i >= 0 would always be true */
	     i += (duk_uint32_t) idx_step) {
		DUK_DDD(DUK_DDDPRINT("i=%ld, len=%ld, have_acc=%ld, top=%ld, acc=%!T",
		                     (long) i, (long) len, (long) have_acc,
		                     (long) duk_get_top(thr),
		                     (duk_tval *) duk_get_tval(thr, 4)));

		DUK_ASSERT((have_acc && duk_get_top(thr) == 5) ||
		           (!have_acc && duk_get_top(thr) == 4));

		if (!duk_has_prop_index(thr, 2, (duk_uarridx_t) i)) {
			continue;
		}

		if (!have_acc) {
			DUK_ASSERT_TOP(thr, 4);
			duk_get_prop_index(thr, 2, (duk_uarridx_t) i);
			have_acc = 1;
			DUK_ASSERT_TOP(thr, 5);
		} else {
			DUK_ASSERT_TOP(thr, 5);
			duk_dup_0(thr);
			duk_dup(thr, 4);
			duk_get_prop_index(thr, 2, (duk_uarridx_t) i);
			duk_push_u32(thr, i);
			duk_dup_2(thr);
			DUK_DDD(DUK_DDDPRINT("calling reduce function: func=%!T, prev=%!T, curr=%!T, idx=%!T, obj=%!T",
			                     (duk_tval *) duk_get_tval(thr, -5), (duk_tval *) duk_get_tval(thr, -4),
			                     (duk_tval *) duk_get_tval(thr, -3), (duk_tval *) duk_get_tval(thr, -2),
			                     (duk_tval *) duk_get_tval(thr, -1)));
			duk_call(thr, 4);
			DUK_DDD(DUK_DDDPRINT("-> result: %!T", (duk_tval *) duk_get_tval(thr, -1)));
			duk_replace(thr, 4);
			DUK_ASSERT_TOP(thr, 5);
		}
	}

	if (!have_acc) {
		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
	}

	DUK_ASSERT_TOP(thr, 5);
	return 1;
}

#endif  /* DUK_USE_ARRAY_BUILTIN */

/* automatic undefs */
#undef DUK__ARRAY_MID_JOIN_LIMIT
#undef DUK__ITER_EVERY
#undef DUK__ITER_FILTER
#undef DUK__ITER_FOREACH
#undef DUK__ITER_MAP
#undef DUK__ITER_SOME
#line 1 "duk_bi_boolean.c"
/*
 *  Boolean built-ins
 */

/* #include duk_internal.h -> already included */

#if defined(DUK_USE_BOOLEAN_BUILTIN)

/* Shared helper to provide toString() and valueOf().  Checks 'this', gets
 * the primitive value to stack top, and optionally coerces with ToString().
 */
DUK_INTERNAL duk_ret_t duk_bi_boolean_prototype_tostring_shared(duk_hthread *thr) {
	duk_tval *tv;
	duk_hobject *h;
	duk_small_int_t coerce_tostring = duk_get_current_magic(thr);

	/* XXX: there is room to use a shared helper here, many built-ins
	 * check the 'this' type, and if it's an object, check its class,
	 * then get its internal value, etc.
	 */

	duk_push_this(thr);
	tv = duk_get_tval(thr, -1);
	DUK_ASSERT(tv != NULL);

	if (DUK_TVAL_IS_BOOLEAN(tv)) {
		goto type_ok;
	} else if (DUK_TVAL_IS_OBJECT(tv)) {
		h = DUK_TVAL_GET_OBJECT(tv);
		DUK_ASSERT(h != NULL);

		if (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_BOOLEAN) {
			duk_xget_owndataprop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
			DUK_ASSERT(duk_is_boolean(thr, -1));
			goto type_ok;
		}
	}

	DUK_DCERROR_TYPE_INVALID_ARGS(thr);
	/* never here */

 type_ok:
	if (coerce_tostring) {
		duk_to_string(thr, -1);
	}
	return 1;
}

DUK_INTERNAL duk_ret_t duk_bi_boolean_constructor(duk_hthread *thr) {
	duk_hobject *h_this;

	duk_to_boolean(thr, 0);

	if (duk_is_constructor_call(thr)) {
		/* XXX: helper; rely on Boolean.prototype as being non-writable, non-configurable */
		duk_push_this(thr);
		h_this = duk_known_hobject(thr, -1);
		DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_this) == thr->builtins[DUK_BIDX_BOOLEAN_PROTOTYPE]);

		DUK_HOBJECT_SET_CLASS_NUMBER(h_this, DUK_HOBJECT_CLASS_BOOLEAN);

		duk_dup_0(thr);  /* -> [ val obj val ] */
		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);  /* XXX: proper flags? */
	}  /* unbalanced stack */

	return 1;
}

#endif  /* DUK_USE_BOOLEAN_BUILTIN */
#line 1 "duk_bi_buffer.c"
/*
 *  ES2015 TypedArray and Node.js Buffer built-ins
 */

/* #include duk_internal.h -> already included */

/*
 *  Helpers for buffer handling, enabled with DUK_USE_BUFFEROBJECT_SUPPORT.
 */

#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
/* Map class number (minus DUK_HOBJECT_CLASS_BUFOBJ_MIN) to a bidx for the
 * default internal prototype.
 */
static const duk_uint8_t duk__buffer_proto_from_classnum[] = {
	DUK_BIDX_ARRAYBUFFER_PROTOTYPE,
	DUK_BIDX_DATAVIEW_PROTOTYPE,
	DUK_BIDX_INT8ARRAY_PROTOTYPE,
	DUK_BIDX_UINT8ARRAY_PROTOTYPE,
	DUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE,
	DUK_BIDX_INT16ARRAY_PROTOTYPE,
	DUK_BIDX_UINT16ARRAY_PROTOTYPE,
	DUK_BIDX_INT32ARRAY_PROTOTYPE,
	DUK_BIDX_UINT32ARRAY_PROTOTYPE,
	DUK_BIDX_FLOAT32ARRAY_PROTOTYPE,
	DUK_BIDX_FLOAT64ARRAY_PROTOTYPE
};

/* Map DUK_HBUFOBJ_ELEM_xxx to duk_hobject class number.
 * Sync with duk_hbufobj.h and duk_hobject.h.
 */
static const duk_uint8_t duk__buffer_class_from_elemtype[9] = {
	DUK_HOBJECT_CLASS_UINT8ARRAY,
	DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY,
	DUK_HOBJECT_CLASS_INT8ARRAY,
	DUK_HOBJECT_CLASS_UINT16ARRAY,
	DUK_HOBJECT_CLASS_INT16ARRAY,
	DUK_HOBJECT_CLASS_UINT32ARRAY,
	DUK_HOBJECT_CLASS_INT32ARRAY,
	DUK_HOBJECT_CLASS_FLOAT32ARRAY,
	DUK_HOBJECT_CLASS_FLOAT64ARRAY
};

/* Map DUK_HBUFOBJ_ELEM_xxx to prototype object built-in index.
 * Sync with duk_hbufobj.h.
 */
static const duk_uint8_t duk__buffer_proto_from_elemtype[9] = {
	DUK_BIDX_UINT8ARRAY_PROTOTYPE,
	DUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE,
	DUK_BIDX_INT8ARRAY_PROTOTYPE,
	DUK_BIDX_UINT16ARRAY_PROTOTYPE,
	DUK_BIDX_INT16ARRAY_PROTOTYPE,
	DUK_BIDX_UINT32ARRAY_PROTOTYPE,
	DUK_BIDX_INT32ARRAY_PROTOTYPE,
	DUK_BIDX_FLOAT32ARRAY_PROTOTYPE,
	DUK_BIDX_FLOAT64ARRAY_PROTOTYPE
};

/* Map DUK__FLD_xxx to byte size. */
static const duk_uint8_t duk__buffer_nbytes_from_fldtype[6] = {
	1,  /* DUK__FLD_8BIT */
	2,  /* DUK__FLD_16BIT */
	4,  /* DUK__FLD_32BIT */
	4,  /* DUK__FLD_FLOAT */
	8,  /* DUK__FLD_DOUBLE */
	0   /* DUK__FLD_VARINT; not relevant here */
};

/* Bitfield for each DUK_HBUFOBJ_ELEM_xxx indicating which element types
 * are compatible with a blind byte copy for the TypedArray set() method (also
 * used for TypedArray constructor).  Array index is target buffer elem type,
 * bitfield indicates compatible source types.  The types must have same byte
 * size and they must be coercion compatible.
 */
#if !defined(DUK_USE_PREFER_SIZE)
static duk_uint16_t duk__buffer_elemtype_copy_compatible[9] = {
	/* xxx -> DUK_HBUFOBJ_ELEM_UINT8 */
	(1U << DUK_HBUFOBJ_ELEM_UINT8) |
		(1U << DUK_HBUFOBJ_ELEM_UINT8CLAMPED) |
		(1U << DUK_HBUFOBJ_ELEM_INT8),

	/* xxx -> DUK_HBUFOBJ_ELEM_UINT8CLAMPED
	 * Note: INT8 is -not- copy compatible, e.g. -1 would coerce to 0x00.
	 */
	(1U << DUK_HBUFOBJ_ELEM_UINT8) |
		(1U << DUK_HBUFOBJ_ELEM_UINT8CLAMPED),

	/* xxx -> DUK_HBUFOBJ_ELEM_INT8 */
	(1U << DUK_HBUFOBJ_ELEM_UINT8) |
		(1U << DUK_HBUFOBJ_ELEM_UINT8CLAMPED) |
		(1U << DUK_HBUFOBJ_ELEM_INT8),

	/* xxx -> DUK_HBUFOBJ_ELEM_UINT16 */
	(1U << DUK_HBUFOBJ_ELEM_UINT16) |
		(1U << DUK_HBUFOBJ_ELEM_INT16),

	/* xxx -> DUK_HBUFOBJ_ELEM_INT16 */
	(1U << DUK_HBUFOBJ_ELEM_UINT16) |
		(1U << DUK_HBUFOBJ_ELEM_INT16),

	/* xxx -> DUK_HBUFOBJ_ELEM_UINT32 */
	(1U << DUK_HBUFOBJ_ELEM_UINT32) |
		(1U << DUK_HBUFOBJ_ELEM_INT32),

	/* xxx -> DUK_HBUFOBJ_ELEM_INT32 */
	(1U << DUK_HBUFOBJ_ELEM_UINT32) |
		(1U << DUK_HBUFOBJ_ELEM_INT32),

	/* xxx -> DUK_HBUFOBJ_ELEM_FLOAT32 */
	(1U << DUK_HBUFOBJ_ELEM_FLOAT32),

	/* xxx -> DUK_HBUFOBJ_ELEM_FLOAT64 */
	(1U << DUK_HBUFOBJ_ELEM_FLOAT64)
};
#endif  /* !DUK_USE_PREFER_SIZE */

DUK_LOCAL duk_hbufobj *duk__hbufobj_promote_this(duk_hthread *thr) {
	duk_tval *tv_dst;
	duk_hbufobj *res;

	duk_push_this(thr);
	DUK_ASSERT(duk_is_buffer(thr, -1));
	res = (duk_hbufobj *) duk_to_hobject(thr, -1);
	DUK_HBUFOBJ_ASSERT_VALID(res);
	DUK_DD(DUK_DDPRINT("promoted 'this' automatically to an ArrayBuffer: %!iT", duk_get_tval(thr, -1)));

	tv_dst = duk_get_borrowed_this_tval(thr);
	DUK_TVAL_SET_OBJECT_UPDREF(thr, tv_dst, (duk_hobject *) res);
	duk_pop(thr);

	return res;
}

#define DUK__BUFOBJ_FLAG_THROW    (1 << 0)
#define DUK__BUFOBJ_FLAG_PROMOTE  (1 << 1)

/* Shared helper.  When DUK__BUFOBJ_FLAG_PROMOTE is given, the return value is
 * always a duk_hbufobj *.  Without the flag the return value can also be a
 * plain buffer, and the caller must check for it using DUK_HEAPHDR_IS_BUFFER().
 */
DUK_LOCAL duk_heaphdr *duk__getrequire_bufobj_this(duk_hthread *thr, duk_small_uint_t flags) {
	duk_tval *tv;
	duk_hbufobj *h_this;

	DUK_ASSERT(thr != NULL);

	tv = duk_get_borrowed_this_tval(thr);
	DUK_ASSERT(tv != NULL);

	if (DUK_TVAL_IS_OBJECT(tv)) {
		h_this = (duk_hbufobj *) DUK_TVAL_GET_OBJECT(tv);
		DUK_ASSERT(h_this != NULL);
		if (DUK_HOBJECT_IS_BUFOBJ((duk_hobject *) h_this)) {
			DUK_HBUFOBJ_ASSERT_VALID(h_this);
			return (duk_heaphdr *) h_this;
		}
	} else if (DUK_TVAL_IS_BUFFER(tv)) {
		if (flags & DUK__BUFOBJ_FLAG_PROMOTE) {
			/* Promote a plain buffer to a Uint8Array.  This is very
			 * inefficient but allows plain buffer to be used wherever an
			 * Uint8Array is used with very small cost; hot path functions
			 * like index read/write calls should provide direct buffer
			 * support to avoid promotion.
			 */
			/* XXX: make this conditional to a flag if call sites need it? */
			h_this = duk__hbufobj_promote_this(thr);
			DUK_ASSERT(h_this != NULL);
			DUK_HBUFOBJ_ASSERT_VALID(h_this);
			return (duk_heaphdr *) h_this;
		} else {
			/* XXX: ugly, share return pointer for duk_hbuffer. */
			return (duk_heaphdr *) DUK_TVAL_GET_BUFFER(tv);
		}
	}

	if (flags & DUK__BUFOBJ_FLAG_THROW) {
		DUK_ERROR_TYPE(thr, DUK_STR_NOT_BUFFER);
		DUK_WO_NORETURN(return NULL;);
	}
	return NULL;
}

/* Check that 'this' is a duk_hbufobj and return a pointer to it. */
DUK_LOCAL duk_hbufobj *duk__get_bufobj_this(duk_hthread *thr) {
	return (duk_hbufobj *) duk__getrequire_bufobj_this(thr, DUK__BUFOBJ_FLAG_PROMOTE);
}

/* Check that 'this' is a duk_hbufobj and return a pointer to it
 * (NULL if not).
 */
DUK_LOCAL duk_hbufobj *duk__require_bufobj_this(duk_hthread *thr) {
	return (duk_hbufobj *) duk__getrequire_bufobj_this(thr, DUK__BUFOBJ_FLAG_THROW | DUK__BUFOBJ_FLAG_PROMOTE);
}

/* Check that value is a duk_hbufobj and return a pointer to it. */
DUK_LOCAL duk_hbufobj *duk__require_bufobj_value(duk_hthread *thr, duk_idx_t idx) {
	duk_tval *tv;
	duk_hbufobj *h_obj;

	/* Don't accept relative indices now. */
	DUK_ASSERT(idx >= 0);

	tv = duk_require_tval(thr, idx);
	DUK_ASSERT(tv != NULL);
	if (DUK_TVAL_IS_OBJECT(tv)) {
		h_obj = (duk_hbufobj *) DUK_TVAL_GET_OBJECT(tv);
		DUK_ASSERT(h_obj != NULL);
		if (DUK_HOBJECT_IS_BUFOBJ((duk_hobject *) h_obj)) {
			DUK_HBUFOBJ_ASSERT_VALID(h_obj);
			return h_obj;
		}
	} else if (DUK_TVAL_IS_BUFFER(tv)) {
		h_obj = (duk_hbufobj *) duk_to_hobject(thr, idx);
		DUK_ASSERT(h_obj != NULL);
		DUK_HBUFOBJ_ASSERT_VALID(h_obj);
		return h_obj;
	}

	DUK_ERROR_TYPE(thr, DUK_STR_NOT_BUFFER);
	DUK_WO_NORETURN(return NULL;);
}

DUK_LOCAL void duk__set_bufobj_buffer(duk_hthread *thr, duk_hbufobj *h_bufobj, duk_hbuffer *h_val) {
	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(h_bufobj != NULL);
	DUK_ASSERT(h_bufobj->buf == NULL);  /* no need to decref */
	DUK_ASSERT(h_val != NULL);
	DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
	DUK_UNREF(thr);

	h_bufobj->buf = h_val;
	DUK_HBUFFER_INCREF(thr, h_val);
	h_bufobj->length = (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_val);
	DUK_ASSERT(h_bufobj->shift == 0);
	DUK_ASSERT(h_bufobj->elem_type == DUK_HBUFOBJ_ELEM_UINT8);
	DUK_ASSERT(h_bufobj->is_typedarray == 0);

	DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
}

/* Shared offset/length coercion helper. */
DUK_LOCAL void duk__resolve_offset_opt_length(duk_hthread *thr,
                                              duk_hbufobj *h_bufarg,
                                              duk_idx_t idx_offset,
                                              duk_idx_t idx_length,
                                              duk_uint_t *out_offset,
                                              duk_uint_t *out_length,
                                              duk_bool_t throw_flag) {
	duk_int_t offset_signed;
	duk_int_t length_signed;
	duk_uint_t offset;
	duk_uint_t length;

	offset_signed = duk_to_int(thr, idx_offset);
	if (offset_signed < 0) {
		goto fail_range;
	}
	offset = (duk_uint_t) offset_signed;
	if (offset > h_bufarg->length) {
		goto fail_range;
	}
	DUK_ASSERT_DISABLE(offset >= 0);  /* unsigned */
	DUK_ASSERT(offset <= h_bufarg->length);

	if (duk_is_undefined(thr, idx_length)) {
		DUK_ASSERT(h_bufarg->length >= offset);
		length = h_bufarg->length - offset;  /* >= 0 */
	} else {
		length_signed = duk_to_int(thr, idx_length);
		if (length_signed < 0) {
			goto fail_range;
		}
		length = (duk_uint_t) length_signed;
		DUK_ASSERT(h_bufarg->length >= offset);
		if (length > h_bufarg->length - offset) {
			/* Unlike for negative arguments, some call sites
			 * want length to be clamped if it's positive.
			 */
			if (throw_flag) {
				goto fail_range;
			} else {
				length = h_bufarg->length - offset;
			}
		}
	}
	DUK_ASSERT_DISABLE(length >= 0);  /* unsigned */
	DUK_ASSERT(offset + length <= h_bufarg->length);

	*out_offset = offset;
	*out_length = length;
	return;

 fail_range:
	DUK_ERROR_RANGE(thr, DUK_STR_INVALID_ARGS);
	DUK_WO_NORETURN(return;);
}

/* Shared lenient buffer length clamping helper.  No negative indices, no
 * element/byte shifting.
 */
DUK_LOCAL void duk__clamp_startend_nonegidx_noshift(duk_hthread *thr,
                                                    duk_int_t buffer_length,
                                                    duk_idx_t idx_start,
                                                    duk_idx_t idx_end,
                                                    duk_int_t *out_start_offset,
                                                    duk_int_t *out_end_offset) {
	duk_int_t start_offset;
	duk_int_t end_offset;

	DUK_ASSERT(out_start_offset != NULL);
	DUK_ASSERT(out_end_offset != NULL);

	/* undefined coerces to zero which is correct */
	start_offset = duk_to_int_clamped(thr, idx_start, 0, buffer_length);
	if (duk_is_undefined(thr, idx_end)) {
		end_offset = buffer_length;
	} else {
		end_offset = duk_to_int_clamped(thr, idx_end, start_offset, buffer_length);
	}

	DUK_ASSERT(start_offset >= 0);
	DUK_ASSERT(start_offset <= buffer_length);
	DUK_ASSERT(end_offset >= 0);
	DUK_ASSERT(end_offset <= buffer_length);
	DUK_ASSERT(start_offset <= end_offset);

	*out_start_offset = start_offset;
	*out_end_offset = end_offset;
}

/* Shared lenient buffer length clamping helper.  Indices are treated as
 * element indices (though output values are byte offsets) which only
 * really matters for TypedArray views as other buffer object have a zero
 * shift.  Negative indices are counted from end of input slice; crossed
 * indices are clamped to zero length; and final indices are clamped
 * against input slice.  Used for e.g. ArrayBuffer slice().
 */
DUK_LOCAL void duk__clamp_startend_negidx_shifted(duk_hthread *thr,
                                                  duk_int_t buffer_length,
                                                  duk_uint8_t buffer_shift,
                                                  duk_idx_t idx_start,
                                                  duk_idx_t idx_end,
                                                  duk_int_t *out_start_offset,
                                                  duk_int_t *out_end_offset) {
	duk_int_t start_offset;
	duk_int_t end_offset;

	DUK_ASSERT(out_start_offset != NULL);
	DUK_ASSERT(out_end_offset != NULL);

	buffer_length >>= buffer_shift;  /* as (full) elements */

	/* Resolve start/end offset as element indices first; arguments
	 * at idx_start/idx_end are element offsets.  Working with element
	 * indices first also avoids potential for wrapping.
	 */

	start_offset = duk_to_int(thr, idx_start);
	if (start_offset < 0) {
		start_offset = buffer_length + start_offset;
	}
	if (duk_is_undefined(thr, idx_end)) {
		end_offset = buffer_length;
	} else {
		end_offset = duk_to_int(thr, idx_end);
		if (end_offset < 0) {
			end_offset = buffer_length + end_offset;
		}
	}
	/* Note: start_offset/end_offset can still be < 0 here. */

	if (start_offset < 0) {
		start_offset = 0;
	} else if (start_offset > buffer_length) {
		start_offset = buffer_length;
	}
	if (end_offset < start_offset) {
		end_offset = start_offset;
	} else if (end_offset > buffer_length) {
		end_offset = buffer_length;
	}
	DUK_ASSERT(start_offset >= 0);
	DUK_ASSERT(start_offset <= buffer_length);
	DUK_ASSERT(end_offset >= 0);
	DUK_ASSERT(end_offset <= buffer_length);
	DUK_ASSERT(start_offset <= end_offset);

	/* Convert indices to byte offsets. */
	start_offset <<= buffer_shift;
	end_offset <<= buffer_shift;

	*out_start_offset = start_offset;
	*out_end_offset = end_offset;
}

DUK_INTERNAL void duk_hbufobj_promote_plain(duk_hthread *thr, duk_idx_t idx) {
	if (duk_is_buffer(thr, idx)) {
		duk_to_object(thr, idx);
	}
}

DUK_INTERNAL void duk_hbufobj_push_uint8array_from_plain(duk_hthread *thr, duk_hbuffer *h_buf) {
	/* Push Uint8Array which will share the same underlying buffer as
	 * the plain buffer argument.  Also create an ArrayBuffer with the
	 * same backing for the result .buffer property.
	 */

	duk_push_hbuffer(thr, h_buf);
	duk_push_buffer_object(thr, -1, 0, (duk_size_t) DUK_HBUFFER_GET_SIZE(h_buf), DUK_BUFOBJ_UINT8ARRAY);
	duk_remove_m2(thr);

#if 0
	/* More verbose equivalent; maybe useful if e.g. .buffer is omitted. */
	h_bufobj = duk_push_bufobj_raw(thr,
	                               DUK_HOBJECT_FLAG_EXTENSIBLE |
	                               DUK_HOBJECT_FLAG_BUFOBJ |
	                               DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_UINT8ARRAY),
	                               DUK_BIDX_UINT8ARRAY_PROTOTYPE);
	DUK_ASSERT(h_bufobj != NULL);
	duk__set_bufobj_buffer(thr, h_bufobj, h_buf);
	h_bufobj->is_typedarray = 1;
	DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);

	h_arrbuf = duk_push_bufobj_raw(thr,
	                               DUK_HOBJECT_FLAG_EXTENSIBLE |
	                               DUK_HOBJECT_FLAG_BUFOBJ |
	                               DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAYBUFFER),
	                               DUK_BIDX_ARRAYBUFFER_PROTOTYPE);
	DUK_ASSERT(h_arrbuf != NULL);
	duk__set_bufobj_buffer(thr, h_arrbuf, h_buf);
	DUK_ASSERT(h_arrbuf->is_typedarray == 0);
	DUK_HBUFOBJ_ASSERT_VALID(h_arrbuf);

	DUK_ASSERT(h_bufobj->buf_prop == NULL);
	h_bufobj->buf_prop = (duk_hobject *) h_arrbuf;
	DUK_ASSERT(h_arrbuf != NULL);
	DUK_HBUFOBJ_INCREF(thr, h_arrbuf);
	duk_pop(thr);
#endif
}

/* Indexed read helper for buffer objects, also called from outside this file. */
DUK_INTERNAL void duk_hbufobj_push_validated_read(duk_hthread *thr, duk_hbufobj *h_bufobj, duk_uint8_t *p, duk_small_uint_t elem_size) {
	duk_double_union du;

	DUK_ASSERT(elem_size > 0);
	duk_memcpy((void *) du.uc, (const void *) p, (size_t) elem_size);

	switch (h_bufobj->elem_type) {
	case DUK_HBUFOBJ_ELEM_UINT8:
	case DUK_HBUFOBJ_ELEM_UINT8CLAMPED:
		duk_push_uint(thr, (duk_uint_t) du.uc[0]);
		break;
	case DUK_HBUFOBJ_ELEM_INT8:
		duk_push_int(thr, (duk_int_t) (duk_int8_t) du.uc[0]);
		break;
	case DUK_HBUFOBJ_ELEM_UINT16:
		duk_push_uint(thr, (duk_uint_t) du.us[0]);
		break;
	case DUK_HBUFOBJ_ELEM_INT16:
		duk_push_int(thr, (duk_int_t) (duk_int16_t) du.us[0]);
		break;
	case DUK_HBUFOBJ_ELEM_UINT32:
		duk_push_uint(thr, (duk_uint_t) du.ui[0]);
		break;
	case DUK_HBUFOBJ_ELEM_INT32:
		duk_push_int(thr, (duk_int_t) (duk_int32_t) du.ui[0]);
		break;
	case DUK_HBUFOBJ_ELEM_FLOAT32:
		duk_push_number(thr, (duk_double_t) du.f[0]);
		break;
	case DUK_HBUFOBJ_ELEM_FLOAT64:
		duk_push_number(thr, (duk_double_t) du.d);
		break;
	default:
		DUK_UNREACHABLE();
	}
}

/* Indexed write helper for buffer objects, also called from outside this file. */
DUK_INTERNAL void duk_hbufobj_validated_write(duk_hthread *thr, duk_hbufobj *h_bufobj, duk_uint8_t *p, duk_small_uint_t elem_size) {
	duk_double_union du;

	/* NOTE! Caller must ensure that any side effects from the
	 * coercions below are safe.  If that cannot be guaranteed
	 * (which is normally the case), caller must coerce the
	 * argument using duk_to_number() before any pointer
	 * validations; the result of duk_to_number() always coerces
	 * without side effects here.
	 */

	switch (h_bufobj->elem_type) {
	case DUK_HBUFOBJ_ELEM_UINT8:
		du.uc[0] = (duk_uint8_t) duk_to_uint32(thr, -1);
		break;
	case DUK_HBUFOBJ_ELEM_UINT8CLAMPED:
		du.uc[0] = (duk_uint8_t) duk_to_uint8clamped(thr, -1);
		break;
	case DUK_HBUFOBJ_ELEM_INT8:
		du.uc[0] = (duk_uint8_t) duk_to_int32(thr, -1);
		break;
	case DUK_HBUFOBJ_ELEM_UINT16:
		du.us[0] = (duk_uint16_t) duk_to_uint32(thr, -1);
		break;
	case DUK_HBUFOBJ_ELEM_INT16:
		du.us[0] = (duk_uint16_t) duk_to_int32(thr, -1);
		break;
	case DUK_HBUFOBJ_ELEM_UINT32:
		du.ui[0] = (duk_uint32_t) duk_to_uint32(thr, -1);
		break;
	case DUK_HBUFOBJ_ELEM_INT32:
		du.ui[0] = (duk_uint32_t) duk_to_int32(thr, -1);
		break;
	case DUK_HBUFOBJ_ELEM_FLOAT32:
		/* A double-to-float cast is undefined behavior in C99 if
		 * the cast is out-of-range, so use a helper.  Example:
		 * runtime error: value -1e+100 is outside the range of representable values of type 'float'
		 */
		du.f[0] = duk_double_to_float_t(duk_to_number_m1(thr));
		break;
	case DUK_HBUFOBJ_ELEM_FLOAT64:
		du.d = (duk_double_t) duk_to_number_m1(thr);
		break;
	default:
		DUK_UNREACHABLE();
	}

	DUK_ASSERT(elem_size > 0);
	duk_memcpy((void *) p, (const void *) du.uc, (size_t) elem_size);
}

/* Helper to create a fixed buffer from argument value at index 0.
 * Node.js and allocPlain() compatible.
 */
DUK_LOCAL duk_hbuffer *duk__hbufobj_fixed_from_argvalue(duk_hthread *thr) {
	duk_int_t len;
	duk_int_t i;
	duk_size_t buf_size;
	duk_uint8_t *buf;

	switch (duk_get_type(thr, 0)) {
	case DUK_TYPE_NUMBER: {
		len = duk_to_int_clamped(thr, 0, 0, DUK_INT_MAX);
		(void) duk_push_fixed_buffer_zero(thr, (duk_size_t) len);
		break;
	}
	case DUK_TYPE_BUFFER: { /* Treat like Uint8Array. */
		goto slow_copy;
	}
	case DUK_TYPE_OBJECT: {
		duk_hobject *h;
		duk_hbufobj *h_bufobj;

		/* For Node.js Buffers "Passing an ArrayBuffer returns a Buffer
		 * that shares allocated memory with the given ArrayBuffer."
		 * https://nodejs.org/api/buffer.html#buffer_buffer_from_buffer_alloc_and_buffer_allocunsafe
		 */

		h = duk_known_hobject(thr, 0);
		if (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAYBUFFER) {
			DUK_ASSERT(DUK_HOBJECT_IS_BUFOBJ(h));
			h_bufobj = (duk_hbufobj *) h;
			if (DUK_UNLIKELY(h_bufobj->buf == NULL)) {
				DUK_ERROR_TYPE_INVALID_ARGS(thr);
				DUK_WO_NORETURN(return NULL;);
			}
			if (DUK_UNLIKELY(h_bufobj->offset != 0 || h_bufobj->length != DUK_HBUFFER_GET_SIZE(h_bufobj->buf))) {
				/* No support for ArrayBuffers with slice
				 * offset/length.
				 */
				DUK_ERROR_TYPE_INVALID_ARGS(thr);
				DUK_WO_NORETURN(return NULL;);
			}
			duk_push_hbuffer(thr, h_bufobj->buf);
			return h_bufobj->buf;
		}
		goto slow_copy;
	}
	case DUK_TYPE_STRING: {
		/* ignore encoding for now */
		duk_require_hstring_notsymbol(thr, 0);
		duk_dup_0(thr);
		(void) duk_to_buffer(thr, -1, &buf_size);
		break;
	}
	default:
		DUK_ERROR_TYPE_INVALID_ARGS(thr);
		DUK_WO_NORETURN(return NULL;);
	}

 done:
	DUK_ASSERT(duk_is_buffer(thr, -1));
	return duk_known_hbuffer(thr, -1);

 slow_copy:
	/* XXX: fast path for typed arrays and other buffer objects? */

	(void) duk_get_prop_stridx_short(thr, 0, DUK_STRIDX_LENGTH);
	len = duk_to_int_clamped(thr, -1, 0, DUK_INT_MAX);
	duk_pop(thr);
	buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, (duk_size_t) len);  /* no zeroing, all indices get initialized */
	for (i = 0; i < len; i++) {
		/* XXX: fast path for array or buffer arguments? */
		duk_get_prop_index(thr, 0, (duk_uarridx_t) i);
		buf[i] = (duk_uint8_t) (duk_to_uint32(thr, -1) & 0xffU);
		duk_pop(thr);
	}
	goto done;
}
#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */

/*
 *  Node.js Buffer constructor
 *
 *  Node.js Buffers are just Uint8Arrays with internal prototype set to
 *  Buffer.prototype so they're handled otherwise the same as Uint8Array.
 *  However, the constructor arguments are very different so a separate
 *  constructor entry point is used.
 */
#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_constructor(duk_hthread *thr) {
	duk_hbuffer *h_buf;

	h_buf = duk__hbufobj_fixed_from_argvalue(thr);
	DUK_ASSERT(h_buf != NULL);

	duk_push_buffer_object(thr,
	                       -1,
	                       0,
	                       DUK_HBUFFER_FIXED_GET_SIZE((duk_hbuffer_fixed *) (void *) h_buf),
	                       DUK_BUFOBJ_UINT8ARRAY);
	duk_push_hobject_bidx(thr, DUK_BIDX_NODEJS_BUFFER_PROTOTYPE);
	duk_set_prototype(thr, -2);

	/* XXX: a more direct implementation */

	return 1;
}
#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */

/*
 *  ArrayBuffer, DataView, and TypedArray constructors
 */

#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
DUK_INTERNAL duk_ret_t duk_bi_arraybuffer_constructor(duk_hthread *thr) {
	duk_hbufobj *h_bufobj;
	duk_hbuffer *h_val;
	duk_int_t len;

	DUK_CTX_ASSERT_VALID(thr);

	duk_require_constructor_call(thr);

	len = duk_to_int(thr, 0);
	if (len < 0) {
		goto fail_length;
	}
	(void) duk_push_fixed_buffer_zero(thr, (duk_size_t) len);
	h_val = (duk_hbuffer *) duk_known_hbuffer(thr, -1);

	h_bufobj = duk_push_bufobj_raw(thr,
	                               DUK_HOBJECT_FLAG_EXTENSIBLE |
	                               DUK_HOBJECT_FLAG_BUFOBJ |
	                               DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAYBUFFER),
	                               DUK_BIDX_ARRAYBUFFER_PROTOTYPE);
	DUK_ASSERT(h_bufobj != NULL);

	duk__set_bufobj_buffer(thr, h_bufobj, h_val);
	DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);

	return 1;

 fail_length:
	DUK_DCERROR_RANGE_INVALID_LENGTH(thr);
}
#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */


/* Format of magic, bits:
 *   0...1: elem size shift (0-3)
 *   2...5: elem type (DUK_HBUFOBJ_ELEM_xxx)
 *
 * XXX: add prototype bidx explicitly to magic instead of using a mapping?
 */

#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
DUK_INTERNAL duk_ret_t duk_bi_typedarray_constructor(duk_hthread *thr) {
	duk_tval *tv;
	duk_hobject *h_obj;
	duk_hbufobj *h_bufobj = NULL;
	duk_hbufobj *h_bufarg = NULL;
	duk_hbuffer *h_val;
	duk_small_uint_t magic;
	duk_small_uint_t shift;
	duk_small_uint_t elem_type;
	duk_small_uint_t elem_size;
	duk_small_uint_t class_num;
	duk_small_uint_t proto_bidx;
	duk_uint_t align_mask;
	duk_uint_t elem_length;
	duk_int_t elem_length_signed;
	duk_uint_t byte_length;
	duk_small_uint_t copy_mode;

	/* XXX: The same copy helpers could be shared with at least some
	 * buffer functions.
	 */

	duk_require_constructor_call(thr);

	/* We could fit built-in index into magic but that'd make the magic
	 * number dependent on built-in numbering (genbuiltins.py doesn't
	 * handle that yet).  So map both class and prototype from the
	 * element type.
	 */
	magic = (duk_small_uint_t) duk_get_current_magic(thr);
	shift = magic & 0x03U;               /* bits 0...1: shift */
	elem_type = (magic >> 2) & 0x0fU;    /* bits 2...5: type */
	elem_size = 1U << shift;
	align_mask = elem_size - 1;
	DUK_ASSERT(elem_type < sizeof(duk__buffer_proto_from_elemtype) / sizeof(duk_uint8_t));
	proto_bidx = duk__buffer_proto_from_elemtype[elem_type];
	DUK_ASSERT(proto_bidx < DUK_NUM_BUILTINS);
	DUK_ASSERT(elem_type < sizeof(duk__buffer_class_from_elemtype) / sizeof(duk_uint8_t));
	class_num = duk__buffer_class_from_elemtype[elem_type];

	DUK_DD(DUK_DDPRINT("typedarray constructor, magic=%d, shift=%d, elem_type=%d, "
	                   "elem_size=%d, proto_bidx=%d, class_num=%d",
	                   (int) magic, (int) shift, (int) elem_type, (int) elem_size,
	                   (int) proto_bidx, (int) class_num));

	/* Argument variants.  When the argument is an ArrayBuffer a view to
	 * the same buffer is created; otherwise a new ArrayBuffer is always
	 * created.
	 */

	/* XXX: initial iteration to treat a plain buffer like an ArrayBuffer:
	 * coerce to an ArrayBuffer object and use that as .buffer.  The underlying
	 * buffer will be the same but result .buffer !== inputPlainBuffer.
	 */
	duk_hbufobj_promote_plain(thr, 0);

	tv = duk_get_tval(thr, 0);
	DUK_ASSERT(tv != NULL);  /* arg count */
	if (DUK_TVAL_IS_OBJECT(tv)) {
		h_obj = DUK_TVAL_GET_OBJECT(tv);
		DUK_ASSERT(h_obj != NULL);

		if (DUK_HOBJECT_GET_CLASS_NUMBER(h_obj) == DUK_HOBJECT_CLASS_ARRAYBUFFER) {
			/* ArrayBuffer: unlike any other argument variant, create
			 * a view into the existing buffer.
			 */

			duk_int_t byte_offset_signed;
			duk_uint_t byte_offset;

			h_bufarg = (duk_hbufobj *) h_obj;

			byte_offset_signed = duk_to_int(thr, 1);
			if (byte_offset_signed < 0) {
				goto fail_arguments;
			}
			byte_offset = (duk_uint_t) byte_offset_signed;
			if (byte_offset > h_bufarg->length ||
			    (byte_offset & align_mask) != 0) {
				/* Must be >= 0 and multiple of element size. */
				goto fail_arguments;
			}
			if (duk_is_undefined(thr, 2)) {
				DUK_ASSERT(h_bufarg->length >= byte_offset);
				byte_length = h_bufarg->length - byte_offset;
				if ((byte_length & align_mask) != 0) {
					/* Must be element size multiple from
					 * start offset to end of buffer.
					 */
					goto fail_arguments;
				}
				elem_length = (byte_length >> shift);
			} else {
				elem_length_signed = duk_to_int(thr, 2);
				if (elem_length_signed < 0) {
					goto fail_arguments;
				}
				elem_length = (duk_uint_t) elem_length_signed;
				byte_length = elem_length << shift;
				if ((byte_length >> shift) != elem_length) {
					/* Byte length would overflow. */
					/* XXX: easier check with less code? */
					goto fail_arguments;
				}
				DUK_ASSERT(h_bufarg->length >= byte_offset);
				if (byte_length > h_bufarg->length - byte_offset) {
					/* Not enough data. */
					goto fail_arguments;
				}
			}
			DUK_UNREF(elem_length);
			DUK_ASSERT_DISABLE(byte_offset >= 0);
			DUK_ASSERT(byte_offset <= h_bufarg->length);
			DUK_ASSERT_DISABLE(byte_length >= 0);
			DUK_ASSERT(byte_offset + byte_length <= h_bufarg->length);
			DUK_ASSERT((elem_length << shift) == byte_length);

			h_bufobj = duk_push_bufobj_raw(thr,
			                               DUK_HOBJECT_FLAG_EXTENSIBLE |
			                               DUK_HOBJECT_FLAG_BUFOBJ |
			                               DUK_HOBJECT_CLASS_AS_FLAGS(class_num),
			                               (duk_small_int_t) proto_bidx);
			h_val = h_bufarg->buf;
			if (h_val == NULL) {
				DUK_DCERROR_TYPE_INVALID_ARGS(thr);
			}
			h_bufobj->buf = h_val;
			DUK_HBUFFER_INCREF(thr, h_val);
			h_bufobj->offset = h_bufarg->offset + byte_offset;
			h_bufobj->length = byte_length;
			h_bufobj->shift = (duk_uint8_t) shift;
			h_bufobj->elem_type = (duk_uint8_t) elem_type;
			h_bufobj->is_typedarray = 1;
			DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);

			/* Set .buffer to the argument ArrayBuffer. */
			DUK_ASSERT(h_bufobj->buf_prop == NULL);
			h_bufobj->buf_prop = (duk_hobject *) h_bufarg;
			DUK_ASSERT(h_bufarg != NULL);
			DUK_HBUFOBJ_INCREF(thr, h_bufarg);
			return 1;
		} else if (DUK_HOBJECT_IS_BUFOBJ(h_obj)) {
			/* TypedArray (or other non-ArrayBuffer duk_hbufobj).
			 * Conceptually same behavior as for an Array-like argument,
			 * with a few fast paths.
			 */

			h_bufarg = (duk_hbufobj *) h_obj;
			DUK_HBUFOBJ_ASSERT_VALID(h_bufarg);
			elem_length_signed = (duk_int_t) (h_bufarg->length >> h_bufarg->shift);
			if (h_bufarg->buf == NULL) {
				DUK_DCERROR_TYPE_INVALID_ARGS(thr);
			}

			/* Select copy mode.  Must take into account element
			 * compatibility and validity of the underlying source
			 * buffer.
			 */

			DUK_DDD(DUK_DDDPRINT("selecting copy mode for bufobj arg, "
			                     "src byte_length=%ld, src shift=%d, "
			                     "src/dst elem_length=%ld; "
			                     "dst shift=%d -> dst byte_length=%ld",
			                     (long) h_bufarg->length, (int) h_bufarg->shift,
			                     (long) elem_length_signed, (int) shift,
			                     (long) (elem_length_signed << shift)));

			copy_mode = 2;  /* default is explicit index read/write copy */
#if !defined(DUK_USE_PREFER_SIZE)
			/* With a size optimized build copy_mode 2 is enough.
			 * Modes 0 and 1 are faster but conceptually the same.
			 */
			DUK_ASSERT(elem_type < sizeof(duk__buffer_elemtype_copy_compatible) / sizeof(duk_uint16_t));
			if (DUK_HBUFOBJ_VALID_SLICE(h_bufarg)) {
				if ((duk__buffer_elemtype_copy_compatible[elem_type] & (1 << h_bufarg->elem_type)) != 0) {
					DUK_DDD(DUK_DDDPRINT("source/target are copy compatible, memcpy"));
					DUK_ASSERT(shift == h_bufarg->shift);  /* byte sizes will match */
					copy_mode = 0;
				} else {
					DUK_DDD(DUK_DDDPRINT("source/target not copy compatible but valid, fast copy"));
					copy_mode = 1;
				}
			}
#endif  /* !DUK_USE_PREFER_SIZE */
		} else {
			/* Array or Array-like */
			elem_length_signed = (duk_int_t) duk_get_length(thr, 0);
			copy_mode = 2;
		}
	} else {
		/* Non-object argument is simply int coerced, matches
		 * V8 behavior (except for "null", which we coerce to
		 * 0 but V8 TypeErrors).
		 */
		elem_length_signed = duk_to_int(thr, 0);
		copy_mode = 3;
	}
	if (elem_length_signed < 0) {
		goto fail_arguments;
	}
	elem_length = (duk_uint_t) elem_length_signed;
	byte_length = (duk_uint_t) (elem_length << shift);
	if ((byte_length >> shift) != elem_length) {
		/* Byte length would overflow. */
		/* XXX: easier check with less code? */
		goto fail_arguments;
	}

	DUK_DDD(DUK_DDDPRINT("elem_length=%ld, byte_length=%ld",
	                     (long) elem_length, (long) byte_length));

	/* ArrayBuffer argument is handled specially above; the rest of the
	 * argument variants are handled by shared code below.
	 *
	 * ArrayBuffer in h_bufobj->buf_prop is intentionally left unset.
	 * It will be automatically created by the .buffer accessor on
	 * first access.
	 */

	/* Push the resulting view object on top of a plain fixed buffer. */
	(void) duk_push_fixed_buffer(thr, byte_length);
	h_val = duk_known_hbuffer(thr, -1);
	DUK_ASSERT(h_val != NULL);

	h_bufobj = duk_push_bufobj_raw(thr,
	                               DUK_HOBJECT_FLAG_EXTENSIBLE |
	                               DUK_HOBJECT_FLAG_BUFOBJ |
	                               DUK_HOBJECT_CLASS_AS_FLAGS(class_num),
	                               (duk_small_int_t) proto_bidx);

	h_bufobj->buf = h_val;
	DUK_HBUFFER_INCREF(thr, h_val);
	DUK_ASSERT(h_bufobj->offset == 0);
	h_bufobj->length = byte_length;
	h_bufobj->shift = (duk_uint8_t) shift;
	h_bufobj->elem_type = (duk_uint8_t) elem_type;
	h_bufobj->is_typedarray = 1;
	DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);

	/* Copy values, the copy method depends on the arguments.
	 *
	 * Copy mode decision may depend on the validity of the underlying
	 * buffer of the source argument; there must be no harmful side effects
	 * from there to here for copy_mode to still be valid.
	 */
	DUK_DDD(DUK_DDDPRINT("copy mode: %d", (int) copy_mode));
	switch (copy_mode) {
		/* Copy modes 0 and 1 can be omitted in size optimized build,
		 * copy mode 2 handles them (but more slowly).
		 */
#if !defined(DUK_USE_PREFER_SIZE)
	case 0: {
		/* Use byte copy. */

		duk_uint8_t *p_src;
		duk_uint8_t *p_dst;

		DUK_ASSERT(h_bufobj != NULL);
		DUK_ASSERT(h_bufobj->buf != NULL);
		DUK_ASSERT(DUK_HBUFOBJ_VALID_SLICE(h_bufobj));
		DUK_ASSERT(h_bufarg != NULL);
		DUK_ASSERT(h_bufarg->buf != NULL);
		DUK_ASSERT(DUK_HBUFOBJ_VALID_SLICE(h_bufarg));

		p_dst = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufobj);
		p_src = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufarg);

		DUK_DDD(DUK_DDDPRINT("using memcpy: p_src=%p, p_dst=%p, byte_length=%ld",
		                     (void *) p_src, (void *) p_dst, (long) byte_length));

		duk_memcpy_unsafe((void *) p_dst, (const void *) p_src, (size_t) byte_length);
		break;
	}
	case 1: {
		/* Copy values through direct validated reads and writes. */

		duk_small_uint_t src_elem_size;
		duk_small_uint_t dst_elem_size;
		duk_uint8_t *p_src;
		duk_uint8_t *p_src_end;
		duk_uint8_t *p_dst;

		DUK_ASSERT(h_bufobj != NULL);
		DUK_ASSERT(h_bufobj->buf != NULL);
		DUK_ASSERT(DUK_HBUFOBJ_VALID_SLICE(h_bufobj));
		DUK_ASSERT(h_bufarg != NULL);
		DUK_ASSERT(h_bufarg->buf != NULL);
		DUK_ASSERT(DUK_HBUFOBJ_VALID_SLICE(h_bufarg));

		src_elem_size = (duk_small_uint_t) (1U << h_bufarg->shift);
		dst_elem_size = elem_size;

		p_src = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufarg);
		p_dst = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufobj);
		p_src_end = p_src + h_bufarg->length;

		DUK_DDD(DUK_DDDPRINT("using fast copy: p_src=%p, p_src_end=%p, p_dst=%p, "
		                     "src_elem_size=%d, dst_elem_size=%d",
		                     (void *) p_src, (void *) p_src_end, (void *) p_dst,
		                     (int) src_elem_size, (int) dst_elem_size));

		while (p_src != p_src_end) {
			DUK_DDD(DUK_DDDPRINT("fast path per element copy loop: "
			                     "p_src=%p, p_src_end=%p, p_dst=%p",
			                     (void *) p_src, (void *) p_src_end, (void *) p_dst));
			/* A validated read() is always a number, so it's write coercion
			 * is always side effect free an won't invalidate pointers etc.
			 */
			duk_hbufobj_push_validated_read(thr, h_bufarg, p_src, src_elem_size);
			duk_hbufobj_validated_write(thr, h_bufobj, p_dst, dst_elem_size);
			duk_pop(thr);
			p_src += src_elem_size;
			p_dst += dst_elem_size;
		}
		break;
	}
#endif  /* !DUK_USE_PREFER_SIZE */
	case 2: {
		/* Copy values by index reads and writes.  Let virtual
		 * property handling take care of coercion.
		 */
		duk_uint_t i;

		DUK_DDD(DUK_DDDPRINT("using slow copy"));

		for (i = 0; i < elem_length; i++) {
			duk_get_prop_index(thr, 0, (duk_uarridx_t) i);
			duk_put_prop_index(thr, -2, (duk_uarridx_t) i);
		}
		break;
	}
	default:
	case 3: {
		/* No copy, leave zero bytes in the buffer.  There's no
		 * ambiguity with Float32/Float64 because zero bytes also
		 * represent 0.0.
		 */

		DUK_DDD(DUK_DDDPRINT("using no copy"));
		break;
	}
	}

	return 1;

 fail_arguments:
	DUK_DCERROR_RANGE_INVALID_ARGS(thr);
}
#else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
/* When bufferobject support is disabled, new Uint8Array() could still be
 * supported to create a plain fixed buffer.  Disabled for now.
 */
#if 0
DUK_INTERNAL duk_ret_t duk_bi_typedarray_constructor(duk_hthread *thr) {
	duk_int_t elem_length_signed;
	duk_uint_t byte_length;

	/* XXX: The same copy helpers could be shared with at least some
	 * buffer functions.
	 */

	duk_require_constructor_call(thr);

	elem_length_signed = duk_require_int(thr, 0);
	if (elem_length_signed < 0) {
		goto fail_arguments;
	}
	byte_length = (duk_uint_t) elem_length_signed;

	(void) duk_push_fixed_buffer_zero(thr, (duk_size_t) byte_length);
	return 1;

 fail_arguments:
	DUK_DCERROR_RANGE_INVALID_ARGS(thr);
}
#endif  /* 0 */
#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */

#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
DUK_INTERNAL duk_ret_t duk_bi_dataview_constructor(duk_hthread *thr) {
	duk_hbufobj *h_bufarg;
	duk_hbufobj *h_bufobj;
	duk_hbuffer *h_val;
	duk_uint_t offset;
	duk_uint_t length;

	duk_require_constructor_call(thr);

	h_bufarg = duk__require_bufobj_value(thr, 0);
	DUK_ASSERT(h_bufarg != NULL);
	if (DUK_HOBJECT_GET_CLASS_NUMBER((duk_hobject *) h_bufarg) != DUK_HOBJECT_CLASS_ARRAYBUFFER) {
		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
	}

	duk__resolve_offset_opt_length(thr, h_bufarg, 1, 2, &offset, &length, 1 /*throw_flag*/);
	DUK_ASSERT(offset <= h_bufarg->length);
	DUK_ASSERT(offset + length <= h_bufarg->length);

	h_bufobj = duk_push_bufobj_raw(thr,
	                               DUK_HOBJECT_FLAG_EXTENSIBLE |
	                               DUK_HOBJECT_FLAG_BUFOBJ |
	                               DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DATAVIEW),
	                               DUK_BIDX_DATAVIEW_PROTOTYPE);

	h_val = h_bufarg->buf;
	if (h_val == NULL) {
		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
	}
	h_bufobj->buf = h_val;
	DUK_HBUFFER_INCREF(thr, h_val);
	h_bufobj->offset = h_bufarg->offset + offset;
	h_bufobj->length = length;
	DUK_ASSERT(h_bufobj->shift == 0);
	DUK_ASSERT(h_bufobj->elem_type == DUK_HBUFOBJ_ELEM_UINT8);
	DUK_ASSERT(h_bufobj->is_typedarray == 0);

	DUK_ASSERT(h_bufobj->buf_prop == NULL);
	h_bufobj->buf_prop = (duk_hobject *) h_bufarg;
	DUK_ASSERT(h_bufarg != NULL);
	DUK_HBUFOBJ_INCREF(thr, h_bufarg);

	DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
	return 1;
}
#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */

/*
 *  ArrayBuffer.isView()
 */

#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
DUK_INTERNAL duk_ret_t duk_bi_arraybuffer_isview(duk_hthread *thr) {
	duk_hobject *h_obj;
	duk_bool_t ret = 0;

	if (duk_is_buffer(thr, 0)) {
		ret = 1;
	} else {
		h_obj = duk_get_hobject(thr, 0);
		if (h_obj != NULL && DUK_HOBJECT_IS_BUFOBJ(h_obj)) {
			/* DataView needs special casing: ArrayBuffer.isView() is
			 * true, but ->is_typedarray is 0.
			 */
			ret = ((duk_hbufobj *) h_obj)->is_typedarray ||
			      (DUK_HOBJECT_GET_CLASS_NUMBER(h_obj) == DUK_HOBJECT_CLASS_DATAVIEW);
		}
	}
	duk_push_boolean(thr, ret);
	return 1;
}
#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */

/*
 *  Uint8Array.allocPlain()
 */

#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
DUK_INTERNAL duk_ret_t duk_bi_uint8array_allocplain(duk_hthread *thr) {
	duk__hbufobj_fixed_from_argvalue(thr);
	return 1;
}
#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */

/*
 *  Uint8Array.plainOf()
 */

#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
DUK_INTERNAL duk_ret_t duk_bi_uint8array_plainof(duk_hthread *thr) {
	duk_hbufobj *h_bufobj;

#if !defined(DUK_USE_PREFER_SIZE)
	/* Avoid churn if argument is already a plain buffer. */
	if (duk_is_buffer(thr, 0)) {
		return 1;
	}
#endif

	/* Promotes plain buffers to ArrayBuffers, so for a plain buffer
	 * argument we'll create a pointless temporary (but still work
	 * correctly).
	 */
	h_bufobj = duk__require_bufobj_value(thr, 0);
	if (h_bufobj->buf == NULL) {
		duk_push_undefined(thr);
	} else {
		duk_push_hbuffer(thr, h_bufobj->buf);
	}
	return 1;
}
#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */

/*
 *  Node.js Buffer: toString([encoding], [start], [end])
 */

#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_tostring(duk_hthread *thr) {
	duk_hbufobj *h_this;
	duk_int_t start_offset, end_offset;
	duk_uint8_t *buf_slice;
	duk_size_t slice_length;

	h_this = duk__get_bufobj_this(thr);
	if (h_this == NULL) {
		/* XXX: happens e.g. when evaluating: String(Buffer.prototype). */
		duk_push_literal(thr, "[object Object]");
		return 1;
	}
	DUK_HBUFOBJ_ASSERT_VALID(h_this);

	/* Ignore encoding for now. */

	duk__clamp_startend_nonegidx_noshift(thr,
	                                     (duk_int_t) h_this->length,
	                                     1 /*idx_start*/,
	                                     2 /*idx_end*/,
	                                     &start_offset,
	                                     &end_offset);

	slice_length = (duk_size_t) (end_offset - start_offset);
	buf_slice = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, slice_length);  /* all bytes initialized below */
	DUK_ASSERT(buf_slice != NULL);

	/* Neutered or uncovered, TypeError. */
	if (h_this->buf == NULL ||
	    !DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_this, (duk_size_t) start_offset + slice_length)) {
		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
	}

	/* XXX: ideally we wouldn't make a copy but a view into the buffer for the
	 * decoding process.  Or the decoding helper could be changed to accept
	 * the slice info (a buffer pointer is NOT a good approach because guaranteeing
	 * its stability is difficult).
	 */

	DUK_ASSERT(DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_this, (duk_size_t) start_offset + slice_length));
	duk_memcpy_unsafe((void *) buf_slice,
	                  (const void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + start_offset),
	                  (size_t) slice_length);

	/* Use the equivalent of: new TextEncoder().encode(this) to convert the
	 * string.  Result will be valid UTF-8; non-CESU-8 inputs are currently
	 * interpreted loosely.  Value stack convention is a bit odd for now.
	 */
	duk_replace(thr, 0);
	duk_set_top(thr, 1);
	return duk_textdecoder_decode_utf8_nodejs(thr);
}
#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */

/*
 *  Node.js Buffer.prototype: toJSON()
 */

#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_tojson(duk_hthread *thr) {
	duk_hbufobj *h_this;
	duk_uint8_t *buf;
	duk_uint_t i, n;
	duk_tval *tv;

	h_this = duk__require_bufobj_this(thr);
	DUK_ASSERT(h_this != NULL);

	if (h_this->buf == NULL || !DUK_HBUFOBJ_VALID_SLICE(h_this)) {
		/* Serialize uncovered backing buffer as a null; doesn't
		 * really matter as long we're memory safe.
		 */
		duk_push_null(thr);
		return 1;
	}

	duk_push_object(thr);
	duk_push_hstring_stridx(thr, DUK_STRIDX_UC_BUFFER);
	duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_TYPE);

	/* XXX: uninitialized would be OK */
	DUK_ASSERT_DISABLE((duk_size_t) h_this->length <= (duk_size_t) DUK_UINT32_MAX);
	tv = duk_push_harray_with_size_outptr(thr, (duk_uint32_t) h_this->length);  /* XXX: needs revision with >4G buffers */
	DUK_ASSERT(!duk_is_bare_object(thr, -1));

	DUK_ASSERT(h_this->buf != NULL);
	buf = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this);
	for (i = 0, n = h_this->length; i < n; i++) {
		DUK_TVAL_SET_U32(tv + i, (duk_uint32_t) buf[i]);  /* no need for decref or incref */
	}
	duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_DATA);

	return 1;
}
#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */

/*
 *  Node.js Buffer.prototype.equals()
 *  Node.js Buffer.prototype.compare()
 *  Node.js Buffer.compare()
 */

#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
DUK_INTERNAL duk_ret_t duk_bi_buffer_compare_shared(duk_hthread *thr) {
	duk_small_uint_t magic;
	duk_hbufobj *h_bufarg1;
	duk_hbufobj *h_bufarg2;
	duk_small_int_t comp_res;

	/* XXX: keep support for plain buffers and non-Node.js buffers? */

	magic = (duk_small_uint_t) duk_get_current_magic(thr);
	if (magic & 0x02U) {
		/* Static call style. */
		h_bufarg1 = duk__require_bufobj_value(thr, 0);
		h_bufarg2 = duk__require_bufobj_value(thr, 1);
	} else {
		h_bufarg1 = duk__require_bufobj_this(thr);
		h_bufarg2 = duk__require_bufobj_value(thr, 0);
	}
	DUK_ASSERT(h_bufarg1 != NULL);
	DUK_ASSERT(h_bufarg2 != NULL);

	/* We want to compare the slice/view areas of the arguments.
	 * If either slice/view is invalid (underlying buffer is shorter)
	 * ensure equals() is false, but otherwise the only thing that
	 * matters is to be memory safe.
	 */

	if (DUK_HBUFOBJ_VALID_SLICE(h_bufarg1) &&
	    DUK_HBUFOBJ_VALID_SLICE(h_bufarg2)) {
		comp_res = duk_js_data_compare((const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufarg1->buf) + h_bufarg1->offset,
		                               (const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufarg2->buf) + h_bufarg2->offset,
		                               (duk_size_t) h_bufarg1->length,
		                               (duk_size_t) h_bufarg2->length);
	} else {
		comp_res = -1;  /* either nonzero value is ok */
	}

	if (magic & 0x01U) {
		/* compare: similar to string comparison but for buffer data. */
		duk_push_int(thr, comp_res);
	} else {
		/* equals */
		duk_push_boolean(thr, (comp_res == 0));
	}

	return 1;
}
#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */

/*
 *  Node.js Buffer.prototype.fill()
 */

#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_fill(duk_hthread *thr) {
	duk_hbufobj *h_this;
	const duk_uint8_t *fill_str_ptr;
	duk_size_t fill_str_len;
	duk_uint8_t fill_value;
	duk_int_t fill_offset;
	duk_int_t fill_end;
	duk_size_t fill_length;
	duk_uint8_t *p;

	h_this = duk__require_bufobj_this(thr);
	DUK_ASSERT(h_this != NULL);
	if (h_this->buf == NULL) {
		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
	}

	/* [ value offset end ] */

	if (duk_is_string_notsymbol(thr, 0)) {
		fill_str_ptr = (const duk_uint8_t *) duk_get_lstring(thr, 0, &fill_str_len);
		DUK_ASSERT(fill_str_ptr != NULL);
	} else {
		/* Symbols get ToNumber() coerced and cause TypeError. */
		fill_value = (duk_uint8_t) duk_to_uint32(thr, 0);
		fill_str_ptr = (const duk_uint8_t *) &fill_value;
		fill_str_len = 1;
	}

	/* Fill offset handling is more lenient than in Node.js. */

	duk__clamp_startend_nonegidx_noshift(thr,
	                                     (duk_int_t) h_this->length,
	                                     1 /*idx_start*/,
	                                     2 /*idx_end*/,
	                                     &fill_offset,
	                                     &fill_end);

	DUK_DDD(DUK_DDDPRINT("fill: fill_value=%02x, fill_offset=%ld, fill_end=%ld, view length=%ld",
	                     (unsigned int) fill_value, (long) fill_offset, (long) fill_end, (long) h_this->length));

	DUK_ASSERT(fill_end - fill_offset >= 0);
	DUK_ASSERT(h_this->buf != NULL);

	p = (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + fill_offset);
	fill_length = (duk_size_t) (fill_end - fill_offset);
	if (fill_str_len == 1) {
		/* Handle single character fills as memset() even when
		 * the fill data comes from a one-char argument.
		 */
		duk_memset_unsafe((void *) p, (int) fill_str_ptr[0], (size_t) fill_length);
	} else if (fill_str_len > 1) {
		duk_size_t i, n, t;

		for (i = 0, n = (duk_size_t) (fill_end - fill_offset), t = 0; i < n; i++) {
			p[i] = fill_str_ptr[t++];
			if (t >= fill_str_len) {
				t = 0;
			}
		}
	} else {
		DUK_DDD(DUK_DDDPRINT("zero size fill pattern, ignore silently"));
	}

	/* Return the Buffer to allow chaining: b.fill(0x11).fill(0x22, 3, 5).toString() */
	duk_push_this(thr);
	return 1;
}
#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */

/*
 *  Node.js Buffer.prototype.write(string, [offset], [length], [encoding])
 */

#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_write(duk_hthread *thr) {
	duk_hbufobj *h_this;
	duk_uint_t offset;
	duk_uint_t length;
	const duk_uint8_t *str_data;
	duk_size_t str_len;

	/* XXX: very inefficient support for plain buffers */
	h_this = duk__require_bufobj_this(thr);
	DUK_ASSERT(h_this != NULL);

	/* Argument must be a string, e.g. a buffer is not allowed. */
	str_data = (const duk_uint8_t *) duk_require_lstring_notsymbol(thr, 0, &str_len);

	duk__resolve_offset_opt_length(thr, h_this, 1, 2, &offset, &length, 0 /*throw_flag*/);
	DUK_ASSERT(offset <= h_this->length);
	DUK_ASSERT(offset + length <= h_this->length);

	/* XXX: encoding is ignored now. */

	if (length > str_len) {
		length = (duk_uint_t) str_len;
	}

	if (DUK_HBUFOBJ_VALID_SLICE(h_this)) {
		/* Cannot overlap. */
		duk_memcpy_unsafe((void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + offset),
		                  (const void *) str_data,
		                  (size_t) length);
	} else {
		DUK_DDD(DUK_DDDPRINT("write() target buffer is not covered, silent ignore"));
	}

	duk_push_uint(thr, length);
	return 1;
}
#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */

/*
 *  Node.js Buffer.prototype.copy()
 */

#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_copy(duk_hthread *thr) {
	duk_hbufobj *h_this;
	duk_hbufobj *h_bufarg;
	duk_int_t source_length;
	duk_int_t target_length;
	duk_int_t target_start, source_start, source_end;
	duk_uint_t target_ustart, source_ustart, source_uend;
	duk_uint_t copy_size = 0;

	/* [ targetBuffer targetStart sourceStart sourceEnd ] */

	h_this = duk__require_bufobj_this(thr);
	h_bufarg = duk__require_bufobj_value(thr, 0);
	DUK_ASSERT(h_this != NULL);
	DUK_ASSERT(h_bufarg != NULL);
	source_length = (duk_int_t) h_this->length;
	target_length = (duk_int_t) h_bufarg->length;

	target_start = duk_to_int(thr, 1);
	source_start = duk_to_int(thr, 2);
	if (duk_is_undefined(thr, 3)) {
		source_end = source_length;
	} else {
		source_end = duk_to_int(thr, 3);
	}

	DUK_DDD(DUK_DDDPRINT("checking copy args: target_start=%ld, target_length=%ld, "
	                     "source_start=%ld, source_end=%ld, source_length=%ld",
	                     (long) target_start, (long) h_bufarg->length,
	                     (long) source_start, (long) source_end, (long) source_length));

	/* This behavior mostly mimics Node.js now. */

	if (source_start < 0 || source_end < 0 || target_start < 0) {
		/* Negative offsets cause a RangeError. */
		goto fail_bounds;
	}
	source_ustart = (duk_uint_t) source_start;
	source_uend = (duk_uint_t) source_end;
	target_ustart = (duk_uint_t) target_start;
	if (source_ustart >= source_uend ||  /* crossed offsets or zero size */
	    source_ustart >= (duk_uint_t) source_length ||  /* source out-of-bounds (but positive) */
	    target_ustart >= (duk_uint_t) target_length) {  /* target out-of-bounds (but positive) */
		goto silent_ignore;
	}
	if (source_uend >= (duk_uint_t) source_length) {
		/* Source end clamped silently to available length. */
		source_uend = (duk_uint_t) source_length;
	}
	copy_size = source_uend - source_ustart;
	if (target_ustart + copy_size > (duk_uint_t) target_length) {
		/* Clamp to target's end if too long.
		 *
		 * NOTE: there's no overflow possibility in the comparison;
		 * both target_ustart and copy_size are >= 0 and based on
		 * values in duk_int_t range.  Adding them as duk_uint_t
		 * values is then guaranteed not to overflow.
		 */
		DUK_ASSERT(target_ustart + copy_size >= target_ustart);  /* no overflow */
		DUK_ASSERT(target_ustart + copy_size >= copy_size);  /* no overflow */
		copy_size = (duk_uint_t) target_length - target_ustart;
	}

	DUK_DDD(DUK_DDDPRINT("making copy: target_ustart=%lu source_ustart=%lu copy_size=%lu",
	                     (unsigned long) target_ustart, (unsigned long) source_ustart,
	                     (unsigned long) copy_size));

	DUK_ASSERT(copy_size >= 1);
	DUK_ASSERT(source_ustart <= (duk_uint_t) source_length);
	DUK_ASSERT(source_ustart + copy_size <= (duk_uint_t) source_length);
	DUK_ASSERT(target_ustart <= (duk_uint_t) target_length);
	DUK_ASSERT(target_ustart + copy_size <= (duk_uint_t) target_length);

	/* Ensure copy is covered by underlying buffers. */
	DUK_ASSERT(h_bufarg->buf != NULL);  /* length check */
	DUK_ASSERT(h_this->buf != NULL);    /* length check */
	if (DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_bufarg, target_ustart + copy_size) &&
	    DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_this, source_ustart + copy_size)) {
		/* Must use memmove() because copy area may overlap (source and target
		 * buffer may be the same, or from different slices.
		 */
		duk_memmove_unsafe((void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufarg) + target_ustart),
		                   (const void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + source_ustart),
		                   (size_t) copy_size);
	} else {
		DUK_DDD(DUK_DDDPRINT("buffer copy not covered by underlying buffer(s), ignoring"));
	}

 silent_ignore:
	/* Return value is like write(), number of bytes written.
	 * The return value matters because of code like:
	 * "off += buf.copy(...)".
         */
	duk_push_uint(thr, copy_size);
	return 1;

 fail_bounds:
	DUK_DCERROR_RANGE_INVALID_ARGS(thr);
}
#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */

/*
 *  TypedArray.prototype.set()
 *
 *  TypedArray set() is pretty interesting to implement because:
 *
 *    - The source argument may be a plain array or a typedarray.  If the
 *      source is a TypedArray, values are decoded and re-encoded into the
 *      target (not as a plain byte copy).  This may happen even when the
 *      element byte size is the same, e.g. integer values may be re-encoded
 *      into floats.
 *
 *    - Source and target may refer to the same underlying buffer, so that
 *      the set() operation may overlap.  The specification requires that this
 *      must work as if a copy was made before the operation.  Note that this
 *      is NOT a simple memmove() situation because the source and target
 *      byte sizes may be different -- e.g. a 4-byte source (Int8Array) may
 *      expand to a 16-byte target (Uint32Array) so that the target overlaps
 *      the source both from beginning and the end (unlike in typical memmove).
 *
 *    - Even if 'buf' pointers of the source and target differ, there's no
 *      guarantee that their memory areas don't overlap.  This may be the
 *      case with external buffers.
 *
 *  Even so, it is nice to optimize for the common case:
 *
 *    - Source and target separate buffers or non-overlapping.
 *
 *    - Source and target have a compatible type so that a plain byte copy
 *      is possible.  Note that while e.g. uint8 and int8 are compatible
 *      (coercion one way or another doesn't change the byte representation),
 *      e.g. int8 and uint8clamped are NOT compatible when writing int8
 *      values into uint8clamped typedarray (-1 would clamp to 0 for instance).
 *
 *  See test-bi-typedarray-proto-set.js.
 */

#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
DUK_INTERNAL duk_ret_t duk_bi_typedarray_set(duk_hthread *thr) {
	duk_hbufobj *h_this;
	duk_hobject *h_obj;
	duk_uarridx_t i, n;
	duk_int_t offset_signed;
	duk_uint_t offset_elems;
	duk_uint_t offset_bytes;

	h_this = duk__require_bufobj_this(thr);
	DUK_ASSERT(h_this != NULL);
	DUK_HBUFOBJ_ASSERT_VALID(h_this);

	if (h_this->buf == NULL) {
		DUK_DDD(DUK_DDDPRINT("source neutered, skip copy"));
		return 0;
	}

	duk_hbufobj_promote_plain(thr, 0);
	h_obj = duk_require_hobject(thr, 0);

	/* XXX: V8 throws a TypeError for negative values.  Would it
	 * be more useful to interpret negative offsets here from the
	 * end of the buffer too?
	 */
	offset_signed = duk_to_int(thr, 1);
	if (offset_signed < 0) {
		/* For some reason this is a TypeError (at least in V8). */
		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
	}
	offset_elems = (duk_uint_t) offset_signed;
	offset_bytes = offset_elems << h_this->shift;
	if ((offset_bytes >> h_this->shift) != offset_elems) {
		/* Byte length would overflow. */
		/* XXX: easier check with less code? */
		goto fail_args;
	}
	if (offset_bytes > h_this->length) {
		/* Equality may be OK but >length not.  Checking
		 * this explicitly avoids some overflow cases
		 * below.
		 */
		goto fail_args;
	}
	DUK_ASSERT(offset_bytes <= h_this->length);

	/* Fast path: source is a TypedArray (or any bufobj). */

	if (DUK_HOBJECT_IS_BUFOBJ(h_obj)) {
		duk_hbufobj *h_bufarg;
#if !defined(DUK_USE_PREFER_SIZE)
		duk_uint16_t comp_mask;
#endif
		duk_small_int_t no_overlap = 0;
		duk_uint_t src_length;
		duk_uint_t dst_length;
		duk_uint_t dst_length_elems;
		duk_uint8_t *p_src_base;
		duk_uint8_t *p_src_end;
		duk_uint8_t *p_src;
		duk_uint8_t *p_dst_base;
		duk_uint8_t *p_dst;
		duk_small_uint_t src_elem_size;
		duk_small_uint_t dst_elem_size;

		h_bufarg = (duk_hbufobj *) h_obj;
		DUK_HBUFOBJ_ASSERT_VALID(h_bufarg);

		if (h_bufarg->buf == NULL) {
			DUK_DDD(DUK_DDDPRINT("target neutered, skip copy"));
			return 0;
		}

		/* Nominal size check. */
		src_length = h_bufarg->length;  /* bytes in source */
		dst_length_elems = (src_length >> h_bufarg->shift);  /* elems in source and dest */
		dst_length = dst_length_elems << h_this->shift;  /* bytes in dest */
		if ((dst_length >> h_this->shift) != dst_length_elems) {
			/* Byte length would overflow. */
			/* XXX: easier check with less code? */
			goto fail_args;
		}
		DUK_DDD(DUK_DDDPRINT("nominal size check: src_length=%ld, dst_length=%ld",
		                     (long) src_length, (long) dst_length));
		DUK_ASSERT(offset_bytes <= h_this->length);
		if (dst_length > h_this->length - offset_bytes) {
			/* Overflow not an issue because subtraction is used on the right
			 * side and guaranteed to be >= 0.
			 */
			DUK_DDD(DUK_DDDPRINT("copy exceeds target buffer nominal length"));
			goto fail_args;
		}
		if (!DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_this, offset_bytes + dst_length)) {
			DUK_DDD(DUK_DDDPRINT("copy not covered by underlying target buffer, ignore"));
			return 0;
		}

		p_src_base = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufarg);
		p_dst_base = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + offset_bytes;

		/* Check actual underlying buffers for validity and that they
		 * cover the copy.  No side effects are allowed after the check
		 * so that the validity status doesn't change.
		 */
		if (!DUK_HBUFOBJ_VALID_SLICE(h_this) ||
		    !DUK_HBUFOBJ_VALID_SLICE(h_bufarg)) {
			/* The condition could be more narrow and check for the
			 * copy area only, but there's no need for fine grained
			 * behavior when the underlying buffer is misconfigured.
			 */
			DUK_DDD(DUK_DDDPRINT("source and/or target not covered by underlying buffer, skip copy"));
			return 0;
		}

		/* We want to do a straight memory copy if possible: this is
		 * an important operation because .set() is the TypedArray
		 * way to copy chunks of memory.  However, because set()
		 * conceptually works in terms of elements, not all views are
		 * compatible with direct byte copying.
		 *
		 * If we do manage a direct copy, the "overlap issue" handled
		 * below can just be solved using memmove() because the source
		 * and destination element sizes are necessarily equal.
		 */

#if !defined(DUK_USE_PREFER_SIZE)
		DUK_ASSERT(h_this->elem_type < sizeof(duk__buffer_elemtype_copy_compatible) / sizeof(duk_uint16_t));
		comp_mask = duk__buffer_elemtype_copy_compatible[h_this->elem_type];
		if (comp_mask & (1 << h_bufarg->elem_type)) {
			DUK_ASSERT(src_length == dst_length);

			DUK_DDD(DUK_DDDPRINT("fast path: able to use memmove() because views are compatible"));
			duk_memmove_unsafe((void *) p_dst_base, (const void *) p_src_base, (size_t) dst_length);
			return 0;
		}
		DUK_DDD(DUK_DDDPRINT("fast path: views are not compatible with a byte copy, copy by item"));
#endif  /* !DUK_USE_PREFER_SIZE */

		/* We want to avoid making a copy to process set() but that's
		 * not always possible: the source and the target may overlap
		 * and because element sizes are different, the overlap cannot
		 * always be handled with a memmove() or choosing the copy
		 * direction in a certain way.  For example, if source type is
		 * uint8 and target type is uint32, the target area may exceed
		 * the source area from both ends!
		 *
		 * Note that because external buffers may point to the same
		 * memory areas, we must ultimately make this check using
		 * pointers.
		 *
		 * NOTE: careful with side effects: any side effect may cause
		 * a buffer resize (or external buffer pointer/length update)!
		 */

		DUK_DDD(DUK_DDDPRINT("overlap check: p_src_base=%p, src_length=%ld, "
		                     "p_dst_base=%p, dst_length=%ld",
		                     (void *) p_src_base, (long) src_length,
		                     (void *) p_dst_base, (long) dst_length));

		if (p_src_base >= p_dst_base + dst_length ||  /* source starts after dest ends */
		    p_src_base + src_length <= p_dst_base) {   /* source ends before dest starts */
			no_overlap = 1;
		}

		if (!no_overlap) {
			/* There's overlap: the desired end result is that
			 * conceptually a copy is made to avoid "trampling"
			 * of source data by destination writes.  We make
			 * an actual temporary copy to handle this case.
			 */
			duk_uint8_t *p_src_copy;

			DUK_DDD(DUK_DDDPRINT("there is overlap, make a copy of the source"));
			p_src_copy = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, src_length);
			DUK_ASSERT(p_src_copy != NULL);
			duk_memcpy_unsafe((void *) p_src_copy, (const void *) p_src_base, (size_t) src_length);

			p_src_base = p_src_copy;  /* use p_src_base from now on */
		}
		/* Value stack intentionally mixed size here. */

		DUK_DDD(DUK_DDDPRINT("after overlap check: p_src_base=%p, src_length=%ld, "
		                     "p_dst_base=%p, dst_length=%ld, valstack top=%ld",
		                     (void *) p_src_base, (long) src_length,
		                     (void *) p_dst_base, (long) dst_length,
		                     (long) duk_get_top(thr)));

		/* Ready to make the copy.  We must proceed element by element
		 * and must avoid any side effects that might cause the buffer
		 * validity check above to become invalid.
		 *
		 * Although we work through the value stack here, only plain
		 * numbers are handled which should be side effect safe.
		 */

		src_elem_size = (duk_small_uint_t) (1U << h_bufarg->shift);
		dst_elem_size = (duk_small_uint_t) (1U << h_this->shift);
		p_src = p_src_base;
		p_dst = p_dst_base;
		p_src_end = p_src_base + src_length;

		while (p_src != p_src_end) {
			DUK_DDD(DUK_DDDPRINT("fast path per element copy loop: "
			                     "p_src=%p, p_src_end=%p, p_dst=%p",
			                     (void *) p_src, (void *) p_src_end, (void *) p_dst));
			/* A validated read() is always a number, so it's write coercion
			 * is always side effect free an won't invalidate pointers etc.
			 */
			duk_hbufobj_push_validated_read(thr, h_bufarg, p_src, src_elem_size);
			duk_hbufobj_validated_write(thr, h_this, p_dst, dst_elem_size);
			duk_pop(thr);
			p_src += src_elem_size;
			p_dst += dst_elem_size;
		}

		return 0;
	} else {
		/* Slow path: quite slow, but we save space by using the property code
		 * to write coerce target values.  We don't need to worry about overlap
		 * here because the source is not a TypedArray.
		 *
		 * We could use the bufobj write coercion helper but since the
		 * property read may have arbitrary side effects, full validity checks
		 * would be needed for every element anyway.
		 */

		n = (duk_uarridx_t) duk_get_length(thr, 0);
		DUK_ASSERT(offset_bytes <= h_this->length);
		if ((n << h_this->shift) > h_this->length - offset_bytes) {
			/* Overflow not an issue because subtraction is used on the right
			 * side and guaranteed to be >= 0.
			 */
			DUK_DDD(DUK_DDDPRINT("copy exceeds target buffer nominal length"));
			goto fail_args;
		}

		/* There's no need to check for buffer validity status for the
		 * target here: the property access code will do that for each
		 * element.  Moreover, if we did check the validity here, side
		 * effects from reading the source argument might invalidate
		 * the results anyway.
		 */

		DUK_ASSERT_TOP(thr, 2);
		duk_push_this(thr);

		for (i = 0; i < n; i++) {
			duk_get_prop_index(thr, 0, i);
			duk_put_prop_index(thr, 2, offset_elems + i);
		}
	}

	return 0;

 fail_args:
	DUK_DCERROR_RANGE_INVALID_ARGS(thr);
}
#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */

/*
 *  Node.js Buffer.prototype.slice([start], [end])
 *  ArrayBuffer.prototype.slice(begin, [end])
 *  TypedArray.prototype.subarray(begin, [end])
 *
 *  The API calls are almost identical; negative indices are counted from end
 *  of buffer, and final indices are clamped (allowing crossed indices).  Main
 *  differences:
 *
 *    - Copy/view behavior; Node.js .slice() and TypedArray .subarray() create
 *      views, ArrayBuffer .slice() creates a copy
 *
 *    - Resulting object has a different class and prototype depending on the
 *      call (or 'this' argument)
 *
 *    - TypedArray .subarray() arguments are element indices, not byte offsets
 *
 *    - Plain buffer argument creates a plain buffer slice
 */

#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
DUK_LOCAL void duk__arraybuffer_plain_slice(duk_hthread *thr, duk_hbuffer *h_val) {
	duk_int_t start_offset, end_offset;
	duk_uint_t slice_length;
	duk_uint8_t *p_copy;
	duk_size_t copy_length;

	duk__clamp_startend_negidx_shifted(thr,
	                                   (duk_int_t) DUK_HBUFFER_GET_SIZE(h_val),
	                                   0 /*buffer_shift*/,
	                                   0 /*idx_start*/,
	                                   1 /*idx_end*/,
	                                   &start_offset,
	                                   &end_offset);
	DUK_ASSERT(end_offset <= (duk_int_t) DUK_HBUFFER_GET_SIZE(h_val));
	DUK_ASSERT(start_offset >= 0);
	DUK_ASSERT(end_offset >= start_offset);
	slice_length = (duk_uint_t) (end_offset - start_offset);

	p_copy = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, (duk_size_t) slice_length);
	DUK_ASSERT(p_copy != NULL);
	copy_length = slice_length;

	duk_memcpy_unsafe((void *) p_copy,
	                  (const void *) ((duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_val) + start_offset),
	                  copy_length);
}
#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */

#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
/* Shared helper for slice/subarray operation.
 * Magic: 0x01=isView, 0x02=copy, 0x04=Node.js Buffer special handling.
 */
DUK_INTERNAL duk_ret_t duk_bi_buffer_slice_shared(duk_hthread *thr) {
	duk_small_int_t magic;
	duk_small_uint_t res_class_num;
	duk_small_int_t res_proto_bidx;
	duk_hbufobj *h_this;
	duk_hbufobj *h_bufobj;
	duk_hbuffer *h_val;
	duk_int_t start_offset, end_offset;
	duk_uint_t slice_length;
	duk_tval *tv;

	/* [ start end ] */

	magic = duk_get_current_magic(thr);

	tv = duk_get_borrowed_this_tval(thr);
	DUK_ASSERT(tv != NULL);

	if (DUK_TVAL_IS_BUFFER(tv)) {
		/* For plain buffers return a plain buffer slice. */
		h_val = DUK_TVAL_GET_BUFFER(tv);
		DUK_ASSERT(h_val != NULL);

		if (magic & 0x02) {
			/* Make copy: ArrayBuffer.prototype.slice() uses this. */
			duk__arraybuffer_plain_slice(thr, h_val);
			return 1;
		} else {
			/* View into existing buffer: cannot be done if the
			 * result is a plain buffer because there's no slice
			 * info.  So return an ArrayBuffer instance; coerce
			 * the 'this' binding into an object and behave as if
			 * the original call was for an Object-coerced plain
			 * buffer (handled automatically by duk__require_bufobj_this()).
			 */

			DUK_DDD(DUK_DDDPRINT("slice() doesn't handle view into plain buffer, coerce 'this' to ArrayBuffer object"));
			/* fall through */
		}
	}
	tv = NULL;  /* No longer valid nor needed. */

	h_this = duk__require_bufobj_this(thr);

	/* Slice offsets are element (not byte) offsets, which only matters
	 * for TypedArray views, Node.js Buffer and ArrayBuffer have shift
	 * zero so byte and element offsets are the same.  Negative indices
	 * are counted from end of slice, crossed indices are allowed (and
	 * result in zero length result), and final values are clamped
	 * against the current slice.  There's intentionally no check
	 * against the underlying buffer here.
	 */

	duk__clamp_startend_negidx_shifted(thr,
	                                   (duk_int_t) h_this->length,
	                                   (duk_uint8_t) h_this->shift,
	                                   0 /*idx_start*/,
	                                   1 /*idx_end*/,
	                                   &start_offset,
	                                   &end_offset);
	DUK_ASSERT(end_offset >= start_offset);
	DUK_ASSERT(start_offset >= 0);
	DUK_ASSERT(end_offset >= 0);
	slice_length = (duk_uint_t) (end_offset - start_offset);

	/* The resulting buffer object gets the same class and prototype as
	 * the buffer in 'this', e.g. if the input is a Uint8Array the
	 * result is a Uint8Array; if the input is a Float32Array, the
	 * result is a Float32Array.  The result internal prototype should
	 * be the default prototype for the class (e.g. initial value of
	 * Uint8Array.prototype), not copied from the argument (Duktape 1.x
	 * did that).
	 *
	 * Node.js Buffers have special handling: they're Uint8Arrays as far
	 * as the internal class is concerned, so the new Buffer should also
	 * be an Uint8Array but inherit from Buffer.prototype.
	 */
	res_class_num = DUK_HOBJECT_GET_CLASS_NUMBER((duk_hobject *) h_this);
	DUK_ASSERT(res_class_num >= DUK_HOBJECT_CLASS_BUFOBJ_MIN);  /* type check guarantees */
	DUK_ASSERT(res_class_num <= DUK_HOBJECT_CLASS_BUFOBJ_MAX);
	res_proto_bidx = duk__buffer_proto_from_classnum[res_class_num - DUK_HOBJECT_CLASS_BUFOBJ_MIN];
	if (magic & 0x04) {
		res_proto_bidx = DUK_BIDX_NODEJS_BUFFER_PROTOTYPE;
	}
	h_bufobj = duk_push_bufobj_raw(thr,
	                               DUK_HOBJECT_FLAG_EXTENSIBLE |
	                               DUK_HOBJECT_FLAG_BUFOBJ |
	                               DUK_HOBJECT_CLASS_AS_FLAGS(res_class_num),
	                               res_proto_bidx);
	DUK_ASSERT(h_bufobj != NULL);

	DUK_ASSERT(h_bufobj->length == 0);
	h_bufobj->shift = h_this->shift;  /* inherit */
	h_bufobj->elem_type = h_this->elem_type;  /* inherit */
	h_bufobj->is_typedarray = magic & 0x01;
	DUK_ASSERT(h_bufobj->is_typedarray == 0 || h_bufobj->is_typedarray == 1);

	h_val = h_this->buf;
	if (h_val == NULL) {
		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
	}

	if (magic & 0x02) {
		/* non-zero: make copy */
		duk_uint8_t *p_copy;
		duk_size_t copy_length;

		p_copy = (duk_uint8_t *) duk_push_fixed_buffer_zero(thr, (duk_size_t) slice_length);  /* must be zeroed, not all bytes always copied */
		DUK_ASSERT(p_copy != NULL);

		/* Copy slice, respecting underlying buffer limits; remainder
		 * is left as zero.
		 */
		copy_length = DUK_HBUFOBJ_CLAMP_BYTELENGTH(h_this, slice_length);
		duk_memcpy_unsafe((void *) p_copy,
		                  (const void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + start_offset),
		                  copy_length);

		h_val = duk_known_hbuffer(thr, -1);

		h_bufobj->buf = h_val;
		DUK_HBUFFER_INCREF(thr, h_val);
		h_bufobj->length = slice_length;
		DUK_ASSERT(h_bufobj->offset == 0);

		duk_pop(thr);  /* reachable so pop OK */
	} else {
		h_bufobj->buf = h_val;
		DUK_HBUFFER_INCREF(thr, h_val);
		h_bufobj->length = slice_length;
		h_bufobj->offset = h_this->offset + (duk_uint_t) start_offset;

		/* Copy the .buffer property, needed for TypedArray.prototype.subarray().
		 *
		 * XXX: limit copy only for TypedArray classes specifically?
		 */

		DUK_ASSERT(h_bufobj->buf_prop == NULL);
		h_bufobj->buf_prop = h_this->buf_prop;  /* may be NULL */
		DUK_HOBJECT_INCREF_ALLOWNULL(thr, (duk_hobject *) h_bufobj->buf_prop);
	}
	/* unbalanced stack on purpose */

	DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
	return 1;
}
#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */

/*
 *  Node.js Buffer.isEncoding()
 */

#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_is_encoding(duk_hthread *thr) {
	const char *encoding;

	/* only accept lowercase 'utf8' now. */

	encoding = duk_to_string(thr, 0);
	DUK_ASSERT(duk_is_string(thr, 0));  /* guaranteed by duk_to_string() */
	duk_push_boolean(thr, DUK_STRCMP(encoding, "utf8") == 0);
	return 1;
}
#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */

/*
 *  Node.js Buffer.isBuffer()
 */

#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_is_buffer(duk_hthread *thr) {
	duk_hobject *h;
	duk_hobject *h_proto;
	duk_bool_t ret = 0;

	DUK_ASSERT(duk_get_top(thr) >= 1);  /* nargs */
	h = duk_get_hobject(thr, 0);
	if (h != NULL) {
		h_proto = thr->builtins[DUK_BIDX_NODEJS_BUFFER_PROTOTYPE];
		DUK_ASSERT(h_proto != NULL);

		h = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
		if (h != NULL) {
			ret = duk_hobject_prototype_chain_contains(thr, h, h_proto, 0 /*ignore_loop*/);
		}
	}

	duk_push_boolean(thr, ret);
	return 1;
}
#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */

/*
 *  Node.js Buffer.byteLength()
 */

#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_byte_length(duk_hthread *thr) {
	const char *str;
	duk_size_t len;

	/* At the moment Buffer(<str>) will just use the string bytes as
	 * is (ignoring encoding), so we return the string length here
	 * unconditionally.
	 */

	/* XXX: to be revised; Old Node.js behavior just coerces any buffer
	 * values to string:
	 * $ node
	 * > Buffer.byteLength(new Uint32Array(10))
	 * 20
	 * > Buffer.byteLength(new Uint32Array(100))
	 * 20
	 * (The 20 comes from '[object Uint32Array]'.length
	 */

	str = duk_to_lstring(thr, 0, &len);
	DUK_UNREF(str);
	duk_push_size_t(thr, len);
	return 1;
}
#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */

/*
 *  Node.js Buffer.concat()
 */

#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_concat(duk_hthread *thr) {
	duk_hobject *h_arg;
	duk_uint_t total_length;
	duk_hbufobj *h_bufobj;
	duk_hbufobj *h_bufres;
	duk_hbuffer *h_val;
	duk_uint_t i, n;
	duk_uint8_t *p;
	duk_size_t space_left;
	duk_size_t copy_size;

	/* Node.js accepts only actual Arrays. */
	h_arg = duk_require_hobject(thr, 0);
	if (DUK_HOBJECT_GET_CLASS_NUMBER(h_arg) != DUK_HOBJECT_CLASS_ARRAY) {
		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
	}

	/* Compute result length and validate argument buffers. */
	n = (duk_uint_t) duk_get_length(thr, 0);
	total_length = 0;
	for (i = 0; i < n; i++) {
		/* Neutered checks not necessary here: neutered buffers have
		 * zero 'length' so we'll effectively skip them.
		 */
		DUK_ASSERT_TOP(thr, 2);  /* [ array totalLength ] */
		duk_get_prop_index(thr, 0, (duk_uarridx_t) i);  /* -> [ array totalLength buf ] */
		h_bufobj = duk__require_bufobj_value(thr, 2);
		DUK_ASSERT(h_bufobj != NULL);
		total_length += h_bufobj->length;
		if (DUK_UNLIKELY(total_length < h_bufobj->length)) {
			DUK_DCERROR_RANGE_INVALID_ARGS(thr);  /* Wrapped. */
		}
		duk_pop(thr);
	}
	/* In Node.js v0.12.1 a 1-element array is special and won't create a
	 * copy, this was fixed later so an explicit check no longer needed.
	 */

	/* User totalLength overrides a computed length, but we'll check
	 * every copy in the copy loop.  Note that duk_to_int() can
	 * technically have arbitrary side effects so we need to recheck
	 * the buffers in the copy loop.
	 */
	if (!duk_is_undefined(thr, 1) && n > 0) {
		/* For n == 0, Node.js ignores totalLength argument and
		 * returns a zero length buffer.
		 */
		duk_int_t total_length_signed;
		total_length_signed = duk_to_int(thr, 1);
		if (total_length_signed < 0) {
			DUK_DCERROR_RANGE_INVALID_ARGS(thr);
		}
		total_length = (duk_uint_t) total_length_signed;
	}

	h_bufres = duk_push_bufobj_raw(thr,
	                               DUK_HOBJECT_FLAG_EXTENSIBLE |
	                               DUK_HOBJECT_FLAG_BUFOBJ |
	                               DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_UINT8ARRAY),
	                               DUK_BIDX_NODEJS_BUFFER_PROTOTYPE);
	DUK_ASSERT(h_bufres != NULL);

	p = (duk_uint8_t *) duk_push_fixed_buffer_zero(thr, total_length);  /* must be zeroed, all bytes not necessarily written over */
	DUK_ASSERT(p != NULL);
	space_left = (duk_size_t) total_length;

	for (i = 0; i < n; i++) {
		DUK_ASSERT_TOP(thr, 4);  /* [ array totalLength bufres buf ] */

		duk_get_prop_index(thr, 0, (duk_uarridx_t) i);
		h_bufobj = duk__require_bufobj_value(thr, 4);
		DUK_ASSERT(h_bufobj != NULL);

		copy_size = h_bufobj->length;
		if (copy_size > space_left) {
			copy_size = space_left;
		}

		if (h_bufobj->buf != NULL &&
		    DUK_HBUFOBJ_VALID_SLICE(h_bufobj)) {
			duk_memcpy_unsafe((void *) p,
			                  (const void *) DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufobj),
			                  copy_size);
		} else {
			/* Just skip, leaving zeroes in the result. */
			;
		}
		p += copy_size;
		space_left -= copy_size;

		duk_pop(thr);
	}

	h_val = duk_known_hbuffer(thr, -1);

	duk__set_bufobj_buffer(thr, h_bufres, h_val);
	h_bufres->is_typedarray = 1;
	DUK_HBUFOBJ_ASSERT_VALID(h_bufres);

	duk_pop(thr);  /* pop plain buffer, now reachable through h_bufres */

	return 1;  /* return h_bufres */
}
#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */

/*
 *  Shared readfield and writefield methods
 *
 *  The readfield/writefield methods need support for endianness and field
 *  types.  All offsets are byte based so no offset shifting is needed.
 */

#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
/* Format of magic, bits:
 *   0...1: field type; 0=uint8, 1=uint16, 2=uint32, 3=float, 4=double, 5=unused, 6=unused, 7=unused
 *       3: endianness: 0=little, 1=big
 *       4: signed: 1=yes, 0=no
 *       5: typedarray: 1=yes, 0=no
 */
#define  DUK__FLD_8BIT         0
#define  DUK__FLD_16BIT        1
#define  DUK__FLD_32BIT        2
#define  DUK__FLD_FLOAT        3
#define  DUK__FLD_DOUBLE       4
#define  DUK__FLD_VARINT       5
#define  DUK__FLD_BIGENDIAN    (1 << 3)
#define  DUK__FLD_SIGNED       (1 << 4)
#define  DUK__FLD_TYPEDARRAY   (1 << 5)

/* XXX: split into separate functions for each field type? */
DUK_INTERNAL duk_ret_t duk_bi_buffer_readfield(duk_hthread *thr) {
	duk_small_uint_t magic = (duk_small_uint_t) duk_get_current_magic(thr);
	duk_small_uint_t magic_ftype;
	duk_small_uint_t magic_bigendian;
	duk_small_uint_t magic_signed;
	duk_small_uint_t magic_typedarray;
	duk_small_uint_t endswap;
	duk_hbufobj *h_this;
	duk_bool_t no_assert;
	duk_int_t offset_signed;
	duk_uint_t offset;
	duk_uint_t buffer_length;
	duk_uint_t check_length;
	duk_uint8_t *buf;
	duk_double_union du;

	magic_ftype = magic & 0x0007U;
	magic_bigendian = magic & 0x0008U;
	magic_signed = magic & 0x0010U;
	magic_typedarray = magic & 0x0020U;

	h_this = duk__require_bufobj_this(thr);  /* XXX: very inefficient for plain buffers */
	DUK_ASSERT(h_this != NULL);
	buffer_length = h_this->length;

	/* [ offset noAssert                 ], when ftype != DUK__FLD_VARINT */
	/* [ offset fieldByteLength noAssert ], when ftype == DUK__FLD_VARINT */
	/* [ offset littleEndian             ], when DUK__FLD_TYPEDARRAY (regardless of ftype) */

	/* Handle TypedArray vs. Node.js Buffer arg differences */
	if (magic_typedarray) {
		no_assert = 0;
#if defined(DUK_USE_INTEGER_LE)
		endswap = !duk_to_boolean(thr, 1);  /* 1=little endian */
#else
		endswap = duk_to_boolean(thr, 1);  /* 1=little endian */
#endif
	} else {
		no_assert = duk_to_boolean(thr, (magic_ftype == DUK__FLD_VARINT) ? 2 : 1);
#if defined(DUK_USE_INTEGER_LE)
		endswap = magic_bigendian;
#else
		endswap = !magic_bigendian;
#endif
	}

	/* Offset is coerced first to signed integer range and then to unsigned.
	 * This ensures we can add a small byte length (1-8) to the offset in
	 * bound checks and not wrap.
	 */
	offset_signed = duk_to_int(thr, 0);
	offset = (duk_uint_t) offset_signed;
	if (offset_signed < 0) {
		goto fail_bounds;
	}

	DUK_DDD(DUK_DDDPRINT("readfield, buffer_length=%ld, offset=%ld, no_assert=%d, "
	                     "magic=%04x, magic_fieldtype=%d, magic_bigendian=%d, magic_signed=%d, "
	                     "endswap=%u",
	                     (long) buffer_length, (long) offset, (int) no_assert,
	                     (unsigned int) magic, (int) magic_ftype, (int) (magic_bigendian >> 3),
	                     (int) (magic_signed >> 4), (int) endswap));

	/* Update 'buffer_length' to be the effective, safe limit which
	 * takes into account the underlying buffer.  This value will be
	 * potentially invalidated by any side effect.
	 */
	check_length = DUK_HBUFOBJ_CLAMP_BYTELENGTH(h_this, buffer_length);
	DUK_DDD(DUK_DDDPRINT("buffer_length=%ld, check_length=%ld",
	                     (long) buffer_length, (long) check_length));

	if (h_this->buf) {
		buf = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this);
	} else {
		/* Neutered.  We could go into the switch-case safely with
		 * buf == NULL because check_length == 0.  To avoid scanbuild
		 * warnings, fail directly instead.
		 */
		DUK_ASSERT(check_length == 0);
		goto fail_neutered;
	}
	DUK_ASSERT(buf != NULL);

	switch (magic_ftype) {
	case DUK__FLD_8BIT: {
		duk_uint8_t tmp;
		if (offset + 1U > check_length) {
			goto fail_bounds;
		}
		tmp = buf[offset];
		if (magic_signed) {
			duk_push_int(thr, (duk_int_t) ((duk_int8_t) tmp));
		} else {
			duk_push_uint(thr, (duk_uint_t) tmp);
		}
		break;
	}
	case DUK__FLD_16BIT: {
		duk_uint16_t tmp;
		if (offset + 2U > check_length) {
			goto fail_bounds;
		}
		duk_memcpy((void *) du.uc, (const void *) (buf + offset), 2);
		tmp = du.us[0];
		if (endswap) {
			tmp = DUK_BSWAP16(tmp);
		}
		if (magic_signed) {
			duk_push_int(thr, (duk_int_t) ((duk_int16_t) tmp));
		} else {
			duk_push_uint(thr, (duk_uint_t) tmp);
		}
		break;
	}
	case DUK__FLD_32BIT: {
		duk_uint32_t tmp;
		if (offset + 4U > check_length) {
			goto fail_bounds;
		}
		duk_memcpy((void *) du.uc, (const void *) (buf + offset), 4);
		tmp = du.ui[0];
		if (endswap) {
			tmp = DUK_BSWAP32(tmp);
		}
		if (magic_signed) {
			duk_push_int(thr, (duk_int_t) ((duk_int32_t) tmp));
		} else {
			duk_push_uint(thr, (duk_uint_t) tmp);
		}
		break;
	}
	case DUK__FLD_FLOAT: {
		duk_uint32_t tmp;
		if (offset + 4U > check_length) {
			goto fail_bounds;
		}
		duk_memcpy((void *) du.uc, (const void *) (buf + offset), 4);
		if (endswap) {
			tmp = du.ui[0];
			tmp = DUK_BSWAP32(tmp);
			du.ui[0] = tmp;
		}
		duk_push_number(thr, (duk_double_t) du.f[0]);
		break;
	}
	case DUK__FLD_DOUBLE: {
		if (offset + 8U > check_length) {
			goto fail_bounds;
		}
		duk_memcpy((void *) du.uc, (const void *) (buf + offset), 8);
		if (endswap) {
			DUK_DBLUNION_BSWAP64(&du);
		}
		duk_push_number(thr, (duk_double_t) du.d);
		break;
	}
	case DUK__FLD_VARINT: {
		/* Node.js Buffer variable width integer field.  We don't really
		 * care about speed here, so aim for shortest algorithm.
		 */
		duk_int_t field_bytelen;
		duk_int_t i, i_step, i_end;
#if defined(DUK_USE_64BIT_OPS)
		duk_int64_t tmp;
		duk_small_uint_t shift_tmp;
#else
		duk_double_t tmp;
		duk_small_int_t highbyte;
#endif
		const duk_uint8_t *p;

		field_bytelen = duk_get_int(thr, 1);  /* avoid side effects! */
		if (field_bytelen < 1 || field_bytelen > 6) {
			goto fail_field_length;
		}
		if (offset + (duk_uint_t) field_bytelen > check_length) {
			goto fail_bounds;
		}
		p = (const duk_uint8_t *) (buf + offset);

		/* Slow gathering of value using either 64-bit arithmetic
		 * or IEEE doubles if 64-bit types not available.  Handling
		 * of negative numbers is a bit non-obvious in both cases.
		 */

		if (magic_bigendian) {
			/* Gather in big endian */
			i = 0;
			i_step = 1;
			i_end = field_bytelen;  /* one i_step over */
		} else {
			/* Gather in little endian */
			i = field_bytelen - 1;
			i_step = -1;
			i_end = -1;  /* one i_step over */
		}

#if defined(DUK_USE_64BIT_OPS)
		tmp = 0;
		do {
			DUK_ASSERT(i >= 0 && i < field_bytelen);
			tmp = (tmp << 8) + (duk_int64_t) p[i];
			i += i_step;
		} while (i != i_end);

		if (magic_signed) {
			/* Shift to sign extend.  Left shift must be unsigned
			 * to avoid undefined behavior; right shift must be
			 * signed to sign extend properly.
			 */
			shift_tmp = (duk_small_uint_t) (64U - (duk_small_uint_t) field_bytelen * 8U);
			tmp = (duk_int64_t) ((duk_uint64_t) tmp << shift_tmp) >> shift_tmp;
		}

		duk_push_i64(thr, tmp);
#else
		highbyte = p[i];
		if (magic_signed && (highbyte & 0x80) != 0) {
			/* 0xff => 255 - 256 = -1; 0x80 => 128 - 256 = -128 */
			tmp = (duk_double_t) (highbyte - 256);
		} else {
			tmp = (duk_double_t) highbyte;
		}
		for (;;) {
			i += i_step;
			if (i == i_end) {
				break;
			}
			DUK_ASSERT(i >= 0 && i < field_bytelen);
			tmp = (tmp * 256.0) + (duk_double_t) p[i];
		}

		duk_push_number(thr, tmp);
#endif
		break;
	}
	default: {  /* should never happen but default here */
		goto fail_bounds;
	}
	}

	return 1;

 fail_neutered:
 fail_field_length:
 fail_bounds:
	if (no_assert) {
		/* Node.js return value for noAssert out-of-bounds reads is
		 * usually (but not always) NaN.  Return NaN consistently.
		 */
		duk_push_nan(thr);
		return 1;
	}
	DUK_DCERROR_RANGE_INVALID_ARGS(thr);
}
#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */

#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
/* XXX: split into separate functions for each field type? */
DUK_INTERNAL duk_ret_t duk_bi_buffer_writefield(duk_hthread *thr) {
	duk_small_uint_t magic = (duk_small_uint_t) duk_get_current_magic(thr);
	duk_small_uint_t magic_ftype;
	duk_small_uint_t magic_bigendian;
	duk_small_uint_t magic_signed;
	duk_small_uint_t magic_typedarray;
	duk_small_uint_t endswap;
	duk_hbufobj *h_this;
	duk_bool_t no_assert;
	duk_int_t offset_signed;
	duk_uint_t offset;
	duk_uint_t buffer_length;
	duk_uint_t check_length;
	duk_uint8_t *buf;
	duk_double_union du;
	duk_int_t nbytes = 0;

	magic_ftype = magic & 0x0007U;
	magic_bigendian = magic & 0x0008U;
	magic_signed = magic & 0x0010U;
	magic_typedarray = magic & 0x0020U;
	DUK_UNREF(magic_signed);

	h_this = duk__require_bufobj_this(thr);  /* XXX: very inefficient for plain buffers */
	DUK_ASSERT(h_this != NULL);
	buffer_length = h_this->length;

	/* [ value  offset noAssert                 ], when ftype != DUK__FLD_VARINT */
	/* [ value  offset fieldByteLength noAssert ], when ftype == DUK__FLD_VARINT */
	/* [ offset value  littleEndian             ], when DUK__FLD_TYPEDARRAY (regardless of ftype) */

	/* Handle TypedArray vs. Node.js Buffer arg differences */
	if (magic_typedarray) {
		no_assert = 0;
#if defined(DUK_USE_INTEGER_LE)
		endswap = !duk_to_boolean(thr, 2);  /* 1=little endian */
#else
		endswap = duk_to_boolean(thr, 2);  /* 1=little endian */
#endif
		duk_swap(thr, 0, 1);  /* offset/value order different from Node.js */
	} else {
		no_assert = duk_to_boolean(thr, (magic_ftype == DUK__FLD_VARINT) ? 3 : 2);
#if defined(DUK_USE_INTEGER_LE)
		endswap = magic_bigendian;
#else
		endswap = !magic_bigendian;
#endif
	}

	/* Offset is coerced first to signed integer range and then to unsigned.
	 * This ensures we can add a small byte length (1-8) to the offset in
	 * bound checks and not wrap.
	 */
	offset_signed = duk_to_int(thr, 1);
	offset = (duk_uint_t) offset_signed;

	/* We need 'nbytes' even for a failed offset; return value must be
	 * (offset + nbytes) even when write fails due to invalid offset.
	 */
	if (magic_ftype != DUK__FLD_VARINT) {
		DUK_ASSERT(magic_ftype < (duk_small_uint_t) (sizeof(duk__buffer_nbytes_from_fldtype) / sizeof(duk_uint8_t)));
		nbytes = duk__buffer_nbytes_from_fldtype[magic_ftype];
	} else {
		nbytes = duk_get_int(thr, 2);
		if (nbytes < 1 || nbytes > 6) {
			goto fail_field_length;
		}
	}
	DUK_ASSERT(nbytes >= 1 && nbytes <= 8);

	/* Now we can check offset validity. */
	if (offset_signed < 0) {
		goto fail_bounds;
	}

	DUK_DDD(DUK_DDDPRINT("writefield, value=%!T, buffer_length=%ld, offset=%ld, no_assert=%d, "
	                     "magic=%04x, magic_fieldtype=%d, magic_bigendian=%d, magic_signed=%d, "
	                     "endswap=%u",
	                     duk_get_tval(thr, 0), (long) buffer_length, (long) offset, (int) no_assert,
	                     (unsigned int) magic, (int) magic_ftype, (int) (magic_bigendian >> 3),
	                     (int) (magic_signed >> 4), (int) endswap));

	/* Coerce value to a number before computing check_length, so that
	 * the field type specific coercion below can't have side effects
	 * that would invalidate check_length.
	 */
	duk_to_number(thr, 0);

	/* Update 'buffer_length' to be the effective, safe limit which
	 * takes into account the underlying buffer.  This value will be
	 * potentially invalidated by any side effect.
	 */
	check_length = DUK_HBUFOBJ_CLAMP_BYTELENGTH(h_this, buffer_length);
	DUK_DDD(DUK_DDDPRINT("buffer_length=%ld, check_length=%ld",
	                     (long) buffer_length, (long) check_length));

	if (h_this->buf) {
		buf = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this);
	} else {
		/* Neutered.  We could go into the switch-case safely with
		 * buf == NULL because check_length == 0.  To avoid scanbuild
		 * warnings, fail directly instead.
		 */
		DUK_ASSERT(check_length == 0);
		goto fail_neutered;
	}
	DUK_ASSERT(buf != NULL);

	switch (magic_ftype) {
	case DUK__FLD_8BIT: {
		if (offset + 1U > check_length) {
			goto fail_bounds;
		}
		/* sign doesn't matter when writing */
		buf[offset] = (duk_uint8_t) duk_to_uint32(thr, 0);
		break;
	}
	case DUK__FLD_16BIT: {
		duk_uint16_t tmp;
		if (offset + 2U > check_length) {
			goto fail_bounds;
		}
		tmp = (duk_uint16_t) duk_to_uint32(thr, 0);
		if (endswap) {
			tmp = DUK_BSWAP16(tmp);
		}
		du.us[0] = tmp;
		/* sign doesn't matter when writing */
		duk_memcpy((void *) (buf + offset), (const void *) du.uc, 2);
		break;
	}
	case DUK__FLD_32BIT: {
		duk_uint32_t tmp;
		if (offset + 4U > check_length) {
			goto fail_bounds;
		}
		tmp = (duk_uint32_t) duk_to_uint32(thr, 0);
		if (endswap) {
			tmp = DUK_BSWAP32(tmp);
		}
		du.ui[0] = tmp;
		/* sign doesn't matter when writing */
		duk_memcpy((void *) (buf + offset), (const void *) du.uc, 4);
		break;
	}
	case DUK__FLD_FLOAT: {
		duk_uint32_t tmp;
		if (offset + 4U > check_length) {
			goto fail_bounds;
		}
		du.f[0] = (duk_float_t) duk_to_number(thr, 0);
		if (endswap) {
			tmp = du.ui[0];
			tmp = DUK_BSWAP32(tmp);
			du.ui[0] = tmp;
		}
		/* sign doesn't matter when writing */
		duk_memcpy((void *) (buf + offset), (const void *) du.uc, 4);
		break;
	}
	case DUK__FLD_DOUBLE: {
		if (offset + 8U > check_length) {
			goto fail_bounds;
		}
		du.d = (duk_double_t) duk_to_number(thr, 0);
		if (endswap) {
			DUK_DBLUNION_BSWAP64(&du);
		}
		/* sign doesn't matter when writing */
		duk_memcpy((void *) (buf + offset), (const void *) du.uc, 8);
		break;
	}
	case DUK__FLD_VARINT: {
		/* Node.js Buffer variable width integer field.  We don't really
		 * care about speed here, so aim for shortest algorithm.
		 */
		duk_int_t field_bytelen;
		duk_int_t i, i_step, i_end;
#if defined(DUK_USE_64BIT_OPS)
		duk_int64_t tmp;
#else
		duk_double_t tmp;
#endif
		duk_uint8_t *p;

		field_bytelen = (duk_int_t) nbytes;
		if (offset + (duk_uint_t) field_bytelen > check_length) {
			goto fail_bounds;
		}

		/* Slow writing of value using either 64-bit arithmetic
		 * or IEEE doubles if 64-bit types not available.  There's
		 * no special sign handling when writing varints.
		 */

		if (magic_bigendian) {
			/* Write in big endian */
			i = field_bytelen;  /* one i_step added at top of loop */
			i_step = -1;
			i_end = 0;
		} else {
			/* Write in little endian */
			i = -1;  /* one i_step added at top of loop */
			i_step = 1;
			i_end = field_bytelen - 1;
		}

		/* XXX: The duk_to_number() cast followed by integer coercion
		 * is platform specific so NaN, +/- Infinity, and out-of-bounds
		 * values result in platform specific output now.
		 * See: test-bi-nodejs-buffer-proto-varint-special.js
		 */

#if defined(DUK_USE_64BIT_OPS)
		tmp = (duk_int64_t) duk_to_number(thr, 0);
		p = (duk_uint8_t *) (buf + offset);
		do {
			i += i_step;
			DUK_ASSERT(i >= 0 && i < field_bytelen);
			p[i] = (duk_uint8_t) (tmp & 0xff);
			tmp = tmp >> 8;  /* unnecessary shift for last byte */
		} while (i != i_end);
#else
		tmp = duk_to_number(thr, 0);
		p = (duk_uint8_t *) (buf + offset);
		do {
			i += i_step;
			tmp = DUK_FLOOR(tmp);
			DUK_ASSERT(i >= 0 && i < field_bytelen);
			p[i] = (duk_uint8_t) (DUK_FMOD(tmp, 256.0));
			tmp = tmp / 256.0;  /* unnecessary div for last byte */
		} while (i != i_end);
#endif
		break;
	}
	default: {  /* should never happen but default here */
		goto fail_bounds;
	}
	}

	/* Node.js Buffer: return offset + #bytes written (i.e. next
	 * write offset).
	 */
	if (magic_typedarray) {
		/* For TypedArrays 'undefined' return value is specified
		 * by ES2015 (matches V8).
		 */
		return 0;
	}
	duk_push_uint(thr, offset + (duk_uint_t) nbytes);
	return 1;

 fail_neutered:
 fail_field_length:
 fail_bounds:
	if (no_assert) {
		/* Node.js return value for failed writes is offset + #bytes
		 * that would have been written.
		 */
		/* XXX: for negative input offsets, 'offset' will be a large
		 * positive value so the result here is confusing.
		 */
		if (magic_typedarray) {
			return 0;
		}
		duk_push_uint(thr, offset + (duk_uint_t) nbytes);
		return 1;
	}
	DUK_DCERROR_RANGE_INVALID_ARGS(thr);
}
#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */

/*
 *  Accessors for .buffer, .byteLength, .byteOffset
 */

#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
DUK_LOCAL duk_hbufobj *duk__autospawn_arraybuffer(duk_hthread *thr, duk_hbuffer *h_buf) {
	duk_hbufobj *h_res;

	h_res = duk_push_bufobj_raw(thr,
	                            DUK_HOBJECT_FLAG_EXTENSIBLE |
	                            DUK_HOBJECT_FLAG_BUFOBJ |
	                            DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAYBUFFER),
	                            DUK_BIDX_ARRAYBUFFER_PROTOTYPE);
	DUK_ASSERT(h_res != NULL);
	DUK_UNREF(h_res);

	duk__set_bufobj_buffer(thr, h_res, h_buf);
	DUK_HBUFOBJ_ASSERT_VALID(h_res);
	DUK_ASSERT(h_res->buf_prop == NULL);
	return h_res;
}

DUK_INTERNAL duk_ret_t duk_bi_typedarray_buffer_getter(duk_hthread *thr) {
	duk_hbufobj *h_bufobj;

	h_bufobj = (duk_hbufobj *) duk__getrequire_bufobj_this(thr, DUK__BUFOBJ_FLAG_THROW /*flags*/);
	DUK_ASSERT(h_bufobj != NULL);
	if (DUK_HEAPHDR_IS_BUFFER((duk_heaphdr *) h_bufobj)) {
		DUK_DD(DUK_DDPRINT("autospawn ArrayBuffer for plain buffer"));
		(void) duk__autospawn_arraybuffer(thr, (duk_hbuffer *) h_bufobj);
		return 1;
	} else {
		if (h_bufobj->buf_prop == NULL &&
		    DUK_HOBJECT_GET_CLASS_NUMBER((duk_hobject *) h_bufobj) != DUK_HOBJECT_CLASS_ARRAYBUFFER &&
		    h_bufobj->buf != NULL) {
			duk_hbufobj *h_arrbuf;

			DUK_DD(DUK_DDPRINT("autospawn ArrayBuffer for typed array or DataView"));
			h_arrbuf = duk__autospawn_arraybuffer(thr, h_bufobj->buf);

			if (h_bufobj->buf_prop == NULL) {
				/* Must recheck buf_prop, in case ArrayBuffer
				 * alloc had a side effect which already filled
				 * it!
				 */

				/* Set ArrayBuffer's .byteOffset and .byteLength based
				 * on the view so that Arraybuffer[view.byteOffset]
				 * matches view[0].
				 */
				h_arrbuf->offset = 0;
				DUK_ASSERT(h_bufobj->offset + h_bufobj->length >= h_bufobj->offset);  /* Wrap check on creation. */
				h_arrbuf->length = h_bufobj->offset + h_bufobj->length;
				DUK_ASSERT(h_arrbuf->buf_prop == NULL);

				DUK_ASSERT(h_bufobj->buf_prop == NULL);
				h_bufobj->buf_prop = (duk_hobject *) h_arrbuf;
				DUK_HBUFOBJ_INCREF(thr, h_arrbuf);  /* Now reachable and accounted for. */
			}

			/* Left on stack; pushed for the second time below (OK). */
		}
		if (h_bufobj->buf_prop) {
			duk_push_hobject(thr, h_bufobj->buf_prop);
			return 1;
		}
	}
	return 0;
}

DUK_INTERNAL duk_ret_t duk_bi_typedarray_byteoffset_getter(duk_hthread *thr) {
	duk_hbufobj *h_bufobj;

	h_bufobj = (duk_hbufobj *) duk__getrequire_bufobj_this(thr, DUK__BUFOBJ_FLAG_THROW /*flags*/);
	DUK_ASSERT(h_bufobj != NULL);
	if (DUK_HEAPHDR_IS_BUFFER((duk_heaphdr *) h_bufobj)) {
		duk_push_uint(thr, 0);
	} else {
		/* If neutered must return 0; offset is zeroed during
		 * neutering.
		 */
		duk_push_uint(thr, h_bufobj->offset);
	}
	return 1;
}

DUK_INTERNAL duk_ret_t duk_bi_typedarray_bytelength_getter(duk_hthread *thr) {
	duk_hbufobj *h_bufobj;

	h_bufobj = (duk_hbufobj *) duk__getrequire_bufobj_this(thr, DUK__BUFOBJ_FLAG_THROW /*flags*/);
	DUK_ASSERT(h_bufobj != NULL);
	if (DUK_HEAPHDR_IS_BUFFER((duk_heaphdr *) h_bufobj)) {
		duk_hbuffer *h_buf;

		h_buf = (duk_hbuffer *) h_bufobj;
		DUK_ASSERT(DUK_HBUFFER_GET_SIZE(h_buf) <= DUK_UINT_MAX);  /* Buffer limits. */
		duk_push_uint(thr, (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_buf));
	} else {
		/* If neutered must return 0; length is zeroed during
		 * neutering.
		 */
		duk_push_uint(thr, h_bufobj->length);
	}
	return 1;
}
#else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
/* No .buffer getter without ArrayBuffer support. */
#if 0
DUK_INTERNAL duk_ret_t duk_bi_typedarray_buffer_getter(duk_hthread *thr) {
	return 0;
}
#endif

DUK_INTERNAL duk_ret_t duk_bi_typedarray_byteoffset_getter(duk_hthread *thr) {
	duk_push_uint(thr, 0);
	return 1;
}

DUK_INTERNAL duk_ret_t duk_bi_typedarray_bytelength_getter(duk_hthread *thr) {
	duk_hbuffer *h_buf;

	/* XXX: helper? */
	duk_push_this(thr);
	h_buf = duk_require_hbuffer(thr, -1);
	duk_push_uint(thr, DUK_HBUFFER_GET_SIZE(h_buf));
	return 1;
}
#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */

/* automatic undefs */
#undef DUK__BUFOBJ_FLAG_PROMOTE
#undef DUK__BUFOBJ_FLAG_THROW
#undef DUK__FLD_16BIT
#undef DUK__FLD_32BIT
#undef DUK__FLD_8BIT
#undef DUK__FLD_BIGENDIAN
#undef DUK__FLD_DOUBLE
#undef DUK__FLD_FLOAT
#undef DUK__FLD_SIGNED
#undef DUK__FLD_TYPEDARRAY
#undef DUK__FLD_VARINT
#line 1 "duk_bi_cbor.c"
/*
 *  CBOR bindings.
 *
 *  http://cbor.io/
 *  https://tools.ietf.org/html/rfc7049
 */

/* #include duk_internal.h -> already included */

#if defined(DUK_USE_CBOR_SUPPORT)

/* #define DUK_CBOR_STRESS */

/* Default behavior for encoding strings: use CBOR text string if string
 * is UTF-8 compatible, otherwise use CBOR byte string.  These defines
 * can be used to force either type for all strings.  Using text strings
 * for non-UTF-8 data is technically invalid CBOR.
 */
/* #define DUK_CBOR_TEXT_STRINGS */
/* #define DUK_CBOR_BYTE_STRINGS */

/* Misc. defines. */
/* #define DUK_CBOR_PREFER_SIZE */
/* #define DUK_CBOR_DOUBLE_AS_IS */
/* #define DUK_CBOR_DECODE_FASTPATH */

typedef struct {
	duk_hthread *thr;
	duk_uint8_t *ptr;
	duk_uint8_t *buf;
	duk_uint8_t *buf_end;
	duk_size_t len;
	duk_idx_t idx_buf;
} duk_cbor_encode_context;

typedef struct {
	duk_hthread *thr;
	const duk_uint8_t *buf;
	duk_size_t off;
	duk_size_t len;
} duk_cbor_decode_context;

DUK_LOCAL void duk__cbor_encode_value(duk_cbor_encode_context *enc_ctx);
DUK_LOCAL void duk__cbor_decode_value(duk_cbor_decode_context *dec_ctx);

/*
 *  Misc
 */

DUK_LOCAL duk_uint32_t duk__cbor_double_to_uint32(double d) {
	/* Out of range casts are undefined behavior, so caller must avoid. */
	DUK_ASSERT(d >= 0.0 && d <= 4294967295.0);
	return (duk_uint32_t) d;
}

/*
 *  Encoding
 */

DUK_LOCAL void duk__cbor_encode_error(duk_cbor_encode_context *enc_ctx) {
	(void) duk_type_error(enc_ctx->thr, "cbor encode error");
}

/* Check that a size_t is in uint32 range to avoid out-of-range casts. */
DUK_LOCAL void duk__cbor_encode_sizet_uint32_check(duk_cbor_encode_context *enc_ctx, duk_size_t len) {
	if (DUK_UNLIKELY(sizeof(duk_size_t) > sizeof(duk_uint32_t) && len > (duk_size_t) DUK_UINT32_MAX)) {
		duk__cbor_encode_error(enc_ctx);
	}
}

DUK_LOCAL DUK_NOINLINE void duk__cbor_encode_ensure_slowpath(duk_cbor_encode_context *enc_ctx, duk_size_t len) {
	duk_size_t oldlen;
	duk_size_t minlen;
	duk_size_t newlen;
	duk_uint8_t *p_new;
	duk_size_t old_data_len;

	DUK_ASSERT(enc_ctx->ptr >= enc_ctx->buf);
	DUK_ASSERT(enc_ctx->buf_end >= enc_ctx->ptr);
	DUK_ASSERT(enc_ctx->buf_end >= enc_ctx->buf);

	/* Overflow check.
	 *
	 * Limit example: 0xffffffffUL / 2U = 0x7fffffffUL, we reject >= 0x80000000UL.
	 */
	oldlen = enc_ctx->len;
	minlen = oldlen + len;
	if (DUK_UNLIKELY(oldlen > DUK_SIZE_MAX / 2U || minlen < oldlen)) {
		duk__cbor_encode_error(enc_ctx);
	}

#if defined(DUK_CBOR_STRESS)
	newlen = oldlen + 1U;
#else
	newlen = oldlen * 2U;
#endif
	DUK_ASSERT(newlen >= oldlen);

	if (minlen > newlen) {
		newlen = minlen;
	}
	DUK_ASSERT(newlen >= oldlen);
	DUK_ASSERT(newlen >= minlen);
	DUK_ASSERT(newlen > 0U);

	DUK_DD(DUK_DDPRINT("cbor encode buffer resized to %ld", (long) newlen));

	p_new = (duk_uint8_t *) duk_resize_buffer(enc_ctx->thr, enc_ctx->idx_buf, newlen);
	DUK_ASSERT(p_new != NULL);
	old_data_len = (duk_size_t) (enc_ctx->ptr - enc_ctx->buf);
	enc_ctx->buf = p_new;
	enc_ctx->buf_end = p_new + newlen;
	enc_ctx->ptr = p_new + old_data_len;
	enc_ctx->len = newlen;
}

DUK_LOCAL DUK_INLINE void duk__cbor_encode_ensure(duk_cbor_encode_context *enc_ctx, duk_size_t len) {
	if (DUK_LIKELY((duk_size_t) (enc_ctx->buf_end - enc_ctx->ptr) >= len)) {
		return;
	}
	duk__cbor_encode_ensure_slowpath(enc_ctx, len);
}

DUK_LOCAL duk_size_t duk__cbor_get_reserve(duk_cbor_encode_context *enc_ctx) {
	DUK_ASSERT(enc_ctx->ptr >= enc_ctx->buf);
	DUK_ASSERT(enc_ctx->ptr <= enc_ctx->buf_end);
	return (duk_size_t) (enc_ctx->buf_end - enc_ctx->ptr);
}

DUK_LOCAL void duk__cbor_encode_uint32(duk_cbor_encode_context *enc_ctx, duk_uint32_t u, duk_uint8_t base) {
	duk_uint8_t *p;

	/* Caller must ensure space. */
	DUK_ASSERT(duk__cbor_get_reserve(enc_ctx) >= 1 + 4);

	p = enc_ctx->ptr;
	if (DUK_LIKELY(u <= 23U)) {
		*p++ = (duk_uint8_t) (base + (duk_uint8_t) u);
	} else if (u <= 0xffUL) {
		*p++ = base + 0x18U;
		*p++ = (duk_uint8_t) u;
	} else if (u <= 0xffffUL) {
		*p++ = base + 0x19U;
		DUK_RAW_WRITEINC_U16_BE(p, (duk_uint16_t) u);
	} else {
		*p++ = base + 0x1aU;
		DUK_RAW_WRITEINC_U32_BE(p, u);
	}
	enc_ctx->ptr = p;
}

#if defined(DUK_CBOR_DOUBLE_AS_IS)
DUK_LOCAL void duk__cbor_encode_double(duk_cbor_encode_context *enc_ctx, double d) {
	duk_uint8_t *p;

	/* Caller must ensure space. */
	DUK_ASSERT(duk__cbor_get_reserve(enc_ctx) >= 1 + 8);

	p = enc_ctx->ptr;
	*p++ = 0xfbU;
	DUK_RAW_WRITEINC_DOUBLE_BE(p, d);
	p += 8;
	enc_ctx->ptr = p;
}
#else  /* DUK_CBOR_DOUBLE_AS_IS */
DUK_LOCAL void duk__cbor_encode_double_fp(duk_cbor_encode_context *enc_ctx, double d) {
	duk_double_union u;
	duk_uint16_t u16;
	duk_int16_t expt;
	duk_uint8_t *p;

	DUK_ASSERT(DUK_FPCLASSIFY(d) != DUK_FP_ZERO);

	/* Caller must ensure space. */
	DUK_ASSERT(duk__cbor_get_reserve(enc_ctx) >= 1 + 8);

	/* Organize into little endian (no-op if platform is little endian). */
	u.d = d;
	duk_dblunion_host_to_little(&u);

	/* Check if 'd' can represented as a normal half-float.
	 * Denormal half-floats could also be used, but that check
	 * isn't done now (denormal half-floats are decoded of course).
	 * So just check exponent range and that at most 10 significant
	 * bits (excluding implicit leading 1) are used in 'd'.
	 */
	u16 = (((duk_uint16_t) u.uc[7]) << 8) | ((duk_uint16_t) u.uc[6]);
	expt = (duk_int16_t) ((u16 & 0x7ff0U) >> 4) - 1023;

	if (expt >= -14 && expt <= 15) {
		/* Half-float normal exponents (excl. denormals).
		 *
		 *          7        6        5        4        3        2        1        0  (LE index)
		 * double: seeeeeee eeeemmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm
		 * half:         seeeee mmmm mmmmmm00 00000000 00000000 00000000 00000000 00000000
		 */
		duk_bool_t use_half_float;

		use_half_float =
		    (u.uc[0] == 0 && u.uc[1] == 0 && u.uc[2] == 0 && u.uc[3] == 0 &&
		     u.uc[4] == 0 && (u.uc[5] & 0x03U) == 0);

		if (use_half_float) {
			duk_uint32_t t;

			expt += 15;
			t = (duk_uint32_t) (u.uc[7] & 0x80U) << 8;
			t += (duk_uint32_t) expt << 10;
			t += ((duk_uint32_t) u.uc[6] & 0x0fU) << 6;
			t += ((duk_uint32_t) u.uc[5]) >> 2;

			/* seeeeemm mmmmmmmm */
			p = enc_ctx->ptr;
			*p++ = 0xf9U;
			DUK_RAW_WRITEINC_U16_BE(p, (duk_uint16_t) t);
			enc_ctx->ptr = p;
			return;
		}
	}

	/* Same check for plain float.  Also no denormal support here. */
	if (expt >= -126 && expt <= 127) {
		/* Float normal exponents (excl. denormals).
		 *
		 * double: seeeeeee eeeemmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm
		 * float:     seeee eeeemmmm mmmmmmmm mmmmmmmm mmm00000 00000000 00000000 00000000
		 */
		duk_bool_t use_float;
		duk_float_t d_float;

		/* We could do this explicit mantissa check, but doing
		 * a double-float-double cast is fine because we've
		 * already verified that the exponent is in range so
		 * that the narrower cast is not undefined behavior.
		 */
#if 0
		use_float =
		    (u.uc[0] == 0 && u.uc[1] == 0 && u.uc[2] == 0 && (u.uc[3] & 0xe0U) == 0);
#endif
		d_float = (duk_float_t) d;
		use_float = duk_double_equals((duk_double_t) d_float, d);
		if (use_float) {
			p = enc_ctx->ptr;
			*p++ = 0xfaU;
			DUK_RAW_WRITEINC_FLOAT_BE(p, d_float);
			enc_ctx->ptr = p;
			return;
		}
	}

	/* Special handling for NaN and Inf which we want to encode as
	 * half-floats.  They share the same (maximum) exponent.
	 */
	if (expt == 1024) {
		DUK_ASSERT(DUK_ISNAN(d) || DUK_ISINF(d));
		p = enc_ctx->ptr;
		*p++ = 0xf9U;
		if (DUK_ISNAN(d)) {
			/* Shortest NaN encoding is using a half-float.  Lose the
			 * exact NaN bits in the process.  IEEE double would be
			 * 7ff8 0000 0000 0000, i.e. a quiet NaN in most architectures
			 * (https://en.wikipedia.org/wiki/NaN#Encoding).  The
			 * equivalent half float is 7e00.
			 */
			*p++ = 0x7eU;
		} else {
			/* Shortest +/- Infinity encoding is using a half-float. */
			if (DUK_SIGNBIT(d)) {
				*p++ = 0xfcU;
			} else {
				*p++ = 0x7cU;
			}
		}
		*p++ = 0x00U;
		enc_ctx->ptr = p;
		return;
	}

	/* Cannot use half-float or float, encode as full IEEE double. */
	p = enc_ctx->ptr;
	*p++ = 0xfbU;
	DUK_RAW_WRITEINC_DOUBLE_BE(p, d);
	enc_ctx->ptr = p;
}

DUK_LOCAL void duk__cbor_encode_double(duk_cbor_encode_context *enc_ctx, double d) {
	duk_uint8_t *p;
	double d_floor;

	/* Integers and floating point values of all types are conceptually
	 * equivalent in CBOR.  Try to always choose the shortest encoding
	 * which is not always immediately obvious.  For example, NaN and Inf
	 * can be most compactly represented as a half-float (assuming NaN
	 * bits are not preserved), and 0x1'0000'0000 as a single precision
	 * float.  Shortest forms in preference order (prefer integer over
	 * float when equal length):
	 *
	 *   uint        1 byte    [0,23] (not -0)
	 *   sint        1 byte    [-24,-1]
	 *   uint+1      2 bytes   [24,255]
	 *   sint+1      2 bytes   [-256,-25]
	 *   uint+2      3 bytes   [256,65535]
	 *   sint+2      3 bytes   [-65536,-257]
	 *   half-float  3 bytes   -0, NaN, +/- Infinity, range [-65504,65504]
	 *   uint+4      5 bytes   [65536,4294967295]
	 *   sint+4      5 bytes   [-4294967296,-258]
	 *   float       5 bytes   range [-(1 - 2^(-24)) * 2^128, (1 - 2^(-24)) * 2^128]
	 *   uint+8      9 bytes   [4294967296,18446744073709551615]
	 *   sint+8      9 bytes   [-18446744073709551616,-4294967297]
	 *   double      9 bytes
	 *
	 * For whole numbers (compatible with integers):
	 *   - 1-byte or 2-byte uint/sint representation is preferred for
	 *     [-256,255].
	 *   - 3-byte uint/sint is preferred for [-65536,65535].  Half floats
	 *     are never preferred because they have the same length.
	 *   - 5-byte uint/sint is preferred for [-4294967296,4294967295].
	 *     Single precision floats are never preferred, and half-floats
	 *     don't reach above the 3-byte uint/sint range so they're never
	 *     preferred.
	 *   - So, for all integers up to signed/unsigned 32-bit range the
	 *     preferred encoding is always an integer uint/sint.
	 *   - For integers above 32 bits the situation is more complicated.
	 *     Half-floats are never useful for them because of their limited
	 *     range, but IEEE single precision floats (5 bytes encoded) can
	 *     represent some integers between the 32-bit and 64-bit ranges
	 *     which require 9 bytes as a uint/sint.
	 *
	 * For floating point values not compatible with integers, the
	 * preferred encoding is quite clear:
	 *   - For +Inf/-Inf use half-float.
	 *   - For NaN use a half-float, assuming NaN bits ("payload") is
	 *     not worth preserving.  Duktape doesn't in general guarantee
	 *     preservation of the NaN payload so using a half-float seems
	 *     consistent with that.
	 *   - For remaining values, prefer the shortest form which doesn't
	 *     lose any precision.  For normal half-floats and single precision
	 *     floats this is simple: just check exponent and mantissa bits
	 *     using a fixed mask.  For denormal half-floats and single
	 *     precision floats the check is a bit more complicated: a normal
	 *     IEEE double can sometimes be represented as a denormal
	 *     half-float or single precision float.
	 *
	 * https://en.wikipedia.org/wiki/Half-precision_floating-point_format#IEEE_754_half-precision_binary_floating-point_format:_binary16
	 */

	/* Caller must ensure space. */
	DUK_ASSERT(duk__cbor_get_reserve(enc_ctx) >= 1 + 8);

	/* Most important path is integers.  The floor() test will be true
	 * for Inf too (but not NaN).
	 */
	d_floor = DUK_FLOOR(d);  /* identity if d is +/- 0.0, NaN, or +/- Infinity */
	if (DUK_LIKELY(duk_double_equals(d_floor, d) != 0)) {
		DUK_ASSERT(!DUK_ISNAN(d));  /* NaN == NaN compares false. */
		if (DUK_SIGNBIT(d)) {
			if (d >= -4294967296.0) {
				d = -1.0 - d;
				if (d >= 0.0) {
					DUK_ASSERT(d >= 0.0);
					duk__cbor_encode_uint32(enc_ctx, duk__cbor_double_to_uint32(d), 0x20U);
					return;
				}

				/* Input was negative zero, d == -1.0 < 0.0.
				 * Shortest -0 is using half-float.
				 */
				p = enc_ctx->ptr;
				*p++ = 0xf9U;
				*p++ = 0x80U;
				*p++ = 0x00U;
				enc_ctx->ptr = p;
				return;
			}
		} else {
			if (d <= 4294967295.0) {
				/* Positive zero needs no special handling. */
				DUK_ASSERT(d >= 0.0);
				duk__cbor_encode_uint32(enc_ctx, duk__cbor_double_to_uint32(d), 0x00U);
				return;
			}
		}
	}

	/* 64-bit integers are not supported at present.  So
	 * we also don't need to deal with choosing between a
	 * 64-bit uint/sint representation vs. IEEE double or
	 * float.
	 */

	DUK_ASSERT(DUK_FPCLASSIFY(d) != DUK_FP_ZERO);
	duk__cbor_encode_double_fp(enc_ctx, d);
}
#endif  /* DUK_CBOR_DOUBLE_AS_IS */

DUK_LOCAL void duk__cbor_encode_string_top(duk_cbor_encode_context *enc_ctx) {
	const duk_uint8_t *str;
	duk_size_t len;
	duk_uint8_t *p;

	/* CBOR differentiates between UTF-8 text strings and byte strings.
	 * Text strings MUST be valid UTF-8, so not all Duktape strings can
	 * be encoded as valid CBOR text strings.  Possible behaviors:
	 *
	 *   1. Use text string when input is valid UTF-8, otherwise use
	 *      byte string (maybe tagged to indicate it was an extended
	 *      UTF-8 string).
	 *   2. Always use text strings, but sanitize input string so that
	 *      invalid UTF-8 is replaced with U+FFFD for example.  Combine
	 *      surrogates whenever possible.
	 *   3. Always use byte strings.  This is simple and produces valid
	 *      CBOR, but isn't ideal for interoperability.
	 *   4. Always use text strings, even for invalid UTF-8 such as
	 *      codepoints in the surrogate pair range.  This is simple but
	 *      produces technically invalid CBOR for non-UTF-8 strings which
	 *      may affect interoperability.
	 *
	 * Current default is 1; can be changed with defines.
	 */

	/* Caller must ensure space. */
	DUK_ASSERT(duk__cbor_get_reserve(enc_ctx) >= 1 + 8);

	str = (const duk_uint8_t *) duk_require_lstring(enc_ctx->thr, -1, &len);
	if (duk_is_symbol(enc_ctx->thr, -1)) {
		/* Symbols, encode as an empty table for now.  This matches
		 * the behavior of cbor-js.
		 *
		 * XXX: Maybe encode String() coercion with a tag?
		 * XXX: Option to keep enough information to recover
		 * Symbols when decoding (this is not always desirable).
		 */
		p = enc_ctx->ptr;
		*p++ = 0xa0U;
		enc_ctx->ptr = p;
		return;
	}

	duk__cbor_encode_sizet_uint32_check(enc_ctx, len);
#if defined(DUK_CBOR_TEXT_STRINGS)
	duk__cbor_encode_uint32(enc_ctx, (duk_uint32_t) len, 0x60U);
#elif defined(DUK_CBOR_BYTE_STRINGS)
	duk__cbor_encode_uint32(enc_ctx, (duk_uint32_t) len, 0x40U);
#else
	duk__cbor_encode_uint32(enc_ctx, (duk_uint32_t) len,
	                        (DUK_LIKELY(duk_unicode_is_utf8_compatible(str, len) != 0) ? 0x60U : 0x40U));
#endif
	duk__cbor_encode_ensure(enc_ctx, len);
	p = enc_ctx->ptr;
	duk_memcpy((void *) p, (const void *) str, len);
	p += len;
	enc_ctx->ptr = p;
}

DUK_LOCAL void duk__cbor_encode_object(duk_cbor_encode_context *enc_ctx) {
	duk_uint8_t *buf;
	duk_size_t len;
	duk_uint8_t *p;
	duk_size_t i;
	duk_size_t off_ib;
	duk_uint32_t count;

	/* Caller must ensure space. */
	DUK_ASSERT(duk__cbor_get_reserve(enc_ctx) >= 1 + 8);

	/* XXX: Support for specific built-ins like Date and RegExp. */
	if (duk_is_array(enc_ctx->thr, -1)) {
		/* Shortest encoding for arrays >= 256 in length is actually
		 * the indefinite length one (3 or more bytes vs. 2 bytes).
		 * We still use the definite length version because it is
		 * more decoding friendly.
		 */
		len = duk_get_length(enc_ctx->thr, -1);
		duk__cbor_encode_sizet_uint32_check(enc_ctx, len);
		duk__cbor_encode_uint32(enc_ctx, (duk_uint32_t) len, 0x80U);
		for (i = 0; i < len; i++) {
			duk_get_prop_index(enc_ctx->thr, -1, (duk_uarridx_t) i);
			duk__cbor_encode_value(enc_ctx);
		}
	} else if (duk_is_buffer_data(enc_ctx->thr, -1)) {
		/* XXX: Tag buffer data?
		 * XXX: Encode typed arrays as integer arrays rather
		 * than buffer data as is?
		 */
		buf = (duk_uint8_t *) duk_require_buffer_data(enc_ctx->thr, -1, &len);
		duk__cbor_encode_sizet_uint32_check(enc_ctx, len);
		duk__cbor_encode_uint32(enc_ctx, (duk_uint32_t) len, 0x40U);
		duk__cbor_encode_ensure(enc_ctx, len);
		p = enc_ctx->ptr;
		duk_memcpy((void *) p, (const void *) buf, len);
		p += len;
		enc_ctx->ptr = p;
	} else {
		/* We don't know the number of properties in advance
		 * but would still like to encode at least small
		 * objects without indefinite length.  Emit an
		 * indefinite length byte initially, and if the final
		 * property count is small enough to also fit in one
		 * byte, backpatch it later.  Otherwise keep the
		 * indefinite length.  This works well up to 23
		 * properties which is practical and good enough.
		 */
		off_ib = (duk_size_t) (enc_ctx->ptr - enc_ctx->buf);  /* XXX: get_offset? */
		count = 0U;
		p = enc_ctx->ptr;
		*p++ = 0xa0U + 0x1fU;  /* indefinite length */
		enc_ctx->ptr = p;
		duk_enum(enc_ctx->thr, -1, DUK_ENUM_OWN_PROPERTIES_ONLY);
		while (duk_next(enc_ctx->thr, -1, 1 /*get_value*/)) {
			duk_insert(enc_ctx->thr, -2);  /* [ ... key value ] -> [ ... value key ] */
			duk__cbor_encode_value(enc_ctx);
			duk__cbor_encode_value(enc_ctx);
			count++;
			if (count == 0U) {
				duk__cbor_encode_error(enc_ctx);
			}
		}
		duk_pop(enc_ctx->thr);
		if (count <= 0x17U) {
			DUK_ASSERT(off_ib < enc_ctx->len);
			enc_ctx->buf[off_ib] = 0xa0U + (duk_uint8_t) count;
		} else {
			duk__cbor_encode_ensure(enc_ctx, 1);
			p = enc_ctx->ptr;
			*p++ = 0xffU;  /* break */
			enc_ctx->ptr = p;
		}
	}
}

DUK_LOCAL void duk__cbor_encode_buffer(duk_cbor_encode_context *enc_ctx) {
	duk_uint8_t *buf;
	duk_size_t len;
	duk_uint8_t *p;

	/* Caller must ensure space. */
	DUK_ASSERT(duk__cbor_get_reserve(enc_ctx) >= 1 + 8);

	/* Tag buffer data? */
	buf = (duk_uint8_t *) duk_require_buffer(enc_ctx->thr, -1, &len);
	duk__cbor_encode_sizet_uint32_check(enc_ctx, len);
	duk__cbor_encode_uint32(enc_ctx, (duk_uint32_t) len, 0x40U);
	duk__cbor_encode_ensure(enc_ctx, len);
	p = enc_ctx->ptr;
	duk_memcpy((void *) p, (const void *) buf, len);
	p += len;
	enc_ctx->ptr = p;
}

DUK_LOCAL void duk__cbor_encode_pointer(duk_cbor_encode_context *enc_ctx) {
	/* Pointers (void *) are challenging to encode.  They can't
	 * be relied to be even 64-bit integer compatible (there are
	 * pointer models larger than that), nor can floats encode
	 * them.  They could be encoded as strings (%p format) but
	 * that's not portable.  They could be encoded as direct memory
	 * representations.  Recovering pointers is non-portable in any
	 * case but it would be nice to be able to detect and recover
	 * compatible pointers.
	 *
	 * For now, encode as "(%p)" string, matching JX.  There doesn't
	 * seem to be an appropriate tag, so pointers don't currently
	 * survive a CBOR encode/decode roundtrip intact.
	 */
	const char *ptr;

	ptr = duk_to_string(enc_ctx->thr, -1);
	DUK_ASSERT(ptr != NULL);
	duk_push_sprintf(enc_ctx->thr, "(%s)", ptr);
	duk_remove(enc_ctx->thr, -2);
	duk__cbor_encode_string_top(enc_ctx);
}

DUK_LOCAL void duk__cbor_encode_lightfunc(duk_cbor_encode_context *enc_ctx) {
	duk_uint8_t *p;

	/* Caller must ensure space. */
	DUK_ASSERT(duk__cbor_get_reserve(enc_ctx) >= 1 + 8);

	/* For now encode as an empty object. */
	p = enc_ctx->ptr;
	*p++ = 0xa0U;
	enc_ctx->ptr = p;
}

DUK_LOCAL void duk__cbor_encode_value(duk_cbor_encode_context *enc_ctx) {
	duk_uint8_t *p;

	/* Encode/decode cycle currently loses some type information.
	 * This can be improved by registering custom tags with IANA.
	 */

	/* When working with deeply recursive structures, this is important
	 * to ensure there's no effective depth limit.
	 */
	duk_require_stack(enc_ctx->thr, 4);

	/* Reserve space for up to 64-bit types (1 initial byte + 8
	 * followup bytes).  This allows encoding of integers, floats,
	 * string/buffer length fields, etc without separate checks
	 * in each code path.
	 */
	duk__cbor_encode_ensure(enc_ctx, 1 + 8);

	switch (duk_get_type(enc_ctx->thr, -1)) {
	case DUK_TYPE_UNDEFINED: {
		p = enc_ctx->ptr;
		*p++ = 0xf7;
		enc_ctx->ptr = p;
		break;
	}
	case DUK_TYPE_NULL: {
		p = enc_ctx->ptr;
		*p++ = 0xf6;
		enc_ctx->ptr = p;
		break;
	}
	case DUK_TYPE_BOOLEAN: {
		duk_uint8_t u8 = duk_get_boolean(enc_ctx->thr, -1) ? 0xf5U : 0xf4U;
		p = enc_ctx->ptr;
		*p++ = u8;
		enc_ctx->ptr = p;
		break;
	}
	case DUK_TYPE_NUMBER: {
		duk__cbor_encode_double(enc_ctx, duk_get_number(enc_ctx->thr, -1));
		break;
	}
	case DUK_TYPE_STRING: {
		duk__cbor_encode_string_top(enc_ctx);
		break;
	}
	case DUK_TYPE_OBJECT: {
		duk__cbor_encode_object(enc_ctx);
		break;
	}
	case DUK_TYPE_BUFFER: {
		duk__cbor_encode_buffer(enc_ctx);
		break;
	}
	case DUK_TYPE_POINTER: {
		duk__cbor_encode_pointer(enc_ctx);
		break;
	}
	case DUK_TYPE_LIGHTFUNC: {
		duk__cbor_encode_lightfunc(enc_ctx);
		break;
	}
	case DUK_TYPE_NONE:
	default:
		goto fail;
	}

	duk_pop(enc_ctx->thr);
	return;

 fail:
	duk__cbor_encode_error(enc_ctx);
}

/*
 *  Decoding
 */

DUK_LOCAL void duk__cbor_req_stack(duk_cbor_decode_context *dec_ctx) {
	duk_require_stack(dec_ctx->thr, 4);
}

DUK_LOCAL void duk__cbor_decode_error(duk_cbor_decode_context *dec_ctx) {
	(void) duk_type_error(dec_ctx->thr, "cbor decode error");
}

DUK_LOCAL duk_uint8_t duk__cbor_decode_readbyte(duk_cbor_decode_context *dec_ctx) {
	DUK_ASSERT(dec_ctx->off <= dec_ctx->len);
	if (DUK_UNLIKELY(dec_ctx->len - dec_ctx->off < 1U)) {
		duk__cbor_decode_error(dec_ctx);
	}
	return dec_ctx->buf[dec_ctx->off++];
}

DUK_LOCAL duk_uint16_t duk__cbor_decode_read_u16(duk_cbor_decode_context *dec_ctx) {
	duk_uint16_t res;

	DUK_ASSERT(dec_ctx->off <= dec_ctx->len);
	if (DUK_UNLIKELY(dec_ctx->len - dec_ctx->off < 2U)) {
		duk__cbor_decode_error(dec_ctx);
	}
	res = DUK_RAW_READ_U16_BE(dec_ctx->buf + dec_ctx->off);
	dec_ctx->off += 2;
	return res;
}

DUK_LOCAL duk_uint32_t duk__cbor_decode_read_u32(duk_cbor_decode_context *dec_ctx) {
	duk_uint32_t res;

	DUK_ASSERT(dec_ctx->off <= dec_ctx->len);
	if (DUK_UNLIKELY(dec_ctx->len - dec_ctx->off < 4U)) {
		duk__cbor_decode_error(dec_ctx);
	}
	res = DUK_RAW_READ_U32_BE(dec_ctx->buf + dec_ctx->off);
	dec_ctx->off += 4;
	return res;
}

DUK_LOCAL duk_uint8_t duk__cbor_decode_peekbyte(duk_cbor_decode_context *dec_ctx) {
	if (DUK_UNLIKELY(dec_ctx->off >= dec_ctx->len)) {
		duk__cbor_decode_error(dec_ctx);
	}
	return dec_ctx->buf[dec_ctx->off];
}

DUK_LOCAL void duk__cbor_decode_rewind(duk_cbor_decode_context *dec_ctx, duk_size_t len) {
	DUK_ASSERT(len <= dec_ctx->off);  /* Caller must ensure. */
	dec_ctx->off -= len;
}

#if 0
DUK_LOCAL void duk__cbor_decode_ensure(duk_cbor_decode_context *dec_ctx, duk_size_t len) {
	if (dec_ctx->off + len > dec_ctx->len) {
		duk__cbor_decode_error(dec_ctx);
	}
}
#endif

DUK_LOCAL const duk_uint8_t *duk__cbor_decode_consume(duk_cbor_decode_context *dec_ctx, duk_size_t len) {
	DUK_ASSERT(dec_ctx->off <= dec_ctx->len);
	if (DUK_LIKELY(dec_ctx->len - dec_ctx->off >= len)) {
		const duk_uint8_t *res = dec_ctx->buf + dec_ctx->off;
		dec_ctx->off += len;
		return res;
	}

	duk__cbor_decode_error(dec_ctx);  /* Not enough input. */
	return NULL;
}

DUK_LOCAL int duk__cbor_decode_checkbreak(duk_cbor_decode_context *dec_ctx) {
	if (duk__cbor_decode_peekbyte(dec_ctx) == 0xffU) {
		DUK_ASSERT(dec_ctx->off < dec_ctx->len);
		dec_ctx->off++;
#if 0
		(void) duk__cbor_decode_readbyte(dec_ctx);
#endif
		return 1;
	}
	return 0;
}

DUK_LOCAL void duk__cbor_decode_push_aival_int(duk_cbor_decode_context *dec_ctx, duk_uint8_t ib, duk_bool_t negative) {
	duk_uint8_t ai;
	duk_uint32_t t, t1, t2;
#if 0
	duk_uint64_t t3;
#endif
	duk_double_t d1, d2;
	duk_double_t d;

	ai = ib & 0x1fU;
	if (ai <= 0x17U) {
		t = ai;
		goto shared_exit;
	}

	switch (ai) {
	case 0x18U:  /* 1 byte */
		t = (duk_uint32_t) duk__cbor_decode_readbyte(dec_ctx);
		goto shared_exit;
	case 0x19U:  /* 2 byte */
		t = (duk_uint32_t) duk__cbor_decode_read_u16(dec_ctx);
		goto shared_exit;
	case 0x1aU:  /* 4 byte */
		t = (duk_uint32_t) duk__cbor_decode_read_u32(dec_ctx);
		goto shared_exit;
	case 0x1bU:  /* 8 byte */
		/* For uint64 it's important to handle the -1.0 part before
		 * casting to double: otherwise the adjustment might be lost
		 * in the cast.  Uses: -1.0 - d <=> -(d + 1.0).
		 */
		t = (duk_uint32_t) duk__cbor_decode_read_u32(dec_ctx);
		t2 = t;
		t = (duk_uint32_t) duk__cbor_decode_read_u32(dec_ctx);
		t1 = t;
#if 0
		t3 = (duk_uint64_t) t2 * DUK_U64_CONSTANT(0x100000000) + (duk_uint64_t) t1;
		if (negative) {
			if (t3 == DUK_UINT64_MAX) {
				/* -(0xffff'ffff'ffff'ffffULL + 1) =
				 * -0x1'0000'0000'0000'0000
				 *
				 * >>> -0x10000000000000000
				 * -18446744073709551616L
				 */
				return -18446744073709551616.0;
			} else {
				return -((duk_double_t) (t3 + DUK_U64_CONSTANT(1)));
			}
		} else {
			return (duk_double_t) t3;  /* XXX: cast helper */
		}
#endif
#if 0
		t3 = (duk_uint64_t) t2 * DUK_U64_CONSTANT(0x100000000) + (duk_uint64_t) t1;
		if (negative) {
			/* Simpler version: take advantage of the fact that
			 * 0xffff'ffff'ffff'ffff and 0x1'0000'0000'0000'0000
			 * both round to 0x1'0000'0000'0000'0000:
			 * > (0xffffffffffffffff).toString(16)
			 * '10000000000000000'
			 * > (0x10000000000000000).toString(16)
			 * '10000000000000000'
			 *
			 * For the DUK_UINT64_MAX case we just skip the +1
			 * increment to avoid wrapping; the result still
			 * comes out right for an IEEE double cast.
			 */
			if (t3 != DUK_UINT64_MAX) {
				t3++;
			}
			return -((duk_double_t) t3);
		} else {
			return (duk_double_t) t3;  /* XXX: cast helper */
		}
#endif
#if 1
		/* Use two double parts, avoids dependency on 64-bit type.
		 * Avoid precision loss carefully, especially when dealing
		 * with the required +1 for negative values.
		 *
		 * No fastint check for this path at present.
		 */
		d1 = (duk_double_t) t1;  /* XXX: cast helpers */
		d2 = (duk_double_t) t2 * 4294967296.0;
		if (negative) {
			d1 += 1.0;
		}
		d = d2 + d1;
		if (negative) {
			d = -d;
		}
#endif
		/* XXX: a push and check for fastint API would be nice */
		duk_push_number(dec_ctx->thr, d);
		return;
	}

	duk__cbor_decode_error(dec_ctx);
	return;

 shared_exit:
	if (negative) {
		/* XXX: a push and check for fastint API would be nice */
		if ((duk_uint_t) t <= (duk_uint_t) -(DUK_INT_MIN + 1)) {
			duk_push_int(dec_ctx->thr, -1 - ((duk_int_t) t));
		} else {
			duk_push_number(dec_ctx->thr, -1.0 - (duk_double_t) t);
		}
	} else {
		duk_push_uint(dec_ctx->thr, (duk_uint_t) t);
	}
}

DUK_LOCAL void duk__cbor_decode_skip_aival_int(duk_cbor_decode_context *dec_ctx, duk_uint8_t ib) {
	const duk_int8_t skips[32] = {
		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 4, 8, -1, -1, -1, -1
	};
	duk_uint8_t ai;
	duk_int8_t skip;

	ai = ib & 0x1fU;
	skip = skips[ai];
	if (DUK_UNLIKELY(skip < 0)) {
		duk__cbor_decode_error(dec_ctx);
	}
	duk__cbor_decode_consume(dec_ctx, (duk_size_t) skip);
	return;
}

DUK_LOCAL duk_uint32_t duk__cbor_decode_aival_uint32(duk_cbor_decode_context *dec_ctx, duk_uint8_t ib) {
	duk_uint8_t ai;
	duk_uint32_t t;

	ai = ib & 0x1fU;
	if (ai <= 0x17U) {
		return (duk_uint32_t) ai;
	}

	switch (ai) {
	case 0x18U:  /* 1 byte */
		t = (duk_uint32_t) duk__cbor_decode_readbyte(dec_ctx);
		return t;
	case 0x19U:  /* 2 byte */
		t = (duk_uint32_t) duk__cbor_decode_read_u16(dec_ctx);
		return t;
	case 0x1aU:  /* 4 byte */
		t = (duk_uint32_t) duk__cbor_decode_read_u32(dec_ctx);
		return t;
	case 0x1bU:  /* 8 byte */
		t = (duk_uint32_t) duk__cbor_decode_read_u32(dec_ctx);
		if (t != 0U) {
			break;
		}
		t = (duk_uint32_t) duk__cbor_decode_read_u32(dec_ctx);
		return t;
	}

	duk__cbor_decode_error(dec_ctx);
	return 0U;
}

DUK_LOCAL void duk__cbor_decode_buffer(duk_cbor_decode_context *dec_ctx, duk_uint8_t expected_base) {
	duk_uint32_t len;
	duk_uint8_t *buf;
	const duk_uint8_t *inp;
	duk_uint8_t ib;

	ib = duk__cbor_decode_readbyte(dec_ctx);
	if ((ib & 0xe0U) != expected_base) {
		duk__cbor_decode_error(dec_ctx);
	}
	/* Indefinite format is rejected by the following on purpose. */
	len = duk__cbor_decode_aival_uint32(dec_ctx, ib);
	inp = duk__cbor_decode_consume(dec_ctx, len);
	/* XXX: duk_push_fixed_buffer_with_data() would be a nice API addition. */
	buf = (duk_uint8_t *) duk_push_fixed_buffer(dec_ctx->thr, (duk_size_t) len);
	duk_memcpy((void *) buf, (const void *) inp, (size_t) len);
}

DUK_LOCAL void duk__cbor_decode_join_buffers(duk_cbor_decode_context *dec_ctx, duk_idx_t count) {
	duk_size_t total_size = 0;
	duk_idx_t top = duk_get_top(dec_ctx->thr);
	duk_idx_t base = top - count;  /* count is >= 1 */
	duk_idx_t idx;
	duk_uint8_t *p = NULL;

	DUK_ASSERT(count >= 1);
	DUK_ASSERT(top >= count);

	for (;;) {
		/* First round: compute total size.
		 * Second round: copy into place.
		 */
		for (idx = base; idx < top; idx++) {
			duk_uint8_t *buf_data;
			duk_size_t buf_size;

			buf_data = (duk_uint8_t *) duk_require_buffer(dec_ctx->thr, idx, &buf_size);
			if (p != NULL) {
				if (buf_size > 0U) {
					duk_memcpy((void *) p, (const void *) buf_data, buf_size);
				}
				p += buf_size;
			} else {
				total_size += buf_size;
				if (DUK_UNLIKELY(total_size < buf_size)) {  /* Wrap check. */
					duk__cbor_decode_error(dec_ctx);
				}
			}
		}

		if (p != NULL) {
			break;
		} else {
			p = (duk_uint8_t *) duk_push_fixed_buffer(dec_ctx->thr, total_size);
			DUK_ASSERT(p != NULL);
		}
	}

	duk_replace(dec_ctx->thr, base);
	duk_pop_n(dec_ctx->thr, count - 1);
}

DUK_LOCAL void duk__cbor_decode_and_join_strbuf(duk_cbor_decode_context *dec_ctx, duk_uint8_t expected_base) {
	duk_idx_t count = 0;
	for (;;) {
		if (duk__cbor_decode_checkbreak(dec_ctx)) {
			break;
		}
		duk_require_stack(dec_ctx->thr, 1);
		duk__cbor_decode_buffer(dec_ctx, expected_base);
		count++;
		if (DUK_UNLIKELY(count <= 0)) {  /* Wrap check. */
			duk__cbor_decode_error(dec_ctx);
		}
	}
	if (count == 0) {
		(void) duk_push_fixed_buffer(dec_ctx->thr, 0);
	} else if (count > 1) {
		duk__cbor_decode_join_buffers(dec_ctx, count);
	}
}

DUK_LOCAL duk_double_t duk__cbor_decode_half_float(duk_cbor_decode_context *dec_ctx) {
	duk_double_union u;
	const duk_uint8_t *inp;
	duk_int_t expt;
	duk_uint_t u16;
	duk_uint_t tmp;
	duk_double_t res;

	inp = duk__cbor_decode_consume(dec_ctx, 2);
	u16 = ((duk_uint_t) inp[0] << 8) + (duk_uint_t) inp[1];
	expt = (duk_int_t) ((u16 >> 10) & 0x1fU) - 15;

	/* Reconstruct IEEE double into little endian order first, then convert
	 * to host order.
	 */

	duk_memzero((void *) &u, sizeof(u));

	if (expt == -15) {
		/* Zero or denormal; but note that half float
		 * denormals become double normals.
		 */
		if ((u16 & 0x03ffU) == 0) {
			u.uc[7] = inp[0] & 0x80U;
		} else {
			/* Create denormal by first creating a double that
			 * contains the denormal bits and a leading implicit
			 * 1-bit.  Then subtract away the implicit 1-bit.
			 *
			 *    0.mmmmmmmmmm * 2^-14
			 *    1.mmmmmmmmmm 0.... * 2^-14
			 *   -1.0000000000 0.... * 2^-14
			 *
			 * Double exponent: -14 + 1023 = 0x3f1
			 */
			u.uc[7] = 0x3fU;
			u.uc[6] = 0x10U + (duk_uint8_t) ((u16 >> 6) & 0x0fU);
			u.uc[5] = (duk_uint8_t) ((u16 << 2) & 0xffU);  /* Mask is really 0xfcU */

			duk_dblunion_little_to_host(&u);
			res = u.d - 0.00006103515625;  /* 2^(-14) */
			if (u16 & 0x8000U) {
				res = -res;
			}
			return res;
		}
	} else if (expt == 16) {
		/* +/- Inf or NaN. */
		if ((u16 & 0x03ffU) == 0) {
			u.uc[7] = (inp[0] & 0x80U) + 0x7fU;
			u.uc[6] = 0xf0U;
		} else {
			/* Create a 'quiet NaN' with highest
			 * bit set (there are some platforms
			 * where the NaN payload convention is
			 * the opposite).  Keep sign.
			 */
			u.uc[7] = (inp[0] & 0x80U) + 0x7fU;
			u.uc[6] = 0xf8U;
		}
	} else {
		/* Normal. */
		tmp = (inp[0] & 0x80U) ? 0x80000000UL : 0UL;
		tmp += (duk_uint_t) (expt + 1023) << 20;
		tmp += (duk_uint_t) (inp[0] & 0x03U) << 18;
		tmp += (duk_uint_t) (inp[1] & 0xffU) << 10;
		u.uc[7] = (tmp >> 24) & 0xffU;
		u.uc[6] = (tmp >> 16) & 0xffU;
		u.uc[5] = (tmp >> 8) & 0xffU;
		u.uc[4] = (tmp >> 0) & 0xffU;
	}

	duk_dblunion_little_to_host(&u);
	return u.d;
}

DUK_LOCAL void duk__cbor_decode_string(duk_cbor_decode_context *dec_ctx, duk_uint8_t ib, duk_uint8_t ai) {
	/* If the CBOR string data is not valid UTF-8 it is technically
	 * invalid CBOR.  Possible behaviors at least:
	 *
	 *   1. Reject the input, i.e. throw TypeError.
	 *
	 *   2. Accept the input, but sanitize non-UTF-8 data into UTF-8
	 *      using U+FFFD replacements.  Also it might make sense to
	 *      decode non-BMP codepoints into surrogates for better
	 *      ECMAScript compatibility.
	 *
	 *   3. Accept the input as a Duktape string (which are not always
	 *      valid UTF-8), but reject any input that would create a
	 *      Symbol representation.
	 *
	 * Current behavior is 3.
	 */

	if (ai == 0x1fU) {
		duk_uint8_t *buf_data;
		duk_size_t buf_size;

		duk__cbor_decode_and_join_strbuf(dec_ctx, 0x60U);
		buf_data = (duk_uint8_t *) duk_require_buffer(dec_ctx->thr, -1, &buf_size);
		(void) duk_push_lstring(dec_ctx->thr, (const char *) buf_data, buf_size);
		duk_remove(dec_ctx->thr, -2);
	} else {
		duk_uint32_t len;
		const duk_uint8_t *inp;

		len = duk__cbor_decode_aival_uint32(dec_ctx, ib);
		inp = duk__cbor_decode_consume(dec_ctx, len);
		(void) duk_push_lstring(dec_ctx->thr, (const char *) inp, (duk_size_t) len);
	}
	if (duk_is_symbol(dec_ctx->thr, -1)) {
		/* Refuse to create Symbols when decoding. */
		duk__cbor_decode_error(dec_ctx);
	}

	/* XXX: Here a Duktape API call to convert input -> utf-8 with
	 * replacements would be nice.
	 */
}

DUK_LOCAL duk_bool_t duk__cbor_decode_array(duk_cbor_decode_context *dec_ctx, duk_uint8_t ib, duk_uint8_t ai) {
	duk_uint32_t idx, len;

	duk__cbor_req_stack(dec_ctx);

	/* Support arrays up to 0xfffffffeU in length.  0xffffffff is
	 * used as an indefinite length marker.
	 */
	if (ai == 0x1fU) {
		len = 0xffffffffUL;
	} else {
		len = duk__cbor_decode_aival_uint32(dec_ctx, ib);
		if (len == 0xffffffffUL) {
			return 0;
		}
	}

	/* XXX: use bare array? */
	duk_push_array(dec_ctx->thr);
	for (idx = 0U; ;) {
		if (len == 0xffffffffUL && duk__cbor_decode_checkbreak(dec_ctx)) {
			break;
		}
		if (idx == len) {
			if (ai == 0x1fU) {
				return 0;
			}
			break;
		}
		duk__cbor_decode_value(dec_ctx);
		duk_put_prop_index(dec_ctx->thr, -2, (duk_uarridx_t) idx);
		idx++;
		if (idx == 0U) {
			return 0;  /* wrapped */
		}
	}

	return 1;
}

DUK_LOCAL duk_bool_t duk__cbor_decode_map(duk_cbor_decode_context *dec_ctx, duk_uint8_t ib, duk_uint8_t ai) {
	duk_uint32_t count;

	duk__cbor_req_stack(dec_ctx);

	if (ai == 0x1fU) {
		count = 0xffffffffUL;
	} else {
		count = duk__cbor_decode_aival_uint32(dec_ctx, ib);
		if (count == 0xffffffffUL) {
			return 0;
		}
	}

	/* XXX: use bare object? */
	duk_push_object(dec_ctx->thr);
	for (;;) {
		if (count == 0xffffffffUL) {
			if (duk__cbor_decode_checkbreak(dec_ctx)) {
				break;
			}
		} else {
			if (count == 0UL) {
				break;
			}
			count--;
		}

		/* Non-string keys are coerced to strings,
		 * possibly leading to overwriting previous
		 * keys.  Last key of a certain coerced name
		 * wins.  If key is an object, it will coerce
		 * to '[object Object]' which is consistent
		 * but potentially misleading.  One alternative
		 * would be to skip non-string keys.
		 */
		duk__cbor_decode_value(dec_ctx);
		duk__cbor_decode_value(dec_ctx);
		duk_put_prop(dec_ctx->thr, -3);
	}

	return 1;
}

DUK_LOCAL duk_double_t duk__cbor_decode_float(duk_cbor_decode_context *dec_ctx) {
	duk_float_union u;
	const duk_uint8_t *inp;
	inp = duk__cbor_decode_consume(dec_ctx, 4);
	duk_memcpy((void *) u.uc, (const void *) inp, 4);
	duk_fltunion_big_to_host(&u);
	return (duk_double_t) u.f;
}

DUK_LOCAL duk_double_t duk__cbor_decode_double(duk_cbor_decode_context *dec_ctx) {
	duk_double_union u;
	const duk_uint8_t *inp;
	inp = duk__cbor_decode_consume(dec_ctx, 8);
	duk_memcpy((void *) u.uc, (const void *) inp, 8);
	duk_dblunion_big_to_host(&u);
	return u.d;
}

#if defined(DUK_CBOR_DECODE_FASTPATH)
#define DUK__CBOR_AI  (ib & 0x1fU)

DUK_LOCAL void duk__cbor_decode_value(duk_cbor_decode_context *dec_ctx) {
	duk_uint8_t ib;

	/* Any paths potentially recursing back to duk__cbor_decode_value()
	 * must perform a Duktape value stack growth check.  Avoid the check
	 * here for simple paths like primitive values.
	 */

 reread_initial_byte:
	DUK_DDD(DUK_DDDPRINT("cbor decode off=%ld len=%ld", (long) dec_ctx->off, (long) dec_ctx->len));

	ib = duk__cbor_decode_readbyte(dec_ctx);

	/* Full initial byte switch, footprint cost over baseline is ~+1kB. */
	/* XXX: Force full switch with no range check. */

	switch (ib) {
	case 0x00U: case 0x01U: case 0x02U: case 0x03U: case 0x04U: case 0x05U: case 0x06U: case 0x07U:
	case 0x08U: case 0x09U: case 0x0aU: case 0x0bU: case 0x0cU: case 0x0dU: case 0x0eU: case 0x0fU:
	case 0x10U: case 0x11U: case 0x12U: case 0x13U: case 0x14U: case 0x15U: case 0x16U: case 0x17U:
		duk_push_uint(dec_ctx->thr, ib);
		break;
	case 0x18U: case 0x19U: case 0x1aU: case 0x1bU:
		duk__cbor_decode_push_aival_int(dec_ctx, ib, 0 /*negative*/);
		break;
	case 0x1cU: case 0x1dU: case 0x1eU: case 0x1fU:
		goto format_error;
	case 0x20U: case 0x21U: case 0x22U: case 0x23U: case 0x24U: case 0x25U: case 0x26U: case 0x27U:
	case 0x28U: case 0x29U: case 0x2aU: case 0x2bU: case 0x2cU: case 0x2dU: case 0x2eU: case 0x2fU:
	case 0x30U: case 0x31U: case 0x32U: case 0x33U: case 0x34U: case 0x35U: case 0x36U: case 0x37U:
		duk_push_int(dec_ctx->thr, -((duk_int_t) ((ib - 0x20U) + 1U)));
		break;
	case 0x38U: case 0x39U: case 0x3aU: case 0x3bU:
		duk__cbor_decode_push_aival_int(dec_ctx, ib, 1 /*negative*/);
		break;
	case 0x3cU: case 0x3dU: case 0x3eU: case 0x3fU:
		goto format_error;
	case 0x40U: case 0x41U: case 0x42U: case 0x43U: case 0x44U: case 0x45U: case 0x46U: case 0x47U:
	case 0x48U: case 0x49U: case 0x4aU: case 0x4bU: case 0x4cU: case 0x4dU: case 0x4eU: case 0x4fU:
	case 0x50U: case 0x51U: case 0x52U: case 0x53U: case 0x54U: case 0x55U: case 0x56U: case 0x57U:
		/* XXX: Avoid rewind, we know the length already. */
		DUK_ASSERT(dec_ctx->off > 0U);
		dec_ctx->off--;
		duk__cbor_decode_buffer(dec_ctx, 0x40U);
		break;
	case 0x58U: case 0x59U: case 0x5aU: case 0x5bU:
		/* XXX: Avoid rewind, decode length inline. */
		DUK_ASSERT(dec_ctx->off > 0U);
		dec_ctx->off--;
		duk__cbor_decode_buffer(dec_ctx, 0x40U);
		break;
	case 0x5cU: case 0x5dU: case 0x5eU:
		goto format_error;
	case 0x5fU:
		duk__cbor_decode_and_join_strbuf(dec_ctx, 0x40U);
		break;
	case 0x60U: case 0x61U: case 0x62U: case 0x63U: case 0x64U: case 0x65U: case 0x66U: case 0x67U:
	case 0x68U: case 0x69U: case 0x6aU: case 0x6bU: case 0x6cU: case 0x6dU: case 0x6eU: case 0x6fU:
	case 0x70U: case 0x71U: case 0x72U: case 0x73U: case 0x74U: case 0x75U: case 0x76U: case 0x77U:
		/* XXX: Avoid double decode of length. */
		duk__cbor_decode_string(dec_ctx, ib, DUK__CBOR_AI);
		break;
	case 0x78U: case 0x79U: case 0x7aU: case 0x7bU:
		/* XXX: Avoid double decode of length. */
		duk__cbor_decode_string(dec_ctx, ib, DUK__CBOR_AI);
		break;
	case 0x7cU: case 0x7dU: case 0x7eU:
		goto format_error;
	case 0x7fU:
		duk__cbor_decode_string(dec_ctx, ib, DUK__CBOR_AI);
		break;
	case 0x80U: case 0x81U: case 0x82U: case 0x83U: case 0x84U: case 0x85U: case 0x86U: case 0x87U:
	case 0x88U: case 0x89U: case 0x8aU: case 0x8bU: case 0x8cU: case 0x8dU: case 0x8eU: case 0x8fU:
	case 0x90U: case 0x91U: case 0x92U: case 0x93U: case 0x94U: case 0x95U: case 0x96U: case 0x97U:
		if (DUK_UNLIKELY(duk__cbor_decode_array(dec_ctx, ib, DUK__CBOR_AI) == 0)) {
			goto format_error;
		}
		break;
	case 0x98U: case 0x99U: case 0x9aU: case 0x9bU:
		if (DUK_UNLIKELY(duk__cbor_decode_array(dec_ctx, ib, DUK__CBOR_AI) == 0)) {
			goto format_error;
		}
		break;
	case 0x9cU: case 0x9dU: case 0x9eU:
		goto format_error;
	case 0x9fU:
		if (DUK_UNLIKELY(duk__cbor_decode_array(dec_ctx, ib, DUK__CBOR_AI) == 0)) {
			goto format_error;
		}
		break;
	case 0xa0U: case 0xa1U: case 0xa2U: case 0xa3U: case 0xa4U: case 0xa5U: case 0xa6U: case 0xa7U:
	case 0xa8U: case 0xa9U: case 0xaaU: case 0xabU: case 0xacU: case 0xadU: case 0xaeU: case 0xafU:
	case 0xb0U: case 0xb1U: case 0xb2U: case 0xb3U: case 0xb4U: case 0xb5U: case 0xb6U: case 0xb7U:
		if (DUK_UNLIKELY(duk__cbor_decode_map(dec_ctx, ib, DUK__CBOR_AI) == 0)) {
			goto format_error;
		}
		break;
	case 0xb8U: case 0xb9U: case 0xbaU: case 0xbbU:
		if (DUK_UNLIKELY(duk__cbor_decode_map(dec_ctx, ib, DUK__CBOR_AI) == 0)) {
			goto format_error;
		}
		break;
	case 0xbcU: case 0xbdU: case 0xbeU:
		goto format_error;
	case 0xbfU:
		if (DUK_UNLIKELY(duk__cbor_decode_map(dec_ctx, ib, DUK__CBOR_AI) == 0)) {
			goto format_error;
		}
		break;
	case 0xc0U: case 0xc1U: case 0xc2U: case 0xc3U: case 0xc4U: case 0xc5U: case 0xc6U: case 0xc7U:
	case 0xc8U: case 0xc9U: case 0xcaU: case 0xcbU: case 0xccU: case 0xcdU: case 0xceU: case 0xcfU:
	case 0xd0U: case 0xd1U: case 0xd2U: case 0xd3U: case 0xd4U: case 0xd5U: case 0xd6U: case 0xd7U:
		/* Tag 0-23: drop. */
		goto reread_initial_byte;
	case 0xd8U: case 0xd9U: case 0xdaU: case 0xdbU:
		duk__cbor_decode_skip_aival_int(dec_ctx, ib);
		goto reread_initial_byte;
	case 0xdcU: case 0xddU: case 0xdeU: case 0xdfU:
		goto format_error;
	case 0xe0U:
		goto format_error;
	case 0xe1U:
		goto format_error;
	case 0xe2U:
		goto format_error;
	case 0xe3U:
		goto format_error;
	case 0xe4U:
		goto format_error;
	case 0xe5U:
		goto format_error;
	case 0xe6U:
		goto format_error;
	case 0xe7U:
		goto format_error;
	case 0xe8U:
		goto format_error;
	case 0xe9U:
		goto format_error;
	case 0xeaU:
		goto format_error;
	case 0xebU:
		goto format_error;
	case 0xecU:
		goto format_error;
	case 0xedU:
		goto format_error;
	case 0xeeU:
		goto format_error;
	case 0xefU:
		goto format_error;
	case 0xf0U:
		goto format_error;
	case 0xf1U:
		goto format_error;
	case 0xf2U:
		goto format_error;
	case 0xf3U:
		goto format_error;
	case 0xf4U:
		duk_push_false(dec_ctx->thr);
		break;
	case 0xf5U:
		duk_push_true(dec_ctx->thr);
		break;
	case 0xf6U:
		duk_push_null(dec_ctx->thr);
		break;
	case 0xf7U:
		duk_push_undefined(dec_ctx->thr);
		break;
	case 0xf8U:
		/* Simple value 32-255, nothing defined yet, so reject. */
		goto format_error;
	case 0xf9U: {
		duk_double_t d;
		d = duk__cbor_decode_half_float(dec_ctx);
		duk_push_number(dec_ctx->thr, d);
		break;
	}
	case 0xfaU: {
		duk_double_t d;
		d = duk__cbor_decode_float(dec_ctx);
		duk_push_number(dec_ctx->thr, d);
		break;
	}
	case 0xfbU: {
		duk_double_t d;
		d = duk__cbor_decode_double(dec_ctx);
		duk_push_number(dec_ctx->thr, d);
		break;
	}
	case 0xfcU:
	case 0xfdU:
	case 0xfeU:
	case 0xffU:
		goto format_error;
	}  /* end switch */

	return;

 format_error:
	duk__cbor_decode_error(dec_ctx);
}
#else  /* DUK_CBOR_DECODE_FASTPATH */
DUK_LOCAL void duk__cbor_decode_value(duk_cbor_decode_context *dec_ctx) {
	duk_uint8_t ib, mt, ai;

	/* Any paths potentially recursing back to duk__cbor_decode_value()
	 * must perform a Duktape value stack growth check.  Avoid the check
	 * here for simple paths like primitive values.
	 */

 reread_initial_byte:
	DUK_DDD(DUK_DDDPRINT("cbor decode off=%ld len=%ld", (long) dec_ctx->off, (long) dec_ctx->len));

	ib = duk__cbor_decode_readbyte(dec_ctx);
	mt = ib >> 5U;
	ai = ib & 0x1fU;

	/* Additional information in [24,27] = [0x18,0x1b] has relatively
	 * uniform handling for all major types: read 1/2/4/8 additional
	 * bytes.  For major type 7 the 1-byte value is a 'simple type', and
	 * 2/4/8-byte values are floats.  For other major types the 1/2/4/8
	 * byte values are integers.  The lengths are uniform, but the typing
	 * is not.
	 */

	switch (mt) {
	case 0U: {  /* unsigned integer */
		duk__cbor_decode_push_aival_int(dec_ctx, ib, 0 /*negative*/);
		break;
	}
	case 1U: {  /* negative integer */
		duk__cbor_decode_push_aival_int(dec_ctx, ib, 1 /*negative*/);
		break;
	}
	case 2U: {  /* byte string */
		if (ai == 0x1fU) {
			duk__cbor_decode_and_join_strbuf(dec_ctx, 0x40U);
		} else {
			duk__cbor_decode_rewind(dec_ctx, 1U);
			duk__cbor_decode_buffer(dec_ctx, 0x40U);
		}
		break;
	}
	case 3U: {  /* text string */
		duk__cbor_decode_string(dec_ctx, ib, ai);
		break;
	}
	case 4U: {  /* array of data items */
		if (DUK_UNLIKELY(duk__cbor_decode_array(dec_ctx, ib, ai) == 0)) {
			goto format_error;
		}
		break;
	}
	case 5U: {  /* map of pairs of data items */
		if (DUK_UNLIKELY(duk__cbor_decode_map(dec_ctx, ib, ai) == 0)) {
			goto format_error;
		}
		break;
	}
	case 6U: {  /* semantic tagging */
		/* Tags are ignored now, re-read initial byte.  A tagged
		 * value may itself be tagged (an unlimited number of times)
		 * so keep on peeling away tags.
		 */
		duk__cbor_decode_skip_aival_int(dec_ctx, ib);
		goto reread_initial_byte;
	}
	case 7U: {  /* floating point numbers, simple data types, break; other */
		switch (ai) {
		case 0x14U: {
			duk_push_false(dec_ctx->thr);
			break;
		}
		case 0x15U: {
			duk_push_true(dec_ctx->thr);
			break;
		}
		case 0x16U: {
			duk_push_null(dec_ctx->thr);
			break;
		}
		case 0x17U: {
			duk_push_undefined(dec_ctx->thr);
			break;
		}
		case 0x18U: {  /* more simple values (1 byte) */
			/* Simple value encoded in additional byte (none
			 * are defined so far).  RFC 7049 states that the
			 * follow-up byte must be 32-255 to minimize
			 * confusion.  So, a non-shortest encoding like
			 * f815 (= true, shortest encoding f5) must be
			 * rejected.  cbor.me tester rejects f815, but
			 * e.g. Python CBOR binding decodes it as true.
			 */
			goto format_error;
		}
		case 0x19U: {  /* half-float (2 bytes) */
			duk_double_t d;
			d = duk__cbor_decode_half_float(dec_ctx);
			duk_push_number(dec_ctx->thr, d);
			break;
		}
		case 0x1aU: {  /* float (4 bytes) */
			duk_double_t d;
			d = duk__cbor_decode_float(dec_ctx);
			duk_push_number(dec_ctx->thr, d);
			break;
		}
		case 0x1bU: {  /* double (8 bytes) */
			duk_double_t d;
			d = duk__cbor_decode_double(dec_ctx);
			duk_push_number(dec_ctx->thr, d);
			break;
		}
		case 0xffU:  /* unexpected break */
		default: {
			goto format_error;
		}
		}  /* end switch */
		break;
	}
	default: {
		goto format_error;  /* will never actually occur */
	}
	}  /* end switch */

	return;

 format_error:
	duk__cbor_decode_error(dec_ctx);
}
#endif  /* DUK_CBOR_DECODE_FASTPATH */

DUK_LOCAL void duk__cbor_encode(duk_hthread *thr, duk_idx_t idx, duk_uint_t encode_flags) {
	duk_cbor_encode_context enc_ctx;
	duk_uint8_t *buf;

	DUK_UNREF(encode_flags);

	idx = duk_require_normalize_index(thr, idx);

	enc_ctx.thr = thr;
	enc_ctx.idx_buf = duk_get_top(thr);

	enc_ctx.len = 64;
	buf = (duk_uint8_t *) duk_push_dynamic_buffer(thr, enc_ctx.len);
	enc_ctx.ptr = buf;
	enc_ctx.buf = buf;
	enc_ctx.buf_end = buf + enc_ctx.len;

	duk_dup(thr, idx);
	duk__cbor_encode_value(&enc_ctx);
	duk_resize_buffer(enc_ctx.thr, enc_ctx.idx_buf, (duk_size_t) (enc_ctx.ptr - enc_ctx.buf));
	duk_replace(thr, idx);
}

DUK_LOCAL void duk__cbor_decode(duk_hthread *thr, duk_idx_t idx, duk_uint_t decode_flags) {
	duk_cbor_decode_context dec_ctx;

	DUK_UNREF(decode_flags);

	/* Suppress compile warnings for functions only needed with e.g.
	 * asserts enabled.
	 */
	DUK_UNREF(duk__cbor_get_reserve);

	idx = duk_require_normalize_index(thr, idx);

	dec_ctx.thr = thr;
	dec_ctx.buf = (const duk_uint8_t *) duk_require_buffer_data(thr, idx, &dec_ctx.len);
	dec_ctx.off = 0;
	/* dec_ctx.len: set above */

	duk__cbor_req_stack(&dec_ctx);
	duk__cbor_decode_value(&dec_ctx);
	if (dec_ctx.off != dec_ctx.len) {
		(void) duk_type_error(thr, "trailing garbage");
	}

	duk_replace(thr, idx);
}

#else  /* DUK_USE_CBOR_SUPPORT */

DUK_LOCAL void duk__cbor_encode(duk_hthread *thr, duk_idx_t idx, duk_uint_t encode_flags) {
	DUK_UNREF(idx);
	DUK_UNREF(encode_flags);
	DUK_ERROR_UNSUPPORTED(thr);
}

DUK_LOCAL void duk__cbor_decode(duk_hthread *thr, duk_idx_t idx, duk_uint_t decode_flags) {
	DUK_UNREF(idx);
	DUK_UNREF(decode_flags);
	DUK_ERROR_UNSUPPORTED(thr);
}

#endif  /* DUK_USE_CBOR_SUPPORT */

/*
 *  Public APIs
 */

DUK_EXTERNAL void duk_cbor_encode(duk_hthread *thr, duk_idx_t idx, duk_uint_t encode_flags) {
	DUK_ASSERT_API_ENTRY(thr);
	duk__cbor_encode(thr, idx, encode_flags);
}
DUK_EXTERNAL void duk_cbor_decode(duk_hthread *thr, duk_idx_t idx, duk_uint_t decode_flags) {
	DUK_ASSERT_API_ENTRY(thr);
	duk__cbor_decode(thr, idx, decode_flags);
}

#if defined(DUK_USE_CBOR_BUILTIN)
#if defined(DUK_USE_CBOR_SUPPORT)
DUK_INTERNAL duk_ret_t duk_bi_cbor_encode(duk_hthread *thr) {
	DUK_ASSERT_TOP(thr, 1);

	duk__cbor_encode(thr, -1, 0 /*flags*/);

	/* Produce an ArrayBuffer by first decoding into a plain buffer which
	 * mimics a Uint8Array and gettings its .buffer property.
	 */
	/* XXX: shortcut */
	(void) duk_get_prop_stridx(thr, -1, DUK_STRIDX_LC_BUFFER);
	return 1;
}

DUK_INTERNAL duk_ret_t duk_bi_cbor_decode(duk_hthread *thr) {
	DUK_ASSERT_TOP(thr, 1);

	duk__cbor_decode(thr, -1, 0 /*flags*/);
	return 1;
}
#else  /* DUK_USE_CBOR_SUPPORT */
DUK_INTERNAL duk_ret_t duk_bi_cbor_encode(duk_hthread *thr) {
	DUK_ERROR_UNSUPPORTED(thr);
	DUK_WO_NORETURN(return 0;);
}
DUK_INTERNAL duk_ret_t duk_bi_cbor_decode(duk_hthread *thr) {
	DUK_ERROR_UNSUPPORTED(thr);
	DUK_WO_NORETURN(return 0;);
}
#endif  /* DUK_USE_CBOR_SUPPORT */
#endif  /* DUK_USE_CBOR_BUILTIN */

/* automatic undefs */
#undef DUK__CBOR_AI
#line 1 "duk_bi_date.c"
/*
 *  Date built-ins
 *
 *  Unlike most built-ins, Date has some platform dependencies for getting
 *  UTC time, converting between UTC and local time, and parsing and
 *  formatting time values.  These are all abstracted behind DUK_USE_xxx
 *  config options.  There are built-in platform specific providers for
 *  POSIX and Windows, but external providers can also be used.
 *
 *  See doc/datetime.rst.
 *
 */

/* #include duk_internal.h -> already included */

/* XXX: currently defines unnecessary symbols when DUK_USE_DATE_BUILTIN is disabled. */

/*
 *  Forward declarations
 */

DUK_LOCAL_DECL duk_double_t duk__push_this_get_timeval_tzoffset(duk_hthread *thr, duk_small_uint_t flags, duk_int_t *out_tzoffset);
DUK_LOCAL_DECL duk_double_t duk__push_this_get_timeval(duk_hthread *thr, duk_small_uint_t flags);
DUK_LOCAL_DECL void duk__twodigit_year_fixup(duk_hthread *thr, duk_idx_t idx_val);
DUK_LOCAL_DECL duk_ret_t duk__set_this_timeval_from_dparts(duk_hthread *thr, duk_double_t *dparts, duk_small_uint_t flags);

/*
 *  Other file level defines
 */

/* Debug macro to print all parts and dparts (used manually because of debug level). */
#define  DUK__DPRINT_PARTS_AND_DPARTS(parts,dparts)  do { \
		DUK_D(DUK_DPRINT("parts: %ld %ld %ld %ld %ld %ld %ld %ld, dparts: %lf %lf %lf %lf %lf %lf %lf %lf", \
		                 (long) (parts)[0], (long) (parts)[1], \
		                 (long) (parts)[2], (long) (parts)[3], \
		                 (long) (parts)[4], (long) (parts)[5], \
		                 (long) (parts)[6], (long) (parts)[7], \
		                 (double) (dparts)[0], (double) (dparts)[1], \
		                 (double) (dparts)[2], (double) (dparts)[3], \
		                 (double) (dparts)[4], (double) (dparts)[5], \
		                 (double) (dparts)[6], (double) (dparts)[7])); \
	} while (0)
#define  DUK__DPRINT_PARTS(parts)  do { \
		DUK_D(DUK_DPRINT("parts: %ld %ld %ld %ld %ld %ld %ld %ld", \
		                 (long) (parts)[0], (long) (parts)[1], \
		                 (long) (parts)[2], (long) (parts)[3], \
		                 (long) (parts)[4], (long) (parts)[5], \
		                 (long) (parts)[6], (long) (parts)[7])); \
	} while (0)
#define  DUK__DPRINT_DPARTS(dparts)  do { \
		DUK_D(DUK_DPRINT("dparts: %lf %lf %lf %lf %lf %lf %lf %lf", \
		                 (double) (dparts)[0], (double) (dparts)[1], \
		                 (double) (dparts)[2], (double) (dparts)[3], \
		                 (double) (dparts)[4], (double) (dparts)[5], \
		                 (double) (dparts)[6], (double) (dparts)[7])); \
	} while (0)

/* Equivalent year for DST calculations outside [1970,2038[ range, see
 * E5 Section 15.9.1.8.  Equivalent year has the same leap-year-ness and
 * starts with the same weekday on Jan 1.
 * https://bugzilla.mozilla.org/show_bug.cgi?id=351066
 */
#define DUK__YEAR(x) ((duk_uint8_t) ((x) - 1970))
DUK_LOCAL duk_uint8_t duk__date_equivyear[14] = {
#if 1
	/* This is based on V8 EquivalentYear() algorithm (see util/genequivyear.py):
	 * http://code.google.com/p/v8/source/browse/trunk/src/date.h#146
	 */

	/* non-leap year: sunday, monday, ... */
	DUK__YEAR(2023), DUK__YEAR(2035), DUK__YEAR(2019), DUK__YEAR(2031),
	DUK__YEAR(2015), DUK__YEAR(2027), DUK__YEAR(2011),

	/* leap year: sunday, monday, ... */
	DUK__YEAR(2012), DUK__YEAR(2024), DUK__YEAR(2008), DUK__YEAR(2020),
	DUK__YEAR(2032), DUK__YEAR(2016), DUK__YEAR(2028)
#endif

#if 0
	/* This is based on Rhino EquivalentYear() algorithm:
	 * https://github.com/mozilla/rhino/blob/f99cc11d616f0cdda2c42bde72b3484df6182947/src/org/mozilla/javascript/NativeDate.java
	 */

	/* non-leap year: sunday, monday, ... */
	DUK__YEAR(1978), DUK__YEAR(1973), DUK__YEAR(1985), DUK__YEAR(1986),
	DUK__YEAR(1981), DUK__YEAR(1971), DUK__YEAR(1977),

	/* leap year: sunday, monday, ... */
	DUK__YEAR(1984), DUK__YEAR(1996), DUK__YEAR(1980), DUK__YEAR(1992),
	DUK__YEAR(1976), DUK__YEAR(1988), DUK__YEAR(1972)
#endif
};

/*
 *  ISO 8601 subset parser.
 */

/* Parser part count. */
#define DUK__NUM_ISO8601_PARSER_PARTS  9

/* Parser part indices. */
#define DUK__PI_YEAR         0
#define DUK__PI_MONTH        1
#define DUK__PI_DAY          2
#define DUK__PI_HOUR         3
#define DUK__PI_MINUTE       4
#define DUK__PI_SECOND       5
#define DUK__PI_MILLISECOND  6
#define DUK__PI_TZHOUR       7
#define DUK__PI_TZMINUTE     8

/* Parser part masks. */
#define DUK__PM_YEAR         (1 << DUK__PI_YEAR)
#define DUK__PM_MONTH        (1 << DUK__PI_MONTH)
#define DUK__PM_DAY          (1 << DUK__PI_DAY)
#define DUK__PM_HOUR         (1 << DUK__PI_HOUR)
#define DUK__PM_MINUTE       (1 << DUK__PI_MINUTE)
#define DUK__PM_SECOND       (1 << DUK__PI_SECOND)
#define DUK__PM_MILLISECOND  (1 << DUK__PI_MILLISECOND)
#define DUK__PM_TZHOUR       (1 << DUK__PI_TZHOUR)
#define DUK__PM_TZMINUTE     (1 << DUK__PI_TZMINUTE)

/* Parser separator indices. */
#define DUK__SI_PLUS         0
#define DUK__SI_MINUS        1
#define DUK__SI_T            2
#define DUK__SI_SPACE        3
#define DUK__SI_COLON        4
#define DUK__SI_PERIOD       5
#define DUK__SI_Z            6
#define DUK__SI_NUL          7

/* Parser separator masks. */
#define DUK__SM_PLUS         (1 << DUK__SI_PLUS)
#define DUK__SM_MINUS        (1 << DUK__SI_MINUS)
#define DUK__SM_T            (1 << DUK__SI_T)
#define DUK__SM_SPACE        (1 << DUK__SI_SPACE)
#define DUK__SM_COLON        (1 << DUK__SI_COLON)
#define DUK__SM_PERIOD       (1 << DUK__SI_PERIOD)
#define DUK__SM_Z            (1 << DUK__SI_Z)
#define DUK__SM_NUL          (1 << DUK__SI_NUL)

/* Rule control flags. */
#define DUK__CF_NEG          (1 << 0)  /* continue matching, set neg_tzoffset flag */
#define DUK__CF_ACCEPT       (1 << 1)  /* accept string */
#define DUK__CF_ACCEPT_NUL   (1 << 2)  /* accept string if next char is NUL (otherwise reject) */

#define DUK__PACK_RULE(partmask,sepmask,nextpart,flags)  \
	((duk_uint32_t) (partmask) + \
	 (((duk_uint32_t) (sepmask)) << 9) + \
	 (((duk_uint32_t) (nextpart)) << 17) + \
	 (((duk_uint32_t) (flags)) << 21))

#define DUK__UNPACK_RULE(rule,var_nextidx,var_flags)  do { \
		(var_nextidx) = (duk_small_uint_t) (((rule) >> 17) & 0x0f); \
		(var_flags) = (duk_small_uint_t) ((rule) >> 21); \
	} while (0)

#define DUK__RULE_MASK_PART_SEP  0x1ffffUL

/* Matching separator index is used in the control table */
DUK_LOCAL const duk_uint8_t duk__parse_iso8601_seps[] = {
	DUK_ASC_PLUS /*0*/, DUK_ASC_MINUS /*1*/, DUK_ASC_UC_T /*2*/, DUK_ASC_SPACE /*3*/,
	DUK_ASC_COLON /*4*/, DUK_ASC_PERIOD /*5*/, DUK_ASC_UC_Z /*6*/, DUK_ASC_NUL /*7*/
};

/* Rule table: first matching rule is used to determine what to do next. */
DUK_LOCAL const duk_uint32_t duk__parse_iso8601_control[] = {
	DUK__PACK_RULE(DUK__PM_YEAR, DUK__SM_MINUS, DUK__PI_MONTH, 0),
	DUK__PACK_RULE(DUK__PM_MONTH, DUK__SM_MINUS, DUK__PI_DAY, 0),
	DUK__PACK_RULE(DUK__PM_YEAR | DUK__PM_MONTH | DUK__PM_DAY, DUK__SM_T | DUK__SM_SPACE, DUK__PI_HOUR, 0),
	DUK__PACK_RULE(DUK__PM_HOUR, DUK__SM_COLON, DUK__PI_MINUTE, 0),
	DUK__PACK_RULE(DUK__PM_MINUTE, DUK__SM_COLON, DUK__PI_SECOND, 0),
	DUK__PACK_RULE(DUK__PM_SECOND, DUK__SM_PERIOD, DUK__PI_MILLISECOND, 0),
	DUK__PACK_RULE(DUK__PM_TZHOUR, DUK__SM_COLON, DUK__PI_TZMINUTE, 0),
	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),
	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),
	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),
	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)

	/* Note1: the specification doesn't require matching a time form with
	 *        just hours ("HH"), but we accept it here, e.g. "2012-01-02T12Z".
	 *
	 * Note2: the specification doesn't require matching a timezone offset
	 *        with just hours ("HH"), but accept it here, e.g. "2012-01-02T03:04:05+02"
	 */
};

DUK_LOCAL duk_bool_t duk__parse_string_iso8601_subset(duk_hthread *thr, const char *str) {
	duk_int_t parts[DUK__NUM_ISO8601_PARSER_PARTS];
	duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
	duk_double_t d;
	const duk_uint8_t *p;
	duk_small_uint_t part_idx = 0;
	duk_int_t accum = 0;
	duk_small_uint_t ndigits = 0;
	duk_bool_t neg_year = 0;
	duk_bool_t neg_tzoffset = 0;
	duk_uint_fast8_t ch;
	duk_small_uint_t i;

	/* During parsing, month and day are one-based; set defaults here. */
	duk_memzero(parts, sizeof(parts));
	DUK_ASSERT(parts[DUK_DATE_IDX_YEAR] == 0);  /* don't care value, year is mandatory */
	parts[DUK_DATE_IDX_MONTH] = 1;
	parts[DUK_DATE_IDX_DAY] = 1;

	/* Special handling for year sign. */
	p = (const duk_uint8_t *) str;
	ch = p[0];
	if (ch == DUK_ASC_PLUS) {
		p++;
	} else if (ch == DUK_ASC_MINUS) {
		neg_year = 1;
		p++;
	}

	for (;;) {
		ch = *p++;
		DUK_DDD(DUK_DDDPRINT("parsing, part_idx=%ld, char=%ld ('%c')",
		                     (long) part_idx, (long) ch,
		                     (int) ((ch >= 0x20 && ch <= 0x7e) ? ch : DUK_ASC_QUESTION)));

		if (ch >= DUK_ASC_0 && ch <= DUK_ASC_9) {
			if (ndigits >= 9) {
				DUK_DDD(DUK_DDDPRINT("too many digits -> reject"));
				goto reject;
			}
			if (part_idx == DUK__PI_MILLISECOND && ndigits >= 3) {
				/* ignore millisecond fractions after 3 */
			} else {
				accum = accum * 10 + ((duk_int_t) ch) - ((duk_int_t) DUK_ASC_0) + 0x00;
				ndigits++;
			}
		} else {
			duk_uint_fast32_t match_val;
			duk_small_uint_t sep_idx;

			if (ndigits <= 0) {
				goto reject;
			}
			if (part_idx == DUK__PI_MILLISECOND) {
				/* complete the millisecond field */
				while (ndigits < 3) {
					accum *= 10;
					ndigits++;
				}
			}
			parts[part_idx] = accum;
			DUK_DDD(DUK_DDDPRINT("wrote part %ld -> value %ld", (long) part_idx, (long) accum));

			accum = 0;
			ndigits = 0;

			for (i = 0; i < (duk_small_uint_t) (sizeof(duk__parse_iso8601_seps) / sizeof(duk_uint8_t)); i++) {
				if (duk__parse_iso8601_seps[i] == ch) {
					break;
				}
			}
			if (i == (duk_small_uint_t) (sizeof(duk__parse_iso8601_seps) / sizeof(duk_uint8_t))) {
				DUK_DDD(DUK_DDDPRINT("separator character doesn't match -> reject"));
				goto reject;
			}

			sep_idx = i;
			match_val = (1UL << part_idx) + (1UL << (sep_idx + 9));  /* match against rule part/sep bits */

			for (i = 0; i < (duk_small_uint_t) (sizeof(duk__parse_iso8601_control) / sizeof(duk_uint32_t)); i++) {
				duk_uint_fast32_t rule = duk__parse_iso8601_control[i];
				duk_small_uint_t nextpart;
				duk_small_uint_t cflags;

				DUK_DDD(DUK_DDDPRINT("part_idx=%ld, sep_idx=%ld, match_val=0x%08lx, considering rule=0x%08lx",
				                     (long) part_idx, (long) sep_idx,
				                     (unsigned long) match_val, (unsigned long) rule));

				if ((rule & match_val) != match_val) {
					continue;
				}

				DUK__UNPACK_RULE(rule, nextpart, cflags);

				DUK_DDD(DUK_DDDPRINT("rule match -> part_idx=%ld, sep_idx=%ld, match_val=0x%08lx, "
				                     "rule=0x%08lx -> nextpart=%ld, cflags=0x%02lx",
				                     (long) part_idx, (long) sep_idx,
				                     (unsigned long) match_val, (unsigned long) rule,
				                     (long) nextpart, (unsigned long) cflags));

				if (cflags & DUK__CF_NEG) {
					neg_tzoffset = 1;
				}

				if (cflags & DUK__CF_ACCEPT) {
					goto accept;
				}

				if (cflags & DUK__CF_ACCEPT_NUL) {
					DUK_ASSERT(*(p - 1) != (char) 0);
					if (*p == DUK_ASC_NUL) {
						goto accept;
					}
					goto reject;
				}

				part_idx = nextpart;
				break;
			}  /* rule match */

			if (i == (duk_small_uint_t) (sizeof(duk__parse_iso8601_control) / sizeof(duk_uint32_t))) {
				DUK_DDD(DUK_DDDPRINT("no rule matches -> reject"));
				goto reject;
			}

			if (ch == 0) {
				/* This shouldn't be necessary, but check just in case
				 * to avoid any chance of overruns.
				 */
				DUK_DDD(DUK_DDDPRINT("NUL after rule matching (should not happen) -> reject"));
				goto reject;
			}
		}  /* if-digit-else-ctrl */
	}  /* char loop */

	/* We should never exit the loop above. */
	DUK_UNREACHABLE();

 reject:
	DUK_DDD(DUK_DDDPRINT("reject"));
	return 0;

 accept:
	DUK_DDD(DUK_DDDPRINT("accept"));

	/* Apply timezone offset to get the main parts in UTC */
	if (neg_year) {
		parts[DUK__PI_YEAR] = -parts[DUK__PI_YEAR];
	}
	if (neg_tzoffset) {
		parts[DUK__PI_HOUR] += parts[DUK__PI_TZHOUR];
		parts[DUK__PI_MINUTE] += parts[DUK__PI_TZMINUTE];
	} else {
		parts[DUK__PI_HOUR] -= parts[DUK__PI_TZHOUR];
		parts[DUK__PI_MINUTE] -= parts[DUK__PI_TZMINUTE];
	}
	parts[DUK__PI_MONTH] -= 1;  /* zero-based month */
	parts[DUK__PI_DAY] -= 1;  /* zero-based day */

	/* Use double parts, they tolerate unnormalized time.
	 *
	 * Note: DUK_DATE_IDX_WEEKDAY is initialized with a bogus value (DUK__PI_TZHOUR)
	 * on purpose.  It won't be actually used by duk_bi_date_get_timeval_from_dparts(),
	 * but will make the value initialized just in case, and avoid any
	 * potential for Valgrind issues.
	 */
	for (i = 0; i < DUK_DATE_IDX_NUM_PARTS; i++) {
		DUK_DDD(DUK_DDDPRINT("part[%ld] = %ld", (long) i, (long) parts[i]));
		dparts[i] = parts[i];
	}

	d = duk_bi_date_get_timeval_from_dparts(dparts, 0 /*flags*/);
	duk_push_number(thr, d);
	return 1;
}

/*
 *  Date/time parsing helper.
 *
 *  Parse a datetime string into a time value.  We must first try to parse
 *  the input according to the standard format in E5.1 Section 15.9.1.15.
 *  If that fails, we can try to parse using custom parsing, which can
 *  either be platform neutral (custom code) or platform specific (using
 *  existing platform API calls).
 *
 *  Note in particular that we must parse whatever toString(), toUTCString(),
 *  and toISOString() can produce; see E5.1 Section 15.9.4.2.
 *
 *  Returns 1 to allow tail calling.
 *
 *  There is much room for improvement here with respect to supporting
 *  alternative datetime formats.  For instance, V8 parses '2012-01-01' as
 *  UTC and '2012/01/01' as local time.
 */

DUK_LOCAL duk_ret_t duk__parse_string(duk_hthread *thr, const char *str) {
	/* XXX: there is a small risk here: because the ISO 8601 parser is
	 * very loose, it may end up parsing some datetime values which
	 * would be better parsed with a platform specific parser.
	 */

	DUK_ASSERT(str != NULL);
	DUK_DDD(DUK_DDDPRINT("parse datetime from string '%s'", (const char *) str));

	if (duk__parse_string_iso8601_subset(thr, str) != 0) {
		return 1;
	}

#if defined(DUK_USE_DATE_PARSE_STRING)
	/* Contract, either:
	 * - Push value on stack and return 1
	 * - Don't push anything on stack and return 0
	 */

	if (DUK_USE_DATE_PARSE_STRING(thr, str) != 0) {
		return 1;
	}
#else
	/* No platform-specific parsing, this is not an error. */
#endif

	duk_push_nan(thr);
	return 1;
}

/*
 *  Calendar helpers
 *
 *  Some helpers are used for getters and can operate on normalized values
 *  which can be represented with 32-bit signed integers.  Other helpers are
 *  needed by setters and operate on un-normalized double values, must watch
 *  out for non-finite numbers etc.
 */

DUK_LOCAL duk_uint8_t duk__days_in_month[12] = {
	(duk_uint8_t) 31, (duk_uint8_t) 28, (duk_uint8_t) 31, (duk_uint8_t) 30,
	(duk_uint8_t) 31, (duk_uint8_t) 30, (duk_uint8_t) 31, (duk_uint8_t) 31,
	(duk_uint8_t) 30, (duk_uint8_t) 31, (duk_uint8_t) 30, (duk_uint8_t) 31
};

/* Maximum iteration count for computing UTC-to-local time offset when
 * creating an ECMAScript time value from local parts.
 */
#define DUK__LOCAL_TZOFFSET_MAXITER   4

/* Because 'day since epoch' can be negative and is used to compute weekday
 * using a modulo operation, add this multiple of 7 to avoid negative values
 * when year is below 1970 epoch.  ECMAScript time values are restricted to
 * +/- 100 million days from epoch, so this adder fits nicely into 32 bits.
 * Round to a multiple of 7 (= floor(100000000 / 7) * 7) and add margin.
 */
#define DUK__WEEKDAY_MOD_ADDER  (20000000 * 7)  /* 0x08583b00 */

DUK_INTERNAL duk_bool_t duk_bi_date_is_leap_year(duk_int_t year) {
	if ((year % 4) != 0) {
		return 0;
	}
	if ((year % 100) != 0) {
		return 1;
	}
	if ((year % 400) != 0) {
		return 0;
	}
	return 1;
}

DUK_INTERNAL duk_bool_t duk_bi_date_timeval_in_valid_range(duk_double_t x) {
	return (x >= -DUK_DATE_MSEC_100M_DAYS && x <= DUK_DATE_MSEC_100M_DAYS);
}

DUK_INTERNAL duk_bool_t duk_bi_date_timeval_in_leeway_range(duk_double_t x) {
	return (x >= -DUK_DATE_MSEC_100M_DAYS_LEEWAY && x <= DUK_DATE_MSEC_100M_DAYS_LEEWAY);
}

DUK_INTERNAL duk_bool_t duk_bi_date_year_in_valid_range(duk_double_t x) {
	return (x >= DUK_DATE_MIN_ECMA_YEAR && x <= DUK_DATE_MAX_ECMA_YEAR);
}

DUK_LOCAL duk_double_t duk__timeclip(duk_double_t x) {
	if (!DUK_ISFINITE(x)) {
		return DUK_DOUBLE_NAN;
	}

	if (!duk_bi_date_timeval_in_valid_range(x)) {
		return DUK_DOUBLE_NAN;
	}

	x = duk_js_tointeger_number(x);

	/* Here we'd have the option to normalize -0 to +0. */
	return x;
}

/* Integer division which floors also negative values correctly. */
DUK_LOCAL duk_int_t duk__div_floor(duk_int_t a, duk_int_t b) {
	DUK_ASSERT(b > 0);
	if (a >= 0) {
		return a / b;
	} else {
		/* e.g. a = -4, b = 5  -->  -4 - 5 + 1 / 5  -->  -8 / 5  -->  -1
		 *      a = -5, b = 5  -->  -5 - 5 + 1 / 5  -->  -9 / 5  -->  -1
		 *      a = -6, b = 5  -->  -6 - 5 + 1 / 5  -->  -10 / 5  -->  -2
		 */
		return (a - b + 1) / b;
	}
}

/* Compute day number of the first day of a given year. */
DUK_LOCAL duk_int_t duk__day_from_year(duk_int_t year) {
	/* Note: in integer arithmetic, (x / 4) is same as floor(x / 4) for non-negative
	 * values, but is incorrect for negative ones.
	 */
	return 365 * (year - 1970)
	       + duk__div_floor(year - 1969, 4)
	       - duk__div_floor(year - 1901, 100)
	       + duk__div_floor(year - 1601, 400);
}

/* Given a day number, determine year and day-within-year. */
DUK_LOCAL duk_int_t duk__year_from_day(duk_int_t day, duk_small_int_t *out_day_within_year) {
	duk_int_t year;
	duk_int_t diff_days;

	/* estimate year upwards (towards positive infinity), then back down;
	 * two iterations should be enough
	 */

	if (day >= 0) {
		year = 1970 + day / 365;
	} else {
		year = 1970 + day / 366;
	}

	for (;;) {
		diff_days = duk__day_from_year(year) - day;
		DUK_DDD(DUK_DDDPRINT("year=%ld day=%ld, diff_days=%ld", (long) year, (long) day, (long) diff_days));
		if (diff_days <= 0) {
			DUK_ASSERT(-diff_days < 366);  /* fits into duk_small_int_t */
			*out_day_within_year = -diff_days;
			DUK_DDD(DUK_DDDPRINT("--> year=%ld, day-within-year=%ld",
			                     (long) year, (long) *out_day_within_year));
			DUK_ASSERT(*out_day_within_year >= 0);
			DUK_ASSERT(*out_day_within_year < (duk_bi_date_is_leap_year(year) ? 366 : 365));
			return year;
		}

		/* Note: this is very tricky; we must never 'overshoot' the
		 * correction downwards.
		 */
		year -= 1 + (diff_days - 1) / 366;  /* conservative */
	}
}

/* Given a (year, month, day-within-month) triple, compute day number.
 * The input triple is un-normalized and may contain non-finite values.
 */
DUK_LOCAL duk_double_t duk__make_day(duk_double_t year, duk_double_t month, duk_double_t day) {
	duk_int_t day_num;
	duk_bool_t is_leap;
	duk_small_int_t i, n;

	/* Assume that year, month, day are all coerced to whole numbers.
	 * They may also be NaN or infinity, in which case this function
	 * must return NaN or infinity to ensure time value becomes NaN.
	 * If 'day' is NaN, the final return will end up returning a NaN,
	 * so it doesn't need to be checked here.
	 */

	if (!DUK_ISFINITE(year) || !DUK_ISFINITE(month)) {
		return DUK_DOUBLE_NAN;
	}

	year += DUK_FLOOR(month / 12.0);

	month = DUK_FMOD(month, 12.0);
	if (month < 0.0) {
		/* handle negative values */
		month += 12.0;
	}

	/* The algorithm in E5.1 Section 15.9.1.12 normalizes month, but
	 * does not normalize the day-of-month (nor check whether or not
	 * it is finite) because it's not necessary for finding the day
	 * number which matches the (year,month) pair.
	 *
	 * We assume that duk__day_from_year() is exact here.
	 *
	 * Without an explicit infinity / NaN check in the beginning,
	 * day_num would be a bogus integer here.
	 *
	 * It's possible for 'year' to be out of integer range here.
	 * If so, we need to return NaN without integer overflow.
	 * This fixes test-bug-setyear-overflow.js.
	 */

	if (!duk_bi_date_year_in_valid_range(year)) {
		DUK_DD(DUK_DDPRINT("year not in ecmascript valid range, avoid integer overflow: %lf", (double) year));
		return DUK_DOUBLE_NAN;
	}
	day_num = duk__day_from_year((duk_int_t) year);
	is_leap = duk_bi_date_is_leap_year((duk_int_t) year);

	n = (duk_small_int_t) month;
	for (i = 0; i < n; i++) {
		day_num += duk__days_in_month[i];
		if (i == 1 && is_leap) {
			day_num++;
		}
	}

	/* If 'day' is NaN, returns NaN. */
	return (duk_double_t) day_num + day;
}

/* Split time value into parts.  The time value may contain fractions (it may
 * come from duk_time_to_components() API call) which are truncated.  Possible
 * local time adjustment has already been applied when reading the time value.
 */
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) {
	duk_double_t d1, d2;
	duk_int_t t1, t2;
	duk_int_t day_since_epoch;
	duk_int_t year;  /* does not fit into 16 bits */
	duk_small_int_t day_in_year;
	duk_small_int_t month;
	duk_small_int_t day;
	duk_small_int_t dim;
	duk_int_t jan1_since_epoch;
	duk_small_int_t jan1_weekday;
	duk_int_t equiv_year;
	duk_small_uint_t i;
	duk_bool_t is_leap;
	duk_small_int_t arridx;

	DUK_ASSERT(DUK_ISFINITE(d));    /* caller checks */
	d = DUK_FLOOR(d);  /* remove fractions if present */
	DUK_ASSERT(duk_double_equals(DUK_FLOOR(d), d));

	/* The timevalue must be in valid ECMAScript range, but since a local
	 * time offset can be applied, we need to allow a +/- 24h leeway to
	 * the value.  In other words, although the UTC time is within the
	 * ECMAScript range, the local part values can be just outside of it.
	 */
	DUK_UNREF(duk_bi_date_timeval_in_leeway_range);
	DUK_ASSERT(duk_bi_date_timeval_in_leeway_range(d));

	/* These computations are guaranteed to be exact for the valid
	 * E5 time value range, assuming milliseconds without fractions.
	 */
	d1 = (duk_double_t) DUK_FMOD(d, (double) DUK_DATE_MSEC_DAY);
	if (d1 < 0.0) {
		/* deal with negative values */
		d1 += (duk_double_t) DUK_DATE_MSEC_DAY;
	}
	d2 = DUK_FLOOR((double) (d / (duk_double_t) DUK_DATE_MSEC_DAY));
	DUK_ASSERT(duk_double_equals(d2 * ((duk_double_t) DUK_DATE_MSEC_DAY) + d1, d));
	/* now expected to fit into a 32-bit integer */
	t1 = (duk_int_t) d1;
	t2 = (duk_int_t) d2;
	day_since_epoch = t2;
	DUK_ASSERT(duk_double_equals((duk_double_t) t1, d1));
	DUK_ASSERT(duk_double_equals((duk_double_t) t2, d2));

	/* t1 = milliseconds within day (fits 32 bit)
	 * t2 = day number from epoch (fits 32 bit, may be negative)
	 */

	parts[DUK_DATE_IDX_MILLISECOND] = t1 % 1000; t1 /= 1000;
	parts[DUK_DATE_IDX_SECOND] = t1 % 60; t1 /= 60;
	parts[DUK_DATE_IDX_MINUTE] = t1 % 60; t1 /= 60;
	parts[DUK_DATE_IDX_HOUR] = t1;
	DUK_ASSERT(parts[DUK_DATE_IDX_MILLISECOND] >= 0 && parts[DUK_DATE_IDX_MILLISECOND] <= 999);
	DUK_ASSERT(parts[DUK_DATE_IDX_SECOND] >= 0 && parts[DUK_DATE_IDX_SECOND] <= 59);
	DUK_ASSERT(parts[DUK_DATE_IDX_MINUTE] >= 0 && parts[DUK_DATE_IDX_MINUTE] <= 59);
	DUK_ASSERT(parts[DUK_DATE_IDX_HOUR] >= 0 && parts[DUK_DATE_IDX_HOUR] <= 23);

	DUK_DDD(DUK_DDDPRINT("d=%lf, d1=%lf, d2=%lf, t1=%ld, t2=%ld, parts: hour=%ld min=%ld sec=%ld msec=%ld",
	                     (double) d, (double) d1, (double) d2, (long) t1, (long) t2,
	                     (long) parts[DUK_DATE_IDX_HOUR],
	                     (long) parts[DUK_DATE_IDX_MINUTE],
	                     (long) parts[DUK_DATE_IDX_SECOND],
	                     (long) parts[DUK_DATE_IDX_MILLISECOND]));

	/* This assert depends on the input parts representing time inside
	 * the ECMAScript range.
	 */
	DUK_ASSERT(t2 + DUK__WEEKDAY_MOD_ADDER >= 0);
	parts[DUK_DATE_IDX_WEEKDAY] = (t2 + 4 + DUK__WEEKDAY_MOD_ADDER) % 7;  /* E5.1 Section 15.9.1.6 */
	DUK_ASSERT(parts[DUK_DATE_IDX_WEEKDAY] >= 0 && parts[DUK_DATE_IDX_WEEKDAY] <= 6);

	year = duk__year_from_day(t2, &day_in_year);
	day = day_in_year;
	is_leap = duk_bi_date_is_leap_year(year);
	for (month = 0; month < 12; month++) {
		dim = duk__days_in_month[month];
		if (month == 1 && is_leap) {
			dim++;
		}
		DUK_DDD(DUK_DDDPRINT("month=%ld, dim=%ld, day=%ld",
		                     (long) month, (long) dim, (long) day));
		if (day < dim) {
			break;
		}
		day -= dim;
	}
	DUK_DDD(DUK_DDDPRINT("final month=%ld", (long) month));
	DUK_ASSERT(month >= 0 && month <= 11);
	DUK_ASSERT(day >= 0 && day <= 31);

	/* Equivalent year mapping, used to avoid DST trouble when platform
	 * may fail to provide reasonable DST answers for dates outside the
	 * ordinary range (e.g. 1970-2038).  An equivalent year has the same
	 * leap-year-ness as the original year and begins on the same weekday
	 * (Jan 1).
	 *
	 * The year 2038 is avoided because there seem to be problems with it
	 * on some platforms.  The year 1970 is also avoided as there were
	 * practical problems with it; an equivalent year is used for it too,
	 * which breaks some DST computations for 1970 right now, see e.g.
	 * test-bi-date-tzoffset-brute-fi.js.
	 */
	if ((flags & DUK_DATE_FLAG_EQUIVYEAR) && (year < 1971 || year > 2037)) {
		DUK_ASSERT(is_leap == 0 || is_leap == 1);

		jan1_since_epoch = day_since_epoch - day_in_year;  /* day number for Jan 1 since epoch */
		DUK_ASSERT(jan1_since_epoch + DUK__WEEKDAY_MOD_ADDER >= 0);
		jan1_weekday = (jan1_since_epoch + 4 + DUK__WEEKDAY_MOD_ADDER) % 7;  /* E5.1 Section 15.9.1.6 */
		DUK_ASSERT(jan1_weekday >= 0 && jan1_weekday <= 6);
		arridx = jan1_weekday;
		if (is_leap) {
			arridx += 7;
		}
		DUK_ASSERT(arridx >= 0 && arridx < (duk_small_int_t) (sizeof(duk__date_equivyear) / sizeof(duk_uint8_t)));

		equiv_year = (duk_int_t) duk__date_equivyear[arridx] + 1970;
		year = equiv_year;
		DUK_DDD(DUK_DDDPRINT("equiv year mapping, year=%ld, day_in_year=%ld, day_since_epoch=%ld, "
		                     "jan1_since_epoch=%ld, jan1_weekday=%ld -> equiv year %ld",
		                     (long) year, (long) day_in_year, (long) day_since_epoch,
		                     (long) jan1_since_epoch, (long) jan1_weekday, (long) equiv_year));
	}

	parts[DUK_DATE_IDX_YEAR] = year;
	parts[DUK_DATE_IDX_MONTH] = month;
	parts[DUK_DATE_IDX_DAY] = day;

	if (flags & DUK_DATE_FLAG_ONEBASED) {
		parts[DUK_DATE_IDX_MONTH]++;  /* zero-based -> one-based */
		parts[DUK_DATE_IDX_DAY]++;    /* -""- */
	}

	if (dparts != NULL) {
		for (i = 0; i < DUK_DATE_IDX_NUM_PARTS; i++) {
			dparts[i] = (duk_double_t) parts[i];
		}
	}
}

/* Compute time value from (double) parts.  The parts can be either UTC
 * or local time; if local, they need to be (conceptually) converted into
 * UTC time.  The parts may represent valid or invalid time, and may be
 * wildly out of range (but may cancel each other and still come out in
 * the valid Date range).
 */
DUK_INTERNAL duk_double_t duk_bi_date_get_timeval_from_dparts(duk_double_t *dparts, duk_small_uint_t flags) {
#if defined(DUK_USE_PARANOID_DATE_COMPUTATION)
	/* See comments below on MakeTime why these are volatile. */
	volatile duk_double_t tmp_time;
	volatile duk_double_t tmp_day;
	volatile duk_double_t d;
#else
	duk_double_t tmp_time;
	duk_double_t tmp_day;
	duk_double_t d;
#endif
	duk_small_uint_t i;
	duk_int_t tzoff, tzoffprev1, tzoffprev2;

	/* Expects 'this' at top of stack on entry. */

	/* Coerce all finite parts with ToInteger().  ToInteger() must not
	 * be called for NaN/Infinity because it will convert e.g. NaN to
	 * zero.  If ToInteger() has already been called, this has no side
	 * effects and is idempotent.
	 *
	 * Don't read dparts[DUK_DATE_IDX_WEEKDAY]; it will cause Valgrind
	 * issues if the value is uninitialized.
	 */
	for (i = 0; i <= DUK_DATE_IDX_MILLISECOND; i++) {
		/* SCANBUILD: scan-build complains here about assigned value
		 * being garbage or undefined.  This is correct but operating
		 * on undefined values has no ill effect and is ignored by the
		 * caller in the case where this happens.
		 */
		d = dparts[i];
		if (DUK_ISFINITE(d)) {
			dparts[i] = duk_js_tointeger_number(d);
		}
	}

	/* Use explicit steps in computation to try to ensure that
	 * computation happens with intermediate results coerced to
	 * double values (instead of using something more accurate).
	 * E.g. E5.1 Section 15.9.1.11 requires use of IEEE 754
	 * rules (= ECMAScript '+' and '*' operators).
	 *
	 * Without 'volatile' even this approach fails on some platform
	 * and compiler combinations.  For instance, gcc 4.8.1 on Ubuntu
	 * 64-bit, with -m32 and without -std=c99, test-bi-date-canceling.js
	 * would fail because of some optimizations when computing tmp_time
	 * (MakeTime below).  Adding 'volatile' to tmp_time solved this
	 * particular problem (annoyingly, also adding debug prints or
	 * running the executable under valgrind hides it).
	 */

	/* MakeTime */
	tmp_time = 0.0;
	tmp_time += dparts[DUK_DATE_IDX_HOUR] * ((duk_double_t) DUK_DATE_MSEC_HOUR);
	tmp_time += dparts[DUK_DATE_IDX_MINUTE] * ((duk_double_t) DUK_DATE_MSEC_MINUTE);
	tmp_time += dparts[DUK_DATE_IDX_SECOND] * ((duk_double_t) DUK_DATE_MSEC_SECOND);
	tmp_time += dparts[DUK_DATE_IDX_MILLISECOND];

	/* MakeDay */
	tmp_day = duk__make_day(dparts[DUK_DATE_IDX_YEAR], dparts[DUK_DATE_IDX_MONTH], dparts[DUK_DATE_IDX_DAY]);

	/* MakeDate */
	d = tmp_day * ((duk_double_t) DUK_DATE_MSEC_DAY) + tmp_time;

	DUK_DDD(DUK_DDDPRINT("time=%lf day=%lf --> timeval=%lf",
	                     (double) tmp_time, (double) tmp_day, (double) d));

	/* Optional UTC conversion. */
	if (flags & DUK_DATE_FLAG_LOCALTIME) {
		/* DUK_USE_DATE_GET_LOCAL_TZOFFSET() needs to be called with a
		 * time value computed from UTC parts.  At this point we only
		 * have 'd' which is a time value computed from local parts, so
		 * it is off by the UTC-to-local time offset which we don't know
		 * yet.  The current solution for computing the UTC-to-local
		 * time offset is to iterate a few times and detect a fixed
		 * point or a two-cycle loop (or a sanity iteration limit),
		 * see test-bi-date-local-parts.js and test-bi-date-tzoffset-basic-fi.js.
		 *
		 * E5.1 Section 15.9.1.9:
		 * UTC(t) = t - LocalTZA - DaylightSavingTA(t - LocalTZA)
		 *
		 * For NaN/inf, DUK_USE_DATE_GET_LOCAL_TZOFFSET() returns 0.
		 */

#if 0
		/* Old solution: don't iterate, incorrect */
		tzoff = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d);
		DUK_DDD(DUK_DDDPRINT("tzoffset w/o iteration, tzoff=%ld", (long) tzoff));
		d -= tzoff * 1000L;
		DUK_UNREF(tzoffprev1);
		DUK_UNREF(tzoffprev2);
#endif

		/* Iteration solution */
		tzoff = 0;
		tzoffprev1 = 999999999L;  /* invalid value which never matches */
		for (i = 0; i < DUK__LOCAL_TZOFFSET_MAXITER; i++) {
			tzoffprev2 = tzoffprev1;
			tzoffprev1 = tzoff;
			tzoff = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d - tzoff * 1000L);
			DUK_DDD(DUK_DDDPRINT("tzoffset iteration, i=%d, tzoff=%ld, tzoffprev1=%ld tzoffprev2=%ld",
			                     (int) i, (long) tzoff, (long) tzoffprev1, (long) tzoffprev2));
			if (tzoff == tzoffprev1) {
				DUK_DDD(DUK_DDDPRINT("tzoffset iteration finished, i=%d, tzoff=%ld, tzoffprev1=%ld, tzoffprev2=%ld",
				                     (int) i, (long) tzoff, (long) tzoffprev1, (long) tzoffprev2));
				break;
			} else if (tzoff == tzoffprev2) {
				/* Two value cycle, see e.g. test-bi-date-tzoffset-basic-fi.js.
				 * In these cases, favor a higher tzoffset to get a consistent
				 * result which is independent of iteration count.  Not sure if
				 * this is a generically correct solution.
				 */
				DUK_DDD(DUK_DDDPRINT("tzoffset iteration two-value cycle, i=%d, tzoff=%ld, tzoffprev1=%ld, tzoffprev2=%ld",
				                     (int) i, (long) tzoff, (long) tzoffprev1, (long) tzoffprev2));
				if (tzoffprev1 > tzoff) {
					tzoff = tzoffprev1;
				}
				break;
			}
		}
		DUK_DDD(DUK_DDDPRINT("tzoffset iteration, tzoff=%ld", (long) tzoff));
		d -= tzoff * 1000L;
	}

	/* TimeClip(), which also handles Infinity -> NaN conversion */
	d = duk__timeclip(d);

	return d;
}

/*
 *  API oriented helpers
 */

/* Push 'this' binding, check that it is a Date object; then push the
 * internal time value.  At the end, stack is: [ ... this timeval ].
 * Returns the time value.  Local time adjustment is done if requested.
 */
DUK_LOCAL duk_double_t duk__push_this_get_timeval_tzoffset(duk_hthread *thr, duk_small_uint_t flags, duk_int_t *out_tzoffset) {
	duk_hobject *h;
	duk_double_t d;
	duk_int_t tzoffset = 0;

	duk_push_this(thr);
	h = duk_get_hobject(thr, -1);  /* XXX: getter with class check, useful in built-ins */
	if (h == NULL || DUK_HOBJECT_GET_CLASS_NUMBER(h) != DUK_HOBJECT_CLASS_DATE) {
		DUK_ERROR_TYPE(thr, "expected Date");
		DUK_WO_NORETURN(return 0.0;);
	}

	duk_xget_owndataprop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
	d = duk_to_number_m1(thr);
	duk_pop(thr);

	if (DUK_ISNAN(d)) {
		if (flags & DUK_DATE_FLAG_NAN_TO_ZERO) {
			d = 0.0;
		}
		if (flags & DUK_DATE_FLAG_NAN_TO_RANGE_ERROR) {
			DUK_ERROR_RANGE(thr, "Invalid Date");
			DUK_WO_NORETURN(return 0.0;);
		}
	}
	/* if no NaN handling flag, may still be NaN here, but not Inf */
	DUK_ASSERT(!DUK_ISINF(d));

	if (flags & DUK_DATE_FLAG_LOCALTIME) {
		/* Note: DST adjustment is determined using UTC time.
		 * If 'd' is NaN, tzoffset will be 0.
		 */
		tzoffset = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d);  /* seconds */
		d += tzoffset * 1000L;
	}
	if (out_tzoffset) {
		*out_tzoffset = tzoffset;
	}

	/* [ ... this ] */
	return d;
}

DUK_LOCAL duk_double_t duk__push_this_get_timeval(duk_hthread *thr, duk_small_uint_t flags) {
	return duk__push_this_get_timeval_tzoffset(thr, flags, NULL);
}

/* Set timeval to 'this' from dparts, push the new time value onto the
 * value stack and return 1 (caller can then tail call us).  Expects
 * the value stack to contain 'this' on the stack top.
 */
DUK_LOCAL duk_ret_t duk__set_this_timeval_from_dparts(duk_hthread *thr, duk_double_t *dparts, duk_small_uint_t flags) {
	duk_double_t d;

	/* [ ... this ] */

	d = duk_bi_date_get_timeval_from_dparts(dparts, flags);
	duk_push_number(thr, d);  /* -> [ ... this timeval_new ] */
	duk_dup_top(thr);         /* -> [ ... this timeval_new timeval_new ] */

	/* Must force write because e.g. .setYear() must work even when
	 * the Date instance is frozen.
	 */
	duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_W);

	/* Stack top: new time value, return 1 to allow tail calls. */
	return 1;
}

/* 'out_buf' must be at least DUK_BI_DATE_ISO8601_BUFSIZE long. */
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) {
	char yearstr[8];   /* "-123456\0" */
	char tzstr[8];     /* "+11:22\0" */
	char sep = (flags & DUK_DATE_FLAG_SEP_T) ? DUK_ASC_UC_T : DUK_ASC_SPACE;

	DUK_ASSERT(parts[DUK_DATE_IDX_MONTH] >= 1 && parts[DUK_DATE_IDX_MONTH] <= 12);
	DUK_ASSERT(parts[DUK_DATE_IDX_DAY] >= 1 && parts[DUK_DATE_IDX_DAY] <= 31);
	DUK_ASSERT(parts[DUK_DATE_IDX_YEAR] >= -999999 && parts[DUK_DATE_IDX_YEAR] <= 999999);

	/* Note: %06d for positive value, %07d for negative value to include
	 * sign and 6 digits.
	 */
	DUK_SNPRINTF(yearstr,
	             sizeof(yearstr),
	             (parts[DUK_DATE_IDX_YEAR] >= 0 && parts[DUK_DATE_IDX_YEAR] <= 9999) ? "%04ld" :
	                    ((parts[DUK_DATE_IDX_YEAR] >= 0) ? "+%06ld" : "%07ld"),
	             (long) parts[DUK_DATE_IDX_YEAR]);
	yearstr[sizeof(yearstr) - 1] = (char) 0;

	if (flags & DUK_DATE_FLAG_LOCALTIME) {
		/* tzoffset seconds are dropped; 16 bits suffice for
		 * time offset in minutes
		 */
		const char *fmt;
		duk_small_int_t tmp, arg_hours, arg_minutes;

		if (tzoffset >= 0) {
			tmp = tzoffset;
			fmt = "+%02d:%02d";
		} else {
			tmp = -tzoffset;
			fmt = "-%02d:%02d";
		}
		tmp = tmp / 60;
		arg_hours = tmp / 60;
		arg_minutes = tmp % 60;
		DUK_ASSERT(arg_hours <= 24);  /* Even less is actually guaranteed for a valid tzoffset. */
		arg_hours = arg_hours & 0x3f;  /* For [0,24] this is a no-op, but fixes GCC 7 warning, see https://github.com/svaarala/duktape/issues/1602. */

		DUK_SNPRINTF(tzstr, sizeof(tzstr), fmt, (int) arg_hours, (int) arg_minutes);
		tzstr[sizeof(tzstr) - 1] = (char) 0;
	} else {
		tzstr[0] = DUK_ASC_UC_Z;
		tzstr[1] = (char) 0;
	}

	/* Unlike year, the other parts fit into 16 bits so %d format
	 * is portable.
	 */
	if ((flags & DUK_DATE_FLAG_TOSTRING_DATE) && (flags & DUK_DATE_FLAG_TOSTRING_TIME)) {
		DUK_SPRINTF((char *) out_buf, "%s-%02d-%02d%c%02d:%02d:%02d.%03d%s",
		            (const char *) yearstr, (int) parts[DUK_DATE_IDX_MONTH], (int) parts[DUK_DATE_IDX_DAY], (int) sep,
		            (int) parts[DUK_DATE_IDX_HOUR], (int) parts[DUK_DATE_IDX_MINUTE],
		            (int) parts[DUK_DATE_IDX_SECOND], (int) parts[DUK_DATE_IDX_MILLISECOND], (const char *) tzstr);
	} else if (flags & DUK_DATE_FLAG_TOSTRING_DATE) {
		DUK_SPRINTF((char *) out_buf, "%s-%02d-%02d",
		            (const char *) yearstr, (int) parts[DUK_DATE_IDX_MONTH], (int) parts[DUK_DATE_IDX_DAY]);
	} else {
		DUK_ASSERT(flags & DUK_DATE_FLAG_TOSTRING_TIME);
		DUK_SPRINTF((char *) out_buf, "%02d:%02d:%02d.%03d%s",
		            (int) parts[DUK_DATE_IDX_HOUR], (int) parts[DUK_DATE_IDX_MINUTE],
		            (int) parts[DUK_DATE_IDX_SECOND], (int) parts[DUK_DATE_IDX_MILLISECOND],
		            (const char *) tzstr);
	}
}

/* Helper for string conversion calls: check 'this' binding, get the
 * internal time value, and format date and/or time in a few formats.
 * Return value allows tail calls.
 */
DUK_LOCAL duk_ret_t duk__to_string_helper(duk_hthread *thr, duk_small_uint_t flags) {
	duk_double_t d;
	duk_int_t parts[DUK_DATE_IDX_NUM_PARTS];
	duk_int_t tzoffset;  /* seconds, doesn't fit into 16 bits */
	duk_bool_t rc;
	duk_uint8_t buf[DUK_BI_DATE_ISO8601_BUFSIZE];

	DUK_UNREF(rc);  /* unreferenced with some options */

	d = duk__push_this_get_timeval_tzoffset(thr, flags, &tzoffset);
	if (DUK_ISNAN(d)) {
		duk_push_hstring_stridx(thr, DUK_STRIDX_INVALID_DATE);
		return 1;
	}
	DUK_ASSERT(DUK_ISFINITE(d));

	/* formatters always get one-based month/day-of-month */
	duk_bi_date_timeval_to_parts(d, parts, NULL, DUK_DATE_FLAG_ONEBASED);
	DUK_ASSERT(parts[DUK_DATE_IDX_MONTH] >= 1 && parts[DUK_DATE_IDX_MONTH] <= 12);
	DUK_ASSERT(parts[DUK_DATE_IDX_DAY] >= 1 && parts[DUK_DATE_IDX_DAY] <= 31);

	if (flags & DUK_DATE_FLAG_TOSTRING_LOCALE) {
		/* try locale specific formatter; if it refuses to format the
		 * string, fall back to an ISO 8601 formatted value in local
		 * time.
		 */
#if defined(DUK_USE_DATE_FORMAT_STRING)
		/* Contract, either:
		 * - Push string to value stack and return 1
		 * - Don't push anything and return 0
		 */

		rc = DUK_USE_DATE_FORMAT_STRING(thr, parts, tzoffset, flags);
		if (rc != 0) {
			return 1;
		}
#else
		/* No locale specific formatter; this is OK, we fall back
		 * to ISO 8601.
		 */
#endif
	}

	/* Different calling convention than above used because the helper
	 * is shared.
	 */
	duk__format_parts_iso8601(parts, tzoffset, flags, buf);
	duk_push_string(thr, (const char *) buf);
	return 1;
}

/* Helper for component getter calls: check 'this' binding, get the
 * internal time value, split it into parts (either as UTC time or
 * local time), push a specified component as a return value to the
 * value stack and return 1 (caller can then tail call us).
 */
DUK_LOCAL duk_ret_t duk__get_part_helper(duk_hthread *thr, duk_small_uint_t flags_and_idx) {
	duk_double_t d;
	duk_int_t parts[DUK_DATE_IDX_NUM_PARTS];
	duk_small_uint_t idx_part = (duk_small_uint_t) (flags_and_idx >> DUK_DATE_FLAG_VALUE_SHIFT);  /* unpack args */

	DUK_ASSERT_DISABLE(idx_part >= 0);  /* unsigned */
	DUK_ASSERT(idx_part < DUK_DATE_IDX_NUM_PARTS);

	d = duk__push_this_get_timeval(thr, flags_and_idx);
	if (DUK_ISNAN(d)) {
		duk_push_nan(thr);
		return 1;
	}
	DUK_ASSERT(DUK_ISFINITE(d));

	duk_bi_date_timeval_to_parts(d, parts, NULL, flags_and_idx);  /* no need to mask idx portion */

	/* Setter APIs detect special year numbers (0...99) and apply a +1900
	 * only in certain cases.  The legacy getYear() getter applies -1900
	 * unconditionally.
	 */
	duk_push_int(thr, (flags_and_idx & DUK_DATE_FLAG_SUB1900) ? parts[idx_part] - 1900 : parts[idx_part]);
	return 1;
}

/* Helper for component setter calls: check 'this' binding, get the
 * internal time value, split it into parts (either as UTC time or
 * local time), modify one or more components as specified, recompute
 * the time value, set it as the internal value.  Finally, push the
 * new time value as a return value to the value stack and return 1
 * (caller can then tail call us).
 */
DUK_LOCAL duk_ret_t duk__set_part_helper(duk_hthread *thr, duk_small_uint_t flags_and_maxnargs) {
	duk_double_t d;
	duk_int_t parts[DUK_DATE_IDX_NUM_PARTS];
	duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
	duk_idx_t nargs;
	duk_small_uint_t maxnargs = (duk_small_uint_t) (flags_and_maxnargs >> DUK_DATE_FLAG_VALUE_SHIFT);  /* unpack args */
	duk_small_uint_t idx_first, idx;
	duk_small_uint_t i;

	nargs = duk_get_top(thr);
	d = duk__push_this_get_timeval(thr, flags_and_maxnargs);
	DUK_ASSERT(DUK_ISFINITE(d) || DUK_ISNAN(d));

	if (DUK_ISFINITE(d)) {
		duk_bi_date_timeval_to_parts(d, parts, dparts, flags_and_maxnargs);
	} else {
		/* NaN timevalue: we need to coerce the arguments, but
		 * the resulting internal timestamp needs to remain NaN.
		 * This works but is not pretty: parts and dparts will
		 * be partially uninitialized, but we only write to them.
		 */
	}

	/*
	 *  Determining which datetime components to overwrite based on
	 *  stack arguments is a bit complicated, but important to factor
	 *  out from setters themselves for compactness.
	 *
	 *  If DUK_DATE_FLAG_TIMESETTER, maxnargs indicates setter type:
	 *
	 *   1 -> millisecond
	 *   2 -> second, [millisecond]
	 *   3 -> minute, [second], [millisecond]
	 *   4 -> hour, [minute], [second], [millisecond]
	 *
	 *  Else:
	 *
	 *   1 -> date
	 *   2 -> month, [date]
	 *   3 -> year, [month], [date]
	 *
	 *  By comparing nargs and maxnargs (and flags) we know which
	 *  components to override.  We rely on part index ordering.
	 */

	if (flags_and_maxnargs & DUK_DATE_FLAG_TIMESETTER) {
		DUK_ASSERT(maxnargs >= 1 && maxnargs <= 4);
		idx_first = DUK_DATE_IDX_MILLISECOND - (maxnargs - 1);
	} else {
		DUK_ASSERT(maxnargs >= 1 && maxnargs <= 3);
		idx_first = DUK_DATE_IDX_DAY - (maxnargs - 1);
	}
	DUK_ASSERT_DISABLE(idx_first >= 0);  /* unsigned */
	DUK_ASSERT(idx_first < DUK_DATE_IDX_NUM_PARTS);

	for (i = 0; i < maxnargs; i++) {
		if ((duk_idx_t) i >= nargs) {
			/* no argument given -> leave components untouched */
			break;
		}
		idx = idx_first + i;
		DUK_ASSERT_DISABLE(idx >= 0);  /* unsigned */
		DUK_ASSERT(idx < DUK_DATE_IDX_NUM_PARTS);

		if (idx == DUK_DATE_IDX_YEAR && (flags_and_maxnargs & DUK_DATE_FLAG_YEAR_FIXUP)) {
			duk__twodigit_year_fixup(thr, (duk_idx_t) i);
		}

		dparts[idx] = duk_to_number(thr, (duk_idx_t) i);

		if (idx == DUK_DATE_IDX_DAY) {
			/* Day-of-month is one-based in the API, but zero-based
			 * internally, so fix here.  Note that month is zero-based
			 * both in the API and internally.
			 */
			/* SCANBUILD: complains about use of uninitialized values.
			 * The complaint is correct, but operating in undefined
			 * values here is intentional in some cases and the caller
			 * ignores the results.
			 */
			dparts[idx] -= 1.0;
		}
	}

	/* Leaves new timevalue on stack top and returns 1, which is correct
	 * for part setters.
	 */
	if (DUK_ISFINITE(d)) {
		return duk__set_this_timeval_from_dparts(thr, dparts, flags_and_maxnargs);
	} else {
		/* Internal timevalue is already NaN, so don't touch it. */
		duk_push_nan(thr);
		return 1;
	}
}

/* Apply ToNumber() to specified index; if ToInteger(val) in [0,99], add
 * 1900 and replace value at idx_val.
 */
DUK_LOCAL void duk__twodigit_year_fixup(duk_hthread *thr, duk_idx_t idx_val) {
	duk_double_t d;

	/* XXX: idx_val would fit into 16 bits, but using duk_small_uint_t
	 * might not generate better code due to casting.
	 */

	/* E5 Sections 15.9.3.1, B.2.4, B.2.5 */
	duk_to_number(thr, idx_val);
	if (duk_is_nan(thr, idx_val)) {
		return;
	}
	duk_dup(thr, idx_val);
	duk_to_int(thr, -1);
	d = duk_get_number(thr, -1);  /* get as double to handle huge numbers correctly */
	if (d >= 0.0 && d <= 99.0) {
		d += 1900.0;
		duk_push_number(thr, d);
		duk_replace(thr, idx_val);
	}
	duk_pop(thr);
}

/* Set datetime parts from stack arguments, defaulting any missing values.
 * Day-of-week is not set; it is not required when setting the time value.
 */
DUK_LOCAL void duk__set_parts_from_args(duk_hthread *thr, duk_double_t *dparts, duk_idx_t nargs) {
	duk_double_t d;
	duk_small_uint_t i;
	duk_small_uint_t idx;

	/* Causes a ToNumber() coercion, but doesn't break coercion order since
	 * year is coerced first anyway.
	 */
	duk__twodigit_year_fixup(thr, 0);

	/* There are at most 7 args, but we use 8 here so that also
	 * DUK_DATE_IDX_WEEKDAY gets initialized (to zero) to avoid the potential
	 * for any Valgrind gripes later.
	 */
	for (i = 0; i < 8; i++) {
		/* Note: rely on index ordering */
		idx = DUK_DATE_IDX_YEAR + i;
		if ((duk_idx_t) i < nargs) {
			d = duk_to_number(thr, (duk_idx_t) i);
			if (idx == DUK_DATE_IDX_DAY) {
				/* Convert day from one-based to zero-based (internal).  This may
				 * cause the day part to be negative, which is OK.
				 */
				d -= 1.0;
			}
		} else {
			/* All components default to 0 except day-of-month which defaults
			 * to 1.  However, because our internal day-of-month is zero-based,
			 * it also defaults to zero here.
			 */
			d = 0.0;
		}
		dparts[idx] = d;
	}

	DUK_DDD(DUK_DDDPRINT("parts from args -> %lf %lf %lf %lf %lf %lf %lf %lf",
	                     (double) dparts[0], (double) dparts[1],
	                     (double) dparts[2], (double) dparts[3],
	                     (double) dparts[4], (double) dparts[5],
	                     (double) dparts[6], (double) dparts[7]));
}

/*
 *  Indirect magic value lookup for Date methods.
 *
 *  Date methods don't put their control flags into the function magic value
 *  because they wouldn't fit into a LIGHTFUNC's magic field.  Instead, the
 *  magic value is set to an index pointing to the array of control flags
 *  below.
 *
 *  This must be kept in strict sync with genbuiltins.py!
 */

static duk_uint16_t duk__date_magics[] = {
	/* 0: toString */
	DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_LOCALTIME,

	/* 1: toDateString */
	DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_LOCALTIME,

	/* 2: toTimeString */
	DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_LOCALTIME,

	/* 3: toLocaleString */
	DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_TOSTRING_LOCALE + DUK_DATE_FLAG_LOCALTIME,

	/* 4: toLocaleDateString */
	DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_LOCALE + DUK_DATE_FLAG_LOCALTIME,

	/* 5: toLocaleTimeString */
	DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_TOSTRING_LOCALE + DUK_DATE_FLAG_LOCALTIME,

	/* 6: toUTCString */
	DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_TIME,

	/* 7: toISOString */
	DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_NAN_TO_RANGE_ERROR + DUK_DATE_FLAG_SEP_T,

	/* 8: getFullYear */
	DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_YEAR << DUK_DATE_FLAG_VALUE_SHIFT),

	/* 9: getUTCFullYear */
	0 + (DUK_DATE_IDX_YEAR << DUK_DATE_FLAG_VALUE_SHIFT),

	/* 10: getMonth */
	DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_MONTH << DUK_DATE_FLAG_VALUE_SHIFT),

	/* 11: getUTCMonth */
	0 + (DUK_DATE_IDX_MONTH << DUK_DATE_FLAG_VALUE_SHIFT),

	/* 12: getDate */
	DUK_DATE_FLAG_ONEBASED + DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_DAY << DUK_DATE_FLAG_VALUE_SHIFT),

	/* 13: getUTCDate */
	DUK_DATE_FLAG_ONEBASED + (DUK_DATE_IDX_DAY << DUK_DATE_FLAG_VALUE_SHIFT),

	/* 14: getDay */
	DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_WEEKDAY << DUK_DATE_FLAG_VALUE_SHIFT),

	/* 15: getUTCDay */
	0 + (DUK_DATE_IDX_WEEKDAY << DUK_DATE_FLAG_VALUE_SHIFT),

	/* 16: getHours */
	DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_HOUR << DUK_DATE_FLAG_VALUE_SHIFT),

	/* 17: getUTCHours */
	0 + (DUK_DATE_IDX_HOUR << DUK_DATE_FLAG_VALUE_SHIFT),

	/* 18: getMinutes */
	DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_MINUTE << DUK_DATE_FLAG_VALUE_SHIFT),

	/* 19: getUTCMinutes */
	0 + (DUK_DATE_IDX_MINUTE << DUK_DATE_FLAG_VALUE_SHIFT),

	/* 20: getSeconds */
	DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_SECOND << DUK_DATE_FLAG_VALUE_SHIFT),

	/* 21: getUTCSeconds */
	0 + (DUK_DATE_IDX_SECOND << DUK_DATE_FLAG_VALUE_SHIFT),

	/* 22: getMilliseconds */
	DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_MILLISECOND << DUK_DATE_FLAG_VALUE_SHIFT),

	/* 23: getUTCMilliseconds */
	0 + (DUK_DATE_IDX_MILLISECOND << DUK_DATE_FLAG_VALUE_SHIFT),

	/* 24: setMilliseconds */
	DUK_DATE_FLAG_TIMESETTER + DUK_DATE_FLAG_LOCALTIME + (1 << DUK_DATE_FLAG_VALUE_SHIFT),

	/* 25: setUTCMilliseconds */
	DUK_DATE_FLAG_TIMESETTER + (1 << DUK_DATE_FLAG_VALUE_SHIFT),

	/* 26: setSeconds */
	DUK_DATE_FLAG_TIMESETTER + DUK_DATE_FLAG_LOCALTIME + (2 << DUK_DATE_FLAG_VALUE_SHIFT),

	/* 27: setUTCSeconds */
	DUK_DATE_FLAG_TIMESETTER + (2 << DUK_DATE_FLAG_VALUE_SHIFT),

	/* 28: setMinutes */
	DUK_DATE_FLAG_TIMESETTER + DUK_DATE_FLAG_LOCALTIME + (3 << DUK_DATE_FLAG_VALUE_SHIFT),

	/* 29: setUTCMinutes */
	DUK_DATE_FLAG_TIMESETTER + (3 << DUK_DATE_FLAG_VALUE_SHIFT),

	/* 30: setHours */
	DUK_DATE_FLAG_TIMESETTER + DUK_DATE_FLAG_LOCALTIME + (4 << DUK_DATE_FLAG_VALUE_SHIFT),

	/* 31: setUTCHours */
	DUK_DATE_FLAG_TIMESETTER + (4 << DUK_DATE_FLAG_VALUE_SHIFT),

	/* 32: setDate */
	DUK_DATE_FLAG_LOCALTIME + (1 << DUK_DATE_FLAG_VALUE_SHIFT),

	/* 33: setUTCDate */
	0 + (1 << DUK_DATE_FLAG_VALUE_SHIFT),

	/* 34: setMonth */
	DUK_DATE_FLAG_LOCALTIME + (2 << DUK_DATE_FLAG_VALUE_SHIFT),

	/* 35: setUTCMonth */
	0 + (2 << DUK_DATE_FLAG_VALUE_SHIFT),

	/* 36: setFullYear */
	DUK_DATE_FLAG_NAN_TO_ZERO + DUK_DATE_FLAG_LOCALTIME + (3 << DUK_DATE_FLAG_VALUE_SHIFT),

	/* 37: setUTCFullYear */
	DUK_DATE_FLAG_NAN_TO_ZERO + (3 << DUK_DATE_FLAG_VALUE_SHIFT),

	/* 38: getYear */
	DUK_DATE_FLAG_LOCALTIME + DUK_DATE_FLAG_SUB1900 + (DUK_DATE_IDX_YEAR << DUK_DATE_FLAG_VALUE_SHIFT),

	/* 39: setYear */
	DUK_DATE_FLAG_NAN_TO_ZERO + DUK_DATE_FLAG_YEAR_FIXUP + (3 << DUK_DATE_FLAG_VALUE_SHIFT),
};

DUK_LOCAL duk_small_uint_t duk__date_get_indirect_magic(duk_hthread *thr) {
	duk_small_uint_t magicidx = (duk_small_uint_t) duk_get_current_magic(thr);
	DUK_ASSERT(magicidx < (duk_small_int_t) (sizeof(duk__date_magics) / sizeof(duk_uint16_t)));
	return (duk_small_uint_t) duk__date_magics[magicidx];
}

#if defined(DUK_USE_DATE_BUILTIN)
/*
 *  Constructor calls
 */

DUK_INTERNAL duk_ret_t duk_bi_date_constructor(duk_hthread *thr) {
	duk_idx_t nargs = duk_get_top(thr);
	duk_bool_t is_cons = duk_is_constructor_call(thr);
	duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
	duk_double_t d;

	DUK_DDD(DUK_DDDPRINT("Date constructor, nargs=%ld, is_cons=%ld", (long) nargs, (long) is_cons));

	(void) duk_push_object_helper(thr,
	                              DUK_HOBJECT_FLAG_EXTENSIBLE |
	                              DUK_HOBJECT_FLAG_FASTREFS |
	                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DATE),
	                              DUK_BIDX_DATE_PROTOTYPE);

	/* Unlike most built-ins, the internal [[PrimitiveValue]] of a Date
	 * is mutable.
	 */

	if (nargs == 0 || !is_cons) {
		d = duk__timeclip(duk_time_get_ecmascript_time_nofrac(thr));
		duk_push_number(thr, d);
		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_W);
		if (!is_cons) {
			/* called as a normal function: return new Date().toString() */
			duk_to_string(thr, -1);
		}
		return 1;
	} else if (nargs == 1) {
		const char *str;
		duk_to_primitive(thr, 0, DUK_HINT_NONE);
		str = duk_get_string_notsymbol(thr, 0);
		if (str) {
			duk__parse_string(thr, str);
			duk_replace(thr, 0);  /* may be NaN */
		}
		d = duk__timeclip(duk_to_number(thr, 0));  /* symbols fail here */
		duk_push_number(thr, d);
		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_W);
		return 1;
	}

	duk__set_parts_from_args(thr, dparts, nargs);

	/* Parts are in local time, convert when setting. */

	(void) duk__set_this_timeval_from_dparts(thr, dparts, DUK_DATE_FLAG_LOCALTIME /*flags*/);  /* -> [ ... this timeval ] */
	duk_pop(thr);  /* -> [ ... this ] */
	return 1;
}

DUK_INTERNAL duk_ret_t duk_bi_date_constructor_parse(duk_hthread *thr) {
	return duk__parse_string(thr, duk_to_string(thr, 0));
}

DUK_INTERNAL duk_ret_t duk_bi_date_constructor_utc(duk_hthread *thr) {
	duk_idx_t nargs = duk_get_top(thr);
	duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
	duk_double_t d;

	/* Behavior for nargs < 2 is implementation dependent: currently we'll
	 * set a NaN time value (matching V8 behavior) in this case.
	 */

	if (nargs < 2) {
		duk_push_nan(thr);
	} else {
		duk__set_parts_from_args(thr, dparts, nargs);
		d = duk_bi_date_get_timeval_from_dparts(dparts, 0 /*flags*/);
		duk_push_number(thr, d);
	}
	return 1;
}

DUK_INTERNAL duk_ret_t duk_bi_date_constructor_now(duk_hthread *thr) {
	duk_double_t d;

	d = duk_time_get_ecmascript_time_nofrac(thr);
	DUK_ASSERT(duk_double_equals(duk__timeclip(d), d));  /* TimeClip() should never be necessary */
	duk_push_number(thr, d);
	return 1;
}

/*
 *  String/JSON conversions
 *
 *  Human readable conversions are now basically ISO 8601 with a space
 *  (instead of 'T') as the date/time separator.  This is a good baseline
 *  and is platform independent.
 *
 *  A shared native helper to provide many conversions.  Magic value contains
 *  a set of flags.  The helper provides:
 *
 *    toString()
 *    toDateString()
 *    toTimeString()
 *    toLocaleString()
 *    toLocaleDateString()
 *    toLocaleTimeString()
 *    toUTCString()
 *    toISOString()
 *
 *  Notes:
 *
 *    - Date.prototype.toGMTString() and Date.prototype.toUTCString() are
 *      required to be the same ECMAScript function object (!), so it is
 *      omitted from here.
 *
 *    - Date.prototype.toUTCString(): E5.1 specification does not require a
 *      specific format, but result should be human readable.  The
 *      specification suggests using ISO 8601 format with a space (instead
 *      of 'T') separator if a more human readable format is not available.
 *
 *    - Date.prototype.toISOString(): unlike other conversion functions,
 *      toISOString() requires a RangeError for invalid date values.
 */

DUK_INTERNAL duk_ret_t duk_bi_date_prototype_tostring_shared(duk_hthread *thr) {
	duk_small_uint_t flags = duk__date_get_indirect_magic(thr);
	return duk__to_string_helper(thr, flags);
}

DUK_INTERNAL duk_ret_t duk_bi_date_prototype_value_of(duk_hthread *thr) {
	/* This native function is also used for Date.prototype.getTime()
	 * as their behavior is identical.
	 */

	duk_double_t d = duk__push_this_get_timeval(thr, 0 /*flags*/);  /* -> [ this ] */
	DUK_ASSERT(DUK_ISFINITE(d) || DUK_ISNAN(d));
	duk_push_number(thr, d);
	return 1;
}

DUK_INTERNAL duk_ret_t duk_bi_date_prototype_to_json(duk_hthread *thr) {
	/* Note: toJSON() is a generic function which works even if 'this'
	 * is not a Date.  The sole argument is ignored.
	 */

	duk_push_this(thr);
	duk_to_object(thr, -1);

	duk_dup_top(thr);
	duk_to_primitive(thr, -1, DUK_HINT_NUMBER);
	if (duk_is_number(thr, -1)) {
		duk_double_t d = duk_get_number(thr, -1);
		if (!DUK_ISFINITE(d)) {
			duk_push_null(thr);
			return 1;
		}
	}
	duk_pop(thr);

	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_TO_ISO_STRING);
	duk_dup_m2(thr);  /* -> [ O toIsoString O ] */
	duk_call_method(thr, 0);
	return 1;
}

/*
 *  Getters.
 *
 *  Implementing getters is quite easy.  The internal time value is either
 *  NaN, or represents milliseconds (without fractions) from Jan 1, 1970.
 *  The internal time value can be converted to integer parts, and each
 *  part will be normalized and will fit into a 32-bit signed integer.
 *
 *  A shared native helper to provide all getters.  Magic value contains
 *  a set of flags and also packs the date component index argument.  The
 *  helper provides:
 *
 *    getFullYear()
 *    getUTCFullYear()
 *    getMonth()
 *    getUTCMonth()
 *    getDate()
 *    getUTCDate()
 *    getDay()
 *    getUTCDay()
 *    getHours()
 *    getUTCHours()
 *    getMinutes()
 *    getUTCMinutes()
 *    getSeconds()
 *    getUTCSeconds()
 *    getMilliseconds()
 *    getUTCMilliseconds()
 *    getYear()
 *
 *  Notes:
 *
 *    - Date.prototype.getDate(): 'date' means day-of-month, and is
 *      zero-based in internal calculations but public API expects it to
 *      be one-based.
 *
 *    - Date.prototype.getTime() and Date.prototype.valueOf() have identical
 *      behavior.  They have separate function objects, but share the same C
 *      function (duk_bi_date_prototype_value_of).
 */

DUK_INTERNAL duk_ret_t duk_bi_date_prototype_get_shared(duk_hthread *thr) {
	duk_small_uint_t flags_and_idx = duk__date_get_indirect_magic(thr);
	return duk__get_part_helper(thr, flags_and_idx);
}

DUK_INTERNAL duk_ret_t duk_bi_date_prototype_get_timezone_offset(duk_hthread *thr) {
	/*
	 *  Return (t - LocalTime(t)) in minutes:
	 *
	 *    t - LocalTime(t) = t - (t + LocalTZA + DaylightSavingTA(t))
	 *                     = -(LocalTZA + DaylightSavingTA(t))
	 *
	 *  where DaylightSavingTA() is checked for time 't'.
	 *
	 *  Note that the sign of the result is opposite to common usage,
	 *  e.g. for EE(S)T which normally is +2h or +3h from UTC, this
	 *  function returns -120 or -180.
	 *
	 */

	duk_double_t d;
	duk_int_t tzoffset;

	/* Note: DST adjustment is determined using UTC time. */
	d = duk__push_this_get_timeval(thr, 0 /*flags*/);
	DUK_ASSERT(DUK_ISFINITE(d) || DUK_ISNAN(d));
	if (DUK_ISNAN(d)) {
		duk_push_nan(thr);
	} else {
		DUK_ASSERT(DUK_ISFINITE(d));
		tzoffset = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d);
		duk_push_int(thr, -tzoffset / 60);
	}
	return 1;
}

/*
 *  Setters.
 *
 *  Setters are a bit more complicated than getters.  Component setters
 *  break down the current time value into its (normalized) component
 *  parts, replace one or more components with -unnormalized- new values,
 *  and the components are then converted back into a time value.  As an
 *  example of using unnormalized values:
 *
 *    var d = new Date(1234567890);
 *
 *  is equivalent to:
 *
 *    var d = new Date(0);
 *    d.setUTCMilliseconds(1234567890);
 *
 *  A shared native helper to provide almost all setters.  Magic value
 *  contains a set of flags and also packs the "maxnargs" argument.  The
 *  helper provides:
 *
 *    setMilliseconds()
 *    setUTCMilliseconds()
 *    setSeconds()
 *    setUTCSeconds()
 *    setMinutes()
 *    setUTCMinutes()
 *    setHours()
 *    setUTCHours()
 *    setDate()
 *    setUTCDate()
 *    setMonth()
 *    setUTCMonth()
 *    setFullYear()
 *    setUTCFullYear()
 *    setYear()
 *
 *  Notes:
 *
 *    - Date.prototype.setYear() (Section B addition): special year check
 *      is omitted.  NaN / Infinity will just flow through and ultimately
 *      result in a NaN internal time value.
 *
 *    - Date.prototype.setYear() does not have optional arguments for
 *      setting month and day-in-month (like setFullYear()), but we indicate
 *      'maxnargs' to be 3 to get the year written to the correct component
 *      index in duk__set_part_helper().  The function has nargs == 1, so only
 *      the year will be set regardless of actual argument count.
 */

DUK_INTERNAL duk_ret_t duk_bi_date_prototype_set_shared(duk_hthread *thr) {
	duk_small_uint_t flags_and_maxnargs = duk__date_get_indirect_magic(thr);
	return duk__set_part_helper(thr, flags_and_maxnargs);
}

DUK_INTERNAL duk_ret_t duk_bi_date_prototype_set_time(duk_hthread *thr) {
	duk_double_t d;

	(void) duk__push_this_get_timeval(thr, 0 /*flags*/); /* -> [ timeval this ] */
	d = duk__timeclip(duk_to_number(thr, 0));
	duk_push_number(thr, d);
	duk_dup_top(thr);
	/* Must force write because .setTime() must work even when
	 * the Date instance is frozen.
	 */
	duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_W);
	/* -> [ timeval this timeval ] */

	return 1;
}

/*
 *  Misc.
 */

#if defined(DUK_USE_SYMBOL_BUILTIN)
DUK_INTERNAL duk_ret_t duk_bi_date_prototype_toprimitive(duk_hthread *thr) {
	duk_size_t hintlen;
	const char *hintstr;
	duk_int_t hint;

	/* Invokes OrdinaryToPrimitive() with suitable hint.  Note that the
	 * method is generic, and works on non-Date arguments too.
	 *
	 * https://www.ecma-international.org/ecma-262/6.0/#sec-date.prototype-@@toprimitive
	 */

	duk_push_this(thr);
	duk_require_object(thr, -1);
	DUK_ASSERT_TOP(thr, 2);

	hintstr = duk_require_lstring(thr, 0, &hintlen);
	if ((hintlen == 6 && DUK_STRCMP(hintstr, "string") == 0) ||
	    (hintlen == 7 && DUK_STRCMP(hintstr, "default") == 0)) {
		hint = DUK_HINT_STRING;
	} else if (hintlen == 6 && DUK_STRCMP(hintstr, "number") == 0) {
		hint = DUK_HINT_NUMBER;
	} else {
		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
	}

	duk_to_primitive_ordinary(thr, -1, hint);
	return 1;
}
#endif  /* DUK_USE_SYMBOL_BUILTIN */

#endif  /* DUK_USE_DATE_BUILTIN */

/* automatic undefs */
#undef DUK__CF_ACCEPT
#undef DUK__CF_ACCEPT_NUL
#undef DUK__CF_NEG
#undef DUK__DPRINT_DPARTS
#undef DUK__DPRINT_PARTS
#undef DUK__DPRINT_PARTS_AND_DPARTS
#undef DUK__LOCAL_TZOFFSET_MAXITER
#undef DUK__NUM_ISO8601_PARSER_PARTS
#undef DUK__PACK_RULE
#undef DUK__PI_DAY
#undef DUK__PI_HOUR
#undef DUK__PI_MILLISECOND
#undef DUK__PI_MINUTE
#undef DUK__PI_MONTH
#undef DUK__PI_SECOND
#undef DUK__PI_TZHOUR
#undef DUK__PI_TZMINUTE
#undef DUK__PI_YEAR
#undef DUK__PM_DAY
#undef DUK__PM_HOUR
#undef DUK__PM_MILLISECOND
#undef DUK__PM_MINUTE
#undef DUK__PM_MONTH
#undef DUK__PM_SECOND
#undef DUK__PM_TZHOUR
#undef DUK__PM_TZMINUTE
#undef DUK__PM_YEAR
#undef DUK__RULE_MASK_PART_SEP
#undef DUK__SI_COLON
#undef DUK__SI_MINUS
#undef DUK__SI_NUL
#undef DUK__SI_PERIOD
#undef DUK__SI_PLUS
#undef DUK__SI_SPACE
#undef DUK__SI_T
#undef DUK__SI_Z
#undef DUK__SM_COLON
#undef DUK__SM_MINUS
#undef DUK__SM_NUL
#undef DUK__SM_PERIOD
#undef DUK__SM_PLUS
#undef DUK__SM_SPACE
#undef DUK__SM_T
#undef DUK__SM_Z
#undef DUK__UNPACK_RULE
#undef DUK__WEEKDAY_MOD_ADDER
#undef DUK__YEAR
#line 1 "duk_bi_date_unix.c"
/*
 *  Unix-like Date providers
 *
 *  Generally useful Unix / POSIX / ANSI Date providers.
 */

/* #include duk_internal.h -> already included */

/* The necessary #includes are in place in duk_config.h. */

/* Buffer sizes for some UNIX calls.  Larger than strictly necessary
 * to avoid Valgrind errors.
 */
#define DUK__STRPTIME_BUF_SIZE  64
#define DUK__STRFTIME_BUF_SIZE  64

#if defined(DUK_USE_DATE_NOW_GETTIMEOFDAY)
/* Get current ECMAScript time (= UNIX/Posix time, but in milliseconds). */
DUK_INTERNAL duk_double_t duk_bi_date_get_now_gettimeofday(void) {
	struct timeval tv;
	duk_double_t d;

	if (gettimeofday(&tv, NULL) != 0) {
		DUK_D(DUK_DPRINT("gettimeofday() failed"));
		return 0.0;
	}

	/* As of Duktape 2.2.0 allow fractions. */
	d = ((duk_double_t) tv.tv_sec) * 1000.0 +
	    ((duk_double_t) tv.tv_usec) / 1000.0;

	return d;
}
#endif  /* DUK_USE_DATE_NOW_GETTIMEOFDAY */

#if defined(DUK_USE_DATE_NOW_TIME)
/* Not a very good provider: only full seconds are available. */
DUK_INTERNAL duk_double_t duk_bi_date_get_now_time(void) {
	time_t t;

	t = time(NULL);
	if (t == (time_t) -1) {
		DUK_D(DUK_DPRINT("time() failed"));
		return 0.0;
	}
	return ((duk_double_t) t) * 1000.0;
}
#endif  /* DUK_USE_DATE_NOW_TIME */

#if defined(DUK_USE_DATE_TZO_GMTIME) || defined(DUK_USE_DATE_TZO_GMTIME_R) || defined(DUK_USE_DATE_TZO_GMTIME_S)
/* Get local time offset (in seconds) for a certain (UTC) instant 'd'. */
DUK_INTERNAL duk_int_t duk_bi_date_get_local_tzoffset_gmtime(duk_double_t d) {
	time_t t, t1, t2;
	duk_int_t parts[DUK_DATE_IDX_NUM_PARTS];
	duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
	struct tm tms[2];
#if defined(DUK_USE_DATE_TZO_GMTIME)
	struct tm *tm_ptr;
#endif

	/* For NaN/inf, the return value doesn't matter. */
	if (!DUK_ISFINITE(d)) {
		return 0;
	}

	/* If not within ECMAScript range, some integer time calculations
	 * won't work correctly (and some asserts will fail), so bail out
	 * if so.  This fixes test-bug-date-insane-setyear.js.  There is
	 * a +/- 24h leeway in this range check to avoid a test262 corner
	 * case documented in test-bug-date-timeval-edges.js.
	 */
	if (!duk_bi_date_timeval_in_leeway_range(d)) {
		DUK_DD(DUK_DDPRINT("timeval not within valid range, skip tzoffset computation to avoid integer overflows"));
		return 0;
	}

	/*
	 *  This is a bit tricky to implement portably.  The result depends
	 *  on the timestamp (specifically, DST depends on the timestamp).
	 *  If e.g. UNIX APIs are used, they'll have portability issues with
	 *  very small and very large years.
	 *
	 *  Current approach:
	 *
	 *  - Stay within portable UNIX limits by using equivalent year mapping.
	 *    Avoid year 1970 and 2038 as some conversions start to fail, at
	 *    least on some platforms.  Avoiding 1970 means that there are
	 *    currently DST discrepancies for 1970.
	 *
	 *  - Create a UTC and local time breakdowns from 't'.  Then create
	 *    a time_t using gmtime() and localtime() and compute the time
	 *    difference between the two.
	 *
	 *  Equivalent year mapping (E5 Section 15.9.1.8):
	 *
	 *    If the host environment provides functionality for determining
	 *    daylight saving time, the implementation of ECMAScript is free
	 *    to map the year in question to an equivalent year (same
	 *    leap-year-ness and same starting week day for the year) for which
	 *    the host environment provides daylight saving time information.
	 *    The only restriction is that all equivalent years should produce
	 *    the same result.
	 *
	 *  This approach is quite reasonable but not entirely correct, e.g.
	 *  the specification also states (E5 Section 15.9.1.8):
	 *
	 *    The implementation of ECMAScript should not try to determine
	 *    whether the exact time was subject to daylight saving time, but
	 *    just whether daylight saving time would have been in effect if
	 *    the _current daylight saving time algorithm_ had been used at the
	 *    time.  This avoids complications such as taking into account the
	 *    years that the locale observed daylight saving time year round.
	 *
	 *  Since we rely on the platform APIs for conversions between local
	 *  time and UTC, we can't guarantee the above.  Rather, if the platform
	 *  has historical DST rules they will be applied.  This seems to be the
	 *  general preferred direction in ECMAScript standardization (or at least
	 *  implementations) anyway, and even the equivalent year mapping should
	 *  be disabled if the platform is known to handle DST properly for the
	 *  full ECMAScript range.
	 *
	 *  The following has useful discussion and links:
	 *
	 *    https://bugzilla.mozilla.org/show_bug.cgi?id=351066
	 */

	duk_bi_date_timeval_to_parts(d, parts, dparts, DUK_DATE_FLAG_EQUIVYEAR /*flags*/);
	DUK_ASSERT(parts[DUK_DATE_IDX_YEAR] >= 1970 && parts[DUK_DATE_IDX_YEAR] <= 2038);

	d = duk_bi_date_get_timeval_from_dparts(dparts, 0 /*flags*/);
	DUK_ASSERT(d >= 0 && d < 2147483648.0 * 1000.0);  /* unsigned 31-bit range */
	t = (time_t) (d / 1000.0);
	DUK_DDD(DUK_DDDPRINT("timeval: %lf -> time_t %ld", (double) d, (long) t));

	duk_memzero((void *) tms, sizeof(struct tm) * 2);

#if defined(DUK_USE_DATE_TZO_GMTIME_R)
	(void) gmtime_r(&t, &tms[0]);
	(void) localtime_r(&t, &tms[1]);
#elif defined(DUK_USE_DATE_TZO_GMTIME_S)
	(void) gmtime_s(&t, &tms[0]);
	(void) localtime_s(&t, &tms[1]);
#elif defined(DUK_USE_DATE_TZO_GMTIME)
	tm_ptr = gmtime(&t);
	duk_memcpy((void *) &tms[0], tm_ptr, sizeof(struct tm));
	tm_ptr = localtime(&t);
	duk_memcpy((void *) &tms[1], tm_ptr, sizeof(struct tm));
#else
#error internal error
#endif
	DUK_DDD(DUK_DDDPRINT("gmtime result: tm={sec:%ld,min:%ld,hour:%ld,mday:%ld,mon:%ld,year:%ld,"
	                     "wday:%ld,yday:%ld,isdst:%ld}",
	                     (long) tms[0].tm_sec, (long) tms[0].tm_min, (long) tms[0].tm_hour,
	                     (long) tms[0].tm_mday, (long) tms[0].tm_mon, (long) tms[0].tm_year,
	                     (long) tms[0].tm_wday, (long) tms[0].tm_yday, (long) tms[0].tm_isdst));
	DUK_DDD(DUK_DDDPRINT("localtime result: tm={sec:%ld,min:%ld,hour:%ld,mday:%ld,mon:%ld,year:%ld,"
	                     "wday:%ld,yday:%ld,isdst:%ld}",
	                     (long) tms[1].tm_sec, (long) tms[1].tm_min, (long) tms[1].tm_hour,
	                     (long) tms[1].tm_mday, (long) tms[1].tm_mon, (long) tms[1].tm_year,
	                     (long) tms[1].tm_wday, (long) tms[1].tm_yday, (long) tms[1].tm_isdst));

	/* tm_isdst is both an input and an output to mktime(), use 0 to
	 * avoid DST handling in mktime():
	 * - https://github.com/svaarala/duktape/issues/406
	 * - http://stackoverflow.com/questions/8558919/mktime-and-tm-isdst
	 */
	tms[0].tm_isdst = 0;
	tms[1].tm_isdst = 0;
	t1 = mktime(&tms[0]);  /* UTC */
	t2 = mktime(&tms[1]);  /* local */
	if (t1 == (time_t) -1 || t2 == (time_t) -1) {
		/* This check used to be for (t < 0) but on some platforms
		 * time_t is unsigned and apparently the proper way to detect
		 * an mktime() error return is the cast above.  See e.g.:
		 * http://pubs.opengroup.org/onlinepubs/009695299/functions/mktime.html
		 */
		goto mktime_error;
	}
	DUK_DDD(DUK_DDDPRINT("t1=%ld (utc), t2=%ld (local)", (long) t1, (long) t2));

	/* Compute final offset in seconds, positive if local time ahead of
	 * UTC (returned value is UTC-to-local offset).
	 *
	 * difftime() returns a double, so coercion to int generates quite
	 * a lot of code.  Direct subtraction is not portable, however.
	 * XXX: allow direct subtraction on known platforms.
	 */
#if 0
	return (duk_int_t) (t2 - t1);
#endif
	return (duk_int_t) difftime(t2, t1);

 mktime_error:
	/* XXX: return something more useful, so that caller can throw? */
	DUK_D(DUK_DPRINT("mktime() failed, d=%lf", (double) d));
	return 0;
}
#endif  /* DUK_USE_DATE_TZO_GMTIME */

#if defined(DUK_USE_DATE_PRS_STRPTIME)
DUK_INTERNAL duk_bool_t duk_bi_date_parse_string_strptime(duk_hthread *thr, const char *str) {
	struct tm tm;
	time_t t;
	char buf[DUK__STRPTIME_BUF_SIZE];

	/* Copy to buffer with slack to avoid Valgrind gripes from strptime. */
	DUK_ASSERT(str != NULL);
	duk_memzero(buf, sizeof(buf));  /* valgrind whine without this */
	DUK_SNPRINTF(buf, sizeof(buf), "%s", (const char *) str);
	buf[sizeof(buf) - 1] = (char) 0;

	DUK_DDD(DUK_DDDPRINT("parsing: '%s'", (const char *) buf));

	duk_memzero(&tm, sizeof(tm));
	if (strptime((const char *) buf, "%c", &tm) != NULL) {
		DUK_DDD(DUK_DDDPRINT("before mktime: tm={sec:%ld,min:%ld,hour:%ld,mday:%ld,mon:%ld,year:%ld,"
		                     "wday:%ld,yday:%ld,isdst:%ld}",
		                     (long) tm.tm_sec, (long) tm.tm_min, (long) tm.tm_hour,
		                     (long) tm.tm_mday, (long) tm.tm_mon, (long) tm.tm_year,
		                     (long) tm.tm_wday, (long) tm.tm_yday, (long) tm.tm_isdst));
		tm.tm_isdst = -1;  /* negative: dst info not available */

		t = mktime(&tm);
		DUK_DDD(DUK_DDDPRINT("mktime() -> %ld", (long) t));
		if (t >= 0) {
			duk_push_number(thr, ((duk_double_t) t) * 1000.0);
			return 1;
		}
	}

	return 0;
}
#endif  /* DUK_USE_DATE_PRS_STRPTIME */

#if defined(DUK_USE_DATE_PRS_GETDATE)
DUK_INTERNAL duk_bool_t duk_bi_date_parse_string_getdate(duk_hthread *thr, const char *str) {
	struct tm tm;
	duk_small_int_t rc;
	time_t t;

	/* For this to work, DATEMSK must be set, so this is not very
	 * convenient for an embeddable interpreter.
	 */

	duk_memzero(&tm, sizeof(struct tm));
	rc = (duk_small_int_t) getdate_r(str, &tm);
	DUK_DDD(DUK_DDDPRINT("getdate_r() -> %ld", (long) rc));

	if (rc == 0) {
		t = mktime(&tm);
		DUK_DDD(DUK_DDDPRINT("mktime() -> %ld", (long) t));
		if (t >= 0) {
			duk_push_number(thr, (duk_double_t) t);
			return 1;
		}
	}

	return 0;
}
#endif  /* DUK_USE_DATE_PRS_GETDATE */

#if defined(DUK_USE_DATE_FMT_STRFTIME)
DUK_INTERNAL duk_bool_t duk_bi_date_format_parts_strftime(duk_hthread *thr, duk_int_t *parts, duk_int_t tzoffset, duk_small_uint_t flags) {
	char buf[DUK__STRFTIME_BUF_SIZE];
	struct tm tm;
	const char *fmt;

	DUK_UNREF(tzoffset);

	/* If the platform doesn't support the entire ECMAScript range, we need
	 * to return 0 so that the caller can fall back to the default formatter.
	 *
	 * For now, assume that if time_t is 8 bytes or more, the whole ECMAScript
	 * range is supported.  For smaller time_t values (4 bytes in practice),
	 * assumes that the signed 32-bit range is supported.
	 *
	 * XXX: detect this more correctly per platform.  The size of time_t is
	 * probably not an accurate guarantee of strftime() supporting or not
	 * supporting a large time range (the full ECMAScript range).
	 */
	if (sizeof(time_t) < 8 &&
	    (parts[DUK_DATE_IDX_YEAR] < 1970 || parts[DUK_DATE_IDX_YEAR] > 2037)) {
		/* be paranoid for 32-bit time values (even avoiding negative ones) */
		return 0;
	}

	duk_memzero(&tm, sizeof(tm));
	tm.tm_sec = parts[DUK_DATE_IDX_SECOND];
	tm.tm_min = parts[DUK_DATE_IDX_MINUTE];
	tm.tm_hour = parts[DUK_DATE_IDX_HOUR];
	tm.tm_mday = parts[DUK_DATE_IDX_DAY];       /* already one-based */
	tm.tm_mon = parts[DUK_DATE_IDX_MONTH] - 1;  /* one-based -> zero-based */
	tm.tm_year = parts[DUK_DATE_IDX_YEAR] - 1900;
	tm.tm_wday = parts[DUK_DATE_IDX_WEEKDAY];
	tm.tm_isdst = 0;

	duk_memzero(buf, sizeof(buf));
	if ((flags & DUK_DATE_FLAG_TOSTRING_DATE) && (flags & DUK_DATE_FLAG_TOSTRING_TIME)) {
		fmt = "%c";
	} else if (flags & DUK_DATE_FLAG_TOSTRING_DATE) {
		fmt = "%x";
	} else {
		DUK_ASSERT(flags & DUK_DATE_FLAG_TOSTRING_TIME);
		fmt = "%X";
	}
	(void) strftime(buf, sizeof(buf) - 1, fmt, &tm);
	DUK_ASSERT(buf[sizeof(buf) - 1] == 0);

	duk_push_string(thr, buf);
	return 1;
}
#endif  /* DUK_USE_DATE_FMT_STRFTIME */

#if defined(DUK_USE_GET_MONOTONIC_TIME_CLOCK_GETTIME)
DUK_INTERNAL duk_double_t duk_bi_date_get_monotonic_time_clock_gettime(void) {
	struct timespec ts;

	if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
		return (duk_double_t) ts.tv_sec * 1000.0 + (duk_double_t) ts.tv_nsec / 1000000.0;
	} else {
		DUK_D(DUK_DPRINT("clock_gettime(CLOCK_MONOTONIC) failed"));
		return 0.0;
	}
}
#endif

/* automatic undefs */
#undef DUK__STRFTIME_BUF_SIZE
#undef DUK__STRPTIME_BUF_SIZE
#line 1 "duk_bi_date_windows.c"
/*
 *  Windows Date providers
 *
 *  Platform specific links:
 *
 *    - http://msdn.microsoft.com/en-us/library/windows/desktop/ms725473(v=vs.85).aspx
 */

/* #include duk_internal.h -> already included */

/* The necessary #includes are in place in duk_config.h. */

#if defined(DUK_USE_DATE_NOW_WINDOWS) || defined(DUK_USE_DATE_TZO_WINDOWS)
/* Shared Windows helpers. */
DUK_LOCAL void duk__convert_systime_to_ularge(const SYSTEMTIME *st, ULARGE_INTEGER *res) {
	FILETIME ft;
	if (SystemTimeToFileTime(st, &ft) == 0) {
		DUK_D(DUK_DPRINT("SystemTimeToFileTime() failed, returning 0"));
		res->QuadPart = 0;
	} else {
		res->LowPart = ft.dwLowDateTime;
		res->HighPart = ft.dwHighDateTime;
	}
}

#if defined(DUK_USE_DATE_NOW_WINDOWS_SUBMS)
DUK_LOCAL void duk__convert_filetime_to_ularge(const FILETIME *ft, ULARGE_INTEGER *res) {
	res->LowPart = ft->dwLowDateTime;
	res->HighPart = ft->dwHighDateTime;
}
#endif  /* DUK_USE_DATE_NOW_WINDOWS_SUBMS */

DUK_LOCAL void duk__set_systime_jan1970(SYSTEMTIME *st) {
	duk_memzero((void *) st, sizeof(*st));
	st->wYear = 1970;
	st->wMonth = 1;
	st->wDayOfWeek = 4;  /* not sure whether or not needed; Thursday */
	st->wDay = 1;
	DUK_ASSERT(st->wHour == 0);
	DUK_ASSERT(st->wMinute == 0);
	DUK_ASSERT(st->wSecond == 0);
	DUK_ASSERT(st->wMilliseconds == 0);
}
#endif  /* defined(DUK_USE_DATE_NOW_WINDOWS) || defined(DUK_USE_DATE_TZO_WINDOWS) */

#if defined(DUK_USE_DATE_NOW_WINDOWS)
DUK_INTERNAL duk_double_t duk_bi_date_get_now_windows(void) {
	/* Suggested step-by-step method from documentation of RtlTimeToSecondsSince1970:
	 * http://msdn.microsoft.com/en-us/library/windows/desktop/ms724928(v=vs.85).aspx
	 */
	SYSTEMTIME st1, st2;
	ULARGE_INTEGER tmp1, tmp2;

	GetSystemTime(&st1);
	duk__convert_systime_to_ularge((const SYSTEMTIME *) &st1, &tmp1);

	duk__set_systime_jan1970(&st2);
	duk__convert_systime_to_ularge((const SYSTEMTIME *) &st2, &tmp2);

	/* Difference is in 100ns units, convert to milliseconds, keeping
	 * fractions since Duktape 2.2.0.  This is only theoretical because
	 * SYSTEMTIME is limited to milliseconds.
	 */
	return (duk_double_t) ((LONGLONG) tmp1.QuadPart - (LONGLONG) tmp2.QuadPart) / 10000.0;
}
#endif  /* DUK_USE_DATE_NOW_WINDOWS */

#if defined(DUK_USE_DATE_NOW_WINDOWS_SUBMS)
DUK_INTERNAL duk_double_t duk_bi_date_get_now_windows_subms(void) {
	/* Variant of the basic algorithm using GetSystemTimePreciseAsFileTime()
	 * for more accuracy.
	 */
	FILETIME ft1;
	SYSTEMTIME st2;
	ULARGE_INTEGER tmp1, tmp2;

	GetSystemTimePreciseAsFileTime(&ft1);
	duk__convert_filetime_to_ularge((const FILETIME *) &ft1, &tmp1);

	duk__set_systime_jan1970(&st2);
	duk__convert_systime_to_ularge((const SYSTEMTIME *) &st2, &tmp2);

	/* Difference is in 100ns units, convert to milliseconds, keeping
	 * fractions since Duktape 2.2.0.
	 */
	return (duk_double_t) ((LONGLONG) tmp1.QuadPart - (LONGLONG) tmp2.QuadPart) / 10000.0;
}
#endif  /* DUK_USE_DATE_NOW_WINDOWS */

#if defined(DUK_USE_DATE_TZO_WINDOWS)
DUK_INTERNAL duk_int_t duk_bi_date_get_local_tzoffset_windows(duk_double_t d) {
	SYSTEMTIME st1;
	SYSTEMTIME st2;
	SYSTEMTIME st3;
	ULARGE_INTEGER tmp1;
	ULARGE_INTEGER tmp2;
	ULARGE_INTEGER tmp3;
	FILETIME ft1;

	/* XXX: handling of timestamps outside Windows supported range.
	 * How does Windows deal with dates before 1600?  Does windows
	 * support all ECMAScript years (like -200000 and +200000)?
	 * Should equivalent year mapping be used here too?  If so, use
	 * a shared helper (currently integrated into timeval-to-parts).
	 */

	/* Use the approach described in "Remarks" of FileTimeToLocalFileTime:
	 * http://msdn.microsoft.com/en-us/library/windows/desktop/ms724277(v=vs.85).aspx
	 */

	duk__set_systime_jan1970(&st1);
	duk__convert_systime_to_ularge((const SYSTEMTIME *) &st1, &tmp1);
	tmp2.QuadPart = (ULONGLONG) (d * 10000.0);  /* millisec -> 100ns units since jan 1, 1970 */
	tmp2.QuadPart += tmp1.QuadPart;             /* input 'd' in Windows UTC, 100ns units */

	ft1.dwLowDateTime = tmp2.LowPart;
	ft1.dwHighDateTime = tmp2.HighPart;
	if (FileTimeToSystemTime((const FILETIME *) &ft1, &st2) == 0) {
		DUK_D(DUK_DPRINT("FileTimeToSystemTime() failed, return tzoffset 0"));
		return 0;
	}
	if (SystemTimeToTzSpecificLocalTime((LPTIME_ZONE_INFORMATION) NULL, &st2, &st3) == 0) {
		DUK_D(DUK_DPRINT("SystemTimeToTzSpecificLocalTime() failed, return tzoffset 0"));
		return 0;
	}
	duk__convert_systime_to_ularge((const SYSTEMTIME *) &st3, &tmp3);

	/* Positive if local time ahead of UTC. */
	return (duk_int_t) (((LONGLONG) tmp3.QuadPart - (LONGLONG) tmp2.QuadPart) / DUK_I64_CONSTANT(10000000));  /* seconds */
}
#endif  /* DUK_USE_DATE_TZO_WINDOWS */

#if defined(DUK_USE_DATE_TZO_WINDOWS_NO_DST)
DUK_INTERNAL duk_int_t duk_bi_date_get_local_tzoffset_windows_no_dst(duk_double_t d) {
	SYSTEMTIME st1;
	SYSTEMTIME st2;
	FILETIME ft1;
	FILETIME ft2;
	ULARGE_INTEGER tmp1;
	ULARGE_INTEGER tmp2;

	/* Do a similar computation to duk_bi_date_get_local_tzoffset_windows
	 * but without accounting for daylight savings time.  Use this on
	 * Windows platforms (like Durango) that don't support the
	 * SystemTimeToTzSpecificLocalTime() call.
	 */

	/* current time not needed for this computation */
	DUK_UNREF(d);

	duk__set_systime_jan1970(&st1);
	duk__convert_systime_to_ularge((const SYSTEMTIME *) &st1, &tmp1);

	ft1.dwLowDateTime = tmp1.LowPart;
	ft1.dwHighDateTime = tmp1.HighPart;
	if (FileTimeToLocalFileTime((const FILETIME *) &ft1, &ft2) == 0) {
		DUK_D(DUK_DPRINT("FileTimeToLocalFileTime() failed, return tzoffset 0"));
		return 0;
	}
	if (FileTimeToSystemTime((const FILETIME *) &ft2, &st2) == 0) {
		DUK_D(DUK_DPRINT("FileTimeToSystemTime() failed, return tzoffset 0"));
		return 0;
	}
	duk__convert_systime_to_ularge((const SYSTEMTIME *) &st2, &tmp2);

	return (duk_int_t) (((LONGLONG) tmp2.QuadPart - (LONGLONG) tmp1.QuadPart) / DUK_I64_CONSTANT(10000000));  /* seconds */
}
#endif  /* DUK_USE_DATE_TZO_WINDOWS_NO_DST */

#if defined(DUK_USE_GET_MONOTONIC_TIME_WINDOWS_QPC)
DUK_INTERNAL duk_double_t duk_bi_date_get_monotonic_time_windows_qpc(void) {
	LARGE_INTEGER count, freq;

	/* There are legacy issues with QueryPerformanceCounter():
	 * - Potential jumps: https://support.microsoft.com/en-us/help/274323/performance-counter-value-may-unexpectedly-leap-forward
	 * - Differences between cores (XP): https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408(v=vs.85).aspx#qpc_support_in_windows_versions
	 *
	 * We avoid these by enabling QPC by default only for Vista or later.
	 */

	if (QueryPerformanceCounter(&count) && QueryPerformanceFrequency(&freq)) {
		/* XXX: QueryPerformanceFrequency() can be cached */
		return (duk_double_t) count.QuadPart / (duk_double_t) freq.QuadPart * 1000.0;
	} else {
		/* MSDN: "On systems that run Windows XP or later, the function
		 * will always succeed and will thus never return zero."
		 * Provide minimal error path just in case user enables this
		 * feature in pre-XP Windows.
		 */
		return 0.0;
	}
}
#endif  /* DUK_USE_GET_MONOTONIC_TIME_WINDOWS_QPC */
#line 1 "duk_bi_duktape.c"
/*
 *  Duktape built-ins
 *
 *  Size optimization note: it might seem that vararg multipurpose functions
 *  like fin(), enc(), and dec() are not very size optimal, but using a single
 *  user-visible ECMAScript function saves a lot of run-time footprint; each
 *  Function instance takes >100 bytes.  Using a shared native helper and a
 *  'magic' value won't save much if there are multiple Function instances
 *  anyway.
 */

/* #include duk_internal.h -> already included */

#if defined(DUK_USE_DUKTAPE_BUILTIN)

DUK_INTERNAL duk_ret_t duk_bi_duktape_object_info(duk_hthread *thr) {
	duk_inspect_value(thr, -1);
	return 1;
}

DUK_INTERNAL duk_ret_t duk_bi_duktape_object_act(duk_hthread *thr) {
	duk_int_t level;

	level = duk_to_int(thr, 0);
	duk_inspect_callstack_entry(thr, level);
	return 1;
}

DUK_INTERNAL duk_ret_t duk_bi_duktape_object_gc(duk_hthread *thr) {
	duk_small_uint_t flags;

	flags = (duk_small_uint_t) duk_get_uint(thr, 0);
	duk_heap_mark_and_sweep(thr->heap, flags);

	/* XXX: Not sure what the best return value would be in the API.
	 * Return true for now.
	 */
	duk_push_true(thr);
	return 1;
}

#if defined(DUK_USE_FINALIZER_SUPPORT)
DUK_INTERNAL duk_ret_t duk_bi_duktape_object_fin(duk_hthread *thr) {
	(void) duk_require_hobject(thr, 0);
	if (duk_get_top(thr) >= 2) {
		/* Set: currently a finalizer is disabled by setting it to
		 * undefined; this does not remove the property at the moment.
		 * The value could be type checked to be either a function
		 * or something else; if something else, the property could
		 * be deleted.  Must use duk_set_finalizer() to keep
		 * DUK_HOBJECT_FLAG_HAVE_FINALIZER in sync.
		 */
		duk_set_top(thr, 2);
		duk_set_finalizer(thr, 0);
		return 0;
	} else {
		/* Get. */
		DUK_ASSERT(duk_get_top(thr) == 1);
		duk_get_finalizer(thr, 0);
		return 1;
	}
}
#endif  /* DUK_USE_FINALIZER_SUPPORT */

DUK_INTERNAL duk_ret_t duk_bi_duktape_object_enc(duk_hthread *thr) {
	duk_hstring *h_str;

	/* Vararg function: must be careful to check/require arguments.
	 * The JSON helpers accept invalid indices and treat them like
	 * non-existent optional parameters.
	 */

	h_str = duk_require_hstring(thr, 0);  /* Could reject symbols, but no point: won't match comparisons. */
	duk_require_valid_index(thr, 1);

	if (h_str == DUK_HTHREAD_STRING_HEX(thr)) {
		duk_set_top(thr, 2);
		duk_hex_encode(thr, 1);
		DUK_ASSERT_TOP(thr, 2);
	} else if (h_str == DUK_HTHREAD_STRING_BASE64(thr)) {
		duk_set_top(thr, 2);
		duk_base64_encode(thr, 1);
		DUK_ASSERT_TOP(thr, 2);
#if defined(DUK_USE_JSON_SUPPORT) && defined(DUK_USE_JX)
	} else if (h_str == DUK_HTHREAD_STRING_JX(thr)) {
		duk_bi_json_stringify_helper(thr,
		                             1 /*idx_value*/,
		                             2 /*idx_replacer*/,
		                             3 /*idx_space*/,
		                             DUK_JSON_FLAG_EXT_CUSTOM |
		                             DUK_JSON_FLAG_ASCII_ONLY |
		                             DUK_JSON_FLAG_AVOID_KEY_QUOTES /*flags*/);
#endif
#if defined(DUK_USE_JSON_SUPPORT) && defined(DUK_USE_JC)
	} else if (h_str == DUK_HTHREAD_STRING_JC(thr)) {
		duk_bi_json_stringify_helper(thr,
		                             1 /*idx_value*/,
		                             2 /*idx_replacer*/,
		                             3 /*idx_space*/,
		                             DUK_JSON_FLAG_EXT_COMPATIBLE |
		                             DUK_JSON_FLAG_ASCII_ONLY /*flags*/);
#endif
	} else {
		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
	}
	return 1;
}

DUK_INTERNAL duk_ret_t duk_bi_duktape_object_dec(duk_hthread *thr) {
	duk_hstring *h_str;

	/* Vararg function: must be careful to check/require arguments.
	 * The JSON helpers accept invalid indices and treat them like
	 * non-existent optional parameters.
	 */

	h_str = duk_require_hstring(thr, 0);  /* Could reject symbols, but no point: won't match comparisons */
	duk_require_valid_index(thr, 1);

	if (h_str == DUK_HTHREAD_STRING_HEX(thr)) {
		duk_set_top(thr, 2);
		duk_hex_decode(thr, 1);
		DUK_ASSERT_TOP(thr, 2);
	} else if (h_str == DUK_HTHREAD_STRING_BASE64(thr)) {
		duk_set_top(thr, 2);
		duk_base64_decode(thr, 1);
		DUK_ASSERT_TOP(thr, 2);
#if defined(DUK_USE_JSON_SUPPORT) && defined(DUK_USE_JX)
	} else if (h_str == DUK_HTHREAD_STRING_JX(thr)) {
		duk_bi_json_parse_helper(thr,
		                         1 /*idx_value*/,
		                         2 /*idx_replacer*/,
		                         DUK_JSON_FLAG_EXT_CUSTOM /*flags*/);
#endif
#if defined(DUK_USE_JSON_SUPPORT) && defined(DUK_USE_JC)
	} else if (h_str == DUK_HTHREAD_STRING_JC(thr)) {
		duk_bi_json_parse_helper(thr,
		                         1 /*idx_value*/,
		                         2 /*idx_replacer*/,
		                         DUK_JSON_FLAG_EXT_COMPATIBLE /*flags*/);
#endif
	} else {
		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
	}
	return 1;
}

/*
 *  Compact an object
 */

DUK_INTERNAL duk_ret_t duk_bi_duktape_object_compact(duk_hthread *thr) {
	DUK_ASSERT_TOP(thr, 1);
	duk_compact(thr, 0);
	return 1;  /* return the argument object */
}

#endif  /* DUK_USE_DUKTAPE_BUILTIN */
#line 1 "duk_bi_encoding.c"
/*
 *  WHATWG Encoding API built-ins
 *
 *  API specification: https://encoding.spec.whatwg.org/#api
 *  Web IDL: https://www.w3.org/TR/WebIDL/
 */

/* #include duk_internal.h -> already included */

/*
 *  Data structures for encoding/decoding
 */

typedef struct {
	duk_uint8_t *out;      /* where to write next byte(s) */
	duk_codepoint_t lead;  /* lead surrogate */
} duk__encode_context;

typedef struct {
	/* UTF-8 decoding state */
	duk_codepoint_t codepoint;  /* built up incrementally */
	duk_uint8_t upper;          /* max value of next byte (decode error otherwise) */
	duk_uint8_t lower;          /* min value of next byte (ditto) */
	duk_uint8_t needed;         /* how many more bytes we need */
	duk_uint8_t bom_handled;    /* BOM seen or no longer expected */

	/* Decoder configuration */
	duk_uint8_t fatal;
	duk_uint8_t ignore_bom;
} duk__decode_context;

/* The signed duk_codepoint_t type is used to signal a decoded codepoint
 * (>= 0) or various other states using negative values.
 */
#define DUK__CP_CONTINUE   (-1)  /* continue to next byte, no completed codepoint */
#define DUK__CP_ERROR      (-2)  /* decoding error */
#define DUK__CP_RETRY      (-3)  /* decoding error; retry last byte */

/*
 *  Raw helpers for encoding/decoding
 */

/* Emit UTF-8 (= CESU-8) encoded U+FFFD (replacement char), i.e. ef bf bd. */
DUK_LOCAL duk_uint8_t *duk__utf8_emit_repl(duk_uint8_t *ptr) {
	*ptr++ = 0xef;
	*ptr++ = 0xbf;
	*ptr++ = 0xbd;
	return ptr;
}

DUK_LOCAL void duk__utf8_decode_init(duk__decode_context *dec_ctx) {
	/* (Re)init the decoding state of 'dec_ctx' but leave decoder
	 * configuration fields untouched.
	 */
	dec_ctx->codepoint = 0x0000L;
	dec_ctx->upper = 0xbf;
	dec_ctx->lower = 0x80;
	dec_ctx->needed = 0;
	dec_ctx->bom_handled = 0;
}

DUK_LOCAL duk_codepoint_t duk__utf8_decode_next(duk__decode_context *dec_ctx, duk_uint8_t x) {
	/*
	 *  UTF-8 algorithm based on the Encoding specification:
	 *  https://encoding.spec.whatwg.org/#utf-8-decoder
	 *
	 *  Two main states: decoding initial byte vs. decoding continuation
	 *  bytes.  Shortest length encoding is validated by restricting the
	 *  allowed range of first continuation byte using 'lower' and 'upper'.
	 */

	if (dec_ctx->needed == 0) {
		/* process initial byte */
		if (x <= 0x7f) {
			/* U+0000-U+007F, 1 byte (ASCII) */
			return (duk_codepoint_t) x;
		} else if (x >= 0xc2 && x <= 0xdf) {
			/* U+0080-U+07FF, 2 bytes */
			dec_ctx->needed = 1;
			dec_ctx->codepoint = x & 0x1f;
			DUK_ASSERT(dec_ctx->lower == 0x80);
			DUK_ASSERT(dec_ctx->upper == 0xbf);
			return DUK__CP_CONTINUE;
		} else if (x >= 0xe0 && x <= 0xef) {
			/* U+0800-U+FFFF, 3 bytes */
			if (x == 0xe0) {
				dec_ctx->lower = 0xa0;
				DUK_ASSERT(dec_ctx->upper == 0xbf);
			} else if (x == 0xed) {
				DUK_ASSERT(dec_ctx->lower == 0x80);
				dec_ctx->upper = 0x9f;
			}
			dec_ctx->needed = 2;
			dec_ctx->codepoint = x & 0x0f;
			return DUK__CP_CONTINUE;
		} else if (x >= 0xf0 && x <= 0xf4) {
			/* U+010000-U+10FFFF, 4 bytes */
			if (x == 0xf0) {
				dec_ctx->lower = 0x90;
				DUK_ASSERT(dec_ctx->upper == 0xbf);
			} else if (x == 0xf4) {
				DUK_ASSERT(dec_ctx->lower == 0x80);
				dec_ctx->upper = 0x8f;
			}
			dec_ctx->needed = 3;
			dec_ctx->codepoint = x & 0x07;
			return DUK__CP_CONTINUE;
		} else {
			/* not a legal initial byte */
			return DUK__CP_ERROR;
		}
	} else {
		/* process continuation byte */
		if (x >= dec_ctx->lower && x <= dec_ctx->upper) {
			dec_ctx->lower = 0x80;
			dec_ctx->upper = 0xbf;
			dec_ctx->codepoint = (dec_ctx->codepoint << 6) | (x & 0x3f);
			if (--dec_ctx->needed > 0) {
				/* need more bytes */
				return DUK__CP_CONTINUE;
			} else {
				/* got a codepoint */
				duk_codepoint_t ret;
				DUK_ASSERT(dec_ctx->codepoint <= 0x10ffffL);  /* Decoding rules guarantee. */
				ret = dec_ctx->codepoint;
				dec_ctx->codepoint = 0x0000L;
				dec_ctx->needed = 0;
				return ret;
			}
		} else {
			/* We just encountered an illegal UTF-8 continuation byte.  This might
			 * be the initial byte of the next character; if we return a plain
			 * error status and the decoder is in replacement mode, the character
			 * will be masked.  We still need to alert the caller to the error
			 * though.
			 */
			dec_ctx->codepoint = 0x0000L;
			dec_ctx->needed = 0;
			dec_ctx->lower = 0x80;
			dec_ctx->upper = 0xbf;
			return DUK__CP_RETRY;
		}
	}
}

#if defined(DUK_USE_ENCODING_BUILTINS)
DUK_LOCAL void duk__utf8_encode_char(void *udata, duk_codepoint_t codepoint) {
	duk__encode_context *enc_ctx;

	DUK_ASSERT(codepoint >= 0);
	enc_ctx = (duk__encode_context *) udata;
	DUK_ASSERT(enc_ctx != NULL);

#if !defined(DUK_USE_PREFER_SIZE)
	if (codepoint <= 0x7f && enc_ctx->lead == 0x0000L) {
		/* Fast path for ASCII. */
		*enc_ctx->out++ = (duk_uint8_t) codepoint;
		return;
	}
#endif

	if (DUK_UNLIKELY(codepoint > 0x10ffffL)) {
		/* cannot legally encode in UTF-8 */
		codepoint = DUK_UNICODE_CP_REPLACEMENT_CHARACTER;
	} else if (codepoint >= 0xd800L && codepoint <= 0xdfffL) {
		if (codepoint <= 0xdbffL) {
			/* high surrogate */
			duk_codepoint_t prev_lead = enc_ctx->lead;
			enc_ctx->lead = codepoint;
			if (prev_lead == 0x0000L) {
				/* high surrogate, no output */
				return;
			} else {
				/* consecutive high surrogates, consider first one unpaired */
				codepoint = DUK_UNICODE_CP_REPLACEMENT_CHARACTER;
			}
		} else {
			/* low surrogate */
			if (enc_ctx->lead != 0x0000L) {
				codepoint = (duk_codepoint_t) (0x010000L + ((enc_ctx->lead - 0xd800L) << 10) + (codepoint - 0xdc00L));
				enc_ctx->lead = 0x0000L;
			} else {
				/* unpaired low surrogate */
				DUK_ASSERT(enc_ctx->lead == 0x0000L);
				codepoint = DUK_UNICODE_CP_REPLACEMENT_CHARACTER;
			}
		}
	} else {
		if (enc_ctx->lead != 0x0000L) {
			/* unpaired high surrogate: emit replacement character and the input codepoint */
			enc_ctx->lead = 0x0000L;
			enc_ctx->out = duk__utf8_emit_repl(enc_ctx->out);
		}
	}

	/* Codepoint may be original input, a decoded surrogate pair, or may
	 * have been replaced with U+FFFD.
	 */
	enc_ctx->out += duk_unicode_encode_xutf8((duk_ucodepoint_t) codepoint, enc_ctx->out);
}
#endif  /* DUK_USE_ENCODING_BUILTINS */

/* Shared helper for buffer-to-string using a TextDecoder() compatible UTF-8
 * decoder.
 */
DUK_LOCAL duk_ret_t duk__decode_helper(duk_hthread *thr, duk__decode_context *dec_ctx) {
	const duk_uint8_t *input;
	duk_size_t len = 0;
	duk_size_t len_tmp;
	duk_bool_t stream = 0;
	duk_codepoint_t codepoint;
	duk_uint8_t *output;
	const duk_uint8_t *in;
	duk_uint8_t *out;

	DUK_ASSERT(dec_ctx != NULL);

	/* Careful with input buffer pointer: any side effects involving
	 * code execution (e.g. getters, coercion calls, and finalizers)
	 * may cause a resize and invalidate a pointer we've read.  This
	 * is why the pointer is actually looked up at the last minute.
	 * Argument validation must still happen first to match WHATWG
	 * required side effect order.
	 */

	if (duk_is_undefined(thr, 0)) {
		duk_push_fixed_buffer_nozero(thr, 0);
		duk_replace(thr, 0);
	}
	(void) duk_require_buffer_data(thr, 0, &len);  /* Need 'len', avoid pointer. */

	if (duk_check_type_mask(thr, 1, DUK_TYPE_MASK_UNDEFINED |
	                                DUK_TYPE_MASK_NULL |
	                                DUK_TYPE_MASK_NONE)) {
		/* Use defaults, treat missing value like undefined. */
	} else {
		duk_require_type_mask(thr, 1, DUK_TYPE_MASK_UNDEFINED |
	                                      DUK_TYPE_MASK_NULL |
	                                      DUK_TYPE_MASK_LIGHTFUNC |
	                                      DUK_TYPE_MASK_BUFFER |
		                              DUK_TYPE_MASK_OBJECT);
		if (duk_get_prop_literal(thr, 1, "stream")) {
			stream = duk_to_boolean(thr, -1);
		}
	}

	/* Allowance is 3*len in the general case because all bytes may potentially
	 * become U+FFFD.  If the first byte completes a non-BMP codepoint it will
	 * decode to a CESU-8 surrogate pair (6 bytes) so we allow 3 extra bytes to
	 * compensate: (1*3)+3 = 6.  Non-BMP codepoints are safe otherwise because
	 * the 4->6 expansion is well under the 3x allowance.
	 *
	 * XXX: As with TextEncoder, need a better buffer allocation strategy here.
	 */
	if (len >= (DUK_HBUFFER_MAX_BYTELEN / 3) - 3) {
		DUK_ERROR_TYPE(thr, DUK_STR_RESULT_TOO_LONG);
		DUK_WO_NORETURN(return 0;);
	}
	output = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, 3 + (3 * len));  /* used parts will be always manually written over */

	input = (const duk_uint8_t *) duk_get_buffer_data(thr, 0, &len_tmp);
	DUK_ASSERT(input != NULL || len == 0);
	if (DUK_UNLIKELY(len != len_tmp)) {
		/* Very unlikely but possible: source buffer was resized by
		 * a side effect when fixed buffer was pushed.  Output buffer
		 * may not be large enough to hold output, so just fail if
		 * length has changed.
		 */
		DUK_D(DUK_DPRINT("input buffer resized by side effect, fail"));
		goto fail_type;
	}

	/* From this point onwards it's critical that no side effect occur
	 * which may disturb 'input': finalizer execution, property accesses,
	 * active coercions, etc.  Even an allocation related mark-and-sweep
	 * may affect the pointer because it may trigger a pending finalizer.
	 */

	in = input;
	out = output;
	while (in < input + len) {
		codepoint = duk__utf8_decode_next(dec_ctx, *in++);
		if (codepoint < 0) {
			if (codepoint == DUK__CP_CONTINUE) {
				continue;
			}

			/* Decoding error with or without retry. */
			DUK_ASSERT(codepoint == DUK__CP_ERROR || codepoint == DUK__CP_RETRY);
			if (codepoint == DUK__CP_RETRY) {
				--in;  /* retry last byte */
			}
			/* replacement mode: replace with U+FFFD */
			codepoint = DUK_UNICODE_CP_REPLACEMENT_CHARACTER;
			if (dec_ctx->fatal) {
				/* fatal mode: throw a TypeError */
				goto fail_type;
			}
			/* Continue with 'codepoint', Unicode replacement. */
		}
		DUK_ASSERT(codepoint >= 0x0000L && codepoint <= 0x10ffffL);

		if (!dec_ctx->bom_handled) {
			dec_ctx->bom_handled = 1;
			if (codepoint == 0xfeffL && !dec_ctx->ignore_bom) {
				continue;
			}
		}

		out += duk_unicode_encode_cesu8((duk_ucodepoint_t) codepoint, out);
		DUK_ASSERT(out <= output + (3 + (3 * len)));
	}

	if (!stream) {
		if (dec_ctx->needed != 0) {
			/* truncated sequence at end of buffer */
			if (dec_ctx->fatal) {
				goto fail_type;
			} else {
				out += duk_unicode_encode_cesu8(DUK_UNICODE_CP_REPLACEMENT_CHARACTER, out);
				DUK_ASSERT(out <= output + (3 + (3 * len)));
			}
		}
		duk__utf8_decode_init(dec_ctx);  /* Initialize decoding state for potential reuse. */
	}

	/* Output buffer is fixed and thus stable even if there had been
	 * side effects (which there shouldn't be).
	 */
	duk_push_lstring(thr, (const char *) output, (duk_size_t) (out - output));
	return 1;

 fail_type:
	DUK_ERROR_TYPE(thr, DUK_STR_UTF8_DECODE_FAILED);
	DUK_WO_NORETURN(return 0;);
}

/*
 *  Built-in bindings
 */

#if defined(DUK_USE_ENCODING_BUILTINS)
DUK_INTERNAL duk_ret_t duk_bi_textencoder_constructor(duk_hthread *thr) {
	/* TextEncoder currently requires no persistent state, so the constructor
	 * does nothing on purpose.
	 */

	duk_require_constructor_call(thr);
	return 0;
}

DUK_INTERNAL duk_ret_t duk_bi_textencoder_prototype_encoding_getter(duk_hthread *thr) {
	duk_push_literal(thr, "utf-8");
	return 1;
}

DUK_INTERNAL duk_ret_t duk_bi_textencoder_prototype_encode(duk_hthread *thr) {
	duk__encode_context enc_ctx;
	duk_size_t len;
	duk_size_t final_len;
	duk_uint8_t *output;

	DUK_ASSERT_TOP(thr, 1);
	if (duk_is_undefined(thr, 0)) {
		len = 0;
	} else {
		duk_hstring *h_input;

		h_input = duk_to_hstring(thr, 0);
		DUK_ASSERT(h_input != NULL);

		len = (duk_size_t) DUK_HSTRING_GET_CHARLEN(h_input);
		if (len >= DUK_HBUFFER_MAX_BYTELEN / 3) {
			DUK_ERROR_TYPE(thr, DUK_STR_RESULT_TOO_LONG);
			DUK_WO_NORETURN(return 0;);
		}
	}

	/* Allowance is 3*len because all bytes can potentially be replaced with
	 * U+FFFD -- which rather inconveniently encodes to 3 bytes in UTF-8.
	 * Rely on dynamic buffer data pointer stability: no other code has
	 * access to the data pointer.
	 *
	 * XXX: The buffer allocation strategy used here is rather inefficient.
	 * Maybe switch to a chunk-based strategy, or preprocess the string to
	 * figure out the space needed ahead of time?
	 */
	DUK_ASSERT(3 * len >= len);
	output = (duk_uint8_t *) duk_push_dynamic_buffer(thr, 3 * len);

	if (len > 0) {
		DUK_ASSERT(duk_is_string(thr, 0));  /* True if len > 0. */

		/* XXX: duk_decode_string() is used to process the input
		 * string.  For standard ECMAScript strings, represented
		 * internally as CESU-8, this is fine.  However, behavior
		 * beyond CESU-8 is not very strict: codepoints using an
		 * extended form of UTF-8 are also accepted, and invalid
		 * codepoint sequences (which are allowed in Duktape strings)
		 * are not handled as well as they could (e.g. invalid
		 * continuation bytes may mask following codepoints).
		 * This is how ECMAScript code would also see such strings.
		 * Maybe replace duk_decode_string() with an explicit strict
		 * CESU-8 decoder here?
		 */
		enc_ctx.lead = 0x0000L;
		enc_ctx.out = output;
		duk_decode_string(thr, 0, duk__utf8_encode_char, (void *) &enc_ctx);
		if (enc_ctx.lead != 0x0000L) {
			/* unpaired high surrogate at end of string */
			enc_ctx.out = duk__utf8_emit_repl(enc_ctx.out);
			DUK_ASSERT(enc_ctx.out <= output + (3 * len));
		}

		/* The output buffer is usually very much oversized, so shrink it to
		 * actually needed size.  Pointer stability assumed up to this point.
		 */
		DUK_ASSERT_TOP(thr, 2);
		DUK_ASSERT(output == (duk_uint8_t *) duk_get_buffer_data(thr, -1, NULL));

		final_len = (duk_size_t) (enc_ctx.out - output);
		duk_resize_buffer(thr, -1, final_len);
		/* 'output' and 'enc_ctx.out' are potentially invalidated by the resize. */
	} else {
		final_len = 0;
	}

	/* Standard WHATWG output is a Uint8Array.  Here the Uint8Array will
	 * be backed by a dynamic buffer which differs from e.g. Uint8Arrays
	 * created as 'new Uint8Array(N)'.  ECMAScript code won't see the
	 * difference but C code will.  When bufferobjects are not supported,
	 * returns a plain dynamic buffer.
	 */
#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
	duk_push_buffer_object(thr, -1, 0, final_len, DUK_BUFOBJ_UINT8ARRAY);
#endif
	return 1;
}

DUK_INTERNAL duk_ret_t duk_bi_textdecoder_constructor(duk_hthread *thr) {
	duk__decode_context *dec_ctx;
	duk_bool_t fatal = 0;
	duk_bool_t ignore_bom = 0;

	DUK_ASSERT_TOP(thr, 2);
	duk_require_constructor_call(thr);
	if (!duk_is_undefined(thr, 0)) {
		/* XXX: For now ignore 'label' (encoding identifier). */
		duk_to_string(thr, 0);
	}
	if (!duk_is_null_or_undefined(thr, 1)) {
		if (duk_get_prop_literal(thr, 1, "fatal")) {
			fatal = duk_to_boolean(thr, -1);
		}
		if (duk_get_prop_literal(thr, 1, "ignoreBOM")) {
			ignore_bom = duk_to_boolean(thr, -1);
		}
	}

	duk_push_this(thr);

	/* The decode context is not assumed to be zeroed; all fields are
	 * initialized explicitly.
	 */
	dec_ctx = (duk__decode_context *) duk_push_fixed_buffer(thr, sizeof(duk__decode_context));
	dec_ctx->fatal = (duk_uint8_t) fatal;
	dec_ctx->ignore_bom = (duk_uint8_t) ignore_bom;
	duk__utf8_decode_init(dec_ctx);  /* Initializes remaining fields. */

	duk_put_prop_literal(thr, -2, DUK_INTERNAL_SYMBOL("Context"));
	return 0;
}

/* Get TextDecoder context from 'this'; leaves garbage on stack. */
DUK_LOCAL duk__decode_context *duk__get_textdecoder_context(duk_hthread *thr) {
	duk__decode_context *dec_ctx;
	duk_push_this(thr);
	duk_get_prop_literal(thr, -1, DUK_INTERNAL_SYMBOL("Context"));
	dec_ctx = (duk__decode_context *) duk_require_buffer(thr, -1, NULL);
	DUK_ASSERT(dec_ctx != NULL);
	return dec_ctx;
}

DUK_INTERNAL duk_ret_t duk_bi_textdecoder_prototype_shared_getter(duk_hthread *thr) {
	duk__decode_context *dec_ctx;
	duk_int_t magic;

	dec_ctx = duk__get_textdecoder_context(thr);
	magic = duk_get_current_magic(thr);
	switch (magic) {
	case 0:
		/* Encoding is now fixed, so _Context lookup is only needed to
		 * validate the 'this' binding (TypeError if not TextDecoder-like).
		 */
		duk_push_literal(thr, "utf-8");
		break;
	case 1:
		duk_push_boolean(thr, dec_ctx->fatal);
		break;
	default:
		duk_push_boolean(thr, dec_ctx->ignore_bom);
		break;
	}

	return 1;
}

DUK_INTERNAL duk_ret_t duk_bi_textdecoder_prototype_decode(duk_hthread *thr) {
	duk__decode_context *dec_ctx;

	dec_ctx = duk__get_textdecoder_context(thr);
	return duk__decode_helper(thr, dec_ctx);
}
#endif  /* DUK_USE_ENCODING_BUILTINS */

/*
 *  Internal helper for Node.js Buffer
 */

/* Internal helper used for Node.js Buffer .toString().  Value stack convention
 * is currently odd: it mimics TextDecoder .decode() so that argument must be at
 * index 0, and decode options (not present for Buffer) at index 1.  Return value
 * is a Duktape/C function return value.
 */
DUK_INTERNAL duk_ret_t duk_textdecoder_decode_utf8_nodejs(duk_hthread *thr) {
	duk__decode_context dec_ctx;

	dec_ctx.fatal = 0;  /* use replacement chars */
	dec_ctx.ignore_bom = 1;  /* ignore BOMs (matches Node.js Buffer .toString()) */
	duk__utf8_decode_init(&dec_ctx);

	return duk__decode_helper(thr, &dec_ctx);
}

/* automatic undefs */
#undef DUK__CP_CONTINUE
#undef DUK__CP_ERROR
#undef DUK__CP_RETRY
#line 1 "duk_bi_error.c"
/*
 *  Error built-ins
 */

/* #include duk_internal.h -> already included */

DUK_INTERNAL duk_ret_t duk_bi_error_constructor_shared(duk_hthread *thr) {
	/* Behavior for constructor and non-constructor call is
	 * the same except for augmenting the created error.  When
	 * called as a constructor, the caller (duk_new()) will handle
	 * augmentation; when called as normal function, we need to do
	 * it here.
	 */

	duk_small_int_t bidx_prototype = duk_get_current_magic(thr);

	/* same for both error and each subclass like TypeError */
	duk_uint_t flags_and_class = DUK_HOBJECT_FLAG_EXTENSIBLE |
	                             DUK_HOBJECT_FLAG_FASTREFS |
	                             DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ERROR);

	(void) duk_push_object_helper(thr, flags_and_class, bidx_prototype);

	/* If message is undefined, the own property 'message' is not set at
	 * all to save property space.  An empty message is inherited anyway.
	 */
	if (!duk_is_undefined(thr, 0)) {
		duk_to_string(thr, 0);
		duk_dup_0(thr);  /* [ message error message ] */
		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_MESSAGE, DUK_PROPDESC_FLAGS_WC);
	}

	/* Augment the error if called as a normal function.  __FILE__ and __LINE__
	 * are not desirable in this case.
	 */

#if defined(DUK_USE_AUGMENT_ERROR_CREATE)
	if (!duk_is_constructor_call(thr)) {
		duk_err_augment_error_create(thr, thr, NULL, 0, DUK_AUGMENT_FLAG_NOBLAME_FILELINE);
	}
#endif

	return 1;
}

DUK_INTERNAL duk_ret_t duk_bi_error_prototype_to_string(duk_hthread *thr) {
	/* XXX: optimize with more direct internal access */

	duk_push_this(thr);
	(void) duk_require_hobject_promote_mask(thr, -1, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);

	/* [ ... this ] */

	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_NAME);
	if (duk_is_undefined(thr, -1)) {
		duk_pop(thr);
		duk_push_literal(thr, "Error");
	} else {
		duk_to_string(thr, -1);
	}

	/* [ ... this name ] */

	/* XXX: Are steps 6 and 7 in E5 Section 15.11.4.4 duplicated by
	 * accident or are they actually needed?  The first ToString()
	 * could conceivably return 'undefined'.
	 */
	duk_get_prop_stridx_short(thr, -2, DUK_STRIDX_MESSAGE);
	if (duk_is_undefined(thr, -1)) {
		duk_pop(thr);
		duk_push_hstring_empty(thr);
	} else {
		duk_to_string(thr, -1);
	}

	/* [ ... this name message ] */

	if (duk_get_length(thr, -2) == 0) {
		/* name is empty -> return message */
		return 1;
	}
	if (duk_get_length(thr, -1) == 0) {
		/* message is empty -> return name */
		duk_pop(thr);
		return 1;
	}
	duk_push_literal(thr, ": ");
	duk_insert(thr, -2);  /* ... name ': ' message */
	duk_concat(thr, 3);

	return 1;
}

#if defined(DUK_USE_TRACEBACKS)

/*
 *  Traceback handling
 *
 *  The unified helper decodes the traceback and produces various requested
 *  outputs.  It should be optimized for size, and may leave garbage on stack,
 *  only the topmost return value matters.  For instance, traceback separator
 *  and decoded strings are pushed even when looking for filename only.
 *
 *  NOTE: although _Tracedata is an internal property, user code can currently
 *  write to the array (or replace it with something other than an array).
 *  The code below must tolerate arbitrary _Tracedata.  It can throw errors
 *  etc, but cannot cause a segfault or memory unsafe behavior.
 */

/* constants arbitrary, chosen for small loads */
#define DUK__OUTPUT_TYPE_TRACEBACK   (-1)
#define DUK__OUTPUT_TYPE_FILENAME    0
#define DUK__OUTPUT_TYPE_LINENUMBER  1

DUK_LOCAL duk_ret_t duk__error_getter_helper(duk_hthread *thr, duk_small_int_t output_type) {
	duk_idx_t idx_td;
	duk_small_int_t i;  /* traceback depth fits into 16 bits */
	duk_small_int_t t;  /* stack type fits into 16 bits */
	duk_small_int_t count_func = 0;  /* traceback depth ensures fits into 16 bits */
	const char *str_tailcall = " tailcall";
	const char *str_strict = " strict";
	const char *str_construct = " construct";
	const char *str_prevyield = " preventsyield";
	const char *str_directeval = " directeval";
	const char *str_empty = "";

	DUK_ASSERT_TOP(thr, 0);  /* fixed arg count */

	duk_push_this(thr);
	duk_xget_owndataprop_stridx_short(thr, -1, DUK_STRIDX_INT_TRACEDATA);
	idx_td = duk_get_top_index(thr);

	duk_push_hstring_stridx(thr, DUK_STRIDX_NEWLINE_4SPACE);
	duk_push_this(thr);

	/* [ ... this tracedata sep this ] */

	/* XXX: skip null filename? */

	if (duk_check_type(thr, idx_td, DUK_TYPE_OBJECT)) {
		/* Current tracedata contains 2 entries per callstack entry. */
		for (i = 0; ; i += 2) {
			duk_int_t pc;
			duk_uint_t line;
			duk_uint_t flags;
			duk_double_t d;
			const char *funcname;
			const char *filename;
			duk_hobject *h_func;
			duk_hstring *h_name;

			duk_require_stack(thr, 5);
			duk_get_prop_index(thr, idx_td, (duk_uarridx_t) i);
			duk_get_prop_index(thr, idx_td, (duk_uarridx_t) (i + 1));
			d = duk_to_number_m1(thr);
			pc = duk_double_to_int_t(DUK_FMOD(d, DUK_DOUBLE_2TO32));
			flags = duk_double_to_uint_t(DUK_FLOOR(d / DUK_DOUBLE_2TO32));
			t = (duk_small_int_t) duk_get_type(thr, -2);

			if (t == DUK_TYPE_OBJECT || t == DUK_TYPE_LIGHTFUNC) {
				/*
				 *  ECMAScript/native function call or lightfunc call
				 */

				count_func++;

				/* [ ... v1(func) v2(pc+flags) ] */

				/* These may be systematically omitted by Duktape
				 * with certain config options, but allow user to
				 * set them on a case-by-case basis.
				 */
				duk_get_prop_stridx_short(thr, -2, DUK_STRIDX_NAME);
				duk_get_prop_stridx_short(thr, -3, DUK_STRIDX_FILE_NAME);

#if defined(DUK_USE_PC2LINE)
				line = (duk_uint_t) duk_hobject_pc2line_query(thr, -4, (duk_uint_fast32_t) pc);
#else
				line = 0;
#endif

				/* [ ... v1 v2 name filename ] */

				/* When looking for .fileName/.lineNumber, blame first
				 * function which has a .fileName.
				 */
				if (duk_is_string_notsymbol(thr, -1)) {
					if (output_type == DUK__OUTPUT_TYPE_FILENAME) {
						return 1;
					} else if (output_type == DUK__OUTPUT_TYPE_LINENUMBER) {
						duk_push_uint(thr, line);
						return 1;
					}
				}

				/* XXX: Change 'anon' handling here too, to use empty string for anonymous functions? */
				/* XXX: Could be improved by coercing to a readable duk_tval (especially string escaping) */
				h_name = duk_get_hstring_notsymbol(thr, -2);  /* may be NULL */
				funcname = (h_name == NULL || h_name == DUK_HTHREAD_STRING_EMPTY_STRING(thr)) ?
				           "[anon]" : (const char *) DUK_HSTRING_GET_DATA(h_name);
				filename = duk_get_string_notsymbol(thr, -1);
				filename = filename ? filename : "";
				DUK_ASSERT(funcname != NULL);
				DUK_ASSERT(filename != NULL);

				h_func = duk_get_hobject(thr, -4);  /* NULL for lightfunc */

				if (h_func == NULL) {
					duk_push_sprintf(thr, "at %s light%s%s%s%s%s",
					                 (const char *) funcname,
					                 (const char *) ((flags & DUK_ACT_FLAG_STRICT) ? str_strict : str_empty),
					                 (const char *) ((flags & DUK_ACT_FLAG_TAILCALLED) ? str_tailcall : str_empty),
					                 (const char *) ((flags & DUK_ACT_FLAG_CONSTRUCT) ? str_construct : str_empty),
					                 (const char *) ((flags & DUK_ACT_FLAG_DIRECT_EVAL) ? str_directeval : str_empty),
					                 (const char *) ((flags & DUK_ACT_FLAG_PREVENT_YIELD) ? str_prevyield : str_empty));
				} else if (DUK_HOBJECT_HAS_NATFUNC(h_func)) {
					duk_push_sprintf(thr, "at %s (%s) native%s%s%s%s%s",
					                 (const char *) funcname,
					                 (const char *) filename,
					                 (const char *) ((flags & DUK_ACT_FLAG_STRICT) ? str_strict : str_empty),
					                 (const char *) ((flags & DUK_ACT_FLAG_TAILCALLED) ? str_tailcall : str_empty),
					                 (const char *) ((flags & DUK_ACT_FLAG_CONSTRUCT) ? str_construct : str_empty),
					                 (const char *) ((flags & DUK_ACT_FLAG_DIRECT_EVAL) ? str_directeval : str_empty),
					                 (const char *) ((flags & DUK_ACT_FLAG_PREVENT_YIELD) ? str_prevyield : str_empty));
				} else {
					duk_push_sprintf(thr, "at %s (%s:%lu)%s%s%s%s%s",
					                 (const char *) funcname,
					                 (const char *) filename,
					                 (unsigned long) line,
					                 (const char *) ((flags & DUK_ACT_FLAG_STRICT) ? str_strict : str_empty),
					                 (const char *) ((flags & DUK_ACT_FLAG_TAILCALLED) ? str_tailcall : str_empty),
					                 (const char *) ((flags & DUK_ACT_FLAG_CONSTRUCT) ? str_construct : str_empty),
					                 (const char *) ((flags & DUK_ACT_FLAG_DIRECT_EVAL) ? str_directeval : str_empty),
					                 (const char *) ((flags & DUK_ACT_FLAG_PREVENT_YIELD) ? str_prevyield : str_empty));
				}
				duk_replace(thr, -5);   /* [ ... v1 v2 name filename str ] -> [ ... str v2 name filename ] */
				duk_pop_3(thr);         /* -> [ ... str ] */
			} else if (t == DUK_TYPE_STRING) {
				const char *str_file;

				/*
				 *  __FILE__ / __LINE__ entry, here 'pc' is line number directly.
				 *  Sometimes __FILE__ / __LINE__ is reported as the source for
				 *  the error (fileName, lineNumber), sometimes not.
				 */

				/* [ ... v1(filename) v2(line+flags) ] */

				/* When looking for .fileName/.lineNumber, blame compilation
				 * or C call site unless flagged not to do so.
				 */
				if (!(flags & DUK_TB_FLAG_NOBLAME_FILELINE)) {
					if (output_type == DUK__OUTPUT_TYPE_FILENAME) {
						duk_pop(thr);
						return 1;
					} else if (output_type == DUK__OUTPUT_TYPE_LINENUMBER) {
						duk_push_int(thr, pc);
						return 1;
					}
				}

				/* Tracedata is trusted but avoid any risk of using a NULL
				 * for %s format because it has undefined behavior.  Symbols
				 * don't need to be explicitly rejected as they pose no memory
				 * safety issues.
				 */
				str_file = (const char *) duk_get_string(thr, -2);
				duk_push_sprintf(thr, "at [anon] (%s:%ld) internal",
				                 (const char *) (str_file ? str_file : "null"), (long) pc);
				duk_replace(thr, -3);  /* [ ... v1 v2 str ] -> [ ... str v2 ] */
				duk_pop(thr);          /* -> [ ... str ] */
			} else {
				/* unknown, ignore */
				duk_pop_2(thr);
				break;
			}
		}

		if (count_func >= DUK_USE_TRACEBACK_DEPTH) {
			/* Possibly truncated; there is no explicit truncation
			 * marker so this is the best we can do.
			 */

			duk_push_hstring_stridx(thr, DUK_STRIDX_BRACKETED_ELLIPSIS);
		}
	}

	/* [ ... this tracedata sep this str1 ... strN ] */

	if (output_type != DUK__OUTPUT_TYPE_TRACEBACK) {
		return 0;
	} else {
		/* The 'this' after 'sep' will get ToString() coerced by
		 * duk_join() automatically.  We don't want to do that
		 * coercion when providing .fileName or .lineNumber (GH-254).
		 */
		duk_join(thr, duk_get_top(thr) - (idx_td + 2) /*count, not including sep*/);
		return 1;
	}
}

/* XXX: Output type could be encoded into native function 'magic' value to
 * save space.  For setters the stridx could be encoded into 'magic'.
 */

DUK_INTERNAL duk_ret_t duk_bi_error_prototype_stack_getter(duk_hthread *thr) {
	return duk__error_getter_helper(thr, DUK__OUTPUT_TYPE_TRACEBACK);
}

DUK_INTERNAL duk_ret_t duk_bi_error_prototype_filename_getter(duk_hthread *thr) {
	return duk__error_getter_helper(thr, DUK__OUTPUT_TYPE_FILENAME);
}

DUK_INTERNAL duk_ret_t duk_bi_error_prototype_linenumber_getter(duk_hthread *thr) {
	return duk__error_getter_helper(thr, DUK__OUTPUT_TYPE_LINENUMBER);
}

#else  /* DUK_USE_TRACEBACKS */

/*
 *  Traceback handling when tracebacks disabled.
 *
 *  The fileName / lineNumber stubs are now necessary because built-in
 *  data will include the accessor properties in Error.prototype.  If those
 *  are removed for builds without tracebacks, these can also be removed.
 *  'stack' should still be present and produce a ToString() equivalent:
 *  this is useful for user code which prints a stacktrace and expects to
 *  see something useful.  A normal stacktrace also begins with a ToString()
 *  of the error so this makes sense.
 */

DUK_INTERNAL duk_ret_t duk_bi_error_prototype_stack_getter(duk_hthread *thr) {
	/* XXX: remove this native function and map 'stack' accessor
	 * to the toString() implementation directly.
	 */
	return duk_bi_error_prototype_to_string(thr);
}

DUK_INTERNAL duk_ret_t duk_bi_error_prototype_filename_getter(duk_hthread *thr) {
	DUK_UNREF(thr);
	return 0;
}

DUK_INTERNAL duk_ret_t duk_bi_error_prototype_linenumber_getter(duk_hthread *thr) {
	DUK_UNREF(thr);
	return 0;
}

#endif  /* DUK_USE_TRACEBACKS */

DUK_LOCAL duk_ret_t duk__error_setter_helper(duk_hthread *thr, duk_small_uint_t stridx_key) {
	/* Attempt to write 'stack', 'fileName', 'lineNumber' works as if
	 * user code called Object.defineProperty() to create an overriding
	 * own property.  This allows user code to overwrite .fileName etc
	 * intuitively as e.g. "err.fileName = 'dummy'" as one might expect.
	 * See https://github.com/svaarala/duktape/issues/387.
	 */

	DUK_ASSERT_TOP(thr, 1);  /* fixed arg count: value */

	duk_push_this(thr);
	duk_push_hstring_stridx(thr, stridx_key);
	duk_dup_0(thr);

	/* [ ... obj key value ] */

	DUK_DD(DUK_DDPRINT("error setter: %!T %!T %!T",
	                   duk_get_tval(thr, -3), duk_get_tval(thr, -2), duk_get_tval(thr, -1)));

	duk_def_prop(thr, -3, DUK_DEFPROP_HAVE_VALUE |
	                      DUK_DEFPROP_HAVE_WRITABLE | DUK_DEFPROP_WRITABLE |
	                      DUK_DEFPROP_HAVE_ENUMERABLE | /*not enumerable*/
	                      DUK_DEFPROP_HAVE_CONFIGURABLE | DUK_DEFPROP_CONFIGURABLE);
	return 0;
}

DUK_INTERNAL duk_ret_t duk_bi_error_prototype_stack_setter(duk_hthread *thr) {
	return duk__error_setter_helper(thr, DUK_STRIDX_STACK);
}

DUK_INTERNAL duk_ret_t duk_bi_error_prototype_filename_setter(duk_hthread *thr) {
	return duk__error_setter_helper(thr, DUK_STRIDX_FILE_NAME);
}

DUK_INTERNAL duk_ret_t duk_bi_error_prototype_linenumber_setter(duk_hthread *thr) {
	return duk__error_setter_helper(thr, DUK_STRIDX_LINE_NUMBER);
}

/* automatic undefs */
#undef DUK__OUTPUT_TYPE_FILENAME
#undef DUK__OUTPUT_TYPE_LINENUMBER
#undef DUK__OUTPUT_TYPE_TRACEBACK
#line 1 "duk_bi_function.c"
/*
 *  Function built-ins
 */

/* #include duk_internal.h -> already included */

/* Needed even when Function built-in is disabled. */
DUK_INTERNAL duk_ret_t duk_bi_function_prototype(duk_hthread *thr) {
	/* ignore arguments, return undefined (E5 Section 15.3.4) */
	DUK_UNREF(thr);
	return 0;
}

#if defined(DUK_USE_FUNCTION_BUILTIN)
DUK_INTERNAL duk_ret_t duk_bi_function_constructor(duk_hthread *thr) {
	duk_hstring *h_sourcecode;
	duk_idx_t nargs;
	duk_idx_t i;
	duk_small_uint_t comp_flags;
	duk_hcompfunc *func;
	duk_hobject *outer_lex_env;
	duk_hobject *outer_var_env;

	/* normal and constructor calls have identical semantics */

	nargs = duk_get_top(thr);
	for (i = 0; i < nargs; i++) {
		duk_to_string(thr, i);  /* Rejects Symbols during coercion. */
	}

	if (nargs == 0) {
		duk_push_hstring_empty(thr);
		duk_push_hstring_empty(thr);
	} else if (nargs == 1) {
		/* XXX: cover this with the generic >1 case? */
		duk_push_hstring_empty(thr);
	} else {
		duk_insert(thr, 0);   /* [ arg1 ... argN-1 body] -> [body arg1 ... argN-1] */
		duk_push_literal(thr, ",");
		duk_insert(thr, 1);
		duk_join(thr, nargs - 1);
	}

	/* [ body formals ], formals is comma separated list that needs to be parsed */

	DUK_ASSERT_TOP(thr, 2);

	/* XXX: this placeholder is not always correct, but use for now.
	 * It will fail in corner cases; see test-dev-func-cons-args.js.
	 */
	duk_push_literal(thr, "function(");
	duk_dup_1(thr);
	duk_push_literal(thr, "){");
	duk_dup_0(thr);
	duk_push_literal(thr, "\n}");  /* Newline is important to handle trailing // comment. */
	duk_concat(thr, 5);

	/* [ body formals source ] */

	DUK_ASSERT_TOP(thr, 3);

	/* strictness is not inherited, intentional */
	comp_flags = DUK_COMPILE_FUNCEXPR;

	duk_push_hstring_stridx(thr, DUK_STRIDX_COMPILE);  /* XXX: copy from caller? */  /* XXX: ignored now */
	h_sourcecode = duk_require_hstring(thr, -2);  /* no symbol check needed; -2 is concat'd code */
	duk_js_compile(thr,
	               (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_sourcecode),
	               (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_sourcecode),
	               comp_flags);

	/* Force .name to 'anonymous' (ES2015). */
	duk_push_literal(thr, "anonymous");
	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_C);

	func = (duk_hcompfunc *) duk_known_hobject(thr, -1);
	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) func));
	DUK_ASSERT(DUK_HOBJECT_HAS_CONSTRUCTABLE((duk_hobject *) func));

	/* [ body formals source template ] */

	/* only outer_lex_env matters, as functions always get a new
	 * variable declaration environment.
	 */

	outer_lex_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
	outer_var_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];

	duk_js_push_closure(thr, func, outer_var_env, outer_lex_env, 1 /*add_auto_proto*/);

	/* [ body formals source template closure ] */

	return 1;
}
#endif  /* DUK_USE_FUNCTION_BUILTIN */

#if defined(DUK_USE_FUNCTION_BUILTIN)
DUK_INTERNAL duk_ret_t duk_bi_function_prototype_to_string(duk_hthread *thr) {
	duk_tval *tv;

	/*
	 *  E5 Section 15.3.4.2 places few requirements on the output of
	 *  this function: the result is implementation dependent, must
	 *  follow FunctionDeclaration syntax (in particular, must have a
	 *  name even for anonymous functions or functions with empty name).
	 *  The output does NOT need to compile into anything useful.
	 *
	 *  E6 Section 19.2.3.5 changes the requirements completely: the
	 *  result must either eval() to a functionally equivalent object
	 *  OR eval() to a SyntaxError.
	 *
	 *  We opt for the SyntaxError approach for now, with a syntax that
	 *  mimics V8's native function syntax:
	 *
	 *      'function cos() { [native code] }'
	 *
	 *  but extended with [ecmascript code], [bound code], and
	 *  [lightfunc code].
	 */

	duk_push_this(thr);
	tv = DUK_GET_TVAL_NEGIDX(thr, -1);
	DUK_ASSERT(tv != NULL);

	if (DUK_TVAL_IS_OBJECT(tv)) {
		duk_hobject *obj = DUK_TVAL_GET_OBJECT(tv);
		const char *func_name;

		/* Function name: missing/undefined is mapped to empty string,
		 * otherwise coerce to string.  No handling for invalid identifier
		 * characters or e.g. '{' in the function name.  This doesn't
		 * really matter as long as a SyntaxError results.  Technically
		 * if the name contained a suitable prefix followed by '//' it
		 * might cause the result to parse without error.
		 */
		duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_NAME);
		if (duk_is_undefined(thr, -1)) {
			func_name = "";
		} else {
			func_name = duk_to_string(thr, -1);
			DUK_ASSERT(func_name != NULL);
		}

		if (DUK_HOBJECT_IS_COMPFUNC(obj)) {
			duk_push_sprintf(thr, "function %s() { [ecmascript code] }", (const char *) func_name);
		} else if (DUK_HOBJECT_IS_NATFUNC(obj)) {
			duk_push_sprintf(thr, "function %s() { [native code] }", (const char *) func_name);
		} else if (DUK_HOBJECT_IS_BOUNDFUNC(obj)) {
			duk_push_sprintf(thr, "function %s() { [bound code] }", (const char *) func_name);
		} else {
			goto type_error;
		}
	} else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
		duk_push_lightfunc_tostring(thr, tv);
	} else {
		goto type_error;
	}

	return 1;

 type_error:
	DUK_DCERROR_TYPE_INVALID_ARGS(thr);
}
#endif

/* Always present because the native function pointer is needed in call
 * handling.
 */
DUK_INTERNAL duk_ret_t duk_bi_function_prototype_call(duk_hthread *thr) {
	/* .call() is dealt with in call handling by simulating its
	 * effects so this function is actually never called.
	 */
	DUK_UNREF(thr);
	return DUK_RET_TYPE_ERROR;
}

DUK_INTERNAL duk_ret_t duk_bi_function_prototype_apply(duk_hthread *thr) {
	/* Like .call(), never actually called. */
	DUK_UNREF(thr);
	return DUK_RET_TYPE_ERROR;
}

DUK_INTERNAL duk_ret_t duk_bi_reflect_apply(duk_hthread *thr) {
	/* Like .call(), never actually called. */
	DUK_UNREF(thr);
	return DUK_RET_TYPE_ERROR;
}

DUK_INTERNAL duk_ret_t duk_bi_reflect_construct(duk_hthread *thr) {
	/* Like .call(), never actually called. */
	DUK_UNREF(thr);
	return DUK_RET_TYPE_ERROR;
}

#if defined(DUK_USE_FUNCTION_BUILTIN)
/* Create a bound function which points to a target function which may
 * be bound or non-bound.  If the target is bound, the argument lists
 * and 'this' binding of the functions are merged and the resulting
 * function points directly to the non-bound target.
 */
DUK_INTERNAL duk_ret_t duk_bi_function_prototype_bind(duk_hthread *thr) {
	duk_hboundfunc *h_bound;
	duk_idx_t nargs;  /* bound args, not counting 'this' binding */
	duk_idx_t bound_nargs;
	duk_int_t bound_len;
	duk_tval *tv_prevbound;
	duk_idx_t n_prevbound;
	duk_tval *tv_res;
	duk_tval *tv_tmp;

	/* XXX: C API call, e.g. duk_push_bound_function(thr, target_idx, nargs); */

	/* Vararg function, careful arg handling, e.g. thisArg may not
	 * be present.
	 */
	nargs = duk_get_top(thr) - 1;  /* actual args, not counting 'this' binding */
	if (nargs < 0) {
		nargs++;
		duk_push_undefined(thr);
	}
	DUK_ASSERT(nargs >= 0);

	/* Limit 'nargs' for bound functions to guarantee arithmetic
	 * below will never wrap.
	 */
	if (nargs > (duk_idx_t) DUK_HBOUNDFUNC_MAX_ARGS) {
		DUK_DCERROR_RANGE_INVALID_COUNT(thr);
	}

	duk_push_this(thr);
	duk_require_callable(thr, -1);

	/* [ thisArg arg1 ... argN func ]  (thisArg+args == nargs+1 total) */
	DUK_ASSERT_TOP(thr, nargs + 2);

	/* Create bound function object. */
	h_bound = duk_push_hboundfunc(thr);
	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&h_bound->target));
	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&h_bound->this_binding));
	DUK_ASSERT(h_bound->args == NULL);
	DUK_ASSERT(h_bound->nargs == 0);
	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_bound) == NULL);

	/* [ thisArg arg1 ... argN func boundFunc ] */

	/* If the target is a bound function, argument lists must be
	 * merged.  The 'this' binding closest to the target function
	 * wins because in call handling the 'this' gets replaced over
	 * and over again until we call the non-bound function.
	 */
	tv_prevbound = NULL;
	n_prevbound = 0;
	tv_tmp = DUK_GET_TVAL_POSIDX(thr, 0);
	DUK_TVAL_SET_TVAL(&h_bound->this_binding, tv_tmp);
	tv_tmp = DUK_GET_TVAL_NEGIDX(thr, -2);
	DUK_TVAL_SET_TVAL(&h_bound->target, tv_tmp);

	if (DUK_TVAL_IS_OBJECT(tv_tmp)) {
		duk_hobject *h_target;
		duk_hobject *bound_proto;

		h_target = DUK_TVAL_GET_OBJECT(tv_tmp);
		DUK_ASSERT(DUK_HOBJECT_IS_CALLABLE(h_target));

		/* Internal prototype must be copied from the target.
		 * For lightfuncs Function.prototype is used and is already
		 * in place.
		 */
		bound_proto = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_target);
		DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) h_bound, bound_proto);

		/* The 'strict' flag is copied to get the special [[Get]] of E5.1
		 * Section 15.3.5.4 to apply when a 'caller' value is a strict bound
		 * function.  Not sure if this is correct, because the specification
		 * is a bit ambiguous on this point but it would make sense.
		 */
		/* Strictness is inherited from target. */
		if (DUK_HOBJECT_HAS_STRICT(h_target)) {
			DUK_HOBJECT_SET_STRICT((duk_hobject *) h_bound);
		}

		if (DUK_HOBJECT_HAS_BOUNDFUNC(h_target)) {
			duk_hboundfunc *h_boundtarget;

			h_boundtarget = (duk_hboundfunc *) (void *) h_target;

			/* The final function should always be non-bound, unless
			 * there's a bug in the internals.  Assert for it.
			 */
			DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(&h_boundtarget->target) ||
			           (DUK_TVAL_IS_OBJECT(&h_boundtarget->target) &&
			            DUK_HOBJECT_IS_CALLABLE(DUK_TVAL_GET_OBJECT(&h_boundtarget->target)) &&
			            !DUK_HOBJECT_IS_BOUNDFUNC(DUK_TVAL_GET_OBJECT(&h_boundtarget->target))));

			DUK_TVAL_SET_TVAL(&h_bound->target, &h_boundtarget->target);
			DUK_TVAL_SET_TVAL(&h_bound->this_binding, &h_boundtarget->this_binding);

			tv_prevbound = h_boundtarget->args;
			n_prevbound = h_boundtarget->nargs;
		}
	} else {
		/* Lightfuncs are always strict. */
		duk_hobject *bound_proto;

		DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv_tmp));
		DUK_HOBJECT_SET_STRICT((duk_hobject *) h_bound);
		bound_proto = thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE];
		DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) h_bound, bound_proto);
	}

	DUK_TVAL_INCREF(thr, &h_bound->target);  /* old values undefined, no decref needed */
	DUK_TVAL_INCREF(thr, &h_bound->this_binding);

	bound_nargs = n_prevbound + nargs;
	if (bound_nargs > (duk_idx_t) DUK_HBOUNDFUNC_MAX_ARGS) {
		DUK_DCERROR_RANGE_INVALID_COUNT(thr);
	}
	tv_res = (duk_tval *) DUK_ALLOC_CHECKED(thr, ((duk_size_t) bound_nargs) * sizeof(duk_tval));
	DUK_ASSERT(tv_res != NULL || bound_nargs == 0);
	DUK_ASSERT(h_bound->args == NULL);
	DUK_ASSERT(h_bound->nargs == 0);
	h_bound->args = tv_res;
	h_bound->nargs = bound_nargs;

	DUK_ASSERT(n_prevbound >= 0);
	duk_copy_tvals_incref(thr, tv_res, tv_prevbound, (duk_size_t) n_prevbound);
	DUK_ASSERT(nargs >= 0);
	duk_copy_tvals_incref(thr, tv_res + n_prevbound, DUK_GET_TVAL_POSIDX(thr, 1), (duk_size_t) nargs);

	/* [ thisArg arg1 ... argN func boundFunc ] */

	/* Bound function 'length' property is interesting.
	 * For lightfuncs, simply read the virtual property.
	 */
	duk_get_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH);
	bound_len = duk_get_int(thr, -1);  /* ES2015: no coercion */
	if (bound_len < nargs) {
		bound_len = 0;
	} else {
		bound_len -= nargs;
	}
	if (sizeof(duk_int_t) > 4 && bound_len > (duk_int_t) DUK_UINT32_MAX) {
		bound_len = (duk_int_t) DUK_UINT32_MAX;
	}
	duk_pop(thr);
	DUK_ASSERT(bound_len >= 0);
	tv_tmp = thr->valstack_top++;
	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv_tmp));
	DUK_ASSERT(!DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv_tmp));
	DUK_TVAL_SET_U32(tv_tmp, (duk_uint32_t) bound_len);  /* in-place update, fastint */
	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_C);  /* attrs in E6 Section 9.2.4 */

	/* XXX: could these be virtual? */
	/* Caller and arguments must use the same thrower, [[ThrowTypeError]]. */
	duk_xdef_prop_stridx_thrower(thr, -1, DUK_STRIDX_CALLER);
	duk_xdef_prop_stridx_thrower(thr, -1, DUK_STRIDX_LC_ARGUMENTS);

	/* Function name and fileName (non-standard). */
	duk_push_literal(thr, "bound ");  /* ES2015 19.2.3.2. */
	duk_get_prop_stridx(thr, -3, DUK_STRIDX_NAME);
	if (!duk_is_string_notsymbol(thr, -1)) {
		/* ES2015 has requirement to check that .name of target is a string
		 * (also must check for Symbol); if not, targetName should be the
		 * empty string.  ES2015 19.2.3.2.
		 */
		duk_pop(thr);
		duk_push_hstring_empty(thr);
	}
	duk_concat(thr, 2);
	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_C);
#if defined(DUK_USE_FUNC_FILENAME_PROPERTY)
	duk_get_prop_stridx_short(thr, -2, DUK_STRIDX_FILE_NAME);
	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_FILE_NAME, DUK_PROPDESC_FLAGS_C);
#endif

	DUK_DDD(DUK_DDDPRINT("created bound function: %!iT", (duk_tval *) duk_get_tval(thr, -1)));

	return 1;
}
#endif  /* DUK_USE_FUNCTION_BUILTIN */

/* %NativeFunctionPrototype% .length getter. */
DUK_INTERNAL duk_ret_t duk_bi_native_function_length(duk_hthread *thr) {
	duk_tval *tv;
	duk_hnatfunc *h;
	duk_int16_t func_nargs;

	tv = duk_get_borrowed_this_tval(thr);
	DUK_ASSERT(tv != NULL);

	if (DUK_TVAL_IS_OBJECT(tv)) {
		h = (duk_hnatfunc *) DUK_TVAL_GET_OBJECT(tv);
		DUK_ASSERT(h != NULL);
		if (!DUK_HOBJECT_IS_NATFUNC((duk_hobject *) h)) {
			goto fail_type;
		}
		func_nargs = h->nargs;
		duk_push_int(thr, func_nargs == DUK_HNATFUNC_NARGS_VARARGS ? 0 : func_nargs);
	} else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
		duk_small_uint_t lf_flags;
		duk_small_uint_t lf_len;

		lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv);
		lf_len = DUK_LFUNC_FLAGS_GET_LENGTH(lf_flags);
		duk_push_uint(thr, lf_len);
	} else {
		goto fail_type;
	}
	return 1;

 fail_type:
	DUK_DCERROR_TYPE_INVALID_ARGS(thr);
}

/* %NativeFunctionPrototype% .name getter. */
DUK_INTERNAL duk_ret_t duk_bi_native_function_name(duk_hthread *thr) {
	duk_tval *tv;
	duk_hnatfunc *h;

	tv = duk_get_borrowed_this_tval(thr);
	DUK_ASSERT(tv != NULL);

	if (DUK_TVAL_IS_OBJECT(tv)) {
		h = (duk_hnatfunc *) DUK_TVAL_GET_OBJECT(tv);
		DUK_ASSERT(h != NULL);
		if (!DUK_HOBJECT_IS_NATFUNC((duk_hobject *) h)) {
			goto fail_type;
		}
#if 0
		duk_push_hnatfunc_name(thr, h);
#endif
		duk_push_hstring_empty(thr);
	} else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
		duk_push_lightfunc_name(thr, tv);
	} else {
		goto fail_type;
	}
	return 1;

 fail_type:
	DUK_DCERROR_TYPE_INVALID_ARGS(thr);
}

#if defined(DUK_USE_SYMBOL_BUILTIN)
DUK_INTERNAL duk_ret_t duk_bi_function_prototype_hasinstance(duk_hthread *thr) {
	/* This binding: RHS, stack index 0: LHS. */
	duk_bool_t ret;

	ret = duk_js_instanceof_ordinary(thr, DUK_GET_TVAL_POSIDX(thr, 0), DUK_GET_THIS_TVAL_PTR(thr));
	duk_push_boolean(thr, ret);
	return 1;
}
#endif  /* DUK_USE_SYMBOL_BUILTIN */
#line 1 "duk_bi_global.c"
/*
 *  Global object built-ins
 */

/* #include duk_internal.h -> already included */

/*
 *  Encoding/decoding helpers
 */

/* XXX: Could add fast path (for each transform callback) with direct byte
 * lookups (no shifting) and no explicit check for x < 0x80 before table
 * lookup.
 */

/* Macros for creating and checking bitmasks for character encoding.
 * Bit number is a bit counterintuitive, but minimizes code size.
 */
#define DUK__MKBITS(a,b,c,d,e,f,g,h)  ((duk_uint8_t) ( \
	((a) << 0) | ((b) << 1) | ((c) << 2) | ((d) << 3) | \
	((e) << 4) | ((f) << 5) | ((g) << 6) | ((h) << 7) \
	))
#define DUK__CHECK_BITMASK(table,cp)  ((table)[(cp) >> 3] & (1 << ((cp) & 0x07)))

/* E5.1 Section 15.1.3.3: uriReserved + uriUnescaped + '#' */
DUK_LOCAL const duk_uint8_t duk__encode_uriunescaped_table[16] = {
	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x00-0x0f */
	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x10-0x1f */
	DUK__MKBITS(0, 1, 0, 1, 1, 0, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1),  /* 0x20-0x2f */
	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 0, 1, 0, 1),  /* 0x30-0x3f */
	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1),  /* 0x40-0x4f */
	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 1),  /* 0x50-0x5f */
	DUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1),  /* 0x60-0x6f */
	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 1, 0),  /* 0x70-0x7f */
};

/* E5.1 Section 15.1.3.4: uriUnescaped */
DUK_LOCAL const duk_uint8_t duk__encode_uricomponent_unescaped_table[16] = {
	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x00-0x0f */
	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x10-0x1f */
	DUK__MKBITS(0, 1, 0, 0, 0, 0, 0, 1), DUK__MKBITS(1, 1, 1, 0, 0, 1, 1, 0),  /* 0x20-0x2f */
	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 0, 0, 0, 0, 0, 0),  /* 0x30-0x3f */
	DUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1),  /* 0x40-0x4f */
	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 1),  /* 0x50-0x5f */
	DUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1),  /* 0x60-0x6f */
	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 1, 0),  /* 0x70-0x7f */
};

/* E5.1 Section 15.1.3.1: uriReserved + '#' */
DUK_LOCAL const duk_uint8_t duk__decode_uri_reserved_table[16] = {
	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x00-0x0f */
	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x10-0x1f */
	DUK__MKBITS(0, 0, 0, 1, 1, 0, 1, 0), DUK__MKBITS(0, 0, 0, 1, 1, 0, 0, 1),  /* 0x20-0x2f */
	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 1, 1, 0, 1, 0, 1),  /* 0x30-0x3f */
	DUK__MKBITS(1, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x40-0x4f */
	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x50-0x5f */
	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x60-0x6f */
	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x70-0x7f */
};

/* E5.1 Section 15.1.3.2: empty */
DUK_LOCAL const duk_uint8_t duk__decode_uri_component_reserved_table[16] = {
	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x00-0x0f */
	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x10-0x1f */
	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x20-0x2f */
	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x30-0x3f */
	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x40-0x4f */
	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x50-0x5f */
	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x60-0x6f */
	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x70-0x7f */
};

#if defined(DUK_USE_SECTION_B)
/* E5.1 Section B.2.2, step 7. */
DUK_LOCAL const duk_uint8_t duk__escape_unescaped_table[16] = {
	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x00-0x0f */
	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x10-0x1f */
	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 1, 1, 0, 1, 1, 1),  /* 0x20-0x2f */
	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 0, 0, 0, 0, 0, 0),  /* 0x30-0x3f */
	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1),  /* 0x40-0x4f */
	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 1),  /* 0x50-0x5f */
	DUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1),  /* 0x60-0x6f */
	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 0)   /* 0x70-0x7f */
};
#endif  /* DUK_USE_SECTION_B */

typedef struct {
	duk_hthread *thr;
	duk_hstring *h_str;
	duk_bufwriter_ctx bw;
	const duk_uint8_t *p;
	const duk_uint8_t *p_start;
	const duk_uint8_t *p_end;
} duk__transform_context;

typedef void (*duk__transform_callback)(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp);

/* XXX: refactor and share with other code */
DUK_LOCAL duk_small_int_t duk__decode_hex_escape(const duk_uint8_t *p, duk_small_int_t n) {
	duk_small_int_t ch;
	duk_small_int_t t = 0;

	while (n > 0) {
		t = t * 16;
		ch = (duk_small_int_t) duk_hex_dectab[*p++];
		if (DUK_LIKELY(ch >= 0)) {
			t += ch;
		} else {
			return -1;
		}
		n--;
	}
	return t;
}

DUK_LOCAL int duk__transform_helper(duk_hthread *thr, duk__transform_callback callback, const void *udata) {
	duk__transform_context tfm_ctx_alloc;
	duk__transform_context *tfm_ctx = &tfm_ctx_alloc;
	duk_codepoint_t cp;

	tfm_ctx->thr = thr;

	tfm_ctx->h_str = duk_to_hstring(thr, 0);
	DUK_ASSERT(tfm_ctx->h_str != NULL);

	DUK_BW_INIT_PUSHBUF(thr, &tfm_ctx->bw, DUK_HSTRING_GET_BYTELEN(tfm_ctx->h_str));  /* initial size guess */

	tfm_ctx->p_start = DUK_HSTRING_GET_DATA(tfm_ctx->h_str);
	tfm_ctx->p_end = tfm_ctx->p_start + DUK_HSTRING_GET_BYTELEN(tfm_ctx->h_str);
	tfm_ctx->p = tfm_ctx->p_start;

	while (tfm_ctx->p < tfm_ctx->p_end) {
		cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &tfm_ctx->p, tfm_ctx->p_start, tfm_ctx->p_end);
		callback(tfm_ctx, udata, cp);
	}

	DUK_BW_COMPACT(thr, &tfm_ctx->bw);

	(void) duk_buffer_to_string(thr, -1);  /* Safe if transform is safe. */
	return 1;
}

DUK_LOCAL void duk__transform_callback_encode_uri(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp) {
	duk_uint8_t xutf8_buf[DUK_UNICODE_MAX_XUTF8_LENGTH];
	duk_small_int_t len;
	duk_codepoint_t cp1, cp2;
	duk_small_int_t i, t;
	const duk_uint8_t *unescaped_table = (const duk_uint8_t *) udata;

	/* UTF-8 encoded bytes escaped as %xx%xx%xx... -> 3 * nbytes.
	 * Codepoint range is restricted so this is a slightly too large
	 * but doesn't matter.
	 */
	DUK_BW_ENSURE(tfm_ctx->thr, &tfm_ctx->bw, 3 * DUK_UNICODE_MAX_XUTF8_LENGTH);

	if (cp < 0) {
		goto uri_error;
	} else if ((cp < 0x80L) && DUK__CHECK_BITMASK(unescaped_table, cp)) {
		DUK_BW_WRITE_RAW_U8(tfm_ctx->thr, &tfm_ctx->bw, (duk_uint8_t) cp);
		return;
	} else if (cp >= 0xdc00L && cp <= 0xdfffL) {
		goto uri_error;
	} else if (cp >= 0xd800L && cp <= 0xdbffL) {
		/* Needs lookahead */
		if (duk_unicode_decode_xutf8(tfm_ctx->thr, &tfm_ctx->p, tfm_ctx->p_start, tfm_ctx->p_end, (duk_ucodepoint_t *) &cp2) == 0) {
			goto uri_error;
		}
		if (!(cp2 >= 0xdc00L && cp2 <= 0xdfffL)) {
			goto uri_error;
		}
		cp1 = cp;
		cp = (duk_codepoint_t) (((cp1 - 0xd800L) << 10) + (cp2 - 0xdc00L) + 0x10000L);
	} else if (cp > 0x10ffffL) {
		/* Although we can allow non-BMP characters (they'll decode
		 * back into surrogate pairs), we don't allow extended UTF-8
		 * characters; they would encode to URIs which won't decode
		 * back because of strict UTF-8 checks in URI decoding.
		 * (However, we could just as well allow them here.)
		 */
		goto uri_error;
	} else {
		/* Non-BMP characters within valid UTF-8 range: encode as is.
		 * They'll decode back into surrogate pairs if the escaped
		 * output is decoded.
		 */
		;
	}

	len = duk_unicode_encode_xutf8((duk_ucodepoint_t) cp, xutf8_buf);
	for (i = 0; i < len; i++) {
		t = (duk_small_int_t) xutf8_buf[i];
		DUK_BW_WRITE_RAW_U8_3(tfm_ctx->thr,
		                      &tfm_ctx->bw,
		                      DUK_ASC_PERCENT,
		                      (duk_uint8_t) duk_uc_nybbles[t >> 4],
                                      (duk_uint8_t) duk_uc_nybbles[t & 0x0f]);
	}

	return;

 uri_error:
	DUK_ERROR_URI(tfm_ctx->thr, DUK_STR_INVALID_INPUT);
	DUK_WO_NORETURN(return;);
}

DUK_LOCAL void duk__transform_callback_decode_uri(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp) {
	const duk_uint8_t *reserved_table = (const duk_uint8_t *) udata;
	duk_small_uint_t utf8_blen;
	duk_codepoint_t min_cp;
	duk_small_int_t t;  /* must be signed */
	duk_small_uint_t i;

	/* Maximum write size: XUTF8 path writes max DUK_UNICODE_MAX_XUTF8_LENGTH,
	 * percent escape path writes max two times CESU-8 encoded BMP length.
	 */
	DUK_BW_ENSURE(tfm_ctx->thr,
	              &tfm_ctx->bw,
	              (DUK_UNICODE_MAX_XUTF8_LENGTH >= 2 * DUK_UNICODE_MAX_CESU8_BMP_LENGTH ?
	              DUK_UNICODE_MAX_XUTF8_LENGTH : DUK_UNICODE_MAX_CESU8_BMP_LENGTH));

	if (cp == (duk_codepoint_t) '%') {
		const duk_uint8_t *p = tfm_ctx->p;
		duk_size_t left = (duk_size_t) (tfm_ctx->p_end - p);  /* bytes left */

		DUK_DDD(DUK_DDDPRINT("percent encoding, left=%ld", (long) left));

		if (left < 2) {
			goto uri_error;
		}

		t = duk__decode_hex_escape(p, 2);
		DUK_DDD(DUK_DDDPRINT("first byte: %ld", (long) t));
		if (t < 0) {
			goto uri_error;
		}

		if (t < 0x80) {
			if (DUK__CHECK_BITMASK(reserved_table, t)) {
				/* decode '%xx' to '%xx' if decoded char in reserved set */
				DUK_ASSERT(tfm_ctx->p - 1 >= tfm_ctx->p_start);
				DUK_BW_WRITE_RAW_U8_3(tfm_ctx->thr,
				                      &tfm_ctx->bw,
				                      DUK_ASC_PERCENT,
				                      p[0],
				                      p[1]);
			} else {
				DUK_BW_WRITE_RAW_U8(tfm_ctx->thr, &tfm_ctx->bw, (duk_uint8_t) t);
			}
			tfm_ctx->p += 2;
			return;
		}

		/* Decode UTF-8 codepoint from a sequence of hex escapes.  The
		 * first byte of the sequence has been decoded to 't'.
		 *
		 * Note that UTF-8 validation must be strict according to the
		 * specification: E5.1 Section 15.1.3, decode algorithm step
		 * 4.d.vii.8.  URIError from non-shortest encodings is also
		 * specifically noted in the spec.
		 */

		DUK_ASSERT(t >= 0x80);
		if (t < 0xc0) {
			/* continuation byte */
			goto uri_error;
		} else if (t < 0xe0) {
			/* 110x xxxx; 2 bytes */
			utf8_blen = 2;
			min_cp = 0x80L;
			cp = t & 0x1f;
		} else if (t < 0xf0) {
			/* 1110 xxxx; 3 bytes */
			utf8_blen = 3;
			min_cp = 0x800L;
			cp = t & 0x0f;
		} else if (t < 0xf8) {
			/* 1111 0xxx; 4 bytes */
			utf8_blen = 4;
			min_cp = 0x10000L;
			cp = t & 0x07;
		} else {
			/* extended utf-8 not allowed for URIs */
			goto uri_error;
		}

		if (left < utf8_blen * 3 - 1) {
			/* '%xx%xx...%xx', p points to char after first '%' */
			goto uri_error;
		}

		p += 3;
		for (i = 1; i < utf8_blen; i++) {
			/* p points to digit part ('%xy', p points to 'x') */
			t = duk__decode_hex_escape(p, 2);
			DUK_DDD(DUK_DDDPRINT("i=%ld utf8_blen=%ld cp=%ld t=0x%02lx",
			                     (long) i, (long) utf8_blen, (long) cp, (unsigned long) t));
			if (t < 0) {
				goto uri_error;
			}
			if ((t & 0xc0) != 0x80) {
				goto uri_error;
			}
			cp = (cp << 6) + (t & 0x3f);
			p += 3;
		}
		p--;  /* p overshoots */
		tfm_ctx->p = p;

		DUK_DDD(DUK_DDDPRINT("final cp=%ld, min_cp=%ld", (long) cp, (long) min_cp));

		if (cp < min_cp || cp > 0x10ffffL || (cp >= 0xd800L && cp <= 0xdfffL)) {
			goto uri_error;
		}

		/* The E5.1 algorithm checks whether or not a decoded codepoint
		 * is below 0x80 and perhaps may be in the "reserved" set.
		 * This seems pointless because the single byte UTF-8 case is
		 * handled separately, and non-shortest encodings are rejected.
		 * So, 'cp' cannot be below 0x80 here, and thus cannot be in
		 * the reserved set.
		 */

		/* utf-8 validation ensures these */
		DUK_ASSERT(cp >= 0x80L && cp <= 0x10ffffL);

		if (cp >= 0x10000L) {
			cp -= 0x10000L;
			DUK_ASSERT(cp < 0x100000L);

			DUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, ((cp >> 10) + 0xd800L));
			DUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, ((cp & 0x03ffL) + 0xdc00L));
		} else {
			DUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, cp);
		}
	} else {
		DUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, cp);
	}
	return;

 uri_error:
	DUK_ERROR_URI(tfm_ctx->thr, DUK_STR_INVALID_INPUT);
	DUK_WO_NORETURN(return;);
}

#if defined(DUK_USE_SECTION_B)
DUK_LOCAL void duk__transform_callback_escape(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp) {
	DUK_UNREF(udata);

	DUK_BW_ENSURE(tfm_ctx->thr, &tfm_ctx->bw, 6);

	if (cp < 0) {
		goto esc_error;
	} else if ((cp < 0x80L) && DUK__CHECK_BITMASK(duk__escape_unescaped_table, cp)) {
		DUK_BW_WRITE_RAW_U8(tfm_ctx->thr, &tfm_ctx->bw, (duk_uint8_t) cp);
	} else if (cp < 0x100L) {
		DUK_BW_WRITE_RAW_U8_3(tfm_ctx->thr,
		                      &tfm_ctx->bw,
		                      (duk_uint8_t) DUK_ASC_PERCENT,
		                      (duk_uint8_t) duk_uc_nybbles[cp >> 4],
		                      (duk_uint8_t) duk_uc_nybbles[cp & 0x0f]);
	} else if (cp < 0x10000L) {
		DUK_BW_WRITE_RAW_U8_6(tfm_ctx->thr,
		                      &tfm_ctx->bw,
		                      (duk_uint8_t) DUK_ASC_PERCENT,
		                      (duk_uint8_t) DUK_ASC_LC_U,
		                      (duk_uint8_t) duk_uc_nybbles[cp >> 12],
		                      (duk_uint8_t) duk_uc_nybbles[(cp >> 8) & 0x0f],
		                      (duk_uint8_t) duk_uc_nybbles[(cp >> 4) & 0x0f],
		                      (duk_uint8_t) duk_uc_nybbles[cp & 0x0f]);
	} else {
		/* Characters outside BMP cannot be escape()'d.  We could
		 * encode them as surrogate pairs (for codepoints inside
		 * valid UTF-8 range, but not extended UTF-8).  Because
		 * escape() and unescape() are legacy functions, we don't.
		 */
		goto esc_error;
	}

	return;

 esc_error:
	DUK_ERROR_TYPE(tfm_ctx->thr, DUK_STR_INVALID_INPUT);
	DUK_WO_NORETURN(return;);
}

DUK_LOCAL void duk__transform_callback_unescape(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp) {
	duk_small_int_t t;

	DUK_UNREF(udata);

	if (cp == (duk_codepoint_t) '%') {
		const duk_uint8_t *p = tfm_ctx->p;
		duk_size_t left = (duk_size_t) (tfm_ctx->p_end - p);  /* bytes left */

		if (left >= 5 && p[0] == 'u' &&
		    ((t = duk__decode_hex_escape(p + 1, 4)) >= 0)) {
			cp = (duk_codepoint_t) t;
			tfm_ctx->p += 5;
		} else if (left >= 2 &&
		           ((t = duk__decode_hex_escape(p, 2)) >= 0)) {
			cp = (duk_codepoint_t) t;
			tfm_ctx->p += 2;
		}
	}

	DUK_BW_WRITE_ENSURE_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, cp);
}
#endif  /* DUK_USE_SECTION_B */

/*
 *  Eval
 *
 *  Eval needs to handle both a "direct eval" and an "indirect eval".
 *  Direct eval handling needs access to the caller's activation so that its
 *  lexical environment can be accessed.  A direct eval is only possible from
 *  ECMAScript code; an indirect eval call is possible also from C code.
 *  When an indirect eval call is made from C code, there may not be a
 *  calling activation at all which needs careful handling.
 */

DUK_INTERNAL duk_ret_t duk_bi_global_object_eval(duk_hthread *thr) {
	duk_hstring *h;
	duk_activation *act_caller;
	duk_activation *act_eval;
	duk_hcompfunc *func;
	duk_hobject *outer_lex_env;
	duk_hobject *outer_var_env;
	duk_bool_t this_to_global = 1;
	duk_small_uint_t comp_flags;
	duk_int_t level = -2;
	duk_small_uint_t call_flags;

	DUK_ASSERT(duk_get_top(thr) == 1 || duk_get_top(thr) == 2);  /* 2 when called by debugger */
	DUK_ASSERT(thr->callstack_top >= 1);  /* at least this function exists */
	DUK_ASSERT(thr->callstack_curr != NULL);
	DUK_ASSERT((thr->callstack_curr->flags & DUK_ACT_FLAG_DIRECT_EVAL) == 0 || /* indirect eval */
	           (thr->callstack_top >= 2));  /* if direct eval, calling activation must exist */

	/*
	 *  callstack_top - 1 --> this function
	 *  callstack_top - 2 --> caller (may not exist)
	 *
	 *  If called directly from C, callstack_top might be 1.  If calling
	 *  activation doesn't exist, call must be indirect.
	 */

	h = duk_get_hstring_notsymbol(thr, 0);
	if (!h) {
		/* Symbol must be returned as is, like any non-string values. */
		return 1;  /* return arg as-is */
	}

#if defined(DUK_USE_DEBUGGER_SUPPORT)
	/* NOTE: level is used only by the debugger and should never be present
	 * for an ECMAScript eval().
	 */
	DUK_ASSERT(level == -2);  /* by default, use caller's environment */
	if (duk_get_top(thr) >= 2 && duk_is_number(thr, 1)) {
		level = duk_get_int(thr, 1);
	}
	DUK_ASSERT(level <= -2);  /* This is guaranteed by debugger code. */
#endif

	/* [ source ] */

	comp_flags = DUK_COMPILE_EVAL;
	act_eval = thr->callstack_curr;  /* this function */
	DUK_ASSERT(act_eval != NULL);
	act_caller = duk_hthread_get_activation_for_level(thr, level);
	if (act_caller != NULL) {
		/* Have a calling activation, check for direct eval (otherwise
		 * assume indirect eval.
		 */
		if ((act_caller->flags & DUK_ACT_FLAG_STRICT) &&
		    (act_eval->flags & DUK_ACT_FLAG_DIRECT_EVAL)) {
			/* Only direct eval inherits strictness from calling code
			 * (E5.1 Section 10.1.1).
			 */
			comp_flags |= DUK_COMPILE_STRICT;
		}
	} else {
		DUK_ASSERT((act_eval->flags & DUK_ACT_FLAG_DIRECT_EVAL) == 0);
	}

	duk_push_hstring_stridx(thr, DUK_STRIDX_INPUT);  /* XXX: copy from caller? */
	duk_js_compile(thr,
	               (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h),
	               (duk_size_t) DUK_HSTRING_GET_BYTELEN(h),
	               comp_flags);
	func = (duk_hcompfunc *) duk_known_hobject(thr, -1);
	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) func));

	/* [ source template ] */

	/* E5 Section 10.4.2 */

	if (act_eval->flags & DUK_ACT_FLAG_DIRECT_EVAL) {
		DUK_ASSERT(thr->callstack_top >= 2);
		DUK_ASSERT(act_caller != NULL);
		if (act_caller->lex_env == NULL) {
			DUK_ASSERT(act_caller->var_env == NULL);
			DUK_DDD(DUK_DDDPRINT("delayed environment initialization"));

			/* this may have side effects, so re-lookup act */
			duk_js_init_activation_environment_records_delayed(thr, act_caller);
		}
		DUK_ASSERT(act_caller->lex_env != NULL);
		DUK_ASSERT(act_caller->var_env != NULL);

		this_to_global = 0;

		if (DUK_HOBJECT_HAS_STRICT((duk_hobject *) func)) {
			duk_hdecenv *new_env;
			duk_hobject *act_lex_env;

			DUK_DDD(DUK_DDDPRINT("direct eval call to a strict function -> "
			                     "var_env and lex_env to a fresh env, "
			                     "this_binding to caller's this_binding"));

			act_lex_env = act_caller->lex_env;

			new_env = duk_hdecenv_alloc(thr,
			                            DUK_HOBJECT_FLAG_EXTENSIBLE |
			                            DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV));
			DUK_ASSERT(new_env != NULL);
			duk_push_hobject(thr, (duk_hobject *) new_env);

			DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) new_env) == NULL);
			DUK_HOBJECT_SET_PROTOTYPE(thr->heap, (duk_hobject *) new_env, act_lex_env);
			DUK_HOBJECT_INCREF_ALLOWNULL(thr, act_lex_env);
			DUK_DDD(DUK_DDDPRINT("new_env allocated: %!iO", (duk_heaphdr *) new_env));

			outer_lex_env = (duk_hobject *) new_env;
			outer_var_env = (duk_hobject *) new_env;

			duk_insert(thr, 0);  /* stash to bottom of value stack to keep new_env reachable for duration of eval */

			/* compiler's responsibility */
			DUK_ASSERT(DUK_HOBJECT_HAS_NEWENV((duk_hobject *) func));
		} else {
			DUK_DDD(DUK_DDDPRINT("direct eval call to a non-strict function -> "
			                     "var_env and lex_env to caller's envs, "
			                     "this_binding to caller's this_binding"));

			outer_lex_env = act_caller->lex_env;
			outer_var_env = act_caller->var_env;

			/* compiler's responsibility */
			DUK_ASSERT(!DUK_HOBJECT_HAS_NEWENV((duk_hobject *) func));
		}
	} else {
		DUK_DDD(DUK_DDDPRINT("indirect eval call -> var_env and lex_env to "
		                     "global object, this_binding to global object"));

		this_to_global = 1;
		outer_lex_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
		outer_var_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
	}

	/* Eval code doesn't need an automatic .prototype object. */
	duk_js_push_closure(thr, func, outer_var_env, outer_lex_env, 0 /*add_auto_proto*/);

	/* [ env? source template closure ] */

	if (this_to_global) {
		DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
		duk_push_hobject_bidx(thr, DUK_BIDX_GLOBAL);
	} else {
		duk_tval *tv;
		DUK_ASSERT(thr->callstack_top >= 2);
		DUK_ASSERT(act_caller != NULL);
		tv = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + act_caller->bottom_byteoff - sizeof(duk_tval));  /* this is just beneath bottom */
		DUK_ASSERT(tv >= thr->valstack);
		duk_push_tval(thr, tv);
	}

	DUK_DDD(DUK_DDDPRINT("eval -> lex_env=%!iO, var_env=%!iO, this_binding=%!T",
	                     (duk_heaphdr *) outer_lex_env,
	                     (duk_heaphdr *) outer_var_env,
	                     duk_get_tval(thr, -1)));

	/* [ env? source template closure this ] */

	call_flags = 0;
	if (act_eval->flags & DUK_ACT_FLAG_DIRECT_EVAL) {
		/* Set DIRECT_EVAL flag for the call; it's not strictly
		 * needed for the 'inner' eval call (the eval body) but
		 * current new.target implementation expects to find it
		 * so it can traverse direct eval chains up to the real
		 * calling function.
		 */
		call_flags |= DUK_CALL_FLAG_DIRECT_EVAL;
	}
	duk_handle_call_unprotected_nargs(thr, 0, call_flags);

	/* [ env? source template result ] */

	return 1;
}

/*
 *  Parsing of ints and floats
 */

#if defined(DUK_USE_GLOBAL_BUILTIN)
DUK_INTERNAL duk_ret_t duk_bi_global_object_parse_int(duk_hthread *thr) {
	duk_int32_t radix;
	duk_small_uint_t s2n_flags;

	DUK_ASSERT_TOP(thr, 2);
	duk_to_string(thr, 0);  /* Reject symbols. */

	radix = duk_to_int32(thr, 1);

	/* While parseInt() recognizes 0xdeadbeef, it doesn't recognize
	 * ES2015 0o123 or 0b10001.
	 */
	s2n_flags = DUK_S2N_FLAG_TRIM_WHITE |
	            DUK_S2N_FLAG_ALLOW_GARBAGE |
	            DUK_S2N_FLAG_ALLOW_PLUS |
	            DUK_S2N_FLAG_ALLOW_MINUS |
	            DUK_S2N_FLAG_ALLOW_LEADING_ZERO |
	            DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT;

	/* Specification stripPrefix maps to DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT.
	 *
	 * Don't autodetect octals (from leading zeroes), require user code to
	 * provide an explicit radix 8 for parsing octal.  See write-up from Mozilla:
	 * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt#ECMAScript_5_Removes_Octal_Interpretation
	 */

	if (radix != 0) {
		if (radix < 2 || radix > 36) {
			goto ret_nan;
		}
		if (radix != 16) {
			s2n_flags &= ~DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT;
		}
	} else {
		radix = 10;
	}

	duk_dup_0(thr);
	duk_numconv_parse(thr, (duk_small_int_t) radix, s2n_flags);
	return 1;

 ret_nan:
	duk_push_nan(thr);
	return 1;
}
#endif  /* DUK_USE_GLOBAL_BUILTIN */

#if defined(DUK_USE_GLOBAL_BUILTIN)
DUK_INTERNAL duk_ret_t duk_bi_global_object_parse_float(duk_hthread *thr) {
	duk_small_uint_t s2n_flags;

	DUK_ASSERT_TOP(thr, 1);
	duk_to_string(thr, 0);  /* Reject symbols. */

	/* XXX: check flags */
	s2n_flags = DUK_S2N_FLAG_TRIM_WHITE |
	            DUK_S2N_FLAG_ALLOW_EXP |
	            DUK_S2N_FLAG_ALLOW_GARBAGE |
	            DUK_S2N_FLAG_ALLOW_PLUS |
	            DUK_S2N_FLAG_ALLOW_MINUS |
	            DUK_S2N_FLAG_ALLOW_INF |
	            DUK_S2N_FLAG_ALLOW_FRAC |
	            DUK_S2N_FLAG_ALLOW_NAKED_FRAC |
	            DUK_S2N_FLAG_ALLOW_EMPTY_FRAC |
	            DUK_S2N_FLAG_ALLOW_LEADING_ZERO;

	duk_numconv_parse(thr, 10 /*radix*/, s2n_flags);
	return 1;
}
#endif  /* DUK_USE_GLOBAL_BUILTIN */

/*
 *  Number checkers
 */

#if defined(DUK_USE_GLOBAL_BUILTIN)
DUK_INTERNAL duk_ret_t duk_bi_global_object_is_nan(duk_hthread *thr) {
	duk_double_t d = duk_to_number(thr, 0);
	duk_push_boolean(thr, (duk_bool_t) DUK_ISNAN(d));
	return 1;
}
#endif  /* DUK_USE_GLOBAL_BUILTIN */

#if defined(DUK_USE_GLOBAL_BUILTIN)
DUK_INTERNAL duk_ret_t duk_bi_global_object_is_finite(duk_hthread *thr) {
	duk_double_t d = duk_to_number(thr, 0);
	duk_push_boolean(thr, (duk_bool_t) DUK_ISFINITE(d));
	return 1;
}
#endif  /* DUK_USE_GLOBAL_BUILTIN */

/*
 *  URI handling
 */

#if defined(DUK_USE_GLOBAL_BUILTIN)
DUK_INTERNAL duk_ret_t duk_bi_global_object_decode_uri(duk_hthread *thr) {
	return duk__transform_helper(thr, duk__transform_callback_decode_uri, (const void *) duk__decode_uri_reserved_table);
}

DUK_INTERNAL duk_ret_t duk_bi_global_object_decode_uri_component(duk_hthread *thr) {
	return duk__transform_helper(thr, duk__transform_callback_decode_uri, (const void *) duk__decode_uri_component_reserved_table);
}

DUK_INTERNAL duk_ret_t duk_bi_global_object_encode_uri(duk_hthread *thr) {
	return duk__transform_helper(thr, duk__transform_callback_encode_uri, (const void *) duk__encode_uriunescaped_table);
}

DUK_INTERNAL duk_ret_t duk_bi_global_object_encode_uri_component(duk_hthread *thr) {
	return duk__transform_helper(thr, duk__transform_callback_encode_uri, (const void *) duk__encode_uricomponent_unescaped_table);
}

#if defined(DUK_USE_SECTION_B)
DUK_INTERNAL duk_ret_t duk_bi_global_object_escape(duk_hthread *thr) {
	return duk__transform_helper(thr, duk__transform_callback_escape, (const void *) NULL);
}

DUK_INTERNAL duk_ret_t duk_bi_global_object_unescape(duk_hthread *thr) {
	return duk__transform_helper(thr, duk__transform_callback_unescape, (const void *) NULL);
}
#endif  /* DUK_USE_SECTION_B */
#endif  /* DUK_USE_GLOBAL_BUILTIN */

/* automatic undefs */
#undef DUK__CHECK_BITMASK
#undef DUK__MKBITS
#line 1 "duk_bi_json.c"
/*
 *  JSON built-ins.
 *
 *  See doc/json.rst.
 *
 *  Codepoints are handled as duk_uint_fast32_t to ensure that the full
 *  unsigned 32-bit range is supported.  This matters to e.g. JX.
 *
 *  Input parsing doesn't do an explicit end-of-input check at all.  This is
 *  safe: input string data is always NUL-terminated (0x00) and valid JSON
 *  inputs never contain plain NUL characters, so that as long as syntax checks
 *  are correct, we'll never read past the NUL.  This approach reduces code size
 *  and improves parsing performance, but it's critical that syntax checks are
 *  indeed correct!
 */

/* #include duk_internal.h -> already included */

#if defined(DUK_USE_JSON_SUPPORT)

/*
 *  Local defines and forward declarations.
 */

#define DUK__JSON_DECSTR_BUFSIZE 128
#define DUK__JSON_DECSTR_CHUNKSIZE 64
#define DUK__JSON_ENCSTR_CHUNKSIZE 64
#define DUK__JSON_STRINGIFY_BUFSIZE 128
#define DUK__JSON_MAX_ESC_LEN 10  /* '\Udeadbeef' */

DUK_LOCAL_DECL void duk__dec_syntax_error(duk_json_dec_ctx *js_ctx);
DUK_LOCAL_DECL void duk__dec_eat_white(duk_json_dec_ctx *js_ctx);
#if defined(DUK_USE_JX)
DUK_LOCAL_DECL duk_uint8_t duk__dec_peek(duk_json_dec_ctx *js_ctx);
#endif
DUK_LOCAL_DECL duk_uint8_t duk__dec_get(duk_json_dec_ctx *js_ctx);
DUK_LOCAL_DECL duk_uint8_t duk__dec_get_nonwhite(duk_json_dec_ctx *js_ctx);
DUK_LOCAL_DECL duk_uint_fast32_t duk__dec_decode_hex_escape(duk_json_dec_ctx *js_ctx, duk_small_uint_t n);
DUK_LOCAL_DECL void duk__dec_req_stridx(duk_json_dec_ctx *js_ctx, duk_small_uint_t stridx);
DUK_LOCAL_DECL void duk__dec_string(duk_json_dec_ctx *js_ctx);
#if defined(DUK_USE_JX)
DUK_LOCAL_DECL void duk__dec_plain_string(duk_json_dec_ctx *js_ctx);
DUK_LOCAL_DECL void duk__dec_pointer(duk_json_dec_ctx *js_ctx);
DUK_LOCAL_DECL void duk__dec_buffer(duk_json_dec_ctx *js_ctx);
#endif
DUK_LOCAL_DECL void duk__dec_number(duk_json_dec_ctx *js_ctx);
DUK_LOCAL_DECL void duk__dec_objarr_entry(duk_json_dec_ctx *js_ctx);
DUK_LOCAL_DECL void duk__dec_objarr_exit(duk_json_dec_ctx *js_ctx);
DUK_LOCAL_DECL void duk__dec_object(duk_json_dec_ctx *js_ctx);
DUK_LOCAL_DECL void duk__dec_array(duk_json_dec_ctx *js_ctx);
DUK_LOCAL_DECL void duk__dec_value(duk_json_dec_ctx *js_ctx);
DUK_LOCAL_DECL void duk__dec_reviver_walk(duk_json_dec_ctx *js_ctx);

DUK_LOCAL_DECL void duk__emit_1(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch);
DUK_LOCAL_DECL void duk__emit_2(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch1, duk_uint_fast8_t ch2);
DUK_LOCAL_DECL void duk__unemit_1(duk_json_enc_ctx *js_ctx);
DUK_LOCAL_DECL void duk__emit_hstring(duk_json_enc_ctx *js_ctx, duk_hstring *h);
#if defined(DUK_USE_FASTINT)
DUK_LOCAL_DECL void duk__emit_cstring(duk_json_enc_ctx *js_ctx, const char *p);
#endif
DUK_LOCAL_DECL void duk__emit_stridx(duk_json_enc_ctx *js_ctx, duk_small_uint_t stridx);
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);
DUK_LOCAL_DECL void duk__enc_key_autoquote(duk_json_enc_ctx *js_ctx, duk_hstring *k);
DUK_LOCAL_DECL void duk__enc_quote_string(duk_json_enc_ctx *js_ctx, duk_hstring *h_str);
DUK_LOCAL_DECL void duk__enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top);
DUK_LOCAL_DECL void duk__enc_objarr_exit(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top);
DUK_LOCAL_DECL void duk__enc_object(duk_json_enc_ctx *js_ctx);
DUK_LOCAL_DECL void duk__enc_array(duk_json_enc_ctx *js_ctx);
DUK_LOCAL_DECL duk_bool_t duk__enc_value(duk_json_enc_ctx *js_ctx, duk_idx_t idx_holder);
DUK_LOCAL_DECL duk_bool_t duk__enc_allow_into_proplist(duk_tval *tv);
DUK_LOCAL_DECL void duk__enc_double(duk_json_enc_ctx *js_ctx);
#if defined(DUK_USE_FASTINT)
DUK_LOCAL_DECL void duk__enc_fastint_tval(duk_json_enc_ctx *js_ctx, duk_tval *tv);
#endif
#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
DUK_LOCAL_DECL void duk__enc_buffer_jx_jc(duk_json_enc_ctx *js_ctx, duk_hbuffer *h);
DUK_LOCAL_DECL void duk__enc_pointer(duk_json_enc_ctx *js_ctx, void *ptr);
#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
DUK_LOCAL_DECL void duk__enc_bufobj(duk_json_enc_ctx *js_ctx, duk_hbufobj *h_bufobj);
#endif
#endif
#if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
DUK_LOCAL_DECL void duk__enc_buffer_json_fastpath(duk_json_enc_ctx *js_ctx, duk_hbuffer *h);
#endif
DUK_LOCAL_DECL void duk__enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_uint_t depth);

/*
 *  Helper tables
 */

#if defined(DUK_USE_JSON_QUOTESTRING_FASTPATH)
DUK_LOCAL const duk_uint8_t duk__json_quotestr_lookup[256] = {
	/* 0x00 ... 0x7f: as is
	 * 0x80: escape generically
	 * 0x81: slow path
	 * 0xa0 ... 0xff: backslash + one char
	 */

	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xe2, 0xf4, 0xee, 0x80, 0xe6, 0xf2, 0x80, 0x80,
	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
	0x20, 0x21, 0xa2, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
	0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
	0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0xdc, 0x5d, 0x5e, 0x5f,
	0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
	0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x81,
	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81
};
#else  /* DUK_USE_JSON_QUOTESTRING_FASTPATH */
DUK_LOCAL const duk_uint8_t duk__json_quotestr_esc[14] = {
	DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL,
	DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL,
	DUK_ASC_LC_B, DUK_ASC_LC_T, DUK_ASC_LC_N, DUK_ASC_NUL,
	DUK_ASC_LC_F, DUK_ASC_LC_R
};
#endif  /* DUK_USE_JSON_QUOTESTRING_FASTPATH */

#if defined(DUK_USE_JSON_DECSTRING_FASTPATH)
DUK_LOCAL const duk_uint8_t duk__json_decstr_lookup[256] = {
	/* 0x00: slow path
	 * other: as is
	 */
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x20, 0x21, 0x00, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
	0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
	0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x00, 0x5d, 0x5e, 0x5f,
	0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
	0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
	0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
	0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
	0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
	0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
	0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
	0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
	0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
#endif  /* DUK_USE_JSON_DECSTRING_FASTPATH */

#if defined(DUK_USE_JSON_EATWHITE_FASTPATH)
DUK_LOCAL const duk_uint8_t duk__json_eatwhite_lookup[256] = {
	/* 0x00: finish (non-white)
	 * 0x01: continue
	 */
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
#endif  /* DUK_USE_JSON_EATWHITE_FASTPATH */

#if defined(DUK_USE_JSON_DECNUMBER_FASTPATH)
DUK_LOCAL const duk_uint8_t duk__json_decnumber_lookup[256] = {
	/* 0x00: finish (not part of number)
	 * 0x01: continue
	 */
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00,
	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
#endif  /* DUK_USE_JSON_DECNUMBER_FASTPATH */

/*
 *  Parsing implementation.
 *
 *  JSON lexer is now separate from duk_lexer.c because there are numerous
 *  small differences making it difficult to share the lexer.
 *
 *  The parser here works with raw bytes directly; this works because all
 *  JSON delimiters are ASCII characters.  Invalid xUTF-8 encoded values
 *  inside strings will be passed on without normalization; this is not a
 *  compliance concern because compliant inputs will always be valid
 *  CESU-8 encodings.
 */

DUK_LOCAL void duk__dec_syntax_error(duk_json_dec_ctx *js_ctx) {
	/* Shared handler to minimize parser size.  Cause will be
	 * hidden, unfortunately, but we'll have an offset which
	 * is often quite enough.
	 */
	DUK_ERROR_FMT1(js_ctx->thr, DUK_ERR_SYNTAX_ERROR, DUK_STR_FMT_INVALID_JSON,
	               (long) (js_ctx->p - js_ctx->p_start));
	DUK_WO_NORETURN(return;);
}

DUK_LOCAL void duk__dec_eat_white(duk_json_dec_ctx *js_ctx) {
	const duk_uint8_t *p;
	duk_uint8_t t;

	p = js_ctx->p;
	for (;;) {
		DUK_ASSERT(p <= js_ctx->p_end);
		t = *p;

#if defined(DUK_USE_JSON_EATWHITE_FASTPATH)
		/* This fast path is pretty marginal in practice.
		 * XXX: candidate for removal.
		 */
		DUK_ASSERT(duk__json_eatwhite_lookup[0x00] == 0x00);  /* end-of-input breaks */
		if (duk__json_eatwhite_lookup[t] == 0) {
			break;
		}
#else  /* DUK_USE_JSON_EATWHITE_FASTPATH */
		if (!(t == 0x20 || t == 0x0a || t == 0x0d || t == 0x09)) {
			/* NUL also comes here.  Comparison order matters, 0x20
			 * is most common whitespace.
			 */
			break;
		}
#endif  /* DUK_USE_JSON_EATWHITE_FASTPATH */
		p++;
	}
	js_ctx->p = p;
}

#if defined(DUK_USE_JX)
DUK_LOCAL duk_uint8_t duk__dec_peek(duk_json_dec_ctx *js_ctx) {
	DUK_ASSERT(js_ctx->p <= js_ctx->p_end);
	return *js_ctx->p;
}
#endif

DUK_LOCAL duk_uint8_t duk__dec_get(duk_json_dec_ctx *js_ctx) {
	DUK_ASSERT(js_ctx->p <= js_ctx->p_end);
	return *js_ctx->p++;
}

DUK_LOCAL duk_uint8_t duk__dec_get_nonwhite(duk_json_dec_ctx *js_ctx) {
	duk__dec_eat_white(js_ctx);
	return duk__dec_get(js_ctx);
}

/* For JX, expressing the whole unsigned 32-bit range matters. */
DUK_LOCAL duk_uint_fast32_t duk__dec_decode_hex_escape(duk_json_dec_ctx *js_ctx, duk_small_uint_t n) {
	duk_small_uint_t i;
	duk_uint_fast32_t res = 0;
	duk_uint8_t x;
	duk_small_int_t t;

	for (i = 0; i < n; i++) {
		/* XXX: share helper from lexer; duk_lexer.c / hexval(). */

		x = duk__dec_get(js_ctx);
		DUK_DDD(DUK_DDDPRINT("decode_hex_escape: i=%ld, n=%ld, res=%ld, x=%ld",
		                     (long) i, (long) n, (long) res, (long) x));

		/* x == 0x00 (EOF) causes syntax_error */
		DUK_ASSERT(duk_hex_dectab[0] == -1);
		t = duk_hex_dectab[x & 0xff];
		if (DUK_LIKELY(t >= 0)) {
			res = (res * 16) + (duk_uint_fast32_t) t;
		} else {
			/* catches EOF and invalid digits */
			goto syntax_error;
		}
	}

	DUK_DDD(DUK_DDDPRINT("final hex decoded value: %ld", (long) res));
	return res;

 syntax_error:
	duk__dec_syntax_error(js_ctx);
	DUK_UNREACHABLE();
	return 0;
}

DUK_LOCAL void duk__dec_req_stridx(duk_json_dec_ctx *js_ctx, duk_small_uint_t stridx) {
	duk_hstring *h;
	const duk_uint8_t *p;
	duk_uint8_t x, y;

	/* First character has already been eaten and checked by the caller.
	 * We can scan until a NUL in stridx string because no built-in strings
	 * have internal NULs.
	 */

	DUK_ASSERT_STRIDX_VALID(stridx);
	h = DUK_HTHREAD_GET_STRING(js_ctx->thr, stridx);
	DUK_ASSERT(h != NULL);

	p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h) + 1;
	DUK_ASSERT(*(js_ctx->p - 1) == *(p - 1));  /* first character has been matched */

	for (;;) {
		x = *p;
		if (x == 0) {
			break;
		}
		y = duk__dec_get(js_ctx);
		if (x != y) {
			/* Catches EOF of JSON input. */
			goto syntax_error;
		}
		p++;
	}

	return;

 syntax_error:
	duk__dec_syntax_error(js_ctx);
	DUK_UNREACHABLE();
}

DUK_LOCAL duk_small_int_t duk__dec_string_escape(duk_json_dec_ctx *js_ctx, duk_uint8_t **ext_p) {
	duk_uint_fast32_t cp;

	/* EOF (-1) will be cast to an unsigned value first
	 * and then re-cast for the switch.  In any case, it
	 * will match the default case (syntax error).
	 */
	cp = (duk_uint_fast32_t) duk__dec_get(js_ctx);
	switch (cp) {
	case DUK_ASC_BACKSLASH: break;
	case DUK_ASC_DOUBLEQUOTE: break;
	case DUK_ASC_SLASH: break;
	case DUK_ASC_LC_T: cp = 0x09; break;
	case DUK_ASC_LC_N: cp = 0x0a; break;
	case DUK_ASC_LC_R: cp = 0x0d; break;
	case DUK_ASC_LC_F: cp = 0x0c; break;
	case DUK_ASC_LC_B: cp = 0x08; break;
	case DUK_ASC_LC_U: {
		cp = duk__dec_decode_hex_escape(js_ctx, 4);
		break;
	}
#if defined(DUK_USE_JX)
	case DUK_ASC_UC_U: {
		if (js_ctx->flag_ext_custom) {
			cp = duk__dec_decode_hex_escape(js_ctx, 8);
		} else {
			return 1;  /* syntax error */
		}
		break;
	}
	case DUK_ASC_LC_X: {
		if (js_ctx->flag_ext_custom) {
			cp = duk__dec_decode_hex_escape(js_ctx, 2);
		} else {
			return 1;  /* syntax error */
		}
		break;
	}
#endif  /* DUK_USE_JX */
	default:
		/* catches EOF (0x00) */
		return 1;  /* syntax error */
	}

	DUK_RAW_WRITEINC_XUTF8(*ext_p, cp);

	return 0;
}

DUK_LOCAL void duk__dec_string(duk_json_dec_ctx *js_ctx) {
	duk_hthread *thr = js_ctx->thr;
	duk_bufwriter_ctx bw_alloc;
	duk_bufwriter_ctx *bw;
	duk_uint8_t *q;

	/* '"' was eaten by caller */

	/* Note that we currently parse -bytes-, not codepoints.
	 * All non-ASCII extended UTF-8 will encode to bytes >= 0x80,
	 * so they'll simply pass through (valid UTF-8 or not).
	 */

	bw = &bw_alloc;
	DUK_BW_INIT_PUSHBUF(js_ctx->thr, bw, DUK__JSON_DECSTR_BUFSIZE);
	q = DUK_BW_GET_PTR(js_ctx->thr, bw);

#if defined(DUK_USE_JSON_DECSTRING_FASTPATH)
	for (;;) {
		duk_small_uint_t safe;
		duk_uint8_t b, x;
		const duk_uint8_t *p;

		/* Select a safe loop count where no output checks are
		 * needed assuming we won't encounter escapes.  Input
		 * bound checks are not necessary as a NUL (guaranteed)
		 * will cause a SyntaxError before we read out of bounds.
		 */

		safe = DUK__JSON_DECSTR_CHUNKSIZE;

		/* Ensure space for 1:1 output plus one escape. */
		q = DUK_BW_ENSURE_RAW(js_ctx->thr, bw, safe + DUK_UNICODE_MAX_XUTF8_LENGTH, q);

		p = js_ctx->p;  /* temp copy, write back for next loop */
		for (;;) {
			if (safe == 0) {
				js_ctx->p = p;
				break;
			}
			safe--;

			/* End of input (NUL) goes through slow path and causes SyntaxError. */
			DUK_ASSERT(duk__json_decstr_lookup[0] == 0x00);

			b = *p++;
			x = (duk_small_int_t) duk__json_decstr_lookup[b];
			if (DUK_LIKELY(x != 0)) {
				/* Fast path, decode as is. */
				*q++ = b;
			} else if (b == DUK_ASC_DOUBLEQUOTE) {
				js_ctx->p = p;
				goto found_quote;
			} else if (b == DUK_ASC_BACKSLASH) {
				/* We've ensured space for one escaped input; then
				 * bail out and recheck (this makes escape handling
				 * quite slow but it's uncommon).
				 */
				js_ctx->p = p;
				if (duk__dec_string_escape(js_ctx, &q) != 0) {
					goto syntax_error;
				}
				break;
			} else {
				js_ctx->p = p;
				goto syntax_error;
			}
		}
	}
 found_quote:
#else  /* DUK_USE_JSON_DECSTRING_FASTPATH */
	for (;;) {
		duk_uint8_t x;

		q = DUK_BW_ENSURE_RAW(js_ctx->thr, bw, DUK_UNICODE_MAX_XUTF8_LENGTH, q);

		x = duk__dec_get(js_ctx);

		if (x == DUK_ASC_DOUBLEQUOTE) {
			break;
		} else if (x == DUK_ASC_BACKSLASH) {
			if (duk__dec_string_escape(js_ctx, &q) != 0) {
				goto syntax_error;
			}
		} else if (x < 0x20) {
			/* catches EOF (NUL) */
			goto syntax_error;
		} else {
			*q++ = (duk_uint8_t) x;
		}
	}
#endif  /* DUK_USE_JSON_DECSTRING_FASTPATH */

	DUK_BW_SETPTR_AND_COMPACT(js_ctx->thr, bw, q);
	(void) duk_buffer_to_string(thr, -1);  /* Safe if input string is safe. */

	/* [ ... str ] */

	return;

 syntax_error:
	duk__dec_syntax_error(js_ctx);
	DUK_UNREACHABLE();
}

#if defined(DUK_USE_JX)
/* Decode a plain string consisting entirely of identifier characters.
 * Used to parse plain keys (e.g. "foo: 123").
 */
DUK_LOCAL void duk__dec_plain_string(duk_json_dec_ctx *js_ctx) {
	duk_hthread *thr = js_ctx->thr;
	const duk_uint8_t *p;
	duk_small_int_t x;

	/* Caller has already eaten the first char so backtrack one byte. */

	js_ctx->p--;  /* safe */
	p = js_ctx->p;

	/* Here again we parse bytes, and non-ASCII UTF-8 will cause end of
	 * parsing (which is correct except if there are non-shortest encodings).
	 * There is also no need to check explicitly for end of input buffer as
	 * the input is NUL padded and NUL will exit the parsing loop.
	 *
	 * Because no unescaping takes place, we can just scan to the end of the
	 * plain string and intern from the input buffer.
	 */

	for (;;) {
		x = *p;

		/* There is no need to check the first character specially here
		 * (i.e. reject digits): the caller only accepts valid initial
		 * characters and won't call us if the first character is a digit.
		 * This also ensures that the plain string won't be empty.
		 */

		if (!duk_unicode_is_identifier_part((duk_codepoint_t) x)) {
			break;
		}
		p++;
	}

	duk_push_lstring(thr, (const char *) js_ctx->p, (duk_size_t) (p - js_ctx->p));
	js_ctx->p = p;

	/* [ ... str ] */
}
#endif  /* DUK_USE_JX */

#if defined(DUK_USE_JX)
DUK_LOCAL void duk__dec_pointer(duk_json_dec_ctx *js_ctx) {
	duk_hthread *thr = js_ctx->thr;
	const duk_uint8_t *p;
	duk_small_int_t x;
	void *voidptr;

	/* Caller has already eaten the first character ('(') which we don't need. */

	p = js_ctx->p;

	for (;;) {
		x = *p;

		/* Assume that the native representation never contains a closing
		 * parenthesis.
		 */

		if (x == DUK_ASC_RPAREN) {
			break;
		} else if (x <= 0) {
			/* NUL term or -1 (EOF), NUL check would suffice */
			goto syntax_error;
		}
		p++;
	}

	/* There is no need to NUL delimit the sscanf() call: trailing garbage is
	 * ignored and there is always a NUL terminator which will force an error
	 * if no error is encountered before it.  It's possible that the scan
	 * would scan further than between [js_ctx->p,p[ though and we'd advance
	 * by less than the scanned value.
	 *
	 * Because pointers are platform specific, a failure to scan a pointer
	 * results in a null pointer which is a better placeholder than a missing
	 * value or an error.
	 */

	voidptr = NULL;
	(void) DUK_SSCANF((const char *) js_ctx->p, DUK_STR_FMT_PTR, &voidptr);
	duk_push_pointer(thr, voidptr);
	js_ctx->p = p + 1;  /* skip ')' */

	/* [ ... ptr ] */

	return;

 syntax_error:
	duk__dec_syntax_error(js_ctx);
	DUK_UNREACHABLE();
}
#endif  /* DUK_USE_JX */

#if defined(DUK_USE_JX)
DUK_LOCAL void duk__dec_buffer(duk_json_dec_ctx *js_ctx) {
	duk_hthread *thr = js_ctx->thr;
	const duk_uint8_t *p;
	duk_uint8_t *buf;
	duk_size_t src_len;
	duk_small_int_t x;

	/* Caller has already eaten the first character ('|') which we don't need. */

	p = js_ctx->p;

	/* XXX: Would be nice to share the fast path loop from duk_hex_decode()
	 * and avoid creating a temporary buffer.  However, there are some
	 * differences which prevent trivial sharing:
	 *
	 *   - Pipe char detection
	 *   - EOF detection
	 *   - Unknown length of input and output
	 *
	 * The best approach here would be a bufwriter and a reasonaly sized
	 * safe inner loop (e.g. 64 output bytes at a time).
	 */

	for (;;) {
		x = *p;

		/* This loop intentionally does not ensure characters are valid
		 * ([0-9a-fA-F]) because the hex decode call below will do that.
		 */
		if (x == DUK_ASC_PIPE) {
			break;
		} else if (x <= 0) {
			/* NUL term or -1 (EOF), NUL check would suffice */
			goto syntax_error;
		}
		p++;
	}

	/* XXX: this is not very nice; unnecessary copy is made. */
	src_len = (duk_size_t) (p - js_ctx->p);
	buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, src_len);
	DUK_ASSERT(buf != NULL);
	duk_memcpy((void *) buf, (const void *) js_ctx->p, src_len);
	duk_hex_decode(thr, -1);

	js_ctx->p = p + 1;  /* skip '|' */

	/* [ ... buf ] */

	return;

 syntax_error:
	duk__dec_syntax_error(js_ctx);
	DUK_UNREACHABLE();
}
#endif  /* DUK_USE_JX */

/* Parse a number, other than NaN or +/- Infinity */
DUK_LOCAL void duk__dec_number(duk_json_dec_ctx *js_ctx) {
	duk_hthread *thr = js_ctx->thr;
	const duk_uint8_t *p_start;
	const duk_uint8_t *p;
	duk_uint8_t x;
	duk_small_uint_t s2n_flags;

	DUK_DDD(DUK_DDDPRINT("parse_number"));

	p_start = js_ctx->p;

	/* First pass parse is very lenient (e.g. allows '1.2.3') and extracts a
	 * string for strict number parsing.
	 */

	p = js_ctx->p;
	for (;;) {
		x = *p;

		DUK_DDD(DUK_DDDPRINT("parse_number: p_start=%p, p=%p, p_end=%p, x=%ld",
		                     (const void *) p_start, (const void *) p,
		                     (const void *) js_ctx->p_end, (long) x));

#if defined(DUK_USE_JSON_DECNUMBER_FASTPATH)
		/* This fast path is pretty marginal in practice.
		 * XXX: candidate for removal.
		 */
		DUK_ASSERT(duk__json_decnumber_lookup[0x00] == 0x00);  /* end-of-input breaks */
		if (duk__json_decnumber_lookup[x] == 0) {
			break;
		}
#else  /* DUK_USE_JSON_DECNUMBER_FASTPATH */
		if (!((x >= DUK_ASC_0 && x <= DUK_ASC_9) ||
		      (x == DUK_ASC_PERIOD || x == DUK_ASC_LC_E ||
		       x == DUK_ASC_UC_E || x == DUK_ASC_MINUS || x == DUK_ASC_PLUS))) {
			/* Plus sign must be accepted for positive exponents
			 * (e.g. '1.5e+2').  This clause catches NULs.
			 */
			break;
		}
#endif  /* DUK_USE_JSON_DECNUMBER_FASTPATH */
		p++;  /* safe, because matched (NUL causes a break) */
	}
	js_ctx->p = p;

	DUK_ASSERT(js_ctx->p > p_start);
	duk_push_lstring(thr, (const char *) p_start, (duk_size_t) (p - p_start));

	s2n_flags = DUK_S2N_FLAG_ALLOW_EXP |
	            DUK_S2N_FLAG_ALLOW_MINUS |  /* but don't allow leading plus */
	            DUK_S2N_FLAG_ALLOW_FRAC;

	DUK_DDD(DUK_DDDPRINT("parse_number: string before parsing: %!T",
	                     (duk_tval *) duk_get_tval(thr, -1)));
	duk_numconv_parse(thr, 10 /*radix*/, s2n_flags);
	if (duk_is_nan(thr, -1)) {
		duk__dec_syntax_error(js_ctx);
	}
	DUK_ASSERT(duk_is_number(thr, -1));
	DUK_DDD(DUK_DDDPRINT("parse_number: final number: %!T",
	                     (duk_tval *) duk_get_tval(thr, -1)));

	/* [ ... num ] */
}

DUK_LOCAL void duk__dec_objarr_entry(duk_json_dec_ctx *js_ctx) {
	duk_hthread *thr = js_ctx->thr;
	duk_require_stack(thr, DUK_JSON_DEC_REQSTACK);

	/* c recursion check */

	DUK_ASSERT_DISABLE(js_ctx->recursion_depth >= 0);  /* unsigned */
	DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
	if (js_ctx->recursion_depth >= js_ctx->recursion_limit) {
		DUK_ERROR_RANGE(thr, DUK_STR_JSONDEC_RECLIMIT);
		DUK_WO_NORETURN(return;);
	}
	js_ctx->recursion_depth++;
}

DUK_LOCAL void duk__dec_objarr_exit(duk_json_dec_ctx *js_ctx) {
	/* c recursion check */

	DUK_ASSERT(js_ctx->recursion_depth > 0);
	DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
	js_ctx->recursion_depth--;
}

DUK_LOCAL void duk__dec_object(duk_json_dec_ctx *js_ctx) {
	duk_hthread *thr = js_ctx->thr;
	duk_int_t key_count;  /* XXX: a "first" flag would suffice */
	duk_uint8_t x;

	DUK_DDD(DUK_DDDPRINT("parse_object"));

	duk__dec_objarr_entry(js_ctx);

	duk_push_object(thr);

	/* Initial '{' has been checked and eaten by caller. */

	key_count = 0;
	for (;;) {
		x = duk__dec_get_nonwhite(js_ctx);

		DUK_DDD(DUK_DDDPRINT("parse_object: obj=%!T, x=%ld, key_count=%ld",
		                     (duk_tval *) duk_get_tval(thr, -1),
		                     (long) x, (long) key_count));

		/* handle comma and closing brace */

		if (x == DUK_ASC_COMMA && key_count > 0) {
			/* accept comma, expect new value */
			x = duk__dec_get_nonwhite(js_ctx);
		} else if (x == DUK_ASC_RCURLY) {
			/* eat closing brace */
			break;
		} else if (key_count == 0) {
			/* accept anything, expect first value (EOF will be
			 * caught by key parsing below.
			 */
			;
		} else {
			/* catches EOF (NUL) and initial comma */
			goto syntax_error;
		}

		/* parse key and value */

		if (x == DUK_ASC_DOUBLEQUOTE) {
			duk__dec_string(js_ctx);
#if defined(DUK_USE_JX)
		} else if (js_ctx->flag_ext_custom &&
		           duk_unicode_is_identifier_start((duk_codepoint_t) x)) {
			duk__dec_plain_string(js_ctx);
#endif
		} else {
			goto syntax_error;
		}

		/* [ ... obj key ] */

		x = duk__dec_get_nonwhite(js_ctx);
		if (x != DUK_ASC_COLON) {
			goto syntax_error;
		}

		duk__dec_value(js_ctx);

		/* [ ... obj key val ] */

		duk_xdef_prop_wec(thr, -3);

		/* [ ... obj ] */

		key_count++;
	}

	/* [ ... obj ] */

	DUK_DDD(DUK_DDDPRINT("parse_object: final object is %!T",
	                     (duk_tval *) duk_get_tval(thr, -1)));

	duk__dec_objarr_exit(js_ctx);
	return;

 syntax_error:
	duk__dec_syntax_error(js_ctx);
	DUK_UNREACHABLE();
}

DUK_LOCAL void duk__dec_array(duk_json_dec_ctx *js_ctx) {
	duk_hthread *thr = js_ctx->thr;
	duk_uarridx_t arr_idx;
	duk_uint8_t x;

	DUK_DDD(DUK_DDDPRINT("parse_array"));

	duk__dec_objarr_entry(js_ctx);

	duk_push_array(thr);

	/* Initial '[' has been checked and eaten by caller. */

	arr_idx = 0;
	for (;;) {
		x = duk__dec_get_nonwhite(js_ctx);

		DUK_DDD(DUK_DDDPRINT("parse_array: arr=%!T, x=%ld, arr_idx=%ld",
		                     (duk_tval *) duk_get_tval(thr, -1),
		                     (long) x, (long) arr_idx));

		/* handle comma and closing bracket */

		if ((x == DUK_ASC_COMMA) && (arr_idx != 0)) {
			/* accept comma, expect new value */
			;
		} else if (x == DUK_ASC_RBRACKET) {
			/* eat closing bracket */
			break;
		} else if (arr_idx == 0) {
			/* accept anything, expect first value (EOF will be
			 * caught by duk__dec_value() below.
			 */
			js_ctx->p--;  /* backtrack (safe) */
		} else {
			/* catches EOF (NUL) and initial comma */
			goto syntax_error;
		}

		/* parse value */

		duk__dec_value(js_ctx);

		/* [ ... arr val ] */

		duk_xdef_prop_index_wec(thr, -2, arr_idx);
		arr_idx++;
	}

	/* Must set 'length' explicitly when using duk_xdef_prop_xxx() to
	 * set the values.
	 */

	duk_set_length(thr, -1, arr_idx);

	/* [ ... arr ] */

	DUK_DDD(DUK_DDDPRINT("parse_array: final array is %!T",
	                     (duk_tval *) duk_get_tval(thr, -1)));

	duk__dec_objarr_exit(js_ctx);
	return;

 syntax_error:
	duk__dec_syntax_error(js_ctx);
	DUK_UNREACHABLE();
}

DUK_LOCAL void duk__dec_value(duk_json_dec_ctx *js_ctx) {
	duk_hthread *thr = js_ctx->thr;
	duk_uint8_t x;

	x = duk__dec_get_nonwhite(js_ctx);

	DUK_DDD(DUK_DDDPRINT("parse_value: initial x=%ld", (long) x));

	/* Note: duk__dec_req_stridx() backtracks one char */

	if (x == DUK_ASC_DOUBLEQUOTE) {
		duk__dec_string(js_ctx);
	} else if ((x >= DUK_ASC_0 && x <= DUK_ASC_9) || (x == DUK_ASC_MINUS)) {
#if defined(DUK_USE_JX)
		if (js_ctx->flag_ext_custom && x == DUK_ASC_MINUS && duk__dec_peek(js_ctx) == DUK_ASC_UC_I) {
			duk__dec_req_stridx(js_ctx, DUK_STRIDX_MINUS_INFINITY);  /* "-Infinity", '-' has been eaten */
			duk_push_number(thr, -DUK_DOUBLE_INFINITY);
		} else {
#else
		{  /* unconditional block */
#endif
			/* We already ate 'x', so backup one byte. */
			js_ctx->p--;  /* safe */
			duk__dec_number(js_ctx);
		}
	} else if (x == DUK_ASC_LC_T) {
		duk__dec_req_stridx(js_ctx, DUK_STRIDX_TRUE);
		duk_push_true(thr);
	} else if (x == DUK_ASC_LC_F) {
		duk__dec_req_stridx(js_ctx, DUK_STRIDX_FALSE);
		duk_push_false(thr);
	} else if (x == DUK_ASC_LC_N) {
		duk__dec_req_stridx(js_ctx, DUK_STRIDX_LC_NULL);
		duk_push_null(thr);
#if defined(DUK_USE_JX)
	} else if (js_ctx->flag_ext_custom && x == DUK_ASC_LC_U) {
		duk__dec_req_stridx(js_ctx, DUK_STRIDX_LC_UNDEFINED);
		duk_push_undefined(thr);
	} else if (js_ctx->flag_ext_custom && x == DUK_ASC_UC_N) {
		duk__dec_req_stridx(js_ctx, DUK_STRIDX_NAN);
		duk_push_nan(thr);
	} else if (js_ctx->flag_ext_custom && x == DUK_ASC_UC_I) {
		duk__dec_req_stridx(js_ctx, DUK_STRIDX_INFINITY);
		duk_push_number(thr, DUK_DOUBLE_INFINITY);
	} else if (js_ctx->flag_ext_custom && x == DUK_ASC_LPAREN) {
		duk__dec_pointer(js_ctx);
	} else if (js_ctx->flag_ext_custom && x == DUK_ASC_PIPE) {
		duk__dec_buffer(js_ctx);
#endif
	} else if (x == DUK_ASC_LCURLY) {
		duk__dec_object(js_ctx);
	} else if (x == DUK_ASC_LBRACKET) {
		duk__dec_array(js_ctx);
	} else {
		/* catches EOF (NUL) */
		goto syntax_error;
	}

	duk__dec_eat_white(js_ctx);

	/* [ ... val ] */
	return;

 syntax_error:
	duk__dec_syntax_error(js_ctx);
	DUK_UNREACHABLE();
}

/* Recursive value reviver, implements the Walk() algorithm.  No C recursion
 * check is done here because the initial parsing step will already ensure
 * there is a reasonable limit on C recursion depth and hence object depth.
 */
DUK_LOCAL void duk__dec_reviver_walk(duk_json_dec_ctx *js_ctx) {
	duk_hthread *thr = js_ctx->thr;
	duk_hobject *h;
	duk_uarridx_t i, arr_len;

	DUK_DDD(DUK_DDDPRINT("walk: top=%ld, holder=%!T, name=%!T",
	                     (long) duk_get_top(thr),
	                     (duk_tval *) duk_get_tval(thr, -2),
	                     (duk_tval *) duk_get_tval(thr, -1)));

	duk_dup_top(thr);
	duk_get_prop(thr, -3);  /* -> [ ... holder name val ] */

	h = duk_get_hobject(thr, -1);
	if (h != NULL) {
		if (duk_js_isarray_hobject(h)) {
			arr_len = (duk_uarridx_t) duk_get_length(thr, -1);
			for (i = 0; i < arr_len; i++) {
				/* [ ... holder name val ] */

				DUK_DDD(DUK_DDDPRINT("walk: array, top=%ld, i=%ld, arr_len=%ld, holder=%!T, name=%!T, val=%!T",
				                     (long) duk_get_top(thr), (long) i, (long) arr_len,
				                     (duk_tval *) duk_get_tval(thr, -3), (duk_tval *) duk_get_tval(thr, -2),
				                     (duk_tval *) duk_get_tval(thr, -1)));

				duk_dup_top(thr);
				(void) duk_push_uint_to_hstring(thr, (duk_uint_t) i);  /* -> [ ... holder name val val ToString(i) ] */
				duk__dec_reviver_walk(js_ctx);  /* -> [ ... holder name val new_elem ] */

				if (duk_is_undefined(thr, -1)) {
					duk_pop(thr);
					duk_del_prop_index(thr, -1, i);
				} else {
					/* XXX: duk_xdef_prop_index_wec() would be more appropriate
					 * here but it currently makes some assumptions that might
					 * not hold (e.g. that previous property is not an accessor).
					 */
					duk_put_prop_index(thr, -2, i);
				}
			}
		} else {
			/* [ ... holder name val ] */
			duk_enum(thr, -1, DUK_ENUM_OWN_PROPERTIES_ONLY /*flags*/);
			while (duk_next(thr, -1 /*enum_index*/, 0 /*get_value*/)) {
				DUK_DDD(DUK_DDDPRINT("walk: object, top=%ld, holder=%!T, name=%!T, val=%!T, enum=%!iT, obj_key=%!T",
				                     (long) duk_get_top(thr), (duk_tval *) duk_get_tval(thr, -5),
				                     (duk_tval *) duk_get_tval(thr, -4), (duk_tval *) duk_get_tval(thr, -3),
				                     (duk_tval *) duk_get_tval(thr, -2), (duk_tval *) duk_get_tval(thr, -1)));

				/* [ ... holder name val enum obj_key ] */
				duk_dup_m3(thr);
				duk_dup_m2(thr);

				/* [ ... holder name val enum obj_key val obj_key ] */
				duk__dec_reviver_walk(js_ctx);

				/* [ ... holder name val enum obj_key new_elem ] */
				if (duk_is_undefined(thr, -1)) {
					duk_pop(thr);
					duk_del_prop(thr, -3);
				} else {
					/* XXX: duk_xdef_prop_index_wec() would be more appropriate
					 * here but it currently makes some assumptions that might
					 * not hold (e.g. that previous property is not an accessor).
					 *
					 * Using duk_put_prop() works incorrectly with '__proto__'
					 * if the own property with that name has been deleted.  This
					 * does not happen normally, but a clever reviver can trigger
					 * that, see complex reviver case in: test-bug-json-parse-__proto__.js.
					 */
					duk_put_prop(thr, -4);
				}
			}
			duk_pop(thr);  /* pop enum */
		}
	}

	/* [ ... holder name val ] */

	duk_dup(thr, js_ctx->idx_reviver);
	duk_insert(thr, -4);  /* -> [ ... reviver holder name val ] */
	duk_call_method(thr, 2);  /* -> [ ... res ] */

	DUK_DDD(DUK_DDDPRINT("walk: top=%ld, result=%!T",
	                     (long) duk_get_top(thr), (duk_tval *) duk_get_tval(thr, -1)));
}

/*
 *  Stringify implementation.
 */

#define DUK__EMIT_1(js_ctx,ch)          duk__emit_1((js_ctx), (duk_uint_fast8_t) (ch))
#define DUK__EMIT_2(js_ctx,ch1,ch2)     duk__emit_2((js_ctx), (duk_uint_fast8_t) (ch1), (duk_uint_fast8_t) (ch2))
#define DUK__EMIT_HSTR(js_ctx,h)        duk__emit_hstring((js_ctx), (h))
#if defined(DUK_USE_FASTINT) || defined(DUK_USE_JX) || defined(DUK_USE_JC)
#define DUK__EMIT_CSTR(js_ctx,p)        duk__emit_cstring((js_ctx), (p))
#endif
#define DUK__EMIT_STRIDX(js_ctx,i)      duk__emit_stridx((js_ctx), (i))
#define DUK__UNEMIT_1(js_ctx)           duk__unemit_1((js_ctx))

DUK_LOCAL void duk__emit_1(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch) {
	DUK_BW_WRITE_ENSURE_U8(js_ctx->thr, &js_ctx->bw, ch);
}

DUK_LOCAL void duk__emit_2(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch1, duk_uint_fast8_t ch2) {
	DUK_BW_WRITE_ENSURE_U8_2(js_ctx->thr, &js_ctx->bw, ch1, ch2);
}

DUK_LOCAL void duk__emit_hstring(duk_json_enc_ctx *js_ctx, duk_hstring *h) {
	DUK_BW_WRITE_ENSURE_HSTRING(js_ctx->thr, &js_ctx->bw, h);
}

#if defined(DUK_USE_FASTINT) || defined(DUK_USE_JX) || defined(DUK_USE_JC)
DUK_LOCAL void duk__emit_cstring(duk_json_enc_ctx *js_ctx, const char *str) {
	DUK_BW_WRITE_ENSURE_CSTRING(js_ctx->thr, &js_ctx->bw, str);
}
#endif

DUK_LOCAL void duk__emit_stridx(duk_json_enc_ctx *js_ctx, duk_small_uint_t stridx) {
	duk_hstring *h;

	DUK_ASSERT_STRIDX_VALID(stridx);
	h = DUK_HTHREAD_GET_STRING(js_ctx->thr, stridx);
	DUK_ASSERT(h != NULL);

	DUK_BW_WRITE_ENSURE_HSTRING(js_ctx->thr, &js_ctx->bw, h);
}

DUK_LOCAL void duk__unemit_1(duk_json_enc_ctx *js_ctx) {
	DUK_ASSERT(DUK_BW_GET_SIZE(js_ctx->thr, &js_ctx->bw) >= 1);
	DUK_BW_ADD_PTR(js_ctx->thr, &js_ctx->bw, -1);
}

#define DUK__MKESC(nybbles,esc1,esc2)  \
	(((duk_uint_fast32_t) (nybbles)) << 16) | \
	(((duk_uint_fast32_t) (esc1)) << 8) | \
	((duk_uint_fast32_t) (esc2))

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) {
	duk_uint_fast32_t tmp;
	duk_small_uint_t dig;

	DUK_UNREF(js_ctx);

	/* Caller ensures space for at least DUK__JSON_MAX_ESC_LEN. */

	/* Select appropriate escape format automatically, and set 'tmp' to a
	 * value encoding both the escape format character and the nybble count:
	 *
	 *   (nybble_count << 16) | (escape_char1) | (escape_char2)
	 */

#if defined(DUK_USE_JX)
	if (DUK_LIKELY(cp < 0x100UL)) {
		if (DUK_UNLIKELY(js_ctx->flag_ext_custom != 0U)) {
			tmp = DUK__MKESC(2, DUK_ASC_BACKSLASH, DUK_ASC_LC_X);
		} else {
			tmp = DUK__MKESC(4, DUK_ASC_BACKSLASH, DUK_ASC_LC_U);
		}
	} else
#endif
	if (DUK_LIKELY(cp < 0x10000UL)) {
		tmp = DUK__MKESC(4, DUK_ASC_BACKSLASH, DUK_ASC_LC_U);
	} else {
#if defined(DUK_USE_JX)
		if (DUK_LIKELY(js_ctx->flag_ext_custom != 0U)) {
			tmp = DUK__MKESC(8, DUK_ASC_BACKSLASH, DUK_ASC_UC_U);
		} else
#endif
		{
			/* In compatible mode and standard JSON mode, output
			 * something useful for non-BMP characters.  This won't
			 * roundtrip but will still be more or less readable and
			 * more useful than an error.
			 */
			tmp = DUK__MKESC(8, DUK_ASC_UC_U, DUK_ASC_PLUS);
		}
	}

	*q++ = (duk_uint8_t) ((tmp >> 8) & 0xff);
	*q++ = (duk_uint8_t) (tmp & 0xff);

	tmp = tmp >> 16;
	while (tmp > 0) {
		tmp--;
		dig = (duk_small_uint_t) ((cp >> (4 * tmp)) & 0x0f);
		*q++ = duk_lc_digits[dig];
	}

	return q;
}

DUK_LOCAL void duk__enc_key_autoquote(duk_json_enc_ctx *js_ctx, duk_hstring *k) {
	const duk_int8_t *p, *p_start, *p_end;  /* Note: intentionally signed. */
	duk_size_t k_len;
	duk_codepoint_t cp;

	DUK_ASSERT(k != NULL);

	/* Accept ASCII strings which conform to identifier requirements
	 * as being emitted without key quotes.  Since we only accept ASCII
	 * there's no need for actual decoding: 'p' is intentionally signed
	 * so that bytes >= 0x80 extend to negative values and are rejected
	 * as invalid identifier codepoints.
	 */

	if (js_ctx->flag_avoid_key_quotes) {
		k_len = DUK_HSTRING_GET_BYTELEN(k);
		p_start = (const duk_int8_t *) DUK_HSTRING_GET_DATA(k);
		p_end = p_start + k_len;
		p = p_start;

		if (p == p_end) {
			/* Zero length string is not accepted without quotes */
			goto quote_normally;
		}
		cp = (duk_codepoint_t) (*p++);
		if (DUK_UNLIKELY(!duk_unicode_is_identifier_start(cp))) {
			goto quote_normally;
		}
		while (p < p_end) {
			cp = (duk_codepoint_t) (*p++);
			if (DUK_UNLIKELY(!duk_unicode_is_identifier_part(cp))) {
				goto quote_normally;
			}
		}

		/* This seems faster than emitting bytes one at a time and
		 * then potentially rewinding.
		 */
		DUK__EMIT_HSTR(js_ctx, k);
		return;
	}

 quote_normally:
	duk__enc_quote_string(js_ctx, k);
}

/* The Quote(value) operation: quote a string.
 *
 * Stack policy: [ ] -> [ ].
 */

DUK_LOCAL void duk__enc_quote_string(duk_json_enc_ctx *js_ctx, duk_hstring *h_str) {
	duk_hthread *thr = js_ctx->thr;
	const duk_uint8_t *p, *p_start, *p_end, *p_now, *p_tmp;
	duk_uint8_t *q;
	duk_ucodepoint_t cp;  /* typed for duk_unicode_decode_xutf8() */

	DUK_DDD(DUK_DDDPRINT("duk__enc_quote_string: h_str=%!O", (duk_heaphdr *) h_str));

	DUK_ASSERT(h_str != NULL);
	p_start = DUK_HSTRING_GET_DATA(h_str);
	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_str);
	p = p_start;

	DUK__EMIT_1(js_ctx, DUK_ASC_DOUBLEQUOTE);

	/* Encode string in small chunks, estimating the maximum expansion so that
	 * there's no need to ensure space while processing the chunk.
	 */

	while (p < p_end) {
		duk_size_t left, now, space;

		left = (duk_size_t) (p_end - p);
		now = (left > DUK__JSON_ENCSTR_CHUNKSIZE ?
		       DUK__JSON_ENCSTR_CHUNKSIZE : left);

		/* Maximum expansion per input byte is 6:
		 *   - invalid UTF-8 byte causes "\uXXXX" to be emitted (6/1 = 6).
		 *   - 2-byte UTF-8 encodes as "\uXXXX" (6/2 = 3).
		 *   - 4-byte UTF-8 encodes as "\Uxxxxxxxx" (10/4 = 2.5).
		 */
		space = now * 6;
		q = DUK_BW_ENSURE_GETPTR(thr, &js_ctx->bw, space);

		p_now = p + now;

		while (p < p_now) {
#if defined(DUK_USE_JSON_QUOTESTRING_FASTPATH)
			duk_uint8_t b;

			b = duk__json_quotestr_lookup[*p++];
			if (DUK_LIKELY(b < 0x80)) {
				/* Most input bytes go through here. */
				*q++ = b;
			} else if (b >= 0xa0) {
				*q++ = DUK_ASC_BACKSLASH;
				*q++ = (duk_uint8_t) (b - 0x80);
			} else if (b == 0x80) {
				cp = (duk_ucodepoint_t) (*(p - 1));
				q = duk__emit_esc_auto_fast(js_ctx, cp, q);
			} else if (b == 0x7f && js_ctx->flag_ascii_only) {
				/* 0x7F is special */
				DUK_ASSERT(b == 0x81);
				cp = (duk_ucodepoint_t) 0x7f;
				q = duk__emit_esc_auto_fast(js_ctx, cp, q);
			} else {
				DUK_ASSERT(b == 0x81);
				p--;

				/* slow path is shared */
#else  /* DUK_USE_JSON_QUOTESTRING_FASTPATH */
			cp = *p;

			if (DUK_LIKELY(cp <= 0x7f)) {
				/* ascii fast path: avoid decoding utf-8 */
				p++;
				if (cp == 0x22 || cp == 0x5c) {
					/* double quote or backslash */
					*q++ = DUK_ASC_BACKSLASH;
					*q++ = (duk_uint8_t) cp;
				} else if (cp < 0x20) {
					duk_uint_fast8_t esc_char;

					/* This approach is a bit shorter than a straight
					 * if-else-ladder and also a bit faster.
					 */
					if (cp < (sizeof(duk__json_quotestr_esc) / sizeof(duk_uint8_t)) &&
					    (esc_char = duk__json_quotestr_esc[cp]) != 0) {
						*q++ = DUK_ASC_BACKSLASH;
						*q++ = (duk_uint8_t) esc_char;
					} else {
						q = duk__emit_esc_auto_fast(js_ctx, cp, q);
					}
				} else if (cp == 0x7f && js_ctx->flag_ascii_only) {
					q = duk__emit_esc_auto_fast(js_ctx, cp, q);
				} else {
					/* any other printable -> as is */
					*q++ = (duk_uint8_t) cp;
				}
			} else {
				/* slow path is shared */
#endif  /* DUK_USE_JSON_QUOTESTRING_FASTPATH */

				/* slow path decode */

				/* If XUTF-8 decoding fails, treat the offending byte as a codepoint directly
				 * and go forward one byte.  This is of course very lossy, but allows some kind
				 * of output to be produced even for internal strings which don't conform to
				 * XUTF-8.  All standard ECMAScript strings are always CESU-8, so this behavior
				 * does not violate the ECMAScript specification.  The behavior is applied to
				 * all modes, including ECMAScript standard JSON.  Because the current XUTF-8
				 * decoding is not very strict, this behavior only really affects initial bytes
				 * and truncated codepoints.
				 *
				 * Another alternative would be to scan forwards to start of next codepoint
				 * (or end of input) and emit just one replacement codepoint.
				 */

				p_tmp = p;
				if (!duk_unicode_decode_xutf8(thr, &p, p_start, p_end, &cp)) {
					/* Decode failed. */
					cp = *p_tmp;
					p = p_tmp + 1;
				}

#if defined(DUK_USE_NONSTD_JSON_ESC_U2028_U2029)
				if (js_ctx->flag_ascii_only || cp == 0x2028 || cp == 0x2029) {
#else
				if (js_ctx->flag_ascii_only) {
#endif
					q = duk__emit_esc_auto_fast(js_ctx, cp, q);
				} else {
					/* as is */
					DUK_RAW_WRITEINC_XUTF8(q, cp);
				}
			}
		}

		DUK_BW_SET_PTR(thr, &js_ctx->bw, q);
	}

	DUK__EMIT_1(js_ctx, DUK_ASC_DOUBLEQUOTE);
}

/* Encode a double (checked by caller) from stack top.  Stack top may be
 * replaced by serialized string but is not popped (caller does that).
 */
DUK_LOCAL void duk__enc_double(duk_json_enc_ctx *js_ctx) {
	duk_hthread *thr;
	duk_tval *tv;
	duk_double_t d;
	duk_small_int_t c;
	duk_small_int_t s;
	duk_small_uint_t stridx;
	duk_small_uint_t n2s_flags;
	duk_hstring *h_str;

	DUK_ASSERT(js_ctx != NULL);
	thr = js_ctx->thr;
	DUK_ASSERT(thr != NULL);

	/* Caller must ensure 'tv' is indeed a double and not a fastint! */
	tv = DUK_GET_TVAL_NEGIDX(thr, -1);
	DUK_ASSERT(DUK_TVAL_IS_DOUBLE(tv));
	d = DUK_TVAL_GET_DOUBLE(tv);

	c = (duk_small_int_t) DUK_FPCLASSIFY(d);
	s = (duk_small_int_t) DUK_SIGNBIT(d);
	DUK_UNREF(s);

	if (DUK_LIKELY(!(c == DUK_FP_INFINITE || c == DUK_FP_NAN))) {
		DUK_ASSERT(DUK_ISFINITE(d));

#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
		/* Negative zero needs special handling in JX/JC because
		 * it would otherwise serialize to '0', not '-0'.
		 */
		if (DUK_UNLIKELY(c == DUK_FP_ZERO && s != 0 &&
		                 (js_ctx->flag_ext_custom_or_compatible))) {
			duk_push_hstring_stridx(thr, DUK_STRIDX_MINUS_ZERO);  /* '-0' */
		} else
#endif  /* DUK_USE_JX || DUK_USE_JC */
		{
			n2s_flags = 0;
			/* [ ... number ] -> [ ... string ] */
			duk_numconv_stringify(thr, 10 /*radix*/, 0 /*digits*/, n2s_flags);
		}
		h_str = duk_known_hstring(thr, -1);
		DUK__EMIT_HSTR(js_ctx, h_str);
		return;
	}

#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
	if (!(js_ctx->flags & (DUK_JSON_FLAG_EXT_CUSTOM |
	                       DUK_JSON_FLAG_EXT_COMPATIBLE))) {
		stridx = DUK_STRIDX_LC_NULL;
	} else if (c == DUK_FP_NAN) {
		stridx = js_ctx->stridx_custom_nan;
	} else if (s == 0) {
		stridx = js_ctx->stridx_custom_posinf;
	} else {
		stridx = js_ctx->stridx_custom_neginf;
	}
#else
	stridx = DUK_STRIDX_LC_NULL;
#endif
	DUK__EMIT_STRIDX(js_ctx, stridx);
}

#if defined(DUK_USE_FASTINT)
/* Encode a fastint from duk_tval ptr, no value stack effects. */
DUK_LOCAL void duk__enc_fastint_tval(duk_json_enc_ctx *js_ctx, duk_tval *tv) {
	duk_int64_t v;

	/* Fastint range is signed 48-bit so longest value is -2^47 = -140737488355328
	 * (16 chars long), longest signed 64-bit value is -2^63 = -9223372036854775808
	 * (20 chars long).  Alloc space for 64-bit range to be safe.
	 */
	duk_uint8_t buf[20 + 1];

	/* Caller must ensure 'tv' is indeed a fastint! */
	DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv));
	v = DUK_TVAL_GET_FASTINT(tv);

	/* XXX: There are no format strings in duk_config.h yet, could add
	 * one for formatting duk_int64_t.  For now, assumes "%lld" and that
	 * "long long" type exists.  Could also rely on C99 directly but that
	 * won't work for older MSVC.
	 */
	DUK_SPRINTF((char *) buf, "%lld", (long long) v);
	DUK__EMIT_CSTR(js_ctx, (const char *) buf);
}
#endif

#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
#if defined(DUK_USE_HEX_FASTPATH)
DUK_LOCAL duk_uint8_t *duk__enc_buffer_data_hex(const duk_uint8_t *src, duk_size_t src_len, duk_uint8_t *dst) {
	duk_uint8_t *q;
	duk_uint16_t *q16;
	duk_small_uint_t x;
	duk_size_t i, len_safe;
#if !defined(DUK_USE_UNALIGNED_ACCESSES_POSSIBLE)
	duk_bool_t shift_dst;
#endif

	/* Unlike in duk_hex_encode() 'dst' is not necessarily aligned by 2.
	 * For platforms where unaligned accesses are not allowed, shift 'dst'
	 * ahead by 1 byte to get alignment and then duk_memmove() the result
	 * in place.  The faster encoding loop makes up the difference.
	 * There's always space for one extra byte because a terminator always
	 * follows the hex data and that's been accounted for by the caller.
	 */

#if defined(DUK_USE_UNALIGNED_ACCESSES_POSSIBLE)
	q16 = (duk_uint16_t *) (void *) dst;
#else
	shift_dst = (duk_bool_t) (((duk_size_t) dst) & 0x01U);
	if (shift_dst) {
		DUK_DD(DUK_DDPRINT("unaligned accesses not possible, dst not aligned -> step to dst + 1"));
		q16 = (duk_uint16_t *) (void *) (dst + 1);
	} else {
		DUK_DD(DUK_DDPRINT("unaligned accesses not possible, dst is aligned"));
		q16 = (duk_uint16_t *) (void *) dst;
	}
	DUK_ASSERT((((duk_size_t) q16) & 0x01U) == 0);
#endif

	len_safe = src_len & ~0x03U;
	for (i = 0; i < len_safe; i += 4) {
		q16[0] = duk_hex_enctab[src[i]];
		q16[1] = duk_hex_enctab[src[i + 1]];
		q16[2] = duk_hex_enctab[src[i + 2]];
		q16[3] = duk_hex_enctab[src[i + 3]];
		q16 += 4;
	}
	q = (duk_uint8_t *) q16;

#if !defined(DUK_USE_UNALIGNED_ACCESSES_POSSIBLE)
	if (shift_dst) {
		q--;
		duk_memmove((void *) dst, (const void *) (dst + 1), 2 * len_safe);
		DUK_ASSERT(dst + 2 * len_safe == q);
	}
#endif

	for (; i < src_len; i++) {
		x = src[i];
		*q++ = duk_lc_digits[x >> 4];
		*q++ = duk_lc_digits[x & 0x0f];
	}

	return q;
}
#else  /* DUK_USE_HEX_FASTPATH */
DUK_LOCAL duk_uint8_t *duk__enc_buffer_data_hex(const duk_uint8_t *src, duk_size_t src_len, duk_uint8_t *dst) {
	const duk_uint8_t *p;
	const duk_uint8_t *p_end;
	duk_uint8_t *q;
	duk_small_uint_t x;

	p = src;
	p_end = src + src_len;
	q = dst;
	while (p != p_end) {
		x = *p++;
		*q++ = duk_lc_digits[x >> 4];
		*q++ = duk_lc_digits[x & 0x0f];
	}

	return q;
}
#endif  /* DUK_USE_HEX_FASTPATH */

DUK_LOCAL void duk__enc_buffer_data(duk_json_enc_ctx *js_ctx, duk_uint8_t *buf_data, duk_size_t buf_len) {
	duk_hthread *thr;
	duk_uint8_t *q;
	duk_size_t space;

	thr = js_ctx->thr;

	DUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible);  /* caller checks */
	DUK_ASSERT(js_ctx->flag_ext_custom_or_compatible);

	/* Buffer values are encoded in (lowercase) hex to make the
	 * binary data readable.  Base64 or similar would be more
	 * compact but less readable, and the point of JX/JC
	 * variants is to be as useful to a programmer as possible.
	 */

	/* The #if defined() clutter here needs to handle the three
	 * cases: (1) JX+JC, (2) JX only, (3) JC only.
	 */

	/* Note: space must cater for both JX and JC. */
	space = 9 + buf_len * 2 + 2;
	DUK_ASSERT(DUK_HBUFFER_MAX_BYTELEN <= 0x7ffffffeUL);
	DUK_ASSERT((space - 2) / 2 >= buf_len);  /* overflow not possible, buffer limits */
	q = DUK_BW_ENSURE_GETPTR(thr, &js_ctx->bw, space);

#if defined(DUK_USE_JX) && defined(DUK_USE_JC)
	if (js_ctx->flag_ext_custom)
#endif
#if defined(DUK_USE_JX)
	{
		*q++ = DUK_ASC_PIPE;
		q = duk__enc_buffer_data_hex(buf_data, buf_len, q);
		*q++ = DUK_ASC_PIPE;

	}
#endif
#if defined(DUK_USE_JX) && defined(DUK_USE_JC)
	else
#endif
#if defined(DUK_USE_JC)
	{
		DUK_ASSERT(js_ctx->flag_ext_compatible);
		duk_memcpy((void *) q, (const void *) "{\"_buf\":\"", 9);  /* len: 9 */
		q += 9;
		q = duk__enc_buffer_data_hex(buf_data, buf_len, q);
		*q++ = DUK_ASC_DOUBLEQUOTE;
		*q++ = DUK_ASC_RCURLY;
	}
#endif

	DUK_BW_SET_PTR(thr, &js_ctx->bw, q);
}

DUK_LOCAL void duk__enc_buffer_jx_jc(duk_json_enc_ctx *js_ctx, duk_hbuffer *h) {
	duk__enc_buffer_data(js_ctx,
	                     (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(js_ctx->thr->heap, h),
	                     (duk_size_t) DUK_HBUFFER_GET_SIZE(h));
}
#endif  /* DUK_USE_JX || DUK_USE_JC */

#if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
DUK_LOCAL void duk__enc_buffer_json_fastpath(duk_json_enc_ctx *js_ctx, duk_hbuffer *h) {
	duk_size_t i, n;
	const duk_uint8_t *buf;
	duk_uint8_t *q;

	n = DUK_HBUFFER_GET_SIZE(h);
	if (n == 0) {
		DUK__EMIT_2(js_ctx, DUK_ASC_LCURLY, DUK_ASC_RCURLY);
		return;
	}

	DUK__EMIT_1(js_ctx, DUK_ASC_LCURLY);

	/* Maximum encoded length with 32-bit index: 1 + 10 + 2 + 3 + 1 + 1 = 18,
	 * with 64-bit index: 1 + 20 + 2 + 3 + 1 + 1 = 28.  32 has some slack.
	 *
	 * Note that because the output buffer is reallocated from time to time,
	 * side effects (such as finalizers) affecting the buffer 'h' must be
	 * disabled.  This is the case in the JSON.stringify() fast path.
	 */

	buf = (const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(js_ctx->thr->heap, h);
	if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
		for (i = 0; i < n; i++) {
			duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth + 1);
			q = DUK_BW_ENSURE_GETPTR(js_ctx->thr, &js_ctx->bw, 32);
			q += DUK_SPRINTF((char *) q, "\"%lu\": %u,", (unsigned long) i, (unsigned int) buf[i]);
			DUK_BW_SET_PTR(js_ctx->thr, &js_ctx->bw, q);
		}
	} else {
		q = DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw);
		for (i = 0; i < n; i++) {
			q = DUK_BW_ENSURE_RAW(js_ctx->thr, &js_ctx->bw, 32, q);
			q += DUK_SPRINTF((char *) q, "\"%lu\":%u,", (unsigned long) i, (unsigned int) buf[i]);
		}
		DUK_BW_SET_PTR(js_ctx->thr, &js_ctx->bw, q);
	}
	DUK__UNEMIT_1(js_ctx);  /* eat trailing comma */

	if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
		duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth);
	}
	DUK__EMIT_1(js_ctx, DUK_ASC_RCURLY);
}
#endif  /* DUK_USE_JSON_STRINGIFY_FASTPATH */

#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
DUK_LOCAL void duk__enc_pointer(duk_json_enc_ctx *js_ctx, void *ptr) {
	char buf[64];  /* XXX: how to figure correct size? */
	const char *fmt;

	DUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible);  /* caller checks */
	DUK_ASSERT(js_ctx->flag_ext_custom_or_compatible);

	duk_memzero(buf, sizeof(buf));

	/* The #if defined() clutter here needs to handle the three
	 * cases: (1) JX+JC, (2) JX only, (3) JC only.
	 */
#if defined(DUK_USE_JX) && defined(DUK_USE_JC)
	if (js_ctx->flag_ext_custom)
#endif
#if defined(DUK_USE_JX)
	{
		fmt = ptr ? "(%p)" : "(null)";
	}
#endif
#if defined(DUK_USE_JX) && defined(DUK_USE_JC)
	else
#endif
#if defined(DUK_USE_JC)
	{
		DUK_ASSERT(js_ctx->flag_ext_compatible);
		fmt = ptr ? "{\"_ptr\":\"%p\"}" : "{\"_ptr\":\"null\"}";
	}
#endif

	/* When ptr == NULL, the format argument is unused. */
	DUK_SNPRINTF(buf, sizeof(buf) - 1, fmt, ptr);  /* must not truncate */
	DUK__EMIT_CSTR(js_ctx, buf);
}
#endif  /* DUK_USE_JX || DUK_USE_JC */

#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
DUK_LOCAL void duk__enc_bufobj(duk_json_enc_ctx *js_ctx, duk_hbufobj *h_bufobj) {
	DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);

	if (h_bufobj->buf == NULL || !DUK_HBUFOBJ_VALID_SLICE(h_bufobj)) {
		DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);
	} else {
		/* Handle both full and partial slice (as long as covered). */
		duk__enc_buffer_data(js_ctx,
		                     (duk_uint8_t *) DUK_HBUFOBJ_GET_SLICE_BASE(js_ctx->thr->heap, h_bufobj),
		                     (duk_size_t) h_bufobj->length);
	}
}
#endif  /* DUK_USE_JX || DUK_USE_JC */
#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */

/* Indent helper.  Calling code relies on js_ctx->recursion_depth also being
 * directly related to indent depth.
 */
#if defined(DUK_USE_PREFER_SIZE)
DUK_LOCAL void duk__enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_uint_t depth) {
	DUK_ASSERT(js_ctx->h_gap != NULL);
	DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(js_ctx->h_gap) > 0);  /* caller guarantees */

	DUK__EMIT_1(js_ctx, 0x0a);
	while (depth-- > 0) {
		DUK__EMIT_HSTR(js_ctx, js_ctx->h_gap);
	}
}
#else  /* DUK_USE_PREFER_SIZE */
DUK_LOCAL void duk__enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_uint_t depth) {
	const duk_uint8_t *gap_data;
	duk_size_t gap_len;
	duk_size_t avail_bytes;   /* bytes of indent available for copying */
	duk_size_t need_bytes;    /* bytes of indent still needed */
	duk_uint8_t *p_start;
	duk_uint8_t *p;

	DUK_ASSERT(js_ctx->h_gap != NULL);
	DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(js_ctx->h_gap) > 0);  /* caller guarantees */

	DUK__EMIT_1(js_ctx, 0x0a);
	if (DUK_UNLIKELY(depth == 0)) {
		return;
	}

	/* To handle deeper indents efficiently, make use of copies we've
	 * already emitted.  In effect we can emit a sequence of 1, 2, 4,
	 * 8, etc copies, and then finish the last run.  Byte counters
	 * avoid multiply with gap_len on every loop.
	 */

	gap_data = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(js_ctx->h_gap);
	gap_len = (duk_size_t) DUK_HSTRING_GET_BYTELEN(js_ctx->h_gap);
	DUK_ASSERT(gap_len > 0);

	need_bytes = gap_len * depth;
	p = DUK_BW_ENSURE_GETPTR(js_ctx->thr, &js_ctx->bw, need_bytes);
	p_start = p;

	duk_memcpy((void *) p, (const void *) gap_data, (size_t) gap_len);
	p += gap_len;
	avail_bytes = gap_len;
	DUK_ASSERT(need_bytes >= gap_len);
	need_bytes -= gap_len;

	while (need_bytes >= avail_bytes) {
		duk_memcpy((void *) p, (const void *) p_start, (size_t) avail_bytes);
		p += avail_bytes;
		need_bytes -= avail_bytes;
		avail_bytes <<= 1;
	}

	DUK_ASSERT(need_bytes < avail_bytes);  /* need_bytes may be zero */
	duk_memcpy((void *) p, (const void *) p_start, (size_t) need_bytes);
	p += need_bytes;
	/*avail_bytes += need_bytes*/

	DUK_BW_SET_PTR(js_ctx->thr, &js_ctx->bw, p);
}
#endif  /* DUK_USE_PREFER_SIZE */

/* Shared entry handling for object/array serialization. */
DUK_LOCAL void duk__enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top) {
	duk_hthread *thr = js_ctx->thr;
	duk_hobject *h_target;
	duk_uint_fast32_t i, n;

	*entry_top = duk_get_top(thr);

	duk_require_stack(thr, DUK_JSON_ENC_REQSTACK);

	/* Loop check using a hybrid approach: a fixed-size visited[] array
	 * with overflow in a loop check object.
	 */

	h_target = duk_known_hobject(thr, -1);  /* object or array */

	n = js_ctx->recursion_depth;
	if (DUK_UNLIKELY(n > DUK_JSON_ENC_LOOPARRAY)) {
		n = DUK_JSON_ENC_LOOPARRAY;
	}
	for (i = 0; i < n; i++) {
		if (DUK_UNLIKELY(js_ctx->visiting[i] == h_target)) {
			DUK_DD(DUK_DDPRINT("slow path loop detect"));
			DUK_ERROR_TYPE(thr, DUK_STR_CYCLIC_INPUT);
			DUK_WO_NORETURN(return;);
		}
	}
	if (js_ctx->recursion_depth < DUK_JSON_ENC_LOOPARRAY) {
		js_ctx->visiting[js_ctx->recursion_depth] = h_target;
	} else {
		duk_push_sprintf(thr, DUK_STR_FMT_PTR, (void *) h_target);
		duk_dup_top(thr);  /* -> [ ... voidp voidp ] */
		if (duk_has_prop(thr, js_ctx->idx_loop)) {
			DUK_ERROR_TYPE(thr, DUK_STR_CYCLIC_INPUT);
			DUK_WO_NORETURN(return;);
		}
		duk_push_true(thr);  /* -> [ ... voidp true ] */
		duk_put_prop(thr, js_ctx->idx_loop);  /* -> [ ... ] */
	}

	/* C recursion check. */

	DUK_ASSERT_DISABLE(js_ctx->recursion_depth >= 0);  /* unsigned */
	DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
	if (js_ctx->recursion_depth >= js_ctx->recursion_limit) {
		DUK_ERROR_RANGE(thr, DUK_STR_JSONENC_RECLIMIT);
		DUK_WO_NORETURN(return;);
	}
	js_ctx->recursion_depth++;

	DUK_DDD(DUK_DDDPRINT("shared entry finished: top=%ld, loop=%!T",
	                     (long) duk_get_top(thr), (duk_tval *) duk_get_tval(thr, js_ctx->idx_loop)));
}

/* Shared exit handling for object/array serialization. */
DUK_LOCAL void duk__enc_objarr_exit(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top) {
	duk_hthread *thr = js_ctx->thr;
	duk_hobject *h_target;

	/* C recursion check. */

	DUK_ASSERT(js_ctx->recursion_depth > 0);
	DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
	js_ctx->recursion_depth--;

	/* Loop check. */

	h_target = duk_known_hobject(thr, *entry_top - 1);  /* original target at entry_top - 1 */

	if (js_ctx->recursion_depth < DUK_JSON_ENC_LOOPARRAY) {
		/* Previous entry was inside visited[], nothing to do. */
	} else {
		duk_push_sprintf(thr, DUK_STR_FMT_PTR, (void *) h_target);
		duk_del_prop(thr, js_ctx->idx_loop);  /* -> [ ... ] */
	}

	/* Restore stack top after unbalanced code paths. */
	duk_set_top(thr, *entry_top);

	DUK_DDD(DUK_DDDPRINT("shared entry finished: top=%ld, loop=%!T",
	                     (long) duk_get_top(thr), (duk_tval *) duk_get_tval(thr, js_ctx->idx_loop)));
}

/* The JO(value) operation: encode object.
 *
 * Stack policy: [ object ] -> [ object ].
 */
DUK_LOCAL void duk__enc_object(duk_json_enc_ctx *js_ctx) {
	duk_hthread *thr = js_ctx->thr;
	duk_hstring *h_key;
	duk_idx_t entry_top;
	duk_idx_t idx_obj;
	duk_idx_t idx_keys;
	duk_bool_t emitted;
	duk_uarridx_t arr_len, i;
	duk_size_t prev_size;

	DUK_DDD(DUK_DDDPRINT("duk__enc_object: obj=%!T", (duk_tval *) duk_get_tval(thr, -1)));

	duk__enc_objarr_entry(js_ctx, &entry_top);

	idx_obj = entry_top - 1;

	if (js_ctx->idx_proplist >= 0) {
		idx_keys = js_ctx->idx_proplist;
	} else {
		/* XXX: would be nice to enumerate an object at specified index */
		duk_dup(thr, idx_obj);
		(void) duk_hobject_get_enumerated_keys(thr, DUK_ENUM_OWN_PROPERTIES_ONLY /*flags*/);  /* [ ... target ] -> [ ... target keys ] */
		idx_keys = duk_require_normalize_index(thr, -1);
		/* leave stack unbalanced on purpose */
	}

	DUK_DDD(DUK_DDDPRINT("idx_keys=%ld, h_keys=%!T",
	                     (long) idx_keys, (duk_tval *) duk_get_tval(thr, idx_keys)));

	/* Steps 8-10 have been merged to avoid a "partial" variable. */

	DUK__EMIT_1(js_ctx, DUK_ASC_LCURLY);

	/* XXX: keys is an internal object with all keys to be processed
	 * in its (gapless) array part.  Because nobody can touch the keys
	 * object, we could iterate its array part directly (keeping in mind
	 * that it can be reallocated).
	 */

	arr_len = (duk_uarridx_t) duk_get_length(thr, idx_keys);
	emitted = 0;
	for (i = 0; i < arr_len; i++) {
		duk_get_prop_index(thr, idx_keys, i);  /* -> [ ... key ] */

		DUK_DDD(DUK_DDDPRINT("object property loop: holder=%!T, key=%!T",
		                     (duk_tval *) duk_get_tval(thr, idx_obj),
		                     (duk_tval *) duk_get_tval(thr, -1)));

		h_key = duk_known_hstring(thr, -1);
		DUK_ASSERT(h_key != NULL);
		DUK_ASSERT(!DUK_HSTRING_HAS_SYMBOL(h_key));  /* proplist filtering; enum options */

		prev_size = DUK_BW_GET_SIZE(js_ctx->thr, &js_ctx->bw);
		if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
			duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth);
			duk__enc_key_autoquote(js_ctx, h_key);
			DUK__EMIT_2(js_ctx, DUK_ASC_COLON, DUK_ASC_SPACE);
		} else {
			duk__enc_key_autoquote(js_ctx, h_key);
			DUK__EMIT_1(js_ctx, DUK_ASC_COLON);
		}

		/* [ ... key ] */

		if (DUK_UNLIKELY(duk__enc_value(js_ctx, idx_obj) == 0)) {
			/* Value would yield 'undefined', so skip key altogether.
			 * Side effects have already happened.
			 */
			DUK_BW_SET_SIZE(js_ctx->thr, &js_ctx->bw, prev_size);
		} else {
			DUK__EMIT_1(js_ctx, DUK_ASC_COMMA);
			emitted = 1;
		}

		/* [ ... ] */
	}

	if (emitted) {
		DUK_ASSERT(*((duk_uint8_t *) DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw) - 1) == DUK_ASC_COMMA);
		DUK__UNEMIT_1(js_ctx);  /* eat trailing comma */
		if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
			DUK_ASSERT(js_ctx->recursion_depth >= 1);
			duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1U);
		}
	}
	DUK__EMIT_1(js_ctx, DUK_ASC_RCURLY);

	duk__enc_objarr_exit(js_ctx, &entry_top);

	DUK_ASSERT_TOP(thr, entry_top);
}

/* The JA(value) operation: encode array.
 *
 * Stack policy: [ array ] -> [ array ].
 */
DUK_LOCAL void duk__enc_array(duk_json_enc_ctx *js_ctx) {
	duk_hthread *thr = js_ctx->thr;
	duk_idx_t entry_top;
	duk_idx_t idx_arr;
	duk_bool_t emitted;
	duk_uarridx_t i, arr_len;

	DUK_DDD(DUK_DDDPRINT("duk__enc_array: array=%!T",
	                     (duk_tval *) duk_get_tval(thr, -1)));

	duk__enc_objarr_entry(js_ctx, &entry_top);

	idx_arr = entry_top - 1;

	/* Steps 8-10 have been merged to avoid a "partial" variable. */

	DUK__EMIT_1(js_ctx, DUK_ASC_LBRACKET);

	arr_len = (duk_uarridx_t) duk_get_length(thr, idx_arr);
	emitted = 0;
	for (i = 0; i < arr_len; i++) {
		DUK_DDD(DUK_DDDPRINT("array entry loop: array=%!T, index=%ld, arr_len=%ld",
		                     (duk_tval *) duk_get_tval(thr, idx_arr),
		                     (long) i, (long) arr_len));

		if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
			DUK_ASSERT(js_ctx->recursion_depth >= 1);
			duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth);
		}

		(void) duk_push_uint_to_hstring(thr, (duk_uint_t) i);  /* -> [ ... key ] */

		/* [ ... key ] */

		if (DUK_UNLIKELY(duk__enc_value(js_ctx, idx_arr) == 0)) {
			/* Value would normally be omitted, replace with 'null'. */
			DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);
		} else {
			;
		}

		/* [ ... ] */

		DUK__EMIT_1(js_ctx, DUK_ASC_COMMA);
		emitted = 1;
	}

	if (emitted) {
		DUK_ASSERT(*((duk_uint8_t *) DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw) - 1) == DUK_ASC_COMMA);
		DUK__UNEMIT_1(js_ctx);  /* eat trailing comma */
		if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
			DUK_ASSERT(js_ctx->recursion_depth >= 1);
			duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1U);
		}
	}
	DUK__EMIT_1(js_ctx, DUK_ASC_RBRACKET);

	duk__enc_objarr_exit(js_ctx, &entry_top);

	DUK_ASSERT_TOP(thr, entry_top);
}

/* The Str(key, holder) operation.
 *
 * Stack policy: [ ... key ] -> [ ... ]
 */
DUK_LOCAL duk_bool_t duk__enc_value(duk_json_enc_ctx *js_ctx, duk_idx_t idx_holder) {
	duk_hthread *thr = js_ctx->thr;
	duk_tval *tv;
	duk_tval *tv_holder;
	duk_tval *tv_key;
	duk_small_int_t c;

	DUK_DDD(DUK_DDDPRINT("duk__enc_value: idx_holder=%ld, holder=%!T, key=%!T",
	                     (long) idx_holder, (duk_tval *) duk_get_tval(thr, idx_holder),
	                     (duk_tval *) duk_get_tval(thr, -1)));

	tv_holder = DUK_GET_TVAL_POSIDX(thr, idx_holder);
	DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv_holder));
	tv_key = DUK_GET_TVAL_NEGIDX(thr, -1);
	DUK_ASSERT(DUK_TVAL_IS_STRING(tv_key));
	DUK_ASSERT(!DUK_HSTRING_HAS_SYMBOL(DUK_TVAL_GET_STRING(tv_key)));  /* Caller responsible. */
	(void) duk_hobject_getprop(thr, tv_holder, tv_key);

	/* -> [ ... key val ] */

	DUK_DDD(DUK_DDDPRINT("value=%!T", (duk_tval *) duk_get_tval(thr, -1)));

	/* Standard JSON checks for .toJSON() only for actual objects; for
	 * example, setting Number.prototype.toJSON and then serializing a
	 * number won't invoke the .toJSON() method.  However, lightfuncs and
	 * plain buffers mimic objects so we check for their .toJSON() method.
	 */
	if (duk_check_type_mask(thr, -1, DUK_TYPE_MASK_OBJECT |
	                                 DUK_TYPE_MASK_LIGHTFUNC |
	                                 DUK_TYPE_MASK_BUFFER)) {
		duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_TO_JSON);
		if (duk_is_callable(thr, -1)) {  /* toJSON() can also be a lightfunc */
			DUK_DDD(DUK_DDDPRINT("value is object, has callable toJSON() -> call it"));
			/* XXX: duk_dup_unvalidated(thr, -2) etc. */
			duk_dup_m2(thr);          /* -> [ ... key val toJSON val ] */
			duk_dup_m4(thr);          /* -> [ ... key val toJSON val key ] */
			duk_call_method(thr, 1);  /* -> [ ... key val val' ] */
			duk_remove_m2(thr);       /* -> [ ... key val' ] */
		} else {
			duk_pop(thr);             /* -> [ ... key val ] */
		}
	}

	/* [ ... key val ] */

	DUK_DDD(DUK_DDDPRINT("value=%!T", (duk_tval *) duk_get_tval(thr, -1)));

	if (js_ctx->h_replacer) {
		/* XXX: Here a "slice copy" would be useful. */
		DUK_DDD(DUK_DDDPRINT("replacer is set, call replacer"));
		duk_push_hobject(thr, js_ctx->h_replacer);  /* -> [ ... key val replacer ] */
		duk_dup(thr, idx_holder);                   /* -> [ ... key val replacer holder ] */
		duk_dup_m4(thr);                            /* -> [ ... key val replacer holder key ] */
		duk_dup_m4(thr);                            /* -> [ ... key val replacer holder key val ] */
		duk_call_method(thr, 2);                    /* -> [ ... key val val' ] */
		duk_remove_m2(thr);                         /* -> [ ... key val' ] */
	}

	/* [ ... key val ] */

	DUK_DDD(DUK_DDDPRINT("value=%!T", (duk_tval *) duk_get_tval(thr, -1)));

	tv = DUK_GET_TVAL_NEGIDX(thr, -1);
	if (DUK_TVAL_IS_OBJECT(tv)) {
		duk_hobject *h;

		h = DUK_TVAL_GET_OBJECT(tv);
		DUK_ASSERT(h != NULL);

#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
		if (DUK_HOBJECT_IS_BUFOBJ(h) &&
		    js_ctx->flags & (DUK_JSON_FLAG_EXT_CUSTOM | DUK_JSON_FLAG_EXT_COMPATIBLE)) {
			/* With JX/JC a bufferobject gets serialized specially. */
			duk_hbufobj *h_bufobj;
			h_bufobj = (duk_hbufobj *) h;
			DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
			duk__enc_bufobj(js_ctx, h_bufobj);
			goto pop2_emitted;
		}
		/* Otherwise bufferobjects get serialized as normal objects. */
#endif  /* JX || JC */
#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
		c = (duk_small_int_t) DUK_HOBJECT_GET_CLASS_NUMBER(h);
		switch (c) {
		case DUK_HOBJECT_CLASS_NUMBER: {
			DUK_DDD(DUK_DDDPRINT("value is a Number object -> coerce with ToNumber()"));
			duk_to_number_m1(thr);
			/* The coercion potentially invokes user .valueOf() and .toString()
			 * but can't result in a function value because ToPrimitive() would
			 * reject such a result: test-dev-json-stringify-coercion-1.js.
			 */
			DUK_ASSERT(!duk_is_callable(thr, -1));
			break;
		}
		case DUK_HOBJECT_CLASS_STRING: {
			DUK_DDD(DUK_DDDPRINT("value is a String object -> coerce with ToString()"));
			duk_to_string(thr, -1);
			/* Same coercion behavior as for Number. */
			DUK_ASSERT(!duk_is_callable(thr, -1));
			break;
		}
#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
		case DUK_HOBJECT_CLASS_POINTER:
#endif
		case DUK_HOBJECT_CLASS_BOOLEAN: {
			DUK_DDD(DUK_DDDPRINT("value is a Boolean/Buffer/Pointer object -> get internal value"));
			duk_xget_owndataprop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
			duk_remove_m2(thr);
			break;
		}
		default: {
			/* Normal object which doesn't get automatically coerced to a
			 * primitive value.  Functions are checked for specially.  The
			 * primitive value coercions for Number, String, Pointer, and
			 * Boolean can't result in functions so suffices to check here.
			 * Symbol objects are handled like plain objects (their primitive
			 * value is NOT looked up like for e.g. String objects).
			 */
			DUK_ASSERT(h != NULL);
			if (DUK_HOBJECT_IS_CALLABLE(h)) {
#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
				if (js_ctx->flags & (DUK_JSON_FLAG_EXT_CUSTOM |
				                     DUK_JSON_FLAG_EXT_COMPATIBLE)) {
					/* We only get here when doing non-standard JSON encoding */
					DUK_DDD(DUK_DDDPRINT("-> function allowed, serialize to custom format"));
					DUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible);
					DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_function);
					goto pop2_emitted;
				} else {
					DUK_DDD(DUK_DDDPRINT("-> will result in undefined (function)"));
					goto pop2_undef;
				}
#else  /* DUK_USE_JX || DUK_USE_JC */
				DUK_DDD(DUK_DDDPRINT("-> will result in undefined (function)"));
				goto pop2_undef;
#endif  /* DUK_USE_JX || DUK_USE_JC */
			}
		}
		}  /* end switch */
	}

	/* [ ... key val ] */

	DUK_DDD(DUK_DDDPRINT("value=%!T", (duk_tval *) duk_get_tval(thr, -1)));

	if (duk_check_type_mask(thr, -1, js_ctx->mask_for_undefined)) {
		/* will result in undefined */
		DUK_DDD(DUK_DDDPRINT("-> will result in undefined (type mask check)"));
		goto pop2_undef;
	}
	tv = DUK_GET_TVAL_NEGIDX(thr, -1);

	switch (DUK_TVAL_GET_TAG(tv)) {
#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
	/* When JX/JC not in use, the type mask above will avoid this case if needed. */
	case DUK_TAG_UNDEFINED: {
		DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_undefined);
		break;
	}
#endif
	case DUK_TAG_NULL: {
		DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);
		break;
	}
	case DUK_TAG_BOOLEAN: {
		DUK__EMIT_STRIDX(js_ctx, DUK_TVAL_GET_BOOLEAN(tv) ?
		                 DUK_STRIDX_TRUE : DUK_STRIDX_FALSE);
		break;
	}
#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
	/* When JX/JC not in use, the type mask above will avoid this case if needed. */
	case DUK_TAG_POINTER: {
		duk__enc_pointer(js_ctx, DUK_TVAL_GET_POINTER(tv));
		break;
	}
#endif  /* DUK_USE_JX || DUK_USE_JC */
	case DUK_TAG_STRING: {
		duk_hstring *h = DUK_TVAL_GET_STRING(tv);
		DUK_ASSERT(h != NULL);
		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
			goto pop2_undef;
		}
		duk__enc_quote_string(js_ctx, h);
		break;
	}
	case DUK_TAG_OBJECT: {
		duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
		DUK_ASSERT(h != NULL);

		/* Function values are handled completely above (including
		 * coercion results):
		 */
		DUK_ASSERT(!DUK_HOBJECT_IS_CALLABLE(h));

		if (duk_js_isarray_hobject(h)) {
			duk__enc_array(js_ctx);
		} else {
			duk__enc_object(js_ctx);
		}
		break;
	}
	/* Because plain buffers mimics Uint8Array, they have enumerable
	 * index properties [0,byteLength[.  Because JSON only serializes
	 * enumerable own properties, no properties can be serialized for
	 * plain buffers (all virtual properties are non-enumerable).  However,
	 * there may be a .toJSON() method which was already handled above.
	 */
	case DUK_TAG_BUFFER: {
#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
		if (js_ctx->flag_ext_custom_or_compatible) {
			duk__enc_buffer_jx_jc(js_ctx, DUK_TVAL_GET_BUFFER(tv));
			break;
		}
#endif

		/* Could implement a fastpath, but the fast path would need
		 * to handle realloc side effects correctly.
		 */
		duk_to_object(thr, -1);
		duk__enc_object(js_ctx);
		break;
	}
	case DUK_TAG_LIGHTFUNC: {
#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
		/* We only get here when doing non-standard JSON encoding */
		DUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible);
		DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_function);
#else
		/* Standard JSON omits functions */
		DUK_UNREACHABLE();
#endif
		break;
	}
#if defined(DUK_USE_FASTINT)
	case DUK_TAG_FASTINT:
		/* Number serialization has a significant impact relative to
		 * other fast path code, so careful fast path for fastints.
		 */
		duk__enc_fastint_tval(js_ctx, tv);
		break;
#endif
	default: {
		/* number */
		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
		/* XXX: A fast path for usual integers would be useful when
		 * fastint support is not enabled.
		 */
		duk__enc_double(js_ctx);
		break;
	}
	}

#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
 pop2_emitted:
#endif
	duk_pop_2(thr); /* [ ... key val ] -> [ ... ] */
	return 1;  /* emitted */

 pop2_undef:
	duk_pop_2(thr);  /* [ ... key val ] -> [ ... ] */
	return 0;  /* not emitted */
}

/* E5 Section 15.12.3, main algorithm, step 4.b.ii steps 1-4. */
DUK_LOCAL duk_bool_t duk__enc_allow_into_proplist(duk_tval *tv) {
	duk_small_int_t c;

	/* XXX: some kind of external internal type checker?
	 * - type mask; symbol flag; class mask
	 */
	DUK_ASSERT(tv != NULL);
	if (DUK_TVAL_IS_STRING(tv)) {
		duk_hstring *h;
		h = DUK_TVAL_GET_STRING(tv);
		DUK_ASSERT(h != NULL);
		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
			return 0;
		}
		return 1;
	} else if (DUK_TVAL_IS_NUMBER(tv)) {
		return 1;
	} else if (DUK_TVAL_IS_OBJECT(tv)) {
		duk_hobject *h;
		h = DUK_TVAL_GET_OBJECT(tv);
		DUK_ASSERT(h != NULL);
		c = (duk_small_int_t) DUK_HOBJECT_GET_CLASS_NUMBER(h);
		if (c == DUK_HOBJECT_CLASS_STRING || c == DUK_HOBJECT_CLASS_NUMBER) {
			return 1;
		}
	}

	return 0;
}

/*
 *  JSON.stringify() fast path
 *
 *  Otherwise supports full JSON, JX, and JC features, but bails out on any
 *  possible side effect which might change the value being serialized.  The
 *  fast path can take advantage of the fact that the value being serialized
 *  is unchanged so that we can walk directly through property tables etc.
 */

#if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
DUK_LOCAL duk_bool_t duk__json_stringify_fast_value(duk_json_enc_ctx *js_ctx, duk_tval *tv) {
	duk_uint_fast32_t i, n;

	DUK_DDD(DUK_DDDPRINT("stringify fast: %!T", tv));

	DUK_ASSERT(js_ctx != NULL);
	DUK_ASSERT(js_ctx->thr != NULL);

#if 0 /* disabled for now */
 restart_match:
#endif

	DUK_ASSERT(tv != NULL);

	switch (DUK_TVAL_GET_TAG(tv)) {
	case DUK_TAG_UNDEFINED: {
#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
		if (js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible) {
			DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_undefined);
			break;
		} else {
			goto emit_undefined;
		}
#else
		goto emit_undefined;
#endif
	}
	case DUK_TAG_NULL: {
		DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);
		break;
	}
	case DUK_TAG_BOOLEAN: {
		DUK__EMIT_STRIDX(js_ctx, DUK_TVAL_GET_BOOLEAN(tv) ?
		                 DUK_STRIDX_TRUE : DUK_STRIDX_FALSE);
		break;
	}
	case DUK_TAG_STRING: {
		duk_hstring *h;
		h = DUK_TVAL_GET_STRING(tv);
		DUK_ASSERT(h != NULL);
		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
			goto emit_undefined;
		}
		duk__enc_quote_string(js_ctx, h);
		break;
	}
	case DUK_TAG_OBJECT: {
		duk_hobject *obj;
		duk_tval *tv_val;
		duk_bool_t emitted = 0;
		duk_uint32_t c_bit, c_all, c_array, c_unbox, c_undef,
		             c_func, c_bufobj, c_object, c_abort;

		/* For objects JSON.stringify() only looks for own, enumerable
		 * properties which is nice for the fast path here.
		 *
		 * For arrays JSON.stringify() uses [[Get]] so it will actually
		 * inherit properties during serialization!  This fast path
		 * supports gappy arrays as long as there's no actual inherited
		 * property (which might be a getter etc).
		 *
		 * Since recursion only happens for objects, we can have both
		 * recursion and loop checks here.  We use a simple, depth-limited
		 * loop check in the fast path because the object-based tracking
		 * is very slow (when tested, it accounted for 50% of fast path
		 * execution time for input data with a lot of small objects!).
		 */

		/* XXX: for real world code, could just ignore array inheritance
		 * and only look at array own properties.
		 */

		/* We rely on a few object flag / class number relationships here,
		 * assert for them.
		 */

		obj = DUK_TVAL_GET_OBJECT(tv);
		DUK_ASSERT(obj != NULL);
		DUK_HOBJECT_ASSERT_VALID(obj);

		/* Once recursion depth is increased, exit path must decrease
		 * it (though it's OK to abort the fast path).
		 */

		DUK_ASSERT_DISABLE(js_ctx->recursion_depth >= 0);  /* unsigned */
		DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
		if (js_ctx->recursion_depth >= js_ctx->recursion_limit) {
			DUK_DD(DUK_DDPRINT("fast path recursion limit"));
			DUK_ERROR_RANGE(js_ctx->thr, DUK_STR_JSONDEC_RECLIMIT);
			DUK_WO_NORETURN(return 0;);
		}

		for (i = 0, n = (duk_uint_fast32_t) js_ctx->recursion_depth; i < n; i++) {
			if (DUK_UNLIKELY(js_ctx->visiting[i] == obj)) {
				DUK_DD(DUK_DDPRINT("fast path loop detect"));
				DUK_ERROR_TYPE(js_ctx->thr, DUK_STR_CYCLIC_INPUT);
				DUK_WO_NORETURN(return 0;);
			}
		}

		/* Guaranteed by recursion_limit setup so we don't have to
		 * check twice.
		 */
		DUK_ASSERT(js_ctx->recursion_depth < DUK_JSON_ENC_LOOPARRAY);
		js_ctx->visiting[js_ctx->recursion_depth] = obj;
		js_ctx->recursion_depth++;

		/* If object has a .toJSON() property, we can't be certain
		 * that it wouldn't mutate any value arbitrarily, so bail
		 * out of the fast path.
		 *
		 * If an object is a Proxy we also can't avoid side effects
		 * so abandon.
		 */
		/* XXX: non-callable .toJSON() doesn't need to cause an abort
		 * but does at the moment, probably not worth fixing.
		 */
		if (duk_hobject_hasprop_raw(js_ctx->thr, obj, DUK_HTHREAD_STRING_TO_JSON(js_ctx->thr)) ||
		    DUK_HOBJECT_IS_PROXY(obj)) {
			DUK_DD(DUK_DDPRINT("object has a .toJSON property or object is a Proxy, abort fast path"));
			goto abort_fastpath;
		}

		/* We could use a switch-case for the class number but it turns out
		 * a small if-else ladder on class masks is better.  The if-ladder
		 * should be in order of relevancy.
		 */

		/* XXX: move masks to js_ctx? they don't change during one
		 * fast path invocation.
		 */
		DUK_ASSERT(DUK_HOBJECT_CLASS_MAX <= 31);
#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
		if (js_ctx->flag_ext_custom_or_compatible) {
			c_all = DUK_HOBJECT_CMASK_ALL;
			c_array = DUK_HOBJECT_CMASK_ARRAY;
			c_unbox = DUK_HOBJECT_CMASK_NUMBER |
			          DUK_HOBJECT_CMASK_STRING |
			          DUK_HOBJECT_CMASK_BOOLEAN |
			          DUK_HOBJECT_CMASK_POINTER;  /* Symbols are not unboxed. */
			c_func = DUK_HOBJECT_CMASK_FUNCTION;
			c_bufobj = DUK_HOBJECT_CMASK_ALL_BUFOBJS;
			c_undef = 0;
			c_abort = 0;
			c_object = c_all & ~(c_array | c_unbox | c_func | c_bufobj | c_undef | c_abort);
		}
		else
#endif
		{
			c_all = DUK_HOBJECT_CMASK_ALL;
			c_array = DUK_HOBJECT_CMASK_ARRAY;
			c_unbox = DUK_HOBJECT_CMASK_NUMBER |
			          DUK_HOBJECT_CMASK_STRING |
			          DUK_HOBJECT_CMASK_BOOLEAN;  /* Symbols are not unboxed. */
			c_func = 0;
			c_bufobj = 0;
			c_undef = DUK_HOBJECT_CMASK_FUNCTION |
			          DUK_HOBJECT_CMASK_POINTER;
			/* As the fast path doesn't currently properly support
			 * duk_hbufobj virtual properties, abort fast path if
			 * we encounter them in plain JSON mode.
			 */
			c_abort = DUK_HOBJECT_CMASK_ALL_BUFOBJS;
			c_object = c_all & ~(c_array | c_unbox | c_func | c_bufobj | c_undef | c_abort);
		}

		c_bit = (duk_uint32_t) DUK_HOBJECT_GET_CLASS_MASK(obj);
		if (c_bit & c_object) {
			/* All other object types. */
			DUK__EMIT_1(js_ctx, DUK_ASC_LCURLY);

			/* A non-Array object should not have an array part in practice.
			 * But since it is supported internally (and perhaps used at some
			 * point), check and abandon if that's the case.
			 */
			if (DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
				DUK_DD(DUK_DDPRINT("non-Array object has array part, abort fast path"));
				goto abort_fastpath;
			}

			for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(obj); i++) {
				duk_hstring *k;
				duk_size_t prev_size;

				k = DUK_HOBJECT_E_GET_KEY(js_ctx->thr->heap, obj, i);
				if (!k) {
					continue;
				}
				if (DUK_HSTRING_HAS_ARRIDX(k)) {
					/* If an object has array index keys we would need
					 * to sort them into the ES2015 enumeration order to
					 * be consistent with the slow path.  Abort the fast
					 * path and handle in the slow path for now.
					 */
					DUK_DD(DUK_DDPRINT("property key is an array index, abort fast path"));
					goto abort_fastpath;
				}
				if (!DUK_HOBJECT_E_SLOT_IS_ENUMERABLE(js_ctx->thr->heap, obj, i)) {
					continue;
				}
				if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(js_ctx->thr->heap, obj, i)) {
					/* Getter might have arbitrary side effects,
					 * so bail out.
					 */
					DUK_DD(DUK_DDPRINT("property is an accessor, abort fast path"));
					goto abort_fastpath;
				}
				if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(k))) {
					continue;
				}

				tv_val = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(js_ctx->thr->heap, obj, i);

				prev_size = DUK_BW_GET_SIZE(js_ctx->thr, &js_ctx->bw);
				if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
					duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth);
					duk__enc_key_autoquote(js_ctx, k);
					DUK__EMIT_2(js_ctx, DUK_ASC_COLON, DUK_ASC_SPACE);
				} else {
					duk__enc_key_autoquote(js_ctx, k);
					DUK__EMIT_1(js_ctx, DUK_ASC_COLON);
				}

				if (duk__json_stringify_fast_value(js_ctx, tv_val) == 0) {
					DUK_DD(DUK_DDPRINT("prop value not supported, rewind key and colon"));
					DUK_BW_SET_SIZE(js_ctx->thr, &js_ctx->bw, prev_size);
				} else {
					DUK__EMIT_1(js_ctx, DUK_ASC_COMMA);
					emitted = 1;
				}
			}

			/* If any non-Array value had enumerable virtual own
			 * properties, they should be serialized here (actually,
			 * before the explicit properties).  Standard types don't.
			 */

			if (emitted) {
				DUK_ASSERT(*((duk_uint8_t *) DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw) - 1) == DUK_ASC_COMMA);
				DUK__UNEMIT_1(js_ctx);  /* eat trailing comma */
				if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
					DUK_ASSERT(js_ctx->recursion_depth >= 1);
					duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1U);
				}
			}
			DUK__EMIT_1(js_ctx, DUK_ASC_RCURLY);
		} else if (c_bit & c_array) {
			duk_uint_fast32_t arr_len;
			duk_uint_fast32_t asize;

			DUK__EMIT_1(js_ctx, DUK_ASC_LBRACKET);

			/* Assume arrays are dense in the fast path. */
			if (!DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
				DUK_DD(DUK_DDPRINT("Array object is sparse, abort fast path"));
				goto abort_fastpath;
			}

			arr_len = (duk_uint_fast32_t) ((duk_harray *) obj)->length;
			asize = (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(obj);
			/* Array part may be larger than 'length'; if so, iterate
			 * only up to array 'length'.  Array part may also be smaller
			 * than 'length' in some cases.
			 */
			for (i = 0; i < arr_len; i++) {
				duk_tval *tv_arrval;
				duk_hstring *h_tmp;
				duk_bool_t has_inherited;

				if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
					duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth);
				}

				if (DUK_LIKELY(i < asize)) {
					tv_arrval = DUK_HOBJECT_A_GET_VALUE_PTR(js_ctx->thr->heap, obj, i);
					if (DUK_LIKELY(!DUK_TVAL_IS_UNUSED(tv_arrval))) {
						/* Expected case: element is present. */
						if (duk__json_stringify_fast_value(js_ctx, tv_arrval) == 0) {
							DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);
						}
						goto elem_done;
					}
				}

				/* Gap in array; check for inherited property,
				 * bail out if one exists.  This should be enough
				 * to support gappy arrays for all practical code.
				 */

				h_tmp = duk_push_uint_to_hstring(js_ctx->thr, (duk_uint_t) i);
				has_inherited = duk_hobject_hasprop_raw(js_ctx->thr, obj, h_tmp);
				duk_pop(js_ctx->thr);
				if (has_inherited) {
					DUK_D(DUK_DPRINT("gap in array, conflicting inherited property, abort fast path"));
					goto abort_fastpath;
				}

				/* Ordinary gap, undefined encodes to 'null' in
				 * standard JSON, but JX/JC use their form for
				 * undefined to better preserve the typing.
				 */
				DUK_D(DUK_DPRINT("gap in array, no conflicting inherited property, remain on fast path"));
#if defined(DUK_USE_JX)
				DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_undefined);
#else
				DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);
#endif
				/* fall through */

			 elem_done:
				DUK__EMIT_1(js_ctx, DUK_ASC_COMMA);
				emitted = 1;
			}

			if (emitted) {
				DUK_ASSERT(*((duk_uint8_t *) DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw) - 1) == DUK_ASC_COMMA);
				DUK__UNEMIT_1(js_ctx);  /* eat trailing comma */
				if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
					DUK_ASSERT(js_ctx->recursion_depth >= 1);
					duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1U);
				}
			}
			DUK__EMIT_1(js_ctx, DUK_ASC_RBRACKET);
		} else if (c_bit & c_unbox) {
			/* Certain boxed types are required to go through
			 * automatic unboxing.  Rely on internal value being
			 * sane (to avoid infinite recursion).
			 */
			DUK_ASSERT((c_bit & DUK_HOBJECT_CMASK_SYMBOL) == 0);  /* Symbols are not unboxed. */

#if 1
			/* The code below is incorrect if .toString() or .valueOf() have
			 * have been overridden.  The correct approach would be to look up
			 * the method(s) and if they resolve to the built-in function we
			 * can safely bypass it and look up the internal value directly.
			 * Unimplemented for now, abort fast path for boxed values.
			 */
			goto abort_fastpath;
#else  /* disabled */
			/* Disabled until fixed, see above. */
			duk_tval *tv_internal;

			DUK_DD(DUK_DDPRINT("auto unboxing in fast path"));

			tv_internal = duk_hobject_get_internal_value_tval_ptr(js_ctx->thr->heap, obj);
			DUK_ASSERT(tv_internal != NULL);
			DUK_ASSERT(DUK_TVAL_IS_STRING(tv_internal) ||
			           DUK_TVAL_IS_NUMBER(tv_internal) ||
			           DUK_TVAL_IS_BOOLEAN(tv_internal) ||
			           DUK_TVAL_IS_POINTER(tv_internal));

			tv = tv_internal;
			DUK_ASSERT(js_ctx->recursion_depth > 0);
			js_ctx->recursion_depth--;  /* required to keep recursion depth correct */
			goto restart_match;
#endif  /* disabled */
#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
		} else if (c_bit & c_func) {
			DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_function);
#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
		} else if (c_bit & c_bufobj) {
			duk__enc_bufobj(js_ctx, (duk_hbufobj *) obj);
#endif
#endif
		} else if (c_bit & c_abort) {
			DUK_DD(DUK_DDPRINT("abort fast path for unsupported type"));
			goto abort_fastpath;
		} else {
			DUK_ASSERT((c_bit & c_undef) != 0);

			/* Must decrease recursion depth before returning. */
			DUK_ASSERT(js_ctx->recursion_depth > 0);
			DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
			js_ctx->recursion_depth--;
			goto emit_undefined;
		}

		DUK_ASSERT(js_ctx->recursion_depth > 0);
		DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
		js_ctx->recursion_depth--;
		break;
	}
	case DUK_TAG_BUFFER: {
		/* Plain buffers are treated like Uint8Arrays: they have
		 * enumerable indices.  Other virtual properties are not
		 * enumerable, and inherited properties are not serialized.
		 * However, there can be a replacer (not relevant here) or
		 * a .toJSON() method (which we need to check for explicitly).
		 */

#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
		if (duk_hobject_hasprop_raw(js_ctx->thr,
		                            js_ctx->thr->builtins[DUK_BIDX_UINT8ARRAY_PROTOTYPE],
		                            DUK_HTHREAD_STRING_TO_JSON(js_ctx->thr))) {
			DUK_DD(DUK_DDPRINT("value is a plain buffer and there's an inherited .toJSON, abort fast path"));
			goto abort_fastpath;
		}
#endif

#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
		if (js_ctx->flag_ext_custom_or_compatible) {
			duk__enc_buffer_jx_jc(js_ctx, DUK_TVAL_GET_BUFFER(tv));
			break;
		}
#endif

		/* Plain buffers mimic Uint8Arrays, and have enumerable index
		 * properties.
		 */
		duk__enc_buffer_json_fastpath(js_ctx, DUK_TVAL_GET_BUFFER(tv));
		break;
	}
	case DUK_TAG_POINTER: {
#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
		if (js_ctx->flag_ext_custom_or_compatible) {
			duk__enc_pointer(js_ctx, DUK_TVAL_GET_POINTER(tv));
			break;
		} else {
			goto emit_undefined;
		}
#else
		goto emit_undefined;
#endif
	}
	case DUK_TAG_LIGHTFUNC: {
		/* A lightfunc might also inherit a .toJSON() so just bail out. */
		/* XXX: Could just lookup .toJSON() and continue in fast path,
		 * as it would almost never be defined.
		 */
		DUK_DD(DUK_DDPRINT("value is a lightfunc, abort fast path"));
		goto abort_fastpath;
	}
#if defined(DUK_USE_FASTINT)
	case DUK_TAG_FASTINT: {
		/* Number serialization has a significant impact relative to
		 * other fast path code, so careful fast path for fastints.
		 */
		duk__enc_fastint_tval(js_ctx, tv);
		break;
	}
#endif
	default: {
		/* XXX: A fast path for usual integers would be useful when
		 * fastint support is not enabled.
		 */
		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));

		/* XXX: Stack discipline is annoying, could be changed in numconv. */
		duk_push_tval(js_ctx->thr, tv);
		duk__enc_double(js_ctx);
		duk_pop(js_ctx->thr);

#if 0
		/* Could also rely on native sprintf(), but it will handle
		 * values like NaN, Infinity, -0, exponent notation etc in
		 * a JSON-incompatible way.
		 */
		duk_double_t d;
		char buf[64];

		DUK_ASSERT(DUK_TVAL_IS_DOUBLE(tv));
		d = DUK_TVAL_GET_DOUBLE(tv);
		DUK_SPRINTF(buf, "%lg", d);
		DUK__EMIT_CSTR(js_ctx, buf);
#endif
	}
	}
	return 1;  /* not undefined */

 emit_undefined:
	return 0;  /* value was undefined/unsupported */

 abort_fastpath:
	/* Error message doesn't matter: the error is ignored anyway. */
	DUK_DD(DUK_DDPRINT("aborting fast path"));
	DUK_ERROR_INTERNAL(js_ctx->thr);
	DUK_WO_NORETURN(return 0;);
}

DUK_LOCAL duk_ret_t duk__json_stringify_fast(duk_hthread *thr, void *udata) {
	duk_json_enc_ctx *js_ctx;
	duk_tval *tv;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(udata != NULL);

	js_ctx = (duk_json_enc_ctx *) udata;
	DUK_ASSERT(js_ctx != NULL);

	tv = DUK_GET_TVAL_NEGIDX(thr, -1);
	if (duk__json_stringify_fast_value(js_ctx, tv) == 0) {
		DUK_DD(DUK_DDPRINT("top level value not supported, fail fast path"));
		DUK_DCERROR_TYPE_INVALID_ARGS(thr);  /* Error message is ignored, so doesn't matter. */
	}

	return 0;
}
#endif  /* DUK_USE_JSON_STRINGIFY_FASTPATH */

/*
 *  Top level wrappers
 */

DUK_INTERNAL
void duk_bi_json_parse_helper(duk_hthread *thr,
                              duk_idx_t idx_value,
                              duk_idx_t idx_reviver,
                              duk_small_uint_t flags) {
	duk_json_dec_ctx js_ctx_alloc;
	duk_json_dec_ctx *js_ctx = &js_ctx_alloc;
	duk_hstring *h_text;
#if defined(DUK_USE_ASSERTIONS)
	duk_idx_t entry_top = duk_get_top(thr);
#endif

	/* negative top-relative indices not allowed now */
	DUK_ASSERT(idx_value == DUK_INVALID_INDEX || idx_value >= 0);
	DUK_ASSERT(idx_reviver == DUK_INVALID_INDEX || idx_reviver >= 0);

	DUK_DDD(DUK_DDDPRINT("JSON parse start: text=%!T, reviver=%!T, flags=0x%08lx, stack_top=%ld",
	                     (duk_tval *) duk_get_tval(thr, idx_value),
	                     (duk_tval *) duk_get_tval(thr, idx_reviver),
	                     (unsigned long) flags,
	                     (long) duk_get_top(thr)));

	duk_memzero(&js_ctx_alloc, sizeof(js_ctx_alloc));
	js_ctx->thr = thr;
#if defined(DUK_USE_EXPLICIT_NULL_INIT)
	/* nothing now */
#endif
	js_ctx->recursion_limit = DUK_USE_JSON_DEC_RECLIMIT;
	DUK_ASSERT(js_ctx->recursion_depth == 0);

	/* Flag handling currently assumes that flags are consistent.  This is OK
	 * because the call sites are now strictly controlled.
	 */

	js_ctx->flags = flags;
#if defined(DUK_USE_JX)
	js_ctx->flag_ext_custom = flags & DUK_JSON_FLAG_EXT_CUSTOM;
#endif
#if defined(DUK_USE_JC)
	js_ctx->flag_ext_compatible = flags & DUK_JSON_FLAG_EXT_COMPATIBLE;
#endif
#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
	js_ctx->flag_ext_custom_or_compatible = flags & (DUK_JSON_FLAG_EXT_CUSTOM | DUK_JSON_FLAG_EXT_COMPATIBLE);
#endif

	h_text = duk_to_hstring(thr, idx_value);  /* coerce in-place; rejects Symbols */
	DUK_ASSERT(h_text != NULL);

	/* JSON parsing code is allowed to read [p_start,p_end]: p_end is
	 * valid and points to the string NUL terminator (which is always
	 * guaranteed for duk_hstrings.
	 */
	js_ctx->p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_text);
	js_ctx->p = js_ctx->p_start;
	js_ctx->p_end = ((const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_text)) +
	                DUK_HSTRING_GET_BYTELEN(h_text);
	DUK_ASSERT(*(js_ctx->p_end) == 0x00);

	duk__dec_value(js_ctx);  /* -> [ ... value ] */

	/* Trailing whitespace has been eaten by duk__dec_value(), so if
	 * we're not at end of input here, it's a SyntaxError.
	 */

	if (js_ctx->p != js_ctx->p_end) {
		duk__dec_syntax_error(js_ctx);
	}

	if (duk_is_callable(thr, idx_reviver)) {
		DUK_DDD(DUK_DDDPRINT("applying reviver: %!T",
		                     (duk_tval *) duk_get_tval(thr, idx_reviver)));

		js_ctx->idx_reviver = idx_reviver;

		duk_push_object(thr);
		duk_dup_m2(thr);  /* -> [ ... val root val ] */
		duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_EMPTY_STRING);  /* default attrs ok */
		duk_push_hstring_stridx(thr, DUK_STRIDX_EMPTY_STRING);  /* -> [ ... val root "" ] */

		DUK_DDD(DUK_DDDPRINT("start reviver walk, root=%!T, name=%!T",
		                     (duk_tval *) duk_get_tval(thr, -2),
		                     (duk_tval *) duk_get_tval(thr, -1)));

		duk__dec_reviver_walk(js_ctx);  /* [ ... val root "" ] -> [ ... val val' ] */
		duk_remove_m2(thr);             /* -> [ ... val' ] */
	} else {
		DUK_DDD(DUK_DDDPRINT("reviver does not exist or is not callable: %!T",
		                     (duk_tval *) duk_get_tval(thr, idx_reviver)));
	}

	/* Final result is at stack top. */

	DUK_DDD(DUK_DDDPRINT("JSON parse end: text=%!T, reviver=%!T, flags=0x%08lx, result=%!T, stack_top=%ld",
	                     (duk_tval *) duk_get_tval(thr, idx_value),
	                     (duk_tval *) duk_get_tval(thr, idx_reviver),
	                     (unsigned long) flags,
	                     (duk_tval *) duk_get_tval(thr, -1),
	                     (long) duk_get_top(thr)));

	DUK_ASSERT(duk_get_top(thr) == entry_top + 1);
}

DUK_INTERNAL
void duk_bi_json_stringify_helper(duk_hthread *thr,
                                  duk_idx_t idx_value,
                                  duk_idx_t idx_replacer,
                                  duk_idx_t idx_space,
                                  duk_small_uint_t flags) {
	duk_json_enc_ctx js_ctx_alloc;
	duk_json_enc_ctx *js_ctx = &js_ctx_alloc;
	duk_hobject *h;
	duk_idx_t idx_holder;
	duk_idx_t entry_top;

	/* negative top-relative indices not allowed now */
	DUK_ASSERT(idx_value == DUK_INVALID_INDEX || idx_value >= 0);
	DUK_ASSERT(idx_replacer == DUK_INVALID_INDEX || idx_replacer >= 0);
	DUK_ASSERT(idx_space == DUK_INVALID_INDEX || idx_space >= 0);

	DUK_DDD(DUK_DDDPRINT("JSON stringify start: value=%!T, replacer=%!T, space=%!T, flags=0x%08lx, stack_top=%ld",
	                     (duk_tval *) duk_get_tval(thr, idx_value),
	                     (duk_tval *) duk_get_tval(thr, idx_replacer),
	                     (duk_tval *) duk_get_tval(thr, idx_space),
	                     (unsigned long) flags,
	                     (long) duk_get_top(thr)));

	entry_top = duk_get_top(thr);

	/*
	 *  Context init
	 */

	duk_memzero(&js_ctx_alloc, sizeof(js_ctx_alloc));
	js_ctx->thr = thr;
#if defined(DUK_USE_EXPLICIT_NULL_INIT)
	js_ctx->h_replacer = NULL;
	js_ctx->h_gap = NULL;
#endif
	js_ctx->idx_proplist = -1;

	/* Flag handling currently assumes that flags are consistent.  This is OK
	 * because the call sites are now strictly controlled.
	 */

	js_ctx->flags = flags;
	js_ctx->flag_ascii_only = flags & DUK_JSON_FLAG_ASCII_ONLY;
	js_ctx->flag_avoid_key_quotes = flags & DUK_JSON_FLAG_AVOID_KEY_QUOTES;
#if defined(DUK_USE_JX)
	js_ctx->flag_ext_custom = flags & DUK_JSON_FLAG_EXT_CUSTOM;
#endif
#if defined(DUK_USE_JC)
	js_ctx->flag_ext_compatible = flags & DUK_JSON_FLAG_EXT_COMPATIBLE;
#endif
#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
	js_ctx->flag_ext_custom_or_compatible = flags & (DUK_JSON_FLAG_EXT_CUSTOM | DUK_JSON_FLAG_EXT_COMPATIBLE);
#endif

	/* The #if defined() clutter here handles the JX/JC enable/disable
	 * combinations properly.
	 */
#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
	js_ctx->stridx_custom_undefined = DUK_STRIDX_LC_NULL;  /* standard JSON; array gaps */
#if defined(DUK_USE_JX)
	if (flags & DUK_JSON_FLAG_EXT_CUSTOM) {
		js_ctx->stridx_custom_undefined = DUK_STRIDX_LC_UNDEFINED;
		js_ctx->stridx_custom_nan = DUK_STRIDX_NAN;
		js_ctx->stridx_custom_neginf = DUK_STRIDX_MINUS_INFINITY;
		js_ctx->stridx_custom_posinf = DUK_STRIDX_INFINITY;
		js_ctx->stridx_custom_function =
		        (flags & DUK_JSON_FLAG_AVOID_KEY_QUOTES) ?
		                DUK_STRIDX_JSON_EXT_FUNCTION2 :
		                DUK_STRIDX_JSON_EXT_FUNCTION1;
	}
#endif  /* DUK_USE_JX */
#if defined(DUK_USE_JX) && defined(DUK_USE_JC)
	else
#endif  /* DUK_USE_JX && DUK_USE_JC */
#if defined(DUK_USE_JC)
	if (js_ctx->flags & DUK_JSON_FLAG_EXT_COMPATIBLE) {
		js_ctx->stridx_custom_undefined = DUK_STRIDX_JSON_EXT_UNDEFINED;
		js_ctx->stridx_custom_nan = DUK_STRIDX_JSON_EXT_NAN;
		js_ctx->stridx_custom_neginf = DUK_STRIDX_JSON_EXT_NEGINF;
		js_ctx->stridx_custom_posinf = DUK_STRIDX_JSON_EXT_POSINF;
		js_ctx->stridx_custom_function = DUK_STRIDX_JSON_EXT_FUNCTION1;
	}
#endif  /* DUK_USE_JC */
#endif  /* DUK_USE_JX || DUK_USE_JC */

#if defined(DUK_USE_JX) || defined(DUK_USE_JC)
	if (js_ctx->flags & (DUK_JSON_FLAG_EXT_CUSTOM |
	                     DUK_JSON_FLAG_EXT_COMPATIBLE)) {
		DUK_ASSERT(js_ctx->mask_for_undefined == 0);  /* already zero */
	}
	else
#endif  /* DUK_USE_JX || DUK_USE_JC */
	{
		/* Plain buffer is treated like ArrayBuffer and serialized.
		 * Lightfuncs are treated like objects, but JSON explicitly
		 * skips serializing Function objects so we can just reject
		 * lightfuncs here.
		 */
		js_ctx->mask_for_undefined = DUK_TYPE_MASK_UNDEFINED |
		                             DUK_TYPE_MASK_POINTER |
		                             DUK_TYPE_MASK_LIGHTFUNC;
	}

	DUK_BW_INIT_PUSHBUF(thr, &js_ctx->bw, DUK__JSON_STRINGIFY_BUFSIZE);

	js_ctx->idx_loop = duk_push_bare_object(thr);
	DUK_ASSERT(js_ctx->idx_loop >= 0);

	/* [ ... buf loop ] */

	/*
	 *  Process replacer/proplist (2nd argument to JSON.stringify)
	 */

	h = duk_get_hobject(thr, idx_replacer);
	if (h != NULL) {
		if (DUK_HOBJECT_IS_CALLABLE(h)) {
			js_ctx->h_replacer = h;
		} else if (duk_js_isarray_hobject(h)) {
			/* Here the specification requires correct array index enumeration
			 * which is a bit tricky for sparse arrays (it is handled by the
			 * enum setup code).  We now enumerate ancestors too, although the
			 * specification is not very clear on whether that is required.
			 */

			duk_uarridx_t plist_idx = 0;
			duk_small_uint_t enum_flags;

			js_ctx->idx_proplist = duk_push_array(thr);  /* XXX: array internal? */

			enum_flags = DUK_ENUM_ARRAY_INDICES_ONLY |
			             DUK_ENUM_SORT_ARRAY_INDICES;  /* expensive flag */
			duk_enum(thr, idx_replacer, enum_flags);
			while (duk_next(thr, -1 /*enum_index*/, 1 /*get_value*/)) {
				/* [ ... proplist enum_obj key val ] */
				if (duk__enc_allow_into_proplist(duk_get_tval(thr, -1))) {
					/* XXX: duplicates should be eliminated here */
					DUK_DDD(DUK_DDDPRINT("proplist enum: key=%!T, val=%!T --> accept",
					                     (duk_tval *) duk_get_tval(thr, -2),
					                     (duk_tval *) duk_get_tval(thr, -1)));
					duk_to_string(thr, -1);  /* extra coercion of strings is OK */
					duk_put_prop_index(thr, -4, plist_idx);  /* -> [ ... proplist enum_obj key ] */
					plist_idx++;
					duk_pop(thr);
				} else {
					DUK_DDD(DUK_DDDPRINT("proplist enum: key=%!T, val=%!T --> reject",
					                     (duk_tval *) duk_get_tval(thr, -2),
					                     (duk_tval *) duk_get_tval(thr, -1)));
					duk_pop_2(thr);
				}
                        }
                        duk_pop(thr);  /* pop enum */

			/* [ ... proplist ] */
		}
	}

	/* [ ... buf loop (proplist) ] */

	/*
	 *  Process space (3rd argument to JSON.stringify)
	 */

	h = duk_get_hobject(thr, idx_space);
	if (h != NULL) {
		duk_small_uint_t c = DUK_HOBJECT_GET_CLASS_NUMBER(h);
		if (c == DUK_HOBJECT_CLASS_NUMBER) {
			duk_to_number(thr, idx_space);
		} else if (c == DUK_HOBJECT_CLASS_STRING) {
			duk_to_string(thr, idx_space);
		}
	}

	if (duk_is_number(thr, idx_space)) {
		duk_small_int_t nspace;
		/* spaces[] must be static to allow initializer with old compilers like BCC */
		static const char spaces[10] = {
			DUK_ASC_SPACE, DUK_ASC_SPACE, DUK_ASC_SPACE, DUK_ASC_SPACE,
			DUK_ASC_SPACE, DUK_ASC_SPACE, DUK_ASC_SPACE, DUK_ASC_SPACE,
			DUK_ASC_SPACE, DUK_ASC_SPACE
		};  /* XXX: helper */

		/* ToInteger() coercion; NaN -> 0, infinities are clamped to 0 and 10 */
		nspace = (duk_small_int_t) duk_to_int_clamped(thr, idx_space, 0 /*minval*/, 10 /*maxval*/);
		DUK_ASSERT(nspace >= 0 && nspace <= 10);

		duk_push_lstring(thr, spaces, (duk_size_t) nspace);
		js_ctx->h_gap = duk_known_hstring(thr, -1);
		DUK_ASSERT(js_ctx->h_gap != NULL);
	} else if (duk_is_string_notsymbol(thr, idx_space)) {
		duk_dup(thr, idx_space);
		duk_substring(thr, -1, 0, 10);  /* clamp to 10 chars */
		js_ctx->h_gap = duk_known_hstring(thr, -1);
	} else {
		/* nop */
	}

	if (js_ctx->h_gap != NULL) {
		/* If gap is empty, behave as if not given at all.  Check
		 * against byte length because character length is more
		 * expensive.
		 */
		if (DUK_HSTRING_GET_BYTELEN(js_ctx->h_gap) == 0) {
			js_ctx->h_gap = NULL;
		}
	}

	/* [ ... buf loop (proplist) (gap) ] */

	/*
	 *  Fast path: assume no mutation, iterate object property tables
	 *  directly; bail out if that assumption doesn't hold.
	 */

#if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
	if (js_ctx->h_replacer == NULL &&  /* replacer is a mutation risk */
	    js_ctx->idx_proplist == -1) {  /* proplist is very rare */
		duk_int_t pcall_rc;
		duk_small_uint_t prev_ms_base_flags;

		DUK_DD(DUK_DDPRINT("try JSON.stringify() fast path"));

		/* Use recursion_limit to ensure we don't overwrite js_ctx->visiting[]
		 * array so we don't need two counter checks in the fast path.  The
		 * slow path has a much larger recursion limit which we'll use if
		 * necessary.
		 */
		DUK_ASSERT(DUK_USE_JSON_ENC_RECLIMIT >= DUK_JSON_ENC_LOOPARRAY);
		js_ctx->recursion_limit = DUK_JSON_ENC_LOOPARRAY;
		DUK_ASSERT(js_ctx->recursion_depth == 0);

		/* Execute the fast path in a protected call.  If any error is thrown,
		 * fall back to the slow path.  This includes e.g. recursion limit
		 * because the fast path has a smaller recursion limit (and simpler,
		 * limited loop detection).
		 */

		duk_dup(thr, idx_value);

		/* Must prevent finalizers which may have arbitrary side effects. */
		prev_ms_base_flags = thr->heap->ms_base_flags;
		thr->heap->ms_base_flags |=
		        DUK_MS_FLAG_NO_OBJECT_COMPACTION;      /* Avoid attempt to compact any objects. */
		thr->heap->pf_prevent_count++;                 /* Prevent finalizers. */
		DUK_ASSERT(thr->heap->pf_prevent_count != 0);  /* Wrap. */

		pcall_rc = duk_safe_call(thr, duk__json_stringify_fast, (void *) js_ctx /*udata*/, 1 /*nargs*/, 0 /*nret*/);

		DUK_ASSERT(thr->heap->pf_prevent_count > 0);
		thr->heap->pf_prevent_count--;
		thr->heap->ms_base_flags = prev_ms_base_flags;

		if (pcall_rc == DUK_EXEC_SUCCESS) {
			DUK_DD(DUK_DDPRINT("fast path successful"));
			DUK_BW_PUSH_AS_STRING(thr, &js_ctx->bw);
			goto replace_finished;
		}

		/* We come here for actual aborts (like encountering .toJSON())
		 * but also for recursion/loop errors.  Bufwriter size can be
		 * kept because we'll probably need at least as much as we've
		 * allocated so far.
		 */
		DUK_D(DUK_DPRINT("fast path failed, serialize using slow path instead"));
		DUK_BW_RESET_SIZE(thr, &js_ctx->bw);
		js_ctx->recursion_depth = 0;
	}
#endif

	/*
	 *  Create wrapper object and serialize
	 */

	idx_holder = duk_push_object(thr);
	duk_dup(thr, idx_value);
	duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_EMPTY_STRING);

	DUK_DDD(DUK_DDDPRINT("before: flags=0x%08lx, loop=%!T, replacer=%!O, "
	                     "proplist=%!T, gap=%!O, holder=%!T",
	                     (unsigned long) js_ctx->flags,
	                     (duk_tval *) duk_get_tval(thr, js_ctx->idx_loop),
	                     (duk_heaphdr *) js_ctx->h_replacer,
	                     (duk_tval *) (js_ctx->idx_proplist >= 0 ? duk_get_tval(thr, js_ctx->idx_proplist) : NULL),
	                     (duk_heaphdr *) js_ctx->h_gap,
	                     (duk_tval *) duk_get_tval(thr, -1)));

	/* serialize the wrapper with empty string key */

	duk_push_hstring_empty(thr);

	/* [ ... buf loop (proplist) (gap) holder "" ] */

	js_ctx->recursion_limit = DUK_USE_JSON_ENC_RECLIMIT;
	DUK_ASSERT(js_ctx->recursion_depth == 0);

	if (DUK_UNLIKELY(duk__enc_value(js_ctx, idx_holder) == 0)) {  /* [ ... holder key ] -> [ ... holder ] */
		/* Result is undefined. */
		duk_push_undefined(thr);
	} else {
		/* Convert buffer to result string. */
		DUK_BW_PUSH_AS_STRING(thr, &js_ctx->bw);
	}

	DUK_DDD(DUK_DDDPRINT("after: flags=0x%08lx, loop=%!T, replacer=%!O, "
	                     "proplist=%!T, gap=%!O, holder=%!T",
	                     (unsigned long) js_ctx->flags,
	                     (duk_tval *) duk_get_tval(thr, js_ctx->idx_loop),
	                     (duk_heaphdr *) js_ctx->h_replacer,
	                     (duk_tval *) (js_ctx->idx_proplist >= 0 ? duk_get_tval(thr, js_ctx->idx_proplist) : NULL),
	                     (duk_heaphdr *) js_ctx->h_gap,
	                     (duk_tval *) duk_get_tval(thr, idx_holder)));

	/* The stack has a variable shape here, so force it to the
	 * desired one explicitly.
	 */

#if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
 replace_finished:
#endif
	duk_replace(thr, entry_top);
	duk_set_top(thr, entry_top + 1);

	DUK_DDD(DUK_DDDPRINT("JSON stringify end: value=%!T, replacer=%!T, space=%!T, "
	                     "flags=0x%08lx, result=%!T, stack_top=%ld",
	                     (duk_tval *) duk_get_tval(thr, idx_value),
	                     (duk_tval *) duk_get_tval(thr, idx_replacer),
	                     (duk_tval *) duk_get_tval(thr, idx_space),
	                     (unsigned long) flags,
	                     (duk_tval *) duk_get_tval(thr, -1),
	                     (long) duk_get_top(thr)));

	DUK_ASSERT(duk_get_top(thr) == entry_top + 1);
}

#if defined(DUK_USE_JSON_BUILTIN)

/*
 *  Entry points
 */

DUK_INTERNAL duk_ret_t duk_bi_json_object_parse(duk_hthread *thr) {
	duk_bi_json_parse_helper(thr,
	                         0 /*idx_value*/,
	                         1 /*idx_replacer*/,
	                         0 /*flags*/);
	return 1;
}

DUK_INTERNAL duk_ret_t duk_bi_json_object_stringify(duk_hthread *thr) {
	duk_bi_json_stringify_helper(thr,
	                             0 /*idx_value*/,
	                             1 /*idx_replacer*/,
	                             2 /*idx_space*/,
	                             0 /*flags*/);
	return 1;
}

#endif  /* DUK_USE_JSON_BUILTIN */

#endif  /* DUK_USE_JSON_SUPPORT */

/* automatic undefs */
#undef DUK__EMIT_1
#undef DUK__EMIT_2
#undef DUK__EMIT_CSTR
#undef DUK__EMIT_HSTR
#undef DUK__EMIT_STRIDX
#undef DUK__JSON_DECSTR_BUFSIZE
#undef DUK__JSON_DECSTR_CHUNKSIZE
#undef DUK__JSON_ENCSTR_CHUNKSIZE
#undef DUK__JSON_MAX_ESC_LEN
#undef DUK__JSON_STRINGIFY_BUFSIZE
#undef DUK__MKESC
#undef DUK__UNEMIT_1
#line 1 "duk_bi_math.c"
/*
 *  Math built-ins
 */

/* #include duk_internal.h -> already included */

#if defined(DUK_USE_MATH_BUILTIN)

/*
 *  Use static helpers which can work with math.h functions matching
 *  the following signatures. This is not portable if any of these math
 *  functions is actually a macro.
 *
 *  Typing here is intentionally 'double' wherever values interact with
 *  the standard library APIs.
 */

typedef double (*duk__one_arg_func)(double);
typedef double (*duk__two_arg_func)(double, double);

DUK_LOCAL duk_ret_t duk__math_minmax(duk_hthread *thr, duk_double_t initial, duk__two_arg_func min_max) {
	duk_idx_t n = duk_get_top(thr);
	duk_idx_t i;
	duk_double_t res = initial;
	duk_double_t t;

	/*
	 *  Note: fmax() does not match the E5 semantics.  E5 requires
	 *  that if -any- input to Math.max() is a NaN, the result is a
	 *  NaN.  fmax() will return a NaN only if -both- inputs are NaN.
	 *  Same applies to fmin().
	 *
	 *  Note: every input value must be coerced with ToNumber(), even
	 *  if we know the result will be a NaN anyway: ToNumber() may have
	 *  side effects for which even order of evaluation matters.
	 */

	for (i = 0; i < n; i++) {
		t = duk_to_number(thr, i);
		if (DUK_FPCLASSIFY(t) == DUK_FP_NAN || DUK_FPCLASSIFY(res) == DUK_FP_NAN) {
			/* Note: not normalized, but duk_push_number() will normalize */
			res = (duk_double_t) DUK_DOUBLE_NAN;
		} else {
			res = (duk_double_t) min_max(res, (double) t);
		}
	}

	duk_push_number(thr, res);
	return 1;
}

DUK_LOCAL double duk__fmin_fixed(double x, double y) {
	/* fmin() with args -0 and +0 is not guaranteed to return
	 * -0 as ECMAScript requires.
	 */
	if (duk_double_equals(x, 0.0) && duk_double_equals(y, 0.0)) {
		duk_double_union du1, du2;
		du1.d = x;
		du2.d = y;

		/* Already checked to be zero so these must hold, and allow us
		 * to check for "x is -0 or y is -0" by ORing the high parts
		 * for comparison.
		 */
		DUK_ASSERT(du1.ui[DUK_DBL_IDX_UI0] == 0 || du1.ui[DUK_DBL_IDX_UI0] == 0x80000000UL);
		DUK_ASSERT(du2.ui[DUK_DBL_IDX_UI0] == 0 || du2.ui[DUK_DBL_IDX_UI0] == 0x80000000UL);

		/* XXX: what's the safest way of creating a negative zero? */
		if ((du1.ui[DUK_DBL_IDX_UI0] | du2.ui[DUK_DBL_IDX_UI0]) != 0) {
			/* Enter here if either x or y (or both) is -0. */
			return -0.0;
		} else {
			return +0.0;
		}
	}
	return duk_double_fmin(x, y);
}

DUK_LOCAL double duk__fmax_fixed(double x, double y) {
	/* fmax() with args -0 and +0 is not guaranteed to return
	 * +0 as ECMAScript requires.
	 */
	if (duk_double_equals(x, 0.0) && duk_double_equals(y, 0.0)) {
		if (DUK_SIGNBIT(x) == 0 || DUK_SIGNBIT(y) == 0) {
			return +0.0;
		} else {
			return -0.0;
		}
	}
	return duk_double_fmax(x, y);
}

#if defined(DUK_USE_ES6)
DUK_LOCAL double duk__cbrt(double x) {
	/* cbrt() is C99.  To avoid hassling embedders with the need to provide a
	 * cube root function, we can get by with pow().  The result is not
	 * identical, but that's OK: ES2015 says it's implementation-dependent.
	 */

#if defined(DUK_CBRT)
	/* cbrt() matches ES2015 requirements. */
	return DUK_CBRT(x);
#else
	duk_small_int_t c = (duk_small_int_t) DUK_FPCLASSIFY(x);

	/* pow() does not, however. */
	if (c == DUK_FP_NAN || c == DUK_FP_INFINITE || c == DUK_FP_ZERO) {
		return x;
	}
	if (DUK_SIGNBIT(x)) {
		return -DUK_POW(-x, 1.0 / 3.0);
	} else {
		return DUK_POW(x, 1.0 / 3.0);
	}
#endif
}

DUK_LOCAL double duk__log2(double x) {
#if defined(DUK_LOG2)
	return DUK_LOG2(x);
#else
	return DUK_LOG(x) * DUK_DOUBLE_LOG2E;
#endif
}

DUK_LOCAL double duk__log10(double x) {
#if defined(DUK_LOG10)
	return DUK_LOG10(x);
#else
	return DUK_LOG(x) * DUK_DOUBLE_LOG10E;
#endif
}

DUK_LOCAL double duk__trunc(double x) {
#if defined(DUK_TRUNC)
	return DUK_TRUNC(x);
#else
	/* Handles -0 correctly: -0.0 matches 'x >= 0.0' but floor()
	 * is required to return -0 when the argument is -0.
	 */
	return x >= 0.0 ? DUK_FLOOR(x) : DUK_CEIL(x);
#endif
}
#endif  /* DUK_USE_ES6 */

DUK_LOCAL double duk__round_fixed(double x) {
	/* Numbers half-way between integers must be rounded towards +Infinity,
	 * e.g. -3.5 must be rounded to -3 (not -4).  When rounded to zero, zero
	 * sign must be set appropriately.  E5.1 Section 15.8.2.15.
	 *
	 * Note that ANSI C round() is "round to nearest integer, away from zero",
	 * which is incorrect for negative values.  Here we make do with floor().
	 */

	duk_small_int_t c = (duk_small_int_t) DUK_FPCLASSIFY(x);
	if (c == DUK_FP_NAN || c == DUK_FP_INFINITE || c == DUK_FP_ZERO) {
		return x;
	}

	/*
	 *  x is finite and non-zero
	 *
	 *  -1.6 -> floor(-1.1) -> -2
	 *  -1.5 -> floor(-1.0) -> -1  (towards +Inf)
	 *  -1.4 -> floor(-0.9) -> -1
	 *  -0.5 -> -0.0               (special case)
	 *  -0.1 -> -0.0               (special case)
	 *  +0.1 -> +0.0               (special case)
	 *  +0.5 -> floor(+1.0) -> 1   (towards +Inf)
	 *  +1.4 -> floor(+1.9) -> 1
	 *  +1.5 -> floor(+2.0) -> 2   (towards +Inf)
	 *  +1.6 -> floor(+2.1) -> 2
	 */

	if (x >= -0.5 && x < 0.5) {
		/* +0.5 is handled by floor, this is on purpose */
		if (x < 0.0) {
			return -0.0;
		} else {
			return +0.0;
		}
	}

	return DUK_FLOOR(x + 0.5);
}

/* Wrappers for calling standard math library methods.  These may be required
 * on platforms where one or more of the math built-ins are defined as macros
 * or inline functions and are thus not suitable to be used as function pointers.
 */
#if defined(DUK_USE_AVOID_PLATFORM_FUNCPTRS)
DUK_LOCAL double duk__fabs(double x) {
	return DUK_FABS(x);
}
DUK_LOCAL double duk__acos(double x) {
	return DUK_ACOS(x);
}
DUK_LOCAL double duk__asin(double x) {
	return DUK_ASIN(x);
}
DUK_LOCAL double duk__atan(double x) {
	return DUK_ATAN(x);
}
DUK_LOCAL double duk__ceil(double x) {
	return DUK_CEIL(x);
}
DUK_LOCAL double duk__cos(double x) {
	return DUK_COS(x);
}
DUK_LOCAL double duk__exp(double x) {
	return DUK_EXP(x);
}
DUK_LOCAL double duk__floor(double x) {
	return DUK_FLOOR(x);
}
DUK_LOCAL double duk__log(double x) {
	return DUK_LOG(x);
}
DUK_LOCAL double duk__sin(double x) {
	return DUK_SIN(x);
}
DUK_LOCAL double duk__sqrt(double x) {
	return DUK_SQRT(x);
}
DUK_LOCAL double duk__tan(double x) {
	return DUK_TAN(x);
}
DUK_LOCAL double duk__atan2_fixed(double x, double y) {
#if defined(DUK_USE_ATAN2_WORKAROUNDS)
	/* Specific fixes to common atan2() implementation issues:
	 * - test-bug-mingw-math-issues.js
	 */
	if (DUK_ISINF(x) && DUK_ISINF(y)) {
		if (DUK_SIGNBIT(x)) {
			if (DUK_SIGNBIT(y)) {
				return -2.356194490192345;
			} else {
				return -0.7853981633974483;
			}
		} else {
			if (DUK_SIGNBIT(y)) {
				return 2.356194490192345;
			} else {
				return 0.7853981633974483;
			}
		}
	}
#else
	/* Some ISO C assumptions. */

	DUK_ASSERT(duk_double_equals(DUK_ATAN2(DUK_DOUBLE_INFINITY, DUK_DOUBLE_INFINITY), 0.7853981633974483));
	DUK_ASSERT(duk_double_equals(DUK_ATAN2(-DUK_DOUBLE_INFINITY, DUK_DOUBLE_INFINITY), -0.7853981633974483));
	DUK_ASSERT(duk_double_equals(DUK_ATAN2(DUK_DOUBLE_INFINITY, -DUK_DOUBLE_INFINITY), 2.356194490192345));
	DUK_ASSERT(duk_double_equals(DUK_ATAN2(-DUK_DOUBLE_INFINITY, -DUK_DOUBLE_INFINITY), -2.356194490192345));
#endif

	return DUK_ATAN2(x, y);
}
#endif  /* DUK_USE_AVOID_PLATFORM_FUNCPTRS */

/* order must match constants in genbuiltins.py */
DUK_LOCAL const duk__one_arg_func duk__one_arg_funcs[] = {
#if defined(DUK_USE_AVOID_PLATFORM_FUNCPTRS)
	duk__fabs,
	duk__acos,
	duk__asin,
	duk__atan,
	duk__ceil,
	duk__cos,
	duk__exp,
	duk__floor,
	duk__log,
	duk__round_fixed,
	duk__sin,
	duk__sqrt,
	duk__tan,
#if defined(DUK_USE_ES6)
	duk__cbrt,
	duk__log2,
	duk__log10,
	duk__trunc
#endif
#else  /* DUK_USE_AVOID_PLATFORM_FUNCPTRS */
	DUK_FABS,
	DUK_ACOS,
	DUK_ASIN,
	DUK_ATAN,
	DUK_CEIL,
	DUK_COS,
	DUK_EXP,
	DUK_FLOOR,
	DUK_LOG,
	duk__round_fixed,
	DUK_SIN,
	DUK_SQRT,
	DUK_TAN,
#if defined(DUK_USE_ES6)
	duk__cbrt,
	duk__log2,
	duk__log10,
	duk__trunc
#endif
#endif  /* DUK_USE_AVOID_PLATFORM_FUNCPTRS */
};

/* order must match constants in genbuiltins.py */
DUK_LOCAL const duk__two_arg_func duk__two_arg_funcs[] = {
#if defined(DUK_USE_AVOID_PLATFORM_FUNCPTRS)
	duk__atan2_fixed,
	duk_js_arith_pow
#else
	duk__atan2_fixed,
	duk_js_arith_pow
#endif
};

DUK_INTERNAL duk_ret_t duk_bi_math_object_onearg_shared(duk_hthread *thr) {
	duk_small_int_t fun_idx = duk_get_current_magic(thr);
	duk__one_arg_func fun;
	duk_double_t arg1;

	DUK_ASSERT(fun_idx >= 0);
	DUK_ASSERT(fun_idx < (duk_small_int_t) (sizeof(duk__one_arg_funcs) / sizeof(duk__one_arg_func)));
	arg1 = duk_to_number(thr, 0);
	fun = duk__one_arg_funcs[fun_idx];
	duk_push_number(thr, (duk_double_t) fun((double) arg1));
	return 1;
}

DUK_INTERNAL duk_ret_t duk_bi_math_object_twoarg_shared(duk_hthread *thr) {
	duk_small_int_t fun_idx = duk_get_current_magic(thr);
	duk__two_arg_func fun;
	duk_double_t arg1;
	duk_double_t arg2;

	DUK_ASSERT(fun_idx >= 0);
	DUK_ASSERT(fun_idx < (duk_small_int_t) (sizeof(duk__two_arg_funcs) / sizeof(duk__two_arg_func)));
	arg1 = duk_to_number(thr, 0);  /* explicit ordered evaluation to match coercion semantics */
	arg2 = duk_to_number(thr, 1);
	fun = duk__two_arg_funcs[fun_idx];
	duk_push_number(thr, (duk_double_t) fun((double) arg1, (double) arg2));
	return 1;
}

DUK_INTERNAL duk_ret_t duk_bi_math_object_max(duk_hthread *thr) {
	return duk__math_minmax(thr, -DUK_DOUBLE_INFINITY, duk__fmax_fixed);
}

DUK_INTERNAL duk_ret_t duk_bi_math_object_min(duk_hthread *thr) {
	return duk__math_minmax(thr, DUK_DOUBLE_INFINITY, duk__fmin_fixed);
}

DUK_INTERNAL duk_ret_t duk_bi_math_object_random(duk_hthread *thr) {
	duk_push_number(thr, (duk_double_t) DUK_UTIL_GET_RANDOM_DOUBLE(thr));
	return 1;
}

#if defined(DUK_USE_ES6)
DUK_INTERNAL duk_ret_t duk_bi_math_object_hypot(duk_hthread *thr) {
	/*
	 *  E6 Section 20.2.2.18: Math.hypot
	 *
	 *  - If no arguments are passed, the result is +0.
	 *  - If any argument is +inf, the result is +inf.
	 *  - If any argument is -inf, the result is +inf.
	 *  - If no argument is +inf or -inf, and any argument is NaN, the result is
	 *    NaN.
	 *  - If all arguments are either +0 or -0, the result is +0.
	 */

	duk_idx_t nargs;
	duk_idx_t i;
	duk_bool_t found_nan;
	duk_double_t max;
	duk_double_t sum, summand;
	duk_double_t comp, prelim;
	duk_double_t t;

	nargs = duk_get_top(thr);

	/* Find the highest value.  Also ToNumber() coerces. */
	max = 0.0;
	found_nan = 0;
	for (i = 0; i < nargs; i++) {
		t = DUK_FABS(duk_to_number(thr, i));
		if (DUK_FPCLASSIFY(t) == DUK_FP_NAN) {
			found_nan = 1;
		} else {
			max = duk_double_fmax(max, t);
		}
	}

	/* Early return cases. */
	if (duk_double_equals(max, DUK_DOUBLE_INFINITY)) {
		duk_push_number(thr, DUK_DOUBLE_INFINITY);
		return 1;
	} else if (found_nan) {
		duk_push_number(thr, DUK_DOUBLE_NAN);
		return 1;
	} else if (duk_double_equals(max, 0.0)) {
		duk_push_number(thr, 0.0);
		/* Otherwise we'd divide by zero. */
		return 1;
	}

	/* Use Kahan summation and normalize to the highest value to minimize
	 * floating point rounding error and avoid overflow.
	 *
	 * https://en.wikipedia.org/wiki/Kahan_summation_algorithm
	 */
	sum = 0.0;
	comp = 0.0;
	for (i = 0; i < nargs; i++) {
		t = DUK_FABS(duk_get_number(thr, i)) / max;
		summand = (t * t) - comp;
		prelim = sum + summand;
		comp = (prelim - sum) - summand;
		sum = prelim;
	}

	duk_push_number(thr, (duk_double_t) DUK_SQRT(sum) * max);
	return 1;
}
#endif  /* DUK_USE_ES6 */

#if defined(DUK_USE_ES6)
DUK_INTERNAL duk_ret_t duk_bi_math_object_sign(duk_hthread *thr) {
	duk_double_t d;

	d = duk_to_number(thr, 0);
	if (duk_double_is_nan(d)) {
		DUK_ASSERT(duk_is_nan(thr, -1));
		return 1;  /* NaN input -> return NaN */
	}
	if (duk_double_equals(d, 0.0)) {
		/* Zero sign kept, i.e. -0 -> -0, +0 -> +0. */
		return 1;
	}
	duk_push_int(thr, (d > 0.0 ? 1 : -1));
	return 1;
}
#endif  /* DUK_USE_ES6 */

#if defined(DUK_USE_ES6)
DUK_INTERNAL duk_ret_t duk_bi_math_object_clz32(duk_hthread *thr) {
	duk_uint32_t x;
	duk_small_uint_t i;

#if defined(DUK_USE_PREFER_SIZE)
	duk_uint32_t mask;

	x = duk_to_uint32(thr, 0);
	for (i = 0, mask = 0x80000000UL; mask != 0; mask >>= 1) {
		if (x & mask) {
			break;
		}
		i++;
	}
	DUK_ASSERT(i <= 32);
	duk_push_uint(thr, i);
	return 1;
#else  /* DUK_USE_PREFER_SIZE */
	i = 0;
	x = duk_to_uint32(thr, 0);
	if (x & 0xffff0000UL) {
		x >>= 16;
	} else {
		i += 16;
	}
	if (x & 0x0000ff00UL) {
		x >>= 8;
	} else {
		i += 8;
	}
	if (x & 0x000000f0UL) {
		x >>= 4;
	} else {
		i += 4;
	}
	if (x & 0x0000000cUL) {
		x >>= 2;
	} else {
		i += 2;
	}
	if (x & 0x00000002UL) {
		x >>= 1;
	} else {
		i += 1;
	}
	if (x & 0x00000001UL) {
		;
	} else {
		i += 1;
	}
	DUK_ASSERT(i <= 32);
	duk_push_uint(thr, i);
	return 1;
#endif  /* DUK_USE_PREFER_SIZE */
}
#endif  /* DUK_USE_ES6 */

#if defined(DUK_USE_ES6)
DUK_INTERNAL duk_ret_t duk_bi_math_object_imul(duk_hthread *thr) {
	duk_uint32_t x, y, z;

	x = duk_to_uint32(thr, 0);
	y = duk_to_uint32(thr, 1);
	z = x * y;

	/* While arguments are ToUint32() coerced and the multiplication
	 * is unsigned as such, the final result is curiously interpreted
	 * as a signed 32-bit value.
	 */
	duk_push_i32(thr, (duk_int32_t) z);
	return 1;
}
#endif  /* DUK_USE_ES6 */

#endif  /* DUK_USE_MATH_BUILTIN */
#line 1 "duk_bi_number.c"
/*
 *  Number built-ins
 */

/* #include duk_internal.h -> already included */

#if defined(DUK_USE_NUMBER_BUILTIN)

DUK_LOCAL duk_double_t duk__push_this_number_plain(duk_hthread *thr) {
	duk_hobject *h;

	/* Number built-in accepts a plain number or a Number object (whose
	 * internal value is operated on).  Other types cause TypeError.
	 */

	duk_push_this(thr);
	if (duk_is_number(thr, -1)) {
		DUK_DDD(DUK_DDDPRINT("plain number value: %!T", (duk_tval *) duk_get_tval(thr, -1)));
		goto done;
	}
	h = duk_get_hobject(thr, -1);
	if (!h ||
	    (DUK_HOBJECT_GET_CLASS_NUMBER(h) != DUK_HOBJECT_CLASS_NUMBER)) {
		DUK_DDD(DUK_DDDPRINT("unacceptable this value: %!T", (duk_tval *) duk_get_tval(thr, -1)));
		DUK_ERROR_TYPE(thr, "number expected");
		DUK_WO_NORETURN(return 0.0;);
	}
	duk_xget_owndataprop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
	DUK_ASSERT(duk_is_number(thr, -1));
	DUK_DDD(DUK_DDDPRINT("number object: %!T, internal value: %!T",
	                     (duk_tval *) duk_get_tval(thr, -2), (duk_tval *) duk_get_tval(thr, -1)));
	duk_remove_m2(thr);

 done:
	return duk_get_number(thr, -1);
}

DUK_INTERNAL duk_ret_t duk_bi_number_constructor(duk_hthread *thr) {
	duk_idx_t nargs;
	duk_hobject *h_this;

	/*
	 *  The Number constructor uses ToNumber(arg) for number coercion
	 *  (coercing an undefined argument to NaN).  However, if the
	 *  argument is not given at all, +0 must be used instead.  To do
	 *  this, a vararg function is used.
	 */

	nargs = duk_get_top(thr);
	if (nargs == 0) {
		duk_push_int(thr, 0);
	}
	duk_to_number(thr, 0);
	duk_set_top(thr, 1);
	DUK_ASSERT_TOP(thr, 1);

	if (!duk_is_constructor_call(thr)) {
		return 1;
	}

	/*
	 *  E5 Section 15.7.2.1 requires that the constructed object
	 *  must have the original Number.prototype as its internal
	 *  prototype.  However, since Number.prototype is non-writable
	 *  and non-configurable, this doesn't have to be enforced here:
	 *  The default object (bound to 'this') is OK, though we have
	 *  to change its class.
	 *
	 *  Internal value set to ToNumber(arg) or +0; if no arg given,
	 *  ToNumber(undefined) = NaN, so special treatment is needed
	 *  (above).  String internal value is immutable.
	 */

	/* XXX: helper */
	duk_push_this(thr);
	h_this = duk_known_hobject(thr, -1);
	DUK_HOBJECT_SET_CLASS_NUMBER(h_this, DUK_HOBJECT_CLASS_NUMBER);

	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_this) == thr->builtins[DUK_BIDX_NUMBER_PROTOTYPE]);
	DUK_ASSERT(DUK_HOBJECT_GET_CLASS_NUMBER(h_this) == DUK_HOBJECT_CLASS_NUMBER);
	DUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE(h_this));

	duk_dup_0(thr);  /* -> [ val obj val ] */
	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);
	return 0;  /* no return value -> don't replace created value */
}

DUK_INTERNAL duk_ret_t duk_bi_number_prototype_value_of(duk_hthread *thr) {
	(void) duk__push_this_number_plain(thr);
	return 1;
}

DUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_string(duk_hthread *thr) {
	duk_small_int_t radix;
	duk_small_uint_t n2s_flags;

	(void) duk__push_this_number_plain(thr);
	if (duk_is_undefined(thr, 0)) {
		radix = 10;
	} else {
		radix = (duk_small_int_t) duk_to_int_check_range(thr, 0, 2, 36);
	}
	DUK_DDD(DUK_DDDPRINT("radix=%ld", (long) radix));

	n2s_flags = 0;

	duk_numconv_stringify(thr,
	                      radix /*radix*/,
	                      0 /*digits*/,
	                      n2s_flags /*flags*/);
	return 1;
}

DUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_locale_string(duk_hthread *thr) {
	/* XXX: just use toString() for now; permitted although not recommended.
	 * nargs==1, so radix is passed to toString().
	 */
	return duk_bi_number_prototype_to_string(thr);
}

/*
 *  toFixed(), toExponential(), toPrecision()
 */

/* XXX: shared helper for toFixed(), toExponential(), toPrecision()? */

DUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_fixed(duk_hthread *thr) {
	duk_small_int_t frac_digits;
	duk_double_t d;
	duk_small_int_t c;
	duk_small_uint_t n2s_flags;

	/* In ES5.1 frac_digits is coerced first; in ES2015 the 'this number
	 * value' check is done first.
	 */
	d = duk__push_this_number_plain(thr);
	frac_digits = (duk_small_int_t) duk_to_int_check_range(thr, 0, 0, 20);

	c = (duk_small_int_t) DUK_FPCLASSIFY(d);
	if (c == DUK_FP_NAN || c == DUK_FP_INFINITE) {
		goto use_to_string;
	}

	if (d >= 1.0e21 || d <= -1.0e21) {
		goto use_to_string;
	}

	n2s_flags = DUK_N2S_FLAG_FIXED_FORMAT |
	            DUK_N2S_FLAG_FRACTION_DIGITS;

	duk_numconv_stringify(thr,
	                      10 /*radix*/,
	                      frac_digits /*digits*/,
	                      n2s_flags /*flags*/);
	return 1;

 use_to_string:
	DUK_ASSERT_TOP(thr, 2);
	duk_to_string(thr, -1);
	return 1;
}

DUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_exponential(duk_hthread *thr) {
	duk_bool_t frac_undefined;
	duk_small_int_t frac_digits;
	duk_double_t d;
	duk_small_int_t c;
	duk_small_uint_t n2s_flags;

	d = duk__push_this_number_plain(thr);

	frac_undefined = duk_is_undefined(thr, 0);
	duk_to_int(thr, 0);  /* for side effects */

	c = (duk_small_int_t) DUK_FPCLASSIFY(d);
	if (c == DUK_FP_NAN || c == DUK_FP_INFINITE) {
		goto use_to_string;
	}

	frac_digits = (duk_small_int_t) duk_to_int_check_range(thr, 0, 0, 20);

	n2s_flags = DUK_N2S_FLAG_FORCE_EXP |
	           (frac_undefined ? 0 : DUK_N2S_FLAG_FIXED_FORMAT);

	duk_numconv_stringify(thr,
	                      10 /*radix*/,
	                      frac_digits + 1 /*leading digit + fractions*/,
	                      n2s_flags /*flags*/);
	return 1;

 use_to_string:
	DUK_ASSERT_TOP(thr, 2);
	duk_to_string(thr, -1);
	return 1;
}

DUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_precision(duk_hthread *thr) {
	/* The specification has quite awkward order of coercion and
	 * checks for toPrecision().  The operations below are a bit
	 * reordered, within constraints of observable side effects.
	 */

	duk_double_t d;
	duk_small_int_t prec;
	duk_small_int_t c;
	duk_small_uint_t n2s_flags;

	DUK_ASSERT_TOP(thr, 1);

	d = duk__push_this_number_plain(thr);
	if (duk_is_undefined(thr, 0)) {
		goto use_to_string;
	}
	DUK_ASSERT_TOP(thr, 2);

	duk_to_int(thr, 0);  /* for side effects */

	c = (duk_small_int_t) DUK_FPCLASSIFY(d);
	if (c == DUK_FP_NAN || c == DUK_FP_INFINITE) {
		goto use_to_string;
	}

	prec = (duk_small_int_t) duk_to_int_check_range(thr, 0, 1, 21);

	n2s_flags = DUK_N2S_FLAG_FIXED_FORMAT |
	            DUK_N2S_FLAG_NO_ZERO_PAD;

	duk_numconv_stringify(thr,
	                      10 /*radix*/,
	                      prec /*digits*/,
	                      n2s_flags /*flags*/);
	return 1;

 use_to_string:
	/* Used when precision is undefined; also used for NaN (-> "NaN"),
	 * and +/- infinity (-> "Infinity", "-Infinity").
	 */

	DUK_ASSERT_TOP(thr, 2);
	duk_to_string(thr, -1);
	return 1;
}

/*
 *  ES2015 isFinite() etc
 */

#if defined(DUK_USE_ES6)
DUK_INTERNAL duk_ret_t duk_bi_number_check_shared(duk_hthread *thr) {
	duk_int_t magic;
	duk_bool_t ret = 0;

	if (duk_is_number(thr, 0)) {
		duk_double_t d;

		magic = duk_get_current_magic(thr);
		d = duk_get_number(thr, 0);

		switch (magic) {
		case 0:  /* isFinite() */
			ret = duk_double_is_finite(d);
			break;
		case 1:  /* isInteger() */
			ret = duk_double_is_integer(d);
			break;
		case 2:  /* isNaN() */
			ret = duk_double_is_nan(d);
			break;
		default:  /* isSafeInteger() */
			DUK_ASSERT(magic == 3);
			ret = duk_double_is_safe_integer(d);
		}
	}

	duk_push_boolean(thr, ret);
	return 1;
}
#endif  /* DUK_USE_ES6 */

#endif  /* DUK_USE_NUMBER_BUILTIN */
#line 1 "duk_bi_object.c"
/*
 *  Object built-ins
 */

/* #include duk_internal.h -> already included */

/* Needed even when Object built-in disabled. */
DUK_INTERNAL duk_ret_t duk_bi_object_prototype_to_string(duk_hthread *thr) {
	duk_tval *tv;

	tv = DUK_HTHREAD_THIS_PTR(thr);
	duk_push_class_string_tval(thr, tv, 0 /*avoid_side_effects*/);
	return 1;
}

#if defined(DUK_USE_OBJECT_BUILTIN)
DUK_INTERNAL duk_ret_t duk_bi_object_constructor(duk_hthread *thr) {
	duk_uint_t arg_mask;

	arg_mask = duk_get_type_mask(thr, 0);

	if (!duk_is_constructor_call(thr) &&  /* not a constructor call */
	    ((arg_mask & (DUK_TYPE_MASK_NULL | DUK_TYPE_MASK_UNDEFINED)) == 0)) {  /* and argument not null or undefined */
		duk_to_object(thr, 0);
		return 1;
	}

	/* Pointer and buffer primitive values are treated like other
	 * primitives values which have a fully fledged object counterpart:
	 * promote to an object value.  Lightfuncs and plain buffers are
	 * coerced with ToObject() even they could also be returned as is.
	 */
	if (arg_mask & (DUK_TYPE_MASK_OBJECT |
	                DUK_TYPE_MASK_STRING |
	                DUK_TYPE_MASK_BOOLEAN |
	                DUK_TYPE_MASK_NUMBER |
	                DUK_TYPE_MASK_POINTER |
	                DUK_TYPE_MASK_BUFFER |
	                DUK_TYPE_MASK_LIGHTFUNC)) {
		/* For DUK_TYPE_OBJECT the coercion is a no-op and could
		 * be checked for explicitly, but Object(obj) calls are
		 * not very common so opt for minimal footprint.
		 */
		duk_to_object(thr, 0);
		return 1;
	}

	(void) duk_push_object_helper(thr,
	                              DUK_HOBJECT_FLAG_EXTENSIBLE |
	                              DUK_HOBJECT_FLAG_FASTREFS |
	                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
	                              DUK_BIDX_OBJECT_PROTOTYPE);
	return 1;
}
#endif  /* DUK_USE_OBJECT_BUILTIN */

#if defined(DUK_USE_OBJECT_BUILTIN) && defined(DUK_USE_ES6)
DUK_INTERNAL duk_ret_t duk_bi_object_constructor_assign(duk_hthread *thr) {
	duk_idx_t nargs;
	duk_int_t idx;

	nargs = duk_get_top_require_min(thr, 1 /*min_top*/);

	duk_to_object(thr, 0);
	for (idx = 1; idx < nargs; idx++) {
		/* E7 19.1.2.1 (step 4a) */
		if (duk_is_null_or_undefined(thr, idx)) {
			continue;
		}

		/* duk_enum() respects ES2015+ [[OwnPropertyKeys]] ordering, which is
		 * convenient here.
		 */
		duk_to_object(thr, idx);
		duk_enum(thr, idx, DUK_ENUM_OWN_PROPERTIES_ONLY);
		while (duk_next(thr, -1, 1 /*get_value*/)) {
			/* [ target ... enum key value ] */
			duk_put_prop(thr, 0);
			/* [ target ... enum ] */
		}
		/* Could pop enumerator, but unnecessary because of duk_set_top()
		 * below.
		 */
	}

	duk_set_top(thr, 1);
	return 1;
}
#endif

#if defined(DUK_USE_OBJECT_BUILTIN) && defined(DUK_USE_ES6)
DUK_INTERNAL duk_ret_t duk_bi_object_constructor_is(duk_hthread *thr) {
	DUK_ASSERT_TOP(thr, 2);
	duk_push_boolean(thr, duk_samevalue(thr, 0, 1));
	return 1;
}
#endif

#if defined(DUK_USE_OBJECT_BUILTIN)
DUK_INTERNAL duk_ret_t duk_bi_object_constructor_create(duk_hthread *thr) {
	duk_hobject *proto;

	DUK_ASSERT_TOP(thr, 2);

#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
	duk_hbufobj_promote_plain(thr, 0);
#endif
	proto = duk_require_hobject_accept_mask(thr, 0, DUK_TYPE_MASK_NULL);
	DUK_ASSERT(proto != NULL || duk_is_null(thr, 0));

	(void) duk_push_object_helper_proto(thr,
	                                    DUK_HOBJECT_FLAG_EXTENSIBLE |
	                                    DUK_HOBJECT_FLAG_FASTREFS |
	                                    DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
	                                    proto);

	if (!duk_is_undefined(thr, 1)) {
		/* [ O Properties obj ] */

		duk_replace(thr, 0);

		/* [ obj Properties ] */

		/* Just call the "original" Object.defineProperties() to
		 * finish up.
		 */

		return duk_bi_object_constructor_define_properties(thr);
	}

	/* [ O Properties obj ] */

	return 1;
}
#endif  /* DUK_USE_OBJECT_BUILTIN */

#if defined(DUK_USE_OBJECT_BUILTIN)
DUK_INTERNAL duk_ret_t duk_bi_object_constructor_define_properties(duk_hthread *thr) {
	duk_small_uint_t pass;
	duk_uint_t defprop_flags;
	duk_hobject *obj;
	duk_idx_t idx_value;
	duk_hobject *get;
	duk_hobject *set;

	/* Lightfunc and plain buffer handling by ToObject() coercion. */
	obj = duk_require_hobject_promote_mask(thr, 0, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
	DUK_ASSERT(obj != NULL);

	duk_to_object(thr, 1);        /* properties object */

	DUK_DDD(DUK_DDDPRINT("target=%!iT, properties=%!iT",
	                     (duk_tval *) duk_get_tval(thr, 0),
	                     (duk_tval *) duk_get_tval(thr, 1)));

	/*
	 *  Two pass approach to processing the property descriptors.
	 *  On first pass validate and normalize all descriptors before
	 *  any changes are made to the target object.  On second pass
	 *  make the actual modifications to the target object.
	 *
	 *  Right now we'll just use the same normalize/validate helper
	 *  on both passes, ignoring its outputs on the first pass.
	 */

	for (pass = 0; pass < 2; pass++) {
		duk_set_top(thr, 2);  /* -> [ hobject props ] */
		duk_enum(thr, 1, DUK_ENUM_OWN_PROPERTIES_ONLY | DUK_ENUM_INCLUDE_SYMBOLS /*enum_flags*/);

		for (;;) {
			duk_hstring *key;

			/* [ hobject props enum(props) ] */

			duk_set_top(thr, 3);

			if (!duk_next(thr, 2, 1 /*get_value*/)) {
				break;
			}

			DUK_DDD(DUK_DDDPRINT("-> key=%!iT, desc=%!iT",
			                     (duk_tval *) duk_get_tval(thr, -2),
			                     (duk_tval *) duk_get_tval(thr, -1)));

			/* [ hobject props enum(props) key desc ] */

			duk_hobject_prepare_property_descriptor(thr,
			                                        4 /*idx_desc*/,
			                                        &defprop_flags,
			                                        &idx_value,
			                                        &get,
			                                        &set);

			/* [ hobject props enum(props) key desc [multiple values] ] */

			if (pass == 0) {
				continue;
			}

			/* This allows symbols on purpose. */
			key = duk_known_hstring(thr, 3);
			DUK_ASSERT(key != NULL);

			duk_hobject_define_property_helper(thr,
			                                   defprop_flags,
			                                   obj,
			                                   key,
			                                   idx_value,
			                                   get,
			                                   set,
			                                   1 /*throw_flag*/);
		}
	}

	/*
	 *  Return target object
	 */

	duk_dup_0(thr);
	return 1;
}
#endif  /* DUK_USE_OBJECT_BUILTIN */

#if defined(DUK_USE_OBJECT_BUILTIN)
DUK_INTERNAL duk_ret_t duk_bi_object_constructor_seal_freeze_shared(duk_hthread *thr) {
	DUK_ASSERT_TOP(thr, 1);

	duk_seal_freeze_raw(thr, 0, (duk_bool_t) duk_get_current_magic(thr) /*is_freeze*/);
	return 1;
}
#endif  /* DUK_USE_OBJECT_BUILTIN */

#if defined(DUK_USE_OBJECT_BUILTIN)
DUK_INTERNAL duk_ret_t duk_bi_object_constructor_is_sealed_frozen_shared(duk_hthread *thr) {
	duk_hobject *h;
	duk_bool_t is_frozen;
	duk_uint_t mask;

	is_frozen = (duk_bool_t) duk_get_current_magic(thr);
	mask = duk_get_type_mask(thr, 0);
	if (mask & (DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER)) {
		DUK_ASSERT(is_frozen == 0 || is_frozen == 1);
		duk_push_boolean(thr, (mask & DUK_TYPE_MASK_LIGHTFUNC) ?
		                          1 :               /* lightfunc always frozen and sealed */
		                          (is_frozen ^ 1)); /* buffer sealed but not frozen (index props writable) */
	} else {
		/* ES2015 Sections 19.1.2.12, 19.1.2.13: anything other than an object
		 * is considered to be already sealed and frozen.
		 */
		h = duk_get_hobject(thr, 0);
		duk_push_boolean(thr, (h == NULL) ||
		                      duk_hobject_object_is_sealed_frozen_helper(thr, h, is_frozen /*is_frozen*/));
	}
	return 1;
}
#endif  /* DUK_USE_OBJECT_BUILTIN */

#if defined(DUK_USE_OBJECT_BUILTIN)
DUK_INTERNAL duk_ret_t duk_bi_object_prototype_to_locale_string(duk_hthread *thr) {
	DUK_ASSERT_TOP(thr, 0);
	(void) duk_push_this_coercible_to_object(thr);
	duk_get_prop_stridx_short(thr, 0, DUK_STRIDX_TO_STRING);
#if 0  /* This is mentioned explicitly in the E5.1 spec, but duk_call_method() checks for it in practice. */
	duk_require_callable(thr, 1);
#endif
	duk_dup_0(thr);  /* -> [ O toString O ] */
	duk_call_method(thr, 0);  /* XXX: call method tail call? */
	return 1;
}
#endif  /* DUK_USE_OBJECT_BUILTIN */

#if defined(DUK_USE_OBJECT_BUILTIN)
DUK_INTERNAL duk_ret_t duk_bi_object_prototype_value_of(duk_hthread *thr) {
	/* For lightfuncs and plain buffers, returns Object() coerced. */
	(void) duk_push_this_coercible_to_object(thr);
	return 1;
}
#endif  /* DUK_USE_OBJECT_BUILTIN */

#if defined(DUK_USE_OBJECT_BUILTIN)
DUK_INTERNAL duk_ret_t duk_bi_object_prototype_is_prototype_of(duk_hthread *thr) {
	duk_hobject *h_v;
	duk_hobject *h_obj;

	DUK_ASSERT_TOP(thr, 1);

	h_v = duk_get_hobject(thr, 0);
	if (!h_v) {
		duk_push_false(thr);  /* XXX: tail call: return duk_push_false(thr) */
		return 1;
	}

	h_obj = duk_push_this_coercible_to_object(thr);
	DUK_ASSERT(h_obj != NULL);

	/* E5.1 Section 15.2.4.6, step 3.a, lookup proto once before compare.
	 * Prototype loops should cause an error to be thrown.
	 */
	duk_push_boolean(thr, duk_hobject_prototype_chain_contains(thr, DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_v), h_obj, 0 /*ignore_loop*/));
	return 1;
}
#endif  /* DUK_USE_OBJECT_BUILTIN */

#if defined(DUK_USE_OBJECT_BUILTIN)
DUK_INTERNAL duk_ret_t duk_bi_object_prototype_has_own_property(duk_hthread *thr) {
	return (duk_ret_t) duk_hobject_object_ownprop_helper(thr, 0 /*required_desc_flags*/);
}
#endif  /* DUK_USE_OBJECT_BUILTIN */

#if defined(DUK_USE_OBJECT_BUILTIN)
DUK_INTERNAL duk_ret_t duk_bi_object_prototype_property_is_enumerable(duk_hthread *thr) {
	return (duk_ret_t) duk_hobject_object_ownprop_helper(thr, DUK_PROPDESC_FLAG_ENUMERABLE /*required_desc_flags*/);
}
#endif  /* DUK_USE_OBJECT_BUILTIN */

#if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
/* Shared helper to implement Object.getPrototypeOf,
 * Object.prototype.__proto__ getter, and Reflect.getPrototypeOf.
 *
 * http://www.ecma-international.org/ecma-262/6.0/index.html#sec-get-object.prototype.__proto__
 */
DUK_INTERNAL duk_ret_t duk_bi_object_getprototype_shared(duk_hthread *thr) {
	/*
	 *  magic = 0: __proto__ getter
	 *  magic = 1: Object.getPrototypeOf()
	 *  magic = 2: Reflect.getPrototypeOf()
	 */

	duk_hobject *h;
	duk_hobject *proto;
	duk_tval *tv;
	duk_int_t magic;

	magic = duk_get_current_magic(thr);

	if (magic == 0) {
		DUK_ASSERT_TOP(thr, 0);
		duk_push_this_coercible_to_object(thr);
	}
	DUK_ASSERT(duk_get_top(thr) >= 1);
	if (magic < 2) {
		/* ES2015 Section 19.1.2.9, step 1 */
		duk_to_object(thr, 0);
	}
	tv = DUK_GET_TVAL_POSIDX(thr, 0);

	switch (DUK_TVAL_GET_TAG(tv)) {
	case DUK_TAG_BUFFER:
		proto = thr->builtins[DUK_BIDX_UINT8ARRAY_PROTOTYPE];
		break;
	case DUK_TAG_LIGHTFUNC:
		proto = thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE];
		break;
	case DUK_TAG_OBJECT:
		h = DUK_TVAL_GET_OBJECT(tv);
		proto = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
		break;
	default:
		/* This implicitly handles CheckObjectCoercible() caused
		 * TypeError.
		 */
		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
	}
	if (proto != NULL) {
		duk_push_hobject(thr, proto);
	} else {
		duk_push_null(thr);
	}
	return 1;
}
#endif  /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */

#if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
/* Shared helper to implement ES2015 Object.setPrototypeOf,
 * Object.prototype.__proto__ setter, and Reflect.setPrototypeOf.
 *
 * http://www.ecma-international.org/ecma-262/6.0/index.html#sec-get-object.prototype.__proto__
 * http://www.ecma-international.org/ecma-262/6.0/index.html#sec-object.setprototypeof
 */
DUK_INTERNAL duk_ret_t duk_bi_object_setprototype_shared(duk_hthread *thr) {
	/*
	 *  magic = 0: __proto__ setter
	 *  magic = 1: Object.setPrototypeOf()
	 *  magic = 2: Reflect.setPrototypeOf()
	 */

	duk_hobject *h_obj;
	duk_hobject *h_new_proto;
	duk_hobject *h_curr;
	duk_ret_t ret_success = 1;  /* retval for success path */
	duk_uint_t mask;
	duk_int_t magic;

	/* Preliminaries for __proto__ and setPrototypeOf (E6 19.1.2.18 steps 1-4). */
	magic = duk_get_current_magic(thr);
	if (magic == 0) {
		duk_push_this_check_object_coercible(thr);
		duk_insert(thr, 0);
		if (!duk_check_type_mask(thr, 1, DUK_TYPE_MASK_NULL | DUK_TYPE_MASK_OBJECT)) {
			return 0;
		}

		/* __proto__ setter returns 'undefined' on success unlike the
		 * setPrototypeOf() call which returns the target object.
		 */
		ret_success = 0;
	} else {
		if (magic == 1) {
			duk_require_object_coercible(thr, 0);
		} else {
			duk_require_hobject_accept_mask(thr, 0,
			                                DUK_TYPE_MASK_LIGHTFUNC |
			                                DUK_TYPE_MASK_BUFFER);
		}
		duk_require_type_mask(thr, 1, DUK_TYPE_MASK_NULL | DUK_TYPE_MASK_OBJECT);
	}

	h_new_proto = duk_get_hobject(thr, 1);
	/* h_new_proto may be NULL */

	mask = duk_get_type_mask(thr, 0);
	if (mask & (DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER)) {
		duk_hobject *curr_proto;
		curr_proto = thr->builtins[(mask & DUK_TYPE_MASK_LIGHTFUNC) ?
		                               DUK_BIDX_FUNCTION_PROTOTYPE :
		                               DUK_BIDX_UINT8ARRAY_PROTOTYPE];
		if (h_new_proto == curr_proto) {
			goto skip;
		}
		goto fail_nonextensible;
	}
	h_obj = duk_get_hobject(thr, 0);
	if (h_obj == NULL) {
		goto skip;
	}
	DUK_ASSERT(h_obj != NULL);

	/* [[SetPrototypeOf]] standard behavior, E6 9.1.2. */
	/* TODO: implement Proxy object support here */

	if (h_new_proto == DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_obj)) {
		goto skip;
	}
	if (!DUK_HOBJECT_HAS_EXTENSIBLE(h_obj)) {
		goto fail_nonextensible;
	}
	for (h_curr = h_new_proto; h_curr != NULL; h_curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_curr)) {
		/* Loop prevention. */
		if (h_curr == h_obj) {
			goto fail_loop;
		}
	}
	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h_obj, h_new_proto);
	/* fall thru */

 skip:
	duk_set_top(thr, 1);
	if (magic == 2) {
		duk_push_true(thr);
	}
	return ret_success;

 fail_nonextensible:
 fail_loop:
	if (magic != 2) {
		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
	} else {
		duk_push_false(thr);
		return 1;
	}
}
#endif  /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */

#if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
DUK_INTERNAL duk_ret_t duk_bi_object_constructor_define_property(duk_hthread *thr) {
	/*
	 *  magic = 0: Object.defineProperty()
	 *  magic = 1: Reflect.defineProperty()
	 */

	duk_hobject *obj;
	duk_hstring *key;
	duk_hobject *get;
	duk_hobject *set;
	duk_idx_t idx_value;
	duk_uint_t defprop_flags;
	duk_small_uint_t magic;
	duk_bool_t throw_flag;
	duk_bool_t ret;

	DUK_ASSERT(thr != NULL);

	DUK_DDD(DUK_DDDPRINT("Object.defineProperty(): ctx=%p obj=%!T key=%!T desc=%!T",
	                     (void *) thr,
	                     (duk_tval *) duk_get_tval(thr, 0),
	                     (duk_tval *) duk_get_tval(thr, 1),
	                     (duk_tval *) duk_get_tval(thr, 2)));

	/* [ obj key desc ] */

	magic = (duk_small_uint_t) duk_get_current_magic(thr);

	/* Lightfuncs are currently supported by coercing to a temporary
	 * Function object; changes will be allowed (the coerced value is
	 * extensible) but will be lost.  Same for plain buffers.
	 */
	obj = duk_require_hobject_promote_mask(thr, 0, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
	DUK_ASSERT(obj != NULL);
	key = duk_to_property_key_hstring(thr, 1);
	(void) duk_require_hobject(thr, 2);

	DUK_ASSERT(obj != NULL);
	DUK_ASSERT(key != NULL);
	DUK_ASSERT(duk_get_hobject(thr, 2) != NULL);

	/*
	 *  Validate and convert argument property descriptor (an ECMAScript
	 *  object) into a set of defprop_flags and possibly property value,
	 *  getter, and/or setter values on the value stack.
	 *
	 *  Lightfunc set/get values are coerced to full Functions.
	 */

	duk_hobject_prepare_property_descriptor(thr,
	                                        2 /*idx_desc*/,
	                                        &defprop_flags,
	                                        &idx_value,
	                                        &get,
	                                        &set);

	/*
	 *  Use Object.defineProperty() helper for the actual operation.
	 */

	DUK_ASSERT(magic == 0U || magic == 1U);
	throw_flag = magic ^ 1U;
	ret = duk_hobject_define_property_helper(thr,
	                                         defprop_flags,
	                                         obj,
	                                         key,
	                                         idx_value,
	                                         get,
	                                         set,
	                                         throw_flag);

	/* Ignore the normalize/validate helper outputs on the value stack,
	 * they're popped automatically.
	 */

	if (magic == 0U) {
		/* Object.defineProperty(): return target object. */
		duk_push_hobject(thr, obj);
	} else {
		/* Reflect.defineProperty(): return success/fail. */
		duk_push_boolean(thr, ret);
	}
	return 1;
}
#endif  /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */

#if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
DUK_INTERNAL duk_ret_t duk_bi_object_constructor_get_own_property_descriptor(duk_hthread *thr) {
	DUK_ASSERT_TOP(thr, 2);

	/* ES2015 Section 19.1.2.6, step 1 */
	if (duk_get_current_magic(thr) == 0) {
		duk_to_object(thr, 0);
	}

	/* [ obj key ] */

	duk_hobject_object_get_own_property_descriptor(thr, -2);
	return 1;
}
#endif  /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */

#if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
DUK_INTERNAL duk_ret_t duk_bi_object_constructor_is_extensible(duk_hthread *thr) {
	/*
	 *  magic = 0: Object.isExtensible()
	 *  magic = 1: Reflect.isExtensible()
	 */

	duk_hobject *h;

	if (duk_get_current_magic(thr) == 0) {
		h = duk_get_hobject(thr, 0);
	} else {
		/* Reflect.isExtensible(): throw if non-object, but we accept lightfuncs
		 * and plain buffers here because they pretend to be objects.
		 */
		h = duk_require_hobject_accept_mask(thr, 0, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
	}

	duk_push_boolean(thr, (h != NULL) && DUK_HOBJECT_HAS_EXTENSIBLE(h));
	return 1;
}
#endif  /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */

#if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
/* Shared helper for various key/symbol listings, magic:
 * 0=Object.keys()
 * 1=Object.getOwnPropertyNames(),
 * 2=Object.getOwnPropertySymbols(),
 * 3=Reflect.ownKeys()
 */
DUK_LOCAL const duk_small_uint_t duk__object_keys_enum_flags[4] = {
	/* Object.keys() */
	DUK_ENUM_OWN_PROPERTIES_ONLY |
	    DUK_ENUM_NO_PROXY_BEHAVIOR,

	/* Object.getOwnPropertyNames() */
	DUK_ENUM_INCLUDE_NONENUMERABLE |
	    DUK_ENUM_OWN_PROPERTIES_ONLY |
	    DUK_ENUM_NO_PROXY_BEHAVIOR,

	/* Object.getOwnPropertySymbols() */
	DUK_ENUM_INCLUDE_SYMBOLS |
	    DUK_ENUM_OWN_PROPERTIES_ONLY |
	    DUK_ENUM_EXCLUDE_STRINGS |
	    DUK_ENUM_INCLUDE_NONENUMERABLE |
	    DUK_ENUM_NO_PROXY_BEHAVIOR,

	/* Reflect.ownKeys() */
	DUK_ENUM_INCLUDE_SYMBOLS |
	    DUK_ENUM_OWN_PROPERTIES_ONLY |
	    DUK_ENUM_INCLUDE_NONENUMERABLE |
	    DUK_ENUM_NO_PROXY_BEHAVIOR
};

DUK_INTERNAL duk_ret_t duk_bi_object_constructor_keys_shared(duk_hthread *thr) {
	duk_hobject *obj;
#if defined(DUK_USE_ES6_PROXY)
	duk_hobject *h_proxy_target;
	duk_hobject *h_proxy_handler;
	duk_hobject *h_trap_result;
#endif
	duk_small_uint_t enum_flags;
	duk_int_t magic;

	DUK_ASSERT_TOP(thr, 1);

	magic = duk_get_current_magic(thr);
	if (magic == 3) {
		/* ES2015 Section 26.1.11 requires a TypeError for non-objects.  Lightfuncs
		 * and plain buffers pretend to be objects, so accept those too.
		 */
		obj = duk_require_hobject_promote_mask(thr, 0, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
	} else {
		/* ES2015: ToObject coerce. */
		obj = duk_to_hobject(thr, 0);
	}
	DUK_ASSERT(obj != NULL);
	DUK_UNREF(obj);

	/* XXX: proxy chains */

#if defined(DUK_USE_ES6_PROXY)
	/* XXX: better sharing of code between proxy target call sites */
	if (DUK_LIKELY(!duk_hobject_proxy_check(obj,
	                                        &h_proxy_target,
	                                        &h_proxy_handler))) {
		goto skip_proxy;
	}

	duk_push_hobject(thr, h_proxy_handler);
	if (!duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_OWN_KEYS)) {
		/* Careful with reachability here: don't pop 'obj' before pushing
		 * proxy target.
		 */
		DUK_DDD(DUK_DDDPRINT("no ownKeys trap, get keys of target instead"));
		duk_pop_2(thr);
		duk_push_hobject(thr, h_proxy_target);
		duk_replace(thr, 0);
		DUK_ASSERT_TOP(thr, 1);
		goto skip_proxy;
	}

	/* [ obj handler trap ] */
	duk_insert(thr, -2);
	duk_push_hobject(thr, h_proxy_target);  /* -> [ obj trap handler target ] */
	duk_call_method(thr, 1 /*nargs*/);      /* -> [ obj trap_result ] */
	h_trap_result = duk_require_hobject(thr, -1);
	DUK_UNREF(h_trap_result);

	magic = duk_get_current_magic(thr);
	DUK_ASSERT(magic >= 0 && magic < (duk_int_t) (sizeof(duk__object_keys_enum_flags) / sizeof(duk_small_uint_t)));
	enum_flags = duk__object_keys_enum_flags[magic];

	duk_proxy_ownkeys_postprocess(thr, h_proxy_target, enum_flags);
	return 1;

 skip_proxy:
#endif  /* DUK_USE_ES6_PROXY */

	DUK_ASSERT_TOP(thr, 1);
	magic = duk_get_current_magic(thr);
	DUK_ASSERT(magic >= 0 && magic < (duk_int_t) (sizeof(duk__object_keys_enum_flags) / sizeof(duk_small_uint_t)));
	enum_flags = duk__object_keys_enum_flags[magic];
	return duk_hobject_get_enumerated_keys(thr, enum_flags);
}
#endif  /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */

#if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
DUK_INTERNAL duk_ret_t duk_bi_object_constructor_prevent_extensions(duk_hthread *thr) {
	/*
	 *  magic = 0: Object.preventExtensions()
	 *  magic = 1: Reflect.preventExtensions()
	 */

	duk_hobject *h;
	duk_uint_t mask;
	duk_int_t magic;

	magic = duk_get_current_magic(thr);

	/* Silent success for lightfuncs and plain buffers always. */
	mask = DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER;

	/* Object.preventExtensions() silent success for non-object. */
	if (magic == 0) {
		mask |= DUK_TYPE_MASK_UNDEFINED |
		        DUK_TYPE_MASK_NULL |
		        DUK_TYPE_MASK_BOOLEAN |
		        DUK_TYPE_MASK_NUMBER |
		        DUK_TYPE_MASK_STRING |
		        DUK_TYPE_MASK_POINTER;
	}

	if (duk_check_type_mask(thr, 0, mask)) {
		/* Not an object, already non-extensible so always success. */
		goto done;
	}
	h = duk_require_hobject(thr, 0);
	DUK_ASSERT(h != NULL);

	DUK_HOBJECT_CLEAR_EXTENSIBLE(h);

	/* A non-extensible object cannot gain any more properties,
	 * so this is a good time to compact.
	 */
	duk_hobject_compact_props(thr, h);

 done:
	if (magic == 1) {
		duk_push_true(thr);
	}
	return 1;
}
#endif  /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */

/*
 *  __defineGetter__, __defineSetter__, __lookupGetter__, __lookupSetter__
 */

#if defined(DUK_USE_ES8)
DUK_INTERNAL duk_ret_t duk_bi_object_prototype_defineaccessor(duk_hthread *thr) {
	duk_push_this(thr);
	duk_insert(thr, 0);
	duk_to_object(thr, 0);
	duk_require_callable(thr, 2);

	/* [ ToObject(this) key getter/setter ] */

	/* ToPropertyKey() coercion is not needed, duk_def_prop() does it. */
	duk_def_prop(thr, 0, DUK_DEFPROP_SET_ENUMERABLE |
	                     DUK_DEFPROP_SET_CONFIGURABLE |
	                     (duk_get_current_magic(thr) ? DUK_DEFPROP_HAVE_SETTER : DUK_DEFPROP_HAVE_GETTER));
	return 0;
}
DUK_INTERNAL duk_ret_t duk_bi_object_prototype_lookupaccessor(duk_hthread *thr) {
	duk_uint_t sanity;

	duk_push_this(thr);
	duk_to_object(thr, -1);

	/* XXX: Prototype walk (with sanity) should be a core property
	 * operation, could add a flag to e.g. duk_get_prop_desc().
	 */

	/* ToPropertyKey() coercion is not needed, duk_get_prop_desc() does it. */
	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
	while (!duk_is_undefined(thr, -1)) {
		/* [ key obj ] */
		duk_dup(thr, 0);
		duk_get_prop_desc(thr, 1, 0 /*flags*/);
		if (!duk_is_undefined(thr, -1)) {
			duk_get_prop_stridx(thr, -1, (duk_get_current_magic(thr) != 0 ? DUK_STRIDX_SET : DUK_STRIDX_GET));
			return 1;
		}
		duk_pop(thr);

		if (DUK_UNLIKELY(sanity-- == 0)) {
			DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
			DUK_WO_NORETURN(return 0;);
		}

		duk_get_prototype(thr, -1);
		duk_remove(thr, -2);
	}
	return 1;
}
#endif  /* DUK_USE_ES8 */
#line 1 "duk_bi_performance.c"
/*
 *  High resolution time API (performance.now() et al)
 *
 *  API specification: https://encoding.spec.whatwg.org/#ap://www.w3.org/TR/hr-time/
 */

/* #include duk_internal.h -> already included */

#if defined(DUK_USE_PERFORMANCE_BUILTIN)
DUK_INTERNAL duk_ret_t duk_bi_performance_now(duk_hthread *thr) {
	/* From API spec:
	 * The DOMHighResTimeStamp type is used to store a time value in
	 * milliseconds, measured relative from the time origin, global
	 * monotonic clock, or a time value that represents a duration
	 * between two DOMHighResTimeStamp's.
	 */
	duk_push_number(thr, duk_time_get_monotonic_time(thr));
	return 1;
}

#if 0  /* Missing until semantics decided. */
DUK_INTERNAL duk_ret_t duk_bi_performance_timeorigin_getter(duk_hthread *thr) {
	/* No decision yet how to handle timeOrigins, e.g. should one be
	 * initialized per heap, or per global object set.  See
	 * https://www.w3.org/TR/hr-time/#time-origin.
	 */
	duk_push_uint(thr, 0);
	return 1;
}
#endif  /* 0 */
#endif  /* DUK_USE_PERFORMANCE_BUILTIN */
#line 1 "duk_bi_pointer.c"
/*
 *  Pointer built-ins
 */

/* #include duk_internal.h -> already included */

/*
 *  Constructor
 */

DUK_INTERNAL duk_ret_t duk_bi_pointer_constructor(duk_hthread *thr) {
	/* XXX: this behavior is quite useless now; it would be nice to be able
	 * to create pointer values from e.g. numbers or strings.  Numbers are
	 * problematic on 64-bit platforms though.  Hex encoded strings?
	 */
	if (duk_get_top(thr) == 0) {
		duk_push_pointer(thr, NULL);
	} else {
		duk_to_pointer(thr, 0);
	}
	DUK_ASSERT(duk_is_pointer(thr, 0));
	duk_set_top(thr, 1);

	if (duk_is_constructor_call(thr)) {
		(void) duk_push_object_helper(thr,
		                              DUK_HOBJECT_FLAG_EXTENSIBLE |
		                              DUK_HOBJECT_FLAG_FASTREFS |
		                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_POINTER),
		                              DUK_BIDX_POINTER_PROTOTYPE);

		/* Pointer object internal value is immutable. */
		duk_dup_0(thr);
		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);
	}
	/* Note: unbalanced stack on purpose */

	return 1;
}

/*
 *  toString(), valueOf()
 */

DUK_INTERNAL duk_ret_t duk_bi_pointer_prototype_tostring_shared(duk_hthread *thr) {
	duk_tval *tv;
	duk_small_int_t to_string = duk_get_current_magic(thr);

	duk_push_this(thr);
	tv = duk_require_tval(thr, -1);
	DUK_ASSERT(tv != NULL);

	if (DUK_TVAL_IS_POINTER(tv)) {
		/* nop */
	} else if (DUK_TVAL_IS_OBJECT(tv)) {
		duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
		DUK_ASSERT(h != NULL);

		/* Must be a "pointer object", i.e. class "Pointer" */
		if (DUK_HOBJECT_GET_CLASS_NUMBER(h) != DUK_HOBJECT_CLASS_POINTER) {
			goto type_error;
		}

		duk_xget_owndataprop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
	} else {
		goto type_error;
	}

	if (to_string) {
		duk_to_string(thr, -1);
	}
	return 1;

 type_error:
	DUK_DCERROR_TYPE_INVALID_ARGS(thr);
}
#line 1 "duk_bi_promise.c"
/*
 *  Promise built-in
 */

/* #include duk_internal.h -> already included */

#if defined(DUK_USE_PROMISE_BUILTIN)

DUK_INTERNAL duk_ret_t duk_bi_promise_constructor(duk_hthread *thr) {
	DUK_ERROR_TYPE(thr, "unimplemented");
	DUK_WO_NORETURN(return 0;);
}

DUK_INTERNAL duk_ret_t duk_bi_promise_all(duk_hthread *thr) {
	DUK_ERROR_TYPE(thr, "unimplemented");
	DUK_WO_NORETURN(return 0;);
}

DUK_INTERNAL duk_ret_t duk_bi_promise_race(duk_hthread *thr) {
	DUK_ERROR_TYPE(thr, "unimplemented");
	DUK_WO_NORETURN(return 0;);
}

DUK_INTERNAL duk_ret_t duk_bi_promise_reject(duk_hthread *thr) {
	DUK_ERROR_TYPE(thr, "unimplemented");
	DUK_WO_NORETURN(return 0;);
}

DUK_INTERNAL duk_ret_t duk_bi_promise_resolve(duk_hthread *thr) {
	DUK_ERROR_TYPE(thr, "unimplemented");
	DUK_WO_NORETURN(return 0;);
}

DUK_INTERNAL duk_ret_t duk_bi_promise_catch(duk_hthread *thr) {
	DUK_ERROR_TYPE(thr, "unimplemented");
	DUK_WO_NORETURN(return 0;);
}

DUK_INTERNAL duk_ret_t duk_bi_promise_then(duk_hthread *thr) {
	DUK_ERROR_TYPE(thr, "unimplemented");
	DUK_WO_NORETURN(return 0;);
}

#endif  /* DUK_USE_PROMISE_BUILTIN */
#line 1 "duk_bi_proxy.c"
/*
 *  Proxy built-in (ES2015)
 */

/* #include duk_internal.h -> already included */

#if defined(DUK_USE_ES6_PROXY)
/* Post-process a Proxy ownKeys() result at stack top.  Push a cleaned up
 * array of valid result keys (strings or symbols).  TypeError for invalid
 * values.  Flags are shared with duk_enum().
 */
DUK_INTERNAL void duk_proxy_ownkeys_postprocess(duk_hthread *thr, duk_hobject *h_proxy_target, duk_uint_t flags) {
	duk_uarridx_t i, len, idx;
	duk_propdesc desc;

	DUK_CTX_ASSERT_VALID(thr);
	DUK_ASSERT(h_proxy_target != NULL);

	len = (duk_uarridx_t) duk_get_length(thr, -1);
	idx = 0;
	duk_push_array(thr);
	/* XXX: preallocated dense array, fill in directly */
	for (i = 0; i < len; i++) {
		duk_hstring *h;

		/* [ obj trap_result res_arr ] */
		(void) duk_get_prop_index(thr, -2, i);
		h = duk_get_hstring(thr, -1);
		if (h == NULL) {
			DUK_ERROR_TYPE_INVALID_TRAP_RESULT(thr);
			DUK_WO_NORETURN(return;);
		}

		if (!(flags & DUK_ENUM_INCLUDE_NONENUMERABLE)) {
			/* No support for 'getOwnPropertyDescriptor' trap yet,
			 * so check enumerability always from target object
			 * descriptor.
			 */
			if (duk_hobject_get_own_propdesc(thr, h_proxy_target, duk_known_hstring(thr, -1), &desc, 0 /*flags*/)) {
				if ((desc.flags & DUK_PROPDESC_FLAG_ENUMERABLE) == 0) {
					DUK_DDD(DUK_DDDPRINT("ignore non-enumerable property: %!T", duk_get_tval(thr, -1)));
					goto skip_key;
				}
			} else {
				DUK_DDD(DUK_DDDPRINT("ignore non-existent property: %!T", duk_get_tval(thr, -1)));
				goto skip_key;
			}
		}
		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
			if (!(flags & DUK_ENUM_INCLUDE_SYMBOLS)) {
				DUK_DDD(DUK_DDDPRINT("ignore symbol property: %!T", duk_get_tval(thr, -1)));
				goto skip_key;
			}
			if (DUK_HSTRING_HAS_HIDDEN(h) && !(flags & DUK_ENUM_INCLUDE_HIDDEN)) {
				DUK_DDD(DUK_DDDPRINT("ignore hidden symbol property: %!T", duk_get_tval(thr, -1)));
				goto skip_key;
			}
		} else {
			if (flags & DUK_ENUM_EXCLUDE_STRINGS) {
				DUK_DDD(DUK_DDDPRINT("ignore string property: %!T", duk_get_tval(thr, -1)));
				goto skip_key;
			}
		}

		/* [ obj trap_result res_arr propname ] */
		duk_put_prop_index(thr, -2, idx++);
		continue;

	 skip_key:
		duk_pop(thr);
		continue;
	}

	/* XXX: Missing trap result validation for non-configurable target keys
	 * (must be present), for non-extensible target all target keys must be
	 * present and no extra keys can be present.
	 * http://www.ecma-international.org/ecma-262/6.0/#sec-proxy-object-internal-methods-and-internal-slots-ownpropertykeys
	 */

	/* XXX: The key enumerability check should trigger the "getOwnPropertyDescriptor"
	 * trap which has not yet been implemented.  In the absence of such a trap,
	 * the enumerability should be checked from the target object; this is
	 * handled above.
	 */
}
#endif  /* DUK_USE_ES6_PROXY */

#if defined(DUK_USE_ES6_PROXY)
DUK_INTERNAL duk_ret_t duk_bi_proxy_constructor(duk_hthread *thr) {
	DUK_ASSERT_TOP(thr, 2);  /* [ target handler ] */

	duk_require_constructor_call(thr);
	duk_push_proxy(thr, 0 /*flags*/);  /* [ target handler ] -> [ proxy ] */
	return 1;  /* replacement */
}
#endif  /* DUK_USE_ES6_PROXY */
#line 1 "duk_bi_reflect.c"
/*
 *  'Reflect' built-in (ES2016 Section 26.1)
 *  http://www.ecma-international.org/ecma-262/7.0/#sec-reflect-object
 *
 *  Many Reflect built-in functions are provided by shared helpers in
 *  duk_bi_object.c or duk_bi_function.c.
 */

/* #include duk_internal.h -> already included */

#if defined(DUK_USE_REFLECT_BUILTIN)
DUK_INTERNAL duk_ret_t duk_bi_reflect_object_delete_property(duk_hthread *thr) {
	duk_tval *tv_obj;
	duk_tval *tv_key;
	duk_bool_t ret;

	DUK_ASSERT_TOP(thr, 2);
	(void) duk_require_hobject(thr, 0);
	(void) duk_to_string(thr, 1);

	/* [ target key ] */

	DUK_ASSERT(thr != NULL);
	tv_obj = DUK_GET_TVAL_POSIDX(thr, 0);
	tv_key = DUK_GET_TVAL_POSIDX(thr, 1);
	ret = duk_hobject_delprop(thr, tv_obj, tv_key, 0 /*throw_flag*/);
	duk_push_boolean(thr, ret);
	return 1;
}

DUK_INTERNAL duk_ret_t duk_bi_reflect_object_get(duk_hthread *thr) {
	duk_tval *tv_obj;
	duk_tval *tv_key;
	duk_idx_t nargs;

	DUK_ASSERT(thr != NULL);
	nargs = duk_get_top_require_min(thr, 2 /*min_top*/);
	(void) duk_require_hobject(thr, 0);
	(void) duk_to_string(thr, 1);
	if (nargs >= 3 && !duk_strict_equals(thr, 0, 2)) {
		/* XXX: [[Get]] receiver currently unsupported */
		DUK_ERROR_UNSUPPORTED(thr);
		DUK_WO_NORETURN(return 0;);
	}

	/* [ target key receiver? ...? ] */

	tv_obj = DUK_GET_TVAL_POSIDX(thr, 0);
	tv_key = DUK_GET_TVAL_POSIDX(thr, 1);
	(void) duk_hobject_getprop(thr, tv_obj, tv_key);  /* This could also be a duk_get_prop(). */
	return 1;
}

DUK_INTERNAL duk_ret_t duk_bi_reflect_object_has(duk_hthread *thr) {
	duk_tval *tv_obj;
	duk_tval *tv_key;
	duk_bool_t ret;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT_TOP(thr, 2);
	(void) duk_require_hobject(thr, 0);
	(void) duk_to_string(thr, 1);

	/* [ target key ] */

	tv_obj = DUK_GET_TVAL_POSIDX(thr, 0);
	tv_key = DUK_GET_TVAL_POSIDX(thr, 1);
	ret = duk_hobject_hasprop(thr, tv_obj, tv_key);
	duk_push_boolean(thr, ret);
	return 1;
}

DUK_INTERNAL duk_ret_t duk_bi_reflect_object_set(duk_hthread *thr) {
	duk_tval *tv_obj;
	duk_tval *tv_key;
	duk_tval *tv_val;
	duk_idx_t nargs;
	duk_bool_t ret;

	DUK_ASSERT(thr != NULL);
	nargs = duk_get_top_require_min(thr, 3 /*min_top*/);
	(void) duk_require_hobject(thr, 0);
	(void) duk_to_string(thr, 1);
	if (nargs >= 4 && !duk_strict_equals(thr, 0, 3)) {
		/* XXX: [[Set]] receiver currently unsupported */
		DUK_ERROR_UNSUPPORTED(thr);
		DUK_WO_NORETURN(return 0;);
	}

	/* [ target key value receiver? ...? ] */

	tv_obj = DUK_GET_TVAL_POSIDX(thr, 0);
	tv_key = DUK_GET_TVAL_POSIDX(thr, 1);
	tv_val = DUK_GET_TVAL_POSIDX(thr, 2);
	ret = duk_hobject_putprop(thr, tv_obj, tv_key, tv_val, 0 /*throw_flag*/);
	duk_push_boolean(thr, ret);
	return 1;
}
#endif  /* DUK_USE_REFLECT_BUILTIN */
#line 1 "duk_bi_regexp.c"
/*
 *  RegExp built-ins
 */

/* #include duk_internal.h -> already included */

#if defined(DUK_USE_REGEXP_SUPPORT)

DUK_LOCAL void duk__get_this_regexp(duk_hthread *thr) {
	duk_hobject *h;

	duk_push_this(thr);
	h = duk_require_hobject_with_class(thr, -1, DUK_HOBJECT_CLASS_REGEXP);
	DUK_ASSERT(h != NULL);
	DUK_UNREF(h);
	duk_insert(thr, 0);  /* prepend regexp to valstack 0 index */
}

/* XXX: much to improve (code size) */
DUK_INTERNAL duk_ret_t duk_bi_regexp_constructor(duk_hthread *thr) {
	duk_hobject *h_pattern;

	DUK_ASSERT_TOP(thr, 2);
	h_pattern = duk_get_hobject(thr, 0);

	if (!duk_is_constructor_call(thr) &&
	    h_pattern != NULL &&
	    DUK_HOBJECT_GET_CLASS_NUMBER(h_pattern) == DUK_HOBJECT_CLASS_REGEXP &&
	    duk_is_undefined(thr, 1)) {
		/* Called as a function, pattern has [[Class]] "RegExp" and
		 * flags is undefined -> return object as is.
		 */
		/* XXX: ES2015 has a NewTarget SameValue() check which is not
		 * yet implemented.
		 */
		duk_dup_0(thr);
		return 1;
	}

	/* Else functionality is identical for function call and constructor
	 * call.
	 */

	if (h_pattern != NULL &&
	    DUK_HOBJECT_GET_CLASS_NUMBER(h_pattern) == DUK_HOBJECT_CLASS_REGEXP) {
		duk_get_prop_stridx_short(thr, 0, DUK_STRIDX_SOURCE);
		if (duk_is_undefined(thr, 1)) {
			/* In ES5 one would need to read the flags individually;
			 * in ES2015 just read .flags.
			 */
			duk_get_prop_stridx(thr, 0, DUK_STRIDX_FLAGS);
		} else {
			/* In ES2015 allowed; overrides argument RegExp flags. */
			duk_dup_1(thr);
		}
	} else {
		if (duk_is_undefined(thr, 0)) {
			duk_push_hstring_empty(thr);
		} else {
			duk_dup_0(thr);
			duk_to_string(thr, -1);  /* Rejects Symbols. */
		}
		if (duk_is_undefined(thr, 1)) {
			duk_push_hstring_empty(thr);
		} else {
			duk_dup_1(thr);
			duk_to_string(thr, -1);  /* Rejects Symbols. */
		}

		/* [ ... pattern flags ] */
	}

	DUK_DDD(DUK_DDDPRINT("RegExp constructor/function call, pattern=%!T, flags=%!T",
	                     (duk_tval *) duk_get_tval(thr, -2), (duk_tval *) duk_get_tval(thr, -1)));

	/* [ ... pattern flags ] (both uncoerced) */

	duk_to_string(thr, -2);
	duk_to_string(thr, -1);
	duk_regexp_compile(thr);

	/* [ ... bytecode escaped_source ] */

	duk_regexp_create_instance(thr);

	/* [ ... RegExp ] */

	return 1;
}

DUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_exec(duk_hthread *thr) {
	duk__get_this_regexp(thr);

	/* [ regexp input ] */

	duk_regexp_match(thr);

	/* [ result ] */

	return 1;
}

DUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_test(duk_hthread *thr) {
	duk__get_this_regexp(thr);

	/* [ regexp input ] */

	/* result object is created and discarded; wasteful but saves code space */
	duk_regexp_match(thr);

	/* [ result ] */

	duk_push_boolean(thr, (duk_is_null(thr, -1) ? 0 : 1));

	return 1;
}

DUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_tostring(duk_hthread *thr) {
	/* This must be generic in ES2015 and later. */
	DUK_ASSERT_TOP(thr, 0);
	duk_push_this(thr);
	duk_push_literal(thr, "/");
	duk_get_prop_stridx(thr, 0, DUK_STRIDX_SOURCE);
	duk_dup_m2(thr);  /* another "/" */
	duk_get_prop_stridx(thr, 0, DUK_STRIDX_FLAGS);
	duk_concat(thr, 4);
	return 1;
}

DUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_flags(duk_hthread *thr) {
	/* .flags is ES2015 but present even when ES2015 bindings are
	 * disabled because the constructor relies on it.
	 */
	duk_uint8_t buf[8];  /* enough for all flags + NUL */
	duk_uint8_t *p = buf;

	/* .flags is generic and works on any object. */
	duk_push_this(thr);
	(void) duk_require_hobject(thr, -1);
	if (duk_get_prop_stridx_boolean(thr, 0, DUK_STRIDX_GLOBAL, NULL)) {
		*p++ = DUK_ASC_LC_G;
	}
	if (duk_get_prop_stridx_boolean(thr, 0, DUK_STRIDX_IGNORE_CASE, NULL)) {
		*p++ = DUK_ASC_LC_I;
	}
	if (duk_get_prop_stridx_boolean(thr, 0, DUK_STRIDX_MULTILINE, NULL)) {
		*p++ = DUK_ASC_LC_M;
	}
	/* .unicode: to be added */
	/* .sticky: to be added */
	*p++ = DUK_ASC_NUL;
	DUK_ASSERT((duk_size_t) (p - buf) <= sizeof(buf));

	duk_push_string(thr, (const char *) buf);
	return 1;
}

/* Shared helper for providing .source, .global, .multiline, etc getters. */
DUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_shared_getter(duk_hthread *thr) {
	duk_hstring *h_bc;
	duk_small_uint_t re_flags;
	duk_hobject *h;
	duk_int_t magic;

	DUK_ASSERT_TOP(thr, 0);

	duk_push_this(thr);
	h = duk_require_hobject(thr, -1);
	magic = duk_get_current_magic(thr);

	if (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_REGEXP) {
		duk_xget_owndataprop_stridx_short(thr, 0, DUK_STRIDX_INT_SOURCE);
		duk_xget_owndataprop_stridx_short(thr, 0, DUK_STRIDX_INT_BYTECODE);
		h_bc = duk_require_hstring(thr, -1);
		re_flags = (duk_small_uint_t) DUK_HSTRING_GET_DATA(h_bc)[0];  /* Safe even if h_bc length is 0 (= NUL) */
		duk_pop(thr);
	} else if (h == thr->builtins[DUK_BIDX_REGEXP_PROTOTYPE]) {
		/* In ES2015 and ES2016 a TypeError would be thrown here.
		 * However, this had real world issues so ES2017 draft
		 * allows RegExp.prototype specifically, returning '(?:)'
		 * for .source and undefined for all flags.
		 */
		if (magic != 16 /* .source */) {
			return 0;
		}
		duk_push_literal(thr, "(?:)");  /* .source handled by switch-case */
		re_flags = 0;
	} else {
		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
	}

	/* [ regexp source ] */

	switch (magic) {
	case 0: {  /* global */
		duk_push_boolean(thr, (re_flags & DUK_RE_FLAG_GLOBAL));
		break;
	}
	case 1: {  /* ignoreCase */
		duk_push_boolean(thr, (re_flags & DUK_RE_FLAG_IGNORE_CASE));
		break;
	}
	case 2: {  /* multiline */
		duk_push_boolean(thr, (re_flags & DUK_RE_FLAG_MULTILINE));
		break;
	}
#if 0
	/* Don't provide until implemented to avoid interfering with feature
	 * detection in user code.
	 */
	case 3:    /* sticky */
	case 4: {  /* unicode */
		duk_push_false(thr);
		break;
	}
#endif
	default: {  /* source */
		/* leave 'source' on top */
		break;
	}
	}

	return 1;
}

#endif  /* DUK_USE_REGEXP_SUPPORT */
#line 1 "duk_bi_string.c"
/*
 *  String built-ins
 *
 *  Most String built-ins must only accept strings (or String objects).
 *  Symbols, represented internally as strings, must be generally rejected.
 *  The duk_push_this_coercible_to_string() helper does this automatically.
 */

/* XXX: There are several limitations in the current implementation for
 * strings with >= 0x80000000UL characters.  In some cases one would need
 * to be able to represent the range [-0xffffffff,0xffffffff] and so on.
 * Generally character and byte length are assumed to fit into signed 32
 * bits (< 0x80000000UL).  Places with issues are not marked explicitly
 * below in all cases, look for signed type usage (duk_int_t etc) for
 * offsets/lengths.
 */

/* #include duk_internal.h -> already included */

#if defined(DUK_USE_STRING_BUILTIN)

/*
 *  Helpers
 */

DUK_LOCAL duk_hstring *duk__str_tostring_notregexp(duk_hthread *thr, duk_idx_t idx) {
	duk_hstring *h;

	if (duk_get_class_number(thr, idx) == DUK_HOBJECT_CLASS_REGEXP) {
		DUK_ERROR_TYPE_INVALID_ARGS(thr);
		DUK_WO_NORETURN(return NULL;);
	}
	h = duk_to_hstring(thr, idx);
	DUK_ASSERT(h != NULL);

	return h;
}

DUK_LOCAL duk_int_t duk__str_search_shared(duk_hthread *thr, duk_hstring *h_this, duk_hstring *h_search, duk_int_t start_cpos, duk_bool_t backwards) {
	duk_int_t cpos;
	duk_int_t bpos;
	const duk_uint8_t *p_start, *p_end, *p;
	const duk_uint8_t *q_start;
	duk_int_t q_blen;
	duk_uint8_t firstbyte;
	duk_uint8_t t;

	cpos = start_cpos;

	/* Empty searchstring always matches; cpos must be clamped here.
	 * (If q_blen were < 0 due to clamped coercion, it would also be
	 * caught here.)
	 */
	q_start = DUK_HSTRING_GET_DATA(h_search);
	q_blen = (duk_int_t) DUK_HSTRING_GET_BYTELEN(h_search);
	if (q_blen <= 0) {
		return cpos;
	}
	DUK_ASSERT(q_blen > 0);

	bpos = (duk_int_t) duk_heap_strcache_offset_char2byte(thr, h_this, (duk_uint32_t) cpos);

	p_start = DUK_HSTRING_GET_DATA(h_this);
	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_this);
	p = p_start + bpos;

	/* This loop is optimized for size.  For speed, there should be
	 * two separate loops, and we should ensure that memcmp() can be
	 * used without an extra "will searchstring fit" check.  Doing
	 * the preconditioning for 'p' and 'p_end' is easy but cpos
	 * must be updated if 'p' is wound back (backward scanning).
	 */

	firstbyte = q_start[0];  /* leading byte of match string */
	while (p <= p_end && p >= p_start) {
		t = *p;

		/* For ECMAScript strings, this check can only match for
		 * initial UTF-8 bytes (not continuation bytes).  For other
		 * strings all bets are off.
		 */

		if ((t == firstbyte) && ((duk_size_t) (p_end - p) >= (duk_size_t) q_blen)) {
			DUK_ASSERT(q_blen > 0);
			if (duk_memcmp((const void *) p, (const void *) q_start, (size_t) q_blen) == 0) {
				return cpos;
			}
		}

		/* track cpos while scanning */
		if (backwards) {
			/* when going backwards, we decrement cpos 'early';
			 * 'p' may point to a continuation byte of the char
			 * at offset 'cpos', but that's OK because we'll
			 * backtrack all the way to the initial byte.
			 */
			if ((t & 0xc0) != 0x80) {
				cpos--;
			}
			p--;
		} else {
			if ((t & 0xc0) != 0x80) {
				cpos++;
			}
			p++;
		}
	}

	/* Not found.  Empty string case is handled specially above. */
	return -1;
}

/*
 *  Constructor
 */

DUK_INTERNAL duk_ret_t duk_bi_string_constructor(duk_hthread *thr) {
	duk_hstring *h;
	duk_uint_t flags;

	/* String constructor needs to distinguish between an argument not given at all
	 * vs. given as 'undefined'.  We're a vararg function to handle this properly.
	 */

	/* XXX: copy current activation flags to thr, including current magic,
	 * is_constructor_call etc.  This takes a few bytes in duk_hthread but
	 * makes call sites smaller (there are >30 is_constructor_call and get
	 * current magic call sites.
	 */

	if (duk_get_top(thr) == 0) {
		duk_push_hstring_empty(thr);
	} else {
		h = duk_to_hstring_acceptsymbol(thr, 0);
		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h) && !duk_is_constructor_call(thr))) {
			duk_push_symbol_descriptive_string(thr, h);
			duk_replace(thr, 0);
		}
	}
	duk_to_string(thr, 0);  /* catches symbol argument for constructor call */
	DUK_ASSERT(duk_is_string(thr, 0));
	duk_set_top(thr, 1);  /* Top may be 1 or larger. */

	if (duk_is_constructor_call(thr)) {
		/* String object internal value is immutable */
		flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
		        DUK_HOBJECT_FLAG_FASTREFS |
		        DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ |
		        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_STRING);
		duk_push_object_helper(thr, flags, DUK_BIDX_STRING_PROTOTYPE);
		duk_dup_0(thr);
		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);
	}
	/* Note: unbalanced stack on purpose */

	return 1;
}

DUK_LOCAL duk_ret_t duk__construct_from_codepoints(duk_hthread *thr, duk_bool_t nonbmp) {
	duk_bufwriter_ctx bw_alloc;
	duk_bufwriter_ctx *bw;
	duk_idx_t i, n;
	duk_ucodepoint_t cp;

	/* XXX: It would be nice to build the string directly but ToUint16()
	 * coercion is needed so a generic helper would not be very
	 * helpful (perhaps coerce the value stack first here and then
	 * build a string from a duk_tval number sequence in one go?).
	 */

	n = duk_get_top(thr);

	bw = &bw_alloc;
	DUK_BW_INIT_PUSHBUF(thr, bw, (duk_size_t) n);  /* initial estimate for ASCII only codepoints */

	for (i = 0; i < n; i++) {
		/* XXX: could improve bufwriter handling to write multiple codepoints
		 * with one ensure call but the relative benefit would be quite small.
		 */

		if (nonbmp) {
			/* ES2015 requires that (1) SameValue(cp, ToInteger(cp)) and
			 * (2) cp >= 0 and cp <= 0x10ffff.  This check does not
			 * implement the steps exactly but the outcome should be
			 * the same.
			 */
			duk_int32_t i32 = 0;
			if (!duk_is_whole_get_int32(duk_to_number(thr, i), &i32) ||
			    i32 < 0 || i32 > 0x10ffffL) {
				DUK_DCERROR_RANGE_INVALID_ARGS(thr);
			}
			DUK_ASSERT(i32 >= 0 && i32 <= 0x10ffffL);
			cp = (duk_ucodepoint_t) i32;
			DUK_BW_WRITE_ENSURE_CESU8(thr, bw, cp);
		} else {
#if defined(DUK_USE_NONSTD_STRING_FROMCHARCODE_32BIT)
			/* ToUint16() coercion is mandatory in the E5.1 specification, but
			 * this non-compliant behavior makes more sense because we support
			 * non-BMP codepoints.  Don't use CESU-8 because that'd create
			 * surrogate pairs.
			 */
			cp = (duk_ucodepoint_t) duk_to_uint32(thr, i);
			DUK_BW_WRITE_ENSURE_XUTF8(thr, bw, cp);
#else
			cp = (duk_ucodepoint_t) duk_to_uint16(thr, i);
			DUK_ASSERT(cp >= 0 && cp <= 0x10ffffL);
			DUK_BW_WRITE_ENSURE_CESU8(thr, bw, cp);
#endif
		}
	}

	DUK_BW_COMPACT(thr, bw);
	(void) duk_buffer_to_string(thr, -1);  /* Safe, extended UTF-8 or CESU-8 encoded. */
	return 1;
}

DUK_INTERNAL duk_ret_t duk_bi_string_constructor_from_char_code(duk_hthread *thr) {
	return duk__construct_from_codepoints(thr, 0 /*nonbmp*/);
}

#if defined(DUK_USE_ES6)
DUK_INTERNAL duk_ret_t duk_bi_string_constructor_from_code_point(duk_hthread *thr) {
	return duk__construct_from_codepoints(thr, 1 /*nonbmp*/);
}
#endif

/*
 *  toString(), valueOf()
 */

DUK_INTERNAL duk_ret_t duk_bi_string_prototype_to_string(duk_hthread *thr) {
	duk_tval *tv;

	duk_push_this(thr);
	tv = duk_require_tval(thr, -1);
	DUK_ASSERT(tv != NULL);

	if (DUK_TVAL_IS_STRING(tv)) {
		/* return as is */
	} else if (DUK_TVAL_IS_OBJECT(tv)) {
		duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
		DUK_ASSERT(h != NULL);

		/* Must be a "string object", i.e. class "String" */
		if (DUK_HOBJECT_GET_CLASS_NUMBER(h) != DUK_HOBJECT_CLASS_STRING) {
			goto type_error;
		}

		duk_xget_owndataprop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
		DUK_ASSERT(duk_is_string(thr, -1));
	} else {
		goto type_error;
	}

	(void) duk_require_hstring_notsymbol(thr, -1);  /* Reject symbols (and wrapped symbols). */
	return 1;

 type_error:
	DUK_DCERROR_TYPE_INVALID_ARGS(thr);
}

/*
 *  Character and charcode access
 */

DUK_INTERNAL duk_ret_t duk_bi_string_prototype_char_at(duk_hthread *thr) {
	duk_hstring *h;
	duk_int_t pos;

	/* XXX: faster implementation */

	h = duk_push_this_coercible_to_string(thr);
	DUK_ASSERT(h != NULL);

	pos = duk_to_int(thr, 0);

	if (sizeof(duk_size_t) >= sizeof(duk_uint_t)) {
		/* Cast to duk_size_t works in this case:
		 * - If pos < 0, (duk_size_t) pos will always be
		 *   >= max_charlen, and result will be the empty string
		 *   (see duk_substring()).
		 * - If pos >= 0, pos + 1 cannot wrap.
		 */
		DUK_ASSERT((duk_size_t) DUK_INT_MIN >= DUK_HSTRING_MAX_BYTELEN);
		DUK_ASSERT((duk_size_t) DUK_INT_MAX + 1U > (duk_size_t) DUK_INT_MAX);
		duk_substring(thr, -1, (duk_size_t) pos, (duk_size_t) pos + 1U);
	} else {
		/* If size_t is smaller than int, explicit bounds checks
		 * are needed because an int may wrap multiple times.
		 */
		if (DUK_UNLIKELY(pos < 0 || (duk_uint_t) pos >= (duk_uint_t) DUK_HSTRING_GET_CHARLEN(h))) {
			duk_push_hstring_empty(thr);
		} else {
			duk_substring(thr, -1, (duk_size_t) pos, (duk_size_t) pos + 1U);
		}
	}

	return 1;
}

/* Magic: 0=charCodeAt, 1=codePointAt */
DUK_INTERNAL duk_ret_t duk_bi_string_prototype_char_code_at(duk_hthread *thr) {
	duk_int_t pos;
	duk_hstring *h;
	duk_bool_t clamped;
	duk_uint32_t cp;
	duk_int_t magic;

	/* XXX: faster implementation */

	DUK_DDD(DUK_DDDPRINT("arg=%!T", (duk_tval *) duk_get_tval(thr, 0)));

	h = duk_push_this_coercible_to_string(thr);
	DUK_ASSERT(h != NULL);

	pos = duk_to_int_clamped_raw(thr,
	                             0 /*index*/,
	                             0 /*min(incl)*/,
	                             (duk_int_t) DUK_HSTRING_GET_CHARLEN(h) - 1 /*max(incl)*/,
	                             &clamped /*out_clamped*/);
#if defined(DUK_USE_ES6)
	magic = duk_get_current_magic(thr);
#else
	DUK_ASSERT(duk_get_current_magic(thr) == 0);
	magic = 0;
#endif
	if (clamped) {
		/* For out-of-bounds indices .charCodeAt() returns NaN and
		 * .codePointAt() returns undefined.
		 */
		if (magic != 0) {
			return 0;
		}
		duk_push_nan(thr);
	} else {
		DUK_ASSERT(pos >= 0);
		cp = (duk_uint32_t) duk_hstring_char_code_at_raw(thr, h, (duk_uint_t) pos, (duk_bool_t) magic /*surrogate_aware*/);
		duk_push_u32(thr, cp);
	}
	return 1;
}

/*
 *  substring(), substr(), slice()
 */

/* XXX: any chance of merging these three similar but still slightly
 * different algorithms so that footprint would be reduced?
 */

DUK_INTERNAL duk_ret_t duk_bi_string_prototype_substring(duk_hthread *thr) {
	duk_hstring *h;
	duk_int_t start_pos, end_pos;
	duk_int_t len;

	h = duk_push_this_coercible_to_string(thr);
	DUK_ASSERT(h != NULL);
	len = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h);

	/* [ start end str ] */

	start_pos = duk_to_int_clamped(thr, 0, 0, len);
	if (duk_is_undefined(thr, 1)) {
		end_pos = len;
	} else {
		end_pos = duk_to_int_clamped(thr, 1, 0, len);
	}
	DUK_ASSERT(start_pos >= 0 && start_pos <= len);
	DUK_ASSERT(end_pos >= 0 && end_pos <= len);

	if (start_pos > end_pos) {
		duk_int_t tmp = start_pos;
		start_pos = end_pos;
		end_pos = tmp;
	}

	DUK_ASSERT(end_pos >= start_pos);

	duk_substring(thr, -1, (duk_size_t) start_pos, (duk_size_t) end_pos);
	return 1;
}

#if defined(DUK_USE_SECTION_B)
DUK_INTERNAL duk_ret_t duk_bi_string_prototype_substr(duk_hthread *thr) {
	duk_hstring *h;
	duk_int_t start_pos, end_pos;
	duk_int_t len;

	/* Unlike non-obsolete String calls, substr() algorithm in E5.1
	 * specification will happily coerce undefined and null to strings
	 * ("undefined" and "null").
	 */
	duk_push_this(thr);
	h = duk_to_hstring_m1(thr);  /* Reject Symbols. */
	DUK_ASSERT(h != NULL);
	len = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h);

	/* [ start length str ] */

	/* The implementation for computing of start_pos and end_pos differs
	 * from the standard algorithm, but is intended to result in the exactly
	 * same behavior.  This is not always obvious.
	 */

	/* combines steps 2 and 5; -len ensures max() not needed for step 5 */
	start_pos = duk_to_int_clamped(thr, 0, -len, len);
	if (start_pos < 0) {
		start_pos = len + start_pos;
	}
	DUK_ASSERT(start_pos >= 0 && start_pos <= len);

	/* combines steps 3, 6; step 7 is not needed */
	if (duk_is_undefined(thr, 1)) {
		end_pos = len;
	} else {
		DUK_ASSERT(start_pos <= len);
		end_pos = start_pos + duk_to_int_clamped(thr, 1, 0, len - start_pos);
	}
	DUK_ASSERT(start_pos >= 0 && start_pos <= len);
	DUK_ASSERT(end_pos >= 0 && end_pos <= len);
	DUK_ASSERT(end_pos >= start_pos);

	duk_substring(thr, -1, (duk_size_t) start_pos, (duk_size_t) end_pos);
	return 1;
}
#endif  /* DUK_USE_SECTION_B */

DUK_INTERNAL duk_ret_t duk_bi_string_prototype_slice(duk_hthread *thr) {
	duk_hstring *h;
	duk_int_t start_pos, end_pos;
	duk_int_t len;

	h = duk_push_this_coercible_to_string(thr);
	DUK_ASSERT(h != NULL);
	len = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h);

	/* [ start end str ] */

	start_pos = duk_to_int_clamped(thr, 0, -len, len);
	if (start_pos < 0) {
		start_pos = len + start_pos;
	}
	if (duk_is_undefined(thr, 1)) {
		end_pos = len;
	} else {
		end_pos = duk_to_int_clamped(thr, 1, -len, len);
		if (end_pos < 0) {
			end_pos = len + end_pos;
		}
	}
	DUK_ASSERT(start_pos >= 0 && start_pos <= len);
	DUK_ASSERT(end_pos >= 0 && end_pos <= len);

	if (end_pos < start_pos) {
		end_pos = start_pos;
	}

	DUK_ASSERT(end_pos >= start_pos);

	duk_substring(thr, -1, (duk_size_t) start_pos, (duk_size_t) end_pos);
	return 1;
}

/*
 *  Case conversion
 */

DUK_INTERNAL duk_ret_t duk_bi_string_prototype_caseconv_shared(duk_hthread *thr) {
	duk_small_int_t uppercase = duk_get_current_magic(thr);

	(void) duk_push_this_coercible_to_string(thr);
	duk_unicode_case_convert_string(thr, (duk_bool_t) uppercase);
	return 1;
}

/*
 *  indexOf() and lastIndexOf()
 */

DUK_INTERNAL duk_ret_t duk_bi_string_prototype_indexof_shared(duk_hthread *thr) {
	duk_hstring *h_this;
	duk_hstring *h_search;
	duk_int_t clen_this;
	duk_int_t cpos;
	duk_small_uint_t is_lastindexof = (duk_small_uint_t) duk_get_current_magic(thr);  /* 0=indexOf, 1=lastIndexOf */

	h_this = duk_push_this_coercible_to_string(thr);
	DUK_ASSERT(h_this != NULL);
	clen_this = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h_this);

	h_search = duk_to_hstring(thr, 0);
	DUK_ASSERT(h_search != NULL);

	duk_to_number(thr, 1);
	if (duk_is_nan(thr, 1) && is_lastindexof) {
		/* indexOf: NaN should cause pos to be zero.
		 * lastIndexOf: NaN should cause pos to be +Infinity
		 * (and later be clamped to len).
		 */
		cpos = clen_this;
	} else {
		cpos = duk_to_int_clamped(thr, 1, 0, clen_this);
	}

	cpos = duk__str_search_shared(thr, h_this, h_search, cpos, is_lastindexof /*backwards*/);
	duk_push_int(thr, cpos);
	return 1;
}

/*
 *  replace()
 */

/* XXX: the current implementation works but is quite clunky; it compiles
 * to almost 1,4kB of x86 code so it needs to be simplified (better approach,
 * shared helpers, etc).  Some ideas for refactoring:
 *
 * - a primitive to convert a string into a regexp matcher (reduces matching
 *   code at the cost of making matching much slower)
 * - use replace() as a basic helper for match() and split(), which are both
 *   much simpler
 * - API call to get_prop and to_boolean
 */

DUK_INTERNAL duk_ret_t duk_bi_string_prototype_replace(duk_hthread *thr) {
	duk_hstring *h_input;
	duk_hstring *h_match;
	duk_hstring *h_search;
	duk_hobject *h_re;
	duk_bufwriter_ctx bw_alloc;
	duk_bufwriter_ctx *bw;
#if defined(DUK_USE_REGEXP_SUPPORT)
	duk_bool_t is_regexp;
	duk_bool_t is_global;
#endif
	duk_bool_t is_repl_func;
	duk_uint32_t match_start_coff, match_start_boff;
#if defined(DUK_USE_REGEXP_SUPPORT)
	duk_int_t match_caps;
#endif
	duk_uint32_t prev_match_end_boff;
	const duk_uint8_t *r_start, *r_end, *r;   /* repl string scan */
	duk_size_t tmp_sz;

	DUK_ASSERT_TOP(thr, 2);
	h_input = duk_push_this_coercible_to_string(thr);
	DUK_ASSERT(h_input != NULL);

	bw = &bw_alloc;
	DUK_BW_INIT_PUSHBUF(thr, bw, DUK_HSTRING_GET_BYTELEN(h_input));  /* input size is good output starting point */

	DUK_ASSERT_TOP(thr, 4);

	/* stack[0] = search value
	 * stack[1] = replace value
	 * stack[2] = input string
	 * stack[3] = result buffer
	 */

	h_re = duk_get_hobject_with_class(thr, 0, DUK_HOBJECT_CLASS_REGEXP);
	if (h_re) {
#if defined(DUK_USE_REGEXP_SUPPORT)
		is_regexp = 1;
		is_global = duk_get_prop_stridx_boolean(thr, 0, DUK_STRIDX_GLOBAL, NULL);

		if (is_global) {
			/* start match from beginning */
			duk_push_int(thr, 0);
			duk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);
		}
#else  /* DUK_USE_REGEXP_SUPPORT */
		DUK_DCERROR_UNSUPPORTED(thr);
#endif  /* DUK_USE_REGEXP_SUPPORT */
	} else {
		duk_to_string(thr, 0);  /* rejects symbols */
#if defined(DUK_USE_REGEXP_SUPPORT)
		is_regexp = 0;
		is_global = 0;
#endif
	}

	if (duk_is_function(thr, 1)) {
		is_repl_func = 1;
		r_start = NULL;
		r_end = NULL;
	} else {
		duk_hstring *h_repl;

		is_repl_func = 0;
		h_repl = duk_to_hstring(thr, 1);  /* reject symbols */
		DUK_ASSERT(h_repl != NULL);
		r_start = DUK_HSTRING_GET_DATA(h_repl);
		r_end = r_start + DUK_HSTRING_GET_BYTELEN(h_repl);
	}

	prev_match_end_boff = 0;

	for (;;) {
		/*
		 *  If matching with a regexp:
		 *    - non-global RegExp: lastIndex not touched on a match, zeroed
		 *      on a non-match
		 *    - global RegExp: on match, lastIndex will be updated by regexp
		 *      executor to point to next char after the matching part (so that
		 *      characters in the matching part are not matched again)
		 *
		 *  If matching with a string:
		 *    - always non-global match, find first occurrence
		 *
		 *  We need:
		 *    - The character offset of start-of-match for the replacer function
		 *    - The byte offsets for start-of-match and end-of-match to implement
		 *      the replacement values $&, $`, and $', and to copy non-matching
		 *      input string portions (including header and trailer) verbatim.
		 *
		 *  NOTE: the E5.1 specification is a bit vague how the RegExp should
		 *  behave in the replacement process; e.g. is matching done first for
		 *  all matches (in the global RegExp case) before any replacer calls
		 *  are made?  See: test-bi-string-proto-replace.js for discussion.
		 */

		DUK_ASSERT_TOP(thr, 4);

#if defined(DUK_USE_REGEXP_SUPPORT)
		if (is_regexp) {
			duk_dup_0(thr);
			duk_dup_2(thr);
			duk_regexp_match(thr);  /* [ ... regexp input ] -> [ res_obj ] */
			if (!duk_is_object(thr, -1)) {
				duk_pop(thr);
				break;
			}

			duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INDEX);
			DUK_ASSERT(duk_is_number(thr, -1));
			match_start_coff = duk_get_uint(thr, -1);
			duk_pop(thr);

			duk_get_prop_index(thr, -1, 0);
			DUK_ASSERT(duk_is_string(thr, -1));
			h_match = duk_known_hstring(thr, -1);
			duk_pop(thr);  /* h_match is borrowed, remains reachable through match_obj */

			if (DUK_HSTRING_GET_BYTELEN(h_match) == 0) {
				/* This should be equivalent to match() algorithm step 8.f.iii.2:
				 * detect an empty match and allow it, but don't allow it twice.
				 */
				duk_uint32_t last_index;

				duk_get_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);
				last_index = (duk_uint32_t) duk_get_uint(thr, -1);
				DUK_DDD(DUK_DDDPRINT("empty match, bump lastIndex: %ld -> %ld",
				                     (long) last_index, (long) (last_index + 1)));
				duk_pop(thr);
				duk_push_uint(thr, (duk_uint_t) (last_index + 1));
				duk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);
			}

			DUK_ASSERT(duk_get_length(thr, -1) <= DUK_INT_MAX);  /* string limits */
			match_caps = (duk_int_t) duk_get_length(thr, -1);
		} else {
#else  /* DUK_USE_REGEXP_SUPPORT */
		{  /* unconditionally */
#endif  /* DUK_USE_REGEXP_SUPPORT */
			const duk_uint8_t *p_start, *p_end, *p;   /* input string scan */
			const duk_uint8_t *q_start;               /* match string */
			duk_size_t q_blen;

#if defined(DUK_USE_REGEXP_SUPPORT)
			DUK_ASSERT(!is_global);  /* single match always */
#endif

			p_start = DUK_HSTRING_GET_DATA(h_input);
			p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
			p = p_start;

			h_search = duk_known_hstring(thr, 0);
			q_start = DUK_HSTRING_GET_DATA(h_search);
			q_blen = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_search);

			p_end -= q_blen;  /* ensure full memcmp() fits in while */

			match_start_coff = 0;

			while (p <= p_end) {
				DUK_ASSERT(p + q_blen <= DUK_HSTRING_GET_DATA(h_input) + DUK_HSTRING_GET_BYTELEN(h_input));
				if (duk_memcmp((const void *) p, (const void *) q_start, (size_t) q_blen) == 0) {
					duk_dup_0(thr);
					h_match = duk_known_hstring(thr, -1);
#if defined(DUK_USE_REGEXP_SUPPORT)
					match_caps = 0;
#endif
					goto found;
				}

				/* track utf-8 non-continuation bytes */
				if ((p[0] & 0xc0) != 0x80) {
					match_start_coff++;
				}
				p++;
			}

			/* not found */
			break;
		}
	 found:

		/* stack[0] = search value
		 * stack[1] = replace value
		 * stack[2] = input string
		 * stack[3] = result buffer
		 * stack[4] = regexp match OR match string
		 */

		match_start_boff = (duk_uint32_t) duk_heap_strcache_offset_char2byte(thr, h_input, match_start_coff);

		tmp_sz = (duk_size_t) (match_start_boff - prev_match_end_boff);
		DUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff, tmp_sz);

		prev_match_end_boff = match_start_boff + DUK_HSTRING_GET_BYTELEN(h_match);

		if (is_repl_func) {
			duk_idx_t idx_args;
			duk_hstring *h_repl;

			/* regexp res_obj is at index 4 */

			duk_dup_1(thr);
			idx_args = duk_get_top(thr);

#if defined(DUK_USE_REGEXP_SUPPORT)
			if (is_regexp) {
				duk_int_t idx;
				duk_require_stack(thr, match_caps + 2);
				for (idx = 0; idx < match_caps; idx++) {
					/* match followed by capture(s) */
					duk_get_prop_index(thr, 4, (duk_uarridx_t) idx);
				}
			} else {
#else  /* DUK_USE_REGEXP_SUPPORT */
			{  /* unconditionally */
#endif  /* DUK_USE_REGEXP_SUPPORT */
				/* match == search string, by definition */
				duk_dup_0(thr);
			}
			duk_push_uint(thr, (duk_uint_t) match_start_coff);
			duk_dup_2(thr);

			/* [ ... replacer match [captures] match_char_offset input ] */

			duk_call(thr, duk_get_top(thr) - idx_args);
			h_repl = duk_to_hstring_m1(thr);  /* -> [ ... repl_value ] */
			DUK_ASSERT(h_repl != NULL);

			DUK_BW_WRITE_ENSURE_HSTRING(thr, bw, h_repl);

			duk_pop(thr);  /* repl_value */
		} else {
			r = r_start;

			while (r < r_end) {
				duk_int_t ch1;
				duk_int_t ch2;
#if defined(DUK_USE_REGEXP_SUPPORT)
				duk_int_t ch3;
#endif
				duk_size_t left;

				ch1 = *r++;
				if (ch1 != DUK_ASC_DOLLAR) {
					goto repl_write;
				}
				DUK_ASSERT(r <= r_end);
				left = (duk_size_t) (r_end - r);

				if (left <= 0) {
					goto repl_write;
				}

				ch2 = r[0];
				switch (ch2) {
				case DUK_ASC_DOLLAR: {
					ch1 = (1 << 8) + DUK_ASC_DOLLAR;
					goto repl_write;
				}
				case DUK_ASC_AMP: {
					DUK_BW_WRITE_ENSURE_HSTRING(thr, bw, h_match);
					r++;
					continue;
				}
				case DUK_ASC_GRAVE: {
					tmp_sz = (duk_size_t) match_start_boff;
					DUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input), tmp_sz);
					r++;
					continue;
				}
				case DUK_ASC_SINGLEQUOTE: {
					duk_uint32_t match_end_boff;

					/* Use match charlen instead of bytelen, just in case the input and
					 * match codepoint encodings would have different lengths.
					 */
					/* XXX: charlen computed here, and also in char2byte helper. */
					match_end_boff = (duk_uint32_t) duk_heap_strcache_offset_char2byte(thr,
					                                                                   h_input,
					                                                                   match_start_coff + (duk_uint_fast32_t) DUK_HSTRING_GET_CHARLEN(h_match));

					tmp_sz = (duk_size_t) (DUK_HSTRING_GET_BYTELEN(h_input) - match_end_boff);
					DUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input) + match_end_boff, tmp_sz);
					r++;
					continue;
				}
				default: {
#if defined(DUK_USE_REGEXP_SUPPORT)
					duk_int_t capnum, captmp, capadv;
					/* XXX: optional check, match_caps is zero if no regexp,
					 * so dollar will be interpreted literally anyway.
					 */

					if (!is_regexp) {
						goto repl_write;
					}

					if (!(ch2 >= DUK_ASC_0 && ch2 <= DUK_ASC_9)) {
						goto repl_write;
					}
					capnum = ch2 - DUK_ASC_0;
					capadv = 1;

					if (left >= 2) {
						ch3 = r[1];
						if (ch3 >= DUK_ASC_0 && ch3 <= DUK_ASC_9) {
							captmp = capnum * 10 + (ch3 - DUK_ASC_0);
							if (captmp < match_caps) {
								capnum = captmp;
								capadv = 2;
							}
						}
					}

					if (capnum > 0 && capnum < match_caps) {
						DUK_ASSERT(is_regexp != 0);  /* match_caps == 0 without regexps */

						/* regexp res_obj is at offset 4 */
						duk_get_prop_index(thr, 4, (duk_uarridx_t) capnum);
						if (duk_is_string(thr, -1)) {
							duk_hstring *h_tmp_str;

							h_tmp_str = duk_known_hstring(thr, -1);

							DUK_BW_WRITE_ENSURE_HSTRING(thr, bw, h_tmp_str);
						} else {
							/* undefined -> skip (replaced with empty) */
						}
						duk_pop(thr);
						r += capadv;
						continue;
					} else {
						goto repl_write;
					}
#else  /* DUK_USE_REGEXP_SUPPORT */
					goto repl_write;  /* unconditionally */
#endif  /* DUK_USE_REGEXP_SUPPORT */
				}  /* default case */
				}  /* switch (ch2) */

			 repl_write:
				/* ch1 = (r_increment << 8) + byte */

				DUK_BW_WRITE_ENSURE_U8(thr, bw, (duk_uint8_t) (ch1 & 0xff));
				r += ch1 >> 8;
			}  /* while repl */
		}  /* if (is_repl_func) */

		duk_pop(thr);  /* pop regexp res_obj or match string */

#if defined(DUK_USE_REGEXP_SUPPORT)
		if (!is_global) {
#else
		{  /* unconditionally; is_global==0 */
#endif
			break;
		}
	}

	/* trailer */
	tmp_sz = (duk_size_t) (DUK_HSTRING_GET_BYTELEN(h_input) - prev_match_end_boff);
	DUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff, tmp_sz);

	DUK_ASSERT_TOP(thr, 4);
	DUK_BW_COMPACT(thr, bw);
	(void) duk_buffer_to_string(thr, -1);  /* Safe if inputs are safe. */
	return 1;
}

/*
 *  split()
 */

/* XXX: very messy now, but works; clean up, remove unused variables (nomimally
 * used so compiler doesn't complain).
 */

DUK_INTERNAL duk_ret_t duk_bi_string_prototype_split(duk_hthread *thr) {
	duk_hstring *h_input;
	duk_hstring *h_sep;
	duk_uint32_t limit;
	duk_uint32_t arr_idx;
#if defined(DUK_USE_REGEXP_SUPPORT)
	duk_bool_t is_regexp;
#endif
	duk_bool_t matched;  /* set to 1 if any match exists (needed for empty input special case) */
	duk_uint32_t prev_match_end_coff, prev_match_end_boff;
	duk_uint32_t match_start_boff, match_start_coff;
	duk_uint32_t match_end_boff, match_end_coff;

	h_input = duk_push_this_coercible_to_string(thr);
	DUK_ASSERT(h_input != NULL);

	duk_push_array(thr);

	if (duk_is_undefined(thr, 1)) {
		limit = 0xffffffffUL;
	} else {
		limit = duk_to_uint32(thr, 1);
	}

	if (limit == 0) {
		return 1;
	}

	/* If the separator is a RegExp, make a "clone" of it.  The specification
	 * algorithm calls [[Match]] directly for specific indices; we emulate this
	 * by tweaking lastIndex and using a "force global" variant of duk_regexp_match()
	 * which will use global-style matching even when the RegExp itself is non-global.
	 */

	if (duk_is_undefined(thr, 0)) {
		/* The spec algorithm first does "R = ToString(separator)" before checking
		 * whether separator is undefined.  Since this is side effect free, we can
		 * skip the ToString() here.
		 */
		duk_dup_2(thr);
		duk_put_prop_index(thr, 3, 0);
		return 1;
	} else if (duk_get_hobject_with_class(thr, 0, DUK_HOBJECT_CLASS_REGEXP) != NULL) {
#if defined(DUK_USE_REGEXP_SUPPORT)
		duk_push_hobject_bidx(thr, DUK_BIDX_REGEXP_CONSTRUCTOR);
		duk_dup_0(thr);
		duk_new(thr, 1);  /* [ ... RegExp val ] -> [ ... res ] */
		duk_replace(thr, 0);
		/* lastIndex is initialized to zero by new RegExp() */
		is_regexp = 1;
#else
		DUK_DCERROR_UNSUPPORTED(thr);
#endif
	} else {
		duk_to_string(thr, 0);
#if defined(DUK_USE_REGEXP_SUPPORT)
		is_regexp = 0;
#endif
	}

	/* stack[0] = separator (string or regexp)
	 * stack[1] = limit
	 * stack[2] = input string
	 * stack[3] = result array
	 */

	prev_match_end_boff = 0;
	prev_match_end_coff = 0;
	arr_idx = 0;
	matched = 0;

	for (;;) {
		/*
		 *  The specification uses RegExp [[Match]] to attempt match at specific
		 *  offsets.  We don't have such a primitive, so we use an actual RegExp
		 *  and tweak lastIndex.  Since the RegExp may be non-global, we use a
		 *  special variant which forces global-like behavior for matching.
		 */

		DUK_ASSERT_TOP(thr, 4);

#if defined(DUK_USE_REGEXP_SUPPORT)
		if (is_regexp) {
			duk_dup_0(thr);
			duk_dup_2(thr);
			duk_regexp_match_force_global(thr);  /* [ ... regexp input ] -> [ res_obj ] */
			if (!duk_is_object(thr, -1)) {
				duk_pop(thr);
				break;
			}
			matched = 1;

			duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INDEX);
			DUK_ASSERT(duk_is_number(thr, -1));
			match_start_coff = duk_get_uint(thr, -1);
			match_start_boff = (duk_uint32_t) duk_heap_strcache_offset_char2byte(thr, h_input, match_start_coff);
			duk_pop(thr);

			if (match_start_coff == DUK_HSTRING_GET_CHARLEN(h_input)) {
				/* don't allow an empty match at the end of the string */
				duk_pop(thr);
				break;
			}

			duk_get_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);
			DUK_ASSERT(duk_is_number(thr, -1));
			match_end_coff = duk_get_uint(thr, -1);
			match_end_boff = (duk_uint32_t) duk_heap_strcache_offset_char2byte(thr, h_input, match_end_coff);
			duk_pop(thr);

			/* empty match -> bump and continue */
			if (prev_match_end_boff == match_end_boff) {
				duk_push_uint(thr, (duk_uint_t) (match_end_coff + 1));
				duk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);
				duk_pop(thr);
				continue;
			}
		} else {
#else  /* DUK_USE_REGEXP_SUPPORT */
		{  /* unconditionally */
#endif  /* DUK_USE_REGEXP_SUPPORT */
			const duk_uint8_t *p_start, *p_end, *p;   /* input string scan */
			const duk_uint8_t *q_start;               /* match string */
			duk_size_t q_blen, q_clen;

			p_start = DUK_HSTRING_GET_DATA(h_input);
			p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
			p = p_start + prev_match_end_boff;

			h_sep = duk_known_hstring(thr, 0);  /* symbol already rejected above */
			q_start = DUK_HSTRING_GET_DATA(h_sep);
			q_blen = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_sep);
			q_clen = (duk_size_t) DUK_HSTRING_GET_CHARLEN(h_sep);

			p_end -= q_blen;  /* ensure full memcmp() fits in while */

			match_start_coff = prev_match_end_coff;

			if (q_blen == 0) {
				/* Handle empty separator case: it will always match, and always
				 * triggers the check in step 13.c.iii initially.  Note that we
				 * must skip to either end of string or start of first codepoint,
				 * skipping over any continuation bytes!
				 *
				 * Don't allow an empty string to match at the end of the input.
				 */

				matched = 1;  /* empty separator can always match */

				match_start_coff++;
				p++;
				while (p < p_end) {
					if ((p[0] & 0xc0) != 0x80) {
						goto found;
					}
					p++;
				}
				goto not_found;
			}

			DUK_ASSERT(q_blen > 0 && q_clen > 0);
			while (p <= p_end) {
				DUK_ASSERT(p + q_blen <= DUK_HSTRING_GET_DATA(h_input) + DUK_HSTRING_GET_BYTELEN(h_input));
				DUK_ASSERT(q_blen > 0);  /* no issues with empty memcmp() */
				if (duk_memcmp((const void *) p, (const void *) q_start, (size_t) q_blen) == 0) {
					/* never an empty match, so step 13.c.iii can't be triggered */
					goto found;
				}

				/* track utf-8 non-continuation bytes */
				if ((p[0] & 0xc0) != 0x80) {
					match_start_coff++;
				}
				p++;
			}

		 not_found:
			/* not found */
			break;

		 found:
			matched = 1;
			match_start_boff = (duk_uint32_t) (p - p_start);
			match_end_coff = (duk_uint32_t) (match_start_coff + q_clen);  /* constrained by string length */
			match_end_boff = (duk_uint32_t) (match_start_boff + q_blen);  /* ditto */

			/* empty match (may happen with empty separator) -> bump and continue */
			if (prev_match_end_boff == match_end_boff) {
				prev_match_end_boff++;
				prev_match_end_coff++;
				continue;
			}
		}  /* if (is_regexp) */

		/* stack[0] = separator (string or regexp)
		 * stack[1] = limit
		 * stack[2] = input string
		 * stack[3] = result array
		 * stack[4] = regexp res_obj (if is_regexp)
		 */

		DUK_DDD(DUK_DDDPRINT("split; match_start b=%ld,c=%ld, match_end b=%ld,c=%ld, prev_end b=%ld,c=%ld",
		                     (long) match_start_boff, (long) match_start_coff,
		                     (long) match_end_boff, (long) match_end_coff,
		                     (long) prev_match_end_boff, (long) prev_match_end_coff));

		duk_push_lstring(thr,
		                 (const char *) (DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff),
		                 (duk_size_t) (match_start_boff - prev_match_end_boff));
		duk_put_prop_index(thr, 3, arr_idx);
		arr_idx++;
		if (arr_idx >= limit) {
			goto hit_limit;
		}

#if defined(DUK_USE_REGEXP_SUPPORT)
		if (is_regexp) {
			duk_size_t i, len;

			len = duk_get_length(thr, 4);
			for (i = 1; i < len; i++) {
				DUK_ASSERT(i <= DUK_UARRIDX_MAX);  /* cannot have >4G captures */
				duk_get_prop_index(thr, 4, (duk_uarridx_t) i);
				duk_put_prop_index(thr, 3, arr_idx);
				arr_idx++;
				if (arr_idx >= limit) {
					goto hit_limit;
				}
			}

			duk_pop(thr);
			/* lastIndex already set up for next match */
		} else {
#else  /* DUK_USE_REGEXP_SUPPORT */
		{  /* unconditionally */
#endif  /* DUK_USE_REGEXP_SUPPORT */
			/* no action */
		}

		prev_match_end_boff = match_end_boff;
		prev_match_end_coff = match_end_coff;
		continue;
	}  /* for */

	/* Combined step 11 (empty string special case) and 14-15. */

	DUK_DDD(DUK_DDDPRINT("split trailer; prev_end b=%ld,c=%ld",
	                     (long) prev_match_end_boff, (long) prev_match_end_coff));

	if (DUK_HSTRING_GET_BYTELEN(h_input) > 0 || !matched) {
		/* Add trailer if:
		 *   a) non-empty input
		 *   b) empty input and no (zero size) match found (step 11)
		 */

		duk_push_lstring(thr,
		                 (const char *) DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff,
		                 (duk_size_t) (DUK_HSTRING_GET_BYTELEN(h_input) - prev_match_end_boff));
		duk_put_prop_index(thr, 3, arr_idx);
		/* No arr_idx update or limit check */
	}

	return 1;

 hit_limit:
#if defined(DUK_USE_REGEXP_SUPPORT)
	if (is_regexp) {
		duk_pop(thr);
	}
#endif

	return 1;
}

/*
 *  Various
 */

#if defined(DUK_USE_REGEXP_SUPPORT)
DUK_LOCAL void duk__to_regexp_helper(duk_hthread *thr, duk_idx_t idx, duk_bool_t force_new) {
	duk_hobject *h;

	/* Shared helper for match() steps 3-4, search() steps 3-4. */

	DUK_ASSERT(idx >= 0);

	if (force_new) {
		goto do_new;
	}

	h = duk_get_hobject_with_class(thr, idx, DUK_HOBJECT_CLASS_REGEXP);
	if (!h) {
		goto do_new;
	}
	return;

 do_new:
	duk_push_hobject_bidx(thr, DUK_BIDX_REGEXP_CONSTRUCTOR);
	duk_dup(thr, idx);
	duk_new(thr, 1);  /* [ ... RegExp val ] -> [ ... res ] */
	duk_replace(thr, idx);
}
#endif  /* DUK_USE_REGEXP_SUPPORT */

#if defined(DUK_USE_REGEXP_SUPPORT)
DUK_INTERNAL duk_ret_t duk_bi_string_prototype_search(duk_hthread *thr) {
	/* Easiest way to implement the search required by the specification
	 * is to do a RegExp test() with lastIndex forced to zero.  To avoid
	 * side effects on the argument, "clone" the RegExp if a RegExp was
	 * given as input.
	 *
	 * The global flag of the RegExp should be ignored; setting lastIndex
	 * to zero (which happens when "cloning" the RegExp) should have an
	 * equivalent effect.
	 */

	DUK_ASSERT_TOP(thr, 1);
	(void) duk_push_this_coercible_to_string(thr);  /* at index 1 */
	duk__to_regexp_helper(thr, 0 /*index*/, 1 /*force_new*/);

	/* stack[0] = regexp
	 * stack[1] = string
	 */

	/* Avoid using RegExp.prototype methods, as they're writable and
	 * configurable and may have been changed.
	 */

	duk_dup_0(thr);
	duk_dup_1(thr);  /* [ ... re_obj input ] */
	duk_regexp_match(thr);  /* -> [ ... res_obj ] */

	if (!duk_is_object(thr, -1)) {
		duk_push_int(thr, -1);
		return 1;
	}

	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INDEX);
	DUK_ASSERT(duk_is_number(thr, -1));
	return 1;
}
#endif  /* DUK_USE_REGEXP_SUPPORT */

#if defined(DUK_USE_REGEXP_SUPPORT)
DUK_INTERNAL duk_ret_t duk_bi_string_prototype_match(duk_hthread *thr) {
	duk_bool_t global;
	duk_int_t prev_last_index;
	duk_int_t this_index;
	duk_int_t arr_idx;

	DUK_ASSERT_TOP(thr, 1);
	(void) duk_push_this_coercible_to_string(thr);
	duk__to_regexp_helper(thr, 0 /*index*/, 0 /*force_new*/);
	global = duk_get_prop_stridx_boolean(thr, 0, DUK_STRIDX_GLOBAL, NULL);
	DUK_ASSERT_TOP(thr, 2);

	/* stack[0] = regexp
	 * stack[1] = string
	 */

	if (!global) {
		duk_regexp_match(thr);  /* -> [ res_obj ] */
		return 1;  /* return 'res_obj' */
	}

	/* Global case is more complex. */

	/* [ regexp string ] */

	duk_push_int(thr, 0);
	duk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);
	duk_push_array(thr);

	/* [ regexp string res_arr ] */

	prev_last_index = 0;
	arr_idx = 0;

	for (;;) {
		DUK_ASSERT_TOP(thr, 3);

		duk_dup_0(thr);
		duk_dup_1(thr);
		duk_regexp_match(thr);  /* -> [ ... regexp string ] -> [ ... res_obj ] */

		if (!duk_is_object(thr, -1)) {
			duk_pop(thr);
			break;
		}

		duk_get_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);
		DUK_ASSERT(duk_is_number(thr, -1));
		this_index = duk_get_int(thr, -1);
		duk_pop(thr);

		if (this_index == prev_last_index) {
			this_index++;
			duk_push_int(thr, this_index);
			duk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);
		}
		prev_last_index = this_index;

		duk_get_prop_index(thr, -1, 0);  /* match string */
		duk_put_prop_index(thr, 2, (duk_uarridx_t) arr_idx);
		arr_idx++;
		duk_pop(thr);  /* res_obj */
	}

	if (arr_idx == 0) {
		duk_push_null(thr);
	}

	return 1;  /* return 'res_arr' or 'null' */
}
#endif  /* DUK_USE_REGEXP_SUPPORT */

DUK_INTERNAL duk_ret_t duk_bi_string_prototype_concat(duk_hthread *thr) {
	/* duk_concat() coerces arguments with ToString() in correct order */
	(void) duk_push_this_coercible_to_string(thr);
	duk_insert(thr, 0);  /* this is relatively expensive */
	duk_concat(thr, duk_get_top(thr));
	return 1;
}

DUK_INTERNAL duk_ret_t duk_bi_string_prototype_trim(duk_hthread *thr) {
	DUK_ASSERT_TOP(thr, 0);
	(void) duk_push_this_coercible_to_string(thr);
	duk_trim(thr, 0);
	DUK_ASSERT_TOP(thr, 1);
	return 1;
}

#if defined(DUK_USE_ES6)
DUK_INTERNAL duk_ret_t duk_bi_string_prototype_repeat(duk_hthread *thr) {
	duk_hstring *h_input;
	duk_size_t input_blen;
	duk_size_t result_len;
	duk_int_t count_signed;
	duk_uint_t count;
	const duk_uint8_t *src;
	duk_uint8_t *buf;
	duk_uint8_t *p;
	duk_double_t d;
#if !defined(DUK_USE_PREFER_SIZE)
	duk_size_t copy_size;
	duk_uint8_t *p_end;
#endif

	DUK_ASSERT_TOP(thr, 1);
	h_input = duk_push_this_coercible_to_string(thr);
	DUK_ASSERT(h_input != NULL);
	input_blen = DUK_HSTRING_GET_BYTELEN(h_input);

	/* Count is ToNumber() coerced; +Infinity must be always rejected
	 * (even if input string is zero length), as well as negative values
	 * and -Infinity.  -Infinity doesn't require an explicit check
	 * because duk_get_int() clamps it to DUK_INT_MIN which gets rejected
	 * as a negative value (regardless of input string length).
	 */
	d = duk_to_number(thr, 0);
	if (duk_double_is_posinf(d)) {
		goto fail_range;
	}
	count_signed = duk_get_int(thr, 0);
	if (count_signed < 0) {
		goto fail_range;
	}
	count = (duk_uint_t) count_signed;

	/* Overflow check for result length. */
	result_len = count * input_blen;
	if (count != 0 && result_len / count != input_blen) {
		goto fail_range;
	}

	/* Temporary fixed buffer, later converted to string. */
	buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, result_len);
	DUK_ASSERT(buf != NULL);
	src = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
	DUK_ASSERT(src != NULL);

#if defined(DUK_USE_PREFER_SIZE)
	p = buf;
	while (count-- > 0) {
		duk_memcpy((void *) p, (const void *) src, input_blen);  /* copy size may be zero, but pointers are valid */
		p += input_blen;
	}
#else  /* DUK_USE_PREFER_SIZE */
	/* Take advantage of already copied pieces to speed up the process
	 * especially for small repeated strings.
	 */
	p = buf;
	p_end = p + result_len;
	copy_size = input_blen;
	for (;;) {
		duk_size_t remain = (duk_size_t) (p_end - p);
		DUK_DDD(DUK_DDDPRINT("remain=%ld, copy_size=%ld, input_blen=%ld, result_len=%ld",
		                     (long) remain, (long) copy_size, (long) input_blen,
		                     (long) result_len));
		if (remain <= copy_size) {
			/* If result_len is zero, this case is taken and does
			 * a zero size copy (with valid pointers).
			 */
			duk_memcpy((void *) p, (const void *) src, remain);
			break;
		} else {
			duk_memcpy((void *) p, (const void *) src, copy_size);
			p += copy_size;
		}

		src = (const duk_uint8_t *) buf;  /* Use buf as source for larger copies. */
		copy_size = (duk_size_t) (p - buf);
	}
#endif  /* DUK_USE_PREFER_SIZE */

	/* XXX: It would be useful to be able to create a duk_hstring with
	 * a certain byte size whose data area wasn't initialized and which
	 * wasn't in the string table yet.  This would allow a string to be
	 * constructed directly without a buffer temporary and when it was
	 * finished, it could be injected into the string table.  Currently
	 * this isn't possible because duk_hstrings are only tracked by the
	 * intern table (they are not in heap_allocated).
	 */

	duk_buffer_to_string(thr, -1);  /* Safe if input is safe. */
	return 1;

 fail_range:
	DUK_DCERROR_RANGE_INVALID_ARGS(thr);
}
#endif  /* DUK_USE_ES6 */

DUK_INTERNAL duk_ret_t duk_bi_string_prototype_locale_compare(duk_hthread *thr) {
	duk_hstring *h1;
	duk_hstring *h2;
	duk_size_t h1_len, h2_len, prefix_len;
	duk_small_int_t ret = 0;
	duk_small_int_t rc;

	/* The current implementation of localeCompare() is simply a codepoint
	 * by codepoint comparison, implemented with a simple string compare
	 * because UTF-8 should preserve codepoint ordering (assuming valid
	 * shortest UTF-8 encoding).
	 *
	 * The specification requires that the return value must be related
	 * to the sort order: e.g. negative means that 'this' comes before
	 * 'that' in sort order.  We assume an ascending sort order.
	 */

	/* XXX: could share code with duk_js_ops.c, duk_js_compare_helper */

	h1 = duk_push_this_coercible_to_string(thr);
	DUK_ASSERT(h1 != NULL);

	h2 = duk_to_hstring(thr, 0);
	DUK_ASSERT(h2 != NULL);

	h1_len = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h1);
	h2_len = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h2);
	prefix_len = (h1_len <= h2_len ? h1_len : h2_len);

	rc = (duk_small_int_t) duk_memcmp((const void *) DUK_HSTRING_GET_DATA(h1),
	                                  (const void *) DUK_HSTRING_GET_DATA(h2),
	                                  (size_t) prefix_len);

	if (rc < 0) {
		ret = -1;
		goto done;
	} else if (rc > 0) {
		ret = 1;
		goto done;
	}

	/* prefix matches, lengths matter now */
	if (h1_len > h2_len) {
		ret = 1;
		goto done;
	} else if (h1_len == h2_len) {
		DUK_ASSERT(ret == 0);
		goto done;
	}
	ret = -1;
	goto done;

 done:
	duk_push_int(thr, (duk_int_t) ret);
	return 1;
}

#if defined(DUK_USE_ES6)
DUK_INTERNAL duk_ret_t duk_bi_string_prototype_startswith_endswith(duk_hthread *thr) {
	duk_int_t magic;
	duk_hstring *h;
	duk_hstring *h_search;
	duk_size_t blen_search;
	const duk_uint8_t *p_cmp_start;
	duk_bool_t result;

	h = duk_push_this_coercible_to_string(thr);
	DUK_ASSERT(h != NULL);

	h_search = duk__str_tostring_notregexp(thr, 0);
	DUK_ASSERT(h_search != NULL);

	magic = duk_get_current_magic(thr);

	p_cmp_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
	blen_search = DUK_HSTRING_GET_BYTELEN(h_search);

	if (duk_is_undefined(thr, 1)) {
		if (magic) {
			p_cmp_start = p_cmp_start + DUK_HSTRING_GET_BYTELEN(h) - blen_search;
		} else {
			/* p_cmp_start already OK */
		}
	} else {
		duk_int_t len;
		duk_int_t pos;

		DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= DUK_INT_MAX);
		len = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h);
		pos = duk_to_int_clamped(thr, 1, 0, len);
		DUK_ASSERT(pos >= 0 && pos <= len);

		if (magic) {
			p_cmp_start -= blen_search;  /* Conceptually subtracted last, but do already here. */
		}
		DUK_ASSERT(pos >= 0 && pos <= len);

		p_cmp_start += duk_heap_strcache_offset_char2byte(thr, h, (duk_uint_fast32_t) pos);
	}

	/* The main comparison can be done using a memcmp() rather than
	 * doing codepoint comparisons: for CESU-8 strings there is a
	 * canonical representation for every codepoint.  But we do need
	 * to deal with the char/byte offset translation to find the
	 * comparison range.
	 */

	result = 0;
	if (p_cmp_start >= DUK_HSTRING_GET_DATA(h) &&
	    (duk_size_t) (p_cmp_start - (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h)) + blen_search <= DUK_HSTRING_GET_BYTELEN(h)) {
		if (duk_memcmp((const void *) p_cmp_start,
		               (const void *) DUK_HSTRING_GET_DATA(h_search),
		               (size_t) blen_search) == 0) {
			result = 1;
		}
	}

	duk_push_boolean(thr, result);
	return 1;
}
#endif  /* DUK_USE_ES6 */

#if defined(DUK_USE_ES6)
DUK_INTERNAL duk_ret_t duk_bi_string_prototype_includes(duk_hthread *thr) {
	duk_hstring *h;
	duk_hstring *h_search;
	duk_int_t len;
	duk_int_t pos;

	h = duk_push_this_coercible_to_string(thr);
	DUK_ASSERT(h != NULL);

	h_search = duk__str_tostring_notregexp(thr, 0);
	DUK_ASSERT(h_search != NULL);

	len = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h);
	pos = duk_to_int_clamped(thr, 1, 0, len);
	DUK_ASSERT(pos >= 0 && pos <= len);

	pos = duk__str_search_shared(thr, h, h_search, pos, 0 /*backwards*/);
	duk_push_boolean(thr, pos >= 0);
	return 1;
}
#endif  /* DUK_USE_ES6 */
#endif  /* DUK_USE_STRING_BUILTIN */
#line 1 "duk_bi_symbol.c"
/*
 *  Symbol built-in
 */

/* #include duk_internal.h -> already included */

#if defined(DUK_USE_SYMBOL_BUILTIN)

/*
 *  Constructor
 */

DUK_INTERNAL duk_ret_t duk_bi_symbol_constructor_shared(duk_hthread *thr) {
	const duk_uint8_t *desc;
	duk_size_t len;
	duk_uint8_t *buf;
	duk_uint8_t *p;
	duk_int_t magic;

	magic = duk_get_current_magic(thr);
	if (duk_is_undefined(thr, 0) && (magic == 0)) {
		/* Symbol() accepts undefined and empty string, but they are
		 * treated differently.
		 */
		desc = NULL;
		len = 0;
	} else {
		/* Symbol.for() coerces undefined to 'undefined' */
		desc = (const duk_uint8_t *) duk_to_lstring(thr, 0, &len);
	}

	/* Maximum symbol data length:
	 *   +1    initial byte (0x80 or 0x81)
	 *   +len  description
	 *   +1    0xff after description, before unique suffix
	 *   +17   autogenerated unique suffix: 'ffffffff-ffffffff' is longest
	 *   +1    0xff after unique suffix for symbols with undefined description
	 */
	buf = (duk_uint8_t *) duk_push_fixed_buffer(thr, 1 + len + 1 + 17 + 1);
	DUK_ASSERT(buf != NULL);
	p = buf + 1;
	DUK_ASSERT(desc != NULL || len == 0);  /* may be NULL if len is 0 */
	duk_memcpy_unsafe((void *) p, (const void *) desc, len);
	p += len;
	if (magic == 0) {
		/* Symbol(): create unique symbol.  Use two 32-bit values
		 * to avoid dependency on 64-bit types and 64-bit integer
		 * formatting (at least for now).
		 */
		if (++thr->heap->sym_counter[0] == 0) {
			thr->heap->sym_counter[1]++;
		}
		p += DUK_SPRINTF((char *) p, "\xFF" "%lx-%lx",
		                 (unsigned long) thr->heap->sym_counter[1],
		                 (unsigned long) thr->heap->sym_counter[0]);
		if (desc == NULL) {
			/* Special case for 'undefined' description, trailing
			 * 0xff distinguishes from empty string description,
			 * but needs minimal special case handling elsewhere.
			 */
			*p++ = 0xff;
		}
		buf[0] = 0x81;
	} else {
		/* Symbol.for(): create a global symbol */
		buf[0] = 0x80;
	}

	duk_push_lstring(thr, (const char *) buf, (duk_size_t) (p - buf));
	DUK_DDD(DUK_DDDPRINT("created symbol: %!T", duk_get_tval(thr, -1)));
	return 1;
}

DUK_LOCAL duk_hstring *duk__auto_unbox_symbol(duk_hthread *thr, duk_tval *tv_arg) {
	duk_tval *tv;
	duk_hobject *h_obj;
	duk_hstring *h_str;

	DUK_ASSERT(tv_arg != NULL);

	/* XXX: add internal helper: duk_auto_unbox_tval(thr, tv, mask); */
	/* XXX: add internal helper: duk_auto_unbox(thr, tv, idx); */

	tv = tv_arg;
	if (DUK_TVAL_IS_OBJECT(tv)) {
		h_obj = DUK_TVAL_GET_OBJECT(tv);
		DUK_ASSERT(h_obj != NULL);
		if (DUK_HOBJECT_GET_CLASS_NUMBER(h_obj) == DUK_HOBJECT_CLASS_SYMBOL) {
			tv = duk_hobject_get_internal_value_tval_ptr(thr->heap, h_obj);
			if (tv == NULL) {
				return NULL;
			}
		} else {
			return NULL;
		}
	}

	if (!DUK_TVAL_IS_STRING(tv)) {
		return NULL;
	}
	h_str = DUK_TVAL_GET_STRING(tv);
	DUK_ASSERT(h_str != NULL);

	/* Here symbol is more expected than not. */
	if (DUK_UNLIKELY(!DUK_HSTRING_HAS_SYMBOL(h_str))) {
		return NULL;
	}

	return h_str;
}

DUK_INTERNAL duk_ret_t duk_bi_symbol_tostring_shared(duk_hthread *thr) {
	duk_hstring *h_str;

	h_str = duk__auto_unbox_symbol(thr, DUK_HTHREAD_THIS_PTR(thr));
	if (h_str == NULL) {
		return DUK_RET_TYPE_ERROR;
	}

	if (duk_get_current_magic(thr) == 0) {
		/* .toString() */
		duk_push_symbol_descriptive_string(thr, h_str);
	} else {
		/* .valueOf() */
		duk_push_hstring(thr, h_str);
	}
	return 1;
}

DUK_INTERNAL duk_ret_t duk_bi_symbol_key_for(duk_hthread *thr) {
	duk_hstring *h;
	const duk_uint8_t *p;

	/* Argument must be a symbol but not checked here.  The initial byte
	 * check will catch non-symbol strings.
	 */
	h = duk_require_hstring(thr, 0);
	DUK_ASSERT(h != NULL);

	p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
	DUK_ASSERT(p != NULL);

	/* Even for zero length strings there's at least one NUL byte so
	 * we can safely check the initial byte.
	 */
	if (p[0] == 0x80) {
		/* Global symbol, return its key (bytes just after the initial byte). */
		duk_push_lstring(thr, (const char *) (p + 1), (duk_size_t) (DUK_HSTRING_GET_BYTELEN(h) - 1));
		return 1;
	} else if (p[0] == 0x81 || p[0] == 0x82 || p[0] == 0xff) {
		/* Local symbol or hidden symbol, return undefined. */
		return 0;
	}

	/* Covers normal strings and unknown initial bytes. */
	return DUK_RET_TYPE_ERROR;
}

DUK_INTERNAL duk_ret_t duk_bi_symbol_toprimitive(duk_hthread *thr) {
	duk_hstring *h_str;

	h_str = duk__auto_unbox_symbol(thr, DUK_HTHREAD_THIS_PTR(thr));
	if (h_str == NULL) {
		return DUK_RET_TYPE_ERROR;
	}
	duk_push_hstring(thr, h_str);
	return 1;
}

#endif  /* DUK_USE_SYMBOL_BUILTIN */
#line 1 "duk_bi_thread.c"
/*
 *  Thread builtins
 */

/* #include duk_internal.h -> already included */

/*
 *  Constructor
 */

#if defined(DUK_USE_COROUTINE_SUPPORT)
DUK_INTERNAL duk_ret_t duk_bi_thread_constructor(duk_hthread *thr) {
	duk_hthread *new_thr;
	duk_hobject *func;

	/* Check that the argument is callable; this is not 100% because we
	 * don't allow native functions to be a thread's initial function.
	 * Resume will reject such functions in any case.
	 */
	/* XXX: need a duk_require_func_promote_lfunc() */
	func = duk_require_hobject_promote_lfunc(thr, 0);
	DUK_ASSERT(func != NULL);
	duk_require_callable(thr, 0);

	duk_push_thread(thr);
	new_thr = (duk_hthread *) duk_known_hobject(thr, -1);
	new_thr->state = DUK_HTHREAD_STATE_INACTIVE;

	/* push initial function call to new thread stack; this is
	 * picked up by resume().
	 */
	duk_push_hobject(new_thr, func);

	return 1;  /* return thread */
}
#endif

/*
 *  Resume a thread.
 *
 *  The thread must be in resumable state, either (a) new thread which hasn't
 *  yet started, or (b) a thread which has previously yielded.  This method
 *  must be called from an ECMAScript function.
 *
 *  Args:
 *    - thread
 *    - value
 *    - isError (defaults to false)
 *
 *  Note: yield and resume handling is currently asymmetric.
 */

#if defined(DUK_USE_COROUTINE_SUPPORT)
DUK_INTERNAL duk_ret_t duk_bi_thread_resume(duk_hthread *ctx) {
	duk_hthread *thr = (duk_hthread *) ctx;
	duk_hthread *thr_resume;
	duk_hobject *caller_func;
	duk_small_uint_t is_error;

	DUK_DDD(DUK_DDDPRINT("Duktape.Thread.resume(): thread=%!T, value=%!T, is_error=%!T",
	                     (duk_tval *) duk_get_tval(thr, 0),
	                     (duk_tval *) duk_get_tval(thr, 1),
	                     (duk_tval *) duk_get_tval(thr, 2)));

	DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);
	DUK_ASSERT(thr->heap->curr_thread == thr);

	thr_resume = duk_require_hthread(thr, 0);
	DUK_ASSERT(duk_get_top(thr) == 3);
	is_error = (duk_small_uint_t) duk_to_boolean_top_pop(thr);
	DUK_ASSERT(duk_get_top(thr) == 2);

	/* [ thread value ] */

	/*
	 *  Thread state and calling context checks
	 */

	if (thr->callstack_top < 2) {
		DUK_DD(DUK_DDPRINT("resume state invalid: callstack should contain at least 2 entries (caller and Duktape.Thread.resume)"));
		goto state_error;
	}
	DUK_ASSERT(thr->callstack_curr != NULL);
	DUK_ASSERT(thr->callstack_curr->parent != NULL);
	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL);  /* us */
	DUK_ASSERT(DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)));
	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr->parent) != NULL);  /* caller */

	caller_func = DUK_ACT_GET_FUNC(thr->callstack_curr->parent);
	if (!DUK_HOBJECT_IS_COMPFUNC(caller_func)) {
		DUK_DD(DUK_DDPRINT("resume state invalid: caller must be ECMAScript code"));
		goto state_error;
	}

	/* Note: there is no requirement that: 'thr->callstack_preventcount == 1'
	 * like for yield.
	 */

	if (thr_resume->state != DUK_HTHREAD_STATE_INACTIVE &&
	    thr_resume->state != DUK_HTHREAD_STATE_YIELDED) {
		DUK_DD(DUK_DDPRINT("resume state invalid: target thread must be INACTIVE or YIELDED"));
		goto state_error;
	}

	DUK_ASSERT(thr_resume->state == DUK_HTHREAD_STATE_INACTIVE ||
	           thr_resume->state == DUK_HTHREAD_STATE_YIELDED);

	/* Further state-dependent pre-checks */

	if (thr_resume->state == DUK_HTHREAD_STATE_YIELDED) {
		/* no pre-checks now, assume a previous yield() has left things in
		 * tip-top shape (longjmp handler will assert for these).
		 */
	} else {
		duk_hobject *h_fun;

		DUK_ASSERT(thr_resume->state == DUK_HTHREAD_STATE_INACTIVE);

		/* The initial function must be an ECMAScript function (but
		 * can be bound).  We must make sure of that before we longjmp
		 * because an error in the RESUME handler call processing will
		 * not be handled very cleanly.
		 */
		if ((thr_resume->callstack_top != 0) ||
		    (thr_resume->valstack_top - thr_resume->valstack != 1)) {
			goto state_error;
		}

		duk_push_tval(thr, DUK_GET_TVAL_NEGIDX(thr_resume, -1));
		duk_resolve_nonbound_function(thr);
		h_fun = duk_require_hobject(thr, -1);  /* reject lightfuncs on purpose */
		if (!DUK_HOBJECT_IS_CALLABLE(h_fun) || !DUK_HOBJECT_IS_COMPFUNC(h_fun)) {
			goto state_error;
		}
		duk_pop(thr);
	}

#if 0
	/* This check would prevent a heap destruction time finalizer from
	 * launching a coroutine, which would ensure that during finalization
	 * 'thr' would always equal heap_thread.  Normal runtime finalizers
	 * run with ms_running == 0, i.e. outside mark-and-sweep.  See GH-2030.
	 */
	if (thr->heap->ms_running) {
		DUK_D(DUK_DPRINT("refuse Duktape.Thread.resume() when ms_running != 0"));
		goto state_error;
	}
#endif

	/*
	 *  The error object has been augmented with a traceback and other
	 *  info from its creation point -- usually another thread.  The
	 *  error handler is called here right before throwing, but it also
	 *  runs in the resumer's thread.  It might be nice to get a traceback
	 *  from the resumee but this is not the case now.
	 */

#if defined(DUK_USE_AUGMENT_ERROR_THROW)
	if (is_error) {
		DUK_ASSERT_TOP(thr, 2);  /* value (error) is at stack top */
		duk_err_augment_error_throw(thr);  /* in resumer's context */
	}
#endif

#if defined(DUK_USE_DEBUG)
	if (is_error) {
		DUK_DDD(DUK_DDDPRINT("RESUME ERROR: thread=%!T, value=%!T",
		                     (duk_tval *) duk_get_tval(thr, 0),
		                     (duk_tval *) duk_get_tval(thr, 1)));
	} else if (thr_resume->state == DUK_HTHREAD_STATE_YIELDED) {
		DUK_DDD(DUK_DDDPRINT("RESUME NORMAL: thread=%!T, value=%!T",
		                     (duk_tval *) duk_get_tval(thr, 0),
		                     (duk_tval *) duk_get_tval(thr, 1)));
	} else {
		DUK_DDD(DUK_DDDPRINT("RESUME INITIAL: thread=%!T, value=%!T",
		                     (duk_tval *) duk_get_tval(thr, 0),
		                     (duk_tval *) duk_get_tval(thr, 1)));
	}
#endif

	thr->heap->lj.type = DUK_LJ_TYPE_RESUME;

	/* lj value2: thread */
	DUK_ASSERT(thr->valstack_bottom < thr->valstack_top);
	DUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value2, &thr->valstack_bottom[0]);  /* side effects */

	/* lj value1: value */
	DUK_ASSERT(thr->valstack_bottom + 1 < thr->valstack_top);
	DUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value1, &thr->valstack_bottom[1]);  /* side effects */
	DUK_TVAL_CHKFAST_INPLACE_SLOW(&thr->heap->lj.value1);

	thr->heap->lj.iserror = is_error;

	DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL);  /* call is from executor, so we know we have a jmpbuf */
	duk_err_longjmp(thr);  /* execution resumes in bytecode executor */
	DUK_UNREACHABLE();
	/* Never here, fall through to error (from compiler point of view). */

 state_error:
	DUK_DCERROR_TYPE_INVALID_STATE(thr);
}
#endif

/*
 *  Yield the current thread.
 *
 *  The thread must be in yieldable state: it must have a resumer, and there
 *  must not be any yield-preventing calls (native calls and constructor calls,
 *  currently) in the thread's call stack (otherwise a resume would not be
 *  possible later).  This method must be called from an ECMAScript function.
 *
 *  Args:
 *    - value
 *    - isError (defaults to false)
 *
 *  Note: yield and resume handling is currently asymmetric.
 */

#if defined(DUK_USE_COROUTINE_SUPPORT)
DUK_INTERNAL duk_ret_t duk_bi_thread_yield(duk_hthread *thr) {
	duk_hobject *caller_func;
	duk_small_uint_t is_error;

	DUK_DDD(DUK_DDDPRINT("Duktape.Thread.yield(): value=%!T, is_error=%!T",
	                     (duk_tval *) duk_get_tval(thr, 0),
	                     (duk_tval *) duk_get_tval(thr, 1)));

	DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);
	DUK_ASSERT(thr->heap->curr_thread == thr);

	DUK_ASSERT(duk_get_top(thr) == 2);
	is_error = (duk_small_uint_t) duk_to_boolean_top_pop(thr);
	DUK_ASSERT(duk_get_top(thr) == 1);

	/* [ value ] */

	/*
	 *  Thread state and calling context checks
	 */

	if (!thr->resumer) {
		DUK_DD(DUK_DDPRINT("yield state invalid: current thread must have a resumer"));
		goto state_error;
	}
	DUK_ASSERT(thr->resumer->state == DUK_HTHREAD_STATE_RESUMED);

	if (thr->callstack_top < 2) {
		DUK_DD(DUK_DDPRINT("yield state invalid: callstack should contain at least 2 entries (caller and Duktape.Thread.yield)"));
		goto state_error;
	}
	DUK_ASSERT(thr->callstack_curr != NULL);
	DUK_ASSERT(thr->callstack_curr->parent != NULL);
	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL);  /* us */
	DUK_ASSERT(DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)));
	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr->parent) != NULL);  /* caller */

	caller_func = DUK_ACT_GET_FUNC(thr->callstack_curr->parent);
	if (!DUK_HOBJECT_IS_COMPFUNC(caller_func)) {
		DUK_DD(DUK_DDPRINT("yield state invalid: caller must be ECMAScript code"));
		goto state_error;
	}

	DUK_ASSERT(thr->callstack_preventcount >= 1);  /* should never be zero, because we (Duktape.Thread.yield) are on the stack */
	if (thr->callstack_preventcount != 1) {
		/* Note: the only yield-preventing call is Duktape.Thread.yield(), hence check for 1, not 0 */
		DUK_DD(DUK_DDPRINT("yield state invalid: there must be no yield-preventing calls in current thread callstack (preventcount is %ld)",
		                   (long) thr->callstack_preventcount));
		goto state_error;
	}

	/*
	 *  The error object has been augmented with a traceback and other
	 *  info from its creation point -- usually the current thread.
	 *  The error handler, however, is called right before throwing
	 *  and runs in the yielder's thread.
	 */

#if defined(DUK_USE_AUGMENT_ERROR_THROW)
	if (is_error) {
		DUK_ASSERT_TOP(thr, 1);  /* value (error) is at stack top */
		duk_err_augment_error_throw(thr);  /* in yielder's context */
	}
#endif

#if defined(DUK_USE_DEBUG)
	if (is_error) {
		DUK_DDD(DUK_DDDPRINT("YIELD ERROR: value=%!T",
		                     (duk_tval *) duk_get_tval(thr, 0)));
	} else {
		DUK_DDD(DUK_DDDPRINT("YIELD NORMAL: value=%!T",
		                     (duk_tval *) duk_get_tval(thr, 0)));
	}
#endif

	/*
	 *  Process yield
	 *
	 *  After longjmp(), processing continues in bytecode executor longjmp
	 *  handler, which will e.g. update thr->resumer to NULL.
	 */

	thr->heap->lj.type = DUK_LJ_TYPE_YIELD;

	/* lj value1: value */
	DUK_ASSERT(thr->valstack_bottom < thr->valstack_top);
	DUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value1, &thr->valstack_bottom[0]);  /* side effects */
	DUK_TVAL_CHKFAST_INPLACE_SLOW(&thr->heap->lj.value1);

	thr->heap->lj.iserror = is_error;

	DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL);  /* call is from executor, so we know we have a jmpbuf */
	duk_err_longjmp(thr);  /* execution resumes in bytecode executor */
	DUK_UNREACHABLE();
	/* Never here, fall through to error (from compiler point of view). */

 state_error:
	DUK_DCERROR_TYPE_INVALID_STATE(thr);
}
#endif

#if defined(DUK_USE_COROUTINE_SUPPORT)
DUK_INTERNAL duk_ret_t duk_bi_thread_current(duk_hthread *thr) {
	duk_push_current_thread(thr);
	return 1;
}
#endif
#line 1 "duk_bi_thrower.c"
/*
 *  Type error thrower, E5 Section 13.2.3.
 */

/* #include duk_internal.h -> already included */

DUK_INTERNAL duk_ret_t duk_bi_type_error_thrower(duk_hthread *thr) {
	DUK_DCERROR_TYPE_INVALID_ARGS(thr);
}
#line 1 "duk_debug_fixedbuffer.c"
/*
 *  Fixed buffer helper useful for debugging, requires no allocation
 *  which is critical for debugging.
 */

/* #include duk_internal.h -> already included */

#if defined(DUK_USE_DEBUG)

DUK_INTERNAL void duk_fb_put_bytes(duk_fixedbuffer *fb, const duk_uint8_t *buffer, duk_size_t length) {
	duk_size_t avail;
	duk_size_t copylen;

	avail = (fb->offset >= fb->length ? (duk_size_t) 0 : (duk_size_t) (fb->length - fb->offset));
	if (length > avail) {
		copylen = avail;
		fb->truncated = 1;
	} else {
		copylen = length;
	}
	duk_memcpy_unsafe(fb->buffer + fb->offset, buffer, copylen);
	fb->offset += copylen;
}

DUK_INTERNAL void duk_fb_put_byte(duk_fixedbuffer *fb, duk_uint8_t x) {
	duk_fb_put_bytes(fb, (const duk_uint8_t *) &x, 1);
}

DUK_INTERNAL void duk_fb_put_cstring(duk_fixedbuffer *fb, const char *x) {
	duk_fb_put_bytes(fb, (const duk_uint8_t *) x, (duk_size_t) DUK_STRLEN(x));
}

DUK_INTERNAL void duk_fb_sprintf(duk_fixedbuffer *fb, const char *fmt, ...) {
	duk_size_t avail;
	va_list ap;

	va_start(ap, fmt);
	avail = (fb->offset >= fb->length ? (duk_size_t) 0 : (duk_size_t) (fb->length - fb->offset));
	if (avail > 0) {
		duk_int_t res = (duk_int_t) DUK_VSNPRINTF((char *) (fb->buffer + fb->offset), avail, fmt, ap);
		if (res < 0) {
			/* error */
		} else if ((duk_size_t) res >= avail) {
			/* (maybe) truncated */
			fb->offset += avail;
			if ((duk_size_t) res > avail) {
				/* actual chars dropped (not just NUL term) */
				fb->truncated = 1;
			}
		} else {
			/* normal */
			fb->offset += (duk_size_t) res;
		}
	}
	va_end(ap);
}

DUK_INTERNAL void duk_fb_put_funcptr(duk_fixedbuffer *fb, duk_uint8_t *fptr, duk_size_t fptr_size) {
	char buf[64+1];
	duk_debug_format_funcptr(buf, sizeof(buf), fptr, fptr_size);
	buf[sizeof(buf) - 1] = (char) 0;
	duk_fb_put_cstring(fb, buf);
}

DUK_INTERNAL duk_bool_t duk_fb_is_full(duk_fixedbuffer *fb) {
	return (fb->offset >= fb->length);
}

#endif  /* DUK_USE_DEBUG */
#line 1 "duk_debug_vsnprintf.c"
/*
 *  Custom formatter for debug printing, allowing Duktape specific data
 *  structures (such as tagged values and heap objects) to be printed with
 *  a nice format string.  Because debug printing should not affect execution
 *  state, formatting here must be independent of execution (see implications
 *  below) and must not allocate memory.
 *
 *  Custom format tags begin with a '%!' to safely distinguish them from
 *  standard format tags.  The following conversions are supported:
 *
 *     %!T    tagged value (duk_tval *)
 *     %!O    heap object (duk_heaphdr *)
 *     %!I    decoded bytecode instruction
 *     %!X    bytecode instruction opcode name (arg is long)
 *     %!C    catcher (duk_catcher *)
 *     %!A    activation (duk_activation *)
 *
 *  Everything is serialized in a JSON-like manner.  The default depth is one
 *  level, internal prototype is not followed, and internal properties are not
 *  serialized.  The following modifiers change this behavior:
 *
 *     @      print pointers
 *     #      print binary representations (where applicable)
 *     d      deep traversal of own properties (not prototype)
 *     p      follow prototype chain (useless without 'd')
 *     i      include internal properties (other than prototype)
 *     x      hexdump buffers
 *     h      heavy formatting
 *
 *  For instance, the following serializes objects recursively, but does not
 *  follow the prototype chain nor print internal properties: "%!dO".
 *
 *  Notes:
 *
 *    * Standard snprintf return value semantics seem to vary.  This
 *      implementation returns the number of bytes it actually wrote
 *      (excluding the null terminator).  If retval == buffer size,
 *      output was truncated (except for corner cases).
 *
 *    * Output format is intentionally different from ECMAScript
 *      formatting requirements, as formatting here serves debugging
 *      of internals.
 *
 *    * Depth checking (and updating) is done in each type printer
 *      separately, to allow them to call each other freely.
 *
 *    * Some pathological structures might take ages to print (e.g.
 *      self recursion with 100 properties pointing to the object
 *      itself).  To guard against these, each printer also checks
 *      whether the output buffer is full; if so, early exit.
 *
 *    * Reference loops are detected using a loop stack.
 */

/* #include duk_internal.h -> already included */

#if defined(DUK_USE_DEBUG)

/* #include stdio.h -> already included */
/* #include stdarg.h -> already included */
#include <string.h>

/* list of conversion specifiers that terminate a format tag;
 * this is unfortunately guesswork.
 */
#define DUK__ALLOWED_STANDARD_SPECIFIERS  "diouxXeEfFgGaAcsCSpnm"

/* maximum length of standard format tag that we support */
#define DUK__MAX_FORMAT_TAG_LENGTH  32

/* heapobj recursion depth when deep printing is selected */
#define DUK__DEEP_DEPTH_LIMIT  8

/* maximum recursion depth for loop detection stacks */
#define DUK__LOOP_STACK_DEPTH  256

/* must match bytecode defines now; build autogenerate? */
DUK_LOCAL const char * const duk__bc_optab[256] = {
	"LDREG", "STREG", "JUMP", "LDCONST", "LDINT", "LDINTX", "LDTHIS", "LDUNDEF",
	"LDNULL", "LDTRUE", "LDFALSE", "GETVAR", "BNOT", "LNOT", "UNM", "UNP",
	"EQ_RR", "EQ_CR", "EQ_RC", "EQ_CC", "NEQ_RR", "NEQ_CR", "NEQ_RC", "NEQ_CC",
	"SEQ_RR", "SEQ_CR", "SEQ_RC", "SEQ_CC", "SNEQ_RR", "SNEQ_CR", "SNEQ_RC", "SNEQ_CC",

	"GT_RR", "GT_CR", "GT_RC", "GT_CC", "GE_RR", "GE_CR", "GE_RC", "GE_CC",
	"LT_RR", "LT_CR", "LT_RC", "LT_CC", "LE_RR", "LE_CR", "LE_RC", "LE_CC",
	"IFTRUE_R", "IFTRUE_C", "IFFALSE_R", "IFFALSE_C", "ADD_RR", "ADD_CR", "ADD_RC", "ADD_CC",
	"SUB_RR", "SUB_CR", "SUB_RC", "SUB_CC", "MUL_RR", "MUL_CR", "MUL_RC", "MUL_CC",

	"DIV_RR", "DIV_CR", "DIV_RC", "DIV_CC", "MOD_RR", "MOD_CR", "MOD_RC", "MOD_CC",
	"EXP_RR", "EXP_CR", "EXP_RC", "EXP_CC", "BAND_RR", "BAND_CR", "BAND_RC", "BAND_CC",
	"BOR_RR", "BOR_CR", "BOR_RC", "BOR_CC", "BXOR_RR", "BXOR_CR", "BXOR_RC", "BXOR_CC",
	"BASL_RR", "BASL_CR", "BASL_RC", "BASL_CC", "BLSR_RR", "BLSR_CR", "BLSR_RC", "BLSR_CC",

	"BASR_RR", "BASR_CR", "BASR_RC", "BASR_CC", "INSTOF_RR", "INSTOF_CR", "INSTOF_RC", "INSTOF_CC",
	"IN_RR", "IN_CR", "IN_RC", "IN_CC", "GETPROP_RR", "GETPROP_CR", "GETPROP_RC", "GETPROP_CC",
	"PUTPROP_RR", "PUTPROP_CR", "PUTPROP_RC", "PUTPROP_CC", "DELPROP_RR", "DELPROP_CR", "DELPROP_RC", "DELPROP_CC",
	"PREINCR", "PREDECR", "POSTINCR", "POSTDECR", "PREINCV", "PREDECV", "POSTINCV", "POSTDECV",

	"PREINCP_RR", "PREINCP_CR", "PREINCP_RC", "PREINCP_CC", "PREDECP_RR", "PREDECP_CR", "PREDECP_RC", "PREDECP_CC",
	"POSTINCP_RR", "POSTINCP_CR", "POSTINCP_RC", "POSTINCP_CC", "POSTDECP_RR", "POSTDECP_CR", "POSTDECP_RC", "POSTDECP_CC",
	"DECLVAR_RR", "DECLVAR_CR", "DECLVAR_RC", "DECLVAR_CC", "REGEXP_RR", "REGEXP_RC", "REGEXP_CR", "REGEXP_CC",
	"CLOSURE", "TYPEOF", "TYPEOFID", "PUTVAR", "DELVAR", "RETREG", "RETUNDEF", "RETCONST",

	"RETCONSTN", "LABEL", "ENDLABEL", "BREAK", "CONTINUE", "TRYCATCH", "ENDTRY", "ENDCATCH",
	"ENDFIN", "THROW", "INVLHS", "CSREG", "CSVAR_RR", "CSVAR_CR", "CSVAR_RC", "CSVAR_CC",
	"CALL0", "CALL1", "CALL2", "CALL3", "CALL4", "CALL5", "CALL6", "CALL7",
	"CALL8", "CALL9", "CALL10", "CALL11", "CALL12", "CALL13", "CALL14", "CALL15",

	"NEWOBJ", "NEWARR", "MPUTOBJ", "MPUTOBJI", "INITSET", "INITGET", "MPUTARR", "MPUTARRI",
	"SETALEN", "INITENUM", "NEXTENUM", "NEWTARGET", "DEBUGGER", "NOP", "INVALID", "UNUSED207",
	"GETPROPC_RR", "GETPROPC_CR", "GETPROPC_RC", "GETPROPC_CC", "UNUSED212", "UNUSED213", "UNUSED214", "UNUSED215",
	"UNUSED216", "UNUSED217", "UNUSED218", "UNUSED219", "UNUSED220", "UNUSED221", "UNUSED222", "UNUSED223",

	"UNUSED224", "UNUSED225", "UNUSED226", "UNUSED227", "UNUSED228", "UNUSED229", "UNUSED230", "UNUSED231",
	"UNUSED232", "UNUSED233", "UNUSED234", "UNUSED235", "UNUSED236", "UNUSED237", "UNUSED238", "UNUSED239",
	"UNUSED240", "UNUSED241", "UNUSED242", "UNUSED243", "UNUSED244", "UNUSED245", "UNUSED246", "UNUSED247",
	"UNUSED248", "UNUSED249", "UNUSED250", "UNUSED251", "UNUSED252", "UNUSED253", "UNUSED254", "UNUSED255"
};

typedef struct duk__dprint_state duk__dprint_state;
struct duk__dprint_state {
	duk_fixedbuffer *fb;

	/* loop_stack_index could be perhaps be replaced by 'depth', but it's nice
	 * to not couple these two mechanisms unnecessarily.
	 */
	duk_hobject *loop_stack[DUK__LOOP_STACK_DEPTH];
	duk_int_t loop_stack_index;
	duk_int_t loop_stack_limit;

	duk_int_t depth;
	duk_int_t depth_limit;

	duk_bool_t pointer;
	duk_bool_t heavy;
	duk_bool_t binary;
	duk_bool_t follow_proto;
	duk_bool_t internal;
	duk_bool_t hexdump;
};

/* helpers */
DUK_LOCAL_DECL void duk__print_hstring(duk__dprint_state *st, duk_hstring *k, duk_bool_t quotes);
DUK_LOCAL_DECL void duk__print_hobject(duk__dprint_state *st, duk_hobject *h);
DUK_LOCAL_DECL void duk__print_hbuffer(duk__dprint_state *st, duk_hbuffer *h);
DUK_LOCAL_DECL void duk__print_tval(duk__dprint_state *st, duk_tval *tv);
DUK_LOCAL_DECL void duk__print_instr(duk__dprint_state *st, duk_instr_t ins);
DUK_LOCAL_DECL void duk__print_heaphdr(duk__dprint_state *st, duk_heaphdr *h);
DUK_LOCAL_DECL void duk__print_shared_heaphdr(duk__dprint_state *st, duk_heaphdr *h);
DUK_LOCAL_DECL void duk__print_shared_heaphdr_string(duk__dprint_state *st, duk_heaphdr_string *h);

DUK_LOCAL void duk__print_shared_heaphdr(duk__dprint_state *st, duk_heaphdr *h) {
	duk_fixedbuffer *fb = st->fb;

	if (st->heavy) {
		duk_fb_sprintf(fb, "(%p)", (void *) h);
	}

	if (!h) {
		return;
	}

	if (st->binary) {
		duk_size_t i;
		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LBRACKET);
		for (i = 0; i < (duk_size_t) sizeof(*h); i++) {
			duk_fb_sprintf(fb, "%02lx", (unsigned long) ((duk_uint8_t *)h)[i]);
		}
		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RBRACKET);
	}

#if defined(DUK_USE_REFERENCE_COUNTING)  /* currently implicitly also DUK_USE_DOUBLE_LINKED_HEAP */
	if (st->heavy) {
		duk_fb_sprintf(fb, "[h_next=%p,h_prev=%p,h_refcount=%lu,h_flags=%08lx,type=%ld,"
		               "reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
		               (void *) DUK_HEAPHDR_GET_NEXT(NULL, h),
		               (void *) DUK_HEAPHDR_GET_PREV(NULL, h),
		               (unsigned long) DUK_HEAPHDR_GET_REFCOUNT(h),
		               (unsigned long) DUK_HEAPHDR_GET_FLAGS(h),
		               (long) DUK_HEAPHDR_GET_TYPE(h),
		               (long) (DUK_HEAPHDR_HAS_REACHABLE(h) ? 1 : 0),
		               (long) (DUK_HEAPHDR_HAS_TEMPROOT(h) ? 1 : 0),
		               (long) (DUK_HEAPHDR_HAS_FINALIZABLE(h) ? 1 : 0),
		               (long) (DUK_HEAPHDR_HAS_FINALIZED(h) ? 1 : 0));
	}
#else
	if (st->heavy) {
		duk_fb_sprintf(fb, "[h_next=%p,h_flags=%08lx,type=%ld,reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
		               (void *) DUK_HEAPHDR_GET_NEXT(NULL, h),
		               (unsigned long) DUK_HEAPHDR_GET_FLAGS(h),
		               (long) DUK_HEAPHDR_GET_TYPE(h),
		               (long) (DUK_HEAPHDR_HAS_REACHABLE(h) ? 1 : 0),
		               (long) (DUK_HEAPHDR_HAS_TEMPROOT(h) ? 1 : 0),
		               (long) (DUK_HEAPHDR_HAS_FINALIZABLE(h) ? 1 : 0),
		               (long) (DUK_HEAPHDR_HAS_FINALIZED(h) ? 1 : 0));
	}
#endif
}

DUK_LOCAL void duk__print_shared_heaphdr_string(duk__dprint_state *st, duk_heaphdr_string *h) {
	duk_fixedbuffer *fb = st->fb;

	if (st->heavy) {
		duk_fb_sprintf(fb, "(%p)", (void *) h);
	}

	if (!h) {
		return;
	}

	if (st->binary) {
		duk_size_t i;
		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LBRACKET);
		for (i = 0; i < (duk_size_t) sizeof(*h); i++) {
			duk_fb_sprintf(fb, "%02lx", (unsigned long) ((duk_uint8_t *)h)[i]);
		}
		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RBRACKET);
	}

#if defined(DUK_USE_REFERENCE_COUNTING)
	if (st->heavy) {
		duk_fb_sprintf(fb, "[h_refcount=%lu,h_flags=%08lx,type=%ld,reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
		               (unsigned long) DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h),
		               (unsigned long) DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) h),
		               (long) DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) h),
		               (long) (DUK_HEAPHDR_HAS_REACHABLE((duk_heaphdr *) h) ? 1 : 0),
		               (long) (DUK_HEAPHDR_HAS_TEMPROOT((duk_heaphdr *) h) ? 1 : 0),
		               (long) (DUK_HEAPHDR_HAS_FINALIZABLE((duk_heaphdr *) h) ? 1 : 0),
		               (long) (DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) h) ? 1 : 0));
	}
#else
	if (st->heavy) {
		duk_fb_sprintf(fb, "[h_flags=%08lx,type=%ld,reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
		               (unsigned long) DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) h),
		               (long) DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) h),
		               (long) (DUK_HEAPHDR_HAS_REACHABLE((duk_heaphdr *) h) ? 1 : 0),
		               (long) (DUK_HEAPHDR_HAS_TEMPROOT((duk_heaphdr *) h) ? 1 : 0),
		               (long) (DUK_HEAPHDR_HAS_FINALIZABLE((duk_heaphdr *) h) ? 1 : 0),
		               (long) (DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) h) ? 1 : 0));
	}
#endif
}

DUK_LOCAL void duk__print_hstring(duk__dprint_state *st, duk_hstring *h, duk_bool_t quotes) {
	duk_fixedbuffer *fb = st->fb;
	const duk_uint8_t *p;
	const duk_uint8_t *p_end;

	/* terminal type: no depth check */

	if (duk_fb_is_full(fb)) {
		return;
	}

	duk__print_shared_heaphdr_string(st, &h->hdr);

	if (!h) {
		duk_fb_put_cstring(fb, "NULL");
		return;
	}

	p = DUK_HSTRING_GET_DATA(h);
	p_end = p + DUK_HSTRING_GET_BYTELEN(h);

	if (p_end > p && p[0] == DUK_ASC_UNDERSCORE) {
		/* If property key begins with underscore, encode it with
		 * forced quotes (e.g. "_Foo") to distinguish it from encoded
		 * internal properties (e.g. \x82Bar -> _Bar).
		 */
		quotes = 1;
	}

	if (quotes) {
		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_DOUBLEQUOTE);
	}
	while (p < p_end) {
		duk_uint8_t ch = *p++;

		/* two special escapes: '\' and '"', other printables as is */
		if (ch == '\\') {
			duk_fb_sprintf(fb, "\\\\");
		} else if (ch == '"') {
			duk_fb_sprintf(fb, "\\\"");
		} else if (ch >= 0x20 && ch <= 0x7e) {
			duk_fb_put_byte(fb, ch);
		} else if (ch == 0x82 && !quotes) {
			/* encode \x82Bar as _Bar if no quotes are
			 * applied, this is for readable internal keys.
			 */
			duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_UNDERSCORE);
		} else {
			duk_fb_sprintf(fb, "\\x%02lx", (unsigned long) ch);
		}
	}
	if (quotes) {
		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_DOUBLEQUOTE);
	}
#if defined(DUK_USE_REFERENCE_COUNTING)
	/* XXX: limit to quoted strings only, to save keys from being cluttered? */
	duk_fb_sprintf(fb, "/%lu", (unsigned long) DUK_HEAPHDR_GET_REFCOUNT(&h->hdr));
#endif
}

#define DUK__COMMA()  do { \
		if (first) { \
			first = 0; \
		} else { \
			duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_COMMA); \
		} \
	} while (0)

DUK_LOCAL void duk__print_hobject(duk__dprint_state *st, duk_hobject *h) {
	duk_fixedbuffer *fb = st->fb;
	duk_uint_fast32_t i;
	duk_tval *tv;
	duk_hstring *key;
	duk_bool_t first = 1;
	const char *brace1 = "{";
	const char *brace2 = "}";
	duk_bool_t pushed_loopstack = 0;

	if (duk_fb_is_full(fb)) {
		return;
	}

	duk__print_shared_heaphdr(st, &h->hdr);

	if (h && DUK_HOBJECT_HAS_ARRAY_PART(h)) {
		brace1 = "[";
		brace2 = "]";
	}

	if (!h) {
		duk_fb_put_cstring(fb, "NULL");
		goto finished;
	}

	if (st->depth >= st->depth_limit) {
		const char *subtype = "generic";

		if (DUK_HOBJECT_IS_COMPFUNC(h)) {
			subtype = "compfunc";
		} else if (DUK_HOBJECT_IS_NATFUNC(h)) {
			subtype = "natfunc";
		} else if (DUK_HOBJECT_IS_THREAD(h)) {
			subtype = "thread";
		} else if (DUK_HOBJECT_IS_BUFOBJ(h)) {
			subtype = "bufobj";
		} else if (DUK_HOBJECT_IS_ARRAY(h)) {
			subtype = "array";
		}
		duk_fb_sprintf(fb, "%sobject/%s %p%s", (const char *) brace1, subtype, (void *) h, (const char *) brace2);
		return;
	}

	for (i = 0; i < (duk_uint_fast32_t) st->loop_stack_index; i++) {
		if (st->loop_stack[i] == h) {
			duk_fb_sprintf(fb, "%sLOOP:%p%s", (const char *) brace1, (void *) h, (const char *) brace2);
			return;
		}
	}

	/* after this, return paths should 'goto finished' for decrement */
	st->depth++;

	if (st->loop_stack_index >= st->loop_stack_limit) {
		duk_fb_sprintf(fb, "%sOUT-OF-LOOP-STACK%s", (const char *) brace1, (const char *) brace2);
		goto finished;
	}
	st->loop_stack[st->loop_stack_index++] = h;
	pushed_loopstack = 1;

	/*
	 *  Notation: double underscore used for internal properties which are not
	 *  stored in the property allocation (e.g. '__valstack').
	 */

	duk_fb_put_cstring(fb, brace1);

	if (DUK_HOBJECT_GET_PROPS(NULL, h)) {
		duk_uint32_t a_limit;

		a_limit = DUK_HOBJECT_GET_ASIZE(h);
		if (st->internal) {
			/* dump all allocated entries, unused entries print as 'unused',
			 * note that these may extend beyond current 'length' and look
			 * a bit funny.
			 */
		} else {
			/* leave out trailing 'unused' elements */
			while (a_limit > 0) {
				tv = DUK_HOBJECT_A_GET_VALUE_PTR(NULL, h, a_limit - 1);
				if (!DUK_TVAL_IS_UNUSED(tv)) {
					break;
				}
				a_limit--;
			}
		}

		for (i = 0; i < a_limit; i++) {
			tv = DUK_HOBJECT_A_GET_VALUE_PTR(NULL, h, i);
			DUK__COMMA();
			duk__print_tval(st, tv);
		}
		for (i = 0; i < DUK_HOBJECT_GET_ENEXT(h); i++) {
			key = DUK_HOBJECT_E_GET_KEY(NULL, h, i);
			if (!key) {
				continue;
			}
			if (!st->internal && DUK_HSTRING_HAS_HIDDEN(key)) {
				continue;
			}
			DUK__COMMA();
			duk__print_hstring(st, key, 0);
			duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_COLON);
			if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(NULL, h, i)) {
				duk_fb_sprintf(fb, "[get:%p,set:%p]",
				               (void *) DUK_HOBJECT_E_GET_VALUE(NULL, h, i).a.get,
				               (void *) DUK_HOBJECT_E_GET_VALUE(NULL, h, i).a.set);
			} else {
				tv = &DUK_HOBJECT_E_GET_VALUE(NULL, h, i).v;
				duk__print_tval(st, tv);
			}
			if (st->heavy) {
				duk_fb_sprintf(fb, "<%02lx>", (unsigned long) DUK_HOBJECT_E_GET_FLAGS(NULL, h, i));
			}
		}
	}
	if (st->internal) {
		if (DUK_HOBJECT_IS_ARRAY(h)) {
			DUK__COMMA(); duk_fb_sprintf(fb, "__array:true");
		}
		if (DUK_HOBJECT_HAS_EXTENSIBLE(h)) {
			DUK__COMMA(); duk_fb_sprintf(fb, "__extensible:true");
		}
		if (DUK_HOBJECT_HAS_CONSTRUCTABLE(h)) {
			DUK__COMMA(); duk_fb_sprintf(fb, "__constructable:true");
		}
		if (DUK_HOBJECT_HAS_BOUNDFUNC(h)) {
			DUK__COMMA(); duk_fb_sprintf(fb, "__boundfunc:true");
		}
		if (DUK_HOBJECT_HAS_COMPFUNC(h)) {
			DUK__COMMA(); duk_fb_sprintf(fb, "__compfunc:true");
		}
		if (DUK_HOBJECT_HAS_NATFUNC(h)) {
			DUK__COMMA(); duk_fb_sprintf(fb, "__natfunc:true");
		}
		if (DUK_HOBJECT_HAS_BUFOBJ(h)) {
			DUK__COMMA(); duk_fb_sprintf(fb, "__bufobj:true");
		}
		if (DUK_HOBJECT_IS_THREAD(h)) {
			DUK__COMMA(); duk_fb_sprintf(fb, "__thread:true");
		}
		if (DUK_HOBJECT_HAS_ARRAY_PART(h)) {
			DUK__COMMA(); duk_fb_sprintf(fb, "__array_part:true");
		}
		if (DUK_HOBJECT_HAS_STRICT(h)) {
			DUK__COMMA(); duk_fb_sprintf(fb, "__strict:true");
		}
		if (DUK_HOBJECT_HAS_NOTAIL(h)) {
			DUK__COMMA(); duk_fb_sprintf(fb, "__notail:true");
		}
		if (DUK_HOBJECT_HAS_NEWENV(h)) {
			DUK__COMMA(); duk_fb_sprintf(fb, "__newenv:true");
		}
		if (DUK_HOBJECT_HAS_NAMEBINDING(h)) {
			DUK__COMMA(); duk_fb_sprintf(fb, "__namebinding:true");
		}
		if (DUK_HOBJECT_HAS_CREATEARGS(h)) {
			DUK__COMMA(); duk_fb_sprintf(fb, "__createargs:true");
		}
		if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(h)) {
			DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_array:true");
		}
		if (DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(h)) {
			DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_stringobj:true");
		}
		if (DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(h)) {
			DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_arguments:true");
		}
		if (DUK_HOBJECT_IS_BUFOBJ(h)) {
			DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_bufobj:true");
		}
		if (DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h)) {
			DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_proxyobj:true");
		}
	}

	if (st->internal && DUK_HOBJECT_IS_ARRAY(h)) {
		duk_harray *a = (duk_harray *) h;
		DUK__COMMA(); duk_fb_sprintf(fb, "__length:%ld", (long) a->length);
		DUK__COMMA(); duk_fb_sprintf(fb, "__length_nonwritable:%ld", (long) a->length_nonwritable);
	} else if (st->internal && DUK_HOBJECT_IS_COMPFUNC(h)) {
		duk_hcompfunc *f = (duk_hcompfunc *) h;
		DUK__COMMA(); duk_fb_put_cstring(fb, "__data:");
		duk__print_hbuffer(st, (duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA(NULL, f));
		DUK__COMMA(); duk_fb_put_cstring(fb, "__lexenv:"); duk__print_hobject(st, DUK_HCOMPFUNC_GET_LEXENV(NULL, f));
		DUK__COMMA(); duk_fb_put_cstring(fb, "__varenv:"); duk__print_hobject(st, DUK_HCOMPFUNC_GET_VARENV(NULL, f));
		DUK__COMMA(); duk_fb_sprintf(fb, "__nregs:%ld", (long) f->nregs);
		DUK__COMMA(); duk_fb_sprintf(fb, "__nargs:%ld", (long) f->nargs);
#if defined(DUK_USE_DEBUGGER_SUPPORT)
		DUK__COMMA(); duk_fb_sprintf(fb, "__start_line:%ld", (long) f->start_line);
		DUK__COMMA(); duk_fb_sprintf(fb, "__end_line:%ld", (long) f->end_line);
#endif
		DUK__COMMA(); duk_fb_put_cstring(fb, "__data:");
		duk__print_hbuffer(st, (duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA(NULL, f));
	} else if (st->internal && DUK_HOBJECT_IS_NATFUNC(h)) {
		duk_hnatfunc *f = (duk_hnatfunc *) h;
		DUK__COMMA(); duk_fb_sprintf(fb, "__func:");
		duk_fb_put_funcptr(fb, (duk_uint8_t *) &f->func, sizeof(f->func));
		DUK__COMMA(); duk_fb_sprintf(fb, "__nargs:%ld", (long) f->nargs);
		DUK__COMMA(); duk_fb_sprintf(fb, "__magic:%ld", (long) f->magic);
	} else if (st->internal && DUK_HOBJECT_IS_DECENV(h)) {
		duk_hdecenv *e = (duk_hdecenv *) h;
		DUK__COMMA(); duk_fb_sprintf(fb, "__thread:"); duk__print_hobject(st, (duk_hobject *) e->thread);
		DUK__COMMA(); duk_fb_sprintf(fb, "__varmap:"); duk__print_hobject(st, (duk_hobject *) e->varmap);
		DUK__COMMA(); duk_fb_sprintf(fb, "__regbase_byteoff:%ld", (long) e->regbase_byteoff);
	} else if (st->internal && DUK_HOBJECT_IS_OBJENV(h)) {
		duk_hobjenv *e = (duk_hobjenv *) h;
		DUK__COMMA(); duk_fb_sprintf(fb, "__target:"); duk__print_hobject(st, (duk_hobject *) e->target);
		DUK__COMMA(); duk_fb_sprintf(fb, "__has_this:%ld", (long) e->has_this);
#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
	} else if (st->internal && DUK_HOBJECT_IS_BUFOBJ(h)) {
		duk_hbufobj *b = (duk_hbufobj *) h;
		DUK__COMMA(); duk_fb_sprintf(fb, "__buf:");
		duk__print_hbuffer(st, (duk_hbuffer *) b->buf);
		DUK__COMMA(); duk_fb_sprintf(fb, "__buf_prop:");
		duk__print_hobject(st, (duk_hobject *) b->buf_prop);
		DUK__COMMA(); duk_fb_sprintf(fb, "__offset:%ld", (long) b->offset);
		DUK__COMMA(); duk_fb_sprintf(fb, "__length:%ld", (long) b->length);
		DUK__COMMA(); duk_fb_sprintf(fb, "__shift:%ld", (long) b->shift);
		DUK__COMMA(); duk_fb_sprintf(fb, "__elemtype:%ld", (long) b->elem_type);
#endif
	} else if (st->internal && DUK_HOBJECT_IS_PROXY(h)) {
		duk_hproxy *p = (duk_hproxy *) h;
		DUK__COMMA(); duk_fb_sprintf(fb, "__target:");
		duk__print_hobject(st, p->target);
		DUK__COMMA(); duk_fb_sprintf(fb, "__handler:");
		duk__print_hobject(st, p->handler);
	} else if (st->internal && DUK_HOBJECT_IS_THREAD(h)) {
		duk_hthread *t = (duk_hthread *) h;
		DUK__COMMA(); duk_fb_sprintf(fb, "__ptr_curr_pc:%p", (void *) t->ptr_curr_pc);
		DUK__COMMA(); duk_fb_sprintf(fb, "__heap:%p", (void *) t->heap);
		DUK__COMMA(); duk_fb_sprintf(fb, "__strict:%ld", (long) t->strict);
		DUK__COMMA(); duk_fb_sprintf(fb, "__state:%ld", (long) t->state);
		DUK__COMMA(); duk_fb_sprintf(fb, "__unused1:%ld", (long) t->unused1);
		DUK__COMMA(); duk_fb_sprintf(fb, "__unused2:%ld", (long) t->unused2);
		DUK__COMMA(); duk_fb_sprintf(fb, "__valstack:%p", (void *) t->valstack);
		DUK__COMMA(); duk_fb_sprintf(fb, "__valstack_end:%p/%ld", (void *) t->valstack_end, (long) (t->valstack_end - t->valstack));
		DUK__COMMA(); duk_fb_sprintf(fb, "__valstack_alloc_end:%p/%ld", (void *) t->valstack_alloc_end, (long) (t->valstack_alloc_end - t->valstack));
		DUK__COMMA(); duk_fb_sprintf(fb, "__valstack_bottom:%p/%ld", (void *) t->valstack_bottom, (long) (t->valstack_bottom - t->valstack));
		DUK__COMMA(); duk_fb_sprintf(fb, "__valstack_top:%p/%ld", (void *) t->valstack_top, (long) (t->valstack_top - t->valstack));
		DUK__COMMA(); duk_fb_sprintf(fb, "__callstack_curr:%p", (void *) t->callstack_curr);
		DUK__COMMA(); duk_fb_sprintf(fb, "__callstack_top:%ld", (long) t->callstack_top);
		DUK__COMMA(); duk_fb_sprintf(fb, "__callstack_preventcount:%ld", (long) t->callstack_preventcount);
		DUK__COMMA(); duk_fb_sprintf(fb, "__resumer:"); duk__print_hobject(st, (duk_hobject *) t->resumer);
		DUK__COMMA(); duk_fb_sprintf(fb, "__compile_ctx:%p", (void *) t->compile_ctx);
#if defined(DUK_USE_INTERRUPT_COUNTER)
		DUK__COMMA(); duk_fb_sprintf(fb, "__interrupt_counter:%ld", (long) t->interrupt_counter);
		DUK__COMMA(); duk_fb_sprintf(fb, "__interrupt_init:%ld", (long) t->interrupt_init);
#endif

		/* XXX: print built-ins array? */

	}
#if defined(DUK_USE_REFERENCE_COUNTING)
	if (st->internal) {
		DUK__COMMA(); duk_fb_sprintf(fb, "__refcount:%lu", (unsigned long) DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h));
	}
#endif
	if (st->internal) {
		DUK__COMMA(); duk_fb_sprintf(fb, "__class:%ld", (long) DUK_HOBJECT_GET_CLASS_NUMBER(h));
	}

	DUK__COMMA(); duk_fb_sprintf(fb, "__heapptr:%p", (void *) h);  /* own pointer */

	/* prototype should be last, for readability */
	if (DUK_HOBJECT_GET_PROTOTYPE(NULL, h)) {
		if (st->follow_proto) {
			DUK__COMMA(); duk_fb_put_cstring(fb, "__prototype:"); duk__print_hobject(st, DUK_HOBJECT_GET_PROTOTYPE(NULL, h));
		} else {
			DUK__COMMA(); duk_fb_sprintf(fb, "__prototype:%p", (void *) DUK_HOBJECT_GET_PROTOTYPE(NULL, h));
		}
	}

	duk_fb_put_cstring(fb, brace2);

#if defined(DUK_USE_HOBJECT_HASH_PART)
	if (st->heavy && DUK_HOBJECT_GET_HSIZE(h) > 0) {
		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LANGLE);
		for (i = 0; i < DUK_HOBJECT_GET_HSIZE(h); i++) {
			duk_uint_t h_idx = DUK_HOBJECT_H_GET_INDEX(NULL, h, i);
			if (i > 0) {
				duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_COMMA);
			}
			if (h_idx == DUK_HOBJECT_HASHIDX_UNUSED) {
				duk_fb_sprintf(fb, "u");
			} else if (h_idx == DUK_HOBJECT_HASHIDX_DELETED) {
				duk_fb_sprintf(fb, "d");
			} else {
				duk_fb_sprintf(fb, "%ld", (long) h_idx);
			}
		}
		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RANGLE);
	}
#endif

 finished:
	st->depth--;
	if (pushed_loopstack) {
		st->loop_stack_index--;
		st->loop_stack[st->loop_stack_index] = NULL;
	}
}

DUK_LOCAL void duk__print_hbuffer(duk__dprint_state *st, duk_hbuffer *h) {
	duk_fixedbuffer *fb = st->fb;
	duk_size_t i, n;
	duk_uint8_t *p;

	if (duk_fb_is_full(fb)) {
		return;
	}

	/* terminal type: no depth check */

	if (!h) {
		duk_fb_put_cstring(fb, "NULL");
		return;
	}

	if (DUK_HBUFFER_HAS_DYNAMIC(h)) {
		if (DUK_HBUFFER_HAS_EXTERNAL(h)) {
			duk_hbuffer_external *g = (duk_hbuffer_external *) h;
			duk_fb_sprintf(fb, "buffer:external:%p:%ld",
			               (void *) DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(NULL, g),
			               (long) DUK_HBUFFER_EXTERNAL_GET_SIZE(g));
		} else {
			duk_hbuffer_dynamic *g = (duk_hbuffer_dynamic *) h;
			duk_fb_sprintf(fb, "buffer:dynamic:%p:%ld",
			               (void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(NULL, g),
			               (long) DUK_HBUFFER_DYNAMIC_GET_SIZE(g));
		}
	} else {
		duk_fb_sprintf(fb, "buffer:fixed:%ld", (long) DUK_HBUFFER_GET_SIZE(h));
	}

#if defined(DUK_USE_REFERENCE_COUNTING)
	duk_fb_sprintf(fb, "/%lu", (unsigned long) DUK_HEAPHDR_GET_REFCOUNT(&h->hdr));
#endif

	if (st->hexdump) {
		duk_fb_sprintf(fb, "=[");
		n = DUK_HBUFFER_GET_SIZE(h);
		p = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(NULL, h);
		for (i = 0; i < n; i++) {
			duk_fb_sprintf(fb, "%02lx", (unsigned long) p[i]);
		}
		duk_fb_sprintf(fb, "]");
	}
}

DUK_LOCAL void duk__print_heaphdr(duk__dprint_state *st, duk_heaphdr *h) {
	duk_fixedbuffer *fb = st->fb;

	if (duk_fb_is_full(fb)) {
		return;
	}

	if (!h) {
		duk_fb_put_cstring(fb, "NULL");
		return;
	}

	switch (DUK_HEAPHDR_GET_TYPE(h)) {
	case DUK_HTYPE_STRING:
		duk__print_hstring(st, (duk_hstring *) h, 1);
		break;
	case DUK_HTYPE_OBJECT:
		duk__print_hobject(st, (duk_hobject *) h);
		break;
	case DUK_HTYPE_BUFFER:
		duk__print_hbuffer(st, (duk_hbuffer *) h);
		break;
	default:
		duk_fb_sprintf(fb, "[unknown htype %ld]", (long) DUK_HEAPHDR_GET_TYPE(h));
		break;
	}
}

DUK_LOCAL void duk__print_tval(duk__dprint_state *st, duk_tval *tv) {
	duk_fixedbuffer *fb = st->fb;

	if (duk_fb_is_full(fb)) {
		return;
	}

	/* depth check is done when printing an actual type */

	if (st->heavy) {
		duk_fb_sprintf(fb, "(%p)", (void *) tv);
	}

	if (!tv) {
		duk_fb_put_cstring(fb, "NULL");
		return;
	}

	if (st->binary) {
		duk_size_t i;
		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LBRACKET);
		for (i = 0; i < (duk_size_t) sizeof(*tv); i++) {
			duk_fb_sprintf(fb, "%02lx", (unsigned long) ((duk_uint8_t *)tv)[i]);
		}
		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RBRACKET);
	}

	if (st->heavy) {
		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LANGLE);
	}
	switch (DUK_TVAL_GET_TAG(tv)) {
	case DUK_TAG_UNDEFINED: {
		duk_fb_put_cstring(fb, "undefined");
		break;
	}
	case DUK_TAG_UNUSED: {
		duk_fb_put_cstring(fb, "unused");
		break;
	}
	case DUK_TAG_NULL: {
		duk_fb_put_cstring(fb, "null");
		break;
	}
	case DUK_TAG_BOOLEAN: {
		duk_fb_put_cstring(fb, DUK_TVAL_GET_BOOLEAN(tv) ? "true" : "false");
		break;
	}
	case DUK_TAG_STRING: {
		/* Note: string is a terminal heap object, so no depth check here */
		duk__print_hstring(st, DUK_TVAL_GET_STRING(tv), 1);
		break;
	}
	case DUK_TAG_OBJECT: {
		duk__print_hobject(st, DUK_TVAL_GET_OBJECT(tv));
		break;
	}
	case DUK_TAG_BUFFER: {
		duk__print_hbuffer(st, DUK_TVAL_GET_BUFFER(tv));
		break;
	}
	case DUK_TAG_POINTER: {
		duk_fb_sprintf(fb, "pointer:%p", (void *) DUK_TVAL_GET_POINTER(tv));
		break;
	}
	case DUK_TAG_LIGHTFUNC: {
		duk_c_function func;
		duk_small_uint_t lf_flags;

		DUK_TVAL_GET_LIGHTFUNC(tv, func, lf_flags);
		duk_fb_sprintf(fb, "lightfunc:");
		duk_fb_put_funcptr(fb, (duk_uint8_t *) &func, sizeof(func));
		duk_fb_sprintf(fb, ":%04lx", (long) lf_flags);
		break;
	}
#if defined(DUK_USE_FASTINT)
	case DUK_TAG_FASTINT:
		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
		duk_fb_sprintf(fb, "%.18g_F", (double) DUK_TVAL_GET_NUMBER(tv));
		break;
#endif
	default: {
		/* IEEE double is approximately 16 decimal digits; print a couple extra */
		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
		duk_fb_sprintf(fb, "%.18g", (double) DUK_TVAL_GET_NUMBER(tv));
		break;
	}
	}
	if (st->heavy) {
		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RANGLE);
	}
}

DUK_LOCAL void duk__print_instr(duk__dprint_state *st, duk_instr_t ins) {
	duk_fixedbuffer *fb = st->fb;
	duk_small_int_t op;
	const char *op_name;

	op = (duk_small_int_t) DUK_DEC_OP(ins);
	op_name = duk__bc_optab[op];

	/* XXX: option to fix opcode length so it lines up nicely */

	if (op == DUK_OP_JUMP) {
		duk_int_t diff1 = (duk_int_t) (DUK_DEC_ABC(ins) - DUK_BC_JUMP_BIAS);  /* from next pc */
		duk_int_t diff2 = diff1 + 1;                                          /* from curr pc */

		duk_fb_sprintf(fb, "%s %ld (to pc%c%ld)",
		               (const char *) op_name, (long) diff1,
		               (int) (diff2 >= 0 ? '+' : '-'),  /* char format: use int */
		               (long) (diff2 >= 0 ? diff2 : -diff2));
	} else {
		duk_fb_sprintf(fb, "%s %ld, %ld, %ld",
		               (const char *) op_name, (long) DUK_DEC_A(ins),
		               (long) DUK_DEC_B(ins), (long) DUK_DEC_C(ins));
	}
}

DUK_LOCAL void duk__print_opcode(duk__dprint_state *st, duk_small_int_t opcode) {
	duk_fixedbuffer *fb = st->fb;

	if (opcode < DUK_BC_OP_MIN || opcode > DUK_BC_OP_MAX) {
		duk_fb_sprintf(fb, "?(%ld)", (long) opcode);
	} else {
		duk_fb_sprintf(fb, "%s", (const char *) duk__bc_optab[opcode]);
	}
}

DUK_LOCAL void duk__print_catcher(duk__dprint_state *st, duk_catcher *cat) {
	duk_fixedbuffer *fb = st->fb;

	if (duk_fb_is_full(fb)) {
		return;
	}

	if (!cat) {
		duk_fb_put_cstring(fb, "NULL");
		return;
	}

	duk_fb_sprintf(fb, "[catcher ptr=%p parent=%p varname=%p pc_base=%p, idx_base=%ld, flags=0x%08lx]",
	               (void *) cat,
	               (void *) cat->parent, (void *) cat->h_varname, (void *) cat->pc_base,
		       (long) cat->idx_base, (unsigned long) cat->flags);
}


DUK_LOCAL void duk__print_activation(duk__dprint_state *st, duk_activation *act) {
	duk_fixedbuffer *fb = st->fb;

	if (duk_fb_is_full(fb)) {
		return;
	}

	if (!act) {
		duk_fb_put_cstring(fb, "NULL");
		return;
	}

	/* prev_caller: conditional, omitted on purpose, it's rarely used. */
	/* prev_line: conditional, omitted on purpose (but would be nice). */
	duk_fb_sprintf(fb, "[activation ptr=%p tv_func=<omit> func=%p parent=%p var_env=%p lex_env=%p cat=%p curr_pc=%p bottom_byteoff=%ld retval_byteoff=%ld reserve_byteoff=%ld flags=%ld]",
	               (void *) act,
	               (void *) act->func, (void *) act->parent, (void *) act->var_env,
		       (void *) act->lex_env, (void *) act->cat, (void *) act->curr_pc,
		       (long) act->bottom_byteoff, (long) act->retval_byteoff, (long) act->reserve_byteoff,
		       (long) act->flags);
}

DUK_INTERNAL duk_int_t duk_debug_vsnprintf(char *str, duk_size_t size, const char *format, va_list ap) {
	duk_fixedbuffer fb;
	const char *p = format;
	const char *p_end = p + DUK_STRLEN(format);
	duk_int_t retval;

	duk_memzero(&fb, sizeof(fb));
	fb.buffer = (duk_uint8_t *) str;
	fb.length = size;
	fb.offset = 0;
	fb.truncated = 0;

	while (p < p_end) {
		char ch = *p++;
		const char *p_begfmt = NULL;
		duk_bool_t got_exclamation = 0;
		duk_bool_t got_long = 0;  /* %lf, %ld etc */
		duk__dprint_state st;

		if (ch != DUK_ASC_PERCENT) {
			duk_fb_put_byte(&fb, (duk_uint8_t) ch);
			continue;
		}

		/*
		 *  Format tag parsing.  Since we don't understand all the
		 *  possible format tags allowed, we just scan for a terminating
		 *  specifier and keep track of relevant modifiers that we do
		 *  understand.  See man 3 printf.
		 */

		duk_memzero(&st, sizeof(st));
		st.fb = &fb;
		st.depth = 0;
		st.depth_limit = 1;
		st.loop_stack_index = 0;
		st.loop_stack_limit = DUK__LOOP_STACK_DEPTH;

		p_begfmt = p - 1;
		while (p < p_end) {
			ch = *p++;

			if (ch == DUK_ASC_STAR) {
				/* unsupported: would consume multiple args */
				goto format_error;
			} else if (ch == DUK_ASC_PERCENT) {
				duk_fb_put_byte(&fb, (duk_uint8_t) DUK_ASC_PERCENT);
				break;
			} else if (ch == DUK_ASC_EXCLAMATION) {
				got_exclamation = 1;
			} else if (!got_exclamation && ch == DUK_ASC_LC_L) {
				got_long = 1;
			} else if (got_exclamation && ch == DUK_ASC_LC_D) {
				st.depth_limit = DUK__DEEP_DEPTH_LIMIT;
			} else if (got_exclamation && ch == DUK_ASC_LC_P) {
				st.follow_proto = 1;
			} else if (got_exclamation && ch == DUK_ASC_LC_I) {
				st.internal = 1;
			} else if (got_exclamation && ch == DUK_ASC_LC_X) {
				st.hexdump = 1;
			} else if (got_exclamation && ch == DUK_ASC_LC_H) {
				st.heavy = 1;
			} else if (got_exclamation && ch == DUK_ASC_ATSIGN) {
				st.pointer = 1;
			} else if (got_exclamation && ch == DUK_ASC_HASH) {
				st.binary = 1;
			} else if (got_exclamation && ch == DUK_ASC_UC_T) {
				duk_tval *t = va_arg(ap, duk_tval *);
				if (st.pointer && !st.heavy) {
					duk_fb_sprintf(&fb, "(%p)", (void *) t);
				}
				duk__print_tval(&st, t);
				break;
			} else if (got_exclamation && ch == DUK_ASC_UC_O) {
				duk_heaphdr *t = va_arg(ap, duk_heaphdr *);
				if (st.pointer && !st.heavy) {
					duk_fb_sprintf(&fb, "(%p)", (void *) t);
				}
				duk__print_heaphdr(&st, t);
				break;
			} else if (got_exclamation && ch == DUK_ASC_UC_I) {
				duk_instr_t t = va_arg(ap, duk_instr_t);
				duk__print_instr(&st, t);
				break;
			} else if (got_exclamation && ch == DUK_ASC_UC_X) {
				long t = va_arg(ap, long);
				duk__print_opcode(&st, (duk_small_int_t) t);
				break;
			} else if (got_exclamation && ch == DUK_ASC_UC_C) {
				duk_catcher *t = va_arg(ap, duk_catcher *);
				duk__print_catcher(&st, t);
				break;
			} else if (got_exclamation && ch == DUK_ASC_UC_A) {
				duk_activation *t = va_arg(ap, duk_activation *);
				duk__print_activation(&st, t);
				break;
			} else if (!got_exclamation && strchr(DUK__ALLOWED_STANDARD_SPECIFIERS, (int) ch)) {
				char fmtbuf[DUK__MAX_FORMAT_TAG_LENGTH];
				duk_size_t fmtlen;

				DUK_ASSERT(p >= p_begfmt);
				fmtlen = (duk_size_t) (p - p_begfmt);
				if (fmtlen >= sizeof(fmtbuf)) {
					/* format is too large, abort */
					goto format_error;
				}
				duk_memzero(fmtbuf, sizeof(fmtbuf));
				duk_memcpy(fmtbuf, p_begfmt, fmtlen);

				/* assume exactly 1 arg, which is why '*' is forbidden; arg size still
				 * depends on type though.
				 */

				if (ch == DUK_ASC_LC_F || ch == DUK_ASC_LC_G || ch == DUK_ASC_LC_E) {
					/* %f and %lf both consume a 'long' */
					double arg = va_arg(ap, double);
					duk_fb_sprintf(&fb, fmtbuf, arg);
				} else if (ch == DUK_ASC_LC_D && got_long) {
					/* %ld */
					long arg = va_arg(ap, long);
					duk_fb_sprintf(&fb, fmtbuf, arg);
				} else if (ch == DUK_ASC_LC_D) {
					/* %d; only 16 bits are guaranteed */
					int arg = va_arg(ap, int);
					duk_fb_sprintf(&fb, fmtbuf, arg);
				} else if (ch == DUK_ASC_LC_U && got_long) {
					/* %lu */
					unsigned long arg = va_arg(ap, unsigned long);
					duk_fb_sprintf(&fb, fmtbuf, arg);
				} else if (ch == DUK_ASC_LC_U) {
					/* %u; only 16 bits are guaranteed */
					unsigned int arg = va_arg(ap, unsigned int);
					duk_fb_sprintf(&fb, fmtbuf, arg);
				} else if (ch == DUK_ASC_LC_X && got_long) {
					/* %lx */
					unsigned long arg = va_arg(ap, unsigned long);
					duk_fb_sprintf(&fb, fmtbuf, arg);
				} else if (ch == DUK_ASC_LC_X) {
					/* %x; only 16 bits are guaranteed */
					unsigned int arg = va_arg(ap, unsigned int);
					duk_fb_sprintf(&fb, fmtbuf, arg);
				} else if (ch == DUK_ASC_LC_S) {
					/* %s */
					const char *arg = va_arg(ap, const char *);
					if (arg == NULL) {
						/* '%s' and NULL is not portable, so special case
						 * it for debug printing.
						 */
						duk_fb_sprintf(&fb, "NULL");
					} else {
						duk_fb_sprintf(&fb, fmtbuf, arg);
					}
				} else if (ch == DUK_ASC_LC_P) {
					/* %p */
					void *arg = va_arg(ap, void *);
					if (arg == NULL) {
						/* '%p' and NULL is portable, but special case it
						 * anyway to get a standard NULL marker in logs.
						 */
						duk_fb_sprintf(&fb, "NULL");
					} else {
						duk_fb_sprintf(&fb, fmtbuf, arg);
					}
				} else if (ch == DUK_ASC_LC_C) {
					/* '%c', passed concretely as int */
					int arg = va_arg(ap, int);
					duk_fb_sprintf(&fb, fmtbuf, arg);
				} else {
					/* Should not happen. */
					duk_fb_sprintf(&fb, "INVALID-FORMAT(%s)", (const char *) fmtbuf);
				}
				break;
			} else {
				/* ignore */
			}
		}
	}
	goto done;

 format_error:
	duk_fb_put_cstring(&fb, "FMTERR");
	/* fall through */

 done:
	retval = (duk_int_t) fb.offset;
	duk_fb_put_byte(&fb, (duk_uint8_t) 0);

	/* return total chars written excluding terminator */
	return retval;
}

#if 0  /*unused*/
DUK_INTERNAL duk_int_t duk_debug_snprintf(char *str, duk_size_t size, const char *format, ...) {
	duk_int_t retval;
	va_list ap;
	va_start(ap, format);
	retval = duk_debug_vsnprintf(str, size, format, ap);
	va_end(ap);
	return retval;
}
#endif

/* Formatting function pointers is tricky: there is no standard pointer for
 * function pointers and the size of a function pointer may depend on the
 * specific pointer type.  This helper formats a function pointer based on
 * its memory layout to get something useful on most platforms.
 */
DUK_INTERNAL void duk_debug_format_funcptr(char *buf, duk_size_t buf_size, duk_uint8_t *fptr, duk_size_t fptr_size) {
	duk_size_t i;
	duk_uint8_t *p = (duk_uint8_t *) buf;
	duk_uint8_t *p_end = (duk_uint8_t *) (buf + buf_size - 1);

	DUK_ASSERT(buf != NULL);
	duk_memzero(buf, buf_size);

	for (i = 0; i < fptr_size; i++) {
		duk_int_t left = (duk_int_t) (p_end - p);
		duk_uint8_t ch;
		if (left <= 0) {
			break;
		}

		/* Quite approximate but should be useful for little and big endian. */
#if defined(DUK_USE_INTEGER_BE)
		ch = fptr[i];
#else
		ch = fptr[fptr_size - 1 - i];
#endif
		p += DUK_SNPRINTF((char *) p, (duk_size_t) left, "%02lx", (unsigned long) ch);
	}
}

#endif  /* DUK_USE_DEBUG */

/* automatic undefs */
#undef DUK__ALLOWED_STANDARD_SPECIFIERS
#undef DUK__COMMA
#undef DUK__DEEP_DEPTH_LIMIT
#undef DUK__LOOP_STACK_DEPTH
#undef DUK__MAX_FORMAT_TAG_LENGTH
#line 1 "duk_debugger.c"
/*
 *  Duktape debugger
 */

/* #include duk_internal.h -> already included */

#if defined(DUK_USE_DEBUGGER_SUPPORT)

/*
 *  Assert helpers
 */

#if defined(DUK_USE_ASSERTIONS)
#define DUK__DBG_TPORT_ENTER() do { \
		DUK_ASSERT(heap->dbg_calling_transport == 0); \
		heap->dbg_calling_transport = 1; \
	} while (0)
#define DUK__DBG_TPORT_EXIT() do { \
		DUK_ASSERT(heap->dbg_calling_transport == 1); \
		heap->dbg_calling_transport = 0; \
	} while (0)
#else
#define DUK__DBG_TPORT_ENTER() do {} while (0)
#define DUK__DBG_TPORT_EXIT() do {} while (0)
#endif

/*
 *  Helper structs
 */

typedef union {
	void *p;
	duk_uint_t b[1];
	/* Use b[] to access the size of the union, which is strictly not
	 * correct.  Can't use fixed size unless there's feature detection
	 * for pointer byte size.
	 */
} duk__ptr_union;

/*
 *  Detach handling
 */

#define DUK__SET_CONN_BROKEN(thr,reason) do { \
		/* For now shared handler is fine. */ \
		duk__debug_do_detach1((thr)->heap, (reason)); \
	} while (0)

DUK_LOCAL void duk__debug_do_detach1(duk_heap *heap, duk_int_t reason) {
	/* Can be called multiple times with no harm.  Mark the transport
	 * bad (dbg_read_cb == NULL) and clear state except for the detached
	 * callback and the udata field.  The detached callback is delayed
	 * to the message loop so that it can be called between messages;
	 * this avoids corner cases related to immediate debugger reattach
	 * inside the detached callback.
	 */

	if (heap->dbg_detaching) {
		DUK_D(DUK_DPRINT("debugger already detaching, ignore detach1"));
		return;
	}

	DUK_D(DUK_DPRINT("debugger transport detaching, marking transport broken"));

	heap->dbg_detaching = 1;  /* prevent multiple in-progress detaches */

	if (heap->dbg_write_cb != NULL) {
		duk_hthread *thr;

		thr = heap->heap_thread;
		DUK_ASSERT(thr != NULL);

		duk_debug_write_notify(thr, DUK_DBG_CMD_DETACHING);
		duk_debug_write_int(thr, reason);
		duk_debug_write_eom(thr);
	}

	heap->dbg_read_cb = NULL;
	heap->dbg_write_cb = NULL;
	heap->dbg_peek_cb = NULL;
	heap->dbg_read_flush_cb = NULL;
	heap->dbg_write_flush_cb = NULL;
	heap->dbg_request_cb = NULL;
	/* heap->dbg_detached_cb: keep */
	/* heap->dbg_udata: keep */
	/* heap->dbg_processing: keep on purpose to avoid debugger re-entry in detaching state */
	heap->dbg_state_dirty = 0;
	heap->dbg_force_restart = 0;
	heap->dbg_pause_flags = 0;
	heap->dbg_pause_act = NULL;
	heap->dbg_pause_startline = 0;
	heap->dbg_have_next_byte = 0;
	duk_debug_clear_paused(heap);  /* XXX: some overlap with field inits above */
	heap->dbg_state_dirty = 0;     /* XXX: clear_paused sets dirty; rework? */

	/* Ensure there are no stale active breakpoint pointers.
	 * Breakpoint list is currently kept - we could empty it
	 * here but we'd need to handle refcounts correctly, and
	 * we'd need a 'thr' reference for that.
	 *
	 * XXX: clear breakpoint on either attach or detach?
	 */
	heap->dbg_breakpoints_active[0] = (duk_breakpoint *) NULL;
}

DUK_LOCAL void duk__debug_do_detach2(duk_heap *heap) {
	duk_debug_detached_function detached_cb;
	void *detached_udata;
	duk_hthread *thr;

	thr = heap->heap_thread;
	if (thr == NULL) {
		DUK_ASSERT(heap->dbg_detached_cb == NULL);
		return;
	}

	/* Safe to call multiple times. */

	detached_cb = heap->dbg_detached_cb;
	detached_udata = heap->dbg_udata;
	heap->dbg_detached_cb = NULL;
	heap->dbg_udata = NULL;

	if (detached_cb) {
		/* Careful here: state must be wiped before the call
		 * so that we can cleanly handle a re-attach from
		 * inside the callback.
		 */
		DUK_D(DUK_DPRINT("detached during message loop, delayed call to detached_cb"));
		detached_cb(thr, detached_udata);
	}

	heap->dbg_detaching = 0;
}

DUK_INTERNAL void duk_debug_do_detach(duk_heap *heap) {
	duk__debug_do_detach1(heap, 0);
	duk__debug_do_detach2(heap);
}

/* Called on a read/write error: NULL all callbacks except the detached
 * callback so that we never accidentally call them after a read/write
 * error has been indicated.  This is especially important for the transport
 * I/O callbacks to fulfill guaranteed callback semantics.
 */
DUK_LOCAL void duk__debug_null_most_callbacks(duk_hthread *thr) {
	duk_heap *heap;

	DUK_ASSERT(thr != NULL);

	heap = thr->heap;
	DUK_D(DUK_DPRINT("transport read/write error, NULL all callbacks expected detached"));
	heap->dbg_read_cb = NULL;
	heap->dbg_write_cb = NULL;  /* this is especially critical to avoid another write call in detach1() */
	heap->dbg_peek_cb = NULL;
	heap->dbg_read_flush_cb = NULL;
	heap->dbg_write_flush_cb = NULL;
	heap->dbg_request_cb = NULL;
	/* keep heap->dbg_detached_cb */
}

/*
 *  Pause handling
 */

DUK_LOCAL void duk__debug_set_pause_state(duk_hthread *thr, duk_heap *heap, duk_small_uint_t pause_flags) {
	duk_uint_fast32_t line;

	line = duk_debug_curr_line(thr);
	if (line == 0) {
		/* No line info for current function. */
		duk_small_uint_t updated_flags;

		updated_flags = pause_flags & ~(DUK_PAUSE_FLAG_LINE_CHANGE);
		DUK_D(DUK_DPRINT("no line info for current activation, disable line-based pause flags: 0x%08lx -> 0x%08lx",
		                 (long) pause_flags, (long) updated_flags));
		pause_flags = updated_flags;
	}

	heap->dbg_pause_flags = pause_flags;
	heap->dbg_pause_act = thr->callstack_curr;
	heap->dbg_pause_startline = (duk_uint32_t) line;
	heap->dbg_state_dirty = 1;

	DUK_D(DUK_DPRINT("set state for automatic pause triggers, flags=0x%08lx, act=%p, startline=%ld",
	                 (long) heap->dbg_pause_flags, (void *) heap->dbg_pause_act,
	                 (long) heap->dbg_pause_startline));
}

/*
 *  Debug connection peek and flush primitives
 */

DUK_INTERNAL duk_bool_t duk_debug_read_peek(duk_hthread *thr) {
	duk_heap *heap;
	duk_bool_t ret;

	DUK_ASSERT(thr != NULL);
	heap = thr->heap;
	DUK_ASSERT(heap != NULL);

	if (heap->dbg_read_cb == NULL) {
		DUK_D(DUK_DPRINT("attempt to peek in detached state, return zero (= no data)"));
		return 0;
	}
	if (heap->dbg_peek_cb == NULL) {
		DUK_DD(DUK_DDPRINT("no peek callback, return zero (= no data)"));
		return 0;
	}

	DUK__DBG_TPORT_ENTER();
	ret = (duk_bool_t) (heap->dbg_peek_cb(heap->dbg_udata) > 0);
	DUK__DBG_TPORT_EXIT();
	return ret;
}

DUK_INTERNAL void duk_debug_read_flush(duk_hthread *thr) {
	duk_heap *heap;

	DUK_ASSERT(thr != NULL);
	heap = thr->heap;
	DUK_ASSERT(heap != NULL);

	if (heap->dbg_read_cb == NULL) {
		DUK_D(DUK_DPRINT("attempt to read flush in detached state, ignore"));
		return;
	}
	if (heap->dbg_read_flush_cb == NULL) {
		DUK_DD(DUK_DDPRINT("no read flush callback, ignore"));
		return;
	}

	DUK__DBG_TPORT_ENTER();
	heap->dbg_read_flush_cb(heap->dbg_udata);
	DUK__DBG_TPORT_EXIT();
}

DUK_INTERNAL void duk_debug_write_flush(duk_hthread *thr) {
	duk_heap *heap;

	DUK_ASSERT(thr != NULL);
	heap = thr->heap;
	DUK_ASSERT(heap != NULL);

	if (heap->dbg_read_cb == NULL) {
		DUK_D(DUK_DPRINT("attempt to write flush in detached state, ignore"));
		return;
	}
	if (heap->dbg_write_flush_cb == NULL) {
		DUK_DD(DUK_DDPRINT("no write flush callback, ignore"));
		return;
	}

	DUK__DBG_TPORT_ENTER();
	heap->dbg_write_flush_cb(heap->dbg_udata);
	DUK__DBG_TPORT_EXIT();
}

/*
 *  Debug connection skip primitives
 */

/* Skip fully. */
DUK_INTERNAL void duk_debug_skip_bytes(duk_hthread *thr, duk_size_t length) {
	duk_uint8_t dummy[64];
	duk_size_t now;

	DUK_ASSERT(thr != NULL);

	while (length > 0) {
		now = (length > sizeof(dummy) ? sizeof(dummy) : length);
		duk_debug_read_bytes(thr, dummy, now);
		length -= now;
	}
}

DUK_INTERNAL void duk_debug_skip_byte(duk_hthread *thr) {
	DUK_ASSERT(thr != NULL);

	(void) duk_debug_read_byte(thr);
}

/*
 *  Debug connection read primitives
 */

/* Peek ahead in the stream one byte. */
DUK_INTERNAL uint8_t duk_debug_peek_byte(duk_hthread *thr) {
	/* It is important not to call this if the last byte read was an EOM.
	 * Reading ahead in this scenario would cause unnecessary blocking if
	 * another message is not available.
	 */

	duk_uint8_t x;

	x = duk_debug_read_byte(thr);
	thr->heap->dbg_have_next_byte = 1;
	thr->heap->dbg_next_byte = x;
	return x;
}

/* Read fully. */
DUK_INTERNAL void duk_debug_read_bytes(duk_hthread *thr, duk_uint8_t *data, duk_size_t length) {
	duk_heap *heap;
	duk_uint8_t *p;
	duk_size_t left;
	duk_size_t got;

	DUK_ASSERT(thr != NULL);
	heap = thr->heap;
	DUK_ASSERT(heap != NULL);
	DUK_ASSERT(data != NULL);

	if (heap->dbg_read_cb == NULL) {
		DUK_D(DUK_DPRINT("attempt to read %ld bytes in detached state, return zero data", (long) length));
		goto fail;
	}

	/* NOTE: length may be zero */
	p = data;
	if (length >= 1 && heap->dbg_have_next_byte) {
		heap->dbg_have_next_byte = 0;
		*p++ = heap->dbg_next_byte;
	}
	for (;;) {
		left = (duk_size_t) ((data + length) - p);
		if (left == 0) {
			break;
		}
		DUK_ASSERT(heap->dbg_read_cb != NULL);
		DUK_ASSERT(left >= 1);
#if defined(DUK_USE_DEBUGGER_TRANSPORT_TORTURE)
		left = 1;
#endif
		DUK__DBG_TPORT_ENTER();
		got = heap->dbg_read_cb(heap->dbg_udata, (char *) p, left);
		DUK__DBG_TPORT_EXIT();

		if (got == 0 || got > left) {
			DUK_D(DUK_DPRINT("connection error during read, return zero data"));
			duk__debug_null_most_callbacks(thr);  /* avoid calling write callback in detach1() */
			DUK__SET_CONN_BROKEN(thr, 1);
			goto fail;
		}
		p += got;
	}
	return;

 fail:
	duk_memzero((void *) data, (size_t) length);
}

DUK_INTERNAL duk_uint8_t duk_debug_read_byte(duk_hthread *thr) {
	duk_uint8_t x;

	x = 0;  /* just in case callback is broken and won't write 'x' */
	duk_debug_read_bytes(thr, &x, 1);
	return x;
}

DUK_LOCAL duk_uint32_t duk__debug_read_uint32_raw(duk_hthread *thr) {
	duk_uint8_t buf[4];

	DUK_ASSERT(thr != NULL);

	duk_debug_read_bytes(thr, buf, 4);
	return ((duk_uint32_t) buf[0] << 24) |
	       ((duk_uint32_t) buf[1] << 16) |
	       ((duk_uint32_t) buf[2] << 8) |
	       (duk_uint32_t) buf[3];
}

DUK_LOCAL duk_int32_t duk__debug_read_int32_raw(duk_hthread *thr) {
	return (duk_int32_t) duk__debug_read_uint32_raw(thr);
}

DUK_LOCAL duk_uint16_t duk__debug_read_uint16_raw(duk_hthread *thr) {
	duk_uint8_t buf[2];

	DUK_ASSERT(thr != NULL);

	duk_debug_read_bytes(thr, buf, 2);
	return ((duk_uint16_t) buf[0] << 8) |
	       (duk_uint16_t) buf[1];
}

DUK_INTERNAL duk_int32_t duk_debug_read_int(duk_hthread *thr) {
	duk_small_uint_t x;
	duk_small_uint_t t;

	DUK_ASSERT(thr != NULL);

	x = duk_debug_read_byte(thr);
	if (x >= 0xc0) {
		t = duk_debug_read_byte(thr);
		return (duk_int32_t) (((x - 0xc0) << 8) + t);
	} else if (x >= 0x80) {
		return (duk_int32_t) (x - 0x80);
	} else if (x == DUK_DBG_IB_INT4) {
		return (duk_int32_t) duk__debug_read_uint32_raw(thr);
	}

	DUK_D(DUK_DPRINT("debug connection error: failed to decode int"));
	DUK__SET_CONN_BROKEN(thr, 1);
	return 0;
}

DUK_LOCAL duk_hstring *duk__debug_read_hstring_raw(duk_hthread *thr, duk_uint32_t len) {
	duk_uint8_t buf[31];
	duk_uint8_t *p;

	if (len <= sizeof(buf)) {
		duk_debug_read_bytes(thr, buf, (duk_size_t) len);
		duk_push_lstring(thr, (const char *) buf, (duk_size_t) len);
	} else {
		p = (duk_uint8_t *) duk_push_fixed_buffer(thr, (duk_size_t) len);  /* zero for paranoia */
		DUK_ASSERT(p != NULL);
		duk_debug_read_bytes(thr, p, (duk_size_t) len);
		(void) duk_buffer_to_string(thr, -1);  /* Safety relies on debug client, which is OK. */
	}

	return duk_require_hstring(thr, -1);
}

DUK_INTERNAL duk_hstring *duk_debug_read_hstring(duk_hthread *thr) {
	duk_small_uint_t x;
	duk_uint32_t len;

	DUK_ASSERT(thr != NULL);

	x = duk_debug_read_byte(thr);
	if (x >= 0x60 && x <= 0x7f) {
		/* For short strings, use a fixed temp buffer. */
		len = (duk_uint32_t) (x - 0x60);
	} else if (x == DUK_DBG_IB_STR2) {
		len = (duk_uint32_t) duk__debug_read_uint16_raw(thr);
	} else if (x == DUK_DBG_IB_STR4) {
		len = (duk_uint32_t) duk__debug_read_uint32_raw(thr);
	} else {
		goto fail;
	}

	return duk__debug_read_hstring_raw(thr, len);

 fail:
	DUK_D(DUK_DPRINT("debug connection error: failed to decode int"));
	DUK__SET_CONN_BROKEN(thr, 1);
	duk_push_hstring_empty(thr);  /* always push some string */
	return duk_require_hstring(thr, -1);
}

DUK_LOCAL duk_hbuffer *duk__debug_read_hbuffer_raw(duk_hthread *thr, duk_uint32_t len) {
	duk_uint8_t *p;

	p = (duk_uint8_t *) duk_push_fixed_buffer(thr, (duk_size_t) len);  /* zero for paranoia */
	DUK_ASSERT(p != NULL);
	duk_debug_read_bytes(thr, p, (duk_size_t) len);

	return duk_require_hbuffer(thr, -1);
}

DUK_LOCAL void *duk__debug_read_pointer_raw(duk_hthread *thr) {
	duk_small_uint_t x;
	duk__ptr_union pu;

	DUK_ASSERT(thr != NULL);

	x = duk_debug_read_byte(thr);
	if (x != sizeof(pu)) {
		goto fail;
	}
	duk_debug_read_bytes(thr, (duk_uint8_t *) &pu.p, sizeof(pu));
#if defined(DUK_USE_INTEGER_LE)
	duk_byteswap_bytes((duk_uint8_t *) pu.b, sizeof(pu));
#endif
	return (void *) pu.p;

 fail:
	DUK_D(DUK_DPRINT("debug connection error: failed to decode pointer"));
	DUK__SET_CONN_BROKEN(thr, 1);
	return (void *) NULL;
}

DUK_LOCAL duk_double_t duk__debug_read_double_raw(duk_hthread *thr) {
	duk_double_union du;

	DUK_ASSERT(sizeof(du.uc) == 8);
	duk_debug_read_bytes(thr, (duk_uint8_t *) du.uc, sizeof(du.uc));
	DUK_DBLUNION_DOUBLE_NTOH(&du);
	return du.d;
}

#if 0
DUK_INTERNAL duk_heaphdr *duk_debug_read_heapptr(duk_hthread *thr) {
	duk_small_uint_t x;

	DUK_ASSERT(thr != NULL);

	x = duk_debug_read_byte(thr);
	if (x != DUK_DBG_IB_HEAPPTR) {
		goto fail;
	}

	return (duk_heaphdr *) duk__debug_read_pointer_raw(thr);

 fail:
	DUK_D(DUK_DPRINT("debug connection error: failed to decode heapptr"));
	DUK__SET_CONN_BROKEN(thr, 1);
	return NULL;
}
#endif

DUK_INTERNAL duk_heaphdr *duk_debug_read_any_ptr(duk_hthread *thr) {
	duk_small_uint_t x;

	DUK_ASSERT(thr != NULL);

	x = duk_debug_read_byte(thr);
	switch (x) {
	case DUK_DBG_IB_OBJECT:
	case DUK_DBG_IB_POINTER:
	case DUK_DBG_IB_HEAPPTR:
		/* Accept any pointer-like value; for 'object' dvalue, read
		 * and ignore the class number.
		 */
		if (x == DUK_DBG_IB_OBJECT) {
			duk_debug_skip_byte(thr);
		}
		break;
	default:
		goto fail;
	}

	return (duk_heaphdr *) duk__debug_read_pointer_raw(thr);

 fail:
	DUK_D(DUK_DPRINT("debug connection error: failed to decode any pointer (object, pointer, heapptr)"));
	DUK__SET_CONN_BROKEN(thr, 1);
	return NULL;
}

DUK_INTERNAL duk_tval *duk_debug_read_tval(duk_hthread *thr) {
	duk_uint8_t x;
	duk_uint_t t;
	duk_uint32_t len;

	DUK_ASSERT(thr != NULL);

	x = duk_debug_read_byte(thr);

	if (x >= 0xc0) {
		t = (duk_uint_t) (x - 0xc0);
		t = (t << 8) + duk_debug_read_byte(thr);
		duk_push_uint(thr, (duk_uint_t) t);
		goto return_ptr;
	}
	if (x >= 0x80) {
		duk_push_uint(thr, (duk_uint_t) (x - 0x80));
		goto return_ptr;
	}
	if (x >= 0x60) {
		len = (duk_uint32_t) (x - 0x60);
		duk__debug_read_hstring_raw(thr, len);
		goto return_ptr;
	}

	switch (x) {
	case DUK_DBG_IB_INT4: {
		duk_int32_t i = duk__debug_read_int32_raw(thr);
		duk_push_i32(thr, i);
		break;
	}
	case DUK_DBG_IB_STR4: {
		len = duk__debug_read_uint32_raw(thr);
		duk__debug_read_hstring_raw(thr, len);
		break;
	}
	case DUK_DBG_IB_STR2: {
		len = duk__debug_read_uint16_raw(thr);
		duk__debug_read_hstring_raw(thr, len);
		break;
	}
	case DUK_DBG_IB_BUF4: {
		len = duk__debug_read_uint32_raw(thr);
		duk__debug_read_hbuffer_raw(thr, len);
		break;
	}
	case DUK_DBG_IB_BUF2: {
		len = duk__debug_read_uint16_raw(thr);
		duk__debug_read_hbuffer_raw(thr, len);
		break;
	}
	case DUK_DBG_IB_UNDEFINED: {
		duk_push_undefined(thr);
		break;
	}
	case DUK_DBG_IB_NULL: {
		duk_push_null(thr);
		break;
	}
	case DUK_DBG_IB_TRUE: {
		duk_push_true(thr);
		break;
	}
	case DUK_DBG_IB_FALSE: {
		duk_push_false(thr);
		break;
	}
	case DUK_DBG_IB_NUMBER: {
		duk_double_t d;
		d = duk__debug_read_double_raw(thr);
		duk_push_number(thr, d);
		break;
	}
	case DUK_DBG_IB_OBJECT: {
		duk_heaphdr *h;
		duk_debug_skip_byte(thr);
		h = (duk_heaphdr *) duk__debug_read_pointer_raw(thr);
		duk_push_heapptr(thr, (void *) h);
		break;
	}
	case DUK_DBG_IB_POINTER: {
		void *ptr;
		ptr = duk__debug_read_pointer_raw(thr);
		duk_push_pointer(thr, ptr);
		break;
	}
	case DUK_DBG_IB_LIGHTFUNC: {
		/* XXX: Not needed for now, so not implemented.  Note that
		 * function pointers may have different size/layout than
		 * a void pointer.
		 */
		DUK_D(DUK_DPRINT("reading lightfunc values unimplemented"));
		goto fail;
	}
	case DUK_DBG_IB_HEAPPTR: {
		duk_heaphdr *h;
		h = (duk_heaphdr *) duk__debug_read_pointer_raw(thr);
		duk_push_heapptr(thr, (void *) h);
		break;
	}
	case DUK_DBG_IB_UNUSED:  /* unused: not accepted in inbound messages */
	default:
		goto fail;
	}

 return_ptr:
	return DUK_GET_TVAL_NEGIDX(thr, -1);

 fail:
	DUK_D(DUK_DPRINT("debug connection error: failed to decode tval"));
	DUK__SET_CONN_BROKEN(thr, 1);
	return NULL;
}

/*
 *  Debug connection write primitives
 */

/* Write fully. */
DUK_INTERNAL void duk_debug_write_bytes(duk_hthread *thr, const duk_uint8_t *data, duk_size_t length) {
	duk_heap *heap;
	const duk_uint8_t *p;
	duk_size_t left;
	duk_size_t got;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(length == 0 || data != NULL);
	heap = thr->heap;
	DUK_ASSERT(heap != NULL);

	if (heap->dbg_write_cb == NULL) {
		DUK_D(DUK_DPRINT("attempt to write %ld bytes in detached state, ignore", (long) length));
		return;
	}
	if (length == 0) {
		/* Avoid doing an actual write callback with length == 0,
		 * because that's reserved for a write flush.
		 */
		return;
	}
	DUK_ASSERT(data != NULL);

	p = data;
	for (;;) {
		left = (duk_size_t) ((data + length) - p);
		if (left == 0) {
			break;
		}
		DUK_ASSERT(heap->dbg_write_cb != NULL);
		DUK_ASSERT(left >= 1);
#if defined(DUK_USE_DEBUGGER_TRANSPORT_TORTURE)
		left = 1;
#endif
		DUK__DBG_TPORT_ENTER();
		got = heap->dbg_write_cb(heap->dbg_udata, (const char *) p, left);
		DUK__DBG_TPORT_EXIT();

		if (got == 0 || got > left) {
			duk__debug_null_most_callbacks(thr);  /* avoid calling write callback in detach1() */
			DUK_D(DUK_DPRINT("connection error during write"));
			DUK__SET_CONN_BROKEN(thr, 1);
			return;
		}
		p += got;
	}
}

DUK_INTERNAL void duk_debug_write_byte(duk_hthread *thr, duk_uint8_t x) {
	duk_debug_write_bytes(thr, (const duk_uint8_t *) &x, 1);
}

DUK_INTERNAL void duk_debug_write_unused(duk_hthread *thr) {
	duk_debug_write_byte(thr, DUK_DBG_IB_UNUSED);
}

DUK_INTERNAL void duk_debug_write_undefined(duk_hthread *thr) {
	duk_debug_write_byte(thr, DUK_DBG_IB_UNDEFINED);
}

#if defined(DUK_USE_DEBUGGER_INSPECT)
DUK_INTERNAL void duk_debug_write_null(duk_hthread *thr) {
	duk_debug_write_byte(thr, DUK_DBG_IB_NULL);
}
#endif

DUK_INTERNAL void duk_debug_write_boolean(duk_hthread *thr, duk_uint_t val) {
	duk_debug_write_byte(thr, val ? DUK_DBG_IB_TRUE : DUK_DBG_IB_FALSE);
}

/* Write signed 32-bit integer. */
DUK_INTERNAL void duk_debug_write_int(duk_hthread *thr, duk_int32_t x) {
	duk_uint8_t buf[5];
	duk_size_t len;

	DUK_ASSERT(thr != NULL);

	if (x >= 0 && x <= 0x3fL) {
		buf[0] = (duk_uint8_t) (0x80 + x);
		len = 1;
	} else if (x >= 0 && x <= 0x3fffL) {
		buf[0] = (duk_uint8_t) (0xc0 + (x >> 8));
		buf[1] = (duk_uint8_t) (x & 0xff);
		len = 2;
	} else {
		/* Signed integers always map to 4 bytes now. */
		buf[0] = (duk_uint8_t) DUK_DBG_IB_INT4;
		buf[1] = (duk_uint8_t) ((x >> 24) & 0xff);
		buf[2] = (duk_uint8_t) ((x >> 16) & 0xff);
		buf[3] = (duk_uint8_t) ((x >> 8) & 0xff);
		buf[4] = (duk_uint8_t) (x & 0xff);
		len = 5;
	}
	duk_debug_write_bytes(thr, buf, len);
}

/* Write unsigned 32-bit integer. */
DUK_INTERNAL void duk_debug_write_uint(duk_hthread *thr, duk_uint32_t x) {
	/* The debugger protocol doesn't support a plain integer encoding for
	 * the full 32-bit unsigned range (only 32-bit signed).  For now,
	 * unsigned 32-bit values simply written as signed ones.  This is not
	 * a concrete issue except for 32-bit heaphdr fields.  Proper solutions
	 * would be to (a) write such integers as IEEE doubles or (b) add an
	 * unsigned 32-bit dvalue.
	 */
	if (x >= 0x80000000UL) {
		DUK_D(DUK_DPRINT("writing unsigned integer 0x%08lx as signed integer",
		                 (long) x));
	}
	duk_debug_write_int(thr, (duk_int32_t) x);
}

DUK_INTERNAL void duk_debug_write_strbuf(duk_hthread *thr, const char *data, duk_size_t length, duk_uint8_t marker_base) {
	duk_uint8_t buf[5];
	duk_size_t buflen;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(length == 0 || data != NULL);

	if (length <= 0x1fUL && marker_base == DUK_DBG_IB_STR4) {
		/* For strings, special form for short lengths. */
		buf[0] = (duk_uint8_t) (0x60 + length);
		buflen = 1;
	} else if (length <= 0xffffUL) {
		buf[0] = (duk_uint8_t) (marker_base + 1);
		buf[1] = (duk_uint8_t) (length >> 8);
		buf[2] = (duk_uint8_t) (length & 0xff);
		buflen = 3;
	} else {
		buf[0] = (duk_uint8_t) marker_base;
		buf[1] = (duk_uint8_t) (length >> 24);
		buf[2] = (duk_uint8_t) ((length >> 16) & 0xff);
		buf[3] = (duk_uint8_t) ((length >> 8) & 0xff);
		buf[4] = (duk_uint8_t) (length & 0xff);
		buflen = 5;
	}

	duk_debug_write_bytes(thr, (const duk_uint8_t *) buf, buflen);
	duk_debug_write_bytes(thr, (const duk_uint8_t *) data, length);
}

DUK_INTERNAL void duk_debug_write_string(duk_hthread *thr, const char *data, duk_size_t length) {
	duk_debug_write_strbuf(thr, data, length, DUK_DBG_IB_STR4);
}

DUK_INTERNAL void duk_debug_write_cstring(duk_hthread *thr, const char *data) {
	DUK_ASSERT(thr != NULL);

	duk_debug_write_string(thr,
	                       data,
	                       data ? DUK_STRLEN(data) : 0);
}

DUK_INTERNAL void duk_debug_write_hstring(duk_hthread *thr, duk_hstring *h) {
	DUK_ASSERT(thr != NULL);

	/* XXX: differentiate null pointer from empty string? */
	duk_debug_write_string(thr,
	                       (h != NULL ? (const char *) DUK_HSTRING_GET_DATA(h) : NULL),
	                       (h != NULL ? (duk_size_t) DUK_HSTRING_GET_BYTELEN(h) : 0));
}

DUK_LOCAL void duk__debug_write_hstring_safe_top(duk_hthread *thr) {
	duk_debug_write_hstring(thr, duk_safe_to_hstring(thr, -1));
}

DUK_INTERNAL void duk_debug_write_buffer(duk_hthread *thr, const char *data, duk_size_t length) {
	duk_debug_write_strbuf(thr, data, length, DUK_DBG_IB_BUF4);
}

DUK_INTERNAL void duk_debug_write_hbuffer(duk_hthread *thr, duk_hbuffer *h) {
	DUK_ASSERT(thr != NULL);

	duk_debug_write_buffer(thr,
	                       (h != NULL ? (const char *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h) : NULL),
	                       (h != NULL ? (duk_size_t) DUK_HBUFFER_GET_SIZE(h) : 0));
}

DUK_LOCAL void duk__debug_write_pointer_raw(duk_hthread *thr, void *ptr, duk_uint8_t ibyte) {
	duk_uint8_t buf[2];
	duk__ptr_union pu;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(sizeof(ptr) >= 1 && sizeof(ptr) <= 16);
	/* ptr may be NULL */

	buf[0] = ibyte;
	buf[1] = sizeof(pu);
	duk_debug_write_bytes(thr, buf, 2);
	pu.p = (void *) ptr;
#if defined(DUK_USE_INTEGER_LE)
	duk_byteswap_bytes((duk_uint8_t *) pu.b, sizeof(pu));
#endif
	duk_debug_write_bytes(thr, (const duk_uint8_t *) &pu.p, (duk_size_t) sizeof(pu));
}

DUK_INTERNAL void duk_debug_write_pointer(duk_hthread *thr, void *ptr) {
	duk__debug_write_pointer_raw(thr, ptr, DUK_DBG_IB_POINTER);
}

#if defined(DUK_USE_DEBUGGER_DUMPHEAP) || defined(DUK_USE_DEBUGGER_INSPECT)
DUK_INTERNAL void duk_debug_write_heapptr(duk_hthread *thr, duk_heaphdr *h) {
	duk__debug_write_pointer_raw(thr, (void *) h, DUK_DBG_IB_HEAPPTR);
}
#endif  /* DUK_USE_DEBUGGER_DUMPHEAP || DUK_USE_DEBUGGER_INSPECT */

DUK_INTERNAL void duk_debug_write_hobject(duk_hthread *thr, duk_hobject *obj) {
	duk_uint8_t buf[3];
	duk__ptr_union pu;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(sizeof(obj) >= 1 && sizeof(obj) <= 16);
	DUK_ASSERT(obj != NULL);

	buf[0] = DUK_DBG_IB_OBJECT;
	buf[1] = (duk_uint8_t) DUK_HOBJECT_GET_CLASS_NUMBER(obj);
	buf[2] = sizeof(pu);
	duk_debug_write_bytes(thr, buf, 3);
	pu.p = (void *) obj;
#if defined(DUK_USE_INTEGER_LE)
	duk_byteswap_bytes((duk_uint8_t *) pu.b, sizeof(pu));
#endif
	duk_debug_write_bytes(thr, (const duk_uint8_t *) &pu.p, (duk_size_t) sizeof(pu));
}

DUK_INTERNAL void duk_debug_write_tval(duk_hthread *thr, duk_tval *tv) {
	duk_c_function lf_func;
	duk_small_uint_t lf_flags;
	duk_uint8_t buf[4];
	duk_double_union du1;
	duk_double_union du2;
	duk_int32_t i32;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(tv != NULL);

	switch (DUK_TVAL_GET_TAG(tv)) {
	case DUK_TAG_UNDEFINED:
		duk_debug_write_byte(thr, DUK_DBG_IB_UNDEFINED);
		break;
	case DUK_TAG_UNUSED:
		duk_debug_write_byte(thr, DUK_DBG_IB_UNUSED);
		break;
	case DUK_TAG_NULL:
		duk_debug_write_byte(thr, DUK_DBG_IB_NULL);
		break;
	case DUK_TAG_BOOLEAN:
		DUK_ASSERT(DUK_TVAL_GET_BOOLEAN(tv) == 0 ||
		           DUK_TVAL_GET_BOOLEAN(tv) == 1);
		duk_debug_write_boolean(thr, DUK_TVAL_GET_BOOLEAN(tv));
		break;
	case DUK_TAG_POINTER:
		duk_debug_write_pointer(thr, (void *) DUK_TVAL_GET_POINTER(tv));
		break;
	case DUK_TAG_LIGHTFUNC:
		DUK_TVAL_GET_LIGHTFUNC(tv, lf_func, lf_flags);
		buf[0] = DUK_DBG_IB_LIGHTFUNC;
		buf[1] = (duk_uint8_t) (lf_flags >> 8);
		buf[2] = (duk_uint8_t) (lf_flags & 0xff);
		buf[3] = sizeof(lf_func);
		duk_debug_write_bytes(thr, buf, 4);
		duk_debug_write_bytes(thr, (const duk_uint8_t *) &lf_func, sizeof(lf_func));
		break;
	case DUK_TAG_STRING:
		duk_debug_write_hstring(thr, DUK_TVAL_GET_STRING(tv));
		break;
	case DUK_TAG_OBJECT:
		duk_debug_write_hobject(thr, DUK_TVAL_GET_OBJECT(tv));
		break;
	case DUK_TAG_BUFFER:
		duk_debug_write_hbuffer(thr, DUK_TVAL_GET_BUFFER(tv));
		break;
#if defined(DUK_USE_FASTINT)
	case DUK_TAG_FASTINT:
#endif
	default:
		/* Numbers are normalized to big (network) endian.  We can
		 * (but are not required) to use integer dvalues when there's
		 * no loss of precision.
		 *
		 * XXX: share check with other code; this check is slow but
		 * reliable and doesn't require careful exponent/mantissa
		 * mask tricks as in the fastint downgrade code.
		 */
		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
		du1.d = DUK_TVAL_GET_NUMBER(tv);
		i32 = (duk_int32_t) du1.d;
		du2.d = (duk_double_t) i32;

		DUK_DD(DUK_DDPRINT("i32=%ld du1=%02x%02x%02x%02x%02x%02x%02x%02x "
		                   "du2=%02x%02x%02x%02x%02x%02x%02x%02x",
		                   (long) i32,
		                   (unsigned int) du1.uc[0], (unsigned int) du1.uc[1],
		                   (unsigned int) du1.uc[2], (unsigned int) du1.uc[3],
		                   (unsigned int) du1.uc[4], (unsigned int) du1.uc[5],
		                   (unsigned int) du1.uc[6], (unsigned int) du1.uc[7],
		                   (unsigned int) du2.uc[0], (unsigned int) du2.uc[1],
		                   (unsigned int) du2.uc[2], (unsigned int) du2.uc[3],
		                   (unsigned int) du2.uc[4], (unsigned int) du2.uc[5],
		                   (unsigned int) du2.uc[6], (unsigned int) du2.uc[7]));

		if (duk_memcmp((const void *) du1.uc, (const void *) du2.uc, sizeof(du1.uc)) == 0) {
			duk_debug_write_int(thr, i32);
		} else {
			DUK_DBLUNION_DOUBLE_HTON(&du1);
			duk_debug_write_byte(thr, DUK_DBG_IB_NUMBER);
			duk_debug_write_bytes(thr, (const duk_uint8_t *) du1.uc, sizeof(du1.uc));
		}
	}
}

#if defined(DUK_USE_DEBUGGER_DUMPHEAP)
/* Variant for writing duk_tvals so that any heap allocated values are
 * written out as tagged heap pointers.
 */
DUK_LOCAL void duk__debug_write_tval_heapptr(duk_hthread *thr, duk_tval *tv) {
	if (DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
		duk_heaphdr *h = DUK_TVAL_GET_HEAPHDR(tv);
		duk_debug_write_heapptr(thr, h);
	} else {
		duk_debug_write_tval(thr, tv);
	}
}
#endif  /* DUK_USE_DEBUGGER_DUMPHEAP */

/*
 *  Debug connection message write helpers
 */

#if 0  /* unused */
DUK_INTERNAL void duk_debug_write_request(duk_hthread *thr, duk_small_uint_t command) {
	duk_debug_write_byte(thr, DUK_DBG_IB_REQUEST);
	duk_debug_write_int(thr, command);
}
#endif

DUK_INTERNAL void duk_debug_write_reply(duk_hthread *thr) {
	duk_debug_write_byte(thr, DUK_DBG_IB_REPLY);
}

DUK_INTERNAL void duk_debug_write_error_eom(duk_hthread *thr, duk_small_uint_t err_code, const char *msg) {
	/* Allow NULL 'msg' */
	duk_debug_write_byte(thr, DUK_DBG_IB_ERROR);
	duk_debug_write_int(thr, (duk_int32_t) err_code);
	duk_debug_write_cstring(thr, msg);
	duk_debug_write_eom(thr);
}

DUK_INTERNAL void duk_debug_write_notify(duk_hthread *thr, duk_small_uint_t command) {
	duk_debug_write_byte(thr, DUK_DBG_IB_NOTIFY);
	duk_debug_write_int(thr, (duk_int32_t) command);
}

DUK_INTERNAL void duk_debug_write_eom(duk_hthread *thr) {
	duk_debug_write_byte(thr, DUK_DBG_IB_EOM);

	/* As an initial implementation, write flush after every EOM (and the
	 * version identifier).  A better implementation would flush only when
	 * Duktape is finished processing messages so that a flush only happens
	 * after all outbound messages are finished on that occasion.
	 */
	duk_debug_write_flush(thr);
}

/*
 *  Status message and helpers
 */

DUK_INTERNAL duk_uint_fast32_t duk_debug_curr_line(duk_hthread *thr) {
	duk_activation *act;
	duk_uint_fast32_t line;
	duk_uint_fast32_t pc;

	act = thr->callstack_curr;
	if (act == NULL) {
		return 0;
	}

	/* We're conceptually between two opcodes; act->pc indicates the next
	 * instruction to be executed.  This is usually the correct pc/line to
	 * indicate in Status.  (For the 'debugger' statement this now reports
	 * the pc/line after the debugger statement because the debugger opcode
	 * has already been executed.)
	 */

	pc = duk_hthread_get_act_curr_pc(thr, act);

	/* XXX: this should be optimized to be a raw query and avoid valstack
	 * operations if possible.
	 */
	duk_push_tval(thr, &act->tv_func);
	line = duk_hobject_pc2line_query(thr, -1, pc);
	duk_pop(thr);
	return line;
}

DUK_INTERNAL void duk_debug_send_status(duk_hthread *thr) {
	duk_activation *act;

	duk_debug_write_notify(thr, DUK_DBG_CMD_STATUS);
	duk_debug_write_int(thr, (DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap) ? 1 : 0));

	act = thr->callstack_curr;
	if (act == NULL) {
		duk_debug_write_undefined(thr);
		duk_debug_write_undefined(thr);
		duk_debug_write_int(thr, 0);
		duk_debug_write_int(thr, 0);
	} else {
		duk_push_tval(thr, &act->tv_func);
		duk_get_prop_literal(thr, -1, "fileName");
		duk__debug_write_hstring_safe_top(thr);
		duk_get_prop_literal(thr, -2, "name");
		duk__debug_write_hstring_safe_top(thr);
		duk_pop_3(thr);
		/* Report next pc/line to be executed. */
		duk_debug_write_uint(thr, (duk_uint32_t) duk_debug_curr_line(thr));
		duk_debug_write_uint(thr, (duk_uint32_t) duk_hthread_get_act_curr_pc(thr, act));
	}

	duk_debug_write_eom(thr);
}

#if defined(DUK_USE_DEBUGGER_THROW_NOTIFY)
DUK_INTERNAL void duk_debug_send_throw(duk_hthread *thr, duk_bool_t fatal) {
	/*
	 *  NFY <int: 5> <int: fatal> <str: msg> <str: filename> <int: linenumber> EOM
	 */

	duk_activation *act;
	duk_uint32_t pc;

	DUK_ASSERT(thr->valstack_top > thr->valstack);  /* At least: ... [err] */

	duk_debug_write_notify(thr, DUK_DBG_CMD_THROW);
	duk_debug_write_int(thr, (duk_int32_t) fatal);

	/* Report thrown value to client coerced to string */
	duk_dup_top(thr);
	duk__debug_write_hstring_safe_top(thr);
	duk_pop(thr);

	if (duk_is_error(thr, -1)) {
		/* Error instance, use augmented error data directly */
		duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_FILE_NAME);
		duk__debug_write_hstring_safe_top(thr);
		duk_get_prop_stridx_short(thr, -2, DUK_STRIDX_LINE_NUMBER);
		duk_debug_write_uint(thr, duk_get_uint(thr, -1));
		duk_pop_2(thr);
	} else {
		/* For anything other than an Error instance, we calculate the
		 * error location directly from the current activation if one
		 * exists.
		 */
		act = thr->callstack_curr;
		if (act != NULL) {
			duk_push_tval(thr, &act->tv_func);
			duk_get_prop_literal(thr, -1, "fileName");
			duk__debug_write_hstring_safe_top(thr);
			pc = (duk_uint32_t) duk_hthread_get_act_prev_pc(thr, act);
			duk_debug_write_uint(thr, (duk_uint32_t) duk_hobject_pc2line_query(thr, -2, pc));
			duk_pop_2(thr);
		} else {
			/* Can happen if duk_throw() is called on an empty
			 * callstack.
			 */
			duk_debug_write_cstring(thr, "");
			duk_debug_write_uint(thr, 0);
		}
	}

	duk_debug_write_eom(thr);
}
#endif  /* DUK_USE_DEBUGGER_THROW_NOTIFY */

/*
 *  Debug message processing
 */

/* Skip dvalue. */
DUK_LOCAL duk_bool_t duk__debug_skip_dvalue(duk_hthread *thr) {
	duk_uint8_t x;
	duk_uint32_t len;

	x = duk_debug_read_byte(thr);

	if (x >= 0xc0) {
		duk_debug_skip_byte(thr);
		return 0;
	}
	if (x >= 0x80) {
		return 0;
	}
	if (x >= 0x60) {
		duk_debug_skip_bytes(thr, (duk_size_t) (x - 0x60));
		return 0;
	}
	switch(x) {
	case DUK_DBG_IB_EOM:
		return 1;  /* Return 1: got EOM */
	case DUK_DBG_IB_REQUEST:
	case DUK_DBG_IB_REPLY:
	case DUK_DBG_IB_ERROR:
	case DUK_DBG_IB_NOTIFY:
		break;
	case DUK_DBG_IB_INT4:
		(void) duk__debug_read_uint32_raw(thr);
		break;
	case DUK_DBG_IB_STR4:
	case DUK_DBG_IB_BUF4:
		len = duk__debug_read_uint32_raw(thr);
		duk_debug_skip_bytes(thr, len);
		break;
	case DUK_DBG_IB_STR2:
	case DUK_DBG_IB_BUF2:
		len = duk__debug_read_uint16_raw(thr);
		duk_debug_skip_bytes(thr, len);
		break;
	case DUK_DBG_IB_UNUSED:
	case DUK_DBG_IB_UNDEFINED:
	case DUK_DBG_IB_NULL:
	case DUK_DBG_IB_TRUE:
	case DUK_DBG_IB_FALSE:
		break;
	case DUK_DBG_IB_NUMBER:
		duk_debug_skip_bytes(thr, 8);
		break;
	case DUK_DBG_IB_OBJECT:
		duk_debug_skip_byte(thr);
		len = duk_debug_read_byte(thr);
		duk_debug_skip_bytes(thr, len);
		break;
	case DUK_DBG_IB_POINTER:
	case DUK_DBG_IB_HEAPPTR:
		len = duk_debug_read_byte(thr);
		duk_debug_skip_bytes(thr, len);
		break;
	case DUK_DBG_IB_LIGHTFUNC:
		duk_debug_skip_bytes(thr, 2);
		len = duk_debug_read_byte(thr);
		duk_debug_skip_bytes(thr, len);
		break;
	default:
		goto fail;
	}

	return 0;

 fail:
	DUK__SET_CONN_BROKEN(thr, 1);
	return 1;  /* Pretend like we got EOM */
}

/* Skip dvalues to EOM. */
DUK_LOCAL void duk__debug_skip_to_eom(duk_hthread *thr) {
	for (;;) {
		if (duk__debug_skip_dvalue(thr)) {
			break;
		}
	}
}

/* Read and validate a call stack index.  If index is invalid, write out an
 * error message and return zero.
 */
DUK_LOCAL duk_int32_t duk__debug_read_validate_csindex(duk_hthread *thr) {
	duk_int32_t level;
	level = duk_debug_read_int(thr);
	if (level >= 0 || -level > (duk_int32_t) thr->callstack_top) {
		duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid callstack index");
		return 0;  /* zero indicates failure */
	}
	return level;
}

/* Read a call stack index and lookup the corresponding duk_activation.
 * If index is invalid, write out an error message and return NULL.
 */
DUK_LOCAL duk_activation *duk__debug_read_level_get_activation(duk_hthread *thr) {
	duk_activation *act;
	duk_int32_t level;

	level = duk_debug_read_int(thr);
	act = duk_hthread_get_activation_for_level(thr, level);
	if (act == NULL) {
		duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid callstack index");
	}
	return act;
}

/*
 *  Simple commands
 */

DUK_LOCAL void duk__debug_handle_basic_info(duk_hthread *thr, duk_heap *heap) {
	DUK_UNREF(heap);
	DUK_D(DUK_DPRINT("debug command Version"));

	duk_debug_write_reply(thr);
	duk_debug_write_int(thr, DUK_VERSION);
	duk_debug_write_cstring(thr, DUK_GIT_DESCRIBE);
	duk_debug_write_cstring(thr, DUK_USE_TARGET_INFO);
#if defined(DUK_USE_DOUBLE_LE)
	duk_debug_write_int(thr, 1);
#elif defined(DUK_USE_DOUBLE_ME)
	duk_debug_write_int(thr, 2);
#elif defined(DUK_USE_DOUBLE_BE)
	duk_debug_write_int(thr, 3);
#else
	duk_debug_write_int(thr, 0);
#endif
	duk_debug_write_int(thr, (duk_int_t) sizeof(void *));
	duk_debug_write_eom(thr);
}

DUK_LOCAL void duk__debug_handle_trigger_status(duk_hthread *thr, duk_heap *heap) {
	DUK_UNREF(heap);
	DUK_D(DUK_DPRINT("debug command TriggerStatus"));

	duk_debug_write_reply(thr);
	duk_debug_write_eom(thr);
	heap->dbg_state_dirty = 1;
}

DUK_LOCAL void duk__debug_handle_pause(duk_hthread *thr, duk_heap *heap) {
	DUK_D(DUK_DPRINT("debug command Pause"));
	duk_debug_set_paused(heap);
	duk_debug_write_reply(thr);
	duk_debug_write_eom(thr);
}

DUK_LOCAL void duk__debug_handle_resume(duk_hthread *thr, duk_heap *heap) {
	duk_small_uint_t pause_flags;

	DUK_D(DUK_DPRINT("debug command Resume"));

	duk_debug_clear_paused(heap);

	pause_flags = 0;
#if 0  /* manual testing */
	pause_flags |= DUK_PAUSE_FLAG_ONE_OPCODE;
	pause_flags |= DUK_PAUSE_FLAG_CAUGHT_ERROR;
	pause_flags |= DUK_PAUSE_FLAG_UNCAUGHT_ERROR;
#endif
#if defined(DUK_USE_DEBUGGER_PAUSE_UNCAUGHT)
	pause_flags |= DUK_PAUSE_FLAG_UNCAUGHT_ERROR;
#endif

	duk__debug_set_pause_state(thr, heap, pause_flags);

	duk_debug_write_reply(thr);
	duk_debug_write_eom(thr);
}

DUK_LOCAL void duk__debug_handle_step(duk_hthread *thr, duk_heap *heap, duk_int32_t cmd) {
	duk_small_uint_t pause_flags;

	DUK_D(DUK_DPRINT("debug command StepInto/StepOver/StepOut: %d", (int) cmd));

	if (cmd == DUK_DBG_CMD_STEPINTO) {
		pause_flags = DUK_PAUSE_FLAG_LINE_CHANGE |
		              DUK_PAUSE_FLAG_FUNC_ENTRY |
		              DUK_PAUSE_FLAG_FUNC_EXIT;
	} else if (cmd == DUK_DBG_CMD_STEPOVER) {
		pause_flags = DUK_PAUSE_FLAG_LINE_CHANGE |
		              DUK_PAUSE_FLAG_FUNC_EXIT;
	} else {
		DUK_ASSERT(cmd == DUK_DBG_CMD_STEPOUT);
		pause_flags = DUK_PAUSE_FLAG_FUNC_EXIT;
	}
#if defined(DUK_USE_DEBUGGER_PAUSE_UNCAUGHT)
	pause_flags |= DUK_PAUSE_FLAG_UNCAUGHT_ERROR;
#endif

	/* If current activation doesn't have line information, line-based
	 * pause flags are automatically disabled.  As a result, e.g.
	 * StepInto will then pause on (native) function entry or exit.
	 */
	duk_debug_clear_paused(heap);
	duk__debug_set_pause_state(thr, heap, pause_flags);

	duk_debug_write_reply(thr);
	duk_debug_write_eom(thr);
}

DUK_LOCAL void duk__debug_handle_list_break(duk_hthread *thr, duk_heap *heap) {
	duk_small_int_t i;

	DUK_D(DUK_DPRINT("debug command ListBreak"));
	duk_debug_write_reply(thr);
	for (i = 0; i < (duk_small_int_t) heap->dbg_breakpoint_count; i++) {
		duk_debug_write_hstring(thr, heap->dbg_breakpoints[i].filename);
		duk_debug_write_uint(thr, (duk_uint32_t) heap->dbg_breakpoints[i].line);
	}
	duk_debug_write_eom(thr);
}

DUK_LOCAL void duk__debug_handle_add_break(duk_hthread *thr, duk_heap *heap) {
	duk_hstring *filename;
	duk_uint32_t linenumber;
	duk_small_int_t idx;

	DUK_UNREF(heap);

	filename = duk_debug_read_hstring(thr);
	linenumber = (duk_uint32_t) duk_debug_read_int(thr);
	DUK_D(DUK_DPRINT("debug command AddBreak: %!O:%ld", (duk_hobject *) filename, (long) linenumber));
	idx = duk_debug_add_breakpoint(thr, filename, linenumber);
	if (idx >= 0) {
		duk_debug_write_reply(thr);
		duk_debug_write_int(thr, (duk_int32_t) idx);
		duk_debug_write_eom(thr);
	} else {
		duk_debug_write_error_eom(thr, DUK_DBG_ERR_TOOMANY, "no space for breakpoint");
	}
}

DUK_LOCAL void duk__debug_handle_del_break(duk_hthread *thr, duk_heap *heap) {
	duk_small_uint_t idx;

	DUK_UNREF(heap);

	DUK_D(DUK_DPRINT("debug command DelBreak"));
	idx = (duk_small_uint_t) duk_debug_read_int(thr);
	if (duk_debug_remove_breakpoint(thr, idx)) {
		duk_debug_write_reply(thr);
		duk_debug_write_eom(thr);
	} else {
		duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid breakpoint index");
	}
}

DUK_LOCAL void duk__debug_handle_get_var(duk_hthread *thr, duk_heap *heap) {
	duk_activation *act;
	duk_hstring *str;
	duk_bool_t rc;

	DUK_UNREF(heap);
	DUK_D(DUK_DPRINT("debug command GetVar"));

	act = duk__debug_read_level_get_activation(thr);
	if (act == NULL) {
		return;
	}
	str = duk_debug_read_hstring(thr);  /* push to stack */
	DUK_ASSERT(str != NULL);

	rc = duk_js_getvar_activation(thr, act, str, 0);

	duk_debug_write_reply(thr);
	if (rc) {
		duk_debug_write_int(thr, 1);
		DUK_ASSERT(duk_get_tval(thr, -2) != NULL);
		duk_debug_write_tval(thr, duk_get_tval(thr, -2));
	} else {
		duk_debug_write_int(thr, 0);
		duk_debug_write_unused(thr);
	}
	duk_debug_write_eom(thr);
}

DUK_LOCAL void duk__debug_handle_put_var(duk_hthread *thr, duk_heap *heap) {
	duk_activation *act;
	duk_hstring *str;
	duk_tval *tv;

	DUK_UNREF(heap);
	DUK_D(DUK_DPRINT("debug command PutVar"));

	act = duk__debug_read_level_get_activation(thr);
	if (act == NULL) {
		return;
	}
	str = duk_debug_read_hstring(thr);  /* push to stack */
	DUK_ASSERT(str != NULL);
	tv = duk_debug_read_tval(thr);
	if (tv == NULL) {
		/* detached */
		return;
	}

	duk_js_putvar_activation(thr, act, str, tv, 0);

	/* XXX: Current putvar implementation doesn't have a success flag,
	 * add one and send to debug client?
	 */
	duk_debug_write_reply(thr);
	duk_debug_write_eom(thr);
}

DUK_LOCAL void duk__debug_handle_get_call_stack(duk_hthread *thr, duk_heap *heap) {
	duk_hthread *curr_thr = thr;
	duk_activation *curr_act;
	duk_uint_fast32_t pc;
	duk_uint_fast32_t line;

	DUK_ASSERT(thr != NULL);
	DUK_UNREF(heap);

	duk_debug_write_reply(thr);
	while (curr_thr != NULL) {
		for (curr_act = curr_thr->callstack_curr; curr_act != NULL; curr_act = curr_act->parent) {
			/* PC/line semantics here are:
			 *   - For callstack top we're conceptually between two
			 *     opcodes and current PC indicates next line to
			 *     execute, so report that (matches Status).
			 *   - For other activations we're conceptually still
			 *     executing the instruction at PC-1, so report that
			 *     (matches error stacktrace behavior).
			 *   - See: https://github.com/svaarala/duktape/issues/281
			 */

			/* XXX: optimize to use direct reads, i.e. avoid
			 * value stack operations.
			 */
			duk_push_tval(thr, &curr_act->tv_func);
			duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_FILE_NAME);
			duk__debug_write_hstring_safe_top(thr);
			duk_get_prop_stridx_short(thr, -2, DUK_STRIDX_NAME);
			duk__debug_write_hstring_safe_top(thr);
			pc = duk_hthread_get_act_curr_pc(thr, curr_act);
			if (curr_act != curr_thr->callstack_curr && pc > 0) {
				pc--;
			}
			line = duk_hobject_pc2line_query(thr, -3, pc);
			duk_debug_write_uint(thr, (duk_uint32_t) line);
			duk_debug_write_uint(thr, (duk_uint32_t) pc);
			duk_pop_3(thr);
		}
		curr_thr = curr_thr->resumer;
	}
	/* SCANBUILD: warning about 'thr' potentially being NULL here,
	 * warning is incorrect because thr != NULL always here.
	 */
	duk_debug_write_eom(thr);
}

DUK_LOCAL void duk__debug_handle_get_locals(duk_hthread *thr, duk_heap *heap) {
	duk_activation *act;
	duk_hstring *varname;

	DUK_UNREF(heap);

	act = duk__debug_read_level_get_activation(thr);
	if (act == NULL) {
		return;
	}

	duk_debug_write_reply(thr);

	/* XXX: several nice-to-have improvements here:
	 *   - Use direct reads avoiding value stack operations
	 *   - Avoid triggering getters, indicate getter values to debug client
	 *   - If side effects are possible, add error catching
	 */

	if (DUK_TVAL_IS_OBJECT(&act->tv_func)) {
		duk_hobject *h_func = DUK_TVAL_GET_OBJECT(&act->tv_func);
		duk_hobject *h_varmap;

		h_varmap = duk_hobject_get_varmap(thr, h_func);
		if (h_varmap != NULL) {
			duk_push_hobject(thr, h_varmap);
			duk_enum(thr, -1, 0 /*enum_flags*/);
			while (duk_next(thr, -1 /*enum_index*/, 0 /*get_value*/)) {
				varname = duk_known_hstring(thr, -1);

				duk_js_getvar_activation(thr, act, varname, 0 /*throw_flag*/);
				/* [ ... func varmap enum key value this ] */
				duk_debug_write_hstring(thr, duk_get_hstring(thr, -3));
				duk_debug_write_tval(thr, duk_get_tval(thr, -2));
				duk_pop_3(thr);  /* -> [ ... func varmap enum ] */
			}
		} else {
			DUK_D(DUK_DPRINT("varmap missing in GetLocals, ignore"));
		}
	} else {
		DUK_D(DUK_DPRINT("varmap is not an object in GetLocals, ignore"));
	}

	duk_debug_write_eom(thr);
}

DUK_LOCAL void duk__debug_handle_eval(duk_hthread *thr, duk_heap *heap) {
	duk_small_uint_t call_flags;
	duk_int_t call_ret;
	duk_small_int_t eval_err;
	duk_bool_t direct_eval;
	duk_int32_t level;
	duk_idx_t idx_func;

	DUK_UNREF(heap);

	DUK_D(DUK_DPRINT("debug command Eval"));

	/* The eval code is executed within the lexical environment of a specified
	 * activation.  For now, use global object eval() function, with the eval
	 * considered a 'direct call to eval'.
	 *
	 * Callstack index for debug commands only affects scope -- the callstack
	 * as seen by, e.g. Duktape.act() will be the same regardless.
	 */

	/* nargs == 2 so we can pass a callstack index to eval(). */
	idx_func = duk_get_top(thr);
	duk_push_c_function(thr, duk_bi_global_object_eval, 2 /*nargs*/);
	duk_push_undefined(thr);  /* 'this' binding shouldn't matter here */

	/* Read callstack index, if non-null. */
	if (duk_debug_peek_byte(thr) == DUK_DBG_IB_NULL) {
		direct_eval = 0;
		level = -1;  /* Not needed, but silences warning. */
		(void) duk_debug_read_byte(thr);
	} else {
		direct_eval = 1;
		level = duk__debug_read_validate_csindex(thr);
		if (level == 0) {
			return;
		}
	}

	DUK_ASSERT(!direct_eval ||
	           (level < 0 && -level <= (duk_int32_t) thr->callstack_top));

	(void) duk_debug_read_hstring(thr);
	if (direct_eval) {
		duk_push_int(thr, level - 1);  /* compensate for eval() call */
	}

	/* [ ... eval "eval" eval_input level? ] */

	call_flags = 0;
	if (direct_eval) {
		duk_activation *act;
		duk_hobject *fun;

		act = duk_hthread_get_activation_for_level(thr, level);
		if (act != NULL) {
			fun = DUK_ACT_GET_FUNC(act);
			if (fun != NULL && DUK_HOBJECT_IS_COMPFUNC(fun)) {
				/* Direct eval requires that there's a current
				 * activation and it is an ECMAScript function.
				 * When Eval is executed from e.g. cooperate API
				 * call we'll need to do an indirect eval instead.
				 */
				call_flags |= DUK_CALL_FLAG_DIRECT_EVAL;
			}
		}
	}

	call_ret = duk_pcall_method_flags(thr, duk_get_top(thr) - (idx_func + 2), call_flags);

	if (call_ret == DUK_EXEC_SUCCESS) {
		eval_err = 0;
		/* Use result value as is. */
	} else {
		/* For errors a string coerced result is most informative
		 * right now, as the debug client doesn't have the capability
		 * to traverse the error object.
		 */
		eval_err = 1;
		duk_safe_to_string(thr, -1);
	}

	/* [ ... result ] */

	duk_debug_write_reply(thr);
	duk_debug_write_int(thr, (duk_int32_t) eval_err);
	DUK_ASSERT(duk_get_tval(thr, -1) != NULL);
	duk_debug_write_tval(thr, duk_get_tval(thr, -1));
	duk_debug_write_eom(thr);
}

DUK_LOCAL void duk__debug_handle_detach(duk_hthread *thr, duk_heap *heap) {
	DUK_UNREF(heap);
	DUK_D(DUK_DPRINT("debug command Detach"));

	duk_debug_write_reply(thr);
	duk_debug_write_eom(thr);

	DUK_D(DUK_DPRINT("debug connection detached, mark broken"));
	DUK__SET_CONN_BROKEN(thr, 0);  /* not an error */
}

DUK_LOCAL void duk__debug_handle_apprequest(duk_hthread *thr, duk_heap *heap) {
	duk_idx_t old_top;

	DUK_D(DUK_DPRINT("debug command AppRequest"));

	old_top = duk_get_top(thr);  /* save stack top */

	if (heap->dbg_request_cb != NULL) {
		duk_idx_t nrets;
		duk_idx_t nvalues = 0;
		duk_idx_t top, idx;

		/* Read tvals from the message and push them onto the valstack,
		 * then call the request callback to process the request.
		 */
		while (duk_debug_peek_byte(thr) != DUK_DBG_IB_EOM) {
			duk_tval *tv;
			if (!duk_check_stack(thr, 1)) {
				DUK_D(DUK_DPRINT("failed to allocate space for request dvalue(s)"));
				goto fail;
			}
			tv = duk_debug_read_tval(thr);  /* push to stack */
			if (tv == NULL) {
				/* detached */
				return;
			}
			nvalues++;
		}
		DUK_ASSERT(duk_get_top(thr) == old_top + nvalues);

		/* Request callback should push values for reply to client onto valstack */
		DUK_D(DUK_DPRINT("calling into AppRequest request_cb with nvalues=%ld, old_top=%ld, top=%ld",
		                 (long) nvalues, (long) old_top, (long) duk_get_top(thr)));
		nrets = heap->dbg_request_cb(thr, heap->dbg_udata, nvalues);
		DUK_D(DUK_DPRINT("returned from AppRequest request_cb; nvalues=%ld -> nrets=%ld, old_top=%ld, top=%ld",
		                 (long) nvalues, (long) nrets, (long) old_top, (long) duk_get_top(thr)));
		if (nrets >= 0) {
			DUK_ASSERT(duk_get_top(thr) >= old_top + nrets);
			if (duk_get_top(thr) < old_top + nrets) {
				DUK_D(DUK_DPRINT("AppRequest callback doesn't match value stack configuration, "
				                 "top=%ld < old_top=%ld + nrets=%ld; "
				                 "this might mean it's unsafe to continue!",
				                 (long) duk_get_top(thr), (long) old_top, (long) nrets));
				goto fail;
			}

			/* Reply with tvals pushed by request callback */
			duk_debug_write_byte(thr, DUK_DBG_IB_REPLY);
			top = duk_get_top(thr);
			for (idx = top - nrets; idx < top; idx++) {
				duk_debug_write_tval(thr, DUK_GET_TVAL_POSIDX(thr, idx));
			}
			duk_debug_write_eom(thr);
		} else {
			DUK_ASSERT(duk_get_top(thr) >= old_top + 1);
			if (duk_get_top(thr) < old_top + 1) {
				DUK_D(DUK_DPRINT("request callback return value doesn't match value stack configuration"));
				goto fail;
			}
			duk_debug_write_error_eom(thr, DUK_DBG_ERR_APPLICATION, duk_get_string(thr, -1));
		}

		duk_set_top(thr, old_top);  /* restore stack top */
	} else {
		DUK_D(DUK_DPRINT("no request callback, treat AppRequest as unsupported"));
		duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNSUPPORTED, "AppRequest unsupported by target");
	}

	return;

 fail:
	duk_set_top(thr, old_top);  /* restore stack top */
	DUK__SET_CONN_BROKEN(thr, 1);
}

/*
 *  DumpHeap command
 */

#if defined(DUK_USE_DEBUGGER_DUMPHEAP)
/* XXX: this has some overlap with object inspection; remove this and make
 * DumpHeap return lists of heapptrs instead?
 */
DUK_LOCAL void duk__debug_dump_heaphdr(duk_hthread *thr, duk_heap *heap, duk_heaphdr *hdr) {
	DUK_UNREF(heap);

	duk_debug_write_heapptr(thr, hdr);
	duk_debug_write_uint(thr, (duk_uint32_t) DUK_HEAPHDR_GET_TYPE(hdr));
	duk_debug_write_uint(thr, (duk_uint32_t) DUK_HEAPHDR_GET_FLAGS_RAW(hdr));
#if defined(DUK_USE_REFERENCE_COUNTING)
	duk_debug_write_uint(thr, (duk_uint32_t) DUK_HEAPHDR_GET_REFCOUNT(hdr));
#else
	duk_debug_write_int(thr, (duk_int32_t) -1);
#endif

	switch (DUK_HEAPHDR_GET_TYPE(hdr)) {
	case DUK_HTYPE_STRING: {
		duk_hstring *h = (duk_hstring *) hdr;

		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HSTRING_GET_BYTELEN(h));
		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HSTRING_GET_CHARLEN(h));
		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HSTRING_GET_HASH(h));
		duk_debug_write_hstring(thr, h);
		break;
	}
	case DUK_HTYPE_OBJECT: {
		duk_hobject *h = (duk_hobject *) hdr;
		duk_hstring *k;
		duk_uint_fast32_t i;

		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_CLASS_NUMBER(h));
		duk_debug_write_heapptr(thr, (duk_heaphdr *) DUK_HOBJECT_GET_PROTOTYPE(heap, h));
		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_ESIZE(h));
		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_ENEXT(h));
		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_ASIZE(h));
		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_HSIZE(h));

		for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h); i++) {
			duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_E_GET_FLAGS(heap, h, i));
			k = DUK_HOBJECT_E_GET_KEY(heap, h, i);
			duk_debug_write_heapptr(thr, (duk_heaphdr *) k);
			if (k == NULL) {
				duk_debug_write_int(thr, 0);  /* isAccessor */
				duk_debug_write_unused(thr);
				continue;
			}
			if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, h, i)) {
				duk_debug_write_int(thr, 1);  /* isAccessor */
				duk_debug_write_heapptr(thr, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.get);
				duk_debug_write_heapptr(thr, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.set);
			} else {
				duk_debug_write_int(thr, 0);  /* isAccessor */

				duk__debug_write_tval_heapptr(thr, &DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->v);
			}
		}

		for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(h); i++) {
			/* Note: array dump will include elements beyond
			 * 'length'.
			 */
			duk__debug_write_tval_heapptr(thr, DUK_HOBJECT_A_GET_VALUE_PTR(heap, h, i));
		}
		break;
	}
	case DUK_HTYPE_BUFFER: {
		duk_hbuffer *h = (duk_hbuffer *) hdr;

		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HBUFFER_GET_SIZE(h));
		duk_debug_write_buffer(thr, (const char *) DUK_HBUFFER_GET_DATA_PTR(heap, h), (duk_size_t) DUK_HBUFFER_GET_SIZE(h));
		break;
	}
	default: {
		DUK_D(DUK_DPRINT("invalid htype: %d", (int) DUK_HEAPHDR_GET_TYPE(hdr)));
	}
	}
}

DUK_LOCAL void duk__debug_dump_heap_allocated(duk_hthread *thr, duk_heap *heap) {
	duk_heaphdr *hdr;

	hdr = heap->heap_allocated;
	while (hdr != NULL) {
		duk__debug_dump_heaphdr(thr, heap, hdr);
		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
	}
}

DUK_LOCAL void duk__debug_dump_strtab(duk_hthread *thr, duk_heap *heap) {
	duk_uint32_t i;
	duk_hstring *h;

	for (i = 0; i < heap->st_size; i++) {
#if defined(DUK_USE_STRTAB_PTRCOMP)
		h = DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, heap->strtable16[i]);
#else
		h = heap->strtable[i];
#endif
		while (h != NULL) {
			duk__debug_dump_heaphdr(thr, heap, (duk_heaphdr *) h);
			h = h->hdr.h_next;
		}
	}
}

DUK_LOCAL void duk__debug_handle_dump_heap(duk_hthread *thr, duk_heap *heap) {
	DUK_D(DUK_DPRINT("debug command DumpHeap"));

	duk_debug_write_reply(thr);
	duk__debug_dump_heap_allocated(thr, heap);
	duk__debug_dump_strtab(thr, heap);
	duk_debug_write_eom(thr);
}
#endif  /* DUK_USE_DEBUGGER_DUMPHEAP */

DUK_LOCAL void duk__debug_handle_get_bytecode(duk_hthread *thr, duk_heap *heap) {
	duk_activation *act;
	duk_hcompfunc *fun = NULL;
	duk_size_t i, n;
	duk_tval *tv;
	duk_hobject **fn;
	duk_int32_t level = -1;
	duk_uint8_t ibyte;

	DUK_UNREF(heap);

	DUK_D(DUK_DPRINT("debug command GetBytecode"));

	ibyte = duk_debug_peek_byte(thr);
	if (ibyte != DUK_DBG_IB_EOM) {
		tv = duk_debug_read_tval(thr);
		if (tv == NULL) {
			/* detached */
			return;
		}
		if (DUK_TVAL_IS_OBJECT(tv)) {
			/* tentative, checked later */
			fun = (duk_hcompfunc *) DUK_TVAL_GET_OBJECT(tv);
			DUK_ASSERT(fun != NULL);
		} else if (DUK_TVAL_IS_NUMBER(tv)) {
			level = (duk_int32_t) DUK_TVAL_GET_NUMBER(tv);
		} else {
			DUK_D(DUK_DPRINT("invalid argument to GetBytecode: %!T", tv));
			goto fail_args;
		}
	}

	if (fun == NULL) {
		act = duk_hthread_get_activation_for_level(thr, level);
		if (act == NULL) {
			goto fail_index;
		}
		fun = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);
	}

	if (fun == NULL || !DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) fun)) {
		DUK_D(DUK_DPRINT("invalid argument to GetBytecode: %!O", fun));
		goto fail_args;
	}
	DUK_ASSERT(fun != NULL && DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) fun));

	duk_debug_write_reply(thr);
	n = DUK_HCOMPFUNC_GET_CONSTS_COUNT(heap, fun);
	duk_debug_write_int(thr, (duk_int32_t) n);
	tv = DUK_HCOMPFUNC_GET_CONSTS_BASE(heap, fun);
	for (i = 0; i < n; i++) {
		duk_debug_write_tval(thr, tv);
		tv++;
	}
	n = DUK_HCOMPFUNC_GET_FUNCS_COUNT(heap, fun);
	duk_debug_write_int(thr, (duk_int32_t) n);
	fn = DUK_HCOMPFUNC_GET_FUNCS_BASE(heap, fun);
	for (i = 0; i < n; i++) {
		duk_debug_write_hobject(thr, *fn);
		fn++;
	}
	duk_debug_write_string(thr,
	                       (const char *) DUK_HCOMPFUNC_GET_CODE_BASE(heap, fun),
	                       (duk_size_t) DUK_HCOMPFUNC_GET_CODE_SIZE(heap, fun));
	duk_debug_write_eom(thr);
	return;

 fail_args:
	duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid argument");
	return;

 fail_index:
	duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid callstack index");
	return;
}

/*
 *  Object inspection commands: GetHeapObjInfo, GetObjPropDesc,
 *  GetObjPropDescRange
 */

#if defined(DUK_USE_DEBUGGER_INSPECT)

#if 0 /* pruned */
DUK_LOCAL const char * const duk__debug_getinfo_heaphdr_keys[] = {
	"reachable",
	"temproot",
	"finalizable",
	"finalized",
	"readonly"
	/* NULL not needed here */
};
DUK_LOCAL duk_uint_t duk__debug_getinfo_heaphdr_masks[] = {
	DUK_HEAPHDR_FLAG_REACHABLE,
	DUK_HEAPHDR_FLAG_TEMPROOT,
	DUK_HEAPHDR_FLAG_FINALIZABLE,
	DUK_HEAPHDR_FLAG_FINALIZED,
	DUK_HEAPHDR_FLAG_READONLY,
	0  /* terminator */
};
#endif
DUK_LOCAL const char * const duk__debug_getinfo_hstring_keys[] = {
#if 0
	"arridx",
	"symbol",
	"hidden",
	"reserved_word",
	"strict_reserved_word",
	"eval_or_arguments",
#endif
	"extdata"
	/* NULL not needed here */
};
DUK_LOCAL duk_uint_t duk__debug_getinfo_hstring_masks[] = {
#if 0
	DUK_HSTRING_FLAG_ARRIDX,
	DUK_HSTRING_FLAG_SYMBOL,
	DUK_HSTRING_FLAG_HIDDEN,
	DUK_HSTRING_FLAG_RESERVED_WORD,
	DUK_HSTRING_FLAG_STRICT_RESERVED_WORD,
	DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS,
#endif
	DUK_HSTRING_FLAG_EXTDATA,
	0  /* terminator */
};
DUK_LOCAL const char * const duk__debug_getinfo_hobject_keys[] = {
	"extensible",
	"constructable",
	"callable",
	"boundfunc",
	"compfunc",
	"natfunc",
	"bufobj",
	"fastrefs",
	"array_part",
	"strict",
	"notail",
	"newenv",
	"namebinding",
	"createargs",
	"have_finalizer",
	"exotic_array",
	"exotic_stringobj",
	"exotic_arguments",
	"exotic_proxyobj",
	"special_call"
	/* NULL not needed here */
};
DUK_LOCAL duk_uint_t duk__debug_getinfo_hobject_masks[] = {
	DUK_HOBJECT_FLAG_EXTENSIBLE,
	DUK_HOBJECT_FLAG_CONSTRUCTABLE,
	DUK_HOBJECT_FLAG_CALLABLE,
	DUK_HOBJECT_FLAG_BOUNDFUNC,
	DUK_HOBJECT_FLAG_COMPFUNC,
	DUK_HOBJECT_FLAG_NATFUNC,
	DUK_HOBJECT_FLAG_BUFOBJ,
	DUK_HOBJECT_FLAG_FASTREFS,
	DUK_HOBJECT_FLAG_ARRAY_PART,
	DUK_HOBJECT_FLAG_STRICT,
	DUK_HOBJECT_FLAG_NOTAIL,
	DUK_HOBJECT_FLAG_NEWENV,
	DUK_HOBJECT_FLAG_NAMEBINDING,
	DUK_HOBJECT_FLAG_CREATEARGS,
	DUK_HOBJECT_FLAG_HAVE_FINALIZER,
	DUK_HOBJECT_FLAG_EXOTIC_ARRAY,
	DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ,
	DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS,
	DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ,
	DUK_HOBJECT_FLAG_SPECIAL_CALL,
	0  /* terminator */
};
DUK_LOCAL const char * const duk__debug_getinfo_hbuffer_keys[] = {
	"dynamic",
	"external"
	/* NULL not needed here */
};
DUK_LOCAL duk_uint_t duk__debug_getinfo_hbuffer_masks[] = {
	DUK_HBUFFER_FLAG_DYNAMIC,
	DUK_HBUFFER_FLAG_EXTERNAL,
	0  /* terminator */
};

DUK_LOCAL void duk__debug_getinfo_flags_key(duk_hthread *thr, const char *key) {
	duk_debug_write_uint(thr, 0);
	duk_debug_write_cstring(thr, key);
}

DUK_LOCAL void duk__debug_getinfo_prop_uint(duk_hthread *thr, const char *key, duk_uint_t val) {
	duk_debug_write_uint(thr, 0);
	duk_debug_write_cstring(thr, key);
	duk_debug_write_uint(thr, val);
}

DUK_LOCAL void duk__debug_getinfo_prop_int(duk_hthread *thr, const char *key, duk_int_t val) {
	duk_debug_write_uint(thr, 0);
	duk_debug_write_cstring(thr, key);
	duk_debug_write_int(thr, val);
}

DUK_LOCAL void duk__debug_getinfo_prop_bool(duk_hthread *thr, const char *key, duk_bool_t val) {
	duk_debug_write_uint(thr, 0);
	duk_debug_write_cstring(thr, key);
	duk_debug_write_boolean(thr, val);
}

DUK_LOCAL void duk__debug_getinfo_bitmask(duk_hthread *thr, const char * const * keys, duk_uint_t *masks, duk_uint_t flags) {
	const char *key;
	duk_uint_t mask;

	for (;;) {
		mask = *masks++;
		if (mask == 0) {
			break;
		}
		key = *keys++;
		DUK_ASSERT(key != NULL);

		DUK_DD(DUK_DDPRINT("inspect bitmask: key=%s, mask=0x%08lx, flags=0x%08lx", key, (unsigned long) mask, (unsigned long) flags));
		duk__debug_getinfo_prop_bool(thr, key, flags & mask);
	}
}

/* Inspect a property using a virtual index into a conceptual property list
 * consisting of (1) all array part items from [0,a_size[ (even when above
 * .length) and (2) all entry part items from [0,e_next[.  Unused slots are
 * indicated using dvalue 'unused'.
 */
DUK_LOCAL duk_bool_t duk__debug_getprop_index(duk_hthread *thr, duk_heap *heap, duk_hobject *h_obj, duk_uint_t idx) {
	duk_uint_t a_size;
	duk_tval *tv;
	duk_hstring *h_key;
	duk_hobject *h_getset;
	duk_uint_t flags;

	DUK_UNREF(heap);

	a_size = DUK_HOBJECT_GET_ASIZE(h_obj);
	if (idx < a_size) {
		duk_debug_write_uint(thr, DUK_PROPDESC_FLAGS_WEC);
		duk_debug_write_uint(thr, idx);
		tv = DUK_HOBJECT_A_GET_VALUE_PTR(heap, h_obj, idx);
		duk_debug_write_tval(thr, tv);
		return 1;
	}

	idx -= a_size;
	if (idx >= DUK_HOBJECT_GET_ENEXT(h_obj)) {
		return 0;
	}

	h_key = DUK_HOBJECT_E_GET_KEY(heap, h_obj, idx);
	if (h_key == NULL) {
		duk_debug_write_uint(thr, 0);
		duk_debug_write_null(thr);
		duk_debug_write_unused(thr);
		return 1;
	}

	flags = DUK_HOBJECT_E_GET_FLAGS(heap, h_obj, idx);
	if (DUK_HSTRING_HAS_SYMBOL(h_key)) {
		flags |= DUK_DBG_PROPFLAG_SYMBOL;
	}
	if (DUK_HSTRING_HAS_HIDDEN(h_key)) {
		flags |= DUK_DBG_PROPFLAG_HIDDEN;
	}
	duk_debug_write_uint(thr, flags);
	duk_debug_write_hstring(thr, h_key);
	if (flags & DUK_PROPDESC_FLAG_ACCESSOR) {
		h_getset = DUK_HOBJECT_E_GET_VALUE_GETTER(heap, h_obj, idx);
		if (h_getset) {
			duk_debug_write_hobject(thr, h_getset);
		} else {
			duk_debug_write_null(thr);
		}
		h_getset = DUK_HOBJECT_E_GET_VALUE_SETTER(heap, h_obj, idx);
		if (h_getset) {
			duk_debug_write_hobject(thr, h_getset);
		} else {
			duk_debug_write_null(thr);
		}
	} else {
		tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap, h_obj, idx);
		duk_debug_write_tval(thr, tv);
	}
	return 1;
}

DUK_LOCAL void duk__debug_handle_get_heap_obj_info(duk_hthread *thr, duk_heap *heap) {
	duk_heaphdr *h;

	DUK_D(DUK_DPRINT("debug command GetHeapObjInfo"));
	DUK_UNREF(heap);

	DUK_ASSERT(sizeof(duk__debug_getinfo_hstring_keys) / sizeof(const char *) == sizeof(duk__debug_getinfo_hstring_masks) / sizeof(duk_uint_t) - 1);
	DUK_ASSERT(sizeof(duk__debug_getinfo_hobject_keys) / sizeof(const char *) == sizeof(duk__debug_getinfo_hobject_masks) / sizeof(duk_uint_t) - 1);
	DUK_ASSERT(sizeof(duk__debug_getinfo_hbuffer_keys) / sizeof(const char *) == sizeof(duk__debug_getinfo_hbuffer_masks) / sizeof(duk_uint_t) - 1);

	h = duk_debug_read_any_ptr(thr);
	if (!h) {
		duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid target");
		return;
	}

	duk_debug_write_reply(thr);

	/* As with all inspection code, we rely on the debug client providing
	 * a valid, non-stale pointer: there's no portable way to safely
	 * validate the pointer here.
	 */

	duk__debug_getinfo_flags_key(thr, "heapptr");
	duk_debug_write_heapptr(thr, h);

	/* XXX: comes out as signed now */
	duk__debug_getinfo_prop_uint(thr, "heaphdr_flags", (duk_uint_t) DUK_HEAPHDR_GET_FLAGS(h));
	duk__debug_getinfo_prop_uint(thr, "heaphdr_type", (duk_uint_t) DUK_HEAPHDR_GET_TYPE(h));
#if defined(DUK_USE_REFERENCE_COUNTING)
	duk__debug_getinfo_prop_uint(thr, "refcount", (duk_uint_t) DUK_HEAPHDR_GET_REFCOUNT(h));
#endif
#if 0 /* pruned */
	duk__debug_getinfo_bitmask(thr,
	                           duk__debug_getinfo_heaphdr_keys,
	                           duk__debug_getinfo_heaphdr_masks,
	                           DUK_HEAPHDR_GET_FLAGS_RAW(h));
#endif

	switch (DUK_HEAPHDR_GET_TYPE(h)) {
	case DUK_HTYPE_STRING: {
		duk_hstring *h_str;

		h_str = (duk_hstring *) h;
		duk__debug_getinfo_bitmask(thr,
		                           duk__debug_getinfo_hstring_keys,
		                           duk__debug_getinfo_hstring_masks,
		                           DUK_HEAPHDR_GET_FLAGS_RAW(h));
		duk__debug_getinfo_prop_uint(thr, "bytelen", (duk_uint_t) DUK_HSTRING_GET_BYTELEN(h_str));
		duk__debug_getinfo_prop_uint(thr, "charlen", (duk_uint_t) DUK_HSTRING_GET_CHARLEN(h_str));
		duk__debug_getinfo_prop_uint(thr, "hash", (duk_uint_t) DUK_HSTRING_GET_HASH(h_str));
		duk__debug_getinfo_flags_key(thr, "data");
		duk_debug_write_hstring(thr, h_str);
		break;
	}
	case DUK_HTYPE_OBJECT: {
		duk_hobject *h_obj;
		duk_hobject *h_proto;

		h_obj = (duk_hobject *) h;
		h_proto = DUK_HOBJECT_GET_PROTOTYPE(heap, h_obj);

		/* duk_hobject specific fields. */
		duk__debug_getinfo_bitmask(thr,
		                           duk__debug_getinfo_hobject_keys,
		                           duk__debug_getinfo_hobject_masks,
		                           DUK_HEAPHDR_GET_FLAGS_RAW(h));
		duk__debug_getinfo_prop_uint(thr, "class_number", DUK_HOBJECT_GET_CLASS_NUMBER(h_obj));
		duk__debug_getinfo_flags_key(thr, "class_name");
		duk_debug_write_hstring(thr, DUK_HOBJECT_GET_CLASS_STRING(heap, h_obj));
		duk__debug_getinfo_flags_key(thr, "prototype");
		if (h_proto != NULL) {
			duk_debug_write_hobject(thr, h_proto);
		} else {
			duk_debug_write_null(thr);
		}
		duk__debug_getinfo_flags_key(thr, "props");
		duk_debug_write_pointer(thr, (void *) DUK_HOBJECT_GET_PROPS(heap, h_obj));
		duk__debug_getinfo_prop_uint(thr, "e_size", (duk_uint_t) DUK_HOBJECT_GET_ESIZE(h_obj));
		duk__debug_getinfo_prop_uint(thr, "e_next", (duk_uint_t) DUK_HOBJECT_GET_ENEXT(h_obj));
		duk__debug_getinfo_prop_uint(thr, "a_size", (duk_uint_t) DUK_HOBJECT_GET_ASIZE(h_obj));
		duk__debug_getinfo_prop_uint(thr, "h_size", (duk_uint_t) DUK_HOBJECT_GET_HSIZE(h_obj));

		if (DUK_HOBJECT_IS_ARRAY(h_obj)) {
			duk_harray *h_arr;
			h_arr = (duk_harray *) h_obj;

			duk__debug_getinfo_prop_uint(thr, "length", (duk_uint_t) h_arr->length);
			duk__debug_getinfo_prop_bool(thr, "length_nonwritable", h_arr->length_nonwritable);
		}

		if (DUK_HOBJECT_IS_NATFUNC(h_obj)) {
			duk_hnatfunc *h_fun;
			h_fun = (duk_hnatfunc *) h_obj;

			duk__debug_getinfo_prop_int(thr, "nargs", h_fun->nargs);
			duk__debug_getinfo_prop_int(thr, "magic", h_fun->magic);
			duk__debug_getinfo_prop_bool(thr, "varargs", h_fun->magic == DUK_HNATFUNC_NARGS_VARARGS);
			/* Native function pointer may be different from a void pointer,
			 * and we serialize it from memory directly now (no byte swapping etc).
			 */
			duk__debug_getinfo_flags_key(thr, "funcptr");
			duk_debug_write_buffer(thr, (const char *) &h_fun->func, sizeof(h_fun->func));
		}

		if (DUK_HOBJECT_IS_COMPFUNC(h_obj)) {
			duk_hcompfunc *h_fun;
			duk_hbuffer *h_buf;
			duk_hobject *h_lexenv;
			duk_hobject *h_varenv;
			h_fun = (duk_hcompfunc *) h_obj;

			duk__debug_getinfo_prop_int(thr, "nregs", h_fun->nregs);
			duk__debug_getinfo_prop_int(thr, "nargs", h_fun->nargs);

			duk__debug_getinfo_flags_key(thr, "lex_env");
			h_lexenv = DUK_HCOMPFUNC_GET_LEXENV(thr->heap, h_fun);
			if (h_lexenv != NULL) {
				duk_debug_write_hobject(thr, h_lexenv);
			} else {
				duk_debug_write_null(thr);
			}
			duk__debug_getinfo_flags_key(thr, "var_env");
			h_varenv = DUK_HCOMPFUNC_GET_VARENV(thr->heap, h_fun);
			if (h_varenv != NULL) {
				duk_debug_write_hobject(thr, h_varenv);
			} else {
				duk_debug_write_null(thr);
			}

			duk__debug_getinfo_prop_uint(thr, "start_line", h_fun->start_line);
			duk__debug_getinfo_prop_uint(thr, "end_line", h_fun->end_line);
			h_buf = (duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA(thr->heap, h_fun);
			if (h_buf != NULL) {
				duk__debug_getinfo_flags_key(thr, "data");
				duk_debug_write_heapptr(thr, (duk_heaphdr *) h_buf);
			}
		}

		if (DUK_HOBJECT_IS_BOUNDFUNC(h_obj)) {
			duk_hboundfunc *h_bfun;
			h_bfun = (duk_hboundfunc *) (void *) h_obj;

			duk__debug_getinfo_flags_key(thr, "target");
			duk_debug_write_tval(thr, &h_bfun->target);
			duk__debug_getinfo_flags_key(thr, "this_binding");
			duk_debug_write_tval(thr, &h_bfun->this_binding);
			duk__debug_getinfo_flags_key(thr, "nargs");
			duk_debug_write_int(thr, h_bfun->nargs);
			/* h_bfun->args not exposed now */
		}

		if (DUK_HOBJECT_IS_THREAD(h_obj)) {
			/* XXX: Currently no inspection of threads, e.g. value stack, call
			 * stack, catch stack, etc.
			 */
			duk_hthread *h_thr;
			h_thr = (duk_hthread *) h_obj;
			DUK_UNREF(h_thr);
		}

		if (DUK_HOBJECT_IS_DECENV(h_obj)) {
			duk_hdecenv *h_env;
			h_env = (duk_hdecenv *) h_obj;

			duk__debug_getinfo_flags_key(thr, "thread");
			duk_debug_write_heapptr(thr, (duk_heaphdr *) (h_env->thread));
			duk__debug_getinfo_flags_key(thr, "varmap");
			duk_debug_write_heapptr(thr, (duk_heaphdr *) (h_env->varmap));
			duk__debug_getinfo_prop_uint(thr, "regbase", (duk_uint_t) h_env->regbase_byteoff);
		}

		if (DUK_HOBJECT_IS_OBJENV(h_obj)) {
			duk_hobjenv *h_env;
			h_env = (duk_hobjenv *) h_obj;

			duk__debug_getinfo_flags_key(thr, "target");
			duk_debug_write_heapptr(thr, (duk_heaphdr *) (h_env->target));
			duk__debug_getinfo_prop_bool(thr, "has_this", h_env->has_this);
		}

#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
		if (DUK_HOBJECT_IS_BUFOBJ(h_obj)) {
			duk_hbufobj *h_bufobj;
			h_bufobj = (duk_hbufobj *) h_obj;

			duk__debug_getinfo_prop_uint(thr, "slice_offset", h_bufobj->offset);
			duk__debug_getinfo_prop_uint(thr, "slice_length", h_bufobj->length);
			duk__debug_getinfo_prop_uint(thr, "elem_shift", (duk_uint_t) h_bufobj->shift);
			duk__debug_getinfo_prop_uint(thr, "elem_type", (duk_uint_t) h_bufobj->elem_type);
			duk__debug_getinfo_prop_bool(thr, "is_typedarray", (duk_uint_t) h_bufobj->is_typedarray);
			if (h_bufobj->buf != NULL) {
				duk__debug_getinfo_flags_key(thr, "buffer");
				duk_debug_write_heapptr(thr, (duk_heaphdr *) h_bufobj->buf);
			}
		}
#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
		break;
	}
	case DUK_HTYPE_BUFFER: {
		duk_hbuffer *h_buf;

		h_buf = (duk_hbuffer *) h;
		duk__debug_getinfo_bitmask(thr,
		                           duk__debug_getinfo_hbuffer_keys,
		                           duk__debug_getinfo_hbuffer_masks,
		                           DUK_HEAPHDR_GET_FLAGS_RAW(h));
		duk__debug_getinfo_prop_uint(thr, "size", (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_buf));
		duk__debug_getinfo_flags_key(thr, "dataptr");
		duk_debug_write_pointer(thr, (void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_buf));
		duk__debug_getinfo_flags_key(thr, "data");
		duk_debug_write_hbuffer(thr, h_buf);  /* tolerates NULL h_buf */
		break;
	}
	default: {
		/* Since we already started writing the reply, just emit nothing. */
		DUK_D(DUK_DPRINT("inspect target pointer has invalid heaphdr type"));
	}
	}

	duk_debug_write_eom(thr);
}

DUK_LOCAL void duk__debug_handle_get_obj_prop_desc(duk_hthread *thr, duk_heap *heap) {
	duk_heaphdr *h;
	duk_hobject *h_obj;
	duk_hstring *h_key;
	duk_propdesc desc;

	DUK_D(DUK_DPRINT("debug command GetObjPropDesc"));
	DUK_UNREF(heap);

	h = duk_debug_read_any_ptr(thr);
	if (!h) {
		duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid target");
		return;
	}
	h_key = duk_debug_read_hstring(thr);
	if (h == NULL || DUK_HEAPHDR_GET_TYPE(h) != DUK_HTYPE_OBJECT || h_key == NULL) {
		goto fail_args;
	}
	h_obj = (duk_hobject *) h;

	if (duk_hobject_get_own_propdesc(thr, h_obj, h_key, &desc, 0 /*flags*/)) {
		duk_int_t virtual_idx;
		duk_bool_t rc;

		/* To use the shared helper need the virtual index. */
		DUK_ASSERT(desc.e_idx >= 0 || desc.a_idx >= 0);
		virtual_idx = (desc.a_idx >= 0 ? desc.a_idx :
		               (duk_int_t) DUK_HOBJECT_GET_ASIZE(h_obj) + desc.e_idx);

		duk_debug_write_reply(thr);
		rc = duk__debug_getprop_index(thr, heap, h_obj, (duk_uint_t) virtual_idx);
		DUK_ASSERT(rc == 1);
		DUK_UNREF(rc);
		duk_debug_write_eom(thr);
	} else {
		duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "not found");
	}
	return;

 fail_args:
	duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid args");
}

DUK_LOCAL void duk__debug_handle_get_obj_prop_desc_range(duk_hthread *thr, duk_heap *heap) {
	duk_heaphdr *h;
	duk_hobject *h_obj;
	duk_uint_t idx, idx_start, idx_end;

	DUK_D(DUK_DPRINT("debug command GetObjPropDescRange"));
	DUK_UNREF(heap);

	h = duk_debug_read_any_ptr(thr);
	idx_start = (duk_uint_t) duk_debug_read_int(thr);
	idx_end = (duk_uint_t) duk_debug_read_int(thr);
	if (h == NULL || DUK_HEAPHDR_GET_TYPE(h) != DUK_HTYPE_OBJECT) {
		goto fail_args;
	}
	h_obj = (duk_hobject *) h;

	/* The index range space is conceptually the array part followed by the
	 * entry part.  Unlike normal enumeration all slots are exposed here as
	 * is and return 'unused' if the slots are not in active use.  In particular
	 * the array part is included for the full a_size regardless of what the
	 * array .length is.
	 */

	duk_debug_write_reply(thr);
	for (idx = idx_start; idx < idx_end; idx++) {
		if (!duk__debug_getprop_index(thr, heap, h_obj, idx)) {
			break;
		}
	}
	duk_debug_write_eom(thr);
	return;

 fail_args:
	duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid args");
}

#endif  /* DUK_USE_DEBUGGER_INSPECT */

/*
 *  Process incoming debug requests
 *
 *  Individual request handlers can push temporaries on the value stack and
 *  rely on duk__debug_process_message() to restore the value stack top
 *  automatically.
 */

/* Process one debug message.  Automatically restore value stack top to its
 * entry value, so that individual message handlers don't need exact value
 * stack handling which is convenient.
 */
DUK_LOCAL void duk__debug_process_message(duk_hthread *thr) {
	duk_heap *heap;
	duk_uint8_t x;
	duk_int32_t cmd;
	duk_idx_t entry_top;

	DUK_ASSERT(thr != NULL);
	heap = thr->heap;
	DUK_ASSERT(heap != NULL);

	entry_top = duk_get_top(thr);

	x = duk_debug_read_byte(thr);
	switch (x) {
	case DUK_DBG_IB_REQUEST: {
		cmd = duk_debug_read_int(thr);
		switch (cmd) {
		case DUK_DBG_CMD_BASICINFO: {
			duk__debug_handle_basic_info(thr, heap);
			break;
		}
		case DUK_DBG_CMD_TRIGGERSTATUS: {
			duk__debug_handle_trigger_status(thr, heap);
			break;
		}
		case DUK_DBG_CMD_PAUSE: {
			duk__debug_handle_pause(thr, heap);
			break;
		}
		case DUK_DBG_CMD_RESUME: {
			duk__debug_handle_resume(thr, heap);
			break;
		}
		case DUK_DBG_CMD_STEPINTO:
		case DUK_DBG_CMD_STEPOVER:
		case DUK_DBG_CMD_STEPOUT: {
			duk__debug_handle_step(thr, heap, cmd);
			break;
		}
		case DUK_DBG_CMD_LISTBREAK: {
			duk__debug_handle_list_break(thr, heap);
			break;
		}
		case DUK_DBG_CMD_ADDBREAK: {
			duk__debug_handle_add_break(thr, heap);
			break;
		}
		case DUK_DBG_CMD_DELBREAK: {
			duk__debug_handle_del_break(thr, heap);
			break;
		}
		case DUK_DBG_CMD_GETVAR: {
			duk__debug_handle_get_var(thr, heap);
			break;
		}
		case DUK_DBG_CMD_PUTVAR: {
			duk__debug_handle_put_var(thr, heap);
			break;
		}
		case DUK_DBG_CMD_GETCALLSTACK: {
			duk__debug_handle_get_call_stack(thr, heap);
			break;
		}
		case DUK_DBG_CMD_GETLOCALS: {
			duk__debug_handle_get_locals(thr, heap);
			break;
		}
		case DUK_DBG_CMD_EVAL: {
			duk__debug_handle_eval(thr, heap);
			break;
		}
		case DUK_DBG_CMD_DETACH: {
			/* The actual detached_cb call is postponed to message loop so
			 * we don't need any special precautions here (just skip to EOM
			 * on the already closed connection).
			 */
			duk__debug_handle_detach(thr, heap);
			break;
		}
#if defined(DUK_USE_DEBUGGER_DUMPHEAP)
		case DUK_DBG_CMD_DUMPHEAP: {
			duk__debug_handle_dump_heap(thr, heap);
			break;
		}
#endif  /* DUK_USE_DEBUGGER_DUMPHEAP */
		case DUK_DBG_CMD_GETBYTECODE: {
			duk__debug_handle_get_bytecode(thr, heap);
			break;
		}
		case DUK_DBG_CMD_APPREQUEST: {
			duk__debug_handle_apprequest(thr, heap);
			break;
		}
#if defined(DUK_USE_DEBUGGER_INSPECT)
		case DUK_DBG_CMD_GETHEAPOBJINFO: {
			duk__debug_handle_get_heap_obj_info(thr, heap);
			break;
		}
		case DUK_DBG_CMD_GETOBJPROPDESC: {
			duk__debug_handle_get_obj_prop_desc(thr, heap);
			break;
		}
		case DUK_DBG_CMD_GETOBJPROPDESCRANGE: {
			duk__debug_handle_get_obj_prop_desc_range(thr, heap);
			break;
		}
#endif  /* DUK_USE_DEBUGGER_INSPECT */
		default: {
			DUK_D(DUK_DPRINT("debug command unsupported: %d", (int) cmd));
			duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNSUPPORTED, "unsupported command");
		}
		}  /* switch cmd */
		break;
	}
	case DUK_DBG_IB_REPLY: {
		DUK_D(DUK_DPRINT("debug reply, skipping"));
		break;
	}
	case DUK_DBG_IB_ERROR: {
		DUK_D(DUK_DPRINT("debug error, skipping"));
		break;
	}
	case DUK_DBG_IB_NOTIFY: {
		DUK_D(DUK_DPRINT("debug notify, skipping"));
		break;
	}
	default: {
		DUK_D(DUK_DPRINT("invalid initial byte, drop connection: %d", (int) x));
		goto fail;
	}
	}  /* switch initial byte */

	DUK_ASSERT(duk_get_top(thr) >= entry_top);
	duk_set_top(thr, entry_top);
	duk__debug_skip_to_eom(thr);
	return;

 fail:
	DUK_ASSERT(duk_get_top(thr) >= entry_top);
	duk_set_top(thr, entry_top);
	DUK__SET_CONN_BROKEN(thr, 1);
	return;
}

DUK_LOCAL void duk__check_resend_status(duk_hthread *thr) {
	if (thr->heap->dbg_read_cb != NULL && thr->heap->dbg_state_dirty) {
		duk_debug_send_status(thr);
		thr->heap->dbg_state_dirty = 0;
	}
}

DUK_INTERNAL duk_bool_t duk_debug_process_messages(duk_hthread *thr, duk_bool_t no_block) {
#if defined(DUK_USE_ASSERTIONS)
	duk_idx_t entry_top;
#endif
	duk_bool_t retval = 0;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(thr->heap != NULL);
#if defined(DUK_USE_ASSERTIONS)
	entry_top = duk_get_top(thr);
#endif

	DUK_D(DUK_DPRINT("process debug messages: read_cb=%s, no_block=%ld, detaching=%ld, processing=%ld",
	                 thr->heap->dbg_read_cb ? "not NULL" : "NULL", (long) no_block,
	                 (long) thr->heap->dbg_detaching, (long) thr->heap->dbg_processing));
	DUK_DD(DUK_DDPRINT("top at entry: %ld", (long) duk_get_top(thr)));

	/* thr->heap->dbg_detaching may be != 0 if a debugger write outside
	 * the message loop caused a transport error and detach1() to run.
	 */
	DUK_ASSERT(thr->heap->dbg_detaching == 0 || thr->heap->dbg_detaching == 1);
	DUK_ASSERT(thr->heap->dbg_processing == 0);
	thr->heap->dbg_processing = 1;

	/* Ensure dirty state causes a Status even if never process any
	 * messages.  This is expected by the bytecode executor when in
	 * the running state.
	 */
	duk__check_resend_status(thr);

	for (;;) {
		/* Process messages until we're no longer paused or we peek
		 * and see there's nothing to read right now.
		 */
		DUK_DD(DUK_DDPRINT("top at loop top: %ld", (long) duk_get_top(thr)));
		DUK_ASSERT(thr->heap->dbg_processing == 1);

		while (thr->heap->dbg_read_cb == NULL && thr->heap->dbg_detaching) {
			/* Detach is pending; can be triggered from outside the
			 * debugger loop (e.g. Status notify write error) or by
			 * previous message handling.  Call detached callback
			 * here, in a controlled state, to ensure a possible
			 * reattach inside the detached_cb is handled correctly.
			 *
			 * Recheck for detach in a while loop: an immediate
			 * reattach involves a call to duk_debugger_attach()
			 * which writes a debugger handshake line immediately
			 * inside the API call.  If the transport write fails
			 * for that handshake, we can immediately end up in a
			 * "transport broken, detaching" case several times here.
			 * Loop back until we're either cleanly attached or
			 * fully detached.
			 *
			 * NOTE: Reset dbg_processing = 1 forcibly, in case we
			 * re-attached; duk_debugger_attach() sets dbg_processing
			 * to 0 at the moment.
			 */

			DUK_D(DUK_DPRINT("detach pending (dbg_read_cb == NULL, dbg_detaching != 0), call detach2"));

			duk__debug_do_detach2(thr->heap);
			thr->heap->dbg_processing = 1;  /* may be set to 0 by duk_debugger_attach() inside callback */

			DUK_D(DUK_DPRINT("after detach2 (and possible reattach): dbg_read_cb=%s, dbg_detaching=%ld",
			                 thr->heap->dbg_read_cb ? "not NULL" : "NULL", (long) thr->heap->dbg_detaching));
		}
		DUK_ASSERT(thr->heap->dbg_detaching == 0);  /* true even with reattach */
		DUK_ASSERT(thr->heap->dbg_processing == 1);  /* even after a detach and possible reattach */

		if (thr->heap->dbg_read_cb == NULL) {
			DUK_D(DUK_DPRINT("debug connection broken (and not detaching), stop processing messages"));
			break;
		}

		if (!DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap) || no_block) {
			if (!duk_debug_read_peek(thr)) {
				/* Note: peek cannot currently trigger a detach
				 * so the dbg_detaching == 0 assert outside the
				 * loop is correct.
				 */
				DUK_D(DUK_DPRINT("processing debug message, peek indicated no data, stop processing messages"));
				break;
			}
			DUK_D(DUK_DPRINT("processing debug message, peek indicated there is data, handle it"));
		} else {
			DUK_D(DUK_DPRINT("paused, process debug message, blocking if necessary"));
		}

		duk__check_resend_status(thr);
		duk__debug_process_message(thr);
		duk__check_resend_status(thr);

		retval = 1;  /* processed one or more messages */
	}

	DUK_ASSERT(thr->heap->dbg_detaching == 0);
	DUK_ASSERT(thr->heap->dbg_processing == 1);
	thr->heap->dbg_processing = 0;

	/* As an initial implementation, read flush after exiting the message
	 * loop.  If transport is broken, this is a no-op (with debug logs).
	 */
	duk_debug_read_flush(thr);  /* this cannot initiate a detach */
	DUK_ASSERT(thr->heap->dbg_detaching == 0);

	DUK_DD(DUK_DDPRINT("top at exit: %ld", (long) duk_get_top(thr)));

#if defined(DUK_USE_ASSERTIONS)
	/* Easy to get wrong, so assert for it. */
	DUK_ASSERT(entry_top == duk_get_top(thr));
#endif

	return retval;
}

/*
 *  Halt execution helper
 */

/* Halt execution and enter a debugger message loop until execution is resumed
 * by the client.  PC for the current activation may be temporarily decremented
 * so that the "current" instruction will be shown by the client.  This helper
 * is callable from anywhere, also outside bytecode executor.
 */

DUK_INTERNAL void duk_debug_halt_execution(duk_hthread *thr, duk_bool_t use_prev_pc) {
	duk_activation *act;
	duk_hcompfunc *fun;
	duk_instr_t *old_pc = NULL;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(thr->heap != NULL);
	DUK_ASSERT(duk_debug_is_attached(thr->heap));
	DUK_ASSERT(thr->heap->dbg_processing == 0);
	DUK_ASSERT(!duk_debug_is_paused(thr->heap));

	duk_debug_set_paused(thr->heap);

	act = thr->callstack_curr;

	/* NOTE: act may be NULL if an error is thrown outside of any activation,
	 * which may happen in the case of, e.g. syntax errors.
	 */

	/* Decrement PC if that was requested, this requires a PC sync. */
	if (act != NULL) {
		duk_hthread_sync_currpc(thr);
		old_pc = act->curr_pc;
		fun = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);

		/* Short circuit if is safe: if act->curr_pc != NULL, 'fun' is
		 * guaranteed to be a non-NULL ECMAScript function.
		 */
		DUK_ASSERT(act->curr_pc == NULL ||
		           (fun != NULL && DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) fun)));
		if (use_prev_pc &&
		    act->curr_pc != NULL &&
		    act->curr_pc > DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, fun)) {
			act->curr_pc--;
		}
	}

	/* Process debug messages until we are no longer paused. */

	/* NOTE: This is a bit fragile.  It's important to ensure that
	 * duk_debug_process_messages() never throws an error or
	 * act->curr_pc will never be reset.
	 */

	thr->heap->dbg_state_dirty = 1;
	while (DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap)) {
		DUK_ASSERT(duk_debug_is_attached(thr->heap));
		DUK_ASSERT(thr->heap->dbg_processing == 0);
		duk_debug_process_messages(thr, 0 /*no_block*/);
	}

	/* XXX: Decrementing and restoring act->curr_pc works now, but if the
	 * debugger message loop gains the ability to adjust the current PC
	 * (e.g. a forced jump) restoring the PC here will break.  Another
	 * approach would be to use a state flag for the "decrement 1 from
	 * topmost activation's PC" and take it into account whenever dealing
	 * with PC values.
	 */
	if (act != NULL) {
		act->curr_pc = old_pc;  /* restore PC */
	}
}

/*
 *  Breakpoint management
 */

DUK_INTERNAL duk_small_int_t duk_debug_add_breakpoint(duk_hthread *thr, duk_hstring *filename, duk_uint32_t line) {
	duk_heap *heap;
	duk_breakpoint *b;

	/* Caller must trigger recomputation of active breakpoint list.  To
	 * ensure stale values are not used if that doesn't happen, clear the
	 * active breakpoint list here.
	 */

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(filename != NULL);
	heap = thr->heap;
	DUK_ASSERT(heap != NULL);

	if (heap->dbg_breakpoint_count >= DUK_HEAP_MAX_BREAKPOINTS) {
		DUK_D(DUK_DPRINT("failed to add breakpoint for %O:%ld, all breakpoint slots used",
		                 (duk_heaphdr *) filename, (long) line));
		return -1;
	}
	heap->dbg_breakpoints_active[0] = (duk_breakpoint *) NULL;
	b = heap->dbg_breakpoints + (heap->dbg_breakpoint_count++);
	b->filename = filename;
	b->line = line;
	DUK_HSTRING_INCREF(thr, filename);

	return (duk_small_int_t) (heap->dbg_breakpoint_count - 1);  /* index */
}

DUK_INTERNAL duk_bool_t duk_debug_remove_breakpoint(duk_hthread *thr, duk_small_uint_t breakpoint_index) {
	duk_heap *heap;
	duk_hstring *h;
	duk_breakpoint *b;
	duk_size_t move_size;

	/* Caller must trigger recomputation of active breakpoint list.  To
	 * ensure stale values are not used if that doesn't happen, clear the
	 * active breakpoint list here.
	 */

	DUK_ASSERT(thr != NULL);
	heap = thr->heap;
	DUK_ASSERT(heap != NULL);
	DUK_ASSERT(duk_debug_is_attached(thr->heap));
	DUK_ASSERT_DISABLE(breakpoint_index >= 0);  /* unsigned */

	if (breakpoint_index >= heap->dbg_breakpoint_count) {
		DUK_D(DUK_DPRINT("invalid breakpoint index: %ld", (long) breakpoint_index));
		return 0;
	}
	b = heap->dbg_breakpoints + breakpoint_index;

	h = b->filename;
	DUK_ASSERT(h != NULL);

	move_size = sizeof(duk_breakpoint) * (heap->dbg_breakpoint_count - breakpoint_index - 1);
	duk_memmove((void *) b,
	            (const void *) (b + 1),
	            (size_t) move_size);

	heap->dbg_breakpoint_count--;
	heap->dbg_breakpoints_active[0] = (duk_breakpoint *) NULL;

	DUK_HSTRING_DECREF(thr, h);  /* side effects */
	DUK_UNREF(h);  /* w/o refcounting */

	/* Breakpoint entries above the used area are left as garbage. */

	return 1;
}

/*
 *  Misc state management
 */

DUK_INTERNAL duk_bool_t duk_debug_is_attached(duk_heap *heap) {
	return (heap->dbg_read_cb != NULL);
}

DUK_INTERNAL duk_bool_t duk_debug_is_paused(duk_heap *heap) {
	return (DUK_HEAP_HAS_DEBUGGER_PAUSED(heap) != 0);
}

DUK_INTERNAL void duk_debug_set_paused(duk_heap *heap) {
	if (duk_debug_is_paused(heap)) {
		DUK_D(DUK_DPRINT("trying to set paused state when already paused, ignoring"));
	} else {
		DUK_HEAP_SET_DEBUGGER_PAUSED(heap);
		heap->dbg_state_dirty = 1;
		duk_debug_clear_pause_state(heap);
		DUK_ASSERT(heap->ms_running == 0);  /* debugger can't be triggered within mark-and-sweep */
		heap->ms_running = 2;  /* prevent mark-and-sweep, prevent refzero queueing */
		heap->ms_prevent_count++;
		DUK_ASSERT(heap->ms_prevent_count != 0);  /* Wrap. */
		DUK_ASSERT(heap->heap_thread != NULL);
	}
}

DUK_INTERNAL void duk_debug_clear_paused(duk_heap *heap) {
	if (duk_debug_is_paused(heap)) {
		DUK_HEAP_CLEAR_DEBUGGER_PAUSED(heap);
		heap->dbg_state_dirty = 1;
		duk_debug_clear_pause_state(heap);
		DUK_ASSERT(heap->ms_running == 2);
		DUK_ASSERT(heap->ms_prevent_count > 0);
		heap->ms_prevent_count--;
		heap->ms_running = 0;
		DUK_ASSERT(heap->heap_thread != NULL);
	} else {
		DUK_D(DUK_DPRINT("trying to clear paused state when not paused, ignoring"));
	}
}

DUK_INTERNAL void duk_debug_clear_pause_state(duk_heap *heap) {
	heap->dbg_pause_flags = 0;
	heap->dbg_pause_act = NULL;
	heap->dbg_pause_startline = 0;
}

#else  /* DUK_USE_DEBUGGER_SUPPORT */

/* No debugger support. */

#endif  /* DUK_USE_DEBUGGER_SUPPORT */

/* automatic undefs */
#undef DUK__DBG_TPORT_ENTER
#undef DUK__DBG_TPORT_EXIT
#undef DUK__SET_CONN_BROKEN
#line 1 "duk_error_augment.c"
/*
 *  Augmenting errors at their creation site and their throw site.
 *
 *  When errors are created, traceback data is added by built-in code
 *  and a user error handler (if defined) can process or replace the
 *  error.  Similarly, when errors are thrown, a user error handler
 *  (if defined) can process or replace the error.
 *
 *  Augmentation and other processing at error creation time is nice
 *  because an error is only created once, but it may be thrown and
 *  rethrown multiple times.  User error handler registered for processing
 *  an error at its throw site must be careful to handle rethrowing in
 *  a useful manner.
 *
 *  Error augmentation may throw an internal error (e.g. alloc error).
 *
 *  ECMAScript allows throwing any values, so all values cannot be
 *  augmented.  Currently, the built-in augmentation at error creation
 *  only augments error values which are Error instances (= have the
 *  built-in Error.prototype in their prototype chain) and are also
 *  extensible.  User error handlers have no limitations in this respect.
 */

/* #include duk_internal.h -> already included */

/*
 *  Helper for calling a user error handler.
 *
 *  'thr' must be the currently active thread; the error handler is called
 *  in its context.  The valstack of 'thr' must have the error value on
 *  top, and will be replaced by another error value based on the return
 *  value of the error handler.
 *
 *  The helper calls duk_handle_call() recursively in protected mode.
 *  Before that call happens, no longjmps should happen; as a consequence,
 *  we must assume that the valstack contains enough temporary space for
 *  arguments and such.
 *
 *  While the error handler runs, any errors thrown will not trigger a
 *  recursive error handler call (this is implemented using a heap level
 *  flag which will "follow" through any coroutines resumed inside the
 *  error handler).  If the error handler is not callable or throws an
 *  error, the resulting error replaces the original error (for Duktape
 *  internal errors, duk_error_throw.c further substitutes this error with
 *  a DoubleError which is not ideal).  This would be easy to change and
 *  even signal to the caller.
 *
 *  The user error handler is stored in 'Duktape.errCreate' or
 *  'Duktape.errThrow' depending on whether we're augmenting the error at
 *  creation or throw time.  There are several alternatives to this approach,
 *  see doc/error-objects.rst for discussion.
 *
 *  Note: since further longjmp()s may occur while calling the error handler
 *  (for many reasons, e.g. a labeled 'break' inside the handler), the
 *  caller can make no assumptions on the thr->heap->lj state after the
 *  call (this affects especially duk_error_throw.c).  This is not an issue
 *  as long as the caller writes to the lj state only after the error handler
 *  finishes.
 */

#if defined(DUK_USE_ERRTHROW) || defined(DUK_USE_ERRCREATE)
DUK_LOCAL void duk__err_augment_user(duk_hthread *thr, duk_small_uint_t stridx_cb) {
	duk_tval *tv_hnd;
	duk_int_t rc;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(thr->heap != NULL);
	DUK_ASSERT_STRIDX_VALID(stridx_cb);

	if (thr->heap->augmenting_error) {
		DUK_D(DUK_DPRINT("recursive call to error augmentation, ignore"));
		return;
	}

	/*
	 *  Check whether or not we have an error handler.
	 *
	 *  We must be careful of not triggering an error when looking up the
	 *  property.  For instance, if the property is a getter, we don't want
	 *  to call it, only plain values are allowed.  The value, if it exists,
	 *  is not checked.  If the value is not a function, a TypeError happens
	 *  when it is called and that error replaces the original one.
	 */

	DUK_ASSERT_VALSTACK_SPACE(thr, 4);  /* 3 entries actually needed below */

	/* [ ... errval ] */

	if (thr->builtins[DUK_BIDX_DUKTAPE] == NULL) {
		/* When creating built-ins, some of the built-ins may not be set
		 * and we want to tolerate that when throwing errors.
		 */
		DUK_DD(DUK_DDPRINT("error occurred when DUK_BIDX_DUKTAPE is NULL, ignoring"));
		return;
	}
	tv_hnd = duk_hobject_find_entry_tval_ptr_stridx(thr->heap,
	                                                thr->builtins[DUK_BIDX_DUKTAPE],
	                                                stridx_cb);
	if (tv_hnd == NULL) {
		DUK_DD(DUK_DDPRINT("error handler does not exist or is not a plain value: %!T",
		                   (duk_tval *) tv_hnd));
		return;
	}
	DUK_DDD(DUK_DDDPRINT("error handler dump (callability not checked): %!T",
	                     (duk_tval *) tv_hnd));
	duk_push_tval(thr, tv_hnd);

	/* [ ... errval errhandler ] */

	duk_insert(thr, -2);  /* -> [ ... errhandler errval ] */
	duk_push_undefined(thr);
	duk_insert(thr, -2);  /* -> [ ... errhandler undefined(= this) errval ] */

	/* [ ... errhandler undefined errval ] */

	/*
	 *  heap->augmenting_error prevents recursive re-entry and also causes
	 *  call handling to use a larger (but not unbounded) call stack limit
	 *  for the duration of error augmentation.
	 *
	 *  We ignore errors now: a success return and an error value both
	 *  replace the original error value.  (This would be easy to change.)
	 */

	DUK_ASSERT(thr->heap->augmenting_error == 0);
	thr->heap->augmenting_error = 1;

	rc = duk_pcall_method(thr, 1);
	DUK_UNREF(rc);  /* no need to check now: both success and error are OK */

	DUK_ASSERT(thr->heap->augmenting_error == 1);
	thr->heap->augmenting_error = 0;

	/* [ ... errval ] */
}
#endif  /* DUK_USE_ERRTHROW || DUK_USE_ERRCREATE */

/*
 *  Add ._Tracedata to an error on the stack top.
 */

#if defined(DUK_USE_TRACEBACKS)
DUK_LOCAL void duk__add_traceback(duk_hthread *thr, duk_hthread *thr_callstack, const char *c_filename, duk_int_t c_line, duk_small_uint_t flags) {
	duk_activation *act;
	duk_int_t depth;
	duk_int_t arr_size;
	duk_tval *tv;
	duk_hstring *s;
	duk_uint32_t u32;
	duk_double_t d;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(thr_callstack != NULL);

	/* [ ... error ] */

	/*
	 *  The traceback format is pretty arcane in an attempt to keep it compact
	 *  and cheap to create.  It may change arbitrarily from version to version.
	 *  It should be decoded/accessed through version specific accessors only.
	 *
	 *  See doc/error-objects.rst.
	 */

	DUK_DDD(DUK_DDDPRINT("adding traceback to object: %!T",
	                     (duk_tval *) duk_get_tval(thr, -1)));

	/* Preallocate array to correct size, so that we can just write out
	 * the _Tracedata values into the array part.
	 */
	act = thr->callstack_curr;
	depth = DUK_USE_TRACEBACK_DEPTH;
	DUK_ASSERT(thr_callstack->callstack_top <= DUK_INT_MAX);  /* callstack limits */
	if (depth > (duk_int_t) thr_callstack->callstack_top) {
		depth = (duk_int_t) thr_callstack->callstack_top;
	}
	if (depth > 0) {
		if (flags & DUK_AUGMENT_FLAG_SKIP_ONE) {
			DUK_ASSERT(act != NULL);
			act = act->parent;
			depth--;
		}
	}
	arr_size = depth * 2;
	if (thr->compile_ctx != NULL && thr->compile_ctx->h_filename != NULL) {
		arr_size += 2;
	}
	if (c_filename) {
		/* We need the C filename to be interned before getting the
		 * array part pointer to avoid any GC interference while the
		 * array part is populated.
		 */
		duk_push_string(thr, c_filename);
		arr_size += 2;
	}

	/* XXX: Uninitialized would be OK.  Maybe add internal primitive to
	 * push bare duk_harray with size?
	 */
	DUK_D(DUK_DPRINT("preallocated _Tracedata to %ld items", (long) arr_size));
	tv = duk_push_harray_with_size_outptr(thr, (duk_uint32_t) arr_size);
	duk_clear_prototype(thr, -1);
	DUK_ASSERT(duk_is_bare_object(thr, -1));
	DUK_ASSERT(arr_size == 0 || tv != NULL);

	/* Compiler SyntaxErrors (and other errors) come first, and are
	 * blamed by default (not flagged "noblame").
	 */
	if (thr->compile_ctx != NULL && thr->compile_ctx->h_filename != NULL) {
		s = thr->compile_ctx->h_filename;
		DUK_TVAL_SET_STRING(tv, s);
		DUK_HSTRING_INCREF(thr, s);
		tv++;

		u32 = (duk_uint32_t) thr->compile_ctx->curr_token.start_line;  /* (flags<<32) + (line), flags = 0 */
		DUK_TVAL_SET_U32(tv, u32);
		tv++;
	}

	/* Filename/line from C macros (__FILE__, __LINE__) are added as an
	 * entry with a special format: (string, number).  The number contains
	 * the line and flags.
	 */

	/* [ ... error c_filename? arr ] */

	if (c_filename) {
		DUK_ASSERT(DUK_TVAL_IS_STRING(thr->valstack_top - 2));
		s = DUK_TVAL_GET_STRING(thr->valstack_top - 2);  /* interned c_filename */
		DUK_ASSERT(s != NULL);
		DUK_TVAL_SET_STRING(tv, s);
		DUK_HSTRING_INCREF(thr, s);
		tv++;

		d = ((flags & DUK_AUGMENT_FLAG_NOBLAME_FILELINE) ? ((duk_double_t) DUK_TB_FLAG_NOBLAME_FILELINE) * DUK_DOUBLE_2TO32 : 0.0) +
		    (duk_double_t) c_line;
		DUK_TVAL_SET_DOUBLE(tv, d);
		tv++;
	}

	/* Traceback depth doesn't take into account the filename/line
	 * special handling above (intentional).
	 */
	for (; depth-- > 0; act = act->parent) {
		duk_uint32_t pc;
		duk_tval *tv_src;

		/* [... arr] */

		DUK_ASSERT(act != NULL);  /* depth check above, assumes book-keeping is correct */
		DUK_ASSERT_DISABLE(act->pc >= 0);  /* unsigned */

		/* Add function object. */
		tv_src = &act->tv_func;  /* object (function) or lightfunc */
		DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv_src) || DUK_TVAL_IS_LIGHTFUNC(tv_src));
		DUK_TVAL_SET_TVAL(tv, tv_src);
		DUK_TVAL_INCREF(thr, tv);
		tv++;

		/* Add a number containing: pc, activation flags.
		 *
		 * PC points to next instruction, find offending PC.  Note that
		 * PC == 0 for native code.
		 */
		pc = (duk_uint32_t) duk_hthread_get_act_prev_pc(thr_callstack, act);
		DUK_ASSERT_DISABLE(pc >= 0);  /* unsigned */
		DUK_ASSERT((duk_double_t) pc < DUK_DOUBLE_2TO32);  /* assume PC is at most 32 bits and non-negative */
		d = ((duk_double_t) act->flags) * DUK_DOUBLE_2TO32 + (duk_double_t) pc;
		DUK_TVAL_SET_DOUBLE(tv, d);
		tv++;
	}

#if defined(DUK_USE_ASSERTIONS)
	{
		duk_harray *a;
		a = (duk_harray *) duk_known_hobject(thr, -1);
		DUK_ASSERT(a != NULL);
		DUK_ASSERT((duk_uint32_t) (tv - DUK_HOBJECT_A_GET_BASE(thr->heap, (duk_hobject *) a)) == a->length);
		DUK_ASSERT(a->length == (duk_uint32_t) arr_size);
		DUK_ASSERT(duk_is_bare_object(thr, -1));
	}
#endif

	/* [ ... error c_filename? arr ] */

	if (c_filename) {
		duk_remove_m2(thr);
	}

	/* [ ... error arr ] */

	duk_xdef_prop_stridx_short_wec(thr, -2, DUK_STRIDX_INT_TRACEDATA);  /* -> [ ... error ] */
}
#endif  /* DUK_USE_TRACEBACKS */

/*
 *  Add .fileName and .lineNumber to an error on the stack top.
 */

#if defined(DUK_USE_AUGMENT_ERROR_CREATE) && !defined(DUK_USE_TRACEBACKS)
DUK_LOCAL void duk__add_fileline(duk_hthread *thr, duk_hthread *thr_callstack, const char *c_filename, duk_int_t c_line, duk_small_uint_t flags) {
#if defined(DUK_USE_ASSERTIONS)
	duk_int_t entry_top;
#endif

#if defined(DUK_USE_ASSERTIONS)
	entry_top = duk_get_top(thr);
#endif

	/*
	 *  If tracebacks are disabled, 'fileName' and 'lineNumber' are added
	 *  as plain own properties.  Since Error.prototype has accessors of
	 *  the same name, we need to define own properties directly (cannot
	 *  just use e.g. duk_put_prop_stridx).  Existing properties are not
	 *  overwritten in case they already exist.
	 */

	if (thr->compile_ctx != NULL && thr->compile_ctx->h_filename != NULL) {
		/* Compiler SyntaxError (or other error) gets the primary blame.
		 * Currently no flag to prevent blaming.
		 */
		duk_push_uint(thr, (duk_uint_t) thr->compile_ctx->curr_token.start_line);
		duk_push_hstring(thr, thr->compile_ctx->h_filename);
	} else if (c_filename && (flags & DUK_AUGMENT_FLAG_NOBLAME_FILELINE) == 0) {
		/* C call site gets blamed next, unless flagged not to do so.
		 * XXX: file/line is disabled in minimal builds, so disable this
		 * too when appropriate.
		 */
		duk_push_int(thr, c_line);
		duk_push_string(thr, c_filename);
	} else {
		/* Finally, blame the innermost callstack entry which has a
		 * .fileName property.
		 */
		duk_small_uint_t depth;
		duk_uint32_t ecma_line;
		duk_activation *act;

		DUK_ASSERT(thr_callstack->callstack_top <= DUK_INT_MAX);  /* callstack limits */
		depth = DUK_USE_TRACEBACK_DEPTH;
		if (depth > thr_callstack->callstack_top) {
			depth = thr_callstack->callstack_top;
		}
		for (act = thr_callstack->callstack_curr; depth-- > 0; act = act->parent) {
			duk_hobject *func;
			duk_uint32_t pc;

			DUK_ASSERT(act != NULL);
			func = DUK_ACT_GET_FUNC(act);
			if (func == NULL) {
				/* Lightfunc, not blamed now. */
				continue;
			}

			/* PC points to next instruction, find offending PC,
			 * PC == 0 for native code.
			 */
			pc = duk_hthread_get_act_prev_pc(thr, act);  /* thr argument only used for thr->heap, so specific thread doesn't matter */
			DUK_UNREF(pc);
			DUK_ASSERT_DISABLE(pc >= 0);  /* unsigned */
			DUK_ASSERT((duk_double_t) pc < DUK_DOUBLE_2TO32);  /* assume PC is at most 32 bits and non-negative */

			duk_push_hobject(thr, func);

			/* [ ... error func ] */

			duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_FILE_NAME);
			if (!duk_is_string_notsymbol(thr, -1)) {
				duk_pop_2(thr);
				continue;
			}

			/* [ ... error func fileName ] */

			ecma_line = 0;
#if defined(DUK_USE_PC2LINE)
			if (DUK_HOBJECT_IS_COMPFUNC(func)) {
				ecma_line = duk_hobject_pc2line_query(thr, -2, (duk_uint_fast32_t) pc);
			} else {
				/* Native function, no relevant lineNumber. */
			}
#endif  /* DUK_USE_PC2LINE */
			duk_push_u32(thr, ecma_line);

			/* [ ... error func fileName lineNumber ] */

			duk_replace(thr, -3);

			/* [ ... error lineNumber fileName ] */
			goto define_props;
		}

		/* No activation matches, use undefined for both .fileName and
		 * .lineNumber (matches what we do with a _Tracedata based
		 * no-match lookup.
		 */
		duk_push_undefined(thr);
		duk_push_undefined(thr);
	}

 define_props:
	/* [ ... error lineNumber fileName ] */
#if defined(DUK_USE_ASSERTIONS)
	DUK_ASSERT(duk_get_top(thr) == entry_top + 2);
#endif
	duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_FILE_NAME, DUK_PROPDESC_FLAGS_C | DUK_PROPDESC_FLAG_NO_OVERWRITE);
	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LINE_NUMBER, DUK_PROPDESC_FLAGS_C | DUK_PROPDESC_FLAG_NO_OVERWRITE);
}
#endif  /* DUK_USE_AUGMENT_ERROR_CREATE && !DUK_USE_TRACEBACKS */

/*
 *  Add line number to a compiler error.
 */

#if defined(DUK_USE_AUGMENT_ERROR_CREATE)
DUK_LOCAL void duk__add_compiler_error_line(duk_hthread *thr) {

	/* Append a "(line NNN)" to the "message" property of any error
	 * thrown during compilation.  Usually compilation errors are
	 * SyntaxErrors but they can also be out-of-memory errors and
	 * the like.
	 */

	/* [ ... error ] */

	DUK_ASSERT(duk_is_object(thr, -1));

	if (!(thr->compile_ctx != NULL && thr->compile_ctx->h_filename != NULL)) {
		return;
	}

	DUK_DDD(DUK_DDDPRINT("compile error, before adding line info: %!T",
	                     (duk_tval *) duk_get_tval(thr, -1)));

	if (duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_MESSAGE)) {
		duk_bool_t at_end;

		/* Best guesstimate that error occurred at end of input, token
		 * truncated by end of input, etc.
		 */
#if 0
		at_end = (thr->compile_ctx->curr_token.start_offset + 1 >= thr->compile_ctx->lex.input_length);
		at_end = (thr->compile_ctx->lex.window[0].codepoint < 0 || thr->compile_ctx->lex.window[1].codepoint < 0);
#endif
		at_end = (thr->compile_ctx->lex.window[0].codepoint < 0);

		DUK_D(DUK_DPRINT("syntax error, determined at_end=%ld; curr_token.start_offset=%ld, "
		                 "lex.input_length=%ld, window[0].codepoint=%ld, window[1].codepoint=%ld",
		                 (long) at_end,
		                 (long) thr->compile_ctx->curr_token.start_offset,
		                 (long) thr->compile_ctx->lex.input_length,
		                 (long) thr->compile_ctx->lex.window[0].codepoint,
		                 (long) thr->compile_ctx->lex.window[1].codepoint));

		duk_push_sprintf(thr, " (line %ld%s)",
		                 (long) thr->compile_ctx->curr_token.start_line,
		                 at_end ? ", end of input" : "");
		duk_concat(thr, 2);
		duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_MESSAGE);
	} else {
		duk_pop(thr);
	}

	DUK_DDD(DUK_DDDPRINT("compile error, after adding line info: %!T",
	                     (duk_tval *) duk_get_tval(thr, -1)));
}
#endif  /* DUK_USE_AUGMENT_ERROR_CREATE */

/*
 *  Augment an error being created using Duktape specific properties
 *  like _Tracedata or .fileName/.lineNumber.
 */

#if defined(DUK_USE_AUGMENT_ERROR_CREATE)
DUK_LOCAL void duk__err_augment_builtin_create(duk_hthread *thr, duk_hthread *thr_callstack, const char *c_filename, duk_int_t c_line, duk_hobject *obj, duk_small_uint_t flags) {
#if defined(DUK_USE_ASSERTIONS)
	duk_int_t entry_top;
#endif

#if defined(DUK_USE_ASSERTIONS)
	entry_top = duk_get_top(thr);
#endif
	DUK_ASSERT(obj != NULL);

	DUK_UNREF(obj);  /* unreferenced w/o tracebacks */

	duk__add_compiler_error_line(thr);

#if defined(DUK_USE_TRACEBACKS)
	/* If tracebacks are enabled, the '_Tracedata' property is the only
	 * thing we need: 'fileName' and 'lineNumber' are virtual properties
	 * which use '_Tracedata'.  (Check _Tracedata only as own property.)
	 */
	if (duk_hobject_find_entry_tval_ptr_stridx(thr->heap, obj, DUK_STRIDX_INT_TRACEDATA) != NULL) {
		DUK_DDD(DUK_DDDPRINT("error value already has a '_Tracedata' property, not modifying it"));
	} else {
		duk__add_traceback(thr, thr_callstack, c_filename, c_line, flags);
	}
#else
	/* Without tracebacks the concrete .fileName and .lineNumber need
	 * to be added directly.
	 */
	duk__add_fileline(thr, thr_callstack, c_filename, c_line, flags);
#endif

#if defined(DUK_USE_ASSERTIONS)
	DUK_ASSERT(duk_get_top(thr) == entry_top);
#endif
}
#endif  /* DUK_USE_AUGMENT_ERROR_CREATE */

/*
 *  Augment an error at creation time with _Tracedata/fileName/lineNumber
 *  and allow a user error handler (if defined) to process/replace the error.
 *  The error to be augmented is at the stack top.
 *
 *  thr: thread containing the error value
 *  thr_callstack: thread which should be used for generating callstack etc.
 *  c_filename: C __FILE__ related to the error
 *  c_line: C __LINE__ related to the error
 *  flags & DUK_AUGMENT_FLAG_NOBLAME_FILELINE:
 *      if true, don't fileName/line as error source, otherwise use traceback
 *      (needed because user code filename/line are reported but internal ones
 *      are not)
 */

#if defined(DUK_USE_AUGMENT_ERROR_CREATE)
DUK_INTERNAL void duk_err_augment_error_create(duk_hthread *thr, duk_hthread *thr_callstack, const char *c_filename, duk_int_t c_line, duk_small_uint_t flags) {
	duk_hobject *obj;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(thr_callstack != NULL);

	/* [ ... error ] */

	/*
	 *  Criteria for augmenting:
	 *
	 *   - augmentation enabled in build (naturally)
	 *   - error value internal prototype chain contains the built-in
	 *     Error prototype object (i.e. 'val instanceof Error')
	 *
	 *  Additional criteria for built-in augmenting:
	 *
	 *   - error value is an extensible object
	 */

	obj = duk_get_hobject(thr, -1);
	if (!obj) {
		DUK_DDD(DUK_DDDPRINT("value is not an object, skip both built-in and user augment"));
		return;
	}
	if (!duk_hobject_prototype_chain_contains(thr, obj, thr->builtins[DUK_BIDX_ERROR_PROTOTYPE], 1 /*ignore_loop*/)) {
		/* If the value has a prototype loop, it's critical not to
		 * throw here.  Instead, assume the value is not to be
		 * augmented.
		 */
		DUK_DDD(DUK_DDDPRINT("value is not an error instance, skip both built-in and user augment"));
		return;
	}
	if (DUK_HOBJECT_HAS_EXTENSIBLE(obj)) {
		DUK_DDD(DUK_DDDPRINT("error meets criteria, built-in augment"));
		duk__err_augment_builtin_create(thr, thr_callstack, c_filename, c_line, obj, flags);
	} else {
		DUK_DDD(DUK_DDDPRINT("error does not meet criteria, no built-in augment"));
	}

	/* [ ... error ] */

#if defined(DUK_USE_ERRCREATE)
	duk__err_augment_user(thr, DUK_STRIDX_ERR_CREATE);
#endif
}
#endif  /* DUK_USE_AUGMENT_ERROR_CREATE */

/*
 *  Augment an error at throw time; allow a user error handler (if defined)
 *  to process/replace the error.  The error to be augmented is at the
 *  stack top.
 */

#if defined(DUK_USE_AUGMENT_ERROR_THROW)
DUK_INTERNAL void duk_err_augment_error_throw(duk_hthread *thr) {
#if defined(DUK_USE_ERRTHROW)
	duk__err_augment_user(thr, DUK_STRIDX_ERR_THROW);
#endif  /* DUK_USE_ERRTHROW */
}
#endif  /* DUK_USE_AUGMENT_ERROR_THROW */
#line 1 "duk_error_longjmp.c"
/*
 *  Do a longjmp call, calling the fatal error handler if no
 *  catchpoint exists.
 */

/* #include duk_internal.h -> already included */

#if defined(DUK_USE_PREFER_SIZE)
DUK_NORETURN(DUK_LOCAL_DECL void duk__uncaught_minimal(duk_hthread *thr));
DUK_LOCAL void duk__uncaught_minimal(duk_hthread *thr) {
	(void) duk_fatal(thr, "uncaught error");
	DUK_WO_NORETURN(return;);
}
#endif

#if 0
DUK_NORETURN(DUK_LOCAL_DECL void duk__uncaught_readable(duk_hthread *thr));
DUK_LOCAL void duk__uncaught_readable(duk_hthread *thr) {
	const char *summary;
	char buf[DUK_USE_FATAL_MAXLEN];

	summary = duk_push_string_tval_readable(thr, &thr->heap->lj.value1);
	DUK_SNPRINTF(buf, sizeof(buf), "uncaught: %s", summary);
	buf[sizeof(buf) - 1] = (char) 0;
	(void) duk_fatal(thr, (const char *) buf);
	DUK_WO_NORETURN(return;);
}
#endif

#if !defined(DUK_USE_PREFER_SIZE)
DUK_NORETURN(DUK_LOCAL_DECL void duk__uncaught_error_aware(duk_hthread *thr));
DUK_LOCAL void duk__uncaught_error_aware(duk_hthread *thr) {
	const char *summary;
	char buf[DUK_USE_FATAL_MAXLEN];

	summary = duk_push_string_tval_readable_error(thr, &thr->heap->lj.value1);
	DUK_ASSERT(summary != NULL);
	DUK_SNPRINTF(buf, sizeof(buf), "uncaught: %s", summary);
	buf[sizeof(buf) - 1] = (char) 0;
	(void) duk_fatal(thr, (const char *) buf);
	DUK_WO_NORETURN(return;);
}
#endif

DUK_INTERNAL void duk_err_longjmp(duk_hthread *thr) {
	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(thr->heap != NULL);

	DUK_DD(DUK_DDPRINT("longjmp error: type=%d iserror=%d value1=%!T value2=%!T",
	                   (int) thr->heap->lj.type, (int) thr->heap->lj.iserror,
	                   &thr->heap->lj.value1, &thr->heap->lj.value2));

	/* Prevent finalizer execution during error handling.  All error
	 * handling sites will process pending finalizers once error handling
	 * is complete and we're ready for the side effects.  Does not prevent
	 * refzero freeing or mark-and-sweep during error handling.
	 *
	 * NOTE: when we come here some calling code may have used DECREF
	 * NORZ macros without an explicit DUK_REFZERO_CHECK_xxx() call.
	 * We don't want to do it here because it would just check for
	 * pending finalizers and we prevent that explicitly.  Instead,
	 * the error catcher will run the finalizers once error handling
	 * is complete.
	 */

	DUK_ASSERT_LJSTATE_SET(thr->heap);

	thr->heap->pf_prevent_count++;
	DUK_ASSERT(thr->heap->pf_prevent_count != 0);  /* Wrap. */

#if defined(DUK_USE_ASSERTIONS)
	/* XXX: set this immediately when longjmp state is set */
	DUK_ASSERT(thr->heap->error_not_allowed == 0);  /* Detect error within critical section. */
	thr->heap->error_not_allowed = 1;
#endif

	DUK_DD(DUK_DDPRINT("about to longjmp, pf_prevent_count=%ld", (long) thr->heap->pf_prevent_count));

	/* If we don't have a jmpbuf_ptr, there is little we can do except
	 * cause a fatal error.  The caller's expectation is that we never
	 * return.
	 */
	if (!thr->heap->lj.jmpbuf_ptr) {
		DUK_D(DUK_DPRINT("uncaught error: type=%d iserror=%d value1=%!T value2=%!T",
		                 (int) thr->heap->lj.type, (int) thr->heap->lj.iserror,
		                 &thr->heap->lj.value1, &thr->heap->lj.value2));

#if defined(DUK_USE_PREFER_SIZE)
		duk__uncaught_minimal(thr);
#else
		duk__uncaught_error_aware(thr);
#endif
		DUK_UNREACHABLE();
	}

#if defined(DUK_USE_CPP_EXCEPTIONS)
	throw duk_internal_exception();  /* dummy */
#else
	DUK_LONGJMP(thr->heap->lj.jmpbuf_ptr->jb);
#endif

	DUK_UNREACHABLE();
}
#line 1 "duk_error_misc.c"
/*
 *  Error helpers
 */

/* #include duk_internal.h -> already included */

/*
 *  Helper to walk the thread chain and see if there is an active error
 *  catcher.  Protected calls or finally blocks aren't considered catching.
 */

#if defined(DUK_USE_DEBUGGER_SUPPORT)
DUK_LOCAL duk_bool_t duk__have_active_catcher(duk_hthread *thr) {
	/* As noted above, a protected API call won't be counted as a
	 * catcher.  This is usually convenient, e.g. in the case of a top-
	 * level duk_pcall(), but may not always be desirable.  Perhaps add
	 * an argument to treat them as catchers?
	 */

	duk_activation *act;
	duk_catcher *cat;

	DUK_ASSERT(thr != NULL);

	for (; thr != NULL; thr = thr->resumer) {
		for (act = thr->callstack_curr; act != NULL; act = act->parent) {
			for (cat = act->cat; cat != NULL; cat = cat->parent) {
				if (DUK_CAT_HAS_CATCH_ENABLED(cat)) {
					return 1;  /* all we need to know */
				}
			}
		}
	}
	return 0;
}
#endif  /* DUK_USE_DEBUGGER_SUPPORT */

/*
 *  Get prototype object for an integer error code.
 */

DUK_INTERNAL duk_hobject *duk_error_prototype_from_code(duk_hthread *thr, duk_errcode_t code) {
	switch (code) {
	case DUK_ERR_EVAL_ERROR:
		return thr->builtins[DUK_BIDX_EVAL_ERROR_PROTOTYPE];
	case DUK_ERR_RANGE_ERROR:
		return thr->builtins[DUK_BIDX_RANGE_ERROR_PROTOTYPE];
	case DUK_ERR_REFERENCE_ERROR:
		return thr->builtins[DUK_BIDX_REFERENCE_ERROR_PROTOTYPE];
	case DUK_ERR_SYNTAX_ERROR:
		return thr->builtins[DUK_BIDX_SYNTAX_ERROR_PROTOTYPE];
	case DUK_ERR_TYPE_ERROR:
		return thr->builtins[DUK_BIDX_TYPE_ERROR_PROTOTYPE];
	case DUK_ERR_URI_ERROR:
		return thr->builtins[DUK_BIDX_URI_ERROR_PROTOTYPE];
	case DUK_ERR_ERROR:
	default:
		return thr->builtins[DUK_BIDX_ERROR_PROTOTYPE];
	}
}

/*
 *  Helper for debugger throw notify and pause-on-uncaught integration.
 */

#if defined(DUK_USE_DEBUGGER_SUPPORT)
DUK_INTERNAL void duk_err_check_debugger_integration(duk_hthread *thr) {
	duk_bool_t uncaught;
	duk_tval *tv_obj;

	/* If something is thrown with the debugger attached and nobody will
	 * catch it, execution is paused before the longjmp, turning over
	 * control to the debug client.  This allows local state to be examined
	 * before the stack is unwound.  Errors are not intercepted when debug
	 * message loop is active (e.g. for Eval).
	 */

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(thr->heap != NULL);

	/* XXX: Allow customizing the pause and notify behavior at runtime
	 * using debugger runtime flags.  For now the behavior is fixed using
	 * config options.
	 */

	if (!duk_debug_is_attached(thr->heap) ||
	    thr->heap->dbg_processing ||
	    thr->heap->lj.type != DUK_LJ_TYPE_THROW ||
	    thr->heap->creating_error) {
		DUK_D(DUK_DPRINT("skip debugger error integration; not attached, debugger processing, not THROW, or error thrown while creating error"));
		return;
	}

	/* Don't intercept a DoubleError, we may have caused the initial double
	 * fault and attempting to intercept it will cause us to be called
	 * recursively and exhaust the C stack.  (This should no longer happen
	 * for the initial throw because DoubleError path doesn't do a debugger
	 * integration check, but it might happen for rethrows.)
	 */
	tv_obj = &thr->heap->lj.value1;
	if (DUK_TVAL_IS_OBJECT(tv_obj) && DUK_TVAL_GET_OBJECT(tv_obj) == thr->builtins[DUK_BIDX_DOUBLE_ERROR]) {
		DUK_D(DUK_DPRINT("built-in DoubleError instance (re)thrown, not intercepting"));
		return;
	}

	uncaught = !duk__have_active_catcher(thr);

	/* Debugger code expects the value at stack top.  This also serves
	 * as a backup: we need to store/restore the longjmp state because
	 * when the debugger is paused Eval commands may be executed and
	 * they can arbitrarily clobber the longjmp state.
	 */
	duk_push_tval(thr, tv_obj);

	/* Store and reset longjmp state. */
	DUK_ASSERT_LJSTATE_SET(thr->heap);
	DUK_TVAL_DECREF_NORZ(thr, tv_obj);
	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&thr->heap->lj.value2));  /* Always for THROW type. */
	DUK_TVAL_SET_UNDEFINED(tv_obj);
	thr->heap->lj.type = DUK_LJ_TYPE_UNKNOWN;
	DUK_ASSERT_LJSTATE_UNSET(thr->heap);

#if defined(DUK_USE_DEBUGGER_THROW_NOTIFY)
	/* Report it to the debug client */
	DUK_D(DUK_DPRINT("throw with debugger attached, report to client"));
	duk_debug_send_throw(thr, uncaught);
#endif

	if (uncaught) {
		if (thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_UNCAUGHT_ERROR) {
			DUK_D(DUK_DPRINT("PAUSE TRIGGERED by uncaught error"));
			duk_debug_halt_execution(thr, 1 /*use_prev_pc*/);
		}
	} else {
		if (thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_CAUGHT_ERROR) {
			DUK_D(DUK_DPRINT("PAUSE TRIGGERED by caught error"));
			duk_debug_halt_execution(thr, 1 /*use_prev_pc*/);
		}
	}

	/* Restore longjmp state. */
	DUK_ASSERT_LJSTATE_UNSET(thr->heap);
	thr->heap->lj.type = DUK_LJ_TYPE_THROW;
	tv_obj = DUK_GET_TVAL_NEGIDX(thr, -1);
	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&thr->heap->lj.value1));
	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&thr->heap->lj.value2));
	DUK_TVAL_SET_TVAL(&thr->heap->lj.value1, tv_obj);
	DUK_TVAL_INCREF(thr, tv_obj);
	DUK_ASSERT_LJSTATE_SET(thr->heap);

	duk_pop(thr);
}
#endif  /* DUK_USE_DEBUGGER_SUPPORT */

/*
 *  Helpers for setting up heap longjmp state.
 */

DUK_INTERNAL void duk_err_setup_ljstate1(duk_hthread *thr, duk_small_uint_t lj_type, duk_tval *tv_val) {
	duk_heap *heap;

	DUK_ASSERT(thr != NULL);
	heap = thr->heap;
	DUK_ASSERT(heap != NULL);
	DUK_ASSERT(tv_val != NULL);

	DUK_ASSERT_LJSTATE_UNSET(heap);

	heap->lj.type = lj_type;
	DUK_TVAL_SET_TVAL(&heap->lj.value1, tv_val);
	DUK_TVAL_INCREF(thr, tv_val);

	DUK_ASSERT_LJSTATE_SET(heap);
}
#line 1 "duk_error_throw.c"
/*
 *  Create and throw an ECMAScript error object based on a code and a message.
 *
 *  Used when we throw errors internally.  ECMAScript generated error objects
 *  are created by ECMAScript code, and the throwing is handled by the bytecode
 *  executor.
 */

/* #include duk_internal.h -> already included */

/*
 *  Create and throw an error (originating from Duktape internally)
 *
 *  Push an error object on top of the stack, possibly throw augmenting
 *  the error, and finally longjmp.
 *
 *  If an error occurs while we're dealing with the current error, we might
 *  enter an infinite recursion loop.  This is prevented by detecting a
 *  "double fault" through the heap->creating_error flag; the recursion
 *  then stops at the second level.
 */

#if defined(DUK_USE_VERBOSE_ERRORS)
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) {
#else
DUK_INTERNAL void duk_err_create_and_throw(duk_hthread *thr, duk_errcode_t code) {
#endif
#if defined(DUK_USE_VERBOSE_ERRORS)
	DUK_DD(DUK_DDPRINT("duk_err_create_and_throw(): code=%ld, msg=%s, filename=%s, line=%ld",
	                   (long) code, (const char *) msg,
	                   (const char *) filename, (long) line));
#else
	DUK_DD(DUK_DDPRINT("duk_err_create_and_throw(): code=%ld", (long) code));
#endif

	DUK_ASSERT(thr != NULL);

	/* Even though nested call is possible because we throw an error when
	 * trying to create an error, the potential errors must happen before
	 * the longjmp state is configured.
	 */
	DUK_ASSERT_LJSTATE_UNSET(thr->heap);

	/* Sync so that augmentation sees up-to-date activations, NULL
	 * thr->ptr_curr_pc so that it's not used if side effects occur
	 * in augmentation or longjmp handling.
	 */
	duk_hthread_sync_and_null_currpc(thr);

	/*
	 *  Create and push an error object onto the top of stack.
	 *  The error is potentially augmented before throwing.
	 *
	 *  If a "double error" occurs, use a fixed error instance
	 *  to avoid further trouble.
	 */

	if (thr->heap->creating_error) {
		duk_tval tv_val;
		duk_hobject *h_err;

		thr->heap->creating_error = 0;

		h_err = thr->builtins[DUK_BIDX_DOUBLE_ERROR];
		if (h_err != NULL) {
			DUK_D(DUK_DPRINT("double fault detected -> use built-in fixed 'double error' instance"));
			DUK_TVAL_SET_OBJECT(&tv_val, h_err);
		} else {
			DUK_D(DUK_DPRINT("double fault detected; there is no built-in fixed 'double error' instance "
			                 "-> use the error code as a number"));
			DUK_TVAL_SET_I32(&tv_val, (duk_int32_t) code);
		}

		duk_err_setup_ljstate1(thr, DUK_LJ_TYPE_THROW, &tv_val);

		/* No augmentation to avoid any allocations or side effects. */
	} else {
		/* Prevent infinite recursion.  Extra call stack and C
		 * recursion headroom (see GH-191) is added for augmentation.
		 * That is now signalled by heap->augmenting error and taken
		 * into account in call handling without an explicit limit bump.
		 */
		thr->heap->creating_error = 1;

		duk_require_stack(thr, 1);

		/* XXX: usually unnecessary '%s' formatting here, but cannot
		 * use 'msg' as a format string directly.
		 */
#if defined(DUK_USE_VERBOSE_ERRORS)
		duk_push_error_object_raw(thr,
		                          code | DUK_ERRCODE_FLAG_NOBLAME_FILELINE,
		                          filename,
		                          line,
		                          "%s",
		                          (const char *) msg);
#else
		duk_push_error_object_raw(thr,
		                          code | DUK_ERRCODE_FLAG_NOBLAME_FILELINE,
		                          NULL,
		                          0,
		                          NULL);
#endif

		/* Note that an alloc error may happen during error augmentation.
		 * This may happen both when the original error is an alloc error
		 * and when it's something else.  Because any error in augmentation
		 * must be handled correctly anyway, there's no special check for
		 * avoiding it for alloc errors (this differs from Duktape 1.x).
		 */
#if defined(DUK_USE_AUGMENT_ERROR_THROW)
		DUK_DDD(DUK_DDDPRINT("THROW ERROR (INTERNAL): %!iT (before throw augment)",
		                     (duk_tval *) duk_get_tval(thr, -1)));
		duk_err_augment_error_throw(thr);
#endif

		duk_err_setup_ljstate1(thr, DUK_LJ_TYPE_THROW, DUK_GET_TVAL_NEGIDX(thr, -1));
		thr->heap->creating_error = 0;

		/* Error is now created and we assume no errors can occur any
		 * more.  Check for debugger Throw integration only when the
		 * error is complete.  If we enter debugger message loop,
		 * creating_error must be 0 so that errors can be thrown in
		 * the paused state, e.g. in Eval commands.
		 */
#if defined(DUK_USE_DEBUGGER_SUPPORT)
		duk_err_check_debugger_integration(thr);
#endif
	}

	/*
	 *  Finally, longjmp
	 */

	DUK_DDD(DUK_DDDPRINT("THROW ERROR (INTERNAL): %!iT, %!iT (after throw augment)",
	                     (duk_tval *) &thr->heap->lj.value1, (duk_tval *) &thr->heap->lj.value2));

	duk_err_longjmp(thr);
	DUK_UNREACHABLE();
}

/*
 *  Helper for C function call negative return values.
 */

DUK_INTERNAL void duk_error_throw_from_negative_rc(duk_hthread *thr, duk_ret_t rc) {
	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(rc < 0);

	/*
	 *  The __FILE__ and __LINE__ information is intentionally not used in the
	 *  creation of the error object, as it isn't useful in the tracedata.  The
	 *  tracedata still contains the function which returned the negative return
	 *  code, and having the file/line of this function isn't very useful.
	 *
	 *  The error messages for DUK_RET_xxx shorthand are intentionally very
	 *  minimal: they're only really useful for low memory targets.
	 */

	duk_error_raw(thr, -rc, NULL, 0, "error (rc %ld)", (long) rc);
	DUK_WO_NORETURN(return;);
}
#line 1 "duk_hbuffer_alloc.c"
/*
 *  duk_hbuffer allocation and freeing.
 */

/* #include duk_internal.h -> already included */

/* Allocate a new duk_hbuffer of a certain type and return a pointer to it
 * (NULL on error).  Write buffer data pointer to 'out_bufdata' (only if
 * allocation successful).
 */
DUK_INTERNAL duk_hbuffer *duk_hbuffer_alloc(duk_heap *heap, duk_size_t size, duk_small_uint_t flags, void **out_bufdata) {
	duk_hbuffer *res = NULL;
	duk_size_t header_size;
	duk_size_t alloc_size;

	DUK_ASSERT(heap != NULL);
	DUK_ASSERT(out_bufdata != NULL);

	DUK_DDD(DUK_DDDPRINT("allocate hbuffer"));

	/* Size sanity check.  Should not be necessary because caller is
	 * required to check this, but we don't want to cause a segfault
	 * if the size wraps either in duk_size_t computation or when
	 * storing the size in a 16-bit field.
	 */
	if (size > DUK_HBUFFER_MAX_BYTELEN) {
		DUK_D(DUK_DPRINT("hbuffer alloc failed: size too large: %ld", (long) size));
		return NULL;  /* no need to write 'out_bufdata' */
	}

	if (flags & DUK_BUF_FLAG_EXTERNAL) {
		header_size = sizeof(duk_hbuffer_external);
		alloc_size = sizeof(duk_hbuffer_external);
	} else if (flags & DUK_BUF_FLAG_DYNAMIC) {
		header_size = sizeof(duk_hbuffer_dynamic);
		alloc_size = sizeof(duk_hbuffer_dynamic);
	} else {
		header_size = sizeof(duk_hbuffer_fixed);
		alloc_size = sizeof(duk_hbuffer_fixed) + size;
		DUK_ASSERT(alloc_size >= sizeof(duk_hbuffer_fixed));  /* no wrapping */
	}

	res = (duk_hbuffer *) DUK_ALLOC(heap, alloc_size);
	if (DUK_UNLIKELY(res == NULL)) {
		goto alloc_error;
	}

	/* zero everything unless requested not to do so */
#if defined(DUK_USE_ZERO_BUFFER_DATA)
	duk_memzero((void *) res,
	            (flags & DUK_BUF_FLAG_NOZERO) ? header_size : alloc_size);
#else
	duk_memzero((void *) res, header_size);
#endif

	if (flags & DUK_BUF_FLAG_EXTERNAL) {
		duk_hbuffer_external *h;
		h = (duk_hbuffer_external *) res;
		DUK_UNREF(h);
		*out_bufdata = NULL;
#if defined(DUK_USE_EXPLICIT_NULL_INIT)
#if defined(DUK_USE_HEAPPTR16)
/* the compressed pointer is zeroed which maps to NULL, so nothing to do. */
#else
		DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(heap, h, NULL);
#endif
#endif
		DUK_ASSERT(DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(heap, h) == NULL);
	} else if (flags & DUK_BUF_FLAG_DYNAMIC) {
		duk_hbuffer_dynamic *h = (duk_hbuffer_dynamic *) res;
		void *ptr;

		if (size > 0) {
			DUK_ASSERT(!(flags & DUK_BUF_FLAG_EXTERNAL));  /* alloc external with size zero */
			DUK_DDD(DUK_DDDPRINT("dynamic buffer with nonzero size, alloc actual buffer"));
#if defined(DUK_USE_ZERO_BUFFER_DATA)
			ptr = DUK_ALLOC_ZEROED(heap, size);
#else
			ptr = DUK_ALLOC(heap, size);
#endif
			if (DUK_UNLIKELY(ptr == NULL)) {
				/* Because size > 0, NULL check is correct */
				goto alloc_error;
			}
			*out_bufdata = ptr;

			DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap, h, ptr);
		} else {
			*out_bufdata = NULL;
#if defined(DUK_USE_EXPLICIT_NULL_INIT)
#if defined(DUK_USE_HEAPPTR16)
/* the compressed pointer is zeroed which maps to NULL, so nothing to do. */
#else
			DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap, h, NULL);
#endif
#endif
			DUK_ASSERT(DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, h) == NULL);
		}
	} else {
		*out_bufdata = (void *) ((duk_hbuffer_fixed *) (void *) res + 1);
	}

	DUK_HBUFFER_SET_SIZE(res, size);

	DUK_HEAPHDR_SET_TYPE(&res->hdr, DUK_HTYPE_BUFFER);
	if (flags & DUK_BUF_FLAG_DYNAMIC) {
		DUK_HBUFFER_SET_DYNAMIC(res);
		if (flags & DUK_BUF_FLAG_EXTERNAL) {
			DUK_HBUFFER_SET_EXTERNAL(res);
		}
	} else {
		DUK_ASSERT(!(flags & DUK_BUF_FLAG_EXTERNAL));
	}
        DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap, &res->hdr);

	DUK_DDD(DUK_DDDPRINT("allocated hbuffer: %p", (void *) res));
	return res;

 alloc_error:
	DUK_DD(DUK_DDPRINT("hbuffer allocation failed"));

	DUK_FREE(heap, res);
	return NULL;  /* no need to write 'out_bufdata' */
}

/* For indirect allocs. */

DUK_INTERNAL void *duk_hbuffer_get_dynalloc_ptr(duk_heap *heap, void *ud) {
	duk_hbuffer_dynamic *buf = (duk_hbuffer_dynamic *) ud;
	DUK_UNREF(heap);
	return (void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, buf);
}
#line 1 "duk_hbuffer_assert.c"
/*
 *  duk_hbuffer assertion helpers
 */

/* #include duk_internal.h -> already included */

#if defined(DUK_USE_ASSERTIONS)

DUK_INTERNAL void duk_hbuffer_assert_valid(duk_hbuffer *h) {
	DUK_ASSERT(h != NULL);
}

#endif  /* DUK_USE_ASSERTIONS */
#line 1 "duk_hbuffer_ops.c"
/*
 *  duk_hbuffer operations such as resizing and inserting/appending data to
 *  a dynamic buffer.
 */

/* #include duk_internal.h -> already included */

/*
 *  Resizing
 */

DUK_INTERNAL void duk_hbuffer_resize(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t new_size) {
	void *res;
	duk_size_t prev_size;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(buf != NULL);
	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf));
	DUK_ASSERT(!DUK_HBUFFER_HAS_EXTERNAL(buf));

	/*
	 *  Maximum size check
	 */

	if (new_size > DUK_HBUFFER_MAX_BYTELEN) {
		DUK_ERROR_RANGE(thr, "buffer too long");
		DUK_WO_NORETURN(return;);
	}

	/*
	 *  Note: use indirect realloc variant just in case mark-and-sweep
	 *  (finalizers) might resize this same buffer during garbage
	 *  collection.
	 */

	res = DUK_REALLOC_INDIRECT(thr->heap, duk_hbuffer_get_dynalloc_ptr, (void *) buf, new_size);
	if (DUK_LIKELY(res != NULL || new_size == 0)) {
		/* 'res' may be NULL if new allocation size is 0. */

		DUK_DDD(DUK_DDDPRINT("resized dynamic buffer %p:%ld -> %p:%ld",
		                     (void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, buf),
		                     (long) DUK_HBUFFER_DYNAMIC_GET_SIZE(buf),
		                     (void *) res,
		                     (long) new_size));

		/*
		 *  The entire allocated buffer area, regardless of actual used
		 *  size, is kept zeroed in resizes for simplicity.  If the buffer
		 *  is grown, zero the new part.
		 */

		prev_size = DUK_HBUFFER_DYNAMIC_GET_SIZE(buf);
		if (new_size > prev_size) {
			DUK_ASSERT(new_size - prev_size > 0);
#if defined(DUK_USE_ZERO_BUFFER_DATA)
			duk_memzero((void *) ((char *) res + prev_size),
			            (duk_size_t) (new_size - prev_size));
#endif
		}

		DUK_HBUFFER_DYNAMIC_SET_SIZE(buf, new_size);
		DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(thr->heap, buf, res);
	} else {
		DUK_ERROR_ALLOC_FAILED(thr);
		DUK_WO_NORETURN(return;);
	}

	DUK_ASSERT(res != NULL || new_size == 0);
}

DUK_INTERNAL void duk_hbuffer_reset(duk_hthread *thr, duk_hbuffer_dynamic *buf) {
	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(buf != NULL);
	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf));
	DUK_ASSERT(!DUK_HBUFFER_HAS_EXTERNAL(buf));

	duk_hbuffer_resize(thr, buf, 0);
}
/* #include duk_internal.h -> already included */
#line 2 "duk_hbufobj_misc.c"

#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
DUK_INTERNAL duk_uint_t duk_hbufobj_clamp_bytelength(duk_hbufobj *h_bufobj, duk_uint_t len) {
	duk_uint_t buf_size;
	duk_uint_t buf_avail;

	DUK_ASSERT(h_bufobj != NULL);
	DUK_ASSERT(h_bufobj->buf != NULL);

	buf_size = (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_bufobj->buf);
	if (h_bufobj->offset > buf_size) {
		/* Slice starting point is beyond current length. */
		return 0;
	}
	buf_avail = buf_size - h_bufobj->offset;

	return buf_avail >= len ? len : buf_avail;
}
#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
#line 1 "duk_heap_alloc.c"
/*
 *  duk_heap allocation and freeing.
 */

/* #include duk_internal.h -> already included */

#if defined(DUK_USE_ROM_STRINGS)
/* Fixed seed value used with ROM strings. */
#define DUK__FIXED_HASH_SEED       0xabcd1234
#endif

/*
 *  Free a heap object.
 *
 *  Free heap object and its internal (non-heap) pointers.  Assumes that
 *  caller has removed the object from heap allocated list or the string
 *  intern table, and any weak references (which strings may have) have
 *  been already dealt with.
 */

DUK_INTERNAL void duk_free_hobject(duk_heap *heap, duk_hobject *h) {
	DUK_ASSERT(heap != NULL);
	DUK_ASSERT(h != NULL);

	DUK_FREE(heap, DUK_HOBJECT_GET_PROPS(heap, h));

	if (DUK_HOBJECT_IS_COMPFUNC(h)) {
		duk_hcompfunc *f = (duk_hcompfunc *) h;
		DUK_UNREF(f);
		/* Currently nothing to free; 'data' is a heap object */
	} else if (DUK_HOBJECT_IS_NATFUNC(h)) {
		duk_hnatfunc *f = (duk_hnatfunc *) h;
		DUK_UNREF(f);
		/* Currently nothing to free */
	} else if (DUK_HOBJECT_IS_THREAD(h)) {
		duk_hthread *t = (duk_hthread *) h;
		duk_activation *act;

		DUK_FREE(heap, t->valstack);

		/* Don't free h->resumer because it exists in the heap.
		 * Callstack entries also contain function pointers which
		 * are not freed for the same reason.  They are decref
		 * finalized and the targets are freed if necessary based
		 * on their refcount (or reachability).
		 */
		for (act = t->callstack_curr; act != NULL;) {
			duk_activation *act_next;
			duk_catcher *cat;

			for (cat = act->cat; cat != NULL;) {
				duk_catcher *cat_next;

				cat_next = cat->parent;
				DUK_FREE(heap, (void *) cat);
				cat = cat_next;
			}

			act_next = act->parent;
			DUK_FREE(heap, (void *) act);
			act = act_next;
		}

		/* XXX: with 'caller' property the callstack would need
		 * to be unwound to update the 'caller' properties of
		 * functions in the callstack.
		 */
	} else if (DUK_HOBJECT_IS_BOUNDFUNC(h)) {
		duk_hboundfunc *f = (duk_hboundfunc *) (void *) h;

		DUK_FREE(heap, f->args);
	}

	DUK_FREE(heap, (void *) h);
}

DUK_INTERNAL void duk_free_hbuffer(duk_heap *heap, duk_hbuffer *h) {
	DUK_ASSERT(heap != NULL);
	DUK_ASSERT(h != NULL);

	if (DUK_HBUFFER_HAS_DYNAMIC(h) && !DUK_HBUFFER_HAS_EXTERNAL(h)) {
		duk_hbuffer_dynamic *g = (duk_hbuffer_dynamic *) h;
		DUK_DDD(DUK_DDDPRINT("free dynamic buffer %p", (void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, g)));
		DUK_FREE(heap, DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, g));
	}
	DUK_FREE(heap, (void *) h);
}

DUK_INTERNAL void duk_free_hstring(duk_heap *heap, duk_hstring *h) {
	DUK_ASSERT(heap != NULL);
	DUK_ASSERT(h != NULL);

	DUK_UNREF(heap);
	DUK_UNREF(h);

#if defined(DUK_USE_HSTRING_EXTDATA) && defined(DUK_USE_EXTSTR_FREE)
	if (DUK_HSTRING_HAS_EXTDATA(h)) {
		DUK_DDD(DUK_DDDPRINT("free extstr: hstring %!O, extdata: %p",
		                     h, DUK_HSTRING_GET_EXTDATA((duk_hstring_external *) h)));
		DUK_USE_EXTSTR_FREE(heap->heap_udata, (const void *) DUK_HSTRING_GET_EXTDATA((duk_hstring_external *) h));
	}
#endif
	DUK_FREE(heap, (void *) h);
}

DUK_INTERNAL void duk_heap_free_heaphdr_raw(duk_heap *heap, duk_heaphdr *hdr) {
	DUK_ASSERT(heap);
	DUK_ASSERT(hdr);

	DUK_DDD(DUK_DDDPRINT("free heaphdr %p, htype %ld", (void *) hdr, (long) DUK_HEAPHDR_GET_TYPE(hdr)));

	switch (DUK_HEAPHDR_GET_TYPE(hdr)) {
	case DUK_HTYPE_STRING:
		duk_free_hstring(heap, (duk_hstring *) hdr);
		break;
	case DUK_HTYPE_OBJECT:
		duk_free_hobject(heap, (duk_hobject *) hdr);
		break;
	default:
		DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(hdr) == DUK_HTYPE_BUFFER);
		duk_free_hbuffer(heap, (duk_hbuffer *) hdr);
	}

}

/*
 *  Free the heap.
 *
 *  Frees heap-related non-heap-tracked allocations such as the
 *  string intern table; then frees the heap allocated objects;
 *  and finally frees the heap structure itself.  Reference counts
 *  and GC markers are ignored (and not updated) in this process,
 *  and finalizers won't be called.
 *
 *  The heap pointer and heap object pointers must not be used
 *  after this call.
 */

#if defined(DUK_USE_CACHE_ACTIVATION)
DUK_LOCAL duk_size_t duk__heap_free_activation_freelist(duk_heap *heap) {
	duk_activation *act;
	duk_activation *act_next;
	duk_size_t count_act = 0;

	for (act = heap->activation_free; act != NULL;) {
		act_next = act->parent;
		DUK_FREE(heap, (void *) act);
		act = act_next;
#if defined(DUK_USE_DEBUG)
		count_act++;
#endif
	}
	heap->activation_free = NULL;  /* needed when called from mark-and-sweep */
	return count_act;
}
#endif  /* DUK_USE_CACHE_ACTIVATION */

#if defined(DUK_USE_CACHE_CATCHER)
DUK_LOCAL duk_size_t duk__heap_free_catcher_freelist(duk_heap *heap) {
	duk_catcher *cat;
	duk_catcher *cat_next;
	duk_size_t count_cat = 0;

	for (cat = heap->catcher_free; cat != NULL;) {
		cat_next = cat->parent;
		DUK_FREE(heap, (void *) cat);
		cat = cat_next;
#if defined(DUK_USE_DEBUG)
		count_cat++;
#endif
	}
	heap->catcher_free = NULL;  /* needed when called from mark-and-sweep */

	return count_cat;
}
#endif  /* DUK_USE_CACHE_CATCHER */

DUK_INTERNAL void duk_heap_free_freelists(duk_heap *heap) {
	duk_size_t count_act = 0;
	duk_size_t count_cat = 0;

#if defined(DUK_USE_CACHE_ACTIVATION)
	count_act = duk__heap_free_activation_freelist(heap);
#endif
#if defined(DUK_USE_CACHE_CATCHER)
	count_cat = duk__heap_free_catcher_freelist(heap);
#endif
	DUK_UNREF(heap);
	DUK_UNREF(count_act);
	DUK_UNREF(count_cat);

	DUK_D(DUK_DPRINT("freed %ld activation freelist entries, %ld catcher freelist entries",
	                 (long) count_act, (long) count_cat));
}

DUK_LOCAL void duk__free_allocated(duk_heap *heap) {
	duk_heaphdr *curr;
	duk_heaphdr *next;

	curr = heap->heap_allocated;
	while (curr) {
		/* We don't log or warn about freeing zero refcount objects
		 * because they may happen with finalizer processing.
		 */

		DUK_DDD(DUK_DDDPRINT("FINALFREE (allocated): %!iO",
		                     (duk_heaphdr *) curr));
		next = DUK_HEAPHDR_GET_NEXT(heap, curr);
		duk_heap_free_heaphdr_raw(heap, curr);
		curr = next;
	}
}

#if defined(DUK_USE_FINALIZER_SUPPORT)
DUK_LOCAL void duk__free_finalize_list(duk_heap *heap) {
	duk_heaphdr *curr;
	duk_heaphdr *next;

	curr = heap->finalize_list;
	while (curr) {
		DUK_DDD(DUK_DDDPRINT("FINALFREE (finalize_list): %!iO",
		                     (duk_heaphdr *) curr));
		next = DUK_HEAPHDR_GET_NEXT(heap, curr);
		duk_heap_free_heaphdr_raw(heap, curr);
		curr = next;
	}
}
#endif  /* DUK_USE_FINALIZER_SUPPORT */

DUK_LOCAL void duk__free_stringtable(duk_heap *heap) {
	/* strings are only tracked by stringtable */
	duk_heap_strtable_free(heap);
}

#if defined(DUK_USE_FINALIZER_SUPPORT)
DUK_LOCAL void duk__free_run_finalizers(duk_heap *heap) {
	duk_heaphdr *curr;
	duk_uint_t round_no;
	duk_size_t count_all;
	duk_size_t count_finalized;
	duk_size_t curr_limit;

	DUK_ASSERT(heap != NULL);

#if defined(DUK_USE_REFERENCE_COUNTING)
	DUK_ASSERT(heap->refzero_list == NULL);  /* refzero not running -> must be empty */
#endif
	DUK_ASSERT(heap->finalize_list == NULL);  /* mark-and-sweep last pass */

	if (heap->heap_thread == NULL) {
		/* May happen when heap allocation fails right off.  There
		 * cannot be any finalizable objects in this case.
		 */
		DUK_D(DUK_DPRINT("no heap_thread in heap destruct, assume no finalizable objects"));
		return;
	}

	/* Prevent finalize_list processing and mark-and-sweep entirely.
	 * Setting ms_running != 0 also prevents refzero handling from moving
	 * objects away from the heap_allocated list.  The flag name is a bit
	 * misleading here.
	 *
	 * Use a distinct value for ms_running here (== 2) so that assertions
	 * can detect this situation separate from the normal runtime
	 * mark-and-sweep case.  This allows better assertions (GH-2030).
	 */
	DUK_ASSERT(heap->pf_prevent_count == 0);
	DUK_ASSERT(heap->ms_running == 0);
	DUK_ASSERT(heap->ms_prevent_count == 0);
	heap->pf_prevent_count = 1;
	heap->ms_running = 2;  /* Use distinguishable value. */
	heap->ms_prevent_count = 1;  /* Bump, because mark-and-sweep assumes it's bumped when ms_running is set. */

	curr_limit = 0;  /* suppress warning, not used */
	for (round_no = 0; ; round_no++) {
		curr = heap->heap_allocated;
		count_all = 0;
		count_finalized = 0;
		while (curr) {
			count_all++;
			if (DUK_HEAPHDR_IS_OBJECT(curr)) {
				/* Only objects in heap_allocated may have finalizers.  Check that
				 * the object itself has a _Finalizer property (own or inherited)
				 * so that we don't execute finalizers for e.g. Proxy objects.
				 */
				DUK_ASSERT(curr != NULL);

				if (DUK_HOBJECT_HAS_FINALIZER_FAST(heap, (duk_hobject *) curr)) {
					if (!DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) curr)) {
						DUK_ASSERT(DUK_HEAP_HAS_FINALIZER_NORESCUE(heap));  /* maps to finalizer 2nd argument */
						duk_heap_run_finalizer(heap, (duk_hobject *) curr);
						count_finalized++;
					}
				}
			}
			curr = DUK_HEAPHDR_GET_NEXT(heap, curr);
		}

		/* Each round of finalizer execution may spawn new finalizable objects
		 * which is normal behavior for some applications.  Allow multiple
		 * rounds of finalization, but use a shrinking limit based on the
		 * first round to detect the case where a runaway finalizer creates
		 * an unbounded amount of new finalizable objects.  Finalizer rescue
		 * is not supported: the semantics are unclear because most of the
		 * objects being finalized here are already reachable.  The finalizer
		 * is given a boolean to indicate that rescue is not possible.
		 *
		 * See discussion in: https://github.com/svaarala/duktape/pull/473
		 */

		if (round_no == 0) {
			/* Cannot wrap: each object is at least 8 bytes so count is
			 * at most 1/8 of that.
			 */
			curr_limit = count_all * 2;
		} else {
			curr_limit = (curr_limit * 3) / 4;   /* Decrease by 25% every round */
		}
		DUK_D(DUK_DPRINT("finalizer round %ld complete, %ld objects, tried to execute %ld finalizers, current limit is %ld",
		                 (long) round_no, (long) count_all, (long) count_finalized, (long) curr_limit));

		if (count_finalized == 0) {
			DUK_D(DUK_DPRINT("no more finalizable objects, forced finalization finished"));
			break;
		}
		if (count_finalized >= curr_limit) {
			DUK_D(DUK_DPRINT("finalizer count above limit, potentially runaway finalizer; skip remaining finalizers"));
			break;
		}
	}

	DUK_ASSERT(heap->ms_running == 2);
	DUK_ASSERT(heap->pf_prevent_count == 1);
	heap->ms_running = 0;
	heap->pf_prevent_count = 0;
}
#endif  /* DUK_USE_FINALIZER_SUPPORT */

DUK_INTERNAL void duk_heap_free(duk_heap *heap) {
	DUK_D(DUK_DPRINT("free heap: %p", (void *) heap));

#if defined(DUK_USE_DEBUG)
	duk_heap_strtable_dump(heap);
#endif

#if defined(DUK_USE_DEBUGGER_SUPPORT)
	/* Detach a debugger if attached (can be called multiple times)
	 * safely.
	 */
	/* XXX: Add a flag to reject an attempt to re-attach?  Otherwise
	 * the detached callback may immediately reattach.
	 */
	duk_debug_do_detach(heap);
#endif

	/* Execute finalizers before freeing the heap, even for reachable
	 * objects.  This gives finalizers the chance to free any native
	 * resources like file handles, allocations made outside Duktape,
	 * etc.  This is quite tricky to get right, so that all finalizer
	 * guarantees are honored.
	 *
	 * Run mark-and-sweep a few times just in case (unreachable object
	 * finalizers run already here).  The last round must rescue objects
	 * from the previous round without running any more finalizers.  This
	 * ensures rescued objects get their FINALIZED flag cleared so that
	 * their finalizer is called once more in forced finalization to
	 * satisfy finalizer guarantees.  However, we don't want to run any
	 * more finalizers because that'd required one more loop, and so on.
	 *
	 * XXX: this perhaps requires an execution time limit.
	 */
	DUK_D(DUK_DPRINT("execute finalizers before freeing heap"));
	DUK_ASSERT(heap->pf_skip_finalizers == 0);
	DUK_D(DUK_DPRINT("forced gc #1 in heap destruction"));
	duk_heap_mark_and_sweep(heap, 0);
	DUK_D(DUK_DPRINT("forced gc #2 in heap destruction"));
	duk_heap_mark_and_sweep(heap, 0);
	DUK_D(DUK_DPRINT("forced gc #3 in heap destruction (don't run finalizers)"));
	heap->pf_skip_finalizers = 1;
	duk_heap_mark_and_sweep(heap, 0);  /* Skip finalizers; queue finalizable objects to heap_allocated. */

	/* There are never objects in refzero_list at this point, or at any
	 * point beyond a DECREF (even a DECREF_NORZ).  Since Duktape 2.1
	 * refzero_list processing is side effect free, so it is always
	 * processed to completion by a DECREF initially triggering a zero
	 * refcount.
	 */
#if defined(DUK_USE_REFERENCE_COUNTING)
	DUK_ASSERT(heap->refzero_list == NULL);  /* Always processed to completion inline. */
#endif
#if defined(DUK_USE_FINALIZER_SUPPORT)
	DUK_ASSERT(heap->finalize_list == NULL);  /* Last mark-and-sweep with skip_finalizers. */
#endif

#if defined(DUK_USE_FINALIZER_SUPPORT)
	DUK_D(DUK_DPRINT("run finalizers for remaining finalizable objects"));
	DUK_HEAP_SET_FINALIZER_NORESCUE(heap);  /* Rescue no longer supported. */
	duk__free_run_finalizers(heap);
#endif  /* DUK_USE_FINALIZER_SUPPORT */

	/* Note: heap->heap_thread, heap->curr_thread, and heap->heap_object
	 * are on the heap allocated list.
	 */

	DUK_D(DUK_DPRINT("freeing temporary freelists"));
	duk_heap_free_freelists(heap);

	DUK_D(DUK_DPRINT("freeing heap_allocated of heap: %p", (void *) heap));
	duk__free_allocated(heap);

#if defined(DUK_USE_REFERENCE_COUNTING)
	DUK_ASSERT(heap->refzero_list == NULL);  /* Always processed to completion inline. */
#endif

#if defined(DUK_USE_FINALIZER_SUPPORT)
	DUK_D(DUK_DPRINT("freeing finalize_list of heap: %p", (void *) heap));
	duk__free_finalize_list(heap);
#endif

	DUK_D(DUK_DPRINT("freeing string table of heap: %p", (void *) heap));
	duk__free_stringtable(heap);

	DUK_D(DUK_DPRINT("freeing heap structure: %p", (void *) heap));
	heap->free_func(heap->heap_udata, heap);
}

/*
 *  Allocate a heap.
 *
 *  String table is initialized with built-in strings from genbuiltins.py,
 *  either by dynamically creating the strings or by referring to ROM strings.
 */

#if defined(DUK_USE_ROM_STRINGS)
DUK_LOCAL duk_bool_t duk__init_heap_strings(duk_heap *heap) {
#if defined(DUK_USE_ASSERTIONS)
	duk_small_uint_t i;
#endif

	DUK_UNREF(heap);

	/* With ROM-based strings, heap->strs[] and thr->strs[] are omitted
	 * so nothing to initialize for strs[].
	 */

#if defined(DUK_USE_ASSERTIONS)
	for (i = 0; i < sizeof(duk_rom_strings_lookup) / sizeof(const duk_hstring *); i++) {
		const duk_hstring *h;
		duk_uint32_t hash;

		h = duk_rom_strings_lookup[i];
		while (h != NULL) {
			hash = duk_heap_hashstring(heap, (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
			DUK_DD(DUK_DDPRINT("duk_rom_strings_lookup[%d] -> hash 0x%08lx, computed 0x%08lx",
			                   (int) i, (unsigned long) DUK_HSTRING_GET_HASH(h), (unsigned long) hash));
			DUK_ASSERT(hash == (duk_uint32_t) DUK_HSTRING_GET_HASH(h));

			h = (const duk_hstring *) h->hdr.h_next;
		}
	}
#endif
	return 1;
}
#else  /* DUK_USE_ROM_STRINGS */

DUK_LOCAL duk_bool_t duk__init_heap_strings(duk_heap *heap) {
	duk_bitdecoder_ctx bd_ctx;
	duk_bitdecoder_ctx *bd = &bd_ctx;  /* convenience */
	duk_small_uint_t i;

	duk_memzero(&bd_ctx, sizeof(bd_ctx));
	bd->data = (const duk_uint8_t *) duk_strings_data;
	bd->length = (duk_size_t) DUK_STRDATA_DATA_LENGTH;

	for (i = 0; i < DUK_HEAP_NUM_STRINGS; i++) {
		duk_uint8_t tmp[DUK_STRDATA_MAX_STRLEN];
		duk_small_uint_t len;
		duk_hstring *h;

		len = duk_bd_decode_bitpacked_string(bd, tmp);

		/* No need to length check string: it will never exceed even
		 * the 16-bit length maximum.
		 */
		DUK_ASSERT(len <= 0xffffUL);
		DUK_DDD(DUK_DDDPRINT("intern built-in string %ld", (long) i));
		h = duk_heap_strtable_intern(heap, tmp, len);
		if (!h) {
			goto failed;
		}
		DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h));

		/* Special flags checks.  Since these strings are always
		 * reachable and a string cannot appear twice in the string
		 * table, there's no need to check/set these flags elsewhere.
		 * The 'internal' flag is set by string intern code.
		 */
		if (i == DUK_STRIDX_EVAL || i == DUK_STRIDX_LC_ARGUMENTS) {
			DUK_HSTRING_SET_EVAL_OR_ARGUMENTS(h);
		}
		if (i >= DUK_STRIDX_START_RESERVED && i < DUK_STRIDX_END_RESERVED) {
			DUK_HSTRING_SET_RESERVED_WORD(h);
			if (i >= DUK_STRIDX_START_STRICT_RESERVED) {
				DUK_HSTRING_SET_STRICT_RESERVED_WORD(h);
			}
		}

		DUK_DDD(DUK_DDDPRINT("interned: %!O", (duk_heaphdr *) h));

		/* XXX: The incref macro takes a thread pointer but doesn't
		 * use it right now.
		 */
		DUK_HSTRING_INCREF(_never_referenced_, h);

#if defined(DUK_USE_HEAPPTR16)
		heap->strs16[i] = DUK_USE_HEAPPTR_ENC16(heap->heap_udata, (void *) h);
#else
		heap->strs[i] = h;
#endif
	}

	return 1;

 failed:
	return 0;
}
#endif  /* DUK_USE_ROM_STRINGS */

DUK_LOCAL duk_bool_t duk__init_heap_thread(duk_heap *heap) {
	duk_hthread *thr;

	DUK_D(DUK_DPRINT("heap init: alloc heap thread"));
	thr = duk_hthread_alloc_unchecked(heap,
	                                  DUK_HOBJECT_FLAG_EXTENSIBLE |
	                                  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_THREAD));
	if (thr == NULL) {
		DUK_D(DUK_DPRINT("failed to alloc heap_thread"));
		return 0;
	}
	thr->state = DUK_HTHREAD_STATE_INACTIVE;
#if defined(DUK_USE_ROM_STRINGS)
	/* No strs[] pointer. */
#else  /* DUK_USE_ROM_STRINGS */
#if defined(DUK_USE_HEAPPTR16)
	thr->strs16 = heap->strs16;
#else
	thr->strs = heap->strs;
#endif
#endif  /* DUK_USE_ROM_STRINGS */

	heap->heap_thread = thr;
	DUK_HTHREAD_INCREF(thr, thr);  /* Note: first argument not really used */

	/* 'thr' is now reachable */

	DUK_D(DUK_DPRINT("heap init: init heap thread stacks"));
	if (!duk_hthread_init_stacks(heap, thr)) {
		return 0;
	}

	/* XXX: this may now fail, and is not handled correctly */
	duk_hthread_create_builtin_objects(thr);

	/* default prototype */
	DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) thr, thr->builtins[DUK_BIDX_THREAD_PROTOTYPE]);

	return 1;
}

#if defined(DUK_USE_DEBUG)
#define DUK__DUMPSZ(t)  do { \
		DUK_D(DUK_DPRINT("" #t "=%ld", (long) sizeof(t))); \
	} while (0)

/* These is not 100% because format would need to be non-portable "long long".
 * Also print out as doubles to catch cases where the "long" type is not wide
 * enough; the limits will then not be printed accurately but the magnitude
 * will be correct.
 */
#define DUK__DUMPLM_SIGNED_RAW(t,a,b)  do { \
		DUK_D(DUK_DPRINT(t "=[%ld,%ld]=[%lf,%lf]", \
		                 (long) (a), (long) (b), \
		                 (double) (a), (double) (b))); \
	} while (0)
#define DUK__DUMPLM_UNSIGNED_RAW(t,a,b)  do { \
		DUK_D(DUK_DPRINT(t "=[%lu,%lu]=[%lf,%lf]", \
		                 (unsigned long) (a), (unsigned long) (b), \
		                 (double) (a), (double) (b))); \
	} while (0)
#define DUK__DUMPLM_SIGNED(t)  do { \
		DUK__DUMPLM_SIGNED_RAW("DUK_" #t "_{MIN,MAX}", DUK_##t##_MIN, DUK_##t##_MAX); \
	} while (0)
#define DUK__DUMPLM_UNSIGNED(t)  do { \
		DUK__DUMPLM_UNSIGNED_RAW("DUK_" #t "_{MIN,MAX}", DUK_##t##_MIN, DUK_##t##_MAX); \
	} while (0)

DUK_LOCAL void duk__dump_type_sizes(void) {
	DUK_D(DUK_DPRINT("sizeof()"));

	/* basic platform types */
	DUK__DUMPSZ(char);
	DUK__DUMPSZ(short);
	DUK__DUMPSZ(int);
	DUK__DUMPSZ(long);
	DUK__DUMPSZ(double);
	DUK__DUMPSZ(void *);
	DUK__DUMPSZ(size_t);

	/* basic types from duk_features.h */
	DUK__DUMPSZ(duk_uint8_t);
	DUK__DUMPSZ(duk_int8_t);
	DUK__DUMPSZ(duk_uint16_t);
	DUK__DUMPSZ(duk_int16_t);
	DUK__DUMPSZ(duk_uint32_t);
	DUK__DUMPSZ(duk_int32_t);
	DUK__DUMPSZ(duk_uint64_t);
	DUK__DUMPSZ(duk_int64_t);
	DUK__DUMPSZ(duk_uint_least8_t);
	DUK__DUMPSZ(duk_int_least8_t);
	DUK__DUMPSZ(duk_uint_least16_t);
	DUK__DUMPSZ(duk_int_least16_t);
	DUK__DUMPSZ(duk_uint_least32_t);
	DUK__DUMPSZ(duk_int_least32_t);
#if defined(DUK_USE_64BIT_OPS)
	DUK__DUMPSZ(duk_uint_least64_t);
	DUK__DUMPSZ(duk_int_least64_t);
#endif
	DUK__DUMPSZ(duk_uint_fast8_t);
	DUK__DUMPSZ(duk_int_fast8_t);
	DUK__DUMPSZ(duk_uint_fast16_t);
	DUK__DUMPSZ(duk_int_fast16_t);
	DUK__DUMPSZ(duk_uint_fast32_t);
	DUK__DUMPSZ(duk_int_fast32_t);
#if defined(DUK_USE_64BIT_OPS)
	DUK__DUMPSZ(duk_uint_fast64_t);
	DUK__DUMPSZ(duk_int_fast64_t);
#endif
	DUK__DUMPSZ(duk_uintptr_t);
	DUK__DUMPSZ(duk_intptr_t);
	DUK__DUMPSZ(duk_uintmax_t);
	DUK__DUMPSZ(duk_intmax_t);
	DUK__DUMPSZ(duk_double_t);

	/* important chosen base types */
	DUK__DUMPSZ(duk_int_t);
	DUK__DUMPSZ(duk_uint_t);
	DUK__DUMPSZ(duk_int_fast_t);
	DUK__DUMPSZ(duk_uint_fast_t);
	DUK__DUMPSZ(duk_small_int_t);
	DUK__DUMPSZ(duk_small_uint_t);
	DUK__DUMPSZ(duk_small_int_fast_t);
	DUK__DUMPSZ(duk_small_uint_fast_t);

	/* some derived types */
	DUK__DUMPSZ(duk_codepoint_t);
	DUK__DUMPSZ(duk_ucodepoint_t);
	DUK__DUMPSZ(duk_idx_t);
	DUK__DUMPSZ(duk_errcode_t);
	DUK__DUMPSZ(duk_uarridx_t);

	/* tval */
	DUK__DUMPSZ(duk_double_union);
	DUK__DUMPSZ(duk_tval);

	/* structs from duk_forwdecl.h */
	DUK__DUMPSZ(duk_jmpbuf);  /* just one 'int' for C++ exceptions */
	DUK__DUMPSZ(duk_heaphdr);
	DUK__DUMPSZ(duk_heaphdr_string);
	DUK__DUMPSZ(duk_hstring);
	DUK__DUMPSZ(duk_hstring_external);
	DUK__DUMPSZ(duk_hobject);
	DUK__DUMPSZ(duk_harray);
	DUK__DUMPSZ(duk_hcompfunc);
	DUK__DUMPSZ(duk_hnatfunc);
	DUK__DUMPSZ(duk_hdecenv);
	DUK__DUMPSZ(duk_hobjenv);
	DUK__DUMPSZ(duk_hthread);
#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
	DUK__DUMPSZ(duk_hbufobj);
#endif
	DUK__DUMPSZ(duk_hproxy);
	DUK__DUMPSZ(duk_hbuffer);
	DUK__DUMPSZ(duk_hbuffer_fixed);
	DUK__DUMPSZ(duk_hbuffer_dynamic);
	DUK__DUMPSZ(duk_hbuffer_external);
	DUK__DUMPSZ(duk_propaccessor);
	DUK__DUMPSZ(duk_propvalue);
	DUK__DUMPSZ(duk_propdesc);
	DUK__DUMPSZ(duk_heap);
	DUK__DUMPSZ(duk_activation);
	DUK__DUMPSZ(duk_catcher);
	DUK__DUMPSZ(duk_strcache_entry);
	DUK__DUMPSZ(duk_litcache_entry);
	DUK__DUMPSZ(duk_ljstate);
	DUK__DUMPSZ(duk_fixedbuffer);
	DUK__DUMPSZ(duk_bitdecoder_ctx);
	DUK__DUMPSZ(duk_bitencoder_ctx);
	DUK__DUMPSZ(duk_token);
	DUK__DUMPSZ(duk_re_token);
	DUK__DUMPSZ(duk_lexer_point);
	DUK__DUMPSZ(duk_lexer_ctx);
	DUK__DUMPSZ(duk_compiler_instr);
	DUK__DUMPSZ(duk_compiler_func);
	DUK__DUMPSZ(duk_compiler_ctx);
	DUK__DUMPSZ(duk_re_matcher_ctx);
	DUK__DUMPSZ(duk_re_compiler_ctx);
}
DUK_LOCAL void duk__dump_type_limits(void) {
	DUK_D(DUK_DPRINT("limits"));

	/* basic types */
	DUK__DUMPLM_SIGNED(INT8);
	DUK__DUMPLM_UNSIGNED(UINT8);
	DUK__DUMPLM_SIGNED(INT_FAST8);
	DUK__DUMPLM_UNSIGNED(UINT_FAST8);
	DUK__DUMPLM_SIGNED(INT_LEAST8);
	DUK__DUMPLM_UNSIGNED(UINT_LEAST8);
	DUK__DUMPLM_SIGNED(INT16);
	DUK__DUMPLM_UNSIGNED(UINT16);
	DUK__DUMPLM_SIGNED(INT_FAST16);
	DUK__DUMPLM_UNSIGNED(UINT_FAST16);
	DUK__DUMPLM_SIGNED(INT_LEAST16);
	DUK__DUMPLM_UNSIGNED(UINT_LEAST16);
	DUK__DUMPLM_SIGNED(INT32);
	DUK__DUMPLM_UNSIGNED(UINT32);
	DUK__DUMPLM_SIGNED(INT_FAST32);
	DUK__DUMPLM_UNSIGNED(UINT_FAST32);
	DUK__DUMPLM_SIGNED(INT_LEAST32);
	DUK__DUMPLM_UNSIGNED(UINT_LEAST32);
#if defined(DUK_USE_64BIT_OPS)
	DUK__DUMPLM_SIGNED(INT64);
	DUK__DUMPLM_UNSIGNED(UINT64);
	DUK__DUMPLM_SIGNED(INT_FAST64);
	DUK__DUMPLM_UNSIGNED(UINT_FAST64);
	DUK__DUMPLM_SIGNED(INT_LEAST64);
	DUK__DUMPLM_UNSIGNED(UINT_LEAST64);
#endif
	DUK__DUMPLM_SIGNED(INTPTR);
	DUK__DUMPLM_UNSIGNED(UINTPTR);
	DUK__DUMPLM_SIGNED(INTMAX);
	DUK__DUMPLM_UNSIGNED(UINTMAX);

	/* derived types */
	DUK__DUMPLM_SIGNED(INT);
	DUK__DUMPLM_UNSIGNED(UINT);
	DUK__DUMPLM_SIGNED(INT_FAST);
	DUK__DUMPLM_UNSIGNED(UINT_FAST);
	DUK__DUMPLM_SIGNED(SMALL_INT);
	DUK__DUMPLM_UNSIGNED(SMALL_UINT);
	DUK__DUMPLM_SIGNED(SMALL_INT_FAST);
	DUK__DUMPLM_UNSIGNED(SMALL_UINT_FAST);
}

DUK_LOCAL void duk__dump_misc_options(void) {
	DUK_D(DUK_DPRINT("DUK_VERSION: %ld", (long) DUK_VERSION));
	DUK_D(DUK_DPRINT("DUK_GIT_DESCRIBE: %s", DUK_GIT_DESCRIBE));
	DUK_D(DUK_DPRINT("OS string: %s", DUK_USE_OS_STRING));
	DUK_D(DUK_DPRINT("architecture string: %s", DUK_USE_ARCH_STRING));
	DUK_D(DUK_DPRINT("compiler string: %s", DUK_USE_COMPILER_STRING));
	DUK_D(DUK_DPRINT("debug level: %ld", (long) DUK_USE_DEBUG_LEVEL));
#if defined(DUK_USE_PACKED_TVAL)
	DUK_D(DUK_DPRINT("DUK_USE_PACKED_TVAL: yes"));
#else
	DUK_D(DUK_DPRINT("DUK_USE_PACKED_TVAL: no"));
#endif
#if defined(DUK_USE_VARIADIC_MACROS)
	DUK_D(DUK_DPRINT("DUK_USE_VARIADIC_MACROS: yes"));
#else
	DUK_D(DUK_DPRINT("DUK_USE_VARIADIC_MACROS: no"));
#endif
#if defined(DUK_USE_INTEGER_LE)
	DUK_D(DUK_DPRINT("integer endianness: little"));
#elif defined(DUK_USE_INTEGER_ME)
	DUK_D(DUK_DPRINT("integer endianness: mixed"));
#elif defined(DUK_USE_INTEGER_BE)
	DUK_D(DUK_DPRINT("integer endianness: big"));
#else
	DUK_D(DUK_DPRINT("integer endianness: ???"));
#endif
#if defined(DUK_USE_DOUBLE_LE)
	DUK_D(DUK_DPRINT("IEEE double endianness: little"));
#elif defined(DUK_USE_DOUBLE_ME)
	DUK_D(DUK_DPRINT("IEEE double endianness: mixed"));
#elif defined(DUK_USE_DOUBLE_BE)
	DUK_D(DUK_DPRINT("IEEE double endianness: big"));
#else
	DUK_D(DUK_DPRINT("IEEE double endianness: ???"));
#endif
}
#endif  /* DUK_USE_DEBUG */

DUK_INTERNAL
duk_heap *duk_heap_alloc(duk_alloc_function alloc_func,
                         duk_realloc_function realloc_func,
                         duk_free_function free_func,
                         void *heap_udata,
                         duk_fatal_function fatal_func) {
	duk_heap *res = NULL;
	duk_uint32_t st_initsize;

	DUK_D(DUK_DPRINT("allocate heap"));

	/*
	 *  Random config sanity asserts
	 */

	DUK_ASSERT(DUK_USE_STRTAB_MINSIZE >= 64);

	DUK_ASSERT((DUK_HTYPE_STRING & 0x01U) == 0);
	DUK_ASSERT((DUK_HTYPE_BUFFER & 0x01U) == 0);
	DUK_ASSERT((DUK_HTYPE_OBJECT & 0x01U) == 1);  /* DUK_HEAPHDR_IS_OBJECT() relies ont his. */

	/*
	 *  Debug dump type sizes
	 */

#if defined(DUK_USE_DEBUG)
	duk__dump_misc_options();
	duk__dump_type_sizes();
	duk__dump_type_limits();
#endif

	/*
	 *  If selftests enabled, run them as early as possible.
	 */

#if defined(DUK_USE_SELF_TESTS)
	DUK_D(DUK_DPRINT("run self tests"));
	if (duk_selftest_run_tests(alloc_func, realloc_func, free_func, heap_udata) > 0) {
		fatal_func(heap_udata, "self test(s) failed");
	}
	DUK_D(DUK_DPRINT("self tests passed"));
#endif

	/*
	 *  Important assert-like checks that should be enabled even
	 *  when assertions are otherwise not enabled.
	 */

#if defined(DUK_USE_EXEC_REGCONST_OPTIMIZE)
	/* Can't check sizeof() using preprocessor so explicit check.
	 * This will be optimized away in practice; unfortunately a
	 * warning is generated on some compilers as a result.
	 */
#if defined(DUK_USE_PACKED_TVAL)
	if (sizeof(duk_tval) != 8) {
#else
	if (sizeof(duk_tval) != 16) {
#endif
		fatal_func(heap_udata, "sizeof(duk_tval) not 8 or 16, cannot use DUK_USE_EXEC_REGCONST_OPTIMIZE option");
	}
#endif  /* DUK_USE_EXEC_REGCONST_OPTIMIZE */

	/*
	 *  Computed values (e.g. INFINITY)
	 */

#if defined(DUK_USE_COMPUTED_NAN)
	do {
		/* Workaround for some exotic platforms where NAN is missing
		 * and the expression (0.0 / 0.0) does NOT result in a NaN.
		 * Such platforms use the global 'duk_computed_nan' which must
		 * be initialized at runtime.  Use 'volatile' to ensure that
		 * the compiler will actually do the computation and not try
		 * to do constant folding which might result in the original
		 * problem.
		 */
		volatile double dbl1 = 0.0;
		volatile double dbl2 = 0.0;
		duk_computed_nan = dbl1 / dbl2;
	} while (0);
#endif

#if defined(DUK_USE_COMPUTED_INFINITY)
	do {
		/* Similar workaround for INFINITY. */
		volatile double dbl1 = 1.0;
		volatile double dbl2 = 0.0;
		duk_computed_infinity = dbl1 / dbl2;
	} while (0);
#endif

	/*
	 *  Allocate heap struct
	 *
	 *  Use a raw call, all macros expect the heap to be initialized
	 */

#if defined(DUK_USE_INJECT_HEAP_ALLOC_ERROR) && (DUK_USE_INJECT_HEAP_ALLOC_ERROR == 1)
	goto failed;
#endif
	DUK_D(DUK_DPRINT("alloc duk_heap object"));
	res = (duk_heap *) alloc_func(heap_udata, sizeof(duk_heap));
	if (!res) {
		goto failed;
	}

	/*
	 *  Zero the struct, and start initializing roughly in order
	 */

	duk_memzero(res, sizeof(*res));
#if defined(DUK_USE_ASSERTIONS)
	res->heap_initializing = 1;
#endif

	/* explicit NULL inits */
#if defined(DUK_USE_EXPLICIT_NULL_INIT)
	res->heap_udata = NULL;
	res->heap_allocated = NULL;
#if defined(DUK_USE_REFERENCE_COUNTING)
	res->refzero_list = NULL;
#endif
#if defined(DUK_USE_FINALIZER_SUPPORT)
	res->finalize_list = NULL;
#if defined(DUK_USE_ASSERTIONS)
	res->currently_finalizing = NULL;
#endif
#endif
#if defined(DUK_USE_CACHE_ACTIVATION)
	res->activation_free = NULL;
#endif
#if defined(DUK_USE_CACHE_CATCHER)
	res->catcher_free = NULL;
#endif
	res->heap_thread = NULL;
	res->curr_thread = NULL;
	res->heap_object = NULL;
#if defined(DUK_USE_STRTAB_PTRCOMP)
	res->strtable16 = NULL;
#else
	res->strtable = NULL;
#endif
#if defined(DUK_USE_ROM_STRINGS)
	/* no res->strs[] */
#else  /* DUK_USE_ROM_STRINGS */
#if defined(DUK_USE_HEAPPTR16)
	/* res->strs16[] is zeroed and zero decodes to NULL, so no NULL inits. */
#else
	{
		duk_small_uint_t i;
	        for (i = 0; i < DUK_HEAP_NUM_STRINGS; i++) {
			res->strs[i] = NULL;
	        }
	}
#endif
#endif  /* DUK_USE_ROM_STRINGS */
#if defined(DUK_USE_DEBUGGER_SUPPORT)
	res->dbg_read_cb = NULL;
	res->dbg_write_cb = NULL;
	res->dbg_peek_cb = NULL;
	res->dbg_read_flush_cb = NULL;
	res->dbg_write_flush_cb = NULL;
	res->dbg_request_cb = NULL;
	res->dbg_udata = NULL;
	res->dbg_pause_act = NULL;
#endif
#endif  /* DUK_USE_EXPLICIT_NULL_INIT */

	res->alloc_func = alloc_func;
	res->realloc_func = realloc_func;
	res->free_func = free_func;
	res->heap_udata = heap_udata;
	res->fatal_func = fatal_func;

	/* XXX: for now there's a pointer packing zero assumption, i.e.
	 * NULL <=> compressed pointer 0.  If this is removed, may need
	 * to precompute e.g. null16 here.
	 */

	/* res->ms_trigger_counter == 0 -> now causes immediate GC; which is OK */

	/* Prevent mark-and-sweep and finalizer execution until heap is completely
	 * initialized.
	 */
	DUK_ASSERT(res->ms_prevent_count == 0);
	DUK_ASSERT(res->pf_prevent_count == 0);
	res->ms_prevent_count = 1;
	res->pf_prevent_count = 1;
	DUK_ASSERT(res->ms_running == 0);

	res->call_recursion_depth = 0;
	res->call_recursion_limit = DUK_USE_NATIVE_CALL_RECLIMIT;

	/* XXX: use the pointer as a seed for now: mix in time at least */

	/* The casts through duk_uintptr_t is to avoid the following GCC warning:
	 *
	 *   warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
	 *
	 * This still generates a /Wp64 warning on VS2010 when compiling for x86.
	 */
#if defined(DUK_USE_ROM_STRINGS)
	/* XXX: make a common DUK_USE_ option, and allow custom fixed seed? */
	DUK_D(DUK_DPRINT("using rom strings, force heap hash_seed to fixed value 0x%08lx", (long) DUK__FIXED_HASH_SEED));
	res->hash_seed = (duk_uint32_t) DUK__FIXED_HASH_SEED;
#else  /* DUK_USE_ROM_STRINGS */
	res->hash_seed = (duk_uint32_t) (duk_uintptr_t) res;
#if !defined(DUK_USE_STRHASH_DENSE)
	res->hash_seed ^= 5381;  /* Bernstein hash init value is normally 5381; XOR it in in case pointer low bits are 0 */
#endif
#endif  /* DUK_USE_ROM_STRINGS */

#if defined(DUK_USE_EXPLICIT_NULL_INIT)
	res->lj.jmpbuf_ptr = NULL;
#endif
	DUK_ASSERT(res->lj.type == DUK_LJ_TYPE_UNKNOWN);  /* zero */
	DUK_ASSERT(res->lj.iserror == 0);
	DUK_TVAL_SET_UNDEFINED(&res->lj.value1);
	DUK_TVAL_SET_UNDEFINED(&res->lj.value2);

	DUK_ASSERT_LJSTATE_UNSET(res);

	/*
	 *  Init stringtable: fixed variant
	 */

	st_initsize = DUK_USE_STRTAB_MINSIZE;
#if defined(DUK_USE_STRTAB_PTRCOMP)
	res->strtable16 = (duk_uint16_t *) alloc_func(heap_udata, sizeof(duk_uint16_t) * st_initsize);
	if (res->strtable16 == NULL) {
		goto failed;
	}
#else
	res->strtable = (duk_hstring **) alloc_func(heap_udata, sizeof(duk_hstring *) * st_initsize);
	if (res->strtable == NULL) {
		goto failed;
	}
#endif
	res->st_size = st_initsize;
	res->st_mask = st_initsize - 1;
#if (DUK_USE_STRTAB_MINSIZE != DUK_USE_STRTAB_MAXSIZE)
	DUK_ASSERT(res->st_count == 0);
#endif

#if defined(DUK_USE_STRTAB_PTRCOMP)
	/* zero assumption */
	duk_memzero(res->strtable16, sizeof(duk_uint16_t) * st_initsize);
#else
#if defined(DUK_USE_EXPLICIT_NULL_INIT)
	{
		duk_uint32_t i;
	        for (i = 0; i < st_initsize; i++) {
			res->strtable[i] = NULL;
	        }
	}
#else
	duk_memzero(res->strtable, sizeof(duk_hstring *) * st_initsize);
#endif  /* DUK_USE_EXPLICIT_NULL_INIT */
#endif  /* DUK_USE_STRTAB_PTRCOMP */

	/*
	 *  Init stringcache
	 */

#if defined(DUK_USE_EXPLICIT_NULL_INIT)
	{
		duk_uint_t i;
		for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
			res->strcache[i].h = NULL;
		}
	}
#endif

	/*
	 *  Init litcache
	 */
#if defined(DUK_USE_LITCACHE_SIZE)
	DUK_ASSERT(DUK_USE_LITCACHE_SIZE > 0);
	DUK_ASSERT(DUK_IS_POWER_OF_TWO((duk_uint_t) DUK_USE_LITCACHE_SIZE));
#if defined(DUK_USE_EXPLICIT_NULL_INIT)
	{
		duk_uint_t i;
		for (i = 0; i < DUK_USE_LITCACHE_SIZE; i++) {
			res->litcache[i].addr = NULL;
			res->litcache[i].h = NULL;
		}
	}
#endif
#endif  /* DUK_USE_LITCACHE_SIZE */

	/* XXX: error handling is incomplete.  It would be cleanest if
	 * there was a setjmp catchpoint, so that all init code could
	 * freely throw errors.  If that were the case, the return code
	 * passing here could be removed.
	 */

	/*
	 *  Init built-in strings
	 */

#if defined(DUK_USE_INJECT_HEAP_ALLOC_ERROR) && (DUK_USE_INJECT_HEAP_ALLOC_ERROR == 2)
	goto failed;
#endif
	DUK_D(DUK_DPRINT("heap init: initialize heap strings"));
	if (!duk__init_heap_strings(res)) {
		goto failed;
	}

	/*
	 *  Init the heap thread
	 */

#if defined(DUK_USE_INJECT_HEAP_ALLOC_ERROR) && (DUK_USE_INJECT_HEAP_ALLOC_ERROR == 3)
	goto failed;
#endif
	DUK_D(DUK_DPRINT("heap init: initialize heap thread"));
	if (!duk__init_heap_thread(res)) {
		goto failed;
	}

	/*
	 *  Init the heap object
	 */

#if defined(DUK_USE_INJECT_HEAP_ALLOC_ERROR) && (DUK_USE_INJECT_HEAP_ALLOC_ERROR == 4)
	goto failed;
#endif
	DUK_D(DUK_DPRINT("heap init: initialize heap object"));
	DUK_ASSERT(res->heap_thread != NULL);
	res->heap_object = duk_hobject_alloc_unchecked(res, DUK_HOBJECT_FLAG_EXTENSIBLE |
	                                                    DUK_HOBJECT_FLAG_FASTREFS |
	                                                    DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT));
	if (res->heap_object == NULL) {
		goto failed;
	}
	DUK_HOBJECT_INCREF(res->heap_thread, res->heap_object);

	/*
	 *  Odds and ends depending on the heap thread
	 */

#if !defined(DUK_USE_GET_RANDOM_DOUBLE)
#if defined(DUK_USE_PREFER_SIZE) || !defined(DUK_USE_64BIT_OPS)
	res->rnd_state = (duk_uint32_t) duk_time_get_ecmascript_time(res->heap_thread);
	duk_util_tinyrandom_prepare_seed(res->heap_thread);
#else
	res->rnd_state[0] = (duk_uint64_t) duk_time_get_ecmascript_time(res->heap_thread);
	DUK_ASSERT(res->rnd_state[1] == 0);  /* Not filled here, filled in by seed preparation. */
#if 0  /* Manual test values matching misc/xoroshiro128plus_test.c. */
	res->rnd_state[0] = DUK_U64_CONSTANT(0xdeadbeef12345678);
	res->rnd_state[1] = DUK_U64_CONSTANT(0xcafed00d12345678);
#endif
	duk_util_tinyrandom_prepare_seed(res->heap_thread);
	/* Mix in heap pointer: this ensures that if two Duktape heaps are
	 * created on the same millisecond, they get a different PRNG
	 * sequence (unless e.g. virtual memory addresses cause also the
	 * heap object pointer to be the same).
	 */
	{
		duk_uint64_t tmp_u64;
		tmp_u64 = 0;
		duk_memcpy((void *) &tmp_u64,
		           (const void *) &res,
		           (size_t) (sizeof(void *) >= sizeof(duk_uint64_t) ? sizeof(duk_uint64_t) : sizeof(void *)));
		res->rnd_state[1] ^= tmp_u64;
	}
	do {
		duk_small_uint_t i;
		for (i = 0; i < 10; i++) {
			/* Throw away a few initial random numbers just in
			 * case.  Probably unnecessary due to SplitMix64
			 * preparation.
			 */
			(void) duk_util_tinyrandom_get_double(res->heap_thread);
		}
	} while (0);
#endif
#endif

	/*
	 *  Allow finalizer and mark-and-sweep processing.
	 */

	DUK_D(DUK_DPRINT("heap init: allow finalizer/mark-and-sweep processing"));
	DUK_ASSERT(res->ms_prevent_count == 1);
	DUK_ASSERT(res->pf_prevent_count == 1);
	res->ms_prevent_count = 0;
	res->pf_prevent_count = 0;
	DUK_ASSERT(res->ms_running == 0);
#if defined(DUK_USE_ASSERTIONS)
	res->heap_initializing = 0;
#endif

	/*
	 *  All done.
	 */

	DUK_D(DUK_DPRINT("allocated heap: %p", (void *) res));
	return res;

 failed:
	DUK_D(DUK_DPRINT("heap allocation failed"));

	if (res != NULL) {
		/* Assumes that allocated pointers and alloc funcs are valid
		 * if res exists.
		 */
		DUK_ASSERT(res->ms_prevent_count == 1);
		DUK_ASSERT(res->pf_prevent_count == 1);
		DUK_ASSERT(res->ms_running == 0);
		if (res->heap_thread != NULL) {
			res->ms_prevent_count = 0;
			res->pf_prevent_count = 0;
		}
#if defined(DUK_USE_ASSERTIONS)
		res->heap_initializing = 0;
#endif

		DUK_ASSERT(res->alloc_func != NULL);
		DUK_ASSERT(res->realloc_func != NULL);
		DUK_ASSERT(res->free_func != NULL);
		duk_heap_free(res);
	}

	return NULL;
}

/* automatic undefs */
#undef DUK__DUMPLM_SIGNED
#undef DUK__DUMPLM_SIGNED_RAW
#undef DUK__DUMPLM_UNSIGNED
#undef DUK__DUMPLM_UNSIGNED_RAW
#undef DUK__DUMPSZ
#undef DUK__FIXED_HASH_SEED
#line 1 "duk_heap_finalize.c"
/*
 *  Finalizer handling.
 */

/* #include duk_internal.h -> already included */

#if defined(DUK_USE_FINALIZER_SUPPORT)

/*
 *  Fake torture finalizer.
 */

#if defined(DUK_USE_FINALIZER_TORTURE)
DUK_LOCAL duk_ret_t duk__fake_global_finalizer(duk_hthread *thr) {
	DUK_DD(DUK_DDPRINT("fake global torture finalizer executed"));

	/* Require a lot of stack to force a value stack grow/shrink. */
	duk_require_stack(thr, 100000);

	/* Force a reallocation with pointer change for value stack
	 * to maximize side effects.
	 */
	duk_hthread_valstack_torture_realloc(thr);

	/* Inner function call, error throw. */
	duk_eval_string_noresult(thr,
		"(function dummy() {\n"
		"    dummy.prototype = null;  /* break reference loop */\n"
		"    try {\n"
		"        throw 'fake-finalizer-dummy-error';\n"
		"    } catch (e) {\n"
		"        void e;\n"
		"    }\n"
		"})()");

	/* The above creates garbage (e.g. a function instance).  Because
	 * the function/prototype reference loop is broken, it gets collected
	 * immediately by DECREF.  If Function.prototype has a _Finalizer
	 * property (happens in some test cases), the garbage gets queued to
	 * finalize_list.  This still won't cause an infinite loop because
	 * the torture finalizer is called once per finalize_list run and
	 * the garbage gets handled in the same run.  (If the garbage needs
	 * mark-and-sweep collection, an infinite loop might ensue.)
	 */
	return 0;
}

DUK_LOCAL void duk__run_global_torture_finalizer(duk_hthread *thr) {
	DUK_ASSERT(thr != NULL);

	/* Avoid fake finalization when callstack limit is near.  Otherwise
	 * a callstack limit error will be created, then refzero'ed.  The
	 * +5 headroom is conservative.
	 */
	if (thr->heap->call_recursion_depth + 5 >= thr->heap->call_recursion_limit ||
	    thr->callstack_top + 5 >= DUK_USE_CALLSTACK_LIMIT) {
		DUK_D(DUK_DPRINT("skip global torture finalizer, too little headroom for call recursion or call stack size"));
		return;
	}

	/* Run fake finalizer.  Avoid creating unnecessary garbage. */
	duk_push_c_function(thr, duk__fake_global_finalizer, 0 /*nargs*/);
	(void) duk_pcall(thr, 0 /*nargs*/);
	duk_pop(thr);
}
#endif  /* DUK_USE_FINALIZER_TORTURE */

/*
 *  Process the finalize_list to completion.
 *
 *  An object may be placed on finalize_list by either refcounting or
 *  mark-and-sweep.  The refcount of objects placed by refcounting will be
 *  zero; the refcount of objects placed by mark-and-sweep is > 0.  In both
 *  cases the refcount is bumped by 1 artificially so that a REFZERO event
 *  can never happen while an object is waiting for finalization.  Without
 *  this bump a REFZERO could now happen because user code may call
 *  duk_push_heapptr() and then pop a value even when it's on finalize_list.
 *
 *  List processing assumes refcounts are kept up-to-date at all times, so
 *  that once the finalizer returns, a zero refcount is a reliable reason to
 *  free the object immediately rather than place it back to the heap.  This
 *  is the case because we run outside of refzero_list processing so that
 *  DECREF cascades are handled fully inline.
 *
 *  For mark-and-sweep queued objects (had_zero_refcount false) the object
 *  may be freed immediately if its refcount is zero after the finalizer call
 *  (i.e. finalizer removed the reference loop for the object).  If not, the
 *  next mark-and-sweep will collect the object unless it has become reachable
 *  (i.e. rescued) by that time and its refcount hasn't fallen to zero before
 *  that.  Mark-and-sweep detects these objects because their FINALIZED flag
 *  is set.
 *
 *  There's an inherent limitation for mark-and-sweep finalizer rescuing: an
 *  object won't get refinalized if (1) it's rescued, but (2) becomes
 *  unreachable before mark-and-sweep has had time to notice it.  The next
 *  mark-and-sweep round simply doesn't have any information of whether the
 *  object has been unreachable the whole time or not (the only way to get
 *  that information would be a mark-and-sweep pass for *every finalized
 *  object*).  This is awkward for the application because the mark-and-sweep
 *  round is not generally visible or under full application control.
 *
 *  For refcount queued objects (had_zero_refcount true) the object is either
 *  immediately freed or rescued, and waiting for a mark-and-sweep round is not
 *  necessary (or desirable); FINALIZED is cleared when a rescued object is
 *  queued back to heap_allocated.  The object is eligible for finalization
 *  again (either via refcounting or mark-and-sweep) immediately after being
 *  rescued.  If a refcount finalized object is placed into an unreachable
 *  reference loop by its finalizer, it will get collected by mark-and-sweep
 *  and currently the finalizer will execute again.
 *
 *  There's a special case where:
 *
 *    - Mark-and-sweep queues an object to finalize_list for finalization.
 *    - The finalizer is executed, FINALIZED is set, and object is queued
 *      back to heap_allocated, waiting for a new mark-and-sweep round.
 *    - The object's refcount drops to zero before mark-and-sweep has a
 *      chance to run another round and make a rescue/free decision.
 *
 *  This is now handled by refzero code: if an object has a finalizer but
 *  FINALIZED is already set, the object is freed without finalizer processing.
 *  The outcome is the same as if mark-and-sweep was executed at that point;
 *  mark-and-sweep would also free the object without another finalizer run.
 *  This could also be changed so that the refzero-triggered finalizer *IS*
 *  executed: being refzero collected implies someone has operated on the
 *  object so it hasn't been totally unreachable the whole time.  This would
 *  risk a finalizer loop however.
 */

DUK_INTERNAL void duk_heap_process_finalize_list(duk_heap *heap) {
	duk_heaphdr *curr;
#if defined(DUK_USE_DEBUG)
	duk_size_t count = 0;
#endif

	DUK_DDD(DUK_DDDPRINT("duk_heap_process_finalize_list: %p", (void *) heap));

	if (heap->pf_prevent_count != 0) {
		DUK_DDD(DUK_DDDPRINT("skip finalize_list processing: pf_prevent_count != 0"));
		return;
	}

	/* Heap alloc prevents mark-and-sweep before heap_thread is ready. */
	DUK_ASSERT(heap != NULL);
	DUK_ASSERT(heap->heap_thread != NULL);
	DUK_ASSERT(heap->heap_thread->valstack != NULL);
#if defined(DUK_USE_REFERENCE_COUNTING)
	DUK_ASSERT(heap->refzero_list == NULL);
#endif

	DUK_ASSERT(heap->pf_prevent_count == 0);
	heap->pf_prevent_count = 1;

	/* Mark-and-sweep no longer needs to be prevented when running
	 * finalizers: mark-and-sweep skips any rescue decisions if there
	 * are any objects in finalize_list when mark-and-sweep is entered.
	 * This protects finalized objects from incorrect rescue decisions
	 * caused by finalize_list being a reachability root and only
	 * partially processed.  Freeing decisions are not postponed.
	 */

	/* When finalizer torture is enabled, make a fake finalizer call with
	 * maximum side effects regardless of whether finalize_list is empty.
	 */
#if defined(DUK_USE_FINALIZER_TORTURE)
	duk__run_global_torture_finalizer(heap->heap_thread);
#endif

	/* Process finalize_list until it becomes empty.  There's currently no
	 * protection against a finalizer always creating more garbage.
	 */
	while ((curr = heap->finalize_list) != NULL) {
#if defined(DUK_USE_REFERENCE_COUNTING)
		duk_bool_t queue_back;
#endif

		DUK_DD(DUK_DDPRINT("processing finalize_list entry: %p -> %!iO", (void *) curr, curr));

		DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT);  /* Only objects have finalizers. */
		DUK_ASSERT(!DUK_HEAPHDR_HAS_REACHABLE(curr));
		DUK_ASSERT(!DUK_HEAPHDR_HAS_TEMPROOT(curr));
		DUK_ASSERT(DUK_HEAPHDR_HAS_FINALIZABLE(curr));  /* All objects on finalize_list will have this flag (except object being finalized right now). */
		DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(curr));   /* Queueing code ensures. */
		DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(curr));  /* ROM objects never get freed (or finalized). */

#if defined(DUK_USE_ASSERTIONS)
		DUK_ASSERT(heap->currently_finalizing == NULL);
		heap->currently_finalizing = curr;
#endif

		/* Clear FINALIZABLE for object being finalized, so that
		 * duk_push_heapptr() can properly ignore the object.
		 */
		DUK_HEAPHDR_CLEAR_FINALIZABLE(curr);

		if (DUK_LIKELY(!heap->pf_skip_finalizers)) {
			/* Run the finalizer, duk_heap_run_finalizer() sets
			 * and checks for FINALIZED to prevent the finalizer
			 * from executing multiple times per finalization cycle.
			 * (This safeguard shouldn't be actually needed anymore).
			 */

#if defined(DUK_USE_REFERENCE_COUNTING)
			duk_bool_t had_zero_refcount;
#endif

			/* The object's refcount is >0 throughout so it won't be
			 * refzero processed prematurely.
			 */
#if defined(DUK_USE_REFERENCE_COUNTING)
			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(curr) >= 1);
			had_zero_refcount = (DUK_HEAPHDR_GET_REFCOUNT(curr) == 1);  /* Preincremented on finalize_list insert. */
#endif

			DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(curr));
			duk_heap_run_finalizer(heap, (duk_hobject *) curr);  /* must never longjmp */
			DUK_ASSERT(DUK_HEAPHDR_HAS_FINALIZED(curr));
			/* XXX: assert that object is still in finalize_list
			 * when duk_push_heapptr() allows automatic rescue.
			 */

#if defined(DUK_USE_REFERENCE_COUNTING)
			DUK_DD(DUK_DDPRINT("refcount after finalizer (includes bump): %ld", (long) DUK_HEAPHDR_GET_REFCOUNT(curr)));
			if (DUK_HEAPHDR_GET_REFCOUNT(curr) == 1) {  /* Only artificial bump in refcount? */
#if defined(DUK_USE_DEBUG)
				if (had_zero_refcount) {
					DUK_DD(DUK_DDPRINT("finalized object's refcount is zero -> free immediately (refcount queued)"));
				} else {
					DUK_DD(DUK_DDPRINT("finalized object's refcount is zero -> free immediately (mark-and-sweep queued)"));
				}
#endif
				queue_back = 0;
			} else
#endif
			{
#if defined(DUK_USE_REFERENCE_COUNTING)
				queue_back = 1;
				if (had_zero_refcount) {
					/* When finalization is triggered
					 * by refzero and we queue the object
					 * back, clear FINALIZED right away
					 * so that the object can be refinalized
					 * immediately if necessary.
					 */
					DUK_HEAPHDR_CLEAR_FINALIZED(curr);
				}
#endif
			}
		} else {
			/* Used during heap destruction: don't actually run finalizers
			 * because we're heading into forced finalization.  Instead,
			 * queue finalizable objects back to the heap_allocated list.
			 */
			DUK_D(DUK_DPRINT("skip finalizers flag set, queue object to heap_allocated without finalizing"));
			DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(curr));
#if defined(DUK_USE_REFERENCE_COUNTING)
			queue_back = 1;
#endif
		}

		/* Dequeue object from finalize_list.  Note that 'curr' may no
		 * longer be finalize_list head because new objects may have
		 * been queued to the list.  As a result we can't optimize for
		 * the single-linked heap case and must scan the list for
		 * removal, typically the scan is very short however.
		 */
		DUK_HEAP_REMOVE_FROM_FINALIZE_LIST(heap, curr);

		/* Queue back to heap_allocated or free immediately. */
#if defined(DUK_USE_REFERENCE_COUNTING)
		if (queue_back) {
			/* FINALIZED is only cleared if object originally
			 * queued for finalization by refcounting.  For
			 * mark-and-sweep FINALIZED is left set, so that
			 * next mark-and-sweep round can make a rescue/free
			 * decision.
			 */
			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(curr) >= 1);
			DUK_HEAPHDR_PREDEC_REFCOUNT(curr);  /* Remove artificial refcount bump. */
			DUK_HEAPHDR_CLEAR_FINALIZABLE(curr);
			DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap, curr);
		} else {
			/* No need to remove the refcount bump here. */
			DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT);  /* currently, always the case */
			DUK_DD(DUK_DDPRINT("refcount finalize after finalizer call: %!O", curr));
			duk_hobject_refcount_finalize_norz(heap, (duk_hobject *) curr);
			duk_free_hobject(heap, (duk_hobject *) curr);
			DUK_DD(DUK_DDPRINT("freed hobject after finalization: %p", (void *) curr));
		}
#else  /* DUK_USE_REFERENCE_COUNTING */
		DUK_HEAPHDR_CLEAR_FINALIZABLE(curr);
		DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap, curr);
#endif  /* DUK_USE_REFERENCE_COUNTING */

#if defined(DUK_USE_DEBUG)
		count++;
#endif

#if defined(DUK_USE_ASSERTIONS)
		DUK_ASSERT(heap->currently_finalizing != NULL);
		heap->currently_finalizing = NULL;
#endif
	}

	/* finalize_list will always be processed completely. */
	DUK_ASSERT(heap->finalize_list == NULL);

#if 0
	/* While NORZ macros are used above, this is unnecessary because the
	 * only pending side effects are now finalizers, and finalize_list is
	 * empty.
	 */
	DUK_REFZERO_CHECK_SLOW(heap->heap_thread);
#endif

	/* Prevent count may be bumped while finalizers run, but should always
	 * be reliably unbumped by the time we get here.
	 */
	DUK_ASSERT(heap->pf_prevent_count == 1);
	heap->pf_prevent_count = 0;

#if defined(DUK_USE_DEBUG)
	DUK_DD(DUK_DDPRINT("duk_heap_process_finalize_list: %ld finalizers called", (long) count));
#endif
}

/*
 *  Run an duk_hobject finalizer.  Must never throw an uncaught error
 *  (but may throw caught errors).
 *
 *  There is no return value.  Any return value or error thrown by
 *  the finalizer is ignored (although errors are debug logged).
 *
 *  Notes:
 *
 *    - The finalizer thread 'top' assertions are there because it is
 *      critical that strict stack policy is observed (i.e. no cruft
 *      left on the finalizer stack).
 */

DUK_LOCAL duk_ret_t duk__finalize_helper(duk_hthread *thr, void *udata) {
	DUK_ASSERT(thr != NULL);
	DUK_UNREF(udata);

	DUK_DDD(DUK_DDDPRINT("protected finalization helper running"));

	/* [... obj] */

	/* _Finalizer property is read without checking if the value is
	 * callable or even exists.  This is intentional, and handled
	 * by throwing an error which is caught by the safe call wrapper.
	 *
	 * XXX: Finalizer lookup should traverse the prototype chain (to allow
	 * inherited finalizers) but should not invoke accessors or proxy object
	 * behavior.  At the moment this lookup will invoke proxy behavior, so
	 * caller must ensure that this function is not called if the target is
	 * a Proxy.
	 */
	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_FINALIZER);  /* -> [... obj finalizer] */
	duk_dup_m2(thr);
	duk_push_boolean(thr, DUK_HEAP_HAS_FINALIZER_NORESCUE(thr->heap));
	DUK_DDD(DUK_DDDPRINT("calling finalizer"));
	duk_call(thr, 2);  /* [ ... obj finalizer obj heapDestruct ]  -> [ ... obj retval ] */
	DUK_DDD(DUK_DDDPRINT("finalizer returned successfully"));
	return 0;

	/* Note: we rely on duk_safe_call() to fix up the stack for the caller,
	 * so we don't need to pop stuff here.  There is no return value;
	 * caller determines rescued status based on object refcount.
	 */
}

DUK_INTERNAL void duk_heap_run_finalizer(duk_heap *heap, duk_hobject *obj) {
	duk_hthread *thr;
	duk_ret_t rc;
#if defined(DUK_USE_ASSERTIONS)
	duk_idx_t entry_top;
#endif

	DUK_DD(DUK_DDPRINT("running duk_hobject finalizer for object: %p", (void *) obj));

	DUK_ASSERT(heap != NULL);
	DUK_ASSERT(heap->heap_thread != NULL);
	thr = heap->heap_thread;
	DUK_ASSERT(obj != NULL);
	DUK_ASSERT_VALSTACK_SPACE(heap->heap_thread, 1);

#if defined(DUK_USE_ASSERTIONS)
	entry_top = duk_get_top(thr);
#endif
	/*
	 *  Get and call the finalizer.  All of this must be wrapped
	 *  in a protected call, because even getting the finalizer
	 *  may trigger an error (getter may throw one, for instance).
	 */

	/* ROM objects could inherit a finalizer, but they are never deemed
	 * unreachable by mark-and-sweep, and their refcount never falls to 0.
	 */
	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));

	/* Duktape 2.1: finalize_list never contains objects with FINALIZED
	 * set, so no need to check here.
	 */
	DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) obj));
#if 0
	if (DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) obj)) {
		DUK_D(DUK_DPRINT("object already finalized, avoid running finalizer twice: %!O", obj));
		return;
	}
#endif
	DUK_HEAPHDR_SET_FINALIZED((duk_heaphdr *) obj);  /* ensure never re-entered until rescue cycle complete */

#if defined(DUK_USE_ES6_PROXY)
	if (DUK_HOBJECT_IS_PROXY(obj)) {
		/* This may happen if duk_set_finalizer() or Duktape.fin() is
		 * called for a Proxy object.  In such cases the fast finalizer
		 * flag will be set on the Proxy, not the target, and neither
		 * will be finalized.
		 */
		DUK_D(DUK_DPRINT("object is a Proxy, skip finalizer call"));
		return;
	}
#endif  /* DUK_USE_ES6_PROXY */

	duk_push_hobject(thr, obj);  /* this also increases refcount by one */
	rc = duk_safe_call(thr, duk__finalize_helper, NULL /*udata*/, 0 /*nargs*/, 1 /*nrets*/);  /* -> [... obj retval/error] */
	DUK_ASSERT_TOP(thr, entry_top + 2);  /* duk_safe_call discipline */

	if (rc != DUK_EXEC_SUCCESS) {
		/* Note: we ask for one return value from duk_safe_call to get this
		 * error debugging here.
		 */
		DUK_D(DUK_DPRINT("wrapped finalizer call failed for object %p (ignored); error: %!T",
		                 (void *) obj, (duk_tval *) duk_get_tval(thr, -1)));
	}
	duk_pop_2(thr);  /* -> [...] */

	DUK_ASSERT_TOP(thr, entry_top);
}

#else  /* DUK_USE_FINALIZER_SUPPORT */

/* nothing */

#endif  /* DUK_USE_FINALIZER_SUPPORT */
#line 1 "duk_heap_hashstring.c"
/*
 *  String hash computation (interning).
 *
 *  String hashing is performance critical because a string hash is computed
 *  for all new strings which are candidates to be added to the string table.
 *  However, strings actually added to the string table go through a codepoint
 *  length calculation which dominates performance because it goes through
 *  every byte of the input string (but only for strings added).
 *
 *  The string hash algorithm should be fast, but on the other hand provide
 *  good enough hashes to ensure both string table and object property table
 *  hash tables work reasonably well (i.e., there aren't too many collisions
 *  with real world inputs).  Unless the hash is cryptographic, it's always
 *  possible to craft inputs with maximal hash collisions.
 *
 *  NOTE: The hash algorithms must match tools/dukutil.py:duk_heap_hashstring()
 *  for ROM string support!
 */

/* #include duk_internal.h -> already included */

#if defined(DUK_USE_STRHASH_DENSE)
/* Constants for duk_hashstring(). */
#define DUK__STRHASH_SHORTSTRING   4096L
#define DUK__STRHASH_MEDIUMSTRING  (256L * 1024L)
#define DUK__STRHASH_BLOCKSIZE     256L

DUK_INTERNAL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const duk_uint8_t *str, duk_size_t len) {
	duk_uint32_t hash;

	/* Use Murmurhash2 directly for short strings, and use "block skipping"
	 * for long strings: hash an initial part and then sample the rest of
	 * the string with reasonably sized chunks.  An initial offset for the
	 * sampling is computed based on a hash of the initial part of the string;
	 * this is done to (usually) avoid the case where all long strings have
	 * certain offset ranges which are never sampled.
	 *
	 * Skip should depend on length and bound the total time to roughly
	 * logarithmic.  With current values:
	 *
	 *   1M string => 256 * 241 = 61696 bytes (0.06M) of hashing
	 *   1G string => 256 * 16321 = 4178176 bytes (3.98M) of hashing
	 *
	 * XXX: It would be better to compute the skip offset more "smoothly"
	 * instead of having a few boundary values.
	 */

	/* note: mixing len into seed improves hashing when skipping */
	duk_uint32_t str_seed = heap->hash_seed ^ ((duk_uint32_t) len);

	if (len <= DUK__STRHASH_SHORTSTRING) {
		hash = duk_util_hashbytes(str, len, str_seed);
	} else {
		duk_size_t off;
		duk_size_t skip;

		if (len <= DUK__STRHASH_MEDIUMSTRING) {
			skip = (duk_size_t) (16 * DUK__STRHASH_BLOCKSIZE + DUK__STRHASH_BLOCKSIZE);
		} else {
			skip = (duk_size_t) (256 * DUK__STRHASH_BLOCKSIZE + DUK__STRHASH_BLOCKSIZE);
		}

		hash = duk_util_hashbytes(str, (duk_size_t) DUK__STRHASH_SHORTSTRING, str_seed);
		off = DUK__STRHASH_SHORTSTRING + (skip * (hash % 256)) / 256;

		/* XXX: inefficient loop */
		while (off < len) {
			duk_size_t left = len - off;
			duk_size_t now = (duk_size_t) (left > DUK__STRHASH_BLOCKSIZE ? DUK__STRHASH_BLOCKSIZE : left);
			hash ^= duk_util_hashbytes(str + off, now, str_seed);
			off += skip;
		}
	}

#if defined(DUK_USE_STRHASH16)
	/* Truncate to 16 bits here, so that a computed hash can be compared
	 * against a hash stored in a 16-bit field.
	 */
	hash &= 0x0000ffffUL;
#endif
	return hash;
}
#else  /* DUK_USE_STRHASH_DENSE */
DUK_INTERNAL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const duk_uint8_t *str, duk_size_t len) {
	duk_uint32_t hash;
	duk_size_t step;
	duk_size_t off;

	/* Slightly modified "Bernstein hash" from:
	 *
	 *     http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx
	 *
	 * Modifications: string skipping and reverse direction similar to
	 * Lua 5.1.5, and different hash initializer.
	 *
	 * The reverse direction ensures last byte it always included in the
	 * hash which is a good default as changing parts of the string are
	 * more often in the suffix than in the prefix.
	 */

	hash = heap->hash_seed ^ ((duk_uint32_t) len);  /* Bernstein hash init value is normally 5381 */
	step = (len >> DUK_USE_STRHASH_SKIP_SHIFT) + 1;
	for (off = len; off >= step; off -= step) {
		DUK_ASSERT(off >= 1);  /* off >= step, and step >= 1 */
		hash = (hash * 33) + str[off - 1];
	}

#if defined(DUK_USE_STRHASH16)
	/* Truncate to 16 bits here, so that a computed hash can be compared
	 * against a hash stored in a 16-bit field.
	 */
	hash &= 0x0000ffffUL;
#endif
	return hash;
}
#endif  /* DUK_USE_STRHASH_DENSE */

/* automatic undefs */
#undef DUK__STRHASH_BLOCKSIZE
#undef DUK__STRHASH_MEDIUMSTRING
#undef DUK__STRHASH_SHORTSTRING
#line 1 "duk_heap_markandsweep.c"
/*
 *  Mark-and-sweep garbage collection.
 */

/* #include duk_internal.h -> already included */

DUK_LOCAL_DECL void duk__mark_heaphdr(duk_heap *heap, duk_heaphdr *h);
DUK_LOCAL_DECL void duk__mark_heaphdr_nonnull(duk_heap *heap, duk_heaphdr *h);
DUK_LOCAL_DECL void duk__mark_tval(duk_heap *heap, duk_tval *tv);
DUK_LOCAL_DECL void duk__mark_tvals(duk_heap *heap, duk_tval *tv, duk_idx_t count);

/*
 *  Marking functions for heap types: mark children recursively.
 */

DUK_LOCAL void duk__mark_hstring(duk_heap *heap, duk_hstring *h) {
	DUK_UNREF(heap);
	DUK_UNREF(h);

	DUK_DDD(DUK_DDDPRINT("duk__mark_hstring: %p", (void *) h));
	DUK_ASSERT(h);
	DUK_HSTRING_ASSERT_VALID(h);

	/* nothing to process */
}

DUK_LOCAL void duk__mark_hobject(duk_heap *heap, duk_hobject *h) {
	duk_uint_fast32_t i;

	DUK_DDD(DUK_DDDPRINT("duk__mark_hobject: %p", (void *) h));

	DUK_ASSERT(h);
	DUK_HOBJECT_ASSERT_VALID(h);

	/* XXX: use advancing pointers instead of index macros -> faster and smaller? */

	for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h); i++) {
		duk_hstring *key = DUK_HOBJECT_E_GET_KEY(heap, h, i);
		if (key == NULL) {
			continue;
		}
		duk__mark_heaphdr_nonnull(heap, (duk_heaphdr *) key);
		if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, h, i)) {
			duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.get);
			duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.set);
		} else {
			duk__mark_tval(heap, &DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->v);
		}
	}

	for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(h); i++) {
		duk__mark_tval(heap, DUK_HOBJECT_A_GET_VALUE_PTR(heap, h, i));
	}

	/* Hash part is a 'weak reference' and does not contribute. */

	duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HOBJECT_GET_PROTOTYPE(heap, h));

	/* Fast path for objects which don't have a subclass struct, or have a
	 * subclass struct but nothing that needs marking in the subclass struct.
	 */
	if (DUK_HOBJECT_HAS_FASTREFS(h)) {
		DUK_ASSERT(DUK_HOBJECT_ALLOWS_FASTREFS(h));
		return;
	}
	DUK_ASSERT(DUK_HOBJECT_PROHIBITS_FASTREFS(h));

	/* XXX: reorg, more common first */
	if (DUK_HOBJECT_IS_COMPFUNC(h)) {
		duk_hcompfunc *f = (duk_hcompfunc *) h;
		duk_tval *tv, *tv_end;
		duk_hobject **fn, **fn_end;

		DUK_HCOMPFUNC_ASSERT_VALID(f);

		/* 'data' is reachable through every compiled function which
		 * contains a reference.
		 */

		duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HCOMPFUNC_GET_DATA(heap, f));
		duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HCOMPFUNC_GET_LEXENV(heap, f));
		duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HCOMPFUNC_GET_VARENV(heap, f));

		if (DUK_HCOMPFUNC_GET_DATA(heap, f) != NULL) {
			tv = DUK_HCOMPFUNC_GET_CONSTS_BASE(heap, f);
			tv_end = DUK_HCOMPFUNC_GET_CONSTS_END(heap, f);
			while (tv < tv_end) {
				duk__mark_tval(heap, tv);
				tv++;
			}

			fn = DUK_HCOMPFUNC_GET_FUNCS_BASE(heap, f);
			fn_end = DUK_HCOMPFUNC_GET_FUNCS_END(heap, f);
			while (fn < fn_end) {
				duk__mark_heaphdr_nonnull(heap, (duk_heaphdr *) *fn);
				fn++;
			}
		} else {
			/* May happen in some out-of-memory corner cases. */
			DUK_D(DUK_DPRINT("duk_hcompfunc 'data' is NULL, skipping marking"));
		}
	} else if (DUK_HOBJECT_IS_DECENV(h)) {
		duk_hdecenv *e = (duk_hdecenv *) h;
		DUK_HDECENV_ASSERT_VALID(e);
		duk__mark_heaphdr(heap, (duk_heaphdr *) e->thread);
		duk__mark_heaphdr(heap, (duk_heaphdr *) e->varmap);
	} else if (DUK_HOBJECT_IS_OBJENV(h)) {
		duk_hobjenv *e = (duk_hobjenv *) h;
		DUK_HOBJENV_ASSERT_VALID(e);
		duk__mark_heaphdr_nonnull(heap, (duk_heaphdr *) e->target);
#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
	} else if (DUK_HOBJECT_IS_BUFOBJ(h)) {
		duk_hbufobj *b = (duk_hbufobj *) h;
		DUK_HBUFOBJ_ASSERT_VALID(b);
		duk__mark_heaphdr(heap, (duk_heaphdr *) b->buf);
		duk__mark_heaphdr(heap, (duk_heaphdr *) b->buf_prop);
#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
	} else if (DUK_HOBJECT_IS_BOUNDFUNC(h)) {
		duk_hboundfunc *f = (duk_hboundfunc *) (void *) h;
		DUK_HBOUNDFUNC_ASSERT_VALID(f);
		duk__mark_tval(heap, &f->target);
		duk__mark_tval(heap, &f->this_binding);
		duk__mark_tvals(heap, f->args, f->nargs);
#if defined(DUK_USE_ES6_PROXY)
	} else if (DUK_HOBJECT_IS_PROXY(h)) {
		duk_hproxy *p = (duk_hproxy *) h;
		DUK_HPROXY_ASSERT_VALID(p);
		duk__mark_heaphdr_nonnull(heap, (duk_heaphdr *) p->target);
		duk__mark_heaphdr_nonnull(heap, (duk_heaphdr *) p->handler);
#endif  /* DUK_USE_ES6_PROXY */
	} else if (DUK_HOBJECT_IS_THREAD(h)) {
		duk_hthread *t = (duk_hthread *) h;
		duk_activation *act;
		duk_tval *tv;

		DUK_HTHREAD_ASSERT_VALID(t);

		tv = t->valstack;
		while (tv < t->valstack_top) {
			duk__mark_tval(heap, tv);
			tv++;
		}

		for (act = t->callstack_curr; act != NULL; act = act->parent) {
			duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_ACT_GET_FUNC(act));
			duk__mark_heaphdr(heap, (duk_heaphdr *) act->var_env);
			duk__mark_heaphdr(heap, (duk_heaphdr *) act->lex_env);
#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
			duk__mark_heaphdr(heap, (duk_heaphdr *) act->prev_caller);
#endif
#if 0  /* nothing now */
			for (cat = act->cat; cat != NULL; cat = cat->parent) {
			}
#endif
		}

		duk__mark_heaphdr(heap, (duk_heaphdr *) t->resumer);

		for (i = 0; i < DUK_NUM_BUILTINS; i++) {
			duk__mark_heaphdr(heap, (duk_heaphdr *) t->builtins[i]);
		}
	} else {
		/* We may come here if the object should have a FASTREFS flag
		 * but it's missing for some reason.  Assert for never getting
		 * here; however, other than performance, this is harmless.
		 */
		DUK_D(DUK_DPRINT("missing FASTREFS flag for: %!iO", h));
		DUK_ASSERT(0);
	}
}

/* Mark any duk_heaphdr type.  Recursion tracking happens only here. */
DUK_LOCAL void duk__mark_heaphdr(duk_heap *heap, duk_heaphdr *h) {
	DUK_DDD(DUK_DDDPRINT("duk__mark_heaphdr %p, type %ld",
	                     (void *) h,
	                     (h != NULL ? (long) DUK_HEAPHDR_GET_TYPE(h) : (long) -1)));

	/* XXX: add non-null variant? */
	if (h == NULL) {
		return;
	}

	DUK_HEAPHDR_ASSERT_VALID(h);
	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(h) || DUK_HEAPHDR_HAS_REACHABLE(h));

#if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_REFERENCE_COUNTING)
	if (!DUK_HEAPHDR_HAS_READONLY(h)) {
		h->h_assert_refcount++;  /* Comparison refcount: bump even if already reachable. */
	}
#endif
	if (DUK_HEAPHDR_HAS_REACHABLE(h)) {
		DUK_DDD(DUK_DDDPRINT("already marked reachable, skip"));
		return;
	}
#if defined(DUK_USE_ROM_OBJECTS)
	/* READONLY objects always have REACHABLE set, so the check above
	 * will prevent READONLY objects from being marked here.
	 */
	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(h));
#endif

	DUK_HEAPHDR_SET_REACHABLE(h);

	if (heap->ms_recursion_depth >= DUK_USE_MARK_AND_SWEEP_RECLIMIT) {
		DUK_D(DUK_DPRINT("mark-and-sweep recursion limit reached, marking as temproot: %p", (void *) h));
		DUK_HEAP_SET_MARKANDSWEEP_RECLIMIT_REACHED(heap);
		DUK_HEAPHDR_SET_TEMPROOT(h);
		return;
	}

	heap->ms_recursion_depth++;
	DUK_ASSERT(heap->ms_recursion_depth != 0);  /* Wrap. */

	switch (DUK_HEAPHDR_GET_TYPE(h)) {
	case DUK_HTYPE_STRING:
		duk__mark_hstring(heap, (duk_hstring *) h);
		break;
	case DUK_HTYPE_OBJECT:
		duk__mark_hobject(heap, (duk_hobject *) h);
		break;
	case DUK_HTYPE_BUFFER:
		/* nothing to mark */
		break;
	default:
		DUK_D(DUK_DPRINT("attempt to mark heaphdr %p with invalid htype %ld", (void *) h, (long) DUK_HEAPHDR_GET_TYPE(h)));
		DUK_UNREACHABLE();
	}

	DUK_ASSERT(heap->ms_recursion_depth > 0);
	heap->ms_recursion_depth--;
}

DUK_LOCAL void duk__mark_tval(duk_heap *heap, duk_tval *tv) {
	DUK_DDD(DUK_DDDPRINT("duk__mark_tval %p", (void *) tv));
	if (tv == NULL) {
		return;
	}
	DUK_TVAL_ASSERT_VALID(tv);
	if (DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
		duk_heaphdr *h;
		h = DUK_TVAL_GET_HEAPHDR(tv);
		DUK_ASSERT(h != NULL);
		duk__mark_heaphdr_nonnull(heap, h);
	}
}

DUK_LOCAL void duk__mark_tvals(duk_heap *heap, duk_tval *tv, duk_idx_t count) {
	DUK_ASSERT(count == 0 || tv != NULL);

	while (count-- > 0) {
		DUK_TVAL_ASSERT_VALID(tv);
		if (DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
			duk_heaphdr *h;
			h = DUK_TVAL_GET_HEAPHDR(tv);
			DUK_ASSERT(h != NULL);
			duk__mark_heaphdr_nonnull(heap, h);
		}
		tv++;
	}
}

/* Mark any duk_heaphdr type, caller guarantees a non-NULL pointer. */
DUK_LOCAL void duk__mark_heaphdr_nonnull(duk_heap *heap, duk_heaphdr *h) {
	/* For now, just call the generic handler.  Change when call sites
	 * are changed too.
	 */
	duk__mark_heaphdr(heap, h);
}

/*
 *  Mark the heap.
 */

DUK_LOCAL void duk__mark_roots_heap(duk_heap *heap) {
	duk_small_uint_t i;

	DUK_DD(DUK_DDPRINT("duk__mark_roots_heap: %p", (void *) heap));

	duk__mark_heaphdr(heap, (duk_heaphdr *) heap->heap_thread);
	duk__mark_heaphdr(heap, (duk_heaphdr *) heap->heap_object);

	for (i = 0; i < DUK_HEAP_NUM_STRINGS; i++) {
		duk_hstring *h = DUK_HEAP_GET_STRING(heap, i);
		duk__mark_heaphdr(heap, (duk_heaphdr *) h);
	}

	duk__mark_tval(heap, &heap->lj.value1);
	duk__mark_tval(heap, &heap->lj.value2);

#if defined(DUK_USE_DEBUGGER_SUPPORT)
	for (i = 0; i < heap->dbg_breakpoint_count; i++) {
		duk__mark_heaphdr(heap, (duk_heaphdr *) heap->dbg_breakpoints[i].filename);
	}
#endif
}

/*
 *  Mark unreachable, finalizable objects.
 *
 *  Such objects will be moved aside and their finalizers run later.  They
 *  have to be treated as reachability roots for their properties etc to
 *  remain allocated.  This marking is only done for unreachable values which
 *  would be swept later.
 *
 *  Objects are first marked FINALIZABLE and only then marked as reachability
 *  roots; otherwise circular references might be handled inconsistently.
 */

#if defined(DUK_USE_FINALIZER_SUPPORT)
DUK_LOCAL void duk__mark_finalizable(duk_heap *heap) {
	duk_heaphdr *hdr;
	duk_size_t count_finalizable = 0;

	DUK_DD(DUK_DDPRINT("duk__mark_finalizable: %p", (void *) heap));

	DUK_ASSERT(heap->heap_thread != NULL);

	hdr = heap->heap_allocated;
	while (hdr != NULL) {
		/* A finalizer is looked up from the object and up its
		 * prototype chain (which allows inherited finalizers).
		 * The finalizer is checked for using a duk_hobject flag
		 * which is kept in sync with the presence and callability
		 * of a _Finalizer hidden symbol.
		 */

		if (!DUK_HEAPHDR_HAS_REACHABLE(hdr) &&
		    DUK_HEAPHDR_IS_OBJECT(hdr) &&
		    !DUK_HEAPHDR_HAS_FINALIZED(hdr) &&
		    DUK_HOBJECT_HAS_FINALIZER_FAST(heap, (duk_hobject *) hdr)) {
			/* heaphdr:
			 *  - is not reachable
			 *  - is an object
			 *  - is not a finalized object waiting for rescue/keep decision
			 *  - has a finalizer
			 */

			DUK_DD(DUK_DDPRINT("unreachable heap object will be "
			                   "finalized -> mark as finalizable "
			                   "and treat as a reachability root: %p",
			                   (void *) hdr));
			DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(hdr));
			DUK_HEAPHDR_SET_FINALIZABLE(hdr);
			count_finalizable++;
		}

		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
	}

	if (count_finalizable == 0) {
		return;
	}

	DUK_DD(DUK_DDPRINT("marked %ld heap objects as finalizable, now mark them reachable",
	                   (long) count_finalizable));

	hdr = heap->heap_allocated;
	while (hdr != NULL) {
		if (DUK_HEAPHDR_HAS_FINALIZABLE(hdr)) {
			duk__mark_heaphdr_nonnull(heap, hdr);
		}

		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
	}

	/* Caller will finish the marking process if we hit a recursion limit. */
}
#endif  /* DUK_USE_FINALIZER_SUPPORT */

/*
 *  Mark objects on finalize_list.
 */

#if defined(DUK_USE_FINALIZER_SUPPORT)
DUK_LOCAL void duk__mark_finalize_list(duk_heap *heap) {
	duk_heaphdr *hdr;
#if defined(DUK_USE_DEBUG)
	duk_size_t count_finalize_list = 0;
#endif

	DUK_DD(DUK_DDPRINT("duk__mark_finalize_list: %p", (void *) heap));

	hdr = heap->finalize_list;
	while (hdr != NULL) {
		duk__mark_heaphdr_nonnull(heap, hdr);
		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
#if defined(DUK_USE_DEBUG)
		count_finalize_list++;
#endif
	}

#if defined(DUK_USE_DEBUG)
	if (count_finalize_list > 0) {
		DUK_D(DUK_DPRINT("marked %ld objects on the finalize_list as reachable (previous finalizer run skipped)",
		                 (long) count_finalize_list));
	}
#endif
}
#endif  /* DUK_USE_FINALIZER_SUPPORT */

/*
 *  Fallback marking handler if recursion limit is reached.
 *
 *  Iterates 'temproots' until recursion limit is no longer hit.  Temproots
 *  can be in heap_allocated or finalize_list; refzero_list is now always
 *  empty for mark-and-sweep.  A temproot may occur in finalize_list now if
 *  there are objects on the finalize_list and user code creates a reference
 *  from an object in heap_allocated to the object in finalize_list (which is
 *  now allowed), and it happened to coincide with the recursion depth limit.
 *
 *  This is a slow scan, but guarantees that we finish with a bounded C stack.
 *
 *  Note that nodes may have been marked as temproots before this scan begun,
 *  OR they may have been marked during the scan (as we process nodes
 *  recursively also during the scan).  This is intended behavior.
 */

#if defined(DUK_USE_DEBUG)
DUK_LOCAL void duk__handle_temproot(duk_heap *heap, duk_heaphdr *hdr, duk_size_t *count) {
#else
DUK_LOCAL void duk__handle_temproot(duk_heap *heap, duk_heaphdr *hdr) {
#endif
	DUK_ASSERT(hdr != NULL);

	if (!DUK_HEAPHDR_HAS_TEMPROOT(hdr)) {
		DUK_DDD(DUK_DDDPRINT("not a temp root: %p", (void *) hdr));
		return;
	}

	DUK_DDD(DUK_DDDPRINT("found a temp root: %p", (void *) hdr));
	DUK_HEAPHDR_CLEAR_TEMPROOT(hdr);
	DUK_HEAPHDR_CLEAR_REACHABLE(hdr);  /* Done so that duk__mark_heaphdr() works correctly. */
#if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_REFERENCE_COUNTING)
	hdr->h_assert_refcount--;  /* Same node visited twice. */
#endif
	duk__mark_heaphdr_nonnull(heap, hdr);

#if defined(DUK_USE_DEBUG)
	(*count)++;
#endif
}

DUK_LOCAL void duk__mark_temproots_by_heap_scan(duk_heap *heap) {
	duk_heaphdr *hdr;
#if defined(DUK_USE_DEBUG)
	duk_size_t count;
#endif

	DUK_DD(DUK_DDPRINT("duk__mark_temproots_by_heap_scan: %p", (void *) heap));

	while (DUK_HEAP_HAS_MARKANDSWEEP_RECLIMIT_REACHED(heap)) {
		DUK_DD(DUK_DDPRINT("recursion limit reached, doing heap scan to continue from temproots"));

#if defined(DUK_USE_DEBUG)
		count = 0;
#endif
		DUK_HEAP_CLEAR_MARKANDSWEEP_RECLIMIT_REACHED(heap);

		hdr = heap->heap_allocated;
		while (hdr) {
#if defined(DUK_USE_DEBUG)
			duk__handle_temproot(heap, hdr, &count);
#else
			duk__handle_temproot(heap, hdr);
#endif
			hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
		}

#if defined(DUK_USE_FINALIZER_SUPPORT)
		hdr = heap->finalize_list;
		while (hdr) {
#if defined(DUK_USE_DEBUG)
			duk__handle_temproot(heap, hdr, &count);
#else
			duk__handle_temproot(heap, hdr);
#endif
			hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
		}
#endif

#if defined(DUK_USE_DEBUG)
		DUK_DD(DUK_DDPRINT("temproot mark heap scan processed %ld temp roots", (long) count));
#endif
	}
}

/*
 *  Finalize refcounts for heap elements just about to be freed.
 *  This must be done for all objects before freeing to avoid any
 *  stale pointer dereferences.
 *
 *  Note that this must deduce the set of objects to be freed
 *  identically to duk__sweep_heap().
 */

#if defined(DUK_USE_REFERENCE_COUNTING)
DUK_LOCAL void duk__finalize_refcounts(duk_heap *heap) {
	duk_heaphdr *hdr;

	DUK_ASSERT(heap->heap_thread != NULL);

	DUK_DD(DUK_DDPRINT("duk__finalize_refcounts: heap=%p", (void *) heap));

	hdr = heap->heap_allocated;
	while (hdr) {
		if (!DUK_HEAPHDR_HAS_REACHABLE(hdr)) {
			/*
			 *  Unreachable object about to be swept.  Finalize target refcounts
			 *  (objects which the unreachable object points to) without doing
			 *  refzero processing.  Recursive decrefs are also prevented when
			 *  refzero processing is disabled.
			 *
			 *  Value cannot be a finalizable object, as they have been made
			 *  temporarily reachable for this round.
			 */

			DUK_DDD(DUK_DDDPRINT("unreachable object, refcount finalize before sweeping: %p", (void *) hdr));

			/* Finalize using heap->heap_thread; DECREF has a
			 * suppress check for mark-and-sweep which is based
			 * on heap->ms_running.
			 */
			duk_heaphdr_refcount_finalize_norz(heap, hdr);
		}

		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
	}
}
#endif  /* DUK_USE_REFERENCE_COUNTING */

/*
 *  Clear (reachable) flags of finalize_list.
 *
 *  We could mostly do in the sweep phase when we move objects from the
 *  heap into the finalize_list.  However, if a finalizer run is skipped
 *  during a mark-and-sweep, the objects on the finalize_list will be marked
 *  reachable during the next mark-and-sweep.  Since they're already on the
 *  finalize_list, no-one will be clearing their REACHABLE flag so we do it
 *  here.  (This now overlaps with the sweep handling in a harmless way.)
 */

#if defined(DUK_USE_FINALIZER_SUPPORT)
DUK_LOCAL void duk__clear_finalize_list_flags(duk_heap *heap) {
	duk_heaphdr *hdr;

	DUK_DD(DUK_DDPRINT("duk__clear_finalize_list_flags: %p", (void *) heap));

	hdr = heap->finalize_list;
	while (hdr) {
		DUK_HEAPHDR_CLEAR_REACHABLE(hdr);
#if defined(DUK_USE_ASSERTIONS)
		DUK_ASSERT(DUK_HEAPHDR_HAS_FINALIZABLE(hdr) || \
		           (heap->currently_finalizing == hdr));
#endif
		/* DUK_HEAPHDR_FLAG_FINALIZED may be set. */
		DUK_ASSERT(!DUK_HEAPHDR_HAS_TEMPROOT(hdr));
		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
	}
}
#endif  /* DUK_USE_FINALIZER_SUPPORT */

/*
 *  Sweep stringtable.
 */

DUK_LOCAL void duk__sweep_stringtable(duk_heap *heap, duk_size_t *out_count_keep) {
	duk_hstring *h;
	duk_hstring *prev;
	duk_uint32_t i;
#if defined(DUK_USE_DEBUG)
	duk_size_t count_free = 0;
#endif
	duk_size_t count_keep = 0;

	DUK_DD(DUK_DDPRINT("duk__sweep_stringtable: %p", (void *) heap));

#if defined(DUK_USE_STRTAB_PTRCOMP)
	if (heap->strtable16 == NULL) {
#else
	if (heap->strtable == NULL) {
#endif
		goto done;
	}

	for (i = 0; i < heap->st_size; i++) {
#if defined(DUK_USE_STRTAB_PTRCOMP)
		h = DUK_USE_HEAPPTR_DEC16(heap->heap_udata, heap->strtable16[i]);
#else
		h = heap->strtable[i];
#endif
		prev = NULL;
		while (h != NULL) {
			duk_hstring *next;
			next = h->hdr.h_next;

			if (DUK_HEAPHDR_HAS_REACHABLE((duk_heaphdr *) h))
			{
				DUK_HEAPHDR_CLEAR_REACHABLE((duk_heaphdr *) h);
				count_keep++;
				prev = h;
			} else {
#if defined(DUK_USE_DEBUG)
				count_free++;
#endif

				/* For pinned strings the refcount has been
				 * bumped.  We could unbump it here before
				 * freeing, but that's actually not necessary
				 * except for assertions.
				 */
#if 0
				if (DUK_HSTRING_HAS_PINNED_LITERAL(h)) {
					DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) > 0U);
					DUK_HSTRING_DECREF_NORZ(heap->heap_thread, h);
					DUK_HSTRING_CLEAR_PINNED_LITERAL(h);
				}
#endif
#if defined(DUK_USE_REFERENCE_COUNTING)
				/* Non-zero refcounts should not happen for unreachable strings,
				 * because we refcount finalize all unreachable objects which
				 * should have decreased unreachable string refcounts to zero
				 * (even for cycles).  However, pinned strings have a +1 bump.
				 */
				DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) ==
				           DUK_HSTRING_HAS_PINNED_LITERAL(h) ? 1U : 0U);
#endif

				/* Deal with weak references first. */
				duk_heap_strcache_string_remove(heap, (duk_hstring *) h);

				/* Remove the string from the string table. */
				duk_heap_strtable_unlink_prev(heap, (duk_hstring *) h, (duk_hstring *) prev);

				/* Free inner references (these exist e.g. when external
				 * strings are enabled) and the struct itself.
				 */
				duk_free_hstring(heap, (duk_hstring *) h);

				/* Don't update 'prev'; it should be last string kept. */
			}

			h = next;
		}
	}

 done:
#if defined(DUK_USE_DEBUG)
	DUK_D(DUK_DPRINT("mark-and-sweep sweep stringtable: %ld freed, %ld kept",
	                 (long) count_free, (long) count_keep));
#endif
	*out_count_keep = count_keep;
}

/*
 *  Sweep heap.
 */

DUK_LOCAL void duk__sweep_heap(duk_heap *heap, duk_small_uint_t flags, duk_size_t *out_count_keep) {
	duk_heaphdr *prev;  /* last element that was left in the heap */
	duk_heaphdr *curr;
	duk_heaphdr *next;
#if defined(DUK_USE_DEBUG)
	duk_size_t count_free = 0;
	duk_size_t count_finalize = 0;
	duk_size_t count_rescue = 0;
#endif
	duk_size_t count_keep = 0;

	DUK_DD(DUK_DDPRINT("duk__sweep_heap: %p", (void *) heap));

	prev = NULL;
	curr = heap->heap_allocated;
	heap->heap_allocated = NULL;
	while (curr) {
		/* Strings and ROM objects are never placed on the heap allocated list. */
		DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) != DUK_HTYPE_STRING);
		DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(curr));

		next = DUK_HEAPHDR_GET_NEXT(heap, curr);

		if (DUK_HEAPHDR_HAS_REACHABLE(curr)) {
			/*
			 *  Reachable object:
			 *    - If FINALIZABLE -> actually unreachable (but marked
			 *      artificially reachable), queue to finalize_list.
			 *    - If !FINALIZABLE but FINALIZED -> rescued after
			 *      finalizer execution.
			 *    - Otherwise just a normal, reachable object.
			 *
			 *  Objects which are kept are queued to heap_allocated
			 *  tail (we're essentially filtering heap_allocated in
			 *  practice).
			 */

#if defined(DUK_USE_FINALIZER_SUPPORT)
			if (DUK_UNLIKELY(DUK_HEAPHDR_HAS_FINALIZABLE(curr))) {
				DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(curr));
				DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT);
				DUK_DD(DUK_DDPRINT("sweep; reachable, finalizable --> move to finalize_list: %p", (void *) curr));

#if defined(DUK_USE_REFERENCE_COUNTING)
				DUK_HEAPHDR_PREINC_REFCOUNT(curr);  /* Bump refcount so that refzero never occurs when pending a finalizer call. */
#endif
				DUK_HEAP_INSERT_INTO_FINALIZE_LIST(heap, curr);
#if defined(DUK_USE_DEBUG)
				count_finalize++;
#endif
			}
			else
#endif  /* DUK_USE_FINALIZER_SUPPORT */
			{
				if (DUK_UNLIKELY(DUK_HEAPHDR_HAS_FINALIZED(curr))) {
					DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(curr));
					DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT);

					if (flags & DUK_MS_FLAG_POSTPONE_RESCUE) {
						DUK_DD(DUK_DDPRINT("sweep; reachable, finalized, but postponing rescue decisions --> keep object (with FINALIZED set): %!iO", curr));
						count_keep++;
					} else {
						DUK_DD(DUK_DDPRINT("sweep; reachable, finalized --> rescued after finalization: %p", (void *) curr));
#if defined(DUK_USE_FINALIZER_SUPPORT)
						DUK_HEAPHDR_CLEAR_FINALIZED(curr);
#endif
#if defined(DUK_USE_DEBUG)
						count_rescue++;
#endif
					}
				} else {
					DUK_DD(DUK_DDPRINT("sweep; reachable --> keep: %!iO", curr));
					count_keep++;
				}

				if (prev != NULL) {
					DUK_ASSERT(heap->heap_allocated != NULL);
					DUK_HEAPHDR_SET_NEXT(heap, prev, curr);
				} else {
					DUK_ASSERT(heap->heap_allocated == NULL);
					heap->heap_allocated = curr;
				}
#if defined(DUK_USE_DOUBLE_LINKED_HEAP)
				DUK_HEAPHDR_SET_PREV(heap, curr, prev);
#endif
				DUK_HEAPHDR_ASSERT_LINKS(heap, prev);
				DUK_HEAPHDR_ASSERT_LINKS(heap, curr);
				prev = curr;
			}

			/*
			 *  Shrink check for value stacks here.  We're inside
			 *  ms_prevent_count protection which prevents recursive
			 *  mark-and-sweep and refzero finalizers, so there are
			 *  no side effects that would affect the heap lists.
			 */
			if (DUK_HEAPHDR_IS_OBJECT(curr) && DUK_HOBJECT_IS_THREAD((duk_hobject *) curr)) {
				duk_hthread *thr_curr = (duk_hthread *) curr;
				DUK_DD(DUK_DDPRINT("value stack shrink check for thread: %!O", curr));
				duk_valstack_shrink_check_nothrow(thr_curr, flags & DUK_MS_FLAG_EMERGENCY /*snug*/);
			}

			DUK_HEAPHDR_CLEAR_REACHABLE(curr);
			/* Keep FINALIZED if set, used if rescue decisions are postponed. */
			/* Keep FINALIZABLE for objects on finalize_list. */
			DUK_ASSERT(!DUK_HEAPHDR_HAS_REACHABLE(curr));
		} else {
			/*
			 *  Unreachable object:
			 *    - If FINALIZED, object was finalized but not
			 *      rescued.  This doesn't affect freeing.
			 *    - Otherwise normal unreachable object.
			 *
			 *  There's no guard preventing a FINALIZED object
			 *  from being freed while finalizers execute: the
			 *  artificial finalize_list reachability roots can't
			 *  cause an incorrect free decision (but can cause
			 *  an incorrect rescue decision).
			 */

#if defined(DUK_USE_REFERENCE_COUNTING)
			/* Non-zero refcounts should not happen because we refcount
			 * finalize all unreachable objects which should cancel out
			 * refcounts (even for cycles).
			 */
			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(curr) == 0);
#endif
			DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(curr));

#if defined(DUK_USE_DEBUG)
			if (DUK_HEAPHDR_HAS_FINALIZED(curr)) {
				DUK_DD(DUK_DDPRINT("sweep; unreachable, finalized --> finalized object not rescued: %p", (void *) curr));
			} else {
				DUK_DD(DUK_DDPRINT("sweep; not reachable --> free: %p", (void *) curr));
			}

#endif

			/* Note: object cannot be a finalizable unreachable object, as
			 * they have been marked temporarily reachable for this round,
			 * and are handled above.
			 */

#if defined(DUK_USE_DEBUG)
			count_free++;
#endif

			/* Weak refs should be handled here, but no weak refs for
			 * any non-string objects exist right now.
			 */

			/* Free object and all auxiliary (non-heap) allocs. */
			duk_heap_free_heaphdr_raw(heap, curr);
		}

		curr = next;
	}

	if (prev != NULL) {
		DUK_HEAPHDR_SET_NEXT(heap, prev, NULL);
	}
	DUK_HEAPHDR_ASSERT_LINKS(heap, prev);

#if defined(DUK_USE_DEBUG)
	DUK_D(DUK_DPRINT("mark-and-sweep sweep objects (non-string): %ld freed, %ld kept, %ld rescued, %ld queued for finalization",
	                 (long) count_free, (long) count_keep, (long) count_rescue, (long) count_finalize));
#endif
	*out_count_keep = count_keep;
}

/*
 *  Litcache helpers.
 */

#if defined(DUK_USE_LITCACHE_SIZE)
DUK_LOCAL void duk__wipe_litcache(duk_heap *heap) {
	duk_uint_t i;
	duk_litcache_entry *e;

	e = heap->litcache;
	for (i = 0; i < DUK_USE_LITCACHE_SIZE; i++) {
		e->addr = NULL;
		/* e->h does not need to be invalidated: when e->addr is
		 * NULL, e->h is considered garbage.
		 */
		e++;
	}
}
#endif  /* DUK_USE_LITCACHE_SIZE */

/*
 *  Object compaction.
 *
 *  Compaction is assumed to never throw an error.
 */

DUK_LOCAL int duk__protected_compact_object(duk_hthread *thr, void *udata) {
	duk_hobject *obj;
	/* XXX: for threads, compact stacks? */

	DUK_UNREF(udata);
	obj = duk_known_hobject(thr, -1);
	duk_hobject_compact_props(thr, obj);
	return 0;
}

#if defined(DUK_USE_DEBUG)
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) {
#else
DUK_LOCAL void duk__compact_object_list(duk_heap *heap, duk_hthread *thr, duk_heaphdr *start) {
#endif
	duk_heaphdr *curr;
#if defined(DUK_USE_DEBUG)
	duk_size_t old_size, new_size;
#endif
	duk_hobject *obj;

	DUK_UNREF(heap);

	curr = start;
	while (curr) {
		DUK_DDD(DUK_DDDPRINT("mark-and-sweep compact: %p", (void *) curr));

		if (DUK_HEAPHDR_GET_TYPE(curr) != DUK_HTYPE_OBJECT) {
			goto next;
		}
		obj = (duk_hobject *) curr;

#if defined(DUK_USE_DEBUG)
		old_size = DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE(obj),
		                                      DUK_HOBJECT_GET_ASIZE(obj),
		                                      DUK_HOBJECT_GET_HSIZE(obj));
#endif

		DUK_DD(DUK_DDPRINT("compact object: %p", (void *) obj));
		duk_push_hobject(thr, obj);
		/* XXX: disable error handlers for duration of compaction? */
		duk_safe_call(thr, duk__protected_compact_object, NULL, 1, 0);

#if defined(DUK_USE_DEBUG)
		new_size = DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE(obj),
		                                      DUK_HOBJECT_GET_ASIZE(obj),
		                                      DUK_HOBJECT_GET_HSIZE(obj));
#endif

#if defined(DUK_USE_DEBUG)
		(*p_count_compact)++;
		(*p_count_bytes_saved) += (duk_size_t) (old_size - new_size);
#endif

	 next:
		curr = DUK_HEAPHDR_GET_NEXT(heap, curr);
#if defined(DUK_USE_DEBUG)
		(*p_count_check)++;
#endif
	}
}

DUK_LOCAL void duk__compact_objects(duk_heap *heap) {
	/* XXX: which lists should participate?  to be finalized? */
#if defined(DUK_USE_DEBUG)
	duk_size_t count_check = 0;
	duk_size_t count_compact = 0;
	duk_size_t count_bytes_saved = 0;
#endif

	DUK_DD(DUK_DDPRINT("duk__compact_objects: %p", (void *) heap));

	DUK_ASSERT(heap->heap_thread != NULL);

#if defined(DUK_USE_DEBUG)
	duk__compact_object_list(heap, heap->heap_thread, heap->heap_allocated, &count_check, &count_compact, &count_bytes_saved);
#if defined(DUK_USE_FINALIZER_SUPPORT)
	duk__compact_object_list(heap, heap->heap_thread, heap->finalize_list, &count_check, &count_compact, &count_bytes_saved);
#endif
#else
	duk__compact_object_list(heap, heap->heap_thread, heap->heap_allocated);
#if defined(DUK_USE_FINALIZER_SUPPORT)
	duk__compact_object_list(heap, heap->heap_thread, heap->finalize_list);
#endif
#endif
#if defined(DUK_USE_REFERENCE_COUNTING)
	DUK_ASSERT(heap->refzero_list == NULL);  /* Always handled to completion inline in DECREF. */
#endif

#if defined(DUK_USE_DEBUG)
	DUK_D(DUK_DPRINT("mark-and-sweep compact objects: %ld checked, %ld compaction attempts, %ld bytes saved by compaction",
	                 (long) count_check, (long) count_compact, (long) count_bytes_saved));
#endif
}

/*
 *  Assertion helpers.
 */

#if defined(DUK_USE_ASSERTIONS)
typedef void (*duk__gc_heaphdr_assert)(duk_heap *heap, duk_heaphdr *h);
typedef void (*duk__gc_hstring_assert)(duk_heap *heap, duk_hstring *h);

DUK_LOCAL void duk__assert_walk_list(duk_heap *heap, duk_heaphdr *start, duk__gc_heaphdr_assert func) {
	duk_heaphdr *curr;
	for (curr = start; curr != NULL; curr = DUK_HEAPHDR_GET_NEXT(heap, curr)) {
		func(heap, curr);
	}
}

DUK_LOCAL void duk__assert_walk_strtable(duk_heap *heap, duk__gc_hstring_assert func) {
	duk_uint32_t i;

	for (i = 0; i < heap->st_size; i++) {
		duk_hstring *h;

#if defined(DUK_USE_STRTAB_PTRCOMP)
		h = DUK_USE_HEAPPTR_DEC16(heap->heap_udata, heap->strtable16[i]);
#else
		h = heap->strtable[i];
#endif
		while (h != NULL) {
			func(heap, h);
			h = h->hdr.h_next;
		}
	}
}

DUK_LOCAL void duk__assert_heaphdr_flags_cb(duk_heap *heap, duk_heaphdr *h) {
	DUK_UNREF(heap);
	DUK_ASSERT(!DUK_HEAPHDR_HAS_REACHABLE(h));
	DUK_ASSERT(!DUK_HEAPHDR_HAS_TEMPROOT(h));
	DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(h));
	/* may have FINALIZED */
}
DUK_LOCAL void duk__assert_heaphdr_flags(duk_heap *heap) {
	duk__assert_walk_list(heap, heap->heap_allocated, duk__assert_heaphdr_flags_cb);
#if defined(DUK_USE_REFERENCE_COUNTING)
	DUK_ASSERT(heap->refzero_list == NULL);  /* Always handled to completion inline in DECREF. */
#endif
	/* XXX: Assertions for finalize_list? */
}

DUK_LOCAL void duk__assert_validity_cb1(duk_heap *heap, duk_heaphdr *h) {
	DUK_UNREF(heap);
	DUK_ASSERT(DUK_HEAPHDR_IS_OBJECT(h) || DUK_HEAPHDR_IS_BUFFER(h));
	duk_heaphdr_assert_valid_subclassed(h);
}
DUK_LOCAL void duk__assert_validity_cb2(duk_heap *heap, duk_hstring *h) {
	DUK_UNREF(heap);
	DUK_ASSERT(DUK_HEAPHDR_IS_STRING((duk_heaphdr *) h));
	duk_heaphdr_assert_valid_subclassed((duk_heaphdr *) h);
}
DUK_LOCAL void duk__assert_validity(duk_heap *heap) {
	duk__assert_walk_list(heap, heap->heap_allocated, duk__assert_validity_cb1);
#if defined(DUK_USE_FINALIZER_SUPPORT)
	duk__assert_walk_list(heap, heap->finalize_list, duk__assert_validity_cb1);
#endif
#if defined(DUK_USE_REFERENCE_COUNTING)
	duk__assert_walk_list(heap, heap->refzero_list, duk__assert_validity_cb1);
#endif
	duk__assert_walk_strtable(heap, duk__assert_validity_cb2);
}

#if defined(DUK_USE_REFERENCE_COUNTING)
DUK_LOCAL void duk__assert_valid_refcounts_cb(duk_heap *heap, duk_heaphdr *h) {
	/* Cannot really assert much w.r.t. refcounts now. */

	DUK_UNREF(heap);
	if (DUK_HEAPHDR_GET_REFCOUNT(h) == 0 &&
	    DUK_HEAPHDR_HAS_FINALIZED(h)) {
		/* An object may be in heap_allocated list with a zero
		 * refcount if it has just been finalized and is waiting
		 * to be collected by the next cycle.
		 * (This doesn't currently happen however.)
		 */
	} else if (DUK_HEAPHDR_GET_REFCOUNT(h) == 0) {
		/* An object may be in heap_allocated list with a zero
		 * refcount also if it is a temporary object created
		 * during debugger paused state.  It will get collected
		 * by mark-and-sweep based on its reachability status
		 * (presumably not reachable because refcount is 0).
		 */
	}
	DUK_ASSERT_DISABLE(DUK_HEAPHDR_GET_REFCOUNT(h) >= 0);  /* Unsigned. */
}
DUK_LOCAL void duk__assert_valid_refcounts(duk_heap *heap) {
	duk__assert_walk_list(heap, heap->heap_allocated, duk__assert_valid_refcounts_cb);
}

DUK_LOCAL void duk__clear_assert_refcounts_cb1(duk_heap *heap, duk_heaphdr *h) {
	DUK_UNREF(heap);
	h->h_assert_refcount = 0;
}
DUK_LOCAL void duk__clear_assert_refcounts_cb2(duk_heap *heap, duk_hstring *h) {
	DUK_UNREF(heap);
	((duk_heaphdr *) h)->h_assert_refcount = 0;
}
DUK_LOCAL void duk__clear_assert_refcounts(duk_heap *heap) {
	duk__assert_walk_list(heap, heap->heap_allocated, duk__clear_assert_refcounts_cb1);
#if defined(DUK_USE_FINALIZER_SUPPORT)
	duk__assert_walk_list(heap, heap->finalize_list, duk__clear_assert_refcounts_cb1);
#endif
#if defined(DUK_USE_REFERENCE_COUNTING)
	duk__assert_walk_list(heap, heap->refzero_list, duk__clear_assert_refcounts_cb1);
#endif
	duk__assert_walk_strtable(heap, duk__clear_assert_refcounts_cb2);
}

DUK_LOCAL void duk__check_refcount_heaphdr(duk_heaphdr *hdr) {
	duk_bool_t count_ok;
	duk_size_t expect_refc;

	/* The refcount check only makes sense for reachable objects on
	 * heap_allocated or string table, after the sweep phase.  Prior to
	 * sweep phase refcounts will include references that are not visible
	 * via reachability roots.
	 *
	 * Because we're called after the sweep phase, all heap objects on
	 * heap_allocated are reachable.  REACHABLE flags have already been
	 * cleared so we can't check them.
	 */

	/* ROM objects have intentionally incorrect refcount (1), but we won't
	 * check them.
	 */
	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(hdr));

	expect_refc = hdr->h_assert_refcount;
	if (DUK_HEAPHDR_IS_STRING(hdr) && DUK_HSTRING_HAS_PINNED_LITERAL((duk_hstring *) hdr)) {
		expect_refc++;
	}
	count_ok = ((duk_size_t) DUK_HEAPHDR_GET_REFCOUNT(hdr) == expect_refc);
	if (!count_ok) {
		DUK_D(DUK_DPRINT("refcount mismatch for: %p: header=%ld counted=%ld --> %!iO",
		                 (void *) hdr, (long) DUK_HEAPHDR_GET_REFCOUNT(hdr),
		                 (long) hdr->h_assert_refcount, hdr));
		DUK_ASSERT(0);
	}
}

DUK_LOCAL void duk__check_assert_refcounts_cb1(duk_heap *heap, duk_heaphdr *h) {
	DUK_UNREF(heap);
	duk__check_refcount_heaphdr(h);
}
DUK_LOCAL void duk__check_assert_refcounts_cb2(duk_heap *heap, duk_hstring *h) {
	DUK_UNREF(heap);
	duk__check_refcount_heaphdr((duk_heaphdr *) h);
}
DUK_LOCAL void duk__check_assert_refcounts(duk_heap *heap) {
	duk__assert_walk_list(heap, heap->heap_allocated, duk__check_assert_refcounts_cb1);
#if defined(DUK_USE_FINALIZER_SUPPORT)
	duk__assert_walk_list(heap, heap->finalize_list, duk__check_assert_refcounts_cb1);
#endif
	/* XXX: Assert anything for refzero_list? */
	duk__assert_walk_strtable(heap, duk__check_assert_refcounts_cb2);
}
#endif  /* DUK_USE_REFERENCE_COUNTING */

#if defined(DUK_USE_LITCACHE_SIZE)
DUK_LOCAL void duk__assert_litcache_nulls(duk_heap *heap) {
	duk_uint_t i;
	duk_litcache_entry *e;

	e = heap->litcache;
	for (i = 0; i < DUK_USE_LITCACHE_SIZE; i++) {
		/* Entry addresses were NULLed before mark-and-sweep, check
		 * that they're still NULL afterwards to ensure no pointers
		 * were recorded through any side effects.
		 */
		DUK_ASSERT(e->addr == NULL);
	}
}
#endif  /* DUK_USE_LITCACHE_SIZE */
#endif  /* DUK_USE_ASSERTIONS */

/*
 *  Stats dump.
 */

#if defined(DUK_USE_DEBUG)
DUK_LOCAL void duk__dump_stats(duk_heap *heap) {
	DUK_D(DUK_DPRINT("stats executor: opcodes=%ld, interrupt=%ld, throw=%ld",
	                 (long) heap->stats_exec_opcodes, (long) heap->stats_exec_interrupt,
	                 (long) heap->stats_exec_throw));
	DUK_D(DUK_DPRINT("stats call: all=%ld, tailcall=%ld, ecmatoecma=%ld",
	                 (long) heap->stats_call_all, (long) heap->stats_call_tailcall,
	                 (long) heap->stats_call_ecmatoecma));
	DUK_D(DUK_DPRINT("stats safecall: all=%ld, nothrow=%ld, throw=%ld",
	                 (long) heap->stats_safecall_all, (long) heap->stats_safecall_nothrow,
	                 (long) heap->stats_safecall_throw));
	DUK_D(DUK_DPRINT("stats mark-and-sweep: try_count=%ld, skip_count=%ld, emergency_count=%ld",
	                 (long) heap->stats_ms_try_count, (long) heap->stats_ms_skip_count,
	                 (long) heap->stats_ms_emergency_count));
	DUK_D(DUK_DPRINT("stats stringtable: intern_hit=%ld, intern_miss=%ld, "
	                 "resize_check=%ld, resize_grow=%ld, resize_shrink=%ld, "
	                 "litcache_hit=%ld, litcache_miss=%ld, litcache_pin=%ld",
	                 (long) heap->stats_strtab_intern_hit, (long) heap->stats_strtab_intern_miss,
	                 (long) heap->stats_strtab_resize_check, (long) heap->stats_strtab_resize_grow,
	                 (long) heap->stats_strtab_resize_shrink, (long) heap->stats_strtab_litcache_hit,
	                 (long) heap->stats_strtab_litcache_miss, (long) heap->stats_strtab_litcache_pin));
	DUK_D(DUK_DPRINT("stats object: realloc_props=%ld, abandon_array=%ld",
	                 (long) heap->stats_object_realloc_props, (long) heap->stats_object_abandon_array));
	DUK_D(DUK_DPRINT("stats getownpropdesc: count=%ld, hit=%ld, miss=%ld",
	                 (long) heap->stats_getownpropdesc_count, (long) heap->stats_getownpropdesc_hit,
	                 (long) heap->stats_getownpropdesc_miss));
	DUK_D(DUK_DPRINT("stats getpropdesc: count=%ld, hit=%ld, miss=%ld",
	                 (long) heap->stats_getpropdesc_count, (long) heap->stats_getpropdesc_hit,
	                 (long) heap->stats_getpropdesc_miss));
	DUK_D(DUK_DPRINT("stats getprop: all=%ld, arrayidx=%ld, bufobjidx=%ld, "
	                 "bufferidx=%ld, bufferlen=%ld, stringidx=%ld, stringlen=%ld, "
	                 "proxy=%ld, arguments=%ld",
	                 (long) heap->stats_getprop_all, (long) heap->stats_getprop_arrayidx,
	                 (long) heap->stats_getprop_bufobjidx, (long) heap->stats_getprop_bufferidx,
	                 (long) heap->stats_getprop_bufferlen, (long) heap->stats_getprop_stringidx,
	                 (long) heap->stats_getprop_stringlen, (long) heap->stats_getprop_proxy,
	                 (long) heap->stats_getprop_arguments));
	DUK_D(DUK_DPRINT("stats putprop: all=%ld, arrayidx=%ld, bufobjidx=%ld, "
	                 "bufferidx=%ld, proxy=%ld",
	                 (long) heap->stats_putprop_all, (long) heap->stats_putprop_arrayidx,
	                 (long) heap->stats_putprop_bufobjidx, (long) heap->stats_putprop_bufferidx,
	                 (long) heap->stats_putprop_proxy));
	DUK_D(DUK_DPRINT("stats getvar: all=%ld",
	                 (long) heap->stats_getvar_all));
	DUK_D(DUK_DPRINT("stats putvar: all=%ld",
	                 (long) heap->stats_putvar_all));
	DUK_D(DUK_DPRINT("stats envrec: delayedcreate=%ld, create=%ld, newenv=%ld, oldenv=%ld, pushclosure=%ld",
	                 (long) heap->stats_envrec_delayedcreate,
	                 (long) heap->stats_envrec_create,
	                 (long) heap->stats_envrec_newenv,
	                 (long) heap->stats_envrec_oldenv,
	                 (long) heap->stats_envrec_pushclosure));
}
#endif  /* DUK_USE_DEBUG */

/*
 *  Main mark-and-sweep function.
 *
 *  'flags' represents the features requested by the caller.  The current
 *  heap->ms_base_flags is ORed automatically into the flags; the base flags
 *  mask typically prevents certain mark-and-sweep operation to avoid trouble.
 */

DUK_INTERNAL void duk_heap_mark_and_sweep(duk_heap *heap, duk_small_uint_t flags) {
	duk_size_t count_keep_obj;
	duk_size_t count_keep_str;
#if defined(DUK_USE_VOLUNTARY_GC)
	duk_size_t tmp;
#endif

	DUK_STATS_INC(heap, stats_ms_try_count);
#if defined(DUK_USE_DEBUG)
	if (flags & DUK_MS_FLAG_EMERGENCY) {
		DUK_STATS_INC(heap, stats_ms_emergency_count);
	}
#endif

	/* If debugger is paused, garbage collection is disabled by default.
	 * This is achieved by bumping ms_prevent_count when becoming paused.
	 */
	DUK_ASSERT(!DUK_HEAP_HAS_DEBUGGER_PAUSED(heap) || heap->ms_prevent_count > 0);

	/* Prevention/recursion check as soon as possible because we may
	 * be called a number of times when voluntary mark-and-sweep is
	 * pending.
	 */
	if (heap->ms_prevent_count != 0) {
		DUK_DD(DUK_DDPRINT("reject recursive mark-and-sweep"));
		DUK_STATS_INC(heap, stats_ms_skip_count);
		return;
	}
	DUK_ASSERT(heap->ms_running == 0);  /* ms_prevent_count is bumped when ms_running is set */

	/* Heap_thread is used during mark-and-sweep for refcount finalization
	 * (it's also used for finalizer execution once mark-and-sweep is
	 * complete).  Heap allocation code ensures heap_thread is set and
	 * properly initialized before setting ms_prevent_count to 0.
	 */
	DUK_ASSERT(heap->heap_thread != NULL);
	DUK_ASSERT(heap->heap_thread->valstack != NULL);

	DUK_D(DUK_DPRINT("garbage collect (mark-and-sweep) starting, requested flags: 0x%08lx, effective flags: 0x%08lx",
	                 (unsigned long) flags, (unsigned long) (flags | heap->ms_base_flags)));

	flags |= heap->ms_base_flags;
#if defined(DUK_USE_FINALIZER_SUPPORT)
	if (heap->finalize_list != NULL) {
		flags |= DUK_MS_FLAG_POSTPONE_RESCUE;
	}
#endif

	/*
	 *  Assertions before
	 */

#if defined(DUK_USE_ASSERTIONS)
	DUK_ASSERT(heap->ms_prevent_count == 0);
	DUK_ASSERT(heap->ms_running == 0);
	DUK_ASSERT(!DUK_HEAP_HAS_DEBUGGER_PAUSED(heap));
	DUK_ASSERT(!DUK_HEAP_HAS_MARKANDSWEEP_RECLIMIT_REACHED(heap));
	DUK_ASSERT(heap->ms_recursion_depth == 0);
	duk__assert_heaphdr_flags(heap);
	duk__assert_validity(heap);
#if defined(DUK_USE_REFERENCE_COUNTING)
	/* Note: heap->refzero_free_running may be true; a refcount
	 * finalizer may trigger a mark-and-sweep.
	 */
	duk__assert_valid_refcounts(heap);
#endif  /* DUK_USE_REFERENCE_COUNTING */
#endif  /* DUK_USE_ASSERTIONS */

	/*
	 *  Begin
	 */

	DUK_ASSERT(heap->ms_prevent_count == 0);
	DUK_ASSERT(heap->ms_running == 0);
	heap->ms_prevent_count = 1;
	heap->ms_running = 1;

	/*
	 *  Free activation/catcher freelists on every mark-and-sweep for now.
	 *  This is an initial rough draft; ideally we'd keep count of the
	 *  freelist size and free only excess entries.
	 */

	DUK_D(DUK_DPRINT("freeing temporary freelists"));
	duk_heap_free_freelists(heap);

	/*
	 *  Mark roots, hoping that recursion limit is not normally hit.
	 *  If recursion limit is hit, run additional reachability rounds
	 *  starting from "temproots" until marking is complete.
	 *
	 *  Marking happens in two phases: first we mark actual reachability
	 *  roots (and run "temproots" to complete the process).  Then we
	 *  check which objects are unreachable and are finalizable; such
	 *  objects are marked as FINALIZABLE and marked as reachability
	 *  (and "temproots" is run again to complete the process).
	 *
	 *  The heap finalize_list must also be marked as a reachability root.
	 *  There may be objects on the list from a previous round if the
	 *  previous run had finalizer skip flag.
	 */

#if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_REFERENCE_COUNTING)
	duk__clear_assert_refcounts(heap);
#endif
#if defined(DUK_USE_LITCACHE_SIZE)
	duk__wipe_litcache(heap);
#endif
	duk__mark_roots_heap(heap);               /* Mark main reachability roots. */
#if defined(DUK_USE_REFERENCE_COUNTING)
	DUK_ASSERT(heap->refzero_list == NULL);   /* Always handled to completion inline in DECREF. */
#endif
	duk__mark_temproots_by_heap_scan(heap);   /* Temproots. */

#if defined(DUK_USE_FINALIZER_SUPPORT)
	duk__mark_finalizable(heap);              /* Mark finalizable as reachability roots. */
	duk__mark_finalize_list(heap);            /* Mark finalizer work list as reachability roots. */
#endif
	duk__mark_temproots_by_heap_scan(heap);   /* Temproots. */

	/*
	 *  Sweep garbage and remove marking flags, and move objects with
	 *  finalizers to the finalizer work list.
	 *
	 *  Objects to be swept need to get their refcounts finalized before
	 *  they are swept.  In other words, their target object refcounts
	 *  need to be decreased.  This has to be done before freeing any
	 *  objects to avoid decref'ing dangling pointers (which may happen
	 *  even without bugs, e.g. with reference loops)
	 *
	 *  Because strings don't point to other heap objects, similar
	 *  finalization is not necessary for strings.
	 */

	/* XXX: more emergency behavior, e.g. find smaller hash sizes etc */

#if defined(DUK_USE_REFERENCE_COUNTING)
	duk__finalize_refcounts(heap);
#endif
	duk__sweep_heap(heap, flags, &count_keep_obj);
	duk__sweep_stringtable(heap, &count_keep_str);
#if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_REFERENCE_COUNTING)
	duk__check_assert_refcounts(heap);
#endif
#if defined(DUK_USE_REFERENCE_COUNTING)
	DUK_ASSERT(heap->refzero_list == NULL);   /* Always handled to completion inline in DECREF. */
#endif
#if defined(DUK_USE_FINALIZER_SUPPORT)
	duk__clear_finalize_list_flags(heap);
#endif

	/*
	 *  Object compaction (emergency only).
	 *
	 *  Object compaction is a separate step after sweeping, as there is
	 *  more free memory for it to work with.  Also, currently compaction
	 *  may insert new objects into the heap allocated list and the string
	 *  table which we don't want to do during a sweep (the reachability
	 *  flags of such objects would be incorrect).  The objects inserted
	 *  are currently:
	 *
	 *    - a temporary duk_hbuffer for a new properties allocation
	 *    - if array part is abandoned, string keys are interned
	 *
	 *  The object insertions go to the front of the list, so they do not
	 *  cause an infinite loop (they are not compacted).
	 *
	 *  At present compaction is not allowed when mark-and-sweep runs
	 *  during error handling because it involves a duk_safe_call()
	 *  interfering with error state.
	 */

	if ((flags & DUK_MS_FLAG_EMERGENCY) &&
	    !(flags & DUK_MS_FLAG_NO_OBJECT_COMPACTION)) {
		if (heap->lj.type != DUK_LJ_TYPE_UNKNOWN) {
			DUK_D(DUK_DPRINT("lj.type (%ld) not DUK_LJ_TYPE_UNKNOWN, skip object compaction", (long) heap->lj.type));
		} else {
			DUK_D(DUK_DPRINT("object compaction"));
			duk__compact_objects(heap);
		}
	}

	/*
	 *  String table resize check.
	 *
	 *  This is mainly useful in emergency GC: if the string table load
	 *  factor is really low for some reason, we can shrink the string
	 *  table to a smaller size and free some memory in the process.
	 *  Only execute in emergency GC.  String table has internal flags
	 *  to protect against recursive resizing if this mark-and-sweep pass
	 *  was triggered by a string table resize.
	 */

	if (flags & DUK_MS_FLAG_EMERGENCY) {
		DUK_D(DUK_DPRINT("stringtable resize check in emergency gc"));
		duk_heap_strtable_force_resize(heap);
	}

	/*
	 *  Finish
	 */

	DUK_ASSERT(heap->ms_prevent_count == 1);
	DUK_ASSERT(heap->ms_running == 1);
	heap->ms_prevent_count = 0;
	heap->ms_running = 0;

	/*
	 *  Assertions after
	 */

#if defined(DUK_USE_ASSERTIONS)
	DUK_ASSERT(heap->ms_prevent_count == 0);
	DUK_ASSERT(!DUK_HEAP_HAS_MARKANDSWEEP_RECLIMIT_REACHED(heap));
	DUK_ASSERT(heap->ms_recursion_depth == 0);
	duk__assert_heaphdr_flags(heap);
	duk__assert_validity(heap);
#if defined(DUK_USE_REFERENCE_COUNTING)
	/* Note: heap->refzero_free_running may be true; a refcount
	 * finalizer may trigger a mark-and-sweep.
	 */
	duk__assert_valid_refcounts(heap);
#endif  /* DUK_USE_REFERENCE_COUNTING */
#if defined(DUK_USE_LITCACHE_SIZE)
	duk__assert_litcache_nulls(heap);
#endif  /* DUK_USE_LITCACHE_SIZE */
#endif  /* DUK_USE_ASSERTIONS */

	/*
	 *  Reset trigger counter
	 */

#if defined(DUK_USE_VOLUNTARY_GC)
	tmp = (count_keep_obj + count_keep_str) / 256;
	heap->ms_trigger_counter = (duk_int_t) (
	    (tmp * DUK_HEAP_MARK_AND_SWEEP_TRIGGER_MULT) +
	    DUK_HEAP_MARK_AND_SWEEP_TRIGGER_ADD);
	DUK_D(DUK_DPRINT("garbage collect (mark-and-sweep) finished: %ld objects kept, %ld strings kept, trigger reset to %ld",
	                 (long) count_keep_obj, (long) count_keep_str, (long) heap->ms_trigger_counter));
#else
	DUK_D(DUK_DPRINT("garbage collect (mark-and-sweep) finished: %ld objects kept, %ld strings kept, no voluntary trigger",
	                 (long) count_keep_obj, (long) count_keep_str));
#endif

	/*
	 *  Stats dump
	 */

#if defined(DUK_USE_DEBUG)
	duk__dump_stats(heap);
#endif

	/*
	 *  Finalize objects in the finalization work list.  Finalized
	 *  objects are queued back to heap_allocated with FINALIZED set.
	 *
	 *  Since finalizers may cause arbitrary side effects, they are
	 *  prevented e.g. during string table and object property allocation
	 *  resizing using heap->pf_prevent_count.  In this case the objects
	 *  remain in the finalization work list after mark-and-sweep exits
	 *  and they may be finalized on the next pass or any DECREF checking
	 *  for finalize_list.
	 *
	 *  As of Duktape 2.1 finalization happens outside mark-and-sweep
	 *  protection.  Mark-and-sweep is allowed while the finalize_list
	 *  is being processed, but no rescue decisions are done while the
	 *  process is on-going.  This avoids incorrect rescue decisions
	 *  if an object is considered reachable (and thus rescued) because
	 *  of a reference via finalize_list (which is considered a reachability
	 *  root).  When finalize_list is being processed, reachable objects
	 *  with FINALIZED set will just keep their FINALIZED flag for later
	 *  mark-and-sweep processing.
	 *
	 *  This could also be handled (a bit better) by having a more refined
	 *  notion of reachability for rescue/free decisions.
	 *
	 *  XXX: avoid finalizer execution when doing emergency GC?
	 */

#if defined(DUK_USE_FINALIZER_SUPPORT)
	/* Attempt to process finalize_list, pf_prevent_count check
	 * is inside the target.
	 */
	duk_heap_process_finalize_list(heap);
#endif  /* DUK_USE_FINALIZER_SUPPORT */
}
#line 1 "duk_heap_memory.c"
/*
 *  Memory allocation handling.
 */

/* #include duk_internal.h -> already included */

/*
 *  Allocate memory with garbage collection.
 */

/* Slow path: voluntary GC triggered, first alloc attempt failed, or zero size. */
DUK_LOCAL DUK_NOINLINE_PERF DUK_COLD void *duk__heap_mem_alloc_slowpath(duk_heap *heap, duk_size_t size) {
	void *res;
	duk_small_int_t i;

	DUK_ASSERT(heap != NULL);
	DUK_ASSERT(heap->alloc_func != NULL);
	DUK_ASSERT_DISABLE(size >= 0);

	if (size == 0) {
		DUK_D(DUK_DPRINT("zero size alloc in slow path, return NULL"));
		return NULL;
	}

	DUK_D(DUK_DPRINT("first alloc attempt failed or voluntary GC limit reached, attempt to gc and retry"));

#if 0
	/*
	 *  If GC is already running there is no point in attempting a GC
	 *  because it will be skipped.  This could be checked for explicitly,
	 *  but it isn't actually needed: the loop below will eventually
	 *  fail resulting in a NULL.
	 */

	if (heap->ms_prevent_count != 0) {
		DUK_D(DUK_DPRINT("duk_heap_mem_alloc() failed, gc in progress (gc skipped), alloc size %ld", (long) size));
		return NULL;
	}
#endif

	/*
	 *  Retry with several GC attempts.  Initial attempts are made without
	 *  emergency mode; later attempts use emergency mode which minimizes
	 *  memory allocations forcibly.
	 */

	for (i = 0; i < DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT; i++) {
		duk_small_uint_t flags;

		flags = 0;
		if (i >= DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_EMERGENCY_LIMIT - 1) {
			flags |= DUK_MS_FLAG_EMERGENCY;
		}

		duk_heap_mark_and_sweep(heap, flags);

		DUK_ASSERT(size > 0);
		res = heap->alloc_func(heap->heap_udata, size);
		if (res != NULL) {
			DUK_D(DUK_DPRINT("duk_heap_mem_alloc() succeeded after gc (pass %ld), alloc size %ld",
			                 (long) (i + 1), (long) size));
			return res;
		}
	}

	DUK_D(DUK_DPRINT("duk_heap_mem_alloc() failed even after gc, alloc size %ld", (long) size));
	return NULL;
}

DUK_INTERNAL DUK_INLINE_PERF DUK_HOT void *duk_heap_mem_alloc(duk_heap *heap, duk_size_t size) {
	void *res;

	DUK_ASSERT(heap != NULL);
	DUK_ASSERT(heap->alloc_func != NULL);
	DUK_ASSERT_DISABLE(size >= 0);

#if defined(DUK_USE_VOLUNTARY_GC)
	/* Voluntary periodic GC (if enabled). */
	if (DUK_UNLIKELY(--(heap)->ms_trigger_counter < 0)) {
		goto slowpath;
	}
#endif

#if defined(DUK_USE_GC_TORTURE)
	/* Simulate alloc failure on every alloc, except when mark-and-sweep
	 * is running.
	 */
	if (heap->ms_prevent_count == 0) {
		DUK_DDD(DUK_DDDPRINT("gc torture enabled, pretend that first alloc attempt fails"));
		res = NULL;
		DUK_UNREF(res);
		goto slowpath;
	}
#endif

	/* Zero-size allocation should happen very rarely (if at all), so
	 * don't check zero size on NULL; handle it in the slow path
	 * instead.  This reduces size of inlined code.
	 */
	res = heap->alloc_func(heap->heap_udata, size);
	if (DUK_LIKELY(res != NULL)) {
		return res;
	}

 slowpath:

	if (size == 0) {
		DUK_D(DUK_DPRINT("first alloc attempt returned NULL for zero size alloc, use slow path to deal with it"));
	} else {
		DUK_D(DUK_DPRINT("first alloc attempt failed, attempt to gc and retry"));
	}
	return duk__heap_mem_alloc_slowpath(heap, size);
}

DUK_INTERNAL DUK_INLINE_PERF DUK_HOT void *duk_heap_mem_alloc_zeroed(duk_heap *heap, duk_size_t size) {
	void *res;

	DUK_ASSERT(heap != NULL);
	DUK_ASSERT(heap->alloc_func != NULL);
	DUK_ASSERT_DISABLE(size >= 0);

	res = DUK_ALLOC(heap, size);
	if (DUK_LIKELY(res != NULL)) {
		duk_memzero(res, size);
	}
	return res;
}

DUK_INTERNAL DUK_INLINE_PERF DUK_HOT void *duk_heap_mem_alloc_checked(duk_hthread *thr, duk_size_t size) {
	void *res;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(thr->heap != NULL);
	DUK_ASSERT(thr->heap->alloc_func != NULL);

	res = duk_heap_mem_alloc(thr->heap, size);
	if (DUK_LIKELY(res != NULL)) {
		return res;
	} else if (size == 0) {
		DUK_ASSERT(res == NULL);
		return res;
	}
	DUK_ERROR_ALLOC_FAILED(thr);
	DUK_WO_NORETURN(return NULL;);
}

DUK_INTERNAL DUK_INLINE_PERF DUK_HOT void *duk_heap_mem_alloc_checked_zeroed(duk_hthread *thr, duk_size_t size) {
	void *res;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(thr->heap != NULL);
	DUK_ASSERT(thr->heap->alloc_func != NULL);

	res = duk_heap_mem_alloc(thr->heap, size);
	if (DUK_LIKELY(res != NULL)) {
		duk_memzero(res, size);
		return res;
	} else if (size == 0) {
		DUK_ASSERT(res == NULL);
		return res;
	}
	DUK_ERROR_ALLOC_FAILED(thr);
	DUK_WO_NORETURN(return NULL;);
}

/*
 *  Reallocate memory with garbage collection.
 */

/* Slow path: voluntary GC triggered, first realloc attempt failed, or zero size. */
DUK_LOCAL DUK_NOINLINE_PERF DUK_COLD void *duk__heap_mem_realloc_slowpath(duk_heap *heap, void *ptr, duk_size_t newsize) {
	void *res;
	duk_small_int_t i;

	DUK_ASSERT(heap != NULL);
	DUK_ASSERT(heap->realloc_func != NULL);
	/* ptr may be NULL */
	DUK_ASSERT_DISABLE(newsize >= 0);

	/* Newsize was 0 and realloc() returned NULL, this has the semantics
	 * of free(oldptr), i.e. memory was successfully freed.
	 */
	if (newsize == 0) {
		DUK_D(DUK_DPRINT("zero size realloc in slow path, return NULL"));
		return NULL;
	}

	DUK_D(DUK_DPRINT("first realloc attempt failed, attempt to gc and retry"));

#if 0
	/*
	 *  Avoid a GC if GC is already running.  See duk_heap_mem_alloc().
	 */

	if (heap->ms_prevent_count != 0) {
		DUK_D(DUK_DPRINT("duk_heap_mem_realloc() failed, gc in progress (gc skipped), alloc size %ld", (long) newsize));
		return NULL;
	}
#endif

	/*
	 *  Retry with several GC attempts.  Initial attempts are made without
	 *  emergency mode; later attempts use emergency mode which minimizes
	 *  memory allocations forcibly.
	 */

	for (i = 0; i < DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT; i++) {
		duk_small_uint_t flags;

		flags = 0;
		if (i >= DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_EMERGENCY_LIMIT - 1) {
			flags |= DUK_MS_FLAG_EMERGENCY;
		}

		duk_heap_mark_and_sweep(heap, flags);

		DUK_ASSERT(newsize > 0);
		res = heap->realloc_func(heap->heap_udata, ptr, newsize);
		if (res || newsize == 0) {
			DUK_D(DUK_DPRINT("duk_heap_mem_realloc() succeeded after gc (pass %ld), alloc size %ld",
			                 (long) (i + 1), (long) newsize));
			return res;
		}
	}

	DUK_D(DUK_DPRINT("duk_heap_mem_realloc() failed even after gc, alloc size %ld", (long) newsize));
	return NULL;
}

DUK_INTERNAL DUK_INLINE_PERF DUK_HOT void *duk_heap_mem_realloc(duk_heap *heap, void *ptr, duk_size_t newsize) {
	void *res;

	DUK_ASSERT(heap != NULL);
	DUK_ASSERT(heap->realloc_func != NULL);
	/* ptr may be NULL */
	DUK_ASSERT_DISABLE(newsize >= 0);

#if defined(DUK_USE_VOLUNTARY_GC)
	/* Voluntary periodic GC (if enabled). */
	if (DUK_UNLIKELY(--(heap)->ms_trigger_counter < 0)) {
		goto slowpath;
	}
#endif

#if defined(DUK_USE_GC_TORTURE)
	/* Simulate alloc failure on every realloc, except when mark-and-sweep
	 * is running.
	 */
	if (heap->ms_prevent_count == 0) {
		DUK_DDD(DUK_DDDPRINT("gc torture enabled, pretend that first realloc attempt fails"));
		res = NULL;
		DUK_UNREF(res);
		goto slowpath;
	}
#endif

	res = heap->realloc_func(heap->heap_udata, ptr, newsize);
	if (DUK_LIKELY(res != NULL)) {
		return res;
	}

 slowpath:

	if (newsize == 0) {
		DUK_D(DUK_DPRINT("first realloc attempt returned NULL for zero size realloc, use slow path to deal with it"));
	} else {
		DUK_D(DUK_DPRINT("first realloc attempt failed, attempt to gc and retry"));
	}
	return duk__heap_mem_realloc_slowpath(heap, ptr, newsize);
}

/*
 *  Reallocate memory with garbage collection, using a callback to provide
 *  the current allocated pointer.  This variant is used when a mark-and-sweep
 *  (e.g. finalizers) might change the original pointer.
 */

/* Slow path: voluntary GC triggered, first realloc attempt failed, or zero size. */
DUK_LOCAL DUK_NOINLINE_PERF DUK_COLD void *duk__heap_mem_realloc_indirect_slowpath(duk_heap *heap, duk_mem_getptr cb, void *ud, duk_size_t newsize) {
	void *res;
	duk_small_int_t i;

	DUK_ASSERT(heap != NULL);
	DUK_ASSERT(heap->realloc_func != NULL);
	DUK_ASSERT_DISABLE(newsize >= 0);

	if (newsize == 0) {
		DUK_D(DUK_DPRINT("zero size indirect realloc in slow path, return NULL"));
		return NULL;
	}

	DUK_D(DUK_DPRINT("first indirect realloc attempt failed, attempt to gc and retry"));

#if 0
	/*
	 *  Avoid a GC if GC is already running.  See duk_heap_mem_alloc().
	 */

	if (heap->ms_prevent_count != 0) {
		DUK_D(DUK_DPRINT("duk_heap_mem_realloc_indirect() failed, gc in progress (gc skipped), alloc size %ld", (long) newsize));
		return NULL;
	}
#endif

	/*
	 *  Retry with several GC attempts.  Initial attempts are made without
	 *  emergency mode; later attempts use emergency mode which minimizes
	 *  memory allocations forcibly.
	 */

	for (i = 0; i < DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT; i++) {
		duk_small_uint_t flags;

#if defined(DUK_USE_DEBUG)
		void *ptr_pre;
		void *ptr_post;
#endif

#if defined(DUK_USE_DEBUG)
		ptr_pre = cb(heap, ud);
#endif
		flags = 0;
		if (i >= DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_EMERGENCY_LIMIT - 1) {
			flags |= DUK_MS_FLAG_EMERGENCY;
		}

		duk_heap_mark_and_sweep(heap, flags);
#if defined(DUK_USE_DEBUG)
		ptr_post = cb(heap, ud);
		if (ptr_pre != ptr_post) {
			DUK_DD(DUK_DDPRINT("realloc base pointer changed by mark-and-sweep: %p -> %p",
			                   (void *) ptr_pre, (void *) ptr_post));
		}
#endif

		/* Note: key issue here is to re-lookup the base pointer on every attempt.
		 * The pointer being reallocated may change after every mark-and-sweep.
		 */

		DUK_ASSERT(newsize > 0);
		res = heap->realloc_func(heap->heap_udata, cb(heap, ud), newsize);
		if (res || newsize == 0) {
			DUK_D(DUK_DPRINT("duk_heap_mem_realloc_indirect() succeeded after gc (pass %ld), alloc size %ld",
			                 (long) (i + 1), (long) newsize));
			return res;
		}
	}

	DUK_D(DUK_DPRINT("duk_heap_mem_realloc_indirect() failed even after gc, alloc size %ld", (long) newsize));
	return NULL;
}

DUK_INTERNAL DUK_INLINE_PERF DUK_HOT void *duk_heap_mem_realloc_indirect(duk_heap *heap, duk_mem_getptr cb, void *ud, duk_size_t newsize) {
	void *res;

	DUK_ASSERT(heap != NULL);
	DUK_ASSERT(heap->realloc_func != NULL);
	DUK_ASSERT_DISABLE(newsize >= 0);

#if defined(DUK_USE_VOLUNTARY_GC)
	/* Voluntary periodic GC (if enabled). */
	if (DUK_UNLIKELY(--(heap)->ms_trigger_counter < 0)) {
		goto slowpath;
	}
#endif

#if defined(DUK_USE_GC_TORTURE)
	/* Simulate alloc failure on every realloc, except when mark-and-sweep
	 * is running.
	 */
	if (heap->ms_prevent_count == 0) {
		DUK_DDD(DUK_DDDPRINT("gc torture enabled, pretend that first indirect realloc attempt fails"));
		res = NULL;
		DUK_UNREF(res);
		goto slowpath;
	}
#endif

	res = heap->realloc_func(heap->heap_udata, cb(heap, ud), newsize);
	if (DUK_LIKELY(res != NULL)) {
		return res;
	}

 slowpath:

	if (newsize == 0) {
		DUK_D(DUK_DPRINT("first indirect realloc attempt returned NULL for zero size realloc, use slow path to deal with it"));
	} else {
		DUK_D(DUK_DPRINT("first indirect realloc attempt failed, attempt to gc and retry"));
	}
	return duk__heap_mem_realloc_indirect_slowpath(heap, cb, ud, newsize);
}

/*
 *  Free memory
 */

DUK_INTERNAL DUK_INLINE_PERF DUK_HOT void duk_heap_mem_free(duk_heap *heap, void *ptr) {
	DUK_ASSERT(heap != NULL);
	DUK_ASSERT(heap->free_func != NULL);
	/* ptr may be NULL */

	/* Must behave like a no-op with NULL and any pointer returned from
	 * malloc/realloc with zero size.
	 */
	heap->free_func(heap->heap_udata, ptr);

	/* Never perform a GC (even voluntary) in a memory free, otherwise
	 * all call sites doing frees would need to deal with the side effects.
	 * No need to update voluntary GC counter either.
	 */
}
#line 1 "duk_heap_misc.c"
/*
 *  Support functions for duk_heap.
 */

/* #include duk_internal.h -> already included */

DUK_INTERNAL void duk_heap_insert_into_heap_allocated(duk_heap *heap, duk_heaphdr *hdr) {
	duk_heaphdr *root;

	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(hdr) != DUK_HTYPE_STRING);

	root = heap->heap_allocated;
#if defined(DUK_USE_DOUBLE_LINKED_HEAP)
	if (root != NULL) {
		DUK_ASSERT(DUK_HEAPHDR_GET_PREV(heap, root) == NULL);
		DUK_HEAPHDR_SET_PREV(heap, root, hdr);
	}
	DUK_HEAPHDR_SET_PREV(heap, hdr, NULL);
#endif
	DUK_HEAPHDR_SET_NEXT(heap, hdr, root);
	DUK_HEAPHDR_ASSERT_LINKS(heap, hdr);
	DUK_HEAPHDR_ASSERT_LINKS(heap, root);
	heap->heap_allocated = hdr;
}

#if defined(DUK_USE_REFERENCE_COUNTING)
DUK_INTERNAL void duk_heap_remove_from_heap_allocated(duk_heap *heap, duk_heaphdr *hdr) {
	duk_heaphdr *prev;
	duk_heaphdr *next;

	/* Strings are in string table. */
	DUK_ASSERT(hdr != NULL);
	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(hdr) != DUK_HTYPE_STRING);

	/* Target 'hdr' must be in heap_allocated (not e.g. finalize_list).
	 * If not, heap lists will become corrupted so assert early for it.
	 */
#if defined(DUK_USE_ASSERTIONS)
	{
		duk_heaphdr *tmp;
		for (tmp = heap->heap_allocated; tmp != NULL; tmp = DUK_HEAPHDR_GET_NEXT(heap, tmp)) {
			if (tmp == hdr) {
				break;
			}
		}
		DUK_ASSERT(tmp == hdr);
	}
#endif

	/* Read/write only once to minimize pointer compression calls. */
	prev = DUK_HEAPHDR_GET_PREV(heap, hdr);
	next = DUK_HEAPHDR_GET_NEXT(heap, hdr);

	if (prev != NULL) {
		DUK_ASSERT(heap->heap_allocated != hdr);
		DUK_HEAPHDR_SET_NEXT(heap, prev, next);
	} else {
		DUK_ASSERT(heap->heap_allocated == hdr);
		heap->heap_allocated = next;
	}
	if (next != NULL) {
		DUK_HEAPHDR_SET_PREV(heap, next, prev);
	} else {
		;
	}
}
#endif  /* DUK_USE_REFERENCE_COUNTING */

#if defined(DUK_USE_FINALIZER_SUPPORT)
DUK_INTERNAL void duk_heap_insert_into_finalize_list(duk_heap *heap, duk_heaphdr *hdr) {
	duk_heaphdr *root;

	root = heap->finalize_list;
#if defined(DUK_USE_DOUBLE_LINKED_HEAP)
	DUK_HEAPHDR_SET_PREV(heap, hdr, NULL);
	if (root != NULL) {
		DUK_ASSERT(DUK_HEAPHDR_GET_PREV(heap, root) == NULL);
		DUK_HEAPHDR_SET_PREV(heap, root, hdr);
	}
#endif
	DUK_HEAPHDR_SET_NEXT(heap, hdr, root);
	DUK_HEAPHDR_ASSERT_LINKS(heap, hdr);
	DUK_HEAPHDR_ASSERT_LINKS(heap, root);
	heap->finalize_list = hdr;
}
#endif  /* DUK_USE_FINALIZER_SUPPORT */

#if defined(DUK_USE_FINALIZER_SUPPORT)
DUK_INTERNAL void duk_heap_remove_from_finalize_list(duk_heap *heap, duk_heaphdr *hdr) {
#if defined(DUK_USE_DOUBLE_LINKED_HEAP)
	duk_heaphdr *next;
	duk_heaphdr *prev;

	next = DUK_HEAPHDR_GET_NEXT(heap, hdr);
	prev = DUK_HEAPHDR_GET_PREV(heap, hdr);
	if (next != NULL) {
		DUK_ASSERT(DUK_HEAPHDR_GET_PREV(heap, next) == hdr);
		DUK_HEAPHDR_SET_PREV(heap, next, prev);
	}
	if (prev == NULL) {
		DUK_ASSERT(hdr == heap->finalize_list);
		heap->finalize_list = next;
	} else {
		DUK_ASSERT(hdr != heap->finalize_list);
		DUK_HEAPHDR_SET_NEXT(heap, prev, next);
	}
#else
	duk_heaphdr *next;
	duk_heaphdr *curr;

	/* Random removal is expensive: we need to locate the previous element
	 * because we don't have a 'prev' pointer.
	 */
	curr = heap->finalize_list;
	if (curr == hdr) {
		heap->finalize_list = DUK_HEAPHDR_GET_NEXT(heap, curr);
	} else {
		DUK_ASSERT(hdr != heap->finalize_list);
		for (;;) {
			DUK_ASSERT(curr != NULL);  /* Caller responsibility. */

			next = DUK_HEAPHDR_GET_NEXT(heap, curr);
			if (next == hdr) {
				next = DUK_HEAPHDR_GET_NEXT(heap, hdr);
				DUK_HEAPHDR_SET_NEXT(heap, curr, next);
				break;
			}
		}
	}
#endif
}
#endif  /* DUK_USE_FINALIZER_SUPPORT */

#if defined(DUK_USE_ASSERTIONS)
DUK_INTERNAL duk_bool_t duk_heap_in_heap_allocated(duk_heap *heap, duk_heaphdr *ptr) {
	duk_heaphdr *curr;
	DUK_ASSERT(heap != NULL);

	for (curr = heap->heap_allocated; curr != NULL; curr = DUK_HEAPHDR_GET_NEXT(heap, curr)) {
		if (curr == ptr) {
			return 1;
		}
	}
	return 0;
}
#endif  /* DUK_USE_ASSERTIONS */

#if defined(DUK_USE_INTERRUPT_COUNTER)
DUK_INTERNAL void duk_heap_switch_thread(duk_heap *heap, duk_hthread *new_thr) {
	duk_hthread *curr_thr;

	DUK_ASSERT(heap != NULL);

	if (new_thr != NULL) {
		curr_thr = heap->curr_thread;
		if (curr_thr == NULL) {
			/* For initial entry use default value; zero forces an
			 * interrupt before executing the first insturction.
			 */
			DUK_DD(DUK_DDPRINT("switch thread, initial entry, init default interrupt counter"));
			new_thr->interrupt_counter = 0;
			new_thr->interrupt_init = 0;
		} else {
			/* Copy interrupt counter/init value state to new thread (if any).
			 * It's OK for new_thr to be the same as curr_thr.
			 */
#if defined(DUK_USE_DEBUG)
			if (new_thr != curr_thr) {
				DUK_DD(DUK_DDPRINT("switch thread, not initial entry, copy interrupt counter"));
			}
#endif
			new_thr->interrupt_counter = curr_thr->interrupt_counter;
			new_thr->interrupt_init = curr_thr->interrupt_init;
		}
	} else {
		DUK_DD(DUK_DDPRINT("switch thread, new thread is NULL, no interrupt counter changes"));
	}

	heap->curr_thread = new_thr;  /* may be NULL */
}
#endif  /* DUK_USE_INTERRUPT_COUNTER */

#if defined(DUK_USE_ASSERTIONS)
DUK_INTERNAL void duk_heap_assert_valid(duk_heap *heap) {
	DUK_ASSERT(heap != NULL);
}
#endif
#line 1 "duk_heap_refcount.c"
/*
 *  Reference counting implementation.
 *
 *  INCREF/DECREF, finalization and freeing of objects whose refcount reaches
 *  zero (refzero).  These operations are very performance sensitive, so
 *  various small tricks are used in an attempt to maximize speed.
 */

/* #include duk_internal.h -> already included */

#if defined(DUK_USE_REFERENCE_COUNTING)

#if !defined(DUK_USE_DOUBLE_LINKED_HEAP)
#error internal error, reference counting requires a double linked heap
#endif

/*
 *  Heap object refcount finalization.
 *
 *  When an object is about to be freed, all other objects it refers to must
 *  be decref'd.  Refcount finalization does NOT free the object or its inner
 *  allocations (mark-and-sweep shares these helpers), it just manipulates
 *  the refcounts.
 *
 *  Note that any of the DECREFs may cause a refcount to drop to zero.  If so,
 *  the object won't be refzero processed inline, but will just be queued to
 *  refzero_list and processed by an earlier caller working on refzero_list,
 *  eliminating C recursion from even long refzero cascades.  If refzero
 *  finalization is triggered by mark-and-sweep, refzero conditions are ignored
 *  (objects are not even queued to refzero_list) because mark-and-sweep deals
 *  with them; refcounts are still updated so that they remain in sync with
 *  actual references.
 */

DUK_LOCAL void duk__decref_tvals_norz(duk_hthread *thr, duk_tval *tv, duk_idx_t count) {
	DUK_ASSERT(count == 0 || tv != NULL);

	while (count-- > 0) {
		DUK_TVAL_DECREF_NORZ(thr, tv);
		tv++;
	}
}

DUK_INTERNAL void duk_hobject_refcount_finalize_norz(duk_heap *heap, duk_hobject *h) {
	duk_hthread *thr;
	duk_uint_fast32_t i;
	duk_uint_fast32_t n;
	duk_propvalue *p_val;
	duk_tval *p_tv;
	duk_hstring **p_key;
	duk_uint8_t *p_flag;
	duk_hobject *h_proto;

	DUK_ASSERT(heap != NULL);
	DUK_ASSERT(heap->heap_thread != NULL);
	DUK_ASSERT(h);
	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) h) == DUK_HTYPE_OBJECT);

	thr = heap->heap_thread;
	DUK_ASSERT(thr != NULL);

	p_key = DUK_HOBJECT_E_GET_KEY_BASE(heap, h);
	p_val = DUK_HOBJECT_E_GET_VALUE_BASE(heap, h);
	p_flag = DUK_HOBJECT_E_GET_FLAGS_BASE(heap, h);
	n = DUK_HOBJECT_GET_ENEXT(h);
	while (n-- > 0) {
		duk_hstring *key;

		key = p_key[n];
		if (DUK_UNLIKELY(key == NULL)) {
			continue;
		}
		DUK_HSTRING_DECREF_NORZ(thr, key);
		if (DUK_UNLIKELY(p_flag[n] & DUK_PROPDESC_FLAG_ACCESSOR)) {
			duk_hobject *h_getset;
			h_getset = p_val[n].a.get;
			DUK_ASSERT(h_getset == NULL || DUK_HEAPHDR_IS_OBJECT((duk_heaphdr *) h_getset));
			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, h_getset);
			h_getset = p_val[n].a.set;
			DUK_ASSERT(h_getset == NULL || DUK_HEAPHDR_IS_OBJECT((duk_heaphdr *) h_getset));
			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, h_getset);
		} else {
			duk_tval *tv_val;
			tv_val = &p_val[n].v;
			DUK_TVAL_DECREF_NORZ(thr, tv_val);
		}
	}

	p_tv = DUK_HOBJECT_A_GET_BASE(heap, h);
	n = DUK_HOBJECT_GET_ASIZE(h);
	while (n-- > 0) {
		duk_tval *tv_val;
		tv_val = p_tv + n;
		DUK_TVAL_DECREF_NORZ(thr, tv_val);
	}

	/* Hash part is a 'weak reference' and doesn't contribute to refcounts. */

	h_proto = (duk_hobject *) DUK_HOBJECT_GET_PROTOTYPE(heap, h);
	DUK_ASSERT(h_proto == NULL || DUK_HEAPHDR_IS_OBJECT((duk_heaphdr *) h_proto));
	DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, h_proto);

	/* XXX: Object subclass tests are quite awkward at present, ideally
	 * we should be able to switch-case here with a dense index (subtype
	 * number or something).  For now, fast path plain objects and arrays
	 * and bit test the rest individually.
	 */

	if (DUK_HOBJECT_HAS_FASTREFS(h)) {
		/* Plain object or array, nothing more to do.  While a
		 * duk_harray has additional fields, none of them need
		 * DECREF updates.
		 */
		DUK_ASSERT(DUK_HOBJECT_ALLOWS_FASTREFS(h));
		return;
	}
	DUK_ASSERT(DUK_HOBJECT_PROHIBITS_FASTREFS(h));

	/* Slow path: special object, start bit checks from most likely. */

	/* XXX: reorg, more common first */
	if (DUK_HOBJECT_IS_COMPFUNC(h)) {
		duk_hcompfunc *f = (duk_hcompfunc *) h;
		duk_tval *tv, *tv_end;
		duk_hobject **funcs, **funcs_end;

		DUK_HCOMPFUNC_ASSERT_VALID(f);

		if (DUK_LIKELY(DUK_HCOMPFUNC_GET_DATA(heap, f) != NULL)) {
			tv = DUK_HCOMPFUNC_GET_CONSTS_BASE(heap, f);
			tv_end = DUK_HCOMPFUNC_GET_CONSTS_END(heap, f);
			while (tv < tv_end) {
				DUK_TVAL_DECREF_NORZ(thr, tv);
				tv++;
			}

			funcs = DUK_HCOMPFUNC_GET_FUNCS_BASE(heap, f);
			funcs_end = DUK_HCOMPFUNC_GET_FUNCS_END(heap, f);
			while (funcs < funcs_end) {
				duk_hobject *h_func;
				h_func = *funcs;
				DUK_ASSERT(h_func != NULL);
				DUK_ASSERT(DUK_HEAPHDR_IS_OBJECT((duk_heaphdr *) h_func));
				DUK_HCOMPFUNC_DECREF_NORZ(thr, (duk_hcompfunc *) h_func);
				funcs++;
			}
		} else {
			/* May happen in some out-of-memory corner cases. */
			DUK_D(DUK_DPRINT("duk_hcompfunc 'data' is NULL, skipping decref"));
		}

		DUK_HEAPHDR_DECREF_ALLOWNULL(thr, (duk_heaphdr *) DUK_HCOMPFUNC_GET_LEXENV(heap, f));
		DUK_HEAPHDR_DECREF_ALLOWNULL(thr, (duk_heaphdr *) DUK_HCOMPFUNC_GET_VARENV(heap, f));
		DUK_HEAPHDR_DECREF_ALLOWNULL(thr, (duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA(heap, f));
	} else if (DUK_HOBJECT_IS_DECENV(h)) {
		duk_hdecenv *e = (duk_hdecenv *) h;
		DUK_HDECENV_ASSERT_VALID(e);
		DUK_HTHREAD_DECREF_NORZ_ALLOWNULL(thr, e->thread);
		DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, e->varmap);
	} else if (DUK_HOBJECT_IS_OBJENV(h)) {
		duk_hobjenv *e = (duk_hobjenv *) h;
		DUK_HOBJENV_ASSERT_VALID(e);
		DUK_ASSERT(e->target != NULL);  /* Required for object environments. */
		DUK_HOBJECT_DECREF_NORZ(thr, e->target);
#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
	} else if (DUK_HOBJECT_IS_BUFOBJ(h)) {
		duk_hbufobj *b = (duk_hbufobj *) h;
		DUK_HBUFOBJ_ASSERT_VALID(b);
		DUK_HBUFFER_DECREF_NORZ_ALLOWNULL(thr, (duk_hbuffer *) b->buf);
		DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, (duk_hobject *) b->buf_prop);
#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
	} else if (DUK_HOBJECT_IS_BOUNDFUNC(h)) {
		duk_hboundfunc *f = (duk_hboundfunc *) (void *) h;
		DUK_HBOUNDFUNC_ASSERT_VALID(f);
		DUK_TVAL_DECREF_NORZ(thr, &f->target);
		DUK_TVAL_DECREF_NORZ(thr, &f->this_binding);
		duk__decref_tvals_norz(thr, f->args, f->nargs);
#if defined(DUK_USE_ES6_PROXY)
	} else if (DUK_HOBJECT_IS_PROXY(h)) {
		duk_hproxy *p = (duk_hproxy *) h;
		DUK_HPROXY_ASSERT_VALID(p);
		DUK_HOBJECT_DECREF_NORZ(thr, p->target);
		DUK_HOBJECT_DECREF_NORZ(thr, p->handler);
#endif  /* DUK_USE_ES6_PROXY */
	} else if (DUK_HOBJECT_IS_THREAD(h)) {
		duk_hthread *t = (duk_hthread *) h;
		duk_activation *act;
		duk_tval *tv;

		DUK_HTHREAD_ASSERT_VALID(t);

		tv = t->valstack;
		while (tv < t->valstack_top) {
			DUK_TVAL_DECREF_NORZ(thr, tv);
			tv++;
		}

		for (act = t->callstack_curr; act != NULL; act = act->parent) {
			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, (duk_hobject *) DUK_ACT_GET_FUNC(act));
			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, (duk_hobject *) act->var_env);
			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, (duk_hobject *) act->lex_env);
#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, (duk_hobject *) act->prev_caller);
#endif
#if 0  /* nothing now */
			for (cat = act->cat; cat != NULL; cat = cat->parent) {
			}
#endif
		}


		for (i = 0; i < DUK_NUM_BUILTINS; i++) {
			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, (duk_hobject *) t->builtins[i]);
		}

		DUK_HTHREAD_DECREF_NORZ_ALLOWNULL(thr, (duk_hthread *) t->resumer);
	} else {
		/* We may come here if the object should have a FASTREFS flag
		 * but it's missing for some reason.  Assert for never getting
		 * here; however, other than performance, this is harmless.
		 */
		DUK_D(DUK_DPRINT("missing FASTREFS flag for: %!iO", h));
		DUK_ASSERT(0);
	}
}

DUK_INTERNAL void duk_heaphdr_refcount_finalize_norz(duk_heap *heap, duk_heaphdr *hdr) {
	DUK_ASSERT(heap != NULL);
	DUK_ASSERT(heap->heap_thread != NULL);
	DUK_ASSERT(hdr != NULL);

	if (DUK_HEAPHDR_IS_OBJECT(hdr)) {
		duk_hobject_refcount_finalize_norz(heap, (duk_hobject *) hdr);
	}
	/* DUK_HTYPE_BUFFER: nothing to finalize */
	/* DUK_HTYPE_STRING: nothing to finalize */
}

/*
 *  Refzero processing for duk_hobject: queue a refzero'ed object to either
 *  finalize_list or refzero_list and process the relevent list(s) if
 *  necessary.
 *
 *  Refzero_list is single linked, with only 'prev' pointers set and valid.
 *  All 'next' pointers are intentionally left as garbage.  This doesn't
 *  matter because refzero_list is processed to completion before any other
 *  code (like mark-and-sweep) might walk the list.
 *
 *  In more detail:
 *
 *  - On first insert refzero_list is NULL and the new object becomes the
 *    first and only element on the list; duk__refcount_free_pending() is
 *    called and it starts processing the list from the initial element,
 *    i.e. the list tail.
 *
 *  - As each object is refcount finalized, new objects may be queued to
 *    refzero_list head.  Their 'next' pointers are left as garbage, but
 *    'prev' points are set correctly, with the element at refzero_list
 *    having a NULL 'prev' pointer.  The fact that refzero_list is non-NULL
 *    is used to reject (1) recursive duk__refcount_free_pending() and
 *    (2) finalize_list processing calls.
 *
 *  - When we're done with the current object, read its 'prev' pointer and
 *    free the object.  If 'prev' is NULL, we've reached head of list and are
 *    done: set refzero_list to NULL and process pending finalizers.  Otherwise
 *    continue processing the list.
 *
 *  A refzero cascade is free of side effects because it only involves
 *  queueing more objects and freeing memory; finalizer execution is blocked
 *  in the code path queueing objects to finalize_list.  As a result the
 *  initial refzero call (which triggers duk__refcount_free_pending()) must
 *  check finalize_list so that finalizers are executed snappily.
 *
 *  If finalize_list processing starts first, refzero may occur while we're
 *  processing finalizers.  That's fine: that particular refzero cascade is
 *  handled to completion without side effects.  Once the cascade is complete,
 *  we'll run pending finalizers but notice that we're already doing that and
 *  return.
 *
 *  This could be expanded to allow incremental freeing: just bail out
 *  early and resume at a future alloc/decref/refzero.  However, if that
 *  were done, the list structure would need to be kept consistent at all
 *  times, mark-and-sweep would need to handle refzero_list, etc.
 */

DUK_LOCAL void duk__refcount_free_pending(duk_heap *heap) {
	duk_heaphdr *curr;
#if defined(DUK_USE_DEBUG)
	duk_int_t count = 0;
#endif

	DUK_ASSERT(heap != NULL);

	curr = heap->refzero_list;
	DUK_ASSERT(curr != NULL);
	DUK_ASSERT(DUK_HEAPHDR_GET_PREV(heap, curr) == NULL);  /* We're called on initial insert only. */
	/* curr->next is GARBAGE. */

	do {
		duk_heaphdr *prev;

		DUK_DDD(DUK_DDDPRINT("refzero processing %p: %!O", (void *) curr, (duk_heaphdr *) curr));

#if defined(DUK_USE_DEBUG)
		count++;
#endif

		DUK_ASSERT(curr != NULL);
		DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT);  /* currently, always the case */
		/* FINALIZED may be set; don't care about flags here. */

		/* Refcount finalize 'curr'.  Refzero_list must be non-NULL
		 * here to prevent recursive entry to duk__refcount_free_pending().
		 */
		DUK_ASSERT(heap->refzero_list != NULL);
		duk_hobject_refcount_finalize_norz(heap, (duk_hobject *) curr);

		prev = DUK_HEAPHDR_GET_PREV(heap, curr);
		DUK_ASSERT((prev == NULL && heap->refzero_list == curr) || \
		           (prev != NULL && heap->refzero_list != curr));
		/* prev->next is intentionally not updated and is garbage. */

		duk_free_hobject(heap, (duk_hobject *) curr);  /* Invalidates 'curr'. */

		curr = prev;
	} while (curr != NULL);

	heap->refzero_list = NULL;

	DUK_DD(DUK_DDPRINT("refzero processed %ld objects", (long) count));
}

DUK_LOCAL DUK_INLINE void duk__refcount_refzero_hobject(duk_heap *heap, duk_hobject *obj, duk_bool_t skip_free_pending) {
	duk_heaphdr *hdr;
	duk_heaphdr *root;

	DUK_ASSERT(heap != NULL);
	DUK_ASSERT(heap->heap_thread != NULL);
	DUK_ASSERT(obj != NULL);
	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) obj) == DUK_HTYPE_OBJECT);

	hdr = (duk_heaphdr *) obj;

	/* Refzero'd objects must be in heap_allocated.  They can't be in
	 * finalize_list because all objects on finalize_list have an
	 * artificial +1 refcount bump.
	 */
#if defined(DUK_USE_ASSERTIONS)
	DUK_ASSERT(duk_heap_in_heap_allocated(heap, (duk_heaphdr *) obj));
#endif

	DUK_HEAP_REMOVE_FROM_HEAP_ALLOCATED(heap, hdr);

#if defined(DUK_USE_FINALIZER_SUPPORT)
	/* This finalizer check MUST BE side effect free.  It should also be
	 * as fast as possible because it's applied to every object freed.
	 */
	if (DUK_UNLIKELY(DUK_HOBJECT_HAS_FINALIZER_FAST(heap, (duk_hobject *) hdr) != 0U)) {
		/* Special case: FINALIZED may be set if mark-and-sweep queued
		 * object for finalization, the finalizer was executed (and
		 * FINALIZED set), mark-and-sweep hasn't yet processed the
		 * object again, but its refcount drops to zero.  Free without
		 * running the finalizer again.
		 */
		if (DUK_HEAPHDR_HAS_FINALIZED(hdr)) {
			DUK_D(DUK_DPRINT("refzero'd object has finalizer and FINALIZED is set -> free"));
		} else {
			/* Set FINALIZABLE flag so that all objects on finalize_list
			 * will have it set and are thus detectable based on the
			 * flag alone.
			 */
			DUK_HEAPHDR_SET_FINALIZABLE(hdr);
			DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(hdr));

#if defined(DUK_USE_REFERENCE_COUNTING)
			/* Bump refcount on finalize_list insert so that a
			 * refzero can never occur when an object is waiting
			 * for its finalizer call.  Refzero might otherwise
			 * now happen because we allow duk_push_heapptr() for
			 * objects pending finalization.
			 */
			DUK_HEAPHDR_PREINC_REFCOUNT(hdr);
#endif
			DUK_HEAP_INSERT_INTO_FINALIZE_LIST(heap, hdr);

			/* Process finalizers unless skipping is explicitly
			 * requested (NORZ) or refzero_list is being processed
			 * (avoids side effects during a refzero cascade).
			 * If refzero_list is processed, the initial refzero
			 * call will run pending finalizers when refzero_list
			 * is done.
			 */
			if (!skip_free_pending && heap->refzero_list == NULL) {
				duk_heap_process_finalize_list(heap);
			}
			return;
		}
	}
#endif  /* DUK_USE_FINALIZER_SUPPORT */

	/* No need to finalize, free object via refzero_list. */

	root = heap->refzero_list;

	DUK_HEAPHDR_SET_PREV(heap, hdr, NULL);
	/* 'next' is left as GARBAGE. */
	heap->refzero_list = hdr;

	if (root == NULL) {
		/* Object is now queued.  Refzero_list was NULL so
		 * no-one is currently processing it; do it here.
		 * With refzero processing just doing a cascade of
		 * free calls, we can process it directly even when
		 * NORZ macros are used: there are no side effects.
		 */
		duk__refcount_free_pending(heap);
		DUK_ASSERT(heap->refzero_list == NULL);

		/* Process finalizers only after the entire cascade
		 * is finished.  In most cases there's nothing to
		 * finalize, so fast path check to avoid a call.
		 */
#if defined(DUK_USE_FINALIZER_SUPPORT)
		if (!skip_free_pending && DUK_UNLIKELY(heap->finalize_list != NULL)) {
			duk_heap_process_finalize_list(heap);
		}
#endif
	} else {
		DUK_ASSERT(DUK_HEAPHDR_GET_PREV(heap, root) == NULL);
		DUK_HEAPHDR_SET_PREV(heap, root, hdr);

		/* Object is now queued.  Because refzero_list was
		 * non-NULL, it's already being processed by someone
		 * in the C call stack, so we're done.
		 */
	}
}

#if defined(DUK_USE_FINALIZER_SUPPORT)
DUK_INTERNAL DUK_ALWAYS_INLINE void duk_refzero_check_fast(duk_hthread *thr) {
	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(thr->heap != NULL);
	DUK_ASSERT(thr->heap->refzero_list == NULL);  /* Processed to completion inline. */

	if (DUK_UNLIKELY(thr->heap->finalize_list != NULL)) {
		duk_heap_process_finalize_list(thr->heap);
	}
}

DUK_INTERNAL void duk_refzero_check_slow(duk_hthread *thr) {
	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(thr->heap != NULL);
	DUK_ASSERT(thr->heap->refzero_list == NULL);  /* Processed to completion inline. */

	if (DUK_UNLIKELY(thr->heap->finalize_list != NULL)) {
		duk_heap_process_finalize_list(thr->heap);
	}
}
#endif  /* DUK_USE_FINALIZER_SUPPORT */

/*
 *  Refzero processing for duk_hstring.
 */

DUK_LOCAL DUK_INLINE void duk__refcount_refzero_hstring(duk_heap *heap, duk_hstring *str) {
	DUK_ASSERT(heap != NULL);
	DUK_ASSERT(heap->heap_thread != NULL);
	DUK_ASSERT(str != NULL);
	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) str) == DUK_HTYPE_STRING);

	duk_heap_strcache_string_remove(heap, str);
	duk_heap_strtable_unlink(heap, str);
	duk_free_hstring(heap, str);
}

/*
 *  Refzero processing for duk_hbuffer.
 */

DUK_LOCAL DUK_INLINE void duk__refcount_refzero_hbuffer(duk_heap *heap, duk_hbuffer *buf) {
	DUK_ASSERT(heap != NULL);
	DUK_ASSERT(heap->heap_thread != NULL);
	DUK_ASSERT(buf != NULL);
	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) buf) == DUK_HTYPE_BUFFER);

	DUK_HEAP_REMOVE_FROM_HEAP_ALLOCATED(heap, (duk_heaphdr *) buf);
	duk_free_hbuffer(heap, buf);
}

/*
 *  Incref and decref functions.
 *
 *  Decref may trigger immediate refzero handling, which may free and finalize
 *  an arbitrary number of objects (a "DECREF cascade").
 *
 *  Refzero handling is skipped entirely if (1) mark-and-sweep is running or
 *  (2) execution is paused in the debugger.  The objects are left in the heap,
 *  and will be freed by mark-and-sweep or eventual heap destruction.
 *
 *  This is necessary during mark-and-sweep because refcounts are also updated
 *  during the sweep phase (otherwise objects referenced by a swept object
 *  would have incorrect refcounts) which then calls here.  This could be
 *  avoided by using separate decref macros in mark-and-sweep; however,
 *  mark-and-sweep also calls finalizers which would use the ordinary decref
 *  macros anyway.
 *
 *  We can't process refzeros (= free objects) when the debugger is running
 *  as the debugger might make an object unreachable but still continue
 *  inspecting it (or even cause it to be pushed back).  So we must rely on
 *  mark-and-sweep to collect them.
 *
 *  The DUK__RZ_SUPPRESS_CHECK() condition is also used in heap destruction
 *  when running finalizers for remaining objects: the flag prevents objects
 *  from being moved around in heap linked lists while that's being done.
 *
 *  The suppress condition is important to performance.
 */

#define DUK__RZ_SUPPRESS_ASSERT1() do { \
		DUK_ASSERT(thr != NULL); \
		DUK_ASSERT(thr->heap != NULL); \
		/* When mark-and-sweep runs, heap_thread must exist. */ \
		DUK_ASSERT(thr->heap->ms_running == 0 || thr->heap->heap_thread != NULL); \
		/* In normal operation finalizers are executed with ms_running == 0 \
		 * so we should never see ms_running == 1 and thr != heap_thread. \
		 * In heap destruction finalizers are executed with ms_running != 0 \
		 * to e.g. prevent refzero; a special value ms_running == 2 is used \
		 * in that case so it can be distinguished from the normal runtime \
		 * case, and allows a stronger assertion here (GH-2030). \
		 */ \
		DUK_ASSERT(!(thr->heap->ms_running == 1 && thr != thr->heap->heap_thread)); \
		/* We may be called when the heap is initializing and we process \
		 * refzeros normally, but mark-and-sweep and finalizers are prevented \
		 * if that's the case. \
		 */ \
		DUK_ASSERT(thr->heap->heap_initializing == 0 || thr->heap->ms_prevent_count > 0); \
		DUK_ASSERT(thr->heap->heap_initializing == 0 || thr->heap->pf_prevent_count > 0); \
	} while (0)

#if defined(DUK_USE_DEBUGGER_SUPPORT)
#define DUK__RZ_SUPPRESS_ASSERT2() do { \
		/* When debugger is paused, ms_running is set. */ \
		DUK_ASSERT(!DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap) || thr->heap->ms_running != 0); \
	} while (0)
#define DUK__RZ_SUPPRESS_COND()  (heap->ms_running != 0)
#else
#define DUK__RZ_SUPPRESS_ASSERT2() do { } while (0)
#define DUK__RZ_SUPPRESS_COND()  (heap->ms_running != 0)
#endif  /* DUK_USE_DEBUGGER_SUPPORT */

#define DUK__RZ_SUPPRESS_CHECK() do { \
		DUK__RZ_SUPPRESS_ASSERT1(); \
		DUK__RZ_SUPPRESS_ASSERT2(); \
		if (DUK_UNLIKELY(DUK__RZ_SUPPRESS_COND())) { \
			DUK_DDD(DUK_DDDPRINT("refzero handling suppressed (not even queued) when mark-and-sweep running, object: %p", (void *) h)); \
			return; \
		} \
	} while (0)

#define DUK__RZ_STRING() do { \
		duk__refcount_refzero_hstring(heap, (duk_hstring *) h); \
	} while (0)
#define DUK__RZ_BUFFER() do { \
		duk__refcount_refzero_hbuffer(heap, (duk_hbuffer *) h); \
	} while (0)
#define DUK__RZ_OBJECT() do { \
		duk__refcount_refzero_hobject(heap, (duk_hobject *) h, skip_free_pending); \
	} while (0)

/* XXX: test the effect of inlining here vs. NOINLINE in refzero helpers */
#if defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
#define DUK__RZ_INLINE DUK_ALWAYS_INLINE
#else
#define DUK__RZ_INLINE /*nop*/
#endif

DUK_LOCAL DUK__RZ_INLINE void duk__hstring_refzero_helper(duk_hthread *thr, duk_hstring *h) {
	duk_heap *heap;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(h != NULL);
	heap = thr->heap;

	DUK__RZ_SUPPRESS_CHECK();
	DUK__RZ_STRING();
}

DUK_LOCAL DUK__RZ_INLINE void duk__hbuffer_refzero_helper(duk_hthread *thr, duk_hbuffer *h) {
	duk_heap *heap;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(h != NULL);
	heap = thr->heap;

	DUK__RZ_SUPPRESS_CHECK();
	DUK__RZ_BUFFER();
}

DUK_LOCAL DUK__RZ_INLINE void duk__hobject_refzero_helper(duk_hthread *thr, duk_hobject *h, duk_bool_t skip_free_pending) {
	duk_heap *heap;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(h != NULL);
	heap = thr->heap;

	DUK__RZ_SUPPRESS_CHECK();
	DUK__RZ_OBJECT();
}

DUK_LOCAL DUK__RZ_INLINE void duk__heaphdr_refzero_helper(duk_hthread *thr, duk_heaphdr *h, duk_bool_t skip_free_pending) {
	duk_heap *heap;
	duk_small_uint_t htype;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(h != NULL);
	heap = thr->heap;

	htype = (duk_small_uint_t) DUK_HEAPHDR_GET_TYPE(h);
	DUK_DDD(DUK_DDDPRINT("ms_running=%ld, heap_thread=%p", (long) thr->heap->ms_running, thr->heap->heap_thread));
	DUK__RZ_SUPPRESS_CHECK();

	switch (htype) {
	case DUK_HTYPE_STRING:
		/* Strings have no internal references but do have "weak"
		 * references in the string cache.  Also note that strings
		 * are not on the heap_allocated list like other heap
		 * elements.
		 */

		DUK__RZ_STRING();
		break;

	case DUK_HTYPE_OBJECT:
		/* Objects have internal references.  Must finalize through
		 * the "refzero" work list.
		 */

		DUK__RZ_OBJECT();
		break;

	default:
		/* Buffers have no internal references.  However, a dynamic
		 * buffer has a separate allocation for the buffer.  This is
		 * freed by duk_heap_free_heaphdr_raw().
		 */

		DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(h) == DUK_HTYPE_BUFFER);
		DUK__RZ_BUFFER();
		break;
	}
}

DUK_INTERNAL DUK_NOINLINE void duk_heaphdr_refzero(duk_hthread *thr, duk_heaphdr *h) {
	duk__heaphdr_refzero_helper(thr, h, 0 /*skip_free_pending*/);
}

DUK_INTERNAL DUK_NOINLINE void duk_heaphdr_refzero_norz(duk_hthread *thr, duk_heaphdr *h) {
	duk__heaphdr_refzero_helper(thr, h, 1 /*skip_free_pending*/);
}

DUK_INTERNAL DUK_NOINLINE void duk_hstring_refzero(duk_hthread *thr, duk_hstring *h) {
	duk__hstring_refzero_helper(thr, h);
}

DUK_INTERNAL DUK_NOINLINE void duk_hbuffer_refzero(duk_hthread *thr, duk_hbuffer *h) {
	duk__hbuffer_refzero_helper(thr, h);
}

DUK_INTERNAL DUK_NOINLINE void duk_hobject_refzero(duk_hthread *thr, duk_hobject *h) {
	duk__hobject_refzero_helper(thr, h, 0 /*skip_free_pending*/);
}

DUK_INTERNAL DUK_NOINLINE void duk_hobject_refzero_norz(duk_hthread *thr, duk_hobject *h) {
	duk__hobject_refzero_helper(thr, h, 1 /*skip_free_pending*/);
}

#if !defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
DUK_INTERNAL void duk_tval_incref(duk_tval *tv) {
	DUK_ASSERT(tv != NULL);

	if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv)) {
		duk_heaphdr *h = DUK_TVAL_GET_HEAPHDR(tv);
		DUK_ASSERT(h != NULL);
		DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
		DUK_ASSERT_DISABLE(h->h_refcount >= 0);
		DUK_HEAPHDR_PREINC_REFCOUNT(h);
		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(h) != 0);  /* No wrapping. */
	}
}

DUK_INTERNAL void duk_tval_decref(duk_hthread *thr, duk_tval *tv) {
	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(tv != NULL);

	if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv)) {
		duk_heaphdr *h = DUK_TVAL_GET_HEAPHDR(tv);
		DUK_ASSERT(h != NULL);
		DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(h) >= 1);
#if 0
		if (DUK_HEAPHDR_PREDEC_REFCOUNT(h) != 0) {
			return;
		}
		duk_heaphdr_refzero(thr, h);
#else
		duk_heaphdr_decref(thr, h);
#endif
	}
}

DUK_INTERNAL void duk_tval_decref_norz(duk_hthread *thr, duk_tval *tv) {
	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(tv != NULL);

	if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv)) {
		duk_heaphdr *h = DUK_TVAL_GET_HEAPHDR(tv);
		DUK_ASSERT(h != NULL);
		DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(h) >= 1);
#if 0
		if (DUK_HEAPHDR_PREDEC_REFCOUNT(h) != 0) {
			return;
		}
		duk_heaphdr_refzero_norz(thr, h);
#else
		duk_heaphdr_decref_norz(thr, h);
#endif
	}
}
#endif  /* !DUK_USE_FAST_REFCOUNT_DEFAULT */

#define DUK__DECREF_ASSERTS() do { \
		DUK_ASSERT(thr != NULL); \
		DUK_ASSERT(thr->heap != NULL); \
		DUK_ASSERT(h != NULL); \
		DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID((duk_heaphdr *) h)); \
		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) >= 1); \
	} while (0)
#if defined(DUK_USE_ROM_OBJECTS)
#define DUK__INCREF_SHARED() do { \
		if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h)) { \
			return; \
		} \
		DUK_HEAPHDR_PREINC_REFCOUNT((duk_heaphdr *) h); \
		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) != 0);  /* No wrapping. */ \
	} while (0)
#define DUK__DECREF_SHARED() do { \
		if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h)) { \
			return; \
		} \
		if (DUK_HEAPHDR_PREDEC_REFCOUNT((duk_heaphdr *) h) != 0) { \
			return; \
		} \
	} while (0)
#else
#define DUK__INCREF_SHARED() do { \
		DUK_HEAPHDR_PREINC_REFCOUNT((duk_heaphdr *) h); \
		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) != 0);  /* No wrapping. */ \
	} while (0)
#define DUK__DECREF_SHARED() do { \
		if (DUK_HEAPHDR_PREDEC_REFCOUNT((duk_heaphdr *) h) != 0) { \
			return; \
		} \
	} while (0)
#endif

#if !defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
/* This will in practice be inlined because it's just an INC instructions
 * and a bit test + INC when ROM objects are enabled.
 */
DUK_INTERNAL void duk_heaphdr_incref(duk_heaphdr *h) {
	DUK_ASSERT(h != NULL);
	DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
	DUK_ASSERT_DISABLE(DUK_HEAPHDR_GET_REFCOUNT(h) >= 0);

	DUK__INCREF_SHARED();
}

DUK_INTERNAL void duk_heaphdr_decref(duk_hthread *thr, duk_heaphdr *h) {
	DUK__DECREF_ASSERTS();
	DUK__DECREF_SHARED();
	duk_heaphdr_refzero(thr, h);

	/* Forced mark-and-sweep when GC torture enabled; this could happen
	 * on any DECREF (but not DECREF_NORZ).
	 */
	DUK_GC_TORTURE(thr->heap);
}
DUK_INTERNAL void duk_heaphdr_decref_norz(duk_hthread *thr, duk_heaphdr *h) {
	DUK__DECREF_ASSERTS();
	DUK__DECREF_SHARED();
	duk_heaphdr_refzero_norz(thr, h);
}
#endif  /* !DUK_USE_FAST_REFCOUNT_DEFAULT */

#if 0  /* Not needed. */
DUK_INTERNAL void duk_hstring_decref(duk_hthread *thr, duk_hstring *h) {
	DUK__DECREF_ASSERTS();
	DUK__DECREF_SHARED();
	duk_hstring_refzero(thr, h);
}
DUK_INTERNAL void duk_hstring_decref_norz(duk_hthread *thr, duk_hstring *h) {
	DUK__DECREF_ASSERTS();
	DUK__DECREF_SHARED();
	duk_hstring_refzero_norz(thr, h);
}
DUK_INTERNAL void duk_hbuffer_decref(duk_hthread *thr, duk_hbuffer *h) {
	DUK__DECREF_ASSERTS();
	DUK__DECREF_SHARED();
	duk_hbuffer_refzero(thr, h);
}
DUK_INTERNAL void duk_hbuffer_decref_norz(duk_hthread *thr, duk_hbuffer *h) {
	DUK__DECREF_ASSERTS();
	DUK__DECREF_SHARED();
	duk_hbuffer_refzero_norz(thr, h);
}
DUK_INTERNAL void duk_hobject_decref(duk_hthread *thr, duk_hobject *h) {
	DUK__DECREF_ASSERTS();
	DUK__DECREF_SHARED();
	duk_hobject_refzero(thr, h);
}
DUK_INTERNAL void duk_hobject_decref_norz(duk_hthread *thr, duk_hobject *h) {
	DUK__DECREF_ASSERTS();
	DUK__DECREF_SHARED();
	duk_hobject_refzero_norz(thr, h);
}
#endif

#else  /* DUK_USE_REFERENCE_COUNTING */

/* no refcounting */

#endif  /* DUK_USE_REFERENCE_COUNTING */

/* automatic undefs */
#undef DUK__DECREF_ASSERTS
#undef DUK__DECREF_SHARED
#undef DUK__INCREF_SHARED
#undef DUK__RZ_BUFFER
#undef DUK__RZ_INLINE
#undef DUK__RZ_OBJECT
#undef DUK__RZ_STRING
#undef DUK__RZ_SUPPRESS_ASSERT1
#undef DUK__RZ_SUPPRESS_ASSERT2
#undef DUK__RZ_SUPPRESS_CHECK
#undef DUK__RZ_SUPPRESS_COND
#line 1 "duk_heap_stringcache.c"
/*
 *  String cache.
 *
 *  Provides a cache to optimize indexed string lookups.  The cache keeps
 *  track of (byte offset, char offset) states for a fixed number of strings.
 *  Otherwise we'd need to scan from either end of the string, as we store
 *  strings in (extended) UTF-8.
 */

/* #include duk_internal.h -> already included */

/*
 *  Delete references to given hstring from the heap string cache.
 *
 *  String cache references are 'weak': they are not counted towards
 *  reference counts, nor serve as roots for mark-and-sweep.  When an
 *  object is about to be freed, such references need to be removed.
 */

DUK_INTERNAL void duk_heap_strcache_string_remove(duk_heap *heap, duk_hstring *h) {
	duk_uint_t i;
	for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
		duk_strcache_entry *c = heap->strcache + i;
		if (c->h == h) {
			DUK_DD(DUK_DDPRINT("deleting weak strcache reference to hstring %p from heap %p",
			                   (void *) h, (void *) heap));
			c->h = NULL;

			/* XXX: the string shouldn't appear twice, but we now loop to the
			 * end anyway; if fixed, add a looping assertion to ensure there
			 * is no duplicate.
			 */
		}
	}
}

/*
 *  String scanning helpers
 *
 *  All bytes other than UTF-8 continuation bytes ([0x80,0xbf]) are
 *  considered to contribute a character.  This must match how string
 *  character length is computed.
 */

DUK_LOCAL const duk_uint8_t *duk__scan_forwards(const duk_uint8_t *p, const duk_uint8_t *q, duk_uint_fast32_t n) {
	while (n > 0) {
		for (;;) {
			p++;
			if (p >= q) {
				return NULL;
			}
			if ((*p & 0xc0) != 0x80) {
				break;
			}
		}
		n--;
	}
	return p;
}

DUK_LOCAL const duk_uint8_t *duk__scan_backwards(const duk_uint8_t *p, const duk_uint8_t *q, duk_uint_fast32_t n) {
	while (n > 0) {
		for (;;) {
			p--;
			if (p < q) {
				return NULL;
			}
			if ((*p & 0xc0) != 0x80) {
				break;
			}
		}
		n--;
	}
	return p;
}

/*
 *  Convert char offset to byte offset
 *
 *  Avoid using the string cache if possible: for ASCII strings byte and
 *  char offsets are equal and for short strings direct scanning may be
 *  better than using the string cache (which may evict a more important
 *  entry).
 *
 *  Typing now assumes 32-bit string byte/char offsets (duk_uint_fast32_t).
 *  Better typing might be to use duk_size_t.
 *
 *  Caller should ensure 'char_offset' is within the string bounds [0,charlen]
 *  (endpoint is inclusive).  If this is not the case, no memory unsafe
 *  behavior will happen but an error will be thrown.
 */

DUK_INTERNAL duk_uint_fast32_t duk_heap_strcache_offset_char2byte(duk_hthread *thr, duk_hstring *h, duk_uint_fast32_t char_offset) {
	duk_heap *heap;
	duk_strcache_entry *sce;
	duk_uint_fast32_t byte_offset;
	duk_uint_t i;
	duk_bool_t use_cache;
	duk_uint_fast32_t dist_start, dist_end, dist_sce;
	duk_uint_fast32_t char_length;
	const duk_uint8_t *p_start;
	const duk_uint8_t *p_end;
	const duk_uint8_t *p_found;

	/*
	 *  For ASCII strings, the answer is simple.
	 */

	if (DUK_LIKELY(DUK_HSTRING_IS_ASCII(h))) {
		return char_offset;
	}

	char_length = (duk_uint_fast32_t) DUK_HSTRING_GET_CHARLEN(h);
	DUK_ASSERT(char_offset <= char_length);

	if (DUK_LIKELY(DUK_HSTRING_IS_ASCII(h))) {
		/* Must recheck because the 'is ascii' flag may be set
		 * lazily.  Alternatively, we could just compare charlen
		 * to bytelen.
		 */
		return char_offset;
	}

	/*
	 *  For non-ASCII strings, we need to scan forwards or backwards
	 *  from some starting point.  The starting point may be the start
	 *  or end of the string, or some cached midpoint in the string
	 *  cache.
	 *
	 *  For "short" strings we simply scan without checking or updating
	 *  the cache.  For longer strings we check and update the cache as
	 *  necessary, inserting a new cache entry if none exists.
	 */

	DUK_DDD(DUK_DDDPRINT("non-ascii string %p, char_offset=%ld, clen=%ld, blen=%ld",
	                     (void *) h, (long) char_offset,
	                     (long) DUK_HSTRING_GET_CHARLEN(h),
	                     (long) DUK_HSTRING_GET_BYTELEN(h)));

	heap = thr->heap;
	sce = NULL;
	use_cache = (char_length > DUK_HEAP_STRINGCACHE_NOCACHE_LIMIT);

	if (use_cache) {
#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
		DUK_DDD(DUK_DDDPRINT("stringcache before char2byte (using cache):"));
		for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
			duk_strcache_entry *c = heap->strcache + i;
			DUK_DDD(DUK_DDDPRINT("  [%ld] -> h=%p, cidx=%ld, bidx=%ld",
			                     (long) i, (void *) c->h, (long) c->cidx, (long) c->bidx));
		}
#endif

		for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
			duk_strcache_entry *c = heap->strcache + i;

			if (c->h == h) {
				sce = c;
				break;
			}
		}
	}

	/*
	 *  Scan from shortest distance:
	 *    - start of string
	 *    - end of string
	 *    - cache entry (if exists)
	 */

	DUK_ASSERT(DUK_HSTRING_GET_CHARLEN(h) >= char_offset);
	dist_start = char_offset;
	dist_end = char_length - char_offset;
	dist_sce = 0; DUK_UNREF(dist_sce);  /* initialize for debug prints, needed if sce==NULL */

	p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
	p_end = (const duk_uint8_t *) (p_start + DUK_HSTRING_GET_BYTELEN(h));
	p_found = NULL;

	if (sce) {
		if (char_offset >= sce->cidx) {
			dist_sce = char_offset - sce->cidx;
			if ((dist_sce <= dist_start) && (dist_sce <= dist_end)) {
				DUK_DDD(DUK_DDDPRINT("non-ascii string, use_cache=%ld, sce=%p:%ld:%ld, "
				                     "dist_start=%ld, dist_end=%ld, dist_sce=%ld => "
				                     "scan forwards from sce",
				                     (long) use_cache, (void *) (sce ? sce->h : NULL),
				                     (sce ? (long) sce->cidx : (long) -1),
				                     (sce ? (long) sce->bidx : (long) -1),
				                     (long) dist_start, (long) dist_end, (long) dist_sce));

				p_found = duk__scan_forwards(p_start + sce->bidx,
				                             p_end,
				                             dist_sce);
				goto scan_done;
			}
		} else {
			dist_sce = sce->cidx - char_offset;
			if ((dist_sce <= dist_start) && (dist_sce <= dist_end)) {
				DUK_DDD(DUK_DDDPRINT("non-ascii string, use_cache=%ld, sce=%p:%ld:%ld, "
				                     "dist_start=%ld, dist_end=%ld, dist_sce=%ld => "
				                     "scan backwards from sce",
				                     (long) use_cache, (void *) (sce ? sce->h : NULL),
				                     (sce ? (long) sce->cidx : (long) -1),
				                     (sce ? (long) sce->bidx : (long) -1),
				                     (long) dist_start, (long) dist_end, (long) dist_sce));

				p_found = duk__scan_backwards(p_start + sce->bidx,
				                              p_start,
				                              dist_sce);
				goto scan_done;
			}
		}
	}

	/* no sce, or sce scan not best */

	if (dist_start <= dist_end) {
		DUK_DDD(DUK_DDDPRINT("non-ascii string, use_cache=%ld, sce=%p:%ld:%ld, "
		                     "dist_start=%ld, dist_end=%ld, dist_sce=%ld => "
		                     "scan forwards from string start",
		                     (long) use_cache, (void *) (sce ? sce->h : NULL),
		                     (sce ? (long) sce->cidx : (long) -1),
		                     (sce ? (long) sce->bidx : (long) -1),
		                     (long) dist_start, (long) dist_end, (long) dist_sce));

		p_found = duk__scan_forwards(p_start,
		                             p_end,
		                             dist_start);
	} else {
		DUK_DDD(DUK_DDDPRINT("non-ascii string, use_cache=%ld, sce=%p:%ld:%ld, "
		                     "dist_start=%ld, dist_end=%ld, dist_sce=%ld => "
		                     "scan backwards from string end",
		                     (long) use_cache, (void *) (sce ? sce->h : NULL),
		                     (sce ? (long) sce->cidx : (long) -1),
		                     (sce ? (long) sce->bidx : (long) -1),
		                     (long) dist_start, (long) dist_end, (long) dist_sce));

		p_found = duk__scan_backwards(p_end,
		                              p_start,
		                              dist_end);
	}

 scan_done:

	if (DUK_UNLIKELY(p_found == NULL)) {
		/* Scan error: this shouldn't normally happen; it could happen if
		 * string is not valid UTF-8 data, and clen/blen are not consistent
		 * with the scanning algorithm.
		 */
		goto scan_error;
	}

	DUK_ASSERT(p_found >= p_start);
	DUK_ASSERT(p_found <= p_end);  /* may be equal */
	byte_offset = (duk_uint32_t) (p_found - p_start);

	DUK_DDD(DUK_DDDPRINT("-> string %p, cidx %ld -> bidx %ld",
	                     (void *) h, (long) char_offset, (long) byte_offset));

	/*
	 *  Update cache entry (allocating if necessary), and move the
	 *  cache entry to the first place (in an "LRU" policy).
	 */

	if (use_cache) {
		/* update entry, allocating if necessary */
		if (!sce) {
			sce = heap->strcache + DUK_HEAP_STRCACHE_SIZE - 1;  /* take last entry */
			sce->h = h;
		}
		DUK_ASSERT(sce != NULL);
		sce->bidx = (duk_uint32_t) (p_found - p_start);
		sce->cidx = (duk_uint32_t) char_offset;

		/* LRU: move our entry to first */
		if (sce > &heap->strcache[0]) {
			/*
			 *   A                  C
			 *   B                  A
			 *   C <- sce    ==>    B
			 *   D                  D
			 */
			duk_strcache_entry tmp;

			tmp = *sce;
			duk_memmove((void *) (&heap->strcache[1]),
			            (const void *) (&heap->strcache[0]),
			            (size_t) (((char *) sce) - ((char *) &heap->strcache[0])));
			heap->strcache[0] = tmp;

			/* 'sce' points to the wrong entry here, but is no longer used */
		}
#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
		DUK_DDD(DUK_DDDPRINT("stringcache after char2byte (using cache):"));
		for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
			duk_strcache_entry *c = heap->strcache + i;
			DUK_DDD(DUK_DDDPRINT("  [%ld] -> h=%p, cidx=%ld, bidx=%ld",
			                     (long) i, (void *) c->h, (long) c->cidx, (long) c->bidx));
		}
#endif
	}

	return byte_offset;

 scan_error:
	DUK_ERROR_INTERNAL(thr);
	DUK_WO_NORETURN(return 0;);
}
#line 1 "duk_heap_stringtable.c"
/*
 *  Heap string table handling, string interning.
 */

/* #include duk_internal.h -> already included */

/* Resize checks not needed if minsize == maxsize, typical for low memory
 * targets.
 */
#define DUK__STRTAB_RESIZE_CHECK
#if (DUK_USE_STRTAB_MINSIZE == DUK_USE_STRTAB_MAXSIZE)
#undef DUK__STRTAB_RESIZE_CHECK
#endif

#if defined(DUK_USE_STRTAB_PTRCOMP)
#define DUK__HEAPPTR_ENC16(heap,ptr)    DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (ptr))
#define DUK__HEAPPTR_DEC16(heap,val)    DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (val))
#define DUK__GET_STRTABLE(heap)         ((heap)->strtable16)
#else
#define DUK__HEAPPTR_ENC16(heap,ptr)    (ptr)
#define DUK__HEAPPTR_DEC16(heap,val)    (val)
#define DUK__GET_STRTABLE(heap)         ((heap)->strtable)
#endif

#define DUK__STRTAB_U32_MAX_STRLEN      10               /* 4'294'967'295 */

/*
 *  Debug dump stringtable.
 */

#if defined(DUK_USE_DEBUG)
DUK_INTERNAL void duk_heap_strtable_dump(duk_heap *heap) {
#if defined(DUK_USE_STRTAB_PTRCOMP)
	duk_uint16_t *strtable;
#else
	duk_hstring **strtable;
#endif
	duk_uint32_t i;
	duk_hstring *h;
	duk_size_t count_total = 0;
	duk_size_t count_chain;
	duk_size_t count_chain_min = DUK_SIZE_MAX;
	duk_size_t count_chain_max = 0;
	duk_size_t count_len[8];  /* chain lengths from 0 to 7 */

	if (heap == NULL) {
		DUK_D(DUK_DPRINT("string table, heap=NULL"));
		return;
	}

	strtable = DUK__GET_STRTABLE(heap);
	if (strtable == NULL) {
		DUK_D(DUK_DPRINT("string table, strtab=NULL"));
		return;
	}

	duk_memzero((void *) count_len, sizeof(count_len));
	for (i = 0; i < heap->st_size; i++) {
		h = DUK__HEAPPTR_DEC16(heap, strtable[i]);
		count_chain = 0;
		while (h != NULL) {
			count_chain++;
			h = h->hdr.h_next;
		}
		if (count_chain < sizeof(count_len) / sizeof(duk_size_t)) {
			count_len[count_chain]++;
		}
		count_chain_max = (count_chain > count_chain_max ? count_chain : count_chain_max);
		count_chain_min = (count_chain < count_chain_min ? count_chain : count_chain_min);
		count_total += count_chain;
	}

	DUK_D(DUK_DPRINT("string table, strtab=%p, count=%lu, chain min=%lu max=%lu avg=%lf: "
	                 "counts: %lu %lu %lu %lu %lu %lu %lu %lu ...",
	                 (void *) heap->strtable, (unsigned long) count_total,
	                 (unsigned long) count_chain_min, (unsigned long) count_chain_max,
	                 (double) count_total / (double) heap->st_size,
	                 (unsigned long) count_len[0], (unsigned long) count_len[1],
	                 (unsigned long) count_len[2], (unsigned long) count_len[3],
	                 (unsigned long) count_len[4], (unsigned long) count_len[5],
	                 (unsigned long) count_len[6], (unsigned long) count_len[7]));
}
#endif  /* DUK_USE_DEBUG */

/*
 *  Assertion helper to ensure strtable is populated correctly.
 */

#if defined(DUK_USE_ASSERTIONS)
DUK_LOCAL void duk__strtable_assert_checks(duk_heap *heap) {
#if defined(DUK_USE_STRTAB_PTRCOMP)
	duk_uint16_t *strtable;
#else
	duk_hstring **strtable;
#endif
	duk_uint32_t i;
	duk_hstring *h;
	duk_size_t count = 0;

	DUK_ASSERT(heap != NULL);

	strtable = DUK__GET_STRTABLE(heap);
	if (strtable != NULL) {
		DUK_ASSERT(heap->st_size != 0);
		DUK_ASSERT(heap->st_mask == heap->st_size - 1);

		for (i = 0; i < heap->st_size; i++) {
			h = DUK__HEAPPTR_DEC16(heap, strtable[i]);
			while (h != NULL) {
				DUK_ASSERT((DUK_HSTRING_GET_HASH(h) & heap->st_mask) == i);
				count++;
				h = h->hdr.h_next;
			}
		}
	} else {
		DUK_ASSERT(heap->st_size == 0);
		DUK_ASSERT(heap->st_mask == 0);
	}

#if defined(DUK__STRTAB_RESIZE_CHECK)
	DUK_ASSERT(count == (duk_size_t) heap->st_count);
#endif
}
#endif  /* DUK_USE_ASSERTIONS */

/*
 *  Allocate and initialize a duk_hstring.
 *
 *  Returns a NULL if allocation or initialization fails for some reason.
 *
 *  The string won't be inserted into the string table and isn't tracked in
 *  any way (link pointers will be NULL).  The caller must place the string
 *  into the string table without any risk of a longjmp, otherwise the string
 *  is leaked.
 */

DUK_LOCAL duk_hstring *duk__strtable_alloc_hstring(duk_heap *heap,
                                                   const duk_uint8_t *str,
                                                   duk_uint32_t blen,
                                                   duk_uint32_t strhash,
                                                   const duk_uint8_t *extdata) {
	duk_hstring *res;
	const duk_uint8_t *data;
#if !defined(DUK_USE_HSTRING_ARRIDX)
	duk_uarridx_t dummy;
#endif

	DUK_ASSERT(heap != NULL);
	DUK_UNREF(extdata);

#if defined(DUK_USE_STRLEN16)
	/* If blen <= 0xffffUL, clen is also guaranteed to be <= 0xffffUL. */
	if (blen > 0xffffUL) {
		DUK_D(DUK_DPRINT("16-bit string blen/clen active and blen over 16 bits, reject intern"));
		goto alloc_error;
	}
#endif

	/* XXX: Memzeroing the allocated structure is not really necessary
	 * because we could just initialize all fields explicitly (almost
	 * all fields are initialized explicitly anyway).
	 */
#if defined(DUK_USE_HSTRING_EXTDATA) && defined(DUK_USE_EXTSTR_INTERN_CHECK)
	if (extdata) {
		res = (duk_hstring *) DUK_ALLOC(heap, sizeof(duk_hstring_external));
		if (DUK_UNLIKELY(res == NULL)) {
			goto alloc_error;
		}
		duk_memzero(res, sizeof(duk_hstring_external));
#if defined(DUK_USE_EXPLICIT_NULL_INIT)
		DUK_HEAPHDR_STRING_INIT_NULLS(&res->hdr);
#endif
		DUK_HEAPHDR_SET_TYPE_AND_FLAGS(&res->hdr, DUK_HTYPE_STRING, DUK_HSTRING_FLAG_EXTDATA);

		DUK_ASSERT(extdata[blen] == 0);  /* Application responsibility. */
		data = extdata;
		((duk_hstring_external *) res)->extdata = extdata;
	} else
#endif  /* DUK_USE_HSTRING_EXTDATA && DUK_USE_EXTSTR_INTERN_CHECK */
	{
		duk_uint8_t *data_tmp;

		/* NUL terminate for convenient C access */
		DUK_ASSERT(sizeof(duk_hstring) + blen + 1 > blen);  /* No wrap, limits ensure. */
		res = (duk_hstring *) DUK_ALLOC(heap, sizeof(duk_hstring) + blen + 1);
		if (DUK_UNLIKELY(res == NULL)) {
			goto alloc_error;
		}
		duk_memzero(res, sizeof(duk_hstring));
#if defined(DUK_USE_EXPLICIT_NULL_INIT)
		DUK_HEAPHDR_STRING_INIT_NULLS(&res->hdr);
#endif
		DUK_HEAPHDR_SET_TYPE_AND_FLAGS(&res->hdr, DUK_HTYPE_STRING, 0);

		data_tmp = (duk_uint8_t *) (res + 1);
		duk_memcpy(data_tmp, str, blen);
		data_tmp[blen] = (duk_uint8_t) 0;
		data = (const duk_uint8_t *) data_tmp;
	}

	DUK_HSTRING_SET_BYTELEN(res, blen);
	DUK_HSTRING_SET_HASH(res, strhash);

	DUK_ASSERT(!DUK_HSTRING_HAS_ARRIDX(res));
#if defined(DUK_USE_HSTRING_ARRIDX)
	res->arridx = duk_js_to_arrayindex_string(data, blen);
	if (res->arridx != DUK_HSTRING_NO_ARRAY_INDEX) {
#else
	dummy = duk_js_to_arrayindex_string(data, blen);
	if (dummy != DUK_HSTRING_NO_ARRAY_INDEX) {
#endif
		/* Array index strings cannot be symbol strings,
		 * and they're always pure ASCII so blen == clen.
		 */
		DUK_HSTRING_SET_ARRIDX(res);
		DUK_HSTRING_SET_ASCII(res);
		DUK_ASSERT(duk_unicode_unvalidated_utf8_length(data, (duk_size_t) blen) == blen);
	} else {
		/* Because 'data' is NUL-terminated, we don't need a
		 * blen > 0 check here.  For NUL (0x00) the symbol
		 * checks will be false.
		 */
		if (DUK_UNLIKELY(data[0] >= 0x80U)) {
			if (data[0] <= 0x81) {
				DUK_HSTRING_SET_SYMBOL(res);
			} else if (data[0] == 0x82U || data[0] == 0xffU) {
				DUK_HSTRING_SET_HIDDEN(res);
				DUK_HSTRING_SET_SYMBOL(res);
			}
		}

		/* Using an explicit 'ASCII' flag has larger footprint (one call site
		 * only) but is quite useful for the case when there's no explicit
		 * 'clen' in duk_hstring.
		 *
		 * The flag is set lazily for RAM strings.
		 */
		DUK_ASSERT(!DUK_HSTRING_HAS_ASCII(res));

#if defined(DUK_USE_HSTRING_LAZY_CLEN)
		/* Charlen initialized to 0, updated on-the-fly. */
#else
		duk_hstring_init_charlen(res);  /* Also sets ASCII flag. */
#endif
	}

	DUK_DDD(DUK_DDDPRINT("interned string, hash=0x%08lx, blen=%ld, has_arridx=%ld, has_extdata=%ld",
	                     (unsigned long) DUK_HSTRING_GET_HASH(res),
	                     (long) DUK_HSTRING_GET_BYTELEN(res),
	                     (long) (DUK_HSTRING_HAS_ARRIDX(res) ? 1 : 0),
	                     (long) (DUK_HSTRING_HAS_EXTDATA(res) ? 1 : 0)));

	DUK_ASSERT(res != NULL);
	return res;

 alloc_error:
	return NULL;
}

/*
 *  Grow strtable allocation in-place.
 */

#if defined(DUK__STRTAB_RESIZE_CHECK)
DUK_LOCAL void duk__strtable_grow_inplace(duk_heap *heap) {
	duk_uint32_t new_st_size;
	duk_uint32_t old_st_size;
	duk_uint32_t i;
	duk_hstring *h;
	duk_hstring *next;
	duk_hstring *prev;
#if defined(DUK_USE_STRTAB_PTRCOMP)
	duk_uint16_t *new_ptr;
	duk_uint16_t *new_ptr_high;
#else
	duk_hstring **new_ptr;
	duk_hstring **new_ptr_high;
#endif

	DUK_DD(DUK_DDPRINT("grow in-place: %lu -> %lu", (unsigned long) heap->st_size, (unsigned long) heap->st_size * 2));

	DUK_ASSERT(heap != NULL);
	DUK_ASSERT(heap->st_resizing == 1);
	DUK_ASSERT(heap->st_size >= 2);
	DUK_ASSERT((heap->st_size & (heap->st_size - 1)) == 0);  /* 2^N */
	DUK_ASSERT(DUK__GET_STRTABLE(heap) != NULL);

	DUK_STATS_INC(heap, stats_strtab_resize_grow);

	new_st_size = heap->st_size << 1U;
	DUK_ASSERT(new_st_size > heap->st_size);  /* No overflow. */

	/* Reallocate the strtable first and then work in-place to rehash
	 * strings.  We don't need an indirect allocation here: even if GC
	 * is triggered to satisfy the allocation, recursive strtable resize
	 * is prevented by flags.  This is also why we don't need to use
	 * DUK_REALLOC_INDIRECT().
	 */

#if defined(DUK_USE_STRTAB_PTRCOMP)
	new_ptr = (duk_uint16_t *) DUK_REALLOC(heap, heap->strtable16, sizeof(duk_uint16_t) * new_st_size);
#else
	new_ptr = (duk_hstring **) DUK_REALLOC(heap, heap->strtable, sizeof(duk_hstring *) * new_st_size);
#endif
	if (DUK_UNLIKELY(new_ptr == NULL)) {
		/* If realloc fails we can continue normally: the string table
		 * won't "fill up" although chains will gradually get longer.
		 * When string insertions continue, we'll quite soon try again
		 * with no special handling.
		 */
		DUK_D(DUK_DPRINT("string table grow failed, ignoring"));
		return;
	}
#if defined(DUK_USE_STRTAB_PTRCOMP)
	heap->strtable16 = new_ptr;
#else
	heap->strtable = new_ptr;
#endif

	/* Rehash a single bucket into two separate ones.  When we grow
	 * by x2 the highest 'new' bit determines whether a string remains
	 * in its old position (bit is 0) or goes to a new one (bit is 1).
	 */

	old_st_size = heap->st_size;
	new_ptr_high = new_ptr + old_st_size;
	for (i = 0; i < old_st_size; i++) {
		duk_hstring *new_root;
		duk_hstring *new_root_high;

		h = DUK__HEAPPTR_DEC16(heap, new_ptr[i]);
		new_root = h;
		new_root_high = NULL;

		prev = NULL;
		while (h != NULL) {
			duk_uint32_t mask;

			DUK_ASSERT((DUK_HSTRING_GET_HASH(h) & heap->st_mask) == i);
			next = h->hdr.h_next;

			/* Example: if previous size was 256, previous mask is 0xFF
			 * and size is 0x100 which corresponds to the new bit that
			 * comes into play.
			 */
			DUK_ASSERT(heap->st_mask == old_st_size - 1);
			mask = old_st_size;
			if (DUK_HSTRING_GET_HASH(h) & mask) {
				if (prev != NULL) {
					prev->hdr.h_next = h->hdr.h_next;
				} else {
					DUK_ASSERT(h == new_root);
					new_root = h->hdr.h_next;
				}

				h->hdr.h_next = new_root_high;
				new_root_high = h;
			} else {
				prev = h;
			}
			h = next;
		}

		new_ptr[i] = DUK__HEAPPTR_ENC16(heap, new_root);
		new_ptr_high[i] = DUK__HEAPPTR_ENC16(heap, new_root_high);
	}

	heap->st_size = new_st_size;
	heap->st_mask = new_st_size - 1;

#if defined(DUK_USE_ASSERTIONS)
	duk__strtable_assert_checks(heap);
#endif
}
#endif  /* DUK__STRTAB_RESIZE_CHECK */

/*
 *  Shrink strtable allocation in-place.
 */

#if defined(DUK__STRTAB_RESIZE_CHECK)
DUK_LOCAL void duk__strtable_shrink_inplace(duk_heap *heap) {
	duk_uint32_t new_st_size;
	duk_uint32_t i;
	duk_hstring *h;
	duk_hstring *other;
	duk_hstring *root;
#if defined(DUK_USE_STRTAB_PTRCOMP)
	duk_uint16_t *old_ptr;
	duk_uint16_t *old_ptr_high;
	duk_uint16_t *new_ptr;
#else
	duk_hstring **old_ptr;
	duk_hstring **old_ptr_high;
	duk_hstring **new_ptr;
#endif

	DUK_DD(DUK_DDPRINT("shrink in-place: %lu -> %lu", (unsigned long) heap->st_size, (unsigned long) heap->st_size / 2));

	DUK_ASSERT(heap != NULL);
	DUK_ASSERT(heap->st_resizing == 1);
	DUK_ASSERT(heap->st_size >= 2);
	DUK_ASSERT((heap->st_size & (heap->st_size - 1)) == 0);  /* 2^N */
	DUK_ASSERT(DUK__GET_STRTABLE(heap) != NULL);

	DUK_STATS_INC(heap, stats_strtab_resize_shrink);

	new_st_size = heap->st_size >> 1U;

	/* Combine two buckets into a single one.  When we shrink, one hash
	 * bit (highest) disappears.
	 */
	old_ptr = DUK__GET_STRTABLE(heap);
	old_ptr_high = old_ptr + new_st_size;
	for (i = 0; i < new_st_size; i++) {
		h = DUK__HEAPPTR_DEC16(heap, old_ptr[i]);
		other = DUK__HEAPPTR_DEC16(heap, old_ptr_high[i]);

		if (h == NULL) {
			/* First chain is empty, so use second one as is. */
			root = other;
		} else {
			/* Find end of first chain, and link in the second. */
			root = h;
			while (h->hdr.h_next != NULL) {
				h = h->hdr.h_next;
			}
			h->hdr.h_next = other;
		}

		old_ptr[i] = DUK__HEAPPTR_ENC16(heap, root);
	}

	heap->st_size = new_st_size;
	heap->st_mask = new_st_size - 1;

	/* The strtable is now consistent and we can realloc safely.  Even
	 * if side effects cause string interning or removal the strtable
	 * updates are safe.  Recursive resize has been prevented by caller.
	 * This is also why we don't need to use DUK_REALLOC_INDIRECT().
	 *
	 * We assume a realloc() to a smaller size is guaranteed to succeed.
	 * It would be relatively straightforward to handle the error by
	 * essentially performing a "grow" step to recover.
	 */

#if defined(DUK_USE_STRTAB_PTRCOMP)
	new_ptr = (duk_uint16_t *) DUK_REALLOC(heap, heap->strtable16, sizeof(duk_uint16_t) * new_st_size);
	DUK_ASSERT(new_ptr != NULL);
	heap->strtable16 = new_ptr;
#else
	new_ptr = (duk_hstring **) DUK_REALLOC(heap, heap->strtable, sizeof(duk_hstring *) * new_st_size);
	DUK_ASSERT(new_ptr != NULL);
	heap->strtable = new_ptr;
#endif

#if defined(DUK_USE_ASSERTIONS)
	duk__strtable_assert_checks(heap);
#endif
}
#endif  /* DUK__STRTAB_RESIZE_CHECK */

/*
 *  Grow/shrink check.
 */

#if defined(DUK__STRTAB_RESIZE_CHECK)
DUK_LOCAL DUK_COLD DUK_NOINLINE void duk__strtable_resize_check(duk_heap *heap) {
	duk_uint32_t load_factor;  /* fixed point */

	DUK_ASSERT(heap != NULL);
#if defined(DUK_USE_STRTAB_PTRCOMP)
	DUK_ASSERT(heap->strtable16 != NULL);
#else
	DUK_ASSERT(heap->strtable != NULL);
#endif

	DUK_STATS_INC(heap, stats_strtab_resize_check);

	/* Prevent recursive resizing. */
	if (DUK_UNLIKELY(heap->st_resizing != 0U)) {
		DUK_D(DUK_DPRINT("prevent recursive strtable resize"));
		return;
	}

	heap->st_resizing = 1;

	DUK_ASSERT(heap->st_size >= 16U);
	DUK_ASSERT((heap->st_size >> 4U) >= 1);
	load_factor = heap->st_count / (heap->st_size >> 4U);

	DUK_DD(DUK_DDPRINT("resize check string table: size=%lu, count=%lu, load_factor=%lu (fixed point .4; float %lf)",
	                   (unsigned long) heap->st_size, (unsigned long) heap->st_count,
	                   (unsigned long) load_factor,
	                   (double) heap->st_count / (double) heap->st_size));

	if (load_factor >= DUK_USE_STRTAB_GROW_LIMIT) {
		if (heap->st_size >= DUK_USE_STRTAB_MAXSIZE) {
			DUK_DD(DUK_DDPRINT("want to grow strtable (based on load factor) but already maximum size"));
		} else {
			DUK_D(DUK_DPRINT("grow string table: %lu -> %lu", (unsigned long) heap->st_size, (unsigned long) heap->st_size * 2));
#if defined(DUK_USE_DEBUG)
			duk_heap_strtable_dump(heap);
#endif
			duk__strtable_grow_inplace(heap);
		}
	} else if (load_factor <= DUK_USE_STRTAB_SHRINK_LIMIT) {
		if (heap->st_size <= DUK_USE_STRTAB_MINSIZE) {
			DUK_DD(DUK_DDPRINT("want to shrink strtable (based on load factor) but already minimum size"));
		} else {
			DUK_D(DUK_DPRINT("shrink string table: %lu -> %lu", (unsigned long) heap->st_size, (unsigned long) heap->st_size / 2));
#if defined(DUK_USE_DEBUG)
			duk_heap_strtable_dump(heap);
#endif
			duk__strtable_shrink_inplace(heap);
		}
	} else {
		DUK_DD(DUK_DDPRINT("no need for strtable resize"));
	}

	heap->st_resizing = 0;
}
#endif  /* DUK__STRTAB_RESIZE_CHECK */

/*
 *  Torture grow/shrink: unconditionally grow and shrink back.
 */

#if defined(DUK_USE_STRTAB_TORTURE) && defined(DUK__STRTAB_RESIZE_CHECK)
DUK_LOCAL void duk__strtable_resize_torture(duk_heap *heap) {
	duk_uint32_t old_st_size;

	DUK_ASSERT(heap != NULL);

	old_st_size = heap->st_size;
	if (old_st_size >= DUK_USE_STRTAB_MAXSIZE) {
		return;
	}

	heap->st_resizing = 1;
	duk__strtable_grow_inplace(heap);
	if (heap->st_size > old_st_size) {
		duk__strtable_shrink_inplace(heap);
	}
	heap->st_resizing = 0;
}
#endif  /* DUK_USE_STRTAB_TORTURE && DUK__STRTAB_RESIZE_CHECK */

/*
 *  Raw intern; string already checked not to be present.
 */

DUK_LOCAL duk_hstring *duk__strtable_do_intern(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t strhash) {
	duk_hstring *res;
	const duk_uint8_t *extdata;
#if defined(DUK_USE_STRTAB_PTRCOMP)
	duk_uint16_t *slot;
#else
	duk_hstring **slot;
#endif

	DUK_DDD(DUK_DDDPRINT("do_intern: heap=%p, str=%p, blen=%lu, strhash=%lx, st_size=%lu, st_count=%lu, load=%lf",
	                     (void *) heap, (const void *) str, (unsigned long) blen, (unsigned long) strhash,
	                     (unsigned long) heap->st_size, (unsigned long) heap->st_count,
	                     (double) heap->st_count / (double) heap->st_size));

	DUK_ASSERT(heap != NULL);

	/* Prevent any side effects on the string table and the caller provided
	 * str/blen arguments while interning is in progress.  For example, if
	 * the caller provided str/blen from a dynamic buffer, a finalizer
	 * might resize or modify that dynamic buffer, invalidating the call
	 * arguments.
	 *
	 * While finalizers must be prevented, mark-and-sweep itself is fine.
	 * Recursive string table resize is prevented explicitly here.
	 */

	heap->pf_prevent_count++;
	DUK_ASSERT(heap->pf_prevent_count != 0);  /* Wrap. */

#if defined(DUK_USE_STRTAB_TORTURE) && defined(DUK__STRTAB_RESIZE_CHECK)
	duk__strtable_resize_torture(heap);
#endif

	/* String table grow/shrink check.  Because of chaining (and no
	 * accumulation issues as with hash probe chains and DELETED
	 * markers) there's never a mandatory need to resize right now.
	 * Check for the resize only periodically, based on st_count
	 * bit pattern.  Because string table removal doesn't do a shrink
	 * check, we do that also here.
	 *
	 * Do the resize and possible grow/shrink before the new duk_hstring
	 * has been allocated.  Otherwise we may trigger a GC when the result
	 * duk_hstring is not yet strongly referenced.
	 */

#if defined(DUK__STRTAB_RESIZE_CHECK)
	if (DUK_UNLIKELY((heap->st_count & DUK_USE_STRTAB_RESIZE_CHECK_MASK) == 0)) {
		duk__strtable_resize_check(heap);
	}
#endif

	/* External string check (low memory optimization). */

#if defined(DUK_USE_HSTRING_EXTDATA) && defined(DUK_USE_EXTSTR_INTERN_CHECK)
	extdata = (const duk_uint8_t *) DUK_USE_EXTSTR_INTERN_CHECK(heap->heap_udata, (void *) DUK_LOSE_CONST(str), (duk_size_t) blen);
#else
	extdata = (const duk_uint8_t *) NULL;
#endif

	/* Allocate and initialize string, not yet linked.  This may cause a
	 * GC which may cause other strings to be interned and inserted into
	 * the string table before we insert our string.  Finalizer execution
	 * is disabled intentionally to avoid a finalizer from e.g. resizing
	 * a buffer used as a data area for 'str'.
	 */

	res = duk__strtable_alloc_hstring(heap, str, blen, strhash, extdata);

	/* Allow side effects again: GC must be avoided until duk_hstring
	 * result (if successful) has been INCREF'd.
	 */
	DUK_ASSERT(heap->pf_prevent_count > 0);
	heap->pf_prevent_count--;

	/* Alloc error handling. */

	if (DUK_UNLIKELY(res == NULL)) {
#if defined(DUK_USE_HSTRING_EXTDATA) && defined(DUK_USE_EXTSTR_INTERN_CHECK)
		if (extdata != NULL) {
			DUK_USE_EXTSTR_FREE(heap->heap_udata, (const void *) extdata);
		}
#endif
		return NULL;
	}

	/* Insert into string table. */

#if defined(DUK_USE_STRTAB_PTRCOMP)
	slot = heap->strtable16 + (strhash & heap->st_mask);
#else
	slot = heap->strtable + (strhash & heap->st_mask);
#endif
	DUK_ASSERT(res->hdr.h_next == NULL);  /* This is the case now, but unnecessary zeroing/NULLing. */
	res->hdr.h_next = DUK__HEAPPTR_DEC16(heap, *slot);
	*slot = DUK__HEAPPTR_ENC16(heap, res);

	/* Update string count only for successful inserts. */

#if defined(DUK__STRTAB_RESIZE_CHECK)
	heap->st_count++;
#endif

	/* The duk_hstring is in the string table but is not yet strongly
	 * reachable.  Calling code MUST NOT make any allocations or other
	 * side effects before the duk_hstring has been INCREF'd and made
	 * reachable.
	 */

	return res;
}

/*
 *  Intern a string from str/blen, returning either an existing duk_hstring
 *  or adding a new one into the string table.  The input string does -not-
 *  need to be NUL terminated.
 *
 *  The input 'str' argument may point to a Duktape managed data area such as
 *  the data area of a dynamic buffer.  It's crucial to avoid any side effects
 *  that might affect the data area (e.g. resize the dynamic buffer, or write
 *  to the buffer) before the string is fully interned.
 */

#if defined(DUK_USE_ROM_STRINGS)
DUK_LOCAL duk_hstring *duk__strtab_romstring_lookup(duk_heap *heap, const duk_uint8_t *str, duk_size_t blen, duk_uint32_t strhash) {
	duk_size_t lookup_hash;
	duk_hstring *curr;

	DUK_ASSERT(heap != NULL);
	DUK_UNREF(heap);

	lookup_hash = (blen << 4);
	if (blen > 0) {
		lookup_hash += str[0];
	}
	lookup_hash &= 0xff;

	curr = (duk_hstring *) DUK_LOSE_CONST(duk_rom_strings_lookup[lookup_hash]);
	while (curr != NULL) {
		/* Unsafe memcmp() because for zero blen, str may be NULL. */
		if (strhash == DUK_HSTRING_GET_HASH(curr) &&
		    blen == DUK_HSTRING_GET_BYTELEN(curr) &&
		    duk_memcmp_unsafe((const void *) str, (const void *) DUK_HSTRING_GET_DATA(curr), blen) == 0) {
			DUK_DDD(DUK_DDDPRINT("intern check: rom string: %!O, computed hash 0x%08lx, rom hash 0x%08lx",
			                     curr, (unsigned long) strhash, (unsigned long) DUK_HSTRING_GET_HASH(curr)));
			return curr;
		}
		curr = curr->hdr.h_next;
	}

	return NULL;
}
#endif  /* DUK_USE_ROM_STRINGS */

DUK_INTERNAL duk_hstring *duk_heap_strtable_intern(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen) {
	duk_uint32_t strhash;
	duk_hstring *h;

	DUK_DDD(DUK_DDDPRINT("intern check: heap=%p, str=%p, blen=%lu", (void *) heap, (const void *) str, (unsigned long) blen));

	/* Preliminaries. */

	/* XXX: maybe just require 'str != NULL' even for zero size? */
	DUK_ASSERT(heap != NULL);
	DUK_ASSERT(blen == 0 || str != NULL);
	DUK_ASSERT(blen <= DUK_HSTRING_MAX_BYTELEN);  /* Caller is responsible for ensuring this. */
	strhash = duk_heap_hashstring(heap, str, (duk_size_t) blen);

	/* String table lookup. */

	DUK_ASSERT(DUK__GET_STRTABLE(heap) != NULL);
	DUK_ASSERT(heap->st_size > 0);
	DUK_ASSERT(heap->st_size == heap->st_mask + 1);
#if defined(DUK_USE_STRTAB_PTRCOMP)
	h = DUK__HEAPPTR_DEC16(heap, heap->strtable16[strhash & heap->st_mask]);
#else
	h = heap->strtable[strhash & heap->st_mask];
#endif
	while (h != NULL) {
		if (DUK_HSTRING_GET_HASH(h) == strhash &&
		    DUK_HSTRING_GET_BYTELEN(h) == blen &&
		    duk_memcmp_unsafe((const void *) str, (const void *) DUK_HSTRING_GET_DATA(h), (size_t) blen) == 0) {
			/* Found existing entry. */
			DUK_STATS_INC(heap, stats_strtab_intern_hit);
			return h;
		}
		h = h->hdr.h_next;
	}

	/* ROM table lookup.  Because this lookup is slower, do it only after
	 * RAM lookup.  This works because no ROM string is ever interned into
	 * the RAM string table.
	 */

#if defined(DUK_USE_ROM_STRINGS)
	h = duk__strtab_romstring_lookup(heap, str, blen, strhash);
	if (h != NULL) {
		DUK_STATS_INC(heap, stats_strtab_intern_hit);
		return h;
	}
#endif

	/* Not found in string table; insert. */

	DUK_STATS_INC(heap, stats_strtab_intern_miss);
	h = duk__strtable_do_intern(heap, str, blen, strhash);
	return h;  /* may be NULL */
}

/*
 *  Intern a string from u32.
 */

/* XXX: Could arrange some special handling because we know that the result
 * will have an arridx flag and an ASCII flag, won't need a clen check, etc.
 */

DUK_INTERNAL duk_hstring *duk_heap_strtable_intern_u32(duk_heap *heap, duk_uint32_t val) {
	duk_uint8_t buf[DUK__STRTAB_U32_MAX_STRLEN];
	duk_uint8_t *p;

	DUK_ASSERT(heap != NULL);

	/* This is smaller and faster than a %lu sprintf. */
	p = buf + sizeof(buf);
	do {
		p--;
		*p = duk_lc_digits[val % 10];
		val = val / 10;
	} while (val != 0);  /* For val == 0, emit exactly one '0'. */
	DUK_ASSERT(p >= buf);

	return duk_heap_strtable_intern(heap, (const duk_uint8_t *) p, (duk_uint32_t) ((buf + sizeof(buf)) - p));
}

/*
 *  Checked convenience variants.
 *
 *  XXX: Because the main use case is for the checked variants, make them the
 *  main functionality and provide a safe variant separately (it is only needed
 *  during heap init).  The problem with that is that longjmp state and error
 *  creation must already be possible to throw.
 */

DUK_INTERNAL duk_hstring *duk_heap_strtable_intern_checked(duk_hthread *thr, const duk_uint8_t *str, duk_uint32_t blen) {
	duk_hstring *res;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(thr->heap != NULL);
	DUK_ASSERT(blen == 0 || str != NULL);

	res = duk_heap_strtable_intern(thr->heap, str, blen);
	if (DUK_UNLIKELY(res == NULL)) {
		DUK_ERROR_ALLOC_FAILED(thr);
		DUK_WO_NORETURN(return NULL;);
	}
	return res;
}

#if defined(DUK_USE_LITCACHE_SIZE)
DUK_LOCAL duk_uint_t duk__strtable_litcache_key(const duk_uint8_t *str, duk_uint32_t blen) {
	duk_uintptr_t key;

	DUK_ASSERT(DUK_USE_LITCACHE_SIZE > 0);
	DUK_ASSERT(DUK_IS_POWER_OF_TWO((duk_uint_t) DUK_USE_LITCACHE_SIZE));

	key = (duk_uintptr_t) blen ^ (duk_uintptr_t) str;
	key &= (duk_uintptr_t) (DUK_USE_LITCACHE_SIZE - 1);  /* Assumes size is power of 2. */
	/* Due to masking, cast is in 32-bit range. */
	DUK_ASSERT(key <= DUK_UINT_MAX);
	return (duk_uint_t) key;
}

DUK_INTERNAL duk_hstring *duk_heap_strtable_intern_literal_checked(duk_hthread *thr, const duk_uint8_t *str, duk_uint32_t blen) {
	duk_uint_t key;
	duk_litcache_entry *ent;
	duk_hstring *h;

	/* Fast path check: literal exists in literal cache. */
	key = duk__strtable_litcache_key(str, blen);
	ent = thr->heap->litcache + key;
	if (ent->addr == str) {
		DUK_DD(DUK_DDPRINT("intern check for cached, pinned literal: str=%p, blen=%ld -> duk_hstring %!O",
		                   (const void *) str, (long) blen, (duk_heaphdr *) ent->h));
		DUK_ASSERT(ent->h != NULL);
		DUK_ASSERT(DUK_HSTRING_HAS_PINNED_LITERAL(ent->h));
		DUK_STATS_INC(thr->heap, stats_strtab_litcache_hit);
		return ent->h;
	}

	/* Intern and update (overwrite) cache entry. */
	h = duk_heap_strtable_intern_checked(thr, str, blen);
	ent->addr = str;
	ent->h = h;
	DUK_STATS_INC(thr->heap, stats_strtab_litcache_miss);

	/* Pin the duk_hstring until the next mark-and-sweep.  This means
	 * litcache entries don't need to be invalidated until the next
	 * mark-and-sweep as their target duk_hstring is not freed before
	 * the mark-and-sweep happens.  The pin remains even if the literal
	 * cache entry is overwritten, and is still useful to avoid string
	 * table traffic.
	 */
	if (!DUK_HSTRING_HAS_PINNED_LITERAL(h)) {
		DUK_DD(DUK_DDPRINT("pin duk_hstring because it is a literal: %!O", (duk_heaphdr *) h));
		DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h));
		DUK_HSTRING_INCREF(thr, h);
		DUK_HSTRING_SET_PINNED_LITERAL(h);
		DUK_STATS_INC(thr->heap, stats_strtab_litcache_pin);
	}

	return h;
}
#endif  /* DUK_USE_LITCACHE_SIZE */

DUK_INTERNAL duk_hstring *duk_heap_strtable_intern_u32_checked(duk_hthread *thr, duk_uint32_t val) {
	duk_hstring *res;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(thr->heap != NULL);

	res = duk_heap_strtable_intern_u32(thr->heap, val);
	if (DUK_UNLIKELY(res == NULL)) {
		DUK_ERROR_ALLOC_FAILED(thr);
		DUK_WO_NORETURN(return NULL;);
	}
	return res;
}

/*
 *  Remove (unlink) a string from the string table.
 *
 *  Just unlinks the duk_hstring, leaving link pointers as garbage.
 *  Caller must free the string itself.
 */

#if defined(DUK_USE_REFERENCE_COUNTING)
/* Unlink without a 'prev' pointer. */
DUK_INTERNAL void duk_heap_strtable_unlink(duk_heap *heap, duk_hstring *h) {
#if defined(DUK_USE_STRTAB_PTRCOMP)
	duk_uint16_t *slot;
#else
	duk_hstring **slot;
#endif
	duk_hstring *other;
	duk_hstring *prev;

	DUK_DDD(DUK_DDDPRINT("remove: heap=%p, h=%p, blen=%lu, strhash=%lx",
	                     (void *) heap, (void *) h,
	                     (unsigned long) (h != NULL ? DUK_HSTRING_GET_BYTELEN(h) : 0),
	                     (unsigned long) (h != NULL ? DUK_HSTRING_GET_HASH(h) : 0)));

	DUK_ASSERT(heap != NULL);
	DUK_ASSERT(h != NULL);

#if defined(DUK__STRTAB_RESIZE_CHECK)
	DUK_ASSERT(heap->st_count > 0);
	heap->st_count--;
#endif

#if defined(DUK_USE_STRTAB_PTRCOMP)
	slot = heap->strtable16 + (DUK_HSTRING_GET_HASH(h) & heap->st_mask);
#else
	slot = heap->strtable + (DUK_HSTRING_GET_HASH(h) & heap->st_mask);
#endif
	other = DUK__HEAPPTR_DEC16(heap, *slot);
	DUK_ASSERT(other != NULL);  /* At least argument string is in the chain. */

	prev = NULL;
	while (other != h) {
		prev = other;
		other = other->hdr.h_next;
		DUK_ASSERT(other != NULL);  /* We'll eventually find 'h'. */
	}
	if (prev != NULL) {
		/* Middle of list. */
		prev->hdr.h_next = h->hdr.h_next;
	} else {
		/* Head of list. */
		*slot = DUK__HEAPPTR_ENC16(heap, h->hdr.h_next);
	}

	/* There's no resize check on a string free.  The next string
	 * intern will do one.
	 */
}
#endif  /* DUK_USE_REFERENCE_COUNTING */

/* Unlink with a 'prev' pointer. */
DUK_INTERNAL void duk_heap_strtable_unlink_prev(duk_heap *heap, duk_hstring *h, duk_hstring *prev) {
#if defined(DUK_USE_STRTAB_PTRCOMP)
	duk_uint16_t *slot;
#else
	duk_hstring **slot;
#endif

	DUK_DDD(DUK_DDDPRINT("remove: heap=%p, prev=%p, h=%p, blen=%lu, strhash=%lx",
	                     (void *) heap, (void *) prev, (void *) h,
	                     (unsigned long) (h != NULL ? DUK_HSTRING_GET_BYTELEN(h) : 0),
	                     (unsigned long) (h != NULL ? DUK_HSTRING_GET_HASH(h) : 0)));

	DUK_ASSERT(heap != NULL);
	DUK_ASSERT(h != NULL);
	DUK_ASSERT(prev == NULL || prev->hdr.h_next == h);

#if defined(DUK__STRTAB_RESIZE_CHECK)
	DUK_ASSERT(heap->st_count > 0);
	heap->st_count--;
#endif

	if (prev != NULL) {
		/* Middle of list. */
		prev->hdr.h_next = h->hdr.h_next;
	} else {
		/* Head of list. */
#if defined(DUK_USE_STRTAB_PTRCOMP)
		slot = heap->strtable16 + (DUK_HSTRING_GET_HASH(h) & heap->st_mask);
#else
		slot = heap->strtable + (DUK_HSTRING_GET_HASH(h) & heap->st_mask);
#endif
		DUK_ASSERT(DUK__HEAPPTR_DEC16(heap, *slot) == h);
		*slot = DUK__HEAPPTR_ENC16(heap, h->hdr.h_next);
	}
}

/*
 *  Force string table resize check in mark-and-sweep.
 */

DUK_INTERNAL void duk_heap_strtable_force_resize(duk_heap *heap) {
	/* Does only one grow/shrink step if needed.  The heap->st_resizing
	 * flag protects against recursive resizing.
	 */

	DUK_ASSERT(heap != NULL);
	DUK_UNREF(heap);

#if defined(DUK__STRTAB_RESIZE_CHECK)
#if defined(DUK_USE_STRTAB_PTRCOMP)
	if (heap->strtable16 != NULL) {
#else
	if (heap->strtable != NULL) {
#endif
		duk__strtable_resize_check(heap);
	}
#endif
}

/*
 *  Free strings in the string table and the string table itself.
 */

DUK_INTERNAL void duk_heap_strtable_free(duk_heap *heap) {
#if defined(DUK_USE_STRTAB_PTRCOMP)
	duk_uint16_t *strtable;
	duk_uint16_t *st;
#else
	duk_hstring **strtable;
	duk_hstring **st;
#endif
	duk_hstring *h;

	DUK_ASSERT(heap != NULL);

#if defined(DUK_USE_ASSERTIONS)
	duk__strtable_assert_checks(heap);
#endif

	/* Strtable can be NULL if heap init fails.  However, in that case
	 * heap->st_size is 0, so strtable == strtable_end and we skip the
	 * loop without a special check.
	 */
	strtable = DUK__GET_STRTABLE(heap);
	st = strtable + heap->st_size;
	DUK_ASSERT(strtable != NULL || heap->st_size == 0);

	while (strtable != st) {
		--st;
		h = DUK__HEAPPTR_DEC16(heap, *st);
		while (h) {
			duk_hstring *h_next;
			h_next = h->hdr.h_next;

			/* Strings may have inner refs (extdata) in some cases. */
			duk_free_hstring(heap, h);

			h = h_next;
		}
	}

	DUK_FREE(heap, strtable);
}

/* automatic undefs */
#undef DUK__GET_STRTABLE
#undef DUK__HEAPPTR_DEC16
#undef DUK__HEAPPTR_ENC16
#undef DUK__STRTAB_U32_MAX_STRLEN
#line 1 "duk_heaphdr_assert.c"
/*
 *  duk_heaphdr assertion helpers
 */

/* #include duk_internal.h -> already included */

#if defined(DUK_USE_ASSERTIONS)

#if defined(DUK_USE_DOUBLE_LINKED_HEAP)
DUK_INTERNAL void duk_heaphdr_assert_links(duk_heap *heap, duk_heaphdr *h) {
	DUK_UNREF(heap);
	if (h != NULL) {
		duk_heaphdr *h_prev, *h_next;
		h_prev = DUK_HEAPHDR_GET_PREV(heap, h);
		h_next = DUK_HEAPHDR_GET_NEXT(heap, h);
		DUK_ASSERT(h_prev == NULL || (DUK_HEAPHDR_GET_NEXT(heap, h_prev) == h));
		DUK_ASSERT(h_next == NULL || (DUK_HEAPHDR_GET_PREV(heap, h_next) == h));
	}
}
#else
DUK_INTERNAL void duk_heaphdr_assert_links(duk_heap *heap, duk_heaphdr *h) {
	DUK_UNREF(heap);
	DUK_UNREF(h);
}
#endif

DUK_INTERNAL void duk_heaphdr_assert_valid(duk_heaphdr *h) {
	DUK_ASSERT(h != NULL);
	DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
}

/* Assert validity of a heaphdr, including all subclasses. */
DUK_INTERNAL void duk_heaphdr_assert_valid_subclassed(duk_heaphdr *h) {
	switch (DUK_HEAPHDR_GET_TYPE(h)) {
	case DUK_HTYPE_OBJECT: {
		duk_hobject *h_obj = (duk_hobject *) h;
		DUK_HOBJECT_ASSERT_VALID(h_obj);
		if (DUK_HOBJECT_IS_COMPFUNC(h_obj)) {
			DUK_HCOMPFUNC_ASSERT_VALID((duk_hcompfunc *) h_obj);
		} else if (DUK_HOBJECT_IS_NATFUNC(h_obj)) {
			DUK_HNATFUNC_ASSERT_VALID((duk_hnatfunc *) h_obj);
		} else if (DUK_HOBJECT_IS_DECENV(h_obj)) {
			DUK_HDECENV_ASSERT_VALID((duk_hdecenv *) h_obj);
		} else if (DUK_HOBJECT_IS_OBJENV(h_obj)) {
			DUK_HOBJENV_ASSERT_VALID((duk_hobjenv *) h_obj);
		} else if (DUK_HOBJECT_IS_BUFOBJ(h_obj)) {
#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
			DUK_HBUFOBJ_ASSERT_VALID((duk_hbufobj *) h_obj);
#endif
		} else if (DUK_HOBJECT_IS_BOUNDFUNC(h_obj)) {
			DUK_HBOUNDFUNC_ASSERT_VALID((duk_hboundfunc *) h_obj);
		} else if (DUK_HOBJECT_IS_PROXY(h_obj)) {
			DUK_HPROXY_ASSERT_VALID((duk_hproxy *) h_obj);
		} else if (DUK_HOBJECT_IS_THREAD(h_obj)) {
			DUK_HTHREAD_ASSERT_VALID((duk_hthread *) h_obj);
		} else {
			/* Just a plain object. */
			;
		}
		break;
	}
	case DUK_HTYPE_STRING: {
		duk_hstring *h_str = (duk_hstring *) h;
		DUK_HSTRING_ASSERT_VALID(h_str);
		break;
	}
	case DUK_HTYPE_BUFFER: {
		duk_hbuffer *h_buf = (duk_hbuffer *) h;
		DUK_HBUFFER_ASSERT_VALID(h_buf);
		break;
	}
	default: {
		DUK_ASSERT(0);
	}
	}
}

#endif  /* DUK_USE_ASSERTIONS */
#line 1 "duk_hobject_alloc.c"
/*
 *  Hobject allocation.
 *
 *  Provides primitive allocation functions for all object types (plain object,
 *  compiled function, native function, thread).  The object return is not yet
 *  in "heap allocated" list and has a refcount of zero, so caller must careful.
 */

/* XXX: In most cases there's no need for plain allocation without pushing
 * to the value stack.  Maybe rework contract?
 */

/* #include duk_internal.h -> already included */

/*
 *  Helpers.
 */

DUK_LOCAL void duk__init_object_parts(duk_heap *heap, duk_uint_t hobject_flags, duk_hobject *obj) {
	DUK_ASSERT(obj != NULL);
	/* Zeroed by caller. */

	obj->hdr.h_flags = hobject_flags | DUK_HTYPE_OBJECT;
	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(&obj->hdr) == DUK_HTYPE_OBJECT);  /* Assume zero shift. */

#if defined(DUK_USE_EXPLICIT_NULL_INIT)
	DUK_HOBJECT_SET_PROTOTYPE(heap, obj, NULL);
	DUK_HOBJECT_SET_PROPS(heap, obj, NULL);
#endif
#if defined(DUK_USE_HEAPPTR16)
	/* Zero encoded pointer is required to match NULL. */
	DUK_HEAPHDR_SET_NEXT(heap, &obj->hdr, NULL);
#if defined(DUK_USE_DOUBLE_LINKED_HEAP)
	DUK_HEAPHDR_SET_PREV(heap, &obj->hdr, NULL);
#endif
#endif
	DUK_HEAPHDR_ASSERT_LINKS(heap, &obj->hdr);
	DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap, &obj->hdr);

	/* obj->props is intentionally left as NULL, and duk_hobject_props.c must deal
	 * with this properly.  This is intentional: empty objects consume a minimum
	 * amount of memory.  Further, an initial allocation might fail and cause
	 * 'obj' to "leak" (require a mark-and-sweep) since it is not reachable yet.
	 */
}

DUK_LOCAL void *duk__hobject_alloc_init(duk_hthread *thr, duk_uint_t hobject_flags, duk_size_t size) {
	void *res;

	res = (void *) DUK_ALLOC_CHECKED_ZEROED(thr, size);
	DUK_ASSERT(res != NULL);
	duk__init_object_parts(thr->heap, hobject_flags, (duk_hobject *) res);
	return res;
}

/*
 *  Allocate an duk_hobject.
 *
 *  The allocated object has no allocation for properties; the caller may
 *  want to force a resize if a desired size is known.
 *
 *  The allocated object has zero reference count and is not reachable.
 *  The caller MUST make the object reachable and increase its reference
 *  count before invoking any operation that might require memory allocation.
 */

DUK_INTERNAL duk_hobject *duk_hobject_alloc_unchecked(duk_heap *heap, duk_uint_t hobject_flags) {
	duk_hobject *res;

	DUK_ASSERT(heap != NULL);

	/* different memory layout, alloc size, and init */
	DUK_ASSERT((hobject_flags & DUK_HOBJECT_FLAG_COMPFUNC) == 0);
	DUK_ASSERT((hobject_flags & DUK_HOBJECT_FLAG_NATFUNC) == 0);
	DUK_ASSERT((hobject_flags & DUK_HOBJECT_FLAG_BOUNDFUNC) == 0);

	res = (duk_hobject *) DUK_ALLOC_ZEROED(heap, sizeof(duk_hobject));
	if (DUK_UNLIKELY(res == NULL)) {
		return NULL;
	}
	DUK_ASSERT(!DUK_HOBJECT_IS_THREAD(res));

	duk__init_object_parts(heap, hobject_flags, res);

	DUK_ASSERT(!DUK_HOBJECT_IS_THREAD(res));
	return res;
}

DUK_INTERNAL duk_hobject *duk_hobject_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {
	duk_hobject *res;

	res = (duk_hobject *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_hobject));
	return res;
}

DUK_INTERNAL duk_hcompfunc *duk_hcompfunc_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {
	duk_hcompfunc *res;

	res = (duk_hcompfunc *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_hcompfunc));
#if defined(DUK_USE_EXPLICIT_NULL_INIT)
#if defined(DUK_USE_HEAPPTR16)
	/* NULL pointer is required to encode to zero, so memset is enough. */
#else
	res->data = NULL;
	res->funcs = NULL;
	res->bytecode = NULL;
#endif
	res->lex_env = NULL;
	res->var_env = NULL;
#endif

	return res;
}

DUK_INTERNAL duk_hnatfunc *duk_hnatfunc_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {
	duk_hnatfunc *res;

	res = (duk_hnatfunc *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_hnatfunc));
#if defined(DUK_USE_EXPLICIT_NULL_INIT)
	res->func = NULL;
#endif

	return res;
}

DUK_INTERNAL duk_hboundfunc *duk_hboundfunc_alloc(duk_heap *heap, duk_uint_t hobject_flags) {
	duk_hboundfunc *res;

	res = (duk_hboundfunc *) DUK_ALLOC(heap, sizeof(duk_hboundfunc));
	if (!res) {
		return NULL;
	}
	duk_memzero(res, sizeof(duk_hboundfunc));

	duk__init_object_parts(heap, hobject_flags, &res->obj);

	DUK_TVAL_SET_UNDEFINED(&res->target);
	DUK_TVAL_SET_UNDEFINED(&res->this_binding);

#if defined(DUK_USE_EXPLICIT_NULL_INIT)
	res->args = NULL;
#endif

	return res;
}

#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
DUK_INTERNAL duk_hbufobj *duk_hbufobj_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {
	duk_hbufobj *res;

	res = (duk_hbufobj *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_hbufobj));
#if defined(DUK_USE_EXPLICIT_NULL_INIT)
	res->buf = NULL;
	res->buf_prop = NULL;
#endif

	DUK_HBUFOBJ_ASSERT_VALID(res);
	return res;
}
#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */

/* Allocate a new thread.
 *
 * Leaves the built-ins array uninitialized.  The caller must either
 * initialize a new global context or share existing built-ins from
 * another thread.
 */
DUK_INTERNAL duk_hthread *duk_hthread_alloc_unchecked(duk_heap *heap, duk_uint_t hobject_flags) {
	duk_hthread *res;

	res = (duk_hthread *) DUK_ALLOC(heap, sizeof(duk_hthread));
	if (DUK_UNLIKELY(res == NULL)) {
		return NULL;
	}
	duk_memzero(res, sizeof(duk_hthread));

	duk__init_object_parts(heap, hobject_flags, &res->obj);

#if defined(DUK_USE_EXPLICIT_NULL_INIT)
	res->ptr_curr_pc = NULL;
	res->heap = NULL;
	res->valstack = NULL;
	res->valstack_end = NULL;
	res->valstack_alloc_end = NULL;
	res->valstack_bottom = NULL;
	res->valstack_top = NULL;
	res->callstack_curr = NULL;
	res->resumer = NULL;
	res->compile_ctx = NULL,
#if defined(DUK_USE_HEAPPTR16)
	res->strs16 = NULL;
#else
	res->strs = NULL;
#endif
	{
		duk_small_uint_t i;
		for (i = 0; i < DUK_NUM_BUILTINS; i++) {
			res->builtins[i] = NULL;
		}
	}
#endif
	/* When nothing is running, API calls are in non-strict mode. */
	DUK_ASSERT(res->strict == 0);

	res->heap = heap;

	/* XXX: Any reason not to merge duk_hthread_alloc.c here? */
	return res;
}

DUK_INTERNAL duk_hthread *duk_hthread_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {
	duk_hthread *res;

	res = duk_hthread_alloc_unchecked(thr->heap, hobject_flags);
	if (res == NULL) {
		DUK_ERROR_ALLOC_FAILED(thr);
		DUK_WO_NORETURN(return NULL;);
	}
	return res;
}

DUK_INTERNAL duk_harray *duk_harray_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {
	duk_harray *res;

	res = (duk_harray *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_harray));

	DUK_ASSERT(res->length == 0);

	return res;
}

DUK_INTERNAL duk_hdecenv *duk_hdecenv_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {
	duk_hdecenv *res;

	res = (duk_hdecenv *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_hdecenv));
#if defined(DUK_USE_EXPLICIT_NULL_INIT)
	res->thread = NULL;
	res->varmap = NULL;
#endif

	DUK_ASSERT(res->thread == NULL);
	DUK_ASSERT(res->varmap == NULL);
	DUK_ASSERT(res->regbase_byteoff == 0);

	return res;
}

DUK_INTERNAL duk_hobjenv *duk_hobjenv_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {
	duk_hobjenv *res;

	res = (duk_hobjenv *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_hobjenv));
#if defined(DUK_USE_EXPLICIT_NULL_INIT)
	res->target = NULL;
#endif

	DUK_ASSERT(res->target == NULL);

	return res;
}

DUK_INTERNAL duk_hproxy *duk_hproxy_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {
	duk_hproxy *res;

	res = (duk_hproxy *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_hproxy));

	/* Leave ->target and ->handler uninitialized, as caller will always
	 * explicitly initialize them before any side effects are possible.
	 */

	return res;
}
#line 1 "duk_hobject_assert.c"
/*
 *  duk_hobject and subclass assertion helpers
 */

/* #include duk_internal.h -> already included */

#if defined(DUK_USE_ASSERTIONS)

DUK_INTERNAL void duk_hobject_assert_valid(duk_hobject *h) {
	DUK_ASSERT(h != NULL);
	DUK_ASSERT(!DUK_HOBJECT_IS_CALLABLE(h) ||
	           DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_FUNCTION);
	DUK_ASSERT(!DUK_HOBJECT_IS_BUFOBJ(h) ||
	           (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAYBUFFER ||
	            DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_DATAVIEW ||
	            DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_INT8ARRAY ||
	            DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_UINT8ARRAY ||
	            DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY ||
	            DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_INT16ARRAY ||
	            DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_UINT16ARRAY ||
	            DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_INT32ARRAY ||
	            DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_UINT32ARRAY ||
	            DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_FLOAT32ARRAY ||
	            DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_FLOAT64ARRAY));
	/* Object is an Array <=> object has exotic array behavior */
	DUK_ASSERT((DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAY && DUK_HOBJECT_HAS_EXOTIC_ARRAY(h)) ||
	           (DUK_HOBJECT_GET_CLASS_NUMBER(h) != DUK_HOBJECT_CLASS_ARRAY && !DUK_HOBJECT_HAS_EXOTIC_ARRAY(h)));
}

DUK_INTERNAL void duk_harray_assert_valid(duk_harray *h) {
	DUK_ASSERT(h != NULL);
	DUK_ASSERT(DUK_HOBJECT_IS_ARRAY((duk_hobject *) h));
	DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY((duk_hobject *) h));
}

DUK_INTERNAL void duk_hboundfunc_assert_valid(duk_hboundfunc *h) {
	DUK_ASSERT(h != NULL);
	DUK_ASSERT(DUK_HOBJECT_IS_BOUNDFUNC((duk_hobject *) h));
	DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(&h->target) ||
	           (DUK_TVAL_IS_OBJECT(&h->target) &&
	            DUK_HOBJECT_IS_CALLABLE(DUK_TVAL_GET_OBJECT(&h->target))));
	DUK_ASSERT(!DUK_TVAL_IS_UNUSED(&h->this_binding));
	DUK_ASSERT(h->nargs == 0 || h->args != NULL);
}

#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
DUK_INTERNAL void duk_hbufobj_assert_valid(duk_hbufobj *h) {
	DUK_ASSERT(h != NULL);
	DUK_ASSERT(h->shift <= 3);
	DUK_ASSERT(h->elem_type <= DUK_HBUFOBJ_ELEM_MAX);
	DUK_ASSERT((h->shift == 0 && h->elem_type == DUK_HBUFOBJ_ELEM_UINT8) ||
	           (h->shift == 0 && h->elem_type == DUK_HBUFOBJ_ELEM_UINT8CLAMPED) ||
	           (h->shift == 0 && h->elem_type == DUK_HBUFOBJ_ELEM_INT8) ||
	           (h->shift == 1 && h->elem_type == DUK_HBUFOBJ_ELEM_UINT16) ||
	           (h->shift == 1 && h->elem_type == DUK_HBUFOBJ_ELEM_INT16) ||
	           (h->shift == 2 && h->elem_type == DUK_HBUFOBJ_ELEM_UINT32) ||
	           (h->shift == 2 && h->elem_type == DUK_HBUFOBJ_ELEM_INT32) ||
	           (h->shift == 2 && h->elem_type == DUK_HBUFOBJ_ELEM_FLOAT32) ||
	           (h->shift == 3 && h->elem_type == DUK_HBUFOBJ_ELEM_FLOAT64));
	DUK_ASSERT(h->is_typedarray == 0 || h->is_typedarray == 1);
	DUK_ASSERT(DUK_HOBJECT_IS_BUFOBJ((duk_hobject *) h));
	if (h->buf == NULL) {
		DUK_ASSERT(h->offset == 0);
		DUK_ASSERT(h->length == 0);
	} else {
		/* No assertions for offset or length; in particular,
		 * it's OK for length to be longer than underlying
		 * buffer.  Just ensure they don't wrap when added.
		 */
		DUK_ASSERT(h->offset + h->length >= h->offset);
	}
}
#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */

DUK_INTERNAL void duk_hcompfunc_assert_valid(duk_hcompfunc *h) {
	DUK_ASSERT(h != NULL);
}

DUK_INTERNAL void duk_hnatfunc_assert_valid(duk_hnatfunc *h) {
	DUK_ASSERT(h != NULL);
}

DUK_INTERNAL void duk_hdecenv_assert_valid(duk_hdecenv *h) {
	DUK_ASSERT(h != NULL);
	DUK_ASSERT(DUK_HOBJECT_IS_DECENV((duk_hobject *) h));
	DUK_ASSERT(h->thread == NULL || h->varmap != NULL);
}

DUK_INTERNAL void duk_hobjenv_assert_valid(duk_hobjenv *h) {
	DUK_ASSERT(h != NULL);
	DUK_ASSERT(DUK_HOBJECT_IS_OBJENV((duk_hobject *) h));
	DUK_ASSERT(h->target != NULL);
	DUK_ASSERT(h->has_this == 0 || h->has_this == 1);
}

DUK_INTERNAL void duk_hproxy_assert_valid(duk_hproxy *h) {
	DUK_ASSERT(h != NULL);
	DUK_ASSERT(h->target != NULL);
	DUK_ASSERT(h->handler != NULL);
	DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ((duk_hobject *) h));
}

DUK_INTERNAL void duk_hthread_assert_valid(duk_hthread *thr) {
	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) thr) == DUK_HTYPE_OBJECT);
	DUK_ASSERT(DUK_HOBJECT_IS_THREAD((duk_hobject *) thr));
	DUK_ASSERT(thr->unused1 == 0);
	DUK_ASSERT(thr->unused2 == 0);
}

DUK_INTERNAL void duk_ctx_assert_valid(duk_hthread *thr) {
	DUK_ASSERT(thr != NULL);
	DUK_HTHREAD_ASSERT_VALID(thr);
	DUK_ASSERT(thr->valstack != NULL);
	DUK_ASSERT(thr->valstack_bottom != NULL);
	DUK_ASSERT(thr->valstack_top != NULL);
	DUK_ASSERT(thr->valstack_end != NULL);
	DUK_ASSERT(thr->valstack_alloc_end != NULL);
	DUK_ASSERT(thr->valstack_alloc_end >= thr->valstack);
	DUK_ASSERT(thr->valstack_end >= thr->valstack);
	DUK_ASSERT(thr->valstack_top >= thr->valstack);
	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
	DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
	DUK_ASSERT(thr->valstack_alloc_end >= thr->valstack_end);
}

#endif  /* DUK_USE_ASSERTIONS */
#line 1 "duk_hobject_enum.c"
/*
 *  Object enumeration support.
 *
 *  Creates an internal enumeration state object to be used e.g. with for-in
 *  enumeration.  The state object contains a snapshot of target object keys
 *  and internal control state for enumeration.  Enumerator flags allow caller
 *  to e.g. request internal/non-enumerable properties, and to enumerate only
 *  "own" properties.
 *
 *  Also creates the result value for e.g. Object.keys() based on the same
 *  internal structure.
 *
 *  This snapshot-based enumeration approach is used to simplify enumeration:
 *  non-snapshot-based approaches are difficult to reconcile with mutating
 *  the enumeration target, running multiple long-lived enumerators at the
 *  same time, garbage collection details, etc.  The downside is that the
 *  enumerator object is memory inefficient especially for iterating arrays.
 */

/* #include duk_internal.h -> already included */

/* XXX: identify enumeration target with an object index (not top of stack) */

/* First enumerated key index in enumerator object, must match exactly the
 * number of control properties inserted to the enumerator.
 */
#define DUK__ENUM_START_INDEX  2

/* Current implementation suffices for ES2015 for now because there's no symbol
 * sorting, so commented out for now.
 */

/*
 *  Helper to sort enumeration keys using a callback for pairwise duk_hstring
 *  comparisons.  The keys are in the enumeration object entry part, starting
 *  from DUK__ENUM_START_INDEX, and the entry part is dense.  Entry part values
 *  are all "true", e.g. "1" -> true, "3" -> true, "foo" -> true, "2" -> true,
 *  so it suffices to just switch keys without switching values.
 *
 *  ES2015 [[OwnPropertyKeys]] enumeration order for ordinary objects:
 *  (1) array indices in ascending order,
 *  (2) non-array-index keys in insertion order, and
 *  (3) symbols in insertion order.
 *  http://www.ecma-international.org/ecma-262/6.0/#sec-ordinary-object-internal-methods-and-internal-slots-ownpropertykeys.
 *
 *  This rule is applied to "own properties" at each inheritance level;
 *  non-duplicate parent keys always follow child keys.  For example,
 *  an inherited array index will enumerate -after- a symbol in the
 *  child.
 *
 *  Insertion sort is used because (1) it's simple and compact, (2) works
 *  in-place, (3) minimizes operations if data is already nearly sorted,
 *  (4) doesn't reorder elements considered equal.
 *  http://en.wikipedia.org/wiki/Insertion_sort
 */

/* Sort key, must hold array indices, "not array index" marker, and one more
 * higher value for symbols.
 */
#if !defined(DUK_USE_SYMBOL_BUILTIN)
typedef duk_uint32_t duk__sort_key_t;
#elif defined(DUK_USE_64BIT_OPS)
typedef duk_uint64_t duk__sort_key_t;
#else
typedef duk_double_t duk__sort_key_t;
#endif

/* Get sort key for a duk_hstring. */
DUK_LOCAL duk__sort_key_t duk__hstring_sort_key(duk_hstring *x) {
	duk__sort_key_t val;

	/* For array indices [0,0xfffffffe] use the array index as is.
	 * For strings, use 0xffffffff, the marker 'arridx' already in
	 * duk_hstring.  For symbols, any value above 0xffffffff works,
	 * as long as it is the same for all symbols; currently just add
	 * the masked flag field into the arridx temporary.
	 */
	DUK_ASSERT(x != NULL);
	DUK_ASSERT(!DUK_HSTRING_HAS_SYMBOL(x) || DUK_HSTRING_GET_ARRIDX_FAST(x) == DUK_HSTRING_NO_ARRAY_INDEX);

	val = (duk__sort_key_t) DUK_HSTRING_GET_ARRIDX_FAST(x);

#if defined(DUK_USE_SYMBOL_BUILTIN)
	val = val + (duk__sort_key_t) (DUK_HEAPHDR_GET_FLAGS_RAW((duk_heaphdr *) x) & DUK_HSTRING_FLAG_SYMBOL);
#endif

	return (duk__sort_key_t) val;
}

/* Insert element 'b' after element 'a'? */
DUK_LOCAL duk_bool_t duk__sort_compare_es6(duk_hstring *a, duk_hstring *b, duk__sort_key_t val_b) {
	duk__sort_key_t val_a;

	DUK_ASSERT(a != NULL);
	DUK_ASSERT(b != NULL);
	DUK_UNREF(b);  /* Not actually needed now, val_b suffices. */

	val_a = duk__hstring_sort_key(a);

	if (val_a > val_b) {
		return 0;
	} else {
		return 1;
	}
}

DUK_LOCAL void duk__sort_enum_keys_es6(duk_hthread *thr, duk_hobject *h_obj, duk_int_fast32_t idx_start, duk_int_fast32_t idx_end) {
	duk_hstring **keys;
	duk_int_fast32_t idx;

	DUK_ASSERT(h_obj != NULL);
	DUK_ASSERT(idx_start >= DUK__ENUM_START_INDEX);
	DUK_ASSERT(idx_end >= idx_start);
	DUK_UNREF(thr);

	if (idx_end <= idx_start + 1) {
		return;  /* Zero or one element(s). */
	}

	keys = DUK_HOBJECT_E_GET_KEY_BASE(thr->heap, h_obj);

	for (idx = idx_start + 1; idx < idx_end; idx++) {
		duk_hstring *h_curr;
		duk_int_fast32_t idx_insert;
		duk__sort_key_t val_curr;

		h_curr = keys[idx];
		DUK_ASSERT(h_curr != NULL);

		/* Scan backwards for insertion place.  This works very well
		 * when the elements are nearly in order which is the common
		 * (and optimized for) case.
		 */

		val_curr = duk__hstring_sort_key(h_curr);  /* Remains same during scanning. */
		for (idx_insert = idx - 1; idx_insert >= idx_start; idx_insert--) {
			duk_hstring *h_insert;
			h_insert = keys[idx_insert];
			DUK_ASSERT(h_insert != NULL);

			if (duk__sort_compare_es6(h_insert, h_curr, val_curr)) {
				break;
			}
		}
		/* If we're out of indices, idx_insert == idx_start - 1 and idx_insert++
		 * brings us back to idx_start.
		 */
		idx_insert++;
		DUK_ASSERT(idx_insert >= 0 && idx_insert <= idx);

		/*        .-- p_insert   .-- p_curr
		 *        v              v
		 *  | ... | insert | ... | curr
		 */

		/* This could also done when the keys are in order, i.e.
		 * idx_insert == idx.  The result would be an unnecessary
		 * memmove() but we use an explicit check because the keys
		 * are very often in order already.
		 */
		if (idx != idx_insert) {
			duk_memmove((void *) (keys + idx_insert + 1),
			            (const void *) (keys + idx_insert),
			            ((size_t) (idx - idx_insert) * sizeof(duk_hstring *)));
			keys[idx_insert] = h_curr;
		}
	}
}

/*
 *  Create an internal enumerator object E, which has its keys ordered
 *  to match desired enumeration ordering.  Also initialize internal control
 *  properties for enumeration.
 *
 *  Note: if an array was used to hold enumeration keys instead, an array
 *  scan would be needed to eliminate duplicates found in the prototype chain.
 */

DUK_LOCAL void duk__add_enum_key(duk_hthread *thr, duk_hstring *k) {
	/* 'k' may be unreachable on entry so must push without any
	 * potential for GC.
	 */
	duk_push_hstring(thr, k);
	duk_push_true(thr);
	duk_put_prop(thr, -3);
}

DUK_LOCAL void duk__add_enum_key_stridx(duk_hthread *thr, duk_small_uint_t stridx) {
	duk__add_enum_key(thr, DUK_HTHREAD_GET_STRING(thr, stridx));
}

DUK_INTERNAL void duk_hobject_enumerator_create(duk_hthread *thr, duk_small_uint_t enum_flags) {
	duk_hobject *enum_target;
	duk_hobject *curr;
	duk_hobject *res;
#if defined(DUK_USE_ES6_PROXY)
	duk_hobject *h_proxy_target;
	duk_hobject *h_proxy_handler;
	duk_hobject *h_trap_result;
#endif
	duk_uint_fast32_t i, len;  /* used for array, stack, and entry indices */
	duk_uint_fast32_t sort_start_index;

	DUK_ASSERT(thr != NULL);

	enum_target = duk_require_hobject(thr, -1);
	DUK_ASSERT(enum_target != NULL);

	duk_push_bare_object(thr);
	res = duk_known_hobject(thr, -1);

	/* [enum_target res] */

	/* Target must be stored so that we can recheck whether or not
	 * keys still exist when we enumerate.  This is not done if the
	 * enumeration result comes from a proxy trap as there is no
	 * real object to check against.
	 */
	duk_push_hobject(thr, enum_target);
	duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_INT_TARGET);  /* Target is bare, plain put OK. */

	/* Initialize index so that we skip internal control keys. */
	duk_push_int(thr, DUK__ENUM_START_INDEX);
	duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_INT_NEXT);  /* Target is bare, plain put OK. */

	/*
	 *  Proxy object handling
	 */

#if defined(DUK_USE_ES6_PROXY)
	if (DUK_LIKELY((enum_flags & DUK_ENUM_NO_PROXY_BEHAVIOR) != 0)) {
		goto skip_proxy;
	}
	if (DUK_LIKELY(!duk_hobject_proxy_check(enum_target,
	                                        &h_proxy_target,
	                                        &h_proxy_handler))) {
		goto skip_proxy;
	}

	/* XXX: share code with Object.keys() Proxy handling */

	/* In ES2015 for-in invoked the "enumerate" trap; in ES2016 "enumerate"
	 * has been obsoleted and "ownKeys" is used instead.
	 */
	DUK_DDD(DUK_DDDPRINT("proxy enumeration"));
	duk_push_hobject(thr, h_proxy_handler);
	if (!duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_OWN_KEYS)) {
		/* No need to replace the 'enum_target' value in stack, only the
		 * enum_target reference.  This also ensures that the original
		 * enum target is reachable, which keeps the proxy and the proxy
		 * target reachable.  We do need to replace the internal _Target.
		 */
		DUK_DDD(DUK_DDDPRINT("no ownKeys trap, enumerate proxy target instead"));
		DUK_DDD(DUK_DDDPRINT("h_proxy_target=%!O", (duk_heaphdr *) h_proxy_target));
		enum_target = h_proxy_target;

		duk_push_hobject(thr, enum_target);  /* -> [ ... enum_target res handler undefined target ] */
		duk_put_prop_stridx_short(thr, -4, DUK_STRIDX_INT_TARGET);  /* Target is bare, plain put OK. */

		duk_pop_2(thr);  /* -> [ ... enum_target res ] */
		goto skip_proxy;
	}

	/* [ ... enum_target res handler trap ] */
	duk_insert(thr, -2);
	duk_push_hobject(thr, h_proxy_target);    /* -> [ ... enum_target res trap handler target ] */
	duk_call_method(thr, 1 /*nargs*/);        /* -> [ ... enum_target res trap_result ] */
	h_trap_result = duk_require_hobject(thr, -1);
	DUK_UNREF(h_trap_result);

	duk_proxy_ownkeys_postprocess(thr, h_proxy_target, enum_flags);
	/* -> [ ... enum_target res trap_result keys_array ] */

	/* Copy cleaned up trap result keys into the enumerator object. */
	/* XXX: result is a dense array; could make use of that. */
	DUK_ASSERT(duk_is_array(thr, -1));
	len = (duk_uint_fast32_t) duk_get_length(thr, -1);
	for (i = 0; i < len; i++) {
		(void) duk_get_prop_index(thr, -1, (duk_uarridx_t) i);
		DUK_ASSERT(duk_is_string(thr, -1));  /* postprocess cleaned up */
		/* [ ... enum_target res trap_result keys_array val ] */
		duk_push_true(thr);
		/* [ ... enum_target res trap_result keys_array val true ] */
		duk_put_prop(thr, -5);
	}
	/* [ ... enum_target res trap_result keys_array ] */
	duk_pop_2(thr);
	duk_remove_m2(thr);

	/* [ ... res ] */

	/* The internal _Target property is kept pointing to the original
	 * enumeration target (the proxy object), so that the enumerator
	 * 'next' operation can read property values if so requested.  The
	 * fact that the _Target is a proxy disables key existence check
	 * during enumeration.
	 */
	DUK_DDD(DUK_DDDPRINT("proxy enumeration, final res: %!O", (duk_heaphdr *) res));
	goto compact_and_return;

 skip_proxy:
#endif  /* DUK_USE_ES6_PROXY */

	curr = enum_target;
	sort_start_index = DUK__ENUM_START_INDEX;
	DUK_ASSERT(DUK_HOBJECT_GET_ENEXT(res) == DUK__ENUM_START_INDEX);
	while (curr) {
		duk_uint_fast32_t sort_end_index;
#if !defined(DUK_USE_PREFER_SIZE)
		duk_bool_t need_sort = 0;
#endif
		duk_bool_t cond;

		/* Enumeration proceeds by inheritance level.  Virtual
		 * properties need to be handled specially, followed by
		 * array part, and finally entry part.
		 *
		 * If there are array index keys in the entry part or any
		 * other risk of the ES2015 [[OwnPropertyKeys]] order being
		 * violated, need_sort is set and an explicit ES2015 sort is
		 * done for the inheritance level.
		 */

		/* XXX: inheriting from proxy */

		/*
		 *  Virtual properties.
		 *
		 *  String and buffer indices are virtual and always enumerable,
		 *  'length' is virtual and non-enumerable.  Array and arguments
		 *  object props have special behavior but are concrete.
		 *
		 *  String and buffer objects don't have an array part so as long
		 *  as virtual array index keys are enumerated first, we don't
		 *  need to set need_sort.
		 */

#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
		cond = DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(curr) || DUK_HOBJECT_IS_BUFOBJ(curr);
#else
		cond = DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(curr);
#endif
		cond = cond && !(enum_flags & DUK_ENUM_EXCLUDE_STRINGS);
		if (cond) {
			duk_bool_t have_length = 1;

			/* String and buffer enumeration behavior is identical now,
			 * so use shared handler.
			 */
			if (DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(curr)) {
				duk_hstring *h_val;
				h_val = duk_hobject_get_internal_value_string(thr->heap, curr);
				DUK_ASSERT(h_val != NULL);  /* string objects must not created without internal value */
				len = (duk_uint_fast32_t) DUK_HSTRING_GET_CHARLEN(h_val);
			}
#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
			else {
				duk_hbufobj *h_bufobj;
				DUK_ASSERT(DUK_HOBJECT_IS_BUFOBJ(curr));
				h_bufobj = (duk_hbufobj *) curr;

				if (h_bufobj == NULL || !h_bufobj->is_typedarray) {
					/* Zero length seems like a good behavior for neutered buffers.
					 * ArrayBuffer (non-view) and DataView don't have index properties
					 * or .length property.
					 */
					len = 0;
					have_length = 0;
				} else {
					/* There's intentionally no check for
					 * current underlying buffer length.
					 */
					len = (duk_uint_fast32_t) (h_bufobj->length >> h_bufobj->shift);
				}
			}
#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */

			for (i = 0; i < len; i++) {
				duk_hstring *k;

				/* This is a bit fragile: the string is not
				 * reachable until it is pushed by the helper.
				 */
				k = duk_heap_strtable_intern_u32_checked(thr, (duk_uint32_t) i);
				DUK_ASSERT(k);

				duk__add_enum_key(thr, k);

				/* [enum_target res] */
			}

			/* 'length' and other virtual properties are not
			 * enumerable, but are included if non-enumerable
			 * properties are requested.
			 */

			if (have_length && (enum_flags & DUK_ENUM_INCLUDE_NONENUMERABLE)) {
				duk__add_enum_key_stridx(thr, DUK_STRIDX_LENGTH);
			}
		}

		/*
		 *  Array part
		 */

		cond = !(enum_flags & DUK_ENUM_EXCLUDE_STRINGS);
		if (cond) {
			for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(curr); i++) {
				duk_hstring *k;
				duk_tval *tv;

				tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, curr, i);
				if (DUK_TVAL_IS_UNUSED(tv)) {
					continue;
				}
				k = duk_heap_strtable_intern_u32_checked(thr, (duk_uint32_t) i);  /* Fragile reachability. */
				DUK_ASSERT(k);

				duk__add_enum_key(thr, k);

				/* [enum_target res] */
			}

			if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(curr)) {
				/* Array .length comes after numeric indices. */
				if (enum_flags & DUK_ENUM_INCLUDE_NONENUMERABLE) {
					duk__add_enum_key_stridx(thr, DUK_STRIDX_LENGTH);
				}
			}
		}

		/*
		 *  Entries part
		 */

		for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(curr); i++) {
			duk_hstring *k;

			k = DUK_HOBJECT_E_GET_KEY(thr->heap, curr, i);
			if (!k) {
				continue;
			}
			if (!(enum_flags & DUK_ENUM_INCLUDE_NONENUMERABLE) &&
			    !DUK_HOBJECT_E_SLOT_IS_ENUMERABLE(thr->heap, curr, i)) {
				continue;
			}
			if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(k))) {
				if (!(enum_flags & DUK_ENUM_INCLUDE_HIDDEN) &&
				    DUK_HSTRING_HAS_HIDDEN(k)) {
					continue;
				}
				if (!(enum_flags & DUK_ENUM_INCLUDE_SYMBOLS)) {
					continue;
				}
#if !defined(DUK_USE_PREFER_SIZE)
				need_sort = 1;
#endif
			} else {
				DUK_ASSERT(!DUK_HSTRING_HAS_HIDDEN(k));  /* would also have symbol flag */
				if (enum_flags & DUK_ENUM_EXCLUDE_STRINGS) {
					continue;
				}
			}
			if (DUK_HSTRING_HAS_ARRIDX(k)) {
				/* This in currently only possible if the
				 * object has no array part: the array part
				 * is exhaustive when it is present.
				 */
#if !defined(DUK_USE_PREFER_SIZE)
				need_sort = 1;
#endif
			} else {
				if (enum_flags & DUK_ENUM_ARRAY_INDICES_ONLY) {
					continue;
				}
			}

			DUK_ASSERT(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, curr, i) ||
			           !DUK_TVAL_IS_UNUSED(&DUK_HOBJECT_E_GET_VALUE_PTR(thr->heap, curr, i)->v));

			duk__add_enum_key(thr, k);

			/* [enum_target res] */
		}

		/* Sort enumerated keys according to ES2015 requirements for
		 * the "inheritance level" just processed.  This is far from
		 * optimal, ES2015 semantics could be achieved more efficiently
		 * by handling array index string keys (and symbol keys)
		 * specially above in effect doing the sort inline.
		 *
		 * Skip the sort if array index sorting is requested because
		 * we must consider all keys, also inherited, so an explicit
		 * sort is done for the whole result after we're done with the
		 * prototype chain.
		 *
		 * Also skip the sort if need_sort == 0, i.e. we know for
		 * certain that the enumerated order is already correct.
		 */
		sort_end_index = DUK_HOBJECT_GET_ENEXT(res);

		if (!(enum_flags & DUK_ENUM_SORT_ARRAY_INDICES)) {
#if defined(DUK_USE_PREFER_SIZE)
			duk__sort_enum_keys_es6(thr, res, (duk_int_fast32_t) sort_start_index, (duk_int_fast32_t) sort_end_index);
#else
			if (need_sort) {
				DUK_DDD(DUK_DDDPRINT("need to sort"));
				duk__sort_enum_keys_es6(thr, res, (duk_int_fast32_t) sort_start_index, (duk_int_fast32_t) sort_end_index);
			} else {
				DUK_DDD(DUK_DDDPRINT("no need to sort"));
			}
#endif
		}

		sort_start_index = sort_end_index;

		if (enum_flags & DUK_ENUM_OWN_PROPERTIES_ONLY) {
			break;
		}

		curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr);
	}

	/* [enum_target res] */

	duk_remove_m2(thr);

	/* [res] */

	if (enum_flags & DUK_ENUM_SORT_ARRAY_INDICES) {
		/* Some E5/E5.1 algorithms require that array indices are iterated
		 * in a strictly ascending order.  This is the case for e.g.
		 * Array.prototype.forEach() and JSON.stringify() PropertyList
		 * handling.  The caller can request an explicit sort in these
		 * cases.
		 */

		/* Sort to ES2015 order which works for pure array incides but
		 * also for mixed keys.
		 */
		duk__sort_enum_keys_es6(thr, res, (duk_int_fast32_t) DUK__ENUM_START_INDEX, (duk_int_fast32_t) DUK_HOBJECT_GET_ENEXT(res));
	}

#if defined(DUK_USE_ES6_PROXY)
 compact_and_return:
#endif
	/* compact; no need to seal because object is internal */
	duk_hobject_compact_props(thr, res);

	DUK_DDD(DUK_DDDPRINT("created enumerator object: %!iT", (duk_tval *) duk_get_tval(thr, -1)));
}

/*
 *  Returns non-zero if a key and/or value was enumerated, and:
 *
 *   [enum] -> [key]        (get_value == 0)
 *   [enum] -> [key value]  (get_value == 1)
 *
 *  Returns zero without pushing anything on the stack otherwise.
 */
DUK_INTERNAL duk_bool_t duk_hobject_enumerator_next(duk_hthread *thr, duk_bool_t get_value) {
	duk_hobject *e;
	duk_hobject *enum_target;
	duk_hstring *res = NULL;
	duk_uint_fast32_t idx;
	duk_bool_t check_existence;

	DUK_ASSERT(thr != NULL);

	/* [... enum] */

	e = duk_require_hobject(thr, -1);

	/* XXX use get tval ptr, more efficient */
	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_NEXT);
	idx = (duk_uint_fast32_t) duk_require_uint(thr, -1);
	duk_pop(thr);
	DUK_DDD(DUK_DDDPRINT("enumeration: index is: %ld", (long) idx));

	/* Enumeration keys are checked against the enumeration target (to see
	 * that they still exist).  In the proxy enumeration case _Target will
	 * be the proxy, and checking key existence against the proxy is not
	 * required (or sensible, as the keys may be fully virtual).
	 */
	duk_xget_owndataprop_stridx_short(thr, -1, DUK_STRIDX_INT_TARGET);
	enum_target = duk_require_hobject(thr, -1);
	DUK_ASSERT(enum_target != NULL);
#if defined(DUK_USE_ES6_PROXY)
	check_existence = (!DUK_HOBJECT_IS_PROXY(enum_target));
#else
	check_existence = 1;
#endif
	duk_pop(thr);  /* still reachable */

	DUK_DDD(DUK_DDDPRINT("getting next enum value, enum_target=%!iO, enumerator=%!iT",
	                     (duk_heaphdr *) enum_target, (duk_tval *) duk_get_tval(thr, -1)));

	/* no array part */
	for (;;) {
		duk_hstring *k;

		if (idx >= DUK_HOBJECT_GET_ENEXT(e)) {
			DUK_DDD(DUK_DDDPRINT("enumeration: ran out of elements"));
			break;
		}

		/* we know these because enum objects are internally created */
		k = DUK_HOBJECT_E_GET_KEY(thr->heap, e, idx);
		DUK_ASSERT(k != NULL);
		DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, e, idx));
		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(&DUK_HOBJECT_E_GET_VALUE(thr->heap, e, idx).v));

		idx++;

		/* recheck that the property still exists */
		if (check_existence && !duk_hobject_hasprop_raw(thr, enum_target, k)) {
			DUK_DDD(DUK_DDDPRINT("property deleted during enumeration, skip"));
			continue;
		}

		DUK_DDD(DUK_DDDPRINT("enumeration: found element, key: %!O", (duk_heaphdr *) k));
		res = k;
		break;
	}

	DUK_DDD(DUK_DDDPRINT("enumeration: updating next index to %ld", (long) idx));

	duk_push_u32(thr, (duk_uint32_t) idx);
	duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_INT_NEXT);

	/* [... enum] */

	if (res) {
		duk_push_hstring(thr, res);
		if (get_value) {
			duk_push_hobject(thr, enum_target);
			duk_dup_m2(thr);       /* -> [... enum key enum_target key] */
			duk_get_prop(thr, -2); /* -> [... enum key enum_target val] */
			duk_remove_m2(thr);    /* -> [... enum key val] */
			duk_remove(thr, -3);   /* -> [... key val] */
		} else {
			duk_remove_m2(thr);    /* -> [... key] */
		}
		return 1;
	} else {
		duk_pop(thr);  /* -> [...] */
		return 0;
	}
}

/*
 *  Get enumerated keys in an ECMAScript array.  Matches Object.keys() behavior
 *  described in E5 Section 15.2.3.14.
 */

DUK_INTERNAL duk_ret_t duk_hobject_get_enumerated_keys(duk_hthread *thr, duk_small_uint_t enum_flags) {
	duk_hobject *e;
	duk_hstring **keys;
	duk_tval *tv;
	duk_uint_fast32_t count;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(duk_get_hobject(thr, -1) != NULL);

	/* Create a temporary enumerator to get the (non-duplicated) key list;
	 * the enumerator state is initialized without being needed, but that
	 * has little impact.
	 */

	duk_hobject_enumerator_create(thr, enum_flags);
	e = duk_known_hobject(thr, -1);

	/* [enum_target enum res] */

	/* Create dense result array to exact size. */
	DUK_ASSERT(DUK_HOBJECT_GET_ENEXT(e) >= DUK__ENUM_START_INDEX);
	count = (duk_uint32_t) (DUK_HOBJECT_GET_ENEXT(e) - DUK__ENUM_START_INDEX);

	/* XXX: uninit would be OK */
	tv = duk_push_harray_with_size_outptr(thr, (duk_uint32_t) count);
	DUK_ASSERT(count == 0 || tv != NULL);
	DUK_ASSERT(!duk_is_bare_object(thr, -1));

	/* Fill result array, no side effects. */

	keys = DUK_HOBJECT_E_GET_KEY_BASE(thr->heap, e);
	keys += DUK__ENUM_START_INDEX;

	while (count-- > 0) {
		duk_hstring *k;

		k = *keys++;
		DUK_ASSERT(k != NULL);  /* enumerator must have no keys deleted */

		DUK_TVAL_SET_STRING(tv, k);
		tv++;
		DUK_HSTRING_INCREF(thr, k);
	}

	/* [enum_target enum res] */
	duk_remove_m2(thr);

	/* [enum_target res] */

	return 1;  /* return 1 to allow callers to tail call */
}

/* automatic undefs */
#undef DUK__ENUM_START_INDEX
#line 1 "duk_hobject_misc.c"
/*
 *  Misc support functions
 */

/* #include duk_internal.h -> already included */

DUK_INTERNAL duk_bool_t duk_hobject_prototype_chain_contains(duk_hthread *thr, duk_hobject *h, duk_hobject *p, duk_bool_t ignore_loop) {
	duk_uint_t sanity;

	DUK_ASSERT(thr != NULL);

	/* False if the object is NULL or the prototype 'p' is NULL.
	 * In particular, false if both are NULL (don't compare equal).
	 */
	if (h == NULL || p == NULL) {
		return 0;
	}

	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
	do {
		if (h == p) {
			return 1;
		}

		if (sanity-- == 0) {
			if (ignore_loop) {
				break;
			} else {
				DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
				DUK_WO_NORETURN(return 0;);
			}
		}
		h = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
	} while (h);

	return 0;
}

DUK_INTERNAL void duk_hobject_set_prototype_updref(duk_hthread *thr, duk_hobject *h, duk_hobject *p) {
#if defined(DUK_USE_REFERENCE_COUNTING)
	duk_hobject *tmp;

	DUK_ASSERT(h);
	tmp = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
	DUK_HOBJECT_SET_PROTOTYPE(thr->heap, h, p);
	DUK_HOBJECT_INCREF_ALLOWNULL(thr, p);  /* avoid problems if p == h->prototype */
	DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);
#else
	DUK_ASSERT(h);
	DUK_UNREF(thr);
	DUK_HOBJECT_SET_PROTOTYPE(thr->heap, h, p);
#endif
}
#line 1 "duk_hobject_pc2line.c"
/*
 *  Helpers for creating and querying pc2line debug data, which
 *  converts a bytecode program counter to a source line number.
 *
 *  The run-time pc2line data is bit-packed, and documented in:
 *
 *    doc/function-objects.rst
 */

/* #include duk_internal.h -> already included */

#if defined(DUK_USE_PC2LINE)

/* Generate pc2line data for an instruction sequence, leaving a buffer on stack top. */
DUK_INTERNAL void duk_hobject_pc2line_pack(duk_hthread *thr, duk_compiler_instr *instrs, duk_uint_fast32_t length) {
	duk_hbuffer_dynamic *h_buf;
	duk_bitencoder_ctx be_ctx_alloc;
	duk_bitencoder_ctx *be_ctx = &be_ctx_alloc;
	duk_uint32_t *hdr;
	duk_size_t new_size;
	duk_uint_fast32_t num_header_entries;
	duk_uint_fast32_t curr_offset;
	duk_int_fast32_t curr_line, next_line, diff_line;
	duk_uint_fast32_t curr_pc;
	duk_uint_fast32_t hdr_index;

	DUK_ASSERT(length <= DUK_COMPILER_MAX_BYTECODE_LENGTH);

	num_header_entries = (length + DUK_PC2LINE_SKIP - 1) / DUK_PC2LINE_SKIP;
	curr_offset = (duk_uint_fast32_t) (sizeof(duk_uint32_t) + num_header_entries * sizeof(duk_uint32_t) * 2);

	duk_push_dynamic_buffer(thr, (duk_size_t) curr_offset);
	h_buf = (duk_hbuffer_dynamic *) duk_known_hbuffer(thr, -1);
	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(h_buf) && !DUK_HBUFFER_HAS_EXTERNAL(h_buf));

	hdr = (duk_uint32_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h_buf);
	DUK_ASSERT(hdr != NULL);
	hdr[0] = (duk_uint32_t) length;  /* valid pc range is [0, length[ */

	curr_pc = 0U;
	while (curr_pc < length) {
		new_size = (duk_size_t) (curr_offset + DUK_PC2LINE_MAX_DIFF_LENGTH);
		duk_hbuffer_resize(thr, h_buf, new_size);

		hdr = (duk_uint32_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h_buf);
		DUK_ASSERT(hdr != NULL);
		DUK_ASSERT(curr_pc < length);
		hdr_index = 1 + (curr_pc / DUK_PC2LINE_SKIP) * 2;
		curr_line = (duk_int_fast32_t) instrs[curr_pc].line;
		hdr[hdr_index + 0] = (duk_uint32_t) curr_line;
		hdr[hdr_index + 1] = (duk_uint32_t) curr_offset;

#if 0
		DUK_DDD(DUK_DDDPRINT("hdr[%ld]: pc=%ld line=%ld offset=%ld",
		                     (long) (curr_pc / DUK_PC2LINE_SKIP),
		                     (long) curr_pc,
		                     (long) hdr[hdr_index + 0],
		                     (long) hdr[hdr_index + 1]));
#endif

		duk_memzero(be_ctx, sizeof(*be_ctx));
		be_ctx->data = ((duk_uint8_t *) hdr) + curr_offset;
		be_ctx->length = (duk_size_t) DUK_PC2LINE_MAX_DIFF_LENGTH;

		for (;;) {
			curr_pc++;
			if ( ((curr_pc % DUK_PC2LINE_SKIP) == 0) ||  /* end of diff run */
			     (curr_pc >= length) ) {                 /* end of bytecode */
				break;
			}
			DUK_ASSERT(curr_pc < length);
			next_line = (duk_int32_t) instrs[curr_pc].line;
			diff_line = next_line - curr_line;

#if 0
			DUK_DDD(DUK_DDDPRINT("curr_line=%ld, next_line=%ld -> diff_line=%ld",
			                     (long) curr_line, (long) next_line, (long) diff_line));
#endif

			if (diff_line == 0) {
				/* 0 */
				duk_be_encode(be_ctx, 0, 1);
			} else if (diff_line >= 1 && diff_line <= 4) {
				/* 1 0 <2 bits> */
				duk_be_encode(be_ctx, (duk_uint32_t) ((0x02 << 2) + (diff_line - 1)), 4);
			} else if (diff_line >= -0x80 && diff_line <= 0x7f) {
				/* 1 1 0 <8 bits> */
				DUK_ASSERT(diff_line + 0x80 >= 0 && diff_line + 0x80 <= 0xff);
				duk_be_encode(be_ctx, (duk_uint32_t) ((0x06 << 8) + (diff_line + 0x80)), 11);
			} else {
				/* 1 1 1 <32 bits>
				 * Encode in two parts to avoid bitencode 24-bit limitation
				 */
				duk_be_encode(be_ctx, (duk_uint32_t) ((0x07 << 16) + ((next_line >> 16) & 0xffff)), 19);
				duk_be_encode(be_ctx, (duk_uint32_t) (next_line & 0xffff), 16);
			}

			curr_line = next_line;
		}

		duk_be_finish(be_ctx);
		DUK_ASSERT(!be_ctx->truncated);

		/* be_ctx->offset == length of encoded bitstream */
		curr_offset += (duk_uint_fast32_t) be_ctx->offset;
	}

	/* compact */
	new_size = (duk_size_t) curr_offset;
	duk_hbuffer_resize(thr, h_buf, new_size);

	(void) duk_to_fixed_buffer(thr, -1, NULL);

	DUK_DDD(DUK_DDDPRINT("final pc2line data: pc_limit=%ld, length=%ld, %lf bits/opcode --> %!ixT",
	                     (long) length, (long) new_size, (double) new_size * 8.0 / (double) length,
	                     (duk_tval *) duk_get_tval(thr, -1)));
}

/* PC is unsigned.  If caller does PC arithmetic and gets a negative result,
 * it will map to a large PC which is out of bounds and causes a zero to be
 * returned.
 */
DUK_LOCAL duk_uint_fast32_t duk__hobject_pc2line_query_raw(duk_hthread *thr, duk_hbuffer_fixed *buf, duk_uint_fast32_t pc) {
	duk_bitdecoder_ctx bd_ctx_alloc;
	duk_bitdecoder_ctx *bd_ctx = &bd_ctx_alloc;
	duk_uint32_t *hdr;
	duk_uint_fast32_t start_offset;
	duk_uint_fast32_t pc_limit;
	duk_uint_fast32_t hdr_index;
	duk_uint_fast32_t pc_base;
	duk_uint_fast32_t n;
	duk_uint_fast32_t curr_line;

	DUK_ASSERT(buf != NULL);
	DUK_ASSERT(!DUK_HBUFFER_HAS_DYNAMIC((duk_hbuffer *) buf) && !DUK_HBUFFER_HAS_EXTERNAL((duk_hbuffer *) buf));
	DUK_UNREF(thr);

	/*
	 *  Use the index in the header to find the right starting point
	 */

	hdr_index = pc / DUK_PC2LINE_SKIP;
	pc_base = hdr_index * DUK_PC2LINE_SKIP;
	n = pc - pc_base;

	if (DUK_HBUFFER_FIXED_GET_SIZE(buf) <= sizeof(duk_uint32_t)) {
		DUK_DD(DUK_DDPRINT("pc2line lookup failed: buffer is smaller than minimal header"));
		goto pc2line_error;
	}

	hdr = (duk_uint32_t *) (void *) DUK_HBUFFER_FIXED_GET_DATA_PTR(thr->heap, buf);
	pc_limit = hdr[0];
	if (pc >= pc_limit) {
		/* Note: pc is unsigned and cannot be negative */
		DUK_DD(DUK_DDPRINT("pc2line lookup failed: pc out of bounds (pc=%ld, limit=%ld)",
		                   (long) pc, (long) pc_limit));
		goto pc2line_error;
	}

	curr_line = hdr[1 + hdr_index * 2];
	start_offset = hdr[1 + hdr_index * 2 + 1];
	if ((duk_size_t) start_offset > DUK_HBUFFER_FIXED_GET_SIZE(buf)) {
		DUK_DD(DUK_DDPRINT("pc2line lookup failed: start_offset out of bounds (start_offset=%ld, buffer_size=%ld)",
		                   (long) start_offset, (long) DUK_HBUFFER_GET_SIZE((duk_hbuffer *) buf)));
		goto pc2line_error;
	}

	/*
	 *  Iterate the bitstream (line diffs) until PC is reached
	 */

	duk_memzero(bd_ctx, sizeof(*bd_ctx));
	bd_ctx->data = ((duk_uint8_t *) hdr) + start_offset;
	bd_ctx->length = (duk_size_t) (DUK_HBUFFER_FIXED_GET_SIZE(buf) - start_offset);

#if 0
	DUK_DDD(DUK_DDDPRINT("pc2line lookup: pc=%ld -> hdr_index=%ld, pc_base=%ld, n=%ld, start_offset=%ld",
	                     (long) pc, (long) hdr_index, (long) pc_base, (long) n, (long) start_offset));
#endif

	while (n > 0) {
#if 0
		DUK_DDD(DUK_DDDPRINT("lookup: n=%ld, curr_line=%ld", (long) n, (long) curr_line));
#endif

		if (duk_bd_decode_flag(bd_ctx)) {
			if (duk_bd_decode_flag(bd_ctx)) {
				if (duk_bd_decode_flag(bd_ctx)) {
					/* 1 1 1 <32 bits> */
					duk_uint_fast32_t t;
					t = duk_bd_decode(bd_ctx, 16);  /* workaround: max nbits = 24 now */
					t = (t << 16) + duk_bd_decode(bd_ctx, 16);
					curr_line = t;
				} else {
					/* 1 1 0 <8 bits> */
					duk_uint_fast32_t t;
					t = duk_bd_decode(bd_ctx, 8);
					curr_line = curr_line + t - 0x80;
				}
			} else {
				/* 1 0 <2 bits> */
				duk_uint_fast32_t t;
				t = duk_bd_decode(bd_ctx, 2);
				curr_line = curr_line + t + 1;
			}
		} else {
			/* 0: no change */
		}

		n--;
	}

	DUK_DDD(DUK_DDDPRINT("pc2line lookup result: pc %ld -> line %ld", (long) pc, (long) curr_line));
	return curr_line;

 pc2line_error:
	DUK_D(DUK_DPRINT("pc2line conversion failed for pc=%ld", (long) pc));
	return 0;
}

DUK_INTERNAL duk_uint_fast32_t duk_hobject_pc2line_query(duk_hthread *thr, duk_idx_t idx_func, duk_uint_fast32_t pc) {
	duk_hbuffer_fixed *pc2line;
	duk_uint_fast32_t line;

	/* XXX: now that pc2line is used by the debugger quite heavily in
	 * checked execution, this should be optimized to avoid value stack
	 * and perhaps also implement some form of pc2line caching (see
	 * future work in debugger.rst).
	 */

	duk_xget_owndataprop_stridx_short(thr, idx_func, DUK_STRIDX_INT_PC2LINE);
	pc2line = (duk_hbuffer_fixed *) (void *) duk_get_hbuffer(thr, -1);
	if (pc2line != NULL) {
		DUK_ASSERT(!DUK_HBUFFER_HAS_DYNAMIC((duk_hbuffer *) pc2line) && !DUK_HBUFFER_HAS_EXTERNAL((duk_hbuffer *) pc2line));
		line = duk__hobject_pc2line_query_raw(thr, pc2line, (duk_uint_fast32_t) pc);
	} else {
		line = 0;
	}
	duk_pop(thr);

	return line;
}

#endif  /* DUK_USE_PC2LINE */
#line 1 "duk_hobject_props.c"
/*
 *  duk_hobject property access functionality.
 *
 *  This is very central functionality for size, performance, and compliance.
 *  It is also rather intricate; see hobject-algorithms.rst for discussion on
 *  the algorithms and memory-management.rst for discussion on refcounts and
 *  side effect issues.
 *
 *  Notes:
 *
 *    - It might be tempting to assert "refcount nonzero" for objects
 *      being operated on, but that's not always correct: objects with
 *      a zero refcount may be operated on by the refcount implementation
 *      (finalization) for instance.  Hence, no refcount assertions are made.
 *
 *    - Many operations (memory allocation, identifier operations, etc)
 *      may cause arbitrary side effects (e.g. through GC and finalization).
 *      These side effects may invalidate duk_tval pointers which point to
 *      areas subject to reallocation (like value stack).  Heap objects
 *      themselves have stable pointers.  Holding heap object pointers or
 *      duk_tval copies is not problematic with respect to side effects;
 *      care must be taken when holding and using argument duk_tval pointers.
 *
 *    - If a finalizer is executed, it may operate on the the same object
 *      we're currently dealing with.  For instance, the finalizer might
 *      delete a certain property which has already been looked up and
 *      confirmed to exist.  Ideally finalizers would be disabled if GC
 *      happens during property access.  At the moment property table realloc
 *      disables finalizers, and all DECREFs may cause arbitrary changes so
 *      handle DECREF carefully.
 *
 *    - The order of operations for a DECREF matters.  When DECREF is executed,
 *      the entire object graph must be consistent; note that a refzero may
 *      lead to a mark-and-sweep through a refcount finalizer.  Use NORZ macros
 *      and an explicit DUK_REFZERO_CHECK_xxx() if achieving correct order is hard.
 */

/*
 *  XXX: array indices are mostly typed as duk_uint32_t here; duk_uarridx_t
 *  might be more appropriate.
 */

/* #include duk_internal.h -> already included */

/*
 *  Local defines
 */

#define DUK__NO_ARRAY_INDEX             DUK_HSTRING_NO_ARRAY_INDEX

/* Marker values for hash part. */
#define DUK__HASH_UNUSED                DUK_HOBJECT_HASHIDX_UNUSED
#define DUK__HASH_DELETED               DUK_HOBJECT_HASHIDX_DELETED

/* Valstack space that suffices for all local calls, excluding any recursion
 * into ECMAScript or Duktape/C calls (Proxy, getters, etc).
 */
#define DUK__VALSTACK_SPACE             10

/* Valstack space allocated especially for proxy lookup which does a
 * recursive property lookup.
 */
#define DUK__VALSTACK_PROXY_LOOKUP      20

/*
 *  Local prototypes
 */

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);
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);
DUK_LOCAL_DECL void duk__check_arguments_map_for_delete(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *temp_desc);

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);
DUK_LOCAL_DECL duk_bool_t duk__handle_put_array_length(duk_hthread *thr, duk_hobject *obj);

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);
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);

DUK_LOCAL_DECL void duk__abandon_array_part(duk_hthread *thr, duk_hobject *obj);
DUK_LOCAL_DECL void duk__grow_props_for_array_item(duk_hthread *thr, duk_hobject *obj, duk_uint32_t highest_arr_idx);

/*
 *  Misc helpers
 */

/* Convert a duk_tval number (caller checks) to a 32-bit index.  Returns
 * DUK__NO_ARRAY_INDEX if the number is not whole or not a valid array
 * index.
 */
/* XXX: for fastints, could use a variant which assumes a double duk_tval
 * (and doesn't need to check for fastint again).
 */
DUK_LOCAL duk_uint32_t duk__tval_number_to_arr_idx(duk_tval *tv) {
	duk_double_t dbl;
	duk_uint32_t idx;

	DUK_ASSERT(tv != NULL);
	DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));

	/* -0 is accepted here as index 0 because ToString(-0) == "0" which is
	 * in canonical form and thus an array index.
	 */
	dbl = DUK_TVAL_GET_NUMBER(tv);
	idx = (duk_uint32_t) dbl;
	if (duk_double_equals((duk_double_t) idx, dbl)) {
	        /* Is whole and within 32 bit range.  If the value happens to be 0xFFFFFFFF,
		 * it's not a valid array index but will then match DUK__NO_ARRAY_INDEX.
		 */
		return idx;
	}
	return DUK__NO_ARRAY_INDEX;
}

#if defined(DUK_USE_FASTINT)
/* Convert a duk_tval fastint (caller checks) to a 32-bit index. */
DUK_LOCAL duk_uint32_t duk__tval_fastint_to_arr_idx(duk_tval *tv) {
	duk_int64_t t;

	DUK_ASSERT(tv != NULL);
	DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv));

	t = DUK_TVAL_GET_FASTINT(tv);
	if (((duk_uint64_t) t & ~DUK_U64_CONSTANT(0xffffffff)) != 0) {
		/* Catches >0x100000000 and negative values. */
		return DUK__NO_ARRAY_INDEX;
	}

	/* If the value happens to be 0xFFFFFFFF, it's not a valid array index
	 * but will then match DUK__NO_ARRAY_INDEX.
	 */
	return (duk_uint32_t) t;
}
#endif  /* DUK_USE_FASTINT */

/* Convert a duk_tval on the value stack (in a trusted index we don't validate)
 * to a string or symbol using ES2015 ToPropertyKey():
 * http://www.ecma-international.org/ecma-262/6.0/#sec-topropertykey.
 *
 * Also check if it's a valid array index and return that (or DUK__NO_ARRAY_INDEX
 * if not).
 */
DUK_LOCAL duk_uint32_t duk__to_property_key(duk_hthread *thr, duk_idx_t idx, duk_hstring **out_h) {
	duk_uint32_t arr_idx;
	duk_hstring *h;
	duk_tval *tv_dst;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(out_h != NULL);
	DUK_ASSERT(duk_is_valid_index(thr, idx));
	DUK_ASSERT(idx < 0);

	/* XXX: The revised ES2015 ToPropertyKey() handling (ES5.1 was just
	 * ToString()) involves a ToPrimitive(), a symbol check, and finally
	 * a ToString().  Figure out the best way to have a good fast path
	 * but still be compliant and share code.
	 */

	tv_dst = DUK_GET_TVAL_NEGIDX(thr, idx);  /* intentionally unvalidated */
	if (DUK_TVAL_IS_STRING(tv_dst)) {
		/* Most important path: strings and plain symbols are used as
		 * is.  For symbols the array index check below is unnecessary
		 * (they're never valid array indices) but checking that the
		 * string is a symbol would make the plain string path slower
		 * unnecessarily.
		 */
		h = DUK_TVAL_GET_STRING(tv_dst);
	} else {
		h = duk_to_property_key_hstring(thr, idx);
	}
	DUK_ASSERT(h != NULL);
	*out_h = h;

	arr_idx = DUK_HSTRING_GET_ARRIDX_FAST(h);
	return arr_idx;
}

DUK_LOCAL duk_uint32_t duk__push_tval_to_property_key(duk_hthread *thr, duk_tval *tv_key, duk_hstring **out_h) {
	duk_push_tval(thr, tv_key);  /* XXX: could use an unsafe push here */
	return duk__to_property_key(thr, -1, out_h);
}

/* String is an own (virtual) property of a plain buffer. */
DUK_LOCAL duk_bool_t duk__key_is_plain_buf_ownprop(duk_hthread *thr, duk_hbuffer *buf, duk_hstring *key, duk_uint32_t arr_idx) {
	DUK_UNREF(thr);

	/* Virtual index properties.  Checking explicitly for
	 * 'arr_idx != DUK__NO_ARRAY_INDEX' is not necessary
	 * because DUK__NO_ARRAY_INDEXi is always larger than
	 * maximum allowed buffer size.
	 */
	DUK_ASSERT(DUK__NO_ARRAY_INDEX >= DUK_HBUFFER_GET_SIZE(buf));
	if (arr_idx < DUK_HBUFFER_GET_SIZE(buf)) {
		return 1;
	}

	/* Other virtual properties. */
	return (key == DUK_HTHREAD_STRING_LENGTH(thr));
}

/*
 *  Helpers for managing property storage size
 */

/* Get default hash part size for a certain entry part size. */
#if defined(DUK_USE_HOBJECT_HASH_PART)
DUK_LOCAL duk_uint32_t duk__get_default_h_size(duk_uint32_t e_size) {
	DUK_ASSERT(e_size <= DUK_HOBJECT_MAX_PROPERTIES);

	if (e_size >= DUK_USE_HOBJECT_HASH_PROP_LIMIT) {
		duk_uint32_t res;
		duk_uint32_t tmp;

		/* Hash size should be 2^N where N is chosen so that 2^N is
		 * larger than e_size.  Extra shifting is used to ensure hash
		 * is relatively sparse.
		 */
		tmp = e_size;
		res = 2;  /* Result will be 2 ** (N + 1). */
		while (tmp >= 0x40) {
			tmp >>= 6;
			res <<= 6;
		}
		while (tmp != 0) {
			tmp >>= 1;
			res <<= 1;
		}
		DUK_ASSERT((DUK_HOBJECT_MAX_PROPERTIES << 2U) > DUK_HOBJECT_MAX_PROPERTIES);  /* Won't wrap, even shifted by 2. */
		DUK_ASSERT(res > e_size);
		return res;
	} else {
		return 0;
	}
}
#endif  /* USE_PROP_HASH_PART */

/* Get minimum entry part growth for a certain size. */
DUK_LOCAL duk_uint32_t duk__get_min_grow_e(duk_uint32_t e_size) {
	duk_uint32_t res;

	res = (e_size + DUK_USE_HOBJECT_ENTRY_MINGROW_ADD) / DUK_USE_HOBJECT_ENTRY_MINGROW_DIVISOR;
	DUK_ASSERT(res >= 1);  /* important for callers */
	return res;
}

/* Get minimum array part growth for a certain size. */
DUK_LOCAL duk_uint32_t duk__get_min_grow_a(duk_uint32_t a_size) {
	duk_uint32_t res;

	res = (a_size + DUK_USE_HOBJECT_ARRAY_MINGROW_ADD) / DUK_USE_HOBJECT_ARRAY_MINGROW_DIVISOR;
	DUK_ASSERT(res >= 1);  /* important for callers */
	return res;
}

/* Count actually used entry part entries (non-NULL keys). */
DUK_LOCAL duk_uint32_t duk__count_used_e_keys(duk_hthread *thr, duk_hobject *obj) {
	duk_uint_fast32_t i;
	duk_uint_fast32_t n = 0;
	duk_hstring **e;

	DUK_ASSERT(obj != NULL);
	DUK_UNREF(thr);

	e = DUK_HOBJECT_E_GET_KEY_BASE(thr->heap, obj);
	for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
		if (*e++) {
			n++;
		}
	}
	return (duk_uint32_t) n;
}

/* Count actually used array part entries and array minimum size.
 * NOTE: 'out_min_size' can be computed much faster by starting from the
 * end and breaking out early when finding first used entry, but this is
 * not needed now.
 */
DUK_LOCAL void duk__compute_a_stats(duk_hthread *thr, duk_hobject *obj, duk_uint32_t *out_used, duk_uint32_t *out_min_size) {
	duk_uint_fast32_t i;
	duk_uint_fast32_t used = 0;
	duk_uint_fast32_t highest_idx = (duk_uint_fast32_t) -1;  /* see below */
	duk_tval *a;

	DUK_ASSERT(obj != NULL);
	DUK_ASSERT(out_used != NULL);
	DUK_ASSERT(out_min_size != NULL);
	DUK_UNREF(thr);

	a = DUK_HOBJECT_A_GET_BASE(thr->heap, obj);
	for (i = 0; i < DUK_HOBJECT_GET_ASIZE(obj); i++) {
		duk_tval *tv = a++;
		if (!DUK_TVAL_IS_UNUSED(tv)) {
			used++;
			highest_idx = i;
		}
	}

	/* Initial value for highest_idx is -1 coerced to unsigned.  This
	 * is a bit odd, but (highest_idx + 1) will then wrap to 0 below
	 * for out_min_size as intended.
	 */

	*out_used = (duk_uint32_t) used;
	*out_min_size = (duk_uint32_t) (highest_idx + 1);  /* 0 if no used entries */
}

/* Check array density and indicate whether or not the array part should be abandoned. */
DUK_LOCAL duk_bool_t duk__abandon_array_density_check(duk_uint32_t a_used, duk_uint32_t a_size) {
	/*
	 *  Array abandon check; abandon if:
	 *
	 *    new_used / new_size < limit
	 *    new_used < limit * new_size        || limit is 3 bits fixed point
	 *    new_used < limit' / 8 * new_size   || *8
	 *    8*new_used < limit' * new_size     || :8
	 *    new_used < limit' * (new_size / 8)
	 *
	 *  Here, new_used = a_used, new_size = a_size.
	 *
	 *  Note: some callers use approximate values for a_used and/or a_size
	 *  (e.g. dropping a '+1' term).  This doesn't affect the usefulness
	 *  of the check, but may confuse debugging.
	 */

	return (a_used < DUK_USE_HOBJECT_ARRAY_ABANDON_LIMIT * (a_size >> 3));
}

/* Fast check for extending array: check whether or not a slow density check is required. */
DUK_LOCAL duk_bool_t duk__abandon_array_slow_check_required(duk_uint32_t arr_idx, duk_uint32_t old_size) {
	duk_uint32_t new_size_min;

	/*
	 *  In a fast check we assume old_size equals old_used (i.e., existing
	 *  array is fully dense).
	 *
	 *  Slow check if:
	 *
	 *    (new_size - old_size) / old_size > limit
	 *    new_size - old_size > limit * old_size
	 *    new_size > (1 + limit) * old_size        || limit' is 3 bits fixed point
	 *    new_size > (1 + (limit' / 8)) * old_size || * 8
	 *    8 * new_size > (8 + limit') * old_size   || : 8
	 *    new_size > (8 + limit') * (old_size / 8)
	 *    new_size > limit'' * (old_size / 8)      || limit'' = 9 -> max 25% increase
	 *    arr_idx + 1 > limit'' * (old_size / 8)
	 *
	 *  This check doesn't work well for small values, so old_size is rounded
	 *  up for the check (and the '+ 1' of arr_idx can be ignored in practice):
	 *
	 *    arr_idx > limit'' * ((old_size + 7) / 8)
	 */

	new_size_min = arr_idx + 1;
	return (new_size_min >= DUK_USE_HOBJECT_ARRAY_ABANDON_MINSIZE) &&
	       (arr_idx > DUK_USE_HOBJECT_ARRAY_FAST_RESIZE_LIMIT * ((old_size + 7) >> 3));
}

DUK_LOCAL duk_bool_t duk__abandon_array_check(duk_hthread *thr, duk_uint32_t arr_idx, duk_hobject *obj) {
	duk_uint32_t min_size;
	duk_uint32_t old_used;
	duk_uint32_t old_size;

	if (!duk__abandon_array_slow_check_required(arr_idx, DUK_HOBJECT_GET_ASIZE(obj))) {
		DUK_DDD(DUK_DDDPRINT("=> fast resize is OK"));
		return 0;
	}

	duk__compute_a_stats(thr, obj, &old_used, &old_size);

	DUK_DDD(DUK_DDDPRINT("abandon check, array stats: old_used=%ld, old_size=%ld, arr_idx=%ld",
	                     (long) old_used, (long) old_size, (long) arr_idx));

	min_size = arr_idx + 1;
#if defined(DUK_USE_OBJSIZES16)
	if (min_size > DUK_UINT16_MAX) {
		goto do_abandon;
	}
#endif
	DUK_UNREF(min_size);

	/* Note: intentionally use approximations to shave a few instructions:
	 *   a_used = old_used  (accurate: old_used + 1)
	 *   a_size = arr_idx   (accurate: arr_idx + 1)
	 */
	if (duk__abandon_array_density_check(old_used, arr_idx)) {
		DUK_DD(DUK_DDPRINT("write to new array entry beyond current length, "
		                   "decided to abandon array part (would become too sparse)"));

		/* Abandoning requires a props allocation resize and
		 * 'rechecks' the valstack, invalidating any existing
		 * valstack value pointers.
		 */
		goto do_abandon;
	}

	DUK_DDD(DUK_DDDPRINT("=> decided to keep array part"));
	return 0;

 do_abandon:
	duk__abandon_array_part(thr, obj);
	DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(obj));
	return 1;
}

DUK_LOCAL duk_tval *duk__obtain_arridx_slot_slowpath(duk_hthread *thr, duk_uint32_t arr_idx, duk_hobject *obj) {
	/*
	 *  Array needs to grow, but we don't want it becoming too sparse.
	 *  If it were to become sparse, abandon array part, moving all
	 *  array entries into the entries part (for good).
	 *
	 *  Since we don't keep track of actual density (used vs. size) of
	 *  the array part, we need to estimate somehow.  The check is made
	 *  in two parts:
	 *
	 *    - Check whether the resize need is small compared to the
	 *      current size (relatively); if so, resize without further
	 *      checking (essentially we assume that the original part is
	 *      "dense" so that the result would be dense enough).
	 *
	 *    - Otherwise, compute the resize using an actual density
	 *      measurement based on counting the used array entries.
	 */

	DUK_DDD(DUK_DDDPRINT("write to new array requires array resize, decide whether to do a "
	                     "fast resize without abandon check (arr_idx=%ld, old_size=%ld)",
	                     (long) arr_idx, (long) DUK_HOBJECT_GET_ASIZE(obj)));

	if (DUK_UNLIKELY(duk__abandon_array_check(thr, arr_idx, obj) != 0)) {
		DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(obj));
		return NULL;
	}

	DUK_DD(DUK_DDPRINT("write to new array entry beyond current length, "
	                   "decided to extend current allocation"));

	/* In principle it's possible to run out of memory extending the
	 * array but with the allocation going through if we were to abandon
	 * the array part and try again.  In practice this should be rare
	 * because abandoned arrays have a higher per-entry footprint.
	 */

	duk__grow_props_for_array_item(thr, obj, arr_idx);

	DUK_ASSERT(DUK_HOBJECT_HAS_ARRAY_PART(obj));
	DUK_ASSERT(arr_idx < DUK_HOBJECT_GET_ASIZE(obj));
	return DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, arr_idx);
}

DUK_LOCAL DUK_INLINE duk_tval *duk__obtain_arridx_slot(duk_hthread *thr, duk_uint32_t arr_idx, duk_hobject *obj) {
	if (DUK_LIKELY(arr_idx < DUK_HOBJECT_GET_ASIZE(obj))) {
		return DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, arr_idx);
	} else {
		return duk__obtain_arridx_slot_slowpath(thr, arr_idx, obj);
	}
}

/*
 *  Proxy helpers
 */

#if defined(DUK_USE_ES6_PROXY)
DUK_INTERNAL duk_bool_t duk_hobject_proxy_check(duk_hobject *obj, duk_hobject **out_target, duk_hobject **out_handler) {
	duk_hproxy *h_proxy;

	DUK_ASSERT(obj != NULL);
	DUK_ASSERT(out_target != NULL);
	DUK_ASSERT(out_handler != NULL);

	/* Caller doesn't need to check exotic proxy behavior (but does so for
	 * some fast paths).
	 */
	if (DUK_LIKELY(!DUK_HOBJECT_IS_PROXY(obj))) {
		return 0;
	}
	h_proxy = (duk_hproxy *) obj;
	DUK_HPROXY_ASSERT_VALID(h_proxy);

	DUK_ASSERT(h_proxy->handler != NULL);
	DUK_ASSERT(h_proxy->target != NULL);
	*out_handler = h_proxy->handler;
	*out_target = h_proxy->target;

	return 1;
}
#endif  /* DUK_USE_ES6_PROXY */

/* Get Proxy target object.  If the argument is not a Proxy, return it as is.
 * If a Proxy is revoked, an error is thrown.
 */
#if defined(DUK_USE_ES6_PROXY)
DUK_INTERNAL duk_hobject *duk_hobject_resolve_proxy_target(duk_hobject *obj) {
	DUK_ASSERT(obj != NULL);

	/* Resolve Proxy targets until Proxy chain ends.  No explicit check for
	 * a Proxy loop: user code cannot create such a loop (it would only be
	 * possible by editing duk_hproxy references directly).
	 */

	while (DUK_HOBJECT_IS_PROXY(obj)) {
		duk_hproxy *h_proxy;

		h_proxy = (duk_hproxy *) obj;
		DUK_HPROXY_ASSERT_VALID(h_proxy);
		obj = h_proxy->target;
		DUK_ASSERT(obj != NULL);
	}

	DUK_ASSERT(obj != NULL);
	return obj;
}
#endif  /* DUK_USE_ES6_PROXY */

#if defined(DUK_USE_ES6_PROXY)
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) {
	duk_hobject *h_handler;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(obj != NULL);
	DUK_ASSERT(tv_key != NULL);
	DUK_ASSERT(out_target != NULL);

	if (!duk_hobject_proxy_check(obj, out_target, &h_handler)) {
		return 0;
	}
	DUK_ASSERT(*out_target != NULL);
	DUK_ASSERT(h_handler != NULL);

	/* XXX: At the moment Duktape accesses internal keys like _Finalizer using a
	 * normal property set/get which would allow a proxy handler to interfere with
	 * such behavior and to get access to internal key strings.  This is not a problem
	 * as such because internal key strings can be created in other ways too (e.g.
	 * through buffers).  The best fix is to change Duktape internal lookups to
	 * skip proxy behavior.  Until that, internal property accesses bypass the
	 * proxy and are applied to the target (as if the handler did not exist).
	 * This has some side effects, see test-bi-proxy-internal-keys.js.
	 */

	if (DUK_TVAL_IS_STRING(tv_key)) {
		duk_hstring *h_key = (duk_hstring *) DUK_TVAL_GET_STRING(tv_key);
		DUK_ASSERT(h_key != NULL);
		if (DUK_HSTRING_HAS_HIDDEN(h_key)) {
			/* Symbol accesses must go through proxy lookup in ES2015.
			 * Hidden symbols behave like Duktape 1.x internal keys
			 * and currently won't.
			 */
			DUK_DDD(DUK_DDDPRINT("hidden key, skip proxy handler and apply to target"));
			return 0;
		}
	}

	/* The handler is looked up with a normal property lookup; it may be an
	 * accessor or the handler object itself may be a proxy object.  If the
	 * handler is a proxy, we need to extend the valstack as we make a
	 * recursive proxy check without a function call in between (in fact
	 * there is no limit to the potential recursion here).
	 *
	 * (For sanity, proxy creation rejects another proxy object as either
	 * the handler or the target at the moment so recursive proxy cases
	 * are not realized now.)
	 */

	/* XXX: C recursion limit if proxies are allowed as handler/target values */

	duk_require_stack(thr, DUK__VALSTACK_PROXY_LOOKUP);
	duk_push_hobject(thr, h_handler);
	if (duk_get_prop_stridx_short(thr, -1, stridx_trap)) {
		/* -> [ ... handler trap ] */
		duk_insert(thr, -2);  /* -> [ ... trap handler ] */

		/* stack prepped for func call: [ ... trap handler ] */
		return 1;
	} else {
		duk_pop_2_unsafe(thr);
		return 0;
	}
}
#endif  /* DUK_USE_ES6_PROXY */

/*
 *  Reallocate property allocation, moving properties to the new allocation.
 *
 *  Includes key compaction, rehashing, and can also optionally abandon
 *  the array part, 'migrating' array entries into the beginning of the
 *  new entry part.
 *
 *  There is no support for in-place reallocation or just compacting keys
 *  without resizing the property allocation.  This is intentional to keep
 *  code size minimal, but would be useful future work.
 *
 *  The implementation is relatively straightforward, except for the array
 *  abandonment process.  Array abandonment requires that new string keys
 *  are interned, which may trigger GC.  All keys interned so far must be
 *  reachable for GC at all times and correctly refcounted for; valstack is
 *  used for that now.
 *
 *  Also, a GC triggered during this reallocation process must not interfere
 *  with the object being resized.  This is currently controlled by preventing
 *  finalizers (as they may affect ANY object) and object compaction in
 *  mark-and-sweep.  It would suffice to protect only this particular object
 *  from compaction, however.  DECREF refzero cascades are side effect free
 *  and OK.
 *
 *  Note: because we need to potentially resize the valstack (as part
 *  of abandoning the array part), any tval pointers to the valstack
 *  will become invalid after this call.
 */

DUK_INTERNAL void duk_hobject_realloc_props(duk_hthread *thr,
                                            duk_hobject *obj,
                                            duk_uint32_t new_e_size,
                                            duk_uint32_t new_a_size,
                                            duk_uint32_t new_h_size,
                                            duk_bool_t abandon_array) {
	duk_small_uint_t prev_ms_base_flags;
	duk_uint32_t new_alloc_size;
	duk_uint32_t new_e_size_adjusted;
	duk_uint8_t *new_p;
	duk_hstring **new_e_k;
	duk_propvalue *new_e_pv;
	duk_uint8_t *new_e_f;
	duk_tval *new_a;
	duk_uint32_t *new_h;
	duk_uint32_t new_e_next;
	duk_uint_fast32_t i;
	duk_size_t array_copy_size;
#if defined(DUK_USE_ASSERTIONS)
	duk_bool_t prev_error_not_allowed;
#endif

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(obj != NULL);
	DUK_ASSERT(!abandon_array || new_a_size == 0);  /* if abandon_array, new_a_size must be 0 */
	DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL || (DUK_HOBJECT_GET_ESIZE(obj) == 0 && DUK_HOBJECT_GET_ASIZE(obj) == 0));
	DUK_ASSERT(new_h_size == 0 || new_h_size >= new_e_size);  /* required to guarantee success of rehashing,
	                                                           * intentionally use unadjusted new_e_size
	                                                           */
	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));
	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);

	DUK_STATS_INC(thr->heap, stats_object_realloc_props);

	/*
	 *  Pre resize assertions.
	 */

#if defined(DUK_USE_ASSERTIONS)
	/* XXX: pre-checks (such as no duplicate keys) */
#endif

	/*
	 *  For property layout 1, tweak e_size to ensure that the whole entry
	 *  part (key + val + flags) is a suitable multiple for alignment
	 *  (platform specific).
	 *
	 *  Property layout 2 does not require this tweaking and is preferred
	 *  on low RAM platforms requiring alignment.
	 */

#if defined(DUK_USE_HOBJECT_LAYOUT_2) || defined(DUK_USE_HOBJECT_LAYOUT_3)
	DUK_DDD(DUK_DDDPRINT("using layout 2 or 3, no need to pad e_size: %ld", (long) new_e_size));
	new_e_size_adjusted = new_e_size;
#elif defined(DUK_USE_HOBJECT_LAYOUT_1) && (DUK_HOBJECT_ALIGN_TARGET == 1)
	DUK_DDD(DUK_DDDPRINT("using layout 1, but no need to pad e_size: %ld", (long) new_e_size));
	new_e_size_adjusted = new_e_size;
#elif defined(DUK_USE_HOBJECT_LAYOUT_1) && ((DUK_HOBJECT_ALIGN_TARGET == 4) || (DUK_HOBJECT_ALIGN_TARGET == 8))
	new_e_size_adjusted = (new_e_size + (duk_uint32_t) DUK_HOBJECT_ALIGN_TARGET - 1U) &
	                      (~((duk_uint32_t) DUK_HOBJECT_ALIGN_TARGET - 1U));
	DUK_DDD(DUK_DDDPRINT("using layout 1, and alignment target is %ld, adjusted e_size: %ld -> %ld",
	                     (long) DUK_HOBJECT_ALIGN_TARGET, (long) new_e_size, (long) new_e_size_adjusted));
	DUK_ASSERT(new_e_size_adjusted >= new_e_size);
#else
#error invalid hobject layout defines
#endif

	/*
	 *  Debug logging after adjustment.
	 */

	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 "
	                     "{e_size=%ld,a_size=%ld,h_size=%ld}, abandon_array=%ld, unadjusted new_e_size=%ld",
	                     (void *) obj,
	                     (long) DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE(obj),
	                                                       DUK_HOBJECT_GET_ASIZE(obj),
	                                                       DUK_HOBJECT_GET_HSIZE(obj)),
	                     (long) DUK_HOBJECT_P_COMPUTE_SIZE(new_e_size_adjusted, new_a_size, new_h_size),
	                     (void *) DUK_HOBJECT_GET_PROPS(thr->heap, obj),
	                     (long) DUK_HOBJECT_GET_ESIZE(obj),
	                     (long) DUK_HOBJECT_GET_ENEXT(obj),
	                     (long) DUK_HOBJECT_GET_ASIZE(obj),
	                     (long) DUK_HOBJECT_GET_HSIZE(obj),
	                     (long) new_e_size_adjusted,
	                     (long) new_a_size,
	                     (long) new_h_size,
	                     (long) abandon_array,
	                     (long) new_e_size));

	/*
	 *  Property count check.  This is the only point where we ensure that
	 *  we don't get more (allocated) property space that we can handle.
	 *  There aren't hard limits as such, but some algorithms may fail
	 *  if we get too close to the 4G property limit.
	 *
	 *  Since this works based on allocation size (not actually used size),
	 *  the limit is a bit approximate but good enough in practice.
	 */

	if (new_e_size_adjusted + new_a_size > DUK_HOBJECT_MAX_PROPERTIES) {
		DUK_ERROR_ALLOC_FAILED(thr);
		DUK_WO_NORETURN(return;);
	}
#if defined(DUK_USE_OBJSIZES16)
	if (new_e_size_adjusted > DUK_UINT16_MAX || new_a_size > DUK_UINT16_MAX) {
		/* If caller gave us sizes larger than what we can store,
		 * fail memory safely with an internal error rather than
		 * truncating the sizes.
		 */
		DUK_ERROR_INTERNAL(thr);
		DUK_WO_NORETURN(return;);
	}
#endif

	/*
	 *  Compute new alloc size and alloc new area.
	 *
	 *  The new area is not tracked in the heap at all, so it's critical
	 *  we get to free/keep it in a controlled manner.
	 */

#if defined(DUK_USE_ASSERTIONS)
	/* Whole path must be error throw free, but we may be called from
	 * within error handling so can't assert for error_not_allowed == 0.
	 */
	prev_error_not_allowed = thr->heap->error_not_allowed;
	thr->heap->error_not_allowed = 1;
#endif
	prev_ms_base_flags = thr->heap->ms_base_flags;
	thr->heap->ms_base_flags |=
	        DUK_MS_FLAG_NO_OBJECT_COMPACTION;      /* Avoid attempt to compact the current object (all objects really). */
	thr->heap->pf_prevent_count++;                 /* Avoid finalizers. */
	DUK_ASSERT(thr->heap->pf_prevent_count != 0);  /* Wrap. */

	new_alloc_size = DUK_HOBJECT_P_COMPUTE_SIZE(new_e_size_adjusted, new_a_size, new_h_size);
	DUK_DDD(DUK_DDDPRINT("new hobject allocation size is %ld", (long) new_alloc_size));
	if (new_alloc_size == 0) {
		DUK_ASSERT(new_e_size_adjusted == 0);
		DUK_ASSERT(new_a_size == 0);
		DUK_ASSERT(new_h_size == 0);
		new_p = NULL;
	} else {
		/* Alloc may trigger mark-and-sweep but no compaction, and
		 * cannot throw.
		 */
#if 0  /* XXX: inject test */
		if (1) {
			new_p = NULL;
			goto alloc_failed;
		}
#endif
		new_p = (duk_uint8_t *) DUK_ALLOC(thr->heap, new_alloc_size);
		if (new_p == NULL) {
			/* NULL always indicates alloc failure because
			 * new_alloc_size > 0.
			 */
			goto alloc_failed;
		}
	}

	/* Set up pointers to the new property area: this is hidden behind a macro
	 * because it is memory layout specific.
	 */
	DUK_HOBJECT_P_SET_REALLOC_PTRS(new_p, new_e_k, new_e_pv, new_e_f, new_a, new_h,
	                               new_e_size_adjusted, new_a_size, new_h_size);
	DUK_UNREF(new_h);  /* happens when hash part dropped */
	new_e_next = 0;

	/* if new_p == NULL, all of these pointers are NULL */
	DUK_ASSERT((new_p != NULL) ||
	           (new_e_k == NULL && new_e_pv == NULL && new_e_f == NULL &&
	            new_a == NULL && new_h == NULL));

	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",
	                     (long) new_alloc_size, (void *) new_e_k, (void *) new_e_pv, (void *) new_e_f,
	                     (void *) new_a, (void *) new_h));

	/*
	 *  Migrate array part to start of entries if requested.
	 *
	 *  Note: from an enumeration perspective the order of entry keys matters.
	 *  Array keys should appear wherever they appeared before the array abandon
	 *  operation.  (This no longer matters much because keys are ES2015 sorted.)
	 */

	if (abandon_array) {
		/* Assuming new_a_size == 0, and that entry part contains
		 * no conflicting keys, refcounts do not need to be adjusted for
		 * the values, as they remain exactly the same.
		 *
		 * The keys, however, need to be interned, incref'd, and be
		 * reachable for GC.  Any intern attempt may trigger a GC and
		 * claim any non-reachable strings, so every key must be reachable
		 * at all times.  Refcounts must be correct to satisfy refcount
		 * assertions.
		 *
		 * A longjmp must not occur here, as the new_p allocation would
		 * leak.  Refcounts would come out correctly as the interned
		 * strings are valstack tracked.
		 */
		DUK_ASSERT(new_a_size == 0);

		DUK_STATS_INC(thr->heap, stats_object_abandon_array);

		for (i = 0; i < DUK_HOBJECT_GET_ASIZE(obj); i++) {
			duk_tval *tv1;
			duk_tval *tv2;
			duk_hstring *key;

			DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL);

			tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, i);
			if (DUK_TVAL_IS_UNUSED(tv1)) {
				continue;
			}

			DUK_ASSERT(new_p != NULL && new_e_k != NULL &&
			           new_e_pv != NULL && new_e_f != NULL);

			/*
			 *  Intern key via the valstack to ensure reachability behaves
			 *  properly.  We must avoid longjmp's here so use non-checked
			 *  primitives.
			 *
			 *  Note: duk_check_stack() potentially reallocs the valstack,
			 *  invalidating any duk_tval pointers to valstack.  Callers
			 *  must be careful.
			 */

#if 0  /* XXX: inject test */
			if (1) {
				goto abandon_error;
			}
#endif
			/* Never shrinks; auto-adds DUK_VALSTACK_INTERNAL_EXTRA, which
			 * is generous.
			 */
			if (!duk_check_stack(thr, 1)) {
				goto abandon_error;
			}
			DUK_ASSERT_VALSTACK_SPACE(thr, 1);
			key = duk_heap_strtable_intern_u32(thr->heap, (duk_uint32_t) i);
			if (key == NULL) {
				goto abandon_error;
			}
			duk_push_hstring(thr, key);  /* keep key reachable for GC etc; guaranteed not to fail */

			/* Key is now reachable in the valstack, don't INCREF
			 * the new allocation yet (we'll steal the refcounts
			 * from the value stack once all keys are done).
			 */

			new_e_k[new_e_next] = key;
			tv2 = &new_e_pv[new_e_next].v;  /* array entries are all plain values */
			DUK_TVAL_SET_TVAL(tv2, tv1);
			new_e_f[new_e_next] = DUK_PROPDESC_FLAG_WRITABLE |
			                      DUK_PROPDESC_FLAG_ENUMERABLE |
			                      DUK_PROPDESC_FLAG_CONFIGURABLE;
			new_e_next++;

			/* Note: new_e_next matches pushed temp key count, and nothing can
			 * fail above between the push and this point.
			 */
		}

		/* Steal refcounts from value stack. */
		DUK_DDD(DUK_DDDPRINT("abandon array: pop %ld key temps from valstack", (long) new_e_next));
		duk_pop_n_nodecref_unsafe(thr, (duk_idx_t) new_e_next);
	}

	/*
	 *  Copy keys and values in the entry part (compacting them at the same time).
	 */

	for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
		duk_hstring *key;

		DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL);

		key = DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i);
		if (key == NULL) {
			continue;
		}

		DUK_ASSERT(new_p != NULL && new_e_k != NULL &&
		           new_e_pv != NULL && new_e_f != NULL);

		new_e_k[new_e_next] = key;
		new_e_pv[new_e_next] = DUK_HOBJECT_E_GET_VALUE(thr->heap, obj, i);
		new_e_f[new_e_next] = DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, i);
		new_e_next++;
	}
	/* the entries [new_e_next, new_e_size_adjusted[ are left uninitialized on purpose (ok, not gc reachable) */

	/*
	 *  Copy array elements to new array part.  If the new array part is
	 *  larger, initialize the unused entries as UNUSED because they are
	 *  GC reachable.
	 */

#if defined(DUK_USE_ASSERTIONS)
	/* Caller must have decref'd values above new_a_size (if that is necessary). */
	if (!abandon_array) {
		for (i = new_a_size; i < DUK_HOBJECT_GET_ASIZE(obj); i++) {
			duk_tval *tv;
			tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, i);
			DUK_ASSERT(DUK_TVAL_IS_UNUSED(tv));
		}
	}
#endif
	if (new_a_size > DUK_HOBJECT_GET_ASIZE(obj)) {
		array_copy_size = sizeof(duk_tval) * DUK_HOBJECT_GET_ASIZE(obj);
	} else {
		array_copy_size = sizeof(duk_tval) * new_a_size;
	}

	DUK_ASSERT(new_a != NULL || array_copy_size == 0U);
	DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL || array_copy_size == 0U);
	DUK_ASSERT(DUK_HOBJECT_GET_ASIZE(obj) > 0 || array_copy_size == 0U);
	duk_memcpy_unsafe((void *) new_a,
	                  (const void *) DUK_HOBJECT_A_GET_BASE(thr->heap, obj),
	                  array_copy_size);

	for (i = DUK_HOBJECT_GET_ASIZE(obj); i < new_a_size; i++) {
		duk_tval *tv = &new_a[i];
		DUK_TVAL_SET_UNUSED(tv);
	}

	/*
	 *  Rebuild the hash part always from scratch (guaranteed to finish
	 *  as long as caller gave consistent parameters).
	 *
	 *  Any resize of hash part requires rehashing.  In addition, by rehashing
	 *  get rid of any elements marked deleted (DUK__HASH_DELETED) which is critical
	 *  to ensuring the hash part never fills up.
	 */

#if defined(DUK_USE_HOBJECT_HASH_PART)
	if (new_h_size == 0) {
		DUK_DDD(DUK_DDDPRINT("no hash part, no rehash"));
	} else {
		duk_uint32_t mask;

		DUK_ASSERT(new_h != NULL);

		/* fill new_h with u32 0xff = UNUSED */
		DUK_ASSERT(new_h_size > 0);
		duk_memset(new_h, 0xff, sizeof(duk_uint32_t) * new_h_size);

		DUK_ASSERT(new_e_next <= new_h_size);  /* equality not actually possible */

		mask = new_h_size - 1;
		for (i = 0; i < new_e_next; i++) {
			duk_hstring *key = new_e_k[i];
			duk_uint32_t j, step;

			DUK_ASSERT(key != NULL);
			j = DUK_HSTRING_GET_HASH(key) & mask;
			step = 1;  /* Cache friendly but clustering prone. */

			for (;;) {
				DUK_ASSERT(new_h[j] != DUK__HASH_DELETED);  /* should never happen */
				if (new_h[j] == DUK__HASH_UNUSED) {
					DUK_DDD(DUK_DDDPRINT("rebuild hit %ld -> %ld", (long) j, (long) i));
					new_h[j] = (duk_uint32_t) i;
					break;
				}
				DUK_DDD(DUK_DDDPRINT("rebuild miss %ld, step %ld", (long) j, (long) step));
				j = (j + step) & mask;

				/* Guaranteed to finish (hash is larger than #props). */
			}
		}
	}
#endif  /* DUK_USE_HOBJECT_HASH_PART */

	/*
	 *  Nice debug log.
	 */

	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 "
	                   "{p=%p,e_size=%ld,e_next=%ld,a_size=%ld,h_size=%ld}, abandon_array=%ld, unadjusted new_e_size=%ld",
	                   (void *) obj,
	                   (long) DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE(obj),
	                                                     DUK_HOBJECT_GET_ASIZE(obj),
	                                                     DUK_HOBJECT_GET_HSIZE(obj)),
	                   (long) new_alloc_size,
	                   (void *) DUK_HOBJECT_GET_PROPS(thr->heap, obj),
	                   (long) DUK_HOBJECT_GET_ESIZE(obj),
	                   (long) DUK_HOBJECT_GET_ENEXT(obj),
	                   (long) DUK_HOBJECT_GET_ASIZE(obj),
	                   (long) DUK_HOBJECT_GET_HSIZE(obj),
	                   (void *) new_p,
	                   (long) new_e_size_adjusted,
	                   (long) new_e_next,
	                   (long) new_a_size,
	                   (long) new_h_size,
	                   (long) abandon_array,
	                   (long) new_e_size));

	/*
	 *  All done, switch properties ('p') allocation to new one.
	 */

	DUK_FREE_CHECKED(thr, DUK_HOBJECT_GET_PROPS(thr->heap, obj));  /* NULL obj->p is OK */
	DUK_HOBJECT_SET_PROPS(thr->heap, obj, new_p);
	DUK_HOBJECT_SET_ESIZE(obj, new_e_size_adjusted);
	DUK_HOBJECT_SET_ENEXT(obj, new_e_next);
	DUK_HOBJECT_SET_ASIZE(obj, new_a_size);
	DUK_HOBJECT_SET_HSIZE(obj, new_h_size);

	/* Clear array part flag only after switching. */
	if (abandon_array) {
		DUK_HOBJECT_CLEAR_ARRAY_PART(obj);
	}

	DUK_DDD(DUK_DDDPRINT("resize result: %!O", (duk_heaphdr *) obj));

	DUK_ASSERT(thr->heap->pf_prevent_count > 0);
	thr->heap->pf_prevent_count--;
	thr->heap->ms_base_flags = prev_ms_base_flags;
#if defined(DUK_USE_ASSERTIONS)
	DUK_ASSERT(thr->heap->error_not_allowed == 1);
	thr->heap->error_not_allowed = prev_error_not_allowed;
#endif

	/*
	 *  Post resize assertions.
	 */

#if defined(DUK_USE_ASSERTIONS)
	/* XXX: post-checks (such as no duplicate keys) */
#endif
	return;

	/*
	 *  Abandon array failed.  We don't need to DECREF anything
	 *  because the references in the new allocation are not
	 *  INCREF'd until abandon is complete.  The string interned
	 *  keys are on the value stack and are handled normally by
	 *  unwind.
	 */

 abandon_error:
 alloc_failed:
	DUK_D(DUK_DPRINT("object property table resize failed"));

	DUK_FREE_CHECKED(thr, new_p);  /* OK for NULL. */

	thr->heap->pf_prevent_count--;
	thr->heap->ms_base_flags = prev_ms_base_flags;
#if defined(DUK_USE_ASSERTIONS)
	DUK_ASSERT(thr->heap->error_not_allowed == 1);
	thr->heap->error_not_allowed = prev_error_not_allowed;
#endif

	DUK_ERROR_ALLOC_FAILED(thr);
	DUK_WO_NORETURN(return;);
}

/*
 *  Helpers to resize properties allocation on specific needs.
 */

DUK_INTERNAL void duk_hobject_resize_entrypart(duk_hthread *thr,
                                               duk_hobject *obj,
                                               duk_uint32_t new_e_size) {
	duk_uint32_t old_e_size;
	duk_uint32_t new_a_size;
	duk_uint32_t new_h_size;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(obj != NULL);

	old_e_size = DUK_HOBJECT_GET_ESIZE(obj);
	if (old_e_size > new_e_size) {
		new_e_size = old_e_size;
	}
#if defined(DUK_USE_HOBJECT_HASH_PART)
	new_h_size = duk__get_default_h_size(new_e_size);
#else
	new_h_size = 0;
#endif
	new_a_size = DUK_HOBJECT_GET_ASIZE(obj);

	duk_hobject_realloc_props(thr, obj, new_e_size, new_a_size, new_h_size, 0);
}

/* Grow entry part allocation for one additional entry. */
DUK_LOCAL void duk__grow_props_for_new_entry_item(duk_hthread *thr, duk_hobject *obj) {
	duk_uint32_t old_e_used;  /* actually used, non-NULL entries */
	duk_uint32_t new_e_size_minimum;
	duk_uint32_t new_e_size;
	duk_uint32_t new_a_size;
	duk_uint32_t new_h_size;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(obj != NULL);

	/* Duktape 0.11.0 and prior tried to optimize the resize by not
	 * counting the number of actually used keys prior to the resize.
	 * This worked mostly well but also caused weird leak-like behavior
	 * as in: test-bug-object-prop-alloc-unbounded.js.  So, now we count
	 * the keys explicitly to compute the new entry part size.
	 */

	old_e_used = duk__count_used_e_keys(thr, obj);
	new_e_size_minimum = old_e_used + 1;
	new_e_size = old_e_used + duk__get_min_grow_e(old_e_used);
#if defined(DUK_USE_HOBJECT_HASH_PART)
	new_h_size = duk__get_default_h_size(new_e_size);
#else
	new_h_size = 0;
#endif
	new_a_size = DUK_HOBJECT_GET_ASIZE(obj);

#if defined(DUK_USE_OBJSIZES16)
	if (new_e_size > DUK_UINT16_MAX) {
		new_e_size = DUK_UINT16_MAX;
	}
	if (new_h_size > DUK_UINT16_MAX) {
		new_h_size = DUK_UINT16_MAX;
	}
	if (new_a_size > DUK_UINT16_MAX) {
		new_a_size = DUK_UINT16_MAX;
	}
#endif
	DUK_ASSERT(new_h_size == 0 || new_h_size >= new_e_size);

	if (!(new_e_size >= new_e_size_minimum)) {
		DUK_ERROR_ALLOC_FAILED(thr);
		DUK_WO_NORETURN(return;);
	}

	duk_hobject_realloc_props(thr, obj, new_e_size, new_a_size, new_h_size, 0);
}

/* Grow array part for a new highest array index. */
DUK_LOCAL void duk__grow_props_for_array_item(duk_hthread *thr, duk_hobject *obj, duk_uint32_t highest_arr_idx) {
	duk_uint32_t new_e_size;
	duk_uint32_t new_a_size;
	duk_uint32_t new_a_size_minimum;
	duk_uint32_t new_h_size;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(obj != NULL);
	DUK_ASSERT(highest_arr_idx >= DUK_HOBJECT_GET_ASIZE(obj));

	new_e_size = DUK_HOBJECT_GET_ESIZE(obj);
	new_h_size = DUK_HOBJECT_GET_HSIZE(obj);
	new_a_size_minimum = highest_arr_idx + 1;
	new_a_size = highest_arr_idx + duk__get_min_grow_a(highest_arr_idx);
	DUK_ASSERT(new_a_size >= highest_arr_idx + 1);  /* duk__get_min_grow_a() is always >= 1 */

#if defined(DUK_USE_OBJSIZES16)
	if (new_e_size > DUK_UINT16_MAX) {
		new_e_size = DUK_UINT16_MAX;
	}
	if (new_h_size > DUK_UINT16_MAX) {
		new_h_size = DUK_UINT16_MAX;
	}
	if (new_a_size > DUK_UINT16_MAX) {
		new_a_size = DUK_UINT16_MAX;
	}
#endif

	if (!(new_a_size >= new_a_size_minimum)) {
		DUK_ERROR_ALLOC_FAILED(thr);
		DUK_WO_NORETURN(return;);
	}

	duk_hobject_realloc_props(thr, obj, new_e_size, new_a_size, new_h_size, 0);
}

/* Abandon array part, moving array entries into entries part.
 * This requires a props resize, which is a heavy operation.
 * We also compact the entries part while we're at it, although
 * this is not strictly required.
 */
DUK_LOCAL void duk__abandon_array_part(duk_hthread *thr, duk_hobject *obj) {
	duk_uint32_t new_e_size_minimum;
	duk_uint32_t new_e_size;
	duk_uint32_t new_a_size;
	duk_uint32_t new_h_size;
	duk_uint32_t e_used;  /* actually used, non-NULL keys */
	duk_uint32_t a_used;
	duk_uint32_t a_size;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(obj != NULL);

	e_used = duk__count_used_e_keys(thr, obj);
	duk__compute_a_stats(thr, obj, &a_used, &a_size);

	/*
	 *  Must guarantee all actually used array entries will fit into
	 *  new entry part.  Add one growth step to ensure we don't run out
	 *  of space right away.
	 */

	new_e_size_minimum = e_used + a_used;
	new_e_size = new_e_size_minimum + duk__get_min_grow_e(new_e_size_minimum);
	new_a_size = 0;
#if defined(DUK_USE_HOBJECT_HASH_PART)
	new_h_size = duk__get_default_h_size(new_e_size);
#else
	new_h_size = 0;
#endif

#if defined(DUK_USE_OBJSIZES16)
	if (new_e_size > DUK_UINT16_MAX) {
		new_e_size = DUK_UINT16_MAX;
	}
	if (new_h_size > DUK_UINT16_MAX) {
		new_h_size = DUK_UINT16_MAX;
	}
	if (new_a_size > DUK_UINT16_MAX) {
		new_a_size = DUK_UINT16_MAX;
	}
#endif

	if (!(new_e_size >= new_e_size_minimum)) {
		DUK_ERROR_ALLOC_FAILED(thr);
		DUK_WO_NORETURN(return;);
	}

	DUK_DD(DUK_DDPRINT("abandon array part for hobject %p, "
	                   "array stats before: e_used=%ld, a_used=%ld, a_size=%ld; "
	                   "resize to e_size=%ld, a_size=%ld, h_size=%ld",
	                   (void *) obj, (long) e_used, (long) a_used, (long) a_size,
	                   (long) new_e_size, (long) new_a_size, (long) new_h_size));

	duk_hobject_realloc_props(thr, obj, new_e_size, new_a_size, new_h_size, 1);
}

/*
 *  Compact an object.  Minimizes allocation size for objects which are
 *  not likely to be extended.  This is useful for internal and non-
 *  extensible objects, but can also be called for non-extensible objects.
 *  May abandon the array part if it is computed to be too sparse.
 *
 *  This call is relatively expensive, as it needs to scan both the
 *  entries and the array part.
 *
 *  The call may fail due to allocation error.
 */

DUK_INTERNAL void duk_hobject_compact_props(duk_hthread *thr, duk_hobject *obj) {
	duk_uint32_t e_size;       /* currently used -> new size */
	duk_uint32_t a_size;       /* currently required */
	duk_uint32_t a_used;       /* actually used */
	duk_uint32_t h_size;
	duk_bool_t abandon_array;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(obj != NULL);

#if defined(DUK_USE_ROM_OBJECTS)
	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {
		DUK_DD(DUK_DDPRINT("ignore attempt to compact a rom object"));
		return;
	}
#endif

	e_size = duk__count_used_e_keys(thr, obj);
	duk__compute_a_stats(thr, obj, &a_used, &a_size);

	DUK_DD(DUK_DDPRINT("compacting hobject, used e keys %ld, used a keys %ld, min a size %ld, "
	                   "resized array density would be: %ld/%ld = %lf",
	                   (long) e_size, (long) a_used, (long) a_size,
	                   (long) a_used, (long) a_size,
	                   (double) a_used / (double) a_size));

	if (duk__abandon_array_density_check(a_used, a_size)) {
		DUK_DD(DUK_DDPRINT("decided to abandon array during compaction, a_used=%ld, a_size=%ld",
		                   (long) a_used, (long) a_size));
		abandon_array = 1;
		e_size += a_used;
		a_size = 0;
	} else {
		DUK_DD(DUK_DDPRINT("decided to keep array during compaction"));
		abandon_array = 0;
	}

#if defined(DUK_USE_HOBJECT_HASH_PART)
	if (e_size >= DUK_USE_HOBJECT_HASH_PROP_LIMIT) {
		h_size = duk__get_default_h_size(e_size);
	} else {
		h_size = 0;
	}
#else
	h_size = 0;
#endif

	DUK_DD(DUK_DDPRINT("compacting hobject -> new e_size %ld, new a_size=%ld, new h_size=%ld, abandon_array=%ld",
	                   (long) e_size, (long) a_size, (long) h_size, (long) abandon_array));

	duk_hobject_realloc_props(thr, obj, e_size, a_size, h_size, abandon_array);
}

/*
 *  Find an existing key from entry part either by linear scan or by
 *  using the hash index (if it exists).
 *
 *  Sets entry index (and possibly the hash index) to output variables,
 *  which allows the caller to update the entry and hash entries in-place.
 *  If entry is not found, both values are set to -1.  If entry is found
 *  but there is no hash part, h_idx is set to -1.
 */

DUK_INTERNAL duk_bool_t duk_hobject_find_entry(duk_heap *heap, duk_hobject *obj, duk_hstring *key, duk_int_t *e_idx, duk_int_t *h_idx) {
	DUK_ASSERT(obj != NULL);
	DUK_ASSERT(key != NULL);
	DUK_ASSERT(e_idx != NULL);
	DUK_ASSERT(h_idx != NULL);
	DUK_UNREF(heap);

	if (DUK_LIKELY(DUK_HOBJECT_GET_HSIZE(obj) == 0))
	{
		/* Linear scan: more likely because most objects are small.
		 * This is an important fast path.
		 *
		 * XXX: this might be worth inlining for property lookups.
		 */
		duk_uint_fast32_t i;
		duk_uint_fast32_t n;
		duk_hstring **h_keys_base;
		DUK_DDD(DUK_DDDPRINT("duk_hobject_find_entry() using linear scan for lookup"));

		h_keys_base = DUK_HOBJECT_E_GET_KEY_BASE(heap, obj);
		n = DUK_HOBJECT_GET_ENEXT(obj);
		for (i = 0; i < n; i++) {
			if (h_keys_base[i] == key) {
				*e_idx = (duk_int_t) i;
				*h_idx = -1;
				return 1;
			}
		}
	}
#if defined(DUK_USE_HOBJECT_HASH_PART)
	else
	{
		/* hash lookup */
		duk_uint32_t n;
		duk_uint32_t i, step;
		duk_uint32_t *h_base;
		duk_uint32_t mask;

		DUK_DDD(DUK_DDDPRINT("duk_hobject_find_entry() using hash part for lookup"));

		h_base = DUK_HOBJECT_H_GET_BASE(heap, obj);
		n = DUK_HOBJECT_GET_HSIZE(obj);
		mask = n - 1;
		i = DUK_HSTRING_GET_HASH(key) & mask;
		step = 1;  /* Cache friendly but clustering prone. */

		for (;;) {
			duk_uint32_t t;

			DUK_ASSERT_DISABLE(i >= 0);  /* unsigned */
			DUK_ASSERT(i < DUK_HOBJECT_GET_HSIZE(obj));
			t = h_base[i];
			DUK_ASSERT(t == DUK__HASH_UNUSED || t == DUK__HASH_DELETED ||
			           (t < DUK_HOBJECT_GET_ESIZE(obj)));  /* t >= 0 always true, unsigned */

			if (t == DUK__HASH_UNUSED) {
				break;
			} else if (t == DUK__HASH_DELETED) {
				DUK_DDD(DUK_DDDPRINT("lookup miss (deleted) i=%ld, t=%ld",
				                     (long) i, (long) t));
			} else {
				DUK_ASSERT(t < DUK_HOBJECT_GET_ESIZE(obj));
				if (DUK_HOBJECT_E_GET_KEY(heap, obj, t) == key) {
					DUK_DDD(DUK_DDDPRINT("lookup hit i=%ld, t=%ld -> key %p",
					                     (long) i, (long) t, (void *) key));
					*e_idx = (duk_int_t) t;
					*h_idx = (duk_int_t) i;
					return 1;
				}
				DUK_DDD(DUK_DDDPRINT("lookup miss i=%ld, t=%ld",
				                     (long) i, (long) t));
			}
			i = (i + step) & mask;

			/* Guaranteed to finish (hash is larger than #props). */
		}
	}
#endif  /* DUK_USE_HOBJECT_HASH_PART */

	/* Not found, leave e_idx and h_idx unset. */
	return 0;
}

/* For internal use: get non-accessor entry value */
DUK_INTERNAL duk_tval *duk_hobject_find_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_hstring *key) {
	duk_int_t e_idx;
	duk_int_t h_idx;

	DUK_ASSERT(obj != NULL);
	DUK_ASSERT(key != NULL);
	DUK_UNREF(heap);

	if (duk_hobject_find_entry(heap, obj, key, &e_idx, &h_idx)) {
		DUK_ASSERT(e_idx >= 0);
		if (!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, obj, e_idx)) {
			return DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap, obj, e_idx);
		}
	}
	return NULL;
}

DUK_INTERNAL duk_tval *duk_hobject_find_entry_tval_ptr_stridx(duk_heap *heap, duk_hobject *obj, duk_small_uint_t stridx) {
	return duk_hobject_find_entry_tval_ptr(heap, obj, DUK_HEAP_GET_STRING(heap, stridx));
}

/* For internal use: get non-accessor entry value and attributes */
DUK_INTERNAL duk_tval *duk_hobject_find_entry_tval_ptr_and_attrs(duk_heap *heap, duk_hobject *obj, duk_hstring *key, duk_uint_t *out_attrs) {
	duk_int_t e_idx;
	duk_int_t h_idx;

	DUK_ASSERT(obj != NULL);
	DUK_ASSERT(key != NULL);
	DUK_ASSERT(out_attrs != NULL);
	DUK_UNREF(heap);

	if (duk_hobject_find_entry(heap, obj, key, &e_idx, &h_idx)) {
		DUK_ASSERT(e_idx >= 0);
		if (!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, obj, e_idx)) {
			*out_attrs = DUK_HOBJECT_E_GET_FLAGS(heap, obj, e_idx);
			return DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap, obj, e_idx);
		}
	}
	/* If not found, out_attrs is left unset. */
	return NULL;
}

/* For internal use: get array part value */
DUK_INTERNAL duk_tval *duk_hobject_find_array_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_uarridx_t i) {
	duk_tval *tv;

	DUK_ASSERT(obj != NULL);
	DUK_UNREF(heap);

	if (!DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
		return NULL;
	}
	if (i >= DUK_HOBJECT_GET_ASIZE(obj)) {
		return NULL;
	}
	tv = DUK_HOBJECT_A_GET_VALUE_PTR(heap, obj, i);
	return tv;
}

/*
 *  Allocate and initialize a new entry, resizing the properties allocation
 *  if necessary.  Returns entry index (e_idx) or throws an error if alloc fails.
 *
 *  Sets the key of the entry (increasing the key's refcount), and updates
 *  the hash part if it exists.  Caller must set value and flags, and update
 *  the entry value refcount.  A decref for the previous value is not necessary.
 */

DUK_LOCAL duk_int_t duk__hobject_alloc_entry_checked(duk_hthread *thr, duk_hobject *obj, duk_hstring *key) {
	duk_uint32_t idx;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(obj != NULL);
	DUK_ASSERT(key != NULL);
	DUK_ASSERT(DUK_HOBJECT_GET_ENEXT(obj) <= DUK_HOBJECT_GET_ESIZE(obj));

#if defined(DUK_USE_ASSERTIONS)
	/* key must not already exist in entry part */
	{
		duk_uint_fast32_t i;
		for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
			DUK_ASSERT(DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i) != key);
		}
	}
#endif

	if (DUK_HOBJECT_GET_ENEXT(obj) >= DUK_HOBJECT_GET_ESIZE(obj)) {
		/* only need to guarantee 1 more slot, but allocation growth is in chunks */
		DUK_DDD(DUK_DDDPRINT("entry part full, allocate space for one more entry"));
		duk__grow_props_for_new_entry_item(thr, obj);
	}
	DUK_ASSERT(DUK_HOBJECT_GET_ENEXT(obj) < DUK_HOBJECT_GET_ESIZE(obj));
	idx = DUK_HOBJECT_POSTINC_ENEXT(obj);

	/* previous value is assumed to be garbage, so don't touch it */
	DUK_HOBJECT_E_SET_KEY(thr->heap, obj, idx, key);
	DUK_HSTRING_INCREF(thr, key);

#if defined(DUK_USE_HOBJECT_HASH_PART)
	if (DUK_UNLIKELY(DUK_HOBJECT_GET_HSIZE(obj) > 0)) {
		duk_uint32_t n, mask;
		duk_uint32_t i, step;
		duk_uint32_t *h_base = DUK_HOBJECT_H_GET_BASE(thr->heap, obj);

		n = DUK_HOBJECT_GET_HSIZE(obj);
		mask = n - 1;
		i = DUK_HSTRING_GET_HASH(key) & mask;
		step = 1;  /* Cache friendly but clustering prone. */

		for (;;) {
			duk_uint32_t t = h_base[i];
			if (t == DUK__HASH_UNUSED || t == DUK__HASH_DELETED) {
				DUK_DDD(DUK_DDDPRINT("duk__hobject_alloc_entry_checked() inserted key into hash part, %ld -> %ld",
				                     (long) i, (long) idx));
				DUK_ASSERT_DISABLE(i >= 0);  /* unsigned */
				DUK_ASSERT(i < DUK_HOBJECT_GET_HSIZE(obj));
				DUK_ASSERT_DISABLE(idx >= 0);
				DUK_ASSERT(idx < DUK_HOBJECT_GET_ESIZE(obj));
				h_base[i] = idx;
				break;
			}
			DUK_DDD(DUK_DDDPRINT("duk__hobject_alloc_entry_checked() miss %ld", (long) i));
			i = (i + step) & mask;

			/* Guaranteed to finish (hash is larger than #props). */
		}
	}
#endif  /* DUK_USE_HOBJECT_HASH_PART */

	/* Note: we could return the hash index here too, but it's not
	 * needed right now.
	 */

	DUK_ASSERT_DISABLE(idx >= 0);
	DUK_ASSERT(idx < DUK_HOBJECT_GET_ESIZE(obj));
	DUK_ASSERT(idx < DUK_HOBJECT_GET_ENEXT(obj));
	return (duk_int_t) idx;
}

/*
 *  Object internal value
 *
 *  Returned value is guaranteed to be reachable / incref'd, caller does not need
 *  to incref OR decref.  No proxies or accessors are invoked, no prototype walk.
 */

DUK_INTERNAL duk_tval *duk_hobject_get_internal_value_tval_ptr(duk_heap *heap, duk_hobject *obj) {
	return duk_hobject_find_entry_tval_ptr_stridx(heap, obj, DUK_STRIDX_INT_VALUE);
}

DUK_LOCAL duk_heaphdr *duk_hobject_get_internal_value_heaphdr(duk_heap *heap, duk_hobject *obj) {
	duk_tval *tv;

	DUK_ASSERT(heap != NULL);
	DUK_ASSERT(obj != NULL);

	tv = duk_hobject_get_internal_value_tval_ptr(heap, obj);
	if (tv != NULL) {
		duk_heaphdr *h = DUK_TVAL_GET_HEAPHDR(tv);
		DUK_ASSERT(h != NULL);
		return h;
	}

	return NULL;
}

DUK_INTERNAL duk_hstring *duk_hobject_get_internal_value_string(duk_heap *heap, duk_hobject *obj) {
	duk_hstring *h;

	h = (duk_hstring *) duk_hobject_get_internal_value_heaphdr(heap, obj);
	if (h != NULL) {
		DUK_ASSERT(DUK_HEAPHDR_IS_STRING((duk_heaphdr *) h));
	}
	return h;
}

DUK_LOCAL duk_hobject *duk__hobject_get_entry_object_stridx(duk_heap *heap, duk_hobject *obj, duk_small_uint_t stridx) {
	duk_tval *tv;
	duk_hobject *h;

	tv = duk_hobject_find_entry_tval_ptr_stridx(heap, obj, stridx);
	if (tv != NULL && DUK_TVAL_IS_OBJECT(tv)) {
		h = DUK_TVAL_GET_OBJECT(tv);
		DUK_ASSERT(h != NULL);
		return h;
	}
	return NULL;
}

DUK_INTERNAL duk_harray *duk_hobject_get_formals(duk_hthread *thr, duk_hobject *obj) {
	duk_harray *h;

	h = (duk_harray *) duk__hobject_get_entry_object_stridx(thr->heap, obj, DUK_STRIDX_INT_FORMALS);
	if (h != NULL) {
		DUK_ASSERT(DUK_HOBJECT_IS_ARRAY((duk_hobject *) h));
		DUK_ASSERT(h->length <= DUK_HOBJECT_GET_ASIZE((duk_hobject *) h));
	}
	return h;
}

DUK_INTERNAL duk_hobject *duk_hobject_get_varmap(duk_hthread *thr, duk_hobject *obj) {
	duk_hobject *h;

	h = duk__hobject_get_entry_object_stridx(thr->heap, obj, DUK_STRIDX_INT_VARMAP);
	return h;
}

/*
 *  Arguments handling helpers (argument map mainly).
 *
 *  An arguments object has exotic behavior for some numeric indices.
 *  Accesses may translate to identifier operations which may have
 *  arbitrary side effects (potentially invalidating any duk_tval
 *  pointers).
 */

/* Lookup 'key' from arguments internal 'map', perform a variable lookup
 * if mapped, and leave the result on top of stack (and return non-zero).
 * Used in E5 Section 10.6 algorithms [[Get]] and [[GetOwnProperty]].
 */
DUK_LOCAL
duk_bool_t duk__lookup_arguments_map(duk_hthread *thr,
                                     duk_hobject *obj,
                                     duk_hstring *key,
                                     duk_propdesc *temp_desc,
                                     duk_hobject **out_map,
                                     duk_hobject **out_varenv) {
	duk_hobject *map;
	duk_hobject *varenv;
	duk_bool_t rc;

	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);

	DUK_DDD(DUK_DDDPRINT("arguments map lookup: thr=%p, obj=%p, key=%p, temp_desc=%p "
	                     "(obj -> %!O, key -> %!O)",
	                     (void *) thr, (void *) obj, (void *) key, (void *) temp_desc,
	                     (duk_heaphdr *) obj, (duk_heaphdr *) key));

	if (!duk_hobject_get_own_propdesc(thr, obj, DUK_HTHREAD_STRING_INT_MAP(thr), temp_desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
		DUK_DDD(DUK_DDDPRINT("-> no 'map'"));
		return 0;
	}

	map = duk_require_hobject(thr, -1);
	DUK_ASSERT(map != NULL);
	duk_pop_unsafe(thr);  /* map is reachable through obj */

	if (!duk_hobject_get_own_propdesc(thr, map, key, temp_desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
		DUK_DDD(DUK_DDDPRINT("-> 'map' exists, but key not in map"));
		return 0;
	}

	/* [... varname] */
	DUK_DDD(DUK_DDDPRINT("-> 'map' exists, and contains key, key is mapped to argument/variable binding %!T",
	                     (duk_tval *) duk_get_tval(thr, -1)));
	DUK_ASSERT(duk_is_string(thr, -1));  /* guaranteed when building arguments */

	/* get varenv for varname (callee's declarative lexical environment) */
	rc = duk_hobject_get_own_propdesc(thr, obj, DUK_HTHREAD_STRING_INT_VARENV(thr), temp_desc, DUK_GETDESC_FLAG_PUSH_VALUE);
	DUK_UNREF(rc);
	DUK_ASSERT(rc != 0);  /* arguments MUST have an initialized lexical environment reference */
	varenv = duk_require_hobject(thr, -1);
	DUK_ASSERT(varenv != NULL);
	duk_pop_unsafe(thr);  /* varenv remains reachable through 'obj' */

	DUK_DDD(DUK_DDDPRINT("arguments varenv is: %!dO", (duk_heaphdr *) varenv));

	/* success: leave varname in stack */
	*out_map = map;
	*out_varenv = varenv;
	return 1;  /* [... varname] */
}

/* Lookup 'key' from arguments internal 'map', and leave replacement value
 * on stack top if mapped (and return non-zero).
 * Used in E5 Section 10.6 algorithm for [[GetOwnProperty]] (used by [[Get]]).
 */
DUK_LOCAL duk_bool_t duk__check_arguments_map_for_get(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *temp_desc) {
	duk_hobject *map;
	duk_hobject *varenv;
	duk_hstring *varname;

	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);

	if (!duk__lookup_arguments_map(thr, obj, key, temp_desc, &map, &varenv)) {
		DUK_DDD(DUK_DDDPRINT("arguments: key not mapped, no exotic get behavior"));
		return 0;
	}

	/* [... varname] */

	varname = duk_require_hstring(thr, -1);
	DUK_ASSERT(varname != NULL);
	duk_pop_unsafe(thr);  /* varname is still reachable */

	DUK_DDD(DUK_DDDPRINT("arguments object automatic getvar for a bound variable; "
	                     "key=%!O, varname=%!O",
	                     (duk_heaphdr *) key,
	                     (duk_heaphdr *) varname));

	(void) duk_js_getvar_envrec(thr, varenv, varname, 1 /*throw*/);

	/* [... value this_binding] */

	duk_pop_unsafe(thr);

	/* leave result on stack top */
	return 1;
}

/* Lookup 'key' from arguments internal 'map', perform a variable write if mapped.
 * Used in E5 Section 10.6 algorithm for [[DefineOwnProperty]] (used by [[Put]]).
 * Assumes stack top contains 'put' value (which is NOT popped).
 */
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) {
	duk_hobject *map;
	duk_hobject *varenv;
	duk_hstring *varname;

	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);

	if (!duk__lookup_arguments_map(thr, obj, key, temp_desc, &map, &varenv)) {
		DUK_DDD(DUK_DDDPRINT("arguments: key not mapped, no exotic put behavior"));
		return;
	}

	/* [... put_value varname] */

	varname = duk_require_hstring(thr, -1);
	DUK_ASSERT(varname != NULL);
	duk_pop_unsafe(thr);  /* varname is still reachable */

	DUK_DDD(DUK_DDDPRINT("arguments object automatic putvar for a bound variable; "
	                     "key=%!O, varname=%!O, value=%!T",
	                     (duk_heaphdr *) key,
	                     (duk_heaphdr *) varname,
	                     (duk_tval *) duk_require_tval(thr, -1)));

	/* [... put_value] */

	/*
	 *  Note: although arguments object variable mappings are only established
	 *  for non-strict functions (and a call to a non-strict function created
	 *  the arguments object in question), an inner strict function may be doing
	 *  the actual property write.  Hence the throw_flag applied here comes from
	 *  the property write call.
	 */

	duk_js_putvar_envrec(thr, varenv, varname, duk_require_tval(thr, -1), throw_flag);

	/* [... put_value] */
}

/* Lookup 'key' from arguments internal 'map', delete mapping if found.
 * Used in E5 Section 10.6 algorithm for [[Delete]].  Note that the
 * variable/argument itself (where the map points) is not deleted.
 */
DUK_LOCAL void duk__check_arguments_map_for_delete(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *temp_desc) {
	duk_hobject *map;

	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);

	if (!duk_hobject_get_own_propdesc(thr, obj, DUK_HTHREAD_STRING_INT_MAP(thr), temp_desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
		DUK_DDD(DUK_DDDPRINT("arguments: key not mapped, no exotic delete behavior"));
		return;
	}

	map = duk_require_hobject(thr, -1);
	DUK_ASSERT(map != NULL);
	duk_pop_unsafe(thr);  /* map is reachable through obj */

	DUK_DDD(DUK_DDDPRINT("-> have 'map', delete key %!O from map (if exists)); ignore result",
	                     (duk_heaphdr *) key));

	/* Note: no recursion issue, we can trust 'map' to behave */
	DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_BEHAVIOR(map));
	DUK_DDD(DUK_DDDPRINT("map before deletion: %!O", (duk_heaphdr *) map));
	(void) duk_hobject_delprop_raw(thr, map, key, 0);  /* ignore result */
	DUK_DDD(DUK_DDDPRINT("map after deletion: %!O", (duk_heaphdr *) map));
}

/*
 *  ECMAScript compliant [[GetOwnProperty]](P), for internal use only.
 *
 *  If property is found:
 *    - Fills descriptor fields to 'out_desc'
 *    - If DUK_GETDESC_FLAG_PUSH_VALUE is set, pushes a value related to the
 *      property onto the stack ('undefined' for accessor properties).
 *    - Returns non-zero
 *
 *  If property is not found:
 *    - 'out_desc' is left in untouched state (possibly garbage)
 *    - Nothing is pushed onto the stack (not even with DUK_GETDESC_FLAG_PUSH_VALUE
 *      set)
 *    - Returns zero
 *
 *  Notes:
 *
 *    - Getting a property descriptor may cause an allocation (and hence
 *      GC) to take place, hence reachability and refcount of all related
 *      values matter.  Reallocation of value stack, properties, etc may
 *      invalidate many duk_tval pointers (concretely, those which reside
 *      in memory areas subject to reallocation).  However, heap object
 *      pointers are never affected (heap objects have stable pointers).
 *
 *    - The value of a plain property is always reachable and has a non-zero
 *      reference count.
 *
 *    - The value of a virtual property is not necessarily reachable from
 *      elsewhere and may have a refcount of zero.  Hence we push it onto
 *      the valstack for the caller, which ensures it remains reachable
 *      while it is needed.
 *
 *    - There are no virtual accessor properties.  Hence, all getters and
 *      setters are always related to concretely stored properties, which
 *      ensures that the get/set functions in the resulting descriptor are
 *      reachable and have non-zero refcounts.  Should there be virtual
 *      accessor properties later, this would need to change.
 */

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) {
	duk_tval *tv;

	DUK_DDD(DUK_DDDPRINT("duk_hobject_get_own_propdesc: thr=%p, obj=%p, key=%p, out_desc=%p, flags=%lx, "
	                     "arr_idx=%ld (obj -> %!O, key -> %!O)",
	                     (void *) thr, (void *) obj, (void *) key, (void *) out_desc,
	                     (long) flags, (long) arr_idx,
	                     (duk_heaphdr *) obj, (duk_heaphdr *) key));

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(thr->heap != NULL);
	DUK_ASSERT(obj != NULL);
	DUK_ASSERT(key != NULL);
	DUK_ASSERT(out_desc != NULL);
	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);

	DUK_STATS_INC(thr->heap, stats_getownpropdesc_count);

	/* Each code path returning 1 (= found) must fill in all the output
	 * descriptor fields.  We don't do it beforehand because it'd be
	 * unnecessary work if the property isn't found and would happen
	 * multiple times for an inheritance chain.
	 */
	DUK_ASSERT_SET_GARBAGE(out_desc, sizeof(*out_desc));
#if 0
	out_desc->flags = 0;
	out_desc->get = NULL;
	out_desc->set = NULL;
	out_desc->e_idx = -1;
	out_desc->h_idx = -1;
	out_desc->a_idx = -1;
#endif

	/*
	 *  Try entries part first because it's the common case.
	 *
	 *  Array part lookups are usually handled by the array fast path, and
	 *  are not usually inherited.  Array and entry parts never contain the
	 *  same keys so the entry part vs. array part order doesn't matter.
	 */

	if (duk_hobject_find_entry(thr->heap, obj, key, &out_desc->e_idx, &out_desc->h_idx)) {
		duk_int_t e_idx = out_desc->e_idx;
		DUK_ASSERT(out_desc->e_idx >= 0);
		out_desc->a_idx = -1;
		out_desc->flags = DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, e_idx);
		out_desc->get = NULL;
		out_desc->set = NULL;
		if (DUK_UNLIKELY(out_desc->flags & DUK_PROPDESC_FLAG_ACCESSOR)) {
			DUK_DDD(DUK_DDDPRINT("-> found accessor property in entry part"));
			out_desc->get = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, obj, e_idx);
			out_desc->set = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, obj, e_idx);
			if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
				/* a dummy undefined value is pushed to make valstack
				 * behavior uniform for caller
				 */
				duk_push_undefined(thr);
			}
		} else {
			DUK_DDD(DUK_DDDPRINT("-> found plain property in entry part"));
			tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, e_idx);
			if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
				duk_push_tval(thr, tv);
			}
		}
		goto prop_found;
	}

	/*
	 *  Try array part.
	 */

	if (DUK_HOBJECT_HAS_ARRAY_PART(obj) && arr_idx != DUK__NO_ARRAY_INDEX) {
		if (arr_idx < DUK_HOBJECT_GET_ASIZE(obj)) {
			tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, arr_idx);
			if (!DUK_TVAL_IS_UNUSED(tv)) {
				DUK_DDD(DUK_DDDPRINT("-> found in array part"));
				if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
					duk_push_tval(thr, tv);
				}
				/* implicit attributes */
				out_desc->flags = DUK_PROPDESC_FLAG_WRITABLE |
				                  DUK_PROPDESC_FLAG_CONFIGURABLE |
				                  DUK_PROPDESC_FLAG_ENUMERABLE;
				out_desc->get = NULL;
				out_desc->set = NULL;
				out_desc->e_idx = -1;
				out_desc->h_idx = -1;
				out_desc->a_idx = (duk_int_t) arr_idx;  /* XXX: limit 2G due to being signed */
				goto prop_found;
			}
		}
	}

	DUK_DDD(DUK_DDDPRINT("-> not found as a concrete property"));

	/*
	 *  Not found as a concrete property, check for virtual properties.
	 */

	if (!DUK_HOBJECT_HAS_VIRTUAL_PROPERTIES(obj)) {
		/* Quick skip. */
		goto prop_not_found;
	}

	if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {
		duk_harray *a;

		DUK_DDD(DUK_DDDPRINT("array object exotic property get for key: %!O, arr_idx: %ld",
		                     (duk_heaphdr *) key, (long) arr_idx));

		a = (duk_harray *) obj;
		DUK_HARRAY_ASSERT_VALID(a);

		if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
			DUK_DDD(DUK_DDDPRINT("-> found, key is 'length', length exotic behavior"));

			if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
				duk_push_uint(thr, (duk_uint_t) a->length);
			}
			out_desc->flags = DUK_PROPDESC_FLAG_VIRTUAL;
			if (DUK_HARRAY_LENGTH_WRITABLE(a)) {
				out_desc->flags |= DUK_PROPDESC_FLAG_WRITABLE;
			}
			out_desc->get = NULL;
			out_desc->set = NULL;
			out_desc->e_idx = -1;
			out_desc->h_idx = -1;
			out_desc->a_idx = -1;

			DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj));
			goto prop_found_noexotic;  /* cannot be arguments exotic */
		}
	} else if (DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(obj)) {
		DUK_DDD(DUK_DDDPRINT("string object exotic property get for key: %!O, arr_idx: %ld",
		                     (duk_heaphdr *) key, (long) arr_idx));

		/* XXX: charlen; avoid multiple lookups? */

		if (arr_idx != DUK__NO_ARRAY_INDEX) {
			duk_hstring *h_val;

			DUK_DDD(DUK_DDDPRINT("array index exists"));

			h_val = duk_hobject_get_internal_value_string(thr->heap, obj);
			DUK_ASSERT(h_val);
			if (arr_idx < DUK_HSTRING_GET_CHARLEN(h_val)) {
				DUK_DDD(DUK_DDDPRINT("-> found, array index inside string"));
				if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
					duk_push_hstring(thr, h_val);
					duk_substring(thr, -1, arr_idx, arr_idx + 1);  /* [str] -> [substr] */
				}
				out_desc->flags = DUK_PROPDESC_FLAG_ENUMERABLE |  /* E5 Section 15.5.5.2 */
				                  DUK_PROPDESC_FLAG_VIRTUAL;
				out_desc->get = NULL;
				out_desc->set = NULL;
				out_desc->e_idx = -1;
				out_desc->h_idx = -1;
				out_desc->a_idx = -1;

				DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj));
				goto prop_found_noexotic;  /* cannot be arguments exotic */
			} else {
				/* index is above internal string length -> property is fully normal */
				DUK_DDD(DUK_DDDPRINT("array index outside string -> normal property"));
			}
		} else if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
			duk_hstring *h_val;

			DUK_DDD(DUK_DDDPRINT("-> found, key is 'length', length exotic behavior"));

			h_val = duk_hobject_get_internal_value_string(thr->heap, obj);
			DUK_ASSERT(h_val != NULL);
			if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
				duk_push_uint(thr, (duk_uint_t) DUK_HSTRING_GET_CHARLEN(h_val));
			}
			out_desc->flags = DUK_PROPDESC_FLAG_VIRTUAL;  /* E5 Section 15.5.5.1 */
			out_desc->get = NULL;
			out_desc->set = NULL;
			out_desc->e_idx = -1;
			out_desc->h_idx = -1;
			out_desc->a_idx = -1;

			DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj));
			goto prop_found_noexotic;  /* cannot be arguments exotic */
		}
	}
#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
	else if (DUK_HOBJECT_IS_BUFOBJ(obj)) {
		duk_hbufobj *h_bufobj;
		duk_uint_t byte_off;
		duk_small_uint_t elem_size;

		h_bufobj = (duk_hbufobj *) obj;
		DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);
		DUK_DDD(DUK_DDDPRINT("bufobj property get for key: %!O, arr_idx: %ld",
		                     (duk_heaphdr *) key, (long) arr_idx));

		if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h_bufobj)) {
			DUK_DDD(DUK_DDDPRINT("array index exists"));

			/* Careful with wrapping: arr_idx upshift may easily wrap, whereas
			 * length downshift won't.
			 */
			if (arr_idx < (h_bufobj->length >> h_bufobj->shift)) {
				byte_off = arr_idx << h_bufobj->shift;  /* no wrap assuming h_bufobj->length is valid */
				elem_size = (duk_small_uint_t) (1U << h_bufobj->shift);
				if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
					duk_uint8_t *data;

					if (h_bufobj->buf != NULL && DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) {
						data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) + h_bufobj->offset + byte_off;
						duk_hbufobj_push_validated_read(thr, h_bufobj, data, elem_size);
					} else {
						DUK_D(DUK_DPRINT("bufobj access out of underlying buffer, ignoring (read zero)"));
						duk_push_uint(thr, 0);
					}
				}
				out_desc->flags = DUK_PROPDESC_FLAG_WRITABLE |
				                  DUK_PROPDESC_FLAG_VIRTUAL;
				if (DUK_HOBJECT_GET_CLASS_NUMBER(obj) != DUK_HOBJECT_CLASS_ARRAYBUFFER) {
					/* ArrayBuffer indices are non-standard and are
					 * non-enumerable to avoid their serialization.
					 */
					out_desc->flags |= DUK_PROPDESC_FLAG_ENUMERABLE;
				}
				out_desc->get = NULL;
				out_desc->set = NULL;
				out_desc->e_idx = -1;
				out_desc->h_idx = -1;
				out_desc->a_idx = -1;

				DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj));
				goto prop_found_noexotic;  /* cannot be e.g. arguments exotic, since exotic 'traits' are mutually exclusive */
			} else {
				/* index is above internal buffer length -> property is fully normal */
				DUK_DDD(DUK_DDDPRINT("array index outside buffer -> normal property"));
			}
		} else if (key == DUK_HTHREAD_STRING_LENGTH(thr) && DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h_bufobj)) {
			DUK_DDD(DUK_DDDPRINT("-> found, key is 'length', length exotic behavior"));

			if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
				/* Length in elements: take into account shift, but
				 * intentionally don't check the underlying buffer here.
				 */
				duk_push_uint(thr, h_bufobj->length >> h_bufobj->shift);
			}
			out_desc->flags = DUK_PROPDESC_FLAG_VIRTUAL;
			out_desc->get = NULL;
			out_desc->set = NULL;
			out_desc->e_idx = -1;
			out_desc->h_idx = -1;
			out_desc->a_idx = -1;

			DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj));
			goto prop_found_noexotic;  /* cannot be arguments exotic */
		}
	}
#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */

	/* Array properties have exotic behavior but they are concrete,
	 * so no special handling here.
	 *
	 * Arguments exotic behavior (E5 Section 10.6, [[GetOwnProperty]]
	 * is only relevant as a post-check implemented below; hence no
	 * check here.
	 */

	/*
	 *  Not found as concrete or virtual.
	 */

 prop_not_found:
	DUK_DDD(DUK_DDDPRINT("-> not found (virtual, entry part, or array part)"));
	DUK_STATS_INC(thr->heap, stats_getownpropdesc_miss);
	return 0;

	/*
	 *  Found.
	 *
	 *  Arguments object has exotic post-processing, see E5 Section 10.6,
	 *  description of [[GetOwnProperty]] variant for arguments.
	 */

 prop_found:
	DUK_DDD(DUK_DDDPRINT("-> property found, checking for arguments exotic post-behavior"));

	/* Notes:
	 *  - Only numbered indices are relevant, so arr_idx fast reject is good
	 *    (this is valid unless there are more than 4**32-1 arguments).
	 *  - Since variable lookup has no side effects, this can be skipped if
	 *    DUK_GETDESC_FLAG_PUSH_VALUE is not set.
	 */

	if (DUK_UNLIKELY(DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj) &&
	                 arr_idx != DUK__NO_ARRAY_INDEX &&
	                 (flags & DUK_GETDESC_FLAG_PUSH_VALUE))) {
		duk_propdesc temp_desc;

		/* Magically bound variable cannot be an accessor.  However,
		 * there may be an accessor property (or a plain property) in
		 * place with magic behavior removed.  This happens e.g. when
		 * a magic property is redefined with defineProperty().
		 * Cannot assert for "not accessor" here.
		 */

		/* replaces top of stack with new value if necessary */
		DUK_ASSERT((flags & DUK_GETDESC_FLAG_PUSH_VALUE) != 0);

		/* This can perform a variable lookup but only into a declarative
		 * environment which has no side effects.
		 */
		if (duk__check_arguments_map_for_get(thr, obj, key, &temp_desc)) {
			DUK_DDD(DUK_DDDPRINT("-> arguments exotic behavior overrides result: %!T -> %!T",
			                     (duk_tval *) duk_get_tval(thr, -2),
			                     (duk_tval *) duk_get_tval(thr, -1)));
			/* [... old_result result] -> [... result] */
			duk_remove_m2(thr);
		}
	}

 prop_found_noexotic:
	DUK_STATS_INC(thr->heap, stats_getownpropdesc_hit);
	return 1;
}

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) {
	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(obj != NULL);
	DUK_ASSERT(key != NULL);
	DUK_ASSERT(out_desc != NULL);
	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);

	return duk__get_own_propdesc_raw(thr, obj, key, DUK_HSTRING_GET_ARRIDX_SLOW(key), out_desc, flags);
}

/*
 *  ECMAScript compliant [[GetProperty]](P), for internal use only.
 *
 *  If property is found:
 *    - Fills descriptor fields to 'out_desc'
 *    - If DUK_GETDESC_FLAG_PUSH_VALUE is set, pushes a value related to the
 *      property onto the stack ('undefined' for accessor properties).
 *    - Returns non-zero
 *
 *  If property is not found:
 *    - 'out_desc' is left in untouched state (possibly garbage)
 *    - Nothing is pushed onto the stack (not even with DUK_GETDESC_FLAG_PUSH_VALUE
 *      set)
 *    - Returns zero
 *
 *  May cause arbitrary side effects and invalidate (most) duk_tval
 *  pointers.
 */

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) {
	duk_hobject *curr;
	duk_uint32_t arr_idx;
	duk_uint_t sanity;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(thr->heap != NULL);
	DUK_ASSERT(obj != NULL);
	DUK_ASSERT(key != NULL);
	DUK_ASSERT(out_desc != NULL);
	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);

	DUK_STATS_INC(thr->heap, stats_getpropdesc_count);

	arr_idx = DUK_HSTRING_GET_ARRIDX_FAST(key);

	DUK_DDD(DUK_DDDPRINT("duk__get_propdesc: thr=%p, obj=%p, key=%p, out_desc=%p, flags=%lx, "
	                     "arr_idx=%ld (obj -> %!O, key -> %!O)",
	                     (void *) thr, (void *) obj, (void *) key, (void *) out_desc,
	                     (long) flags, (long) arr_idx,
	                     (duk_heaphdr *) obj, (duk_heaphdr *) key));

	curr = obj;
	DUK_ASSERT(curr != NULL);
	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
	do {
		if (duk__get_own_propdesc_raw(thr, curr, key, arr_idx, out_desc, flags)) {
			/* stack contains value (if requested), 'out_desc' is set */
			DUK_STATS_INC(thr->heap, stats_getpropdesc_hit);
			return 1;
		}

		/* not found in 'curr', next in prototype chain; impose max depth */
		if (DUK_UNLIKELY(sanity-- == 0)) {
			if (flags & DUK_GETDESC_FLAG_IGNORE_PROTOLOOP) {
				/* treat like property not found */
				break;
			} else {
				DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
				DUK_WO_NORETURN(return 0;);
			}
		}
		curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr);
	} while (curr != NULL);

	/* out_desc is left untouched (possibly garbage), caller must use return
	 * value to determine whether out_desc can be looked up
	 */

	DUK_STATS_INC(thr->heap, stats_getpropdesc_miss);
	return 0;
}

/*
 *  Shallow fast path checks for accessing array elements with numeric
 *  indices.  The goal is to try to avoid coercing an array index to an
 *  (interned) string for the most common lookups, in particular, for
 *  standard Array objects.
 *
 *  Interning is avoided but only for a very narrow set of cases:
 *    - Object has array part, index is within array allocation, and
 *      value is not unused (= key exists)
 *    - Object has no interfering exotic behavior (e.g. arguments or
 *      string object exotic behaviors interfere, array exotic
 *      behavior does not).
 *
 *  Current shortcoming: if key does not exist (even if it is within
 *  the array allocation range) a slow path lookup with interning is
 *  always required.  This can probably be fixed so that there is a
 *  quick fast path for non-existent elements as well, at least for
 *  standard Array objects.
 */

#if defined(DUK_USE_ARRAY_PROP_FASTPATH)
DUK_LOCAL duk_tval *duk__getprop_shallow_fastpath_array_tval(duk_hthread *thr, duk_hobject *obj, duk_tval *tv_key) {
	duk_tval *tv;
	duk_uint32_t idx;

	DUK_UNREF(thr);

	if (!(DUK_HOBJECT_HAS_ARRAY_PART(obj) &&
	     !DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj) &&
	     !DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(obj) &&
	     !DUK_HOBJECT_IS_BUFOBJ(obj) &&
	     !DUK_HOBJECT_IS_PROXY(obj))) {
		/* Must have array part and no conflicting exotic behaviors.
		 * Doesn't need to have array special behavior, e.g. Arguments
		 * object has array part.
		 */
		return NULL;
	}

	/* Arrays never have other exotic behaviors. */

	DUK_DDD(DUK_DDDPRINT("fast path attempt (no exotic string/arguments/buffer "
	                     "behavior, object has array part)"));

#if defined(DUK_USE_FASTINT)
	if (DUK_TVAL_IS_FASTINT(tv_key)) {
		idx = duk__tval_fastint_to_arr_idx(tv_key);
	} else
#endif
	if (DUK_TVAL_IS_DOUBLE(tv_key)) {
		idx = duk__tval_number_to_arr_idx(tv_key);
	} else {
		DUK_DDD(DUK_DDDPRINT("key is not a number"));
		return NULL;
	}

	/* If index is not valid, idx will be DUK__NO_ARRAY_INDEX which
	 * is 0xffffffffUL.  We don't need to check for that explicitly
	 * because 0xffffffffUL will never be inside object 'a_size'.
	 */

	if (idx >= DUK_HOBJECT_GET_ASIZE(obj)) {
		DUK_DDD(DUK_DDDPRINT("key is not an array index or outside array part"));
		return NULL;
	}
	DUK_ASSERT(idx != 0xffffffffUL);
	DUK_ASSERT(idx != DUK__NO_ARRAY_INDEX);

	/* XXX: for array instances we could take a shortcut here and assume
	 * Array.prototype doesn't contain an array index property.
	 */

	DUK_DDD(DUK_DDDPRINT("key is a valid array index and inside array part"));
	tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, idx);
	if (!DUK_TVAL_IS_UNUSED(tv)) {
		DUK_DDD(DUK_DDDPRINT("-> fast path successful"));
		return tv;
	}

	DUK_DDD(DUK_DDDPRINT("fast path attempt failed, fall back to slow path"));
	return NULL;
}

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_tval *tv;
	duk_harray *a;
	duk_uint32_t idx;
	duk_uint32_t old_len, new_len;

	if (!(DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj) &&
	      DUK_HOBJECT_HAS_ARRAY_PART(obj) &&
	      DUK_HOBJECT_HAS_EXTENSIBLE(obj))) {
		return 0;
	}
	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));  /* caller ensures */

	a = (duk_harray *) obj;
	DUK_HARRAY_ASSERT_VALID(a);

#if defined(DUK_USE_FASTINT)
	if (DUK_TVAL_IS_FASTINT(tv_key)) {
		idx = duk__tval_fastint_to_arr_idx(tv_key);
	} else
#endif
	if (DUK_TVAL_IS_DOUBLE(tv_key)) {
		idx = duk__tval_number_to_arr_idx(tv_key);
	} else {
		DUK_DDD(DUK_DDDPRINT("key is not a number"));
		return 0;
	}

	/* If index is not valid, idx will be DUK__NO_ARRAY_INDEX which
	 * is 0xffffffffUL.  We don't need to check for that explicitly
	 * because 0xffffffffUL will never be inside object 'a_size'.
	 */

	if (idx >= DUK_HOBJECT_GET_ASIZE(obj)) {  /* for resizing of array part, use slow path */
		return 0;
	}
	DUK_ASSERT(idx != 0xffffffffUL);
	DUK_ASSERT(idx != DUK__NO_ARRAY_INDEX);

	old_len = a->length;

	if (idx >= old_len) {
		DUK_DDD(DUK_DDDPRINT("write new array entry requires length update "
		                     "(arr_idx=%ld, old_len=%ld)",
		                     (long) idx, (long) old_len));
		if (DUK_HARRAY_LENGTH_NONWRITABLE(a)) {
			/* The correct behavior here is either a silent error
			 * or a TypeError, depending on strictness.  Fall back
			 * to the slow path to handle the situation.
			 */
			return 0;
		}
		new_len = idx + 1;

		((duk_harray *) obj)->length = new_len;
	}

	tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, idx);
	DUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv_val);  /* side effects */

	DUK_DDD(DUK_DDDPRINT("array fast path success for index %ld", (long) idx));
	return 1;
}
#endif  /* DUK_USE_ARRAY_PROP_FASTPATH */

/*
 *  Fast path for bufobj getprop/putprop
 */

#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
DUK_LOCAL duk_bool_t duk__getprop_fastpath_bufobj_tval(duk_hthread *thr, duk_hobject *obj, duk_tval *tv_key) {
	duk_uint32_t idx;
	duk_hbufobj *h_bufobj;
	duk_uint_t byte_off;
	duk_small_uint_t elem_size;
	duk_uint8_t *data;

	if (!DUK_HOBJECT_IS_BUFOBJ(obj)) {
		return 0;
	}
	h_bufobj = (duk_hbufobj *) obj;
	if (!DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h_bufobj)) {
		return 0;
	}

#if defined(DUK_USE_FASTINT)
	if (DUK_TVAL_IS_FASTINT(tv_key)) {
		idx = duk__tval_fastint_to_arr_idx(tv_key);
	} else
#endif
	if (DUK_TVAL_IS_DOUBLE(tv_key)) {
		idx = duk__tval_number_to_arr_idx(tv_key);
	} else {
		return 0;
	}

	/* If index is not valid, idx will be DUK__NO_ARRAY_INDEX which
	 * is 0xffffffffUL.  We don't need to check for that explicitly
	 * because 0xffffffffUL will never be inside bufobj length.
	 */

	/* Careful with wrapping (left shifting idx would be unsafe). */
	if (idx >= (h_bufobj->length >> h_bufobj->shift)) {
		return 0;
	}
	DUK_ASSERT(idx != DUK__NO_ARRAY_INDEX);

	byte_off = idx << h_bufobj->shift;  /* no wrap assuming h_bufobj->length is valid */
	elem_size = (duk_small_uint_t) (1U << h_bufobj->shift);

	if (h_bufobj->buf != NULL && DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) {
		data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) + h_bufobj->offset + byte_off;
		duk_hbufobj_push_validated_read(thr, h_bufobj, data, elem_size);
	} else {
		DUK_D(DUK_DPRINT("bufobj access out of underlying buffer, ignoring (read zero)"));
		duk_push_uint(thr, 0);
	}

	return 1;
}
#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */

#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
DUK_LOCAL duk_bool_t duk__putprop_fastpath_bufobj_tval(duk_hthread *thr, duk_hobject *obj, duk_tval *tv_key, duk_tval *tv_val) {
	duk_uint32_t idx;
	duk_hbufobj *h_bufobj;
	duk_uint_t byte_off;
	duk_small_uint_t elem_size;
	duk_uint8_t *data;

	if (!(DUK_HOBJECT_IS_BUFOBJ(obj) &&
	      DUK_TVAL_IS_NUMBER(tv_val))) {
		return 0;
	}
	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));  /* caller ensures; rom objects are never bufobjs now */

	h_bufobj = (duk_hbufobj *) obj;
	if (!DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h_bufobj)) {
		return 0;
	}

#if defined(DUK_USE_FASTINT)
	if (DUK_TVAL_IS_FASTINT(tv_key)) {
		idx = duk__tval_fastint_to_arr_idx(tv_key);
	} else
#endif
	if (DUK_TVAL_IS_DOUBLE(tv_key)) {
		idx = duk__tval_number_to_arr_idx(tv_key);
	} else {
		return 0;
	}

	/* If index is not valid, idx will be DUK__NO_ARRAY_INDEX which
	 * is 0xffffffffUL.  We don't need to check for that explicitly
	 * because 0xffffffffUL will never be inside bufobj length.
	 */

	/* Careful with wrapping (left shifting idx would be unsafe). */
	if (idx >= (h_bufobj->length >> h_bufobj->shift)) {
		return 0;
	}
	DUK_ASSERT(idx != DUK__NO_ARRAY_INDEX);

	byte_off = idx << h_bufobj->shift;  /* no wrap assuming h_bufobj->length is valid */
	elem_size = (duk_small_uint_t) (1U << h_bufobj->shift);

	/* Value is required to be a number in the fast path so there
	 * are no side effects in write coercion.
	 */
	duk_push_tval(thr, tv_val);
	DUK_ASSERT(duk_is_number(thr, -1));

	if (h_bufobj->buf != NULL && DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) {
		data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) + h_bufobj->offset + byte_off;
		duk_hbufobj_validated_write(thr, h_bufobj, data, elem_size);
	} else {
		DUK_D(DUK_DPRINT("bufobj access out of underlying buffer, ignoring (write skipped)"));
	}

	duk_pop_unsafe(thr);
	return 1;
}
#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */

/*
 *  GETPROP: ECMAScript property read.
 */

DUK_INTERNAL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key) {
	duk_tval tv_obj_copy;
	duk_tval tv_key_copy;
	duk_hobject *curr = NULL;
	duk_hstring *key = NULL;
	duk_uint32_t arr_idx = DUK__NO_ARRAY_INDEX;
	duk_propdesc desc;
	duk_uint_t sanity;

	DUK_DDD(DUK_DDDPRINT("getprop: thr=%p, obj=%p, key=%p (obj -> %!T, key -> %!T)",
	                     (void *) thr, (void *) tv_obj, (void *) tv_key,
	                     (duk_tval *) tv_obj, (duk_tval *) tv_key));

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(thr->heap != NULL);
	DUK_ASSERT(tv_obj != NULL);
	DUK_ASSERT(tv_key != NULL);

	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);

	DUK_STATS_INC(thr->heap, stats_getprop_all);

	/*
	 *  Make a copy of tv_obj, tv_key, and tv_val to avoid any issues of
	 *  them being invalidated by a valstack resize.
	 *
	 *  XXX: this is now an overkill for many fast paths.  Rework this
	 *  to be faster (although switching to a valstack discipline might
	 *  be a better solution overall).
	 */

	DUK_TVAL_SET_TVAL(&tv_obj_copy, tv_obj);
	DUK_TVAL_SET_TVAL(&tv_key_copy, tv_key);
	tv_obj = &tv_obj_copy;
	tv_key = &tv_key_copy;

	/*
	 *  Coercion and fast path processing
	 */

	switch (DUK_TVAL_GET_TAG(tv_obj)) {
	case DUK_TAG_UNDEFINED:
	case DUK_TAG_NULL: {
		/* Note: unconditional throw */
		DUK_DDD(DUK_DDDPRINT("base object is undefined or null -> reject"));
#if defined(DUK_USE_PARANOID_ERRORS)
		DUK_ERROR_TYPE(thr, DUK_STR_INVALID_BASE);
#else
		DUK_ERROR_FMT2(thr, DUK_ERR_TYPE_ERROR, "cannot read property %s of %s",
		               duk_push_string_tval_readable(thr, tv_key), duk_push_string_tval_readable(thr, tv_obj));
#endif
		DUK_WO_NORETURN(return 0;);
		break;
	}

	case DUK_TAG_BOOLEAN: {
		DUK_DDD(DUK_DDDPRINT("base object is a boolean, start lookup from boolean prototype"));
		curr = thr->builtins[DUK_BIDX_BOOLEAN_PROTOTYPE];
		break;
	}

	case DUK_TAG_STRING: {
		duk_hstring *h = DUK_TVAL_GET_STRING(tv_obj);
		duk_int_t pop_count;

		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
			/* Symbols (ES2015 or hidden) don't have virtual properties. */
			DUK_DDD(DUK_DDDPRINT("base object is a symbol, start lookup from symbol prototype"));
			curr = thr->builtins[DUK_BIDX_SYMBOL_PROTOTYPE];
			break;
		}

#if defined(DUK_USE_FASTINT)
		if (DUK_TVAL_IS_FASTINT(tv_key)) {
			arr_idx = duk__tval_fastint_to_arr_idx(tv_key);
			DUK_DDD(DUK_DDDPRINT("base object string, key is a fast-path fastint; arr_idx %ld", (long) arr_idx));
			pop_count = 0;
		} else
#endif
		if (DUK_TVAL_IS_NUMBER(tv_key)) {
			arr_idx = duk__tval_number_to_arr_idx(tv_key);
			DUK_DDD(DUK_DDDPRINT("base object string, key is a fast-path number; arr_idx %ld", (long) arr_idx));
			pop_count = 0;
		} else {
			arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
			DUK_ASSERT(key != NULL);
			DUK_DDD(DUK_DDDPRINT("base object string, key is a non-fast-path number; after "
			                     "coercion key is %!T, arr_idx %ld",
			                     (duk_tval *) duk_get_tval(thr, -1), (long) arr_idx));
			pop_count = 1;
		}

		if (arr_idx != DUK__NO_ARRAY_INDEX &&
		    arr_idx < DUK_HSTRING_GET_CHARLEN(h)) {
			duk_pop_n_unsafe(thr, pop_count);
			duk_push_hstring(thr, h);
			duk_substring(thr, -1, arr_idx, arr_idx + 1);  /* [str] -> [substr] */

			DUK_STATS_INC(thr->heap, stats_getprop_stringidx);
			DUK_DDD(DUK_DDDPRINT("-> %!T (base is string, key is an index inside string length "
			                     "after coercion -> return char)",
			                     (duk_tval *) duk_get_tval(thr, -1)));
			return 1;
		}

		if (pop_count == 0) {
			/* This is a pretty awkward control flow, but we need to recheck the
			 * key coercion here.
			 */
			arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
			DUK_ASSERT(key != NULL);
			DUK_DDD(DUK_DDDPRINT("base object string, key is a non-fast-path number; after "
			                     "coercion key is %!T, arr_idx %ld",
			                     (duk_tval *) duk_get_tval(thr, -1), (long) arr_idx));
		}

		if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
			duk_pop_unsafe(thr);  /* [key] -> [] */
			duk_push_uint(thr, (duk_uint_t) DUK_HSTRING_GET_CHARLEN(h));  /* [] -> [res] */

			DUK_STATS_INC(thr->heap, stats_getprop_stringlen);
			DUK_DDD(DUK_DDDPRINT("-> %!T (base is string, key is 'length' after coercion -> "
			                     "return string length)",
			                     (duk_tval *) duk_get_tval(thr, -1)));
			return 1;
		}

		DUK_DDD(DUK_DDDPRINT("base object is a string, start lookup from string prototype"));
		curr = thr->builtins[DUK_BIDX_STRING_PROTOTYPE];
		goto lookup;  /* avoid double coercion */
	}

	case DUK_TAG_OBJECT: {
#if defined(DUK_USE_ARRAY_PROP_FASTPATH)
		duk_tval *tmp;
#endif

		curr = DUK_TVAL_GET_OBJECT(tv_obj);
		DUK_ASSERT(curr != NULL);

		/* XXX: array .length fast path (important in e.g. loops)? */

#if defined(DUK_USE_ARRAY_PROP_FASTPATH)
		tmp = duk__getprop_shallow_fastpath_array_tval(thr, curr, tv_key);
		if (tmp) {
			duk_push_tval(thr, tmp);

			DUK_DDD(DUK_DDDPRINT("-> %!T (base is object, key is a number, array part "
			                     "fast path)",
			                     (duk_tval *) duk_get_tval(thr, -1)));
			DUK_STATS_INC(thr->heap, stats_getprop_arrayidx);
			return 1;
		}
#endif

#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
		if (duk__getprop_fastpath_bufobj_tval(thr, curr, tv_key) != 0) {
			/* Read value pushed on stack. */
			DUK_DDD(DUK_DDDPRINT("-> %!T (base is bufobj, key is a number, bufobj "
			                     "fast path)",
			                     (duk_tval *) duk_get_tval(thr, -1)));
			DUK_STATS_INC(thr->heap, stats_getprop_bufobjidx);
			return 1;
		}
#endif

#if defined(DUK_USE_ES6_PROXY)
		if (DUK_UNLIKELY(DUK_HOBJECT_IS_PROXY(curr))) {
			duk_hobject *h_target;

			if (duk__proxy_check_prop(thr, curr, DUK_STRIDX_GET, tv_key, &h_target)) {
				/* -> [ ... trap handler ] */
				DUK_DDD(DUK_DDDPRINT("-> proxy object 'get' for key %!T", (duk_tval *) tv_key));
				DUK_STATS_INC(thr->heap, stats_getprop_proxy);
				duk_push_hobject(thr, h_target);  /* target */
				duk_push_tval(thr, tv_key);       /* P */
				duk_push_tval(thr, tv_obj);       /* Receiver: Proxy object */
				duk_call_method(thr, 3 /*nargs*/);

				/* Target object must be checked for a conflicting
				 * non-configurable property.
				 */
				arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
				DUK_ASSERT(key != NULL);

				if (duk__get_own_propdesc_raw(thr, h_target, key, arr_idx, &desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
					duk_tval *tv_hook = duk_require_tval(thr, -3);  /* value from hook */
					duk_tval *tv_targ = duk_require_tval(thr, -1);  /* value from target */
					duk_bool_t datadesc_reject;
					duk_bool_t accdesc_reject;

					DUK_DDD(DUK_DDDPRINT("proxy 'get': target has matching property %!O, check for "
					                     "conflicting property; tv_hook=%!T, tv_targ=%!T, desc.flags=0x%08lx, "
					                     "desc.get=%p, desc.set=%p",
					                     (duk_heaphdr *) key, (duk_tval *) tv_hook, (duk_tval *) tv_targ,
					                     (unsigned long) desc.flags,
					                     (void *) desc.get, (void *) desc.set));

					datadesc_reject = !(desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
					                  !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) &&
					                  !(desc.flags & DUK_PROPDESC_FLAG_WRITABLE) &&
					                  !duk_js_samevalue(tv_hook, tv_targ);
					accdesc_reject = (desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
					                 !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) &&
					                 (desc.get == NULL) &&
					                 !DUK_TVAL_IS_UNDEFINED(tv_hook);
					if (datadesc_reject || accdesc_reject) {
						DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);
						DUK_WO_NORETURN(return 0;);
					}

					duk_pop_2_unsafe(thr);
				} else {
					duk_pop_unsafe(thr);
				}
				return 1;  /* return value */
			}

			curr = h_target;  /* resume lookup from target */
			DUK_TVAL_SET_OBJECT(tv_obj, curr);
		}
#endif  /* DUK_USE_ES6_PROXY */

		if (DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(curr)) {
			arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
			DUK_ASSERT(key != NULL);

			DUK_STATS_INC(thr->heap, stats_getprop_arguments);
			if (duk__check_arguments_map_for_get(thr, curr, key, &desc)) {
				DUK_DDD(DUK_DDDPRINT("-> %!T (base is object with arguments exotic behavior, "
				                     "key matches magically bound property -> skip standard "
				                     "Get with replacement value)",
				                     (duk_tval *) duk_get_tval(thr, -1)));

				/* no need for 'caller' post-check, because 'key' must be an array index */

				duk_remove_m2(thr);  /* [key result] -> [result] */
				return 1;
			}

			goto lookup;  /* avoid double coercion */
		}
		break;
	}

	/* Buffer has virtual properties similar to string, but indexed values
	 * are numbers, not 1-byte buffers/strings which would perform badly.
	 */
	case DUK_TAG_BUFFER: {
		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv_obj);
		duk_int_t pop_count;

		/*
		 *  Because buffer values are often looped over, a number fast path
		 *  is important.
		 */

#if defined(DUK_USE_FASTINT)
		if (DUK_TVAL_IS_FASTINT(tv_key)) {
			arr_idx = duk__tval_fastint_to_arr_idx(tv_key);
			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a fast-path fastint; arr_idx %ld", (long) arr_idx));
			pop_count = 0;
		}
		else
#endif
		if (DUK_TVAL_IS_NUMBER(tv_key)) {
			arr_idx = duk__tval_number_to_arr_idx(tv_key);
			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a fast-path number; arr_idx %ld", (long) arr_idx));
			pop_count = 0;
		} else {
			arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
			DUK_ASSERT(key != NULL);
			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a non-fast-path number; after "
			                     "coercion key is %!T, arr_idx %ld",
			                     (duk_tval *) duk_get_tval(thr, -1), (long) arr_idx));
			pop_count = 1;
		}

		if (arr_idx != DUK__NO_ARRAY_INDEX &&
		    arr_idx < DUK_HBUFFER_GET_SIZE(h)) {
			duk_pop_n_unsafe(thr, pop_count);
			duk_push_uint(thr, ((duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h))[arr_idx]);
			DUK_STATS_INC(thr->heap, stats_getprop_bufferidx);
			DUK_DDD(DUK_DDDPRINT("-> %!T (base is buffer, key is an index inside buffer length "
			                     "after coercion -> return byte as number)",
			                     (duk_tval *) duk_get_tval(thr, -1)));
			return 1;
		}

		if (pop_count == 0) {
			/* This is a pretty awkward control flow, but we need to recheck the
			 * key coercion here.
			 */
			arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
			DUK_ASSERT(key != NULL);
			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a non-fast-path number; after "
			                     "coercion key is %!T, arr_idx %ld",
			                     (duk_tval *) duk_get_tval(thr, -1), (long) arr_idx));
		}

		if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
			duk_pop_unsafe(thr);  /* [key] -> [] */
			duk_push_uint(thr, (duk_uint_t) DUK_HBUFFER_GET_SIZE(h));  /* [] -> [res] */
			DUK_STATS_INC(thr->heap, stats_getprop_bufferlen);

			DUK_DDD(DUK_DDDPRINT("-> %!T (base is buffer, key is 'length' "
			                     "after coercion -> return buffer length)",
			                     (duk_tval *) duk_get_tval(thr, -1)));
			return 1;
		}

		DUK_DDD(DUK_DDDPRINT("base object is a buffer, start lookup from Uint8Array prototype"));
		curr = thr->builtins[DUK_BIDX_UINT8ARRAY_PROTOTYPE];
		goto lookup;  /* avoid double coercion */
	}

	case DUK_TAG_POINTER: {
		DUK_DDD(DUK_DDDPRINT("base object is a pointer, start lookup from pointer prototype"));
		curr = thr->builtins[DUK_BIDX_POINTER_PROTOTYPE];
		break;
	}

	case DUK_TAG_LIGHTFUNC: {
		/* Lightfuncs inherit getter .name and .length from %NativeFunctionPrototype%. */
		DUK_DDD(DUK_DDDPRINT("base object is a lightfunc, start lookup from function prototype"));
		curr = thr->builtins[DUK_BIDX_NATIVE_FUNCTION_PROTOTYPE];
		break;
	}

#if defined(DUK_USE_FASTINT)
	case DUK_TAG_FASTINT:
#endif
	default: {
		/* number */
		DUK_DDD(DUK_DDDPRINT("base object is a number, start lookup from number prototype"));
		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv_obj));
		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_obj));
		curr = thr->builtins[DUK_BIDX_NUMBER_PROTOTYPE];
		break;
	}
	}

	/* key coercion (unless already coerced above) */
	DUK_ASSERT(key == NULL);
	arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
	DUK_ASSERT(key != NULL);
	/*
	 *  Property lookup
	 */

 lookup:
	/* [key] (coerced) */
	DUK_ASSERT(curr != NULL);
	DUK_ASSERT(key != NULL);

	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
	do {
		if (!duk__get_own_propdesc_raw(thr, curr, key, arr_idx, &desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
			goto next_in_chain;
		}

		if (desc.get != NULL) {
			/* accessor with defined getter */
			DUK_ASSERT((desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) != 0);

			duk_pop_unsafe(thr);              /* [key undefined] -> [key] */
			duk_push_hobject(thr, desc.get);
			duk_push_tval(thr, tv_obj);       /* note: original, uncoerced base */
#if defined(DUK_USE_NONSTD_GETTER_KEY_ARGUMENT)
			duk_dup_m3(thr);
			duk_call_method(thr, 1);          /* [key getter this key] -> [key retval] */
#else
			duk_call_method(thr, 0);          /* [key getter this] -> [key retval] */
#endif
		} else {
			/* [key value] or [key undefined] */

			/* data property or accessor without getter */
			DUK_ASSERT(((desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) == 0) ||
			           (desc.get == NULL));

			/* if accessor without getter, return value is undefined */
			DUK_ASSERT(((desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) == 0) ||
			           duk_is_undefined(thr, -1));

			/* Note: for an accessor without getter, falling through to
			 * check for "caller" exotic behavior is unnecessary as
			 * "undefined" will never activate the behavior.  But it does
			 * no harm, so we'll do it anyway.
			 */
		}

		goto found;  /* [key result] */

	 next_in_chain:
		/* XXX: option to pretend property doesn't exist if sanity limit is
		 * hit might be useful.
		 */
		if (DUK_UNLIKELY(sanity-- == 0)) {
			DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
			DUK_WO_NORETURN(return 0;);
		}
		curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr);
	} while (curr != NULL);

	/*
	 *  Not found
	 */

	duk_to_undefined(thr, -1);  /* [key] -> [undefined] (default value) */

	DUK_DDD(DUK_DDDPRINT("-> %!T (not found)", (duk_tval *) duk_get_tval(thr, -1)));
	return 0;

	/*
	 *  Found; post-processing (Function and arguments objects)
	 */

 found:
	/* [key result] */

#if !defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
	/* Special behavior for 'caller' property of (non-bound) function objects
	 * and non-strict Arguments objects: if 'caller' -value- (!) is a strict
	 * mode function, throw a TypeError (E5 Sections 15.3.5.4, 10.6).
	 * Quite interestingly, a non-strict function with no formal arguments
	 * will get an arguments object -without- special 'caller' behavior!
	 *
	 * The E5.1 spec is a bit ambiguous if this special behavior applies when
	 * a bound function is the base value (not the 'caller' value): Section
	 * 15.3.4.5 (describing bind()) states that [[Get]] for bound functions
	 * matches that of Section 15.3.5.4 ([[Get]] for Function instances).
	 * However, Section 13.3.5.4 has "NOTE: Function objects created using
	 * Function.prototype.bind use the default [[Get]] internal method."
	 * The current implementation assumes this means that bound functions
	 * should not have the special [[Get]] behavior.
	 *
	 * The E5.1 spec is also a bit unclear if the TypeError throwing is
	 * applied if the 'caller' value is a strict bound function.  The
	 * current implementation will throw even for both strict non-bound
	 * and strict bound functions.
	 *
	 * See test-dev-strict-func-as-caller-prop-value.js for quite extensive
	 * tests.
	 *
	 * This exotic behavior is disabled when the non-standard 'caller' property
	 * is enabled, as it conflicts with the free use of 'caller'.
	 */
	if (key == DUK_HTHREAD_STRING_CALLER(thr) &&
	    DUK_TVAL_IS_OBJECT(tv_obj)) {
		duk_hobject *orig = DUK_TVAL_GET_OBJECT(tv_obj);
		DUK_ASSERT(orig != NULL);

		if (DUK_HOBJECT_IS_NONBOUND_FUNCTION(orig) ||
		    DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(orig)) {
			duk_hobject *h;

			/* XXX: The TypeError is currently not applied to bound
			 * functions because the 'strict' flag is not copied by
			 * bind().  This may or may not be correct, the specification
			 * only refers to the value being a "strict mode Function
			 * object" which is ambiguous.
			 */
			DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(orig));

			h = duk_get_hobject(thr, -1);  /* NULL if not an object */
			if (h &&
			    DUK_HOBJECT_IS_FUNCTION(h) &&
			    DUK_HOBJECT_HAS_STRICT(h)) {
				/* XXX: sufficient to check 'strict', assert for 'is function' */
				DUK_ERROR_TYPE(thr, DUK_STR_STRICT_CALLER_READ);
				DUK_WO_NORETURN(return 0;);
			}
		}
	}
#endif   /* !DUK_USE_NONSTD_FUNC_CALLER_PROPERTY */

	duk_remove_m2(thr);  /* [key result] -> [result] */

	DUK_DDD(DUK_DDDPRINT("-> %!T (found)", (duk_tval *) duk_get_tval(thr, -1)));
	return 1;
}

/*
 *  HASPROP: ECMAScript property existence check ("in" operator).
 *
 *  Interestingly, the 'in' operator does not do any coercion of
 *  the target object.
 */

DUK_INTERNAL duk_bool_t duk_hobject_hasprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key) {
	duk_tval tv_key_copy;
	duk_hobject *obj;
	duk_hstring *key;
	duk_uint32_t arr_idx;
	duk_bool_t rc;
	duk_propdesc desc;

	DUK_DDD(DUK_DDDPRINT("hasprop: thr=%p, obj=%p, key=%p (obj -> %!T, key -> %!T)",
	                     (void *) thr, (void *) tv_obj, (void *) tv_key,
	                     (duk_tval *) tv_obj, (duk_tval *) tv_key));

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(thr->heap != NULL);
	DUK_ASSERT(tv_obj != NULL);
	DUK_ASSERT(tv_key != NULL);
	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);

	DUK_TVAL_SET_TVAL(&tv_key_copy, tv_key);
	tv_key = &tv_key_copy;

	/*
	 *  The 'in' operator requires an object as its right hand side,
	 *  throwing a TypeError unconditionally if this is not the case.
	 *
	 *  However, lightfuncs need to behave like fully fledged objects
	 *  here to be maximally transparent, so we need to handle them
	 *  here.  Same goes for plain buffers which behave like ArrayBuffers.
	 */

	/* XXX: Refactor key coercion so that it's only called once.  It can't
	 * be trivially lifted here because the object must be type checked
	 * first.
	 */

	if (DUK_TVAL_IS_OBJECT(tv_obj)) {
		obj = DUK_TVAL_GET_OBJECT(tv_obj);
		DUK_ASSERT(obj != NULL);

		arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
	} else if (DUK_TVAL_IS_BUFFER(tv_obj)) {
		arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
		if (duk__key_is_plain_buf_ownprop(thr, DUK_TVAL_GET_BUFFER(tv_obj), key, arr_idx)) {
			rc = 1;
			goto pop_and_return;
		}
		obj = thr->builtins[DUK_BIDX_UINT8ARRAY_PROTOTYPE];
	} else if (DUK_TVAL_IS_LIGHTFUNC(tv_obj)) {
		arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);

		/* If not found, resume existence check from %NativeFunctionPrototype%.
		 * We can just substitute the value in this case; nothing will
		 * need the original base value (as would be the case with e.g.
		 * setters/getters.
		 */
		obj = thr->builtins[DUK_BIDX_NATIVE_FUNCTION_PROTOTYPE];
	} else {
		/* Note: unconditional throw */
		DUK_DDD(DUK_DDDPRINT("base object is not an object -> reject"));
		DUK_ERROR_TYPE(thr, DUK_STR_INVALID_BASE);
		DUK_WO_NORETURN(return 0;);
	}

	/* XXX: fast path for arrays? */

	DUK_ASSERT(key != NULL);
	DUK_ASSERT(obj != NULL);
	DUK_UNREF(arr_idx);

#if defined(DUK_USE_ES6_PROXY)
	if (DUK_UNLIKELY(DUK_HOBJECT_IS_PROXY(obj))) {
		duk_hobject *h_target;
		duk_bool_t tmp_bool;

		/* XXX: the key in 'key in obj' is string coerced before we're called
		 * (which is the required behavior in E5/E5.1/E6) so the key is a string
		 * here already.
		 */

		if (duk__proxy_check_prop(thr, obj, DUK_STRIDX_HAS, tv_key, &h_target)) {
			/* [ ... key trap handler ] */
			DUK_DDD(DUK_DDDPRINT("-> proxy object 'has' for key %!T", (duk_tval *) tv_key));
			duk_push_hobject(thr, h_target);  /* target */
			duk_push_tval(thr, tv_key);       /* P */
			duk_call_method(thr, 2 /*nargs*/);
			tmp_bool = duk_to_boolean_top_pop(thr);
			if (!tmp_bool) {
				/* Target object must be checked for a conflicting
				 * non-configurable property.
				 */

				if (duk__get_own_propdesc_raw(thr, h_target, key, arr_idx, &desc, 0 /*flags*/)) {  /* don't push value */
					DUK_DDD(DUK_DDDPRINT("proxy 'has': target has matching property %!O, check for "
					                     "conflicting property; desc.flags=0x%08lx, "
					                     "desc.get=%p, desc.set=%p",
					                     (duk_heaphdr *) key, (unsigned long) desc.flags,
					                     (void *) desc.get, (void *) desc.set));
					/* XXX: Extensibility check for target uses IsExtensible().  If we
					 * implemented the isExtensible trap and didn't reject proxies as
					 * proxy targets, it should be respected here.
					 */
					if (!((desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) &&  /* property is configurable and */
					      DUK_HOBJECT_HAS_EXTENSIBLE(h_target))) {          /* ... target is extensible */
						DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);
						DUK_WO_NORETURN(return 0;);
					}
				}
			}

			duk_pop_unsafe(thr);  /* [ key ] -> [] */
			return tmp_bool;
		}

		obj = h_target;  /* resume check from proxy target */
	}
#endif  /* DUK_USE_ES6_PROXY */

	/* XXX: inline into a prototype walking loop? */

	rc = duk__get_propdesc(thr, obj, key, &desc, 0 /*flags*/);  /* don't push value */
	/* fall through */

 pop_and_return:
	duk_pop_unsafe(thr);  /* [ key ] -> [] */
	return rc;
}

/*
 *  HASPROP variant used internally.
 *
 *  This primitive must never throw an error, callers rely on this.
 *  In particular, don't throw an error for prototype loops; instead,
 *  pretend like the property doesn't exist if a prototype sanity limit
 *  is reached.
 *
 *  Does not implement proxy behavior: if applied to a proxy object,
 *  returns key existence on the proxy object itself.
 */

DUK_INTERNAL duk_bool_t duk_hobject_hasprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key) {
	duk_propdesc dummy;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(thr->heap != NULL);
	DUK_ASSERT(obj != NULL);
	DUK_ASSERT(key != NULL);

	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);

	return duk__get_propdesc(thr, obj, key, &dummy, DUK_GETDESC_FLAG_IGNORE_PROTOLOOP);  /* don't push value */
}

/*
 *  Helper: handle Array object 'length' write which automatically
 *  deletes properties, see E5 Section 15.4.5.1, step 3.  This is
 *  quite tricky to get right.
 *
 *  Used by duk_hobject_putprop().
 */

/* Coerce a new .length candidate to a number and check that it's a valid
 * .length.
 */
DUK_LOCAL duk_uint32_t duk__to_new_array_length_checked(duk_hthread *thr, duk_tval *tv) {
	duk_uint32_t res;
	duk_double_t d;

#if !defined(DUK_USE_PREFER_SIZE)
#if defined(DUK_USE_FASTINT)
	/* When fastints are enabled, the most interesting case is assigning
	 * a fastint to .length (e.g. arr.length = 0).
	 */
	if (DUK_TVAL_IS_FASTINT(tv)) {
		/* Very common case. */
		duk_int64_t fi;
		fi = DUK_TVAL_GET_FASTINT(tv);
		if (fi < 0 || fi > DUK_I64_CONSTANT(0xffffffff)) {
			goto fail_range;
		}
		return (duk_uint32_t) fi;
	}
#else  /* DUK_USE_FASTINT */
	/* When fastints are not enabled, the most interesting case is any
	 * number.
	 */
	if (DUK_TVAL_IS_DOUBLE(tv)) {
		d = DUK_TVAL_GET_NUMBER(tv);
	}
#endif  /* DUK_USE_FASTINT */
	else
#endif  /* !DUK_USE_PREFER_SIZE */
	{
		/* In all other cases, and when doing a size optimized build,
		 * fall back to the comprehensive handler.
		 */
		d = duk_js_tonumber(thr, tv);
	}

	/* Refuse to update an Array's 'length' to a value outside the
	 * 32-bit range.  Negative zero is accepted as zero.
	 */
	res = duk_double_to_uint32_t(d);
	if (!duk_double_equals((duk_double_t) res, d)) {
		goto fail_range;
	}

	return res;

 fail_range:
	DUK_ERROR_RANGE(thr, DUK_STR_INVALID_ARRAY_LENGTH);
	DUK_WO_NORETURN(return 0;);
}

/* Delete elements required by a smaller length, taking into account
 * potentially non-configurable elements.  Returns non-zero if all
 * elements could be deleted, and zero if all or some elements could
 * not be deleted.  Also writes final "target length" to 'out_result_len'.
 * This is the length value that should go into the 'length' property
 * (must be set by the caller).  Never throws an error.
 */
DUK_LOCAL
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) {
	duk_uint32_t target_len;
	duk_uint_fast32_t i;
	duk_uint32_t arr_idx;
	duk_hstring *key;
	duk_tval *tv;
	duk_bool_t rc;

	DUK_DDD(DUK_DDDPRINT("new array length smaller than old (%ld -> %ld), "
	                     "probably need to remove elements",
	                     (long) old_len, (long) new_len));

	/*
	 *  New length is smaller than old length, need to delete properties above
	 *  the new length.
	 *
	 *  If array part exists, this is straightforward: array entries cannot
	 *  be non-configurable so this is guaranteed to work.
	 *
	 *  If array part does not exist, array-indexed values are scattered
	 *  in the entry part, and some may not be configurable (preventing length
	 *  from becoming lower than their index + 1).  To handle the algorithm
	 *  in E5 Section 15.4.5.1, step l correctly, we scan the entire property
	 *  set twice.
	 */

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(obj != NULL);
	DUK_ASSERT(new_len < old_len);
	DUK_ASSERT(out_result_len != NULL);
	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);

	DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj));
	DUK_ASSERT(DUK_HOBJECT_IS_ARRAY(obj));

	if (DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
		/*
		 *  All defined array-indexed properties are in the array part
		 *  (we assume the array part is comprehensive), and all array
		 *  entries are writable, configurable, and enumerable.  Thus,
		 *  nothing can prevent array entries from being deleted.
		 */

		DUK_DDD(DUK_DDDPRINT("have array part, easy case"));

		if (old_len < DUK_HOBJECT_GET_ASIZE(obj)) {
			/* XXX: assertion that entries >= old_len are already unused */
			i = old_len;
		} else {
			i = DUK_HOBJECT_GET_ASIZE(obj);
		}
		DUK_ASSERT(i <= DUK_HOBJECT_GET_ASIZE(obj));

		while (i > new_len) {
			i--;
			tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, i);
			DUK_TVAL_SET_UNUSED_UPDREF(thr, tv);  /* side effects */
		}

		*out_result_len = new_len;
		return 1;
	} else {
		/*
		 *  Entries part is a bit more complex.
		 */

		/* Stage 1: find highest preventing non-configurable entry (if any).
		 * When forcing, ignore non-configurability.
		 */

		DUK_DDD(DUK_DDDPRINT("no array part, slow case"));

		DUK_DDD(DUK_DDDPRINT("array length write, no array part, stage 1: find target_len "
		                     "(highest preventing non-configurable entry (if any))"));

		target_len = new_len;
		if (force_flag) {
			DUK_DDD(DUK_DDDPRINT("array length write, no array part; force flag -> skip stage 1"));
			goto skip_stage1;
		}
		for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
			key = DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i);
			if (!key) {
				DUK_DDD(DUK_DDDPRINT("skip entry index %ld: null key", (long) i));
				continue;
			}
			if (!DUK_HSTRING_HAS_ARRIDX(key)) {
				DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key not an array index", (long) i));
				continue;
			}

			DUK_ASSERT(DUK_HSTRING_HAS_ARRIDX(key));  /* XXX: macro checks for array index flag, which is unnecessary here */
			arr_idx = DUK_HSTRING_GET_ARRIDX_SLOW(key);
			DUK_ASSERT(arr_idx != DUK__NO_ARRAY_INDEX);
			DUK_ASSERT(arr_idx < old_len);  /* consistency requires this */

			if (arr_idx < new_len) {
				DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key is array index %ld, below new_len",
				                     (long) i, (long) arr_idx));
				continue;
			}
			if (DUK_HOBJECT_E_SLOT_IS_CONFIGURABLE(thr->heap, obj, i)) {
				DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key is a relevant array index %ld, but configurable",
				                     (long) i, (long) arr_idx));
				continue;
			}

			/* relevant array index is non-configurable, blocks write */
			if (arr_idx >= target_len) {
				DUK_DDD(DUK_DDDPRINT("entry at index %ld has arr_idx %ld, is not configurable, "
				                     "update target_len %ld -> %ld",
				                     (long) i, (long) arr_idx, (long) target_len,
				                     (long) (arr_idx + 1)));
				target_len = arr_idx + 1;
			}
		}
	 skip_stage1:

		/* stage 2: delete configurable entries above target length */

		DUK_DDD(DUK_DDDPRINT("old_len=%ld, new_len=%ld, target_len=%ld",
		                     (long) old_len, (long) new_len, (long) target_len));

		DUK_DDD(DUK_DDDPRINT("array length write, no array part, stage 2: remove "
		                     "entries >= target_len"));

		for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
			key = DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i);
			if (!key) {
				DUK_DDD(DUK_DDDPRINT("skip entry index %ld: null key", (long) i));
				continue;
			}
			if (!DUK_HSTRING_HAS_ARRIDX(key)) {
				DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key not an array index", (long) i));
				continue;
			}

			DUK_ASSERT(DUK_HSTRING_HAS_ARRIDX(key));  /* XXX: macro checks for array index flag, which is unnecessary here */
			arr_idx = DUK_HSTRING_GET_ARRIDX_SLOW(key);
			DUK_ASSERT(arr_idx != DUK__NO_ARRAY_INDEX);
			DUK_ASSERT(arr_idx < old_len);  /* consistency requires this */

			if (arr_idx < target_len) {
				DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key is array index %ld, below target_len",
				                     (long) i, (long) arr_idx));
				continue;
			}
			DUK_ASSERT(force_flag || DUK_HOBJECT_E_SLOT_IS_CONFIGURABLE(thr->heap, obj, i));  /* stage 1 guarantees */

			DUK_DDD(DUK_DDDPRINT("delete entry index %ld: key is array index %ld",
			                     (long) i, (long) arr_idx));

			/*
			 *  Slow delete, but we don't care as we're already in a very slow path.
			 *  The delete always succeeds: key has no exotic behavior, property
			 *  is configurable, and no resize occurs.
			 */
			rc = duk_hobject_delprop_raw(thr, obj, key, force_flag ? DUK_DELPROP_FLAG_FORCE : 0);
			DUK_UNREF(rc);
			DUK_ASSERT(rc != 0);
		}

		/* stage 3: update length (done by caller), decide return code */

		DUK_DDD(DUK_DDDPRINT("array length write, no array part, stage 3: update length (done by caller)"));

		*out_result_len = target_len;

		if (target_len == new_len) {
			DUK_DDD(DUK_DDDPRINT("target_len matches new_len, return success"));
			return 1;
		}
		DUK_DDD(DUK_DDDPRINT("target_len does not match new_len (some entry prevented "
		                     "full length adjustment), return error"));
		return 0;
	}

	DUK_UNREACHABLE();
}

/* XXX: is valstack top best place for argument? */
DUK_LOCAL duk_bool_t duk__handle_put_array_length(duk_hthread *thr, duk_hobject *obj) {
	duk_harray *a;
	duk_uint32_t old_len;
	duk_uint32_t new_len;
	duk_uint32_t result_len;
	duk_bool_t rc;

	DUK_DDD(DUK_DDDPRINT("handling a put operation to array 'length' exotic property, "
	                     "new val: %!T",
	                     (duk_tval *) duk_get_tval(thr, -1)));

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(obj != NULL);

	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);

	DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj));
	DUK_ASSERT(DUK_HOBJECT_IS_ARRAY(obj));
	a = (duk_harray *) obj;
	DUK_HARRAY_ASSERT_VALID(a);

	DUK_ASSERT(duk_is_valid_index(thr, -1));

	/*
	 *  Get old and new length
	 */

	old_len = a->length;
	new_len = duk__to_new_array_length_checked(thr, DUK_GET_TVAL_NEGIDX(thr, -1));
	DUK_DDD(DUK_DDDPRINT("old_len=%ld, new_len=%ld", (long) old_len, (long) new_len));

	/*
	 *  Writability check
	 */

	if (DUK_HARRAY_LENGTH_NONWRITABLE(a)) {
		DUK_DDD(DUK_DDDPRINT("length is not writable, fail"));
		return 0;
	}

	/*
	 *  New length not lower than old length => no changes needed
	 *  (not even array allocation).
	 */

	if (new_len >= old_len) {
		DUK_DDD(DUK_DDDPRINT("new length is same or higher than old length, just update length, no deletions"));
		a->length = new_len;
		return 1;
	}

	DUK_DDD(DUK_DDDPRINT("new length is lower than old length, probably must delete entries"));

	/*
	 *  New length lower than old length => delete elements, then
	 *  update length.
	 *
	 *  Note: even though a bunch of elements have been deleted, the 'desc' is
	 *  still valid as properties haven't been resized (and entries compacted).
	 */

	rc = duk__handle_put_array_length_smaller(thr, obj, old_len, new_len, 0 /*force_flag*/, &result_len);
	DUK_ASSERT(result_len >= new_len && result_len <= old_len);

	a->length = result_len;

	/* XXX: shrink array allocation or entries compaction here? */

	return rc;
}

/*
 *  PUTPROP: ECMAScript property write.
 *
 *  Unlike ECMAScript primitive which returns nothing, returns 1 to indicate
 *  success and 0 to indicate failure (assuming throw is not set).
 *
 *  This is an extremely tricky function.  Some examples:
 *
 *    * Currently a decref may trigger a GC, which may compact an object's
 *      property allocation.  Consequently, any entry indices (e_idx) will
 *      be potentially invalidated by a decref.
 *
 *    * Exotic behaviors (strings, arrays, arguments object) require,
 *      among other things:
 *
 *      - Preprocessing before and postprocessing after an actual property
 *        write.  For example, array index write requires pre-checking the
 *        array 'length' property for access control, and may require an
 *        array 'length' update after the actual write has succeeded (but
 *        not if it fails).
 *
 *      - Deletion of multiple entries, as a result of array 'length' write.
 *
 *    * Input values are taken as pointers which may point to the valstack.
 *      If valstack is resized because of the put (this may happen at least
 *      when the array part is abandoned), the pointers can be invalidated.
 *      (We currently make a copy of all of the input values to avoid issues.)
 */

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) {
	duk_tval tv_obj_copy;
	duk_tval tv_key_copy;
	duk_tval tv_val_copy;
	duk_hobject *orig = NULL;  /* NULL if tv_obj is primitive */
	duk_hobject *curr;
	duk_hstring *key = NULL;
	duk_propdesc desc;
	duk_tval *tv;
	duk_uint32_t arr_idx;
	duk_bool_t rc;
	duk_int_t e_idx;
	duk_uint_t sanity;
	duk_uint32_t new_array_length = 0;  /* 0 = no update */

	DUK_DDD(DUK_DDDPRINT("putprop: thr=%p, obj=%p, key=%p, val=%p, throw=%ld "
	                     "(obj -> %!T, key -> %!T, val -> %!T)",
	                     (void *) thr, (void *) tv_obj, (void *) tv_key, (void *) tv_val,
	                     (long) throw_flag, (duk_tval *) tv_obj, (duk_tval *) tv_key, (duk_tval *) tv_val));

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(thr->heap != NULL);
	DUK_ASSERT(tv_obj != NULL);
	DUK_ASSERT(tv_key != NULL);
	DUK_ASSERT(tv_val != NULL);

	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);

	DUK_STATS_INC(thr->heap, stats_putprop_all);

	/*
	 *  Make a copy of tv_obj, tv_key, and tv_val to avoid any issues of
	 *  them being invalidated by a valstack resize.
	 *
	 *  XXX: this is an overkill for some paths, so optimize this later
	 *  (or maybe switch to a stack arguments model entirely).
	 */

	DUK_TVAL_SET_TVAL(&tv_obj_copy, tv_obj);
	DUK_TVAL_SET_TVAL(&tv_key_copy, tv_key);
	DUK_TVAL_SET_TVAL(&tv_val_copy, tv_val);
	tv_obj = &tv_obj_copy;
	tv_key = &tv_key_copy;
	tv_val = &tv_val_copy;

	/*
	 *  Coercion and fast path processing.
	 */

	switch (DUK_TVAL_GET_TAG(tv_obj)) {
	case DUK_TAG_UNDEFINED:
	case DUK_TAG_NULL: {
		/* Note: unconditional throw */
		DUK_DDD(DUK_DDDPRINT("base object is undefined or null -> reject (object=%!iT)",
		                     (duk_tval *) tv_obj));
#if defined(DUK_USE_PARANOID_ERRORS)
		DUK_ERROR_TYPE(thr, DUK_STR_INVALID_BASE);
#else
		DUK_ERROR_FMT2(thr, DUK_ERR_TYPE_ERROR, "cannot write property %s of %s",
		               duk_push_string_tval_readable(thr, tv_key), duk_push_string_tval_readable(thr, tv_obj));
#endif
		DUK_WO_NORETURN(return 0;);
		break;
	}

	case DUK_TAG_BOOLEAN: {
		DUK_DDD(DUK_DDDPRINT("base object is a boolean, start lookup from boolean prototype"));
		curr = thr->builtins[DUK_BIDX_BOOLEAN_PROTOTYPE];
		break;
	}

	case DUK_TAG_STRING: {
		duk_hstring *h = DUK_TVAL_GET_STRING(tv_obj);

		/*
		 *  Note: currently no fast path for array index writes.
		 *  They won't be possible anyway as strings are immutable.
		 */

		DUK_ASSERT(key == NULL);
		arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
		DUK_ASSERT(key != NULL);

		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
			/* Symbols (ES2015 or hidden) don't have virtual properties. */
			curr = thr->builtins[DUK_BIDX_SYMBOL_PROTOTYPE];
			goto lookup;
		}

		if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
			goto fail_not_writable;
		}

		if (arr_idx != DUK__NO_ARRAY_INDEX &&
		    arr_idx < DUK_HSTRING_GET_CHARLEN(h)) {
			goto fail_not_writable;
		}

		DUK_DDD(DUK_DDDPRINT("base object is a string, start lookup from string prototype"));
		curr = thr->builtins[DUK_BIDX_STRING_PROTOTYPE];
		goto lookup;  /* avoid double coercion */
	}

	case DUK_TAG_OBJECT: {
		orig = DUK_TVAL_GET_OBJECT(tv_obj);
		DUK_ASSERT(orig != NULL);

#if defined(DUK_USE_ROM_OBJECTS)
		/* With this check in place fast paths won't need read-only
		 * object checks.  This is technically incorrect if there are
		 * setters that cause no writes to ROM objects, but current
		 * built-ins don't have such setters.
		 */
		if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) orig)) {
			DUK_DD(DUK_DDPRINT("attempt to putprop on read-only target object"));
			goto fail_not_writable_no_pop;  /* Must avoid duk_pop() in exit path */
		}
#endif

		/* The fast path for array property put is not fully compliant:
		 * If one places conflicting number-indexed properties into
		 * Array.prototype (for example, a non-writable Array.prototype[7])
		 * the fast path will incorrectly ignore them.
		 *
		 * This fast path could be made compliant by falling through
		 * to the slow path if the previous value was UNUSED.  This would
		 * also remove the need to check for extensibility.  Right now a
		 * non-extensible array is slower than an extensible one as far
		 * as writes are concerned.
		 *
		 * The fast path behavior is documented in more detail here:
		 * tests/ecmascript/test-misc-array-fast-write.js
		 */

		/* XXX: array .length? */

#if defined(DUK_USE_ARRAY_PROP_FASTPATH)
		if (duk__putprop_shallow_fastpath_array_tval(thr, orig, tv_key, tv_val) != 0) {
			DUK_DDD(DUK_DDDPRINT("array fast path success"));
			DUK_STATS_INC(thr->heap, stats_putprop_arrayidx);
			return 1;
		}
#endif

#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
		if (duk__putprop_fastpath_bufobj_tval(thr, orig, tv_key, tv_val) != 0) {
			DUK_DDD(DUK_DDDPRINT("base is bufobj, key is a number, bufobj fast path"));
			DUK_STATS_INC(thr->heap, stats_putprop_bufobjidx);
			return 1;
		}
#endif

#if defined(DUK_USE_ES6_PROXY)
		if (DUK_UNLIKELY(DUK_HOBJECT_IS_PROXY(orig))) {
			duk_hobject *h_target;
			duk_bool_t tmp_bool;

			if (duk__proxy_check_prop(thr, orig, DUK_STRIDX_SET, tv_key, &h_target)) {
				/* -> [ ... trap handler ] */
				DUK_DDD(DUK_DDDPRINT("-> proxy object 'set' for key %!T", (duk_tval *) tv_key));
				DUK_STATS_INC(thr->heap, stats_putprop_proxy);
				duk_push_hobject(thr, h_target);  /* target */
				duk_push_tval(thr, tv_key);       /* P */
				duk_push_tval(thr, tv_val);       /* V */
				duk_push_tval(thr, tv_obj);       /* Receiver: Proxy object */
				duk_call_method(thr, 4 /*nargs*/);
				tmp_bool = duk_to_boolean_top_pop(thr);
				if (!tmp_bool) {
					goto fail_proxy_rejected;
				}

				/* Target object must be checked for a conflicting
				 * non-configurable property.
				 */
				arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
				DUK_ASSERT(key != NULL);

				if (duk__get_own_propdesc_raw(thr, h_target, key, arr_idx, &desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
					duk_tval *tv_targ = duk_require_tval(thr, -1);
					duk_bool_t datadesc_reject;
					duk_bool_t accdesc_reject;

					DUK_DDD(DUK_DDDPRINT("proxy 'set': target has matching property %!O, check for "
					                     "conflicting property; tv_val=%!T, tv_targ=%!T, desc.flags=0x%08lx, "
					                     "desc.get=%p, desc.set=%p",
					                     (duk_heaphdr *) key, (duk_tval *) tv_val, (duk_tval *) tv_targ,
					                     (unsigned long) desc.flags,
					                     (void *) desc.get, (void *) desc.set));

					datadesc_reject = !(desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
					                  !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) &&
					                  !(desc.flags & DUK_PROPDESC_FLAG_WRITABLE) &&
					                  !duk_js_samevalue(tv_val, tv_targ);
					accdesc_reject = (desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
					                 !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) &&
					                 (desc.set == NULL);
					if (datadesc_reject || accdesc_reject) {
						DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);
						DUK_WO_NORETURN(return 0;);
					}

					duk_pop_2_unsafe(thr);
				} else {
					duk_pop_unsafe(thr);
				}
				return 1;  /* success */
			}

			orig = h_target;  /* resume write to target */
			DUK_TVAL_SET_OBJECT(tv_obj, orig);
		}
#endif  /* DUK_USE_ES6_PROXY */

		curr = orig;
		break;
	}

	case DUK_TAG_BUFFER: {
		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv_obj);
		duk_int_t pop_count = 0;

		/*
		 *  Because buffer values may be looped over and read/written
		 *  from, an array index fast path is important.
		 */

#if defined(DUK_USE_FASTINT)
		if (DUK_TVAL_IS_FASTINT(tv_key)) {
			arr_idx = duk__tval_fastint_to_arr_idx(tv_key);
			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a fast-path fastint; arr_idx %ld", (long) arr_idx));
			pop_count = 0;
		} else
#endif
		if (DUK_TVAL_IS_NUMBER(tv_key)) {
			arr_idx = duk__tval_number_to_arr_idx(tv_key);
			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a fast-path number; arr_idx %ld", (long) arr_idx));
			pop_count = 0;
		} else {
			arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
			DUK_ASSERT(key != NULL);
			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a non-fast-path number; after "
			                     "coercion key is %!T, arr_idx %ld",
			                     (duk_tval *) duk_get_tval(thr, -1), (long) arr_idx));
			pop_count = 1;
		}

		if (arr_idx != DUK__NO_ARRAY_INDEX &&
		    arr_idx < DUK_HBUFFER_GET_SIZE(h)) {
			duk_uint8_t *data;
			DUK_DDD(DUK_DDDPRINT("writing to buffer data at index %ld", (long) arr_idx));
			data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h);

			/* XXX: duk_to_int() ensures we'll get 8 lowest bits as
			 * as input is within duk_int_t range (capped outside it).
			 */
#if defined(DUK_USE_FASTINT)
			/* Buffer writes are often integers. */
			if (DUK_TVAL_IS_FASTINT(tv_val)) {
				data[arr_idx] = (duk_uint8_t) DUK_TVAL_GET_FASTINT_U32(tv_val);
			}
			else
#endif
			{
				duk_push_tval(thr, tv_val);
				data[arr_idx] = (duk_uint8_t) duk_to_uint32(thr, -1);
				pop_count++;
			}

			duk_pop_n_unsafe(thr, pop_count);
			DUK_DDD(DUK_DDDPRINT("result: success (buffer data write)"));
			DUK_STATS_INC(thr->heap, stats_putprop_bufferidx);
			return 1;
		}

		if (pop_count == 0) {
			/* This is a pretty awkward control flow, but we need to recheck the
			 * key coercion here.
			 */
			arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
			DUK_ASSERT(key != NULL);
			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a non-fast-path number; after "
			                     "coercion key is %!T, arr_idx %ld",
			                     (duk_tval *) duk_get_tval(thr, -1), (long) arr_idx));
		}

		if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
			goto fail_not_writable;
		}

		DUK_DDD(DUK_DDDPRINT("base object is a buffer, start lookup from Uint8Array prototype"));
		curr = thr->builtins[DUK_BIDX_UINT8ARRAY_PROTOTYPE];
		goto lookup;  /* avoid double coercion */
	}

	case DUK_TAG_POINTER: {
		DUK_DDD(DUK_DDDPRINT("base object is a pointer, start lookup from pointer prototype"));
		curr = thr->builtins[DUK_BIDX_POINTER_PROTOTYPE];
		break;
	}

	case DUK_TAG_LIGHTFUNC: {
		/* Lightfuncs have no own properties and are considered non-extensible.
		 * However, the write may be captured by an inherited setter which
		 * means we can't stop the lookup here.
		 */
		DUK_DDD(DUK_DDDPRINT("base object is a lightfunc, start lookup from function prototype"));
		curr = thr->builtins[DUK_BIDX_NATIVE_FUNCTION_PROTOTYPE];
		break;
	}

#if defined(DUK_USE_FASTINT)
	case DUK_TAG_FASTINT:
#endif
	default: {
		/* number */
		DUK_DDD(DUK_DDDPRINT("base object is a number, start lookup from number prototype"));
		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_obj));
		curr = thr->builtins[DUK_BIDX_NUMBER_PROTOTYPE];
		break;
	}
	}

	DUK_ASSERT(key == NULL);
	arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
	DUK_ASSERT(key != NULL);

 lookup:

	/*
	 *  Check whether the property already exists in the prototype chain.
	 *  Note that the actual write goes into the original base object
	 *  (except if an accessor property captures the write).
	 */

	/* [key] */

	DUK_ASSERT(curr != NULL);
	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
	do {
		if (!duk__get_own_propdesc_raw(thr, curr, key, arr_idx, &desc, 0 /*flags*/)) {  /* don't push value */
			goto next_in_chain;
		}

		if (desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
			/*
			 *  Found existing accessor property (own or inherited).
			 *  Call setter with 'this' set to orig, and value as the only argument.
			 *  Setter calls are OK even for ROM objects.
			 *
			 *  Note: no exotic arguments object behavior, because [[Put]] never
			 *  calls [[DefineOwnProperty]] (E5 Section 8.12.5, step 5.b).
			 */

			duk_hobject *setter;

			DUK_DD(DUK_DDPRINT("put to an own or inherited accessor, calling setter"));

			setter = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, curr, desc.e_idx);
			if (!setter) {
				goto fail_no_setter;
			}
			duk_push_hobject(thr, setter);
			duk_push_tval(thr, tv_obj);  /* note: original, uncoerced base */
			duk_push_tval(thr, tv_val);  /* [key setter this val] */
#if defined(DUK_USE_NONSTD_SETTER_KEY_ARGUMENT)
			duk_dup_m4(thr);
			duk_call_method(thr, 2);     /* [key setter this val key] -> [key retval] */
#else
			duk_call_method(thr, 1);     /* [key setter this val] -> [key retval] */
#endif
			duk_pop_unsafe(thr);         /* ignore retval -> [key] */
			goto success_no_arguments_exotic;
		}

		if (orig == NULL) {
			/*
			 *  Found existing own or inherited plain property, but original
			 *  base is a primitive value.
			 */
			DUK_DD(DUK_DDPRINT("attempt to create a new property in a primitive base object"));
			goto fail_base_primitive;
		}

		if (curr != orig) {
			/*
			 *  Found existing inherited plain property.
			 *  Do an access control check, and if OK, write
			 *  new property to 'orig'.
			 */
			if (!DUK_HOBJECT_HAS_EXTENSIBLE(orig)) {
				DUK_DD(DUK_DDPRINT("found existing inherited plain property, but original object is not extensible"));
				goto fail_not_extensible;
			}
			if (!(desc.flags & DUK_PROPDESC_FLAG_WRITABLE)) {
				DUK_DD(DUK_DDPRINT("found existing inherited plain property, original object is extensible, but inherited property is not writable"));
				goto fail_not_writable;
			}
			DUK_DD(DUK_DDPRINT("put to new property, object extensible, inherited property found and is writable"));
			goto create_new;
		} else {
			/*
			 *  Found existing own (non-inherited) plain property.
			 *  Do an access control check and update in place.
			 */

			if (!(desc.flags & DUK_PROPDESC_FLAG_WRITABLE)) {
				DUK_DD(DUK_DDPRINT("found existing own (non-inherited) plain property, but property is not writable"));
				goto fail_not_writable;
			}
			if (desc.flags & DUK_PROPDESC_FLAG_VIRTUAL) {
				DUK_DD(DUK_DDPRINT("found existing own (non-inherited) virtual property, property is writable"));

				if (DUK_HOBJECT_IS_ARRAY(curr)) {
					/*
					 *  Write to 'length' of an array is a very complex case
					 *  handled in a helper which updates both the array elements
					 *  and writes the new 'length'.  The write may result in an
					 *  unconditional RangeError or a partial write (indicated
					 *  by a return code).
					 *
					 *  Note: the helper has an unnecessary writability check
					 *  for 'length', we already know it is writable.
					 */
					DUK_ASSERT(key == DUK_HTHREAD_STRING_LENGTH(thr));  /* only virtual array property */

					DUK_DDD(DUK_DDDPRINT("writing existing 'length' property to array exotic, invoke complex helper"));

					/* XXX: the helper currently assumes stack top contains new
					 * 'length' value and the whole calling convention is not very
					 * compatible with what we need.
					 */

					duk_push_tval(thr, tv_val);  /* [key val] */
					rc = duk__handle_put_array_length(thr, orig);
					duk_pop_unsafe(thr);  /* [key val] -> [key] */
					if (!rc) {
						goto fail_array_length_partial;
					}

					/* key is 'length', cannot match argument exotic behavior */
					goto success_no_arguments_exotic;
				}
#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
				else if (DUK_HOBJECT_IS_BUFOBJ(curr)) {
					duk_hbufobj *h_bufobj;
					duk_uint_t byte_off;
					duk_small_uint_t elem_size;

					h_bufobj = (duk_hbufobj *) curr;
					DUK_HBUFOBJ_ASSERT_VALID(h_bufobj);

					DUK_DD(DUK_DDPRINT("writable virtual property is in buffer object"));

					/* Careful with wrapping: arr_idx upshift may easily wrap, whereas
					 * length downshift won't.
					 */
					if (arr_idx < (h_bufobj->length >> h_bufobj->shift) && DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h_bufobj)) {
						duk_uint8_t *data;
						DUK_DDD(DUK_DDDPRINT("writing to buffer data at index %ld", (long) arr_idx));

						DUK_ASSERT(arr_idx != DUK__NO_ARRAY_INDEX);  /* index/length check guarantees */
						byte_off = arr_idx << h_bufobj->shift;       /* no wrap assuming h_bufobj->length is valid */
						elem_size = (duk_small_uint_t) (1U << h_bufobj->shift);

						/* Coerce to number before validating pointers etc so that the
						 * number coercions in duk_hbufobj_validated_write() are
						 * guaranteed to be side effect free and not invalidate the
						 * pointer checks we do here.
						 */
						duk_push_tval(thr, tv_val);
						(void) duk_to_number_m1(thr);

						if (h_bufobj->buf != NULL && DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) {
							data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) + h_bufobj->offset + byte_off;
							duk_hbufobj_validated_write(thr, h_bufobj, data, elem_size);
						} else {
							DUK_D(DUK_DPRINT("bufobj access out of underlying buffer, ignoring (write skipped)"));
						}
						duk_pop_unsafe(thr);
						goto success_no_arguments_exotic;
					}
				}
#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */

				DUK_D(DUK_DPRINT("should not happen, key %!O", key));
				goto fail_internal;  /* should not happen */
			}
			DUK_DD(DUK_DDPRINT("put to existing own plain property, property is writable"));
			goto update_old;
		}
		DUK_UNREACHABLE();

	 next_in_chain:
		/* XXX: option to pretend property doesn't exist if sanity limit is
		 * hit might be useful.
		 */
		if (DUK_UNLIKELY(sanity-- == 0)) {
			DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
			DUK_WO_NORETURN(return 0;);
		}
		curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr);
	} while (curr != NULL);

	/*
	 *  Property not found in prototype chain.
	 */

	DUK_DDD(DUK_DDDPRINT("property not found in prototype chain"));

	if (orig == NULL) {
		DUK_DD(DUK_DDPRINT("attempt to create a new property in a primitive base object"));
		goto fail_base_primitive;
	}

	if (!DUK_HOBJECT_HAS_EXTENSIBLE(orig)) {
		DUK_DD(DUK_DDPRINT("put to a new property (not found in prototype chain), but original object not extensible"));
		goto fail_not_extensible;
	}

	goto create_new;

 update_old:

	/*
	 *  Update an existing property of the base object.
	 */

	/* [key] */

	DUK_DDD(DUK_DDDPRINT("update an existing property of the original object"));

	DUK_ASSERT(orig != NULL);
#if defined(DUK_USE_ROM_OBJECTS)
	/* This should not happen because DUK_TAG_OBJECT case checks
	 * for this already, but check just in case.
	 */
	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) orig)) {
		goto fail_not_writable;
	}
#endif

	/* Although there are writable virtual properties (e.g. plain buffer
	 * and buffer object number indices), they are handled before we come
	 * here.
	 */
	DUK_ASSERT((desc.flags & DUK_PROPDESC_FLAG_VIRTUAL) == 0);
	DUK_ASSERT(desc.a_idx >= 0 || desc.e_idx >= 0);

	/* Array own property .length is handled above. */
	DUK_ASSERT(!(DUK_HOBJECT_IS_ARRAY(orig) && key == DUK_HTHREAD_STRING_LENGTH(thr)));

	if (desc.e_idx >= 0) {
		tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, orig, desc.e_idx);
		DUK_DDD(DUK_DDDPRINT("previous entry value: %!iT", (duk_tval *) tv));
		DUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv_val);  /* side effects; e_idx may be invalidated */
		/* don't touch property attributes or hash part */
		DUK_DD(DUK_DDPRINT("put to an existing entry at index %ld -> new value %!iT",
		                   (long) desc.e_idx, (duk_tval *) tv));
	} else {
		/* Note: array entries are always writable, so the writability check
		 * above is pointless for them.  The check could be avoided with some
		 * refactoring but is probably not worth it.
		 */

		DUK_ASSERT(desc.a_idx >= 0);
		tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, orig, desc.a_idx);
		DUK_DDD(DUK_DDDPRINT("previous array value: %!iT", (duk_tval *) tv));
		DUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv_val);  /* side effects; a_idx may be invalidated */
		DUK_DD(DUK_DDPRINT("put to an existing array entry at index %ld -> new value %!iT",
		                   (long) desc.a_idx, (duk_tval *) tv));
	}

	/* Regardless of whether property is found in entry or array part,
	 * it may have arguments exotic behavior (array indices may reside
	 * in entry part for abandoned / non-existent array parts).
	 */
	goto success_with_arguments_exotic;

 create_new:

	/*
	 *  Create a new property in the original object.
	 *
	 *  Exotic properties need to be reconsidered here from a write
	 *  perspective (not just property attributes perspective).
	 *  However, the property does not exist in the object already,
	 *  so this limits the kind of exotic properties that apply.
	 */

	/* [key] */

	DUK_DDD(DUK_DDDPRINT("create new property to original object"));

	DUK_ASSERT(orig != NULL);

	/* Array own property .length is handled above. */
	DUK_ASSERT(!(DUK_HOBJECT_IS_ARRAY(orig) && key == DUK_HTHREAD_STRING_LENGTH(thr)));

#if defined(DUK_USE_ROM_OBJECTS)
	/* This should not happen because DUK_TAG_OBJECT case checks
	 * for this already, but check just in case.
	 */
	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) orig)) {
		goto fail_not_writable;
	}
#endif

	/* Not possible because array object 'length' is present
	 * from its creation and cannot be deleted, and is thus
	 * caught as an existing property above.
	 */
	DUK_ASSERT(!(DUK_HOBJECT_HAS_EXOTIC_ARRAY(orig) &&
	             key == DUK_HTHREAD_STRING_LENGTH(thr)));

	if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(orig) &&
	    arr_idx != DUK__NO_ARRAY_INDEX) {
		/* automatic length update */
		duk_uint32_t old_len;
		duk_harray *a;

		a = (duk_harray *) orig;
		DUK_HARRAY_ASSERT_VALID(a);

		old_len = a->length;

		if (arr_idx >= old_len) {
			DUK_DDD(DUK_DDDPRINT("write new array entry requires length update "
			                     "(arr_idx=%ld, old_len=%ld)",
			                     (long) arr_idx, (long) old_len));

			if (DUK_HARRAY_LENGTH_NONWRITABLE(a)) {
				DUK_DD(DUK_DDPRINT("attempt to extend array, but array 'length' is not writable"));
				goto fail_not_writable;
			}

			/* Note: actual update happens once write has been completed
			 * without error below.  The write should always succeed
			 * from a specification viewpoint, but we may e.g. run out
			 * of memory.  It's safer in this order.
			 */

			DUK_ASSERT(arr_idx != 0xffffffffUL);
			new_array_length = arr_idx + 1;  /* flag for later write */
		} else {
			DUK_DDD(DUK_DDDPRINT("write new array entry does not require length update "
			                     "(arr_idx=%ld, old_len=%ld)",
			                     (long) arr_idx, (long) old_len));
		}
	}

 /* write_to_array_part: */

	/*
	 *  Write to array part?
	 *
	 *  Note: array abandonding requires a property resize which uses
	 *  'rechecks' valstack for temporaries and may cause any existing
	 *  valstack pointers to be invalidated.  To protect against this,
	 *  tv_obj, tv_key, and tv_val are copies of the original inputs.
	 */

	if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HOBJECT_HAS_ARRAY_PART(orig)) {
		tv = duk__obtain_arridx_slot(thr, arr_idx, orig);
		if (tv == NULL) {
			DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(orig));
			goto write_to_entry_part;
		}

		/* prev value must be unused, no decref */
		DUK_ASSERT(DUK_TVAL_IS_UNUSED(tv));
		DUK_TVAL_SET_TVAL(tv, tv_val);
		DUK_TVAL_INCREF(thr, tv);
		DUK_DD(DUK_DDPRINT("put to new array entry: %ld -> %!T",
		                   (long) arr_idx, (duk_tval *) tv));

		/* Note: array part values are [[Writable]], [[Enumerable]],
		 * and [[Configurable]] which matches the required attributes
		 * here.
		 */
		goto entry_updated;
	}

 write_to_entry_part:

	/*
	 *  Write to entry part
	 */

	/* entry allocation updates hash part and increases the key
	 * refcount; may need a props allocation resize but doesn't
	 * 'recheck' the valstack.
	 */
	e_idx = duk__hobject_alloc_entry_checked(thr, orig, key);
	DUK_ASSERT(e_idx >= 0);

	tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, orig, e_idx);
	/* prev value can be garbage, no decref */
	DUK_TVAL_SET_TVAL(tv, tv_val);
	DUK_TVAL_INCREF(thr, tv);
	DUK_HOBJECT_E_SET_FLAGS(thr->heap, orig, e_idx, DUK_PROPDESC_FLAGS_WEC);
	goto entry_updated;

 entry_updated:

	/*
	 *  Possible pending array length update, which must only be done
	 *  if the actual entry write succeeded.
	 */

	if (new_array_length > 0) {
		/* Note: zero works as a "no update" marker because the new length
		 * can never be zero after a new property is written.
		 */

		DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY(orig));

		DUK_DDD(DUK_DDDPRINT("write successful, pending array length update to: %ld",
		                     (long) new_array_length));

		((duk_harray *) orig)->length = new_array_length;
	}

	/*
	 *  Arguments exotic behavior not possible for new properties: all
	 *  magically bound properties are initially present in the arguments
	 *  object, and if they are deleted, the binding is also removed from
	 *  parameter map.
	 */

	goto success_no_arguments_exotic;

 success_with_arguments_exotic:

	/*
	 *  Arguments objects have exotic [[DefineOwnProperty]] which updates
	 *  the internal 'map' of arguments for writes to currently mapped
	 *  arguments.  More conretely, writes to mapped arguments generate
	 *  a write to a bound variable.
	 *
	 *  The [[Put]] algorithm invokes [[DefineOwnProperty]] for existing
	 *  data properties and new properties, but not for existing accessors.
	 *  Hence, in E5 Section 10.6 ([[DefinedOwnProperty]] algorithm), we
	 *  have a Desc with 'Value' (and possibly other properties too), and
	 *  we end up in step 5.b.i.
	 */

	if (arr_idx != DUK__NO_ARRAY_INDEX &&
	    DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(orig)) {
		/* Note: only numbered indices are relevant, so arr_idx fast reject
		 * is good (this is valid unless there are more than 4**32-1 arguments).
		 */

		DUK_DDD(DUK_DDDPRINT("putprop successful, arguments exotic behavior needed"));

		/* Note: we can reuse 'desc' here */

		/* XXX: top of stack must contain value, which helper doesn't touch,
		 * rework to use tv_val directly?
		 */

		duk_push_tval(thr, tv_val);
		(void) duk__check_arguments_map_for_put(thr, orig, key, &desc, throw_flag);
		duk_pop_unsafe(thr);
	}
	/* fall thru */

 success_no_arguments_exotic:
	/* shared exit path now */
	DUK_DDD(DUK_DDDPRINT("result: success"));
	duk_pop_unsafe(thr);  /* remove key */
	return 1;

#if defined(DUK_USE_ES6_PROXY)
 fail_proxy_rejected:
	DUK_DDD(DUK_DDDPRINT("result: error, proxy rejects"));
	if (throw_flag) {
		DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);
		DUK_WO_NORETURN(return 0;);
	}
	/* Note: no key on stack */
	return 0;
#endif

 fail_base_primitive:
	DUK_DDD(DUK_DDDPRINT("result: error, base primitive"));
	if (throw_flag) {
#if defined(DUK_USE_PARANOID_ERRORS)
		DUK_ERROR_TYPE(thr, DUK_STR_INVALID_BASE);
#else
		DUK_ERROR_FMT2(thr, DUK_ERR_TYPE_ERROR, "cannot write property %s of %s",
		               duk_push_string_tval_readable(thr, tv_key), duk_push_string_tval_readable(thr, tv_obj));
#endif
		DUK_WO_NORETURN(return 0;);
	}
	duk_pop_unsafe(thr);  /* remove key */
	return 0;

 fail_not_extensible:
	DUK_DDD(DUK_DDDPRINT("result: error, not extensible"));
	if (throw_flag) {
		DUK_ERROR_TYPE(thr, DUK_STR_NOT_EXTENSIBLE);
		DUK_WO_NORETURN(return 0;);
	}
	duk_pop_unsafe(thr);  /* remove key */
	return 0;

 fail_not_writable:
	DUK_DDD(DUK_DDDPRINT("result: error, not writable"));
	if (throw_flag) {
		DUK_ERROR_TYPE(thr, DUK_STR_NOT_WRITABLE);
		DUK_WO_NORETURN(return 0;);
	}
	duk_pop_unsafe(thr);  /* remove key */
	return 0;

#if defined(DUK_USE_ROM_OBJECTS)
 fail_not_writable_no_pop:
	DUK_DDD(DUK_DDDPRINT("result: error, not writable"));
	if (throw_flag) {
		DUK_ERROR_TYPE(thr, DUK_STR_NOT_WRITABLE);
		DUK_WO_NORETURN(return 0;);
	}
	return 0;
#endif

 fail_array_length_partial:
	DUK_DD(DUK_DDPRINT("result: error, array length write only partially successful"));
	if (throw_flag) {
		DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);
		DUK_WO_NORETURN(return 0;);
	}
	duk_pop_unsafe(thr);  /* remove key */
	return 0;

 fail_no_setter:
	DUK_DDD(DUK_DDDPRINT("result: error, accessor property without setter"));
	if (throw_flag) {
		DUK_ERROR_TYPE(thr, DUK_STR_SETTER_UNDEFINED);
		DUK_WO_NORETURN(return 0;);
	}
	duk_pop_unsafe(thr);  /* remove key */
	return 0;

 fail_internal:
	DUK_DDD(DUK_DDDPRINT("result: error, internal"));
	if (throw_flag) {
		DUK_ERROR_INTERNAL(thr);
		DUK_WO_NORETURN(return 0;);
	}
	duk_pop_unsafe(thr);  /* remove key */
	return 0;
}

/*
 *  ECMAScript compliant [[Delete]](P, Throw).
 */

DUK_INTERNAL duk_bool_t duk_hobject_delprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags) {
	duk_propdesc desc;
	duk_tval *tv;
	duk_uint32_t arr_idx;
	duk_bool_t throw_flag;
	duk_bool_t force_flag;

	throw_flag = (flags & DUK_DELPROP_FLAG_THROW);
	force_flag = (flags & DUK_DELPROP_FLAG_FORCE);

	DUK_DDD(DUK_DDDPRINT("delprop_raw: thr=%p, obj=%p, key=%p, throw=%ld, force=%ld (obj -> %!O, key -> %!O)",
	                     (void *) thr, (void *) obj, (void *) key, (long) throw_flag, (long) force_flag,
	                     (duk_heaphdr *) obj, (duk_heaphdr *) key));

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(thr->heap != NULL);
	DUK_ASSERT(obj != NULL);
	DUK_ASSERT(key != NULL);

	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);

	arr_idx = DUK_HSTRING_GET_ARRIDX_FAST(key);

	/* 0 = don't push current value */
	if (!duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &desc, 0 /*flags*/)) {  /* don't push value */
		DUK_DDD(DUK_DDDPRINT("property not found, succeed always"));
		goto success;
	}

#if defined(DUK_USE_ROM_OBJECTS)
	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {
		DUK_DD(DUK_DDPRINT("attempt to delprop on read-only target object"));
		goto fail_not_configurable;
	}
#endif

	if ((desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) == 0 && !force_flag) {
		goto fail_not_configurable;
	}
	if (desc.a_idx < 0 && desc.e_idx < 0) {
		/* Currently there are no deletable virtual properties, but
		 * with force_flag we might attempt to delete one.
		 */
		DUK_DD(DUK_DDPRINT("delete failed: property found, force flag, but virtual (and implicitly non-configurable)"));
		goto fail_virtual;
	}

	if (desc.a_idx >= 0) {
		DUK_ASSERT(desc.e_idx < 0);

		tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, desc.a_idx);
		DUK_TVAL_SET_UNUSED_UPDREF(thr, tv);  /* side effects */
		goto success;
	} else {
		DUK_ASSERT(desc.a_idx < 0);

		/* remove hash entry (no decref) */
#if defined(DUK_USE_HOBJECT_HASH_PART)
		if (desc.h_idx >= 0) {
			duk_uint32_t *h_base = DUK_HOBJECT_H_GET_BASE(thr->heap, obj);

			DUK_DDD(DUK_DDDPRINT("removing hash entry at h_idx %ld", (long) desc.h_idx));
			DUK_ASSERT(DUK_HOBJECT_GET_HSIZE(obj) > 0);
			DUK_ASSERT((duk_uint32_t) desc.h_idx < DUK_HOBJECT_GET_HSIZE(obj));
			h_base[desc.h_idx] = DUK__HASH_DELETED;
		} else {
			DUK_ASSERT(DUK_HOBJECT_GET_HSIZE(obj) == 0);
		}
#else
		DUK_ASSERT(DUK_HOBJECT_GET_HSIZE(obj) == 0);
#endif

		/* Remove value.  This requires multiple writes so avoid side
		 * effects via no-refzero macros so that e_idx is not
		 * invalidated.
		 */
		DUK_DDD(DUK_DDDPRINT("before removing value, e_idx %ld, key %p, key at slot %p",
		                     (long) desc.e_idx, (void *) key, (void *) DUK_HOBJECT_E_GET_KEY(thr->heap, obj, desc.e_idx)));
		DUK_DDD(DUK_DDDPRINT("removing value at e_idx %ld", (long) desc.e_idx));
		if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, desc.e_idx)) {
			duk_hobject *tmp;

			tmp = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, obj, desc.e_idx);
			DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, desc.e_idx, NULL);
			DUK_UNREF(tmp);
			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, tmp);

			tmp = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, obj, desc.e_idx);
			DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, desc.e_idx, NULL);
			DUK_UNREF(tmp);
			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, tmp);
		} else {
			tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, desc.e_idx);
			DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ(thr, tv);
		}
#if 0
		/* Not strictly necessary because if key == NULL, flag MUST be ignored. */
		DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, desc.e_idx, 0);
#endif

		/* Remove key. */
		DUK_DDD(DUK_DDDPRINT("before removing key, e_idx %ld, key %p, key at slot %p",
		                     (long) desc.e_idx, (void *) key, (void *) DUK_HOBJECT_E_GET_KEY(thr->heap, obj, desc.e_idx)));
		DUK_DDD(DUK_DDDPRINT("removing key at e_idx %ld", (long) desc.e_idx));
		DUK_ASSERT(key == DUK_HOBJECT_E_GET_KEY(thr->heap, obj, desc.e_idx));
		DUK_HOBJECT_E_SET_KEY(thr->heap, obj, desc.e_idx, NULL);
		DUK_HSTRING_DECREF_NORZ(thr, key);

		/* Trigger refzero side effects only when we're done as a
		 * finalizer might operate on the object and affect the
		 * e_idx we're supposed to use.
		 */
		DUK_REFZERO_CHECK_SLOW(thr);
		goto success;
	}

	DUK_UNREACHABLE();

 success:
	/*
	 *  Argument exotic [[Delete]] behavior (E5 Section 10.6) is
	 *  a post-check, keeping arguments internal 'map' in sync with
	 *  any successful deletes (note that property does not need to
	 *  exist for delete to 'succeed').
	 *
	 *  Delete key from 'map'.  Since 'map' only contains array index
	 *  keys, we can use arr_idx for a fast skip.
	 */

	DUK_DDD(DUK_DDDPRINT("delete successful, check for arguments exotic behavior"));

	if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj)) {
		/* Note: only numbered indices are relevant, so arr_idx fast reject
		 * is good (this is valid unless there are more than 4**32-1 arguments).
		 */

		DUK_DDD(DUK_DDDPRINT("delete successful, arguments exotic behavior needed"));

		/* Note: we can reuse 'desc' here */
		(void) duk__check_arguments_map_for_delete(thr, obj, key, &desc);
	}

	DUK_DDD(DUK_DDDPRINT("delete successful"));
	return 1;

 fail_virtual:  /* just use the same "not configurable" error message */
 fail_not_configurable:
	DUK_DDD(DUK_DDDPRINT("delete failed: property found, not configurable"));

	if (throw_flag) {
		DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);
		DUK_WO_NORETURN(return 0;);
	}
	return 0;
}

/*
 *  DELPROP: ECMAScript property deletion.
 */

DUK_INTERNAL duk_bool_t duk_hobject_delprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key, duk_bool_t throw_flag) {
	duk_hstring *key = NULL;
#if defined(DUK_USE_ES6_PROXY)
	duk_propdesc desc;
#endif
	duk_int_t entry_top;
	duk_uint32_t arr_idx = DUK__NO_ARRAY_INDEX;
	duk_bool_t rc;

	DUK_DDD(DUK_DDDPRINT("delprop: thr=%p, obj=%p, key=%p (obj -> %!T, key -> %!T)",
	                     (void *) thr, (void *) tv_obj, (void *) tv_key,
	                     (duk_tval *) tv_obj, (duk_tval *) tv_key));

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(thr->heap != NULL);
	DUK_ASSERT(tv_obj != NULL);
	DUK_ASSERT(tv_key != NULL);

	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);

	/* Storing the entry top is cheaper here to ensure stack is correct at exit,
	 * as there are several paths out.
	 */
	entry_top = duk_get_top(thr);

	if (DUK_TVAL_IS_UNDEFINED(tv_obj) ||
	    DUK_TVAL_IS_NULL(tv_obj)) {
		DUK_DDD(DUK_DDDPRINT("base object is undefined or null -> reject"));
		goto fail_invalid_base_uncond;
	}

	duk_push_tval(thr, tv_obj);
	duk_push_tval(thr, tv_key);

	tv_obj = DUK_GET_TVAL_NEGIDX(thr, -2);
	if (DUK_TVAL_IS_OBJECT(tv_obj)) {
		duk_hobject *obj = DUK_TVAL_GET_OBJECT(tv_obj);
		DUK_ASSERT(obj != NULL);

#if defined(DUK_USE_ES6_PROXY)
		if (DUK_UNLIKELY(DUK_HOBJECT_IS_PROXY(obj))) {
			duk_hobject *h_target;
			duk_bool_t tmp_bool;

			/* Note: proxy handling must happen before key is string coerced. */

			if (duk__proxy_check_prop(thr, obj, DUK_STRIDX_DELETE_PROPERTY, tv_key, &h_target)) {
				/* -> [ ... obj key trap handler ] */
				DUK_DDD(DUK_DDDPRINT("-> proxy object 'deleteProperty' for key %!T", (duk_tval *) tv_key));
				duk_push_hobject(thr, h_target);  /* target */
				duk_dup_m4(thr);  /* P */
				duk_call_method(thr, 2 /*nargs*/);
				tmp_bool = duk_to_boolean_top_pop(thr);
				if (!tmp_bool) {
					goto fail_proxy_rejected;  /* retval indicates delete failed */
				}

				/* Target object must be checked for a conflicting
				 * non-configurable property.
				 */
				tv_key = DUK_GET_TVAL_NEGIDX(thr, -1);
				arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
				DUK_ASSERT(key != NULL);

				if (duk__get_own_propdesc_raw(thr, h_target, key, arr_idx, &desc, 0 /*flags*/)) {  /* don't push value */
					duk_small_int_t desc_reject;

					DUK_DDD(DUK_DDDPRINT("proxy 'deleteProperty': target has matching property %!O, check for "
					                     "conflicting property; desc.flags=0x%08lx, "
					                     "desc.get=%p, desc.set=%p",
					                     (duk_heaphdr *) key, (unsigned long) desc.flags,
					                     (void *) desc.get, (void *) desc.set));

					desc_reject = !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE);
					if (desc_reject) {
						/* unconditional */
						DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);
						DUK_WO_NORETURN(return 0;);
					}
				}
				rc = 1;  /* success */
				goto done_rc;
			}

			obj = h_target;  /* resume delete to target */
		}
#endif  /* DUK_USE_ES6_PROXY */

		arr_idx = duk__to_property_key(thr, -1, &key);
		DUK_ASSERT(key != NULL);

		rc = duk_hobject_delprop_raw(thr, obj, key, throw_flag ? DUK_DELPROP_FLAG_THROW : 0);
		goto done_rc;
	} else if (DUK_TVAL_IS_STRING(tv_obj)) {
		/* String has .length and array index virtual properties
		 * which can't be deleted.  No need for a symbol check;
		 * no offending virtual symbols exist.
		 */
		/* XXX: unnecessary string coercion for array indices,
		 * intentional to keep small.
		 */
		duk_hstring *h = DUK_TVAL_GET_STRING(tv_obj);
		DUK_ASSERT(h != NULL);

		arr_idx = duk__to_property_key(thr, -1, &key);
		DUK_ASSERT(key != NULL);

		if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
			goto fail_not_configurable;
		}

		if (arr_idx != DUK__NO_ARRAY_INDEX &&
		    arr_idx < DUK_HSTRING_GET_CHARLEN(h)) {
			goto fail_not_configurable;
		}
	} else if (DUK_TVAL_IS_BUFFER(tv_obj)) {
		/* XXX: unnecessary string coercion for array indices,
		 * intentional to keep small; some overlap with string
		 * handling.
		 */
		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv_obj);
		DUK_ASSERT(h != NULL);

		arr_idx = duk__to_property_key(thr, -1, &key);
		DUK_ASSERT(key != NULL);

		if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
			goto fail_not_configurable;
		}

		if (arr_idx != DUK__NO_ARRAY_INDEX &&
		    arr_idx < DUK_HBUFFER_GET_SIZE(h)) {
			goto fail_not_configurable;
		}
	} else if (DUK_TVAL_IS_LIGHTFUNC(tv_obj)) {
		/* Lightfunc has no virtual properties since Duktape 2.2
		 * so success.  Still must coerce key for side effects.
		 */

		arr_idx = duk__to_property_key(thr, -1, &key);
		DUK_ASSERT(key != NULL);
		DUK_UNREF(key);
	}

	/* non-object base, no offending virtual property */
	rc = 1;
	goto done_rc;

 done_rc:
	duk_set_top_unsafe(thr, entry_top);
	return rc;

 fail_invalid_base_uncond:
	/* Note: unconditional throw */
	DUK_ASSERT(duk_get_top(thr) == entry_top);
#if defined(DUK_USE_PARANOID_ERRORS)
	DUK_ERROR_TYPE(thr, DUK_STR_INVALID_BASE);
#else
	DUK_ERROR_FMT2(thr, DUK_ERR_TYPE_ERROR, "cannot delete property %s of %s",
	               duk_push_string_tval_readable(thr, tv_key), duk_push_string_tval_readable(thr, tv_obj));
#endif
	DUK_WO_NORETURN(return 0;);

#if defined(DUK_USE_ES6_PROXY)
 fail_proxy_rejected:
	if (throw_flag) {
		DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);
		DUK_WO_NORETURN(return 0;);
	}
	duk_set_top_unsafe(thr, entry_top);
	return 0;
#endif

 fail_not_configurable:
	if (throw_flag) {
		DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);
		DUK_WO_NORETURN(return 0;);
	}
	duk_set_top_unsafe(thr, entry_top);
	return 0;
}

/*
 *  Internal helper to define a property with specific flags, ignoring
 *  normal semantics such as extensibility, write protection etc.
 *  Overwrites any existing value and attributes unless caller requests
 *  that value only be updated if it doesn't already exists.
 *
 *  Does not support:
 *    - virtual properties (error if write attempted)
 *    - getter/setter properties (error if write attempted)
 *    - non-default (!= WEC) attributes for array entries (error if attempted)
 *    - array abandoning: if array part exists, it is always extended
 *    - array 'length' updating
 *
 *  Stack: [... in_val] -> []
 *
 *  Used for e.g. built-in initialization and environment record
 *  operations.
 */

DUK_INTERNAL void duk_hobject_define_property_internal(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags) {
	duk_propdesc desc;
	duk_uint32_t arr_idx;
	duk_int_t e_idx;
	duk_tval *tv1 = NULL;
	duk_tval *tv2 = NULL;
	duk_small_uint_t propflags = flags & DUK_PROPDESC_FLAGS_MASK;  /* mask out flags not actually stored */

	DUK_DDD(DUK_DDDPRINT("define new property (internal): thr=%p, obj=%!O, key=%!O, flags=0x%02lx, val=%!T",
	                     (void *) thr, (duk_heaphdr *) obj, (duk_heaphdr *) key,
	                     (unsigned long) flags, (duk_tval *) duk_get_tval(thr, -1)));

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(thr->heap != NULL);
	DUK_ASSERT(obj != NULL);
	DUK_ASSERT(key != NULL);
	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));
	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
	DUK_ASSERT(duk_is_valid_index(thr, -1));  /* contains value */

	arr_idx = DUK_HSTRING_GET_ARRIDX_SLOW(key);

	if (duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &desc, 0 /*flags*/)) {  /* don't push value */
		if (desc.e_idx >= 0) {
			if (flags & DUK_PROPDESC_FLAG_NO_OVERWRITE) {
				DUK_DDD(DUK_DDDPRINT("property already exists in the entry part -> skip as requested"));
				goto pop_exit;
			}
			DUK_DDD(DUK_DDDPRINT("property already exists in the entry part -> update value and attributes"));
			if (DUK_UNLIKELY(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, desc.e_idx))) {
				DUK_D(DUK_DPRINT("existing property is an accessor, not supported"));
				goto error_internal;
			}

			DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, desc.e_idx, propflags);
			tv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, desc.e_idx);
		} else if (desc.a_idx >= 0) {
			if (flags & DUK_PROPDESC_FLAG_NO_OVERWRITE) {
				DUK_DDD(DUK_DDDPRINT("property already exists in the array part -> skip as requested"));
				goto pop_exit;
			}
			DUK_DDD(DUK_DDDPRINT("property already exists in the array part -> update value (assert attributes)"));
			if (propflags != DUK_PROPDESC_FLAGS_WEC) {
				DUK_D(DUK_DPRINT("existing property in array part, but propflags not WEC (0x%02lx)",
				                 (unsigned long) propflags));
				goto error_internal;
			}

			tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, desc.a_idx);
		} else {
			if (flags & DUK_PROPDESC_FLAG_NO_OVERWRITE) {
				DUK_DDD(DUK_DDDPRINT("property already exists but is virtual -> skip as requested"));
				goto pop_exit;
			}
			if (key == DUK_HTHREAD_STRING_LENGTH(thr) && DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {
				duk_uint32_t new_len;
#if defined(DUK_USE_DEBUG)
				duk_uint32_t prev_len;
				prev_len = ((duk_harray *) obj)->length;
#endif
				new_len = duk__to_new_array_length_checked(thr, DUK_GET_TVAL_NEGIDX(thr, -1));
				((duk_harray *) obj)->length = new_len;
				DUK_DD(DUK_DDPRINT("internal define property for array .length: %ld -> %ld",
				                   (long) prev_len, (long) ((duk_harray *) obj)->length));
				goto pop_exit;
			}
			DUK_DD(DUK_DDPRINT("property already exists but is virtual -> failure"));
			goto error_virtual;
		}

		goto write_value;
	}

	if (DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
		if (arr_idx != DUK__NO_ARRAY_INDEX) {
			DUK_DDD(DUK_DDDPRINT("property does not exist, object has array part -> possibly extend array part and write value (assert attributes)"));
			DUK_ASSERT(propflags == DUK_PROPDESC_FLAGS_WEC);

			tv1 = duk__obtain_arridx_slot(thr, arr_idx, obj);
			if (tv1 == NULL) {
				DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(obj));
				goto write_to_entry_part;
			}

			tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, arr_idx);
			goto write_value;
		}
	}

 write_to_entry_part:
	DUK_DDD(DUK_DDDPRINT("property does not exist, object belongs in entry part -> allocate new entry and write value and attributes"));
	e_idx = duk__hobject_alloc_entry_checked(thr, obj, key);  /* increases key refcount */
	DUK_ASSERT(e_idx >= 0);
	DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, e_idx, propflags);
	tv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, e_idx);
	/* new entry: previous value is garbage; set to undefined to share write_value */
	DUK_TVAL_SET_UNDEFINED(tv1);
	goto write_value;

 write_value:
	/* tv1 points to value storage */

	tv2 = duk_require_tval(thr, -1);  /* late lookup, avoid side effects */
	DUK_DDD(DUK_DDDPRINT("writing/updating value: %!T -> %!T",
	                     (duk_tval *) tv1, (duk_tval *) tv2));

	DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2);  /* side effects */
	goto pop_exit;

 pop_exit:
	duk_pop_unsafe(thr);  /* remove in_val */
	return;

 error_virtual:  /* share error message */
 error_internal:
	DUK_ERROR_INTERNAL(thr);
	DUK_WO_NORETURN(return;);
}

/*
 *  Fast path for defining array indexed values without interning the key.
 *  This is used by e.g. code for Array prototype and traceback creation so
 *  must avoid interning.
 */

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) {
	duk_hstring *key;
	duk_tval *tv1, *tv2;

	DUK_DDD(DUK_DDDPRINT("define new property (internal) arr_idx fast path: thr=%p, obj=%!O, "
	                     "arr_idx=%ld, flags=0x%02lx, val=%!T",
	                     (void *) thr, obj, (long) arr_idx, (unsigned long) flags,
	                     (duk_tval *) duk_get_tval(thr, -1)));

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(thr->heap != NULL);
	DUK_ASSERT(obj != NULL);
	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));

	if (DUK_HOBJECT_HAS_ARRAY_PART(obj) &&
	    arr_idx != DUK__NO_ARRAY_INDEX &&
	    flags == DUK_PROPDESC_FLAGS_WEC) {
		DUK_ASSERT((flags & DUK_PROPDESC_FLAG_NO_OVERWRITE) == 0);  /* covered by comparison */

		DUK_DDD(DUK_DDDPRINT("define property to array part (property may or may not exist yet)"));

		tv1 = duk__obtain_arridx_slot(thr, arr_idx, obj);
		if (tv1 == NULL) {
			DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(obj));
			goto write_slow;
		}
		tv2 = duk_require_tval(thr, -1);

		DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2);  /* side effects */

		duk_pop_unsafe(thr);  /* [ ...val ] -> [ ... ] */
		return;
	}

 write_slow:
	DUK_DDD(DUK_DDDPRINT("define property fast path didn't work, use slow path"));

	key = duk_push_uint_to_hstring(thr, (duk_uint_t) arr_idx);
	DUK_ASSERT(key != NULL);
	duk_insert(thr, -2);  /* [ ... val key ] -> [ ... key val ] */

	duk_hobject_define_property_internal(thr, obj, key, flags);

	duk_pop_unsafe(thr);  /* [ ... key ] -> [ ... ] */
}

/*
 *  Internal helpers for managing object 'length'
 */

DUK_INTERNAL duk_size_t duk_hobject_get_length(duk_hthread *thr, duk_hobject *obj) {
	duk_double_t val;

	DUK_CTX_ASSERT_VALID(thr);
	DUK_ASSERT(obj != NULL);

	/* Fast path for Arrays. */
	if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {
		return ((duk_harray *) obj)->length;
	}

	/* Slow path, .length can be e.g. accessor, obj can be a Proxy, etc. */
	duk_push_hobject(thr, obj);
	duk_push_hstring_stridx(thr, DUK_STRIDX_LENGTH);
	(void) duk_hobject_getprop(thr,
	                           DUK_GET_TVAL_NEGIDX(thr, -2),
	                           DUK_GET_TVAL_NEGIDX(thr, -1));
	val = duk_to_number_m1(thr);
	duk_pop_3_unsafe(thr);

	/* This isn't part of ECMAScript semantics; return a value within
	 * duk_size_t range, or 0 otherwise.
	 */
	if (val >= 0.0 && val <= (duk_double_t) DUK_SIZE_MAX) {
		return (duk_size_t) val;
	}
	return 0;
}

/*
 *  Fast finalizer check for an object.  Walks the prototype chain, checking
 *  for finalizer presence using DUK_HOBJECT_FLAG_HAVE_FINALIZER which is kept
 *  in sync with the actual property when setting/removing the finalizer.
 */

#if defined(DUK_USE_HEAPPTR16)
DUK_INTERNAL duk_bool_t duk_hobject_has_finalizer_fast_raw(duk_heap *heap, duk_hobject *obj) {
#else
DUK_INTERNAL duk_bool_t duk_hobject_has_finalizer_fast_raw(duk_hobject *obj) {
#endif
	duk_uint_t sanity;

	DUK_ASSERT(obj != NULL);

	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
	do {
		if (DUK_UNLIKELY(DUK_HOBJECT_HAS_HAVE_FINALIZER(obj))) {
			return 1;
		}
		if (DUK_UNLIKELY(sanity-- == 0)) {
			DUK_D(DUK_DPRINT("prototype loop when checking for finalizer existence; returning false"));
			return 0;
		}
#if defined(DUK_USE_HEAPPTR16)
		DUK_ASSERT(heap != NULL);
		obj = DUK_HOBJECT_GET_PROTOTYPE(heap, obj);
#else
		obj = DUK_HOBJECT_GET_PROTOTYPE(NULL, obj);  /* 'heap' arg ignored */
#endif
	} while (obj != NULL);

	return 0;
}

/*
 *  Object.getOwnPropertyDescriptor()  (E5 Sections 15.2.3.3, 8.10.4)
 *
 *  [ ... key ] -> [ ... desc/undefined ]
 */

DUK_INTERNAL void duk_hobject_object_get_own_property_descriptor(duk_hthread *thr, duk_idx_t obj_idx) {
	duk_hobject *obj;
	duk_hstring *key;
	duk_propdesc pd;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(thr->heap != NULL);

	obj = duk_require_hobject_promote_mask(thr, obj_idx, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
	key = duk_to_property_key_hstring(thr, -1);
	DUK_ASSERT(key != NULL);

	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);

	if (!duk_hobject_get_own_propdesc(thr, obj, key, &pd, DUK_GETDESC_FLAG_PUSH_VALUE)) {
		duk_push_undefined(thr);
		duk_remove_m2(thr);
		return;
	}

	duk_push_object(thr);

	/* [ ... key value desc ] */

	if (DUK_PROPDESC_IS_ACCESSOR(&pd)) {
		/* If a setter/getter is missing (undefined), the descriptor must
		 * still have the property present with the value 'undefined'.
		 */
		if (pd.get) {
			duk_push_hobject(thr, pd.get);
		} else {
			duk_push_undefined(thr);
		}
		duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_GET);
		if (pd.set) {
			duk_push_hobject(thr, pd.set);
		} else {
			duk_push_undefined(thr);
		}
		duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_SET);
	} else {
		duk_dup_m2(thr);
		duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_VALUE);
		duk_push_boolean(thr, DUK_PROPDESC_IS_WRITABLE(&pd));
		duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_WRITABLE);
	}
	duk_push_boolean(thr, DUK_PROPDESC_IS_ENUMERABLE(&pd));
	duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_ENUMERABLE);
	duk_push_boolean(thr, DUK_PROPDESC_IS_CONFIGURABLE(&pd));
	duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_CONFIGURABLE);

	/* [ ... key value desc ] */

	duk_replace(thr, -3);
	duk_pop_unsafe(thr);  /* -> [ ... desc ] */
}

/*
 *  NormalizePropertyDescriptor() related helper.
 *
 *  Internal helper which validates and normalizes a property descriptor
 *  represented as an ECMAScript object (e.g. argument to defineProperty()).
 *  The output of this conversion is a set of defprop_flags and possibly
 *  some values pushed on the value stack to (1) ensure borrowed pointers
 *  remain valid, and (2) avoid unnecessary pops for footprint reasons.
 *  Caller must manage stack top carefully because the number of values
 *  pushed depends on the input property descriptor.
 *
 *  The original descriptor object must not be altered in the process.
 */

/* XXX: very basic optimization -> duk_get_prop_stridx_top */

DUK_INTERNAL
void duk_hobject_prepare_property_descriptor(duk_hthread *thr,
                                             duk_idx_t idx_in,
                                             duk_uint_t *out_defprop_flags,
                                             duk_idx_t *out_idx_value,
                                             duk_hobject **out_getter,
                                             duk_hobject **out_setter) {
	duk_idx_t idx_value = -1;
	duk_hobject *getter = NULL;
	duk_hobject *setter = NULL;
	duk_bool_t is_data_desc = 0;
	duk_bool_t is_acc_desc = 0;
	duk_uint_t defprop_flags = 0;

	DUK_ASSERT(out_defprop_flags != NULL);
	DUK_ASSERT(out_idx_value != NULL);
	DUK_ASSERT(out_getter != NULL);
	DUK_ASSERT(out_setter != NULL);
	DUK_ASSERT(idx_in <= 0x7fffL);  /* short variants would be OK, but not used to avoid shifts */

	/* Must be an object, otherwise TypeError (E5.1 Section 8.10.5, step 1). */
	idx_in = duk_require_normalize_index(thr, idx_in);
	(void) duk_require_hobject(thr, idx_in);

	/* The coercion order must match the ToPropertyDescriptor() algorithm
	 * so that side effects in coercion happen in the correct order.
	 * (This order also happens to be compatible with duk_def_prop(),
	 * although it doesn't matter in practice.)
	 */

	if (duk_get_prop_stridx(thr, idx_in, DUK_STRIDX_VALUE)) {
		is_data_desc = 1;
		defprop_flags |= DUK_DEFPROP_HAVE_VALUE;
		idx_value = duk_get_top_index(thr);
	}

	if (duk_get_prop_stridx(thr, idx_in, DUK_STRIDX_WRITABLE)) {
		is_data_desc = 1;
		if (duk_to_boolean_top_pop(thr)) {
			defprop_flags |= DUK_DEFPROP_HAVE_WRITABLE | DUK_DEFPROP_WRITABLE;
		} else {
			defprop_flags |= DUK_DEFPROP_HAVE_WRITABLE;
		}
	}

	if (duk_get_prop_stridx(thr, idx_in, DUK_STRIDX_GET)) {
		duk_tval *tv = duk_require_tval(thr, -1);
		duk_hobject *h_get;

		if (DUK_TVAL_IS_UNDEFINED(tv)) {
			/* undefined is accepted */
			DUK_ASSERT(getter == NULL);
		} else {
			/* NOTE: lightfuncs are coerced to full functions because
			 * lightfuncs don't fit into a property value slot.  This
			 * has some side effects, see test-dev-lightfunc-accessor.js.
			 */
			h_get = duk_get_hobject_promote_lfunc(thr, -1);
			if (h_get == NULL || !DUK_HOBJECT_IS_CALLABLE(h_get)) {
				goto type_error;
			}
			getter = h_get;
		}
		is_acc_desc = 1;
		defprop_flags |= DUK_DEFPROP_HAVE_GETTER;
	}

	if (duk_get_prop_stridx(thr, idx_in, DUK_STRIDX_SET)) {
		duk_tval *tv = duk_require_tval(thr, -1);
		duk_hobject *h_set;

		if (DUK_TVAL_IS_UNDEFINED(tv)) {
			/* undefined is accepted */
			DUK_ASSERT(setter == NULL);
		}  else {
			/* NOTE: lightfuncs are coerced to full functions because
			 * lightfuncs don't fit into a property value slot.  This
			 * has some side effects, see test-dev-lightfunc-accessor.js.
			 */
			h_set = duk_get_hobject_promote_lfunc(thr, -1);
			if (h_set == NULL || !DUK_HOBJECT_IS_CALLABLE(h_set)) {
				goto type_error;
			}
			setter = h_set;
		}
		is_acc_desc = 1;
		defprop_flags |= DUK_DEFPROP_HAVE_SETTER;
	}

	if (duk_get_prop_stridx(thr, idx_in, DUK_STRIDX_ENUMERABLE)) {
		if (duk_to_boolean_top_pop(thr)) {
			defprop_flags |= DUK_DEFPROP_HAVE_ENUMERABLE | DUK_DEFPROP_ENUMERABLE;
		} else {
			defprop_flags |= DUK_DEFPROP_HAVE_ENUMERABLE;
		}
	}

	if (duk_get_prop_stridx(thr, idx_in, DUK_STRIDX_CONFIGURABLE)) {
		if (duk_to_boolean_top_pop(thr)) {
			defprop_flags |= DUK_DEFPROP_HAVE_CONFIGURABLE | DUK_DEFPROP_CONFIGURABLE;
		} else {
			defprop_flags |= DUK_DEFPROP_HAVE_CONFIGURABLE;
		}
	}

	if (is_data_desc && is_acc_desc) {
		goto type_error;
	}

	*out_defprop_flags = defprop_flags;
	*out_idx_value = idx_value;
	*out_getter = getter;
	*out_setter = setter;

	/* [ ... [multiple values] ] */
	return;

 type_error:
	DUK_ERROR_TYPE(thr, DUK_STR_INVALID_DESCRIPTOR);
	DUK_WO_NORETURN(return;);
}

/*
 *  Object.defineProperty() related helper (E5 Section 15.2.3.6).
 *  Also handles ES2015 Reflect.defineProperty().
 *
 *  Inlines all [[DefineOwnProperty]] exotic behaviors.
 *
 *  Note: ECMAScript compliant [[DefineOwnProperty]](P, Desc, Throw) is not
 *  implemented directly, but Object.defineProperty() serves its purpose.
 *  We don't need the [[DefineOwnProperty]] internally and we don't have a
 *  property descriptor with 'missing values' so it's easier to avoid it
 *  entirely.
 *
 *  Note: this is only called for actual objects, not primitive values.
 *  This must support virtual properties for full objects (e.g. Strings)
 *  but not for plain values (e.g. strings).  Lightfuncs, even though
 *  primitive in a sense, are treated like objects and accepted as target
 *  values.
 */

/* XXX: this is a major target for size optimization */
DUK_INTERNAL
duk_bool_t duk_hobject_define_property_helper(duk_hthread *thr,
                                              duk_uint_t defprop_flags,
                                              duk_hobject *obj,
                                              duk_hstring *key,
                                              duk_idx_t idx_value,
                                              duk_hobject *get,
                                              duk_hobject *set,
                                              duk_bool_t throw_flag) {
	duk_uint32_t arr_idx;
	duk_tval tv;
	duk_bool_t has_enumerable;
	duk_bool_t has_configurable;
	duk_bool_t has_writable;
	duk_bool_t has_value;
	duk_bool_t has_get;
	duk_bool_t has_set;
	duk_bool_t is_enumerable;
	duk_bool_t is_configurable;
	duk_bool_t is_writable;
	duk_bool_t force_flag;
	duk_small_uint_t new_flags;
	duk_propdesc curr;
	duk_uint32_t arridx_new_array_length;  /* != 0 => post-update for array 'length' (used when key is an array index) */
	duk_uint32_t arrlen_old_len;
	duk_uint32_t arrlen_new_len;
	duk_bool_t pending_write_protect;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(thr->heap != NULL);
	DUK_ASSERT(obj != NULL);
	DUK_ASSERT(key != NULL);
	/* idx_value may be < 0 (no value), set and get may be NULL */

	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);

	/* All the flags fit in 16 bits, so will fit into duk_bool_t. */

	has_writable = (defprop_flags & DUK_DEFPROP_HAVE_WRITABLE);
	has_enumerable = (defprop_flags & DUK_DEFPROP_HAVE_ENUMERABLE);
	has_configurable = (defprop_flags & DUK_DEFPROP_HAVE_CONFIGURABLE);
	has_value = (defprop_flags & DUK_DEFPROP_HAVE_VALUE);
	has_get = (defprop_flags & DUK_DEFPROP_HAVE_GETTER);
	has_set = (defprop_flags & DUK_DEFPROP_HAVE_SETTER);
	is_writable = (defprop_flags & DUK_DEFPROP_WRITABLE);
	is_enumerable = (defprop_flags & DUK_DEFPROP_ENUMERABLE);
	is_configurable = (defprop_flags & DUK_DEFPROP_CONFIGURABLE);
	force_flag = (defprop_flags & DUK_DEFPROP_FORCE);

	arr_idx = DUK_HSTRING_GET_ARRIDX_SLOW(key);

	arridx_new_array_length = 0;
	pending_write_protect = 0;
	arrlen_old_len = 0;
	arrlen_new_len = 0;

	DUK_DDD(DUK_DDDPRINT("has_enumerable=%ld is_enumerable=%ld "
	                     "has_configurable=%ld is_configurable=%ld "
	                     "has_writable=%ld is_writable=%ld "
	                     "has_value=%ld value=%!T "
	                     "has_get=%ld get=%p=%!O "
	                     "has_set=%ld set=%p=%!O "
	                     "arr_idx=%ld throw_flag=!%ld",
	                     (long) has_enumerable, (long) is_enumerable,
	                     (long) has_configurable, (long) is_configurable,
	                     (long) has_writable, (long) is_writable,
	                     (long) has_value, (duk_tval *) (idx_value >= 0 ? duk_get_tval(thr, idx_value) : NULL),
	                     (long) has_get, (void *) get, (duk_heaphdr *) get,
	                     (long) has_set, (void *) set, (duk_heaphdr *) set,
	                     (long) arr_idx, (long) throw_flag));

	/*
	 *  Array exotic behaviors can be implemented at this point.  The local variables
	 *  are essentially a 'value copy' of the input descriptor (Desc), which is modified
	 *  by the Array [[DefineOwnProperty]] (E5 Section 15.4.5.1).
	 */

	if (!DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {
		goto skip_array_exotic;
	}

	if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
		duk_harray *a;

		/* E5 Section 15.4.5.1, step 3, steps a - i are implemented here, j - n at the end */
		if (!has_value) {
			DUK_DDD(DUK_DDDPRINT("exotic array behavior for 'length', but no value in descriptor -> normal behavior"));
			goto skip_array_exotic;
		}

		DUK_DDD(DUK_DDDPRINT("exotic array behavior for 'length', value present in descriptor -> exotic behavior"));

		/*
		 *  Get old and new length
		 */

		a = (duk_harray *) obj;
		DUK_HARRAY_ASSERT_VALID(a);
		arrlen_old_len = a->length;

		DUK_ASSERT(idx_value >= 0);
		arrlen_new_len = duk__to_new_array_length_checked(thr, DUK_GET_TVAL_POSIDX(thr, idx_value));
		duk_push_u32(thr, arrlen_new_len);
		duk_replace(thr, idx_value);  /* step 3.e: replace 'Desc.[[Value]]' */

		DUK_DDD(DUK_DDDPRINT("old_len=%ld, new_len=%ld", (long) arrlen_old_len, (long) arrlen_new_len));

		if (arrlen_new_len >= arrlen_old_len) {
			/* standard behavior, step 3.f.i */
			DUK_DDD(DUK_DDDPRINT("new length is same or higher as previous => standard behavior"));
			goto skip_array_exotic;
		}
		DUK_DDD(DUK_DDDPRINT("new length is smaller than previous => exotic post behavior"));

		/* XXX: consolidated algorithm step 15.f -> redundant? */
		if (DUK_HARRAY_LENGTH_NONWRITABLE(a) && !force_flag) {
			/* Array .length is always non-configurable; if it's also
			 * non-writable, don't allow it to be written.
			 */
			goto fail_not_configurable;
		}

		/* steps 3.h and 3.i */
		if (has_writable && !is_writable) {
			DUK_DDD(DUK_DDDPRINT("desc writable is false, force it back to true, and flag pending write protect"));
			is_writable = 1;
			pending_write_protect = 1;
		}

		/* remaining actual steps are carried out if standard DefineOwnProperty succeeds */
	} else if (arr_idx != DUK__NO_ARRAY_INDEX) {
		/* XXX: any chance of unifying this with the 'length' key handling? */

		/* E5 Section 15.4.5.1, step 4 */
		duk_uint32_t old_len;
		duk_harray *a;

		a = (duk_harray *) obj;
		DUK_HARRAY_ASSERT_VALID(a);

		old_len = a->length;

		if (arr_idx >= old_len) {
			DUK_DDD(DUK_DDDPRINT("defineProperty requires array length update "
			                     "(arr_idx=%ld, old_len=%ld)",
			                     (long) arr_idx, (long) old_len));

			if (DUK_HARRAY_LENGTH_NONWRITABLE(a) && !force_flag) {
				/* Array .length is always non-configurable, so
				 * if it's also non-writable, don't allow a value
				 * write.  With force flag allow writing.
				 */
				goto fail_not_configurable;
			}

			/* actual update happens once write has been completed without
			 * error below.
			 */
			DUK_ASSERT(arr_idx != 0xffffffffUL);
			arridx_new_array_length = arr_idx + 1;
		} else {
			DUK_DDD(DUK_DDDPRINT("defineProperty does not require length update "
			                     "(arr_idx=%ld, old_len=%ld) -> standard behavior",
			                     (long) arr_idx, (long) old_len));
		}
	}
 skip_array_exotic:

	/* XXX: There is currently no support for writing buffer object
	 * indexed elements here.  Attempt to do so will succeed and
	 * write a concrete property into the buffer object.  This should
	 * be fixed at some point but because buffers are a custom feature
	 * anyway, this is relatively unimportant.
	 */

	/*
	 *  Actual Object.defineProperty() default algorithm.
	 */

	/*
	 *  First check whether property exists; if not, simple case.  This covers
	 *  steps 1-4.
	 */

	if (!duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &curr, DUK_GETDESC_FLAG_PUSH_VALUE)) {
		DUK_DDD(DUK_DDDPRINT("property does not exist"));

		if (!DUK_HOBJECT_HAS_EXTENSIBLE(obj) && !force_flag) {
			goto fail_not_extensible;
		}

#if defined(DUK_USE_ROM_OBJECTS)
		/* ROM objects are never extensible but force flag may
		 * allow us to come here anyway.
		 */
		DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj) || !DUK_HOBJECT_HAS_EXTENSIBLE(obj));
		if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {
			DUK_D(DUK_DPRINT("attempt to define property on a read-only target object"));
			goto fail_not_configurable;
		}
#endif

		/* XXX: share final setting code for value and flags?  difficult because
		 * refcount code is different.  Share entry allocation?  But can't allocate
		 * until array index checked.
		 */

		/* steps 4.a and 4.b are tricky */
		if (has_set || has_get) {
			duk_int_t e_idx;

			DUK_DDD(DUK_DDDPRINT("create new accessor property"));

			DUK_ASSERT(has_set || set == NULL);
			DUK_ASSERT(has_get || get == NULL);
			DUK_ASSERT(!has_value);
			DUK_ASSERT(!has_writable);

			new_flags = DUK_PROPDESC_FLAG_ACCESSOR;  /* defaults, E5 Section 8.6.1, Table 7 */
			if (has_enumerable && is_enumerable) {
				new_flags |= DUK_PROPDESC_FLAG_ENUMERABLE;
			}
			if (has_configurable && is_configurable) {
				new_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;
			}

			if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
				DUK_DDD(DUK_DDDPRINT("accessor cannot go to array part, abandon array"));
				duk__abandon_array_part(thr, obj);
			}

			/* write to entry part */
			e_idx = duk__hobject_alloc_entry_checked(thr, obj, key);
			DUK_ASSERT(e_idx >= 0);

			DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, e_idx, get);
			DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, e_idx, set);
			DUK_HOBJECT_INCREF_ALLOWNULL(thr, get);
			DUK_HOBJECT_INCREF_ALLOWNULL(thr, set);

			DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, e_idx, new_flags);
			goto success_exotics;
		} else {
			duk_int_t e_idx;
			duk_tval *tv2;

			DUK_DDD(DUK_DDDPRINT("create new data property"));

			DUK_ASSERT(!has_set);
			DUK_ASSERT(!has_get);

			new_flags = 0;  /* defaults, E5 Section 8.6.1, Table 7 */
			if (has_writable && is_writable) {
				new_flags |= DUK_PROPDESC_FLAG_WRITABLE;
			}
			if (has_enumerable && is_enumerable) {
				new_flags |= DUK_PROPDESC_FLAG_ENUMERABLE;
			}
			if (has_configurable && is_configurable) {
				new_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;
			}
			if (has_value) {
				duk_tval *tv_tmp = duk_require_tval(thr, idx_value);
				DUK_TVAL_SET_TVAL(&tv, tv_tmp);
			} else {
				DUK_TVAL_SET_UNDEFINED(&tv);  /* default value */
			}

			if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
				if (new_flags == DUK_PROPDESC_FLAGS_WEC) {
					DUK_DDD(DUK_DDDPRINT("new data property attributes match array defaults, attempt to write to array part"));
					tv2 = duk__obtain_arridx_slot(thr, arr_idx, obj);
					if (tv2 == NULL) {
						DUK_DDD(DUK_DDDPRINT("failed writing to array part, abandoned array"));
					} else {
						DUK_DDD(DUK_DDDPRINT("success in writing to array part"));
						DUK_ASSERT(DUK_HOBJECT_HAS_ARRAY_PART(obj));
						DUK_ASSERT(DUK_TVAL_IS_UNUSED(tv2));
						DUK_TVAL_SET_TVAL(tv2, &tv);
						DUK_TVAL_INCREF(thr, tv2);
						goto success_exotics;
					}
				} else {
					DUK_DDD(DUK_DDDPRINT("new data property cannot go to array part, abandon array"));
					duk__abandon_array_part(thr, obj);
				}
				/* fall through */
			}

			/* write to entry part */
			e_idx = duk__hobject_alloc_entry_checked(thr, obj, key);
			DUK_ASSERT(e_idx >= 0);
			tv2 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, e_idx);
			DUK_TVAL_SET_TVAL(tv2, &tv);
			DUK_TVAL_INCREF(thr, tv2);

			DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, e_idx, new_flags);
			goto success_exotics;
		}
		DUK_UNREACHABLE();
	}

	/* we currently assume virtual properties are not configurable (as none of them are) */
	DUK_ASSERT((curr.e_idx >= 0 || curr.a_idx >= 0) || !(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE));

	/* [obj key desc value get set curr_value] */

	/*
	 *  Property already exists.  Steps 5-6 detect whether any changes need
	 *  to be made.
	 */

	if (has_enumerable) {
		if (is_enumerable) {
			if (!(curr.flags & DUK_PROPDESC_FLAG_ENUMERABLE)) {
				goto need_check;
			}
		} else {
			if (curr.flags & DUK_PROPDESC_FLAG_ENUMERABLE) {
				goto need_check;
			}
		}
	}
	if (has_configurable) {
		if (is_configurable) {
			if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE)) {
				goto need_check;
			}
		} else {
			if (curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) {
				goto need_check;
			}
		}
	}
	if (has_value) {
		duk_tval *tmp1;
		duk_tval *tmp2;

		/* attempt to change from accessor to data property */
		if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
			goto need_check;
		}

		tmp1 = duk_require_tval(thr, -1);         /* curr value */
		tmp2 = duk_require_tval(thr, idx_value);  /* new value */
		if (!duk_js_samevalue(tmp1, tmp2)) {
			goto need_check;
		}
	}
	if (has_writable) {
		/* attempt to change from accessor to data property */
		if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
			goto need_check;
		}

		if (is_writable) {
			if (!(curr.flags & DUK_PROPDESC_FLAG_WRITABLE)) {
				goto need_check;
			}
		} else {
			if (curr.flags & DUK_PROPDESC_FLAG_WRITABLE) {
				goto need_check;
			}
		}
	}
	if (has_set) {
		if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
			if (set != curr.set) {
				goto need_check;
			}
		} else {
			goto need_check;
		}
	}
	if (has_get) {
		if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
			if (get != curr.get) {
				goto need_check;
			}
		} else {
			goto need_check;
		}
	}

	/* property exists, either 'desc' is empty, or all values
	 * match (SameValue)
	 */
	goto success_no_exotics;

 need_check:

	/*
	 *  Some change(s) need to be made.  Steps 7-11.
	 */

	/* shared checks for all descriptor types */
	if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
		if (has_configurable && is_configurable) {
			goto fail_not_configurable;
		}
		if (has_enumerable) {
			if (curr.flags & DUK_PROPDESC_FLAG_ENUMERABLE) {
				if (!is_enumerable) {
					goto fail_not_configurable;
				}
			} else {
				if (is_enumerable) {
					goto fail_not_configurable;
				}
			}
		}
	}

	/* Virtual properties don't have backing so they can't mostly be
	 * edited.  Some virtual properties are, however, writable: for
	 * example, virtual index properties of buffer objects and Array
	 * instance .length.  These are not configurable so the checks
	 * above mostly cover attempts to change them, except when the
	 * duk_def_prop() call is used with DUK_DEFPROP_FORCE; even in
	 * that case we can't forcibly change the property attributes
	 * because they don't have concrete backing.
	 */

	/* XXX: for ROM objects too it'd be best if value modify was
	 * allowed if the value matches SameValue.
	 */
	/* Reject attempt to change a read-only object. */
#if defined(DUK_USE_ROM_OBJECTS)
	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {
		DUK_DD(DUK_DDPRINT("attempt to define property on read-only target object"));
		goto fail_not_configurable;
	}
#endif

	/* descriptor type specific checks */
	if (has_set || has_get) {
		/* IsAccessorDescriptor(desc) == true */
		DUK_ASSERT(!has_writable);
		DUK_ASSERT(!has_value);

		if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
			/* curr and desc are accessors */
			if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
				if (has_set && set != curr.set) {
					goto fail_not_configurable;
				}
				if (has_get && get != curr.get) {
					goto fail_not_configurable;
				}
			}
		} else {
			duk_bool_t rc;
			duk_tval *tv1;

			/* curr is data, desc is accessor */
			if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
				goto fail_not_configurable;
			}

			DUK_DDD(DUK_DDDPRINT("convert property to accessor property"));
			if (curr.a_idx >= 0) {
				DUK_DDD(DUK_DDDPRINT("property to convert is stored in an array entry, abandon array and re-lookup"));
				duk__abandon_array_part(thr, obj);
				duk_pop_unsafe(thr);  /* remove old value */
				rc = duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &curr, DUK_GETDESC_FLAG_PUSH_VALUE);
				DUK_UNREF(rc);
				DUK_ASSERT(rc != 0);
				DUK_ASSERT(curr.e_idx >= 0 && curr.a_idx < 0);
			}
			if (curr.e_idx < 0) {
				DUK_ASSERT(curr.a_idx < 0 && curr.e_idx < 0);
				goto fail_virtual;  /* safeguard for virtual property */
			}

			DUK_ASSERT(curr.e_idx >= 0);
			DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, curr.e_idx));

			tv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, curr.e_idx);
			DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ(thr, tv1);  /* XXX: just decref */

			DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, curr.e_idx, NULL);
			DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, curr.e_idx, NULL);
			DUK_HOBJECT_E_SLOT_CLEAR_WRITABLE(thr->heap, obj, curr.e_idx);
			DUK_HOBJECT_E_SLOT_SET_ACCESSOR(thr->heap, obj, curr.e_idx);

			DUK_DDD(DUK_DDDPRINT("flags after data->accessor conversion: 0x%02lx",
			                     (unsigned long) DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, curr.e_idx)));
			/* Update curr.flags; faster than a re-lookup. */
			curr.flags &= ~DUK_PROPDESC_FLAG_WRITABLE;
			curr.flags |= DUK_PROPDESC_FLAG_ACCESSOR;
		}
	} else if (has_value || has_writable) {
		/* IsDataDescriptor(desc) == true */
		DUK_ASSERT(!has_set);
		DUK_ASSERT(!has_get);

		if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
			duk_hobject *tmp;

			/* curr is accessor, desc is data */
			if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
				goto fail_not_configurable;
			}

			/* curr is accessor -> cannot be in array part. */
			DUK_ASSERT(curr.a_idx < 0);
			if (curr.e_idx < 0) {
				goto fail_virtual;  /* safeguard; no virtual accessors now */
			}

			DUK_DDD(DUK_DDDPRINT("convert property to data property"));

			DUK_ASSERT(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, curr.e_idx));
			tmp = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, obj, curr.e_idx);
			DUK_UNREF(tmp);
			DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, curr.e_idx, NULL);
			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, tmp);
			tmp = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, obj, curr.e_idx);
			DUK_UNREF(tmp);
			DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, curr.e_idx, NULL);
			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, tmp);

			DUK_TVAL_SET_UNDEFINED(DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, curr.e_idx));
			DUK_HOBJECT_E_SLOT_CLEAR_WRITABLE(thr->heap, obj, curr.e_idx);
			DUK_HOBJECT_E_SLOT_CLEAR_ACCESSOR(thr->heap, obj, curr.e_idx);

			DUK_DDD(DUK_DDDPRINT("flags after accessor->data conversion: 0x%02lx",
			                     (unsigned long) DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, curr.e_idx)));

			/* Update curr.flags; faster than a re-lookup. */
			curr.flags &= ~(DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_ACCESSOR);
		} else {
			/* curr and desc are data */
			if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
				if (!(curr.flags & DUK_PROPDESC_FLAG_WRITABLE) && has_writable && is_writable) {
					goto fail_not_configurable;
				}
				/* Note: changing from writable to non-writable is OK */
				if (!(curr.flags & DUK_PROPDESC_FLAG_WRITABLE) && has_value) {
					duk_tval *tmp1 = duk_require_tval(thr, -1);         /* curr value */
					duk_tval *tmp2 = duk_require_tval(thr, idx_value);  /* new value */
					if (!duk_js_samevalue(tmp1, tmp2)) {
						goto fail_not_configurable;
					}
				}
			}
		}
	} else {
		/* IsGenericDescriptor(desc) == true; this means in practice that 'desc'
		 * only has [[Enumerable]] or [[Configurable]] flag updates, which are
		 * allowed at this point.
		 */

		DUK_ASSERT(!has_value && !has_writable && !has_get && !has_set);
	}

	/*
	 *  Start doing property attributes updates.  Steps 12-13.
	 *
	 *  Start by computing new attribute flags without writing yet.
	 *  Property type conversion is done above if necessary.
	 */

	new_flags = curr.flags;

	if (has_enumerable) {
		if (is_enumerable) {
			new_flags |= DUK_PROPDESC_FLAG_ENUMERABLE;
		} else {
			new_flags &= ~DUK_PROPDESC_FLAG_ENUMERABLE;
		}
	}
	if (has_configurable) {
		if (is_configurable) {
			new_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;
		} else {
			new_flags &= ~DUK_PROPDESC_FLAG_CONFIGURABLE;
		}
	}
	if (has_writable) {
		if (is_writable) {
			new_flags |= DUK_PROPDESC_FLAG_WRITABLE;
		} else {
			new_flags &= ~DUK_PROPDESC_FLAG_WRITABLE;
		}
	}

	/* XXX: write protect after flag? -> any chance of handling it here? */

	DUK_DDD(DUK_DDDPRINT("new flags that we want to write: 0x%02lx",
	                     (unsigned long) new_flags));

	/*
	 *  Check whether we need to abandon an array part (if it exists)
	 */

	if (curr.a_idx >= 0) {
		duk_bool_t rc;

		DUK_ASSERT(curr.e_idx < 0);

		if (new_flags == DUK_PROPDESC_FLAGS_WEC) {
			duk_tval *tv1, *tv2;

			DUK_DDD(DUK_DDDPRINT("array index, new property attributes match array defaults, update in-place"));

			DUK_ASSERT(curr.flags == DUK_PROPDESC_FLAGS_WEC);  /* must have been, since in array part */
			DUK_ASSERT(!has_set);
			DUK_ASSERT(!has_get);
			DUK_ASSERT(idx_value >= 0);  /* must be: if attributes match and we get here the value must differ (otherwise no change) */

			tv2 = duk_require_tval(thr, idx_value);
			tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, curr.a_idx);
			DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2);  /* side effects; may invalidate a_idx */
			goto success_exotics;
		}

		DUK_DDD(DUK_DDDPRINT("array index, new property attributes do not match array defaults, abandon array and re-lookup"));
		duk__abandon_array_part(thr, obj);
		duk_pop_unsafe(thr);  /* remove old value */
		rc = duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &curr, DUK_GETDESC_FLAG_PUSH_VALUE);
		DUK_UNREF(rc);
		DUK_ASSERT(rc != 0);
		DUK_ASSERT(curr.e_idx >= 0 && curr.a_idx < 0);
	}

	DUK_DDD(DUK_DDDPRINT("updating existing property in entry part"));

	/* Array case is handled comprehensively above: either in entry
	 * part or a virtual property.
	 */
	DUK_ASSERT(curr.a_idx < 0);

	DUK_DDD(DUK_DDDPRINT("update existing property attributes"));
	if (curr.e_idx >= 0) {
		DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, curr.e_idx, new_flags);
	} else {
		/* For Array .length the only allowed transition is for .length
		 * to become non-writable.
		 */
		if (key == DUK_HTHREAD_STRING_LENGTH(thr) && DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {
			duk_harray *a;
			a = (duk_harray *) obj;
			DUK_DD(DUK_DDPRINT("Object.defineProperty() attribute update for duk_harray .length -> %02lx", (unsigned long) new_flags));
			DUK_HARRAY_ASSERT_VALID(a);
			if ((new_flags & DUK_PROPDESC_FLAGS_EC) != (curr.flags & DUK_PROPDESC_FLAGS_EC)) {
				DUK_D(DUK_DPRINT("Object.defineProperty() attempt to change virtual array .length enumerable or configurable attribute, fail"));
				goto fail_virtual;
			}
			if (new_flags & DUK_PROPDESC_FLAG_WRITABLE) {
				DUK_HARRAY_SET_LENGTH_WRITABLE(a);
			} else {
				DUK_HARRAY_SET_LENGTH_NONWRITABLE(a);
			}
		}
	}

	if (has_set) {
		duk_hobject *tmp;

		/* Virtual properties are non-configurable but with a 'force'
		 * flag we might come here so check explicitly for virtual.
		 */
		if (curr.e_idx < 0) {
			goto fail_virtual;
		}

		DUK_DDD(DUK_DDDPRINT("update existing property setter"));
		DUK_ASSERT(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, curr.e_idx));

		tmp = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, obj, curr.e_idx);
		DUK_UNREF(tmp);
		DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, curr.e_idx, set);
		DUK_HOBJECT_INCREF_ALLOWNULL(thr, set);
		DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);  /* side effects; may invalidate e_idx */
	}
	if (has_get) {
		duk_hobject *tmp;

		if (curr.e_idx < 0) {
			goto fail_virtual;
		}

		DUK_DDD(DUK_DDDPRINT("update existing property getter"));
		DUK_ASSERT(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, curr.e_idx));

		tmp = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, obj, curr.e_idx);
		DUK_UNREF(tmp);
		DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, curr.e_idx, get);
		DUK_HOBJECT_INCREF_ALLOWNULL(thr, get);
		DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);  /* side effects; may invalidate e_idx */
	}
	if (has_value) {
		duk_tval *tv1, *tv2;

		DUK_DDD(DUK_DDDPRINT("update existing property value"));

		if (curr.e_idx >= 0) {
			DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, curr.e_idx));
			tv2 = duk_require_tval(thr, idx_value);
			tv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, curr.e_idx);
			DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2);  /* side effects; may invalidate e_idx */
		} else {
			DUK_ASSERT(curr.a_idx < 0);  /* array part case handled comprehensively previously */

			DUK_DD(DUK_DDPRINT("Object.defineProperty(), value update for virtual property"));
			/* XXX: Uint8Array and other typed array virtual writes not currently
			 * handled.
			 */
			if (key == DUK_HTHREAD_STRING_LENGTH(thr) && DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {
				duk_harray *a;
				a = (duk_harray *) obj;
				DUK_DD(DUK_DDPRINT("Object.defineProperty() value update for duk_harray .length -> %ld", (long) arrlen_new_len));
				DUK_HARRAY_ASSERT_VALID(a);
				a->length = arrlen_new_len;
			} else {
				goto fail_virtual;  /* should not happen */
			}
		}
	}

	/*
	 *  Standard algorithm succeeded without errors, check for exotic post-behaviors.
	 *
	 *  Arguments exotic behavior in E5 Section 10.6 occurs after the standard
	 *  [[DefineOwnProperty]] has completed successfully.
	 *
	 *  Array exotic behavior in E5 Section 15.4.5.1 is implemented partly
	 *  prior to the default [[DefineOwnProperty]], but:
	 *    - for an array index key (e.g. "10") the final 'length' update occurs here
	 *    - for 'length' key the element deletion and 'length' update occurs here
	 */

 success_exotics:

	/* curr.a_idx or curr.e_idx may have been invalidated by side effects
	 * above.
	 */

	/* [obj key desc value get set curr_value] */

	if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {
		duk_harray *a;

		a = (duk_harray *) obj;
		DUK_HARRAY_ASSERT_VALID(a);

		if (arridx_new_array_length > 0) {
			/*
			 *  Note: zero works as a "no update" marker because the new length
			 *  can never be zero after a new property is written.
			 */

			/* E5 Section 15.4.5.1, steps 4.e.i - 4.e.ii */

			DUK_DDD(DUK_DDDPRINT("defineProperty successful, pending array length update to: %ld",
			                     (long) arridx_new_array_length));

			a->length = arridx_new_array_length;
		}

		if (key == DUK_HTHREAD_STRING_LENGTH(thr) && arrlen_new_len < arrlen_old_len) {
			/*
			 *  E5 Section 15.4.5.1, steps 3.k - 3.n.  The order at the end combines
			 *  the error case 3.l.iii and the success case 3.m-3.n.
			 */

			/* XXX: investigate whether write protect can be handled above, if we
			 * just update length here while ignoring its protected status
			 */

			duk_uint32_t result_len;
			duk_bool_t rc;

			DUK_DDD(DUK_DDDPRINT("defineProperty successful, key is 'length', exotic array behavior, "
			                     "doing array element deletion and length update"));

			rc = duk__handle_put_array_length_smaller(thr, obj, arrlen_old_len, arrlen_new_len, force_flag, &result_len);

			/* update length (curr points to length, and we assume it's still valid) */
			DUK_ASSERT(result_len >= arrlen_new_len && result_len <= arrlen_old_len);

			a->length = result_len;

			if (pending_write_protect) {
				DUK_DDD(DUK_DDDPRINT("setting array length non-writable (pending writability update)"));
				DUK_HARRAY_SET_LENGTH_NONWRITABLE(a);
			}

			/* XXX: shrink array allocation or entries compaction here? */
			if (!rc) {
				DUK_DD(DUK_DDPRINT("array length write only partially successful"));
				goto fail_not_configurable;
			}
		}
	} else if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj)) {
		duk_hobject *map;
		duk_hobject *varenv;

		DUK_ASSERT(arridx_new_array_length == 0);
		DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj));  /* traits are separate; in particular, arguments not an array */

		map = NULL;
		varenv = NULL;
		if (!duk__lookup_arguments_map(thr, obj, key, &curr, &map, &varenv)) {
			goto success_no_exotics;
		}
		DUK_ASSERT(map != NULL);
		DUK_ASSERT(varenv != NULL);

		/* [obj key desc value get set curr_value varname] */

		if (has_set || has_get) {
			/* = IsAccessorDescriptor(Desc) */
			DUK_DDD(DUK_DDDPRINT("defineProperty successful, key mapped to arguments 'map' "
			                     "changed to an accessor, delete arguments binding"));

			(void) duk_hobject_delprop_raw(thr, map, key, 0);  /* ignore result */
		} else {
			/* Note: this order matters (final value before deleting map entry must be done) */
			DUK_DDD(DUK_DDDPRINT("defineProperty successful, key mapped to arguments 'map', "
			                     "check for value update / binding deletion"));

			if (has_value) {
				duk_hstring *varname;

				DUK_DDD(DUK_DDDPRINT("defineProperty successful, key mapped to arguments 'map', "
				                     "update bound value (variable/argument)"));

				varname = duk_require_hstring(thr, -1);
				DUK_ASSERT(varname != NULL);

				DUK_DDD(DUK_DDDPRINT("arguments object automatic putvar for a bound variable; "
				                     "key=%!O, varname=%!O, value=%!T",
				                     (duk_heaphdr *) key,
				                     (duk_heaphdr *) varname,
				                     (duk_tval *) duk_require_tval(thr, idx_value)));

				/* strict flag for putvar comes from our caller (currently: fixed) */
				duk_js_putvar_envrec(thr, varenv, varname, duk_require_tval(thr, idx_value), 1 /*throw_flag*/);
			}
			if (has_writable && !is_writable) {
				DUK_DDD(DUK_DDDPRINT("defineProperty successful, key mapped to arguments 'map', "
				                     "changed to non-writable, delete arguments binding"));

				(void) duk_hobject_delprop_raw(thr, map, key, 0);  /* ignore result */
			}
		}

		/* 'varname' is in stack in this else branch, leaving an unbalanced stack below,
		 * but this doesn't matter now.
		 */
	}

 success_no_exotics:
	/* Some code paths use NORZ macros for simplicity, ensure refzero
	 * handling is completed.
	 */
	DUK_REFZERO_CHECK_SLOW(thr);
	return 1;

 fail_not_extensible:
	if (throw_flag) {
		DUK_ERROR_TYPE(thr, DUK_STR_NOT_EXTENSIBLE);
		DUK_WO_NORETURN(return 0;);
	}
	return 0;

 fail_virtual:  /* just use the same "not configurable" error message" */
 fail_not_configurable:
	if (throw_flag) {
		DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);
		DUK_WO_NORETURN(return 0;);
	}
	return 0;
}

/*
 *  Object.prototype.hasOwnProperty() and Object.prototype.propertyIsEnumerable().
 */

DUK_INTERNAL duk_bool_t duk_hobject_object_ownprop_helper(duk_hthread *thr, duk_small_uint_t required_desc_flags) {
	duk_hstring *h_v;
	duk_hobject *h_obj;
	duk_propdesc desc;
	duk_bool_t ret;

	/* coercion order matters */
	h_v = duk_to_hstring_acceptsymbol(thr, 0);
	DUK_ASSERT(h_v != NULL);

	h_obj = duk_push_this_coercible_to_object(thr);
	DUK_ASSERT(h_obj != NULL);

	ret = duk_hobject_get_own_propdesc(thr, h_obj, h_v, &desc, 0 /*flags*/);  /* don't push value */

	duk_push_boolean(thr, ret && ((desc.flags & required_desc_flags) == required_desc_flags));
	return 1;
}

/*
 *  Object.seal() and Object.freeze()  (E5 Sections 15.2.3.8 and 15.2.3.9)
 *
 *  Since the algorithms are similar, a helper provides both functions.
 *  Freezing is essentially sealing + making plain properties non-writable.
 *
 *  Note: virtual (non-concrete) properties which are non-configurable but
 *  writable would pose some problems, but such properties do not currently
 *  exist (all virtual properties are non-configurable and non-writable).
 *  If they did exist, the non-configurability does NOT prevent them from
 *  becoming non-writable.  However, this change should be recorded somehow
 *  so that it would turn up (e.g. when getting the property descriptor),
 *  requiring some additional flags in the object.
 */

DUK_INTERNAL void duk_hobject_object_seal_freeze_helper(duk_hthread *thr, duk_hobject *obj, duk_bool_t is_freeze) {
	duk_uint_fast32_t i;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(thr->heap != NULL);
	DUK_ASSERT(obj != NULL);

	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);

#if defined(DUK_USE_ROM_OBJECTS)
	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {
		DUK_DD(DUK_DDPRINT("attempt to seal/freeze a readonly object, reject"));
		DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);
		DUK_WO_NORETURN(return;);
	}
#endif

	/*
	 *  Abandon array part because all properties must become non-configurable.
	 *  Note that this is now done regardless of whether this is always the case
	 *  (skips check, but performance problem if caller would do this many times
	 *  for the same object; not likely).
	 */

	duk__abandon_array_part(thr, obj);
	DUK_ASSERT(DUK_HOBJECT_GET_ASIZE(obj) == 0);

	for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
		duk_uint8_t *fp;

		/* since duk__abandon_array_part() causes a resize, there should be no gaps in keys */
		DUK_ASSERT(DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i) != NULL);

		/* avoid multiple computations of flags address; bypasses macros */
		fp = DUK_HOBJECT_E_GET_FLAGS_PTR(thr->heap, obj, i);
		if (is_freeze && !((*fp) & DUK_PROPDESC_FLAG_ACCESSOR)) {
			*fp &= ~(DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_CONFIGURABLE);
		} else {
			*fp &= ~DUK_PROPDESC_FLAG_CONFIGURABLE;
		}
	}

	DUK_HOBJECT_CLEAR_EXTENSIBLE(obj);

	/* no need to compact since we already did that in duk__abandon_array_part()
	 * (regardless of whether an array part existed or not.
	 */

	return;
}

/*
 *  Object.isSealed() and Object.isFrozen()  (E5 Sections 15.2.3.11, 15.2.3.13)
 *
 *  Since the algorithms are similar, a helper provides both functions.
 *  Freezing is essentially sealing + making plain properties non-writable.
 *
 *  Note: all virtual (non-concrete) properties are currently non-configurable
 *  and non-writable (and there are no accessor virtual properties), so they don't
 *  need to be considered here now.
 */

DUK_INTERNAL duk_bool_t duk_hobject_object_is_sealed_frozen_helper(duk_hthread *thr, duk_hobject *obj, duk_bool_t is_frozen) {
	duk_uint_fast32_t i;

	DUK_ASSERT(obj != NULL);
	DUK_UNREF(thr);

	/* Note: no allocation pressure, no need to check refcounts etc */

	/* must not be extensible */
	if (DUK_HOBJECT_HAS_EXTENSIBLE(obj)) {
		return 0;
	}

	/* all virtual properties are non-configurable and non-writable */

	/* entry part must not contain any configurable properties, or
	 * writable properties (if is_frozen).
	 */
	for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
		duk_small_uint_t flags;

		if (!DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i)) {
			continue;
		}

		/* avoid multiple computations of flags address; bypasses macros */
		flags = (duk_small_uint_t) DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, i);

		if (flags & DUK_PROPDESC_FLAG_CONFIGURABLE) {
			return 0;
		}
		if (is_frozen &&
		    !(flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
		    (flags & DUK_PROPDESC_FLAG_WRITABLE)) {
			return 0;
		}
	}

	/* array part must not contain any non-unused properties, as they would
	 * be configurable and writable.
	 */
	for (i = 0; i < DUK_HOBJECT_GET_ASIZE(obj); i++) {
		duk_tval *tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, i);
		if (!DUK_TVAL_IS_UNUSED(tv)) {
			return 0;
		}
	}

	return 1;
}

/*
 *  Object.preventExtensions() and Object.isExtensible()  (E5 Sections 15.2.3.10, 15.2.3.13)
 *
 *  Not needed, implemented by macros DUK_HOBJECT_{HAS,CLEAR,SET}_EXTENSIBLE
 *  and the Object built-in bindings.
 */

/* automatic undefs */
#undef DUK__HASH_DELETED
#undef DUK__HASH_UNUSED
#undef DUK__NO_ARRAY_INDEX
#undef DUK__VALSTACK_PROXY_LOOKUP
#undef DUK__VALSTACK_SPACE
#line 1 "duk_hstring_assert.c"
/*
 *  duk_hstring assertion helpers.
 */

/* #include duk_internal.h -> already included */

#if defined(DUK_USE_ASSERTIONS)

DUK_INTERNAL void duk_hstring_assert_valid(duk_hstring *h) {
	DUK_ASSERT(h != NULL);
}

#endif  /* DUK_USE_ASSERTIONS */
#line 1 "duk_hstring_misc.c"
/*
 *  Misc support functions
 */

/* #include duk_internal.h -> already included */

/*
 *  duk_hstring charCodeAt, with and without surrogate awareness
 */

DUK_INTERNAL duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr, duk_hstring *h, duk_uint_t pos, duk_bool_t surrogate_aware) {
	duk_uint32_t boff;
	const duk_uint8_t *p, *p_start, *p_end;
	duk_ucodepoint_t cp1;
	duk_ucodepoint_t cp2;

	/* Caller must check character offset to be inside the string. */
	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(h != NULL);
	DUK_ASSERT_DISABLE(pos >= 0);  /* unsigned */
	DUK_ASSERT(pos < (duk_uint_t) DUK_HSTRING_GET_CHARLEN(h));

	boff = (duk_uint32_t) duk_heap_strcache_offset_char2byte(thr, h, (duk_uint32_t) pos);
	DUK_DDD(DUK_DDDPRINT("charCodeAt: pos=%ld -> boff=%ld, str=%!O",
	                     (long) pos, (long) boff, (duk_heaphdr *) h));
	DUK_ASSERT_DISABLE(boff >= 0);
	DUK_ASSERT(boff < DUK_HSTRING_GET_BYTELEN(h));

	p_start = DUK_HSTRING_GET_DATA(h);
	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h);
	p = p_start + boff;
	DUK_DDD(DUK_DDDPRINT("p_start=%p, p_end=%p, p=%p",
	                     (const void *) p_start, (const void *) p_end,
	                     (const void *) p));

	/* For invalid UTF-8 (never happens for standard ECMAScript strings)
	 * return U+FFFD replacement character.
	 */
	if (duk_unicode_decode_xutf8(thr, &p, p_start, p_end, &cp1)) {
		if (surrogate_aware && cp1 >= 0xd800UL && cp1 <= 0xdbffUL) {
			/* The decode helper is memory safe even if 'cp1' was
			 * decoded at the end of the string and 'p' is no longer
			 * within string memory range.
			 */
			cp2 = 0;  /* If call fails, this is left untouched and won't match cp2 check. */
			(void) duk_unicode_decode_xutf8(thr, &p, p_start, p_end, &cp2);
			if (cp2 >= 0xdc00UL && cp2 <= 0xdfffUL) {
				cp1 = (duk_ucodepoint_t) (((cp1 - 0xd800UL) << 10) + (cp2 - 0xdc00UL) + 0x10000UL);
			}
		}
	} else {
		cp1 = DUK_UNICODE_CP_REPLACEMENT_CHARACTER;
	}

	return cp1;
}

/*
 *  duk_hstring charlen, when lazy charlen disabled
 */

#if !defined(DUK_USE_HSTRING_LAZY_CLEN)
#if !defined(DUK_USE_HSTRING_CLEN)
#error non-lazy duk_hstring charlen but DUK_USE_HSTRING_CLEN not set
#endif
DUK_INTERNAL void duk_hstring_init_charlen(duk_hstring *h) {
	duk_uint32_t clen;

	DUK_ASSERT(h != NULL);
	DUK_ASSERT(!DUK_HSTRING_HAS_ASCII(h));
	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h));

	clen = duk_unicode_unvalidated_utf8_length(DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
#if defined(DUK_USE_STRLEN16)
	DUK_ASSERT(clen <= 0xffffUL);  /* Bytelength checked during interning. */
	h->clen16 = (duk_uint16_t) clen;
#else
	h->clen = (duk_uint32_t) clen;
#endif
	if (DUK_LIKELY(clen == DUK_HSTRING_GET_BYTELEN(h))) {
		DUK_HSTRING_SET_ASCII(h);
	}
}

DUK_INTERNAL DUK_HOT duk_size_t duk_hstring_get_charlen(duk_hstring *h) {
#if defined(DUK_USE_STRLEN16)
	return h->clen16;
#else
	return h->clen;
#endif
}
#endif  /* !DUK_USE_HSTRING_LAZY_CLEN */

/*
 *  duk_hstring charlen, when lazy charlen enabled
 */

#if defined(DUK_USE_HSTRING_LAZY_CLEN)
#if defined(DUK_USE_HSTRING_CLEN)
DUK_LOCAL DUK_COLD duk_size_t duk__hstring_get_charlen_slowpath(duk_hstring *h) {
	duk_size_t res;

	DUK_ASSERT(h->clen == 0);  /* Checked by caller. */

#if defined(DUK_USE_ROM_STRINGS)
	/* ROM strings have precomputed clen, but if the computed clen is zero
	 * we can still come here and can't write anything.
	 */
	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h)) {
		return 0;
	}
#endif

	res = duk_unicode_unvalidated_utf8_length(DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
#if defined(DUK_USE_STRLEN16)
	DUK_ASSERT(res <= 0xffffUL);  /* Bytelength checked during interning. */
	h->clen16 = (duk_uint16_t) res;
#else
	h->clen = (duk_uint32_t) res;
#endif
	if (DUK_LIKELY(res == DUK_HSTRING_GET_BYTELEN(h))) {
		DUK_HSTRING_SET_ASCII(h);
	}
	return res;
}
#else  /* DUK_USE_HSTRING_CLEN */
DUK_LOCAL duk_size_t duk__hstring_get_charlen_slowpath(duk_hstring *h) {
	if (DUK_LIKELY(DUK_HSTRING_HAS_ASCII(h))) {
		/* Most practical strings will go here. */
		return DUK_HSTRING_GET_BYTELEN(h);
	} else {
		/* ASCII flag is lazy, so set it here. */
		duk_size_t res;

		/* XXX: here we could use the strcache to speed up the
		 * computation (matters for 'i < str.length' loops).
		 */

		res = duk_unicode_unvalidated_utf8_length(DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));

#if defined(DUK_USE_ROM_STRINGS)
		if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h)) {
			/* For ROM strings, can't write anything; ASCII flag
			 * is preset so we don't need to update it.
			 */
			return res;
		}
#endif
		if (DUK_LIKELY(res == DUK_HSTRING_GET_BYTELEN(h))) {
			DUK_HSTRING_SET_ASCII(h);
		}
		return res;
	}
}
#endif  /* DUK_USE_HSTRING_CLEN */

#if defined(DUK_USE_HSTRING_CLEN)
DUK_INTERNAL DUK_HOT duk_size_t duk_hstring_get_charlen(duk_hstring *h) {
#if defined(DUK_USE_STRLEN16)
	if (DUK_LIKELY(h->clen16 != 0)) {
		return h->clen16;
	}
#else
	if (DUK_LIKELY(h->clen != 0)) {
		return h->clen;
	}
#endif
	return duk__hstring_get_charlen_slowpath(h);
}
#else  /* DUK_USE_HSTRING_CLEN */
DUK_INTERNAL DUK_HOT duk_size_t duk_hstring_get_charlen(duk_hstring *h) {
	/* Always use slow path. */
	return duk__hstring_get_charlen_slowpath(h);
}
#endif  /* DUK_USE_HSTRING_CLEN */
#endif  /* DUK_USE_HSTRING_LAZY_CLEN */

/*
 *  Compare duk_hstring to an ASCII cstring.
 */

DUK_INTERNAL duk_bool_t duk_hstring_equals_ascii_cstring(duk_hstring *h, const char *cstr) {
	duk_size_t len;

	DUK_ASSERT(h != NULL);
	DUK_ASSERT(cstr != NULL);

	len = DUK_STRLEN(cstr);
	if (len != DUK_HSTRING_GET_BYTELEN(h)) {
		return 0;
	}
	if (duk_memcmp((const void *) cstr, (const void *) DUK_HSTRING_GET_DATA(h), len) == 0) {
		return 1;
	}
	return 0;
}
#line 1 "duk_hthread_alloc.c"
/*
 *  duk_hthread allocation and freeing.
 */

/* #include duk_internal.h -> already included */

/*
 *  Allocate initial stacks for a thread.  Note that 'thr' must be reachable
 *  as a garbage collection may be triggered by the allocation attempts.
 *  Returns zero (without leaking memory) if init fails.
 */

DUK_INTERNAL duk_bool_t duk_hthread_init_stacks(duk_heap *heap, duk_hthread *thr) {
	duk_size_t alloc_size;
	duk_size_t i;

	DUK_ASSERT(heap != NULL);
	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(thr->valstack == NULL);
	DUK_ASSERT(thr->valstack_end == NULL);
	DUK_ASSERT(thr->valstack_alloc_end == NULL);
	DUK_ASSERT(thr->valstack_bottom == NULL);
	DUK_ASSERT(thr->valstack_top == NULL);
	DUK_ASSERT(thr->callstack_curr == NULL);

	/* valstack */
	DUK_ASSERT(DUK_VALSTACK_API_ENTRY_MINIMUM <= DUK_VALSTACK_INITIAL_SIZE);
	alloc_size = sizeof(duk_tval) * DUK_VALSTACK_INITIAL_SIZE;
	thr->valstack = (duk_tval *) DUK_ALLOC(heap, alloc_size);
	if (!thr->valstack) {
		goto fail;
	}
	duk_memzero(thr->valstack, alloc_size);
	thr->valstack_end = thr->valstack + DUK_VALSTACK_API_ENTRY_MINIMUM;
	thr->valstack_alloc_end = thr->valstack + DUK_VALSTACK_INITIAL_SIZE;
	thr->valstack_bottom = thr->valstack;
	thr->valstack_top = thr->valstack;

	for (i = 0; i < DUK_VALSTACK_INITIAL_SIZE; i++) {
		DUK_TVAL_SET_UNDEFINED(&thr->valstack[i]);
	}

	return 1;

 fail:
	DUK_FREE(heap, thr->valstack);
	DUK_ASSERT(thr->callstack_curr == NULL);

	thr->valstack = NULL;
	return 0;
}

/* For indirect allocs. */

DUK_INTERNAL void *duk_hthread_get_valstack_ptr(duk_heap *heap, void *ud) {
	duk_hthread *thr = (duk_hthread *) ud;
	DUK_UNREF(heap);
	return (void *) thr->valstack;
}
#line 1 "duk_hthread_builtins.c"
/*
 *  Initialize built-in objects.  Current thread must have a valstack
 *  and initialization errors may longjmp, so a setjmp() catch point
 *  must exist.
 */

/* #include duk_internal.h -> already included */

/*
 *  Encoding constants, must match genbuiltins.py
 */

#define DUK__PROP_FLAGS_BITS             3
#define DUK__LENGTH_PROP_BITS            3
#define DUK__NARGS_BITS                  3
#define DUK__PROP_TYPE_BITS              3

#define DUK__NARGS_VARARGS_MARKER        0x07

#define DUK__PROP_TYPE_DOUBLE            0
#define DUK__PROP_TYPE_STRING            1
#define DUK__PROP_TYPE_STRIDX            2
#define DUK__PROP_TYPE_BUILTIN           3
#define DUK__PROP_TYPE_UNDEFINED         4
#define DUK__PROP_TYPE_BOOLEAN_TRUE      5
#define DUK__PROP_TYPE_BOOLEAN_FALSE     6
#define DUK__PROP_TYPE_ACCESSOR          7

/*
 *  Create built-in objects by parsing an init bitstream generated
 *  by genbuiltins.py.
 */

#if defined(DUK_USE_ROM_OBJECTS)
#if defined(DUK_USE_ROM_GLOBAL_CLONE) || defined(DUK_USE_ROM_GLOBAL_INHERIT)
DUK_LOCAL void duk__duplicate_ram_global_object(duk_hthread *thr) {
	duk_hobject *h_global;
#if defined(DUK_USE_ROM_GLOBAL_CLONE)
	duk_hobject *h_oldglobal;
	duk_uint8_t *props;
	duk_size_t alloc_size;
#endif
	duk_hobject *h_objenv;

	/* XXX: refactor into internal helper, duk_clone_hobject() */

#if defined(DUK_USE_ROM_GLOBAL_INHERIT)
	/* Inherit from ROM-based global object: less RAM usage, less transparent. */
	h_global = duk_push_object_helper(thr,
	                                  DUK_HOBJECT_FLAG_EXTENSIBLE |
	                                  DUK_HOBJECT_FLAG_FASTREFS |
	                                  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_GLOBAL),
	                                  DUK_BIDX_GLOBAL);
	DUK_ASSERT(h_global != NULL);
#elif defined(DUK_USE_ROM_GLOBAL_CLONE)
	/* Clone the properties of the ROM-based global object to create a
	 * fully RAM-based global object.  Uses more memory than the inherit
	 * model but more compliant.
	 */
	h_global = duk_push_object_helper(thr,
	                                  DUK_HOBJECT_FLAG_EXTENSIBLE |
	                                  DUK_HOBJECT_FLAG_FASTREFS |
	                                  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_GLOBAL),
	                                  DUK_BIDX_OBJECT_PROTOTYPE);
	DUK_ASSERT(h_global != NULL);
	h_oldglobal = thr->builtins[DUK_BIDX_GLOBAL];
	DUK_ASSERT(h_oldglobal != NULL);

	/* Copy the property table verbatim; this handles attributes etc.
	 * For ROM objects it's not necessary (or possible) to update
	 * refcounts so leave them as is.
	 */
	alloc_size = DUK_HOBJECT_P_ALLOC_SIZE(h_oldglobal);
	DUK_ASSERT(alloc_size > 0);
	props = DUK_ALLOC_CHECKED(thr, alloc_size);
	DUK_ASSERT(props != NULL);
	DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, h_oldglobal) != NULL);
	duk_memcpy((void *) props, (const void *) DUK_HOBJECT_GET_PROPS(thr->heap, h_oldglobal), alloc_size);

	/* XXX: keep property attributes or tweak them here?
	 * Properties will now be non-configurable even when they're
	 * normally configurable for the global object.
	 */

	DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, h_global) == NULL);
	DUK_HOBJECT_SET_PROPS(thr->heap, h_global, props);
	DUK_HOBJECT_SET_ESIZE(h_global, DUK_HOBJECT_GET_ESIZE(h_oldglobal));
	DUK_HOBJECT_SET_ENEXT(h_global, DUK_HOBJECT_GET_ENEXT(h_oldglobal));
	DUK_HOBJECT_SET_ASIZE(h_global, DUK_HOBJECT_GET_ASIZE(h_oldglobal));
	DUK_HOBJECT_SET_HSIZE(h_global, DUK_HOBJECT_GET_HSIZE(h_oldglobal));
#else
#error internal error in config defines
#endif

	duk_hobject_compact_props(thr, h_global);
	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
	DUK_ASSERT(!DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE((duk_heaphdr *) thr->builtins[DUK_BIDX_GLOBAL]));  /* no need to decref: ROM object */
	thr->builtins[DUK_BIDX_GLOBAL] = h_global;
	DUK_HOBJECT_INCREF(thr, h_global);
	DUK_D(DUK_DPRINT("duplicated global object: %!O", h_global));

	/* Create a fresh object environment for the global scope.  This is
	 * needed so that the global scope points to the newly created RAM-based
	 * global object.
	 */
	h_objenv = (duk_hobject *) duk_hobjenv_alloc(thr,
	                                             DUK_HOBJECT_FLAG_EXTENSIBLE |
	                                             DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJENV));
	DUK_ASSERT(h_objenv != NULL);
	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_objenv) == NULL);
	duk_push_hobject(thr, h_objenv);

	DUK_ASSERT(h_global != NULL);
	((duk_hobjenv *) h_objenv)->target = h_global;
	DUK_HOBJECT_INCREF(thr, h_global);
	DUK_ASSERT(((duk_hobjenv *) h_objenv)->has_this == 0);

	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL_ENV] != NULL);
	DUK_ASSERT(!DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE((duk_heaphdr *) thr->builtins[DUK_BIDX_GLOBAL_ENV]));  /* no need to decref: ROM object */
	thr->builtins[DUK_BIDX_GLOBAL_ENV] = h_objenv;
	DUK_HOBJECT_INCREF(thr, h_objenv);
	DUK_D(DUK_DPRINT("duplicated global env: %!O", h_objenv));

	DUK_HOBJENV_ASSERT_VALID((duk_hobjenv *) h_objenv);

	duk_pop_2(thr);  /* Pop global object and global env. */
}
#endif  /* DUK_USE_ROM_GLOBAL_CLONE || DUK_USE_ROM_GLOBAL_INHERIT */

DUK_INTERNAL void duk_hthread_create_builtin_objects(duk_hthread *thr) {
	/* Setup builtins from ROM objects.  All heaps/threads will share
	 * the same readonly objects.
	 */
	duk_small_uint_t i;

	for (i = 0; i < DUK_NUM_BUILTINS; i++) {
		duk_hobject *h;
		h = (duk_hobject *) DUK_LOSE_CONST(duk_rom_builtins_bidx[i]);
		DUK_ASSERT(h != NULL);
		thr->builtins[i] = h;
	}

#if defined(DUK_USE_ROM_GLOBAL_CLONE) || defined(DUK_USE_ROM_GLOBAL_INHERIT)
	/* By default the global object is read-only which is often much
	 * more of an issue than having read-only built-in objects (like
	 * RegExp, Date, etc).  Use a RAM-based copy of the global object
	 * and the global environment object for convenience.
	 */
	duk__duplicate_ram_global_object(thr);
#endif
}
#else  /* DUK_USE_ROM_OBJECTS */
DUK_LOCAL void duk__push_stridx(duk_hthread *thr, duk_bitdecoder_ctx *bd) {
	duk_small_uint_t n;

	n = (duk_small_uint_t) duk_bd_decode_varuint(bd);
	DUK_ASSERT_DISABLE(n >= 0);  /* unsigned */
	DUK_ASSERT(n < DUK_HEAP_NUM_STRINGS);
	duk_push_hstring_stridx(thr, n);
}
DUK_LOCAL void duk__push_string(duk_hthread *thr, duk_bitdecoder_ctx *bd) {
	/* XXX: built-ins data could provide a maximum length that is
	 * actually needed; bitpacked max length is now 256 bytes.
	 */
	duk_uint8_t tmp[DUK_BD_BITPACKED_STRING_MAXLEN];
	duk_small_uint_t len;

	len = duk_bd_decode_bitpacked_string(bd, tmp);
	duk_push_lstring(thr, (const char *) tmp, (duk_size_t) len);
}
DUK_LOCAL void duk__push_stridx_or_string(duk_hthread *thr, duk_bitdecoder_ctx *bd) {
	duk_small_uint_t n;

	n = (duk_small_uint_t) duk_bd_decode_varuint(bd);
	if (n == 0) {
		duk__push_string(thr, bd);
	} else {
		n--;
		DUK_ASSERT(n < DUK_HEAP_NUM_STRINGS);
		duk_push_hstring_stridx(thr, n);
	}
}
DUK_LOCAL void duk__push_double(duk_hthread *thr, duk_bitdecoder_ctx *bd) {
	duk_double_union du;
	duk_small_uint_t i;

	for (i = 0; i < 8; i++) {
		/* Encoding endianness must match target memory layout,
		 * build scripts and genbuiltins.py must ensure this.
		 */
		du.uc[i] = (duk_uint8_t) duk_bd_decode(bd, 8);
	}

	duk_push_number(thr, du.d);  /* push operation normalizes NaNs */
}

DUK_INTERNAL void duk_hthread_create_builtin_objects(duk_hthread *thr) {
	duk_bitdecoder_ctx bd_ctx;
	duk_bitdecoder_ctx *bd = &bd_ctx;  /* convenience */
	duk_hobject *h;
	duk_small_uint_t i, j;

	DUK_D(DUK_DPRINT("INITBUILTINS BEGIN: DUK_NUM_BUILTINS=%d, DUK_NUM_BUILTINS_ALL=%d", (int) DUK_NUM_BUILTINS, (int) DUK_NUM_ALL_BUILTINS));

	duk_memzero(&bd_ctx, sizeof(bd_ctx));
	bd->data = (const duk_uint8_t *) duk_builtins_data;
	bd->length = (duk_size_t) DUK_BUILTINS_DATA_LENGTH;

	/*
	 *  First create all built-in bare objects on the empty valstack.
	 *
	 *  Built-ins in the index range [0,DUK_NUM_BUILTINS-1] have value
	 *  stack indices matching their eventual thr->builtins[] index.
	 *
	 *  Built-ins in the index range [DUK_NUM_BUILTINS,DUK_NUM_ALL_BUILTINS]
	 *  will exist on the value stack during init but won't be placed
	 *  into thr->builtins[].  These are objects referenced in some way
	 *  from thr->builtins[] roots but which don't need to be indexed by
	 *  Duktape through thr->builtins[] (e.g. user custom objects).
	 *
	 *  Internal prototypes will be incorrect (NULL) at this stage.
	 */

	duk_require_stack(thr, DUK_NUM_ALL_BUILTINS);

	DUK_DD(DUK_DDPRINT("create empty built-ins"));
	DUK_ASSERT_TOP(thr, 0);
	for (i = 0; i < DUK_NUM_ALL_BUILTINS; i++) {
		duk_small_uint_t class_num;
		duk_small_int_t len = -1;  /* must be signed */

		class_num = (duk_small_uint_t) duk_bd_decode_varuint(bd);
		len = (duk_small_int_t) duk_bd_decode_flagged_signed(bd, DUK__LENGTH_PROP_BITS, (duk_int32_t) -1 /*def_value*/);

		if (class_num == DUK_HOBJECT_CLASS_FUNCTION) {
			duk_small_uint_t natidx;
			duk_small_int_t c_nargs;  /* must hold DUK_VARARGS */
			duk_c_function c_func;
			duk_int16_t magic;

			DUK_DDD(DUK_DDDPRINT("len=%ld", (long) len));
			DUK_ASSERT(len >= 0);

			natidx = (duk_small_uint_t) duk_bd_decode_varuint(bd);
			DUK_ASSERT(natidx != 0);
			c_func = duk_bi_native_functions[natidx];
			DUK_ASSERT(c_func != NULL);

			c_nargs = (duk_small_int_t) duk_bd_decode_flagged_signed(bd, DUK__NARGS_BITS, len /*def_value*/);
			if (c_nargs == DUK__NARGS_VARARGS_MARKER) {
				c_nargs = DUK_VARARGS;
			}

			/* XXX: set magic directly here? (it could share the c_nargs arg) */
			(void) duk_push_c_function_builtin(thr, c_func, c_nargs);
			h = duk_known_hobject(thr, -1);

			/* Currently all built-in native functions are strict.
			 * duk_push_c_function() now sets strict flag, so
			 * assert for it.
			 */
			DUK_ASSERT(DUK_HOBJECT_HAS_STRICT(h));

			/* XXX: function properties */

			duk__push_stridx_or_string(thr, bd);
#if defined(DUK_USE_FUNC_NAME_PROPERTY)
			duk_xdef_prop_stridx_short(thr,
			                           -2,
			                           DUK_STRIDX_NAME,
			                           DUK_PROPDESC_FLAGS_C);
#else
			duk_pop(thr);  /* Not very ideal but good enough for now. */
#endif

			/* Almost all global level Function objects are constructable
			 * but not all: Function.prototype is a non-constructable,
			 * callable Function.
			 */
			if (duk_bd_decode_flag(bd)) {
				DUK_ASSERT(DUK_HOBJECT_HAS_CONSTRUCTABLE(h));
			} else {
				DUK_HOBJECT_CLEAR_CONSTRUCTABLE(h);
			}

			/* Cast converts magic to 16-bit signed value */
			magic = (duk_int16_t) duk_bd_decode_varuint(bd);
			((duk_hnatfunc *) h)->magic = magic;
		} else if (class_num == DUK_HOBJECT_CLASS_ARRAY) {
			duk_push_array(thr);
		} else if (class_num == DUK_HOBJECT_CLASS_OBJENV) {
			duk_hobjenv *env;
			duk_hobject *global;

			DUK_ASSERT(i == DUK_BIDX_GLOBAL_ENV);
			DUK_ASSERT(DUK_BIDX_GLOBAL_ENV > DUK_BIDX_GLOBAL);

			env = duk_hobjenv_alloc(thr,
	                                        DUK_HOBJECT_FLAG_EXTENSIBLE |
	                                        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJENV));
			DUK_ASSERT(env->target == NULL);
			duk_push_hobject(thr, (duk_hobject *) env);

			global = duk_known_hobject(thr, DUK_BIDX_GLOBAL);
			DUK_ASSERT(global != NULL);
			env->target = global;
			DUK_HOBJECT_INCREF(thr, global);
			DUK_ASSERT(env->has_this == 0);

			DUK_HOBJENV_ASSERT_VALID(env);
		} else {
			DUK_ASSERT(class_num != DUK_HOBJECT_CLASS_DECENV);

			(void) duk_push_object_helper(thr,
			                              DUK_HOBJECT_FLAG_FASTREFS |
			                              DUK_HOBJECT_FLAG_EXTENSIBLE,
			                              -1);  /* no prototype or class yet */

		}

		h = duk_known_hobject(thr, -1);
		DUK_HOBJECT_SET_CLASS_NUMBER(h, class_num);

		if (i < DUK_NUM_BUILTINS) {
			thr->builtins[i] = h;
			DUK_HOBJECT_INCREF(thr, &h->hdr);
		}

		if (len >= 0) {
			/* In ES2015+ built-in function object .length property
			 * has property attributes C (configurable only):
			 * http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-standard-built-in-objects
			 *
			 * Array.prototype remains an Array instance in ES2015+
			 * and its length has attributes W (writable only).
			 * Because .length is now virtual for duk_harray, it is
			 * not encoded explicitly in init data.
			 */

			DUK_ASSERT(class_num != DUK_HOBJECT_CLASS_ARRAY);  /* .length is virtual */
			duk_push_int(thr, len);
			duk_xdef_prop_stridx_short(thr,
			                           -2,
			                           DUK_STRIDX_LENGTH,
			                           DUK_PROPDESC_FLAGS_C);
		}

		/* enable exotic behaviors last */

		if (class_num == DUK_HOBJECT_CLASS_ARRAY) {
			DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY(h));  /* set by duk_push_array() */
		}
		if (class_num == DUK_HOBJECT_CLASS_STRING) {
			DUK_HOBJECT_SET_EXOTIC_STRINGOBJ(h);
		}

		/* some assertions */

		DUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE(h));
		/* DUK_HOBJECT_FLAG_CONSTRUCTABLE varies */
		DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(h));
		DUK_ASSERT(!DUK_HOBJECT_HAS_COMPFUNC(h));
		/* DUK_HOBJECT_FLAG_NATFUNC varies */
		DUK_ASSERT(!DUK_HOBJECT_IS_THREAD(h));
		DUK_ASSERT(!DUK_HOBJECT_IS_PROXY(h));
		DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(h) || class_num == DUK_HOBJECT_CLASS_ARRAY);
		/* DUK_HOBJECT_FLAG_STRICT varies */
		DUK_ASSERT(!DUK_HOBJECT_HAS_NATFUNC(h) ||  /* all native functions have NEWENV */
		           DUK_HOBJECT_HAS_NEWENV(h));
		DUK_ASSERT(!DUK_HOBJECT_HAS_NAMEBINDING(h));
		DUK_ASSERT(!DUK_HOBJECT_HAS_CREATEARGS(h));
		/* DUK_HOBJECT_FLAG_EXOTIC_ARRAY varies */
		/* DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ varies */
		DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(h));

		DUK_DDD(DUK_DDDPRINT("created built-in %ld, class=%ld, length=%ld", (long) i, (long) class_num, (long) len));
	}

	/*
	 *  Then decode the builtins init data (see genbuiltins.py) to
	 *  init objects.  Internal prototypes are set at this stage,
	 *  with thr->builtins[] populated.
	 */

	DUK_DD(DUK_DDPRINT("initialize built-in object properties"));
	for (i = 0; i < DUK_NUM_ALL_BUILTINS; i++) {
		duk_small_uint_t t;
		duk_small_uint_t num;

		DUK_DDD(DUK_DDDPRINT("initializing built-in object at index %ld", (long) i));
		h = duk_known_hobject(thr, (duk_idx_t) i);

		t = (duk_small_uint_t) duk_bd_decode_varuint(bd);
		if (t > 0) {
			t--;
			DUK_DDD(DUK_DDDPRINT("set internal prototype: built-in %ld", (long) t));
			DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h, duk_known_hobject(thr, (duk_idx_t) t));
		} else if (DUK_HOBJECT_IS_NATFUNC(h)) {
			/* Standard native built-ins cannot inherit from
			 * %NativeFunctionPrototype%, they are required to
			 * inherit from Function.prototype directly.
			 */
			DUK_ASSERT(thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE] != NULL);
			DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h, thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
		}

		t = (duk_small_uint_t) duk_bd_decode_varuint(bd);
		if (t > 0) {
			/* 'prototype' property for all built-in objects (which have it) has attributes:
			 *  [[Writable]] = false,
			 *  [[Enumerable]] = false,
			 *  [[Configurable]] = false
			 */
			t--;
			DUK_DDD(DUK_DDDPRINT("set external prototype: built-in %ld", (long) t));
			duk_dup(thr, (duk_idx_t) t);
			duk_xdef_prop_stridx(thr, (duk_idx_t) i, DUK_STRIDX_PROTOTYPE, DUK_PROPDESC_FLAGS_NONE);
		}

		t = (duk_small_uint_t) duk_bd_decode_varuint(bd);
		if (t > 0) {
			/* 'constructor' property for all built-in objects (which have it) has attributes:
			 *  [[Writable]] = true,
			 *  [[Enumerable]] = false,
			 *  [[Configurable]] = true
			 */
			t--;
			DUK_DDD(DUK_DDDPRINT("set external constructor: built-in %ld", (long) t));
			duk_dup(thr, (duk_idx_t) t);
			duk_xdef_prop_stridx(thr, (duk_idx_t) i, DUK_STRIDX_CONSTRUCTOR, DUK_PROPDESC_FLAGS_WC);
		}

		/* normal valued properties */
		num = (duk_small_uint_t) duk_bd_decode_varuint(bd);
		DUK_DDD(DUK_DDDPRINT("built-in object %ld, %ld normal valued properties", (long) i, (long) num));
		for (j = 0; j < num; j++) {
			duk_small_uint_t defprop_flags;

			duk__push_stridx_or_string(thr, bd);

			/*
			 *  Property attribute defaults are defined in E5 Section 15 (first
			 *  few pages); there is a default for all properties and a special
			 *  default for 'length' properties.  Variation from the defaults is
			 *  signaled using a single flag bit in the bitstream.
			 */

			defprop_flags = (duk_small_uint_t) duk_bd_decode_flagged(bd,
			                                                         DUK__PROP_FLAGS_BITS,
			                                                         (duk_uint32_t) DUK_PROPDESC_FLAGS_WC);
			defprop_flags |= DUK_DEFPROP_FORCE |
			                 DUK_DEFPROP_HAVE_VALUE |
			                 DUK_DEFPROP_HAVE_WRITABLE |
			                 DUK_DEFPROP_HAVE_ENUMERABLE |
			                 DUK_DEFPROP_HAVE_CONFIGURABLE;  /* Defaults for data properties. */

			/* The writable, enumerable, configurable flags in prop_flags
			 * match both duk_def_prop() and internal property flags.
			 */
			DUK_ASSERT(DUK_PROPDESC_FLAG_WRITABLE == DUK_DEFPROP_WRITABLE);
			DUK_ASSERT(DUK_PROPDESC_FLAG_ENUMERABLE == DUK_DEFPROP_ENUMERABLE);
			DUK_ASSERT(DUK_PROPDESC_FLAG_CONFIGURABLE == DUK_DEFPROP_CONFIGURABLE);

			t = (duk_small_uint_t) duk_bd_decode(bd, DUK__PROP_TYPE_BITS);

			DUK_DDD(DUK_DDDPRINT("built-in %ld, normal-valued property %ld, key %!T, flags 0x%02lx, type %ld",
			                     (long) i, (long) j, duk_get_tval(thr, -1), (unsigned long) defprop_flags, (long) t));

			switch (t) {
			case DUK__PROP_TYPE_DOUBLE: {
				duk__push_double(thr, bd);
				break;
			}
			case DUK__PROP_TYPE_STRING: {
				duk__push_string(thr, bd);
				break;
			}
			case DUK__PROP_TYPE_STRIDX: {
				duk__push_stridx(thr, bd);
				break;
			}
			case DUK__PROP_TYPE_BUILTIN: {
				duk_small_uint_t bidx;

				bidx = (duk_small_uint_t) duk_bd_decode_varuint(bd);
				duk_dup(thr, (duk_idx_t) bidx);
				break;
			}
			case DUK__PROP_TYPE_UNDEFINED: {
				duk_push_undefined(thr);
				break;
			}
			case DUK__PROP_TYPE_BOOLEAN_TRUE: {
				duk_push_true(thr);
				break;
			}
			case DUK__PROP_TYPE_BOOLEAN_FALSE: {
				duk_push_false(thr);
				break;
			}
			case DUK__PROP_TYPE_ACCESSOR: {
				duk_small_uint_t natidx_getter = (duk_small_uint_t) duk_bd_decode_varuint(bd);
				duk_small_uint_t natidx_setter = (duk_small_uint_t) duk_bd_decode_varuint(bd);
				duk_small_uint_t accessor_magic = (duk_small_uint_t) duk_bd_decode_varuint(bd);
				duk_c_function c_func_getter;
				duk_c_function c_func_setter;

				DUK_DDD(DUK_DDDPRINT("built-in accessor property: objidx=%ld, key=%!T, getteridx=%ld, setteridx=%ld, flags=0x%04lx",
				                     (long) i, duk_get_tval(thr, -1), (long) natidx_getter, (long) natidx_setter, (unsigned long) defprop_flags));

				c_func_getter = duk_bi_native_functions[natidx_getter];
				if (c_func_getter != NULL) {
					duk_push_c_function_builtin_noconstruct(thr, c_func_getter, 0);  /* always 0 args */
					duk_set_magic(thr, -1, (duk_int_t) accessor_magic);
					defprop_flags |= DUK_DEFPROP_HAVE_GETTER;
				}
				c_func_setter = duk_bi_native_functions[natidx_setter];
				if (c_func_setter != NULL) {
					duk_push_c_function_builtin_noconstruct(thr, c_func_setter, 1);  /* always 1 arg */
					duk_set_magic(thr, -1, (duk_int_t) accessor_magic);
					defprop_flags |= DUK_DEFPROP_HAVE_SETTER;
				}

				/* Writable flag doesn't make sense for an accessor. */
				DUK_ASSERT((defprop_flags & DUK_PROPDESC_FLAG_WRITABLE) == 0);  /* genbuiltins.py ensures */

				defprop_flags &= ~(DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_HAVE_WRITABLE);
				defprop_flags |= DUK_DEFPROP_HAVE_ENUMERABLE | DUK_DEFPROP_HAVE_CONFIGURABLE;
				break;
			}
			default: {
				/* exhaustive */
				DUK_UNREACHABLE();
			}
			}

			duk_def_prop(thr, (duk_idx_t) i, defprop_flags);
			DUK_ASSERT_TOP(thr, DUK_NUM_ALL_BUILTINS);
		}

		/* native function properties */
		num = (duk_small_uint_t) duk_bd_decode_varuint(bd);
		DUK_DDD(DUK_DDDPRINT("built-in object %ld, %ld function valued properties", (long) i, (long) num));
		for (j = 0; j < num; j++) {
			duk_hstring *h_key;
			duk_small_uint_t natidx;
			duk_int_t c_nargs;  /* must hold DUK_VARARGS */
			duk_small_uint_t c_length;
			duk_int16_t magic;
			duk_c_function c_func;
			duk_hnatfunc *h_func;
#if defined(DUK_USE_LIGHTFUNC_BUILTINS)
			duk_small_int_t lightfunc_eligible;
#endif
			duk_small_uint_t defprop_flags;

			duk__push_stridx_or_string(thr, bd);
			h_key = duk_known_hstring(thr, -1);
			DUK_UNREF(h_key);
			natidx = (duk_small_uint_t) duk_bd_decode_varuint(bd);

			c_length = (duk_small_uint_t) duk_bd_decode(bd, DUK__LENGTH_PROP_BITS);
			c_nargs = (duk_int_t) duk_bd_decode_flagged(bd, DUK__NARGS_BITS, (duk_uint32_t) c_length /*def_value*/);
			if (c_nargs == DUK__NARGS_VARARGS_MARKER) {
				c_nargs = DUK_VARARGS;
			}

			c_func = duk_bi_native_functions[natidx];

			DUK_DDD(DUK_DDDPRINT("built-in %ld, function-valued property %ld, key %!O, natidx %ld, length %ld, nargs %ld",
			                     (long) i, (long) j, (duk_heaphdr *) h_key, (long) natidx, (long) c_length,
			                     (c_nargs == DUK_VARARGS ? (long) -1 : (long) c_nargs)));

			/* Cast converts magic to 16-bit signed value */
			magic = (duk_int16_t) duk_bd_decode_varuint(bd);

#if defined(DUK_USE_LIGHTFUNC_BUILTINS)
			lightfunc_eligible =
				((c_nargs >= DUK_LFUNC_NARGS_MIN && c_nargs <= DUK_LFUNC_NARGS_MAX) || (c_nargs == DUK_VARARGS)) &&
				(c_length <= DUK_LFUNC_LENGTH_MAX) &&
				(magic >= DUK_LFUNC_MAGIC_MIN && magic <= DUK_LFUNC_MAGIC_MAX);

			/* These functions have trouble working as lightfuncs.
			 * Some of them have specific asserts and some may have
		         * additional properties (e.g. 'require.id' may be written).
			 */
			if (c_func == duk_bi_global_object_eval) {
				lightfunc_eligible = 0;
			}
#if defined(DUK_USE_COROUTINE_SUPPORT)
			if (c_func == duk_bi_thread_yield ||
			    c_func == duk_bi_thread_resume) {
				lightfunc_eligible = 0;
			}
#endif
			if (c_func == duk_bi_function_prototype_call ||
			    c_func == duk_bi_function_prototype_apply ||
			    c_func == duk_bi_reflect_apply ||
			    c_func == duk_bi_reflect_construct) {
				lightfunc_eligible = 0;
			}

			if (lightfunc_eligible) {
				duk_tval tv_lfunc;
				duk_small_uint_t lf_nargs = (duk_small_uint_t) (c_nargs == DUK_VARARGS ? DUK_LFUNC_NARGS_VARARGS : c_nargs);
				duk_small_uint_t lf_flags = DUK_LFUNC_FLAGS_PACK(magic, c_length, lf_nargs);
				DUK_TVAL_SET_LIGHTFUNC(&tv_lfunc, c_func, lf_flags);
				duk_push_tval(thr, &tv_lfunc);
				DUK_D(DUK_DPRINT("built-in function eligible as light function: i=%d, j=%d c_length=%ld, c_nargs=%ld, magic=%ld -> %!iT", (int) i, (int) j, (long) c_length, (long) c_nargs, (long) magic, duk_get_tval(thr, -1)));
				goto lightfunc_skip;
			}

			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));
#endif  /* DUK_USE_LIGHTFUNC_BUILTINS */

			/* [ (builtin objects) name ] */

			duk_push_c_function_builtin_noconstruct(thr, c_func, c_nargs);
			h_func = duk_known_hnatfunc(thr, -1);
			DUK_UNREF(h_func);

			/* XXX: add into init data? */

			/* Special call handling, not described in init data. */
			if (c_func == duk_bi_global_object_eval ||
			    c_func == duk_bi_function_prototype_call ||
			    c_func == duk_bi_function_prototype_apply ||
			    c_func == duk_bi_reflect_apply ||
			    c_func == duk_bi_reflect_construct) {
				DUK_HOBJECT_SET_SPECIAL_CALL((duk_hobject *) h_func);
			}

			/* Currently all built-in native functions are strict.
			 * This doesn't matter for many functions, but e.g.
			 * String.prototype.charAt (and other string functions)
			 * rely on being strict so that their 'this' binding is
			 * not automatically coerced.
			 */
			DUK_HOBJECT_SET_STRICT((duk_hobject *) h_func);

			/* No built-in functions are constructable except the top
			 * level ones (Number, etc).
			 */
			DUK_ASSERT(!DUK_HOBJECT_HAS_CONSTRUCTABLE((duk_hobject *) h_func));

			/* XXX: any way to avoid decoding magic bit; there are quite
			 * many function properties and relatively few with magic values.
			 */
			h_func->magic = magic;

			/* [ (builtin objects) name func ] */

			duk_push_uint(thr, c_length);
			duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_C);

			duk_dup_m2(thr);
			duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_C);

			/* XXX: other properties of function instances; 'arguments', 'caller'. */

			DUK_DD(DUK_DDPRINT("built-in object %ld, function property %ld -> %!T",
			                   (long) i, (long) j, (duk_tval *) duk_get_tval(thr, -1)));

			/* [ (builtin objects) name func ] */

			/*
			 *  The default property attributes are correct for all
			 *  function valued properties of built-in objects now.
			 */

#if defined(DUK_USE_LIGHTFUNC_BUILTINS)
		 lightfunc_skip:
#endif

			defprop_flags = (duk_small_uint_t) duk_bd_decode_flagged(bd,
			                                                         DUK__PROP_FLAGS_BITS,
			                                                         (duk_uint32_t) DUK_PROPDESC_FLAGS_WC);
			defprop_flags |= DUK_DEFPROP_FORCE |
			                 DUK_DEFPROP_HAVE_VALUE |
			                 DUK_DEFPROP_HAVE_WRITABLE |
			                 DUK_DEFPROP_HAVE_ENUMERABLE |
			                 DUK_DEFPROP_HAVE_CONFIGURABLE;
			DUK_ASSERT(DUK_PROPDESC_FLAG_WRITABLE == DUK_DEFPROP_WRITABLE);
			DUK_ASSERT(DUK_PROPDESC_FLAG_ENUMERABLE == DUK_DEFPROP_ENUMERABLE);
			DUK_ASSERT(DUK_PROPDESC_FLAG_CONFIGURABLE == DUK_DEFPROP_CONFIGURABLE);

			duk_def_prop(thr, (duk_idx_t) i, defprop_flags);

			/* [ (builtin objects) ] */
		}
	}

	/*
	 *  Special post-tweaks, for cases not covered by the init data format.
	 *
	 *  - Set Date.prototype.toGMTString to Date.prototype.toUTCString.
	 *    toGMTString is required to have the same Function object as
	 *    toUTCString in E5 Section B.2.6.  Note that while Smjs respects
	 *    this, V8 does not (the Function objects are distinct).
	 *
	 *  - Make DoubleError non-extensible.
	 *
	 *  - Add info about most important effective compile options to Duktape.
	 *
	 *  - Possibly remove some properties (values or methods) which are not
	 *    desirable with current feature options but are not currently
	 *    conditional in init data.
	 */

#if defined(DUK_USE_DATE_BUILTIN)
	duk_get_prop_stridx_short(thr, DUK_BIDX_DATE_PROTOTYPE, DUK_STRIDX_TO_UTC_STRING);
	duk_xdef_prop_stridx_short(thr, DUK_BIDX_DATE_PROTOTYPE, DUK_STRIDX_TO_GMT_STRING, DUK_PROPDESC_FLAGS_WC);
#endif

	h = duk_known_hobject(thr, DUK_BIDX_DOUBLE_ERROR);
	DUK_HOBJECT_CLEAR_EXTENSIBLE(h);

#if !defined(DUK_USE_ES6_OBJECT_PROTO_PROPERTY)
	DUK_DD(DUK_DDPRINT("delete Object.prototype.__proto__ built-in which is not enabled in features"));
	(void) duk_hobject_delprop_raw(thr, thr->builtins[DUK_BIDX_OBJECT_PROTOTYPE], DUK_HTHREAD_STRING___PROTO__(thr), DUK_DELPROP_FLAG_THROW);
#endif

#if !defined(DUK_USE_ES6_OBJECT_SETPROTOTYPEOF)
	DUK_DD(DUK_DDPRINT("delete Object.setPrototypeOf built-in which is not enabled in features"));
	(void) duk_hobject_delprop_raw(thr, thr->builtins[DUK_BIDX_OBJECT_CONSTRUCTOR], DUK_HTHREAD_STRING_SET_PROTOTYPE_OF(thr), DUK_DELPROP_FLAG_THROW);
#endif

	/* XXX: relocate */
	duk_push_string(thr,
			/* Endianness indicator */
#if defined(DUK_USE_INTEGER_LE)
	                "l"
#elif defined(DUK_USE_INTEGER_BE)
	                "b"
#elif defined(DUK_USE_INTEGER_ME)  /* integer mixed endian not really used now */
	                "m"
#else
	                "?"
#endif
#if defined(DUK_USE_DOUBLE_LE)
	                "l"
#elif defined(DUK_USE_DOUBLE_BE)
	                "b"
#elif defined(DUK_USE_DOUBLE_ME)
	                "m"
#else
	                "?"
#endif
	                " "
			/* Packed or unpacked tval */
#if defined(DUK_USE_PACKED_TVAL)
	                "p"
#else
	                "u"
#endif
#if defined(DUK_USE_FASTINT)
			"f"
#endif
			" "
			/* Low memory/performance options */
#if defined(DUK_USE_STRTAB_PTRCOMP)
			"s"
#endif
#if !defined(DUK_USE_HEAPPTR16) && !defined(DUK_DATAPTR16) && !defined(DUK_FUNCPTR16)
			"n"
#endif
#if defined(DUK_USE_HEAPPTR16)
			"h"
#endif
#if defined(DUK_USE_DATAPTR16)
			"d"
#endif
#if defined(DUK_USE_FUNCPTR16)
			"f"
#endif
#if defined(DUK_USE_REFCOUNT16)
			"R"
#endif
#if defined(DUK_USE_STRHASH16)
			"H"
#endif
#if defined(DUK_USE_STRLEN16)
			"S"
#endif
#if defined(DUK_USE_BUFLEN16)
			"B"
#endif
#if defined(DUK_USE_OBJSIZES16)
			"O"
#endif
#if defined(DUK_USE_LIGHTFUNC_BUILTINS)
			"L"
#endif
#if defined(DUK_USE_ROM_STRINGS) || defined(DUK_USE_ROM_OBJECTS)
			/* XXX: This won't be shown in practice now
			 * because this code is not run when builtins
			 * are in ROM.
			 */
			"Z"
#endif
#if defined(DUK_USE_LITCACHE_SIZE)
			"l"
#endif
	                " "
			/* Object property allocation layout */
#if defined(DUK_USE_HOBJECT_LAYOUT_1)
			"p1"
#elif defined(DUK_USE_HOBJECT_LAYOUT_2)
			"p2"
#elif defined(DUK_USE_HOBJECT_LAYOUT_3)
			"p3"
#else
			"p?"
#endif
			" "
			/* Alignment guarantee */
#if (DUK_USE_ALIGN_BY == 4)
			"a4"
#elif (DUK_USE_ALIGN_BY == 8)
			"a8"
#elif (DUK_USE_ALIGN_BY == 1)
			"a1"
#else
#error invalid DUK_USE_ALIGN_BY
#endif
			" "
			/* Architecture, OS, and compiler strings */
	                DUK_USE_ARCH_STRING
			" "
	                DUK_USE_OS_STRING
			" "
	                DUK_USE_COMPILER_STRING);
	duk_xdef_prop_stridx_short(thr, DUK_BIDX_DUKTAPE, DUK_STRIDX_ENV, DUK_PROPDESC_FLAGS_WC);

	/*
	 *  Since built-ins are not often extended, compact them.
	 */

	DUK_DD(DUK_DDPRINT("compact built-ins"));
	for (i = 0; i < DUK_NUM_ALL_BUILTINS; i++) {
		duk_hobject_compact_props(thr, duk_known_hobject(thr, (duk_idx_t) i));
	}

	DUK_D(DUK_DPRINT("INITBUILTINS END"));

#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 1)
	for (i = 0; i < DUK_NUM_ALL_BUILTINS; i++) {
		DUK_DD(DUK_DDPRINT("built-in object %ld after initialization and compacting: %!@iO",
		                   (long) i, (duk_heaphdr *) duk_require_hobject(thr, (duk_idx_t) i)));
	}
#endif

	/*
	 *  Pop built-ins from stack: they are now INCREF'd and
	 *  reachable from the builtins[] array or indirectly
	 *  through builtins[].
	 */

	duk_set_top(thr, 0);
	DUK_ASSERT_TOP(thr, 0);
}
#endif  /* DUK_USE_ROM_OBJECTS */

DUK_INTERNAL void duk_hthread_copy_builtin_objects(duk_hthread *thr_from, duk_hthread *thr_to) {
	duk_small_uint_t i;

	for (i = 0; i < DUK_NUM_BUILTINS; i++) {
		thr_to->builtins[i] = thr_from->builtins[i];
		DUK_HOBJECT_INCREF_ALLOWNULL(thr_to, thr_to->builtins[i]);  /* side effect free */
	}
}

/* automatic undefs */
#undef DUK__LENGTH_PROP_BITS
#undef DUK__NARGS_BITS
#undef DUK__NARGS_VARARGS_MARKER
#undef DUK__PROP_FLAGS_BITS
#undef DUK__PROP_TYPE_ACCESSOR
#undef DUK__PROP_TYPE_BITS
#undef DUK__PROP_TYPE_BOOLEAN_FALSE
#undef DUK__PROP_TYPE_BOOLEAN_TRUE
#undef DUK__PROP_TYPE_BUILTIN
#undef DUK__PROP_TYPE_DOUBLE
#undef DUK__PROP_TYPE_STRIDX
#undef DUK__PROP_TYPE_STRING
#undef DUK__PROP_TYPE_UNDEFINED
#line 1 "duk_hthread_misc.c"
/*
 *  Thread support.
 */

/* #include duk_internal.h -> already included */

DUK_INTERNAL void duk_hthread_terminate(duk_hthread *thr) {
	DUK_ASSERT(thr != NULL);

	while (thr->callstack_curr != NULL) {
		duk_hthread_activation_unwind_norz(thr);
	}

	thr->valstack_bottom = thr->valstack;
	duk_set_top(thr, 0);  /* unwinds valstack, updating refcounts */

	thr->state = DUK_HTHREAD_STATE_TERMINATED;

	/* Here we could remove references to built-ins, but it may not be
	 * worth the effort because built-ins are quite likely to be shared
	 * with another (unterminated) thread, and terminated threads are also
	 * usually garbage collected quite quickly.
	 *
	 * We could also shrink the value stack here, but that also may not
	 * be worth the effort for the same reason.
	 */

	DUK_REFZERO_CHECK_SLOW(thr);
}

#if defined(DUK_USE_DEBUGGER_SUPPORT)
DUK_INTERNAL duk_uint_fast32_t duk_hthread_get_act_curr_pc(duk_hthread *thr, duk_activation *act) {
	duk_instr_t *bcode;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(act != NULL);
	DUK_UNREF(thr);

	/* XXX: store 'bcode' pointer to activation for faster lookup? */
	if (act->func && DUK_HOBJECT_IS_COMPFUNC(act->func)) {
		bcode = DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, (duk_hcompfunc *) (act->func));
		return (duk_uint_fast32_t) (act->curr_pc - bcode);
	}
	return 0;
}
#endif  /* DUK_USE_DEBUGGER_SUPPORT */

DUK_INTERNAL duk_uint_fast32_t duk_hthread_get_act_prev_pc(duk_hthread *thr, duk_activation *act) {
	duk_instr_t *bcode;
	duk_uint_fast32_t ret;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(act != NULL);
	DUK_UNREF(thr);

	if (act->func && DUK_HOBJECT_IS_COMPFUNC(act->func)) {
		bcode = DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, (duk_hcompfunc *) (act->func));
		ret = (duk_uint_fast32_t) (act->curr_pc - bcode);
		if (ret > 0) {
			ret--;
		}
		return ret;
	}
	return 0;
}

/* Write bytecode executor's curr_pc back to topmost activation (if any). */
DUK_INTERNAL void duk_hthread_sync_currpc(duk_hthread *thr) {
	duk_activation *act;

	DUK_ASSERT(thr != NULL);

	if (thr->ptr_curr_pc != NULL) {
		/* ptr_curr_pc != NULL only when bytecode executor is active. */
		DUK_ASSERT(thr->callstack_top > 0);
		DUK_ASSERT(thr->callstack_curr != NULL);
		act = thr->callstack_curr;
		DUK_ASSERT(act != NULL);
		act->curr_pc = *thr->ptr_curr_pc;
	}
}

DUK_INTERNAL void duk_hthread_sync_and_null_currpc(duk_hthread *thr) {
	duk_activation *act;

	DUK_ASSERT(thr != NULL);

	if (thr->ptr_curr_pc != NULL) {
		/* ptr_curr_pc != NULL only when bytecode executor is active. */
		DUK_ASSERT(thr->callstack_top > 0);
		DUK_ASSERT(thr->callstack_curr != NULL);
		act = thr->callstack_curr;
		DUK_ASSERT(act != NULL);
		act->curr_pc = *thr->ptr_curr_pc;
		thr->ptr_curr_pc = NULL;
	}
}
#line 1 "duk_hthread_stacks.c"
/*
 *  Thread stack (mainly call stack) primitives: allocation of activations,
 *  unwinding catchers and activations, etc.
 *
 *  Value stack handling is a part of the API implementation.
 */

/* #include duk_internal.h -> already included */

/* Unwind the topmost catcher of the current activation (caller must check that
 * both exist) without side effects.
 */
DUK_INTERNAL void duk_hthread_catcher_unwind_norz(duk_hthread *thr, duk_activation *act) {
	duk_catcher *cat;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(act != NULL);
	DUK_ASSERT(act->cat != NULL);  /* caller must check */
	cat = act->cat;
	DUK_ASSERT(cat != NULL);

	DUK_DDD(DUK_DDDPRINT("unwinding catch stack entry %p (lexenv check is done)", (void *) cat));

	if (DUK_CAT_HAS_LEXENV_ACTIVE(cat)) {
		duk_hobject *env;

		env = act->lex_env;             /* current lex_env of the activation (created for catcher) */
		DUK_ASSERT(env != NULL);        /* must be, since env was created when catcher was created */
		act->lex_env = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, env);  /* prototype is lex_env before catcher created */
		DUK_HOBJECT_INCREF(thr, act->lex_env);
		DUK_HOBJECT_DECREF_NORZ(thr, env);

		/* There is no need to decref anything else than 'env': if 'env'
		 * becomes unreachable, refzero will handle decref'ing its prototype.
		 */
	}

	act->cat = cat->parent;
	duk_hthread_catcher_free(thr, cat);
}

/* Same as above, but caller is certain no catcher-related lexenv may exist. */
DUK_INTERNAL void duk_hthread_catcher_unwind_nolexenv_norz(duk_hthread *thr, duk_activation *act) {
	duk_catcher *cat;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(act != NULL);
	DUK_ASSERT(act->cat != NULL);  /* caller must check */
	cat = act->cat;
	DUK_ASSERT(cat != NULL);

	DUK_DDD(DUK_DDDPRINT("unwinding catch stack entry %p (lexenv check is not done)", (void *) cat));

	DUK_ASSERT(!DUK_CAT_HAS_LEXENV_ACTIVE(cat));

	act->cat = cat->parent;
	duk_hthread_catcher_free(thr, cat);
}

DUK_LOCAL
#if defined(DUK_USE_CACHE_CATCHER)
DUK_NOINLINE
#endif
duk_catcher *duk__hthread_catcher_alloc_slow(duk_hthread *thr) {
	duk_catcher *cat;

	cat = (duk_catcher *) DUK_ALLOC_CHECKED(thr, sizeof(duk_catcher));
	DUK_ASSERT(cat != NULL);
	return cat;
}

#if defined(DUK_USE_CACHE_CATCHER)
DUK_INTERNAL DUK_INLINE duk_catcher *duk_hthread_catcher_alloc(duk_hthread *thr) {
	duk_catcher *cat;

	DUK_ASSERT(thr != NULL);

	cat = thr->heap->catcher_free;
	if (DUK_LIKELY(cat != NULL)) {
		thr->heap->catcher_free = cat->parent;
		return cat;
	}

	return duk__hthread_catcher_alloc_slow(thr);
}
#else  /* DUK_USE_CACHE_CATCHER */
DUK_INTERNAL duk_catcher *duk_hthread_catcher_alloc(duk_hthread *thr) {
	return duk__hthread_catcher_alloc_slow(thr);
}
#endif  /* DUK_USE_CACHE_CATCHER */

DUK_INTERNAL void duk_hthread_catcher_free(duk_hthread *thr, duk_catcher *cat) {
	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(cat != NULL);

#if defined(DUK_USE_CACHE_CATCHER)
	/* Unconditional caching for now; freed in mark-and-sweep. */
	cat->parent = thr->heap->catcher_free;
	thr->heap->catcher_free = cat;
#else
	DUK_FREE_CHECKED(thr, (void *) cat);
#endif
}

DUK_LOCAL
#if defined(DUK_USE_CACHE_ACTIVATION)
DUK_NOINLINE
#endif
duk_activation *duk__hthread_activation_alloc_slow(duk_hthread *thr) {
	duk_activation *act;

	act = (duk_activation *) DUK_ALLOC_CHECKED(thr, sizeof(duk_activation));
	DUK_ASSERT(act != NULL);
	return act;
}

#if defined(DUK_USE_CACHE_ACTIVATION)
DUK_INTERNAL DUK_INLINE duk_activation *duk_hthread_activation_alloc(duk_hthread *thr) {
	duk_activation *act;

	DUK_ASSERT(thr != NULL);

	act = thr->heap->activation_free;
	if (DUK_LIKELY(act != NULL)) {
		thr->heap->activation_free = act->parent;
		return act;
	}

	return duk__hthread_activation_alloc_slow(thr);
}
#else  /* DUK_USE_CACHE_ACTIVATION */
DUK_INTERNAL duk_activation *duk_hthread_activation_alloc(duk_hthread *thr) {
	return duk__hthread_activation_alloc_slow(thr);
}
#endif  /* DUK_USE_CACHE_ACTIVATION */


DUK_INTERNAL void duk_hthread_activation_free(duk_hthread *thr, duk_activation *act) {
	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(act != NULL);

#if defined(DUK_USE_CACHE_ACTIVATION)
	/* Unconditional caching for now; freed in mark-and-sweep. */
	act->parent = thr->heap->activation_free;
	thr->heap->activation_free = act;
#else
	DUK_FREE_CHECKED(thr, (void *) act);
#endif
}

/* Internal helper: process the unwind for the topmost activation of a thread,
 * but leave the duk_activation in place for possible tailcall reuse.
 */
DUK_LOCAL void duk__activation_unwind_nofree_norz(duk_hthread *thr) {
#if defined(DUK_USE_DEBUGGER_SUPPORT)
	duk_heap *heap;
#endif
	duk_activation *act;
	duk_hobject *func;
	duk_hobject *tmp;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(thr->callstack_curr != NULL);  /* caller must check */
	DUK_ASSERT(thr->callstack_top > 0);
	act = thr->callstack_curr;
	DUK_ASSERT(act != NULL);
	/* With lightfuncs, act 'func' may be NULL. */

	/* With duk_activation records allocated separately, 'act' is a stable
	 * pointer and not affected by side effects.
	 */

#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
	/*
	 *  Restore 'caller' property for non-strict callee functions.
	 */

	func = DUK_ACT_GET_FUNC(act);
	if (func != NULL && !DUK_HOBJECT_HAS_STRICT(func)) {
		duk_tval *tv_caller;
		duk_tval tv_tmp;
		duk_hobject *h_tmp;

		tv_caller = duk_hobject_find_entry_tval_ptr_stridx(thr->heap, func, DUK_STRIDX_CALLER);

		/* The act->prev_caller should only be set if the entry for 'caller'
		 * exists (as it is only set in that case, and the property is not
		 * configurable), but handle all the cases anyway.
		 */

		if (tv_caller) {
			DUK_TVAL_SET_TVAL(&tv_tmp, tv_caller);
			if (act->prev_caller) {
				/* Just transfer the refcount from act->prev_caller to tv_caller,
				 * so no need for a refcount update.  This is the expected case.
				 */
				DUK_TVAL_SET_OBJECT(tv_caller, act->prev_caller);
				act->prev_caller = NULL;
			} else {
				DUK_TVAL_SET_NULL(tv_caller);   /* no incref needed */
				DUK_ASSERT(act->prev_caller == NULL);
			}
			DUK_TVAL_DECREF_NORZ(thr, &tv_tmp);
		} else {
			h_tmp = act->prev_caller;
			if (h_tmp) {
				act->prev_caller = NULL;
				DUK_HOBJECT_DECREF_NORZ(thr, h_tmp);
			}
		}
		DUK_ASSERT(act->prev_caller == NULL);
	}
#endif

	/*
	 *  Unwind debugger state.  If we unwind while stepping
	 *  (for any step type), pause execution.  This is the
	 *  only place explicitly handling a step out.
	 */

#if defined(DUK_USE_DEBUGGER_SUPPORT)
	heap = thr->heap;
	if (heap->dbg_pause_act == thr->callstack_curr) {
		if (heap->dbg_pause_flags & DUK_PAUSE_FLAG_FUNC_EXIT) {
			DUK_D(DUK_DPRINT("PAUSE TRIGGERED by function exit"));
			duk_debug_set_paused(heap);
		} else {
			DUK_D(DUK_DPRINT("unwound past dbg_pause_act, set to NULL"));
			heap->dbg_pause_act = NULL;  /* avoid stale pointers */
		}
		DUK_ASSERT(heap->dbg_pause_act == NULL);
	}
#endif

	/*
	 *  Unwind catchers.
	 *
	 *  Since there are no references in the catcher structure,
	 *  unwinding is quite simple.  The only thing we need to
	 *  look out for is popping a possible lexical environment
	 *  established for an active catch clause.
	 */

	while (act->cat != NULL) {
		duk_hthread_catcher_unwind_norz(thr, act);
	}

	/*
	 *  Close environment record(s) if they exist.
	 *
	 *  Only variable environments are closed.  If lex_env != var_env, it
	 *  cannot currently contain any register bound declarations.
	 *
	 *  Only environments created for a NEWENV function are closed.  If an
	 *  environment is created for e.g. an eval call, it must not be closed.
	 */

	func = DUK_ACT_GET_FUNC(act);
	if (func != NULL && !DUK_HOBJECT_HAS_NEWENV(func)) {
		DUK_DDD(DUK_DDDPRINT("skip closing environments, envs not owned by this activation"));
		goto skip_env_close;
	}
	/* func is NULL for lightfunc */

	/* Catch sites are required to clean up their environments
	 * in FINALLY part before propagating, so this should
	 * always hold here.
	 */
	DUK_ASSERT(act->lex_env == act->var_env);

	/* XXX: Closing the environment record copies values from registers
	 * into the scope object.  It's side effect free as such, but may
	 * currently run out of memory which causes an error throw.  This is
	 * an actual sandboxing problem for error unwinds, and needs to be
	 * fixed e.g. by preallocating the scope property slots.
	 */
	if (act->var_env != NULL) {
		DUK_DDD(DUK_DDDPRINT("closing var_env record %p -> %!O",
		                     (void *) act->var_env, (duk_heaphdr *) act->var_env));
		duk_js_close_environment_record(thr, act->var_env);
	}

 skip_env_close:

	/*
	 *  Update preventcount
	 */

	if (act->flags & DUK_ACT_FLAG_PREVENT_YIELD) {
		DUK_ASSERT(thr->callstack_preventcount >= 1);
		thr->callstack_preventcount--;
	}

	/*
	 *  Reference count updates, using NORZ macros so we don't
	 *  need to handle side effects.
	 *
	 *  duk_activation pointers like act->var_env are intentionally
	 *  left as garbage and not NULLed.  Without side effects they
	 *  can't be used when the values are dangling/garbage.
	 */

	DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, act->var_env);
	DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, act->lex_env);
	tmp = DUK_ACT_GET_FUNC(act);
	DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, tmp);
	DUK_UNREF(tmp);
}

/* Unwind topmost duk_activation of a thread, caller must ensure that an
 * activation exists.  The call is side effect free, except that scope
 * closure may currently throw an out-of-memory error.
 */
DUK_INTERNAL void duk_hthread_activation_unwind_norz(duk_hthread *thr) {
	duk_activation *act;

	duk__activation_unwind_nofree_norz(thr);

	DUK_ASSERT(thr->callstack_curr != NULL);
	DUK_ASSERT(thr->callstack_top > 0);
	act = thr->callstack_curr;
	thr->callstack_curr = act->parent;
	thr->callstack_top--;

	/* Ideally we'd restore value stack reserve here to caller's value.
	 * This doesn't work for current unwind call sites however, because
	 * the current (unwound) value stack top may be above the reserve.
	 * Thus value stack reserve is restored by the call sites.
	 */

	/* XXX: inline for performance builds? */
	duk_hthread_activation_free(thr, act);

	/* We could clear the book-keeping variables like retval_byteoff for
	 * the topmost activation, but don't do so now as it's not necessary.
	 */
}

DUK_INTERNAL void duk_hthread_activation_unwind_reuse_norz(duk_hthread *thr) {
	duk__activation_unwind_nofree_norz(thr);
}

/* Get duk_activation for given callstack level or NULL if level is invalid
 * or deeper than the call stack.  Level -1 refers to current activation, -2
 * to its caller, etc.  Starting from Duktape 2.2 finding the activation is
 * a linked list scan which gets more expensive the deeper the lookup is.
 */
DUK_INTERNAL duk_activation *duk_hthread_get_activation_for_level(duk_hthread *thr, duk_int_t level) {
	duk_activation *act;

	if (level >= 0) {
		return NULL;
	}
	act = thr->callstack_curr;
	for (;;) {
		if (act == NULL) {
			return act;
		}
		if (level == -1) {
			return act;
		}
		level++;
		act = act->parent;
	}
	/* never here */
}

#if defined(DUK_USE_FINALIZER_TORTURE)
DUK_INTERNAL void duk_hthread_valstack_torture_realloc(duk_hthread *thr) {
	duk_size_t alloc_size;
	duk_tval *new_ptr;
	duk_ptrdiff_t alloc_end_off;
	duk_ptrdiff_t end_off;
	duk_ptrdiff_t bottom_off;
	duk_ptrdiff_t top_off;

	if (thr->valstack == NULL) {
		DUK_D(DUK_DPRINT("skip valstack torture realloc, valstack is NULL"));
		return;
	}

	alloc_end_off = (duk_ptrdiff_t) ((duk_uint8_t *) thr->valstack_alloc_end - (duk_uint8_t *) thr->valstack);
	end_off = (duk_ptrdiff_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack);
	bottom_off = (duk_ptrdiff_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack);
	top_off = (duk_ptrdiff_t) ((duk_uint8_t *) thr->valstack_top - (duk_uint8_t *) thr->valstack);
	alloc_size = (duk_size_t) alloc_end_off;
	if (alloc_size == 0) {
		DUK_D(DUK_DPRINT("skip valstack torture realloc, alloc_size is zero"));
		return;
	}

	/* Use DUK_ALLOC_RAW() to avoid side effects. */
	new_ptr = (duk_tval *) DUK_ALLOC_RAW(thr->heap, alloc_size);
	if (new_ptr != NULL) {
		duk_memcpy((void *) new_ptr, (const void *) thr->valstack, alloc_size);
		duk_memset((void *) thr->valstack, 0x55, alloc_size);
		DUK_FREE_CHECKED(thr, (void *) thr->valstack);
		thr->valstack = new_ptr;
		thr->valstack_alloc_end = (duk_tval *) ((duk_uint8_t *) new_ptr + alloc_end_off);
		thr->valstack_end = (duk_tval *) ((duk_uint8_t *) new_ptr + end_off);
		thr->valstack_bottom = (duk_tval *) ((duk_uint8_t *) new_ptr + bottom_off);
		thr->valstack_top = (duk_tval *) ((duk_uint8_t *) new_ptr + top_off);
	} else {
		DUK_D(DUK_DPRINT("failed to realloc valstack for torture, ignore"));
	}
}
#endif  /* DUK_USE_FINALIZER_TORTURE */
#line 1 "duk_js_arith.c"
/*
 *  Shared helpers for arithmetic operations
 */

/* #include duk_internal.h -> already included */

/* ECMAScript modulus ('%') does not match IEEE 754 "remainder" operation
 * (implemented by remainder() in C99) but does seem to match ANSI C fmod().
 * Compare E5 Section 11.5.3 and "man fmod".
 */
DUK_INTERNAL double duk_js_arith_mod(double d1, double d2) {
#if defined(DUK_USE_POW_WORKAROUNDS)
	/* Specific fixes to common fmod() implementation issues:
	 * - test-bug-mingw-math-issues.js
	 */
	if (DUK_ISINF(d2)) {
		if (DUK_ISINF(d1)) {
			return DUK_DOUBLE_NAN;
		} else {
			return d1;
		}
	} else if (duk_double_equals(d1, 0.0)) {
		/* d1 +/-0 is returned as is (preserving sign) except when
		 * d2 is zero or NaN.
		 */
		if (duk_double_equals(d2, 0.0) || DUK_ISNAN(d2)) {
			return DUK_DOUBLE_NAN;
		} else {
			return d1;
		}
	}
#else
	/* Some ISO C assumptions. */
	DUK_ASSERT(duk_double_equals(DUK_FMOD(1.0, DUK_DOUBLE_INFINITY), 1.0));
	DUK_ASSERT(duk_double_equals(DUK_FMOD(-1.0, DUK_DOUBLE_INFINITY), -1.0));
	DUK_ASSERT(duk_double_equals(DUK_FMOD(1.0, -DUK_DOUBLE_INFINITY), 1.0));
	DUK_ASSERT(duk_double_equals(DUK_FMOD(-1.0, -DUK_DOUBLE_INFINITY), -1.0));
	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(DUK_DOUBLE_INFINITY, DUK_DOUBLE_INFINITY)));
	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(DUK_DOUBLE_INFINITY, -DUK_DOUBLE_INFINITY)));
	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(-DUK_DOUBLE_INFINITY, DUK_DOUBLE_INFINITY)));
	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(-DUK_DOUBLE_INFINITY, -DUK_DOUBLE_INFINITY)));
	DUK_ASSERT(duk_double_equals(DUK_FMOD(0.0, 1.0), 0.0) && DUK_SIGNBIT(DUK_FMOD(0.0, 1.0)) == 0);
	DUK_ASSERT(duk_double_equals(DUK_FMOD(-0.0, 1.0), 0.0) && DUK_SIGNBIT(DUK_FMOD(-0.0, 1.0)) != 0);
	DUK_ASSERT(duk_double_equals(DUK_FMOD(0.0, DUK_DOUBLE_INFINITY), 0.0) && DUK_SIGNBIT(DUK_FMOD(0.0, DUK_DOUBLE_INFINITY)) == 0);
	DUK_ASSERT(duk_double_equals(DUK_FMOD(-0.0, DUK_DOUBLE_INFINITY), 0.0) && DUK_SIGNBIT(DUK_FMOD(-0.0, DUK_DOUBLE_INFINITY)) != 0);
	DUK_ASSERT(duk_double_equals(DUK_FMOD(0.0, -DUK_DOUBLE_INFINITY), 0.0) && DUK_SIGNBIT(DUK_FMOD(0.0, DUK_DOUBLE_INFINITY)) == 0);
	DUK_ASSERT(duk_double_equals(DUK_FMOD(-0.0, -DUK_DOUBLE_INFINITY), 0.0) && DUK_SIGNBIT(DUK_FMOD(-0.0, -DUK_DOUBLE_INFINITY)) != 0);
	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(0.0, 0.0)));
	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(-0.0, 0.0)));
	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(0.0, -0.0)));
	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(-0.0, -0.0)));
	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(0.0, DUK_DOUBLE_NAN)));
	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(-0.0, DUK_DOUBLE_NAN)));
#endif

	return (duk_double_t) DUK_FMOD((double) d1, (double) d2);
}

/* Shared helper for Math.pow() and exponentiation operator. */
DUK_INTERNAL double duk_js_arith_pow(double x, double y) {
	/* The ANSI C pow() semantics differ from ECMAScript.
	 *
	 * E.g. when x==1 and y is +/- infinite, the ECMAScript required
	 * result is NaN, while at least Linux pow() returns 1.
	 */

	duk_small_int_t cx, cy, sx;

	DUK_UNREF(cx);
	DUK_UNREF(sx);
	cy = (duk_small_int_t) DUK_FPCLASSIFY(y);

	if (cy == DUK_FP_NAN) {
		goto ret_nan;
	}
	if (duk_double_equals(DUK_FABS(x), 1.0) && cy == DUK_FP_INFINITE) {
		goto ret_nan;
	}

#if defined(DUK_USE_POW_WORKAROUNDS)
	/* Specific fixes to common pow() implementation issues:
	 *   - test-bug-netbsd-math-pow.js: NetBSD 6.0 on x86 (at least)
	 *   - test-bug-mingw-math-issues.js
	 */
	cx = (duk_small_int_t) DUK_FPCLASSIFY(x);
	if (cx == DUK_FP_ZERO && y < 0.0) {
		sx = (duk_small_int_t) DUK_SIGNBIT(x);
		if (sx == 0) {
			/* Math.pow(+0,y) should be Infinity when y<0.  NetBSD pow()
			 * returns -Infinity instead when y is <0 and finite.  The
			 * if-clause also catches y == -Infinity (which works even
			 * without the fix).
			 */
			return DUK_DOUBLE_INFINITY;
		} else {
			/* Math.pow(-0,y) where y<0 should be:
			 *   - -Infinity if y<0 and an odd integer
			 *   - Infinity if y<0 but not an odd integer
			 * NetBSD pow() returns -Infinity for all finite y<0.  The
			 * if-clause also catches y == -Infinity (which works even
			 * without the fix).
			 */

			/* fmod() return value has same sign as input (negative) so
			 * the result here will be in the range ]-2,0], -1 indicates
			 * odd.  If x is -Infinity, NaN is returned and the odd check
			 * always concludes "not odd" which results in desired outcome.
			 */
			double tmp = DUK_FMOD(y, 2);
			if (tmp == -1.0) {
				return -DUK_DOUBLE_INFINITY;
			} else {
				/* Not odd, or y == -Infinity */
				return DUK_DOUBLE_INFINITY;
			}
		}
	} else if (cx == DUK_FP_NAN) {
		if (duk_double_equals(y, 0.0)) {
			/* NaN ** +/- 0 should always be 1, but is NaN on
			 * at least some Cygwin/MinGW versions.
			 */
			return 1.0;
		}
	}
#else
	/* Some ISO C assumptions. */
	DUK_ASSERT(duk_double_equals(DUK_POW(DUK_DOUBLE_NAN, 0.0), 1.0));
	DUK_ASSERT(DUK_ISINF(DUK_POW(0.0, -1.0)) && DUK_SIGNBIT(DUK_POW(0.0, -1.0)) == 0);
	DUK_ASSERT(DUK_ISINF(DUK_POW(-0.0, -2.0)) && DUK_SIGNBIT(DUK_POW(-0.0, -2.0)) == 0);
	DUK_ASSERT(DUK_ISINF(DUK_POW(-0.0, -3.0)) && DUK_SIGNBIT(DUK_POW(-0.0, -3.0)) != 0);
#endif

	return DUK_POW(x, y);

 ret_nan:
	return DUK_DOUBLE_NAN;
}
#line 1 "duk_js_call.c"
/*
 *  Call handling.
 *
 *  duk_handle_call_unprotected():
 *
 *    - Unprotected call to ECMAScript or Duktape/C function, from native
 *      code or bytecode executor.
 *
 *    - Also handles Ecma-to-Ecma calls which reuses a currently running
 *      executor instance to avoid native recursion.  Call setup is done
 *      normally, but just before calling the bytecode executor a special
 *      return code is used to indicate that a calling executor is reused.
 *
 *    - Also handles tailcalls, i.e. reuse of current duk_activation.
 *
 *    - Also handles setup for initial Duktape.Thread.resume().
 *
 *  duk_handle_safe_call():
 *
 *    - Protected C call within current activation.
 *
 *  setjmp() and local variables have a nasty interaction, see execution.rst;
 *  non-volatile locals modified after setjmp() call are not guaranteed to
 *  keep their value and can cause compiler or compiler version specific
 *  difficult to replicate issues.
 *
 *  See 'execution.rst'.
 */

/* #include duk_internal.h -> already included */

/* XXX: heap->error_not_allowed for success path too? */

/*
 *  Limit check helpers.
 */

/* Check native stack space if DUK_USE_NATIVE_STACK_CHECK() defined. */
DUK_INTERNAL void duk_native_stack_check(duk_hthread *thr) {
#if defined(DUK_USE_NATIVE_STACK_CHECK)
	if (DUK_USE_NATIVE_STACK_CHECK() != 0) {
		DUK_ERROR_RANGE(thr, DUK_STR_NATIVE_STACK_LIMIT);
	}
#else
	DUK_UNREF(thr);
#endif
}

/* Allow headroom for calls during error augmentation (see GH-191).
 * We allow space for 10 additional recursions, with one extra
 * for, e.g. a print() call at the deepest level, and an extra
 * +1 for protected call wrapping.
 */
#define DUK__AUGMENT_CALL_RELAX_COUNT  (10 + 2)

/* Stack space required by call handling entry. */
#define DUK__CALL_HANDLING_REQUIRE_STACK  8

DUK_LOCAL DUK_NOINLINE void duk__call_c_recursion_limit_check_slowpath(duk_hthread *thr) {
	/* When augmenting an error, the effective limit is a bit higher.
	 * Check for it only if the fast path check fails.
	 */
#if defined(DUK_USE_AUGMENT_ERROR_THROW) || defined(DUK_USE_AUGMENT_ERROR_CREATE)
	if (thr->heap->augmenting_error) {
		if (thr->heap->call_recursion_depth < thr->heap->call_recursion_limit + DUK__AUGMENT_CALL_RELAX_COUNT) {
			DUK_D(DUK_DPRINT("C recursion limit reached but augmenting error and within relaxed limit"));
			return;
		}
	}
#endif

	DUK_D(DUK_DPRINT("call prevented because C recursion limit reached"));
	DUK_ERROR_RANGE(thr, DUK_STR_NATIVE_STACK_LIMIT);
	DUK_WO_NORETURN(return;);
}

DUK_LOCAL DUK_ALWAYS_INLINE void duk__call_c_recursion_limit_check(duk_hthread *thr) {
	DUK_ASSERT(thr->heap->call_recursion_depth >= 0);
	DUK_ASSERT(thr->heap->call_recursion_depth <= thr->heap->call_recursion_limit);

	duk_native_stack_check(thr);

	/* This check is forcibly inlined because it's very cheap and almost
	 * always passes.  The slow path is forcibly noinline.
	 */
	if (DUK_LIKELY(thr->heap->call_recursion_depth < thr->heap->call_recursion_limit)) {
		return;
	}

	duk__call_c_recursion_limit_check_slowpath(thr);
}

DUK_LOCAL DUK_NOINLINE void duk__call_callstack_limit_check_slowpath(duk_hthread *thr) {
	/* When augmenting an error, the effective limit is a bit higher.
	 * Check for it only if the fast path check fails.
	 */
#if defined(DUK_USE_AUGMENT_ERROR_THROW) || defined(DUK_USE_AUGMENT_ERROR_CREATE)
	if (thr->heap->augmenting_error) {
		if (thr->callstack_top < DUK_USE_CALLSTACK_LIMIT + DUK__AUGMENT_CALL_RELAX_COUNT) {
			DUK_D(DUK_DPRINT("call stack limit reached but augmenting error and within relaxed limit"));
			return;
		}
	}
#endif

	/* XXX: error message is a bit misleading: we reached a recursion
	 * limit which is also essentially the same as a C callstack limit
	 * (except perhaps with some relaxed threading assumptions).
	 */
	DUK_D(DUK_DPRINT("call prevented because call stack limit reached"));
	DUK_ERROR_RANGE(thr, DUK_STR_CALLSTACK_LIMIT);
	DUK_WO_NORETURN(return;);
}

DUK_LOCAL DUK_ALWAYS_INLINE void duk__call_callstack_limit_check(duk_hthread *thr) {
	/* This check is forcibly inlined because it's very cheap and almost
	 * always passes.  The slow path is forcibly noinline.
	 */
	if (DUK_LIKELY(thr->callstack_top < DUK_USE_CALLSTACK_LIMIT)) {
		return;
	}

	duk__call_callstack_limit_check_slowpath(thr);
}

/*
 *  Interrupt counter fixup (for development only).
 */

#if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
DUK_LOCAL void duk__interrupt_fixup(duk_hthread *thr, duk_hthread *entry_curr_thread) {
	/* Currently the bytecode executor and executor interrupt
	 * instruction counts are off because we don't execute the
	 * interrupt handler when we're about to exit from the initial
	 * user call into Duktape.
	 *
	 * If we were to execute the interrupt handler here, the counts
	 * would match.  You can enable this block manually to check
	 * that this is the case.
	 */

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(thr->heap != NULL);

#if defined(DUK_USE_INTERRUPT_DEBUG_FIXUP)
	if (entry_curr_thread == NULL) {
		thr->interrupt_init = thr->interrupt_init - thr->interrupt_counter;
		thr->heap->inst_count_interrupt += thr->interrupt_init;
		DUK_DD(DUK_DDPRINT("debug test: updated interrupt count on exit to "
		                   "user code, instruction counts: executor=%ld, interrupt=%ld",
		                   (long) thr->heap->inst_count_exec, (long) thr->heap->inst_count_interrupt));
		DUK_ASSERT(thr->heap->inst_count_exec == thr->heap->inst_count_interrupt);
	}
#else
	DUK_UNREF(thr);
	DUK_UNREF(entry_curr_thread);
#endif
}
#endif

/*
 *  Arguments object creation.
 *
 *  Creating arguments objects involves many small details, see E5 Section
 *  10.6 for the specific requirements.  Much of the arguments object exotic
 *  behavior is implemented in duk_hobject_props.c, and is enabled by the
 *  object flag DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS.
 */

DUK_LOCAL void duk__create_arguments_object(duk_hthread *thr,
                                            duk_hobject *func,
                                            duk_hobject *varenv,
                                            duk_idx_t idx_args) {
	duk_hobject *arg;          /* 'arguments' */
	duk_hobject *formals;      /* formals for 'func' (may be NULL if func is a C function) */
	duk_idx_t i_arg;
	duk_idx_t i_map;
	duk_idx_t i_mappednames;
	duk_idx_t i_formals;
	duk_idx_t i_argbase;
	duk_idx_t n_formals;
	duk_idx_t idx;
	duk_idx_t num_stack_args;
	duk_bool_t need_map;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(func != NULL);
	DUK_ASSERT(DUK_HOBJECT_IS_NONBOUND_FUNCTION(func));
	DUK_ASSERT(varenv != NULL);

	/* [ ... func this arg1(@idx_args) ... argN envobj ]
	 * [ arg1(@idx_args) ... argN envobj ] (for tailcalls)
	 */

	need_map = 0;

	i_argbase = idx_args;
	num_stack_args = duk_get_top(thr) - i_argbase - 1;
	DUK_ASSERT(i_argbase >= 0);
	DUK_ASSERT(num_stack_args >= 0);

	formals = (duk_hobject *) duk_hobject_get_formals(thr, (duk_hobject *) func);
	if (formals) {
		n_formals = (duk_idx_t) ((duk_harray *) formals)->length;
		duk_push_hobject(thr, formals);
	} else {
		/* This shouldn't happen without tampering of internal
		 * properties: if a function accesses 'arguments', _Formals
		 * is kept.  Check for the case anyway in case internal
		 * properties have been modified manually.
		 */
		DUK_D(DUK_DPRINT("_Formals is undefined when creating arguments, use n_formals == 0"));
		n_formals = 0;
		duk_push_undefined(thr);
	}
	i_formals = duk_require_top_index(thr);

	DUK_ASSERT(n_formals >= 0);
	DUK_ASSERT(formals != NULL || n_formals == 0);

	DUK_DDD(DUK_DDDPRINT("func=%!O, formals=%!O, n_formals=%ld",
	                     (duk_heaphdr *) func, (duk_heaphdr *) formals,
	                     (long) n_formals));

	/* [ ... formals ] */

	/*
	 *  Create required objects:
	 *    - 'arguments' object: array-like, but not an array
	 *    - 'map' object: internal object, tied to 'arguments' (bare)
	 *    - 'mappedNames' object: temporary value used during construction (bare)
	 */

	arg = duk_push_object_helper(thr,
	                             DUK_HOBJECT_FLAG_EXTENSIBLE |
	                             DUK_HOBJECT_FLAG_FASTREFS |
	                             DUK_HOBJECT_FLAG_ARRAY_PART |
	                             DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARGUMENTS),
	                             DUK_BIDX_OBJECT_PROTOTYPE);
	DUK_ASSERT(arg != NULL);
	(void) duk_push_object_helper(thr,
	                              DUK_HOBJECT_FLAG_EXTENSIBLE |
	                              DUK_HOBJECT_FLAG_FASTREFS |
	                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
	                              -1);  /* no prototype */
	(void) duk_push_object_helper(thr,
	                              DUK_HOBJECT_FLAG_EXTENSIBLE |
	                              DUK_HOBJECT_FLAG_FASTREFS |
	                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
	                              -1);  /* no prototype */
	i_arg = duk_get_top(thr) - 3;
	i_map = i_arg + 1;
	i_mappednames = i_arg + 2;
	DUK_ASSERT(!duk_is_bare_object(thr, -3));  /* arguments */
	DUK_ASSERT(duk_is_bare_object(thr, -2));  /* map */
	DUK_ASSERT(duk_is_bare_object(thr, -1));  /* mappedNames */

	/* [ ... formals arguments map mappedNames ] */

	DUK_DDD(DUK_DDDPRINT("created arguments related objects: "
	                     "arguments at index %ld -> %!O "
	                     "map at index %ld -> %!O "
	                     "mappednames at index %ld -> %!O",
	                     (long) i_arg, (duk_heaphdr *) duk_get_hobject(thr, i_arg),
	                     (long) i_map, (duk_heaphdr *) duk_get_hobject(thr, i_map),
	                     (long) i_mappednames, (duk_heaphdr *) duk_get_hobject(thr, i_mappednames)));

	/*
	 *  Init arguments properties, map, etc.
	 */

	duk_push_int(thr, num_stack_args);
	duk_xdef_prop_stridx(thr, i_arg, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_WC);

	/*
	 *  Init argument related properties.
	 */

	/* step 11 */
	idx = num_stack_args - 1;
	while (idx >= 0) {
		DUK_DDD(DUK_DDDPRINT("arg idx %ld, argbase=%ld, argidx=%ld",
		                     (long) idx, (long) i_argbase, (long) (i_argbase + idx)));

		DUK_DDD(DUK_DDDPRINT("define arguments[%ld]=arg", (long) idx));
		duk_dup(thr, i_argbase + idx);
		duk_xdef_prop_index_wec(thr, i_arg, (duk_uarridx_t) idx);
		DUK_DDD(DUK_DDDPRINT("defined arguments[%ld]=arg", (long) idx));

		/* step 11.c is relevant only if non-strict (checked in 11.c.ii) */
		if (!DUK_HOBJECT_HAS_STRICT(func) && idx < n_formals) {
			DUK_ASSERT(formals != NULL);

			DUK_DDD(DUK_DDDPRINT("strict function, index within formals (%ld < %ld)",
			                     (long) idx, (long) n_formals));

			duk_get_prop_index(thr, i_formals, (duk_uarridx_t) idx);
			DUK_ASSERT(duk_is_string(thr, -1));

			duk_dup_top(thr);  /* [ ... name name ] */

			if (!duk_has_prop(thr, i_mappednames)) {
				/* steps 11.c.ii.1 - 11.c.ii.4, but our internal book-keeping
				 * differs from the reference model
				 */

				/* [ ... name ] */

				need_map = 1;

				DUK_DDD(DUK_DDDPRINT("set mappednames[%s]=%ld",
				                     (const char *) duk_get_string(thr, -1),
				                     (long) idx));
				duk_dup_top(thr);                      /* name */
				(void) duk_push_uint_to_hstring(thr, (duk_uint_t) idx);  /* index */
				duk_xdef_prop_wec(thr, i_mappednames);  /* out of spec, must be configurable */

				DUK_DDD(DUK_DDDPRINT("set map[%ld]=%s",
				                     (long) idx,
				                     duk_get_string(thr, -1)));
				duk_dup_top(thr);         /* name */
				duk_xdef_prop_index_wec(thr, i_map, (duk_uarridx_t) idx);  /* out of spec, must be configurable */
			} else {
				/* duk_has_prop() popped the second 'name' */
			}

			/* [ ... name ] */
			duk_pop(thr);  /* pop 'name' */
		}

		idx--;
	}

	DUK_DDD(DUK_DDDPRINT("actual arguments processed"));

	/* step 12 */
	if (need_map) {
		DUK_DDD(DUK_DDDPRINT("adding 'map' and 'varenv' to arguments object"));

		/* should never happen for a strict callee */
		DUK_ASSERT(!DUK_HOBJECT_HAS_STRICT(func));

		duk_dup(thr, i_map);
		duk_xdef_prop_stridx(thr, i_arg, DUK_STRIDX_INT_MAP, DUK_PROPDESC_FLAGS_NONE);  /* out of spec, don't care */

		/* The variable environment for magic variable bindings needs to be
		 * given by the caller and recorded in the arguments object.
		 *
		 * See E5 Section 10.6, the creation of setters/getters.
		 *
		 * The variable environment also provides access to the callee, so
		 * an explicit (internal) callee property is not needed.
		 */

		duk_push_hobject(thr, varenv);
		duk_xdef_prop_stridx(thr, i_arg, DUK_STRIDX_INT_VARENV, DUK_PROPDESC_FLAGS_NONE);  /* out of spec, don't care */
	}

	/* steps 13-14 */
	if (DUK_HOBJECT_HAS_STRICT(func)) {
		/* Callee/caller are throwers and are not deletable etc.  They
		 * could be implemented as virtual properties, but currently
		 * there is no support for virtual properties which are accessors
		 * (only plain virtual properties).  This would not be difficult
		 * to change in duk_hobject_props, but we can make the throwers
		 * normal, concrete properties just as easily.
		 *
		 * Note that the specification requires that the *same* thrower
		 * built-in object is used here!  See E5 Section 10.6 main
		 * algoritm, step 14, and Section 13.2.3 which describes the
		 * thrower.  See test case test-arguments-throwers.js.
		 */

		DUK_DDD(DUK_DDDPRINT("strict function, setting caller/callee to throwers"));

		/* In ES2017 .caller is no longer set at all. */
		duk_xdef_prop_stridx_thrower(thr, i_arg, DUK_STRIDX_CALLEE);
	} else {
		DUK_DDD(DUK_DDDPRINT("non-strict function, setting callee to actual value"));
		duk_push_hobject(thr, func);
		duk_xdef_prop_stridx(thr, i_arg, DUK_STRIDX_CALLEE, DUK_PROPDESC_FLAGS_WC);
	}

	/* set exotic behavior only after we're done */
	if (need_map) {
		/* Exotic behaviors are only enabled for arguments objects
		 * which have a parameter map (see E5 Section 10.6 main
		 * algorithm, step 12).
		 *
		 * In particular, a non-strict arguments object with no
		 * mapped formals does *NOT* get exotic behavior, even
		 * for e.g. "caller" property.  This seems counterintuitive
		 * but seems to be the case.
		 */

		/* cannot be strict (never mapped variables) */
		DUK_ASSERT(!DUK_HOBJECT_HAS_STRICT(func));

		DUK_DDD(DUK_DDDPRINT("enabling exotic behavior for arguments object"));
		DUK_HOBJECT_SET_EXOTIC_ARGUMENTS(arg);
	} else {
		DUK_DDD(DUK_DDDPRINT("not enabling exotic behavior for arguments object"));
	}

	DUK_DDD(DUK_DDDPRINT("final arguments related objects: "
	                     "arguments at index %ld -> %!O "
	                     "map at index %ld -> %!O "
	                     "mappednames at index %ld -> %!O",
	                     (long) i_arg, (duk_heaphdr *) duk_get_hobject(thr, i_arg),
	                     (long) i_map, (duk_heaphdr *) duk_get_hobject(thr, i_map),
	                     (long) i_mappednames, (duk_heaphdr *) duk_get_hobject(thr, i_mappednames)));

	/* [ args(n) envobj formals arguments map mappednames ] */

	duk_pop_2(thr);
	duk_remove_m2(thr);

	/* [ args(n) envobj arguments ] */
}

/* Helper for creating the arguments object and adding it to the env record
 * on top of the value stack.
 */
DUK_LOCAL void duk__handle_createargs_for_call(duk_hthread *thr,
                                               duk_hobject *func,
                                               duk_hobject *env,
                                               duk_idx_t idx_args) {
	DUK_DDD(DUK_DDDPRINT("creating arguments object for function call"));

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(func != NULL);
	DUK_ASSERT(env != NULL);
	DUK_ASSERT(DUK_HOBJECT_HAS_CREATEARGS(func));

	/* [ ... arg1 ... argN envobj ] */

	duk__create_arguments_object(thr,
	                             func,
	                             env,
	                             idx_args);

	/* [ ... arg1 ... argN envobj argobj ] */

	duk_xdef_prop_stridx_short(thr,
	                           -2,
	                           DUK_STRIDX_LC_ARGUMENTS,
	                           DUK_HOBJECT_HAS_STRICT(func) ? DUK_PROPDESC_FLAGS_E :   /* strict: non-deletable, non-writable */
	                                                          DUK_PROPDESC_FLAGS_WE);  /* non-strict: non-deletable, writable */
	/* [ ... arg1 ... argN envobj ] */
}

/*
 *  Helpers for constructor call handling.
 *
 *  There are two [[Construct]] operations in the specification:
 *
 *    - E5 Section 13.2.2: for Function objects
 *    - E5 Section 15.3.4.5.2: for "bound" Function objects
 *
 *  The chain of bound functions is resolved in Section 15.3.4.5.2,
 *  with arguments "piling up" until the [[Construct]] internal
 *  method is called on the final, actual Function object.  Note
 *  that the "prototype" property is looked up *only* from the
 *  final object, *before* calling the constructor.
 *
 *  Since Duktape 2.2 bound functions are represented with the
 *  duk_hboundfunc internal type, and bound function chains are
 *  collapsed when a bound function is created.  As a result, the
 *  direct target of a duk_hboundfunc is always non-bound and the
 *  this/argument lists have been resolved.
 *
 *  When constructing new Array instances, an unnecessary object is
 *  created and discarded now: the standard [[Construct]] creates an
 *  object, and calls the Array constructor.  The Array constructor
 *  returns an Array instance, which is used as the result value for
 *  the "new" operation; the object created before the Array constructor
 *  call is discarded.
 *
 *  This would be easy to fix, e.g. by knowing that the Array constructor
 *  will always create a replacement object and skip creating the fallback
 *  object in that case.
 */

/* Update default instance prototype for constructor call. */
DUK_LOCAL void duk__update_default_instance_proto(duk_hthread *thr, duk_idx_t idx_func) {
	duk_hobject *proto;
	duk_hobject *fallback;

	DUK_ASSERT(duk_is_constructable(thr, idx_func));

	duk_get_prop_stridx_short(thr, idx_func, DUK_STRIDX_PROTOTYPE);
	proto = duk_get_hobject(thr, -1);
	if (proto == NULL) {
		DUK_DDD(DUK_DDDPRINT("constructor has no 'prototype' property, or value not an object "
		                     "-> leave standard Object prototype as fallback prototype"));
	} else {
		DUK_DDD(DUK_DDDPRINT("constructor has 'prototype' property with object value "
		                     "-> set fallback prototype to that value: %!iO", (duk_heaphdr *) proto));
		/* Original fallback (default instance) is untouched when
		 * resolving bound functions etc.
		 */
		fallback = duk_known_hobject(thr, idx_func + 1);
		DUK_ASSERT(fallback != NULL);
		DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, fallback, proto);
	}
	duk_pop(thr);
}

/* Postprocess: return value special handling, error augmentation. */
DUK_INTERNAL void duk_call_construct_postprocess(duk_hthread *thr, duk_small_uint_t proxy_invariant) {
	/* Use either fallback (default instance) or retval depending
	 * on retval type.  Needs to be called before unwind because
	 * the default instance is read from the current (immutable)
	 * 'this' binding.
	 *
	 * For Proxy 'construct' calls the return value must be an
	 * Object (we accept object-like values like buffers and
	 * lightfuncs too).  If not, TypeError.
	 */
	if (duk_check_type_mask(thr, -1, DUK_TYPE_MASK_OBJECT |
	                                 DUK_TYPE_MASK_BUFFER |
	                                 DUK_TYPE_MASK_LIGHTFUNC)) {
		DUK_DDD(DUK_DDDPRINT("replacement value"));
	} else {
		if (DUK_UNLIKELY(proxy_invariant != 0U)) {
			/* Proxy 'construct' return value invariant violated. */
			DUK_ERROR_TYPE_INVALID_TRAP_RESULT(thr);
			DUK_WO_NORETURN(return;);
		}
		/* XXX: direct value stack access */
		duk_pop(thr);
		duk_push_this(thr);
	}

#if defined(DUK_USE_AUGMENT_ERROR_CREATE)
	/* Augment created errors upon creation, not when they are thrown or
	 * rethrown.  __FILE__ and __LINE__ are not desirable here; the call
	 * stack reflects the caller which is correct.  Skip topmost, unwound
	 * activation when creating a traceback.  If thr->ptr_curr_pc was !=
	 * NULL we'd need to sync the current PC so that the traceback comes
	 * out right; however it is always synced here so just assert for it.
	 */
	DUK_ASSERT(thr->ptr_curr_pc == NULL);
	duk_err_augment_error_create(thr, thr, NULL, 0, DUK_AUGMENT_FLAG_NOBLAME_FILELINE |
	                                                DUK_AUGMENT_FLAG_SKIP_ONE);
#endif
}

/*
 *  Helper for handling a bound function when a call is being made.
 *
 *  Assumes that bound function chains have been "collapsed" so that either
 *  the target is non-bound or there is one bound function that points to a
 *  nonbound target.
 *
 *  Prepends the bound arguments to the value stack (at idx_func + 2).
 *  The 'this' binding is also updated if necessary (at idx_func + 1).
 *  Note that for constructor calls the 'this' binding is never updated by
 *  [[BoundThis]].
 */

DUK_LOCAL void duk__handle_bound_chain_for_call(duk_hthread *thr,
                                                duk_idx_t idx_func,
                                                duk_bool_t is_constructor_call) {
	duk_tval *tv_func;
	duk_hobject *func;
	duk_idx_t len;

	DUK_ASSERT(thr != NULL);

	/* On entry, item at idx_func is a bound, non-lightweight function,
	 * but we don't rely on that below.
	 */

	DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);

	tv_func = duk_require_tval(thr, idx_func);
	DUK_ASSERT(tv_func != NULL);

	if (DUK_TVAL_IS_OBJECT(tv_func)) {
		func = DUK_TVAL_GET_OBJECT(tv_func);

		/* XXX: separate helper function, out of fast path? */
		if (DUK_HOBJECT_HAS_BOUNDFUNC(func)) {
			duk_hboundfunc *h_bound;
			duk_tval *tv_args;
			duk_tval *tv_gap;

			h_bound = (duk_hboundfunc *) (void *) func;
			tv_args = h_bound->args;
			len = h_bound->nargs;
			DUK_ASSERT(len == 0 || tv_args != NULL);

			DUK_DDD(DUK_DDDPRINT("bound function encountered, ptr=%p: %!T",
			                     (void *) DUK_TVAL_GET_OBJECT(tv_func), tv_func));

			/* [ ... func this arg1 ... argN ] */

			if (is_constructor_call) {
				/* See: tests/ecmascript/test-spec-bound-constructor.js */
				DUK_DDD(DUK_DDDPRINT("constructor call: don't update this binding"));
			} else {
				/* XXX: duk_replace_tval */
				duk_push_tval(thr, &h_bound->this_binding);
				duk_replace(thr, idx_func + 1);  /* idx_this = idx_func + 1 */
			}

			/* [ ... func this arg1 ... argN ] */

			duk_require_stack(thr, len);

			tv_gap = duk_reserve_gap(thr, idx_func + 2, len);
			duk_copy_tvals_incref(thr, tv_gap, tv_args, (duk_size_t) len);

			/* [ ... func this <bound args> arg1 ... argN ] */

			duk_push_tval(thr, &h_bound->target);
			duk_replace(thr, idx_func);  /* replace in stack */

			DUK_DDD(DUK_DDDPRINT("bound function handled, idx_func=%ld, curr func=%!T",
			                     (long) idx_func, duk_get_tval(thr, idx_func)));
		}
	} else if (DUK_TVAL_IS_LIGHTFUNC(tv_func)) {
		/* Lightweight function: never bound, so terminate. */
		;
	} else {
		/* Shouldn't happen, so ugly error is enough. */
		DUK_ERROR_INTERNAL(thr);
		DUK_WO_NORETURN(return;);
	}

	DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);

	DUK_DDD(DUK_DDDPRINT("final non-bound function is: %!T", duk_get_tval(thr, idx_func)));

#if defined(DUK_USE_ASSERTIONS)
	tv_func = duk_require_tval(thr, idx_func);
	DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv_func) || DUK_TVAL_IS_OBJECT(tv_func));
	if (DUK_TVAL_IS_OBJECT(tv_func)) {
		func = DUK_TVAL_GET_OBJECT(tv_func);
		DUK_ASSERT(func != NULL);
		DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(func));
		DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(func) ||
		           DUK_HOBJECT_HAS_NATFUNC(func) ||
		           DUK_HOBJECT_IS_PROXY(func));
	}
#endif
}

/*
 *  Helper for inline handling of .call(), .apply(), and .construct().
 */

DUK_LOCAL duk_bool_t duk__handle_specialfuncs_for_call(duk_hthread *thr, duk_idx_t idx_func, duk_hobject *func, duk_small_uint_t *call_flags, duk_bool_t first) {
#if defined(DUK_USE_ASSERTIONS)
	duk_c_function natfunc;
#endif
	duk_tval *tv_args;

	DUK_ASSERT(func != NULL);
	DUK_ASSERT((*call_flags & DUK_CALL_FLAG_CONSTRUCT) == 0);  /* Caller. */

#if defined(DUK_USE_ASSERTIONS)
	natfunc = ((duk_hnatfunc *) func)->func;
	DUK_ASSERT(natfunc != NULL);
#endif

	/* On every round of function resolution at least target function and
	 * 'this' binding are set.  We can assume that here, and must guarantee
	 * it on exit.  Value stack reserve is extended for bound function and
	 * .apply() unpacking so we don't need to extend it here when we need a
	 * few slots.
	 */
	DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);

	/* Handle native 'eval' specially.  A direct eval check is only made
	 * for the first resolution attempt; e.g. a bound eval call is -not-
	 * a direct eval call.
	 */
	if (DUK_UNLIKELY(((duk_hnatfunc *) func)->magic == 15)) {
		/* For now no special handling except for direct eval
		 * detection.
		 */
		DUK_ASSERT(((duk_hnatfunc *) func)->func == duk_bi_global_object_eval);
		if (first && (*call_flags & DUK_CALL_FLAG_CALLED_AS_EVAL)) {
			*call_flags = (*call_flags & ~DUK_CALL_FLAG_CALLED_AS_EVAL) | DUK_CALL_FLAG_DIRECT_EVAL;
		}
		DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
		return 1;  /* stop resolving */
	}

	/* Handle special functions based on the DUK_HOBJECT_FLAG_SPECIAL_CALL
	 * flag; their magic value is used for switch-case.
	 *
	 * NOTE: duk_unpack_array_like() reserves value stack space
	 * for the result values (unlike most other value stack calls).
	 */
	switch (((duk_hnatfunc *) func)->magic) {
	case 0: {  /* 0=Function.prototype.call() */
		/* Value stack:
		 * idx_func + 0: Function.prototype.call()  [removed]
		 * idx_func + 1: this binding for .call (target function)
		 * idx_func + 2: 1st argument to .call, desired 'this' binding
		 * idx_func + 3: 2nd argument to .call, desired 1st argument for ultimate target
		 * ...
		 *
		 * Remove idx_func + 0 to get:
		 * idx_func + 0: target function
		 * idx_func + 1: this binding
		 * idx_func + 2: call arguments
		 * ...
		 */
		DUK_ASSERT(natfunc == duk_bi_function_prototype_call);
		duk_remove_unsafe(thr, idx_func);
		tv_args = thr->valstack_bottom + idx_func + 2;
		if (thr->valstack_top < tv_args) {
			DUK_ASSERT(tv_args <= thr->valstack_end);
			thr->valstack_top = tv_args;  /* at least target function and 'this' binding present */
		}
		break;
	}
	case 1: {  /* 1=Function.prototype.apply() */
		/* Value stack:
		 * idx_func + 0: Function.prototype.apply()  [removed]
		 * idx_func + 1: this binding for .apply (target function)
		 * idx_func + 2: 1st argument to .apply, desired 'this' binding
		 * idx_func + 3: 2nd argument to .apply, argArray
		 * [anything after this MUST be ignored]
		 *
		 * Remove idx_func + 0 and unpack the argArray to get:
		 * idx_func + 0: target function
		 * idx_func + 1: this binding
		 * idx_func + 2: call arguments
		 * ...
		 */
		DUK_ASSERT(natfunc == duk_bi_function_prototype_apply);
		duk_remove_unsafe(thr, idx_func);
		goto apply_shared;
	}
#if defined(DUK_USE_REFLECT_BUILTIN)
	case 2: {  /* 2=Reflect.apply() */
		/* Value stack:
		 * idx_func + 0: Reflect.apply()  [removed]
		 * idx_func + 1: this binding for .apply (ignored, usually Reflect)  [removed]
		 * idx_func + 2: 1st argument to .apply, target function
		 * idx_func + 3: 2nd argument to .apply, desired 'this' binding
		 * idx_func + 4: 3rd argument to .apply, argArray
		 * [anything after this MUST be ignored]
		 *
		 * Remove idx_func + 0 and idx_func + 1, and unpack the argArray to get:
		 * idx_func + 0: target function
		 * idx_func + 1: this binding
		 * idx_func + 2: call arguments
		 * ...
		 */
		DUK_ASSERT(natfunc == duk_bi_reflect_apply);
		duk_remove_n_unsafe(thr, idx_func, 2);
		goto apply_shared;
	}
	case 3: {  /* 3=Reflect.construct() */
		/* Value stack:
		 * idx_func + 0: Reflect.construct()  [removed]
		 * idx_func + 1: this binding for .construct (ignored, usually Reflect)  [removed]
		 * idx_func + 2: 1st argument to .construct, target function
		 * idx_func + 3: 2nd argument to .construct, argArray
		 * idx_func + 4: 3rd argument to .construct, newTarget
		 * [anything after this MUST be ignored]
		 *
		 * Remove idx_func + 0 and idx_func + 1, unpack the argArray,
		 * and insert default instance (prototype not yet updated), to get:
		 * idx_func + 0: target function
		 * idx_func + 1: this binding (default instance)
		 * idx_func + 2: constructor call arguments
		 * ...
		 *
		 * Call flags must be updated to reflect the fact that we're
		 * now dealing with a constructor call, and e.g. the 'this'
		 * binding cannot be overwritten if the target is bound.
		 *
		 * newTarget is checked but not yet passed onwards.
		 */

		duk_idx_t top;

		DUK_ASSERT(natfunc == duk_bi_reflect_construct);
		*call_flags |= DUK_CALL_FLAG_CONSTRUCT;
		duk_remove_n_unsafe(thr, idx_func, 2);
		top = duk_get_top(thr);
		if (!duk_is_constructable(thr, idx_func)) {
			/* Target constructability must be checked before
			 * unpacking argArray (which may cause side effects).
			 * Just return; caller will throw the error.
			 */
			duk_set_top_unsafe(thr, idx_func + 2);  /* satisfy asserts */
			break;
		}
		duk_push_object(thr);
		duk_insert(thr, idx_func + 1);  /* default instance */

		/* [ ... func default_instance argArray newTarget? ] */

		top = duk_get_top(thr);
		if (top < idx_func + 3) {
			/* argArray is a mandatory argument for Reflect.construct(). */
			DUK_ERROR_TYPE_INVALID_ARGS(thr);
			DUK_WO_NORETURN(return 0;);
		}
		if (top > idx_func + 3) {
			if (!duk_strict_equals(thr, idx_func, idx_func + 3)) {
				/* XXX: [[Construct]] newTarget currently unsupported */
				DUK_ERROR_UNSUPPORTED(thr);
				DUK_WO_NORETURN(return 0;);
			}
			duk_set_top_unsafe(thr, idx_func + 3);  /* remove any args beyond argArray */
		}
		DUK_ASSERT(duk_get_top(thr) == idx_func + 3);
		DUK_ASSERT(duk_is_valid_index(thr, idx_func + 2));
		(void) duk_unpack_array_like(thr, idx_func + 2);  /* XXX: should also remove target to be symmetric with duk_pack()? */
		duk_remove(thr, idx_func + 2);
		DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
		break;
	}
#endif  /* DUK_USE_REFLECT_BUILTIN */
	default: {
		DUK_ASSERT(0);
		DUK_UNREACHABLE();
	}
	}

	DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
	return 0;  /* keep resolving */

 apply_shared:
	tv_args = thr->valstack_bottom + idx_func + 2;
	if (thr->valstack_top <= tv_args) {
		DUK_ASSERT(tv_args <= thr->valstack_end);
		thr->valstack_top = tv_args;  /* at least target func and 'this' binding present */
		/* No need to check for argArray. */
	} else {
		DUK_ASSERT(duk_get_top(thr) >= idx_func + 3);  /* idx_func + 2 covered above */
		if (thr->valstack_top > tv_args + 1) {
			duk_set_top_unsafe(thr, idx_func + 3);  /* remove any args beyond argArray */
		}
		DUK_ASSERT(duk_is_valid_index(thr, idx_func + 2));
		if (!duk_is_callable(thr, idx_func)) {
			/* Avoid unpack side effects if the target isn't callable.
			 * Calling code will throw the actual error.
			 */
		} else {
			(void) duk_unpack_array_like(thr, idx_func + 2);
			duk_remove(thr, idx_func + 2);
		}
	}
	DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
	return 0;  /* keep resolving */
}

/*
 *  Helper for Proxy handling.
 */

#if defined(DUK_USE_ES6_PROXY)
DUK_LOCAL void duk__handle_proxy_for_call(duk_hthread *thr, duk_idx_t idx_func, duk_hproxy *h_proxy, duk_small_uint_t *call_flags) {
	duk_bool_t rc;

	/* Value stack:
	 * idx_func + 0: Proxy object
	 * idx_func + 1: this binding for call
	 * idx_func + 2: 1st argument for call
	 * idx_func + 3: 2nd argument for call
	 * ...
	 *
	 * If Proxy doesn't have a trap for the call ('apply' or 'construct'),
	 * replace Proxy object with target object.
	 *
	 * If we're dealing with a normal call and the Proxy has an 'apply'
	 * trap, manipulate value stack to:
	 *
	 * idx_func + 0: trap
	 * idx_func + 1: Proxy's handler
	 * idx_func + 2: Proxy's target
	 * idx_func + 3: this binding for call (from idx_func + 1)
	 * idx_func + 4: call arguments packed to an array
	 *
	 * If we're dealing with a constructor call and the Proxy has a
	 * 'construct' trap, manipulate value stack to:
	 *
	 * idx_func + 0: trap
	 * idx_func + 1: Proxy's handler
	 * idx_func + 2: Proxy's target
	 * idx_func + 3: call arguments packed to an array
	 * idx_func + 4: newTarget == Proxy object here
	 *
	 * As we don't yet have proper newTarget support, the newTarget at
	 * idx_func + 3 is just the original constructor being called, i.e.
	 * the Proxy object (not the target).  Note that the default instance
	 * (original 'this' binding) is dropped and ignored.
	 */

	duk_push_hobject(thr, h_proxy->handler);
	rc = duk_get_prop_stridx_short(thr, -1, (*call_flags & DUK_CALL_FLAG_CONSTRUCT) ? DUK_STRIDX_CONSTRUCT : DUK_STRIDX_APPLY);
	if (rc == 0) {
		/* Not found, continue to target.  If this is a construct
		 * call, update default instance prototype using the Proxy,
		 * not the target.
		 */
		if (*call_flags & DUK_CALL_FLAG_CONSTRUCT) {
			if (!(*call_flags & DUK_CALL_FLAG_DEFAULT_INSTANCE_UPDATED)) {
				*call_flags |= DUK_CALL_FLAG_DEFAULT_INSTANCE_UPDATED;
				duk__update_default_instance_proto(thr, idx_func);
			}
		}
		duk_pop_2(thr);
		duk_push_hobject(thr, h_proxy->target);
		duk_replace(thr, idx_func);
		return;
	}

	/* Here we must be careful not to replace idx_func while
	 * h_proxy is still needed, otherwise h_proxy may become
	 * dangling.  This could be improved e.g. using a
	 * duk_pack_slice() with a freeform slice.
	 */

	/* Here:
	 * idx_func + 0: Proxy object
	 * idx_func + 1: this binding for call
	 * idx_func + 2: 1st argument for call
	 * idx_func + 3: 2nd argument for call
	 * ...
	 * idx_func + N: handler
	 * idx_func + N + 1: trap
	 */

	duk_insert(thr, idx_func + 1);
	duk_insert(thr, idx_func + 2);
	duk_push_hobject(thr, h_proxy->target);
	duk_insert(thr, idx_func + 3);
	duk_pack(thr, duk_get_top(thr) - (idx_func + 5));
	DUK_ASSERT(!duk_is_bare_object(thr, -1));

	/* Here:
	 * idx_func + 0: Proxy object
	 * idx_func + 1: trap
	 * idx_func + 2: Proxy's handler
	 * idx_func + 3: Proxy's target
	 * idx_func + 4: this binding for call
	 * idx_func + 5: arguments array
	 */
	DUK_ASSERT(duk_get_top(thr) == idx_func + 6);

	if (*call_flags & DUK_CALL_FLAG_CONSTRUCT) {
		*call_flags |= DUK_CALL_FLAG_CONSTRUCT_PROXY;  /* Enable 'construct' trap return invariant check. */
		*call_flags &= ~(DUK_CALL_FLAG_CONSTRUCT);     /* Resume as non-constructor call to the trap. */

		/* 'apply' args: target, thisArg, argArray
		 * 'construct' args: target, argArray, newTarget
		 */
		duk_remove(thr, idx_func + 4);
		duk_push_hobject(thr, (duk_hobject *) h_proxy);
	}

	/* Finalize value stack layout by removing Proxy reference. */
	duk_remove(thr, idx_func);
	h_proxy = NULL;  /* invalidated */
	DUK_ASSERT(duk_get_top(thr) == idx_func + 5);
}
#endif  /* DUK_USE_ES6_PROXY */

/*
 *  Helper for setting up var_env and lex_env of an activation,
 *  assuming it does NOT have the DUK_HOBJECT_FLAG_NEWENV flag.
 */

DUK_LOCAL void duk__handle_oldenv_for_call(duk_hthread *thr,
                                           duk_hobject *func,
                                           duk_activation *act) {
	duk_hcompfunc *f;
	duk_hobject *h_lex;
	duk_hobject *h_var;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(func != NULL);
	DUK_ASSERT(act != NULL);
	DUK_ASSERT(!DUK_HOBJECT_HAS_NEWENV(func));
	DUK_ASSERT(!DUK_HOBJECT_HAS_CREATEARGS(func));
	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(func));
	DUK_UNREF(thr);

	f = (duk_hcompfunc *) func;
	h_lex = DUK_HCOMPFUNC_GET_LEXENV(thr->heap, f);
	h_var = DUK_HCOMPFUNC_GET_VARENV(thr->heap, f);
	DUK_ASSERT(h_lex != NULL);  /* Always true for closures (not for templates) */
	DUK_ASSERT(h_var != NULL);
	act->lex_env = h_lex;
	act->var_env = h_var;
	DUK_HOBJECT_INCREF(thr, h_lex);
	DUK_HOBJECT_INCREF(thr, h_var);
}

/*
 *  Helper for updating callee 'caller' property.
 */

#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
DUK_LOCAL void duk__update_func_caller_prop(duk_hthread *thr, duk_hobject *func) {
	duk_tval *tv_caller;
	duk_hobject *h_tmp;
	duk_activation *act_callee;
	duk_activation *act_caller;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(func != NULL);
	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(func));  /* bound chain resolved */
	DUK_ASSERT(thr->callstack_top >= 1);

	if (DUK_HOBJECT_HAS_STRICT(func)) {
		/* Strict functions don't get their 'caller' updated. */
		return;
	}

	DUK_ASSERT(thr->callstack_top > 0);
	act_callee = thr->callstack_curr;
	DUK_ASSERT(act_callee != NULL);
	act_caller = (thr->callstack_top >= 2 ? act_callee->parent : NULL);

	/* XXX: check .caller writability? */

	/* Backup 'caller' property and update its value. */
	tv_caller = duk_hobject_find_entry_tval_ptr_stridx(thr->heap, func, DUK_STRIDX_CALLER);
	if (tv_caller) {
		/* If caller is global/eval code, 'caller' should be set to
		 * 'null'.
		 *
		 * XXX: there is no exotic flag to infer this correctly now.
		 * The NEWENV flag is used now which works as intended for
		 * everything (global code, non-strict eval code, and functions)
		 * except strict eval code.  Bound functions are never an issue
		 * because 'func' has been resolved to a non-bound function.
		 */

		if (act_caller != NULL) {
			/* act_caller->func may be NULL in some finalization cases,
			 * just treat like we don't know the caller.
			 */
			if (act_caller->func && !DUK_HOBJECT_HAS_NEWENV(act_caller->func)) {
				/* Setting to NULL causes 'caller' to be set to
				 * 'null' as desired.
				 */
				act_caller = NULL;
			}
		}

		if (DUK_TVAL_IS_OBJECT(tv_caller)) {
			h_tmp = DUK_TVAL_GET_OBJECT(tv_caller);
			DUK_ASSERT(h_tmp != NULL);
			act_callee->prev_caller = h_tmp;

			/* Previous value doesn't need refcount changes because its ownership
			 * is transferred to prev_caller.
			 */

			if (act_caller != NULL) {
				DUK_ASSERT(act_caller->func != NULL);
				DUK_TVAL_SET_OBJECT(tv_caller, act_caller->func);
				DUK_TVAL_INCREF(thr, tv_caller);
			} else {
				DUK_TVAL_SET_NULL(tv_caller);  /* no incref */
			}
		} else {
			/* 'caller' must only take on 'null' or function value */
			DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv_caller));
			DUK_ASSERT(act_callee->prev_caller == NULL);
			if (act_caller != NULL && act_caller->func) {
				/* Tolerate act_caller->func == NULL which happens in
				 * some finalization cases; treat like unknown caller.
				 */
				DUK_TVAL_SET_OBJECT(tv_caller, act_caller->func);
				DUK_TVAL_INCREF(thr, tv_caller);
			} else {
				DUK_TVAL_SET_NULL(tv_caller);  /* no incref */
			}
		}
	}
}
#endif  /* DUK_USE_NONSTD_FUNC_CALLER_PROPERTY */

/*
 *  Shared helpers for resolving the final, non-bound target function of the
 *  call and the effective 'this' binding.  Resolves bound functions and
 *  applies .call(), .apply(), and .construct() inline.
 *
 *  Proxy traps are also handled inline so that if the target is a Proxy with
 *  a 'call' or 'construct' trap, the trap handler is called with a modified
 *  argument list.
 *
 *  Once the bound function / .call() / .apply() / .construct() sequence has
 *  been resolved, the value at idx_func + 1 may need coercion described in
 *  E5 Section 10.4.3.
 *
 *  A call that begins as a non-constructor call may be converted into a
 *  constructor call during the resolution process if Reflect.construct()
 *  is invoked.  This is handled by updating the caller's call_flags.
 *
 *  For global and eval code (E5 Sections 10.4.1 and 10.4.2), we assume
 *  that the caller has provided the correct 'this' binding explicitly
 *  when calling, i.e.:
 *
 *    - global code: this=global object
 *    - direct eval: this=copy from eval() caller's this binding
 *    - other eval:  this=global object
 *
 *  The 'this' coercion may cause a recursive function call with arbitrary
 *  side effects, because ToObject() may be called.
 */

DUK_LOCAL DUK_INLINE void duk__coerce_nonstrict_this_binding(duk_hthread *thr, duk_idx_t idx_this) {
	duk_tval *tv_this;
	duk_hobject *obj_global;

	tv_this = thr->valstack_bottom + idx_this;
	switch (DUK_TVAL_GET_TAG(tv_this)) {
	case DUK_TAG_OBJECT:
		DUK_DDD(DUK_DDDPRINT("this binding: non-strict, object -> use directly"));
		break;
	case DUK_TAG_UNDEFINED:
	case DUK_TAG_NULL:
		DUK_DDD(DUK_DDDPRINT("this binding: non-strict, undefined/null -> use global object"));
		obj_global = thr->builtins[DUK_BIDX_GLOBAL];
		/* XXX: avoid this check somehow */
		if (DUK_LIKELY(obj_global != NULL)) {
			DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv_this));  /* no need to decref previous value */
			DUK_TVAL_SET_OBJECT(tv_this, obj_global);
			DUK_HOBJECT_INCREF(thr, obj_global);
		} else {
			/* This may only happen if built-ins are being "torn down".
			 * This behavior is out of specification scope.
			 */
			DUK_D(DUK_DPRINT("this binding: wanted to use global object, but it is NULL -> using undefined instead"));
			DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv_this));  /* no need to decref previous value */
			DUK_TVAL_SET_UNDEFINED(tv_this);  /* nothing to incref */
		}
		break;
	default:
		/* Plain buffers and lightfuncs are object coerced.  Lightfuncs
		 * very rarely come here however, because the call target would
		 * need to be a non-strict non-lightfunc (lightfuncs are considered
		 * strict) with an explicit lightfunc 'this' binding.
		 */
		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv_this));
		DUK_DDD(DUK_DDDPRINT("this binding: non-strict, not object/undefined/null -> use ToObject(value)"));
		duk_to_object(thr, idx_this);  /* may have side effects */
		break;
	}
}

DUK_LOCAL DUK_ALWAYS_INLINE duk_bool_t duk__resolve_target_fastpath_check(duk_hthread *thr, duk_idx_t idx_func, duk_hobject **out_func, duk_small_uint_t call_flags) {
#if defined(DUK_USE_PREFER_SIZE)
	DUK_UNREF(thr);
	DUK_UNREF(idx_func);
	DUK_UNREF(out_func);
	DUK_UNREF(call_flags);
#else  /* DUK_USE_PREFER_SIZE */
	duk_tval *tv_func;
	duk_hobject *func;

	if (DUK_UNLIKELY(call_flags & DUK_CALL_FLAG_CONSTRUCT)) {
		return 0;
	}

	tv_func = DUK_GET_TVAL_POSIDX(thr, idx_func);
	DUK_ASSERT(tv_func != NULL);

	if (DUK_LIKELY(DUK_TVAL_IS_OBJECT(tv_func))) {
		func = DUK_TVAL_GET_OBJECT(tv_func);
		if (DUK_HOBJECT_IS_CALLABLE(func) &&
		    !DUK_HOBJECT_HAS_BOUNDFUNC(func) &&
		    !DUK_HOBJECT_HAS_SPECIAL_CALL(func)) {
			*out_func = func;

			if (DUK_HOBJECT_HAS_STRICT(func)) {
				/* Strict function: no 'this' coercion. */
				return 1;
			}

			duk__coerce_nonstrict_this_binding(thr, idx_func + 1);
			return 1;
		}
	} else if (DUK_TVAL_IS_LIGHTFUNC(tv_func)) {
		*out_func = NULL;

		/* Lightfuncs are considered strict, so 'this' binding is
		 * used as is.  They're never bound, always constructable,
		 * and never special functions.
		 */
		return 1;
	}
#endif  /* DUK_USE_PREFER_SIZE */
	return 0;  /* let slow path deal with it */
}

DUK_LOCAL duk_hobject *duk__resolve_target_func_and_this_binding(duk_hthread *thr,
                                                                 duk_idx_t idx_func,
                                                                 duk_small_uint_t *call_flags) {
	duk_tval *tv_func;
	duk_hobject *func;
	duk_bool_t first;

	DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);

	for (first = 1;; first = 0) {
		DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);

		tv_func = DUK_GET_TVAL_POSIDX(thr, idx_func);
		DUK_ASSERT(tv_func != NULL);

		DUK_DD(DUK_DDPRINT("target func: %!iT", tv_func));

		if (DUK_TVAL_IS_OBJECT(tv_func)) {
			func = DUK_TVAL_GET_OBJECT(tv_func);

			if (*call_flags & DUK_CALL_FLAG_CONSTRUCT) {
				if (DUK_UNLIKELY(!DUK_HOBJECT_HAS_CONSTRUCTABLE(func))) {
					goto not_constructable;
				}
			} else {
				if (DUK_UNLIKELY(!DUK_HOBJECT_IS_CALLABLE(func))) {
					goto not_callable;
				}
			}

			if (DUK_LIKELY(!DUK_HOBJECT_HAS_BOUNDFUNC(func) &&
			               !DUK_HOBJECT_HAS_SPECIAL_CALL(func) &&
			               !DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(func))) {
				/* Common case, so test for using a single bitfield test.
				 * Break out to handle this coercion etc.
				 */
				break;
			}

			/* XXX: could set specialcall for boundfuncs too, simplify check above */

			if (DUK_HOBJECT_HAS_BOUNDFUNC(func)) {
				DUK_ASSERT(!DUK_HOBJECT_HAS_SPECIAL_CALL(func));
				DUK_ASSERT(!DUK_HOBJECT_IS_NATFUNC(func));

				/* Callable/constructable flags are the same
				 * for the bound function and its target, so
				 * we don't need to check them here, we can
				 * check them from the target only.
				 */
				duk__handle_bound_chain_for_call(thr, idx_func, *call_flags & DUK_CALL_FLAG_CONSTRUCT);

				DUK_ASSERT(DUK_TVAL_IS_OBJECT(duk_require_tval(thr, idx_func)) ||
				           DUK_TVAL_IS_LIGHTFUNC(duk_require_tval(thr, idx_func)));
			} else {
				DUK_ASSERT(DUK_HOBJECT_HAS_SPECIAL_CALL(func));

#if defined(DUK_USE_ES6_PROXY)
				if (DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(func)) {
					/* If no trap, resume processing from Proxy trap.
					 * If trap exists, helper converts call into a trap
					 * call; this may change a constructor call into a
					 * normal (non-constructor) trap call.  We must
					 * continue processing even when a trap is found as
					 * the trap may be bound.
					 */
					duk__handle_proxy_for_call(thr, idx_func, (duk_hproxy *) func, call_flags);
				}
				else
#endif
				{
					DUK_ASSERT(DUK_HOBJECT_IS_NATFUNC(func));
					DUK_ASSERT(DUK_HOBJECT_HAS_CALLABLE(func));
					DUK_ASSERT(!DUK_HOBJECT_HAS_CONSTRUCTABLE(func));
					/* Constructable check already done above. */

					if (duk__handle_specialfuncs_for_call(thr, idx_func, func, call_flags, first) != 0) {
						/* Encountered native eval call, normal call
						 * context.  Break out, handle this coercion etc.
						 */
						break;
					}
				}
			}
			/* Retry loop. */
		} else if (DUK_TVAL_IS_LIGHTFUNC(tv_func)) {
			/* Lightfuncs are:
			 *   - Always strict, so no 'this' coercion.
			 *   - Always callable.
			 *   - Always constructable.
			 *   - Never specialfuncs.
			 */
			func = NULL;
			goto finished;
		} else {
			goto not_callable;
		}
	}

	DUK_ASSERT(func != NULL);

	if (!DUK_HOBJECT_HAS_STRICT(func)) {
		/* Non-strict target needs 'this' coercion.
		 * This has potential side effects invalidating
		 * 'tv_func'.
		 */
		duk__coerce_nonstrict_this_binding(thr, idx_func + 1);
	}
	if (*call_flags & DUK_CALL_FLAG_CONSTRUCT) {
		if (!(*call_flags & DUK_CALL_FLAG_DEFAULT_INSTANCE_UPDATED)) {
			*call_flags |= DUK_CALL_FLAG_DEFAULT_INSTANCE_UPDATED;
			duk__update_default_instance_proto(thr, idx_func);
		}
	}

 finished:

#if defined(DUK_USE_ASSERTIONS)
	{
		duk_tval *tv_tmp;

		tv_tmp = duk_get_tval(thr, idx_func);
		DUK_ASSERT(tv_tmp != NULL);

		DUK_ASSERT((DUK_TVAL_IS_OBJECT(tv_tmp) && DUK_HOBJECT_IS_CALLABLE(DUK_TVAL_GET_OBJECT(tv_tmp))) ||
		           DUK_TVAL_IS_LIGHTFUNC(tv_tmp));
		DUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUNDFUNC(func));
		DUK_ASSERT(func == NULL || (DUK_HOBJECT_IS_COMPFUNC(func) ||
		                            DUK_HOBJECT_IS_NATFUNC(func)));
		DUK_ASSERT(func == NULL || (DUK_HOBJECT_HAS_CONSTRUCTABLE(func) ||
		                            (*call_flags & DUK_CALL_FLAG_CONSTRUCT) == 0));
	}
#endif

	return func;

 not_callable:
	DUK_ASSERT(tv_func != NULL);

#if defined(DUK_USE_VERBOSE_ERRORS)
	/* GETPROPC delayed error handling: when target is not callable,
	 * GETPROPC replaces idx_func+0 with a non-callable wrapper object
	 * with a hidden Symbol to signify it's to be handled here.  If
	 * found, unwrap the original Error and throw it as is here.  The
	 * hidden Symbol is only checked as an own property, not inherited
	 * (which would be dangerous).
	 */
	if (DUK_TVAL_IS_OBJECT(tv_func)) {
		duk_tval *tv_wrap = duk_hobject_find_entry_tval_ptr_stridx(thr->heap, DUK_TVAL_GET_OBJECT(tv_func), DUK_STRIDX_INT_TARGET);
		if (tv_wrap != NULL) {
			DUK_DD(DUK_DDPRINT("delayed error from GETPROPC: %!T", tv_wrap));
			duk_push_tval(thr, tv_wrap);
			(void) duk_throw(thr);
			DUK_WO_NORETURN(return NULL;);
		}
	}
#endif

#if defined(DUK_USE_VERBOSE_ERRORS)
#if defined(DUK_USE_PARANOID_ERRORS)
	DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "%s not callable", duk_get_type_name(thr, idx_func));
#else
	DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "%s not callable", duk_push_string_tval_readable(thr, tv_func));
#endif
#else
	DUK_ERROR_TYPE(thr, DUK_STR_NOT_CALLABLE);
#endif
	DUK_WO_NORETURN(return NULL;);

 not_constructable:
	/* For now GETPROPC delayed error not needed for constructor calls. */
#if defined(DUK_USE_VERBOSE_ERRORS)
#if defined(DUK_USE_PARANOID_ERRORS)
	DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "%s not constructable", duk_get_type_name(thr, idx_func));
#else
	DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "%s not constructable", duk_push_string_tval_readable(thr, tv_func));
#endif
#else
	DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONSTRUCTABLE);
#endif
	DUK_WO_NORETURN(return NULL;);
}

/*
 *  Manipulate value stack so that exactly 'num_stack_rets' return
 *  values are at 'idx_retbase' in every case, assuming there are
 *  'rc' return values on top of stack.
 *
 *  This is a bit tricky, because the called C function operates in
 *  the same activation record and may have e.g. popped the stack
 *  empty (below idx_retbase).
 */

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) {
	duk_idx_t idx_rcbase;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(idx_retbase >= 0);
	DUK_ASSERT(num_stack_rets >= 0);
	DUK_ASSERT(num_actual_rets >= 0);

	idx_rcbase = duk_get_top(thr) - num_actual_rets;  /* base of known return values */
	if (DUK_UNLIKELY(idx_rcbase < 0)) {
		DUK_ERROR_TYPE(thr, DUK_STR_INVALID_CFUNC_RC);
		DUK_WO_NORETURN(return;);
	}

	DUK_DDD(DUK_DDDPRINT("adjust valstack after func call: "
	                     "num_stack_rets=%ld, num_actual_rets=%ld, stack_top=%ld, idx_retbase=%ld, idx_rcbase=%ld",
	                     (long) num_stack_rets, (long) num_actual_rets, (long) duk_get_top(thr),
	                     (long) idx_retbase, (long) idx_rcbase));

	DUK_ASSERT(idx_rcbase >= 0);  /* caller must check */

	/* Space for num_stack_rets was reserved before the safe call.
	 * Because value stack reserve cannot shrink except in call returns,
	 * the reserve is still in place.  Adjust valstack, carefully
	 * ensuring we don't overstep the reserve.
	 */

	/* Match idx_rcbase with idx_retbase so that the return values
	 * start at the correct index.
	 */
	if (idx_rcbase > idx_retbase) {
		duk_idx_t count = idx_rcbase - idx_retbase;

		DUK_DDD(DUK_DDDPRINT("elements at/after idx_retbase have enough to cover func retvals "
		                     "(idx_retbase=%ld, idx_rcbase=%ld)", (long) idx_retbase, (long) idx_rcbase));

		/* Remove values between irc_rcbase (start of intended return
		 * values) and idx_retbase to lower return values to idx_retbase.
		 */
		DUK_ASSERT(count > 0);
		duk_remove_n(thr, idx_retbase, count);  /* may be NORZ */
	} else {
		duk_idx_t count = idx_retbase - idx_rcbase;

		DUK_DDD(DUK_DDDPRINT("not enough elements at/after idx_retbase to cover func retvals "
		                     "(idx_retbase=%ld, idx_rcbase=%ld)", (long) idx_retbase, (long) idx_rcbase));

		/* Insert 'undefined' at idx_rcbase (start of intended return
		 * values) to lift return values to idx_retbase.
		 */
		DUK_ASSERT(count >= 0);
		DUK_ASSERT(thr->valstack_end - thr->valstack_top >= count);  /* reserve cannot shrink */
		duk_insert_undefined_n(thr, idx_rcbase, count);
	}

	/* Chop extra retvals away / extend with undefined. */
	duk_set_top_unsafe(thr, idx_retbase + num_stack_rets);
}

/*
 *  Activation setup for tailcalls and non-tailcalls.
 */

#if defined(DUK_USE_TAILCALL)
DUK_LOCAL duk_small_uint_t duk__call_setup_act_attempt_tailcall(duk_hthread *thr,
                                                                duk_small_uint_t call_flags,
                                                                duk_idx_t idx_func,
                                                                duk_hobject *func,
                                                                duk_size_t entry_valstack_bottom_byteoff,
                                                                duk_size_t entry_valstack_end_byteoff,
                                                                duk_idx_t *out_nargs,
                                                                duk_idx_t *out_nregs,
                                                                duk_size_t *out_vs_min_bytes,
                                                                duk_activation **out_act) {
	duk_activation *act;
	duk_tval *tv1, *tv2;
	duk_idx_t idx_args;
	duk_small_uint_t flags1, flags2;
#if defined(DUK_USE_DEBUGGER_SUPPORT)
	duk_activation *prev_pause_act;
#endif

	DUK_UNREF(entry_valstack_end_byteoff);

	/* Tailcall cannot be flagged to resume calls, and a
	 * previous frame must exist.
	 */
	DUK_ASSERT(thr->callstack_top >= 1);

	act = thr->callstack_curr;
	DUK_ASSERT(act != NULL);
	*out_act = act;

	if (func == NULL || !DUK_HOBJECT_IS_COMPFUNC(func)) {
		DUK_DDD(DUK_DDDPRINT("tail call prevented by target not being ecma function"));
		return 0;
	}
	if (act->flags & DUK_ACT_FLAG_PREVENT_YIELD) {
		DUK_DDD(DUK_DDDPRINT("tail call prevented by current activation having DUK_ACT_FLAG_PREVENT_YIELD"));
		return 0;
	}
	/* Tailcall is only allowed if current and candidate
	 * function have identical return value handling.  There
	 * are three possible return value handling cases:
	 *   1. Normal function call, no special return value handling.
	 *   2. Constructor call, return value replacement object check.
	 *   3. Proxy 'construct' trap call, return value invariant check.
	 */
	flags1 = (duk_small_uint_t) ((act->flags & DUK_ACT_FLAG_CONSTRUCT) ? 1 : 0)
#if defined(DUK_USE_ES6_PROXY)
	         | (duk_small_uint_t) ((act->flags & DUK_ACT_FLAG_CONSTRUCT_PROXY) ? 2 : 0)
#endif
	         ;
	flags2 = (duk_small_uint_t) ((call_flags & DUK_CALL_FLAG_CONSTRUCT) ? 1 : 0)
#if defined(DUK_USE_ES6_PROXY)
	         | (duk_small_uint_t) ((call_flags & DUK_CALL_FLAG_CONSTRUCT_PROXY) ? 2 : 0);
#endif
	         ;
	if (flags1 != flags2) {
		DUK_DDD(DUK_DDDPRINT("tail call prevented by incompatible return value handling"));
		return 0;
	}
	DUK_ASSERT(((act->flags & DUK_ACT_FLAG_CONSTRUCT) && (call_flags & DUK_CALL_FLAG_CONSTRUCT)) ||
	           (!(act->flags & DUK_ACT_FLAG_CONSTRUCT) && !(call_flags & DUK_CALL_FLAG_CONSTRUCT)));
	DUK_ASSERT(((act->flags & DUK_ACT_FLAG_CONSTRUCT_PROXY) && (call_flags & DUK_CALL_FLAG_CONSTRUCT_PROXY)) ||
	           (!(act->flags & DUK_ACT_FLAG_CONSTRUCT_PROXY) && !(call_flags & DUK_CALL_FLAG_CONSTRUCT_PROXY)));
	if (DUK_HOBJECT_HAS_NOTAIL(func)) {
		/* See: test-bug-tailcall-preventyield-assert.c. */
		DUK_DDD(DUK_DDDPRINT("tail call prevented by function having a notail flag"));
		return 0;
	}

	/*
	 *  Tailcall handling
	 *
	 *  Although the callstack entry is reused, we need to explicitly unwind
	 *  the current activation (or simulate an unwind).  In particular, the
	 *  current activation must be closed, otherwise something like
	 *  test-bug-reduce-judofyr.js results.  Also catchers need to be unwound
	 *  because there may be non-error-catching label entries in valid tail calls.
	 *
	 *  Special attention is needed for debugger and pause behavior when
	 *  reusing an activation.
	 *    - Disable StepOut processing for the activation unwind because
	 *      we reuse the activation, see:
	 *      https://github.com/svaarala/duktape/issues/1684.
	 *    - Disable line change pause flag permanently if act == dbg_pause_act
	 *      (if set) because it would no longer be relevant, see:
	 *      https://github.com/svaarala/duktape/issues/1726,
	 *      https://github.com/svaarala/duktape/issues/1786.
	 *    - Check for function entry (e.g. StepInto) pause flag here, because
	 *      the executor pause check won't trigger due to shared activation, see:
	 *      https://github.com/svaarala/duktape/issues/1726.
	 */

	DUK_DDD(DUK_DDDPRINT("is tail call, reusing activation at callstack top, at index %ld",
                             (long) (thr->callstack_top - 1)));

	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(func));
	DUK_ASSERT(!DUK_HOBJECT_HAS_NATFUNC(func));
	DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(func));
	DUK_ASSERT((act->flags & DUK_ACT_FLAG_PREVENT_YIELD) == 0);
	DUK_ASSERT(call_flags & DUK_CALL_FLAG_ALLOW_ECMATOECMA);

	/* Unwind the topmost callstack entry before reusing it.  This
	 * also unwinds the catchers related to the topmost entry.
	 */
	DUK_ASSERT(thr->callstack_top > 0);
	DUK_ASSERT(thr->callstack_curr != NULL);
#if defined(DUK_USE_DEBUGGER_SUPPORT)
	if (act == thr->heap->dbg_pause_act) {
		thr->heap->dbg_pause_flags &= ~DUK_PAUSE_FLAG_LINE_CHANGE;
	}

	prev_pause_act = thr->heap->dbg_pause_act;
	thr->heap->dbg_pause_act = NULL;
	if (thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_FUNC_ENTRY) {
		DUK_D(DUK_DPRINT("PAUSE TRIGGERED by function entry (tailcall)"));
		duk_debug_set_paused(thr->heap);
	}
#endif
	duk_hthread_activation_unwind_reuse_norz(thr);
#if defined(DUK_USE_DEBUGGER_SUPPORT)
	thr->heap->dbg_pause_act = prev_pause_act;
#endif
	DUK_ASSERT(act == thr->callstack_curr);

	/* XXX: We could restore the caller's value stack reserve
	 * here, as if we did an actual unwind-and-call.  Without
	 * the restoration, value stack reserve may remain higher
	 * than would otherwise be possible until we return to a
	 * non-tailcall.
	 */

	/* Then reuse the unwound activation. */
	act->cat = NULL;
	act->var_env = NULL;
	act->lex_env = NULL;
	DUK_ASSERT(func != NULL);
	DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(func));
	act->func = func;  /* don't want an intermediate exposed state with func == NULL */
#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
	act->prev_caller = NULL;
#endif
	/* don't want an intermediate exposed state with invalid pc */
	act->curr_pc = DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, (duk_hcompfunc *) func);
#if defined(DUK_USE_DEBUGGER_SUPPORT)
	act->prev_line = 0;
#endif
	DUK_TVAL_SET_OBJECT(&act->tv_func, func);  /* borrowed, no refcount */
	DUK_HOBJECT_INCREF(thr, func);

	act->flags = DUK_ACT_FLAG_TAILCALLED;
	if (DUK_HOBJECT_HAS_STRICT(func)) {
		act->flags |= DUK_ACT_FLAG_STRICT;
	}
	if (call_flags & DUK_CALL_FLAG_CONSTRUCT) {
		act->flags |= DUK_ACT_FLAG_CONSTRUCT;
	}
#if defined(DUK_USE_ES6_PROXY)
	if (call_flags & DUK_CALL_FLAG_CONSTRUCT_PROXY) {
		act->flags |= DUK_ACT_FLAG_CONSTRUCT_PROXY;
	}
#endif

	DUK_ASSERT(DUK_ACT_GET_FUNC(act) == func);      /* already updated */
	DUK_ASSERT(act->var_env == NULL);
	DUK_ASSERT(act->lex_env == NULL);
	act->bottom_byteoff = entry_valstack_bottom_byteoff;  /* tail call -> reuse current "frame" */
#if 0
	/* Topmost activation retval_byteoff is considered garbage, no need to init. */
	act->retval_byteoff = 0;
#endif
	/* Filled in when final reserve is known, dummy value doesn't matter
	 * even in error unwind because reserve_byteoff is only used when
	 * returning to -this- activation.
	 */
	act->reserve_byteoff = 0;

	/*
	 *  Manipulate valstack so that args are on the current bottom and the
	 *  previous caller's 'this' binding (which is the value preceding the
	 *  current bottom) is replaced with the new 'this' binding:
	 *
	 *       [ ... this_old | (crud) func this_new arg1 ... argN ]
	 *  -->  [ ... this_new | arg1 ... argN ]
	 *
	 *  For tail calling to work properly, the valstack bottom must not grow
	 *  here; otherwise crud would accumulate on the valstack.
	 */

	tv1 = thr->valstack_bottom - 1;
	tv2 = thr->valstack_bottom + idx_func + 1;
	DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);  /* tv1 is -below- valstack_bottom */
	DUK_ASSERT(tv2 >= thr->valstack_bottom && tv2 < thr->valstack_top);
	DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2);  /* side effects */

	idx_args = idx_func + 2;
	duk_remove_n(thr, 0, idx_args);  /* may be NORZ */

	idx_func = 0; DUK_UNREF(idx_func);  /* really 'not applicable' anymore, should not be referenced after this */
	idx_args = 0;

	*out_nargs = ((duk_hcompfunc *) func)->nargs;
	*out_nregs = ((duk_hcompfunc *) func)->nregs;
	DUK_ASSERT(*out_nregs >= 0);
	DUK_ASSERT(*out_nregs >= *out_nargs);
	*out_vs_min_bytes = entry_valstack_bottom_byteoff + sizeof(duk_tval) * ((duk_size_t) *out_nregs + DUK_VALSTACK_INTERNAL_EXTRA);


#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
#if defined(DUK_USE_TAILCALL)
#error incorrect options: tail calls enabled with function caller property
#endif
	/* XXX: This doesn't actually work properly for tail calls, so
	 * tail calls are disabled when DUK_USE_NONSTD_FUNC_CALLER_PROPERTY
	 * is in use.
	 */
	duk__update_func_caller_prop(thr, func);
#endif

	/* [ ... this_new | arg1 ... argN ] */

	return 1;
}
#endif  /* DUK_USE_TAILCALL */

DUK_LOCAL void duk__call_setup_act_not_tailcall(duk_hthread *thr,
                                                duk_small_uint_t call_flags,
                                                duk_idx_t idx_func,
                                                duk_hobject *func,
                                                duk_size_t entry_valstack_bottom_byteoff,
                                                duk_size_t entry_valstack_end_byteoff,
                                                duk_idx_t *out_nargs,
                                                duk_idx_t *out_nregs,
                                                duk_size_t *out_vs_min_bytes,
                                                duk_activation **out_act) {
	duk_activation *act;
	duk_activation *new_act;

	DUK_UNREF(entry_valstack_end_byteoff);

	DUK_DDD(DUK_DDDPRINT("not a tail call, pushing a new activation to callstack, to index %ld",
	                     (long) (thr->callstack_top)));

	duk__call_callstack_limit_check(thr);
	new_act = duk_hthread_activation_alloc(thr);
	DUK_ASSERT(new_act != NULL);

	act = thr->callstack_curr;
	if (act != NULL) {
		/*
		 *  Update return value stack index of current activation (if any).
		 *
		 *  Although it might seem this is not necessary (bytecode executor
		 *  does this for ECMAScript-to-ECMAScript calls; other calls are
		 *  handled here), this turns out to be necessary for handling yield
		 *  and resume.  For them, an ECMAScript-to-native call happens, and
		 *  the ECMAScript call's retval_byteoff must be set for things to work.
		 */

		act->retval_byteoff = entry_valstack_bottom_byteoff + (duk_size_t) idx_func * sizeof(duk_tval);
	}

	new_act->parent = act;
	thr->callstack_curr = new_act;
	thr->callstack_top++;
	act = new_act;
	*out_act = act;

	DUK_ASSERT(thr->valstack_top > thr->valstack_bottom);  /* at least effective 'this' */
	DUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUNDFUNC(func));

	act->cat = NULL;

	act->flags = 0;
	if (call_flags & DUK_CALL_FLAG_CONSTRUCT) {
		act->flags |= DUK_ACT_FLAG_CONSTRUCT;
	}
#if defined(DUK_USE_ES6_PROXY)
	if (call_flags & DUK_CALL_FLAG_CONSTRUCT_PROXY) {
		act->flags |= DUK_ACT_FLAG_CONSTRUCT_PROXY;
	}
#endif
	if (call_flags & DUK_CALL_FLAG_DIRECT_EVAL) {
		act->flags |= DUK_ACT_FLAG_DIRECT_EVAL;
	}

	/* start of arguments: idx_func + 2. */
	act->func = func;  /* NULL for lightfunc */
	if (DUK_LIKELY(func != NULL)) {
		DUK_TVAL_SET_OBJECT(&act->tv_func, func);  /* borrowed, no refcount */
		if (DUK_HOBJECT_HAS_STRICT(func)) {
			act->flags |= DUK_ACT_FLAG_STRICT;
		}
		if (DUK_HOBJECT_IS_COMPFUNC(func)) {
			*out_nargs = ((duk_hcompfunc *) func)->nargs;
			*out_nregs = ((duk_hcompfunc *) func)->nregs;
			DUK_ASSERT(*out_nregs >= 0);
			DUK_ASSERT(*out_nregs >= *out_nargs);
			*out_vs_min_bytes = entry_valstack_bottom_byteoff +
				sizeof(duk_tval) * ((duk_size_t) idx_func + 2U + (duk_size_t) *out_nregs + DUK_VALSTACK_INTERNAL_EXTRA);
		} else {
			/* True because of call target lookup checks. */
			DUK_ASSERT(DUK_HOBJECT_IS_NATFUNC(func));

			*out_nargs = ((duk_hnatfunc *) func)->nargs;
			*out_nregs = *out_nargs;
			if (*out_nargs >= 0) {
				*out_vs_min_bytes = entry_valstack_bottom_byteoff +
					sizeof(duk_tval) * ((duk_size_t) idx_func + 2U + (duk_size_t) *out_nregs + DUK_VALSTACK_API_ENTRY_MINIMUM + DUK_VALSTACK_INTERNAL_EXTRA);
			} else {
				/* Vararg function. */
				duk_size_t valstack_top_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_top - ((duk_uint8_t *) thr->valstack));
				*out_vs_min_bytes = valstack_top_byteoff +
					sizeof(duk_tval) * (DUK_VALSTACK_API_ENTRY_MINIMUM + DUK_VALSTACK_INTERNAL_EXTRA);
			}
		}
	} else {
		duk_small_uint_t lf_flags;
		duk_tval *tv_func;

		act->flags |= DUK_ACT_FLAG_STRICT;

		tv_func = DUK_GET_TVAL_POSIDX(thr, idx_func);
		DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv_func));
		DUK_TVAL_SET_TVAL(&act->tv_func, tv_func);  /* borrowed, no refcount */

		lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv_func);
		*out_nargs = DUK_LFUNC_FLAGS_GET_NARGS(lf_flags);
		if (*out_nargs != DUK_LFUNC_NARGS_VARARGS) {
			*out_vs_min_bytes = entry_valstack_bottom_byteoff +
				sizeof(duk_tval) * ((duk_size_t) idx_func + 2U + (duk_size_t) *out_nargs + DUK_VALSTACK_API_ENTRY_MINIMUM + DUK_VALSTACK_INTERNAL_EXTRA);
		} else {
			duk_size_t valstack_top_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_top - ((duk_uint8_t *) thr->valstack));
			*out_vs_min_bytes = valstack_top_byteoff +
				sizeof(duk_tval) * (DUK_VALSTACK_API_ENTRY_MINIMUM + DUK_VALSTACK_INTERNAL_EXTRA);
			*out_nargs = -1;  /* vararg */
		}
		*out_nregs = *out_nargs;
	}

	act->var_env = NULL;
	act->lex_env = NULL;
#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
	act->prev_caller = NULL;
#endif
	act->curr_pc = NULL;
#if defined(DUK_USE_DEBUGGER_SUPPORT)
	act->prev_line = 0;
#endif
	act->bottom_byteoff = entry_valstack_bottom_byteoff + sizeof(duk_tval) * ((duk_size_t) idx_func + 2U);
#if 0
	act->retval_byteoff = 0;   /* topmost activation retval_byteoff is considered garbage, no need to init */
#endif
	/* Filled in when final reserve is known, dummy value doesn't matter
	 * even in error unwind because reserve_byteoff is only used when
	 * returning to -this- activation.
	 */
	act->reserve_byteoff = 0;  /* filled in by caller */

	/* XXX: Is this INCREF necessary? 'func' is always a borrowed
	 * reference reachable through the value stack?  If changed, stack
	 * unwind code also needs to be fixed to match.
	 */
	DUK_HOBJECT_INCREF_ALLOWNULL(thr, func);  /* act->func */

#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
	if (func) {
		duk__update_func_caller_prop(thr, func);
	}
#endif
}

/*
 *  Environment setup.
 */

DUK_LOCAL void duk__call_env_setup(duk_hthread *thr, duk_hobject *func, duk_activation *act, duk_idx_t idx_args) {
	duk_hobject *env;

	DUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUNDFUNC(func));  /* bound function has already been resolved */

	if (DUK_LIKELY(func != NULL)) {
		if (DUK_LIKELY(DUK_HOBJECT_HAS_NEWENV(func))) {
			DUK_STATS_INC(thr->heap, stats_envrec_newenv);
			if (DUK_LIKELY(!DUK_HOBJECT_HAS_CREATEARGS(func))) {
				/* Use a new environment but there's no 'arguments' object;
				 * delayed environment initialization.  This is the most
				 * common case.
				 */
				DUK_ASSERT(act->lex_env == NULL);
				DUK_ASSERT(act->var_env == NULL);
			} else {
				/* Use a new environment and there's an 'arguments' object.
				 * We need to initialize it right now.
				 */

				/* third arg: absolute index (to entire valstack) of bottom_byteoff of new activation */
				env = duk_create_activation_environment_record(thr, func, act->bottom_byteoff);
				DUK_ASSERT(env != NULL);

				/* [ ... func this arg1 ... argN envobj ] */

				DUK_ASSERT(DUK_HOBJECT_HAS_CREATEARGS(func));
				duk__handle_createargs_for_call(thr, func, env, idx_args);

				/* [ ... func this arg1 ... argN envobj ] */

				act->lex_env = env;
				act->var_env = env;
				DUK_HOBJECT_INCREF(thr, env);
				DUK_HOBJECT_INCREF(thr, env);  /* XXX: incref by count (2) directly */
				duk_pop(thr);
			}
		} else {
			/* Use existing env (e.g. for non-strict eval); cannot have
			 * an own 'arguments' object (but can refer to an existing one).
			 */

			DUK_ASSERT(!DUK_HOBJECT_HAS_CREATEARGS(func));

			DUK_STATS_INC(thr->heap, stats_envrec_oldenv);
			duk__handle_oldenv_for_call(thr, func, act);

			DUK_ASSERT(act->lex_env != NULL);
			DUK_ASSERT(act->var_env != NULL);
		}
	} else {
		/* Lightfuncs are always native functions and have "newenv". */
		DUK_ASSERT(act->lex_env == NULL);
		DUK_ASSERT(act->var_env == NULL);
		DUK_STATS_INC(thr->heap, stats_envrec_newenv);
	}
}

/*
 *  Misc shared helpers.
 */

/* Check thread state, update current thread. */
DUK_LOCAL void duk__call_thread_state_update(duk_hthread *thr) {
	DUK_ASSERT(thr != NULL);

	if (DUK_LIKELY(thr == thr->heap->curr_thread)) {
		if (DUK_UNLIKELY(thr->state != DUK_HTHREAD_STATE_RUNNING)) {
			/* Should actually never happen, but check anyway. */
			goto thread_state_error;
		}
	} else {
		DUK_ASSERT(thr->heap->curr_thread == NULL ||
		           thr->heap->curr_thread->state == DUK_HTHREAD_STATE_RUNNING);
		if (DUK_UNLIKELY(thr->state != DUK_HTHREAD_STATE_INACTIVE)) {
			goto thread_state_error;
		}
		DUK_HEAP_SWITCH_THREAD(thr->heap, thr);
		thr->state = DUK_HTHREAD_STATE_RUNNING;

		/* Multiple threads may be simultaneously in the RUNNING
		 * state, but not in the same "resume chain".
		 */
	}
	DUK_ASSERT(thr->heap->curr_thread == thr);
	DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);
	return;

 thread_state_error:
	DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "invalid thread state (%ld)", (long) thr->state);
	DUK_WO_NORETURN(return;);
}

/*
 *  Main unprotected call handler, handles:
 *
 *    - All combinations of native/ECMAScript caller and native/ECMAScript
 *      target.
 *
 *    - Optimized ECMAScript-to-ECMAScript call where call handling only
 *      sets up a new duk_activation but reuses an existing bytecode executor
 *      (the caller) without native recursion.
 *
 *    - Tailcalls, where an activation is reused without increasing call
 *      stack (duk_activation) depth.
 *
 *    - Setup for an initial Duktape.Thread.resume().
 *
 *  The call handler doesn't provide any protection guarantees, protected calls
 *  must be implemented e.g. by wrapping the call in a duk_safe_call().
 *  Call setup may fail at any stage, even when the new activation is in
 *  place; the only guarantee is that the state is consistent for unwinding.
 */

DUK_LOCAL duk_int_t duk__handle_call_raw(duk_hthread *thr,
                                         duk_idx_t idx_func,
                                         duk_small_uint_t call_flags) {
#if defined(DUK_USE_ASSERTIONS)
	duk_activation *entry_act;
	duk_size_t entry_callstack_top;
#endif
	duk_size_t entry_valstack_bottom_byteoff;
	duk_size_t entry_valstack_end_byteoff;
	duk_int_t entry_call_recursion_depth;
	duk_hthread *entry_curr_thread;
	duk_uint_fast8_t entry_thread_state;
	duk_instr_t **entry_ptr_curr_pc;
	duk_idx_t idx_args;
	duk_idx_t nargs;            /* # argument registers target function wants (< 0 => "as is") */
	duk_idx_t nregs;            /* # total registers target function wants on entry (< 0 => "as is") */
	duk_size_t vs_min_bytes;    /* minimum value stack size (bytes) for handling call */
	duk_hobject *func;          /* 'func' on stack (borrowed reference) */
	duk_activation *act;
	duk_ret_t rc;
	duk_small_uint_t use_tailcall;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(thr->heap != NULL);
	/* Asserts for heap->curr_thread omitted: it may be NULL, 'thr', or
	 * any other thread (e.g. when heap thread is used to run finalizers).
	 */
	DUK_CTX_ASSERT_VALID(thr);
	DUK_ASSERT(duk_is_valid_index(thr, idx_func));
	DUK_ASSERT(idx_func >= 0);

	DUK_STATS_INC(thr->heap, stats_call_all);

	/* If a tail call:
	 *   - an ECMAScript activation must be on top of the callstack
	 *   - there cannot be any catch stack entries that would catch
	 *     a return
	 */
#if defined(DUK_USE_ASSERTIONS)
	if (call_flags & DUK_CALL_FLAG_TAILCALL) {
		duk_activation *tmp_act;
		duk_catcher *tmp_cat;

		DUK_ASSERT(thr->callstack_top >= 1);
		DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL);
		DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)));

		/* No entry in the catch stack which would actually catch a
		 * throw can refer to the callstack entry being reused.
		 * There *can* be catch stack entries referring to the current
		 * callstack entry as long as they don't catch (e.g. label sites).
		 */

		tmp_act = thr->callstack_curr;
		for (tmp_cat = tmp_act->cat; tmp_cat != NULL; tmp_cat = tmp_cat->parent) {
			DUK_ASSERT(DUK_CAT_GET_TYPE(tmp_cat) == DUK_CAT_TYPE_LABEL); /* a non-catching entry */
		}
	}
#endif  /* DUK_USE_ASSERTIONS */

	/*
	 *  Store entry state.
	 */

#if defined(DUK_USE_ASSERTIONS)
	entry_act = thr->callstack_curr;
	entry_callstack_top = thr->callstack_top;
#endif
	entry_valstack_bottom_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack);
	entry_valstack_end_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack);
	entry_call_recursion_depth = thr->heap->call_recursion_depth;
	entry_curr_thread = thr->heap->curr_thread;  /* may be NULL if first call */
	entry_thread_state = thr->state;
	entry_ptr_curr_pc = thr->ptr_curr_pc;  /* may be NULL */

	/* If thr->ptr_curr_pc is set, sync curr_pc to act->pc.  Then NULL
	 * thr->ptr_curr_pc so that it's not accidentally used with an incorrect
	 * activation when side effects occur.
	 */
	duk_hthread_sync_and_null_currpc(thr);
	DUK_ASSERT(thr->ptr_curr_pc == NULL);

	DUK_DD(DUK_DDPRINT("duk__handle_call_raw: thr=%p, idx_func=%ld, "
	                   "call_flags=0x%08lx (constructor=%ld), "
	                   "valstack_top=%ld, idx_func=%ld, idx_args=%ld, rec_depth=%ld/%ld, "
	                   "entry_valstack_bottom_byteoff=%ld, entry_valstack_end_byteoff=%ld, "
	                   "entry_call_recursion_depth=%ld, "
	                   "entry_curr_thread=%p, entry_thread_state=%ld",
	                   (void *) thr,
	                   (long) idx_func,
	                   (unsigned long) call_flags,
	                   (long) ((call_flags & DUK_CALL_FLAG_CONSTRUCT) != 0 ? 1 : 0),
	                   (long) duk_get_top(thr),
	                   (long) idx_func,
	                   (long) (idx_func + 2),
	                   (long) thr->heap->call_recursion_depth,
	                   (long) thr->heap->call_recursion_limit,
	                   (long) entry_valstack_bottom_byteoff,
	                   (long) entry_valstack_end_byteoff,
	                   (long) entry_call_recursion_depth,
	                   (void *) entry_curr_thread,
	                   (long) entry_thread_state));

	/*
	 *  Thread state check and book-keeping.
	 */

	duk__call_thread_state_update(thr);

	/*
	 *  Increase call recursion depth as early as possible so that if we
	 *  enter a recursive call for any reason there's a backstop to native
	 *  recursion.  This can happen e.g. for almost any property read
	 *  because it may cause a getter call or a Proxy trap (GC and finalizers
	 *  are not an issue because they are not recursive).  If we end up
	 *  doing an Ecma-to-Ecma call, revert the increase.  (See GH-2032.)
	 *
	 *  For similar reasons, ensure there is a known value stack spare
	 *  even before we actually prepare the value stack for the target
	 *  function.  If this isn't done, early recursion may consume the
	 *  value stack space.
	 *
	 *  XXX: Should bump yield preventcount early, for the same reason.
	 */

	duk__call_c_recursion_limit_check(thr);
	thr->heap->call_recursion_depth++;
	duk_require_stack(thr, DUK__CALL_HANDLING_REQUIRE_STACK);

	/*
	 *  Resolve final target function; handle bound functions and special
	 *  functions like .call() and .apply().  Also figure out the effective
	 *  'this' binding, which replaces the current value at idx_func + 1.
	 */

	if (DUK_LIKELY(duk__resolve_target_fastpath_check(thr, idx_func, &func, call_flags) != 0U)) {
		DUK_DDD(DUK_DDDPRINT("fast path target resolve"));
	} else {
		DUK_DDD(DUK_DDDPRINT("slow path target resolve"));
		func = duk__resolve_target_func_and_this_binding(thr, idx_func, &call_flags);
	}
	DUK_ASSERT(duk_get_top(thr) - idx_func >= 2);  /* at least func and this present */

	DUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUNDFUNC(func));
	DUK_ASSERT(func == NULL || (DUK_HOBJECT_IS_COMPFUNC(func) ||
	                            DUK_HOBJECT_IS_NATFUNC(func)));

	/* [ ... func this arg1 ... argN ] */

	/*
	 *  Setup a preliminary activation and figure out nargs/nregs and
	 *  value stack minimum size.
	 *
	 *  Don't touch valstack_bottom or valstack_top yet so that Duktape API
	 *  calls work normally.
	 *
	 *  Because 'act' is not zeroed, all fields must be filled in.
	 */

	/* Should not be necessary, but initialize to silence warnings. */
	act = NULL;
	nargs = 0;
	nregs = 0;
	vs_min_bytes = 0;

#if defined(DUK_USE_TAILCALL)
	use_tailcall = (call_flags & DUK_CALL_FLAG_TAILCALL);
	if (use_tailcall) {
		use_tailcall = duk__call_setup_act_attempt_tailcall(thr,
		                                                    call_flags,
		                                                    idx_func,
		                                                    func,
		                                                    entry_valstack_bottom_byteoff,
		                                                    entry_valstack_end_byteoff,
		                                                    &nargs,
		                                                    &nregs,
		                                                    &vs_min_bytes,
		                                                    &act);
	}
#else
	DUK_ASSERT((call_flags & DUK_CALL_FLAG_TAILCALL) == 0);  /* compiler ensures this */
	use_tailcall = 0;
#endif

	if (use_tailcall) {
		idx_args = 0;
		DUK_STATS_INC(thr->heap, stats_call_tailcall);
	} else {
		duk__call_setup_act_not_tailcall(thr,
		                                 call_flags,
		                                 idx_func,
		                                 func,
		                                 entry_valstack_bottom_byteoff,
		                                 entry_valstack_end_byteoff,
		                                 &nargs,
		                                 &nregs,
		                                 &vs_min_bytes,
		                                 &act);
		idx_args = idx_func + 2;
	}
	/* After this point idx_func is no longer valid for tailcalls. */

	DUK_ASSERT(act != NULL);

	/* [ ... func this arg1 ... argN ] */

	/*
	 *  Environment record creation and 'arguments' object creation.
	 *  Named function expression name binding is handled by the
	 *  compiler; the compiled function's parent env will contain
	 *  the (immutable) binding already.
	 *
	 *  This handling is now identical for C and ECMAScript functions.
	 *  C functions always have the 'NEWENV' flag set, so their
	 *  environment record initialization is delayed (which is good).
	 *
	 *  Delayed creation (on demand) is handled in duk_js_var.c.
	 */

	duk__call_env_setup(thr, func, act, idx_args);

	/* [ ... func this arg1 ... argN ] */

	/*
	 *  Setup value stack: clamp to 'nargs', fill up to 'nregs',
	 *  ensure value stack size matches target requirements, and
	 *  switch value stack bottom.  Valstack top is kept.
	 *
	 *  Value stack can only grow here.
	 */

	duk_valstack_grow_check_throw(thr, vs_min_bytes);
	act->reserve_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack);

	if (use_tailcall) {
		DUK_ASSERT(nregs >= 0);
		DUK_ASSERT(nregs >= nargs);
		duk_set_top_and_wipe(thr, nregs, nargs);
	} else {
		if (nregs >= 0) {
			DUK_ASSERT(nregs >= nargs);
			duk_set_top_and_wipe(thr, idx_func + 2 + nregs, idx_func + 2 + nargs);
		} else {
			;
		}
		thr->valstack_bottom = thr->valstack_bottom + idx_func + 2;
	}
	DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
	DUK_ASSERT(thr->valstack_end >= thr->valstack_top);

	/*
	 *  Make the actual call.  For Ecma-to-Ecma calls detect that
	 *  setup is complete, then return with a status code that allows
	 *  the caller to reuse the running executor.
	 */

	if (func != NULL && DUK_HOBJECT_IS_COMPFUNC(func)) {
		/*
		 *  ECMAScript call.
		 */

		DUK_ASSERT(func != NULL);
		DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(func));
		act->curr_pc = DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, (duk_hcompfunc *) func);

		if (call_flags & DUK_CALL_FLAG_ALLOW_ECMATOECMA) {
			DUK_DD(DUK_DDPRINT("avoid native call, use existing executor"));
			DUK_STATS_INC(thr->heap, stats_call_ecmatoecma);
			DUK_ASSERT((act->flags & DUK_ACT_FLAG_PREVENT_YIELD) == 0);
			DUK_REFZERO_CHECK_FAST(thr);
			DUK_ASSERT(thr->ptr_curr_pc == NULL);
			thr->heap->call_recursion_depth--;  /* No recursion increase for this case. */
			return 1;  /* 1=reuse executor */
		}
		DUK_ASSERT(use_tailcall == 0);

		/* duk_hthread_activation_unwind_norz() will decrease this on unwind */
		DUK_ASSERT((act->flags & DUK_ACT_FLAG_PREVENT_YIELD) == 0);
		act->flags |= DUK_ACT_FLAG_PREVENT_YIELD;
		thr->callstack_preventcount++;

		/* [ ... func this | arg1 ... argN ] ('this' must precede new bottom) */

		/*
		 *  Bytecode executor call.
		 *
		 *  Execute bytecode, handling any recursive function calls and
		 *  thread resumptions.  Returns when execution would return from
		 *  the entry level activation.  When the executor returns, a
		 *  single return value is left on the stack top.
		 *
		 *  The only possible longjmp() is an error (DUK_LJ_TYPE_THROW),
		 *  other types are handled internally by the executor.
		 */

		/* thr->ptr_curr_pc is set by bytecode executor early on entry */
		DUK_ASSERT(thr->ptr_curr_pc == NULL);
		DUK_DDD(DUK_DDDPRINT("entering bytecode execution"));
		duk_js_execute_bytecode(thr);
		DUK_DDD(DUK_DDDPRINT("returned from bytecode execution"));
	} else {
		/*
		 *  Native call.
		 */

		DUK_ASSERT(func == NULL || ((duk_hnatfunc *) func)->func != NULL);
		DUK_ASSERT(use_tailcall == 0);

		/* [ ... func this | arg1 ... argN ] ('this' must precede new bottom) */

		/* duk_hthread_activation_unwind_norz() will decrease this on unwind */
		DUK_ASSERT((act->flags & DUK_ACT_FLAG_PREVENT_YIELD) == 0);
		act->flags |= DUK_ACT_FLAG_PREVENT_YIELD;
		thr->callstack_preventcount++;

		/* For native calls must be NULL so we don't sync back */
		DUK_ASSERT(thr->ptr_curr_pc == NULL);

		/* XXX: native funcptr could come out of call setup. */
		if (func) {
			rc = ((duk_hnatfunc *) func)->func(thr);
		} else {
			duk_tval *tv_func;
			duk_c_function funcptr;

			tv_func = &act->tv_func;
			DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv_func));
			funcptr = DUK_TVAL_GET_LIGHTFUNC_FUNCPTR(tv_func);
			rc = funcptr(thr);
		}

		/* Automatic error throwing, retval check. */

		if (rc == 0) {
			DUK_ASSERT(thr->valstack < thr->valstack_end);
			DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top));
			thr->valstack_top++;
		} else if (rc == 1) {
			;
		} else if (rc < 0) {
			duk_error_throw_from_negative_rc(thr, rc);
			DUK_WO_NORETURN(return 0;);
		} else {
			DUK_ERROR_TYPE(thr, DUK_STR_INVALID_CFUNC_RC);
			DUK_WO_NORETURN(return 0;);
		}
	}
	DUK_ASSERT(thr->ptr_curr_pc == NULL);
	DUK_ASSERT(use_tailcall == 0);

	/*
	 *  Constructor call post processing.
	 */

#if defined(DUK_USE_ES6_PROXY)
	if (call_flags & (DUK_CALL_FLAG_CONSTRUCT | DUK_CALL_FLAG_CONSTRUCT_PROXY)) {
		duk_call_construct_postprocess(thr, call_flags & DUK_CALL_FLAG_CONSTRUCT_PROXY);
	}
#else
	if (call_flags & DUK_CALL_FLAG_CONSTRUCT) {
		duk_call_construct_postprocess(thr, 0);
	}
#endif

	/*
	 *  Unwind, restore valstack bottom and other book-keeping.
	 */

	DUK_ASSERT(thr->callstack_curr != NULL);
	DUK_ASSERT(thr->callstack_curr->parent == entry_act);
	DUK_ASSERT(thr->callstack_top == entry_callstack_top + 1);
	duk_hthread_activation_unwind_norz(thr);
	DUK_ASSERT(thr->callstack_curr == entry_act);
	DUK_ASSERT(thr->callstack_top == entry_callstack_top);

	thr->valstack_bottom = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + entry_valstack_bottom_byteoff);
	/* keep current valstack_top */
	DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
	DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
	DUK_ASSERT(thr->valstack_top - thr->valstack_bottom >= idx_func + 1);

	/* Return value handling. */

	/* [ ... func this (crud) retval ] */

	{
		duk_tval *tv_ret;
		duk_tval *tv_funret;

		tv_ret = thr->valstack_bottom + idx_func;
		tv_funret = thr->valstack_top - 1;
#if defined(DUK_USE_FASTINT)
		/* Explicit check for fastint downgrade. */
		DUK_TVAL_CHKFAST_INPLACE_FAST(tv_funret);
#endif
		DUK_TVAL_SET_TVAL_UPDREF(thr, tv_ret, tv_funret);  /* side effects */
	}

	duk_set_top_unsafe(thr, idx_func + 1);

	/* [ ... retval ] */

	/* Restore caller's value stack reserve (cannot fail). */
	DUK_ASSERT((duk_uint8_t *) thr->valstack + entry_valstack_end_byteoff >= (duk_uint8_t *) thr->valstack_top);
	DUK_ASSERT((duk_uint8_t *) thr->valstack + entry_valstack_end_byteoff <= (duk_uint8_t *) thr->valstack_alloc_end);
	thr->valstack_end = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + entry_valstack_end_byteoff);

	/* XXX: Trial value stack shrink would be OK here, but we'd need
	 * to prevent side effects of the potential realloc.
	 */

	/* Restore entry thread executor curr_pc stack frame pointer. */
	thr->ptr_curr_pc = entry_ptr_curr_pc;

	DUK_HEAP_SWITCH_THREAD(thr->heap, entry_curr_thread);  /* may be NULL */
	thr->state = (duk_uint8_t) entry_thread_state;

	/* Disabled assert: triggered with some torture tests. */
#if 0
	DUK_ASSERT((thr->state == DUK_HTHREAD_STATE_INACTIVE && thr->heap->curr_thread == NULL) ||  /* first call */
	           (thr->state == DUK_HTHREAD_STATE_INACTIVE && thr->heap->curr_thread != NULL) ||  /* other call */
	           (thr->state == DUK_HTHREAD_STATE_RUNNING && thr->heap->curr_thread == thr));     /* current thread */
#endif

	thr->heap->call_recursion_depth = entry_call_recursion_depth;

	/* If the debugger is active we need to force an interrupt so that
	 * debugger breakpoints are rechecked.  This is important for function
	 * calls caused by side effects (e.g. when doing a DUK_OP_GETPROP), see
	 * GH-303.  Only needed for success path, error path always causes a
	 * breakpoint recheck in the executor.  It would be enough to set this
	 * only when returning to an ECMAScript activation, but setting the flag
	 * on every return should have no ill effect.
	 */
#if defined(DUK_USE_DEBUGGER_SUPPORT)
	if (duk_debug_is_attached(thr->heap)) {
		DUK_DD(DUK_DDPRINT("returning with debugger enabled, force interrupt"));
		DUK_ASSERT(thr->interrupt_counter <= thr->interrupt_init);
		thr->interrupt_init -= thr->interrupt_counter;
		thr->interrupt_counter = 0;
		thr->heap->dbg_force_restart = 1;
	}
#endif

#if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
	duk__interrupt_fixup(thr, entry_curr_thread);
#endif

	/* Restored by success path. */
	DUK_ASSERT(thr->heap->call_recursion_depth == entry_call_recursion_depth);
	DUK_ASSERT(thr->ptr_curr_pc == entry_ptr_curr_pc);
	DUK_ASSERT_LJSTATE_UNSET(thr->heap);

	DUK_REFZERO_CHECK_FAST(thr);

	return 0;  /* 0=call handled inline */
}

DUK_INTERNAL duk_int_t duk_handle_call_unprotected_nargs(duk_hthread *thr,
                                                         duk_idx_t nargs,
                                                         duk_small_uint_t call_flags) {
	duk_idx_t idx_func;
	DUK_ASSERT(duk_get_top(thr) >= nargs + 2);
	idx_func = duk_get_top(thr) - (nargs + 2);
	DUK_ASSERT(idx_func >= 0);
	return duk_handle_call_unprotected(thr, idx_func, call_flags);
}

DUK_INTERNAL duk_int_t duk_handle_call_unprotected(duk_hthread *thr,
                                                   duk_idx_t idx_func,
                                                   duk_small_uint_t call_flags) {
	DUK_ASSERT(duk_is_valid_index(thr, idx_func));
	DUK_ASSERT(idx_func >= 0);
	return duk__handle_call_raw(thr, idx_func, call_flags);
}

/*
 *  duk_handle_safe_call(): make a "C protected call" within the
 *  current activation.
 *
 *  The allowed thread states for making a call are the same as for
 *  duk_handle_call_protected().
 *
 *  Even though this call is protected, errors are thrown for insane arguments
 *  and may result in a fatal error unless there's another protected call which
 *  catches such errors.
 *
 *  The error handling path should be error free, even for out-of-memory
 *  errors, to ensure safe sandboxing.  (As of Duktape 2.2.0 this is not
 *  yet the case for environment closing which may run out of memory, see
 *  XXX notes below.)
 */

DUK_LOCAL void duk__handle_safe_call_inner(duk_hthread *thr,
                                           duk_safe_call_function func,
                                           void *udata,
#if defined(DUK_USE_ASSERTIONS)
                                           duk_size_t entry_valstack_bottom_byteoff,
                                           duk_size_t entry_callstack_top,
#endif
                                           duk_hthread *entry_curr_thread,
                                           duk_uint_fast8_t entry_thread_state,
                                           duk_idx_t idx_retbase,
                                           duk_idx_t num_stack_rets) {
	duk_ret_t rc;

	DUK_ASSERT(thr != NULL);
	DUK_CTX_ASSERT_VALID(thr);

	/*
	 *  Thread state check and book-keeping.
	 */

	duk__call_thread_state_update(thr);

	/*
	 *  Recursion limit check.
	 */

	duk__call_c_recursion_limit_check(thr);
	thr->heap->call_recursion_depth++;

	/*
	 *  Make the C call.
	 */

	rc = func(thr, udata);

	DUK_DDD(DUK_DDDPRINT("safe_call, func rc=%ld", (long) rc));

	/*
	 *  Valstack manipulation for results.
	 */

	/* we're running inside the caller's activation, so no change in call/catch stack or valstack bottom */
	DUK_ASSERT(thr->callstack_top == entry_callstack_top);
	DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
	DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack) == entry_valstack_bottom_byteoff);
	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
	DUK_ASSERT(thr->valstack_end >= thr->valstack_top);

	if (DUK_UNLIKELY(rc < 0)) {
		duk_error_throw_from_negative_rc(thr, rc);
		DUK_WO_NORETURN(return;);
	}
	DUK_ASSERT(rc >= 0);

	duk__safe_call_adjust_valstack(thr, idx_retbase, num_stack_rets, rc);  /* throws for insane rc */

	DUK_HEAP_SWITCH_THREAD(thr->heap, entry_curr_thread);  /* may be NULL */
	thr->state = (duk_uint8_t) entry_thread_state;
}

DUK_LOCAL void duk__handle_safe_call_error(duk_hthread *thr,
                                           duk_activation *entry_act,
#if defined(DUK_USE_ASSERTIONS)
                                           duk_size_t entry_callstack_top,
#endif
                                           duk_hthread *entry_curr_thread,
                                           duk_uint_fast8_t entry_thread_state,
                                           duk_idx_t idx_retbase,
                                           duk_idx_t num_stack_rets,
                                           duk_size_t entry_valstack_bottom_byteoff,
                                           duk_jmpbuf *old_jmpbuf_ptr) {
	DUK_ASSERT(thr != NULL);
	DUK_CTX_ASSERT_VALID(thr);

	/*
	 *  Error during call.  The error value is at heap->lj.value1.
	 *
	 *  The very first thing we do is restore the previous setjmp catcher.
	 *  This means that any error in error handling will propagate outwards
	 *  instead of causing a setjmp() re-entry above.
	 */

	DUK_DDD(DUK_DDDPRINT("error caught during protected duk_handle_safe_call()"));

	/* Other longjmp types are handled by executor before propagating
	 * the error here.
	 */
	DUK_ASSERT(thr->heap->lj.type == DUK_LJ_TYPE_THROW);
	DUK_ASSERT_LJSTATE_SET(thr->heap);

	/* Either pointer may be NULL (at entry), so don't assert. */
	thr->heap->lj.jmpbuf_ptr = old_jmpbuf_ptr;

	/* XXX: callstack unwind may now throw an error when closing
	 * scopes; this is a sandboxing issue, described in:
	 * https://github.com/svaarala/duktape/issues/476
	 */
	/* XXX: "unwind to" primitive? */

	DUK_ASSERT(thr->callstack_top >= entry_callstack_top);
	while (thr->callstack_curr != entry_act) {
		DUK_ASSERT(thr->callstack_curr != NULL);
		duk_hthread_activation_unwind_norz(thr);
	}
	DUK_ASSERT(thr->callstack_top == entry_callstack_top);

	/* Switch active thread before any side effects to avoid a
	 * dangling curr_thread pointer.
	 */
	DUK_HEAP_SWITCH_THREAD(thr->heap, entry_curr_thread);  /* may be NULL */
	thr->state = (duk_uint8_t) entry_thread_state;

	DUK_ASSERT(thr->heap->curr_thread == entry_curr_thread);
	DUK_ASSERT(thr->state == entry_thread_state);

	/* Restore valstack bottom. */
	thr->valstack_bottom = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + entry_valstack_bottom_byteoff);

	/* [ ... | (crud) ] */

	/* XXX: ensure space in valstack (now relies on internal reserve)? */
	duk_push_tval(thr, &thr->heap->lj.value1);

	/* [ ... | (crud) errobj ] */

	DUK_ASSERT(duk_get_top(thr) >= 1);  /* at least errobj must be on stack */

	duk__safe_call_adjust_valstack(thr, idx_retbase, num_stack_rets, 1);  /* 1 = num actual 'return values' */

	/* [ ... | ] or [ ... | errobj (M * undefined)] where M = num_stack_rets - 1 */

	/* Reset longjmp state. */
	thr->heap->lj.type = DUK_LJ_TYPE_UNKNOWN;
	thr->heap->lj.iserror = 0;
	DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ(thr, &thr->heap->lj.value1);
	DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ(thr, &thr->heap->lj.value2);

	/* Error handling complete, remove side effect protections.  Caller
	 * will process pending finalizers.
	 */
#if defined(DUK_USE_ASSERTIONS)
	DUK_ASSERT(thr->heap->error_not_allowed == 1);
	thr->heap->error_not_allowed = 0;
#endif
	DUK_ASSERT(thr->heap->pf_prevent_count > 0);
	thr->heap->pf_prevent_count--;
	DUK_DD(DUK_DDPRINT("safe call error handled, pf_prevent_count updated to %ld", (long) thr->heap->pf_prevent_count));

	/* thr->ptr_curr_pc is restored by
	 * duk__handle_safe_call_shared_unwind() which is also used for
	 * success path.
	 */
}

DUK_LOCAL void duk__handle_safe_call_shared_unwind(duk_hthread *thr,
                                                   duk_idx_t idx_retbase,
                                                   duk_idx_t num_stack_rets,
#if defined(DUK_USE_ASSERTIONS)
                                                   duk_size_t entry_callstack_top,
#endif
                                                   duk_int_t entry_call_recursion_depth,
                                                   duk_hthread *entry_curr_thread,
                                                   duk_instr_t **entry_ptr_curr_pc) {
	DUK_ASSERT(thr != NULL);
	DUK_CTX_ASSERT_VALID(thr);
	DUK_UNREF(idx_retbase);
	DUK_UNREF(num_stack_rets);
	DUK_UNREF(entry_curr_thread);

	DUK_ASSERT(thr->callstack_top == entry_callstack_top);

	/* Restore entry thread executor curr_pc stack frame pointer.
	 * XXX: would be enough to do in error path only, should nest
	 * cleanly in success path.
	 */
	thr->ptr_curr_pc = entry_ptr_curr_pc;

	thr->heap->call_recursion_depth = entry_call_recursion_depth;

	/* stack discipline consistency check */
	DUK_ASSERT(duk_get_top(thr) == idx_retbase + num_stack_rets);

	/* A debugger forced interrupt check is not needed here, as
	 * problematic safe calls are not caused by side effects.
	 */

#if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
	duk__interrupt_fixup(thr, entry_curr_thread);
#endif
}

DUK_INTERNAL duk_int_t duk_handle_safe_call(duk_hthread *thr,
                                            duk_safe_call_function func,
                                            void *udata,
                                            duk_idx_t num_stack_args,
                                            duk_idx_t num_stack_rets) {
	duk_activation *entry_act;
	duk_size_t entry_valstack_bottom_byteoff;
#if defined(DUK_USE_ASSERTIONS)
	duk_size_t entry_valstack_end_byteoff;
	duk_size_t entry_callstack_top;
	duk_size_t entry_callstack_preventcount;
#endif
	duk_int_t entry_call_recursion_depth;
	duk_hthread *entry_curr_thread;
	duk_uint_fast8_t entry_thread_state;
	duk_instr_t **entry_ptr_curr_pc;
	duk_jmpbuf *old_jmpbuf_ptr = NULL;
	duk_jmpbuf our_jmpbuf;
	duk_idx_t idx_retbase;
	duk_int_t retval;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(duk_get_top(thr) >= num_stack_args);  /* Caller ensures. */

	DUK_STATS_INC(thr->heap, stats_safecall_all);

	/* Value stack reserve handling: safe call assumes caller has reserved
	 * space for nrets (assuming optimal unwind processing).  Value stack
	 * reserve is not stored/restored as for normal calls because a safe
	 * call conceptually happens in the same activation.
	 */

	/* Careful with indices like '-x'; if 'x' is zero, it refers to bottom */
	entry_act = thr->callstack_curr;
	entry_valstack_bottom_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack);
#if defined(DUK_USE_ASSERTIONS)
	entry_valstack_end_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack);
	entry_callstack_top = thr->callstack_top;
	entry_callstack_preventcount = thr->callstack_preventcount;
#endif
	entry_call_recursion_depth = thr->heap->call_recursion_depth;
	entry_curr_thread = thr->heap->curr_thread;  /* may be NULL if first call */
	entry_thread_state = thr->state;
	entry_ptr_curr_pc = thr->ptr_curr_pc;  /* may be NULL */
	idx_retbase = duk_get_top(thr) - num_stack_args;  /* not a valid stack index if num_stack_args == 0 */
	DUK_ASSERT(idx_retbase >= 0);

	DUK_ASSERT((duk_idx_t) (thr->valstack_top - thr->valstack_bottom) >= num_stack_args);  /* Caller ensures. */
	DUK_ASSERT((duk_idx_t) (thr->valstack_end - (thr->valstack_bottom + idx_retbase)) >= num_stack_rets);  /* Caller ensures. */

	/* Cannot portably debug print a function pointer, hence 'func' not printed! */
	DUK_DD(DUK_DDPRINT("duk_handle_safe_call: thr=%p, num_stack_args=%ld, num_stack_rets=%ld, "
	                   "valstack_top=%ld, idx_retbase=%ld, rec_depth=%ld/%ld, "
	                   "entry_act=%p, entry_valstack_bottom_byteoff=%ld, entry_call_recursion_depth=%ld, "
	                   "entry_curr_thread=%p, entry_thread_state=%ld",
	                   (void *) thr,
	                   (long) num_stack_args,
	                   (long) num_stack_rets,
	                   (long) duk_get_top(thr),
	                   (long) idx_retbase,
	                   (long) thr->heap->call_recursion_depth,
	                   (long) thr->heap->call_recursion_limit,
	                   (void *) entry_act,
	                   (long) entry_valstack_bottom_byteoff,
	                   (long) entry_call_recursion_depth,
	                   (void *) entry_curr_thread,
	                   (long) entry_thread_state));

	/* Setjmp catchpoint setup. */
	old_jmpbuf_ptr = thr->heap->lj.jmpbuf_ptr;
	thr->heap->lj.jmpbuf_ptr = &our_jmpbuf;

	/* Prevent yields for the duration of the safe call.  This only
	 * matters if the executor makes safe calls to functions that
	 * yield, this doesn't currently happen.
	 */
	thr->callstack_preventcount++;

#if defined(DUK_USE_CPP_EXCEPTIONS)
	try {
#else
	DUK_ASSERT(thr->heap->lj.jmpbuf_ptr == &our_jmpbuf);
	if (DUK_SETJMP(our_jmpbuf.jb) == 0) {
		/* Success path. */
#endif
		DUK_DDD(DUK_DDDPRINT("safe_call setjmp catchpoint setup complete"));

		duk__handle_safe_call_inner(thr,
		                            func,
		                            udata,
#if defined(DUK_USE_ASSERTIONS)
		                            entry_valstack_bottom_byteoff,
		                            entry_callstack_top,
#endif
		                            entry_curr_thread,
		                            entry_thread_state,
		                            idx_retbase,
		                            num_stack_rets);

		DUK_STATS_INC(thr->heap, stats_safecall_nothrow);

		/* Either pointer may be NULL (at entry), so don't assert */
		thr->heap->lj.jmpbuf_ptr = old_jmpbuf_ptr;

		/* If calls happen inside the safe call, these are restored by
		 * whatever calls are made.  Reserve cannot decrease.
		 */
		DUK_ASSERT(thr->callstack_curr == entry_act);
		DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >= entry_valstack_end_byteoff);

		retval = DUK_EXEC_SUCCESS;
#if defined(DUK_USE_CPP_EXCEPTIONS)
	} catch (duk_internal_exception &exc) {
		DUK_UNREF(exc);
#else
	} else {
		/* Error path. */
#endif
		DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >= entry_valstack_end_byteoff);

		DUK_STATS_INC(thr->heap, stats_safecall_throw);

		duk__handle_safe_call_error(thr,
		                            entry_act,
#if defined(DUK_USE_ASSERTIONS)
		                            entry_callstack_top,
#endif
		                            entry_curr_thread,
		                            entry_thread_state,
		                            idx_retbase,
		                            num_stack_rets,
		                            entry_valstack_bottom_byteoff,
		                            old_jmpbuf_ptr);

		retval = DUK_EXEC_ERROR;
	}
#if defined(DUK_USE_CPP_EXCEPTIONS)
	catch (duk_fatal_exception &exc) {
		DUK_D(DUK_DPRINT("rethrow duk_fatal_exception"));
		DUK_UNREF(exc);
		throw;
	} catch (std::exception &exc) {
		const char *what = exc.what();
		DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >= entry_valstack_end_byteoff);
		DUK_STATS_INC(thr->heap, stats_safecall_throw);
		if (!what) {
			what = "unknown";
		}
		DUK_D(DUK_DPRINT("unexpected c++ std::exception (perhaps thrown by user code)"));
		try {
			DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "caught invalid c++ std::exception '%s' (perhaps thrown by user code)", what);
			DUK_WO_NORETURN(return 0;);
		} catch (duk_internal_exception exc) {
			DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ std::exception"));
			DUK_UNREF(exc);
			duk__handle_safe_call_error(thr,
			                            entry_act,
#if defined(DUK_USE_ASSERTIONS)
			                            entry_callstack_top,
#endif
			                            entry_curr_thread,
			                            entry_thread_state,
			                            idx_retbase,
			                            num_stack_rets,
			                            entry_valstack_bottom_byteoff,
			                            old_jmpbuf_ptr);
			retval = DUK_EXEC_ERROR;
		}
	} catch (...) {
		DUK_D(DUK_DPRINT("unexpected c++ exception (perhaps thrown by user code)"));
		DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >= entry_valstack_end_byteoff);
		DUK_STATS_INC(thr->heap, stats_safecall_throw);
		try {
			DUK_ERROR_TYPE(thr, "caught invalid c++ exception (perhaps thrown by user code)");
			DUK_WO_NORETURN(return 0;);
		} catch (duk_internal_exception exc) {
			DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ exception"));
			DUK_UNREF(exc);
			duk__handle_safe_call_error(thr,
			                            entry_act,
#if defined(DUK_USE_ASSERTIONS)
			                            entry_callstack_top,
#endif
			                            entry_curr_thread,
			                            entry_thread_state,
			                            idx_retbase,
			                            num_stack_rets,
			                            entry_valstack_bottom_byteoff,
			                            old_jmpbuf_ptr);
			retval = DUK_EXEC_ERROR;
		}
	}
#endif

	DUK_ASSERT(thr->heap->lj.jmpbuf_ptr == old_jmpbuf_ptr);  /* success/error path both do this */

	DUK_ASSERT_LJSTATE_UNSET(thr->heap);

	DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >= entry_valstack_end_byteoff);
	duk__handle_safe_call_shared_unwind(thr,
	                                    idx_retbase,
	                                    num_stack_rets,
#if defined(DUK_USE_ASSERTIONS)
	                                    entry_callstack_top,
#endif
	                                    entry_call_recursion_depth,
	                                    entry_curr_thread,
	                                    entry_ptr_curr_pc);

	/* Restore preventcount. */
	thr->callstack_preventcount--;
	DUK_ASSERT(thr->callstack_preventcount == entry_callstack_preventcount);

	/* Final asserts. */
	DUK_ASSERT(thr->callstack_curr == entry_act);
	DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack) == entry_valstack_bottom_byteoff);
	DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >= entry_valstack_end_byteoff);
	DUK_ASSERT(thr->callstack_top == entry_callstack_top);
	DUK_ASSERT(thr->heap->call_recursion_depth == entry_call_recursion_depth);
	DUK_ASSERT(thr->heap->curr_thread == entry_curr_thread);
	DUK_ASSERT(thr->state == entry_thread_state);
	DUK_ASSERT(thr->ptr_curr_pc == entry_ptr_curr_pc);
	DUK_ASSERT(duk_get_top(thr) == idx_retbase + num_stack_rets);
	DUK_ASSERT_LJSTATE_UNSET(thr->heap);

	/* Pending side effects. */
	DUK_REFZERO_CHECK_FAST(thr);

	return retval;
}

/*
 *  Property-based call (foo.noSuch()) error setup: replace target function
 *  on stack top with a hidden Symbol tagged non-callable wrapper object
 *  holding the error.  The error gets thrown in call handling at the
 *  proper spot to follow ECMAScript semantics.
 */

#if defined(DUK_USE_VERBOSE_ERRORS)
DUK_INTERNAL DUK_NOINLINE DUK_COLD void duk_call_setup_propcall_error(duk_hthread *thr, duk_tval *tv_base, duk_tval *tv_key) {
	const char *str_targ, *str_key, *str_base;
	duk_idx_t entry_top;

	entry_top = duk_get_top(thr);

	/* [ <nargs> target ] */

	/* Must stabilize pointers first.  tv_targ is already on stack top. */
	duk_push_tval(thr, tv_base);
	duk_push_tval(thr, tv_key);

	DUK_GC_TORTURE(thr->heap);

	duk_push_bare_object(thr);

	/* [ <nargs> target base key {} ] */

	/* We only push a wrapped error, replacing the call target (at
	 * idx_func) with the error to ensure side effects come out
	 * correctly:
	 * - Property read
	 * - Call argument evaluation
	 * - Callability check and error thrown
	 *
	 * A hidden Symbol on the wrapper object pushed above is used by
	 * call handling to figure out the error is to be thrown as is.
	 * It is CRITICAL that the hidden Symbol can never occur on a
	 * user visible object that may get thrown.
	 */

#if defined(DUK_USE_PARANOID_ERRORS)
	str_targ = duk_get_type_name(thr, -4);
	str_key = duk_get_type_name(thr, -2);
	str_base = duk_get_type_name(thr, -3);
	duk_push_error_object(thr,
	                      DUK_ERR_TYPE_ERROR | DUK_ERRCODE_FLAG_NOBLAME_FILELINE,
	                      "%s not callable (property %s of %s)", str_targ, str_key, str_base);
	duk_xdef_prop_stridx(thr, -2, DUK_STRIDX_INT_TARGET, DUK_PROPDESC_FLAGS_NONE);  /* Marker property, reuse _Target. */
	/* [ <nargs> target base key { _Target: error } ] */
	duk_replace(thr, entry_top - 1);
#else
	str_targ = duk_push_string_readable(thr, -4);
	str_key = duk_push_string_readable(thr, -3);
	str_base = duk_push_string_readable(thr, -5);
	duk_push_error_object(thr,
	                      DUK_ERR_TYPE_ERROR | DUK_ERRCODE_FLAG_NOBLAME_FILELINE,
	                      "%s not callable (property %s of %s)", str_targ, str_key, str_base);
	/* [ <nargs> target base key {} str_targ str_key str_base error ] */
	duk_xdef_prop_stridx(thr, -5, DUK_STRIDX_INT_TARGET, DUK_PROPDESC_FLAGS_NONE);  /* Marker property, reuse _Target. */
	/* [ <nargs> target base key { _Target: error } str_targ str_key str_base ] */
	duk_swap(thr, -4, entry_top - 1);
	/* [ <nargs> { _Target: error } base key target str_targ str_key str_base ] */
#endif

	/* [ <nregs> { _Target: error } <variable> */
	duk_set_top(thr, entry_top);

	/* [ <nregs> { _Target: error } */
	DUK_ASSERT(!duk_is_callable(thr, -1));  /* Critical so that call handling will throw the error. */
}
#endif  /* DUK_USE_VERBOSE_ERRORS */

/* automatic undefs */
#undef DUK__AUGMENT_CALL_RELAX_COUNT
#undef DUK__CALL_HANDLING_REQUIRE_STACK
#line 1 "duk_js_compiler.c"
/*
 *  ECMAScript compiler.
 *
 *  Parses an input string and generates a function template result.
 *  Compilation may happen in multiple contexts (global code, eval
 *  code, function code).
 *
 *  The parser uses a traditional top-down recursive parsing for the
 *  statement level, and an operator precedence based top-down approach
 *  for the expression level.  The attempt is to minimize the C stack
 *  depth.  Bytecode is generated directly without an intermediate
 *  representation (tree), at the cost of needing two (and sometimes
 *  three) passes over each function.
 *
 *  The top-down recursive parser functions are named "duk__parse_XXX".
 *
 *  Recursion limits are in key functions to prevent arbitrary C recursion:
 *  function body parsing, statement parsing, and expression parsing.
 *
 *  See doc/compiler.rst for discussion on the design.
 *
 *  A few typing notes:
 *
 *    - duk_regconst_t: signed, highest bit set (< 0) means constant,
 *      some call sites use -1 for "none" (equivalent to constant 0x7fffffff)
 *    - PC values: duk_int_t, negative values used as markers
 */

/* #include duk_internal.h -> already included */

/* If highest bit of a register number is set, it refers to a constant instead.
 * When interpreted as a signed value, this means const values are always
 * negative (when interpreted as two's complement).  For example DUK__ISREG_TEMP()
 * uses this approach to avoid an explicit DUK__ISREG() check (the condition is
 * logically "'x' is a register AND 'x' >= temp_first").
 */
#define DUK__CONST_MARKER                   DUK_REGCONST_CONST_MARKER
#define DUK__REMOVECONST(x)                 ((x) & ~DUK__CONST_MARKER)
#define DUK__ISREG(x)                       ((x) >= 0)
#define DUK__ISCONST(x)                     ((x) < 0)
#define DUK__ISREG_TEMP(comp_ctx,x)         ((duk_int32_t) (x) >= (duk_int32_t) ((comp_ctx)->curr_func.temp_first))   /* Check for x >= temp_first && x >= 0 by comparing as signed. */
#define DUK__ISREG_NOTTEMP(comp_ctx,x)      ((duk_uint32_t) (x) < (duk_uint32_t) ((comp_ctx)->curr_func.temp_first))  /* Check for x >= 0 && x < temp_first by interpreting as unsigned. */
#define DUK__GETTEMP(comp_ctx)              ((comp_ctx)->curr_func.temp_next)
#define DUK__SETTEMP(comp_ctx,x)            ((comp_ctx)->curr_func.temp_next = (x))  /* dangerous: must only lower (temp_max not updated) */
#define DUK__SETTEMP_CHECKMAX(comp_ctx,x)   duk__settemp_checkmax((comp_ctx),(x))
#define DUK__ALLOCTEMP(comp_ctx)            duk__alloctemp((comp_ctx))
#define DUK__ALLOCTEMPS(comp_ctx,count)     duk__alloctemps((comp_ctx),(count))

/* Init value set size for array and object literals. */
#define DUK__MAX_ARRAY_INIT_VALUES        20
#define DUK__MAX_OBJECT_INIT_PAIRS        10

/* XXX: hack, remove when const lookup is not O(n) */
#define DUK__GETCONST_MAX_CONSTS_CHECK    256

/* These limits are based on bytecode limits.  Max temps is limited
 * by duk_hcompfunc nargs/nregs fields being 16 bits.
 */
#define DUK__MAX_CONSTS                   DUK_BC_BC_MAX
#define DUK__MAX_FUNCS                    DUK_BC_BC_MAX
#define DUK__MAX_TEMPS                    0xffffL

/* Initial bytecode size allocation. */
#if defined(DUK_USE_PREFER_SIZE)
#define DUK__BC_INITIAL_INSTS             16
#else
#define DUK__BC_INITIAL_INSTS             256
#endif

#define DUK__RECURSION_INCREASE(comp_ctx,thr)  do { \
		DUK_DDD(DUK_DDDPRINT("RECURSION INCREASE: %s:%ld", (const char *) DUK_FILE_MACRO, (long) DUK_LINE_MACRO)); \
		duk__comp_recursion_increase((comp_ctx)); \
	} while (0)

#define DUK__RECURSION_DECREASE(comp_ctx,thr)  do { \
		DUK_DDD(DUK_DDDPRINT("RECURSION DECREASE: %s:%ld", (const char *) DUK_FILE_MACRO, (long) DUK_LINE_MACRO)); \
		duk__comp_recursion_decrease((comp_ctx)); \
	} while (0)

/* Value stack slot limits: these are quite approximate right now, and
 * because they overlap in control flow, some could be eliminated.
 */
#define DUK__COMPILE_ENTRY_SLOTS          8
#define DUK__FUNCTION_INIT_REQUIRE_SLOTS  16
#define DUK__FUNCTION_BODY_REQUIRE_SLOTS  16
#define DUK__PARSE_STATEMENTS_SLOTS       16
#define DUK__PARSE_EXPR_SLOTS             16

/* Temporary structure used to pass a stack allocated region through
 * duk_safe_call().
 */
typedef struct {
	duk_small_uint_t flags;
	duk_compiler_ctx comp_ctx_alloc;
	duk_lexer_point lex_pt_alloc;
} duk__compiler_stkstate;

/*
 *  Prototypes
 */

/* lexing */
DUK_LOCAL_DECL void duk__advance_helper(duk_compiler_ctx *comp_ctx, duk_small_int_t expect);
DUK_LOCAL_DECL void duk__advance_expect(duk_compiler_ctx *comp_ctx, duk_small_int_t expect);
DUK_LOCAL_DECL void duk__advance(duk_compiler_ctx *ctx);

/* function helpers */
DUK_LOCAL_DECL void duk__init_func_valstack_slots(duk_compiler_ctx *comp_ctx);
DUK_LOCAL_DECL void duk__reset_func_for_pass2(duk_compiler_ctx *comp_ctx);
DUK_LOCAL_DECL void duk__init_varmap_and_prologue_for_pass2(duk_compiler_ctx *comp_ctx, duk_regconst_t *out_stmt_value_reg);
DUK_LOCAL_DECL void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx);
DUK_LOCAL_DECL duk_int_t duk__cleanup_varmap(duk_compiler_ctx *comp_ctx);

/* code emission */
DUK_LOCAL_DECL duk_int_t duk__get_current_pc(duk_compiler_ctx *comp_ctx);
DUK_LOCAL_DECL duk_compiler_instr *duk__get_instr_ptr(duk_compiler_ctx *comp_ctx, duk_int_t pc);
DUK_LOCAL_DECL void duk__emit(duk_compiler_ctx *comp_ctx, duk_instr_t ins);
DUK_LOCAL_DECL void duk__emit_op_only(duk_compiler_ctx *comp_ctx, duk_small_uint_t op);
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);
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);
DUK_LOCAL_DECL void duk__emit_b_c(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t b, duk_regconst_t c);
#if 0  /* unused */
DUK_LOCAL_DECL void duk__emit_a(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t a);
DUK_LOCAL_DECL void duk__emit_b(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t b);
#endif
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);
DUK_LOCAL_DECL void duk__emit_bc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op, duk_regconst_t bc);
DUK_LOCAL_DECL void duk__emit_abc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op, duk_regconst_t abc);
DUK_LOCAL_DECL void duk__emit_load_int32(duk_compiler_ctx *comp_ctx, duk_regconst_t reg, duk_int32_t val);
DUK_LOCAL_DECL void duk__emit_load_int32_noshuffle(duk_compiler_ctx *comp_ctx, duk_regconst_t reg, duk_int32_t val);
DUK_LOCAL_DECL void duk__emit_jump(duk_compiler_ctx *comp_ctx, duk_int_t target_pc);
DUK_LOCAL_DECL duk_int_t duk__emit_jump_empty(duk_compiler_ctx *comp_ctx);
DUK_LOCAL_DECL void duk__insert_jump_entry(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc);
DUK_LOCAL_DECL void duk__patch_jump(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc, duk_int_t target_pc);
DUK_LOCAL_DECL void duk__patch_jump_here(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc);
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);
DUK_LOCAL_DECL void duk__emit_if_false_skip(duk_compiler_ctx *comp_ctx, duk_regconst_t regconst);
DUK_LOCAL_DECL void duk__emit_if_true_skip(duk_compiler_ctx *comp_ctx, duk_regconst_t regconst);
DUK_LOCAL_DECL void duk__emit_invalid(duk_compiler_ctx *comp_ctx);

/* ivalue/ispec helpers */
DUK_LOCAL_DECL void duk__ivalue_regconst(duk_ivalue *x, duk_regconst_t regconst);
DUK_LOCAL_DECL void duk__ivalue_plain_fromstack(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
DUK_LOCAL_DECL void duk__ivalue_var_fromstack(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
DUK_LOCAL_DECL void duk__ivalue_var_hstring(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_hstring *h);
DUK_LOCAL_DECL void duk__copy_ispec(duk_compiler_ctx *comp_ctx, duk_ispec *src, duk_ispec *dst);
DUK_LOCAL_DECL void duk__copy_ivalue(duk_compiler_ctx *comp_ctx, duk_ivalue *src, duk_ivalue *dst);
DUK_LOCAL_DECL duk_regconst_t duk__alloctemps(duk_compiler_ctx *comp_ctx, duk_small_int_t num);
DUK_LOCAL_DECL duk_regconst_t duk__alloctemp(duk_compiler_ctx *comp_ctx);
DUK_LOCAL_DECL void duk__settemp_checkmax(duk_compiler_ctx *comp_ctx, duk_regconst_t temp_next);
DUK_LOCAL_DECL duk_regconst_t duk__getconst(duk_compiler_ctx *comp_ctx);
DUK_LOCAL_DECL
duk_regconst_t duk__ispec_toregconst_raw(duk_compiler_ctx *comp_ctx,
                                         duk_ispec *x,
                                         duk_regconst_t forced_reg,
                                         duk_small_uint_t flags);
DUK_LOCAL_DECL void duk__ispec_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ispec *x, duk_regconst_t forced_reg);
DUK_LOCAL_DECL void duk__ivalue_toplain_raw(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_regconst_t forced_reg);
DUK_LOCAL_DECL void duk__ivalue_toplain(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
DUK_LOCAL_DECL void duk__ivalue_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
DUK_LOCAL_DECL
duk_regconst_t duk__ivalue_toregconst_raw(duk_compiler_ctx *comp_ctx,
                                          duk_ivalue *x,
                                          duk_regconst_t forced_reg,
                                          duk_small_uint_t flags);
DUK_LOCAL_DECL duk_regconst_t duk__ivalue_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
#if 0  /* unused */
DUK_LOCAL_DECL duk_regconst_t duk__ivalue_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
#endif
DUK_LOCAL_DECL void duk__ivalue_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_int_t forced_reg);
DUK_LOCAL_DECL duk_regconst_t duk__ivalue_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
DUK_LOCAL_DECL duk_regconst_t duk__ivalue_totempconst(duk_compiler_ctx *comp_ctx, duk_ivalue *x);

/* identifier handling */
DUK_LOCAL_DECL duk_regconst_t duk__lookup_active_register_binding(duk_compiler_ctx *comp_ctx);
DUK_LOCAL_DECL duk_bool_t duk__lookup_lhs(duk_compiler_ctx *ctx, duk_regconst_t *out_reg_varbind, duk_regconst_t *out_rc_varname);

/* label handling */
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);
DUK_LOCAL_DECL void duk__update_label_flags(duk_compiler_ctx *comp_ctx, duk_int_t label_id, duk_small_uint_t flags);
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);
DUK_LOCAL_DECL void duk__reset_labels_to_length(duk_compiler_ctx *comp_ctx, duk_size_t len);

/* top-down expression parser */
DUK_LOCAL_DECL void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
DUK_LOCAL_DECL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_ivalue *res);
DUK_LOCAL_DECL duk_small_uint_t duk__expr_lbp(duk_compiler_ctx *comp_ctx);
DUK_LOCAL_DECL duk_bool_t duk__expr_is_empty(duk_compiler_ctx *comp_ctx);

/* exprtop is the top level variant which resets nud/led counts */
DUK_LOCAL_DECL void duk__expr(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
DUK_LOCAL_DECL void duk__exprtop(duk_compiler_ctx *ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);

/* convenience helpers */
#if 0  /* unused */
DUK_LOCAL_DECL duk_regconst_t duk__expr_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
#endif
#if 0  /* unused */
DUK_LOCAL_DECL duk_regconst_t duk__expr_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
#endif
DUK_LOCAL_DECL void duk__expr_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags, duk_regconst_t forced_reg);
DUK_LOCAL_DECL duk_regconst_t duk__expr_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
#if 0  /* unused */
DUK_LOCAL_DECL duk_regconst_t duk__expr_totempconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
#endif
DUK_LOCAL_DECL void duk__expr_toplain(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
DUK_LOCAL_DECL void duk__expr_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
DUK_LOCAL_DECL duk_regconst_t duk__exprtop_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
#if 0  /* unused */
DUK_LOCAL_DECL duk_regconst_t duk__exprtop_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
#endif
DUK_LOCAL_DECL void duk__exprtop_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags, duk_regconst_t forced_reg);
DUK_LOCAL_DECL duk_regconst_t duk__exprtop_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
#if 0  /* unused */
DUK_LOCAL_DECL void duk__exprtop_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
#endif

/* expression parsing helpers */
DUK_LOCAL_DECL duk_int_t duk__parse_arguments(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
DUK_LOCAL_DECL void duk__nud_array_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
DUK_LOCAL_DECL void duk__nud_object_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res);

/* statement parsing */
DUK_LOCAL_DECL void duk__parse_var_decl(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t expr_flags, duk_regconst_t *out_reg_varbind, duk_regconst_t *out_rc_varname);
DUK_LOCAL_DECL void duk__parse_var_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t expr_flags);
DUK_LOCAL_DECL void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site);
DUK_LOCAL_DECL void duk__parse_switch_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site);
DUK_LOCAL_DECL void duk__parse_if_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
DUK_LOCAL_DECL void duk__parse_do_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site);
DUK_LOCAL_DECL void duk__parse_while_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site);
DUK_LOCAL_DECL void duk__parse_break_or_continue_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
DUK_LOCAL_DECL void duk__parse_return_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
DUK_LOCAL_DECL void duk__parse_throw_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
DUK_LOCAL_DECL void duk__parse_try_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
DUK_LOCAL_DECL void duk__parse_with_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
DUK_LOCAL_DECL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_bool_t allow_source_elem);
DUK_LOCAL_DECL duk_int_t duk__stmt_label_site(duk_compiler_ctx *comp_ctx, duk_int_t label_id);
DUK_LOCAL_DECL void duk__parse_stmts(duk_compiler_ctx *comp_ctx, duk_bool_t allow_source_elem, duk_bool_t expect_eof, duk_bool_t regexp_after);

DUK_LOCAL_DECL void duk__parse_func_body(duk_compiler_ctx *comp_ctx, duk_bool_t expect_eof, duk_bool_t implicit_return_value, duk_bool_t regexp_after, duk_small_int_t expect_token);
DUK_LOCAL_DECL void duk__parse_func_formals(duk_compiler_ctx *comp_ctx);
DUK_LOCAL_DECL void duk__parse_func_like_raw(duk_compiler_ctx *comp_ctx, duk_small_uint_t flags);
DUK_LOCAL_DECL duk_int_t duk__parse_func_like_fnum(duk_compiler_ctx *comp_ctx, duk_small_uint_t flags);

#define DUK__FUNC_FLAG_DECL            (1 << 0)   /* Parsing a function declaration. */
#define DUK__FUNC_FLAG_GETSET          (1 << 1)   /* Parsing an object literal getter/setter. */
#define DUK__FUNC_FLAG_METDEF          (1 << 2)   /* Parsing an object literal method definition shorthand. */
#define DUK__FUNC_FLAG_PUSHNAME_PASS1  (1 << 3)   /* Push function name when creating template (first pass only). */
#define DUK__FUNC_FLAG_USE_PREVTOKEN   (1 << 4)   /* Use prev_token to start function parsing (workaround for object literal). */

/*
 *  Parser control values for tokens.  The token table is ordered by the
 *  DUK_TOK_XXX defines.
 *
 *  The binding powers are for lbp() use (i.e. for use in led() context).
 *  Binding powers are positive for typing convenience, and bits at the
 *  top should be reserved for flags.  Binding power step must be higher
 *  than 1 so that binding power "lbp - 1" can be used for right associative
 *  operators.  Currently a step of 2 is used (which frees one more bit for
 *  flags).
 */

/* XXX: actually single step levels would work just fine, clean up */

/* binding power "levels" (see doc/compiler.rst) */
#define DUK__BP_INVALID                0             /* always terminates led() */
#define DUK__BP_EOF                    2
#define DUK__BP_CLOSING                4             /* token closes expression, e.g. ')', ']' */
#define DUK__BP_FOR_EXPR               DUK__BP_CLOSING    /* bp to use when parsing a top level Expression */
#define DUK__BP_COMMA                  6
#define DUK__BP_ASSIGNMENT             8
#define DUK__BP_CONDITIONAL            10
#define DUK__BP_LOR                    12
#define DUK__BP_LAND                   14
#define DUK__BP_BOR                    16
#define DUK__BP_BXOR                   18
#define DUK__BP_BAND                   20
#define DUK__BP_EQUALITY               22
#define DUK__BP_RELATIONAL             24
#define DUK__BP_SHIFT                  26
#define DUK__BP_ADDITIVE               28
#define DUK__BP_MULTIPLICATIVE         30
#define DUK__BP_EXPONENTIATION         32
#define DUK__BP_POSTFIX                34
#define DUK__BP_CALL                   36
#define DUK__BP_MEMBER                 38

#define DUK__TOKEN_LBP_BP_MASK         0x1f
#define DUK__TOKEN_LBP_FLAG_NO_REGEXP  (1 << 5)   /* regexp literal must not follow this token */
#define DUK__TOKEN_LBP_FLAG_TERMINATES (1 << 6)   /* terminates expression; e.g. post-increment/-decrement */
#define DUK__TOKEN_LBP_FLAG_UNUSED     (1 << 7)   /* unused */

#define DUK__TOKEN_LBP_GET_BP(x)       ((duk_small_uint_t) (((x) & DUK__TOKEN_LBP_BP_MASK) * 2))

#define DUK__MK_LBP(bp)                ((bp) >> 1)    /* bp is assumed to be even */
#define DUK__MK_LBP_FLAGS(bp,flags)    (((bp) >> 1) | (flags))

DUK_LOCAL const duk_uint8_t duk__token_lbp[] = {
	DUK__MK_LBP(DUK__BP_EOF),                                 /* DUK_TOK_EOF */
	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_IDENTIFIER */
	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_BREAK */
	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_CASE */
	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_CATCH */
	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_CONTINUE */
	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_DEBUGGER */
	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_DEFAULT */
	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_DELETE */
	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_DO */
	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_ELSE */
	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_FINALLY */
	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_FOR */
	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_FUNCTION */
	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_IF */
	DUK__MK_LBP(DUK__BP_RELATIONAL),                          /* DUK_TOK_IN */
	DUK__MK_LBP(DUK__BP_RELATIONAL),                          /* DUK_TOK_INSTANCEOF */
	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_NEW */
	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_RETURN */
	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_SWITCH */
	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_THIS */
	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_THROW */
	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_TRY */
	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_TYPEOF */
	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_VAR */
	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_CONST */
	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_VOID */
	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_WHILE */
	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_WITH */
	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_CLASS */
	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_ENUM */
	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_EXPORT */
	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_EXTENDS */
	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_IMPORT */
	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_SUPER */
	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_NULL */
	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_TRUE */
	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_FALSE */
	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_GET */
	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_SET */
	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_IMPLEMENTS */
	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_INTERFACE */
	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_LET */
	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_PACKAGE */
	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_PRIVATE */
	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_PROTECTED */
	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_PUBLIC */
	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_STATIC */
	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_YIELD */
	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_LCURLY */
	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_RCURLY */
	DUK__MK_LBP(DUK__BP_MEMBER),                              /* DUK_TOK_LBRACKET */
	DUK__MK_LBP_FLAGS(DUK__BP_CLOSING, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_RBRACKET */
	DUK__MK_LBP(DUK__BP_CALL),                                /* DUK_TOK_LPAREN */
	DUK__MK_LBP_FLAGS(DUK__BP_CLOSING, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_RPAREN */
	DUK__MK_LBP(DUK__BP_MEMBER),                              /* DUK_TOK_PERIOD */
	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_SEMICOLON */
	DUK__MK_LBP(DUK__BP_COMMA),                               /* DUK_TOK_COMMA */
	DUK__MK_LBP(DUK__BP_RELATIONAL),                          /* DUK_TOK_LT */
	DUK__MK_LBP(DUK__BP_RELATIONAL),                          /* DUK_TOK_GT */
	DUK__MK_LBP(DUK__BP_RELATIONAL),                          /* DUK_TOK_LE */
	DUK__MK_LBP(DUK__BP_RELATIONAL),                          /* DUK_TOK_GE */
	DUK__MK_LBP(DUK__BP_EQUALITY),                            /* DUK_TOK_EQ */
	DUK__MK_LBP(DUK__BP_EQUALITY),                            /* DUK_TOK_NEQ */
	DUK__MK_LBP(DUK__BP_EQUALITY),                            /* DUK_TOK_SEQ */
	DUK__MK_LBP(DUK__BP_EQUALITY),                            /* DUK_TOK_SNEQ */
	DUK__MK_LBP(DUK__BP_ADDITIVE),                            /* DUK_TOK_ADD */
	DUK__MK_LBP(DUK__BP_ADDITIVE),                            /* DUK_TOK_SUB */
	DUK__MK_LBP(DUK__BP_MULTIPLICATIVE),                      /* DUK_TOK_MUL */
	DUK__MK_LBP(DUK__BP_MULTIPLICATIVE),                      /* DUK_TOK_DIV */
	DUK__MK_LBP(DUK__BP_MULTIPLICATIVE),                      /* DUK_TOK_MOD */
	DUK__MK_LBP(DUK__BP_EXPONENTIATION),                      /* DUK_TOK_EXP */
	DUK__MK_LBP_FLAGS(DUK__BP_POSTFIX, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_INCREMENT */
	DUK__MK_LBP_FLAGS(DUK__BP_POSTFIX, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_DECREMENT */
	DUK__MK_LBP(DUK__BP_SHIFT),                               /* DUK_TOK_ALSHIFT */
	DUK__MK_LBP(DUK__BP_SHIFT),                               /* DUK_TOK_ARSHIFT */
	DUK__MK_LBP(DUK__BP_SHIFT),                               /* DUK_TOK_RSHIFT */
	DUK__MK_LBP(DUK__BP_BAND),                                /* DUK_TOK_BAND */
	DUK__MK_LBP(DUK__BP_BOR),                                 /* DUK_TOK_BOR */
	DUK__MK_LBP(DUK__BP_BXOR),                                /* DUK_TOK_BXOR */
	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_LNOT */
	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_BNOT */
	DUK__MK_LBP(DUK__BP_LAND),                                /* DUK_TOK_LAND */
	DUK__MK_LBP(DUK__BP_LOR),                                 /* DUK_TOK_LOR */
	DUK__MK_LBP(DUK__BP_CONDITIONAL),                         /* DUK_TOK_QUESTION */
	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_COLON */
	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_EQUALSIGN */
	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_ADD_EQ */
	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_SUB_EQ */
	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_MUL_EQ */
	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_DIV_EQ */
	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_MOD_EQ */
	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_EXP_EQ */
	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_ALSHIFT_EQ */
	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_ARSHIFT_EQ */
	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_RSHIFT_EQ */
	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_BAND_EQ */
	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_BOR_EQ */
	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_BXOR_EQ */
	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_NUMBER */
	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_STRING */
	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_REGEXP */
};

/*
 *  Misc helpers
 */

DUK_LOCAL void duk__comp_recursion_increase(duk_compiler_ctx *comp_ctx) {
	DUK_ASSERT(comp_ctx != NULL);
	DUK_ASSERT(comp_ctx->recursion_depth >= 0);
	if (comp_ctx->recursion_depth >= comp_ctx->recursion_limit) {
		DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_COMPILER_RECURSION_LIMIT);
		DUK_WO_NORETURN(return;);
	}
	comp_ctx->recursion_depth++;
}

DUK_LOCAL void duk__comp_recursion_decrease(duk_compiler_ctx *comp_ctx) {
	DUK_ASSERT(comp_ctx != NULL);
	DUK_ASSERT(comp_ctx->recursion_depth > 0);
	comp_ctx->recursion_depth--;
}

DUK_LOCAL duk_bool_t duk__hstring_is_eval_or_arguments(duk_compiler_ctx *comp_ctx, duk_hstring *h) {
	DUK_UNREF(comp_ctx);
	DUK_ASSERT(h != NULL);
	return DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(h);
}

DUK_LOCAL duk_bool_t duk__hstring_is_eval_or_arguments_in_strict_mode(duk_compiler_ctx *comp_ctx, duk_hstring *h) {
	DUK_ASSERT(h != NULL);
	return (comp_ctx->curr_func.is_strict &&
	        DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(h));
}

/*
 *  Parser duk__advance() token eating functions
 */

/* XXX: valstack handling is awkward.  Add a valstack helper which
 * avoids dup():ing; valstack_copy(src, dst)?
 */

DUK_LOCAL void duk__advance_helper(duk_compiler_ctx *comp_ctx, duk_small_int_t expect) {
	duk_hthread *thr = comp_ctx->thr;
	duk_bool_t regexp;

	DUK_ASSERT_DISABLE(comp_ctx->curr_token.t >= 0);  /* unsigned */
	DUK_ASSERT(comp_ctx->curr_token.t <= DUK_TOK_MAXVAL);  /* MAXVAL is inclusive */

	/*
	 *  Use current token to decide whether a RegExp can follow.
	 *
	 *  We can use either 't' or 't_nores'; the latter would not
	 *  recognize keywords.  Some keywords can be followed by a
	 *  RegExp (e.g. "return"), so using 't' is better.  This is
	 *  not trivial, see doc/compiler.rst.
	 */

	regexp = 1;
	if (duk__token_lbp[comp_ctx->curr_token.t] & DUK__TOKEN_LBP_FLAG_NO_REGEXP) {
		regexp = 0;
	}
	if (comp_ctx->curr_func.reject_regexp_in_adv) {
		comp_ctx->curr_func.reject_regexp_in_adv = 0;
		regexp = 0;
	}
	if (comp_ctx->curr_func.allow_regexp_in_adv) {
		comp_ctx->curr_func.allow_regexp_in_adv = 0;
		regexp = 1;
	}

	if (expect >= 0 && comp_ctx->curr_token.t != (duk_small_uint_t) expect) {
		DUK_D(DUK_DPRINT("parse error: expect=%ld, got=%ld",
		                 (long) expect, (long) comp_ctx->curr_token.t));
		DUK_ERROR_SYNTAX(thr, DUK_STR_PARSE_ERROR);
		DUK_WO_NORETURN(return;);
	}

	/* make current token the previous; need to fiddle with valstack "backing store" */
	duk_memcpy(&comp_ctx->prev_token, &comp_ctx->curr_token, sizeof(duk_token));
	duk_copy(thr, comp_ctx->tok11_idx, comp_ctx->tok21_idx);
	duk_copy(thr, comp_ctx->tok12_idx, comp_ctx->tok22_idx);

	/* parse new token */
	duk_lexer_parse_js_input_element(&comp_ctx->lex,
	                                 &comp_ctx->curr_token,
	                                 comp_ctx->curr_func.is_strict,
	                                 regexp);

	DUK_DDD(DUK_DDDPRINT("advance: curr: tok=%ld/%ld,%ld,term=%ld,%!T,%!T "
	                     "prev: tok=%ld/%ld,%ld,term=%ld,%!T,%!T",
	                     (long) comp_ctx->curr_token.t,
	                     (long) comp_ctx->curr_token.t_nores,
	                     (long) comp_ctx->curr_token.start_line,
	                     (long) comp_ctx->curr_token.lineterm,
	                     (duk_tval *) duk_get_tval(thr, comp_ctx->tok11_idx),
	                     (duk_tval *) duk_get_tval(thr, comp_ctx->tok12_idx),
	                     (long) comp_ctx->prev_token.t,
	                     (long) comp_ctx->prev_token.t_nores,
	                     (long) comp_ctx->prev_token.start_line,
	                     (long) comp_ctx->prev_token.lineterm,
	                     (duk_tval *) duk_get_tval(thr, comp_ctx->tok21_idx),
	                     (duk_tval *) duk_get_tval(thr, comp_ctx->tok22_idx)));
}

/* advance, expecting current token to be a specific token; parse next token in regexp context */
DUK_LOCAL void duk__advance_expect(duk_compiler_ctx *comp_ctx, duk_small_int_t expect) {
	duk__advance_helper(comp_ctx, expect);
}

/* advance, whatever the current token is; parse next token in regexp context */
DUK_LOCAL void duk__advance(duk_compiler_ctx *comp_ctx) {
	duk__advance_helper(comp_ctx, -1);
}

/*
 *  Helpers for duk_compiler_func.
 */

/* init function state: inits valstack allocations */
DUK_LOCAL void duk__init_func_valstack_slots(duk_compiler_ctx *comp_ctx) {
	duk_compiler_func *func = &comp_ctx->curr_func;
	duk_hthread *thr = comp_ctx->thr;
	duk_idx_t entry_top;

	entry_top = duk_get_top(thr);

	duk_memzero(func, sizeof(*func));  /* intentional overlap with earlier memzero */
#if defined(DUK_USE_EXPLICIT_NULL_INIT)
	func->h_name = NULL;
	func->h_consts = NULL;
	func->h_funcs = NULL;
	func->h_decls = NULL;
	func->h_labelnames = NULL;
	func->h_labelinfos = NULL;
	func->h_argnames = NULL;
	func->h_varmap = NULL;
#endif

	duk_require_stack(thr, DUK__FUNCTION_INIT_REQUIRE_SLOTS);

	DUK_BW_INIT_PUSHBUF(thr, &func->bw_code, DUK__BC_INITIAL_INSTS * sizeof(duk_compiler_instr));
	/* code_idx = entry_top + 0 */

	duk_push_bare_array(thr);
	func->consts_idx = entry_top + 1;
	func->h_consts = DUK_GET_HOBJECT_POSIDX(thr, entry_top + 1);
	DUK_ASSERT(func->h_consts != NULL);

	duk_push_bare_array(thr);
	func->funcs_idx = entry_top + 2;
	func->h_funcs = DUK_GET_HOBJECT_POSIDX(thr, entry_top + 2);
	DUK_ASSERT(func->h_funcs != NULL);
	DUK_ASSERT(func->fnum_next == 0);

	duk_push_bare_array(thr);
	func->decls_idx = entry_top + 3;
	func->h_decls = DUK_GET_HOBJECT_POSIDX(thr, entry_top + 3);
	DUK_ASSERT(func->h_decls != NULL);

	duk_push_bare_array(thr);
	func->labelnames_idx = entry_top + 4;
	func->h_labelnames = DUK_GET_HOBJECT_POSIDX(thr, entry_top + 4);
	DUK_ASSERT(func->h_labelnames != NULL);

	duk_push_dynamic_buffer(thr, 0);
	func->labelinfos_idx = entry_top + 5;
	func->h_labelinfos = (duk_hbuffer_dynamic *) duk_known_hbuffer(thr, entry_top + 5);
	DUK_ASSERT(func->h_labelinfos != NULL);
	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(func->h_labelinfos) && !DUK_HBUFFER_HAS_EXTERNAL(func->h_labelinfos));

	duk_push_bare_array(thr);
	func->argnames_idx = entry_top + 6;
	func->h_argnames = DUK_GET_HOBJECT_POSIDX(thr, entry_top + 6);
	DUK_ASSERT(func->h_argnames != NULL);

	duk_push_bare_object(thr);
	func->varmap_idx = entry_top + 7;
	func->h_varmap = DUK_GET_HOBJECT_POSIDX(thr, entry_top + 7);
	DUK_ASSERT(func->h_varmap != NULL);
}

/* reset function state (prepare for pass 2) */
DUK_LOCAL void duk__reset_func_for_pass2(duk_compiler_ctx *comp_ctx) {
	duk_compiler_func *func = &comp_ctx->curr_func;
	duk_hthread *thr = comp_ctx->thr;

	/* reset bytecode buffer but keep current size; pass 2 will
	 * require same amount or more.
	 */
	DUK_BW_RESET_SIZE(thr, &func->bw_code);

	duk_set_length(thr, func->consts_idx, 0);
	/* keep func->h_funcs; inner functions are not reparsed to avoid O(depth^2) parsing */
	func->fnum_next = 0;
	/* duk_set_length(thr, func->funcs_idx, 0); */
	duk_set_length(thr, func->labelnames_idx, 0);
	duk_hbuffer_reset(thr, func->h_labelinfos);
	/* keep func->h_argnames; it is fixed for all passes */

	/* truncated in case pass 3 needed */
	duk_push_bare_object(thr);
	duk_replace(thr, func->varmap_idx);
	func->h_varmap = DUK_GET_HOBJECT_POSIDX(thr, func->varmap_idx);
	DUK_ASSERT(func->h_varmap != NULL);
}

/* cleanup varmap from any null entries, compact it, etc; returns number
 * of final entries after cleanup.
 */
DUK_LOCAL duk_int_t duk__cleanup_varmap(duk_compiler_ctx *comp_ctx) {
	duk_hthread *thr = comp_ctx->thr;
	duk_hobject *h_varmap;
	duk_hstring *h_key;
	duk_tval *tv;
	duk_uint32_t i, e_next;
	duk_int_t ret;

	/* [ ... varmap ] */

	h_varmap = DUK_GET_HOBJECT_NEGIDX(thr, -1);
	DUK_ASSERT(h_varmap != NULL);

	ret = 0;
	e_next = DUK_HOBJECT_GET_ENEXT(h_varmap);
	for (i = 0; i < e_next; i++) {
		h_key = DUK_HOBJECT_E_GET_KEY(thr->heap, h_varmap, i);
		if (!h_key) {
			continue;
		}

		DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, h_varmap, i));

		/* The entries can either be register numbers or 'null' values.
		 * Thus, no need to DECREF them and get side effects.  DECREF'ing
		 * the keys (strings) can cause memory to be freed but no side
		 * effects as strings don't have finalizers.  This is why we can
		 * rely on the object properties not changing from underneath us.
		 */

		tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, h_varmap, i);
		if (!DUK_TVAL_IS_NUMBER(tv)) {
			DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv));
			DUK_HOBJECT_E_SET_KEY(thr->heap, h_varmap, i, NULL);
			DUK_HSTRING_DECREF(thr, h_key);
			/* when key is NULL, value is garbage so no need to set */
		} else {
			ret++;
		}
	}

	duk_compact_m1(thr);

	return ret;
}

/* Convert duk_compiler_func into a function template, leaving the result
 * on top of stack.
 */
/* XXX: awkward and bloated asm -- use faster internal accesses */
DUK_LOCAL void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx) {
	duk_compiler_func *func = &comp_ctx->curr_func;
	duk_hthread *thr = comp_ctx->thr;
	duk_hcompfunc *h_res;
	duk_hbuffer_fixed *h_data;
	duk_size_t consts_count;
	duk_size_t funcs_count;
	duk_size_t code_count;
	duk_size_t code_size;
	duk_size_t data_size;
	duk_size_t i;
	duk_tval *p_const;
	duk_hobject **p_func;
	duk_instr_t *p_instr;
	duk_compiler_instr *q_instr;
	duk_tval *tv;
	duk_bool_t keep_varmap;
	duk_bool_t keep_formals;
#if !defined(DUK_USE_DEBUGGER_SUPPORT)
	duk_size_t formals_length;
#endif

	DUK_DDD(DUK_DDDPRINT("converting duk_compiler_func to function/template"));

	/*
	 *  Push result object and init its flags
	 */

	/* Valstack should suffice here, required on function valstack init */

	h_res = duk_push_hcompfunc(thr);
	DUK_ASSERT(h_res != NULL);
	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_res) == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, (duk_hobject *) h_res, NULL);  /* Function templates are "bare objects". */

	if (func->is_function) {
		DUK_DDD(DUK_DDDPRINT("function -> set NEWENV"));
		DUK_HOBJECT_SET_NEWENV((duk_hobject *) h_res);

		if (!func->is_arguments_shadowed) {
			/* arguments object would be accessible; note that shadowing
			 * bindings are arguments or function declarations, neither
			 * of which are deletable, so this is safe.
			 */

			if (func->id_access_arguments || func->may_direct_eval) {
				DUK_DDD(DUK_DDDPRINT("function may access 'arguments' object directly or "
				                     "indirectly -> set CREATEARGS"));
				DUK_HOBJECT_SET_CREATEARGS((duk_hobject *) h_res);
			}
		}
	} else if (func->is_eval && func->is_strict) {
		DUK_DDD(DUK_DDDPRINT("strict eval code -> set NEWENV"));
		DUK_HOBJECT_SET_NEWENV((duk_hobject *) h_res);
	} else {
		/* non-strict eval: env is caller's env or global env (direct vs. indirect call)
		 * global code: env is is global env
		 */
		DUK_DDD(DUK_DDDPRINT("non-strict eval code or global code -> no NEWENV"));
		DUK_ASSERT(!DUK_HOBJECT_HAS_NEWENV((duk_hobject *) h_res));
	}

#if defined(DUK_USE_FUNC_NAME_PROPERTY)
	if (func->is_function && func->is_namebinding && func->h_name != NULL) {
		/* Object literal set/get functions have a name (property
		 * name) but must not have a lexical name binding, see
		 * test-bug-getset-func-name.js.
		 */
		DUK_DDD(DUK_DDDPRINT("function expression with a name -> set NAMEBINDING"));
		DUK_HOBJECT_SET_NAMEBINDING((duk_hobject *) h_res);
	}
#endif

	if (func->is_strict) {
		DUK_DDD(DUK_DDDPRINT("function is strict -> set STRICT"));
		DUK_HOBJECT_SET_STRICT((duk_hobject *) h_res);
	}

	if (func->is_notail) {
		DUK_DDD(DUK_DDDPRINT("function is notail -> set NOTAIL"));
		DUK_HOBJECT_SET_NOTAIL((duk_hobject *) h_res);
	}

	if (func->is_constructable) {
		DUK_DDD(DUK_DDDPRINT("function is constructable -> set CONSTRUCTABLE"));
		DUK_HOBJECT_SET_CONSTRUCTABLE((duk_hobject *) h_res);
	}

	/*
	 *  Build function fixed size 'data' buffer, which contains bytecode,
	 *  constants, and inner function references.
	 *
	 *  During the building phase 'data' is reachable but incomplete.
	 *  Only incref's occur during building (no refzero or GC happens),
	 *  so the building process is atomic.
	 */

	consts_count = duk_hobject_get_length(thr, func->h_consts);
	funcs_count = duk_hobject_get_length(thr, func->h_funcs) / 3;
	code_count = DUK_BW_GET_SIZE(thr, &func->bw_code) / sizeof(duk_compiler_instr);
	code_size = code_count * sizeof(duk_instr_t);

	data_size = consts_count * sizeof(duk_tval) +
	            funcs_count * sizeof(duk_hobject *) +
	            code_size;

	DUK_DDD(DUK_DDDPRINT("consts_count=%ld, funcs_count=%ld, code_size=%ld -> "
	                     "data_size=%ld*%ld + %ld*%ld + %ld = %ld",
	                     (long) consts_count, (long) funcs_count, (long) code_size,
	                     (long) consts_count, (long) sizeof(duk_tval),
	                     (long) funcs_count, (long) sizeof(duk_hobject *),
	                     (long) code_size, (long) data_size));

	duk_push_fixed_buffer_nozero(thr, data_size);
	h_data = (duk_hbuffer_fixed *) (void *) duk_known_hbuffer(thr, -1);

	DUK_HCOMPFUNC_SET_DATA(thr->heap, h_res, (duk_hbuffer *) h_data);
	DUK_HEAPHDR_INCREF(thr, h_data);

	p_const = (duk_tval *) (void *) DUK_HBUFFER_FIXED_GET_DATA_PTR(thr->heap, h_data);
	for (i = 0; i < consts_count; i++) {
		DUK_ASSERT(i <= DUK_UARRIDX_MAX);  /* const limits */
		tv = duk_hobject_find_array_entry_tval_ptr(thr->heap, func->h_consts, (duk_uarridx_t) i);
		DUK_ASSERT(tv != NULL);
		DUK_TVAL_SET_TVAL(p_const, tv);
		p_const++;
		DUK_TVAL_INCREF(thr, tv);  /* may be a string constant */

		DUK_DDD(DUK_DDDPRINT("constant: %!T", (duk_tval *) tv));
	}

	p_func = (duk_hobject **) p_const;
	DUK_HCOMPFUNC_SET_FUNCS(thr->heap, h_res, p_func);
	for (i = 0; i < funcs_count; i++) {
		duk_hobject *h;
		DUK_ASSERT(i * 3 <= DUK_UARRIDX_MAX);  /* func limits */
		tv = duk_hobject_find_array_entry_tval_ptr(thr->heap, func->h_funcs, (duk_uarridx_t) (i * 3));
		DUK_ASSERT(tv != NULL);
		DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv));
		h = DUK_TVAL_GET_OBJECT(tv);
		DUK_ASSERT(h != NULL);
		DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(h));
		*p_func++ = h;
		DUK_HOBJECT_INCREF(thr, h);

		DUK_DDD(DUK_DDDPRINT("inner function: %p -> %!iO",
		                     (void *) h, (duk_heaphdr *) h));
	}

	p_instr = (duk_instr_t *) p_func;
	DUK_HCOMPFUNC_SET_BYTECODE(thr->heap, h_res, p_instr);

	/* copy bytecode instructions one at a time */
	q_instr = (duk_compiler_instr *) (void *) DUK_BW_GET_BASEPTR(thr, &func->bw_code);
	for (i = 0; i < code_count; i++) {
		p_instr[i] = q_instr[i].ins;
	}
	/* Note: 'q_instr' is still used below */

	DUK_ASSERT((duk_uint8_t *) (p_instr + code_count) == DUK_HBUFFER_FIXED_GET_DATA_PTR(thr->heap, h_data) + data_size);

	duk_pop(thr);  /* 'data' (and everything in it) is reachable through h_res now */

	/*
	 *  Init non-property result fields
	 *
	 *  'nregs' controls how large a register frame is allocated.
	 *
	 *  'nargs' controls how many formal arguments are written to registers:
	 *  r0, ... r(nargs-1).  The remaining registers are initialized to
	 *  undefined.
	 */

	DUK_ASSERT(func->temp_max >= 0);
	h_res->nregs = (duk_uint16_t) func->temp_max;
	h_res->nargs = (duk_uint16_t) duk_hobject_get_length(thr, func->h_argnames);
	DUK_ASSERT(h_res->nregs >= h_res->nargs);  /* pass2 allocation handles this */
#if defined(DUK_USE_DEBUGGER_SUPPORT)
	h_res->start_line = (duk_uint32_t) func->min_line;
	h_res->end_line = (duk_uint32_t) func->max_line;
#endif

	/*
	 *  Init object properties
	 *
	 *  Properties should be added in decreasing order of access frequency.
	 *  (Not very critical for function templates.)
	 */

	DUK_DDD(DUK_DDDPRINT("init function properties"));

	/* [ ... res ] */

	/* _Varmap: omitted if function is guaranteed not to do a slow path
	 * identifier access that might be caught by locally declared variables.
	 * The varmap can also be omitted if it turns out empty of actual
	 * register mappings after a cleanup.  When debugging is enabled, we
	 * always need the varmap to be able to lookup variables at any point.
	 */

#if defined(DUK_USE_DEBUGGER_SUPPORT)
	DUK_DD(DUK_DDPRINT("keeping _Varmap because debugger support is enabled"));
	keep_varmap = 1;
#else
	if (func->id_access_slow_own ||   /* directly uses slow accesses that may match own variables */
	    func->id_access_arguments ||  /* accesses 'arguments' directly */
	    func->may_direct_eval ||      /* may indirectly slow access through a direct eval */
	    funcs_count > 0) {            /* has inner functions which may slow access (XXX: this can be optimized by looking at the inner functions) */
		DUK_DD(DUK_DDPRINT("keeping _Varmap because of direct eval, slow path access that may match local variables, or presence of inner functions"));
		keep_varmap = 1;
	} else {
		DUK_DD(DUK_DDPRINT("dropping _Varmap"));
		keep_varmap = 0;
	}
#endif

	if (keep_varmap) {
		duk_int_t num_used;
		duk_dup(thr, func->varmap_idx);
		num_used = duk__cleanup_varmap(comp_ctx);
		DUK_DDD(DUK_DDDPRINT("cleaned up varmap: %!T (num_used=%ld)",
		                     (duk_tval *) duk_get_tval(thr, -1), (long) num_used));

		if (num_used > 0) {
			duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VARMAP, DUK_PROPDESC_FLAGS_NONE);
		} else {
			DUK_DD(DUK_DDPRINT("varmap is empty after cleanup -> no need to add"));
			duk_pop(thr);
		}
	}

	/* _Formals: omitted if function is guaranteed not to need a (non-strict)
	 * arguments object, and _Formals.length matches nargs exactly.
	 *
	 * Non-arrow functions can't see an outer function's 'argument' binding
	 * (because they have their own), but arrow functions can.  When arrow
	 * functions are added, this condition would need to be added:
	 *     inner_arrow_funcs_count > 0   inner arrow functions may access 'arguments'
	 */
#if defined(DUK_USE_DEBUGGER_SUPPORT)
	DUK_DD(DUK_DDPRINT("keeping _Formals because debugger support is enabled"));
	keep_formals = 1;
#else
	formals_length = duk_get_length(thr, func->argnames_idx);
	if (formals_length != (duk_size_t) h_res->nargs) {
		/* Nargs not enough for closure .length: keep _Formals regardless
		 * of its length.  Shouldn't happen in practice at the moment.
		 */
		DUK_DD(DUK_DDPRINT("keeping _Formals because _Formals.length != nargs"));
		keep_formals = 1;
	} else if ((func->id_access_arguments || func->may_direct_eval) &&
	           (formals_length > 0)) {
		/* Direct eval (may access 'arguments') or accesses 'arguments'
		 * explicitly: keep _Formals unless it is zero length.
		 */
		DUK_DD(DUK_DDPRINT("keeping _Formals because of direct eval or explicit access to 'arguments', and _Formals.length != 0"));
		keep_formals = 1;
	} else {
		DUK_DD(DUK_DDPRINT("omitting _Formals, nargs matches _Formals.length, so no properties added"));
		keep_formals = 0;
	}
#endif

	if (keep_formals) {
		duk_dup(thr, func->argnames_idx);
		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_FORMALS, DUK_PROPDESC_FLAGS_NONE);
	}

	/* name */
#if defined(DUK_USE_FUNC_NAME_PROPERTY)
	if (func->h_name) {
		duk_push_hstring(thr, func->h_name);
		DUK_DD(DUK_DDPRINT("setting function template .name to %!T", duk_get_tval(thr, -1)));
		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_NONE);
	}
#endif  /* DUK_USE_FUNC_NAME_PROPERTY */

	/* _Source */
#if defined(DUK_USE_NONSTD_FUNC_SOURCE_PROPERTY)
	if (0) {
		/* XXX: Currently function source code is not stored, as it is not
		 * required by the standard.  Source code should not be stored by
		 * default (user should enable it explicitly), and the source should
		 * probably be compressed with a trivial text compressor; average
		 * compression of 20-30% is quite easy to achieve even with a trivial
		 * compressor (RLE + backwards lookup).
		 *
		 * Debugging needs source code to be useful: sometimes input code is
		 * not found in files as it may be generated and then eval()'d, given
		 * by dynamic C code, etc.
		 *
		 * Other issues:
		 *
		 *   - Need tokenizer indices for start and end to substring
		 *   - Always normalize function declaration part?
		 *   - If we keep _Formals, only need to store body
		 */

		/*
		 *  For global or eval code this is straightforward.  For functions
		 *  created with the Function constructor we only get the source for
		 *  the body and must manufacture the "function ..." part.
		 *
		 *  For instance, for constructed functions (v8):
		 *
		 *    > a = new Function("foo", "bar", "print(foo)");
		 *    [Function]
		 *    > a.toString()
		 *    'function anonymous(foo,bar) {\nprint(foo)\n}'
		 *
		 *  Similarly for e.g. getters (v8):
		 *
		 *    > x = { get a(foo,bar) { print(foo); } }
		 *    { a: [Getter] }
		 *    > Object.getOwnPropertyDescriptor(x, 'a').get.toString()
		 *    'function a(foo,bar) { print(foo); }'
		 */

#if 0
		duk_push_literal(thr, "XXX");
		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_SOURCE, DUK_PROPDESC_FLAGS_NONE);
#endif
	}
#endif  /* DUK_USE_NONSTD_FUNC_SOURCE_PROPERTY */

	/* _Pc2line */
#if defined(DUK_USE_PC2LINE)
	if (1) {
		/*
		 *  Size-optimized pc->line mapping.
		 */

		DUK_ASSERT(code_count <= DUK_COMPILER_MAX_BYTECODE_LENGTH);
		duk_hobject_pc2line_pack(thr, q_instr, (duk_uint_fast32_t) code_count);  /* -> pushes fixed buffer */
		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_PC2LINE, DUK_PROPDESC_FLAGS_NONE);

		/* XXX: if assertions enabled, walk through all valid PCs
		 * and check line mapping.
		 */
	}
#endif  /* DUK_USE_PC2LINE */

	/* fileName */
#if defined(DUK_USE_FUNC_FILENAME_PROPERTY)
	if (comp_ctx->h_filename) {
		/*
		 *  Source filename (or equivalent), for identifying thrown errors.
		 */

		duk_push_hstring(thr, comp_ctx->h_filename);
		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_FILE_NAME, DUK_PROPDESC_FLAGS_NONE);
	}
#endif

	DUK_DD(DUK_DDPRINT("converted function: %!ixT",
	                   (duk_tval *) duk_get_tval(thr, -1)));

	/*
	 *  Compact the function template.
	 */

	duk_compact_m1(thr);

	/*
	 *  Debug dumping
	 */

#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
	{
		duk_hcompfunc *h;
		duk_instr_t *p, *p_start, *p_end;

		h = (duk_hcompfunc *) duk_get_hobject(thr, -1);
		p_start = (duk_instr_t *) DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, h);
		p_end = (duk_instr_t *) DUK_HCOMPFUNC_GET_CODE_END(thr->heap, h);

		p = p_start;
		while (p < p_end) {
			DUK_DDD(DUK_DDDPRINT("BC %04ld: %!I        ; 0x%08lx op=%ld (%!X) a=%ld b=%ld c=%ld",
			                     (long) (p - p_start),
			                     (duk_instr_t) (*p),
			                     (unsigned long) (*p),
			                     (long) DUK_DEC_OP(*p),
			                     (long) DUK_DEC_OP(*p),
			                     (long) DUK_DEC_A(*p),
			                     (long) DUK_DEC_B(*p),
			                     (long) DUK_DEC_C(*p)));
			p++;
		}
	}
#endif
}

/*
 *  Code emission helpers
 *
 *  Some emission helpers understand the range of target and source reg/const
 *  values and automatically emit shuffling code if necessary.  This is the
 *  case when the slot in question (A, B, C) is used in the standard way and
 *  for opcodes the emission helpers explicitly understand (like DUK_OP_MPUTOBJ).
 *
 *  The standard way is that:
 *    - slot A is a target register
 *    - slot B is a source register/constant
 *    - slot C is a source register/constant
 *
 *  If a slot is used in a non-standard way the caller must indicate this
 *  somehow.  If a slot is used as a target instead of a source (or vice
 *  versa), this can be indicated with a flag to trigger proper shuffling
 *  (e.g. DUK__EMIT_FLAG_B_IS_TARGET).  If the value in the slot is not
 *  register/const related at all, the caller must ensure that the raw value
 *  fits into the corresponding slot so as to not trigger shuffling.  The
 *  caller must set a "no shuffle" flag to ensure compilation fails if
 *  shuffling were to be triggered because of an internal error.
 *
 *  For slots B and C the raw slot size is 9 bits but one bit is reserved for
 *  the reg/const indicator.  To use the full 9-bit range for a raw value,
 *  shuffling must be disabled with the DUK__EMIT_FLAG_NO_SHUFFLE_{B,C} flag.
 *  Shuffling is only done for A, B, and C slots, not the larger BC or ABC slots.
 *
 *  There is call handling specific understanding in the A-B-C emitter to
 *  convert call setup and call instructions into indirect ones if necessary.
 */

/* Code emission flags, passed in the 'opcode' field.  Opcode + flags
 * fit into 16 bits for now, so use duk_small_uint_t.
 */
#define DUK__EMIT_FLAG_NO_SHUFFLE_A      (1 << 8)
#define DUK__EMIT_FLAG_NO_SHUFFLE_B      (1 << 9)
#define DUK__EMIT_FLAG_NO_SHUFFLE_C      (1 << 10)
#define DUK__EMIT_FLAG_A_IS_SOURCE       (1 << 11)  /* slot A is a source (default: target) */
#define DUK__EMIT_FLAG_B_IS_TARGET       (1 << 12)  /* slot B is a target (default: source) */
#define DUK__EMIT_FLAG_C_IS_TARGET       (1 << 13)  /* slot C is a target (default: source) */
#define DUK__EMIT_FLAG_BC_REGCONST       (1 << 14)  /* slots B and C are reg/const */
#define DUK__EMIT_FLAG_RESERVE_JUMPSLOT  (1 << 15)  /* reserve a jumpslot after instr before target spilling, used for NEXTENUM */

/* XXX: macro smaller than call? */
DUK_LOCAL duk_int_t duk__get_current_pc(duk_compiler_ctx *comp_ctx) {
	duk_compiler_func *func;
	func = &comp_ctx->curr_func;
	return (duk_int_t) (DUK_BW_GET_SIZE(comp_ctx->thr, &func->bw_code) / sizeof(duk_compiler_instr));
}

DUK_LOCAL duk_compiler_instr *duk__get_instr_ptr(duk_compiler_ctx *comp_ctx, duk_int_t pc) {
	DUK_ASSERT(pc >= 0);
	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)));
	return ((duk_compiler_instr *) (void *) DUK_BW_GET_BASEPTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code)) + pc;
}

/* emit instruction; could return PC but that's not needed in the majority
 * of cases.
 */
DUK_LOCAL void duk__emit(duk_compiler_ctx *comp_ctx, duk_instr_t ins) {
#if defined(DUK_USE_PC2LINE)
	duk_int_t line;
#endif
	duk_compiler_instr *instr;

	DUK_DDD(DUK_DDDPRINT("duk__emit: 0x%08lx curr_token.start_line=%ld prev_token.start_line=%ld pc=%ld --> %!I",
	                     (unsigned long) ins,
	                     (long) comp_ctx->curr_token.start_line,
	                     (long) comp_ctx->prev_token.start_line,
	                     (long) duk__get_current_pc(comp_ctx),
	                     (duk_instr_t) ins));

	instr = (duk_compiler_instr *) (void *) DUK_BW_ENSURE_GETPTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code, sizeof(duk_compiler_instr));
	DUK_BW_ADD_PTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code, sizeof(duk_compiler_instr));

#if defined(DUK_USE_PC2LINE)
	/* The line number tracking is a bit inconsistent right now, which
	 * affects debugger accuracy.  Mostly call sites emit opcodes when
	 * they have parsed a token (say a terminating semicolon) and called
	 * duk__advance().  In this case the line number of the previous
	 * token is the most accurate one (except in prologue where
	 * prev_token.start_line is 0).  This is probably not 100% correct
	 * right now.
	 */
	/* approximation, close enough */
	line = comp_ctx->prev_token.start_line;
	if (line == 0) {
		line = comp_ctx->curr_token.start_line;
	}
#endif

	instr->ins = ins;
#if defined(DUK_USE_PC2LINE)
	instr->line = (duk_uint32_t) line;
#endif
#if defined(DUK_USE_DEBUGGER_SUPPORT)
	if (line < comp_ctx->curr_func.min_line) {
		comp_ctx->curr_func.min_line = line;
	}
	if (line > comp_ctx->curr_func.max_line) {
		comp_ctx->curr_func.max_line = line;
	}
#endif

	/* Limit checks for bytecode byte size and line number. */
	if (DUK_UNLIKELY(DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) > DUK_USE_ESBC_MAX_BYTES)) {
		goto fail_bc_limit;
	}
#if defined(DUK_USE_PC2LINE) && defined(DUK_USE_ESBC_LIMITS)
#if defined(DUK_USE_BUFLEN16)
	/* Buffer length is bounded to 0xffff automatically, avoid compile warning. */
	if (DUK_UNLIKELY(line > DUK_USE_ESBC_MAX_LINENUMBER)) {
		goto fail_bc_limit;
	}
#else
	if (DUK_UNLIKELY(line > DUK_USE_ESBC_MAX_LINENUMBER)) {
		goto fail_bc_limit;
	}
#endif
#endif

	return;

  fail_bc_limit:
	DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_BYTECODE_LIMIT);
	DUK_WO_NORETURN(return;);
}

/* Update function min/max line from current token.  Needed to improve
 * function line range information for debugging, so that e.g. opening
 * curly brace is covered by line range even when no opcodes are emitted
 * for the line containing the brace.
 */
DUK_LOCAL void duk__update_lineinfo_currtoken(duk_compiler_ctx *comp_ctx) {
#if defined(DUK_USE_DEBUGGER_SUPPORT)
	duk_int_t line;

	line = comp_ctx->curr_token.start_line;
	if (line == 0) {
		return;
	}
	if (line < comp_ctx->curr_func.min_line) {
		comp_ctx->curr_func.min_line = line;
	}
	if (line > comp_ctx->curr_func.max_line) {
		comp_ctx->curr_func.max_line = line;
	}
#else
	DUK_UNREF(comp_ctx);
#endif
}

DUK_LOCAL void duk__emit_op_only(duk_compiler_ctx *comp_ctx, duk_small_uint_t op) {
	duk__emit(comp_ctx, DUK_ENC_OP_ABC(op, 0));
}

/* Important main primitive. */
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) {
	duk_instr_t ins = 0;
	duk_int_t a_out = -1;
	duk_int_t b_out = -1;
	duk_int_t c_out = -1;
	duk_int_t tmp;
	duk_small_uint_t op = op_flags & 0xffU;

	DUK_DDD(DUK_DDDPRINT("emit: op_flags=%04lx, a=%ld, b=%ld, c=%ld",
	                     (unsigned long) op_flags, (long) a, (long) b, (long) c));

	/* We could rely on max temp/const checks: if they don't exceed BC
	 * limit, nothing here can either (just asserts would be enough).
	 * Currently we check for the limits, which provides additional
	 * protection against creating invalid bytecode due to compiler
	 * bugs.
	 */

	DUK_ASSERT_DISABLE((op_flags & 0xff) >= DUK_BC_OP_MIN);  /* unsigned */
	DUK_ASSERT((op_flags & 0xff) <= DUK_BC_OP_MAX);
	DUK_ASSERT(DUK__ISREG(a));
	DUK_ASSERT(b != -1);  /* Not 'none'. */
	DUK_ASSERT(c != -1);  /* Not 'none'. */

	/* Input shuffling happens before the actual operation, while output
	 * shuffling happens afterwards.  Output shuffling decisions are still
	 * made at the same time to reduce branch clutter; output shuffle decisions
	 * are recorded into X_out variables.
	 */

	/* Slot A: currently no support for reg/const. */

#if defined(DUK_USE_SHUFFLE_TORTURE)
	if (a <= DUK_BC_A_MAX && (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_A)) {
#else
	if (a <= DUK_BC_A_MAX) {
#endif
		;
	} else if (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_A) {
		DUK_D(DUK_DPRINT("out of regs: 'a' (reg) needs shuffling but shuffle prohibited, a: %ld", (long) a));
		goto error_outofregs;
	} else if (a <= DUK_BC_BC_MAX) {
		comp_ctx->curr_func.needs_shuffle = 1;
		tmp = comp_ctx->curr_func.shuffle1;
		if (op_flags & DUK__EMIT_FLAG_A_IS_SOURCE) {
			duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDREG, tmp, a));
		} else {
			/* Output shuffle needed after main operation */
			a_out = a;

			/* The DUK_OP_CSVAR output shuffle assumes shuffle registers are
			 * consecutive.
			 */
			DUK_ASSERT((comp_ctx->curr_func.shuffle1 == 0 && comp_ctx->curr_func.shuffle2 == 0) ||
			           (comp_ctx->curr_func.shuffle2 == comp_ctx->curr_func.shuffle1 + 1));
			if (op == DUK_OP_CSVAR) {
				/* For CSVAR the limit is one smaller because output shuffle
				 * must be able to express 'a + 1' in BC.
				 */
				if (a + 1 > DUK_BC_BC_MAX) {
					goto error_outofregs;
				}
			}
		}
		a = tmp;
	} else {
		DUK_D(DUK_DPRINT("out of regs: 'a' (reg) needs shuffling but does not fit into BC, a: %ld", (long) a));
		goto error_outofregs;
	}

	/* Slot B: reg/const support, mapped to bit 0 of opcode. */

	if ((b & DUK__CONST_MARKER) != 0) {
		DUK_ASSERT((op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_B) == 0);
		DUK_ASSERT((op_flags & DUK__EMIT_FLAG_B_IS_TARGET) == 0);
		b = b & ~DUK__CONST_MARKER;
#if defined(DUK_USE_SHUFFLE_TORTURE)
		if (0) {
#else
		if (b <= 0xff) {
#endif
			if (op_flags & DUK__EMIT_FLAG_BC_REGCONST) {
				/* Opcode follows B/C reg/const convention. */
				DUK_ASSERT((op & 0x01) == 0);
				ins |= DUK_ENC_OP_A_B_C(0x01, 0, 0, 0);  /* const flag for B */
			} else {
				DUK_D(DUK_DPRINT("B is const, opcode is not B/C reg/const: %x", op_flags));
			}
		} else if (b <= DUK_BC_BC_MAX) {
			comp_ctx->curr_func.needs_shuffle = 1;
			tmp = comp_ctx->curr_func.shuffle2;
			duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDCONST, tmp, b));
			b = tmp;
		} else {
			DUK_D(DUK_DPRINT("out of regs: 'b' (const) needs shuffling but does not fit into BC, b: %ld", (long) b));
			goto error_outofregs;
		}
	} else {
#if defined(DUK_USE_SHUFFLE_TORTURE)
		if (b <= 0xff && (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_B)) {
#else
		if (b <= 0xff) {
#endif
			;
		} else if (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_B) {
			if (b > DUK_BC_B_MAX) {
				/* Note: 0xff != DUK_BC_B_MAX */
				DUK_D(DUK_DPRINT("out of regs: 'b' (reg) needs shuffling but shuffle prohibited, b: %ld", (long) b));
				goto error_outofregs;
			}
		} else if (b <= DUK_BC_BC_MAX) {
			comp_ctx->curr_func.needs_shuffle = 1;
			tmp = comp_ctx->curr_func.shuffle2;
			if (op_flags & DUK__EMIT_FLAG_B_IS_TARGET) {
				/* Output shuffle needed after main operation */
				b_out = b;
			}
			if (!(op_flags & DUK__EMIT_FLAG_B_IS_TARGET)) {
				if (op == DUK_OP_MPUTOBJ || op == DUK_OP_MPUTARR) {
					/* Special handling for MPUTOBJ/MPUTARR shuffling.
					 * For each, slot B identifies the first register of a range
					 * of registers, so normal shuffling won't work.  Instead,
					 * an indirect version of the opcode is used.
					 */
					DUK_ASSERT((op_flags & DUK__EMIT_FLAG_B_IS_TARGET) == 0);
					duk__emit_load_int32_noshuffle(comp_ctx, tmp, b);
					DUK_ASSERT(DUK_OP_MPUTOBJI == DUK_OP_MPUTOBJ + 1);
					DUK_ASSERT(DUK_OP_MPUTARRI == DUK_OP_MPUTARR + 1);
					op_flags++;  /* indirect opcode follows direct */
				} else {
					duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDREG, tmp, b));
				}
			}
			b = tmp;
		} else {
			DUK_D(DUK_DPRINT("out of regs: 'b' (reg) needs shuffling but does not fit into BC, b: %ld", (long) b));
			goto error_outofregs;
		}
	}

	/* Slot C: reg/const support, mapped to bit 1 of opcode. */

	if ((c & DUK__CONST_MARKER) != 0) {
		DUK_ASSERT((op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_C) == 0);
		DUK_ASSERT((op_flags & DUK__EMIT_FLAG_C_IS_TARGET) == 0);
		c = c & ~DUK__CONST_MARKER;
#if defined(DUK_USE_SHUFFLE_TORTURE)
		if (0) {
#else
		if (c <= 0xff) {
#endif
			if (op_flags & DUK__EMIT_FLAG_BC_REGCONST) {
				/* Opcode follows B/C reg/const convention. */
				DUK_ASSERT((op & 0x02) == 0);
				ins |= DUK_ENC_OP_A_B_C(0x02, 0, 0, 0);  /* const flag for C */
			} else {
				DUK_D(DUK_DPRINT("C is const, opcode is not B/C reg/const: %x", op_flags));
			}
		} else if (c <= DUK_BC_BC_MAX) {
			comp_ctx->curr_func.needs_shuffle = 1;
			tmp = comp_ctx->curr_func.shuffle3;
			duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDCONST, tmp, c));
			c = tmp;
		} else {
			DUK_D(DUK_DPRINT("out of regs: 'c' (const) needs shuffling but does not fit into BC, c: %ld", (long) c));
			goto error_outofregs;
		}
	} else {
#if defined(DUK_USE_SHUFFLE_TORTURE)
		if (c <= 0xff && (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_C)) {
#else
		if (c <= 0xff) {
#endif
			;
		} else if (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_C) {
			if (c > DUK_BC_C_MAX) {
				/* Note: 0xff != DUK_BC_C_MAX */
				DUK_D(DUK_DPRINT("out of regs: 'c' (reg) needs shuffling but shuffle prohibited, c: %ld", (long) c));
				goto error_outofregs;
			}
		} else if (c <= DUK_BC_BC_MAX) {
			comp_ctx->curr_func.needs_shuffle = 1;
			tmp = comp_ctx->curr_func.shuffle3;
			if (op_flags & DUK__EMIT_FLAG_C_IS_TARGET) {
				/* Output shuffle needed after main operation */
				c_out = c;
			} else {
				duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDREG, tmp, c));
			}
			c = tmp;
		} else {
			DUK_D(DUK_DPRINT("out of regs: 'c' (reg) needs shuffling but does not fit into BC, c: %ld", (long) c));
			goto error_outofregs;
		}
	}

	/* Main operation */

	DUK_ASSERT(a >= DUK_BC_A_MIN);
	DUK_ASSERT(a <= DUK_BC_A_MAX);
	DUK_ASSERT(b >= DUK_BC_B_MIN);
	DUK_ASSERT(b <= DUK_BC_B_MAX);
	DUK_ASSERT(c >= DUK_BC_C_MIN);
	DUK_ASSERT(c <= DUK_BC_C_MAX);

	ins |= DUK_ENC_OP_A_B_C(op_flags & 0xff, a, b, c);
	duk__emit(comp_ctx, ins);

	/* NEXTENUM needs a jump slot right after the main instruction.
	 * When the JUMP is taken, output spilling is not needed so this
	 * workaround is possible.  The jump slot PC is exceptionally
	 * plumbed through comp_ctx to minimize call sites.
	 */
	if (op_flags & DUK__EMIT_FLAG_RESERVE_JUMPSLOT) {
		comp_ctx->emit_jumpslot_pc = duk__get_current_pc(comp_ctx);
		duk__emit_abc(comp_ctx, DUK_OP_JUMP, 0);
	}

	/* Output shuffling: only one output register is realistically possible.
	 *
	 * (Zero would normally be an OK marker value: if the target register
	 * was zero, it would never be shuffled.  But with DUK_USE_SHUFFLE_TORTURE
	 * this is no longer true, so use -1 as a marker instead.)
	 */

	if (a_out >= 0) {
		DUK_ASSERT(b_out < 0);
		DUK_ASSERT(c_out < 0);
		duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, a, a_out));

		if (op == DUK_OP_CSVAR) {
			/* Special handling for CSVAR shuffling.  The variable lookup
			 * results in a <value, this binding> pair in successive
			 * registers so use two shuffle registers and two output
			 * loads.  (In practice this is dead code because temp/const
			 * limit is reached first.)
			 */
			duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, a + 1, a_out + 1));
		}
	} else if (b_out >= 0) {
		DUK_ASSERT(a_out < 0);
		DUK_ASSERT(c_out < 0);
		duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, b, b_out));
	} else if (c_out >= 0) {
		DUK_ASSERT(b_out < 0);
		DUK_ASSERT(c_out < 0);
		duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, c, c_out));
	}

	return;

 error_outofregs:
	DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_REG_LIMIT);
	DUK_WO_NORETURN(return;);
}

/* For many of the helpers below it'd be technically correct to add
 * "no shuffle" flags for parameters passed in as zero.  For example,
 * duk__emit_a_b() should call duk__emit_a_b_c() with C set to 0, and
 * DUK__EMIT_FLAG_NO_SHUFFLE_C added to op_flags.  However, since the
 * C value is 0, it'll never get shuffled so adding the flag is just
 * unnecessary additional code.  This is unfortunately not true for
 * "shuffle torture" mode which needs special handling.
 */

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) {
#if defined(DUK_USE_SHUFFLE_TORTURE)
	op_flags |= DUK__EMIT_FLAG_NO_SHUFFLE_C;
#endif
	duk__emit_a_b_c(comp_ctx, op_flags, a, b, 0);
}

DUK_LOCAL void duk__emit_b_c(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t b, duk_regconst_t c) {
#if defined(DUK_USE_SHUFFLE_TORTURE)
	op_flags |= DUK__EMIT_FLAG_NO_SHUFFLE_A;
#endif
	duk__emit_a_b_c(comp_ctx, op_flags, 0, b, c);
}

#if 0  /* unused */
DUK_LOCAL void duk__emit_a(duk_compiler_ctx *comp_ctx, int op_flags, int a) {
#if defined(DUK_USE_SHUFFLE_TORTURE)
	op_flags |= DUK__EMIT_FLAG_NO_SHUFFLE_B | DUK__EMIT_FLAG_NO_SHUFFLE_C;
#endif
	duk__emit_a_b_c(comp_ctx, op_flags, a, 0, 0);
}
#endif

#if 0  /* unused */
DUK_LOCAL void duk__emit_b(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t b) {
#if defined(DUK_USE_SHUFFLE_TORTURE)
	op_flags |= DUK__EMIT_FLAG_NO_SHUFFLE_A | DUK__EMIT_FLAG_NO_SHUFFLE_C;
#endif
	duk__emit_a_b_c(comp_ctx, op_flags, 0, b, 0);
}
#endif

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) {
	duk_instr_t ins;
	duk_int_t tmp;

	/* allow caller to give a const number with the DUK__CONST_MARKER */
	DUK_ASSERT(bc != -1);  /* Not 'none'. */
	bc = bc & (~DUK__CONST_MARKER);

	DUK_ASSERT_DISABLE((op_flags & 0xff) >= DUK_BC_OP_MIN);  /* unsigned */
	DUK_ASSERT((op_flags & 0xff) <= DUK_BC_OP_MAX);
	DUK_ASSERT(bc >= DUK_BC_BC_MIN);
	DUK_ASSERT(bc <= DUK_BC_BC_MAX);
	DUK_ASSERT((bc & DUK__CONST_MARKER) == 0);

	if (bc <= DUK_BC_BC_MAX) {
		;
	} else {
		/* No BC shuffling now. */
		goto error_outofregs;
	}

#if defined(DUK_USE_SHUFFLE_TORTURE)
	if (a <= DUK_BC_A_MAX && (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_A)) {
#else
	if (a <= DUK_BC_A_MAX) {
#endif
		ins = DUK_ENC_OP_A_BC(op_flags & 0xff, a, bc);
		duk__emit(comp_ctx, ins);
	} else if (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_A) {
		goto error_outofregs;
	} else if ((op_flags & 0xf0U) == DUK_OP_CALL0) {
		comp_ctx->curr_func.needs_shuffle = 1;
		tmp = comp_ctx->curr_func.shuffle1;
		duk__emit_load_int32_noshuffle(comp_ctx, tmp, a);
		op_flags |= DUK_BC_CALL_FLAG_INDIRECT;
		ins = DUK_ENC_OP_A_BC(op_flags & 0xff, tmp, bc);
		duk__emit(comp_ctx, ins);
	} else if (a <= DUK_BC_BC_MAX) {
		comp_ctx->curr_func.needs_shuffle = 1;
		tmp = comp_ctx->curr_func.shuffle1;
		ins = DUK_ENC_OP_A_BC(op_flags & 0xff, tmp, bc);
		if (op_flags & DUK__EMIT_FLAG_A_IS_SOURCE) {
			duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDREG, tmp, a));
			duk__emit(comp_ctx, ins);
		} else {
			duk__emit(comp_ctx, ins);
			duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, tmp, a));
		}
	} else {
		goto error_outofregs;
	}
	return;

 error_outofregs:
	DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_REG_LIMIT);
	DUK_WO_NORETURN(return;);
}

DUK_LOCAL void duk__emit_bc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op, duk_regconst_t bc) {
#if defined(DUK_USE_SHUFFLE_TORTURE)
	op |= DUK__EMIT_FLAG_NO_SHUFFLE_A;
#endif
	duk__emit_a_bc(comp_ctx, op, 0, bc);
}

DUK_LOCAL void duk__emit_abc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op, duk_regconst_t abc) {
	duk_instr_t ins;

	DUK_ASSERT_DISABLE(op >= DUK_BC_OP_MIN);  /* unsigned */
	DUK_ASSERT(op <= DUK_BC_OP_MAX);
	DUK_ASSERT_DISABLE(abc >= DUK_BC_ABC_MIN);  /* unsigned */
	DUK_ASSERT(abc <= DUK_BC_ABC_MAX);
	DUK_ASSERT((abc & DUK__CONST_MARKER) == 0);
	DUK_ASSERT(abc != -1);  /* Not 'none'. */

	if (abc <= DUK_BC_ABC_MAX) {
		;
	} else {
		goto error_outofregs;
	}
	ins = DUK_ENC_OP_ABC(op, abc);
	DUK_DDD(DUK_DDDPRINT("duk__emit_abc: 0x%08lx line=%ld pc=%ld op=%ld (%!X) abc=%ld (%!I)",
	                     (unsigned long) ins, (long) comp_ctx->curr_token.start_line,
	                     (long) duk__get_current_pc(comp_ctx), (long) op, (long) op,
	                     (long) abc, (duk_instr_t) ins));
	duk__emit(comp_ctx, ins);
	return;

 error_outofregs:
	DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_REG_LIMIT);
	DUK_WO_NORETURN(return;);
}

DUK_LOCAL void duk__emit_load_int32_raw(duk_compiler_ctx *comp_ctx, duk_regconst_t reg, duk_int32_t val, duk_small_uint_t op_flags) {
	/* XXX: Shuffling support could be implemented here so that LDINT+LDINTX
	 * would only shuffle once (instead of twice).  The current code works
	 * though, and has a smaller compiler footprint.
	 */

	if ((val >= (duk_int32_t) DUK_BC_BC_MIN - (duk_int32_t) DUK_BC_LDINT_BIAS) &&
	    (val <= (duk_int32_t) DUK_BC_BC_MAX - (duk_int32_t) DUK_BC_LDINT_BIAS)) {
		DUK_DDD(DUK_DDDPRINT("emit LDINT to reg %ld for %ld", (long) reg, (long) val));
		duk__emit_a_bc(comp_ctx, DUK_OP_LDINT | op_flags, reg, (duk_regconst_t) (val + (duk_int32_t) DUK_BC_LDINT_BIAS));
	} else {
		duk_int32_t hi = val >> DUK_BC_LDINTX_SHIFT;
		duk_int32_t lo = val & ((((duk_int32_t) 1) << DUK_BC_LDINTX_SHIFT) - 1);
		DUK_ASSERT(lo >= 0);
		DUK_DDD(DUK_DDDPRINT("emit LDINT+LDINTX to reg %ld for %ld -> hi %ld, lo %ld",
		                     (long) reg, (long) val, (long) hi, (long) lo));
		duk__emit_a_bc(comp_ctx, DUK_OP_LDINT | op_flags, reg, (duk_regconst_t) (hi + (duk_int32_t) DUK_BC_LDINT_BIAS));
		duk__emit_a_bc(comp_ctx, DUK_OP_LDINTX | op_flags, reg, (duk_regconst_t) lo);
	}
}

DUK_LOCAL void duk__emit_load_int32(duk_compiler_ctx *comp_ctx, duk_regconst_t reg, duk_int32_t val) {
	duk__emit_load_int32_raw(comp_ctx, reg, val, 0 /*op_flags*/);
}

#if defined(DUK_USE_SHUFFLE_TORTURE)
/* Used by duk__emit*() calls so that we don't shuffle the loadints that
 * are needed to handle indirect opcodes.
 */
DUK_LOCAL void duk__emit_load_int32_noshuffle(duk_compiler_ctx *comp_ctx, duk_regconst_t reg, duk_int32_t val) {
	duk__emit_load_int32_raw(comp_ctx, reg, val, DUK__EMIT_FLAG_NO_SHUFFLE_A /*op_flags*/);
}
#else
DUK_LOCAL void duk__emit_load_int32_noshuffle(duk_compiler_ctx *comp_ctx, duk_regconst_t reg, duk_int32_t val) {
	/* When torture not enabled, can just use the same helper because
	 * 'reg' won't get spilled.
	 */
	DUK_ASSERT(reg <= DUK_BC_A_MAX);
	duk__emit_load_int32(comp_ctx, reg, val);
}
#endif

DUK_LOCAL void duk__emit_jump(duk_compiler_ctx *comp_ctx, duk_int_t target_pc) {
	duk_int_t curr_pc;
	duk_int_t offset;

	curr_pc = (duk_int_t) (DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) / sizeof(duk_compiler_instr));
	offset = (duk_int_t) target_pc - (duk_int_t) curr_pc - 1;
	DUK_ASSERT(offset + DUK_BC_JUMP_BIAS >= DUK_BC_ABC_MIN);
	DUK_ASSERT(offset + DUK_BC_JUMP_BIAS <= DUK_BC_ABC_MAX);
	duk__emit_abc(comp_ctx, DUK_OP_JUMP, (duk_regconst_t) (offset + DUK_BC_JUMP_BIAS));
}

DUK_LOCAL duk_int_t duk__emit_jump_empty(duk_compiler_ctx *comp_ctx) {
	duk_int_t ret;

	ret = duk__get_current_pc(comp_ctx);  /* useful for patching jumps later */
	duk__emit_op_only(comp_ctx, DUK_OP_JUMP);
	return ret;
}

/* Insert an empty jump in the middle of code emitted earlier.  This is
 * currently needed for compiling for-in.
 */
DUK_LOCAL void duk__insert_jump_entry(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc) {
#if defined(DUK_USE_PC2LINE)
	duk_int_t line;
#endif
	duk_compiler_instr *instr;
	duk_size_t offset;

	DUK_ASSERT(jump_pc >= 0);
	offset = (duk_size_t) jump_pc * sizeof(duk_compiler_instr);
	instr = (duk_compiler_instr *) (void *)
	        DUK_BW_INSERT_ENSURE_AREA(comp_ctx->thr,
	                                  &comp_ctx->curr_func.bw_code,
	                                  offset,
	                                  sizeof(duk_compiler_instr));

#if defined(DUK_USE_PC2LINE)
	line = comp_ctx->curr_token.start_line;  /* approximation, close enough */
#endif
	instr->ins = DUK_ENC_OP_ABC(DUK_OP_JUMP, 0);
#if defined(DUK_USE_PC2LINE)
	instr->line = (duk_uint32_t) line;
#endif

	DUK_BW_ADD_PTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code, sizeof(duk_compiler_instr));
	if (DUK_UNLIKELY(DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) > DUK_USE_ESBC_MAX_BYTES)) {
		goto fail_bc_limit;
	}
	return;

  fail_bc_limit:
	DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_BYTECODE_LIMIT);
	DUK_WO_NORETURN(return;);
}

/* Does not assume that jump_pc contains a DUK_OP_JUMP previously; this is intentional
 * to allow e.g. an INVALID opcode be overwritten with a JUMP (label management uses this).
 */
DUK_LOCAL void duk__patch_jump(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc, duk_int_t target_pc) {
	duk_compiler_instr *instr;
	duk_int_t offset;

	/* allow negative PCs, behave as a no-op */
	if (jump_pc < 0) {
		DUK_DDD(DUK_DDDPRINT("duk__patch_jump(): nop call, jump_pc=%ld (<0), target_pc=%ld",
		                     (long) jump_pc, (long) target_pc));
		return;
	}
	DUK_ASSERT(jump_pc >= 0);

	/* XXX: range assert */
	instr = duk__get_instr_ptr(comp_ctx, jump_pc);
	DUK_ASSERT(instr != NULL);

	/* XXX: range assert */
	offset = target_pc - jump_pc - 1;

	instr->ins = DUK_ENC_OP_ABC(DUK_OP_JUMP, offset + DUK_BC_JUMP_BIAS);
	DUK_DDD(DUK_DDDPRINT("duk__patch_jump(): jump_pc=%ld, target_pc=%ld, offset=%ld",
	                     (long) jump_pc, (long) target_pc, (long) offset));
}

DUK_LOCAL void duk__patch_jump_here(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc) {
	duk__patch_jump(comp_ctx, jump_pc, duk__get_current_pc(comp_ctx));
}

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) {
	duk_compiler_instr *instr;

	DUK_ASSERT(DUK__ISREG(reg_catch));

	instr = duk__get_instr_ptr(comp_ctx, ldconst_pc);
	DUK_ASSERT(DUK_DEC_OP(instr->ins) == DUK_OP_LDCONST);
	DUK_ASSERT(instr != NULL);
	if (const_varname & DUK__CONST_MARKER) {
		/* Have a catch variable. */
		const_varname = const_varname & (~DUK__CONST_MARKER);
		if (reg_catch > DUK_BC_BC_MAX || const_varname > DUK_BC_BC_MAX) {
			/* Catch attempts to use out-of-range reg/const.  Without this
			 * check Duktape 0.12.0 could generate invalid code which caused
			 * an assert failure on execution.  This error is triggered e.g.
			 * for functions with a lot of constants and a try-catch statement.
			 * Shuffling or opcode semantics change is needed to fix the issue.
			 * See: test-bug-trycatch-many-constants.js.
			 */
			DUK_D(DUK_DPRINT("failed to patch trycatch: flags=%ld, reg_catch=%ld, const_varname=%ld (0x%08lx)",
			                 (long) flags, (long) reg_catch, (long) const_varname, (long) const_varname));
			DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_REG_LIMIT);
			DUK_WO_NORETURN(return;);
		}
		instr->ins |= DUK_ENC_OP_A_BC(0, 0, const_varname);
	} else {
		/* No catch variable, e.g. a try-finally; replace LDCONST with
		 * NOP to avoid a bogus LDCONST.
		 */
		instr->ins = DUK_ENC_OP(DUK_OP_NOP);
	}

	instr = duk__get_instr_ptr(comp_ctx, trycatch_pc);
	DUK_ASSERT(instr != NULL);
	DUK_ASSERT_DISABLE(flags >= DUK_BC_A_MIN);
	DUK_ASSERT(flags <= DUK_BC_A_MAX);
	instr->ins = DUK_ENC_OP_A_BC(DUK_OP_TRYCATCH, flags, reg_catch);
}

DUK_LOCAL void duk__emit_if_false_skip(duk_compiler_ctx *comp_ctx, duk_regconst_t regconst) {
	duk_small_uint_t op;

	op = DUK__ISREG(regconst) ? DUK_OP_IFFALSE_R : DUK_OP_IFFALSE_C;
	duk__emit_bc(comp_ctx, op, regconst);  /* helper will remove const flag */
}

DUK_LOCAL void duk__emit_if_true_skip(duk_compiler_ctx *comp_ctx, duk_regconst_t regconst) {
	duk_small_uint_t op;

	op = DUK__ISREG(regconst) ? DUK_OP_IFTRUE_R : DUK_OP_IFTRUE_C;
	duk__emit_bc(comp_ctx, op, regconst);  /* helper will remove const flag */
}

DUK_LOCAL void duk__emit_invalid(duk_compiler_ctx *comp_ctx) {
	duk__emit_op_only(comp_ctx, DUK_OP_INVALID);
}

/*
 *  Peephole optimizer for finished bytecode.
 *
 *  Does not remove opcodes; currently only straightens out unconditional
 *  jump chains which are generated by several control structures.
 */

DUK_LOCAL void duk__peephole_optimize_bytecode(duk_compiler_ctx *comp_ctx) {
	duk_compiler_instr *bc;
	duk_small_uint_t iter;
	duk_int_t i, n;
	duk_int_t count_opt;

	bc = (duk_compiler_instr *) (void *) DUK_BW_GET_BASEPTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code);
#if defined(DUK_USE_BUFLEN16)
	/* No need to assert, buffer size maximum is 0xffff. */
#else
	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 */
#endif
	n = (duk_int_t) (DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) / sizeof(duk_compiler_instr));

	for (iter = 0; iter < DUK_COMPILER_PEEPHOLE_MAXITER; iter++) {
		count_opt = 0;

		for (i = 0; i < n; i++) {
			duk_instr_t ins;
			duk_int_t target_pc1;
			duk_int_t target_pc2;

			ins = bc[i].ins;
			if (DUK_DEC_OP(ins) != DUK_OP_JUMP) {
				continue;
			}

			target_pc1 = i + 1 + (duk_int_t) DUK_DEC_ABC(ins) - (duk_int_t) DUK_BC_JUMP_BIAS;
			DUK_DDD(DUK_DDDPRINT("consider jump at pc %ld; target_pc=%ld", (long) i, (long) target_pc1));
			DUK_ASSERT(target_pc1 >= 0);
			DUK_ASSERT(target_pc1 < n);

			/* Note: if target_pc1 == i, we'll optimize a jump to itself.
			 * This does not need to be checked for explicitly; the case
			 * is rare and max iter breaks us out.
			 */

			ins = bc[target_pc1].ins;
			if (DUK_DEC_OP(ins) != DUK_OP_JUMP) {
				continue;
			}

			target_pc2 = target_pc1 + 1 + (duk_int_t) DUK_DEC_ABC(ins) - (duk_int_t) DUK_BC_JUMP_BIAS;

			DUK_DDD(DUK_DDDPRINT("optimizing jump at pc %ld; old target is %ld -> new target is %ld",
			                     (long) i, (long) target_pc1, (long) target_pc2));

			bc[i].ins = DUK_ENC_OP_ABC(DUK_OP_JUMP, target_pc2 - (i + 1) + DUK_BC_JUMP_BIAS);

			count_opt++;
		}

		DUK_DD(DUK_DDPRINT("optimized %ld jumps on peephole round %ld", (long) count_opt, (long) (iter + 1)));

		if (count_opt == 0) {
			break;
		}
	}
}

/*
 *  Intermediate value helpers
 */

/* Flags for intermediate value coercions.  A flag for using a forced reg
 * is not needed, the forced_reg argument suffices and generates better
 * code (it is checked as it is used).
 */
/* XXX: DUK__IVAL_FLAG_REQUIRE_SHORT is passed but not currently implemented
 * by ispec/ivalue operations.
 */
#define DUK__IVAL_FLAG_ALLOW_CONST          (1 << 0)  /* allow a constant to be returned */
#define DUK__IVAL_FLAG_REQUIRE_TEMP         (1 << 1)  /* require a (mutable) temporary as a result (or a const if allowed) */
#define DUK__IVAL_FLAG_REQUIRE_SHORT        (1 << 2)  /* require a short (8-bit) reg/const which fits into bytecode B/C slot */

/* XXX: some code might benefit from DUK__SETTEMP_IFTEMP(thr,x) */

#if 0  /* enable manually for dumping */
#define DUK__DUMP_ISPEC(compctx,ispec) do { duk__dump_ispec((compctx), (ispec)); } while (0)
#define DUK__DUMP_IVALUE(compctx,ivalue) do { duk__dump_ivalue((compctx), (ivalue)); } while (0)

DUK_LOCAL void duk__dump_ispec(duk_compiler_ctx *comp_ctx, duk_ispec *x) {
	DUK_D(DUK_DPRINT("ispec dump: t=%ld regconst=0x%08lx, valstack_idx=%ld, value=%!T",
	                 (long) x->t, (unsigned long) x->regconst, (long) x->valstack_idx,
	                 duk_get_tval(comp_ctx->thr, x->valstack_idx)));
}
DUK_LOCAL void duk__dump_ivalue(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
	DUK_D(DUK_DPRINT("ivalue dump: t=%ld op=%ld "
	                 "x1={t=%ld regconst=0x%08lx valstack_idx=%ld value=%!T} "
	                 "x2={t=%ld regconst=0x%08lx valstack_idx=%ld value=%!T}",
		         (long) x->t, (long) x->op,
	                 (long) x->x1.t, (unsigned long) x->x1.regconst, (long) x->x1.valstack_idx,
	                 duk_get_tval(comp_ctx->thr, x->x1.valstack_idx),
	                 (long) x->x2.t, (unsigned long) x->x2.regconst, (long) x->x2.valstack_idx,
	                 duk_get_tval(comp_ctx->thr, x->x2.valstack_idx)));
}
#else
#define DUK__DUMP_ISPEC(comp_ctx,x) do {} while (0)
#define DUK__DUMP_IVALUE(comp_ctx,x) do {} while (0)
#endif

DUK_LOCAL void duk__ivalue_regconst(duk_ivalue *x, duk_regconst_t regconst) {
	x->t = DUK_IVAL_PLAIN;
	x->x1.t = DUK_ISPEC_REGCONST;
	x->x1.regconst = regconst;
}

DUK_LOCAL void duk__ivalue_plain_fromstack(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
	x->t = DUK_IVAL_PLAIN;
	x->x1.t = DUK_ISPEC_VALUE;
	duk_replace(comp_ctx->thr, x->x1.valstack_idx);
}

DUK_LOCAL void duk__ivalue_var_fromstack(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
	x->t = DUK_IVAL_VAR;
	x->x1.t = DUK_ISPEC_VALUE;
	duk_replace(comp_ctx->thr, x->x1.valstack_idx);
}

DUK_LOCAL_DECL void duk__ivalue_var_hstring(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_hstring *h) {
	DUK_ASSERT(h != NULL);
	duk_push_hstring(comp_ctx->thr, h);
	duk__ivalue_var_fromstack(comp_ctx, x);
}

DUK_LOCAL void duk__copy_ispec(duk_compiler_ctx *comp_ctx, duk_ispec *src, duk_ispec *dst) {
	dst->t = src->t;
	dst->regconst = src->regconst;
	duk_copy(comp_ctx->thr, src->valstack_idx, dst->valstack_idx);
}

DUK_LOCAL void duk__copy_ivalue(duk_compiler_ctx *comp_ctx, duk_ivalue *src, duk_ivalue *dst) {
	dst->t = src->t;
	dst->op = src->op;
	dst->x1.t = src->x1.t;
	dst->x1.regconst = src->x1.regconst;
	dst->x2.t = src->x2.t;
	dst->x2.regconst = src->x2.regconst;
	duk_copy(comp_ctx->thr, src->x1.valstack_idx, dst->x1.valstack_idx);
	duk_copy(comp_ctx->thr, src->x2.valstack_idx, dst->x2.valstack_idx);
}

DUK_LOCAL duk_regconst_t duk__alloctemps(duk_compiler_ctx *comp_ctx, duk_small_int_t num) {
	duk_regconst_t res;

	res = comp_ctx->curr_func.temp_next;
	comp_ctx->curr_func.temp_next += num;

	if (comp_ctx->curr_func.temp_next > DUK__MAX_TEMPS) {  /* == DUK__MAX_TEMPS is OK */
		DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_TEMP_LIMIT);
		DUK_WO_NORETURN(return 0;);
	}

	/* maintain highest 'used' temporary, needed to figure out nregs of function */
	if (comp_ctx->curr_func.temp_next > comp_ctx->curr_func.temp_max) {
		comp_ctx->curr_func.temp_max = comp_ctx->curr_func.temp_next;
	}

	return res;
}

DUK_LOCAL duk_regconst_t duk__alloctemp(duk_compiler_ctx *comp_ctx) {
	return duk__alloctemps(comp_ctx, 1);
}

DUK_LOCAL void duk__settemp_checkmax(duk_compiler_ctx *comp_ctx, duk_regconst_t temp_next) {
	comp_ctx->curr_func.temp_next = temp_next;
	if (temp_next > comp_ctx->curr_func.temp_max) {
		comp_ctx->curr_func.temp_max = temp_next;
	}
}

/* get const for value at valstack top */
DUK_LOCAL duk_regconst_t duk__getconst(duk_compiler_ctx *comp_ctx) {
	duk_hthread *thr = comp_ctx->thr;
	duk_compiler_func *f = &comp_ctx->curr_func;
	duk_tval *tv1;
	duk_int_t i, n, n_check;

	n = (duk_int_t) duk_get_length(thr, f->consts_idx);

	tv1 = DUK_GET_TVAL_NEGIDX(thr, -1);
	DUK_ASSERT(tv1 != NULL);

#if defined(DUK_USE_FASTINT)
	/* Explicit check for fastint downgrade. */
	DUK_TVAL_CHKFAST_INPLACE_SLOW(tv1);
#endif

	/* Sanity workaround for handling functions with a large number of
	 * constants at least somewhat reasonably.  Otherwise checking whether
	 * we already have the constant would grow very slow (as it is O(N^2)).
	 */
	n_check = (n > DUK__GETCONST_MAX_CONSTS_CHECK ? DUK__GETCONST_MAX_CONSTS_CHECK : n);
	for (i = 0; i < n_check; i++) {
		duk_tval *tv2 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, f->h_consts, i);

		/* Strict equality is NOT enough, because we cannot use the same
		 * constant for e.g. +0 and -0.
		 */
		if (duk_js_samevalue(tv1, tv2)) {
			DUK_DDD(DUK_DDDPRINT("reused existing constant for %!T -> const index %ld",
			                     (duk_tval *) tv1, (long) i));
			duk_pop(thr);
			return (duk_regconst_t) i | (duk_regconst_t) DUK__CONST_MARKER;
		}
	}

	if (n > DUK__MAX_CONSTS) {
		DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_CONST_LIMIT);
		DUK_WO_NORETURN(return 0;);
	}

	DUK_DDD(DUK_DDDPRINT("allocating new constant for %!T -> const index %ld",
	                     (duk_tval *) tv1, (long) n));
	(void) duk_put_prop_index(thr, f->consts_idx, (duk_uarridx_t) n);  /* invalidates tv1, tv2 */
	return (duk_regconst_t) n | (duk_regconst_t) DUK__CONST_MARKER;
}

DUK_LOCAL duk_bool_t duk__const_needs_refcount(duk_compiler_ctx *comp_ctx, duk_regconst_t rc) {
#if defined(DUK_USE_REFERENCE_COUNTING)
	duk_compiler_func *f = &comp_ctx->curr_func;
	duk_bool_t ret;

	DUK_ASSERT((rc & DUK__CONST_MARKER) == 0);  /* caller removes const marker */
	(void) duk_get_prop_index(comp_ctx->thr, f->consts_idx, (duk_uarridx_t) rc);
	ret = !duk_is_number(comp_ctx->thr, -1);  /* now only number/string, so conservative check */
	duk_pop(comp_ctx->thr);
	return ret;
#else
	DUK_UNREF(comp_ctx);
	DUK_UNREF(rc);
	DUK_ASSERT((rc & DUK__CONST_MARKER) == 0);  /* caller removes const marker */
	return 0;
#endif
}

/* Get the value represented by an duk_ispec to a register or constant.
 * The caller can control the result by indicating whether or not:
 *
 *   (1) a constant is allowed (sometimes the caller needs the result to
 *       be in a register)
 *
 *   (2) a temporary register is required (usually when caller requires
 *       the register to be safely mutable; normally either a bound
 *       register or a temporary register are both OK)
 *
 *   (3) a forced register target needs to be used
 *
 * Bytecode may be emitted to generate the necessary value.  The return
 * value is either a register or a constant.
 */

DUK_LOCAL
duk_regconst_t duk__ispec_toregconst_raw(duk_compiler_ctx *comp_ctx,
                                         duk_ispec *x,
                                         duk_regconst_t forced_reg,
                                         duk_small_uint_t flags) {
	duk_hthread *thr = comp_ctx->thr;

	DUK_DDD(DUK_DDDPRINT("duk__ispec_toregconst_raw(): x={%ld:%ld:%!T}, "
	                     "forced_reg=%ld, flags 0x%08lx: allow_const=%ld require_temp=%ld require_short=%ld",
	                     (long) x->t,
	                     (long) x->regconst,
	                     (duk_tval *) duk_get_tval(thr, x->valstack_idx),
	                     (long) forced_reg,
	                     (unsigned long) flags,
	                     (long) ((flags & DUK__IVAL_FLAG_ALLOW_CONST) ? 1 : 0),
	                     (long) ((flags & DUK__IVAL_FLAG_REQUIRE_TEMP) ? 1 : 0),
	                     (long) ((flags & DUK__IVAL_FLAG_REQUIRE_SHORT) ? 1 : 0)));

	switch (x->t) {
	case DUK_ISPEC_VALUE: {
		duk_tval *tv;

		tv = DUK_GET_TVAL_POSIDX(thr, x->valstack_idx);
		DUK_ASSERT(tv != NULL);

		switch (DUK_TVAL_GET_TAG(tv)) {
		case DUK_TAG_UNDEFINED: {
			/* Note: although there is no 'undefined' literal, undefined
			 * values can occur during compilation as a result of e.g.
			 * the 'void' operator.
			 */
			duk_regconst_t dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
			duk__emit_bc(comp_ctx, DUK_OP_LDUNDEF, dest);
			return dest;
		}
		case DUK_TAG_NULL: {
			duk_regconst_t dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
			duk__emit_bc(comp_ctx, DUK_OP_LDNULL, dest);
			return dest;
		}
		case DUK_TAG_BOOLEAN: {
			duk_regconst_t dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
			duk__emit_bc(comp_ctx,
			             (DUK_TVAL_GET_BOOLEAN(tv) ? DUK_OP_LDTRUE : DUK_OP_LDFALSE),
			             dest);
			return dest;
		}
		case DUK_TAG_POINTER: {
			DUK_UNREACHABLE();
			break;
		}
		case DUK_TAG_STRING: {
			duk_hstring *h;
			duk_regconst_t dest;
			duk_regconst_t constidx;

			h = DUK_TVAL_GET_STRING(tv);
			DUK_UNREF(h);
			DUK_ASSERT(h != NULL);

#if 0  /* XXX: to be implemented? */
			/* Use special opcodes to load short strings */
			if (DUK_HSTRING_GET_BYTELEN(h) <= 2) {
				/* Encode into a single opcode (18 bits can encode 1-2 bytes + length indicator) */
			} else if (DUK_HSTRING_GET_BYTELEN(h) <= 6) {
				/* Encode into a double constant (53 bits can encode 6*8 = 48 bits + 3-bit length */
			}
#endif
			duk_dup(thr, x->valstack_idx);
			constidx = duk__getconst(comp_ctx);

			if (flags & DUK__IVAL_FLAG_ALLOW_CONST) {
				return constidx;
			}

			dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
			duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, dest, constidx);
			return dest;
		}
		case DUK_TAG_OBJECT: {
			DUK_UNREACHABLE();
			break;
		}
		case DUK_TAG_BUFFER: {
			DUK_UNREACHABLE();
			break;
		}
		case DUK_TAG_LIGHTFUNC: {
			DUK_UNREACHABLE();
			break;
		}
#if defined(DUK_USE_FASTINT)
		case DUK_TAG_FASTINT:
#endif
		default: {
			/* number */
			duk_regconst_t dest;
			duk_regconst_t constidx;
			duk_double_t dval;
			duk_int32_t ival;

			DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
			dval = DUK_TVAL_GET_NUMBER(tv);

			if (!(flags & DUK__IVAL_FLAG_ALLOW_CONST)) {
				/* A number can be loaded either through a constant, using
				 * LDINT, or using LDINT+LDINTX.  LDINT is always a size win,
				 * LDINT+LDINTX is not if the constant is used multiple times.
				 * Currently always prefer LDINT+LDINTX over a double constant.
				 */

				if (duk_is_whole_get_int32_nonegzero(dval, &ival)) {
					dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
					duk__emit_load_int32(comp_ctx, dest, ival);
					return dest;
				}
			}

			duk_dup(thr, x->valstack_idx);
			constidx = duk__getconst(comp_ctx);

			if (flags & DUK__IVAL_FLAG_ALLOW_CONST) {
				return constidx;
			} else {
				dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
				duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, dest, constidx);
				return dest;
			}
		}
		}  /* end switch */
		goto fail_internal;  /* never here */
	}
	case DUK_ISPEC_REGCONST: {
		if (forced_reg >= 0) {
			if (DUK__ISCONST(x->regconst)) {
				duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, forced_reg, x->regconst);
			} else if (x->regconst != forced_reg) {
				duk__emit_a_bc(comp_ctx, DUK_OP_LDREG, forced_reg, x->regconst);
			} else {
				; /* already in correct reg */
			}
			return forced_reg;
		}

		DUK_ASSERT(forced_reg < 0);
		if (DUK__ISCONST(x->regconst)) {
			if (!(flags & DUK__IVAL_FLAG_ALLOW_CONST)) {
				duk_regconst_t dest = DUK__ALLOCTEMP(comp_ctx);
				duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, dest, x->regconst);
				return dest;
			}
			return x->regconst;
		}

		DUK_ASSERT(forced_reg < 0 && !DUK__ISCONST(x->regconst));
		if ((flags & DUK__IVAL_FLAG_REQUIRE_TEMP) && !DUK__ISREG_TEMP(comp_ctx, x->regconst)) {
			duk_regconst_t dest = DUK__ALLOCTEMP(comp_ctx);
			duk__emit_a_bc(comp_ctx, DUK_OP_LDREG, dest, x->regconst);
			return dest;
		}
		return x->regconst;
	}
	default: {
		break;  /* never here */
	}
	}

 fail_internal:
	DUK_ERROR_INTERNAL(thr);
	DUK_WO_NORETURN(return 0;);
}

DUK_LOCAL void duk__ispec_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ispec *x, duk_regconst_t forced_reg) {
	DUK_ASSERT(forced_reg >= 0);
	(void) duk__ispec_toregconst_raw(comp_ctx, x, forced_reg, 0 /*flags*/);
}

/* Coerce an duk_ivalue to a 'plain' value by generating the necessary
 * arithmetic operations, property access, or variable access bytecode.
 * The duk_ivalue argument ('x') is converted into a plain value as a
 * side effect.
 */
DUK_LOCAL void duk__ivalue_toplain_raw(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_regconst_t forced_reg) {
	duk_hthread *thr = comp_ctx->thr;

	DUK_DDD(DUK_DDDPRINT("duk__ivalue_toplain_raw(): x={t=%ld,op=%ld,x1={%ld:%ld:%!T},x2={%ld:%ld:%!T}}, "
	                     "forced_reg=%ld",
	                     (long) x->t, (long) x->op,
	                     (long) x->x1.t, (long) x->x1.regconst,
	                     (duk_tval *) duk_get_tval(thr, x->x1.valstack_idx),
	                     (long) x->x2.t, (long) x->x2.regconst,
	                     (duk_tval *) duk_get_tval(thr, x->x2.valstack_idx),
	                     (long) forced_reg));

	switch (x->t) {
	case DUK_IVAL_PLAIN: {
		return;
	}
	/* XXX: support unary arithmetic ivalues (useful?) */
	case DUK_IVAL_ARITH: {
		duk_regconst_t arg1;
		duk_regconst_t arg2;
		duk_regconst_t dest;
		duk_tval *tv1;
		duk_tval *tv2;

		DUK_DDD(DUK_DDDPRINT("arith to plain conversion"));

		/* inline arithmetic check for constant values */
		/* XXX: use the exactly same arithmetic function here as in executor */
		if (x->x1.t == DUK_ISPEC_VALUE && x->x2.t == DUK_ISPEC_VALUE && x->t == DUK_IVAL_ARITH) {
			tv1 = DUK_GET_TVAL_POSIDX(thr, x->x1.valstack_idx);
			tv2 = DUK_GET_TVAL_POSIDX(thr, x->x2.valstack_idx);
			DUK_ASSERT(tv1 != NULL);
			DUK_ASSERT(tv2 != NULL);

			DUK_DDD(DUK_DDDPRINT("arith: tv1=%!T, tv2=%!T",
			                     (duk_tval *) tv1,
			                     (duk_tval *) tv2));

			if (DUK_TVAL_IS_NUMBER(tv1) && DUK_TVAL_IS_NUMBER(tv2)) {
				duk_double_t d1 = DUK_TVAL_GET_NUMBER(tv1);
				duk_double_t d2 = DUK_TVAL_GET_NUMBER(tv2);
				duk_double_t d3;
				duk_bool_t accept_fold = 1;

				DUK_DDD(DUK_DDDPRINT("arith inline check: d1=%lf, d2=%lf, op=%ld",
				                     (double) d1, (double) d2, (long) x->op));
				switch (x->op) {
				case DUK_OP_ADD: {
					d3 = d1 + d2;
					break;
				}
				case DUK_OP_SUB: {
					d3 = d1 - d2;
					break;
				}
				case DUK_OP_MUL: {
					d3 = d1 * d2;
					break;
				}
				case DUK_OP_DIV: {
					/* Division-by-zero is undefined
					 * behavior, so rely on a helper.
					 */
					d3 = duk_double_div(d1, d2);
					break;
				}
				case DUK_OP_EXP: {
					d3 = (duk_double_t) duk_js_arith_pow((double) d1, (double) d2);
					break;
				}
				default: {
					d3 = 0.0;  /* Won't be used, but silence MSVC /W4 warning. */
					accept_fold = 0;
					break;
				}
				}

				if (accept_fold) {
					duk_double_union du;
					du.d = d3;
					DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);
					d3 = du.d;

					x->t = DUK_IVAL_PLAIN;
					DUK_ASSERT(x->x1.t == DUK_ISPEC_VALUE);
					DUK_TVAL_SET_NUMBER(tv1, d3);  /* old value is number: no refcount */
					return;
				}
			} else if (x->op == DUK_OP_ADD && DUK_TVAL_IS_STRING(tv1) && DUK_TVAL_IS_STRING(tv2)) {
				/* Inline string concatenation.  No need to check for
				 * symbols, as all inputs are valid ECMAScript strings.
				 */
				duk_dup(thr, x->x1.valstack_idx);
				duk_dup(thr, x->x2.valstack_idx);
				duk_concat(thr, 2);
				duk_replace(thr, x->x1.valstack_idx);
				x->t = DUK_IVAL_PLAIN;
				DUK_ASSERT(x->x1.t == DUK_ISPEC_VALUE);
				return;
			}
		}

		arg1 = duk__ispec_toregconst_raw(comp_ctx, &x->x1, -1, DUK__IVAL_FLAG_ALLOW_CONST | DUK__IVAL_FLAG_REQUIRE_SHORT /*flags*/);
		arg2 = duk__ispec_toregconst_raw(comp_ctx, &x->x2, -1, DUK__IVAL_FLAG_ALLOW_CONST | DUK__IVAL_FLAG_REQUIRE_SHORT /*flags*/);

		/* If forced reg, use it as destination.  Otherwise try to
		 * use either coerced ispec if it is a temporary.
		 */
		if (forced_reg >= 0) {
			dest = forced_reg;
		} else if (DUK__ISREG_TEMP(comp_ctx, arg1)) {
			dest = arg1;
		} else if (DUK__ISREG_TEMP(comp_ctx, arg2)) {
			dest = arg2;
		} else {
			dest = DUK__ALLOCTEMP(comp_ctx);
		}

		DUK_ASSERT(DUK__ISREG(dest));
		duk__emit_a_b_c(comp_ctx, x->op | DUK__EMIT_FLAG_BC_REGCONST, dest, arg1, arg2);

		duk__ivalue_regconst(x, dest);
		return;
	}
	case DUK_IVAL_PROP: {
		/* XXX: very similar to DUK_IVAL_ARITH - merge? */
		duk_regconst_t arg1;
		duk_regconst_t arg2;
		duk_regconst_t dest;

		/* Need a short reg/const, does not have to be a mutable temp. */
		arg1 = duk__ispec_toregconst_raw(comp_ctx, &x->x1, -1, DUK__IVAL_FLAG_ALLOW_CONST | DUK__IVAL_FLAG_REQUIRE_SHORT /*flags*/);
		arg2 = duk__ispec_toregconst_raw(comp_ctx, &x->x2, -1, DUK__IVAL_FLAG_ALLOW_CONST | DUK__IVAL_FLAG_REQUIRE_SHORT /*flags*/);

		/* Pick a destination register.  If either base value or key
		 * happens to be a temp value, reuse it as the destination.
		 *
		 * XXX: The temp must be a "mutable" one, i.e. such that no
		 * other expression is using it anymore.  Here this should be
		 * the case because the value of a property access expression
		 * is neither the base nor the key, but the lookup result.
		 */

		if (forced_reg >= 0) {
			dest = forced_reg;
		} else if (DUK__ISREG_TEMP(comp_ctx, arg1)) {
			dest = arg1;
		} else if (DUK__ISREG_TEMP(comp_ctx, arg2)) {
			dest = arg2;
		} else {
			dest = DUK__ALLOCTEMP(comp_ctx);
		}

		duk__emit_a_b_c(comp_ctx,
		                DUK_OP_GETPROP | DUK__EMIT_FLAG_BC_REGCONST,
		                dest,
		                arg1,
		                arg2);

		duk__ivalue_regconst(x, dest);
		return;
	}
	case DUK_IVAL_VAR: {
		/* x1 must be a string */
		duk_regconst_t dest;
		duk_regconst_t reg_varbind;
		duk_regconst_t rc_varname;

		DUK_ASSERT(x->x1.t == DUK_ISPEC_VALUE);

		duk_dup(thr, x->x1.valstack_idx);
		if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
			duk__ivalue_regconst(x, reg_varbind);
		} else {
			dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
			duk__emit_a_bc(comp_ctx, DUK_OP_GETVAR, dest, rc_varname);
			duk__ivalue_regconst(x, dest);
		}
		return;
	}
	case DUK_IVAL_NONE:
	default: {
		DUK_D(DUK_DPRINT("invalid ivalue type: %ld", (long) x->t));
		break;
	}
	}

	DUK_ERROR_INTERNAL(thr);
	DUK_WO_NORETURN(return;);
}

/* evaluate to plain value, no forced register (temp/bound reg both ok) */
DUK_LOCAL void duk__ivalue_toplain(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
	duk__ivalue_toplain_raw(comp_ctx, x, -1 /*forced_reg*/);
}

/* evaluate to final form (e.g. coerce GETPROP to code), throw away temp */
DUK_LOCAL void duk__ivalue_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
	duk_regconst_t temp;

	/* If duk__ivalue_toplain_raw() allocates a temp, forget it and
	 * restore next temp state.
	 */
	temp = DUK__GETTEMP(comp_ctx);
	duk__ivalue_toplain_raw(comp_ctx, x, -1 /*forced_reg*/);
	DUK__SETTEMP(comp_ctx, temp);
}

/* Coerce an duk_ivalue to a register or constant; result register may
 * be a temp or a bound register.
 *
 * The duk_ivalue argument ('x') is converted into a regconst as a
 * side effect.
 */
DUK_LOCAL
duk_regconst_t duk__ivalue_toregconst_raw(duk_compiler_ctx *comp_ctx,
                                          duk_ivalue *x,
                                          duk_regconst_t forced_reg,
                                          duk_small_uint_t flags) {
	duk_hthread *thr = comp_ctx->thr;
	duk_regconst_t reg;
	DUK_UNREF(thr);

	DUK_DDD(DUK_DDDPRINT("duk__ivalue_toregconst_raw(): x={t=%ld,op=%ld,x1={%ld:%ld:%!T},x2={%ld:%ld:%!T}}, "
	                     "forced_reg=%ld, flags 0x%08lx: allow_const=%ld require_temp=%ld require_short=%ld",
	                     (long) x->t, (long) x->op,
	                     (long) x->x1.t, (long) x->x1.regconst,
	                     (duk_tval *) duk_get_tval(thr, x->x1.valstack_idx),
	                     (long) x->x2.t, (long) x->x2.regconst,
	                     (duk_tval *) duk_get_tval(thr, x->x2.valstack_idx),
	                     (long) forced_reg,
	                     (unsigned long) flags,
	                     (long) ((flags & DUK__IVAL_FLAG_ALLOW_CONST) ? 1 : 0),
	                     (long) ((flags & DUK__IVAL_FLAG_REQUIRE_TEMP) ? 1 : 0),
	                     (long) ((flags & DUK__IVAL_FLAG_REQUIRE_SHORT) ? 1 : 0)));

	/* first coerce to a plain value */
	duk__ivalue_toplain_raw(comp_ctx, x, forced_reg);
	DUK_ASSERT(x->t == DUK_IVAL_PLAIN);

	/* then to a register */
	reg = duk__ispec_toregconst_raw(comp_ctx, &x->x1, forced_reg, flags);
	duk__ivalue_regconst(x, reg);

	return reg;
}

DUK_LOCAL duk_regconst_t duk__ivalue_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
	return duk__ivalue_toregconst_raw(comp_ctx, x, -1, 0 /*flags*/);
}

#if 0  /* unused */
DUK_LOCAL duk_regconst_t duk__ivalue_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
	return duk__ivalue_toregconst_raw(comp_ctx, x, -1, DUK__IVAL_FLAG_REQUIRE_TEMP /*flags*/);
}
#endif

DUK_LOCAL void duk__ivalue_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_int_t forced_reg) {
	DUK_ASSERT(forced_reg >= 0);
	(void) duk__ivalue_toregconst_raw(comp_ctx, x, forced_reg, 0 /*flags*/);
}

DUK_LOCAL duk_regconst_t duk__ivalue_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
	return duk__ivalue_toregconst_raw(comp_ctx, x, -1, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
}

DUK_LOCAL duk_regconst_t duk__ivalue_totempconst(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
	return duk__ivalue_toregconst_raw(comp_ctx, x, -1, DUK__IVAL_FLAG_ALLOW_CONST | DUK__IVAL_FLAG_REQUIRE_TEMP /*flags*/);
}

/* The issues below can be solved with better flags */

/* XXX: many operations actually want toforcedtemp() -- brand new temp? */
/* XXX: need a toplain_ignore() which will only coerce a value to a temp
 * register if it might have a side effect.  Side-effect free values do not
 * need to be coerced.
 */

/*
 *  Identifier handling
 */

DUK_LOCAL duk_regconst_t duk__lookup_active_register_binding(duk_compiler_ctx *comp_ctx) {
	duk_hthread *thr = comp_ctx->thr;
	duk_hstring *h_varname;
	duk_regconst_t ret;

	DUK_DDD(DUK_DDDPRINT("resolving identifier reference to '%!T'",
	                     (duk_tval *) duk_get_tval(thr, -1)));

	/*
	 *  Special name handling
	 */

	h_varname = duk_known_hstring(thr, -1);

	if (h_varname == DUK_HTHREAD_STRING_LC_ARGUMENTS(thr)) {
		DUK_DDD(DUK_DDDPRINT("flagging function as accessing 'arguments'"));
		comp_ctx->curr_func.id_access_arguments = 1;
	}

	/*
	 *  Inside one or more 'with' statements fall back to slow path always.
	 *  (See e.g. test-stmt-with.js.)
	 */

	if (comp_ctx->curr_func.with_depth > 0) {
		DUK_DDD(DUK_DDDPRINT("identifier lookup inside a 'with' -> fall back to slow path"));
		goto slow_path_own;
	}

	/*
	 *  Any catch bindings ("catch (e)") also affect identifier binding.
	 *
	 *  Currently, the varmap is modified for the duration of the catch
	 *  clause to ensure any identifier accesses with the catch variable
	 *  name will use slow path.
	 */

	duk_get_prop(thr, comp_ctx->curr_func.varmap_idx);
	if (duk_is_number(thr, -1)) {
		ret = duk_to_int(thr, -1);
		duk_pop(thr);
	} else {
		duk_pop(thr);
		if (comp_ctx->curr_func.catch_depth > 0 || comp_ctx->curr_func.with_depth > 0) {
			DUK_DDD(DUK_DDDPRINT("slow path access from inside a try-catch or with needs _Varmap"));
			goto slow_path_own;
		} else {
			/* In this case we're doing a variable lookup that doesn't
			 * match our own variables, so _Varmap won't be needed at
			 * run time.
			 */
			DUK_DDD(DUK_DDDPRINT("slow path access outside of try-catch and with, no need for _Varmap"));
			goto slow_path_notown;
		}
	}

	DUK_DDD(DUK_DDDPRINT("identifier lookup -> reg %ld", (long) ret));
	return ret;

 slow_path_notown:
	DUK_DDD(DUK_DDDPRINT("identifier lookup -> slow path, not own variable"));

	comp_ctx->curr_func.id_access_slow = 1;
	return (duk_regconst_t) -1;

 slow_path_own:
	DUK_DDD(DUK_DDDPRINT("identifier lookup -> slow path, may be own variable"));

	comp_ctx->curr_func.id_access_slow = 1;
	comp_ctx->curr_func.id_access_slow_own = 1;
	return (duk_regconst_t) -1;
}

/* Lookup an identifier name in the current varmap, indicating whether the
 * identifier is register-bound and if not, allocating a constant for the
 * identifier name.  Returns 1 if register-bound, 0 otherwise.  Caller can
 * also check (out_reg_varbind >= 0) to check whether or not identifier is
 * register bound.  The caller must NOT use out_rc_varname at all unless
 * return code is 0 or out_reg_varbind is < 0; this is becuase out_rc_varname
 * is unsigned and doesn't have a "unused" / none value.
 */
DUK_LOCAL duk_bool_t duk__lookup_lhs(duk_compiler_ctx *comp_ctx, duk_regconst_t *out_reg_varbind, duk_regconst_t *out_rc_varname) {
	duk_hthread *thr = comp_ctx->thr;
	duk_regconst_t reg_varbind;
	duk_regconst_t rc_varname;

	/* [ ... varname ] */

	duk_dup_top(thr);
	reg_varbind = duk__lookup_active_register_binding(comp_ctx);

	if (reg_varbind >= 0) {
		*out_reg_varbind = reg_varbind;
		*out_rc_varname = 0;  /* duk_regconst_t is unsigned, so use 0 as dummy value (ignored by caller) */
		duk_pop(thr);
		return 1;
	} else {
		rc_varname = duk__getconst(comp_ctx);
		*out_reg_varbind = -1;
		*out_rc_varname = rc_varname;
		return 0;
	}
}

/*
 *  Label handling
 *
 *  Labels are initially added with flags prohibiting both break and continue.
 *  When the statement type is finally uncovered (after potentially multiple
 *  labels), all the labels are updated to allow/prohibit break and continue.
 */

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) {
	duk_hthread *thr = comp_ctx->thr;
	duk_size_t n;
	duk_size_t new_size;
	duk_uint8_t *p;
	duk_labelinfo *li_start, *li;

	/* Duplicate (shadowing) labels are not allowed, except for the empty
	 * labels (which are used as default labels for switch and iteration
	 * statements).
	 *
	 * We could also allow shadowing of non-empty pending labels without any
	 * other issues than breaking the required label shadowing requirements
	 * of the E5 specification, see Section 12.12.
	 */

	p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, comp_ctx->curr_func.h_labelinfos);
	li_start = (duk_labelinfo *) (void *) p;
	li = (duk_labelinfo *) (void *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos));
	n = (duk_size_t) (li - li_start);

	while (li > li_start) {
		li--;

		if (li->h_label == h_label && h_label != DUK_HTHREAD_STRING_EMPTY_STRING(thr)) {
			DUK_ERROR_SYNTAX(thr, DUK_STR_DUPLICATE_LABEL);
			DUK_WO_NORETURN(return;);
		}
	}

	duk_push_hstring(thr, h_label);
	DUK_ASSERT(n <= DUK_UARRIDX_MAX);  /* label limits */
	(void) duk_put_prop_index(thr, comp_ctx->curr_func.labelnames_idx, (duk_uarridx_t) n);

	new_size = (n + 1) * sizeof(duk_labelinfo);
	duk_hbuffer_resize(thr, comp_ctx->curr_func.h_labelinfos, new_size);
	/* XXX: slack handling, slow now */

	/* relookup after possible realloc */
	p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, comp_ctx->curr_func.h_labelinfos);
	li_start = (duk_labelinfo *) (void *) p;
	DUK_UNREF(li_start);  /* silence scan-build warning */
	li = (duk_labelinfo *) (void *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos));
	li--;

	/* Labels can be used for iteration statements but also for other statements,
	 * in particular a label can be used for a block statement.  All cases of a
	 * named label accept a 'break' so that flag is set here.  Iteration statements
	 * also allow 'continue', so that flag is updated when we figure out the
	 * statement type.
	 */

	li->flags = DUK_LABEL_FLAG_ALLOW_BREAK;
	li->label_id = label_id;
	li->h_label = h_label;
	li->catch_depth = comp_ctx->curr_func.catch_depth;   /* catch depth from current func */
	li->pc_label = pc_label;

	DUK_DDD(DUK_DDDPRINT("registered label: flags=0x%08lx, id=%ld, name=%!O, catch_depth=%ld, pc_label=%ld",
	                     (unsigned long) li->flags, (long) li->label_id, (duk_heaphdr *) li->h_label,
	                     (long) li->catch_depth, (long) li->pc_label));
}

/* Update all labels with matching label_id. */
DUK_LOCAL void duk__update_label_flags(duk_compiler_ctx *comp_ctx, duk_int_t label_id, duk_small_uint_t flags) {
	duk_uint8_t *p;
	duk_labelinfo *li_start, *li;

	p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(comp_ctx->thr->heap, comp_ctx->curr_func.h_labelinfos);
	li_start = (duk_labelinfo *) (void *) p;
	li = (duk_labelinfo *) (void *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos));

	/* Match labels starting from latest; once label_id no longer matches, we can
	 * safely exit without checking the rest of the labels (only the topmost labels
	 * are ever updated).
	 */
	while (li > li_start) {
		li--;

		if (li->label_id != label_id) {
			break;
		}

		DUK_DDD(DUK_DDDPRINT("updating (overwriting) label flags for li=%p, label_id=%ld, flags=%ld",
		                     (void *) li, (long) label_id, (long) flags));

		li->flags = flags;
	}
}

/* Lookup active label information.  Break/continue distinction is necessary to handle switch
 * statement related labels correctly: a switch will only catch a 'break', not a 'continue'.
 *
 * An explicit label cannot appear multiple times in the active set, but empty labels (unlabelled
 * iteration and switch statements) can.  A break will match the closest unlabelled or labelled
 * statement.  A continue will match the closest unlabelled or labelled iteration statement.  It is
 * a syntax error if a continue matches a labelled switch statement; because an explicit label cannot
 * be duplicated, the continue cannot match any valid label outside the switch.
 *
 * A side effect of these rules is that a LABEL statement related to a switch should never actually
 * catch a continue abrupt completion at run-time.  Hence an INVALID opcode can be placed in the
 * continue slot of the switch's LABEL statement.
 */

/* XXX: awkward, especially the bunch of separate output values -> output struct? */
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) {
	duk_hthread *thr = comp_ctx->thr;
	duk_uint8_t *p;
	duk_labelinfo *li_start, *li_end, *li;
	duk_bool_t match = 0;

	DUK_DDD(DUK_DDDPRINT("looking up active label: label='%!O', is_break=%ld",
	                     (duk_heaphdr *) h_label, (long) is_break));

	DUK_UNREF(thr);

	p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, comp_ctx->curr_func.h_labelinfos);
	li_start = (duk_labelinfo *) (void *) p;
	li_end = (duk_labelinfo *) (void *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos));
	li = li_end;

	/* Match labels starting from latest label because there can be duplicate empty
	 * labels in the label set.
	 */
	while (li > li_start) {
		li--;

		if (li->h_label != h_label) {
			DUK_DDD(DUK_DDDPRINT("labelinfo[%ld] ->'%!O' != %!O",
			                     (long) (li - li_start),
			                     (duk_heaphdr *) li->h_label,
			                     (duk_heaphdr *) h_label));
			continue;
		}

		DUK_DDD(DUK_DDDPRINT("labelinfo[%ld] -> '%!O' label name matches (still need to check type)",
		                     (long) (li - li_start), (duk_heaphdr *) h_label));

		/* currently all labels accept a break, so no explicit check for it now */
		DUK_ASSERT(li->flags & DUK_LABEL_FLAG_ALLOW_BREAK);

		if (is_break) {
			/* break matches always */
			match = 1;
			break;
		} else if (li->flags & DUK_LABEL_FLAG_ALLOW_CONTINUE) {
			/* iteration statements allow continue */
			match = 1;
			break;
		} else {
			/* continue matched this label -- we can only continue if this is the empty
			 * label, for which duplication is allowed, and thus there is hope of
			 * finding a match deeper in the label stack.
			 */
			if (h_label != DUK_HTHREAD_STRING_EMPTY_STRING(thr)) {
				DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_LABEL);
				DUK_WO_NORETURN(return;);
			} else {
				DUK_DDD(DUK_DDDPRINT("continue matched an empty label which does not "
				                     "allow a continue -> continue lookup deeper in label stack"));
			}
		}
	}
	/* XXX: match flag is awkward, rework */
	if (!match) {
		DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_LABEL);
		DUK_WO_NORETURN(return;);
	}

	DUK_DDD(DUK_DDDPRINT("label match: %!O -> label_id %ld, catch_depth=%ld, pc_label=%ld",
	                     (duk_heaphdr *) h_label, (long) li->label_id,
	                     (long) li->catch_depth, (long) li->pc_label));

	*out_label_id = li->label_id;
	*out_label_catch_depth = li->catch_depth;
	*out_label_pc = li->pc_label;
	*out_is_closest = (li == li_end - 1);
}

DUK_LOCAL void duk__reset_labels_to_length(duk_compiler_ctx *comp_ctx, duk_size_t len) {
	duk_hthread *thr = comp_ctx->thr;

	duk_set_length(thr, comp_ctx->curr_func.labelnames_idx, len);
	duk_hbuffer_resize(thr, comp_ctx->curr_func.h_labelinfos, sizeof(duk_labelinfo) * len);
}

/*
 *  Expression parsing: duk__expr_nud(), duk__expr_led(), duk__expr_lbp(), and helpers.
 *
 *  - duk__expr_nud(): ("null denotation"): process prev_token as a "start" of an expression (e.g. literal)
 *  - duk__expr_led(): ("left denotation"): process prev_token in the "middle" of an expression (e.g. operator)
 *  - duk__expr_lbp(): ("left-binding power"): return left-binding power of curr_token
 */

/* object literal key tracking flags */
#define DUK__OBJ_LIT_KEY_PLAIN  (1 << 0)  /* key encountered as a plain property */
#define DUK__OBJ_LIT_KEY_GET    (1 << 1)  /* key encountered as a getter */
#define DUK__OBJ_LIT_KEY_SET    (1 << 2)  /* key encountered as a setter */

DUK_LOCAL void duk__nud_array_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
	duk_hthread *thr = comp_ctx->thr;
	duk_regconst_t reg_obj;                 /* result reg */
	duk_regconst_t reg_temp;                /* temp reg */
	duk_regconst_t temp_start;              /* temp reg value for start of loop */
	duk_small_uint_t max_init_values;  /* max # of values initialized in one MPUTARR set */
	duk_small_uint_t num_values;       /* number of values in current MPUTARR set */
	duk_uarridx_t curr_idx;            /* current (next) array index */
	duk_uarridx_t start_idx;           /* start array index of current MPUTARR set */
	duk_uarridx_t init_idx;            /* last array index explicitly initialized, +1 */
	duk_bool_t require_comma;          /* next loop requires a comma */
#if !defined(DUK_USE_PREFER_SIZE)
	duk_int_t pc_newarr;
	duk_compiler_instr *instr;
#endif

	/* DUK_TOK_LBRACKET already eaten, current token is right after that */
	DUK_ASSERT(comp_ctx->prev_token.t == DUK_TOK_LBRACKET);

	max_init_values = DUK__MAX_ARRAY_INIT_VALUES;  /* XXX: depend on available temps? */

	reg_obj = DUK__ALLOCTEMP(comp_ctx);
#if !defined(DUK_USE_PREFER_SIZE)
	pc_newarr = duk__get_current_pc(comp_ctx);
#endif
	duk__emit_bc(comp_ctx, DUK_OP_NEWARR, reg_obj);  /* XXX: patch initial size hint afterwards? */
	temp_start = DUK__GETTEMP(comp_ctx);

	/*
	 *  Emit initializers in sets of maximum max_init_values.
	 *  Corner cases such as single value initializers do not have
	 *  special handling now.
	 *
	 *  Elided elements must not be emitted as 'undefined' values,
	 *  because such values would be enumerable (which is incorrect).
	 *  Also note that trailing elisions must be reflected in the
	 *  length of the final array but cause no elements to be actually
	 *  inserted.
	 */

	curr_idx = 0;
	init_idx = 0;         /* tracks maximum initialized index + 1 */
	start_idx = 0;
	require_comma = 0;

	for (;;) {
		num_values = 0;
		DUK__SETTEMP(comp_ctx, temp_start);

		if (comp_ctx->curr_token.t == DUK_TOK_RBRACKET) {
			break;
		}

		for (;;) {
			if (comp_ctx->curr_token.t == DUK_TOK_RBRACKET) {
				/* the outer loop will recheck and exit */
				break;
			}

			/* comma check */
			if (require_comma) {
				if (comp_ctx->curr_token.t == DUK_TOK_COMMA) {
					/* comma after a value, expected */
					duk__advance(comp_ctx);
					require_comma = 0;
					continue;
				} else {
					goto syntax_error;
				}
			} else {
				if (comp_ctx->curr_token.t == DUK_TOK_COMMA) {
					/* elision - flush */
					curr_idx++;
					duk__advance(comp_ctx);
					/* if num_values > 0, MPUTARR emitted by outer loop after break */
					break;
				}
			}
			/* else an array initializer element */

			/* initial index */
			if (num_values == 0) {
				start_idx = curr_idx;
				reg_temp = DUK__ALLOCTEMP(comp_ctx);
				duk__emit_load_int32(comp_ctx, reg_temp, (duk_int32_t) start_idx);
			}

			reg_temp = DUK__ALLOCTEMP(comp_ctx);   /* alloc temp just in case, to update max temp */
			DUK__SETTEMP(comp_ctx, reg_temp);
			duk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp /*forced_reg*/);
			DUK__SETTEMP(comp_ctx, reg_temp + 1);

			num_values++;
			curr_idx++;
			require_comma = 1;

			if (num_values >= max_init_values) {
				/* MPUTARR emitted by outer loop */
				break;
			}
		}

		if (num_values > 0) {
			/* - A is a source register (it's not a write target, but used
			 *   to identify the target object) but can be shuffled.
			 * - B cannot be shuffled normally because it identifies a range
			 *   of registers, the emitter has special handling for this
			 *   (the "no shuffle" flag must not be set).
			 * - C is a non-register number and cannot be shuffled, but
			 *   never needs to be.
			 */
			duk__emit_a_b_c(comp_ctx,
			                DUK_OP_MPUTARR |
			                    DUK__EMIT_FLAG_NO_SHUFFLE_C |
			                    DUK__EMIT_FLAG_A_IS_SOURCE,
			                reg_obj,
			                temp_start,
			                (duk_regconst_t) (num_values + 1));
			init_idx = start_idx + num_values;

			/* num_values and temp_start reset at top of outer loop */
		}
	}

	/* Update initil size for NEWARR, doesn't need to be exact and is
	 * capped at A field limit.
	 */
#if !defined(DUK_USE_PREFER_SIZE)
	instr = duk__get_instr_ptr(comp_ctx, pc_newarr);
	instr->ins |= DUK_ENC_OP_A(0, curr_idx > DUK_BC_A_MAX ? DUK_BC_A_MAX : curr_idx);
#endif

	DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_RBRACKET);
	duk__advance(comp_ctx);

	DUK_DDD(DUK_DDDPRINT("array literal done, curridx=%ld, initidx=%ld",
	                     (long) curr_idx, (long) init_idx));

	/* trailing elisions? */
	if (curr_idx > init_idx) {
		/* yes, must set array length explicitly */
		DUK_DDD(DUK_DDDPRINT("array literal has trailing elisions which affect its length"));
		reg_temp = DUK__ALLOCTEMP(comp_ctx);
		duk__emit_load_int32(comp_ctx, reg_temp, (duk_int_t) curr_idx);
		duk__emit_a_bc(comp_ctx,
		               DUK_OP_SETALEN | DUK__EMIT_FLAG_A_IS_SOURCE,
		               reg_obj,
		               reg_temp);
	}

	DUK__SETTEMP(comp_ctx, temp_start);

	duk__ivalue_regconst(res, reg_obj);
	return;

 syntax_error:
	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_ARRAY_LITERAL);
	DUK_WO_NORETURN(return;);
}

typedef struct {
	duk_regconst_t reg_obj;
	duk_regconst_t temp_start;
	duk_small_uint_t num_pairs;
	duk_small_uint_t num_total_pairs;
} duk__objlit_state;

DUK_LOCAL void duk__objlit_flush_keys(duk_compiler_ctx *comp_ctx, duk__objlit_state *st) {
	if (st->num_pairs > 0) {
		/* - A is a source register (it's not a write target, but used
		 *   to identify the target object) but can be shuffled.
		 * - B cannot be shuffled normally because it identifies a range
		 *   of registers, the emitter has special handling for this
		 *   (the "no shuffle" flag must not be set).
		 * - C is a non-register number and cannot be shuffled, but
		 *   never needs to be.
		 */
		DUK_ASSERT(st->num_pairs > 0);
		duk__emit_a_b_c(comp_ctx,
		                DUK_OP_MPUTOBJ |
		                    DUK__EMIT_FLAG_NO_SHUFFLE_C |
		                    DUK__EMIT_FLAG_A_IS_SOURCE,
		                st->reg_obj,
		                st->temp_start,
		                (duk_regconst_t) (st->num_pairs * 2));
		st->num_total_pairs += st->num_pairs;
		st->num_pairs = 0;
	}
	DUK__SETTEMP(comp_ctx, st->temp_start);
}

DUK_LOCAL duk_bool_t duk__objlit_load_key(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_token *tok, duk_regconst_t reg_temp) {
	if (tok->t_nores == DUK_TOK_IDENTIFIER || tok->t_nores == DUK_TOK_STRING) {
		/* same handling for identifiers and strings */
		DUK_ASSERT(tok->str1 != NULL);
		duk_push_hstring(comp_ctx->thr, tok->str1);
	} else if (tok->t == DUK_TOK_NUMBER) {
		/* numbers can be loaded as numbers and coerced on the fly */
		duk_push_number(comp_ctx->thr, tok->num);
	} else {
		return 1;  /* error */
	}

	duk__ivalue_plain_fromstack(comp_ctx, res);
	DUK__SETTEMP(comp_ctx, reg_temp + 1);
	duk__ivalue_toforcedreg(comp_ctx, res, reg_temp);
	DUK__SETTEMP(comp_ctx, reg_temp + 1);
	return 0;
}

DUK_LOCAL void duk__nud_object_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
	duk_hthread *thr = comp_ctx->thr;
	duk__objlit_state st;
	duk_regconst_t reg_temp;          /* temp reg */
	duk_small_uint_t max_init_pairs;  /* max # of key-value pairs initialized in one MPUTOBJ set */
	duk_bool_t first;                 /* first value: comma must not precede the value */
	duk_bool_t is_set, is_get;        /* temps */
#if !defined(DUK_USE_PREFER_SIZE)
	duk_int_t pc_newobj;
	duk_compiler_instr *instr;
#endif

	DUK_ASSERT(comp_ctx->prev_token.t == DUK_TOK_LCURLY);

	max_init_pairs = DUK__MAX_OBJECT_INIT_PAIRS;  /* XXX: depend on available temps? */

	st.reg_obj = DUK__ALLOCTEMP(comp_ctx);    /* target object */
	st.temp_start = DUK__GETTEMP(comp_ctx);   /* start of MPUTOBJ argument list */
	st.num_pairs = 0;                         /* number of key/value pairs emitted for current MPUTOBJ set */
	st.num_total_pairs = 0;                   /* number of key/value pairs emitted overall */

#if !defined(DUK_USE_PREFER_SIZE)
	pc_newobj = duk__get_current_pc(comp_ctx);
#endif
	duk__emit_bc(comp_ctx, DUK_OP_NEWOBJ, st.reg_obj);

	/*
	 *  Emit initializers in sets of maximum max_init_pairs keys.
	 *  Setter/getter is handled separately and terminates the
	 *  current set of initializer values.  Corner cases such as
	 *  single value initializers do not have special handling now.
	 */

	first = 1;
	for (;;) {
		/*
		 *  ES5 and ES2015+ provide a lot of different PropertyDefinition
		 *  formats, see http://www.ecma-international.org/ecma-262/6.0/#sec-object-initializer.
		 *
		 *  PropertyName can be IdentifierName (includes reserved words), a string
		 *  literal, or a number literal.  Note that IdentifierName allows 'get' and
		 *  'set' too, so we need to look ahead to the next token to distinguish:
		 *
		 *     { get : 1 }
		 *
		 *  and
		 *
		 *     { get foo() { return 1 } }
		 *     { get get() { return 1 } }    // 'get' as getter propertyname
		 *
		 *  Finally, a trailing comma is allowed.
		 *
		 *  Key name is coerced to string at compile time (and ends up as a
		 *  a string constant) even for numeric keys (e.g. "{1:'foo'}").
		 *  These could be emitted using e.g. LDINT, but that seems hardly
		 *  worth the effort and would increase code size.
		 */

		DUK_DDD(DUK_DDDPRINT("object literal loop, curr_token->t = %ld",
		                     (long) comp_ctx->curr_token.t));

		if (comp_ctx->curr_token.t == DUK_TOK_RCURLY) {
			break;
		}

		if (first) {
			first = 0;
		} else {
			if (comp_ctx->curr_token.t != DUK_TOK_COMMA) {
				goto syntax_error;
			}
			duk__advance(comp_ctx);
			if (comp_ctx->curr_token.t == DUK_TOK_RCURLY) {
				/* trailing comma followed by rcurly */
				break;
			}
		}

		/* Advance to get one step of lookup. */
		duk__advance(comp_ctx);

		/* Flush current MPUTOBJ if enough many pairs gathered. */
		if (st.num_pairs >= max_init_pairs) {
			duk__objlit_flush_keys(comp_ctx, &st);
			DUK_ASSERT(st.num_pairs == 0);
		}

		/* Reset temp register state and reserve reg_temp and
		 * reg_temp + 1 for handling the current property.
		 */
		DUK__SETTEMP(comp_ctx, st.temp_start + 2 * (duk_regconst_t) st.num_pairs);
		reg_temp = DUK__ALLOCTEMPS(comp_ctx, 2);

		/* NOTE: "get" and "set" are not officially ReservedWords and the lexer
		 * currently treats them always like ordinary identifiers (DUK_TOK_GET
		 * and DUK_TOK_SET are unused).  They need to be detected based on the
		 * identifier string content.
		 */

		is_get = (comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER &&
		          comp_ctx->prev_token.str1 == DUK_HTHREAD_STRING_GET(thr));
		is_set = (comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER &&
		          comp_ctx->prev_token.str1 == DUK_HTHREAD_STRING_SET(thr));
		if ((is_get || is_set) && comp_ctx->curr_token.t != DUK_TOK_COLON) {
			/* getter/setter */
			duk_int_t fnum;

			duk__objlit_flush_keys(comp_ctx, &st);
			DUK_ASSERT(DUK__GETTEMP(comp_ctx) == st.temp_start);  /* 2 regs are guaranteed to be allocated w.r.t. temp_max */
			reg_temp = DUK__ALLOCTEMPS(comp_ctx, 2);

			if (duk__objlit_load_key(comp_ctx, res, &comp_ctx->curr_token, reg_temp) != 0) {
				goto syntax_error;
			}

			/* curr_token = get/set name */
			fnum = duk__parse_func_like_fnum(comp_ctx, DUK__FUNC_FLAG_GETSET);

			duk__emit_a_bc(comp_ctx,
			               DUK_OP_CLOSURE,
			               st.temp_start + 1,
			               (duk_regconst_t) fnum);

			/* Slot C is used in a non-standard fashion (range of regs),
			 * emitter code has special handling for it (must not set the
			 * "no shuffle" flag).
			 */
			duk__emit_a_bc(comp_ctx,
			              (is_get ? DUK_OP_INITGET : DUK_OP_INITSET) | DUK__EMIT_FLAG_A_IS_SOURCE,
			              st.reg_obj,
			              st.temp_start);   /* temp_start+0 = key, temp_start+1 = closure */

			DUK_ASSERT(st.num_pairs == 0);  /* temp state is reset on next loop */
#if defined(DUK_USE_ES6)
		} else if (comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER &&
		           (comp_ctx->curr_token.t == DUK_TOK_COMMA || comp_ctx->curr_token.t == DUK_TOK_RCURLY)) {
			duk_bool_t load_rc;

			load_rc = duk__objlit_load_key(comp_ctx, res, &comp_ctx->prev_token, reg_temp);
			DUK_UNREF(load_rc);
			DUK_ASSERT(load_rc == 0);  /* always succeeds because token is identifier */

			duk__ivalue_var_hstring(comp_ctx, res, comp_ctx->prev_token.str1);
			DUK_ASSERT(DUK__GETTEMP(comp_ctx) == reg_temp + 1);
			duk__ivalue_toforcedreg(comp_ctx, res, reg_temp + 1);

			st.num_pairs++;
		} else if ((comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER ||
		            comp_ctx->prev_token.t == DUK_TOK_STRING ||
		            comp_ctx->prev_token.t == DUK_TOK_NUMBER) &&
		           comp_ctx->curr_token.t == DUK_TOK_LPAREN) {
			duk_int_t fnum;

			/* Parsing-wise there's a small hickup here: the token parsing
			 * state is one step too advanced for the function parse helper
			 * compared to other cases.  The current solution is an extra
			 * flag to indicate whether function parsing should use the
			 * current or the previous token to starting parsing from.
			 */

			if (duk__objlit_load_key(comp_ctx, res, &comp_ctx->prev_token, reg_temp) != 0) {
				goto syntax_error;
			}

			fnum = duk__parse_func_like_fnum(comp_ctx, DUK__FUNC_FLAG_USE_PREVTOKEN | DUK__FUNC_FLAG_METDEF);

			duk__emit_a_bc(comp_ctx,
			               DUK_OP_CLOSURE,
			               reg_temp + 1,
			               (duk_regconst_t) fnum);

			st.num_pairs++;
#endif  /* DUK_USE_ES6 */
		} else {
#if defined(DUK_USE_ES6)
			if (comp_ctx->prev_token.t == DUK_TOK_LBRACKET) {
				/* ES2015 computed property name.  Executor ToPropertyKey()
				 * coerces the key at runtime.
				 */
				DUK__SETTEMP(comp_ctx, reg_temp);
				duk__expr_toforcedreg(comp_ctx, res, DUK__BP_FOR_EXPR, reg_temp);
				duk__advance_expect(comp_ctx, DUK_TOK_RBRACKET);

				/* XXX: If next token is '(' we're dealing with
				 * the method shorthand with a computed name,
				 * e.g. { [Symbol.for('foo')](a,b) {} }.  This
				 * form is not yet supported and causes a
				 * SyntaxError on the DUK_TOK_COLON check below.
				 */
			}
			else
#endif  /* DUK_USE_ES6 */
			{
				if (duk__objlit_load_key(comp_ctx, res, &comp_ctx->prev_token, reg_temp) != 0) {
					goto syntax_error;
				}
			}

			duk__advance_expect(comp_ctx, DUK_TOK_COLON);

			DUK__SETTEMP(comp_ctx, reg_temp + 1);
			duk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp + 1 /*forced_reg*/);

			st.num_pairs++;
		}
	}  /* property loop */

	/* Flush remaining properties. */
	duk__objlit_flush_keys(comp_ctx, &st);
	DUK_ASSERT(st.num_pairs == 0);
	DUK_ASSERT(DUK__GETTEMP(comp_ctx) == st.temp_start);

	/* Update initial size for NEWOBJ.  The init size doesn't need to be
	 * exact as the purpose is just to avoid object resizes in common
	 * cases.  The size is capped to field A limit, and will be too high
	 * if the object literal contains duplicate keys (this is harmless but
	 * increases memory traffic if the object is compacted later on).
	 */
#if !defined(DUK_USE_PREFER_SIZE)
	instr = duk__get_instr_ptr(comp_ctx, pc_newobj);
	instr->ins |= DUK_ENC_OP_A(0, st.num_total_pairs > DUK_BC_A_MAX ? DUK_BC_A_MAX : st.num_total_pairs);
#endif

	DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_RCURLY);
	duk__advance(comp_ctx);  /* No RegExp after object literal. */

	duk__ivalue_regconst(res, st.reg_obj);
	return;

 syntax_error:
	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_OBJECT_LITERAL);
	DUK_WO_NORETURN(return;);
}

/* Parse argument list.  Arguments are written to temps starting from
 * "next temp".  Returns number of arguments parsed.  Expects left paren
 * to be already eaten, and eats the right paren before returning.
 */
DUK_LOCAL duk_int_t duk__parse_arguments(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
	duk_int_t nargs = 0;
	duk_regconst_t reg_temp;

	/* Note: expect that caller has already eaten the left paren */

	DUK_DDD(DUK_DDDPRINT("start parsing arguments, prev_token.t=%ld, curr_token.t=%ld",
	                     (long) comp_ctx->prev_token.t, (long) comp_ctx->curr_token.t));

	for (;;) {
		if (comp_ctx->curr_token.t == DUK_TOK_RPAREN) {
			break;
		}
		if (nargs > 0) {
			duk__advance_expect(comp_ctx, DUK_TOK_COMMA);
		}

		/* We want the argument expression value to go to "next temp"
		 * without additional moves.  That should almost always be the
		 * case, but we double check after expression parsing.
		 *
		 * This is not the cleanest possible approach.
		 */

		reg_temp = DUK__ALLOCTEMP(comp_ctx);  /* bump up "allocated" reg count, just in case */
		DUK__SETTEMP(comp_ctx, reg_temp);

		/* binding power must be high enough to NOT allow comma expressions directly */
		duk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp);  /* always allow 'in', coerce to 'tr' just in case */

		DUK__SETTEMP(comp_ctx, reg_temp + 1);
		nargs++;

		DUK_DDD(DUK_DDDPRINT("argument #%ld written into reg %ld", (long) nargs, (long) reg_temp));
	}

	/* eat the right paren */
	duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);  /* RegExp mode does not matter. */

	DUK_DDD(DUK_DDDPRINT("end parsing arguments"));

	return nargs;
}

DUK_LOCAL duk_bool_t duk__expr_is_empty(duk_compiler_ctx *comp_ctx) {
	/* empty expressions can be detected conveniently with nud/led counts */
	return (comp_ctx->curr_func.nud_count == 0) &&
	       (comp_ctx->curr_func.led_count == 0);
}

DUK_LOCAL void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
	duk_hthread *thr = comp_ctx->thr;
	duk_token *tk;
	duk_regconst_t temp_at_entry;
	duk_small_uint_t tok;
	duk_uint32_t args;  /* temp variable to pass constants and flags to shared code */

	/*
	 *  ctx->prev_token     token to process with duk__expr_nud()
	 *  ctx->curr_token     updated by caller
	 *
	 *  Note: the token in the switch below has already been eaten.
	 */

	temp_at_entry = DUK__GETTEMP(comp_ctx);

	comp_ctx->curr_func.nud_count++;

	tk = &comp_ctx->prev_token;
	tok = tk->t;
	res->t = DUK_IVAL_NONE;

	DUK_DDD(DUK_DDDPRINT("duk__expr_nud(), prev_token.t=%ld, allow_in=%ld, paren_level=%ld",
	                     (long) tk->t, (long) comp_ctx->curr_func.allow_in, (long) comp_ctx->curr_func.paren_level));

	switch (tok) {

	/* PRIMARY EXPRESSIONS */

	case DUK_TOK_THIS: {
		duk_regconst_t reg_temp;
		reg_temp = DUK__ALLOCTEMP(comp_ctx);
		duk__emit_bc(comp_ctx,
		             DUK_OP_LDTHIS,
		             reg_temp);
		duk__ivalue_regconst(res, reg_temp);
		return;
	}
	case DUK_TOK_IDENTIFIER: {
		duk__ivalue_var_hstring(comp_ctx, res, tk->str1);
		return;
	}
	case DUK_TOK_NULL: {
		duk_push_null(thr);
		goto plain_value;
	}
	case DUK_TOK_TRUE: {
		duk_push_true(thr);
		goto plain_value;
	}
	case DUK_TOK_FALSE: {
		duk_push_false(thr);
		goto plain_value;
	}
	case DUK_TOK_NUMBER: {
		duk_push_number(thr, tk->num);
		goto plain_value;
	}
	case DUK_TOK_STRING: {
		DUK_ASSERT(tk->str1 != NULL);
		duk_push_hstring(thr, tk->str1);
		goto plain_value;
	}
	case DUK_TOK_REGEXP: {
#if defined(DUK_USE_REGEXP_SUPPORT)
		duk_regconst_t reg_temp;
		duk_regconst_t rc_re_bytecode;  /* const */
		duk_regconst_t rc_re_source;    /* const */

		DUK_ASSERT(tk->str1 != NULL);
		DUK_ASSERT(tk->str2 != NULL);

		DUK_DDD(DUK_DDDPRINT("emitting regexp op, str1=%!O, str2=%!O",
		                     (duk_heaphdr *) tk->str1,
		                     (duk_heaphdr *) tk->str2));

		reg_temp = DUK__ALLOCTEMP(comp_ctx);
		duk_push_hstring(thr, tk->str1);
		duk_push_hstring(thr, tk->str2);

		/* [ ... pattern flags ] */

		duk_regexp_compile(thr);

		/* [ ... escaped_source bytecode ] */

		rc_re_bytecode = duk__getconst(comp_ctx);
		rc_re_source = duk__getconst(comp_ctx);

		duk__emit_a_b_c(comp_ctx,
		                DUK_OP_REGEXP | DUK__EMIT_FLAG_BC_REGCONST,
		                reg_temp /*a*/,
		                rc_re_bytecode /*b*/,
		                rc_re_source /*c*/);

		duk__ivalue_regconst(res, reg_temp);
		return;
#else  /* DUK_USE_REGEXP_SUPPORT */
		goto syntax_error;
#endif  /* DUK_USE_REGEXP_SUPPORT */
	}
	case DUK_TOK_LBRACKET: {
		DUK_DDD(DUK_DDDPRINT("parsing array literal"));
		duk__nud_array_literal(comp_ctx, res);
		return;
	}
	case DUK_TOK_LCURLY: {
		DUK_DDD(DUK_DDDPRINT("parsing object literal"));
		duk__nud_object_literal(comp_ctx, res);
		return;
	}
	case DUK_TOK_LPAREN: {
		duk_bool_t prev_allow_in;

		comp_ctx->curr_func.paren_level++;
		prev_allow_in = comp_ctx->curr_func.allow_in;
		comp_ctx->curr_func.allow_in = 1; /* reset 'allow_in' for parenthesized expression */

		duk__expr(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);  /* Expression, terminates at a ')' */

		duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);  /* No RegExp after parenthesized expression. */
		comp_ctx->curr_func.allow_in = prev_allow_in;
		comp_ctx->curr_func.paren_level--;
		return;
	}

	/* MEMBER/NEW/CALL EXPRESSIONS */

	case DUK_TOK_NEW: {
		/*
		 *  Parsing an expression starting with 'new' is tricky because
		 *  there are multiple possible productions deriving from
		 *  LeftHandSideExpression which begin with 'new'.
		 *
		 *  We currently resort to one-token lookahead to distinguish the
		 *  cases.  Hopefully this is correct.  The binding power must be
		 *  such that parsing ends at an LPAREN (CallExpression) but not at
		 *  a PERIOD or LBRACKET (MemberExpression).
		 *
		 *  See doc/compiler.rst for discussion on the parsing approach,
		 *  and testcases/test-dev-new.js for a bunch of documented tests.
		 */

		duk_regconst_t reg_target;
		duk_int_t nargs;

		DUK_DDD(DUK_DDDPRINT("begin parsing new expression"));

		reg_target = DUK__ALLOCTEMPS(comp_ctx, 2);

#if defined(DUK_USE_ES6)
		if (comp_ctx->curr_token.t == DUK_TOK_PERIOD) {
			/* new.target */
			DUK_DDD(DUK_DDDPRINT("new.target"));
			duk__advance(comp_ctx);
			if (comp_ctx->curr_token.t_nores != DUK_TOK_IDENTIFIER ||
			    !duk_hstring_equals_ascii_cstring(comp_ctx->curr_token.str1, "target")) {
				goto syntax_error_newtarget;
			}
			if (comp_ctx->curr_func.is_global) {
				goto syntax_error_newtarget;
			}
			duk__advance(comp_ctx);
			duk__emit_bc(comp_ctx,
			             DUK_OP_NEWTARGET,
			             reg_target);
			duk__ivalue_regconst(res, reg_target);
			return;
		}
#endif  /* DUK_USE_ES6 */

		duk__expr_toforcedreg(comp_ctx, res, DUK__BP_CALL /*rbp_flags*/, reg_target /*forced_reg*/);
		duk__emit_bc(comp_ctx, DUK_OP_NEWOBJ, reg_target + 1);  /* default instance */
		DUK__SETTEMP(comp_ctx, reg_target + 2);

		/* XXX: 'new obj.noSuch()' doesn't use GETPROPC now which
		 * makes the error message worse than for obj.noSuch().
		 */

		if (comp_ctx->curr_token.t == DUK_TOK_LPAREN) {
			/* 'new' MemberExpression Arguments */
			DUK_DDD(DUK_DDDPRINT("new expression has argument list"));
			duk__advance(comp_ctx);
			nargs = duk__parse_arguments(comp_ctx, res);  /* parse args starting from "next temp", reg_target + 1 */
			/* right paren eaten */
		} else {
			/* 'new' MemberExpression */
			DUK_DDD(DUK_DDDPRINT("new expression has no argument list"));
			nargs = 0;
		}

		duk__emit_a_bc(comp_ctx,
		              DUK_OP_CALL0 | DUK_BC_CALL_FLAG_CONSTRUCT,
		              nargs /*num_args*/,
		              reg_target /*target*/);

		DUK_DDD(DUK_DDDPRINT("end parsing new expression"));

		duk__ivalue_regconst(res, reg_target);
		return;
	}

	/* FUNCTION EXPRESSIONS */

	case DUK_TOK_FUNCTION: {
		/* Function expression.  Note that any statement beginning with 'function'
		 * is handled by the statement parser as a function declaration, or a
		 * non-standard function expression/statement (or a SyntaxError).  We only
		 * handle actual function expressions (occurring inside an expression) here.
		 *
		 * O(depth^2) parse count for inner functions is handled by recording a
		 * lexer offset on the first compilation pass, so that the function can
		 * be efficiently skipped on the second pass.  This is encapsulated into
		 * duk__parse_func_like_fnum().
		 */

		duk_regconst_t reg_temp;
		duk_int_t fnum;

		reg_temp = DUK__ALLOCTEMP(comp_ctx);

		/* curr_token follows 'function' */
		fnum = duk__parse_func_like_fnum(comp_ctx, 0 /*flags*/);
		DUK_DDD(DUK_DDDPRINT("parsed inner function -> fnum %ld", (long) fnum));

		duk__emit_a_bc(comp_ctx,
		               DUK_OP_CLOSURE,
		               reg_temp /*a*/,
		               (duk_regconst_t) fnum /*bc*/);

		duk__ivalue_regconst(res, reg_temp);
		return;
	}

	/* UNARY EXPRESSIONS */

	case DUK_TOK_DELETE: {
		/* Delete semantics are a bit tricky.  The description in E5 specification
		 * is kind of confusing, because it distinguishes between resolvability of
		 * a reference (which is only known at runtime) seemingly at compile time
		 * (= SyntaxError throwing).
		 */
		duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
		if (res->t == DUK_IVAL_VAR) {
			/* not allowed in strict mode, regardless of whether resolves;
			 * in non-strict mode DELVAR handles both non-resolving and
			 * resolving cases (the specification description is a bit confusing).
			 */

			duk_regconst_t reg_temp;
			duk_regconst_t reg_varbind;
			duk_regconst_t rc_varname;

			if (comp_ctx->curr_func.is_strict) {
				DUK_ERROR_SYNTAX(thr, DUK_STR_CANNOT_DELETE_IDENTIFIER);
				DUK_WO_NORETURN(return;);
			}

			DUK__SETTEMP(comp_ctx, temp_at_entry);
			reg_temp = DUK__ALLOCTEMP(comp_ctx);

			duk_dup(thr, res->x1.valstack_idx);
			if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
				/* register bound variables are non-configurable -> always false */
				duk__emit_bc(comp_ctx,
				             DUK_OP_LDFALSE,
				             reg_temp);
			} else {
				duk_dup(thr, res->x1.valstack_idx);
				rc_varname = duk__getconst(comp_ctx);
				duk__emit_a_bc(comp_ctx,
				               DUK_OP_DELVAR,
				               reg_temp,
				               rc_varname);
			}
			duk__ivalue_regconst(res, reg_temp);
		} else if (res->t == DUK_IVAL_PROP) {
			duk_regconst_t reg_temp;
			duk_regconst_t reg_obj;
			duk_regconst_t rc_key;

			DUK__SETTEMP(comp_ctx, temp_at_entry);
			reg_temp = DUK__ALLOCTEMP(comp_ctx);
			reg_obj = duk__ispec_toregconst_raw(comp_ctx, &res->x1, -1 /*forced_reg*/, 0 /*flags*/);  /* don't allow const */
			rc_key = duk__ispec_toregconst_raw(comp_ctx, &res->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
			duk__emit_a_b_c(comp_ctx,
			                DUK_OP_DELPROP | DUK__EMIT_FLAG_BC_REGCONST,
			                reg_temp,
			                reg_obj,
			                rc_key);

			duk__ivalue_regconst(res, reg_temp);
		} else {
			/* non-Reference deletion is always 'true', even in strict mode */
			duk_push_true(thr);
			goto plain_value;
		}
		return;
	}
	case DUK_TOK_VOID: {
		duk__expr_toplain_ignore(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
		duk_push_undefined(thr);
		goto plain_value;
	}
	case DUK_TOK_TYPEOF: {
		/* 'typeof' must handle unresolvable references without throwing
		 * a ReferenceError (E5 Section 11.4.3).  Register mapped values
		 * will never be unresolvable so special handling is only required
		 * when an identifier is a "slow path" one.
		 */
		duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */

		if (res->t == DUK_IVAL_VAR) {
			duk_regconst_t reg_varbind;
			duk_regconst_t rc_varname;
			duk_regconst_t reg_temp;

			duk_dup(thr, res->x1.valstack_idx);
			if (!duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
				DUK_DDD(DUK_DDDPRINT("typeof for an identifier name which could not be resolved "
				                     "at compile time, need to use special run-time handling"));
				reg_temp = DUK__ALLOCTEMP(comp_ctx);
				duk__emit_a_bc(comp_ctx,
				               DUK_OP_TYPEOFID,
				               reg_temp,
				               rc_varname);
				duk__ivalue_regconst(res, reg_temp);
				return;
			}
		}

		args = DUK_OP_TYPEOF;
		goto unary;
	}
	case DUK_TOK_INCREMENT: {
		args = (DUK_OP_PREINCP << 8) + DUK_OP_PREINCR;
		goto preincdec;
	}
	case DUK_TOK_DECREMENT: {
		args = (DUK_OP_PREDECP << 8) + DUK_OP_PREDECR;
		goto preincdec;
	}
	case DUK_TOK_ADD: {
		/* unary plus */
		duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
		if (res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_VALUE &&
		    duk_is_number(thr, res->x1.valstack_idx)) {
			/* unary plus of a number is identity */
			return;
		}
		args = DUK_OP_UNP;
		goto unary;
	}
	case DUK_TOK_SUB: {
		/* unary minus */
		duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
		if (res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_VALUE &&
		    duk_is_number(thr, res->x1.valstack_idx)) {
			/* this optimization is important to handle negative literals
			 * (which are not directly provided by the lexical grammar)
			 */
			duk_tval *tv_num;
			duk_double_union du;

			tv_num = DUK_GET_TVAL_POSIDX(thr, res->x1.valstack_idx);
			DUK_ASSERT(tv_num != NULL);
			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_num));
			du.d = DUK_TVAL_GET_NUMBER(tv_num);
			du.d = -du.d;
			DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);
			DUK_TVAL_SET_NUMBER(tv_num, du.d);
			return;
		}
		args = DUK_OP_UNM;
		goto unary;
	}
	case DUK_TOK_BNOT: {
		duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
		args = DUK_OP_BNOT;
		goto unary;
	}
	case DUK_TOK_LNOT: {
		duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
		if (res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_VALUE) {
			/* Very minimal inlining to handle common idioms '!0' and '!1',
			 * and also boolean arguments like '!false' and '!true'.
			 */
			duk_tval *tv_val;

			tv_val = DUK_GET_TVAL_POSIDX(thr, res->x1.valstack_idx);
			DUK_ASSERT(tv_val != NULL);
			if (DUK_TVAL_IS_NUMBER(tv_val)) {
				duk_double_t d;
				d = DUK_TVAL_GET_NUMBER(tv_val);
				if (duk_double_equals(d, 0.0)) {
					/* Matches both +0 and -0 on purpose. */
					DUK_DDD(DUK_DDDPRINT("inlined lnot: !0 -> true"));
					DUK_TVAL_SET_BOOLEAN_TRUE(tv_val);
					return;
				} else if (duk_double_equals(d, 1.0)) {
					DUK_DDD(DUK_DDDPRINT("inlined lnot: !1 -> false"));
					DUK_TVAL_SET_BOOLEAN_FALSE(tv_val);
					return;
				}
			} else if (DUK_TVAL_IS_BOOLEAN(tv_val)) {
				duk_small_uint_t v;
				v = DUK_TVAL_GET_BOOLEAN(tv_val);
				DUK_DDD(DUK_DDDPRINT("inlined lnot boolean: %ld", (long) v));
				DUK_ASSERT(v == 0 || v == 1);
				DUK_TVAL_SET_BOOLEAN(tv_val, v ^ 0x01);
				return;
			}
		}
		args = DUK_OP_LNOT;
		goto unary;
	}

	}  /* end switch */

	DUK_ERROR_SYNTAX(thr, DUK_STR_PARSE_ERROR);
	DUK_WO_NORETURN(return;);

 unary:
	{
		/* Unary opcodes use just the 'BC' register source because it
		 * matches current shuffle limits, and maps cleanly to 16 high
		 * bits of the opcode.
		 */

		duk_regconst_t reg_src, reg_res;

		reg_src = duk__ivalue_toregconst_raw(comp_ctx, res, -1 /*forced_reg*/, 0 /*flags*/);
		if (DUK__ISREG_TEMP(comp_ctx, reg_src)) {
			reg_res = reg_src;
		} else {
			reg_res = DUK__ALLOCTEMP(comp_ctx);
		}
		duk__emit_a_bc(comp_ctx,
		             args,
		             reg_res,
		             reg_src);
		duk__ivalue_regconst(res, reg_res);
		return;
	}

 preincdec:
	{
		/* preincrement and predecrement */
		duk_regconst_t reg_res;
		duk_small_uint_t args_op1 = args & 0xff;  /* DUK_OP_PREINCR/DUK_OP_PREDECR */
		duk_small_uint_t args_op2 = args >> 8;    /* DUK_OP_PREINCP_RR/DUK_OP_PREDECP_RR */

		/* Specific assumptions for opcode numbering. */
		DUK_ASSERT(DUK_OP_PREINCR + 4 == DUK_OP_PREINCV);
		DUK_ASSERT(DUK_OP_PREDECR + 4 == DUK_OP_PREDECV);

		reg_res = DUK__ALLOCTEMP(comp_ctx);

		duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
		if (res->t == DUK_IVAL_VAR) {
			duk_hstring *h_varname;
			duk_regconst_t reg_varbind;
			duk_regconst_t rc_varname;

			h_varname = duk_known_hstring(thr, res->x1.valstack_idx);

			if (duk__hstring_is_eval_or_arguments_in_strict_mode(comp_ctx, h_varname)) {
				goto syntax_error;
			}

			duk_dup(thr, res->x1.valstack_idx);
			if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
				duk__emit_a_bc(comp_ctx,
				               args_op1,  /* e.g. DUK_OP_PREINCR */
				               reg_res,
				               reg_varbind);
			} else {
				duk__emit_a_bc(comp_ctx,
				                args_op1 + 4,  /* e.g. DUK_OP_PREINCV */
				                reg_res,
				                rc_varname);
			}

			DUK_DDD(DUK_DDDPRINT("preincdec to '%!O' -> reg_varbind=%ld, rc_varname=%ld",
			                     (duk_heaphdr *) h_varname, (long) reg_varbind, (long) rc_varname));
		} else if (res->t == DUK_IVAL_PROP) {
			duk_regconst_t reg_obj;  /* allocate to reg only (not const) */
			duk_regconst_t rc_key;
			reg_obj = duk__ispec_toregconst_raw(comp_ctx, &res->x1, -1 /*forced_reg*/, 0 /*flags*/);  /* don't allow const */
			rc_key = duk__ispec_toregconst_raw(comp_ctx, &res->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
			duk__emit_a_b_c(comp_ctx,
			                args_op2 | DUK__EMIT_FLAG_BC_REGCONST,  /* e.g. DUK_OP_PREINCP */
			                reg_res,
			                reg_obj,
			                rc_key);
		} else {
			/* Technically return value is not needed because INVLHS will
			 * unconditially throw a ReferenceError.  Coercion is necessary
			 * for proper semantics (consider ToNumber() called for an object).
			 * Use DUK_OP_UNP with a dummy register to get ToNumber().
			 */

			duk__ivalue_toforcedreg(comp_ctx, res, reg_res);
			duk__emit_bc(comp_ctx,
			             DUK_OP_UNP,
			             reg_res);  /* for side effects, result ignored */
			duk__emit_op_only(comp_ctx,
			                  DUK_OP_INVLHS);
		}
		DUK__SETTEMP(comp_ctx, reg_res + 1);
		duk__ivalue_regconst(res, reg_res);
		return;
	}

 plain_value:
	{
		/* Stack top contains plain value */
		duk__ivalue_plain_fromstack(comp_ctx, res);
		return;
	}

#if defined(DUK_USE_ES6)
 syntax_error_newtarget:
	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_NEWTARGET);
	DUK_WO_NORETURN(return;);
#endif

 syntax_error:
	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_EXPRESSION);
	DUK_WO_NORETURN(return;);
}

/* XXX: add flag to indicate whether caller cares about return value; this
 * affects e.g. handling of assignment expressions.  This change needs API
 * changes elsewhere too.
 */
DUK_LOCAL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_ivalue *res) {
	duk_hthread *thr = comp_ctx->thr;
	duk_token *tk;
	duk_small_uint_t tok;
	duk_uint32_t args;  /* temp variable to pass constants and flags to shared code */

	/*
	 *  ctx->prev_token     token to process with duk__expr_led()
	 *  ctx->curr_token     updated by caller
	 */

	comp_ctx->curr_func.led_count++;

	/* The token in the switch has already been eaten here */
	tk = &comp_ctx->prev_token;
	tok = tk->t;

	DUK_DDD(DUK_DDDPRINT("duk__expr_led(), prev_token.t=%ld, allow_in=%ld, paren_level=%ld",
	                     (long) tk->t, (long) comp_ctx->curr_func.allow_in, (long) comp_ctx->curr_func.paren_level));

	/* XXX: default priority for infix operators is duk__expr_lbp(tok) -> get it here? */

	switch (tok) {

	/* PRIMARY EXPRESSIONS */

	case DUK_TOK_PERIOD: {
		/* Property access expressions are critical for correct LHS ordering,
		 * see comments in duk__expr()!
		 *
		 * A conservative approach would be to use duk__ivalue_totempconst()
		 * for 'left'.  However, allowing a reg-bound variable seems safe here
		 * and is nice because "foo.bar" is a common expression.  If the ivalue
		 * is used in an expression a GETPROP will occur before any changes to
		 * the base value can occur.  If the ivalue is used as an assignment
		 * LHS, the assignment code will ensure the base value is safe from
		 * RHS mutation.
		 */

		/* XXX: This now coerces an identifier into a GETVAR to a temp, which
		 * causes an extra LDREG in call setup.  It's sufficient to coerce to a
		 * unary ivalue?
		 */
		duk__ivalue_toplain(comp_ctx, left);

		/* NB: must accept reserved words as property name */
		if (comp_ctx->curr_token.t_nores != DUK_TOK_IDENTIFIER) {
			DUK_ERROR_SYNTAX(thr, DUK_STR_EXPECTED_IDENTIFIER);
			DUK_WO_NORETURN(return;);
		}

		res->t = DUK_IVAL_PROP;
		duk__copy_ispec(comp_ctx, &left->x1, &res->x1);  /* left.x1 -> res.x1 */
		DUK_ASSERT(comp_ctx->curr_token.str1 != NULL);
		duk_push_hstring(thr, comp_ctx->curr_token.str1);
		duk_replace(thr, res->x2.valstack_idx);
		res->x2.t = DUK_ISPEC_VALUE;

		/* special RegExp literal handling after IdentifierName */
		comp_ctx->curr_func.reject_regexp_in_adv = 1;

		duk__advance(comp_ctx);
		return;
	}
	case DUK_TOK_LBRACKET: {
		/* Property access expressions are critical for correct LHS ordering,
		 * see comments in duk__expr()!
		 */

		/* XXX: optimize temp reg use */
		/* XXX: similar coercion issue as in DUK_TOK_PERIOD */
		/* XXX: coerce to regs? it might be better for enumeration use, where the
		 * same PROP ivalue is used multiple times.  Or perhaps coerce PROP further
		 * there?
		 */
		/* XXX: for simple cases like x['y'] an unnecessary LDREG is
		 * emitted for the base value; could avoid it if we knew that
		 * the key expression is safe (e.g. just a single literal).
		 */

		/* The 'left' value must not be a register bound variable
		 * because it may be mutated during the rest of the expression
		 * and E5.1 Section 11.2.1 specifies the order of evaluation
		 * so that the base value is evaluated first.
		 * See: test-bug-nested-prop-mutate.js.
		 */
		duk__ivalue_totempconst(comp_ctx, left);
		duk__expr_toplain(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);  /* Expression, ']' terminates */
		duk__advance_expect(comp_ctx, DUK_TOK_RBRACKET);

		res->t = DUK_IVAL_PROP;
		duk__copy_ispec(comp_ctx, &res->x1, &res->x2);   /* res.x1 -> res.x2 */
		duk__copy_ispec(comp_ctx, &left->x1, &res->x1);  /* left.x1 -> res.x1 */
		return;
	}
	case DUK_TOK_LPAREN: {
		/* function call */
		duk_regconst_t reg_cs = DUK__ALLOCTEMPS(comp_ctx, 2);
		duk_int_t nargs;
		duk_small_uint_t call_op = DUK_OP_CALL0;

		/* XXX: attempt to get the call result to "next temp" whenever
		 * possible to avoid unnecessary register shuffles.
		 */

		/*
		 *  Setup call: target and 'this' binding.  Three cases:
		 *
		 *    1. Identifier base (e.g. "foo()")
		 *    2. Property base (e.g. "foo.bar()")
		 *    3. Register base (e.g. "foo()()"; i.e. when a return value is a function)
		 */

		if (left->t == DUK_IVAL_VAR) {
			duk_hstring *h_varname;
			duk_regconst_t reg_varbind;
			duk_regconst_t rc_varname;

			DUK_DDD(DUK_DDDPRINT("function call with identifier base"));

			h_varname = duk_known_hstring(thr, left->x1.valstack_idx);
			if (h_varname == DUK_HTHREAD_STRING_EVAL(thr)) {
				/* Potential direct eval call detected, flag the CALL
				 * so that a run-time "direct eval" check is made and
				 * special behavior may be triggered.  Note that this
				 * does not prevent 'eval' from being register bound.
				 */
				DUK_DDD(DUK_DDDPRINT("function call with identifier 'eval' "
				                     "-> using EVALCALL, marking function "
				                     "as may_direct_eval"));
				call_op |= DUK_BC_CALL_FLAG_CALLED_AS_EVAL;
				comp_ctx->curr_func.may_direct_eval = 1;
			}

			duk_dup(thr, left->x1.valstack_idx);
			if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
				duk__emit_a_bc(comp_ctx,
				              DUK_OP_CSREG | DUK__EMIT_FLAG_A_IS_SOURCE,
				              reg_varbind,
				              reg_cs + 0);
			} else {
				/* XXX: expand target register or constant field to
				 * reduce shuffling.
				 */
				DUK_ASSERT(DUK__ISCONST(rc_varname));
				duk__emit_a_b(comp_ctx,
				              DUK_OP_CSVAR | DUK__EMIT_FLAG_BC_REGCONST,
				              reg_cs + 0,
				              rc_varname);
			}
		} else if (left->t == DUK_IVAL_PROP) {
			/* Call through a property lookup, E5 Section 11.2.3, step 6.a.i,
			 * E5 Section 10.4.3.  There used to be a separate CSPROP opcode
			 * but a typical call setup took 3 opcodes (e.g. LDREG, LDCONST,
			 * CSPROP) and the same can be achieved with ordinary loads.
			 */
#if defined(DUK_USE_VERBOSE_ERRORS)
			duk_regconst_t reg_key;
#endif

			DUK_DDD(DUK_DDDPRINT("function call with property base"));

			/* XXX: For Math.sin() this generates: LDCONST + LDREG +
			 * GETPROPC + call.  The LDREG is unnecessary because LDCONST
			 * could be loaded directly into reg_cs + 1.  This doesn't
			 * happen now because a variable cannot be in left->x1 of a
			 * DUK_IVAL_PROP.  We could notice that left->x1 is a temp
			 * and reuse, but it would still be in the wrong position
			 * (reg_cs + 0 rather than reg_cs + 1).
			 */
			duk__ispec_toforcedreg(comp_ctx, &left->x1, reg_cs + 1);  /* base */
#if defined(DUK_USE_VERBOSE_ERRORS)
			reg_key = duk__ispec_toregconst_raw(comp_ctx, &left->x2, -1, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
			duk__emit_a_b_c(comp_ctx,
			                DUK_OP_GETPROPC | DUK__EMIT_FLAG_BC_REGCONST,
			                reg_cs + 0,
			                reg_cs + 1,
			                reg_key);
#else
			duk__ivalue_toforcedreg(comp_ctx, left, reg_cs + 0);  /* base[key] */
#endif
		} else {
			DUK_DDD(DUK_DDDPRINT("function call with register base"));

			duk__ivalue_toforcedreg(comp_ctx, left, reg_cs + 0);
#if 0
			duk__emit_a_bc(comp_ctx,
			               DUK_OP_CSREG | DUK__EMIT_FLAG_A_IS_SOURCE,
			               reg_cs + 0,
			               reg_cs + 0);  /* in-place setup */
#endif
			/* Because of in-place setup, REGCS is equivalent to
			 * just this LDUNDEF.
			 */
			duk__emit_bc(comp_ctx, DUK_OP_LDUNDEF, reg_cs + 1);
		}

		DUK__SETTEMP(comp_ctx, reg_cs + 2);
		nargs = duk__parse_arguments(comp_ctx, res);  /* parse args starting from "next temp" */

		/* Tailcalls are handled by back-patching the already emitted opcode
		 * later in return statement parser.
		 */

		duk__emit_a_bc(comp_ctx,
		               call_op,
		               (duk_regconst_t) nargs /*numargs*/,
		               reg_cs /*basereg*/);
		DUK__SETTEMP(comp_ctx, reg_cs + 1);    /* result in csreg */

		duk__ivalue_regconst(res, reg_cs);
		return;
	}

	/* POSTFIX EXPRESSION */

	case DUK_TOK_INCREMENT: {
		args = (DUK_OP_POSTINCP_RR << 16) + (DUK_OP_POSTINCR << 8) + 0;
		goto postincdec;
	}
	case DUK_TOK_DECREMENT: {
		args = (DUK_OP_POSTDECP_RR << 16) + (DUK_OP_POSTDECR << 8) + 0;
		goto postincdec;
	}

	/* EXPONENTIATION EXPRESSION */

#if defined(DUK_USE_ES7_EXP_OPERATOR)
	case DUK_TOK_EXP: {
		args = (DUK_OP_EXP << 8) + DUK__BP_EXPONENTIATION - 1;  /* UnaryExpression */
		goto binary;
	}
#endif

	/* MULTIPLICATIVE EXPRESSION */

	case DUK_TOK_MUL: {
		args = (DUK_OP_MUL << 8) + DUK__BP_MULTIPLICATIVE;  /* ExponentiationExpression */
		goto binary;
	}
	case DUK_TOK_DIV: {
		args = (DUK_OP_DIV << 8) + DUK__BP_MULTIPLICATIVE;  /* ExponentiationExpression */
		goto binary;
	}
	case DUK_TOK_MOD: {
		args = (DUK_OP_MOD << 8) + DUK__BP_MULTIPLICATIVE;  /* ExponentiationExpression */
		goto binary;
	}

	/* ADDITIVE EXPRESSION */

	case DUK_TOK_ADD: {
		args = (DUK_OP_ADD << 8) + DUK__BP_ADDITIVE;  /* MultiplicativeExpression */
		goto binary;
	}
	case DUK_TOK_SUB: {
		args = (DUK_OP_SUB << 8) + DUK__BP_ADDITIVE;  /* MultiplicativeExpression */
		goto binary;
	}

	/* SHIFT EXPRESSION */

	case DUK_TOK_ALSHIFT: {
		/* << */
		args = (DUK_OP_BASL << 8) + DUK__BP_SHIFT;
		goto binary;
	}
	case DUK_TOK_ARSHIFT: {
		/* >> */
		args = (DUK_OP_BASR << 8) + DUK__BP_SHIFT;
		goto binary;
	}
	case DUK_TOK_RSHIFT: {
		/* >>> */
		args = (DUK_OP_BLSR << 8) + DUK__BP_SHIFT;
		goto binary;
	}

	/* RELATIONAL EXPRESSION */

	case DUK_TOK_LT: {
		/* < */
		args = (DUK_OP_LT << 8) + DUK__BP_RELATIONAL;
		goto binary;
	}
	case DUK_TOK_GT: {
		args = (DUK_OP_GT << 8) + DUK__BP_RELATIONAL;
		goto binary;
	}
	case DUK_TOK_LE: {
		args = (DUK_OP_LE << 8) + DUK__BP_RELATIONAL;
		goto binary;
	}
	case DUK_TOK_GE: {
		args = (DUK_OP_GE << 8) + DUK__BP_RELATIONAL;
		goto binary;
	}
	case DUK_TOK_INSTANCEOF: {
		args = (DUK_OP_INSTOF << 8) + DUK__BP_RELATIONAL;
		goto binary;
	}
	case DUK_TOK_IN: {
		args = (DUK_OP_IN << 8) + DUK__BP_RELATIONAL;
		goto binary;
	}

	/* EQUALITY EXPRESSION */

	case DUK_TOK_EQ: {
		args = (DUK_OP_EQ << 8) + DUK__BP_EQUALITY;
		goto binary;
	}
	case DUK_TOK_NEQ: {
		args = (DUK_OP_NEQ << 8) + DUK__BP_EQUALITY;
		goto binary;
	}
	case DUK_TOK_SEQ: {
		args = (DUK_OP_SEQ << 8) + DUK__BP_EQUALITY;
		goto binary;
	}
	case DUK_TOK_SNEQ: {
		args = (DUK_OP_SNEQ << 8) + DUK__BP_EQUALITY;
		goto binary;
	}

	/* BITWISE EXPRESSIONS */

	case DUK_TOK_BAND: {
		args = (DUK_OP_BAND << 8) + DUK__BP_BAND;
		goto binary;
	}
	case DUK_TOK_BXOR: {
		args = (DUK_OP_BXOR << 8) + DUK__BP_BXOR;
		goto binary;
	}
	case DUK_TOK_BOR: {
		args = (DUK_OP_BOR << 8) + DUK__BP_BOR;
		goto binary;
	}

	/* LOGICAL EXPRESSIONS */

	case DUK_TOK_LAND: {
		/* syntactically left-associative but parsed as right-associative */
		args = (1 << 8) + DUK__BP_LAND - 1;
		goto binary_logical;
	}
	case DUK_TOK_LOR: {
		/* syntactically left-associative but parsed as right-associative */
		args = (0 << 8) + DUK__BP_LOR - 1;
		goto binary_logical;
	}

	/* CONDITIONAL EXPRESSION */

	case DUK_TOK_QUESTION: {
		/* XXX: common reg allocation need is to reuse a sub-expression's temp reg,
		 * but only if it really is a temp.  Nothing fancy here now.
		 */
		duk_regconst_t reg_temp;
		duk_int_t pc_jump1;
		duk_int_t pc_jump2;

		reg_temp = DUK__ALLOCTEMP(comp_ctx);
		duk__ivalue_toforcedreg(comp_ctx, left, reg_temp);
		duk__emit_if_true_skip(comp_ctx, reg_temp);
		pc_jump1 = duk__emit_jump_empty(comp_ctx);  /* jump to false */
		duk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp /*forced_reg*/);  /* AssignmentExpression */
		duk__advance_expect(comp_ctx, DUK_TOK_COLON);
		pc_jump2 = duk__emit_jump_empty(comp_ctx);  /* jump to end */
		duk__patch_jump_here(comp_ctx, pc_jump1);
		duk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp /*forced_reg*/);  /* AssignmentExpression */
		duk__patch_jump_here(comp_ctx, pc_jump2);

		DUK__SETTEMP(comp_ctx, reg_temp + 1);
		duk__ivalue_regconst(res, reg_temp);
		return;
	}

	/* ASSIGNMENT EXPRESSION */

	case DUK_TOK_EQUALSIGN: {
		/*
		 *  Assignments are right associative, allows e.g.
		 *    a = 5;
		 *    a += b = 9;   // same as a += (b = 9)
		 *  -> expression value 14, a = 14, b = 9
		 *
		 *  Right associativiness is reflected in the BP for recursion,
		 *  "-1" ensures assignment operations are allowed.
		 *
		 *  XXX: just use DUK__BP_COMMA (i.e. no need for 2-step bp levels)?
		 */
		args = (DUK_OP_NONE << 8) + DUK__BP_ASSIGNMENT - 1;   /* DUK_OP_NONE marks a 'plain' assignment */
		goto assign;
	}
	case DUK_TOK_ADD_EQ: {
		/* right associative */
		args = (DUK_OP_ADD << 8) + DUK__BP_ASSIGNMENT - 1;
		goto assign;
	}
	case DUK_TOK_SUB_EQ: {
		/* right associative */
		args = (DUK_OP_SUB << 8) + DUK__BP_ASSIGNMENT - 1;
		goto assign;
	}
	case DUK_TOK_MUL_EQ: {
		/* right associative */
		args = (DUK_OP_MUL << 8) + DUK__BP_ASSIGNMENT - 1;
		goto assign;
	}
	case DUK_TOK_DIV_EQ: {
		/* right associative */
		args = (DUK_OP_DIV << 8) + DUK__BP_ASSIGNMENT - 1;
		goto assign;
	}
	case DUK_TOK_MOD_EQ: {
		/* right associative */
		args = (DUK_OP_MOD << 8) + DUK__BP_ASSIGNMENT - 1;
		goto assign;
	}
#if defined(DUK_USE_ES7_EXP_OPERATOR)
	case DUK_TOK_EXP_EQ: {
		/* right associative */
		args = (DUK_OP_EXP << 8) + DUK__BP_ASSIGNMENT - 1;
		goto assign;
	}
#endif
	case DUK_TOK_ALSHIFT_EQ: {
		/* right associative */
		args = (DUK_OP_BASL << 8) + DUK__BP_ASSIGNMENT - 1;
		goto assign;
	}
	case DUK_TOK_ARSHIFT_EQ: {
		/* right associative */
		args = (DUK_OP_BASR << 8) + DUK__BP_ASSIGNMENT - 1;
		goto assign;
	}
	case DUK_TOK_RSHIFT_EQ: {
		/* right associative */
		args = (DUK_OP_BLSR << 8) + DUK__BP_ASSIGNMENT - 1;
		goto assign;
	}
	case DUK_TOK_BAND_EQ: {
		/* right associative */
		args = (DUK_OP_BAND << 8) + DUK__BP_ASSIGNMENT - 1;
		goto assign;
	}
	case DUK_TOK_BOR_EQ: {
		/* right associative */
		args = (DUK_OP_BOR << 8) + DUK__BP_ASSIGNMENT - 1;
		goto assign;
	}
	case DUK_TOK_BXOR_EQ: {
		/* right associative */
		args = (DUK_OP_BXOR << 8) + DUK__BP_ASSIGNMENT - 1;
		goto assign;
	}

	/* COMMA */

	case DUK_TOK_COMMA: {
		/* right associative */

		duk__ivalue_toplain_ignore(comp_ctx, left);  /* need side effects, not value */
		duk__expr_toplain(comp_ctx, res, DUK__BP_COMMA - 1 /*rbp_flags*/);

		/* return 'res' (of right part) as our result */
		return;
	}

	default: {
		break;
	}
	}

	DUK_D(DUK_DPRINT("parse error: unexpected token: %ld", (long) tok));
	DUK_ERROR_SYNTAX(thr, DUK_STR_PARSE_ERROR);
	DUK_WO_NORETURN(return;);

#if 0
	/* XXX: shared handling for 'duk__expr_lhs'? */
	if (comp_ctx->curr_func.paren_level == 0 && XXX) {
		comp_ctx->curr_func.duk__expr_lhs = 0;
	}
#endif

 binary:
	/*
	 *  Shared handling of binary operations
	 *
	 *  args = (opcode << 8) + rbp
	 */
	{
		duk__ivalue_toplain(comp_ctx, left);
		duk__expr_toplain(comp_ctx, res, args & 0xff /*rbp_flags*/);

		/* combine left->x1 and res->x1 (right->x1, really) -> (left->x1 OP res->x1) */
		DUK_ASSERT(left->t == DUK_IVAL_PLAIN);
		DUK_ASSERT(res->t == DUK_IVAL_PLAIN);

		res->t = DUK_IVAL_ARITH;
		res->op = (args >> 8) & 0xff;

		res->x2.t = res->x1.t;
		res->x2.regconst = res->x1.regconst;
		duk_copy(thr, res->x1.valstack_idx, res->x2.valstack_idx);

		res->x1.t = left->x1.t;
		res->x1.regconst = left->x1.regconst;
		duk_copy(thr, left->x1.valstack_idx, res->x1.valstack_idx);

		DUK_DDD(DUK_DDDPRINT("binary op, res: t=%ld, x1.t=%ld, x1.regconst=0x%08lx, x2.t=%ld, x2.regconst=0x%08lx",
		                     (long) res->t, (long) res->x1.t, (unsigned long) res->x1.regconst, (long) res->x2.t, (unsigned long) res->x2.regconst));
		return;
	}

 binary_logical:
	/*
	 *  Shared handling for logical AND and logical OR.
	 *
	 *  args = (truthval << 8) + rbp
	 *
	 *  Truthval determines when to skip right-hand-side.
	 *  For logical AND truthval=1, for logical OR truthval=0.
	 *
	 *  See doc/compiler.rst for discussion on compiling logical
	 *  AND and OR expressions.  The approach here is very simplistic,
	 *  generating extra jumps and multiple evaluations of truth values,
	 *  but generates code on-the-fly with only local back-patching.
	 *
	 *  Both logical AND and OR are syntactically left-associated.
	 *  However, logical ANDs are compiled as right associative
	 *  expressions, i.e. "A && B && C" as "A && (B && C)", to allow
	 *  skip jumps to skip over the entire tail.  Similarly for logical OR.
	 */

	{
		duk_regconst_t reg_temp;
		duk_int_t pc_jump;
		duk_small_uint_t args_truthval = args >> 8;
		duk_small_uint_t args_rbp = args & 0xff;

		/* XXX: unoptimal use of temps, resetting */

		reg_temp = DUK__ALLOCTEMP(comp_ctx);

		duk__ivalue_toforcedreg(comp_ctx, left, reg_temp);
		DUK_ASSERT(DUK__ISREG(reg_temp));
		duk__emit_bc(comp_ctx,
		            (args_truthval ? DUK_OP_IFTRUE_R : DUK_OP_IFFALSE_R),
		            reg_temp);  /* skip jump conditionally */
		pc_jump = duk__emit_jump_empty(comp_ctx);
		duk__expr_toforcedreg(comp_ctx, res, args_rbp /*rbp_flags*/, reg_temp /*forced_reg*/);
		duk__patch_jump_here(comp_ctx, pc_jump);

		duk__ivalue_regconst(res, reg_temp);
		return;
	}

 assign:
	/*
	 *  Shared assignment expression handling
	 *
	 *  args = (opcode << 8) + rbp
	 *
	 *  If 'opcode' is DUK_OP_NONE, plain assignment without arithmetic.
	 *  Syntactically valid left-hand-side forms which are not accepted as
	 *  left-hand-side values (e.g. as in "f() = 1") must NOT cause a
	 *  SyntaxError, but rather a run-time ReferenceError.
	 *
	 *  When evaluating X <op>= Y, the LHS (X) is conceptually evaluated
	 *  to a temporary first.  The RHS is then evaluated.  Finally, the
	 *  <op> is applied to the initial value of RHS (not the value after
	 *  RHS evaluation), and written to X.  Doing so concretely generates
	 *  inefficient code so we'd like to avoid the temporary when possible.
	 *  See: https://github.com/svaarala/duktape/pull/992.
	 *
	 *  The expression value (final LHS value, written to RHS) is
	 *  conceptually copied into a fresh temporary so that it won't
	 *  change even if the LHS/RHS values change in outer expressions.
	 *  For example, it'd be generally incorrect for the expression value
	 *  to be the RHS register binding, unless there's a guarantee that it
	 *  won't change during further expression evaluation.  Using the
	 *  temporary concretely produces inefficient bytecode, so we try to
	 *  avoid the extra temporary for some known-to-be-safe cases.
	 *  Currently the only safe case we detect is a "top level assignment",
	 *  for example "x = y + z;", where the assignment expression value is
	 *  ignored.
	 *  See: test-dev-assign-expr.js and test-bug-assign-mutate-gh381.js.
	 */

	{
		duk_small_uint_t args_op = args >> 8;
		duk_small_uint_t args_rbp = args & 0xff;
		duk_bool_t toplevel_assign;

		/* XXX: here we need to know if 'left' is left-hand-side compatible.
		 * That information is no longer available from current expr parsing
		 * state; it would need to be carried into the 'left' ivalue or by
		 * some other means.
		 */

		/* A top-level assignment is e.g. "x = y;".  For these it's safe
		 * to use the RHS as-is as the expression value, even if the RHS
		 * is a reg-bound identifier.  The RHS ('res') is right associative
		 * so it has consumed all other assignment level operations; the
		 * only relevant lower binding power construct is comma operator
		 * which will ignore the expression value provided here.  Usually
		 * the top level assignment expression value is ignored, but it
		 * is relevant for e.g. eval code.
		 */
		toplevel_assign = (comp_ctx->curr_func.nud_count == 1 && /* one token before */
		                   comp_ctx->curr_func.led_count == 1);  /* one operator (= assign) */
		DUK_DDD(DUK_DDDPRINT("assignment: nud_count=%ld, led_count=%ld, toplevel_assign=%ld",
		                     (long) comp_ctx->curr_func.nud_count,
		                     (long) comp_ctx->curr_func.led_count,
		                     (long) toplevel_assign));

		if (left->t == DUK_IVAL_VAR) {
			duk_hstring *h_varname;
			duk_regconst_t reg_varbind;
			duk_regconst_t rc_varname;

			DUK_ASSERT(left->x1.t == DUK_ISPEC_VALUE);  /* LHS is already side effect free */

			h_varname = duk_known_hstring(thr, left->x1.valstack_idx);
			if (duk__hstring_is_eval_or_arguments_in_strict_mode(comp_ctx, h_varname)) {
				/* E5 Section 11.13.1 (and others for other assignments), step 4. */
				goto syntax_error_lvalue;
			}
			duk_dup(thr, left->x1.valstack_idx);
			(void) duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname);

			if (args_op == DUK_OP_NONE) {
				duk__expr(comp_ctx, res, args_rbp /*rbp_flags*/);
				if (toplevel_assign) {
					/* Any 'res' will do. */
					DUK_DDD(DUK_DDDPRINT("plain assignment, toplevel assign, use as is"));
				} else {
					/* 'res' must be a plain ivalue, and not register-bound variable. */
					DUK_DDD(DUK_DDDPRINT("plain assignment, not toplevel assign, ensure not a reg-bound identifier"));
					if (res->t != DUK_IVAL_PLAIN || (res->x1.t == DUK_ISPEC_REGCONST &&
					                                 DUK__ISREG_NOTTEMP(comp_ctx, res->x1.regconst))) {
						duk__ivalue_totempconst(comp_ctx, res);
					}
				}
			} else {
				/* For X <op>= Y we need to evaluate the pre-op
				 * value of X before evaluating the RHS: the RHS
				 * can change X, but when we do <op> we must use
				 * the pre-op value.
				 */
				duk_regconst_t reg_temp;

				reg_temp = DUK__ALLOCTEMP(comp_ctx);

				if (reg_varbind >= 0) {
					duk_regconst_t reg_res;
					duk_regconst_t reg_src;
					duk_int_t pc_temp_load;
					duk_int_t pc_before_rhs;
					duk_int_t pc_after_rhs;

					if (toplevel_assign) {
						/* 'reg_varbind' is the operation result and can also
						 * become the expression value for top level assignments
						 * such as: "var x; x += y;".
						 */
						DUK_DD(DUK_DDPRINT("<op>= expression is top level, write directly to reg_varbind"));
						reg_res = reg_varbind;
					} else {
						/* Not safe to use 'reg_varbind' as assignment expression
						 * value, so go through a temp.
						 */
						DUK_DD(DUK_DDPRINT("<op>= expression is not top level, write to reg_temp"));
						reg_res = reg_temp;  /* reg_res should be smallest possible */
						reg_temp = DUK__ALLOCTEMP(comp_ctx);
					}

					/* Try to optimize X <op>= Y for reg-bound
					 * variables.  Detect side-effect free RHS
					 * narrowly by seeing whether it emits code.
					 * If not, rewind the code emitter and overwrite
					 * the unnecessary temp reg load.
					 */

					pc_temp_load = duk__get_current_pc(comp_ctx);
					duk__emit_a_bc(comp_ctx,
					               DUK_OP_LDREG,
					               reg_temp,
					               reg_varbind);

					pc_before_rhs = duk__get_current_pc(comp_ctx);
					duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
					DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
					pc_after_rhs = duk__get_current_pc(comp_ctx);

					DUK_DD(DUK_DDPRINT("pc_temp_load=%ld, pc_before_rhs=%ld, pc_after_rhs=%ld",
					                   (long) pc_temp_load, (long) pc_before_rhs,
					                   (long) pc_after_rhs));

					if (pc_after_rhs == pc_before_rhs) {
						/* Note: if the reg_temp load generated shuffling
						 * instructions, we may need to rewind more than
						 * one instruction, so use explicit PC computation.
						 */
						DUK_DD(DUK_DDPRINT("rhs is side effect free, rewind and avoid unnecessary temp for reg-based <op>="));
						DUK_BW_ADD_PTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code, (pc_temp_load - pc_before_rhs) * (duk_int_t) sizeof(duk_compiler_instr));
						reg_src = reg_varbind;
					} else {
						DUK_DD(DUK_DDPRINT("rhs evaluation emitted code, not sure if rhs is side effect free; use temp reg for LHS"));
						reg_src = reg_temp;
					}

					duk__emit_a_b_c(comp_ctx,
					                args_op | DUK__EMIT_FLAG_BC_REGCONST,
					                reg_res,
					                reg_src,
					                res->x1.regconst);

					res->x1.regconst = reg_res;

					/* Ensure compact use of temps. */
					if (DUK__ISREG_TEMP(comp_ctx, reg_res)) {
						DUK__SETTEMP(comp_ctx, reg_res + 1);
					}
				} else {
					/* When LHS is not register bound, always go through a
					 * temporary.  No optimization for top level assignment.
					 */

					duk__emit_a_bc(comp_ctx,
					               DUK_OP_GETVAR,
					               reg_temp,
					               rc_varname);

					duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
					DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);

					duk__emit_a_b_c(comp_ctx,
					                args_op | DUK__EMIT_FLAG_BC_REGCONST,
					                reg_temp,
					                reg_temp,
					                res->x1.regconst);
					res->x1.regconst = reg_temp;
				}

				DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
			}

			/* At this point 'res' holds the potential expression value.
			 * It can be basically any ivalue here, including a reg-bound
			 * identifier (if code above deems it safe) or a unary/binary
			 * operation.  Operations must be resolved to a side effect free
			 * plain value, and the side effects must happen exactly once.
			 */

			if (reg_varbind >= 0) {
				if (res->t != DUK_IVAL_PLAIN) {
					/* Resolve 'res' directly into the LHS binding, and use
					 * that as the expression value if safe.  If not safe,
					 * resolve to a temp/const and copy to LHS.
					 */
					if (toplevel_assign) {
						duk__ivalue_toforcedreg(comp_ctx, res, (duk_int_t) reg_varbind);
					} else {
						duk__ivalue_totempconst(comp_ctx, res);
						duk__copy_ivalue(comp_ctx, res, left);  /* use 'left' as a temp */
						duk__ivalue_toforcedreg(comp_ctx, left, (duk_int_t) reg_varbind);
					}
				} else {
					/* Use 'res' as the expression value (it's side effect
					 * free and may be a plain value, a register, or a
					 * constant) and write it to the LHS binding too.
					 */
					duk__copy_ivalue(comp_ctx, res, left);  /* use 'left' as a temp */
					duk__ivalue_toforcedreg(comp_ctx, left, (duk_int_t) reg_varbind);
				}
			} else {
				/* Only a reg fits into 'A' so coerce 'res' into a register
				 * for PUTVAR.
				 *
				 * XXX: here the current A/B/C split is suboptimal: we could
				 * just use 9 bits for reg_res (and support constants) and 17
				 * instead of 18 bits for the varname const index.
				 */

				duk__ivalue_toreg(comp_ctx, res);
				duk__emit_a_bc(comp_ctx,
				               DUK_OP_PUTVAR | DUK__EMIT_FLAG_A_IS_SOURCE,
				               res->x1.regconst,
				               rc_varname);
			}

			/* 'res' contains expression value */
		} else if (left->t == DUK_IVAL_PROP) {
			/* E5 Section 11.13.1 (and others) step 4 never matches for prop writes -> no check */
			duk_regconst_t reg_obj;
			duk_regconst_t rc_key;
			duk_regconst_t rc_res;
			duk_regconst_t reg_temp;

			/* Property access expressions ('a[b]') are critical to correct
			 * LHS evaluation ordering, see test-dev-assign-eval-order*.js.
			 * We must make sure that the LHS target slot (base object and
			 * key) don't change during RHS evaluation.  The only concrete
			 * problem is a register reference to a variable-bound register
			 * (i.e., non-temp).  Require temp regs for both key and base.
			 *
			 * Don't allow a constant for the object (even for a number
			 * etc), as it goes into the 'A' field of the opcode.
			 */

			reg_obj = duk__ispec_toregconst_raw(comp_ctx,
			                                    &left->x1,
			                                    -1 /*forced_reg*/,
			                                    DUK__IVAL_FLAG_REQUIRE_TEMP /*flags*/);

			rc_key = duk__ispec_toregconst_raw(comp_ctx,
			                                   &left->x2,
			                                   -1 /*forced_reg*/,
			                                   DUK__IVAL_FLAG_REQUIRE_TEMP | DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);

			/* Evaluate RHS only when LHS is safe. */

			if (args_op == DUK_OP_NONE) {
				duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
				DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
				rc_res = res->x1.regconst;
			} else {
				reg_temp = DUK__ALLOCTEMP(comp_ctx);
				duk__emit_a_b_c(comp_ctx,
				                DUK_OP_GETPROP | DUK__EMIT_FLAG_BC_REGCONST,
				                reg_temp,
				                reg_obj,
				                rc_key);

				duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
				DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);

				duk__emit_a_b_c(comp_ctx,
				                args_op | DUK__EMIT_FLAG_BC_REGCONST,
				                reg_temp,
				                reg_temp,
				                res->x1.regconst);
				rc_res = reg_temp;
			}

			duk__emit_a_b_c(comp_ctx,
			                DUK_OP_PUTPROP | DUK__EMIT_FLAG_A_IS_SOURCE | DUK__EMIT_FLAG_BC_REGCONST,
			                reg_obj,
			                rc_key,
			                rc_res);

			duk__ivalue_regconst(res, rc_res);
		} else {
			/* No support for lvalues returned from new or function call expressions.
			 * However, these must NOT cause compile-time SyntaxErrors, but run-time
			 * ReferenceErrors.  Both left and right sides of the assignment must be
			 * evaluated before throwing a ReferenceError.  For instance:
			 *
			 *     f() = g();
			 *
			 * must result in f() being evaluated, then g() being evaluated, and
			 * finally, a ReferenceError being thrown.  See E5 Section 11.13.1.
			 */

			duk_regconst_t rc_res;

			/* First evaluate LHS fully to ensure all side effects are out. */
			duk__ivalue_toplain_ignore(comp_ctx, left);

			/* Then evaluate RHS fully (its value becomes the expression value too).
			 * Technically we'd need the side effect safety check here too, but because
			 * we always throw using INVLHS the result doesn't matter.
			 */
			rc_res = duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);

			duk__emit_op_only(comp_ctx, DUK_OP_INVLHS);

			duk__ivalue_regconst(res, rc_res);
		}

		return;
	}

 postincdec:
	{
		/*
		 *  Post-increment/decrement will return the original value as its
		 *  result value.  However, even that value will be coerced using
		 *  ToNumber() which is quite awkward.  Specific bytecode opcodes
		 *  are used to handle these semantics.
		 *
		 *  Note that post increment/decrement has a "no LineTerminator here"
		 *  restriction.  This is handled by duk__expr_lbp(), which forcibly terminates
		 *  the previous expression if a LineTerminator occurs before '++'/'--'.
		 */

		duk_regconst_t reg_res;
		duk_small_uint_t args_op1 = (args >> 8) & 0xff;  /* DUK_OP_POSTINCR/DUK_OP_POSTDECR */
		duk_small_uint_t args_op2 = args >> 16;          /* DUK_OP_POSTINCP_RR/DUK_OP_POSTDECP_RR */

		/* Specific assumptions for opcode numbering. */
		DUK_ASSERT(DUK_OP_POSTINCR + 4 == DUK_OP_POSTINCV);
		DUK_ASSERT(DUK_OP_POSTDECR + 4 == DUK_OP_POSTDECV);

		reg_res = DUK__ALLOCTEMP(comp_ctx);

		if (left->t == DUK_IVAL_VAR) {
			duk_hstring *h_varname;
			duk_regconst_t reg_varbind;
			duk_regconst_t rc_varname;

			h_varname = duk_known_hstring(thr, left->x1.valstack_idx);

			if (duk__hstring_is_eval_or_arguments_in_strict_mode(comp_ctx, h_varname)) {
				goto syntax_error;
			}

			duk_dup(thr, left->x1.valstack_idx);
			if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
				duk__emit_a_bc(comp_ctx,
				               args_op1,  /* e.g. DUK_OP_POSTINCR */
				               reg_res,
				               reg_varbind);
			} else {
				duk__emit_a_bc(comp_ctx,
				               args_op1 + 4,  /* e.g. DUK_OP_POSTINCV */
				               reg_res,
				               rc_varname);
			}

			DUK_DDD(DUK_DDDPRINT("postincdec to '%!O' -> reg_varbind=%ld, rc_varname=%ld",
			                     (duk_heaphdr *) h_varname, (long) reg_varbind, (long) rc_varname));
		} else if (left->t == DUK_IVAL_PROP) {
			duk_regconst_t reg_obj;  /* allocate to reg only (not const) */
			duk_regconst_t rc_key;

			reg_obj = duk__ispec_toregconst_raw(comp_ctx, &left->x1, -1 /*forced_reg*/, 0 /*flags*/);  /* don't allow const */
			rc_key = duk__ispec_toregconst_raw(comp_ctx, &left->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
			duk__emit_a_b_c(comp_ctx,
			                args_op2 | DUK__EMIT_FLAG_BC_REGCONST,  /* e.g. DUK_OP_POSTINCP */
			                reg_res,
			                reg_obj,
			                rc_key);
		} else {
			/* Technically return value is not needed because INVLHS will
			 * unconditially throw a ReferenceError.  Coercion is necessary
			 * for proper semantics (consider ToNumber() called for an object).
			 * Use DUK_OP_UNP with a dummy register to get ToNumber().
			 */
			duk__ivalue_toforcedreg(comp_ctx, left, reg_res);
			duk__emit_bc(comp_ctx,
			             DUK_OP_UNP,
			             reg_res);  /* for side effects, result ignored */
			duk__emit_op_only(comp_ctx,
			                  DUK_OP_INVLHS);
		}

		DUK__SETTEMP(comp_ctx, reg_res + 1);
		duk__ivalue_regconst(res, reg_res);
		return;
	}

 syntax_error:
	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_EXPRESSION);
	DUK_WO_NORETURN(return;);

 syntax_error_lvalue:
	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_LVALUE);
	DUK_WO_NORETURN(return;);
}

DUK_LOCAL duk_small_uint_t duk__expr_lbp(duk_compiler_ctx *comp_ctx) {
	duk_small_uint_t tok = comp_ctx->curr_token.t;

	DUK_ASSERT_DISABLE(tok >= DUK_TOK_MINVAL);  /* unsigned */
	DUK_ASSERT(tok <= DUK_TOK_MAXVAL);
	DUK_ASSERT(sizeof(duk__token_lbp) == DUK_TOK_MAXVAL + 1);

	/* XXX: integrate support for this into led() instead?
	 * Similar issue as post-increment/post-decrement.
	 */

	/* prevent duk__expr_led() by using a binding power less than anything valid */
	if (tok == DUK_TOK_IN && !comp_ctx->curr_func.allow_in) {
		return 0;
	}

	if ((tok == DUK_TOK_DECREMENT || tok == DUK_TOK_INCREMENT) &&
	    (comp_ctx->curr_token.lineterm)) {
		/* '++' or '--' in a post-increment/decrement position,
		 * and a LineTerminator occurs between the operator and
		 * the preceding expression.  Force the previous expr
		 * to terminate, in effect treating e.g. "a,b\n++" as
		 * "a,b;++" (= SyntaxError).
		 */
		return 0;
	}

	return DUK__TOKEN_LBP_GET_BP(duk__token_lbp[tok]);  /* format is bit packed */
}

/*
 *  Expression parsing.
 *
 *  Upon entry to 'expr' and its variants, 'curr_tok' is assumed to be the
 *  first token of the expression.  Upon exit, 'curr_tok' will be the first
 *  token not part of the expression (e.g. semicolon terminating an expression
 *  statement).
 */

#define DUK__EXPR_RBP_MASK           0xff
#define DUK__EXPR_FLAG_REJECT_IN     (1 << 8)   /* reject 'in' token (used for for-in) */
#define DUK__EXPR_FLAG_ALLOW_EMPTY   (1 << 9)   /* allow empty expression */
#define DUK__EXPR_FLAG_REQUIRE_INIT  (1 << 10)  /* require initializer for var/const */

/* main expression parser function */
DUK_LOCAL void duk__expr(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
	duk_hthread *thr = comp_ctx->thr;
	duk_ivalue tmp_alloc;   /* 'res' is used for "left", and 'tmp' for "right" */
	duk_ivalue *tmp = &tmp_alloc;
	duk_small_uint_t rbp;

	DUK__RECURSION_INCREASE(comp_ctx, thr);

	duk_require_stack(thr, DUK__PARSE_EXPR_SLOTS);

	/* filter out flags from exprtop rbp_flags here to save space */
	rbp = rbp_flags & DUK__EXPR_RBP_MASK;

	DUK_DDD(DUK_DDDPRINT("duk__expr(), rbp_flags=%ld, rbp=%ld, allow_in=%ld, paren_level=%ld",
	                     (long) rbp_flags, (long) rbp, (long) comp_ctx->curr_func.allow_in,
	                     (long) comp_ctx->curr_func.paren_level));

	duk_memzero(&tmp_alloc, sizeof(tmp_alloc));
	tmp->x1.valstack_idx = duk_get_top(thr);
	tmp->x2.valstack_idx = tmp->x1.valstack_idx + 1;
	duk_push_undefined(thr);
	duk_push_undefined(thr);

	/* XXX: where to release temp regs in intermediate expressions?
	 * e.g. 1+2+3 -> don't inflate temp register count when parsing this.
	 * that particular expression temp regs can be forced here.
	 */

	/* XXX: increase ctx->expr_tokens here for every consumed token
	 * (this would be a nice statistic)?
	 */

	if (comp_ctx->curr_token.t == DUK_TOK_SEMICOLON || comp_ctx->curr_token.t == DUK_TOK_RPAREN) {
		/* XXX: possibly incorrect handling of empty expression */
		DUK_DDD(DUK_DDDPRINT("empty expression"));
		if (!(rbp_flags & DUK__EXPR_FLAG_ALLOW_EMPTY)) {
			DUK_ERROR_SYNTAX(thr, DUK_STR_EMPTY_EXPR_NOT_ALLOWED);
			DUK_WO_NORETURN(return;);
		}
		duk_push_undefined(thr);
		duk__ivalue_plain_fromstack(comp_ctx, res);
		goto cleanup;
	}

	duk__advance(comp_ctx);
	duk__expr_nud(comp_ctx, res);  /* reuse 'res' as 'left' */
	while (rbp < duk__expr_lbp(comp_ctx)) {
		duk__advance(comp_ctx);
		duk__expr_led(comp_ctx, res, tmp);
		duk__copy_ivalue(comp_ctx, tmp, res);  /* tmp -> res */
	}

 cleanup:
	/* final result is already in 'res' */

	duk_pop_2(thr);

	DUK__RECURSION_DECREASE(comp_ctx, thr);
}

DUK_LOCAL void duk__exprtop(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
	duk_hthread *thr = comp_ctx->thr;

	/* Note: these variables must reside in 'curr_func' instead of the global
	 * context: when parsing function expressions, expression parsing is nested.
	 */
	comp_ctx->curr_func.nud_count = 0;
	comp_ctx->curr_func.led_count = 0;
	comp_ctx->curr_func.paren_level = 0;
	comp_ctx->curr_func.expr_lhs = 1;
	comp_ctx->curr_func.allow_in = (rbp_flags & DUK__EXPR_FLAG_REJECT_IN ? 0 : 1);

	duk__expr(comp_ctx, res, rbp_flags);

	if (!(rbp_flags & DUK__EXPR_FLAG_ALLOW_EMPTY) && duk__expr_is_empty(comp_ctx)) {
		DUK_ERROR_SYNTAX(thr, DUK_STR_EMPTY_EXPR_NOT_ALLOWED);
		DUK_WO_NORETURN(return;);
	}
}

/* A bunch of helpers (for size optimization) that combine duk__expr()/duk__exprtop()
 * and result conversions.
 *
 * Each helper needs at least 2-3 calls to make it worth while to wrap.
 */

#if 0  /* unused */
DUK_LOCAL duk_regconst_t duk__expr_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
	duk__expr(comp_ctx, res, rbp_flags);
	return duk__ivalue_toreg(comp_ctx, res);
}
#endif

#if 0  /* unused */
DUK_LOCAL duk_regconst_t duk__expr_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
	duk__expr(comp_ctx, res, rbp_flags);
	return duk__ivalue_totemp(comp_ctx, res);
}
#endif

DUK_LOCAL void duk__expr_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags, duk_regconst_t forced_reg) {
	DUK_ASSERT(forced_reg >= 0);
	duk__expr(comp_ctx, res, rbp_flags);
	duk__ivalue_toforcedreg(comp_ctx, res, forced_reg);
}

DUK_LOCAL duk_regconst_t duk__expr_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
	duk__expr(comp_ctx, res, rbp_flags);
	return duk__ivalue_toregconst(comp_ctx, res);
}

#if 0  /* unused */
DUK_LOCAL duk_regconst_t duk__expr_totempconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
	duk__expr(comp_ctx, res, rbp_flags);
	return duk__ivalue_totempconst(comp_ctx, res);
}
#endif

DUK_LOCAL void duk__expr_toplain(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
	duk__expr(comp_ctx, res, rbp_flags);
	duk__ivalue_toplain(comp_ctx, res);
}

DUK_LOCAL void duk__expr_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
	duk__expr(comp_ctx, res, rbp_flags);
	duk__ivalue_toplain_ignore(comp_ctx, res);
}

DUK_LOCAL duk_regconst_t duk__exprtop_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
	duk__exprtop(comp_ctx, res, rbp_flags);
	return duk__ivalue_toreg(comp_ctx, res);
}

#if 0  /* unused */
DUK_LOCAL duk_regconst_t duk__exprtop_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
	duk__exprtop(comp_ctx, res, rbp_flags);
	return duk__ivalue_totemp(comp_ctx, res);
}
#endif

DUK_LOCAL void duk__exprtop_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags, duk_regconst_t forced_reg) {
	DUK_ASSERT(forced_reg >= 0);
	duk__exprtop(comp_ctx, res, rbp_flags);
	duk__ivalue_toforcedreg(comp_ctx, res, forced_reg);
}

DUK_LOCAL duk_regconst_t duk__exprtop_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
	duk__exprtop(comp_ctx, res, rbp_flags);
	return duk__ivalue_toregconst(comp_ctx, res);
}

#if 0  /* unused */
DUK_LOCAL void duk__exprtop_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *res, int rbp_flags) {
	duk__exprtop(comp_ctx, res, rbp_flags);
	duk__ivalue_toplain_ignore(comp_ctx, res);
}
#endif

/*
 *  Parse an individual source element (top level statement) or a statement.
 *
 *  Handles labeled statements automatically (peeling away labels before
 *  parsing an expression that follows the label(s)).
 *
 *  Upon entry, 'curr_tok' contains the first token of the statement (parsed
 *  in "allow regexp literal" mode).  Upon exit, 'curr_tok' contains the first
 *  token following the statement (if the statement has a terminator, this is
 *  the token after the terminator).
 */

#define DUK__HAS_VAL                  (1 << 0)  /* stmt has non-empty value */
#define DUK__HAS_TERM                 (1 << 1)  /* stmt has explicit/implicit semicolon terminator */
#define DUK__ALLOW_AUTO_SEMI_ALWAYS   (1 << 2)  /* allow automatic semicolon even without lineterm (compatibility) */
#define DUK__STILL_PROLOGUE           (1 << 3)  /* statement does not terminate directive prologue */
#define DUK__IS_TERMINAL              (1 << 4)  /* statement is guaranteed to be terminal (control doesn't flow to next statement) */

/* Parse a single variable declaration (e.g. "i" or "i=10").  A leading 'var'
 * has already been eaten.  These is no return value in 'res', it is used only
 * as a temporary.
 *
 * When called from 'for-in' statement parser, the initializer expression must
 * not allow the 'in' token.  The caller supply additional expression parsing
 * flags (like DUK__EXPR_FLAG_REJECT_IN) in 'expr_flags'.
 *
 * Finally, out_rc_varname and out_reg_varbind are updated to reflect where
 * the identifier is bound:
 *
 *    If register bound:      out_reg_varbind >= 0, out_rc_varname == 0 (ignore)
 *    If not register bound:  out_reg_varbind < 0, out_rc_varname >= 0
 *
 * These allow the caller to use the variable for further assignment, e.g.
 * as is done in 'for-in' parsing.
 */

DUK_LOCAL void duk__parse_var_decl(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t expr_flags, duk_regconst_t *out_reg_varbind, duk_regconst_t *out_rc_varname) {
	duk_hthread *thr = comp_ctx->thr;
	duk_hstring *h_varname;
	duk_regconst_t reg_varbind;
	duk_regconst_t rc_varname;

	/* assume 'var' has been eaten */

	/* Note: Identifier rejects reserved words */
	if (comp_ctx->curr_token.t != DUK_TOK_IDENTIFIER) {
		goto syntax_error;
	}
	h_varname = comp_ctx->curr_token.str1;

	DUK_ASSERT(h_varname != NULL);

	/* strict mode restrictions (E5 Section 12.2.1) */
	if (duk__hstring_is_eval_or_arguments_in_strict_mode(comp_ctx, h_varname)) {
		goto syntax_error;
	}

	/* register declarations in first pass */
	if (comp_ctx->curr_func.in_scanning) {
		duk_uarridx_t n;
		DUK_DDD(DUK_DDDPRINT("register variable declaration %!O in pass 1",
		                     (duk_heaphdr *) h_varname));
		n = (duk_uarridx_t) duk_get_length(thr, comp_ctx->curr_func.decls_idx);
		duk_push_hstring(thr, h_varname);
		duk_put_prop_index(thr, comp_ctx->curr_func.decls_idx, n);
		duk_push_int(thr, DUK_DECL_TYPE_VAR + (0 << 8));
		duk_put_prop_index(thr, comp_ctx->curr_func.decls_idx, n + 1);
	}

	duk_push_hstring(thr, h_varname);  /* push before advancing to keep reachable */

	/* register binding lookup is based on varmap (even in first pass) */
	duk_dup_top(thr);
	(void) duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname);

	duk__advance(comp_ctx);  /* eat identifier */

	if (comp_ctx->curr_token.t == DUK_TOK_EQUALSIGN) {
		duk__advance(comp_ctx);

		DUK_DDD(DUK_DDDPRINT("vardecl, assign to '%!O' -> reg_varbind=%ld, rc_varname=%ld",
		                     (duk_heaphdr *) h_varname, (long) reg_varbind, (long) rc_varname));

		duk__exprtop(comp_ctx, res, DUK__BP_COMMA | expr_flags /*rbp_flags*/);  /* AssignmentExpression */

		if (reg_varbind >= 0) {
			duk__ivalue_toforcedreg(comp_ctx, res, reg_varbind);
		} else {
			duk_regconst_t reg_val;
			reg_val = duk__ivalue_toreg(comp_ctx, res);
			duk__emit_a_bc(comp_ctx,
			               DUK_OP_PUTVAR | DUK__EMIT_FLAG_A_IS_SOURCE,
			               reg_val,
			               rc_varname);
		}
	} else {
		if (expr_flags & DUK__EXPR_FLAG_REQUIRE_INIT) {
			/* Used for minimal 'const': initializer required. */
			goto syntax_error;
		}
	}

	duk_pop(thr);  /* pop varname */

	*out_rc_varname = rc_varname;
	*out_reg_varbind = reg_varbind;

	return;

 syntax_error:
	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_VAR_DECLARATION);
	DUK_WO_NORETURN(return;);
}

DUK_LOCAL void duk__parse_var_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t expr_flags) {
	duk_regconst_t reg_varbind;
	duk_regconst_t rc_varname;

	duk__advance(comp_ctx);  /* eat 'var' */

	for (;;) {
		/* rc_varname and reg_varbind are ignored here */
		duk__parse_var_decl(comp_ctx, res, 0 | expr_flags, &reg_varbind, &rc_varname);

		if (comp_ctx->curr_token.t != DUK_TOK_COMMA) {
			break;
		}
		duk__advance(comp_ctx);
	}
}

DUK_LOCAL void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {
	duk_hthread *thr = comp_ctx->thr;
	duk_int_t pc_v34_lhs;         /* start variant 3/4 left-hand-side code (L1 in doc/compiler.rst example) */
	duk_regconst_t temp_reset;    /* knock back "next temp" to this whenever possible */
	duk_regconst_t reg_temps;     /* preallocated temporaries (2) for variants 3 and 4 */

	DUK_DDD(DUK_DDDPRINT("start parsing a for/for-in statement"));

	/* Two temporaries are preallocated here for variants 3 and 4 which need
	 * registers which are never clobbered by expressions in the loop
	 * (concretely: for the enumerator object and the next enumerated value).
	 * Variants 1 and 2 "release" these temps.
	 */

	reg_temps = DUK__ALLOCTEMPS(comp_ctx, 2);

	temp_reset = DUK__GETTEMP(comp_ctx);

	/*
	 *  For/for-in main variants are:
	 *
	 *    1. for (ExpressionNoIn_opt; Expression_opt; Expression_opt) Statement
	 *    2. for (var VariableDeclarationNoIn; Expression_opt; Expression_opt) Statement
	 *    3. for (LeftHandSideExpression in Expression) Statement
	 *    4. for (var VariableDeclarationNoIn in Expression) Statement
	 *
	 *  Parsing these without arbitrary lookahead or backtracking is relatively
	 *  tricky but we manage to do so for now.
	 *
	 *  See doc/compiler.rst for a detailed discussion of control flow
	 *  issues, evaluation order issues, etc.
	 */

	duk__advance(comp_ctx);  /* eat 'for' */
	duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);

	DUK_DDD(DUK_DDDPRINT("detecting for/for-in loop variant, pc=%ld", (long) duk__get_current_pc(comp_ctx)));

	/* a label site has been emitted by duk__parse_stmt() automatically
	 * (it will also emit the ENDLABEL).
	 */

	if (comp_ctx->curr_token.t == DUK_TOK_VAR) {
		/*
		 *  Variant 2 or 4
		 */

		duk_regconst_t reg_varbind;  /* variable binding register if register-bound (otherwise < 0) */
		duk_regconst_t rc_varname;   /* variable name reg/const, if variable not register-bound */

		duk__advance(comp_ctx);  /* eat 'var' */
		duk__parse_var_decl(comp_ctx, res, DUK__EXPR_FLAG_REJECT_IN, &reg_varbind, &rc_varname);
		DUK__SETTEMP(comp_ctx, temp_reset);

		if (comp_ctx->curr_token.t == DUK_TOK_IN) {
			/*
			 *  Variant 4
			 */

			DUK_DDD(DUK_DDDPRINT("detected for variant 4: for (var VariableDeclarationNoIn in Expression) Statement"));
			pc_v34_lhs = duk__get_current_pc(comp_ctx);  /* jump is inserted here */
			if (reg_varbind >= 0) {
				duk__emit_a_bc(comp_ctx,
				               DUK_OP_LDREG,
				               reg_varbind,
				               reg_temps + 0);
			} else {
				duk__emit_a_bc(comp_ctx,
				               DUK_OP_PUTVAR | DUK__EMIT_FLAG_A_IS_SOURCE,
				               reg_temps + 0,
				               rc_varname);
			}
			goto parse_3_or_4;
		} else {
			/*
			 *  Variant 2
			 */

			DUK_DDD(DUK_DDDPRINT("detected for variant 2: for (var VariableDeclarationNoIn; Expression_opt; Expression_opt) Statement"));
			for (;;) {
				/* more initializers */
				if (comp_ctx->curr_token.t != DUK_TOK_COMMA) {
					break;
				}
				DUK_DDD(DUK_DDDPRINT("variant 2 has another variable initializer"));

				duk__advance(comp_ctx);  /* eat comma */
				duk__parse_var_decl(comp_ctx, res, DUK__EXPR_FLAG_REJECT_IN, &reg_varbind, &rc_varname);
			}
			goto parse_1_or_2;
		}
	} else {
		/*
		 *  Variant 1 or 3
		 */

		pc_v34_lhs = duk__get_current_pc(comp_ctx);  /* jump is inserted here (variant 3) */

		/* Note that duk__exprtop() here can clobber any reg above current temp_next,
		 * so any loop variables (e.g. enumerator) must be "preallocated".
		 */

		/* don't coerce yet to a plain value (variant 3 needs special handling) */
		duk__exprtop(comp_ctx, res, DUK__BP_FOR_EXPR | DUK__EXPR_FLAG_REJECT_IN | DUK__EXPR_FLAG_ALLOW_EMPTY /*rbp_flags*/);  /* Expression */
		if (comp_ctx->curr_token.t == DUK_TOK_IN) {
			/*
			 *  Variant 3
			 */

			/* XXX: need to determine LHS type, and check that it is LHS compatible */
			DUK_DDD(DUK_DDDPRINT("detected for variant 3: for (LeftHandSideExpression in Expression) Statement"));
			if (duk__expr_is_empty(comp_ctx)) {
				goto syntax_error;  /* LeftHandSideExpression does not allow empty expression */
			}

			if (res->t == DUK_IVAL_VAR) {
				duk_regconst_t reg_varbind;
				duk_regconst_t rc_varname;

				duk_dup(thr, res->x1.valstack_idx);
				if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
					duk__emit_a_bc(comp_ctx,
					               DUK_OP_LDREG,
					               reg_varbind,
					               reg_temps + 0);
				} else {
					duk__emit_a_bc(comp_ctx,
					               DUK_OP_PUTVAR | DUK__EMIT_FLAG_A_IS_SOURCE,
					               reg_temps + 0,
					               rc_varname);
				}
			} else if (res->t == DUK_IVAL_PROP) {
				/* Don't allow a constant for the object (even for a number etc), as
				 * it goes into the 'A' field of the opcode.
				 */
				duk_regconst_t reg_obj;
				duk_regconst_t rc_key;
				reg_obj = duk__ispec_toregconst_raw(comp_ctx, &res->x1, -1 /*forced_reg*/, 0 /*flags*/);  /* don't allow const */
				rc_key = duk__ispec_toregconst_raw(comp_ctx, &res->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
				duk__emit_a_b_c(comp_ctx,
				                DUK_OP_PUTPROP | DUK__EMIT_FLAG_A_IS_SOURCE | DUK__EMIT_FLAG_BC_REGCONST,
				                reg_obj,
				                rc_key,
				                reg_temps + 0);
			} else {
				duk__ivalue_toplain_ignore(comp_ctx, res);  /* just in case */
				duk__emit_op_only(comp_ctx,
				                  DUK_OP_INVLHS);
			}
			goto parse_3_or_4;
		} else {
			/*
			 *  Variant 1
			 */

			DUK_DDD(DUK_DDDPRINT("detected for variant 1: for (ExpressionNoIn_opt; Expression_opt; Expression_opt) Statement"));
			duk__ivalue_toplain_ignore(comp_ctx, res);
			goto parse_1_or_2;
		}
	}

 parse_1_or_2:
	/*
	 *  Parse variant 1 or 2.  The first part expression (which differs
	 *  in the variants) has already been parsed and its code emitted.
	 *
	 *  reg_temps + 0: unused
	 *  reg_temps + 1: unused
	 */
	{
		duk_regconst_t rc_cond;
		duk_int_t pc_l1, pc_l2, pc_l3, pc_l4;
		duk_int_t pc_jumpto_l3, pc_jumpto_l4;
		duk_bool_t expr_c_empty;

		DUK_DDD(DUK_DDDPRINT("shared code for parsing variants 1 and 2"));

		/* "release" preallocated temps since we won't need them */
		temp_reset = reg_temps + 0;
		DUK__SETTEMP(comp_ctx, temp_reset);

		duk__advance_expect(comp_ctx, DUK_TOK_SEMICOLON);

		pc_l1 = duk__get_current_pc(comp_ctx);
		duk__exprtop(comp_ctx, res, DUK__BP_FOR_EXPR | DUK__EXPR_FLAG_ALLOW_EMPTY /*rbp_flags*/);  /* Expression_opt */
		if (duk__expr_is_empty(comp_ctx)) {
			/* no need to coerce */
			pc_jumpto_l3 = duk__emit_jump_empty(comp_ctx);  /* to body */
			pc_jumpto_l4 = -1;  /* omitted */
		} else {
			rc_cond = duk__ivalue_toregconst(comp_ctx, res);
			duk__emit_if_false_skip(comp_ctx, rc_cond);
			pc_jumpto_l3 = duk__emit_jump_empty(comp_ctx);  /* to body */
			pc_jumpto_l4 = duk__emit_jump_empty(comp_ctx);  /* to exit */
		}
		DUK__SETTEMP(comp_ctx, temp_reset);

		duk__advance_expect(comp_ctx, DUK_TOK_SEMICOLON);

		pc_l2 = duk__get_current_pc(comp_ctx);
		duk__exprtop(comp_ctx, res, DUK__BP_FOR_EXPR | DUK__EXPR_FLAG_ALLOW_EMPTY /*rbp_flags*/);  /* Expression_opt */
		if (duk__expr_is_empty(comp_ctx)) {
			/* no need to coerce */
			expr_c_empty = 1;
			/* JUMP L1 omitted */
		} else {
			duk__ivalue_toplain_ignore(comp_ctx, res);
			expr_c_empty = 0;
			duk__emit_jump(comp_ctx, pc_l1);
		}
		DUK__SETTEMP(comp_ctx, temp_reset);

		comp_ctx->curr_func.allow_regexp_in_adv = 1;
		duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);  /* Allow RegExp as part of next stmt. */

		pc_l3 = duk__get_current_pc(comp_ctx);
		duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
		if (expr_c_empty) {
			duk__emit_jump(comp_ctx, pc_l1);
		} else {
			duk__emit_jump(comp_ctx, pc_l2);
		}
		/* temp reset is not necessary after duk__parse_stmt(), which already does it */

		pc_l4 = duk__get_current_pc(comp_ctx);

		DUK_DDD(DUK_DDDPRINT("patching jumps: jumpto_l3: %ld->%ld, jumpto_l4: %ld->%ld, "
		                     "break: %ld->%ld, continue: %ld->%ld",
			             (long) pc_jumpto_l3, (long) pc_l3, (long) pc_jumpto_l4, (long) pc_l4,
		                     (long) (pc_label_site + 1), (long) pc_l4, (long) (pc_label_site + 2), (long) pc_l2));

		duk__patch_jump(comp_ctx, pc_jumpto_l3, pc_l3);
		duk__patch_jump(comp_ctx, pc_jumpto_l4, pc_l4);
		duk__patch_jump(comp_ctx,
		                pc_label_site + 1,
		                pc_l4);                         /* break jump */
		duk__patch_jump(comp_ctx,
		                pc_label_site + 2,
		                expr_c_empty ? pc_l1 : pc_l2);  /* continue jump */
	}
	goto finished;

 parse_3_or_4:
	/*
	 *  Parse variant 3 or 4.
	 *
	 *  For variant 3 (e.g. "for (A in C) D;") the code for A (except the
	 *  final property/variable write) has already been emitted.  The first
	 *  instruction of that code is at pc_v34_lhs; a JUMP needs to be inserted
	 *  there to satisfy control flow needs.
	 *
	 *  For variant 4, if the variable declaration had an initializer
	 *  (e.g. "for (var A = B in C) D;") the code for the assignment
	 *  (B) has already been emitted.
	 *
	 *  Variables set before entering here:
	 *
	 *    pc_v34_lhs:    insert a "JUMP L2" here (see doc/compiler.rst example).
	 *    reg_temps + 0: iteration target value (written to LHS)
	 *    reg_temps + 1: enumerator object
	 */
	{
		duk_int_t pc_l1, pc_l2, pc_l3, pc_l4, pc_l5;
		duk_int_t pc_jumpto_l2, pc_jumpto_l3, pc_jumpto_l4, pc_jumpto_l5;
		duk_regconst_t reg_target;

		DUK_DDD(DUK_DDDPRINT("shared code for parsing variants 3 and 4, pc_v34_lhs=%ld", (long) pc_v34_lhs));

		DUK__SETTEMP(comp_ctx, temp_reset);

		/* First we need to insert a jump in the middle of previously
		 * emitted code to get the control flow right.  No jumps can
		 * cross the position where the jump is inserted.  See doc/compiler.rst
		 * for discussion on the intricacies of control flow and side effects
		 * for variants 3 and 4.
		 */

		duk__insert_jump_entry(comp_ctx, pc_v34_lhs);
		pc_jumpto_l2 = pc_v34_lhs;  /* inserted jump */
		pc_l1 = pc_v34_lhs + 1;     /* +1, right after inserted jump */

		/* The code for writing reg_temps + 0 to the left hand side has already
		 * been emitted.
		 */

		pc_jumpto_l3 = duk__emit_jump_empty(comp_ctx);  /* -> loop body */

		duk__advance(comp_ctx);  /* eat 'in' */

		/* Parse enumeration target and initialize enumerator.  For 'null' and 'undefined',
		 * INITENUM will creates a 'null' enumerator which works like an empty enumerator
		 * (E5 Section 12.6.4, step 3).  Note that INITENUM requires the value to be in a
		 * register (constant not allowed).
		 */

		pc_l2 = duk__get_current_pc(comp_ctx);
		reg_target = duk__exprtop_toreg(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);  /* Expression */
		duk__emit_b_c(comp_ctx,
		              DUK_OP_INITENUM | DUK__EMIT_FLAG_B_IS_TARGET,
		              reg_temps + 1,
		              reg_target);
		pc_jumpto_l4 = duk__emit_jump_empty(comp_ctx);
		DUK__SETTEMP(comp_ctx, temp_reset);

		comp_ctx->curr_func.allow_regexp_in_adv = 1;
		duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);  /* Allow RegExp as part of next stmt. */

		pc_l3 = duk__get_current_pc(comp_ctx);
		duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
		/* temp reset is not necessary after duk__parse_stmt(), which already does it */

		/* NEXTENUM needs a jump slot right after the main opcode.
		 * We need the code emitter to reserve the slot: if there's
		 * target shuffling, the target shuffle opcodes must happen
		 * after the jump slot (for NEXTENUM the shuffle opcodes are
		 * not needed if the enum is finished).
		 */
		pc_l4 = duk__get_current_pc(comp_ctx);
		duk__emit_b_c(comp_ctx,
		              DUK_OP_NEXTENUM | DUK__EMIT_FLAG_B_IS_TARGET | DUK__EMIT_FLAG_RESERVE_JUMPSLOT,
		              reg_temps + 0,
		              reg_temps + 1);
		pc_jumpto_l5 = comp_ctx->emit_jumpslot_pc;  /* NEXTENUM jump slot: executed when enum finished */
		duk__emit_jump(comp_ctx, pc_l1);  /* jump to next loop, using reg_v34_iter as iterated value */

		pc_l5 = duk__get_current_pc(comp_ctx);

		/* XXX: since the enumerator may be a memory expensive object,
		 * perhaps clear it explicitly here?  If so, break jump must
		 * go through this clearing operation.
		 */

		DUK_DDD(DUK_DDDPRINT("patching jumps: jumpto_l2: %ld->%ld, jumpto_l3: %ld->%ld, "
		                     "jumpto_l4: %ld->%ld, jumpto_l5: %ld->%ld, "
		                     "break: %ld->%ld, continue: %ld->%ld",
			             (long) pc_jumpto_l2, (long) pc_l2, (long) pc_jumpto_l3, (long) pc_l3,
			             (long) pc_jumpto_l4, (long) pc_l4, (long) pc_jumpto_l5, (long) pc_l5,
		                     (long) (pc_label_site + 1), (long) pc_l5, (long) (pc_label_site + 2), (long) pc_l4));

		duk__patch_jump(comp_ctx, pc_jumpto_l2, pc_l2);
		duk__patch_jump(comp_ctx, pc_jumpto_l3, pc_l3);
		duk__patch_jump(comp_ctx, pc_jumpto_l4, pc_l4);
		duk__patch_jump(comp_ctx, pc_jumpto_l5, pc_l5);
		duk__patch_jump(comp_ctx, pc_label_site + 1, pc_l5);  /* break jump */
		duk__patch_jump(comp_ctx, pc_label_site + 2, pc_l4);  /* continue jump */
	}
	goto finished;

 finished:
	DUK_DDD(DUK_DDDPRINT("end parsing a for/for-in statement"));
	return;

 syntax_error:
	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_FOR);
	DUK_WO_NORETURN(return;);
}

DUK_LOCAL void duk__parse_switch_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {
	duk_hthread *thr = comp_ctx->thr;
	duk_regconst_t temp_at_loop;
	duk_regconst_t rc_switch;    /* reg/const for switch value */
	duk_regconst_t rc_case;      /* reg/const for case value */
	duk_regconst_t reg_temp;     /* general temp register */
	duk_int_t pc_prevcase = -1;
	duk_int_t pc_prevstmt = -1;
	duk_int_t pc_default = -1;   /* -1 == not set, -2 == pending (next statement list) */

	/* Note: negative pc values are ignored when patching jumps, so no explicit checks needed */

	/*
	 *  Switch is pretty complicated because of several conflicting concerns:
	 *
	 *    - Want to generate code without an intermediate representation,
	 *      i.e., in one go
	 *
	 *    - Case selectors are expressions, not values, and may thus e.g. throw
	 *      exceptions (which causes evaluation order concerns)
	 *
	 *    - Evaluation semantics of case selectors and default clause need to be
	 *      carefully implemented to provide correct behavior even with case value
	 *      side effects
	 *
	 *    - Fall through case and default clauses; avoiding dead JUMPs if case
	 *      ends with an unconditional jump (a break or a continue)
	 *
	 *    - The same case value may occur multiple times, but evaluation rules
	 *      only process the first match before switching to a "propagation" mode
	 *      where case values are no longer evaluated
	 *
	 *  See E5 Section 12.11.  Also see doc/compiler.rst for compilation
	 *  discussion.
	 */

	duk__advance(comp_ctx);
	duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
	rc_switch = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
	duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);  /* RegExp mode does not matter. */
	duk__advance_expect(comp_ctx, DUK_TOK_LCURLY);

	DUK_DDD(DUK_DDDPRINT("switch value in register %ld", (long) rc_switch));

	temp_at_loop = DUK__GETTEMP(comp_ctx);

	for (;;) {
		duk_int_t num_stmts;
		duk_small_uint_t tok;

		/* sufficient for keeping temp reg numbers in check */
		DUK__SETTEMP(comp_ctx, temp_at_loop);

		if (comp_ctx->curr_token.t == DUK_TOK_RCURLY) {
			break;
		}

		/*
		 *  Parse a case or default clause.
		 */

		if (comp_ctx->curr_token.t == DUK_TOK_CASE) {
			/*
			 *  Case clause.
			 *
			 *  Note: cannot use reg_case as a temp register (for SEQ target)
			 *  because it may be a constant.
			 */

			duk__patch_jump_here(comp_ctx, pc_prevcase);  /* chain jumps for case
			                                               * evaluation and checking
			                                               */

			duk__advance(comp_ctx);
			rc_case = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
			duk__advance_expect(comp_ctx, DUK_TOK_COLON);

			reg_temp = DUK__ALLOCTEMP(comp_ctx);
			duk__emit_a_b_c(comp_ctx,
			                DUK_OP_SEQ | DUK__EMIT_FLAG_BC_REGCONST,
			                reg_temp,
			                rc_switch,
			                rc_case);
			duk__emit_if_true_skip(comp_ctx, reg_temp);

			/* jump to next case clause */
			pc_prevcase = duk__emit_jump_empty(comp_ctx);  /* no match, next case */

			/* statements go here (if any) on next loop */
		} else if (comp_ctx->curr_token.t == DUK_TOK_DEFAULT) {
			/*
			 *  Default clause.
			 */

			if (pc_default >= 0) {
				goto syntax_error;
			}
			duk__advance(comp_ctx);
			duk__advance_expect(comp_ctx, DUK_TOK_COLON);

			/* Fix for https://github.com/svaarala/duktape/issues/155:
			 * If 'default' is first clause (detected by pc_prevcase < 0)
			 * we need to ensure we stay in the matching chain.
			 */
			if (pc_prevcase < 0) {
				DUK_DD(DUK_DDPRINT("default clause is first, emit prevcase jump"));
				pc_prevcase = duk__emit_jump_empty(comp_ctx);
			}

			/* default clause matches next statement list (if any) */
			pc_default = -2;
		} else {
			/* Code is not accepted before the first case/default clause */
			goto syntax_error;
		}

		/*
		 *  Parse code after the clause.  Possible terminators are
		 *  'case', 'default', and '}'.
		 *
		 *  Note that there may be no code at all, not even an empty statement,
		 *  between case clauses.  This must be handled just like an empty statement
		 *  (omitting seemingly pointless JUMPs), to avoid situations like
		 *  test-bug-case-fallthrough.js.
		 */

		num_stmts = 0;
		if (pc_default == -2) {
			pc_default = duk__get_current_pc(comp_ctx);
		}

		/* Note: this is correct even for default clause statements:
		 * they participate in 'fall-through' behavior even if the
		 * default clause is in the middle.
		 */
		duk__patch_jump_here(comp_ctx, pc_prevstmt);  /* chain jumps for 'fall-through'
		                                               * after a case matches.
		                                               */

		for (;;) {
			tok = comp_ctx->curr_token.t;
			if (tok == DUK_TOK_CASE || tok == DUK_TOK_DEFAULT ||
			    tok == DUK_TOK_RCURLY) {
				break;
			}
			num_stmts++;
			duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
		}

		/* fall-through jump to next code of next case (backpatched) */
		pc_prevstmt = duk__emit_jump_empty(comp_ctx);

		/* XXX: would be nice to omit this jump when the jump is not
		 * reachable, at least in the obvious cases (such as the case
		 * ending with a 'break'.
		 *
		 * Perhaps duk__parse_stmt() could provide some info on whether
		 * the statement is a "dead end"?
		 *
		 * If implemented, just set pc_prevstmt to -1 when not needed.
		 */
	}

	DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_RCURLY);
	comp_ctx->curr_func.allow_regexp_in_adv = 1;
	duk__advance(comp_ctx);  /* Allow RegExp as part of next stmt. */

	/* default case control flow patchup; note that if pc_prevcase < 0
	 * (i.e. no case clauses), control enters default case automatically.
	 */
	if (pc_default >= 0) {
		/* default case exists: go there if no case matches */
		duk__patch_jump(comp_ctx, pc_prevcase, pc_default);
	} else {
		/* default case does not exist, or no statements present
		 * after default case: finish case evaluation
		 */
		duk__patch_jump_here(comp_ctx, pc_prevcase);
	}

	/* fall-through control flow patchup; note that pc_prevstmt may be
	 * < 0 (i.e. no case clauses), in which case this is a no-op.
	 */
	duk__patch_jump_here(comp_ctx, pc_prevstmt);

	/* continue jump not patched, an INVALID opcode remains there */
	duk__patch_jump_here(comp_ctx, pc_label_site + 1);  /* break jump */

	/* Note: 'fast' breaks will jump to pc_label_site + 1, which will
	 * then jump here.  The double jump will be eliminated by a
	 * peephole pass, resulting in an optimal jump here.  The label
	 * site jumps will remain in bytecode and will waste code size.
	 */

	return;

 syntax_error:
	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_SWITCH);
	DUK_WO_NORETURN(return;);
}

DUK_LOCAL void duk__parse_if_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
	duk_regconst_t temp_reset;
	duk_regconst_t rc_cond;
	duk_int_t pc_jump_false;

	DUK_DDD(DUK_DDDPRINT("begin parsing if statement"));

	temp_reset = DUK__GETTEMP(comp_ctx);

	duk__advance(comp_ctx);  /* eat 'if' */
	duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);

	rc_cond = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
	duk__emit_if_true_skip(comp_ctx, rc_cond);
	pc_jump_false = duk__emit_jump_empty(comp_ctx);  /* jump to end or else part */
	DUK__SETTEMP(comp_ctx, temp_reset);

	comp_ctx->curr_func.allow_regexp_in_adv = 1;
	duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);  /* Allow RegExp as part of next stmt. */

	duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);

	/* The 'else' ambiguity is resolved by 'else' binding to the innermost
	 * construct, so greedy matching is correct here.
	 */

	if (comp_ctx->curr_token.t == DUK_TOK_ELSE) {
		duk_int_t pc_jump_end;

		DUK_DDD(DUK_DDDPRINT("if has else part"));

		duk__advance(comp_ctx);

		pc_jump_end = duk__emit_jump_empty(comp_ctx);  /* jump from true part to end */
		duk__patch_jump_here(comp_ctx, pc_jump_false);

		duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);

		duk__patch_jump_here(comp_ctx, pc_jump_end);
	} else {
		DUK_DDD(DUK_DDDPRINT("if does not have else part"));

		duk__patch_jump_here(comp_ctx, pc_jump_false);
	}

	DUK_DDD(DUK_DDDPRINT("end parsing if statement"));
}

DUK_LOCAL void duk__parse_do_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {
	duk_regconst_t rc_cond;
	duk_int_t pc_start;

	DUK_DDD(DUK_DDDPRINT("begin parsing do statement"));

	duk__advance(comp_ctx);  /* Eat 'do'; allow RegExp as part of next stmt. */

	pc_start = duk__get_current_pc(comp_ctx);
	duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
	duk__patch_jump_here(comp_ctx, pc_label_site + 2);  /* continue jump */

	duk__advance_expect(comp_ctx, DUK_TOK_WHILE);
	duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);

	rc_cond = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
	duk__emit_if_false_skip(comp_ctx, rc_cond);
	duk__emit_jump(comp_ctx, pc_start);
	/* no need to reset temps, as we're finished emitting code */

	comp_ctx->curr_func.allow_regexp_in_adv = 1;  /* Allow RegExp as part of next stmt. */
	duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);

	duk__patch_jump_here(comp_ctx, pc_label_site + 1);  /* break jump */

	DUK_DDD(DUK_DDDPRINT("end parsing do statement"));
}

DUK_LOCAL void duk__parse_while_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {
	duk_regconst_t temp_reset;
	duk_regconst_t rc_cond;
	duk_int_t pc_start;
	duk_int_t pc_jump_false;

	DUK_DDD(DUK_DDDPRINT("begin parsing while statement"));

	temp_reset = DUK__GETTEMP(comp_ctx);

	duk__advance(comp_ctx);  /* eat 'while' */

	duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);

	pc_start = duk__get_current_pc(comp_ctx);
	duk__patch_jump_here(comp_ctx, pc_label_site + 2);  /* continue jump */

	rc_cond = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
	duk__emit_if_true_skip(comp_ctx, rc_cond);
	pc_jump_false = duk__emit_jump_empty(comp_ctx);
	DUK__SETTEMP(comp_ctx, temp_reset);

	comp_ctx->curr_func.allow_regexp_in_adv = 1;
	duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);  /* Allow RegExp as part of next stmt. */

	duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
	duk__emit_jump(comp_ctx, pc_start);

	duk__patch_jump_here(comp_ctx, pc_jump_false);
	duk__patch_jump_here(comp_ctx, pc_label_site + 1);  /* break jump */

	DUK_DDD(DUK_DDDPRINT("end parsing while statement"));
}

DUK_LOCAL void duk__parse_break_or_continue_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
	duk_hthread *thr = comp_ctx->thr;
	duk_bool_t is_break = (comp_ctx->curr_token.t == DUK_TOK_BREAK);
	duk_int_t label_id;
	duk_int_t label_catch_depth;
	duk_int_t label_pc;  /* points to LABEL; pc+1 = jump site for break; pc+2 = jump site for continue */
	duk_bool_t label_is_closest;

	DUK_UNREF(res);

	duk__advance(comp_ctx);  /* eat 'break' or 'continue' */

	if (comp_ctx->curr_token.t == DUK_TOK_SEMICOLON ||  /* explicit semi follows */
	    comp_ctx->curr_token.lineterm ||                /* automatic semi will be inserted */
	    comp_ctx->curr_token.allow_auto_semi) {         /* automatic semi will be inserted */
		/* break/continue without label */

		duk__lookup_active_label(comp_ctx, DUK_HTHREAD_STRING_EMPTY_STRING(thr), is_break, &label_id, &label_catch_depth, &label_pc, &label_is_closest);
	} else if (comp_ctx->curr_token.t == DUK_TOK_IDENTIFIER) {
		/* break/continue with label (label cannot be a reserved word, production is 'Identifier' */
		DUK_ASSERT(comp_ctx->curr_token.str1 != NULL);
		duk__lookup_active_label(comp_ctx, comp_ctx->curr_token.str1, is_break, &label_id, &label_catch_depth, &label_pc, &label_is_closest);
		duk__advance(comp_ctx);
	} else {
		DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_BREAK_CONT_LABEL);
		DUK_WO_NORETURN(return;);
	}

	/* Use a fast break/continue when possible.  A fast break/continue is
	 * just a jump to the LABEL break/continue jump slot, which then jumps
	 * to an appropriate place (for break, going through ENDLABEL correctly).
	 * The peephole optimizer will optimize the jump to a direct one.
	 */

	if (label_catch_depth == comp_ctx->curr_func.catch_depth &&
	    label_is_closest) {
		DUK_DDD(DUK_DDDPRINT("break/continue: is_break=%ld, label_id=%ld, label_is_closest=%ld, "
		                     "label_catch_depth=%ld, catch_depth=%ld "
		                     "-> use fast variant (direct jump)",
		                     (long) is_break, (long) label_id, (long) label_is_closest,
		                     (long) label_catch_depth, (long) comp_ctx->curr_func.catch_depth));

		duk__emit_jump(comp_ctx, label_pc + (is_break ? 1 : 2));
	} else {
		DUK_DDD(DUK_DDDPRINT("break/continue: is_break=%ld, label_id=%ld, label_is_closest=%ld, "
		                     "label_catch_depth=%ld, catch_depth=%ld "
		                     "-> use slow variant (longjmp)",
		                     (long) is_break, (long) label_id, (long) label_is_closest,
		                     (long) label_catch_depth, (long) comp_ctx->curr_func.catch_depth));

		duk__emit_bc(comp_ctx,
		             is_break ? DUK_OP_BREAK : DUK_OP_CONTINUE,
		             (duk_regconst_t) label_id);
	}
}

DUK_LOCAL void duk__parse_return_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
	duk_hthread *thr = comp_ctx->thr;
	duk_regconst_t rc_val;

	duk__advance(comp_ctx);  /* eat 'return' */

	/* A 'return' statement is only allowed inside an actual function body,
	 * not as part of eval or global code.
	 */
	if (!comp_ctx->curr_func.is_function) {
		DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_RETURN);
		DUK_WO_NORETURN(return;);
	}

	if (comp_ctx->curr_token.t == DUK_TOK_SEMICOLON ||  /* explicit semi follows */
	    comp_ctx->curr_token.lineterm ||                /* automatic semi will be inserted */
	    comp_ctx->curr_token.allow_auto_semi) {         /* automatic semi will be inserted */
		DUK_DDD(DUK_DDDPRINT("empty return value -> undefined"));
		duk__emit_op_only(comp_ctx, DUK_OP_RETUNDEF);
	} else {
		duk_int_t pc_before_expr;
		duk_int_t pc_after_expr;

		DUK_DDD(DUK_DDDPRINT("return with a value"));

		DUK_UNREF(pc_before_expr);
		DUK_UNREF(pc_after_expr);

		pc_before_expr = duk__get_current_pc(comp_ctx);
		rc_val = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
		pc_after_expr = duk__get_current_pc(comp_ctx);

		/* Tail call check: if last opcode emitted was CALL, and
		 * the context allows it, add a tailcall flag to the CALL.
		 * This doesn't guarantee that a tail call will be allowed at
		 * runtime, so the RETURN must still be emitted.  (Duktape
		 * 0.10.0 avoided this and simulated a RETURN if a tail call
		 * couldn't be used at runtime; but this didn't work
		 * correctly with a thread yield/resume, see
		 * test-bug-tailcall-thread-yield-resume.js for discussion.)
		 *
		 * In addition to the last opcode being CALL, we also need to
		 * be sure that 'rc_val' is the result register of the CALL.
		 * For instance, for the expression 'return 0, (function ()
		 * { return 1; }), 2' the last opcode emitted is CALL (no
		 * bytecode is emitted for '2') but 'rc_val' indicates
		 * constant '2'.  Similarly if '2' is replaced by a register
		 * bound variable, no opcodes are emitted but tail call would
		 * be incorrect.
		 *
		 * This is tricky and easy to get wrong.  It would be best to
		 * track enough expression metadata to check that 'rc_val' came
		 * from that last CALL instruction.  We don't have that metadata
		 * now, so we check that 'rc_val' is a temporary register result
		 * (not a constant or a register bound variable).  There should
		 * be no way currently for 'rc_val' to be a temporary for an
		 * expression following the CALL instruction without emitting
		 * some opcodes following the CALL.  This proxy check is used
		 * below.
		 *
		 * See: test-bug-comma-expr-gh131.js.
		 *
		 * The non-standard 'caller' property disables tail calls
		 * because they pose some special cases which haven't been
		 * fixed yet.
		 */

#if defined(DUK_USE_TAILCALL)
		if (comp_ctx->curr_func.catch_depth == 0 &&   /* no catchers */
		    pc_after_expr > pc_before_expr) {         /* at least one opcode emitted */
			duk_compiler_instr *instr;
			duk_instr_t ins;
			duk_small_uint_t op;

			instr = duk__get_instr_ptr(comp_ctx, pc_after_expr - 1);
			DUK_ASSERT(instr != NULL);

			ins = instr->ins;
			op = (duk_small_uint_t) DUK_DEC_OP(ins);
			if ((op & ~0x0fU) == DUK_OP_CALL0 &&
			    DUK__ISREG_TEMP(comp_ctx, rc_val) /* see above */) {
				DUK_DDD(DUK_DDDPRINT("return statement detected a tail call opportunity: "
				                     "catch depth is 0, duk__exprtop() emitted >= 1 instructions, "
				                     "and last instruction is a CALL "
				                     "-> change to TAILCALL"));
				ins |= DUK_ENC_OP(DUK_BC_CALL_FLAG_TAILCALL);
				instr->ins = ins;
			}
		}
#endif  /* DUK_USE_TAILCALL */

		if (DUK__ISREG(rc_val)) {
			duk__emit_bc(comp_ctx, DUK_OP_RETREG, rc_val);
		} else {
			rc_val = DUK__REMOVECONST(rc_val);
			if (duk__const_needs_refcount(comp_ctx, rc_val)) {
				duk__emit_bc(comp_ctx, DUK_OP_RETCONST, rc_val);
			} else {
				duk__emit_bc(comp_ctx, DUK_OP_RETCONSTN, rc_val);
			}
		}
	}
}

DUK_LOCAL void duk__parse_throw_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
	duk_regconst_t reg_val;

	duk__advance(comp_ctx);  /* eat 'throw' */

	/* Unlike break/continue, throw statement does not allow an empty value. */

	if (comp_ctx->curr_token.lineterm) {
		DUK_ERROR_SYNTAX(comp_ctx->thr, DUK_STR_INVALID_THROW);
		DUK_WO_NORETURN(return;);
	}

	reg_val = duk__exprtop_toreg(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
	duk__emit_bc(comp_ctx,
	             DUK_OP_THROW,
	             reg_val);
}

DUK_LOCAL void duk__parse_try_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
	duk_hthread *thr = comp_ctx->thr;
	duk_regconst_t reg_catch;      /* reg_catch+0 and reg_catch+1 are reserved for TRYCATCH */
	duk_regconst_t rc_varname = 0;
	duk_small_uint_t trycatch_flags = 0;
	duk_int_t pc_ldconst = -1;
	duk_int_t pc_trycatch = -1;
	duk_int_t pc_catch = -1;
	duk_int_t pc_finally = -1;

	DUK_UNREF(res);

	/*
	 *  See the following documentation for discussion:
	 *
	 *    doc/execution.rst: control flow details
	 *
	 *  Try, catch, and finally "parts" are Blocks, not Statements, so
	 *  they must always be delimited by curly braces.  This is unlike e.g.
	 *  the if statement, which accepts any Statement.  This eliminates any
	 *  questions of matching parts of nested try statements.  The Block
	 *  parsing is implemented inline here (instead of calling out).
	 *
	 *  Finally part has a 'let scoped' variable, which requires a few kinks
	 *  here.
	 */

	comp_ctx->curr_func.catch_depth++;

	duk__advance(comp_ctx);  /* eat 'try' */

	reg_catch = DUK__ALLOCTEMPS(comp_ctx, 2);

	/* The target for this LDCONST may need output shuffling, but we assume
	 * that 'pc_ldconst' will be the LDCONST that we can patch later.  This
	 * should be the case because there's no input shuffling.  (If there's
	 * no catch clause, this LDCONST will be replaced with a NOP.)
	 */
	pc_ldconst = duk__get_current_pc(comp_ctx);
	duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, reg_catch, 0 /*patched later*/);

	pc_trycatch = duk__get_current_pc(comp_ctx);
	duk__emit_invalid(comp_ctx);  /* TRYCATCH, cannot emit now (not enough info) */
	duk__emit_invalid(comp_ctx);  /* jump for 'catch' case */
	duk__emit_invalid(comp_ctx);  /* jump for 'finally' case or end (if no finally) */

	/* try part */
	duk__advance_expect(comp_ctx, DUK_TOK_LCURLY);
	duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/, 1 /*regexp_after*/);
	/* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */
	duk__emit_op_only(comp_ctx, DUK_OP_ENDTRY);

	if (comp_ctx->curr_token.t == DUK_TOK_CATCH) {
		/*
		 *  The catch variable must be updated to reflect the new allocated
		 *  register for the duration of the catch clause.  We need to store
		 *  and restore the original value for the varmap entry (if any).
		 */

		/*
		 *  Note: currently register bindings must be fixed for the entire
		 *  function.  So, even though the catch variable is in a register
		 *  we know, we must use an explicit environment record and slow path
		 *  accesses to read/write the catch binding to make closures created
		 *  within the catch clause work correctly.  This restriction should
		 *  be fixable (at least in common cases) later.
		 *
		 *  See: test-bug-catch-binding-2.js.
		 *
		 *  XXX: improve to get fast path access to most catch clauses.
		 */

		duk_hstring *h_var;
		duk_int_t varmap_value;  /* for storing/restoring the varmap binding for catch variable */

		DUK_DDD(DUK_DDDPRINT("stack top at start of catch clause: %ld", (long) duk_get_top(thr)));

		trycatch_flags |= DUK_BC_TRYCATCH_FLAG_HAVE_CATCH;

		pc_catch = duk__get_current_pc(comp_ctx);

		duk__advance(comp_ctx);
		duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);

		if (comp_ctx->curr_token.t != DUK_TOK_IDENTIFIER) {
			/* Identifier, i.e. don't allow reserved words */
			goto syntax_error;
		}
		h_var = comp_ctx->curr_token.str1;
		DUK_ASSERT(h_var != NULL);

		duk_push_hstring(thr, h_var);  /* keep in on valstack, use borrowed ref below */

		if (comp_ctx->curr_func.is_strict &&
		    ((h_var == DUK_HTHREAD_STRING_EVAL(thr)) ||
		     (h_var == DUK_HTHREAD_STRING_LC_ARGUMENTS(thr)))) {
			DUK_DDD(DUK_DDDPRINT("catch identifier 'eval' or 'arguments' in strict mode -> SyntaxError"));
			goto syntax_error;
		}

		duk_dup_top(thr);
		rc_varname = duk__getconst(comp_ctx);
		DUK_DDD(DUK_DDDPRINT("catch clause, rc_varname=0x%08lx (%ld)",
		                     (unsigned long) rc_varname, (long) rc_varname));

		duk__advance(comp_ctx);
		duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);

		duk__advance_expect(comp_ctx, DUK_TOK_LCURLY);

		DUK_DDD(DUK_DDDPRINT("varmap before modifying for catch clause: %!iT",
		                     (duk_tval *) duk_get_tval(thr, comp_ctx->curr_func.varmap_idx)));

		duk_dup_top(thr);
		duk_get_prop(thr, comp_ctx->curr_func.varmap_idx);
		if (duk_is_undefined(thr, -1)) {
			varmap_value = -2;
		} else if (duk_is_null(thr, -1)) {
			varmap_value = -1;
		} else {
			DUK_ASSERT(duk_is_number(thr, -1));
			varmap_value = duk_get_int(thr, -1);
			DUK_ASSERT(varmap_value >= 0);
		}
		duk_pop(thr);

#if 0
		/* It'd be nice to do something like this - but it doesn't
		 * work for closures created inside the catch clause.
		 */
		duk_dup_top(thr);
		duk_push_int(thr, (duk_int_t) (reg_catch + 0));
		duk_put_prop(thr, comp_ctx->curr_func.varmap_idx);
#endif
		duk_dup_top(thr);
		duk_push_null(thr);
		duk_put_prop(thr, comp_ctx->curr_func.varmap_idx);

		duk__emit_a_bc(comp_ctx,
		               DUK_OP_PUTVAR | DUK__EMIT_FLAG_A_IS_SOURCE,
		               reg_catch + 0 /*value*/,
		               rc_varname /*varname*/);

		DUK_DDD(DUK_DDDPRINT("varmap before parsing catch clause: %!iT",
		                     (duk_tval *) duk_get_tval(thr, comp_ctx->curr_func.varmap_idx)));

		duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/, 1 /*regexp_after*/);
		/* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */

		if (varmap_value == -2) {
			/* not present */
			duk_del_prop(thr, comp_ctx->curr_func.varmap_idx);
		} else {
			if (varmap_value == -1) {
				duk_push_null(thr);
			} else {
				DUK_ASSERT(varmap_value >= 0);
				duk_push_int(thr, varmap_value);
			}
			duk_put_prop(thr, comp_ctx->curr_func.varmap_idx);
		}
		/* varname is popped by above code */

		DUK_DDD(DUK_DDDPRINT("varmap after restore catch clause: %!iT",
		                     (duk_tval *) duk_get_tval(thr, comp_ctx->curr_func.varmap_idx)));

		duk__emit_op_only(comp_ctx,
		                  DUK_OP_ENDCATCH);

		/*
		 *  XXX: for now, indicate that an expensive catch binding
		 *  declarative environment is always needed.  If we don't
		 *  need it, we don't need the const_varname either.
		 */

		trycatch_flags |= DUK_BC_TRYCATCH_FLAG_CATCH_BINDING;

		DUK_DDD(DUK_DDDPRINT("stack top at end of catch clause: %ld", (long) duk_get_top(thr)));
	}

	if (comp_ctx->curr_token.t == DUK_TOK_FINALLY) {
		trycatch_flags |= DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY;

		pc_finally = duk__get_current_pc(comp_ctx);

		duk__advance(comp_ctx);

		duk__advance_expect(comp_ctx, DUK_TOK_LCURLY);
		duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/, 1 /*regexp_after*/);
		/* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */
		duk__emit_abc(comp_ctx,
		              DUK_OP_ENDFIN,
		              reg_catch);  /* rethrow */
	}

	if (!(trycatch_flags & DUK_BC_TRYCATCH_FLAG_HAVE_CATCH) &&
	    !(trycatch_flags & DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY)) {
		/* must have catch and/or finally */
		goto syntax_error;
	}

	/* If there's no catch block, rc_varname will be 0 and duk__patch_trycatch()
	 * will replace the LDCONST with a NOP.  For any actual constant (including
	 * constant 0) the DUK__CONST_MARKER flag will be set in rc_varname.
	 */

	duk__patch_trycatch(comp_ctx,
	                    pc_ldconst,
	                    pc_trycatch,
	                    reg_catch,
	                    rc_varname,
	                    trycatch_flags);

	if (trycatch_flags & DUK_BC_TRYCATCH_FLAG_HAVE_CATCH) {
		DUK_ASSERT(pc_catch >= 0);
		duk__patch_jump(comp_ctx, pc_trycatch + 1, pc_catch);
	}

	if (trycatch_flags & DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY) {
		DUK_ASSERT(pc_finally >= 0);
		duk__patch_jump(comp_ctx, pc_trycatch + 2, pc_finally);
	} else {
		/* without finally, the second jump slot is used to jump to end of stmt */
		duk__patch_jump_here(comp_ctx, pc_trycatch + 2);
	}

	comp_ctx->curr_func.catch_depth--;
	return;

 syntax_error:
	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_TRY);
	DUK_WO_NORETURN(return;);
}

DUK_LOCAL void duk__parse_with_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
	duk_int_t pc_trycatch;
	duk_int_t pc_finished;
	duk_regconst_t reg_catch;
	duk_small_uint_t trycatch_flags;

	if (comp_ctx->curr_func.is_strict) {
		DUK_ERROR_SYNTAX(comp_ctx->thr, DUK_STR_WITH_IN_STRICT_MODE);
		DUK_WO_NORETURN(return;);
	}

	comp_ctx->curr_func.catch_depth++;

	duk__advance(comp_ctx);  /* eat 'with' */

	reg_catch = DUK__ALLOCTEMPS(comp_ctx, 2);

	duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
	duk__exprtop_toforcedreg(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/, reg_catch);
	comp_ctx->curr_func.allow_regexp_in_adv = 1;
	duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);  /* Allow RegExp as part of next stmt. */

	pc_trycatch = duk__get_current_pc(comp_ctx);
	trycatch_flags = DUK_BC_TRYCATCH_FLAG_WITH_BINDING;
	duk__emit_a_bc(comp_ctx,
	                DUK_OP_TRYCATCH | DUK__EMIT_FLAG_NO_SHUFFLE_A,
	                (duk_regconst_t) trycatch_flags /*a*/,
	                reg_catch /*bc*/);
	duk__emit_invalid(comp_ctx);  /* catch jump */
	duk__emit_invalid(comp_ctx);  /* finished jump */

	duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
	duk__emit_op_only(comp_ctx, DUK_OP_ENDTRY);

	pc_finished = duk__get_current_pc(comp_ctx);

	duk__patch_jump(comp_ctx, pc_trycatch + 2, pc_finished);

	comp_ctx->curr_func.catch_depth--;
}

DUK_LOCAL duk_int_t duk__stmt_label_site(duk_compiler_ctx *comp_ctx, duk_int_t label_id) {
	/* if a site already exists, nop: max one label site per statement */
	if (label_id >= 0) {
		return label_id;
	}

	label_id = comp_ctx->curr_func.label_next++;
	DUK_DDD(DUK_DDDPRINT("allocated new label id for label site: %ld", (long) label_id));

	duk__emit_bc(comp_ctx,
	             DUK_OP_LABEL,
	             (duk_regconst_t) label_id);
	duk__emit_invalid(comp_ctx);
	duk__emit_invalid(comp_ctx);

	return label_id;
}

/* Parse a single statement.
 *
 * Creates a label site (with an empty label) automatically for iteration
 * statements.  Also "peels off" any label statements for explicit labels.
 */
DUK_LOCAL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_bool_t allow_source_elem) {
	duk_hthread *thr = comp_ctx->thr;
	duk_bool_t dir_prol_at_entry;    /* directive prologue status at entry */
	duk_regconst_t temp_at_entry;
	duk_size_t labels_len_at_entry;
	duk_int_t pc_at_entry;           /* assumed to also be PC of "LABEL" */
	duk_int_t stmt_id;
	duk_small_uint_t stmt_flags = 0;
	duk_int_t label_id = -1;
	duk_small_uint_t tok;
	duk_bool_t test_func_decl;

	DUK__RECURSION_INCREASE(comp_ctx, thr);

	temp_at_entry = DUK__GETTEMP(comp_ctx);
	pc_at_entry = duk__get_current_pc(comp_ctx);
	labels_len_at_entry = duk_get_length(thr, comp_ctx->curr_func.labelnames_idx);
	stmt_id = comp_ctx->curr_func.stmt_next++;
	dir_prol_at_entry = comp_ctx->curr_func.in_directive_prologue;

	DUK_UNREF(stmt_id);

	DUK_DDD(DUK_DDDPRINT("parsing a statement, stmt_id=%ld, temp_at_entry=%ld, labels_len_at_entry=%ld, "
	                     "is_strict=%ld, in_directive_prologue=%ld, catch_depth=%ld",
	                     (long) stmt_id, (long) temp_at_entry, (long) labels_len_at_entry,
	                     (long) comp_ctx->curr_func.is_strict, (long) comp_ctx->curr_func.in_directive_prologue,
	                     (long) comp_ctx->curr_func.catch_depth));

	/* The directive prologue flag is cleared by default so that it is
	 * unset for any recursive statement parsing.  It is only "revived"
	 * if a directive is detected.  (We could also make directives only
	 * allowed if 'allow_source_elem' was true.)
	 */
	comp_ctx->curr_func.in_directive_prologue = 0;

 retry_parse:

	DUK_DDD(DUK_DDDPRINT("try stmt parse, stmt_id=%ld, label_id=%ld, allow_source_elem=%ld, catch_depth=%ld",
	                     (long) stmt_id, (long) label_id, (long) allow_source_elem,
	                     (long) comp_ctx->curr_func.catch_depth));

	/*
	 *  Detect iteration statements; if encountered, establish an
	 *  empty label.
	 */

	tok = comp_ctx->curr_token.t;
	if (tok == DUK_TOK_FOR || tok == DUK_TOK_DO || tok == DUK_TOK_WHILE ||
	    tok == DUK_TOK_SWITCH) {
		DUK_DDD(DUK_DDDPRINT("iteration/switch statement -> add empty label"));

		label_id = duk__stmt_label_site(comp_ctx, label_id);
		duk__add_label(comp_ctx,
		               DUK_HTHREAD_STRING_EMPTY_STRING(thr),
		               pc_at_entry /*pc_label*/,
		               label_id);
	}

	/*
	 *  Main switch for statement / source element type.
	 */

	switch (comp_ctx->curr_token.t) {
	case DUK_TOK_FUNCTION: {
		/*
		 *  Function declaration, function expression, or (non-standard)
		 *  function statement.
		 *
		 *  The E5 specification only allows function declarations at
		 *  the top level (in "source elements").  An ExpressionStatement
		 *  is explicitly not allowed to begin with a "function" keyword
		 *  (E5 Section 12.4).  Hence any non-error semantics for such
		 *  non-top-level statements are non-standard.  Duktape semantics
		 *  for function statements are modelled after V8, see
		 *  test-dev-func-decl-outside-top.js.
		 */
		test_func_decl = allow_source_elem;
#if defined(DUK_USE_NONSTD_FUNC_STMT)
		/* Lenient: allow function declarations outside top level in
		 * non-strict mode but reject them in strict mode.
		 */
		test_func_decl = test_func_decl || !comp_ctx->curr_func.is_strict;
#endif  /* DUK_USE_NONSTD_FUNC_STMT */
		/* Strict: never allow function declarations outside top level. */
		if (test_func_decl) {
			/* FunctionDeclaration: not strictly a statement but handled as such.
			 *
			 * O(depth^2) parse count for inner functions is handled by recording a
			 * lexer offset on the first compilation pass, so that the function can
			 * be efficiently skipped on the second pass.  This is encapsulated into
			 * duk__parse_func_like_fnum().
			 */

			duk_int_t fnum;
#if defined(DUK_USE_ASSERTIONS)
			duk_idx_t top_before;
#endif

			DUK_DDD(DUK_DDDPRINT("function declaration statement"));

#if defined(DUK_USE_ASSERTIONS)
			top_before = duk_get_top(thr);
#endif

			duk__advance(comp_ctx);  /* eat 'function' */
			fnum = duk__parse_func_like_fnum(comp_ctx, DUK__FUNC_FLAG_DECL | DUK__FUNC_FLAG_PUSHNAME_PASS1);

			/* The value stack convention here is a bit odd: the function
			 * name is only pushed on pass 1 (in_scanning), and is needed
			 * to process function declarations.
			 */
			if (comp_ctx->curr_func.in_scanning) {
				duk_uarridx_t n;

#if defined(DUK_USE_ASSERTIONS)
				DUK_ASSERT(duk_get_top(thr) == top_before + 1);
#endif
				DUK_DDD(DUK_DDDPRINT("register function declaration %!T in pass 1, fnum %ld",
				                     duk_get_tval(thr, -1), (long) fnum));
				n = (duk_uarridx_t) duk_get_length(thr, comp_ctx->curr_func.decls_idx);
				/* funcname is at index -1 */
				duk_put_prop_index(thr, comp_ctx->curr_func.decls_idx, n);
				duk_push_int(thr, (duk_int_t) (DUK_DECL_TYPE_FUNC + (fnum << 8)));
				duk_put_prop_index(thr, comp_ctx->curr_func.decls_idx, n + 1);
			} else {
#if defined(DUK_USE_ASSERTIONS)
				DUK_ASSERT(duk_get_top(thr) == top_before);
#endif
			}

			/* no statement value (unlike function expression) */
			stmt_flags = 0;
			break;
		} else {
			DUK_ERROR_SYNTAX(thr, DUK_STR_FUNC_STMT_NOT_ALLOWED);
			DUK_WO_NORETURN(return;);
		}
		break;
	}
	case DUK_TOK_LCURLY: {
		DUK_DDD(DUK_DDDPRINT("block statement"));
		duk__advance(comp_ctx);
		duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/, 1 /*regexp_after*/);
		/* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */
		if (label_id >= 0) {
			duk__patch_jump_here(comp_ctx, pc_at_entry + 1);  /* break jump */
		}
		stmt_flags = 0;
		break;
	}
	case DUK_TOK_CONST: {
		DUK_DDD(DUK_DDDPRINT("constant declaration statement"));
		duk__parse_var_stmt(comp_ctx, res, DUK__EXPR_FLAG_REQUIRE_INIT /*expr_flags*/);
		stmt_flags = DUK__HAS_TERM;
		break;
	}
	case DUK_TOK_VAR: {
		DUK_DDD(DUK_DDDPRINT("variable declaration statement"));
		duk__parse_var_stmt(comp_ctx, res, 0 /*expr_flags*/);
		stmt_flags = DUK__HAS_TERM;
		break;
	}
	case DUK_TOK_SEMICOLON: {
		/* empty statement with an explicit semicolon */
		DUK_DDD(DUK_DDDPRINT("empty statement"));
		stmt_flags = DUK__HAS_TERM;
		break;
	}
	case DUK_TOK_IF: {
		DUK_DDD(DUK_DDDPRINT("if statement"));
		duk__parse_if_stmt(comp_ctx, res);
		if (label_id >= 0) {
			duk__patch_jump_here(comp_ctx, pc_at_entry + 1);  /* break jump */
		}
		stmt_flags = 0;
		break;
	}
	case DUK_TOK_DO: {
		/*
		 *  Do-while statement is mostly trivial, but there is special
		 *  handling for automatic semicolon handling (triggered by the
		 *  DUK__ALLOW_AUTO_SEMI_ALWAYS) flag related to a bug filed at:
		 *
		 *    https://bugs.ecmascript.org/show_bug.cgi?id=8
		 *
		 *  See doc/compiler.rst for details.
		 */
		DUK_DDD(DUK_DDDPRINT("do statement"));
		DUK_ASSERT(label_id >= 0);
		duk__update_label_flags(comp_ctx,
		                        label_id,
		                        DUK_LABEL_FLAG_ALLOW_BREAK | DUK_LABEL_FLAG_ALLOW_CONTINUE);
		duk__parse_do_stmt(comp_ctx, res, pc_at_entry);
		stmt_flags = DUK__HAS_TERM | DUK__ALLOW_AUTO_SEMI_ALWAYS;  /* DUK__ALLOW_AUTO_SEMI_ALWAYS workaround */
		break;
	}
	case DUK_TOK_WHILE: {
		DUK_DDD(DUK_DDDPRINT("while statement"));
		DUK_ASSERT(label_id >= 0);
		duk__update_label_flags(comp_ctx,
		                        label_id,
		                        DUK_LABEL_FLAG_ALLOW_BREAK | DUK_LABEL_FLAG_ALLOW_CONTINUE);
		duk__parse_while_stmt(comp_ctx, res, pc_at_entry);
		stmt_flags = 0;
		break;
	}
	case DUK_TOK_FOR: {
		/*
		 *  For/for-in statement is complicated to parse because
		 *  determining the statement type (three-part for vs. a
		 *  for-in) requires potential backtracking.
		 *
		 *  See the helper for the messy stuff.
		 */
		DUK_DDD(DUK_DDDPRINT("for/for-in statement"));
		DUK_ASSERT(label_id >= 0);
		duk__update_label_flags(comp_ctx,
		                        label_id,
		                        DUK_LABEL_FLAG_ALLOW_BREAK | DUK_LABEL_FLAG_ALLOW_CONTINUE);
		duk__parse_for_stmt(comp_ctx, res, pc_at_entry);
		stmt_flags = 0;
		break;
	}
	case DUK_TOK_CONTINUE:
	case DUK_TOK_BREAK: {
		DUK_DDD(DUK_DDDPRINT("break/continue statement"));
		duk__parse_break_or_continue_stmt(comp_ctx, res);
		stmt_flags = DUK__HAS_TERM | DUK__IS_TERMINAL;
		break;
	}
	case DUK_TOK_RETURN: {
		DUK_DDD(DUK_DDDPRINT("return statement"));
		duk__parse_return_stmt(comp_ctx, res);
		stmt_flags = DUK__HAS_TERM | DUK__IS_TERMINAL;
		break;
	}
	case DUK_TOK_WITH: {
		DUK_DDD(DUK_DDDPRINT("with statement"));
		comp_ctx->curr_func.with_depth++;
		duk__parse_with_stmt(comp_ctx, res);
		if (label_id >= 0) {
			duk__patch_jump_here(comp_ctx, pc_at_entry + 1);  /* break jump */
		}
		comp_ctx->curr_func.with_depth--;
		stmt_flags = 0;
		break;
	}
	case DUK_TOK_SWITCH: {
		/*
		 *  The switch statement is pretty messy to compile.
		 *  See the helper for details.
		 */
		DUK_DDD(DUK_DDDPRINT("switch statement"));
		DUK_ASSERT(label_id >= 0);
		duk__update_label_flags(comp_ctx,
		                        label_id,
		                        DUK_LABEL_FLAG_ALLOW_BREAK);  /* don't allow continue */
		duk__parse_switch_stmt(comp_ctx, res, pc_at_entry);
		stmt_flags = 0;
		break;
	}
	case DUK_TOK_THROW: {
		DUK_DDD(DUK_DDDPRINT("throw statement"));
		duk__parse_throw_stmt(comp_ctx, res);
		stmt_flags = DUK__HAS_TERM | DUK__IS_TERMINAL;
		break;
	}
	case DUK_TOK_TRY: {
		DUK_DDD(DUK_DDDPRINT("try statement"));
		duk__parse_try_stmt(comp_ctx, res);
		stmt_flags = 0;
		break;
	}
	case DUK_TOK_DEBUGGER: {
		duk__advance(comp_ctx);
#if defined(DUK_USE_DEBUGGER_SUPPORT)
		DUK_DDD(DUK_DDDPRINT("debugger statement: debugging enabled, emit debugger opcode"));
		duk__emit_op_only(comp_ctx, DUK_OP_DEBUGGER);
#else
		DUK_DDD(DUK_DDDPRINT("debugger statement: ignored"));
#endif
		stmt_flags = DUK__HAS_TERM;
		break;
	}
	default: {
		/*
		 *  Else, must be one of:
		 *    - ExpressionStatement, possibly a directive (String)
		 *    - LabelledStatement (Identifier followed by ':')
		 *
		 *  Expressions beginning with 'function' keyword are covered by a case
		 *  above (such expressions are not allowed in standard E5 anyway).
		 *  Also expressions starting with '{' are interpreted as block
		 *  statements.  See E5 Section 12.4.
		 *
		 *  Directive detection is tricky; see E5 Section 14.1 on directive
		 *  prologue.  A directive is an expression statement with a single
		 *  string literal and an explicit or automatic semicolon.  Escape
		 *  characters are significant and no parens etc are allowed:
		 *
		 *    'use strict';          // valid 'use strict' directive
		 *    'use\u0020strict';     // valid directive, not a 'use strict' directive
		 *    ('use strict');        // not a valid directive
		 *
		 *  The expression is determined to consist of a single string literal
		 *  based on duk__expr_nud() and duk__expr_led() call counts.  The string literal
		 *  of a 'use strict' directive is determined to lack any escapes based
		 *  num_escapes count from the lexer.  Note that other directives may be
		 *  allowed to contain escapes, so a directive with escapes does not
		 *  terminate a directive prologue.
		 *
		 *  We rely on the fact that the expression parser will not emit any
		 *  code for a single token expression.  However, it will generate an
		 *  intermediate value which we will then successfully ignore.
		 *
		 *  A similar approach is used for labels.
		 */

		duk_bool_t single_token;

		DUK_DDD(DUK_DDDPRINT("expression statement"));
		duk__exprtop(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);

		single_token = (comp_ctx->curr_func.nud_count == 1 &&  /* one token */
		                comp_ctx->curr_func.led_count == 0);   /* no operators */

		if (single_token &&
		    comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER &&
		    comp_ctx->curr_token.t == DUK_TOK_COLON) {
			/*
			 *  Detected label
			 */

			duk_hstring *h_lab;

			/* expected ival */
			DUK_ASSERT(res->t == DUK_IVAL_VAR);
			DUK_ASSERT(res->x1.t == DUK_ISPEC_VALUE);
			DUK_ASSERT(DUK_TVAL_IS_STRING(duk_get_tval(thr, res->x1.valstack_idx)));
			h_lab = comp_ctx->prev_token.str1;
			DUK_ASSERT(h_lab != NULL);

			DUK_DDD(DUK_DDDPRINT("explicit label site for label '%!O'",
			                     (duk_heaphdr *) h_lab));

			duk__advance(comp_ctx);  /* eat colon */

			label_id = duk__stmt_label_site(comp_ctx, label_id);

			duk__add_label(comp_ctx,
			               h_lab,
			               pc_at_entry /*pc_label*/,
			               label_id);

			/* a statement following a label cannot be a source element
			 * (a function declaration).
			 */
			allow_source_elem = 0;

			DUK_DDD(DUK_DDDPRINT("label handled, retry statement parsing"));
			goto retry_parse;
		}

		stmt_flags = 0;

		if (dir_prol_at_entry &&                           /* still in prologue */
		    single_token &&                                /* single string token */
		    comp_ctx->prev_token.t == DUK_TOK_STRING) {
			/*
			 *  Detected a directive
			 */
			duk_hstring *h_dir;

			/* expected ival */
			DUK_ASSERT(res->t == DUK_IVAL_PLAIN);
			DUK_ASSERT(res->x1.t == DUK_ISPEC_VALUE);
			DUK_ASSERT(DUK_TVAL_IS_STRING(duk_get_tval(thr, res->x1.valstack_idx)));
			h_dir = comp_ctx->prev_token.str1;
			DUK_ASSERT(h_dir != NULL);

			DUK_DDD(DUK_DDDPRINT("potential directive: %!O", h_dir));

			stmt_flags |= DUK__STILL_PROLOGUE;

			/* Note: escaped characters differentiate directives */

			if (comp_ctx->prev_token.num_escapes > 0) {
				DUK_DDD(DUK_DDDPRINT("directive contains escapes: valid directive "
				                     "but we ignore such directives"));
			} else {
				/*
				 * The length comparisons are present to handle
				 * strings like "use strict\u0000foo" as required.
				 */

				if (DUK_HSTRING_GET_BYTELEN(h_dir) == 10 &&
				    DUK_STRCMP((const char *) DUK_HSTRING_GET_DATA(h_dir), "use strict") == 0) {
#if defined(DUK_USE_STRICT_DECL)
					DUK_DDD(DUK_DDDPRINT("use strict directive detected: strict flag %ld -> %ld",
					                     (long) comp_ctx->curr_func.is_strict, (long) 1));
					comp_ctx->curr_func.is_strict = 1;
#else
					DUK_DDD(DUK_DDDPRINT("use strict detected but strict declarations disabled, ignoring"));
#endif
				} else if (DUK_HSTRING_GET_BYTELEN(h_dir) == 14 &&
				           DUK_STRCMP((const char *) DUK_HSTRING_GET_DATA(h_dir), "use duk notail") == 0) {
					DUK_DDD(DUK_DDDPRINT("use duk notail directive detected: notail flag %ld -> %ld",
					                     (long) comp_ctx->curr_func.is_notail, (long) 1));
					comp_ctx->curr_func.is_notail = 1;
				} else {
					DUK_DD(DUK_DDPRINT("unknown directive: '%!O', ignoring but not terminating "
					                   "directive prologue", (duk_hobject *) h_dir));
				}
			}
		} else {
			DUK_DDD(DUK_DDDPRINT("non-directive expression statement or no longer in prologue; "
			                     "prologue terminated if still active"));
                }

		stmt_flags |= DUK__HAS_VAL | DUK__HAS_TERM;
	}
	}  /* end switch (tok) */

	/*
	 *  Statement value handling.
	 *
	 *  Global code and eval code has an implicit return value
	 *  which comes from the last statement with a value
	 *  (technically a non-"empty" continuation, which is
	 *  different from an empty statement).
	 *
	 *  Since we don't know whether a later statement will
	 *  override the value of the current statement, we need
	 *  to coerce the statement value to a register allocated
	 *  for implicit return values.  In other cases we need
	 *  to coerce the statement value to a plain value to get
	 *  any side effects out (consider e.g. "foo.bar;").
	 */

	/* XXX: what about statements which leave a half-cooked value in 'res'
	 * but have no stmt value?  Any such statements?
	 */

	if (stmt_flags & DUK__HAS_VAL) {
		duk_regconst_t reg_stmt_value = comp_ctx->curr_func.reg_stmt_value;
		if (reg_stmt_value >= 0) {
			duk__ivalue_toforcedreg(comp_ctx, res, reg_stmt_value);
		} else {
			duk__ivalue_toplain_ignore(comp_ctx, res);
		}
	} else {
		;
	}

	/*
	 *  Statement terminator check, including automatic semicolon
	 *  handling.  After this step, 'curr_tok' should be the first
	 *  token after a possible statement terminator.
	 */

	if (stmt_flags & DUK__HAS_TERM) {
		if (comp_ctx->curr_token.t == DUK_TOK_SEMICOLON) {
			DUK_DDD(DUK_DDDPRINT("explicit semicolon terminates statement"));
			duk__advance(comp_ctx);
		} else {
			if (comp_ctx->curr_token.allow_auto_semi) {
				DUK_DDD(DUK_DDDPRINT("automatic semicolon terminates statement"));
			} else if (stmt_flags & DUK__ALLOW_AUTO_SEMI_ALWAYS) {
				/* XXX: make this lenience dependent on flags or strictness? */
				DUK_DDD(DUK_DDDPRINT("automatic semicolon terminates statement (allowed for compatibility "
				                     "even though no lineterm present before next token)"));
			} else {
				DUK_ERROR_SYNTAX(thr, DUK_STR_UNTERMINATED_STMT);
				DUK_WO_NORETURN(return;);
			}
		}
	} else {
		DUK_DDD(DUK_DDDPRINT("statement has no terminator"));
	}

	/*
	 *  Directive prologue tracking.
	 */

	if (stmt_flags & DUK__STILL_PROLOGUE) {
		DUK_DDD(DUK_DDDPRINT("setting in_directive_prologue"));
		comp_ctx->curr_func.in_directive_prologue = 1;
	}

	/*
	 *  Cleanups (all statement parsing flows through here).
	 *
	 *  Pop label site and reset labels.  Reset 'next temp' to value at
	 *  entry to reuse temps.
	 */

	if (label_id >= 0) {
		duk__emit_bc(comp_ctx,
		             DUK_OP_ENDLABEL,
		             (duk_regconst_t) label_id);
	}

	DUK__SETTEMP(comp_ctx, temp_at_entry);

	duk__reset_labels_to_length(comp_ctx, labels_len_at_entry);

	/* XXX: return indication of "terminalness" (e.g. a 'throw' is terminal) */

	DUK__RECURSION_DECREASE(comp_ctx, thr);
}

/*
 *  Parse a statement list.
 *
 *  Handles automatic semicolon insertion and implicit return value.
 *
 *  Upon entry, 'curr_tok' should contain the first token of the first
 *  statement (parsed in the "allow regexp literal" mode).  Upon exit,
 *  'curr_tok' contains the token following the statement list terminator
 *  (EOF or closing brace).
 */

DUK_LOCAL void duk__parse_stmts(duk_compiler_ctx *comp_ctx, duk_bool_t allow_source_elem, duk_bool_t expect_eof, duk_bool_t regexp_after) {
	duk_hthread *thr = comp_ctx->thr;
	duk_ivalue res_alloc;
	duk_ivalue *res = &res_alloc;

	/* Setup state.  Initial ivalue is 'undefined'. */

	duk_require_stack(thr, DUK__PARSE_STATEMENTS_SLOTS);

	/* XXX: 'res' setup can be moved to function body level; in fact, two 'res'
	 * intermediate values suffice for parsing of each function.  Nesting is needed
	 * for nested functions (which may occur inside expressions).
	 */

	duk_memzero(&res_alloc, sizeof(res_alloc));
	res->t = DUK_IVAL_PLAIN;
	res->x1.t = DUK_ISPEC_VALUE;
	res->x1.valstack_idx = duk_get_top(thr);
	res->x2.valstack_idx = res->x1.valstack_idx + 1;
	duk_push_undefined(thr);
	duk_push_undefined(thr);

	/* Parse statements until a closing token (EOF or '}') is found. */

	for (;;) {
		/* Check whether statement list ends. */

		if (expect_eof) {
			if (comp_ctx->curr_token.t == DUK_TOK_EOF) {
				break;
			}
		} else {
			if (comp_ctx->curr_token.t == DUK_TOK_RCURLY) {
				break;
			}
		}

		/* Check statement type based on the first token type.
		 *
		 * Note: expression parsing helpers expect 'curr_tok' to
		 * contain the first token of the expression upon entry.
		 */

		DUK_DDD(DUK_DDDPRINT("TOKEN %ld (non-whitespace, non-comment)", (long) comp_ctx->curr_token.t));

		duk__parse_stmt(comp_ctx, res, allow_source_elem);
	}

	/* RegExp is allowed / not allowed depending on context.  For function
	 * declarations RegExp is allowed because it follows a function
	 * declaration statement and may appear as part of the next statement.
	 * For function expressions RegExp is not allowed, and it's possible
	 * to do something like '(function () {} / 123)'.
	 */
	if (regexp_after) {
		comp_ctx->curr_func.allow_regexp_in_adv = 1;
	}
	duk__advance(comp_ctx);

	/* Tear down state. */

	duk_pop_2(thr);
}

/*
 *  Declaration binding instantiation conceptually happens when calling a
 *  function; for us it essentially means that function prologue.  The
 *  conceptual process is described in E5 Section 10.5.
 *
 *  We need to keep track of all encountered identifiers to (1) create an
 *  identifier-to-register map ("varmap"); and (2) detect duplicate
 *  declarations.  Identifiers which are not bound to registers still need
 *  to be tracked for detecting duplicates.  Currently such identifiers
 *  are put into the varmap with a 'null' value, which is later cleaned up.
 *
 *  To support functions with a large number of variable and function
 *  declarations, registers are not allocated beyond a certain limit;
 *  after that limit, variables and functions need slow path access.
 *  Arguments are currently always register bound, which imposes a hard
 *  (and relatively small) argument count limit.
 *
 *  Some bindings in E5 are not configurable (= deletable) and almost all
 *  are mutable (writable).  Exceptions are:
 *
 *    - The 'arguments' binding, established only if no shadowing argument
 *      or function declaration exists.  We handle 'arguments' creation
 *      and binding through an explicit slow path environment record.
 *
 *    - The "name" binding for a named function expression.  This is also
 *      handled through an explicit slow path environment record.
 */

/* XXX: add support for variables to not be register bound always, to
 * handle cases with a very large number of variables?
 */

DUK_LOCAL void duk__init_varmap_and_prologue_for_pass2(duk_compiler_ctx *comp_ctx, duk_regconst_t *out_stmt_value_reg) {
	duk_hthread *thr = comp_ctx->thr;
	duk_hstring *h_name;
	duk_bool_t configurable_bindings;
	duk_uarridx_t num_args;
	duk_uarridx_t num_decls;
	duk_regconst_t rc_name;
	duk_small_uint_t declvar_flags;
	duk_uarridx_t i;
#if defined(DUK_USE_ASSERTIONS)
	duk_idx_t entry_top;
#endif

#if defined(DUK_USE_ASSERTIONS)
	entry_top = duk_get_top(thr);
#endif

	/*
	 *  Preliminaries
	 */

	configurable_bindings = comp_ctx->curr_func.is_eval;
	DUK_DDD(DUK_DDDPRINT("configurable_bindings=%ld", (long) configurable_bindings));

	/* varmap is already in comp_ctx->curr_func.varmap_idx */

	/*
	 *  Function formal arguments, always bound to registers
	 *  (there's no support for shuffling them now).
	 */

	num_args = (duk_uarridx_t) duk_get_length(thr, comp_ctx->curr_func.argnames_idx);
	DUK_DDD(DUK_DDDPRINT("num_args=%ld", (long) num_args));
	/* XXX: check num_args */

	for (i = 0; i < num_args; i++) {
		duk_get_prop_index(thr, comp_ctx->curr_func.argnames_idx, i);
		h_name = duk_known_hstring(thr, -1);

		if (comp_ctx->curr_func.is_strict) {
			if (duk__hstring_is_eval_or_arguments(comp_ctx, h_name)) {
				DUK_DDD(DUK_DDDPRINT("arg named 'eval' or 'arguments' in strict mode -> SyntaxError"));
				goto error_argname;
			}
			duk_dup_top(thr);
			if (duk_has_prop(thr, comp_ctx->curr_func.varmap_idx)) {
				DUK_DDD(DUK_DDDPRINT("duplicate arg name in strict mode -> SyntaxError"));
				goto error_argname;
			}

			/* Ensure argument name is not a reserved word in current
			 * (final) strictness.  Formal argument parsing may not
			 * catch reserved names if strictness changes during
			 * parsing.
			 *
			 * We only need to do this in strict mode because non-strict
			 * keyword are always detected in formal argument parsing.
			 */

			if (DUK_HSTRING_HAS_STRICT_RESERVED_WORD(h_name)) {
				goto error_argname;
			}
		}

		/* overwrite any previous binding of the same name; the effect is
		 * that last argument of a certain name wins.
		 */

		/* only functions can have arguments */
		DUK_ASSERT(comp_ctx->curr_func.is_function);
		duk_push_uarridx(thr, i);  /* -> [ ... name index ] */
		duk_put_prop(thr, comp_ctx->curr_func.varmap_idx); /* -> [ ... ] */

		/* no code needs to be emitted, the regs already have values */
	}

	/* use temp_next for tracking register allocations */
	DUK__SETTEMP_CHECKMAX(comp_ctx, (duk_regconst_t) num_args);

	/*
	 *  After arguments, allocate special registers (like shuffling temps)
	 */

	if (out_stmt_value_reg) {
		*out_stmt_value_reg = DUK__ALLOCTEMP(comp_ctx);
	}
	if (comp_ctx->curr_func.needs_shuffle) {
		duk_regconst_t shuffle_base = DUK__ALLOCTEMPS(comp_ctx, 3);
		comp_ctx->curr_func.shuffle1 = shuffle_base;
		comp_ctx->curr_func.shuffle2 = shuffle_base + 1;
		comp_ctx->curr_func.shuffle3 = shuffle_base + 2;
		DUK_D(DUK_DPRINT("shuffle registers needed by function, allocated: %ld %ld %ld",
		                 (long) comp_ctx->curr_func.shuffle1,
		                 (long) comp_ctx->curr_func.shuffle2,
		                 (long) comp_ctx->curr_func.shuffle3));
	}
	if (comp_ctx->curr_func.temp_next > 0x100) {
		DUK_D(DUK_DPRINT("not enough 8-bit regs: temp_next=%ld", (long) comp_ctx->curr_func.temp_next));
		goto error_outofregs;
	}

	/*
	 *  Function declarations
	 */

	num_decls = (duk_uarridx_t) duk_get_length(thr, comp_ctx->curr_func.decls_idx);
	DUK_DDD(DUK_DDDPRINT("num_decls=%ld -> %!T",
	                     (long) num_decls,
	                     (duk_tval *) duk_get_tval(thr, comp_ctx->curr_func.decls_idx)));
	for (i = 0; i < num_decls; i += 2) {
		duk_int_t decl_type;
		duk_int_t fnum;

		duk_get_prop_index(thr, comp_ctx->curr_func.decls_idx, i + 1);  /* decl type */
		decl_type = duk_to_int(thr, -1);
		fnum = decl_type >> 8;  /* XXX: macros */
		decl_type = decl_type & 0xff;
		duk_pop(thr);

		if (decl_type != DUK_DECL_TYPE_FUNC) {
			continue;
		}

		duk_get_prop_index(thr, comp_ctx->curr_func.decls_idx, i);  /* decl name */

		/* XXX: spilling */
		if (comp_ctx->curr_func.is_function) {
			duk_regconst_t reg_bind;
			duk_dup_top(thr);
			if (duk_has_prop(thr, comp_ctx->curr_func.varmap_idx)) {
				/* shadowed; update value */
				duk_dup_top(thr);
				duk_get_prop(thr, comp_ctx->curr_func.varmap_idx);
				reg_bind = duk_to_int(thr, -1);  /* [ ... name reg_bind ] */
				duk__emit_a_bc(comp_ctx,
				               DUK_OP_CLOSURE,
				               reg_bind,
				               (duk_regconst_t) fnum);
			} else {
				/* function: always register bound */
				reg_bind = DUK__ALLOCTEMP(comp_ctx);
				duk__emit_a_bc(comp_ctx,
				               DUK_OP_CLOSURE,
				               reg_bind,
				               (duk_regconst_t) fnum);
				duk_push_int(thr, (duk_int_t) reg_bind);
			}
		} else {
			/* Function declaration for global/eval code is emitted even
			 * for duplicates, because of E5 Section 10.5, step 5.e of
			 * E5.1 (special behavior for variable bound to global object).
			 *
			 * DECLVAR will not re-declare a variable as such, but will
			 * update the binding value.
			 */

			duk_regconst_t reg_temp = DUK__ALLOCTEMP(comp_ctx);
			duk_dup_top(thr);
			rc_name = duk__getconst(comp_ctx);
			duk_push_null(thr);

			duk__emit_a_bc(comp_ctx,
			               DUK_OP_CLOSURE,
			               reg_temp,
			               (duk_regconst_t) fnum);

			declvar_flags = DUK_PROPDESC_FLAG_WRITABLE |
			                DUK_PROPDESC_FLAG_ENUMERABLE |
			                DUK_BC_DECLVAR_FLAG_FUNC_DECL;

			if (configurable_bindings) {
				declvar_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;
			}

			duk__emit_a_b_c(comp_ctx,
			                DUK_OP_DECLVAR | DUK__EMIT_FLAG_NO_SHUFFLE_A | DUK__EMIT_FLAG_BC_REGCONST,
			                (duk_regconst_t) declvar_flags /*flags*/,
			                rc_name /*name*/,
			                reg_temp /*value*/);

			DUK__SETTEMP(comp_ctx, reg_temp);  /* forget temp */
		}

		DUK_DDD(DUK_DDDPRINT("function declaration to varmap: %!T -> %!T",
		                     (duk_tval *) duk_get_tval(thr, -2),
		                     (duk_tval *) duk_get_tval(thr, -1)));

#if defined(DUK_USE_FASTINT)
		DUK_ASSERT(DUK_TVAL_IS_NULL(duk_get_tval(thr, -1)) || DUK_TVAL_IS_FASTINT(duk_get_tval(thr, -1)));
#endif
		duk_put_prop(thr, comp_ctx->curr_func.varmap_idx);  /* [ ... name reg/null ] -> [ ... ] */
	}

	/*
	 *  'arguments' binding is special; if a shadowing argument or
	 *  function declaration exists, an arguments object will
	 *  definitely not be needed, regardless of whether the identifier
	 *  'arguments' is referenced inside the function body.
	 */

	if (duk_has_prop_stridx(thr, comp_ctx->curr_func.varmap_idx, DUK_STRIDX_LC_ARGUMENTS)) {
		DUK_DDD(DUK_DDDPRINT("'arguments' is shadowed by argument or function declaration "
		                     "-> arguments object creation can be skipped"));
		comp_ctx->curr_func.is_arguments_shadowed = 1;
	}

	/*
	 *  Variable declarations.
	 *
	 *  Unlike function declarations, variable declaration values don't get
	 *  assigned on entry.  If a binding of the same name already exists, just
	 *  ignore it silently.
	 */

	for (i = 0; i < num_decls; i += 2) {
		duk_int_t decl_type;

		duk_get_prop_index(thr, comp_ctx->curr_func.decls_idx, i + 1);  /* decl type */
		decl_type = duk_to_int(thr, -1);
		decl_type = decl_type & 0xff;
		duk_pop(thr);

		if (decl_type != DUK_DECL_TYPE_VAR) {
			continue;
		}

		duk_get_prop_index(thr, comp_ctx->curr_func.decls_idx, i);  /* decl name */

		if (duk_has_prop(thr, comp_ctx->curr_func.varmap_idx)) {
			/* shadowed, ignore */
		} else {
			duk_get_prop_index(thr, comp_ctx->curr_func.decls_idx, i);  /* decl name */
			h_name = duk_known_hstring(thr, -1);

			if (h_name == DUK_HTHREAD_STRING_LC_ARGUMENTS(thr) &&
			    !comp_ctx->curr_func.is_arguments_shadowed) {
				/* E5 Section steps 7-8 */
				DUK_DDD(DUK_DDDPRINT("'arguments' not shadowed by a function declaration, "
				                     "but appears as a variable declaration -> treat as "
				                     "a no-op for variable declaration purposes"));
				duk_pop(thr);
				continue;
			}

			/* XXX: spilling */
			if (comp_ctx->curr_func.is_function) {
				duk_regconst_t reg_bind = DUK__ALLOCTEMP(comp_ctx);
				/* no need to init reg, it will be undefined on entry */
				duk_push_int(thr, (duk_int_t) reg_bind);
			} else {
				duk_dup_top(thr);
				rc_name = duk__getconst(comp_ctx);
				duk_push_null(thr);

				declvar_flags = DUK_PROPDESC_FLAG_WRITABLE |
			                        DUK_PROPDESC_FLAG_ENUMERABLE;
				if (configurable_bindings) {
					declvar_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;
				}

				duk__emit_a_b_c(comp_ctx,
				                DUK_OP_DECLVAR | DUK__EMIT_FLAG_NO_SHUFFLE_A | DUK__EMIT_FLAG_BC_REGCONST,
				                (duk_regconst_t) declvar_flags /*flags*/,
				                rc_name /*name*/,
				                0 /*value*/);
			}

			duk_put_prop(thr, comp_ctx->curr_func.varmap_idx);  /* [ ... name reg/null ] -> [ ... ] */
		}
	}

	/*
	 *  Wrap up
	 */

	DUK_DDD(DUK_DDDPRINT("varmap: %!T, is_arguments_shadowed=%ld",
	                     (duk_tval *) duk_get_tval(thr, comp_ctx->curr_func.varmap_idx),
	                     (long) comp_ctx->curr_func.is_arguments_shadowed));

	DUK_ASSERT_TOP(thr, entry_top);
	return;

 error_outofregs:
	DUK_ERROR_RANGE(thr, DUK_STR_REG_LIMIT);
	DUK_WO_NORETURN(return;);

 error_argname:
	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_ARG_NAME);
	DUK_WO_NORETURN(return;);
}

/*
 *  Parse a function-body-like expression (FunctionBody or Program
 *  in E5 grammar) using a two-pass parse.  The productions appear
 *  in the following contexts:
 *
 *    - function expression
 *    - function statement
 *    - function declaration
 *    - getter in object literal
 *    - setter in object literal
 *    - global code
 *    - eval code
 *    - Function constructor body
 *
 *  This function only parses the statement list of the body; the argument
 *  list and possible function name must be initialized by the caller.
 *  For instance, for Function constructor, the argument names are originally
 *  on the value stack.  The parsing of statements ends either at an EOF or
 *  a closing brace; this is controlled by an input flag.
 *
 *  Note that there are many differences affecting parsing and even code
 *  generation:
 *
 *    - Global and eval code have an implicit return value generated
 *      by the last statement; function code does not
 *
 *    - Global code, eval code, and Function constructor body end in
 *      an EOF, other bodies in a closing brace ('}')
 *
 *  Upon entry, 'curr_tok' is ignored and the function will pull in the
 *  first token on its own.  Upon exit, 'curr_tok' is the terminating
 *  token (EOF or closing brace).
 */

DUK_LOCAL void duk__parse_func_body(duk_compiler_ctx *comp_ctx, duk_bool_t expect_eof, duk_bool_t implicit_return_value, duk_bool_t regexp_after, duk_small_int_t expect_token) {
	duk_compiler_func *func;
	duk_hthread *thr;
	duk_regconst_t reg_stmt_value = -1;
	duk_lexer_point lex_pt;
	duk_regconst_t temp_first;
	duk_small_int_t compile_round = 1;

	DUK_ASSERT(comp_ctx != NULL);

	thr = comp_ctx->thr;
	DUK_ASSERT(thr != NULL);

	func = &comp_ctx->curr_func;
	DUK_ASSERT(func != NULL);

	DUK__RECURSION_INCREASE(comp_ctx, thr);

	duk_require_stack(thr, DUK__FUNCTION_BODY_REQUIRE_SLOTS);

	/*
	 *  Store lexer position for a later rewind
	 */

	DUK_LEXER_GETPOINT(&comp_ctx->lex, &lex_pt);

	/*
	 *  Program code (global and eval code) has an implicit return value
	 *  from the last statement value (e.g. eval("1; 2+3;") returns 3).
	 *  This is not the case with functions.  If implicit statement return
	 *  value is requested, all statements are coerced to a register
	 *  allocated here, and used in the implicit return statement below.
	 */

	/* XXX: this is pointless here because pass 1 is throw-away */
	if (implicit_return_value) {
		reg_stmt_value = DUK__ALLOCTEMP(comp_ctx);

		/* If an implicit return value is needed by caller, it must be
		 * initialized to 'undefined' because we don't know whether any
		 * non-empty (where "empty" is a continuation type, and different
		 * from an empty statement) statements will be executed.
		 *
		 * However, since 1st pass is a throwaway one, no need to emit
		 * it here.
		 */
#if 0
		duk__emit_bc(comp_ctx,
		             DUK_OP_LDUNDEF,
		             0);
#endif
	}

	/*
	 *  First pass.
	 *
	 *  Gather variable/function declarations needed for second pass.
	 *  Code generated is dummy and discarded.
	 */

	func->in_directive_prologue = 1;
	func->in_scanning = 1;
	func->may_direct_eval = 0;
	func->id_access_arguments = 0;
	func->id_access_slow = 0;
	func->id_access_slow_own = 0;
	func->reg_stmt_value = reg_stmt_value;
#if defined(DUK_USE_DEBUGGER_SUPPORT)
	func->min_line = DUK_INT_MAX;
	func->max_line = 0;
#endif

	/* duk__parse_stmts() expects curr_tok to be set; parse in "allow
	 * regexp literal" mode with current strictness.
	 */
	if (expect_token >= 0) {
		/* Eating a left curly; regexp mode is allowed by left curly
		 * based on duk__token_lbp[] automatically.
		 */
		DUK_ASSERT(expect_token == DUK_TOK_LCURLY);
		duk__update_lineinfo_currtoken(comp_ctx);
		duk__advance_expect(comp_ctx, expect_token);
	} else {
		/* Need to set curr_token.t because lexing regexp mode depends on current
		 * token type.  Zero value causes "allow regexp" mode.
		 */
		comp_ctx->curr_token.t = 0;
		duk__advance(comp_ctx);
	}

	DUK_DDD(DUK_DDDPRINT("begin 1st pass"));
	duk__parse_stmts(comp_ctx,
	                 1,             /* allow source elements */
	                 expect_eof,    /* expect EOF instead of } */
	                 regexp_after); /* regexp after */
	DUK_DDD(DUK_DDDPRINT("end 1st pass"));

	/*
	 *  Second (and possibly third) pass.
	 *
	 *  Generate actual code.  In most cases the need for shuffle
	 *  registers is detected during pass 1, but in some corner cases
	 *  we'll only detect it during pass 2 and a third pass is then
	 *  needed (see GH-115).
	 */

	for (;;) {
		duk_bool_t needs_shuffle_before = comp_ctx->curr_func.needs_shuffle;
		compile_round++;

		/*
		 *  Rewind lexer.
		 *
		 *  duk__parse_stmts() expects curr_tok to be set; parse in "allow regexp
		 *  literal" mode with current strictness.
		 *
		 *  curr_token line number info should be initialized for pass 2 before
		 *  generating prologue, to ensure prologue bytecode gets nice line numbers.
		 */

		DUK_DDD(DUK_DDDPRINT("rewind lexer"));
		DUK_LEXER_SETPOINT(&comp_ctx->lex, &lex_pt);
		comp_ctx->curr_token.t = 0;  /* this is needed for regexp mode */
		comp_ctx->curr_token.start_line = 0;  /* needed for line number tracking (becomes prev_token.start_line) */
		duk__advance(comp_ctx);

		/*
		 *  Reset function state and perform register allocation, which creates
		 *  'varmap' for second pass.  Function prologue for variable declarations,
		 *  binding value initializations etc is emitted as a by-product.
		 *
		 *  Strict mode restrictions for duplicate and invalid argument
		 *  names are checked here now that we know whether the function
		 *  is actually strict.  See: test-dev-strict-mode-boundary.js.
		 *
		 *  Inner functions are compiled during pass 1 and are not reset.
		 */

		duk__reset_func_for_pass2(comp_ctx);
		func->in_directive_prologue = 1;
		func->in_scanning = 0;

		/* must be able to emit code, alloc consts, etc. */

		duk__init_varmap_and_prologue_for_pass2(comp_ctx,
		                                        (implicit_return_value ? &reg_stmt_value : NULL));
		func->reg_stmt_value = reg_stmt_value;

		temp_first = DUK__GETTEMP(comp_ctx);

		func->temp_first = temp_first;
		func->temp_next = temp_first;
		func->stmt_next = 0;
		func->label_next = 0;

		/* XXX: init or assert catch depth etc -- all values */
		func->id_access_arguments = 0;
		func->id_access_slow = 0;
		func->id_access_slow_own = 0;

		/*
		 *  Check function name validity now that we know strictness.
		 *  This only applies to function declarations and expressions,
		 *  not setter/getter name.
		 *
		 *  See: test-dev-strict-mode-boundary.js
		 */

		if (func->is_function && !func->is_setget && func->h_name != NULL) {
			if (func->is_strict) {
				if (duk__hstring_is_eval_or_arguments(comp_ctx, func->h_name)) {
					DUK_DDD(DUK_DDDPRINT("func name is 'eval' or 'arguments' in strict mode"));
					goto error_funcname;
				}
				if (DUK_HSTRING_HAS_STRICT_RESERVED_WORD(func->h_name)) {
					DUK_DDD(DUK_DDDPRINT("func name is a reserved word in strict mode"));
					goto error_funcname;
				}
			} else {
				if (DUK_HSTRING_HAS_RESERVED_WORD(func->h_name) &&
				    !DUK_HSTRING_HAS_STRICT_RESERVED_WORD(func->h_name)) {
					DUK_DDD(DUK_DDDPRINT("func name is a reserved word in non-strict mode"));
					goto error_funcname;
				}
			}
		}

		/*
		 *  Second pass parsing.
		 */

		if (implicit_return_value) {
			/* Default implicit return value. */
			duk__emit_bc(comp_ctx,
			             DUK_OP_LDUNDEF,
			             0);
		}

		DUK_DDD(DUK_DDDPRINT("begin 2nd pass"));
		duk__parse_stmts(comp_ctx,
		                 1,             /* allow source elements */
		                 expect_eof,    /* expect EOF instead of } */
		                 regexp_after); /* regexp after */
		DUK_DDD(DUK_DDDPRINT("end 2nd pass"));

		duk__update_lineinfo_currtoken(comp_ctx);

		if (needs_shuffle_before == comp_ctx->curr_func.needs_shuffle) {
			/* Shuffle decision not changed. */
			break;
		}
		if (compile_round >= 3) {
			/* Should never happen but avoid infinite loop just in case. */
			DUK_D(DUK_DPRINT("more than 3 compile passes needed, should never happen"));
			DUK_ERROR_INTERNAL(thr);
			DUK_WO_NORETURN(return;);
		}
		DUK_D(DUK_DPRINT("need additional round to compile function, round now %d", (int) compile_round));
	}

	/*
	 *  Emit a final RETURN.
	 *
	 *  It would be nice to avoid emitting an unnecessary "return" opcode
	 *  if the current PC is not reachable.  However, this cannot be reliably
	 *  detected; even if the previous instruction is an unconditional jump,
	 *  there may be a previous jump which jumps to current PC (which is the
	 *  case for iteration and conditional statements, for instance).
	 */

	/* XXX: request a "last statement is terminal" from duk__parse_stmt() and duk__parse_stmts();
	 * we could avoid the last RETURN if we could ensure there is no way to get here
	 * (directly or via a jump)
	 */

	DUK_ASSERT(comp_ctx->curr_func.catch_depth == 0);
	if (reg_stmt_value >= 0) {
		DUK_ASSERT(DUK__ISREG(reg_stmt_value));
		duk__emit_bc(comp_ctx, DUK_OP_RETREG, reg_stmt_value /*reg*/);
	} else {
		duk__emit_op_only(comp_ctx, DUK_OP_RETUNDEF);
	}

	/*
	 *  Peephole optimize JUMP chains.
	 */

	duk__peephole_optimize_bytecode(comp_ctx);

	/*
	 *  comp_ctx->curr_func is now ready to be converted into an actual
	 *  function template.
	 */

	DUK__RECURSION_DECREASE(comp_ctx, thr);
	return;

 error_funcname:
	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_FUNC_NAME);
	DUK_WO_NORETURN(return;);
}

/*
 *  Parse a function-like expression:
 *
 *    - function expression
 *    - function declaration
 *    - function statement (non-standard)
 *    - setter/getter
 *
 *  Adds the function to comp_ctx->curr_func function table and returns the
 *  function number.
 *
 *  On entry, curr_token points to:
 *
 *    - the token after 'function' for function expression/declaration/statement
 *    - the token after 'set' or 'get' for setter/getter
 */

/* Parse formals. */
DUK_LOCAL void duk__parse_func_formals(duk_compiler_ctx *comp_ctx) {
	duk_hthread *thr = comp_ctx->thr;
	duk_bool_t first = 1;
	duk_uarridx_t n;

	for (;;) {
		if (comp_ctx->curr_token.t == DUK_TOK_RPAREN) {
			break;
		}

		if (first) {
			/* no comma */
			first = 0;
		} else {
			duk__advance_expect(comp_ctx, DUK_TOK_COMMA);
		}

		/* Note: when parsing a formal list in non-strict context, e.g.
		 * "implements" is parsed as an identifier.  When the function is
		 * later detected to be strict, the argument list must be rechecked
		 * against a larger set of reserved words (that of strict mode).
		 * This is handled by duk__parse_func_body().  Here we recognize
		 * whatever tokens are considered reserved in current strictness
		 * (which is not always enough).
		 */

		if (comp_ctx->curr_token.t != DUK_TOK_IDENTIFIER) {
			DUK_ERROR_SYNTAX(thr, DUK_STR_EXPECTED_IDENTIFIER);
			DUK_WO_NORETURN(return;);
		}
		DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_IDENTIFIER);
		DUK_ASSERT(comp_ctx->curr_token.str1 != NULL);
		DUK_DDD(DUK_DDDPRINT("formal argument: %!O",
		                     (duk_heaphdr *) comp_ctx->curr_token.str1));

		/* XXX: append primitive */
		duk_push_hstring(thr, comp_ctx->curr_token.str1);
		n = (duk_uarridx_t) duk_get_length(thr, comp_ctx->curr_func.argnames_idx);
		duk_put_prop_index(thr, comp_ctx->curr_func.argnames_idx, n);

		duk__advance(comp_ctx);  /* eat identifier */
	}
}

/* Parse a function-like expression, assuming that 'comp_ctx->curr_func' is
 * correctly set up.  Assumes that curr_token is just after 'function' (or
 * 'set'/'get' etc).
 */
DUK_LOCAL void duk__parse_func_like_raw(duk_compiler_ctx *comp_ctx, duk_small_uint_t flags) {
	duk_hthread *thr = comp_ctx->thr;
	duk_token *tok;
	duk_bool_t no_advance;

	DUK_ASSERT(comp_ctx->curr_func.num_formals == 0);
	DUK_ASSERT(comp_ctx->curr_func.is_function == 1);
	DUK_ASSERT(comp_ctx->curr_func.is_eval == 0);
	DUK_ASSERT(comp_ctx->curr_func.is_global == 0);
	DUK_ASSERT(comp_ctx->curr_func.is_setget == ((flags & DUK__FUNC_FLAG_GETSET) != 0));

	duk__update_lineinfo_currtoken(comp_ctx);

	/*
	 *  Function name (if any)
	 *
	 *  We don't check for prohibited names here, because we don't
	 *  yet know whether the function will be strict.  Function body
	 *  parsing handles this retroactively.
	 *
	 *  For function expressions and declarations function name must
	 *  be an Identifer (excludes reserved words).  For setter/getter
	 *  it is a PropertyName which allows reserved words and also
	 *  strings and numbers (e.g. "{ get 1() { ... } }").
	 *
	 *  Function parsing may start either from prev_token or curr_token
	 *  (object literal method definition uses prev_token for example).
	 *  This is dealt with for the initial token.
	 */

	no_advance = (flags & DUK__FUNC_FLAG_USE_PREVTOKEN);
	if (no_advance) {
		tok = &comp_ctx->prev_token;
	} else {
		tok = &comp_ctx->curr_token;
	}

	if (flags & DUK__FUNC_FLAG_GETSET) {
		/* PropertyName -> IdentifierName | StringLiteral | NumericLiteral */
		if (tok->t_nores == DUK_TOK_IDENTIFIER || tok->t == DUK_TOK_STRING) {
			duk_push_hstring(thr, tok->str1);       /* keep in valstack */
		} else if (tok->t == DUK_TOK_NUMBER) {
			duk_push_number(thr, tok->num);
			duk_to_string(thr, -1);
		} else {
			DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_GETSET_NAME);
			DUK_WO_NORETURN(return;);
		}
		comp_ctx->curr_func.h_name = duk_known_hstring(thr, -1);  /* borrowed reference */
	} else {
		/* Function name is an Identifier (not IdentifierName), but we get
		 * the raw name (not recognizing keywords) here and perform the name
		 * checks only after pass 1.
		 */
		if (tok->t_nores == DUK_TOK_IDENTIFIER) {
			duk_push_hstring(thr, tok->str1);       /* keep in valstack */
			comp_ctx->curr_func.h_name = duk_known_hstring(thr, -1);  /* borrowed reference */
		} else {
			/* valstack will be unbalanced, which is OK */
			DUK_ASSERT((flags & DUK__FUNC_FLAG_GETSET) == 0);
			DUK_ASSERT(comp_ctx->curr_func.h_name == NULL);
			no_advance = 1;
			if (flags & DUK__FUNC_FLAG_DECL) {
				DUK_ERROR_SYNTAX(thr, DUK_STR_FUNC_NAME_REQUIRED);
				DUK_WO_NORETURN(return;);
			}
		}
	}

	DUK_DD(DUK_DDPRINT("function name: %!O",
	                   (duk_heaphdr *) comp_ctx->curr_func.h_name));

	if (!no_advance) {
		duk__advance(comp_ctx);
	}

	/*
	 *  Formal argument list
	 *
	 *  We don't check for prohibited names or for duplicate argument
	 *  names here, becase we don't yet know whether the function will
	 *  be strict.  Function body parsing handles this retroactively.
	 */

	duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);

	duk__parse_func_formals(comp_ctx);

	DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_RPAREN);
	duk__advance(comp_ctx);

	/*
	 *  Parse function body
	 */

	duk__parse_func_body(comp_ctx,
	                     0,   /* expect_eof */
	                     0,   /* implicit_return_value */
	                     flags & DUK__FUNC_FLAG_DECL, /* regexp_after */
	                     DUK_TOK_LCURLY);  /* expect_token */

	/*
	 *  Convert duk_compiler_func to a function template and add it
	 *  to the parent function table.
	 */

	duk__convert_to_func_template(comp_ctx);  /* -> [ ... func ] */
}

/* Parse an inner function, adding the function template to the current function's
 * function table.  Return a function number to be used by the outer function.
 *
 * Avoiding O(depth^2) inner function parsing is handled here.  On the first pass,
 * compile and register the function normally into the 'funcs' array, also recording
 * a lexer point (offset/line) to the closing brace of the function.  On the second
 * pass, skip the function and return the same 'fnum' as on the first pass by using
 * a running counter.
 *
 * An unfortunate side effect of this is that when parsing the inner function, almost
 * nothing is known of the outer function, i.e. the inner function's scope.  We don't
 * need that information at the moment, but it would allow some optimizations if it
 * were used.
 */
DUK_LOCAL duk_int_t duk__parse_func_like_fnum(duk_compiler_ctx *comp_ctx, duk_small_uint_t flags) {
	duk_hthread *thr = comp_ctx->thr;
	duk_compiler_func old_func;
	duk_idx_t entry_top;
	duk_int_t fnum;

	/*
	 *  On second pass, skip the function.
	 */

	if (!comp_ctx->curr_func.in_scanning) {
		duk_lexer_point lex_pt;

		fnum = comp_ctx->curr_func.fnum_next++;
		duk_get_prop_index(thr, comp_ctx->curr_func.funcs_idx, (duk_uarridx_t) (fnum * 3 + 1));
		lex_pt.offset = (duk_size_t) duk_to_uint(thr, -1);
		duk_pop(thr);
		duk_get_prop_index(thr, comp_ctx->curr_func.funcs_idx, (duk_uarridx_t) (fnum * 3 + 2));
		lex_pt.line = duk_to_int(thr, -1);
		duk_pop(thr);

		DUK_DDD(DUK_DDDPRINT("second pass of an inner func, skip the function, reparse closing brace; lex offset=%ld, line=%ld",
		                     (long) lex_pt.offset, (long) lex_pt.line));

		DUK_LEXER_SETPOINT(&comp_ctx->lex, &lex_pt);
		comp_ctx->curr_token.t = 0;  /* this is needed for regexp mode */
		comp_ctx->curr_token.start_line = 0;  /* needed for line number tracking (becomes prev_token.start_line) */
		duk__advance(comp_ctx);

		/* RegExp is not allowed after a function expression, e.g. in
		 * (function () {} / 123).  A RegExp *is* allowed after a
		 * function declaration!
		 */
		if (flags & DUK__FUNC_FLAG_DECL) {
			comp_ctx->curr_func.allow_regexp_in_adv = 1;
		}
		duk__advance_expect(comp_ctx, DUK_TOK_RCURLY);

		return fnum;
	}

	/*
	 *  On first pass, perform actual parsing.  Remember valstack top on entry
	 *  to restore it later, and switch to using a new function in comp_ctx.
	 */

	entry_top = duk_get_top(thr);
	DUK_DDD(DUK_DDDPRINT("before func: entry_top=%ld, curr_tok.start_offset=%ld",
	                     (long) entry_top, (long) comp_ctx->curr_token.start_offset));

	duk_memcpy(&old_func, &comp_ctx->curr_func, sizeof(duk_compiler_func));

	duk_memzero(&comp_ctx->curr_func, sizeof(duk_compiler_func));
	duk__init_func_valstack_slots(comp_ctx);
	DUK_ASSERT(comp_ctx->curr_func.num_formals == 0);

	/* inherit initial strictness from parent */
	comp_ctx->curr_func.is_strict = old_func.is_strict;

	/* XXX: It might be better to just store the flags into the curr_func
	 * struct and use them as is without this flag interpretation step
	 * here.
	 */
	DUK_ASSERT(comp_ctx->curr_func.is_notail == 0);
	comp_ctx->curr_func.is_function = 1;
	DUK_ASSERT(comp_ctx->curr_func.is_eval == 0);
	DUK_ASSERT(comp_ctx->curr_func.is_global == 0);
	comp_ctx->curr_func.is_setget = ((flags & DUK__FUNC_FLAG_GETSET) != 0);
	comp_ctx->curr_func.is_namebinding = !(flags & (DUK__FUNC_FLAG_GETSET |
	                                                DUK__FUNC_FLAG_METDEF |
	                                                DUK__FUNC_FLAG_DECL));  /* no name binding for: declarations, objlit getset, objlit method def */
	comp_ctx->curr_func.is_constructable = !(flags & (DUK__FUNC_FLAG_GETSET |
	                                                  DUK__FUNC_FLAG_METDEF));  /* not constructable: objlit getset, objlit method def */

	/*
	 *  Parse inner function
	 */

	duk__parse_func_like_raw(comp_ctx, flags);  /* pushes function template */

	/* prev_token.start_offset points to the closing brace here; when skipping
	 * we're going to reparse the closing brace to ensure semicolon insertion
	 * etc work as expected.
	 */
	DUK_DDD(DUK_DDDPRINT("after func: prev_tok.start_offset=%ld, curr_tok.start_offset=%ld",
	                     (long) comp_ctx->prev_token.start_offset, (long) comp_ctx->curr_token.start_offset));
	DUK_ASSERT(comp_ctx->lex.input[comp_ctx->prev_token.start_offset] == (duk_uint8_t) DUK_ASC_RCURLY);

	/* XXX: append primitive */
	DUK_ASSERT(duk_get_length(thr, old_func.funcs_idx) == (duk_size_t) (old_func.fnum_next * 3));
	fnum = old_func.fnum_next++;

	if (fnum > DUK__MAX_FUNCS) {
		DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_FUNC_LIMIT);
		DUK_WO_NORETURN(return 0;);
	}

	/* array writes autoincrement length */
	(void) duk_put_prop_index(thr, old_func.funcs_idx, (duk_uarridx_t) (fnum * 3));
	duk_push_size_t(thr, comp_ctx->prev_token.start_offset);
	(void) duk_put_prop_index(thr, old_func.funcs_idx, (duk_uarridx_t) (fnum * 3 + 1));
	duk_push_int(thr, comp_ctx->prev_token.start_line);
	(void) duk_put_prop_index(thr, old_func.funcs_idx, (duk_uarridx_t) (fnum * 3 + 2));

	/*
	 *  Cleanup: restore original function, restore valstack state.
	 *
	 *  Function declaration handling needs the function name to be pushed
	 *  on the value stack.
	 */

	if (flags & DUK__FUNC_FLAG_PUSHNAME_PASS1) {
		DUK_ASSERT(comp_ctx->curr_func.h_name != NULL);
		duk_push_hstring(thr, comp_ctx->curr_func.h_name);
		duk_replace(thr, entry_top);
		duk_set_top(thr, entry_top + 1);
	} else {
		duk_set_top(thr, entry_top);
	}
	duk_memcpy((void *) &comp_ctx->curr_func, (void *) &old_func, sizeof(duk_compiler_func));

	return fnum;
}

/*
 *  Compile input string into an executable function template without
 *  arguments.
 *
 *  The string is parsed as the "Program" production of ECMAScript E5.
 *  Compilation context can be either global code or eval code (see E5
 *  Sections 14 and 15.1.2.1).
 *
 *  Input stack:  [ ... filename ]
 *  Output stack: [ ... func_template ]
 */

/* XXX: source code property */

DUK_LOCAL duk_ret_t duk__js_compile_raw(duk_hthread *thr, void *udata) {
	duk_hstring *h_filename;
	duk__compiler_stkstate *comp_stk;
	duk_compiler_ctx *comp_ctx;
	duk_lexer_point *lex_pt;
	duk_compiler_func *func;
	duk_idx_t entry_top;
	duk_bool_t is_strict;
	duk_bool_t is_eval;
	duk_bool_t is_funcexpr;
	duk_small_uint_t flags;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(udata != NULL);

	/*
	 *  Arguments check
	 */

	entry_top = duk_get_top(thr);
	DUK_ASSERT(entry_top >= 1);

	comp_stk = (duk__compiler_stkstate *) udata;
	comp_ctx = &comp_stk->comp_ctx_alloc;
	lex_pt = &comp_stk->lex_pt_alloc;
	DUK_ASSERT(comp_ctx != NULL);
	DUK_ASSERT(lex_pt != NULL);

	flags = comp_stk->flags;
	is_eval = (flags & DUK_COMPILE_EVAL ? 1 : 0);
	is_strict = (flags & DUK_COMPILE_STRICT ? 1 : 0);
	is_funcexpr = (flags & DUK_COMPILE_FUNCEXPR ? 1 : 0);

	h_filename = duk_get_hstring(thr, -1);  /* may be undefined */

	/*
	 *  Init compiler and lexer contexts
	 */

	func = &comp_ctx->curr_func;
#if defined(DUK_USE_EXPLICIT_NULL_INIT)
	comp_ctx->thr = NULL;
	comp_ctx->h_filename = NULL;
	comp_ctx->prev_token.str1 = NULL;
	comp_ctx->prev_token.str2 = NULL;
	comp_ctx->curr_token.str1 = NULL;
	comp_ctx->curr_token.str2 = NULL;
#endif

	duk_require_stack(thr, DUK__COMPILE_ENTRY_SLOTS);

	duk_push_dynamic_buffer(thr, 0);       /* entry_top + 0 */
	duk_push_undefined(thr);               /* entry_top + 1 */
	duk_push_undefined(thr);               /* entry_top + 2 */
	duk_push_undefined(thr);               /* entry_top + 3 */
	duk_push_undefined(thr);               /* entry_top + 4 */

	comp_ctx->thr = thr;
	comp_ctx->h_filename = h_filename;
	comp_ctx->tok11_idx = entry_top + 1;
	comp_ctx->tok12_idx = entry_top + 2;
	comp_ctx->tok21_idx = entry_top + 3;
	comp_ctx->tok22_idx = entry_top + 4;
	comp_ctx->recursion_limit = DUK_USE_COMPILER_RECLIMIT;

	/* comp_ctx->lex has been pre-initialized by caller: it has been
	 * zeroed and input/input_length has been set.
	 */
	comp_ctx->lex.thr = thr;
	/* comp_ctx->lex.input and comp_ctx->lex.input_length filled by caller */
	comp_ctx->lex.slot1_idx = comp_ctx->tok11_idx;
	comp_ctx->lex.slot2_idx = comp_ctx->tok12_idx;
	comp_ctx->lex.buf_idx = entry_top + 0;
	comp_ctx->lex.buf = (duk_hbuffer_dynamic *) duk_known_hbuffer(thr, entry_top + 0);
	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(comp_ctx->lex.buf) && !DUK_HBUFFER_HAS_EXTERNAL(comp_ctx->lex.buf));
	comp_ctx->lex.token_limit = DUK_COMPILER_TOKEN_LIMIT;

	lex_pt->offset = 0;
	lex_pt->line = 1;
	DUK_LEXER_SETPOINT(&comp_ctx->lex, lex_pt);    /* fills window */
	comp_ctx->curr_token.start_line = 0;  /* needed for line number tracking (becomes prev_token.start_line) */

	/*
	 *  Initialize function state for a zero-argument function
	 */

	duk__init_func_valstack_slots(comp_ctx);
	DUK_ASSERT(func->num_formals == 0);

	if (is_funcexpr) {
		/* Name will be filled from function expression, not by caller.
		 * This case is used by Function constructor and duk_compile()
		 * API with the DUK_COMPILE_FUNCTION option.
		 */
		DUK_ASSERT(func->h_name == NULL);
	} else {
		duk_push_hstring_stridx(thr, (is_eval ? DUK_STRIDX_EVAL :
		                                        DUK_STRIDX_GLOBAL));
		func->h_name = duk_get_hstring(thr, -1);
	}

	/*
	 *  Parse a function body or a function-like expression, depending
	 *  on flags.
	 */

	DUK_ASSERT(func->is_setget == 0);
	func->is_strict = (duk_uint8_t) is_strict;
	DUK_ASSERT(func->is_notail == 0);

	if (is_funcexpr) {
		func->is_function = 1;
		DUK_ASSERT(func->is_eval == 0);
		DUK_ASSERT(func->is_global == 0);
		func->is_namebinding = 1;
		func->is_constructable = 1;

		duk__advance(comp_ctx);  /* init 'curr_token' */
		duk__advance_expect(comp_ctx, DUK_TOK_FUNCTION);
		(void) duk__parse_func_like_raw(comp_ctx, 0 /*flags*/);
	} else {
		DUK_ASSERT(func->is_function == 0);
		DUK_ASSERT(is_eval == 0 || is_eval == 1);
		func->is_eval = (duk_uint8_t) is_eval;
		func->is_global = (duk_uint8_t) !is_eval;
		DUK_ASSERT(func->is_namebinding == 0);
		DUK_ASSERT(func->is_constructable == 0);

		duk__parse_func_body(comp_ctx,
		                     1,             /* expect_eof */
		                     1,             /* implicit_return_value */
		                     1,             /* regexp_after (does not matter) */
		                     -1);           /* expect_token */
	}

	/*
	 *  Convert duk_compiler_func to a function template
	 */

	duk__convert_to_func_template(comp_ctx);

	/*
	 *  Wrapping duk_safe_call() will mangle the stack, just return stack top
	 */

	/* [ ... filename (temps) func ] */

	return 1;
}

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) {
	duk__compiler_stkstate comp_stk;
	duk_compiler_ctx *prev_ctx;
	duk_ret_t safe_rc;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(src_buffer != NULL);

	/* preinitialize lexer state partially */
	duk_memzero(&comp_stk, sizeof(comp_stk));
	comp_stk.flags = flags;
	DUK_LEXER_INITCTX(&comp_stk.comp_ctx_alloc.lex);
	comp_stk.comp_ctx_alloc.lex.input = src_buffer;
	comp_stk.comp_ctx_alloc.lex.input_length = src_length;
	comp_stk.comp_ctx_alloc.lex.flags = flags;  /* Forward flags directly for now. */

	/* [ ... filename ] */

	prev_ctx = thr->compile_ctx;
	thr->compile_ctx = &comp_stk.comp_ctx_alloc;  /* for duk_error_augment.c */
	safe_rc = duk_safe_call(thr, duk__js_compile_raw, (void *) &comp_stk /*udata*/, 1 /*nargs*/, 1 /*nrets*/);
	thr->compile_ctx = prev_ctx;  /* must restore reliably before returning */

	if (safe_rc != DUK_EXEC_SUCCESS) {
		DUK_D(DUK_DPRINT("compilation failed: %!T", duk_get_tval(thr, -1)));
		(void) duk_throw(thr);
		DUK_WO_NORETURN(return;);
	}

	/* [ ... template ] */
}

/* automatic undefs */
#undef DUK__ALLOCTEMP
#undef DUK__ALLOCTEMPS
#undef DUK__ALLOW_AUTO_SEMI_ALWAYS
#undef DUK__BC_INITIAL_INSTS
#undef DUK__BP_ADDITIVE
#undef DUK__BP_ASSIGNMENT
#undef DUK__BP_BAND
#undef DUK__BP_BOR
#undef DUK__BP_BXOR
#undef DUK__BP_CALL
#undef DUK__BP_CLOSING
#undef DUK__BP_COMMA
#undef DUK__BP_CONDITIONAL
#undef DUK__BP_EOF
#undef DUK__BP_EQUALITY
#undef DUK__BP_EXPONENTIATION
#undef DUK__BP_FOR_EXPR
#undef DUK__BP_INVALID
#undef DUK__BP_LAND
#undef DUK__BP_LOR
#undef DUK__BP_MEMBER
#undef DUK__BP_MULTIPLICATIVE
#undef DUK__BP_POSTFIX
#undef DUK__BP_RELATIONAL
#undef DUK__BP_SHIFT
#undef DUK__COMPILE_ENTRY_SLOTS
#undef DUK__CONST_MARKER
#undef DUK__DUMP_ISPEC
#undef DUK__DUMP_IVALUE
#undef DUK__EMIT_FLAG_A_IS_SOURCE
#undef DUK__EMIT_FLAG_BC_REGCONST
#undef DUK__EMIT_FLAG_B_IS_TARGET
#undef DUK__EMIT_FLAG_C_IS_TARGET
#undef DUK__EMIT_FLAG_NO_SHUFFLE_A
#undef DUK__EMIT_FLAG_NO_SHUFFLE_B
#undef DUK__EMIT_FLAG_NO_SHUFFLE_C
#undef DUK__EMIT_FLAG_RESERVE_JUMPSLOT
#undef DUK__EXPR_FLAG_ALLOW_EMPTY
#undef DUK__EXPR_FLAG_REJECT_IN
#undef DUK__EXPR_FLAG_REQUIRE_INIT
#undef DUK__EXPR_RBP_MASK
#undef DUK__FUNCTION_BODY_REQUIRE_SLOTS
#undef DUK__FUNCTION_INIT_REQUIRE_SLOTS
#undef DUK__FUNC_FLAG_DECL
#undef DUK__FUNC_FLAG_GETSET
#undef DUK__FUNC_FLAG_METDEF
#undef DUK__FUNC_FLAG_PUSHNAME_PASS1
#undef DUK__FUNC_FLAG_USE_PREVTOKEN
#undef DUK__GETCONST_MAX_CONSTS_CHECK
#undef DUK__GETTEMP
#undef DUK__HAS_TERM
#undef DUK__HAS_VAL
#undef DUK__ISCONST
#undef DUK__ISREG
#undef DUK__ISREG_NOTTEMP
#undef DUK__ISREG_TEMP
#undef DUK__IS_TERMINAL
#undef DUK__IVAL_FLAG_ALLOW_CONST
#undef DUK__IVAL_FLAG_REQUIRE_SHORT
#undef DUK__IVAL_FLAG_REQUIRE_TEMP
#undef DUK__MAX_ARRAY_INIT_VALUES
#undef DUK__MAX_CONSTS
#undef DUK__MAX_FUNCS
#undef DUK__MAX_OBJECT_INIT_PAIRS
#undef DUK__MAX_TEMPS
#undef DUK__MK_LBP
#undef DUK__MK_LBP_FLAGS
#undef DUK__OBJ_LIT_KEY_GET
#undef DUK__OBJ_LIT_KEY_PLAIN
#undef DUK__OBJ_LIT_KEY_SET
#undef DUK__PARSE_EXPR_SLOTS
#undef DUK__PARSE_STATEMENTS_SLOTS
#undef DUK__RECURSION_DECREASE
#undef DUK__RECURSION_INCREASE
#undef DUK__REMOVECONST
#undef DUK__SETTEMP
#undef DUK__SETTEMP_CHECKMAX
#undef DUK__STILL_PROLOGUE
#undef DUK__TOKEN_LBP_BP_MASK
#undef DUK__TOKEN_LBP_FLAG_NO_REGEXP
#undef DUK__TOKEN_LBP_FLAG_TERMINATES
#undef DUK__TOKEN_LBP_FLAG_UNUSED
#undef DUK__TOKEN_LBP_GET_BP
#line 1 "duk_js_executor.c"
/*
 *  ECMAScript bytecode executor.
 */

/* #include duk_internal.h -> already included */

/*
 *  Local declarations.
 */

DUK_LOCAL_DECL void duk__js_execute_bytecode_inner(duk_hthread *entry_thread, duk_activation *entry_act);

/*
 *  Misc helpers.
 */

/* Replace value stack top to value at 'tv_ptr'.  Optimize for
 * performance by only applying the net refcount change.
 */
#define DUK__REPLACE_TO_TVPTR(thr,tv_ptr) do { \
		duk_hthread *duk__thr; \
		duk_tval *duk__tvsrc; \
		duk_tval *duk__tvdst; \
		duk_tval duk__tvtmp; \
		duk__thr = (thr); \
		duk__tvsrc = DUK_GET_TVAL_NEGIDX(duk__thr, -1); \
		duk__tvdst = (tv_ptr); \
		DUK_TVAL_SET_TVAL(&duk__tvtmp, duk__tvdst); \
		DUK_TVAL_SET_TVAL(duk__tvdst, duk__tvsrc); \
		DUK_TVAL_SET_UNDEFINED(duk__tvsrc);  /* value stack init policy */ \
		duk__thr->valstack_top = duk__tvsrc; \
		DUK_TVAL_DECREF(duk__thr, &duk__tvtmp); \
	} while (0)

/* XXX: candidate of being an internal shared API call */
#if 0  /* unused */
DUK_LOCAL void duk__push_tvals_incref_only(duk_hthread *thr, duk_tval *tv_src, duk_small_uint_fast_t count) {
	duk_tval *tv_dst;
	duk_size_t copy_size;
	duk_size_t i;

	tv_dst = thr->valstack_top;
	copy_size = sizeof(duk_tval) * count;
	duk_memcpy((void *) tv_dst, (const void *) tv_src, copy_size);
	for (i = 0; i < count; i++) {
		DUK_TVAL_INCREF(thr, tv_dst);
		tv_dst++;
	}
	thr->valstack_top = tv_dst;
}
#endif

/*
 *  Arithmetic, binary, and logical helpers.
 *
 *  Note: there is no opcode for logical AND or logical OR; this is on
 *  purpose, because the evalution order semantics for them make such
 *  opcodes pretty pointless: short circuiting means they are most
 *  comfortably implemented as jumps.  However, a logical NOT opcode
 *  is useful.
 *
 *  Note: careful with duk_tval pointers here: they are potentially
 *  invalidated by any DECREF and almost any API call.  It's still
 *  preferable to work without making a copy but that's not always
 *  possible.
 */

DUK_LOCAL DUK_EXEC_ALWAYS_INLINE_PERF duk_double_t duk__compute_mod(duk_double_t d1, duk_double_t d2) {
	return (duk_double_t) duk_js_arith_mod((double) d1, (double) d2);
}

#if defined(DUK_USE_ES7_EXP_OPERATOR)
DUK_LOCAL DUK_EXEC_ALWAYS_INLINE_PERF duk_double_t duk__compute_exp(duk_double_t d1, duk_double_t d2) {
	return (duk_double_t) duk_js_arith_pow((double) d1, (double) d2);
}
#endif

DUK_LOCAL DUK_EXEC_ALWAYS_INLINE_PERF void duk__vm_arith_add(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_uint_fast_t idx_z) {
	/*
	 *  Addition operator is different from other arithmetic
	 *  operations in that it also provides string concatenation.
	 *  Hence it is implemented separately.
	 *
	 *  There is a fast path for number addition.  Other cases go
	 *  through potentially multiple coercions as described in the
	 *  E5 specification.  It may be possible to reduce the number
	 *  of coercions, but this must be done carefully to preserve
	 *  the exact semantics.
	 *
	 *  E5 Section 11.6.1.
	 *
	 *  Custom types also have special behavior implemented here.
	 */

	duk_double_union du;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(tv_x != NULL);  /* may be reg or const */
	DUK_ASSERT(tv_y != NULL);  /* may be reg or const */
	DUK_ASSERT_DISABLE(idx_z >= 0);  /* unsigned */
	DUK_ASSERT((duk_uint_t) idx_z < (duk_uint_t) duk_get_top(thr));

	/*
	 *  Fast paths
	 */

#if defined(DUK_USE_FASTINT)
	if (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {
		duk_int64_t v1, v2, v3;
		duk_int32_t v3_hi;
		duk_tval *tv_z;

		/* Input values are signed 48-bit so we can detect overflow
		 * reliably from high bits or just a comparison.
		 */

		v1 = DUK_TVAL_GET_FASTINT(tv_x);
		v2 = DUK_TVAL_GET_FASTINT(tv_y);
		v3 = v1 + v2;
		v3_hi = (duk_int32_t) (v3 >> 32);
		if (DUK_LIKELY(v3_hi >= DUK_I64_CONSTANT(-0x8000) && v3_hi <= DUK_I64_CONSTANT(0x7fff))) {
			tv_z = thr->valstack_bottom + idx_z;
			DUK_TVAL_SET_FASTINT_UPDREF(thr, tv_z, v3);  /* side effects */
			return;
		} else {
			/* overflow, fall through */
			;
		}
	}
#endif  /* DUK_USE_FASTINT */

	if (DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y)) {
#if !defined(DUK_USE_EXEC_PREFER_SIZE)
		duk_tval *tv_z;
#endif

		du.d = DUK_TVAL_GET_NUMBER(tv_x) + DUK_TVAL_GET_NUMBER(tv_y);
#if defined(DUK_USE_EXEC_PREFER_SIZE)
		duk_push_number(thr, du.d);  /* will NaN normalize result */
		duk_replace(thr, (duk_idx_t) idx_z);
#else  /* DUK_USE_EXEC_PREFER_SIZE */
		DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);
		DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
		tv_z = thr->valstack_bottom + idx_z;
		DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_z, du.d);  /* side effects */
#endif  /* DUK_USE_EXEC_PREFER_SIZE */
		return;
	}

	/*
	 *  Slow path: potentially requires function calls for coercion
	 */

	duk_push_tval(thr, tv_x);
	duk_push_tval(thr, tv_y);
	duk_to_primitive(thr, -2, DUK_HINT_NONE);  /* side effects -> don't use tv_x, tv_y after */
	duk_to_primitive(thr, -1, DUK_HINT_NONE);

	/* Since Duktape 2.x plain buffers are treated like ArrayBuffer. */
	if (duk_is_string(thr, -2) || duk_is_string(thr, -1)) {
		/* Symbols shouldn't technically be handled here, but should
		 * go into the default ToNumber() coercion path instead and
		 * fail there with a TypeError.  However, there's a ToString()
		 * in duk_concat_2() which also fails with TypeError so no
		 * explicit check is needed.
		 */
		duk_concat_2(thr);  /* [... s1 s2] -> [... s1+s2] */
	} else {
		duk_double_t d1, d2;

		d1 = duk_to_number_m2(thr);
		d2 = duk_to_number_m1(thr);
		DUK_ASSERT(duk_is_number(thr, -2));
		DUK_ASSERT(duk_is_number(thr, -1));
		DUK_ASSERT_DOUBLE_IS_NORMALIZED(d1);
		DUK_ASSERT_DOUBLE_IS_NORMALIZED(d2);

		du.d = d1 + d2;
		duk_pop_2_unsafe(thr);
		duk_push_number(thr, du.d);  /* will NaN normalize result */
	}
	duk_replace(thr, (duk_idx_t) idx_z);  /* side effects */
}

DUK_LOCAL DUK_EXEC_ALWAYS_INLINE_PERF void duk__vm_arith_binary_op(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_uint_fast_t idx_z, duk_small_uint_fast_t opcode) {
	/*
	 *  Arithmetic operations other than '+' have number-only semantics
	 *  and are implemented here.  The separate switch-case here means a
	 *  "double dispatch" of the arithmetic opcode, but saves code space.
	 *
	 *  E5 Sections 11.5, 11.5.1, 11.5.2, 11.5.3, 11.6, 11.6.1, 11.6.2, 11.6.3.
	 */

	duk_double_t d1, d2;
	duk_double_union du;
	duk_small_uint_fast_t opcode_shifted;
#if defined(DUK_USE_FASTINT) || !defined(DUK_USE_EXEC_PREFER_SIZE)
	duk_tval *tv_z;
#endif

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(tv_x != NULL);  /* may be reg or const */
	DUK_ASSERT(tv_y != NULL);  /* may be reg or const */
	DUK_ASSERT_DISABLE(idx_z >= 0);  /* unsigned */
	DUK_ASSERT((duk_uint_t) idx_z < (duk_uint_t) duk_get_top(thr));

	opcode_shifted = opcode >> 2;  /* Get base opcode without reg/const modifiers. */

#if defined(DUK_USE_FASTINT)
	if (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {
		duk_int64_t v1, v2, v3;
		duk_int32_t v3_hi;

		v1 = DUK_TVAL_GET_FASTINT(tv_x);
		v2 = DUK_TVAL_GET_FASTINT(tv_y);

		switch (opcode_shifted) {
		case DUK_OP_SUB >> 2: {
			v3 = v1 - v2;
			break;
		}
		case DUK_OP_MUL >> 2: {
			/* Must ensure result is 64-bit (no overflow); a
			 * simple and sufficient fast path is to allow only
			 * 32-bit inputs.  Avoid zero inputs to avoid
			 * negative zero issues (-1 * 0 = -0, for instance).
			 */
			if (v1 >= DUK_I64_CONSTANT(-0x80000000) && v1 <= DUK_I64_CONSTANT(0x7fffffff) && v1 != 0 &&
			    v2 >= DUK_I64_CONSTANT(-0x80000000) && v2 <= DUK_I64_CONSTANT(0x7fffffff) && v2 != 0) {
				v3 = v1 * v2;
			} else {
				goto skip_fastint;
			}
			break;
		}
		case DUK_OP_DIV >> 2: {
			/* Don't allow a zero divisor.  Fast path check by
			 * "verifying" with multiplication.  Also avoid zero
			 * dividend to avoid negative zero issues (0 / -1 = -0
			 * for instance).
			 */
			if (v1 == 0 || v2 == 0) {
				goto skip_fastint;
			}
			v3 = v1 / v2;
			if (v3 * v2 != v1) {
				goto skip_fastint;
			}
			break;
		}
		case DUK_OP_MOD >> 2: {
			/* Don't allow a zero divisor.  Restrict both v1 and
			 * v2 to positive values to avoid compiler specific
			 * behavior.
			 */
			if (v1 < 1 || v2 < 1) {
				goto skip_fastint;
			}
			v3 = v1 % v2;
			DUK_ASSERT(v3 >= 0);
			DUK_ASSERT(v3 < v2);
			DUK_ASSERT(v1 - (v1 / v2) * v2 == v3);
			break;
		}
		default: {
			/* Possible with DUK_OP_EXP. */
			goto skip_fastint;
		}
		}

		v3_hi = (duk_int32_t) (v3 >> 32);
		if (DUK_LIKELY(v3_hi >= DUK_I64_CONSTANT(-0x8000) && v3_hi <= DUK_I64_CONSTANT(0x7fff))) {
			tv_z = thr->valstack_bottom + idx_z;
			DUK_TVAL_SET_FASTINT_UPDREF(thr, tv_z, v3);  /* side effects */
			return;
		}
		/* fall through if overflow etc */
	}
 skip_fastint:
#endif  /* DUK_USE_FASTINT */

	if (DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y)) {
		/* fast path */
		d1 = DUK_TVAL_GET_NUMBER(tv_x);
		d2 = DUK_TVAL_GET_NUMBER(tv_y);
	} else {
		duk_push_tval(thr, tv_x);
		duk_push_tval(thr, tv_y);
		d1 = duk_to_number_m2(thr);  /* side effects */
		d2 = duk_to_number_m1(thr);
		DUK_ASSERT(duk_is_number(thr, -2));
		DUK_ASSERT(duk_is_number(thr, -1));
		DUK_ASSERT_DOUBLE_IS_NORMALIZED(d1);
		DUK_ASSERT_DOUBLE_IS_NORMALIZED(d2);
		duk_pop_2_unsafe(thr);
	}

	switch (opcode_shifted) {
	case DUK_OP_SUB >> 2: {
		du.d = d1 - d2;
		break;
	}
	case DUK_OP_MUL >> 2: {
		du.d = d1 * d2;
		break;
	}
	case DUK_OP_DIV >> 2: {
		/* Division-by-zero is undefined behavior, so
		 * rely on a helper.
		 */
		du.d = duk_double_div(d1, d2);
		break;
	}
	case DUK_OP_MOD >> 2: {
		du.d = duk__compute_mod(d1, d2);
		break;
	}
#if defined(DUK_USE_ES7_EXP_OPERATOR)
	case DUK_OP_EXP >> 2: {
		du.d = duk__compute_exp(d1, d2);
		break;
	}
#endif
	default: {
		DUK_UNREACHABLE();
		du.d = DUK_DOUBLE_NAN;  /* should not happen */
		break;
	}
	}

#if defined(DUK_USE_EXEC_PREFER_SIZE)
	duk_push_number(thr, du.d);  /* will NaN normalize result */
	duk_replace(thr, (duk_idx_t) idx_z);
#else  /* DUK_USE_EXEC_PREFER_SIZE */
	/* important to use normalized NaN with 8-byte tagged types */
	DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);
	DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
	tv_z = thr->valstack_bottom + idx_z;
	DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_z, du.d);  /* side effects */
#endif  /* DUK_USE_EXEC_PREFER_SIZE */
}

DUK_LOCAL DUK_EXEC_ALWAYS_INLINE_PERF void duk__vm_bitwise_binary_op(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_uint_fast_t idx_z, duk_small_uint_fast_t opcode) {
	/*
	 *  Binary bitwise operations use different coercions (ToInt32, ToUint32)
	 *  depending on the operation.  We coerce the arguments first using
	 *  ToInt32(), and then cast to an 32-bit value if necessary.  Note that
	 *  such casts must be correct even if there is no native 32-bit type
	 *  (e.g., duk_int32_t and duk_uint32_t are 64-bit).
	 *
	 *  E5 Sections 11.10, 11.7.1, 11.7.2, 11.7.3
	 */

	duk_int32_t i1, i2, i3;
	duk_uint32_t u1, u2, u3;
#if defined(DUK_USE_FASTINT)
	duk_int64_t fi3;
#else
	duk_double_t d3;
#endif
	duk_small_uint_fast_t opcode_shifted;
#if defined(DUK_USE_FASTINT) || !defined(DUK_USE_EXEC_PREFER_SIZE)
	duk_tval *tv_z;
#endif

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(tv_x != NULL);  /* may be reg or const */
	DUK_ASSERT(tv_y != NULL);  /* may be reg or const */
	DUK_ASSERT_DISABLE(idx_z >= 0);  /* unsigned */
	DUK_ASSERT((duk_uint_t) idx_z < (duk_uint_t) duk_get_top(thr));

	opcode_shifted = opcode >> 2;  /* Get base opcode without reg/const modifiers. */

#if defined(DUK_USE_FASTINT)
	if (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {
		i1 = (duk_int32_t) DUK_TVAL_GET_FASTINT_I32(tv_x);
		i2 = (duk_int32_t) DUK_TVAL_GET_FASTINT_I32(tv_y);
	}
	else
#endif  /* DUK_USE_FASTINT */
	{
		duk_push_tval(thr, tv_x);
		duk_push_tval(thr, tv_y);
		i1 = duk_to_int32(thr, -2);
		i2 = duk_to_int32(thr, -1);
		duk_pop_2_unsafe(thr);
	}

	switch (opcode_shifted) {
	case DUK_OP_BAND >> 2: {
		i3 = i1 & i2;
		break;
	}
	case DUK_OP_BOR >> 2: {
		i3 = i1 | i2;
		break;
	}
	case DUK_OP_BXOR >> 2: {
		i3 = i1 ^ i2;
		break;
	}
	case DUK_OP_BASL >> 2: {
		/* Signed shift, named "arithmetic" (asl) because the result
		 * is signed, e.g. 4294967295 << 1 -> -2.  Note that result
		 * must be masked.
		 */

		u2 = ((duk_uint32_t) i2) & 0xffffffffUL;
		i3 = (duk_int32_t) (((duk_uint32_t) i1) << (u2 & 0x1fUL));  /* E5 Section 11.7.1, steps 7 and 8 */
		i3 = i3 & ((duk_int32_t) 0xffffffffUL);                     /* Note: left shift, should mask */
		break;
	}
	case DUK_OP_BASR >> 2: {
		/* signed shift */

		u2 = ((duk_uint32_t) i2) & 0xffffffffUL;
		i3 = i1 >> (u2 & 0x1fUL);                      /* E5 Section 11.7.2, steps 7 and 8 */
		break;
	}
	case DUK_OP_BLSR >> 2: {
		/* unsigned shift */

		u1 = ((duk_uint32_t) i1) & 0xffffffffUL;
		u2 = ((duk_uint32_t) i2) & 0xffffffffUL;

		/* special result value handling */
		u3 = u1 >> (u2 & 0x1fUL);     /* E5 Section 11.7.2, steps 7 and 8 */
#if defined(DUK_USE_FASTINT)
		fi3 = (duk_int64_t) u3;
		goto fastint_result_set;
#else
		d3 = (duk_double_t) u3;
		goto result_set;
#endif
	}
	default: {
		DUK_UNREACHABLE();
		i3 = 0;  /* should not happen */
		break;
	}
	}

#if defined(DUK_USE_FASTINT)
	/* Result is always fastint compatible. */
	/* XXX: Set 32-bit result (but must then handle signed and
	 * unsigned results separately).
	 */
	fi3 = (duk_int64_t) i3;

 fastint_result_set:
	tv_z = thr->valstack_bottom + idx_z;
	DUK_TVAL_SET_FASTINT_UPDREF(thr, tv_z, fi3);  /* side effects */
#else  /* DUK_USE_FASTINT */
	d3 = (duk_double_t) i3;

 result_set:
	DUK_ASSERT(!DUK_ISNAN(d3));            /* 'd3' is never NaN, so no need to normalize */
	DUK_ASSERT_DOUBLE_IS_NORMALIZED(d3);   /* always normalized */

#if defined(DUK_USE_EXEC_PREFER_SIZE)
	duk_push_number(thr, d3);  /* would NaN normalize result, but unnecessary */
	duk_replace(thr, (duk_idx_t) idx_z);
#else  /* DUK_USE_EXEC_PREFER_SIZE */
	tv_z = thr->valstack_bottom + idx_z;
	DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_z, d3);  /* side effects */
#endif  /* DUK_USE_EXEC_PREFER_SIZE */
#endif  /* DUK_USE_FASTINT */
}

/* In-place unary operation. */
DUK_LOCAL DUK_EXEC_ALWAYS_INLINE_PERF void duk__vm_arith_unary_op(duk_hthread *thr, duk_uint_fast_t idx_src, duk_uint_fast_t idx_dst, duk_small_uint_fast_t opcode) {
	/*
	 *  Arithmetic operations other than '+' have number-only semantics
	 *  and are implemented here.  The separate switch-case here means a
	 *  "double dispatch" of the arithmetic opcode, but saves code space.
	 *
	 *  E5 Sections 11.5, 11.5.1, 11.5.2, 11.5.3, 11.6, 11.6.1, 11.6.2, 11.6.3.
	 */

	duk_tval *tv;
	duk_double_t d1;
	duk_double_union du;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(opcode == DUK_OP_UNM || opcode == DUK_OP_UNP);
	DUK_ASSERT_DISABLE(idx_src >= 0);
	DUK_ASSERT_DISABLE(idx_dst >= 0);

	tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_src);

#if defined(DUK_USE_FASTINT)
	if (DUK_TVAL_IS_FASTINT(tv)) {
		duk_int64_t v1, v2;

		v1 = DUK_TVAL_GET_FASTINT(tv);
		if (opcode == DUK_OP_UNM) {
			/* The smallest fastint is no longer 48-bit when
			 * negated.  Positive zero becames negative zero
			 * (cannot be represented) when negated.
			 */
			if (DUK_LIKELY(v1 != DUK_FASTINT_MIN && v1 != 0)) {
				v2 = -v1;
				tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst);
				DUK_TVAL_SET_FASTINT_UPDREF(thr, tv, v2);
				return;
			}
		} else {
			/* ToNumber() for a fastint is a no-op. */
			DUK_ASSERT(opcode == DUK_OP_UNP);
			v2 = v1;
			tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst);
			DUK_TVAL_SET_FASTINT_UPDREF(thr, tv, v2);
			return;
		}
		/* fall through if overflow etc */
	}
#endif  /* DUK_USE_FASTINT */

	if (DUK_TVAL_IS_NUMBER(tv)) {
		d1 = DUK_TVAL_GET_NUMBER(tv);
	} else {
		d1 = duk_to_number_tval(thr, tv);  /* side effects */
	}

	if (opcode == DUK_OP_UNP) {
		/* ToNumber() for a double is a no-op, but unary plus is
		 * used to force a fastint check so do that here.
		 */
		du.d = d1;
		DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
#if defined(DUK_USE_FASTINT)
		tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst);
		DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF(thr, tv, du.d);  /* always 'fast', i.e. inlined */
		return;
#endif
	} else {
		DUK_ASSERT(opcode == DUK_OP_UNM);
		du.d = -d1;
		DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);  /* mandatory if du.d is a NaN */
		DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
	}

	/* XXX: size optimize: push+replace? */
	tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst);
	DUK_TVAL_SET_NUMBER_UPDREF(thr, tv, du.d);
}

DUK_LOCAL DUK_EXEC_ALWAYS_INLINE_PERF void duk__vm_bitwise_not(duk_hthread *thr, duk_uint_fast_t idx_src, duk_uint_fast_t idx_dst) {
	/*
	 *  E5 Section 11.4.8
	 */

	duk_tval *tv;
	duk_int32_t i1, i2;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT_DISABLE(idx_src >= 0);
	DUK_ASSERT_DISABLE(idx_dst >= 0);
	DUK_ASSERT((duk_uint_t) idx_src < (duk_uint_t) duk_get_top(thr));
	DUK_ASSERT((duk_uint_t) idx_dst < (duk_uint_t) duk_get_top(thr));

	tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_src);

#if defined(DUK_USE_FASTINT)
	if (DUK_TVAL_IS_FASTINT(tv)) {
		i1 = (duk_int32_t) DUK_TVAL_GET_FASTINT_I32(tv);
	}
	else
#endif  /* DUK_USE_FASTINT */
	{
		duk_push_tval(thr, tv);
		i1 = duk_to_int32(thr, -1);  /* side effects */
		duk_pop_unsafe(thr);
	}

	/* Result is always fastint compatible. */
	i2 = ~i1;
	tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst);
	DUK_TVAL_SET_I32_UPDREF(thr, tv, i2);  /* side effects */
}

DUK_LOCAL DUK_EXEC_ALWAYS_INLINE_PERF void duk__vm_logical_not(duk_hthread *thr, duk_uint_fast_t idx_src, duk_uint_fast_t idx_dst) {
	/*
	 *  E5 Section 11.4.9
	 */

	duk_tval *tv;
	duk_bool_t res;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT_DISABLE(idx_src >= 0);
	DUK_ASSERT_DISABLE(idx_dst >= 0);
	DUK_ASSERT((duk_uint_t) idx_src < (duk_uint_t) duk_get_top(thr));
	DUK_ASSERT((duk_uint_t) idx_dst < (duk_uint_t) duk_get_top(thr));

	/* ToBoolean() does not require any operations with side effects so
	 * we can do it efficiently.  For footprint it would be better to use
	 * duk_js_toboolean() and then push+replace to the result slot.
	 */
	tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_src);
	res = duk_js_toboolean(tv);  /* does not modify 'tv' */
	DUK_ASSERT(res == 0 || res == 1);
	res ^= 1;
	tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst);
	/* XXX: size optimize: push+replace? */
	DUK_TVAL_SET_BOOLEAN_UPDREF(thr, tv, res);  /* side effects */
}

/* XXX: size optimized variant */
DUK_LOCAL DUK_EXEC_ALWAYS_INLINE_PERF void duk__prepost_incdec_reg_helper(duk_hthread *thr, duk_tval *tv_dst, duk_tval *tv_src, duk_small_uint_t op) {
	duk_double_t x, y, z;

	/* Two lowest bits of opcode are used to distinguish
	 * variants.  Bit 0 = inc(0)/dec(1), bit 1 = pre(0)/post(1).
	 */
	DUK_ASSERT((DUK_OP_PREINCR & 0x03) == 0x00);
	DUK_ASSERT((DUK_OP_PREDECR & 0x03) == 0x01);
	DUK_ASSERT((DUK_OP_POSTINCR & 0x03) == 0x02);
	DUK_ASSERT((DUK_OP_POSTDECR & 0x03) == 0x03);

#if defined(DUK_USE_FASTINT)
	if (DUK_TVAL_IS_FASTINT(tv_src)) {
		duk_int64_t x_fi, y_fi, z_fi;
		x_fi = DUK_TVAL_GET_FASTINT(tv_src);
		if (op & 0x01) {
			if (DUK_UNLIKELY(x_fi == DUK_FASTINT_MIN)) {
				goto skip_fastint;
			}
			y_fi = x_fi - 1;
		} else {
			if (DUK_UNLIKELY(x_fi == DUK_FASTINT_MAX)) {
				goto skip_fastint;
			}
			y_fi = x_fi + 1;
		}

		DUK_TVAL_SET_FASTINT(tv_src, y_fi);  /* no need for refcount update */

		z_fi = (op & 0x02) ? x_fi : y_fi;
		DUK_TVAL_SET_FASTINT_UPDREF(thr, tv_dst, z_fi);  /* side effects */
		return;
	}
 skip_fastint:
#endif
	if (DUK_TVAL_IS_NUMBER(tv_src)) {
		/* Fast path for the case where the register
		 * is a number (e.g. loop counter).
		 */

		x = DUK_TVAL_GET_NUMBER(tv_src);
		if (op & 0x01) {
			y = x - 1.0;
		} else {
			y = x + 1.0;
		}

		DUK_TVAL_SET_NUMBER(tv_src, y);  /* no need for refcount update */
	} else {
		/* Preserve duk_tval pointer(s) across a potential valstack
		 * resize by converting them into offsets temporarily.
		 */
		duk_idx_t bc;
		duk_size_t off_dst;

		off_dst = (duk_size_t) ((duk_uint8_t *) tv_dst - (duk_uint8_t *) thr->valstack_bottom);
		bc = (duk_idx_t) (tv_src - thr->valstack_bottom);  /* XXX: pass index explicitly? */
		tv_src = NULL;  /* no longer referenced */

		x = duk_to_number(thr, bc);
		if (op & 0x01) {
			y = x - 1.0;
		} else {
			y = x + 1.0;
		}

		duk_push_number(thr, y);
		duk_replace(thr, bc);

		tv_dst = (duk_tval *) (void *) (((duk_uint8_t *) thr->valstack_bottom) + off_dst);
	}

	z = (op & 0x02) ? x : y;
	DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_dst, z);  /* side effects */
}

DUK_LOCAL DUK_EXEC_ALWAYS_INLINE_PERF void duk__prepost_incdec_var_helper(duk_hthread *thr, duk_small_uint_t idx_dst, duk_tval *tv_id, duk_small_uint_t op, duk_small_uint_t is_strict) {
	duk_activation *act;
	duk_double_t x, y;
	duk_hstring *name;

	/* XXX: The pre/post inc/dec for an identifier lookup is
	 * missing the important fast path where the identifier
	 * has a storage location e.g. in a scope object so that
	 * it can be updated in-place.  In particular, the case
	 * where the identifier has a storage location AND the
	 * previous value is a number should be optimized because
	 * it's side effect free.
	 */

	/* Two lowest bits of opcode are used to distinguish
	 * variants.  Bit 0 = inc(0)/dec(1), bit 1 = pre(0)/post(1).
	 */
	DUK_ASSERT((DUK_OP_PREINCV & 0x03) == 0x00);
	DUK_ASSERT((DUK_OP_PREDECV & 0x03) == 0x01);
	DUK_ASSERT((DUK_OP_POSTINCV & 0x03) == 0x02);
	DUK_ASSERT((DUK_OP_POSTDECV & 0x03) == 0x03);

	DUK_ASSERT(DUK_TVAL_IS_STRING(tv_id));
	name = DUK_TVAL_GET_STRING(tv_id);
	DUK_ASSERT(name != NULL);
	act = thr->callstack_curr;
	(void) duk_js_getvar_activation(thr, act, name, 1 /*throw*/);  /* -> [ ... val this ] */

	/* XXX: Fastint fast path would be useful here.  Also fastints
	 * now lose their fastint status in current handling which is
	 * not intuitive.
	 */

	x = duk_to_number_m2(thr);
	if (op & 0x01) {
		y = x - 1.0;
	} else {
		y = x + 1.0;
	}

	/* [... x this] */

	if (op & 0x02) {
		duk_push_number(thr, y);  /* -> [ ... x this y ] */
		DUK_ASSERT(act == thr->callstack_curr);
		duk_js_putvar_activation(thr, act, name, DUK_GET_TVAL_NEGIDX(thr, -1), is_strict);
		duk_pop_2_unsafe(thr);  /* -> [ ... x ] */
	} else {
		duk_pop_2_unsafe(thr);  /* -> [ ... ] */
		duk_push_number(thr, y);  /* -> [ ... y ] */
		DUK_ASSERT(act == thr->callstack_curr);
		duk_js_putvar_activation(thr, act, name, DUK_GET_TVAL_NEGIDX(thr, -1), is_strict);
	}

#if defined(DUK_USE_EXEC_PREFER_SIZE)
	duk_replace(thr, (duk_idx_t) idx_dst);
#else  /* DUK_USE_EXEC_PREFER_SIZE */
	DUK__REPLACE_TO_TVPTR(thr, DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst));
#endif  /* DUK_USE_EXEC_PREFER_SIZE */
}

/*
 *  Longjmp and other control flow transfer for the bytecode executor.
 *
 *  The longjmp handler can handle all longjmp types: error, yield, and
 *  resume (pseudotypes are never actually thrown).
 *
 *  Error policy for longjmp: should not ordinarily throw errors; if errors
 *  occur (e.g. due to out-of-memory) they bubble outwards rather than being
 *  handled recursively.
 */

#define DUK__LONGJMP_RESTART   0  /* state updated, restart bytecode execution */
#define DUK__LONGJMP_RETHROW   1  /* exit bytecode executor by rethrowing an error to caller */

#define DUK__RETHAND_RESTART   0  /* state updated, restart bytecode execution */
#define DUK__RETHAND_FINISHED  1  /* exit bytecode execution with return value */

/* XXX: optimize reconfig valstack operations so that resize, clamp, and setting
 * top are combined into one pass.
 */

/* Reconfigure value stack for return to an ECMAScript function at
 * callstack top (caller unwinds).
 */
DUK_LOCAL void duk__reconfig_valstack_ecma_return(duk_hthread *thr) {
	duk_activation *act;
	duk_hcompfunc *h_func;
	duk_idx_t clamp_top;

	DUK_ASSERT(thr != NULL);
	act = thr->callstack_curr;
	DUK_ASSERT(act != NULL);
	DUK_ASSERT(DUK_ACT_GET_FUNC(act) != NULL);
	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(act)));

	/* Clamp so that values at 'clamp_top' and above are wiped and won't
	 * retain reachable garbage.  Then extend to 'nregs' because we're
	 * returning to an ECMAScript function.
	 */

	h_func = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);

	thr->valstack_bottom = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + act->bottom_byteoff);
	DUK_ASSERT(act->retval_byteoff >= act->bottom_byteoff);
	clamp_top = (duk_idx_t) ((act->retval_byteoff - act->bottom_byteoff + sizeof(duk_tval)) / sizeof(duk_tval));  /* +1 = one retval */
	duk_set_top_and_wipe(thr, h_func->nregs, clamp_top);

	DUK_ASSERT((duk_uint8_t *) thr->valstack_end >= (duk_uint8_t *) thr->valstack + act->reserve_byteoff);
	thr->valstack_end = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + act->reserve_byteoff);

	/* XXX: a best effort shrink check would be OK here */
}

/* Reconfigure value stack for an ECMAScript catcher.  Use topmost catcher
 * in 'act'.
 */
DUK_LOCAL void duk__reconfig_valstack_ecma_catcher(duk_hthread *thr, duk_activation *act) {
	duk_catcher *cat;
	duk_hcompfunc *h_func;
	duk_size_t idx_bottom;
	duk_idx_t clamp_top;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(act != NULL);
	DUK_ASSERT(DUK_ACT_GET_FUNC(act) != NULL);
	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(act)));
	cat = act->cat;
	DUK_ASSERT(cat != NULL);

	h_func = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);

	thr->valstack_bottom = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + act->bottom_byteoff);
	idx_bottom = (duk_size_t) (thr->valstack_bottom - thr->valstack);
	DUK_ASSERT(cat->idx_base >= idx_bottom);
	clamp_top = (duk_idx_t) (cat->idx_base - idx_bottom + 2);  /* +2 = catcher value, catcher lj_type */
	duk_set_top_and_wipe(thr, h_func->nregs, clamp_top);

	DUK_ASSERT((duk_uint8_t *) thr->valstack_end >= (duk_uint8_t *) thr->valstack + act->reserve_byteoff);
	thr->valstack_end = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + act->reserve_byteoff);

	/* XXX: a best effort shrink check would be OK here */
}

/* Set catcher regs: idx_base+0 = value, idx_base+1 = lj_type.
 * No side effects.
 */
DUK_LOCAL void duk__set_catcher_regs_norz(duk_hthread *thr, duk_catcher *cat, duk_tval *tv_val_unstable, duk_small_uint_t lj_type) {
	duk_tval *tv1;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(tv_val_unstable != NULL);

	tv1 = thr->valstack + cat->idx_base;
	DUK_ASSERT(tv1 < thr->valstack_top);
	DUK_TVAL_SET_TVAL_UPDREF_NORZ(thr, tv1, tv_val_unstable);

	tv1++;
	DUK_ASSERT(tv1 == thr->valstack + cat->idx_base + 1);
	DUK_ASSERT(tv1 < thr->valstack_top);
	DUK_TVAL_SET_U32_UPDREF_NORZ(thr, tv1, (duk_uint32_t) lj_type);
}

DUK_LOCAL void duk__handle_catch_part1(duk_hthread *thr, duk_tval *tv_val_unstable, duk_small_uint_t lj_type, volatile duk_bool_t *out_delayed_catch_setup) {
	duk_activation *act;
	duk_catcher *cat;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(tv_val_unstable != NULL);

	act = thr->callstack_curr;
	DUK_ASSERT(act != NULL);
	DUK_DD(DUK_DDPRINT("handle catch, part 1; act=%!A, cat=%!C", act, act->cat));

	DUK_ASSERT(act->cat != NULL);
	DUK_ASSERT(DUK_CAT_GET_TYPE(act->cat) == DUK_CAT_TYPE_TCF);

	/* The part1/part2 split could also be made here at the very top
	 * of catch handling.  Value stack would be reconfigured inside
	 * part2's protection.  Value stack reconfiguration should be free
	 * of allocs, however.
	 */

	duk__set_catcher_regs_norz(thr, act->cat, tv_val_unstable, lj_type);

	DUK_ASSERT(thr->callstack_top >= 1);
	DUK_ASSERT(thr->callstack_curr != NULL);
	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL);
	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)));

	DUK_ASSERT(thr->callstack_top >= 1);
	DUK_ASSERT(act == thr->callstack_curr);
	DUK_ASSERT(act != NULL);
	duk__reconfig_valstack_ecma_catcher(thr, act);

	DUK_ASSERT(thr->callstack_top >= 1);
	DUK_ASSERT(act == thr->callstack_curr);
	DUK_ASSERT(act != NULL);
	cat = act->cat;
	DUK_ASSERT(cat != NULL);

	act->curr_pc = cat->pc_base + 0;  /* +0 = catch */

	/*
	 *  If the catch block has an automatic catch variable binding,
	 *  we need to create a lexical environment for it which requires
	 *  allocations.  Move out of "error handling state" before the
	 *  allocations to avoid e.g. out-of-memory errors (leading to
	 *  GH-2022 or similar).
	 */

	if (DUK_CAT_HAS_CATCH_BINDING_ENABLED(cat)) {
		DUK_DDD(DUK_DDDPRINT("catcher has an automatic catch binding, handle in part 2"));
		*out_delayed_catch_setup = 1;
	} else {
		DUK_DDD(DUK_DDDPRINT("catcher has no catch binding"));
	}

	DUK_CAT_CLEAR_CATCH_ENABLED(cat);
}

DUK_LOCAL void duk__handle_catch_part2(duk_hthread *thr) {
	duk_activation *act;
	duk_catcher *cat;
	duk_hdecenv *new_env;

	DUK_ASSERT(thr != NULL);

	act = thr->callstack_curr;
	DUK_ASSERT(act != NULL);
	DUK_DD(DUK_DDPRINT("handle catch, part 2; act=%!A, cat=%!C", act, act->cat));

	DUK_ASSERT(act->cat != NULL);
	cat = act->cat;
	DUK_ASSERT(cat != NULL);
	DUK_ASSERT(DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_TCF);
	DUK_ASSERT(DUK_CAT_HAS_CATCH_BINDING_ENABLED(cat));
	DUK_ASSERT(thr->valstack + cat->idx_base < thr->valstack_top);

	/*
	 *  Create lexical environment for the catch clause, containing
	 *  a binding for the caught value.
	 *
	 *  The binding is mutable (= writable) but not deletable.
	 *  Step 4 for the catch production in E5 Section 12.14;
	 *  no value is given for CreateMutableBinding 'D' argument,
	 *  which implies the binding is not deletable.
	 */

	if (act->lex_env == NULL) {
		DUK_ASSERT(act->var_env == NULL);
		DUK_DDD(DUK_DDDPRINT("delayed environment initialization"));

		duk_js_init_activation_environment_records_delayed(thr, act);
		DUK_ASSERT(act == thr->callstack_curr);
		DUK_ASSERT(act != NULL);
	}
	DUK_ASSERT(act->lex_env != NULL);
	DUK_ASSERT(act->var_env != NULL);
	DUK_ASSERT(DUK_ACT_GET_FUNC(act) != NULL);

	new_env = duk_hdecenv_alloc(thr,
	                            DUK_HOBJECT_FLAG_EXTENSIBLE |
	                            DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV));
	DUK_ASSERT(new_env != NULL);
	duk_push_hobject(thr, (duk_hobject *) new_env);
	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) new_env) == NULL);
	DUK_DDD(DUK_DDDPRINT("new_env allocated: %!iO", (duk_heaphdr *) new_env));

	/* Note: currently the catch binding is handled without a register
	 * binding because we don't support dynamic register bindings (they
	 * must be fixed for an entire function).  So, there is no need to
	 * record regbases etc.
	 */

	/* [ ...env ] */

	DUK_ASSERT(cat->h_varname != NULL);
	duk_push_hstring(thr, cat->h_varname);
	DUK_ASSERT(thr->valstack + cat->idx_base < thr->valstack_top);
	duk_push_tval(thr, thr->valstack + cat->idx_base);
	duk_xdef_prop(thr, -3, DUK_PROPDESC_FLAGS_W);  /* writable, not configurable */

	/* [ ... env ] */

	DUK_ASSERT(act == thr->callstack_curr);
	DUK_ASSERT(act != NULL);
	DUK_HOBJECT_SET_PROTOTYPE(thr->heap, (duk_hobject *) new_env, act->lex_env);
	act->lex_env = (duk_hobject *) new_env;
	DUK_HOBJECT_INCREF(thr, (duk_hobject *) new_env);  /* reachable through activation */
	/* Net refcount change to act->lex_env is 0: incref for new_env's
	 * prototype, decref for act->lex_env overwrite.
	 */

	DUK_CAT_SET_LEXENV_ACTIVE(cat);

	duk_pop_unsafe(thr);

	DUK_DDD(DUK_DDDPRINT("new_env finished: %!iO", (duk_heaphdr *) new_env));
}

DUK_LOCAL void duk__handle_finally(duk_hthread *thr, duk_tval *tv_val_unstable, duk_small_uint_t lj_type) {
	duk_activation *act;
	duk_catcher *cat;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(tv_val_unstable != NULL);

	act = thr->callstack_curr;
	DUK_ASSERT(act != NULL);
	DUK_ASSERT(act->cat != NULL);
	DUK_ASSERT(DUK_CAT_GET_TYPE(act->cat) == DUK_CAT_TYPE_TCF);

	duk__set_catcher_regs_norz(thr, act->cat, tv_val_unstable, lj_type);

	DUK_ASSERT(thr->callstack_top >= 1);
	DUK_ASSERT(thr->callstack_curr != NULL);
	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL);
	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)));

	DUK_ASSERT(thr->callstack_top >= 1);
	DUK_ASSERT(act == thr->callstack_curr);
	DUK_ASSERT(act != NULL);
	duk__reconfig_valstack_ecma_catcher(thr, act);

	DUK_ASSERT(thr->callstack_top >= 1);
	DUK_ASSERT(act == thr->callstack_curr);
	DUK_ASSERT(act != NULL);
	cat = act->cat;
	DUK_ASSERT(cat != NULL);

	act->curr_pc = cat->pc_base + 1;  /* +1 = finally */

	DUK_CAT_CLEAR_FINALLY_ENABLED(cat);
}

DUK_LOCAL void duk__handle_label(duk_hthread *thr, duk_small_uint_t lj_type) {
	duk_activation *act;
	duk_catcher *cat;

	DUK_ASSERT(thr != NULL);

	DUK_ASSERT(thr->callstack_top >= 1);
	act = thr->callstack_curr;
	DUK_ASSERT(act != NULL);
	DUK_ASSERT(DUK_ACT_GET_FUNC(act) != NULL);
	DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(DUK_ACT_GET_FUNC(act)));

	/* +0 = break, +1 = continue */
	cat = act->cat;
	DUK_ASSERT(cat != NULL);
	DUK_ASSERT(DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_LABEL);

	act->curr_pc = cat->pc_base + (lj_type == DUK_LJ_TYPE_CONTINUE ? 1 : 0);

	/* valstack should not need changes */
#if defined(DUK_USE_ASSERTIONS)
	DUK_ASSERT(thr->callstack_top >= 1);
	DUK_ASSERT(act == thr->callstack_curr);
	DUK_ASSERT(act != NULL);
	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) ==
	           (duk_size_t) ((duk_hcompfunc *) DUK_ACT_GET_FUNC(act))->nregs);
#endif
}

/* Called for handling both a longjmp() with type DUK_LJ_TYPE_YIELD and
 * when a RETURN opcode terminates a thread and yields to the resumer.
 * Caller unwinds so that top of callstack is the activation we return to.
 */
#if defined(DUK_USE_COROUTINE_SUPPORT)
DUK_LOCAL void duk__handle_yield(duk_hthread *thr, duk_hthread *resumer, duk_tval *tv_val_unstable) {
	duk_activation *act_resumer;
	duk_tval *tv1;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(resumer != NULL);
	DUK_ASSERT(tv_val_unstable != NULL);
	act_resumer = resumer->callstack_curr;
	DUK_ASSERT(act_resumer != NULL);
	DUK_ASSERT(DUK_ACT_GET_FUNC(act_resumer) != NULL);
	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(act_resumer)));  /* resume caller must be an ECMAScript func */

	tv1 = (duk_tval *) (void *) ((duk_uint8_t *) resumer->valstack + act_resumer->retval_byteoff);  /* return value from Duktape.Thread.resume() */
	DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv_val_unstable);  /* side effects */  /* XXX: avoid side effects */

	duk__reconfig_valstack_ecma_return(resumer);

	/* caller must change active thread, and set thr->resumer to NULL */
}
#endif  /* DUK_USE_COROUTINE_SUPPORT */

DUK_LOCAL duk_small_uint_t duk__handle_longjmp(duk_hthread *thr, duk_activation *entry_act, volatile duk_bool_t *out_delayed_catch_setup) {
	duk_small_uint_t retval = DUK__LONGJMP_RESTART;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(entry_act != NULL);

	/* 'thr' is the current thread, as no-one resumes except us and we
	 * switch 'thr' in that case.
	 */
	DUK_ASSERT(thr == thr->heap->curr_thread);

	/*
	 *  (Re)try handling the longjmp.
	 *
	 *  A longjmp handler may convert the longjmp to a different type and
	 *  "virtually" rethrow by goto'ing to 'check_longjmp'.  Before the goto,
	 *  the following must be updated:
	 *    - the heap 'lj' state
	 *    - 'thr' must reflect the "throwing" thread
	 */

 check_longjmp:

	DUK_DD(DUK_DDPRINT("handling longjmp: type=%ld, value1=%!T, value2=%!T, iserror=%ld, top=%ld",
	                   (long) thr->heap->lj.type,
	                   (duk_tval *) &thr->heap->lj.value1,
	                   (duk_tval *) &thr->heap->lj.value2,
	                   (long) thr->heap->lj.iserror,
			   (long) duk_get_top(thr)));

	switch (thr->heap->lj.type) {

#if defined(DUK_USE_COROUTINE_SUPPORT)
	case DUK_LJ_TYPE_RESUME: {
		/*
		 *  Note: lj.value1 is 'value', lj.value2 is 'resumee'.
		 *  This differs from YIELD.
		 */

		duk_tval *tv;
		duk_tval *tv2;
		duk_hthread *resumee;

		/* duk_bi_duk_object_yield() and duk_bi_duk_object_resume() ensure all of these are met */

		DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);                                                         /* unchanged by Duktape.Thread.resume() */
		DUK_ASSERT(thr->callstack_top >= 2);                                                                         /* ECMAScript activation + Duktape.Thread.resume() activation */
		DUK_ASSERT(thr->callstack_curr != NULL);
		DUK_ASSERT(thr->callstack_curr->parent != NULL);
		DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL &&
		           DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)) &&
		           ((duk_hnatfunc *) DUK_ACT_GET_FUNC(thr->callstack_curr))->func == duk_bi_thread_resume);

		tv = &thr->heap->lj.value2;  /* resumee */
		DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv));
		DUK_ASSERT(DUK_TVAL_GET_OBJECT(tv) != NULL);
		DUK_ASSERT(DUK_HOBJECT_IS_THREAD(DUK_TVAL_GET_OBJECT(tv)));
		resumee = (duk_hthread *) DUK_TVAL_GET_OBJECT(tv);

		DUK_ASSERT(resumee != NULL);
		DUK_ASSERT(resumee->resumer == NULL);
		DUK_ASSERT(resumee->state == DUK_HTHREAD_STATE_INACTIVE ||
		           resumee->state == DUK_HTHREAD_STATE_YIELDED);                                                     /* checked by Duktape.Thread.resume() */
		DUK_ASSERT(resumee->state != DUK_HTHREAD_STATE_YIELDED ||
		           resumee->callstack_top >= 2);                                                                     /* YIELDED: ECMAScript activation + Duktape.Thread.yield() activation */
		DUK_ASSERT(resumee->state != DUK_HTHREAD_STATE_YIELDED ||
		           (DUK_ACT_GET_FUNC(resumee->callstack_curr) != NULL &&
		            DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(resumee->callstack_curr)) &&
		            ((duk_hnatfunc *) DUK_ACT_GET_FUNC(resumee->callstack_curr))->func == duk_bi_thread_yield));
		DUK_ASSERT(resumee->state != DUK_HTHREAD_STATE_INACTIVE ||
		           resumee->callstack_top == 0);                                                                     /* INACTIVE: no activation, single function value on valstack */

		if (thr->heap->lj.iserror) {
			/*
			 *  Throw the error in the resumed thread's context; the
			 *  error value is pushed onto the resumee valstack.
			 *
			 *  Note: the callstack of the target may empty in this case
			 *  too (i.e. the target thread has never been resumed).  The
			 *  value stack will contain the initial function in that case,
			 *  which we simply ignore.
			 */

			DUK_ASSERT(resumee->resumer == NULL);
			resumee->resumer = thr;
			DUK_HTHREAD_INCREF(thr, thr);
			resumee->state = DUK_HTHREAD_STATE_RUNNING;
			thr->state = DUK_HTHREAD_STATE_RESUMED;
			DUK_HEAP_SWITCH_THREAD(thr->heap, resumee);
			thr = resumee;

			thr->heap->lj.type = DUK_LJ_TYPE_THROW;

			/* thr->heap->lj.value1 is already the value to throw */
			/* thr->heap->lj.value2 is 'thread', will be wiped out at the end */

			DUK_ASSERT(thr->heap->lj.iserror);  /* already set */

			DUK_DD(DUK_DDPRINT("-> resume with an error, converted to a throw in the resumee, propagate"));
			goto check_longjmp;
		} else if (resumee->state == DUK_HTHREAD_STATE_YIELDED) {
			/* Unwind previous Duktape.Thread.yield() call.  The
			 * activation remaining must always be an ECMAScript
			 * call now (yield() accepts calls from ECMAScript
			 * only).
			 */
			duk_activation *act_resumee;

			DUK_ASSERT(resumee->callstack_top >= 2);
			act_resumee = resumee->callstack_curr;  /* Duktape.Thread.yield() */
			DUK_ASSERT(act_resumee != NULL);
			act_resumee = act_resumee->parent;      /* ECMAScript call site for yield() */
			DUK_ASSERT(act_resumee != NULL);

			tv = (duk_tval *) (void *) ((duk_uint8_t *) resumee->valstack + act_resumee->retval_byteoff);  /* return value from Duktape.Thread.yield() */
			DUK_ASSERT(tv >= resumee->valstack && tv < resumee->valstack_top);
			tv2 = &thr->heap->lj.value1;
			DUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv2);  /* side effects */  /* XXX: avoid side effects */

			duk_hthread_activation_unwind_norz(resumee);  /* unwind to 'yield' caller */
			/* no need to unwind catch stack */

			duk__reconfig_valstack_ecma_return(resumee);

			DUK_ASSERT(resumee->resumer == NULL);
			resumee->resumer = thr;
			DUK_HTHREAD_INCREF(thr, thr);
			resumee->state = DUK_HTHREAD_STATE_RUNNING;
			thr->state = DUK_HTHREAD_STATE_RESUMED;
			DUK_HEAP_SWITCH_THREAD(thr->heap, resumee);
#if 0
			thr = resumee;  /* not needed, as we exit right away */
#endif
			DUK_DD(DUK_DDPRINT("-> resume with a value, restart execution in resumee"));
			retval = DUK__LONGJMP_RESTART;
			goto wipe_and_return;
		} else {
			/* Initial resume call. */
			duk_small_uint_t call_flags;
			duk_int_t setup_rc;

			/* resumee: [... initial_func]  (currently actually: [initial_func]) */

			duk_push_undefined(resumee);
			tv = &thr->heap->lj.value1;
			duk_push_tval(resumee, tv);

			/* resumee: [... initial_func undefined(= this) resume_value ] */

			call_flags = DUK_CALL_FLAG_ALLOW_ECMATOECMA;  /* not tailcall, ecma-to-ecma (assumed to succeed) */

			setup_rc = duk_handle_call_unprotected_nargs(resumee, 1 /*nargs*/, call_flags);
			if (setup_rc == 0) {
				/* This shouldn't happen; Duktape.Thread.resume()
				 * should make sure of that.  If it does happen
				 * this internal error will propagate out of the
				 * executor which can be quite misleading.
				 */
				DUK_ERROR_INTERNAL(thr);
				DUK_WO_NORETURN(return 0;);
			}

			DUK_ASSERT(resumee->resumer == NULL);
			resumee->resumer = thr;
			DUK_HTHREAD_INCREF(thr, thr);
			resumee->state = DUK_HTHREAD_STATE_RUNNING;
			thr->state = DUK_HTHREAD_STATE_RESUMED;
			DUK_HEAP_SWITCH_THREAD(thr->heap, resumee);
#if 0
			thr = resumee;  /* not needed, as we exit right away */
#endif
			DUK_DD(DUK_DDPRINT("-> resume with a value, restart execution in resumee"));
			retval = DUK__LONGJMP_RESTART;
			goto wipe_and_return;
		}
		DUK_UNREACHABLE();
		break;  /* never here */
	}

	case DUK_LJ_TYPE_YIELD: {
		/*
		 *  Currently only allowed only if yielding thread has only
		 *  ECMAScript activations (except for the Duktape.Thread.yield()
		 *  call at the callstack top) and none of them constructor
		 *  calls.
		 *
		 *  This excludes the 'entry' thread which will always have
		 *  a preventcount > 0.
		 */

		duk_hthread *resumer;

		/* duk_bi_duk_object_yield() and duk_bi_duk_object_resume() ensure all of these are met */

#if 0  /* entry_thread not available for assert */
		DUK_ASSERT(thr != entry_thread);                                                                             /* Duktape.Thread.yield() should prevent */
#endif
		DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);                                                         /* unchanged from Duktape.Thread.yield() */
		DUK_ASSERT(thr->callstack_top >= 2);                                                                         /* ECMAScript activation + Duktape.Thread.yield() activation */
		DUK_ASSERT(thr->callstack_curr != NULL);
		DUK_ASSERT(thr->callstack_curr->parent != NULL);
		DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL &&
		           DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)) &&
		           ((duk_hnatfunc *) DUK_ACT_GET_FUNC(thr->callstack_curr))->func == duk_bi_thread_yield);
		DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr->parent) != NULL &&
		           DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr->parent)));                              /* an ECMAScript function */

		resumer = thr->resumer;

		DUK_ASSERT(resumer != NULL);
		DUK_ASSERT(resumer->state == DUK_HTHREAD_STATE_RESUMED);                                                     /* written by a previous RESUME handling */
		DUK_ASSERT(resumer->callstack_top >= 2);                                                                     /* ECMAScript activation + Duktape.Thread.resume() activation */
		DUK_ASSERT(resumer->callstack_curr != NULL);
		DUK_ASSERT(resumer->callstack_curr->parent != NULL);
		DUK_ASSERT(DUK_ACT_GET_FUNC(resumer->callstack_curr) != NULL &&
		           DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(resumer->callstack_curr)) &&
		           ((duk_hnatfunc *) DUK_ACT_GET_FUNC(resumer->callstack_curr))->func == duk_bi_thread_resume);
		DUK_ASSERT(DUK_ACT_GET_FUNC(resumer->callstack_curr->parent) != NULL &&
		           DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(resumer->callstack_curr->parent)));                            /* an ECMAScript function */

		if (thr->heap->lj.iserror) {
			thr->state = DUK_HTHREAD_STATE_YIELDED;
			thr->resumer = NULL;
			DUK_HTHREAD_DECREF_NORZ(thr, resumer);
			resumer->state = DUK_HTHREAD_STATE_RUNNING;
			DUK_HEAP_SWITCH_THREAD(thr->heap, resumer);
			thr = resumer;

			thr->heap->lj.type = DUK_LJ_TYPE_THROW;
			/* lj.value1 is already set */
			DUK_ASSERT(thr->heap->lj.iserror);  /* already set */

			DUK_DD(DUK_DDPRINT("-> yield an error, converted to a throw in the resumer, propagate"));
			goto check_longjmp;
		} else {
			duk_hthread_activation_unwind_norz(resumer);
			duk__handle_yield(thr, resumer, &thr->heap->lj.value1);

			thr->state = DUK_HTHREAD_STATE_YIELDED;
			thr->resumer = NULL;
			DUK_HTHREAD_DECREF_NORZ(thr, resumer);
			resumer->state = DUK_HTHREAD_STATE_RUNNING;
			DUK_HEAP_SWITCH_THREAD(thr->heap, resumer);
#if 0
			thr = resumer;  /* not needed, as we exit right away */
#endif

			DUK_DD(DUK_DDPRINT("-> yield a value, restart execution in resumer"));
			retval = DUK__LONGJMP_RESTART;
			goto wipe_and_return;
		}
		DUK_UNREACHABLE();
		break;  /* never here */
	}
#endif  /* DUK_USE_COROUTINE_SUPPORT */

	case DUK_LJ_TYPE_THROW: {
		/*
		 *  Three possible outcomes:
		 *    * A try or finally catcher is found => resume there.
		 *      (or)
		 *    * The error propagates to the bytecode executor entry
		 *      level (and we're in the entry thread) => rethrow
		 *      with a new longjmp(), after restoring the previous
		 *      catchpoint.
		 *    * The error is not caught in the current thread, so
		 *      the thread finishes with an error.  This works like
		 *      a yielded error, except that the thread is finished
		 *      and can no longer be resumed.  (There is always a
		 *      resumer in this case.)
		 *
		 *  Note: until we hit the entry level, there can only be
		 *  ECMAScript activations.
		 */

		duk_activation *act;
		duk_catcher *cat;
		duk_hthread *resumer;

		for (;;) {
			act = thr->callstack_curr;
			if (act == NULL) {
				break;
			}

			for (;;) {
				cat = act->cat;
				if (cat == NULL) {
					break;
				}

				if (DUK_CAT_HAS_CATCH_ENABLED(cat)) {
					DUK_ASSERT(DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_TCF);

					DUK_DDD(DUK_DDDPRINT("before catch part 1: thr=%p, act=%p, cat=%p",
					                     (void *) thr, (void *) act, (void *) act->cat));
					duk__handle_catch_part1(thr,
					                        &thr->heap->lj.value1,
					                        DUK_LJ_TYPE_THROW,
							        out_delayed_catch_setup);

					DUK_DD(DUK_DDPRINT("-> throw caught by a 'catch' clause, restart execution"));
					retval = DUK__LONGJMP_RESTART;
					goto wipe_and_return;
				}

				if (DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
					DUK_ASSERT(DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_TCF);
					DUK_ASSERT(!DUK_CAT_HAS_CATCH_ENABLED(cat));

					duk__handle_finally(thr,
					                    &thr->heap->lj.value1,
					                    DUK_LJ_TYPE_THROW);

					DUK_DD(DUK_DDPRINT("-> throw caught by a 'finally' clause, restart execution"));
					retval = DUK__LONGJMP_RESTART;
					goto wipe_and_return;
				}

				duk_hthread_catcher_unwind_norz(thr, act);
			}

			if (act == entry_act) {
				/* Not caught by anything before entry level; rethrow and let the
				 * final catcher finish unwinding (esp. value stack).
				 */
				DUK_D(DUK_DPRINT("-> throw propagated up to entry level, rethrow and exit bytecode executor"));
				retval = DUK__LONGJMP_RETHROW;
				goto just_return;
			}

			duk_hthread_activation_unwind_norz(thr);
		}

		DUK_DD(DUK_DDPRINT("-> throw not caught by current thread, yield error to resumer and recheck longjmp"));

		/* Not caught by current thread, thread terminates (yield error to resumer);
		 * note that this may cause a cascade if the resumer terminates with an uncaught
		 * exception etc (this is OK, but needs careful testing).
		 */

		DUK_ASSERT(thr->resumer != NULL);
		DUK_ASSERT(thr->resumer->callstack_top >= 2);  /* ECMAScript activation + Duktape.Thread.resume() activation */
		DUK_ASSERT(thr->resumer->callstack_curr != NULL);
		DUK_ASSERT(thr->resumer->callstack_curr->parent != NULL);
		DUK_ASSERT(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr->parent) != NULL &&
		           DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr->parent)));  /* an ECMAScript function */

		resumer = thr->resumer;

		/* reset longjmp */

		DUK_ASSERT(thr->heap->lj.type == DUK_LJ_TYPE_THROW);  /* already set */
		/* lj.value1 already set */

		duk_hthread_terminate(thr);  /* updates thread state, minimizes its allocations */
		DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_TERMINATED);

		thr->resumer = NULL;
		DUK_HTHREAD_DECREF_NORZ(thr, resumer);
		resumer->state = DUK_HTHREAD_STATE_RUNNING;
		DUK_HEAP_SWITCH_THREAD(thr->heap, resumer);
		thr = resumer;
		goto check_longjmp;
	}

	case DUK_LJ_TYPE_BREAK:  /* pseudotypes, not used in actual longjmps */
	case DUK_LJ_TYPE_CONTINUE:
	case DUK_LJ_TYPE_RETURN:
	case DUK_LJ_TYPE_NORMAL:
	default: {
		/* should never happen, but be robust */
		DUK_D(DUK_DPRINT("caught unknown longjmp type %ld, treat as internal error", (long) thr->heap->lj.type));
		goto convert_to_internal_error;
	}

	}  /* end switch */

	DUK_UNREACHABLE();

 wipe_and_return:
	DUK_DD(DUK_DDPRINT("handling longjmp done, wipe-and-return, top=%ld",
	                   (long) duk_get_top(thr)));
	thr->heap->lj.type = DUK_LJ_TYPE_UNKNOWN;
	thr->heap->lj.iserror = 0;

	DUK_TVAL_SET_UNDEFINED_UPDREF(thr, &thr->heap->lj.value1);  /* side effects */
	DUK_TVAL_SET_UNDEFINED_UPDREF(thr, &thr->heap->lj.value2);  /* side effects */

	DUK_GC_TORTURE(thr->heap);

 just_return:
	return retval;

 convert_to_internal_error:
	/* This could also be thrown internally (set the error, goto check_longjmp),
	 * but it's better for internal errors to bubble outwards so that we won't
	 * infinite loop in this catchpoint.
	 */
	DUK_ERROR_INTERNAL(thr);
	DUK_WO_NORETURN(return 0;);
}

/* Handle a BREAK/CONTINUE opcode.  Avoid using longjmp() for BREAK/CONTINUE
 * handling because it has a measurable performance impact in ordinary
 * environments and an extreme impact in Emscripten (GH-342).
 */
DUK_LOCAL DUK_EXEC_NOINLINE_PERF void duk__handle_break_or_continue(duk_hthread *thr,
                                                                    duk_uint_t label_id,
                                                                    duk_small_uint_t lj_type) {
	duk_activation *act;
	duk_catcher *cat;

	DUK_ASSERT(thr != NULL);

	/* Find a matching label catcher or 'finally' catcher in
	 * the same function, unwinding catchers as we go.
	 *
	 * A label catcher must always exist and will match unless
	 * a 'finally' captures the break/continue first.  It is the
	 * compiler's responsibility to ensure that labels are used
	 * correctly.
	 */

	act = thr->callstack_curr;
	DUK_ASSERT(act != NULL);

	for (;;) {
		cat = act->cat;
		if (cat == NULL) {
			break;
		}

		DUK_DDD(DUK_DDDPRINT("considering catcher %p: type=%ld label=%ld",
		                     (void *) cat,
		                     (long) DUK_CAT_GET_TYPE(cat),
		                     (long) DUK_CAT_GET_LABEL(cat)));

		/* XXX: bit mask test; FINALLY <-> TCF, single bit mask would suffice? */

		if (DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_TCF &&
		    DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
			duk_tval tv_tmp;

			DUK_TVAL_SET_U32(&tv_tmp, (duk_uint32_t) label_id);
			duk__handle_finally(thr, &tv_tmp, lj_type);

			DUK_DD(DUK_DDPRINT("-> break/continue caught by 'finally', restart execution"));
			return;
		}
		if (DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_LABEL &&
		    (duk_uint_t) DUK_CAT_GET_LABEL(cat) == label_id) {
			duk__handle_label(thr, lj_type);

			DUK_DD(DUK_DDPRINT("-> break/continue caught by a label catcher (in the same function), restart execution"));
			return;
		}

		duk_hthread_catcher_unwind_norz(thr, act);
	}

	/* Should never happen, but be robust. */
	DUK_D(DUK_DPRINT("-> break/continue not caught by anything in the current function (should never happen), throw internal error"));
	DUK_ERROR_INTERNAL(thr);
	DUK_WO_NORETURN(return;);
}

/* Handle a RETURN opcode.  Avoid using longjmp() for return handling because
 * it has a measurable performance impact in ordinary environments and an extreme
 * impact in Emscripten (GH-342).  Return value is on value stack top.
 */
DUK_LOCAL duk_small_uint_t duk__handle_return(duk_hthread *thr, duk_activation *entry_act) {
	duk_tval *tv1;
	duk_tval *tv2;
#if defined(DUK_USE_COROUTINE_SUPPORT)
	duk_hthread *resumer;
#endif
	duk_activation *act;
	duk_catcher *cat;

	/* We can directly access value stack here. */

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(entry_act != NULL);
	DUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);
	tv1 = thr->valstack_top - 1;
	DUK_TVAL_CHKFAST_INPLACE_FAST(tv1);  /* fastint downgrade check for return values */

	/*
	 *  Four possible outcomes:
	 *
	 *    1. A 'finally' in the same function catches the 'return'.
	 *       It may continue to propagate when 'finally' is finished,
	 *       or it may be neutralized by 'finally' (both handled by
	 *       ENDFIN).
	 *
	 *    2. The return happens at the entry level of the bytecode
	 *       executor, so return from the executor (in C stack).
	 *
	 *    3. There is a calling (ECMAScript) activation in the call
	 *       stack => return to it, in the same executor instance.
	 *
	 *    4. There is no calling activation, and the thread is
	 *       terminated.  There is always a resumer in this case,
	 *       which gets the return value similarly to a 'yield'
	 *       (except that the current thread can no longer be
	 *       resumed).
	 */

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(thr->callstack_top >= 1);

	act = thr->callstack_curr;
	DUK_ASSERT(act != NULL);

	for (;;) {
		cat = act->cat;
		if (cat == NULL) {
			break;
		}

		if (DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_TCF &&
		    DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
			DUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);
			duk__handle_finally(thr, thr->valstack_top - 1, DUK_LJ_TYPE_RETURN);

			DUK_DD(DUK_DDPRINT("-> return caught by 'finally', restart execution"));
			return DUK__RETHAND_RESTART;
		}

		duk_hthread_catcher_unwind_norz(thr, act);
	}

	if (act == entry_act) {
		/* Return to the bytecode executor caller who will unwind stacks
		 * and handle constructor post-processing.
		 * Return value is already on the stack top: [ ... retval ].
		 */

		DUK_DDD(DUK_DDDPRINT("-> return propagated up to entry level, exit bytecode executor"));
		return DUK__RETHAND_FINISHED;
	}

	if (thr->callstack_top >= 2) {
		/* There is a caller; it MUST be an ECMAScript caller (otherwise it would
		 * match entry_act check).
		 */
		DUK_DDD(DUK_DDDPRINT("return to ECMAScript caller, retval_byteoff=%ld, lj_value1=%!T",
		                     (long) (thr->callstack_curr->parent->retval_byteoff),
		                     (duk_tval *) &thr->heap->lj.value1));

		DUK_ASSERT(thr->callstack_curr != NULL);
		DUK_ASSERT(thr->callstack_curr->parent != NULL);
		DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr->parent)));   /* must be ECMAScript */

#if defined(DUK_USE_ES6_PROXY)
		if (thr->callstack_curr->flags & (DUK_ACT_FLAG_CONSTRUCT | DUK_ACT_FLAG_CONSTRUCT_PROXY)) {
			duk_call_construct_postprocess(thr, thr->callstack_curr->flags & DUK_ACT_FLAG_CONSTRUCT_PROXY);  /* side effects */
		}
#else
		if (thr->callstack_curr->flags & DUK_ACT_FLAG_CONSTRUCT) {
			duk_call_construct_postprocess(thr, 0);  /* side effects */
		}
#endif

		tv1 = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + thr->callstack_curr->parent->retval_byteoff);
		DUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);
		tv2 = thr->valstack_top - 1;
		DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2);  /* side effects */

		/* Catch stack unwind happens inline in callstack unwind. */
		duk_hthread_activation_unwind_norz(thr);

		duk__reconfig_valstack_ecma_return(thr);

		DUK_DD(DUK_DDPRINT("-> return not intercepted, restart execution in caller"));
		return DUK__RETHAND_RESTART;
	}

#if defined(DUK_USE_COROUTINE_SUPPORT)
	DUK_DD(DUK_DDPRINT("no calling activation, thread finishes (similar to yield)"));

	DUK_ASSERT(thr->resumer != NULL);
	DUK_ASSERT(thr->resumer->callstack_top >= 2);  /* ECMAScript activation + Duktape.Thread.resume() activation */
	DUK_ASSERT(thr->resumer->callstack_curr != NULL);
	DUK_ASSERT(thr->resumer->callstack_curr->parent != NULL);
	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr) != NULL &&
			DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr)) &&
			((duk_hnatfunc *) DUK_ACT_GET_FUNC(thr->resumer->callstack_curr))->func == duk_bi_thread_resume);  /* Duktape.Thread.resume() */
	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr->parent) != NULL &&
			DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr->parent)));  /* an ECMAScript function */
	DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);
	DUK_ASSERT(thr->resumer->state == DUK_HTHREAD_STATE_RESUMED);

	resumer = thr->resumer;

	/* Share yield longjmp handler.
	 *
	 * This sequence of steps is a bit fragile (see GH-1845):
	 * - We need the return value from 'thr' (resumed thread) value stack.
	 *   The termination unwinds its value stack, losing the value.
	 * - We need a refcounted reference for 'thr', which may only exist
	 *   in the caller value stack.  We can't unwind or reconfigure the
	 *   caller's value stack without potentially freeing 'thr'.
	 *
	 * Current approach is to capture the 'thr' return value and store
	 * a reference to 'thr' in the caller value stack temporarily.  This
	 * keeps 'thr' reachable until final yield/return handling which
	 * removes the references atomatically.
	 */

	DUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);
	duk_hthread_activation_unwind_norz(resumer);  /* May remove last reference to 'thr', but is NORZ. */
	duk_push_tval(resumer, thr->valstack_top - 1);  /* Capture return value, side effect free. */
	duk_push_hthread(resumer, thr);  /* Make 'thr' reachable again, before side effects. */

	duk_hthread_terminate(thr);  /* Updates thread state, minimizes its allocations. */
	thr->resumer = NULL;
	DUK_HTHREAD_DECREF(thr, resumer);
	DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_TERMINATED);

	resumer->state = DUK_HTHREAD_STATE_RUNNING;
	DUK_HEAP_SWITCH_THREAD(thr->heap, resumer);

	DUK_ASSERT(resumer->valstack_top - 2 >= resumer->valstack_bottom);
	duk__handle_yield(thr, resumer, resumer->valstack_top - 2);
	thr = NULL;  /* 'thr' invalidated by call */

#if 0
	thr = resumer;  /* not needed */
#endif

	DUK_DD(DUK_DDPRINT("-> return not caught, thread terminated; handle like yield, restart execution in resumer"));
	return DUK__RETHAND_RESTART;
#else
	/* Without coroutine support this case should never happen. */
	DUK_ERROR_INTERNAL(thr);
	DUK_WO_NORETURN(return 0;);
#endif
}

/*
 *  Executor interrupt handling
 *
 *  The handler is called whenever the interrupt countdown reaches zero
 *  (or below).  The handler must perform whatever checks are activated,
 *  e.g. check for cumulative step count to impose an execution step
 *  limit or check for breakpoints or other debugger interaction.
 *
 *  When the actions are done, the handler must reinit the interrupt
 *  init and counter values.  The 'init' value must indicate how many
 *  bytecode instructions are executed before the next interrupt.  The
 *  counter must interface with the bytecode executor loop.  Concretely,
 *  the new init value is normally one higher than the new counter value.
 *  For instance, to execute exactly one bytecode instruction the init
 *  value is set to 1 and the counter to 0.  If an error is thrown by the
 *  interrupt handler, the counters are set to the same value (e.g. both
 *  to 0 to cause an interrupt when the next bytecode instruction is about
 *  to be executed after error handling).
 *
 *  Maintaining the init/counter value properly is important for accurate
 *  behavior.  For instance, executor step limit needs a cumulative step
 *  count which is simply computed as a sum of 'init' values.  This must
 *  work accurately even when single stepping.
 */

#if defined(DUK_USE_INTERRUPT_COUNTER)

#define DUK__INT_NOACTION    0    /* no specific action, resume normal execution */
#define DUK__INT_RESTART     1    /* must "goto restart_execution", e.g. breakpoints changed */

#if defined(DUK_USE_DEBUGGER_SUPPORT)
DUK_LOCAL void duk__interrupt_handle_debugger(duk_hthread *thr, duk_bool_t *out_immediate, duk_small_uint_t *out_interrupt_retval) {
	duk_activation *act;
	duk_breakpoint *bp;
	duk_breakpoint **bp_active;
	duk_uint_fast32_t line = 0;
	duk_bool_t process_messages;
	duk_bool_t processed_messages = 0;

	DUK_ASSERT(thr->heap->dbg_processing == 0);  /* don't re-enter e.g. during Eval */

	act = thr->callstack_curr;
	DUK_ASSERT(act != NULL);

	/* It might seem that replacing 'thr->heap' with just 'heap' below
	 * might be a good idea, but it increases code size slightly
	 * (probably due to unnecessary spilling) at least on x64.
	 */

	/*
	 *  Single opcode step check
	 */

	if (thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_ONE_OPCODE_ACTIVE) {
		DUK_D(DUK_DPRINT("PAUSE TRIGGERED by one opcode step"));
		duk_debug_set_paused(thr->heap);
	}

	/*
	 *  Breakpoint and step state checks
	 */

	if (act->flags & DUK_ACT_FLAG_BREAKPOINT_ACTIVE ||
	    (thr->heap->dbg_pause_act == thr->callstack_curr)) {
		line = duk_debug_curr_line(thr);

		if (act->prev_line != line) {
			/* Stepped?  Step out is handled by callstack unwind. */
			if ((thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_LINE_CHANGE) &&
			    (thr->heap->dbg_pause_act == thr->callstack_curr) &&
			    (line != thr->heap->dbg_pause_startline)) {
				DUK_D(DUK_DPRINT("PAUSE TRIGGERED by line change, at line %ld",
				                 (long) line));
				duk_debug_set_paused(thr->heap);
			}

			/* Check for breakpoints only on line transition.
			 * Breakpoint is triggered when we enter the target
			 * line from a different line, and the previous line
			 * was within the same function.
			 *
			 * This condition is tricky: the condition used to be
			 * that transition to -or across- the breakpoint line
			 * triggered the breakpoint.  This seems intuitively
			 * better because it handles breakpoints on lines with
			 * no emitted opcodes; but this leads to the issue
			 * described in: https://github.com/svaarala/duktape/issues/263.
			 */
			bp_active = thr->heap->dbg_breakpoints_active;
			for (;;) {
				bp = *bp_active++;
				if (bp == NULL) {
					break;
				}

				DUK_ASSERT(bp->filename != NULL);
				if (act->prev_line != bp->line && line == bp->line) {
					DUK_D(DUK_DPRINT("PAUSE TRIGGERED by breakpoint at %!O:%ld",
					                 (duk_heaphdr *) bp->filename, (long) bp->line));
					duk_debug_set_paused(thr->heap);
				}
			}
		} else {
			;
		}

		act->prev_line = (duk_uint32_t) line;
	}

	/*
	 *  Rate limit check for sending status update or peeking into
	 *  the debug transport.  Both can be expensive operations that
	 *  we don't want to do on every opcode.
	 *
	 *  Making sure the interval remains reasonable on a wide variety
	 *  of targets and bytecode is difficult without a timestamp, so
	 *  we use a Date-provided timestamp for the rate limit check.
	 *  But since it's also expensive to get a timestamp, a bytecode
	 *  counter is used to rate limit getting timestamps.
	 */

	process_messages = 0;
	if (thr->heap->dbg_state_dirty || DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap) || thr->heap->dbg_detaching) {
		/* Enter message processing loop for sending Status notifys and
		 * to finish a pending detach.
		 */
		process_messages = 1;
	}

	/* XXX: remove heap->dbg_exec_counter, use heap->inst_count_interrupt instead? */
	DUK_ASSERT(thr->interrupt_init >= 0);
	thr->heap->dbg_exec_counter += (duk_uint_t) thr->interrupt_init;
	if (thr->heap->dbg_exec_counter - thr->heap->dbg_last_counter >= DUK_HEAP_DBG_RATELIMIT_OPCODES) {
		/* Overflow of the execution counter is fine and doesn't break
		 * anything here.
		 */

		duk_double_t now, diff_last;

		thr->heap->dbg_last_counter = thr->heap->dbg_exec_counter;
		now = duk_time_get_monotonic_time(thr);

		diff_last = now - thr->heap->dbg_last_time;
		if (diff_last < 0.0 || diff_last >= (duk_double_t) DUK_HEAP_DBG_RATELIMIT_MILLISECS) {
			/* Monotonic time should not experience time jumps,
			 * but the provider may be missing and we're actually
			 * using ECMAScript time.  So, tolerate negative values
			 * so that a time jump works reasonably.
			 *
			 * Same interval is now used for status sending and
			 * peeking.
			 */

			thr->heap->dbg_last_time = now;
			thr->heap->dbg_state_dirty = 1;
			process_messages = 1;
		}
	}

	/*
	 *  Process messages and send status if necessary.
	 *
	 *  If we're paused, we'll block for new messages.  If we're not
	 *  paused, we'll process anything we can peek but won't block
	 *  for more.  Detach (and re-attach) handling is all localized
	 *  to duk_debug_process_messages() too.
	 *
	 *  Debugger writes outside the message loop may cause debugger
	 *  detach1 phase to run, after which dbg_read_cb == NULL and
	 *  dbg_detaching != 0.  The message loop will finish the detach
	 *  by running detach2 phase, so enter the message loop also when
	 *  detaching.
	 */

	if (process_messages) {
		DUK_ASSERT(thr->heap->dbg_processing == 0);
		processed_messages = duk_debug_process_messages(thr, 0 /*no_block*/);
		DUK_ASSERT(thr->heap->dbg_processing == 0);
	}

	/* Continue checked execution if there are breakpoints or we're stepping.
	 * Also use checked execution if paused flag is active - it shouldn't be
	 * because the debug message loop shouldn't terminate if it was.  Step out
	 * is handled by callstack unwind and doesn't need checked execution.
	 * Note that debugger may have detached due to error or explicit request
	 * above, so we must recheck attach status.
	 */

	if (duk_debug_is_attached(thr->heap)) {
		DUK_ASSERT(act == thr->callstack_curr);
		DUK_ASSERT(act != NULL);
		if (act->flags & DUK_ACT_FLAG_BREAKPOINT_ACTIVE ||
		    (thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_ONE_OPCODE) ||
		    ((thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_LINE_CHANGE) &&
		     thr->heap->dbg_pause_act == thr->callstack_curr) ||
		     DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap)) {
			*out_immediate = 1;
		}

		/* If we processed any debug messages breakpoints may have
		 * changed; restart execution to re-check active breakpoints.
		 */
		if (processed_messages) {
			DUK_D(DUK_DPRINT("processed debug messages, restart execution to recheck possibly changed breakpoints"));
			*out_interrupt_retval = DUK__INT_RESTART;
		} else {
			if (thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_ONE_OPCODE) {
				/* Set 'pause after one opcode' active only when we're
				 * actually just about to execute code.
				 */
				thr->heap->dbg_pause_flags |= DUK_PAUSE_FLAG_ONE_OPCODE_ACTIVE;
			}
		}
	} else {
		DUK_D(DUK_DPRINT("debugger became detached, resume normal execution"));
	}
}
#endif  /* DUK_USE_DEBUGGER_SUPPORT */

DUK_LOCAL DUK_EXEC_NOINLINE_PERF DUK_COLD duk_small_uint_t duk__executor_interrupt(duk_hthread *thr) {
	duk_int_t ctr;
	duk_activation *act;
	duk_hcompfunc *fun;
	duk_bool_t immediate = 0;
	duk_small_uint_t retval;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(thr->heap != NULL);
	DUK_ASSERT(thr->callstack_top > 0);

#if defined(DUK_USE_DEBUG)
	thr->heap->inst_count_interrupt += thr->interrupt_init;
	DUK_DD(DUK_DDPRINT("execution interrupt, counter=%ld, init=%ld, "
	                   "instruction counts: executor=%ld, interrupt=%ld",
	                   (long) thr->interrupt_counter, (long) thr->interrupt_init,
	                   (long) thr->heap->inst_count_exec, (long) thr->heap->inst_count_interrupt));
#endif

	retval = DUK__INT_NOACTION;
	ctr = DUK_HTHREAD_INTCTR_DEFAULT;

	/*
	 *  Avoid nested calls.  Concretely this happens during debugging, e.g.
	 *  when we eval() an expression.
	 *
	 *  Also don't interrupt if we're currently doing debug processing
	 *  (which can be initiated outside the bytecode executor) as this
	 *  may cause the debugger to be called recursively.  Check required
	 *  for correct operation of throw intercept and other "exotic" halting
	 * scenarios.
	 */

#if defined(DUK_USE_DEBUGGER_SUPPORT)
	if (DUK_HEAP_HAS_INTERRUPT_RUNNING(thr->heap) || thr->heap->dbg_processing) {
#else
	if (DUK_HEAP_HAS_INTERRUPT_RUNNING(thr->heap)) {
#endif
		DUK_DD(DUK_DDPRINT("nested executor interrupt, ignoring"));

		/* Set a high interrupt counter; the original executor
		 * interrupt invocation will rewrite before exiting.
		 */
		thr->interrupt_init = ctr;
		thr->interrupt_counter = ctr - 1;
		return DUK__INT_NOACTION;
	}
	DUK_HEAP_SET_INTERRUPT_RUNNING(thr->heap);

	act = thr->callstack_curr;
	DUK_ASSERT(act != NULL);

	fun = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);
	DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC((duk_hobject *) fun));

	DUK_UNREF(fun);

#if defined(DUK_USE_EXEC_TIMEOUT_CHECK)
	/*
	 *  Execution timeout check
	 */

	if (DUK_USE_EXEC_TIMEOUT_CHECK(thr->heap->heap_udata)) {
		/* Keep throwing an error whenever we get here.  The unusual values
		 * are set this way because no instruction is ever executed, we just
		 * throw an error until all try/catch/finally and other catchpoints
		 * have been exhausted.  Duktape/C code gets control at each protected
		 * call but whenever it enters back into Duktape the RangeError gets
		 * raised.  User exec timeout check must consistently indicate a timeout
		 * until we've fully bubbled out of Duktape.
		 */
		DUK_D(DUK_DPRINT("execution timeout, throwing a RangeError"));
		thr->interrupt_init = 0;
		thr->interrupt_counter = 0;
		DUK_HEAP_CLEAR_INTERRUPT_RUNNING(thr->heap);
		DUK_ERROR_RANGE(thr, "execution timeout");
		DUK_WO_NORETURN(return 0;);
	}
#endif  /* DUK_USE_EXEC_TIMEOUT_CHECK */

#if defined(DUK_USE_DEBUGGER_SUPPORT)
	if (!thr->heap->dbg_processing &&
	    (thr->heap->dbg_read_cb != NULL || thr->heap->dbg_detaching)) {
		/* Avoid recursive re-entry; enter when we're attached or
		 * detaching (to finish off the pending detach).
		 */
		duk__interrupt_handle_debugger(thr, &immediate, &retval);
		DUK_ASSERT(act == thr->callstack_curr);
	}
#endif  /* DUK_USE_DEBUGGER_SUPPORT */

	/*
	 *  Update the interrupt counter
	 */

	if (immediate) {
		/* Cause an interrupt after executing one instruction. */
		ctr = 1;
	}

	/* The counter value is one less than the init value: init value should
	 * indicate how many instructions are executed before interrupt.  To
	 * execute 1 instruction (after interrupt handler return), counter must
	 * be 0.
	 */
	DUK_ASSERT(ctr >= 1);
	thr->interrupt_init = ctr;
	thr->interrupt_counter = ctr - 1;
	DUK_HEAP_CLEAR_INTERRUPT_RUNNING(thr->heap);

	return retval;
}
#endif  /* DUK_USE_INTERRUPT_COUNTER */

/*
 *  Debugger handling for executor restart
 *
 *  Check for breakpoints, stepping, etc, and figure out if we should execute
 *  in checked or normal mode.  Note that we can't do this when an activation
 *  is created, because breakpoint status (and stepping status) may change
 *  later, so we must recheck every time we're executing an activation.
 *  This primitive should be side effect free to avoid changes during check.
 */

#if defined(DUK_USE_DEBUGGER_SUPPORT)
DUK_LOCAL void duk__executor_recheck_debugger(duk_hthread *thr, duk_activation *act, duk_hcompfunc *fun) {
	duk_heap *heap;
	duk_tval *tv_tmp;
	duk_hstring *filename;
	duk_small_uint_t bp_idx;
	duk_breakpoint **bp_active;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(act != NULL);
	DUK_ASSERT(fun != NULL);

	heap = thr->heap;
	bp_active = heap->dbg_breakpoints_active;
	act->flags &= ~DUK_ACT_FLAG_BREAKPOINT_ACTIVE;

	tv_tmp = duk_hobject_find_entry_tval_ptr_stridx(thr->heap, (duk_hobject *) fun, DUK_STRIDX_FILE_NAME);
	if (tv_tmp && DUK_TVAL_IS_STRING(tv_tmp)) {
		filename = DUK_TVAL_GET_STRING(tv_tmp);

		/* Figure out all active breakpoints.  A breakpoint is
		 * considered active if the current function's fileName
		 * matches the breakpoint's fileName, AND there is no
		 * inner function that has matching line numbers
		 * (otherwise a breakpoint would be triggered both
		 * inside and outside of the inner function which would
		 * be confusing).  Example:
		 *
		 *     function foo() {
		 *         print('foo');
		 *         function bar() {    <-.  breakpoints in these
		 *             print('bar');     |  lines should not affect
		 *         }                   <-'  foo() execution
		 *         bar();
		 *     }
		 *
		 * We need a few things that are only available when
		 * debugger support is enabled: (1) a line range for
		 * each function, and (2) access to the function
		 * template to access the inner functions (and their
		 * line ranges).
		 *
		 * It's important to have a narrow match for active
		 * breakpoints so that we don't enter checked execution
		 * when that's not necessary.  For instance, if we're
		 * running inside a certain function and there's
		 * breakpoint outside in (after the call site), we
		 * don't want to slow down execution of the function.
		 */

		for (bp_idx = 0; bp_idx < heap->dbg_breakpoint_count; bp_idx++) {
			duk_breakpoint *bp = heap->dbg_breakpoints + bp_idx;
			duk_hobject **funcs, **funcs_end;
			duk_hcompfunc *inner_fun;
			duk_bool_t bp_match;

			if (bp->filename == filename &&
			    bp->line >= fun->start_line && bp->line <= fun->end_line) {
				bp_match = 1;
				DUK_DD(DUK_DDPRINT("breakpoint filename and line match: "
				                   "%s:%ld vs. %s (line %ld vs. %ld-%ld)",
				                   DUK_HSTRING_GET_DATA(bp->filename),
				                   (long) bp->line,
				                   DUK_HSTRING_GET_DATA(filename),
				                   (long) bp->line,
				                   (long) fun->start_line,
				                   (long) fun->end_line));

				funcs = DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, fun);
				funcs_end = DUK_HCOMPFUNC_GET_FUNCS_END(thr->heap, fun);
				while (funcs != funcs_end) {
					inner_fun = (duk_hcompfunc *) *funcs;
					DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) inner_fun));
					if (bp->line >= inner_fun->start_line && bp->line <= inner_fun->end_line) {
						DUK_DD(DUK_DDPRINT("inner function masks ('captures') breakpoint"));
						bp_match = 0;
						break;
					}
					funcs++;
				}

				if (bp_match) {
					/* No need to check for size of bp_active list,
					 * it's always larger than maximum number of
					 * breakpoints.
					 */
					act->flags |= DUK_ACT_FLAG_BREAKPOINT_ACTIVE;
					*bp_active = heap->dbg_breakpoints + bp_idx;
					bp_active++;
				}
			}
		}
	}

	*bp_active = NULL;  /* terminate */

	DUK_DD(DUK_DDPRINT("ACTIVE BREAKPOINTS: %ld", (long) (bp_active - thr->heap->dbg_breakpoints_active)));

	/* Force pause if we were doing "step into" in another activation. */
	if ((thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_FUNC_ENTRY) &&
	    thr->heap->dbg_pause_act != thr->callstack_curr) {
		DUK_D(DUK_DPRINT("PAUSE TRIGGERED by function entry"));
		duk_debug_set_paused(thr->heap);
	}

	/* Force interrupt right away if we're paused or in "checked mode".
	 * Step out is handled by callstack unwind.
	 */
	if ((act->flags & DUK_ACT_FLAG_BREAKPOINT_ACTIVE) ||
	    DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap) ||
	    ((thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_LINE_CHANGE) &&
	     thr->heap->dbg_pause_act == thr->callstack_curr)) {
		/* We'll need to interrupt early so recompute the init
		 * counter to reflect the number of bytecode instructions
		 * executed so that step counts for e.g. debugger rate
		 * limiting are accurate.
		 */
		DUK_ASSERT(thr->interrupt_counter <= thr->interrupt_init);
		thr->interrupt_init = thr->interrupt_init - thr->interrupt_counter;
		thr->interrupt_counter = 0;
	}
}
#endif  /* DUK_USE_DEBUGGER_SUPPORT */

/*
 *  Opcode handlers for opcodes with a lot of code and which are relatively
 *  rare; NOINLINE to reduce amount of code in main bytecode dispatcher.
 */

DUK_LOCAL DUK_EXEC_NOINLINE_PERF void duk__handle_op_initset_initget(duk_hthread *thr, duk_uint_fast32_t ins) {
	duk_bool_t is_set = (DUK_DEC_OP(ins) == DUK_OP_INITSET);
	duk_uint_fast_t idx;
	duk_uint_t defprop_flags;

	/* A -> object register (acts as a source)
	 * BC -> BC+0 contains key, BC+1 closure (value)
	 */

	/* INITSET/INITGET are only used to initialize object literal keys.
	 * There may be a previous propery in ES2015 because duplicate property
	 * names are allowed.
	 */

	/* This could be made more optimal by accessing internals directly. */

	idx = (duk_uint_fast_t) DUK_DEC_BC(ins);
	duk_dup(thr, (duk_idx_t) (idx + 0));  /* key */
	duk_dup(thr, (duk_idx_t) (idx + 1));  /* getter/setter */
	if (is_set) {
	        defprop_flags = DUK_DEFPROP_HAVE_SETTER |
	                        DUK_DEFPROP_FORCE |
	                        DUK_DEFPROP_SET_ENUMERABLE |
	                        DUK_DEFPROP_SET_CONFIGURABLE;
	} else {
	        defprop_flags = DUK_DEFPROP_HAVE_GETTER |
	                        DUK_DEFPROP_FORCE |
	                        DUK_DEFPROP_SET_ENUMERABLE |
	                        DUK_DEFPROP_SET_CONFIGURABLE;
	}
	duk_def_prop(thr, (duk_idx_t) DUK_DEC_A(ins), defprop_flags);
}

DUK_LOCAL DUK_EXEC_NOINLINE_PERF void duk__handle_op_trycatch(duk_hthread *thr, duk_uint_fast32_t ins, duk_instr_t *curr_pc) {
	duk_activation *act;
	duk_catcher *cat;
	duk_tval *tv1;
	duk_small_uint_fast_t a;
	duk_small_uint_fast_t bc;

	/* A -> flags
	 * BC -> reg_catch; base register for two registers used both during
	 *       trycatch setup and when catch is triggered
	 *
	 *      If DUK_BC_TRYCATCH_FLAG_CATCH_BINDING set:
	 *          reg_catch + 0: catch binding variable name (string).
	 *          Automatic declarative environment is established for
	 *          the duration of the 'catch' clause.
	 *
	 *      If DUK_BC_TRYCATCH_FLAG_WITH_BINDING set:
	 *          reg_catch + 0: with 'target value', which is coerced to
	 *          an object and then used as a bindind object for an
	 *          environment record.  The binding is initialized here, for
	 *          the 'try' clause.
	 *
	 * Note that a TRYCATCH generated for a 'with' statement has no
	 * catch or finally parts.
	 */

	/* XXX: TRYCATCH handling should be reworked to avoid creating
	 * an explicit scope unless it is actually needed (e.g. function
	 * instances or eval is executed inside the catch block).  This
	 * rework is not trivial because the compiler doesn't have an
	 * intermediate representation.  When the rework is done, the
	 * opcode format can also be made more straightforward.
	 */

	/* XXX: side effect handling is quite awkward here */

	DUK_DDD(DUK_DDDPRINT("TRYCATCH: reg_catch=%ld, have_catch=%ld, "
	                     "have_finally=%ld, catch_binding=%ld, with_binding=%ld (flags=0x%02lx)",
	                     (long) DUK_DEC_BC(ins),
	                     (long) (DUK_DEC_A(ins) & DUK_BC_TRYCATCH_FLAG_HAVE_CATCH ? 1 : 0),
	                     (long) (DUK_DEC_A(ins) & DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY ? 1 : 0),
	                     (long) (DUK_DEC_A(ins) & DUK_BC_TRYCATCH_FLAG_CATCH_BINDING ? 1 : 0),
	                     (long) (DUK_DEC_A(ins) & DUK_BC_TRYCATCH_FLAG_WITH_BINDING ? 1 : 0),
	                     (unsigned long) DUK_DEC_A(ins)));

	a = DUK_DEC_A(ins);
	bc = DUK_DEC_BC(ins);

	/* Registers 'bc' and 'bc + 1' are written in longjmp handling
	 * and if their previous values (which are temporaries) become
	 * unreachable -and- have a finalizer, there'll be a function
	 * call during error handling which is not supported now (GH-287).
	 * Ensure that both 'bc' and 'bc + 1' have primitive values to
	 * guarantee no finalizer calls in error handling.  Scrubbing also
	 * ensures finalizers for the previous values run here rather than
	 * later.  Error handling related values are also written to 'bc'
	 * and 'bc + 1' but those values never become unreachable during
	 * error handling, so there's no side effect problem even if the
	 * error value has a finalizer.
	 */
	duk_dup(thr, (duk_idx_t) bc);  /* Stabilize value. */
	duk_to_undefined(thr, (duk_idx_t) bc);
	duk_to_undefined(thr, (duk_idx_t) (bc + 1));

	/* Allocate catcher and populate it.  Doesn't have to
	 * be fully atomic, but the catcher must be in a
	 * consistent state if side effects (such as finalizer
	 * calls) occur.
	 */

	cat = duk_hthread_catcher_alloc(thr);
	DUK_ASSERT(cat != NULL);

	cat->flags = DUK_CAT_TYPE_TCF;
	cat->h_varname = NULL;
	cat->pc_base = (duk_instr_t *) curr_pc;  /* pre-incremented, points to first jump slot */
	cat->idx_base = (duk_size_t) (thr->valstack_bottom - thr->valstack) + bc;

	act = thr->callstack_curr;
	DUK_ASSERT(act != NULL);
	cat->parent = act->cat;
	act->cat = cat;

	if (a & DUK_BC_TRYCATCH_FLAG_HAVE_CATCH) {
		cat->flags |= DUK_CAT_FLAG_CATCH_ENABLED;
	}
	if (a & DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY) {
		cat->flags |= DUK_CAT_FLAG_FINALLY_ENABLED;
	}
	if (a & DUK_BC_TRYCATCH_FLAG_CATCH_BINDING) {
		DUK_DDD(DUK_DDDPRINT("catch binding flag set to catcher"));
		cat->flags |= DUK_CAT_FLAG_CATCH_BINDING_ENABLED;
		tv1 = DUK_GET_TVAL_NEGIDX(thr, -1);
		DUK_ASSERT(DUK_TVAL_IS_STRING(tv1));

		/* borrowed reference; although 'tv1' comes from a register,
		 * its value was loaded using LDCONST so the constant will
		 * also exist and be reachable.
		 */
		cat->h_varname = DUK_TVAL_GET_STRING(tv1);
	} else if (a & DUK_BC_TRYCATCH_FLAG_WITH_BINDING) {
		duk_hobjenv *env;
		duk_hobject *target;

		/* Delayed env initialization for activation (if needed). */
		DUK_ASSERT(thr->callstack_top >= 1);
		DUK_ASSERT(act == thr->callstack_curr);
		DUK_ASSERT(act != NULL);
		if (act->lex_env == NULL) {
			DUK_DDD(DUK_DDDPRINT("delayed environment initialization"));
			DUK_ASSERT(act->var_env == NULL);

			duk_js_init_activation_environment_records_delayed(thr, act);
			DUK_ASSERT(act == thr->callstack_curr);
			DUK_UNREF(act);  /* 'act' is no longer accessed, scanbuild fix */
		}
		DUK_ASSERT(act->lex_env != NULL);
		DUK_ASSERT(act->var_env != NULL);

		/* Coerce 'with' target. */
		target = duk_to_hobject(thr, -1);
		DUK_ASSERT(target != NULL);

		/* Create an object environment; it is not pushed
		 * so avoid side effects very carefully until it is
		 * referenced.
		 */
		env = duk_hobjenv_alloc(thr,
		                        DUK_HOBJECT_FLAG_EXTENSIBLE |
		                        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJENV));
		DUK_ASSERT(env != NULL);
		DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) env) == NULL);
		env->target = target;  /* always provideThis=true */
		DUK_HOBJECT_INCREF(thr, target);
		env->has_this = 1;
		DUK_HOBJENV_ASSERT_VALID(env);
		DUK_DDD(DUK_DDDPRINT("environment for with binding: %!iO", env));

		DUK_ASSERT(act == thr->callstack_curr);
		DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) env) == NULL);
		DUK_ASSERT(act->lex_env != NULL);
		DUK_HOBJECT_SET_PROTOTYPE(thr->heap, (duk_hobject *) env, act->lex_env);
		act->lex_env = (duk_hobject *) env;  /* Now reachable. */
		DUK_HOBJECT_INCREF(thr, (duk_hobject *) env);
		/* Net refcount change to act->lex_env is 0: incref for env's
		 * prototype, decref for act->lex_env overwrite.
		 */

		/* Set catcher lex_env active (affects unwind)
		 * only when the whole setup is complete.
		 */
		cat = act->cat;  /* XXX: better to relookup? not mandatory because 'cat' is stable */
		cat->flags |= DUK_CAT_FLAG_LEXENV_ACTIVE;
	} else {
		;
	}

	DUK_DDD(DUK_DDDPRINT("TRYCATCH catcher: flags=0x%08lx, pc_base=%ld, "
	                     "idx_base=%ld, h_varname=%!O",
	                     (unsigned long) cat->flags,
	                     (long) cat->pc_base, (long) cat->idx_base, (duk_heaphdr *) cat->h_varname));

	duk_pop_unsafe(thr);
}

DUK_LOCAL DUK_EXEC_NOINLINE_PERF duk_instr_t *duk__handle_op_endtry(duk_hthread *thr, duk_uint_fast32_t ins) {
	duk_activation *act;
	duk_catcher *cat;
	duk_tval *tv1;
	duk_instr_t *pc_base;

	DUK_UNREF(ins);

	DUK_ASSERT(thr->callstack_top >= 1);
	act = thr->callstack_curr;
	DUK_ASSERT(act != NULL);
	cat = act->cat;
	DUK_ASSERT(cat != NULL);
	DUK_ASSERT(DUK_CAT_GET_TYPE(act->cat) == DUK_CAT_TYPE_TCF);

	DUK_DDD(DUK_DDDPRINT("ENDTRY: clearing catch active flag (regardless of whether it was set or not)"));
	DUK_CAT_CLEAR_CATCH_ENABLED(cat);

	pc_base = cat->pc_base;

	if (DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
		DUK_DDD(DUK_DDDPRINT("ENDTRY: finally part is active, jump through 2nd jump slot with 'normal continuation'"));

		tv1 = thr->valstack + cat->idx_base;
		DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);
		DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv1);  /* side effects */
		tv1 = NULL;

		tv1 = thr->valstack + cat->idx_base + 1;
		DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);
		DUK_TVAL_SET_U32_UPDREF(thr, tv1, (duk_uint32_t) DUK_LJ_TYPE_NORMAL);  /* side effects */
		tv1 = NULL;

		DUK_CAT_CLEAR_FINALLY_ENABLED(cat);
	} else {
		DUK_DDD(DUK_DDDPRINT("ENDTRY: no finally part, dismantle catcher, jump through 2nd jump slot (to end of statement)"));

		duk_hthread_catcher_unwind_norz(thr, act);  /* lexenv may be set for 'with' binding */
		/* no need to unwind callstack */
	}

	return pc_base + 1;  /* new curr_pc value */
}

DUK_LOCAL DUK_EXEC_NOINLINE_PERF duk_instr_t *duk__handle_op_endcatch(duk_hthread *thr, duk_uint_fast32_t ins) {
	duk_activation *act;
	duk_catcher *cat;
	duk_tval *tv1;
	duk_instr_t *pc_base;

	DUK_UNREF(ins);

	DUK_ASSERT(thr->callstack_top >= 1);
	act = thr->callstack_curr;
	DUK_ASSERT(act != NULL);
	cat = act->cat;
	DUK_ASSERT(cat != NULL);
	DUK_ASSERT(!DUK_CAT_HAS_CATCH_ENABLED(cat));  /* cleared before entering catch part */

	if (DUK_CAT_HAS_LEXENV_ACTIVE(cat)) {
		duk_hobject *prev_env;

		/* 'with' binding has no catch clause, so can't be here unless a normal try-catch */
		DUK_ASSERT(DUK_CAT_HAS_CATCH_BINDING_ENABLED(cat));
		DUK_ASSERT(act->lex_env != NULL);

		DUK_DDD(DUK_DDDPRINT("ENDCATCH: popping catcher part lexical environment"));

		prev_env = act->lex_env;
		DUK_ASSERT(prev_env != NULL);
		act->lex_env = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, prev_env);
		DUK_CAT_CLEAR_LEXENV_ACTIVE(cat);
		DUK_HOBJECT_INCREF(thr, act->lex_env);
		DUK_HOBJECT_DECREF(thr, prev_env);  /* side effects */

		DUK_ASSERT(act == thr->callstack_curr);
		DUK_ASSERT(act != NULL);
	}

	pc_base = cat->pc_base;

	if (DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
		DUK_DDD(DUK_DDDPRINT("ENDCATCH: finally part is active, jump through 2nd jump slot with 'normal continuation'"));

		tv1 = thr->valstack + cat->idx_base;
		DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);
		DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv1);  /* side effects */
		tv1 = NULL;

		tv1 = thr->valstack + cat->idx_base + 1;
		DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);
		DUK_TVAL_SET_U32_UPDREF(thr, tv1, (duk_uint32_t) DUK_LJ_TYPE_NORMAL);  /* side effects */
		tv1 = NULL;

		DUK_CAT_CLEAR_FINALLY_ENABLED(cat);
	} else {
		DUK_DDD(DUK_DDDPRINT("ENDCATCH: no finally part, dismantle catcher, jump through 2nd jump slot (to end of statement)"));

		duk_hthread_catcher_unwind_norz(thr, act);
		/* no need to unwind callstack */
	}

	return pc_base + 1;  /* new curr_pc value */
}

DUK_LOCAL DUK_EXEC_NOINLINE_PERF duk_small_uint_t duk__handle_op_endfin(duk_hthread *thr, duk_uint_fast32_t ins, duk_activation *entry_act) {
	duk_activation *act;
	duk_tval *tv1;
	duk_uint_t reg_catch;
	duk_small_uint_t cont_type;
	duk_small_uint_t ret_result;

	DUK_ASSERT(thr->ptr_curr_pc == NULL);
	DUK_ASSERT(thr->callstack_top >= 1);
	act = thr->callstack_curr;
	DUK_ASSERT(act != NULL);
	reg_catch = DUK_DEC_ABC(ins);

	/* CATCH flag may be enabled or disabled here; it may be enabled if
	 * the statement has a catch block but the try block does not throw
	 * an error.
	 */

	DUK_DDD(DUK_DDDPRINT("ENDFIN: completion value=%!T, type=%!T",
	                     (duk_tval *) (thr->valstack_bottom + reg_catch + 0),
	                     (duk_tval *) (thr->valstack_bottom + reg_catch + 1)));

	tv1 = thr->valstack_bottom + reg_catch + 1;  /* type */
	DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv1));
#if defined(DUK_USE_FASTINT)
	DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv1));
	cont_type = (duk_small_uint_t) DUK_TVAL_GET_FASTINT_U32(tv1);
#else
	cont_type = (duk_small_uint_t) DUK_TVAL_GET_NUMBER(tv1);
#endif

	tv1--;  /* value */

	switch (cont_type) {
	case DUK_LJ_TYPE_NORMAL: {
		DUK_DDD(DUK_DDDPRINT("ENDFIN: finally part finishing with 'normal' (non-abrupt) completion -> "
		                     "dismantle catcher, resume execution after ENDFIN"));

		duk_hthread_catcher_unwind_norz(thr, act);
		/* no need to unwind callstack */
		return 0;  /* restart execution */
	}
	case DUK_LJ_TYPE_RETURN: {
		DUK_DDD(DUK_DDDPRINT("ENDFIN: finally part finishing with 'return' complation -> dismantle "
		                     "catcher, handle return, lj.value1=%!T", tv1));

		/* Not necessary to unwind catch stack: return handling will
		 * do it.  The finally flag of 'cat' is no longer set.  The
		 * catch flag may be set, but it's not checked by return handling.
		 */

		duk_push_tval(thr, tv1);
		ret_result = duk__handle_return(thr, entry_act);
		if (ret_result == DUK__RETHAND_RESTART) {
			return 0;  /* restart execution */
		}
		DUK_ASSERT(ret_result == DUK__RETHAND_FINISHED);

		DUK_DDD(DUK_DDDPRINT("exiting executor after ENDFIN and RETURN (pseudo) longjmp type"));
		return 1;  /* exit executor */
	}
	case DUK_LJ_TYPE_BREAK:
	case DUK_LJ_TYPE_CONTINUE: {
		duk_uint_t label_id;
		duk_small_uint_t lj_type;

		/* Not necessary to unwind catch stack: break/continue
		 * handling will do it.  The finally flag of 'cat' is
		 * no longer set.  The catch flag may be set, but it's
		 * not checked by break/continue handling.
		 */

		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv1));
#if defined(DUK_USE_FASTINT)
		DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv1));
		label_id = (duk_small_uint_t) DUK_TVAL_GET_FASTINT_U32(tv1);
#else
		label_id = (duk_small_uint_t) DUK_TVAL_GET_NUMBER(tv1);
#endif
		lj_type = cont_type;
		duk__handle_break_or_continue(thr, label_id, lj_type);
		return 0;  /* restart execution */
	}
	default: {
		DUK_DDD(DUK_DDDPRINT("ENDFIN: finally part finishing with abrupt completion, lj_type=%ld -> "
		                     "dismantle catcher, re-throw error",
		                     (long) cont_type));

		duk_err_setup_ljstate1(thr, (duk_small_uint_t) cont_type, tv1);
		/* No debugger Throw notify check on purpose (rethrow). */

		DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL);  /* always in executor */
		duk_err_longjmp(thr);
		DUK_UNREACHABLE();
	}
	}

	DUK_UNREACHABLE();
	return 0;
}

DUK_LOCAL DUK_EXEC_NOINLINE_PERF void duk__handle_op_initenum(duk_hthread *thr, duk_uint_fast32_t ins) {
	duk_small_uint_t b;
	duk_small_uint_t c;

	/*
	 *  Enumeration semantics come from for-in statement, E5 Section 12.6.4.
	 *  If called with 'null' or 'undefined', this opcode returns 'null' as
	 *  the enumerator, which is special cased in NEXTENUM.  This simplifies
	 *  the compiler part
	 */

	/* B -> register for writing enumerator object
	 * C -> value to be enumerated (register)
	 */
	b = DUK_DEC_B(ins);
	c = DUK_DEC_C(ins);

	if (duk_is_null_or_undefined(thr, (duk_idx_t) c)) {
		duk_push_null(thr);
		duk_replace(thr, (duk_idx_t) b);
	} else {
		duk_dup(thr, (duk_idx_t) c);
		duk_to_object(thr, -1);
		duk_hobject_enumerator_create(thr, 0 /*enum_flags*/);  /* [ ... val ] --> [ ... enum ] */
		duk_replace(thr, (duk_idx_t) b);
	}
}

DUK_LOCAL DUK_EXEC_NOINLINE_PERF duk_small_uint_t duk__handle_op_nextenum(duk_hthread *thr, duk_uint_fast32_t ins) {
	duk_small_uint_t b;
	duk_small_uint_t c;
	duk_small_uint_t pc_skip = 0;

	/*
	 *  NEXTENUM checks whether the enumerator still has unenumerated
	 *  keys.  If so, the next key is loaded to the target register
	 *  and the next instruction is skipped.  Otherwise the next instruction
	 *  will be executed, jumping out of the enumeration loop.
	 */

	/* B -> target register for next key
	 * C -> enum register
	 */
	b = DUK_DEC_B(ins);
	c = DUK_DEC_C(ins);

	DUK_DDD(DUK_DDDPRINT("NEXTENUM: b->%!T, c->%!T",
	                     (duk_tval *) duk_get_tval(thr, (duk_idx_t) b),
	                     (duk_tval *) duk_get_tval(thr, (duk_idx_t) c)));

	if (duk_is_object(thr, (duk_idx_t) c)) {
		/* XXX: assert 'c' is an enumerator */
		duk_dup(thr, (duk_idx_t) c);
		if (duk_hobject_enumerator_next(thr, 0 /*get_value*/)) {
			/* [ ... enum ] -> [ ... next_key ] */
			DUK_DDD(DUK_DDDPRINT("enum active, next key is %!T, skip jump slot ",
			                     (duk_tval *) duk_get_tval(thr, -1)));
			pc_skip = 1;
		} else {
			/* [ ... enum ] -> [ ... ] */
			DUK_DDD(DUK_DDDPRINT("enum finished, execute jump slot"));
			DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top));  /* valstack policy */
			thr->valstack_top++;
		}
		duk_replace(thr, (duk_idx_t) b);
	} else {
		/* 'null' enumerator case -> behave as with an empty enumerator */
		DUK_ASSERT(duk_is_null(thr, (duk_idx_t) c));
		DUK_DDD(DUK_DDDPRINT("enum is null, execute jump slot"));
	}

	return pc_skip;
}

/*
 *  Call handling helpers.
 */

DUK_LOCAL duk_bool_t duk__executor_handle_call(duk_hthread *thr, duk_idx_t idx, duk_idx_t nargs, duk_small_uint_t call_flags) {
	duk_bool_t rc;

	duk_set_top_unsafe(thr, (duk_idx_t) (idx + nargs + 2));   /* [ ... func this arg1 ... argN ] */

	/* Attempt an Ecma-to-Ecma call setup.  If the call
	 * target is (directly or indirectly) Reflect.construct(),
	 * the call may change into a constructor call on the fly.
	 */
	rc = (duk_bool_t) duk_handle_call_unprotected(thr, idx, call_flags);
	if (rc != 0) {
		/* Ecma-to-ecma call possible, may or may not
		 * be a tail call.  Avoid C recursion by
		 * reusing current executor instance.
		 */
		DUK_DDD(DUK_DDDPRINT("ecma-to-ecma call setup possible, restart execution"));
		/* curr_pc synced by duk_handle_call_unprotected() */
		DUK_ASSERT(thr->ptr_curr_pc == NULL);
		return rc;
	} else {
		/* Call was handled inline. */
	}
	DUK_ASSERT(thr->ptr_curr_pc != NULL);
	return rc;
}

/*
 *  ECMAScript bytecode executor.
 *
 *  Resume execution for the current thread from its current activation.
 *  Returns when execution would return from the entry level activation,
 *  leaving a single return value on top of the stack.  Function calls
 *  and thread resumptions are handled internally.  If an error occurs,
 *  a longjmp() with type DUK_LJ_TYPE_THROW is called on the entry level
 *  setjmp() jmpbuf.
 *
 *  ECMAScript function calls and coroutine resumptions are handled
 *  internally (by the outer executor function) without recursive C calls.
 *  Other function calls are handled using duk_handle_call(), increasing
 *  C recursion depth.
 *
 *  Abrupt completions (= long control tranfers) are handled either
 *  directly by reconfiguring relevant stacks and restarting execution,
 *  or via a longjmp.  Longjmp-free handling is preferable for performance
 *  (especially Emscripten performance), and is used for: break, continue,
 *  and return.
 *
 *  For more detailed notes, see doc/execution.rst.
 *
 *  Also see doc/code-issues.rst for discussion of setjmp(), longjmp(),
 *  and volatile.
 */

/* Presence of 'fun' is config based, there's a marginal performance
 * difference and the best option is architecture dependent.
 */
#if defined(DUK_USE_EXEC_FUN_LOCAL)
#define DUK__FUN()          fun
#else
#define DUK__FUN()          ((duk_hcompfunc *) DUK_ACT_GET_FUNC((thr)->callstack_curr))
#endif

/* Strict flag. */
#define DUK__STRICT()       ((duk_small_uint_t) DUK_HOBJECT_HAS_STRICT((duk_hobject *) DUK__FUN()))

/* Reg/const access macros: these are very footprint and performance sensitive
 * so modify with care.  Arguments are sometimes evaluated multiple times which
 * is not ideal.
 */
#define DUK__REG(x)         (*(thr->valstack_bottom + (x)))
#define DUK__REGP(x)        (thr->valstack_bottom + (x))
#define DUK__CONST(x)       (*(consts + (x)))
#define DUK__CONSTP(x)      (consts + (x))

/* Reg/const access macros which take the 32-bit instruction and avoid an
 * explicit field decoding step by using shifts and masks.  These must be
 * kept in sync with duk_js_bytecode.h.  The shift/mask values are chosen
 * so that 'ins' can be shifted and masked and used as a -byte- offset
 * instead of a duk_tval offset which needs further shifting (which is an
 * issue on some, but not all, CPUs).
 */
#define DUK__RCBIT_B           DUK_BC_REGCONST_B
#define DUK__RCBIT_C           DUK_BC_REGCONST_C
#if defined(DUK_USE_EXEC_REGCONST_OPTIMIZE)
#if defined(DUK_USE_PACKED_TVAL)
#define DUK__TVAL_SHIFT        3  /* sizeof(duk_tval) == 8 */
#else
#define DUK__TVAL_SHIFT        4  /* sizeof(duk_tval) == 16; not always the case so also asserted for */
#endif
#define DUK__SHIFT_A           (DUK_BC_SHIFT_A - DUK__TVAL_SHIFT)
#define DUK__SHIFT_B           (DUK_BC_SHIFT_B - DUK__TVAL_SHIFT)
#define DUK__SHIFT_C           (DUK_BC_SHIFT_C - DUK__TVAL_SHIFT)
#define DUK__SHIFT_BC          (DUK_BC_SHIFT_BC - DUK__TVAL_SHIFT)
#define DUK__MASK_A            (DUK_BC_UNSHIFTED_MASK_A << DUK__TVAL_SHIFT)
#define DUK__MASK_B            (DUK_BC_UNSHIFTED_MASK_B << DUK__TVAL_SHIFT)
#define DUK__MASK_C            (DUK_BC_UNSHIFTED_MASK_C << DUK__TVAL_SHIFT)
#define DUK__MASK_BC           (DUK_BC_UNSHIFTED_MASK_BC << DUK__TVAL_SHIFT)
#define DUK__BYTEOFF_A(ins)    (((ins) >> DUK__SHIFT_A) & DUK__MASK_A)
#define DUK__BYTEOFF_B(ins)    (((ins) >> DUK__SHIFT_B) & DUK__MASK_B)
#define DUK__BYTEOFF_C(ins)    (((ins) >> DUK__SHIFT_C) & DUK__MASK_C)
#define DUK__BYTEOFF_BC(ins)   (((ins) >> DUK__SHIFT_BC) & DUK__MASK_BC)

#define DUK__REGP_A(ins)       ((duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_bottom + DUK__BYTEOFF_A((ins))))
#define DUK__REGP_B(ins)       ((duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_bottom + DUK__BYTEOFF_B((ins))))
#define DUK__REGP_C(ins)       ((duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_bottom + DUK__BYTEOFF_C((ins))))
#define DUK__REGP_BC(ins)      ((duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_bottom + DUK__BYTEOFF_BC((ins))))
#define DUK__CONSTP_A(ins)     ((duk_tval *) (void *) ((duk_uint8_t *) consts + DUK__BYTEOFF_A((ins))))
#define DUK__CONSTP_B(ins)     ((duk_tval *) (void *) ((duk_uint8_t *) consts + DUK__BYTEOFF_B((ins))))
#define DUK__CONSTP_C(ins)     ((duk_tval *) (void *) ((duk_uint8_t *) consts + DUK__BYTEOFF_C((ins))))
#define DUK__CONSTP_BC(ins)    ((duk_tval *) (void *) ((duk_uint8_t *) consts + DUK__BYTEOFF_BC((ins))))
#define DUK__REGCONSTP_B(ins)  ((duk_tval *) (void *) ((duk_uint8_t *) (((ins) & DUK__RCBIT_B) ? consts : thr->valstack_bottom) + DUK__BYTEOFF_B((ins))))
#define DUK__REGCONSTP_C(ins)  ((duk_tval *) (void *) ((duk_uint8_t *) (((ins) & DUK__RCBIT_C) ? consts : thr->valstack_bottom) + DUK__BYTEOFF_C((ins))))
#else  /* DUK_USE_EXEC_REGCONST_OPTIMIZE */
/* Safe alternatives, no assumption about duk_tval size. */
#define DUK__REGP_A(ins)       DUK__REGP(DUK_DEC_A((ins)))
#define DUK__REGP_B(ins)       DUK__REGP(DUK_DEC_B((ins)))
#define DUK__REGP_C(ins)       DUK__REGP(DUK_DEC_C((ins)))
#define DUK__REGP_BC(ins)      DUK__REGP(DUK_DEC_BC((ins)))
#define DUK__CONSTP_A(ins)     DUK__CONSTP(DUK_DEC_A((ins)))
#define DUK__CONSTP_B(ins)     DUK__CONSTP(DUK_DEC_B((ins)))
#define DUK__CONSTP_C(ins)     DUK__CONSTP(DUK_DEC_C((ins)))
#define DUK__CONSTP_BC(ins)    DUK__CONSTP(DUK_DEC_BC((ins)))
#define DUK__REGCONSTP_B(ins)  ((((ins) & DUK__RCBIT_B) ? consts : thr->valstack_bottom) + DUK_DEC_B((ins)))
#define DUK__REGCONSTP_C(ins)  ((((ins) & DUK__RCBIT_C) ? consts : thr->valstack_bottom) + DUK_DEC_C((ins)))
#endif  /* DUK_USE_EXEC_REGCONST_OPTIMIZE */

#if defined(DUK_USE_VERBOSE_EXECUTOR_ERRORS)
#define DUK__INTERNAL_ERROR(msg)  do { \
		DUK_ERROR_ERROR(thr, (msg)); \
		DUK_WO_NORETURN(return;); \
	} while (0)
#else
#define DUK__INTERNAL_ERROR(msg)  do { \
		goto internal_error; \
	} while (0)
#endif

#define DUK__SYNC_CURR_PC()  do { \
		duk_activation *duk__act; \
		duk__act = thr->callstack_curr; \
		duk__act->curr_pc = curr_pc; \
	} while (0)
#define DUK__SYNC_AND_NULL_CURR_PC()  do { \
		duk_activation *duk__act; \
		duk__act = thr->callstack_curr; \
		duk__act->curr_pc = curr_pc; \
		thr->ptr_curr_pc = NULL; \
	} while (0)

#if defined(DUK_USE_EXEC_PREFER_SIZE)
#define DUK__LOOKUP_INDIRECT(idx) do { \
		(idx) = (duk_uint_fast_t) duk_get_uint(thr, (duk_idx_t) (idx)); \
	} while (0)
#elif defined(DUK_USE_FASTINT)
#define DUK__LOOKUP_INDIRECT(idx) do { \
		duk_tval *tv_ind; \
		tv_ind = DUK__REGP((idx)); \
		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_ind)); \
		DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv_ind));  /* compiler guarantees */ \
		(idx) = (duk_uint_fast_t) DUK_TVAL_GET_FASTINT_U32(tv_ind); \
	} while (0)
#else
#define DUK__LOOKUP_INDIRECT(idx) do { \
		duk_tval *tv_ind; \
		tv_ind = DUK__REGP(idx); \
		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_ind)); \
		idx = (duk_uint_fast_t) DUK_TVAL_GET_NUMBER(tv_ind); \
	} while (0)
#endif

DUK_LOCAL void duk__handle_executor_error(duk_heap *heap,
                                          duk_activation *entry_act,
                                          duk_int_t entry_call_recursion_depth,
                                          duk_jmpbuf *entry_jmpbuf_ptr,
                                          volatile duk_bool_t *out_delayed_catch_setup) {
	duk_small_uint_t lj_ret;

	/* Longjmp callers are required to sync-and-null thr->ptr_curr_pc
	 * before longjmp.
	 */
	DUK_ASSERT(heap->curr_thread != NULL);
	DUK_ASSERT(heap->curr_thread->ptr_curr_pc == NULL);

	/* XXX: signalling the need to shrink check (only if unwound) */

	/* Must be restored here to handle e.g. yields properly. */
	heap->call_recursion_depth = entry_call_recursion_depth;

	/* Switch to caller's setjmp() catcher so that if an error occurs
	 * during error handling, it is always propagated outwards instead
	 * of causing an infinite loop in our own handler.
	 */
	heap->lj.jmpbuf_ptr = (duk_jmpbuf *) entry_jmpbuf_ptr;

	lj_ret = duk__handle_longjmp(heap->curr_thread, entry_act, out_delayed_catch_setup);

	/* Error handling complete, remove side effect protections.
	 */
#if defined(DUK_USE_ASSERTIONS)
	DUK_ASSERT(heap->error_not_allowed == 1);
	heap->error_not_allowed = 0;
#endif
	DUK_ASSERT(heap->pf_prevent_count > 0);
	heap->pf_prevent_count--;
	DUK_DD(DUK_DDPRINT("executor error handled, pf_prevent_count updated to %ld", (long) heap->pf_prevent_count));

	if (lj_ret == DUK__LONGJMP_RESTART) {
		/* Restart bytecode execution, possibly with a changed thread. */
		DUK_REFZERO_CHECK_SLOW(heap->curr_thread);
	} else {
		/* If an error is propagated, don't run refzero checks here.
		 * The next catcher will deal with that.  Pf_prevent_count
		 * will be re-bumped by the longjmp.
		 */

		DUK_ASSERT(lj_ret == DUK__LONGJMP_RETHROW);  /* Rethrow error to calling state. */
		DUK_ASSERT(heap->lj.jmpbuf_ptr == entry_jmpbuf_ptr);  /* Longjmp handling has restored jmpbuf_ptr. */

		/* Thread may have changed, e.g. YIELD converted to THROW. */
		duk_err_longjmp(heap->curr_thread);
		DUK_UNREACHABLE();
	}
}

/* Outer executor with setjmp/longjmp handling. */
DUK_INTERNAL void duk_js_execute_bytecode(duk_hthread *exec_thr) {
	/* Entry level info. */
	duk_hthread *entry_thread;
	duk_activation *entry_act;
	duk_int_t entry_call_recursion_depth;
	duk_jmpbuf *entry_jmpbuf_ptr;
	duk_jmpbuf our_jmpbuf;
	duk_heap *heap;
	volatile duk_bool_t delayed_catch_setup = 0;

	DUK_ASSERT(exec_thr != NULL);
	DUK_ASSERT(exec_thr->heap != NULL);
	DUK_ASSERT(exec_thr->heap->curr_thread != NULL);
	DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR((duk_heaphdr *) exec_thr);
	DUK_ASSERT(exec_thr->callstack_top >= 1);  /* at least one activation, ours */
	DUK_ASSERT(exec_thr->callstack_curr != NULL);
	DUK_ASSERT(DUK_ACT_GET_FUNC(exec_thr->callstack_curr) != NULL);
	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(exec_thr->callstack_curr)));

	DUK_GC_TORTURE(exec_thr->heap);

	entry_thread = exec_thr;
	heap = entry_thread->heap;
	entry_act = entry_thread->callstack_curr;
	DUK_ASSERT(entry_act != NULL);
	entry_call_recursion_depth = entry_thread->heap->call_recursion_depth;
	entry_jmpbuf_ptr = entry_thread->heap->lj.jmpbuf_ptr;

	/*
	 *  Note: we currently assume that the setjmp() catchpoint is
	 *  not re-entrant (longjmp() cannot be called more than once
	 *  for a single setjmp()).
	 *
	 *  See doc/code-issues.rst for notes on variable assignment
	 *  before and after setjmp().
	 */

	for (;;) {
		heap->lj.jmpbuf_ptr = &our_jmpbuf;
		DUK_ASSERT(heap->lj.jmpbuf_ptr != NULL);

#if defined(DUK_USE_CPP_EXCEPTIONS)
		try {
#else
		DUK_ASSERT(heap->lj.jmpbuf_ptr == &our_jmpbuf);
		if (DUK_SETJMP(our_jmpbuf.jb) == 0) {
#endif
			DUK_DDD(DUK_DDDPRINT("after setjmp, delayed catch setup: %ld\n", (long) delayed_catch_setup));

			if (DUK_UNLIKELY(delayed_catch_setup != 0)) {
				duk_hthread *thr = entry_thread->heap->curr_thread;

				delayed_catch_setup = 0;
				duk__handle_catch_part2(thr);
				DUK_ASSERT(delayed_catch_setup == 0);
				DUK_DDD(DUK_DDDPRINT("top after delayed catch setup: %ld", (long) duk_get_top(entry_thread)));
			}

			/* Execute bytecode until returned or longjmp(). */
			duk__js_execute_bytecode_inner(entry_thread, entry_act);

			/* Successful return: restore jmpbuf and return to caller. */
			heap->lj.jmpbuf_ptr = entry_jmpbuf_ptr;

			return;
#if defined(DUK_USE_CPP_EXCEPTIONS)
		} catch (duk_internal_exception &exc) {
#else
		} else {
#endif
#if defined(DUK_USE_CPP_EXCEPTIONS)
			DUK_UNREF(exc);
#endif
			DUK_DDD(DUK_DDDPRINT("longjmp caught by bytecode executor"));
			DUK_STATS_INC(exec_thr->heap, stats_exec_throw);

			duk__handle_executor_error(heap,
			                           entry_act,
			                           entry_call_recursion_depth,
			                           entry_jmpbuf_ptr,
						   &delayed_catch_setup);
		}
#if defined(DUK_USE_CPP_EXCEPTIONS)
		catch (duk_fatal_exception &exc) {
			DUK_D(DUK_DPRINT("rethrow duk_fatal_exception"));
			DUK_UNREF(exc);
			throw;
		} catch (std::exception &exc) {
			const char *what = exc.what();
			if (!what) {
				what = "unknown";
			}
			DUK_D(DUK_DPRINT("unexpected c++ std::exception (perhaps thrown by user code)"));
			DUK_STATS_INC(exec_thr->heap, stats_exec_throw);
			try {
				DUK_ASSERT(heap->curr_thread != NULL);
				DUK_ERROR_FMT1(heap->curr_thread, DUK_ERR_TYPE_ERROR, "caught invalid c++ std::exception '%s' (perhaps thrown by user code)", what);
				DUK_WO_NORETURN(return;);
			} catch (duk_internal_exception exc) {
				DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ std::exception"));
				DUK_UNREF(exc);
				duk__handle_executor_error(heap,
				                           entry_act,
				                           entry_call_recursion_depth,
				                           entry_jmpbuf_ptr,
							   &delayed_catch_setup);
			}
		} catch (...) {
			DUK_D(DUK_DPRINT("unexpected c++ exception (perhaps thrown by user code)"));
			DUK_STATS_INC(exec_thr->heap, stats_exec_throw);
			try {
				DUK_ASSERT(heap->curr_thread != NULL);
				DUK_ERROR_TYPE(heap->curr_thread, "caught invalid c++ exception (perhaps thrown by user code)");
				DUK_WO_NORETURN(return;);
			} catch (duk_internal_exception exc) {
				DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ exception"));
				DUK_UNREF(exc);
				duk__handle_executor_error(heap,
				                           entry_act,
				                           entry_call_recursion_depth,
				                           entry_jmpbuf_ptr,
							   &delayed_catch_setup);
			}
		}
#endif
	}

	DUK_WO_NORETURN(return;);
}

/* Inner executor, performance critical. */
DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *entry_thread, duk_activation *entry_act) {
	/* Current PC, accessed by other functions through thr->ptr_to_curr_pc.
	 * Critical for performance.  It would be safest to make this volatile,
	 * but that eliminates performance benefits; aliasing guarantees
	 * should be enough though.
	 */
	duk_instr_t *curr_pc;         /* bytecode has a stable pointer */

	/* Hot variables for interpretation.  Critical for performance,
	 * but must add sparingly to minimize register shuffling.
	 */
	duk_hthread *thr;             /* stable */
	duk_tval *consts;             /* stable */
	duk_uint_fast32_t ins;
	/* 'funcs' is quite rarely used, so no local for it */
#if defined(DUK_USE_EXEC_FUN_LOCAL)
	duk_hcompfunc *fun;
#else
	/* 'fun' is quite rarely used, so no local for it */
#endif

#if defined(DUK_USE_INTERRUPT_COUNTER)
	duk_int_t int_ctr;
#endif

#if defined(DUK_USE_ASSERTIONS)
	duk_size_t valstack_top_base;    /* valstack top, should match before interpreting each op (no leftovers) */
#endif

	/* Optimized reg/const access macros assume sizeof(duk_tval) to be
	 * either 8 or 16.  Heap allocation checks this even without asserts
	 * enabled now because it can't be autodetected in duk_config.h.
	 */
#if 1
#if defined(DUK_USE_PACKED_TVAL)
	DUK_ASSERT(sizeof(duk_tval) == 8);
#else
	DUK_ASSERT(sizeof(duk_tval) == 16);
#endif
#endif

	DUK_GC_TORTURE(entry_thread->heap);

	/*
	 *  Restart execution by reloading thread state.
	 *
	 *  Note that 'thr' and any thread configuration may have changed,
	 *  so all local variables are suspect and we need to reinitialize.
	 *
	 *  The number of local variables should be kept to a minimum: if
	 *  the variables are spilled, they will need to be loaded from
	 *  memory anyway.
	 *
	 *  Any 'goto restart_execution;' code path in opcode dispatch must
	 *  ensure 'curr_pc' is synced back to act->curr_pc before the goto
	 *  takes place.
	 *
	 *  The interpreter must be very careful with memory pointers, as
	 *  many pointers are not guaranteed to be 'stable' and may be
	 *  reallocated and relocated on-the-fly quite easily (e.g. by a
	 *  memory allocation or a property access).
	 *
	 *  The following are assumed to have stable pointers:
	 *    - the current thread
	 *    - the current function
	 *    - the bytecode, constant table, inner function table of the
	 *      current function (as they are a part of the function allocation)
	 *
	 *  The following are assumed to have semi-stable pointers:
	 *    - the current activation entry: stable as long as callstack
	 *      is not changed (reallocated by growing or shrinking), or
	 *      by any garbage collection invocation (through finalizers)
	 *    - Note in particular that ANY DECREF can invalidate the
	 *      activation pointer, so for the most part a fresh lookup
	 *      is required
	 *
	 *  The following are not assumed to have stable pointers at all:
	 *    - the value stack (registers) of the current thread
	 *
	 *  See execution.rst for discussion.
	 */

 restart_execution:

	/* Lookup current thread; use the stable 'entry_thread' for this to
	 * avoid clobber warnings.  Any valid, reachable 'thr' value would be
	 * fine for this, so using 'entry_thread' is just to silence warnings.
	 */
	thr = entry_thread->heap->curr_thread;
	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(thr->callstack_top >= 1);
	DUK_ASSERT(thr->callstack_curr != NULL);
	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL);
	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)));

	DUK_GC_TORTURE(thr->heap);

	thr->ptr_curr_pc = &curr_pc;

	/* Relookup and initialize dispatch loop variables.  Debugger check. */
	{
		duk_activation *act;
#if !defined(DUK_USE_EXEC_FUN_LOCAL)
		duk_hcompfunc *fun;
#endif

		/* Assume interrupt init/counter are properly initialized here. */
		/* Assume that thr->valstack_bottom has been set-up before getting here. */

		act = thr->callstack_curr;
		DUK_ASSERT(act != NULL);
		fun = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);
		DUK_ASSERT(fun != NULL);
		DUK_ASSERT(thr->valstack_top - thr->valstack_bottom == fun->nregs);
		consts = DUK_HCOMPFUNC_GET_CONSTS_BASE(thr->heap, fun);
		DUK_ASSERT(consts != NULL);

#if defined(DUK_USE_DEBUGGER_SUPPORT)
		if (DUK_UNLIKELY(duk_debug_is_attached(thr->heap) && !thr->heap->dbg_processing)) {
			duk__executor_recheck_debugger(thr, act, fun);
			DUK_ASSERT(act == thr->callstack_curr);
			DUK_ASSERT(act != NULL);
		}
#endif  /* DUK_USE_DEBUGGER_SUPPORT */

#if defined(DUK_USE_ASSERTIONS)
		valstack_top_base = (duk_size_t) (thr->valstack_top - thr->valstack);
#endif

		/* Set up curr_pc for opcode dispatch. */
		curr_pc = act->curr_pc;
	}

	DUK_DD(DUK_DDPRINT("restarting execution, thr %p, act idx %ld, fun %p,"
	                   "consts %p, funcs %p, lev %ld, regbot %ld, regtop %ld, "
	                   "preventcount=%ld",
	                   (void *) thr,
	                   (long) (thr->callstack_top - 1),
	                   (void *) DUK__FUN(),
	                   (void *) DUK_HCOMPFUNC_GET_CONSTS_BASE(thr->heap, DUK__FUN()),
	                   (void *) DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, DUK__FUN()),
	                   (long) (thr->callstack_top - 1),
	                   (long) (thr->valstack_bottom - thr->valstack),
	                   (long) (thr->valstack_top - thr->valstack),
	                   (long) thr->callstack_preventcount));

	/* Dispatch loop. */

	for (;;) {
		duk_uint8_t op;

		DUK_ASSERT(thr->callstack_top >= 1);
		DUK_ASSERT(thr->valstack_top - thr->valstack_bottom == DUK__FUN()->nregs);
		DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack) == valstack_top_base);

		/* Executor interrupt counter check, used to implement breakpoints,
		 * debugging interface, execution timeouts, etc.  The counter is heap
		 * specific but is maintained in the current thread to make the check
		 * as fast as possible.  The counter is copied back to the heap struct
		 * whenever a thread switch occurs by the DUK_HEAP_SWITCH_THREAD() macro.
		 */
#if defined(DUK_USE_INTERRUPT_COUNTER)
		int_ctr = thr->interrupt_counter;
		if (DUK_LIKELY(int_ctr > 0)) {
			thr->interrupt_counter = int_ctr - 1;
		} else {
			/* Trigger at zero or below */
			duk_small_uint_t exec_int_ret;

			DUK_STATS_INC(thr->heap, stats_exec_interrupt);

			/* Write curr_pc back for the debugger. */
			{
				duk_activation *act;
				DUK_ASSERT(thr->callstack_top > 0);
				act = thr->callstack_curr;
				DUK_ASSERT(act != NULL);
				act->curr_pc = (duk_instr_t *) curr_pc;
			}

			/* Forced restart caused by a function return; must recheck
			 * debugger breakpoints before checking line transitions,
			 * see GH-303.  Restart and then handle interrupt_counter
			 * zero again.
			 */
#if defined(DUK_USE_DEBUGGER_SUPPORT)
			if (thr->heap->dbg_force_restart) {
				DUK_DD(DUK_DDPRINT("dbg_force_restart flag forced restart execution"));  /* GH-303 */
				thr->heap->dbg_force_restart = 0;
				goto restart_execution;
			}
#endif

			exec_int_ret = duk__executor_interrupt(thr);
			if (exec_int_ret == DUK__INT_RESTART) {
				/* curr_pc synced back above */
				goto restart_execution;
			}
		}
#endif  /* DUK_USE_INTERRUPT_COUNTER */
#if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
		/* For cross-checking during development: ensure dispatch count
		 * matches cumulative interrupt counter init value sums.
		 */
		thr->heap->inst_count_exec++;
#endif

#if defined(DUK_USE_ASSERTIONS) || defined(DUK_USE_DEBUG)
		{
			duk_activation *act;
			act = thr->callstack_curr;
			DUK_ASSERT(curr_pc >= DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, DUK__FUN()));
			DUK_ASSERT(curr_pc < DUK_HCOMPFUNC_GET_CODE_END(thr->heap, DUK__FUN()));
			DUK_UNREF(act);  /* if debugging disabled */

			DUK_DDD(DUK_DDDPRINT("executing bytecode: pc=%ld, ins=0x%08lx, op=%ld, valstack_top=%ld/%ld, nregs=%ld  -->  %!I",
			                     (long) (curr_pc - DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, DUK__FUN())),
			                     (unsigned long) *curr_pc,
			                     (long) DUK_DEC_OP(*curr_pc),
			                     (long) (thr->valstack_top - thr->valstack),
			                     (long) (thr->valstack_end - thr->valstack),
			                     (long) (DUK__FUN() ? DUK__FUN()->nregs : -1),
			                     (duk_instr_t) *curr_pc));
		}
#endif

#if defined(DUK_USE_ASSERTIONS)
		/* Quite heavy assert: check valstack policy.  Improper
		 * shuffle instructions can write beyond valstack_top/end
		 * so this check catches them in the act.
		 */
		{
			duk_tval *tv;
			tv = thr->valstack_top;
			while (tv != thr->valstack_end) {
				DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv));
				tv++;
			}
		}
#endif

		ins = *curr_pc++;
		DUK_STATS_INC(thr->heap, stats_exec_opcodes);

		/* Typing: use duk_small_(u)int_fast_t when decoding small
		 * opcode fields (op, A, B, C, BC) which fit into 16 bits
		 * and duk_(u)int_fast_t when decoding larger fields (e.g.
		 * ABC).  Use unsigned variant by default, signed when the
		 * value is used in signed arithmetic.  Using variable names
		 * such as 'a', 'b', 'c', 'bc', etc makes it easier to spot
		 * typing mismatches.
		 */

		/* Switch based on opcode.  Cast to 8-bit unsigned value and
		 * use a fully populated case clauses so that the compiler
		 * will (at least usually) omit a bounds check.
		 */
		op = (duk_uint8_t) DUK_DEC_OP(ins);
		switch (op) {

		/* Some useful macros.  These access inner executor variables
		 * directly so they only apply within the executor.
		 */
#if defined(DUK_USE_EXEC_PREFER_SIZE)
#define DUK__REPLACE_TOP_A_BREAK() { goto replace_top_a; }
#define DUK__REPLACE_TOP_BC_BREAK() { goto replace_top_bc; }
#define DUK__REPLACE_BOOL_A_BREAK(bval) { \
		duk_bool_t duk__bval; \
		duk__bval = (bval); \
		DUK_ASSERT(duk__bval == 0 || duk__bval == 1); \
		duk_push_boolean(thr, duk__bval); \
		DUK__REPLACE_TOP_A_BREAK(); \
	}
#else
#define DUK__REPLACE_TOP_A_BREAK() { DUK__REPLACE_TO_TVPTR(thr, DUK__REGP_A(ins)); break; }
#define DUK__REPLACE_TOP_BC_BREAK() { DUK__REPLACE_TO_TVPTR(thr, DUK__REGP_BC(ins)); break; }
#define DUK__REPLACE_BOOL_A_BREAK(bval) { \
		duk_bool_t duk__bval; \
		duk_tval *duk__tvdst; \
		duk__bval = (bval); \
		DUK_ASSERT(duk__bval == 0 || duk__bval == 1); \
		duk__tvdst = DUK__REGP_A(ins); \
		DUK_TVAL_SET_BOOLEAN_UPDREF(thr, duk__tvdst, duk__bval); \
		break; \
	}
#endif

		/* XXX: 12 + 12 bit variant might make sense too, for both reg and
		 * const loads.
		 */

		/* For LDREG, STREG, LDCONST footprint optimized variants would just
		 * duk_dup() + duk_replace(), but because they're used quite a lot
		 * they're currently intentionally not size optimized.
		 */
		case DUK_OP_LDREG: {
			duk_tval *tv1, *tv2;

			tv1 = DUK__REGP_A(ins);
			tv2 = DUK__REGP_BC(ins);
			DUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv1, tv2);  /* side effects */
			break;
		}

		case DUK_OP_STREG: {
			duk_tval *tv1, *tv2;

			tv1 = DUK__REGP_A(ins);
			tv2 = DUK__REGP_BC(ins);
			DUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv2, tv1);  /* side effects */
			break;
		}

		case DUK_OP_LDCONST: {
			duk_tval *tv1, *tv2;

			tv1 = DUK__REGP_A(ins);
			tv2 = DUK__CONSTP_BC(ins);
			DUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv1, tv2);  /* side effects */
			break;
		}

		/* LDINT and LDINTX are intended to load an arbitrary signed
		 * 32-bit value.  Only an LDINT+LDINTX sequence is supported.
		 * This also guarantees all values remain fastints.
		 */
#if defined(DUK_USE_EXEC_PREFER_SIZE)
		case DUK_OP_LDINT: {
			duk_int32_t val;

			val = (duk_int32_t) DUK_DEC_BC(ins) - (duk_int32_t) DUK_BC_LDINT_BIAS;
			duk_push_int(thr, val);
			DUK__REPLACE_TOP_A_BREAK();
		}
		case DUK_OP_LDINTX: {
			duk_int32_t val;

			val = (duk_int32_t) duk_get_int(thr, DUK_DEC_A(ins));
			val = (val << DUK_BC_LDINTX_SHIFT) + (duk_int32_t) DUK_DEC_BC(ins);  /* no bias */
			duk_push_int(thr, val);
			DUK__REPLACE_TOP_A_BREAK();
		}
#else  /* DUK_USE_EXEC_PREFER_SIZE */
		case DUK_OP_LDINT: {
			duk_tval *tv1;
			duk_int32_t val;

			val = (duk_int32_t) DUK_DEC_BC(ins) - (duk_int32_t) DUK_BC_LDINT_BIAS;
			tv1 = DUK__REGP_A(ins);
			DUK_TVAL_SET_I32_UPDREF(thr, tv1, val);  /* side effects */
			break;
		}
		case DUK_OP_LDINTX: {
			duk_tval *tv1;
			duk_int32_t val;

			tv1 = DUK__REGP_A(ins);
			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv1));
#if defined(DUK_USE_FASTINT)
			DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv1));
			val = DUK_TVAL_GET_FASTINT_I32(tv1);
#else
			/* XXX: fast double-to-int conversion, we know number is integer in [-0x80000000,0xffffffff]. */
			val = (duk_int32_t) DUK_TVAL_GET_NUMBER(tv1);
#endif
			val = (duk_int32_t) ((duk_uint32_t) val << DUK_BC_LDINTX_SHIFT) + (duk_int32_t) DUK_DEC_BC(ins);  /* no bias */
			DUK_TVAL_SET_I32_UPDREF(thr, tv1, val);  /* side effects */
			break;
		}
#endif  /* DUK_USE_EXEC_PREFER_SIZE */

#if defined(DUK_USE_EXEC_PREFER_SIZE)
		case DUK_OP_LDTHIS: {
			duk_push_this(thr);
			DUK__REPLACE_TOP_BC_BREAK();
		}
		case DUK_OP_LDUNDEF: {
			duk_to_undefined(thr, (duk_idx_t) DUK_DEC_BC(ins));
			break;
		}
		case DUK_OP_LDNULL: {
			duk_to_null(thr, (duk_idx_t) DUK_DEC_BC(ins));
			break;
		}
		case DUK_OP_LDTRUE: {
			duk_push_true(thr);
			DUK__REPLACE_TOP_BC_BREAK();
		}
		case DUK_OP_LDFALSE: {
			duk_push_false(thr);
			DUK__REPLACE_TOP_BC_BREAK();
		}
#else  /* DUK_USE_EXEC_PREFER_SIZE */
		case DUK_OP_LDTHIS: {
			/* Note: 'this' may be bound to any value, not just an object */
			duk_tval *tv1, *tv2;

			tv1 = DUK__REGP_BC(ins);
			tv2 = thr->valstack_bottom - 1;  /* 'this binding' is just under bottom */
			DUK_ASSERT(tv2 >= thr->valstack);
			DUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv1, tv2);  /* side effects */
			break;
		}
		case DUK_OP_LDUNDEF: {
			duk_tval *tv1;

			tv1 = DUK__REGP_BC(ins);
			DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv1);  /* side effects */
			break;
		}
		case DUK_OP_LDNULL: {
			duk_tval *tv1;

			tv1 = DUK__REGP_BC(ins);
			DUK_TVAL_SET_NULL_UPDREF(thr, tv1);  /* side effects */
			break;
		}
		case DUK_OP_LDTRUE: {
			duk_tval *tv1;

			tv1 = DUK__REGP_BC(ins);
			DUK_TVAL_SET_BOOLEAN_UPDREF(thr, tv1, 1);  /* side effects */
			break;
		}
		case DUK_OP_LDFALSE: {
			duk_tval *tv1;

			tv1 = DUK__REGP_BC(ins);
			DUK_TVAL_SET_BOOLEAN_UPDREF(thr, tv1, 0);  /* side effects */
			break;
		}
#endif  /* DUK_USE_EXEC_PREFER_SIZE */

		case DUK_OP_BNOT: {
			duk__vm_bitwise_not(thr, DUK_DEC_BC(ins), DUK_DEC_A(ins));
			break;
		}

		case DUK_OP_LNOT: {
			duk__vm_logical_not(thr, DUK_DEC_BC(ins), DUK_DEC_A(ins));
			break;
		}

#if defined(DUK_USE_EXEC_PREFER_SIZE)
		case DUK_OP_UNM:
		case DUK_OP_UNP: {
			duk__vm_arith_unary_op(thr, DUK_DEC_BC(ins), DUK_DEC_A(ins), op);
			break;
		}
#else  /* DUK_USE_EXEC_PREFER_SIZE */
		case DUK_OP_UNM: {
			duk__vm_arith_unary_op(thr, DUK_DEC_BC(ins), DUK_DEC_A(ins), DUK_OP_UNM);
			break;
		}
		case DUK_OP_UNP: {
			duk__vm_arith_unary_op(thr, DUK_DEC_BC(ins), DUK_DEC_A(ins), DUK_OP_UNP);
			break;
		}
#endif  /* DUK_USE_EXEC_PREFER_SIZE */

#if defined(DUK_USE_EXEC_PREFER_SIZE)
		case DUK_OP_TYPEOF: {
			duk_small_uint_t stridx;

			stridx = duk_js_typeof_stridx(DUK__REGP_BC(ins));
			DUK_ASSERT_STRIDX_VALID(stridx);
			duk_push_hstring_stridx(thr, stridx);
			DUK__REPLACE_TOP_A_BREAK();
		}
#else  /* DUK_USE_EXEC_PREFER_SIZE */
		case DUK_OP_TYPEOF: {
			duk_tval *tv;
			duk_small_uint_t stridx;
			duk_hstring *h_str;

			tv = DUK__REGP_BC(ins);
			stridx = duk_js_typeof_stridx(tv);
			DUK_ASSERT_STRIDX_VALID(stridx);
			h_str = DUK_HTHREAD_GET_STRING(thr, stridx);
			tv = DUK__REGP_A(ins);
			DUK_TVAL_SET_STRING_UPDREF(thr, tv, h_str);
			break;
		}
#endif  /* DUK_USE_EXEC_PREFER_SIZE */

		case DUK_OP_TYPEOFID: {
			duk_small_uint_t stridx;
#if !defined(DUK_USE_EXEC_PREFER_SIZE)
			duk_hstring *h_str;
#endif
			duk_activation *act;
			duk_hstring *name;
			duk_tval *tv;

			/* A -> target register
			 * BC -> constant index of identifier name
			 */

			tv = DUK__CONSTP_BC(ins);
			DUK_ASSERT(DUK_TVAL_IS_STRING(tv));
			name = DUK_TVAL_GET_STRING(tv);
			tv = NULL;  /* lookup has side effects */
			act = thr->callstack_curr;
			if (duk_js_getvar_activation(thr, act, name, 0 /*throw*/)) {
				/* -> [... val this] */
				tv = DUK_GET_TVAL_NEGIDX(thr, -2);
				stridx = duk_js_typeof_stridx(tv);
				tv = NULL;  /* no longer needed */
				duk_pop_2_unsafe(thr);
			} else {
				/* unresolvable, no stack changes */
				stridx = DUK_STRIDX_LC_UNDEFINED;
			}
			DUK_ASSERT_STRIDX_VALID(stridx);
#if defined(DUK_USE_EXEC_PREFER_SIZE)
			duk_push_hstring_stridx(thr, stridx);
			DUK__REPLACE_TOP_A_BREAK();
#else  /* DUK_USE_EXEC_PREFER_SIZE */
			h_str = DUK_HTHREAD_GET_STRING(thr, stridx);
			tv = DUK__REGP_A(ins);
			DUK_TVAL_SET_STRING_UPDREF(thr, tv, h_str);
			break;
#endif  /* DUK_USE_EXEC_PREFER_SIZE */
		}

		/* Equality: E5 Sections 11.9.1, 11.9.3 */

#define DUK__EQ_BODY(barg,carg) { \
		duk_bool_t tmp; \
		tmp = duk_js_equals(thr, (barg), (carg)); \
		DUK_ASSERT(tmp == 0 || tmp == 1); \
		DUK__REPLACE_BOOL_A_BREAK(tmp); \
	}
#define DUK__NEQ_BODY(barg,carg) { \
		duk_bool_t tmp; \
		tmp = duk_js_equals(thr, (barg), (carg)); \
		DUK_ASSERT(tmp == 0 || tmp == 1); \
		tmp ^= 1; \
		DUK__REPLACE_BOOL_A_BREAK(tmp); \
	}
#define DUK__SEQ_BODY(barg,carg) { \
		duk_bool_t tmp; \
		tmp = duk_js_strict_equals((barg), (carg)); \
		DUK_ASSERT(tmp == 0 || tmp == 1); \
		DUK__REPLACE_BOOL_A_BREAK(tmp); \
	}
#define DUK__SNEQ_BODY(barg,carg) { \
		duk_bool_t tmp; \
		tmp = duk_js_strict_equals((barg), (carg)); \
		DUK_ASSERT(tmp == 0 || tmp == 1); \
		tmp ^= 1; \
		DUK__REPLACE_BOOL_A_BREAK(tmp); \
	}
#if defined(DUK_USE_EXEC_PREFER_SIZE)
		case DUK_OP_EQ_RR:
		case DUK_OP_EQ_CR:
		case DUK_OP_EQ_RC:
		case DUK_OP_EQ_CC:
			DUK__EQ_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
		case DUK_OP_NEQ_RR:
		case DUK_OP_NEQ_CR:
		case DUK_OP_NEQ_RC:
		case DUK_OP_NEQ_CC:
			DUK__NEQ_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
		case DUK_OP_SEQ_RR:
		case DUK_OP_SEQ_CR:
		case DUK_OP_SEQ_RC:
		case DUK_OP_SEQ_CC:
			DUK__SEQ_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
		case DUK_OP_SNEQ_RR:
		case DUK_OP_SNEQ_CR:
		case DUK_OP_SNEQ_RC:
		case DUK_OP_SNEQ_CC:
			DUK__SNEQ_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
#else  /* DUK_USE_EXEC_PREFER_SIZE */
		case DUK_OP_EQ_RR:
			DUK__EQ_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
		case DUK_OP_EQ_CR:
			DUK__EQ_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
		case DUK_OP_EQ_RC:
			DUK__EQ_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
		case DUK_OP_EQ_CC:
			DUK__EQ_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
		case DUK_OP_NEQ_RR:
			DUK__NEQ_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
		case DUK_OP_NEQ_CR:
			DUK__NEQ_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
		case DUK_OP_NEQ_RC:
			DUK__NEQ_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
		case DUK_OP_NEQ_CC:
			DUK__NEQ_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
		case DUK_OP_SEQ_RR:
			DUK__SEQ_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
		case DUK_OP_SEQ_CR:
			DUK__SEQ_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
		case DUK_OP_SEQ_RC:
			DUK__SEQ_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
		case DUK_OP_SEQ_CC:
			DUK__SEQ_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
		case DUK_OP_SNEQ_RR:
			DUK__SNEQ_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
		case DUK_OP_SNEQ_CR:
			DUK__SNEQ_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
		case DUK_OP_SNEQ_RC:
			DUK__SNEQ_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
		case DUK_OP_SNEQ_CC:
			DUK__SNEQ_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
#endif  /* DUK_USE_EXEC_PREFER_SIZE */

#define DUK__COMPARE_BODY(arg1,arg2,flags) { \
		duk_bool_t tmp; \
		tmp = duk_js_compare_helper(thr, (arg1), (arg2), (flags)); \
		DUK_ASSERT(tmp == 0 || tmp == 1); \
		DUK__REPLACE_BOOL_A_BREAK(tmp); \
	}
#define DUK__GT_BODY(barg,carg) DUK__COMPARE_BODY((carg), (barg), 0)
#define DUK__GE_BODY(barg,carg) DUK__COMPARE_BODY((barg), (carg), DUK_COMPARE_FLAG_EVAL_LEFT_FIRST | DUK_COMPARE_FLAG_NEGATE)
#define DUK__LT_BODY(barg,carg) DUK__COMPARE_BODY((barg), (carg), DUK_COMPARE_FLAG_EVAL_LEFT_FIRST)
#define DUK__LE_BODY(barg,carg) DUK__COMPARE_BODY((carg), (barg), DUK_COMPARE_FLAG_NEGATE)
#if defined(DUK_USE_EXEC_PREFER_SIZE)
		case DUK_OP_GT_RR:
		case DUK_OP_GT_CR:
		case DUK_OP_GT_RC:
		case DUK_OP_GT_CC:
			DUK__GT_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
		case DUK_OP_GE_RR:
		case DUK_OP_GE_CR:
		case DUK_OP_GE_RC:
		case DUK_OP_GE_CC:
			DUK__GE_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
		case DUK_OP_LT_RR:
		case DUK_OP_LT_CR:
		case DUK_OP_LT_RC:
		case DUK_OP_LT_CC:
			DUK__LT_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
		case DUK_OP_LE_RR:
		case DUK_OP_LE_CR:
		case DUK_OP_LE_RC:
		case DUK_OP_LE_CC:
			DUK__LE_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
#else  /* DUK_USE_EXEC_PREFER_SIZE */
		case DUK_OP_GT_RR:
			DUK__GT_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
		case DUK_OP_GT_CR:
			DUK__GT_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
		case DUK_OP_GT_RC:
			DUK__GT_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
		case DUK_OP_GT_CC:
			DUK__GT_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
		case DUK_OP_GE_RR:
			DUK__GE_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
		case DUK_OP_GE_CR:
			DUK__GE_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
		case DUK_OP_GE_RC:
			DUK__GE_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
		case DUK_OP_GE_CC:
			DUK__GE_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
		case DUK_OP_LT_RR:
			DUK__LT_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
		case DUK_OP_LT_CR:
			DUK__LT_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
		case DUK_OP_LT_RC:
			DUK__LT_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
		case DUK_OP_LT_CC:
			DUK__LT_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
		case DUK_OP_LE_RR:
			DUK__LE_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
		case DUK_OP_LE_CR:
			DUK__LE_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
		case DUK_OP_LE_RC:
			DUK__LE_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
		case DUK_OP_LE_CC:
			DUK__LE_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
#endif  /* DUK_USE_EXEC_PREFER_SIZE */

		/* No size optimized variant at present for IF. */
		case DUK_OP_IFTRUE_R: {
			if (duk_js_toboolean(DUK__REGP_BC(ins)) != 0) {
				curr_pc++;
			}
			break;
		}
		case DUK_OP_IFTRUE_C: {
			if (duk_js_toboolean(DUK__CONSTP_BC(ins)) != 0) {
				curr_pc++;
			}
			break;
		}
		case DUK_OP_IFFALSE_R: {
			if (duk_js_toboolean(DUK__REGP_BC(ins)) == 0) {
				curr_pc++;
			}
			break;
		}
		case DUK_OP_IFFALSE_C: {
			if (duk_js_toboolean(DUK__CONSTP_BC(ins)) == 0) {
				curr_pc++;
			}
			break;
		}

#if defined(DUK_USE_EXEC_PREFER_SIZE)
		case DUK_OP_ADD_RR:
		case DUK_OP_ADD_CR:
		case DUK_OP_ADD_RC:
		case DUK_OP_ADD_CC: {
			/* XXX: could leave value on stack top and goto replace_top_a; */
			duk__vm_arith_add(thr, DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins), DUK_DEC_A(ins));
			break;
		}
#else  /* DUK_USE_EXEC_PREFER_SIZE */
		case DUK_OP_ADD_RR: {
			duk__vm_arith_add(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins));
			break;
		}
		case DUK_OP_ADD_CR: {
			duk__vm_arith_add(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins));
			break;
		}
		case DUK_OP_ADD_RC: {
			duk__vm_arith_add(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins));
			break;
		}
		case DUK_OP_ADD_CC: {
			duk__vm_arith_add(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins));
			break;
		}
#endif  /* DUK_USE_EXEC_PREFER_SIZE */

#if defined(DUK_USE_EXEC_PREFER_SIZE)
		case DUK_OP_SUB_RR:
		case DUK_OP_SUB_CR:
		case DUK_OP_SUB_RC:
		case DUK_OP_SUB_CC:
		case DUK_OP_MUL_RR:
		case DUK_OP_MUL_CR:
		case DUK_OP_MUL_RC:
		case DUK_OP_MUL_CC:
		case DUK_OP_DIV_RR:
		case DUK_OP_DIV_CR:
		case DUK_OP_DIV_RC:
		case DUK_OP_DIV_CC:
		case DUK_OP_MOD_RR:
		case DUK_OP_MOD_CR:
		case DUK_OP_MOD_RC:
		case DUK_OP_MOD_CC:
#if defined(DUK_USE_ES7_EXP_OPERATOR)
		case DUK_OP_EXP_RR:
		case DUK_OP_EXP_CR:
		case DUK_OP_EXP_RC:
		case DUK_OP_EXP_CC:
#endif  /* DUK_USE_ES7_EXP_OPERATOR */
		{
			/* XXX: could leave value on stack top and goto replace_top_a; */
			duk__vm_arith_binary_op(thr, DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins), DUK_DEC_A(ins), op);
			break;
		}
#else  /* DUK_USE_EXEC_PREFER_SIZE */
		case DUK_OP_SUB_RR: {
			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_SUB);
			break;
		}
		case DUK_OP_SUB_CR: {
			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_SUB);
			break;
		}
		case DUK_OP_SUB_RC: {
			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_SUB);
			break;
		}
		case DUK_OP_SUB_CC: {
			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_SUB);
			break;
		}
		case DUK_OP_MUL_RR: {
			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_MUL);
			break;
		}
		case DUK_OP_MUL_CR: {
			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_MUL);
			break;
		}
		case DUK_OP_MUL_RC: {
			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_MUL);
			break;
		}
		case DUK_OP_MUL_CC: {
			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_MUL);
			break;
		}
		case DUK_OP_DIV_RR: {
			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_DIV);
			break;
		}
		case DUK_OP_DIV_CR: {
			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_DIV);
			break;
		}
		case DUK_OP_DIV_RC: {
			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_DIV);
			break;
		}
		case DUK_OP_DIV_CC: {
			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_DIV);
			break;
		}
		case DUK_OP_MOD_RR: {
			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_MOD);
			break;
		}
		case DUK_OP_MOD_CR: {
			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_MOD);
			break;
		}
		case DUK_OP_MOD_RC: {
			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_MOD);
			break;
		}
		case DUK_OP_MOD_CC: {
			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_MOD);
			break;
		}
#if defined(DUK_USE_ES7_EXP_OPERATOR)
		case DUK_OP_EXP_RR: {
			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_EXP);
			break;
		}
		case DUK_OP_EXP_CR: {
			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_EXP);
			break;
		}
		case DUK_OP_EXP_RC: {
			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_EXP);
			break;
		}
		case DUK_OP_EXP_CC: {
			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_EXP);
			break;
		}
#endif  /* DUK_USE_ES7_EXP_OPERATOR */
#endif  /* DUK_USE_EXEC_PREFER_SIZE */

#if defined(DUK_USE_EXEC_PREFER_SIZE)
		case DUK_OP_BAND_RR:
		case DUK_OP_BAND_CR:
		case DUK_OP_BAND_RC:
		case DUK_OP_BAND_CC:
		case DUK_OP_BOR_RR:
		case DUK_OP_BOR_CR:
		case DUK_OP_BOR_RC:
		case DUK_OP_BOR_CC:
		case DUK_OP_BXOR_RR:
		case DUK_OP_BXOR_CR:
		case DUK_OP_BXOR_RC:
		case DUK_OP_BXOR_CC:
		case DUK_OP_BASL_RR:
		case DUK_OP_BASL_CR:
		case DUK_OP_BASL_RC:
		case DUK_OP_BASL_CC:
		case DUK_OP_BLSR_RR:
		case DUK_OP_BLSR_CR:
		case DUK_OP_BLSR_RC:
		case DUK_OP_BLSR_CC:
		case DUK_OP_BASR_RR:
		case DUK_OP_BASR_CR:
		case DUK_OP_BASR_RC:
		case DUK_OP_BASR_CC: {
			/* XXX: could leave value on stack top and goto replace_top_a; */
			duk__vm_bitwise_binary_op(thr, DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins), DUK_DEC_A(ins), op);
			break;
		}
#else  /* DUK_USE_EXEC_PREFER_SIZE */
		case DUK_OP_BAND_RR: {
			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BAND);
			break;
		}
		case DUK_OP_BAND_CR: {
			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BAND);
			break;
		}
		case DUK_OP_BAND_RC: {
			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BAND);
			break;
		}
		case DUK_OP_BAND_CC: {
			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BAND);
			break;
		}
		case DUK_OP_BOR_RR: {
			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BOR);
			break;
		}
		case DUK_OP_BOR_CR: {
			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BOR);
			break;
		}
		case DUK_OP_BOR_RC: {
			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BOR);
			break;
		}
		case DUK_OP_BOR_CC: {
			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BOR);
			break;
		}
		case DUK_OP_BXOR_RR: {
			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BXOR);
			break;
		}
		case DUK_OP_BXOR_CR: {
			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BXOR);
			break;
		}
		case DUK_OP_BXOR_RC: {
			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BXOR);
			break;
		}
		case DUK_OP_BXOR_CC: {
			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BXOR);
			break;
		}
		case DUK_OP_BASL_RR: {
			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BASL);
			break;
		}
		case DUK_OP_BASL_CR: {
			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BASL);
			break;
		}
		case DUK_OP_BASL_RC: {
			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BASL);
			break;
		}
		case DUK_OP_BASL_CC: {
			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BASL);
			break;
		}
		case DUK_OP_BLSR_RR: {
			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BLSR);
			break;
		}
		case DUK_OP_BLSR_CR: {
			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BLSR);
			break;
		}
		case DUK_OP_BLSR_RC: {
			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BLSR);
			break;
		}
		case DUK_OP_BLSR_CC: {
			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BLSR);
			break;
		}
		case DUK_OP_BASR_RR: {
			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BASR);
			break;
		}
		case DUK_OP_BASR_CR: {
			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BASR);
			break;
		}
		case DUK_OP_BASR_RC: {
			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BASR);
			break;
		}
		case DUK_OP_BASR_CC: {
			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BASR);
			break;
		}
#endif  /* DUK_USE_EXEC_PREFER_SIZE */

		/* For INSTOF and IN, B is always a register. */
#define DUK__INSTOF_BODY(barg,carg) { \
		duk_bool_t tmp; \
		tmp = duk_js_instanceof(thr, (barg), (carg)); \
		DUK_ASSERT(tmp == 0 || tmp == 1); \
		DUK__REPLACE_BOOL_A_BREAK(tmp); \
	}
#define DUK__IN_BODY(barg,carg) { \
		duk_bool_t tmp; \
		tmp = duk_js_in(thr, (barg), (carg)); \
		DUK_ASSERT(tmp == 0 || tmp == 1); \
		DUK__REPLACE_BOOL_A_BREAK(tmp); \
	}
#if defined(DUK_USE_EXEC_PREFER_SIZE)
		case DUK_OP_INSTOF_RR:
		case DUK_OP_INSTOF_CR:
		case DUK_OP_INSTOF_RC:
		case DUK_OP_INSTOF_CC:
			DUK__INSTOF_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
		case DUK_OP_IN_RR:
		case DUK_OP_IN_CR:
		case DUK_OP_IN_RC:
		case DUK_OP_IN_CC:
			DUK__IN_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
#else  /* DUK_USE_EXEC_PREFER_SIZE */
		case DUK_OP_INSTOF_RR:
			DUK__INSTOF_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
		case DUK_OP_INSTOF_CR:
			DUK__INSTOF_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
		case DUK_OP_INSTOF_RC:
			DUK__INSTOF_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
		case DUK_OP_INSTOF_CC:
			DUK__INSTOF_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
		case DUK_OP_IN_RR:
			DUK__IN_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
		case DUK_OP_IN_CR:
			DUK__IN_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
		case DUK_OP_IN_RC:
			DUK__IN_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
		case DUK_OP_IN_CC:
			DUK__IN_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
#endif  /* DUK_USE_EXEC_PREFER_SIZE */

		/* Pre/post inc/dec for register variables, important for loops. */
#if defined(DUK_USE_EXEC_PREFER_SIZE)
		case DUK_OP_PREINCR:
		case DUK_OP_PREDECR:
		case DUK_OP_POSTINCR:
		case DUK_OP_POSTDECR: {
			duk__prepost_incdec_reg_helper(thr, DUK__REGP_A(ins), DUK__REGP_BC(ins), op);
			break;
		}
		case DUK_OP_PREINCV:
		case DUK_OP_PREDECV:
		case DUK_OP_POSTINCV:
		case DUK_OP_POSTDECV: {
			duk__prepost_incdec_var_helper(thr, DUK_DEC_A(ins), DUK__CONSTP_BC(ins), op, DUK__STRICT());
			break;
		}
#else  /* DUK_USE_EXEC_PREFER_SIZE */
		case DUK_OP_PREINCR: {
			duk__prepost_incdec_reg_helper(thr, DUK__REGP_A(ins), DUK__REGP_BC(ins), DUK_OP_PREINCR);
			break;
		}
		case DUK_OP_PREDECR: {
			duk__prepost_incdec_reg_helper(thr, DUK__REGP_A(ins), DUK__REGP_BC(ins), DUK_OP_PREDECR);
			break;
		}
		case DUK_OP_POSTINCR: {
			duk__prepost_incdec_reg_helper(thr, DUK__REGP_A(ins), DUK__REGP_BC(ins), DUK_OP_POSTINCR);
			break;
		}
		case DUK_OP_POSTDECR: {
			duk__prepost_incdec_reg_helper(thr, DUK__REGP_A(ins), DUK__REGP_BC(ins), DUK_OP_POSTDECR);
			break;
		}
		case DUK_OP_PREINCV: {
			duk__prepost_incdec_var_helper(thr, DUK_DEC_A(ins), DUK__CONSTP_BC(ins), DUK_OP_PREINCV, DUK__STRICT());
			break;
		}
		case DUK_OP_PREDECV: {
			duk__prepost_incdec_var_helper(thr, DUK_DEC_A(ins), DUK__CONSTP_BC(ins), DUK_OP_PREDECV, DUK__STRICT());
			break;
		}
		case DUK_OP_POSTINCV: {
			duk__prepost_incdec_var_helper(thr, DUK_DEC_A(ins), DUK__CONSTP_BC(ins), DUK_OP_POSTINCV, DUK__STRICT());
			break;
		}
		case DUK_OP_POSTDECV: {
			duk__prepost_incdec_var_helper(thr, DUK_DEC_A(ins), DUK__CONSTP_BC(ins), DUK_OP_POSTDECV, DUK__STRICT());
			break;
		}
#endif  /* DUK_USE_EXEC_PREFER_SIZE */

		/* XXX: Move to separate helper, optimize for perf/size separately. */
		/* Preinc/predec for object properties. */
		case DUK_OP_PREINCP_RR:
		case DUK_OP_PREINCP_CR:
		case DUK_OP_PREINCP_RC:
		case DUK_OP_PREINCP_CC:
		case DUK_OP_PREDECP_RR:
		case DUK_OP_PREDECP_CR:
		case DUK_OP_PREDECP_RC:
		case DUK_OP_PREDECP_CC:
		case DUK_OP_POSTINCP_RR:
		case DUK_OP_POSTINCP_CR:
		case DUK_OP_POSTINCP_RC:
		case DUK_OP_POSTINCP_CC:
		case DUK_OP_POSTDECP_RR:
		case DUK_OP_POSTDECP_CR:
		case DUK_OP_POSTDECP_RC:
		case DUK_OP_POSTDECP_CC: {
			duk_tval *tv_obj;
			duk_tval *tv_key;
			duk_tval *tv_val;
			duk_bool_t rc;
			duk_double_t x, y, z;
#if !defined(DUK_USE_EXEC_PREFER_SIZE)
			duk_tval *tv_dst;
#endif  /* DUK_USE_EXEC_PREFER_SIZE */

			/* A -> target reg
			 * B -> object reg/const (may be const e.g. in "'foo'[1]")
			 * C -> key reg/const
			 */

			/* Opcode bits 0-1 are used to distinguish reg/const variants.
			 * Opcode bits 2-3 are used to distinguish inc/dec variants:
			 * Bit 2 = inc(0)/dec(1), bit 3 = pre(0)/post(1).
			 */
			DUK_ASSERT((DUK_OP_PREINCP_RR & 0x0c) == 0x00);
			DUK_ASSERT((DUK_OP_PREDECP_RR & 0x0c) == 0x04);
			DUK_ASSERT((DUK_OP_POSTINCP_RR & 0x0c) == 0x08);
			DUK_ASSERT((DUK_OP_POSTDECP_RR & 0x0c) == 0x0c);

			tv_obj = DUK__REGCONSTP_B(ins);
			tv_key = DUK__REGCONSTP_C(ins);
			rc = duk_hobject_getprop(thr, tv_obj, tv_key);  /* -> [val] */
			DUK_UNREF(rc);  /* ignore */
			tv_obj = NULL;  /* invalidated */
			tv_key = NULL;  /* invalidated */

			/* XXX: Fastint fast path would be useful here.  Also fastints
			 * now lose their fastint status in current handling which is
			 * not intuitive.
			 */

			x = duk_to_number_m1(thr);
			duk_pop_unsafe(thr);
			if (ins & DUK_BC_INCDECP_FLAG_DEC) {
				y = x - 1.0;
			} else {
				y = x + 1.0;
			}

			duk_push_number(thr, y);
			tv_val = DUK_GET_TVAL_NEGIDX(thr, -1);
			DUK_ASSERT(tv_val != NULL);
			tv_obj = DUK__REGCONSTP_B(ins);
			tv_key = DUK__REGCONSTP_C(ins);
			rc = duk_hobject_putprop(thr, tv_obj, tv_key, tv_val, DUK__STRICT());
			DUK_UNREF(rc);  /* ignore */
			tv_obj = NULL;  /* invalidated */
			tv_key = NULL;  /* invalidated */
			duk_pop_unsafe(thr);

			z = (ins & DUK_BC_INCDECP_FLAG_POST) ? x : y;
#if defined(DUK_USE_EXEC_PREFER_SIZE)
			duk_push_number(thr, z);
			DUK__REPLACE_TOP_A_BREAK();
#else
			tv_dst = DUK__REGP_A(ins);
			DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_dst, z);
			break;
#endif
		}

		/* XXX: GETPROP where object is 'this', GETPROPT?
		 * Occurs relatively often in object oriented code.
		 */

#define DUK__GETPROP_BODY(barg,carg) { \
		/* A -> target reg \
		 * B -> object reg/const (may be const e.g. in "'foo'[1]") \
		 * C -> key reg/const \
		 */ \
		(void) duk_hobject_getprop(thr, (barg), (carg)); \
		DUK__REPLACE_TOP_A_BREAK(); \
	}
#define DUK__GETPROPC_BODY(barg,carg) { \
		/* Same as GETPROP but callability check for property-based calls. */ \
		duk_tval *tv__targ; \
		(void) duk_hobject_getprop(thr, (barg), (carg)); \
		DUK_GC_TORTURE(thr->heap); \
		tv__targ = DUK_GET_TVAL_NEGIDX(thr, -1); \
		if (DUK_UNLIKELY(!duk_is_callable_tval(thr, tv__targ))) { \
			/* Here we intentionally re-evaluate the macro \
			 * arguments to deal with potentially changed \
			 * valstack base pointer! \
			 */ \
			duk_call_setup_propcall_error(thr, (barg), (carg)); \
		} \
		DUK__REPLACE_TOP_A_BREAK(); \
	}
#define DUK__PUTPROP_BODY(aarg,barg,carg) { \
		/* A -> object reg \
		 * B -> key reg/const \
		 * C -> value reg/const \
		 * \
		 * Note: intentional difference to register arrangement \
		 * of e.g. GETPROP; 'A' must contain a register-only value. \
		 */ \
		(void) duk_hobject_putprop(thr, (aarg), (barg), (carg), DUK__STRICT()); \
		break; \
	}
#define DUK__DELPROP_BODY(barg,carg) { \
		/* A -> result reg \
		 * B -> object reg \
		 * C -> key reg/const \
		 */ \
		duk_bool_t rc; \
		rc = duk_hobject_delprop(thr, (barg), (carg), DUK__STRICT()); \
		DUK_ASSERT(rc == 0 || rc == 1); \
		DUK__REPLACE_BOOL_A_BREAK(rc); \
	}
#if defined(DUK_USE_EXEC_PREFER_SIZE)
		case DUK_OP_GETPROP_RR:
		case DUK_OP_GETPROP_CR:
		case DUK_OP_GETPROP_RC:
		case DUK_OP_GETPROP_CC:
			DUK__GETPROP_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
#if defined(DUK_USE_VERBOSE_ERRORS)
		case DUK_OP_GETPROPC_RR:
		case DUK_OP_GETPROPC_CR:
		case DUK_OP_GETPROPC_RC:
		case DUK_OP_GETPROPC_CC:
			DUK__GETPROPC_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
#endif
		case DUK_OP_PUTPROP_RR:
		case DUK_OP_PUTPROP_CR:
		case DUK_OP_PUTPROP_RC:
		case DUK_OP_PUTPROP_CC:
			DUK__PUTPROP_BODY(DUK__REGP_A(ins), DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
		case DUK_OP_DELPROP_RR:
		case DUK_OP_DELPROP_RC:  /* B is always reg */
			DUK__DELPROP_BODY(DUK__REGP_B(ins), DUK__REGCONSTP_C(ins));
#else  /* DUK_USE_EXEC_PREFER_SIZE */
		case DUK_OP_GETPROP_RR:
			DUK__GETPROP_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
		case DUK_OP_GETPROP_CR:
			DUK__GETPROP_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
		case DUK_OP_GETPROP_RC:
			DUK__GETPROP_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
		case DUK_OP_GETPROP_CC:
			DUK__GETPROP_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
#if defined(DUK_USE_VERBOSE_ERRORS)
		case DUK_OP_GETPROPC_RR:
			DUK__GETPROPC_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
		case DUK_OP_GETPROPC_CR:
			DUK__GETPROPC_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
		case DUK_OP_GETPROPC_RC:
			DUK__GETPROPC_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
		case DUK_OP_GETPROPC_CC:
			DUK__GETPROPC_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
#endif
		case DUK_OP_PUTPROP_RR:
			DUK__PUTPROP_BODY(DUK__REGP_A(ins), DUK__REGP_B(ins), DUK__REGP_C(ins));
		case DUK_OP_PUTPROP_CR:
			DUK__PUTPROP_BODY(DUK__REGP_A(ins), DUK__CONSTP_B(ins), DUK__REGP_C(ins));
		case DUK_OP_PUTPROP_RC:
			DUK__PUTPROP_BODY(DUK__REGP_A(ins), DUK__REGP_B(ins), DUK__CONSTP_C(ins));
		case DUK_OP_PUTPROP_CC:
			DUK__PUTPROP_BODY(DUK__REGP_A(ins), DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
		case DUK_OP_DELPROP_RR:  /* B is always reg */
			DUK__DELPROP_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
		case DUK_OP_DELPROP_RC:
			DUK__DELPROP_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
#endif  /* DUK_USE_EXEC_PREFER_SIZE */

		/* No fast path for DECLVAR now, it's quite a rare instruction. */
		case DUK_OP_DECLVAR_RR:
		case DUK_OP_DECLVAR_CR:
		case DUK_OP_DECLVAR_RC:
		case DUK_OP_DECLVAR_CC: {
			duk_activation *act;
			duk_small_uint_fast_t a = DUK_DEC_A(ins);
			duk_tval *tv1;
			duk_hstring *name;
			duk_small_uint_t prop_flags;
			duk_bool_t is_func_decl;

			tv1 = DUK__REGCONSTP_B(ins);
			DUK_ASSERT(DUK_TVAL_IS_STRING(tv1));
			name = DUK_TVAL_GET_STRING(tv1);
			DUK_ASSERT(name != NULL);

			is_func_decl = ((a & DUK_BC_DECLVAR_FLAG_FUNC_DECL) != 0);

			/* XXX: declvar takes an duk_tval pointer, which is awkward and
			 * should be reworked.
			 */

			/* Compiler is responsible for selecting property flags (configurability,
			 * writability, etc).
			 */
			prop_flags = a & DUK_PROPDESC_FLAGS_MASK;

			if (is_func_decl) {
				duk_push_tval(thr, DUK__REGCONSTP_C(ins));
			} else {
				DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top));  /* valstack policy */
				thr->valstack_top++;
			}
			tv1 = DUK_GET_TVAL_NEGIDX(thr, -1);

			act = thr->callstack_curr;
			if (duk_js_declvar_activation(thr, act, name, tv1, prop_flags, is_func_decl)) {
				if (is_func_decl) {
					/* Already declared, update value. */
					tv1 = DUK_GET_TVAL_NEGIDX(thr, -1);
					duk_js_putvar_activation(thr, act, name, tv1, DUK__STRICT());
				} else {
					/* Already declared but no initializer value
					 * (e.g. 'var xyz;'), no-op.
					 */
				}
			}

			duk_pop_unsafe(thr);
			break;
		}

#if defined(DUK_USE_REGEXP_SUPPORT)
		/* The compiler should never emit DUK_OP_REGEXP if there is no
		 * regexp support.
		 */
		case DUK_OP_REGEXP_RR:
		case DUK_OP_REGEXP_CR:
		case DUK_OP_REGEXP_RC:
		case DUK_OP_REGEXP_CC: {
			/* A -> target register
			 * B -> bytecode (also contains flags)
			 * C -> escaped source
			 */

			duk_push_tval(thr, DUK__REGCONSTP_C(ins));
			duk_push_tval(thr, DUK__REGCONSTP_B(ins));  /* -> [ ... escaped_source bytecode ] */
			duk_regexp_create_instance(thr);   /* -> [ ... regexp_instance ] */
			DUK__REPLACE_TOP_A_BREAK();
		}
#endif  /* DUK_USE_REGEXP_SUPPORT */

		/* XXX: 'c' is unused, use whole BC, etc. */
		case DUK_OP_CSVAR_RR:
		case DUK_OP_CSVAR_CR:
		case DUK_OP_CSVAR_RC:
		case DUK_OP_CSVAR_CC: {
			/* The speciality of calling through a variable binding is that the
			 * 'this' value may be provided by the variable lookup: E5 Section 6.b.i.
			 *
			 * The only (standard) case where the 'this' binding is non-null is when
			 *   (1) the variable is found in an object environment record, and
			 *   (2) that object environment record is a 'with' block.
			 */

			duk_activation *act;
			duk_uint_fast_t idx;
			duk_tval *tv1;
			duk_hstring *name;

			/* A -> target registers (A, A + 1) for call setup
			 * B -> identifier name, usually constant but can be a register due to shuffling
			 */

			tv1 = DUK__REGCONSTP_B(ins);
			DUK_ASSERT(DUK_TVAL_IS_STRING(tv1));
			name = DUK_TVAL_GET_STRING(tv1);
			DUK_ASSERT(name != NULL);
			act = thr->callstack_curr;
			(void) duk_js_getvar_activation(thr, act, name, 1 /*throw*/);  /* -> [... val this] */

			idx = (duk_uint_fast_t) DUK_DEC_A(ins);

			/* Could add direct value stack handling. */
			duk_replace(thr, (duk_idx_t) (idx + 1));  /* 'this' binding */
			duk_replace(thr, (duk_idx_t) idx);        /* variable value (function, we hope, not checked here) */
			break;
		}

		case DUK_OP_CLOSURE: {
			duk_activation *act;
			duk_hcompfunc *fun_act;
			duk_small_uint_fast_t bc = DUK_DEC_BC(ins);
			duk_hobject *fun_temp;

			/* A -> target reg
			 * BC -> inner function index
			 */

			DUK_DDD(DUK_DDDPRINT("CLOSURE to target register %ld, fnum %ld (count %ld)",
			                     (long) DUK_DEC_A(ins), (long) DUK_DEC_BC(ins), (long) DUK_HCOMPFUNC_GET_FUNCS_COUNT(thr->heap, DUK__FUN())));

			DUK_ASSERT_DISABLE(bc >= 0); /* unsigned */
			DUK_ASSERT((duk_uint_t) bc < (duk_uint_t) DUK_HCOMPFUNC_GET_FUNCS_COUNT(thr->heap, DUK__FUN()));

			act = thr->callstack_curr;
			fun_act = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);
			fun_temp = DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, fun_act)[bc];
			DUK_ASSERT(fun_temp != NULL);
			DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(fun_temp));

			DUK_DDD(DUK_DDDPRINT("CLOSURE: function template is: %p -> %!O",
			                     (void *) fun_temp, (duk_heaphdr *) fun_temp));

			if (act->lex_env == NULL) {
				DUK_ASSERT(act->var_env == NULL);
				duk_js_init_activation_environment_records_delayed(thr, act);
				act = thr->callstack_curr;
			}
			DUK_ASSERT(act->lex_env != NULL);
			DUK_ASSERT(act->var_env != NULL);

			/* functions always have a NEWENV flag, i.e. they get a
			 * new variable declaration environment, so only lex_env
			 * matters here.
			 */
			duk_js_push_closure(thr,
			                    (duk_hcompfunc *) fun_temp,
			                    act->var_env,
			                    act->lex_env,
			                    1 /*add_auto_proto*/);
			DUK__REPLACE_TOP_A_BREAK();
		}

		case DUK_OP_GETVAR: {
			duk_activation *act;
			duk_tval *tv1;
			duk_hstring *name;

			tv1 = DUK__CONSTP_BC(ins);
			DUK_ASSERT(DUK_TVAL_IS_STRING(tv1));
			name = DUK_TVAL_GET_STRING(tv1);
			DUK_ASSERT(name != NULL);
			act = thr->callstack_curr;
			DUK_ASSERT(act != NULL);
			(void) duk_js_getvar_activation(thr, act, name, 1 /*throw*/);  /* -> [... val this] */
			duk_pop_unsafe(thr);  /* 'this' binding is not needed here */
			DUK__REPLACE_TOP_A_BREAK();
		}

		case DUK_OP_PUTVAR: {
			duk_activation *act;
			duk_tval *tv1;
			duk_hstring *name;

			tv1 = DUK__CONSTP_BC(ins);
			DUK_ASSERT(DUK_TVAL_IS_STRING(tv1));
			name = DUK_TVAL_GET_STRING(tv1);
			DUK_ASSERT(name != NULL);

			/* XXX: putvar takes a duk_tval pointer, which is awkward and
			 * should be reworked.
			 */

			tv1 = DUK__REGP_A(ins);  /* val */
			act = thr->callstack_curr;
			duk_js_putvar_activation(thr, act, name, tv1, DUK__STRICT());
			break;
		}

		case DUK_OP_DELVAR: {
			duk_activation *act;
			duk_tval *tv1;
			duk_hstring *name;
			duk_bool_t rc;

			tv1 = DUK__CONSTP_BC(ins);
			DUK_ASSERT(DUK_TVAL_IS_STRING(tv1));
			name = DUK_TVAL_GET_STRING(tv1);
			DUK_ASSERT(name != NULL);
			act = thr->callstack_curr;
			rc = duk_js_delvar_activation(thr, act, name);
			DUK__REPLACE_BOOL_A_BREAK(rc);
		}

		case DUK_OP_JUMP: {
			/* Note: without explicit cast to signed, MSVC will
			 * apparently generate a large positive jump when the
			 * bias-corrected value would normally be negative.
			 */
			curr_pc += (duk_int_fast_t) DUK_DEC_ABC(ins) - (duk_int_fast_t) DUK_BC_JUMP_BIAS;
			break;
		}

#define DUK__RETURN_SHARED() do { \
		duk_small_uint_t ret_result; \
		/* duk__handle_return() is guaranteed never to throw, except \
		 * for potential out-of-memory situations which will then \
		 * propagate out of the executor longjmp handler. \
		 */ \
		DUK_ASSERT(thr->ptr_curr_pc == NULL); \
		ret_result = duk__handle_return(thr, entry_act); \
		if (ret_result == DUK__RETHAND_RESTART) { \
			goto restart_execution; \
		} \
		DUK_ASSERT(ret_result == DUK__RETHAND_FINISHED); \
		return; \
	} while (0)
#if defined(DUK_USE_EXEC_PREFER_SIZE)
		case DUK_OP_RETREG:
		case DUK_OP_RETCONST:
		case DUK_OP_RETCONSTN:
		case DUK_OP_RETUNDEF: {
			 /* BC -> return value reg/const */

			DUK__SYNC_AND_NULL_CURR_PC();

			if (op == DUK_OP_RETREG) {
				duk_push_tval(thr, DUK__REGP_BC(ins));
			} else if (op == DUK_OP_RETUNDEF) {
				DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top));  /* valstack policy */
				thr->valstack_top++;
			} else {
				DUK_ASSERT(op == DUK_OP_RETCONST || op == DUK_OP_RETCONSTN);
				duk_push_tval(thr, DUK__CONSTP_BC(ins));
			}

			DUK__RETURN_SHARED();
		}
#else  /* DUK_USE_EXEC_PREFER_SIZE */
		case DUK_OP_RETREG: {
			duk_tval *tv;

			DUK__SYNC_AND_NULL_CURR_PC();
			tv = DUK__REGP_BC(ins);
			DUK_TVAL_SET_TVAL(thr->valstack_top, tv);
			DUK_TVAL_INCREF(thr, tv);
			thr->valstack_top++;
			DUK__RETURN_SHARED();
		}
		/* This will be unused without refcounting. */
		case DUK_OP_RETCONST: {
			duk_tval *tv;

			DUK__SYNC_AND_NULL_CURR_PC();
			tv = DUK__CONSTP_BC(ins);
			DUK_TVAL_SET_TVAL(thr->valstack_top, tv);
			DUK_TVAL_INCREF(thr, tv);
			thr->valstack_top++;
			DUK__RETURN_SHARED();
		}
		case DUK_OP_RETCONSTN: {
			duk_tval *tv;

			DUK__SYNC_AND_NULL_CURR_PC();
			tv = DUK__CONSTP_BC(ins);
			DUK_TVAL_SET_TVAL(thr->valstack_top, tv);
#if defined(DUK_USE_REFERENCE_COUNTING)
			/* Without refcounting only RETCONSTN is used. */
			DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv));  /* no INCREF for this constant */
#endif
			thr->valstack_top++;
			DUK__RETURN_SHARED();
		}
		case DUK_OP_RETUNDEF: {
			DUK__SYNC_AND_NULL_CURR_PC();
			thr->valstack_top++;  /* value at valstack top is already undefined by valstack policy */
			DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top));
			DUK__RETURN_SHARED();
		}
#endif  /* DUK_USE_EXEC_PREFER_SIZE */

		case DUK_OP_LABEL: {
			duk_activation *act;
			duk_catcher *cat;
			duk_small_uint_fast_t bc = DUK_DEC_BC(ins);

			/* Allocate catcher and populate it (must be atomic). */

			cat = duk_hthread_catcher_alloc(thr);
			DUK_ASSERT(cat != NULL);

			cat->flags = (duk_uint32_t) (DUK_CAT_TYPE_LABEL | (bc << DUK_CAT_LABEL_SHIFT));
			cat->pc_base = (duk_instr_t *) curr_pc;  /* pre-incremented, points to first jump slot */
			cat->idx_base = 0;  /* unused for label */
			cat->h_varname = NULL;

			act = thr->callstack_curr;
			DUK_ASSERT(act != NULL);
			cat->parent = act->cat;
			act->cat = cat;

			DUK_DDD(DUK_DDDPRINT("LABEL catcher: flags=0x%08lx, pc_base=%ld, "
			                     "idx_base=%ld, h_varname=%!O, label_id=%ld",
			                     (long) cat->flags, (long) cat->pc_base,
			                     (long) cat->idx_base, (duk_heaphdr *) cat->h_varname, (long) DUK_CAT_GET_LABEL(cat)));

			curr_pc += 2;  /* skip jump slots */
			break;
		}

		case DUK_OP_ENDLABEL: {
			duk_activation *act;
#if (defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)) || defined(DUK_USE_ASSERTIONS)
			duk_small_uint_fast_t bc = DUK_DEC_BC(ins);
#endif
#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
			DUK_DDD(DUK_DDDPRINT("ENDLABEL %ld", (long) bc));
#endif

			act = thr->callstack_curr;
			DUK_ASSERT(act->cat != NULL);
			DUK_ASSERT(DUK_CAT_GET_TYPE(act->cat) == DUK_CAT_TYPE_LABEL);
			DUK_ASSERT((duk_uint_fast_t) DUK_CAT_GET_LABEL(act->cat) == bc);
			duk_hthread_catcher_unwind_nolexenv_norz(thr, act);

			/* no need to unwind callstack */
			break;
		}

		case DUK_OP_BREAK: {
			duk_small_uint_fast_t bc = DUK_DEC_BC(ins);

			DUK__SYNC_AND_NULL_CURR_PC();
			duk__handle_break_or_continue(thr, (duk_uint_t) bc, DUK_LJ_TYPE_BREAK);
			goto restart_execution;
		}

		case DUK_OP_CONTINUE: {
			duk_small_uint_fast_t bc = DUK_DEC_BC(ins);

			DUK__SYNC_AND_NULL_CURR_PC();
			duk__handle_break_or_continue(thr, (duk_uint_t) bc, DUK_LJ_TYPE_CONTINUE);
			goto restart_execution;
		}

		/* XXX: move to helper, too large to be inline here */
		case DUK_OP_TRYCATCH: {
			duk__handle_op_trycatch(thr, ins, curr_pc);
			curr_pc += 2;  /* skip jump slots */
			break;
		}

		case DUK_OP_ENDTRY: {
			curr_pc = duk__handle_op_endtry(thr, ins);
			break;
		}

		case DUK_OP_ENDCATCH: {
			duk__handle_op_endcatch(thr, ins);
			break;
		}

		case DUK_OP_ENDFIN: {
			/* Sync and NULL early. */
			DUK__SYNC_AND_NULL_CURR_PC();

			if (duk__handle_op_endfin(thr, ins, entry_act) != 0) {
				return;
			}

			/* Must restart because we NULLed out curr_pc. */
			goto restart_execution;
		}

		case DUK_OP_THROW: {
			duk_small_uint_fast_t bc = DUK_DEC_BC(ins);

			/* Note: errors are augmented when they are created, not
			 * when they are thrown.  So, don't augment here, it would
			 * break re-throwing for instance.
			 */

			/* Sync so that augmentation sees up-to-date activations, NULL
			 * thr->ptr_curr_pc so that it's not used if side effects occur
			 * in augmentation or longjmp handling.
			 */
			DUK__SYNC_AND_NULL_CURR_PC();

			duk_dup(thr, (duk_idx_t) bc);
			DUK_DDD(DUK_DDDPRINT("THROW ERROR (BYTECODE): %!dT (before throw augment)",
			                     (duk_tval *) duk_get_tval(thr, -1)));
#if defined(DUK_USE_AUGMENT_ERROR_THROW)
			duk_err_augment_error_throw(thr);
			DUK_DDD(DUK_DDDPRINT("THROW ERROR (BYTECODE): %!dT (after throw augment)",
			                     (duk_tval *) duk_get_tval(thr, -1)));
#endif

			duk_err_setup_ljstate1(thr, DUK_LJ_TYPE_THROW, DUK_GET_TVAL_NEGIDX(thr, -1));
#if defined(DUK_USE_DEBUGGER_SUPPORT)
			duk_err_check_debugger_integration(thr);
#endif

			DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL);  /* always in executor */
			duk_err_longjmp(thr);
			DUK_UNREACHABLE();
			break;
		}

		case DUK_OP_CSREG: {
			/*
			 *  Assuming a register binds to a variable declared within this
			 *  function (a declarative binding), the 'this' for the call
			 *  setup is always 'undefined'.  E5 Section 10.2.1.1.6.
			 */

			duk_small_uint_fast_t a = DUK_DEC_A(ins);
			duk_small_uint_fast_t bc = DUK_DEC_BC(ins);

			/* A -> register containing target function (not type checked here)
			 * BC -> target registers (BC, BC + 1) for call setup
			 */

#if defined(DUK_USE_PREFER_SIZE)
			duk_dup(thr, (duk_idx_t) a);
			duk_replace(thr, (duk_idx_t) bc);
			duk_to_undefined(thr, (duk_idx_t) (bc + 1));
#else
			duk_tval *tv1;
			duk_tval *tv2;
			duk_tval *tv3;
			duk_tval tv_tmp1;
			duk_tval tv_tmp2;

			tv1 = DUK__REGP(bc);
			tv2 = tv1 + 1;
			DUK_TVAL_SET_TVAL(&tv_tmp1, tv1);
			DUK_TVAL_SET_TVAL(&tv_tmp2, tv2);
			tv3 = DUK__REGP(a);
			DUK_TVAL_SET_TVAL(tv1, tv3);
			DUK_TVAL_INCREF(thr, tv1);  /* no side effects */
			DUK_TVAL_SET_UNDEFINED(tv2);  /* no need for incref */
			DUK_TVAL_DECREF(thr, &tv_tmp1);
			DUK_TVAL_DECREF(thr, &tv_tmp2);
#endif
			break;
		}


		/* XXX: in some cases it's faster NOT to reuse the value
		 * stack but rather copy the arguments on top of the stack
		 * (mainly when the calling value stack is large and the value
		 * stack resize would be large).
		 */

		case DUK_OP_CALL0:
		case DUK_OP_CALL1:
		case DUK_OP_CALL2:
		case DUK_OP_CALL3:
		case DUK_OP_CALL4:
		case DUK_OP_CALL5:
		case DUK_OP_CALL6:
		case DUK_OP_CALL7: {
			/* Opcode packs 4 flag bits: 1 for indirect, 3 map
			 * 1:1 to three lowest call handling flags.
			 *
			 * A -> nargs or register with nargs (indirect)
			 * BC -> base register for call (base -> func, base+1 -> this, base+2 -> arg1 ... base+2+N-1 -> argN)
			 */

			duk_idx_t nargs;
			duk_idx_t idx;
			duk_small_uint_t call_flags;
#if !defined(DUK_USE_EXEC_FUN_LOCAL)
			duk_hcompfunc *fun;
#endif

			DUK_ASSERT((DUK_OP_CALL0 & 0x0fU) == 0);
			DUK_ASSERT((ins & DUK_BC_CALL_FLAG_INDIRECT) == 0);

			nargs = (duk_idx_t) DUK_DEC_A(ins);
			call_flags = (ins & 0x07U) | DUK_CALL_FLAG_ALLOW_ECMATOECMA;
			idx = (duk_idx_t) DUK_DEC_BC(ins);

			if (duk__executor_handle_call(thr, idx, nargs, call_flags)) {
				/* curr_pc synced by duk_handle_call_unprotected() */
				DUK_ASSERT(thr->ptr_curr_pc == NULL);
				goto restart_execution;
			}
			DUK_ASSERT(thr->ptr_curr_pc != NULL);

			/* duk_js_call.c is required to restore the stack reserve
			 * so we only need to reset the top.
			 */
#if !defined(DUK_USE_EXEC_FUN_LOCAL)
			fun = DUK__FUN();
#endif
			duk_set_top_unsafe(thr, (duk_idx_t) fun->nregs);

			/* No need to reinit setjmp() catchpoint, as call handling
			 * will store and restore our state.
			 *
			 * When debugger is enabled, we need to recheck the activation
			 * status after returning.  This is now handled by call handling
			 * and heap->dbg_force_restart.
			 */
			break;
		}

		case DUK_OP_CALL8:
		case DUK_OP_CALL9:
		case DUK_OP_CALL10:
		case DUK_OP_CALL11:
		case DUK_OP_CALL12:
		case DUK_OP_CALL13:
		case DUK_OP_CALL14:
		case DUK_OP_CALL15: {
			/* Indirect variant. */
			duk_uint_fast_t nargs;
			duk_idx_t idx;
			duk_small_uint_t call_flags;
#if !defined(DUK_USE_EXEC_FUN_LOCAL)
			duk_hcompfunc *fun;
#endif

			DUK_ASSERT((DUK_OP_CALL0 & 0x0fU) == 0);
			DUK_ASSERT((ins & DUK_BC_CALL_FLAG_INDIRECT) != 0);

			nargs = (duk_uint_fast_t) DUK_DEC_A(ins);
			DUK__LOOKUP_INDIRECT(nargs);
			call_flags = (ins & 0x07U) | DUK_CALL_FLAG_ALLOW_ECMATOECMA;
			idx = (duk_idx_t) DUK_DEC_BC(ins);

			if (duk__executor_handle_call(thr, idx, (duk_idx_t) nargs, call_flags)) {
				DUK_ASSERT(thr->ptr_curr_pc == NULL);
				goto restart_execution;
			}
			DUK_ASSERT(thr->ptr_curr_pc != NULL);

#if !defined(DUK_USE_EXEC_FUN_LOCAL)
			fun = DUK__FUN();
#endif
			duk_set_top_unsafe(thr, (duk_idx_t) fun->nregs);
			break;
		}

		case DUK_OP_NEWOBJ: {
			duk_push_object(thr);
#if defined(DUK_USE_ASSERTIONS)
			{
				duk_hobject *h;
				h = duk_require_hobject(thr, -1);
				DUK_ASSERT(DUK_HOBJECT_GET_ESIZE(h) == 0);
				DUK_ASSERT(DUK_HOBJECT_GET_ENEXT(h) == 0);
				DUK_ASSERT(DUK_HOBJECT_GET_ASIZE(h) == 0);
				DUK_ASSERT(DUK_HOBJECT_GET_HSIZE(h) == 0);
			}
#endif
#if !defined(DUK_USE_PREFER_SIZE)
			/* XXX: could do a direct props realloc, but need hash size */
			duk_hobject_resize_entrypart(thr, duk_known_hobject(thr, -1), DUK_DEC_A(ins));
#endif
			DUK__REPLACE_TOP_BC_BREAK();
		}

		case DUK_OP_NEWARR: {
			duk_push_array(thr);
#if defined(DUK_USE_ASSERTIONS)
			{
				duk_hobject *h;
				h = duk_require_hobject(thr, -1);
				DUK_ASSERT(DUK_HOBJECT_GET_ESIZE(h) == 0);
				DUK_ASSERT(DUK_HOBJECT_GET_ENEXT(h) == 0);
				DUK_ASSERT(DUK_HOBJECT_GET_ASIZE(h) == 0);
				DUK_ASSERT(DUK_HOBJECT_GET_HSIZE(h) == 0);
				DUK_ASSERT(DUK_HOBJECT_HAS_ARRAY_PART(h));
			}
#endif
#if !defined(DUK_USE_PREFER_SIZE)
			duk_hobject_realloc_props(thr,
			                          duk_known_hobject(thr, -1),
			                          0 /*new_e_size*/,
			                          DUK_DEC_A(ins) /*new_a_size*/,
			                          0 /*new_h_size*/,
			                          0 /*abandon_array*/);
#if 0
			duk_hobject_resize_arraypart(thr, duk_known_hobject(thr, -1), DUK_DEC_A(ins));
#endif
#endif
			DUK__REPLACE_TOP_BC_BREAK();
		}

		case DUK_OP_MPUTOBJ:
		case DUK_OP_MPUTOBJI: {
			duk_idx_t obj_idx;
			duk_uint_fast_t idx, idx_end;
			duk_small_uint_fast_t count;

			/* A -> register of target object
			 * B -> first register of key/value pair list
			 *      or register containing first register number if indirect
			 * C -> number of key/value pairs * 2
			 *      (= number of value stack indices used starting from 'B')
			 */

			obj_idx = DUK_DEC_A(ins);
			DUK_ASSERT(duk_is_object(thr, obj_idx));

			idx = (duk_uint_fast_t) DUK_DEC_B(ins);
			if (DUK_DEC_OP(ins) == DUK_OP_MPUTOBJI) {
				DUK__LOOKUP_INDIRECT(idx);
			}

			count = (duk_small_uint_fast_t) DUK_DEC_C(ins);
			DUK_ASSERT(count > 0);  /* compiler guarantees */
			idx_end = idx + count;

#if defined(DUK_USE_EXEC_INDIRECT_BOUND_CHECK)
			if (DUK_UNLIKELY(idx_end > (duk_uint_fast_t) duk_get_top(thr))) {
				/* XXX: use duk_is_valid_index() instead? */
				/* XXX: improve check; check against nregs, not against top */
				DUK__INTERNAL_ERROR("MPUTOBJ out of bounds");
			}
#endif

			/* Use 'force' flag to duk_def_prop() to ensure that any
			 * inherited properties don't prevent the operation.
			 * With ES2015 duplicate properties are allowed, so that we
			 * must overwrite any previous data or accessor property.
			 *
			 * With ES2015 computed property names the literal keys
			 * may be arbitrary values and need to be ToPropertyKey()
			 * coerced at runtime.
			 */
			do {
				/* XXX: faster initialization (direct access or better primitives) */
				duk_dup(thr, (duk_idx_t) idx);
				duk_dup(thr, (duk_idx_t) (idx + 1));
				duk_def_prop(thr, obj_idx, DUK_DEFPROP_HAVE_VALUE |
				                           DUK_DEFPROP_FORCE |
				                           DUK_DEFPROP_SET_WRITABLE |
				                           DUK_DEFPROP_SET_ENUMERABLE |
				                           DUK_DEFPROP_SET_CONFIGURABLE);
				idx += 2;
			} while (idx < idx_end);
			break;
		}

		case DUK_OP_INITSET:
		case DUK_OP_INITGET: {
			duk__handle_op_initset_initget(thr, ins);
			break;
		}

		case DUK_OP_MPUTARR:
		case DUK_OP_MPUTARRI: {
			duk_idx_t obj_idx;
			duk_uint_fast_t idx, idx_end;
			duk_small_uint_fast_t count;
			duk_tval *tv1;
			duk_uint32_t arr_idx;

			/* A -> register of target object
			 * B -> first register of value data (start_index, value1, value2, ..., valueN)
			 *      or register containing first register number if indirect
			 * C -> number of key/value pairs (N)
			 */

			obj_idx = DUK_DEC_A(ins);
			DUK_ASSERT(duk_is_object(thr, obj_idx));

			idx = (duk_uint_fast_t) DUK_DEC_B(ins);
			if (DUK_DEC_OP(ins) == DUK_OP_MPUTARRI) {
				DUK__LOOKUP_INDIRECT(idx);
			}

			count = (duk_small_uint_fast_t) DUK_DEC_C(ins);
			DUK_ASSERT(count > 0 + 1);  /* compiler guarantees */
			idx_end = idx + count;

#if defined(DUK_USE_EXEC_INDIRECT_BOUND_CHECK)
			if (idx_end > (duk_uint_fast_t) duk_get_top(thr)) {
				/* XXX: use duk_is_valid_index() instead? */
				/* XXX: improve check; check against nregs, not against top */
				DUK__INTERNAL_ERROR("MPUTARR out of bounds");
			}
#endif

			tv1 = DUK__REGP(idx);
			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv1));
#if defined(DUK_USE_FASTINT)
			DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv1));
			arr_idx = (duk_uint32_t) DUK_TVAL_GET_FASTINT_U32(tv1);
#else
			arr_idx = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv1);
#endif
			idx++;

			do {
				/* duk_xdef_prop() will define an own property without any array
				 * special behaviors.  We'll need to set the array length explicitly
				 * in the end.  For arrays with elisions, the compiler will emit an
				 * explicit SETALEN which will update the length.
				 */

				/* XXX: because we're dealing with 'own' properties of a fresh array,
				 * the array initializer should just ensure that the array has a large
				 * enough array part and write the values directly into array part,
				 * and finally set 'length' manually in the end (as already happens now).
				 */

				duk_dup(thr, (duk_idx_t) idx);
				duk_xdef_prop_index_wec(thr, obj_idx, arr_idx);

				idx++;
				arr_idx++;
			} while (idx < idx_end);

			/* XXX: E5.1 Section 11.1.4 coerces the final length through
			 * ToUint32() which is odd but happens now as a side effect of
			 * 'arr_idx' type.
			 */
			duk_set_length(thr, obj_idx, (duk_size_t) (duk_uarridx_t) arr_idx);
			break;
		}

		case DUK_OP_SETALEN: {
			duk_tval *tv1;
			duk_hobject *h;
			duk_uint32_t len;

			tv1 = DUK__REGP_A(ins);
			DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv1));
			h = DUK_TVAL_GET_OBJECT(tv1);
			DUK_ASSERT(DUK_HOBJECT_IS_ARRAY(h));

			tv1 = DUK__REGP_BC(ins);
			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv1));
#if defined(DUK_USE_FASTINT)
			DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv1));
			len = (duk_uint32_t) DUK_TVAL_GET_FASTINT_U32(tv1);
#else
			len = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv1);
#endif
			((duk_harray *) h)->length = len;
			break;
		}

		case DUK_OP_INITENUM: {
			duk__handle_op_initenum(thr, ins);
			break;
		}

		case DUK_OP_NEXTENUM: {
			curr_pc += duk__handle_op_nextenum(thr, ins);
			break;
		}

		case DUK_OP_INVLHS: {
			DUK_ERROR_REFERENCE(thr, DUK_STR_INVALID_LVALUE);
			DUK_WO_NORETURN(return;);
			break;
		}

		case DUK_OP_DEBUGGER: {
			/* Opcode only emitted by compiler when debugger
			 * support is enabled.  Ignore it silently without
			 * debugger support, in case it has been loaded
			 * from precompiled bytecode.
			 */
#if defined(DUK_USE_DEBUGGER_SUPPORT)
			if (duk_debug_is_attached(thr->heap)) {
				DUK_D(DUK_DPRINT("DEBUGGER statement encountered, halt execution"));
				DUK__SYNC_AND_NULL_CURR_PC();
				duk_debug_halt_execution(thr, 1 /*use_prev_pc*/);
				DUK_D(DUK_DPRINT("DEBUGGER statement finished, resume execution"));
				goto restart_execution;
			} else {
				DUK_D(DUK_DPRINT("DEBUGGER statement ignored, debugger not attached"));
			}
#else
			DUK_D(DUK_DPRINT("DEBUGGER statement ignored, no debugger support"));
#endif
			break;
		}

		case DUK_OP_NOP: {
			/* Nop, ignored, but ABC fields may carry a value e.g.
			 * for indirect opcode handling.
			 */
			break;
		}

		case DUK_OP_INVALID: {
			DUK_ERROR_FMT1(thr, DUK_ERR_ERROR, "INVALID opcode (%ld)", (long) DUK_DEC_ABC(ins));
			DUK_WO_NORETURN(return;);
			break;
		}

#if defined(DUK_USE_ES6)
		case DUK_OP_NEWTARGET: {
			duk_push_new_target(thr);
			DUK__REPLACE_TOP_BC_BREAK();
		}
#endif  /* DUK_USE_ES6 */

#if !defined(DUK_USE_EXEC_PREFER_SIZE)
#if !defined(DUK_USE_ES7_EXP_OPERATOR)
		case DUK_OP_EXP_RR:
		case DUK_OP_EXP_CR:
		case DUK_OP_EXP_RC:
		case DUK_OP_EXP_CC:
#endif
#if !defined(DUK_USE_ES6)
		case DUK_OP_NEWTARGET:
#endif
#if !defined(DUK_USE_VERBOSE_ERRORS)
		case DUK_OP_GETPROPC_RR:
		case DUK_OP_GETPROPC_CR:
		case DUK_OP_GETPROPC_RC:
		case DUK_OP_GETPROPC_CC:
#endif
		case DUK_OP_UNUSED207:
		case DUK_OP_UNUSED212:
		case DUK_OP_UNUSED213:
		case DUK_OP_UNUSED214:
		case DUK_OP_UNUSED215:
		case DUK_OP_UNUSED216:
		case DUK_OP_UNUSED217:
		case DUK_OP_UNUSED218:
		case DUK_OP_UNUSED219:
		case DUK_OP_UNUSED220:
		case DUK_OP_UNUSED221:
		case DUK_OP_UNUSED222:
		case DUK_OP_UNUSED223:
		case DUK_OP_UNUSED224:
		case DUK_OP_UNUSED225:
		case DUK_OP_UNUSED226:
		case DUK_OP_UNUSED227:
		case DUK_OP_UNUSED228:
		case DUK_OP_UNUSED229:
		case DUK_OP_UNUSED230:
		case DUK_OP_UNUSED231:
		case DUK_OP_UNUSED232:
		case DUK_OP_UNUSED233:
		case DUK_OP_UNUSED234:
		case DUK_OP_UNUSED235:
		case DUK_OP_UNUSED236:
		case DUK_OP_UNUSED237:
		case DUK_OP_UNUSED238:
		case DUK_OP_UNUSED239:
		case DUK_OP_UNUSED240:
		case DUK_OP_UNUSED241:
		case DUK_OP_UNUSED242:
		case DUK_OP_UNUSED243:
		case DUK_OP_UNUSED244:
		case DUK_OP_UNUSED245:
		case DUK_OP_UNUSED246:
		case DUK_OP_UNUSED247:
		case DUK_OP_UNUSED248:
		case DUK_OP_UNUSED249:
		case DUK_OP_UNUSED250:
		case DUK_OP_UNUSED251:
		case DUK_OP_UNUSED252:
		case DUK_OP_UNUSED253:
		case DUK_OP_UNUSED254:
		case DUK_OP_UNUSED255:
		/* Force all case clauses to map to an actual handler
		 * so that the compiler can emit a jump without a bounds
		 * check: the switch argument is a duk_uint8_t so that
		 * the compiler may be able to figure it out.  This is
		 * a small detail and obviously compiler dependent.
		 */
		/* default: clause omitted on purpose */
#else  /* DUK_USE_EXEC_PREFER_SIZE */
		default:
#endif  /* DUK_USE_EXEC_PREFER_SIZE */
		{
			/* Default case catches invalid/unsupported opcodes. */
			DUK_D(DUK_DPRINT("invalid opcode: %ld - %!I", (long) op, ins));
			DUK__INTERNAL_ERROR("invalid opcode");
			break;
		}

		}  /* end switch */

		continue;

		/* Some shared exit paths for opcode handling below.  These
		 * are mostly useful to reduce code footprint when multiple
		 * opcodes have a similar epilogue (like replacing stack top
		 * with index 'a').
		 */

#if defined(DUK_USE_EXEC_PREFER_SIZE)
	 replace_top_a:
		DUK__REPLACE_TO_TVPTR(thr, DUK__REGP_A(ins));
		continue;
	 replace_top_bc:
		DUK__REPLACE_TO_TVPTR(thr, DUK__REGP_BC(ins));
		continue;
#endif
	}
	DUK_WO_NORETURN(return;);

#if !defined(DUK_USE_VERBOSE_EXECUTOR_ERRORS)
 internal_error:
	DUK_ERROR_INTERNAL(thr);
	DUK_WO_NORETURN(return;);
#endif
}

/* automatic undefs */
#undef DUK__BYTEOFF_A
#undef DUK__BYTEOFF_B
#undef DUK__BYTEOFF_BC
#undef DUK__BYTEOFF_C
#undef DUK__COMPARE_BODY
#undef DUK__CONST
#undef DUK__CONSTP
#undef DUK__CONSTP_A
#undef DUK__CONSTP_B
#undef DUK__CONSTP_BC
#undef DUK__CONSTP_C
#undef DUK__DELPROP_BODY
#undef DUK__EQ_BODY
#undef DUK__FUN
#undef DUK__GETPROPC_BODY
#undef DUK__GETPROP_BODY
#undef DUK__GE_BODY
#undef DUK__GT_BODY
#undef DUK__INSTOF_BODY
#undef DUK__INTERNAL_ERROR
#undef DUK__INT_NOACTION
#undef DUK__INT_RESTART
#undef DUK__IN_BODY
#undef DUK__LE_BODY
#undef DUK__LONGJMP_RESTART
#undef DUK__LONGJMP_RETHROW
#undef DUK__LOOKUP_INDIRECT
#undef DUK__LT_BODY
#undef DUK__MASK_A
#undef DUK__MASK_B
#undef DUK__MASK_BC
#undef DUK__MASK_C
#undef DUK__NEQ_BODY
#undef DUK__PUTPROP_BODY
#undef DUK__RCBIT_B
#undef DUK__RCBIT_C
#undef DUK__REG
#undef DUK__REGCONSTP_B
#undef DUK__REGCONSTP_C
#undef DUK__REGP
#undef DUK__REGP_A
#undef DUK__REGP_B
#undef DUK__REGP_BC
#undef DUK__REGP_C
#undef DUK__REPLACE_BOOL_A_BREAK
#undef DUK__REPLACE_TOP_A_BREAK
#undef DUK__REPLACE_TOP_BC_BREAK
#undef DUK__REPLACE_TO_TVPTR
#undef DUK__RETHAND_FINISHED
#undef DUK__RETHAND_RESTART
#undef DUK__RETURN_SHARED
#undef DUK__SEQ_BODY
#undef DUK__SHIFT_A
#undef DUK__SHIFT_B
#undef DUK__SHIFT_BC
#undef DUK__SHIFT_C
#undef DUK__SNEQ_BODY
#undef DUK__STRICT
#undef DUK__SYNC_AND_NULL_CURR_PC
#undef DUK__SYNC_CURR_PC
#undef DUK__TVAL_SHIFT
#line 1 "duk_js_ops.c"
/*
 *  ECMAScript specification algorithm and conversion helpers.
 *
 *  These helpers encapsulate the primitive ECMAScript operation semantics,
 *  and are used by the bytecode executor and the API (among other places).
 *  Some primitives are only implemented as part of the API and have no
 *  "internal" helper.  This is the case when an internal helper would not
 *  really be useful; e.g. the operation is rare, uses value stack heavily,
 *  etc.
 *
 *  The operation arguments depend on what is required to implement
 *  the operation:
 *
 *    - If an operation is simple and stateless, and has no side
 *      effects, it won't take an duk_hthread argument and its
 *      arguments may be duk_tval pointers (which are safe as long
 *      as no side effects take place).
 *
 *    - If complex coercions are required (e.g. a "ToNumber" coercion)
 *      or errors may be thrown, the operation takes an duk_hthread
 *      argument.  This also implies that the operation may have
 *      arbitrary side effects, invalidating any duk_tval pointers.
 *
 *    - For operations with potential side effects, arguments can be
 *      taken in several ways:
 *
 *      a) as duk_tval pointers, which makes sense if the "common case"
 *         can be resolved without side effects (e.g. coercion); the
 *         arguments are pushed to the valstack for coercion if
 *         necessary
 *
 *      b) as duk_tval values
 *
 *      c) implicitly on value stack top
 *
 *      d) as indices to the value stack
 *
 *  Future work:
 *
 *     - Argument styles may not be the most sensible in every case now.
 *
 *     - In-place coercions might be useful for several operations, if
 *       in-place coercion is OK for the bytecode executor and the API.
 */

/* #include duk_internal.h -> already included */

/*
 *  ToPrimitive()  (E5 Section 9.1)
 *
 *  ==> implemented in the API.
 */

/*
 *  ToBoolean()  (E5 Section 9.2)
 */

DUK_INTERNAL duk_bool_t duk_js_toboolean(duk_tval *tv) {
	switch (DUK_TVAL_GET_TAG(tv)) {
	case DUK_TAG_UNDEFINED:
	case DUK_TAG_NULL:
		return 0;
	case DUK_TAG_BOOLEAN:
		DUK_ASSERT(DUK_TVAL_GET_BOOLEAN(tv) == 0 || DUK_TVAL_GET_BOOLEAN(tv) == 1);
		return DUK_TVAL_GET_BOOLEAN(tv);
	case DUK_TAG_STRING: {
		/* Symbols ToBoolean() coerce to true, regardless of their
		 * description.  This happens with no explicit check because
		 * of the symbol representation byte prefix.
		 */
		duk_hstring *h = DUK_TVAL_GET_STRING(tv);
		DUK_ASSERT(h != NULL);
		return (DUK_HSTRING_GET_BYTELEN(h) > 0 ? 1 : 0);
	}
	case DUK_TAG_OBJECT: {
		return 1;
	}
	case DUK_TAG_BUFFER: {
		/* Mimic Uint8Array semantics: objects coerce true, regardless
		 * of buffer length (zero or not) or context.
		 */
		return 1;
	}
	case DUK_TAG_POINTER: {
		void *p = DUK_TVAL_GET_POINTER(tv);
		return (p != NULL ? 1 : 0);
	}
	case DUK_TAG_LIGHTFUNC: {
		return 1;
	}
#if defined(DUK_USE_FASTINT)
	case DUK_TAG_FASTINT:
		if (DUK_TVAL_GET_FASTINT(tv) != 0) {
			return 1;
		} else {
			return 0;
		}
#endif
	default: {
		/* number */
		duk_double_t d;
#if defined(DUK_USE_PREFER_SIZE)
		int c;
#endif
		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
		DUK_ASSERT(DUK_TVAL_IS_DOUBLE(tv));
		d = DUK_TVAL_GET_DOUBLE(tv);
#if defined(DUK_USE_PREFER_SIZE)
		c = DUK_FPCLASSIFY((double) d);
		if (c == DUK_FP_ZERO || c == DUK_FP_NAN) {
			return 0;
		} else {
			return 1;
		}
#else
		DUK_ASSERT(duk_double_is_nan_or_zero(d) == 0 || duk_double_is_nan_or_zero(d) == 1);
		return duk_double_is_nan_or_zero(d) ^ 1;
#endif
	}
	}
	DUK_UNREACHABLE();
	DUK_WO_UNREACHABLE(return 0;);
}

/*
 *  ToNumber()  (E5 Section 9.3)
 *
 *  Value to convert must be on stack top, and is popped before exit.
 *
 *  See: http://www.cs.indiana.edu/~burger/FP-Printing-PLDI96.pdf
 *       http://www.cs.indiana.edu/~burger/fp/index.html
 *
 *  Notes on the conversion:
 *
 *    - There are specific requirements on the accuracy of the conversion
 *      through a "Mathematical Value" (MV), so this conversion is not
 *      trivial.
 *
 *    - Quick rejects (e.g. based on first char) are difficult because
 *      the grammar allows leading and trailing white space.
 *
 *    - Quick reject based on string length is difficult even after
 *      accounting for white space; there may be arbitrarily many
 *      decimal digits.
 *
 *    - Standard grammar allows decimal values ("123"), hex values
 *      ("0x123") and infinities
 *
 *    - Unlike source code literals, ToNumber() coerces empty strings
 *      and strings with only whitespace to zero (not NaN).  However,
 *      while '' coerces to 0, '+' and '-' coerce to NaN.
 */

/* E5 Section 9.3.1 */
DUK_LOCAL duk_double_t duk__tonumber_string_raw(duk_hthread *thr) {
	duk_small_uint_t s2n_flags;
	duk_double_t d;

	DUK_ASSERT(duk_is_string(thr, -1));

	/* Quite lenient, e.g. allow empty as zero, but don't allow trailing
	 * garbage.
	 */
	s2n_flags = DUK_S2N_FLAG_TRIM_WHITE |
	            DUK_S2N_FLAG_ALLOW_EXP |
	            DUK_S2N_FLAG_ALLOW_PLUS |
	            DUK_S2N_FLAG_ALLOW_MINUS |
	            DUK_S2N_FLAG_ALLOW_INF |
	            DUK_S2N_FLAG_ALLOW_FRAC |
	            DUK_S2N_FLAG_ALLOW_NAKED_FRAC |
	            DUK_S2N_FLAG_ALLOW_EMPTY_FRAC |
	            DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO |
	            DUK_S2N_FLAG_ALLOW_LEADING_ZERO |
	            DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT |
	            DUK_S2N_FLAG_ALLOW_AUTO_OCT_INT |
	            DUK_S2N_FLAG_ALLOW_AUTO_BIN_INT;

	duk_numconv_parse(thr, 10 /*radix*/, s2n_flags);

#if defined(DUK_USE_PREFER_SIZE)
	d = duk_get_number(thr, -1);
	duk_pop_unsafe(thr);
#else
	thr->valstack_top--;
	DUK_ASSERT(DUK_TVAL_IS_NUMBER(thr->valstack_top));
	DUK_ASSERT(DUK_TVAL_IS_DOUBLE(thr->valstack_top));  /* no fastint conversion in numconv now */
	DUK_ASSERT(!DUK_TVAL_NEEDS_REFCOUNT_UPDATE(thr->valstack_top));
	d = DUK_TVAL_GET_DOUBLE(thr->valstack_top);  /* assumes not a fastint */
	DUK_TVAL_SET_UNDEFINED(thr->valstack_top);
#endif

	return d;
}

DUK_INTERNAL duk_double_t duk_js_tonumber(duk_hthread *thr, duk_tval *tv) {
	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(tv != NULL);

	switch (DUK_TVAL_GET_TAG(tv)) {
	case DUK_TAG_UNDEFINED: {
		/* return a specific NaN (although not strictly necessary) */
		duk_double_union du;
		DUK_DBLUNION_SET_NAN(&du);
		DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
		return du.d;
	}
	case DUK_TAG_NULL: {
		/* +0.0 */
		return 0.0;
	}
	case DUK_TAG_BOOLEAN: {
		if (DUK_TVAL_IS_BOOLEAN_TRUE(tv)) {
			return 1.0;
		}
		return 0.0;
	}
	case DUK_TAG_STRING: {
		/* For Symbols ToNumber() is always a TypeError. */
		duk_hstring *h = DUK_TVAL_GET_STRING(tv);
		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
			DUK_ERROR_TYPE(thr, DUK_STR_CANNOT_NUMBER_COERCE_SYMBOL);
			DUK_WO_NORETURN(return 0.0;);
		}
		duk_push_hstring(thr, h);
		return duk__tonumber_string_raw(thr);
	}
	case DUK_TAG_BUFFER:  /* plain buffer treated like object */
	case DUK_TAG_OBJECT: {
		duk_double_t d;
		duk_push_tval(thr, tv);
		duk_to_primitive(thr, -1, DUK_HINT_NUMBER);  /* 'tv' becomes invalid */

		/* recursive call for a primitive value (guaranteed not to cause second
		 * recursion).
		 */
		DUK_ASSERT(duk_get_tval(thr, -1) != NULL);
		d = duk_js_tonumber(thr, duk_get_tval(thr, -1));

		duk_pop_unsafe(thr);
		return d;
	}
	case DUK_TAG_POINTER: {
		/* Coerce like boolean */
		void *p = DUK_TVAL_GET_POINTER(tv);
		return (p != NULL ? 1.0 : 0.0);
	}
	case DUK_TAG_LIGHTFUNC: {
		/* +(function(){}) -> NaN */
		return DUK_DOUBLE_NAN;
	}
#if defined(DUK_USE_FASTINT)
	case DUK_TAG_FASTINT:
		return (duk_double_t) DUK_TVAL_GET_FASTINT(tv);
#endif
	default: {
		/* number */
		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
		DUK_ASSERT(DUK_TVAL_IS_DOUBLE(tv));
		return DUK_TVAL_GET_DOUBLE(tv);
	}
	}

	DUK_UNREACHABLE();
	DUK_WO_UNREACHABLE(return 0.0;);
}

/*
 *  ToInteger()  (E5 Section 9.4)
 */

/* exposed, used by e.g. duk_bi_date.c */
DUK_INTERNAL duk_double_t duk_js_tointeger_number(duk_double_t x) {
#if defined(DUK_USE_PREFER_SIZE)
	duk_small_int_t c = (duk_small_int_t) DUK_FPCLASSIFY(x);

	if (DUK_UNLIKELY(c == DUK_FP_NAN)) {
		return 0.0;
	} else if (DUK_UNLIKELY(c == DUK_FP_INFINITE)) {
		return x;
	} else {
		/* Finite, including neg/pos zero.  Neg zero sign must be
		 * preserved.
		 */
		return duk_double_trunc_towards_zero(x);
	}
#else  /* DUK_USE_PREFER_SIZE */
	/* NaN and Infinity have the same exponent so it's a cheap
	 * initial check for the rare path.
	 */
	if (DUK_UNLIKELY(duk_double_is_nan_or_inf(x) != 0U)) {
		if (duk_double_is_nan(x)) {
			return 0.0;
		} else {
			return x;
		}
	} else {
		return duk_double_trunc_towards_zero(x);
	}
#endif  /* DUK_USE_PREFER_SIZE */
}

DUK_INTERNAL duk_double_t duk_js_tointeger(duk_hthread *thr, duk_tval *tv) {
	/* XXX: fastint */
	duk_double_t d = duk_js_tonumber(thr, tv);  /* invalidates tv */
	return duk_js_tointeger_number(d);
}

/*
 *  ToInt32(), ToUint32(), ToUint16()  (E5 Sections 9.5, 9.6, 9.7)
 */

/* combined algorithm matching E5 Sections 9.5 and 9.6 */
DUK_LOCAL duk_double_t duk__toint32_touint32_helper(duk_double_t x, duk_bool_t is_toint32) {
#if defined (DUK_USE_PREFER_SIZE)
	duk_small_int_t c;
#endif

#if defined (DUK_USE_PREFER_SIZE)
	c = (duk_small_int_t) DUK_FPCLASSIFY(x);
	if (c == DUK_FP_NAN || c == DUK_FP_ZERO || c == DUK_FP_INFINITE) {
		return 0.0;
	}
#else
	if (duk_double_is_nan_zero_inf(x)) {
		return 0.0;
	}
#endif

	/* x = sign(x) * floor(abs(x)), i.e. truncate towards zero, keep sign */
	x = duk_double_trunc_towards_zero(x);

	/* NOTE: fmod(x) result sign is same as sign of x, which
	 * differs from what Javascript wants (see Section 9.6).
	 */

	x = DUK_FMOD(x, DUK_DOUBLE_2TO32);    /* -> x in ]-2**32, 2**32[ */

	if (x < 0.0) {
		x += DUK_DOUBLE_2TO32;
	}
	DUK_ASSERT(x >= 0 && x < DUK_DOUBLE_2TO32);  /* -> x in [0, 2**32[ */

	if (is_toint32) {
		if (x >= DUK_DOUBLE_2TO31) {
			/* x in [2**31, 2**32[ */

			x -= DUK_DOUBLE_2TO32;  /* -> x in [-2**31,2**31[ */
		}
	}

	return x;
}

DUK_INTERNAL duk_int32_t duk_js_toint32(duk_hthread *thr, duk_tval *tv) {
	duk_double_t d;

#if defined(DUK_USE_FASTINT)
	if (DUK_TVAL_IS_FASTINT(tv)) {
		return DUK_TVAL_GET_FASTINT_I32(tv);
	}
#endif

	d = duk_js_tonumber(thr, tv);  /* invalidates tv */
	d = duk__toint32_touint32_helper(d, 1);
	DUK_ASSERT(DUK_FPCLASSIFY(d) == DUK_FP_ZERO || DUK_FPCLASSIFY(d) == DUK_FP_NORMAL);
	DUK_ASSERT(d >= -2147483648.0 && d <= 2147483647.0);  /* [-0x80000000,0x7fffffff] */
	DUK_ASSERT(duk_double_equals(d, (duk_double_t) ((duk_int32_t) d)));  /* whole, won't clip */
	return (duk_int32_t) d;
}


DUK_INTERNAL duk_uint32_t duk_js_touint32(duk_hthread *thr, duk_tval *tv) {
	duk_double_t d;

#if defined(DUK_USE_FASTINT)
	if (DUK_TVAL_IS_FASTINT(tv)) {
		return DUK_TVAL_GET_FASTINT_U32(tv);
	}
#endif

	d = duk_js_tonumber(thr, tv);  /* invalidates tv */
	d = duk__toint32_touint32_helper(d, 0);
	DUK_ASSERT(DUK_FPCLASSIFY(d) == DUK_FP_ZERO || DUK_FPCLASSIFY(d) == DUK_FP_NORMAL);
	DUK_ASSERT(d >= 0.0 && d <= 4294967295.0);  /* [0x00000000, 0xffffffff] */
	DUK_ASSERT(duk_double_equals(d, (duk_double_t) ((duk_uint32_t) d)));  /* whole, won't clip */
	return (duk_uint32_t) d;

}

DUK_INTERNAL duk_uint16_t duk_js_touint16(duk_hthread *thr, duk_tval *tv) {
	/* should be a safe way to compute this */
	return (duk_uint16_t) (duk_js_touint32(thr, tv) & 0x0000ffffU);
}

/*
 *  ToString()  (E5 Section 9.8)
 *  ToObject()  (E5 Section 9.9)
 *  CheckObjectCoercible()  (E5 Section 9.10)
 *  IsCallable()  (E5 Section 9.11)
 *
 *  ==> implemented in the API.
 */

/*
 *  Loose equality, strict equality, and SameValue (E5 Sections 11.9.1, 11.9.4,
 *  9.12).  These have much in common so they can share some helpers.
 *
 *  Future work notes:
 *
 *    - Current implementation (and spec definition) has recursion; this should
 *      be fixed if possible.
 *
 *    - String-to-number coercion should be possible without going through the
 *      value stack (and be more compact) if a shared helper is invoked.
 */

/* Note that this is the same operation for strict and loose equality:
 *  - E5 Section 11.9.3, step 1.c (loose)
 *  - E5 Section 11.9.6, step 4 (strict)
 */

DUK_LOCAL duk_bool_t duk__js_equals_number(duk_double_t x, duk_double_t y) {
#if defined(DUK_USE_PARANOID_MATH)
	/* Straightforward algorithm, makes fewer compiler assumptions. */
	duk_small_int_t cx = (duk_small_int_t) DUK_FPCLASSIFY(x);
	duk_small_int_t cy = (duk_small_int_t) DUK_FPCLASSIFY(y);
	if (cx == DUK_FP_NAN || cy == DUK_FP_NAN) {
		return 0;
	}
	if (cx == DUK_FP_ZERO && cy == DUK_FP_ZERO) {
		return 1;
	}
	if (x == y) {
		return 1;
	}
	return 0;
#else  /* DUK_USE_PARANOID_MATH */
	/* Better equivalent algorithm.  If the compiler is compliant, C and
	 * ECMAScript semantics are identical for this particular comparison.
	 * In particular, NaNs must never compare equal and zeroes must compare
	 * equal regardless of sign.  Could also use a macro, but this inlines
	 * already nicely (no difference on gcc, for instance).
	 */
	if (duk_double_equals(x, y)) {
		/* IEEE requires that NaNs compare false */
		DUK_ASSERT(DUK_FPCLASSIFY(x) != DUK_FP_NAN);
		DUK_ASSERT(DUK_FPCLASSIFY(y) != DUK_FP_NAN);
		return 1;
	} else {
		/* IEEE requires that zeros compare the same regardless
		 * of their signed, so if both x and y are zeroes, they
		 * are caught above.
		 */
		DUK_ASSERT(!(DUK_FPCLASSIFY(x) == DUK_FP_ZERO && DUK_FPCLASSIFY(y) == DUK_FP_ZERO));
		return 0;
	}
#endif  /* DUK_USE_PARANOID_MATH */
}

DUK_LOCAL duk_bool_t duk__js_samevalue_number(duk_double_t x, duk_double_t y) {
#if defined(DUK_USE_PARANOID_MATH)
	duk_small_int_t cx = (duk_small_int_t) DUK_FPCLASSIFY(x);
	duk_small_int_t cy = (duk_small_int_t) DUK_FPCLASSIFY(y);

	if (cx == DUK_FP_NAN && cy == DUK_FP_NAN) {
		/* SameValue(NaN, NaN) = true, regardless of NaN sign or extra bits */
		return 1;
	}
	if (cx == DUK_FP_ZERO && cy == DUK_FP_ZERO) {
		/* Note: cannot assume that a non-zero return value of signbit() would
		 * always be the same -- hence cannot (portably) use something like:
		 *
		 *     signbit(x) == signbit(y)
		 */
		duk_small_int_t sx = DUK_SIGNBIT(x) ? 1 : 0;
		duk_small_int_t sy = DUK_SIGNBIT(y) ? 1 : 0;
		return (sx == sy);
	}

	/* normal comparison; known:
	 *   - both x and y are not NaNs (but one of them can be)
	 *   - both x and y are not zero (but one of them can be)
	 *   - x and y may be denormal or infinite
	 */

	return (x == y);
#else  /* DUK_USE_PARANOID_MATH */
	duk_small_int_t cx = (duk_small_int_t) DUK_FPCLASSIFY(x);
	duk_small_int_t cy = (duk_small_int_t) DUK_FPCLASSIFY(y);

	if (duk_double_equals(x, y)) {
		/* IEEE requires that NaNs compare false */
		DUK_ASSERT(DUK_FPCLASSIFY(x) != DUK_FP_NAN);
		DUK_ASSERT(DUK_FPCLASSIFY(y) != DUK_FP_NAN);

		/* Using classification has smaller footprint than direct comparison. */
		if (DUK_UNLIKELY(cx == DUK_FP_ZERO && cy == DUK_FP_ZERO)) {
			/* Note: cannot assume that a non-zero return value of signbit() would
			 * always be the same -- hence cannot (portably) use something like:
			 *
			 *     signbit(x) == signbit(y)
			 */
			return duk_double_same_sign(x, y);
		}
		return 1;
	} else {
		/* IEEE requires that zeros compare the same regardless
		 * of their sign, so if both x and y are zeroes, they
		 * are caught above.
		 */
		DUK_ASSERT(!(DUK_FPCLASSIFY(x) == DUK_FP_ZERO && DUK_FPCLASSIFY(y) == DUK_FP_ZERO));

		/* Difference to non-strict/strict comparison is that NaNs compare
		 * equal and signed zero signs matter.
		 */
		if (DUK_UNLIKELY(cx == DUK_FP_NAN && cy == DUK_FP_NAN)) {
			/* SameValue(NaN, NaN) = true, regardless of NaN sign or extra bits */
			return 1;
		}
		return 0;
	}
#endif  /* DUK_USE_PARANOID_MATH */
}

DUK_INTERNAL duk_bool_t duk_js_equals_helper(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_uint_t flags) {
	duk_uint_t type_mask_x;
	duk_uint_t type_mask_y;

	/* If flags != 0 (strict or SameValue), thr can be NULL.  For loose
	 * equals comparison it must be != NULL.
	 */
	DUK_ASSERT(flags != 0 || thr != NULL);

	/*
	 *  Same type?
	 *
	 *  Note: since number values have no explicit tag in the 8-byte
	 *  representation, need the awkward if + switch.
	 */

#if defined(DUK_USE_FASTINT)
	if (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {
		if (DUK_TVAL_GET_FASTINT(tv_x) == DUK_TVAL_GET_FASTINT(tv_y)) {
			return 1;
		} else {
			return 0;
		}
	}
	else
#endif
	if (DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y)) {
		duk_double_t d1, d2;

		/* Catches both doubles and cases where only one argument is
		 * a fastint so can't assume a double.
		 */
		d1 = DUK_TVAL_GET_NUMBER(tv_x);
		d2 = DUK_TVAL_GET_NUMBER(tv_y);
		if (DUK_UNLIKELY((flags & DUK_EQUALS_FLAG_SAMEVALUE) != 0)) {
			/* SameValue */
			return duk__js_samevalue_number(d1, d2);
		} else {
			/* equals and strict equals */
			return duk__js_equals_number(d1, d2);
		}
	} else if (DUK_TVAL_GET_TAG(tv_x) == DUK_TVAL_GET_TAG(tv_y)) {
		switch (DUK_TVAL_GET_TAG(tv_x)) {
		case DUK_TAG_UNDEFINED:
		case DUK_TAG_NULL: {
			return 1;
		}
		case DUK_TAG_BOOLEAN: {
			return DUK_TVAL_GET_BOOLEAN(tv_x) == DUK_TVAL_GET_BOOLEAN(tv_y);
		}
		case DUK_TAG_POINTER: {
			return DUK_TVAL_GET_POINTER(tv_x) == DUK_TVAL_GET_POINTER(tv_y);
		}
		case DUK_TAG_STRING:
		case DUK_TAG_OBJECT: {
			/* Heap pointer comparison suffices for strings and objects.
			 * Symbols compare equal if they have the same internal
			 * representation; again heap pointer comparison suffices.
			 */
			return DUK_TVAL_GET_HEAPHDR(tv_x) == DUK_TVAL_GET_HEAPHDR(tv_y);
		}
		case DUK_TAG_BUFFER: {
			/* In Duktape 2.x plain buffers mimic Uint8Array objects
			 * so always compare by heap pointer.  In Duktape 1.x
			 * strict comparison would compare heap pointers and
			 * non-strict would compare contents.
			 */
			return DUK_TVAL_GET_HEAPHDR(tv_x) == DUK_TVAL_GET_HEAPHDR(tv_y);
		}
		case DUK_TAG_LIGHTFUNC: {
			/* At least 'magic' has a significant impact on function
			 * identity.
			 */
			duk_small_uint_t lf_flags_x;
			duk_small_uint_t lf_flags_y;
			duk_c_function func_x;
			duk_c_function func_y;

			DUK_TVAL_GET_LIGHTFUNC(tv_x, func_x, lf_flags_x);
			DUK_TVAL_GET_LIGHTFUNC(tv_y, func_y, lf_flags_y);
			return ((func_x == func_y) && (lf_flags_x == lf_flags_y)) ? 1 : 0;
		}
#if defined(DUK_USE_FASTINT)
		case DUK_TAG_FASTINT:
#endif
		default: {
			DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv_x));
			DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv_y));
			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_x));
			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_y));
			DUK_UNREACHABLE();
			DUK_WO_UNREACHABLE(return 0;);
		}
		}
	}

	if ((flags & (DUK_EQUALS_FLAG_STRICT | DUK_EQUALS_FLAG_SAMEVALUE)) != 0) {
		return 0;
	}

	DUK_ASSERT(flags == 0);  /* non-strict equality from here on */

	/*
	 *  Types are different; various cases for non-strict comparison
	 *
	 *  Since comparison is symmetric, we use a "swap trick" to reduce
	 *  code size.
	 */

	type_mask_x = duk_get_type_mask_tval(tv_x);
	type_mask_y = duk_get_type_mask_tval(tv_y);

	/* Undefined/null are considered equal (e.g. "null == undefined" -> true). */
	if ((type_mask_x & (DUK_TYPE_MASK_UNDEFINED | DUK_TYPE_MASK_NULL)) &&
	    (type_mask_y & (DUK_TYPE_MASK_NULL | DUK_TYPE_MASK_UNDEFINED))) {
		return 1;
	}

	/* Number/string -> coerce string to number (e.g. "'1.5' == 1.5" -> true). */
	if ((type_mask_x & DUK_TYPE_MASK_NUMBER) && (type_mask_y & DUK_TYPE_MASK_STRING)) {
		if (!DUK_TVAL_STRING_IS_SYMBOL(tv_y)) {
			duk_double_t d1, d2;
			d1 = DUK_TVAL_GET_NUMBER(tv_x);
			d2 = duk_to_number_tval(thr, tv_y);
			return duk__js_equals_number(d1, d2);
		}
	}
	if ((type_mask_x & DUK_TYPE_MASK_STRING) && (type_mask_y & DUK_TYPE_MASK_NUMBER)) {
		if (!DUK_TVAL_STRING_IS_SYMBOL(tv_x)) {
			duk_double_t d1, d2;
			d1 = DUK_TVAL_GET_NUMBER(tv_y);
			d2 = duk_to_number_tval(thr, tv_x);
			return duk__js_equals_number(d1, d2);
		}
	}

	/* Boolean/any -> coerce boolean to number and try again.  If boolean is
	 * compared to a pointer, the final comparison after coercion now always
	 * yields false (as pointer vs. number compares to false), but this is
	 * not special cased.
	 *
	 * ToNumber(bool) is +1.0 or 0.0.  Tagged boolean value is always 0 or 1.
	 */
	if (type_mask_x & DUK_TYPE_MASK_BOOLEAN) {
		DUK_ASSERT(DUK_TVAL_GET_BOOLEAN(tv_x) == 0 || DUK_TVAL_GET_BOOLEAN(tv_x) == 1);
		duk_push_uint(thr, DUK_TVAL_GET_BOOLEAN(tv_x));
		duk_push_tval(thr, tv_y);
		goto recursive_call;
	}
	if (type_mask_y & DUK_TYPE_MASK_BOOLEAN) {
		DUK_ASSERT(DUK_TVAL_GET_BOOLEAN(tv_y) == 0 || DUK_TVAL_GET_BOOLEAN(tv_y) == 1);
		duk_push_tval(thr, tv_x);
		duk_push_uint(thr, DUK_TVAL_GET_BOOLEAN(tv_y));
		goto recursive_call;
	}

	/* String-number-symbol/object -> coerce object to primitive (apparently without hint), then try again. */
	if ((type_mask_x & (DUK_TYPE_MASK_STRING | DUK_TYPE_MASK_NUMBER)) &&
	    (type_mask_y & DUK_TYPE_MASK_OBJECT)) {
		/* No symbol check needed because symbols and strings are accepted. */
		duk_push_tval(thr, tv_x);
		duk_push_tval(thr, tv_y);
		duk_to_primitive(thr, -1, DUK_HINT_NONE);  /* apparently no hint? */
		goto recursive_call;
	}
	if ((type_mask_x & DUK_TYPE_MASK_OBJECT) &&
	    (type_mask_y & (DUK_TYPE_MASK_STRING | DUK_TYPE_MASK_NUMBER))) {
		/* No symbol check needed because symbols and strings are accepted. */
		duk_push_tval(thr, tv_x);
		duk_push_tval(thr, tv_y);
		duk_to_primitive(thr, -2, DUK_HINT_NONE);  /* apparently no hint? */
		goto recursive_call;
	}

	/* Nothing worked -> not equal. */
	return 0;

 recursive_call:
	/* Shared code path to call the helper again with arguments on stack top. */
	{
		duk_bool_t rc;
		rc = duk_js_equals_helper(thr,
		                          DUK_GET_TVAL_NEGIDX(thr, -2),
		                          DUK_GET_TVAL_NEGIDX(thr, -1),
		                          0 /*flags:nonstrict*/);
		duk_pop_2_unsafe(thr);
		return rc;
	}
}

/*
 *  Comparisons (x >= y, x > y, x <= y, x < y)
 *
 *  E5 Section 11.8.5: implement 'x < y' and then use negate and eval_left_first
 *  flags to get the rest.
 */

/* XXX: this should probably just operate on the stack top, because it
 * needs to push stuff on the stack anyway...
 */

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) {
	duk_size_t prefix_len;
	duk_small_int_t rc;

	prefix_len = (len1 <= len2 ? len1 : len2);

	/* duk_memcmp() is guaranteed to return zero (equal) for zero length
	 * inputs.
	 */
	rc = duk_memcmp_unsafe((const void *) buf1,
	                       (const void *) buf2,
	                       (size_t) prefix_len);

	if (rc < 0) {
		return -1;
	} else if (rc > 0) {
		return 1;
	}

	/* prefix matches, lengths matter now */
	if (len1 < len2) {
		/* e.g. "x" < "xx" */
		return -1;
	} else if (len1 > len2) {
		return 1;
	}

	return 0;
}

DUK_INTERNAL duk_small_int_t duk_js_string_compare(duk_hstring *h1, duk_hstring *h2) {
	/*
	 *  String comparison (E5 Section 11.8.5, step 4), which
	 *  needs to compare codepoint by codepoint.
	 *
	 *  However, UTF-8 allows us to use strcmp directly: the shared
	 *  prefix will be encoded identically (UTF-8 has unique encoding)
	 *  and the first differing character can be compared with a simple
	 *  unsigned byte comparison (which strcmp does).
	 *
	 *  This will not work properly for non-xutf-8 strings, but this
	 *  is not an issue for compliance.
	 */

	DUK_ASSERT(h1 != NULL);
	DUK_ASSERT(h2 != NULL);

	return duk_js_data_compare((const duk_uint8_t *) DUK_HSTRING_GET_DATA(h1),
	                           (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h2),
	                           (duk_size_t) DUK_HSTRING_GET_BYTELEN(h1),
	                           (duk_size_t) DUK_HSTRING_GET_BYTELEN(h2));
}

#if 0  /* unused */
DUK_INTERNAL duk_small_int_t duk_js_buffer_compare(duk_heap *heap, duk_hbuffer *h1, duk_hbuffer *h2) {
	/* Similar to String comparison. */

	DUK_ASSERT(h1 != NULL);
	DUK_ASSERT(h2 != NULL);
	DUK_UNREF(heap);

	return duk_js_data_compare((const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(heap, h1),
	                           (const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(heap, h2),
	                           (duk_size_t) DUK_HBUFFER_GET_SIZE(h1),
	                           (duk_size_t) DUK_HBUFFER_GET_SIZE(h2));
}
#endif

#if defined(DUK_USE_FASTINT)
DUK_LOCAL duk_bool_t duk__compare_fastint(duk_bool_t retval, duk_int64_t v1, duk_int64_t v2) {
	DUK_ASSERT(retval == 0 || retval == 1);
	if (v1 < v2) {
		return retval ^ 1;
	} else {
		return retval;
	}
}
#endif

#if defined(DUK_USE_PARANOID_MATH)
DUK_LOCAL duk_bool_t duk__compare_number(duk_bool_t retval, duk_double_t d1, duk_double_t d2) {
	duk_small_int_t c1, s1, c2, s2;

	DUK_ASSERT(retval == 0 || retval == 1);
	c1 = (duk_small_int_t) DUK_FPCLASSIFY(d1);
	s1 = (duk_small_int_t) DUK_SIGNBIT(d1);
	c2 = (duk_small_int_t) DUK_FPCLASSIFY(d2);
	s2 = (duk_small_int_t) DUK_SIGNBIT(d2);

	if (c1 == DUK_FP_NAN || c2 == DUK_FP_NAN) {
		return 0;  /* Always false, regardless of negation. */
	}

	if (c1 == DUK_FP_ZERO && c2 == DUK_FP_ZERO) {
		/* For all combinations: +0 < +0, +0 < -0, -0 < +0, -0 < -0,
		 * steps e, f, and g.
		 */
		return retval;  /* false */
	}

	if (d1 == d2) {
		return retval;  /* false */
	}

	if (c1 == DUK_FP_INFINITE && s1 == 0) {
		/* x == +Infinity */
		return retval;  /* false */
	}

	if (c2 == DUK_FP_INFINITE && s2 == 0) {
		/* y == +Infinity */
		return retval ^ 1;  /* true */
	}

	if (c2 == DUK_FP_INFINITE && s2 != 0) {
		/* y == -Infinity */
		return retval;  /* false */
	}

	if (c1 == DUK_FP_INFINITE && s1 != 0) {
		/* x == -Infinity */
		return retval ^ 1;  /* true */
	}

	if (d1 < d2) {
		return retval ^ 1;  /* true */
	}

	return retval;  /* false */
}
#else  /* DUK_USE_PARANOID_MATH */
DUK_LOCAL duk_bool_t duk__compare_number(duk_bool_t retval, duk_double_t d1, duk_double_t d2) {
	/* This comparison tree relies doesn't match the exact steps in
	 * E5 Section 11.8.5 but should produce the same results.  The
	 * steps rely on exact IEEE semantics for NaNs, etc.
	 */

	DUK_ASSERT(retval == 0 || retval == 1);
	if (d1 < d2) {
		/* In no case should both (d1 < d2) and (d2 < d1) be true.
		 * It's possible that neither is true though, and that's
		 * handled below.
		 */
		DUK_ASSERT(!(d2 < d1));

		/* - d1 < d2, both d1/d2 are normals (not Infinity, not NaN)
		 * - d2 is +Infinity, d1 != +Infinity and NaN
		 * - d1 is -Infinity, d2 != -Infinity and NaN
		 */
		return retval ^ 1;
	} else {
		if (d2 < d1) {
			/* - !(d1 < d2), both d1/d2 are normals (not Infinity, not NaN)
			 * - d1 is +Infinity, d2 != +Infinity and NaN
			 * - d2 is -Infinity, d1 != -Infinity and NaN
			 */
			return retval;
		} else {
			/* - d1 and/or d2 is NaN
			 * - d1 and d2 are both +/- 0
			 * - d1 == d2 (including infinities)
			 */
			if (duk_double_is_nan(d1) || duk_double_is_nan(d2)) {
				/* Note: undefined from Section 11.8.5 always
				 * results in false return (see e.g. Section
				 * 11.8.3) - hence special treatment here.
				 */
				return 0;  /* zero regardless of negation */
			} else {
				return retval;
			}
		}
	}
}
#endif  /* DUK_USE_PARANOID_MATH */

DUK_INTERNAL duk_bool_t duk_js_compare_helper(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_uint_t flags) {
	duk_double_t d1, d2;
	duk_small_int_t rc;
	duk_bool_t retval;

	DUK_ASSERT(DUK_COMPARE_FLAG_NEGATE == 1);  /* Rely on this flag being lowest. */
	retval = flags & DUK_COMPARE_FLAG_NEGATE;
	DUK_ASSERT(retval == 0 || retval == 1);

	/* Fast path for fastints */
#if defined(DUK_USE_FASTINT)
	if (DUK_LIKELY(DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y))) {
		return duk__compare_fastint(retval,
		                            DUK_TVAL_GET_FASTINT(tv_x),
		                            DUK_TVAL_GET_FASTINT(tv_y));
	}
#endif  /* DUK_USE_FASTINT */

	/* Fast path for numbers (one of which may be a fastint) */
#if !defined(DUK_USE_PREFER_SIZE)
	if (DUK_LIKELY(DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y))) {
		return duk__compare_number(retval,
		                           DUK_TVAL_GET_NUMBER(tv_x),
		                           DUK_TVAL_GET_NUMBER(tv_y));
	}
#endif

	/* Slow path */

	duk_push_tval(thr, tv_x);
	duk_push_tval(thr, tv_y);

	if (flags & DUK_COMPARE_FLAG_EVAL_LEFT_FIRST) {
		duk_to_primitive(thr, -2, DUK_HINT_NUMBER);
		duk_to_primitive(thr, -1, DUK_HINT_NUMBER);
	} else {
		duk_to_primitive(thr, -1, DUK_HINT_NUMBER);
		duk_to_primitive(thr, -2, DUK_HINT_NUMBER);
	}

	/* Note: reuse variables */
	tv_x = DUK_GET_TVAL_NEGIDX(thr, -2);
	tv_y = DUK_GET_TVAL_NEGIDX(thr, -1);

	if (DUK_TVAL_IS_STRING(tv_x) && DUK_TVAL_IS_STRING(tv_y)) {
		duk_hstring *h1 = DUK_TVAL_GET_STRING(tv_x);
		duk_hstring *h2 = DUK_TVAL_GET_STRING(tv_y);
		DUK_ASSERT(h1 != NULL);
		DUK_ASSERT(h2 != NULL);

		if (DUK_LIKELY(!DUK_HSTRING_HAS_SYMBOL(h1) && !DUK_HSTRING_HAS_SYMBOL(h2))) {
			rc = duk_js_string_compare(h1, h2);
			duk_pop_2_unsafe(thr);
			if (rc < 0) {
				return retval ^ 1;
			} else {
				return retval;
			}
		}

		/* One or both are Symbols: fall through to handle in the
		 * generic path.  Concretely, ToNumber() will fail.
		 */
	}

	/* Ordering should not matter (E5 Section 11.8.5, step 3.a). */
#if 0
	if (flags & DUK_COMPARE_FLAG_EVAL_LEFT_FIRST) {
		d1 = duk_to_number_m2(thr);
		d2 = duk_to_number_m1(thr);
	} else {
		d2 = duk_to_number_m1(thr);
		d1 = duk_to_number_m2(thr);
	}
#endif
	d1 = duk_to_number_m2(thr);
	d2 = duk_to_number_m1(thr);

	/* We want to duk_pop_2_unsafe(thr); because the values are numbers
	 * no decref check is needed.
	 */
#if defined(DUK_USE_PREFER_SIZE)
	duk_pop_2_nodecref_unsafe(thr);
#else
	DUK_ASSERT(!DUK_TVAL_NEEDS_REFCOUNT_UPDATE(duk_get_tval(thr, -2)));
	DUK_ASSERT(!DUK_TVAL_NEEDS_REFCOUNT_UPDATE(duk_get_tval(thr, -1)));
	DUK_ASSERT(duk_get_top(thr) >= 2);
	thr->valstack_top -= 2;
	tv_x = thr->valstack_top;
	tv_y = tv_x + 1;
	DUK_TVAL_SET_UNDEFINED(tv_x);  /* Value stack policy */
	DUK_TVAL_SET_UNDEFINED(tv_y);
#endif

	return duk__compare_number(retval, d1, d2);
}

/*
 *  instanceof
 */

/*
 *  ES2015 Section 7.3.19 describes the OrdinaryHasInstance() algorithm
 *  which covers both bound and non-bound functions; in effect the algorithm
 *  includes E5 Sections 11.8.6, 15.3.5.3, and 15.3.4.5.3.
 *
 *  ES2015 Section 12.9.4 describes the instanceof operator which first
 *  checks @@hasInstance well-known symbol and falls back to
 *  OrdinaryHasInstance().
 *
 *  Limited Proxy support: don't support 'getPrototypeOf' trap but
 *  continue lookup in Proxy target if the value is a Proxy.
 */

DUK_LOCAL duk_bool_t duk__js_instanceof_helper(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_bool_t skip_sym_check) {
	duk_hobject *func;
	duk_hobject *val;
	duk_hobject *proto;
	duk_tval *tv;
	duk_bool_t skip_first;
	duk_uint_t sanity;

	/*
	 *  Get the values onto the stack first.  It would be possible to cover
	 *  some normal cases without resorting to the value stack.
	 *
	 *  The right hand side could be a light function (as they generally
	 *  behave like objects).  Light functions never have a 'prototype'
	 *  property so E5.1 Section 15.3.5.3 step 3 always throws a TypeError.
	 *  Using duk_require_hobject() is thus correct (except for error msg).
	 */

	duk_push_tval(thr, tv_x);
	duk_push_tval(thr, tv_y);
	func = duk_require_hobject(thr, -1);
	DUK_ASSERT(func != NULL);

#if defined(DUK_USE_SYMBOL_BUILTIN)
	/*
	 *  @@hasInstance check, ES2015 Section 12.9.4, Steps 2-4.
	 */
	if (!skip_sym_check) {
		if (duk_get_method_stridx(thr, -1, DUK_STRIDX_WELLKNOWN_SYMBOL_HAS_INSTANCE)) {
			/* [ ... lhs rhs func ] */
			duk_insert(thr, -3);    /* -> [ ... func lhs rhs ] */
			duk_swap_top(thr, -2);  /* -> [ ... func rhs(this) lhs ] */
			duk_call_method(thr, 1);
			return duk_to_boolean_top_pop(thr);
		}
	}
#else
	DUK_UNREF(skip_sym_check);
#endif

	/*
	 *  For bound objects, [[HasInstance]] just calls the target function
	 *  [[HasInstance]].  If that is again a bound object, repeat until
	 *  we find a non-bound Function object.
	 *
	 *  The bound function chain is now "collapsed" so there can be only
	 *  one bound function in the chain.
	 */

	if (!DUK_HOBJECT_IS_CALLABLE(func)) {
		/*
		 *  Note: of native ECMAScript objects, only Function instances
		 *  have a [[HasInstance]] internal property.  Custom objects might
		 *  also have it, but not in current implementation.
		 *
		 *  XXX: add a separate flag, DUK_HOBJECT_FLAG_ALLOW_INSTANCEOF?
		 */
		goto error_invalid_rval;
	}

	if (DUK_HOBJECT_HAS_BOUNDFUNC(func)) {
		duk_push_tval(thr, &((duk_hboundfunc *) (void *) func)->target);
		duk_replace(thr, -2);
		func = duk_require_hobject(thr, -1);  /* lightfunc throws */

		/* Rely on Function.prototype.bind() never creating bound
		 * functions whose target is not proper.
		 */
		DUK_ASSERT(func != NULL);
		DUK_ASSERT(DUK_HOBJECT_IS_CALLABLE(func));
	}

	/*
	 *  'func' is now a non-bound object which supports [[HasInstance]]
	 *  (which here just means DUK_HOBJECT_FLAG_CALLABLE).  Move on
	 *  to execute E5 Section 15.3.5.3.
	 */

	DUK_ASSERT(func != NULL);
	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(func));
	DUK_ASSERT(DUK_HOBJECT_IS_CALLABLE(func));

	/* [ ... lval rval(func) ] */

	/* For lightfuncs, buffers, and pointers start the comparison directly
	 * from the virtual prototype object.
	 */
	skip_first = 0;
	tv = DUK_GET_TVAL_NEGIDX(thr, -2);
	switch (DUK_TVAL_GET_TAG(tv)) {
	case DUK_TAG_LIGHTFUNC:
		val = thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE];
		DUK_ASSERT(val != NULL);
		break;
	case DUK_TAG_BUFFER:
		val = thr->builtins[DUK_BIDX_UINT8ARRAY_PROTOTYPE];
		DUK_ASSERT(val != NULL);
		break;
	case DUK_TAG_POINTER:
		val = thr->builtins[DUK_BIDX_POINTER_PROTOTYPE];
		DUK_ASSERT(val != NULL);
		break;
	case DUK_TAG_OBJECT:
		skip_first = 1;  /* Ignore object itself on first round. */
		val = DUK_TVAL_GET_OBJECT(tv);
		DUK_ASSERT(val != NULL);
		break;
	default:
		goto pop2_and_false;
	}
	DUK_ASSERT(val != NULL);  /* Loop doesn't actually rely on this. */

	/* Look up .prototype of rval.  Leave it on the value stack in case it
	 * has been virtualized (e.g. getter, Proxy trap).
	 */
	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_PROTOTYPE);  /* -> [ ... lval rval rval.prototype ] */
#if defined(DUK_USE_VERBOSE_ERRORS)
	proto = duk_get_hobject(thr, -1);
	if (proto == NULL) {
		goto error_invalid_rval_noproto;
	}
#else
	proto = duk_require_hobject(thr, -1);
#endif

	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
	do {
		/*
		 *  Note: prototype chain is followed BEFORE first comparison.  This
		 *  means that the instanceof lval is never itself compared to the
		 *  rval.prototype property.  This is apparently intentional, see E5
		 *  Section 15.3.5.3, step 4.a.
		 *
		 *  Also note:
		 *
		 *      js> (function() {}) instanceof Function
		 *      true
		 *      js> Function instanceof Function
		 *      true
		 *
		 *  For the latter, h_proto will be Function.prototype, which is the
		 *  built-in Function prototype.  Because Function.[[Prototype]] is
		 *  also the built-in Function prototype, the result is true.
		 */

		if (!val) {
			goto pop3_and_false;
		}

		DUK_ASSERT(val != NULL);
#if defined(DUK_USE_ES6_PROXY)
		val = duk_hobject_resolve_proxy_target(val);
#endif

		if (skip_first) {
			skip_first = 0;
		} else if (val == proto) {
			goto pop3_and_true;
		}

		DUK_ASSERT(val != NULL);
		val = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, val);
	} while (--sanity > 0);

	DUK_ASSERT(sanity == 0);
	DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
	DUK_WO_NORETURN(return 0;);

 pop2_and_false:
	duk_pop_2_unsafe(thr);
	return 0;

 pop3_and_false:
	duk_pop_3_unsafe(thr);
	return 0;

 pop3_and_true:
	duk_pop_3_unsafe(thr);
	return 1;

 error_invalid_rval:
	DUK_ERROR_TYPE(thr, DUK_STR_INVALID_INSTANCEOF_RVAL);
	DUK_WO_NORETURN(return 0;);

#if defined(DUK_USE_VERBOSE_ERRORS)
 error_invalid_rval_noproto:
	DUK_ERROR_TYPE(thr, DUK_STR_INVALID_INSTANCEOF_RVAL_NOPROTO);
	DUK_WO_NORETURN(return 0;);
#endif
}

#if defined(DUK_USE_SYMBOL_BUILTIN)
DUK_INTERNAL duk_bool_t duk_js_instanceof_ordinary(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y) {
	return duk__js_instanceof_helper(thr, tv_x, tv_y, 1 /*skip_sym_check*/);
}
#endif

DUK_INTERNAL duk_bool_t duk_js_instanceof(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y) {
	return duk__js_instanceof_helper(thr, tv_x, tv_y, 0 /*skip_sym_check*/);
}

/*
 *  in
 */

/*
 *  E5 Sections 11.8.7, 8.12.6.
 *
 *  Basically just a property existence check using [[HasProperty]].
 */

DUK_INTERNAL duk_bool_t duk_js_in(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y) {
	duk_bool_t retval;

	/*
	 *  Get the values onto the stack first.  It would be possible to cover
	 *  some normal cases without resorting to the value stack (e.g. if
	 *  lval is already a string).
	 */

	/* XXX: The ES5/5.1/6 specifications require that the key in 'key in obj'
	 * must be string coerced before the internal HasProperty() algorithm is
	 * invoked.  A fast path skipping coercion could be safely implemented for
	 * numbers (as number-to-string coercion has no side effects).  For ES2015
	 * proxy behavior, the trap 'key' argument must be in a string coerced
	 * form (which is a shame).
	 */

	/* TypeError if rval is not an object or object like (e.g. lightfunc
	 * or plain buffer).
	 */
	duk_push_tval(thr, tv_x);
	duk_push_tval(thr, tv_y);
	duk_require_type_mask(thr, -1, DUK_TYPE_MASK_OBJECT | DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);

	(void) duk_to_property_key_hstring(thr, -2);

	retval = duk_hobject_hasprop(thr,
	                             DUK_GET_TVAL_NEGIDX(thr, -1),
	                             DUK_GET_TVAL_NEGIDX(thr, -2));

	duk_pop_2_unsafe(thr);
	return retval;
}

/*
 *  typeof
 *
 *  E5 Section 11.4.3.
 *
 *  Very straightforward.  The only question is what to return for our
 *  non-standard tag / object types.
 *
 *  There is an unfortunate string constant define naming problem with
 *  typeof return values for e.g. "Object" and "object"; careful with
 *  the built-in string defines.  The LC_XXX defines are used for the
 *  lowercase variants now.
 */

DUK_INTERNAL duk_small_uint_t duk_js_typeof_stridx(duk_tval *tv_x) {
	duk_small_uint_t stridx = 0;

	switch (DUK_TVAL_GET_TAG(tv_x)) {
	case DUK_TAG_UNDEFINED: {
		stridx = DUK_STRIDX_LC_UNDEFINED;
		break;
	}
	case DUK_TAG_NULL: {
		/* Note: not a typo, "object" is returned for a null value. */
		stridx = DUK_STRIDX_LC_OBJECT;
		break;
	}
	case DUK_TAG_BOOLEAN: {
		stridx = DUK_STRIDX_LC_BOOLEAN;
		break;
	}
	case DUK_TAG_POINTER: {
		/* Implementation specific. */
		stridx = DUK_STRIDX_LC_POINTER;
		break;
	}
	case DUK_TAG_STRING: {
		duk_hstring *str;

		/* All internal keys are identified as Symbols. */
		str = DUK_TVAL_GET_STRING(tv_x);
		DUK_ASSERT(str != NULL);
		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(str))) {
			stridx = DUK_STRIDX_LC_SYMBOL;
		} else {
			stridx = DUK_STRIDX_LC_STRING;
		}
		break;
	}
	case DUK_TAG_OBJECT: {
		duk_hobject *obj = DUK_TVAL_GET_OBJECT(tv_x);
		DUK_ASSERT(obj != NULL);
		if (DUK_HOBJECT_IS_CALLABLE(obj)) {
			stridx = DUK_STRIDX_LC_FUNCTION;
		} else {
			stridx = DUK_STRIDX_LC_OBJECT;
		}
		break;
	}
	case DUK_TAG_BUFFER: {
		/* Implementation specific.  In Duktape 1.x this would be
		 * 'buffer', in Duktape 2.x changed to 'object' because plain
		 * buffers now mimic Uint8Array objects.
		 */
		stridx = DUK_STRIDX_LC_OBJECT;
		break;
	}
	case DUK_TAG_LIGHTFUNC: {
		stridx = DUK_STRIDX_LC_FUNCTION;
		break;
	}
#if defined(DUK_USE_FASTINT)
	case DUK_TAG_FASTINT:
#endif
	default: {
		/* number */
		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv_x));
		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_x));
		stridx = DUK_STRIDX_LC_NUMBER;
		break;
	}
	}

	DUK_ASSERT_STRIDX_VALID(stridx);
	return stridx;
}

/*
 *  IsArray()
 */

DUK_INTERNAL duk_bool_t duk_js_isarray_hobject(duk_hobject *h) {
	DUK_ASSERT(h != NULL);
#if defined(DUK_USE_ES6_PROXY)
	h = duk_hobject_resolve_proxy_target(h);
#endif
	return (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAY ? 1 : 0);
}

DUK_INTERNAL duk_bool_t duk_js_isarray(duk_tval *tv) {
	DUK_ASSERT(tv != NULL);
	if (DUK_TVAL_IS_OBJECT(tv)) {
		return duk_js_isarray_hobject(DUK_TVAL_GET_OBJECT(tv));
	}
	return 0;
}

/*
 *  Array index and length
 *
 *  Array index: E5 Section 15.4
 *  Array length: E5 Section 15.4.5.1 steps 3.c - 3.d (array length write)
 */

/* Compure array index from string context, or return a "not array index"
 * indicator.
 */
DUK_INTERNAL duk_uarridx_t duk_js_to_arrayindex_string(const duk_uint8_t *str, duk_uint32_t blen) {
	duk_uarridx_t res;

	/* Only strings with byte length 1-10 can be 32-bit array indices.
	 * Leading zeroes (except '0' alone), plus/minus signs are not allowed.
	 * We could do a lot of prechecks here, but since most strings won't
	 * start with any digits, it's simpler to just parse the number and
	 * fail quickly.
	 */

	res = 0;
	if (blen == 0) {
		goto parse_fail;
	}
	do {
		duk_uarridx_t dig;
		dig = (duk_uarridx_t) (*str++) - DUK_ASC_0;

		if (dig <= 9U) {
			/* Careful overflow handling.  When multiplying by 10:
			 * - 0x19999998 x 10 = 0xfffffff0: no overflow, and adding
			 *   0...9 is safe.
			 * - 0x19999999 x 10 = 0xfffffffa: no overflow, adding
			 *   0...5 is safe, 6...9 overflows.
			 * - 0x1999999a x 10 = 0x100000004: always overflow.
			 */
			if (DUK_UNLIKELY(res >= 0x19999999UL)) {
				if (res >= 0x1999999aUL) {
					/* Always overflow. */
					goto parse_fail;
				}
				DUK_ASSERT(res == 0x19999999UL);
				if (dig >= 6U) {
					goto parse_fail;
				}
				res = 0xfffffffaUL + dig;
				DUK_ASSERT(res >= 0xfffffffaUL);
				DUK_ASSERT_DISABLE(res <= 0xffffffffUL);  /* range */
			} else {
				res = res * 10U + dig;
				if (DUK_UNLIKELY(res == 0)) {
					/* If 'res' is 0, previous 'res' must
					 * have been 0 and we scanned in a zero.
					 * This is only allowed if blen == 1,
					 * i.e. the exact string '0'.
					 */
					if (blen == (duk_uint32_t) 1) {
						return 0;
					}
					goto parse_fail;
				}
			}
		} else {
			/* Because 'dig' is unsigned, catches both values
			 * above '9' and below '0'.
			 */
			goto parse_fail;
		}
	} while (--blen > 0);

	return res;

 parse_fail:
	return DUK_HSTRING_NO_ARRAY_INDEX;
}

#if !defined(DUK_USE_HSTRING_ARRIDX)
/* Get array index for a string which is known to be an array index.  This helper
 * is needed when duk_hstring doesn't concretely store the array index, but strings
 * are flagged as array indices at intern time.
 */
DUK_INTERNAL duk_uarridx_t duk_js_to_arrayindex_hstring_fast_known(duk_hstring *h) {
	const duk_uint8_t *p;
	duk_uarridx_t res;
	duk_uint8_t t;

	DUK_ASSERT(h != NULL);
	DUK_ASSERT(DUK_HSTRING_HAS_ARRIDX(h));

	p = DUK_HSTRING_GET_DATA(h);
	res = 0;
	for (;;) {
		t = *p++;
		if (DUK_UNLIKELY(t == 0)) {
			/* Scanning to NUL is always safe for interned strings. */
			break;
		}
		DUK_ASSERT(t >= (duk_uint8_t) DUK_ASC_0 && t <= (duk_uint8_t) DUK_ASC_9);
		res = res * 10U + (duk_uarridx_t) t - (duk_uarridx_t) DUK_ASC_0;
	}
	return res;
}

DUK_INTERNAL duk_uarridx_t duk_js_to_arrayindex_hstring_fast(duk_hstring *h) {
	DUK_ASSERT(h != NULL);
	if (!DUK_HSTRING_HAS_ARRIDX(h)) {
		return DUK_HSTRING_NO_ARRAY_INDEX;
	}
	return duk_js_to_arrayindex_hstring_fast_known(h);
}
#endif  /* DUK_USE_HSTRING_ARRIDX */
#line 1 "duk_js_var.c"
/*
 *  Identifier access and function closure handling.
 *
 *  Provides the primitives for slow path identifier accesses: GETVAR,
 *  PUTVAR, DELVAR, etc.  The fast path, direct register accesses, should
 *  be used for most identifier accesses.  Consequently, these slow path
 *  primitives should be optimized for maximum compactness.
 *
 *  ECMAScript environment records (declarative and object) are represented
 *  as internal objects with control keys.  Environment records have a
 *  parent record ("outer environment reference") which is represented by
 *  the implicit prototype for technical reasons (in other words, it is a
 *  convenient field).  The prototype chain is not followed in the ordinary
 *  sense for variable lookups.
 *
 *  See identifier-handling.rst for more details on the identifier algorithms
 *  and the internal representation.  See function-objects.rst for details on
 *  what function templates and instances are expected to look like.
 *
 *  Care must be taken to avoid duk_tval pointer invalidation caused by
 *  e.g. value stack or object resizing.
 *
 *  TODO: properties for function instances could be initialized much more
 *  efficiently by creating a property allocation for a certain size and
 *  filling in keys and values directly (and INCREFing both with "bulk incref"
 *  primitives.
 *
 *  XXX: duk_hobject_getprop() and duk_hobject_putprop() calls are a bit
 *  awkward (especially because they follow the prototype chain); rework
 *  if "raw" own property helpers are added.
 */

/* #include duk_internal.h -> already included */

/*
 *  Local result type for duk__get_identifier_reference() lookup.
 */

typedef struct {
	duk_hobject *env;
	duk_hobject *holder;      /* for object-bound identifiers */
	duk_tval *value;          /* for register-bound and declarative env identifiers */
	duk_uint_t attrs;         /* property attributes for identifier (relevant if value != NULL) */
	duk_bool_t has_this;      /* for object-bound identifiers: provide 'this' binding */
} duk__id_lookup_result;

/*
 *  Create a new function object based on a "template function" which contains
 *  compiled bytecode, constants, etc, but lacks a lexical environment.
 *
 *  ECMAScript requires that each created closure is a separate object, with
 *  its own set of editable properties.  However, structured property values
 *  (such as the formal arguments list and the variable map) are shared.
 *  Also the bytecode, constants, and inner functions are shared.
 *
 *  See E5 Section 13.2 for detailed requirements on the function objects;
 *  there are no similar requirements for function "templates" which are an
 *  implementation dependent internal feature.  Also see function-objects.rst
 *  for a discussion on the function instance properties provided by this
 *  implementation.
 *
 *  Notes:
 *
 *   * Order of internal properties should match frequency of use, since the
 *     properties will be linearly scanned on lookup (functions usually don't
 *     have enough properties to warrant a hash part).
 *
 *   * The created closure is independent of its template; they do share the
 *     same 'data' buffer object, but the template object itself can be freed
 *     even if the closure object remains reachable.
 */

DUK_LOCAL void duk__inc_data_inner_refcounts(duk_hthread *thr, duk_hcompfunc *f) {
	duk_tval *tv, *tv_end;
	duk_hobject **funcs, **funcs_end;

	DUK_UNREF(thr);

	/* If function creation fails due to out-of-memory, the data buffer
	 * pointer may be NULL in some cases.  That's actually possible for
	 * GC code, but shouldn't be possible here because the incomplete
	 * function will be unwound from the value stack and never instantiated.
	 */
	DUK_ASSERT(DUK_HCOMPFUNC_GET_DATA(thr->heap, f) != NULL);

	tv = DUK_HCOMPFUNC_GET_CONSTS_BASE(thr->heap, f);
	tv_end = DUK_HCOMPFUNC_GET_CONSTS_END(thr->heap, f);
	while (tv < tv_end) {
		DUK_TVAL_INCREF(thr, tv);
		tv++;
	}

	funcs = DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, f);
	funcs_end = DUK_HCOMPFUNC_GET_FUNCS_END(thr->heap, f);
	while (funcs < funcs_end) {
		DUK_HEAPHDR_INCREF(thr, (duk_heaphdr *) *funcs);
		funcs++;
	}
}

/* Push a new closure on the stack.
 *
 * Note: if fun_temp has NEWENV, i.e. a new lexical and variable declaration
 * is created when the function is called, only outer_lex_env matters
 * (outer_var_env is ignored and may or may not be same as outer_lex_env).
 */

DUK_LOCAL const duk_uint16_t duk__closure_copy_proplist[] = {
	/* order: most frequent to least frequent */
	DUK_STRIDX_INT_VARMAP,
	DUK_STRIDX_INT_FORMALS,
#if defined(DUK_USE_PC2LINE)
	DUK_STRIDX_INT_PC2LINE,
#endif
#if defined(DUK_USE_FUNC_FILENAME_PROPERTY)
	DUK_STRIDX_FILE_NAME,
#endif
#if defined(DUK_USE_NONSTD_FUNC_SOURCE_PROPERTY)
	DUK_STRIDX_INT_SOURCE
#endif
};

DUK_INTERNAL
void duk_js_push_closure(duk_hthread *thr,
                         duk_hcompfunc *fun_temp,
                         duk_hobject *outer_var_env,
                         duk_hobject *outer_lex_env,
                         duk_bool_t add_auto_proto) {
	duk_hcompfunc *fun_clos;
	duk_harray *formals;
	duk_small_uint_t i;
	duk_uint_t len_value;

	DUK_ASSERT(fun_temp != NULL);
	DUK_ASSERT(DUK_HCOMPFUNC_GET_DATA(thr->heap, fun_temp) != NULL);
	DUK_ASSERT(DUK_HCOMPFUNC_GET_FUNCS(thr->heap, fun_temp) != NULL);
	DUK_ASSERT(DUK_HCOMPFUNC_GET_BYTECODE(thr->heap, fun_temp) != NULL);
	DUK_ASSERT(outer_var_env != NULL);
	DUK_ASSERT(outer_lex_env != NULL);
	DUK_UNREF(len_value);

	DUK_STATS_INC(thr->heap, stats_envrec_pushclosure);

	fun_clos = duk_push_hcompfunc(thr);
	DUK_ASSERT(fun_clos != NULL);
	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) fun_clos) == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);

	duk_push_hobject(thr, &fun_temp->obj);  /* -> [ ... closure template ] */

	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) fun_clos));
	DUK_ASSERT(DUK_HCOMPFUNC_GET_DATA(thr->heap, fun_clos) == NULL);
	DUK_ASSERT(DUK_HCOMPFUNC_GET_FUNCS(thr->heap, fun_clos) == NULL);
	DUK_ASSERT(DUK_HCOMPFUNC_GET_BYTECODE(thr->heap, fun_clos) == NULL);

	DUK_HCOMPFUNC_SET_DATA(thr->heap, fun_clos, DUK_HCOMPFUNC_GET_DATA(thr->heap, fun_temp));
	DUK_HCOMPFUNC_SET_FUNCS(thr->heap, fun_clos, DUK_HCOMPFUNC_GET_FUNCS(thr->heap, fun_temp));
	DUK_HCOMPFUNC_SET_BYTECODE(thr->heap, fun_clos, DUK_HCOMPFUNC_GET_BYTECODE(thr->heap, fun_temp));

	/* Note: all references inside 'data' need to get their refcounts
	 * upped too.  This is the case because refcounts are decreased
	 * through every function referencing 'data' independently.
	 */

	DUK_HBUFFER_INCREF(thr, DUK_HCOMPFUNC_GET_DATA(thr->heap, fun_clos));
	duk__inc_data_inner_refcounts(thr, fun_temp);

	fun_clos->nregs = fun_temp->nregs;
	fun_clos->nargs = fun_temp->nargs;
#if defined(DUK_USE_DEBUGGER_SUPPORT)
	fun_clos->start_line = fun_temp->start_line;
	fun_clos->end_line = fun_temp->end_line;
#endif

	DUK_ASSERT(DUK_HCOMPFUNC_GET_DATA(thr->heap, fun_clos) != NULL);
	DUK_ASSERT(DUK_HCOMPFUNC_GET_FUNCS(thr->heap, fun_clos) != NULL);
	DUK_ASSERT(DUK_HCOMPFUNC_GET_BYTECODE(thr->heap, fun_clos) != NULL);

	/* XXX: Could also copy from template, but there's no way to have any
	 * other value here now (used code has no access to the template).
	 * Prototype is set by duk_push_hcompfunc().
	 */
	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, &fun_clos->obj) == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
#if 0
	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, &fun_clos->obj, thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
#endif

	/* Copy duk_hobject flags as is from the template using a mask.
	 * Leave out duk_heaphdr owned flags just in case (e.g. if there's
	 * some GC flag or similar).  Some flags can then be adjusted
	 * separately if necessary.
	 */

	/* DUK_HEAPHDR_SET_FLAGS() masks changes to non-duk_heaphdr flags only. */
	DUK_HEAPHDR_SET_FLAGS((duk_heaphdr *) fun_clos, DUK_HEAPHDR_GET_FLAGS_RAW((duk_heaphdr *) fun_temp));
	DUK_DD(DUK_DDPRINT("fun_temp heaphdr flags: 0x%08lx, fun_clos heaphdr flags: 0x%08lx",
	                   (unsigned long) DUK_HEAPHDR_GET_FLAGS_RAW((duk_heaphdr *) fun_temp),
	                   (unsigned long) DUK_HEAPHDR_GET_FLAGS_RAW((duk_heaphdr *) fun_clos)));

	DUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE(&fun_clos->obj));
	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(&fun_clos->obj));
	DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(&fun_clos->obj));
	DUK_ASSERT(!DUK_HOBJECT_HAS_NATFUNC(&fun_clos->obj));
	DUK_ASSERT(!DUK_HOBJECT_IS_THREAD(&fun_clos->obj));
	/* DUK_HOBJECT_FLAG_ARRAY_PART: don't care */
	/* DUK_HOBJECT_FLAG_NEWENV: handled below */
	DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARRAY(&fun_clos->obj));
	DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(&fun_clos->obj));
	DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(&fun_clos->obj));

	if (!DUK_HOBJECT_HAS_CONSTRUCTABLE(&fun_clos->obj)) {
		/* If the template is not constructable don't add an automatic
		 * .prototype property.  This is the case for e.g. ES2015 object
		 * literal getters/setters and method definitions.
		 */
		add_auto_proto = 0;
	}

	/*
	 *  Setup environment record properties based on the template and
	 *  its flags.
	 *
	 *  If DUK_HOBJECT_HAS_NEWENV(fun_temp) is true, the environment
	 *  records represent identifiers "outside" the function; the
	 *  "inner" environment records are created on demand.  Otherwise,
	 *  the environment records are those that will be directly used
	 *  (e.g. for declarations).
	 *
	 *  _Lexenv is always set; _Varenv defaults to _Lexenv if missing,
	 *  so _Varenv is only set if _Lexenv != _Varenv.
	 *
	 *  This is relatively complex, see doc/identifier-handling.rst.
	 */

	if (DUK_HOBJECT_HAS_NEWENV(&fun_clos->obj)) {
#if defined(DUK_USE_FUNC_NAME_PROPERTY)
		if (DUK_HOBJECT_HAS_NAMEBINDING(&fun_clos->obj)) {
			duk_hobject *proto;
			duk_hdecenv *new_env;

			/*
			 *  Named function expression, name needs to be bound
			 *  in an intermediate environment record.  The "outer"
			 *  lexical/variable environment will thus be:
			 *
			 *  a) { funcname: <func>, __prototype: outer_lex_env }
			 *  b) { funcname: <func>, __prototype:  <globalenv> }  (if outer_lex_env missing)
			 */

			if (outer_lex_env) {
				proto = outer_lex_env;
			} else {
				proto = thr->builtins[DUK_BIDX_GLOBAL_ENV];
			}

			/* -> [ ... closure template env ] */
			new_env = duk_hdecenv_alloc(thr,
			                            DUK_HOBJECT_FLAG_EXTENSIBLE |
			                            DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV));
			DUK_ASSERT(new_env != NULL);
			duk_push_hobject(thr, (duk_hobject *) new_env);

			DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) new_env) == NULL);
			DUK_HOBJECT_SET_PROTOTYPE(thr->heap, (duk_hobject *) new_env, proto);
			DUK_HOBJECT_INCREF_ALLOWNULL(thr, proto);

			DUK_ASSERT(new_env->thread == NULL);  /* Closed. */
			DUK_ASSERT(new_env->varmap == NULL);

			/* It's important that duk_xdef_prop() is a 'raw define' so that any
			 * properties in an ancestor are never an issue (they should never be
			 * e.g. non-writable, but just in case).
			 *
			 * Because template objects are not visible to user code, the case
			 * where .name is missing shouldn't happen in practice.  It it does,
			 * the name 'undefined' gets bound and maps to the closure (which is
			 * a bit odd, but safe).
			 */
			(void) duk_get_prop_stridx_short(thr, -2, DUK_STRIDX_NAME);
			/* -> [ ... closure template env funcname ] */
			duk_dup_m4(thr);                                           /* -> [ ... closure template env funcname closure ] */
			duk_xdef_prop(thr, -3, DUK_PROPDESC_FLAGS_NONE);           /* -> [ ... closure template env ] */
			/* env[funcname] = closure */

			/* [ ... closure template env ] */

			DUK_HCOMPFUNC_SET_LEXENV(thr->heap, fun_clos, (duk_hobject *) new_env);
			DUK_HCOMPFUNC_SET_VARENV(thr->heap, fun_clos, (duk_hobject *) new_env);
			DUK_HOBJECT_INCREF(thr, (duk_hobject *) new_env);
			DUK_HOBJECT_INCREF(thr, (duk_hobject *) new_env);
			duk_pop_unsafe(thr);

			/* [ ... closure template ] */
		}
		else
#endif  /* DUK_USE_FUNC_NAME_PROPERTY */
		{
			/*
			 *  Other cases (function declaration, anonymous function expression,
			 *  strict direct eval code).  The "outer" environment will be whatever
			 *  the caller gave us.
			 */

			DUK_HCOMPFUNC_SET_LEXENV(thr->heap, fun_clos, outer_lex_env);
			DUK_HCOMPFUNC_SET_VARENV(thr->heap, fun_clos, outer_lex_env);
			DUK_HOBJECT_INCREF(thr, outer_lex_env);
			DUK_HOBJECT_INCREF(thr, outer_lex_env);

			/* [ ... closure template ] */
		}
	} else {
		/*
		 *  Function gets no new environment when called.  This is the
		 *  case for global code, indirect eval code, and non-strict
		 *  direct eval code.  There is no direct correspondence to the
		 *  E5 specification, as global/eval code is not exposed as a
		 *  function.
		 */

		DUK_ASSERT(!DUK_HOBJECT_HAS_NAMEBINDING(&fun_temp->obj));

		DUK_HCOMPFUNC_SET_LEXENV(thr->heap, fun_clos, outer_lex_env);
		DUK_HCOMPFUNC_SET_VARENV(thr->heap, fun_clos, outer_var_env);
		DUK_HOBJECT_INCREF(thr, outer_lex_env);  /* NULLs not allowed; asserted on entry */
		DUK_HOBJECT_INCREF(thr, outer_var_env);
	}
	DUK_DDD(DUK_DDDPRINT("closure varenv -> %!ipO, lexenv -> %!ipO",
	                     (duk_heaphdr *) fun_clos->var_env,
	                     (duk_heaphdr *) fun_clos->lex_env));

	/* Call handling assumes this for all callable closures. */
	DUK_ASSERT(DUK_HCOMPFUNC_GET_LEXENV(thr->heap, fun_clos) != NULL);
	DUK_ASSERT(DUK_HCOMPFUNC_GET_VARENV(thr->heap, fun_clos) != NULL);

	/*
	 *  Copy some internal properties directly
	 *
	 *  The properties will be non-writable and non-enumerable, but
	 *  configurable.
	 *
	 *  Function templates are bare objects, so inheritance of internal
	 *  Symbols is not an issue here even when using ordinary property
	 *  reads.  The function instance created is not bare, so internal
	 *  Symbols must be defined without inheritance checks.
	 */

	/* [ ... closure template ] */

	DUK_DDD(DUK_DDDPRINT("copying properties: closure=%!iT, template=%!iT",
	                     (duk_tval *) duk_get_tval(thr, -2),
	                     (duk_tval *) duk_get_tval(thr, -1)));

	for (i = 0; i < (duk_small_uint_t) (sizeof(duk__closure_copy_proplist) / sizeof(duk_uint16_t)); i++) {
		duk_small_int_t stridx = (duk_small_int_t) duk__closure_copy_proplist[i];
		if (duk_xget_owndataprop_stridx_short(thr, -1, stridx)) {
			/* [ ... closure template val ] */
			DUK_DDD(DUK_DDDPRINT("copying property, stridx=%ld -> found", (long) stridx));
			duk_xdef_prop_stridx_short(thr, -3, stridx, DUK_PROPDESC_FLAGS_C);
		} else {
			DUK_DDD(DUK_DDDPRINT("copying property, stridx=%ld -> not found", (long) stridx));
			duk_pop_unsafe(thr);
		}
	}

	/*
	 *  "length" maps to number of formals (E5 Section 13.2) for function
	 *  declarations/expressions (non-bound functions).  Note that 'nargs'
	 *  is NOT necessarily equal to the number of arguments.  Use length
	 *  of _Formals; if missing, assume nargs matches .length.
	 */

	/* [ ... closure template ] */

	formals = duk_hobject_get_formals(thr, (duk_hobject *) fun_temp);
	if (formals) {
		len_value = (duk_uint_t) formals->length;
		DUK_DD(DUK_DDPRINT("closure length from _Formals -> %ld", (long) len_value));
	} else {
		len_value = fun_temp->nargs;
		DUK_DD(DUK_DDPRINT("closure length defaulted from nargs -> %ld", (long) len_value));
	}

	duk_push_uint(thr, len_value);  /* [ ... closure template len_value ] */
	duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_C);

	/*
	 *  "prototype" is, by default, a fresh object with the "constructor"
	 *  property.
	 *
	 *  Note that this creates a circular reference for every function
	 *  instance (closure) which prevents refcount-based collection of
	 *  function instances.
	 *
	 *  XXX: Try to avoid creating the default prototype object, because
	 *  many functions are not used as constructors and the default
	 *  prototype is unnecessary.  Perhaps it could be created on-demand
	 *  when it is first accessed?
	 */

	/* [ ... closure template ] */

	if (add_auto_proto) {
		duk_push_object(thr);  /* -> [ ... closure template newobj ] */
		duk_dup_m3(thr);       /* -> [ ... closure template newobj closure ] */
		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_CONSTRUCTOR, DUK_PROPDESC_FLAGS_WC);  /* -> [ ... closure template newobj ] */
		duk_compact(thr, -1);  /* compact the prototype */
		duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_PROTOTYPE, DUK_PROPDESC_FLAGS_W);     /* -> [ ... closure template ] */
	}

	/*
	 *  "arguments" and "caller" must be mapped to throwers for strict
	 *  mode and bound functions (E5 Section 15.3.5).
	 *
	 *  XXX: This is expensive to have for every strict function instance.
	 *  Try to implement as virtual properties or on-demand created properties.
	 */

	/* [ ... closure template ] */

	if (DUK_HOBJECT_HAS_STRICT(&fun_clos->obj)) {
		duk_xdef_prop_stridx_thrower(thr, -2, DUK_STRIDX_CALLER);
		duk_xdef_prop_stridx_thrower(thr, -2, DUK_STRIDX_LC_ARGUMENTS);
	} else {
#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
		DUK_DDD(DUK_DDDPRINT("function is non-strict and non-standard 'caller' property in use, add initial 'null' value"));
		duk_push_null(thr);
		duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_CALLER, DUK_PROPDESC_FLAGS_NONE);
#else
		DUK_DDD(DUK_DDDPRINT("function is non-strict and non-standard 'caller' property not used"));
#endif
	}

	/*
	 *  "name" used to be non-standard but is now defined by ES2015.
	 *  In ES2015/ES2016 the .name property is configurable.
	 */

	/* [ ... closure template ] */

#if defined(DUK_USE_FUNC_NAME_PROPERTY)
	/* XXX: Look for own property only; doesn't matter much because
	 * templates are bare objects.
	 */
	if (duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_NAME)) {
		/* [ ... closure template name ] */
		DUK_ASSERT(duk_is_string(thr, -1));
		DUK_DD(DUK_DDPRINT("setting function instance name to %!T", duk_get_tval(thr, -1)));
		duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_C);  /* -> [ ... closure template ] */
	} else {
		/* Anonymous functions don't have a .name in ES2015, so don't set
		 * it on the instance either.  The instance will then inherit
		 * it from Function.prototype.name.
		 */
		DUK_DD(DUK_DDPRINT("not setting function instance .name"));
		duk_pop_unsafe(thr);
	}
#endif

	/*
	 *  Compact the closure, in most cases no properties will be added later.
	 *  Also, without this the closures end up having unused property slots
	 *  (e.g. in Duktape 0.9.0, 8 slots would be allocated and only 7 used).
	 *  A better future solution would be to allocate the closure directly
	 *  to correct size (and setup the properties directly without going
	 *  through the API).
	 */

	duk_compact(thr, -2);

	/*
	 *  Some assertions (E5 Section 13.2).
	 */

	DUK_ASSERT(DUK_HOBJECT_GET_CLASS_NUMBER(&fun_clos->obj) == DUK_HOBJECT_CLASS_FUNCTION);
	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, &fun_clos->obj) == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
	DUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE(&fun_clos->obj));
	DUK_ASSERT(duk_has_prop_stridx(thr, -2, DUK_STRIDX_LENGTH) != 0);
	DUK_ASSERT(add_auto_proto == 0 || duk_has_prop_stridx(thr, -2, DUK_STRIDX_PROTOTYPE) != 0);
	/* May be missing .name */
	DUK_ASSERT(!DUK_HOBJECT_HAS_STRICT(&fun_clos->obj) ||
	           duk_has_prop_stridx(thr, -2, DUK_STRIDX_CALLER) != 0);
	DUK_ASSERT(!DUK_HOBJECT_HAS_STRICT(&fun_clos->obj) ||
	           duk_has_prop_stridx(thr, -2, DUK_STRIDX_LC_ARGUMENTS) != 0);

	/*
	 *  Finish
	 */

	/* [ ... closure template ] */

	DUK_DDD(DUK_DDDPRINT("created function instance: template=%!iT -> closure=%!iT",
	                     (duk_tval *) duk_get_tval(thr, -1),
	                     (duk_tval *) duk_get_tval(thr, -2)));

	duk_pop_unsafe(thr);

	/* [ ... closure ] */
}

/*
 *  Delayed activation environment record initialization (for functions
 *  with NEWENV).
 *
 *  The non-delayed initialization is handled by duk_handle_call().
 */

DUK_LOCAL void duk__preallocate_env_entries(duk_hthread *thr, duk_hobject *varmap, duk_hobject *env) {
	duk_uint_fast32_t i;

	for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(varmap); i++) {
		duk_hstring *key;

		key = DUK_HOBJECT_E_GET_KEY(thr->heap, varmap, i);
		DUK_ASSERT(key != NULL);   /* assume keys are compact in _Varmap */
		DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, varmap, i));  /* assume plain values */

		/* Predefine as 'undefined' to reserve a property slot.
		 * This makes the unwind process (where register values
		 * are copied to the env object) safe against throwing.
		 *
		 * XXX: This could be made much faster by creating the
		 * property table directly.
		 */
		duk_push_undefined(thr);
		DUK_DDD(DUK_DDDPRINT("preallocate env entry for key %!O", key));
		duk_hobject_define_property_internal(thr, env, key, DUK_PROPDESC_FLAGS_WE);
	}
}

/* shared helper */
DUK_INTERNAL
duk_hobject *duk_create_activation_environment_record(duk_hthread *thr,
                                                      duk_hobject *func,
                                                      duk_size_t bottom_byteoff) {
	duk_hdecenv *env;
	duk_hobject *parent;
	duk_hcompfunc *f;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(func != NULL);

	DUK_STATS_INC(thr->heap, stats_envrec_create);

	f = (duk_hcompfunc *) func;
	parent = DUK_HCOMPFUNC_GET_LEXENV(thr->heap, f);
	if (!parent) {
		parent = thr->builtins[DUK_BIDX_GLOBAL_ENV];
	}

	env = duk_hdecenv_alloc(thr,
	                        DUK_HOBJECT_FLAG_EXTENSIBLE |
	                        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV));
	DUK_ASSERT(env != NULL);
	duk_push_hobject(thr, (duk_hobject *) env);

	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) env) == NULL);
	DUK_HOBJECT_SET_PROTOTYPE(thr->heap, (duk_hobject *) env, parent);
	DUK_HOBJECT_INCREF_ALLOWNULL(thr, parent);  /* parent env is the prototype */

	/* open scope information, for compiled functions only */

	DUK_ASSERT(env->thread == NULL);
	DUK_ASSERT(env->varmap == NULL);
	DUK_ASSERT(env->regbase_byteoff == 0);
	if (DUK_HOBJECT_IS_COMPFUNC(func)) {
		duk_hobject *varmap;

		varmap = duk_hobject_get_varmap(thr, func);
		if (varmap != NULL) {
			env->varmap = varmap;
			DUK_HOBJECT_INCREF(thr, varmap);
			env->thread = thr;
			DUK_HTHREAD_INCREF(thr, thr);
			env->regbase_byteoff = bottom_byteoff;

			/* Preallocate env property table to avoid potential
			 * for out-of-memory on unwind when the env is closed.
			 */
			duk__preallocate_env_entries(thr, varmap, (duk_hobject *) env);
		} else {
			/* If function has no _Varmap, leave the environment closed. */
			DUK_ASSERT(env->thread == NULL);
			DUK_ASSERT(env->varmap == NULL);
			DUK_ASSERT(env->regbase_byteoff == 0);
		}
	}

	return (duk_hobject *) env;
}

DUK_INTERNAL
void duk_js_init_activation_environment_records_delayed(duk_hthread *thr,
                                                        duk_activation *act) {
	duk_hobject *func;
	duk_hobject *env;

	DUK_ASSERT(thr != NULL);
	func = DUK_ACT_GET_FUNC(act);
	DUK_ASSERT(func != NULL);
	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(func));  /* bound functions are never in act 'func' */

	/*
	 *  Delayed initialization only occurs for 'NEWENV' functions.
	 */

	DUK_ASSERT(DUK_HOBJECT_HAS_NEWENV(func));
	DUK_ASSERT(act->lex_env == NULL);
	DUK_ASSERT(act->var_env == NULL);

	DUK_STATS_INC(thr->heap, stats_envrec_delayedcreate);

	env = duk_create_activation_environment_record(thr, func, act->bottom_byteoff);
	DUK_ASSERT(env != NULL);
	/* 'act' is a stable pointer, so still OK. */

	DUK_DDD(DUK_DDDPRINT("created delayed fresh env: %!ipO", (duk_heaphdr *) env));
#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
	{
		duk_hobject *p = env;
		while (p) {
			DUK_DDD(DUK_DDDPRINT("  -> %!ipO", (duk_heaphdr *) p));
			p = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, p);
		}
	}
#endif

	act->lex_env = env;
	act->var_env = env;
	DUK_HOBJECT_INCREF(thr, env);  /* XXX: incref by count (here 2 times) */
	DUK_HOBJECT_INCREF(thr, env);

	duk_pop_unsafe(thr);
}

/*
 *  Closing environment records.
 *
 *  The environment record MUST be closed with the thread where its activation
 *  is; i.e. if 'env' is open, 'thr' must match env->thread, and the regbase
 *  and varmap must still be valid.  On entry, 'env' must be reachable.
 */

DUK_INTERNAL void duk_js_close_environment_record(duk_hthread *thr, duk_hobject *env) {
	duk_uint_fast32_t i;
	duk_hobject *varmap;
	duk_hstring *key;
	duk_tval *tv;
	duk_uint_t regnum;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(env != NULL);

	if (DUK_UNLIKELY(!DUK_HOBJECT_IS_DECENV(env))) {
		DUK_DDD(DUK_DDDPRINT("env not a declarative record: %!iO", (duk_heaphdr *) env));
		return;
	}

	varmap = ((duk_hdecenv *) env)->varmap;
	if (varmap == NULL) {
		DUK_DDD(DUK_DDDPRINT("env already closed: %!iO", (duk_heaphdr *) env));

		return;
	}
	DUK_ASSERT(((duk_hdecenv *) env)->thread != NULL);
	DUK_HDECENV_ASSERT_VALID((duk_hdecenv *) env);

	DUK_DDD(DUK_DDDPRINT("closing env: %!iO", (duk_heaphdr *) env));
	DUK_DDD(DUK_DDDPRINT("varmap: %!O", (duk_heaphdr *) varmap));

	/* Env must be closed in the same thread as where it runs. */
	DUK_ASSERT(((duk_hdecenv *) env)->thread == thr);

	/* XXX: additional conditions when to close variables? we don't want to do it
	 * unless the environment may have "escaped" (referenced in a function closure).
	 * With delayed environments, the existence is probably good enough of a check.
	 */

	/* Note: we rely on the _Varmap having a bunch of nice properties, like:
	 *  - being compacted and unmodified during this process
	 *  - not containing an array part
	 *  - having correct value types
	 */

	DUK_DDD(DUK_DDDPRINT("copying bound register values, %ld bound regs", (long) DUK_HOBJECT_GET_ENEXT(varmap)));

	/* Copy over current variable values from value stack to the
	 * environment record.  The scope object is empty but may
	 * inherit from another scope which has conflicting names.
	 */

	/* XXX: Do this using a once allocated entry area, no side effects.
	 * Hash part would need special treatment however (maybe copy, and
	 * then realloc with hash part if large enough).
	 */
	for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(varmap); i++) {
		duk_size_t regbase_byteoff;

		key = DUK_HOBJECT_E_GET_KEY(thr->heap, varmap, i);
		DUK_ASSERT(key != NULL);   /* assume keys are compact in _Varmap */
		DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, varmap, i));  /* assume plain values */

		tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, varmap, i);
		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
		DUK_ASSERT(DUK_TVAL_GET_NUMBER(tv) <= (duk_double_t) DUK_UINT32_MAX);  /* limits */
#if defined(DUK_USE_FASTINT)
		DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv));
		regnum = (duk_uint_t) DUK_TVAL_GET_FASTINT_U32(tv);
#else
		regnum = (duk_uint_t) DUK_TVAL_GET_NUMBER(tv);
#endif

		regbase_byteoff = ((duk_hdecenv *) env)->regbase_byteoff;
		DUK_ASSERT((duk_uint8_t *) thr->valstack + regbase_byteoff + sizeof(duk_tval) * regnum >= (duk_uint8_t *) thr->valstack);
		DUK_ASSERT((duk_uint8_t *) thr->valstack + regbase_byteoff + sizeof(duk_tval) * regnum < (duk_uint8_t *) thr->valstack_top);

		/* Write register value into env as named properties.
		 * If property already exists, overwrites silently.
		 * Property is writable, but not deletable (not configurable
		 * in terms of property attributes).
		 *
		 * This property write must not throw because we're unwinding
		 * and unwind code is not allowed to throw at present.  The
		 * call itself has no such guarantees, but we've preallocated
		 * entries for each property when the env was created, so no
		 * out-of-memory error should be possible.  If this guarantee
		 * is not provided, problems like GH-476 may happen.
		 */
		duk_push_tval(thr, (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + regbase_byteoff + sizeof(duk_tval) * regnum));
		DUK_DDD(DUK_DDDPRINT("closing identifier %!O -> reg %ld, value %!T",
		                     (duk_heaphdr *) key,
		                     (long) regnum,
		                     (duk_tval *) duk_get_tval(thr, -1)));
		duk_hobject_define_property_internal(thr, env, key, DUK_PROPDESC_FLAGS_WE);
	}

	/* NULL atomically to avoid inconsistent state + side effects. */
	DUK_HOBJECT_DECREF_NORZ(thr, ((duk_hdecenv *) env)->thread);
	DUK_HOBJECT_DECREF_NORZ(thr, ((duk_hdecenv *) env)->varmap);
	((duk_hdecenv *) env)->thread = NULL;
	((duk_hdecenv *) env)->varmap = NULL;

	DUK_DDD(DUK_DDDPRINT("env after closing: %!O", (duk_heaphdr *) env));
}

/*
 *  GETIDREF: a GetIdentifierReference-like helper.
 *
 *  Provides a parent traversing lookup and a single level lookup
 *  (for HasBinding).
 *
 *  Instead of returning the value, returns a bunch of values allowing
 *  the caller to read, write, or delete the binding.  Value pointers
 *  are duk_tval pointers which can be mutated directly as long as
 *  refcounts are properly updated.  Note that any operation which may
 *  reallocate valstacks or compact objects may invalidate the returned
 *  duk_tval (but not object) pointers, so caller must be very careful.
 *
 *  If starting environment record 'env' is given, 'act' is ignored.
 *  However, if 'env' is NULL, the caller may identify, in 'act', an
 *  activation which hasn't had its declarative environment initialized
 *  yet.  The activation registers are then looked up, and its parent
 *  traversed normally.
 *
 *  The 'out' structure values are only valid if the function returns
 *  success (non-zero).
 */

/* lookup name from an open declarative record's registers */
DUK_LOCAL
duk_bool_t duk__getid_open_decl_env_regs(duk_hthread *thr,
                                         duk_hstring *name,
                                         duk_hdecenv *env,
                                         duk__id_lookup_result *out) {
	duk_tval *tv;
	duk_size_t reg_rel;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(name != NULL);
	DUK_ASSERT(env != NULL);
	DUK_ASSERT(out != NULL);

	DUK_ASSERT(DUK_HOBJECT_IS_DECENV((duk_hobject *) env));
	DUK_HDECENV_ASSERT_VALID(env);

	if (env->thread == NULL) {
		/* already closed */
		return 0;
	}
	DUK_ASSERT(env->varmap != NULL);

	tv = duk_hobject_find_entry_tval_ptr(thr->heap, env->varmap, name);
	if (DUK_UNLIKELY(tv == NULL)) {
		return 0;
	}

	DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
	DUK_ASSERT(DUK_TVAL_GET_NUMBER(tv) <= (duk_double_t) DUK_UINT32_MAX);  /* limits */
#if defined(DUK_USE_FASTINT)
	DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv));
	reg_rel = (duk_size_t) DUK_TVAL_GET_FASTINT_U32(tv);
#else
	reg_rel = (duk_size_t) DUK_TVAL_GET_NUMBER(tv);
#endif
	DUK_ASSERT_DISABLE(reg_rel >= 0);  /* unsigned */

	tv = (duk_tval *) (void *) ((duk_uint8_t *) env->thread->valstack + env->regbase_byteoff + sizeof(duk_tval) * reg_rel);
	DUK_ASSERT(tv >= env->thread->valstack && tv < env->thread->valstack_end);  /* XXX: more accurate? */

	out->value = tv;
	out->attrs = DUK_PROPDESC_FLAGS_W;  /* registers are mutable, non-deletable */
	out->env = (duk_hobject *) env;
	out->holder = NULL;
	out->has_this = 0;
	return 1;
}

/* lookup name from current activation record's functions' registers */
DUK_LOCAL
duk_bool_t duk__getid_activation_regs(duk_hthread *thr,
                                      duk_hstring *name,
                                      duk_activation *act,
                                      duk__id_lookup_result *out) {
	duk_tval *tv;
	duk_hobject *func;
	duk_hobject *varmap;
	duk_size_t reg_rel;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(name != NULL);
	DUK_ASSERT(act != NULL);
	DUK_ASSERT(out != NULL);

	func = DUK_ACT_GET_FUNC(act);
	DUK_ASSERT(func != NULL);
	DUK_ASSERT(DUK_HOBJECT_HAS_NEWENV(func));

	if (!DUK_HOBJECT_IS_COMPFUNC(func)) {
		return 0;
	}

	/* XXX: move varmap to duk_hcompfunc struct field? */
	varmap = duk_hobject_get_varmap(thr, func);
	if (!varmap) {
		return 0;
	}

	tv = duk_hobject_find_entry_tval_ptr(thr->heap, varmap, name);
	if (!tv) {
		return 0;
	}
	DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
	reg_rel = (duk_size_t) DUK_TVAL_GET_NUMBER(tv);
	DUK_ASSERT_DISABLE(reg_rel >= 0);
	DUK_ASSERT(reg_rel < ((duk_hcompfunc *) func)->nregs);

	tv = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + act->bottom_byteoff);
	tv += reg_rel;

	out->value = tv;
	out->attrs = DUK_PROPDESC_FLAGS_W;  /* registers are mutable, non-deletable */
	out->env = NULL;
	out->holder = NULL;
	out->has_this = 0;
	return 1;
}

DUK_LOCAL
duk_bool_t duk__get_identifier_reference(duk_hthread *thr,
                                         duk_hobject *env,
                                         duk_hstring *name,
                                         duk_activation *act,
                                         duk_bool_t parents,
                                         duk__id_lookup_result *out) {
	duk_tval *tv;
	duk_uint_t sanity;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(env != NULL || act != NULL);
	DUK_ASSERT(name != NULL);
	DUK_ASSERT(out != NULL);

	DUK_ASSERT(!env || DUK_HOBJECT_IS_ENV(env));
	DUK_ASSERT(!env || !DUK_HOBJECT_HAS_ARRAY_PART(env));

	/*
	 *  Conceptually, we look for the identifier binding by starting from
	 *  'env' and following to chain of environment records (represented
	 *  by the prototype chain).
	 *
	 *  If 'env' is NULL, the current activation does not yet have an
	 *  allocated declarative environment record; this should be treated
	 *  exactly as if the environment record existed but had no bindings
	 *  other than register bindings.
	 *
	 *  Note: we assume that with the DUK_HOBJECT_FLAG_NEWENV cleared
	 *  the environment will always be initialized immediately; hence
	 *  a NULL 'env' should only happen with the flag set.  This is the
	 *  case for: (1) function calls, and (2) strict, direct eval calls.
	 */

	if (env == NULL && act != NULL) {
		duk_hobject *func;
		duk_hcompfunc *f;

		DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference: env is NULL, activation is non-NULL -> "
		                     "delayed env case, look up activation regs first"));

		/*
		 *  Try registers
		 */

		if (duk__getid_activation_regs(thr, name, act, out)) {
			DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference successful: "
			                     "name=%!O -> value=%!T, attrs=%ld, has_this=%ld, env=%!O, holder=%!O "
			                     "(found from register bindings when env=NULL)",
			                     (duk_heaphdr *) name, (duk_tval *) out->value,
			                     (long) out->attrs, (long) out->has_this,
			                     (duk_heaphdr *) out->env, (duk_heaphdr *) out->holder));
			return 1;
		}

		DUK_DDD(DUK_DDDPRINT("not found in current activation regs"));

		/*
		 *  Not found in registers, proceed to the parent record.
		 *  Here we need to determine what the parent would be,
		 *  if 'env' was not NULL (i.e. same logic as when initializing
		 *  the record).
		 *
		 *  Note that environment initialization is only deferred when
		 *  DUK_HOBJECT_HAS_NEWENV is set, and this only happens for:
		 *    - Function code
		 *    - Strict eval code
		 *
		 *  We only need to check _Lexenv here; _Varenv exists only if it
		 *  differs from _Lexenv (and thus _Lexenv will also be present).
		 */

		if (!parents) {
			DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference failed, no parent traversal "
			                     "(not found from register bindings when env=NULL)"));
			goto fail_not_found;
		}

		func = DUK_ACT_GET_FUNC(act);
		DUK_ASSERT(func != NULL);
		DUK_ASSERT(DUK_HOBJECT_HAS_NEWENV(func));
		f = (duk_hcompfunc *) func;

		env = DUK_HCOMPFUNC_GET_LEXENV(thr->heap, f);
		if (!env) {
			env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
		}

		DUK_DDD(DUK_DDDPRINT("continue lookup from env: %!iO",
		                     (duk_heaphdr *) env));
	}

	/*
	 *  Prototype walking starting from 'env'.
	 *
	 *  ('act' is not needed anywhere here.)
	 */

	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
	while (env != NULL) {
		duk_small_uint_t cl;
		duk_uint_t attrs;

		DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference, name=%!O, considering env=%p -> %!iO",
		                     (duk_heaphdr *) name,
		                     (void *) env,
		                     (duk_heaphdr *) env));

		DUK_ASSERT(env != NULL);
		DUK_ASSERT(DUK_HOBJECT_IS_ENV(env));
		DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(env));

		cl = DUK_HOBJECT_GET_CLASS_NUMBER(env);
		DUK_ASSERT(cl == DUK_HOBJECT_CLASS_OBJENV || cl == DUK_HOBJECT_CLASS_DECENV);
		if (cl == DUK_HOBJECT_CLASS_DECENV) {
			/*
			 *  Declarative environment record.
			 *
			 *  Identifiers can never be stored in ancestors and are
			 *  always plain values, so we can use an internal helper
			 *  and access the value directly with an duk_tval ptr.
			 *
			 *  A closed environment is only indicated by it missing
			 *  the "book-keeping" properties required for accessing
			 *  register-bound variables.
			 */

			DUK_HDECENV_ASSERT_VALID((duk_hdecenv *) env);
			if (duk__getid_open_decl_env_regs(thr, name, (duk_hdecenv *) env, out)) {
				DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference successful: "
				                     "name=%!O -> value=%!T, attrs=%ld, has_this=%ld, env=%!O, holder=%!O "
				                     "(declarative environment record, scope open, found in regs)",
				                     (duk_heaphdr *) name, (duk_tval *) out->value,
				                     (long) out->attrs, (long) out->has_this,
				                     (duk_heaphdr *) out->env, (duk_heaphdr *) out->holder));
				return 1;
			}

			tv = duk_hobject_find_entry_tval_ptr_and_attrs(thr->heap, env, name, &attrs);
			if (tv) {
				out->value = tv;
				out->attrs = attrs;
				out->env = env;
				out->holder = env;
				out->has_this = 0;

				DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference successful: "
				                     "name=%!O -> value=%!T, attrs=%ld, has_this=%ld, env=%!O, holder=%!O "
				                     "(declarative environment record, found in properties)",
				                     (duk_heaphdr *) name, (duk_tval *) out->value,
				                     (long) out->attrs, (long) out->has_this,
				                     (duk_heaphdr *) out->env, (duk_heaphdr *) out->holder));
				return 1;
			}
		} else {
			/*
			 *  Object environment record.
			 *
			 *  Binding (target) object is an external, uncontrolled object.
			 *  Identifier may be bound in an ancestor property, and may be
			 *  an accessor.  Target can also be a Proxy which we must support
			 *  here.
			 */

			/* XXX: we could save space by using _Target OR _This.  If _Target, assume
			 * this binding is undefined.  If _This, assumes this binding is _This, and
			 * target is also _This.  One property would then be enough.
			 */

			duk_hobject *target;
			duk_bool_t found;

			DUK_ASSERT(cl == DUK_HOBJECT_CLASS_OBJENV);
			DUK_HOBJENV_ASSERT_VALID((duk_hobjenv *) env);

			target = ((duk_hobjenv *) env)->target;
			DUK_ASSERT(target != NULL);

			/* Target may be a Proxy or property may be an accessor, so we must
			 * use an actual, Proxy-aware hasprop check here.
			 *
			 * out->holder is NOT set to the actual duk_hobject where the
			 * property is found, but rather the object binding target object.
			 */

#if defined(DUK_USE_ES6_PROXY)
			if (DUK_UNLIKELY(DUK_HOBJECT_IS_PROXY(target))) {
				duk_tval tv_name;
				duk_tval tv_target_tmp;

				DUK_ASSERT(name != NULL);
				DUK_TVAL_SET_STRING(&tv_name, name);
				DUK_TVAL_SET_OBJECT(&tv_target_tmp, target);

				found = duk_hobject_hasprop(thr, &tv_target_tmp, &tv_name);
			} else
#endif  /* DUK_USE_ES6_PROXY */
			{
				/* XXX: duk_hobject_hasprop() would be correct for
				 * non-Proxy objects too, but it is about ~20-25%
				 * slower at present so separate code paths for
				 * Proxy and non-Proxy now.
				 */
				found = duk_hobject_hasprop_raw(thr, target, name);
			}

			if (found) {
				out->value = NULL;  /* can't get value, may be accessor */
				out->attrs = 0;     /* irrelevant when out->value == NULL */
				out->env = env;
				out->holder = target;
				out->has_this = ((duk_hobjenv *) env)->has_this;

				DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference successful: "
				                     "name=%!O -> value=%!T, attrs=%ld, has_this=%ld, env=%!O, holder=%!O "
				                     "(object environment record)",
				                     (duk_heaphdr *) name, (duk_tval *) out->value,
				                     (long) out->attrs, (long) out->has_this,
				                     (duk_heaphdr *) out->env, (duk_heaphdr *) out->holder));
				return 1;
			}
		}

		if (!parents) {
			DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference failed, no parent traversal "
			                     "(not found from first traversed env)"));
			goto fail_not_found;
		}

                if (DUK_UNLIKELY(sanity-- == 0)) {
                        DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
			DUK_WO_NORETURN(return 0;);
                }
		env = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, env);
	}

	/*
	 *  Not found (even in global object)
	 */

 fail_not_found:
	return 0;
}

/*
 *  HASVAR: check identifier binding from a given environment record
 *  without traversing its parents.
 *
 *  This primitive is not exposed to user code as such, but is used
 *  internally for e.g. declaration binding instantiation.
 *
 *  See E5 Sections:
 *    10.2.1.1.1 HasBinding(N)
 *    10.2.1.2.1 HasBinding(N)
 *
 *  Note: strictness has no bearing on this check.  Hence we don't take
 *  a 'strict' parameter.
 */

#if 0  /*unused*/
DUK_INTERNAL
duk_bool_t duk_js_hasvar_envrec(duk_hthread *thr,
                                duk_hobject *env,
                                duk_hstring *name) {
	duk__id_lookup_result ref;
	duk_bool_t parents;

	DUK_DDD(DUK_DDDPRINT("hasvar: thr=%p, env=%p, name=%!O "
	                     "(env -> %!dO)",
	                     (void *) thr, (void *) env, (duk_heaphdr *) name,
	                     (duk_heaphdr *) env));

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(env != NULL);
	DUK_ASSERT(name != NULL);

        DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(env);
        DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(name);

	DUK_ASSERT(DUK_HOBJECT_IS_ENV(env));
	DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(env));

	/* lookup results is ignored */
	parents = 0;
	return duk__get_identifier_reference(thr, env, name, NULL, parents, &ref);
}
#endif

/*
 *  GETVAR
 *
 *  See E5 Sections:
 *    11.1.2 Identifier Reference
 *    10.3.1 Identifier Resolution
 *    11.13.1 Simple Assignment  [example of where the Reference is GetValue'd]
 *    8.7.1 GetValue (V)
 *    8.12.1 [[GetOwnProperty]] (P)
 *    8.12.2 [[GetProperty]] (P)
 *    8.12.3 [[Get]] (P)
 *
 *  If 'throw' is true, always leaves two values on top of stack: [val this].
 *
 *  If 'throw' is false, returns 0 if identifier cannot be resolved, and the
 *  stack will be unaffected in this case.  If identifier is resolved, returns
 *  1 and leaves [val this] on top of stack.
 *
 *  Note: the 'strict' flag of a reference returned by GetIdentifierReference
 *  is ignored by GetValue.  Hence we don't take a 'strict' parameter.
 *
 *  The 'throw' flag is needed for implementing 'typeof' for an unreferenced
 *  identifier.  An unreference identifier in other contexts generates a
 *  ReferenceError.
 */

DUK_LOCAL
duk_bool_t duk__getvar_helper(duk_hthread *thr,
                              duk_hobject *env,
                              duk_activation *act,
                              duk_hstring *name,
                              duk_bool_t throw_flag) {
	duk__id_lookup_result ref;
	duk_tval tv_tmp_obj;
	duk_tval tv_tmp_key;
	duk_bool_t parents;

	DUK_DDD(DUK_DDDPRINT("getvar: thr=%p, env=%p, act=%p, name=%!O "
	                     "(env -> %!dO)",
	                     (void *) thr, (void *) env, (void *) act,
	                     (duk_heaphdr *) name, (duk_heaphdr *) env));

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(name != NULL);
	/* env and act may be NULL */

	DUK_STATS_INC(thr->heap, stats_getvar_all);

        DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(env);
        DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(name);

	parents = 1;     /* follow parent chain */
	if (duk__get_identifier_reference(thr, env, name, act, parents, &ref)) {
		if (ref.value) {
			duk_push_tval(thr, ref.value);
			duk_push_undefined(thr);
		} else {
			DUK_ASSERT(ref.holder != NULL);

			/* ref.holder is safe across the getprop call (even
			 * with side effects) because 'env' is reachable and
			 * ref.holder is a direct heap pointer.
			 */

			DUK_TVAL_SET_OBJECT(&tv_tmp_obj, ref.holder);
			DUK_TVAL_SET_STRING(&tv_tmp_key, name);
			(void) duk_hobject_getprop(thr, &tv_tmp_obj, &tv_tmp_key);  /* [value] */

			if (ref.has_this) {
				duk_push_hobject(thr, ref.holder);
			} else {
				duk_push_undefined(thr);
			}

			/* [value this] */
		}

		return 1;
	} else {
		if (throw_flag) {
			DUK_ERROR_FMT1(thr, DUK_ERR_REFERENCE_ERROR,
			               "identifier '%s' undefined",
			               (const char *) DUK_HSTRING_GET_DATA(name));
			DUK_WO_NORETURN(return 0;);
		}

		return 0;
	}
}

DUK_INTERNAL
duk_bool_t duk_js_getvar_envrec(duk_hthread *thr,
                                duk_hobject *env,
                                duk_hstring *name,
                                duk_bool_t throw_flag) {
	return duk__getvar_helper(thr, env, NULL, name, throw_flag);
}

DUK_INTERNAL
duk_bool_t duk_js_getvar_activation(duk_hthread *thr,
                                    duk_activation *act,
                                    duk_hstring *name,
                                    duk_bool_t throw_flag) {
	DUK_ASSERT(act != NULL);
	return duk__getvar_helper(thr, act->lex_env, act, name, throw_flag);
}

/*
 *  PUTVAR
 *
 *  See E5 Sections:
 *    11.1.2 Identifier Reference
 *    10.3.1 Identifier Resolution
 *    11.13.1 Simple Assignment  [example of where the Reference is PutValue'd]
 *    8.7.2 PutValue (V,W)  [see especially step 3.b, undefined -> automatic global in non-strict mode]
 *    8.12.4 [[CanPut]] (P)
 *    8.12.5 [[Put]] (P)
 *
 *  Note: may invalidate any valstack (or object) duk_tval pointers because
 *  putting a value may reallocate any object or any valstack.  Caller beware.
 */

DUK_LOCAL
void duk__putvar_helper(duk_hthread *thr,
                        duk_hobject *env,
                        duk_activation *act,
                        duk_hstring *name,
                        duk_tval *val,
                        duk_bool_t strict) {
	duk__id_lookup_result ref;
	duk_tval tv_tmp_obj;
	duk_tval tv_tmp_key;
	duk_bool_t parents;

	DUK_STATS_INC(thr->heap, stats_putvar_all);

	DUK_DDD(DUK_DDDPRINT("putvar: thr=%p, env=%p, act=%p, name=%!O, val=%p, strict=%ld "
	                     "(env -> %!dO, val -> %!T)",
	                     (void *) thr, (void *) env, (void *) act,
	                     (duk_heaphdr *) name, (void *) val, (long) strict,
	                     (duk_heaphdr *) env, (duk_tval *) val));

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(name != NULL);
	DUK_ASSERT(val != NULL);
	/* env and act may be NULL */

        DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(env);
        DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(name);
	DUK_ASSERT_REFCOUNT_NONZERO_TVAL(val);

	/*
	 *  In strict mode E5 protects 'eval' and 'arguments' from being
	 *  assigned to (or even declared anywhere).  Attempt to do so
	 *  should result in a compile time SyntaxError.  See the internal
	 *  design documentation for details.
	 *
	 *  Thus, we should never come here, run-time, for strict code,
	 *  and name 'eval' or 'arguments'.
	 */

	DUK_ASSERT(!strict ||
	           (name != DUK_HTHREAD_STRING_EVAL(thr) &&
	            name != DUK_HTHREAD_STRING_LC_ARGUMENTS(thr)));

	/*
	 *  Lookup variable and update in-place if found.
	 */

	parents = 1;     /* follow parent chain */

	if (duk__get_identifier_reference(thr, env, name, act, parents, &ref)) {
		if (ref.value && (ref.attrs & DUK_PROPDESC_FLAG_WRITABLE)) {
			/* Update duk_tval in-place if pointer provided and the
			 * property is writable.  If the property is not writable
			 * (immutable binding), use duk_hobject_putprop() which
			 * will respect mutability.
			 */
			duk_tval *tv_val;

			tv_val = ref.value;
			DUK_ASSERT(tv_val != NULL);
			DUK_TVAL_SET_TVAL_UPDREF(thr, tv_val, val);  /* side effects */

			/* ref.value invalidated here */
		} else {
			DUK_ASSERT(ref.holder != NULL);

			DUK_TVAL_SET_OBJECT(&tv_tmp_obj, ref.holder);
			DUK_TVAL_SET_STRING(&tv_tmp_key, name);
			(void) duk_hobject_putprop(thr, &tv_tmp_obj, &tv_tmp_key, val, strict);

			/* ref.value invalidated here */
		}

		return;
	}

	/*
	 *  Not found: write to global object (non-strict) or ReferenceError
	 *  (strict); see E5 Section 8.7.2, step 3.
	 */

	if (strict) {
		DUK_DDD(DUK_DDDPRINT("identifier binding not found, strict => reference error"));
		DUK_ERROR_FMT1(thr, DUK_ERR_REFERENCE_ERROR,
		               "identifier '%s' undefined",
		               (const char *) DUK_HSTRING_GET_DATA(name));
		DUK_WO_NORETURN(return;);
	}

	DUK_DDD(DUK_DDDPRINT("identifier binding not found, not strict => set to global"));

	DUK_TVAL_SET_OBJECT(&tv_tmp_obj, thr->builtins[DUK_BIDX_GLOBAL]);
	DUK_TVAL_SET_STRING(&tv_tmp_key, name);
	(void) duk_hobject_putprop(thr, &tv_tmp_obj, &tv_tmp_key, val, 0);  /* 0 = no throw */

	/* NB: 'val' may be invalidated here because put_value may realloc valstack,
	 * caller beware.
	 */
}

DUK_INTERNAL
void duk_js_putvar_envrec(duk_hthread *thr,
                          duk_hobject *env,
                          duk_hstring *name,
                          duk_tval *val,
                          duk_bool_t strict) {
	duk__putvar_helper(thr, env, NULL, name, val, strict);
}

DUK_INTERNAL
void duk_js_putvar_activation(duk_hthread *thr,
                              duk_activation *act,
                              duk_hstring *name,
                              duk_tval *val,
                              duk_bool_t strict) {
	DUK_ASSERT(act != NULL);
	duk__putvar_helper(thr, act->lex_env, act, name, val, strict);
}

/*
 *  DELVAR
 *
 *  See E5 Sections:
 *    11.4.1 The delete operator
 *    10.2.1.1.5 DeleteBinding (N)  [declarative environment record]
 *    10.2.1.2.5 DeleteBinding (N)  [object environment record]
 *
 *  Variable bindings established inside eval() are deletable (configurable),
 *  other bindings are not, including variables declared in global level.
 *  Registers are always non-deletable, and the deletion of other bindings
 *  is controlled by the configurable flag.
 *
 *  For strict mode code, the 'delete' operator should fail with a compile
 *  time SyntaxError if applied to identifiers.  Hence, no strict mode
 *  run-time deletion of identifiers should ever happen.  This function
 *  should never be called from strict mode code!
 */

DUK_LOCAL
duk_bool_t duk__delvar_helper(duk_hthread *thr,
                              duk_hobject *env,
                              duk_activation *act,
                              duk_hstring *name) {
	duk__id_lookup_result ref;
	duk_bool_t parents;

	DUK_DDD(DUK_DDDPRINT("delvar: thr=%p, env=%p, act=%p, name=%!O "
	                     "(env -> %!dO)",
	                     (void *) thr, (void *) env, (void *) act,
	                     (duk_heaphdr *) name, (duk_heaphdr *) env));

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(name != NULL);
	/* env and act may be NULL */

        DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(name);

	parents = 1;     /* follow parent chain */

	if (duk__get_identifier_reference(thr, env, name, act, parents, &ref)) {
		if (ref.value && !(ref.attrs & DUK_PROPDESC_FLAG_CONFIGURABLE)) {
			/* Identifier found in registers (always non-deletable)
			 * or declarative environment record and non-configurable.
			 */
			return 0;
		}
		DUK_ASSERT(ref.holder != NULL);

		return duk_hobject_delprop_raw(thr, ref.holder, name, 0);
	}

	/*
	 *  Not found (even in global object).
	 *
	 *  In non-strict mode this is a silent SUCCESS (!), see E5 Section 11.4.1,
	 *  step 3.b.  In strict mode this case is a compile time SyntaxError so
	 *  we should not come here.
	 */

	DUK_DDD(DUK_DDDPRINT("identifier to be deleted not found: name=%!O "
	                     "(treated as silent success)",
	                     (duk_heaphdr *) name));
	return 1;
}

#if 0  /*unused*/
DUK_INTERNAL
duk_bool_t duk_js_delvar_envrec(duk_hthread *thr,
                                duk_hobject *env,
                                duk_hstring *name) {
	return duk__delvar_helper(thr, env, NULL, name);
}
#endif

DUK_INTERNAL
duk_bool_t duk_js_delvar_activation(duk_hthread *thr,
                                    duk_activation *act,
                                    duk_hstring *name) {
	DUK_ASSERT(act != NULL);
	return duk__delvar_helper(thr, act->lex_env, act, name);
}

/*
 *  DECLVAR
 *
 *  See E5 Sections:
 *    10.4.3 Entering Function Code
 *    10.5 Declaration Binding Instantion
 *    12.2 Variable Statement
 *    11.1.2 Identifier Reference
 *    10.3.1 Identifier Resolution
 *
 *  Variable declaration behavior is mainly discussed in Section 10.5,
 *  and is not discussed in the execution semantics (Sections 11-13).
 *
 *  Conceptually declarations happen when code (global, eval, function)
 *  is entered, before any user code is executed.  In practice, register-
 *  bound identifiers are 'declared' automatically (by virtue of being
 *  allocated to registers with the initial value 'undefined').  Other
 *  identifiers are declared in the function prologue with this primitive.
 *
 *  Since non-register bindings eventually back to an internal object's
 *  properties, the 'prop_flags' argument is used to specify binding
 *  type:
 *
 *    - Immutable binding: set DUK_PROPDESC_FLAG_WRITABLE to false
 *    - Non-deletable binding: set DUK_PROPDESC_FLAG_CONFIGURABLE to false
 *    - The flag DUK_PROPDESC_FLAG_ENUMERABLE should be set, although it
 *      doesn't really matter for internal objects
 *
 *  All bindings are non-deletable mutable bindings except:
 *
 *    - Declarations in eval code (mutable, deletable)
 *    - 'arguments' binding in strict function code (immutable)
 *    - Function name binding of a function expression (immutable)
 *
 *  Declarations may go to declarative environment records (always
 *  so for functions), but may also go to object environment records
 *  (e.g. global code).  The global object environment has special
 *  behavior when re-declaring a function (but not a variable); see
 *  E5.1 specification, Section 10.5, step 5.e.
 *
 *  Declarations always go to the 'top-most' environment record, i.e.
 *  we never check the record chain.  It's not an error even if a
 *  property (even an immutable or non-deletable one) of the same name
 *  already exists.
 *
 *  If a declared variable already exists, its value needs to be updated
 *  (if possible).  Returns 1 if a PUTVAR needs to be done by the caller;
 *  otherwise returns 0.
 */

DUK_LOCAL
duk_bool_t duk__declvar_helper(duk_hthread *thr,
                               duk_hobject *env,
                               duk_hstring *name,
                               duk_tval *val,
                               duk_small_uint_t prop_flags,
                               duk_bool_t is_func_decl) {
	duk_hobject *holder;
	duk_bool_t parents;
	duk__id_lookup_result ref;
	duk_tval *tv;

	DUK_DDD(DUK_DDDPRINT("declvar: thr=%p, env=%p, name=%!O, val=%!T, prop_flags=0x%08lx, is_func_decl=%ld "
	                     "(env -> %!iO)",
	                     (void *) thr, (void *) env, (duk_heaphdr *) name,
	                     (duk_tval *) val, (unsigned long) prop_flags,
	                     (unsigned int) is_func_decl, (duk_heaphdr *) env));

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(env != NULL);
	DUK_ASSERT(name != NULL);
	DUK_ASSERT(val != NULL);

	/* Note: in strict mode the compiler should reject explicit
	 * declaration of 'eval' or 'arguments'.  However, internal
	 * bytecode may declare 'arguments' in the function prologue.
	 * We don't bother checking (or asserting) for these now.
	 */

	/* Note: val is a stable duk_tval pointer.  The caller makes
	 * a value copy into its stack frame, so 'tv_val' is not subject
	 * to side effects here.
	 */

	/*
	 *  Check whether already declared.
	 *
	 *  We need to check whether the binding exists in the environment
	 *  without walking its parents.  However, we still need to check
	 *  register-bound identifiers and the prototype chain of an object
	 *  environment target object.
	 */

	parents = 0;  /* just check 'env' */
	if (duk__get_identifier_reference(thr, env, name, NULL, parents, &ref)) {
		duk_int_t e_idx;
		duk_int_t h_idx;
		duk_small_uint_t flags;

		/*
		 *  Variable already declared, ignore re-declaration.
		 *  The only exception is the updated behavior of E5.1 for
		 *  global function declarations, E5.1 Section 10.5, step 5.e.
		 *  This behavior does not apply to global variable declarations.
		 */

		if (!(is_func_decl && env == thr->builtins[DUK_BIDX_GLOBAL_ENV])) {
			DUK_DDD(DUK_DDDPRINT("re-declare a binding, ignoring"));
			return 1;  /* 1 -> needs a PUTVAR */
		}

		/*
		 *  Special behavior in E5.1.
		 *
		 *  Note that even though parents == 0, the conflicting property
		 *  may be an inherited property (currently our global object's
		 *  prototype is Object.prototype).  Step 5.e first operates on
		 *  the existing property (which is potentially in an ancestor)
		 *  and then defines a new property in the global object (and
		 *  never modifies the ancestor).
		 *
		 *  Also note that this logic would become even more complicated
		 *  if the conflicting property might be a virtual one.  Object
		 *  prototype has no virtual properties, though.
		 *
		 *  XXX: this is now very awkward, rework.
		 */

		DUK_DDD(DUK_DDDPRINT("re-declare a function binding in global object, "
		                     "updated E5.1 processing"));

		DUK_ASSERT(ref.holder != NULL);
		holder = ref.holder;

		/* holder will be set to the target object, not the actual object
		 * where the property was found (see duk__get_identifier_reference()).
		 */
		DUK_ASSERT(DUK_HOBJECT_GET_CLASS_NUMBER(holder) == DUK_HOBJECT_CLASS_GLOBAL);
		DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARRAY(holder));  /* global object doesn't have array part */

		/* XXX: use a helper for prototype traversal; no loop check here */
		/* must be found: was found earlier, and cannot be inherited */
		for (;;) {
			DUK_ASSERT(holder != NULL);
			if (duk_hobject_find_entry(thr->heap, holder, name, &e_idx, &h_idx)) {
				DUK_ASSERT(e_idx >= 0);
				break;
			}
			/* SCANBUILD: NULL pointer dereference, doesn't actually trigger,
			 * asserted above.
			 */
			holder = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, holder);
		}
		DUK_ASSERT(holder != NULL);
		DUK_ASSERT(e_idx >= 0);
		/* SCANBUILD: scan-build produces a NULL pointer dereference warning
		 * below; it never actually triggers because holder is actually never
		 * NULL.
		 */

		/* ref.holder is global object, holder is the object with the
		 * conflicting property.
		 */

		flags = DUK_HOBJECT_E_GET_FLAGS(thr->heap, holder, e_idx);
		if (!(flags & DUK_PROPDESC_FLAG_CONFIGURABLE)) {
			if (flags & DUK_PROPDESC_FLAG_ACCESSOR) {
				DUK_DDD(DUK_DDDPRINT("existing property is a non-configurable "
				                     "accessor -> reject"));
				goto fail_existing_attributes;
			}
			if (!((flags & DUK_PROPDESC_FLAG_WRITABLE) &&
			      (flags & DUK_PROPDESC_FLAG_ENUMERABLE))) {
				DUK_DDD(DUK_DDDPRINT("existing property is a non-configurable "
				                     "plain property which is not writable and "
				                     "enumerable -> reject"));
				goto fail_existing_attributes;
			}

			DUK_DDD(DUK_DDDPRINT("existing property is not configurable but "
			                     "is plain, enumerable, and writable -> "
			                     "allow redeclaration"));
		}

		if (holder == ref.holder) {
			/* XXX: if duk_hobject_define_property_internal() was updated
			 * to handle a pre-existing accessor property, this would be
			 * a simple call (like for the ancestor case).
			 */
			DUK_DDD(DUK_DDDPRINT("redefine, offending property in global object itself"));

			if (flags & DUK_PROPDESC_FLAG_ACCESSOR) {
				duk_hobject *tmp;

				tmp = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, holder, e_idx);
				DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, holder, e_idx, NULL);
				DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);
				DUK_UNREF(tmp);
				tmp = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, holder, e_idx);
				DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, holder, e_idx, NULL);
				DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);
				DUK_UNREF(tmp);
			} else {
				tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, holder, e_idx);
				DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv);
			}

			/* Here val would be potentially invalid if we didn't make
			 * a value copy at the caller.
			 */

			tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, holder, e_idx);
			DUK_TVAL_SET_TVAL(tv, val);
			DUK_TVAL_INCREF(thr, tv);
			DUK_HOBJECT_E_SET_FLAGS(thr->heap, holder, e_idx, prop_flags);

			DUK_DDD(DUK_DDDPRINT("updated global binding, final result: "
			                     "value -> %!T, prop_flags=0x%08lx",
			                     (duk_tval *) DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, holder, e_idx),
			                     (unsigned long) prop_flags));
		} else {
			DUK_DDD(DUK_DDDPRINT("redefine, offending property in ancestor"));

			DUK_ASSERT(ref.holder == thr->builtins[DUK_BIDX_GLOBAL]);
			duk_push_tval(thr, val);
			duk_hobject_define_property_internal(thr, ref.holder, name, prop_flags);
		}

		return 0;
	}

	/*
	 *  Not found (in registers or record objects).  Declare
	 *  to current variable environment.
	 */

	/*
	 *  Get holder object
	 */

	if (DUK_HOBJECT_IS_DECENV(env)) {
		DUK_HDECENV_ASSERT_VALID((duk_hdecenv *) env);
		holder = env;
	} else {
		DUK_HOBJENV_ASSERT_VALID((duk_hobjenv *) env);
		holder = ((duk_hobjenv *) env)->target;
		DUK_ASSERT(holder != NULL);
	}

	/*
	 *  Define new property
	 *
	 *  Note: this may fail if the holder is not extensible.
	 */

	/* XXX: this is awkward as we use an internal method which doesn't handle
	 * extensibility etc correctly.  Basically we'd want to do a [[DefineOwnProperty]]
	 * or Object.defineProperty() here.
	 */

	if (!DUK_HOBJECT_HAS_EXTENSIBLE(holder)) {
		goto fail_not_extensible;
	}

	duk_push_hobject(thr, holder);
	duk_push_hstring(thr, name);
	duk_push_tval(thr, val);
	duk_xdef_prop(thr, -3, prop_flags);  /* [holder name val] -> [holder] */
	duk_pop_unsafe(thr);

	return 0;

 fail_existing_attributes:
 fail_not_extensible:
	DUK_ERROR_TYPE(thr, "declaration failed");
	DUK_WO_NORETURN(return 0;);
}

DUK_INTERNAL
duk_bool_t duk_js_declvar_activation(duk_hthread *thr,
                                     duk_activation *act,
                                     duk_hstring *name,
                                     duk_tval *val,
                                     duk_small_uint_t prop_flags,
                                     duk_bool_t is_func_decl) {
	duk_hobject *env;
	duk_tval tv_val_copy;

	DUK_ASSERT(act != NULL);

	/*
	 *  Make a value copy of the input val.  This ensures that
	 *  side effects cannot invalidate the pointer.
	 */

	DUK_TVAL_SET_TVAL(&tv_val_copy, val);
	val = &tv_val_copy;

	/*
	 *  Delayed env creation check
	 */

	if (!act->var_env) {
		DUK_ASSERT(act->lex_env == NULL);
		duk_js_init_activation_environment_records_delayed(thr, act);
		/* 'act' is a stable pointer, so still OK. */
	}
	DUK_ASSERT(act->lex_env != NULL);
	DUK_ASSERT(act->var_env != NULL);

	env = act->var_env;
	DUK_ASSERT(env != NULL);
	DUK_ASSERT(DUK_HOBJECT_IS_ENV(env));

	return duk__declvar_helper(thr, env, name, val, prop_flags, is_func_decl);
}
#line 1 "duk_lexer.c"
/*
 *  Lexer for source files, ToNumber() string conversions, RegExp expressions,
 *  and JSON.
 *
 *  Provides a stream of ECMAScript tokens from an UTF-8/CESU-8 buffer.  The
 *  caller can also rewind the token stream into a certain position which is
 *  needed by the compiler part for multi-pass scanning.  Tokens are
 *  represented as duk_token structures, and contain line number information.
 *  Token types are identified with DUK_TOK_* defines.
 *
 *  Characters are decoded into a fixed size lookup window consisting of
 *  decoded Unicode code points, with window positions past the end of the
 *  input filled with an invalid codepoint (-1).  The tokenizer can thus
 *  perform multiple character lookups efficiently and with few sanity
 *  checks (such as access outside the end of the input), which keeps the
 *  tokenization code small at the cost of performance.
 *
 *  Character data in tokens, such as identifier names and string literals,
 *  is encoded into CESU-8 format on-the-fly while parsing the token in
 *  question.  The string data is made reachable to garbage collection by
 *  placing the token-related values in value stack entries allocated for
 *  this purpose by the caller.  The characters exist in Unicode code point
 *  form only in the fixed size lookup window, which keeps character data
 *  expansion (of especially ASCII data) low.
 *
 *  Token parsing supports the full range of Unicode characters as described
 *  in the E5 specification.  Parsing has been optimized for ASCII characters
 *  because ordinary ECMAScript code consists almost entirely of ASCII
 *  characters.  Matching of complex Unicode codepoint sets (such as in the
 *  IdentifierStart and IdentifierPart productions) is optimized for size,
 *  and is done using a linear scan of a bit-packed list of ranges.  This is
 *  very slow, but should never be entered unless the source code actually
 *  contains Unicode characters.
 *
 *  ECMAScript tokenization is partially context sensitive.  First,
 *  additional future reserved words are recognized in strict mode (see E5
 *  Section 7.6.1.2).  Second, a forward slash character ('/') can be
 *  recognized either as starting a RegExp literal or as a division operator,
 *  depending on context.  The caller must provide necessary context flags
 *  when requesting a new token.
 *
 *  Future work:
 *
 *    * Make line number tracking optional, as it consumes space.
 *
 *    * Add a feature flag for disabling UTF-8 decoding of input, as most
 *      source code is ASCII.  Because of Unicode escapes written in ASCII,
 *      this does not allow Unicode support to be removed from e.g.
 *      duk_unicode_is_identifier_start() nor does it allow removal of CESU-8
 *      encoding of e.g. string literals.
 *
 *    * Add a feature flag for disabling Unicode compliance of e.g. identifier
 *      names.  This allows for a build more than a kilobyte smaller, because
 *      Unicode ranges needed by duk_unicode_is_identifier_start() and
 *      duk_unicode_is_identifier_part() can be dropped.  String literals
 *      should still be allowed to contain escaped Unicode, so this still does
 *      not allow removal of CESU-8 encoding of e.g. string literals.
 *
 *    * Character lookup tables for codepoints above BMP could be stripped.
 *
 *    * Strictly speaking, E5 specification requires that source code consists
 *      of 16-bit code units, and if not, must be conceptually converted to
 *      that format first.  The current lexer processes Unicode code points
 *      and allows characters outside the BMP.  These should be converted to
 *      surrogate pairs while reading the source characters into the window,
 *      not after tokens have been formed (as is done now).  However, the fix
 *      is not trivial because two characters are decoded from one codepoint.
 *
 *    * Optimize for speed as well as size.  Large if-else ladders are (at
 *      least potentially) slow.
 */

/* #include duk_internal.h -> already included */

/*
 *  Various defines and file specific helper macros
 */

#define DUK__MAX_RE_DECESC_DIGITS     9
#define DUK__MAX_RE_QUANT_DIGITS      9   /* Does not allow e.g. 2**31-1, but one more would allow overflows of u32. */

/* whether to use macros or helper function depends on call count */
#define DUK__ISDIGIT(x)          ((x) >= DUK_ASC_0 && (x) <= DUK_ASC_9)
#define DUK__ISHEXDIGIT(x)       duk__is_hex_digit((x))
#define DUK__ISOCTDIGIT(x)       ((x) >= DUK_ASC_0 && (x) <= DUK_ASC_7)
#define DUK__ISDIGIT03(x)        ((x) >= DUK_ASC_0 && (x) <= DUK_ASC_3)
#define DUK__ISDIGIT47(x)        ((x) >= DUK_ASC_4 && (x) <= DUK_ASC_7)

/* lexer character window helpers */
#define DUK__LOOKUP(lex_ctx,idx)            ((lex_ctx)->window[(idx)].codepoint)
#define DUK__ADVANCECHARS(lex_ctx,count)    duk__advance_chars((lex_ctx), (count))
#define DUK__ADVANCEBYTES(lex_ctx,count)    duk__advance_bytes((lex_ctx), (count))
#define DUK__INITBUFFER(lex_ctx)            duk__initbuffer((lex_ctx))
#define DUK__APPENDBUFFER(lex_ctx,x)        duk__appendbuffer((lex_ctx), (duk_codepoint_t) (x))
#define DUK__APPENDBUFFER_ASCII(lex_ctx,x)  duk__appendbuffer_ascii((lex_ctx), (duk_codepoint_t) (x))

/* lookup shorthands (note: assume context variable is named 'lex_ctx') */
#define DUK__L0()  DUK__LOOKUP(lex_ctx, 0)
#define DUK__L1()  DUK__LOOKUP(lex_ctx, 1)
#define DUK__L2()  DUK__LOOKUP(lex_ctx, 2)
#define DUK__L3()  DUK__LOOKUP(lex_ctx, 3)
#define DUK__L4()  DUK__LOOKUP(lex_ctx, 4)
#define DUK__L5()  DUK__LOOKUP(lex_ctx, 5)

/* packed advance/token number macro used by multiple functions */
#define DUK__ADVTOK(advbytes,tok)  ((((advbytes) * sizeof(duk_lexer_codepoint)) << 8) + (tok))

/*
 *  Advance lookup window by N characters, filling in new characters as
 *  necessary.  After returning caller is guaranteed a character window of
 *  at least DUK_LEXER_WINDOW_SIZE characters.
 *
 *  The main function duk__advance_bytes() is called at least once per every
 *  token so it has a major lexer/compiler performance impact.  There are two
 *  variants for the main duk__advance_bytes() algorithm: a sliding window
 *  approach which is slightly faster at the cost of larger code footprint,
 *  and a simple copying one.
 *
 *  Decoding directly from the source string would be another lexing option.
 *  But the lookup window based approach has the advantage of hiding the
 *  source string and its encoding effectively which gives more flexibility
 *  going forward to e.g. support chunked streaming of source from flash.
 *
 *  Decodes UTF-8/CESU-8 leniently with support for code points from U+0000 to
 *  U+10FFFF, causing an error if the input is unparseable.  Leniency means:
 *
 *    * Unicode code point validation is intentionally not performed,
 *      except to check that the codepoint does not exceed 0x10ffff.
 *
 *    * In particular, surrogate pairs are allowed and not combined, which
 *      allows source files to represent all SourceCharacters with CESU-8.
 *      Broken surrogate pairs are allowed, as ECMAScript does not mandate
 *      their validation.
 *
 *    * Allow non-shortest UTF-8 encodings.
 *
 *  Leniency here causes few security concerns because all character data is
 *  decoded into Unicode codepoints before lexer processing, and is then
 *  re-encoded into CESU-8.  The source can be parsed as strict UTF-8 with
 *  a compiler option.  However, ECMAScript source characters include -all-
 *  16-bit unsigned integer codepoints, so leniency seems to be appropriate.
 *
 *  Note that codepoints above the BMP are not strictly SourceCharacters,
 *  but the lexer still accepts them as such.  Before ending up in a string
 *  or an identifier name, codepoints above BMP are converted into surrogate
 *  pairs and then CESU-8 encoded, resulting in 16-bit Unicode data as
 *  expected by ECMAScript.
 *
 *  An alternative approach to dealing with invalid or partial sequences
 *  would be to skip them and replace them with e.g. the Unicode replacement
 *  character U+FFFD.  This has limited utility because a replacement character
 *  will most likely cause a parse error, unless it occurs inside a string.
 *  Further, ECMAScript source is typically pure ASCII.
 *
 *  See:
 *
 *     http://en.wikipedia.org/wiki/UTF-8
 *     http://en.wikipedia.org/wiki/CESU-8
 *     http://tools.ietf.org/html/rfc3629
 *     http://en.wikipedia.org/wiki/UTF-8#Invalid_byte_sequences
 *
 *  Future work:
 *
 *    * Reject other invalid Unicode sequences (see Wikipedia entry for examples)
 *      in strict UTF-8 mode.
 *
 *    * Size optimize.  An attempt to use a 16-byte lookup table for the first
 *      byte resulted in a code increase though.
 *
 *    * Is checking against maximum 0x10ffff really useful?  4-byte encoding
 *      imposes a certain limit anyway.
 *
 *    * Support chunked streaming of source code.  Can be implemented either
 *      by streaming chunks of bytes or chunks of codepoints.
 */

#if defined(DUK_USE_LEXER_SLIDING_WINDOW)
DUK_LOCAL void duk__fill_lexer_buffer(duk_lexer_ctx *lex_ctx, duk_small_uint_t start_offset_bytes) {
	duk_lexer_codepoint *cp, *cp_end;
	duk_ucodepoint_t x;
	duk_small_uint_t contlen;
	const duk_uint8_t *p, *p_end;
#if defined(DUK_USE_STRICT_UTF8_SOURCE)
	duk_ucodepoint_t mincp;
#endif
	duk_int_t input_line;

	/* Use temporaries and update lex_ctx only when finished. */
	input_line = lex_ctx->input_line;
	p = lex_ctx->input + lex_ctx->input_offset;
	p_end = lex_ctx->input + lex_ctx->input_length;

	cp = (duk_lexer_codepoint *) (void *) ((duk_uint8_t *) lex_ctx->buffer + start_offset_bytes);
	cp_end = lex_ctx->buffer + DUK_LEXER_BUFFER_SIZE;

	for (; cp != cp_end; cp++) {
		cp->offset = (duk_size_t) (p - lex_ctx->input);
		cp->line = input_line;

		/* XXX: potential issue with signed pointers, p_end < p. */
		if (DUK_UNLIKELY(p >= p_end)) {
			/* If input_offset were assigned a negative value, it would
			 * result in a large positive value.  Most likely it would be
			 * larger than input_length and be caught here.  In any case
			 * no memory unsafe behavior would happen.
			 */
			cp->codepoint = -1;
			continue;
		}

		x = (duk_ucodepoint_t) (*p++);

		/* Fast path. */

		if (DUK_LIKELY(x < 0x80UL)) {
			DUK_ASSERT(x != 0x2028UL && x != 0x2029UL);  /* not LS/PS */
			if (DUK_UNLIKELY(x <= 0x000dUL)) {
				if ((x == 0x000aUL) ||
				    ((x == 0x000dUL) && (p >= p_end || *p != 0x000aUL))) {
					/* lookup for 0x000a above assumes shortest encoding now */

					/* E5 Section 7.3, treat the following as newlines:
					 *   LF
					 *   CR [not followed by LF]
					 *   LS
					 *   PS
					 *
					 * For CR LF, CR is ignored if it is followed by LF, and the LF will bump
					 * the line number.
					 */
					input_line++;
				}
			}

			cp->codepoint = (duk_codepoint_t) x;
			continue;
		}

		/* Slow path. */

		if (x < 0xc0UL) {
			/* 10xx xxxx -> invalid */
			goto error_encoding;
		} else if (x < 0xe0UL) {
			/* 110x xxxx   10xx xxxx  */
			contlen = 1;
#if defined(DUK_USE_STRICT_UTF8_SOURCE)
			mincp = 0x80UL;
#endif
			x = x & 0x1fUL;
		} else if (x < 0xf0UL) {
			/* 1110 xxxx   10xx xxxx   10xx xxxx */
			contlen = 2;
#if defined(DUK_USE_STRICT_UTF8_SOURCE)
			mincp = 0x800UL;
#endif
			x = x & 0x0fUL;
		} else if (x < 0xf8UL) {
			/* 1111 0xxx   10xx xxxx   10xx xxxx   10xx xxxx */
			contlen = 3;
#if defined(DUK_USE_STRICT_UTF8_SOURCE)
			mincp = 0x10000UL;
#endif
			x = x & 0x07UL;
		} else {
			/* no point in supporting encodings of 5 or more bytes */
			goto error_encoding;
		}

		DUK_ASSERT(p_end >= p);
		if ((duk_size_t) contlen > (duk_size_t) (p_end - p)) {
			goto error_clipped;
		}

		while (contlen > 0) {
			duk_small_uint_t y;
			y = *p++;
			if ((y & 0xc0U) != 0x80U) {
				/* check that byte has the form 10xx xxxx */
				goto error_encoding;
			}
			x = x << 6;
			x += y & 0x3fUL;
			contlen--;
		}

		/* check final character validity */

		if (x > 0x10ffffUL) {
			goto error_encoding;
		}
#if defined(DUK_USE_STRICT_UTF8_SOURCE)
		if (x < mincp || (x >= 0xd800UL && x <= 0xdfffUL) || x == 0xfffeUL) {
			goto error_encoding;
		}
#endif

		DUK_ASSERT(x != 0x000aUL && x != 0x000dUL);
		if ((x == 0x2028UL) || (x == 0x2029UL)) {
			input_line++;
		}

		cp->codepoint = (duk_codepoint_t) x;
	}

	lex_ctx->input_offset = (duk_size_t) (p - lex_ctx->input);
	lex_ctx->input_line = input_line;
	return;

 error_clipped:   /* clipped codepoint */
 error_encoding:  /* invalid codepoint encoding or codepoint */
	lex_ctx->input_offset = (duk_size_t) (p - lex_ctx->input);
	lex_ctx->input_line = input_line;

	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_SOURCE_DECODE_FAILED);
	DUK_WO_NORETURN(return;);
}

DUK_LOCAL void duk__advance_bytes(duk_lexer_ctx *lex_ctx, duk_small_uint_t count_bytes) {
	duk_small_uint_t used_bytes, avail_bytes;

	DUK_ASSERT_DISABLE(count_bytes >= 0);  /* unsigned */
	DUK_ASSERT(count_bytes <= (duk_small_uint_t) (DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint)));
	DUK_ASSERT(lex_ctx->window >= lex_ctx->buffer);
	DUK_ASSERT(lex_ctx->window < lex_ctx->buffer + DUK_LEXER_BUFFER_SIZE);
	DUK_ASSERT((duk_uint8_t *) lex_ctx->window + count_bytes <= (duk_uint8_t *) lex_ctx->buffer + DUK_LEXER_BUFFER_SIZE * sizeof(duk_lexer_codepoint));

	/* Zero 'count' is also allowed to make call sites easier.
	 * Arithmetic in bytes generates better code in GCC.
	 */

	lex_ctx->window = (duk_lexer_codepoint *) (void *) ((duk_uint8_t *) lex_ctx->window + count_bytes);  /* avoid multiply */
	used_bytes = (duk_small_uint_t) ((duk_uint8_t *) lex_ctx->window - (duk_uint8_t *) lex_ctx->buffer);
	avail_bytes = DUK_LEXER_BUFFER_SIZE * sizeof(duk_lexer_codepoint) - used_bytes;
	if (avail_bytes < (duk_small_uint_t) (DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint))) {
		/* Not enough data to provide a full window, so "scroll" window to
		 * start of buffer and fill up the rest.
		 */
		duk_memmove((void *) lex_ctx->buffer,
		            (const void *) lex_ctx->window,
		            (size_t) avail_bytes);
		lex_ctx->window = lex_ctx->buffer;
		duk__fill_lexer_buffer(lex_ctx, avail_bytes);
	}
}

DUK_LOCAL void duk__init_lexer_window(duk_lexer_ctx *lex_ctx) {
	lex_ctx->window = lex_ctx->buffer;
	duk__fill_lexer_buffer(lex_ctx, 0);
}
#else  /* DUK_USE_LEXER_SLIDING_WINDOW */
DUK_LOCAL duk_codepoint_t duk__read_char(duk_lexer_ctx *lex_ctx) {
	duk_ucodepoint_t x;
	duk_small_uint_t len;
	duk_small_uint_t i;
	const duk_uint8_t *p;
#if defined(DUK_USE_STRICT_UTF8_SOURCE)
	duk_ucodepoint_t mincp;
#endif
	duk_size_t input_offset;

	input_offset = lex_ctx->input_offset;
	if (DUK_UNLIKELY(input_offset >= lex_ctx->input_length)) {
		/* If input_offset were assigned a negative value, it would
		 * result in a large positive value.  Most likely it would be
		 * larger than input_length and be caught here.  In any case
		 * no memory unsafe behavior would happen.
		 */
		return -1;
	}

	p = lex_ctx->input + input_offset;
	x = (duk_ucodepoint_t) (*p);

	if (DUK_LIKELY(x < 0x80UL)) {
		/* 0xxx xxxx -> fast path */

		/* input offset tracking */
		lex_ctx->input_offset++;

		DUK_ASSERT(x != 0x2028UL && x != 0x2029UL);  /* not LS/PS */
		if (DUK_UNLIKELY(x <= 0x000dUL)) {
			if ((x == 0x000aUL) ||
			    ((x == 0x000dUL) && (lex_ctx->input_offset >= lex_ctx->input_length ||
			                         lex_ctx->input[lex_ctx->input_offset] != 0x000aUL))) {
				/* lookup for 0x000a above assumes shortest encoding now */

				/* E5 Section 7.3, treat the following as newlines:
				 *   LF
				 *   CR [not followed by LF]
				 *   LS
				 *   PS
				 *
				 * For CR LF, CR is ignored if it is followed by LF, and the LF will bump
				 * the line number.
				 */
				lex_ctx->input_line++;
			}
		}

		return (duk_codepoint_t) x;
	}

	/* Slow path. */

	if (x < 0xc0UL) {
		/* 10xx xxxx -> invalid */
		goto error_encoding;
	} else if (x < 0xe0UL) {
		/* 110x xxxx   10xx xxxx  */
		len = 2;
#if defined(DUK_USE_STRICT_UTF8_SOURCE)
		mincp = 0x80UL;
#endif
		x = x & 0x1fUL;
	} else if (x < 0xf0UL) {
		/* 1110 xxxx   10xx xxxx   10xx xxxx */
		len = 3;
#if defined(DUK_USE_STRICT_UTF8_SOURCE)
		mincp = 0x800UL;
#endif
		x = x & 0x0fUL;
	} else if (x < 0xf8UL) {
		/* 1111 0xxx   10xx xxxx   10xx xxxx   10xx xxxx */
		len = 4;
#if defined(DUK_USE_STRICT_UTF8_SOURCE)
		mincp = 0x10000UL;
#endif
		x = x & 0x07UL;
	} else {
		/* no point in supporting encodings of 5 or more bytes */
		goto error_encoding;
	}

	DUK_ASSERT(lex_ctx->input_length >= lex_ctx->input_offset);
	if ((duk_size_t) len > (duk_size_t) (lex_ctx->input_length - lex_ctx->input_offset)) {
		goto error_clipped;
	}

	p++;
	for (i = 1; i < len; i++) {
		duk_small_uint_t y;
		y = *p++;
		if ((y & 0xc0U) != 0x80U) {
			/* check that byte has the form 10xx xxxx */
			goto error_encoding;
		}
		x = x << 6;
		x += y & 0x3fUL;
	}

	/* check final character validity */

	if (x > 0x10ffffUL) {
		goto error_encoding;
	}
#if defined(DUK_USE_STRICT_UTF8_SOURCE)
	if (x < mincp || (x >= 0xd800UL && x <= 0xdfffUL) || x == 0xfffeUL) {
		goto error_encoding;
	}
#endif

	/* input offset tracking */
	lex_ctx->input_offset += len;

	/* line tracking */
	DUK_ASSERT(x != 0x000aUL && x != 0x000dUL);
	if ((x == 0x2028UL) || (x == 0x2029UL)) {
		lex_ctx->input_line++;
	}

	return (duk_codepoint_t) x;

 error_clipped:   /* clipped codepoint */
 error_encoding:  /* invalid codepoint encoding or codepoint */
	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_SOURCE_DECODE_FAILED);
	DUK_WO_NORETURN(return 0;);
}

DUK_LOCAL void duk__advance_bytes(duk_lexer_ctx *lex_ctx, duk_small_uint_t count_bytes) {
	duk_small_uint_t keep_bytes;
	duk_lexer_codepoint *cp, *cp_end;

	DUK_ASSERT_DISABLE(count_bytes >= 0);  /* unsigned */
	DUK_ASSERT(count_bytes <= (duk_small_uint_t) (DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint)));

	/* Zero 'count' is also allowed to make call sites easier. */

	keep_bytes = DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint) - count_bytes;
	duk_memmove((void *) lex_ctx->window,
	            (const void *) ((duk_uint8_t *) lex_ctx->window + count_bytes),
	            (size_t) keep_bytes);

	cp = (duk_lexer_codepoint *) ((duk_uint8_t *) lex_ctx->window + keep_bytes);
	cp_end = lex_ctx->window + DUK_LEXER_WINDOW_SIZE;
	for (; cp != cp_end; cp++) {
		cp->offset = lex_ctx->input_offset;
		cp->line = lex_ctx->input_line;
		cp->codepoint = duk__read_char(lex_ctx);
	}
}

DUK_LOCAL void duk__init_lexer_window(duk_lexer_ctx *lex_ctx) {
	/* Call with count == DUK_LEXER_WINDOW_SIZE to fill buffer initially. */
	duk__advance_bytes(lex_ctx, DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint));  /* fill window */
}
#endif  /* DUK_USE_LEXER_SLIDING_WINDOW */

DUK_LOCAL void duk__advance_chars(duk_lexer_ctx *lex_ctx, duk_small_uint_t count_chars) {
	duk__advance_bytes(lex_ctx, count_chars * sizeof(duk_lexer_codepoint));
}

/*
 *  (Re)initialize the temporary byte buffer.  May be called extra times
 *  with little impact.
 */

DUK_LOCAL void duk__initbuffer(duk_lexer_ctx *lex_ctx) {
	/* Reuse buffer as is unless buffer has grown large. */
	if (DUK_HBUFFER_DYNAMIC_GET_SIZE(lex_ctx->buf) < DUK_LEXER_TEMP_BUF_LIMIT) {
		/* Keep current size */
	} else {
		duk_hbuffer_resize(lex_ctx->thr, lex_ctx->buf, DUK_LEXER_TEMP_BUF_LIMIT);
	}

	DUK_BW_INIT_WITHBUF(lex_ctx->thr, &lex_ctx->bw, lex_ctx->buf);
}

/*
 *  Append a Unicode codepoint to the temporary byte buffer.  Performs
 *  CESU-8 surrogate pair encoding for codepoints above the BMP.
 *  Existing surrogate pairs are allowed and also encoded into CESU-8.
 */

DUK_LOCAL void duk__appendbuffer(duk_lexer_ctx *lex_ctx, duk_codepoint_t x) {
	/*
	 *  Since character data is only generated by decoding the source or by
	 *  the compiler itself, we rely on the input codepoints being correct
	 *  and avoid a check here.
	 *
	 *  Character data can also come here through decoding of Unicode
	 *  escapes ("\udead\ubeef") so all 16-but unsigned values can be
	 *  present, even when the source file itself is strict UTF-8.
	 */
	DUK_ASSERT(x >= 0 && x <= 0x10ffffL);

	DUK_BW_WRITE_ENSURE_CESU8(lex_ctx->thr, &lex_ctx->bw, (duk_ucodepoint_t) x);
}

DUK_LOCAL void duk__appendbuffer_ascii(duk_lexer_ctx *lex_ctx, duk_codepoint_t x) {
	/* ASCII characters can be emitted as a single byte without encoding
	 * which matters for some fast paths.
	 */
	DUK_ASSERT(x >= 0 && x <= 0x7f);

	DUK_BW_WRITE_ENSURE_U8(lex_ctx->thr, &lex_ctx->bw, (duk_uint8_t) x);
}

/*
 *  Intern the temporary byte buffer into a valstack slot
 *  (in practice, slot1 or slot2).
 */

DUK_LOCAL duk_hstring *duk__internbuffer(duk_lexer_ctx *lex_ctx, duk_idx_t valstack_idx) {
	DUK_ASSERT(valstack_idx == lex_ctx->slot1_idx || valstack_idx == lex_ctx->slot2_idx);

	DUK_BW_PUSH_AS_STRING(lex_ctx->thr, &lex_ctx->bw);
	duk_replace(lex_ctx->thr, valstack_idx);
	return duk_known_hstring(lex_ctx->thr, valstack_idx);
}

/*
 *  Init lexer context
 */

DUK_INTERNAL void duk_lexer_initctx(duk_lexer_ctx *lex_ctx) {
	DUK_ASSERT(lex_ctx != NULL);

	duk_memzero(lex_ctx, sizeof(*lex_ctx));
#if defined(DUK_USE_EXPLICIT_NULL_INIT)
#if defined(DUK_USE_LEXER_SLIDING_WINDOW)
	lex_ctx->window = NULL;
#endif
	lex_ctx->thr = NULL;
	lex_ctx->input = NULL;
	lex_ctx->buf = NULL;
#endif
}

/*
 *  Set lexer input position and reinitialize lookup window.
 */

DUK_INTERNAL void duk_lexer_getpoint(duk_lexer_ctx *lex_ctx, duk_lexer_point *pt) {
	pt->offset = lex_ctx->window[0].offset;
	pt->line = lex_ctx->window[0].line;
}

DUK_INTERNAL void duk_lexer_setpoint(duk_lexer_ctx *lex_ctx, duk_lexer_point *pt) {
	DUK_ASSERT_DISABLE(pt->offset >= 0);  /* unsigned */
	DUK_ASSERT(pt->line >= 1);
	lex_ctx->input_offset = pt->offset;
	lex_ctx->input_line = pt->line;
	duk__init_lexer_window(lex_ctx);
}

/*
 *  Lexing helpers
 */

/* Numeric value of a hex digit (also covers octal and decimal digits) or
 * -1 if not a valid hex digit.
 */
DUK_LOCAL duk_codepoint_t duk__hexval_validate(duk_codepoint_t x) {
	duk_small_int_t t;

	/* Here 'x' is a Unicode codepoint */
	if (DUK_LIKELY(x >= 0 && x <= 0xff)) {
		t = duk_hex_dectab[x];
		if (DUK_LIKELY(t >= 0)) {
			return t;
		}
	}

	return -1;
}

/* Just a wrapper for call sites where 'x' is known to be valid so
 * we assert for it before decoding.
 */
DUK_LOCAL duk_codepoint_t duk__hexval(duk_codepoint_t x) {
	duk_codepoint_t ret;

	DUK_ASSERT((x >= DUK_ASC_0 && x <= DUK_ASC_9) ||
	           (x >= DUK_ASC_LC_A && x <= DUK_ASC_LC_F) ||
	           (x >= DUK_ASC_UC_A && x <= DUK_ASC_UC_F));
	ret = duk__hexval_validate(x);
	DUK_ASSERT(ret >= 0 && ret <= 15);
	return ret;
}

/* having this as a separate function provided a size benefit */
DUK_LOCAL duk_bool_t duk__is_hex_digit(duk_codepoint_t x) {
	if (DUK_LIKELY(x >= 0 && x <= 0xff)) {
		return (duk_hex_dectab[x] >= 0);
	}
	return 0;
}

/* Parse a Unicode escape of the form \xHH, \uHHHH, or \u{H+}.  Shared by
 * source and RegExp parsing.
 */
DUK_LOCAL duk_codepoint_t duk__lexer_parse_escape(duk_lexer_ctx *lex_ctx, duk_bool_t allow_es6) {
	duk_small_int_t digits;  /* Initial value 2 or 4 for fixed length escapes, 0 for ES2015 \u{H+}. */
	duk_codepoint_t escval;
	duk_codepoint_t x;
	duk_small_uint_t adv;

	DUK_ASSERT(DUK__L0() == DUK_ASC_BACKSLASH);  /* caller responsibilities */
	DUK_ASSERT(DUK__L1() == DUK_ASC_LC_X || DUK__L1() == DUK_ASC_LC_U);
	DUK_UNREF(allow_es6);

	adv = 2;
	digits = 2;
	if (DUK__L1() == DUK_ASC_LC_U) {
		digits = 4;
#if defined(DUK_USE_ES6_UNICODE_ESCAPE)
		if (DUK__L2() == DUK_ASC_LCURLY && allow_es6) {
			digits = 0;
			adv = 3;
		}
#endif
	}
	DUK__ADVANCECHARS(lex_ctx, adv);

	escval = 0;
	for (;;) {
		/* One of the escape forms: \xHH, \uHHHH, \u{H+}.
		 * The 'digits' variable tracks parsing state and is
		 * initialized to:
		 *
		 *   \xHH     2
		 *   \uHH     4
		 *   \u{H+}   0 first time, updated to -1 to indicate
		 *            at least one digit has been parsed
		 *
		 * Octal parsing is handled separately because it can be
		 * done with fixed lookahead and also has validation
		 * rules which depend on the escape length (which is
		 * variable).
		 *
		 * We don't need a specific check for x < 0 (end of
		 * input) or duk_unicode_is_line_terminator(x)
		 * because the 'dig' decode will fail and lead to a
		 * SyntaxError.
		 */
		duk_codepoint_t dig;

		x = DUK__L0();
		DUK__ADVANCECHARS(lex_ctx, 1);

		dig = duk__hexval_validate(x);
		if (digits > 0) {
			digits--;
			if (dig < 0) {
				goto fail_escape;
			}
			DUK_ASSERT(dig >= 0x00 && dig <= 0x0f);
			escval = (escval << 4) + dig;
			if (digits == 0) {
				DUK_ASSERT(escval >= 0 && escval <= 0xffffL);
				break;
			}
		} else {
#if defined(DUK_USE_ES6_UNICODE_ESCAPE)
			DUK_ASSERT(digits == 0 /* first time */ || digits == -1 /* others */);
			if (dig >= 0) {
				DUK_ASSERT(dig >= 0x00 && dig <= 0x0f);
				escval = (escval << 4) + dig;
				if (escval > 0x10ffffL) {
					goto fail_escape;
				}
			} else if (x == DUK_ASC_RCURLY) {
				if (digits == 0) {
					/* Empty escape, \u{}. */
					goto fail_escape;
				}
				DUK_ASSERT(escval >= 0 && escval <= 0x10ffffL);
				break;
			} else {
				goto fail_escape;
			}
			digits = -1;  /* Indicate we have at least one digit. */
#else  /* DUK_USE_ES6_UNICODE_ESCAPE */
			DUK_ASSERT(0);  /* Never happens if \u{H+} support disabled. */
#endif  /* DUK_USE_ES6_UNICODE_ESCAPE */
		}
	}

	return escval;

 fail_escape:
	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_ESCAPE);
	DUK_WO_NORETURN(return 0;);
}

/* Parse legacy octal escape of the form \N{1,3}, e.g. \0, \5, \0377.  Maximum
 * allowed value is \0377 (U+00FF), longest match is used.  Used for both string
 * RegExp octal escape parsing.  Window[0] must be the slash '\' and the first
 * digit must already be validated to be in [0-9] by the caller.
 */
DUK_LOCAL duk_codepoint_t duk__lexer_parse_legacy_octal(duk_lexer_ctx *lex_ctx, duk_small_uint_t *out_adv, duk_bool_t reject_annex_b) {
	duk_codepoint_t cp;
	duk_small_uint_t lookup_idx;
	duk_small_uint_t adv;
	duk_codepoint_t tmp;

	DUK_ASSERT(out_adv != NULL);
	DUK_ASSERT(DUK__LOOKUP(lex_ctx, 0) == DUK_ASC_BACKSLASH);
	DUK_ASSERT(DUK__LOOKUP(lex_ctx, 1) >= DUK_ASC_0 && DUK__LOOKUP(lex_ctx, 1) <= DUK_ASC_9);

	cp = 0;
	tmp = 0;
	for (lookup_idx = 1; lookup_idx <= 3; lookup_idx++) {
		DUK_DDD(DUK_DDDPRINT("lookup_idx=%ld, cp=%ld", (long) lookup_idx, (long) cp));
		tmp = DUK__LOOKUP(lex_ctx, lookup_idx);
		if (tmp < DUK_ASC_0 || tmp > DUK_ASC_7) {
			/* No more valid digits. */
			break;
		}
		tmp = (cp << 3) + (tmp - DUK_ASC_0);
		if (tmp > 0xff) {
			/* Three digit octal escapes above \377 (= 0xff)
			 * are not allowed.
			 */
			break;
		}
		cp = tmp;
	}
	DUK_DDD(DUK_DDDPRINT("final lookup_idx=%ld, cp=%ld", (long) lookup_idx, (long) cp));

	adv = lookup_idx;
	if (lookup_idx == 1) {
		DUK_DDD(DUK_DDDPRINT("\\8 or \\9 -> treat as literal, accept in strict mode too"));
		DUK_ASSERT(tmp == DUK_ASC_8 || tmp == DUK_ASC_9);
		cp = tmp;
		adv++;  /* correction to above, eat offending character */
	} else if (lookup_idx == 2 && cp == 0) {
		/* Note: 'foo\0bar' is OK in strict mode, but 'foo\00bar' is not.
		 * It won't be interpreted as 'foo\u{0}0bar' but as a SyntaxError.
		 */
		DUK_DDD(DUK_DDDPRINT("\\0 -> accept in strict mode too"));
	} else {
		/* This clause also handles non-shortest zero, e.g. \00. */
		if (reject_annex_b) {
			DUK_DDD(DUK_DDDPRINT("non-zero octal literal %ld -> reject in strict-mode", (long) cp));
			cp = -1;
		} else {
			DUK_DDD(DUK_DDDPRINT("non-zero octal literal %ld -> accepted", (long) cp));
			DUK_ASSERT(cp >= 0 && cp <= 0xff);
		}
	}

	*out_adv = adv;

	DUK_ASSERT((cp >= 0 && cp <= 0xff) || (cp == -1 && reject_annex_b));
	return cp;
}

/* XXX: move strict mode to lex_ctx? */
DUK_LOCAL void duk__lexer_parse_string_literal(duk_lexer_ctx *lex_ctx, duk_token *out_token, duk_small_int_t quote, duk_bool_t strict_mode) {
	duk_small_uint_t adv;

	for (adv = 1 /* initial quote */ ;;) {
		duk_codepoint_t x;

		DUK__ADVANCECHARS(lex_ctx, adv);  /* eat opening quote on first loop */
		x = DUK__L0();

		adv = 1;
		if (x == quote) {
			DUK__ADVANCECHARS(lex_ctx, 1);  /* eat closing quote */
			break;
		} else if (x == '\\') {
			/* DUK__L0        -> '\' char
			 * DUK__L1 ... DUK__L5 -> more lookup
			 */
			duk_small_int_t emitcp = -1;

			x = DUK__L1();

			/* How much to advance before next loop. */
			adv = 2;  /* note: long live range */

			switch (x) {
			case '\'':
				emitcp = 0x0027;
				break;
			case '"':
				emitcp = 0x0022;
				break;
			case '\\':
				emitcp = 0x005c;
				break;
			case 'b':
				emitcp = 0x0008;
				break;
			case 'f':
				emitcp = 0x000c;
				break;
			case 'n':
				emitcp = 0x000a;
				break;
			case 'r':
				emitcp = 0x000d;
				break;
			case 't':
				emitcp = 0x0009;
				break;
			case 'v':
				emitcp = 0x000b;
				break;
			case 'x':
			case 'u': {
				duk_codepoint_t esc_cp;
				esc_cp = duk__lexer_parse_escape(lex_ctx, 1 /*allow_es6*/);
				DUK__APPENDBUFFER(lex_ctx, esc_cp);
				adv = 0;
				break;
			}
			default: {
				if (duk_unicode_is_line_terminator(x)) {
					/* line continuation */
					if (x == 0x000d && DUK__L2() == 0x000a) {
						/* CR LF again a special case */
						adv = 3;  /* line terminator, CR, LF */
					}
				} else if (DUK__ISDIGIT(x)) {
					/*
					 *  Octal escape or zero escape:
					 *    \0                                     (lookahead not OctalDigit)
					 *    \1 ... \7                              (lookahead not OctalDigit)
					 *    \ZeroToThree OctalDigit                (lookahead not OctalDigit)
					 *    \FourToSeven OctalDigit                (no lookahead restrictions)
					 *    \ZeroToThree OctalDigit OctalDigit     (no lookahead restrictions)
					 *
					 *  Zero escape is part of the standard syntax.  Octal escapes are
					 *  defined in E5 Section B.1.2, and are only allowed in non-strict mode.
					 *  Any other productions starting with a decimal digit are invalid
					 *  but are in practice treated like identity escapes.
					 *
					 *  Parse octal (up to 3 digits) from the lookup window.
					 */

					emitcp = duk__lexer_parse_legacy_octal(lex_ctx, &adv, strict_mode /*reject_annex_b*/);
					if (emitcp < 0) {
						goto fail_escape;
					}
				} else if (x < 0) {
					goto fail_unterminated;
				} else {
					/* escaped NonEscapeCharacter */
					DUK__APPENDBUFFER(lex_ctx, x);
				}
			}  /* end default clause */
			}  /* end switch */

			/* Shared handling for single codepoint escapes. */
			if (emitcp >= 0) {
				DUK__APPENDBUFFER(lex_ctx, emitcp);
			}

			/* Track number of escapes; count not really needed but directive
			 * prologues need to detect whether there were any escapes or line
			 * continuations or not.
			 */
			out_token->num_escapes++;
		} else if (x >= 0x20 && x <= 0x7f) {
			/* Fast path for ASCII case, avoids line terminator
			 * check and CESU-8 encoding.
			 */
			DUK_ASSERT(x >= 0);
			DUK_ASSERT(!duk_unicode_is_line_terminator(x));
			DUK_ASSERT(x != quote);
			DUK_ASSERT(x != DUK_ASC_BACKSLASH);
			DUK__APPENDBUFFER_ASCII(lex_ctx, x);
		} else if (x < 0 || duk_unicode_is_line_terminator(x)) {
			goto fail_unterminated;
		} else {
			/* Character which is part of the string but wasn't handled
			 * by the fast path.
			 */
			DUK__APPENDBUFFER(lex_ctx, x);
		}
	} /* string parse loop */

	return;

 fail_escape:
	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_ESCAPE);
	DUK_WO_NORETURN(return;);

 fail_unterminated:
	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_UNTERMINATED_STRING);
	DUK_WO_NORETURN(return;);
}

/* Skip to end-of-line (or end-of-file), used for single line comments. */
DUK_LOCAL void duk__lexer_skip_to_endofline(duk_lexer_ctx *lex_ctx) {
	for (;;) {
		duk_codepoint_t x;

		x = DUK__L0();
		if (x < 0 || duk_unicode_is_line_terminator(x)) {
			break;
		}
		DUK__ADVANCECHARS(lex_ctx, 1);
	}
}

/*
 *  Parse ECMAScript source InputElementDiv or InputElementRegExp
 *  (E5 Section 7), skipping whitespace, comments, and line terminators.
 *
 *  Possible results are:
 *    (1) a token
 *    (2) a line terminator (skipped)
 *    (3) a comment (skipped)
 *    (4) EOF
 *
 *  White space is automatically skipped from the current position (but
 *  not after the input element).  If input has already ended, returns
 *  DUK_TOK_EOF indefinitely.  If a parse error occurs, uses an DUK_ERROR()
 *  macro call (and hence a longjmp through current heap longjmp context).
 *  Comments and line terminator tokens are automatically skipped.
 *
 *  The input element being matched is determined by regexp_mode; if set,
 *  parses a InputElementRegExp, otherwise a InputElementDiv.  The
 *  difference between these are handling of productions starting with a
 *  forward slash.
 *
 *  If strict_mode is set, recognizes additional future reserved words
 *  specific to strict mode, and refuses to parse octal literals.
 *
 *  The matching strategy below is to (currently) use a six character
 *  lookup window to quickly determine which production is the -longest-
 *  matching one, and then parse that.  The top-level if-else clauses
 *  match the first character, and the code blocks for each clause
 *  handle -all- alternatives for that first character.  ECMAScript
 *  specification uses the "longest match wins" semantics, so the order
 *  of the if-clauses matters.
 *
 *  Misc notes:
 *
 *    * ECMAScript numeric literals do not accept a sign character.
 *      Consequently e.g. "-1.0" is parsed as two tokens: a negative
 *      sign and a positive numeric literal.  The compiler performs
 *      the negation during compilation, so this has no adverse impact.
 *
 *    * There is no token for "undefined": it is just a value available
 *      from the global object (or simply established by doing a reference
 *      to an undefined value).
 *
 *    * Some contexts want Identifier tokens, which are IdentifierNames
 *      excluding reserved words, while some contexts want IdentifierNames
 *      directly.  In the latter case e.g. "while" is interpreted as an
 *      identifier name, not a DUK_TOK_WHILE token.  The solution here is
 *      to provide both token types: DUK_TOK_WHILE goes to 't' while
 *      DUK_TOK_IDENTIFIER goes to 't_nores', and 'slot1' always contains
 *      the identifier / keyword name.
 *
 *    * Directive prologue needs to identify string literals such as
 *      "use strict" and 'use strict', which are sensitive to line
 *      continuations and escape sequences.  For instance, "use\u0020strict"
 *      is a valid directive but is distinct from "use strict".  The solution
 *      here is to decode escapes while tokenizing, but to keep track of the
 *      number of escapes.  Directive detection can then check that the
 *      number of escapes is zero.
 *
 *    * Multi-line comments with one or more internal LineTerminator are
 *      treated like a line terminator to comply with automatic semicolon
 *      insertion.
 */

DUK_INTERNAL
void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx,
                                      duk_token *out_token,
                                      duk_bool_t strict_mode,
                                      duk_bool_t regexp_mode) {
	duk_codepoint_t x;           /* temporary, must be signed and 32-bit to hold Unicode code points */
	duk_small_uint_t advtok = 0; /* (advance << 8) + token_type, updated at function end,
	                              * init is unnecessary but suppresses "may be used uninitialized" warnings.
	                              */
	duk_bool_t got_lineterm = 0;  /* got lineterm preceding non-whitespace, non-lineterm token */

	if (++lex_ctx->token_count >= lex_ctx->token_limit) {
		goto fail_token_limit;
	}

	out_token->t = DUK_TOK_EOF;
	out_token->t_nores = DUK_TOK_INVALID;  /* marker: copy t if not changed */
#if 0  /* not necessary to init, disabled for faster parsing */
	out_token->num = DUK_DOUBLE_NAN;
	out_token->str1 = NULL;
	out_token->str2 = NULL;
#endif
	out_token->num_escapes = 0;
	/* out_token->lineterm set by caller */

	/* This would be nice, but parsing is faster without resetting the
	 * value slots.  The only side effect is that references to temporary
	 * string values may linger until lexing is finished; they're then
	 * freed normally.
	 */
#if 0
	duk_to_undefined(lex_ctx->thr, lex_ctx->slot1_idx);
	duk_to_undefined(lex_ctx->thr, lex_ctx->slot2_idx);
#endif

	/* 'advtok' indicates how much to advance and which token id to assign
	 * at the end.  This shared functionality minimizes code size.  All
	 * code paths are required to set 'advtok' to some value, so no default
	 * init value is used.  Code paths calling DUK_ERROR() never return so
	 * they don't need to set advtok.
	 */

	/*
	 *  Matching order:
	 *
	 *    Punctuator first chars, also covers comments, regexps
	 *    LineTerminator
	 *    Identifier or reserved word, also covers null/true/false literals
	 *    NumericLiteral
	 *    StringLiteral
	 *    EOF
	 *
	 *  The order does not matter as long as the longest match is
	 *  always correctly identified.  There are order dependencies
	 *  in the clauses, so it's not trivial to convert to a switch.
	 */

 restart_lineupdate:
	out_token->start_line = lex_ctx->window[0].line;

 restart:
	out_token->start_offset = lex_ctx->window[0].offset;

	x = DUK__L0();

	switch (x) {
	case DUK_ASC_SPACE:
	case DUK_ASC_HT:  /* fast paths for space and tab */
		DUK__ADVANCECHARS(lex_ctx, 1);
		goto restart;
	case DUK_ASC_LF:  /* LF line terminator; CR LF and Unicode lineterms are handled in slow path */
		DUK__ADVANCECHARS(lex_ctx, 1);
		got_lineterm = 1;
		goto restart_lineupdate;
#if defined(DUK_USE_SHEBANG_COMMENTS)
	case DUK_ASC_HASH:  /* '#' */
		if (DUK__L1() == DUK_ASC_EXCLAMATION && lex_ctx->window[0].offset == 0 &&
		    (lex_ctx->flags & DUK_COMPILE_SHEBANG)) {
			/* "Shebang" comment ('#! ...') on first line. */
			/* DUK__ADVANCECHARS(lex_ctx, 2) would be correct here, but not necessary */
			duk__lexer_skip_to_endofline(lex_ctx);
			goto restart;  /* line terminator will be handled on next round */
		}
		goto fail_token;
#endif  /* DUK_USE_SHEBANG_COMMENTS */
	case DUK_ASC_SLASH:  /* '/' */
		if (DUK__L1() == DUK_ASC_SLASH) {
			/*
			 *  E5 Section 7.4, allow SourceCharacter (which is any 16-bit
			 *  code point).
			 */

			/* DUK__ADVANCECHARS(lex_ctx, 2) would be correct here, but not necessary */
			duk__lexer_skip_to_endofline(lex_ctx);
			goto restart;  /* line terminator will be handled on next round */
		} else if (DUK__L1() == DUK_ASC_STAR) {
			/*
			 *  E5 Section 7.4.  If the multi-line comment contains a newline,
			 *  it is treated like a single line terminator for automatic
			 *  semicolon insertion.
			 */

			duk_bool_t last_asterisk = 0;
			DUK__ADVANCECHARS(lex_ctx, 2);
			for (;;) {
				x = DUK__L0();
				if (x < 0) {
					goto fail_unterm_comment;
				}
				DUK__ADVANCECHARS(lex_ctx, 1);
				if (last_asterisk && x == DUK_ASC_SLASH) {
					break;
				}
				if (duk_unicode_is_line_terminator(x)) {
					got_lineterm = 1;
				}
				last_asterisk = (x == DUK_ASC_STAR);
			}
			goto restart_lineupdate;
		} else if (regexp_mode) {
#if defined(DUK_USE_REGEXP_SUPPORT)
			/*
			 *  "/" followed by something in regexp mode.  See E5 Section 7.8.5.
			 *
			 *  RegExp parsing is a bit complex.  First, the regexp body is delimited
			 *  by forward slashes, but the body may also contain forward slashes as
			 *  part of an escape sequence or inside a character class (delimited by
			 *  square brackets).  A mini state machine is used to implement these.
			 *
			 *  Further, an early (parse time) error must be thrown if the regexp
			 *  would cause a run-time error when used in the expression new RegExp(...).
			 *  Parsing here simply extracts the (candidate) regexp, and also accepts
			 *  invalid regular expressions (which are delimited properly).  The caller
			 *  (compiler) must perform final validation and regexp compilation.
			 *
			 *  RegExp first char may not be '/' (single line comment) or '*' (multi-
			 *  line comment).  These have already been checked above, so there is no
			 *  need below for special handling of the first regexp character as in
			 *  the E5 productions.
			 *
			 *  About unicode escapes within regexp literals:
			 *
			 *      E5 Section 7.8.5 grammar does NOT accept \uHHHH escapes.
			 *      However, Section 6 states that regexps accept the escapes,
			 *      see paragraph starting with "In string literals...".
			 *      The regexp grammar, which sees the decoded regexp literal
			 *      (after lexical parsing) DOES have a \uHHHH unicode escape.
			 *      So, for instance:
			 *
			 *          /\u1234/
			 *
			 *      should first be parsed by the lexical grammar as:
			 *
			 *          '\' 'u'      RegularExpressionBackslashSequence
			 *          '1'          RegularExpressionNonTerminator
			 *          '2'          RegularExpressionNonTerminator
			 *          '3'          RegularExpressionNonTerminator
			 *          '4'          RegularExpressionNonTerminator
			 *
			 *      and the escape itself is then parsed by the regexp engine.
			 *      This is the current implementation.
			 *
			 *  Minor spec inconsistency:
			 *
			 *      E5 Section 7.8.5 RegularExpressionBackslashSequence is:
			 *
			 *         \ RegularExpressionNonTerminator
			 *
			 *      while Section A.1 RegularExpressionBackslashSequence is:
			 *
			 *         \ NonTerminator
			 *
			 *      The latter is not normative and a typo.
			 *
			 */

			/* first, parse regexp body roughly */

			duk_small_int_t state = 0;  /* 0=base, 1=esc, 2=class, 3=class+esc */

			DUK__INITBUFFER(lex_ctx);
			for (;;) {
				DUK__ADVANCECHARS(lex_ctx, 1);  /* skip opening slash on first loop */
				x = DUK__L0();
				if (x < 0 || duk_unicode_is_line_terminator(x)) {
					goto fail_unterm_regexp;
				}
				x = DUK__L0();  /* re-read to avoid spill / fetch */
				if (state == 0) {
					if (x == DUK_ASC_SLASH) {
						DUK__ADVANCECHARS(lex_ctx, 1);  /* eat closing slash */
						break;
					} else if (x == DUK_ASC_BACKSLASH) {
						state = 1;
					} else if (x == DUK_ASC_LBRACKET) {
						state = 2;
					}
				} else if (state == 1) {
					state = 0;
				} else if (state == 2) {
					if (x == DUK_ASC_RBRACKET) {
						state = 0;
					} else if (x == DUK_ASC_BACKSLASH) {
						state = 3;
					}
				} else { /* state == 3 */
					state = 2;
				}
				DUK__APPENDBUFFER(lex_ctx, x);
			}
			out_token->str1 = duk__internbuffer(lex_ctx, lex_ctx->slot1_idx);

			/* second, parse flags */

			DUK__INITBUFFER(lex_ctx);
			for (;;) {
				x = DUK__L0();
				if (!duk_unicode_is_identifier_part(x)) {
					break;
				}
				x = DUK__L0();  /* re-read to avoid spill / fetch */
				DUK__APPENDBUFFER(lex_ctx, x);
				DUK__ADVANCECHARS(lex_ctx, 1);
			}
			out_token->str2 = duk__internbuffer(lex_ctx, lex_ctx->slot2_idx);

			DUK__INITBUFFER(lex_ctx);  /* free some memory */

			/* validation of the regexp is caller's responsibility */

			advtok = DUK__ADVTOK(0, DUK_TOK_REGEXP);
#else  /* DUK_USE_REGEXP_SUPPORT */
			goto fail_regexp_support;
#endif  /* DUK_USE_REGEXP_SUPPORT */
		} else if (DUK__L1() == DUK_ASC_EQUALS) {
			/* "/=" and not in regexp mode */
			advtok = DUK__ADVTOK(2, DUK_TOK_DIV_EQ);
		} else {
			/* "/" and not in regexp mode */
			advtok = DUK__ADVTOK(1, DUK_TOK_DIV);
		}
		break;
	case DUK_ASC_LCURLY:  /* '{' */
		advtok = DUK__ADVTOK(1, DUK_TOK_LCURLY);
		break;
	case DUK_ASC_RCURLY:  /* '}' */
		advtok = DUK__ADVTOK(1, DUK_TOK_RCURLY);
		break;
	case DUK_ASC_LPAREN:  /* '(' */
		advtok = DUK__ADVTOK(1, DUK_TOK_LPAREN);
		break;
	case DUK_ASC_RPAREN:  /* ')' */
		advtok = DUK__ADVTOK(1, DUK_TOK_RPAREN);
		break;
	case DUK_ASC_LBRACKET:  /* '[' */
		advtok = DUK__ADVTOK(1, DUK_TOK_LBRACKET);
		break;
	case DUK_ASC_RBRACKET:  /* ']' */
		advtok = DUK__ADVTOK(1, DUK_TOK_RBRACKET);
		break;
	case DUK_ASC_PERIOD:  /* '.' */
		if (DUK__ISDIGIT(DUK__L1())) {
			/* Period followed by a digit can only start DecimalLiteral
			 * (handled in slow path).  We could jump straight into the
			 * DecimalLiteral handling but should avoid goto to inside
			 * a block.
			 */
			goto slow_path;
		}
		advtok = DUK__ADVTOK(1, DUK_TOK_PERIOD);
		break;
	case DUK_ASC_SEMICOLON:  /* ';' */
		advtok = DUK__ADVTOK(1, DUK_TOK_SEMICOLON);
		break;
	case DUK_ASC_COMMA:  /* ',' */
		advtok = DUK__ADVTOK(1, DUK_TOK_COMMA);
		break;
	case DUK_ASC_LANGLE:  /* '<' */
#if defined(DUK_USE_HTML_COMMENTS)
		if (DUK__L1() == DUK_ASC_EXCLAMATION && DUK__L2() == DUK_ASC_MINUS && DUK__L3() == DUK_ASC_MINUS) {
			/*
			 *  ES2015: B.1.3, handle "<!--" SingleLineHTMLOpenComment
			 */

			/* DUK__ADVANCECHARS(lex_ctx, 4) would be correct here, but not necessary */
			duk__lexer_skip_to_endofline(lex_ctx);
			goto restart;  /* line terminator will be handled on next round */
		}
		else
#endif  /* DUK_USE_HTML_COMMENTS */
		if (DUK__L1() == DUK_ASC_LANGLE && DUK__L2() == DUK_ASC_EQUALS) {
			advtok = DUK__ADVTOK(3, DUK_TOK_ALSHIFT_EQ);
		} else if (DUK__L1() == DUK_ASC_EQUALS) {
			advtok = DUK__ADVTOK(2, DUK_TOK_LE);
		} else if (DUK__L1() == DUK_ASC_LANGLE) {
			advtok = DUK__ADVTOK(2, DUK_TOK_ALSHIFT);
		} else {
			advtok = DUK__ADVTOK(1, DUK_TOK_LT);
		}
		break;
	case DUK_ASC_RANGLE:  /* '>' */
		if (DUK__L1() == DUK_ASC_RANGLE && DUK__L2() == DUK_ASC_RANGLE && DUK__L3() == DUK_ASC_EQUALS) {
			advtok = DUK__ADVTOK(4, DUK_TOK_RSHIFT_EQ);
		} else if (DUK__L1() == DUK_ASC_RANGLE && DUK__L2() == DUK_ASC_RANGLE) {
			advtok = DUK__ADVTOK(3, DUK_TOK_RSHIFT);
		} else if (DUK__L1() == DUK_ASC_RANGLE && DUK__L2() == DUK_ASC_EQUALS) {
			advtok = DUK__ADVTOK(3, DUK_TOK_ARSHIFT_EQ);
		} else if (DUK__L1() == DUK_ASC_EQUALS) {
			advtok = DUK__ADVTOK(2, DUK_TOK_GE);
		} else if (DUK__L1() == DUK_ASC_RANGLE) {
			advtok = DUK__ADVTOK(2, DUK_TOK_ARSHIFT);
		} else {
			advtok = DUK__ADVTOK(1, DUK_TOK_GT);
		}
		break;
	case DUK_ASC_EQUALS:  /* '=' */
		if (DUK__L1() == DUK_ASC_EQUALS && DUK__L2() == DUK_ASC_EQUALS) {
			advtok = DUK__ADVTOK(3, DUK_TOK_SEQ);
		} else if (DUK__L1() == DUK_ASC_EQUALS) {
			advtok = DUK__ADVTOK(2, DUK_TOK_EQ);
		} else {
			advtok = DUK__ADVTOK(1, DUK_TOK_EQUALSIGN);
		}
		break;
	case DUK_ASC_EXCLAMATION:  /* '!' */
		if (DUK__L1() == DUK_ASC_EQUALS && DUK__L2() == DUK_ASC_EQUALS) {
			advtok = DUK__ADVTOK(3, DUK_TOK_SNEQ);
		} else if (DUK__L1() == DUK_ASC_EQUALS) {
			advtok = DUK__ADVTOK(2, DUK_TOK_NEQ);
		} else {
			advtok = DUK__ADVTOK(1, DUK_TOK_LNOT);
		}
		break;
	case DUK_ASC_PLUS:  /* '+' */
		if (DUK__L1() == DUK_ASC_PLUS) {
			advtok = DUK__ADVTOK(2, DUK_TOK_INCREMENT);
		} else if (DUK__L1() == DUK_ASC_EQUALS) {
			advtok = DUK__ADVTOK(2, DUK_TOK_ADD_EQ);
		} else {
			advtok = DUK__ADVTOK(1, DUK_TOK_ADD);
		}
		break;
	case DUK_ASC_MINUS:  /* '-' */
#if defined(DUK_USE_HTML_COMMENTS)
		if (got_lineterm && DUK__L1() == DUK_ASC_MINUS && DUK__L2() == DUK_ASC_RANGLE) {
			/*
			 *  ES2015: B.1.3, handle "-->" SingleLineHTMLCloseComment
			 *  Only allowed:
			 *  - on new line
			 *  - preceded only by whitespace
			 *  - preceded by end of multiline comment and optional whitespace
			 *
			 * Since whitespace generates no tokens, and multiline comments
			 * are treated as a line ending, consulting `got_lineterm` is
			 * sufficient to test for these three options.
			 */

			/* DUK__ADVANCECHARS(lex_ctx, 3) would be correct here, but not necessary */
			duk__lexer_skip_to_endofline(lex_ctx);
			goto restart;  /* line terminator will be handled on next round */
		} else
#endif  /* DUK_USE_HTML_COMMENTS */
		if (DUK__L1() == DUK_ASC_MINUS) {
			advtok = DUK__ADVTOK(2, DUK_TOK_DECREMENT);
		} else if (DUK__L1() == DUK_ASC_EQUALS) {
			advtok = DUK__ADVTOK(2, DUK_TOK_SUB_EQ);
		} else {
			advtok = DUK__ADVTOK(1, DUK_TOK_SUB);
		}
		break;
	case DUK_ASC_STAR:  /* '*' */
#if defined(DUK_USE_ES7_EXP_OPERATOR)
		if (DUK__L1() == DUK_ASC_STAR && DUK__L2() == DUK_ASC_EQUALS) {
			advtok = DUK__ADVTOK(3, DUK_TOK_EXP_EQ);
		} else if (DUK__L1() == DUK_ASC_STAR) {
			advtok = DUK__ADVTOK(2, DUK_TOK_EXP);
		} else
#endif
		if (DUK__L1() == DUK_ASC_EQUALS) {
			advtok = DUK__ADVTOK(2, DUK_TOK_MUL_EQ);
		} else {
			advtok = DUK__ADVTOK(1, DUK_TOK_MUL);
		}
		break;
	case DUK_ASC_PERCENT:  /* '%' */
		if (DUK__L1() == DUK_ASC_EQUALS) {
			advtok = DUK__ADVTOK(2, DUK_TOK_MOD_EQ);
		} else {
			advtok = DUK__ADVTOK(1, DUK_TOK_MOD);
		}
		break;
	case DUK_ASC_AMP:  /* '&' */
		if (DUK__L1() == DUK_ASC_AMP) {
			advtok = DUK__ADVTOK(2, DUK_TOK_LAND);
		} else if (DUK__L1() == DUK_ASC_EQUALS) {
			advtok = DUK__ADVTOK(2, DUK_TOK_BAND_EQ);
		} else {
			advtok = DUK__ADVTOK(1, DUK_TOK_BAND);
		}
		break;
	case DUK_ASC_PIPE:  /* '|' */
		if (DUK__L1() == DUK_ASC_PIPE) {
			advtok = DUK__ADVTOK(2, DUK_TOK_LOR);
		} else if (DUK__L1() == DUK_ASC_EQUALS) {
			advtok = DUK__ADVTOK(2, DUK_TOK_BOR_EQ);
		} else {
			advtok = DUK__ADVTOK(1, DUK_TOK_BOR);
		}
		break;
	case DUK_ASC_CARET:  /* '^' */
		if (DUK__L1() == DUK_ASC_EQUALS) {
			advtok = DUK__ADVTOK(2, DUK_TOK_BXOR_EQ);
		} else {
			advtok = DUK__ADVTOK(1, DUK_TOK_BXOR);
		}
		break;
	case DUK_ASC_TILDE:  /* '~' */
		advtok = DUK__ADVTOK(1, DUK_TOK_BNOT);
		break;
	case DUK_ASC_QUESTION:  /* '?' */
		advtok = DUK__ADVTOK(1, DUK_TOK_QUESTION);
		break;
	case DUK_ASC_COLON:  /* ':' */
		advtok = DUK__ADVTOK(1, DUK_TOK_COLON);
		break;
	case DUK_ASC_DOUBLEQUOTE:    /* '"' */
	case DUK_ASC_SINGLEQUOTE: {  /* '\'' */
		DUK__INITBUFFER(lex_ctx);
		duk__lexer_parse_string_literal(lex_ctx, out_token, x /*quote*/, strict_mode);
		duk__internbuffer(lex_ctx, lex_ctx->slot1_idx);
		out_token->str1 = duk_known_hstring(lex_ctx->thr, lex_ctx->slot1_idx);

		DUK__INITBUFFER(lex_ctx);  /* free some memory */

		advtok = DUK__ADVTOK(0, DUK_TOK_STRING);
		break;
	}
	default:
		goto slow_path;
	}  /* switch */

	goto skip_slow_path;

 slow_path:
	if (duk_unicode_is_line_terminator(x)) {
		if (x == 0x000d && DUK__L1() == 0x000a) {
			/*
			 *  E5 Section 7.3: CR LF is detected as a single line terminator for
			 *  line numbers.  Here we also detect it as a single line terminator
			 *  token.
			 */
			DUK__ADVANCECHARS(lex_ctx, 2);
		} else {
			DUK__ADVANCECHARS(lex_ctx, 1);
		}
		got_lineterm = 1;
		goto restart_lineupdate;
	} else if (duk_unicode_is_identifier_start(x) || x == DUK_ASC_BACKSLASH) {
		/*
		 *  Parse an identifier and then check whether it is:
		 *    - reserved word (keyword or other reserved word)
		 *    - "null"  (NullLiteral)
		 *    - "true"  (BooleanLiteral)
		 *    - "false" (BooleanLiteral)
		 *    - anything else => identifier
		 *
		 *  This does not follow the E5 productions cleanly, but is
		 *  useful and compact.
		 *
		 *  Note that identifiers may contain Unicode escapes,
		 *  see E5 Sections 6 and 7.6.  They must be decoded first,
		 *  and the result checked against allowed characters.
		 *  The above if-clause accepts an identifier start and an
		 *  '\' character -- no other token can begin with a '\'.
		 *
		 *  Note that "get" and "set" are not reserved words in E5
		 *  specification so they are recognized as plain identifiers
		 *  (the tokens DUK_TOK_GET and DUK_TOK_SET are actually not
		 *  used now).  The compiler needs to work around this.
		 *
		 *  Strictly speaking, following ECMAScript longest match
		 *  specification, an invalid escape for the first character
		 *  should cause a syntax error.  However, an invalid escape
		 *  for IdentifierParts should just terminate the identifier
		 *  early (longest match), and let the next tokenization
		 *  fail.  For instance Rhino croaks with 'foo\z' when
		 *  parsing the identifier.  This has little practical impact.
		 */

		duk_small_uint_t i, i_end;
		duk_bool_t first = 1;
		duk_hstring *str;

		DUK__INITBUFFER(lex_ctx);
		for (;;) {
			/* re-lookup first char on first loop */
			if (DUK__L0() == DUK_ASC_BACKSLASH) {
				duk_codepoint_t esc_cp;
				if (DUK__L1() != DUK_ASC_LC_U) {
					goto fail_escape;
				}
				esc_cp = duk__lexer_parse_escape(lex_ctx, 1 /*allow_es6*/);
				DUK__APPENDBUFFER(lex_ctx, esc_cp);

				/* IdentifierStart is stricter than IdentifierPart, so if the first
				 * character is escaped, must have a stricter check here.
				 */
				if (!(first ? duk_unicode_is_identifier_start(esc_cp) : duk_unicode_is_identifier_part(esc_cp))) {
					goto fail_escape;
				}

				/* Track number of escapes: necessary for proper keyword
				 * detection.
				 */
				out_token->num_escapes++;
			} else {
				/* Note: first character is checked against this.  But because
				 * IdentifierPart includes all IdentifierStart characters, and
				 * the first character (if unescaped) has already been checked
				 * in the if condition, this is OK.
				 */
				if (!duk_unicode_is_identifier_part(DUK__L0())) {
					break;
				}
				DUK__APPENDBUFFER(lex_ctx, DUK__L0());
				DUK__ADVANCECHARS(lex_ctx, 1);
			}
			first = 0;
		}

		out_token->str1 = duk__internbuffer(lex_ctx, lex_ctx->slot1_idx);
		str = out_token->str1;
		out_token->t_nores = DUK_TOK_IDENTIFIER;

		DUK__INITBUFFER(lex_ctx);  /* free some memory */

		/*
		 *  Interned identifier is compared against reserved words, which are
		 *  currently interned into the heap context.  See genbuiltins.py.
		 *
		 *  Note that an escape in the identifier disables recognition of
		 *  keywords; e.g. "\u0069f = 1;" is a valid statement (assigns to
		 *  identifier named "if").  This is not necessarily compliant,
		 *  see test-dec-escaped-char-in-keyword.js.
		 *
		 *  Note: "get" and "set" are awkward.  They are not officially
		 *  ReservedWords (and indeed e.g. "var set = 1;" is valid), and
		 *  must come out as DUK_TOK_IDENTIFIER.  The compiler needs to
		 *  work around this a bit.
		 */

		/* XXX: optimize by adding the token numbers directly into the
		 * always interned duk_hstring objects (there should be enough
		 * flag bits free for that)?
		 */

		i_end = (strict_mode ? DUK_STRIDX_END_RESERVED : DUK_STRIDX_START_STRICT_RESERVED);

		advtok = DUK__ADVTOK(0, DUK_TOK_IDENTIFIER);
		if (out_token->num_escapes == 0) {
			for (i = DUK_STRIDX_START_RESERVED; i < i_end; i++) {
				DUK_ASSERT_DISABLE(i >= 0);  /* unsigned */
				DUK_ASSERT(i < DUK_HEAP_NUM_STRINGS);
				if (DUK_HTHREAD_GET_STRING(lex_ctx->thr, i) == str) {
					advtok = DUK__ADVTOK(0, DUK_STRIDX_TO_TOK(i));
					break;
				}
			}
		}
	} else if (DUK__ISDIGIT(x) || (x == DUK_ASC_PERIOD)) {
		/* Note: decimal number may start with a period, but must be followed by a digit */

		/*
		 *  Pre-parsing for decimal, hex, octal (both legacy and ES2015),
		 *  and binary literals, followed by an actual parser step
		 *  provided by numconv.
		 *
		 *  Note: the leading sign character ('+' or '-') is -not- part of
		 *  the production in E5 grammar, and that the a DecimalLiteral
		 *  starting with a '0' must be followed by a non-digit.
		 *
		 *  XXX: the two step parsing process is quite awkward, it would
		 *  be more straightforward to allow numconv to parse the longest
		 *  valid prefix (it already does that, it only needs to indicate
		 *  where the input ended).  However, the lexer decodes characters
		 *  using a limited lookup window, so this is not a trivial change.
		 */

		/* XXX: because of the final check below (that the literal is not
		 * followed by a digit), this could maybe be simplified, if we bail
		 * out early from a leading zero (and if there are no periods etc).
		 * Maybe too complex.
		 */

		duk_double_t val;
		duk_bool_t legacy_oct = 0;
		duk_small_int_t state;  /* 0=before period/exp,
		                         * 1=after period, before exp
		                         * 2=after exp, allow '+' or '-'
		                         * 3=after exp and exp sign
		                         */
		duk_small_uint_t s2n_flags;
		duk_codepoint_t y, z;
		duk_small_int_t s2n_radix = 10;
		duk_small_uint_t pre_adv = 0;

		DUK__INITBUFFER(lex_ctx);
		y = DUK__L1();

		if (x == DUK_ASC_0) {
			z = DUK_LOWERCASE_CHAR_ASCII(y);

			pre_adv = 2;  /* default for 0xNNN, 0oNNN, 0bNNN. */
			if (z == DUK_ASC_LC_X) {
				s2n_radix = 16;
			} else if (z == DUK_ASC_LC_O) {
				s2n_radix = 8;
			} else if (z == DUK_ASC_LC_B) {
				s2n_radix = 2;
			} else {
				pre_adv = 0;
				if (DUK__ISDIGIT(y)) {
					if (strict_mode) {
						/* Reject octal like \07 but also octal-lookalike
						 * decimal like \08 in strict mode.
						 */
						goto fail_number_literal;
					} else {
						/* Legacy OctalIntegerLiteral or octal-lookalice
						 * decimal.  Deciding between the two happens below
						 * in digit scanning.
						 */
						DUK__APPENDBUFFER(lex_ctx, x);
						pre_adv = 1;
						legacy_oct = 1;
						s2n_radix = 8;  /* tentative unless conflicting digits found */
					}
				}
			}
		}

		DUK__ADVANCECHARS(lex_ctx, pre_adv);

		/* XXX: we could parse integers here directly, and fall back
		 * to numconv only when encountering a fractional expression
		 * or when an octal literal turned out to be decimal (0778 etc).
		 */
		state = 0;
		for (;;) {
			x = DUK__L0();  /* re-lookup curr char on first round */
			if (DUK__ISDIGIT(x)) {
				/* Note: intentionally allow leading zeroes here, as the
				 * actual parser will check for them.
				 */
				if (state == 0 && legacy_oct && (x == DUK_ASC_8 || x == DUK_ASC_9)) {
					/* Started out as an octal-lookalike
					 * but interpreted as decimal, e.g.
					 * '0779' -> 779.  This also means
					 * that fractions are allowed, e.g.
					 * '0779.123' is allowed but '0777.123'
					 * is not!
					 */
					s2n_radix = 10;
				}
				if (state == 2) {
					state = 3;
				}
			} else if (s2n_radix == 16 && DUK__ISHEXDIGIT(x)) {
				/* Note: 'e' and 'E' are also accepted here. */
				;
			} else if (x == DUK_ASC_PERIOD) {
				if (state >= 1 || s2n_radix != 10) {
					break;
				} else {
					state = 1;
				}
			} else if (x == DUK_ASC_LC_E || x == DUK_ASC_UC_E) {
				if (state >= 2 || s2n_radix != 10) {
					break;
				} else {
					state = 2;
				}
			} else if (x == DUK_ASC_MINUS || x == DUK_ASC_PLUS) {
				if (state != 2) {
					break;
				} else {
					state = 3;
				}
			} else {
				break;
			}
			DUK__APPENDBUFFER(lex_ctx, x);
			DUK__ADVANCECHARS(lex_ctx, 1);
		}

		/* XXX: better coercion */
		(void) duk__internbuffer(lex_ctx, lex_ctx->slot1_idx);

		if (s2n_radix != 10) {
			/* For bases other than 10, integer only. */
			s2n_flags = DUK_S2N_FLAG_ALLOW_LEADING_ZERO;
		} else {
			s2n_flags = DUK_S2N_FLAG_ALLOW_EXP |
			            DUK_S2N_FLAG_ALLOW_FRAC |
			            DUK_S2N_FLAG_ALLOW_NAKED_FRAC |
			            DUK_S2N_FLAG_ALLOW_EMPTY_FRAC |
			            DUK_S2N_FLAG_ALLOW_LEADING_ZERO;
		}

		duk_dup(lex_ctx->thr, lex_ctx->slot1_idx);
		duk_numconv_parse(lex_ctx->thr, s2n_radix, s2n_flags);
		val = duk_to_number_m1(lex_ctx->thr);
		if (DUK_ISNAN(val)) {
			goto fail_number_literal;
		}
		duk_replace(lex_ctx->thr, lex_ctx->slot1_idx);  /* could also just pop? */

		DUK__INITBUFFER(lex_ctx);  /* free some memory */

		/* Section 7.8.3 (note): NumericLiteral must be followed by something other than
		 * IdentifierStart or DecimalDigit.
		 */

		if (DUK__ISDIGIT(DUK__L0()) || duk_unicode_is_identifier_start(DUK__L0())) {
			goto fail_number_literal;
		}

		out_token->num = val;
		advtok = DUK__ADVTOK(0, DUK_TOK_NUMBER);
	} else if (duk_unicode_is_whitespace(DUK__LOOKUP(lex_ctx, 0))) {
		DUK__ADVANCECHARS(lex_ctx, 1);
		goto restart;
	} else if (x < 0) {
		advtok = DUK__ADVTOK(0, DUK_TOK_EOF);
	} else {
		goto fail_token;
	}
 skip_slow_path:

	/*
	 *  Shared exit path
	 */

	DUK__ADVANCEBYTES(lex_ctx, advtok >> 8);
	out_token->t = advtok & 0xff;
	if (out_token->t_nores == DUK_TOK_INVALID) {
		out_token->t_nores = out_token->t;
	}
	out_token->lineterm = got_lineterm;

	/* Automatic semicolon insertion is allowed if a token is preceded
	 * by line terminator(s), or terminates a statement list (right curly
	 * or EOF).
	 */
	if (got_lineterm || out_token->t == DUK_TOK_RCURLY || out_token->t == DUK_TOK_EOF) {
		out_token->allow_auto_semi = 1;
	} else {
		out_token->allow_auto_semi = 0;
	}

	return;

 fail_token_limit:
	DUK_ERROR_RANGE(lex_ctx->thr, DUK_STR_TOKEN_LIMIT);
	DUK_WO_NORETURN(return;);

 fail_token:
	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_TOKEN);
	DUK_WO_NORETURN(return;);

 fail_number_literal:
	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_NUMBER_LITERAL);
	DUK_WO_NORETURN(return;);

 fail_escape:
	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_ESCAPE);
	DUK_WO_NORETURN(return;);

 fail_unterm_regexp:
	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_UNTERMINATED_REGEXP);
	DUK_WO_NORETURN(return;);

 fail_unterm_comment:
	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_UNTERMINATED_COMMENT);
	DUK_WO_NORETURN(return;);

#if !defined(DUK_USE_REGEXP_SUPPORT)
 fail_regexp_support:
	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_REGEXP_SUPPORT_DISABLED);
	DUK_WO_NORETURN(return;);
#endif
}

#if defined(DUK_USE_REGEXP_SUPPORT)

/*
 *  Parse a RegExp token.  The grammar is described in E5 Section 15.10.
 *  Terminal constructions (such as quantifiers) are parsed directly here.
 *
 *  0xffffffffU is used as a marker for "infinity" in quantifiers.  Further,
 *  DUK__MAX_RE_QUANT_DIGITS limits the maximum number of digits that
 *  will be accepted for a quantifier.
 */

DUK_INTERNAL void duk_lexer_parse_re_token(duk_lexer_ctx *lex_ctx, duk_re_token *out_token) {
	duk_small_uint_t advtok = 0;  /* init is unnecessary but suppresses "may be used uninitialized" warnings */
	duk_codepoint_t x, y;

	if (++lex_ctx->token_count >= lex_ctx->token_limit) {
		goto fail_token_limit;
	}

	duk_memzero(out_token, sizeof(*out_token));

	x = DUK__L0();
	y = DUK__L1();

	DUK_DDD(DUK_DDDPRINT("parsing regexp token, L0=%ld, L1=%ld", (long) x, (long) y));

	switch (x) {
	case DUK_ASC_PIPE: {
		advtok = DUK__ADVTOK(1, DUK_RETOK_DISJUNCTION);
		break;
	}
	case DUK_ASC_CARET: {
		advtok = DUK__ADVTOK(1, DUK_RETOK_ASSERT_START);
		break;
	}
	case DUK_ASC_DOLLAR: {
		advtok = DUK__ADVTOK(1, DUK_RETOK_ASSERT_END);
		break;
	}
	case DUK_ASC_QUESTION: {
		out_token->qmin = 0;
		out_token->qmax = 1;
		if (y == DUK_ASC_QUESTION) {
			advtok = DUK__ADVTOK(2, DUK_RETOK_QUANTIFIER);
			out_token->greedy = 0;
		} else {
			advtok = DUK__ADVTOK(1, DUK_RETOK_QUANTIFIER);
			out_token->greedy = 1;
		}
		break;
	}
	case DUK_ASC_STAR: {
		out_token->qmin = 0;
		out_token->qmax = DUK_RE_QUANTIFIER_INFINITE;
		if (y == DUK_ASC_QUESTION) {
			advtok = DUK__ADVTOK(2, DUK_RETOK_QUANTIFIER);
			out_token->greedy = 0;
		} else {
			advtok = DUK__ADVTOK(1, DUK_RETOK_QUANTIFIER);
			out_token->greedy = 1;
		}
		break;
	}
	case DUK_ASC_PLUS: {
		out_token->qmin = 1;
		out_token->qmax = DUK_RE_QUANTIFIER_INFINITE;
		if (y == DUK_ASC_QUESTION) {
			advtok = DUK__ADVTOK(2, DUK_RETOK_QUANTIFIER);
			out_token->greedy = 0;
		} else {
			advtok = DUK__ADVTOK(1, DUK_RETOK_QUANTIFIER);
			out_token->greedy = 1;
		}
		break;
	}
	case DUK_ASC_LCURLY: {
		/* Production allows 'DecimalDigits', including leading zeroes */
		duk_uint32_t val1 = 0;
		duk_uint32_t val2 = DUK_RE_QUANTIFIER_INFINITE;
		duk_small_int_t digits = 0;
#if defined(DUK_USE_ES6_REGEXP_SYNTAX)
		duk_lexer_point lex_pt;
#endif

#if defined(DUK_USE_ES6_REGEXP_SYNTAX)
		/* Store lexer position, restoring if quantifier is invalid. */
		DUK_LEXER_GETPOINT(lex_ctx, &lex_pt);
#endif

		for (;;) {
			DUK__ADVANCECHARS(lex_ctx, 1);  /* eat '{' on entry */
			x = DUK__L0();
			if (DUK__ISDIGIT(x)) {
				digits++;
				val1 = val1 * 10 + (duk_uint32_t) duk__hexval(x);
			} else if (x == DUK_ASC_COMMA) {
				if (digits > DUK__MAX_RE_QUANT_DIGITS) {
					goto invalid_quantifier;
				}
				if (val2 != DUK_RE_QUANTIFIER_INFINITE) {
					goto invalid_quantifier;
				}
				if (DUK__L1() == DUK_ASC_RCURLY) {
					/* form: { DecimalDigits , }, val1 = min count */
					if (digits == 0) {
						goto invalid_quantifier;
					}
					out_token->qmin = val1;
					out_token->qmax = DUK_RE_QUANTIFIER_INFINITE;
					DUK__ADVANCECHARS(lex_ctx, 2);
					break;
				}
				val2 = val1;
				val1 = 0;
				digits = 0;  /* not strictly necessary because of lookahead '}' above */
			} else if (x == DUK_ASC_RCURLY) {
				if (digits > DUK__MAX_RE_QUANT_DIGITS) {
					goto invalid_quantifier;
				}
				if (digits == 0) {
					goto invalid_quantifier;
				}
				if (val2 != DUK_RE_QUANTIFIER_INFINITE) {
					/* val2 = min count, val1 = max count */
					out_token->qmin = val2;
					out_token->qmax = val1;
				} else {
					/* val1 = count */
					out_token->qmin = val1;
					out_token->qmax = val1;
				}
				DUK__ADVANCECHARS(lex_ctx, 1);
				break;
			} else {
				goto invalid_quantifier;
			}
		}
		if (DUK__L0() == DUK_ASC_QUESTION) {
			out_token->greedy = 0;
			DUK__ADVANCECHARS(lex_ctx, 1);
		} else {
			out_token->greedy = 1;
		}
		advtok = DUK__ADVTOK(0, DUK_RETOK_QUANTIFIER);
		break;
 invalid_quantifier:
#if defined(DUK_USE_ES6_REGEXP_SYNTAX)
		/* Failed to match the quantifier, restore lexer and parse
		 * opening brace as a literal.
		 */
		DUK_LEXER_SETPOINT(lex_ctx, &lex_pt);
		advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_CHAR);
		out_token->num = DUK_ASC_LCURLY;
#else
		goto fail_quantifier;
#endif
		break;
	}
	case DUK_ASC_PERIOD: {
		advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_PERIOD);
		break;
	}
	case DUK_ASC_BACKSLASH: {
		/* The E5.1 specification does not seem to allow IdentifierPart characters
		 * to be used as identity escapes.  Unfortunately this includes '$', which
		 * cannot be escaped as '\$'; it needs to be escaped e.g. as '\u0024'.
		 * Many other implementations (including V8 and Rhino, for instance) do
		 * accept '\$' as a valid identity escape, which is quite pragmatic, and
		 * ES2015 Annex B relaxes the rules to allow these (and other) real world forms.
		 */

		advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_CHAR);  /* default: char escape (two chars) */
		if (y == DUK_ASC_LC_B) {
			advtok = DUK__ADVTOK(2, DUK_RETOK_ASSERT_WORD_BOUNDARY);
		} else if (y == DUK_ASC_UC_B) {
			advtok = DUK__ADVTOK(2, DUK_RETOK_ASSERT_NOT_WORD_BOUNDARY);
		} else if (y == DUK_ASC_LC_F) {
			out_token->num = 0x000c;
		} else if (y == DUK_ASC_LC_N) {
			out_token->num = 0x000a;
		} else if (y == DUK_ASC_LC_T) {
			out_token->num = 0x0009;
		} else if (y == DUK_ASC_LC_R) {
			out_token->num = 0x000d;
		} else if (y == DUK_ASC_LC_V) {
			out_token->num = 0x000b;
		} else if (y == DUK_ASC_LC_C) {
			x = DUK__L2();
			if ((x >= DUK_ASC_LC_A && x <= DUK_ASC_LC_Z) ||
			    (x >= DUK_ASC_UC_A && x <= DUK_ASC_UC_Z)) {
				out_token->num = (duk_uint32_t) (x % 32);
				advtok = DUK__ADVTOK(3, DUK_RETOK_ATOM_CHAR);
			} else {
				goto fail_escape;
			}
		} else if (y == DUK_ASC_LC_X || y == DUK_ASC_LC_U) {
			/* The token value is the Unicode codepoint without
			 * it being decode into surrogate pair characters
			 * here.  The \u{H+} is only allowed in Unicode mode
			 * which we don't support yet.
			 */
			out_token->num = (duk_uint32_t) duk__lexer_parse_escape(lex_ctx, 0 /*allow_es6*/);
			advtok = DUK__ADVTOK(0, DUK_RETOK_ATOM_CHAR);
		} else if (y == DUK_ASC_LC_D) {
			advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_DIGIT);
		} else if (y == DUK_ASC_UC_D) {
			advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_NOT_DIGIT);
		} else if (y == DUK_ASC_LC_S) {
			advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_WHITE);
		} else if (y == DUK_ASC_UC_S) {
			advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_NOT_WHITE);
		} else if (y == DUK_ASC_LC_W) {
			advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_WORD_CHAR);
		} else if (y == DUK_ASC_UC_W) {
			advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_NOT_WORD_CHAR);
		} else if (DUK__ISDIGIT(y)) {
			/* E5 Section 15.10.2.11 */
			if (y == DUK_ASC_0) {
				if (DUK__ISDIGIT(DUK__L2())) {
					goto fail_escape;
				}
				out_token->num = 0x0000;
				advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_CHAR);
			} else {
				/* XXX: shared parsing? */
				duk_uint32_t val = 0;
				duk_small_int_t i;
				for (i = 0; ; i++) {
					if (i >= DUK__MAX_RE_DECESC_DIGITS) {
						goto fail_escape;
					}
					DUK__ADVANCECHARS(lex_ctx, 1);  /* eat backslash on entry */
					x = DUK__L0();
					if (!DUK__ISDIGIT(x)) {
						break;
					}
					val = val * 10 + (duk_uint32_t) duk__hexval(x);
				}
				/* DUK__L0() cannot be a digit, because the loop doesn't terminate if it is */
				advtok = DUK__ADVTOK(0, DUK_RETOK_ATOM_BACKREFERENCE);
				out_token->num = val;
			}
#if defined(DUK_USE_ES6_REGEXP_SYNTAX)
		} else if (y >= 0) {
			/* For ES2015 Annex B, accept any source character as identity
			 * escape except 'c' which is used for control characters.
			 * http://www.ecma-international.org/ecma-262/6.0/#sec-regular-expressions-patterns
			 * Careful not to match end-of-buffer (<0) here.
			 * This is not yet full ES2015 Annex B because cases above
			 * (like hex escape) won't backtrack.
			 */
			DUK_ASSERT(y != DUK_ASC_LC_C);  /* covered above */
#else  /* DUK_USE_ES6_REGEXP_SYNTAX */
		} else if ((y >= 0 && !duk_unicode_is_identifier_part(y)) ||
		           y == DUK_UNICODE_CP_ZWNJ ||
		           y == DUK_UNICODE_CP_ZWJ) {
			/* For ES5.1 identity escapes are not allowed for identifier
			 * parts.  This conflicts with a lot of real world code as this
			 * doesn't e.g. allow escaping a dollar sign as /\$/, see
			 * test-regexp-identity-escape-dollar.js.
			 */
#endif  /* DUK_USE_ES6_REGEXP_SYNTAX */
			out_token->num = (duk_uint32_t) y;
		} else {
			goto fail_escape;
		}
		break;
	}
	case DUK_ASC_LPAREN: {
		/* XXX: naming is inconsistent: ATOM_END_GROUP ends an ASSERT_START_LOOKAHEAD */

		if (y == DUK_ASC_QUESTION) {
			if (DUK__L2() == DUK_ASC_EQUALS) {
				/* (?= */
				advtok = DUK__ADVTOK(3, DUK_RETOK_ASSERT_START_POS_LOOKAHEAD);
			} else if (DUK__L2() == DUK_ASC_EXCLAMATION) {
				/* (?! */
				advtok = DUK__ADVTOK(3, DUK_RETOK_ASSERT_START_NEG_LOOKAHEAD);
			} else if (DUK__L2() == DUK_ASC_COLON) {
				/* (?: */
				advtok = DUK__ADVTOK(3, DUK_RETOK_ATOM_START_NONCAPTURE_GROUP);
			} else {
				goto fail_group;
			}
		} else {
			/* ( */
			advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_START_CAPTURE_GROUP);
		}
		break;
	}
	case DUK_ASC_RPAREN: {
		advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_END_GROUP);
		break;
	}
	case DUK_ASC_LBRACKET: {
		/*
		 *  To avoid creating a heavy intermediate value for the list of ranges,
		 *  only the start token ('[' or '[^') is parsed here.  The regexp
		 *  compiler parses the ranges itself.
		 */

		/* XXX: with DUK_USE_ES6_REGEXP_SYNTAX we should allow left bracket
		 * literal too, but it's not easy to parse without backtracking.
		 */

		advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_START_CHARCLASS);
		if (y == DUK_ASC_CARET) {
			advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_START_CHARCLASS_INVERTED);
		}
		break;
	}
#if !defined(DUK_USE_ES6_REGEXP_SYNTAX)
	case DUK_ASC_RCURLY:
	case DUK_ASC_RBRACKET: {
		/* Although these could be parsed as PatternCharacters unambiguously (here),
		 * E5 Section 15.10.1 grammar explicitly forbids these as PatternCharacters.
		 */
		goto fail_invalid_char;
		break;
	}
#endif
	case -1: {
		/* EOF */
		advtok = DUK__ADVTOK(0, DUK_TOK_EOF);
		break;
	}
	default: {
		/* PatternCharacter, all excluded characters are matched by cases above */
		advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_CHAR);
		out_token->num = (duk_uint32_t) x;
		break;
	}
	}

	/*
	 *  Shared exit path
	 */

	DUK__ADVANCEBYTES(lex_ctx, advtok >> 8);
	out_token->t = advtok & 0xff;
	return;

 fail_token_limit:
	DUK_ERROR_RANGE(lex_ctx->thr, DUK_STR_TOKEN_LIMIT);
	DUK_WO_NORETURN(return;);

 fail_escape:
	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_REGEXP_ESCAPE);
	DUK_WO_NORETURN(return;);

 fail_group:
	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_REGEXP_GROUP);
	DUK_WO_NORETURN(return;);

#if !defined(DUK_USE_ES6_REGEXP_SYNTAX)
 fail_invalid_char:
	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_REGEXP_CHARACTER);
	DUK_WO_NORETURN(return;);

 fail_quantifier:
	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_QUANTIFIER);
	DUK_WO_NORETURN(return;);
#endif
}

/*
 *  Special parser for character classes; calls callback for every
 *  range parsed and returns the number of ranges present.
 */

/* XXX: this duplicates functionality in duk_regexp.c where a similar loop is
 * required anyway.  We could use that BUT we need to update the regexp compiler
 * 'nranges' too.  Work this out a bit more cleanly to save space.
 */

/* XXX: the handling of character range detection is a bit convoluted.
 * Try to simplify and make smaller.
 */

/* XXX: logic for handling character ranges is now incorrect, it will accept
 * e.g. [\d-z] whereas it should croak from it?  SMJS accepts this too, though.
 *
 * Needs a read through and a lot of additional tests.
 */

DUK_LOCAL
void duk__emit_u16_direct_ranges(duk_lexer_ctx *lex_ctx,
                                 duk_re_range_callback gen_range,
                                 void *userdata,
                                 const duk_uint16_t *ranges,
                                 duk_small_int_t num) {
	const duk_uint16_t *ranges_end;

	DUK_UNREF(lex_ctx);

	ranges_end = ranges + num;
	while (ranges < ranges_end) {
		/* mark range 'direct', bypass canonicalization (see Wiki) */
		gen_range(userdata, (duk_codepoint_t) ranges[0], (duk_codepoint_t) ranges[1], 1);
		ranges += 2;
	}
}

DUK_INTERNAL void duk_lexer_parse_re_ranges(duk_lexer_ctx *lex_ctx, duk_re_range_callback gen_range, void *userdata) {
	duk_codepoint_t start = -1;
	duk_codepoint_t ch;
	duk_codepoint_t x;
	duk_bool_t dash = 0;
	duk_small_uint_t adv = 0;

	DUK_DD(DUK_DDPRINT("parsing regexp ranges"));

	for (;;) {
		DUK__ADVANCECHARS(lex_ctx, adv);
		adv = 1;

		x = DUK__L0();

		ch = -1;  /* not strictly necessary, but avoids "uninitialized variable" warnings */
		DUK_UNREF(ch);

		if (x < 0) {
			goto fail_unterm_charclass;
		} else if (x == DUK_ASC_RBRACKET) {
			if (start >= 0) {
				gen_range(userdata, start, start, 0);
			}
			DUK__ADVANCECHARS(lex_ctx, 1);  /* eat ']' before finishing */
			break;
		} else if (x == DUK_ASC_MINUS) {
			if (start >= 0 && !dash && DUK__L1() != DUK_ASC_RBRACKET) {
				/* '-' as a range indicator */
				dash = 1;
				continue;
			} else {
				/* '-' verbatim */
				ch = x;
			}
		} else if (x == DUK_ASC_BACKSLASH) {
			/*
			 *  The escapes are same as outside a character class, except that \b has a
			 *  different meaning, and \B and backreferences are prohibited (see E5
			 *  Section 15.10.2.19).  However, it's difficult to share code because we
			 *  handle e.g. "\n" very differently: here we generate a single character
			 *  range for it.
			 */

			/* XXX: ES2015 surrogate pair handling. */

			x = DUK__L1();

			adv = 2;

			if (x == DUK_ASC_LC_B) {
				/* Note: '\b' in char class is different than outside (assertion),
				 * '\B' is not allowed and is caught by the duk_unicode_is_identifier_part()
				 * check below.
				 */
				ch = 0x0008;
			} else if (x == DUK_ASC_LC_F) {
				ch = 0x000c;
			} else if (x == DUK_ASC_LC_N) {
				ch = 0x000a;
			} else if (x == DUK_ASC_LC_T) {
				ch = 0x0009;
			} else if (x == DUK_ASC_LC_R) {
				ch = 0x000d;
			} else if (x == DUK_ASC_LC_V) {
				ch = 0x000b;
			} else if (x == DUK_ASC_LC_C) {
				x = DUK__L2();
				adv = 3;
				if ((x >= DUK_ASC_LC_A && x <= DUK_ASC_LC_Z) ||
				    (x >= DUK_ASC_UC_A && x <= DUK_ASC_UC_Z)) {
					ch = (x % 32);
				} else {
					goto fail_escape;
				}
			} else if (x == DUK_ASC_LC_X || x == DUK_ASC_LC_U) {
				/* The \u{H+} form is only allowed in Unicode mode which
				 * we don't support yet.
				 */
				ch = duk__lexer_parse_escape(lex_ctx, 0 /*allow_es6*/);
				adv = 0;
			} else if (x == DUK_ASC_LC_D) {
				duk__emit_u16_direct_ranges(lex_ctx,
				                            gen_range,
				                            userdata,
				                            duk_unicode_re_ranges_digit,
				                            sizeof(duk_unicode_re_ranges_digit) / sizeof(duk_uint16_t));
				ch = -1;
			} else if (x == DUK_ASC_UC_D) {
				duk__emit_u16_direct_ranges(lex_ctx,
				                            gen_range,
				                            userdata,
				                            duk_unicode_re_ranges_not_digit,
				                            sizeof(duk_unicode_re_ranges_not_digit) / sizeof(duk_uint16_t));
				ch = -1;
			} else if (x == DUK_ASC_LC_S) {
				duk__emit_u16_direct_ranges(lex_ctx,
				                            gen_range,
				                            userdata,
				                            duk_unicode_re_ranges_white,
				                            sizeof(duk_unicode_re_ranges_white) / sizeof(duk_uint16_t));
				ch = -1;
			} else if (x == DUK_ASC_UC_S) {
				duk__emit_u16_direct_ranges(lex_ctx,
				                            gen_range,
				                            userdata,
				                            duk_unicode_re_ranges_not_white,
				                            sizeof(duk_unicode_re_ranges_not_white) / sizeof(duk_uint16_t));
				ch = -1;
			} else if (x == DUK_ASC_LC_W) {
				duk__emit_u16_direct_ranges(lex_ctx,
				                            gen_range,
				                            userdata,
				                            duk_unicode_re_ranges_wordchar,
				                            sizeof(duk_unicode_re_ranges_wordchar) / sizeof(duk_uint16_t));
				ch = -1;
			} else if (x == DUK_ASC_UC_W) {
				duk__emit_u16_direct_ranges(lex_ctx,
				                            gen_range,
				                            userdata,
				                            duk_unicode_re_ranges_not_wordchar,
				                            sizeof(duk_unicode_re_ranges_not_wordchar) / sizeof(duk_uint16_t));
				ch = -1;
			} else if (DUK__ISDIGIT(x)) {
				/* DecimalEscape, only \0 is allowed, no leading
				 * zeroes are allowed.
				 *
				 * ES2015 Annex B also allows (maximal match) legacy
				 * octal escapes up to \377 and \8 and \9 are
				 * accepted as literal '8' and '9', also in strict mode.
				 */

#if defined(DUK_USE_ES6_REGEXP_SYNTAX)
				ch = duk__lexer_parse_legacy_octal(lex_ctx, &adv, 0 /*reject_annex_b*/);
				DUK_ASSERT(ch >= 0);  /* no rejections */
#else
				if (x == DUK_ASC_0 && !DUK__ISDIGIT(DUK__L2())) {
					ch = 0x0000;
				} else {
					goto fail_escape;
				}
#endif
#if defined(DUK_USE_ES6_REGEXP_SYNTAX)
			} else if (x >= 0) {
				/* IdentityEscape: ES2015 Annex B allows almost all
				 * source characters here.  Match anything except
				 * EOF here.
				 */
				ch = x;
#else  /* DUK_USE_ES6_REGEXP_SYNTAX */
			} else if (!duk_unicode_is_identifier_part(x)) {
				/* IdentityEscape: ES5.1 doesn't allow identity escape
				 * for identifier part characters, which conflicts with
				 * some real world code.  For example, it doesn't allow
				 * /[\$]/ which is awkward.
				 */
				ch = x;
#endif  /* DUK_USE_ES6_REGEXP_SYNTAX */
			} else {
				goto fail_escape;
			}
		} else {
			/* character represents itself */
			ch = x;
		}

		/* ch is a literal character here or -1 if parsed entity was
		 * an escape such as "\s".
		 */

		if (ch < 0) {
			/* multi-character sets not allowed as part of ranges, see
			 * E5 Section 15.10.2.15, abstract operation CharacterRange.
			 */
			if (start >= 0) {
				if (dash) {
					goto fail_range;
				} else {
					gen_range(userdata, start, start, 0);
					start = -1;
					/* dash is already 0 */
				}
			}
		} else {
			if (start >= 0) {
				if (dash) {
					if (start > ch) {
						goto fail_range;
					}
					gen_range(userdata, start, ch, 0);
					start = -1;
					dash = 0;
				} else {
					gen_range(userdata, start, start, 0);
					start = ch;
					/* dash is already 0 */
				}
			} else {
				start = ch;
			}
		}
	}

	return;

 fail_escape:
	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_REGEXP_ESCAPE);
	DUK_WO_NORETURN(return;);

 fail_range:
	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_RANGE);
	DUK_WO_NORETURN(return;);

 fail_unterm_charclass:
	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_UNTERMINATED_CHARCLASS);
	DUK_WO_NORETURN(return;);
}

#endif  /* DUK_USE_REGEXP_SUPPORT */

/* automatic undefs */
#undef DUK__ADVANCEBYTES
#undef DUK__ADVANCECHARS
#undef DUK__ADVTOK
#undef DUK__APPENDBUFFER
#undef DUK__APPENDBUFFER_ASCII
#undef DUK__INITBUFFER
#undef DUK__ISDIGIT
#undef DUK__ISDIGIT03
#undef DUK__ISDIGIT47
#undef DUK__ISHEXDIGIT
#undef DUK__ISOCTDIGIT
#undef DUK__L0
#undef DUK__L1
#undef DUK__L2
#undef DUK__L3
#undef DUK__L4
#undef DUK__L5
#undef DUK__LOOKUP
#undef DUK__MAX_RE_DECESC_DIGITS
#undef DUK__MAX_RE_QUANT_DIGITS
#line 1 "duk_numconv.c"
/*
 *  Number-to-string and string-to-number conversions.
 *
 *  Slow path number-to-string and string-to-number conversion is based on
 *  a Dragon4 variant, with fast paths for small integers.  Big integer
 *  arithmetic is needed for guaranteeing that the conversion is correct
 *  and uses a minimum number of digits.  The big number arithmetic has a
 *  fixed maximum size and does not require dynamic allocations.
 *
 *  See: doc/number-conversion.rst.
 */

/* #include duk_internal.h -> already included */

#define DUK__IEEE_DOUBLE_EXP_BIAS  1023
#define DUK__IEEE_DOUBLE_EXP_MIN   (-1022)   /* biased exp == 0 -> denormal, exp -1022 */

#define DUK__DIGITCHAR(x)  duk_lc_digits[(x)]

/*
 *  Tables generated with util/gennumdigits.py.
 *
 *  duk__str2num_digits_for_radix indicates, for each radix, how many input
 *  digits should be considered significant for string-to-number conversion.
 *  The input is also padded to this many digits to give the Dragon4
 *  conversion enough (apparent) precision to work with.
 *
 *  duk__str2num_exp_limits indicates, for each radix, the radix-specific
 *  minimum/maximum exponent values (for a Dragon4 integer mantissa)
 *  below and above which the number is guaranteed to underflow to zero
 *  or overflow to Infinity.  This allows parsing to keep bigint values
 *  bounded.
 */

DUK_LOCAL const duk_uint8_t duk__str2num_digits_for_radix[] = {
	69, 44, 35, 30, 27, 25, 23, 22, 20, 20,    /* 2 to 11 */
	20, 19, 19, 18, 18, 17, 17, 17, 16, 16,    /* 12 to 21 */
	16, 16, 16, 15, 15, 15, 15, 15, 15, 14,    /* 22 to 31 */
	14, 14, 14, 14, 14                         /* 31 to 36 */
};

typedef struct {
	duk_int16_t upper;
	duk_int16_t lower;
} duk__exp_limits;

DUK_LOCAL const duk__exp_limits duk__str2num_exp_limits[] = {
	{ 957, -1147 }, { 605, -725 },  { 479, -575 },  { 414, -496 },
	{ 372, -446 },  { 342, -411 },  { 321, -384 },  { 304, -364 },
	{ 291, -346 },  { 279, -334 },  { 268, -323 },  { 260, -312 },
	{ 252, -304 },  { 247, -296 },  { 240, -289 },  { 236, -283 },
	{ 231, -278 },  { 227, -273 },  { 223, -267 },  { 220, -263 },
	{ 216, -260 },  { 213, -256 },  { 210, -253 },  { 208, -249 },
	{ 205, -246 },  { 203, -244 },  { 201, -241 },  { 198, -239 },
	{ 196, -237 },  { 195, -234 },  { 193, -232 },  { 191, -230 },
	{ 190, -228 },  { 188, -226 },  { 187, -225 },
};

/*
 *  Limited functionality bigint implementation.
 *
 *  Restricted to non-negative numbers with less than 32 * DUK__BI_MAX_PARTS bits,
 *  with the caller responsible for ensuring this is never exceeded.  No memory
 *  allocation (except stack) is needed for bigint computation.  Operations
 *  have been tailored for number conversion needs.
 *
 *  Argument order is "assignment order", i.e. target first, then arguments:
 *  x <- y * z  -->  duk__bi_mul(x, y, z);
 */

/* This upper value has been experimentally determined; debug build will check
 * bigint size with assertions.
 */
#define DUK__BI_MAX_PARTS  37  /* 37x32 = 1184 bits */

#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
#define DUK__BI_PRINT(name,x)  duk__bi_print((name),(x))
#else
#define DUK__BI_PRINT(name,x)
#endif

/* Current size is about 152 bytes. */
typedef struct {
	duk_small_int_t n;
	duk_uint32_t v[DUK__BI_MAX_PARTS];  /* low to high */
} duk__bigint;

#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
DUK_LOCAL void duk__bi_print(const char *name, duk__bigint *x) {
	/* Overestimate required size; debug code so not critical to be tight. */
	char buf[DUK__BI_MAX_PARTS * 9 + 64];
	char *p = buf;
	duk_small_int_t i;

	/* No NUL term checks in this debug code. */
	p += DUK_SPRINTF(p, "%p n=%ld", (void *) x, (long) x->n);
	if (x->n == 0) {
		p += DUK_SPRINTF(p, " 0");
	}
	for (i = x->n - 1; i >= 0; i--) {
		p += DUK_SPRINTF(p, " %08lx", (unsigned long) x->v[i]);
	}

	DUK_DDD(DUK_DDDPRINT("%s: %s", (const char *) name, (const char *) buf));
}
#endif

#if defined(DUK_USE_ASSERTIONS)
DUK_LOCAL duk_small_int_t duk__bi_is_valid(duk__bigint *x) {
	return (duk_small_int_t)
	       ( ((x->n >= 0) && (x->n <= DUK__BI_MAX_PARTS)) /* is valid size */ &&
	         ((x->n == 0) || (x->v[x->n - 1] != 0)) /* is normalized */ );
}
#endif

DUK_LOCAL void duk__bi_normalize(duk__bigint *x) {
	duk_small_int_t i;

	for (i = x->n - 1; i >= 0; i--) {
		if (x->v[i] != 0) {
			break;
		}
	}

	/* Note: if 'x' is zero, x->n becomes 0 here */
	x->n = i + 1;
	DUK_ASSERT(duk__bi_is_valid(x));
}

/* x <- y */
DUK_LOCAL void duk__bi_copy(duk__bigint *x, duk__bigint *y) {
	duk_small_int_t n;

	n = y->n;
	x->n = n;
	/* No need to special case n == 0. */
	duk_memcpy((void *) x->v, (const void *) y->v, (size_t) (sizeof(duk_uint32_t) * (size_t) n));
}

DUK_LOCAL void duk__bi_set_small(duk__bigint *x, duk_uint32_t v) {
	if (v == 0U) {
		x->n = 0;
	} else {
		x->n = 1;
		x->v[0] = v;
	}
	DUK_ASSERT(duk__bi_is_valid(x));
}

/* Return value: <0  <=>  x < y
 *                0  <=>  x == y
 *               >0  <=>  x > y
 */
DUK_LOCAL int duk__bi_compare(duk__bigint *x, duk__bigint *y) {
	duk_small_int_t i, nx, ny;
	duk_uint32_t tx, ty;

	DUK_ASSERT(duk__bi_is_valid(x));
	DUK_ASSERT(duk__bi_is_valid(y));

	nx = x->n;
	ny = y->n;
	if (nx > ny) {
		goto ret_gt;
	}
	if (nx < ny) {
		goto ret_lt;
	}
	for (i = nx - 1; i >= 0; i--) {
		tx = x->v[i];
		ty = y->v[i];

		if (tx > ty) {
			goto ret_gt;
		}
		if (tx < ty) {
			goto ret_lt;
		}
	}

	return 0;

 ret_gt:
	return 1;

 ret_lt:
	return -1;
}

/* x <- y + z */
#if defined(DUK_USE_64BIT_OPS)
DUK_LOCAL void duk__bi_add(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
	duk_uint64_t tmp;
	duk_small_int_t i, ny, nz;

	DUK_ASSERT(duk__bi_is_valid(y));
	DUK_ASSERT(duk__bi_is_valid(z));

	if (z->n > y->n) {
		duk__bigint *t;
		t = y; y = z; z = t;
	}
	DUK_ASSERT(y->n >= z->n);

	ny = y->n; nz = z->n;
	tmp = 0U;
	for (i = 0; i < ny; i++) {
		DUK_ASSERT(i < DUK__BI_MAX_PARTS);
		tmp += y->v[i];
		if (i < nz) {
			tmp += z->v[i];
		}
		x->v[i] = (duk_uint32_t) (tmp & 0xffffffffUL);
		tmp = tmp >> 32;
	}
	if (tmp != 0U) {
		DUK_ASSERT(i < DUK__BI_MAX_PARTS);
		x->v[i++] = (duk_uint32_t) tmp;
	}
	x->n = i;
	DUK_ASSERT(x->n <= DUK__BI_MAX_PARTS);

	/* no need to normalize */
	DUK_ASSERT(duk__bi_is_valid(x));
}
#else  /* DUK_USE_64BIT_OPS */
DUK_LOCAL void duk__bi_add(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
	duk_uint32_t carry, tmp1, tmp2;
	duk_small_int_t i, ny, nz;

	DUK_ASSERT(duk__bi_is_valid(y));
	DUK_ASSERT(duk__bi_is_valid(z));

	if (z->n > y->n) {
		duk__bigint *t;
		t = y; y = z; z = t;
	}
	DUK_ASSERT(y->n >= z->n);

	ny = y->n; nz = z->n;
	carry = 0U;
	for (i = 0; i < ny; i++) {
		/* Carry is detected based on wrapping which relies on exact 32-bit
		 * types.
		 */
		DUK_ASSERT(i < DUK__BI_MAX_PARTS);
		tmp1 = y->v[i];
		tmp2 = tmp1;
		if (i < nz) {
			tmp2 += z->v[i];
		}

		/* Careful with carry condition:
		 *  - If carry not added: 0x12345678 + 0 + 0xffffffff = 0x12345677 (< 0x12345678)
		 *  - If carry added:     0x12345678 + 1 + 0xffffffff = 0x12345678 (== 0x12345678)
		 */
		if (carry) {
			tmp2++;
			carry = (tmp2 <= tmp1 ? 1U : 0U);
		} else {
			carry = (tmp2 < tmp1 ? 1U : 0U);
		}

		x->v[i] = tmp2;
	}
	if (carry) {
		DUK_ASSERT(i < DUK__BI_MAX_PARTS);
		DUK_ASSERT(carry == 1U);
		x->v[i++] = carry;
	}
	x->n = i;
	DUK_ASSERT(x->n <= DUK__BI_MAX_PARTS);

	/* no need to normalize */
	DUK_ASSERT(duk__bi_is_valid(x));
}
#endif  /* DUK_USE_64BIT_OPS */

/* x <- y + z */
DUK_LOCAL void duk__bi_add_small(duk__bigint *x, duk__bigint *y, duk_uint32_t z) {
	duk__bigint tmp;

	DUK_ASSERT(duk__bi_is_valid(y));

	/* XXX: this could be optimized; there is only one call site now though */
	duk__bi_set_small(&tmp, z);
	duk__bi_add(x, y, &tmp);

	DUK_ASSERT(duk__bi_is_valid(x));
}

#if 0  /* unused */
/* x <- x + y, use t as temp */
DUK_LOCAL void duk__bi_add_copy(duk__bigint *x, duk__bigint *y, duk__bigint *t) {
	duk__bi_add(t, x, y);
	duk__bi_copy(x, t);
}
#endif

/* x <- y - z, require x >= y => z >= 0, i.e. y >= z */
#if defined(DUK_USE_64BIT_OPS)
DUK_LOCAL void duk__bi_sub(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
	duk_small_int_t i, ny, nz;
	duk_uint32_t ty, tz;
	duk_int64_t tmp;

	DUK_ASSERT(duk__bi_is_valid(y));
	DUK_ASSERT(duk__bi_is_valid(z));
	DUK_ASSERT(duk__bi_compare(y, z) >= 0);
	DUK_ASSERT(y->n >= z->n);

	ny = y->n; nz = z->n;
	tmp = 0;
	for (i = 0; i < ny; i++) {
		ty = y->v[i];
		if (i < nz) {
			tz = z->v[i];
		} else {
			tz = 0;
		}
		tmp = (duk_int64_t) ty - (duk_int64_t) tz + tmp;
		x->v[i] = (duk_uint32_t) ((duk_uint64_t) tmp & 0xffffffffUL);
		tmp = tmp >> 32;  /* 0 or -1 */
	}
	DUK_ASSERT(tmp == 0);

	x->n = i;
	duk__bi_normalize(x);  /* need to normalize, may even cancel to 0 */
	DUK_ASSERT(duk__bi_is_valid(x));
}
#else
DUK_LOCAL void duk__bi_sub(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
	duk_small_int_t i, ny, nz;
	duk_uint32_t tmp1, tmp2, borrow;

	DUK_ASSERT(duk__bi_is_valid(y));
	DUK_ASSERT(duk__bi_is_valid(z));
	DUK_ASSERT(duk__bi_compare(y, z) >= 0);
	DUK_ASSERT(y->n >= z->n);

	ny = y->n; nz = z->n;
	borrow = 0U;
	for (i = 0; i < ny; i++) {
		/* Borrow is detected based on wrapping which relies on exact 32-bit
		 * types.
		 */
		tmp1 = y->v[i];
		tmp2 = tmp1;
		if (i < nz) {
			tmp2 -= z->v[i];
		}

		/* Careful with borrow condition:
		 *  - If borrow not subtracted: 0x12345678 - 0 - 0xffffffff = 0x12345679 (> 0x12345678)
		 *  - If borrow subtracted:     0x12345678 - 1 - 0xffffffff = 0x12345678 (== 0x12345678)
		 */
		if (borrow) {
			tmp2--;
			borrow = (tmp2 >= tmp1 ? 1U : 0U);
		} else {
			borrow = (tmp2 > tmp1 ? 1U : 0U);
		}

		x->v[i] = tmp2;
	}
	DUK_ASSERT(borrow == 0U);

	x->n = i;
	duk__bi_normalize(x);  /* need to normalize, may even cancel to 0 */
	DUK_ASSERT(duk__bi_is_valid(x));
}
#endif

#if 0  /* unused */
/* x <- y - z */
DUK_LOCAL void duk__bi_sub_small(duk__bigint *x, duk__bigint *y, duk_uint32_t z) {
	duk__bigint tmp;

	DUK_ASSERT(duk__bi_is_valid(y));

	/* XXX: this could be optimized */
	duk__bi_set_small(&tmp, z);
	duk__bi_sub(x, y, &tmp);

	DUK_ASSERT(duk__bi_is_valid(x));
}
#endif

/* x <- x - y, use t as temp */
DUK_LOCAL void duk__bi_sub_copy(duk__bigint *x, duk__bigint *y, duk__bigint *t) {
	duk__bi_sub(t, x, y);
	duk__bi_copy(x, t);
}

/* x <- y * z */
DUK_LOCAL void duk__bi_mul(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
	duk_small_int_t i, j, nx, nz;

	DUK_ASSERT(duk__bi_is_valid(y));
	DUK_ASSERT(duk__bi_is_valid(z));

	nx = y->n + z->n;  /* max possible */
	DUK_ASSERT(nx <= DUK__BI_MAX_PARTS);

	if (nx == 0) {
		/* Both inputs are zero; cases where only one is zero can go
		 * through main algorithm.
		 */
		x->n = 0;
		return;
	}

	duk_memzero((void *) x->v, (size_t) (sizeof(duk_uint32_t) * (size_t) nx));
	x->n = nx;

	nz = z->n;
	for (i = 0; i < y->n; i++) {
#if defined(DUK_USE_64BIT_OPS)
		duk_uint64_t tmp = 0U;
		for (j = 0; j < nz; j++) {
			tmp += (duk_uint64_t) y->v[i] * (duk_uint64_t) z->v[j] + x->v[i+j];
			x->v[i+j] = (duk_uint32_t) (tmp & 0xffffffffUL);
			tmp = tmp >> 32;
		}
		if (tmp > 0) {
			DUK_ASSERT(i + j < nx);
			DUK_ASSERT(i + j < DUK__BI_MAX_PARTS);
			DUK_ASSERT(x->v[i+j] == 0U);
			x->v[i+j] = (duk_uint32_t) tmp;
		}
#else
		/*
		 *  Multiply + add + carry for 32-bit components using only 16x16->32
		 *  multiplies and carry detection based on unsigned overflow.
		 *
		 *    1st mult, 32-bit: (A*2^16 + B)
		 *    2nd mult, 32-bit: (C*2^16 + D)
		 *    3rd add, 32-bit: E
		 *    4th add, 32-bit: F
		 *
		 *      (AC*2^16 + B) * (C*2^16 + D) + E + F
		 *    = AC*2^32 + AD*2^16 + BC*2^16 + BD + E + F
		 *    = AC*2^32 + (AD + BC)*2^16 + (BD + E + F)
		 *    = AC*2^32 + AD*2^16 + BC*2^16 + (BD + E + F)
		 */
		duk_uint32_t a, b, c, d, e, f;
		duk_uint32_t r, s, t;

		a = y->v[i]; b = a & 0xffffUL; a = a >> 16;

		f = 0;
		for (j = 0; j < nz; j++) {
			c = z->v[j]; d = c & 0xffffUL; c = c >> 16;
			e = x->v[i+j];

			/* build result as: (r << 32) + s: start with (BD + E + F) */
			r = 0;
			s = b * d;

			/* add E */
			t = s + e;
			if (t < s) { r++; }  /* carry */
			s = t;

			/* add F */
			t = s + f;
			if (t < s) { r++; }  /* carry */
			s = t;

			/* add BC*2^16 */
			t = b * c;
			r += (t >> 16);
			t = s + ((t & 0xffffUL) << 16);
			if (t < s) { r++; }  /* carry */
			s = t;

			/* add AD*2^16 */
			t = a * d;
			r += (t >> 16);
			t = s + ((t & 0xffffUL) << 16);
			if (t < s) { r++; }  /* carry */
			s = t;

			/* add AC*2^32 */
			t = a * c;
			r += t;

			DUK_DDD(DUK_DDDPRINT("ab=%08lx cd=%08lx ef=%08lx -> rs=%08lx %08lx",
			                     (unsigned long) y->v[i], (unsigned long) z->v[j],
			                     (unsigned long) x->v[i+j], (unsigned long) r,
			                     (unsigned long) s));

			x->v[i+j] = s;
			f = r;
		}
		if (f > 0U) {
			DUK_ASSERT(i + j < nx);
			DUK_ASSERT(i + j < DUK__BI_MAX_PARTS);
			DUK_ASSERT(x->v[i+j] == 0U);
			x->v[i+j] = (duk_uint32_t) f;
		}
#endif  /* DUK_USE_64BIT_OPS */
	}

	duk__bi_normalize(x);
	DUK_ASSERT(duk__bi_is_valid(x));
}

/* x <- y * z */
DUK_LOCAL void duk__bi_mul_small(duk__bigint *x, duk__bigint *y, duk_uint32_t z) {
	duk__bigint tmp;

	DUK_ASSERT(duk__bi_is_valid(y));

	/* XXX: this could be optimized */
	duk__bi_set_small(&tmp, z);
	duk__bi_mul(x, y, &tmp);

	DUK_ASSERT(duk__bi_is_valid(x));
}

/* x <- x * y, use t as temp */
DUK_LOCAL void duk__bi_mul_copy(duk__bigint *x, duk__bigint *y, duk__bigint *t) {
	duk__bi_mul(t, x, y);
	duk__bi_copy(x, t);
}

/* x <- x * y, use t as temp */
DUK_LOCAL void duk__bi_mul_small_copy(duk__bigint *x, duk_uint32_t y, duk__bigint *t) {
	duk__bi_mul_small(t, x, y);
	duk__bi_copy(x, t);
}

DUK_LOCAL int duk__bi_is_even(duk__bigint *x) {
	DUK_ASSERT(duk__bi_is_valid(x));
	return (x->n == 0) || ((x->v[0] & 0x01) == 0);
}

DUK_LOCAL int duk__bi_is_zero(duk__bigint *x) {
	DUK_ASSERT(duk__bi_is_valid(x));
	return (x->n == 0);  /* this is the case for normalized numbers */
}

/* Bigint is 2^52.  Used to detect normalized IEEE double mantissa values
 * which are at the lowest edge (next floating point value downwards has
 * a different exponent).  The lowest mantissa has the form:
 *
 *     1000........000    (52 zeroes; only "hidden bit" is set)
 */
DUK_LOCAL duk_small_int_t duk__bi_is_2to52(duk__bigint *x) {
	DUK_ASSERT(duk__bi_is_valid(x));
	return (duk_small_int_t)
	        (x->n == 2) && (x->v[0] == 0U) && (x->v[1] == (1U << (52-32)));
}

/* x <- (1<<y) */
DUK_LOCAL void duk__bi_twoexp(duk__bigint *x, duk_small_int_t y) {
	duk_small_int_t n, r;

	n = (y / 32) + 1;
	DUK_ASSERT(n > 0);
	r = y % 32;
	duk_memzero((void *) x->v, sizeof(duk_uint32_t) * (size_t) n);
	x->n = n;
	x->v[n - 1] = (((duk_uint32_t) 1) << r);
}

/* x <- b^y; use t1 and t2 as temps */
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) {
	/* Fast path the binary case */

	DUK_ASSERT(x != t1 && x != t2 && t1 != t2);  /* distinct bignums, easy mistake to make */
	DUK_ASSERT(b >= 0);
	DUK_ASSERT(y >= 0);

	if (b == 2) {
		duk__bi_twoexp(x, y);
		return;
	}

	/* http://en.wikipedia.org/wiki/Exponentiation_by_squaring */

	DUK_DDD(DUK_DDDPRINT("exp_small: b=%ld, y=%ld", (long) b, (long) y));

	duk__bi_set_small(x, 1);
	duk__bi_set_small(t1, (duk_uint32_t) b);
	for (;;) {
		/* Loop structure ensures that we don't compute t1^2 unnecessarily
		 * on the final round, as that might create a bignum exceeding the
		 * current DUK__BI_MAX_PARTS limit.
		 */
		if (y & 0x01) {
			duk__bi_mul_copy(x, t1, t2);
		}
		y = y >> 1;
		if (y == 0) {
			break;
		}
		duk__bi_mul_copy(t1, t1, t2);
	}

	DUK__BI_PRINT("exp_small result", x);
}

/*
 *  A Dragon4 number-to-string variant, based on:
 *
 *    Guy L. Steele Jr., Jon L. White: "How to Print Floating-Point Numbers
 *    Accurately"
 *
 *    Robert G. Burger, R. Kent Dybvig: "Printing Floating-Point Numbers
 *    Quickly and Accurately"
 *
 *  The current algorithm is based on Figure 1 of the Burger-Dybvig paper,
 *  i.e. the base implementation without logarithm estimation speedups
 *  (these would increase code footprint considerably).  Fixed-format output
 *  does not follow the suggestions in the paper; instead, we generate an
 *  extra digit and round-with-carry.
 *
 *  The same algorithm is used for number parsing (with b=10 and B=2)
 *  by generating one extra digit and doing rounding manually.
 *
 *  See doc/number-conversion.rst for limitations.
 */

/* Maximum number of digits generated. */
#define DUK__MAX_OUTPUT_DIGITS          1040  /* (Number.MAX_VALUE).toString(2).length == 1024, + slack */

/* Maximum number of characters in formatted value. */
#define DUK__MAX_FORMATTED_LENGTH       1040  /* (-Number.MAX_VALUE).toString(2).length == 1025, + slack */

/* Number and (minimum) size of bigints in the nc_ctx structure. */
#define DUK__NUMCONV_CTX_NUM_BIGINTS    7
#define DUK__NUMCONV_CTX_BIGINTS_SIZE   (sizeof(duk__bigint) * DUK__NUMCONV_CTX_NUM_BIGINTS)

typedef struct {
	/* Currently about 7*152 = 1064 bytes.  The space for these
	 * duk__bigints is used also as a temporary buffer for generating
	 * the final string.  This is a bit awkard; a union would be
	 * more correct.
	 */
	duk__bigint f, r, s, mp, mm, t1, t2;

	duk_small_int_t is_s2n;        /* if 1, doing a string-to-number; else doing a number-to-string */
	duk_small_int_t is_fixed;      /* if 1, doing a fixed format output (not free format) */
	duk_small_int_t req_digits;    /* requested number of output digits; 0 = free-format */
	duk_small_int_t abs_pos;       /* digit position is absolute, not relative */
	duk_small_int_t e;             /* exponent for 'f' */
	duk_small_int_t b;             /* input radix */
	duk_small_int_t B;             /* output radix */
	duk_small_int_t k;             /* see algorithm */
	duk_small_int_t low_ok;        /* see algorithm */
	duk_small_int_t high_ok;       /* see algorithm */
	duk_small_int_t unequal_gaps;  /* m+ != m- (very rarely) */

	/* Buffer used for generated digits, values are in the range [0,B-1]. */
	duk_uint8_t digits[DUK__MAX_OUTPUT_DIGITS];
	duk_small_int_t count;  /* digit count */
} duk__numconv_stringify_ctx;

/* Note: computes with 'idx' in assertions, so caller beware.
 * 'idx' is preincremented, i.e. '1' on first call, because it
 * is more convenient for the caller.
 */
#define DUK__DRAGON4_OUTPUT_PREINC(nc_ctx,preinc_idx,x)  do { \
		DUK_ASSERT((preinc_idx) - 1 >= 0); \
		DUK_ASSERT((preinc_idx) - 1 < DUK__MAX_OUTPUT_DIGITS); \
		((nc_ctx)->digits[(preinc_idx) - 1]) = (duk_uint8_t) (x); \
	} while (0)

DUK_LOCAL duk_size_t duk__dragon4_format_uint32(duk_uint8_t *buf, duk_uint32_t x, duk_small_int_t radix) {
	duk_uint8_t *p;
	duk_size_t len;
	duk_small_int_t dig;
	duk_uint32_t t;

	DUK_ASSERT(buf != NULL);
	DUK_ASSERT(radix >= 2 && radix <= 36);

	/* A 32-bit unsigned integer formats to at most 32 digits (the
	 * worst case happens with radix == 2).  Output the digits backwards,
	 * and use a memmove() to get them in the right place.
	 */

	p = buf + 32;
	for (;;) {
		t = x / (duk_uint32_t) radix;
		dig = (duk_small_int_t) (x - t * (duk_uint32_t) radix);
		x = t;

		DUK_ASSERT(dig >= 0 && dig < 36);
		*(--p) = DUK__DIGITCHAR(dig);

		if (x == 0) {
			break;
		}
	}
	len = (duk_size_t) ((buf + 32) - p);

	duk_memmove((void *) buf, (const void *) p, (size_t) len);

	return len;
}

DUK_LOCAL void duk__dragon4_prepare(duk__numconv_stringify_ctx *nc_ctx) {
	duk_small_int_t lowest_mantissa;

#if 1
	/* Assume IEEE round-to-even, so that shorter encoding can be used
	 * when round-to-even would produce correct result.  By removing
	 * this check (and having low_ok == high_ok == 0) the results would
	 * still be accurate but in some cases longer than necessary.
	 */
	if (duk__bi_is_even(&nc_ctx->f)) {
		DUK_DDD(DUK_DDDPRINT("f is even"));
		nc_ctx->low_ok = 1;
		nc_ctx->high_ok = 1;
	} else {
		DUK_DDD(DUK_DDDPRINT("f is odd"));
		nc_ctx->low_ok = 0;
		nc_ctx->high_ok = 0;
	}
#else
	/* Note: not honoring round-to-even should work but now generates incorrect
	 * results.  For instance, 1e23 serializes to "a000...", i.e. the first digit
	 * equals the radix (10).  Scaling stops one step too early in this case.
	 * Don't know why this is the case, but since this code path is unused, it
	 * doesn't matter.
	 */
	nc_ctx->low_ok = 0;
	nc_ctx->high_ok = 0;
#endif

	/* For string-to-number, pretend we never have the lowest mantissa as there
	 * is no natural "precision" for inputs.  Having lowest_mantissa == 0, we'll
	 * fall into the base cases for both e >= 0 and e < 0.
	 */
	if (nc_ctx->is_s2n) {
		lowest_mantissa = 0;
	} else {
		lowest_mantissa = duk__bi_is_2to52(&nc_ctx->f);
	}

	nc_ctx->unequal_gaps = 0;
	if (nc_ctx->e >= 0) {
		/* exponent non-negative (and thus not minimum exponent) */

		if (lowest_mantissa) {
			/* (>= e 0) AND (= f (expt b (- p 1)))
			 *
			 * be <- (expt b e) == b^e
			 * be1 <- (* be b) == (expt b (+ e 1)) == b^(e+1)
			 * r <- (* f be1 2) == 2 * f * b^(e+1)    [if b==2 -> f * b^(e+2)]
			 * s <- (* b 2)                           [if b==2 -> 4]
			 * m+ <- be1 == b^(e+1)
			 * m- <- be == b^e
			 * k <- 0
			 * B <- B
			 * low_ok <- round
			 * high_ok <- round
			 */

			DUK_DDD(DUK_DDDPRINT("non-negative exponent (not smallest exponent); "
			                     "lowest mantissa value for this exponent -> "
			                     "unequal gaps"));

			duk__bi_exp_small(&nc_ctx->mm, nc_ctx->b, nc_ctx->e, &nc_ctx->t1, &nc_ctx->t2);  /* mm <- b^e */
			duk__bi_mul_small(&nc_ctx->mp, &nc_ctx->mm, (duk_uint32_t) nc_ctx->b);           /* mp <- b^(e+1) */
			duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->f, 2);
			duk__bi_mul(&nc_ctx->r, &nc_ctx->t1, &nc_ctx->mp);              /* r <- (2 * f) * b^(e+1) */
			duk__bi_set_small(&nc_ctx->s, (duk_uint32_t) (nc_ctx->b * 2));  /* s <- 2 * b */
			nc_ctx->unequal_gaps = 1;
		} else {
			/* (>= e 0) AND (not (= f (expt b (- p 1))))
			 *
			 * be <- (expt b e) == b^e
			 * r <- (* f be 2) == 2 * f * b^e    [if b==2 -> f * b^(e+1)]
			 * s <- 2
			 * m+ <- be == b^e
			 * m- <- be == b^e
			 * k <- 0
			 * B <- B
			 * low_ok <- round
			 * high_ok <- round
			 */

			DUK_DDD(DUK_DDDPRINT("non-negative exponent (not smallest exponent); "
			                     "not lowest mantissa for this exponent -> "
			                     "equal gaps"));

			duk__bi_exp_small(&nc_ctx->mm, nc_ctx->b, nc_ctx->e, &nc_ctx->t1, &nc_ctx->t2);  /* mm <- b^e */
			duk__bi_copy(&nc_ctx->mp, &nc_ctx->mm);                /* mp <- b^e */
			duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->f, 2);
			duk__bi_mul(&nc_ctx->r, &nc_ctx->t1, &nc_ctx->mp);     /* r <- (2 * f) * b^e */
			duk__bi_set_small(&nc_ctx->s, 2);                      /* s <- 2 */
		}
	} else {
		/* When doing string-to-number, lowest_mantissa is always 0 so
		 * the exponent check, while incorrect, won't matter.
		 */
		if (nc_ctx->e > DUK__IEEE_DOUBLE_EXP_MIN /*not minimum exponent*/ &&
		    lowest_mantissa /* lowest mantissa for this exponent*/) {
			/* r <- (* f b 2)                                [if b==2 -> (* f 4)]
			 * s <- (* (expt b (- 1 e)) 2) == b^(1-e) * 2    [if b==2 -> b^(2-e)]
			 * m+ <- b == 2
			 * m- <- 1
			 * k <- 0
			 * B <- B
			 * low_ok <- round
			 * high_ok <- round
			 */

			DUK_DDD(DUK_DDDPRINT("negative exponent; not minimum exponent and "
			                     "lowest mantissa for this exponent -> "
			                     "unequal gaps"));

			duk__bi_mul_small(&nc_ctx->r, &nc_ctx->f, (duk_uint32_t) (nc_ctx->b * 2));  /* r <- (2 * b) * f */
			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 */
			duk__bi_mul_small(&nc_ctx->s, &nc_ctx->t1, 2);             /* s <- b^(1-e) * 2 */
			duk__bi_set_small(&nc_ctx->mp, 2);
			duk__bi_set_small(&nc_ctx->mm, 1);
			nc_ctx->unequal_gaps = 1;
		} else {
			/* r <- (* f 2)
			 * s <- (* (expt b (- e)) 2) == b^(-e) * 2    [if b==2 -> b^(1-e)]
			 * m+ <- 1
			 * m- <- 1
			 * k <- 0
			 * B <- B
			 * low_ok <- round
			 * high_ok <- round
			 */

			DUK_DDD(DUK_DDDPRINT("negative exponent; minimum exponent or not "
			                     "lowest mantissa for this exponent -> "
			                     "equal gaps"));

			duk__bi_mul_small(&nc_ctx->r, &nc_ctx->f, 2);            /* r <- 2 * f */
			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 */
			duk__bi_mul_small(&nc_ctx->s, &nc_ctx->t1, 2);           /* s <- b^(-e) * 2 */
			duk__bi_set_small(&nc_ctx->mp, 1);
			duk__bi_set_small(&nc_ctx->mm, 1);
		}
	}
}

DUK_LOCAL void duk__dragon4_scale(duk__numconv_stringify_ctx *nc_ctx) {
	duk_small_int_t k = 0;

	/* This is essentially the 'scale' algorithm, with recursion removed.
	 * Note that 'k' is either correct immediately, or will move in one
	 * direction in the loop.  There's no need to do the low/high checks
	 * on every round (like the Scheme algorithm does).
	 *
	 * The scheme algorithm finds 'k' and updates 's' simultaneously,
	 * while the logical algorithm finds 'k' with 's' having its initial
	 * value, after which 's' is updated separately (see the Burger-Dybvig
	 * paper, Section 3.1, steps 2 and 3).
	 *
	 * The case where m+ == m- (almost always) is optimized for, because
	 * it reduces the bigint operations considerably and almost always
	 * applies.  The scale loop only needs to work with m+, so this works.
	 */

	/* XXX: this algorithm could be optimized quite a lot by using e.g.
	 * a logarithm based estimator for 'k' and performing B^n multiplication
	 * using a lookup table or using some bit-representation based exp
	 * algorithm.  Currently we just loop, with significant performance
	 * impact for very large and very small numbers.
	 */

	DUK_DDD(DUK_DDDPRINT("scale: B=%ld, low_ok=%ld, high_ok=%ld",
	                     (long) nc_ctx->B, (long) nc_ctx->low_ok, (long) nc_ctx->high_ok));
	DUK__BI_PRINT("r(init)", &nc_ctx->r);
	DUK__BI_PRINT("s(init)", &nc_ctx->s);
	DUK__BI_PRINT("mp(init)", &nc_ctx->mp);
	DUK__BI_PRINT("mm(init)", &nc_ctx->mm);

	for (;;) {
		DUK_DDD(DUK_DDDPRINT("scale loop (inc k), k=%ld", (long) k));
		DUK__BI_PRINT("r", &nc_ctx->r);
		DUK__BI_PRINT("s", &nc_ctx->s);
		DUK__BI_PRINT("m+", &nc_ctx->mp);
		DUK__BI_PRINT("m-", &nc_ctx->mm);

		duk__bi_add(&nc_ctx->t1, &nc_ctx->r, &nc_ctx->mp);  /* t1 = (+ r m+) */
		if (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) >= (nc_ctx->high_ok ? 0 : 1)) {
			DUK_DDD(DUK_DDDPRINT("k is too low"));
			/* r <- r
			 * s <- (* s B)
			 * m+ <- m+
			 * m- <- m-
			 * k <- (+ k 1)
			 */

			duk__bi_mul_small_copy(&nc_ctx->s, (duk_uint32_t) nc_ctx->B, &nc_ctx->t1);
			k++;
		} else {
			break;
		}
	}

	/* k > 0 -> k was too low, and cannot be too high */
	if (k > 0) {
		goto skip_dec_k;
	}

	for (;;) {
		DUK_DDD(DUK_DDDPRINT("scale loop (dec k), k=%ld", (long) k));
		DUK__BI_PRINT("r", &nc_ctx->r);
		DUK__BI_PRINT("s", &nc_ctx->s);
		DUK__BI_PRINT("m+", &nc_ctx->mp);
		DUK__BI_PRINT("m-", &nc_ctx->mm);

		duk__bi_add(&nc_ctx->t1, &nc_ctx->r, &nc_ctx->mp);  /* t1 = (+ r m+) */
		duk__bi_mul_small(&nc_ctx->t2, &nc_ctx->t1, (duk_uint32_t) nc_ctx->B);   /* t2 = (* (+ r m+) B) */
		if (duk__bi_compare(&nc_ctx->t2, &nc_ctx->s) <= (nc_ctx->high_ok ? -1 : 0)) {
			DUK_DDD(DUK_DDDPRINT("k is too high"));
			/* r <- (* r B)
			 * s <- s
			 * m+ <- (* m+ B)
			 * m- <- (* m- B)
			 * k <- (- k 1)
			 */
			duk__bi_mul_small_copy(&nc_ctx->r, (duk_uint32_t) nc_ctx->B, &nc_ctx->t1);
			duk__bi_mul_small_copy(&nc_ctx->mp, (duk_uint32_t) nc_ctx->B, &nc_ctx->t1);
			if (nc_ctx->unequal_gaps) {
				DUK_DDD(DUK_DDDPRINT("m+ != m- -> need to update m- too"));
				duk__bi_mul_small_copy(&nc_ctx->mm, (duk_uint32_t) nc_ctx->B, &nc_ctx->t1);
			}
			k--;
		} else {
			break;
		}
	}

 skip_dec_k:

	if (!nc_ctx->unequal_gaps) {
		DUK_DDD(DUK_DDDPRINT("equal gaps, copy m- from m+"));
		duk__bi_copy(&nc_ctx->mm, &nc_ctx->mp);  /* mm <- mp */
	}
	nc_ctx->k = k;

	DUK_DDD(DUK_DDDPRINT("final k: %ld", (long) k));
	DUK__BI_PRINT("r(final)", &nc_ctx->r);
	DUK__BI_PRINT("s(final)", &nc_ctx->s);
	DUK__BI_PRINT("mp(final)", &nc_ctx->mp);
	DUK__BI_PRINT("mm(final)", &nc_ctx->mm);
}

DUK_LOCAL void duk__dragon4_generate(duk__numconv_stringify_ctx *nc_ctx) {
	duk_small_int_t tc1, tc2;    /* terminating conditions */
	duk_small_int_t d;           /* current digit */
	duk_small_int_t count = 0;   /* digit count */

	/*
	 *  Digit generation loop.
	 *
	 *  Different termination conditions:
	 *
	 *    1. Free format output.  Terminate when shortest accurate
	 *       representation found.
	 *
	 *    2. Fixed format output, with specific number of digits.
	 *       Ignore termination conditions, terminate when digits
	 *       generated.  Caller requests an extra digit and rounds.
	 *
	 *    3. Fixed format output, with a specific absolute cut-off
	 *       position (e.g. 10 digits after decimal point).  Note
	 *       that we always generate at least one digit, even if
	 *       the digit is below the cut-off point already.
	 */

	for (;;) {
		DUK_DDD(DUK_DDDPRINT("generate loop, count=%ld, k=%ld, B=%ld, low_ok=%ld, high_ok=%ld",
		                     (long) count, (long) nc_ctx->k, (long) nc_ctx->B,
		                     (long) nc_ctx->low_ok, (long) nc_ctx->high_ok));
		DUK__BI_PRINT("r", &nc_ctx->r);
		DUK__BI_PRINT("s", &nc_ctx->s);
		DUK__BI_PRINT("m+", &nc_ctx->mp);
		DUK__BI_PRINT("m-", &nc_ctx->mm);

		/* (quotient-remainder (* r B) s) using a dummy subtraction loop */
		duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->r, (duk_uint32_t) nc_ctx->B);       /* t1 <- (* r B) */
		d = 0;
		for (;;) {
			if (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) < 0) {
				break;
			}
			duk__bi_sub_copy(&nc_ctx->t1, &nc_ctx->s, &nc_ctx->t2);  /* t1 <- t1 - s */
			d++;
		}
		duk__bi_copy(&nc_ctx->r, &nc_ctx->t1);  /* r <- (remainder (* r B) s) */
		                                        /* d <- (quotient (* r B) s)   (in range 0...B-1) */
		DUK_DDD(DUK_DDDPRINT("-> d(quot)=%ld", (long) d));
		DUK__BI_PRINT("r(rem)", &nc_ctx->r);

		duk__bi_mul_small_copy(&nc_ctx->mp, (duk_uint32_t) nc_ctx->B, &nc_ctx->t2); /* m+ <- (* m+ B) */
		duk__bi_mul_small_copy(&nc_ctx->mm, (duk_uint32_t) nc_ctx->B, &nc_ctx->t2); /* m- <- (* m- B) */
		DUK__BI_PRINT("mp(upd)", &nc_ctx->mp);
		DUK__BI_PRINT("mm(upd)", &nc_ctx->mm);

		/* Terminating conditions.  For fixed width output, we just ignore the
		 * terminating conditions (and pretend that tc1 == tc2 == false).  The
		 * the current shortcut for fixed-format output is to generate a few
		 * extra digits and use rounding (with carry) to finish the output.
		 */

		if (nc_ctx->is_fixed == 0) {
			/* free-form */
			tc1 = (duk__bi_compare(&nc_ctx->r, &nc_ctx->mm) <= (nc_ctx->low_ok ? 0 : -1));

			duk__bi_add(&nc_ctx->t1, &nc_ctx->r, &nc_ctx->mp);  /* t1 <- (+ r m+) */
			tc2 = (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) >= (nc_ctx->high_ok ? 0 : 1));

			DUK_DDD(DUK_DDDPRINT("tc1=%ld, tc2=%ld", (long) tc1, (long) tc2));
		} else {
			/* fixed-format */
			tc1 = 0;
			tc2 = 0;
		}

		/* Count is incremented before DUK__DRAGON4_OUTPUT_PREINC() call
		 * on purpose, which is taken into account by the macro.
		 */
		count++;

		if (tc1) {
			if (tc2) {
				/* tc1 = true, tc2 = true */
				duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->r, 2);
				if (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) < 0) {  /* (< (* r 2) s) */
					DUK_DDD(DUK_DDDPRINT("tc1=true, tc2=true, 2r > s: output d --> %ld (k=%ld)",
					                     (long) d, (long) nc_ctx->k));
					DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d);
				} else {
					DUK_DDD(DUK_DDDPRINT("tc1=true, tc2=true, 2r <= s: output d+1 --> %ld (k=%ld)",
					                     (long) (d + 1), (long) nc_ctx->k));
					DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d + 1);
				}
				break;
			} else {
				/* tc1 = true, tc2 = false */
				DUK_DDD(DUK_DDDPRINT("tc1=true, tc2=false: output d --> %ld (k=%ld)",
				                     (long) d, (long) nc_ctx->k));
				DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d);
				break;
			}
		} else {
			if (tc2) {
				/* tc1 = false, tc2 = true */
				DUK_DDD(DUK_DDDPRINT("tc1=false, tc2=true: output d+1 --> %ld (k=%ld)",
				                     (long) (d + 1), (long) nc_ctx->k));
				DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d + 1);
				break;
			} else {
				/* tc1 = false, tc2 = false */
				DUK_DDD(DUK_DDDPRINT("tc1=false, tc2=false: output d --> %ld (k=%ld)",
				                     (long) d, (long) nc_ctx->k));
				DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d);

				/* r <- r    (updated above: r <- (remainder (* r B) s)
				 * s <- s
				 * m+ <- m+  (updated above: m+ <- (* m+ B)
				 * m- <- m-  (updated above: m- <- (* m- B)
				 * B, low_ok, high_ok are fixed
				 */

				/* fall through and continue for-loop */
			}
		}

		/* fixed-format termination conditions */
		if (nc_ctx->is_fixed) {
			if (nc_ctx->abs_pos) {
				int pos = nc_ctx->k - count + 1;  /* count is already incremented, take into account */
				DUK_DDD(DUK_DDDPRINT("fixed format, absolute: abs pos=%ld, k=%ld, count=%ld, req=%ld",
				                     (long) pos, (long) nc_ctx->k, (long) count, (long) nc_ctx->req_digits));
				if (pos <= nc_ctx->req_digits) {
					DUK_DDD(DUK_DDDPRINT("digit position reached req_digits, end generate loop"));
					break;
				}
			} else {
				DUK_DDD(DUK_DDDPRINT("fixed format, relative: k=%ld, count=%ld, req=%ld",
				                     (long) nc_ctx->k, (long) count, (long) nc_ctx->req_digits));
				if (count >= nc_ctx->req_digits) {
					DUK_DDD(DUK_DDDPRINT("digit count reached req_digits, end generate loop"));
					break;
				}
			}
		}
	}  /* for */

	nc_ctx->count = count;

	DUK_DDD(DUK_DDDPRINT("generate finished"));

#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
	{
		duk_uint8_t buf[2048];
		duk_small_int_t i, t;
		duk_memzero(buf, sizeof(buf));
		for (i = 0; i < nc_ctx->count; i++) {
			t = nc_ctx->digits[i];
			if (t < 0 || t > 36) {
				buf[i] = (duk_uint8_t) '?';
			} else {
				buf[i] = (duk_uint8_t) DUK__DIGITCHAR(t);
			}
		}
		DUK_DDD(DUK_DDDPRINT("-> generated digits; k=%ld, digits='%s'",
		                     (long) nc_ctx->k, (const char *) buf));
	}
#endif
}

/* Round up digits to a given position.  If position is out-of-bounds,
 * does nothing.  If carry propagates over the first digit, a '1' is
 * prepended to digits and 'k' will be updated.  Return value indicates
 * whether carry propagated over the first digit.
 *
 * Note that nc_ctx->count is NOT updated based on the rounding position
 * (it is updated only if carry overflows over the first digit and an
 * extra digit is prepended).
 */
DUK_LOCAL duk_small_int_t duk__dragon4_fixed_format_round(duk__numconv_stringify_ctx *nc_ctx, duk_small_int_t round_idx) {
	duk_small_int_t t;
	duk_uint8_t *p;
	duk_uint8_t roundup_limit;
	duk_small_int_t ret = 0;

	/*
	 *  round_idx points to the digit which is considered for rounding; the
	 *  digit to its left is the final digit of the rounded value.  If round_idx
	 *  is zero, rounding will be performed; the result will either be an empty
	 *  rounded value or if carry happens a '1' digit is generated.
	 */

	if (round_idx >= nc_ctx->count) {
		DUK_DDD(DUK_DDDPRINT("round_idx out of bounds (%ld >= %ld (count)) -> no rounding",
		                     (long) round_idx, (long) nc_ctx->count));
		return 0;
	} else if (round_idx < 0) {
		DUK_DDD(DUK_DDDPRINT("round_idx out of bounds (%ld < 0) -> no rounding",
		                     (long) round_idx));
		return 0;
	}

	/*
	 *  Round-up limit.
	 *
	 *  For even values, divides evenly, e.g. 10 -> roundup_limit=5.
	 *
	 *  For odd values, rounds up, e.g. 3 -> roundup_limit=2.
	 *  If radix is 3, 0/3 -> down, 1/3 -> down, 2/3 -> up.
	 */
	roundup_limit = (duk_uint8_t) ((nc_ctx->B + 1) / 2);

	p = &nc_ctx->digits[round_idx];
	if (*p >= roundup_limit) {
		DUK_DDD(DUK_DDDPRINT("fixed-format rounding carry required"));
		/* carry */
		for (;;) {
			*p = 0;
			if (p == &nc_ctx->digits[0]) {
				DUK_DDD(DUK_DDDPRINT("carry propagated to first digit -> special case handling"));
				duk_memmove((void *) (&nc_ctx->digits[1]),
				            (const void *) (&nc_ctx->digits[0]),
				            (size_t) (sizeof(char) * (size_t) nc_ctx->count));
				nc_ctx->digits[0] = 1;  /* don't increase 'count' */
				nc_ctx->k++;  /* position of highest digit changed */
				nc_ctx->count++;  /* number of digits changed */
				ret = 1;
				break;
			}

			DUK_DDD(DUK_DDDPRINT("fixed-format rounding carry: B=%ld, roundup_limit=%ld, p=%p, digits=%p",
			                     (long) nc_ctx->B, (long) roundup_limit, (void *) p, (void *) nc_ctx->digits));
			p--;
			t = *p;
			DUK_DDD(DUK_DDDPRINT("digit before carry: %ld", (long) t));
			if (++t < nc_ctx->B) {
				DUK_DDD(DUK_DDDPRINT("rounding carry terminated"));
				*p = (duk_uint8_t) t;
				break;
			}

			DUK_DDD(DUK_DDDPRINT("wraps, carry to next digit"));
		}
	}

	return ret;
}

#define DUK__NO_EXP  (65536)  /* arbitrary marker, outside valid exp range */

DUK_LOCAL void duk__dragon4_convert_and_push(duk__numconv_stringify_ctx *nc_ctx,
                                             duk_hthread *thr,
                                             duk_small_int_t radix,
                                             duk_small_int_t digits,
                                             duk_small_uint_t flags,
                                             duk_small_int_t neg) {
	duk_small_int_t k;
	duk_small_int_t pos, pos_end;
	duk_small_int_t expt;
	duk_small_int_t dig;
	duk_uint8_t *q;
	duk_uint8_t *buf;

	/*
	 *  The string conversion here incorporates all the necessary ECMAScript
	 *  semantics without attempting to be generic.  nc_ctx->digits contains
	 *  nc_ctx->count digits (>= 1), with the topmost digit's 'position'
	 *  indicated by nc_ctx->k as follows:
	 *
	 *    digits="123" count=3 k=0   -->   0.123
	 *    digits="123" count=3 k=1   -->   1.23
	 *    digits="123" count=3 k=5   -->   12300
	 *    digits="123" count=3 k=-1  -->   0.0123
	 *
	 *  Note that the identifier names used for format selection are different
	 *  in Burger-Dybvig paper and ECMAScript specification (quite confusingly
	 *  so, because e.g. 'k' has a totally different meaning in each).  See
	 *  documentation for discussion.
	 *
	 *  ECMAScript doesn't specify any specific behavior for format selection
	 *  (e.g. when to use exponent notation) for non-base-10 numbers.
	 *
	 *  The bigint space in the context is reused for string output, as there
	 *  is more than enough space for that (>1kB at the moment), and we avoid
	 *  allocating even more stack.
	 */

	DUK_ASSERT(DUK__NUMCONV_CTX_BIGINTS_SIZE >= DUK__MAX_FORMATTED_LENGTH);
	DUK_ASSERT(nc_ctx->count >= 1);

	k = nc_ctx->k;
	buf = (duk_uint8_t *) &nc_ctx->f;  /* XXX: union would be more correct */
	q = buf;

	/* Exponent handling: if exponent format is used, record exponent value and
	 * fake k such that one leading digit is generated (e.g. digits=123 -> "1.23").
	 *
	 * toFixed() prevents exponent use; otherwise apply a set of criteria to
	 * match the other API calls (toString(), toPrecision, etc).
	 */

	expt = DUK__NO_EXP;
	if (!nc_ctx->abs_pos /* toFixed() */) {
		if ((flags & DUK_N2S_FLAG_FORCE_EXP) ||             /* exponential notation forced */
		    ((flags & DUK_N2S_FLAG_NO_ZERO_PAD) &&          /* fixed precision and zero padding would be required */
	             (k - digits >= 1)) ||                          /* (e.g. k=3, digits=2 -> "12X") */
		    ((k > 21 || k <= -6) && (radix == 10))) {       /* toString() conditions */
			DUK_DDD(DUK_DDDPRINT("use exponential notation: k=%ld -> expt=%ld",
			                     (long) k, (long) (k - 1)));
			expt = k - 1;  /* e.g. 12.3 -> digits="123" k=2 -> 1.23e1 */
			k = 1;  /* generate mantissa with a single leading whole number digit */
		}
	}

	if (neg) {
		*q++ = '-';
	}

	/* Start position (inclusive) and end position (exclusive) */
	pos = (k >= 1 ? k : 1);
	if (nc_ctx->is_fixed) {
		if (nc_ctx->abs_pos) {
			/* toFixed() */
			pos_end = -digits;
		} else {
			pos_end = k - digits;
		}
	} else {
		pos_end = k - nc_ctx->count;
	}
	if (pos_end > 0) {
		pos_end = 0;
	}

	DUK_DDD(DUK_DDDPRINT("expt=%ld, k=%ld, count=%ld, pos=%ld, pos_end=%ld, is_fixed=%ld, "
	                     "digits=%ld, abs_pos=%ld",
	                     (long) expt, (long) k, (long) nc_ctx->count, (long) pos, (long) pos_end,
	                     (long) nc_ctx->is_fixed, (long) digits, (long) nc_ctx->abs_pos));

	/* Digit generation */
	while (pos > pos_end) {
		DUK_DDD(DUK_DDDPRINT("digit generation: pos=%ld, pos_end=%ld",
		                     (long) pos, (long) pos_end));
		if (pos == 0) {
			*q++ = (duk_uint8_t) '.';
		}
		if (pos > k) {
			*q++ = (duk_uint8_t) '0';
		} else if (pos <= k - nc_ctx->count) {
			*q++ = (duk_uint8_t) '0';
		} else {
			dig = nc_ctx->digits[k - pos];
			DUK_ASSERT(dig >= 0 && dig < nc_ctx->B);
			*q++ = (duk_uint8_t) DUK__DIGITCHAR(dig);
		}

		pos--;
	}
	DUK_ASSERT(pos <= 1);

	/* Exponent */
	if (expt != DUK__NO_EXP) {
		/*
		 *  Exponent notation for non-base-10 numbers isn't specified in ECMAScript
		 *  specification, as it never explicitly turns up: non-decimal numbers can
		 *  only be formatted with Number.prototype.toString([radix]) and for that,
		 *  behavior is not explicitly specified.
		 *
		 *  Logical choices include formatting the exponent as decimal (e.g. binary
		 *  100000 as 1e+5) or in current radix (e.g. binary 100000 as 1e+101).
		 *  The Dragon4 algorithm (in the original paper) prints the exponent value
		 *  in the target radix B.  However, for radix values 15 and above, the
		 *  exponent separator 'e' is no longer easily parseable.  Consider, for
		 *  instance, the number "1.faecee+1c".
		 */

		duk_size_t len;
		char expt_sign;

		*q++ = 'e';
		if (expt >= 0) {
			expt_sign = '+';
		} else {
			expt_sign = '-';
			expt = -expt;
		}
		*q++ = (duk_uint8_t) expt_sign;
		len = duk__dragon4_format_uint32(q, (duk_uint32_t) expt, radix);
		q += len;
	}

	duk_push_lstring(thr, (const char *) buf, (size_t) (q - buf));
}

/*
 *  Conversion helpers
 */

DUK_LOCAL void duk__dragon4_double_to_ctx(duk__numconv_stringify_ctx *nc_ctx, duk_double_t x) {
	duk_double_union u;
	duk_uint32_t tmp;
	duk_small_int_t expt;

	/*
	 *    seeeeeee eeeeffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff
	 *       A        B        C        D        E        F        G        H
	 *
	 *    s       sign bit
	 *    eee...  exponent field
	 *    fff...  fraction
	 *
	 *    ieee value = 1.ffff... * 2^(e - 1023)  (normal)
	 *               = 0.ffff... * 2^(-1022)     (denormal)
	 *
	 *    algorithm v = f * b^e
	 */

	DUK_DBLUNION_SET_DOUBLE(&u, x);

	nc_ctx->f.n = 2;

	tmp = DUK_DBLUNION_GET_LOW32(&u);
	nc_ctx->f.v[0] = tmp;
	tmp = DUK_DBLUNION_GET_HIGH32(&u);
	nc_ctx->f.v[1] = tmp & 0x000fffffUL;
	expt = (duk_small_int_t) ((tmp >> 20) & 0x07ffUL);

	if (expt == 0) {
		/* denormal */
		expt = DUK__IEEE_DOUBLE_EXP_MIN - 52;
		duk__bi_normalize(&nc_ctx->f);
	} else {
		/* normal: implicit leading 1-bit */
		nc_ctx->f.v[1] |= 0x00100000UL;
		expt = expt - DUK__IEEE_DOUBLE_EXP_BIAS - 52;
		DUK_ASSERT(duk__bi_is_valid(&nc_ctx->f));  /* true, because v[1] has at least one bit set */
	}

	DUK_ASSERT(duk__bi_is_valid(&nc_ctx->f));

	nc_ctx->e = expt;
}

DUK_LOCAL void duk__dragon4_ctx_to_double(duk__numconv_stringify_ctx *nc_ctx, duk_double_t *x) {
	duk_double_union u;
	duk_small_int_t expt;
	duk_small_int_t i;
	duk_small_int_t bitstart;
	duk_small_int_t bitround;
	duk_small_int_t bitidx;
	duk_small_int_t skip_round;
	duk_uint32_t t, v;

	DUK_ASSERT(nc_ctx->count == 53 + 1);

	/* Sometimes this assert is not true right now; it will be true after
	 * rounding.  See: test-bug-numconv-mantissa-assert.js.
	 */
	DUK_ASSERT_DISABLE(nc_ctx->digits[0] == 1);  /* zero handled by caller */

	/* Should not be required because the code below always sets both high
	 * and low parts, but at least gcc-4.4.5 fails to deduce this correctly
	 * (perhaps because the low part is set (seemingly) conditionally in a
	 * loop), so this is here to avoid the bogus warning.
	 */
	duk_memzero((void *) &u, sizeof(u));

	/*
	 *  Figure out how generated digits match up with the mantissa,
	 *  and then perform rounding.  If mantissa overflows, need to
	 *  recompute the exponent (it is bumped and may overflow to
	 *  infinity).
	 *
	 *  For normal numbers the leading '1' is hidden and ignored,
	 *  and the last bit is used for rounding:
	 *
	 *                          rounding pt
	 *       <--------52------->|
	 *     1 x x x x ... x x x x|y  ==>  x x x x ... x x x x
	 *
	 *  For denormals, the leading '1' is included in the number,
	 *  and the rounding point is different:
	 *
	 *                      rounding pt
	 *     <--52 or less--->|
	 *     1 x x x x ... x x|x x y  ==>  0 0 ... 1 x x ... x x
	 *
	 *  The largest denormals will have a mantissa beginning with
	 *  a '1' (the explicit leading bit); smaller denormals will
	 *  have leading zero bits.
	 *
	 *  If the exponent would become too high, the result becomes
	 *  Infinity.  If the exponent is so small that the entire
	 *  mantissa becomes zero, the result becomes zero.
	 *
	 *  Note: the Dragon4 'k' is off-by-one with respect to the IEEE
	 *  exponent.  For instance, k==0 indicates that the leading '1'
	 *  digit is at the first binary fraction position (0.1xxx...);
	 *  the corresponding IEEE exponent would be -1.
	 */

	skip_round = 0;

 recheck_exp:

	expt = nc_ctx->k - 1;   /* IEEE exp without bias */
	if (expt > 1023) {
		/* Infinity */
		bitstart = -255;  /* needed for inf: causes mantissa to become zero,
		                   * and rounding to be skipped.
		                   */
		expt = 2047;
	} else if (expt >= -1022) {
		/* normal */
		bitstart = 1;  /* skip leading digit */
		expt += DUK__IEEE_DOUBLE_EXP_BIAS;
		DUK_ASSERT(expt >= 1 && expt <= 2046);
	} else {
		/* denormal or zero */
		bitstart = 1023 + expt;  /* expt==-1023 -> bitstart=0 (leading 1);
		                          * expt==-1024 -> bitstart=-1 (one left of leading 1), etc
		                          */
		expt = 0;
	}
	bitround = bitstart + 52;

	DUK_DDD(DUK_DDDPRINT("ieee expt=%ld, bitstart=%ld, bitround=%ld",
	                     (long) expt, (long) bitstart, (long) bitround));

	if (!skip_round) {
		if (duk__dragon4_fixed_format_round(nc_ctx, bitround)) {
			/* Corner case: see test-numconv-parse-mant-carry.js.  We could
			 * just bump the exponent and update bitstart, but it's more robust
			 * to recompute (but avoid rounding twice).
			 */
			DUK_DDD(DUK_DDDPRINT("rounding caused exponent to be bumped, recheck exponent"));
			skip_round = 1;
			goto recheck_exp;
		}
	}

	/*
	 *  Create mantissa
	 */

	t = 0;
	for (i = 0; i < 52; i++) {
		bitidx = bitstart + 52 - 1 - i;
		if (bitidx >= nc_ctx->count) {
			v = 0;
		} else if (bitidx < 0) {
			v = 0;
		} else {
			v = nc_ctx->digits[bitidx];
		}
		DUK_ASSERT(v == 0 || v == 1);
		t += v << (i % 32);
		if (i == 31) {
			/* low 32 bits is complete */
			DUK_DBLUNION_SET_LOW32(&u, t);
			t = 0;
		}
	}
	/* t has high mantissa */

	DUK_DDD(DUK_DDDPRINT("mantissa is complete: %08lx %08lx",
	                     (unsigned long) t,
	                     (unsigned long) DUK_DBLUNION_GET_LOW32(&u)));

	DUK_ASSERT(expt >= 0 && expt <= 0x7ffL);
	t += ((duk_uint32_t) expt) << 20;
#if 0  /* caller handles sign change */
	if (negative) {
		t |= 0x80000000U;
	}
#endif
	DUK_DBLUNION_SET_HIGH32(&u, t);

	DUK_DDD(DUK_DDDPRINT("number is complete: %08lx %08lx",
	                     (unsigned long) DUK_DBLUNION_GET_HIGH32(&u),
	                     (unsigned long) DUK_DBLUNION_GET_LOW32(&u)));

	*x = DUK_DBLUNION_GET_DOUBLE(&u);
}

/*
 *  Exposed number-to-string API
 *
 *  Input: [ number ]
 *  Output: [ string ]
 */

DUK_LOCAL DUK_NOINLINE void duk__numconv_stringify_raw(duk_hthread *thr, duk_small_int_t radix, duk_small_int_t digits, duk_small_uint_t flags) {
	duk_double_t x;
	duk_small_int_t c;
	duk_small_int_t neg;
	duk_uint32_t uval;
	duk__numconv_stringify_ctx nc_ctx_alloc;  /* large context; around 2kB now */
	duk__numconv_stringify_ctx *nc_ctx = &nc_ctx_alloc;

	x = (duk_double_t) duk_require_number(thr, -1);
	duk_pop(thr);

	/*
	 *  Handle special cases (NaN, infinity, zero).
	 */

	c = (duk_small_int_t) DUK_FPCLASSIFY(x);
	if (DUK_SIGNBIT((double) x)) {
		x = -x;
		neg = 1;
	} else {
		neg = 0;
	}

	/* NaN sign bit is platform specific with unpacked, un-normalized NaNs */
	DUK_ASSERT(c == DUK_FP_NAN || DUK_SIGNBIT((double) x) == 0);

	if (c == DUK_FP_NAN) {
		duk_push_hstring_stridx(thr, DUK_STRIDX_NAN);
		return;
	} else if (c == DUK_FP_INFINITE) {
		if (neg) {
			/* -Infinity */
			duk_push_hstring_stridx(thr, DUK_STRIDX_MINUS_INFINITY);
		} else {
			/* Infinity */
			duk_push_hstring_stridx(thr, DUK_STRIDX_INFINITY);
		}
		return;
	} else if (c == DUK_FP_ZERO) {
		/* We can't shortcut zero here if it goes through special formatting
		 * (such as forced exponential notation).
		 */
		;
	}

	/*
	 *  Handle integers in 32-bit range (that is, [-(2**32-1),2**32-1])
	 *  specially, as they're very likely for embedded programs.  This
	 *  is now done for all radix values.  We must be careful not to use
	 *  the fast path when special formatting (e.g. forced exponential)
	 *  is in force.
	 *
	 *  XXX: could save space by supporting radix 10 only and using
	 *  sprintf "%lu" for the fast path and for exponent formatting.
	 */

	uval = duk_double_to_uint32_t(x);
	if (duk_double_equals((double) uval, x) &&  /* integer number in range */
	    flags == 0) {                           /* no special formatting */
		/* use bigint area as a temp */
		duk_uint8_t *buf = (duk_uint8_t *) (&nc_ctx->f);
		duk_uint8_t *p = buf;

		DUK_ASSERT(DUK__NUMCONV_CTX_BIGINTS_SIZE >= 32 + 1);  /* max size: radix=2 + sign */
		if (neg && uval != 0) {
			/* no negative sign for zero */
			*p++ = (duk_uint8_t) '-';
		}
		p += duk__dragon4_format_uint32(p, uval, radix);
		duk_push_lstring(thr, (const char *) buf, (duk_size_t) (p - buf));
		return;
	}

	/*
	 *  Dragon4 setup.
	 *
	 *  Convert double from IEEE representation for conversion;
	 *  normal finite values have an implicit leading 1-bit.  The
	 *  slow path algorithm doesn't handle zero, so zero is special
	 *  cased here but still creates a valid nc_ctx, and goes
	 *  through normal formatting in case special formatting has
	 *  been requested (e.g. forced exponential format: 0 -> "0e+0").
	 */

	/* Would be nice to bulk clear the allocation, but the context
	 * is 1-2 kilobytes and nothing should rely on it being zeroed.
	 */
#if 0
	duk_memzero((void *) nc_ctx, sizeof(*nc_ctx));  /* slow init, do only for slow path cases */
#endif

	nc_ctx->is_s2n = 0;
	nc_ctx->b = 2;
	nc_ctx->B = radix;
	nc_ctx->abs_pos = 0;
	if (flags & DUK_N2S_FLAG_FIXED_FORMAT) {
		nc_ctx->is_fixed = 1;
		if (flags & DUK_N2S_FLAG_FRACTION_DIGITS) {
			/* absolute req_digits; e.g. digits = 1 -> last digit is 0,
			 * but add an extra digit for rounding.
			 */
			nc_ctx->abs_pos = 1;
			nc_ctx->req_digits = (-digits + 1) - 1;
		} else {
			nc_ctx->req_digits = digits + 1;
		}
	} else {
		nc_ctx->is_fixed = 0;
		nc_ctx->req_digits = 0;
	}

	if (c == DUK_FP_ZERO) {
		/* Zero special case: fake requested number of zero digits; ensure
		 * no sign bit is printed.  Relative and absolute fixed format
		 * require separate handling.
		 */
		duk_small_int_t count;
		if (nc_ctx->is_fixed) {
			if (nc_ctx->abs_pos) {
				count = digits + 2;  /* lead zero + 'digits' fractions + 1 for rounding */
			} else {
				count = digits + 1;  /* + 1 for rounding */
			}
		} else {
			count = 1;
		}
		DUK_DDD(DUK_DDDPRINT("count=%ld", (long) count));
		DUK_ASSERT(count >= 1);
		duk_memzero((void *) nc_ctx->digits, (size_t) count);
		nc_ctx->count = count;
		nc_ctx->k = 1;  /* 0.000... */
		neg = 0;
		goto zero_skip;
	}

	duk__dragon4_double_to_ctx(nc_ctx, x);   /* -> sets 'f' and 'e' */
	DUK__BI_PRINT("f", &nc_ctx->f);
	DUK_DDD(DUK_DDDPRINT("e=%ld", (long) nc_ctx->e));

	/*
	 *  Dragon4 slow path digit generation.
	 */

	duk__dragon4_prepare(nc_ctx);  /* setup many variables in nc_ctx */

	DUK_DDD(DUK_DDDPRINT("after prepare:"));
	DUK__BI_PRINT("r", &nc_ctx->r);
	DUK__BI_PRINT("s", &nc_ctx->s);
	DUK__BI_PRINT("mp", &nc_ctx->mp);
	DUK__BI_PRINT("mm", &nc_ctx->mm);

	duk__dragon4_scale(nc_ctx);

	DUK_DDD(DUK_DDDPRINT("after scale; k=%ld", (long) nc_ctx->k));
	DUK__BI_PRINT("r", &nc_ctx->r);
	DUK__BI_PRINT("s", &nc_ctx->s);
	DUK__BI_PRINT("mp", &nc_ctx->mp);
	DUK__BI_PRINT("mm", &nc_ctx->mm);

	duk__dragon4_generate(nc_ctx);

	/*
	 *  Convert and push final string.
	 */

 zero_skip:

	if (flags & DUK_N2S_FLAG_FIXED_FORMAT) {
		/* Perform fixed-format rounding. */
		duk_small_int_t roundpos;
		if (flags & DUK_N2S_FLAG_FRACTION_DIGITS) {
			/* 'roundpos' is relative to nc_ctx->k and increases to the right
			 * (opposite of how 'k' changes).
			 */
			roundpos = -digits;  /* absolute position for digit considered for rounding */
			roundpos = nc_ctx->k - roundpos;
		} else {
			roundpos = digits;
		}
		DUK_DDD(DUK_DDDPRINT("rounding: k=%ld, count=%ld, digits=%ld, roundpos=%ld",
		                     (long) nc_ctx->k, (long) nc_ctx->count, (long) digits, (long) roundpos));
		(void) duk__dragon4_fixed_format_round(nc_ctx, roundpos);

		/* Note: 'count' is currently not adjusted by rounding (i.e. the
		 * digits are not "chopped off".  That shouldn't matter because
		 * the digit position (absolute or relative) is passed on to the
		 * convert-and-push function.
		 */
	}

	duk__dragon4_convert_and_push(nc_ctx, thr, radix, digits, flags, neg);
}

DUK_INTERNAL void duk_numconv_stringify(duk_hthread *thr, duk_small_int_t radix, duk_small_int_t digits, duk_small_uint_t flags) {
	duk_native_stack_check(thr);
	duk__numconv_stringify_raw(thr, radix, digits, flags);
}

/*
 *  Exposed string-to-number API
 *
 *  Input: [ string ]
 *  Output: [ number ]
 *
 *  If number parsing fails, a NaN is pushed as the result.  If number parsing
 *  fails due to an internal error, an InternalError is thrown.
 */

DUK_LOCAL DUK_NOINLINE void duk__numconv_parse_raw(duk_hthread *thr, duk_small_int_t radix, duk_small_uint_t flags) {
	duk__numconv_stringify_ctx nc_ctx_alloc;  /* large context; around 2kB now */
	duk__numconv_stringify_ctx *nc_ctx = &nc_ctx_alloc;
	duk_double_t res;
	duk_hstring *h_str;
	duk_int_t expt;
	duk_bool_t expt_neg;
	duk_small_int_t expt_adj;
	duk_small_int_t neg;
	duk_small_int_t dig;
	duk_small_int_t dig_whole;
	duk_small_int_t dig_lzero;
	duk_small_int_t dig_frac;
	duk_small_int_t dig_expt;
	duk_small_int_t dig_prec;
	const duk__exp_limits *explim;
	const duk_uint8_t *p;
	duk_small_int_t ch;

	DUK_DDD(DUK_DDDPRINT("parse number: %!T, radix=%ld, flags=0x%08lx",
	                     (duk_tval *) duk_get_tval(thr, -1),
	                     (long) radix, (unsigned long) flags));

	DUK_ASSERT(radix >= 2 && radix <= 36);
	DUK_ASSERT(radix - 2 < (duk_small_int_t) sizeof(duk__str2num_digits_for_radix));

	/*
	 *  Preliminaries: trim, sign, Infinity check
	 *
	 *  We rely on the interned string having a NUL terminator, which will
	 *  cause a parse failure wherever it is encountered.  As a result, we
	 *  don't need separate pointer checks.
	 *
	 *  There is no special parsing for 'NaN' in the specification although
	 *  'Infinity' (with an optional sign) is allowed in some contexts.
	 *  Some contexts allow plus/minus sign, while others only allow the
	 *  minus sign (like JSON.parse()).
	 *
	 *  Automatic hex number detection (leading '0x' or '0X') and octal
	 *  number detection (leading '0' followed by at least one octal digit)
	 *  is done here too.
	 *
	 *  Symbols are not explicitly rejected here (that's up to the caller).
	 *  If a symbol were passed here, it should ultimately safely fail
	 *  parsing due to a syntax error.
	 */

	if (flags & DUK_S2N_FLAG_TRIM_WHITE) {
		/* Leading / trailing whitespace is sometimes accepted and
		 * sometimes not.  After white space trimming, all valid input
		 * characters are pure ASCII.
		 */
		duk_trim(thr, -1);
	}
	h_str = duk_require_hstring(thr, -1);
	DUK_ASSERT(h_str != NULL);
	p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_str);

	neg = 0;
	ch = *p;
	if (ch == (duk_small_int_t) '+') {
		if ((flags & DUK_S2N_FLAG_ALLOW_PLUS) == 0) {
			DUK_DDD(DUK_DDDPRINT("parse failed: leading plus sign not allowed"));
			goto parse_fail;
		}
		p++;
	} else if (ch == (duk_small_int_t) '-') {
		if ((flags & DUK_S2N_FLAG_ALLOW_MINUS) == 0) {
			DUK_DDD(DUK_DDDPRINT("parse failed: leading minus sign not allowed"));
			goto parse_fail;
		}
		p++;
		neg = 1;
	}

	if ((flags & DUK_S2N_FLAG_ALLOW_INF) && DUK_STRNCMP((const char *) p, "Infinity", 8) == 0) {
		/* Don't check for Infinity unless the context allows it.
		 * 'Infinity' is a valid integer literal in e.g. base-36:
		 *
		 *   parseInt('Infinity', 36)
		 *   1461559270678
		 */

		if ((flags & DUK_S2N_FLAG_ALLOW_GARBAGE) == 0 && p[8] != DUK_ASC_NUL) {
			DUK_DDD(DUK_DDDPRINT("parse failed: trailing garbage after matching 'Infinity' not allowed"));
			goto parse_fail;
		} else {
			res = DUK_DOUBLE_INFINITY;
			goto negcheck_and_ret;
		}
	}
	ch = *p;
	if (ch == (duk_small_int_t) '0') {
		duk_small_int_t detect_radix = 0;
		ch = DUK_LOWERCASE_CHAR_ASCII(p[1]);  /* 'x' or 'X' -> 'x' */
		if ((flags & DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT) && ch == DUK_ASC_LC_X) {
			DUK_DDD(DUK_DDDPRINT("detected 0x/0X hex prefix, changing radix and preventing fractions and exponent"));
			detect_radix = 16;
#if 0
		} else if ((flags & DUK_S2N_FLAG_ALLOW_AUTO_LEGACY_OCT_INT) &&
		           (ch >= (duk_small_int_t) '0' && ch <= (duk_small_int_t) '9')) {
			DUK_DDD(DUK_DDDPRINT("detected 0n oct prefix, changing radix and preventing fractions and exponent"));
			detect_radix = 8;

			/* NOTE: if this legacy octal case is added back, it has
			 * different flags and 'p' advance so this needs to be
			 * reworked.
			 */
			flags |= DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO;  /* interpret e.g. '09' as '0', not NaN */
			p += 1;
#endif
		} else if ((flags & DUK_S2N_FLAG_ALLOW_AUTO_OCT_INT) && ch == DUK_ASC_LC_O) {
			DUK_DDD(DUK_DDDPRINT("detected 0o oct prefix, changing radix and preventing fractions and exponent"));
			detect_radix = 8;
		} else if ((flags & DUK_S2N_FLAG_ALLOW_AUTO_BIN_INT) && ch == DUK_ASC_LC_B) {
			DUK_DDD(DUK_DDDPRINT("detected 0b bin prefix, changing radix and preventing fractions and exponent"));
			detect_radix = 2;
		}
		if (detect_radix > 0) {
			radix = detect_radix;
			/* Clear empty as zero flag: interpret e.g. '0x' and '0xg' as a NaN (= parse error) */
			flags &= ~(DUK_S2N_FLAG_ALLOW_EXP | DUK_S2N_FLAG_ALLOW_EMPTY_FRAC |
			           DUK_S2N_FLAG_ALLOW_FRAC | DUK_S2N_FLAG_ALLOW_NAKED_FRAC |
			           DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO);
			flags |= DUK_S2N_FLAG_ALLOW_LEADING_ZERO;  /* allow e.g. '0x0009' and '0b00010001' */
			p += 2;
		}
	}

	/*
	 *  Scan number and setup for Dragon4.
	 *
	 *  The fast path case is detected during setup: an integer which
	 *  can be converted without rounding, no net exponent.  The fast
	 *  path could be implemented as a separate scan, but may not really
	 *  be worth it: the multiplications for building 'f' are not
	 *  expensive when 'f' is small.
	 *
	 *  The significand ('f') must contain enough bits of (apparent)
	 *  accuracy, so that Dragon4 will generate enough binary output digits.
	 *  For decimal numbers, this means generating a 20-digit significand,
	 *  which should yield enough practical accuracy to parse IEEE doubles.
	 *  In fact, the ECMAScript specification explicitly allows an
	 *  implementation to treat digits beyond 20 as zeroes (and even
	 *  to round the 20th digit upwards).  For non-decimal numbers, the
	 *  appropriate number of digits has been precomputed for comparable
	 *  accuracy.
	 *
	 *  Digit counts:
	 *
	 *    [ dig_lzero ]
	 *      |
	 *     .+-..---[ dig_prec ]----.
	 *     |  ||                   |
	 *     0000123.456789012345678901234567890e+123456
	 *     |     | |                         |  |    |
	 *     `--+--' `------[ dig_frac ]-------'  `-+--'
	 *        |                                   |
	 *    [ dig_whole ]                       [ dig_expt ]
	 *
	 *    dig_frac and dig_expt are -1 if not present
	 *    dig_lzero is only computed for whole number part
	 *
	 *  Parsing state
	 *
	 *     Parsing whole part      dig_frac < 0 AND dig_expt < 0
	 *     Parsing fraction part   dig_frac >= 0 AND dig_expt < 0
	 *     Parsing exponent part   dig_expt >= 0   (dig_frac may be < 0 or >= 0)
	 *
	 *  Note: in case we hit an implementation limit (like exponent range),
	 *  we should throw an error, NOT return NaN or Infinity.  Even with
	 *  very large exponent (or significand) values the final result may be
	 *  finite, so NaN/Infinity would be incorrect.
	 */

	duk__bi_set_small(&nc_ctx->f, 0);
	dig_prec = 0;
	dig_lzero = 0;
	dig_whole = 0;
	dig_frac = -1;
	dig_expt = -1;
	expt = 0;
	expt_adj = 0;  /* essentially tracks digit position of lowest 'f' digit */
	expt_neg = 0;
	for (;;) {
		ch = *p++;

		DUK_DDD(DUK_DDDPRINT("parse digits: p=%p, ch='%c' (%ld), expt=%ld, expt_adj=%ld, "
		                     "dig_whole=%ld, dig_frac=%ld, dig_expt=%ld, dig_lzero=%ld, dig_prec=%ld",
		                     (const void *) p, (int) ((ch >= 0x20 && ch <= 0x7e) ? ch : '?'), (long) ch,
		                     (long) expt, (long) expt_adj, (long) dig_whole, (long) dig_frac,
		                     (long) dig_expt, (long) dig_lzero, (long) dig_prec));
		DUK__BI_PRINT("f", &nc_ctx->f);

		/* Most common cases first. */
		if (ch >= (duk_small_int_t) '0' && ch <= (duk_small_int_t) '9') {
			dig = (duk_small_int_t) ch - '0' + 0;
		} else if (ch == (duk_small_int_t) '.') {
			/* A leading digit is not required in some cases, e.g. accept ".123".
			 * In other cases (JSON.parse()) a leading digit is required.  This
			 * is checked for after the loop.
			 */
			if (dig_frac >= 0 || dig_expt >= 0) {
				if (flags & DUK_S2N_FLAG_ALLOW_GARBAGE) {
					DUK_DDD(DUK_DDDPRINT("garbage termination (invalid period)"));
					break;
				} else {
					DUK_DDD(DUK_DDDPRINT("parse failed: period not allowed"));
					goto parse_fail;
				}
			}

			if ((flags & DUK_S2N_FLAG_ALLOW_FRAC) == 0) {
				/* Some contexts don't allow fractions at all; this can't be a
				 * post-check because the state ('f' and expt) would be incorrect.
				 */
				if (flags & DUK_S2N_FLAG_ALLOW_GARBAGE) {
					DUK_DDD(DUK_DDDPRINT("garbage termination (invalid first period)"));
					break;
				} else {
					DUK_DDD(DUK_DDDPRINT("parse failed: fraction part not allowed"));
				}
			}

			DUK_DDD(DUK_DDDPRINT("start fraction part"));
			dig_frac = 0;
			continue;
		} else if (ch == (duk_small_int_t) 0) {
			DUK_DDD(DUK_DDDPRINT("NUL termination"));
			break;
		} else if ((flags & DUK_S2N_FLAG_ALLOW_EXP) &&
		           dig_expt < 0 && (ch == (duk_small_int_t) 'e' || ch == (duk_small_int_t) 'E')) {
			/* Note: we don't parse back exponent notation for anything else
			 * than radix 10, so this is not an ambiguous check (e.g. hex
			 * exponent values may have 'e' either as a significand digit
			 * or as an exponent separator).
			 *
			 * If the exponent separator occurs twice, 'e' will be interpreted
			 * as a digit (= 14) and will be rejected as an invalid decimal
			 * digit.
			 */

			DUK_DDD(DUK_DDDPRINT("start exponent part"));

			/* Exponent without a sign or with a +/- sign is accepted
			 * by all call sites (even JSON.parse()).
			 */
			ch = *p;
			if (ch == (duk_small_int_t) '-') {
				expt_neg = 1;
				p++;
			} else if (ch == (duk_small_int_t) '+') {
				p++;
			}
			dig_expt = 0;
			continue;
		} else if (ch >= (duk_small_int_t) 'a' && ch <= (duk_small_int_t) 'z') {
			dig = (duk_small_int_t) (ch - (duk_small_int_t) 'a' + 0x0a);
		} else if (ch >= (duk_small_int_t) 'A' && ch <= (duk_small_int_t) 'Z') {
			dig = (duk_small_int_t) (ch - (duk_small_int_t) 'A' + 0x0a);
		} else {
			dig = 255;  /* triggers garbage digit check below */
		}
		DUK_ASSERT((dig >= 0 && dig <= 35) || dig == 255);

		if (dig >= radix) {
			if (flags & DUK_S2N_FLAG_ALLOW_GARBAGE) {
				DUK_DDD(DUK_DDDPRINT("garbage termination"));
				break;
			} else {
				DUK_DDD(DUK_DDDPRINT("parse failed: trailing garbage or invalid digit"));
				goto parse_fail;
			}
		}

		if (dig_expt < 0) {
			/* whole or fraction digit */

			if (dig_prec < duk__str2num_digits_for_radix[radix - 2]) {
				/* significant from precision perspective */

				duk_small_int_t f_zero = duk__bi_is_zero(&nc_ctx->f);
				if (f_zero && dig == 0) {
					/* Leading zero is not counted towards precision digits; not
					 * in the integer part, nor in the fraction part.
					 */
					if (dig_frac < 0) {
						dig_lzero++;
					}
				} else {
					/* XXX: join these ops (multiply-accumulate), but only if
					 * code footprint decreases.
					 */
					duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->f, (duk_uint32_t) radix);
					duk__bi_add_small(&nc_ctx->f, &nc_ctx->t1, (duk_uint32_t) dig);
					dig_prec++;
				}
			} else {
				/* Ignore digits beyond a radix-specific limit, but note them
				 * in expt_adj.
				 */
				expt_adj++;
			}

			if (dig_frac >= 0) {
				dig_frac++;
				expt_adj--;
			} else {
				dig_whole++;
			}
		} else {
			/* exponent digit */

			DUK_ASSERT(radix == 10);
			expt = expt * radix + dig;
			if (expt > DUK_S2N_MAX_EXPONENT) {
				/* Impose a reasonable exponent limit, so that exp
				 * doesn't need to get tracked using a bigint.
				 */
				DUK_DDD(DUK_DDDPRINT("parse failed: exponent too large"));
				goto parse_explimit_error;
			}
			dig_expt++;
		}
	}

	/* Leading zero. */

	if (dig_lzero > 0 && dig_whole > 1) {
		if ((flags & DUK_S2N_FLAG_ALLOW_LEADING_ZERO) == 0) {
			DUK_DDD(DUK_DDDPRINT("parse failed: leading zeroes not allowed in integer part"));
			goto parse_fail;
		}
	}

	/* Validity checks for various fraction formats ("0.1", ".1", "1.", "."). */

	if (dig_whole == 0) {
		if (dig_frac == 0) {
			/* "." is not accepted in any format */
			DUK_DDD(DUK_DDDPRINT("parse failed: plain period without leading or trailing digits"));
			goto parse_fail;
		} else if (dig_frac > 0) {
			/* ".123" */
			if ((flags & DUK_S2N_FLAG_ALLOW_NAKED_FRAC) == 0) {
				DUK_DDD(DUK_DDDPRINT("parse failed: fraction part not allowed without "
				                     "leading integer digit(s)"));
				goto parse_fail;
			}
		} else {
			/* Empty ("") is allowed in some formats (e.g. Number(''), as zero,
			 * but it must not have a leading +/- sign (GH-2019).  Note that
			 * for Number(), h_str is already trimmed so we can check for zero
			 * length and still get Number('  +  ') == NaN.
			 */
			if ((flags & DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO) == 0) {
				DUK_DDD(DUK_DDDPRINT("parse failed: empty string not allowed (as zero)"));
				goto parse_fail;
			} else if (DUK_HSTRING_GET_BYTELEN(h_str) != 0) {
				DUK_DDD(DUK_DDDPRINT("parse failed: no digits, but not empty (had a +/- sign)"));
				goto parse_fail;
			}
		}
	} else {
		if (dig_frac == 0) {
			/* "123." is allowed in some formats */
			if ((flags & DUK_S2N_FLAG_ALLOW_EMPTY_FRAC) == 0) {
				DUK_DDD(DUK_DDDPRINT("parse failed: empty fractions"));
				goto parse_fail;
			}
		} else if (dig_frac > 0) {
			/* "123.456" */
			;
		} else {
			/* "123" */
			;
		}
	}

	/* Exponent without digits (e.g. "1e" or "1e+").  If trailing garbage is
	 * allowed, ignore exponent part as garbage (= parse as "1", i.e. exp 0).
	 */

	if (dig_expt == 0) {
		if ((flags & DUK_S2N_FLAG_ALLOW_GARBAGE) == 0) {
			DUK_DDD(DUK_DDDPRINT("parse failed: empty exponent"));
			goto parse_fail;
		}
		DUK_ASSERT(expt == 0);
	}

	if (expt_neg) {
		expt = -expt;
	}
	DUK_DDD(DUK_DDDPRINT("expt=%ld, expt_adj=%ld, net exponent -> %ld",
	                     (long) expt, (long) expt_adj, (long) (expt + expt_adj)));
	expt += expt_adj;

	/* Fast path check. */

	if (nc_ctx->f.n <= 1 &&   /* 32-bit value */
	    expt == 0    /* no net exponent */) {
		/* Fast path is triggered for no exponent and also for balanced exponent
		 * and fraction parts, e.g. for "1.23e2" == "123".  Remember to respect
		 * zero sign.
		 */

		/* XXX: could accept numbers larger than 32 bits, e.g. up to 53 bits? */
		DUK_DDD(DUK_DDDPRINT("fast path number parse"));
		if (nc_ctx->f.n == 1) {
			res = (double) nc_ctx->f.v[0];
		} else {
			res = 0.0;
		}
		goto negcheck_and_ret;
	}

	/* Significand ('f') padding. */

	while (dig_prec < duk__str2num_digits_for_radix[radix - 2]) {
		/* Pad significand with "virtual" zero digits so that Dragon4 will
		 * have enough (apparent) precision to work with.
		 */
		DUK_DDD(DUK_DDDPRINT("dig_prec=%ld, pad significand with zero", (long) dig_prec));
		duk__bi_mul_small_copy(&nc_ctx->f, (duk_uint32_t) radix, &nc_ctx->t1);
		DUK__BI_PRINT("f", &nc_ctx->f);
		expt--;
		dig_prec++;
	}

	DUK_DDD(DUK_DDDPRINT("final exponent: %ld", (long) expt));

	/* Detect zero special case. */

	if (nc_ctx->f.n == 0) {
		/* This may happen even after the fast path check, if exponent is
		 * not balanced (e.g. "0e1").  Remember to respect zero sign.
		 */
		DUK_DDD(DUK_DDDPRINT("significand is zero"));
		res = 0.0;
		goto negcheck_and_ret;
	}


	/* Quick reject of too large or too small exponents.  This check
	 * would be incorrect for zero (e.g. "0e1000" is zero, not Infinity)
	 * so zero check must be above.
	 */

	explim = &duk__str2num_exp_limits[radix - 2];
	if (expt > explim->upper) {
		DUK_DDD(DUK_DDDPRINT("exponent too large -> infinite"));
		res = (duk_double_t) DUK_DOUBLE_INFINITY;
		goto negcheck_and_ret;
	} else if (expt < explim->lower) {
		DUK_DDD(DUK_DDDPRINT("exponent too small -> zero"));
		res = (duk_double_t) 0.0;
		goto negcheck_and_ret;
	}

	nc_ctx->is_s2n = 1;
	nc_ctx->e = expt;
	nc_ctx->b = radix;
	nc_ctx->B = 2;
	nc_ctx->is_fixed = 1;
	nc_ctx->abs_pos = 0;
	nc_ctx->req_digits = 53 + 1;

	DUK__BI_PRINT("f", &nc_ctx->f);
	DUK_DDD(DUK_DDDPRINT("e=%ld", (long) nc_ctx->e));

	/*
	 *  Dragon4 slow path (binary) digit generation.
	 *  An extra digit is generated for rounding.
	 */

	duk__dragon4_prepare(nc_ctx);  /* setup many variables in nc_ctx */

	DUK_DDD(DUK_DDDPRINT("after prepare:"));
	DUK__BI_PRINT("r", &nc_ctx->r);
	DUK__BI_PRINT("s", &nc_ctx->s);
	DUK__BI_PRINT("mp", &nc_ctx->mp);
	DUK__BI_PRINT("mm", &nc_ctx->mm);

	duk__dragon4_scale(nc_ctx);

	DUK_DDD(DUK_DDDPRINT("after scale; k=%ld", (long) nc_ctx->k));
	DUK__BI_PRINT("r", &nc_ctx->r);
	DUK__BI_PRINT("s", &nc_ctx->s);
	DUK__BI_PRINT("mp", &nc_ctx->mp);
	DUK__BI_PRINT("mm", &nc_ctx->mm);

	duk__dragon4_generate(nc_ctx);

	DUK_ASSERT(nc_ctx->count == 53 + 1);

	/*
	 *  Convert binary digits into an IEEE double.  Need to handle
	 *  denormals and rounding correctly.
	 *
	 *  Some call sites currently assume the result is always a
	 *  non-fastint double.  If this is changed, check all call
	 *  sites.
	 */

	duk__dragon4_ctx_to_double(nc_ctx, &res);
	goto negcheck_and_ret;

 negcheck_and_ret:
	if (neg) {
		res = -res;
	}
	duk_pop(thr);
	duk_push_number(thr, (double) res);
	DUK_DDD(DUK_DDDPRINT("result: %!T", (duk_tval *) duk_get_tval(thr, -1)));
	return;

 parse_fail:
	DUK_DDD(DUK_DDDPRINT("parse failed"));
	duk_pop(thr);
	duk_push_nan(thr);
	return;

 parse_explimit_error:
	DUK_DDD(DUK_DDDPRINT("parse failed, internal error, can't return a value"));
	DUK_ERROR_RANGE(thr, "exponent too large");
	DUK_WO_NORETURN(return;);
}

DUK_INTERNAL void duk_numconv_parse(duk_hthread *thr, duk_small_int_t radix, duk_small_uint_t flags) {
	duk_native_stack_check(thr);
	duk__numconv_parse_raw(thr, radix, flags);
}

/* automatic undefs */
#undef DUK__BI_MAX_PARTS
#undef DUK__BI_PRINT
#undef DUK__DIGITCHAR
#undef DUK__DRAGON4_OUTPUT_PREINC
#undef DUK__IEEE_DOUBLE_EXP_BIAS
#undef DUK__IEEE_DOUBLE_EXP_MIN
#undef DUK__MAX_FORMATTED_LENGTH
#undef DUK__MAX_OUTPUT_DIGITS
#undef DUK__NO_EXP
#undef DUK__NUMCONV_CTX_BIGINTS_SIZE
#undef DUK__NUMCONV_CTX_NUM_BIGINTS
#line 1 "duk_regexp_compiler.c"
/*
 *  Regexp compilation.
 *
 *  See doc/regexp.rst for a discussion of the compilation approach and
 *  current limitations.
 *
 *  Regexp bytecode assumes jumps can be expressed with signed 32-bit
 *  integers.  Consequently the bytecode size must not exceed 0x7fffffffL.
 *  The implementation casts duk_size_t (buffer size) to duk_(u)int32_t
 *  in many places.  Although this could be changed, the bytecode format
 *  limit would still prevent regexps exceeding the signed 32-bit limit
 *  from working.
 *
 *  XXX: The implementation does not prevent bytecode from exceeding the
 *  maximum supported size.  This could be done by limiting the maximum
 *  input string size (assuming an upper bound can be computed for number
 *  of bytecode bytes emitted per input byte) or checking buffer maximum
 *  size when emitting bytecode (slower).
 */

/* #include duk_internal.h -> already included */

#if defined(DUK_USE_REGEXP_SUPPORT)

/*
 *  Helper macros
 */

#define DUK__RE_INITIAL_BUFSIZE 64

#define DUK__RE_BUFLEN(re_ctx) \
	DUK_BW_GET_SIZE(re_ctx->thr, &re_ctx->bw)

/*
 *  Disjunction struct: result of parsing a disjunction
 */

typedef struct {
	/* Number of characters that the atom matches (e.g. 3 for 'abc'),
	 * -1 if atom is complex and number of matched characters either
	 * varies or is not known.
	 */
	duk_int32_t charlen;

#if 0
	/* These are not needed to implement quantifier capture handling,
	 * but might be needed at some point.
	 */

	/* re_ctx->captures at start and end of atom parsing.
	 * Since 'captures' indicates highest capture number emitted
	 * so far in a DUK_REOP_SAVE, the captures numbers saved by
	 * the atom are: ]start_captures,end_captures].
	 */
	duk_uint32_t start_captures;
	duk_uint32_t end_captures;
#endif
} duk__re_disjunction_info;

/*
 *  Encoding helpers
 *
 *  Some of the typing is bytecode based, e.g. slice sizes are unsigned 32-bit
 *  even though the buffer operations will use duk_size_t.
 */

/* XXX: the insert helpers should ensure that the bytecode result is not
 * larger than expected (or at least assert for it).  Many things in the
 * bytecode, like skip offsets, won't work correctly if the bytecode is
 * larger than say 2G.
 */

DUK_LOCAL duk_uint32_t duk__encode_i32(duk_int32_t x) {
	if (x < 0) {
		return ((duk_uint32_t) (-x)) * 2 + 1;
	} else {
		return ((duk_uint32_t) x) * 2;
	}
}

/* XXX: return type should probably be duk_size_t, or explicit checks are needed for
 * maximum size.
 */
DUK_LOCAL duk_uint32_t duk__insert_u32(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_uint32_t x) {
	duk_uint8_t buf[DUK_UNICODE_MAX_XUTF8_LENGTH];
	duk_small_int_t len;

	len = duk_unicode_encode_xutf8((duk_ucodepoint_t) x, buf);
	DUK_ASSERT(len >= 0);
	DUK_BW_INSERT_ENSURE_BYTES(re_ctx->thr, &re_ctx->bw, offset, buf, (duk_size_t) len);
	return (duk_uint32_t) len;
}

DUK_LOCAL void duk__append_u32(duk_re_compiler_ctx *re_ctx, duk_uint32_t x) {
	DUK_BW_WRITE_ENSURE_XUTF8(re_ctx->thr, &re_ctx->bw, x);
}

DUK_LOCAL void duk__append_7bit(duk_re_compiler_ctx *re_ctx, duk_uint32_t x) {
#if defined(DUK_USE_PREFER_SIZE)
	duk__append_u32(re_ctx, x);
#else
	DUK_ASSERT(x <= 0x7fU);
	DUK_BW_WRITE_ENSURE_U8(re_ctx->thr, &re_ctx->bw, (duk_uint8_t) x);
#endif
}

#if 0
DUK_LOCAL void duk__append_2bytes(duk_re_compiler_ctx *re_ctx, duk_uint8_t x, duk_uint8_t y) {
	DUK_BW_WRITE_ENSURE_U8_2(re_ctx->thr, &re_ctx->bw, x, y);
}
#endif

DUK_LOCAL duk_uint32_t duk__insert_i32(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_int32_t x) {
	return duk__insert_u32(re_ctx, offset, duk__encode_i32(x));
}

DUK_LOCAL void duk__append_reop(duk_re_compiler_ctx *re_ctx, duk_uint32_t reop) {
	DUK_ASSERT(reop <= 0x7fU);
	(void) duk__append_7bit(re_ctx, reop);
}

#if 0  /* unused */
DUK_LOCAL void duk__append_i32(duk_re_compiler_ctx *re_ctx, duk_int32_t x) {
	duk__append_u32(re_ctx, duk__encode_i32(x));
}
#endif

/* special helper for emitting u16 lists (used for character ranges for built-in char classes) */
DUK_LOCAL void duk__append_u16_list(duk_re_compiler_ctx *re_ctx, const duk_uint16_t *values, duk_uint32_t count) {
	/* Call sites don't need the result length so it's not accumulated. */
	while (count-- > 0) {
		duk__append_u32(re_ctx, (duk_uint32_t) (*values++));
	}
}

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) {
	DUK_BW_INSERT_ENSURE_SLICE(re_ctx->thr, &re_ctx->bw, offset, data_offset, data_length);
}

DUK_LOCAL void duk__append_slice(duk_re_compiler_ctx *re_ctx, duk_uint32_t data_offset, duk_uint32_t data_length) {
	DUK_BW_WRITE_ENSURE_SLICE(re_ctx->thr, &re_ctx->bw, data_offset, data_length);
}

DUK_LOCAL void duk__remove_slice(duk_re_compiler_ctx *re_ctx, duk_uint32_t data_offset, duk_uint32_t data_length) {
	DUK_BW_REMOVE_ENSURE_SLICE(re_ctx->thr, &re_ctx->bw, data_offset, data_length);
}

/*
 *  Insert a jump offset at 'offset' to complete an instruction
 *  (the jump offset is always the last component of an instruction).
 *  The 'skip' argument must be computed relative to 'offset',
 *  -without- taking into account the skip field being inserted.
 *
 *       ... A B C ins X Y Z ...   (ins may be a JUMP, SPLIT1/SPLIT2, etc)
 *   =>  ... A B C ins SKIP X Y Z
 *
 *  Computing the final (adjusted) skip value, which is relative to the
 *  first byte of the next instruction, is a bit tricky because of the
 *  variable length UTF-8 encoding.  See doc/regexp.rst for discussion.
 */
DUK_LOCAL duk_uint32_t duk__insert_jump_offset(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_int32_t skip) {
#if 0
	/* Iterative solution. */
	if (skip < 0) {
		duk_small_int_t len;
		/* two encoding attempts suffices */
		len = duk_unicode_get_xutf8_length((duk_codepoint_t) duk__encode_i32(skip));
		len = duk_unicode_get_xutf8_length((duk_codepoint_t) duk__encode_i32(skip - (duk_int32_t) len));
		DUK_ASSERT(duk_unicode_get_xutf8_length(duk__encode_i32(skip - (duk_int32_t) len)) == len);  /* no change */
		skip -= (duk_int32_t) len;
	}
#endif

#if defined(DUK_USE_PREFER_SIZE)
	/* Closed form solution, this produces smallest code.
	 * See re_neg_jump_offset (closed2).
	 */
	if (skip < 0) {
		skip--;
		if (skip < -0x3fL) {
			skip--;
		}
		if (skip < -0x3ffL) {
			skip--;
		}
		if (skip < -0x7fffL) {
			skip--;
		}
		if (skip < -0xfffffL) {
			skip--;
		}
		if (skip < -0x1ffffffL) {
			skip--;
		}
		if (skip < -0x3fffffffL) {
			skip--;
		}
	}
#else  /* DUK_USE_PREFER_SIZE */
	/* Closed form solution, this produces fastest code.
	 * See re_neg_jump_offset (closed1).
	 */
	if (skip < 0) {
		if (skip >= -0x3eL) {
			skip -= 1;
		} else if (skip >= -0x3fdL) {
			skip -= 2;
		} else if (skip >= -0x7ffcL) {
			skip -= 3;
		} else if (skip >= -0xffffbL) {
			skip -= 4;
		} else if (skip >= -0x1fffffaL) {
			skip -= 5;
		} else if (skip >= -0x3ffffff9L) {
			skip -= 6;
		} else {
			skip -= 7;
		}
	}
#endif  /* DUK_USE_PREFER_SIZE */

	return duk__insert_i32(re_ctx, offset, skip);
}

DUK_LOCAL duk_uint32_t duk__append_jump_offset(duk_re_compiler_ctx *re_ctx, duk_int32_t skip) {
	return (duk_uint32_t) duk__insert_jump_offset(re_ctx, (duk_uint32_t) DUK__RE_BUFLEN(re_ctx), skip);
}

/*
 *  duk_re_range_callback for generating character class ranges.
 *
 *  When ignoreCase is false, the range is simply emitted as is.  We don't,
 *  for instance, eliminate duplicates or overlapping ranges in a character
 *  class.
 *
 *  When ignoreCase is true but the 'direct' flag is set, the caller knows
 *  that the range canonicalizes to itself for case insensitive matching,
 *  so the range is emitted as is.  This is mainly useful for built-in ranges
 *  like \W.
 *
 *  Otherwise, when ignoreCase is true, the range needs to be normalized
 *  through canonicalization.  Unfortunately a canonicalized version of a
 *  continuous range is not necessarily continuous (e.g. [x-{] is continuous
 *  but [X-{] is not).  As a result, a single input range may expand to a lot
 *  of output ranges.  The current algorithm creates the canonicalized ranges
 *  footprint efficiently at the cost of compile time execution time; see
 *  doc/regexp.rst for discussion, and some more details below.
 *
 *  Note that the ctx->nranges is a context-wide temporary value.  This is OK
 *  because there cannot be multiple character classes being parsed
 *  simultaneously.
 *
 *  More detail on canonicalization:
 *
 *  Conceptually, a range is canonicalized by scanning the entire range,
 *  normalizing each codepoint by converting it to uppercase, and generating
 *  a set of result ranges.
 *
 *  Ideally a minimal set of output ranges would be emitted by merging all
 *  possible ranges even if they're emitted out of sequence.  Because the
 *  input string is also case normalized during matching, some codepoints
 *  never occur at runtime; these "don't care" codepoints can be included or
 *  excluded from ranges when merging/optimizing ranges.
 *
 *  The current algorithm does not do optimal range merging.  Rather, output
 *  codepoints are generated in sequence, and when the output codepoints are
 *  continuous (CP, CP+1, CP+2, ...), they are merged locally into as large a
 *  range as possible.  A small canonicalization bitmap is used to reduce
 *  actual codepoint canonicalizations which are quite slow at present.  The
 *  bitmap provides a "codepoint block is continuous with respect to
 *  canonicalization" for N-codepoint blocks.  This allows blocks to be
 *  skipped quickly.
 *
 *  There are a number of shortcomings and future work here:
 *
 *    - Individual codepoint normalizations are slow because they involve
 *      walking bit-packed rules without a lookup index.
 *
 *    - The conceptual algorithm needs to canonicalize every codepoint in the
 *      input range to figure out the output range(s).  Even with the small
 *      canonicalization bitmap the algorithm runs quite slowly for worst case
 *      inputs.  There are many data structure alternatives to improve this.
 *
 *    - While the current algorithm generates maximal output ranges when the
 *      output codepoints are emitted linearly, output ranges are not sorted or
 *      merged otherwise.  In the worst case a lot of ranges are emitted when
 *      most of the ranges could be merged.  In this process one could take
 *      advantage of "don't care" codepoints, which are never matched against at
 *      runtime due to canonicalization of input codepoints before comparison,
 *      to merge otherwise discontinuous output ranges.
 *
 *    - The runtime data structure is just a linear list of ranges to match
 *      against.  This can be quite slow if there are a lot of output ranges.
 *      There are various ways to make matching against the ranges faster,
 *      e.g. sorting the ranges and using a binary search; skip lists; tree
 *      based representations; full or approximate codepoint bitmaps, etc.
 *
 *    - Only BMP is supported, codepoints above BMP are assumed to canonicalize
 *      to themselves.  For now this is one place where we don't want to
 *      support chars outside the BMP, because the exhaustive search would be
 *      massively larger.  It would be possible to support non-BMP with a
 *      different algorithm, or perhaps doing case normalization only at match
 *      time.
 */

DUK_LOCAL void duk__regexp_emit_range(duk_re_compiler_ctx *re_ctx, duk_codepoint_t r1, duk_codepoint_t r2) {
	DUK_ASSERT(r2 >= r1);
	duk__append_u32(re_ctx, (duk_uint32_t) r1);
	duk__append_u32(re_ctx, (duk_uint32_t) r2);
	re_ctx->nranges++;
}

#if defined(DUK_USE_REGEXP_CANON_BITMAP)
/* Find next canonicalization discontinuity (conservative estimate) starting
 * from 'start', not exceeding 'end'.  If continuity is fine up to 'end'
 * inclusive, returns end.  Minimum possible return value is start.
 */
DUK_LOCAL duk_codepoint_t duk__re_canon_next_discontinuity(duk_codepoint_t start, duk_codepoint_t end) {
	duk_uint_t start_blk;
	duk_uint_t end_blk;
	duk_uint_t blk;
	duk_uint_t offset;
	duk_uint8_t mask;

	/* Inclusive block range. */
	DUK_ASSERT(start >= 0);
	DUK_ASSERT(end >= 0);
	DUK_ASSERT(end >= start);
	start_blk = (duk_uint_t) (start >> DUK_CANON_BITMAP_BLKSHIFT);
	end_blk = (duk_uint_t) (end >> DUK_CANON_BITMAP_BLKSHIFT);

	for (blk = start_blk; blk <= end_blk; blk++) {
		offset = blk >> 3;
		mask = 1U << (blk & 0x07);
		if (offset >= sizeof(duk_unicode_re_canon_bitmap)) {
			/* Reached non-BMP range which is assumed continuous. */
			return end;
		}
		DUK_ASSERT(offset < sizeof(duk_unicode_re_canon_bitmap));
		if ((duk_unicode_re_canon_bitmap[offset] & mask) == 0) {
			/* Block is discontinuous, continuity is guaranteed
			 * only up to end of previous block (+1 for exclusive
			 * return value => start of current block).  Start
			 * block requires special handling.
			 */
			if (blk > start_blk) {
				return (duk_codepoint_t) (blk << DUK_CANON_BITMAP_BLKSHIFT);
			} else {
				return start;
			}
		}
	}
	DUK_ASSERT(blk == end_blk + 1);  /* Reached end block which is continuous. */
	return end;
}
#else  /* DUK_USE_REGEXP_CANON_BITMAP */
DUK_LOCAL duk_codepoint_t duk__re_canon_next_discontinuity(duk_codepoint_t start, duk_codepoint_t end) {
	DUK_ASSERT(start >= 0);
	DUK_ASSERT(end >= 0);
	DUK_ASSERT(end >= start);
	if (start >= 0x10000) {
		/* Even without the bitmap, treat non-BMP as continuous. */
		return end;
	}
	return start;
}
#endif  /* DUK_USE_REGEXP_CANON_BITMAP */

DUK_LOCAL void duk__regexp_generate_ranges(void *userdata, duk_codepoint_t r1, duk_codepoint_t r2, duk_bool_t direct) {
	duk_re_compiler_ctx *re_ctx = (duk_re_compiler_ctx *) userdata;
	duk_codepoint_t r_start;
	duk_codepoint_t r_end;
	duk_codepoint_t i;
	duk_codepoint_t t;
	duk_codepoint_t r_disc;

	DUK_DD(DUK_DDPRINT("duk__regexp_generate_ranges(): re_ctx=%p, range=[%ld,%ld] direct=%ld",
	                   (void *) re_ctx, (long) r1, (long) r2, (long) direct));

	DUK_ASSERT(r2 >= r1);  /* SyntaxError for out of order range. */

	if (direct || (re_ctx->re_flags & DUK_RE_FLAG_IGNORE_CASE) == 0) {
		DUK_DD(DUK_DDPRINT("direct or not case sensitive, emit range: [%ld,%ld]", (long) r1, (long) r2));
		duk__regexp_emit_range(re_ctx, r1, r2);
		return;
	}

	DUK_DD(DUK_DDPRINT("case sensitive, process range: [%ld,%ld]", (long) r1, (long) r2));

	r_start = duk_unicode_re_canonicalize_char(re_ctx->thr, r1);
	r_end = r_start;

	for (i = r1 + 1; i <= r2;) {
		/* Input codepoint space processed up to i-1, and
		 * current range in r_{start,end} is up-to-date
		 * (inclusive) and may either break or continue.
		 */
		r_disc = duk__re_canon_next_discontinuity(i, r2);
		DUK_ASSERT(r_disc >= i);
		DUK_ASSERT(r_disc <= r2);

		r_end += r_disc - i;  /* May be zero. */
		t = duk_unicode_re_canonicalize_char(re_ctx->thr, r_disc);
		if (t == r_end + 1) {
			/* Not actually a discontinuity, continue range
			 * to r_disc and recheck.
			 */
			r_end = t;
		} else {
			duk__regexp_emit_range(re_ctx, r_start, r_end);
			r_start = t;
			r_end = t;
		}
		i = r_disc + 1;  /* Guarantees progress. */
	}
	duk__regexp_emit_range(re_ctx, r_start, r_end);

#if 0  /* Exhaustive search, very slow. */
	r_start = duk_unicode_re_canonicalize_char(re_ctx->thr, r1);
	r_end = r_start;
	for (i = r1 + 1; i <= r2; i++) {
		t = duk_unicode_re_canonicalize_char(re_ctx->thr, i);
		if (t == r_end + 1) {
			r_end = t;
		} else {
			DUK_DD(DUK_DDPRINT("canonicalized, emit range: [%ld,%ld]", (long) r_start, (long) r_end));
			duk__append_u32(re_ctx, (duk_uint32_t) r_start);
			duk__append_u32(re_ctx, (duk_uint32_t) r_end);
			re_ctx->nranges++;
			r_start = t;
			r_end = t;
		}
	}
	DUK_DD(DUK_DDPRINT("canonicalized, emit range: [%ld,%ld]", (long) r_start, (long) r_end));
	duk__append_u32(re_ctx, (duk_uint32_t) r_start);
	duk__append_u32(re_ctx, (duk_uint32_t) r_end);
	re_ctx->nranges++;
#endif
}

/*
 *  Parse regexp Disjunction.  Most of regexp compilation happens here.
 *
 *  Handles Disjunction, Alternative, and Term productions directly without
 *  recursion.  The only constructs requiring recursion are positive/negative
 *  lookaheads, capturing parentheses, and non-capturing parentheses.
 *
 *  The function determines whether the entire disjunction is a 'simple atom'
 *  (see doc/regexp.rst discussion on 'simple quantifiers') and if so,
 *  returns the atom character length which is needed by the caller to keep
 *  track of its own atom character length.  A disjunction with more than one
 *  alternative is never considered a simple atom (although in some cases
 *  that might be the case).
 *
 *  Return value: simple atom character length or < 0 if not a simple atom.
 *  Appends the bytecode for the disjunction matcher to the end of the temp
 *  buffer.
 *
 *  Regexp top level structure is:
 *
 *    Disjunction = Term*
 *                | Term* | Disjunction
 *
 *    Term = Assertion
 *         | Atom
 *         | Atom Quantifier
 *
 *  An empty Term sequence is a valid disjunction alternative (e.g. /|||c||/).
 *
 *  Notes:
 *
 *    * Tracking of the 'simple-ness' of the current atom vs. the entire
 *      disjunction are separate matters.  For instance, the disjunction
 *      may be complex, but individual atoms may be simple.  Furthermore,
 *      simple quantifiers are used whenever possible, even if the
 *      disjunction as a whole is complex.
 *
 *    * The estimate of whether an atom is simple is conservative now,
 *      and it would be possible to expand it.  For instance, captures
 *      cause the disjunction to be marked complex, even though captures
 *      -can- be handled by simple quantifiers with some minor modifications.
 *
 *    * Disjunction 'tainting' as 'complex' is handled at the end of the
 *      main for loop collectively for atoms.  Assertions, quantifiers,
 *      and '|' tokens need to taint the result manually if necessary.
 *      Assertions cannot add to result char length, only atoms (and
 *      quantifiers) can; currently quantifiers will taint the result
 *      as complex though.
 */

DUK_LOCAL const duk_uint16_t * const duk__re_range_lookup1[3] = {
	duk_unicode_re_ranges_digit,
	duk_unicode_re_ranges_white,
	duk_unicode_re_ranges_wordchar
};
DUK_LOCAL const duk_uint8_t duk__re_range_lookup2[3] = {
	sizeof(duk_unicode_re_ranges_digit) / (2 * sizeof(duk_uint16_t)),
	sizeof(duk_unicode_re_ranges_white) / (2 * sizeof(duk_uint16_t)),
	sizeof(duk_unicode_re_ranges_wordchar) / (2 * sizeof(duk_uint16_t))
};

DUK_LOCAL void duk__append_range_atom_matcher(duk_re_compiler_ctx *re_ctx, duk_small_uint_t re_op, const duk_uint16_t *ranges, duk_small_uint_t count) {
#if 0
	DUK_ASSERT(re_op <= 0x7fUL);
	DUK_ASSERT(count <= 0x7fUL);
	duk__append_2bytes(re_ctx, (duk_uint8_t) re_op, (duk_uint8_t) count);
#endif
	duk__append_reop(re_ctx, re_op);
	duk__append_7bit(re_ctx, count);
	duk__append_u16_list(re_ctx, ranges, count * 2);
}

DUK_LOCAL void duk__parse_disjunction(duk_re_compiler_ctx *re_ctx, duk_bool_t expect_eof, duk__re_disjunction_info *out_atom_info) {
	duk_int32_t atom_start_offset = -1;                   /* negative -> no atom matched on previous round */
	duk_int32_t atom_char_length = 0;                     /* negative -> complex atom */
	duk_uint32_t atom_start_captures = re_ctx->captures;  /* value of re_ctx->captures at start of atom */
	duk_int32_t unpatched_disjunction_split = -1;
	duk_int32_t unpatched_disjunction_jump = -1;
	duk_uint32_t entry_offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx);
	duk_int32_t res_charlen = 0;  /* -1 if disjunction is complex, char length if simple */
	duk__re_disjunction_info tmp_disj;

	DUK_ASSERT(out_atom_info != NULL);

	duk_native_stack_check(re_ctx->thr);
	if (re_ctx->recursion_depth >= re_ctx->recursion_limit) {
		DUK_ERROR_RANGE(re_ctx->thr, DUK_STR_REGEXP_COMPILER_RECURSION_LIMIT);
		DUK_WO_NORETURN(return;);
	}
	re_ctx->recursion_depth++;

#if 0
	out_atom_info->start_captures = re_ctx->captures;
#endif

	for (;;) {
		/* atom_char_length, atom_start_offset, atom_start_offset reflect the
		 * atom matched on the previous loop.  If a quantifier is encountered
		 * on this loop, these are needed to handle the quantifier correctly.
		 * new_atom_char_length etc are for the atom parsed on this round;
		 * they're written to atom_char_length etc at the end of the round.
		 */
		duk_int32_t new_atom_char_length;   /* char length of the atom parsed in this loop */
		duk_int32_t new_atom_start_offset;  /* bytecode start offset of the atom parsed in this loop
		                                     * (allows quantifiers to copy the atom bytecode)
		                                     */
		duk_uint32_t new_atom_start_captures;  /* re_ctx->captures at the start of the atom parsed in this loop */

		duk_lexer_parse_re_token(&re_ctx->lex, &re_ctx->curr_token);

		DUK_DD(DUK_DDPRINT("re token: %ld (num=%ld, char=%c)",
		                   (long) re_ctx->curr_token.t,
		                   (long) re_ctx->curr_token.num,
		                   (re_ctx->curr_token.num >= 0x20 && re_ctx->curr_token.num <= 0x7e) ?
		                   (int) re_ctx->curr_token.num : (int) '?'));

		/* set by atom case clauses */
		new_atom_start_offset = -1;
		new_atom_char_length = -1;
		new_atom_start_captures = re_ctx->captures;

		switch (re_ctx->curr_token.t) {
		case DUK_RETOK_DISJUNCTION: {
			/*
			 *  The handling here is a bit tricky.  If a previous '|' has been processed,
			 *  we have a pending split1 and a pending jump (for a previous match).  These
			 *  need to be back-patched carefully.  See docs for a detailed example.
			 */

			/* patch pending jump and split */
			if (unpatched_disjunction_jump >= 0) {
				duk_uint32_t offset;

				DUK_ASSERT(unpatched_disjunction_split >= 0);
				offset = (duk_uint32_t) unpatched_disjunction_jump;
				offset += duk__insert_jump_offset(re_ctx,
				                                  offset,
				                                  (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - offset));
				/* offset is now target of the pending split (right after jump) */
				duk__insert_jump_offset(re_ctx,
				                        (duk_uint32_t) unpatched_disjunction_split,
				                        (duk_int32_t) offset - unpatched_disjunction_split);
			}

			/* add a new pending split to the beginning of the entire disjunction */
			(void) duk__insert_u32(re_ctx,
			                       entry_offset,
			                       DUK_REOP_SPLIT1);   /* prefer direct execution */
			unpatched_disjunction_split = (duk_int32_t) (entry_offset + 1);   /* +1 for opcode */

			/* add a new pending match jump for latest finished alternative */
			duk__append_reop(re_ctx, DUK_REOP_JUMP);
			unpatched_disjunction_jump = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);

			/* 'taint' result as complex */
			res_charlen = -1;
			break;
		}
		case DUK_RETOK_QUANTIFIER: {
			if (atom_start_offset < 0) {
				DUK_ERROR_SYNTAX(re_ctx->thr, DUK_STR_INVALID_QUANTIFIER_NO_ATOM);
				DUK_WO_NORETURN(return;);
			}
			if (re_ctx->curr_token.qmin > re_ctx->curr_token.qmax) {
				DUK_ERROR_SYNTAX(re_ctx->thr, DUK_STR_INVALID_QUANTIFIER_VALUES);
				DUK_WO_NORETURN(return;);
			}
			if (atom_char_length >= 0) {
				/*
				 *  Simple atom
				 *
				 *  If atom_char_length is zero, we'll have unbounded execution time for e.g.
				 *  /()*x/.exec('x').  We can't just skip the match because it might have some
				 *  side effects (for instance, if we allowed captures in simple atoms, the
				 *  capture needs to happen).  The simple solution below is to force the
				 *  quantifier to match at most once, since the additional matches have no effect.
				 *
				 *  With a simple atom there can be no capture groups, so no captures need
				 *  to be reset.
				 */
				duk_int32_t atom_code_length;
				duk_uint32_t offset;
				duk_uint32_t qmin, qmax;

				qmin = re_ctx->curr_token.qmin;
				qmax = re_ctx->curr_token.qmax;
				if (atom_char_length == 0) {
					/* qmin and qmax will be 0 or 1 */
					if (qmin > 1) {
						qmin = 1;
					}
					if (qmax > 1) {
						qmax = 1;
					}
				}

				duk__append_reop(re_ctx, DUK_REOP_MATCH);   /* complete 'sub atom' */
				atom_code_length = (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - (duk_size_t) atom_start_offset);

				offset = (duk_uint32_t) atom_start_offset;
				if (re_ctx->curr_token.greedy) {
					offset += duk__insert_u32(re_ctx, offset, DUK_REOP_SQGREEDY);
					offset += duk__insert_u32(re_ctx, offset, qmin);
					offset += duk__insert_u32(re_ctx, offset, qmax);
					offset += duk__insert_u32(re_ctx, offset, (duk_uint32_t) atom_char_length);
					offset += duk__insert_jump_offset(re_ctx, offset, atom_code_length);
				} else {
					offset += duk__insert_u32(re_ctx, offset, DUK_REOP_SQMINIMAL);
					offset += duk__insert_u32(re_ctx, offset, qmin);
					offset += duk__insert_u32(re_ctx, offset, qmax);
					offset += duk__insert_jump_offset(re_ctx, offset, atom_code_length);
				}
				DUK_UNREF(offset);  /* silence scan-build warning */
			} else {
				/*
				 *  Complex atom
				 *
				 *  The original code is used as a template, and removed at the end
				 *  (this differs from the handling of simple quantifiers).
				 *
				 *  NOTE: there is no current solution for empty atoms in complex
				 *  quantifiers.  This would need some sort of a 'progress' instruction.
				 *
				 *  XXX: impose limit on maximum result size, i.e. atom_code_len * atom_copies?
				 */
				duk_int32_t atom_code_length;
				duk_uint32_t atom_copies;
				duk_uint32_t tmp_qmin, tmp_qmax;

				/* pre-check how many atom copies we're willing to make (atom_copies not needed below) */
				atom_copies = (re_ctx->curr_token.qmax == DUK_RE_QUANTIFIER_INFINITE) ?
				              re_ctx->curr_token.qmin : re_ctx->curr_token.qmax;
				if (atom_copies > DUK_RE_MAX_ATOM_COPIES) {
					DUK_ERROR_RANGE(re_ctx->thr, DUK_STR_QUANTIFIER_TOO_MANY_COPIES);
					DUK_WO_NORETURN(return;);
				}

				/* wipe the capture range made by the atom (if any) */
				DUK_ASSERT(atom_start_captures <= re_ctx->captures);
				if (atom_start_captures != re_ctx->captures) {
					DUK_ASSERT(atom_start_captures < re_ctx->captures);
					DUK_DDD(DUK_DDDPRINT("must wipe ]atom_start_captures,re_ctx->captures]: ]%ld,%ld]",
					                     (long) atom_start_captures, (long) re_ctx->captures));

					/* insert (DUK_REOP_WIPERANGE, start, count) in reverse order so the order ends up right */
					duk__insert_u32(re_ctx, (duk_uint32_t) atom_start_offset, (re_ctx->captures - atom_start_captures) * 2U);
					duk__insert_u32(re_ctx, (duk_uint32_t) atom_start_offset, (atom_start_captures + 1) * 2);
					duk__insert_u32(re_ctx, (duk_uint32_t) atom_start_offset, DUK_REOP_WIPERANGE);
				} else {
					DUK_DDD(DUK_DDDPRINT("no need to wipe captures: atom_start_captures == re_ctx->captures == %ld",
					                     (long) atom_start_captures));
				}

				atom_code_length = (duk_int32_t) DUK__RE_BUFLEN(re_ctx) - atom_start_offset;

				/* insert the required matches (qmin) by copying the atom */
				tmp_qmin = re_ctx->curr_token.qmin;
				tmp_qmax = re_ctx->curr_token.qmax;
				while (tmp_qmin > 0) {
					duk__append_slice(re_ctx, (duk_uint32_t) atom_start_offset, (duk_uint32_t) atom_code_length);
					tmp_qmin--;
					if (tmp_qmax != DUK_RE_QUANTIFIER_INFINITE) {
						tmp_qmax--;
					}
				}
				DUK_ASSERT(tmp_qmin == 0);

				/* insert code for matching the remainder - infinite or finite */
				if (tmp_qmax == DUK_RE_QUANTIFIER_INFINITE) {
					/* reuse last emitted atom for remaining 'infinite' quantifier */

					if (re_ctx->curr_token.qmin == 0) {
						/* Special case: original qmin was zero so there is nothing
						 * to repeat.  Emit an atom copy but jump over it here.
						 */
						duk__append_reop(re_ctx, DUK_REOP_JUMP);
						duk__append_jump_offset(re_ctx, atom_code_length);
						duk__append_slice(re_ctx, (duk_uint32_t) atom_start_offset, (duk_uint32_t) atom_code_length);
					}
					if (re_ctx->curr_token.greedy) {
						duk__append_reop(re_ctx, DUK_REOP_SPLIT2);   /* prefer jump */
					} else {
						duk__append_reop(re_ctx, DUK_REOP_SPLIT1);   /* prefer direct */
					}
					duk__append_jump_offset(re_ctx, -atom_code_length - 1);  /* -1 for opcode */
				} else {
					/*
					 *  The remaining matches are emitted as sequence of SPLITs and atom
					 *  copies; the SPLITs skip the remaining copies and match the sequel.
					 *  This sequence needs to be emitted starting from the last copy
					 *  because the SPLITs are variable length due to the variable length
					 *  skip offset.  This causes a lot of memory copying now.
					 *
					 *  Example structure (greedy, match maximum # atoms):
					 *
					 *      SPLIT1 LSEQ
					 *      (atom)
					 *      SPLIT1 LSEQ    ; <- the byte length of this instruction is needed
					 *      (atom)         ; to encode the above SPLIT1 correctly
					 *      ...
					 *   LSEQ:
					 */
					duk_uint32_t offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx);
					while (tmp_qmax > 0) {
						duk__insert_slice(re_ctx, offset, (duk_uint32_t) atom_start_offset, (duk_uint32_t) atom_code_length);
						if (re_ctx->curr_token.greedy) {
							duk__insert_u32(re_ctx, offset, DUK_REOP_SPLIT1);   /* prefer direct */
						} else {
							duk__insert_u32(re_ctx, offset, DUK_REOP_SPLIT2);   /* prefer jump */
						}
						duk__insert_jump_offset(re_ctx,
						                        offset + 1,   /* +1 for opcode */
						                        (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - (offset + 1)));
						tmp_qmax--;
					}
				}

				/* remove the original 'template' atom */
				duk__remove_slice(re_ctx, (duk_uint32_t) atom_start_offset, (duk_uint32_t) atom_code_length);
			}

			/* 'taint' result as complex */
			res_charlen = -1;
			break;
		}
		case DUK_RETOK_ASSERT_START: {
			duk__append_reop(re_ctx, DUK_REOP_ASSERT_START);
			break;
		}
		case DUK_RETOK_ASSERT_END: {
			duk__append_reop(re_ctx, DUK_REOP_ASSERT_END);
			break;
		}
		case DUK_RETOK_ASSERT_WORD_BOUNDARY: {
			duk__append_reop(re_ctx, DUK_REOP_ASSERT_WORD_BOUNDARY);
			break;
		}
		case DUK_RETOK_ASSERT_NOT_WORD_BOUNDARY: {
			duk__append_reop(re_ctx, DUK_REOP_ASSERT_NOT_WORD_BOUNDARY);
			break;
		}
		case DUK_RETOK_ASSERT_START_POS_LOOKAHEAD:
		case DUK_RETOK_ASSERT_START_NEG_LOOKAHEAD: {
			duk_uint32_t offset;
			duk_uint32_t opcode = (re_ctx->curr_token.t == DUK_RETOK_ASSERT_START_POS_LOOKAHEAD) ?
			                      DUK_REOP_LOOKPOS : DUK_REOP_LOOKNEG;

			offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx);
			duk__parse_disjunction(re_ctx, 0, &tmp_disj);
			duk__append_reop(re_ctx, DUK_REOP_MATCH);

			(void) duk__insert_u32(re_ctx, offset, opcode);
			(void) duk__insert_jump_offset(re_ctx,
			                               offset + 1,   /* +1 for opcode */
			                               (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - (offset + 1)));

			/* 'taint' result as complex -- this is conservative,
			 * as lookaheads do not backtrack.
			 */
			res_charlen = -1;
			break;
		}
		case DUK_RETOK_ATOM_PERIOD: {
			new_atom_char_length = 1;
			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
			duk__append_reop(re_ctx, DUK_REOP_PERIOD);
			break;
		}
		case DUK_RETOK_ATOM_CHAR: {
			/* Note: successive characters could be joined into string matches
			 * but this is not trivial (consider e.g. '/xyz+/); see docs for
			 * more discussion.
			 *
			 * No support for \u{H+} yet.  While only BMP Unicode escapes are
			 * supported for RegExps at present, 'ch' may still be a non-BMP
			 * codepoint if it is decoded straight from source text UTF-8.
			 * There's no non-BMP support yet so this is handled simply by
			 * matching the non-BMP character (which is custom behavior).
			 */
			duk_uint32_t ch;

			new_atom_char_length = 1;
			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
			duk__append_reop(re_ctx, DUK_REOP_CHAR);
			ch = re_ctx->curr_token.num;
			if (re_ctx->re_flags & DUK_RE_FLAG_IGNORE_CASE) {
				ch = (duk_uint32_t) duk_unicode_re_canonicalize_char(re_ctx->thr, (duk_codepoint_t) ch);
			}
			duk__append_u32(re_ctx, ch);
			break;
		}
		case DUK_RETOK_ATOM_DIGIT:
		case DUK_RETOK_ATOM_NOT_DIGIT:
		case DUK_RETOK_ATOM_WHITE:
		case DUK_RETOK_ATOM_NOT_WHITE:
		case DUK_RETOK_ATOM_WORD_CHAR:
		case DUK_RETOK_ATOM_NOT_WORD_CHAR: {
			duk_small_uint_t re_op;
			duk_small_uint_t idx;

			new_atom_char_length = 1;
			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);

			DUK_ASSERT((DUK_RETOK_ATOM_DIGIT & 0x01) != 0);
			DUK_ASSERT((DUK_RETOK_ATOM_WHITE & 0x01) != 0);
			DUK_ASSERT((DUK_RETOK_ATOM_WORD_CHAR & 0x01) != 0);
			DUK_ASSERT((DUK_RETOK_ATOM_NOT_DIGIT & 0x01) == 0);
			DUK_ASSERT((DUK_RETOK_ATOM_NOT_WHITE & 0x01) == 0);
			DUK_ASSERT((DUK_RETOK_ATOM_NOT_WORD_CHAR & 0x01) == 0);
			re_op = (re_ctx->curr_token.t & 0x01) ? DUK_REOP_RANGES : DUK_REOP_INVRANGES;

			DUK_ASSERT(DUK_RETOK_ATOM_WHITE == DUK_RETOK_ATOM_DIGIT + 2);
			DUK_ASSERT(DUK_RETOK_ATOM_WORD_CHAR == DUK_RETOK_ATOM_DIGIT + 4);
			idx = (duk_small_uint_t) ((re_ctx->curr_token.t - DUK_RETOK_ATOM_DIGIT) >> 1U);
			DUK_ASSERT(idx <= 2U);  /* Assume continuous token numbers; also checks negative underflow. */

			duk__append_range_atom_matcher(re_ctx, re_op, duk__re_range_lookup1[idx], duk__re_range_lookup2[idx]);
			break;
		}
		case DUK_RETOK_ATOM_BACKREFERENCE: {
			duk_uint32_t backref = (duk_uint32_t) re_ctx->curr_token.num;
			if (backref > re_ctx->highest_backref) {
				re_ctx->highest_backref = backref;
			}
			new_atom_char_length = -1;   /* mark as complex */
			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
			duk__append_reop(re_ctx, DUK_REOP_BACKREFERENCE);
			duk__append_u32(re_ctx, backref);
			break;
		}
		case DUK_RETOK_ATOM_START_CAPTURE_GROUP: {
			duk_uint32_t cap;

			new_atom_char_length = -1;   /* mark as complex (capture handling) */
			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
			cap = ++re_ctx->captures;
			duk__append_reop(re_ctx, DUK_REOP_SAVE);
			duk__append_u32(re_ctx, cap * 2);
			duk__parse_disjunction(re_ctx, 0, &tmp_disj);  /* retval (sub-atom char length) unused, tainted as complex above */
			duk__append_reop(re_ctx, DUK_REOP_SAVE);
			duk__append_u32(re_ctx, cap * 2 + 1);
			break;
		}
		case DUK_RETOK_ATOM_START_NONCAPTURE_GROUP: {
			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
			duk__parse_disjunction(re_ctx, 0, &tmp_disj);
			new_atom_char_length = tmp_disj.charlen;
			break;
		}
		case DUK_RETOK_ATOM_START_CHARCLASS:
		case DUK_RETOK_ATOM_START_CHARCLASS_INVERTED: {
			/*
			 *  Range parsing is done with a special lexer function which calls
			 *  us for every range parsed.  This is different from how rest of
			 *  the parsing works, but avoids a heavy, arbitrary size intermediate
			 *  value type to hold the ranges.
			 *
			 *  Another complication is the handling of character ranges when
			 *  case insensitive matching is used (see docs for discussion).
			 *  The range handler callback given to the lexer takes care of this
			 *  as well.
			 *
			 *  Note that duplicate ranges are not eliminated when parsing character
			 *  classes, so that canonicalization of
			 *
			 *    [0-9a-fA-Fx-{]
			 *
			 *  creates the result (note the duplicate ranges):
			 *
			 *    [0-9A-FA-FX-Z{-{]
			 *
			 *  where [x-{] is split as a result of canonicalization.  The duplicate
			 *  ranges are not a semantics issue: they work correctly.
			 */

			duk_uint32_t offset;

			DUK_DD(DUK_DDPRINT("character class"));

			/* insert ranges instruction, range count patched in later */
			new_atom_char_length = 1;
			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
			duk__append_reop(re_ctx,
			                 (re_ctx->curr_token.t == DUK_RETOK_ATOM_START_CHARCLASS) ?
			                 DUK_REOP_RANGES : DUK_REOP_INVRANGES);
			offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx);    /* patch in range count later */

			/* parse ranges until character class ends */
			re_ctx->nranges = 0;    /* note: ctx-wide temporary */
			duk_lexer_parse_re_ranges(&re_ctx->lex, duk__regexp_generate_ranges, (void *) re_ctx);

			/* insert range count */
			duk__insert_u32(re_ctx, offset, re_ctx->nranges);
			break;
		}
		case DUK_RETOK_ATOM_END_GROUP: {
			if (expect_eof) {
				DUK_ERROR_SYNTAX(re_ctx->thr, DUK_STR_UNEXPECTED_CLOSING_PAREN);
				DUK_WO_NORETURN(return;);
			}
			goto done;
		}
		case DUK_RETOK_EOF: {
			if (!expect_eof) {
				DUK_ERROR_SYNTAX(re_ctx->thr, DUK_STR_UNEXPECTED_END_OF_PATTERN);
				DUK_WO_NORETURN(return;);
			}
			goto done;
		}
		default: {
			DUK_ERROR_SYNTAX(re_ctx->thr, DUK_STR_UNEXPECTED_REGEXP_TOKEN);
			DUK_WO_NORETURN(return;);
		}
		}

		/* a complex (new) atom taints the result */
		if (new_atom_start_offset >= 0) {
			if (new_atom_char_length < 0) {
				res_charlen = -1;
			} else if (res_charlen >= 0) {
				/* only advance if not tainted */
				res_charlen += new_atom_char_length;
			}
		}

		/* record previous atom info in case next token is a quantifier */
		atom_start_offset = new_atom_start_offset;
		atom_char_length = new_atom_char_length;
		atom_start_captures = new_atom_start_captures;
	}

 done:

	/* finish up pending jump and split for last alternative */
	if (unpatched_disjunction_jump >= 0) {
		duk_uint32_t offset;

		DUK_ASSERT(unpatched_disjunction_split >= 0);
		offset = (duk_uint32_t) unpatched_disjunction_jump;
		offset += duk__insert_jump_offset(re_ctx,
		                                  offset,
		                                  (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - offset));
		/* offset is now target of the pending split (right after jump) */
		duk__insert_jump_offset(re_ctx,
		                        (duk_uint32_t) unpatched_disjunction_split,
		                        (duk_int32_t) offset - unpatched_disjunction_split);
	}

#if 0
	out_atom_info->end_captures = re_ctx->captures;
#endif
	out_atom_info->charlen = res_charlen;
	DUK_DDD(DUK_DDDPRINT("parse disjunction finished: charlen=%ld",
	                     (long) out_atom_info->charlen));

	re_ctx->recursion_depth--;
}

/*
 *  Flags parsing (see E5 Section 15.10.4.1).
 */

DUK_LOCAL duk_uint32_t duk__parse_regexp_flags(duk_hthread *thr, duk_hstring *h) {
	const duk_uint8_t *p;
	const duk_uint8_t *p_end;
	duk_uint32_t flags = 0;

	p = DUK_HSTRING_GET_DATA(h);
	p_end = p + DUK_HSTRING_GET_BYTELEN(h);

	/* Note: can be safely scanned as bytes (undecoded) */

	while (p < p_end) {
		duk_uint8_t c = *p++;
		switch (c) {
		case (duk_uint8_t) 'g': {
			if (flags & DUK_RE_FLAG_GLOBAL) {
				goto flags_error;
			}
			flags |= DUK_RE_FLAG_GLOBAL;
			break;
		}
		case (duk_uint8_t) 'i': {
			if (flags & DUK_RE_FLAG_IGNORE_CASE) {
				goto flags_error;
			}
			flags |= DUK_RE_FLAG_IGNORE_CASE;
			break;
		}
		case (duk_uint8_t) 'm': {
			if (flags & DUK_RE_FLAG_MULTILINE) {
				goto flags_error;
			}
			flags |= DUK_RE_FLAG_MULTILINE;
			break;
		}
		default: {
			goto flags_error;
		}
		}
	}

	return flags;

 flags_error:
	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_REGEXP_FLAGS);
	DUK_WO_NORETURN(return 0U;);
}

/*
 *  Create escaped RegExp source (E5 Section 15.10.3).
 *
 *  The current approach is to special case the empty RegExp
 *  ('' -> '(?:)') and otherwise replace unescaped '/' characters
 *  with '\/' regardless of where they occur in the regexp.
 *
 *  Note that normalization does not seem to be necessary for
 *  RegExp literals (e.g. '/foo/') because to be acceptable as
 *  a RegExp literal, the text between forward slashes must
 *  already match the escaping requirements (e.g. must not contain
 *  unescaped forward slashes or be empty).  Escaping IS needed
 *  for expressions like 'new Regexp("...", "")' however.
 *  Currently, we re-escape in either case.
 *
 *  Also note that we process the source here in UTF-8 encoded
 *  form.  This is correct, because any non-ASCII characters are
 *  passed through without change.
 */

DUK_LOCAL void duk__create_escaped_source(duk_hthread *thr, int idx_pattern) {
	duk_hstring *h;
	const duk_uint8_t *p;
	duk_bufwriter_ctx bw_alloc;
	duk_bufwriter_ctx *bw;
	duk_uint8_t *q;
	duk_size_t i, n;
	duk_uint_fast8_t c_prev, c;

	h = duk_known_hstring(thr, idx_pattern);
	p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
	n = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h);

	if (n == 0) {
		duk_push_literal(thr, "(?:)");
		return;
	}

	bw = &bw_alloc;
	DUK_BW_INIT_PUSHBUF(thr, bw, n);
	q = DUK_BW_GET_PTR(thr, bw);

	c_prev = (duk_uint_fast8_t) 0;

	for (i = 0; i < n; i++) {
		c = p[i];

		q = DUK_BW_ENSURE_RAW(thr, bw, 2, q);

		if (c == (duk_uint_fast8_t) '/' && c_prev != (duk_uint_fast8_t) '\\') {
			/* Unescaped '/' ANYWHERE in the regexp (in disjunction,
			 * inside a character class, ...) => same escape works.
			 */
			*q++ = DUK_ASC_BACKSLASH;
		}
		*q++ = (duk_uint8_t) c;

		c_prev = c;
	}

	DUK_BW_SETPTR_AND_COMPACT(thr, bw, q);
	(void) duk_buffer_to_string(thr, -1);  /* Safe if input is safe. */

	/* [ ... escaped_source ] */
}

/*
 *  Exposed regexp compilation primitive.
 *
 *  Sets up a regexp compilation context, and calls duk__parse_disjunction() to do the
 *  actual parsing.  Handles generation of the compiled regexp header and the
 *  "boilerplate" capture of the matching substring (save 0 and 1).  Also does some
 *  global level regexp checks after recursive compilation has finished.
 *
 *  An escaped version of the regexp source, suitable for use as a RegExp instance
 *  'source' property (see E5 Section 15.10.3), is also left on the stack.
 *
 *  Input stack:  [ pattern flags ]
 *  Output stack: [ bytecode escaped_source ]  (both as strings)
 */

DUK_INTERNAL void duk_regexp_compile(duk_hthread *thr) {
	duk_re_compiler_ctx re_ctx;
	duk_lexer_point lex_point;
	duk_hstring *h_pattern;
	duk_hstring *h_flags;
	duk__re_disjunction_info ign_disj;

	DUK_ASSERT(thr != NULL);

	/*
	 *  Args validation
	 */

	/* TypeError if fails */
	h_pattern = duk_require_hstring_notsymbol(thr, -2);
	h_flags = duk_require_hstring_notsymbol(thr, -1);

	/*
	 *  Create normalized 'source' property (E5 Section 15.10.3).
	 */

	/* [ ... pattern flags ] */

	duk__create_escaped_source(thr, -2);

	/* [ ... pattern flags escaped_source ] */

	/*
	 *  Init compilation context
	 */

	/* [ ... pattern flags escaped_source buffer ] */

	duk_memzero(&re_ctx, sizeof(re_ctx));
	DUK_LEXER_INITCTX(&re_ctx.lex);  /* duplicate zeroing, expect for (possible) NULL inits */
	re_ctx.thr = thr;
	re_ctx.lex.thr = thr;
	re_ctx.lex.input = DUK_HSTRING_GET_DATA(h_pattern);
	re_ctx.lex.input_length = DUK_HSTRING_GET_BYTELEN(h_pattern);
	re_ctx.lex.token_limit = DUK_RE_COMPILE_TOKEN_LIMIT;
	re_ctx.recursion_limit = DUK_USE_REGEXP_COMPILER_RECLIMIT;
	re_ctx.re_flags = duk__parse_regexp_flags(thr, h_flags);

	DUK_BW_INIT_PUSHBUF(thr, &re_ctx.bw, DUK__RE_INITIAL_BUFSIZE);

	DUK_DD(DUK_DDPRINT("regexp compiler ctx initialized, flags=0x%08lx, recursion_limit=%ld",
	                   (unsigned long) re_ctx.re_flags, (long) re_ctx.recursion_limit));

	/*
	 *  Init lexer
	 */

	lex_point.offset = 0;  /* expensive init, just want to fill window */
	lex_point.line = 1;
	DUK_LEXER_SETPOINT(&re_ctx.lex, &lex_point);

	/*
	 *  Compilation
	 */

	DUK_DD(DUK_DDPRINT("starting regexp compilation"));

	duk__append_reop(&re_ctx, DUK_REOP_SAVE);
	duk__append_7bit(&re_ctx, 0);
	duk__parse_disjunction(&re_ctx, 1 /*expect_eof*/, &ign_disj);
	duk__append_reop(&re_ctx, DUK_REOP_SAVE);
	duk__append_7bit(&re_ctx, 1);
	duk__append_reop(&re_ctx, DUK_REOP_MATCH);

	/*
	 *  Check for invalid backreferences; note that it is NOT an error
	 *  to back-reference a capture group which has not yet been introduced
	 *  in the pattern (as in /\1(foo)/); in fact, the backreference will
	 *  always match!  It IS an error to back-reference a capture group
	 *  which will never be introduced in the pattern.  Thus, we can check
	 *  for such references only after parsing is complete.
	 */

	if (re_ctx.highest_backref > re_ctx.captures) {
		DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_BACKREFS);
		DUK_WO_NORETURN(return;);
	}

	/*
	 *  Emit compiled regexp header: flags, ncaptures
	 *  (insertion order inverted on purpose)
	 */

	duk__insert_u32(&re_ctx, 0, (re_ctx.captures + 1) * 2);
	duk__insert_u32(&re_ctx, 0, re_ctx.re_flags);

	/* [ ... pattern flags escaped_source buffer ] */

	DUK_BW_COMPACT(thr, &re_ctx.bw);
	(void) duk_buffer_to_string(thr, -1);  /* Safe because flags is at most 7 bit. */

	/* [ ... pattern flags escaped_source bytecode ] */

	/*
	 *  Finalize stack
	 */

	duk_remove(thr, -4);     /* -> [ ... flags escaped_source bytecode ] */
	duk_remove(thr, -3);     /* -> [ ... escaped_source bytecode ] */

	DUK_DD(DUK_DDPRINT("regexp compilation successful, bytecode: %!T, escaped source: %!T",
	                   (duk_tval *) duk_get_tval(thr, -1), (duk_tval *) duk_get_tval(thr, -2)));
}

/*
 *  Create a RegExp instance (E5 Section 15.10.7).
 *
 *  Note: the output stack left by duk_regexp_compile() is directly compatible
 *  with the input here.
 *
 *  Input stack:  [ escaped_source bytecode ]  (both as strings)
 *  Output stack: [ RegExp ]
 */

DUK_INTERNAL void duk_regexp_create_instance(duk_hthread *thr) {
	duk_hobject *h;

	/* [ ... escaped_source bytecode ] */

	duk_push_object(thr);
	h = duk_known_hobject(thr, -1);
	duk_insert(thr, -3);

	/* [ ... regexp_object escaped_source bytecode ] */

	DUK_HOBJECT_SET_CLASS_NUMBER(h, DUK_HOBJECT_CLASS_REGEXP);
	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h, thr->builtins[DUK_BIDX_REGEXP_PROTOTYPE]);

	duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_INT_BYTECODE, DUK_PROPDESC_FLAGS_NONE);

	/* [ ... regexp_object escaped_source ] */

	/* In ES2015 .source, and the .global, .multiline, etc flags are
	 * inherited getters.  Store the escaped source as an internal
	 * property for the getter.
	 */

	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_SOURCE, DUK_PROPDESC_FLAGS_NONE);

	/* [ ... regexp_object ] */

	duk_push_int(thr, 0);
	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LAST_INDEX, DUK_PROPDESC_FLAGS_W);

	/* [ ... regexp_object ] */
}

#else  /* DUK_USE_REGEXP_SUPPORT */

/* regexp support disabled */

#endif  /* DUK_USE_REGEXP_SUPPORT */

/* automatic undefs */
#undef DUK__RE_BUFLEN
#undef DUK__RE_INITIAL_BUFSIZE
#line 1 "duk_regexp_executor.c"
/*
 *  Regexp executor.
 *
 *  Safety: the ECMAScript executor should prevent user from reading and
 *  replacing regexp bytecode.  Even so, the executor must validate all
 *  memory accesses etc.  When an invalid access is detected (e.g. a 'save'
 *  opcode to invalid, unallocated index) it should fail with an internal
 *  error but not cause a segmentation fault.
 *
 *  Notes:
 *
 *    - Backtrack counts are limited to unsigned 32 bits but should
 *      technically be duk_size_t for strings longer than 4G chars.
 *      This also requires a regexp bytecode change.
 */

/* #include duk_internal.h -> already included */

#if defined(DUK_USE_REGEXP_SUPPORT)

/*
 *  Helpers for UTF-8 handling
 *
 *  For bytecode readers the duk_uint32_t and duk_int32_t types are correct
 *  because they're used for more than just codepoints.
 */

DUK_LOCAL duk_uint32_t duk__bc_get_u32(duk_re_matcher_ctx *re_ctx, const duk_uint8_t **pc) {
	return (duk_uint32_t) duk_unicode_decode_xutf8_checked(re_ctx->thr, pc, re_ctx->bytecode, re_ctx->bytecode_end);
}

DUK_LOCAL duk_int32_t duk__bc_get_i32(duk_re_matcher_ctx *re_ctx, const duk_uint8_t **pc) {
	duk_uint32_t t;

	/* signed integer encoding needed to work with UTF-8 */
	t = (duk_uint32_t) duk_unicode_decode_xutf8_checked(re_ctx->thr, pc, re_ctx->bytecode, re_ctx->bytecode_end);
	if (t & 1) {
		return -((duk_int32_t) (t >> 1));
	} else {
		return (duk_int32_t) (t >> 1);
	}
}

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) {
	const duk_uint8_t *p;

	/* Note: allow backtracking from p == ptr_end */
	p = *ptr;
	if (p < ptr_start || p > ptr_end) {
		goto fail;
	}

	while (count > 0) {
		for (;;) {
			p--;
			if (p < ptr_start) {
				goto fail;
			}
			if ((*p & 0xc0) != 0x80) {
				/* utf-8 continuation bytes have the form 10xx xxxx */
				break;
			}
		}
		count--;
	}
	*ptr = p;
	return p;

 fail:
	DUK_ERROR_INTERNAL(thr);
	DUK_WO_NORETURN(return NULL;);
}

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) {
	const duk_uint8_t *p;

	p = *ptr;
	if (p < ptr_start || p >= ptr_end) {
		goto fail;
	}

	while (count > 0) {
		for (;;) {
			p++;

			/* Note: if encoding ends by hitting end of input, we don't check that
			 * the encoding is valid, we just assume it is.
			 */
			if (p >= ptr_end || ((*p & 0xc0) != 0x80)) {
				/* utf-8 continuation bytes have the form 10xx xxxx */
				break;
			}
		}
		count--;
	}

	*ptr = p;
	return p;

 fail:
	DUK_ERROR_INTERNAL(thr);
	DUK_WO_NORETURN(return NULL;);
}

/*
 *  Helpers for dealing with the input string
 */

/* Get a (possibly canonicalized) input character from current sp.  The input
 * itself is never modified, and captures always record non-canonicalized
 * characters even in case-insensitive matching.  Return <0 if out of input.
 */
DUK_LOCAL duk_codepoint_t duk__inp_get_cp(duk_re_matcher_ctx *re_ctx, const duk_uint8_t **sp) {
	duk_codepoint_t res;

	if (*sp >= re_ctx->input_end) {
		return -1;
	}
	res = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(re_ctx->thr, sp, re_ctx->input, re_ctx->input_end);
	if (re_ctx->re_flags & DUK_RE_FLAG_IGNORE_CASE) {
		res = duk_unicode_re_canonicalize_char(re_ctx->thr, res);
	}
	return res;
}

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) {
	return duk__utf8_backtrack(re_ctx->thr, sp, re_ctx->input, re_ctx->input_end, count);
}

/* Backtrack utf-8 input and return a (possibly canonicalized) input character. */
DUK_LOCAL duk_codepoint_t duk__inp_get_prev_cp(duk_re_matcher_ctx *re_ctx, const duk_uint8_t *sp) {
	/* note: caller 'sp' is intentionally not updated here */
	(void) duk__inp_backtrack(re_ctx, &sp, (duk_uint_fast32_t) 1);
	return duk__inp_get_cp(re_ctx, &sp);
}

/*
 *  Regexp recursive matching function.
 *
 *  Returns 'sp' on successful match (points to character after last matched one),
 *  NULL otherwise.
 *
 *  The C recursion depth limit check is only performed in this function, this
 *  suffices because the function is present in all true recursion required by
 *  regexp execution.
 */

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) {
	duk_native_stack_check(re_ctx->thr);
	if (re_ctx->recursion_depth >= re_ctx->recursion_limit) {
		DUK_ERROR_RANGE(re_ctx->thr, DUK_STR_REGEXP_EXECUTOR_RECURSION_LIMIT);
		DUK_WO_NORETURN(return NULL;);
	}
	re_ctx->recursion_depth++;

	for (;;) {
		duk_small_int_t op;

		if (re_ctx->steps_count >= re_ctx->steps_limit) {
			DUK_ERROR_RANGE(re_ctx->thr, DUK_STR_REGEXP_EXECUTOR_STEP_LIMIT);
			DUK_WO_NORETURN(return NULL;);
		}
		re_ctx->steps_count++;

		/* Opcodes are at most 7 bits now so they encode to one byte.  If this
		 * were not the case or 'pc' is invalid here (due to a bug etc) we'll
		 * still fail safely through the switch default case.
		 */
		DUK_ASSERT(pc[0] <= 0x7fU);
#if 0
		op = (duk_small_int_t) duk__bc_get_u32(re_ctx, &pc);
#endif
		op = *pc++;

		DUK_DDD(DUK_DDDPRINT("match: rec=%ld, steps=%ld, pc (after op)=%ld, sp=%ld, op=%ld",
		                     (long) re_ctx->recursion_depth,
		                     (long) re_ctx->steps_count,
		                     (long) (pc - re_ctx->bytecode),
		                     (long) (sp - re_ctx->input),
		                     (long) op));

		switch (op) {
		case DUK_REOP_MATCH: {
			goto match;
		}
		case DUK_REOP_CHAR: {
			/*
			 *  Byte-based matching would be possible for case-sensitive
			 *  matching but not for case-insensitive matching.  So, we
			 *  match by decoding the input and bytecode character normally.
			 *
			 *  Bytecode characters are assumed to be already canonicalized.
			 *  Input characters are canonicalized automatically by
			 *  duk__inp_get_cp() if necessary.
			 *
			 *  There is no opcode for matching multiple characters.  The
			 *  regexp compiler has trouble joining strings efficiently
			 *  during compilation.  See doc/regexp.rst for more discussion.
			 */
			duk_codepoint_t c1, c2;

			c1 = (duk_codepoint_t) duk__bc_get_u32(re_ctx, &pc);
			DUK_ASSERT(!(re_ctx->re_flags & DUK_RE_FLAG_IGNORE_CASE) ||
			           c1 == duk_unicode_re_canonicalize_char(re_ctx->thr, c1));  /* canonicalized by compiler */
			c2 = duk__inp_get_cp(re_ctx, &sp);
			/* No need to check for c2 < 0 (end of input): because c1 >= 0, it
			 * will fail the match below automatically and cause goto fail.
			 */
#if 0
			if (c2 < 0) {
				goto fail;
			}
#endif
			DUK_ASSERT(c1 >= 0);

			DUK_DDD(DUK_DDDPRINT("char match, c1=%ld, c2=%ld", (long) c1, (long) c2));
			if (c1 != c2) {
				goto fail;
			}
			break;
		}
		case DUK_REOP_PERIOD: {
			duk_codepoint_t c;

			c = duk__inp_get_cp(re_ctx, &sp);
			if (c < 0 || duk_unicode_is_line_terminator(c)) {
				/* E5 Sections 15.10.2.8, 7.3 */
				goto fail;
			}
			break;
		}
		case DUK_REOP_RANGES:
		case DUK_REOP_INVRANGES: {
			duk_uint32_t n;
			duk_codepoint_t c;
			duk_small_int_t match;

			n = duk__bc_get_u32(re_ctx, &pc);
			c = duk__inp_get_cp(re_ctx, &sp);
			if (c < 0) {
				goto fail;
			}

			match = 0;
			while (n) {
				duk_codepoint_t r1, r2;
				r1 = (duk_codepoint_t) duk__bc_get_u32(re_ctx, &pc);
				r2 = (duk_codepoint_t) duk__bc_get_u32(re_ctx, &pc);
				DUK_DDD(DUK_DDDPRINT("matching ranges/invranges, n=%ld, r1=%ld, r2=%ld, c=%ld",
				                     (long) n, (long) r1, (long) r2, (long) c));
				if (c >= r1 && c <= r2) {
					/* Note: don't bail out early, we must read all the ranges from
					 * bytecode.  Another option is to skip them efficiently after
					 * breaking out of here.  Prefer smallest code.
					 */
					match = 1;
				}
				n--;
			}

			if (op == DUK_REOP_RANGES) {
				if (!match) {
					goto fail;
				}
			} else {
				DUK_ASSERT(op == DUK_REOP_INVRANGES);
				if (match) {
					goto fail;
				}
			}
			break;
		}
		case DUK_REOP_ASSERT_START: {
			duk_codepoint_t c;

			if (sp <= re_ctx->input) {
				break;
			}
			if (!(re_ctx->re_flags & DUK_RE_FLAG_MULTILINE)) {
				goto fail;
			}
			c = duk__inp_get_prev_cp(re_ctx, sp);
			if (duk_unicode_is_line_terminator(c)) {
				/* E5 Sections 15.10.2.8, 7.3 */
				break;
			}
			goto fail;
		}
		case DUK_REOP_ASSERT_END: {
			duk_codepoint_t c;
			const duk_uint8_t *tmp_sp;

			tmp_sp = sp;
			c = duk__inp_get_cp(re_ctx, &tmp_sp);
			if (c < 0) {
				break;
			}
			if (!(re_ctx->re_flags & DUK_RE_FLAG_MULTILINE)) {
				goto fail;
			}
			if (duk_unicode_is_line_terminator(c)) {
				/* E5 Sections 15.10.2.8, 7.3 */
				break;
			}
			goto fail;
		}
		case DUK_REOP_ASSERT_WORD_BOUNDARY:
		case DUK_REOP_ASSERT_NOT_WORD_BOUNDARY: {
			/*
			 *  E5 Section 15.10.2.6.  The previous and current character
			 *  should -not- be canonicalized as they are now.  However,
			 *  canonicalization does not affect the result of IsWordChar()
			 *  (which depends on Unicode characters never canonicalizing
			 *  into ASCII characters) so this does not matter.
			 */
			duk_small_int_t w1, w2;

			if (sp <= re_ctx->input) {
				w1 = 0;  /* not a wordchar */
			} else {
				duk_codepoint_t c;
				c = duk__inp_get_prev_cp(re_ctx, sp);
				w1 = duk_unicode_re_is_wordchar(c);
			}
			if (sp >= re_ctx->input_end) {
				w2 = 0;  /* not a wordchar */
			} else {
				const duk_uint8_t *tmp_sp = sp;  /* dummy so sp won't get updated */
				duk_codepoint_t c;
				c = duk__inp_get_cp(re_ctx, &tmp_sp);
				w2 = duk_unicode_re_is_wordchar(c);
			}

			if (op == DUK_REOP_ASSERT_WORD_BOUNDARY) {
				if (w1 == w2) {
					goto fail;
				}
			} else {
				DUK_ASSERT(op == DUK_REOP_ASSERT_NOT_WORD_BOUNDARY);
				if (w1 != w2) {
					goto fail;
				}
			}
			break;
		}
		case DUK_REOP_JUMP: {
			duk_int32_t skip;

			skip = duk__bc_get_i32(re_ctx, &pc);
			pc += skip;
			break;
		}
		case DUK_REOP_SPLIT1: {
			/* split1: prefer direct execution (no jump) */
			const duk_uint8_t *sub_sp;
			duk_int32_t skip;

			skip = duk__bc_get_i32(re_ctx, &pc);
			sub_sp = duk__match_regexp(re_ctx, pc, sp);
			if (sub_sp) {
				sp = sub_sp;
				goto match;
			}
			pc += skip;
			break;
		}
		case DUK_REOP_SPLIT2: {
			/* split2: prefer jump execution (not direct) */
			const duk_uint8_t *sub_sp;
			duk_int32_t skip;

			skip = duk__bc_get_i32(re_ctx, &pc);
			sub_sp = duk__match_regexp(re_ctx, pc + skip, sp);
			if (sub_sp) {
				sp = sub_sp;
				goto match;
			}
			break;
		}
		case DUK_REOP_SQMINIMAL: {
			duk_uint32_t q, qmin, qmax;
			duk_int32_t skip;
			const duk_uint8_t *sub_sp;

			qmin = duk__bc_get_u32(re_ctx, &pc);
			qmax = duk__bc_get_u32(re_ctx, &pc);
			skip = duk__bc_get_i32(re_ctx, &pc);
			DUK_DDD(DUK_DDDPRINT("minimal quantifier, qmin=%lu, qmax=%lu, skip=%ld",
			                     (unsigned long) qmin, (unsigned long) qmax, (long) skip));

			q = 0;
			while (q <= qmax) {
				if (q >= qmin) {
					sub_sp = duk__match_regexp(re_ctx, pc + skip, sp);
					if (sub_sp) {
						sp = sub_sp;
						goto match;
					}
				}
				sub_sp = duk__match_regexp(re_ctx, pc, sp);
				if (!sub_sp) {
					break;
				}
				sp = sub_sp;
				q++;
			}
			goto fail;
		}
		case DUK_REOP_SQGREEDY: {
			duk_uint32_t q, qmin, qmax, atomlen;
			duk_int32_t skip;
			const duk_uint8_t *sub_sp;

			qmin = duk__bc_get_u32(re_ctx, &pc);
			qmax = duk__bc_get_u32(re_ctx, &pc);
			atomlen = duk__bc_get_u32(re_ctx, &pc);
			skip = duk__bc_get_i32(re_ctx, &pc);
			DUK_DDD(DUK_DDDPRINT("greedy quantifier, qmin=%lu, qmax=%lu, atomlen=%lu, skip=%ld",
			                     (unsigned long) qmin, (unsigned long) qmax, (unsigned long) atomlen, (long) skip));

			q = 0;
			while (q < qmax) {
				sub_sp = duk__match_regexp(re_ctx, pc, sp);
				if (!sub_sp) {
					break;
				}
				sp = sub_sp;
				q++;
			}
			while (q >= qmin) {
				sub_sp = duk__match_regexp(re_ctx, pc + skip, sp);
				if (sub_sp) {
					sp = sub_sp;
					goto match;
				}
				if (q == qmin) {
					break;
				}

				/* Note: if atom were to contain e.g. captures, we would need to
				 * re-match the atom to get correct captures.  Simply quantifiers
				 * do not allow captures in their atom now, so this is not an issue.
				 */

				DUK_DDD(DUK_DDDPRINT("greedy quantifier, backtrack %ld characters (atomlen)",
				                     (long) atomlen));
				sp = duk__inp_backtrack(re_ctx, &sp, (duk_uint_fast32_t) atomlen);
				q--;
			}
			goto fail;
		}
		case DUK_REOP_SAVE: {
			duk_uint32_t idx;
			const duk_uint8_t *old;
			const duk_uint8_t *sub_sp;

			idx = duk__bc_get_u32(re_ctx, &pc);
			if (idx >= re_ctx->nsaved) {
				/* idx is unsigned, < 0 check is not necessary */
				DUK_D(DUK_DPRINT("internal error, regexp save index insane: idx=%ld", (long) idx));
				goto internal_error;
			}
			old = re_ctx->saved[idx];
			re_ctx->saved[idx] = sp;
			sub_sp = duk__match_regexp(re_ctx, pc, sp);
			if (sub_sp) {
				sp = sub_sp;
				goto match;
			}
			re_ctx->saved[idx] = old;
			goto fail;
		}
		case DUK_REOP_WIPERANGE: {
			/* Wipe capture range and save old values for backtracking.
			 *
			 * XXX: this typically happens with a relatively small idx_count.
			 * It might be useful to handle cases where the count is small
			 * (say <= 8) by saving the values in stack instead.  This would
			 * reduce memory churn and improve performance, at the cost of a
			 * slightly higher code footprint.
			 */
			duk_uint32_t idx_start, idx_count;
#if defined(DUK_USE_EXPLICIT_NULL_INIT)
			duk_uint32_t idx_end, idx;
#endif
			duk_uint8_t **range_save;
			const duk_uint8_t *sub_sp;

			idx_start = duk__bc_get_u32(re_ctx, &pc);
			idx_count = duk__bc_get_u32(re_ctx, &pc);
			DUK_DDD(DUK_DDDPRINT("wipe saved range: start=%ld, count=%ld -> [%ld,%ld] (captures [%ld,%ld])",
			                     (long) idx_start, (long) idx_count,
			                     (long) idx_start, (long) (idx_start + idx_count - 1),
			                     (long) (idx_start / 2), (long) ((idx_start + idx_count - 1) / 2)));
			if (idx_start + idx_count > re_ctx->nsaved || idx_count == 0) {
				/* idx is unsigned, < 0 check is not necessary */
				DUK_D(DUK_DPRINT("internal error, regexp wipe indices insane: idx_start=%ld, idx_count=%ld",
				                 (long) idx_start, (long) idx_count));
				goto internal_error;
			}
			DUK_ASSERT(idx_count > 0);

			duk_require_stack(re_ctx->thr, 1);
			range_save = (duk_uint8_t **) duk_push_fixed_buffer_nozero(re_ctx->thr,
			                                                           sizeof(duk_uint8_t *) * idx_count);
			DUK_ASSERT(range_save != NULL);
			duk_memcpy(range_save, re_ctx->saved + idx_start, sizeof(duk_uint8_t *) * idx_count);
#if defined(DUK_USE_EXPLICIT_NULL_INIT)
			idx_end = idx_start + idx_count;
			for (idx = idx_start; idx < idx_end; idx++) {
				re_ctx->saved[idx] = NULL;
			}
#else
			duk_memzero((void *) (re_ctx->saved + idx_start), sizeof(duk_uint8_t *) * idx_count);
#endif

			sub_sp = duk__match_regexp(re_ctx, pc, sp);
			if (sub_sp) {
				/* match: keep wiped/resaved values */
				DUK_DDD(DUK_DDDPRINT("match: keep wiped/resaved values [%ld,%ld] (captures [%ld,%ld])",
				                     (long) idx_start, (long) (idx_start + idx_count - 1),
			                             (long) (idx_start / 2), (long) ((idx_start + idx_count - 1) / 2)));
				duk_pop_unsafe(re_ctx->thr);
				sp = sub_sp;
				goto match;
			}

			/* fail: restore saves */
			DUK_DDD(DUK_DDDPRINT("fail: restore wiped/resaved values [%ld,%ld] (captures [%ld,%ld])",
			                     (long) idx_start, (long) (idx_start + idx_count - 1),
			                     (long) (idx_start / 2), (long) ((idx_start + idx_count - 1) / 2)));
			duk_memcpy((void *) (re_ctx->saved + idx_start),
			           (const void *) range_save,
			           sizeof(duk_uint8_t *) * idx_count);
			duk_pop_unsafe(re_ctx->thr);
			goto fail;
		}
		case DUK_REOP_LOOKPOS:
		case DUK_REOP_LOOKNEG: {
			/*
			 *  Needs a save of multiple saved[] entries depending on what range
			 *  may be overwritten.  Because the regexp parser does no such analysis,
			 *  we currently save the entire saved array here.  Lookaheads are thus
			 *  a bit expensive.  Note that the saved array is not needed for just
			 *  the lookahead sub-match, but for the matching of the entire sequel.
			 *
			 *  The temporary save buffer is pushed on to the valstack to handle
			 *  errors correctly.  Each lookahead causes a C recursion and pushes
			 *  more stuff on the value stack.  If the C recursion limit is less
			 *  than the value stack slack, there is no need to check the stack.
			 *  We do so regardless, just in case.
			 */

			duk_int32_t skip;
			duk_uint8_t **full_save;
			const duk_uint8_t *sub_sp;

			DUK_ASSERT(re_ctx->nsaved > 0);

			duk_require_stack(re_ctx->thr, 1);
			full_save = (duk_uint8_t **) duk_push_fixed_buffer_nozero(re_ctx->thr,
			                                                          sizeof(duk_uint8_t *) * re_ctx->nsaved);
			DUK_ASSERT(full_save != NULL);
			duk_memcpy(full_save, re_ctx->saved, sizeof(duk_uint8_t *) * re_ctx->nsaved);

			skip = duk__bc_get_i32(re_ctx, &pc);
			sub_sp = duk__match_regexp(re_ctx, pc, sp);
			if (op == DUK_REOP_LOOKPOS) {
				if (!sub_sp) {
					goto lookahead_fail;
				}
			} else {
				if (sub_sp) {
					goto lookahead_fail;
				}
			}
			sub_sp = duk__match_regexp(re_ctx, pc + skip, sp);
			if (sub_sp) {
				/* match: keep saves */
				duk_pop_unsafe(re_ctx->thr);
				sp = sub_sp;
				goto match;
			}

			/* fall through */

		 lookahead_fail:
			/* fail: restore saves */
			duk_memcpy((void *) re_ctx->saved,
			           (const void *) full_save,
			           sizeof(duk_uint8_t *) * re_ctx->nsaved);
			duk_pop_unsafe(re_ctx->thr);
			goto fail;
		}
		case DUK_REOP_BACKREFERENCE: {
			/*
			 *  Byte matching for back-references would be OK in case-
			 *  sensitive matching.  In case-insensitive matching we need
			 *  to canonicalize characters, so back-reference matching needs
			 *  to be done with codepoints instead.  So, we just decode
			 *  everything normally here, too.
			 *
			 *  Note: back-reference index which is 0 or higher than
			 *  NCapturingParens (= number of capturing parens in the
			 *  -entire- regexp) is a compile time error.  However, a
			 *  backreference referring to a valid capture which has
			 *  not matched anything always succeeds!  See E5 Section
			 *  15.10.2.9, step 5, sub-step 3.
			 */
			duk_uint32_t idx;
			const duk_uint8_t *p;

			idx = duk__bc_get_u32(re_ctx, &pc);
			idx = idx << 1;  /* backref n -> saved indices [n*2, n*2+1] */
			if (idx < 2 || idx + 1 >= re_ctx->nsaved) {
				/* regexp compiler should catch these */
				DUK_D(DUK_DPRINT("internal error, backreference index insane"));
				goto internal_error;
			}
			if (!re_ctx->saved[idx] || !re_ctx->saved[idx+1]) {
				/* capture is 'undefined', always matches! */
				DUK_DDD(DUK_DDDPRINT("backreference: saved[%ld,%ld] not complete, always match",
				                     (long) idx, (long) (idx + 1)));
				break;
			}
			DUK_DDD(DUK_DDDPRINT("backreference: match saved[%ld,%ld]", (long) idx, (long) (idx + 1)));

			p = re_ctx->saved[idx];
			while (p < re_ctx->saved[idx+1]) {
				duk_codepoint_t c1, c2;

				/* Note: not necessary to check p against re_ctx->input_end:
				 * the memory access is checked by duk__inp_get_cp(), while
				 * valid compiled regexps cannot write a saved[] entry
				 * which points to outside the string.
				 */
				c1 = duk__inp_get_cp(re_ctx, &p);
				DUK_ASSERT(c1 >= 0);
				c2 = duk__inp_get_cp(re_ctx, &sp);
				/* No need for an explicit c2 < 0 check: because c1 >= 0,
				 * the comparison will always fail if c2 < 0.
				 */
#if 0
				if (c2 < 0) {
					goto fail;
				}
#endif
				if (c1 != c2) {
					goto fail;
				}
			}
			break;
		}
		default: {
			DUK_D(DUK_DPRINT("internal error, regexp opcode error: %ld", (long) op));
			goto internal_error;
		}
		}
	}

 match:
	re_ctx->recursion_depth--;
	return sp;

 fail:
	re_ctx->recursion_depth--;
	return NULL;

 internal_error:
	DUK_ERROR_INTERNAL(re_ctx->thr);
	DUK_WO_NORETURN(return NULL;);
}

/*
 *  Exposed matcher function which provides the semantics of RegExp.prototype.exec().
 *
 *  RegExp.prototype.test() has the same semantics as exec() but does not return the
 *  result object (which contains the matching string and capture groups).  Currently
 *  there is no separate test() helper, so a temporary result object is created and
 *  discarded if test() is needed.  This is intentional, to save code space.
 *
 *  Input stack:  [ ... re_obj input ]
 *  Output stack: [ ... result ]
 */

DUK_LOCAL void duk__regexp_match_helper(duk_hthread *thr, duk_small_int_t force_global) {
	duk_re_matcher_ctx re_ctx;
	duk_hobject *h_regexp;
	duk_hstring *h_bytecode;
	duk_hstring *h_input;
	duk_uint8_t *p_buf;
	const duk_uint8_t *pc;
	const duk_uint8_t *sp;
	duk_small_int_t match = 0;
	duk_small_int_t global;
	duk_uint_fast32_t i;
	double d;
	duk_uint32_t char_offset;

	DUK_ASSERT(thr != NULL);

	DUK_DD(DUK_DDPRINT("regexp match: regexp=%!T, input=%!T",
	                   (duk_tval *) duk_get_tval(thr, -2),
	                   (duk_tval *) duk_get_tval(thr, -1)));

	/*
	 *  Regexp instance check, bytecode check, input coercion.
	 *
	 *  See E5 Section 15.10.6.
	 */

	/* TypeError if wrong; class check, see E5 Section 15.10.6 */
	h_regexp = duk_require_hobject_with_class(thr, -2, DUK_HOBJECT_CLASS_REGEXP);
	DUK_ASSERT(h_regexp != NULL);
	DUK_ASSERT(DUK_HOBJECT_GET_CLASS_NUMBER(h_regexp) == DUK_HOBJECT_CLASS_REGEXP);
	DUK_UNREF(h_regexp);

	h_input = duk_to_hstring(thr, -1);
	DUK_ASSERT(h_input != NULL);

	duk_xget_owndataprop_stridx_short(thr, -2, DUK_STRIDX_INT_BYTECODE);  /* [ ... re_obj input ] -> [ ... re_obj input bc ] */
	h_bytecode = duk_require_hstring(thr, -1);  /* no regexp instance should exist without a non-configurable bytecode property */
	DUK_ASSERT(h_bytecode != NULL);

	/*
	 *  Basic context initialization.
	 *
	 *  Some init values are read from the bytecode header
	 *  whose format is (UTF-8 codepoints):
	 *
	 *    uint   flags
	 *    uint   nsaved (even, 2n+2 where n = num captures)
	 */

	/* [ ... re_obj input bc ] */

	duk_memzero(&re_ctx, sizeof(re_ctx));

	re_ctx.thr = thr;
	re_ctx.input = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
	re_ctx.input_end = re_ctx.input + DUK_HSTRING_GET_BYTELEN(h_input);
	re_ctx.bytecode = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_bytecode);
	re_ctx.bytecode_end = re_ctx.bytecode + DUK_HSTRING_GET_BYTELEN(h_bytecode);
	re_ctx.saved = NULL;
	re_ctx.recursion_limit = DUK_USE_REGEXP_EXECUTOR_RECLIMIT;
	re_ctx.steps_limit = DUK_RE_EXECUTE_STEPS_LIMIT;

	/* read header */
	pc = re_ctx.bytecode;
	re_ctx.re_flags = duk__bc_get_u32(&re_ctx, &pc);
	re_ctx.nsaved = duk__bc_get_u32(&re_ctx, &pc);
	re_ctx.bytecode = pc;

	DUK_ASSERT(DUK_RE_FLAG_GLOBAL < 0x10000UL);  /* must fit into duk_small_int_t */
	global = (duk_small_int_t) (force_global | (duk_small_int_t) (re_ctx.re_flags & DUK_RE_FLAG_GLOBAL));

	DUK_ASSERT(re_ctx.nsaved >= 2);
	DUK_ASSERT((re_ctx.nsaved % 2) == 0);

	p_buf = (duk_uint8_t *) duk_push_fixed_buffer(thr, sizeof(duk_uint8_t *) * re_ctx.nsaved);  /* rely on zeroing */
	DUK_UNREF(p_buf);
	re_ctx.saved = (const duk_uint8_t **) duk_get_buffer(thr, -1, NULL);
	DUK_ASSERT(re_ctx.saved != NULL);

	/* [ ... re_obj input bc saved_buf ] */

#if defined(DUK_USE_EXPLICIT_NULL_INIT)
	for (i = 0; i < re_ctx.nsaved; i++) {
		re_ctx.saved[i] = (duk_uint8_t *) NULL;
	}
#elif defined(DUK_USE_ZERO_BUFFER_DATA)
	/* buffer is automatically zeroed */
#else
	duk_memzero((void *) p_buf, sizeof(duk_uint8_t *) * re_ctx.nsaved);
#endif

	DUK_DDD(DUK_DDDPRINT("regexp ctx initialized, flags=0x%08lx, nsaved=%ld, recursion_limit=%ld, steps_limit=%ld",
	                     (unsigned long) re_ctx.re_flags, (long) re_ctx.nsaved, (long) re_ctx.recursion_limit,
	                     (long) re_ctx.steps_limit));

	/*
	 *  Get starting character offset for match, and initialize 'sp' based on it.
	 *
	 *  Note: lastIndex is non-configurable so it must be present (we check the
	 *  internal class of the object above, so we know it is).  User code can set
	 *  its value to an arbitrary (garbage) value though; E5 requires that lastIndex
	 *  be coerced to a number before using.  The code below works even if the
	 *  property is missing: the value will then be coerced to zero.
	 *
	 *  Note: lastIndex may be outside Uint32 range even after ToInteger() coercion.
	 *  For instance, ToInteger(+Infinity) = +Infinity.  We track the match offset
	 *  as an integer, but pre-check it to be inside the 32-bit range before the loop.
	 *  If not, the check in E5 Section 15.10.6.2, step 9.a applies.
	 */

	/* XXX: lastIndex handling produces a lot of asm */

	/* [ ... re_obj input bc saved_buf ] */

	duk_get_prop_stridx_short(thr, -4, DUK_STRIDX_LAST_INDEX);  /* -> [ ... re_obj input bc saved_buf lastIndex ] */
	(void) duk_to_int(thr, -1);  /* ToInteger(lastIndex) */
	d = duk_get_number(thr, -1);  /* integer, but may be +/- Infinite, +/- zero (not NaN, though) */
	duk_pop_nodecref_unsafe(thr);

	if (global) {
		if (d < 0.0 || d > (double) DUK_HSTRING_GET_CHARLEN(h_input)) {
			/* match fail */
			char_offset = 0;   /* not really necessary */
			DUK_ASSERT(match == 0);
			goto match_over;
		}
		char_offset = (duk_uint32_t) d;
	} else {
		/* lastIndex must be ignored for non-global regexps, but get the
		 * value for (theoretical) side effects.  No side effects can
		 * really occur, because lastIndex is a normal property and is
		 * always non-configurable for RegExp instances.
		 */
		char_offset = (duk_uint32_t) 0;
	}

	DUK_ASSERT(char_offset <= DUK_HSTRING_GET_CHARLEN(h_input));
	sp = re_ctx.input + duk_heap_strcache_offset_char2byte(thr, h_input, char_offset);

	/*
	 *  Match loop.
	 *
	 *  Try matching at different offsets until match found or input exhausted.
	 */

	/* [ ... re_obj input bc saved_buf ] */

	DUK_ASSERT(match == 0);

	for (;;) {
		/* char offset in [0, h_input->clen] (both ends inclusive), checked before entry */
		DUK_ASSERT_DISABLE(char_offset >= 0);
		DUK_ASSERT(char_offset <= DUK_HSTRING_GET_CHARLEN(h_input));

		/* Note: re_ctx.steps is intentionally not reset, it applies to the entire unanchored match */
		DUK_ASSERT(re_ctx.recursion_depth == 0);

		DUK_DDD(DUK_DDDPRINT("attempt match at char offset %ld; %p [%p,%p]",
		                     (long) char_offset, (const void *) sp,
		                     (const void *) re_ctx.input, (const void *) re_ctx.input_end));

		/*
		 *  Note:
		 *
		 *    - duk__match_regexp() is required not to longjmp() in ordinary "non-match"
		 *      conditions; a longjmp() will terminate the entire matching process.
		 *
		 *    - Clearing saved[] is not necessary because backtracking does it
		 *
		 *    - Backtracking also rewinds re_ctx.recursion back to zero, unless an
		 *      internal/limit error occurs (which causes a longjmp())
		 *
		 *    - If we supported anchored matches, we would break out here
		 *      unconditionally; however, ECMAScript regexps don't have anchored
		 *      matches.  It might make sense to implement a fast bail-out if
		 *      the regexp begins with '^' and sp is not 0: currently we'll just
		 *      run through the entire input string, trivially failing the match
		 *      at every non-zero offset.
		 */

		if (duk__match_regexp(&re_ctx, re_ctx.bytecode, sp) != NULL) {
			DUK_DDD(DUK_DDDPRINT("match at offset %ld", (long) char_offset));
			match = 1;
			break;
		}

		/* advance by one character (code point) and one char_offset */
		char_offset++;
		if (char_offset > DUK_HSTRING_GET_CHARLEN(h_input)) {
			/*
			 *  Note:
			 *
			 *    - Intentionally attempt (empty) match at char_offset == k_input->clen
			 *
			 *    - Negative char_offsets have been eliminated and char_offset is duk_uint32_t
			 *      -> no need or use for a negative check
			 */

			DUK_DDD(DUK_DDDPRINT("no match after trying all sp offsets"));
			break;
		}

		/* avoid calling at end of input, will DUK_ERROR (above check suffices to avoid this) */
		(void) duk__utf8_advance(thr, &sp, re_ctx.input, re_ctx.input_end, (duk_uint_fast32_t) 1);
	}

 match_over:

	/*
	 *  Matching complete, create result array or return a 'null'.  Update lastIndex
	 *  if necessary.  See E5 Section 15.10.6.2.
	 *
	 *  Because lastIndex is a character (not byte) offset, we need the character
	 *  length of the match which we conveniently get as a side effect of interning
	 *  the matching substring (0th index of result array).
	 *
	 *  saved[0]         start pointer (~ byte offset) of current match
	 *  saved[1]         end pointer (~ byte offset) of current match (exclusive)
	 *  char_offset      start character offset of current match (-> .index of result)
	 *  char_end_offset  end character offset (computed below)
	 */

	/* [ ... re_obj input bc saved_buf ] */

	if (match) {
#if defined(DUK_USE_ASSERTIONS)
		duk_hobject *h_res;
#endif
		duk_uint32_t char_end_offset = 0;

		DUK_DDD(DUK_DDDPRINT("regexp matches at char_offset %ld", (long) char_offset));

		DUK_ASSERT(re_ctx.nsaved >= 2);        /* must have start and end */
		DUK_ASSERT((re_ctx.nsaved % 2) == 0);  /* and even number */

		/* XXX: Array size is known before and (2 * re_ctx.nsaved) but not taken
		 * advantage of now.  The array is not compacted either, as regexp match
		 * objects are usually short lived.
		 */

		duk_push_array(thr);

#if defined(DUK_USE_ASSERTIONS)
		h_res = duk_require_hobject(thr, -1);
		DUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE(h_res));
		DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY(h_res));
		DUK_ASSERT(DUK_HOBJECT_GET_CLASS_NUMBER(h_res) == DUK_HOBJECT_CLASS_ARRAY);
#endif

		/* [ ... re_obj input bc saved_buf res_obj ] */

		duk_push_u32(thr, char_offset);
		duk_xdef_prop_stridx_short_wec(thr, -2, DUK_STRIDX_INDEX);

		duk_dup_m4(thr);
		duk_xdef_prop_stridx_short_wec(thr, -2, DUK_STRIDX_INPUT);

		for (i = 0; i < re_ctx.nsaved; i += 2) {
			/* Captures which are undefined have NULL pointers and are returned
			 * as 'undefined'.  The same is done when saved[] pointers are insane
			 * (this should, of course, never happen in practice).
			 */
			if (re_ctx.saved[i] && re_ctx.saved[i + 1] && re_ctx.saved[i + 1] >= re_ctx.saved[i]) {
				duk_push_lstring(thr,
				                 (const char *) re_ctx.saved[i],
				                 (duk_size_t) (re_ctx.saved[i+1] - re_ctx.saved[i]));
				if (i == 0) {
					/* Assumes that saved[0] and saved[1] are always
					 * set by regexp bytecode (if not, char_end_offset
					 * will be zero).  Also assumes clen reflects the
					 * correct char length.
					 */
					char_end_offset = char_offset + (duk_uint32_t) duk_get_length(thr, -1);  /* add charlen */
				}
			} else {
				duk_push_undefined(thr);
			}

			/* [ ... re_obj input bc saved_buf res_obj val ] */
			duk_put_prop_index(thr, -2, (duk_uarridx_t) (i / 2));
		}

		/* [ ... re_obj input bc saved_buf res_obj ] */

		/* NB: 'length' property is automatically updated by the array setup loop */

		if (global) {
			/* global regexp: lastIndex updated on match */
			duk_push_u32(thr, char_end_offset);
			duk_put_prop_stridx_short(thr, -6, DUK_STRIDX_LAST_INDEX);
		} else {
			/* non-global regexp: lastIndex never updated on match */
			;
		}
	} else {
		/*
		 *  No match, E5 Section 15.10.6.2, step 9.a.i - 9.a.ii apply, regardless
		 *  of 'global' flag of the RegExp.  In particular, if lastIndex is invalid
		 *  initially, it is reset to zero.
		 */

		DUK_DDD(DUK_DDDPRINT("regexp does not match"));

		duk_push_null(thr);

		/* [ ... re_obj input bc saved_buf res_obj ] */

		duk_push_int(thr, 0);
		duk_put_prop_stridx_short(thr, -6, DUK_STRIDX_LAST_INDEX);
	}

	/* [ ... re_obj input bc saved_buf res_obj ] */

	duk_insert(thr, -5);

	/* [ ... res_obj re_obj input bc saved_buf ] */

	duk_pop_n_unsafe(thr, 4);

	/* [ ... res_obj ] */

	/* XXX: these last tricks are unnecessary if the function is made
	 * a genuine native function.
	 */
}

DUK_INTERNAL void duk_regexp_match(duk_hthread *thr) {
	duk__regexp_match_helper(thr, 0 /*force_global*/);
}

/* This variant is needed by String.prototype.split(); it needs to perform
 * global-style matching on a cloned RegExp which is potentially non-global.
 */
DUK_INTERNAL void duk_regexp_match_force_global(duk_hthread *thr) {
	duk__regexp_match_helper(thr, 1 /*force_global*/);
}

#else  /* DUK_USE_REGEXP_SUPPORT */

/* regexp support disabled */

#endif  /* DUK_USE_REGEXP_SUPPORT */
#line 1 "duk_selftest.c"
/*
 *  Self tests to ensure execution environment is sane.  Intended to catch
 *  compiler/platform problems which cannot be detected at compile time.
 */

/* #include duk_internal.h -> already included */

#if defined(DUK_USE_SELF_TESTS)

/*
 *  Unions and structs for self tests
 */

typedef union {
	double d;
	duk_uint8_t x[8];
} duk__test_double_union;

/* Self test failed.  Expects a local variable 'error_count' to exist. */
#define DUK__FAILED(msg)  do { \
		DUK_D(DUK_DPRINT("self test failed: " #msg " at " DUK_FILE_MACRO ":" DUK_MACRO_STRINGIFY(DUK_LINE_MACRO))); \
		error_count++; \
	} while (0)

#define DUK__DBLUNION_CMP_TRUE(a,b)  do { \
		if (duk_memcmp((const void *) (a), (const void *) (b), sizeof(duk__test_double_union)) != 0) { \
			DUK__FAILED("double union compares false (expected true)"); \
		} \
	} while (0)

#define DUK__DBLUNION_CMP_FALSE(a,b)  do { \
		if (duk_memcmp((const void *) (a), (const void *) (b), sizeof(duk__test_double_union)) == 0) { \
			DUK__FAILED("double union compares true (expected false)"); \
		} \
	} while (0)

typedef union {
	duk_uint32_t i;
	duk_uint8_t x[8];
} duk__test_u32_union;

#if defined(DUK_USE_INTEGER_LE)
#define DUK__U32_INIT(u, a, b, c, d) do { \
		(u)->x[0] = (d); (u)->x[1] = (c); (u)->x[2] = (b); (u)->x[3] = (a); \
	} while (0)
#elif defined(DUK_USE_INTEGER_ME)
#error integer mixed endian not supported now
#elif defined(DUK_USE_INTEGER_BE)
#define DUK__U32_INIT(u, a, b, c, d) do { \
		(u)->x[0] = (a); (u)->x[1] = (b); (u)->x[2] = (c); (u)->x[3] = (d); \
	} while (0)
#else
#error unknown integer endianness
#endif

#if defined(DUK_USE_DOUBLE_LE)
#define DUK__DOUBLE_INIT(u, a, b, c, d, e, f, g, h) do { \
		(u)->x[0] = (h); (u)->x[1] = (g); (u)->x[2] = (f); (u)->x[3] = (e); \
		(u)->x[4] = (d); (u)->x[5] = (c); (u)->x[6] = (b); (u)->x[7] = (a); \
	} while (0)
#define DUK__DOUBLE_COMPARE(u, a, b, c, d, e, f, g, h) \
	((u)->x[0] == (h) && (u)->x[1] == (g) && (u)->x[2] == (f) && (u)->x[3] == (e) && \
	 (u)->x[4] == (d) && (u)->x[5] == (c) && (u)->x[6] == (b) && (u)->x[7] == (a))
#elif defined(DUK_USE_DOUBLE_ME)
#define DUK__DOUBLE_INIT(u, a, b, c, d, e, f, g, h) do { \
		(u)->x[0] = (d); (u)->x[1] = (c); (u)->x[2] = (b); (u)->x[3] = (a); \
		(u)->x[4] = (h); (u)->x[5] = (g); (u)->x[6] = (f); (u)->x[7] = (e); \
	} while (0)
#define DUK__DOUBLE_COMPARE(u, a, b, c, d, e, f, g, h) \
	((u)->x[0] == (d) && (u)->x[1] == (c) && (u)->x[2] == (b) && (u)->x[3] == (a) && \
	 (u)->x[4] == (h) && (u)->x[5] == (g) && (u)->x[6] == (f) && (u)->x[7] == (e))
#elif defined(DUK_USE_DOUBLE_BE)
#define DUK__DOUBLE_INIT(u, a, b, c, d, e, f, g, h) do { \
		(u)->x[0] = (a); (u)->x[1] = (b); (u)->x[2] = (c); (u)->x[3] = (d); \
		(u)->x[4] = (e); (u)->x[5] = (f); (u)->x[6] = (g); (u)->x[7] = (h); \
	} while (0)
#define DUK__DOUBLE_COMPARE(u, a, b, c, d, e, f, g, h) \
	((u)->x[0] == (a) && (u)->x[1] == (b) && (u)->x[2] == (c) && (u)->x[3] == (d) && \
	 (u)->x[4] == (e) && (u)->x[5] == (f) && (u)->x[6] == (g) && (u)->x[7] == (h))
#else
#error unknown double endianness
#endif

/*
 *  Various sanity checks for typing
 */

DUK_LOCAL duk_uint_t duk__selftest_types(void) {
	duk_uint_t error_count = 0;

	if (!(sizeof(duk_int8_t) == 1 &&
	      sizeof(duk_uint8_t) == 1 &&
	      sizeof(duk_int16_t) == 2 &&
	      sizeof(duk_uint16_t) == 2 &&
	      sizeof(duk_int32_t) == 4 &&
	      sizeof(duk_uint32_t) == 4)) {
		DUK__FAILED("duk_(u)int{8,16,32}_t size");
	}
#if defined(DUK_USE_64BIT_OPS)
	if (!(sizeof(duk_int64_t) == 8 &&
	      sizeof(duk_uint64_t) == 8)) {
		DUK__FAILED("duk_(u)int64_t size");
	}
#endif

	if (!(sizeof(duk_size_t) >= sizeof(duk_uint_t))) {
		/* Some internal code now assumes that all duk_uint_t values
		 * can be expressed with a duk_size_t.
		 */
		DUK__FAILED("duk_size_t is smaller than duk_uint_t");
	}
	if (!(sizeof(duk_int_t) >= 4)) {
		DUK__FAILED("duk_int_t is not 32 bits");
	}

	return error_count;
}

/*
 *  Packed tval sanity
 */

DUK_LOCAL duk_uint_t duk__selftest_packed_tval(void) {
	duk_uint_t error_count = 0;

#if defined(DUK_USE_PACKED_TVAL)
	if (sizeof(void *) > 4) {
		DUK__FAILED("packed duk_tval in use but sizeof(void *) > 4");
	}
#endif

	return error_count;
}

/*
 *  Two's complement arithmetic.
 */

DUK_LOCAL duk_uint_t duk__selftest_twos_complement(void) {
	duk_uint_t error_count = 0;
	volatile int test;
	test = -1;

	/* Note that byte order doesn't affect this test: all bytes in
	 * 'test' will be 0xFF for two's complement.
	 */
	if (((volatile duk_uint8_t *) &test)[0] != (duk_uint8_t) 0xff) {
		DUK__FAILED("two's complement arithmetic");
	}

	return error_count;
}

/*
 *  Byte order.  Important to self check, because on some exotic platforms
 *  there is no actual detection but rather assumption based on platform
 *  defines.
 */

DUK_LOCAL duk_uint_t duk__selftest_byte_order(void) {
	duk_uint_t error_count = 0;
	duk__test_u32_union u1;
	duk__test_double_union u2;

	/*
	 *  >>> struct.pack('>d', 102030405060).encode('hex')
	 *  '4237c17c6dc40000'
	 */

	DUK__U32_INIT(&u1, 0xde, 0xad, 0xbe, 0xef);
	DUK__DOUBLE_INIT(&u2, 0x42, 0x37, 0xc1, 0x7c, 0x6d, 0xc4, 0x00, 0x00);

	if (u1.i != (duk_uint32_t) 0xdeadbeefUL) {
		DUK__FAILED("duk_uint32_t byte order");
	}

	if (!duk_double_equals(u2.d, 102030405060.0)) {
		DUK__FAILED("double byte order");
	}

	return error_count;
}

/*
 *  DUK_BSWAP macros
 */

DUK_LOCAL duk_uint_t duk__selftest_bswap_macros(void) {
	duk_uint_t error_count = 0;
	volatile duk_uint32_t x32_input, x32_output;
	duk_uint32_t x32;
	volatile duk_uint16_t x16_input, x16_output;
	duk_uint16_t x16;
	duk_double_union du;
	duk_double_t du_diff;
#if defined(DUK_BSWAP64)
	volatile duk_uint64_t x64_input, x64_output;
	duk_uint64_t x64;
#endif

	/* Cover both compile time and runtime bswap operations, as these
	 * may have different bugs.
	 */

	x16_input = 0xbeefUL;
	x16 = x16_input;
	x16 = DUK_BSWAP16(x16);
	x16_output = x16;
	if (x16_output != (duk_uint16_t) 0xefbeUL) {
		DUK__FAILED("DUK_BSWAP16");
	}

	x16 = 0xbeefUL;
	x16 = DUK_BSWAP16(x16);
	if (x16 != (duk_uint16_t) 0xefbeUL) {
		DUK__FAILED("DUK_BSWAP16");
	}

	x32_input = 0xdeadbeefUL;
	x32 = x32_input;
	x32 = DUK_BSWAP32(x32);
	x32_output = x32;
	if (x32_output != (duk_uint32_t) 0xefbeaddeUL) {
		DUK__FAILED("DUK_BSWAP32");
	}

	x32 = 0xdeadbeefUL;
	x32 = DUK_BSWAP32(x32);
	if (x32 != (duk_uint32_t) 0xefbeaddeUL) {
		DUK__FAILED("DUK_BSWAP32");
	}

#if defined(DUK_BSWAP64)
	x64_input = DUK_U64_CONSTANT(0x8899aabbccddeeff);
	x64 = x64_input;
	x64 = DUK_BSWAP64(x64);
	x64_output = x64;
	if (x64_output != (duk_uint64_t) DUK_U64_CONSTANT(0xffeeddccbbaa9988)) {
		DUK__FAILED("DUK_BSWAP64");
	}

	x64 = DUK_U64_CONSTANT(0x8899aabbccddeeff);
	x64 = DUK_BSWAP64(x64);
	if (x64 != (duk_uint64_t) DUK_U64_CONSTANT(0xffeeddccbbaa9988)) {
		DUK__FAILED("DUK_BSWAP64");
	}
#endif

	/* >>> struct.unpack('>d', '4000112233445566'.decode('hex'))
	 * (2.008366013071895,)
	 */

	du.uc[0] = 0x40; du.uc[1] = 0x00; du.uc[2] = 0x11; du.uc[3] = 0x22;
	du.uc[4] = 0x33; du.uc[5] = 0x44; du.uc[6] = 0x55; du.uc[7] = 0x66;
	DUK_DBLUNION_DOUBLE_NTOH(&du);
	du_diff = du.d - 2.008366013071895;
#if 0
	DUK_D(DUK_DPRINT("du_diff: %lg\n", (double) du_diff));
#endif
	if (du_diff > 1e-15) {
		/* Allow very small lenience because some compilers won't parse
		 * exact IEEE double constants (happened in matrix testing with
		 * Linux gcc-4.8 -m32 at least).
		 */
#if 0
		DUK_D(DUK_DPRINT("Result of DUK_DBLUNION_DOUBLE_NTOH: %02x %02x %02x %02x %02x %02x %02x %02x\n",
		            (unsigned int) du.uc[0], (unsigned int) du.uc[1],
		            (unsigned int) du.uc[2], (unsigned int) du.uc[3],
		            (unsigned int) du.uc[4], (unsigned int) du.uc[5],
		            (unsigned int) du.uc[6], (unsigned int) du.uc[7]));
#endif
		DUK__FAILED("DUK_DBLUNION_DOUBLE_NTOH");
	}

	return error_count;
}

/*
 *  Basic double / byte union memory layout.
 */

DUK_LOCAL duk_uint_t duk__selftest_double_union_size(void) {
	duk_uint_t error_count = 0;

	if (sizeof(duk__test_double_union) != 8) {
		DUK__FAILED("invalid union size");
	}

	return error_count;
}

/*
 *  Union aliasing, see misc/clang_aliasing.c.
 */

DUK_LOCAL duk_uint_t duk__selftest_double_aliasing(void) {
	/* This testcase fails when Emscripten-generated code runs on Firefox.
	 * It's not an issue because the failure should only affect packed
	 * duk_tval representation, which is not used with Emscripten.
	 */
#if defined(DUK_USE_PACKED_TVAL)
	duk_uint_t error_count = 0;
	duk__test_double_union a, b;

	/* Test signaling NaN and alias assignment in all endianness combinations.
	 */

	/* little endian */
	a.x[0] = 0x11; a.x[1] = 0x22; a.x[2] = 0x33; a.x[3] = 0x44;
	a.x[4] = 0x00; a.x[5] = 0x00; a.x[6] = 0xf1; a.x[7] = 0xff;
	b = a;
	DUK__DBLUNION_CMP_TRUE(&a, &b);

	/* big endian */
	a.x[0] = 0xff; a.x[1] = 0xf1; a.x[2] = 0x00; a.x[3] = 0x00;
	a.x[4] = 0x44; a.x[5] = 0x33; a.x[6] = 0x22; a.x[7] = 0x11;
	b = a;
	DUK__DBLUNION_CMP_TRUE(&a, &b);

	/* mixed endian */
	a.x[0] = 0x00; a.x[1] = 0x00; a.x[2] = 0xf1; a.x[3] = 0xff;
	a.x[4] = 0x11; a.x[5] = 0x22; a.x[6] = 0x33; a.x[7] = 0x44;
	b = a;
	DUK__DBLUNION_CMP_TRUE(&a, &b);

	return error_count;
#else
	DUK_D(DUK_DPRINT("skip double aliasing self test when duk_tval is not packed"));
	return 0;
#endif
}

/*
 *  Zero sign, see misc/tcc_zerosign2.c.
 */

DUK_LOCAL duk_uint_t duk__selftest_double_zero_sign(void) {
	duk_uint_t error_count = 0;
	duk__test_double_union a, b;

	a.d = 0.0;
	b.d = -a.d;
	DUK__DBLUNION_CMP_FALSE(&a, &b);

	return error_count;
}

/*
 *  Rounding mode: Duktape assumes round-to-nearest, check that this is true.
 *  If we had C99 fenv.h we could check that fegetround() == FE_TONEAREST,
 *  but we don't want to rely on that header; and even if we did, it's good
 *  to ensure the rounding actually works.
 */

DUK_LOCAL duk_uint_t duk__selftest_double_rounding(void) {
	duk_uint_t error_count = 0;
	duk__test_double_union a, b, c;

#if 0
	/* Include <fenv.h> and test manually; these trigger failures: */
	fesetround(FE_UPWARD);
	fesetround(FE_DOWNWARD);
	fesetround(FE_TOWARDZERO);

	/* This is the default and passes. */
	fesetround(FE_TONEAREST);
#endif

	/* Rounding tests check that none of the other modes (round to
	 * +Inf, round to -Inf, round to zero) can be active:
	 * http://www.gnu.org/software/libc/manual/html_node/Rounding.html
	 */

	/* 1.0 + 2^(-53): result is midway between 1.0 and 1.0 + ulp.
	 * Round to nearest: 1.0
	 * Round to +Inf:    1.0 + ulp
	 * Round to -Inf:    1.0
	 * Round to zero:    1.0
	 * => Correct result eliminates round to +Inf.
	 */
	DUK__DOUBLE_INIT(&a, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
	DUK__DOUBLE_INIT(&b, 0x3c, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
	duk_memset((void *) &c, 0, sizeof(c));
	c.d = a.d + b.d;
	if (!DUK__DOUBLE_COMPARE(&c, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)) {
		DUK_D(DUK_DPRINT("broken result (native endiannesss): %02x %02x %02x %02x %02x %02x %02x %02x",
		                 (unsigned int) c.x[0], (unsigned int) c.x[1],
		                 (unsigned int) c.x[2], (unsigned int) c.x[3],
		                 (unsigned int) c.x[4], (unsigned int) c.x[5],
		                 (unsigned int) c.x[6], (unsigned int) c.x[7]));
		DUK__FAILED("invalid result from 1.0 + 0.5ulp");
	}

	/* (1.0 + ulp) + 2^(-53): result is midway between 1.0 + ulp and 1.0 + 2*ulp.
	 * Round to nearest: 1.0 + 2*ulp (round to even mantissa)
	 * Round to +Inf:    1.0 + 2*ulp
	 * Round to -Inf:    1.0 + ulp
	 * Round to zero:    1.0 + ulp
	 * => Correct result eliminates round to -Inf and round to zero.
	 */
	DUK__DOUBLE_INIT(&a, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01);
	DUK__DOUBLE_INIT(&b, 0x3c, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
	duk_memset((void *) &c, 0, sizeof(c));
	c.d = a.d + b.d;
	if (!DUK__DOUBLE_COMPARE(&c, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02)) {
		DUK_D(DUK_DPRINT("broken result (native endiannesss): %02x %02x %02x %02x %02x %02x %02x %02x",
		                 (unsigned int) c.x[0], (unsigned int) c.x[1],
		                 (unsigned int) c.x[2], (unsigned int) c.x[3],
		                 (unsigned int) c.x[4], (unsigned int) c.x[5],
		                 (unsigned int) c.x[6], (unsigned int) c.x[7]));
		DUK__FAILED("invalid result from (1.0 + ulp) + 0.5ulp");
	}

	/* Could do negative number testing too, but the tests above should
	 * differentiate between IEEE 754 rounding modes.
	 */
	return error_count;
}

/*
 *  fmod(): often a portability issue in embedded or bare platform targets.
 *  Check for at least minimally correct behavior.  Unlike some other math
 *  functions (like cos()) Duktape relies on fmod() internally too.
 */

DUK_LOCAL duk_uint_t duk__selftest_fmod(void) {
	duk_uint_t error_count = 0;
	duk__test_double_union u1, u2;
	volatile duk_double_t t1, t2, t3;

	/* fmod() with integer argument and exponent 2^32 is used by e.g.
	 * ToUint32() and some Duktape internals.
	 */
	u1.d = DUK_FMOD(10.0, 4294967296.0);
	u2.d = 10.0;
	DUK__DBLUNION_CMP_TRUE(&u1, &u2);

	u1.d = DUK_FMOD(4294967306.0, 4294967296.0);
	u2.d = 10.0;
	DUK__DBLUNION_CMP_TRUE(&u1, &u2);

	u1.d = DUK_FMOD(73014444042.0, 4294967296.0);
	u2.d = 10.0;
	DUK__DBLUNION_CMP_TRUE(&u1, &u2);

	/* 52-bit integer split into two parts:
	 * >>> 0x1fedcba9876543
	 * 8987183256397123
	 * >>> float(0x1fedcba9876543) / float(2**53)
	 * 0.9977777777777778
	 */
	u1.d = DUK_FMOD(8987183256397123.0, 4294967296.0);
	u2.d = (duk_double_t) 0xa9876543UL;
	DUK__DBLUNION_CMP_TRUE(&u1, &u2);
	t1 = 8987183256397123.0;
	t2 = 4294967296.0;
	t3 = t1 / t2;
	u1.d = DUK_FLOOR(t3);
	u2.d = (duk_double_t) 0x1fedcbUL;
	DUK__DBLUNION_CMP_TRUE(&u1, &u2);

	/* C99 behavior is for fmod() result sign to mathc argument sign. */
	u1.d = DUK_FMOD(-10.0, 4294967296.0);
	u2.d = -10.0;
	DUK__DBLUNION_CMP_TRUE(&u1, &u2);

	u1.d = DUK_FMOD(-4294967306.0, 4294967296.0);
	u2.d = -10.0;
	DUK__DBLUNION_CMP_TRUE(&u1, &u2);

	u1.d = DUK_FMOD(-73014444042.0, 4294967296.0);
	u2.d = -10.0;
	DUK__DBLUNION_CMP_TRUE(&u1, &u2);

	return error_count;
}

/*
 *  Struct size/alignment if platform requires it
 *
 *  There are some compiler specific struct padding pragmas etc in use, this
 *  selftest ensures they're correctly detected and used.
 */

DUK_LOCAL duk_uint_t duk__selftest_struct_align(void) {
	duk_uint_t error_count = 0;

#if (DUK_USE_ALIGN_BY == 4)
	if ((sizeof(duk_hbuffer_fixed) % 4) != 0) {
		DUK__FAILED("sizeof(duk_hbuffer_fixed) not aligned to 4");
	}
#elif (DUK_USE_ALIGN_BY == 8)
	if ((sizeof(duk_hbuffer_fixed) % 8) != 0) {
		DUK__FAILED("sizeof(duk_hbuffer_fixed) not aligned to 8");
	}
#elif (DUK_USE_ALIGN_BY == 1)
	/* no check */
#else
#error invalid DUK_USE_ALIGN_BY
#endif
	return error_count;
}

/*
 *  64-bit arithmetic
 *
 *  There are some platforms/compilers where 64-bit types are available
 *  but don't work correctly.  Test for known cases.
 */

DUK_LOCAL duk_uint_t duk__selftest_64bit_arithmetic(void) {
	duk_uint_t error_count = 0;
#if defined(DUK_USE_64BIT_OPS)
	volatile duk_int64_t i;
	volatile duk_double_t d;

	/* Catch a double-to-int64 cast issue encountered in practice. */
	d = 2147483648.0;
	i = (duk_int64_t) d;
	if (i != DUK_I64_CONSTANT(0x80000000)) {
		DUK__FAILED("casting 2147483648.0 to duk_int64_t failed");
	}
#else
	/* nop */
#endif
	return error_count;
}

/*
 *  Casting
 */

DUK_LOCAL duk_uint_t duk__selftest_cast_double_to_small_uint(void) {
	/*
	 *  https://github.com/svaarala/duktape/issues/127#issuecomment-77863473
	 */

	duk_uint_t error_count = 0;

	duk_double_t d1, d2;
	duk_small_uint_t u;

	duk_double_t d1v, d2v;
	duk_small_uint_t uv;

	/* Test without volatiles */

	d1 = 1.0;
	u = (duk_small_uint_t) d1;
	d2 = (duk_double_t) u;

	if (!(duk_double_equals(d1, 1.0) && u == 1 && duk_double_equals(d2, 1.0) && duk_double_equals(d1, d2))) {
		DUK__FAILED("double to duk_small_uint_t cast failed");
	}

	/* Same test with volatiles */

	d1v = 1.0;
	uv = (duk_small_uint_t) d1v;
	d2v = (duk_double_t) uv;

	if (!(duk_double_equals(d1v, 1.0) && uv == 1 && duk_double_equals(d2v, 1.0) && duk_double_equals(d1v, d2v))) {
		DUK__FAILED("double to duk_small_uint_t cast failed");
	}

	return error_count;
}

DUK_LOCAL duk_uint_t duk__selftest_cast_double_to_uint32(void) {
	/*
	 *  This test fails on an exotic ARM target; double-to-uint
	 *  cast is incorrectly clamped to -signed- int highest value.
	 *
	 *  https://github.com/svaarala/duktape/issues/336
	 */

	duk_uint_t error_count = 0;
	duk_double_t dv;
	duk_uint32_t uv;

	dv = 3735928559.0;  /* 0xdeadbeef in decimal */
	uv = (duk_uint32_t) dv;

	if (uv != 0xdeadbeefUL) {
		DUK__FAILED("double to duk_uint32_t cast failed");
	}

	return error_count;
}

/*
 *  Minimal test of user supplied allocation functions
 *
 *    - Basic alloc + realloc + free cycle
 *
 *    - Realloc to significantly larger size to (hopefully) trigger a
 *      relocation and check that relocation copying works
 */

DUK_LOCAL duk_uint_t duk__selftest_alloc_funcs(duk_alloc_function alloc_func,
                                               duk_realloc_function realloc_func,
                                               duk_free_function free_func,
                                               void *udata) {
	duk_uint_t error_count = 0;
	void *ptr;
	void *new_ptr;
	duk_small_int_t i, j;
	unsigned char x;

	if (alloc_func == NULL || realloc_func == NULL || free_func == NULL) {
		return 0;
	}

	for (i = 1; i <= 256; i++) {
		ptr = alloc_func(udata, (duk_size_t) i);
		if (ptr == NULL) {
			DUK_D(DUK_DPRINT("alloc failed, ignore"));
			continue;  /* alloc failed, ignore */
		}
		for (j = 0; j < i; j++) {
			((unsigned char *) ptr)[j] = (unsigned char) (0x80 + j);
		}
		new_ptr = realloc_func(udata, ptr, 1024);
		if (new_ptr == NULL) {
			DUK_D(DUK_DPRINT("realloc failed, ignore"));
			free_func(udata, ptr);
			continue;  /* realloc failed, ignore */
		}
		ptr = new_ptr;
		for (j = 0; j < i; j++) {
			x = ((unsigned char *) ptr)[j];
			if (x != (unsigned char) (0x80 + j)) {
				DUK_D(DUK_DPRINT("byte at index %ld doesn't match after realloc: %02lx",
				                 (long) j, (unsigned long) x));
				DUK__FAILED("byte compare after realloc");
				break;
			}
		}
		free_func(udata, ptr);
	}

	return error_count;
}

/*
 *  Self test main
 */

DUK_INTERNAL duk_uint_t duk_selftest_run_tests(duk_alloc_function alloc_func,
                                               duk_realloc_function realloc_func,
                                               duk_free_function free_func,
                                               void *udata) {
	duk_uint_t error_count = 0;

	DUK_D(DUK_DPRINT("self test starting"));

	error_count += duk__selftest_types();
	error_count += duk__selftest_packed_tval();
	error_count += duk__selftest_twos_complement();
	error_count += duk__selftest_byte_order();
	error_count += duk__selftest_bswap_macros();
	error_count += duk__selftest_double_union_size();
	error_count += duk__selftest_double_aliasing();
	error_count += duk__selftest_double_zero_sign();
	error_count += duk__selftest_double_rounding();
	error_count += duk__selftest_fmod();
	error_count += duk__selftest_struct_align();
	error_count += duk__selftest_64bit_arithmetic();
	error_count += duk__selftest_cast_double_to_small_uint();
	error_count += duk__selftest_cast_double_to_uint32();
	error_count += duk__selftest_alloc_funcs(alloc_func, realloc_func, free_func, udata);

	DUK_D(DUK_DPRINT("self test complete, total error count: %ld", (long) error_count));

	return error_count;
}

#endif  /* DUK_USE_SELF_TESTS */

/* automatic undefs */
#undef DUK__DBLUNION_CMP_FALSE
#undef DUK__DBLUNION_CMP_TRUE
#undef DUK__DOUBLE_COMPARE
#undef DUK__DOUBLE_INIT
#undef DUK__FAILED
#undef DUK__U32_INIT
/* #include duk_internal.h -> already included */
#line 2 "duk_tval.c"

#if defined(DUK_USE_FASTINT)

/*
 *  Manually optimized double-to-fastint downgrade check.
 *
 *  This check has a large impact on performance, especially for fastint
 *  slow paths, so must be changed carefully.  The code should probably be
 *  optimized for the case where the result does not fit into a fastint,
 *  to minimize the penalty for "slow path code" dealing with fractions etc.
 *
 *  At least on one tested soft float ARM platform double-to-int64 coercion
 *  is very slow (and sometimes produces incorrect results, see self tests).
 *  This algorithm combines a fastint compatibility check and extracting the
 *  integer value from an IEEE double for setting the tagged fastint.  For
 *  other platforms a more naive approach might be better.
 *
 *  See doc/fastint.rst for details.
 */

DUK_INTERNAL DUK_ALWAYS_INLINE void duk_tval_set_number_chkfast_fast(duk_tval *tv, duk_double_t x) {
	duk_double_union du;
	duk_int64_t i;
	duk_small_int_t expt;
	duk_small_int_t shift;

	/* XXX: optimize for packed duk_tval directly? */

	du.d = x;
	i = (duk_int64_t) DUK_DBLUNION_GET_INT64(&du);
	expt = (duk_small_int_t) ((i >> 52) & 0x07ff);
	shift = expt - 1023;

	if (shift >= 0 && shift <= 46) {  /* exponents 1023 to 1069 */
		duk_int64_t t;

		if (((DUK_I64_CONSTANT(0x000fffffffffffff) >> shift) & i) == 0) {
			t = i | DUK_I64_CONSTANT(0x0010000000000000);  /* implicit leading one */
			t = t & DUK_I64_CONSTANT(0x001fffffffffffff);
			t = t >> (52 - shift);
			if (i < 0) {
				t = -t;
			}
			DUK_TVAL_SET_FASTINT(tv, t);
			return;
		}
	} else if (shift == -1023) {  /* exponent 0 */
		if (i >= 0 && (i & DUK_I64_CONSTANT(0x000fffffffffffff)) == 0) {
			/* Note: reject negative zero. */
			DUK_TVAL_SET_FASTINT(tv, (duk_int64_t) 0);
			return;
		}
	} else if (shift == 47) {  /* exponent 1070 */
		if (i < 0 && (i & DUK_I64_CONSTANT(0x000fffffffffffff)) == 0) {
			DUK_TVAL_SET_FASTINT(tv, (duk_int64_t) DUK_FASTINT_MIN);
			return;
		}
	}

	DUK_TVAL_SET_DOUBLE(tv, x);
	return;
}

DUK_INTERNAL DUK_NOINLINE void duk_tval_set_number_chkfast_slow(duk_tval *tv, duk_double_t x) {
	duk_tval_set_number_chkfast_fast(tv, x);
}

/*
 *  Manually optimized number-to-double conversion
 */

#if defined(DUK_USE_FASTINT) && defined(DUK_USE_PACKED_TVAL)
DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_tval_get_number_packed(duk_tval *tv) {
	duk_double_union du;
	duk_uint64_t t;

	t = (duk_uint64_t) DUK_DBLUNION_GET_UINT64(tv);
	if ((t >> 48) != DUK_TAG_FASTINT) {
		return tv->d;
	} else if (t & DUK_U64_CONSTANT(0x0000800000000000)) {
		t = (duk_uint64_t) (-((duk_int64_t) t));  /* avoid unary minus on unsigned */
		t = t & DUK_U64_CONSTANT(0x0000ffffffffffff);  /* negative */
		t |= DUK_U64_CONSTANT(0xc330000000000000);
		DUK_DBLUNION_SET_UINT64(&du, t);
		return du.d + 4503599627370496.0;  /* 1 << 52 */
	} else if (t != 0) {
		t &= DUK_U64_CONSTANT(0x0000ffffffffffff);  /* positive */
		t |= DUK_U64_CONSTANT(0x4330000000000000);
		DUK_DBLUNION_SET_UINT64(&du, t);
		return du.d - 4503599627370496.0;  /* 1 << 52 */
	} else {
		return 0.0;  /* zero */
	}
}
#endif  /* DUK_USE_FASTINT && DUK_USE_PACKED_TVAL */

#if 0  /* unused */
#if defined(DUK_USE_FASTINT) && !defined(DUK_USE_PACKED_TVAL)
DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_tval_get_number_unpacked(duk_tval *tv) {
	duk_double_union du;
	duk_uint64_t t;

	DUK_ASSERT(tv->t == DUK_TAG_NUMBER || tv->t == DUK_TAG_FASTINT);

	if (tv->t == DUK_TAG_FASTINT) {
		if (tv->v.fi >= 0) {
			t = DUK_U64_CONSTANT(0x4330000000000000) | (duk_uint64_t) tv->v.fi;
			DUK_DBLUNION_SET_UINT64(&du, t);
			return du.d - 4503599627370496.0;  /* 1 << 52 */
		} else {
			t = DUK_U64_CONSTANT(0xc330000000000000) | (duk_uint64_t) (-tv->v.fi);
			DUK_DBLUNION_SET_UINT64(&du, t);
			return du.d + 4503599627370496.0;  /* 1 << 52 */
		}
	} else {
		return tv->v.d;
	}
}
#endif  /* DUK_USE_FASTINT && DUK_USE_PACKED_TVAL */
#endif  /* 0 */

#if defined(DUK_USE_FASTINT) && !defined(DUK_USE_PACKED_TVAL)
DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_tval_get_number_unpacked_fastint(duk_tval *tv) {
	duk_double_union du;
	duk_uint64_t t;

	DUK_ASSERT(tv->t == DUK_TAG_FASTINT);

	if (tv->v.fi >= 0) {
		t = DUK_U64_CONSTANT(0x4330000000000000) | (duk_uint64_t) tv->v.fi;
		DUK_DBLUNION_SET_UINT64(&du, t);
		return du.d - 4503599627370496.0;  /* 1 << 52 */
	} else {
		t = DUK_U64_CONSTANT(0xc330000000000000) | (duk_uint64_t) (-tv->v.fi);
		DUK_DBLUNION_SET_UINT64(&du, t);
		return du.d + 4503599627370496.0;  /* 1 << 52 */
	}
}
#endif  /* DUK_USE_FASTINT && DUK_USE_PACKED_TVAL */

#endif  /* DUK_USE_FASTINT */

/*
 *  Assertion helpers.
 */

#if defined(DUK_USE_ASSERTIONS)
DUK_INTERNAL void duk_tval_assert_valid(duk_tval *tv) {
	DUK_ASSERT(tv != NULL);
}
#endif
#line 1 "duk_unicode_tables.c"
/*
 *  Unicode support tables automatically generated during build.
 */

/* #include duk_internal.h -> already included */

/*
 *  Unicode tables containing ranges of Unicode characters in a
 *  packed format.  These tables are used to match non-ASCII
 *  characters of complex productions by resorting to a linear
 *  range-by-range comparison.  This is very slow, but is expected
 *  to be very rare in practical ECMAScript source code, and thus
 *  compactness is most important.
 *
 *  The tables are matched using uni_range_match() and the format
 *  is described in tools/extract_chars.py.
 */

#if defined(DUK_USE_SOURCE_NONBMP)
/* IdentifierStart production with ASCII excluded */
/* duk_unicode_ids_noa[] */
/*
 *  Automatically generated by extract_chars.py, do not edit!
 */

const duk_uint8_t duk_unicode_ids_noa[1116] = {
249,176,176,80,111,7,47,15,47,254,11,197,191,0,72,2,15,115,66,19,50,7,2,34,
2,240,66,244,50,247,185,249,98,241,99,7,241,159,57,240,181,63,31,241,191,
21,18,245,50,15,1,24,27,35,15,2,2,240,239,15,244,156,15,10,241,26,21,6,240,
101,10,4,15,9,240,152,175,39,240,82,127,56,242,100,15,4,8,159,1,240,5,115,
19,240,98,98,4,52,15,2,14,18,47,0,27,9,85,19,240,98,98,18,18,31,17,50,15,5,
47,2,130,34,240,98,98,18,68,15,4,15,1,31,9,12,115,19,240,98,98,18,68,15,16,
18,47,1,15,3,2,84,34,52,18,2,20,20,36,191,8,15,38,114,34,240,114,240,4,15,
12,38,31,16,5,114,34,240,114,146,68,15,18,2,31,1,31,4,114,34,241,147,15,2,
6,41,47,10,86,240,36,240,130,130,3,111,44,242,2,29,111,44,18,2,66,240,130,
2,146,26,3,66,15,7,63,18,15,49,114,241,79,13,79,101,241,191,6,15,2,85,52,4,
24,37,205,15,3,241,98,6,3,241,178,255,224,63,35,54,32,35,63,25,35,63,17,35,
54,32,35,62,47,41,35,63,51,241,127,0,240,47,70,53,79,254,21,227,240,18,240,
166,243,180,168,194,63,0,240,47,0,240,47,0,194,47,1,242,79,21,5,15,53,244,
152,67,241,34,6,243,107,240,255,35,240,227,76,241,197,240,175,40,240,122,
242,95,68,15,79,241,255,3,111,41,240,238,27,241,207,12,241,79,27,43,241,67,
136,241,179,47,27,50,82,20,6,251,15,50,255,224,8,53,63,22,53,55,32,32,32,
47,15,63,37,38,32,66,38,67,53,92,98,38,246,96,224,240,44,245,112,80,57,32,
68,112,32,32,35,42,51,100,80,240,63,25,255,233,107,241,242,241,242,247,87,
52,29,241,98,6,3,242,136,15,2,240,122,98,98,98,98,98,98,98,111,66,15,254,
12,146,240,184,132,52,95,70,114,47,74,35,111,27,47,78,240,63,11,242,127,0,
255,224,244,255,240,0,138,143,60,255,240,4,14,47,2,255,227,127,243,95,30,
63,253,79,0,177,240,111,31,240,47,15,63,64,241,152,63,87,63,37,52,242,42,
34,35,47,7,240,255,36,240,15,34,243,5,64,33,207,12,191,7,240,191,13,143,31,
240,224,240,36,41,180,47,25,240,146,39,240,111,7,64,79,34,32,65,52,48,32,
240,162,58,130,213,53,53,166,38,47,27,43,159,99,240,255,255,0,26,150,223,7,
95,33,255,240,0,255,143,254,6,3,245,175,24,109,70,2,146,194,66,2,18,18,245,
207,19,255,224,93,240,79,48,63,38,241,171,246,100,47,119,241,111,10,127,10,
207,73,69,53,53,50,241,91,47,10,47,3,33,46,61,241,79,107,243,127,37,255,
223,13,79,33,242,31,16,239,14,111,22,191,14,63,20,87,36,241,207,142,240,79,
20,95,20,95,24,159,36,248,239,254,2,154,240,107,127,138,83,2,241,194,20,3,
240,123,240,122,240,255,51,240,50,27,240,107,240,175,56,242,135,31,50,15,1,
50,34,240,223,28,240,212,240,223,21,114,240,207,13,242,107,240,107,240,62,
240,47,96,243,159,41,242,62,242,62,241,79,254,13,15,13,176,159,6,248,207,7,
223,37,243,223,29,241,47,9,240,207,20,240,240,207,19,64,223,32,240,3,240,
112,32,241,95,2,47,9,244,102,32,35,46,41,143,31,241,135,49,63,6,38,33,36,
64,240,64,212,249,15,37,240,67,240,96,241,47,32,240,97,32,250,175,31,241,
179,241,111,32,240,96,242,223,27,224,243,159,11,253,127,28,246,111,48,241,
16,249,39,63,23,240,32,32,240,224,191,24,128,240,112,207,30,240,80,241,79,
41,255,152,47,21,240,48,242,63,14,246,38,33,47,22,240,112,240,181,33,47,16,
240,0,255,224,59,240,63,254,0,31,254,40,207,88,245,255,3,251,79,254,155,15,
254,50,31,254,236,95,254,19,159,255,0,16,173,255,225,43,143,15,246,63,14,
240,79,32,240,35,241,31,5,111,3,255,225,164,243,15,114,243,182,15,52,207,
50,18,15,14,255,240,0,110,169,255,225,229,255,240,1,64,31,254,1,31,35,47,3,
57,255,224,126,255,231,248,245,182,196,136,159,255,0,6,90,244,82,243,114,
19,3,19,50,178,2,98,243,18,51,114,98,240,194,50,66,4,98,255,224,70,63,9,47,
9,47,15,47,9,47,15,47,9,47,15,47,9,47,15,47,9,39,255,232,40,241,219,111,2,
15,254,6,95,28,255,228,8,251,95,45,243,72,15,254,58,131,47,11,33,32,48,41,
35,32,32,112,80,32,32,34,33,32,48,32,32,32,32,33,32,51,38,35,35,32,41,47,1,
98,36,47,1,255,240,0,3,143,255,0,149,201,241,191,254,242,124,252,227,255,
240,0,87,79,0,255,240,0,194,63,254,177,63,254,17,0,
};
#else
/* IdentifierStart production with ASCII and non-BMP excluded */
/* duk_unicode_ids_noabmp[] */
/*
 *  Automatically generated by extract_chars.py, do not edit!
 */

const duk_uint8_t duk_unicode_ids_noabmp[625] = {
249,176,176,80,111,7,47,15,47,254,11,197,191,0,72,2,15,115,66,19,50,7,2,34,
2,240,66,244,50,247,185,249,98,241,99,7,241,159,57,240,181,63,31,241,191,
21,18,245,50,15,1,24,27,35,15,2,2,240,239,15,244,156,15,10,241,26,21,6,240,
101,10,4,15,9,240,152,175,39,240,82,127,56,242,100,15,4,8,159,1,240,5,115,
19,240,98,98,4,52,15,2,14,18,47,0,27,9,85,19,240,98,98,18,18,31,17,50,15,5,
47,2,130,34,240,98,98,18,68,15,4,15,1,31,9,12,115,19,240,98,98,18,68,15,16,
18,47,1,15,3,2,84,34,52,18,2,20,20,36,191,8,15,38,114,34,240,114,240,4,15,
12,38,31,16,5,114,34,240,114,146,68,15,18,2,31,1,31,4,114,34,241,147,15,2,
6,41,47,10,86,240,36,240,130,130,3,111,44,242,2,29,111,44,18,2,66,240,130,
2,146,26,3,66,15,7,63,18,15,49,114,241,79,13,79,101,241,191,6,15,2,85,52,4,
24,37,205,15,3,241,98,6,3,241,178,255,224,63,35,54,32,35,63,25,35,63,17,35,
54,32,35,62,47,41,35,63,51,241,127,0,240,47,70,53,79,254,21,227,240,18,240,
166,243,180,168,194,63,0,240,47,0,240,47,0,194,47,1,242,79,21,5,15,53,244,
152,67,241,34,6,243,107,240,255,35,240,227,76,241,197,240,175,40,240,122,
242,95,68,15,79,241,255,3,111,41,240,238,27,241,207,12,241,79,27,43,241,67,
136,241,179,47,27,50,82,20,6,251,15,50,255,224,8,53,63,22,53,55,32,32,32,
47,15,63,37,38,32,66,38,67,53,92,98,38,246,96,224,240,44,245,112,80,57,32,
68,112,32,32,35,42,51,100,80,240,63,25,255,233,107,241,242,241,242,247,87,
52,29,241,98,6,3,242,136,15,2,240,122,98,98,98,98,98,98,98,111,66,15,254,
12,146,240,184,132,52,95,70,114,47,74,35,111,27,47,78,240,63,11,242,127,0,
255,224,244,255,240,0,138,143,60,255,240,4,14,47,2,255,227,127,243,95,30,
63,253,79,0,177,240,111,31,240,47,15,63,64,241,152,63,87,63,37,52,242,42,
34,35,47,7,240,255,36,240,15,34,243,5,64,33,207,12,191,7,240,191,13,143,31,
240,224,240,36,41,180,47,25,240,146,39,240,111,7,64,79,34,32,65,52,48,32,
240,162,58,130,213,53,53,166,38,47,27,43,159,99,240,255,255,0,26,150,223,7,
95,33,255,240,0,255,143,254,6,3,245,175,24,109,70,2,146,194,66,2,18,18,245,
207,19,255,224,93,240,79,48,63,38,241,171,246,100,47,119,241,111,10,127,10,
207,73,69,53,53,50,0,
};
#endif

#if defined(DUK_USE_SOURCE_NONBMP)
/* IdentifierStart production with Letter and ASCII excluded */
/* duk_unicode_ids_m_let_noa[] */
/*
 *  Automatically generated by extract_chars.py, do not edit!
 */

const duk_uint8_t duk_unicode_ids_m_let_noa[42] = {
255,240,0,94,18,255,233,99,241,51,63,254,215,32,240,184,240,2,255,240,6,89,
249,255,240,4,148,79,37,255,224,192,9,15,120,79,255,0,15,30,245,240,
};
#else
/* IdentifierStart production with Letter, ASCII, and non-BMP excluded */
/* duk_unicode_ids_m_let_noabmp[] */
/*
 *  Automatically generated by extract_chars.py, do not edit!
 */

const duk_uint8_t duk_unicode_ids_m_let_noabmp[24] = {
255,240,0,94,18,255,233,99,241,51,63,254,215,32,240,184,240,2,255,240,6,89,
249,0,
};
#endif

#if defined(DUK_USE_SOURCE_NONBMP)
/* IdentifierPart production with IdentifierStart and ASCII excluded */
/* duk_unicode_idp_m_ids_noa[] */
/*
 *  Automatically generated by extract_chars.py, do not edit!
 */

const duk_uint8_t duk_unicode_idp_m_ids_noa[576] = {
255,225,243,246,15,254,0,116,255,191,29,32,33,33,32,243,170,242,47,15,112,
245,118,53,49,35,57,240,144,241,15,11,244,218,240,25,241,56,160,240,163,40,
34,36,241,210,246,158,47,17,242,130,47,2,38,177,57,240,50,242,160,38,49,50,
160,177,57,240,0,50,242,160,36,81,50,64,240,107,64,194,242,160,39,34,34,
240,97,57,181,34,242,160,38,49,50,145,177,57,240,64,242,212,66,35,160,240,
9,240,36,242,182,34,35,129,193,57,240,50,242,160,38,34,35,129,193,57,240,
35,242,145,38,34,35,160,177,57,240,65,243,128,85,32,39,121,49,242,240,54,
215,41,244,144,56,197,57,243,1,121,192,32,32,81,242,63,4,33,106,47,20,160,
245,111,4,41,211,82,34,54,67,235,46,255,225,179,47,254,42,98,240,242,240,
241,241,1,243,47,16,160,57,241,50,57,245,209,241,64,246,139,91,185,247,41,
242,244,242,185,47,13,58,121,240,141,243,68,242,31,1,201,240,56,210,241,12,
57,241,237,242,47,4,153,121,246,130,47,5,80,112,50,251,143,42,36,255,225,0,
31,35,31,5,15,109,197,4,191,254,175,34,247,240,245,47,16,255,225,30,95,91,
31,255,0,100,121,159,55,5,159,18,31,66,31,254,0,64,64,80,240,148,244,161,
242,79,2,185,127,2,234,240,231,240,188,241,227,242,29,240,25,192,185,242,
29,208,145,57,241,50,242,64,34,49,97,32,241,180,97,253,231,33,57,255,240,3,
225,128,255,225,213,240,15,2,240,4,31,10,47,178,159,23,15,254,27,16,253,64,
248,116,255,224,25,159,254,68,178,33,99,241,162,80,249,113,255,225,49,57,
159,254,16,10,250,18,242,126,241,25,240,19,241,250,242,121,114,241,109,41,
97,241,224,210,242,45,147,73,244,75,112,249,43,105,115,242,145,38,49,50,
160,177,54,68,251,47,2,169,80,244,63,4,217,252,118,56,240,209,244,79,1,240,
25,244,60,153,244,94,89,254,78,249,121,253,150,54,64,240,233,241,166,35,
144,170,242,15,0,255,224,137,114,127,2,159,42,240,98,223,108,84,2,18,98,9,
159,34,66,18,73,159,254,3,211,255,240,3,165,217,247,132,242,214,240,185,
255,226,233,2,242,120,63,255,0,59,254,31,255,0,3,186,68,89,115,111,16,63,
134,47,254,71,223,34,255,224,244,242,117,242,41,15,0,15,8,66,239,254,68,70,
47,1,54,33,36,255,118,169,255,224,150,223,254,76,166,245,246,105,255,240,
192,105,175,224,0,
};
#else
/* IdentifierPart production with IdentifierStart, ASCII, and non-BMP excluded */
/* duk_unicode_idp_m_ids_noabmp[] */
/*
 *  Automatically generated by extract_chars.py, do not edit!
 */

const duk_uint8_t duk_unicode_idp_m_ids_noabmp[358] = {
255,225,243,246,15,254,0,116,255,191,29,32,33,33,32,243,170,242,47,15,112,
245,118,53,49,35,57,240,144,241,15,11,244,218,240,25,241,56,160,240,163,40,
34,36,241,210,246,158,47,17,242,130,47,2,38,177,57,240,50,242,160,38,49,50,
160,177,57,240,0,50,242,160,36,81,50,64,240,107,64,194,242,160,39,34,34,
240,97,57,181,34,242,160,38,49,50,145,177,57,240,64,242,212,66,35,160,240,
9,240,36,242,182,34,35,129,193,57,240,50,242,160,38,34,35,129,193,57,240,
35,242,145,38,34,35,160,177,57,240,65,243,128,85,32,39,121,49,242,240,54,
215,41,244,144,56,197,57,243,1,121,192,32,32,81,242,63,4,33,106,47,20,160,
245,111,4,41,211,82,34,54,67,235,46,255,225,179,47,254,42,98,240,242,240,
241,241,1,243,47,16,160,57,241,50,57,245,209,241,64,246,139,91,185,247,41,
242,244,242,185,47,13,58,121,240,141,243,68,242,31,1,201,240,56,210,241,12,
57,241,237,242,47,4,153,121,246,130,47,5,80,112,50,251,143,42,36,255,225,0,
31,35,31,5,15,109,197,4,191,254,175,34,247,240,245,47,16,255,225,30,95,91,
31,255,0,100,121,159,55,5,159,18,31,66,31,254,0,64,64,80,240,148,244,161,
242,79,2,185,127,2,234,240,231,240,188,241,227,242,29,240,25,192,185,242,
29,208,145,57,241,50,242,64,34,49,97,32,241,180,97,253,231,33,57,255,240,3,
225,128,255,225,213,240,15,2,240,4,31,10,47,178,159,23,0,
};
#endif

/*
 *  Case conversion tables generated using tools/extract_caseconv.py.
 */

/* duk_unicode_caseconv_uc[] */
/* duk_unicode_caseconv_lc[] */

/*
 *  Automatically generated by extract_caseconv.py, do not edit!
 */

const duk_uint8_t duk_unicode_caseconv_uc[1411] = {
152,3,128,3,0,184,7,192,6,192,112,35,242,199,224,64,74,192,49,32,128,162,
128,108,65,1,189,129,254,131,3,173,3,136,6,7,98,7,34,68,15,12,14,140,72,30,
104,28,112,32,67,0,65,4,0,138,0,128,4,1,88,65,76,83,8,104,14,72,43,16,253,
28,189,6,39,240,39,224,24,114,12,16,132,16,248,0,248,64,129,241,1,241,128,
195,228,3,229,2,7,204,7,206,4,15,160,15,164,6,31,96,31,104,16,62,224,63,
116,8,125,200,127,32,32,251,176,254,208,33,247,129,255,128,67,239,67,253,
64,135,223,7,254,129,15,216,15,220,2,31,208,31,216,4,63,192,63,208,8,133,
192,133,128,129,38,129,37,177,162,195,2,192,5,229,160,2,20,9,170,220,4,232,
40,127,160,255,144,154,136,4,4,4,0,192,9,152,9,144,48,19,160,19,145,0,41,
96,41,69,192,94,128,94,65,128,193,128,193,2,1,161,1,160,6,3,104,3,102,8,7,
56,7,52,64,14,248,14,240,144,31,144,31,130,128,68,96,68,66,64,145,192,145,
130,129,184,129,184,2,3,217,3,216,24,8,194,8,192,68,18,44,18,40,216,38,16,
38,8,112,77,16,77,6,3,192,35,192,18,199,168,71,168,24,15,168,143,172,132,
44,104,44,103,6,89,2,89,0,200,179,176,179,172,21,50,13,50,1,122,104,26,104,
1,212,228,116,228,65,233,204,233,204,143,211,189,83,188,130,167,127,167,
126,11,79,35,79,32,10,158,94,158,88,85,61,173,61,160,97,192,107,64,107,1,0,
226,128,226,3,1,198,1,196,6,3,228,3,226,8,10,0,6,152,16,31,192,31,184,34,
199,50,199,32,65,128,196,0,195,130,1,185,1,184,4,4,205,79,84,8,0,192,143,0,
142,193,1,52,128,203,2,45,39,16,199,5,253,0,11,80,57,192,15,240,23,128,19,
16,4,144,23,240,5,48,24,0,36,48,25,32,25,16,25,80,31,96,25,144,25,128,25,
160,35,208,25,224,34,0,26,128,26,112,27,240,31,112,29,208,24,224,31,48,31,
16,37,2,198,240,37,18,198,208,37,34,199,0,37,48,24,16,37,64,24,96,37,144,
24,240,37,176,25,0,37,202,122,176,38,0,25,48,38,26,122,192,38,48,25,64,38,
90,120,208,38,128,25,112,38,178,198,32,38,202,122,208,39,18,198,224,39,32,
25,208,39,80,25,240,39,210,198,64,40,42,124,80,40,122,123,16,40,128,26,224,
40,144,36,64,40,192,36,80,41,32,27,112,41,218,123,32,41,234,123,0,52,80,57,
144,55,112,55,96,58,192,56,96,60,32,58,48,60,192,56,192,61,0,57,32,61,16,
57,128,61,80,58,96,61,96,58,0,61,112,60,240,63,0,57,160,63,16,58,16,63,32,
63,144,63,48,55,240,63,80,57,80,76,240,76,1,200,0,65,33,200,16,65,65,200,
32,65,225,200,80,66,33,200,96,66,161,200,112,70,33,200,138,100,161,215,154,
119,209,215,210,198,49,216,234,124,97,233,177,230,1,251,224,57,145,254,81,
254,194,20,226,19,34,24,66,24,50,198,18,198,2,198,80,35,162,198,96,35,226,
207,50,207,42,120,202,120,186,121,74,124,74,124,58,124,42,181,58,123,60,
192,27,240,2,152,2,152,10,76,5,120,0,156,3,225,0,37,1,134,1,200,96,115,32,
97,0,96,32,118,24,29,40,24,64,24,8,44,60,10,106,10,164,61,45,0,36,1,152,
143,75,192,10,128,97,3,211,16,2,184,24,80,244,204,0,178,6,20,61,53,0,32,
129,95,15,168,64,116,160,98,99,234,88,29,40,24,152,24,0,250,166,7,74,6,38,
6,2,62,173,129,210,129,137,129,161,15,192,67,225,0,115,35,240,48,248,72,28,
200,252,20,62,20,7,50,63,7,15,133,129,204,143,194,67,225,128,115,35,240,
176,248,104,28,200,252,52,62,28,7,50,63,15,15,135,129,204,143,196,67,225,0,
115,35,241,48,248,72,28,200,252,84,62,20,7,50,63,23,15,133,129,204,143,198,
67,225,128,115,35,241,176,248,104,28,200,252,116,62,28,7,50,63,31,15,135,
129,204,143,200,67,229,0,115,35,242,48,249,72,28,200,252,148,62,84,7,50,63,
39,15,149,129,204,143,202,67,229,128,115,35,242,176,249,104,28,200,252,180,
62,92,7,50,63,47,15,151,129,204,143,204,67,229,0,115,35,243,48,249,72,28,
200,252,212,62,84,7,50,63,55,15,149,129,204,143,206,67,229,128,115,35,243,
176,249,104,28,200,252,244,62,92,7,50,63,63,15,151,129,204,143,208,67,237,
0,115,35,244,48,251,72,28,200,253,20,62,212,7,50,63,71,15,181,129,204,143,
210,67,237,128,115,35,244,176,251,104,28,200,253,52,62,220,7,50,63,79,15,
183,129,204,143,212,67,237,0,115,35,245,48,251,72,28,200,253,84,62,212,7,
50,63,87,15,181,129,204,143,214,67,237,128,115,35,245,176,251,104,28,200,
253,116,62,220,7,50,63,95,15,183,129,204,143,217,67,247,64,115,35,246,112,
28,136,28,200,253,164,7,12,7,50,63,109,1,200,129,161,15,219,224,114,32,104,
64,115,35,247,144,28,136,28,200,254,20,63,148,7,50,63,135,1,203,129,204,
143,226,64,113,32,115,35,248,208,28,184,26,16,254,62,7,46,6,132,7,50,63,
153,1,203,129,204,143,233,96,115,32,97,0,96,3,250,120,28,200,24,64,24,8,
254,180,7,50,6,132,63,175,129,204,129,132,1,161,15,241,96,116,160,97,0,96,
3,252,120,29,40,24,64,24,8,255,36,7,66,6,38,63,205,1,210,129,161,15,243,
224,116,160,97,0,104,67,254,80,255,208,28,200,255,156,7,82,7,50,63,233,1,
199,129,204,143,251,64,117,32,104,67,254,248,29,72,26,16,28,200,255,228,7,
82,7,51,246,1,0,35,0,35,125,128,192,8,192,9,63,96,80,2,48,2,103,216,30,0,
140,0,140,0,147,246,9,128,35,0,35,0,38,125,130,192,10,96,10,159,96,208,2,
152,2,167,216,156,10,136,10,141,246,41,2,162,2,154,253,138,192,168,128,167,
127,98,208,42,112,42,55,216,188,10,136,10,122,
};
const duk_uint8_t duk_unicode_caseconv_lc[706] = {
160,3,0,3,128,184,6,192,7,192,112,24,144,37,96,64,54,32,81,64,128,226,0,
235,65,129,199,1,230,130,3,145,3,177,34,7,70,7,134,36,15,244,13,236,24,32,
0,34,129,0,65,0,67,4,0,166,32,172,41,132,40,11,64,19,9,208,85,184,80,19,
240,19,248,12,57,32,33,160,172,114,244,67,244,24,248,64,248,0,129,241,129,
241,0,195,229,3,228,2,7,206,7,204,4,15,164,15,160,6,31,104,31,96,16,63,16,
63,0,32,126,96,126,64,64,253,64,253,0,129,251,129,251,0,67,247,67,238,0,
135,242,7,220,130,15,236,15,232,2,31,218,31,118,4,63,208,63,192,8,127,168,
125,232,16,255,192,251,192,33,255,161,247,192,68,44,4,46,4,9,45,137,52,13,
22,0,22,24,47,44,126,2,63,5,254,67,254,130,106,48,16,0,16,19,0,38,64,38,96,
192,78,64,78,132,0,165,0,165,151,1,121,1,122,6,3,4,3,6,8,6,128,6,132,24,13,
152,13,160,32,28,176,28,193,32,59,192,59,226,64,124,128,124,193,0,252,0,
252,148,2,34,2,35,18,4,140,4,142,20,13,192,13,196,16,30,192,30,200,192,70,
0,70,18,32,145,64,145,102,193,48,65,48,131,130,104,2,104,176,30,0,30,1,150,
61,64,61,66,192,125,100,125,68,33,99,57,99,64,50,200,2,200,22,69,157,101,
157,128,169,144,41,144,75,211,64,83,64,142,167,34,167,35,15,78,101,78,102,
126,157,230,157,232,21,59,245,59,248,90,121,10,121,16,84,242,212,242,226,
169,237,41,237,67,12,3,76,5,0,8,6,176,6,180,16,14,32,14,48,48,28,80,28,96,
64,126,224,127,0,139,28,139,28,193,6,3,14,3,16,8,6,224,6,228,21,61,80,19,
48,32,3,1,150,2,105,4,4,118,4,120,8,67,28,180,156,23,240,192,94,0,63,192,
96,64,148,192,97,128,149,0,99,128,119,64,99,192,150,64,100,0,150,192,100,
64,100,128,100,192,152,0,101,0,152,192,101,192,154,0,102,0,102,64,103,64,
156,128,103,192,157,64,105,192,106,0,107,128,162,0,109,192,164,128,124,64,
124,192,125,128,101,64,125,192,111,192,136,0,103,128,142,139,25,64,143,64,
102,128,143,139,25,128,144,192,96,0,145,0,162,64,145,64,163,0,221,128,221,
192,223,192,252,192,225,128,235,0,227,0,243,0,243,192,245,192,253,0,238,0,
254,64,252,129,48,1,51,199,167,128,55,199,239,7,236,199,243,7,240,199,251,
7,249,71,255,7,252,200,73,128,242,72,74,128,26,200,74,192,57,72,76,136,83,
136,96,200,97,11,24,11,24,75,24,128,154,203,24,199,95,75,25,0,159,75,27,64,
148,75,27,128,156,75,27,192,148,11,28,0,148,139,60,139,60,233,223,71,94,
105,226,233,227,41,227,64,153,105,234,192,151,41,235,0,152,105,235,64,155,
41,236,0,167,169,236,64,161,233,236,128,167,105,236,234,212,233,240,169,
240,233,241,41,229,41,241,64,160,169,241,135,99,128,128,152,64,13,32,96,
224,
};

#if defined(DUK_USE_REGEXP_CANON_WORKAROUND)
/*
 *  Automatically generated by extract_caseconv.py, do not edit!
 */

const duk_uint16_t duk_unicode_re_canon_lookup[65536] = {
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,
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,
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,
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,
71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,123,124,125,
126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,
162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,
180,924,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,
198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,
216,217,218,219,220,221,222,223,192,193,194,195,196,197,198,199,200,201,
202,203,204,205,206,207,208,209,210,211,212,213,214,247,216,217,218,219,
220,221,222,376,256,256,258,258,260,260,262,262,264,264,266,266,268,268,
270,270,272,272,274,274,276,276,278,278,280,280,282,282,284,284,286,286,
288,288,290,290,292,292,294,294,296,296,298,298,300,300,302,302,304,305,
306,306,308,308,310,310,312,313,313,315,315,317,317,319,319,321,321,323,
323,325,325,327,327,329,330,330,332,332,334,334,336,336,338,338,340,340,
342,342,344,344,346,346,348,348,350,350,352,352,354,354,356,356,358,358,
360,360,362,362,364,364,366,366,368,368,370,370,372,372,374,374,376,377,
377,379,379,381,381,383,579,385,386,386,388,388,390,391,391,393,394,395,
395,397,398,399,400,401,401,403,404,502,406,407,408,408,573,411,412,413,
544,415,416,416,418,418,420,420,422,423,423,425,426,427,428,428,430,431,
431,433,434,435,435,437,437,439,440,440,442,443,444,444,446,503,448,449,
450,451,452,452,452,455,455,455,458,458,458,461,461,463,463,465,465,467,
467,469,469,471,471,473,473,475,475,398,478,478,480,480,482,482,484,484,
486,486,488,488,490,490,492,492,494,494,496,497,497,497,500,500,502,503,
504,504,506,506,508,508,510,510,512,512,514,514,516,516,518,518,520,520,
522,522,524,524,526,526,528,528,530,530,532,532,534,534,536,536,538,538,
540,540,542,542,544,545,546,546,548,548,550,550,552,552,554,554,556,556,
558,558,560,560,562,562,564,565,566,567,568,569,570,571,571,573,574,11390,
11391,577,577,579,580,581,582,582,584,584,586,586,588,588,590,590,11375,
11373,11376,385,390,597,393,394,600,399,602,400,42923L,605,606,607,403,
42924L,610,404,612,42893L,42922L,615,407,406,42926L,11362,42925L,621,622,
412,624,11374,413,627,628,415,630,631,632,633,634,635,636,11364,638,639,
422,641,42949L,425,644,645,646,42929L,430,580,433,434,581,653,654,655,656,
657,439,659,660,661,662,663,664,665,666,667,668,42930L,42928L,671,672,673,
674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,
692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,
710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,
728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,
746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,
764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,
782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,
800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,
818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,
836,921,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,
854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,
872,873,874,875,876,877,878,879,880,880,882,882,884,885,886,886,888,889,
890,1021,1022,1023,894,895,896,897,898,899,900,901,902,903,904,905,906,907,
908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,
926,927,928,929,930,931,932,933,934,935,936,937,938,939,902,904,905,906,
944,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,
931,931,932,933,934,935,936,937,938,939,908,910,911,975,914,920,978,979,
980,934,928,975,984,984,986,986,988,988,990,990,992,992,994,994,996,996,
998,998,1000,1000,1002,1002,1004,1004,1006,1006,922,929,1017,895,1012,917,
1014,1015,1015,1017,1018,1018,1020,1021,1022,1023,1024,1025,1026,1027,1028,
1029,1030,1031,1032,1033,1034,1035,1036,1037,1038,1039,1040,1041,1042,1043,
1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,
1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1040,1041,
1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,
1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,
1024,1025,1026,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,1037,1038,
1039,1120,1120,1122,1122,1124,1124,1126,1126,1128,1128,1130,1130,1132,1132,
1134,1134,1136,1136,1138,1138,1140,1140,1142,1142,1144,1144,1146,1146,1148,
1148,1150,1150,1152,1152,1154,1155,1156,1157,1158,1159,1160,1161,1162,1162,
1164,1164,1166,1166,1168,1168,1170,1170,1172,1172,1174,1174,1176,1176,1178,
1178,1180,1180,1182,1182,1184,1184,1186,1186,1188,1188,1190,1190,1192,1192,
1194,1194,1196,1196,1198,1198,1200,1200,1202,1202,1204,1204,1206,1206,1208,
1208,1210,1210,1212,1212,1214,1214,1216,1217,1217,1219,1219,1221,1221,1223,
1223,1225,1225,1227,1227,1229,1229,1216,1232,1232,1234,1234,1236,1236,1238,
1238,1240,1240,1242,1242,1244,1244,1246,1246,1248,1248,1250,1250,1252,1252,
1254,1254,1256,1256,1258,1258,1260,1260,1262,1262,1264,1264,1266,1266,1268,
1268,1270,1270,1272,1272,1274,1274,1276,1276,1278,1278,1280,1280,1282,1282,
1284,1284,1286,1286,1288,1288,1290,1290,1292,1292,1294,1294,1296,1296,1298,
1298,1300,1300,1302,1302,1304,1304,1306,1306,1308,1308,1310,1310,1312,1312,
1314,1314,1316,1316,1318,1318,1320,1320,1322,1322,1324,1324,1326,1326,1328,
1329,1330,1331,1332,1333,1334,1335,1336,1337,1338,1339,1340,1341,1342,1343,
1344,1345,1346,1347,1348,1349,1350,1351,1352,1353,1354,1355,1356,1357,1358,
1359,1360,1361,1362,1363,1364,1365,1366,1367,1368,1369,1370,1371,1372,1373,
1374,1375,1376,1329,1330,1331,1332,1333,1334,1335,1336,1337,1338,1339,1340,
1341,1342,1343,1344,1345,1346,1347,1348,1349,1350,1351,1352,1353,1354,1355,
1356,1357,1358,1359,1360,1361,1362,1363,1364,1365,1366,1415,1416,1417,1418,
1419,1420,1421,1422,1423,1424,1425,1426,1427,1428,1429,1430,1431,1432,1433,
1434,1435,1436,1437,1438,1439,1440,1441,1442,1443,1444,1445,1446,1447,1448,
1449,1450,1451,1452,1453,1454,1455,1456,1457,1458,1459,1460,1461,1462,1463,
1464,1465,1466,1467,1468,1469,1470,1471,1472,1473,1474,1475,1476,1477,1478,
1479,1480,1481,1482,1483,1484,1485,1486,1487,1488,1489,1490,1491,1492,1493,
1494,1495,1496,1497,1498,1499,1500,1501,1502,1503,1504,1505,1506,1507,1508,
1509,1510,1511,1512,1513,1514,1515,1516,1517,1518,1519,1520,1521,1522,1523,
1524,1525,1526,1527,1528,1529,1530,1531,1532,1533,1534,1535,1536,1537,1538,
1539,1540,1541,1542,1543,1544,1545,1546,1547,1548,1549,1550,1551,1552,1553,
1554,1555,1556,1557,1558,1559,1560,1561,1562,1563,1564,1565,1566,1567,1568,
1569,1570,1571,1572,1573,1574,1575,1576,1577,1578,1579,1580,1581,1582,1583,
1584,1585,1586,1587,1588,1589,1590,1591,1592,1593,1594,1595,1596,1597,1598,
1599,1600,1601,1602,1603,1604,1605,1606,1607,1608,1609,1610,1611,1612,1613,
1614,1615,1616,1617,1618,1619,1620,1621,1622,1623,1624,1625,1626,1627,1628,
1629,1630,1631,1632,1633,1634,1635,1636,1637,1638,1639,1640,1641,1642,1643,
1644,1645,1646,1647,1648,1649,1650,1651,1652,1653,1654,1655,1656,1657,1658,
1659,1660,1661,1662,1663,1664,1665,1666,1667,1668,1669,1670,1671,1672,1673,
1674,1675,1676,1677,1678,1679,1680,1681,1682,1683,1684,1685,1686,1687,1688,
1689,1690,1691,1692,1693,1694,1695,1696,1697,1698,1699,1700,1701,1702,1703,
1704,1705,1706,1707,1708,1709,1710,1711,1712,1713,1714,1715,1716,1717,1718,
1719,1720,1721,1722,1723,1724,1725,1726,1727,1728,1729,1730,1731,1732,1733,
1734,1735,1736,1737,1738,1739,1740,1741,1742,1743,1744,1745,1746,1747,1748,
1749,1750,1751,1752,1753,1754,1755,1756,1757,1758,1759,1760,1761,1762,1763,
1764,1765,1766,1767,1768,1769,1770,1771,1772,1773,1774,1775,1776,1777,1778,
1779,1780,1781,1782,1783,1784,1785,1786,1787,1788,1789,1790,1791,1792,1793,
1794,1795,1796,1797,1798,1799,1800,1801,1802,1803,1804,1805,1806,1807,1808,
1809,1810,1811,1812,1813,1814,1815,1816,1817,1818,1819,1820,1821,1822,1823,
1824,1825,1826,1827,1828,1829,1830,1831,1832,1833,1834,1835,1836,1837,1838,
1839,1840,1841,1842,1843,1844,1845,1846,1847,1848,1849,1850,1851,1852,1853,
1854,1855,1856,1857,1858,1859,1860,1861,1862,1863,1864,1865,1866,1867,1868,
1869,1870,1871,1872,1873,1874,1875,1876,1877,1878,1879,1880,1881,1882,1883,
1884,1885,1886,1887,1888,1889,1890,1891,1892,1893,1894,1895,1896,1897,1898,
1899,1900,1901,1902,1903,1904,1905,1906,1907,1908,1909,1910,1911,1912,1913,
1914,1915,1916,1917,1918,1919,1920,1921,1922,1923,1924,1925,1926,1927,1928,
1929,1930,1931,1932,1933,1934,1935,1936,1937,1938,1939,1940,1941,1942,1943,
1944,1945,1946,1947,1948,1949,1950,1951,1952,1953,1954,1955,1956,1957,1958,
1959,1960,1961,1962,1963,1964,1965,1966,1967,1968,1969,1970,1971,1972,1973,
1974,1975,1976,1977,1978,1979,1980,1981,1982,1983,1984,1985,1986,1987,1988,
1989,1990,1991,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,
2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,
2019,2020,2021,2022,2023,2024,2025,2026,2027,2028,2029,2030,2031,2032,2033,
2034,2035,2036,2037,2038,2039,2040,2041,2042,2043,2044,2045,2046,2047,2048,
2049,2050,2051,2052,2053,2054,2055,2056,2057,2058,2059,2060,2061,2062,2063,
2064,2065,2066,2067,2068,2069,2070,2071,2072,2073,2074,2075,2076,2077,2078,
2079,2080,2081,2082,2083,2084,2085,2086,2087,2088,2089,2090,2091,2092,2093,
2094,2095,2096,2097,2098,2099,2100,2101,2102,2103,2104,2105,2106,2107,2108,
2109,2110,2111,2112,2113,2114,2115,2116,2117,2118,2119,2120,2121,2122,2123,
2124,2125,2126,2127,2128,2129,2130,2131,2132,2133,2134,2135,2136,2137,2138,
2139,2140,2141,2142,2143,2144,2145,2146,2147,2148,2149,2150,2151,2152,2153,
2154,2155,2156,2157,2158,2159,2160,2161,2162,2163,2164,2165,2166,2167,2168,
2169,2170,2171,2172,2173,2174,2175,2176,2177,2178,2179,2180,2181,2182,2183,
2184,2185,2186,2187,2188,2189,2190,2191,2192,2193,2194,2195,2196,2197,2198,
2199,2200,2201,2202,2203,2204,2205,2206,2207,2208,2209,2210,2211,2212,2213,
2214,2215,2216,2217,2218,2219,2220,2221,2222,2223,2224,2225,2226,2227,2228,
2229,2230,2231,2232,2233,2234,2235,2236,2237,2238,2239,2240,2241,2242,2243,
2244,2245,2246,2247,2248,2249,2250,2251,2252,2253,2254,2255,2256,2257,2258,
2259,2260,2261,2262,2263,2264,2265,2266,2267,2268,2269,2270,2271,2272,2273,
2274,2275,2276,2277,2278,2279,2280,2281,2282,2283,2284,2285,2286,2287,2288,
2289,2290,2291,2292,2293,2294,2295,2296,2297,2298,2299,2300,2301,2302,2303,
2304,2305,2306,2307,2308,2309,2310,2311,2312,2313,2314,2315,2316,2317,2318,
2319,2320,2321,2322,2323,2324,2325,2326,2327,2328,2329,2330,2331,2332,2333,
2334,2335,2336,2337,2338,2339,2340,2341,2342,2343,2344,2345,2346,2347,2348,
2349,2350,2351,2352,2353,2354,2355,2356,2357,2358,2359,2360,2361,2362,2363,
2364,2365,2366,2367,2368,2369,2370,2371,2372,2373,2374,2375,2376,2377,2378,
2379,2380,2381,2382,2383,2384,2385,2386,2387,2388,2389,2390,2391,2392,2393,
2394,2395,2396,2397,2398,2399,2400,2401,2402,2403,2404,2405,2406,2407,2408,
2409,2410,2411,2412,2413,2414,2415,2416,2417,2418,2419,2420,2421,2422,2423,
2424,2425,2426,2427,2428,2429,2430,2431,2432,2433,2434,2435,2436,2437,2438,
2439,2440,2441,2442,2443,2444,2445,2446,2447,2448,2449,2450,2451,2452,2453,
2454,2455,2456,2457,2458,2459,2460,2461,2462,2463,2464,2465,2466,2467,2468,
2469,2470,2471,2472,2473,2474,2475,2476,2477,2478,2479,2480,2481,2482,2483,
2484,2485,2486,2487,2488,2489,2490,2491,2492,2493,2494,2495,2496,2497,2498,
2499,2500,2501,2502,2503,2504,2505,2506,2507,2508,2509,2510,2511,2512,2513,
2514,2515,2516,2517,2518,2519,2520,2521,2522,2523,2524,2525,2526,2527,2528,
2529,2530,2531,2532,2533,2534,2535,2536,2537,2538,2539,2540,2541,2542,2543,
2544,2545,2546,2547,2548,2549,2550,2551,2552,2553,2554,2555,2556,2557,2558,
2559,2560,2561,2562,2563,2564,2565,2566,2567,2568,2569,2570,2571,2572,2573,
2574,2575,2576,2577,2578,2579,2580,2581,2582,2583,2584,2585,2586,2587,2588,
2589,2590,2591,2592,2593,2594,2595,2596,2597,2598,2599,2600,2601,2602,2603,
2604,2605,2606,2607,2608,2609,2610,2611,2612,2613,2614,2615,2616,2617,2618,
2619,2620,2621,2622,2623,2624,2625,2626,2627,2628,2629,2630,2631,2632,2633,
2634,2635,2636,2637,2638,2639,2640,2641,2642,2643,2644,2645,2646,2647,2648,
2649,2650,2651,2652,2653,2654,2655,2656,2657,2658,2659,2660,2661,2662,2663,
2664,2665,2666,2667,2668,2669,2670,2671,2672,2673,2674,2675,2676,2677,2678,
2679,2680,2681,2682,2683,2684,2685,2686,2687,2688,2689,2690,2691,2692,2693,
2694,2695,2696,2697,2698,2699,2700,2701,2702,2703,2704,2705,2706,2707,2708,
2709,2710,2711,2712,2713,2714,2715,2716,2717,2718,2719,2720,2721,2722,2723,
2724,2725,2726,2727,2728,2729,2730,2731,2732,2733,2734,2735,2736,2737,2738,
2739,2740,2741,2742,2743,2744,2745,2746,2747,2748,2749,2750,2751,2752,2753,
2754,2755,2756,2757,2758,2759,2760,2761,2762,2763,2764,2765,2766,2767,2768,
2769,2770,2771,2772,2773,2774,2775,2776,2777,2778,2779,2780,2781,2782,2783,
2784,2785,2786,2787,2788,2789,2790,2791,2792,2793,2794,2795,2796,2797,2798,
2799,2800,2801,2802,2803,2804,2805,2806,2807,2808,2809,2810,2811,2812,2813,
2814,2815,2816,2817,2818,2819,2820,2821,2822,2823,2824,2825,2826,2827,2828,
2829,2830,2831,2832,2833,2834,2835,2836,2837,2838,2839,2840,2841,2842,2843,
2844,2845,2846,2847,2848,2849,2850,2851,2852,2853,2854,2855,2856,2857,2858,
2859,2860,2861,2862,2863,2864,2865,2866,2867,2868,2869,2870,2871,2872,2873,
2874,2875,2876,2877,2878,2879,2880,2881,2882,2883,2884,2885,2886,2887,2888,
2889,2890,2891,2892,2893,2894,2895,2896,2897,2898,2899,2900,2901,2902,2903,
2904,2905,2906,2907,2908,2909,2910,2911,2912,2913,2914,2915,2916,2917,2918,
2919,2920,2921,2922,2923,2924,2925,2926,2927,2928,2929,2930,2931,2932,2933,
2934,2935,2936,2937,2938,2939,2940,2941,2942,2943,2944,2945,2946,2947,2948,
2949,2950,2951,2952,2953,2954,2955,2956,2957,2958,2959,2960,2961,2962,2963,
2964,2965,2966,2967,2968,2969,2970,2971,2972,2973,2974,2975,2976,2977,2978,
2979,2980,2981,2982,2983,2984,2985,2986,2987,2988,2989,2990,2991,2992,2993,
2994,2995,2996,2997,2998,2999,3000,3001,3002,3003,3004,3005,3006,3007,3008,
3009,3010,3011,3012,3013,3014,3015,3016,3017,3018,3019,3020,3021,3022,3023,
3024,3025,3026,3027,3028,3029,3030,3031,3032,3033,3034,3035,3036,3037,3038,
3039,3040,3041,3042,3043,3044,3045,3046,3047,3048,3049,3050,3051,3052,3053,
3054,3055,3056,3057,3058,3059,3060,3061,3062,3063,3064,3065,3066,3067,3068,
3069,3070,3071,3072,3073,3074,3075,3076,3077,3078,3079,3080,3081,3082,3083,
3084,3085,3086,3087,3088,3089,3090,3091,3092,3093,3094,3095,3096,3097,3098,
3099,3100,3101,3102,3103,3104,3105,3106,3107,3108,3109,3110,3111,3112,3113,
3114,3115,3116,3117,3118,3119,3120,3121,3122,3123,3124,3125,3126,3127,3128,
3129,3130,3131,3132,3133,3134,3135,3136,3137,3138,3139,3140,3141,3142,3143,
3144,3145,3146,3147,3148,3149,3150,3151,3152,3153,3154,3155,3156,3157,3158,
3159,3160,3161,3162,3163,3164,3165,3166,3167,3168,3169,3170,3171,3172,3173,
3174,3175,3176,3177,3178,3179,3180,3181,3182,3183,3184,3185,3186,3187,3188,
3189,3190,3191,3192,3193,3194,3195,3196,3197,3198,3199,3200,3201,3202,3203,
3204,3205,3206,3207,3208,3209,3210,3211,3212,3213,3214,3215,3216,3217,3218,
3219,3220,3221,3222,3223,3224,3225,3226,3227,3228,3229,3230,3231,3232,3233,
3234,3235,3236,3237,3238,3239,3240,3241,3242,3243,3244,3245,3246,3247,3248,
3249,3250,3251,3252,3253,3254,3255,3256,3257,3258,3259,3260,3261,3262,3263,
3264,3265,3266,3267,3268,3269,3270,3271,3272,3273,3274,3275,3276,3277,3278,
3279,3280,3281,3282,3283,3284,3285,3286,3287,3288,3289,3290,3291,3292,3293,
3294,3295,3296,3297,3298,3299,3300,3301,3302,3303,3304,3305,3306,3307,3308,
3309,3310,3311,3312,3313,3314,3315,3316,3317,3318,3319,3320,3321,3322,3323,
3324,3325,3326,3327,3328,3329,3330,3331,3332,3333,3334,3335,3336,3337,3338,
3339,3340,3341,3342,3343,3344,3345,3346,3347,3348,3349,3350,3351,3352,3353,
3354,3355,3356,3357,3358,3359,3360,3361,3362,3363,3364,3365,3366,3367,3368,
3369,3370,3371,3372,3373,3374,3375,3376,3377,3378,3379,3380,3381,3382,3383,
3384,3385,3386,3387,3388,3389,3390,3391,3392,3393,3394,3395,3396,3397,3398,
3399,3400,3401,3402,3403,3404,3405,3406,3407,3408,3409,3410,3411,3412,3413,
3414,3415,3416,3417,3418,3419,3420,3421,3422,3423,3424,3425,3426,3427,3428,
3429,3430,3431,3432,3433,3434,3435,3436,3437,3438,3439,3440,3441,3442,3443,
3444,3445,3446,3447,3448,3449,3450,3451,3452,3453,3454,3455,3456,3457,3458,
3459,3460,3461,3462,3463,3464,3465,3466,3467,3468,3469,3470,3471,3472,3473,
3474,3475,3476,3477,3478,3479,3480,3481,3482,3483,3484,3485,3486,3487,3488,
3489,3490,3491,3492,3493,3494,3495,3496,3497,3498,3499,3500,3501,3502,3503,
3504,3505,3506,3507,3508,3509,3510,3511,3512,3513,3514,3515,3516,3517,3518,
3519,3520,3521,3522,3523,3524,3525,3526,3527,3528,3529,3530,3531,3532,3533,
3534,3535,3536,3537,3538,3539,3540,3541,3542,3543,3544,3545,3546,3547,3548,
3549,3550,3551,3552,3553,3554,3555,3556,3557,3558,3559,3560,3561,3562,3563,
3564,3565,3566,3567,3568,3569,3570,3571,3572,3573,3574,3575,3576,3577,3578,
3579,3580,3581,3582,3583,3584,3585,3586,3587,3588,3589,3590,3591,3592,3593,
3594,3595,3596,3597,3598,3599,3600,3601,3602,3603,3604,3605,3606,3607,3608,
3609,3610,3611,3612,3613,3614,3615,3616,3617,3618,3619,3620,3621,3622,3623,
3624,3625,3626,3627,3628,3629,3630,3631,3632,3633,3634,3635,3636,3637,3638,
3639,3640,3641,3642,3643,3644,3645,3646,3647,3648,3649,3650,3651,3652,3653,
3654,3655,3656,3657,3658,3659,3660,3661,3662,3663,3664,3665,3666,3667,3668,
3669,3670,3671,3672,3673,3674,3675,3676,3677,3678,3679,3680,3681,3682,3683,
3684,3685,3686,3687,3688,3689,3690,3691,3692,3693,3694,3695,3696,3697,3698,
3699,3700,3701,3702,3703,3704,3705,3706,3707,3708,3709,3710,3711,3712,3713,
3714,3715,3716,3717,3718,3719,3720,3721,3722,3723,3724,3725,3726,3727,3728,
3729,3730,3731,3732,3733,3734,3735,3736,3737,3738,3739,3740,3741,3742,3743,
3744,3745,3746,3747,3748,3749,3750,3751,3752,3753,3754,3755,3756,3757,3758,
3759,3760,3761,3762,3763,3764,3765,3766,3767,3768,3769,3770,3771,3772,3773,
3774,3775,3776,3777,3778,3779,3780,3781,3782,3783,3784,3785,3786,3787,3788,
3789,3790,3791,3792,3793,3794,3795,3796,3797,3798,3799,3800,3801,3802,3803,
3804,3805,3806,3807,3808,3809,3810,3811,3812,3813,3814,3815,3816,3817,3818,
3819,3820,3821,3822,3823,3824,3825,3826,3827,3828,3829,3830,3831,3832,3833,
3834,3835,3836,3837,3838,3839,3840,3841,3842,3843,3844,3845,3846,3847,3848,
3849,3850,3851,3852,3853,3854,3855,3856,3857,3858,3859,3860,3861,3862,3863,
3864,3865,3866,3867,3868,3869,3870,3871,3872,3873,3874,3875,3876,3877,3878,
3879,3880,3881,3882,3883,3884,3885,3886,3887,3888,3889,3890,3891,3892,3893,
3894,3895,3896,3897,3898,3899,3900,3901,3902,3903,3904,3905,3906,3907,3908,
3909,3910,3911,3912,3913,3914,3915,3916,3917,3918,3919,3920,3921,3922,3923,
3924,3925,3926,3927,3928,3929,3930,3931,3932,3933,3934,3935,3936,3937,3938,
3939,3940,3941,3942,3943,3944,3945,3946,3947,3948,3949,3950,3951,3952,3953,
3954,3955,3956,3957,3958,3959,3960,3961,3962,3963,3964,3965,3966,3967,3968,
3969,3970,3971,3972,3973,3974,3975,3976,3977,3978,3979,3980,3981,3982,3983,
3984,3985,3986,3987,3988,3989,3990,3991,3992,3993,3994,3995,3996,3997,3998,
3999,4000,4001,4002,4003,4004,4005,4006,4007,4008,4009,4010,4011,4012,4013,
4014,4015,4016,4017,4018,4019,4020,4021,4022,4023,4024,4025,4026,4027,4028,
4029,4030,4031,4032,4033,4034,4035,4036,4037,4038,4039,4040,4041,4042,4043,
4044,4045,4046,4047,4048,4049,4050,4051,4052,4053,4054,4055,4056,4057,4058,
4059,4060,4061,4062,4063,4064,4065,4066,4067,4068,4069,4070,4071,4072,4073,
4074,4075,4076,4077,4078,4079,4080,4081,4082,4083,4084,4085,4086,4087,4088,
4089,4090,4091,4092,4093,4094,4095,4096,4097,4098,4099,4100,4101,4102,4103,
4104,4105,4106,4107,4108,4109,4110,4111,4112,4113,4114,4115,4116,4117,4118,
4119,4120,4121,4122,4123,4124,4125,4126,4127,4128,4129,4130,4131,4132,4133,
4134,4135,4136,4137,4138,4139,4140,4141,4142,4143,4144,4145,4146,4147,4148,
4149,4150,4151,4152,4153,4154,4155,4156,4157,4158,4159,4160,4161,4162,4163,
4164,4165,4166,4167,4168,4169,4170,4171,4172,4173,4174,4175,4176,4177,4178,
4179,4180,4181,4182,4183,4184,4185,4186,4187,4188,4189,4190,4191,4192,4193,
4194,4195,4196,4197,4198,4199,4200,4201,4202,4203,4204,4205,4206,4207,4208,
4209,4210,4211,4212,4213,4214,4215,4216,4217,4218,4219,4220,4221,4222,4223,
4224,4225,4226,4227,4228,4229,4230,4231,4232,4233,4234,4235,4236,4237,4238,
4239,4240,4241,4242,4243,4244,4245,4246,4247,4248,4249,4250,4251,4252,4253,
4254,4255,4256,4257,4258,4259,4260,4261,4262,4263,4264,4265,4266,4267,4268,
4269,4270,4271,4272,4273,4274,4275,4276,4277,4278,4279,4280,4281,4282,4283,
4284,4285,4286,4287,4288,4289,4290,4291,4292,4293,4294,4295,4296,4297,4298,
4299,4300,4301,4302,4303,7312,7313,7314,7315,7316,7317,7318,7319,7320,7321,
7322,7323,7324,7325,7326,7327,7328,7329,7330,7331,7332,7333,7334,7335,7336,
7337,7338,7339,7340,7341,7342,7343,7344,7345,7346,7347,7348,7349,7350,7351,
7352,7353,7354,4347,4348,7357,7358,7359,4352,4353,4354,4355,4356,4357,4358,
4359,4360,4361,4362,4363,4364,4365,4366,4367,4368,4369,4370,4371,4372,4373,
4374,4375,4376,4377,4378,4379,4380,4381,4382,4383,4384,4385,4386,4387,4388,
4389,4390,4391,4392,4393,4394,4395,4396,4397,4398,4399,4400,4401,4402,4403,
4404,4405,4406,4407,4408,4409,4410,4411,4412,4413,4414,4415,4416,4417,4418,
4419,4420,4421,4422,4423,4424,4425,4426,4427,4428,4429,4430,4431,4432,4433,
4434,4435,4436,4437,4438,4439,4440,4441,4442,4443,4444,4445,4446,4447,4448,
4449,4450,4451,4452,4453,4454,4455,4456,4457,4458,4459,4460,4461,4462,4463,
4464,4465,4466,4467,4468,4469,4470,4471,4472,4473,4474,4475,4476,4477,4478,
4479,4480,4481,4482,4483,4484,4485,4486,4487,4488,4489,4490,4491,4492,4493,
4494,4495,4496,4497,4498,4499,4500,4501,4502,4503,4504,4505,4506,4507,4508,
4509,4510,4511,4512,4513,4514,4515,4516,4517,4518,4519,4520,4521,4522,4523,
4524,4525,4526,4527,4528,4529,4530,4531,4532,4533,4534,4535,4536,4537,4538,
4539,4540,4541,4542,4543,4544,4545,4546,4547,4548,4549,4550,4551,4552,4553,
4554,4555,4556,4557,4558,4559,4560,4561,4562,4563,4564,4565,4566,4567,4568,
4569,4570,4571,4572,4573,4574,4575,4576,4577,4578,4579,4580,4581,4582,4583,
4584,4585,4586,4587,4588,4589,4590,4591,4592,4593,4594,4595,4596,4597,4598,
4599,4600,4601,4602,4603,4604,4605,4606,4607,4608,4609,4610,4611,4612,4613,
4614,4615,4616,4617,4618,4619,4620,4621,4622,4623,4624,4625,4626,4627,4628,
4629,4630,4631,4632,4633,4634,4635,4636,4637,4638,4639,4640,4641,4642,4643,
4644,4645,4646,4647,4648,4649,4650,4651,4652,4653,4654,4655,4656,4657,4658,
4659,4660,4661,4662,4663,4664,4665,4666,4667,4668,4669,4670,4671,4672,4673,
4674,4675,4676,4677,4678,4679,4680,4681,4682,4683,4684,4685,4686,4687,4688,
4689,4690,4691,4692,4693,4694,4695,4696,4697,4698,4699,4700,4701,4702,4703,
4704,4705,4706,4707,4708,4709,4710,4711,4712,4713,4714,4715,4716,4717,4718,
4719,4720,4721,4722,4723,4724,4725,4726,4727,4728,4729,4730,4731,4732,4733,
4734,4735,4736,4737,4738,4739,4740,4741,4742,4743,4744,4745,4746,4747,4748,
4749,4750,4751,4752,4753,4754,4755,4756,4757,4758,4759,4760,4761,4762,4763,
4764,4765,4766,4767,4768,4769,4770,4771,4772,4773,4774,4775,4776,4777,4778,
4779,4780,4781,4782,4783,4784,4785,4786,4787,4788,4789,4790,4791,4792,4793,
4794,4795,4796,4797,4798,4799,4800,4801,4802,4803,4804,4805,4806,4807,4808,
4809,4810,4811,4812,4813,4814,4815,4816,4817,4818,4819,4820,4821,4822,4823,
4824,4825,4826,4827,4828,4829,4830,4831,4832,4833,4834,4835,4836,4837,4838,
4839,4840,4841,4842,4843,4844,4845,4846,4847,4848,4849,4850,4851,4852,4853,
4854,4855,4856,4857,4858,4859,4860,4861,4862,4863,4864,4865,4866,4867,4868,
4869,4870,4871,4872,4873,4874,4875,4876,4877,4878,4879,4880,4881,4882,4883,
4884,4885,4886,4887,4888,4889,4890,4891,4892,4893,4894,4895,4896,4897,4898,
4899,4900,4901,4902,4903,4904,4905,4906,4907,4908,4909,4910,4911,4912,4913,
4914,4915,4916,4917,4918,4919,4920,4921,4922,4923,4924,4925,4926,4927,4928,
4929,4930,4931,4932,4933,4934,4935,4936,4937,4938,4939,4940,4941,4942,4943,
4944,4945,4946,4947,4948,4949,4950,4951,4952,4953,4954,4955,4956,4957,4958,
4959,4960,4961,4962,4963,4964,4965,4966,4967,4968,4969,4970,4971,4972,4973,
4974,4975,4976,4977,4978,4979,4980,4981,4982,4983,4984,4985,4986,4987,4988,
4989,4990,4991,4992,4993,4994,4995,4996,4997,4998,4999,5000,5001,5002,5003,
5004,5005,5006,5007,5008,5009,5010,5011,5012,5013,5014,5015,5016,5017,5018,
5019,5020,5021,5022,5023,5024,5025,5026,5027,5028,5029,5030,5031,5032,5033,
5034,5035,5036,5037,5038,5039,5040,5041,5042,5043,5044,5045,5046,5047,5048,
5049,5050,5051,5052,5053,5054,5055,5056,5057,5058,5059,5060,5061,5062,5063,
5064,5065,5066,5067,5068,5069,5070,5071,5072,5073,5074,5075,5076,5077,5078,
5079,5080,5081,5082,5083,5084,5085,5086,5087,5088,5089,5090,5091,5092,5093,
5094,5095,5096,5097,5098,5099,5100,5101,5102,5103,5104,5105,5106,5107,5108,
5109,5110,5111,5104,5105,5106,5107,5108,5109,5118,5119,5120,5121,5122,5123,
5124,5125,5126,5127,5128,5129,5130,5131,5132,5133,5134,5135,5136,5137,5138,
5139,5140,5141,5142,5143,5144,5145,5146,5147,5148,5149,5150,5151,5152,5153,
5154,5155,5156,5157,5158,5159,5160,5161,5162,5163,5164,5165,5166,5167,5168,
5169,5170,5171,5172,5173,5174,5175,5176,5177,5178,5179,5180,5181,5182,5183,
5184,5185,5186,5187,5188,5189,5190,5191,5192,5193,5194,5195,5196,5197,5198,
5199,5200,5201,5202,5203,5204,5205,5206,5207,5208,5209,5210,5211,5212,5213,
5214,5215,5216,5217,5218,5219,5220,5221,5222,5223,5224,5225,5226,5227,5228,
5229,5230,5231,5232,5233,5234,5235,5236,5237,5238,5239,5240,5241,5242,5243,
5244,5245,5246,5247,5248,5249,5250,5251,5252,5253,5254,5255,5256,5257,5258,
5259,5260,5261,5262,5263,5264,5265,5266,5267,5268,5269,5270,5271,5272,5273,
5274,5275,5276,5277,5278,5279,5280,5281,5282,5283,5284,5285,5286,5287,5288,
5289,5290,5291,5292,5293,5294,5295,5296,5297,5298,5299,5300,5301,5302,5303,
5304,5305,5306,5307,5308,5309,5310,5311,5312,5313,5314,5315,5316,5317,5318,
5319,5320,5321,5322,5323,5324,5325,5326,5327,5328,5329,5330,5331,5332,5333,
5334,5335,5336,5337,5338,5339,5340,5341,5342,5343,5344,5345,5346,5347,5348,
5349,5350,5351,5352,5353,5354,5355,5356,5357,5358,5359,5360,5361,5362,5363,
5364,5365,5366,5367,5368,5369,5370,5371,5372,5373,5374,5375,5376,5377,5378,
5379,5380,5381,5382,5383,5384,5385,5386,5387,5388,5389,5390,5391,5392,5393,
5394,5395,5396,5397,5398,5399,5400,5401,5402,5403,5404,5405,5406,5407,5408,
5409,5410,5411,5412,5413,5414,5415,5416,5417,5418,5419,5420,5421,5422,5423,
5424,5425,5426,5427,5428,5429,5430,5431,5432,5433,5434,5435,5436,5437,5438,
5439,5440,5441,5442,5443,5444,5445,5446,5447,5448,5449,5450,5451,5452,5453,
5454,5455,5456,5457,5458,5459,5460,5461,5462,5463,5464,5465,5466,5467,5468,
5469,5470,5471,5472,5473,5474,5475,5476,5477,5478,5479,5480,5481,5482,5483,
5484,5485,5486,5487,5488,5489,5490,5491,5492,5493,5494,5495,5496,5497,5498,
5499,5500,5501,5502,5503,5504,5505,5506,5507,5508,5509,5510,5511,5512,5513,
5514,5515,5516,5517,5518,5519,5520,5521,5522,5523,5524,5525,5526,5527,5528,
5529,5530,5531,5532,5533,5534,5535,5536,5537,5538,5539,5540,5541,5542,5543,
5544,5545,5546,5547,5548,5549,5550,5551,5552,5553,5554,5555,5556,5557,5558,
5559,5560,5561,5562,5563,5564,5565,5566,5567,5568,5569,5570,5571,5572,5573,
5574,5575,5576,5577,5578,5579,5580,5581,5582,5583,5584,5585,5586,5587,5588,
5589,5590,5591,5592,5593,5594,5595,5596,5597,5598,5599,5600,5601,5602,5603,
5604,5605,5606,5607,5608,5609,5610,5611,5612,5613,5614,5615,5616,5617,5618,
5619,5620,5621,5622,5623,5624,5625,5626,5627,5628,5629,5630,5631,5632,5633,
5634,5635,5636,5637,5638,5639,5640,5641,5642,5643,5644,5645,5646,5647,5648,
5649,5650,5651,5652,5653,5654,5655,5656,5657,5658,5659,5660,5661,5662,5663,
5664,5665,5666,5667,5668,5669,5670,5671,5672,5673,5674,5675,5676,5677,5678,
5679,5680,5681,5682,5683,5684,5685,5686,5687,5688,5689,5690,5691,5692,5693,
5694,5695,5696,5697,5698,5699,5700,5701,5702,5703,5704,5705,5706,5707,5708,
5709,5710,5711,5712,5713,5714,5715,5716,5717,5718,5719,5720,5721,5722,5723,
5724,5725,5726,5727,5728,5729,5730,5731,5732,5733,5734,5735,5736,5737,5738,
5739,5740,5741,5742,5743,5744,5745,5746,5747,5748,5749,5750,5751,5752,5753,
5754,5755,5756,5757,5758,5759,5760,5761,5762,5763,5764,5765,5766,5767,5768,
5769,5770,5771,5772,5773,5774,5775,5776,5777,5778,5779,5780,5781,5782,5783,
5784,5785,5786,5787,5788,5789,5790,5791,5792,5793,5794,5795,5796,5797,5798,
5799,5800,5801,5802,5803,5804,5805,5806,5807,5808,5809,5810,5811,5812,5813,
5814,5815,5816,5817,5818,5819,5820,5821,5822,5823,5824,5825,5826,5827,5828,
5829,5830,5831,5832,5833,5834,5835,5836,5837,5838,5839,5840,5841,5842,5843,
5844,5845,5846,5847,5848,5849,5850,5851,5852,5853,5854,5855,5856,5857,5858,
5859,5860,5861,5862,5863,5864,5865,5866,5867,5868,5869,5870,5871,5872,5873,
5874,5875,5876,5877,5878,5879,5880,5881,5882,5883,5884,5885,5886,5887,5888,
5889,5890,5891,5892,5893,5894,5895,5896,5897,5898,5899,5900,5901,5902,5903,
5904,5905,5906,5907,5908,5909,5910,5911,5912,5913,5914,5915,5916,5917,5918,
5919,5920,5921,5922,5923,5924,5925,5926,5927,5928,5929,5930,5931,5932,5933,
5934,5935,5936,5937,5938,5939,5940,5941,5942,5943,5944,5945,5946,5947,5948,
5949,5950,5951,5952,5953,5954,5955,5956,5957,5958,5959,5960,5961,5962,5963,
5964,5965,5966,5967,5968,5969,5970,5971,5972,5973,5974,5975,5976,5977,5978,
5979,5980,5981,5982,5983,5984,5985,5986,5987,5988,5989,5990,5991,5992,5993,
5994,5995,5996,5997,5998,5999,6000,6001,6002,6003,6004,6005,6006,6007,6008,
6009,6010,6011,6012,6013,6014,6015,6016,6017,6018,6019,6020,6021,6022,6023,
6024,6025,6026,6027,6028,6029,6030,6031,6032,6033,6034,6035,6036,6037,6038,
6039,6040,6041,6042,6043,6044,6045,6046,6047,6048,6049,6050,6051,6052,6053,
6054,6055,6056,6057,6058,6059,6060,6061,6062,6063,6064,6065,6066,6067,6068,
6069,6070,6071,6072,6073,6074,6075,6076,6077,6078,6079,6080,6081,6082,6083,
6084,6085,6086,6087,6088,6089,6090,6091,6092,6093,6094,6095,6096,6097,6098,
6099,6100,6101,6102,6103,6104,6105,6106,6107,6108,6109,6110,6111,6112,6113,
6114,6115,6116,6117,6118,6119,6120,6121,6122,6123,6124,6125,6126,6127,6128,
6129,6130,6131,6132,6133,6134,6135,6136,6137,6138,6139,6140,6141,6142,6143,
6144,6145,6146,6147,6148,6149,6150,6151,6152,6153,6154,6155,6156,6157,6158,
6159,6160,6161,6162,6163,6164,6165,6166,6167,6168,6169,6170,6171,6172,6173,
6174,6175,6176,6177,6178,6179,6180,6181,6182,6183,6184,6185,6186,6187,6188,
6189,6190,6191,6192,6193,6194,6195,6196,6197,6198,6199,6200,6201,6202,6203,
6204,6205,6206,6207,6208,6209,6210,6211,6212,6213,6214,6215,6216,6217,6218,
6219,6220,6221,6222,6223,6224,6225,6226,6227,6228,6229,6230,6231,6232,6233,
6234,6235,6236,6237,6238,6239,6240,6241,6242,6243,6244,6245,6246,6247,6248,
6249,6250,6251,6252,6253,6254,6255,6256,6257,6258,6259,6260,6261,6262,6263,
6264,6265,6266,6267,6268,6269,6270,6271,6272,6273,6274,6275,6276,6277,6278,
6279,6280,6281,6282,6283,6284,6285,6286,6287,6288,6289,6290,6291,6292,6293,
6294,6295,6296,6297,6298,6299,6300,6301,6302,6303,6304,6305,6306,6307,6308,
6309,6310,6311,6312,6313,6314,6315,6316,6317,6318,6319,6320,6321,6322,6323,
6324,6325,6326,6327,6328,6329,6330,6331,6332,6333,6334,6335,6336,6337,6338,
6339,6340,6341,6342,6343,6344,6345,6346,6347,6348,6349,6350,6351,6352,6353,
6354,6355,6356,6357,6358,6359,6360,6361,6362,6363,6364,6365,6366,6367,6368,
6369,6370,6371,6372,6373,6374,6375,6376,6377,6378,6379,6380,6381,6382,6383,
6384,6385,6386,6387,6388,6389,6390,6391,6392,6393,6394,6395,6396,6397,6398,
6399,6400,6401,6402,6403,6404,6405,6406,6407,6408,6409,6410,6411,6412,6413,
6414,6415,6416,6417,6418,6419,6420,6421,6422,6423,6424,6425,6426,6427,6428,
6429,6430,6431,6432,6433,6434,6435,6436,6437,6438,6439,6440,6441,6442,6443,
6444,6445,6446,6447,6448,6449,6450,6451,6452,6453,6454,6455,6456,6457,6458,
6459,6460,6461,6462,6463,6464,6465,6466,6467,6468,6469,6470,6471,6472,6473,
6474,6475,6476,6477,6478,6479,6480,6481,6482,6483,6484,6485,6486,6487,6488,
6489,6490,6491,6492,6493,6494,6495,6496,6497,6498,6499,6500,6501,6502,6503,
6504,6505,6506,6507,6508,6509,6510,6511,6512,6513,6514,6515,6516,6517,6518,
6519,6520,6521,6522,6523,6524,6525,6526,6527,6528,6529,6530,6531,6532,6533,
6534,6535,6536,6537,6538,6539,6540,6541,6542,6543,6544,6545,6546,6547,6548,
6549,6550,6551,6552,6553,6554,6555,6556,6557,6558,6559,6560,6561,6562,6563,
6564,6565,6566,6567,6568,6569,6570,6571,6572,6573,6574,6575,6576,6577,6578,
6579,6580,6581,6582,6583,6584,6585,6586,6587,6588,6589,6590,6591,6592,6593,
6594,6595,6596,6597,6598,6599,6600,6601,6602,6603,6604,6605,6606,6607,6608,
6609,6610,6611,6612,6613,6614,6615,6616,6617,6618,6619,6620,6621,6622,6623,
6624,6625,6626,6627,6628,6629,6630,6631,6632,6633,6634,6635,6636,6637,6638,
6639,6640,6641,6642,6643,6644,6645,6646,6647,6648,6649,6650,6651,6652,6653,
6654,6655,6656,6657,6658,6659,6660,6661,6662,6663,6664,6665,6666,6667,6668,
6669,6670,6671,6672,6673,6674,6675,6676,6677,6678,6679,6680,6681,6682,6683,
6684,6685,6686,6687,6688,6689,6690,6691,6692,6693,6694,6695,6696,6697,6698,
6699,6700,6701,6702,6703,6704,6705,6706,6707,6708,6709,6710,6711,6712,6713,
6714,6715,6716,6717,6718,6719,6720,6721,6722,6723,6724,6725,6726,6727,6728,
6729,6730,6731,6732,6733,6734,6735,6736,6737,6738,6739,6740,6741,6742,6743,
6744,6745,6746,6747,6748,6749,6750,6751,6752,6753,6754,6755,6756,6757,6758,
6759,6760,6761,6762,6763,6764,6765,6766,6767,6768,6769,6770,6771,6772,6773,
6774,6775,6776,6777,6778,6779,6780,6781,6782,6783,6784,6785,6786,6787,6788,
6789,6790,6791,6792,6793,6794,6795,6796,6797,6798,6799,6800,6801,6802,6803,
6804,6805,6806,6807,6808,6809,6810,6811,6812,6813,6814,6815,6816,6817,6818,
6819,6820,6821,6822,6823,6824,6825,6826,6827,6828,6829,6830,6831,6832,6833,
6834,6835,6836,6837,6838,6839,6840,6841,6842,6843,6844,6845,6846,6847,6848,
6849,6850,6851,6852,6853,6854,6855,6856,6857,6858,6859,6860,6861,6862,6863,
6864,6865,6866,6867,6868,6869,6870,6871,6872,6873,6874,6875,6876,6877,6878,
6879,6880,6881,6882,6883,6884,6885,6886,6887,6888,6889,6890,6891,6892,6893,
6894,6895,6896,6897,6898,6899,6900,6901,6902,6903,6904,6905,6906,6907,6908,
6909,6910,6911,6912,6913,6914,6915,6916,6917,6918,6919,6920,6921,6922,6923,
6924,6925,6926,6927,6928,6929,6930,6931,6932,6933,6934,6935,6936,6937,6938,
6939,6940,6941,6942,6943,6944,6945,6946,6947,6948,6949,6950,6951,6952,6953,
6954,6955,6956,6957,6958,6959,6960,6961,6962,6963,6964,6965,6966,6967,6968,
6969,6970,6971,6972,6973,6974,6975,6976,6977,6978,6979,6980,6981,6982,6983,
6984,6985,6986,6987,6988,6989,6990,6991,6992,6993,6994,6995,6996,6997,6998,
6999,7000,7001,7002,7003,7004,7005,7006,7007,7008,7009,7010,7011,7012,7013,
7014,7015,7016,7017,7018,7019,7020,7021,7022,7023,7024,7025,7026,7027,7028,
7029,7030,7031,7032,7033,7034,7035,7036,7037,7038,7039,7040,7041,7042,7043,
7044,7045,7046,7047,7048,7049,7050,7051,7052,7053,7054,7055,7056,7057,7058,
7059,7060,7061,7062,7063,7064,7065,7066,7067,7068,7069,7070,7071,7072,7073,
7074,7075,7076,7077,7078,7079,7080,7081,7082,7083,7084,7085,7086,7087,7088,
7089,7090,7091,7092,7093,7094,7095,7096,7097,7098,7099,7100,7101,7102,7103,
7104,7105,7106,7107,7108,7109,7110,7111,7112,7113,7114,7115,7116,7117,7118,
7119,7120,7121,7122,7123,7124,7125,7126,7127,7128,7129,7130,7131,7132,7133,
7134,7135,7136,7137,7138,7139,7140,7141,7142,7143,7144,7145,7146,7147,7148,
7149,7150,7151,7152,7153,7154,7155,7156,7157,7158,7159,7160,7161,7162,7163,
7164,7165,7166,7167,7168,7169,7170,7171,7172,7173,7174,7175,7176,7177,7178,
7179,7180,7181,7182,7183,7184,7185,7186,7187,7188,7189,7190,7191,7192,7193,
7194,7195,7196,7197,7198,7199,7200,7201,7202,7203,7204,7205,7206,7207,7208,
7209,7210,7211,7212,7213,7214,7215,7216,7217,7218,7219,7220,7221,7222,7223,
7224,7225,7226,7227,7228,7229,7230,7231,7232,7233,7234,7235,7236,7237,7238,
7239,7240,7241,7242,7243,7244,7245,7246,7247,7248,7249,7250,7251,7252,7253,
7254,7255,7256,7257,7258,7259,7260,7261,7262,7263,7264,7265,7266,7267,7268,
7269,7270,7271,7272,7273,7274,7275,7276,7277,7278,7279,7280,7281,7282,7283,
7284,7285,7286,7287,7288,7289,7290,7291,7292,7293,7294,7295,1042,1044,1054,
1057,1058,1058,1066,1122,42570L,7305,7306,7307,7308,7309,7310,7311,7312,
7313,7314,7315,7316,7317,7318,7319,7320,7321,7322,7323,7324,7325,7326,7327,
7328,7329,7330,7331,7332,7333,7334,7335,7336,7337,7338,7339,7340,7341,7342,
7343,7344,7345,7346,7347,7348,7349,7350,7351,7352,7353,7354,7355,7356,7357,
7358,7359,7360,7361,7362,7363,7364,7365,7366,7367,7368,7369,7370,7371,7372,
7373,7374,7375,7376,7377,7378,7379,7380,7381,7382,7383,7384,7385,7386,7387,
7388,7389,7390,7391,7392,7393,7394,7395,7396,7397,7398,7399,7400,7401,7402,
7403,7404,7405,7406,7407,7408,7409,7410,7411,7412,7413,7414,7415,7416,7417,
7418,7419,7420,7421,7422,7423,7424,7425,7426,7427,7428,7429,7430,7431,7432,
7433,7434,7435,7436,7437,7438,7439,7440,7441,7442,7443,7444,7445,7446,7447,
7448,7449,7450,7451,7452,7453,7454,7455,7456,7457,7458,7459,7460,7461,7462,
7463,7464,7465,7466,7467,7468,7469,7470,7471,7472,7473,7474,7475,7476,7477,
7478,7479,7480,7481,7482,7483,7484,7485,7486,7487,7488,7489,7490,7491,7492,
7493,7494,7495,7496,7497,7498,7499,7500,7501,7502,7503,7504,7505,7506,7507,
7508,7509,7510,7511,7512,7513,7514,7515,7516,7517,7518,7519,7520,7521,7522,
7523,7524,7525,7526,7527,7528,7529,7530,7531,7532,7533,7534,7535,7536,7537,
7538,7539,7540,7541,7542,7543,7544,42877L,7546,7547,7548,11363,7550,7551,
7552,7553,7554,7555,7556,7557,7558,7559,7560,7561,7562,7563,7564,7565,
42950L,7567,7568,7569,7570,7571,7572,7573,7574,7575,7576,7577,7578,7579,
7580,7581,7582,7583,7584,7585,7586,7587,7588,7589,7590,7591,7592,7593,7594,
7595,7596,7597,7598,7599,7600,7601,7602,7603,7604,7605,7606,7607,7608,7609,
7610,7611,7612,7613,7614,7615,7616,7617,7618,7619,7620,7621,7622,7623,7624,
7625,7626,7627,7628,7629,7630,7631,7632,7633,7634,7635,7636,7637,7638,7639,
7640,7641,7642,7643,7644,7645,7646,7647,7648,7649,7650,7651,7652,7653,7654,
7655,7656,7657,7658,7659,7660,7661,7662,7663,7664,7665,7666,7667,7668,7669,
7670,7671,7672,7673,7674,7675,7676,7677,7678,7679,7680,7680,7682,7682,7684,
7684,7686,7686,7688,7688,7690,7690,7692,7692,7694,7694,7696,7696,7698,7698,
7700,7700,7702,7702,7704,7704,7706,7706,7708,7708,7710,7710,7712,7712,7714,
7714,7716,7716,7718,7718,7720,7720,7722,7722,7724,7724,7726,7726,7728,7728,
7730,7730,7732,7732,7734,7734,7736,7736,7738,7738,7740,7740,7742,7742,7744,
7744,7746,7746,7748,7748,7750,7750,7752,7752,7754,7754,7756,7756,7758,7758,
7760,7760,7762,7762,7764,7764,7766,7766,7768,7768,7770,7770,7772,7772,7774,
7774,7776,7776,7778,7778,7780,7780,7782,7782,7784,7784,7786,7786,7788,7788,
7790,7790,7792,7792,7794,7794,7796,7796,7798,7798,7800,7800,7802,7802,7804,
7804,7806,7806,7808,7808,7810,7810,7812,7812,7814,7814,7816,7816,7818,7818,
7820,7820,7822,7822,7824,7824,7826,7826,7828,7828,7830,7831,7832,7833,7834,
7776,7836,7837,7838,7839,7840,7840,7842,7842,7844,7844,7846,7846,7848,7848,
7850,7850,7852,7852,7854,7854,7856,7856,7858,7858,7860,7860,7862,7862,7864,
7864,7866,7866,7868,7868,7870,7870,7872,7872,7874,7874,7876,7876,7878,7878,
7880,7880,7882,7882,7884,7884,7886,7886,7888,7888,7890,7890,7892,7892,7894,
7894,7896,7896,7898,7898,7900,7900,7902,7902,7904,7904,7906,7906,7908,7908,
7910,7910,7912,7912,7914,7914,7916,7916,7918,7918,7920,7920,7922,7922,7924,
7924,7926,7926,7928,7928,7930,7930,7932,7932,7934,7934,7944,7945,7946,7947,
7948,7949,7950,7951,7944,7945,7946,7947,7948,7949,7950,7951,7960,7961,7962,
7963,7964,7965,7958,7959,7960,7961,7962,7963,7964,7965,7966,7967,7976,7977,
7978,7979,7980,7981,7982,7983,7976,7977,7978,7979,7980,7981,7982,7983,7992,
7993,7994,7995,7996,7997,7998,7999,7992,7993,7994,7995,7996,7997,7998,7999,
8008,8009,8010,8011,8012,8013,8006,8007,8008,8009,8010,8011,8012,8013,8014,
8015,8016,8025,8018,8027,8020,8029,8022,8031,8024,8025,8026,8027,8028,8029,
8030,8031,8040,8041,8042,8043,8044,8045,8046,8047,8040,8041,8042,8043,8044,
8045,8046,8047,8122,8123,8136,8137,8138,8139,8154,8155,8184,8185,8170,8171,
8186,8187,8062,8063,8064,8065,8066,8067,8068,8069,8070,8071,8072,8073,8074,
8075,8076,8077,8078,8079,8080,8081,8082,8083,8084,8085,8086,8087,8088,8089,
8090,8091,8092,8093,8094,8095,8096,8097,8098,8099,8100,8101,8102,8103,8104,
8105,8106,8107,8108,8109,8110,8111,8120,8121,8114,8115,8116,8117,8118,8119,
8120,8121,8122,8123,8124,8125,921,8127,8128,8129,8130,8131,8132,8133,8134,
8135,8136,8137,8138,8139,8140,8141,8142,8143,8152,8153,8146,8147,8148,8149,
8150,8151,8152,8153,8154,8155,8156,8157,8158,8159,8168,8169,8162,8163,8164,
8172,8166,8167,8168,8169,8170,8171,8172,8173,8174,8175,8176,8177,8178,8179,
8180,8181,8182,8183,8184,8185,8186,8187,8188,8189,8190,8191,8192,8193,8194,
8195,8196,8197,8198,8199,8200,8201,8202,8203,8204,8205,8206,8207,8208,8209,
8210,8211,8212,8213,8214,8215,8216,8217,8218,8219,8220,8221,8222,8223,8224,
8225,8226,8227,8228,8229,8230,8231,8232,8233,8234,8235,8236,8237,8238,8239,
8240,8241,8242,8243,8244,8245,8246,8247,8248,8249,8250,8251,8252,8253,8254,
8255,8256,8257,8258,8259,8260,8261,8262,8263,8264,8265,8266,8267,8268,8269,
8270,8271,8272,8273,8274,8275,8276,8277,8278,8279,8280,8281,8282,8283,8284,
8285,8286,8287,8288,8289,8290,8291,8292,8293,8294,8295,8296,8297,8298,8299,
8300,8301,8302,8303,8304,8305,8306,8307,8308,8309,8310,8311,8312,8313,8314,
8315,8316,8317,8318,8319,8320,8321,8322,8323,8324,8325,8326,8327,8328,8329,
8330,8331,8332,8333,8334,8335,8336,8337,8338,8339,8340,8341,8342,8343,8344,
8345,8346,8347,8348,8349,8350,8351,8352,8353,8354,8355,8356,8357,8358,8359,
8360,8361,8362,8363,8364,8365,8366,8367,8368,8369,8370,8371,8372,8373,8374,
8375,8376,8377,8378,8379,8380,8381,8382,8383,8384,8385,8386,8387,8388,8389,
8390,8391,8392,8393,8394,8395,8396,8397,8398,8399,8400,8401,8402,8403,8404,
8405,8406,8407,8408,8409,8410,8411,8412,8413,8414,8415,8416,8417,8418,8419,
8420,8421,8422,8423,8424,8425,8426,8427,8428,8429,8430,8431,8432,8433,8434,
8435,8436,8437,8438,8439,8440,8441,8442,8443,8444,8445,8446,8447,8448,8449,
8450,8451,8452,8453,8454,8455,8456,8457,8458,8459,8460,8461,8462,8463,8464,
8465,8466,8467,8468,8469,8470,8471,8472,8473,8474,8475,8476,8477,8478,8479,
8480,8481,8482,8483,8484,8485,8486,8487,8488,8489,8490,8491,8492,8493,8494,
8495,8496,8497,8498,8499,8500,8501,8502,8503,8504,8505,8506,8507,8508,8509,
8510,8511,8512,8513,8514,8515,8516,8517,8518,8519,8520,8521,8522,8523,8524,
8525,8498,8527,8528,8529,8530,8531,8532,8533,8534,8535,8536,8537,8538,8539,
8540,8541,8542,8543,8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,8554,
8555,8556,8557,8558,8559,8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,
8554,8555,8556,8557,8558,8559,8576,8577,8578,8579,8579,8581,8582,8583,8584,
8585,8586,8587,8588,8589,8590,8591,8592,8593,8594,8595,8596,8597,8598,8599,
8600,8601,8602,8603,8604,8605,8606,8607,8608,8609,8610,8611,8612,8613,8614,
8615,8616,8617,8618,8619,8620,8621,8622,8623,8624,8625,8626,8627,8628,8629,
8630,8631,8632,8633,8634,8635,8636,8637,8638,8639,8640,8641,8642,8643,8644,
8645,8646,8647,8648,8649,8650,8651,8652,8653,8654,8655,8656,8657,8658,8659,
8660,8661,8662,8663,8664,8665,8666,8667,8668,8669,8670,8671,8672,8673,8674,
8675,8676,8677,8678,8679,8680,8681,8682,8683,8684,8685,8686,8687,8688,8689,
8690,8691,8692,8693,8694,8695,8696,8697,8698,8699,8700,8701,8702,8703,8704,
8705,8706,8707,8708,8709,8710,8711,8712,8713,8714,8715,8716,8717,8718,8719,
8720,8721,8722,8723,8724,8725,8726,8727,8728,8729,8730,8731,8732,8733,8734,
8735,8736,8737,8738,8739,8740,8741,8742,8743,8744,8745,8746,8747,8748,8749,
8750,8751,8752,8753,8754,8755,8756,8757,8758,8759,8760,8761,8762,8763,8764,
8765,8766,8767,8768,8769,8770,8771,8772,8773,8774,8775,8776,8777,8778,8779,
8780,8781,8782,8783,8784,8785,8786,8787,8788,8789,8790,8791,8792,8793,8794,
8795,8796,8797,8798,8799,8800,8801,8802,8803,8804,8805,8806,8807,8808,8809,
8810,8811,8812,8813,8814,8815,8816,8817,8818,8819,8820,8821,8822,8823,8824,
8825,8826,8827,8828,8829,8830,8831,8832,8833,8834,8835,8836,8837,8838,8839,
8840,8841,8842,8843,8844,8845,8846,8847,8848,8849,8850,8851,8852,8853,8854,
8855,8856,8857,8858,8859,8860,8861,8862,8863,8864,8865,8866,8867,8868,8869,
8870,8871,8872,8873,8874,8875,8876,8877,8878,8879,8880,8881,8882,8883,8884,
8885,8886,8887,8888,8889,8890,8891,8892,8893,8894,8895,8896,8897,8898,8899,
8900,8901,8902,8903,8904,8905,8906,8907,8908,8909,8910,8911,8912,8913,8914,
8915,8916,8917,8918,8919,8920,8921,8922,8923,8924,8925,8926,8927,8928,8929,
8930,8931,8932,8933,8934,8935,8936,8937,8938,8939,8940,8941,8942,8943,8944,
8945,8946,8947,8948,8949,8950,8951,8952,8953,8954,8955,8956,8957,8958,8959,
8960,8961,8962,8963,8964,8965,8966,8967,8968,8969,8970,8971,8972,8973,8974,
8975,8976,8977,8978,8979,8980,8981,8982,8983,8984,8985,8986,8987,8988,8989,
8990,8991,8992,8993,8994,8995,8996,8997,8998,8999,9000,9001,9002,9003,9004,
9005,9006,9007,9008,9009,9010,9011,9012,9013,9014,9015,9016,9017,9018,9019,
9020,9021,9022,9023,9024,9025,9026,9027,9028,9029,9030,9031,9032,9033,9034,
9035,9036,9037,9038,9039,9040,9041,9042,9043,9044,9045,9046,9047,9048,9049,
9050,9051,9052,9053,9054,9055,9056,9057,9058,9059,9060,9061,9062,9063,9064,
9065,9066,9067,9068,9069,9070,9071,9072,9073,9074,9075,9076,9077,9078,9079,
9080,9081,9082,9083,9084,9085,9086,9087,9088,9089,9090,9091,9092,9093,9094,
9095,9096,9097,9098,9099,9100,9101,9102,9103,9104,9105,9106,9107,9108,9109,
9110,9111,9112,9113,9114,9115,9116,9117,9118,9119,9120,9121,9122,9123,9124,
9125,9126,9127,9128,9129,9130,9131,9132,9133,9134,9135,9136,9137,9138,9139,
9140,9141,9142,9143,9144,9145,9146,9147,9148,9149,9150,9151,9152,9153,9154,
9155,9156,9157,9158,9159,9160,9161,9162,9163,9164,9165,9166,9167,9168,9169,
9170,9171,9172,9173,9174,9175,9176,9177,9178,9179,9180,9181,9182,9183,9184,
9185,9186,9187,9188,9189,9190,9191,9192,9193,9194,9195,9196,9197,9198,9199,
9200,9201,9202,9203,9204,9205,9206,9207,9208,9209,9210,9211,9212,9213,9214,
9215,9216,9217,9218,9219,9220,9221,9222,9223,9224,9225,9226,9227,9228,9229,
9230,9231,9232,9233,9234,9235,9236,9237,9238,9239,9240,9241,9242,9243,9244,
9245,9246,9247,9248,9249,9250,9251,9252,9253,9254,9255,9256,9257,9258,9259,
9260,9261,9262,9263,9264,9265,9266,9267,9268,9269,9270,9271,9272,9273,9274,
9275,9276,9277,9278,9279,9280,9281,9282,9283,9284,9285,9286,9287,9288,9289,
9290,9291,9292,9293,9294,9295,9296,9297,9298,9299,9300,9301,9302,9303,9304,
9305,9306,9307,9308,9309,9310,9311,9312,9313,9314,9315,9316,9317,9318,9319,
9320,9321,9322,9323,9324,9325,9326,9327,9328,9329,9330,9331,9332,9333,9334,
9335,9336,9337,9338,9339,9340,9341,9342,9343,9344,9345,9346,9347,9348,9349,
9350,9351,9352,9353,9354,9355,9356,9357,9358,9359,9360,9361,9362,9363,9364,
9365,9366,9367,9368,9369,9370,9371,9372,9373,9374,9375,9376,9377,9378,9379,
9380,9381,9382,9383,9384,9385,9386,9387,9388,9389,9390,9391,9392,9393,9394,
9395,9396,9397,9398,9399,9400,9401,9402,9403,9404,9405,9406,9407,9408,9409,
9410,9411,9412,9413,9414,9415,9416,9417,9418,9419,9420,9421,9422,9423,9398,
9399,9400,9401,9402,9403,9404,9405,9406,9407,9408,9409,9410,9411,9412,9413,
9414,9415,9416,9417,9418,9419,9420,9421,9422,9423,9450,9451,9452,9453,9454,
9455,9456,9457,9458,9459,9460,9461,9462,9463,9464,9465,9466,9467,9468,9469,
9470,9471,9472,9473,9474,9475,9476,9477,9478,9479,9480,9481,9482,9483,9484,
9485,9486,9487,9488,9489,9490,9491,9492,9493,9494,9495,9496,9497,9498,9499,
9500,9501,9502,9503,9504,9505,9506,9507,9508,9509,9510,9511,9512,9513,9514,
9515,9516,9517,9518,9519,9520,9521,9522,9523,9524,9525,9526,9527,9528,9529,
9530,9531,9532,9533,9534,9535,9536,9537,9538,9539,9540,9541,9542,9543,9544,
9545,9546,9547,9548,9549,9550,9551,9552,9553,9554,9555,9556,9557,9558,9559,
9560,9561,9562,9563,9564,9565,9566,9567,9568,9569,9570,9571,9572,9573,9574,
9575,9576,9577,9578,9579,9580,9581,9582,9583,9584,9585,9586,9587,9588,9589,
9590,9591,9592,9593,9594,9595,9596,9597,9598,9599,9600,9601,9602,9603,9604,
9605,9606,9607,9608,9609,9610,9611,9612,9613,9614,9615,9616,9617,9618,9619,
9620,9621,9622,9623,9624,9625,9626,9627,9628,9629,9630,9631,9632,9633,9634,
9635,9636,9637,9638,9639,9640,9641,9642,9643,9644,9645,9646,9647,9648,9649,
9650,9651,9652,9653,9654,9655,9656,9657,9658,9659,9660,9661,9662,9663,9664,
9665,9666,9667,9668,9669,9670,9671,9672,9673,9674,9675,9676,9677,9678,9679,
9680,9681,9682,9683,9684,9685,9686,9687,9688,9689,9690,9691,9692,9693,9694,
9695,9696,9697,9698,9699,9700,9701,9702,9703,9704,9705,9706,9707,9708,9709,
9710,9711,9712,9713,9714,9715,9716,9717,9718,9719,9720,9721,9722,9723,9724,
9725,9726,9727,9728,9729,9730,9731,9732,9733,9734,9735,9736,9737,9738,9739,
9740,9741,9742,9743,9744,9745,9746,9747,9748,9749,9750,9751,9752,9753,9754,
9755,9756,9757,9758,9759,9760,9761,9762,9763,9764,9765,9766,9767,9768,9769,
9770,9771,9772,9773,9774,9775,9776,9777,9778,9779,9780,9781,9782,9783,9784,
9785,9786,9787,9788,9789,9790,9791,9792,9793,9794,9795,9796,9797,9798,9799,
9800,9801,9802,9803,9804,9805,9806,9807,9808,9809,9810,9811,9812,9813,9814,
9815,9816,9817,9818,9819,9820,9821,9822,9823,9824,9825,9826,9827,9828,9829,
9830,9831,9832,9833,9834,9835,9836,9837,9838,9839,9840,9841,9842,9843,9844,
9845,9846,9847,9848,9849,9850,9851,9852,9853,9854,9855,9856,9857,9858,9859,
9860,9861,9862,9863,9864,9865,9866,9867,9868,9869,9870,9871,9872,9873,9874,
9875,9876,9877,9878,9879,9880,9881,9882,9883,9884,9885,9886,9887,9888,9889,
9890,9891,9892,9893,9894,9895,9896,9897,9898,9899,9900,9901,9902,9903,9904,
9905,9906,9907,9908,9909,9910,9911,9912,9913,9914,9915,9916,9917,9918,9919,
9920,9921,9922,9923,9924,9925,9926,9927,9928,9929,9930,9931,9932,9933,9934,
9935,9936,9937,9938,9939,9940,9941,9942,9943,9944,9945,9946,9947,9948,9949,
9950,9951,9952,9953,9954,9955,9956,9957,9958,9959,9960,9961,9962,9963,9964,
9965,9966,9967,9968,9969,9970,9971,9972,9973,9974,9975,9976,9977,9978,9979,
9980,9981,9982,9983,9984,9985,9986,9987,9988,9989,9990,9991,9992,9993,9994,
9995,9996,9997,9998,9999,10000,10001,10002,10003,10004,10005,10006,10007,
10008,10009,10010,10011,10012,10013,10014,10015,10016,10017,10018,10019,
10020,10021,10022,10023,10024,10025,10026,10027,10028,10029,10030,10031,
10032,10033,10034,10035,10036,10037,10038,10039,10040,10041,10042,10043,
10044,10045,10046,10047,10048,10049,10050,10051,10052,10053,10054,10055,
10056,10057,10058,10059,10060,10061,10062,10063,10064,10065,10066,10067,
10068,10069,10070,10071,10072,10073,10074,10075,10076,10077,10078,10079,
10080,10081,10082,10083,10084,10085,10086,10087,10088,10089,10090,10091,
10092,10093,10094,10095,10096,10097,10098,10099,10100,10101,10102,10103,
10104,10105,10106,10107,10108,10109,10110,10111,10112,10113,10114,10115,
10116,10117,10118,10119,10120,10121,10122,10123,10124,10125,10126,10127,
10128,10129,10130,10131,10132,10133,10134,10135,10136,10137,10138,10139,
10140,10141,10142,10143,10144,10145,10146,10147,10148,10149,10150,10151,
10152,10153,10154,10155,10156,10157,10158,10159,10160,10161,10162,10163,
10164,10165,10166,10167,10168,10169,10170,10171,10172,10173,10174,10175,
10176,10177,10178,10179,10180,10181,10182,10183,10184,10185,10186,10187,
10188,10189,10190,10191,10192,10193,10194,10195,10196,10197,10198,10199,
10200,10201,10202,10203,10204,10205,10206,10207,10208,10209,10210,10211,
10212,10213,10214,10215,10216,10217,10218,10219,10220,10221,10222,10223,
10224,10225,10226,10227,10228,10229,10230,10231,10232,10233,10234,10235,
10236,10237,10238,10239,10240,10241,10242,10243,10244,10245,10246,10247,
10248,10249,10250,10251,10252,10253,10254,10255,10256,10257,10258,10259,
10260,10261,10262,10263,10264,10265,10266,10267,10268,10269,10270,10271,
10272,10273,10274,10275,10276,10277,10278,10279,10280,10281,10282,10283,
10284,10285,10286,10287,10288,10289,10290,10291,10292,10293,10294,10295,
10296,10297,10298,10299,10300,10301,10302,10303,10304,10305,10306,10307,
10308,10309,10310,10311,10312,10313,10314,10315,10316,10317,10318,10319,
10320,10321,10322,10323,10324,10325,10326,10327,10328,10329,10330,10331,
10332,10333,10334,10335,10336,10337,10338,10339,10340,10341,10342,10343,
10344,10345,10346,10347,10348,10349,10350,10351,10352,10353,10354,10355,
10356,10357,10358,10359,10360,10361,10362,10363,10364,10365,10366,10367,
10368,10369,10370,10371,10372,10373,10374,10375,10376,10377,10378,10379,
10380,10381,10382,10383,10384,10385,10386,10387,10388,10389,10390,10391,
10392,10393,10394,10395,10396,10397,10398,10399,10400,10401,10402,10403,
10404,10405,10406,10407,10408,10409,10410,10411,10412,10413,10414,10415,
10416,10417,10418,10419,10420,10421,10422,10423,10424,10425,10426,10427,
10428,10429,10430,10431,10432,10433,10434,10435,10436,10437,10438,10439,
10440,10441,10442,10443,10444,10445,10446,10447,10448,10449,10450,10451,
10452,10453,10454,10455,10456,10457,10458,10459,10460,10461,10462,10463,
10464,10465,10466,10467,10468,10469,10470,10471,10472,10473,10474,10475,
10476,10477,10478,10479,10480,10481,10482,10483,10484,10485,10486,10487,
10488,10489,10490,10491,10492,10493,10494,10495,10496,10497,10498,10499,
10500,10501,10502,10503,10504,10505,10506,10507,10508,10509,10510,10511,
10512,10513,10514,10515,10516,10517,10518,10519,10520,10521,10522,10523,
10524,10525,10526,10527,10528,10529,10530,10531,10532,10533,10534,10535,
10536,10537,10538,10539,10540,10541,10542,10543,10544,10545,10546,10547,
10548,10549,10550,10551,10552,10553,10554,10555,10556,10557,10558,10559,
10560,10561,10562,10563,10564,10565,10566,10567,10568,10569,10570,10571,
10572,10573,10574,10575,10576,10577,10578,10579,10580,10581,10582,10583,
10584,10585,10586,10587,10588,10589,10590,10591,10592,10593,10594,10595,
10596,10597,10598,10599,10600,10601,10602,10603,10604,10605,10606,10607,
10608,10609,10610,10611,10612,10613,10614,10615,10616,10617,10618,10619,
10620,10621,10622,10623,10624,10625,10626,10627,10628,10629,10630,10631,
10632,10633,10634,10635,10636,10637,10638,10639,10640,10641,10642,10643,
10644,10645,10646,10647,10648,10649,10650,10651,10652,10653,10654,10655,
10656,10657,10658,10659,10660,10661,10662,10663,10664,10665,10666,10667,
10668,10669,10670,10671,10672,10673,10674,10675,10676,10677,10678,10679,
10680,10681,10682,10683,10684,10685,10686,10687,10688,10689,10690,10691,
10692,10693,10694,10695,10696,10697,10698,10699,10700,10701,10702,10703,
10704,10705,10706,10707,10708,10709,10710,10711,10712,10713,10714,10715,
10716,10717,10718,10719,10720,10721,10722,10723,10724,10725,10726,10727,
10728,10729,10730,10731,10732,10733,10734,10735,10736,10737,10738,10739,
10740,10741,10742,10743,10744,10745,10746,10747,10748,10749,10750,10751,
10752,10753,10754,10755,10756,10757,10758,10759,10760,10761,10762,10763,
10764,10765,10766,10767,10768,10769,10770,10771,10772,10773,10774,10775,
10776,10777,10778,10779,10780,10781,10782,10783,10784,10785,10786,10787,
10788,10789,10790,10791,10792,10793,10794,10795,10796,10797,10798,10799,
10800,10801,10802,10803,10804,10805,10806,10807,10808,10809,10810,10811,
10812,10813,10814,10815,10816,10817,10818,10819,10820,10821,10822,10823,
10824,10825,10826,10827,10828,10829,10830,10831,10832,10833,10834,10835,
10836,10837,10838,10839,10840,10841,10842,10843,10844,10845,10846,10847,
10848,10849,10850,10851,10852,10853,10854,10855,10856,10857,10858,10859,
10860,10861,10862,10863,10864,10865,10866,10867,10868,10869,10870,10871,
10872,10873,10874,10875,10876,10877,10878,10879,10880,10881,10882,10883,
10884,10885,10886,10887,10888,10889,10890,10891,10892,10893,10894,10895,
10896,10897,10898,10899,10900,10901,10902,10903,10904,10905,10906,10907,
10908,10909,10910,10911,10912,10913,10914,10915,10916,10917,10918,10919,
10920,10921,10922,10923,10924,10925,10926,10927,10928,10929,10930,10931,
10932,10933,10934,10935,10936,10937,10938,10939,10940,10941,10942,10943,
10944,10945,10946,10947,10948,10949,10950,10951,10952,10953,10954,10955,
10956,10957,10958,10959,10960,10961,10962,10963,10964,10965,10966,10967,
10968,10969,10970,10971,10972,10973,10974,10975,10976,10977,10978,10979,
10980,10981,10982,10983,10984,10985,10986,10987,10988,10989,10990,10991,
10992,10993,10994,10995,10996,10997,10998,10999,11000,11001,11002,11003,
11004,11005,11006,11007,11008,11009,11010,11011,11012,11013,11014,11015,
11016,11017,11018,11019,11020,11021,11022,11023,11024,11025,11026,11027,
11028,11029,11030,11031,11032,11033,11034,11035,11036,11037,11038,11039,
11040,11041,11042,11043,11044,11045,11046,11047,11048,11049,11050,11051,
11052,11053,11054,11055,11056,11057,11058,11059,11060,11061,11062,11063,
11064,11065,11066,11067,11068,11069,11070,11071,11072,11073,11074,11075,
11076,11077,11078,11079,11080,11081,11082,11083,11084,11085,11086,11087,
11088,11089,11090,11091,11092,11093,11094,11095,11096,11097,11098,11099,
11100,11101,11102,11103,11104,11105,11106,11107,11108,11109,11110,11111,
11112,11113,11114,11115,11116,11117,11118,11119,11120,11121,11122,11123,
11124,11125,11126,11127,11128,11129,11130,11131,11132,11133,11134,11135,
11136,11137,11138,11139,11140,11141,11142,11143,11144,11145,11146,11147,
11148,11149,11150,11151,11152,11153,11154,11155,11156,11157,11158,11159,
11160,11161,11162,11163,11164,11165,11166,11167,11168,11169,11170,11171,
11172,11173,11174,11175,11176,11177,11178,11179,11180,11181,11182,11183,
11184,11185,11186,11187,11188,11189,11190,11191,11192,11193,11194,11195,
11196,11197,11198,11199,11200,11201,11202,11203,11204,11205,11206,11207,
11208,11209,11210,11211,11212,11213,11214,11215,11216,11217,11218,11219,
11220,11221,11222,11223,11224,11225,11226,11227,11228,11229,11230,11231,
11232,11233,11234,11235,11236,11237,11238,11239,11240,11241,11242,11243,
11244,11245,11246,11247,11248,11249,11250,11251,11252,11253,11254,11255,
11256,11257,11258,11259,11260,11261,11262,11263,11264,11265,11266,11267,
11268,11269,11270,11271,11272,11273,11274,11275,11276,11277,11278,11279,
11280,11281,11282,11283,11284,11285,11286,11287,11288,11289,11290,11291,
11292,11293,11294,11295,11296,11297,11298,11299,11300,11301,11302,11303,
11304,11305,11306,11307,11308,11309,11310,11311,11264,11265,11266,11267,
11268,11269,11270,11271,11272,11273,11274,11275,11276,11277,11278,11279,
11280,11281,11282,11283,11284,11285,11286,11287,11288,11289,11290,11291,
11292,11293,11294,11295,11296,11297,11298,11299,11300,11301,11302,11303,
11304,11305,11306,11307,11308,11309,11310,11359,11360,11360,11362,11363,
11364,570,574,11367,11367,11369,11369,11371,11371,11373,11374,11375,11376,
11377,11378,11378,11380,11381,11381,11383,11384,11385,11386,11387,11388,
11389,11390,11391,11392,11392,11394,11394,11396,11396,11398,11398,11400,
11400,11402,11402,11404,11404,11406,11406,11408,11408,11410,11410,11412,
11412,11414,11414,11416,11416,11418,11418,11420,11420,11422,11422,11424,
11424,11426,11426,11428,11428,11430,11430,11432,11432,11434,11434,11436,
11436,11438,11438,11440,11440,11442,11442,11444,11444,11446,11446,11448,
11448,11450,11450,11452,11452,11454,11454,11456,11456,11458,11458,11460,
11460,11462,11462,11464,11464,11466,11466,11468,11468,11470,11470,11472,
11472,11474,11474,11476,11476,11478,11478,11480,11480,11482,11482,11484,
11484,11486,11486,11488,11488,11490,11490,11492,11493,11494,11495,11496,
11497,11498,11499,11499,11501,11501,11503,11504,11505,11506,11506,11508,
11509,11510,11511,11512,11513,11514,11515,11516,11517,11518,11519,4256,
4257,4258,4259,4260,4261,4262,4263,4264,4265,4266,4267,4268,4269,4270,4271,
4272,4273,4274,4275,4276,4277,4278,4279,4280,4281,4282,4283,4284,4285,4286,
4287,4288,4289,4290,4291,4292,4293,11558,4295,11560,11561,11562,11563,
11564,4301,11566,11567,11568,11569,11570,11571,11572,11573,11574,11575,
11576,11577,11578,11579,11580,11581,11582,11583,11584,11585,11586,11587,
11588,11589,11590,11591,11592,11593,11594,11595,11596,11597,11598,11599,
11600,11601,11602,11603,11604,11605,11606,11607,11608,11609,11610,11611,
11612,11613,11614,11615,11616,11617,11618,11619,11620,11621,11622,11623,
11624,11625,11626,11627,11628,11629,11630,11631,11632,11633,11634,11635,
11636,11637,11638,11639,11640,11641,11642,11643,11644,11645,11646,11647,
11648,11649,11650,11651,11652,11653,11654,11655,11656,11657,11658,11659,
11660,11661,11662,11663,11664,11665,11666,11667,11668,11669,11670,11671,
11672,11673,11674,11675,11676,11677,11678,11679,11680,11681,11682,11683,
11684,11685,11686,11687,11688,11689,11690,11691,11692,11693,11694,11695,
11696,11697,11698,11699,11700,11701,11702,11703,11704,11705,11706,11707,
11708,11709,11710,11711,11712,11713,11714,11715,11716,11717,11718,11719,
11720,11721,11722,11723,11724,11725,11726,11727,11728,11729,11730,11731,
11732,11733,11734,11735,11736,11737,11738,11739,11740,11741,11742,11743,
11744,11745,11746,11747,11748,11749,11750,11751,11752,11753,11754,11755,
11756,11757,11758,11759,11760,11761,11762,11763,11764,11765,11766,11767,
11768,11769,11770,11771,11772,11773,11774,11775,11776,11777,11778,11779,
11780,11781,11782,11783,11784,11785,11786,11787,11788,11789,11790,11791,
11792,11793,11794,11795,11796,11797,11798,11799,11800,11801,11802,11803,
11804,11805,11806,11807,11808,11809,11810,11811,11812,11813,11814,11815,
11816,11817,11818,11819,11820,11821,11822,11823,11824,11825,11826,11827,
11828,11829,11830,11831,11832,11833,11834,11835,11836,11837,11838,11839,
11840,11841,11842,11843,11844,11845,11846,11847,11848,11849,11850,11851,
11852,11853,11854,11855,11856,11857,11858,11859,11860,11861,11862,11863,
11864,11865,11866,11867,11868,11869,11870,11871,11872,11873,11874,11875,
11876,11877,11878,11879,11880,11881,11882,11883,11884,11885,11886,11887,
11888,11889,11890,11891,11892,11893,11894,11895,11896,11897,11898,11899,
11900,11901,11902,11903,11904,11905,11906,11907,11908,11909,11910,11911,
11912,11913,11914,11915,11916,11917,11918,11919,11920,11921,11922,11923,
11924,11925,11926,11927,11928,11929,11930,11931,11932,11933,11934,11935,
11936,11937,11938,11939,11940,11941,11942,11943,11944,11945,11946,11947,
11948,11949,11950,11951,11952,11953,11954,11955,11956,11957,11958,11959,
11960,11961,11962,11963,11964,11965,11966,11967,11968,11969,11970,11971,
11972,11973,11974,11975,11976,11977,11978,11979,11980,11981,11982,11983,
11984,11985,11986,11987,11988,11989,11990,11991,11992,11993,11994,11995,
11996,11997,11998,11999,12000,12001,12002,12003,12004,12005,12006,12007,
12008,12009,12010,12011,12012,12013,12014,12015,12016,12017,12018,12019,
12020,12021,12022,12023,12024,12025,12026,12027,12028,12029,12030,12031,
12032,12033,12034,12035,12036,12037,12038,12039,12040,12041,12042,12043,
12044,12045,12046,12047,12048,12049,12050,12051,12052,12053,12054,12055,
12056,12057,12058,12059,12060,12061,12062,12063,12064,12065,12066,12067,
12068,12069,12070,12071,12072,12073,12074,12075,12076,12077,12078,12079,
12080,12081,12082,12083,12084,12085,12086,12087,12088,12089,12090,12091,
12092,12093,12094,12095,12096,12097,12098,12099,12100,12101,12102,12103,
12104,12105,12106,12107,12108,12109,12110,12111,12112,12113,12114,12115,
12116,12117,12118,12119,12120,12121,12122,12123,12124,12125,12126,12127,
12128,12129,12130,12131,12132,12133,12134,12135,12136,12137,12138,12139,
12140,12141,12142,12143,12144,12145,12146,12147,12148,12149,12150,12151,
12152,12153,12154,12155,12156,12157,12158,12159,12160,12161,12162,12163,
12164,12165,12166,12167,12168,12169,12170,12171,12172,12173,12174,12175,
12176,12177,12178,12179,12180,12181,12182,12183,12184,12185,12186,12187,
12188,12189,12190,12191,12192,12193,12194,12195,12196,12197,12198,12199,
12200,12201,12202,12203,12204,12205,12206,12207,12208,12209,12210,12211,
12212,12213,12214,12215,12216,12217,12218,12219,12220,12221,12222,12223,
12224,12225,12226,12227,12228,12229,12230,12231,12232,12233,12234,12235,
12236,12237,12238,12239,12240,12241,12242,12243,12244,12245,12246,12247,
12248,12249,12250,12251,12252,12253,12254,12255,12256,12257,12258,12259,
12260,12261,12262,12263,12264,12265,12266,12267,12268,12269,12270,12271,
12272,12273,12274,12275,12276,12277,12278,12279,12280,12281,12282,12283,
12284,12285,12286,12287,12288,12289,12290,12291,12292,12293,12294,12295,
12296,12297,12298,12299,12300,12301,12302,12303,12304,12305,12306,12307,
12308,12309,12310,12311,12312,12313,12314,12315,12316,12317,12318,12319,
12320,12321,12322,12323,12324,12325,12326,12327,12328,12329,12330,12331,
12332,12333,12334,12335,12336,12337,12338,12339,12340,12341,12342,12343,
12344,12345,12346,12347,12348,12349,12350,12351,12352,12353,12354,12355,
12356,12357,12358,12359,12360,12361,12362,12363,12364,12365,12366,12367,
12368,12369,12370,12371,12372,12373,12374,12375,12376,12377,12378,12379,
12380,12381,12382,12383,12384,12385,12386,12387,12388,12389,12390,12391,
12392,12393,12394,12395,12396,12397,12398,12399,12400,12401,12402,12403,
12404,12405,12406,12407,12408,12409,12410,12411,12412,12413,12414,12415,
12416,12417,12418,12419,12420,12421,12422,12423,12424,12425,12426,12427,
12428,12429,12430,12431,12432,12433,12434,12435,12436,12437,12438,12439,
12440,12441,12442,12443,12444,12445,12446,12447,12448,12449,12450,12451,
12452,12453,12454,12455,12456,12457,12458,12459,12460,12461,12462,12463,
12464,12465,12466,12467,12468,12469,12470,12471,12472,12473,12474,12475,
12476,12477,12478,12479,12480,12481,12482,12483,12484,12485,12486,12487,
12488,12489,12490,12491,12492,12493,12494,12495,12496,12497,12498,12499,
12500,12501,12502,12503,12504,12505,12506,12507,12508,12509,12510,12511,
12512,12513,12514,12515,12516,12517,12518,12519,12520,12521,12522,12523,
12524,12525,12526,12527,12528,12529,12530,12531,12532,12533,12534,12535,
12536,12537,12538,12539,12540,12541,12542,12543,12544,12545,12546,12547,
12548,12549,12550,12551,12552,12553,12554,12555,12556,12557,12558,12559,
12560,12561,12562,12563,12564,12565,12566,12567,12568,12569,12570,12571,
12572,12573,12574,12575,12576,12577,12578,12579,12580,12581,12582,12583,
12584,12585,12586,12587,12588,12589,12590,12591,12592,12593,12594,12595,
12596,12597,12598,12599,12600,12601,12602,12603,12604,12605,12606,12607,
12608,12609,12610,12611,12612,12613,12614,12615,12616,12617,12618,12619,
12620,12621,12622,12623,12624,12625,12626,12627,12628,12629,12630,12631,
12632,12633,12634,12635,12636,12637,12638,12639,12640,12641,12642,12643,
12644,12645,12646,12647,12648,12649,12650,12651,12652,12653,12654,12655,
12656,12657,12658,12659,12660,12661,12662,12663,12664,12665,12666,12667,
12668,12669,12670,12671,12672,12673,12674,12675,12676,12677,12678,12679,
12680,12681,12682,12683,12684,12685,12686,12687,12688,12689,12690,12691,
12692,12693,12694,12695,12696,12697,12698,12699,12700,12701,12702,12703,
12704,12705,12706,12707,12708,12709,12710,12711,12712,12713,12714,12715,
12716,12717,12718,12719,12720,12721,12722,12723,12724,12725,12726,12727,
12728,12729,12730,12731,12732,12733,12734,12735,12736,12737,12738,12739,
12740,12741,12742,12743,12744,12745,12746,12747,12748,12749,12750,12751,
12752,12753,12754,12755,12756,12757,12758,12759,12760,12761,12762,12763,
12764,12765,12766,12767,12768,12769,12770,12771,12772,12773,12774,12775,
12776,12777,12778,12779,12780,12781,12782,12783,12784,12785,12786,12787,
12788,12789,12790,12791,12792,12793,12794,12795,12796,12797,12798,12799,
12800,12801,12802,12803,12804,12805,12806,12807,12808,12809,12810,12811,
12812,12813,12814,12815,12816,12817,12818,12819,12820,12821,12822,12823,
12824,12825,12826,12827,12828,12829,12830,12831,12832,12833,12834,12835,
12836,12837,12838,12839,12840,12841,12842,12843,12844,12845,12846,12847,
12848,12849,12850,12851,12852,12853,12854,12855,12856,12857,12858,12859,
12860,12861,12862,12863,12864,12865,12866,12867,12868,12869,12870,12871,
12872,12873,12874,12875,12876,12877,12878,12879,12880,12881,12882,12883,
12884,12885,12886,12887,12888,12889,12890,12891,12892,12893,12894,12895,
12896,12897,12898,12899,12900,12901,12902,12903,12904,12905,12906,12907,
12908,12909,12910,12911,12912,12913,12914,12915,12916,12917,12918,12919,
12920,12921,12922,12923,12924,12925,12926,12927,12928,12929,12930,12931,
12932,12933,12934,12935,12936,12937,12938,12939,12940,12941,12942,12943,
12944,12945,12946,12947,12948,12949,12950,12951,12952,12953,12954,12955,
12956,12957,12958,12959,12960,12961,12962,12963,12964,12965,12966,12967,
12968,12969,12970,12971,12972,12973,12974,12975,12976,12977,12978,12979,
12980,12981,12982,12983,12984,12985,12986,12987,12988,12989,12990,12991,
12992,12993,12994,12995,12996,12997,12998,12999,13000,13001,13002,13003,
13004,13005,13006,13007,13008,13009,13010,13011,13012,13013,13014,13015,
13016,13017,13018,13019,13020,13021,13022,13023,13024,13025,13026,13027,
13028,13029,13030,13031,13032,13033,13034,13035,13036,13037,13038,13039,
13040,13041,13042,13043,13044,13045,13046,13047,13048,13049,13050,13051,
13052,13053,13054,13055,13056,13057,13058,13059,13060,13061,13062,13063,
13064,13065,13066,13067,13068,13069,13070,13071,13072,13073,13074,13075,
13076,13077,13078,13079,13080,13081,13082,13083,13084,13085,13086,13087,
13088,13089,13090,13091,13092,13093,13094,13095,13096,13097,13098,13099,
13100,13101,13102,13103,13104,13105,13106,13107,13108,13109,13110,13111,
13112,13113,13114,13115,13116,13117,13118,13119,13120,13121,13122,13123,
13124,13125,13126,13127,13128,13129,13130,13131,13132,13133,13134,13135,
13136,13137,13138,13139,13140,13141,13142,13143,13144,13145,13146,13147,
13148,13149,13150,13151,13152,13153,13154,13155,13156,13157,13158,13159,
13160,13161,13162,13163,13164,13165,13166,13167,13168,13169,13170,13171,
13172,13173,13174,13175,13176,13177,13178,13179,13180,13181,13182,13183,
13184,13185,13186,13187,13188,13189,13190,13191,13192,13193,13194,13195,
13196,13197,13198,13199,13200,13201,13202,13203,13204,13205,13206,13207,
13208,13209,13210,13211,13212,13213,13214,13215,13216,13217,13218,13219,
13220,13221,13222,13223,13224,13225,13226,13227,13228,13229,13230,13231,
13232,13233,13234,13235,13236,13237,13238,13239,13240,13241,13242,13243,
13244,13245,13246,13247,13248,13249,13250,13251,13252,13253,13254,13255,
13256,13257,13258,13259,13260,13261,13262,13263,13264,13265,13266,13267,
13268,13269,13270,13271,13272,13273,13274,13275,13276,13277,13278,13279,
13280,13281,13282,13283,13284,13285,13286,13287,13288,13289,13290,13291,
13292,13293,13294,13295,13296,13297,13298,13299,13300,13301,13302,13303,
13304,13305,13306,13307,13308,13309,13310,13311,13312,13313,13314,13315,
13316,13317,13318,13319,13320,13321,13322,13323,13324,13325,13326,13327,
13328,13329,13330,13331,13332,13333,13334,13335,13336,13337,13338,13339,
13340,13341,13342,13343,13344,13345,13346,13347,13348,13349,13350,13351,
13352,13353,13354,13355,13356,13357,13358,13359,13360,13361,13362,13363,
13364,13365,13366,13367,13368,13369,13370,13371,13372,13373,13374,13375,
13376,13377,13378,13379,13380,13381,13382,13383,13384,13385,13386,13387,
13388,13389,13390,13391,13392,13393,13394,13395,13396,13397,13398,13399,
13400,13401,13402,13403,13404,13405,13406,13407,13408,13409,13410,13411,
13412,13413,13414,13415,13416,13417,13418,13419,13420,13421,13422,13423,
13424,13425,13426,13427,13428,13429,13430,13431,13432,13433,13434,13435,
13436,13437,13438,13439,13440,13441,13442,13443,13444,13445,13446,13447,
13448,13449,13450,13451,13452,13453,13454,13455,13456,13457,13458,13459,
13460,13461,13462,13463,13464,13465,13466,13467,13468,13469,13470,13471,
13472,13473,13474,13475,13476,13477,13478,13479,13480,13481,13482,13483,
13484,13485,13486,13487,13488,13489,13490,13491,13492,13493,13494,13495,
13496,13497,13498,13499,13500,13501,13502,13503,13504,13505,13506,13507,
13508,13509,13510,13511,13512,13513,13514,13515,13516,13517,13518,13519,
13520,13521,13522,13523,13524,13525,13526,13527,13528,13529,13530,13531,
13532,13533,13534,13535,13536,13537,13538,13539,13540,13541,13542,13543,
13544,13545,13546,13547,13548,13549,13550,13551,13552,13553,13554,13555,
13556,13557,13558,13559,13560,13561,13562,13563,13564,13565,13566,13567,
13568,13569,13570,13571,13572,13573,13574,13575,13576,13577,13578,13579,
13580,13581,13582,13583,13584,13585,13586,13587,13588,13589,13590,13591,
13592,13593,13594,13595,13596,13597,13598,13599,13600,13601,13602,13603,
13604,13605,13606,13607,13608,13609,13610,13611,13612,13613,13614,13615,
13616,13617,13618,13619,13620,13621,13622,13623,13624,13625,13626,13627,
13628,13629,13630,13631,13632,13633,13634,13635,13636,13637,13638,13639,
13640,13641,13642,13643,13644,13645,13646,13647,13648,13649,13650,13651,
13652,13653,13654,13655,13656,13657,13658,13659,13660,13661,13662,13663,
13664,13665,13666,13667,13668,13669,13670,13671,13672,13673,13674,13675,
13676,13677,13678,13679,13680,13681,13682,13683,13684,13685,13686,13687,
13688,13689,13690,13691,13692,13693,13694,13695,13696,13697,13698,13699,
13700,13701,13702,13703,13704,13705,13706,13707,13708,13709,13710,13711,
13712,13713,13714,13715,13716,13717,13718,13719,13720,13721,13722,13723,
13724,13725,13726,13727,13728,13729,13730,13731,13732,13733,13734,13735,
13736,13737,13738,13739,13740,13741,13742,13743,13744,13745,13746,13747,
13748,13749,13750,13751,13752,13753,13754,13755,13756,13757,13758,13759,
13760,13761,13762,13763,13764,13765,13766,13767,13768,13769,13770,13771,
13772,13773,13774,13775,13776,13777,13778,13779,13780,13781,13782,13783,
13784,13785,13786,13787,13788,13789,13790,13791,13792,13793,13794,13795,
13796,13797,13798,13799,13800,13801,13802,13803,13804,13805,13806,13807,
13808,13809,13810,13811,13812,13813,13814,13815,13816,13817,13818,13819,
13820,13821,13822,13823,13824,13825,13826,13827,13828,13829,13830,13831,
13832,13833,13834,13835,13836,13837,13838,13839,13840,13841,13842,13843,
13844,13845,13846,13847,13848,13849,13850,13851,13852,13853,13854,13855,
13856,13857,13858,13859,13860,13861,13862,13863,13864,13865,13866,13867,
13868,13869,13870,13871,13872,13873,13874,13875,13876,13877,13878,13879,
13880,13881,13882,13883,13884,13885,13886,13887,13888,13889,13890,13891,
13892,13893,13894,13895,13896,13897,13898,13899,13900,13901,13902,13903,
13904,13905,13906,13907,13908,13909,13910,13911,13912,13913,13914,13915,
13916,13917,13918,13919,13920,13921,13922,13923,13924,13925,13926,13927,
13928,13929,13930,13931,13932,13933,13934,13935,13936,13937,13938,13939,
13940,13941,13942,13943,13944,13945,13946,13947,13948,13949,13950,13951,
13952,13953,13954,13955,13956,13957,13958,13959,13960,13961,13962,13963,
13964,13965,13966,13967,13968,13969,13970,13971,13972,13973,13974,13975,
13976,13977,13978,13979,13980,13981,13982,13983,13984,13985,13986,13987,
13988,13989,13990,13991,13992,13993,13994,13995,13996,13997,13998,13999,
14000,14001,14002,14003,14004,14005,14006,14007,14008,14009,14010,14011,
14012,14013,14014,14015,14016,14017,14018,14019,14020,14021,14022,14023,
14024,14025,14026,14027,14028,14029,14030,14031,14032,14033,14034,14035,
14036,14037,14038,14039,14040,14041,14042,14043,14044,14045,14046,14047,
14048,14049,14050,14051,14052,14053,14054,14055,14056,14057,14058,14059,
14060,14061,14062,14063,14064,14065,14066,14067,14068,14069,14070,14071,
14072,14073,14074,14075,14076,14077,14078,14079,14080,14081,14082,14083,
14084,14085,14086,14087,14088,14089,14090,14091,14092,14093,14094,14095,
14096,14097,14098,14099,14100,14101,14102,14103,14104,14105,14106,14107,
14108,14109,14110,14111,14112,14113,14114,14115,14116,14117,14118,14119,
14120,14121,14122,14123,14124,14125,14126,14127,14128,14129,14130,14131,
14132,14133,14134,14135,14136,14137,14138,14139,14140,14141,14142,14143,
14144,14145,14146,14147,14148,14149,14150,14151,14152,14153,14154,14155,
14156,14157,14158,14159,14160,14161,14162,14163,14164,14165,14166,14167,
14168,14169,14170,14171,14172,14173,14174,14175,14176,14177,14178,14179,
14180,14181,14182,14183,14184,14185,14186,14187,14188,14189,14190,14191,
14192,14193,14194,14195,14196,14197,14198,14199,14200,14201,14202,14203,
14204,14205,14206,14207,14208,14209,14210,14211,14212,14213,14214,14215,
14216,14217,14218,14219,14220,14221,14222,14223,14224,14225,14226,14227,
14228,14229,14230,14231,14232,14233,14234,14235,14236,14237,14238,14239,
14240,14241,14242,14243,14244,14245,14246,14247,14248,14249,14250,14251,
14252,14253,14254,14255,14256,14257,14258,14259,14260,14261,14262,14263,
14264,14265,14266,14267,14268,14269,14270,14271,14272,14273,14274,14275,
14276,14277,14278,14279,14280,14281,14282,14283,14284,14285,14286,14287,
14288,14289,14290,14291,14292,14293,14294,14295,14296,14297,14298,14299,
14300,14301,14302,14303,14304,14305,14306,14307,14308,14309,14310,14311,
14312,14313,14314,14315,14316,14317,14318,14319,14320,14321,14322,14323,
14324,14325,14326,14327,14328,14329,14330,14331,14332,14333,14334,14335,
14336,14337,14338,14339,14340,14341,14342,14343,14344,14345,14346,14347,
14348,14349,14350,14351,14352,14353,14354,14355,14356,14357,14358,14359,
14360,14361,14362,14363,14364,14365,14366,14367,14368,14369,14370,14371,
14372,14373,14374,14375,14376,14377,14378,14379,14380,14381,14382,14383,
14384,14385,14386,14387,14388,14389,14390,14391,14392,14393,14394,14395,
14396,14397,14398,14399,14400,14401,14402,14403,14404,14405,14406,14407,
14408,14409,14410,14411,14412,14413,14414,14415,14416,14417,14418,14419,
14420,14421,14422,14423,14424,14425,14426,14427,14428,14429,14430,14431,
14432,14433,14434,14435,14436,14437,14438,14439,14440,14441,14442,14443,
14444,14445,14446,14447,14448,14449,14450,14451,14452,14453,14454,14455,
14456,14457,14458,14459,14460,14461,14462,14463,14464,14465,14466,14467,
14468,14469,14470,14471,14472,14473,14474,14475,14476,14477,14478,14479,
14480,14481,14482,14483,14484,14485,14486,14487,14488,14489,14490,14491,
14492,14493,14494,14495,14496,14497,14498,14499,14500,14501,14502,14503,
14504,14505,14506,14507,14508,14509,14510,14511,14512,14513,14514,14515,
14516,14517,14518,14519,14520,14521,14522,14523,14524,14525,14526,14527,
14528,14529,14530,14531,14532,14533,14534,14535,14536,14537,14538,14539,
14540,14541,14542,14543,14544,14545,14546,14547,14548,14549,14550,14551,
14552,14553,14554,14555,14556,14557,14558,14559,14560,14561,14562,14563,
14564,14565,14566,14567,14568,14569,14570,14571,14572,14573,14574,14575,
14576,14577,14578,14579,14580,14581,14582,14583,14584,14585,14586,14587,
14588,14589,14590,14591,14592,14593,14594,14595,14596,14597,14598,14599,
14600,14601,14602,14603,14604,14605,14606,14607,14608,14609,14610,14611,
14612,14613,14614,14615,14616,14617,14618,14619,14620,14621,14622,14623,
14624,14625,14626,14627,14628,14629,14630,14631,14632,14633,14634,14635,
14636,14637,14638,14639,14640,14641,14642,14643,14644,14645,14646,14647,
14648,14649,14650,14651,14652,14653,14654,14655,14656,14657,14658,14659,
14660,14661,14662,14663,14664,14665,14666,14667,14668,14669,14670,14671,
14672,14673,14674,14675,14676,14677,14678,14679,14680,14681,14682,14683,
14684,14685,14686,14687,14688,14689,14690,14691,14692,14693,14694,14695,
14696,14697,14698,14699,14700,14701,14702,14703,14704,14705,14706,14707,
14708,14709,14710,14711,14712,14713,14714,14715,14716,14717,14718,14719,
14720,14721,14722,14723,14724,14725,14726,14727,14728,14729,14730,14731,
14732,14733,14734,14735,14736,14737,14738,14739,14740,14741,14742,14743,
14744,14745,14746,14747,14748,14749,14750,14751,14752,14753,14754,14755,
14756,14757,14758,14759,14760,14761,14762,14763,14764,14765,14766,14767,
14768,14769,14770,14771,14772,14773,14774,14775,14776,14777,14778,14779,
14780,14781,14782,14783,14784,14785,14786,14787,14788,14789,14790,14791,
14792,14793,14794,14795,14796,14797,14798,14799,14800,14801,14802,14803,
14804,14805,14806,14807,14808,14809,14810,14811,14812,14813,14814,14815,
14816,14817,14818,14819,14820,14821,14822,14823,14824,14825,14826,14827,
14828,14829,14830,14831,14832,14833,14834,14835,14836,14837,14838,14839,
14840,14841,14842,14843,14844,14845,14846,14847,14848,14849,14850,14851,
14852,14853,14854,14855,14856,14857,14858,14859,14860,14861,14862,14863,
14864,14865,14866,14867,14868,14869,14870,14871,14872,14873,14874,14875,
14876,14877,14878,14879,14880,14881,14882,14883,14884,14885,14886,14887,
14888,14889,14890,14891,14892,14893,14894,14895,14896,14897,14898,14899,
14900,14901,14902,14903,14904,14905,14906,14907,14908,14909,14910,14911,
14912,14913,14914,14915,14916,14917,14918,14919,14920,14921,14922,14923,
14924,14925,14926,14927,14928,14929,14930,14931,14932,14933,14934,14935,
14936,14937,14938,14939,14940,14941,14942,14943,14944,14945,14946,14947,
14948,14949,14950,14951,14952,14953,14954,14955,14956,14957,14958,14959,
14960,14961,14962,14963,14964,14965,14966,14967,14968,14969,14970,14971,
14972,14973,14974,14975,14976,14977,14978,14979,14980,14981,14982,14983,
14984,14985,14986,14987,14988,14989,14990,14991,14992,14993,14994,14995,
14996,14997,14998,14999,15000,15001,15002,15003,15004,15005,15006,15007,
15008,15009,15010,15011,15012,15013,15014,15015,15016,15017,15018,15019,
15020,15021,15022,15023,15024,15025,15026,15027,15028,15029,15030,15031,
15032,15033,15034,15035,15036,15037,15038,15039,15040,15041,15042,15043,
15044,15045,15046,15047,15048,15049,15050,15051,15052,15053,15054,15055,
15056,15057,15058,15059,15060,15061,15062,15063,15064,15065,15066,15067,
15068,15069,15070,15071,15072,15073,15074,15075,15076,15077,15078,15079,
15080,15081,15082,15083,15084,15085,15086,15087,15088,15089,15090,15091,
15092,15093,15094,15095,15096,15097,15098,15099,15100,15101,15102,15103,
15104,15105,15106,15107,15108,15109,15110,15111,15112,15113,15114,15115,
15116,15117,15118,15119,15120,15121,15122,15123,15124,15125,15126,15127,
15128,15129,15130,15131,15132,15133,15134,15135,15136,15137,15138,15139,
15140,15141,15142,15143,15144,15145,15146,15147,15148,15149,15150,15151,
15152,15153,15154,15155,15156,15157,15158,15159,15160,15161,15162,15163,
15164,15165,15166,15167,15168,15169,15170,15171,15172,15173,15174,15175,
15176,15177,15178,15179,15180,15181,15182,15183,15184,15185,15186,15187,
15188,15189,15190,15191,15192,15193,15194,15195,15196,15197,15198,15199,
15200,15201,15202,15203,15204,15205,15206,15207,15208,15209,15210,15211,
15212,15213,15214,15215,15216,15217,15218,15219,15220,15221,15222,15223,
15224,15225,15226,15227,15228,15229,15230,15231,15232,15233,15234,15235,
15236,15237,15238,15239,15240,15241,15242,15243,15244,15245,15246,15247,
15248,15249,15250,15251,15252,15253,15254,15255,15256,15257,15258,15259,
15260,15261,15262,15263,15264,15265,15266,15267,15268,15269,15270,15271,
15272,15273,15274,15275,15276,15277,15278,15279,15280,15281,15282,15283,
15284,15285,15286,15287,15288,15289,15290,15291,15292,15293,15294,15295,
15296,15297,15298,15299,15300,15301,15302,15303,15304,15305,15306,15307,
15308,15309,15310,15311,15312,15313,15314,15315,15316,15317,15318,15319,
15320,15321,15322,15323,15324,15325,15326,15327,15328,15329,15330,15331,
15332,15333,15334,15335,15336,15337,15338,15339,15340,15341,15342,15343,
15344,15345,15346,15347,15348,15349,15350,15351,15352,15353,15354,15355,
15356,15357,15358,15359,15360,15361,15362,15363,15364,15365,15366,15367,
15368,15369,15370,15371,15372,15373,15374,15375,15376,15377,15378,15379,
15380,15381,15382,15383,15384,15385,15386,15387,15388,15389,15390,15391,
15392,15393,15394,15395,15396,15397,15398,15399,15400,15401,15402,15403,
15404,15405,15406,15407,15408,15409,15410,15411,15412,15413,15414,15415,
15416,15417,15418,15419,15420,15421,15422,15423,15424,15425,15426,15427,
15428,15429,15430,15431,15432,15433,15434,15435,15436,15437,15438,15439,
15440,15441,15442,15443,15444,15445,15446,15447,15448,15449,15450,15451,
15452,15453,15454,15455,15456,15457,15458,15459,15460,15461,15462,15463,
15464,15465,15466,15467,15468,15469,15470,15471,15472,15473,15474,15475,
15476,15477,15478,15479,15480,15481,15482,15483,15484,15485,15486,15487,
15488,15489,15490,15491,15492,15493,15494,15495,15496,15497,15498,15499,
15500,15501,15502,15503,15504,15505,15506,15507,15508,15509,15510,15511,
15512,15513,15514,15515,15516,15517,15518,15519,15520,15521,15522,15523,
15524,15525,15526,15527,15528,15529,15530,15531,15532,15533,15534,15535,
15536,15537,15538,15539,15540,15541,15542,15543,15544,15545,15546,15547,
15548,15549,15550,15551,15552,15553,15554,15555,15556,15557,15558,15559,
15560,15561,15562,15563,15564,15565,15566,15567,15568,15569,15570,15571,
15572,15573,15574,15575,15576,15577,15578,15579,15580,15581,15582,15583,
15584,15585,15586,15587,15588,15589,15590,15591,15592,15593,15594,15595,
15596,15597,15598,15599,15600,15601,15602,15603,15604,15605,15606,15607,
15608,15609,15610,15611,15612,15613,15614,15615,15616,15617,15618,15619,
15620,15621,15622,15623,15624,15625,15626,15627,15628,15629,15630,15631,
15632,15633,15634,15635,15636,15637,15638,15639,15640,15641,15642,15643,
15644,15645,15646,15647,15648,15649,15650,15651,15652,15653,15654,15655,
15656,15657,15658,15659,15660,15661,15662,15663,15664,15665,15666,15667,
15668,15669,15670,15671,15672,15673,15674,15675,15676,15677,15678,15679,
15680,15681,15682,15683,15684,15685,15686,15687,15688,15689,15690,15691,
15692,15693,15694,15695,15696,15697,15698,15699,15700,15701,15702,15703,
15704,15705,15706,15707,15708,15709,15710,15711,15712,15713,15714,15715,
15716,15717,15718,15719,15720,15721,15722,15723,15724,15725,15726,15727,
15728,15729,15730,15731,15732,15733,15734,15735,15736,15737,15738,15739,
15740,15741,15742,15743,15744,15745,15746,15747,15748,15749,15750,15751,
15752,15753,15754,15755,15756,15757,15758,15759,15760,15761,15762,15763,
15764,15765,15766,15767,15768,15769,15770,15771,15772,15773,15774,15775,
15776,15777,15778,15779,15780,15781,15782,15783,15784,15785,15786,15787,
15788,15789,15790,15791,15792,15793,15794,15795,15796,15797,15798,15799,
15800,15801,15802,15803,15804,15805,15806,15807,15808,15809,15810,15811,
15812,15813,15814,15815,15816,15817,15818,15819,15820,15821,15822,15823,
15824,15825,15826,15827,15828,15829,15830,15831,15832,15833,15834,15835,
15836,15837,15838,15839,15840,15841,15842,15843,15844,15845,15846,15847,
15848,15849,15850,15851,15852,15853,15854,15855,15856,15857,15858,15859,
15860,15861,15862,15863,15864,15865,15866,15867,15868,15869,15870,15871,
15872,15873,15874,15875,15876,15877,15878,15879,15880,15881,15882,15883,
15884,15885,15886,15887,15888,15889,15890,15891,15892,15893,15894,15895,
15896,15897,15898,15899,15900,15901,15902,15903,15904,15905,15906,15907,
15908,15909,15910,15911,15912,15913,15914,15915,15916,15917,15918,15919,
15920,15921,15922,15923,15924,15925,15926,15927,15928,15929,15930,15931,
15932,15933,15934,15935,15936,15937,15938,15939,15940,15941,15942,15943,
15944,15945,15946,15947,15948,15949,15950,15951,15952,15953,15954,15955,
15956,15957,15958,15959,15960,15961,15962,15963,15964,15965,15966,15967,
15968,15969,15970,15971,15972,15973,15974,15975,15976,15977,15978,15979,
15980,15981,15982,15983,15984,15985,15986,15987,15988,15989,15990,15991,
15992,15993,15994,15995,15996,15997,15998,15999,16000,16001,16002,16003,
16004,16005,16006,16007,16008,16009,16010,16011,16012,16013,16014,16015,
16016,16017,16018,16019,16020,16021,16022,16023,16024,16025,16026,16027,
16028,16029,16030,16031,16032,16033,16034,16035,16036,16037,16038,16039,
16040,16041,16042,16043,16044,16045,16046,16047,16048,16049,16050,16051,
16052,16053,16054,16055,16056,16057,16058,16059,16060,16061,16062,16063,
16064,16065,16066,16067,16068,16069,16070,16071,16072,16073,16074,16075,
16076,16077,16078,16079,16080,16081,16082,16083,16084,16085,16086,16087,
16088,16089,16090,16091,16092,16093,16094,16095,16096,16097,16098,16099,
16100,16101,16102,16103,16104,16105,16106,16107,16108,16109,16110,16111,
16112,16113,16114,16115,16116,16117,16118,16119,16120,16121,16122,16123,
16124,16125,16126,16127,16128,16129,16130,16131,16132,16133,16134,16135,
16136,16137,16138,16139,16140,16141,16142,16143,16144,16145,16146,16147,
16148,16149,16150,16151,16152,16153,16154,16155,16156,16157,16158,16159,
16160,16161,16162,16163,16164,16165,16166,16167,16168,16169,16170,16171,
16172,16173,16174,16175,16176,16177,16178,16179,16180,16181,16182,16183,
16184,16185,16186,16187,16188,16189,16190,16191,16192,16193,16194,16195,
16196,16197,16198,16199,16200,16201,16202,16203,16204,16205,16206,16207,
16208,16209,16210,16211,16212,16213,16214,16215,16216,16217,16218,16219,
16220,16221,16222,16223,16224,16225,16226,16227,16228,16229,16230,16231,
16232,16233,16234,16235,16236,16237,16238,16239,16240,16241,16242,16243,
16244,16245,16246,16247,16248,16249,16250,16251,16252,16253,16254,16255,
16256,16257,16258,16259,16260,16261,16262,16263,16264,16265,16266,16267,
16268,16269,16270,16271,16272,16273,16274,16275,16276,16277,16278,16279,
16280,16281,16282,16283,16284,16285,16286,16287,16288,16289,16290,16291,
16292,16293,16294,16295,16296,16297,16298,16299,16300,16301,16302,16303,
16304,16305,16306,16307,16308,16309,16310,16311,16312,16313,16314,16315,
16316,16317,16318,16319,16320,16321,16322,16323,16324,16325,16326,16327,
16328,16329,16330,16331,16332,16333,16334,16335,16336,16337,16338,16339,
16340,16341,16342,16343,16344,16345,16346,16347,16348,16349,16350,16351,
16352,16353,16354,16355,16356,16357,16358,16359,16360,16361,16362,16363,
16364,16365,16366,16367,16368,16369,16370,16371,16372,16373,16374,16375,
16376,16377,16378,16379,16380,16381,16382,16383,16384,16385,16386,16387,
16388,16389,16390,16391,16392,16393,16394,16395,16396,16397,16398,16399,
16400,16401,16402,16403,16404,16405,16406,16407,16408,16409,16410,16411,
16412,16413,16414,16415,16416,16417,16418,16419,16420,16421,16422,16423,
16424,16425,16426,16427,16428,16429,16430,16431,16432,16433,16434,16435,
16436,16437,16438,16439,16440,16441,16442,16443,16444,16445,16446,16447,
16448,16449,16450,16451,16452,16453,16454,16455,16456,16457,16458,16459,
16460,16461,16462,16463,16464,16465,16466,16467,16468,16469,16470,16471,
16472,16473,16474,16475,16476,16477,16478,16479,16480,16481,16482,16483,
16484,16485,16486,16487,16488,16489,16490,16491,16492,16493,16494,16495,
16496,16497,16498,16499,16500,16501,16502,16503,16504,16505,16506,16507,
16508,16509,16510,16511,16512,16513,16514,16515,16516,16517,16518,16519,
16520,16521,16522,16523,16524,16525,16526,16527,16528,16529,16530,16531,
16532,16533,16534,16535,16536,16537,16538,16539,16540,16541,16542,16543,
16544,16545,16546,16547,16548,16549,16550,16551,16552,16553,16554,16555,
16556,16557,16558,16559,16560,16561,16562,16563,16564,16565,16566,16567,
16568,16569,16570,16571,16572,16573,16574,16575,16576,16577,16578,16579,
16580,16581,16582,16583,16584,16585,16586,16587,16588,16589,16590,16591,
16592,16593,16594,16595,16596,16597,16598,16599,16600,16601,16602,16603,
16604,16605,16606,16607,16608,16609,16610,16611,16612,16613,16614,16615,
16616,16617,16618,16619,16620,16621,16622,16623,16624,16625,16626,16627,
16628,16629,16630,16631,16632,16633,16634,16635,16636,16637,16638,16639,
16640,16641,16642,16643,16644,16645,16646,16647,16648,16649,16650,16651,
16652,16653,16654,16655,16656,16657,16658,16659,16660,16661,16662,16663,
16664,16665,16666,16667,16668,16669,16670,16671,16672,16673,16674,16675,
16676,16677,16678,16679,16680,16681,16682,16683,16684,16685,16686,16687,
16688,16689,16690,16691,16692,16693,16694,16695,16696,16697,16698,16699,
16700,16701,16702,16703,16704,16705,16706,16707,16708,16709,16710,16711,
16712,16713,16714,16715,16716,16717,16718,16719,16720,16721,16722,16723,
16724,16725,16726,16727,16728,16729,16730,16731,16732,16733,16734,16735,
16736,16737,16738,16739,16740,16741,16742,16743,16744,16745,16746,16747,
16748,16749,16750,16751,16752,16753,16754,16755,16756,16757,16758,16759,
16760,16761,16762,16763,16764,16765,16766,16767,16768,16769,16770,16771,
16772,16773,16774,16775,16776,16777,16778,16779,16780,16781,16782,16783,
16784,16785,16786,16787,16788,16789,16790,16791,16792,16793,16794,16795,
16796,16797,16798,16799,16800,16801,16802,16803,16804,16805,16806,16807,
16808,16809,16810,16811,16812,16813,16814,16815,16816,16817,16818,16819,
16820,16821,16822,16823,16824,16825,16826,16827,16828,16829,16830,16831,
16832,16833,16834,16835,16836,16837,16838,16839,16840,16841,16842,16843,
16844,16845,16846,16847,16848,16849,16850,16851,16852,16853,16854,16855,
16856,16857,16858,16859,16860,16861,16862,16863,16864,16865,16866,16867,
16868,16869,16870,16871,16872,16873,16874,16875,16876,16877,16878,16879,
16880,16881,16882,16883,16884,16885,16886,16887,16888,16889,16890,16891,
16892,16893,16894,16895,16896,16897,16898,16899,16900,16901,16902,16903,
16904,16905,16906,16907,16908,16909,16910,16911,16912,16913,16914,16915,
16916,16917,16918,16919,16920,16921,16922,16923,16924,16925,16926,16927,
16928,16929,16930,16931,16932,16933,16934,16935,16936,16937,16938,16939,
16940,16941,16942,16943,16944,16945,16946,16947,16948,16949,16950,16951,
16952,16953,16954,16955,16956,16957,16958,16959,16960,16961,16962,16963,
16964,16965,16966,16967,16968,16969,16970,16971,16972,16973,16974,16975,
16976,16977,16978,16979,16980,16981,16982,16983,16984,16985,16986,16987,
16988,16989,16990,16991,16992,16993,16994,16995,16996,16997,16998,16999,
17000,17001,17002,17003,17004,17005,17006,17007,17008,17009,17010,17011,
17012,17013,17014,17015,17016,17017,17018,17019,17020,17021,17022,17023,
17024,17025,17026,17027,17028,17029,17030,17031,17032,17033,17034,17035,
17036,17037,17038,17039,17040,17041,17042,17043,17044,17045,17046,17047,
17048,17049,17050,17051,17052,17053,17054,17055,17056,17057,17058,17059,
17060,17061,17062,17063,17064,17065,17066,17067,17068,17069,17070,17071,
17072,17073,17074,17075,17076,17077,17078,17079,17080,17081,17082,17083,
17084,17085,17086,17087,17088,17089,17090,17091,17092,17093,17094,17095,
17096,17097,17098,17099,17100,17101,17102,17103,17104,17105,17106,17107,
17108,17109,17110,17111,17112,17113,17114,17115,17116,17117,17118,17119,
17120,17121,17122,17123,17124,17125,17126,17127,17128,17129,17130,17131,
17132,17133,17134,17135,17136,17137,17138,17139,17140,17141,17142,17143,
17144,17145,17146,17147,17148,17149,17150,17151,17152,17153,17154,17155,
17156,17157,17158,17159,17160,17161,17162,17163,17164,17165,17166,17167,
17168,17169,17170,17171,17172,17173,17174,17175,17176,17177,17178,17179,
17180,17181,17182,17183,17184,17185,17186,17187,17188,17189,17190,17191,
17192,17193,17194,17195,17196,17197,17198,17199,17200,17201,17202,17203,
17204,17205,17206,17207,17208,17209,17210,17211,17212,17213,17214,17215,
17216,17217,17218,17219,17220,17221,17222,17223,17224,17225,17226,17227,
17228,17229,17230,17231,17232,17233,17234,17235,17236,17237,17238,17239,
17240,17241,17242,17243,17244,17245,17246,17247,17248,17249,17250,17251,
17252,17253,17254,17255,17256,17257,17258,17259,17260,17261,17262,17263,
17264,17265,17266,17267,17268,17269,17270,17271,17272,17273,17274,17275,
17276,17277,17278,17279,17280,17281,17282,17283,17284,17285,17286,17287,
17288,17289,17290,17291,17292,17293,17294,17295,17296,17297,17298,17299,
17300,17301,17302,17303,17304,17305,17306,17307,17308,17309,17310,17311,
17312,17313,17314,17315,17316,17317,17318,17319,17320,17321,17322,17323,
17324,17325,17326,17327,17328,17329,17330,17331,17332,17333,17334,17335,
17336,17337,17338,17339,17340,17341,17342,17343,17344,17345,17346,17347,
17348,17349,17350,17351,17352,17353,17354,17355,17356,17357,17358,17359,
17360,17361,17362,17363,17364,17365,17366,17367,17368,17369,17370,17371,
17372,17373,17374,17375,17376,17377,17378,17379,17380,17381,17382,17383,
17384,17385,17386,17387,17388,17389,17390,17391,17392,17393,17394,17395,
17396,17397,17398,17399,17400,17401,17402,17403,17404,17405,17406,17407,
17408,17409,17410,17411,17412,17413,17414,17415,17416,17417,17418,17419,
17420,17421,17422,17423,17424,17425,17426,17427,17428,17429,17430,17431,
17432,17433,17434,17435,17436,17437,17438,17439,17440,17441,17442,17443,
17444,17445,17446,17447,17448,17449,17450,17451,17452,17453,17454,17455,
17456,17457,17458,17459,17460,17461,17462,17463,17464,17465,17466,17467,
17468,17469,17470,17471,17472,17473,17474,17475,17476,17477,17478,17479,
17480,17481,17482,17483,17484,17485,17486,17487,17488,17489,17490,17491,
17492,17493,17494,17495,17496,17497,17498,17499,17500,17501,17502,17503,
17504,17505,17506,17507,17508,17509,17510,17511,17512,17513,17514,17515,
17516,17517,17518,17519,17520,17521,17522,17523,17524,17525,17526,17527,
17528,17529,17530,17531,17532,17533,17534,17535,17536,17537,17538,17539,
17540,17541,17542,17543,17544,17545,17546,17547,17548,17549,17550,17551,
17552,17553,17554,17555,17556,17557,17558,17559,17560,17561,17562,17563,
17564,17565,17566,17567,17568,17569,17570,17571,17572,17573,17574,17575,
17576,17577,17578,17579,17580,17581,17582,17583,17584,17585,17586,17587,
17588,17589,17590,17591,17592,17593,17594,17595,17596,17597,17598,17599,
17600,17601,17602,17603,17604,17605,17606,17607,17608,17609,17610,17611,
17612,17613,17614,17615,17616,17617,17618,17619,17620,17621,17622,17623,
17624,17625,17626,17627,17628,17629,17630,17631,17632,17633,17634,17635,
17636,17637,17638,17639,17640,17641,17642,17643,17644,17645,17646,17647,
17648,17649,17650,17651,17652,17653,17654,17655,17656,17657,17658,17659,
17660,17661,17662,17663,17664,17665,17666,17667,17668,17669,17670,17671,
17672,17673,17674,17675,17676,17677,17678,17679,17680,17681,17682,17683,
17684,17685,17686,17687,17688,17689,17690,17691,17692,17693,17694,17695,
17696,17697,17698,17699,17700,17701,17702,17703,17704,17705,17706,17707,
17708,17709,17710,17711,17712,17713,17714,17715,17716,17717,17718,17719,
17720,17721,17722,17723,17724,17725,17726,17727,17728,17729,17730,17731,
17732,17733,17734,17735,17736,17737,17738,17739,17740,17741,17742,17743,
17744,17745,17746,17747,17748,17749,17750,17751,17752,17753,17754,17755,
17756,17757,17758,17759,17760,17761,17762,17763,17764,17765,17766,17767,
17768,17769,17770,17771,17772,17773,17774,17775,17776,17777,17778,17779,
17780,17781,17782,17783,17784,17785,17786,17787,17788,17789,17790,17791,
17792,17793,17794,17795,17796,17797,17798,17799,17800,17801,17802,17803,
17804,17805,17806,17807,17808,17809,17810,17811,17812,17813,17814,17815,
17816,17817,17818,17819,17820,17821,17822,17823,17824,17825,17826,17827,
17828,17829,17830,17831,17832,17833,17834,17835,17836,17837,17838,17839,
17840,17841,17842,17843,17844,17845,17846,17847,17848,17849,17850,17851,
17852,17853,17854,17855,17856,17857,17858,17859,17860,17861,17862,17863,
17864,17865,17866,17867,17868,17869,17870,17871,17872,17873,17874,17875,
17876,17877,17878,17879,17880,17881,17882,17883,17884,17885,17886,17887,
17888,17889,17890,17891,17892,17893,17894,17895,17896,17897,17898,17899,
17900,17901,17902,17903,17904,17905,17906,17907,17908,17909,17910,17911,
17912,17913,17914,17915,17916,17917,17918,17919,17920,17921,17922,17923,
17924,17925,17926,17927,17928,17929,17930,17931,17932,17933,17934,17935,
17936,17937,17938,17939,17940,17941,17942,17943,17944,17945,17946,17947,
17948,17949,17950,17951,17952,17953,17954,17955,17956,17957,17958,17959,
17960,17961,17962,17963,17964,17965,17966,17967,17968,17969,17970,17971,
17972,17973,17974,17975,17976,17977,17978,17979,17980,17981,17982,17983,
17984,17985,17986,17987,17988,17989,17990,17991,17992,17993,17994,17995,
17996,17997,17998,17999,18000,18001,18002,18003,18004,18005,18006,18007,
18008,18009,18010,18011,18012,18013,18014,18015,18016,18017,18018,18019,
18020,18021,18022,18023,18024,18025,18026,18027,18028,18029,18030,18031,
18032,18033,18034,18035,18036,18037,18038,18039,18040,18041,18042,18043,
18044,18045,18046,18047,18048,18049,18050,18051,18052,18053,18054,18055,
18056,18057,18058,18059,18060,18061,18062,18063,18064,18065,18066,18067,
18068,18069,18070,18071,18072,18073,18074,18075,18076,18077,18078,18079,
18080,18081,18082,18083,18084,18085,18086,18087,18088,18089,18090,18091,
18092,18093,18094,18095,18096,18097,18098,18099,18100,18101,18102,18103,
18104,18105,18106,18107,18108,18109,18110,18111,18112,18113,18114,18115,
18116,18117,18118,18119,18120,18121,18122,18123,18124,18125,18126,18127,
18128,18129,18130,18131,18132,18133,18134,18135,18136,18137,18138,18139,
18140,18141,18142,18143,18144,18145,18146,18147,18148,18149,18150,18151,
18152,18153,18154,18155,18156,18157,18158,18159,18160,18161,18162,18163,
18164,18165,18166,18167,18168,18169,18170,18171,18172,18173,18174,18175,
18176,18177,18178,18179,18180,18181,18182,18183,18184,18185,18186,18187,
18188,18189,18190,18191,18192,18193,18194,18195,18196,18197,18198,18199,
18200,18201,18202,18203,18204,18205,18206,18207,18208,18209,18210,18211,
18212,18213,18214,18215,18216,18217,18218,18219,18220,18221,18222,18223,
18224,18225,18226,18227,18228,18229,18230,18231,18232,18233,18234,18235,
18236,18237,18238,18239,18240,18241,18242,18243,18244,18245,18246,18247,
18248,18249,18250,18251,18252,18253,18254,18255,18256,18257,18258,18259,
18260,18261,18262,18263,18264,18265,18266,18267,18268,18269,18270,18271,
18272,18273,18274,18275,18276,18277,18278,18279,18280,18281,18282,18283,
18284,18285,18286,18287,18288,18289,18290,18291,18292,18293,18294,18295,
18296,18297,18298,18299,18300,18301,18302,18303,18304,18305,18306,18307,
18308,18309,18310,18311,18312,18313,18314,18315,18316,18317,18318,18319,
18320,18321,18322,18323,18324,18325,18326,18327,18328,18329,18330,18331,
18332,18333,18334,18335,18336,18337,18338,18339,18340,18341,18342,18343,
18344,18345,18346,18347,18348,18349,18350,18351,18352,18353,18354,18355,
18356,18357,18358,18359,18360,18361,18362,18363,18364,18365,18366,18367,
18368,18369,18370,18371,18372,18373,18374,18375,18376,18377,18378,18379,
18380,18381,18382,18383,18384,18385,18386,18387,18388,18389,18390,18391,
18392,18393,18394,18395,18396,18397,18398,18399,18400,18401,18402,18403,
18404,18405,18406,18407,18408,18409,18410,18411,18412,18413,18414,18415,
18416,18417,18418,18419,18420,18421,18422,18423,18424,18425,18426,18427,
18428,18429,18430,18431,18432,18433,18434,18435,18436,18437,18438,18439,
18440,18441,18442,18443,18444,18445,18446,18447,18448,18449,18450,18451,
18452,18453,18454,18455,18456,18457,18458,18459,18460,18461,18462,18463,
18464,18465,18466,18467,18468,18469,18470,18471,18472,18473,18474,18475,
18476,18477,18478,18479,18480,18481,18482,18483,18484,18485,18486,18487,
18488,18489,18490,18491,18492,18493,18494,18495,18496,18497,18498,18499,
18500,18501,18502,18503,18504,18505,18506,18507,18508,18509,18510,18511,
18512,18513,18514,18515,18516,18517,18518,18519,18520,18521,18522,18523,
18524,18525,18526,18527,18528,18529,18530,18531,18532,18533,18534,18535,
18536,18537,18538,18539,18540,18541,18542,18543,18544,18545,18546,18547,
18548,18549,18550,18551,18552,18553,18554,18555,18556,18557,18558,18559,
18560,18561,18562,18563,18564,18565,18566,18567,18568,18569,18570,18571,
18572,18573,18574,18575,18576,18577,18578,18579,18580,18581,18582,18583,
18584,18585,18586,18587,18588,18589,18590,18591,18592,18593,18594,18595,
18596,18597,18598,18599,18600,18601,18602,18603,18604,18605,18606,18607,
18608,18609,18610,18611,18612,18613,18614,18615,18616,18617,18618,18619,
18620,18621,18622,18623,18624,18625,18626,18627,18628,18629,18630,18631,
18632,18633,18634,18635,18636,18637,18638,18639,18640,18641,18642,18643,
18644,18645,18646,18647,18648,18649,18650,18651,18652,18653,18654,18655,
18656,18657,18658,18659,18660,18661,18662,18663,18664,18665,18666,18667,
18668,18669,18670,18671,18672,18673,18674,18675,18676,18677,18678,18679,
18680,18681,18682,18683,18684,18685,18686,18687,18688,18689,18690,18691,
18692,18693,18694,18695,18696,18697,18698,18699,18700,18701,18702,18703,
18704,18705,18706,18707,18708,18709,18710,18711,18712,18713,18714,18715,
18716,18717,18718,18719,18720,18721,18722,18723,18724,18725,18726,18727,
18728,18729,18730,18731,18732,18733,18734,18735,18736,18737,18738,18739,
18740,18741,18742,18743,18744,18745,18746,18747,18748,18749,18750,18751,
18752,18753,18754,18755,18756,18757,18758,18759,18760,18761,18762,18763,
18764,18765,18766,18767,18768,18769,18770,18771,18772,18773,18774,18775,
18776,18777,18778,18779,18780,18781,18782,18783,18784,18785,18786,18787,
18788,18789,18790,18791,18792,18793,18794,18795,18796,18797,18798,18799,
18800,18801,18802,18803,18804,18805,18806,18807,18808,18809,18810,18811,
18812,18813,18814,18815,18816,18817,18818,18819,18820,18821,18822,18823,
18824,18825,18826,18827,18828,18829,18830,18831,18832,18833,18834,18835,
18836,18837,18838,18839,18840,18841,18842,18843,18844,18845,18846,18847,
18848,18849,18850,18851,18852,18853,18854,18855,18856,18857,18858,18859,
18860,18861,18862,18863,18864,18865,18866,18867,18868,18869,18870,18871,
18872,18873,18874,18875,18876,18877,18878,18879,18880,18881,18882,18883,
18884,18885,18886,18887,18888,18889,18890,18891,18892,18893,18894,18895,
18896,18897,18898,18899,18900,18901,18902,18903,18904,18905,18906,18907,
18908,18909,18910,18911,18912,18913,18914,18915,18916,18917,18918,18919,
18920,18921,18922,18923,18924,18925,18926,18927,18928,18929,18930,18931,
18932,18933,18934,18935,18936,18937,18938,18939,18940,18941,18942,18943,
18944,18945,18946,18947,18948,18949,18950,18951,18952,18953,18954,18955,
18956,18957,18958,18959,18960,18961,18962,18963,18964,18965,18966,18967,
18968,18969,18970,18971,18972,18973,18974,18975,18976,18977,18978,18979,
18980,18981,18982,18983,18984,18985,18986,18987,18988,18989,18990,18991,
18992,18993,18994,18995,18996,18997,18998,18999,19000,19001,19002,19003,
19004,19005,19006,19007,19008,19009,19010,19011,19012,19013,19014,19015,
19016,19017,19018,19019,19020,19021,19022,19023,19024,19025,19026,19027,
19028,19029,19030,19031,19032,19033,19034,19035,19036,19037,19038,19039,
19040,19041,19042,19043,19044,19045,19046,19047,19048,19049,19050,19051,
19052,19053,19054,19055,19056,19057,19058,19059,19060,19061,19062,19063,
19064,19065,19066,19067,19068,19069,19070,19071,19072,19073,19074,19075,
19076,19077,19078,19079,19080,19081,19082,19083,19084,19085,19086,19087,
19088,19089,19090,19091,19092,19093,19094,19095,19096,19097,19098,19099,
19100,19101,19102,19103,19104,19105,19106,19107,19108,19109,19110,19111,
19112,19113,19114,19115,19116,19117,19118,19119,19120,19121,19122,19123,
19124,19125,19126,19127,19128,19129,19130,19131,19132,19133,19134,19135,
19136,19137,19138,19139,19140,19141,19142,19143,19144,19145,19146,19147,
19148,19149,19150,19151,19152,19153,19154,19155,19156,19157,19158,19159,
19160,19161,19162,19163,19164,19165,19166,19167,19168,19169,19170,19171,
19172,19173,19174,19175,19176,19177,19178,19179,19180,19181,19182,19183,
19184,19185,19186,19187,19188,19189,19190,19191,19192,19193,19194,19195,
19196,19197,19198,19199,19200,19201,19202,19203,19204,19205,19206,19207,
19208,19209,19210,19211,19212,19213,19214,19215,19216,19217,19218,19219,
19220,19221,19222,19223,19224,19225,19226,19227,19228,19229,19230,19231,
19232,19233,19234,19235,19236,19237,19238,19239,19240,19241,19242,19243,
19244,19245,19246,19247,19248,19249,19250,19251,19252,19253,19254,19255,
19256,19257,19258,19259,19260,19261,19262,19263,19264,19265,19266,19267,
19268,19269,19270,19271,19272,19273,19274,19275,19276,19277,19278,19279,
19280,19281,19282,19283,19284,19285,19286,19287,19288,19289,19290,19291,
19292,19293,19294,19295,19296,19297,19298,19299,19300,19301,19302,19303,
19304,19305,19306,19307,19308,19309,19310,19311,19312,19313,19314,19315,
19316,19317,19318,19319,19320,19321,19322,19323,19324,19325,19326,19327,
19328,19329,19330,19331,19332,19333,19334,19335,19336,19337,19338,19339,
19340,19341,19342,19343,19344,19345,19346,19347,19348,19349,19350,19351,
19352,19353,19354,19355,19356,19357,19358,19359,19360,19361,19362,19363,
19364,19365,19366,19367,19368,19369,19370,19371,19372,19373,19374,19375,
19376,19377,19378,19379,19380,19381,19382,19383,19384,19385,19386,19387,
19388,19389,19390,19391,19392,19393,19394,19395,19396,19397,19398,19399,
19400,19401,19402,19403,19404,19405,19406,19407,19408,19409,19410,19411,
19412,19413,19414,19415,19416,19417,19418,19419,19420,19421,19422,19423,
19424,19425,19426,19427,19428,19429,19430,19431,19432,19433,19434,19435,
19436,19437,19438,19439,19440,19441,19442,19443,19444,19445,19446,19447,
19448,19449,19450,19451,19452,19453,19454,19455,19456,19457,19458,19459,
19460,19461,19462,19463,19464,19465,19466,19467,19468,19469,19470,19471,
19472,19473,19474,19475,19476,19477,19478,19479,19480,19481,19482,19483,
19484,19485,19486,19487,19488,19489,19490,19491,19492,19493,19494,19495,
19496,19497,19498,19499,19500,19501,19502,19503,19504,19505,19506,19507,
19508,19509,19510,19511,19512,19513,19514,19515,19516,19517,19518,19519,
19520,19521,19522,19523,19524,19525,19526,19527,19528,19529,19530,19531,
19532,19533,19534,19535,19536,19537,19538,19539,19540,19541,19542,19543,
19544,19545,19546,19547,19548,19549,19550,19551,19552,19553,19554,19555,
19556,19557,19558,19559,19560,19561,19562,19563,19564,19565,19566,19567,
19568,19569,19570,19571,19572,19573,19574,19575,19576,19577,19578,19579,
19580,19581,19582,19583,19584,19585,19586,19587,19588,19589,19590,19591,
19592,19593,19594,19595,19596,19597,19598,19599,19600,19601,19602,19603,
19604,19605,19606,19607,19608,19609,19610,19611,19612,19613,19614,19615,
19616,19617,19618,19619,19620,19621,19622,19623,19624,19625,19626,19627,
19628,19629,19630,19631,19632,19633,19634,19635,19636,19637,19638,19639,
19640,19641,19642,19643,19644,19645,19646,19647,19648,19649,19650,19651,
19652,19653,19654,19655,19656,19657,19658,19659,19660,19661,19662,19663,
19664,19665,19666,19667,19668,19669,19670,19671,19672,19673,19674,19675,
19676,19677,19678,19679,19680,19681,19682,19683,19684,19685,19686,19687,
19688,19689,19690,19691,19692,19693,19694,19695,19696,19697,19698,19699,
19700,19701,19702,19703,19704,19705,19706,19707,19708,19709,19710,19711,
19712,19713,19714,19715,19716,19717,19718,19719,19720,19721,19722,19723,
19724,19725,19726,19727,19728,19729,19730,19731,19732,19733,19734,19735,
19736,19737,19738,19739,19740,19741,19742,19743,19744,19745,19746,19747,
19748,19749,19750,19751,19752,19753,19754,19755,19756,19757,19758,19759,
19760,19761,19762,19763,19764,19765,19766,19767,19768,19769,19770,19771,
19772,19773,19774,19775,19776,19777,19778,19779,19780,19781,19782,19783,
19784,19785,19786,19787,19788,19789,19790,19791,19792,19793,19794,19795,
19796,19797,19798,19799,19800,19801,19802,19803,19804,19805,19806,19807,
19808,19809,19810,19811,19812,19813,19814,19815,19816,19817,19818,19819,
19820,19821,19822,19823,19824,19825,19826,19827,19828,19829,19830,19831,
19832,19833,19834,19835,19836,19837,19838,19839,19840,19841,19842,19843,
19844,19845,19846,19847,19848,19849,19850,19851,19852,19853,19854,19855,
19856,19857,19858,19859,19860,19861,19862,19863,19864,19865,19866,19867,
19868,19869,19870,19871,19872,19873,19874,19875,19876,19877,19878,19879,
19880,19881,19882,19883,19884,19885,19886,19887,19888,19889,19890,19891,
19892,19893,19894,19895,19896,19897,19898,19899,19900,19901,19902,19903,
19904,19905,19906,19907,19908,19909,19910,19911,19912,19913,19914,19915,
19916,19917,19918,19919,19920,19921,19922,19923,19924,19925,19926,19927,
19928,19929,19930,19931,19932,19933,19934,19935,19936,19937,19938,19939,
19940,19941,19942,19943,19944,19945,19946,19947,19948,19949,19950,19951,
19952,19953,19954,19955,19956,19957,19958,19959,19960,19961,19962,19963,
19964,19965,19966,19967,19968,19969,19970,19971,19972,19973,19974,19975,
19976,19977,19978,19979,19980,19981,19982,19983,19984,19985,19986,19987,
19988,19989,19990,19991,19992,19993,19994,19995,19996,19997,19998,19999,
20000,20001,20002,20003,20004,20005,20006,20007,20008,20009,20010,20011,
20012,20013,20014,20015,20016,20017,20018,20019,20020,20021,20022,20023,
20024,20025,20026,20027,20028,20029,20030,20031,20032,20033,20034,20035,
20036,20037,20038,20039,20040,20041,20042,20043,20044,20045,20046,20047,
20048,20049,20050,20051,20052,20053,20054,20055,20056,20057,20058,20059,
20060,20061,20062,20063,20064,20065,20066,20067,20068,20069,20070,20071,
20072,20073,20074,20075,20076,20077,20078,20079,20080,20081,20082,20083,
20084,20085,20086,20087,20088,20089,20090,20091,20092,20093,20094,20095,
20096,20097,20098,20099,20100,20101,20102,20103,20104,20105,20106,20107,
20108,20109,20110,20111,20112,20113,20114,20115,20116,20117,20118,20119,
20120,20121,20122,20123,20124,20125,20126,20127,20128,20129,20130,20131,
20132,20133,20134,20135,20136,20137,20138,20139,20140,20141,20142,20143,
20144,20145,20146,20147,20148,20149,20150,20151,20152,20153,20154,20155,
20156,20157,20158,20159,20160,20161,20162,20163,20164,20165,20166,20167,
20168,20169,20170,20171,20172,20173,20174,20175,20176,20177,20178,20179,
20180,20181,20182,20183,20184,20185,20186,20187,20188,20189,20190,20191,
20192,20193,20194,20195,20196,20197,20198,20199,20200,20201,20202,20203,
20204,20205,20206,20207,20208,20209,20210,20211,20212,20213,20214,20215,
20216,20217,20218,20219,20220,20221,20222,20223,20224,20225,20226,20227,
20228,20229,20230,20231,20232,20233,20234,20235,20236,20237,20238,20239,
20240,20241,20242,20243,20244,20245,20246,20247,20248,20249,20250,20251,
20252,20253,20254,20255,20256,20257,20258,20259,20260,20261,20262,20263,
20264,20265,20266,20267,20268,20269,20270,20271,20272,20273,20274,20275,
20276,20277,20278,20279,20280,20281,20282,20283,20284,20285,20286,20287,
20288,20289,20290,20291,20292,20293,20294,20295,20296,20297,20298,20299,
20300,20301,20302,20303,20304,20305,20306,20307,20308,20309,20310,20311,
20312,20313,20314,20315,20316,20317,20318,20319,20320,20321,20322,20323,
20324,20325,20326,20327,20328,20329,20330,20331,20332,20333,20334,20335,
20336,20337,20338,20339,20340,20341,20342,20343,20344,20345,20346,20347,
20348,20349,20350,20351,20352,20353,20354,20355,20356,20357,20358,20359,
20360,20361,20362,20363,20364,20365,20366,20367,20368,20369,20370,20371,
20372,20373,20374,20375,20376,20377,20378,20379,20380,20381,20382,20383,
20384,20385,20386,20387,20388,20389,20390,20391,20392,20393,20394,20395,
20396,20397,20398,20399,20400,20401,20402,20403,20404,20405,20406,20407,
20408,20409,20410,20411,20412,20413,20414,20415,20416,20417,20418,20419,
20420,20421,20422,20423,20424,20425,20426,20427,20428,20429,20430,20431,
20432,20433,20434,20435,20436,20437,20438,20439,20440,20441,20442,20443,
20444,20445,20446,20447,20448,20449,20450,20451,20452,20453,20454,20455,
20456,20457,20458,20459,20460,20461,20462,20463,20464,20465,20466,20467,
20468,20469,20470,20471,20472,20473,20474,20475,20476,20477,20478,20479,
20480,20481,20482,20483,20484,20485,20486,20487,20488,20489,20490,20491,
20492,20493,20494,20495,20496,20497,20498,20499,20500,20501,20502,20503,
20504,20505,20506,20507,20508,20509,20510,20511,20512,20513,20514,20515,
20516,20517,20518,20519,20520,20521,20522,20523,20524,20525,20526,20527,
20528,20529,20530,20531,20532,20533,20534,20535,20536,20537,20538,20539,
20540,20541,20542,20543,20544,20545,20546,20547,20548,20549,20550,20551,
20552,20553,20554,20555,20556,20557,20558,20559,20560,20561,20562,20563,
20564,20565,20566,20567,20568,20569,20570,20571,20572,20573,20574,20575,
20576,20577,20578,20579,20580,20581,20582,20583,20584,20585,20586,20587,
20588,20589,20590,20591,20592,20593,20594,20595,20596,20597,20598,20599,
20600,20601,20602,20603,20604,20605,20606,20607,20608,20609,20610,20611,
20612,20613,20614,20615,20616,20617,20618,20619,20620,20621,20622,20623,
20624,20625,20626,20627,20628,20629,20630,20631,20632,20633,20634,20635,
20636,20637,20638,20639,20640,20641,20642,20643,20644,20645,20646,20647,
20648,20649,20650,20651,20652,20653,20654,20655,20656,20657,20658,20659,
20660,20661,20662,20663,20664,20665,20666,20667,20668,20669,20670,20671,
20672,20673,20674,20675,20676,20677,20678,20679,20680,20681,20682,20683,
20684,20685,20686,20687,20688,20689,20690,20691,20692,20693,20694,20695,
20696,20697,20698,20699,20700,20701,20702,20703,20704,20705,20706,20707,
20708,20709,20710,20711,20712,20713,20714,20715,20716,20717,20718,20719,
20720,20721,20722,20723,20724,20725,20726,20727,20728,20729,20730,20731,
20732,20733,20734,20735,20736,20737,20738,20739,20740,20741,20742,20743,
20744,20745,20746,20747,20748,20749,20750,20751,20752,20753,20754,20755,
20756,20757,20758,20759,20760,20761,20762,20763,20764,20765,20766,20767,
20768,20769,20770,20771,20772,20773,20774,20775,20776,20777,20778,20779,
20780,20781,20782,20783,20784,20785,20786,20787,20788,20789,20790,20791,
20792,20793,20794,20795,20796,20797,20798,20799,20800,20801,20802,20803,
20804,20805,20806,20807,20808,20809,20810,20811,20812,20813,20814,20815,
20816,20817,20818,20819,20820,20821,20822,20823,20824,20825,20826,20827,
20828,20829,20830,20831,20832,20833,20834,20835,20836,20837,20838,20839,
20840,20841,20842,20843,20844,20845,20846,20847,20848,20849,20850,20851,
20852,20853,20854,20855,20856,20857,20858,20859,20860,20861,20862,20863,
20864,20865,20866,20867,20868,20869,20870,20871,20872,20873,20874,20875,
20876,20877,20878,20879,20880,20881,20882,20883,20884,20885,20886,20887,
20888,20889,20890,20891,20892,20893,20894,20895,20896,20897,20898,20899,
20900,20901,20902,20903,20904,20905,20906,20907,20908,20909,20910,20911,
20912,20913,20914,20915,20916,20917,20918,20919,20920,20921,20922,20923,
20924,20925,20926,20927,20928,20929,20930,20931,20932,20933,20934,20935,
20936,20937,20938,20939,20940,20941,20942,20943,20944,20945,20946,20947,
20948,20949,20950,20951,20952,20953,20954,20955,20956,20957,20958,20959,
20960,20961,20962,20963,20964,20965,20966,20967,20968,20969,20970,20971,
20972,20973,20974,20975,20976,20977,20978,20979,20980,20981,20982,20983,
20984,20985,20986,20987,20988,20989,20990,20991,20992,20993,20994,20995,
20996,20997,20998,20999,21000,21001,21002,21003,21004,21005,21006,21007,
21008,21009,21010,21011,21012,21013,21014,21015,21016,21017,21018,21019,
21020,21021,21022,21023,21024,21025,21026,21027,21028,21029,21030,21031,
21032,21033,21034,21035,21036,21037,21038,21039,21040,21041,21042,21043,
21044,21045,21046,21047,21048,21049,21050,21051,21052,21053,21054,21055,
21056,21057,21058,21059,21060,21061,21062,21063,21064,21065,21066,21067,
21068,21069,21070,21071,21072,21073,21074,21075,21076,21077,21078,21079,
21080,21081,21082,21083,21084,21085,21086,21087,21088,21089,21090,21091,
21092,21093,21094,21095,21096,21097,21098,21099,21100,21101,21102,21103,
21104,21105,21106,21107,21108,21109,21110,21111,21112,21113,21114,21115,
21116,21117,21118,21119,21120,21121,21122,21123,21124,21125,21126,21127,
21128,21129,21130,21131,21132,21133,21134,21135,21136,21137,21138,21139,
21140,21141,21142,21143,21144,21145,21146,21147,21148,21149,21150,21151,
21152,21153,21154,21155,21156,21157,21158,21159,21160,21161,21162,21163,
21164,21165,21166,21167,21168,21169,21170,21171,21172,21173,21174,21175,
21176,21177,21178,21179,21180,21181,21182,21183,21184,21185,21186,21187,
21188,21189,21190,21191,21192,21193,21194,21195,21196,21197,21198,21199,
21200,21201,21202,21203,21204,21205,21206,21207,21208,21209,21210,21211,
21212,21213,21214,21215,21216,21217,21218,21219,21220,21221,21222,21223,
21224,21225,21226,21227,21228,21229,21230,21231,21232,21233,21234,21235,
21236,21237,21238,21239,21240,21241,21242,21243,21244,21245,21246,21247,
21248,21249,21250,21251,21252,21253,21254,21255,21256,21257,21258,21259,
21260,21261,21262,21263,21264,21265,21266,21267,21268,21269,21270,21271,
21272,21273,21274,21275,21276,21277,21278,21279,21280,21281,21282,21283,
21284,21285,21286,21287,21288,21289,21290,21291,21292,21293,21294,21295,
21296,21297,21298,21299,21300,21301,21302,21303,21304,21305,21306,21307,
21308,21309,21310,21311,21312,21313,21314,21315,21316,21317,21318,21319,
21320,21321,21322,21323,21324,21325,21326,21327,21328,21329,21330,21331,
21332,21333,21334,21335,21336,21337,21338,21339,21340,21341,21342,21343,
21344,21345,21346,21347,21348,21349,21350,21351,21352,21353,21354,21355,
21356,21357,21358,21359,21360,21361,21362,21363,21364,21365,21366,21367,
21368,21369,21370,21371,21372,21373,21374,21375,21376,21377,21378,21379,
21380,21381,21382,21383,21384,21385,21386,21387,21388,21389,21390,21391,
21392,21393,21394,21395,21396,21397,21398,21399,21400,21401,21402,21403,
21404,21405,21406,21407,21408,21409,21410,21411,21412,21413,21414,21415,
21416,21417,21418,21419,21420,21421,21422,21423,21424,21425,21426,21427,
21428,21429,21430,21431,21432,21433,21434,21435,21436,21437,21438,21439,
21440,21441,21442,21443,21444,21445,21446,21447,21448,21449,21450,21451,
21452,21453,21454,21455,21456,21457,21458,21459,21460,21461,21462,21463,
21464,21465,21466,21467,21468,21469,21470,21471,21472,21473,21474,21475,
21476,21477,21478,21479,21480,21481,21482,21483,21484,21485,21486,21487,
21488,21489,21490,21491,21492,21493,21494,21495,21496,21497,21498,21499,
21500,21501,21502,21503,21504,21505,21506,21507,21508,21509,21510,21511,
21512,21513,21514,21515,21516,21517,21518,21519,21520,21521,21522,21523,
21524,21525,21526,21527,21528,21529,21530,21531,21532,21533,21534,21535,
21536,21537,21538,21539,21540,21541,21542,21543,21544,21545,21546,21547,
21548,21549,21550,21551,21552,21553,21554,21555,21556,21557,21558,21559,
21560,21561,21562,21563,21564,21565,21566,21567,21568,21569,21570,21571,
21572,21573,21574,21575,21576,21577,21578,21579,21580,21581,21582,21583,
21584,21585,21586,21587,21588,21589,21590,21591,21592,21593,21594,21595,
21596,21597,21598,21599,21600,21601,21602,21603,21604,21605,21606,21607,
21608,21609,21610,21611,21612,21613,21614,21615,21616,21617,21618,21619,
21620,21621,21622,21623,21624,21625,21626,21627,21628,21629,21630,21631,
21632,21633,21634,21635,21636,21637,21638,21639,21640,21641,21642,21643,
21644,21645,21646,21647,21648,21649,21650,21651,21652,21653,21654,21655,
21656,21657,21658,21659,21660,21661,21662,21663,21664,21665,21666,21667,
21668,21669,21670,21671,21672,21673,21674,21675,21676,21677,21678,21679,
21680,21681,21682,21683,21684,21685,21686,21687,21688,21689,21690,21691,
21692,21693,21694,21695,21696,21697,21698,21699,21700,21701,21702,21703,
21704,21705,21706,21707,21708,21709,21710,21711,21712,21713,21714,21715,
21716,21717,21718,21719,21720,21721,21722,21723,21724,21725,21726,21727,
21728,21729,21730,21731,21732,21733,21734,21735,21736,21737,21738,21739,
21740,21741,21742,21743,21744,21745,21746,21747,21748,21749,21750,21751,
21752,21753,21754,21755,21756,21757,21758,21759,21760,21761,21762,21763,
21764,21765,21766,21767,21768,21769,21770,21771,21772,21773,21774,21775,
21776,21777,21778,21779,21780,21781,21782,21783,21784,21785,21786,21787,
21788,21789,21790,21791,21792,21793,21794,21795,21796,21797,21798,21799,
21800,21801,21802,21803,21804,21805,21806,21807,21808,21809,21810,21811,
21812,21813,21814,21815,21816,21817,21818,21819,21820,21821,21822,21823,
21824,21825,21826,21827,21828,21829,21830,21831,21832,21833,21834,21835,
21836,21837,21838,21839,21840,21841,21842,21843,21844,21845,21846,21847,
21848,21849,21850,21851,21852,21853,21854,21855,21856,21857,21858,21859,
21860,21861,21862,21863,21864,21865,21866,21867,21868,21869,21870,21871,
21872,21873,21874,21875,21876,21877,21878,21879,21880,21881,21882,21883,
21884,21885,21886,21887,21888,21889,21890,21891,21892,21893,21894,21895,
21896,21897,21898,21899,21900,21901,21902,21903,21904,21905,21906,21907,
21908,21909,21910,21911,21912,21913,21914,21915,21916,21917,21918,21919,
21920,21921,21922,21923,21924,21925,21926,21927,21928,21929,21930,21931,
21932,21933,21934,21935,21936,21937,21938,21939,21940,21941,21942,21943,
21944,21945,21946,21947,21948,21949,21950,21951,21952,21953,21954,21955,
21956,21957,21958,21959,21960,21961,21962,21963,21964,21965,21966,21967,
21968,21969,21970,21971,21972,21973,21974,21975,21976,21977,21978,21979,
21980,21981,21982,21983,21984,21985,21986,21987,21988,21989,21990,21991,
21992,21993,21994,21995,21996,21997,21998,21999,22000,22001,22002,22003,
22004,22005,22006,22007,22008,22009,22010,22011,22012,22013,22014,22015,
22016,22017,22018,22019,22020,22021,22022,22023,22024,22025,22026,22027,
22028,22029,22030,22031,22032,22033,22034,22035,22036,22037,22038,22039,
22040,22041,22042,22043,22044,22045,22046,22047,22048,22049,22050,22051,
22052,22053,22054,22055,22056,22057,22058,22059,22060,22061,22062,22063,
22064,22065,22066,22067,22068,22069,22070,22071,22072,22073,22074,22075,
22076,22077,22078,22079,22080,22081,22082,22083,22084,22085,22086,22087,
22088,22089,22090,22091,22092,22093,22094,22095,22096,22097,22098,22099,
22100,22101,22102,22103,22104,22105,22106,22107,22108,22109,22110,22111,
22112,22113,22114,22115,22116,22117,22118,22119,22120,22121,22122,22123,
22124,22125,22126,22127,22128,22129,22130,22131,22132,22133,22134,22135,
22136,22137,22138,22139,22140,22141,22142,22143,22144,22145,22146,22147,
22148,22149,22150,22151,22152,22153,22154,22155,22156,22157,22158,22159,
22160,22161,22162,22163,22164,22165,22166,22167,22168,22169,22170,22171,
22172,22173,22174,22175,22176,22177,22178,22179,22180,22181,22182,22183,
22184,22185,22186,22187,22188,22189,22190,22191,22192,22193,22194,22195,
22196,22197,22198,22199,22200,22201,22202,22203,22204,22205,22206,22207,
22208,22209,22210,22211,22212,22213,22214,22215,22216,22217,22218,22219,
22220,22221,22222,22223,22224,22225,22226,22227,22228,22229,22230,22231,
22232,22233,22234,22235,22236,22237,22238,22239,22240,22241,22242,22243,
22244,22245,22246,22247,22248,22249,22250,22251,22252,22253,22254,22255,
22256,22257,22258,22259,22260,22261,22262,22263,22264,22265,22266,22267,
22268,22269,22270,22271,22272,22273,22274,22275,22276,22277,22278,22279,
22280,22281,22282,22283,22284,22285,22286,22287,22288,22289,22290,22291,
22292,22293,22294,22295,22296,22297,22298,22299,22300,22301,22302,22303,
22304,22305,22306,22307,22308,22309,22310,22311,22312,22313,22314,22315,
22316,22317,22318,22319,22320,22321,22322,22323,22324,22325,22326,22327,
22328,22329,22330,22331,22332,22333,22334,22335,22336,22337,22338,22339,
22340,22341,22342,22343,22344,22345,22346,22347,22348,22349,22350,22351,
22352,22353,22354,22355,22356,22357,22358,22359,22360,22361,22362,22363,
22364,22365,22366,22367,22368,22369,22370,22371,22372,22373,22374,22375,
22376,22377,22378,22379,22380,22381,22382,22383,22384,22385,22386,22387,
22388,22389,22390,22391,22392,22393,22394,22395,22396,22397,22398,22399,
22400,22401,22402,22403,22404,22405,22406,22407,22408,22409,22410,22411,
22412,22413,22414,22415,22416,22417,22418,22419,22420,22421,22422,22423,
22424,22425,22426,22427,22428,22429,22430,22431,22432,22433,22434,22435,
22436,22437,22438,22439,22440,22441,22442,22443,22444,22445,22446,22447,
22448,22449,22450,22451,22452,22453,22454,22455,22456,22457,22458,22459,
22460,22461,22462,22463,22464,22465,22466,22467,22468,22469,22470,22471,
22472,22473,22474,22475,22476,22477,22478,22479,22480,22481,22482,22483,
22484,22485,22486,22487,22488,22489,22490,22491,22492,22493,22494,22495,
22496,22497,22498,22499,22500,22501,22502,22503,22504,22505,22506,22507,
22508,22509,22510,22511,22512,22513,22514,22515,22516,22517,22518,22519,
22520,22521,22522,22523,22524,22525,22526,22527,22528,22529,22530,22531,
22532,22533,22534,22535,22536,22537,22538,22539,22540,22541,22542,22543,
22544,22545,22546,22547,22548,22549,22550,22551,22552,22553,22554,22555,
22556,22557,22558,22559,22560,22561,22562,22563,22564,22565,22566,22567,
22568,22569,22570,22571,22572,22573,22574,22575,22576,22577,22578,22579,
22580,22581,22582,22583,22584,22585,22586,22587,22588,22589,22590,22591,
22592,22593,22594,22595,22596,22597,22598,22599,22600,22601,22602,22603,
22604,22605,22606,22607,22608,22609,22610,22611,22612,22613,22614,22615,
22616,22617,22618,22619,22620,22621,22622,22623,22624,22625,22626,22627,
22628,22629,22630,22631,22632,22633,22634,22635,22636,22637,22638,22639,
22640,22641,22642,22643,22644,22645,22646,22647,22648,22649,22650,22651,
22652,22653,22654,22655,22656,22657,22658,22659,22660,22661,22662,22663,
22664,22665,22666,22667,22668,22669,22670,22671,22672,22673,22674,22675,
22676,22677,22678,22679,22680,22681,22682,22683,22684,22685,22686,22687,
22688,22689,22690,22691,22692,22693,22694,22695,22696,22697,22698,22699,
22700,22701,22702,22703,22704,22705,22706,22707,22708,22709,22710,22711,
22712,22713,22714,22715,22716,22717,22718,22719,22720,22721,22722,22723,
22724,22725,22726,22727,22728,22729,22730,22731,22732,22733,22734,22735,
22736,22737,22738,22739,22740,22741,22742,22743,22744,22745,22746,22747,
22748,22749,22750,22751,22752,22753,22754,22755,22756,22757,22758,22759,
22760,22761,22762,22763,22764,22765,22766,22767,22768,22769,22770,22771,
22772,22773,22774,22775,22776,22777,22778,22779,22780,22781,22782,22783,
22784,22785,22786,22787,22788,22789,22790,22791,22792,22793,22794,22795,
22796,22797,22798,22799,22800,22801,22802,22803,22804,22805,22806,22807,
22808,22809,22810,22811,22812,22813,22814,22815,22816,22817,22818,22819,
22820,22821,22822,22823,22824,22825,22826,22827,22828,22829,22830,22831,
22832,22833,22834,22835,22836,22837,22838,22839,22840,22841,22842,22843,
22844,22845,22846,22847,22848,22849,22850,22851,22852,22853,22854,22855,
22856,22857,22858,22859,22860,22861,22862,22863,22864,22865,22866,22867,
22868,22869,22870,22871,22872,22873,22874,22875,22876,22877,22878,22879,
22880,22881,22882,22883,22884,22885,22886,22887,22888,22889,22890,22891,
22892,22893,22894,22895,22896,22897,22898,22899,22900,22901,22902,22903,
22904,22905,22906,22907,22908,22909,22910,22911,22912,22913,22914,22915,
22916,22917,22918,22919,22920,22921,22922,22923,22924,22925,22926,22927,
22928,22929,22930,22931,22932,22933,22934,22935,22936,22937,22938,22939,
22940,22941,22942,22943,22944,22945,22946,22947,22948,22949,22950,22951,
22952,22953,22954,22955,22956,22957,22958,22959,22960,22961,22962,22963,
22964,22965,22966,22967,22968,22969,22970,22971,22972,22973,22974,22975,
22976,22977,22978,22979,22980,22981,22982,22983,22984,22985,22986,22987,
22988,22989,22990,22991,22992,22993,22994,22995,22996,22997,22998,22999,
23000,23001,23002,23003,23004,23005,23006,23007,23008,23009,23010,23011,
23012,23013,23014,23015,23016,23017,23018,23019,23020,23021,23022,23023,
23024,23025,23026,23027,23028,23029,23030,23031,23032,23033,23034,23035,
23036,23037,23038,23039,23040,23041,23042,23043,23044,23045,23046,23047,
23048,23049,23050,23051,23052,23053,23054,23055,23056,23057,23058,23059,
23060,23061,23062,23063,23064,23065,23066,23067,23068,23069,23070,23071,
23072,23073,23074,23075,23076,23077,23078,23079,23080,23081,23082,23083,
23084,23085,23086,23087,23088,23089,23090,23091,23092,23093,23094,23095,
23096,23097,23098,23099,23100,23101,23102,23103,23104,23105,23106,23107,
23108,23109,23110,23111,23112,23113,23114,23115,23116,23117,23118,23119,
23120,23121,23122,23123,23124,23125,23126,23127,23128,23129,23130,23131,
23132,23133,23134,23135,23136,23137,23138,23139,23140,23141,23142,23143,
23144,23145,23146,23147,23148,23149,23150,23151,23152,23153,23154,23155,
23156,23157,23158,23159,23160,23161,23162,23163,23164,23165,23166,23167,
23168,23169,23170,23171,23172,23173,23174,23175,23176,23177,23178,23179,
23180,23181,23182,23183,23184,23185,23186,23187,23188,23189,23190,23191,
23192,23193,23194,23195,23196,23197,23198,23199,23200,23201,23202,23203,
23204,23205,23206,23207,23208,23209,23210,23211,23212,23213,23214,23215,
23216,23217,23218,23219,23220,23221,23222,23223,23224,23225,23226,23227,
23228,23229,23230,23231,23232,23233,23234,23235,23236,23237,23238,23239,
23240,23241,23242,23243,23244,23245,23246,23247,23248,23249,23250,23251,
23252,23253,23254,23255,23256,23257,23258,23259,23260,23261,23262,23263,
23264,23265,23266,23267,23268,23269,23270,23271,23272,23273,23274,23275,
23276,23277,23278,23279,23280,23281,23282,23283,23284,23285,23286,23287,
23288,23289,23290,23291,23292,23293,23294,23295,23296,23297,23298,23299,
23300,23301,23302,23303,23304,23305,23306,23307,23308,23309,23310,23311,
23312,23313,23314,23315,23316,23317,23318,23319,23320,23321,23322,23323,
23324,23325,23326,23327,23328,23329,23330,23331,23332,23333,23334,23335,
23336,23337,23338,23339,23340,23341,23342,23343,23344,23345,23346,23347,
23348,23349,23350,23351,23352,23353,23354,23355,23356,23357,23358,23359,
23360,23361,23362,23363,23364,23365,23366,23367,23368,23369,23370,23371,
23372,23373,23374,23375,23376,23377,23378,23379,23380,23381,23382,23383,
23384,23385,23386,23387,23388,23389,23390,23391,23392,23393,23394,23395,
23396,23397,23398,23399,23400,23401,23402,23403,23404,23405,23406,23407,
23408,23409,23410,23411,23412,23413,23414,23415,23416,23417,23418,23419,
23420,23421,23422,23423,23424,23425,23426,23427,23428,23429,23430,23431,
23432,23433,23434,23435,23436,23437,23438,23439,23440,23441,23442,23443,
23444,23445,23446,23447,23448,23449,23450,23451,23452,23453,23454,23455,
23456,23457,23458,23459,23460,23461,23462,23463,23464,23465,23466,23467,
23468,23469,23470,23471,23472,23473,23474,23475,23476,23477,23478,23479,
23480,23481,23482,23483,23484,23485,23486,23487,23488,23489,23490,23491,
23492,23493,23494,23495,23496,23497,23498,23499,23500,23501,23502,23503,
23504,23505,23506,23507,23508,23509,23510,23511,23512,23513,23514,23515,
23516,23517,23518,23519,23520,23521,23522,23523,23524,23525,23526,23527,
23528,23529,23530,23531,23532,23533,23534,23535,23536,23537,23538,23539,
23540,23541,23542,23543,23544,23545,23546,23547,23548,23549,23550,23551,
23552,23553,23554,23555,23556,23557,23558,23559,23560,23561,23562,23563,
23564,23565,23566,23567,23568,23569,23570,23571,23572,23573,23574,23575,
23576,23577,23578,23579,23580,23581,23582,23583,23584,23585,23586,23587,
23588,23589,23590,23591,23592,23593,23594,23595,23596,23597,23598,23599,
23600,23601,23602,23603,23604,23605,23606,23607,23608,23609,23610,23611,
23612,23613,23614,23615,23616,23617,23618,23619,23620,23621,23622,23623,
23624,23625,23626,23627,23628,23629,23630,23631,23632,23633,23634,23635,
23636,23637,23638,23639,23640,23641,23642,23643,23644,23645,23646,23647,
23648,23649,23650,23651,23652,23653,23654,23655,23656,23657,23658,23659,
23660,23661,23662,23663,23664,23665,23666,23667,23668,23669,23670,23671,
23672,23673,23674,23675,23676,23677,23678,23679,23680,23681,23682,23683,
23684,23685,23686,23687,23688,23689,23690,23691,23692,23693,23694,23695,
23696,23697,23698,23699,23700,23701,23702,23703,23704,23705,23706,23707,
23708,23709,23710,23711,23712,23713,23714,23715,23716,23717,23718,23719,
23720,23721,23722,23723,23724,23725,23726,23727,23728,23729,23730,23731,
23732,23733,23734,23735,23736,23737,23738,23739,23740,23741,23742,23743,
23744,23745,23746,23747,23748,23749,23750,23751,23752,23753,23754,23755,
23756,23757,23758,23759,23760,23761,23762,23763,23764,23765,23766,23767,
23768,23769,23770,23771,23772,23773,23774,23775,23776,23777,23778,23779,
23780,23781,23782,23783,23784,23785,23786,23787,23788,23789,23790,23791,
23792,23793,23794,23795,23796,23797,23798,23799,23800,23801,23802,23803,
23804,23805,23806,23807,23808,23809,23810,23811,23812,23813,23814,23815,
23816,23817,23818,23819,23820,23821,23822,23823,23824,23825,23826,23827,
23828,23829,23830,23831,23832,23833,23834,23835,23836,23837,23838,23839,
23840,23841,23842,23843,23844,23845,23846,23847,23848,23849,23850,23851,
23852,23853,23854,23855,23856,23857,23858,23859,23860,23861,23862,23863,
23864,23865,23866,23867,23868,23869,23870,23871,23872,23873,23874,23875,
23876,23877,23878,23879,23880,23881,23882,23883,23884,23885,23886,23887,
23888,23889,23890,23891,23892,23893,23894,23895,23896,23897,23898,23899,
23900,23901,23902,23903,23904,23905,23906,23907,23908,23909,23910,23911,
23912,23913,23914,23915,23916,23917,23918,23919,23920,23921,23922,23923,
23924,23925,23926,23927,23928,23929,23930,23931,23932,23933,23934,23935,
23936,23937,23938,23939,23940,23941,23942,23943,23944,23945,23946,23947,
23948,23949,23950,23951,23952,23953,23954,23955,23956,23957,23958,23959,
23960,23961,23962,23963,23964,23965,23966,23967,23968,23969,23970,23971,
23972,23973,23974,23975,23976,23977,23978,23979,23980,23981,23982,23983,
23984,23985,23986,23987,23988,23989,23990,23991,23992,23993,23994,23995,
23996,23997,23998,23999,24000,24001,24002,24003,24004,24005,24006,24007,
24008,24009,24010,24011,24012,24013,24014,24015,24016,24017,24018,24019,
24020,24021,24022,24023,24024,24025,24026,24027,24028,24029,24030,24031,
24032,24033,24034,24035,24036,24037,24038,24039,24040,24041,24042,24043,
24044,24045,24046,24047,24048,24049,24050,24051,24052,24053,24054,24055,
24056,24057,24058,24059,24060,24061,24062,24063,24064,24065,24066,24067,
24068,24069,24070,24071,24072,24073,24074,24075,24076,24077,24078,24079,
24080,24081,24082,24083,24084,24085,24086,24087,24088,24089,24090,24091,
24092,24093,24094,24095,24096,24097,24098,24099,24100,24101,24102,24103,
24104,24105,24106,24107,24108,24109,24110,24111,24112,24113,24114,24115,
24116,24117,24118,24119,24120,24121,24122,24123,24124,24125,24126,24127,
24128,24129,24130,24131,24132,24133,24134,24135,24136,24137,24138,24139,
24140,24141,24142,24143,24144,24145,24146,24147,24148,24149,24150,24151,
24152,24153,24154,24155,24156,24157,24158,24159,24160,24161,24162,24163,
24164,24165,24166,24167,24168,24169,24170,24171,24172,24173,24174,24175,
24176,24177,24178,24179,24180,24181,24182,24183,24184,24185,24186,24187,
24188,24189,24190,24191,24192,24193,24194,24195,24196,24197,24198,24199,
24200,24201,24202,24203,24204,24205,24206,24207,24208,24209,24210,24211,
24212,24213,24214,24215,24216,24217,24218,24219,24220,24221,24222,24223,
24224,24225,24226,24227,24228,24229,24230,24231,24232,24233,24234,24235,
24236,24237,24238,24239,24240,24241,24242,24243,24244,24245,24246,24247,
24248,24249,24250,24251,24252,24253,24254,24255,24256,24257,24258,24259,
24260,24261,24262,24263,24264,24265,24266,24267,24268,24269,24270,24271,
24272,24273,24274,24275,24276,24277,24278,24279,24280,24281,24282,24283,
24284,24285,24286,24287,24288,24289,24290,24291,24292,24293,24294,24295,
24296,24297,24298,24299,24300,24301,24302,24303,24304,24305,24306,24307,
24308,24309,24310,24311,24312,24313,24314,24315,24316,24317,24318,24319,
24320,24321,24322,24323,24324,24325,24326,24327,24328,24329,24330,24331,
24332,24333,24334,24335,24336,24337,24338,24339,24340,24341,24342,24343,
24344,24345,24346,24347,24348,24349,24350,24351,24352,24353,24354,24355,
24356,24357,24358,24359,24360,24361,24362,24363,24364,24365,24366,24367,
24368,24369,24370,24371,24372,24373,24374,24375,24376,24377,24378,24379,
24380,24381,24382,24383,24384,24385,24386,24387,24388,24389,24390,24391,
24392,24393,24394,24395,24396,24397,24398,24399,24400,24401,24402,24403,
24404,24405,24406,24407,24408,24409,24410,24411,24412,24413,24414,24415,
24416,24417,24418,24419,24420,24421,24422,24423,24424,24425,24426,24427,
24428,24429,24430,24431,24432,24433,24434,24435,24436,24437,24438,24439,
24440,24441,24442,24443,24444,24445,24446,24447,24448,24449,24450,24451,
24452,24453,24454,24455,24456,24457,24458,24459,24460,24461,24462,24463,
24464,24465,24466,24467,24468,24469,24470,24471,24472,24473,24474,24475,
24476,24477,24478,24479,24480,24481,24482,24483,24484,24485,24486,24487,
24488,24489,24490,24491,24492,24493,24494,24495,24496,24497,24498,24499,
24500,24501,24502,24503,24504,24505,24506,24507,24508,24509,24510,24511,
24512,24513,24514,24515,24516,24517,24518,24519,24520,24521,24522,24523,
24524,24525,24526,24527,24528,24529,24530,24531,24532,24533,24534,24535,
24536,24537,24538,24539,24540,24541,24542,24543,24544,24545,24546,24547,
24548,24549,24550,24551,24552,24553,24554,24555,24556,24557,24558,24559,
24560,24561,24562,24563,24564,24565,24566,24567,24568,24569,24570,24571,
24572,24573,24574,24575,24576,24577,24578,24579,24580,24581,24582,24583,
24584,24585,24586,24587,24588,24589,24590,24591,24592,24593,24594,24595,
24596,24597,24598,24599,24600,24601,24602,24603,24604,24605,24606,24607,
24608,24609,24610,24611,24612,24613,24614,24615,24616,24617,24618,24619,
24620,24621,24622,24623,24624,24625,24626,24627,24628,24629,24630,24631,
24632,24633,24634,24635,24636,24637,24638,24639,24640,24641,24642,24643,
24644,24645,24646,24647,24648,24649,24650,24651,24652,24653,24654,24655,
24656,24657,24658,24659,24660,24661,24662,24663,24664,24665,24666,24667,
24668,24669,24670,24671,24672,24673,24674,24675,24676,24677,24678,24679,
24680,24681,24682,24683,24684,24685,24686,24687,24688,24689,24690,24691,
24692,24693,24694,24695,24696,24697,24698,24699,24700,24701,24702,24703,
24704,24705,24706,24707,24708,24709,24710,24711,24712,24713,24714,24715,
24716,24717,24718,24719,24720,24721,24722,24723,24724,24725,24726,24727,
24728,24729,24730,24731,24732,24733,24734,24735,24736,24737,24738,24739,
24740,24741,24742,24743,24744,24745,24746,24747,24748,24749,24750,24751,
24752,24753,24754,24755,24756,24757,24758,24759,24760,24761,24762,24763,
24764,24765,24766,24767,24768,24769,24770,24771,24772,24773,24774,24775,
24776,24777,24778,24779,24780,24781,24782,24783,24784,24785,24786,24787,
24788,24789,24790,24791,24792,24793,24794,24795,24796,24797,24798,24799,
24800,24801,24802,24803,24804,24805,24806,24807,24808,24809,24810,24811,
24812,24813,24814,24815,24816,24817,24818,24819,24820,24821,24822,24823,
24824,24825,24826,24827,24828,24829,24830,24831,24832,24833,24834,24835,
24836,24837,24838,24839,24840,24841,24842,24843,24844,24845,24846,24847,
24848,24849,24850,24851,24852,24853,24854,24855,24856,24857,24858,24859,
24860,24861,24862,24863,24864,24865,24866,24867,24868,24869,24870,24871,
24872,24873,24874,24875,24876,24877,24878,24879,24880,24881,24882,24883,
24884,24885,24886,24887,24888,24889,24890,24891,24892,24893,24894,24895,
24896,24897,24898,24899,24900,24901,24902,24903,24904,24905,24906,24907,
24908,24909,24910,24911,24912,24913,24914,24915,24916,24917,24918,24919,
24920,24921,24922,24923,24924,24925,24926,24927,24928,24929,24930,24931,
24932,24933,24934,24935,24936,24937,24938,24939,24940,24941,24942,24943,
24944,24945,24946,24947,24948,24949,24950,24951,24952,24953,24954,24955,
24956,24957,24958,24959,24960,24961,24962,24963,24964,24965,24966,24967,
24968,24969,24970,24971,24972,24973,24974,24975,24976,24977,24978,24979,
24980,24981,24982,24983,24984,24985,24986,24987,24988,24989,24990,24991,
24992,24993,24994,24995,24996,24997,24998,24999,25000,25001,25002,25003,
25004,25005,25006,25007,25008,25009,25010,25011,25012,25013,25014,25015,
25016,25017,25018,25019,25020,25021,25022,25023,25024,25025,25026,25027,
25028,25029,25030,25031,25032,25033,25034,25035,25036,25037,25038,25039,
25040,25041,25042,25043,25044,25045,25046,25047,25048,25049,25050,25051,
25052,25053,25054,25055,25056,25057,25058,25059,25060,25061,25062,25063,
25064,25065,25066,25067,25068,25069,25070,25071,25072,25073,25074,25075,
25076,25077,25078,25079,25080,25081,25082,25083,25084,25085,25086,25087,
25088,25089,25090,25091,25092,25093,25094,25095,25096,25097,25098,25099,
25100,25101,25102,25103,25104,25105,25106,25107,25108,25109,25110,25111,
25112,25113,25114,25115,25116,25117,25118,25119,25120,25121,25122,25123,
25124,25125,25126,25127,25128,25129,25130,25131,25132,25133,25134,25135,
25136,25137,25138,25139,25140,25141,25142,25143,25144,25145,25146,25147,
25148,25149,25150,25151,25152,25153,25154,25155,25156,25157,25158,25159,
25160,25161,25162,25163,25164,25165,25166,25167,25168,25169,25170,25171,
25172,25173,25174,25175,25176,25177,25178,25179,25180,25181,25182,25183,
25184,25185,25186,25187,25188,25189,25190,25191,25192,25193,25194,25195,
25196,25197,25198,25199,25200,25201,25202,25203,25204,25205,25206,25207,
25208,25209,25210,25211,25212,25213,25214,25215,25216,25217,25218,25219,
25220,25221,25222,25223,25224,25225,25226,25227,25228,25229,25230,25231,
25232,25233,25234,25235,25236,25237,25238,25239,25240,25241,25242,25243,
25244,25245,25246,25247,25248,25249,25250,25251,25252,25253,25254,25255,
25256,25257,25258,25259,25260,25261,25262,25263,25264,25265,25266,25267,
25268,25269,25270,25271,25272,25273,25274,25275,25276,25277,25278,25279,
25280,25281,25282,25283,25284,25285,25286,25287,25288,25289,25290,25291,
25292,25293,25294,25295,25296,25297,25298,25299,25300,25301,25302,25303,
25304,25305,25306,25307,25308,25309,25310,25311,25312,25313,25314,25315,
25316,25317,25318,25319,25320,25321,25322,25323,25324,25325,25326,25327,
25328,25329,25330,25331,25332,25333,25334,25335,25336,25337,25338,25339,
25340,25341,25342,25343,25344,25345,25346,25347,25348,25349,25350,25351,
25352,25353,25354,25355,25356,25357,25358,25359,25360,25361,25362,25363,
25364,25365,25366,25367,25368,25369,25370,25371,25372,25373,25374,25375,
25376,25377,25378,25379,25380,25381,25382,25383,25384,25385,25386,25387,
25388,25389,25390,25391,25392,25393,25394,25395,25396,25397,25398,25399,
25400,25401,25402,25403,25404,25405,25406,25407,25408,25409,25410,25411,
25412,25413,25414,25415,25416,25417,25418,25419,25420,25421,25422,25423,
25424,25425,25426,25427,25428,25429,25430,25431,25432,25433,25434,25435,
25436,25437,25438,25439,25440,25441,25442,25443,25444,25445,25446,25447,
25448,25449,25450,25451,25452,25453,25454,25455,25456,25457,25458,25459,
25460,25461,25462,25463,25464,25465,25466,25467,25468,25469,25470,25471,
25472,25473,25474,25475,25476,25477,25478,25479,25480,25481,25482,25483,
25484,25485,25486,25487,25488,25489,25490,25491,25492,25493,25494,25495,
25496,25497,25498,25499,25500,25501,25502,25503,25504,25505,25506,25507,
25508,25509,25510,25511,25512,25513,25514,25515,25516,25517,25518,25519,
25520,25521,25522,25523,25524,25525,25526,25527,25528,25529,25530,25531,
25532,25533,25534,25535,25536,25537,25538,25539,25540,25541,25542,25543,
25544,25545,25546,25547,25548,25549,25550,25551,25552,25553,25554,25555,
25556,25557,25558,25559,25560,25561,25562,25563,25564,25565,25566,25567,
25568,25569,25570,25571,25572,25573,25574,25575,25576,25577,25578,25579,
25580,25581,25582,25583,25584,25585,25586,25587,25588,25589,25590,25591,
25592,25593,25594,25595,25596,25597,25598,25599,25600,25601,25602,25603,
25604,25605,25606,25607,25608,25609,25610,25611,25612,25613,25614,25615,
25616,25617,25618,25619,25620,25621,25622,25623,25624,25625,25626,25627,
25628,25629,25630,25631,25632,25633,25634,25635,25636,25637,25638,25639,
25640,25641,25642,25643,25644,25645,25646,25647,25648,25649,25650,25651,
25652,25653,25654,25655,25656,25657,25658,25659,25660,25661,25662,25663,
25664,25665,25666,25667,25668,25669,25670,25671,25672,25673,25674,25675,
25676,25677,25678,25679,25680,25681,25682,25683,25684,25685,25686,25687,
25688,25689,25690,25691,25692,25693,25694,25695,25696,25697,25698,25699,
25700,25701,25702,25703,25704,25705,25706,25707,25708,25709,25710,25711,
25712,25713,25714,25715,25716,25717,25718,25719,25720,25721,25722,25723,
25724,25725,25726,25727,25728,25729,25730,25731,25732,25733,25734,25735,
25736,25737,25738,25739,25740,25741,25742,25743,25744,25745,25746,25747,
25748,25749,25750,25751,25752,25753,25754,25755,25756,25757,25758,25759,
25760,25761,25762,25763,25764,25765,25766,25767,25768,25769,25770,25771,
25772,25773,25774,25775,25776,25777,25778,25779,25780,25781,25782,25783,
25784,25785,25786,25787,25788,25789,25790,25791,25792,25793,25794,25795,
25796,25797,25798,25799,25800,25801,25802,25803,25804,25805,25806,25807,
25808,25809,25810,25811,25812,25813,25814,25815,25816,25817,25818,25819,
25820,25821,25822,25823,25824,25825,25826,25827,25828,25829,25830,25831,
25832,25833,25834,25835,25836,25837,25838,25839,25840,25841,25842,25843,
25844,25845,25846,25847,25848,25849,25850,25851,25852,25853,25854,25855,
25856,25857,25858,25859,25860,25861,25862,25863,25864,25865,25866,25867,
25868,25869,25870,25871,25872,25873,25874,25875,25876,25877,25878,25879,
25880,25881,25882,25883,25884,25885,25886,25887,25888,25889,25890,25891,
25892,25893,25894,25895,25896,25897,25898,25899,25900,25901,25902,25903,
25904,25905,25906,25907,25908,25909,25910,25911,25912,25913,25914,25915,
25916,25917,25918,25919,25920,25921,25922,25923,25924,25925,25926,25927,
25928,25929,25930,25931,25932,25933,25934,25935,25936,25937,25938,25939,
25940,25941,25942,25943,25944,25945,25946,25947,25948,25949,25950,25951,
25952,25953,25954,25955,25956,25957,25958,25959,25960,25961,25962,25963,
25964,25965,25966,25967,25968,25969,25970,25971,25972,25973,25974,25975,
25976,25977,25978,25979,25980,25981,25982,25983,25984,25985,25986,25987,
25988,25989,25990,25991,25992,25993,25994,25995,25996,25997,25998,25999,
26000,26001,26002,26003,26004,26005,26006,26007,26008,26009,26010,26011,
26012,26013,26014,26015,26016,26017,26018,26019,26020,26021,26022,26023,
26024,26025,26026,26027,26028,26029,26030,26031,26032,26033,26034,26035,
26036,26037,26038,26039,26040,26041,26042,26043,26044,26045,26046,26047,
26048,26049,26050,26051,26052,26053,26054,26055,26056,26057,26058,26059,
26060,26061,26062,26063,26064,26065,26066,26067,26068,26069,26070,26071,
26072,26073,26074,26075,26076,26077,26078,26079,26080,26081,26082,26083,
26084,26085,26086,26087,26088,26089,26090,26091,26092,26093,26094,26095,
26096,26097,26098,26099,26100,26101,26102,26103,26104,26105,26106,26107,
26108,26109,26110,26111,26112,26113,26114,26115,26116,26117,26118,26119,
26120,26121,26122,26123,26124,26125,26126,26127,26128,26129,26130,26131,
26132,26133,26134,26135,26136,26137,26138,26139,26140,26141,26142,26143,
26144,26145,26146,26147,26148,26149,26150,26151,26152,26153,26154,26155,
26156,26157,26158,26159,26160,26161,26162,26163,26164,26165,26166,26167,
26168,26169,26170,26171,26172,26173,26174,26175,26176,26177,26178,26179,
26180,26181,26182,26183,26184,26185,26186,26187,26188,26189,26190,26191,
26192,26193,26194,26195,26196,26197,26198,26199,26200,26201,26202,26203,
26204,26205,26206,26207,26208,26209,26210,26211,26212,26213,26214,26215,
26216,26217,26218,26219,26220,26221,26222,26223,26224,26225,26226,26227,
26228,26229,26230,26231,26232,26233,26234,26235,26236,26237,26238,26239,
26240,26241,26242,26243,26244,26245,26246,26247,26248,26249,26250,26251,
26252,26253,26254,26255,26256,26257,26258,26259,26260,26261,26262,26263,
26264,26265,26266,26267,26268,26269,26270,26271,26272,26273,26274,26275,
26276,26277,26278,26279,26280,26281,26282,26283,26284,26285,26286,26287,
26288,26289,26290,26291,26292,26293,26294,26295,26296,26297,26298,26299,
26300,26301,26302,26303,26304,26305,26306,26307,26308,26309,26310,26311,
26312,26313,26314,26315,26316,26317,26318,26319,26320,26321,26322,26323,
26324,26325,26326,26327,26328,26329,26330,26331,26332,26333,26334,26335,
26336,26337,26338,26339,26340,26341,26342,26343,26344,26345,26346,26347,
26348,26349,26350,26351,26352,26353,26354,26355,26356,26357,26358,26359,
26360,26361,26362,26363,26364,26365,26366,26367,26368,26369,26370,26371,
26372,26373,26374,26375,26376,26377,26378,26379,26380,26381,26382,26383,
26384,26385,26386,26387,26388,26389,26390,26391,26392,26393,26394,26395,
26396,26397,26398,26399,26400,26401,26402,26403,26404,26405,26406,26407,
26408,26409,26410,26411,26412,26413,26414,26415,26416,26417,26418,26419,
26420,26421,26422,26423,26424,26425,26426,26427,26428,26429,26430,26431,
26432,26433,26434,26435,26436,26437,26438,26439,26440,26441,26442,26443,
26444,26445,26446,26447,26448,26449,26450,26451,26452,26453,26454,26455,
26456,26457,26458,26459,26460,26461,26462,26463,26464,26465,26466,26467,
26468,26469,26470,26471,26472,26473,26474,26475,26476,26477,26478,26479,
26480,26481,26482,26483,26484,26485,26486,26487,26488,26489,26490,26491,
26492,26493,26494,26495,26496,26497,26498,26499,26500,26501,26502,26503,
26504,26505,26506,26507,26508,26509,26510,26511,26512,26513,26514,26515,
26516,26517,26518,26519,26520,26521,26522,26523,26524,26525,26526,26527,
26528,26529,26530,26531,26532,26533,26534,26535,26536,26537,26538,26539,
26540,26541,26542,26543,26544,26545,26546,26547,26548,26549,26550,26551,
26552,26553,26554,26555,26556,26557,26558,26559,26560,26561,26562,26563,
26564,26565,26566,26567,26568,26569,26570,26571,26572,26573,26574,26575,
26576,26577,26578,26579,26580,26581,26582,26583,26584,26585,26586,26587,
26588,26589,26590,26591,26592,26593,26594,26595,26596,26597,26598,26599,
26600,26601,26602,26603,26604,26605,26606,26607,26608,26609,26610,26611,
26612,26613,26614,26615,26616,26617,26618,26619,26620,26621,26622,26623,
26624,26625,26626,26627,26628,26629,26630,26631,26632,26633,26634,26635,
26636,26637,26638,26639,26640,26641,26642,26643,26644,26645,26646,26647,
26648,26649,26650,26651,26652,26653,26654,26655,26656,26657,26658,26659,
26660,26661,26662,26663,26664,26665,26666,26667,26668,26669,26670,26671,
26672,26673,26674,26675,26676,26677,26678,26679,26680,26681,26682,26683,
26684,26685,26686,26687,26688,26689,26690,26691,26692,26693,26694,26695,
26696,26697,26698,26699,26700,26701,26702,26703,26704,26705,26706,26707,
26708,26709,26710,26711,26712,26713,26714,26715,26716,26717,26718,26719,
26720,26721,26722,26723,26724,26725,26726,26727,26728,26729,26730,26731,
26732,26733,26734,26735,26736,26737,26738,26739,26740,26741,26742,26743,
26744,26745,26746,26747,26748,26749,26750,26751,26752,26753,26754,26755,
26756,26757,26758,26759,26760,26761,26762,26763,26764,26765,26766,26767,
26768,26769,26770,26771,26772,26773,26774,26775,26776,26777,26778,26779,
26780,26781,26782,26783,26784,26785,26786,26787,26788,26789,26790,26791,
26792,26793,26794,26795,26796,26797,26798,26799,26800,26801,26802,26803,
26804,26805,26806,26807,26808,26809,26810,26811,26812,26813,26814,26815,
26816,26817,26818,26819,26820,26821,26822,26823,26824,26825,26826,26827,
26828,26829,26830,26831,26832,26833,26834,26835,26836,26837,26838,26839,
26840,26841,26842,26843,26844,26845,26846,26847,26848,26849,26850,26851,
26852,26853,26854,26855,26856,26857,26858,26859,26860,26861,26862,26863,
26864,26865,26866,26867,26868,26869,26870,26871,26872,26873,26874,26875,
26876,26877,26878,26879,26880,26881,26882,26883,26884,26885,26886,26887,
26888,26889,26890,26891,26892,26893,26894,26895,26896,26897,26898,26899,
26900,26901,26902,26903,26904,26905,26906,26907,26908,26909,26910,26911,
26912,26913,26914,26915,26916,26917,26918,26919,26920,26921,26922,26923,
26924,26925,26926,26927,26928,26929,26930,26931,26932,26933,26934,26935,
26936,26937,26938,26939,26940,26941,26942,26943,26944,26945,26946,26947,
26948,26949,26950,26951,26952,26953,26954,26955,26956,26957,26958,26959,
26960,26961,26962,26963,26964,26965,26966,26967,26968,26969,26970,26971,
26972,26973,26974,26975,26976,26977,26978,26979,26980,26981,26982,26983,
26984,26985,26986,26987,26988,26989,26990,26991,26992,26993,26994,26995,
26996,26997,26998,26999,27000,27001,27002,27003,27004,27005,27006,27007,
27008,27009,27010,27011,27012,27013,27014,27015,27016,27017,27018,27019,
27020,27021,27022,27023,27024,27025,27026,27027,27028,27029,27030,27031,
27032,27033,27034,27035,27036,27037,27038,27039,27040,27041,27042,27043,
27044,27045,27046,27047,27048,27049,27050,27051,27052,27053,27054,27055,
27056,27057,27058,27059,27060,27061,27062,27063,27064,27065,27066,27067,
27068,27069,27070,27071,27072,27073,27074,27075,27076,27077,27078,27079,
27080,27081,27082,27083,27084,27085,27086,27087,27088,27089,27090,27091,
27092,27093,27094,27095,27096,27097,27098,27099,27100,27101,27102,27103,
27104,27105,27106,27107,27108,27109,27110,27111,27112,27113,27114,27115,
27116,27117,27118,27119,27120,27121,27122,27123,27124,27125,27126,27127,
27128,27129,27130,27131,27132,27133,27134,27135,27136,27137,27138,27139,
27140,27141,27142,27143,27144,27145,27146,27147,27148,27149,27150,27151,
27152,27153,27154,27155,27156,27157,27158,27159,27160,27161,27162,27163,
27164,27165,27166,27167,27168,27169,27170,27171,27172,27173,27174,27175,
27176,27177,27178,27179,27180,27181,27182,27183,27184,27185,27186,27187,
27188,27189,27190,27191,27192,27193,27194,27195,27196,27197,27198,27199,
27200,27201,27202,27203,27204,27205,27206,27207,27208,27209,27210,27211,
27212,27213,27214,27215,27216,27217,27218,27219,27220,27221,27222,27223,
27224,27225,27226,27227,27228,27229,27230,27231,27232,27233,27234,27235,
27236,27237,27238,27239,27240,27241,27242,27243,27244,27245,27246,27247,
27248,27249,27250,27251,27252,27253,27254,27255,27256,27257,27258,27259,
27260,27261,27262,27263,27264,27265,27266,27267,27268,27269,27270,27271,
27272,27273,27274,27275,27276,27277,27278,27279,27280,27281,27282,27283,
27284,27285,27286,27287,27288,27289,27290,27291,27292,27293,27294,27295,
27296,27297,27298,27299,27300,27301,27302,27303,27304,27305,27306,27307,
27308,27309,27310,27311,27312,27313,27314,27315,27316,27317,27318,27319,
27320,27321,27322,27323,27324,27325,27326,27327,27328,27329,27330,27331,
27332,27333,27334,27335,27336,27337,27338,27339,27340,27341,27342,27343,
27344,27345,27346,27347,27348,27349,27350,27351,27352,27353,27354,27355,
27356,27357,27358,27359,27360,27361,27362,27363,27364,27365,27366,27367,
27368,27369,27370,27371,27372,27373,27374,27375,27376,27377,27378,27379,
27380,27381,27382,27383,27384,27385,27386,27387,27388,27389,27390,27391,
27392,27393,27394,27395,27396,27397,27398,27399,27400,27401,27402,27403,
27404,27405,27406,27407,27408,27409,27410,27411,27412,27413,27414,27415,
27416,27417,27418,27419,27420,27421,27422,27423,27424,27425,27426,27427,
27428,27429,27430,27431,27432,27433,27434,27435,27436,27437,27438,27439,
27440,27441,27442,27443,27444,27445,27446,27447,27448,27449,27450,27451,
27452,27453,27454,27455,27456,27457,27458,27459,27460,27461,27462,27463,
27464,27465,27466,27467,27468,27469,27470,27471,27472,27473,27474,27475,
27476,27477,27478,27479,27480,27481,27482,27483,27484,27485,27486,27487,
27488,27489,27490,27491,27492,27493,27494,27495,27496,27497,27498,27499,
27500,27501,27502,27503,27504,27505,27506,27507,27508,27509,27510,27511,
27512,27513,27514,27515,27516,27517,27518,27519,27520,27521,27522,27523,
27524,27525,27526,27527,27528,27529,27530,27531,27532,27533,27534,27535,
27536,27537,27538,27539,27540,27541,27542,27543,27544,27545,27546,27547,
27548,27549,27550,27551,27552,27553,27554,27555,27556,27557,27558,27559,
27560,27561,27562,27563,27564,27565,27566,27567,27568,27569,27570,27571,
27572,27573,27574,27575,27576,27577,27578,27579,27580,27581,27582,27583,
27584,27585,27586,27587,27588,27589,27590,27591,27592,27593,27594,27595,
27596,27597,27598,27599,27600,27601,27602,27603,27604,27605,27606,27607,
27608,27609,27610,27611,27612,27613,27614,27615,27616,27617,27618,27619,
27620,27621,27622,27623,27624,27625,27626,27627,27628,27629,27630,27631,
27632,27633,27634,27635,27636,27637,27638,27639,27640,27641,27642,27643,
27644,27645,27646,27647,27648,27649,27650,27651,27652,27653,27654,27655,
27656,27657,27658,27659,27660,27661,27662,27663,27664,27665,27666,27667,
27668,27669,27670,27671,27672,27673,27674,27675,27676,27677,27678,27679,
27680,27681,27682,27683,27684,27685,27686,27687,27688,27689,27690,27691,
27692,27693,27694,27695,27696,27697,27698,27699,27700,27701,27702,27703,
27704,27705,27706,27707,27708,27709,27710,27711,27712,27713,27714,27715,
27716,27717,27718,27719,27720,27721,27722,27723,27724,27725,27726,27727,
27728,27729,27730,27731,27732,27733,27734,27735,27736,27737,27738,27739,
27740,27741,27742,27743,27744,27745,27746,27747,27748,27749,27750,27751,
27752,27753,27754,27755,27756,27757,27758,27759,27760,27761,27762,27763,
27764,27765,27766,27767,27768,27769,27770,27771,27772,27773,27774,27775,
27776,27777,27778,27779,27780,27781,27782,27783,27784,27785,27786,27787,
27788,27789,27790,27791,27792,27793,27794,27795,27796,27797,27798,27799,
27800,27801,27802,27803,27804,27805,27806,27807,27808,27809,27810,27811,
27812,27813,27814,27815,27816,27817,27818,27819,27820,27821,27822,27823,
27824,27825,27826,27827,27828,27829,27830,27831,27832,27833,27834,27835,
27836,27837,27838,27839,27840,27841,27842,27843,27844,27845,27846,27847,
27848,27849,27850,27851,27852,27853,27854,27855,27856,27857,27858,27859,
27860,27861,27862,27863,27864,27865,27866,27867,27868,27869,27870,27871,
27872,27873,27874,27875,27876,27877,27878,27879,27880,27881,27882,27883,
27884,27885,27886,27887,27888,27889,27890,27891,27892,27893,27894,27895,
27896,27897,27898,27899,27900,27901,27902,27903,27904,27905,27906,27907,
27908,27909,27910,27911,27912,27913,27914,27915,27916,27917,27918,27919,
27920,27921,27922,27923,27924,27925,27926,27927,27928,27929,27930,27931,
27932,27933,27934,27935,27936,27937,27938,27939,27940,27941,27942,27943,
27944,27945,27946,27947,27948,27949,27950,27951,27952,27953,27954,27955,
27956,27957,27958,27959,27960,27961,27962,27963,27964,27965,27966,27967,
27968,27969,27970,27971,27972,27973,27974,27975,27976,27977,27978,27979,
27980,27981,27982,27983,27984,27985,27986,27987,27988,27989,27990,27991,
27992,27993,27994,27995,27996,27997,27998,27999,28000,28001,28002,28003,
28004,28005,28006,28007,28008,28009,28010,28011,28012,28013,28014,28015,
28016,28017,28018,28019,28020,28021,28022,28023,28024,28025,28026,28027,
28028,28029,28030,28031,28032,28033,28034,28035,28036,28037,28038,28039,
28040,28041,28042,28043,28044,28045,28046,28047,28048,28049,28050,28051,
28052,28053,28054,28055,28056,28057,28058,28059,28060,28061,28062,28063,
28064,28065,28066,28067,28068,28069,28070,28071,28072,28073,28074,28075,
28076,28077,28078,28079,28080,28081,28082,28083,28084,28085,28086,28087,
28088,28089,28090,28091,28092,28093,28094,28095,28096,28097,28098,28099,
28100,28101,28102,28103,28104,28105,28106,28107,28108,28109,28110,28111,
28112,28113,28114,28115,28116,28117,28118,28119,28120,28121,28122,28123,
28124,28125,28126,28127,28128,28129,28130,28131,28132,28133,28134,28135,
28136,28137,28138,28139,28140,28141,28142,28143,28144,28145,28146,28147,
28148,28149,28150,28151,28152,28153,28154,28155,28156,28157,28158,28159,
28160,28161,28162,28163,28164,28165,28166,28167,28168,28169,28170,28171,
28172,28173,28174,28175,28176,28177,28178,28179,28180,28181,28182,28183,
28184,28185,28186,28187,28188,28189,28190,28191,28192,28193,28194,28195,
28196,28197,28198,28199,28200,28201,28202,28203,28204,28205,28206,28207,
28208,28209,28210,28211,28212,28213,28214,28215,28216,28217,28218,28219,
28220,28221,28222,28223,28224,28225,28226,28227,28228,28229,28230,28231,
28232,28233,28234,28235,28236,28237,28238,28239,28240,28241,28242,28243,
28244,28245,28246,28247,28248,28249,28250,28251,28252,28253,28254,28255,
28256,28257,28258,28259,28260,28261,28262,28263,28264,28265,28266,28267,
28268,28269,28270,28271,28272,28273,28274,28275,28276,28277,28278,28279,
28280,28281,28282,28283,28284,28285,28286,28287,28288,28289,28290,28291,
28292,28293,28294,28295,28296,28297,28298,28299,28300,28301,28302,28303,
28304,28305,28306,28307,28308,28309,28310,28311,28312,28313,28314,28315,
28316,28317,28318,28319,28320,28321,28322,28323,28324,28325,28326,28327,
28328,28329,28330,28331,28332,28333,28334,28335,28336,28337,28338,28339,
28340,28341,28342,28343,28344,28345,28346,28347,28348,28349,28350,28351,
28352,28353,28354,28355,28356,28357,28358,28359,28360,28361,28362,28363,
28364,28365,28366,28367,28368,28369,28370,28371,28372,28373,28374,28375,
28376,28377,28378,28379,28380,28381,28382,28383,28384,28385,28386,28387,
28388,28389,28390,28391,28392,28393,28394,28395,28396,28397,28398,28399,
28400,28401,28402,28403,28404,28405,28406,28407,28408,28409,28410,28411,
28412,28413,28414,28415,28416,28417,28418,28419,28420,28421,28422,28423,
28424,28425,28426,28427,28428,28429,28430,28431,28432,28433,28434,28435,
28436,28437,28438,28439,28440,28441,28442,28443,28444,28445,28446,28447,
28448,28449,28450,28451,28452,28453,28454,28455,28456,28457,28458,28459,
28460,28461,28462,28463,28464,28465,28466,28467,28468,28469,28470,28471,
28472,28473,28474,28475,28476,28477,28478,28479,28480,28481,28482,28483,
28484,28485,28486,28487,28488,28489,28490,28491,28492,28493,28494,28495,
28496,28497,28498,28499,28500,28501,28502,28503,28504,28505,28506,28507,
28508,28509,28510,28511,28512,28513,28514,28515,28516,28517,28518,28519,
28520,28521,28522,28523,28524,28525,28526,28527,28528,28529,28530,28531,
28532,28533,28534,28535,28536,28537,28538,28539,28540,28541,28542,28543,
28544,28545,28546,28547,28548,28549,28550,28551,28552,28553,28554,28555,
28556,28557,28558,28559,28560,28561,28562,28563,28564,28565,28566,28567,
28568,28569,28570,28571,28572,28573,28574,28575,28576,28577,28578,28579,
28580,28581,28582,28583,28584,28585,28586,28587,28588,28589,28590,28591,
28592,28593,28594,28595,28596,28597,28598,28599,28600,28601,28602,28603,
28604,28605,28606,28607,28608,28609,28610,28611,28612,28613,28614,28615,
28616,28617,28618,28619,28620,28621,28622,28623,28624,28625,28626,28627,
28628,28629,28630,28631,28632,28633,28634,28635,28636,28637,28638,28639,
28640,28641,28642,28643,28644,28645,28646,28647,28648,28649,28650,28651,
28652,28653,28654,28655,28656,28657,28658,28659,28660,28661,28662,28663,
28664,28665,28666,28667,28668,28669,28670,28671,28672,28673,28674,28675,
28676,28677,28678,28679,28680,28681,28682,28683,28684,28685,28686,28687,
28688,28689,28690,28691,28692,28693,28694,28695,28696,28697,28698,28699,
28700,28701,28702,28703,28704,28705,28706,28707,28708,28709,28710,28711,
28712,28713,28714,28715,28716,28717,28718,28719,28720,28721,28722,28723,
28724,28725,28726,28727,28728,28729,28730,28731,28732,28733,28734,28735,
28736,28737,28738,28739,28740,28741,28742,28743,28744,28745,28746,28747,
28748,28749,28750,28751,28752,28753,28754,28755,28756,28757,28758,28759,
28760,28761,28762,28763,28764,28765,28766,28767,28768,28769,28770,28771,
28772,28773,28774,28775,28776,28777,28778,28779,28780,28781,28782,28783,
28784,28785,28786,28787,28788,28789,28790,28791,28792,28793,28794,28795,
28796,28797,28798,28799,28800,28801,28802,28803,28804,28805,28806,28807,
28808,28809,28810,28811,28812,28813,28814,28815,28816,28817,28818,28819,
28820,28821,28822,28823,28824,28825,28826,28827,28828,28829,28830,28831,
28832,28833,28834,28835,28836,28837,28838,28839,28840,28841,28842,28843,
28844,28845,28846,28847,28848,28849,28850,28851,28852,28853,28854,28855,
28856,28857,28858,28859,28860,28861,28862,28863,28864,28865,28866,28867,
28868,28869,28870,28871,28872,28873,28874,28875,28876,28877,28878,28879,
28880,28881,28882,28883,28884,28885,28886,28887,28888,28889,28890,28891,
28892,28893,28894,28895,28896,28897,28898,28899,28900,28901,28902,28903,
28904,28905,28906,28907,28908,28909,28910,28911,28912,28913,28914,28915,
28916,28917,28918,28919,28920,28921,28922,28923,28924,28925,28926,28927,
28928,28929,28930,28931,28932,28933,28934,28935,28936,28937,28938,28939,
28940,28941,28942,28943,28944,28945,28946,28947,28948,28949,28950,28951,
28952,28953,28954,28955,28956,28957,28958,28959,28960,28961,28962,28963,
28964,28965,28966,28967,28968,28969,28970,28971,28972,28973,28974,28975,
28976,28977,28978,28979,28980,28981,28982,28983,28984,28985,28986,28987,
28988,28989,28990,28991,28992,28993,28994,28995,28996,28997,28998,28999,
29000,29001,29002,29003,29004,29005,29006,29007,29008,29009,29010,29011,
29012,29013,29014,29015,29016,29017,29018,29019,29020,29021,29022,29023,
29024,29025,29026,29027,29028,29029,29030,29031,29032,29033,29034,29035,
29036,29037,29038,29039,29040,29041,29042,29043,29044,29045,29046,29047,
29048,29049,29050,29051,29052,29053,29054,29055,29056,29057,29058,29059,
29060,29061,29062,29063,29064,29065,29066,29067,29068,29069,29070,29071,
29072,29073,29074,29075,29076,29077,29078,29079,29080,29081,29082,29083,
29084,29085,29086,29087,29088,29089,29090,29091,29092,29093,29094,29095,
29096,29097,29098,29099,29100,29101,29102,29103,29104,29105,29106,29107,
29108,29109,29110,29111,29112,29113,29114,29115,29116,29117,29118,29119,
29120,29121,29122,29123,29124,29125,29126,29127,29128,29129,29130,29131,
29132,29133,29134,29135,29136,29137,29138,29139,29140,29141,29142,29143,
29144,29145,29146,29147,29148,29149,29150,29151,29152,29153,29154,29155,
29156,29157,29158,29159,29160,29161,29162,29163,29164,29165,29166,29167,
29168,29169,29170,29171,29172,29173,29174,29175,29176,29177,29178,29179,
29180,29181,29182,29183,29184,29185,29186,29187,29188,29189,29190,29191,
29192,29193,29194,29195,29196,29197,29198,29199,29200,29201,29202,29203,
29204,29205,29206,29207,29208,29209,29210,29211,29212,29213,29214,29215,
29216,29217,29218,29219,29220,29221,29222,29223,29224,29225,29226,29227,
29228,29229,29230,29231,29232,29233,29234,29235,29236,29237,29238,29239,
29240,29241,29242,29243,29244,29245,29246,29247,29248,29249,29250,29251,
29252,29253,29254,29255,29256,29257,29258,29259,29260,29261,29262,29263,
29264,29265,29266,29267,29268,29269,29270,29271,29272,29273,29274,29275,
29276,29277,29278,29279,29280,29281,29282,29283,29284,29285,29286,29287,
29288,29289,29290,29291,29292,29293,29294,29295,29296,29297,29298,29299,
29300,29301,29302,29303,29304,29305,29306,29307,29308,29309,29310,29311,
29312,29313,29314,29315,29316,29317,29318,29319,29320,29321,29322,29323,
29324,29325,29326,29327,29328,29329,29330,29331,29332,29333,29334,29335,
29336,29337,29338,29339,29340,29341,29342,29343,29344,29345,29346,29347,
29348,29349,29350,29351,29352,29353,29354,29355,29356,29357,29358,29359,
29360,29361,29362,29363,29364,29365,29366,29367,29368,29369,29370,29371,
29372,29373,29374,29375,29376,29377,29378,29379,29380,29381,29382,29383,
29384,29385,29386,29387,29388,29389,29390,29391,29392,29393,29394,29395,
29396,29397,29398,29399,29400,29401,29402,29403,29404,29405,29406,29407,
29408,29409,29410,29411,29412,29413,29414,29415,29416,29417,29418,29419,
29420,29421,29422,29423,29424,29425,29426,29427,29428,29429,29430,29431,
29432,29433,29434,29435,29436,29437,29438,29439,29440,29441,29442,29443,
29444,29445,29446,29447,29448,29449,29450,29451,29452,29453,29454,29455,
29456,29457,29458,29459,29460,29461,29462,29463,29464,29465,29466,29467,
29468,29469,29470,29471,29472,29473,29474,29475,29476,29477,29478,29479,
29480,29481,29482,29483,29484,29485,29486,29487,29488,29489,29490,29491,
29492,29493,29494,29495,29496,29497,29498,29499,29500,29501,29502,29503,
29504,29505,29506,29507,29508,29509,29510,29511,29512,29513,29514,29515,
29516,29517,29518,29519,29520,29521,29522,29523,29524,29525,29526,29527,
29528,29529,29530,29531,29532,29533,29534,29535,29536,29537,29538,29539,
29540,29541,29542,29543,29544,29545,29546,29547,29548,29549,29550,29551,
29552,29553,29554,29555,29556,29557,29558,29559,29560,29561,29562,29563,
29564,29565,29566,29567,29568,29569,29570,29571,29572,29573,29574,29575,
29576,29577,29578,29579,29580,29581,29582,29583,29584,29585,29586,29587,
29588,29589,29590,29591,29592,29593,29594,29595,29596,29597,29598,29599,
29600,29601,29602,29603,29604,29605,29606,29607,29608,29609,29610,29611,
29612,29613,29614,29615,29616,29617,29618,29619,29620,29621,29622,29623,
29624,29625,29626,29627,29628,29629,29630,29631,29632,29633,29634,29635,
29636,29637,29638,29639,29640,29641,29642,29643,29644,29645,29646,29647,
29648,29649,29650,29651,29652,29653,29654,29655,29656,29657,29658,29659,
29660,29661,29662,29663,29664,29665,29666,29667,29668,29669,29670,29671,
29672,29673,29674,29675,29676,29677,29678,29679,29680,29681,29682,29683,
29684,29685,29686,29687,29688,29689,29690,29691,29692,29693,29694,29695,
29696,29697,29698,29699,29700,29701,29702,29703,29704,29705,29706,29707,
29708,29709,29710,29711,29712,29713,29714,29715,29716,29717,29718,29719,
29720,29721,29722,29723,29724,29725,29726,29727,29728,29729,29730,29731,
29732,29733,29734,29735,29736,29737,29738,29739,29740,29741,29742,29743,
29744,29745,29746,29747,29748,29749,29750,29751,29752,29753,29754,29755,
29756,29757,29758,29759,29760,29761,29762,29763,29764,29765,29766,29767,
29768,29769,29770,29771,29772,29773,29774,29775,29776,29777,29778,29779,
29780,29781,29782,29783,29784,29785,29786,29787,29788,29789,29790,29791,
29792,29793,29794,29795,29796,29797,29798,29799,29800,29801,29802,29803,
29804,29805,29806,29807,29808,29809,29810,29811,29812,29813,29814,29815,
29816,29817,29818,29819,29820,29821,29822,29823,29824,29825,29826,29827,
29828,29829,29830,29831,29832,29833,29834,29835,29836,29837,29838,29839,
29840,29841,29842,29843,29844,29845,29846,29847,29848,29849,29850,29851,
29852,29853,29854,29855,29856,29857,29858,29859,29860,29861,29862,29863,
29864,29865,29866,29867,29868,29869,29870,29871,29872,29873,29874,29875,
29876,29877,29878,29879,29880,29881,29882,29883,29884,29885,29886,29887,
29888,29889,29890,29891,29892,29893,29894,29895,29896,29897,29898,29899,
29900,29901,29902,29903,29904,29905,29906,29907,29908,29909,29910,29911,
29912,29913,29914,29915,29916,29917,29918,29919,29920,29921,29922,29923,
29924,29925,29926,29927,29928,29929,29930,29931,29932,29933,29934,29935,
29936,29937,29938,29939,29940,29941,29942,29943,29944,29945,29946,29947,
29948,29949,29950,29951,29952,29953,29954,29955,29956,29957,29958,29959,
29960,29961,29962,29963,29964,29965,29966,29967,29968,29969,29970,29971,
29972,29973,29974,29975,29976,29977,29978,29979,29980,29981,29982,29983,
29984,29985,29986,29987,29988,29989,29990,29991,29992,29993,29994,29995,
29996,29997,29998,29999,30000,30001,30002,30003,30004,30005,30006,30007,
30008,30009,30010,30011,30012,30013,30014,30015,30016,30017,30018,30019,
30020,30021,30022,30023,30024,30025,30026,30027,30028,30029,30030,30031,
30032,30033,30034,30035,30036,30037,30038,30039,30040,30041,30042,30043,
30044,30045,30046,30047,30048,30049,30050,30051,30052,30053,30054,30055,
30056,30057,30058,30059,30060,30061,30062,30063,30064,30065,30066,30067,
30068,30069,30070,30071,30072,30073,30074,30075,30076,30077,30078,30079,
30080,30081,30082,30083,30084,30085,30086,30087,30088,30089,30090,30091,
30092,30093,30094,30095,30096,30097,30098,30099,30100,30101,30102,30103,
30104,30105,30106,30107,30108,30109,30110,30111,30112,30113,30114,30115,
30116,30117,30118,30119,30120,30121,30122,30123,30124,30125,30126,30127,
30128,30129,30130,30131,30132,30133,30134,30135,30136,30137,30138,30139,
30140,30141,30142,30143,30144,30145,30146,30147,30148,30149,30150,30151,
30152,30153,30154,30155,30156,30157,30158,30159,30160,30161,30162,30163,
30164,30165,30166,30167,30168,30169,30170,30171,30172,30173,30174,30175,
30176,30177,30178,30179,30180,30181,30182,30183,30184,30185,30186,30187,
30188,30189,30190,30191,30192,30193,30194,30195,30196,30197,30198,30199,
30200,30201,30202,30203,30204,30205,30206,30207,30208,30209,30210,30211,
30212,30213,30214,30215,30216,30217,30218,30219,30220,30221,30222,30223,
30224,30225,30226,30227,30228,30229,30230,30231,30232,30233,30234,30235,
30236,30237,30238,30239,30240,30241,30242,30243,30244,30245,30246,30247,
30248,30249,30250,30251,30252,30253,30254,30255,30256,30257,30258,30259,
30260,30261,30262,30263,30264,30265,30266,30267,30268,30269,30270,30271,
30272,30273,30274,30275,30276,30277,30278,30279,30280,30281,30282,30283,
30284,30285,30286,30287,30288,30289,30290,30291,30292,30293,30294,30295,
30296,30297,30298,30299,30300,30301,30302,30303,30304,30305,30306,30307,
30308,30309,30310,30311,30312,30313,30314,30315,30316,30317,30318,30319,
30320,30321,30322,30323,30324,30325,30326,30327,30328,30329,30330,30331,
30332,30333,30334,30335,30336,30337,30338,30339,30340,30341,30342,30343,
30344,30345,30346,30347,30348,30349,30350,30351,30352,30353,30354,30355,
30356,30357,30358,30359,30360,30361,30362,30363,30364,30365,30366,30367,
30368,30369,30370,30371,30372,30373,30374,30375,30376,30377,30378,30379,
30380,30381,30382,30383,30384,30385,30386,30387,30388,30389,30390,30391,
30392,30393,30394,30395,30396,30397,30398,30399,30400,30401,30402,30403,
30404,30405,30406,30407,30408,30409,30410,30411,30412,30413,30414,30415,
30416,30417,30418,30419,30420,30421,30422,30423,30424,30425,30426,30427,
30428,30429,30430,30431,30432,30433,30434,30435,30436,30437,30438,30439,
30440,30441,30442,30443,30444,30445,30446,30447,30448,30449,30450,30451,
30452,30453,30454,30455,30456,30457,30458,30459,30460,30461,30462,30463,
30464,30465,30466,30467,30468,30469,30470,30471,30472,30473,30474,30475,
30476,30477,30478,30479,30480,30481,30482,30483,30484,30485,30486,30487,
30488,30489,30490,30491,30492,30493,30494,30495,30496,30497,30498,30499,
30500,30501,30502,30503,30504,30505,30506,30507,30508,30509,30510,30511,
30512,30513,30514,30515,30516,30517,30518,30519,30520,30521,30522,30523,
30524,30525,30526,30527,30528,30529,30530,30531,30532,30533,30534,30535,
30536,30537,30538,30539,30540,30541,30542,30543,30544,30545,30546,30547,
30548,30549,30550,30551,30552,30553,30554,30555,30556,30557,30558,30559,
30560,30561,30562,30563,30564,30565,30566,30567,30568,30569,30570,30571,
30572,30573,30574,30575,30576,30577,30578,30579,30580,30581,30582,30583,
30584,30585,30586,30587,30588,30589,30590,30591,30592,30593,30594,30595,
30596,30597,30598,30599,30600,30601,30602,30603,30604,30605,30606,30607,
30608,30609,30610,30611,30612,30613,30614,30615,30616,30617,30618,30619,
30620,30621,30622,30623,30624,30625,30626,30627,30628,30629,30630,30631,
30632,30633,30634,30635,30636,30637,30638,30639,30640,30641,30642,30643,
30644,30645,30646,30647,30648,30649,30650,30651,30652,30653,30654,30655,
30656,30657,30658,30659,30660,30661,30662,30663,30664,30665,30666,30667,
30668,30669,30670,30671,30672,30673,30674,30675,30676,30677,30678,30679,
30680,30681,30682,30683,30684,30685,30686,30687,30688,30689,30690,30691,
30692,30693,30694,30695,30696,30697,30698,30699,30700,30701,30702,30703,
30704,30705,30706,30707,30708,30709,30710,30711,30712,30713,30714,30715,
30716,30717,30718,30719,30720,30721,30722,30723,30724,30725,30726,30727,
30728,30729,30730,30731,30732,30733,30734,30735,30736,30737,30738,30739,
30740,30741,30742,30743,30744,30745,30746,30747,30748,30749,30750,30751,
30752,30753,30754,30755,30756,30757,30758,30759,30760,30761,30762,30763,
30764,30765,30766,30767,30768,30769,30770,30771,30772,30773,30774,30775,
30776,30777,30778,30779,30780,30781,30782,30783,30784,30785,30786,30787,
30788,30789,30790,30791,30792,30793,30794,30795,30796,30797,30798,30799,
30800,30801,30802,30803,30804,30805,30806,30807,30808,30809,30810,30811,
30812,30813,30814,30815,30816,30817,30818,30819,30820,30821,30822,30823,
30824,30825,30826,30827,30828,30829,30830,30831,30832,30833,30834,30835,
30836,30837,30838,30839,30840,30841,30842,30843,30844,30845,30846,30847,
30848,30849,30850,30851,30852,30853,30854,30855,30856,30857,30858,30859,
30860,30861,30862,30863,30864,30865,30866,30867,30868,30869,30870,30871,
30872,30873,30874,30875,30876,30877,30878,30879,30880,30881,30882,30883,
30884,30885,30886,30887,30888,30889,30890,30891,30892,30893,30894,30895,
30896,30897,30898,30899,30900,30901,30902,30903,30904,30905,30906,30907,
30908,30909,30910,30911,30912,30913,30914,30915,30916,30917,30918,30919,
30920,30921,30922,30923,30924,30925,30926,30927,30928,30929,30930,30931,
30932,30933,30934,30935,30936,30937,30938,30939,30940,30941,30942,30943,
30944,30945,30946,30947,30948,30949,30950,30951,30952,30953,30954,30955,
30956,30957,30958,30959,30960,30961,30962,30963,30964,30965,30966,30967,
30968,30969,30970,30971,30972,30973,30974,30975,30976,30977,30978,30979,
30980,30981,30982,30983,30984,30985,30986,30987,30988,30989,30990,30991,
30992,30993,30994,30995,30996,30997,30998,30999,31000,31001,31002,31003,
31004,31005,31006,31007,31008,31009,31010,31011,31012,31013,31014,31015,
31016,31017,31018,31019,31020,31021,31022,31023,31024,31025,31026,31027,
31028,31029,31030,31031,31032,31033,31034,31035,31036,31037,31038,31039,
31040,31041,31042,31043,31044,31045,31046,31047,31048,31049,31050,31051,
31052,31053,31054,31055,31056,31057,31058,31059,31060,31061,31062,31063,
31064,31065,31066,31067,31068,31069,31070,31071,31072,31073,31074,31075,
31076,31077,31078,31079,31080,31081,31082,31083,31084,31085,31086,31087,
31088,31089,31090,31091,31092,31093,31094,31095,31096,31097,31098,31099,
31100,31101,31102,31103,31104,31105,31106,31107,31108,31109,31110,31111,
31112,31113,31114,31115,31116,31117,31118,31119,31120,31121,31122,31123,
31124,31125,31126,31127,31128,31129,31130,31131,31132,31133,31134,31135,
31136,31137,31138,31139,31140,31141,31142,31143,31144,31145,31146,31147,
31148,31149,31150,31151,31152,31153,31154,31155,31156,31157,31158,31159,
31160,31161,31162,31163,31164,31165,31166,31167,31168,31169,31170,31171,
31172,31173,31174,31175,31176,31177,31178,31179,31180,31181,31182,31183,
31184,31185,31186,31187,31188,31189,31190,31191,31192,31193,31194,31195,
31196,31197,31198,31199,31200,31201,31202,31203,31204,31205,31206,31207,
31208,31209,31210,31211,31212,31213,31214,31215,31216,31217,31218,31219,
31220,31221,31222,31223,31224,31225,31226,31227,31228,31229,31230,31231,
31232,31233,31234,31235,31236,31237,31238,31239,31240,31241,31242,31243,
31244,31245,31246,31247,31248,31249,31250,31251,31252,31253,31254,31255,
31256,31257,31258,31259,31260,31261,31262,31263,31264,31265,31266,31267,
31268,31269,31270,31271,31272,31273,31274,31275,31276,31277,31278,31279,
31280,31281,31282,31283,31284,31285,31286,31287,31288,31289,31290,31291,
31292,31293,31294,31295,31296,31297,31298,31299,31300,31301,31302,31303,
31304,31305,31306,31307,31308,31309,31310,31311,31312,31313,31314,31315,
31316,31317,31318,31319,31320,31321,31322,31323,31324,31325,31326,31327,
31328,31329,31330,31331,31332,31333,31334,31335,31336,31337,31338,31339,
31340,31341,31342,31343,31344,31345,31346,31347,31348,31349,31350,31351,
31352,31353,31354,31355,31356,31357,31358,31359,31360,31361,31362,31363,
31364,31365,31366,31367,31368,31369,31370,31371,31372,31373,31374,31375,
31376,31377,31378,31379,31380,31381,31382,31383,31384,31385,31386,31387,
31388,31389,31390,31391,31392,31393,31394,31395,31396,31397,31398,31399,
31400,31401,31402,31403,31404,31405,31406,31407,31408,31409,31410,31411,
31412,31413,31414,31415,31416,31417,31418,31419,31420,31421,31422,31423,
31424,31425,31426,31427,31428,31429,31430,31431,31432,31433,31434,31435,
31436,31437,31438,31439,31440,31441,31442,31443,31444,31445,31446,31447,
31448,31449,31450,31451,31452,31453,31454,31455,31456,31457,31458,31459,
31460,31461,31462,31463,31464,31465,31466,31467,31468,31469,31470,31471,
31472,31473,31474,31475,31476,31477,31478,31479,31480,31481,31482,31483,
31484,31485,31486,31487,31488,31489,31490,31491,31492,31493,31494,31495,
31496,31497,31498,31499,31500,31501,31502,31503,31504,31505,31506,31507,
31508,31509,31510,31511,31512,31513,31514,31515,31516,31517,31518,31519,
31520,31521,31522,31523,31524,31525,31526,31527,31528,31529,31530,31531,
31532,31533,31534,31535,31536,31537,31538,31539,31540,31541,31542,31543,
31544,31545,31546,31547,31548,31549,31550,31551,31552,31553,31554,31555,
31556,31557,31558,31559,31560,31561,31562,31563,31564,31565,31566,31567,
31568,31569,31570,31571,31572,31573,31574,31575,31576,31577,31578,31579,
31580,31581,31582,31583,31584,31585,31586,31587,31588,31589,31590,31591,
31592,31593,31594,31595,31596,31597,31598,31599,31600,31601,31602,31603,
31604,31605,31606,31607,31608,31609,31610,31611,31612,31613,31614,31615,
31616,31617,31618,31619,31620,31621,31622,31623,31624,31625,31626,31627,
31628,31629,31630,31631,31632,31633,31634,31635,31636,31637,31638,31639,
31640,31641,31642,31643,31644,31645,31646,31647,31648,31649,31650,31651,
31652,31653,31654,31655,31656,31657,31658,31659,31660,31661,31662,31663,
31664,31665,31666,31667,31668,31669,31670,31671,31672,31673,31674,31675,
31676,31677,31678,31679,31680,31681,31682,31683,31684,31685,31686,31687,
31688,31689,31690,31691,31692,31693,31694,31695,31696,31697,31698,31699,
31700,31701,31702,31703,31704,31705,31706,31707,31708,31709,31710,31711,
31712,31713,31714,31715,31716,31717,31718,31719,31720,31721,31722,31723,
31724,31725,31726,31727,31728,31729,31730,31731,31732,31733,31734,31735,
31736,31737,31738,31739,31740,31741,31742,31743,31744,31745,31746,31747,
31748,31749,31750,31751,31752,31753,31754,31755,31756,31757,31758,31759,
31760,31761,31762,31763,31764,31765,31766,31767,31768,31769,31770,31771,
31772,31773,31774,31775,31776,31777,31778,31779,31780,31781,31782,31783,
31784,31785,31786,31787,31788,31789,31790,31791,31792,31793,31794,31795,
31796,31797,31798,31799,31800,31801,31802,31803,31804,31805,31806,31807,
31808,31809,31810,31811,31812,31813,31814,31815,31816,31817,31818,31819,
31820,31821,31822,31823,31824,31825,31826,31827,31828,31829,31830,31831,
31832,31833,31834,31835,31836,31837,31838,31839,31840,31841,31842,31843,
31844,31845,31846,31847,31848,31849,31850,31851,31852,31853,31854,31855,
31856,31857,31858,31859,31860,31861,31862,31863,31864,31865,31866,31867,
31868,31869,31870,31871,31872,31873,31874,31875,31876,31877,31878,31879,
31880,31881,31882,31883,31884,31885,31886,31887,31888,31889,31890,31891,
31892,31893,31894,31895,31896,31897,31898,31899,31900,31901,31902,31903,
31904,31905,31906,31907,31908,31909,31910,31911,31912,31913,31914,31915,
31916,31917,31918,31919,31920,31921,31922,31923,31924,31925,31926,31927,
31928,31929,31930,31931,31932,31933,31934,31935,31936,31937,31938,31939,
31940,31941,31942,31943,31944,31945,31946,31947,31948,31949,31950,31951,
31952,31953,31954,31955,31956,31957,31958,31959,31960,31961,31962,31963,
31964,31965,31966,31967,31968,31969,31970,31971,31972,31973,31974,31975,
31976,31977,31978,31979,31980,31981,31982,31983,31984,31985,31986,31987,
31988,31989,31990,31991,31992,31993,31994,31995,31996,31997,31998,31999,
32000,32001,32002,32003,32004,32005,32006,32007,32008,32009,32010,32011,
32012,32013,32014,32015,32016,32017,32018,32019,32020,32021,32022,32023,
32024,32025,32026,32027,32028,32029,32030,32031,32032,32033,32034,32035,
32036,32037,32038,32039,32040,32041,32042,32043,32044,32045,32046,32047,
32048,32049,32050,32051,32052,32053,32054,32055,32056,32057,32058,32059,
32060,32061,32062,32063,32064,32065,32066,32067,32068,32069,32070,32071,
32072,32073,32074,32075,32076,32077,32078,32079,32080,32081,32082,32083,
32084,32085,32086,32087,32088,32089,32090,32091,32092,32093,32094,32095,
32096,32097,32098,32099,32100,32101,32102,32103,32104,32105,32106,32107,
32108,32109,32110,32111,32112,32113,32114,32115,32116,32117,32118,32119,
32120,32121,32122,32123,32124,32125,32126,32127,32128,32129,32130,32131,
32132,32133,32134,32135,32136,32137,32138,32139,32140,32141,32142,32143,
32144,32145,32146,32147,32148,32149,32150,32151,32152,32153,32154,32155,
32156,32157,32158,32159,32160,32161,32162,32163,32164,32165,32166,32167,
32168,32169,32170,32171,32172,32173,32174,32175,32176,32177,32178,32179,
32180,32181,32182,32183,32184,32185,32186,32187,32188,32189,32190,32191,
32192,32193,32194,32195,32196,32197,32198,32199,32200,32201,32202,32203,
32204,32205,32206,32207,32208,32209,32210,32211,32212,32213,32214,32215,
32216,32217,32218,32219,32220,32221,32222,32223,32224,32225,32226,32227,
32228,32229,32230,32231,32232,32233,32234,32235,32236,32237,32238,32239,
32240,32241,32242,32243,32244,32245,32246,32247,32248,32249,32250,32251,
32252,32253,32254,32255,32256,32257,32258,32259,32260,32261,32262,32263,
32264,32265,32266,32267,32268,32269,32270,32271,32272,32273,32274,32275,
32276,32277,32278,32279,32280,32281,32282,32283,32284,32285,32286,32287,
32288,32289,32290,32291,32292,32293,32294,32295,32296,32297,32298,32299,
32300,32301,32302,32303,32304,32305,32306,32307,32308,32309,32310,32311,
32312,32313,32314,32315,32316,32317,32318,32319,32320,32321,32322,32323,
32324,32325,32326,32327,32328,32329,32330,32331,32332,32333,32334,32335,
32336,32337,32338,32339,32340,32341,32342,32343,32344,32345,32346,32347,
32348,32349,32350,32351,32352,32353,32354,32355,32356,32357,32358,32359,
32360,32361,32362,32363,32364,32365,32366,32367,32368,32369,32370,32371,
32372,32373,32374,32375,32376,32377,32378,32379,32380,32381,32382,32383,
32384,32385,32386,32387,32388,32389,32390,32391,32392,32393,32394,32395,
32396,32397,32398,32399,32400,32401,32402,32403,32404,32405,32406,32407,
32408,32409,32410,32411,32412,32413,32414,32415,32416,32417,32418,32419,
32420,32421,32422,32423,32424,32425,32426,32427,32428,32429,32430,32431,
32432,32433,32434,32435,32436,32437,32438,32439,32440,32441,32442,32443,
32444,32445,32446,32447,32448,32449,32450,32451,32452,32453,32454,32455,
32456,32457,32458,32459,32460,32461,32462,32463,32464,32465,32466,32467,
32468,32469,32470,32471,32472,32473,32474,32475,32476,32477,32478,32479,
32480,32481,32482,32483,32484,32485,32486,32487,32488,32489,32490,32491,
32492,32493,32494,32495,32496,32497,32498,32499,32500,32501,32502,32503,
32504,32505,32506,32507,32508,32509,32510,32511,32512,32513,32514,32515,
32516,32517,32518,32519,32520,32521,32522,32523,32524,32525,32526,32527,
32528,32529,32530,32531,32532,32533,32534,32535,32536,32537,32538,32539,
32540,32541,32542,32543,32544,32545,32546,32547,32548,32549,32550,32551,
32552,32553,32554,32555,32556,32557,32558,32559,32560,32561,32562,32563,
32564,32565,32566,32567,32568,32569,32570,32571,32572,32573,32574,32575,
32576,32577,32578,32579,32580,32581,32582,32583,32584,32585,32586,32587,
32588,32589,32590,32591,32592,32593,32594,32595,32596,32597,32598,32599,
32600,32601,32602,32603,32604,32605,32606,32607,32608,32609,32610,32611,
32612,32613,32614,32615,32616,32617,32618,32619,32620,32621,32622,32623,
32624,32625,32626,32627,32628,32629,32630,32631,32632,32633,32634,32635,
32636,32637,32638,32639,32640,32641,32642,32643,32644,32645,32646,32647,
32648,32649,32650,32651,32652,32653,32654,32655,32656,32657,32658,32659,
32660,32661,32662,32663,32664,32665,32666,32667,32668,32669,32670,32671,
32672,32673,32674,32675,32676,32677,32678,32679,32680,32681,32682,32683,
32684,32685,32686,32687,32688,32689,32690,32691,32692,32693,32694,32695,
32696,32697,32698,32699,32700,32701,32702,32703,32704,32705,32706,32707,
32708,32709,32710,32711,32712,32713,32714,32715,32716,32717,32718,32719,
32720,32721,32722,32723,32724,32725,32726,32727,32728,32729,32730,32731,
32732,32733,32734,32735,32736,32737,32738,32739,32740,32741,32742,32743,
32744,32745,32746,32747,32748,32749,32750,32751,32752,32753,32754,32755,
32756,32757,32758,32759,32760,32761,32762,32763,32764,32765,32766,32767,
32768L,32769L,32770L,32771L,32772L,32773L,32774L,32775L,32776L,32777L,
32778L,32779L,32780L,32781L,32782L,32783L,32784L,32785L,32786L,32787L,
32788L,32789L,32790L,32791L,32792L,32793L,32794L,32795L,32796L,32797L,
32798L,32799L,32800L,32801L,32802L,32803L,32804L,32805L,32806L,32807L,
32808L,32809L,32810L,32811L,32812L,32813L,32814L,32815L,32816L,32817L,
32818L,32819L,32820L,32821L,32822L,32823L,32824L,32825L,32826L,32827L,
32828L,32829L,32830L,32831L,32832L,32833L,32834L,32835L,32836L,32837L,
32838L,32839L,32840L,32841L,32842L,32843L,32844L,32845L,32846L,32847L,
32848L,32849L,32850L,32851L,32852L,32853L,32854L,32855L,32856L,32857L,
32858L,32859L,32860L,32861L,32862L,32863L,32864L,32865L,32866L,32867L,
32868L,32869L,32870L,32871L,32872L,32873L,32874L,32875L,32876L,32877L,
32878L,32879L,32880L,32881L,32882L,32883L,32884L,32885L,32886L,32887L,
32888L,32889L,32890L,32891L,32892L,32893L,32894L,32895L,32896L,32897L,
32898L,32899L,32900L,32901L,32902L,32903L,32904L,32905L,32906L,32907L,
32908L,32909L,32910L,32911L,32912L,32913L,32914L,32915L,32916L,32917L,
32918L,32919L,32920L,32921L,32922L,32923L,32924L,32925L,32926L,32927L,
32928L,32929L,32930L,32931L,32932L,32933L,32934L,32935L,32936L,32937L,
32938L,32939L,32940L,32941L,32942L,32943L,32944L,32945L,32946L,32947L,
32948L,32949L,32950L,32951L,32952L,32953L,32954L,32955L,32956L,32957L,
32958L,32959L,32960L,32961L,32962L,32963L,32964L,32965L,32966L,32967L,
32968L,32969L,32970L,32971L,32972L,32973L,32974L,32975L,32976L,32977L,
32978L,32979L,32980L,32981L,32982L,32983L,32984L,32985L,32986L,32987L,
32988L,32989L,32990L,32991L,32992L,32993L,32994L,32995L,32996L,32997L,
32998L,32999L,33000L,33001L,33002L,33003L,33004L,33005L,33006L,33007L,
33008L,33009L,33010L,33011L,33012L,33013L,33014L,33015L,33016L,33017L,
33018L,33019L,33020L,33021L,33022L,33023L,33024L,33025L,33026L,33027L,
33028L,33029L,33030L,33031L,33032L,33033L,33034L,33035L,33036L,33037L,
33038L,33039L,33040L,33041L,33042L,33043L,33044L,33045L,33046L,33047L,
33048L,33049L,33050L,33051L,33052L,33053L,33054L,33055L,33056L,33057L,
33058L,33059L,33060L,33061L,33062L,33063L,33064L,33065L,33066L,33067L,
33068L,33069L,33070L,33071L,33072L,33073L,33074L,33075L,33076L,33077L,
33078L,33079L,33080L,33081L,33082L,33083L,33084L,33085L,33086L,33087L,
33088L,33089L,33090L,33091L,33092L,33093L,33094L,33095L,33096L,33097L,
33098L,33099L,33100L,33101L,33102L,33103L,33104L,33105L,33106L,33107L,
33108L,33109L,33110L,33111L,33112L,33113L,33114L,33115L,33116L,33117L,
33118L,33119L,33120L,33121L,33122L,33123L,33124L,33125L,33126L,33127L,
33128L,33129L,33130L,33131L,33132L,33133L,33134L,33135L,33136L,33137L,
33138L,33139L,33140L,33141L,33142L,33143L,33144L,33145L,33146L,33147L,
33148L,33149L,33150L,33151L,33152L,33153L,33154L,33155L,33156L,33157L,
33158L,33159L,33160L,33161L,33162L,33163L,33164L,33165L,33166L,33167L,
33168L,33169L,33170L,33171L,33172L,33173L,33174L,33175L,33176L,33177L,
33178L,33179L,33180L,33181L,33182L,33183L,33184L,33185L,33186L,33187L,
33188L,33189L,33190L,33191L,33192L,33193L,33194L,33195L,33196L,33197L,
33198L,33199L,33200L,33201L,33202L,33203L,33204L,33205L,33206L,33207L,
33208L,33209L,33210L,33211L,33212L,33213L,33214L,33215L,33216L,33217L,
33218L,33219L,33220L,33221L,33222L,33223L,33224L,33225L,33226L,33227L,
33228L,33229L,33230L,33231L,33232L,33233L,33234L,33235L,33236L,33237L,
33238L,33239L,33240L,33241L,33242L,33243L,33244L,33245L,33246L,33247L,
33248L,33249L,33250L,33251L,33252L,33253L,33254L,33255L,33256L,33257L,
33258L,33259L,33260L,33261L,33262L,33263L,33264L,33265L,33266L,33267L,
33268L,33269L,33270L,33271L,33272L,33273L,33274L,33275L,33276L,33277L,
33278L,33279L,33280L,33281L,33282L,33283L,33284L,33285L,33286L,33287L,
33288L,33289L,33290L,33291L,33292L,33293L,33294L,33295L,33296L,33297L,
33298L,33299L,33300L,33301L,33302L,33303L,33304L,33305L,33306L,33307L,
33308L,33309L,33310L,33311L,33312L,33313L,33314L,33315L,33316L,33317L,
33318L,33319L,33320L,33321L,33322L,33323L,33324L,33325L,33326L,33327L,
33328L,33329L,33330L,33331L,33332L,33333L,33334L,33335L,33336L,33337L,
33338L,33339L,33340L,33341L,33342L,33343L,33344L,33345L,33346L,33347L,
33348L,33349L,33350L,33351L,33352L,33353L,33354L,33355L,33356L,33357L,
33358L,33359L,33360L,33361L,33362L,33363L,33364L,33365L,33366L,33367L,
33368L,33369L,33370L,33371L,33372L,33373L,33374L,33375L,33376L,33377L,
33378L,33379L,33380L,33381L,33382L,33383L,33384L,33385L,33386L,33387L,
33388L,33389L,33390L,33391L,33392L,33393L,33394L,33395L,33396L,33397L,
33398L,33399L,33400L,33401L,33402L,33403L,33404L,33405L,33406L,33407L,
33408L,33409L,33410L,33411L,33412L,33413L,33414L,33415L,33416L,33417L,
33418L,33419L,33420L,33421L,33422L,33423L,33424L,33425L,33426L,33427L,
33428L,33429L,33430L,33431L,33432L,33433L,33434L,33435L,33436L,33437L,
33438L,33439L,33440L,33441L,33442L,33443L,33444L,33445L,33446L,33447L,
33448L,33449L,33450L,33451L,33452L,33453L,33454L,33455L,33456L,33457L,
33458L,33459L,33460L,33461L,33462L,33463L,33464L,33465L,33466L,33467L,
33468L,33469L,33470L,33471L,33472L,33473L,33474L,33475L,33476L,33477L,
33478L,33479L,33480L,33481L,33482L,33483L,33484L,33485L,33486L,33487L,
33488L,33489L,33490L,33491L,33492L,33493L,33494L,33495L,33496L,33497L,
33498L,33499L,33500L,33501L,33502L,33503L,33504L,33505L,33506L,33507L,
33508L,33509L,33510L,33511L,33512L,33513L,33514L,33515L,33516L,33517L,
33518L,33519L,33520L,33521L,33522L,33523L,33524L,33525L,33526L,33527L,
33528L,33529L,33530L,33531L,33532L,33533L,33534L,33535L,33536L,33537L,
33538L,33539L,33540L,33541L,33542L,33543L,33544L,33545L,33546L,33547L,
33548L,33549L,33550L,33551L,33552L,33553L,33554L,33555L,33556L,33557L,
33558L,33559L,33560L,33561L,33562L,33563L,33564L,33565L,33566L,33567L,
33568L,33569L,33570L,33571L,33572L,33573L,33574L,33575L,33576L,33577L,
33578L,33579L,33580L,33581L,33582L,33583L,33584L,33585L,33586L,33587L,
33588L,33589L,33590L,33591L,33592L,33593L,33594L,33595L,33596L,33597L,
33598L,33599L,33600L,33601L,33602L,33603L,33604L,33605L,33606L,33607L,
33608L,33609L,33610L,33611L,33612L,33613L,33614L,33615L,33616L,33617L,
33618L,33619L,33620L,33621L,33622L,33623L,33624L,33625L,33626L,33627L,
33628L,33629L,33630L,33631L,33632L,33633L,33634L,33635L,33636L,33637L,
33638L,33639L,33640L,33641L,33642L,33643L,33644L,33645L,33646L,33647L,
33648L,33649L,33650L,33651L,33652L,33653L,33654L,33655L,33656L,33657L,
33658L,33659L,33660L,33661L,33662L,33663L,33664L,33665L,33666L,33667L,
33668L,33669L,33670L,33671L,33672L,33673L,33674L,33675L,33676L,33677L,
33678L,33679L,33680L,33681L,33682L,33683L,33684L,33685L,33686L,33687L,
33688L,33689L,33690L,33691L,33692L,33693L,33694L,33695L,33696L,33697L,
33698L,33699L,33700L,33701L,33702L,33703L,33704L,33705L,33706L,33707L,
33708L,33709L,33710L,33711L,33712L,33713L,33714L,33715L,33716L,33717L,
33718L,33719L,33720L,33721L,33722L,33723L,33724L,33725L,33726L,33727L,
33728L,33729L,33730L,33731L,33732L,33733L,33734L,33735L,33736L,33737L,
33738L,33739L,33740L,33741L,33742L,33743L,33744L,33745L,33746L,33747L,
33748L,33749L,33750L,33751L,33752L,33753L,33754L,33755L,33756L,33757L,
33758L,33759L,33760L,33761L,33762L,33763L,33764L,33765L,33766L,33767L,
33768L,33769L,33770L,33771L,33772L,33773L,33774L,33775L,33776L,33777L,
33778L,33779L,33780L,33781L,33782L,33783L,33784L,33785L,33786L,33787L,
33788L,33789L,33790L,33791L,33792L,33793L,33794L,33795L,33796L,33797L,
33798L,33799L,33800L,33801L,33802L,33803L,33804L,33805L,33806L,33807L,
33808L,33809L,33810L,33811L,33812L,33813L,33814L,33815L,33816L,33817L,
33818L,33819L,33820L,33821L,33822L,33823L,33824L,33825L,33826L,33827L,
33828L,33829L,33830L,33831L,33832L,33833L,33834L,33835L,33836L,33837L,
33838L,33839L,33840L,33841L,33842L,33843L,33844L,33845L,33846L,33847L,
33848L,33849L,33850L,33851L,33852L,33853L,33854L,33855L,33856L,33857L,
33858L,33859L,33860L,33861L,33862L,33863L,33864L,33865L,33866L,33867L,
33868L,33869L,33870L,33871L,33872L,33873L,33874L,33875L,33876L,33877L,
33878L,33879L,33880L,33881L,33882L,33883L,33884L,33885L,33886L,33887L,
33888L,33889L,33890L,33891L,33892L,33893L,33894L,33895L,33896L,33897L,
33898L,33899L,33900L,33901L,33902L,33903L,33904L,33905L,33906L,33907L,
33908L,33909L,33910L,33911L,33912L,33913L,33914L,33915L,33916L,33917L,
33918L,33919L,33920L,33921L,33922L,33923L,33924L,33925L,33926L,33927L,
33928L,33929L,33930L,33931L,33932L,33933L,33934L,33935L,33936L,33937L,
33938L,33939L,33940L,33941L,33942L,33943L,33944L,33945L,33946L,33947L,
33948L,33949L,33950L,33951L,33952L,33953L,33954L,33955L,33956L,33957L,
33958L,33959L,33960L,33961L,33962L,33963L,33964L,33965L,33966L,33967L,
33968L,33969L,33970L,33971L,33972L,33973L,33974L,33975L,33976L,33977L,
33978L,33979L,33980L,33981L,33982L,33983L,33984L,33985L,33986L,33987L,
33988L,33989L,33990L,33991L,33992L,33993L,33994L,33995L,33996L,33997L,
33998L,33999L,34000L,34001L,34002L,34003L,34004L,34005L,34006L,34007L,
34008L,34009L,34010L,34011L,34012L,34013L,34014L,34015L,34016L,34017L,
34018L,34019L,34020L,34021L,34022L,34023L,34024L,34025L,34026L,34027L,
34028L,34029L,34030L,34031L,34032L,34033L,34034L,34035L,34036L,34037L,
34038L,34039L,34040L,34041L,34042L,34043L,34044L,34045L,34046L,34047L,
34048L,34049L,34050L,34051L,34052L,34053L,34054L,34055L,34056L,34057L,
34058L,34059L,34060L,34061L,34062L,34063L,34064L,34065L,34066L,34067L,
34068L,34069L,34070L,34071L,34072L,34073L,34074L,34075L,34076L,34077L,
34078L,34079L,34080L,34081L,34082L,34083L,34084L,34085L,34086L,34087L,
34088L,34089L,34090L,34091L,34092L,34093L,34094L,34095L,34096L,34097L,
34098L,34099L,34100L,34101L,34102L,34103L,34104L,34105L,34106L,34107L,
34108L,34109L,34110L,34111L,34112L,34113L,34114L,34115L,34116L,34117L,
34118L,34119L,34120L,34121L,34122L,34123L,34124L,34125L,34126L,34127L,
34128L,34129L,34130L,34131L,34132L,34133L,34134L,34135L,34136L,34137L,
34138L,34139L,34140L,34141L,34142L,34143L,34144L,34145L,34146L,34147L,
34148L,34149L,34150L,34151L,34152L,34153L,34154L,34155L,34156L,34157L,
34158L,34159L,34160L,34161L,34162L,34163L,34164L,34165L,34166L,34167L,
34168L,34169L,34170L,34171L,34172L,34173L,34174L,34175L,34176L,34177L,
34178L,34179L,34180L,34181L,34182L,34183L,34184L,34185L,34186L,34187L,
34188L,34189L,34190L,34191L,34192L,34193L,34194L,34195L,34196L,34197L,
34198L,34199L,34200L,34201L,34202L,34203L,34204L,34205L,34206L,34207L,
34208L,34209L,34210L,34211L,34212L,34213L,34214L,34215L,34216L,34217L,
34218L,34219L,34220L,34221L,34222L,34223L,34224L,34225L,34226L,34227L,
34228L,34229L,34230L,34231L,34232L,34233L,34234L,34235L,34236L,34237L,
34238L,34239L,34240L,34241L,34242L,34243L,34244L,34245L,34246L,34247L,
34248L,34249L,34250L,34251L,34252L,34253L,34254L,34255L,34256L,34257L,
34258L,34259L,34260L,34261L,34262L,34263L,34264L,34265L,34266L,34267L,
34268L,34269L,34270L,34271L,34272L,34273L,34274L,34275L,34276L,34277L,
34278L,34279L,34280L,34281L,34282L,34283L,34284L,34285L,34286L,34287L,
34288L,34289L,34290L,34291L,34292L,34293L,34294L,34295L,34296L,34297L,
34298L,34299L,34300L,34301L,34302L,34303L,34304L,34305L,34306L,34307L,
34308L,34309L,34310L,34311L,34312L,34313L,34314L,34315L,34316L,34317L,
34318L,34319L,34320L,34321L,34322L,34323L,34324L,34325L,34326L,34327L,
34328L,34329L,34330L,34331L,34332L,34333L,34334L,34335L,34336L,34337L,
34338L,34339L,34340L,34341L,34342L,34343L,34344L,34345L,34346L,34347L,
34348L,34349L,34350L,34351L,34352L,34353L,34354L,34355L,34356L,34357L,
34358L,34359L,34360L,34361L,34362L,34363L,34364L,34365L,34366L,34367L,
34368L,34369L,34370L,34371L,34372L,34373L,34374L,34375L,34376L,34377L,
34378L,34379L,34380L,34381L,34382L,34383L,34384L,34385L,34386L,34387L,
34388L,34389L,34390L,34391L,34392L,34393L,34394L,34395L,34396L,34397L,
34398L,34399L,34400L,34401L,34402L,34403L,34404L,34405L,34406L,34407L,
34408L,34409L,34410L,34411L,34412L,34413L,34414L,34415L,34416L,34417L,
34418L,34419L,34420L,34421L,34422L,34423L,34424L,34425L,34426L,34427L,
34428L,34429L,34430L,34431L,34432L,34433L,34434L,34435L,34436L,34437L,
34438L,34439L,34440L,34441L,34442L,34443L,34444L,34445L,34446L,34447L,
34448L,34449L,34450L,34451L,34452L,34453L,34454L,34455L,34456L,34457L,
34458L,34459L,34460L,34461L,34462L,34463L,34464L,34465L,34466L,34467L,
34468L,34469L,34470L,34471L,34472L,34473L,34474L,34475L,34476L,34477L,
34478L,34479L,34480L,34481L,34482L,34483L,34484L,34485L,34486L,34487L,
34488L,34489L,34490L,34491L,34492L,34493L,34494L,34495L,34496L,34497L,
34498L,34499L,34500L,34501L,34502L,34503L,34504L,34505L,34506L,34507L,
34508L,34509L,34510L,34511L,34512L,34513L,34514L,34515L,34516L,34517L,
34518L,34519L,34520L,34521L,34522L,34523L,34524L,34525L,34526L,34527L,
34528L,34529L,34530L,34531L,34532L,34533L,34534L,34535L,34536L,34537L,
34538L,34539L,34540L,34541L,34542L,34543L,34544L,34545L,34546L,34547L,
34548L,34549L,34550L,34551L,34552L,34553L,34554L,34555L,34556L,34557L,
34558L,34559L,34560L,34561L,34562L,34563L,34564L,34565L,34566L,34567L,
34568L,34569L,34570L,34571L,34572L,34573L,34574L,34575L,34576L,34577L,
34578L,34579L,34580L,34581L,34582L,34583L,34584L,34585L,34586L,34587L,
34588L,34589L,34590L,34591L,34592L,34593L,34594L,34595L,34596L,34597L,
34598L,34599L,34600L,34601L,34602L,34603L,34604L,34605L,34606L,34607L,
34608L,34609L,34610L,34611L,34612L,34613L,34614L,34615L,34616L,34617L,
34618L,34619L,34620L,34621L,34622L,34623L,34624L,34625L,34626L,34627L,
34628L,34629L,34630L,34631L,34632L,34633L,34634L,34635L,34636L,34637L,
34638L,34639L,34640L,34641L,34642L,34643L,34644L,34645L,34646L,34647L,
34648L,34649L,34650L,34651L,34652L,34653L,34654L,34655L,34656L,34657L,
34658L,34659L,34660L,34661L,34662L,34663L,34664L,34665L,34666L,34667L,
34668L,34669L,34670L,34671L,34672L,34673L,34674L,34675L,34676L,34677L,
34678L,34679L,34680L,34681L,34682L,34683L,34684L,34685L,34686L,34687L,
34688L,34689L,34690L,34691L,34692L,34693L,34694L,34695L,34696L,34697L,
34698L,34699L,34700L,34701L,34702L,34703L,34704L,34705L,34706L,34707L,
34708L,34709L,34710L,34711L,34712L,34713L,34714L,34715L,34716L,34717L,
34718L,34719L,34720L,34721L,34722L,34723L,34724L,34725L,34726L,34727L,
34728L,34729L,34730L,34731L,34732L,34733L,34734L,34735L,34736L,34737L,
34738L,34739L,34740L,34741L,34742L,34743L,34744L,34745L,34746L,34747L,
34748L,34749L,34750L,34751L,34752L,34753L,34754L,34755L,34756L,34757L,
34758L,34759L,34760L,34761L,34762L,34763L,34764L,34765L,34766L,34767L,
34768L,34769L,34770L,34771L,34772L,34773L,34774L,34775L,34776L,34777L,
34778L,34779L,34780L,34781L,34782L,34783L,34784L,34785L,34786L,34787L,
34788L,34789L,34790L,34791L,34792L,34793L,34794L,34795L,34796L,34797L,
34798L,34799L,34800L,34801L,34802L,34803L,34804L,34805L,34806L,34807L,
34808L,34809L,34810L,34811L,34812L,34813L,34814L,34815L,34816L,34817L,
34818L,34819L,34820L,34821L,34822L,34823L,34824L,34825L,34826L,34827L,
34828L,34829L,34830L,34831L,34832L,34833L,34834L,34835L,34836L,34837L,
34838L,34839L,34840L,34841L,34842L,34843L,34844L,34845L,34846L,34847L,
34848L,34849L,34850L,34851L,34852L,34853L,34854L,34855L,34856L,34857L,
34858L,34859L,34860L,34861L,34862L,34863L,34864L,34865L,34866L,34867L,
34868L,34869L,34870L,34871L,34872L,34873L,34874L,34875L,34876L,34877L,
34878L,34879L,34880L,34881L,34882L,34883L,34884L,34885L,34886L,34887L,
34888L,34889L,34890L,34891L,34892L,34893L,34894L,34895L,34896L,34897L,
34898L,34899L,34900L,34901L,34902L,34903L,34904L,34905L,34906L,34907L,
34908L,34909L,34910L,34911L,34912L,34913L,34914L,34915L,34916L,34917L,
34918L,34919L,34920L,34921L,34922L,34923L,34924L,34925L,34926L,34927L,
34928L,34929L,34930L,34931L,34932L,34933L,34934L,34935L,34936L,34937L,
34938L,34939L,34940L,34941L,34942L,34943L,34944L,34945L,34946L,34947L,
34948L,34949L,34950L,34951L,34952L,34953L,34954L,34955L,34956L,34957L,
34958L,34959L,34960L,34961L,34962L,34963L,34964L,34965L,34966L,34967L,
34968L,34969L,34970L,34971L,34972L,34973L,34974L,34975L,34976L,34977L,
34978L,34979L,34980L,34981L,34982L,34983L,34984L,34985L,34986L,34987L,
34988L,34989L,34990L,34991L,34992L,34993L,34994L,34995L,34996L,34997L,
34998L,34999L,35000L,35001L,35002L,35003L,35004L,35005L,35006L,35007L,
35008L,35009L,35010L,35011L,35012L,35013L,35014L,35015L,35016L,35017L,
35018L,35019L,35020L,35021L,35022L,35023L,35024L,35025L,35026L,35027L,
35028L,35029L,35030L,35031L,35032L,35033L,35034L,35035L,35036L,35037L,
35038L,35039L,35040L,35041L,35042L,35043L,35044L,35045L,35046L,35047L,
35048L,35049L,35050L,35051L,35052L,35053L,35054L,35055L,35056L,35057L,
35058L,35059L,35060L,35061L,35062L,35063L,35064L,35065L,35066L,35067L,
35068L,35069L,35070L,35071L,35072L,35073L,35074L,35075L,35076L,35077L,
35078L,35079L,35080L,35081L,35082L,35083L,35084L,35085L,35086L,35087L,
35088L,35089L,35090L,35091L,35092L,35093L,35094L,35095L,35096L,35097L,
35098L,35099L,35100L,35101L,35102L,35103L,35104L,35105L,35106L,35107L,
35108L,35109L,35110L,35111L,35112L,35113L,35114L,35115L,35116L,35117L,
35118L,35119L,35120L,35121L,35122L,35123L,35124L,35125L,35126L,35127L,
35128L,35129L,35130L,35131L,35132L,35133L,35134L,35135L,35136L,35137L,
35138L,35139L,35140L,35141L,35142L,35143L,35144L,35145L,35146L,35147L,
35148L,35149L,35150L,35151L,35152L,35153L,35154L,35155L,35156L,35157L,
35158L,35159L,35160L,35161L,35162L,35163L,35164L,35165L,35166L,35167L,
35168L,35169L,35170L,35171L,35172L,35173L,35174L,35175L,35176L,35177L,
35178L,35179L,35180L,35181L,35182L,35183L,35184L,35185L,35186L,35187L,
35188L,35189L,35190L,35191L,35192L,35193L,35194L,35195L,35196L,35197L,
35198L,35199L,35200L,35201L,35202L,35203L,35204L,35205L,35206L,35207L,
35208L,35209L,35210L,35211L,35212L,35213L,35214L,35215L,35216L,35217L,
35218L,35219L,35220L,35221L,35222L,35223L,35224L,35225L,35226L,35227L,
35228L,35229L,35230L,35231L,35232L,35233L,35234L,35235L,35236L,35237L,
35238L,35239L,35240L,35241L,35242L,35243L,35244L,35245L,35246L,35247L,
35248L,35249L,35250L,35251L,35252L,35253L,35254L,35255L,35256L,35257L,
35258L,35259L,35260L,35261L,35262L,35263L,35264L,35265L,35266L,35267L,
35268L,35269L,35270L,35271L,35272L,35273L,35274L,35275L,35276L,35277L,
35278L,35279L,35280L,35281L,35282L,35283L,35284L,35285L,35286L,35287L,
35288L,35289L,35290L,35291L,35292L,35293L,35294L,35295L,35296L,35297L,
35298L,35299L,35300L,35301L,35302L,35303L,35304L,35305L,35306L,35307L,
35308L,35309L,35310L,35311L,35312L,35313L,35314L,35315L,35316L,35317L,
35318L,35319L,35320L,35321L,35322L,35323L,35324L,35325L,35326L,35327L,
35328L,35329L,35330L,35331L,35332L,35333L,35334L,35335L,35336L,35337L,
35338L,35339L,35340L,35341L,35342L,35343L,35344L,35345L,35346L,35347L,
35348L,35349L,35350L,35351L,35352L,35353L,35354L,35355L,35356L,35357L,
35358L,35359L,35360L,35361L,35362L,35363L,35364L,35365L,35366L,35367L,
35368L,35369L,35370L,35371L,35372L,35373L,35374L,35375L,35376L,35377L,
35378L,35379L,35380L,35381L,35382L,35383L,35384L,35385L,35386L,35387L,
35388L,35389L,35390L,35391L,35392L,35393L,35394L,35395L,35396L,35397L,
35398L,35399L,35400L,35401L,35402L,35403L,35404L,35405L,35406L,35407L,
35408L,35409L,35410L,35411L,35412L,35413L,35414L,35415L,35416L,35417L,
35418L,35419L,35420L,35421L,35422L,35423L,35424L,35425L,35426L,35427L,
35428L,35429L,35430L,35431L,35432L,35433L,35434L,35435L,35436L,35437L,
35438L,35439L,35440L,35441L,35442L,35443L,35444L,35445L,35446L,35447L,
35448L,35449L,35450L,35451L,35452L,35453L,35454L,35455L,35456L,35457L,
35458L,35459L,35460L,35461L,35462L,35463L,35464L,35465L,35466L,35467L,
35468L,35469L,35470L,35471L,35472L,35473L,35474L,35475L,35476L,35477L,
35478L,35479L,35480L,35481L,35482L,35483L,35484L,35485L,35486L,35487L,
35488L,35489L,35490L,35491L,35492L,35493L,35494L,35495L,35496L,35497L,
35498L,35499L,35500L,35501L,35502L,35503L,35504L,35505L,35506L,35507L,
35508L,35509L,35510L,35511L,35512L,35513L,35514L,35515L,35516L,35517L,
35518L,35519L,35520L,35521L,35522L,35523L,35524L,35525L,35526L,35527L,
35528L,35529L,35530L,35531L,35532L,35533L,35534L,35535L,35536L,35537L,
35538L,35539L,35540L,35541L,35542L,35543L,35544L,35545L,35546L,35547L,
35548L,35549L,35550L,35551L,35552L,35553L,35554L,35555L,35556L,35557L,
35558L,35559L,35560L,35561L,35562L,35563L,35564L,35565L,35566L,35567L,
35568L,35569L,35570L,35571L,35572L,35573L,35574L,35575L,35576L,35577L,
35578L,35579L,35580L,35581L,35582L,35583L,35584L,35585L,35586L,35587L,
35588L,35589L,35590L,35591L,35592L,35593L,35594L,35595L,35596L,35597L,
35598L,35599L,35600L,35601L,35602L,35603L,35604L,35605L,35606L,35607L,
35608L,35609L,35610L,35611L,35612L,35613L,35614L,35615L,35616L,35617L,
35618L,35619L,35620L,35621L,35622L,35623L,35624L,35625L,35626L,35627L,
35628L,35629L,35630L,35631L,35632L,35633L,35634L,35635L,35636L,35637L,
35638L,35639L,35640L,35641L,35642L,35643L,35644L,35645L,35646L,35647L,
35648L,35649L,35650L,35651L,35652L,35653L,35654L,35655L,35656L,35657L,
35658L,35659L,35660L,35661L,35662L,35663L,35664L,35665L,35666L,35667L,
35668L,35669L,35670L,35671L,35672L,35673L,35674L,35675L,35676L,35677L,
35678L,35679L,35680L,35681L,35682L,35683L,35684L,35685L,35686L,35687L,
35688L,35689L,35690L,35691L,35692L,35693L,35694L,35695L,35696L,35697L,
35698L,35699L,35700L,35701L,35702L,35703L,35704L,35705L,35706L,35707L,
35708L,35709L,35710L,35711L,35712L,35713L,35714L,35715L,35716L,35717L,
35718L,35719L,35720L,35721L,35722L,35723L,35724L,35725L,35726L,35727L,
35728L,35729L,35730L,35731L,35732L,35733L,35734L,35735L,35736L,35737L,
35738L,35739L,35740L,35741L,35742L,35743L,35744L,35745L,35746L,35747L,
35748L,35749L,35750L,35751L,35752L,35753L,35754L,35755L,35756L,35757L,
35758L,35759L,35760L,35761L,35762L,35763L,35764L,35765L,35766L,35767L,
35768L,35769L,35770L,35771L,35772L,35773L,35774L,35775L,35776L,35777L,
35778L,35779L,35780L,35781L,35782L,35783L,35784L,35785L,35786L,35787L,
35788L,35789L,35790L,35791L,35792L,35793L,35794L,35795L,35796L,35797L,
35798L,35799L,35800L,35801L,35802L,35803L,35804L,35805L,35806L,35807L,
35808L,35809L,35810L,35811L,35812L,35813L,35814L,35815L,35816L,35817L,
35818L,35819L,35820L,35821L,35822L,35823L,35824L,35825L,35826L,35827L,
35828L,35829L,35830L,35831L,35832L,35833L,35834L,35835L,35836L,35837L,
35838L,35839L,35840L,35841L,35842L,35843L,35844L,35845L,35846L,35847L,
35848L,35849L,35850L,35851L,35852L,35853L,35854L,35855L,35856L,35857L,
35858L,35859L,35860L,35861L,35862L,35863L,35864L,35865L,35866L,35867L,
35868L,35869L,35870L,35871L,35872L,35873L,35874L,35875L,35876L,35877L,
35878L,35879L,35880L,35881L,35882L,35883L,35884L,35885L,35886L,35887L,
35888L,35889L,35890L,35891L,35892L,35893L,35894L,35895L,35896L,35897L,
35898L,35899L,35900L,35901L,35902L,35903L,35904L,35905L,35906L,35907L,
35908L,35909L,35910L,35911L,35912L,35913L,35914L,35915L,35916L,35917L,
35918L,35919L,35920L,35921L,35922L,35923L,35924L,35925L,35926L,35927L,
35928L,35929L,35930L,35931L,35932L,35933L,35934L,35935L,35936L,35937L,
35938L,35939L,35940L,35941L,35942L,35943L,35944L,35945L,35946L,35947L,
35948L,35949L,35950L,35951L,35952L,35953L,35954L,35955L,35956L,35957L,
35958L,35959L,35960L,35961L,35962L,35963L,35964L,35965L,35966L,35967L,
35968L,35969L,35970L,35971L,35972L,35973L,35974L,35975L,35976L,35977L,
35978L,35979L,35980L,35981L,35982L,35983L,35984L,35985L,35986L,35987L,
35988L,35989L,35990L,35991L,35992L,35993L,35994L,35995L,35996L,35997L,
35998L,35999L,36000L,36001L,36002L,36003L,36004L,36005L,36006L,36007L,
36008L,36009L,36010L,36011L,36012L,36013L,36014L,36015L,36016L,36017L,
36018L,36019L,36020L,36021L,36022L,36023L,36024L,36025L,36026L,36027L,
36028L,36029L,36030L,36031L,36032L,36033L,36034L,36035L,36036L,36037L,
36038L,36039L,36040L,36041L,36042L,36043L,36044L,36045L,36046L,36047L,
36048L,36049L,36050L,36051L,36052L,36053L,36054L,36055L,36056L,36057L,
36058L,36059L,36060L,36061L,36062L,36063L,36064L,36065L,36066L,36067L,
36068L,36069L,36070L,36071L,36072L,36073L,36074L,36075L,36076L,36077L,
36078L,36079L,36080L,36081L,36082L,36083L,36084L,36085L,36086L,36087L,
36088L,36089L,36090L,36091L,36092L,36093L,36094L,36095L,36096L,36097L,
36098L,36099L,36100L,36101L,36102L,36103L,36104L,36105L,36106L,36107L,
36108L,36109L,36110L,36111L,36112L,36113L,36114L,36115L,36116L,36117L,
36118L,36119L,36120L,36121L,36122L,36123L,36124L,36125L,36126L,36127L,
36128L,36129L,36130L,36131L,36132L,36133L,36134L,36135L,36136L,36137L,
36138L,36139L,36140L,36141L,36142L,36143L,36144L,36145L,36146L,36147L,
36148L,36149L,36150L,36151L,36152L,36153L,36154L,36155L,36156L,36157L,
36158L,36159L,36160L,36161L,36162L,36163L,36164L,36165L,36166L,36167L,
36168L,36169L,36170L,36171L,36172L,36173L,36174L,36175L,36176L,36177L,
36178L,36179L,36180L,36181L,36182L,36183L,36184L,36185L,36186L,36187L,
36188L,36189L,36190L,36191L,36192L,36193L,36194L,36195L,36196L,36197L,
36198L,36199L,36200L,36201L,36202L,36203L,36204L,36205L,36206L,36207L,
36208L,36209L,36210L,36211L,36212L,36213L,36214L,36215L,36216L,36217L,
36218L,36219L,36220L,36221L,36222L,36223L,36224L,36225L,36226L,36227L,
36228L,36229L,36230L,36231L,36232L,36233L,36234L,36235L,36236L,36237L,
36238L,36239L,36240L,36241L,36242L,36243L,36244L,36245L,36246L,36247L,
36248L,36249L,36250L,36251L,36252L,36253L,36254L,36255L,36256L,36257L,
36258L,36259L,36260L,36261L,36262L,36263L,36264L,36265L,36266L,36267L,
36268L,36269L,36270L,36271L,36272L,36273L,36274L,36275L,36276L,36277L,
36278L,36279L,36280L,36281L,36282L,36283L,36284L,36285L,36286L,36287L,
36288L,36289L,36290L,36291L,36292L,36293L,36294L,36295L,36296L,36297L,
36298L,36299L,36300L,36301L,36302L,36303L,36304L,36305L,36306L,36307L,
36308L,36309L,36310L,36311L,36312L,36313L,36314L,36315L,36316L,36317L,
36318L,36319L,36320L,36321L,36322L,36323L,36324L,36325L,36326L,36327L,
36328L,36329L,36330L,36331L,36332L,36333L,36334L,36335L,36336L,36337L,
36338L,36339L,36340L,36341L,36342L,36343L,36344L,36345L,36346L,36347L,
36348L,36349L,36350L,36351L,36352L,36353L,36354L,36355L,36356L,36357L,
36358L,36359L,36360L,36361L,36362L,36363L,36364L,36365L,36366L,36367L,
36368L,36369L,36370L,36371L,36372L,36373L,36374L,36375L,36376L,36377L,
36378L,36379L,36380L,36381L,36382L,36383L,36384L,36385L,36386L,36387L,
36388L,36389L,36390L,36391L,36392L,36393L,36394L,36395L,36396L,36397L,
36398L,36399L,36400L,36401L,36402L,36403L,36404L,36405L,36406L,36407L,
36408L,36409L,36410L,36411L,36412L,36413L,36414L,36415L,36416L,36417L,
36418L,36419L,36420L,36421L,36422L,36423L,36424L,36425L,36426L,36427L,
36428L,36429L,36430L,36431L,36432L,36433L,36434L,36435L,36436L,36437L,
36438L,36439L,36440L,36441L,36442L,36443L,36444L,36445L,36446L,36447L,
36448L,36449L,36450L,36451L,36452L,36453L,36454L,36455L,36456L,36457L,
36458L,36459L,36460L,36461L,36462L,36463L,36464L,36465L,36466L,36467L,
36468L,36469L,36470L,36471L,36472L,36473L,36474L,36475L,36476L,36477L,
36478L,36479L,36480L,36481L,36482L,36483L,36484L,36485L,36486L,36487L,
36488L,36489L,36490L,36491L,36492L,36493L,36494L,36495L,36496L,36497L,
36498L,36499L,36500L,36501L,36502L,36503L,36504L,36505L,36506L,36507L,
36508L,36509L,36510L,36511L,36512L,36513L,36514L,36515L,36516L,36517L,
36518L,36519L,36520L,36521L,36522L,36523L,36524L,36525L,36526L,36527L,
36528L,36529L,36530L,36531L,36532L,36533L,36534L,36535L,36536L,36537L,
36538L,36539L,36540L,36541L,36542L,36543L,36544L,36545L,36546L,36547L,
36548L,36549L,36550L,36551L,36552L,36553L,36554L,36555L,36556L,36557L,
36558L,36559L,36560L,36561L,36562L,36563L,36564L,36565L,36566L,36567L,
36568L,36569L,36570L,36571L,36572L,36573L,36574L,36575L,36576L,36577L,
36578L,36579L,36580L,36581L,36582L,36583L,36584L,36585L,36586L,36587L,
36588L,36589L,36590L,36591L,36592L,36593L,36594L,36595L,36596L,36597L,
36598L,36599L,36600L,36601L,36602L,36603L,36604L,36605L,36606L,36607L,
36608L,36609L,36610L,36611L,36612L,36613L,36614L,36615L,36616L,36617L,
36618L,36619L,36620L,36621L,36622L,36623L,36624L,36625L,36626L,36627L,
36628L,36629L,36630L,36631L,36632L,36633L,36634L,36635L,36636L,36637L,
36638L,36639L,36640L,36641L,36642L,36643L,36644L,36645L,36646L,36647L,
36648L,36649L,36650L,36651L,36652L,36653L,36654L,36655L,36656L,36657L,
36658L,36659L,36660L,36661L,36662L,36663L,36664L,36665L,36666L,36667L,
36668L,36669L,36670L,36671L,36672L,36673L,36674L,36675L,36676L,36677L,
36678L,36679L,36680L,36681L,36682L,36683L,36684L,36685L,36686L,36687L,
36688L,36689L,36690L,36691L,36692L,36693L,36694L,36695L,36696L,36697L,
36698L,36699L,36700L,36701L,36702L,36703L,36704L,36705L,36706L,36707L,
36708L,36709L,36710L,36711L,36712L,36713L,36714L,36715L,36716L,36717L,
36718L,36719L,36720L,36721L,36722L,36723L,36724L,36725L,36726L,36727L,
36728L,36729L,36730L,36731L,36732L,36733L,36734L,36735L,36736L,36737L,
36738L,36739L,36740L,36741L,36742L,36743L,36744L,36745L,36746L,36747L,
36748L,36749L,36750L,36751L,36752L,36753L,36754L,36755L,36756L,36757L,
36758L,36759L,36760L,36761L,36762L,36763L,36764L,36765L,36766L,36767L,
36768L,36769L,36770L,36771L,36772L,36773L,36774L,36775L,36776L,36777L,
36778L,36779L,36780L,36781L,36782L,36783L,36784L,36785L,36786L,36787L,
36788L,36789L,36790L,36791L,36792L,36793L,36794L,36795L,36796L,36797L,
36798L,36799L,36800L,36801L,36802L,36803L,36804L,36805L,36806L,36807L,
36808L,36809L,36810L,36811L,36812L,36813L,36814L,36815L,36816L,36817L,
36818L,36819L,36820L,36821L,36822L,36823L,36824L,36825L,36826L,36827L,
36828L,36829L,36830L,36831L,36832L,36833L,36834L,36835L,36836L,36837L,
36838L,36839L,36840L,36841L,36842L,36843L,36844L,36845L,36846L,36847L,
36848L,36849L,36850L,36851L,36852L,36853L,36854L,36855L,36856L,36857L,
36858L,36859L,36860L,36861L,36862L,36863L,36864L,36865L,36866L,36867L,
36868L,36869L,36870L,36871L,36872L,36873L,36874L,36875L,36876L,36877L,
36878L,36879L,36880L,36881L,36882L,36883L,36884L,36885L,36886L,36887L,
36888L,36889L,36890L,36891L,36892L,36893L,36894L,36895L,36896L,36897L,
36898L,36899L,36900L,36901L,36902L,36903L,36904L,36905L,36906L,36907L,
36908L,36909L,36910L,36911L,36912L,36913L,36914L,36915L,36916L,36917L,
36918L,36919L,36920L,36921L,36922L,36923L,36924L,36925L,36926L,36927L,
36928L,36929L,36930L,36931L,36932L,36933L,36934L,36935L,36936L,36937L,
36938L,36939L,36940L,36941L,36942L,36943L,36944L,36945L,36946L,36947L,
36948L,36949L,36950L,36951L,36952L,36953L,36954L,36955L,36956L,36957L,
36958L,36959L,36960L,36961L,36962L,36963L,36964L,36965L,36966L,36967L,
36968L,36969L,36970L,36971L,36972L,36973L,36974L,36975L,36976L,36977L,
36978L,36979L,36980L,36981L,36982L,36983L,36984L,36985L,36986L,36987L,
36988L,36989L,36990L,36991L,36992L,36993L,36994L,36995L,36996L,36997L,
36998L,36999L,37000L,37001L,37002L,37003L,37004L,37005L,37006L,37007L,
37008L,37009L,37010L,37011L,37012L,37013L,37014L,37015L,37016L,37017L,
37018L,37019L,37020L,37021L,37022L,37023L,37024L,37025L,37026L,37027L,
37028L,37029L,37030L,37031L,37032L,37033L,37034L,37035L,37036L,37037L,
37038L,37039L,37040L,37041L,37042L,37043L,37044L,37045L,37046L,37047L,
37048L,37049L,37050L,37051L,37052L,37053L,37054L,37055L,37056L,37057L,
37058L,37059L,37060L,37061L,37062L,37063L,37064L,37065L,37066L,37067L,
37068L,37069L,37070L,37071L,37072L,37073L,37074L,37075L,37076L,37077L,
37078L,37079L,37080L,37081L,37082L,37083L,37084L,37085L,37086L,37087L,
37088L,37089L,37090L,37091L,37092L,37093L,37094L,37095L,37096L,37097L,
37098L,37099L,37100L,37101L,37102L,37103L,37104L,37105L,37106L,37107L,
37108L,37109L,37110L,37111L,37112L,37113L,37114L,37115L,37116L,37117L,
37118L,37119L,37120L,37121L,37122L,37123L,37124L,37125L,37126L,37127L,
37128L,37129L,37130L,37131L,37132L,37133L,37134L,37135L,37136L,37137L,
37138L,37139L,37140L,37141L,37142L,37143L,37144L,37145L,37146L,37147L,
37148L,37149L,37150L,37151L,37152L,37153L,37154L,37155L,37156L,37157L,
37158L,37159L,37160L,37161L,37162L,37163L,37164L,37165L,37166L,37167L,
37168L,37169L,37170L,37171L,37172L,37173L,37174L,37175L,37176L,37177L,
37178L,37179L,37180L,37181L,37182L,37183L,37184L,37185L,37186L,37187L,
37188L,37189L,37190L,37191L,37192L,37193L,37194L,37195L,37196L,37197L,
37198L,37199L,37200L,37201L,37202L,37203L,37204L,37205L,37206L,37207L,
37208L,37209L,37210L,37211L,37212L,37213L,37214L,37215L,37216L,37217L,
37218L,37219L,37220L,37221L,37222L,37223L,37224L,37225L,37226L,37227L,
37228L,37229L,37230L,37231L,37232L,37233L,37234L,37235L,37236L,37237L,
37238L,37239L,37240L,37241L,37242L,37243L,37244L,37245L,37246L,37247L,
37248L,37249L,37250L,37251L,37252L,37253L,37254L,37255L,37256L,37257L,
37258L,37259L,37260L,37261L,37262L,37263L,37264L,37265L,37266L,37267L,
37268L,37269L,37270L,37271L,37272L,37273L,37274L,37275L,37276L,37277L,
37278L,37279L,37280L,37281L,37282L,37283L,37284L,37285L,37286L,37287L,
37288L,37289L,37290L,37291L,37292L,37293L,37294L,37295L,37296L,37297L,
37298L,37299L,37300L,37301L,37302L,37303L,37304L,37305L,37306L,37307L,
37308L,37309L,37310L,37311L,37312L,37313L,37314L,37315L,37316L,37317L,
37318L,37319L,37320L,37321L,37322L,37323L,37324L,37325L,37326L,37327L,
37328L,37329L,37330L,37331L,37332L,37333L,37334L,37335L,37336L,37337L,
37338L,37339L,37340L,37341L,37342L,37343L,37344L,37345L,37346L,37347L,
37348L,37349L,37350L,37351L,37352L,37353L,37354L,37355L,37356L,37357L,
37358L,37359L,37360L,37361L,37362L,37363L,37364L,37365L,37366L,37367L,
37368L,37369L,37370L,37371L,37372L,37373L,37374L,37375L,37376L,37377L,
37378L,37379L,37380L,37381L,37382L,37383L,37384L,37385L,37386L,37387L,
37388L,37389L,37390L,37391L,37392L,37393L,37394L,37395L,37396L,37397L,
37398L,37399L,37400L,37401L,37402L,37403L,37404L,37405L,37406L,37407L,
37408L,37409L,37410L,37411L,37412L,37413L,37414L,37415L,37416L,37417L,
37418L,37419L,37420L,37421L,37422L,37423L,37424L,37425L,37426L,37427L,
37428L,37429L,37430L,37431L,37432L,37433L,37434L,37435L,37436L,37437L,
37438L,37439L,37440L,37441L,37442L,37443L,37444L,37445L,37446L,37447L,
37448L,37449L,37450L,37451L,37452L,37453L,37454L,37455L,37456L,37457L,
37458L,37459L,37460L,37461L,37462L,37463L,37464L,37465L,37466L,37467L,
37468L,37469L,37470L,37471L,37472L,37473L,37474L,37475L,37476L,37477L,
37478L,37479L,37480L,37481L,37482L,37483L,37484L,37485L,37486L,37487L,
37488L,37489L,37490L,37491L,37492L,37493L,37494L,37495L,37496L,37497L,
37498L,37499L,37500L,37501L,37502L,37503L,37504L,37505L,37506L,37507L,
37508L,37509L,37510L,37511L,37512L,37513L,37514L,37515L,37516L,37517L,
37518L,37519L,37520L,37521L,37522L,37523L,37524L,37525L,37526L,37527L,
37528L,37529L,37530L,37531L,37532L,37533L,37534L,37535L,37536L,37537L,
37538L,37539L,37540L,37541L,37542L,37543L,37544L,37545L,37546L,37547L,
37548L,37549L,37550L,37551L,37552L,37553L,37554L,37555L,37556L,37557L,
37558L,37559L,37560L,37561L,37562L,37563L,37564L,37565L,37566L,37567L,
37568L,37569L,37570L,37571L,37572L,37573L,37574L,37575L,37576L,37577L,
37578L,37579L,37580L,37581L,37582L,37583L,37584L,37585L,37586L,37587L,
37588L,37589L,37590L,37591L,37592L,37593L,37594L,37595L,37596L,37597L,
37598L,37599L,37600L,37601L,37602L,37603L,37604L,37605L,37606L,37607L,
37608L,37609L,37610L,37611L,37612L,37613L,37614L,37615L,37616L,37617L,
37618L,37619L,37620L,37621L,37622L,37623L,37624L,37625L,37626L,37627L,
37628L,37629L,37630L,37631L,37632L,37633L,37634L,37635L,37636L,37637L,
37638L,37639L,37640L,37641L,37642L,37643L,37644L,37645L,37646L,37647L,
37648L,37649L,37650L,37651L,37652L,37653L,37654L,37655L,37656L,37657L,
37658L,37659L,37660L,37661L,37662L,37663L,37664L,37665L,37666L,37667L,
37668L,37669L,37670L,37671L,37672L,37673L,37674L,37675L,37676L,37677L,
37678L,37679L,37680L,37681L,37682L,37683L,37684L,37685L,37686L,37687L,
37688L,37689L,37690L,37691L,37692L,37693L,37694L,37695L,37696L,37697L,
37698L,37699L,37700L,37701L,37702L,37703L,37704L,37705L,37706L,37707L,
37708L,37709L,37710L,37711L,37712L,37713L,37714L,37715L,37716L,37717L,
37718L,37719L,37720L,37721L,37722L,37723L,37724L,37725L,37726L,37727L,
37728L,37729L,37730L,37731L,37732L,37733L,37734L,37735L,37736L,37737L,
37738L,37739L,37740L,37741L,37742L,37743L,37744L,37745L,37746L,37747L,
37748L,37749L,37750L,37751L,37752L,37753L,37754L,37755L,37756L,37757L,
37758L,37759L,37760L,37761L,37762L,37763L,37764L,37765L,37766L,37767L,
37768L,37769L,37770L,37771L,37772L,37773L,37774L,37775L,37776L,37777L,
37778L,37779L,37780L,37781L,37782L,37783L,37784L,37785L,37786L,37787L,
37788L,37789L,37790L,37791L,37792L,37793L,37794L,37795L,37796L,37797L,
37798L,37799L,37800L,37801L,37802L,37803L,37804L,37805L,37806L,37807L,
37808L,37809L,37810L,37811L,37812L,37813L,37814L,37815L,37816L,37817L,
37818L,37819L,37820L,37821L,37822L,37823L,37824L,37825L,37826L,37827L,
37828L,37829L,37830L,37831L,37832L,37833L,37834L,37835L,37836L,37837L,
37838L,37839L,37840L,37841L,37842L,37843L,37844L,37845L,37846L,37847L,
37848L,37849L,37850L,37851L,37852L,37853L,37854L,37855L,37856L,37857L,
37858L,37859L,37860L,37861L,37862L,37863L,37864L,37865L,37866L,37867L,
37868L,37869L,37870L,37871L,37872L,37873L,37874L,37875L,37876L,37877L,
37878L,37879L,37880L,37881L,37882L,37883L,37884L,37885L,37886L,37887L,
37888L,37889L,37890L,37891L,37892L,37893L,37894L,37895L,37896L,37897L,
37898L,37899L,37900L,37901L,37902L,37903L,37904L,37905L,37906L,37907L,
37908L,37909L,37910L,37911L,37912L,37913L,37914L,37915L,37916L,37917L,
37918L,37919L,37920L,37921L,37922L,37923L,37924L,37925L,37926L,37927L,
37928L,37929L,37930L,37931L,37932L,37933L,37934L,37935L,37936L,37937L,
37938L,37939L,37940L,37941L,37942L,37943L,37944L,37945L,37946L,37947L,
37948L,37949L,37950L,37951L,37952L,37953L,37954L,37955L,37956L,37957L,
37958L,37959L,37960L,37961L,37962L,37963L,37964L,37965L,37966L,37967L,
37968L,37969L,37970L,37971L,37972L,37973L,37974L,37975L,37976L,37977L,
37978L,37979L,37980L,37981L,37982L,37983L,37984L,37985L,37986L,37987L,
37988L,37989L,37990L,37991L,37992L,37993L,37994L,37995L,37996L,37997L,
37998L,37999L,38000L,38001L,38002L,38003L,38004L,38005L,38006L,38007L,
38008L,38009L,38010L,38011L,38012L,38013L,38014L,38015L,38016L,38017L,
38018L,38019L,38020L,38021L,38022L,38023L,38024L,38025L,38026L,38027L,
38028L,38029L,38030L,38031L,38032L,38033L,38034L,38035L,38036L,38037L,
38038L,38039L,38040L,38041L,38042L,38043L,38044L,38045L,38046L,38047L,
38048L,38049L,38050L,38051L,38052L,38053L,38054L,38055L,38056L,38057L,
38058L,38059L,38060L,38061L,38062L,38063L,38064L,38065L,38066L,38067L,
38068L,38069L,38070L,38071L,38072L,38073L,38074L,38075L,38076L,38077L,
38078L,38079L,38080L,38081L,38082L,38083L,38084L,38085L,38086L,38087L,
38088L,38089L,38090L,38091L,38092L,38093L,38094L,38095L,38096L,38097L,
38098L,38099L,38100L,38101L,38102L,38103L,38104L,38105L,38106L,38107L,
38108L,38109L,38110L,38111L,38112L,38113L,38114L,38115L,38116L,38117L,
38118L,38119L,38120L,38121L,38122L,38123L,38124L,38125L,38126L,38127L,
38128L,38129L,38130L,38131L,38132L,38133L,38134L,38135L,38136L,38137L,
38138L,38139L,38140L,38141L,38142L,38143L,38144L,38145L,38146L,38147L,
38148L,38149L,38150L,38151L,38152L,38153L,38154L,38155L,38156L,38157L,
38158L,38159L,38160L,38161L,38162L,38163L,38164L,38165L,38166L,38167L,
38168L,38169L,38170L,38171L,38172L,38173L,38174L,38175L,38176L,38177L,
38178L,38179L,38180L,38181L,38182L,38183L,38184L,38185L,38186L,38187L,
38188L,38189L,38190L,38191L,38192L,38193L,38194L,38195L,38196L,38197L,
38198L,38199L,38200L,38201L,38202L,38203L,38204L,38205L,38206L,38207L,
38208L,38209L,38210L,38211L,38212L,38213L,38214L,38215L,38216L,38217L,
38218L,38219L,38220L,38221L,38222L,38223L,38224L,38225L,38226L,38227L,
38228L,38229L,38230L,38231L,38232L,38233L,38234L,38235L,38236L,38237L,
38238L,38239L,38240L,38241L,38242L,38243L,38244L,38245L,38246L,38247L,
38248L,38249L,38250L,38251L,38252L,38253L,38254L,38255L,38256L,38257L,
38258L,38259L,38260L,38261L,38262L,38263L,38264L,38265L,38266L,38267L,
38268L,38269L,38270L,38271L,38272L,38273L,38274L,38275L,38276L,38277L,
38278L,38279L,38280L,38281L,38282L,38283L,38284L,38285L,38286L,38287L,
38288L,38289L,38290L,38291L,38292L,38293L,38294L,38295L,38296L,38297L,
38298L,38299L,38300L,38301L,38302L,38303L,38304L,38305L,38306L,38307L,
38308L,38309L,38310L,38311L,38312L,38313L,38314L,38315L,38316L,38317L,
38318L,38319L,38320L,38321L,38322L,38323L,38324L,38325L,38326L,38327L,
38328L,38329L,38330L,38331L,38332L,38333L,38334L,38335L,38336L,38337L,
38338L,38339L,38340L,38341L,38342L,38343L,38344L,38345L,38346L,38347L,
38348L,38349L,38350L,38351L,38352L,38353L,38354L,38355L,38356L,38357L,
38358L,38359L,38360L,38361L,38362L,38363L,38364L,38365L,38366L,38367L,
38368L,38369L,38370L,38371L,38372L,38373L,38374L,38375L,38376L,38377L,
38378L,38379L,38380L,38381L,38382L,38383L,38384L,38385L,38386L,38387L,
38388L,38389L,38390L,38391L,38392L,38393L,38394L,38395L,38396L,38397L,
38398L,38399L,38400L,38401L,38402L,38403L,38404L,38405L,38406L,38407L,
38408L,38409L,38410L,38411L,38412L,38413L,38414L,38415L,38416L,38417L,
38418L,38419L,38420L,38421L,38422L,38423L,38424L,38425L,38426L,38427L,
38428L,38429L,38430L,38431L,38432L,38433L,38434L,38435L,38436L,38437L,
38438L,38439L,38440L,38441L,38442L,38443L,38444L,38445L,38446L,38447L,
38448L,38449L,38450L,38451L,38452L,38453L,38454L,38455L,38456L,38457L,
38458L,38459L,38460L,38461L,38462L,38463L,38464L,38465L,38466L,38467L,
38468L,38469L,38470L,38471L,38472L,38473L,38474L,38475L,38476L,38477L,
38478L,38479L,38480L,38481L,38482L,38483L,38484L,38485L,38486L,38487L,
38488L,38489L,38490L,38491L,38492L,38493L,38494L,38495L,38496L,38497L,
38498L,38499L,38500L,38501L,38502L,38503L,38504L,38505L,38506L,38507L,
38508L,38509L,38510L,38511L,38512L,38513L,38514L,38515L,38516L,38517L,
38518L,38519L,38520L,38521L,38522L,38523L,38524L,38525L,38526L,38527L,
38528L,38529L,38530L,38531L,38532L,38533L,38534L,38535L,38536L,38537L,
38538L,38539L,38540L,38541L,38542L,38543L,38544L,38545L,38546L,38547L,
38548L,38549L,38550L,38551L,38552L,38553L,38554L,38555L,38556L,38557L,
38558L,38559L,38560L,38561L,38562L,38563L,38564L,38565L,38566L,38567L,
38568L,38569L,38570L,38571L,38572L,38573L,38574L,38575L,38576L,38577L,
38578L,38579L,38580L,38581L,38582L,38583L,38584L,38585L,38586L,38587L,
38588L,38589L,38590L,38591L,38592L,38593L,38594L,38595L,38596L,38597L,
38598L,38599L,38600L,38601L,38602L,38603L,38604L,38605L,38606L,38607L,
38608L,38609L,38610L,38611L,38612L,38613L,38614L,38615L,38616L,38617L,
38618L,38619L,38620L,38621L,38622L,38623L,38624L,38625L,38626L,38627L,
38628L,38629L,38630L,38631L,38632L,38633L,38634L,38635L,38636L,38637L,
38638L,38639L,38640L,38641L,38642L,38643L,38644L,38645L,38646L,38647L,
38648L,38649L,38650L,38651L,38652L,38653L,38654L,38655L,38656L,38657L,
38658L,38659L,38660L,38661L,38662L,38663L,38664L,38665L,38666L,38667L,
38668L,38669L,38670L,38671L,38672L,38673L,38674L,38675L,38676L,38677L,
38678L,38679L,38680L,38681L,38682L,38683L,38684L,38685L,38686L,38687L,
38688L,38689L,38690L,38691L,38692L,38693L,38694L,38695L,38696L,38697L,
38698L,38699L,38700L,38701L,38702L,38703L,38704L,38705L,38706L,38707L,
38708L,38709L,38710L,38711L,38712L,38713L,38714L,38715L,38716L,38717L,
38718L,38719L,38720L,38721L,38722L,38723L,38724L,38725L,38726L,38727L,
38728L,38729L,38730L,38731L,38732L,38733L,38734L,38735L,38736L,38737L,
38738L,38739L,38740L,38741L,38742L,38743L,38744L,38745L,38746L,38747L,
38748L,38749L,38750L,38751L,38752L,38753L,38754L,38755L,38756L,38757L,
38758L,38759L,38760L,38761L,38762L,38763L,38764L,38765L,38766L,38767L,
38768L,38769L,38770L,38771L,38772L,38773L,38774L,38775L,38776L,38777L,
38778L,38779L,38780L,38781L,38782L,38783L,38784L,38785L,38786L,38787L,
38788L,38789L,38790L,38791L,38792L,38793L,38794L,38795L,38796L,38797L,
38798L,38799L,38800L,38801L,38802L,38803L,38804L,38805L,38806L,38807L,
38808L,38809L,38810L,38811L,38812L,38813L,38814L,38815L,38816L,38817L,
38818L,38819L,38820L,38821L,38822L,38823L,38824L,38825L,38826L,38827L,
38828L,38829L,38830L,38831L,38832L,38833L,38834L,38835L,38836L,38837L,
38838L,38839L,38840L,38841L,38842L,38843L,38844L,38845L,38846L,38847L,
38848L,38849L,38850L,38851L,38852L,38853L,38854L,38855L,38856L,38857L,
38858L,38859L,38860L,38861L,38862L,38863L,38864L,38865L,38866L,38867L,
38868L,38869L,38870L,38871L,38872L,38873L,38874L,38875L,38876L,38877L,
38878L,38879L,38880L,38881L,38882L,38883L,38884L,38885L,38886L,38887L,
38888L,38889L,38890L,38891L,38892L,38893L,38894L,38895L,38896L,38897L,
38898L,38899L,38900L,38901L,38902L,38903L,38904L,38905L,38906L,38907L,
38908L,38909L,38910L,38911L,38912L,38913L,38914L,38915L,38916L,38917L,
38918L,38919L,38920L,38921L,38922L,38923L,38924L,38925L,38926L,38927L,
38928L,38929L,38930L,38931L,38932L,38933L,38934L,38935L,38936L,38937L,
38938L,38939L,38940L,38941L,38942L,38943L,38944L,38945L,38946L,38947L,
38948L,38949L,38950L,38951L,38952L,38953L,38954L,38955L,38956L,38957L,
38958L,38959L,38960L,38961L,38962L,38963L,38964L,38965L,38966L,38967L,
38968L,38969L,38970L,38971L,38972L,38973L,38974L,38975L,38976L,38977L,
38978L,38979L,38980L,38981L,38982L,38983L,38984L,38985L,38986L,38987L,
38988L,38989L,38990L,38991L,38992L,38993L,38994L,38995L,38996L,38997L,
38998L,38999L,39000L,39001L,39002L,39003L,39004L,39005L,39006L,39007L,
39008L,39009L,39010L,39011L,39012L,39013L,39014L,39015L,39016L,39017L,
39018L,39019L,39020L,39021L,39022L,39023L,39024L,39025L,39026L,39027L,
39028L,39029L,39030L,39031L,39032L,39033L,39034L,39035L,39036L,39037L,
39038L,39039L,39040L,39041L,39042L,39043L,39044L,39045L,39046L,39047L,
39048L,39049L,39050L,39051L,39052L,39053L,39054L,39055L,39056L,39057L,
39058L,39059L,39060L,39061L,39062L,39063L,39064L,39065L,39066L,39067L,
39068L,39069L,39070L,39071L,39072L,39073L,39074L,39075L,39076L,39077L,
39078L,39079L,39080L,39081L,39082L,39083L,39084L,39085L,39086L,39087L,
39088L,39089L,39090L,39091L,39092L,39093L,39094L,39095L,39096L,39097L,
39098L,39099L,39100L,39101L,39102L,39103L,39104L,39105L,39106L,39107L,
39108L,39109L,39110L,39111L,39112L,39113L,39114L,39115L,39116L,39117L,
39118L,39119L,39120L,39121L,39122L,39123L,39124L,39125L,39126L,39127L,
39128L,39129L,39130L,39131L,39132L,39133L,39134L,39135L,39136L,39137L,
39138L,39139L,39140L,39141L,39142L,39143L,39144L,39145L,39146L,39147L,
39148L,39149L,39150L,39151L,39152L,39153L,39154L,39155L,39156L,39157L,
39158L,39159L,39160L,39161L,39162L,39163L,39164L,39165L,39166L,39167L,
39168L,39169L,39170L,39171L,39172L,39173L,39174L,39175L,39176L,39177L,
39178L,39179L,39180L,39181L,39182L,39183L,39184L,39185L,39186L,39187L,
39188L,39189L,39190L,39191L,39192L,39193L,39194L,39195L,39196L,39197L,
39198L,39199L,39200L,39201L,39202L,39203L,39204L,39205L,39206L,39207L,
39208L,39209L,39210L,39211L,39212L,39213L,39214L,39215L,39216L,39217L,
39218L,39219L,39220L,39221L,39222L,39223L,39224L,39225L,39226L,39227L,
39228L,39229L,39230L,39231L,39232L,39233L,39234L,39235L,39236L,39237L,
39238L,39239L,39240L,39241L,39242L,39243L,39244L,39245L,39246L,39247L,
39248L,39249L,39250L,39251L,39252L,39253L,39254L,39255L,39256L,39257L,
39258L,39259L,39260L,39261L,39262L,39263L,39264L,39265L,39266L,39267L,
39268L,39269L,39270L,39271L,39272L,39273L,39274L,39275L,39276L,39277L,
39278L,39279L,39280L,39281L,39282L,39283L,39284L,39285L,39286L,39287L,
39288L,39289L,39290L,39291L,39292L,39293L,39294L,39295L,39296L,39297L,
39298L,39299L,39300L,39301L,39302L,39303L,39304L,39305L,39306L,39307L,
39308L,39309L,39310L,39311L,39312L,39313L,39314L,39315L,39316L,39317L,
39318L,39319L,39320L,39321L,39322L,39323L,39324L,39325L,39326L,39327L,
39328L,39329L,39330L,39331L,39332L,39333L,39334L,39335L,39336L,39337L,
39338L,39339L,39340L,39341L,39342L,39343L,39344L,39345L,39346L,39347L,
39348L,39349L,39350L,39351L,39352L,39353L,39354L,39355L,39356L,39357L,
39358L,39359L,39360L,39361L,39362L,39363L,39364L,39365L,39366L,39367L,
39368L,39369L,39370L,39371L,39372L,39373L,39374L,39375L,39376L,39377L,
39378L,39379L,39380L,39381L,39382L,39383L,39384L,39385L,39386L,39387L,
39388L,39389L,39390L,39391L,39392L,39393L,39394L,39395L,39396L,39397L,
39398L,39399L,39400L,39401L,39402L,39403L,39404L,39405L,39406L,39407L,
39408L,39409L,39410L,39411L,39412L,39413L,39414L,39415L,39416L,39417L,
39418L,39419L,39420L,39421L,39422L,39423L,39424L,39425L,39426L,39427L,
39428L,39429L,39430L,39431L,39432L,39433L,39434L,39435L,39436L,39437L,
39438L,39439L,39440L,39441L,39442L,39443L,39444L,39445L,39446L,39447L,
39448L,39449L,39450L,39451L,39452L,39453L,39454L,39455L,39456L,39457L,
39458L,39459L,39460L,39461L,39462L,39463L,39464L,39465L,39466L,39467L,
39468L,39469L,39470L,39471L,39472L,39473L,39474L,39475L,39476L,39477L,
39478L,39479L,39480L,39481L,39482L,39483L,39484L,39485L,39486L,39487L,
39488L,39489L,39490L,39491L,39492L,39493L,39494L,39495L,39496L,39497L,
39498L,39499L,39500L,39501L,39502L,39503L,39504L,39505L,39506L,39507L,
39508L,39509L,39510L,39511L,39512L,39513L,39514L,39515L,39516L,39517L,
39518L,39519L,39520L,39521L,39522L,39523L,39524L,39525L,39526L,39527L,
39528L,39529L,39530L,39531L,39532L,39533L,39534L,39535L,39536L,39537L,
39538L,39539L,39540L,39541L,39542L,39543L,39544L,39545L,39546L,39547L,
39548L,39549L,39550L,39551L,39552L,39553L,39554L,39555L,39556L,39557L,
39558L,39559L,39560L,39561L,39562L,39563L,39564L,39565L,39566L,39567L,
39568L,39569L,39570L,39571L,39572L,39573L,39574L,39575L,39576L,39577L,
39578L,39579L,39580L,39581L,39582L,39583L,39584L,39585L,39586L,39587L,
39588L,39589L,39590L,39591L,39592L,39593L,39594L,39595L,39596L,39597L,
39598L,39599L,39600L,39601L,39602L,39603L,39604L,39605L,39606L,39607L,
39608L,39609L,39610L,39611L,39612L,39613L,39614L,39615L,39616L,39617L,
39618L,39619L,39620L,39621L,39622L,39623L,39624L,39625L,39626L,39627L,
39628L,39629L,39630L,39631L,39632L,39633L,39634L,39635L,39636L,39637L,
39638L,39639L,39640L,39641L,39642L,39643L,39644L,39645L,39646L,39647L,
39648L,39649L,39650L,39651L,39652L,39653L,39654L,39655L,39656L,39657L,
39658L,39659L,39660L,39661L,39662L,39663L,39664L,39665L,39666L,39667L,
39668L,39669L,39670L,39671L,39672L,39673L,39674L,39675L,39676L,39677L,
39678L,39679L,39680L,39681L,39682L,39683L,39684L,39685L,39686L,39687L,
39688L,39689L,39690L,39691L,39692L,39693L,39694L,39695L,39696L,39697L,
39698L,39699L,39700L,39701L,39702L,39703L,39704L,39705L,39706L,39707L,
39708L,39709L,39710L,39711L,39712L,39713L,39714L,39715L,39716L,39717L,
39718L,39719L,39720L,39721L,39722L,39723L,39724L,39725L,39726L,39727L,
39728L,39729L,39730L,39731L,39732L,39733L,39734L,39735L,39736L,39737L,
39738L,39739L,39740L,39741L,39742L,39743L,39744L,39745L,39746L,39747L,
39748L,39749L,39750L,39751L,39752L,39753L,39754L,39755L,39756L,39757L,
39758L,39759L,39760L,39761L,39762L,39763L,39764L,39765L,39766L,39767L,
39768L,39769L,39770L,39771L,39772L,39773L,39774L,39775L,39776L,39777L,
39778L,39779L,39780L,39781L,39782L,39783L,39784L,39785L,39786L,39787L,
39788L,39789L,39790L,39791L,39792L,39793L,39794L,39795L,39796L,39797L,
39798L,39799L,39800L,39801L,39802L,39803L,39804L,39805L,39806L,39807L,
39808L,39809L,39810L,39811L,39812L,39813L,39814L,39815L,39816L,39817L,
39818L,39819L,39820L,39821L,39822L,39823L,39824L,39825L,39826L,39827L,
39828L,39829L,39830L,39831L,39832L,39833L,39834L,39835L,39836L,39837L,
39838L,39839L,39840L,39841L,39842L,39843L,39844L,39845L,39846L,39847L,
39848L,39849L,39850L,39851L,39852L,39853L,39854L,39855L,39856L,39857L,
39858L,39859L,39860L,39861L,39862L,39863L,39864L,39865L,39866L,39867L,
39868L,39869L,39870L,39871L,39872L,39873L,39874L,39875L,39876L,39877L,
39878L,39879L,39880L,39881L,39882L,39883L,39884L,39885L,39886L,39887L,
39888L,39889L,39890L,39891L,39892L,39893L,39894L,39895L,39896L,39897L,
39898L,39899L,39900L,39901L,39902L,39903L,39904L,39905L,39906L,39907L,
39908L,39909L,39910L,39911L,39912L,39913L,39914L,39915L,39916L,39917L,
39918L,39919L,39920L,39921L,39922L,39923L,39924L,39925L,39926L,39927L,
39928L,39929L,39930L,39931L,39932L,39933L,39934L,39935L,39936L,39937L,
39938L,39939L,39940L,39941L,39942L,39943L,39944L,39945L,39946L,39947L,
39948L,39949L,39950L,39951L,39952L,39953L,39954L,39955L,39956L,39957L,
39958L,39959L,39960L,39961L,39962L,39963L,39964L,39965L,39966L,39967L,
39968L,39969L,39970L,39971L,39972L,39973L,39974L,39975L,39976L,39977L,
39978L,39979L,39980L,39981L,39982L,39983L,39984L,39985L,39986L,39987L,
39988L,39989L,39990L,39991L,39992L,39993L,39994L,39995L,39996L,39997L,
39998L,39999L,40000L,40001L,40002L,40003L,40004L,40005L,40006L,40007L,
40008L,40009L,40010L,40011L,40012L,40013L,40014L,40015L,40016L,40017L,
40018L,40019L,40020L,40021L,40022L,40023L,40024L,40025L,40026L,40027L,
40028L,40029L,40030L,40031L,40032L,40033L,40034L,40035L,40036L,40037L,
40038L,40039L,40040L,40041L,40042L,40043L,40044L,40045L,40046L,40047L,
40048L,40049L,40050L,40051L,40052L,40053L,40054L,40055L,40056L,40057L,
40058L,40059L,40060L,40061L,40062L,40063L,40064L,40065L,40066L,40067L,
40068L,40069L,40070L,40071L,40072L,40073L,40074L,40075L,40076L,40077L,
40078L,40079L,40080L,40081L,40082L,40083L,40084L,40085L,40086L,40087L,
40088L,40089L,40090L,40091L,40092L,40093L,40094L,40095L,40096L,40097L,
40098L,40099L,40100L,40101L,40102L,40103L,40104L,40105L,40106L,40107L,
40108L,40109L,40110L,40111L,40112L,40113L,40114L,40115L,40116L,40117L,
40118L,40119L,40120L,40121L,40122L,40123L,40124L,40125L,40126L,40127L,
40128L,40129L,40130L,40131L,40132L,40133L,40134L,40135L,40136L,40137L,
40138L,40139L,40140L,40141L,40142L,40143L,40144L,40145L,40146L,40147L,
40148L,40149L,40150L,40151L,40152L,40153L,40154L,40155L,40156L,40157L,
40158L,40159L,40160L,40161L,40162L,40163L,40164L,40165L,40166L,40167L,
40168L,40169L,40170L,40171L,40172L,40173L,40174L,40175L,40176L,40177L,
40178L,40179L,40180L,40181L,40182L,40183L,40184L,40185L,40186L,40187L,
40188L,40189L,40190L,40191L,40192L,40193L,40194L,40195L,40196L,40197L,
40198L,40199L,40200L,40201L,40202L,40203L,40204L,40205L,40206L,40207L,
40208L,40209L,40210L,40211L,40212L,40213L,40214L,40215L,40216L,40217L,
40218L,40219L,40220L,40221L,40222L,40223L,40224L,40225L,40226L,40227L,
40228L,40229L,40230L,40231L,40232L,40233L,40234L,40235L,40236L,40237L,
40238L,40239L,40240L,40241L,40242L,40243L,40244L,40245L,40246L,40247L,
40248L,40249L,40250L,40251L,40252L,40253L,40254L,40255L,40256L,40257L,
40258L,40259L,40260L,40261L,40262L,40263L,40264L,40265L,40266L,40267L,
40268L,40269L,40270L,40271L,40272L,40273L,40274L,40275L,40276L,40277L,
40278L,40279L,40280L,40281L,40282L,40283L,40284L,40285L,40286L,40287L,
40288L,40289L,40290L,40291L,40292L,40293L,40294L,40295L,40296L,40297L,
40298L,40299L,40300L,40301L,40302L,40303L,40304L,40305L,40306L,40307L,
40308L,40309L,40310L,40311L,40312L,40313L,40314L,40315L,40316L,40317L,
40318L,40319L,40320L,40321L,40322L,40323L,40324L,40325L,40326L,40327L,
40328L,40329L,40330L,40331L,40332L,40333L,40334L,40335L,40336L,40337L,
40338L,40339L,40340L,40341L,40342L,40343L,40344L,40345L,40346L,40347L,
40348L,40349L,40350L,40351L,40352L,40353L,40354L,40355L,40356L,40357L,
40358L,40359L,40360L,40361L,40362L,40363L,40364L,40365L,40366L,40367L,
40368L,40369L,40370L,40371L,40372L,40373L,40374L,40375L,40376L,40377L,
40378L,40379L,40380L,40381L,40382L,40383L,40384L,40385L,40386L,40387L,
40388L,40389L,40390L,40391L,40392L,40393L,40394L,40395L,40396L,40397L,
40398L,40399L,40400L,40401L,40402L,40403L,40404L,40405L,40406L,40407L,
40408L,40409L,40410L,40411L,40412L,40413L,40414L,40415L,40416L,40417L,
40418L,40419L,40420L,40421L,40422L,40423L,40424L,40425L,40426L,40427L,
40428L,40429L,40430L,40431L,40432L,40433L,40434L,40435L,40436L,40437L,
40438L,40439L,40440L,40441L,40442L,40443L,40444L,40445L,40446L,40447L,
40448L,40449L,40450L,40451L,40452L,40453L,40454L,40455L,40456L,40457L,
40458L,40459L,40460L,40461L,40462L,40463L,40464L,40465L,40466L,40467L,
40468L,40469L,40470L,40471L,40472L,40473L,40474L,40475L,40476L,40477L,
40478L,40479L,40480L,40481L,40482L,40483L,40484L,40485L,40486L,40487L,
40488L,40489L,40490L,40491L,40492L,40493L,40494L,40495L,40496L,40497L,
40498L,40499L,40500L,40501L,40502L,40503L,40504L,40505L,40506L,40507L,
40508L,40509L,40510L,40511L,40512L,40513L,40514L,40515L,40516L,40517L,
40518L,40519L,40520L,40521L,40522L,40523L,40524L,40525L,40526L,40527L,
40528L,40529L,40530L,40531L,40532L,40533L,40534L,40535L,40536L,40537L,
40538L,40539L,40540L,40541L,40542L,40543L,40544L,40545L,40546L,40547L,
40548L,40549L,40550L,40551L,40552L,40553L,40554L,40555L,40556L,40557L,
40558L,40559L,40560L,40561L,40562L,40563L,40564L,40565L,40566L,40567L,
40568L,40569L,40570L,40571L,40572L,40573L,40574L,40575L,40576L,40577L,
40578L,40579L,40580L,40581L,40582L,40583L,40584L,40585L,40586L,40587L,
40588L,40589L,40590L,40591L,40592L,40593L,40594L,40595L,40596L,40597L,
40598L,40599L,40600L,40601L,40602L,40603L,40604L,40605L,40606L,40607L,
40608L,40609L,40610L,40611L,40612L,40613L,40614L,40615L,40616L,40617L,
40618L,40619L,40620L,40621L,40622L,40623L,40624L,40625L,40626L,40627L,
40628L,40629L,40630L,40631L,40632L,40633L,40634L,40635L,40636L,40637L,
40638L,40639L,40640L,40641L,40642L,40643L,40644L,40645L,40646L,40647L,
40648L,40649L,40650L,40651L,40652L,40653L,40654L,40655L,40656L,40657L,
40658L,40659L,40660L,40661L,40662L,40663L,40664L,40665L,40666L,40667L,
40668L,40669L,40670L,40671L,40672L,40673L,40674L,40675L,40676L,40677L,
40678L,40679L,40680L,40681L,40682L,40683L,40684L,40685L,40686L,40687L,
40688L,40689L,40690L,40691L,40692L,40693L,40694L,40695L,40696L,40697L,
40698L,40699L,40700L,40701L,40702L,40703L,40704L,40705L,40706L,40707L,
40708L,40709L,40710L,40711L,40712L,40713L,40714L,40715L,40716L,40717L,
40718L,40719L,40720L,40721L,40722L,40723L,40724L,40725L,40726L,40727L,
40728L,40729L,40730L,40731L,40732L,40733L,40734L,40735L,40736L,40737L,
40738L,40739L,40740L,40741L,40742L,40743L,40744L,40745L,40746L,40747L,
40748L,40749L,40750L,40751L,40752L,40753L,40754L,40755L,40756L,40757L,
40758L,40759L,40760L,40761L,40762L,40763L,40764L,40765L,40766L,40767L,
40768L,40769L,40770L,40771L,40772L,40773L,40774L,40775L,40776L,40777L,
40778L,40779L,40780L,40781L,40782L,40783L,40784L,40785L,40786L,40787L,
40788L,40789L,40790L,40791L,40792L,40793L,40794L,40795L,40796L,40797L,
40798L,40799L,40800L,40801L,40802L,40803L,40804L,40805L,40806L,40807L,
40808L,40809L,40810L,40811L,40812L,40813L,40814L,40815L,40816L,40817L,
40818L,40819L,40820L,40821L,40822L,40823L,40824L,40825L,40826L,40827L,
40828L,40829L,40830L,40831L,40832L,40833L,40834L,40835L,40836L,40837L,
40838L,40839L,40840L,40841L,40842L,40843L,40844L,40845L,40846L,40847L,
40848L,40849L,40850L,40851L,40852L,40853L,40854L,40855L,40856L,40857L,
40858L,40859L,40860L,40861L,40862L,40863L,40864L,40865L,40866L,40867L,
40868L,40869L,40870L,40871L,40872L,40873L,40874L,40875L,40876L,40877L,
40878L,40879L,40880L,40881L,40882L,40883L,40884L,40885L,40886L,40887L,
40888L,40889L,40890L,40891L,40892L,40893L,40894L,40895L,40896L,40897L,
40898L,40899L,40900L,40901L,40902L,40903L,40904L,40905L,40906L,40907L,
40908L,40909L,40910L,40911L,40912L,40913L,40914L,40915L,40916L,40917L,
40918L,40919L,40920L,40921L,40922L,40923L,40924L,40925L,40926L,40927L,
40928L,40929L,40930L,40931L,40932L,40933L,40934L,40935L,40936L,40937L,
40938L,40939L,40940L,40941L,40942L,40943L,40944L,40945L,40946L,40947L,
40948L,40949L,40950L,40951L,40952L,40953L,40954L,40955L,40956L,40957L,
40958L,40959L,40960L,40961L,40962L,40963L,40964L,40965L,40966L,40967L,
40968L,40969L,40970L,40971L,40972L,40973L,40974L,40975L,40976L,40977L,
40978L,40979L,40980L,40981L,40982L,40983L,40984L,40985L,40986L,40987L,
40988L,40989L,40990L,40991L,40992L,40993L,40994L,40995L,40996L,40997L,
40998L,40999L,41000L,41001L,41002L,41003L,41004L,41005L,41006L,41007L,
41008L,41009L,41010L,41011L,41012L,41013L,41014L,41015L,41016L,41017L,
41018L,41019L,41020L,41021L,41022L,41023L,41024L,41025L,41026L,41027L,
41028L,41029L,41030L,41031L,41032L,41033L,41034L,41035L,41036L,41037L,
41038L,41039L,41040L,41041L,41042L,41043L,41044L,41045L,41046L,41047L,
41048L,41049L,41050L,41051L,41052L,41053L,41054L,41055L,41056L,41057L,
41058L,41059L,41060L,41061L,41062L,41063L,41064L,41065L,41066L,41067L,
41068L,41069L,41070L,41071L,41072L,41073L,41074L,41075L,41076L,41077L,
41078L,41079L,41080L,41081L,41082L,41083L,41084L,41085L,41086L,41087L,
41088L,41089L,41090L,41091L,41092L,41093L,41094L,41095L,41096L,41097L,
41098L,41099L,41100L,41101L,41102L,41103L,41104L,41105L,41106L,41107L,
41108L,41109L,41110L,41111L,41112L,41113L,41114L,41115L,41116L,41117L,
41118L,41119L,41120L,41121L,41122L,41123L,41124L,41125L,41126L,41127L,
41128L,41129L,41130L,41131L,41132L,41133L,41134L,41135L,41136L,41137L,
41138L,41139L,41140L,41141L,41142L,41143L,41144L,41145L,41146L,41147L,
41148L,41149L,41150L,41151L,41152L,41153L,41154L,41155L,41156L,41157L,
41158L,41159L,41160L,41161L,41162L,41163L,41164L,41165L,41166L,41167L,
41168L,41169L,41170L,41171L,41172L,41173L,41174L,41175L,41176L,41177L,
41178L,41179L,41180L,41181L,41182L,41183L,41184L,41185L,41186L,41187L,
41188L,41189L,41190L,41191L,41192L,41193L,41194L,41195L,41196L,41197L,
41198L,41199L,41200L,41201L,41202L,41203L,41204L,41205L,41206L,41207L,
41208L,41209L,41210L,41211L,41212L,41213L,41214L,41215L,41216L,41217L,
41218L,41219L,41220L,41221L,41222L,41223L,41224L,41225L,41226L,41227L,
41228L,41229L,41230L,41231L,41232L,41233L,41234L,41235L,41236L,41237L,
41238L,41239L,41240L,41241L,41242L,41243L,41244L,41245L,41246L,41247L,
41248L,41249L,41250L,41251L,41252L,41253L,41254L,41255L,41256L,41257L,
41258L,41259L,41260L,41261L,41262L,41263L,41264L,41265L,41266L,41267L,
41268L,41269L,41270L,41271L,41272L,41273L,41274L,41275L,41276L,41277L,
41278L,41279L,41280L,41281L,41282L,41283L,41284L,41285L,41286L,41287L,
41288L,41289L,41290L,41291L,41292L,41293L,41294L,41295L,41296L,41297L,
41298L,41299L,41300L,41301L,41302L,41303L,41304L,41305L,41306L,41307L,
41308L,41309L,41310L,41311L,41312L,41313L,41314L,41315L,41316L,41317L,
41318L,41319L,41320L,41321L,41322L,41323L,41324L,41325L,41326L,41327L,
41328L,41329L,41330L,41331L,41332L,41333L,41334L,41335L,41336L,41337L,
41338L,41339L,41340L,41341L,41342L,41343L,41344L,41345L,41346L,41347L,
41348L,41349L,41350L,41351L,41352L,41353L,41354L,41355L,41356L,41357L,
41358L,41359L,41360L,41361L,41362L,41363L,41364L,41365L,41366L,41367L,
41368L,41369L,41370L,41371L,41372L,41373L,41374L,41375L,41376L,41377L,
41378L,41379L,41380L,41381L,41382L,41383L,41384L,41385L,41386L,41387L,
41388L,41389L,41390L,41391L,41392L,41393L,41394L,41395L,41396L,41397L,
41398L,41399L,41400L,41401L,41402L,41403L,41404L,41405L,41406L,41407L,
41408L,41409L,41410L,41411L,41412L,41413L,41414L,41415L,41416L,41417L,
41418L,41419L,41420L,41421L,41422L,41423L,41424L,41425L,41426L,41427L,
41428L,41429L,41430L,41431L,41432L,41433L,41434L,41435L,41436L,41437L,
41438L,41439L,41440L,41441L,41442L,41443L,41444L,41445L,41446L,41447L,
41448L,41449L,41450L,41451L,41452L,41453L,41454L,41455L,41456L,41457L,
41458L,41459L,41460L,41461L,41462L,41463L,41464L,41465L,41466L,41467L,
41468L,41469L,41470L,41471L,41472L,41473L,41474L,41475L,41476L,41477L,
41478L,41479L,41480L,41481L,41482L,41483L,41484L,41485L,41486L,41487L,
41488L,41489L,41490L,41491L,41492L,41493L,41494L,41495L,41496L,41497L,
41498L,41499L,41500L,41501L,41502L,41503L,41504L,41505L,41506L,41507L,
41508L,41509L,41510L,41511L,41512L,41513L,41514L,41515L,41516L,41517L,
41518L,41519L,41520L,41521L,41522L,41523L,41524L,41525L,41526L,41527L,
41528L,41529L,41530L,41531L,41532L,41533L,41534L,41535L,41536L,41537L,
41538L,41539L,41540L,41541L,41542L,41543L,41544L,41545L,41546L,41547L,
41548L,41549L,41550L,41551L,41552L,41553L,41554L,41555L,41556L,41557L,
41558L,41559L,41560L,41561L,41562L,41563L,41564L,41565L,41566L,41567L,
41568L,41569L,41570L,41571L,41572L,41573L,41574L,41575L,41576L,41577L,
41578L,41579L,41580L,41581L,41582L,41583L,41584L,41585L,41586L,41587L,
41588L,41589L,41590L,41591L,41592L,41593L,41594L,41595L,41596L,41597L,
41598L,41599L,41600L,41601L,41602L,41603L,41604L,41605L,41606L,41607L,
41608L,41609L,41610L,41611L,41612L,41613L,41614L,41615L,41616L,41617L,
41618L,41619L,41620L,41621L,41622L,41623L,41624L,41625L,41626L,41627L,
41628L,41629L,41630L,41631L,41632L,41633L,41634L,41635L,41636L,41637L,
41638L,41639L,41640L,41641L,41642L,41643L,41644L,41645L,41646L,41647L,
41648L,41649L,41650L,41651L,41652L,41653L,41654L,41655L,41656L,41657L,
41658L,41659L,41660L,41661L,41662L,41663L,41664L,41665L,41666L,41667L,
41668L,41669L,41670L,41671L,41672L,41673L,41674L,41675L,41676L,41677L,
41678L,41679L,41680L,41681L,41682L,41683L,41684L,41685L,41686L,41687L,
41688L,41689L,41690L,41691L,41692L,41693L,41694L,41695L,41696L,41697L,
41698L,41699L,41700L,41701L,41702L,41703L,41704L,41705L,41706L,41707L,
41708L,41709L,41710L,41711L,41712L,41713L,41714L,41715L,41716L,41717L,
41718L,41719L,41720L,41721L,41722L,41723L,41724L,41725L,41726L,41727L,
41728L,41729L,41730L,41731L,41732L,41733L,41734L,41735L,41736L,41737L,
41738L,41739L,41740L,41741L,41742L,41743L,41744L,41745L,41746L,41747L,
41748L,41749L,41750L,41751L,41752L,41753L,41754L,41755L,41756L,41757L,
41758L,41759L,41760L,41761L,41762L,41763L,41764L,41765L,41766L,41767L,
41768L,41769L,41770L,41771L,41772L,41773L,41774L,41775L,41776L,41777L,
41778L,41779L,41780L,41781L,41782L,41783L,41784L,41785L,41786L,41787L,
41788L,41789L,41790L,41791L,41792L,41793L,41794L,41795L,41796L,41797L,
41798L,41799L,41800L,41801L,41802L,41803L,41804L,41805L,41806L,41807L,
41808L,41809L,41810L,41811L,41812L,41813L,41814L,41815L,41816L,41817L,
41818L,41819L,41820L,41821L,41822L,41823L,41824L,41825L,41826L,41827L,
41828L,41829L,41830L,41831L,41832L,41833L,41834L,41835L,41836L,41837L,
41838L,41839L,41840L,41841L,41842L,41843L,41844L,41845L,41846L,41847L,
41848L,41849L,41850L,41851L,41852L,41853L,41854L,41855L,41856L,41857L,
41858L,41859L,41860L,41861L,41862L,41863L,41864L,41865L,41866L,41867L,
41868L,41869L,41870L,41871L,41872L,41873L,41874L,41875L,41876L,41877L,
41878L,41879L,41880L,41881L,41882L,41883L,41884L,41885L,41886L,41887L,
41888L,41889L,41890L,41891L,41892L,41893L,41894L,41895L,41896L,41897L,
41898L,41899L,41900L,41901L,41902L,41903L,41904L,41905L,41906L,41907L,
41908L,41909L,41910L,41911L,41912L,41913L,41914L,41915L,41916L,41917L,
41918L,41919L,41920L,41921L,41922L,41923L,41924L,41925L,41926L,41927L,
41928L,41929L,41930L,41931L,41932L,41933L,41934L,41935L,41936L,41937L,
41938L,41939L,41940L,41941L,41942L,41943L,41944L,41945L,41946L,41947L,
41948L,41949L,41950L,41951L,41952L,41953L,41954L,41955L,41956L,41957L,
41958L,41959L,41960L,41961L,41962L,41963L,41964L,41965L,41966L,41967L,
41968L,41969L,41970L,41971L,41972L,41973L,41974L,41975L,41976L,41977L,
41978L,41979L,41980L,41981L,41982L,41983L,41984L,41985L,41986L,41987L,
41988L,41989L,41990L,41991L,41992L,41993L,41994L,41995L,41996L,41997L,
41998L,41999L,42000L,42001L,42002L,42003L,42004L,42005L,42006L,42007L,
42008L,42009L,42010L,42011L,42012L,42013L,42014L,42015L,42016L,42017L,
42018L,42019L,42020L,42021L,42022L,42023L,42024L,42025L,42026L,42027L,
42028L,42029L,42030L,42031L,42032L,42033L,42034L,42035L,42036L,42037L,
42038L,42039L,42040L,42041L,42042L,42043L,42044L,42045L,42046L,42047L,
42048L,42049L,42050L,42051L,42052L,42053L,42054L,42055L,42056L,42057L,
42058L,42059L,42060L,42061L,42062L,42063L,42064L,42065L,42066L,42067L,
42068L,42069L,42070L,42071L,42072L,42073L,42074L,42075L,42076L,42077L,
42078L,42079L,42080L,42081L,42082L,42083L,42084L,42085L,42086L,42087L,
42088L,42089L,42090L,42091L,42092L,42093L,42094L,42095L,42096L,42097L,
42098L,42099L,42100L,42101L,42102L,42103L,42104L,42105L,42106L,42107L,
42108L,42109L,42110L,42111L,42112L,42113L,42114L,42115L,42116L,42117L,
42118L,42119L,42120L,42121L,42122L,42123L,42124L,42125L,42126L,42127L,
42128L,42129L,42130L,42131L,42132L,42133L,42134L,42135L,42136L,42137L,
42138L,42139L,42140L,42141L,42142L,42143L,42144L,42145L,42146L,42147L,
42148L,42149L,42150L,42151L,42152L,42153L,42154L,42155L,42156L,42157L,
42158L,42159L,42160L,42161L,42162L,42163L,42164L,42165L,42166L,42167L,
42168L,42169L,42170L,42171L,42172L,42173L,42174L,42175L,42176L,42177L,
42178L,42179L,42180L,42181L,42182L,42183L,42184L,42185L,42186L,42187L,
42188L,42189L,42190L,42191L,42192L,42193L,42194L,42195L,42196L,42197L,
42198L,42199L,42200L,42201L,42202L,42203L,42204L,42205L,42206L,42207L,
42208L,42209L,42210L,42211L,42212L,42213L,42214L,42215L,42216L,42217L,
42218L,42219L,42220L,42221L,42222L,42223L,42224L,42225L,42226L,42227L,
42228L,42229L,42230L,42231L,42232L,42233L,42234L,42235L,42236L,42237L,
42238L,42239L,42240L,42241L,42242L,42243L,42244L,42245L,42246L,42247L,
42248L,42249L,42250L,42251L,42252L,42253L,42254L,42255L,42256L,42257L,
42258L,42259L,42260L,42261L,42262L,42263L,42264L,42265L,42266L,42267L,
42268L,42269L,42270L,42271L,42272L,42273L,42274L,42275L,42276L,42277L,
42278L,42279L,42280L,42281L,42282L,42283L,42284L,42285L,42286L,42287L,
42288L,42289L,42290L,42291L,42292L,42293L,42294L,42295L,42296L,42297L,
42298L,42299L,42300L,42301L,42302L,42303L,42304L,42305L,42306L,42307L,
42308L,42309L,42310L,42311L,42312L,42313L,42314L,42315L,42316L,42317L,
42318L,42319L,42320L,42321L,42322L,42323L,42324L,42325L,42326L,42327L,
42328L,42329L,42330L,42331L,42332L,42333L,42334L,42335L,42336L,42337L,
42338L,42339L,42340L,42341L,42342L,42343L,42344L,42345L,42346L,42347L,
42348L,42349L,42350L,42351L,42352L,42353L,42354L,42355L,42356L,42357L,
42358L,42359L,42360L,42361L,42362L,42363L,42364L,42365L,42366L,42367L,
42368L,42369L,42370L,42371L,42372L,42373L,42374L,42375L,42376L,42377L,
42378L,42379L,42380L,42381L,42382L,42383L,42384L,42385L,42386L,42387L,
42388L,42389L,42390L,42391L,42392L,42393L,42394L,42395L,42396L,42397L,
42398L,42399L,42400L,42401L,42402L,42403L,42404L,42405L,42406L,42407L,
42408L,42409L,42410L,42411L,42412L,42413L,42414L,42415L,42416L,42417L,
42418L,42419L,42420L,42421L,42422L,42423L,42424L,42425L,42426L,42427L,
42428L,42429L,42430L,42431L,42432L,42433L,42434L,42435L,42436L,42437L,
42438L,42439L,42440L,42441L,42442L,42443L,42444L,42445L,42446L,42447L,
42448L,42449L,42450L,42451L,42452L,42453L,42454L,42455L,42456L,42457L,
42458L,42459L,42460L,42461L,42462L,42463L,42464L,42465L,42466L,42467L,
42468L,42469L,42470L,42471L,42472L,42473L,42474L,42475L,42476L,42477L,
42478L,42479L,42480L,42481L,42482L,42483L,42484L,42485L,42486L,42487L,
42488L,42489L,42490L,42491L,42492L,42493L,42494L,42495L,42496L,42497L,
42498L,42499L,42500L,42501L,42502L,42503L,42504L,42505L,42506L,42507L,
42508L,42509L,42510L,42511L,42512L,42513L,42514L,42515L,42516L,42517L,
42518L,42519L,42520L,42521L,42522L,42523L,42524L,42525L,42526L,42527L,
42528L,42529L,42530L,42531L,42532L,42533L,42534L,42535L,42536L,42537L,
42538L,42539L,42540L,42541L,42542L,42543L,42544L,42545L,42546L,42547L,
42548L,42549L,42550L,42551L,42552L,42553L,42554L,42555L,42556L,42557L,
42558L,42559L,42560L,42560L,42562L,42562L,42564L,42564L,42566L,42566L,
42568L,42568L,42570L,42570L,42572L,42572L,42574L,42574L,42576L,42576L,
42578L,42578L,42580L,42580L,42582L,42582L,42584L,42584L,42586L,42586L,
42588L,42588L,42590L,42590L,42592L,42592L,42594L,42594L,42596L,42596L,
42598L,42598L,42600L,42600L,42602L,42602L,42604L,42604L,42606L,42607L,
42608L,42609L,42610L,42611L,42612L,42613L,42614L,42615L,42616L,42617L,
42618L,42619L,42620L,42621L,42622L,42623L,42624L,42624L,42626L,42626L,
42628L,42628L,42630L,42630L,42632L,42632L,42634L,42634L,42636L,42636L,
42638L,42638L,42640L,42640L,42642L,42642L,42644L,42644L,42646L,42646L,
42648L,42648L,42650L,42650L,42652L,42653L,42654L,42655L,42656L,42657L,
42658L,42659L,42660L,42661L,42662L,42663L,42664L,42665L,42666L,42667L,
42668L,42669L,42670L,42671L,42672L,42673L,42674L,42675L,42676L,42677L,
42678L,42679L,42680L,42681L,42682L,42683L,42684L,42685L,42686L,42687L,
42688L,42689L,42690L,42691L,42692L,42693L,42694L,42695L,42696L,42697L,
42698L,42699L,42700L,42701L,42702L,42703L,42704L,42705L,42706L,42707L,
42708L,42709L,42710L,42711L,42712L,42713L,42714L,42715L,42716L,42717L,
42718L,42719L,42720L,42721L,42722L,42723L,42724L,42725L,42726L,42727L,
42728L,42729L,42730L,42731L,42732L,42733L,42734L,42735L,42736L,42737L,
42738L,42739L,42740L,42741L,42742L,42743L,42744L,42745L,42746L,42747L,
42748L,42749L,42750L,42751L,42752L,42753L,42754L,42755L,42756L,42757L,
42758L,42759L,42760L,42761L,42762L,42763L,42764L,42765L,42766L,42767L,
42768L,42769L,42770L,42771L,42772L,42773L,42774L,42775L,42776L,42777L,
42778L,42779L,42780L,42781L,42782L,42783L,42784L,42785L,42786L,42786L,
42788L,42788L,42790L,42790L,42792L,42792L,42794L,42794L,42796L,42796L,
42798L,42798L,42800L,42801L,42802L,42802L,42804L,42804L,42806L,42806L,
42808L,42808L,42810L,42810L,42812L,42812L,42814L,42814L,42816L,42816L,
42818L,42818L,42820L,42820L,42822L,42822L,42824L,42824L,42826L,42826L,
42828L,42828L,42830L,42830L,42832L,42832L,42834L,42834L,42836L,42836L,
42838L,42838L,42840L,42840L,42842L,42842L,42844L,42844L,42846L,42846L,
42848L,42848L,42850L,42850L,42852L,42852L,42854L,42854L,42856L,42856L,
42858L,42858L,42860L,42860L,42862L,42862L,42864L,42865L,42866L,42867L,
42868L,42869L,42870L,42871L,42872L,42873L,42873L,42875L,42875L,42877L,
42878L,42878L,42880L,42880L,42882L,42882L,42884L,42884L,42886L,42886L,
42888L,42889L,42890L,42891L,42891L,42893L,42894L,42895L,42896L,42896L,
42898L,42898L,42948L,42901L,42902L,42902L,42904L,42904L,42906L,42906L,
42908L,42908L,42910L,42910L,42912L,42912L,42914L,42914L,42916L,42916L,
42918L,42918L,42920L,42920L,42922L,42923L,42924L,42925L,42926L,42927L,
42928L,42929L,42930L,42931L,42932L,42932L,42934L,42934L,42936L,42936L,
42938L,42938L,42940L,42940L,42942L,42942L,42944L,42945L,42946L,42946L,
42948L,42949L,42950L,42951L,42952L,42953L,42954L,42955L,42956L,42957L,
42958L,42959L,42960L,42961L,42962L,42963L,42964L,42965L,42966L,42967L,
42968L,42969L,42970L,42971L,42972L,42973L,42974L,42975L,42976L,42977L,
42978L,42979L,42980L,42981L,42982L,42983L,42984L,42985L,42986L,42987L,
42988L,42989L,42990L,42991L,42992L,42993L,42994L,42995L,42996L,42997L,
42998L,42999L,43000L,43001L,43002L,43003L,43004L,43005L,43006L,43007L,
43008L,43009L,43010L,43011L,43012L,43013L,43014L,43015L,43016L,43017L,
43018L,43019L,43020L,43021L,43022L,43023L,43024L,43025L,43026L,43027L,
43028L,43029L,43030L,43031L,43032L,43033L,43034L,43035L,43036L,43037L,
43038L,43039L,43040L,43041L,43042L,43043L,43044L,43045L,43046L,43047L,
43048L,43049L,43050L,43051L,43052L,43053L,43054L,43055L,43056L,43057L,
43058L,43059L,43060L,43061L,43062L,43063L,43064L,43065L,43066L,43067L,
43068L,43069L,43070L,43071L,43072L,43073L,43074L,43075L,43076L,43077L,
43078L,43079L,43080L,43081L,43082L,43083L,43084L,43085L,43086L,43087L,
43088L,43089L,43090L,43091L,43092L,43093L,43094L,43095L,43096L,43097L,
43098L,43099L,43100L,43101L,43102L,43103L,43104L,43105L,43106L,43107L,
43108L,43109L,43110L,43111L,43112L,43113L,43114L,43115L,43116L,43117L,
43118L,43119L,43120L,43121L,43122L,43123L,43124L,43125L,43126L,43127L,
43128L,43129L,43130L,43131L,43132L,43133L,43134L,43135L,43136L,43137L,
43138L,43139L,43140L,43141L,43142L,43143L,43144L,43145L,43146L,43147L,
43148L,43149L,43150L,43151L,43152L,43153L,43154L,43155L,43156L,43157L,
43158L,43159L,43160L,43161L,43162L,43163L,43164L,43165L,43166L,43167L,
43168L,43169L,43170L,43171L,43172L,43173L,43174L,43175L,43176L,43177L,
43178L,43179L,43180L,43181L,43182L,43183L,43184L,43185L,43186L,43187L,
43188L,43189L,43190L,43191L,43192L,43193L,43194L,43195L,43196L,43197L,
43198L,43199L,43200L,43201L,43202L,43203L,43204L,43205L,43206L,43207L,
43208L,43209L,43210L,43211L,43212L,43213L,43214L,43215L,43216L,43217L,
43218L,43219L,43220L,43221L,43222L,43223L,43224L,43225L,43226L,43227L,
43228L,43229L,43230L,43231L,43232L,43233L,43234L,43235L,43236L,43237L,
43238L,43239L,43240L,43241L,43242L,43243L,43244L,43245L,43246L,43247L,
43248L,43249L,43250L,43251L,43252L,43253L,43254L,43255L,43256L,43257L,
43258L,43259L,43260L,43261L,43262L,43263L,43264L,43265L,43266L,43267L,
43268L,43269L,43270L,43271L,43272L,43273L,43274L,43275L,43276L,43277L,
43278L,43279L,43280L,43281L,43282L,43283L,43284L,43285L,43286L,43287L,
43288L,43289L,43290L,43291L,43292L,43293L,43294L,43295L,43296L,43297L,
43298L,43299L,43300L,43301L,43302L,43303L,43304L,43305L,43306L,43307L,
43308L,43309L,43310L,43311L,43312L,43313L,43314L,43315L,43316L,43317L,
43318L,43319L,43320L,43321L,43322L,43323L,43324L,43325L,43326L,43327L,
43328L,43329L,43330L,43331L,43332L,43333L,43334L,43335L,43336L,43337L,
43338L,43339L,43340L,43341L,43342L,43343L,43344L,43345L,43346L,43347L,
43348L,43349L,43350L,43351L,43352L,43353L,43354L,43355L,43356L,43357L,
43358L,43359L,43360L,43361L,43362L,43363L,43364L,43365L,43366L,43367L,
43368L,43369L,43370L,43371L,43372L,43373L,43374L,43375L,43376L,43377L,
43378L,43379L,43380L,43381L,43382L,43383L,43384L,43385L,43386L,43387L,
43388L,43389L,43390L,43391L,43392L,43393L,43394L,43395L,43396L,43397L,
43398L,43399L,43400L,43401L,43402L,43403L,43404L,43405L,43406L,43407L,
43408L,43409L,43410L,43411L,43412L,43413L,43414L,43415L,43416L,43417L,
43418L,43419L,43420L,43421L,43422L,43423L,43424L,43425L,43426L,43427L,
43428L,43429L,43430L,43431L,43432L,43433L,43434L,43435L,43436L,43437L,
43438L,43439L,43440L,43441L,43442L,43443L,43444L,43445L,43446L,43447L,
43448L,43449L,43450L,43451L,43452L,43453L,43454L,43455L,43456L,43457L,
43458L,43459L,43460L,43461L,43462L,43463L,43464L,43465L,43466L,43467L,
43468L,43469L,43470L,43471L,43472L,43473L,43474L,43475L,43476L,43477L,
43478L,43479L,43480L,43481L,43482L,43483L,43484L,43485L,43486L,43487L,
43488L,43489L,43490L,43491L,43492L,43493L,43494L,43495L,43496L,43497L,
43498L,43499L,43500L,43501L,43502L,43503L,43504L,43505L,43506L,43507L,
43508L,43509L,43510L,43511L,43512L,43513L,43514L,43515L,43516L,43517L,
43518L,43519L,43520L,43521L,43522L,43523L,43524L,43525L,43526L,43527L,
43528L,43529L,43530L,43531L,43532L,43533L,43534L,43535L,43536L,43537L,
43538L,43539L,43540L,43541L,43542L,43543L,43544L,43545L,43546L,43547L,
43548L,43549L,43550L,43551L,43552L,43553L,43554L,43555L,43556L,43557L,
43558L,43559L,43560L,43561L,43562L,43563L,43564L,43565L,43566L,43567L,
43568L,43569L,43570L,43571L,43572L,43573L,43574L,43575L,43576L,43577L,
43578L,43579L,43580L,43581L,43582L,43583L,43584L,43585L,43586L,43587L,
43588L,43589L,43590L,43591L,43592L,43593L,43594L,43595L,43596L,43597L,
43598L,43599L,43600L,43601L,43602L,43603L,43604L,43605L,43606L,43607L,
43608L,43609L,43610L,43611L,43612L,43613L,43614L,43615L,43616L,43617L,
43618L,43619L,43620L,43621L,43622L,43623L,43624L,43625L,43626L,43627L,
43628L,43629L,43630L,43631L,43632L,43633L,43634L,43635L,43636L,43637L,
43638L,43639L,43640L,43641L,43642L,43643L,43644L,43645L,43646L,43647L,
43648L,43649L,43650L,43651L,43652L,43653L,43654L,43655L,43656L,43657L,
43658L,43659L,43660L,43661L,43662L,43663L,43664L,43665L,43666L,43667L,
43668L,43669L,43670L,43671L,43672L,43673L,43674L,43675L,43676L,43677L,
43678L,43679L,43680L,43681L,43682L,43683L,43684L,43685L,43686L,43687L,
43688L,43689L,43690L,43691L,43692L,43693L,43694L,43695L,43696L,43697L,
43698L,43699L,43700L,43701L,43702L,43703L,43704L,43705L,43706L,43707L,
43708L,43709L,43710L,43711L,43712L,43713L,43714L,43715L,43716L,43717L,
43718L,43719L,43720L,43721L,43722L,43723L,43724L,43725L,43726L,43727L,
43728L,43729L,43730L,43731L,43732L,43733L,43734L,43735L,43736L,43737L,
43738L,43739L,43740L,43741L,43742L,43743L,43744L,43745L,43746L,43747L,
43748L,43749L,43750L,43751L,43752L,43753L,43754L,43755L,43756L,43757L,
43758L,43759L,43760L,43761L,43762L,43763L,43764L,43765L,43766L,43767L,
43768L,43769L,43770L,43771L,43772L,43773L,43774L,43775L,43776L,43777L,
43778L,43779L,43780L,43781L,43782L,43783L,43784L,43785L,43786L,43787L,
43788L,43789L,43790L,43791L,43792L,43793L,43794L,43795L,43796L,43797L,
43798L,43799L,43800L,43801L,43802L,43803L,43804L,43805L,43806L,43807L,
43808L,43809L,43810L,43811L,43812L,43813L,43814L,43815L,43816L,43817L,
43818L,43819L,43820L,43821L,43822L,43823L,43824L,43825L,43826L,43827L,
43828L,43829L,43830L,43831L,43832L,43833L,43834L,43835L,43836L,43837L,
43838L,43839L,43840L,43841L,43842L,43843L,43844L,43845L,43846L,43847L,
43848L,43849L,43850L,43851L,43852L,43853L,43854L,43855L,43856L,43857L,
43858L,42931L,43860L,43861L,43862L,43863L,43864L,43865L,43866L,43867L,
43868L,43869L,43870L,43871L,43872L,43873L,43874L,43875L,43876L,43877L,
43878L,43879L,43880L,43881L,43882L,43883L,43884L,43885L,43886L,43887L,5024,
5025,5026,5027,5028,5029,5030,5031,5032,5033,5034,5035,5036,5037,5038,5039,
5040,5041,5042,5043,5044,5045,5046,5047,5048,5049,5050,5051,5052,5053,5054,
5055,5056,5057,5058,5059,5060,5061,5062,5063,5064,5065,5066,5067,5068,5069,
5070,5071,5072,5073,5074,5075,5076,5077,5078,5079,5080,5081,5082,5083,5084,
5085,5086,5087,5088,5089,5090,5091,5092,5093,5094,5095,5096,5097,5098,5099,
5100,5101,5102,5103,43968L,43969L,43970L,43971L,43972L,43973L,43974L,
43975L,43976L,43977L,43978L,43979L,43980L,43981L,43982L,43983L,43984L,
43985L,43986L,43987L,43988L,43989L,43990L,43991L,43992L,43993L,43994L,
43995L,43996L,43997L,43998L,43999L,44000L,44001L,44002L,44003L,44004L,
44005L,44006L,44007L,44008L,44009L,44010L,44011L,44012L,44013L,44014L,
44015L,44016L,44017L,44018L,44019L,44020L,44021L,44022L,44023L,44024L,
44025L,44026L,44027L,44028L,44029L,44030L,44031L,44032L,44033L,44034L,
44035L,44036L,44037L,44038L,44039L,44040L,44041L,44042L,44043L,44044L,
44045L,44046L,44047L,44048L,44049L,44050L,44051L,44052L,44053L,44054L,
44055L,44056L,44057L,44058L,44059L,44060L,44061L,44062L,44063L,44064L,
44065L,44066L,44067L,44068L,44069L,44070L,44071L,44072L,44073L,44074L,
44075L,44076L,44077L,44078L,44079L,44080L,44081L,44082L,44083L,44084L,
44085L,44086L,44087L,44088L,44089L,44090L,44091L,44092L,44093L,44094L,
44095L,44096L,44097L,44098L,44099L,44100L,44101L,44102L,44103L,44104L,
44105L,44106L,44107L,44108L,44109L,44110L,44111L,44112L,44113L,44114L,
44115L,44116L,44117L,44118L,44119L,44120L,44121L,44122L,44123L,44124L,
44125L,44126L,44127L,44128L,44129L,44130L,44131L,44132L,44133L,44134L,
44135L,44136L,44137L,44138L,44139L,44140L,44141L,44142L,44143L,44144L,
44145L,44146L,44147L,44148L,44149L,44150L,44151L,44152L,44153L,44154L,
44155L,44156L,44157L,44158L,44159L,44160L,44161L,44162L,44163L,44164L,
44165L,44166L,44167L,44168L,44169L,44170L,44171L,44172L,44173L,44174L,
44175L,44176L,44177L,44178L,44179L,44180L,44181L,44182L,44183L,44184L,
44185L,44186L,44187L,44188L,44189L,44190L,44191L,44192L,44193L,44194L,
44195L,44196L,44197L,44198L,44199L,44200L,44201L,44202L,44203L,44204L,
44205L,44206L,44207L,44208L,44209L,44210L,44211L,44212L,44213L,44214L,
44215L,44216L,44217L,44218L,44219L,44220L,44221L,44222L,44223L,44224L,
44225L,44226L,44227L,44228L,44229L,44230L,44231L,44232L,44233L,44234L,
44235L,44236L,44237L,44238L,44239L,44240L,44241L,44242L,44243L,44244L,
44245L,44246L,44247L,44248L,44249L,44250L,44251L,44252L,44253L,44254L,
44255L,44256L,44257L,44258L,44259L,44260L,44261L,44262L,44263L,44264L,
44265L,44266L,44267L,44268L,44269L,44270L,44271L,44272L,44273L,44274L,
44275L,44276L,44277L,44278L,44279L,44280L,44281L,44282L,44283L,44284L,
44285L,44286L,44287L,44288L,44289L,44290L,44291L,44292L,44293L,44294L,
44295L,44296L,44297L,44298L,44299L,44300L,44301L,44302L,44303L,44304L,
44305L,44306L,44307L,44308L,44309L,44310L,44311L,44312L,44313L,44314L,
44315L,44316L,44317L,44318L,44319L,44320L,44321L,44322L,44323L,44324L,
44325L,44326L,44327L,44328L,44329L,44330L,44331L,44332L,44333L,44334L,
44335L,44336L,44337L,44338L,44339L,44340L,44341L,44342L,44343L,44344L,
44345L,44346L,44347L,44348L,44349L,44350L,44351L,44352L,44353L,44354L,
44355L,44356L,44357L,44358L,44359L,44360L,44361L,44362L,44363L,44364L,
44365L,44366L,44367L,44368L,44369L,44370L,44371L,44372L,44373L,44374L,
44375L,44376L,44377L,44378L,44379L,44380L,44381L,44382L,44383L,44384L,
44385L,44386L,44387L,44388L,44389L,44390L,44391L,44392L,44393L,44394L,
44395L,44396L,44397L,44398L,44399L,44400L,44401L,44402L,44403L,44404L,
44405L,44406L,44407L,44408L,44409L,44410L,44411L,44412L,44413L,44414L,
44415L,44416L,44417L,44418L,44419L,44420L,44421L,44422L,44423L,44424L,
44425L,44426L,44427L,44428L,44429L,44430L,44431L,44432L,44433L,44434L,
44435L,44436L,44437L,44438L,44439L,44440L,44441L,44442L,44443L,44444L,
44445L,44446L,44447L,44448L,44449L,44450L,44451L,44452L,44453L,44454L,
44455L,44456L,44457L,44458L,44459L,44460L,44461L,44462L,44463L,44464L,
44465L,44466L,44467L,44468L,44469L,44470L,44471L,44472L,44473L,44474L,
44475L,44476L,44477L,44478L,44479L,44480L,44481L,44482L,44483L,44484L,
44485L,44486L,44487L,44488L,44489L,44490L,44491L,44492L,44493L,44494L,
44495L,44496L,44497L,44498L,44499L,44500L,44501L,44502L,44503L,44504L,
44505L,44506L,44507L,44508L,44509L,44510L,44511L,44512L,44513L,44514L,
44515L,44516L,44517L,44518L,44519L,44520L,44521L,44522L,44523L,44524L,
44525L,44526L,44527L,44528L,44529L,44530L,44531L,44532L,44533L,44534L,
44535L,44536L,44537L,44538L,44539L,44540L,44541L,44542L,44543L,44544L,
44545L,44546L,44547L,44548L,44549L,44550L,44551L,44552L,44553L,44554L,
44555L,44556L,44557L,44558L,44559L,44560L,44561L,44562L,44563L,44564L,
44565L,44566L,44567L,44568L,44569L,44570L,44571L,44572L,44573L,44574L,
44575L,44576L,44577L,44578L,44579L,44580L,44581L,44582L,44583L,44584L,
44585L,44586L,44587L,44588L,44589L,44590L,44591L,44592L,44593L,44594L,
44595L,44596L,44597L,44598L,44599L,44600L,44601L,44602L,44603L,44604L,
44605L,44606L,44607L,44608L,44609L,44610L,44611L,44612L,44613L,44614L,
44615L,44616L,44617L,44618L,44619L,44620L,44621L,44622L,44623L,44624L,
44625L,44626L,44627L,44628L,44629L,44630L,44631L,44632L,44633L,44634L,
44635L,44636L,44637L,44638L,44639L,44640L,44641L,44642L,44643L,44644L,
44645L,44646L,44647L,44648L,44649L,44650L,44651L,44652L,44653L,44654L,
44655L,44656L,44657L,44658L,44659L,44660L,44661L,44662L,44663L,44664L,
44665L,44666L,44667L,44668L,44669L,44670L,44671L,44672L,44673L,44674L,
44675L,44676L,44677L,44678L,44679L,44680L,44681L,44682L,44683L,44684L,
44685L,44686L,44687L,44688L,44689L,44690L,44691L,44692L,44693L,44694L,
44695L,44696L,44697L,44698L,44699L,44700L,44701L,44702L,44703L,44704L,
44705L,44706L,44707L,44708L,44709L,44710L,44711L,44712L,44713L,44714L,
44715L,44716L,44717L,44718L,44719L,44720L,44721L,44722L,44723L,44724L,
44725L,44726L,44727L,44728L,44729L,44730L,44731L,44732L,44733L,44734L,
44735L,44736L,44737L,44738L,44739L,44740L,44741L,44742L,44743L,44744L,
44745L,44746L,44747L,44748L,44749L,44750L,44751L,44752L,44753L,44754L,
44755L,44756L,44757L,44758L,44759L,44760L,44761L,44762L,44763L,44764L,
44765L,44766L,44767L,44768L,44769L,44770L,44771L,44772L,44773L,44774L,
44775L,44776L,44777L,44778L,44779L,44780L,44781L,44782L,44783L,44784L,
44785L,44786L,44787L,44788L,44789L,44790L,44791L,44792L,44793L,44794L,
44795L,44796L,44797L,44798L,44799L,44800L,44801L,44802L,44803L,44804L,
44805L,44806L,44807L,44808L,44809L,44810L,44811L,44812L,44813L,44814L,
44815L,44816L,44817L,44818L,44819L,44820L,44821L,44822L,44823L,44824L,
44825L,44826L,44827L,44828L,44829L,44830L,44831L,44832L,44833L,44834L,
44835L,44836L,44837L,44838L,44839L,44840L,44841L,44842L,44843L,44844L,
44845L,44846L,44847L,44848L,44849L,44850L,44851L,44852L,44853L,44854L,
44855L,44856L,44857L,44858L,44859L,44860L,44861L,44862L,44863L,44864L,
44865L,44866L,44867L,44868L,44869L,44870L,44871L,44872L,44873L,44874L,
44875L,44876L,44877L,44878L,44879L,44880L,44881L,44882L,44883L,44884L,
44885L,44886L,44887L,44888L,44889L,44890L,44891L,44892L,44893L,44894L,
44895L,44896L,44897L,44898L,44899L,44900L,44901L,44902L,44903L,44904L,
44905L,44906L,44907L,44908L,44909L,44910L,44911L,44912L,44913L,44914L,
44915L,44916L,44917L,44918L,44919L,44920L,44921L,44922L,44923L,44924L,
44925L,44926L,44927L,44928L,44929L,44930L,44931L,44932L,44933L,44934L,
44935L,44936L,44937L,44938L,44939L,44940L,44941L,44942L,44943L,44944L,
44945L,44946L,44947L,44948L,44949L,44950L,44951L,44952L,44953L,44954L,
44955L,44956L,44957L,44958L,44959L,44960L,44961L,44962L,44963L,44964L,
44965L,44966L,44967L,44968L,44969L,44970L,44971L,44972L,44973L,44974L,
44975L,44976L,44977L,44978L,44979L,44980L,44981L,44982L,44983L,44984L,
44985L,44986L,44987L,44988L,44989L,44990L,44991L,44992L,44993L,44994L,
44995L,44996L,44997L,44998L,44999L,45000L,45001L,45002L,45003L,45004L,
45005L,45006L,45007L,45008L,45009L,45010L,45011L,45012L,45013L,45014L,
45015L,45016L,45017L,45018L,45019L,45020L,45021L,45022L,45023L,45024L,
45025L,45026L,45027L,45028L,45029L,45030L,45031L,45032L,45033L,45034L,
45035L,45036L,45037L,45038L,45039L,45040L,45041L,45042L,45043L,45044L,
45045L,45046L,45047L,45048L,45049L,45050L,45051L,45052L,45053L,45054L,
45055L,45056L,45057L,45058L,45059L,45060L,45061L,45062L,45063L,45064L,
45065L,45066L,45067L,45068L,45069L,45070L,45071L,45072L,45073L,45074L,
45075L,45076L,45077L,45078L,45079L,45080L,45081L,45082L,45083L,45084L,
45085L,45086L,45087L,45088L,45089L,45090L,45091L,45092L,45093L,45094L,
45095L,45096L,45097L,45098L,45099L,45100L,45101L,45102L,45103L,45104L,
45105L,45106L,45107L,45108L,45109L,45110L,45111L,45112L,45113L,45114L,
45115L,45116L,45117L,45118L,45119L,45120L,45121L,45122L,45123L,45124L,
45125L,45126L,45127L,45128L,45129L,45130L,45131L,45132L,45133L,45134L,
45135L,45136L,45137L,45138L,45139L,45140L,45141L,45142L,45143L,45144L,
45145L,45146L,45147L,45148L,45149L,45150L,45151L,45152L,45153L,45154L,
45155L,45156L,45157L,45158L,45159L,45160L,45161L,45162L,45163L,45164L,
45165L,45166L,45167L,45168L,45169L,45170L,45171L,45172L,45173L,45174L,
45175L,45176L,45177L,45178L,45179L,45180L,45181L,45182L,45183L,45184L,
45185L,45186L,45187L,45188L,45189L,45190L,45191L,45192L,45193L,45194L,
45195L,45196L,45197L,45198L,45199L,45200L,45201L,45202L,45203L,45204L,
45205L,45206L,45207L,45208L,45209L,45210L,45211L,45212L,45213L,45214L,
45215L,45216L,45217L,45218L,45219L,45220L,45221L,45222L,45223L,45224L,
45225L,45226L,45227L,45228L,45229L,45230L,45231L,45232L,45233L,45234L,
45235L,45236L,45237L,45238L,45239L,45240L,45241L,45242L,45243L,45244L,
45245L,45246L,45247L,45248L,45249L,45250L,45251L,45252L,45253L,45254L,
45255L,45256L,45257L,45258L,45259L,45260L,45261L,45262L,45263L,45264L,
45265L,45266L,45267L,45268L,45269L,45270L,45271L,45272L,45273L,45274L,
45275L,45276L,45277L,45278L,45279L,45280L,45281L,45282L,45283L,45284L,
45285L,45286L,45287L,45288L,45289L,45290L,45291L,45292L,45293L,45294L,
45295L,45296L,45297L,45298L,45299L,45300L,45301L,45302L,45303L,45304L,
45305L,45306L,45307L,45308L,45309L,45310L,45311L,45312L,45313L,45314L,
45315L,45316L,45317L,45318L,45319L,45320L,45321L,45322L,45323L,45324L,
45325L,45326L,45327L,45328L,45329L,45330L,45331L,45332L,45333L,45334L,
45335L,45336L,45337L,45338L,45339L,45340L,45341L,45342L,45343L,45344L,
45345L,45346L,45347L,45348L,45349L,45350L,45351L,45352L,45353L,45354L,
45355L,45356L,45357L,45358L,45359L,45360L,45361L,45362L,45363L,45364L,
45365L,45366L,45367L,45368L,45369L,45370L,45371L,45372L,45373L,45374L,
45375L,45376L,45377L,45378L,45379L,45380L,45381L,45382L,45383L,45384L,
45385L,45386L,45387L,45388L,45389L,45390L,45391L,45392L,45393L,45394L,
45395L,45396L,45397L,45398L,45399L,45400L,45401L,45402L,45403L,45404L,
45405L,45406L,45407L,45408L,45409L,45410L,45411L,45412L,45413L,45414L,
45415L,45416L,45417L,45418L,45419L,45420L,45421L,45422L,45423L,45424L,
45425L,45426L,45427L,45428L,45429L,45430L,45431L,45432L,45433L,45434L,
45435L,45436L,45437L,45438L,45439L,45440L,45441L,45442L,45443L,45444L,
45445L,45446L,45447L,45448L,45449L,45450L,45451L,45452L,45453L,45454L,
45455L,45456L,45457L,45458L,45459L,45460L,45461L,45462L,45463L,45464L,
45465L,45466L,45467L,45468L,45469L,45470L,45471L,45472L,45473L,45474L,
45475L,45476L,45477L,45478L,45479L,45480L,45481L,45482L,45483L,45484L,
45485L,45486L,45487L,45488L,45489L,45490L,45491L,45492L,45493L,45494L,
45495L,45496L,45497L,45498L,45499L,45500L,45501L,45502L,45503L,45504L,
45505L,45506L,45507L,45508L,45509L,45510L,45511L,45512L,45513L,45514L,
45515L,45516L,45517L,45518L,45519L,45520L,45521L,45522L,45523L,45524L,
45525L,45526L,45527L,45528L,45529L,45530L,45531L,45532L,45533L,45534L,
45535L,45536L,45537L,45538L,45539L,45540L,45541L,45542L,45543L,45544L,
45545L,45546L,45547L,45548L,45549L,45550L,45551L,45552L,45553L,45554L,
45555L,45556L,45557L,45558L,45559L,45560L,45561L,45562L,45563L,45564L,
45565L,45566L,45567L,45568L,45569L,45570L,45571L,45572L,45573L,45574L,
45575L,45576L,45577L,45578L,45579L,45580L,45581L,45582L,45583L,45584L,
45585L,45586L,45587L,45588L,45589L,45590L,45591L,45592L,45593L,45594L,
45595L,45596L,45597L,45598L,45599L,45600L,45601L,45602L,45603L,45604L,
45605L,45606L,45607L,45608L,45609L,45610L,45611L,45612L,45613L,45614L,
45615L,45616L,45617L,45618L,45619L,45620L,45621L,45622L,45623L,45624L,
45625L,45626L,45627L,45628L,45629L,45630L,45631L,45632L,45633L,45634L,
45635L,45636L,45637L,45638L,45639L,45640L,45641L,45642L,45643L,45644L,
45645L,45646L,45647L,45648L,45649L,45650L,45651L,45652L,45653L,45654L,
45655L,45656L,45657L,45658L,45659L,45660L,45661L,45662L,45663L,45664L,
45665L,45666L,45667L,45668L,45669L,45670L,45671L,45672L,45673L,45674L,
45675L,45676L,45677L,45678L,45679L,45680L,45681L,45682L,45683L,45684L,
45685L,45686L,45687L,45688L,45689L,45690L,45691L,45692L,45693L,45694L,
45695L,45696L,45697L,45698L,45699L,45700L,45701L,45702L,45703L,45704L,
45705L,45706L,45707L,45708L,45709L,45710L,45711L,45712L,45713L,45714L,
45715L,45716L,45717L,45718L,45719L,45720L,45721L,45722L,45723L,45724L,
45725L,45726L,45727L,45728L,45729L,45730L,45731L,45732L,45733L,45734L,
45735L,45736L,45737L,45738L,45739L,45740L,45741L,45742L,45743L,45744L,
45745L,45746L,45747L,45748L,45749L,45750L,45751L,45752L,45753L,45754L,
45755L,45756L,45757L,45758L,45759L,45760L,45761L,45762L,45763L,45764L,
45765L,45766L,45767L,45768L,45769L,45770L,45771L,45772L,45773L,45774L,
45775L,45776L,45777L,45778L,45779L,45780L,45781L,45782L,45783L,45784L,
45785L,45786L,45787L,45788L,45789L,45790L,45791L,45792L,45793L,45794L,
45795L,45796L,45797L,45798L,45799L,45800L,45801L,45802L,45803L,45804L,
45805L,45806L,45807L,45808L,45809L,45810L,45811L,45812L,45813L,45814L,
45815L,45816L,45817L,45818L,45819L,45820L,45821L,45822L,45823L,45824L,
45825L,45826L,45827L,45828L,45829L,45830L,45831L,45832L,45833L,45834L,
45835L,45836L,45837L,45838L,45839L,45840L,45841L,45842L,45843L,45844L,
45845L,45846L,45847L,45848L,45849L,45850L,45851L,45852L,45853L,45854L,
45855L,45856L,45857L,45858L,45859L,45860L,45861L,45862L,45863L,45864L,
45865L,45866L,45867L,45868L,45869L,45870L,45871L,45872L,45873L,45874L,
45875L,45876L,45877L,45878L,45879L,45880L,45881L,45882L,45883L,45884L,
45885L,45886L,45887L,45888L,45889L,45890L,45891L,45892L,45893L,45894L,
45895L,45896L,45897L,45898L,45899L,45900L,45901L,45902L,45903L,45904L,
45905L,45906L,45907L,45908L,45909L,45910L,45911L,45912L,45913L,45914L,
45915L,45916L,45917L,45918L,45919L,45920L,45921L,45922L,45923L,45924L,
45925L,45926L,45927L,45928L,45929L,45930L,45931L,45932L,45933L,45934L,
45935L,45936L,45937L,45938L,45939L,45940L,45941L,45942L,45943L,45944L,
45945L,45946L,45947L,45948L,45949L,45950L,45951L,45952L,45953L,45954L,
45955L,45956L,45957L,45958L,45959L,45960L,45961L,45962L,45963L,45964L,
45965L,45966L,45967L,45968L,45969L,45970L,45971L,45972L,45973L,45974L,
45975L,45976L,45977L,45978L,45979L,45980L,45981L,45982L,45983L,45984L,
45985L,45986L,45987L,45988L,45989L,45990L,45991L,45992L,45993L,45994L,
45995L,45996L,45997L,45998L,45999L,46000L,46001L,46002L,46003L,46004L,
46005L,46006L,46007L,46008L,46009L,46010L,46011L,46012L,46013L,46014L,
46015L,46016L,46017L,46018L,46019L,46020L,46021L,46022L,46023L,46024L,
46025L,46026L,46027L,46028L,46029L,46030L,46031L,46032L,46033L,46034L,
46035L,46036L,46037L,46038L,46039L,46040L,46041L,46042L,46043L,46044L,
46045L,46046L,46047L,46048L,46049L,46050L,46051L,46052L,46053L,46054L,
46055L,46056L,46057L,46058L,46059L,46060L,46061L,46062L,46063L,46064L,
46065L,46066L,46067L,46068L,46069L,46070L,46071L,46072L,46073L,46074L,
46075L,46076L,46077L,46078L,46079L,46080L,46081L,46082L,46083L,46084L,
46085L,46086L,46087L,46088L,46089L,46090L,46091L,46092L,46093L,46094L,
46095L,46096L,46097L,46098L,46099L,46100L,46101L,46102L,46103L,46104L,
46105L,46106L,46107L,46108L,46109L,46110L,46111L,46112L,46113L,46114L,
46115L,46116L,46117L,46118L,46119L,46120L,46121L,46122L,46123L,46124L,
46125L,46126L,46127L,46128L,46129L,46130L,46131L,46132L,46133L,46134L,
46135L,46136L,46137L,46138L,46139L,46140L,46141L,46142L,46143L,46144L,
46145L,46146L,46147L,46148L,46149L,46150L,46151L,46152L,46153L,46154L,
46155L,46156L,46157L,46158L,46159L,46160L,46161L,46162L,46163L,46164L,
46165L,46166L,46167L,46168L,46169L,46170L,46171L,46172L,46173L,46174L,
46175L,46176L,46177L,46178L,46179L,46180L,46181L,46182L,46183L,46184L,
46185L,46186L,46187L,46188L,46189L,46190L,46191L,46192L,46193L,46194L,
46195L,46196L,46197L,46198L,46199L,46200L,46201L,46202L,46203L,46204L,
46205L,46206L,46207L,46208L,46209L,46210L,46211L,46212L,46213L,46214L,
46215L,46216L,46217L,46218L,46219L,46220L,46221L,46222L,46223L,46224L,
46225L,46226L,46227L,46228L,46229L,46230L,46231L,46232L,46233L,46234L,
46235L,46236L,46237L,46238L,46239L,46240L,46241L,46242L,46243L,46244L,
46245L,46246L,46247L,46248L,46249L,46250L,46251L,46252L,46253L,46254L,
46255L,46256L,46257L,46258L,46259L,46260L,46261L,46262L,46263L,46264L,
46265L,46266L,46267L,46268L,46269L,46270L,46271L,46272L,46273L,46274L,
46275L,46276L,46277L,46278L,46279L,46280L,46281L,46282L,46283L,46284L,
46285L,46286L,46287L,46288L,46289L,46290L,46291L,46292L,46293L,46294L,
46295L,46296L,46297L,46298L,46299L,46300L,46301L,46302L,46303L,46304L,
46305L,46306L,46307L,46308L,46309L,46310L,46311L,46312L,46313L,46314L,
46315L,46316L,46317L,46318L,46319L,46320L,46321L,46322L,46323L,46324L,
46325L,46326L,46327L,46328L,46329L,46330L,46331L,46332L,46333L,46334L,
46335L,46336L,46337L,46338L,46339L,46340L,46341L,46342L,46343L,46344L,
46345L,46346L,46347L,46348L,46349L,46350L,46351L,46352L,46353L,46354L,
46355L,46356L,46357L,46358L,46359L,46360L,46361L,46362L,46363L,46364L,
46365L,46366L,46367L,46368L,46369L,46370L,46371L,46372L,46373L,46374L,
46375L,46376L,46377L,46378L,46379L,46380L,46381L,46382L,46383L,46384L,
46385L,46386L,46387L,46388L,46389L,46390L,46391L,46392L,46393L,46394L,
46395L,46396L,46397L,46398L,46399L,46400L,46401L,46402L,46403L,46404L,
46405L,46406L,46407L,46408L,46409L,46410L,46411L,46412L,46413L,46414L,
46415L,46416L,46417L,46418L,46419L,46420L,46421L,46422L,46423L,46424L,
46425L,46426L,46427L,46428L,46429L,46430L,46431L,46432L,46433L,46434L,
46435L,46436L,46437L,46438L,46439L,46440L,46441L,46442L,46443L,46444L,
46445L,46446L,46447L,46448L,46449L,46450L,46451L,46452L,46453L,46454L,
46455L,46456L,46457L,46458L,46459L,46460L,46461L,46462L,46463L,46464L,
46465L,46466L,46467L,46468L,46469L,46470L,46471L,46472L,46473L,46474L,
46475L,46476L,46477L,46478L,46479L,46480L,46481L,46482L,46483L,46484L,
46485L,46486L,46487L,46488L,46489L,46490L,46491L,46492L,46493L,46494L,
46495L,46496L,46497L,46498L,46499L,46500L,46501L,46502L,46503L,46504L,
46505L,46506L,46507L,46508L,46509L,46510L,46511L,46512L,46513L,46514L,
46515L,46516L,46517L,46518L,46519L,46520L,46521L,46522L,46523L,46524L,
46525L,46526L,46527L,46528L,46529L,46530L,46531L,46532L,46533L,46534L,
46535L,46536L,46537L,46538L,46539L,46540L,46541L,46542L,46543L,46544L,
46545L,46546L,46547L,46548L,46549L,46550L,46551L,46552L,46553L,46554L,
46555L,46556L,46557L,46558L,46559L,46560L,46561L,46562L,46563L,46564L,
46565L,46566L,46567L,46568L,46569L,46570L,46571L,46572L,46573L,46574L,
46575L,46576L,46577L,46578L,46579L,46580L,46581L,46582L,46583L,46584L,
46585L,46586L,46587L,46588L,46589L,46590L,46591L,46592L,46593L,46594L,
46595L,46596L,46597L,46598L,46599L,46600L,46601L,46602L,46603L,46604L,
46605L,46606L,46607L,46608L,46609L,46610L,46611L,46612L,46613L,46614L,
46615L,46616L,46617L,46618L,46619L,46620L,46621L,46622L,46623L,46624L,
46625L,46626L,46627L,46628L,46629L,46630L,46631L,46632L,46633L,46634L,
46635L,46636L,46637L,46638L,46639L,46640L,46641L,46642L,46643L,46644L,
46645L,46646L,46647L,46648L,46649L,46650L,46651L,46652L,46653L,46654L,
46655L,46656L,46657L,46658L,46659L,46660L,46661L,46662L,46663L,46664L,
46665L,46666L,46667L,46668L,46669L,46670L,46671L,46672L,46673L,46674L,
46675L,46676L,46677L,46678L,46679L,46680L,46681L,46682L,46683L,46684L,
46685L,46686L,46687L,46688L,46689L,46690L,46691L,46692L,46693L,46694L,
46695L,46696L,46697L,46698L,46699L,46700L,46701L,46702L,46703L,46704L,
46705L,46706L,46707L,46708L,46709L,46710L,46711L,46712L,46713L,46714L,
46715L,46716L,46717L,46718L,46719L,46720L,46721L,46722L,46723L,46724L,
46725L,46726L,46727L,46728L,46729L,46730L,46731L,46732L,46733L,46734L,
46735L,46736L,46737L,46738L,46739L,46740L,46741L,46742L,46743L,46744L,
46745L,46746L,46747L,46748L,46749L,46750L,46751L,46752L,46753L,46754L,
46755L,46756L,46757L,46758L,46759L,46760L,46761L,46762L,46763L,46764L,
46765L,46766L,46767L,46768L,46769L,46770L,46771L,46772L,46773L,46774L,
46775L,46776L,46777L,46778L,46779L,46780L,46781L,46782L,46783L,46784L,
46785L,46786L,46787L,46788L,46789L,46790L,46791L,46792L,46793L,46794L,
46795L,46796L,46797L,46798L,46799L,46800L,46801L,46802L,46803L,46804L,
46805L,46806L,46807L,46808L,46809L,46810L,46811L,46812L,46813L,46814L,
46815L,46816L,46817L,46818L,46819L,46820L,46821L,46822L,46823L,46824L,
46825L,46826L,46827L,46828L,46829L,46830L,46831L,46832L,46833L,46834L,
46835L,46836L,46837L,46838L,46839L,46840L,46841L,46842L,46843L,46844L,
46845L,46846L,46847L,46848L,46849L,46850L,46851L,46852L,46853L,46854L,
46855L,46856L,46857L,46858L,46859L,46860L,46861L,46862L,46863L,46864L,
46865L,46866L,46867L,46868L,46869L,46870L,46871L,46872L,46873L,46874L,
46875L,46876L,46877L,46878L,46879L,46880L,46881L,46882L,46883L,46884L,
46885L,46886L,46887L,46888L,46889L,46890L,46891L,46892L,46893L,46894L,
46895L,46896L,46897L,46898L,46899L,46900L,46901L,46902L,46903L,46904L,
46905L,46906L,46907L,46908L,46909L,46910L,46911L,46912L,46913L,46914L,
46915L,46916L,46917L,46918L,46919L,46920L,46921L,46922L,46923L,46924L,
46925L,46926L,46927L,46928L,46929L,46930L,46931L,46932L,46933L,46934L,
46935L,46936L,46937L,46938L,46939L,46940L,46941L,46942L,46943L,46944L,
46945L,46946L,46947L,46948L,46949L,46950L,46951L,46952L,46953L,46954L,
46955L,46956L,46957L,46958L,46959L,46960L,46961L,46962L,46963L,46964L,
46965L,46966L,46967L,46968L,46969L,46970L,46971L,46972L,46973L,46974L,
46975L,46976L,46977L,46978L,46979L,46980L,46981L,46982L,46983L,46984L,
46985L,46986L,46987L,46988L,46989L,46990L,46991L,46992L,46993L,46994L,
46995L,46996L,46997L,46998L,46999L,47000L,47001L,47002L,47003L,47004L,
47005L,47006L,47007L,47008L,47009L,47010L,47011L,47012L,47013L,47014L,
47015L,47016L,47017L,47018L,47019L,47020L,47021L,47022L,47023L,47024L,
47025L,47026L,47027L,47028L,47029L,47030L,47031L,47032L,47033L,47034L,
47035L,47036L,47037L,47038L,47039L,47040L,47041L,47042L,47043L,47044L,
47045L,47046L,47047L,47048L,47049L,47050L,47051L,47052L,47053L,47054L,
47055L,47056L,47057L,47058L,47059L,47060L,47061L,47062L,47063L,47064L,
47065L,47066L,47067L,47068L,47069L,47070L,47071L,47072L,47073L,47074L,
47075L,47076L,47077L,47078L,47079L,47080L,47081L,47082L,47083L,47084L,
47085L,47086L,47087L,47088L,47089L,47090L,47091L,47092L,47093L,47094L,
47095L,47096L,47097L,47098L,47099L,47100L,47101L,47102L,47103L,47104L,
47105L,47106L,47107L,47108L,47109L,47110L,47111L,47112L,47113L,47114L,
47115L,47116L,47117L,47118L,47119L,47120L,47121L,47122L,47123L,47124L,
47125L,47126L,47127L,47128L,47129L,47130L,47131L,47132L,47133L,47134L,
47135L,47136L,47137L,47138L,47139L,47140L,47141L,47142L,47143L,47144L,
47145L,47146L,47147L,47148L,47149L,47150L,47151L,47152L,47153L,47154L,
47155L,47156L,47157L,47158L,47159L,47160L,47161L,47162L,47163L,47164L,
47165L,47166L,47167L,47168L,47169L,47170L,47171L,47172L,47173L,47174L,
47175L,47176L,47177L,47178L,47179L,47180L,47181L,47182L,47183L,47184L,
47185L,47186L,47187L,47188L,47189L,47190L,47191L,47192L,47193L,47194L,
47195L,47196L,47197L,47198L,47199L,47200L,47201L,47202L,47203L,47204L,
47205L,47206L,47207L,47208L,47209L,47210L,47211L,47212L,47213L,47214L,
47215L,47216L,47217L,47218L,47219L,47220L,47221L,47222L,47223L,47224L,
47225L,47226L,47227L,47228L,47229L,47230L,47231L,47232L,47233L,47234L,
47235L,47236L,47237L,47238L,47239L,47240L,47241L,47242L,47243L,47244L,
47245L,47246L,47247L,47248L,47249L,47250L,47251L,47252L,47253L,47254L,
47255L,47256L,47257L,47258L,47259L,47260L,47261L,47262L,47263L,47264L,
47265L,47266L,47267L,47268L,47269L,47270L,47271L,47272L,47273L,47274L,
47275L,47276L,47277L,47278L,47279L,47280L,47281L,47282L,47283L,47284L,
47285L,47286L,47287L,47288L,47289L,47290L,47291L,47292L,47293L,47294L,
47295L,47296L,47297L,47298L,47299L,47300L,47301L,47302L,47303L,47304L,
47305L,47306L,47307L,47308L,47309L,47310L,47311L,47312L,47313L,47314L,
47315L,47316L,47317L,47318L,47319L,47320L,47321L,47322L,47323L,47324L,
47325L,47326L,47327L,47328L,47329L,47330L,47331L,47332L,47333L,47334L,
47335L,47336L,47337L,47338L,47339L,47340L,47341L,47342L,47343L,47344L,
47345L,47346L,47347L,47348L,47349L,47350L,47351L,47352L,47353L,47354L,
47355L,47356L,47357L,47358L,47359L,47360L,47361L,47362L,47363L,47364L,
47365L,47366L,47367L,47368L,47369L,47370L,47371L,47372L,47373L,47374L,
47375L,47376L,47377L,47378L,47379L,47380L,47381L,47382L,47383L,47384L,
47385L,47386L,47387L,47388L,47389L,47390L,47391L,47392L,47393L,47394L,
47395L,47396L,47397L,47398L,47399L,47400L,47401L,47402L,47403L,47404L,
47405L,47406L,47407L,47408L,47409L,47410L,47411L,47412L,47413L,47414L,
47415L,47416L,47417L,47418L,47419L,47420L,47421L,47422L,47423L,47424L,
47425L,47426L,47427L,47428L,47429L,47430L,47431L,47432L,47433L,47434L,
47435L,47436L,47437L,47438L,47439L,47440L,47441L,47442L,47443L,47444L,
47445L,47446L,47447L,47448L,47449L,47450L,47451L,47452L,47453L,47454L,
47455L,47456L,47457L,47458L,47459L,47460L,47461L,47462L,47463L,47464L,
47465L,47466L,47467L,47468L,47469L,47470L,47471L,47472L,47473L,47474L,
47475L,47476L,47477L,47478L,47479L,47480L,47481L,47482L,47483L,47484L,
47485L,47486L,47487L,47488L,47489L,47490L,47491L,47492L,47493L,47494L,
47495L,47496L,47497L,47498L,47499L,47500L,47501L,47502L,47503L,47504L,
47505L,47506L,47507L,47508L,47509L,47510L,47511L,47512L,47513L,47514L,
47515L,47516L,47517L,47518L,47519L,47520L,47521L,47522L,47523L,47524L,
47525L,47526L,47527L,47528L,47529L,47530L,47531L,47532L,47533L,47534L,
47535L,47536L,47537L,47538L,47539L,47540L,47541L,47542L,47543L,47544L,
47545L,47546L,47547L,47548L,47549L,47550L,47551L,47552L,47553L,47554L,
47555L,47556L,47557L,47558L,47559L,47560L,47561L,47562L,47563L,47564L,
47565L,47566L,47567L,47568L,47569L,47570L,47571L,47572L,47573L,47574L,
47575L,47576L,47577L,47578L,47579L,47580L,47581L,47582L,47583L,47584L,
47585L,47586L,47587L,47588L,47589L,47590L,47591L,47592L,47593L,47594L,
47595L,47596L,47597L,47598L,47599L,47600L,47601L,47602L,47603L,47604L,
47605L,47606L,47607L,47608L,47609L,47610L,47611L,47612L,47613L,47614L,
47615L,47616L,47617L,47618L,47619L,47620L,47621L,47622L,47623L,47624L,
47625L,47626L,47627L,47628L,47629L,47630L,47631L,47632L,47633L,47634L,
47635L,47636L,47637L,47638L,47639L,47640L,47641L,47642L,47643L,47644L,
47645L,47646L,47647L,47648L,47649L,47650L,47651L,47652L,47653L,47654L,
47655L,47656L,47657L,47658L,47659L,47660L,47661L,47662L,47663L,47664L,
47665L,47666L,47667L,47668L,47669L,47670L,47671L,47672L,47673L,47674L,
47675L,47676L,47677L,47678L,47679L,47680L,47681L,47682L,47683L,47684L,
47685L,47686L,47687L,47688L,47689L,47690L,47691L,47692L,47693L,47694L,
47695L,47696L,47697L,47698L,47699L,47700L,47701L,47702L,47703L,47704L,
47705L,47706L,47707L,47708L,47709L,47710L,47711L,47712L,47713L,47714L,
47715L,47716L,47717L,47718L,47719L,47720L,47721L,47722L,47723L,47724L,
47725L,47726L,47727L,47728L,47729L,47730L,47731L,47732L,47733L,47734L,
47735L,47736L,47737L,47738L,47739L,47740L,47741L,47742L,47743L,47744L,
47745L,47746L,47747L,47748L,47749L,47750L,47751L,47752L,47753L,47754L,
47755L,47756L,47757L,47758L,47759L,47760L,47761L,47762L,47763L,47764L,
47765L,47766L,47767L,47768L,47769L,47770L,47771L,47772L,47773L,47774L,
47775L,47776L,47777L,47778L,47779L,47780L,47781L,47782L,47783L,47784L,
47785L,47786L,47787L,47788L,47789L,47790L,47791L,47792L,47793L,47794L,
47795L,47796L,47797L,47798L,47799L,47800L,47801L,47802L,47803L,47804L,
47805L,47806L,47807L,47808L,47809L,47810L,47811L,47812L,47813L,47814L,
47815L,47816L,47817L,47818L,47819L,47820L,47821L,47822L,47823L,47824L,
47825L,47826L,47827L,47828L,47829L,47830L,47831L,47832L,47833L,47834L,
47835L,47836L,47837L,47838L,47839L,47840L,47841L,47842L,47843L,47844L,
47845L,47846L,47847L,47848L,47849L,47850L,47851L,47852L,47853L,47854L,
47855L,47856L,47857L,47858L,47859L,47860L,47861L,47862L,47863L,47864L,
47865L,47866L,47867L,47868L,47869L,47870L,47871L,47872L,47873L,47874L,
47875L,47876L,47877L,47878L,47879L,47880L,47881L,47882L,47883L,47884L,
47885L,47886L,47887L,47888L,47889L,47890L,47891L,47892L,47893L,47894L,
47895L,47896L,47897L,47898L,47899L,47900L,47901L,47902L,47903L,47904L,
47905L,47906L,47907L,47908L,47909L,47910L,47911L,47912L,47913L,47914L,
47915L,47916L,47917L,47918L,47919L,47920L,47921L,47922L,47923L,47924L,
47925L,47926L,47927L,47928L,47929L,47930L,47931L,47932L,47933L,47934L,
47935L,47936L,47937L,47938L,47939L,47940L,47941L,47942L,47943L,47944L,
47945L,47946L,47947L,47948L,47949L,47950L,47951L,47952L,47953L,47954L,
47955L,47956L,47957L,47958L,47959L,47960L,47961L,47962L,47963L,47964L,
47965L,47966L,47967L,47968L,47969L,47970L,47971L,47972L,47973L,47974L,
47975L,47976L,47977L,47978L,47979L,47980L,47981L,47982L,47983L,47984L,
47985L,47986L,47987L,47988L,47989L,47990L,47991L,47992L,47993L,47994L,
47995L,47996L,47997L,47998L,47999L,48000L,48001L,48002L,48003L,48004L,
48005L,48006L,48007L,48008L,48009L,48010L,48011L,48012L,48013L,48014L,
48015L,48016L,48017L,48018L,48019L,48020L,48021L,48022L,48023L,48024L,
48025L,48026L,48027L,48028L,48029L,48030L,48031L,48032L,48033L,48034L,
48035L,48036L,48037L,48038L,48039L,48040L,48041L,48042L,48043L,48044L,
48045L,48046L,48047L,48048L,48049L,48050L,48051L,48052L,48053L,48054L,
48055L,48056L,48057L,48058L,48059L,48060L,48061L,48062L,48063L,48064L,
48065L,48066L,48067L,48068L,48069L,48070L,48071L,48072L,48073L,48074L,
48075L,48076L,48077L,48078L,48079L,48080L,48081L,48082L,48083L,48084L,
48085L,48086L,48087L,48088L,48089L,48090L,48091L,48092L,48093L,48094L,
48095L,48096L,48097L,48098L,48099L,48100L,48101L,48102L,48103L,48104L,
48105L,48106L,48107L,48108L,48109L,48110L,48111L,48112L,48113L,48114L,
48115L,48116L,48117L,48118L,48119L,48120L,48121L,48122L,48123L,48124L,
48125L,48126L,48127L,48128L,48129L,48130L,48131L,48132L,48133L,48134L,
48135L,48136L,48137L,48138L,48139L,48140L,48141L,48142L,48143L,48144L,
48145L,48146L,48147L,48148L,48149L,48150L,48151L,48152L,48153L,48154L,
48155L,48156L,48157L,48158L,48159L,48160L,48161L,48162L,48163L,48164L,
48165L,48166L,48167L,48168L,48169L,48170L,48171L,48172L,48173L,48174L,
48175L,48176L,48177L,48178L,48179L,48180L,48181L,48182L,48183L,48184L,
48185L,48186L,48187L,48188L,48189L,48190L,48191L,48192L,48193L,48194L,
48195L,48196L,48197L,48198L,48199L,48200L,48201L,48202L,48203L,48204L,
48205L,48206L,48207L,48208L,48209L,48210L,48211L,48212L,48213L,48214L,
48215L,48216L,48217L,48218L,48219L,48220L,48221L,48222L,48223L,48224L,
48225L,48226L,48227L,48228L,48229L,48230L,48231L,48232L,48233L,48234L,
48235L,48236L,48237L,48238L,48239L,48240L,48241L,48242L,48243L,48244L,
48245L,48246L,48247L,48248L,48249L,48250L,48251L,48252L,48253L,48254L,
48255L,48256L,48257L,48258L,48259L,48260L,48261L,48262L,48263L,48264L,
48265L,48266L,48267L,48268L,48269L,48270L,48271L,48272L,48273L,48274L,
48275L,48276L,48277L,48278L,48279L,48280L,48281L,48282L,48283L,48284L,
48285L,48286L,48287L,48288L,48289L,48290L,48291L,48292L,48293L,48294L,
48295L,48296L,48297L,48298L,48299L,48300L,48301L,48302L,48303L,48304L,
48305L,48306L,48307L,48308L,48309L,48310L,48311L,48312L,48313L,48314L,
48315L,48316L,48317L,48318L,48319L,48320L,48321L,48322L,48323L,48324L,
48325L,48326L,48327L,48328L,48329L,48330L,48331L,48332L,48333L,48334L,
48335L,48336L,48337L,48338L,48339L,48340L,48341L,48342L,48343L,48344L,
48345L,48346L,48347L,48348L,48349L,48350L,48351L,48352L,48353L,48354L,
48355L,48356L,48357L,48358L,48359L,48360L,48361L,48362L,48363L,48364L,
48365L,48366L,48367L,48368L,48369L,48370L,48371L,48372L,48373L,48374L,
48375L,48376L,48377L,48378L,48379L,48380L,48381L,48382L,48383L,48384L,
48385L,48386L,48387L,48388L,48389L,48390L,48391L,48392L,48393L,48394L,
48395L,48396L,48397L,48398L,48399L,48400L,48401L,48402L,48403L,48404L,
48405L,48406L,48407L,48408L,48409L,48410L,48411L,48412L,48413L,48414L,
48415L,48416L,48417L,48418L,48419L,48420L,48421L,48422L,48423L,48424L,
48425L,48426L,48427L,48428L,48429L,48430L,48431L,48432L,48433L,48434L,
48435L,48436L,48437L,48438L,48439L,48440L,48441L,48442L,48443L,48444L,
48445L,48446L,48447L,48448L,48449L,48450L,48451L,48452L,48453L,48454L,
48455L,48456L,48457L,48458L,48459L,48460L,48461L,48462L,48463L,48464L,
48465L,48466L,48467L,48468L,48469L,48470L,48471L,48472L,48473L,48474L,
48475L,48476L,48477L,48478L,48479L,48480L,48481L,48482L,48483L,48484L,
48485L,48486L,48487L,48488L,48489L,48490L,48491L,48492L,48493L,48494L,
48495L,48496L,48497L,48498L,48499L,48500L,48501L,48502L,48503L,48504L,
48505L,48506L,48507L,48508L,48509L,48510L,48511L,48512L,48513L,48514L,
48515L,48516L,48517L,48518L,48519L,48520L,48521L,48522L,48523L,48524L,
48525L,48526L,48527L,48528L,48529L,48530L,48531L,48532L,48533L,48534L,
48535L,48536L,48537L,48538L,48539L,48540L,48541L,48542L,48543L,48544L,
48545L,48546L,48547L,48548L,48549L,48550L,48551L,48552L,48553L,48554L,
48555L,48556L,48557L,48558L,48559L,48560L,48561L,48562L,48563L,48564L,
48565L,48566L,48567L,48568L,48569L,48570L,48571L,48572L,48573L,48574L,
48575L,48576L,48577L,48578L,48579L,48580L,48581L,48582L,48583L,48584L,
48585L,48586L,48587L,48588L,48589L,48590L,48591L,48592L,48593L,48594L,
48595L,48596L,48597L,48598L,48599L,48600L,48601L,48602L,48603L,48604L,
48605L,48606L,48607L,48608L,48609L,48610L,48611L,48612L,48613L,48614L,
48615L,48616L,48617L,48618L,48619L,48620L,48621L,48622L,48623L,48624L,
48625L,48626L,48627L,48628L,48629L,48630L,48631L,48632L,48633L,48634L,
48635L,48636L,48637L,48638L,48639L,48640L,48641L,48642L,48643L,48644L,
48645L,48646L,48647L,48648L,48649L,48650L,48651L,48652L,48653L,48654L,
48655L,48656L,48657L,48658L,48659L,48660L,48661L,48662L,48663L,48664L,
48665L,48666L,48667L,48668L,48669L,48670L,48671L,48672L,48673L,48674L,
48675L,48676L,48677L,48678L,48679L,48680L,48681L,48682L,48683L,48684L,
48685L,48686L,48687L,48688L,48689L,48690L,48691L,48692L,48693L,48694L,
48695L,48696L,48697L,48698L,48699L,48700L,48701L,48702L,48703L,48704L,
48705L,48706L,48707L,48708L,48709L,48710L,48711L,48712L,48713L,48714L,
48715L,48716L,48717L,48718L,48719L,48720L,48721L,48722L,48723L,48724L,
48725L,48726L,48727L,48728L,48729L,48730L,48731L,48732L,48733L,48734L,
48735L,48736L,48737L,48738L,48739L,48740L,48741L,48742L,48743L,48744L,
48745L,48746L,48747L,48748L,48749L,48750L,48751L,48752L,48753L,48754L,
48755L,48756L,48757L,48758L,48759L,48760L,48761L,48762L,48763L,48764L,
48765L,48766L,48767L,48768L,48769L,48770L,48771L,48772L,48773L,48774L,
48775L,48776L,48777L,48778L,48779L,48780L,48781L,48782L,48783L,48784L,
48785L,48786L,48787L,48788L,48789L,48790L,48791L,48792L,48793L,48794L,
48795L,48796L,48797L,48798L,48799L,48800L,48801L,48802L,48803L,48804L,
48805L,48806L,48807L,48808L,48809L,48810L,48811L,48812L,48813L,48814L,
48815L,48816L,48817L,48818L,48819L,48820L,48821L,48822L,48823L,48824L,
48825L,48826L,48827L,48828L,48829L,48830L,48831L,48832L,48833L,48834L,
48835L,48836L,48837L,48838L,48839L,48840L,48841L,48842L,48843L,48844L,
48845L,48846L,48847L,48848L,48849L,48850L,48851L,48852L,48853L,48854L,
48855L,48856L,48857L,48858L,48859L,48860L,48861L,48862L,48863L,48864L,
48865L,48866L,48867L,48868L,48869L,48870L,48871L,48872L,48873L,48874L,
48875L,48876L,48877L,48878L,48879L,48880L,48881L,48882L,48883L,48884L,
48885L,48886L,48887L,48888L,48889L,48890L,48891L,48892L,48893L,48894L,
48895L,48896L,48897L,48898L,48899L,48900L,48901L,48902L,48903L,48904L,
48905L,48906L,48907L,48908L,48909L,48910L,48911L,48912L,48913L,48914L,
48915L,48916L,48917L,48918L,48919L,48920L,48921L,48922L,48923L,48924L,
48925L,48926L,48927L,48928L,48929L,48930L,48931L,48932L,48933L,48934L,
48935L,48936L,48937L,48938L,48939L,48940L,48941L,48942L,48943L,48944L,
48945L,48946L,48947L,48948L,48949L,48950L,48951L,48952L,48953L,48954L,
48955L,48956L,48957L,48958L,48959L,48960L,48961L,48962L,48963L,48964L,
48965L,48966L,48967L,48968L,48969L,48970L,48971L,48972L,48973L,48974L,
48975L,48976L,48977L,48978L,48979L,48980L,48981L,48982L,48983L,48984L,
48985L,48986L,48987L,48988L,48989L,48990L,48991L,48992L,48993L,48994L,
48995L,48996L,48997L,48998L,48999L,49000L,49001L,49002L,49003L,49004L,
49005L,49006L,49007L,49008L,49009L,49010L,49011L,49012L,49013L,49014L,
49015L,49016L,49017L,49018L,49019L,49020L,49021L,49022L,49023L,49024L,
49025L,49026L,49027L,49028L,49029L,49030L,49031L,49032L,49033L,49034L,
49035L,49036L,49037L,49038L,49039L,49040L,49041L,49042L,49043L,49044L,
49045L,49046L,49047L,49048L,49049L,49050L,49051L,49052L,49053L,49054L,
49055L,49056L,49057L,49058L,49059L,49060L,49061L,49062L,49063L,49064L,
49065L,49066L,49067L,49068L,49069L,49070L,49071L,49072L,49073L,49074L,
49075L,49076L,49077L,49078L,49079L,49080L,49081L,49082L,49083L,49084L,
49085L,49086L,49087L,49088L,49089L,49090L,49091L,49092L,49093L,49094L,
49095L,49096L,49097L,49098L,49099L,49100L,49101L,49102L,49103L,49104L,
49105L,49106L,49107L,49108L,49109L,49110L,49111L,49112L,49113L,49114L,
49115L,49116L,49117L,49118L,49119L,49120L,49121L,49122L,49123L,49124L,
49125L,49126L,49127L,49128L,49129L,49130L,49131L,49132L,49133L,49134L,
49135L,49136L,49137L,49138L,49139L,49140L,49141L,49142L,49143L,49144L,
49145L,49146L,49147L,49148L,49149L,49150L,49151L,49152L,49153L,49154L,
49155L,49156L,49157L,49158L,49159L,49160L,49161L,49162L,49163L,49164L,
49165L,49166L,49167L,49168L,49169L,49170L,49171L,49172L,49173L,49174L,
49175L,49176L,49177L,49178L,49179L,49180L,49181L,49182L,49183L,49184L,
49185L,49186L,49187L,49188L,49189L,49190L,49191L,49192L,49193L,49194L,
49195L,49196L,49197L,49198L,49199L,49200L,49201L,49202L,49203L,49204L,
49205L,49206L,49207L,49208L,49209L,49210L,49211L,49212L,49213L,49214L,
49215L,49216L,49217L,49218L,49219L,49220L,49221L,49222L,49223L,49224L,
49225L,49226L,49227L,49228L,49229L,49230L,49231L,49232L,49233L,49234L,
49235L,49236L,49237L,49238L,49239L,49240L,49241L,49242L,49243L,49244L,
49245L,49246L,49247L,49248L,49249L,49250L,49251L,49252L,49253L,49254L,
49255L,49256L,49257L,49258L,49259L,49260L,49261L,49262L,49263L,49264L,
49265L,49266L,49267L,49268L,49269L,49270L,49271L,49272L,49273L,49274L,
49275L,49276L,49277L,49278L,49279L,49280L,49281L,49282L,49283L,49284L,
49285L,49286L,49287L,49288L,49289L,49290L,49291L,49292L,49293L,49294L,
49295L,49296L,49297L,49298L,49299L,49300L,49301L,49302L,49303L,49304L,
49305L,49306L,49307L,49308L,49309L,49310L,49311L,49312L,49313L,49314L,
49315L,49316L,49317L,49318L,49319L,49320L,49321L,49322L,49323L,49324L,
49325L,49326L,49327L,49328L,49329L,49330L,49331L,49332L,49333L,49334L,
49335L,49336L,49337L,49338L,49339L,49340L,49341L,49342L,49343L,49344L,
49345L,49346L,49347L,49348L,49349L,49350L,49351L,49352L,49353L,49354L,
49355L,49356L,49357L,49358L,49359L,49360L,49361L,49362L,49363L,49364L,
49365L,49366L,49367L,49368L,49369L,49370L,49371L,49372L,49373L,49374L,
49375L,49376L,49377L,49378L,49379L,49380L,49381L,49382L,49383L,49384L,
49385L,49386L,49387L,49388L,49389L,49390L,49391L,49392L,49393L,49394L,
49395L,49396L,49397L,49398L,49399L,49400L,49401L,49402L,49403L,49404L,
49405L,49406L,49407L,49408L,49409L,49410L,49411L,49412L,49413L,49414L,
49415L,49416L,49417L,49418L,49419L,49420L,49421L,49422L,49423L,49424L,
49425L,49426L,49427L,49428L,49429L,49430L,49431L,49432L,49433L,49434L,
49435L,49436L,49437L,49438L,49439L,49440L,49441L,49442L,49443L,49444L,
49445L,49446L,49447L,49448L,49449L,49450L,49451L,49452L,49453L,49454L,
49455L,49456L,49457L,49458L,49459L,49460L,49461L,49462L,49463L,49464L,
49465L,49466L,49467L,49468L,49469L,49470L,49471L,49472L,49473L,49474L,
49475L,49476L,49477L,49478L,49479L,49480L,49481L,49482L,49483L,49484L,
49485L,49486L,49487L,49488L,49489L,49490L,49491L,49492L,49493L,49494L,
49495L,49496L,49497L,49498L,49499L,49500L,49501L,49502L,49503L,49504L,
49505L,49506L,49507L,49508L,49509L,49510L,49511L,49512L,49513L,49514L,
49515L,49516L,49517L,49518L,49519L,49520L,49521L,49522L,49523L,49524L,
49525L,49526L,49527L,49528L,49529L,49530L,49531L,49532L,49533L,49534L,
49535L,49536L,49537L,49538L,49539L,49540L,49541L,49542L,49543L,49544L,
49545L,49546L,49547L,49548L,49549L,49550L,49551L,49552L,49553L,49554L,
49555L,49556L,49557L,49558L,49559L,49560L,49561L,49562L,49563L,49564L,
49565L,49566L,49567L,49568L,49569L,49570L,49571L,49572L,49573L,49574L,
49575L,49576L,49577L,49578L,49579L,49580L,49581L,49582L,49583L,49584L,
49585L,49586L,49587L,49588L,49589L,49590L,49591L,49592L,49593L,49594L,
49595L,49596L,49597L,49598L,49599L,49600L,49601L,49602L,49603L,49604L,
49605L,49606L,49607L,49608L,49609L,49610L,49611L,49612L,49613L,49614L,
49615L,49616L,49617L,49618L,49619L,49620L,49621L,49622L,49623L,49624L,
49625L,49626L,49627L,49628L,49629L,49630L,49631L,49632L,49633L,49634L,
49635L,49636L,49637L,49638L,49639L,49640L,49641L,49642L,49643L,49644L,
49645L,49646L,49647L,49648L,49649L,49650L,49651L,49652L,49653L,49654L,
49655L,49656L,49657L,49658L,49659L,49660L,49661L,49662L,49663L,49664L,
49665L,49666L,49667L,49668L,49669L,49670L,49671L,49672L,49673L,49674L,
49675L,49676L,49677L,49678L,49679L,49680L,49681L,49682L,49683L,49684L,
49685L,49686L,49687L,49688L,49689L,49690L,49691L,49692L,49693L,49694L,
49695L,49696L,49697L,49698L,49699L,49700L,49701L,49702L,49703L,49704L,
49705L,49706L,49707L,49708L,49709L,49710L,49711L,49712L,49713L,49714L,
49715L,49716L,49717L,49718L,49719L,49720L,49721L,49722L,49723L,49724L,
49725L,49726L,49727L,49728L,49729L,49730L,49731L,49732L,49733L,49734L,
49735L,49736L,49737L,49738L,49739L,49740L,49741L,49742L,49743L,49744L,
49745L,49746L,49747L,49748L,49749L,49750L,49751L,49752L,49753L,49754L,
49755L,49756L,49757L,49758L,49759L,49760L,49761L,49762L,49763L,49764L,
49765L,49766L,49767L,49768L,49769L,49770L,49771L,49772L,49773L,49774L,
49775L,49776L,49777L,49778L,49779L,49780L,49781L,49782L,49783L,49784L,
49785L,49786L,49787L,49788L,49789L,49790L,49791L,49792L,49793L,49794L,
49795L,49796L,49797L,49798L,49799L,49800L,49801L,49802L,49803L,49804L,
49805L,49806L,49807L,49808L,49809L,49810L,49811L,49812L,49813L,49814L,
49815L,49816L,49817L,49818L,49819L,49820L,49821L,49822L,49823L,49824L,
49825L,49826L,49827L,49828L,49829L,49830L,49831L,49832L,49833L,49834L,
49835L,49836L,49837L,49838L,49839L,49840L,49841L,49842L,49843L,49844L,
49845L,49846L,49847L,49848L,49849L,49850L,49851L,49852L,49853L,49854L,
49855L,49856L,49857L,49858L,49859L,49860L,49861L,49862L,49863L,49864L,
49865L,49866L,49867L,49868L,49869L,49870L,49871L,49872L,49873L,49874L,
49875L,49876L,49877L,49878L,49879L,49880L,49881L,49882L,49883L,49884L,
49885L,49886L,49887L,49888L,49889L,49890L,49891L,49892L,49893L,49894L,
49895L,49896L,49897L,49898L,49899L,49900L,49901L,49902L,49903L,49904L,
49905L,49906L,49907L,49908L,49909L,49910L,49911L,49912L,49913L,49914L,
49915L,49916L,49917L,49918L,49919L,49920L,49921L,49922L,49923L,49924L,
49925L,49926L,49927L,49928L,49929L,49930L,49931L,49932L,49933L,49934L,
49935L,49936L,49937L,49938L,49939L,49940L,49941L,49942L,49943L,49944L,
49945L,49946L,49947L,49948L,49949L,49950L,49951L,49952L,49953L,49954L,
49955L,49956L,49957L,49958L,49959L,49960L,49961L,49962L,49963L,49964L,
49965L,49966L,49967L,49968L,49969L,49970L,49971L,49972L,49973L,49974L,
49975L,49976L,49977L,49978L,49979L,49980L,49981L,49982L,49983L,49984L,
49985L,49986L,49987L,49988L,49989L,49990L,49991L,49992L,49993L,49994L,
49995L,49996L,49997L,49998L,49999L,50000L,50001L,50002L,50003L,50004L,
50005L,50006L,50007L,50008L,50009L,50010L,50011L,50012L,50013L,50014L,
50015L,50016L,50017L,50018L,50019L,50020L,50021L,50022L,50023L,50024L,
50025L,50026L,50027L,50028L,50029L,50030L,50031L,50032L,50033L,50034L,
50035L,50036L,50037L,50038L,50039L,50040L,50041L,50042L,50043L,50044L,
50045L,50046L,50047L,50048L,50049L,50050L,50051L,50052L,50053L,50054L,
50055L,50056L,50057L,50058L,50059L,50060L,50061L,50062L,50063L,50064L,
50065L,50066L,50067L,50068L,50069L,50070L,50071L,50072L,50073L,50074L,
50075L,50076L,50077L,50078L,50079L,50080L,50081L,50082L,50083L,50084L,
50085L,50086L,50087L,50088L,50089L,50090L,50091L,50092L,50093L,50094L,
50095L,50096L,50097L,50098L,50099L,50100L,50101L,50102L,50103L,50104L,
50105L,50106L,50107L,50108L,50109L,50110L,50111L,50112L,50113L,50114L,
50115L,50116L,50117L,50118L,50119L,50120L,50121L,50122L,50123L,50124L,
50125L,50126L,50127L,50128L,50129L,50130L,50131L,50132L,50133L,50134L,
50135L,50136L,50137L,50138L,50139L,50140L,50141L,50142L,50143L,50144L,
50145L,50146L,50147L,50148L,50149L,50150L,50151L,50152L,50153L,50154L,
50155L,50156L,50157L,50158L,50159L,50160L,50161L,50162L,50163L,50164L,
50165L,50166L,50167L,50168L,50169L,50170L,50171L,50172L,50173L,50174L,
50175L,50176L,50177L,50178L,50179L,50180L,50181L,50182L,50183L,50184L,
50185L,50186L,50187L,50188L,50189L,50190L,50191L,50192L,50193L,50194L,
50195L,50196L,50197L,50198L,50199L,50200L,50201L,50202L,50203L,50204L,
50205L,50206L,50207L,50208L,50209L,50210L,50211L,50212L,50213L,50214L,
50215L,50216L,50217L,50218L,50219L,50220L,50221L,50222L,50223L,50224L,
50225L,50226L,50227L,50228L,50229L,50230L,50231L,50232L,50233L,50234L,
50235L,50236L,50237L,50238L,50239L,50240L,50241L,50242L,50243L,50244L,
50245L,50246L,50247L,50248L,50249L,50250L,50251L,50252L,50253L,50254L,
50255L,50256L,50257L,50258L,50259L,50260L,50261L,50262L,50263L,50264L,
50265L,50266L,50267L,50268L,50269L,50270L,50271L,50272L,50273L,50274L,
50275L,50276L,50277L,50278L,50279L,50280L,50281L,50282L,50283L,50284L,
50285L,50286L,50287L,50288L,50289L,50290L,50291L,50292L,50293L,50294L,
50295L,50296L,50297L,50298L,50299L,50300L,50301L,50302L,50303L,50304L,
50305L,50306L,50307L,50308L,50309L,50310L,50311L,50312L,50313L,50314L,
50315L,50316L,50317L,50318L,50319L,50320L,50321L,50322L,50323L,50324L,
50325L,50326L,50327L,50328L,50329L,50330L,50331L,50332L,50333L,50334L,
50335L,50336L,50337L,50338L,50339L,50340L,50341L,50342L,50343L,50344L,
50345L,50346L,50347L,50348L,50349L,50350L,50351L,50352L,50353L,50354L,
50355L,50356L,50357L,50358L,50359L,50360L,50361L,50362L,50363L,50364L,
50365L,50366L,50367L,50368L,50369L,50370L,50371L,50372L,50373L,50374L,
50375L,50376L,50377L,50378L,50379L,50380L,50381L,50382L,50383L,50384L,
50385L,50386L,50387L,50388L,50389L,50390L,50391L,50392L,50393L,50394L,
50395L,50396L,50397L,50398L,50399L,50400L,50401L,50402L,50403L,50404L,
50405L,50406L,50407L,50408L,50409L,50410L,50411L,50412L,50413L,50414L,
50415L,50416L,50417L,50418L,50419L,50420L,50421L,50422L,50423L,50424L,
50425L,50426L,50427L,50428L,50429L,50430L,50431L,50432L,50433L,50434L,
50435L,50436L,50437L,50438L,50439L,50440L,50441L,50442L,50443L,50444L,
50445L,50446L,50447L,50448L,50449L,50450L,50451L,50452L,50453L,50454L,
50455L,50456L,50457L,50458L,50459L,50460L,50461L,50462L,50463L,50464L,
50465L,50466L,50467L,50468L,50469L,50470L,50471L,50472L,50473L,50474L,
50475L,50476L,50477L,50478L,50479L,50480L,50481L,50482L,50483L,50484L,
50485L,50486L,50487L,50488L,50489L,50490L,50491L,50492L,50493L,50494L,
50495L,50496L,50497L,50498L,50499L,50500L,50501L,50502L,50503L,50504L,
50505L,50506L,50507L,50508L,50509L,50510L,50511L,50512L,50513L,50514L,
50515L,50516L,50517L,50518L,50519L,50520L,50521L,50522L,50523L,50524L,
50525L,50526L,50527L,50528L,50529L,50530L,50531L,50532L,50533L,50534L,
50535L,50536L,50537L,50538L,50539L,50540L,50541L,50542L,50543L,50544L,
50545L,50546L,50547L,50548L,50549L,50550L,50551L,50552L,50553L,50554L,
50555L,50556L,50557L,50558L,50559L,50560L,50561L,50562L,50563L,50564L,
50565L,50566L,50567L,50568L,50569L,50570L,50571L,50572L,50573L,50574L,
50575L,50576L,50577L,50578L,50579L,50580L,50581L,50582L,50583L,50584L,
50585L,50586L,50587L,50588L,50589L,50590L,50591L,50592L,50593L,50594L,
50595L,50596L,50597L,50598L,50599L,50600L,50601L,50602L,50603L,50604L,
50605L,50606L,50607L,50608L,50609L,50610L,50611L,50612L,50613L,50614L,
50615L,50616L,50617L,50618L,50619L,50620L,50621L,50622L,50623L,50624L,
50625L,50626L,50627L,50628L,50629L,50630L,50631L,50632L,50633L,50634L,
50635L,50636L,50637L,50638L,50639L,50640L,50641L,50642L,50643L,50644L,
50645L,50646L,50647L,50648L,50649L,50650L,50651L,50652L,50653L,50654L,
50655L,50656L,50657L,50658L,50659L,50660L,50661L,50662L,50663L,50664L,
50665L,50666L,50667L,50668L,50669L,50670L,50671L,50672L,50673L,50674L,
50675L,50676L,50677L,50678L,50679L,50680L,50681L,50682L,50683L,50684L,
50685L,50686L,50687L,50688L,50689L,50690L,50691L,50692L,50693L,50694L,
50695L,50696L,50697L,50698L,50699L,50700L,50701L,50702L,50703L,50704L,
50705L,50706L,50707L,50708L,50709L,50710L,50711L,50712L,50713L,50714L,
50715L,50716L,50717L,50718L,50719L,50720L,50721L,50722L,50723L,50724L,
50725L,50726L,50727L,50728L,50729L,50730L,50731L,50732L,50733L,50734L,
50735L,50736L,50737L,50738L,50739L,50740L,50741L,50742L,50743L,50744L,
50745L,50746L,50747L,50748L,50749L,50750L,50751L,50752L,50753L,50754L,
50755L,50756L,50757L,50758L,50759L,50760L,50761L,50762L,50763L,50764L,
50765L,50766L,50767L,50768L,50769L,50770L,50771L,50772L,50773L,50774L,
50775L,50776L,50777L,50778L,50779L,50780L,50781L,50782L,50783L,50784L,
50785L,50786L,50787L,50788L,50789L,50790L,50791L,50792L,50793L,50794L,
50795L,50796L,50797L,50798L,50799L,50800L,50801L,50802L,50803L,50804L,
50805L,50806L,50807L,50808L,50809L,50810L,50811L,50812L,50813L,50814L,
50815L,50816L,50817L,50818L,50819L,50820L,50821L,50822L,50823L,50824L,
50825L,50826L,50827L,50828L,50829L,50830L,50831L,50832L,50833L,50834L,
50835L,50836L,50837L,50838L,50839L,50840L,50841L,50842L,50843L,50844L,
50845L,50846L,50847L,50848L,50849L,50850L,50851L,50852L,50853L,50854L,
50855L,50856L,50857L,50858L,50859L,50860L,50861L,50862L,50863L,50864L,
50865L,50866L,50867L,50868L,50869L,50870L,50871L,50872L,50873L,50874L,
50875L,50876L,50877L,50878L,50879L,50880L,50881L,50882L,50883L,50884L,
50885L,50886L,50887L,50888L,50889L,50890L,50891L,50892L,50893L,50894L,
50895L,50896L,50897L,50898L,50899L,50900L,50901L,50902L,50903L,50904L,
50905L,50906L,50907L,50908L,50909L,50910L,50911L,50912L,50913L,50914L,
50915L,50916L,50917L,50918L,50919L,50920L,50921L,50922L,50923L,50924L,
50925L,50926L,50927L,50928L,50929L,50930L,50931L,50932L,50933L,50934L,
50935L,50936L,50937L,50938L,50939L,50940L,50941L,50942L,50943L,50944L,
50945L,50946L,50947L,50948L,50949L,50950L,50951L,50952L,50953L,50954L,
50955L,50956L,50957L,50958L,50959L,50960L,50961L,50962L,50963L,50964L,
50965L,50966L,50967L,50968L,50969L,50970L,50971L,50972L,50973L,50974L,
50975L,50976L,50977L,50978L,50979L,50980L,50981L,50982L,50983L,50984L,
50985L,50986L,50987L,50988L,50989L,50990L,50991L,50992L,50993L,50994L,
50995L,50996L,50997L,50998L,50999L,51000L,51001L,51002L,51003L,51004L,
51005L,51006L,51007L,51008L,51009L,51010L,51011L,51012L,51013L,51014L,
51015L,51016L,51017L,51018L,51019L,51020L,51021L,51022L,51023L,51024L,
51025L,51026L,51027L,51028L,51029L,51030L,51031L,51032L,51033L,51034L,
51035L,51036L,51037L,51038L,51039L,51040L,51041L,51042L,51043L,51044L,
51045L,51046L,51047L,51048L,51049L,51050L,51051L,51052L,51053L,51054L,
51055L,51056L,51057L,51058L,51059L,51060L,51061L,51062L,51063L,51064L,
51065L,51066L,51067L,51068L,51069L,51070L,51071L,51072L,51073L,51074L,
51075L,51076L,51077L,51078L,51079L,51080L,51081L,51082L,51083L,51084L,
51085L,51086L,51087L,51088L,51089L,51090L,51091L,51092L,51093L,51094L,
51095L,51096L,51097L,51098L,51099L,51100L,51101L,51102L,51103L,51104L,
51105L,51106L,51107L,51108L,51109L,51110L,51111L,51112L,51113L,51114L,
51115L,51116L,51117L,51118L,51119L,51120L,51121L,51122L,51123L,51124L,
51125L,51126L,51127L,51128L,51129L,51130L,51131L,51132L,51133L,51134L,
51135L,51136L,51137L,51138L,51139L,51140L,51141L,51142L,51143L,51144L,
51145L,51146L,51147L,51148L,51149L,51150L,51151L,51152L,51153L,51154L,
51155L,51156L,51157L,51158L,51159L,51160L,51161L,51162L,51163L,51164L,
51165L,51166L,51167L,51168L,51169L,51170L,51171L,51172L,51173L,51174L,
51175L,51176L,51177L,51178L,51179L,51180L,51181L,51182L,51183L,51184L,
51185L,51186L,51187L,51188L,51189L,51190L,51191L,51192L,51193L,51194L,
51195L,51196L,51197L,51198L,51199L,51200L,51201L,51202L,51203L,51204L,
51205L,51206L,51207L,51208L,51209L,51210L,51211L,51212L,51213L,51214L,
51215L,51216L,51217L,51218L,51219L,51220L,51221L,51222L,51223L,51224L,
51225L,51226L,51227L,51228L,51229L,51230L,51231L,51232L,51233L,51234L,
51235L,51236L,51237L,51238L,51239L,51240L,51241L,51242L,51243L,51244L,
51245L,51246L,51247L,51248L,51249L,51250L,51251L,51252L,51253L,51254L,
51255L,51256L,51257L,51258L,51259L,51260L,51261L,51262L,51263L,51264L,
51265L,51266L,51267L,51268L,51269L,51270L,51271L,51272L,51273L,51274L,
51275L,51276L,51277L,51278L,51279L,51280L,51281L,51282L,51283L,51284L,
51285L,51286L,51287L,51288L,51289L,51290L,51291L,51292L,51293L,51294L,
51295L,51296L,51297L,51298L,51299L,51300L,51301L,51302L,51303L,51304L,
51305L,51306L,51307L,51308L,51309L,51310L,51311L,51312L,51313L,51314L,
51315L,51316L,51317L,51318L,51319L,51320L,51321L,51322L,51323L,51324L,
51325L,51326L,51327L,51328L,51329L,51330L,51331L,51332L,51333L,51334L,
51335L,51336L,51337L,51338L,51339L,51340L,51341L,51342L,51343L,51344L,
51345L,51346L,51347L,51348L,51349L,51350L,51351L,51352L,51353L,51354L,
51355L,51356L,51357L,51358L,51359L,51360L,51361L,51362L,51363L,51364L,
51365L,51366L,51367L,51368L,51369L,51370L,51371L,51372L,51373L,51374L,
51375L,51376L,51377L,51378L,51379L,51380L,51381L,51382L,51383L,51384L,
51385L,51386L,51387L,51388L,51389L,51390L,51391L,51392L,51393L,51394L,
51395L,51396L,51397L,51398L,51399L,51400L,51401L,51402L,51403L,51404L,
51405L,51406L,51407L,51408L,51409L,51410L,51411L,51412L,51413L,51414L,
51415L,51416L,51417L,51418L,51419L,51420L,51421L,51422L,51423L,51424L,
51425L,51426L,51427L,51428L,51429L,51430L,51431L,51432L,51433L,51434L,
51435L,51436L,51437L,51438L,51439L,51440L,51441L,51442L,51443L,51444L,
51445L,51446L,51447L,51448L,51449L,51450L,51451L,51452L,51453L,51454L,
51455L,51456L,51457L,51458L,51459L,51460L,51461L,51462L,51463L,51464L,
51465L,51466L,51467L,51468L,51469L,51470L,51471L,51472L,51473L,51474L,
51475L,51476L,51477L,51478L,51479L,51480L,51481L,51482L,51483L,51484L,
51485L,51486L,51487L,51488L,51489L,51490L,51491L,51492L,51493L,51494L,
51495L,51496L,51497L,51498L,51499L,51500L,51501L,51502L,51503L,51504L,
51505L,51506L,51507L,51508L,51509L,51510L,51511L,51512L,51513L,51514L,
51515L,51516L,51517L,51518L,51519L,51520L,51521L,51522L,51523L,51524L,
51525L,51526L,51527L,51528L,51529L,51530L,51531L,51532L,51533L,51534L,
51535L,51536L,51537L,51538L,51539L,51540L,51541L,51542L,51543L,51544L,
51545L,51546L,51547L,51548L,51549L,51550L,51551L,51552L,51553L,51554L,
51555L,51556L,51557L,51558L,51559L,51560L,51561L,51562L,51563L,51564L,
51565L,51566L,51567L,51568L,51569L,51570L,51571L,51572L,51573L,51574L,
51575L,51576L,51577L,51578L,51579L,51580L,51581L,51582L,51583L,51584L,
51585L,51586L,51587L,51588L,51589L,51590L,51591L,51592L,51593L,51594L,
51595L,51596L,51597L,51598L,51599L,51600L,51601L,51602L,51603L,51604L,
51605L,51606L,51607L,51608L,51609L,51610L,51611L,51612L,51613L,51614L,
51615L,51616L,51617L,51618L,51619L,51620L,51621L,51622L,51623L,51624L,
51625L,51626L,51627L,51628L,51629L,51630L,51631L,51632L,51633L,51634L,
51635L,51636L,51637L,51638L,51639L,51640L,51641L,51642L,51643L,51644L,
51645L,51646L,51647L,51648L,51649L,51650L,51651L,51652L,51653L,51654L,
51655L,51656L,51657L,51658L,51659L,51660L,51661L,51662L,51663L,51664L,
51665L,51666L,51667L,51668L,51669L,51670L,51671L,51672L,51673L,51674L,
51675L,51676L,51677L,51678L,51679L,51680L,51681L,51682L,51683L,51684L,
51685L,51686L,51687L,51688L,51689L,51690L,51691L,51692L,51693L,51694L,
51695L,51696L,51697L,51698L,51699L,51700L,51701L,51702L,51703L,51704L,
51705L,51706L,51707L,51708L,51709L,51710L,51711L,51712L,51713L,51714L,
51715L,51716L,51717L,51718L,51719L,51720L,51721L,51722L,51723L,51724L,
51725L,51726L,51727L,51728L,51729L,51730L,51731L,51732L,51733L,51734L,
51735L,51736L,51737L,51738L,51739L,51740L,51741L,51742L,51743L,51744L,
51745L,51746L,51747L,51748L,51749L,51750L,51751L,51752L,51753L,51754L,
51755L,51756L,51757L,51758L,51759L,51760L,51761L,51762L,51763L,51764L,
51765L,51766L,51767L,51768L,51769L,51770L,51771L,51772L,51773L,51774L,
51775L,51776L,51777L,51778L,51779L,51780L,51781L,51782L,51783L,51784L,
51785L,51786L,51787L,51788L,51789L,51790L,51791L,51792L,51793L,51794L,
51795L,51796L,51797L,51798L,51799L,51800L,51801L,51802L,51803L,51804L,
51805L,51806L,51807L,51808L,51809L,51810L,51811L,51812L,51813L,51814L,
51815L,51816L,51817L,51818L,51819L,51820L,51821L,51822L,51823L,51824L,
51825L,51826L,51827L,51828L,51829L,51830L,51831L,51832L,51833L,51834L,
51835L,51836L,51837L,51838L,51839L,51840L,51841L,51842L,51843L,51844L,
51845L,51846L,51847L,51848L,51849L,51850L,51851L,51852L,51853L,51854L,
51855L,51856L,51857L,51858L,51859L,51860L,51861L,51862L,51863L,51864L,
51865L,51866L,51867L,51868L,51869L,51870L,51871L,51872L,51873L,51874L,
51875L,51876L,51877L,51878L,51879L,51880L,51881L,51882L,51883L,51884L,
51885L,51886L,51887L,51888L,51889L,51890L,51891L,51892L,51893L,51894L,
51895L,51896L,51897L,51898L,51899L,51900L,51901L,51902L,51903L,51904L,
51905L,51906L,51907L,51908L,51909L,51910L,51911L,51912L,51913L,51914L,
51915L,51916L,51917L,51918L,51919L,51920L,51921L,51922L,51923L,51924L,
51925L,51926L,51927L,51928L,51929L,51930L,51931L,51932L,51933L,51934L,
51935L,51936L,51937L,51938L,51939L,51940L,51941L,51942L,51943L,51944L,
51945L,51946L,51947L,51948L,51949L,51950L,51951L,51952L,51953L,51954L,
51955L,51956L,51957L,51958L,51959L,51960L,51961L,51962L,51963L,51964L,
51965L,51966L,51967L,51968L,51969L,51970L,51971L,51972L,51973L,51974L,
51975L,51976L,51977L,51978L,51979L,51980L,51981L,51982L,51983L,51984L,
51985L,51986L,51987L,51988L,51989L,51990L,51991L,51992L,51993L,51994L,
51995L,51996L,51997L,51998L,51999L,52000L,52001L,52002L,52003L,52004L,
52005L,52006L,52007L,52008L,52009L,52010L,52011L,52012L,52013L,52014L,
52015L,52016L,52017L,52018L,52019L,52020L,52021L,52022L,52023L,52024L,
52025L,52026L,52027L,52028L,52029L,52030L,52031L,52032L,52033L,52034L,
52035L,52036L,52037L,52038L,52039L,52040L,52041L,52042L,52043L,52044L,
52045L,52046L,52047L,52048L,52049L,52050L,52051L,52052L,52053L,52054L,
52055L,52056L,52057L,52058L,52059L,52060L,52061L,52062L,52063L,52064L,
52065L,52066L,52067L,52068L,52069L,52070L,52071L,52072L,52073L,52074L,
52075L,52076L,52077L,52078L,52079L,52080L,52081L,52082L,52083L,52084L,
52085L,52086L,52087L,52088L,52089L,52090L,52091L,52092L,52093L,52094L,
52095L,52096L,52097L,52098L,52099L,52100L,52101L,52102L,52103L,52104L,
52105L,52106L,52107L,52108L,52109L,52110L,52111L,52112L,52113L,52114L,
52115L,52116L,52117L,52118L,52119L,52120L,52121L,52122L,52123L,52124L,
52125L,52126L,52127L,52128L,52129L,52130L,52131L,52132L,52133L,52134L,
52135L,52136L,52137L,52138L,52139L,52140L,52141L,52142L,52143L,52144L,
52145L,52146L,52147L,52148L,52149L,52150L,52151L,52152L,52153L,52154L,
52155L,52156L,52157L,52158L,52159L,52160L,52161L,52162L,52163L,52164L,
52165L,52166L,52167L,52168L,52169L,52170L,52171L,52172L,52173L,52174L,
52175L,52176L,52177L,52178L,52179L,52180L,52181L,52182L,52183L,52184L,
52185L,52186L,52187L,52188L,52189L,52190L,52191L,52192L,52193L,52194L,
52195L,52196L,52197L,52198L,52199L,52200L,52201L,52202L,52203L,52204L,
52205L,52206L,52207L,52208L,52209L,52210L,52211L,52212L,52213L,52214L,
52215L,52216L,52217L,52218L,52219L,52220L,52221L,52222L,52223L,52224L,
52225L,52226L,52227L,52228L,52229L,52230L,52231L,52232L,52233L,52234L,
52235L,52236L,52237L,52238L,52239L,52240L,52241L,52242L,52243L,52244L,
52245L,52246L,52247L,52248L,52249L,52250L,52251L,52252L,52253L,52254L,
52255L,52256L,52257L,52258L,52259L,52260L,52261L,52262L,52263L,52264L,
52265L,52266L,52267L,52268L,52269L,52270L,52271L,52272L,52273L,52274L,
52275L,52276L,52277L,52278L,52279L,52280L,52281L,52282L,52283L,52284L,
52285L,52286L,52287L,52288L,52289L,52290L,52291L,52292L,52293L,52294L,
52295L,52296L,52297L,52298L,52299L,52300L,52301L,52302L,52303L,52304L,
52305L,52306L,52307L,52308L,52309L,52310L,52311L,52312L,52313L,52314L,
52315L,52316L,52317L,52318L,52319L,52320L,52321L,52322L,52323L,52324L,
52325L,52326L,52327L,52328L,52329L,52330L,52331L,52332L,52333L,52334L,
52335L,52336L,52337L,52338L,52339L,52340L,52341L,52342L,52343L,52344L,
52345L,52346L,52347L,52348L,52349L,52350L,52351L,52352L,52353L,52354L,
52355L,52356L,52357L,52358L,52359L,52360L,52361L,52362L,52363L,52364L,
52365L,52366L,52367L,52368L,52369L,52370L,52371L,52372L,52373L,52374L,
52375L,52376L,52377L,52378L,52379L,52380L,52381L,52382L,52383L,52384L,
52385L,52386L,52387L,52388L,52389L,52390L,52391L,52392L,52393L,52394L,
52395L,52396L,52397L,52398L,52399L,52400L,52401L,52402L,52403L,52404L,
52405L,52406L,52407L,52408L,52409L,52410L,52411L,52412L,52413L,52414L,
52415L,52416L,52417L,52418L,52419L,52420L,52421L,52422L,52423L,52424L,
52425L,52426L,52427L,52428L,52429L,52430L,52431L,52432L,52433L,52434L,
52435L,52436L,52437L,52438L,52439L,52440L,52441L,52442L,52443L,52444L,
52445L,52446L,52447L,52448L,52449L,52450L,52451L,52452L,52453L,52454L,
52455L,52456L,52457L,52458L,52459L,52460L,52461L,52462L,52463L,52464L,
52465L,52466L,52467L,52468L,52469L,52470L,52471L,52472L,52473L,52474L,
52475L,52476L,52477L,52478L,52479L,52480L,52481L,52482L,52483L,52484L,
52485L,52486L,52487L,52488L,52489L,52490L,52491L,52492L,52493L,52494L,
52495L,52496L,52497L,52498L,52499L,52500L,52501L,52502L,52503L,52504L,
52505L,52506L,52507L,52508L,52509L,52510L,52511L,52512L,52513L,52514L,
52515L,52516L,52517L,52518L,52519L,52520L,52521L,52522L,52523L,52524L,
52525L,52526L,52527L,52528L,52529L,52530L,52531L,52532L,52533L,52534L,
52535L,52536L,52537L,52538L,52539L,52540L,52541L,52542L,52543L,52544L,
52545L,52546L,52547L,52548L,52549L,52550L,52551L,52552L,52553L,52554L,
52555L,52556L,52557L,52558L,52559L,52560L,52561L,52562L,52563L,52564L,
52565L,52566L,52567L,52568L,52569L,52570L,52571L,52572L,52573L,52574L,
52575L,52576L,52577L,52578L,52579L,52580L,52581L,52582L,52583L,52584L,
52585L,52586L,52587L,52588L,52589L,52590L,52591L,52592L,52593L,52594L,
52595L,52596L,52597L,52598L,52599L,52600L,52601L,52602L,52603L,52604L,
52605L,52606L,52607L,52608L,52609L,52610L,52611L,52612L,52613L,52614L,
52615L,52616L,52617L,52618L,52619L,52620L,52621L,52622L,52623L,52624L,
52625L,52626L,52627L,52628L,52629L,52630L,52631L,52632L,52633L,52634L,
52635L,52636L,52637L,52638L,52639L,52640L,52641L,52642L,52643L,52644L,
52645L,52646L,52647L,52648L,52649L,52650L,52651L,52652L,52653L,52654L,
52655L,52656L,52657L,52658L,52659L,52660L,52661L,52662L,52663L,52664L,
52665L,52666L,52667L,52668L,52669L,52670L,52671L,52672L,52673L,52674L,
52675L,52676L,52677L,52678L,52679L,52680L,52681L,52682L,52683L,52684L,
52685L,52686L,52687L,52688L,52689L,52690L,52691L,52692L,52693L,52694L,
52695L,52696L,52697L,52698L,52699L,52700L,52701L,52702L,52703L,52704L,
52705L,52706L,52707L,52708L,52709L,52710L,52711L,52712L,52713L,52714L,
52715L,52716L,52717L,52718L,52719L,52720L,52721L,52722L,52723L,52724L,
52725L,52726L,52727L,52728L,52729L,52730L,52731L,52732L,52733L,52734L,
52735L,52736L,52737L,52738L,52739L,52740L,52741L,52742L,52743L,52744L,
52745L,52746L,52747L,52748L,52749L,52750L,52751L,52752L,52753L,52754L,
52755L,52756L,52757L,52758L,52759L,52760L,52761L,52762L,52763L,52764L,
52765L,52766L,52767L,52768L,52769L,52770L,52771L,52772L,52773L,52774L,
52775L,52776L,52777L,52778L,52779L,52780L,52781L,52782L,52783L,52784L,
52785L,52786L,52787L,52788L,52789L,52790L,52791L,52792L,52793L,52794L,
52795L,52796L,52797L,52798L,52799L,52800L,52801L,52802L,52803L,52804L,
52805L,52806L,52807L,52808L,52809L,52810L,52811L,52812L,52813L,52814L,
52815L,52816L,52817L,52818L,52819L,52820L,52821L,52822L,52823L,52824L,
52825L,52826L,52827L,52828L,52829L,52830L,52831L,52832L,52833L,52834L,
52835L,52836L,52837L,52838L,52839L,52840L,52841L,52842L,52843L,52844L,
52845L,52846L,52847L,52848L,52849L,52850L,52851L,52852L,52853L,52854L,
52855L,52856L,52857L,52858L,52859L,52860L,52861L,52862L,52863L,52864L,
52865L,52866L,52867L,52868L,52869L,52870L,52871L,52872L,52873L,52874L,
52875L,52876L,52877L,52878L,52879L,52880L,52881L,52882L,52883L,52884L,
52885L,52886L,52887L,52888L,52889L,52890L,52891L,52892L,52893L,52894L,
52895L,52896L,52897L,52898L,52899L,52900L,52901L,52902L,52903L,52904L,
52905L,52906L,52907L,52908L,52909L,52910L,52911L,52912L,52913L,52914L,
52915L,52916L,52917L,52918L,52919L,52920L,52921L,52922L,52923L,52924L,
52925L,52926L,52927L,52928L,52929L,52930L,52931L,52932L,52933L,52934L,
52935L,52936L,52937L,52938L,52939L,52940L,52941L,52942L,52943L,52944L,
52945L,52946L,52947L,52948L,52949L,52950L,52951L,52952L,52953L,52954L,
52955L,52956L,52957L,52958L,52959L,52960L,52961L,52962L,52963L,52964L,
52965L,52966L,52967L,52968L,52969L,52970L,52971L,52972L,52973L,52974L,
52975L,52976L,52977L,52978L,52979L,52980L,52981L,52982L,52983L,52984L,
52985L,52986L,52987L,52988L,52989L,52990L,52991L,52992L,52993L,52994L,
52995L,52996L,52997L,52998L,52999L,53000L,53001L,53002L,53003L,53004L,
53005L,53006L,53007L,53008L,53009L,53010L,53011L,53012L,53013L,53014L,
53015L,53016L,53017L,53018L,53019L,53020L,53021L,53022L,53023L,53024L,
53025L,53026L,53027L,53028L,53029L,53030L,53031L,53032L,53033L,53034L,
53035L,53036L,53037L,53038L,53039L,53040L,53041L,53042L,53043L,53044L,
53045L,53046L,53047L,53048L,53049L,53050L,53051L,53052L,53053L,53054L,
53055L,53056L,53057L,53058L,53059L,53060L,53061L,53062L,53063L,53064L,
53065L,53066L,53067L,53068L,53069L,53070L,53071L,53072L,53073L,53074L,
53075L,53076L,53077L,53078L,53079L,53080L,53081L,53082L,53083L,53084L,
53085L,53086L,53087L,53088L,53089L,53090L,53091L,53092L,53093L,53094L,
53095L,53096L,53097L,53098L,53099L,53100L,53101L,53102L,53103L,53104L,
53105L,53106L,53107L,53108L,53109L,53110L,53111L,53112L,53113L,53114L,
53115L,53116L,53117L,53118L,53119L,53120L,53121L,53122L,53123L,53124L,
53125L,53126L,53127L,53128L,53129L,53130L,53131L,53132L,53133L,53134L,
53135L,53136L,53137L,53138L,53139L,53140L,53141L,53142L,53143L,53144L,
53145L,53146L,53147L,53148L,53149L,53150L,53151L,53152L,53153L,53154L,
53155L,53156L,53157L,53158L,53159L,53160L,53161L,53162L,53163L,53164L,
53165L,53166L,53167L,53168L,53169L,53170L,53171L,53172L,53173L,53174L,
53175L,53176L,53177L,53178L,53179L,53180L,53181L,53182L,53183L,53184L,
53185L,53186L,53187L,53188L,53189L,53190L,53191L,53192L,53193L,53194L,
53195L,53196L,53197L,53198L,53199L,53200L,53201L,53202L,53203L,53204L,
53205L,53206L,53207L,53208L,53209L,53210L,53211L,53212L,53213L,53214L,
53215L,53216L,53217L,53218L,53219L,53220L,53221L,53222L,53223L,53224L,
53225L,53226L,53227L,53228L,53229L,53230L,53231L,53232L,53233L,53234L,
53235L,53236L,53237L,53238L,53239L,53240L,53241L,53242L,53243L,53244L,
53245L,53246L,53247L,53248L,53249L,53250L,53251L,53252L,53253L,53254L,
53255L,53256L,53257L,53258L,53259L,53260L,53261L,53262L,53263L,53264L,
53265L,53266L,53267L,53268L,53269L,53270L,53271L,53272L,53273L,53274L,
53275L,53276L,53277L,53278L,53279L,53280L,53281L,53282L,53283L,53284L,
53285L,53286L,53287L,53288L,53289L,53290L,53291L,53292L,53293L,53294L,
53295L,53296L,53297L,53298L,53299L,53300L,53301L,53302L,53303L,53304L,
53305L,53306L,53307L,53308L,53309L,53310L,53311L,53312L,53313L,53314L,
53315L,53316L,53317L,53318L,53319L,53320L,53321L,53322L,53323L,53324L,
53325L,53326L,53327L,53328L,53329L,53330L,53331L,53332L,53333L,53334L,
53335L,53336L,53337L,53338L,53339L,53340L,53341L,53342L,53343L,53344L,
53345L,53346L,53347L,53348L,53349L,53350L,53351L,53352L,53353L,53354L,
53355L,53356L,53357L,53358L,53359L,53360L,53361L,53362L,53363L,53364L,
53365L,53366L,53367L,53368L,53369L,53370L,53371L,53372L,53373L,53374L,
53375L,53376L,53377L,53378L,53379L,53380L,53381L,53382L,53383L,53384L,
53385L,53386L,53387L,53388L,53389L,53390L,53391L,53392L,53393L,53394L,
53395L,53396L,53397L,53398L,53399L,53400L,53401L,53402L,53403L,53404L,
53405L,53406L,53407L,53408L,53409L,53410L,53411L,53412L,53413L,53414L,
53415L,53416L,53417L,53418L,53419L,53420L,53421L,53422L,53423L,53424L,
53425L,53426L,53427L,53428L,53429L,53430L,53431L,53432L,53433L,53434L,
53435L,53436L,53437L,53438L,53439L,53440L,53441L,53442L,53443L,53444L,
53445L,53446L,53447L,53448L,53449L,53450L,53451L,53452L,53453L,53454L,
53455L,53456L,53457L,53458L,53459L,53460L,53461L,53462L,53463L,53464L,
53465L,53466L,53467L,53468L,53469L,53470L,53471L,53472L,53473L,53474L,
53475L,53476L,53477L,53478L,53479L,53480L,53481L,53482L,53483L,53484L,
53485L,53486L,53487L,53488L,53489L,53490L,53491L,53492L,53493L,53494L,
53495L,53496L,53497L,53498L,53499L,53500L,53501L,53502L,53503L,53504L,
53505L,53506L,53507L,53508L,53509L,53510L,53511L,53512L,53513L,53514L,
53515L,53516L,53517L,53518L,53519L,53520L,53521L,53522L,53523L,53524L,
53525L,53526L,53527L,53528L,53529L,53530L,53531L,53532L,53533L,53534L,
53535L,53536L,53537L,53538L,53539L,53540L,53541L,53542L,53543L,53544L,
53545L,53546L,53547L,53548L,53549L,53550L,53551L,53552L,53553L,53554L,
53555L,53556L,53557L,53558L,53559L,53560L,53561L,53562L,53563L,53564L,
53565L,53566L,53567L,53568L,53569L,53570L,53571L,53572L,53573L,53574L,
53575L,53576L,53577L,53578L,53579L,53580L,53581L,53582L,53583L,53584L,
53585L,53586L,53587L,53588L,53589L,53590L,53591L,53592L,53593L,53594L,
53595L,53596L,53597L,53598L,53599L,53600L,53601L,53602L,53603L,53604L,
53605L,53606L,53607L,53608L,53609L,53610L,53611L,53612L,53613L,53614L,
53615L,53616L,53617L,53618L,53619L,53620L,53621L,53622L,53623L,53624L,
53625L,53626L,53627L,53628L,53629L,53630L,53631L,53632L,53633L,53634L,
53635L,53636L,53637L,53638L,53639L,53640L,53641L,53642L,53643L,53644L,
53645L,53646L,53647L,53648L,53649L,53650L,53651L,53652L,53653L,53654L,
53655L,53656L,53657L,53658L,53659L,53660L,53661L,53662L,53663L,53664L,
53665L,53666L,53667L,53668L,53669L,53670L,53671L,53672L,53673L,53674L,
53675L,53676L,53677L,53678L,53679L,53680L,53681L,53682L,53683L,53684L,
53685L,53686L,53687L,53688L,53689L,53690L,53691L,53692L,53693L,53694L,
53695L,53696L,53697L,53698L,53699L,53700L,53701L,53702L,53703L,53704L,
53705L,53706L,53707L,53708L,53709L,53710L,53711L,53712L,53713L,53714L,
53715L,53716L,53717L,53718L,53719L,53720L,53721L,53722L,53723L,53724L,
53725L,53726L,53727L,53728L,53729L,53730L,53731L,53732L,53733L,53734L,
53735L,53736L,53737L,53738L,53739L,53740L,53741L,53742L,53743L,53744L,
53745L,53746L,53747L,53748L,53749L,53750L,53751L,53752L,53753L,53754L,
53755L,53756L,53757L,53758L,53759L,53760L,53761L,53762L,53763L,53764L,
53765L,53766L,53767L,53768L,53769L,53770L,53771L,53772L,53773L,53774L,
53775L,53776L,53777L,53778L,53779L,53780L,53781L,53782L,53783L,53784L,
53785L,53786L,53787L,53788L,53789L,53790L,53791L,53792L,53793L,53794L,
53795L,53796L,53797L,53798L,53799L,53800L,53801L,53802L,53803L,53804L,
53805L,53806L,53807L,53808L,53809L,53810L,53811L,53812L,53813L,53814L,
53815L,53816L,53817L,53818L,53819L,53820L,53821L,53822L,53823L,53824L,
53825L,53826L,53827L,53828L,53829L,53830L,53831L,53832L,53833L,53834L,
53835L,53836L,53837L,53838L,53839L,53840L,53841L,53842L,53843L,53844L,
53845L,53846L,53847L,53848L,53849L,53850L,53851L,53852L,53853L,53854L,
53855L,53856L,53857L,53858L,53859L,53860L,53861L,53862L,53863L,53864L,
53865L,53866L,53867L,53868L,53869L,53870L,53871L,53872L,53873L,53874L,
53875L,53876L,53877L,53878L,53879L,53880L,53881L,53882L,53883L,53884L,
53885L,53886L,53887L,53888L,53889L,53890L,53891L,53892L,53893L,53894L,
53895L,53896L,53897L,53898L,53899L,53900L,53901L,53902L,53903L,53904L,
53905L,53906L,53907L,53908L,53909L,53910L,53911L,53912L,53913L,53914L,
53915L,53916L,53917L,53918L,53919L,53920L,53921L,53922L,53923L,53924L,
53925L,53926L,53927L,53928L,53929L,53930L,53931L,53932L,53933L,53934L,
53935L,53936L,53937L,53938L,53939L,53940L,53941L,53942L,53943L,53944L,
53945L,53946L,53947L,53948L,53949L,53950L,53951L,53952L,53953L,53954L,
53955L,53956L,53957L,53958L,53959L,53960L,53961L,53962L,53963L,53964L,
53965L,53966L,53967L,53968L,53969L,53970L,53971L,53972L,53973L,53974L,
53975L,53976L,53977L,53978L,53979L,53980L,53981L,53982L,53983L,53984L,
53985L,53986L,53987L,53988L,53989L,53990L,53991L,53992L,53993L,53994L,
53995L,53996L,53997L,53998L,53999L,54000L,54001L,54002L,54003L,54004L,
54005L,54006L,54007L,54008L,54009L,54010L,54011L,54012L,54013L,54014L,
54015L,54016L,54017L,54018L,54019L,54020L,54021L,54022L,54023L,54024L,
54025L,54026L,54027L,54028L,54029L,54030L,54031L,54032L,54033L,54034L,
54035L,54036L,54037L,54038L,54039L,54040L,54041L,54042L,54043L,54044L,
54045L,54046L,54047L,54048L,54049L,54050L,54051L,54052L,54053L,54054L,
54055L,54056L,54057L,54058L,54059L,54060L,54061L,54062L,54063L,54064L,
54065L,54066L,54067L,54068L,54069L,54070L,54071L,54072L,54073L,54074L,
54075L,54076L,54077L,54078L,54079L,54080L,54081L,54082L,54083L,54084L,
54085L,54086L,54087L,54088L,54089L,54090L,54091L,54092L,54093L,54094L,
54095L,54096L,54097L,54098L,54099L,54100L,54101L,54102L,54103L,54104L,
54105L,54106L,54107L,54108L,54109L,54110L,54111L,54112L,54113L,54114L,
54115L,54116L,54117L,54118L,54119L,54120L,54121L,54122L,54123L,54124L,
54125L,54126L,54127L,54128L,54129L,54130L,54131L,54132L,54133L,54134L,
54135L,54136L,54137L,54138L,54139L,54140L,54141L,54142L,54143L,54144L,
54145L,54146L,54147L,54148L,54149L,54150L,54151L,54152L,54153L,54154L,
54155L,54156L,54157L,54158L,54159L,54160L,54161L,54162L,54163L,54164L,
54165L,54166L,54167L,54168L,54169L,54170L,54171L,54172L,54173L,54174L,
54175L,54176L,54177L,54178L,54179L,54180L,54181L,54182L,54183L,54184L,
54185L,54186L,54187L,54188L,54189L,54190L,54191L,54192L,54193L,54194L,
54195L,54196L,54197L,54198L,54199L,54200L,54201L,54202L,54203L,54204L,
54205L,54206L,54207L,54208L,54209L,54210L,54211L,54212L,54213L,54214L,
54215L,54216L,54217L,54218L,54219L,54220L,54221L,54222L,54223L,54224L,
54225L,54226L,54227L,54228L,54229L,54230L,54231L,54232L,54233L,54234L,
54235L,54236L,54237L,54238L,54239L,54240L,54241L,54242L,54243L,54244L,
54245L,54246L,54247L,54248L,54249L,54250L,54251L,54252L,54253L,54254L,
54255L,54256L,54257L,54258L,54259L,54260L,54261L,54262L,54263L,54264L,
54265L,54266L,54267L,54268L,54269L,54270L,54271L,54272L,54273L,54274L,
54275L,54276L,54277L,54278L,54279L,54280L,54281L,54282L,54283L,54284L,
54285L,54286L,54287L,54288L,54289L,54290L,54291L,54292L,54293L,54294L,
54295L,54296L,54297L,54298L,54299L,54300L,54301L,54302L,54303L,54304L,
54305L,54306L,54307L,54308L,54309L,54310L,54311L,54312L,54313L,54314L,
54315L,54316L,54317L,54318L,54319L,54320L,54321L,54322L,54323L,54324L,
54325L,54326L,54327L,54328L,54329L,54330L,54331L,54332L,54333L,54334L,
54335L,54336L,54337L,54338L,54339L,54340L,54341L,54342L,54343L,54344L,
54345L,54346L,54347L,54348L,54349L,54350L,54351L,54352L,54353L,54354L,
54355L,54356L,54357L,54358L,54359L,54360L,54361L,54362L,54363L,54364L,
54365L,54366L,54367L,54368L,54369L,54370L,54371L,54372L,54373L,54374L,
54375L,54376L,54377L,54378L,54379L,54380L,54381L,54382L,54383L,54384L,
54385L,54386L,54387L,54388L,54389L,54390L,54391L,54392L,54393L,54394L,
54395L,54396L,54397L,54398L,54399L,54400L,54401L,54402L,54403L,54404L,
54405L,54406L,54407L,54408L,54409L,54410L,54411L,54412L,54413L,54414L,
54415L,54416L,54417L,54418L,54419L,54420L,54421L,54422L,54423L,54424L,
54425L,54426L,54427L,54428L,54429L,54430L,54431L,54432L,54433L,54434L,
54435L,54436L,54437L,54438L,54439L,54440L,54441L,54442L,54443L,54444L,
54445L,54446L,54447L,54448L,54449L,54450L,54451L,54452L,54453L,54454L,
54455L,54456L,54457L,54458L,54459L,54460L,54461L,54462L,54463L,54464L,
54465L,54466L,54467L,54468L,54469L,54470L,54471L,54472L,54473L,54474L,
54475L,54476L,54477L,54478L,54479L,54480L,54481L,54482L,54483L,54484L,
54485L,54486L,54487L,54488L,54489L,54490L,54491L,54492L,54493L,54494L,
54495L,54496L,54497L,54498L,54499L,54500L,54501L,54502L,54503L,54504L,
54505L,54506L,54507L,54508L,54509L,54510L,54511L,54512L,54513L,54514L,
54515L,54516L,54517L,54518L,54519L,54520L,54521L,54522L,54523L,54524L,
54525L,54526L,54527L,54528L,54529L,54530L,54531L,54532L,54533L,54534L,
54535L,54536L,54537L,54538L,54539L,54540L,54541L,54542L,54543L,54544L,
54545L,54546L,54547L,54548L,54549L,54550L,54551L,54552L,54553L,54554L,
54555L,54556L,54557L,54558L,54559L,54560L,54561L,54562L,54563L,54564L,
54565L,54566L,54567L,54568L,54569L,54570L,54571L,54572L,54573L,54574L,
54575L,54576L,54577L,54578L,54579L,54580L,54581L,54582L,54583L,54584L,
54585L,54586L,54587L,54588L,54589L,54590L,54591L,54592L,54593L,54594L,
54595L,54596L,54597L,54598L,54599L,54600L,54601L,54602L,54603L,54604L,
54605L,54606L,54607L,54608L,54609L,54610L,54611L,54612L,54613L,54614L,
54615L,54616L,54617L,54618L,54619L,54620L,54621L,54622L,54623L,54624L,
54625L,54626L,54627L,54628L,54629L,54630L,54631L,54632L,54633L,54634L,
54635L,54636L,54637L,54638L,54639L,54640L,54641L,54642L,54643L,54644L,
54645L,54646L,54647L,54648L,54649L,54650L,54651L,54652L,54653L,54654L,
54655L,54656L,54657L,54658L,54659L,54660L,54661L,54662L,54663L,54664L,
54665L,54666L,54667L,54668L,54669L,54670L,54671L,54672L,54673L,54674L,
54675L,54676L,54677L,54678L,54679L,54680L,54681L,54682L,54683L,54684L,
54685L,54686L,54687L,54688L,54689L,54690L,54691L,54692L,54693L,54694L,
54695L,54696L,54697L,54698L,54699L,54700L,54701L,54702L,54703L,54704L,
54705L,54706L,54707L,54708L,54709L,54710L,54711L,54712L,54713L,54714L,
54715L,54716L,54717L,54718L,54719L,54720L,54721L,54722L,54723L,54724L,
54725L,54726L,54727L,54728L,54729L,54730L,54731L,54732L,54733L,54734L,
54735L,54736L,54737L,54738L,54739L,54740L,54741L,54742L,54743L,54744L,
54745L,54746L,54747L,54748L,54749L,54750L,54751L,54752L,54753L,54754L,
54755L,54756L,54757L,54758L,54759L,54760L,54761L,54762L,54763L,54764L,
54765L,54766L,54767L,54768L,54769L,54770L,54771L,54772L,54773L,54774L,
54775L,54776L,54777L,54778L,54779L,54780L,54781L,54782L,54783L,54784L,
54785L,54786L,54787L,54788L,54789L,54790L,54791L,54792L,54793L,54794L,
54795L,54796L,54797L,54798L,54799L,54800L,54801L,54802L,54803L,54804L,
54805L,54806L,54807L,54808L,54809L,54810L,54811L,54812L,54813L,54814L,
54815L,54816L,54817L,54818L,54819L,54820L,54821L,54822L,54823L,54824L,
54825L,54826L,54827L,54828L,54829L,54830L,54831L,54832L,54833L,54834L,
54835L,54836L,54837L,54838L,54839L,54840L,54841L,54842L,54843L,54844L,
54845L,54846L,54847L,54848L,54849L,54850L,54851L,54852L,54853L,54854L,
54855L,54856L,54857L,54858L,54859L,54860L,54861L,54862L,54863L,54864L,
54865L,54866L,54867L,54868L,54869L,54870L,54871L,54872L,54873L,54874L,
54875L,54876L,54877L,54878L,54879L,54880L,54881L,54882L,54883L,54884L,
54885L,54886L,54887L,54888L,54889L,54890L,54891L,54892L,54893L,54894L,
54895L,54896L,54897L,54898L,54899L,54900L,54901L,54902L,54903L,54904L,
54905L,54906L,54907L,54908L,54909L,54910L,54911L,54912L,54913L,54914L,
54915L,54916L,54917L,54918L,54919L,54920L,54921L,54922L,54923L,54924L,
54925L,54926L,54927L,54928L,54929L,54930L,54931L,54932L,54933L,54934L,
54935L,54936L,54937L,54938L,54939L,54940L,54941L,54942L,54943L,54944L,
54945L,54946L,54947L,54948L,54949L,54950L,54951L,54952L,54953L,54954L,
54955L,54956L,54957L,54958L,54959L,54960L,54961L,54962L,54963L,54964L,
54965L,54966L,54967L,54968L,54969L,54970L,54971L,54972L,54973L,54974L,
54975L,54976L,54977L,54978L,54979L,54980L,54981L,54982L,54983L,54984L,
54985L,54986L,54987L,54988L,54989L,54990L,54991L,54992L,54993L,54994L,
54995L,54996L,54997L,54998L,54999L,55000L,55001L,55002L,55003L,55004L,
55005L,55006L,55007L,55008L,55009L,55010L,55011L,55012L,55013L,55014L,
55015L,55016L,55017L,55018L,55019L,55020L,55021L,55022L,55023L,55024L,
55025L,55026L,55027L,55028L,55029L,55030L,55031L,55032L,55033L,55034L,
55035L,55036L,55037L,55038L,55039L,55040L,55041L,55042L,55043L,55044L,
55045L,55046L,55047L,55048L,55049L,55050L,55051L,55052L,55053L,55054L,
55055L,55056L,55057L,55058L,55059L,55060L,55061L,55062L,55063L,55064L,
55065L,55066L,55067L,55068L,55069L,55070L,55071L,55072L,55073L,55074L,
55075L,55076L,55077L,55078L,55079L,55080L,55081L,55082L,55083L,55084L,
55085L,55086L,55087L,55088L,55089L,55090L,55091L,55092L,55093L,55094L,
55095L,55096L,55097L,55098L,55099L,55100L,55101L,55102L,55103L,55104L,
55105L,55106L,55107L,55108L,55109L,55110L,55111L,55112L,55113L,55114L,
55115L,55116L,55117L,55118L,55119L,55120L,55121L,55122L,55123L,55124L,
55125L,55126L,55127L,55128L,55129L,55130L,55131L,55132L,55133L,55134L,
55135L,55136L,55137L,55138L,55139L,55140L,55141L,55142L,55143L,55144L,
55145L,55146L,55147L,55148L,55149L,55150L,55151L,55152L,55153L,55154L,
55155L,55156L,55157L,55158L,55159L,55160L,55161L,55162L,55163L,55164L,
55165L,55166L,55167L,55168L,55169L,55170L,55171L,55172L,55173L,55174L,
55175L,55176L,55177L,55178L,55179L,55180L,55181L,55182L,55183L,55184L,
55185L,55186L,55187L,55188L,55189L,55190L,55191L,55192L,55193L,55194L,
55195L,55196L,55197L,55198L,55199L,55200L,55201L,55202L,55203L,55204L,
55205L,55206L,55207L,55208L,55209L,55210L,55211L,55212L,55213L,55214L,
55215L,55216L,55217L,55218L,55219L,55220L,55221L,55222L,55223L,55224L,
55225L,55226L,55227L,55228L,55229L,55230L,55231L,55232L,55233L,55234L,
55235L,55236L,55237L,55238L,55239L,55240L,55241L,55242L,55243L,55244L,
55245L,55246L,55247L,55248L,55249L,55250L,55251L,55252L,55253L,55254L,
55255L,55256L,55257L,55258L,55259L,55260L,55261L,55262L,55263L,55264L,
55265L,55266L,55267L,55268L,55269L,55270L,55271L,55272L,55273L,55274L,
55275L,55276L,55277L,55278L,55279L,55280L,55281L,55282L,55283L,55284L,
55285L,55286L,55287L,55288L,55289L,55290L,55291L,55292L,55293L,55294L,
55295L,55296L,55297L,55298L,55299L,55300L,55301L,55302L,55303L,55304L,
55305L,55306L,55307L,55308L,55309L,55310L,55311L,55312L,55313L,55314L,
55315L,55316L,55317L,55318L,55319L,55320L,55321L,55322L,55323L,55324L,
55325L,55326L,55327L,55328L,55329L,55330L,55331L,55332L,55333L,55334L,
55335L,55336L,55337L,55338L,55339L,55340L,55341L,55342L,55343L,55344L,
55345L,55346L,55347L,55348L,55349L,55350L,55351L,55352L,55353L,55354L,
55355L,55356L,55357L,55358L,55359L,55360L,55361L,55362L,55363L,55364L,
55365L,55366L,55367L,55368L,55369L,55370L,55371L,55372L,55373L,55374L,
55375L,55376L,55377L,55378L,55379L,55380L,55381L,55382L,55383L,55384L,
55385L,55386L,55387L,55388L,55389L,55390L,55391L,55392L,55393L,55394L,
55395L,55396L,55397L,55398L,55399L,55400L,55401L,55402L,55403L,55404L,
55405L,55406L,55407L,55408L,55409L,55410L,55411L,55412L,55413L,55414L,
55415L,55416L,55417L,55418L,55419L,55420L,55421L,55422L,55423L,55424L,
55425L,55426L,55427L,55428L,55429L,55430L,55431L,55432L,55433L,55434L,
55435L,55436L,55437L,55438L,55439L,55440L,55441L,55442L,55443L,55444L,
55445L,55446L,55447L,55448L,55449L,55450L,55451L,55452L,55453L,55454L,
55455L,55456L,55457L,55458L,55459L,55460L,55461L,55462L,55463L,55464L,
55465L,55466L,55467L,55468L,55469L,55470L,55471L,55472L,55473L,55474L,
55475L,55476L,55477L,55478L,55479L,55480L,55481L,55482L,55483L,55484L,
55485L,55486L,55487L,55488L,55489L,55490L,55491L,55492L,55493L,55494L,
55495L,55496L,55497L,55498L,55499L,55500L,55501L,55502L,55503L,55504L,
55505L,55506L,55507L,55508L,55509L,55510L,55511L,55512L,55513L,55514L,
55515L,55516L,55517L,55518L,55519L,55520L,55521L,55522L,55523L,55524L,
55525L,55526L,55527L,55528L,55529L,55530L,55531L,55532L,55533L,55534L,
55535L,55536L,55537L,55538L,55539L,55540L,55541L,55542L,55543L,55544L,
55545L,55546L,55547L,55548L,55549L,55550L,55551L,55552L,55553L,55554L,
55555L,55556L,55557L,55558L,55559L,55560L,55561L,55562L,55563L,55564L,
55565L,55566L,55567L,55568L,55569L,55570L,55571L,55572L,55573L,55574L,
55575L,55576L,55577L,55578L,55579L,55580L,55581L,55582L,55583L,55584L,
55585L,55586L,55587L,55588L,55589L,55590L,55591L,55592L,55593L,55594L,
55595L,55596L,55597L,55598L,55599L,55600L,55601L,55602L,55603L,55604L,
55605L,55606L,55607L,55608L,55609L,55610L,55611L,55612L,55613L,55614L,
55615L,55616L,55617L,55618L,55619L,55620L,55621L,55622L,55623L,55624L,
55625L,55626L,55627L,55628L,55629L,55630L,55631L,55632L,55633L,55634L,
55635L,55636L,55637L,55638L,55639L,55640L,55641L,55642L,55643L,55644L,
55645L,55646L,55647L,55648L,55649L,55650L,55651L,55652L,55653L,55654L,
55655L,55656L,55657L,55658L,55659L,55660L,55661L,55662L,55663L,55664L,
55665L,55666L,55667L,55668L,55669L,55670L,55671L,55672L,55673L,55674L,
55675L,55676L,55677L,55678L,55679L,55680L,55681L,55682L,55683L,55684L,
55685L,55686L,55687L,55688L,55689L,55690L,55691L,55692L,55693L,55694L,
55695L,55696L,55697L,55698L,55699L,55700L,55701L,55702L,55703L,55704L,
55705L,55706L,55707L,55708L,55709L,55710L,55711L,55712L,55713L,55714L,
55715L,55716L,55717L,55718L,55719L,55720L,55721L,55722L,55723L,55724L,
55725L,55726L,55727L,55728L,55729L,55730L,55731L,55732L,55733L,55734L,
55735L,55736L,55737L,55738L,55739L,55740L,55741L,55742L,55743L,55744L,
55745L,55746L,55747L,55748L,55749L,55750L,55751L,55752L,55753L,55754L,
55755L,55756L,55757L,55758L,55759L,55760L,55761L,55762L,55763L,55764L,
55765L,55766L,55767L,55768L,55769L,55770L,55771L,55772L,55773L,55774L,
55775L,55776L,55777L,55778L,55779L,55780L,55781L,55782L,55783L,55784L,
55785L,55786L,55787L,55788L,55789L,55790L,55791L,55792L,55793L,55794L,
55795L,55796L,55797L,55798L,55799L,55800L,55801L,55802L,55803L,55804L,
55805L,55806L,55807L,55808L,55809L,55810L,55811L,55812L,55813L,55814L,
55815L,55816L,55817L,55818L,55819L,55820L,55821L,55822L,55823L,55824L,
55825L,55826L,55827L,55828L,55829L,55830L,55831L,55832L,55833L,55834L,
55835L,55836L,55837L,55838L,55839L,55840L,55841L,55842L,55843L,55844L,
55845L,55846L,55847L,55848L,55849L,55850L,55851L,55852L,55853L,55854L,
55855L,55856L,55857L,55858L,55859L,55860L,55861L,55862L,55863L,55864L,
55865L,55866L,55867L,55868L,55869L,55870L,55871L,55872L,55873L,55874L,
55875L,55876L,55877L,55878L,55879L,55880L,55881L,55882L,55883L,55884L,
55885L,55886L,55887L,55888L,55889L,55890L,55891L,55892L,55893L,55894L,
55895L,55896L,55897L,55898L,55899L,55900L,55901L,55902L,55903L,55904L,
55905L,55906L,55907L,55908L,55909L,55910L,55911L,55912L,55913L,55914L,
55915L,55916L,55917L,55918L,55919L,55920L,55921L,55922L,55923L,55924L,
55925L,55926L,55927L,55928L,55929L,55930L,55931L,55932L,55933L,55934L,
55935L,55936L,55937L,55938L,55939L,55940L,55941L,55942L,55943L,55944L,
55945L,55946L,55947L,55948L,55949L,55950L,55951L,55952L,55953L,55954L,
55955L,55956L,55957L,55958L,55959L,55960L,55961L,55962L,55963L,55964L,
55965L,55966L,55967L,55968L,55969L,55970L,55971L,55972L,55973L,55974L,
55975L,55976L,55977L,55978L,55979L,55980L,55981L,55982L,55983L,55984L,
55985L,55986L,55987L,55988L,55989L,55990L,55991L,55992L,55993L,55994L,
55995L,55996L,55997L,55998L,55999L,56000L,56001L,56002L,56003L,56004L,
56005L,56006L,56007L,56008L,56009L,56010L,56011L,56012L,56013L,56014L,
56015L,56016L,56017L,56018L,56019L,56020L,56021L,56022L,56023L,56024L,
56025L,56026L,56027L,56028L,56029L,56030L,56031L,56032L,56033L,56034L,
56035L,56036L,56037L,56038L,56039L,56040L,56041L,56042L,56043L,56044L,
56045L,56046L,56047L,56048L,56049L,56050L,56051L,56052L,56053L,56054L,
56055L,56056L,56057L,56058L,56059L,56060L,56061L,56062L,56063L,56064L,
56065L,56066L,56067L,56068L,56069L,56070L,56071L,56072L,56073L,56074L,
56075L,56076L,56077L,56078L,56079L,56080L,56081L,56082L,56083L,56084L,
56085L,56086L,56087L,56088L,56089L,56090L,56091L,56092L,56093L,56094L,
56095L,56096L,56097L,56098L,56099L,56100L,56101L,56102L,56103L,56104L,
56105L,56106L,56107L,56108L,56109L,56110L,56111L,56112L,56113L,56114L,
56115L,56116L,56117L,56118L,56119L,56120L,56121L,56122L,56123L,56124L,
56125L,56126L,56127L,56128L,56129L,56130L,56131L,56132L,56133L,56134L,
56135L,56136L,56137L,56138L,56139L,56140L,56141L,56142L,56143L,56144L,
56145L,56146L,56147L,56148L,56149L,56150L,56151L,56152L,56153L,56154L,
56155L,56156L,56157L,56158L,56159L,56160L,56161L,56162L,56163L,56164L,
56165L,56166L,56167L,56168L,56169L,56170L,56171L,56172L,56173L,56174L,
56175L,56176L,56177L,56178L,56179L,56180L,56181L,56182L,56183L,56184L,
56185L,56186L,56187L,56188L,56189L,56190L,56191L,56192L,56193L,56194L,
56195L,56196L,56197L,56198L,56199L,56200L,56201L,56202L,56203L,56204L,
56205L,56206L,56207L,56208L,56209L,56210L,56211L,56212L,56213L,56214L,
56215L,56216L,56217L,56218L,56219L,56220L,56221L,56222L,56223L,56224L,
56225L,56226L,56227L,56228L,56229L,56230L,56231L,56232L,56233L,56234L,
56235L,56236L,56237L,56238L,56239L,56240L,56241L,56242L,56243L,56244L,
56245L,56246L,56247L,56248L,56249L,56250L,56251L,56252L,56253L,56254L,
56255L,56256L,56257L,56258L,56259L,56260L,56261L,56262L,56263L,56264L,
56265L,56266L,56267L,56268L,56269L,56270L,56271L,56272L,56273L,56274L,
56275L,56276L,56277L,56278L,56279L,56280L,56281L,56282L,56283L,56284L,
56285L,56286L,56287L,56288L,56289L,56290L,56291L,56292L,56293L,56294L,
56295L,56296L,56297L,56298L,56299L,56300L,56301L,56302L,56303L,56304L,
56305L,56306L,56307L,56308L,56309L,56310L,56311L,56312L,56313L,56314L,
56315L,56316L,56317L,56318L,56319L,56320L,56321L,56322L,56323L,56324L,
56325L,56326L,56327L,56328L,56329L,56330L,56331L,56332L,56333L,56334L,
56335L,56336L,56337L,56338L,56339L,56340L,56341L,56342L,56343L,56344L,
56345L,56346L,56347L,56348L,56349L,56350L,56351L,56352L,56353L,56354L,
56355L,56356L,56357L,56358L,56359L,56360L,56361L,56362L,56363L,56364L,
56365L,56366L,56367L,56368L,56369L,56370L,56371L,56372L,56373L,56374L,
56375L,56376L,56377L,56378L,56379L,56380L,56381L,56382L,56383L,56384L,
56385L,56386L,56387L,56388L,56389L,56390L,56391L,56392L,56393L,56394L,
56395L,56396L,56397L,56398L,56399L,56400L,56401L,56402L,56403L,56404L,
56405L,56406L,56407L,56408L,56409L,56410L,56411L,56412L,56413L,56414L,
56415L,56416L,56417L,56418L,56419L,56420L,56421L,56422L,56423L,56424L,
56425L,56426L,56427L,56428L,56429L,56430L,56431L,56432L,56433L,56434L,
56435L,56436L,56437L,56438L,56439L,56440L,56441L,56442L,56443L,56444L,
56445L,56446L,56447L,56448L,56449L,56450L,56451L,56452L,56453L,56454L,
56455L,56456L,56457L,56458L,56459L,56460L,56461L,56462L,56463L,56464L,
56465L,56466L,56467L,56468L,56469L,56470L,56471L,56472L,56473L,56474L,
56475L,56476L,56477L,56478L,56479L,56480L,56481L,56482L,56483L,56484L,
56485L,56486L,56487L,56488L,56489L,56490L,56491L,56492L,56493L,56494L,
56495L,56496L,56497L,56498L,56499L,56500L,56501L,56502L,56503L,56504L,
56505L,56506L,56507L,56508L,56509L,56510L,56511L,56512L,56513L,56514L,
56515L,56516L,56517L,56518L,56519L,56520L,56521L,56522L,56523L,56524L,
56525L,56526L,56527L,56528L,56529L,56530L,56531L,56532L,56533L,56534L,
56535L,56536L,56537L,56538L,56539L,56540L,56541L,56542L,56543L,56544L,
56545L,56546L,56547L,56548L,56549L,56550L,56551L,56552L,56553L,56554L,
56555L,56556L,56557L,56558L,56559L,56560L,56561L,56562L,56563L,56564L,
56565L,56566L,56567L,56568L,56569L,56570L,56571L,56572L,56573L,56574L,
56575L,56576L,56577L,56578L,56579L,56580L,56581L,56582L,56583L,56584L,
56585L,56586L,56587L,56588L,56589L,56590L,56591L,56592L,56593L,56594L,
56595L,56596L,56597L,56598L,56599L,56600L,56601L,56602L,56603L,56604L,
56605L,56606L,56607L,56608L,56609L,56610L,56611L,56612L,56613L,56614L,
56615L,56616L,56617L,56618L,56619L,56620L,56621L,56622L,56623L,56624L,
56625L,56626L,56627L,56628L,56629L,56630L,56631L,56632L,56633L,56634L,
56635L,56636L,56637L,56638L,56639L,56640L,56641L,56642L,56643L,56644L,
56645L,56646L,56647L,56648L,56649L,56650L,56651L,56652L,56653L,56654L,
56655L,56656L,56657L,56658L,56659L,56660L,56661L,56662L,56663L,56664L,
56665L,56666L,56667L,56668L,56669L,56670L,56671L,56672L,56673L,56674L,
56675L,56676L,56677L,56678L,56679L,56680L,56681L,56682L,56683L,56684L,
56685L,56686L,56687L,56688L,56689L,56690L,56691L,56692L,56693L,56694L,
56695L,56696L,56697L,56698L,56699L,56700L,56701L,56702L,56703L,56704L,
56705L,56706L,56707L,56708L,56709L,56710L,56711L,56712L,56713L,56714L,
56715L,56716L,56717L,56718L,56719L,56720L,56721L,56722L,56723L,56724L,
56725L,56726L,56727L,56728L,56729L,56730L,56731L,56732L,56733L,56734L,
56735L,56736L,56737L,56738L,56739L,56740L,56741L,56742L,56743L,56744L,
56745L,56746L,56747L,56748L,56749L,56750L,56751L,56752L,56753L,56754L,
56755L,56756L,56757L,56758L,56759L,56760L,56761L,56762L,56763L,56764L,
56765L,56766L,56767L,56768L,56769L,56770L,56771L,56772L,56773L,56774L,
56775L,56776L,56777L,56778L,56779L,56780L,56781L,56782L,56783L,56784L,
56785L,56786L,56787L,56788L,56789L,56790L,56791L,56792L,56793L,56794L,
56795L,56796L,56797L,56798L,56799L,56800L,56801L,56802L,56803L,56804L,
56805L,56806L,56807L,56808L,56809L,56810L,56811L,56812L,56813L,56814L,
56815L,56816L,56817L,56818L,56819L,56820L,56821L,56822L,56823L,56824L,
56825L,56826L,56827L,56828L,56829L,56830L,56831L,56832L,56833L,56834L,
56835L,56836L,56837L,56838L,56839L,56840L,56841L,56842L,56843L,56844L,
56845L,56846L,56847L,56848L,56849L,56850L,56851L,56852L,56853L,56854L,
56855L,56856L,56857L,56858L,56859L,56860L,56861L,56862L,56863L,56864L,
56865L,56866L,56867L,56868L,56869L,56870L,56871L,56872L,56873L,56874L,
56875L,56876L,56877L,56878L,56879L,56880L,56881L,56882L,56883L,56884L,
56885L,56886L,56887L,56888L,56889L,56890L,56891L,56892L,56893L,56894L,
56895L,56896L,56897L,56898L,56899L,56900L,56901L,56902L,56903L,56904L,
56905L,56906L,56907L,56908L,56909L,56910L,56911L,56912L,56913L,56914L,
56915L,56916L,56917L,56918L,56919L,56920L,56921L,56922L,56923L,56924L,
56925L,56926L,56927L,56928L,56929L,56930L,56931L,56932L,56933L,56934L,
56935L,56936L,56937L,56938L,56939L,56940L,56941L,56942L,56943L,56944L,
56945L,56946L,56947L,56948L,56949L,56950L,56951L,56952L,56953L,56954L,
56955L,56956L,56957L,56958L,56959L,56960L,56961L,56962L,56963L,56964L,
56965L,56966L,56967L,56968L,56969L,56970L,56971L,56972L,56973L,56974L,
56975L,56976L,56977L,56978L,56979L,56980L,56981L,56982L,56983L,56984L,
56985L,56986L,56987L,56988L,56989L,56990L,56991L,56992L,56993L,56994L,
56995L,56996L,56997L,56998L,56999L,57000L,57001L,57002L,57003L,57004L,
57005L,57006L,57007L,57008L,57009L,57010L,57011L,57012L,57013L,57014L,
57015L,57016L,57017L,57018L,57019L,57020L,57021L,57022L,57023L,57024L,
57025L,57026L,57027L,57028L,57029L,57030L,57031L,57032L,57033L,57034L,
57035L,57036L,57037L,57038L,57039L,57040L,57041L,57042L,57043L,57044L,
57045L,57046L,57047L,57048L,57049L,57050L,57051L,57052L,57053L,57054L,
57055L,57056L,57057L,57058L,57059L,57060L,57061L,57062L,57063L,57064L,
57065L,57066L,57067L,57068L,57069L,57070L,57071L,57072L,57073L,57074L,
57075L,57076L,57077L,57078L,57079L,57080L,57081L,57082L,57083L,57084L,
57085L,57086L,57087L,57088L,57089L,57090L,57091L,57092L,57093L,57094L,
57095L,57096L,57097L,57098L,57099L,57100L,57101L,57102L,57103L,57104L,
57105L,57106L,57107L,57108L,57109L,57110L,57111L,57112L,57113L,57114L,
57115L,57116L,57117L,57118L,57119L,57120L,57121L,57122L,57123L,57124L,
57125L,57126L,57127L,57128L,57129L,57130L,57131L,57132L,57133L,57134L,
57135L,57136L,57137L,57138L,57139L,57140L,57141L,57142L,57143L,57144L,
57145L,57146L,57147L,57148L,57149L,57150L,57151L,57152L,57153L,57154L,
57155L,57156L,57157L,57158L,57159L,57160L,57161L,57162L,57163L,57164L,
57165L,57166L,57167L,57168L,57169L,57170L,57171L,57172L,57173L,57174L,
57175L,57176L,57177L,57178L,57179L,57180L,57181L,57182L,57183L,57184L,
57185L,57186L,57187L,57188L,57189L,57190L,57191L,57192L,57193L,57194L,
57195L,57196L,57197L,57198L,57199L,57200L,57201L,57202L,57203L,57204L,
57205L,57206L,57207L,57208L,57209L,57210L,57211L,57212L,57213L,57214L,
57215L,57216L,57217L,57218L,57219L,57220L,57221L,57222L,57223L,57224L,
57225L,57226L,57227L,57228L,57229L,57230L,57231L,57232L,57233L,57234L,
57235L,57236L,57237L,57238L,57239L,57240L,57241L,57242L,57243L,57244L,
57245L,57246L,57247L,57248L,57249L,57250L,57251L,57252L,57253L,57254L,
57255L,57256L,57257L,57258L,57259L,57260L,57261L,57262L,57263L,57264L,
57265L,57266L,57267L,57268L,57269L,57270L,57271L,57272L,57273L,57274L,
57275L,57276L,57277L,57278L,57279L,57280L,57281L,57282L,57283L,57284L,
57285L,57286L,57287L,57288L,57289L,57290L,57291L,57292L,57293L,57294L,
57295L,57296L,57297L,57298L,57299L,57300L,57301L,57302L,57303L,57304L,
57305L,57306L,57307L,57308L,57309L,57310L,57311L,57312L,57313L,57314L,
57315L,57316L,57317L,57318L,57319L,57320L,57321L,57322L,57323L,57324L,
57325L,57326L,57327L,57328L,57329L,57330L,57331L,57332L,57333L,57334L,
57335L,57336L,57337L,57338L,57339L,57340L,57341L,57342L,57343L,57344L,
57345L,57346L,57347L,57348L,57349L,57350L,57351L,57352L,57353L,57354L,
57355L,57356L,57357L,57358L,57359L,57360L,57361L,57362L,57363L,57364L,
57365L,57366L,57367L,57368L,57369L,57370L,57371L,57372L,57373L,57374L,
57375L,57376L,57377L,57378L,57379L,57380L,57381L,57382L,57383L,57384L,
57385L,57386L,57387L,57388L,57389L,57390L,57391L,57392L,57393L,57394L,
57395L,57396L,57397L,57398L,57399L,57400L,57401L,57402L,57403L,57404L,
57405L,57406L,57407L,57408L,57409L,57410L,57411L,57412L,57413L,57414L,
57415L,57416L,57417L,57418L,57419L,57420L,57421L,57422L,57423L,57424L,
57425L,57426L,57427L,57428L,57429L,57430L,57431L,57432L,57433L,57434L,
57435L,57436L,57437L,57438L,57439L,57440L,57441L,57442L,57443L,57444L,
57445L,57446L,57447L,57448L,57449L,57450L,57451L,57452L,57453L,57454L,
57455L,57456L,57457L,57458L,57459L,57460L,57461L,57462L,57463L,57464L,
57465L,57466L,57467L,57468L,57469L,57470L,57471L,57472L,57473L,57474L,
57475L,57476L,57477L,57478L,57479L,57480L,57481L,57482L,57483L,57484L,
57485L,57486L,57487L,57488L,57489L,57490L,57491L,57492L,57493L,57494L,
57495L,57496L,57497L,57498L,57499L,57500L,57501L,57502L,57503L,57504L,
57505L,57506L,57507L,57508L,57509L,57510L,57511L,57512L,57513L,57514L,
57515L,57516L,57517L,57518L,57519L,57520L,57521L,57522L,57523L,57524L,
57525L,57526L,57527L,57528L,57529L,57530L,57531L,57532L,57533L,57534L,
57535L,57536L,57537L,57538L,57539L,57540L,57541L,57542L,57543L,57544L,
57545L,57546L,57547L,57548L,57549L,57550L,57551L,57552L,57553L,57554L,
57555L,57556L,57557L,57558L,57559L,57560L,57561L,57562L,57563L,57564L,
57565L,57566L,57567L,57568L,57569L,57570L,57571L,57572L,57573L,57574L,
57575L,57576L,57577L,57578L,57579L,57580L,57581L,57582L,57583L,57584L,
57585L,57586L,57587L,57588L,57589L,57590L,57591L,57592L,57593L,57594L,
57595L,57596L,57597L,57598L,57599L,57600L,57601L,57602L,57603L,57604L,
57605L,57606L,57607L,57608L,57609L,57610L,57611L,57612L,57613L,57614L,
57615L,57616L,57617L,57618L,57619L,57620L,57621L,57622L,57623L,57624L,
57625L,57626L,57627L,57628L,57629L,57630L,57631L,57632L,57633L,57634L,
57635L,57636L,57637L,57638L,57639L,57640L,57641L,57642L,57643L,57644L,
57645L,57646L,57647L,57648L,57649L,57650L,57651L,57652L,57653L,57654L,
57655L,57656L,57657L,57658L,57659L,57660L,57661L,57662L,57663L,57664L,
57665L,57666L,57667L,57668L,57669L,57670L,57671L,57672L,57673L,57674L,
57675L,57676L,57677L,57678L,57679L,57680L,57681L,57682L,57683L,57684L,
57685L,57686L,57687L,57688L,57689L,57690L,57691L,57692L,57693L,57694L,
57695L,57696L,57697L,57698L,57699L,57700L,57701L,57702L,57703L,57704L,
57705L,57706L,57707L,57708L,57709L,57710L,57711L,57712L,57713L,57714L,
57715L,57716L,57717L,57718L,57719L,57720L,57721L,57722L,57723L,57724L,
57725L,57726L,57727L,57728L,57729L,57730L,57731L,57732L,57733L,57734L,
57735L,57736L,57737L,57738L,57739L,57740L,57741L,57742L,57743L,57744L,
57745L,57746L,57747L,57748L,57749L,57750L,57751L,57752L,57753L,57754L,
57755L,57756L,57757L,57758L,57759L,57760L,57761L,57762L,57763L,57764L,
57765L,57766L,57767L,57768L,57769L,57770L,57771L,57772L,57773L,57774L,
57775L,57776L,57777L,57778L,57779L,57780L,57781L,57782L,57783L,57784L,
57785L,57786L,57787L,57788L,57789L,57790L,57791L,57792L,57793L,57794L,
57795L,57796L,57797L,57798L,57799L,57800L,57801L,57802L,57803L,57804L,
57805L,57806L,57807L,57808L,57809L,57810L,57811L,57812L,57813L,57814L,
57815L,57816L,57817L,57818L,57819L,57820L,57821L,57822L,57823L,57824L,
57825L,57826L,57827L,57828L,57829L,57830L,57831L,57832L,57833L,57834L,
57835L,57836L,57837L,57838L,57839L,57840L,57841L,57842L,57843L,57844L,
57845L,57846L,57847L,57848L,57849L,57850L,57851L,57852L,57853L,57854L,
57855L,57856L,57857L,57858L,57859L,57860L,57861L,57862L,57863L,57864L,
57865L,57866L,57867L,57868L,57869L,57870L,57871L,57872L,57873L,57874L,
57875L,57876L,57877L,57878L,57879L,57880L,57881L,57882L,57883L,57884L,
57885L,57886L,57887L,57888L,57889L,57890L,57891L,57892L,57893L,57894L,
57895L,57896L,57897L,57898L,57899L,57900L,57901L,57902L,57903L,57904L,
57905L,57906L,57907L,57908L,57909L,57910L,57911L,57912L,57913L,57914L,
57915L,57916L,57917L,57918L,57919L,57920L,57921L,57922L,57923L,57924L,
57925L,57926L,57927L,57928L,57929L,57930L,57931L,57932L,57933L,57934L,
57935L,57936L,57937L,57938L,57939L,57940L,57941L,57942L,57943L,57944L,
57945L,57946L,57947L,57948L,57949L,57950L,57951L,57952L,57953L,57954L,
57955L,57956L,57957L,57958L,57959L,57960L,57961L,57962L,57963L,57964L,
57965L,57966L,57967L,57968L,57969L,57970L,57971L,57972L,57973L,57974L,
57975L,57976L,57977L,57978L,57979L,57980L,57981L,57982L,57983L,57984L,
57985L,57986L,57987L,57988L,57989L,57990L,57991L,57992L,57993L,57994L,
57995L,57996L,57997L,57998L,57999L,58000L,58001L,58002L,58003L,58004L,
58005L,58006L,58007L,58008L,58009L,58010L,58011L,58012L,58013L,58014L,
58015L,58016L,58017L,58018L,58019L,58020L,58021L,58022L,58023L,58024L,
58025L,58026L,58027L,58028L,58029L,58030L,58031L,58032L,58033L,58034L,
58035L,58036L,58037L,58038L,58039L,58040L,58041L,58042L,58043L,58044L,
58045L,58046L,58047L,58048L,58049L,58050L,58051L,58052L,58053L,58054L,
58055L,58056L,58057L,58058L,58059L,58060L,58061L,58062L,58063L,58064L,
58065L,58066L,58067L,58068L,58069L,58070L,58071L,58072L,58073L,58074L,
58075L,58076L,58077L,58078L,58079L,58080L,58081L,58082L,58083L,58084L,
58085L,58086L,58087L,58088L,58089L,58090L,58091L,58092L,58093L,58094L,
58095L,58096L,58097L,58098L,58099L,58100L,58101L,58102L,58103L,58104L,
58105L,58106L,58107L,58108L,58109L,58110L,58111L,58112L,58113L,58114L,
58115L,58116L,58117L,58118L,58119L,58120L,58121L,58122L,58123L,58124L,
58125L,58126L,58127L,58128L,58129L,58130L,58131L,58132L,58133L,58134L,
58135L,58136L,58137L,58138L,58139L,58140L,58141L,58142L,58143L,58144L,
58145L,58146L,58147L,58148L,58149L,58150L,58151L,58152L,58153L,58154L,
58155L,58156L,58157L,58158L,58159L,58160L,58161L,58162L,58163L,58164L,
58165L,58166L,58167L,58168L,58169L,58170L,58171L,58172L,58173L,58174L,
58175L,58176L,58177L,58178L,58179L,58180L,58181L,58182L,58183L,58184L,
58185L,58186L,58187L,58188L,58189L,58190L,58191L,58192L,58193L,58194L,
58195L,58196L,58197L,58198L,58199L,58200L,58201L,58202L,58203L,58204L,
58205L,58206L,58207L,58208L,58209L,58210L,58211L,58212L,58213L,58214L,
58215L,58216L,58217L,58218L,58219L,58220L,58221L,58222L,58223L,58224L,
58225L,58226L,58227L,58228L,58229L,58230L,58231L,58232L,58233L,58234L,
58235L,58236L,58237L,58238L,58239L,58240L,58241L,58242L,58243L,58244L,
58245L,58246L,58247L,58248L,58249L,58250L,58251L,58252L,58253L,58254L,
58255L,58256L,58257L,58258L,58259L,58260L,58261L,58262L,58263L,58264L,
58265L,58266L,58267L,58268L,58269L,58270L,58271L,58272L,58273L,58274L,
58275L,58276L,58277L,58278L,58279L,58280L,58281L,58282L,58283L,58284L,
58285L,58286L,58287L,58288L,58289L,58290L,58291L,58292L,58293L,58294L,
58295L,58296L,58297L,58298L,58299L,58300L,58301L,58302L,58303L,58304L,
58305L,58306L,58307L,58308L,58309L,58310L,58311L,58312L,58313L,58314L,
58315L,58316L,58317L,58318L,58319L,58320L,58321L,58322L,58323L,58324L,
58325L,58326L,58327L,58328L,58329L,58330L,58331L,58332L,58333L,58334L,
58335L,58336L,58337L,58338L,58339L,58340L,58341L,58342L,58343L,58344L,
58345L,58346L,58347L,58348L,58349L,58350L,58351L,58352L,58353L,58354L,
58355L,58356L,58357L,58358L,58359L,58360L,58361L,58362L,58363L,58364L,
58365L,58366L,58367L,58368L,58369L,58370L,58371L,58372L,58373L,58374L,
58375L,58376L,58377L,58378L,58379L,58380L,58381L,58382L,58383L,58384L,
58385L,58386L,58387L,58388L,58389L,58390L,58391L,58392L,58393L,58394L,
58395L,58396L,58397L,58398L,58399L,58400L,58401L,58402L,58403L,58404L,
58405L,58406L,58407L,58408L,58409L,58410L,58411L,58412L,58413L,58414L,
58415L,58416L,58417L,58418L,58419L,58420L,58421L,58422L,58423L,58424L,
58425L,58426L,58427L,58428L,58429L,58430L,58431L,58432L,58433L,58434L,
58435L,58436L,58437L,58438L,58439L,58440L,58441L,58442L,58443L,58444L,
58445L,58446L,58447L,58448L,58449L,58450L,58451L,58452L,58453L,58454L,
58455L,58456L,58457L,58458L,58459L,58460L,58461L,58462L,58463L,58464L,
58465L,58466L,58467L,58468L,58469L,58470L,58471L,58472L,58473L,58474L,
58475L,58476L,58477L,58478L,58479L,58480L,58481L,58482L,58483L,58484L,
58485L,58486L,58487L,58488L,58489L,58490L,58491L,58492L,58493L,58494L,
58495L,58496L,58497L,58498L,58499L,58500L,58501L,58502L,58503L,58504L,
58505L,58506L,58507L,58508L,58509L,58510L,58511L,58512L,58513L,58514L,
58515L,58516L,58517L,58518L,58519L,58520L,58521L,58522L,58523L,58524L,
58525L,58526L,58527L,58528L,58529L,58530L,58531L,58532L,58533L,58534L,
58535L,58536L,58537L,58538L,58539L,58540L,58541L,58542L,58543L,58544L,
58545L,58546L,58547L,58548L,58549L,58550L,58551L,58552L,58553L,58554L,
58555L,58556L,58557L,58558L,58559L,58560L,58561L,58562L,58563L,58564L,
58565L,58566L,58567L,58568L,58569L,58570L,58571L,58572L,58573L,58574L,
58575L,58576L,58577L,58578L,58579L,58580L,58581L,58582L,58583L,58584L,
58585L,58586L,58587L,58588L,58589L,58590L,58591L,58592L,58593L,58594L,
58595L,58596L,58597L,58598L,58599L,58600L,58601L,58602L,58603L,58604L,
58605L,58606L,58607L,58608L,58609L,58610L,58611L,58612L,58613L,58614L,
58615L,58616L,58617L,58618L,58619L,58620L,58621L,58622L,58623L,58624L,
58625L,58626L,58627L,58628L,58629L,58630L,58631L,58632L,58633L,58634L,
58635L,58636L,58637L,58638L,58639L,58640L,58641L,58642L,58643L,58644L,
58645L,58646L,58647L,58648L,58649L,58650L,58651L,58652L,58653L,58654L,
58655L,58656L,58657L,58658L,58659L,58660L,58661L,58662L,58663L,58664L,
58665L,58666L,58667L,58668L,58669L,58670L,58671L,58672L,58673L,58674L,
58675L,58676L,58677L,58678L,58679L,58680L,58681L,58682L,58683L,58684L,
58685L,58686L,58687L,58688L,58689L,58690L,58691L,58692L,58693L,58694L,
58695L,58696L,58697L,58698L,58699L,58700L,58701L,58702L,58703L,58704L,
58705L,58706L,58707L,58708L,58709L,58710L,58711L,58712L,58713L,58714L,
58715L,58716L,58717L,58718L,58719L,58720L,58721L,58722L,58723L,58724L,
58725L,58726L,58727L,58728L,58729L,58730L,58731L,58732L,58733L,58734L,
58735L,58736L,58737L,58738L,58739L,58740L,58741L,58742L,58743L,58744L,
58745L,58746L,58747L,58748L,58749L,58750L,58751L,58752L,58753L,58754L,
58755L,58756L,58757L,58758L,58759L,58760L,58761L,58762L,58763L,58764L,
58765L,58766L,58767L,58768L,58769L,58770L,58771L,58772L,58773L,58774L,
58775L,58776L,58777L,58778L,58779L,58780L,58781L,58782L,58783L,58784L,
58785L,58786L,58787L,58788L,58789L,58790L,58791L,58792L,58793L,58794L,
58795L,58796L,58797L,58798L,58799L,58800L,58801L,58802L,58803L,58804L,
58805L,58806L,58807L,58808L,58809L,58810L,58811L,58812L,58813L,58814L,
58815L,58816L,58817L,58818L,58819L,58820L,58821L,58822L,58823L,58824L,
58825L,58826L,58827L,58828L,58829L,58830L,58831L,58832L,58833L,58834L,
58835L,58836L,58837L,58838L,58839L,58840L,58841L,58842L,58843L,58844L,
58845L,58846L,58847L,58848L,58849L,58850L,58851L,58852L,58853L,58854L,
58855L,58856L,58857L,58858L,58859L,58860L,58861L,58862L,58863L,58864L,
58865L,58866L,58867L,58868L,58869L,58870L,58871L,58872L,58873L,58874L,
58875L,58876L,58877L,58878L,58879L,58880L,58881L,58882L,58883L,58884L,
58885L,58886L,58887L,58888L,58889L,58890L,58891L,58892L,58893L,58894L,
58895L,58896L,58897L,58898L,58899L,58900L,58901L,58902L,58903L,58904L,
58905L,58906L,58907L,58908L,58909L,58910L,58911L,58912L,58913L,58914L,
58915L,58916L,58917L,58918L,58919L,58920L,58921L,58922L,58923L,58924L,
58925L,58926L,58927L,58928L,58929L,58930L,58931L,58932L,58933L,58934L,
58935L,58936L,58937L,58938L,58939L,58940L,58941L,58942L,58943L,58944L,
58945L,58946L,58947L,58948L,58949L,58950L,58951L,58952L,58953L,58954L,
58955L,58956L,58957L,58958L,58959L,58960L,58961L,58962L,58963L,58964L,
58965L,58966L,58967L,58968L,58969L,58970L,58971L,58972L,58973L,58974L,
58975L,58976L,58977L,58978L,58979L,58980L,58981L,58982L,58983L,58984L,
58985L,58986L,58987L,58988L,58989L,58990L,58991L,58992L,58993L,58994L,
58995L,58996L,58997L,58998L,58999L,59000L,59001L,59002L,59003L,59004L,
59005L,59006L,59007L,59008L,59009L,59010L,59011L,59012L,59013L,59014L,
59015L,59016L,59017L,59018L,59019L,59020L,59021L,59022L,59023L,59024L,
59025L,59026L,59027L,59028L,59029L,59030L,59031L,59032L,59033L,59034L,
59035L,59036L,59037L,59038L,59039L,59040L,59041L,59042L,59043L,59044L,
59045L,59046L,59047L,59048L,59049L,59050L,59051L,59052L,59053L,59054L,
59055L,59056L,59057L,59058L,59059L,59060L,59061L,59062L,59063L,59064L,
59065L,59066L,59067L,59068L,59069L,59070L,59071L,59072L,59073L,59074L,
59075L,59076L,59077L,59078L,59079L,59080L,59081L,59082L,59083L,59084L,
59085L,59086L,59087L,59088L,59089L,59090L,59091L,59092L,59093L,59094L,
59095L,59096L,59097L,59098L,59099L,59100L,59101L,59102L,59103L,59104L,
59105L,59106L,59107L,59108L,59109L,59110L,59111L,59112L,59113L,59114L,
59115L,59116L,59117L,59118L,59119L,59120L,59121L,59122L,59123L,59124L,
59125L,59126L,59127L,59128L,59129L,59130L,59131L,59132L,59133L,59134L,
59135L,59136L,59137L,59138L,59139L,59140L,59141L,59142L,59143L,59144L,
59145L,59146L,59147L,59148L,59149L,59150L,59151L,59152L,59153L,59154L,
59155L,59156L,59157L,59158L,59159L,59160L,59161L,59162L,59163L,59164L,
59165L,59166L,59167L,59168L,59169L,59170L,59171L,59172L,59173L,59174L,
59175L,59176L,59177L,59178L,59179L,59180L,59181L,59182L,59183L,59184L,
59185L,59186L,59187L,59188L,59189L,59190L,59191L,59192L,59193L,59194L,
59195L,59196L,59197L,59198L,59199L,59200L,59201L,59202L,59203L,59204L,
59205L,59206L,59207L,59208L,59209L,59210L,59211L,59212L,59213L,59214L,
59215L,59216L,59217L,59218L,59219L,59220L,59221L,59222L,59223L,59224L,
59225L,59226L,59227L,59228L,59229L,59230L,59231L,59232L,59233L,59234L,
59235L,59236L,59237L,59238L,59239L,59240L,59241L,59242L,59243L,59244L,
59245L,59246L,59247L,59248L,59249L,59250L,59251L,59252L,59253L,59254L,
59255L,59256L,59257L,59258L,59259L,59260L,59261L,59262L,59263L,59264L,
59265L,59266L,59267L,59268L,59269L,59270L,59271L,59272L,59273L,59274L,
59275L,59276L,59277L,59278L,59279L,59280L,59281L,59282L,59283L,59284L,
59285L,59286L,59287L,59288L,59289L,59290L,59291L,59292L,59293L,59294L,
59295L,59296L,59297L,59298L,59299L,59300L,59301L,59302L,59303L,59304L,
59305L,59306L,59307L,59308L,59309L,59310L,59311L,59312L,59313L,59314L,
59315L,59316L,59317L,59318L,59319L,59320L,59321L,59322L,59323L,59324L,
59325L,59326L,59327L,59328L,59329L,59330L,59331L,59332L,59333L,59334L,
59335L,59336L,59337L,59338L,59339L,59340L,59341L,59342L,59343L,59344L,
59345L,59346L,59347L,59348L,59349L,59350L,59351L,59352L,59353L,59354L,
59355L,59356L,59357L,59358L,59359L,59360L,59361L,59362L,59363L,59364L,
59365L,59366L,59367L,59368L,59369L,59370L,59371L,59372L,59373L,59374L,
59375L,59376L,59377L,59378L,59379L,59380L,59381L,59382L,59383L,59384L,
59385L,59386L,59387L,59388L,59389L,59390L,59391L,59392L,59393L,59394L,
59395L,59396L,59397L,59398L,59399L,59400L,59401L,59402L,59403L,59404L,
59405L,59406L,59407L,59408L,59409L,59410L,59411L,59412L,59413L,59414L,
59415L,59416L,59417L,59418L,59419L,59420L,59421L,59422L,59423L,59424L,
59425L,59426L,59427L,59428L,59429L,59430L,59431L,59432L,59433L,59434L,
59435L,59436L,59437L,59438L,59439L,59440L,59441L,59442L,59443L,59444L,
59445L,59446L,59447L,59448L,59449L,59450L,59451L,59452L,59453L,59454L,
59455L,59456L,59457L,59458L,59459L,59460L,59461L,59462L,59463L,59464L,
59465L,59466L,59467L,59468L,59469L,59470L,59471L,59472L,59473L,59474L,
59475L,59476L,59477L,59478L,59479L,59480L,59481L,59482L,59483L,59484L,
59485L,59486L,59487L,59488L,59489L,59490L,59491L,59492L,59493L,59494L,
59495L,59496L,59497L,59498L,59499L,59500L,59501L,59502L,59503L,59504L,
59505L,59506L,59507L,59508L,59509L,59510L,59511L,59512L,59513L,59514L,
59515L,59516L,59517L,59518L,59519L,59520L,59521L,59522L,59523L,59524L,
59525L,59526L,59527L,59528L,59529L,59530L,59531L,59532L,59533L,59534L,
59535L,59536L,59537L,59538L,59539L,59540L,59541L,59542L,59543L,59544L,
59545L,59546L,59547L,59548L,59549L,59550L,59551L,59552L,59553L,59554L,
59555L,59556L,59557L,59558L,59559L,59560L,59561L,59562L,59563L,59564L,
59565L,59566L,59567L,59568L,59569L,59570L,59571L,59572L,59573L,59574L,
59575L,59576L,59577L,59578L,59579L,59580L,59581L,59582L,59583L,59584L,
59585L,59586L,59587L,59588L,59589L,59590L,59591L,59592L,59593L,59594L,
59595L,59596L,59597L,59598L,59599L,59600L,59601L,59602L,59603L,59604L,
59605L,59606L,59607L,59608L,59609L,59610L,59611L,59612L,59613L,59614L,
59615L,59616L,59617L,59618L,59619L,59620L,59621L,59622L,59623L,59624L,
59625L,59626L,59627L,59628L,59629L,59630L,59631L,59632L,59633L,59634L,
59635L,59636L,59637L,59638L,59639L,59640L,59641L,59642L,59643L,59644L,
59645L,59646L,59647L,59648L,59649L,59650L,59651L,59652L,59653L,59654L,
59655L,59656L,59657L,59658L,59659L,59660L,59661L,59662L,59663L,59664L,
59665L,59666L,59667L,59668L,59669L,59670L,59671L,59672L,59673L,59674L,
59675L,59676L,59677L,59678L,59679L,59680L,59681L,59682L,59683L,59684L,
59685L,59686L,59687L,59688L,59689L,59690L,59691L,59692L,59693L,59694L,
59695L,59696L,59697L,59698L,59699L,59700L,59701L,59702L,59703L,59704L,
59705L,59706L,59707L,59708L,59709L,59710L,59711L,59712L,59713L,59714L,
59715L,59716L,59717L,59718L,59719L,59720L,59721L,59722L,59723L,59724L,
59725L,59726L,59727L,59728L,59729L,59730L,59731L,59732L,59733L,59734L,
59735L,59736L,59737L,59738L,59739L,59740L,59741L,59742L,59743L,59744L,
59745L,59746L,59747L,59748L,59749L,59750L,59751L,59752L,59753L,59754L,
59755L,59756L,59757L,59758L,59759L,59760L,59761L,59762L,59763L,59764L,
59765L,59766L,59767L,59768L,59769L,59770L,59771L,59772L,59773L,59774L,
59775L,59776L,59777L,59778L,59779L,59780L,59781L,59782L,59783L,59784L,
59785L,59786L,59787L,59788L,59789L,59790L,59791L,59792L,59793L,59794L,
59795L,59796L,59797L,59798L,59799L,59800L,59801L,59802L,59803L,59804L,
59805L,59806L,59807L,59808L,59809L,59810L,59811L,59812L,59813L,59814L,
59815L,59816L,59817L,59818L,59819L,59820L,59821L,59822L,59823L,59824L,
59825L,59826L,59827L,59828L,59829L,59830L,59831L,59832L,59833L,59834L,
59835L,59836L,59837L,59838L,59839L,59840L,59841L,59842L,59843L,59844L,
59845L,59846L,59847L,59848L,59849L,59850L,59851L,59852L,59853L,59854L,
59855L,59856L,59857L,59858L,59859L,59860L,59861L,59862L,59863L,59864L,
59865L,59866L,59867L,59868L,59869L,59870L,59871L,59872L,59873L,59874L,
59875L,59876L,59877L,59878L,59879L,59880L,59881L,59882L,59883L,59884L,
59885L,59886L,59887L,59888L,59889L,59890L,59891L,59892L,59893L,59894L,
59895L,59896L,59897L,59898L,59899L,59900L,59901L,59902L,59903L,59904L,
59905L,59906L,59907L,59908L,59909L,59910L,59911L,59912L,59913L,59914L,
59915L,59916L,59917L,59918L,59919L,59920L,59921L,59922L,59923L,59924L,
59925L,59926L,59927L,59928L,59929L,59930L,59931L,59932L,59933L,59934L,
59935L,59936L,59937L,59938L,59939L,59940L,59941L,59942L,59943L,59944L,
59945L,59946L,59947L,59948L,59949L,59950L,59951L,59952L,59953L,59954L,
59955L,59956L,59957L,59958L,59959L,59960L,59961L,59962L,59963L,59964L,
59965L,59966L,59967L,59968L,59969L,59970L,59971L,59972L,59973L,59974L,
59975L,59976L,59977L,59978L,59979L,59980L,59981L,59982L,59983L,59984L,
59985L,59986L,59987L,59988L,59989L,59990L,59991L,59992L,59993L,59994L,
59995L,59996L,59997L,59998L,59999L,60000L,60001L,60002L,60003L,60004L,
60005L,60006L,60007L,60008L,60009L,60010L,60011L,60012L,60013L,60014L,
60015L,60016L,60017L,60018L,60019L,60020L,60021L,60022L,60023L,60024L,
60025L,60026L,60027L,60028L,60029L,60030L,60031L,60032L,60033L,60034L,
60035L,60036L,60037L,60038L,60039L,60040L,60041L,60042L,60043L,60044L,
60045L,60046L,60047L,60048L,60049L,60050L,60051L,60052L,60053L,60054L,
60055L,60056L,60057L,60058L,60059L,60060L,60061L,60062L,60063L,60064L,
60065L,60066L,60067L,60068L,60069L,60070L,60071L,60072L,60073L,60074L,
60075L,60076L,60077L,60078L,60079L,60080L,60081L,60082L,60083L,60084L,
60085L,60086L,60087L,60088L,60089L,60090L,60091L,60092L,60093L,60094L,
60095L,60096L,60097L,60098L,60099L,60100L,60101L,60102L,60103L,60104L,
60105L,60106L,60107L,60108L,60109L,60110L,60111L,60112L,60113L,60114L,
60115L,60116L,60117L,60118L,60119L,60120L,60121L,60122L,60123L,60124L,
60125L,60126L,60127L,60128L,60129L,60130L,60131L,60132L,60133L,60134L,
60135L,60136L,60137L,60138L,60139L,60140L,60141L,60142L,60143L,60144L,
60145L,60146L,60147L,60148L,60149L,60150L,60151L,60152L,60153L,60154L,
60155L,60156L,60157L,60158L,60159L,60160L,60161L,60162L,60163L,60164L,
60165L,60166L,60167L,60168L,60169L,60170L,60171L,60172L,60173L,60174L,
60175L,60176L,60177L,60178L,60179L,60180L,60181L,60182L,60183L,60184L,
60185L,60186L,60187L,60188L,60189L,60190L,60191L,60192L,60193L,60194L,
60195L,60196L,60197L,60198L,60199L,60200L,60201L,60202L,60203L,60204L,
60205L,60206L,60207L,60208L,60209L,60210L,60211L,60212L,60213L,60214L,
60215L,60216L,60217L,60218L,60219L,60220L,60221L,60222L,60223L,60224L,
60225L,60226L,60227L,60228L,60229L,60230L,60231L,60232L,60233L,60234L,
60235L,60236L,60237L,60238L,60239L,60240L,60241L,60242L,60243L,60244L,
60245L,60246L,60247L,60248L,60249L,60250L,60251L,60252L,60253L,60254L,
60255L,60256L,60257L,60258L,60259L,60260L,60261L,60262L,60263L,60264L,
60265L,60266L,60267L,60268L,60269L,60270L,60271L,60272L,60273L,60274L,
60275L,60276L,60277L,60278L,60279L,60280L,60281L,60282L,60283L,60284L,
60285L,60286L,60287L,60288L,60289L,60290L,60291L,60292L,60293L,60294L,
60295L,60296L,60297L,60298L,60299L,60300L,60301L,60302L,60303L,60304L,
60305L,60306L,60307L,60308L,60309L,60310L,60311L,60312L,60313L,60314L,
60315L,60316L,60317L,60318L,60319L,60320L,60321L,60322L,60323L,60324L,
60325L,60326L,60327L,60328L,60329L,60330L,60331L,60332L,60333L,60334L,
60335L,60336L,60337L,60338L,60339L,60340L,60341L,60342L,60343L,60344L,
60345L,60346L,60347L,60348L,60349L,60350L,60351L,60352L,60353L,60354L,
60355L,60356L,60357L,60358L,60359L,60360L,60361L,60362L,60363L,60364L,
60365L,60366L,60367L,60368L,60369L,60370L,60371L,60372L,60373L,60374L,
60375L,60376L,60377L,60378L,60379L,60380L,60381L,60382L,60383L,60384L,
60385L,60386L,60387L,60388L,60389L,60390L,60391L,60392L,60393L,60394L,
60395L,60396L,60397L,60398L,60399L,60400L,60401L,60402L,60403L,60404L,
60405L,60406L,60407L,60408L,60409L,60410L,60411L,60412L,60413L,60414L,
60415L,60416L,60417L,60418L,60419L,60420L,60421L,60422L,60423L,60424L,
60425L,60426L,60427L,60428L,60429L,60430L,60431L,60432L,60433L,60434L,
60435L,60436L,60437L,60438L,60439L,60440L,60441L,60442L,60443L,60444L,
60445L,60446L,60447L,60448L,60449L,60450L,60451L,60452L,60453L,60454L,
60455L,60456L,60457L,60458L,60459L,60460L,60461L,60462L,60463L,60464L,
60465L,60466L,60467L,60468L,60469L,60470L,60471L,60472L,60473L,60474L,
60475L,60476L,60477L,60478L,60479L,60480L,60481L,60482L,60483L,60484L,
60485L,60486L,60487L,60488L,60489L,60490L,60491L,60492L,60493L,60494L,
60495L,60496L,60497L,60498L,60499L,60500L,60501L,60502L,60503L,60504L,
60505L,60506L,60507L,60508L,60509L,60510L,60511L,60512L,60513L,60514L,
60515L,60516L,60517L,60518L,60519L,60520L,60521L,60522L,60523L,60524L,
60525L,60526L,60527L,60528L,60529L,60530L,60531L,60532L,60533L,60534L,
60535L,60536L,60537L,60538L,60539L,60540L,60541L,60542L,60543L,60544L,
60545L,60546L,60547L,60548L,60549L,60550L,60551L,60552L,60553L,60554L,
60555L,60556L,60557L,60558L,60559L,60560L,60561L,60562L,60563L,60564L,
60565L,60566L,60567L,60568L,60569L,60570L,60571L,60572L,60573L,60574L,
60575L,60576L,60577L,60578L,60579L,60580L,60581L,60582L,60583L,60584L,
60585L,60586L,60587L,60588L,60589L,60590L,60591L,60592L,60593L,60594L,
60595L,60596L,60597L,60598L,60599L,60600L,60601L,60602L,60603L,60604L,
60605L,60606L,60607L,60608L,60609L,60610L,60611L,60612L,60613L,60614L,
60615L,60616L,60617L,60618L,60619L,60620L,60621L,60622L,60623L,60624L,
60625L,60626L,60627L,60628L,60629L,60630L,60631L,60632L,60633L,60634L,
60635L,60636L,60637L,60638L,60639L,60640L,60641L,60642L,60643L,60644L,
60645L,60646L,60647L,60648L,60649L,60650L,60651L,60652L,60653L,60654L,
60655L,60656L,60657L,60658L,60659L,60660L,60661L,60662L,60663L,60664L,
60665L,60666L,60667L,60668L,60669L,60670L,60671L,60672L,60673L,60674L,
60675L,60676L,60677L,60678L,60679L,60680L,60681L,60682L,60683L,60684L,
60685L,60686L,60687L,60688L,60689L,60690L,60691L,60692L,60693L,60694L,
60695L,60696L,60697L,60698L,60699L,60700L,60701L,60702L,60703L,60704L,
60705L,60706L,60707L,60708L,60709L,60710L,60711L,60712L,60713L,60714L,
60715L,60716L,60717L,60718L,60719L,60720L,60721L,60722L,60723L,60724L,
60725L,60726L,60727L,60728L,60729L,60730L,60731L,60732L,60733L,60734L,
60735L,60736L,60737L,60738L,60739L,60740L,60741L,60742L,60743L,60744L,
60745L,60746L,60747L,60748L,60749L,60750L,60751L,60752L,60753L,60754L,
60755L,60756L,60757L,60758L,60759L,60760L,60761L,60762L,60763L,60764L,
60765L,60766L,60767L,60768L,60769L,60770L,60771L,60772L,60773L,60774L,
60775L,60776L,60777L,60778L,60779L,60780L,60781L,60782L,60783L,60784L,
60785L,60786L,60787L,60788L,60789L,60790L,60791L,60792L,60793L,60794L,
60795L,60796L,60797L,60798L,60799L,60800L,60801L,60802L,60803L,60804L,
60805L,60806L,60807L,60808L,60809L,60810L,60811L,60812L,60813L,60814L,
60815L,60816L,60817L,60818L,60819L,60820L,60821L,60822L,60823L,60824L,
60825L,60826L,60827L,60828L,60829L,60830L,60831L,60832L,60833L,60834L,
60835L,60836L,60837L,60838L,60839L,60840L,60841L,60842L,60843L,60844L,
60845L,60846L,60847L,60848L,60849L,60850L,60851L,60852L,60853L,60854L,
60855L,60856L,60857L,60858L,60859L,60860L,60861L,60862L,60863L,60864L,
60865L,60866L,60867L,60868L,60869L,60870L,60871L,60872L,60873L,60874L,
60875L,60876L,60877L,60878L,60879L,60880L,60881L,60882L,60883L,60884L,
60885L,60886L,60887L,60888L,60889L,60890L,60891L,60892L,60893L,60894L,
60895L,60896L,60897L,60898L,60899L,60900L,60901L,60902L,60903L,60904L,
60905L,60906L,60907L,60908L,60909L,60910L,60911L,60912L,60913L,60914L,
60915L,60916L,60917L,60918L,60919L,60920L,60921L,60922L,60923L,60924L,
60925L,60926L,60927L,60928L,60929L,60930L,60931L,60932L,60933L,60934L,
60935L,60936L,60937L,60938L,60939L,60940L,60941L,60942L,60943L,60944L,
60945L,60946L,60947L,60948L,60949L,60950L,60951L,60952L,60953L,60954L,
60955L,60956L,60957L,60958L,60959L,60960L,60961L,60962L,60963L,60964L,
60965L,60966L,60967L,60968L,60969L,60970L,60971L,60972L,60973L,60974L,
60975L,60976L,60977L,60978L,60979L,60980L,60981L,60982L,60983L,60984L,
60985L,60986L,60987L,60988L,60989L,60990L,60991L,60992L,60993L,60994L,
60995L,60996L,60997L,60998L,60999L,61000L,61001L,61002L,61003L,61004L,
61005L,61006L,61007L,61008L,61009L,61010L,61011L,61012L,61013L,61014L,
61015L,61016L,61017L,61018L,61019L,61020L,61021L,61022L,61023L,61024L,
61025L,61026L,61027L,61028L,61029L,61030L,61031L,61032L,61033L,61034L,
61035L,61036L,61037L,61038L,61039L,61040L,61041L,61042L,61043L,61044L,
61045L,61046L,61047L,61048L,61049L,61050L,61051L,61052L,61053L,61054L,
61055L,61056L,61057L,61058L,61059L,61060L,61061L,61062L,61063L,61064L,
61065L,61066L,61067L,61068L,61069L,61070L,61071L,61072L,61073L,61074L,
61075L,61076L,61077L,61078L,61079L,61080L,61081L,61082L,61083L,61084L,
61085L,61086L,61087L,61088L,61089L,61090L,61091L,61092L,61093L,61094L,
61095L,61096L,61097L,61098L,61099L,61100L,61101L,61102L,61103L,61104L,
61105L,61106L,61107L,61108L,61109L,61110L,61111L,61112L,61113L,61114L,
61115L,61116L,61117L,61118L,61119L,61120L,61121L,61122L,61123L,61124L,
61125L,61126L,61127L,61128L,61129L,61130L,61131L,61132L,61133L,61134L,
61135L,61136L,61137L,61138L,61139L,61140L,61141L,61142L,61143L,61144L,
61145L,61146L,61147L,61148L,61149L,61150L,61151L,61152L,61153L,61154L,
61155L,61156L,61157L,61158L,61159L,61160L,61161L,61162L,61163L,61164L,
61165L,61166L,61167L,61168L,61169L,61170L,61171L,61172L,61173L,61174L,
61175L,61176L,61177L,61178L,61179L,61180L,61181L,61182L,61183L,61184L,
61185L,61186L,61187L,61188L,61189L,61190L,61191L,61192L,61193L,61194L,
61195L,61196L,61197L,61198L,61199L,61200L,61201L,61202L,61203L,61204L,
61205L,61206L,61207L,61208L,61209L,61210L,61211L,61212L,61213L,61214L,
61215L,61216L,61217L,61218L,61219L,61220L,61221L,61222L,61223L,61224L,
61225L,61226L,61227L,61228L,61229L,61230L,61231L,61232L,61233L,61234L,
61235L,61236L,61237L,61238L,61239L,61240L,61241L,61242L,61243L,61244L,
61245L,61246L,61247L,61248L,61249L,61250L,61251L,61252L,61253L,61254L,
61255L,61256L,61257L,61258L,61259L,61260L,61261L,61262L,61263L,61264L,
61265L,61266L,61267L,61268L,61269L,61270L,61271L,61272L,61273L,61274L,
61275L,61276L,61277L,61278L,61279L,61280L,61281L,61282L,61283L,61284L,
61285L,61286L,61287L,61288L,61289L,61290L,61291L,61292L,61293L,61294L,
61295L,61296L,61297L,61298L,61299L,61300L,61301L,61302L,61303L,61304L,
61305L,61306L,61307L,61308L,61309L,61310L,61311L,61312L,61313L,61314L,
61315L,61316L,61317L,61318L,61319L,61320L,61321L,61322L,61323L,61324L,
61325L,61326L,61327L,61328L,61329L,61330L,61331L,61332L,61333L,61334L,
61335L,61336L,61337L,61338L,61339L,61340L,61341L,61342L,61343L,61344L,
61345L,61346L,61347L,61348L,61349L,61350L,61351L,61352L,61353L,61354L,
61355L,61356L,61357L,61358L,61359L,61360L,61361L,61362L,61363L,61364L,
61365L,61366L,61367L,61368L,61369L,61370L,61371L,61372L,61373L,61374L,
61375L,61376L,61377L,61378L,61379L,61380L,61381L,61382L,61383L,61384L,
61385L,61386L,61387L,61388L,61389L,61390L,61391L,61392L,61393L,61394L,
61395L,61396L,61397L,61398L,61399L,61400L,61401L,61402L,61403L,61404L,
61405L,61406L,61407L,61408L,61409L,61410L,61411L,61412L,61413L,61414L,
61415L,61416L,61417L,61418L,61419L,61420L,61421L,61422L,61423L,61424L,
61425L,61426L,61427L,61428L,61429L,61430L,61431L,61432L,61433L,61434L,
61435L,61436L,61437L,61438L,61439L,61440L,61441L,61442L,61443L,61444L,
61445L,61446L,61447L,61448L,61449L,61450L,61451L,61452L,61453L,61454L,
61455L,61456L,61457L,61458L,61459L,61460L,61461L,61462L,61463L,61464L,
61465L,61466L,61467L,61468L,61469L,61470L,61471L,61472L,61473L,61474L,
61475L,61476L,61477L,61478L,61479L,61480L,61481L,61482L,61483L,61484L,
61485L,61486L,61487L,61488L,61489L,61490L,61491L,61492L,61493L,61494L,
61495L,61496L,61497L,61498L,61499L,61500L,61501L,61502L,61503L,61504L,
61505L,61506L,61507L,61508L,61509L,61510L,61511L,61512L,61513L,61514L,
61515L,61516L,61517L,61518L,61519L,61520L,61521L,61522L,61523L,61524L,
61525L,61526L,61527L,61528L,61529L,61530L,61531L,61532L,61533L,61534L,
61535L,61536L,61537L,61538L,61539L,61540L,61541L,61542L,61543L,61544L,
61545L,61546L,61547L,61548L,61549L,61550L,61551L,61552L,61553L,61554L,
61555L,61556L,61557L,61558L,61559L,61560L,61561L,61562L,61563L,61564L,
61565L,61566L,61567L,61568L,61569L,61570L,61571L,61572L,61573L,61574L,
61575L,61576L,61577L,61578L,61579L,61580L,61581L,61582L,61583L,61584L,
61585L,61586L,61587L,61588L,61589L,61590L,61591L,61592L,61593L,61594L,
61595L,61596L,61597L,61598L,61599L,61600L,61601L,61602L,61603L,61604L,
61605L,61606L,61607L,61608L,61609L,61610L,61611L,61612L,61613L,61614L,
61615L,61616L,61617L,61618L,61619L,61620L,61621L,61622L,61623L,61624L,
61625L,61626L,61627L,61628L,61629L,61630L,61631L,61632L,61633L,61634L,
61635L,61636L,61637L,61638L,61639L,61640L,61641L,61642L,61643L,61644L,
61645L,61646L,61647L,61648L,61649L,61650L,61651L,61652L,61653L,61654L,
61655L,61656L,61657L,61658L,61659L,61660L,61661L,61662L,61663L,61664L,
61665L,61666L,61667L,61668L,61669L,61670L,61671L,61672L,61673L,61674L,
61675L,61676L,61677L,61678L,61679L,61680L,61681L,61682L,61683L,61684L,
61685L,61686L,61687L,61688L,61689L,61690L,61691L,61692L,61693L,61694L,
61695L,61696L,61697L,61698L,61699L,61700L,61701L,61702L,61703L,61704L,
61705L,61706L,61707L,61708L,61709L,61710L,61711L,61712L,61713L,61714L,
61715L,61716L,61717L,61718L,61719L,61720L,61721L,61722L,61723L,61724L,
61725L,61726L,61727L,61728L,61729L,61730L,61731L,61732L,61733L,61734L,
61735L,61736L,61737L,61738L,61739L,61740L,61741L,61742L,61743L,61744L,
61745L,61746L,61747L,61748L,61749L,61750L,61751L,61752L,61753L,61754L,
61755L,61756L,61757L,61758L,61759L,61760L,61761L,61762L,61763L,61764L,
61765L,61766L,61767L,61768L,61769L,61770L,61771L,61772L,61773L,61774L,
61775L,61776L,61777L,61778L,61779L,61780L,61781L,61782L,61783L,61784L,
61785L,61786L,61787L,61788L,61789L,61790L,61791L,61792L,61793L,61794L,
61795L,61796L,61797L,61798L,61799L,61800L,61801L,61802L,61803L,61804L,
61805L,61806L,61807L,61808L,61809L,61810L,61811L,61812L,61813L,61814L,
61815L,61816L,61817L,61818L,61819L,61820L,61821L,61822L,61823L,61824L,
61825L,61826L,61827L,61828L,61829L,61830L,61831L,61832L,61833L,61834L,
61835L,61836L,61837L,61838L,61839L,61840L,61841L,61842L,61843L,61844L,
61845L,61846L,61847L,61848L,61849L,61850L,61851L,61852L,61853L,61854L,
61855L,61856L,61857L,61858L,61859L,61860L,61861L,61862L,61863L,61864L,
61865L,61866L,61867L,61868L,61869L,61870L,61871L,61872L,61873L,61874L,
61875L,61876L,61877L,61878L,61879L,61880L,61881L,61882L,61883L,61884L,
61885L,61886L,61887L,61888L,61889L,61890L,61891L,61892L,61893L,61894L,
61895L,61896L,61897L,61898L,61899L,61900L,61901L,61902L,61903L,61904L,
61905L,61906L,61907L,61908L,61909L,61910L,61911L,61912L,61913L,61914L,
61915L,61916L,61917L,61918L,61919L,61920L,61921L,61922L,61923L,61924L,
61925L,61926L,61927L,61928L,61929L,61930L,61931L,61932L,61933L,61934L,
61935L,61936L,61937L,61938L,61939L,61940L,61941L,61942L,61943L,61944L,
61945L,61946L,61947L,61948L,61949L,61950L,61951L,61952L,61953L,61954L,
61955L,61956L,61957L,61958L,61959L,61960L,61961L,61962L,61963L,61964L,
61965L,61966L,61967L,61968L,61969L,61970L,61971L,61972L,61973L,61974L,
61975L,61976L,61977L,61978L,61979L,61980L,61981L,61982L,61983L,61984L,
61985L,61986L,61987L,61988L,61989L,61990L,61991L,61992L,61993L,61994L,
61995L,61996L,61997L,61998L,61999L,62000L,62001L,62002L,62003L,62004L,
62005L,62006L,62007L,62008L,62009L,62010L,62011L,62012L,62013L,62014L,
62015L,62016L,62017L,62018L,62019L,62020L,62021L,62022L,62023L,62024L,
62025L,62026L,62027L,62028L,62029L,62030L,62031L,62032L,62033L,62034L,
62035L,62036L,62037L,62038L,62039L,62040L,62041L,62042L,62043L,62044L,
62045L,62046L,62047L,62048L,62049L,62050L,62051L,62052L,62053L,62054L,
62055L,62056L,62057L,62058L,62059L,62060L,62061L,62062L,62063L,62064L,
62065L,62066L,62067L,62068L,62069L,62070L,62071L,62072L,62073L,62074L,
62075L,62076L,62077L,62078L,62079L,62080L,62081L,62082L,62083L,62084L,
62085L,62086L,62087L,62088L,62089L,62090L,62091L,62092L,62093L,62094L,
62095L,62096L,62097L,62098L,62099L,62100L,62101L,62102L,62103L,62104L,
62105L,62106L,62107L,62108L,62109L,62110L,62111L,62112L,62113L,62114L,
62115L,62116L,62117L,62118L,62119L,62120L,62121L,62122L,62123L,62124L,
62125L,62126L,62127L,62128L,62129L,62130L,62131L,62132L,62133L,62134L,
62135L,62136L,62137L,62138L,62139L,62140L,62141L,62142L,62143L,62144L,
62145L,62146L,62147L,62148L,62149L,62150L,62151L,62152L,62153L,62154L,
62155L,62156L,62157L,62158L,62159L,62160L,62161L,62162L,62163L,62164L,
62165L,62166L,62167L,62168L,62169L,62170L,62171L,62172L,62173L,62174L,
62175L,62176L,62177L,62178L,62179L,62180L,62181L,62182L,62183L,62184L,
62185L,62186L,62187L,62188L,62189L,62190L,62191L,62192L,62193L,62194L,
62195L,62196L,62197L,62198L,62199L,62200L,62201L,62202L,62203L,62204L,
62205L,62206L,62207L,62208L,62209L,62210L,62211L,62212L,62213L,62214L,
62215L,62216L,62217L,62218L,62219L,62220L,62221L,62222L,62223L,62224L,
62225L,62226L,62227L,62228L,62229L,62230L,62231L,62232L,62233L,62234L,
62235L,62236L,62237L,62238L,62239L,62240L,62241L,62242L,62243L,62244L,
62245L,62246L,62247L,62248L,62249L,62250L,62251L,62252L,62253L,62254L,
62255L,62256L,62257L,62258L,62259L,62260L,62261L,62262L,62263L,62264L,
62265L,62266L,62267L,62268L,62269L,62270L,62271L,62272L,62273L,62274L,
62275L,62276L,62277L,62278L,62279L,62280L,62281L,62282L,62283L,62284L,
62285L,62286L,62287L,62288L,62289L,62290L,62291L,62292L,62293L,62294L,
62295L,62296L,62297L,62298L,62299L,62300L,62301L,62302L,62303L,62304L,
62305L,62306L,62307L,62308L,62309L,62310L,62311L,62312L,62313L,62314L,
62315L,62316L,62317L,62318L,62319L,62320L,62321L,62322L,62323L,62324L,
62325L,62326L,62327L,62328L,62329L,62330L,62331L,62332L,62333L,62334L,
62335L,62336L,62337L,62338L,62339L,62340L,62341L,62342L,62343L,62344L,
62345L,62346L,62347L,62348L,62349L,62350L,62351L,62352L,62353L,62354L,
62355L,62356L,62357L,62358L,62359L,62360L,62361L,62362L,62363L,62364L,
62365L,62366L,62367L,62368L,62369L,62370L,62371L,62372L,62373L,62374L,
62375L,62376L,62377L,62378L,62379L,62380L,62381L,62382L,62383L,62384L,
62385L,62386L,62387L,62388L,62389L,62390L,62391L,62392L,62393L,62394L,
62395L,62396L,62397L,62398L,62399L,62400L,62401L,62402L,62403L,62404L,
62405L,62406L,62407L,62408L,62409L,62410L,62411L,62412L,62413L,62414L,
62415L,62416L,62417L,62418L,62419L,62420L,62421L,62422L,62423L,62424L,
62425L,62426L,62427L,62428L,62429L,62430L,62431L,62432L,62433L,62434L,
62435L,62436L,62437L,62438L,62439L,62440L,62441L,62442L,62443L,62444L,
62445L,62446L,62447L,62448L,62449L,62450L,62451L,62452L,62453L,62454L,
62455L,62456L,62457L,62458L,62459L,62460L,62461L,62462L,62463L,62464L,
62465L,62466L,62467L,62468L,62469L,62470L,62471L,62472L,62473L,62474L,
62475L,62476L,62477L,62478L,62479L,62480L,62481L,62482L,62483L,62484L,
62485L,62486L,62487L,62488L,62489L,62490L,62491L,62492L,62493L,62494L,
62495L,62496L,62497L,62498L,62499L,62500L,62501L,62502L,62503L,62504L,
62505L,62506L,62507L,62508L,62509L,62510L,62511L,62512L,62513L,62514L,
62515L,62516L,62517L,62518L,62519L,62520L,62521L,62522L,62523L,62524L,
62525L,62526L,62527L,62528L,62529L,62530L,62531L,62532L,62533L,62534L,
62535L,62536L,62537L,62538L,62539L,62540L,62541L,62542L,62543L,62544L,
62545L,62546L,62547L,62548L,62549L,62550L,62551L,62552L,62553L,62554L,
62555L,62556L,62557L,62558L,62559L,62560L,62561L,62562L,62563L,62564L,
62565L,62566L,62567L,62568L,62569L,62570L,62571L,62572L,62573L,62574L,
62575L,62576L,62577L,62578L,62579L,62580L,62581L,62582L,62583L,62584L,
62585L,62586L,62587L,62588L,62589L,62590L,62591L,62592L,62593L,62594L,
62595L,62596L,62597L,62598L,62599L,62600L,62601L,62602L,62603L,62604L,
62605L,62606L,62607L,62608L,62609L,62610L,62611L,62612L,62613L,62614L,
62615L,62616L,62617L,62618L,62619L,62620L,62621L,62622L,62623L,62624L,
62625L,62626L,62627L,62628L,62629L,62630L,62631L,62632L,62633L,62634L,
62635L,62636L,62637L,62638L,62639L,62640L,62641L,62642L,62643L,62644L,
62645L,62646L,62647L,62648L,62649L,62650L,62651L,62652L,62653L,62654L,
62655L,62656L,62657L,62658L,62659L,62660L,62661L,62662L,62663L,62664L,
62665L,62666L,62667L,62668L,62669L,62670L,62671L,62672L,62673L,62674L,
62675L,62676L,62677L,62678L,62679L,62680L,62681L,62682L,62683L,62684L,
62685L,62686L,62687L,62688L,62689L,62690L,62691L,62692L,62693L,62694L,
62695L,62696L,62697L,62698L,62699L,62700L,62701L,62702L,62703L,62704L,
62705L,62706L,62707L,62708L,62709L,62710L,62711L,62712L,62713L,62714L,
62715L,62716L,62717L,62718L,62719L,62720L,62721L,62722L,62723L,62724L,
62725L,62726L,62727L,62728L,62729L,62730L,62731L,62732L,62733L,62734L,
62735L,62736L,62737L,62738L,62739L,62740L,62741L,62742L,62743L,62744L,
62745L,62746L,62747L,62748L,62749L,62750L,62751L,62752L,62753L,62754L,
62755L,62756L,62757L,62758L,62759L,62760L,62761L,62762L,62763L,62764L,
62765L,62766L,62767L,62768L,62769L,62770L,62771L,62772L,62773L,62774L,
62775L,62776L,62777L,62778L,62779L,62780L,62781L,62782L,62783L,62784L,
62785L,62786L,62787L,62788L,62789L,62790L,62791L,62792L,62793L,62794L,
62795L,62796L,62797L,62798L,62799L,62800L,62801L,62802L,62803L,62804L,
62805L,62806L,62807L,62808L,62809L,62810L,62811L,62812L,62813L,62814L,
62815L,62816L,62817L,62818L,62819L,62820L,62821L,62822L,62823L,62824L,
62825L,62826L,62827L,62828L,62829L,62830L,62831L,62832L,62833L,62834L,
62835L,62836L,62837L,62838L,62839L,62840L,62841L,62842L,62843L,62844L,
62845L,62846L,62847L,62848L,62849L,62850L,62851L,62852L,62853L,62854L,
62855L,62856L,62857L,62858L,62859L,62860L,62861L,62862L,62863L,62864L,
62865L,62866L,62867L,62868L,62869L,62870L,62871L,62872L,62873L,62874L,
62875L,62876L,62877L,62878L,62879L,62880L,62881L,62882L,62883L,62884L,
62885L,62886L,62887L,62888L,62889L,62890L,62891L,62892L,62893L,62894L,
62895L,62896L,62897L,62898L,62899L,62900L,62901L,62902L,62903L,62904L,
62905L,62906L,62907L,62908L,62909L,62910L,62911L,62912L,62913L,62914L,
62915L,62916L,62917L,62918L,62919L,62920L,62921L,62922L,62923L,62924L,
62925L,62926L,62927L,62928L,62929L,62930L,62931L,62932L,62933L,62934L,
62935L,62936L,62937L,62938L,62939L,62940L,62941L,62942L,62943L,62944L,
62945L,62946L,62947L,62948L,62949L,62950L,62951L,62952L,62953L,62954L,
62955L,62956L,62957L,62958L,62959L,62960L,62961L,62962L,62963L,62964L,
62965L,62966L,62967L,62968L,62969L,62970L,62971L,62972L,62973L,62974L,
62975L,62976L,62977L,62978L,62979L,62980L,62981L,62982L,62983L,62984L,
62985L,62986L,62987L,62988L,62989L,62990L,62991L,62992L,62993L,62994L,
62995L,62996L,62997L,62998L,62999L,63000L,63001L,63002L,63003L,63004L,
63005L,63006L,63007L,63008L,63009L,63010L,63011L,63012L,63013L,63014L,
63015L,63016L,63017L,63018L,63019L,63020L,63021L,63022L,63023L,63024L,
63025L,63026L,63027L,63028L,63029L,63030L,63031L,63032L,63033L,63034L,
63035L,63036L,63037L,63038L,63039L,63040L,63041L,63042L,63043L,63044L,
63045L,63046L,63047L,63048L,63049L,63050L,63051L,63052L,63053L,63054L,
63055L,63056L,63057L,63058L,63059L,63060L,63061L,63062L,63063L,63064L,
63065L,63066L,63067L,63068L,63069L,63070L,63071L,63072L,63073L,63074L,
63075L,63076L,63077L,63078L,63079L,63080L,63081L,63082L,63083L,63084L,
63085L,63086L,63087L,63088L,63089L,63090L,63091L,63092L,63093L,63094L,
63095L,63096L,63097L,63098L,63099L,63100L,63101L,63102L,63103L,63104L,
63105L,63106L,63107L,63108L,63109L,63110L,63111L,63112L,63113L,63114L,
63115L,63116L,63117L,63118L,63119L,63120L,63121L,63122L,63123L,63124L,
63125L,63126L,63127L,63128L,63129L,63130L,63131L,63132L,63133L,63134L,
63135L,63136L,63137L,63138L,63139L,63140L,63141L,63142L,63143L,63144L,
63145L,63146L,63147L,63148L,63149L,63150L,63151L,63152L,63153L,63154L,
63155L,63156L,63157L,63158L,63159L,63160L,63161L,63162L,63163L,63164L,
63165L,63166L,63167L,63168L,63169L,63170L,63171L,63172L,63173L,63174L,
63175L,63176L,63177L,63178L,63179L,63180L,63181L,63182L,63183L,63184L,
63185L,63186L,63187L,63188L,63189L,63190L,63191L,63192L,63193L,63194L,
63195L,63196L,63197L,63198L,63199L,63200L,63201L,63202L,63203L,63204L,
63205L,63206L,63207L,63208L,63209L,63210L,63211L,63212L,63213L,63214L,
63215L,63216L,63217L,63218L,63219L,63220L,63221L,63222L,63223L,63224L,
63225L,63226L,63227L,63228L,63229L,63230L,63231L,63232L,63233L,63234L,
63235L,63236L,63237L,63238L,63239L,63240L,63241L,63242L,63243L,63244L,
63245L,63246L,63247L,63248L,63249L,63250L,63251L,63252L,63253L,63254L,
63255L,63256L,63257L,63258L,63259L,63260L,63261L,63262L,63263L,63264L,
63265L,63266L,63267L,63268L,63269L,63270L,63271L,63272L,63273L,63274L,
63275L,63276L,63277L,63278L,63279L,63280L,63281L,63282L,63283L,63284L,
63285L,63286L,63287L,63288L,63289L,63290L,63291L,63292L,63293L,63294L,
63295L,63296L,63297L,63298L,63299L,63300L,63301L,63302L,63303L,63304L,
63305L,63306L,63307L,63308L,63309L,63310L,63311L,63312L,63313L,63314L,
63315L,63316L,63317L,63318L,63319L,63320L,63321L,63322L,63323L,63324L,
63325L,63326L,63327L,63328L,63329L,63330L,63331L,63332L,63333L,63334L,
63335L,63336L,63337L,63338L,63339L,63340L,63341L,63342L,63343L,63344L,
63345L,63346L,63347L,63348L,63349L,63350L,63351L,63352L,63353L,63354L,
63355L,63356L,63357L,63358L,63359L,63360L,63361L,63362L,63363L,63364L,
63365L,63366L,63367L,63368L,63369L,63370L,63371L,63372L,63373L,63374L,
63375L,63376L,63377L,63378L,63379L,63380L,63381L,63382L,63383L,63384L,
63385L,63386L,63387L,63388L,63389L,63390L,63391L,63392L,63393L,63394L,
63395L,63396L,63397L,63398L,63399L,63400L,63401L,63402L,63403L,63404L,
63405L,63406L,63407L,63408L,63409L,63410L,63411L,63412L,63413L,63414L,
63415L,63416L,63417L,63418L,63419L,63420L,63421L,63422L,63423L,63424L,
63425L,63426L,63427L,63428L,63429L,63430L,63431L,63432L,63433L,63434L,
63435L,63436L,63437L,63438L,63439L,63440L,63441L,63442L,63443L,63444L,
63445L,63446L,63447L,63448L,63449L,63450L,63451L,63452L,63453L,63454L,
63455L,63456L,63457L,63458L,63459L,63460L,63461L,63462L,63463L,63464L,
63465L,63466L,63467L,63468L,63469L,63470L,63471L,63472L,63473L,63474L,
63475L,63476L,63477L,63478L,63479L,63480L,63481L,63482L,63483L,63484L,
63485L,63486L,63487L,63488L,63489L,63490L,63491L,63492L,63493L,63494L,
63495L,63496L,63497L,63498L,63499L,63500L,63501L,63502L,63503L,63504L,
63505L,63506L,63507L,63508L,63509L,63510L,63511L,63512L,63513L,63514L,
63515L,63516L,63517L,63518L,63519L,63520L,63521L,63522L,63523L,63524L,
63525L,63526L,63527L,63528L,63529L,63530L,63531L,63532L,63533L,63534L,
63535L,63536L,63537L,63538L,63539L,63540L,63541L,63542L,63543L,63544L,
63545L,63546L,63547L,63548L,63549L,63550L,63551L,63552L,63553L,63554L,
63555L,63556L,63557L,63558L,63559L,63560L,63561L,63562L,63563L,63564L,
63565L,63566L,63567L,63568L,63569L,63570L,63571L,63572L,63573L,63574L,
63575L,63576L,63577L,63578L,63579L,63580L,63581L,63582L,63583L,63584L,
63585L,63586L,63587L,63588L,63589L,63590L,63591L,63592L,63593L,63594L,
63595L,63596L,63597L,63598L,63599L,63600L,63601L,63602L,63603L,63604L,
63605L,63606L,63607L,63608L,63609L,63610L,63611L,63612L,63613L,63614L,
63615L,63616L,63617L,63618L,63619L,63620L,63621L,63622L,63623L,63624L,
63625L,63626L,63627L,63628L,63629L,63630L,63631L,63632L,63633L,63634L,
63635L,63636L,63637L,63638L,63639L,63640L,63641L,63642L,63643L,63644L,
63645L,63646L,63647L,63648L,63649L,63650L,63651L,63652L,63653L,63654L,
63655L,63656L,63657L,63658L,63659L,63660L,63661L,63662L,63663L,63664L,
63665L,63666L,63667L,63668L,63669L,63670L,63671L,63672L,63673L,63674L,
63675L,63676L,63677L,63678L,63679L,63680L,63681L,63682L,63683L,63684L,
63685L,63686L,63687L,63688L,63689L,63690L,63691L,63692L,63693L,63694L,
63695L,63696L,63697L,63698L,63699L,63700L,63701L,63702L,63703L,63704L,
63705L,63706L,63707L,63708L,63709L,63710L,63711L,63712L,63713L,63714L,
63715L,63716L,63717L,63718L,63719L,63720L,63721L,63722L,63723L,63724L,
63725L,63726L,63727L,63728L,63729L,63730L,63731L,63732L,63733L,63734L,
63735L,63736L,63737L,63738L,63739L,63740L,63741L,63742L,63743L,63744L,
63745L,63746L,63747L,63748L,63749L,63750L,63751L,63752L,63753L,63754L,
63755L,63756L,63757L,63758L,63759L,63760L,63761L,63762L,63763L,63764L,
63765L,63766L,63767L,63768L,63769L,63770L,63771L,63772L,63773L,63774L,
63775L,63776L,63777L,63778L,63779L,63780L,63781L,63782L,63783L,63784L,
63785L,63786L,63787L,63788L,63789L,63790L,63791L,63792L,63793L,63794L,
63795L,63796L,63797L,63798L,63799L,63800L,63801L,63802L,63803L,63804L,
63805L,63806L,63807L,63808L,63809L,63810L,63811L,63812L,63813L,63814L,
63815L,63816L,63817L,63818L,63819L,63820L,63821L,63822L,63823L,63824L,
63825L,63826L,63827L,63828L,63829L,63830L,63831L,63832L,63833L,63834L,
63835L,63836L,63837L,63838L,63839L,63840L,63841L,63842L,63843L,63844L,
63845L,63846L,63847L,63848L,63849L,63850L,63851L,63852L,63853L,63854L,
63855L,63856L,63857L,63858L,63859L,63860L,63861L,63862L,63863L,63864L,
63865L,63866L,63867L,63868L,63869L,63870L,63871L,63872L,63873L,63874L,
63875L,63876L,63877L,63878L,63879L,63880L,63881L,63882L,63883L,63884L,
63885L,63886L,63887L,63888L,63889L,63890L,63891L,63892L,63893L,63894L,
63895L,63896L,63897L,63898L,63899L,63900L,63901L,63902L,63903L,63904L,
63905L,63906L,63907L,63908L,63909L,63910L,63911L,63912L,63913L,63914L,
63915L,63916L,63917L,63918L,63919L,63920L,63921L,63922L,63923L,63924L,
63925L,63926L,63927L,63928L,63929L,63930L,63931L,63932L,63933L,63934L,
63935L,63936L,63937L,63938L,63939L,63940L,63941L,63942L,63943L,63944L,
63945L,63946L,63947L,63948L,63949L,63950L,63951L,63952L,63953L,63954L,
63955L,63956L,63957L,63958L,63959L,63960L,63961L,63962L,63963L,63964L,
63965L,63966L,63967L,63968L,63969L,63970L,63971L,63972L,63973L,63974L,
63975L,63976L,63977L,63978L,63979L,63980L,63981L,63982L,63983L,63984L,
63985L,63986L,63987L,63988L,63989L,63990L,63991L,63992L,63993L,63994L,
63995L,63996L,63997L,63998L,63999L,64000L,64001L,64002L,64003L,64004L,
64005L,64006L,64007L,64008L,64009L,64010L,64011L,64012L,64013L,64014L,
64015L,64016L,64017L,64018L,64019L,64020L,64021L,64022L,64023L,64024L,
64025L,64026L,64027L,64028L,64029L,64030L,64031L,64032L,64033L,64034L,
64035L,64036L,64037L,64038L,64039L,64040L,64041L,64042L,64043L,64044L,
64045L,64046L,64047L,64048L,64049L,64050L,64051L,64052L,64053L,64054L,
64055L,64056L,64057L,64058L,64059L,64060L,64061L,64062L,64063L,64064L,
64065L,64066L,64067L,64068L,64069L,64070L,64071L,64072L,64073L,64074L,
64075L,64076L,64077L,64078L,64079L,64080L,64081L,64082L,64083L,64084L,
64085L,64086L,64087L,64088L,64089L,64090L,64091L,64092L,64093L,64094L,
64095L,64096L,64097L,64098L,64099L,64100L,64101L,64102L,64103L,64104L,
64105L,64106L,64107L,64108L,64109L,64110L,64111L,64112L,64113L,64114L,
64115L,64116L,64117L,64118L,64119L,64120L,64121L,64122L,64123L,64124L,
64125L,64126L,64127L,64128L,64129L,64130L,64131L,64132L,64133L,64134L,
64135L,64136L,64137L,64138L,64139L,64140L,64141L,64142L,64143L,64144L,
64145L,64146L,64147L,64148L,64149L,64150L,64151L,64152L,64153L,64154L,
64155L,64156L,64157L,64158L,64159L,64160L,64161L,64162L,64163L,64164L,
64165L,64166L,64167L,64168L,64169L,64170L,64171L,64172L,64173L,64174L,
64175L,64176L,64177L,64178L,64179L,64180L,64181L,64182L,64183L,64184L,
64185L,64186L,64187L,64188L,64189L,64190L,64191L,64192L,64193L,64194L,
64195L,64196L,64197L,64198L,64199L,64200L,64201L,64202L,64203L,64204L,
64205L,64206L,64207L,64208L,64209L,64210L,64211L,64212L,64213L,64214L,
64215L,64216L,64217L,64218L,64219L,64220L,64221L,64222L,64223L,64224L,
64225L,64226L,64227L,64228L,64229L,64230L,64231L,64232L,64233L,64234L,
64235L,64236L,64237L,64238L,64239L,64240L,64241L,64242L,64243L,64244L,
64245L,64246L,64247L,64248L,64249L,64250L,64251L,64252L,64253L,64254L,
64255L,64256L,64257L,64258L,64259L,64260L,64261L,64262L,64263L,64264L,
64265L,64266L,64267L,64268L,64269L,64270L,64271L,64272L,64273L,64274L,
64275L,64276L,64277L,64278L,64279L,64280L,64281L,64282L,64283L,64284L,
64285L,64286L,64287L,64288L,64289L,64290L,64291L,64292L,64293L,64294L,
64295L,64296L,64297L,64298L,64299L,64300L,64301L,64302L,64303L,64304L,
64305L,64306L,64307L,64308L,64309L,64310L,64311L,64312L,64313L,64314L,
64315L,64316L,64317L,64318L,64319L,64320L,64321L,64322L,64323L,64324L,
64325L,64326L,64327L,64328L,64329L,64330L,64331L,64332L,64333L,64334L,
64335L,64336L,64337L,64338L,64339L,64340L,64341L,64342L,64343L,64344L,
64345L,64346L,64347L,64348L,64349L,64350L,64351L,64352L,64353L,64354L,
64355L,64356L,64357L,64358L,64359L,64360L,64361L,64362L,64363L,64364L,
64365L,64366L,64367L,64368L,64369L,64370L,64371L,64372L,64373L,64374L,
64375L,64376L,64377L,64378L,64379L,64380L,64381L,64382L,64383L,64384L,
64385L,64386L,64387L,64388L,64389L,64390L,64391L,64392L,64393L,64394L,
64395L,64396L,64397L,64398L,64399L,64400L,64401L,64402L,64403L,64404L,
64405L,64406L,64407L,64408L,64409L,64410L,64411L,64412L,64413L,64414L,
64415L,64416L,64417L,64418L,64419L,64420L,64421L,64422L,64423L,64424L,
64425L,64426L,64427L,64428L,64429L,64430L,64431L,64432L,64433L,64434L,
64435L,64436L,64437L,64438L,64439L,64440L,64441L,64442L,64443L,64444L,
64445L,64446L,64447L,64448L,64449L,64450L,64451L,64452L,64453L,64454L,
64455L,64456L,64457L,64458L,64459L,64460L,64461L,64462L,64463L,64464L,
64465L,64466L,64467L,64468L,64469L,64470L,64471L,64472L,64473L,64474L,
64475L,64476L,64477L,64478L,64479L,64480L,64481L,64482L,64483L,64484L,
64485L,64486L,64487L,64488L,64489L,64490L,64491L,64492L,64493L,64494L,
64495L,64496L,64497L,64498L,64499L,64500L,64501L,64502L,64503L,64504L,
64505L,64506L,64507L,64508L,64509L,64510L,64511L,64512L,64513L,64514L,
64515L,64516L,64517L,64518L,64519L,64520L,64521L,64522L,64523L,64524L,
64525L,64526L,64527L,64528L,64529L,64530L,64531L,64532L,64533L,64534L,
64535L,64536L,64537L,64538L,64539L,64540L,64541L,64542L,64543L,64544L,
64545L,64546L,64547L,64548L,64549L,64550L,64551L,64552L,64553L,64554L,
64555L,64556L,64557L,64558L,64559L,64560L,64561L,64562L,64563L,64564L,
64565L,64566L,64567L,64568L,64569L,64570L,64571L,64572L,64573L,64574L,
64575L,64576L,64577L,64578L,64579L,64580L,64581L,64582L,64583L,64584L,
64585L,64586L,64587L,64588L,64589L,64590L,64591L,64592L,64593L,64594L,
64595L,64596L,64597L,64598L,64599L,64600L,64601L,64602L,64603L,64604L,
64605L,64606L,64607L,64608L,64609L,64610L,64611L,64612L,64613L,64614L,
64615L,64616L,64617L,64618L,64619L,64620L,64621L,64622L,64623L,64624L,
64625L,64626L,64627L,64628L,64629L,64630L,64631L,64632L,64633L,64634L,
64635L,64636L,64637L,64638L,64639L,64640L,64641L,64642L,64643L,64644L,
64645L,64646L,64647L,64648L,64649L,64650L,64651L,64652L,64653L,64654L,
64655L,64656L,64657L,64658L,64659L,64660L,64661L,64662L,64663L,64664L,
64665L,64666L,64667L,64668L,64669L,64670L,64671L,64672L,64673L,64674L,
64675L,64676L,64677L,64678L,64679L,64680L,64681L,64682L,64683L,64684L,
64685L,64686L,64687L,64688L,64689L,64690L,64691L,64692L,64693L,64694L,
64695L,64696L,64697L,64698L,64699L,64700L,64701L,64702L,64703L,64704L,
64705L,64706L,64707L,64708L,64709L,64710L,64711L,64712L,64713L,64714L,
64715L,64716L,64717L,64718L,64719L,64720L,64721L,64722L,64723L,64724L,
64725L,64726L,64727L,64728L,64729L,64730L,64731L,64732L,64733L,64734L,
64735L,64736L,64737L,64738L,64739L,64740L,64741L,64742L,64743L,64744L,
64745L,64746L,64747L,64748L,64749L,64750L,64751L,64752L,64753L,64754L,
64755L,64756L,64757L,64758L,64759L,64760L,64761L,64762L,64763L,64764L,
64765L,64766L,64767L,64768L,64769L,64770L,64771L,64772L,64773L,64774L,
64775L,64776L,64777L,64778L,64779L,64780L,64781L,64782L,64783L,64784L,
64785L,64786L,64787L,64788L,64789L,64790L,64791L,64792L,64793L,64794L,
64795L,64796L,64797L,64798L,64799L,64800L,64801L,64802L,64803L,64804L,
64805L,64806L,64807L,64808L,64809L,64810L,64811L,64812L,64813L,64814L,
64815L,64816L,64817L,64818L,64819L,64820L,64821L,64822L,64823L,64824L,
64825L,64826L,64827L,64828L,64829L,64830L,64831L,64832L,64833L,64834L,
64835L,64836L,64837L,64838L,64839L,64840L,64841L,64842L,64843L,64844L,
64845L,64846L,64847L,64848L,64849L,64850L,64851L,64852L,64853L,64854L,
64855L,64856L,64857L,64858L,64859L,64860L,64861L,64862L,64863L,64864L,
64865L,64866L,64867L,64868L,64869L,64870L,64871L,64872L,64873L,64874L,
64875L,64876L,64877L,64878L,64879L,64880L,64881L,64882L,64883L,64884L,
64885L,64886L,64887L,64888L,64889L,64890L,64891L,64892L,64893L,64894L,
64895L,64896L,64897L,64898L,64899L,64900L,64901L,64902L,64903L,64904L,
64905L,64906L,64907L,64908L,64909L,64910L,64911L,64912L,64913L,64914L,
64915L,64916L,64917L,64918L,64919L,64920L,64921L,64922L,64923L,64924L,
64925L,64926L,64927L,64928L,64929L,64930L,64931L,64932L,64933L,64934L,
64935L,64936L,64937L,64938L,64939L,64940L,64941L,64942L,64943L,64944L,
64945L,64946L,64947L,64948L,64949L,64950L,64951L,64952L,64953L,64954L,
64955L,64956L,64957L,64958L,64959L,64960L,64961L,64962L,64963L,64964L,
64965L,64966L,64967L,64968L,64969L,64970L,64971L,64972L,64973L,64974L,
64975L,64976L,64977L,64978L,64979L,64980L,64981L,64982L,64983L,64984L,
64985L,64986L,64987L,64988L,64989L,64990L,64991L,64992L,64993L,64994L,
64995L,64996L,64997L,64998L,64999L,65000L,65001L,65002L,65003L,65004L,
65005L,65006L,65007L,65008L,65009L,65010L,65011L,65012L,65013L,65014L,
65015L,65016L,65017L,65018L,65019L,65020L,65021L,65022L,65023L,65024L,
65025L,65026L,65027L,65028L,65029L,65030L,65031L,65032L,65033L,65034L,
65035L,65036L,65037L,65038L,65039L,65040L,65041L,65042L,65043L,65044L,
65045L,65046L,65047L,65048L,65049L,65050L,65051L,65052L,65053L,65054L,
65055L,65056L,65057L,65058L,65059L,65060L,65061L,65062L,65063L,65064L,
65065L,65066L,65067L,65068L,65069L,65070L,65071L,65072L,65073L,65074L,
65075L,65076L,65077L,65078L,65079L,65080L,65081L,65082L,65083L,65084L,
65085L,65086L,65087L,65088L,65089L,65090L,65091L,65092L,65093L,65094L,
65095L,65096L,65097L,65098L,65099L,65100L,65101L,65102L,65103L,65104L,
65105L,65106L,65107L,65108L,65109L,65110L,65111L,65112L,65113L,65114L,
65115L,65116L,65117L,65118L,65119L,65120L,65121L,65122L,65123L,65124L,
65125L,65126L,65127L,65128L,65129L,65130L,65131L,65132L,65133L,65134L,
65135L,65136L,65137L,65138L,65139L,65140L,65141L,65142L,65143L,65144L,
65145L,65146L,65147L,65148L,65149L,65150L,65151L,65152L,65153L,65154L,
65155L,65156L,65157L,65158L,65159L,65160L,65161L,65162L,65163L,65164L,
65165L,65166L,65167L,65168L,65169L,65170L,65171L,65172L,65173L,65174L,
65175L,65176L,65177L,65178L,65179L,65180L,65181L,65182L,65183L,65184L,
65185L,65186L,65187L,65188L,65189L,65190L,65191L,65192L,65193L,65194L,
65195L,65196L,65197L,65198L,65199L,65200L,65201L,65202L,65203L,65204L,
65205L,65206L,65207L,65208L,65209L,65210L,65211L,65212L,65213L,65214L,
65215L,65216L,65217L,65218L,65219L,65220L,65221L,65222L,65223L,65224L,
65225L,65226L,65227L,65228L,65229L,65230L,65231L,65232L,65233L,65234L,
65235L,65236L,65237L,65238L,65239L,65240L,65241L,65242L,65243L,65244L,
65245L,65246L,65247L,65248L,65249L,65250L,65251L,65252L,65253L,65254L,
65255L,65256L,65257L,65258L,65259L,65260L,65261L,65262L,65263L,65264L,
65265L,65266L,65267L,65268L,65269L,65270L,65271L,65272L,65273L,65274L,
65275L,65276L,65277L,65278L,65279L,65280L,65281L,65282L,65283L,65284L,
65285L,65286L,65287L,65288L,65289L,65290L,65291L,65292L,65293L,65294L,
65295L,65296L,65297L,65298L,65299L,65300L,65301L,65302L,65303L,65304L,
65305L,65306L,65307L,65308L,65309L,65310L,65311L,65312L,65313L,65314L,
65315L,65316L,65317L,65318L,65319L,65320L,65321L,65322L,65323L,65324L,
65325L,65326L,65327L,65328L,65329L,65330L,65331L,65332L,65333L,65334L,
65335L,65336L,65337L,65338L,65339L,65340L,65341L,65342L,65343L,65344L,
65313L,65314L,65315L,65316L,65317L,65318L,65319L,65320L,65321L,65322L,
65323L,65324L,65325L,65326L,65327L,65328L,65329L,65330L,65331L,65332L,
65333L,65334L,65335L,65336L,65337L,65338L,65371L,65372L,65373L,65374L,
65375L,65376L,65377L,65378L,65379L,65380L,65381L,65382L,65383L,65384L,
65385L,65386L,65387L,65388L,65389L,65390L,65391L,65392L,65393L,65394L,
65395L,65396L,65397L,65398L,65399L,65400L,65401L,65402L,65403L,65404L,
65405L,65406L,65407L,65408L,65409L,65410L,65411L,65412L,65413L,65414L,
65415L,65416L,65417L,65418L,65419L,65420L,65421L,65422L,65423L,65424L,
65425L,65426L,65427L,65428L,65429L,65430L,65431L,65432L,65433L,65434L,
65435L,65436L,65437L,65438L,65439L,65440L,65441L,65442L,65443L,65444L,
65445L,65446L,65447L,65448L,65449L,65450L,65451L,65452L,65453L,65454L,
65455L,65456L,65457L,65458L,65459L,65460L,65461L,65462L,65463L,65464L,
65465L,65466L,65467L,65468L,65469L,65470L,65471L,65472L,65473L,65474L,
65475L,65476L,65477L,65478L,65479L,65480L,65481L,65482L,65483L,65484L,
65485L,65486L,65487L,65488L,65489L,65490L,65491L,65492L,65493L,65494L,
65495L,65496L,65497L,65498L,65499L,65500L,65501L,65502L,65503L,65504L,
65505L,65506L,65507L,65508L,65509L,65510L,65511L,65512L,65513L,65514L,
65515L,65516L,65517L,65518L,65519L,65520L,65521L,65522L,65523L,65524L,
65525L,65526L,65527L,65528L,65529L,65530L,65531L,65532L,65533L,65534L,
65535L,
};
#endif

#if defined(DUK_USE_REGEXP_CANON_BITMAP)
/*
 *  Automatically generated by extract_caseconv.py, do not edit!
 */

const duk_uint8_t duk_unicode_re_canon_bitmap[256] = {
23,0,224,19,1,228,255,255,255,255,255,255,255,255,255,255,63,254,255,127,
255,255,255,255,255,255,255,255,231,231,0,16,255,227,255,255,63,255,255,
255,255,255,255,255,1,252,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
227,129,255,255,255,147,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,251,
};
#endif
#line 1 "duk_util_bitdecoder.c"
/*
 *  Bitstream decoder.
 */

/* #include duk_internal.h -> already included */

/* Decode 'bits' bits from the input stream (bits must be 1...24).
 * When reading past bitstream end, zeroes are shifted in.  The result
 * is signed to match duk_bd_decode_flagged.
 */
DUK_INTERNAL duk_uint32_t duk_bd_decode(duk_bitdecoder_ctx *ctx, duk_small_int_t bits) {
	duk_small_int_t shift;
	duk_uint32_t mask;
	duk_uint32_t tmp;

	/* Note: cannot read more than 24 bits without possibly shifting top bits out.
	 * Fixable, but adds complexity.
	 */
	DUK_ASSERT(bits >= 1 && bits <= 24);

	while (ctx->currbits < bits) {
#if 0
		DUK_DDD(DUK_DDDPRINT("decode_bits: shift more data (bits=%ld, currbits=%ld)",
		                     (long) bits, (long) ctx->currbits));
#endif
		ctx->currval <<= 8;
		if (ctx->offset < ctx->length) {
			/* If ctx->offset >= ctx->length, we "shift zeroes in"
			 * instead of croaking.
			 */
			ctx->currval |= ctx->data[ctx->offset++];
		}
		ctx->currbits += 8;
	}
#if 0
	DUK_DDD(DUK_DDDPRINT("decode_bits: bits=%ld, currbits=%ld, currval=0x%08lx",
	                     (long) bits, (long) ctx->currbits, (unsigned long) ctx->currval));
#endif

	/* Extract 'top' bits of currval; note that the extracted bits do not need
	 * to be cleared, we just ignore them on next round.
	 */
	shift = ctx->currbits - bits;
	mask = (((duk_uint32_t) 1U) << bits) - 1U;
	tmp = (ctx->currval >> shift) & mask;
	ctx->currbits = shift;  /* remaining */

#if 0
	DUK_DDD(DUK_DDDPRINT("decode_bits: %ld bits -> 0x%08lx (%ld), currbits=%ld, currval=0x%08lx",
	                     (long) bits, (unsigned long) tmp, (long) tmp, (long) ctx->currbits, (unsigned long) ctx->currval));
#endif

	return tmp;
}

DUK_INTERNAL duk_small_uint_t duk_bd_decode_flag(duk_bitdecoder_ctx *ctx) {
	return (duk_small_uint_t) duk_bd_decode(ctx, 1);
}

/* Decode a one-bit flag, and if set, decode a value of 'bits', otherwise return
 * default value.
 */
DUK_INTERNAL duk_uint32_t duk_bd_decode_flagged(duk_bitdecoder_ctx *ctx, duk_small_int_t bits, duk_uint32_t def_value) {
	if (duk_bd_decode_flag(ctx)) {
		return duk_bd_decode(ctx, bits);
	} else {
		return def_value;
	}
}

/* Signed variant, allows negative marker value. */
DUK_INTERNAL duk_int32_t duk_bd_decode_flagged_signed(duk_bitdecoder_ctx *ctx, duk_small_int_t bits, duk_int32_t def_value) {
	return (duk_int32_t) duk_bd_decode_flagged(ctx, bits, (duk_uint32_t) def_value);
}

/* Shared varint encoding.  Match dukutil.py BitEncode.varuint(). */
DUK_INTERNAL duk_uint32_t duk_bd_decode_varuint(duk_bitdecoder_ctx *ctx) {
	duk_small_uint_t t;

	/* The bit encoding choices here are based on manual testing against
	 * the actual varuints generated by genbuiltins.py.
	 */
	switch (duk_bd_decode(ctx, 2)) {
	case 0:
		return 0;  /* [0,0] */
	case 1:
		return duk_bd_decode(ctx, 2) + 1;  /* [1,4] */
	case 2:
		return duk_bd_decode(ctx, 5) + 5;  /* [5,36] */
	default:
		t = duk_bd_decode(ctx, 7);
		if (t == 0) {
			return duk_bd_decode(ctx, 20);
		}
		return (t - 1) + 37;  /* [37,163] */
	}
}

/* Decode a bit packed string from a custom format used by genbuiltins.py.
 * This function is here because it's used for both heap and thread inits.
 * Caller must supply the output buffer whose size is NOT checked!
 */

#define DUK__BITPACK_LETTER_LIMIT  26
#define DUK__BITPACK_LOOKUP1       26
#define DUK__BITPACK_LOOKUP2       27
#define DUK__BITPACK_SWITCH1       28
#define DUK__BITPACK_SWITCH        29
#define DUK__BITPACK_UNUSED1       30
#define DUK__BITPACK_EIGHTBIT      31

DUK_LOCAL const duk_uint8_t duk__bitpacked_lookup[16] = {
	DUK_ASC_0, DUK_ASC_1, DUK_ASC_2, DUK_ASC_3,
	DUK_ASC_4, DUK_ASC_5, DUK_ASC_6, DUK_ASC_7,
	DUK_ASC_8, DUK_ASC_9, DUK_ASC_UNDERSCORE, DUK_ASC_SPACE,
	0x82, 0x80, DUK_ASC_DOUBLEQUOTE, DUK_ASC_LCURLY
};

DUK_INTERNAL duk_small_uint_t duk_bd_decode_bitpacked_string(duk_bitdecoder_ctx *bd, duk_uint8_t *out) {
	duk_small_uint_t len;
	duk_small_uint_t mode;
	duk_small_uint_t t;
	duk_small_uint_t i;

	len = duk_bd_decode(bd, 5);
	if (len == 31) {
		len = duk_bd_decode(bd, 8);  /* Support up to 256 bytes; rare. */
	}

	mode = 32;  /* 0 = uppercase, 32 = lowercase (= 'a' - 'A') */
	for (i = 0; i < len; i++) {
		t = duk_bd_decode(bd, 5);
		if (t < DUK__BITPACK_LETTER_LIMIT) {
			t = t + DUK_ASC_UC_A + mode;
		} else if (t == DUK__BITPACK_LOOKUP1) {
			t = duk__bitpacked_lookup[duk_bd_decode(bd, 3)];
		} else if (t == DUK__BITPACK_LOOKUP2) {
			t = duk__bitpacked_lookup[8 + duk_bd_decode(bd, 3)];
		} else if (t == DUK__BITPACK_SWITCH1) {
			t = duk_bd_decode(bd, 5);
			DUK_ASSERT_DISABLE(t >= 0);  /* unsigned */
			DUK_ASSERT(t <= 25);
			t = t + DUK_ASC_UC_A + (mode ^ 32);
		} else if (t == DUK__BITPACK_SWITCH) {
			mode = mode ^ 32;
			t = duk_bd_decode(bd, 5);
			DUK_ASSERT_DISABLE(t >= 0);
			DUK_ASSERT(t <= 25);
			t = t + DUK_ASC_UC_A + mode;
		} else if (t == DUK__BITPACK_EIGHTBIT) {
			t = duk_bd_decode(bd, 8);
		}
		out[i] = (duk_uint8_t) t;
	}

	return len;
}

/* automatic undefs */
#undef DUK__BITPACK_EIGHTBIT
#undef DUK__BITPACK_LETTER_LIMIT
#undef DUK__BITPACK_LOOKUP1
#undef DUK__BITPACK_LOOKUP2
#undef DUK__BITPACK_SWITCH
#undef DUK__BITPACK_SWITCH1
#undef DUK__BITPACK_UNUSED1
#line 1 "duk_util_bitencoder.c"
/*
 *  Bitstream encoder.
 */

/* #include duk_internal.h -> already included */

DUK_INTERNAL void duk_be_encode(duk_bitencoder_ctx *ctx, duk_uint32_t data, duk_small_int_t bits) {
	duk_uint8_t tmp;

	DUK_ASSERT(ctx != NULL);
	DUK_ASSERT(ctx->currbits < 8);

	/* This limitation would be fixable but adds unnecessary complexity. */
	DUK_ASSERT(bits >= 1 && bits <= 24);

	ctx->currval = (ctx->currval << bits) | data;
	ctx->currbits += bits;

	while (ctx->currbits >= 8) {
		if (ctx->offset < ctx->length) {
			tmp = (duk_uint8_t) ((ctx->currval >> (ctx->currbits - 8)) & 0xff);
			ctx->data[ctx->offset++] = tmp;
		} else {
			/* If buffer has been exhausted, truncate bitstream */
			ctx->truncated = 1;
		}

		ctx->currbits -= 8;
	}
}

DUK_INTERNAL void duk_be_finish(duk_bitencoder_ctx *ctx) {
	duk_small_int_t npad;

	DUK_ASSERT(ctx != NULL);
	DUK_ASSERT(ctx->currbits < 8);

	npad = (duk_small_int_t) (8 - ctx->currbits);
	if (npad > 0) {
		duk_be_encode(ctx, 0, npad);
	}
	DUK_ASSERT(ctx->currbits == 0);
}
#line 1 "duk_util_bufwriter.c"
/*
 *  Fast buffer writer with slack management.
 */

/* #include duk_internal.h -> already included */

/* XXX: Avoid duk_{memcmp,memmove}_unsafe() by imposing a minimum length of
 * >0 for the underlying dynamic buffer.
 */

/*
 *  Macro support functions (use only macros in calling code)
 */

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) {
	duk_uint8_t *p;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(bw_ctx != NULL);
	DUK_UNREF(thr);

	/* 'p' might be NULL when the underlying buffer is zero size.  If so,
	 * the resulting pointers are not used unsafely.
	 */
	p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, bw_ctx->buf);
	DUK_ASSERT(p != NULL || (DUK_HBUFFER_DYNAMIC_GET_SIZE(bw_ctx->buf) == 0 && curr_offset == 0 && new_length == 0));
	bw_ctx->p = p + curr_offset;
	bw_ctx->p_base = p;
	bw_ctx->p_limit = p + new_length;
}

DUK_INTERNAL void duk_bw_init(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_hbuffer_dynamic *h_buf) {
	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(bw_ctx != NULL);
	DUK_ASSERT(h_buf != NULL);

	bw_ctx->buf = h_buf;
	duk__bw_update_ptrs(thr, bw_ctx, 0, DUK_HBUFFER_DYNAMIC_GET_SIZE(h_buf));
}

DUK_INTERNAL void duk_bw_init_pushbuf(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t buf_size) {
	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(bw_ctx != NULL);

	(void) duk_push_dynamic_buffer(thr, buf_size);
	bw_ctx->buf = (duk_hbuffer_dynamic *) duk_known_hbuffer(thr, -1);
	DUK_ASSERT(bw_ctx->buf != NULL);
	duk__bw_update_ptrs(thr, bw_ctx, 0, buf_size);
}

/* Resize target buffer for requested size.  Called by the macro only when the
 * fast path test (= there is space) fails.
 */
DUK_INTERNAL duk_uint8_t *duk_bw_resize(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t sz) {
	duk_size_t curr_off;
	duk_size_t add_sz;
	duk_size_t new_sz;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(bw_ctx != NULL);

	/* We could do this operation without caller updating bw_ctx->ptr,
	 * but by writing it back here we can share code better.
	 */

	curr_off = (duk_size_t) (bw_ctx->p - bw_ctx->p_base);
	add_sz = (curr_off >> DUK_BW_SLACK_SHIFT) + DUK_BW_SLACK_ADD;
	new_sz = curr_off + sz + add_sz;
	if (DUK_UNLIKELY(new_sz < curr_off)) {
		/* overflow */
		DUK_ERROR_RANGE(thr, DUK_STR_BUFFER_TOO_LONG);
		DUK_WO_NORETURN(return NULL;);
	}
#if 0  /* for manual torture testing: tight allocation, useful with valgrind */
	new_sz = curr_off + sz;
#endif

	/* This is important to ensure dynamic buffer data pointer is not
	 * NULL (which is possible if buffer size is zero), which in turn
	 * causes portability issues with e.g. memmove() and memcpy().
	 */
	DUK_ASSERT(new_sz >= 1);

	DUK_DD(DUK_DDPRINT("resize bufferwriter from %ld to %ld (add_sz=%ld)", (long) curr_off, (long) new_sz, (long) add_sz));

	duk_hbuffer_resize(thr, bw_ctx->buf, new_sz);
	duk__bw_update_ptrs(thr, bw_ctx, curr_off, new_sz);
	return bw_ctx->p;
}

/* Make buffer compact, matching current written size. */
DUK_INTERNAL void duk_bw_compact(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx) {
	duk_size_t len;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(bw_ctx != NULL);
	DUK_UNREF(thr);

	len = (duk_size_t) (bw_ctx->p - bw_ctx->p_base);
	duk_hbuffer_resize(thr, bw_ctx->buf, len);
	duk__bw_update_ptrs(thr, bw_ctx, len, len);
}

DUK_INTERNAL void duk_bw_write_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t src_off, duk_size_t len) {
	duk_uint8_t *p_base;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(bw != NULL);
	DUK_ASSERT(src_off <= DUK_BW_GET_SIZE(thr, bw));
	DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
	DUK_ASSERT(src_off + len <= DUK_BW_GET_SIZE(thr, bw));
	DUK_UNREF(thr);

	p_base = bw->p_base;
	duk_memcpy_unsafe((void *) bw->p,
	                  (const void *) (p_base + src_off),
	                  (size_t) len);
	bw->p += len;
}

DUK_INTERNAL void duk_bw_write_ensure_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t src_off, duk_size_t len) {
	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(bw != NULL);
	DUK_ASSERT(src_off <= DUK_BW_GET_SIZE(thr, bw));
	DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
	DUK_ASSERT(src_off + len <= DUK_BW_GET_SIZE(thr, bw));

	DUK_BW_ENSURE(thr, bw, len);
	duk_bw_write_raw_slice(thr, bw, src_off, len);
}

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) {
	duk_uint8_t *p_base;
	duk_size_t buf_sz, move_sz;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(bw != NULL);
	DUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw));
	DUK_ASSERT(buf != NULL);
	DUK_UNREF(thr);

	p_base = bw->p_base;
	buf_sz = (duk_size_t) (bw->p - p_base);  /* constrained by maximum buffer size */
	move_sz = buf_sz - dst_off;

	DUK_ASSERT(p_base != NULL);  /* buffer size is >= 1 */
	duk_memmove_unsafe((void *) (p_base + dst_off + len),
	                   (const void *) (p_base + dst_off),
	                   (size_t) move_sz);
	duk_memcpy_unsafe((void *) (p_base + dst_off),
	                  (const void *) buf,
	                  (size_t) len);
	bw->p += len;
}

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) {
	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(bw != NULL);
	DUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw));
	DUK_ASSERT(buf != NULL);

	DUK_BW_ENSURE(thr, bw, len);
	duk_bw_insert_raw_bytes(thr, bw, dst_off, buf, len);
}

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) {
	duk_uint8_t *p_base;
	duk_size_t buf_sz, move_sz;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(bw != NULL);
	DUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw));
	DUK_ASSERT(src_off <= DUK_BW_GET_SIZE(thr, bw));
	DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
	DUK_ASSERT(src_off + len <= DUK_BW_GET_SIZE(thr, bw));
	DUK_UNREF(thr);

	p_base = bw->p_base;

	/* Don't support "straddled" source now. */
	DUK_ASSERT(dst_off <= src_off || dst_off >= src_off + len);

	if (dst_off <= src_off) {
		/* Target is before source.  Source offset is expressed as
		 * a "before change" offset.  Account for the memmove.
		 */
		src_off += len;
	}

	buf_sz = (duk_size_t) (bw->p - p_base);
	move_sz = buf_sz - dst_off;

	DUK_ASSERT(p_base != NULL);  /* buffer size is >= 1 */
	duk_memmove_unsafe((void *) (p_base + dst_off + len),
	                   (const void *) (p_base + dst_off),
	                   (size_t) move_sz);
	duk_memcpy_unsafe((void *) (p_base + dst_off),
	                  (const void *) (p_base + src_off),
	                  (size_t) len);
	bw->p += len;
}

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) {
	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(bw != NULL);
	DUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw));
	DUK_ASSERT(src_off <= DUK_BW_GET_SIZE(thr, bw));
	DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
	DUK_ASSERT(src_off + len <= DUK_BW_GET_SIZE(thr, bw));

	/* Don't support "straddled" source now. */
	DUK_ASSERT(dst_off <= src_off || dst_off >= src_off + len);

	DUK_BW_ENSURE(thr, bw, len);
	duk_bw_insert_raw_slice(thr, bw, dst_off, src_off, len);
}

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) {
	duk_uint8_t *p_base, *p_dst, *p_src;
	duk_size_t buf_sz, move_sz;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(bw != NULL);
	DUK_ASSERT(off <= DUK_BW_GET_SIZE(thr, bw));
	DUK_UNREF(thr);

	p_base = bw->p_base;
	buf_sz = (duk_size_t) (bw->p - p_base);
	move_sz = buf_sz - off;
	p_dst = p_base + off + len;
	p_src = p_base + off;
	duk_memmove_unsafe((void *) p_dst, (const void *) p_src, (size_t) move_sz);
	return p_src;  /* point to start of 'reserved area' */
}

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) {
	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(bw != NULL);
	DUK_ASSERT(off <= DUK_BW_GET_SIZE(thr, bw));

	DUK_BW_ENSURE(thr, bw, len);
	return duk_bw_insert_raw_area(thr, bw, off, len);
}

DUK_INTERNAL void duk_bw_remove_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len) {
	duk_size_t move_sz;

	duk_uint8_t *p_base;
	duk_uint8_t *p_src;
	duk_uint8_t *p_dst;

	DUK_ASSERT(thr != NULL);
	DUK_ASSERT(bw != NULL);
	DUK_ASSERT(off <= DUK_BW_GET_SIZE(thr, bw));
	DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
	DUK_ASSERT(off + len <= DUK_BW_GET_SIZE(thr, bw));
	DUK_UNREF(thr);

	p_base = bw->p_base;
	p_dst = p_base + off;
	p_src = p_dst + len;
	move_sz = (duk_size_t) (bw->p - p_src);
	duk_memmove_unsafe((void *) p_dst,
	                   (const void *) p_src,
	                   (size_t) move_sz);
	bw->p -= len;
}

/*
 *  Assertion helpers
 */

#if defined(DUK_USE_ASSERTIONS)
DUK_INTERNAL void duk_bw_assert_valid(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx) {
	DUK_UNREF(thr);
	DUK_ASSERT(bw_ctx != NULL);
	DUK_ASSERT(bw_ctx->buf != NULL);
	DUK_ASSERT((DUK_HBUFFER_DYNAMIC_GET_SIZE(bw_ctx->buf) == 0) ||
	           (bw_ctx->p != NULL &&
	            bw_ctx->p_base != NULL &&
	            bw_ctx->p_limit != NULL &&
	            bw_ctx->p_limit >= bw_ctx->p_base &&
	            bw_ctx->p >= bw_ctx->p_base &&
	            bw_ctx->p <= bw_ctx->p_limit));
}
#endif
#line 1 "duk_util_cast.c"
/*
 *  Cast helpers.
 *
 *  C99+ coercion is challenging portability-wise because out-of-range casts
 *  may invoke implementation defined or even undefined behavior.  See e.g.
 *  http://blog.frama-c.com/index.php?post/2013/10/09/Overflow-float-integer.
 *
 *  Provide explicit cast helpers which try to avoid implementation defined
 *  or undefined behavior.  These helpers can then be simplified in the vast
 *  majority of cases where the implementation defined or undefined behavior
 *  is not problematic.
 */

/* #include duk_internal.h -> already included */

/* Portable double-to-integer cast which avoids undefined behavior and avoids
 * relying on fmin(), fmax(), or other intrinsics.  Out-of-range results are
 * not assumed by caller, but here value is clamped, NaN converts to minval.
 */
#define DUK__DOUBLE_INT_CAST1(tname,minval,maxval)  do { \
		if (DUK_LIKELY(x >= (duk_double_t) (minval))) { \
			DUK_ASSERT(!DUK_ISNAN(x)); \
			if (DUK_LIKELY(x <= (duk_double_t) (maxval))) { \
				return (tname) x; \
			} else { \
				return (tname) (maxval); \
			} \
		} else { \
			/* NaN or below minval.  Since we don't care about the result \
			 * for out-of-range values, just return the minimum value for \
			 * both. \
			 */ \
			return (tname) (minval); \
		} \
	} while (0)

/* Rely on specific NaN behavior for duk_double_{fmin,fmax}(): if either
 * argument is a NaN, return the second argument.  This avoids a
 * NaN-to-integer cast which is undefined behavior.
 */
#define DUK__DOUBLE_INT_CAST2(tname,minval,maxval)  do { \
		return (tname) duk_double_fmin(duk_double_fmax(x, (duk_double_t) (minval)), (duk_double_t) (maxval)); \
	} while (0)

/* Another solution which doesn't need C99+ behavior for fmin() and fmax(). */
#define DUK__DOUBLE_INT_CAST3(tname,minval,maxval)  do { \
		if (DUK_ISNAN(x)) { \
			/* 0 or any other value is fine. */ \
			return (tname) 0; \
		} else \
			return (tname) DUK_FMIN(DUK_FMAX(x, (duk_double_t) (minval)), (duk_double_t) (maxval)); \
		} \
	} while (0)

/* C99+ solution: relies on specific fmin() and fmax() behavior in C99: if
 * one argument is NaN but the other isn't, the non-NaN argument is returned.
 * Because the limits are non-NaN values, explicit NaN check is not needed.
 * This may not work on all legacy platforms, and also doesn't seem to inline
 * the fmin() and fmax() calls (unless one uses -ffast-math which we don't
 * support).
 */
#define DUK__DOUBLE_INT_CAST4(tname,minval,maxval)  do { \
		return (tname) DUK_FMIN(DUK_FMAX(x, (duk_double_t) (minval)), (duk_double_t) (maxval)); \
	} while (0)

DUK_INTERNAL duk_int_t duk_double_to_int_t(duk_double_t x) {
#if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
	/* Real world solution: almost any practical platform will provide
	 * an integer value without any guarantees what it is (which is fine).
	 */
	return (duk_int_t) x;
#else
	DUK__DOUBLE_INT_CAST1(duk_int_t, DUK_INT_MIN, DUK_INT_MAX);
#endif
}

DUK_INTERNAL duk_uint_t duk_double_to_uint_t(duk_double_t x) {
#if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
	return (duk_uint_t) x;
#else
	DUK__DOUBLE_INT_CAST1(duk_uint_t, DUK_UINT_MIN, DUK_UINT_MAX);
#endif
}

DUK_INTERNAL duk_int32_t duk_double_to_int32_t(duk_double_t x) {
#if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
	return (duk_int32_t) x;
#else
	DUK__DOUBLE_INT_CAST1(duk_int32_t, DUK_INT32_MIN, DUK_INT32_MAX);
#endif
}

DUK_INTERNAL duk_uint32_t duk_double_to_uint32_t(duk_double_t x) {
#if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
	return (duk_uint32_t) x;
#else
	DUK__DOUBLE_INT_CAST1(duk_uint32_t, DUK_UINT32_MIN, DUK_UINT32_MAX);
#endif
}

/* Largest IEEE double that doesn't round to infinity in the default rounding
 * mode.  The exact midpoint between (1 - 2^(-24)) * 2^128 and 2^128 rounds to
 * infinity, at least on x64.  This number is one double unit below that
 * midpoint.  See misc/float_cast.c.
 */
#define DUK__FLOAT_ROUND_LIMIT      340282356779733623858607532500980858880.0

/* Maximum IEEE float.  Double-to-float conversion above this would be out of
 * range and thus technically undefined behavior.
 */
#define DUK__FLOAT_MAX              340282346638528859811704183484516925440.0

DUK_INTERNAL duk_float_t duk_double_to_float_t(duk_double_t x) {
	/* Even a double-to-float cast is technically undefined behavior if
	 * the double is out-of-range.  C99 Section 6.3.1.5:
	 *
	 *   If the value being converted is in the range of values that can
	 *   be represented but cannot be represented exactly, the result is
	 *   either the nearest higher or nearest lower representable value,
	 *   chosen in an implementation-defined manner.  If the value being
	 *   converted is outside the range of values that can be represented,
	 *   the behavior is undefined.
	 */
#if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
	return (duk_float_t) x;
#else
	duk_double_t t;

	t = DUK_FABS(x);
	DUK_ASSERT((DUK_ISNAN(x) && DUK_ISNAN(t)) ||
	           (!DUK_ISNAN(x) && !DUK_ISNAN(t)));

	if (DUK_LIKELY(t <= DUK__FLOAT_MAX)) {
		/* Standard in-range case, try to get here with a minimum
		 * number of checks and branches.
		 */
		DUK_ASSERT(!DUK_ISNAN(x));
		return (duk_float_t) x;
	} else if (t <= DUK__FLOAT_ROUND_LIMIT) {
		/* Out-of-range, but rounds to min/max float. */
		DUK_ASSERT(!DUK_ISNAN(x));
		if (x < 0.0) {
			return (duk_float_t) -DUK__FLOAT_MAX;
		} else {
			return (duk_float_t) DUK__FLOAT_MAX;
		}
	} else if (DUK_ISNAN(x)) {
		/* Assumes double NaN -> float NaN considered "in range". */
		DUK_ASSERT(DUK_ISNAN(x));
		return (duk_float_t) x;
	} else {
		/* Out-of-range, rounds to +/- Infinity. */
		if (x < 0.0) {
			return (duk_float_t) -DUK_DOUBLE_INFINITY;
		} else {
			return (duk_float_t) DUK_DOUBLE_INFINITY;
		}
	}
#endif
}

/* automatic undefs */
#undef DUK__DOUBLE_INT_CAST1
#undef DUK__DOUBLE_INT_CAST2
#undef DUK__DOUBLE_INT_CAST3
#undef DUK__DOUBLE_INT_CAST4
#undef DUK__FLOAT_MAX
#undef DUK__FLOAT_ROUND_LIMIT
#line 1 "duk_util_double.c"
/*
 *  IEEE double helpers.
 */

/* #include duk_internal.h -> already included */

DUK_INTERNAL duk_bool_t duk_double_is_anyinf(duk_double_t x) {
	duk_double_union du;
	du.d = x;
	return DUK_DBLUNION_IS_ANYINF(&du);
}

DUK_INTERNAL duk_bool_t duk_double_is_posinf(duk_double_t x) {
	duk_double_union du;
	du.d = x;
	return DUK_DBLUNION_IS_POSINF(&du);
}

DUK_INTERNAL duk_bool_t duk_double_is_neginf(duk_double_t x) {
	duk_double_union du;
	du.d = x;
	return DUK_DBLUNION_IS_NEGINF(&du);
}

DUK_INTERNAL duk_bool_t duk_double_is_nan(duk_double_t x) {
	duk_double_union du;
	du.d = x;
	/* Assumes we're dealing with a Duktape internal NaN which is
	 * NaN normalized if duk_tval requires it.
	 */
	DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
	return DUK_DBLUNION_IS_NAN(&du);
}

DUK_INTERNAL duk_bool_t duk_double_is_nan_or_zero(duk_double_t x) {
	duk_double_union du;
	du.d = x;
	/* Assumes we're dealing with a Duktape internal NaN which is
	 * NaN normalized if duk_tval requires it.
	 */
	DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
	return DUK_DBLUNION_IS_NAN(&du) || DUK_DBLUNION_IS_ANYZERO(&du);
}

DUK_INTERNAL duk_bool_t duk_double_is_nan_or_inf(duk_double_t x) {
	duk_double_union du;
	du.d = x;
	/* If exponent is 0x7FF the argument is either a NaN or an
	 * infinity.  We don't need to check any other fields.
	 */
#if defined(DUK_USE_64BIT_OPS)
#if defined(DUK_USE_DOUBLE_ME)
	return (du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x000000007ff00000)) == DUK_U64_CONSTANT(0x000000007ff00000);
#else
	return (du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x7ff0000000000000)) == DUK_U64_CONSTANT(0x7ff0000000000000);
#endif
#else
	return (du.ui[DUK_DBL_IDX_UI0] & 0x7ff00000UL) == 0x7ff00000UL;
#endif
}

DUK_INTERNAL duk_bool_t duk_double_is_nan_zero_inf(duk_double_t x) {
	duk_double_union du;
#if defined(DUK_USE_64BIT_OPS)
	duk_uint64_t t;
#else
	duk_uint32_t t;
#endif
	du.d = x;
#if defined(DUK_USE_64BIT_OPS)
#if defined(DUK_USE_DOUBLE_ME)
	t = du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x000000007ff00000);
	if (t == DUK_U64_CONSTANT(0x0000000000000000)) {
		t = du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x0000000080000000);
		return t == 0;
	}
	if (t == DUK_U64_CONSTANT(0x000000007ff00000)) {
		return 1;
	}
#else
	t = du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x7ff0000000000000);
	if (t == DUK_U64_CONSTANT(0x0000000000000000)) {
		t = du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x8000000000000000);
		return t == 0;
	}
	if (t == DUK_U64_CONSTANT(0x7ff0000000000000)) {
		return 1;
	}
#endif
#else
	t = du.ui[DUK_DBL_IDX_UI0] & 0x7ff00000UL;
	if (t == 0x00000000UL) {
		return DUK_DBLUNION_IS_ANYZERO(&du);
	}
	if (t == 0x7ff00000UL) {
		return 1;
	}
#endif
	return 0;
}

DUK_INTERNAL duk_small_uint_t duk_double_signbit(duk_double_t x) {
	duk_double_union du;
	du.d = x;
	return (duk_small_uint_t) DUK_DBLUNION_GET_SIGNBIT(&du);
}

DUK_INTERNAL duk_double_t duk_double_trunc_towards_zero(duk_double_t x) {
	/* XXX: optimize */
	duk_small_uint_t s = duk_double_signbit(x);
	x = DUK_FLOOR(DUK_FABS(x));  /* truncate towards zero */
	if (s) {
		x = -x;
	}
	return x;
}

DUK_INTERNAL duk_bool_t duk_double_same_sign(duk_double_t x, duk_double_t y) {
	duk_double_union du1;
	duk_double_union du2;
	du1.d = x;
	du2.d = y;

	return (((du1.ui[DUK_DBL_IDX_UI0] ^ du2.ui[DUK_DBL_IDX_UI0]) & 0x80000000UL) == 0);
}

DUK_INTERNAL duk_double_t duk_double_fmin(duk_double_t x, duk_double_t y) {
	/* Doesn't replicate fmin() behavior exactly: for fmin() if one
	 * argument is a NaN, the other argument should be returned.
	 * Duktape doesn't rely on this behavior so the replacement can
	 * be simplified.
	 */
	return (x < y ? x : y);
}

DUK_INTERNAL duk_double_t duk_double_fmax(duk_double_t x, duk_double_t y) {
	/* Doesn't replicate fmax() behavior exactly: for fmax() if one
	 * argument is a NaN, the other argument should be returned.
	 * Duktape doesn't rely on this behavior so the replacement can
	 * be simplified.
	 */
	return (x > y ? x : y);
}

DUK_INTERNAL duk_bool_t duk_double_is_finite(duk_double_t x) {
	return !duk_double_is_nan_or_inf(x);
}

DUK_INTERNAL duk_bool_t duk_double_is_integer(duk_double_t x) {
	if (duk_double_is_nan_or_inf(x)) {
		return 0;
	} else {
		return duk_double_equals(duk_js_tointeger_number(x), x);
	}
}

DUK_INTERNAL duk_bool_t duk_double_is_safe_integer(duk_double_t x) {
	/* >>> 2**53-1
	 * 9007199254740991
	 */
	return duk_double_is_integer(x) && DUK_FABS(x) <= 9007199254740991.0;
}

/* Check whether a duk_double_t is a whole number in the 32-bit range (reject
 * negative zero), and if so, return a duk_int32_t.
 * For compiler use: don't allow negative zero as it will cause trouble with
 * LDINT+LDINTX, positive zero is OK.
 */
DUK_INTERNAL duk_bool_t duk_is_whole_get_int32_nonegzero(duk_double_t x, duk_int32_t *ival) {
	duk_int32_t t;

	t = duk_double_to_int32_t(x);
	if (!duk_double_equals((duk_double_t) t, x)) {
		return 0;
	}
	if (t == 0) {
		duk_double_union du;
		du.d = x;
		if (DUK_DBLUNION_HAS_SIGNBIT(&du)) {
			return 0;
		}
	}
	*ival = t;
	return 1;
}

/* Check whether a duk_double_t is a whole number in the 32-bit range, and if
 * so, return a duk_int32_t.
 */
DUK_INTERNAL duk_bool_t duk_is_whole_get_int32(duk_double_t x, duk_int32_t *ival) {
	duk_int32_t t;

	t = duk_double_to_int32_t(x);
	if (!duk_double_equals((duk_double_t) t, x)) {
		return 0;
	}
	*ival = t;
	return 1;
}

/* Division: division by zero is undefined behavior (and may in fact trap)
 * so it needs special handling for portability.
 */

DUK_INTERNAL DUK_INLINE duk_double_t duk_double_div(duk_double_t x, duk_double_t y) {
#if !defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
	if (DUK_UNLIKELY(duk_double_equals(y, 0.0) != 0)) {
		/* In C99+ division by zero is undefined behavior so
		 * avoid it entirely.  Hopefully the compiler is
		 * smart enough to avoid emitting any actual code
		 * because almost all practical platforms behave as
		 * expected.
		 */
		if (x > 0.0) {
			if (DUK_SIGNBIT(y)) {
				return -DUK_DOUBLE_INFINITY;
			} else {
				return DUK_DOUBLE_INFINITY;
			}
		} else if (x < 0.0) {
			if (DUK_SIGNBIT(y)) {
				return DUK_DOUBLE_INFINITY;
			} else {
				return -DUK_DOUBLE_INFINITY;
			}
		} else {
			/* +/- 0, NaN */
			return DUK_DOUBLE_NAN;
		}
	}
#endif

	return x / y;
}

/* Double and float byteorder changes. */

DUK_INTERNAL DUK_INLINE void duk_dblunion_host_to_little(duk_double_union *u) {
#if defined(DUK_USE_DOUBLE_LE)
	/* HGFEDCBA -> HGFEDCBA */
	DUK_UNREF(u);
#elif defined(DUK_USE_DOUBLE_ME)
	duk_uint32_t a, b;

	/* DCBAHGFE -> HGFEDCBA */
	a = u->ui[0];
	b = u->ui[1];
	u->ui[0] = b;
	u->ui[1] = a;
#elif defined(DUK_USE_DOUBLE_BE)
	/* ABCDEFGH -> HGFEDCBA */
#if defined(DUK_USE_64BIT_OPS)
	u->ull[0] = DUK_BSWAP64(u->ull[0]);
#else
	duk_uint32_t a, b;

	a = u->ui[0];
	b = u->ui[1];
	u->ui[0] = DUK_BSWAP32(b);
	u->ui[1] = DUK_BSWAP32(a);
#endif
#else
#error internal error
#endif
}

DUK_INTERNAL DUK_INLINE void duk_dblunion_little_to_host(duk_double_union *u) {
	duk_dblunion_host_to_little(u);
}

DUK_INTERNAL DUK_INLINE void duk_dblunion_host_to_big(duk_double_union *u) {
#if defined(DUK_USE_DOUBLE_LE)
	/* HGFEDCBA -> ABCDEFGH */
#if defined(DUK_USE_64BIT_OPS)
	u->ull[0] = DUK_BSWAP64(u->ull[0]);
#else
	duk_uint32_t a, b;

	a = u->ui[0];
	b = u->ui[1];
	u->ui[0] = DUK_BSWAP32(b);
	u->ui[1] = DUK_BSWAP32(a);
#endif
#elif defined(DUK_USE_DOUBLE_ME)
	duk_uint32_t a, b;

	/* DCBAHGFE -> ABCDEFGH */
	a = u->ui[0];
	b = u->ui[1];
	u->ui[0] = DUK_BSWAP32(a);
	u->ui[1] = DUK_BSWAP32(b);
#elif defined(DUK_USE_DOUBLE_BE)
	/* ABCDEFGH -> ABCDEFGH */
	DUK_UNREF(u);
#else
#error internal error
#endif
}

DUK_INTERNAL DUK_INLINE void duk_dblunion_big_to_host(duk_double_union *u) {
	duk_dblunion_host_to_big(u);
}

DUK_INTERNAL DUK_INLINE void duk_fltunion_host_to_big(duk_float_union *u) {
#if defined(DUK_USE_DOUBLE_LE) || defined(DUK_USE_DOUBLE_ME)
	/* DCBA -> ABCD */
	u->ui[0] = DUK_BSWAP32(u->ui[0]);
#elif defined(DUK_USE_DOUBLE_BE)
	/* ABCD -> ABCD */
	DUK_UNREF(u);
#else
#error internal error
#endif
}

DUK_INTERNAL DUK_INLINE void duk_fltunion_big_to_host(duk_float_union *u) {
	duk_fltunion_host_to_big(u);
}

/* Comparison: ensures comparison operates on exactly correct types, avoiding
 * some floating point comparison pitfalls (e.g. atan2() assertions failed on
 * -m32 with direct comparison, even with explicit casts).
 */
#if defined(DUK_USE_GCC_PRAGMAS)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wfloat-equal"
#elif defined(DUK_USE_CLANG_PRAGMAS)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wfloat-equal"
#endif

DUK_INTERNAL DUK_ALWAYS_INLINE duk_bool_t duk_double_equals(duk_double_t x, duk_double_t y) {
	return x == y;
}

DUK_INTERNAL DUK_ALWAYS_INLINE duk_bool_t duk_float_equals(duk_float_t x, duk_float_t y) {
	return x == y;
}
#if defined(DUK_USE_GCC_PRAGMAS)
#pragma GCC diagnostic pop
#elif defined(DUK_USE_CLANG_PRAGMAS)
#pragma clang diagnostic pop
#endif
#line 1 "duk_util_hashbytes.c"
/*
 *  Hash function duk_util_hashbytes().
 *
 *  Currently, 32-bit MurmurHash2.
 *
 *  Don't rely on specific hash values; hash function may be endianness
 *  dependent, for instance.
 */

/* #include duk_internal.h -> already included */

#if defined(DUK_USE_STRHASH_DENSE)
/* 'magic' constants for Murmurhash2 */
#define DUK__MAGIC_M  ((duk_uint32_t) 0x5bd1e995UL)
#define DUK__MAGIC_R  24

DUK_INTERNAL duk_uint32_t duk_util_hashbytes(const duk_uint8_t *data, duk_size_t len, duk_uint32_t seed) {
	duk_uint32_t h = seed ^ ((duk_uint32_t) len);

	while (len >= 4) {
		/* Portability workaround is required for platforms without
		 * unaligned access.  The replacement code emulates little
		 * endian access even on big endian architectures, which is
		 * OK as long as it is consistent for a build.
		 */
#if defined(DUK_USE_HASHBYTES_UNALIGNED_U32_ACCESS)
		duk_uint32_t k = *((const duk_uint32_t *) (const void *) data);
#else
		duk_uint32_t k = ((duk_uint32_t) data[0]) |
		                 (((duk_uint32_t) data[1]) << 8) |
		                 (((duk_uint32_t) data[2]) << 16) |
		                 (((duk_uint32_t) data[3]) << 24);
#endif

		k *= DUK__MAGIC_M;
		k ^= k >> DUK__MAGIC_R;
		k *= DUK__MAGIC_M;
		h *= DUK__MAGIC_M;
		h ^= k;
		data += 4;
		len -= 4;
	}

	switch (len) {
	case 3: h ^= data[2] << 16;
	case 2: h ^= data[1] << 8;
	case 1: h ^= data[0];
	        h *= DUK__MAGIC_M;
        }

	h ^= h >> 13;
	h *= DUK__MAGIC_M;
	h ^= h >> 15;

	return h;
}
#endif  /* DUK_USE_STRHASH_DENSE */

/* automatic undefs */
#undef DUK__MAGIC_M
#undef DUK__MAGIC_R
#line 1 "duk_util_memory.c"
/*
 *  Memory utils.
 */

/* #include duk_internal.h -> already included */

#if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
DUK_INTERNAL DUK_INLINE duk_small_int_t duk_memcmp_unsafe(const void *s1, const void *s2, duk_size_t len) {
	DUK_ASSERT(s1 != NULL || len == 0U);
	DUK_ASSERT(s2 != NULL || len == 0U);
	return DUK_MEMCMP(s1, s2, (size_t) len);
}

DUK_INTERNAL DUK_INLINE duk_small_int_t duk_memcmp(const void *s1, const void *s2, duk_size_t len) {
	DUK_ASSERT(s1 != NULL);
	DUK_ASSERT(s2 != NULL);
	return DUK_MEMCMP(s1, s2, (size_t) len);
}
#else  /* DUK_USE_ALLOW_UNDEFINED_BEHAVIOR */
DUK_INTERNAL DUK_INLINE duk_small_int_t duk_memcmp_unsafe(const void *s1, const void *s2, duk_size_t len) {
	DUK_ASSERT(s1 != NULL || len == 0U);
	DUK_ASSERT(s2 != NULL || len == 0U);
	if (DUK_UNLIKELY(len == 0U)) {
		return 0;
	}
	DUK_ASSERT(s1 != NULL);
	DUK_ASSERT(s2 != NULL);
	return duk_memcmp(s1, s2, len);
}

DUK_INTERNAL DUK_INLINE duk_small_int_t duk_memcmp(const void *s1, const void *s2, duk_size_t len) {
	DUK_ASSERT(s1 != NULL);
	DUK_ASSERT(s2 != NULL);
	return DUK_MEMCMP(s1, s2, (size_t) len);
}
#endif  /* DUK_USE_ALLOW_UNDEFINED_BEHAVIOR */
#line 1 "duk_util_tinyrandom.c"
/*
 *  A tiny random number generator used for Math.random() and other internals.
 *
 *  Default algorithm is xoroshiro128+: http://xoroshiro.di.unimi.it/xoroshiro128plus.c
 *  with SplitMix64 seed preparation: http://xorshift.di.unimi.it/splitmix64.c.
 *
 *  Low memory targets and targets without 64-bit types use a slightly smaller
 *  (but slower) algorithm by Adi Shamir:
 *  http://www.woodmann.com/forum/archive/index.php/t-3100.html.
 *
 */

/* #include duk_internal.h -> already included */

#if !defined(DUK_USE_GET_RANDOM_DOUBLE)

#if defined(DUK_USE_PREFER_SIZE) || !defined(DUK_USE_64BIT_OPS)
#define DUK__RANDOM_SHAMIR3OP
#else
#define DUK__RANDOM_XOROSHIRO128PLUS
#endif

#if defined(DUK__RANDOM_SHAMIR3OP)
#define DUK__UPDATE_RND(rnd) do { \
		(rnd) += ((rnd) * (rnd)) | 0x05UL; \
		(rnd) = ((rnd) & 0xffffffffUL);       /* if duk_uint32_t is exactly 32 bits, this is a NOP */ \
	} while (0)

#define DUK__RND_BIT(rnd)  ((rnd) >> 31)  /* only use the highest bit */

DUK_INTERNAL void duk_util_tinyrandom_prepare_seed(duk_hthread *thr) {
	DUK_UNREF(thr);  /* Nothing now. */
}

DUK_INTERNAL duk_double_t duk_util_tinyrandom_get_double(duk_hthread *thr) {
	duk_double_t t;
	duk_small_int_t n;
	duk_uint32_t rnd;

	rnd = thr->heap->rnd_state;

	n = 53;  /* enough to cover the whole mantissa */
	t = 0.0;

	do {
		DUK__UPDATE_RND(rnd);
		t += DUK__RND_BIT(rnd);
		t /= 2.0;
	} while (--n);

	thr->heap->rnd_state = rnd;

	DUK_ASSERT(t >= (duk_double_t) 0.0);
	DUK_ASSERT(t < (duk_double_t) 1.0);

	return t;
}
#endif  /* DUK__RANDOM_SHAMIR3OP */

#if defined(DUK__RANDOM_XOROSHIRO128PLUS)
DUK_LOCAL DUK_ALWAYS_INLINE duk_uint64_t duk__rnd_splitmix64(duk_uint64_t *x) {
	duk_uint64_t z;
	z = (*x += DUK_U64_CONSTANT(0x9E3779B97F4A7C15));
	z = (z ^ (z >> 30U)) * DUK_U64_CONSTANT(0xBF58476D1CE4E5B9);
	z = (z ^ (z >> 27U)) * DUK_U64_CONSTANT(0x94D049BB133111EB);
	return z ^ (z >> 31U);
}

DUK_LOCAL DUK_ALWAYS_INLINE duk_uint64_t duk__rnd_rotl(const duk_uint64_t x, duk_small_uint_t k) {
	return (x << k) | (x >> (64U - k));
}

DUK_LOCAL DUK_ALWAYS_INLINE duk_uint64_t duk__xoroshiro128plus(duk_uint64_t *s) {
	duk_uint64_t s0;
	duk_uint64_t s1;
	duk_uint64_t res;

	s0 = s[0];
	s1 = s[1];
	res = s0 + s1;
	s1 ^= s0;
	s[0] = duk__rnd_rotl(s0, 55) ^ s1 ^ (s1 << 14U);
	s[1] = duk__rnd_rotl(s1, 36);

	return res;
}

DUK_INTERNAL void duk_util_tinyrandom_prepare_seed(duk_hthread *thr) {
	duk_small_uint_t i;
	duk_uint64_t x;

	/* Mix both halves of the initial seed with SplitMix64.  The intent
	 * is to ensure that very similar raw seeds (which is usually the case
	 * because current seed is Date.now()) result in different xoroshiro128+
	 * seeds.
	 */
	x = thr->heap->rnd_state[0];  /* Only [0] is used as input here. */
	for (i = 0; i < 64; i++) {
		thr->heap->rnd_state[i & 0x01] = duk__rnd_splitmix64(&x);  /* Keep last 2 values. */
	}
}

DUK_INTERNAL duk_double_t duk_util_tinyrandom_get_double(duk_hthread *thr) {
	duk_uint64_t v;
	duk_double_union du;

	/* For big and little endian the integer and IEEE double byte order
	 * is the same so a direct assignment works.  For mixed endian the
	 * 32-bit parts must be swapped.
	 */
	v = (DUK_U64_CONSTANT(0x3ff) << 52U) | (duk__xoroshiro128plus((duk_uint64_t *) thr->heap->rnd_state) >> 12U);
	du.ull[0] = v;
#if defined(DUK_USE_DOUBLE_ME)
	do {
		duk_uint32_t tmp;
		tmp = du.ui[0];
		du.ui[0] = du.ui[1];
		du.ui[1] = tmp;
	} while (0);
#endif
	return du.d - 1.0;
}
#endif  /* DUK__RANDOM_XOROSHIRO128PLUS */

#endif  /* !DUK_USE_GET_RANDOM_DOUBLE */

/* automatic undefs */
#undef DUK__RANDOM_SHAMIR3OP
#undef DUK__RANDOM_XOROSHIRO128PLUS
#undef DUK__RND_BIT
#undef DUK__UPDATE_RND